EnableWindow doesn't release the capture of a child window.
[wine.git] / windows / win.c
blob585fd0847586e9453ef86c68d1ec4781aed0696a
1 /*
2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
5 */
7 #include <stdlib.h>
8 #include <string.h>
9 #include "wine/winbase16.h"
10 #include "wine/winuser16.h"
11 #include "options.h"
12 #include "class.h"
13 #include "win.h"
14 #include "heap.h"
15 #include "user.h"
16 #include "dce.h"
17 #include "cursoricon.h"
18 #include "hook.h"
19 #include "menu.h"
20 #include "message.h"
21 #include "nonclient.h"
22 #include "queue.h"
23 #include "winpos.h"
24 #include "shm_main_blk.h"
25 #include "dde_proc.h"
26 #include "clipboard.h"
27 #include "winproc.h"
28 #include "task.h"
29 #include "thread.h"
30 #include "process.h"
31 #include "debugtools.h"
32 #include "winerror.h"
33 #include "mdi.h"
34 #include "local.h"
35 #include "desktop.h"
36 #include "syslevel.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 SYSLEVEL WIN_SysLevel;
56 /***********************************************************************
57 * WIN_Init
58 */
59 void WIN_Init( void )
61 /* Initialisation of the critical section for thread safeness */
62 _CreateSysLevel( &WIN_SysLevel, 2 );
65 /***********************************************************************
66 * WIN_LockWnds
68 * Locks access to all WND structures for thread safeness
70 void WIN_LockWnds( void )
72 _EnterSysLevel( &WIN_SysLevel );
75 /***********************************************************************
76 * WIN_UnlockWnds
78 * Unlocks access to all WND structures
80 void WIN_UnlockWnds( void )
82 _LeaveSysLevel( &WIN_SysLevel );
85 /***********************************************************************
86 * WIN_SuspendWndsLock
88 * Suspend the lock on WND structures.
89 * Returns the number of locks suspended
91 int WIN_SuspendWndsLock( void )
93 int isuspendedLocks = _ConfirmSysLevel( &WIN_SysLevel );
94 int count = isuspendedLocks;
96 while ( count-- > 0 )
97 _LeaveSysLevel( &WIN_SysLevel );
99 return isuspendedLocks;
102 /***********************************************************************
103 * WIN_RestoreWndsLock
105 * Restore the suspended locks on WND structures
107 void WIN_RestoreWndsLock( int ipreviousLocks )
109 while ( ipreviousLocks-- > 0 )
110 _EnterSysLevel( &WIN_SysLevel );
113 /***********************************************************************
114 * WIN_FindWndPtr
116 * Return a pointer to the WND structure corresponding to a HWND.
118 WND * WIN_FindWndPtr( HWND hwnd )
120 WND * ptr;
122 if (!hwnd || HIWORD(hwnd)) goto error2;
123 ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
124 /* Lock all WND structures for thread safeness*/
125 WIN_LockWnds();
126 /*and increment destruction monitoring*/
127 ptr->irefCount++;
129 if (ptr->dwMagic != WND_MAGIC) goto error;
130 if (ptr->hwndSelf != hwnd)
132 ERR_(win)("Can't happen: hwnd %04x self pointer is %04x\n",hwnd, ptr->hwndSelf );
133 goto error;
135 /* returns a locked pointer */
136 return ptr;
137 error:
138 /* Unlock all WND structures for thread safeness*/
139 WIN_UnlockWnds();
140 /* and decrement destruction monitoring value */
141 ptr->irefCount--;
143 error2:
144 if ( hwnd!=0 )
145 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
146 return NULL;
149 /***********************************************************************
150 * WIN_LockWndPtr
152 * Use in case the wnd ptr is not initialized with WIN_FindWndPtr
153 * but by initWndPtr;
154 * Returns the locked initialisation pointer
156 WND *WIN_LockWndPtr(WND *initWndPtr)
158 if(!initWndPtr) return 0;
160 /* Lock all WND structures for thread safeness*/
161 WIN_LockWnds();
162 /*and increment destruction monitoring*/
163 initWndPtr->irefCount++;
165 return initWndPtr;
169 /***********************************************************************
170 * WIN_ReleaseWndPtr
172 * Release the pointer to the WND structure.
174 void WIN_ReleaseWndPtr(WND *wndPtr)
176 if(!wndPtr) return;
178 /*Decrement destruction monitoring value*/
179 wndPtr->irefCount--;
180 /* Check if it's time to release the memory*/
181 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
183 /* Release memory */
184 USER_HEAP_FREE( wndPtr->hwndSelf);
185 wndPtr->hwndSelf = 0;
187 else if(wndPtr->irefCount < 0)
189 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
190 ERR_(win)("forgot a Lock on %p somewhere\n",wndPtr);
192 /*unlock all WND structures for thread safeness*/
193 WIN_UnlockWnds();
196 /***********************************************************************
197 * WIN_UpdateWndPtr
199 * Updates the value of oldPtr to newPtr.
201 void WIN_UpdateWndPtr(WND **oldPtr, WND *newPtr)
203 WND *tmpWnd = NULL;
205 tmpWnd = WIN_LockWndPtr(newPtr);
206 WIN_ReleaseWndPtr(*oldPtr);
207 *oldPtr = tmpWnd;
211 /***********************************************************************
212 * WIN_DumpWindow
214 * Dump the content of a window structure to stderr.
216 void WIN_DumpWindow( HWND hwnd )
218 WND *ptr;
219 char className[80];
220 int i;
222 if (!(ptr = WIN_FindWndPtr( hwnd )))
224 WARN_(win)("%04x is not a window handle\n", hwnd );
225 return;
228 if (!GetClassNameA( hwnd, className, sizeof(className ) ))
229 strcpy( className, "#NULL#" );
231 TRACE_(win)("Window %04x (%p):\n", hwnd, ptr );
232 DPRINTF( "next=%p child=%p parent=%p owner=%p class=%p '%s'\n"
233 "inst=%04x taskQ=%04x updRgn=%04x active=%04x dce=%p idmenu=%08x\n"
234 "style=%08lx exstyle=%08lx wndproc=%08x text='%s'\n"
235 "client=%d,%d-%d,%d window=%d,%d-%d,%d"
236 "sysmenu=%04x flags=%04x props=%p vscroll=%p hscroll=%p\n",
237 ptr->next, ptr->child, ptr->parent, ptr->owner,
238 ptr->class, className, ptr->hInstance, ptr->hmemTaskQ,
239 ptr->hrgnUpdate, ptr->hwndLastActive, ptr->dce, ptr->wIDmenu,
240 ptr->dwStyle, ptr->dwExStyle, (UINT)ptr->winproc,
241 ptr->text ? ptr->text : "",
242 ptr->rectClient.left, ptr->rectClient.top, ptr->rectClient.right,
243 ptr->rectClient.bottom, ptr->rectWindow.left, ptr->rectWindow.top,
244 ptr->rectWindow.right, ptr->rectWindow.bottom, ptr->hSysMenu,
245 ptr->flags, ptr->pProp, ptr->pVScroll, ptr->pHScroll );
247 if (ptr->class->cbWndExtra)
249 DPRINTF( "extra bytes:" );
250 for (i = 0; i < ptr->class->cbWndExtra; i++)
251 DPRINTF( " %02x", *((BYTE*)ptr->wExtra+i) );
252 DPRINTF( "\n" );
254 DPRINTF( "\n" );
255 WIN_ReleaseWndPtr(ptr);
259 /***********************************************************************
260 * WIN_WalkWindows
262 * Walk the windows tree and print each window on stderr.
264 void WIN_WalkWindows( HWND hwnd, int indent )
266 WND *ptr;
267 char className[80];
269 ptr = hwnd ? WIN_FindWndPtr( hwnd ) : WIN_GetDesktop();
271 if (!ptr)
273 WARN_(win)("Invalid window handle %04x\n", hwnd );
274 return;
277 if (!indent) /* first time around */
278 DPRINTF( "%-16.16s %-8.8s %-6.6s %-17.17s %-8.8s %s\n",
279 "hwnd", " wndPtr", "queue", "Class Name", " Style", " WndProc"
280 " Text");
282 while (ptr)
284 DPRINTF( "%*s%04x%*s", indent, "", ptr->hwndSelf, 13-indent,"");
286 GlobalGetAtomName16(ptr->class->atomName,className,sizeof(className));
288 DPRINTF( "%08lx %-6.4x %-17.17s %08x %08x %.14s\n",
289 (DWORD)ptr, ptr->hmemTaskQ, className,
290 (UINT)ptr->dwStyle, (UINT)ptr->winproc,
291 ptr->text?ptr->text:"<null>");
293 if (ptr->child) WIN_WalkWindows( ptr->child->hwndSelf, indent+1 );
294 WIN_UpdateWndPtr(&ptr,ptr->next);
300 /***********************************************************************
301 * WIN_UnlinkWindow
303 * Remove a window from the siblings linked list.
305 BOOL WIN_UnlinkWindow( HWND hwnd )
307 WND *wndPtr, **ppWnd;
308 BOOL ret = FALSE;
310 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
311 else if(!wndPtr->parent)
313 WIN_ReleaseWndPtr(wndPtr);
314 return FALSE;
317 ppWnd = &wndPtr->parent->child;
318 while (*ppWnd && *ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
319 if (*ppWnd)
321 *ppWnd = wndPtr->next;
322 ret = TRUE;
324 WIN_ReleaseWndPtr(wndPtr);
325 return ret;
329 /***********************************************************************
330 * WIN_LinkWindow
332 * Insert a window into the siblings linked list.
333 * The window is inserted after the specified window, which can also
334 * be specified as HWND_TOP or HWND_BOTTOM.
336 BOOL WIN_LinkWindow( HWND hwnd, HWND hwndInsertAfter )
338 WND *wndPtr, **ppWnd;
340 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
341 else if(!wndPtr->parent)
343 WIN_ReleaseWndPtr(wndPtr);
344 return FALSE;
346 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
348 ppWnd = &wndPtr->parent->child; /* Point to first sibling hwnd */
349 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
350 while (*ppWnd) ppWnd = &(*ppWnd)->next;
352 else /* Normal case */
354 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
355 if (!afterPtr)
357 WIN_ReleaseWndPtr(wndPtr);
358 return FALSE;
360 ppWnd = &afterPtr->next;
361 WIN_ReleaseWndPtr(afterPtr);
363 wndPtr->next = *ppWnd;
364 *ppWnd = wndPtr;
365 WIN_ReleaseWndPtr(wndPtr);
366 return TRUE;
370 /***********************************************************************
371 * WIN_FindWinToRepaint
373 * Find a window that needs repaint.
375 HWND WIN_FindWinToRepaint( HWND hwnd, HQUEUE16 hQueue )
377 HWND hwndRet;
378 WND *pWnd;
380 /* Note: the desktop window never gets WM_PAINT messages
381 * The real reason why is because Windows DesktopWndProc
382 * does ValidateRgn inside WM_ERASEBKGND handler.
385 pWnd = hwnd ? WIN_FindWndPtr(hwnd) : WIN_LockWndPtr(pWndDesktop->child);
387 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
389 if (!(pWnd->dwStyle & WS_VISIBLE))
391 TRACE_(win)("skipping window %04x\n",
392 pWnd->hwndSelf );
394 else if ((pWnd->hmemTaskQ == hQueue) &&
395 (pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT)))
396 break;
398 else if (pWnd->child )
399 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf, hQueue )) )
401 WIN_ReleaseWndPtr(pWnd);
402 return hwndRet;
407 if(!pWnd)
409 return 0;
412 hwndRet = pWnd->hwndSelf;
414 /* look among siblings if we got a transparent window */
415 while (pWnd && ((pWnd->dwExStyle & WS_EX_TRANSPARENT) ||
416 !(pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))))
418 WIN_UpdateWndPtr(&pWnd,pWnd->next);
420 if (pWnd)
422 hwndRet = pWnd->hwndSelf;
423 WIN_ReleaseWndPtr(pWnd);
425 TRACE_(win)("found %04x\n",hwndRet);
426 return hwndRet;
430 /***********************************************************************
431 * WIN_DestroyWindow
433 * Destroy storage associated to a window. "Internals" p.358
434 * returns a locked wndPtr->next
436 static WND* WIN_DestroyWindow( WND* wndPtr )
438 HWND hwnd = wndPtr->hwndSelf;
439 WND *pWnd;
441 TRACE_(win)("%04x\n", wndPtr->hwndSelf );
443 #ifdef CONFIG_IPC
444 if (main_block)
445 DDE_DestroyWindow(wndPtr->hwndSelf);
446 #endif /* CONFIG_IPC */
448 /* free child windows */
449 WIN_LockWndPtr(wndPtr->child);
450 while ((pWnd = wndPtr->child))
452 wndPtr->child = WIN_DestroyWindow( pWnd );
453 WIN_ReleaseWndPtr(pWnd);
457 * Clear the update region to make sure no WM_PAINT messages will be
458 * generated for this window while processing the WM_NCDESTROY.
460 if ((wndPtr->hrgnUpdate) || (wndPtr->flags & WIN_INTERNAL_PAINT))
462 if (wndPtr->hrgnUpdate > 1)
463 DeleteObject( wndPtr->hrgnUpdate );
465 QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
467 wndPtr->hrgnUpdate = 0;
471 * Send the WM_NCDESTROY to the window being destroyed.
473 SendMessageA( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
475 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
477 WINPOS_CheckInternalPos( wndPtr );
478 if( hwnd == GetCapture()) ReleaseCapture();
480 /* free resources associated with the window */
482 TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
483 PROPERTY_RemoveWindowProps( wndPtr );
485 wndPtr->dwMagic = 0; /* Mark it as invalid */
487 /* toss stale messages from the queue */
489 if( wndPtr->hmemTaskQ )
491 BOOL bPostQuit = FALSE;
492 WPARAM wQuitParam = 0;
493 MESSAGEQUEUE* msgQ = (MESSAGEQUEUE*) QUEUE_Lock(wndPtr->hmemTaskQ);
494 QMSG *qmsg;
496 while( (qmsg = QUEUE_FindMsg(msgQ, hwnd, 0, 0)) != 0 )
498 if( qmsg->msg.message == WM_QUIT )
500 bPostQuit = TRUE;
501 wQuitParam = qmsg->msg.wParam;
503 QUEUE_RemoveMsg(msgQ, qmsg);
506 QUEUE_Unlock(msgQ);
508 /* repost WM_QUIT to make sure this app exits its message loop */
509 if( bPostQuit ) PostQuitMessage(wQuitParam);
510 wndPtr->hmemTaskQ = 0;
513 if (!(wndPtr->dwStyle & WS_CHILD))
514 if (wndPtr->wIDmenu) DestroyMenu( (HMENU)wndPtr->wIDmenu );
515 if (wndPtr->hSysMenu) DestroyMenu( wndPtr->hSysMenu );
516 wndPtr->pDriver->pDestroyWindow( wndPtr );
517 DCE_FreeWindowDCE( wndPtr ); /* Always do this to catch orphaned DCs */
518 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
519 wndPtr->class->cWindows--;
520 wndPtr->class = NULL;
522 WIN_UpdateWndPtr(&pWnd,wndPtr->next);
524 wndPtr->pDriver->pFinalize(wndPtr);
526 return pWnd;
529 /***********************************************************************
530 * WIN_ResetQueueWindows
532 * Reset the queue of all the children of a given window.
533 * Return TRUE if something was done.
535 BOOL WIN_ResetQueueWindows( WND* wnd, HQUEUE16 hQueue, HQUEUE16 hNew )
537 BOOL ret = FALSE;
539 if (hNew) /* Set a new queue */
541 for (wnd = WIN_LockWndPtr(wnd->child); (wnd);WIN_UpdateWndPtr(&wnd,wnd->next))
543 if (wnd->hmemTaskQ == hQueue)
545 wnd->hmemTaskQ = hNew;
546 ret = TRUE;
548 if (wnd->child)
550 ret |= WIN_ResetQueueWindows( wnd, hQueue, hNew );
554 else /* Queue is being destroyed */
556 while (wnd->child)
558 WND *tmp = WIN_LockWndPtr(wnd->child);
559 WND *tmp2;
560 ret = FALSE;
561 while (tmp)
563 if (tmp->hmemTaskQ == hQueue)
565 DestroyWindow( tmp->hwndSelf );
566 ret = TRUE;
567 break;
569 tmp2 = WIN_LockWndPtr(tmp->child);
570 if (tmp2 && WIN_ResetQueueWindows(tmp2,hQueue,0))
571 ret = TRUE;
572 else
574 WIN_UpdateWndPtr(&tmp,tmp->next);
576 WIN_ReleaseWndPtr(tmp2);
578 WIN_ReleaseWndPtr(tmp);
579 if (!ret) break;
582 return ret;
585 /***********************************************************************
586 * WIN_CreateDesktopWindow
588 * Create the desktop window.
590 BOOL WIN_CreateDesktopWindow(void)
592 CLASS *class;
593 HWND hwndDesktop;
594 DESKTOP *pDesktop;
596 TRACE_(win)("Creating desktop window\n");
599 if (!ICONTITLE_Init() ||
600 !WINPOS_CreateInternalPosAtom() ||
601 !(class = CLASS_FindClassByAtom( DESKTOP_CLASS_ATOM, 0 )))
602 return FALSE;
604 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND)+class->cbWndExtra );
605 if (!hwndDesktop) return FALSE;
606 pWndDesktop = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
608 pDesktop = (DESKTOP *) pWndDesktop->wExtra;
609 pDesktop->pDriver = DESKTOP_Driver;
610 pWndDesktop->pDriver = WND_Driver;
612 pDesktop->pDriver->pInitialize(pDesktop);
613 pWndDesktop->pDriver->pInitialize(pWndDesktop);
615 pWndDesktop->next = NULL;
616 pWndDesktop->child = NULL;
617 pWndDesktop->parent = NULL;
618 pWndDesktop->owner = NULL;
619 pWndDesktop->class = class;
620 pWndDesktop->dwMagic = WND_MAGIC;
621 pWndDesktop->hwndSelf = hwndDesktop;
622 pWndDesktop->hInstance = 0;
623 pWndDesktop->rectWindow.left = 0;
624 pWndDesktop->rectWindow.top = 0;
625 pWndDesktop->rectWindow.right = GetSystemMetrics(SM_CXSCREEN);
626 pWndDesktop->rectWindow.bottom = GetSystemMetrics(SM_CYSCREEN);
627 pWndDesktop->rectClient = pWndDesktop->rectWindow;
628 pWndDesktop->text = NULL;
629 pWndDesktop->hmemTaskQ = GetFastQueue16();
630 pWndDesktop->hrgnUpdate = 0;
631 pWndDesktop->hwndLastActive = hwndDesktop;
632 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
633 WS_CLIPSIBLINGS;
634 pWndDesktop->dwExStyle = 0;
635 pWndDesktop->dce = NULL;
636 pWndDesktop->pVScroll = NULL;
637 pWndDesktop->pHScroll = NULL;
638 pWndDesktop->pProp = NULL;
639 pWndDesktop->wIDmenu = 0;
640 pWndDesktop->helpContext = 0;
641 pWndDesktop->flags = Options.desktopGeometry ? WIN_NATIVE : 0;
642 pWndDesktop->hSysMenu = 0;
643 pWndDesktop->userdata = 0;
644 pWndDesktop->winproc = (WNDPROC16)class->winproc;
645 pWndDesktop->irefCount = 0;
647 /* FIXME: How do we know if it should be Unicode or not */
648 if(!pWndDesktop->pDriver->pCreateDesktopWindow(pWndDesktop, class, FALSE))
649 return FALSE;
651 SendMessageA( hwndDesktop, WM_NCCREATE, 0, 0 );
652 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
653 return TRUE;
657 /***********************************************************************
658 * WIN_CreateWindowEx
660 * Implementation of CreateWindowEx().
662 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
663 BOOL win32, BOOL unicode )
665 INT sw = SW_SHOW;
666 CLASS *classPtr;
667 WND *wndPtr;
668 HWND retvalue;
669 HWND16 hwnd, hwndLinkAfter;
670 POINT maxSize, maxPos, minTrack, maxTrack;
671 LRESULT (CALLBACK *localSend32)(HWND, UINT, WPARAM, LPARAM);
672 char buffer[256];
674 TRACE_(win)("%s %s %08lx %08lx %d,%d %dx%d %04x %04x %08x %p\n",
675 unicode ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
676 unicode ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
677 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
678 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
680 /* Find the parent window */
682 if (cs->hwndParent)
684 /* Make sure parent is valid */
685 if (!IsWindow( cs->hwndParent ))
687 WARN_(win)("Bad parent %04x\n", cs->hwndParent );
688 return 0;
690 } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
691 WARN_(win)("No parent for child window\n" );
692 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
695 /* Find the window class */
696 if (!(classPtr = CLASS_FindClassByAtom( classAtom, win32?cs->hInstance:GetExePtr(cs->hInstance) )))
698 GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) );
699 WARN_(win)("Bad class '%s'\n", buffer );
700 return 0;
703 /* Fix the lpszClass field: from existing programs, it seems ok to call a CreateWindowXXX
704 * with an atom as the class name, put some programs expect to have a *REAL* string in
705 * lpszClass when the CREATESTRUCT is sent with WM_CREATE
707 if ( !HIWORD(cs->lpszClass) ) {
708 if (unicode) {
709 GlobalGetAtomNameW( classAtom, (LPWSTR)buffer, sizeof(buffer) );
710 } else {
711 GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) );
713 cs->lpszClass = buffer;
716 /* Fix the coordinates */
718 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
720 PDB *pdb = PROCESS_Current();
722 /* Never believe Microsoft's documentation... CreateWindowEx doc says
723 * that if an overlapped window is created with WS_VISIBLE style bit
724 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
725 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
726 * reveals that
728 * 1) not only if checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
729 * 2) it does not ignore the y parameter as the docs claim; instead, it
730 * uses it as second parameter to ShowWindow() unless y is either
731 * CW_USEDEFAULT or CW_USEDEFAULT16.
733 * The fact that we didn't do 2) caused bogus windows pop up when wine
734 * was running apps that were using this obscure feature. Example -
735 * calc.exe that comes with Win98 (only Win98, it's different from
736 * the one that comes with Win95 and NT)
738 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) sw = cs->y;
740 /* We have saved cs->y, now we can trash it */
741 if ( !(cs->style & (WS_CHILD | WS_POPUP))
742 && (pdb->env_db->startup_info->dwFlags & STARTF_USEPOSITION) )
744 cs->x = pdb->env_db->startup_info->dwX;
745 cs->y = pdb->env_db->startup_info->dwY;
747 else
749 cs->x = 0;
750 cs->y = 0;
753 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
755 PDB *pdb = PROCESS_Current();
756 if ( !(cs->style & (WS_CHILD | WS_POPUP))
757 && (pdb->env_db->startup_info->dwFlags & STARTF_USESIZE) )
759 cs->cx = pdb->env_db->startup_info->dwXSize;
760 cs->cy = pdb->env_db->startup_info->dwYSize;
762 else
764 cs->cx = 600; /* FIXME */
765 cs->cy = 400;
769 /* Create the window structure */
771 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + classPtr->cbWndExtra
772 - sizeof(wndPtr->wExtra) )))
774 TRACE_(win)("out of memory\n" );
775 return 0;
778 /* Fill the window structure */
780 wndPtr = WIN_LockWndPtr((WND *) USER_HEAP_LIN_ADDR( hwnd ));
781 wndPtr->next = NULL;
782 wndPtr->child = NULL;
784 if ((cs->style & WS_CHILD) && cs->hwndParent)
786 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
787 wndPtr->owner = NULL;
788 WIN_ReleaseWndPtr(wndPtr->parent);
790 else
792 wndPtr->parent = pWndDesktop;
793 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
794 wndPtr->owner = NULL;
795 else
797 WND *tmpWnd = WIN_FindWndPtr(cs->hwndParent);
798 wndPtr->owner = WIN_GetTopParentPtr(tmpWnd);
799 WIN_ReleaseWndPtr(wndPtr->owner);
800 WIN_ReleaseWndPtr(tmpWnd);
805 wndPtr->pDriver = wndPtr->parent->pDriver;
806 wndPtr->pDriver->pInitialize(wndPtr);
808 wndPtr->class = classPtr;
809 wndPtr->winproc = classPtr->winproc;
810 wndPtr->dwMagic = WND_MAGIC;
811 wndPtr->hwndSelf = hwnd;
812 wndPtr->hInstance = cs->hInstance;
813 wndPtr->text = NULL;
814 wndPtr->hmemTaskQ = GetFastQueue16();
815 wndPtr->hrgnUpdate = 0;
816 wndPtr->hwndLastActive = hwnd;
817 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
818 wndPtr->dwExStyle = cs->dwExStyle;
819 wndPtr->wIDmenu = 0;
820 wndPtr->helpContext = 0;
821 wndPtr->flags = win32 ? WIN_ISWIN32 : 0;
822 wndPtr->pVScroll = NULL;
823 wndPtr->pHScroll = NULL;
824 wndPtr->pProp = NULL;
825 wndPtr->userdata = 0;
826 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
827 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
828 wndPtr->irefCount = 1;
830 if (classPtr->cbWndExtra) memset( wndPtr->wExtra, 0, classPtr->cbWndExtra);
832 /* Call the WH_CBT hook */
834 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
835 ? HWND_BOTTOM : HWND_TOP;
837 if (HOOK_IsHooked( WH_CBT ))
839 CBT_CREATEWNDA cbtc;
840 LRESULT ret;
842 cbtc.lpcs = cs;
843 cbtc.hwndInsertAfter = hwndLinkAfter;
844 ret = unicode ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc)
845 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc);
846 if (ret)
848 TRACE_(win)("CBT-hook returned 0\n");
849 wndPtr->pDriver->pFinalize(wndPtr);
850 USER_HEAP_FREE( hwnd );
851 retvalue = 0;
852 goto end;
856 /* Increment class window counter */
858 classPtr->cWindows++;
860 /* Correct the window style */
862 if (!(cs->style & WS_CHILD))
864 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
865 if (!(cs->style & WS_POPUP))
867 wndPtr->dwStyle |= WS_CAPTION;
868 wndPtr->flags |= WIN_NEED_SIZE;
871 if (cs->dwExStyle & WS_EX_DLGMODALFRAME) wndPtr->dwStyle &= ~WS_THICKFRAME;
873 /* Get class or window DC if needed */
875 if (classPtr->style & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
876 else if (classPtr->style & CS_CLASSDC) wndPtr->dce = classPtr->dce;
877 else wndPtr->dce = NULL;
879 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
881 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
883 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack);
884 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
885 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
886 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
887 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
890 if(cs->style & WS_CHILD)
892 if(cs->cx < 0) cs->cx = 0;
893 if(cs->cy < 0) cs->cy = 0;
895 else
897 if (cs->cx <= 0) cs->cx = 1;
898 if (cs->cy <= 0) cs->cy = 1;
901 wndPtr->rectWindow.left = cs->x;
902 wndPtr->rectWindow.top = cs->y;
903 wndPtr->rectWindow.right = cs->x + cs->cx;
904 wndPtr->rectWindow.bottom = cs->y + cs->cy;
905 wndPtr->rectClient = wndPtr->rectWindow;
907 if(!wndPtr->pDriver->pCreateWindow(wndPtr, classPtr, cs, unicode))
909 retvalue = FALSE;
910 goto end;
913 /* Set the window menu */
915 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
917 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
918 else
920 #if 0 /* FIXME: should check if classPtr->menuNameW can be used as is */
921 if (classPtr->menuNameA)
922 cs->hMenu = HIWORD(classPtr->menuNameA) ?
923 LoadMenu(cs->hInstance,SEGPTR_GET(classPtr->menuNameA)):
924 LoadMenu(cs->hInstance,(SEGPTR)classPtr->menuNameA);
925 #else
926 SEGPTR menuName = (SEGPTR)GetClassLong16( hwnd, GCL_MENUNAME );
927 if (menuName)
929 if (HIWORD(cs->hInstance))
930 cs->hMenu = LoadMenuA(cs->hInstance,PTR_SEG_TO_LIN(menuName));
931 else
932 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
934 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
936 #endif
939 else wndPtr->wIDmenu = (UINT)cs->hMenu;
941 /* Send the WM_CREATE message
942 * Perhaps we shouldn't allow width/height changes as well.
943 * See p327 in "Internals".
946 maxPos.x = wndPtr->rectWindow.left; maxPos.y = wndPtr->rectWindow.top;
948 localSend32 = unicode ? SendMessageW : SendMessageA;
949 if( (*localSend32)( hwnd, WM_NCCREATE, 0, (LPARAM)cs) )
951 /* Insert the window in the linked list */
953 WIN_LinkWindow( hwnd, hwndLinkAfter );
955 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
956 NULL, NULL, 0, &wndPtr->rectClient );
957 OffsetRect(&wndPtr->rectWindow, maxPos.x - wndPtr->rectWindow.left,
958 maxPos.y - wndPtr->rectWindow.top);
959 if( ((*localSend32)( hwnd, WM_CREATE, 0, (LPARAM)cs )) != -1 )
961 /* Send the size messages */
963 if (!(wndPtr->flags & WIN_NEED_SIZE))
965 /* send it anyway */
966 if (((wndPtr->rectClient.right-wndPtr->rectClient.left) <0)
967 ||((wndPtr->rectClient.bottom-wndPtr->rectClient.top)<0))
968 WARN_(win)("sending bogus WM_SIZE message 0x%08lx\n",
969 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
970 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
971 SendMessageA( hwnd, WM_SIZE, SIZE_RESTORED,
972 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
973 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
974 SendMessageA( hwnd, WM_MOVE, 0,
975 MAKELONG( wndPtr->rectClient.left,
976 wndPtr->rectClient.top ) );
979 /* Show the window, maximizing or minimizing if needed */
981 if (wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE))
983 RECT16 newPos;
984 UINT16 swFlag = (wndPtr->dwStyle & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
985 wndPtr->dwStyle &= ~(WS_MAXIMIZE | WS_MINIMIZE);
986 WINPOS_MinMaximize( wndPtr, swFlag, &newPos );
987 swFlag = ((wndPtr->dwStyle & WS_CHILD) || GetActiveWindow())
988 ? SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED
989 : SWP_NOZORDER | SWP_FRAMECHANGED;
990 SetWindowPos( hwnd, 0, newPos.left, newPos.top,
991 newPos.right, newPos.bottom, swFlag );
994 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
996 /* Notify the parent window only */
998 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
999 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
1000 if( !IsWindow(hwnd) )
1002 retvalue = 0;
1003 goto end;
1007 if (cs->style & WS_VISIBLE) ShowWindow( hwnd, sw );
1009 /* Call WH_SHELL hook */
1011 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1012 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
1014 TRACE_(win)("created window %04x\n", hwnd);
1015 retvalue = hwnd;
1016 goto end;
1018 WIN_UnlinkWindow( hwnd );
1021 /* Abort window creation */
1023 WARN_(win)("aborted by WM_xxCREATE!\n");
1024 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1025 retvalue = 0;
1026 end:
1027 WIN_ReleaseWndPtr(wndPtr);
1029 return retvalue;
1033 /***********************************************************************
1034 * CreateWindow16 (USER.41)
1036 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1037 DWORD style, INT16 x, INT16 y, INT16 width,
1038 INT16 height, HWND16 parent, HMENU16 menu,
1039 HINSTANCE16 instance, LPVOID data )
1041 return CreateWindowEx16( 0, className, windowName, style,
1042 x, y, width, height, parent, menu, instance, data );
1046 /***********************************************************************
1047 * CreateWindowEx16 (USER.452)
1049 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1050 LPCSTR windowName, DWORD style, INT16 x,
1051 INT16 y, INT16 width, INT16 height,
1052 HWND16 parent, HMENU16 menu,
1053 HINSTANCE16 instance, LPVOID data )
1055 ATOM classAtom;
1056 CREATESTRUCTA cs;
1058 /* Find the class atom */
1060 if (!(classAtom = GlobalFindAtomA( className )))
1062 fprintf( stderr, "CreateWindowEx16: bad class name " );
1063 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
1064 else fprintf( stderr, "'%s'\n", className );
1065 return 0;
1068 /* Fix the coordinates */
1070 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1071 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1072 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1073 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1075 /* Create the window */
1077 cs.lpCreateParams = data;
1078 cs.hInstance = (HINSTANCE)instance;
1079 cs.hMenu = (HMENU)menu;
1080 cs.hwndParent = (HWND)parent;
1081 cs.style = style;
1082 cs.lpszName = windowName;
1083 cs.lpszClass = className;
1084 cs.dwExStyle = exStyle;
1085 return WIN_CreateWindowEx( &cs, classAtom, FALSE, FALSE );
1089 /***********************************************************************
1090 * CreateWindowEx32A (USER32.83)
1092 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1093 LPCSTR windowName, DWORD style, INT x,
1094 INT y, INT width, INT height,
1095 HWND parent, HMENU menu,
1096 HINSTANCE instance, LPVOID data )
1098 ATOM classAtom;
1099 CREATESTRUCTA cs;
1101 if(exStyle & WS_EX_MDICHILD)
1102 return MDI_CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1103 /* Find the class atom */
1105 if (!(classAtom = GlobalFindAtomA( className )))
1107 fprintf( stderr, "CreateWindowEx32A: bad class name " );
1108 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
1109 else fprintf( stderr, "'%s'\n", className );
1110 return 0;
1113 /* Create the window */
1115 cs.lpCreateParams = data;
1116 cs.hInstance = instance;
1117 cs.hMenu = menu;
1118 cs.hwndParent = parent;
1119 cs.x = x;
1120 cs.y = y;
1121 cs.cx = width;
1122 cs.cy = height;
1123 cs.style = style;
1124 cs.lpszName = windowName;
1125 cs.lpszClass = className;
1126 cs.dwExStyle = exStyle;
1127 return WIN_CreateWindowEx( &cs, classAtom, TRUE, FALSE );
1131 /***********************************************************************
1132 * CreateWindowEx32W (USER32.84)
1134 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1135 LPCWSTR windowName, DWORD style, INT x,
1136 INT y, INT width, INT height,
1137 HWND parent, HMENU menu,
1138 HINSTANCE instance, LPVOID data )
1140 ATOM classAtom;
1141 CREATESTRUCTW cs;
1143 if(exStyle & WS_EX_MDICHILD)
1144 return MDI_CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1146 /* Find the class atom */
1148 if (!(classAtom = GlobalFindAtomW( className )))
1150 if (HIWORD(className))
1152 LPSTR cn = HEAP_strdupWtoA( GetProcessHeap(), 0, className );
1153 WARN_(win)("Bad class name '%s'\n",cn);
1154 HeapFree( GetProcessHeap(), 0, cn );
1156 else
1157 WARN_(win)("Bad class name %p\n", className );
1158 return 0;
1161 /* Create the window */
1163 cs.lpCreateParams = data;
1164 cs.hInstance = instance;
1165 cs.hMenu = menu;
1166 cs.hwndParent = parent;
1167 cs.x = x;
1168 cs.y = y;
1169 cs.cx = width;
1170 cs.cy = height;
1171 cs.style = style;
1172 cs.lpszName = windowName;
1173 cs.lpszClass = className;
1174 cs.dwExStyle = exStyle;
1175 /* Note: we rely on the fact that CREATESTRUCT32A and */
1176 /* CREATESTRUCT32W have the same layout. */
1177 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, TRUE, TRUE );
1181 /***********************************************************************
1182 * WIN_CheckFocus
1184 static void WIN_CheckFocus( WND* pWnd )
1186 if( GetFocus16() == pWnd->hwndSelf )
1187 SetFocus16( (pWnd->dwStyle & WS_CHILD) ? pWnd->parent->hwndSelf : 0 );
1190 /***********************************************************************
1191 * WIN_SendDestroyMsg
1193 static void WIN_SendDestroyMsg( WND* pWnd )
1195 WIN_CheckFocus(pWnd);
1197 if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret();
1198 CLIPBOARD_Driver->pResetOwner( pWnd, TRUE );
1201 * Send the WM_DESTROY to the window.
1203 SendMessageA( pWnd->hwndSelf, WM_DESTROY, 0, 0);
1206 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1207 * make sure that the window still exists when we come back.
1209 if (IsWindow(pWnd->hwndSelf))
1211 HWND* pWndArray = NULL;
1212 WND* pChild = NULL;
1213 int nKidCount = 0;
1216 * Now, if the window has kids, we have to send WM_DESTROY messages
1217 * recursively to it's kids. It seems that those calls can also
1218 * trigger re-entrant calls to DestroyWindow for the kids so we must
1219 * protect against corruption of the list of siblings. We first build
1220 * a list of HWNDs representing all the kids.
1222 pChild = WIN_LockWndPtr(pWnd->child);
1223 while( pChild )
1225 nKidCount++;
1226 WIN_UpdateWndPtr(&pChild,pChild->next);
1230 * If there are no kids, we're done.
1232 if (nKidCount==0)
1233 return;
1235 pWndArray = HeapAlloc(GetProcessHeap(), 0, nKidCount*sizeof(HWND));
1238 * Sanity check
1240 if (pWndArray==NULL)
1241 return;
1244 * Now, enumerate all the kids in a list, since we wait to make the SendMessage
1245 * call, our linked list of siblings should be safe.
1247 nKidCount = 0;
1248 pChild = WIN_LockWndPtr(pWnd->child);
1249 while( pChild )
1251 pWndArray[nKidCount] = pChild->hwndSelf;
1252 nKidCount++;
1253 WIN_UpdateWndPtr(&pChild,pChild->next);
1257 * Now that we have a list, go through that list again and send the destroy
1258 * message to those windows. We are using the HWND to retrieve the
1259 * WND pointer so we are effectively checking that all the kid windows are
1260 * still valid before sending the message.
1262 while (nKidCount>0)
1264 pChild = WIN_FindWndPtr(pWndArray[--nKidCount]);
1266 if (pChild!=NULL)
1268 WIN_SendDestroyMsg( pChild );
1269 WIN_ReleaseWndPtr(pChild);
1274 * Cleanup
1276 HeapFree(GetProcessHeap(), 0, pWndArray);
1277 WIN_CheckFocus(pWnd);
1279 else
1280 WARN_(win)("\tdestroyed itself while in WM_DESTROY!\n");
1284 /***********************************************************************
1285 * DestroyWindow16 (USER.53)
1287 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
1289 return DestroyWindow(hwnd);
1293 /***********************************************************************
1294 * DestroyWindow32 (USER32.135)
1296 BOOL WINAPI DestroyWindow( HWND hwnd )
1298 WND * wndPtr;
1299 BOOL retvalue;
1301 TRACE_(win)("(%04x)\n", hwnd);
1303 /* Initialization */
1305 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1306 if (wndPtr == pWndDesktop)
1308 WIN_ReleaseWndPtr(wndPtr);
1309 return FALSE; /* Can't destroy desktop */
1312 /* Call hooks */
1314 if( HOOK_CallHooks16( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
1316 retvalue = FALSE;
1317 goto end;
1320 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1322 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
1323 /* FIXME: clean up palette - see "Internals" p.352 */
1326 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
1327 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
1329 /* Notify the parent window only */
1330 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
1331 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
1332 if( !IsWindow(hwnd) )
1334 retvalue = TRUE;
1335 goto end;
1339 CLIPBOARD_Driver->pResetOwner( wndPtr, FALSE ); /* before the window is unmapped */
1341 /* Hide the window */
1343 if (wndPtr->dwStyle & WS_VISIBLE)
1345 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW |
1346 SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|
1347 ((QUEUE_IsExitingQueue(wndPtr->hmemTaskQ))?SWP_DEFERERASE:0) );
1348 if (!IsWindow(hwnd))
1350 retvalue = TRUE;
1351 goto end;
1355 /* Recursively destroy owned windows */
1357 if( !(wndPtr->dwStyle & WS_CHILD) )
1359 /* make sure top menu popup doesn't get destroyed */
1360 MENU_PatchResidentPopup( (HQUEUE16)0xFFFF, wndPtr );
1362 for (;;)
1364 WND *siblingPtr = WIN_LockWndPtr(wndPtr->parent->child); /* First sibling */
1365 while (siblingPtr)
1367 if (siblingPtr->owner == wndPtr)
1369 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1370 break;
1371 else
1372 siblingPtr->owner = NULL;
1374 WIN_UpdateWndPtr(&siblingPtr,siblingPtr->next);
1376 if (siblingPtr)
1378 DestroyWindow( siblingPtr->hwndSelf );
1379 WIN_ReleaseWndPtr(siblingPtr);
1381 else break;
1384 if( !Options.managed || EVENT_CheckFocus() )
1385 WINPOS_ActivateOtherWindow(wndPtr);
1387 if( wndPtr->owner &&
1388 wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1389 wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1392 /* Send destroy messages */
1394 WIN_SendDestroyMsg( wndPtr );
1395 if (!IsWindow(hwnd))
1397 retvalue = TRUE;
1398 goto end;
1401 /* Unlink now so we won't bother with the children later on */
1403 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1405 /* Destroy the window storage */
1407 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1408 retvalue = TRUE;
1409 end:
1410 WIN_ReleaseWndPtr(wndPtr);
1411 return retvalue;
1415 /***********************************************************************
1416 * CloseWindow16 (USER.43)
1418 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1420 return CloseWindow( hwnd );
1424 /***********************************************************************
1425 * CloseWindow32 (USER32.56)
1427 BOOL WINAPI CloseWindow( HWND hwnd )
1429 WND * wndPtr = WIN_FindWndPtr( hwnd );
1430 BOOL retvalue;
1432 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD))
1434 retvalue = FALSE;
1435 goto end;
1437 ShowWindow( hwnd, SW_MINIMIZE );
1438 retvalue = TRUE;
1439 end:
1440 WIN_ReleaseWndPtr(wndPtr);
1441 return retvalue;
1446 /***********************************************************************
1447 * OpenIcon16 (USER.44)
1449 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1451 return OpenIcon( hwnd );
1455 /***********************************************************************
1456 * OpenIcon32 (USER32.410)
1458 BOOL WINAPI OpenIcon( HWND hwnd )
1460 if (!IsIconic( hwnd )) return FALSE;
1461 ShowWindow( hwnd, SW_SHOWNORMAL );
1462 return TRUE;
1466 /***********************************************************************
1467 * WIN_FindWindow
1469 * Implementation of FindWindow() and FindWindowEx().
1471 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className,
1472 LPCSTR title )
1474 WND *pWnd;
1475 HWND retvalue;
1476 CLASS *pClass = NULL;
1478 if (child)
1480 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1481 if (parent)
1483 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent))
1485 retvalue = 0;
1486 goto end;
1489 else if (pWnd->parent != pWndDesktop)
1491 retvalue = 0;
1492 goto end;
1494 WIN_UpdateWndPtr(&pWnd,pWnd->next);
1496 else
1498 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : WIN_LockWndPtr(pWndDesktop)))
1500 retvalue = 0;
1501 goto end;
1503 WIN_UpdateWndPtr(&pWnd,pWnd->child);
1505 if (!pWnd)
1507 retvalue = 0;
1508 goto end;
1511 /* For a child window, all siblings will have the same hInstance, */
1512 /* so we can look for the class once and for all. */
1514 if (className && (pWnd->dwStyle & WS_CHILD))
1516 if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance )))
1518 retvalue = 0;
1519 goto end;
1524 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
1526 if (className && !(pWnd->dwStyle & WS_CHILD))
1528 if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance)))
1529 continue; /* Skip this window */
1532 if (pClass && (pWnd->class != pClass))
1533 continue; /* Not the right class */
1535 /* Now check the title */
1537 if (!title)
1539 retvalue = pWnd->hwndSelf;
1540 goto end;
1542 if (pWnd->text && !strcmp( pWnd->text, title ))
1544 retvalue = pWnd->hwndSelf;
1545 goto end;
1548 retvalue = 0;
1549 end:
1550 WIN_ReleaseWndPtr(pWnd);
1551 return retvalue;
1556 /***********************************************************************
1557 * FindWindow16 (USER.50)
1559 HWND16 WINAPI FindWindow16( SEGPTR className, LPCSTR title )
1561 return FindWindowEx16( 0, 0, className, title );
1565 /***********************************************************************
1566 * FindWindowEx16 (USER.427)
1568 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child,
1569 SEGPTR className, LPCSTR title )
1571 ATOM atom = 0;
1573 TRACE_(win)("%04x %04x '%s' '%s'\n", parent,
1574 child, HIWORD(className)?(char *)PTR_SEG_TO_LIN(className):"",
1575 title ? title : "");
1577 if (className)
1579 /* If the atom doesn't exist, then no class */
1580 /* with this name exists either. */
1581 if (!(atom = GlobalFindAtom16( className ))) return 0;
1583 return WIN_FindWindow( parent, child, atom, title );
1587 /***********************************************************************
1588 * FindWindow32A (USER32.198)
1590 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1592 HWND ret = FindWindowExA( 0, 0, className, title );
1593 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1594 return ret;
1598 /***********************************************************************
1599 * FindWindowEx32A (USER32.199)
1601 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1602 LPCSTR className, LPCSTR title )
1604 ATOM atom = 0;
1606 if (className)
1608 /* If the atom doesn't exist, then no class */
1609 /* with this name exists either. */
1610 if (!(atom = GlobalFindAtomA( className )))
1612 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1613 return 0;
1616 return WIN_FindWindow( parent, child, atom, title );
1620 /***********************************************************************
1621 * FindWindowEx32W (USER32.200)
1623 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1624 LPCWSTR className, LPCWSTR title )
1626 ATOM atom = 0;
1627 char *buffer;
1628 HWND hwnd;
1630 if (className)
1632 /* If the atom doesn't exist, then no class */
1633 /* with this name exists either. */
1634 if (!(atom = GlobalFindAtomW( className )))
1636 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1637 return 0;
1640 buffer = HEAP_strdupWtoA( GetProcessHeap(), 0, title );
1641 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1642 HeapFree( GetProcessHeap(), 0, buffer );
1643 return hwnd;
1647 /***********************************************************************
1648 * FindWindow32W (USER32.201)
1650 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1652 return FindWindowExW( 0, 0, className, title );
1656 /**********************************************************************
1657 * WIN_GetDesktop
1658 * returns a locked pointer
1660 WND *WIN_GetDesktop(void)
1662 return WIN_LockWndPtr(pWndDesktop);
1664 /**********************************************************************
1665 * WIN_ReleaseDesktop
1666 * unlock the desktop pointer
1668 void WIN_ReleaseDesktop(void)
1670 WIN_ReleaseWndPtr(pWndDesktop);
1674 /**********************************************************************
1675 * GetDesktopWindow16 (USER.286)
1677 HWND16 WINAPI GetDesktopWindow16(void)
1679 return (HWND16)pWndDesktop->hwndSelf;
1683 /**********************************************************************
1684 * GetDesktopWindow32 (USER32.232)
1686 HWND WINAPI GetDesktopWindow(void)
1688 return pWndDesktop->hwndSelf;
1692 /**********************************************************************
1693 * GetDesktopHwnd (USER.278)
1695 * Exactly the same thing as GetDesktopWindow(), but not documented.
1696 * Don't ask me why...
1698 HWND16 WINAPI GetDesktopHwnd16(void)
1700 return (HWND16)pWndDesktop->hwndSelf;
1704 /*******************************************************************
1705 * EnableWindow16 (USER.34)
1707 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1709 return EnableWindow( hwnd, enable );
1713 /*******************************************************************
1714 * EnableWindow32 (USER32.172)
1716 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1718 WND *wndPtr;
1719 BOOL retvalue;
1721 TRACE_(win)("EnableWindow32: ( %x, %d )\n", hwnd, enable);
1723 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1724 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1726 /* Enable window */
1727 wndPtr->dwStyle &= ~WS_DISABLED;
1729 if( wndPtr->flags & WIN_NATIVE )
1730 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, TRUE );
1732 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1733 retvalue = TRUE;
1734 goto end;
1736 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1738 SendMessageA( wndPtr->hwndSelf, WM_CANCELMODE, 0, 0);
1740 /* Disable window */
1741 wndPtr->dwStyle |= WS_DISABLED;
1743 if( wndPtr->flags & WIN_NATIVE )
1744 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, FALSE );
1746 if (hwnd == GetFocus())
1748 SetFocus( 0 ); /* A disabled window can't have the focus */
1750 if (hwnd == GetCapture())
1752 ReleaseCapture(); /* A disabled window can't capture the mouse */
1754 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1755 retvalue = FALSE;
1756 goto end;
1758 retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
1759 end:
1760 WIN_ReleaseWndPtr(wndPtr);
1761 return retvalue;
1765 /***********************************************************************
1766 * IsWindowEnabled16 (USER.35)
1768 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1770 return IsWindowEnabled(hWnd);
1774 /***********************************************************************
1775 * IsWindowEnabled32 (USER32.349)
1777 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1779 WND * wndPtr;
1780 BOOL retvalue;
1782 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1783 retvalue = !(wndPtr->dwStyle & WS_DISABLED);
1784 WIN_ReleaseWndPtr(wndPtr);
1785 return retvalue;
1790 /***********************************************************************
1791 * IsWindowUnicode (USER32.350)
1793 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1795 WND * wndPtr;
1796 BOOL retvalue;
1798 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1799 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1800 WIN_ReleaseWndPtr(wndPtr);
1801 return retvalue;
1805 /**********************************************************************
1806 * GetWindowWord16 (USER.133)
1808 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1810 return GetWindowWord( hwnd, offset );
1814 /**********************************************************************
1815 * GetWindowWord32 (USER32.314)
1817 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1819 WORD retvalue;
1820 WND * wndPtr = WIN_FindWndPtr( hwnd );
1821 if (!wndPtr) return 0;
1822 if (offset >= 0)
1824 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1826 WARN_(win)("Invalid offset %d\n", offset );
1827 retvalue = 0;
1828 goto end;
1830 retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1831 goto end;
1833 switch(offset)
1835 case GWW_ID:
1836 if (HIWORD(wndPtr->wIDmenu))
1837 WARN_(win)("GWW_ID: discards high bits of 0x%08x!\n",
1838 wndPtr->wIDmenu);
1839 retvalue = (WORD)wndPtr->wIDmenu;
1840 goto end;
1841 case GWW_HWNDPARENT:
1842 retvalue = GetParent(hwnd);
1843 goto end;
1844 case GWW_HINSTANCE:
1845 if (HIWORD(wndPtr->hInstance))
1846 WARN_(win)("GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1847 wndPtr->hInstance);
1848 retvalue = (WORD)wndPtr->hInstance;
1849 goto end;
1850 default:
1851 WARN_(win)("Invalid offset %d\n", offset );
1852 retvalue = 0;
1853 goto end;
1855 end:
1856 WIN_ReleaseWndPtr(wndPtr);
1857 return retvalue;
1860 /**********************************************************************
1861 * SetWindowWord16 (USER.134)
1863 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1865 return SetWindowWord( hwnd, offset, newval );
1869 /**********************************************************************
1870 * SetWindowWord32 (USER32.524)
1872 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1874 WORD *ptr, retval;
1875 WND * wndPtr = WIN_FindWndPtr( hwnd );
1876 if (!wndPtr) return 0;
1877 if (offset >= 0)
1879 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1881 WARN_(win)("Invalid offset %d\n", offset );
1882 retval = 0;
1883 goto end;
1885 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1887 else switch(offset)
1889 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1890 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1891 case GWW_HWNDPARENT: retval = SetParent( hwnd, newval );
1892 goto end;
1893 default:
1894 WARN_(win)("Invalid offset %d\n", offset );
1895 retval = 0;
1896 goto end;
1898 retval = *ptr;
1899 *ptr = newval;
1900 end:
1901 WIN_ReleaseWndPtr(wndPtr);
1902 return retval;
1906 /**********************************************************************
1907 * WIN_GetWindowLong
1909 * Helper function for GetWindowLong().
1911 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1913 LONG retvalue;
1914 WND * wndPtr = WIN_FindWndPtr( hwnd );
1915 if (!wndPtr) return 0;
1916 if (offset >= 0)
1918 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1920 WARN_(win)("Invalid offset %d\n", offset );
1921 retvalue = 0;
1922 goto end;
1924 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1925 /* Special case for dialog window procedure */
1926 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1928 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1929 goto end;
1931 goto end;
1933 switch(offset)
1935 case GWL_USERDATA: retvalue = wndPtr->userdata;
1936 goto end;
1937 case GWL_STYLE: retvalue = wndPtr->dwStyle;
1938 goto end;
1939 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle;
1940 goto end;
1941 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu;
1942 goto end;
1943 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc,
1944 type );
1945 goto end;
1946 case GWL_HWNDPARENT: retvalue = GetParent(hwnd);
1947 goto end;
1948 case GWL_HINSTANCE: retvalue = wndPtr->hInstance;
1949 goto end;
1950 default:
1951 WARN_(win)("Unknown offset %d\n", offset );
1953 retvalue = 0;
1954 end:
1955 WIN_ReleaseWndPtr(wndPtr);
1956 return retvalue;
1960 /**********************************************************************
1961 * WIN_SetWindowLong
1963 * Helper function for SetWindowLong().
1965 * 0 is the failure code. However, in the case of failure SetLastError
1966 * must be set to distinguish between a 0 return value and a failure.
1968 * FIXME: The error values for SetLastError may not be right. Can
1969 * someone check with the real thing?
1971 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1972 WINDOWPROCTYPE type )
1974 LONG *ptr, retval;
1975 WND * wndPtr = WIN_FindWndPtr( hwnd );
1976 STYLESTRUCT style;
1978 TRACE_(win)("%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1980 if (!wndPtr)
1982 /* Is this the right error? */
1983 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1984 return 0;
1987 if (offset >= 0)
1989 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1991 WARN_(win)("Invalid offset %d\n", offset );
1993 /* Is this the right error? */
1994 SetLastError( ERROR_OUTOFMEMORY );
1996 retval = 0;
1997 goto end;
1999 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
2000 /* Special case for dialog window procedure */
2001 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2003 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
2004 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
2005 type, WIN_PROC_WINDOW );
2006 goto end;
2009 else switch(offset)
2011 case GWL_ID:
2012 ptr = (DWORD*)&wndPtr->wIDmenu;
2013 break;
2014 case GWL_HINSTANCE:
2015 retval = SetWindowWord( hwnd, offset, newval );
2016 goto end;
2017 case GWL_WNDPROC:
2018 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
2019 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
2020 type, WIN_PROC_WINDOW );
2021 goto end;;
2022 case GWL_STYLE:
2023 style.styleOld = wndPtr->dwStyle;
2024 newval &= ~(WS_VISIBLE | WS_CHILD); /* Some bits can't be changed this way */
2025 style.styleNew = newval | (style.styleOld & (WS_VISIBLE | WS_CHILD));
2027 if (wndPtr->flags & WIN_ISWIN32)
2028 SendMessageA(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
2029 wndPtr->dwStyle = style.styleNew;
2030 if (wndPtr->flags & WIN_ISWIN32)
2031 SendMessageA(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
2032 retval = style.styleOld;
2033 goto end;
2035 case GWL_USERDATA:
2036 ptr = &wndPtr->userdata;
2037 break;
2038 case GWL_EXSTYLE:
2039 style.styleOld = wndPtr->dwExStyle;
2040 style.styleNew = newval;
2041 if (wndPtr->flags & WIN_ISWIN32)
2042 SendMessageA(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
2043 wndPtr->dwExStyle = newval;
2044 if (wndPtr->flags & WIN_ISWIN32)
2045 SendMessageA(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
2046 retval = style.styleOld;
2047 goto end;
2049 default:
2050 WARN_(win)("Invalid offset %d\n", offset );
2052 /* Don't think this is right error but it should do */
2053 SetLastError( ERROR_OUTOFMEMORY );
2055 retval = 0;
2056 goto end;
2058 retval = *ptr;
2059 *ptr = newval;
2060 end:
2061 WIN_ReleaseWndPtr(wndPtr);
2062 return retval;
2066 /**********************************************************************
2067 * GetWindowLong16 (USER.135)
2069 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2071 return WIN_GetWindowLong( (HWND)hwnd, offset, WIN_PROC_16 );
2075 /**********************************************************************
2076 * GetWindowLong32A (USER32.305)
2078 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2080 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2084 /**********************************************************************
2085 * GetWindowLong32W (USER32.306)
2087 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2089 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2093 /**********************************************************************
2094 * SetWindowLong16 (USER.136)
2096 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2098 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
2102 /**********************************************************************
2103 * SetWindowLong32A (USER32.517)
2105 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2107 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2111 /**********************************************************************
2112 * SetWindowLong32W (USER32.518) Set window attribute
2114 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2115 * value in a window's extra memory.
2117 * The _hwnd_ parameter specifies the window. is the handle to a
2118 * window that has extra memory. The _newval_ parameter contains the
2119 * new attribute or extra memory value. If positive, the _offset_
2120 * parameter is the byte-addressed location in the window's extra
2121 * memory to set. If negative, _offset_ specifies the window
2122 * attribute to set, and should be one of the following values:
2124 * GWL_EXSTYLE The window's extended window style
2126 * GWL_STYLE The window's window style.
2128 * GWL_WNDPROC Pointer to the window's window procedure.
2130 * GWL_HINSTANCE The window's pplication instance handle.
2132 * GWL_ID The window's identifier.
2134 * GWL_USERDATA The window's user-specified data.
2136 * If the window is a dialog box, the _offset_ parameter can be one of
2137 * the following values:
2139 * DWL_DLGPROC The address of the window's dialog box procedure.
2141 * DWL_MSGRESULT The return value of a message
2142 * that the dialog box procedure processed.
2144 * DWL_USER Application specific information.
2146 * RETURNS
2148 * If successful, returns the previous value located at _offset_. Otherwise,
2149 * returns 0.
2151 * NOTES
2153 * Extra memory for a window class is specified by a nonzero cbWndExtra
2154 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2155 * time of class creation.
2157 * Using GWL_WNDPROC to set a new window procedure effectively creates
2158 * a window subclass. Use CallWindowProc() in the new windows procedure
2159 * to pass messages to the superclass's window procedure.
2161 * The user data is reserved for use by the application which created
2162 * the window.
2164 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
2165 * instead, call the EnableWindow() function to change the window's
2166 * disabled state.
2168 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2169 * SetParent() instead.
2171 * Win95:
2172 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2173 * it sends WM_STYLECHANGING before changing the settings
2174 * and WM_STYLECHANGED afterwards.
2175 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2177 * BUGS
2179 * GWL_STYLE does not dispatch WM_STYLE... messages.
2181 * CONFORMANCE
2183 * ECMA-234, Win32
2186 LONG WINAPI SetWindowLongW(
2187 HWND hwnd, /* window to alter */
2188 INT offset, /* offset, in bytes, of location to alter */
2189 LONG newval /* new value of location */
2191 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2195 /*******************************************************************
2196 * GetWindowText16 (USER.36)
2198 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
2200 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
2204 /*******************************************************************
2205 * GetWindowText32A (USER32.309)
2207 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2209 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount,
2210 (LPARAM)lpString );
2213 /*******************************************************************
2214 * InternalGetWindowText (USER32.326)
2216 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2218 FIXME_(win)("(0x%08x,%p,0x%x),stub!\n",hwnd,lpString,nMaxCount);
2219 return GetWindowTextW(hwnd,lpString,nMaxCount);
2223 /*******************************************************************
2224 * GetWindowText32W (USER32.312)
2226 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2228 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount,
2229 (LPARAM)lpString );
2233 /*******************************************************************
2234 * SetWindowText16 (USER.37)
2236 BOOL16 WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
2238 return (BOOL16)SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2242 /*******************************************************************
2243 * SetWindowText32A (USER32.521)
2245 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2247 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2251 /*******************************************************************
2252 * SetWindowText32W (USER32.523)
2254 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2256 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2260 /*******************************************************************
2261 * GetWindowTextLength16 (USER.38)
2263 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
2265 return (INT16)SendMessage16( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2269 /*******************************************************************
2270 * GetWindowTextLength32A (USER32.310)
2272 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2274 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2277 /*******************************************************************
2278 * GetWindowTextLength32W (USER32.311)
2280 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2282 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2286 /*******************************************************************
2287 * IsWindow16 (USER.47)
2289 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
2291 return IsWindow( hwnd );
2294 void WINAPI WIN16_IsWindow16( CONTEXT *context )
2296 WORD *stack = PTR_SEG_OFF_TO_LIN(SS_reg(context), SP_reg(context));
2297 HWND16 hwnd = (HWND16)stack[2];
2299 AX_reg(context) = IsWindow( hwnd );
2300 ES_reg(context) = USER_HeapSel;
2304 /*******************************************************************
2305 * IsWindow32 (USER32.348)
2307 BOOL WINAPI IsWindow( HWND hwnd )
2309 WND * wndPtr;
2310 BOOL retvalue;
2312 if(!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2313 retvalue = (wndPtr->dwMagic == WND_MAGIC);
2314 WIN_ReleaseWndPtr(wndPtr);
2315 return retvalue;
2320 /*****************************************************************
2321 * GetParent16 (USER.46)
2323 HWND16 WINAPI GetParent16( HWND16 hwnd )
2325 return (HWND16)GetParent( hwnd );
2329 /*****************************************************************
2330 * GetParent32 (USER32.278)
2332 HWND WINAPI GetParent( HWND hwnd )
2334 WND *wndPtr;
2335 HWND retvalue;
2337 if(!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2338 if ((!(wndPtr->dwStyle & (WS_POPUP|WS_CHILD))))
2340 WIN_ReleaseWndPtr(wndPtr);
2341 return 0;
2343 WIN_UpdateWndPtr(&wndPtr,((wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner));
2344 retvalue = wndPtr ? wndPtr->hwndSelf : 0;
2346 WIN_ReleaseWndPtr(wndPtr);
2347 return retvalue;
2351 /*****************************************************************
2352 * WIN_GetTopParent
2354 * Get the top-level parent for a child window.
2355 * returns a locked pointer
2357 WND* WIN_GetTopParentPtr( WND* pWnd )
2359 WND *tmpWnd = WIN_LockWndPtr(pWnd);
2361 while( tmpWnd && (tmpWnd->dwStyle & WS_CHILD))
2363 WIN_UpdateWndPtr(&tmpWnd,tmpWnd->parent);
2365 return tmpWnd;
2368 /*****************************************************************
2369 * WIN_GetTopParent
2371 * Get the top-level parent for a child window.
2373 HWND WIN_GetTopParent( HWND hwnd )
2375 HWND retvalue;
2376 WND *tmpPtr = WIN_FindWndPtr(hwnd);
2377 WND *wndPtr = WIN_GetTopParentPtr (tmpPtr );
2379 retvalue = wndPtr ? wndPtr->hwndSelf : 0;
2380 WIN_ReleaseWndPtr(tmpPtr);
2381 WIN_ReleaseWndPtr(wndPtr);
2382 return retvalue;
2386 /*****************************************************************
2387 * SetParent16 (USER.233)
2389 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
2391 return SetParent( hwndChild, hwndNewParent );
2395 /*****************************************************************
2396 * SetParent32 (USER32.495)
2398 HWND WINAPI SetParent( HWND hwndChild, HWND hwndNewParent )
2400 WND *wndPtr;
2401 DWORD dwStyle;
2402 WND *pWndNewParent;
2403 WND *pWndOldParent;
2404 HWND retvalue;
2407 if(!(wndPtr = WIN_FindWndPtr(hwndChild))) return 0;
2409 dwStyle = wndPtr->dwStyle;
2411 pWndNewParent = hwndNewParent ? WIN_FindWndPtr(hwndNewParent)
2412 : WIN_LockWndPtr(pWndDesktop);
2414 /* Windows hides the window first, then shows it again
2415 * including the WM_SHOWWINDOW messages and all */
2416 if (dwStyle & WS_VISIBLE)
2417 ShowWindow( hwndChild, SW_HIDE );
2419 pWndOldParent = WIN_LockWndPtr((*wndPtr->pDriver->pSetParent)(wndPtr, pWndNewParent));
2421 /* SetParent32 additionally needs to make hwndChild the topmost window
2422 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2423 WM_WINDOWPOSCHANGED notification messages.
2425 SetWindowPos( hwndChild, HWND_TOPMOST, 0, 0, 0, 0,
2426 SWP_NOMOVE|SWP_NOSIZE|((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
2427 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2428 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2430 retvalue = pWndOldParent?pWndOldParent->hwndSelf:0;
2432 WIN_ReleaseWndPtr(pWndOldParent);
2433 WIN_ReleaseWndPtr(pWndNewParent);
2434 WIN_ReleaseWndPtr(wndPtr);
2436 return retvalue;
2440 /*******************************************************************
2441 * IsChild16 (USER.48)
2443 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
2445 return IsChild(parent,child);
2449 /*******************************************************************
2450 * IsChild32 (USER32.339)
2452 BOOL WINAPI IsChild( HWND parent, HWND child )
2454 WND * wndPtr = WIN_FindWndPtr( child );
2455 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2457 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2458 if (wndPtr->hwndSelf == parent)
2460 WIN_ReleaseWndPtr(wndPtr);
2461 return TRUE;
2464 WIN_ReleaseWndPtr(wndPtr);
2465 return FALSE;
2469 /***********************************************************************
2470 * IsWindowVisible16 (USER.49)
2472 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
2474 return IsWindowVisible(hwnd);
2478 /***********************************************************************
2479 * IsWindowVisible32 (USER32.351)
2481 BOOL WINAPI IsWindowVisible( HWND hwnd )
2483 BOOL retval;
2484 WND *wndPtr = WIN_FindWndPtr( hwnd );
2485 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2487 if (!(wndPtr->dwStyle & WS_VISIBLE))
2489 WIN_ReleaseWndPtr(wndPtr);
2490 return FALSE;
2492 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2494 retval = (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
2495 WIN_ReleaseWndPtr(wndPtr);
2496 return retval;
2501 /***********************************************************************
2502 * WIN_IsWindowDrawable
2504 * hwnd is drawable when it is visible, all parents are not
2505 * minimized, and it is itself not minimized unless we are
2506 * trying to draw its default class icon.
2508 BOOL WIN_IsWindowDrawable( WND* wnd, BOOL icon )
2510 if( (wnd->dwStyle & WS_MINIMIZE &&
2511 icon && wnd->class->hIcon) ||
2512 !(wnd->dwStyle & WS_VISIBLE) ) return FALSE;
2513 for(wnd = wnd->parent; wnd; wnd = wnd->parent)
2514 if( wnd->dwStyle & WS_MINIMIZE ||
2515 !(wnd->dwStyle & WS_VISIBLE) ) break;
2516 return (wnd == NULL);
2520 /*******************************************************************
2521 * GetTopWindow16 (USER.229)
2523 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
2525 return GetTopWindow(hwnd);
2529 /*******************************************************************
2530 * GetTopWindow32 (USER.229)
2532 HWND WINAPI GetTopWindow( HWND hwnd )
2534 HWND retval;
2535 WND * wndPtr = NULL;
2537 if (hwnd!=0)
2538 wndPtr = WIN_FindWndPtr( hwnd );
2539 else
2540 wndPtr = WIN_GetDesktop();
2542 if (wndPtr && wndPtr->child)
2544 retval = wndPtr->child->hwndSelf;
2546 else retval = 0;
2547 WIN_ReleaseWndPtr(wndPtr);
2548 return retval;
2552 /*******************************************************************
2553 * GetWindow16 (USER.262)
2555 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
2557 return GetWindow( hwnd,rel );
2561 /*******************************************************************
2562 * GetWindow32 (USER32.302)
2564 HWND WINAPI GetWindow( HWND hwnd, WORD rel )
2566 HWND retval;
2568 WND * wndPtr = WIN_FindWndPtr( hwnd );
2569 if (!wndPtr) return 0;
2570 switch(rel)
2572 case GW_HWNDFIRST:
2573 if (wndPtr->parent) retval = wndPtr->parent->child->hwndSelf;
2574 else retval = 0;
2575 goto end;
2577 case GW_HWNDLAST:
2578 if (!wndPtr->parent)
2580 retval = 0; /* Desktop window */
2581 goto end;
2583 while (wndPtr->next)
2585 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2587 retval = wndPtr->hwndSelf;
2588 goto end;
2590 case GW_HWNDNEXT:
2591 if (!wndPtr->next) retval = 0;
2592 else retval = wndPtr->next->hwndSelf;
2593 goto end;
2595 case GW_HWNDPREV:
2596 if (!wndPtr->parent)
2598 retval = 0; /* Desktop window */
2599 goto end;
2601 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent->child); /* First sibling */
2602 if (wndPtr->hwndSelf == hwnd)
2604 retval = 0; /* First in list */
2605 goto end;
2607 while (wndPtr->next)
2609 if (wndPtr->next->hwndSelf == hwnd)
2611 retval = wndPtr->hwndSelf;
2612 goto end;
2614 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2616 retval = 0;
2617 goto end;
2619 case GW_OWNER:
2620 retval = wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
2621 goto end;
2623 case GW_CHILD:
2624 retval = wndPtr->child ? wndPtr->child->hwndSelf : 0;
2625 goto end;
2627 retval = 0;
2628 end:
2629 WIN_ReleaseWndPtr(wndPtr);
2630 return retval;
2634 /*******************************************************************
2635 * GetNextWindow16 (USER.230)
2637 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2639 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2640 return GetWindow16( hwnd, flag );
2643 /*******************************************************************
2644 * ShowOwnedPopups16 (USER.265)
2646 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2648 ShowOwnedPopups( owner, fShow );
2652 /*******************************************************************
2653 * ShowOwnedPopups32 (USER32.531)
2655 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2657 WND *pWnd;
2658 pWnd = WIN_LockWndPtr(pWndDesktop->child);
2659 while (pWnd)
2661 if (pWnd->owner && (pWnd->owner->hwndSelf == owner) &&
2662 (pWnd->dwStyle & WS_POPUP))
2663 ShowWindow( pWnd->hwndSelf, fShow ? SW_SHOW : SW_HIDE );
2664 WIN_UpdateWndPtr(&pWnd,pWnd->next);
2666 return TRUE;
2670 /*******************************************************************
2671 * GetLastActivePopup16 (USER.287)
2673 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2675 return GetLastActivePopup( hwnd );
2678 /*******************************************************************
2679 * GetLastActivePopup32 (USER32.256)
2681 HWND WINAPI GetLastActivePopup( HWND hwnd )
2683 WND *wndPtr;
2684 HWND retval;
2685 wndPtr = WIN_FindWndPtr(hwnd);
2686 if (!wndPtr) return hwnd;
2687 retval = wndPtr->hwndLastActive;
2688 WIN_ReleaseWndPtr(wndPtr);
2689 return retval;
2693 /*******************************************************************
2694 * WIN_BuildWinArray
2696 * Build an array of pointers to the children of a given window.
2697 * The array must be freed with HeapFree(SystemHeap). Return NULL
2698 * when no windows are found.
2700 WND **WIN_BuildWinArray( WND *wndPtr, UINT bwaFlags, UINT* pTotal )
2702 /* Future : this function will lock all windows associated with this array */
2704 WND **list, **ppWnd;
2705 WND *pWnd;
2706 UINT count = 0, skipOwned, skipHidden;
2707 DWORD skipFlags;
2709 skipHidden = bwaFlags & BWA_SKIPHIDDEN;
2710 skipOwned = bwaFlags & BWA_SKIPOWNED;
2711 skipFlags = (bwaFlags & BWA_SKIPDISABLED) ? WS_DISABLED : 0;
2712 if( bwaFlags & BWA_SKIPICONIC ) skipFlags |= WS_MINIMIZE;
2714 /* First count the windows */
2716 if (!wndPtr)
2717 wndPtr = WIN_GetDesktop();
2719 pWnd = WIN_LockWndPtr(wndPtr->child);
2720 while (pWnd)
2722 if( !(pWnd->dwStyle & skipFlags) && !(skipOwned && pWnd->owner) &&
2723 (!skipHidden || (pWnd->dwStyle & WS_VISIBLE)) )
2724 count++;
2725 WIN_UpdateWndPtr(&pWnd,pWnd->next);
2728 if( count )
2730 /* Now build the list of all windows */
2732 if ((list = (WND **)HeapAlloc( SystemHeap, 0, sizeof(WND *) * (count + 1))))
2734 for (pWnd = WIN_LockWndPtr(wndPtr->child), ppWnd = list, count = 0; pWnd; WIN_UpdateWndPtr(&pWnd,pWnd->next))
2736 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) );
2737 else if( !skipHidden || pWnd->dwStyle & WS_VISIBLE )
2739 *ppWnd++ = pWnd;
2740 count++;
2743 WIN_ReleaseWndPtr(pWnd);
2744 *ppWnd = NULL;
2746 else count = 0;
2747 } else list = NULL;
2749 if( pTotal ) *pTotal = count;
2750 return list;
2752 /*******************************************************************
2753 * WIN_ReleaseWinArray
2755 void WIN_ReleaseWinArray(WND **wndArray)
2757 /* Future : this function will also unlock all windows associated with wndArray */
2758 HeapFree( SystemHeap, 0, wndArray );
2762 /*******************************************************************
2763 * EnumWindows16 (USER.54)
2765 BOOL16 WINAPI EnumWindows16( WNDENUMPROC16 lpEnumFunc, LPARAM lParam )
2767 WND **list, **ppWnd;
2769 /* We have to build a list of all windows first, to avoid */
2770 /* unpleasant side-effects, for instance if the callback */
2771 /* function changes the Z-order of the windows. */
2773 if (!(list = WIN_BuildWinArray(WIN_GetDesktop(), 0, NULL )))
2775 WIN_ReleaseDesktop();
2776 return FALSE;
2779 /* Now call the callback function for every window */
2781 for (ppWnd = list; *ppWnd; ppWnd++)
2783 LRESULT lpEnumFuncRetval;
2784 int iWndsLocks = 0;
2785 /* Make sure that the window still exists */
2786 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2788 /* To avoid any deadlocks, all the locks on the windows
2789 structures must be suspended before the control
2790 is passed to the application */
2791 iWndsLocks = WIN_SuspendWndsLock();
2792 lpEnumFuncRetval = lpEnumFunc( (*ppWnd)->hwndSelf, lParam);
2793 WIN_RestoreWndsLock(iWndsLocks);
2795 if (!lpEnumFuncRetval) break;
2797 WIN_ReleaseWinArray(list);
2798 WIN_ReleaseDesktop();
2799 return TRUE;
2803 /*******************************************************************
2804 * EnumWindows32 (USER32.193)
2806 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2808 return (BOOL)EnumWindows16( (WNDENUMPROC16)lpEnumFunc, lParam );
2812 /**********************************************************************
2813 * EnumTaskWindows16 (USER.225)
2815 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2816 LPARAM lParam )
2818 WND **list, **ppWnd;
2820 /* This function is the same as EnumWindows(), */
2821 /* except for an added check on the window's task. */
2823 if (!(list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
2825 WIN_ReleaseDesktop();
2826 return FALSE;
2829 /* Now call the callback function for every window */
2831 for (ppWnd = list; *ppWnd; ppWnd++)
2833 LRESULT funcRetval;
2834 int iWndsLocks = 0;
2835 /* Make sure that the window still exists */
2836 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2837 if (QUEUE_GetQueueTask((*ppWnd)->hmemTaskQ) != hTask) continue;
2839 /* To avoid any deadlocks, all the locks on the windows
2840 structures must be suspended before the control
2841 is passed to the application */
2842 iWndsLocks = WIN_SuspendWndsLock();
2843 funcRetval = func( (*ppWnd)->hwndSelf, lParam );
2844 WIN_RestoreWndsLock(iWndsLocks);
2846 if (!funcRetval) break;
2848 WIN_ReleaseWinArray(list);
2849 WIN_ReleaseDesktop();
2850 return TRUE;
2854 /**********************************************************************
2855 * EnumThreadWindows (USER32.190)
2857 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2859 TEB *teb = THREAD_IdToTEB(id);
2861 return (BOOL16)EnumTaskWindows16(teb->htask16, (WNDENUMPROC16)func, lParam);
2865 /**********************************************************************
2866 * WIN_EnumChildWindows
2868 * Helper function for EnumChildWindows().
2870 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC16 func,
2871 LPARAM lParam )
2873 WND **childList;
2874 BOOL16 ret = FALSE;
2876 for ( ; *ppWnd; ppWnd++)
2878 int iWndsLocks = 0;
2880 /* Make sure that the window still exists */
2881 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2882 /* Build children list first */
2883 childList = WIN_BuildWinArray( *ppWnd, BWA_SKIPOWNED, NULL );
2885 /* To avoid any deadlocks, all the locks on the windows
2886 structures must be suspended before the control
2887 is passed to the application */
2888 iWndsLocks = WIN_SuspendWndsLock();
2889 ret = func( (*ppWnd)->hwndSelf, lParam );
2890 WIN_RestoreWndsLock(iWndsLocks);
2892 if (childList)
2894 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2895 WIN_ReleaseWinArray(childList);
2897 if (!ret) return FALSE;
2899 return TRUE;
2903 /**********************************************************************
2904 * EnumChildWindows16 (USER.55)
2906 BOOL16 WINAPI EnumChildWindows16( HWND16 parent, WNDENUMPROC16 func,
2907 LPARAM lParam )
2909 WND **list, *pParent;
2911 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
2912 if (!(list = WIN_BuildWinArray( pParent, BWA_SKIPOWNED, NULL )))
2914 WIN_ReleaseWndPtr(pParent);
2915 return FALSE;
2917 WIN_EnumChildWindows( list, func, lParam );
2918 WIN_ReleaseWinArray(list);
2919 WIN_ReleaseWndPtr(pParent);
2920 return TRUE;
2924 /**********************************************************************
2925 * EnumChildWindows32 (USER32.178)
2927 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func,
2928 LPARAM lParam )
2930 return (BOOL)EnumChildWindows16( (HWND16)parent, (WNDENUMPROC16)func,
2931 lParam );
2935 /*******************************************************************
2936 * AnyPopup16 (USER.52)
2938 BOOL16 WINAPI AnyPopup16(void)
2940 return AnyPopup();
2944 /*******************************************************************
2945 * AnyPopup32 (USER32.4)
2947 BOOL WINAPI AnyPopup(void)
2949 WND *wndPtr = WIN_LockWndPtr(pWndDesktop->child);
2950 BOOL retvalue;
2952 while (wndPtr)
2954 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE))
2956 retvalue = TRUE;
2957 goto end;
2959 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2961 retvalue = FALSE;
2962 end:
2963 WIN_ReleaseWndPtr(wndPtr);
2964 return retvalue;
2968 /*******************************************************************
2969 * FlashWindow16 (USER.105)
2971 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
2973 return FlashWindow( hWnd, bInvert );
2977 /*******************************************************************
2978 * FlashWindow32 (USER32.202)
2980 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2982 WND *wndPtr = WIN_FindWndPtr(hWnd);
2984 TRACE_(win)("%04x\n", hWnd);
2986 if (!wndPtr) return FALSE;
2988 if (wndPtr->dwStyle & WS_MINIMIZE)
2990 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2992 HDC hDC = GetDC(hWnd);
2994 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2995 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2997 ReleaseDC( hWnd, hDC );
2998 wndPtr->flags |= WIN_NCACTIVATED;
3000 else
3002 PAINT_RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
3003 RDW_UPDATENOW | RDW_FRAME, 0 );
3004 wndPtr->flags &= ~WIN_NCACTIVATED;
3006 WIN_ReleaseWndPtr(wndPtr);
3007 return TRUE;
3009 else
3011 WPARAM16 wparam;
3012 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3013 else wparam = (hWnd == GetActiveWindow());
3015 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3016 WIN_ReleaseWndPtr(wndPtr);
3017 return wparam;
3022 /*******************************************************************
3023 * SetSysModalWindow16 (USER.188)
3025 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
3027 HWND hWndOldModal = hwndSysModal;
3028 hwndSysModal = hWnd;
3029 FIXME_(win)("EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
3030 return hWndOldModal;
3034 /*******************************************************************
3035 * GetSysModalWindow16 (USER.52)
3037 HWND16 WINAPI GetSysModalWindow16(void)
3039 return hwndSysModal;
3043 /*******************************************************************
3044 * GetWindowContextHelpId (USER32.303)
3046 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3048 DWORD retval;
3049 WND *wnd = WIN_FindWndPtr( hwnd );
3050 if (!wnd) return 0;
3051 retval = wnd->helpContext;
3052 WIN_ReleaseWndPtr(wnd);
3053 return retval;
3057 /*******************************************************************
3058 * SetWindowContextHelpId (USER32.515)
3060 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3062 WND *wnd = WIN_FindWndPtr( hwnd );
3063 if (!wnd) return FALSE;
3064 wnd->helpContext = id;
3065 WIN_ReleaseWndPtr(wnd);
3066 return TRUE;
3070 /*******************************************************************
3071 * DRAG_QueryUpdate
3073 * recursively find a child that contains spDragInfo->pt point
3074 * and send WM_QUERYDROPOBJECT
3076 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
3078 BOOL16 wParam,bResult = 0;
3079 POINT pt;
3080 LPDRAGINFO ptrDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN(spDragInfo);
3081 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
3082 RECT tempRect;
3084 if( !ptrQueryWnd || !ptrDragInfo )
3086 WIN_ReleaseWndPtr(ptrQueryWnd);
3087 return 0;
3090 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
3092 GetWindowRect(hQueryWnd,&tempRect);
3094 if( !PtInRect(&tempRect,pt) ||
3095 (ptrQueryWnd->dwStyle & WS_DISABLED) )
3097 WIN_ReleaseWndPtr(ptrQueryWnd);
3098 return 0;
3101 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
3103 tempRect = ptrQueryWnd->rectClient;
3104 if(ptrQueryWnd->dwStyle & WS_CHILD)
3105 MapWindowPoints( ptrQueryWnd->parent->hwndSelf, 0,
3106 (LPPOINT)&tempRect, 2 );
3108 if (PtInRect( &tempRect, pt))
3110 wParam = 0;
3112 for (ptrWnd = WIN_LockWndPtr(ptrQueryWnd->child); ptrWnd ;WIN_UpdateWndPtr(&ptrWnd,ptrWnd->next))
3114 if( ptrWnd->dwStyle & WS_VISIBLE )
3116 GetWindowRect( ptrWnd->hwndSelf, &tempRect );
3117 if (PtInRect( &tempRect, pt )) break;
3121 if(ptrWnd)
3123 TRACE_(msg)("hwnd = %04x, %d %d - %d %d\n",
3124 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
3125 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
3126 if( !(ptrWnd->dwStyle & WS_DISABLED) )
3127 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
3129 WIN_ReleaseWndPtr(ptrWnd);
3132 if(bResult)
3134 WIN_ReleaseWndPtr(ptrQueryWnd);
3135 return bResult;
3138 else wParam = 1;
3140 else wParam = 1;
3142 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
3144 ptrDragInfo->hScope = hQueryWnd;
3146 bResult = ( bNoSend )
3147 ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
3148 : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
3149 (WPARAM16)wParam ,(LPARAM) spDragInfo );
3150 if( !bResult )
3151 CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3153 WIN_ReleaseWndPtr(ptrQueryWnd);
3154 return bResult;
3158 /*******************************************************************
3159 * DragDetect (USER.465)
3161 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
3163 POINT pt32;
3164 CONV_POINT16TO32( &pt, &pt32 );
3165 return DragDetect( hWnd, pt32 );
3168 /*******************************************************************
3169 * DragDetect32 (USER32.151)
3171 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3173 MSG16 msg;
3174 RECT16 rect;
3176 rect.left = pt.x - wDragWidth;
3177 rect.right = pt.x + wDragWidth;
3179 rect.top = pt.y - wDragHeight;
3180 rect.bottom = pt.y + wDragHeight;
3182 SetCapture(hWnd);
3184 while(1)
3186 while(PeekMessage16(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3188 if( msg.message == WM_LBUTTONUP )
3190 ReleaseCapture();
3191 return 0;
3193 if( msg.message == WM_MOUSEMOVE )
3195 if( !PtInRect16( &rect, MAKEPOINT16(msg.lParam) ) )
3197 ReleaseCapture();
3198 return 1;
3202 WaitMessage();
3204 return 0;
3207 /******************************************************************************
3208 * DragObject16 (USER.464)
3210 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3211 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3213 MSG16 msg;
3214 LPDRAGINFO lpDragInfo;
3215 SEGPTR spDragInfo;
3216 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
3217 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO));
3218 WND *wndPtr = WIN_FindWndPtr(hWnd);
3219 HCURSOR16 hCurrentCursor = 0;
3220 HWND16 hCurrentWnd = 0;
3222 lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo);
3223 spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
3225 if( !lpDragInfo || !spDragInfo )
3227 WIN_ReleaseWndPtr(wndPtr);
3228 return 0L;
3231 hBummer = LoadCursor16(0, IDC_BUMMER16);
3233 if( !hBummer || !wndPtr )
3235 GlobalFree16(hDragInfo);
3236 WIN_ReleaseWndPtr(wndPtr);
3237 return 0L;
3240 if(hCursor)
3242 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
3244 GlobalFree16(hDragInfo);
3245 WIN_ReleaseWndPtr(wndPtr);
3246 return 0L;
3249 if( hDragCursor == hCursor ) hDragCursor = 0;
3250 else hCursor = hDragCursor;
3252 hOldCursor = SetCursor(hDragCursor);
3255 lpDragInfo->hWnd = hWnd;
3256 lpDragInfo->hScope = 0;
3257 lpDragInfo->wFlags = wObj;
3258 lpDragInfo->hList = szList; /* near pointer! */
3259 lpDragInfo->hOfStruct = hOfStruct;
3260 lpDragInfo->l = 0L;
3262 SetCapture(hWnd);
3263 ShowCursor( TRUE );
3267 do{ WaitMessage(); }
3268 while( !PeekMessage16(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) );
3270 *(lpDragInfo+1) = *lpDragInfo;
3272 lpDragInfo->pt = msg.pt;
3274 /* update DRAGINFO struct */
3275 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
3277 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
3278 hCurrentCursor = hCursor;
3279 else
3281 hCurrentCursor = hBummer;
3282 lpDragInfo->hScope = 0;
3284 if( hCurrentCursor )
3285 SetCursor(hCurrentCursor);
3287 /* send WM_DRAGLOOP */
3288 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3289 (LPARAM) spDragInfo );
3290 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3291 if( hCurrentWnd != lpDragInfo->hScope )
3293 if( hCurrentWnd )
3294 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3295 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO),
3296 HIWORD(spDragInfo)) );
3297 hCurrentWnd = lpDragInfo->hScope;
3298 if( hCurrentWnd )
3299 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3301 else
3302 if( hCurrentWnd )
3303 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3305 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3307 ReleaseCapture();
3308 ShowCursor( FALSE );
3310 if( hCursor )
3312 SetCursor( hOldCursor );
3313 if (hDragCursor) DestroyCursor( hDragCursor );
3316 if( hCurrentCursor != hBummer )
3317 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3318 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3319 else
3320 msg.lParam = 0;
3321 GlobalFree16(hDragInfo);
3322 WIN_ReleaseWndPtr(wndPtr);
3324 return (DWORD)(msg.lParam);