2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
10 #include "wine/winbase16.h"
11 #include "wine/winuser16.h"
12 #include "wine/unicode.h"
19 #include "cursoricon.h"
25 #include "stackframe.h"
26 #include "debugtools.h"
28 DEFAULT_DEBUG_CHANNEL(win);
29 DECLARE_DEBUG_CHANNEL(msg);
31 /**********************************************************************/
33 WND_DRIVER *WND_Driver = NULL;
36 static WND *pWndDesktop = NULL;
38 static HWND hwndSysModal = 0;
40 static WORD wDragWidth = 4;
41 static WORD wDragHeight= 3;
44 static SYSLEVEL WIN_SysLevel = { CRITICAL_SECTION_INIT, 2 };
46 /***********************************************************************
49 * Locks access to all WND structures for thread safeness
51 void WIN_LockWnds( void )
53 _EnterSysLevel( &WIN_SysLevel );
56 /***********************************************************************
59 * Unlocks access to all WND structures
61 void WIN_UnlockWnds( void )
63 _LeaveSysLevel( &WIN_SysLevel );
66 /***********************************************************************
69 * Suspend the lock on WND structures.
70 * Returns the number of locks suspended
72 int WIN_SuspendWndsLock( void )
74 int isuspendedLocks = _ConfirmSysLevel( &WIN_SysLevel );
75 int count = isuspendedLocks;
78 _LeaveSysLevel( &WIN_SysLevel );
80 return isuspendedLocks;
83 /***********************************************************************
86 * Restore the suspended locks on WND structures
88 void WIN_RestoreWndsLock( int ipreviousLocks )
90 while ( ipreviousLocks-- > 0 )
91 _EnterSysLevel( &WIN_SysLevel );
94 /***********************************************************************
97 * Return a pointer to the WND structure corresponding to a HWND.
99 WND * WIN_FindWndPtr( HWND hwnd )
103 if (!hwnd || HIWORD(hwnd)) goto error2;
104 ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
105 /* Lock all WND structures for thread safeness*/
107 /*and increment destruction monitoring*/
110 if (ptr->dwMagic != WND_MAGIC) goto error;
111 if (ptr->hwndSelf != hwnd)
113 ERR("Can't happen: hwnd %04x self pointer is %04x\n",hwnd, ptr->hwndSelf );
116 /* returns a locked pointer */
119 /* Unlock all WND structures for thread safeness*/
121 /* and decrement destruction monitoring value */
126 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
130 /***********************************************************************
133 * Use in case the wnd ptr is not initialized with WIN_FindWndPtr
135 * Returns the locked initialisation pointer
137 WND *WIN_LockWndPtr(WND *initWndPtr)
139 if(!initWndPtr) return 0;
141 /* Lock all WND structures for thread safeness*/
143 /*and increment destruction monitoring*/
144 initWndPtr->irefCount++;
150 /***********************************************************************
153 * Release the pointer to the WND structure.
155 void WIN_ReleaseWndPtr(WND *wndPtr)
159 /*Decrement destruction monitoring value*/
161 /* Check if it's time to release the memory*/
162 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
165 USER_HEAP_FREE( wndPtr->hwndSelf);
166 wndPtr->hwndSelf = 0;
168 else if(wndPtr->irefCount < 0)
170 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
171 ERR("forgot a Lock on %p somewhere\n",wndPtr);
173 /*unlock all WND structures for thread safeness*/
177 /***********************************************************************
180 * Updates the value of oldPtr to newPtr.
182 void WIN_UpdateWndPtr(WND **oldPtr, WND *newPtr)
186 tmpWnd = WIN_LockWndPtr(newPtr);
187 WIN_ReleaseWndPtr(*oldPtr);
192 /***********************************************************************
195 * Dump the content of a window structure to stderr.
197 void WIN_DumpWindow( HWND hwnd )
203 if (!(ptr = WIN_FindWndPtr( hwnd )))
205 WARN("%04x is not a window handle\n", hwnd );
209 if (!GetClassNameA( hwnd, className, sizeof(className ) ))
210 strcpy( className, "#NULL#" );
212 TRACE("Window %04x (%p):\n", hwnd, ptr );
213 DPRINTF( "next=%p child=%p parent=%p owner=%p class=%p '%s'\n"
214 "inst=%04x taskQ=%04x updRgn=%04x active=%04x dce=%p idmenu=%08x\n"
215 "style=%08lx exstyle=%08lx wndproc=%08x text='%s'\n"
216 "client=%d,%d-%d,%d window=%d,%d-%d,%d"
217 "sysmenu=%04x flags=%04x props=%p vscroll=%p hscroll=%p\n",
218 ptr->next, ptr->child, ptr->parent, ptr->owner,
219 ptr->class, className, ptr->hInstance, ptr->hmemTaskQ,
220 ptr->hrgnUpdate, ptr->hwndLastActive, ptr->dce, ptr->wIDmenu,
221 ptr->dwStyle, ptr->dwExStyle, (UINT)ptr->winproc,
222 ptr->text ? debugstr_w(ptr->text) : "",
223 ptr->rectClient.left, ptr->rectClient.top, ptr->rectClient.right,
224 ptr->rectClient.bottom, ptr->rectWindow.left, ptr->rectWindow.top,
225 ptr->rectWindow.right, ptr->rectWindow.bottom, ptr->hSysMenu,
226 ptr->flags, ptr->pProp, ptr->pVScroll, ptr->pHScroll );
230 DPRINTF( "extra bytes:" );
231 for (i = 0; i < ptr->cbWndExtra; i++)
232 DPRINTF( " %02x", *((BYTE*)ptr->wExtra+i) );
236 WIN_ReleaseWndPtr(ptr);
240 /***********************************************************************
243 * Walk the windows tree and print each window on stderr.
245 void WIN_WalkWindows( HWND hwnd, int indent )
250 ptr = hwnd ? WIN_FindWndPtr( hwnd ) : WIN_GetDesktop();
254 WARN("Invalid window handle %04x\n", hwnd );
258 if (!indent) /* first time around */
259 DPRINTF( "%-16.16s %-8.8s %-6.6s %-17.17s %-8.8s %s\n",
260 "hwnd", " wndPtr", "queue", "Class Name", " Style", " WndProc"
265 DPRINTF( "%*s%04x%*s", indent, "", ptr->hwndSelf, 13-indent,"");
267 GetClassNameA( ptr->hwndSelf, className, sizeof(className) );
268 DPRINTF( "%08lx %-6.4x %-17.17s %08x %08x %.14s\n",
269 (DWORD)ptr, ptr->hmemTaskQ, className,
270 (UINT)ptr->dwStyle, (UINT)ptr->winproc,
271 ptr->text ? debugstr_w(ptr->text) : "<null>");
273 if (ptr->child) WIN_WalkWindows( ptr->child->hwndSelf, indent+1 );
274 WIN_UpdateWndPtr(&ptr,ptr->next);
278 /***********************************************************************
281 * Remove a window from the siblings linked list.
283 BOOL WIN_UnlinkWindow( HWND hwnd )
285 WND *wndPtr, **ppWnd;
288 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
289 else if(!wndPtr->parent)
291 WIN_ReleaseWndPtr(wndPtr);
295 ppWnd = &wndPtr->parent->child;
296 while (*ppWnd && *ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
299 *ppWnd = wndPtr->next;
302 WIN_ReleaseWndPtr(wndPtr);
307 /***********************************************************************
310 * Insert a window into the siblings linked list.
311 * The window is inserted after the specified window, which can also
312 * be specified as HWND_TOP or HWND_BOTTOM.
314 BOOL WIN_LinkWindow( HWND hwnd, HWND hwndInsertAfter )
316 WND *wndPtr, **ppWnd;
318 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
319 else if(!wndPtr->parent)
321 WIN_ReleaseWndPtr(wndPtr);
324 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
326 ppWnd = &wndPtr->parent->child; /* Point to first sibling hwnd */
327 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
328 while (*ppWnd) ppWnd = &(*ppWnd)->next;
330 else /* Normal case */
332 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
335 WIN_ReleaseWndPtr(wndPtr);
338 ppWnd = &afterPtr->next;
339 WIN_ReleaseWndPtr(afterPtr);
341 wndPtr->next = *ppWnd;
343 WIN_ReleaseWndPtr(wndPtr);
348 /***********************************************************************
349 * WIN_FindWinToRepaint
351 * Find a window that needs repaint.
353 HWND WIN_FindWinToRepaint( HWND hwnd, HQUEUE16 hQueue )
358 /* Note: the desktop window never gets WM_PAINT messages
359 * The real reason why is because Windows DesktopWndProc
360 * does ValidateRgn inside WM_ERASEBKGND handler.
362 if (hwnd == GetDesktopWindow()) hwnd = 0;
364 pWnd = hwnd ? WIN_FindWndPtr(hwnd) : WIN_LockWndPtr(pWndDesktop->child);
366 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
368 if (!(pWnd->dwStyle & WS_VISIBLE))
370 TRACE("skipping window %04x\n",
373 else if ((pWnd->hmemTaskQ == hQueue) &&
374 (pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT)))
377 else if (pWnd->child )
378 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf, hQueue )) )
380 WIN_ReleaseWndPtr(pWnd);
391 hwndRet = pWnd->hwndSelf;
393 /* look among siblings if we got a transparent window */
394 while (pWnd && ((pWnd->dwExStyle & WS_EX_TRANSPARENT) ||
395 !(pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))))
397 WIN_UpdateWndPtr(&pWnd,pWnd->next);
401 hwndRet = pWnd->hwndSelf;
402 WIN_ReleaseWndPtr(pWnd);
404 TRACE("found %04x\n",hwndRet);
409 /***********************************************************************
412 * Destroy storage associated to a window. "Internals" p.358
413 * returns a locked wndPtr->next
415 static WND* WIN_DestroyWindow( WND* wndPtr )
417 HWND hwnd = wndPtr->hwndSelf;
420 TRACE("%04x\n", wndPtr->hwndSelf );
422 /* free child windows */
423 WIN_LockWndPtr(wndPtr->child);
424 while ((pWnd = wndPtr->child))
426 wndPtr->child = WIN_DestroyWindow( pWnd );
427 WIN_ReleaseWndPtr(pWnd);
431 * Clear the update region to make sure no WM_PAINT messages will be
432 * generated for this window while processing the WM_NCDESTROY.
434 if ((wndPtr->hrgnUpdate) || (wndPtr->flags & WIN_INTERNAL_PAINT))
436 if (wndPtr->hrgnUpdate > 1)
437 DeleteObject( wndPtr->hrgnUpdate );
439 QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
441 wndPtr->hrgnUpdate = 0;
445 * Send the WM_NCDESTROY to the window being destroyed.
447 SendMessageA( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
449 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
451 WINPOS_CheckInternalPos( wndPtr );
452 if( hwnd == GetCapture()) ReleaseCapture();
454 /* free resources associated with the window */
456 TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
457 PROPERTY_RemoveWindowProps( wndPtr );
459 /* toss stale messages from the queue */
461 if( wndPtr->hmemTaskQ )
463 BOOL bPostQuit = FALSE;
464 WPARAM wQuitParam = 0;
465 MESSAGEQUEUE* msgQ = (MESSAGEQUEUE*) QUEUE_Lock(wndPtr->hmemTaskQ);
468 while( (qmsg = QUEUE_FindMsg(msgQ, hwnd, 0, 0)) != 0 )
470 if( qmsg->msg.message == WM_QUIT )
473 wQuitParam = qmsg->msg.wParam;
475 QUEUE_RemoveMsg(msgQ, qmsg);
480 /* repost WM_QUIT to make sure this app exits its message loop */
481 if( bPostQuit ) PostQuitMessage(wQuitParam);
482 wndPtr->hmemTaskQ = 0;
485 if (!(wndPtr->dwStyle & WS_CHILD))
488 DestroyMenu( wndPtr->wIDmenu );
491 if (wndPtr->hSysMenu)
493 DestroyMenu( wndPtr->hSysMenu );
494 wndPtr->hSysMenu = 0;
496 USER_Driver.pDestroyWindow( wndPtr->hwndSelf );
497 DCE_FreeWindowDCE( wndPtr ); /* Always do this to catch orphaned DCs */
498 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
499 CLASS_RemoveWindow( wndPtr->class );
500 wndPtr->class = NULL;
501 wndPtr->dwMagic = 0; /* Mark it as invalid */
503 WIN_UpdateWndPtr(&pWnd,wndPtr->next);
508 /***********************************************************************
509 * WIN_ResetQueueWindows
511 * Reset the queue of all the children of a given window.
512 * Return TRUE if something was done.
514 BOOL WIN_ResetQueueWindows( WND* wnd, HQUEUE16 hQueue, HQUEUE16 hNew )
518 if (hNew) /* Set a new queue */
520 for (wnd = WIN_LockWndPtr(wnd->child); (wnd);WIN_UpdateWndPtr(&wnd,wnd->next))
522 if (wnd->hmemTaskQ == hQueue)
524 wnd->hmemTaskQ = hNew;
529 ret |= WIN_ResetQueueWindows( wnd, hQueue, hNew );
533 else /* Queue is being destroyed */
537 WND *tmp = WIN_LockWndPtr(wnd->child);
542 if (tmp->hmemTaskQ == hQueue)
544 DestroyWindow( tmp->hwndSelf );
548 tmp2 = WIN_LockWndPtr(tmp->child);
549 if (tmp2 && WIN_ResetQueueWindows(tmp2,hQueue,0))
553 WIN_UpdateWndPtr(&tmp,tmp->next);
555 WIN_ReleaseWndPtr(tmp2);
557 WIN_ReleaseWndPtr(tmp);
564 /***********************************************************************
565 * WIN_CreateDesktopWindow
567 * Create the desktop window.
569 BOOL WIN_CreateDesktopWindow(void)
571 struct tagCLASS *class;
578 TRACE("Creating desktop window\n");
581 if (!WINPOS_CreateInternalPosAtom() ||
582 !(class = CLASS_AddWindow( (ATOM)LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W,
583 &wndExtra, &winproc, &clsStyle, &dce )))
586 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND) + wndExtra );
587 if (!hwndDesktop) return FALSE;
588 pWndDesktop = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
590 pWndDesktop->pDriver = WND_Driver;
591 pWndDesktop->next = NULL;
592 pWndDesktop->child = NULL;
593 pWndDesktop->parent = NULL;
594 pWndDesktop->owner = NULL;
595 pWndDesktop->class = class;
596 pWndDesktop->dwMagic = WND_MAGIC;
597 pWndDesktop->hwndSelf = hwndDesktop;
598 pWndDesktop->hInstance = 0;
599 pWndDesktop->rectWindow.left = 0;
600 pWndDesktop->rectWindow.top = 0;
601 pWndDesktop->rectWindow.right = GetSystemMetrics(SM_CXSCREEN);
602 pWndDesktop->rectWindow.bottom = GetSystemMetrics(SM_CYSCREEN);
603 pWndDesktop->rectClient = pWndDesktop->rectWindow;
604 pWndDesktop->text = NULL;
605 pWndDesktop->hmemTaskQ = 0;
606 pWndDesktop->hrgnUpdate = 0;
607 pWndDesktop->hwndLastActive = hwndDesktop;
608 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
610 pWndDesktop->dwExStyle = 0;
611 pWndDesktop->clsStyle = clsStyle;
612 pWndDesktop->dce = NULL;
613 pWndDesktop->pVScroll = NULL;
614 pWndDesktop->pHScroll = NULL;
615 pWndDesktop->pProp = NULL;
616 pWndDesktop->wIDmenu = 0;
617 pWndDesktop->helpContext = 0;
618 pWndDesktop->flags = 0;
619 pWndDesktop->hSysMenu = 0;
620 pWndDesktop->userdata = 0;
621 pWndDesktop->winproc = winproc;
622 pWndDesktop->cbWndExtra = wndExtra;
623 pWndDesktop->irefCount = 0;
625 if (!USER_Driver.pCreateWindow( hwndDesktop )) return FALSE;
627 SendMessageW( hwndDesktop, WM_NCCREATE, 0, 0 );
628 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
633 /***********************************************************************
636 * Fix the coordinates - Helper for WIN_CreateWindowEx.
637 * returns default show mode in sw.
638 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
640 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
642 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
643 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
645 if (cs->style & (WS_CHILD | WS_POPUP))
647 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16) cs->x = cs->y = 0;
648 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16) cs->cx = cs->cy = 0;
650 else /* overlapped window */
654 GetStartupInfoA( &info );
656 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
658 /* Never believe Microsoft's documentation... CreateWindowEx doc says
659 * that if an overlapped window is created with WS_VISIBLE style bit
660 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
661 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
664 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
665 * 2) it does not ignore the y parameter as the docs claim; instead, it
666 * uses it as second parameter to ShowWindow() unless y is either
667 * CW_USEDEFAULT or CW_USEDEFAULT16.
669 * The fact that we didn't do 2) caused bogus windows pop up when wine
670 * was running apps that were using this obscure feature. Example -
671 * calc.exe that comes with Win98 (only Win98, it's different from
672 * the one that comes with Win95 and NT)
674 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
675 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
676 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
679 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
681 if (info.dwFlags & STARTF_USESIZE)
683 cs->cx = info.dwXSize;
684 cs->cy = info.dwYSize;
686 else /* if no other hint from the app, pick 3/4 of the screen real estate */
689 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
690 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
691 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
698 /***********************************************************************
701 * Implementation of CreateWindowEx().
703 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
704 WINDOWPROCTYPE type )
707 struct tagCLASS *classPtr;
710 HWND16 hwnd, hwndLinkAfter;
711 POINT maxSize, maxPos, minTrack, maxTrack;
716 LRESULT CALLBACK (*localSend32)(HWND, UINT, WPARAM, LPARAM);
718 TRACE("%s %s %08lx %08lx %d,%d %dx%d %04x %04x %08x %p\n",
719 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
720 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
721 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
722 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
724 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
725 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
727 /* Find the parent window */
731 /* Make sure parent is valid */
732 if (!IsWindow( cs->hwndParent ))
734 WARN("Bad parent %04x\n", cs->hwndParent );
737 } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
738 WARN("No parent for child window\n" );
739 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
742 /* Find the window class */
743 if (!(classPtr = CLASS_AddWindow( classAtom, cs->hInstance, type,
744 &wndExtra, &winproc, &clsStyle, &dce )))
746 WARN("Bad class '%s'\n", cs->lpszClass );
750 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
752 /* Create the window structure */
754 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + wndExtra - sizeof(wndPtr->wExtra) )))
756 TRACE("out of memory\n" );
760 /* Fill the window structure */
762 wndPtr = WIN_LockWndPtr((WND *) USER_HEAP_LIN_ADDR( hwnd ));
764 wndPtr->child = NULL;
766 if ((cs->style & WS_CHILD) && cs->hwndParent)
768 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
769 wndPtr->owner = NULL;
770 WIN_ReleaseWndPtr(wndPtr->parent);
774 wndPtr->parent = pWndDesktop;
775 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
776 wndPtr->owner = NULL;
779 WND *tmpWnd = WIN_FindWndPtr(cs->hwndParent);
780 wndPtr->owner = WIN_GetTopParentPtr(tmpWnd);
781 WIN_ReleaseWndPtr(wndPtr->owner);
782 WIN_ReleaseWndPtr(tmpWnd);
787 wndPtr->pDriver = wndPtr->parent->pDriver;
789 wndPtr->class = classPtr;
790 wndPtr->winproc = winproc;
791 wndPtr->dwMagic = WND_MAGIC;
792 wndPtr->hwndSelf = hwnd;
793 wndPtr->hInstance = cs->hInstance;
795 wndPtr->hmemTaskQ = GetFastQueue16();
796 wndPtr->hrgnUpdate = 0;
798 wndPtr->hwndLastActive = hwnd;
799 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
800 wndPtr->dwExStyle = cs->dwExStyle;
801 wndPtr->clsStyle = clsStyle;
803 wndPtr->helpContext = 0;
804 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
805 wndPtr->pVScroll = NULL;
806 wndPtr->pHScroll = NULL;
807 wndPtr->pProp = NULL;
808 wndPtr->userdata = 0;
809 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
810 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
811 wndPtr->cbWndExtra = wndExtra;
812 wndPtr->irefCount = 1;
814 if (wndExtra) memset( wndPtr->wExtra, 0, wndExtra);
816 /* Call the WH_CBT hook */
818 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
819 ? HWND_BOTTOM : HWND_TOP;
821 if (HOOK_IsHooked( WH_CBT ))
827 cbtc.hwndInsertAfter = hwndLinkAfter;
828 ret = (type == WIN_PROC_32W) ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc)
829 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc);
832 TRACE("CBT-hook returned 0\n");
833 USER_HEAP_FREE( hwnd );
834 CLASS_RemoveWindow( classPtr );
840 /* Correct the window style */
842 if (!(cs->style & WS_CHILD))
844 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
845 if (!(cs->style & WS_POPUP))
847 wndPtr->dwStyle |= WS_CAPTION;
848 wndPtr->flags |= WIN_NEED_SIZE;
852 /* Get class or window DC if needed */
854 if (clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
855 else if (clsStyle & CS_CLASSDC) wndPtr->dce = dce;
856 else wndPtr->dce = NULL;
858 /* Initialize the dimensions before sending WM_GETMINMAXINFO */
860 wndPtr->rectWindow.left = cs->x;
861 wndPtr->rectWindow.top = cs->y;
862 wndPtr->rectWindow.right = cs->x + cs->cx;
863 wndPtr->rectWindow.bottom = cs->y + cs->cy;
864 wndPtr->rectClient = wndPtr->rectWindow;
866 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
868 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
870 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack);
871 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
872 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
873 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
874 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
877 if (cs->cx < 0) cs->cx = 0;
878 if (cs->cy < 0) cs->cy = 0;
880 wndPtr->rectWindow.left = cs->x;
881 wndPtr->rectWindow.top = cs->y;
882 wndPtr->rectWindow.right = cs->x + cs->cx;
883 wndPtr->rectWindow.bottom = cs->y + cs->cy;
884 wndPtr->rectClient = wndPtr->rectWindow;
886 if (!USER_Driver.pCreateWindow(wndPtr->hwndSelf))
892 /* Set the window menu */
894 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
896 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
899 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
902 if (HIWORD(cs->hInstance))
903 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
905 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
907 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
911 else wndPtr->wIDmenu = (UINT)cs->hMenu;
913 /* Send the WM_CREATE message
914 * Perhaps we shouldn't allow width/height changes as well.
915 * See p327 in "Internals".
918 maxPos.x = wndPtr->rectWindow.left; maxPos.y = wndPtr->rectWindow.top;
920 localSend32 = (type == WIN_PROC_32W) ? SendMessageW : SendMessageA;
921 if( (*localSend32)( hwnd, WM_NCCREATE, 0, (LPARAM)cs) )
923 /* Insert the window in the linked list */
925 WIN_LinkWindow( hwnd, hwndLinkAfter );
927 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
928 NULL, NULL, 0, &wndPtr->rectClient );
929 OffsetRect(&wndPtr->rectWindow, maxPos.x - wndPtr->rectWindow.left,
930 maxPos.y - wndPtr->rectWindow.top);
931 if( ((*localSend32)( hwnd, WM_CREATE, 0, (LPARAM)cs )) != -1 )
933 /* Send the size messages */
935 if (!(wndPtr->flags & WIN_NEED_SIZE))
938 if (((wndPtr->rectClient.right-wndPtr->rectClient.left) <0)
939 ||((wndPtr->rectClient.bottom-wndPtr->rectClient.top)<0))
940 WARN("sending bogus WM_SIZE message 0x%08lx\n",
941 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
942 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
943 (*localSend32)( hwnd, WM_SIZE, SIZE_RESTORED,
944 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
945 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
946 (*localSend32)( hwnd, WM_MOVE, 0,
947 MAKELONG( wndPtr->rectClient.left,
948 wndPtr->rectClient.top ) );
951 /* Show the window, maximizing or minimizing if needed */
953 if (wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE))
956 UINT16 swFlag = (wndPtr->dwStyle & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
957 wndPtr->dwStyle &= ~(WS_MAXIMIZE | WS_MINIMIZE);
958 WINPOS_MinMaximize( wndPtr, swFlag, &newPos );
959 swFlag = ((wndPtr->dwStyle & WS_CHILD) || GetActiveWindow())
960 ? SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED
961 : SWP_NOZORDER | SWP_FRAMECHANGED;
962 SetWindowPos( hwnd, 0, newPos.left, newPos.top,
963 newPos.right, newPos.bottom, swFlag );
966 if( (wndPtr->dwStyle & WS_CHILD) && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
968 /* Notify the parent window only */
970 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
971 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
972 if( !IsWindow(hwnd) )
979 if (cs->style & WS_VISIBLE) ShowWindow( hwnd, sw );
981 /* Call WH_SHELL hook */
983 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
984 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
986 TRACE("created window %04x\n", hwnd);
990 WIN_UnlinkWindow( hwnd );
993 /* Abort window creation */
995 WARN("aborted by WM_xxCREATE!\n");
996 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
997 CLASS_RemoveWindow( classPtr );
1000 WIN_ReleaseWndPtr(wndPtr);
1006 /***********************************************************************
1007 * CreateWindow (USER.41)
1009 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1010 DWORD style, INT16 x, INT16 y, INT16 width,
1011 INT16 height, HWND16 parent, HMENU16 menu,
1012 HINSTANCE16 instance, LPVOID data )
1014 return CreateWindowEx16( 0, className, windowName, style,
1015 x, y, width, height, parent, menu, instance, data );
1019 /***********************************************************************
1020 * CreateWindowEx (USER.452)
1022 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1023 LPCSTR windowName, DWORD style, INT16 x,
1024 INT16 y, INT16 width, INT16 height,
1025 HWND16 parent, HMENU16 menu,
1026 HINSTANCE16 instance, LPVOID data )
1032 /* Find the class atom */
1034 if (HIWORD(className))
1036 if (!(classAtom = GlobalFindAtomA( className )))
1038 ERR( "bad class name %s\n", debugres_a(className) );
1044 classAtom = LOWORD(className);
1045 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1047 ERR( "bad atom %x\n", classAtom);
1053 /* Fix the coordinates */
1055 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1056 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1057 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1058 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1060 /* Create the window */
1062 cs.lpCreateParams = data;
1063 cs.hInstance = (HINSTANCE)instance;
1064 cs.hMenu = (HMENU)menu;
1065 cs.hwndParent = (HWND)parent;
1067 cs.lpszName = windowName;
1068 cs.lpszClass = className;
1069 cs.dwExStyle = exStyle;
1071 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 );
1075 /***********************************************************************
1076 * CreateWindowExA (USER32.@)
1078 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1079 LPCSTR windowName, DWORD style, INT x,
1080 INT y, INT width, INT height,
1081 HWND parent, HMENU menu,
1082 HINSTANCE instance, LPVOID data )
1089 instance=GetModuleHandleA(NULL);
1091 if(exStyle & WS_EX_MDICHILD)
1092 return CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1094 /* Find the class atom */
1096 if (HIWORD(className))
1098 if (!(classAtom = GlobalFindAtomA( className )))
1100 ERR( "bad class name %s\n", debugres_a(className) );
1106 classAtom = LOWORD(className);
1107 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1109 ERR( "bad atom %x\n", classAtom);
1115 /* Create the window */
1117 cs.lpCreateParams = data;
1118 cs.hInstance = instance;
1120 cs.hwndParent = parent;
1126 cs.lpszName = windowName;
1127 cs.lpszClass = className;
1128 cs.dwExStyle = exStyle;
1130 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1134 /***********************************************************************
1135 * CreateWindowExW (USER32.@)
1137 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1138 LPCWSTR windowName, DWORD style, INT x,
1139 INT y, INT width, INT height,
1140 HWND parent, HMENU menu,
1141 HINSTANCE instance, LPVOID data )
1148 instance=GetModuleHandleA(NULL);
1150 if(exStyle & WS_EX_MDICHILD)
1151 return CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1153 /* Find the class atom */
1155 if (HIWORD(className))
1157 if (!(classAtom = GlobalFindAtomW( className )))
1159 ERR( "bad class name %s\n", debugres_w(className) );
1165 classAtom = LOWORD(className);
1166 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1168 ERR( "bad atom %x\n", classAtom);
1174 /* Create the window */
1176 cs.lpCreateParams = data;
1177 cs.hInstance = instance;
1179 cs.hwndParent = parent;
1185 cs.lpszName = windowName;
1186 cs.lpszClass = className;
1187 cs.dwExStyle = exStyle;
1189 /* Note: we rely on the fact that CREATESTRUCTA and */
1190 /* CREATESTRUCTW have the same layout. */
1191 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1194 /***********************************************************************
1195 * WIN_SendDestroyMsg
1197 static void WIN_SendDestroyMsg( WND* pWnd )
1199 if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret();
1200 USER_Driver.pResetSelectionOwner( pWnd, TRUE );
1203 * Send the WM_DESTROY to the window.
1205 SendMessageA( pWnd->hwndSelf, WM_DESTROY, 0, 0);
1208 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1209 * make sure that the window still exists when we come back.
1211 if (IsWindow(pWnd->hwndSelf))
1213 HWND* pWndArray = NULL;
1218 * Now, if the window has kids, we have to send WM_DESTROY messages
1219 * recursively to it's kids. It seems that those calls can also
1220 * trigger re-entrant calls to DestroyWindow for the kids so we must
1221 * protect against corruption of the list of siblings. We first build
1222 * a list of HWNDs representing all the kids.
1224 pChild = WIN_LockWndPtr(pWnd->child);
1228 WIN_UpdateWndPtr(&pChild,pChild->next);
1232 * If there are no kids, we're done.
1237 pWndArray = HeapAlloc(GetProcessHeap(), 0, nKidCount*sizeof(HWND));
1242 if (pWndArray==NULL)
1246 * Now, enumerate all the kids in a list, since we wait to make the SendMessage
1247 * call, our linked list of siblings should be safe.
1250 pChild = WIN_LockWndPtr(pWnd->child);
1253 pWndArray[nKidCount] = pChild->hwndSelf;
1255 WIN_UpdateWndPtr(&pChild,pChild->next);
1259 * Now that we have a list, go through that list again and send the destroy
1260 * message to those windows. We are using the HWND to retrieve the
1261 * WND pointer so we are effectively checking that all the kid windows are
1262 * still valid before sending the message.
1266 pChild = WIN_FindWndPtr(pWndArray[--nKidCount]);
1270 WIN_SendDestroyMsg( pChild );
1271 WIN_ReleaseWndPtr(pChild);
1278 HeapFree(GetProcessHeap(), 0, pWndArray);
1281 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1285 /***********************************************************************
1286 * DestroyWindow (USER.53)
1288 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
1290 return DestroyWindow(hwnd);
1294 /***********************************************************************
1295 * DestroyWindow (USER32.@)
1297 BOOL WINAPI DestroyWindow( HWND hwnd )
1302 BOOL bFocusSet = FALSE;
1304 TRACE("(%04x)\n", hwnd);
1306 /* Initialization */
1308 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1309 if (wndPtr == pWndDesktop)
1311 retvalue = FALSE; /* Can't destroy desktop */
1315 /* Look whether the focus is within the tree of windows we will
1319 while (h && (GetWindowLongA(h,GWL_STYLE) & WS_CHILD))
1323 SetFocus(GetParent(h));
1329 /* If the focus is on the window we will destroy and it has no parent,
1330 * set the focus to 0.
1332 if (! bFocusSet && (h == hwnd))
1334 if (!(GetWindowLongA(h,GWL_STYLE) & WS_CHILD))
1340 if( HOOK_CallHooksA( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
1346 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1348 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
1349 /* FIXME: clean up palette - see "Internals" p.352 */
1352 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
1353 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
1355 /* Notify the parent window only */
1356 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
1357 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
1358 if( !IsWindow(hwnd) )
1365 USER_Driver.pResetSelectionOwner( wndPtr, FALSE ); /* before the window is unmapped */
1367 /* Hide the window */
1369 if (wndPtr->dwStyle & WS_VISIBLE)
1371 ShowWindow( hwnd, SW_HIDE );
1372 if (!IsWindow(hwnd))
1379 /* Recursively destroy owned windows */
1381 if( !(wndPtr->dwStyle & WS_CHILD) )
1385 WND *siblingPtr = WIN_LockWndPtr(wndPtr->parent->child); /* First sibling */
1388 if (siblingPtr->owner == wndPtr)
1390 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1393 siblingPtr->owner = NULL;
1395 WIN_UpdateWndPtr(&siblingPtr,siblingPtr->next);
1399 DestroyWindow( siblingPtr->hwndSelf );
1400 WIN_ReleaseWndPtr(siblingPtr);
1405 WINPOS_ActivateOtherWindow(wndPtr);
1407 if( wndPtr->owner &&
1408 wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1409 wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1412 /* Send destroy messages */
1414 WIN_SendDestroyMsg( wndPtr );
1415 if (!IsWindow(hwnd))
1421 /* Unlink now so we won't bother with the children later on */
1423 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1425 /* Destroy the window storage */
1427 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1430 WIN_ReleaseWndPtr(wndPtr);
1435 /***********************************************************************
1436 * CloseWindow (USER.43)
1438 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1440 return CloseWindow( hwnd );
1444 /***********************************************************************
1445 * CloseWindow (USER32.@)
1447 BOOL WINAPI CloseWindow( HWND hwnd )
1449 WND * wndPtr = WIN_FindWndPtr( hwnd );
1452 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD))
1457 ShowWindow( hwnd, SW_MINIMIZE );
1460 WIN_ReleaseWndPtr(wndPtr);
1466 /***********************************************************************
1467 * OpenIcon (USER.44)
1469 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1471 return OpenIcon( hwnd );
1475 /***********************************************************************
1476 * OpenIcon (USER32.@)
1478 BOOL WINAPI OpenIcon( HWND hwnd )
1480 if (!IsIconic( hwnd )) return FALSE;
1481 ShowWindow( hwnd, SW_SHOWNORMAL );
1486 /***********************************************************************
1489 * Implementation of FindWindow() and FindWindowEx().
1491 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className,
1499 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1502 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent))
1508 else if (pWnd->parent != pWndDesktop)
1513 WIN_UpdateWndPtr(&pWnd,pWnd->next);
1517 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : WIN_LockWndPtr(pWndDesktop)))
1522 WIN_UpdateWndPtr(&pWnd,pWnd->child);
1530 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
1532 if (className && (GetClassWord(pWnd->hwndSelf, GCW_ATOM) != className))
1533 continue; /* Not the right class */
1535 /* Now check the title */
1539 retvalue = pWnd->hwndSelf;
1542 if (pWnd->text && !strcmpW( pWnd->text, title ))
1544 retvalue = pWnd->hwndSelf;
1549 /* In this case we need to check whether other processes
1550 own a window with the given paramters on the Desktop,
1551 but we don't, so let's at least warn about it */
1552 FIXME("Returning 0 without checking other processes\n");
1554 WIN_ReleaseWndPtr(pWnd);
1560 /***********************************************************************
1561 * FindWindow (USER.50)
1563 HWND16 WINAPI FindWindow16( LPCSTR className, LPCSTR title )
1565 return FindWindowA( className, title );
1569 /***********************************************************************
1570 * FindWindowEx (USER.427)
1572 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child, LPCSTR className, LPCSTR title )
1574 return FindWindowExA( parent, child, className, title );
1578 /***********************************************************************
1579 * FindWindowA (USER32.@)
1581 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1583 HWND ret = FindWindowExA( 0, 0, className, title );
1584 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1589 /***********************************************************************
1590 * FindWindowExA (USER32.@)
1592 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1593 LPCSTR className, LPCSTR title )
1601 /* If the atom doesn't exist, then no class */
1602 /* with this name exists either. */
1603 if (!(atom = GlobalFindAtomA( className )))
1605 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1610 buffer = HEAP_strdupAtoW( GetProcessHeap(), 0, title );
1611 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1612 HeapFree( GetProcessHeap(), 0, buffer );
1617 /***********************************************************************
1618 * FindWindowExW (USER32.@)
1620 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1621 LPCWSTR className, LPCWSTR title )
1627 /* If the atom doesn't exist, then no class */
1628 /* with this name exists either. */
1629 if (!(atom = GlobalFindAtomW( className )))
1631 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1635 return WIN_FindWindow( parent, child, atom, title );
1639 /***********************************************************************
1640 * FindWindowW (USER32.@)
1642 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1644 return FindWindowExW( 0, 0, className, title );
1648 /**********************************************************************
1650 * returns a locked pointer
1652 WND *WIN_GetDesktop(void)
1654 return WIN_LockWndPtr(pWndDesktop);
1656 /**********************************************************************
1657 * WIN_ReleaseDesktop
1658 * unlock the desktop pointer
1660 void WIN_ReleaseDesktop(void)
1662 WIN_ReleaseWndPtr(pWndDesktop);
1666 /**********************************************************************
1667 * GetDesktopWindow (USER.286)
1669 HWND16 WINAPI GetDesktopWindow16(void)
1671 return (HWND16)pWndDesktop->hwndSelf;
1675 /**********************************************************************
1676 * GetDesktopWindow (USER32.@)
1678 HWND WINAPI GetDesktopWindow(void)
1680 if (pWndDesktop) return pWndDesktop->hwndSelf;
1681 ERR( "You need the -desktop option when running with native USER\n" );
1687 /**********************************************************************
1688 * GetDesktopHwnd (USER.278)
1690 * Exactly the same thing as GetDesktopWindow(), but not documented.
1691 * Don't ask me why...
1693 HWND16 WINAPI GetDesktopHwnd16(void)
1695 return (HWND16)pWndDesktop->hwndSelf;
1699 /*******************************************************************
1700 * EnableWindow (USER.34)
1702 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1704 return EnableWindow( hwnd, enable );
1708 /*******************************************************************
1709 * EnableWindow (USER32.@)
1711 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1716 TRACE("( %x, %d )\n", hwnd, enable);
1718 if (USER_Driver.pEnableWindow)
1719 return USER_Driver.pEnableWindow( hwnd, enable );
1721 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1723 retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
1725 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1727 wndPtr->dwStyle &= ~WS_DISABLED; /* Enable window */
1728 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1730 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1732 SendMessageA( wndPtr->hwndSelf, WM_CANCELMODE, 0, 0);
1734 wndPtr->dwStyle |= WS_DISABLED; /* Disable window */
1736 if (hwnd == GetFocus())
1737 SetFocus( 0 ); /* A disabled window can't have the focus */
1739 if (hwnd == GetCapture())
1740 ReleaseCapture(); /* A disabled window can't capture the mouse */
1742 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1744 WIN_ReleaseWndPtr(wndPtr);
1749 /***********************************************************************
1750 * IsWindowEnabled (USER.35)
1752 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1754 return IsWindowEnabled(hWnd);
1758 /***********************************************************************
1759 * IsWindowEnabled (USER32.@)
1761 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1766 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1767 retvalue = !(wndPtr->dwStyle & WS_DISABLED);
1768 WIN_ReleaseWndPtr(wndPtr);
1774 /***********************************************************************
1775 * IsWindowUnicode (USER32.@)
1777 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1782 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1783 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1784 WIN_ReleaseWndPtr(wndPtr);
1789 /**********************************************************************
1790 * GetWindowWord (USER.133)
1792 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1794 return GetWindowWord( hwnd, offset );
1798 /**********************************************************************
1799 * GetWindowWord (USER32.@)
1801 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1804 WND * wndPtr = WIN_FindWndPtr( hwnd );
1805 if (!wndPtr) return 0;
1808 if (offset + sizeof(WORD) > wndPtr->cbWndExtra)
1810 WARN("Invalid offset %d\n", offset );
1814 retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1820 if (HIWORD(wndPtr->wIDmenu))
1821 WARN("GWW_ID: discards high bits of 0x%08x!\n",
1823 retvalue = (WORD)wndPtr->wIDmenu;
1825 case GWW_HWNDPARENT:
1826 retvalue = GetParent(hwnd);
1829 if (HIWORD(wndPtr->hInstance))
1830 WARN("GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1832 retvalue = (WORD)wndPtr->hInstance;
1835 WARN("Invalid offset %d\n", offset );
1840 WIN_ReleaseWndPtr(wndPtr);
1844 /**********************************************************************
1845 * SetWindowWord (USER.134)
1847 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1849 return SetWindowWord( hwnd, offset, newval );
1853 /**********************************************************************
1854 * SetWindowWord (USER32.@)
1856 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1859 WND * wndPtr = WIN_FindWndPtr( hwnd );
1860 if (!wndPtr) return 0;
1863 if (offset + sizeof(WORD) > wndPtr->cbWndExtra)
1865 WARN("Invalid offset %d\n", offset );
1869 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1873 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1874 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1875 case GWW_HWNDPARENT: retval = SetParent( hwnd, newval );
1878 WARN("Invalid offset %d\n", offset );
1885 WIN_ReleaseWndPtr(wndPtr);
1890 /**********************************************************************
1893 * Helper function for GetWindowLong().
1895 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1898 WND * wndPtr = WIN_FindWndPtr( hwnd );
1899 if (!wndPtr) return 0;
1902 if (offset + sizeof(LONG) > wndPtr->cbWndExtra)
1904 WARN("Invalid offset %d\n", offset );
1908 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1909 /* Special case for dialog window procedure */
1910 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1912 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1919 case GWL_USERDATA: retvalue = wndPtr->userdata;
1921 case GWL_STYLE: retvalue = wndPtr->dwStyle;
1923 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle;
1925 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu;
1927 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc,
1930 case GWL_HWNDPARENT: retvalue = GetParent(hwnd);
1932 case GWL_HINSTANCE: retvalue = wndPtr->hInstance;
1935 WARN("Unknown offset %d\n", offset );
1939 WIN_ReleaseWndPtr(wndPtr);
1944 /**********************************************************************
1947 * Helper function for SetWindowLong().
1949 * 0 is the failure code. However, in the case of failure SetLastError
1950 * must be set to distinguish between a 0 return value and a failure.
1952 * FIXME: The error values for SetLastError may not be right. Can
1953 * someone check with the real thing?
1955 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1956 WINDOWPROCTYPE type )
1959 WND * wndPtr = WIN_FindWndPtr( hwnd );
1962 TRACE("%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1966 /* Is this the right error? */
1967 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1973 if (offset + sizeof(LONG) > wndPtr->cbWndExtra)
1975 WARN("Invalid offset %d\n", offset );
1977 /* Is this the right error? */
1978 SetLastError( ERROR_OUTOFMEMORY );
1983 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1984 /* Special case for dialog window procedure */
1985 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1987 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1988 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
1989 type, WIN_PROC_WINDOW );
1996 ptr = (DWORD*)&wndPtr->wIDmenu;
1999 retval = SetWindowWord( hwnd, offset, newval );
2002 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
2003 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
2004 type, WIN_PROC_WINDOW );
2007 style.styleOld = wndPtr->dwStyle;
2008 style.styleNew = newval;
2009 if (wndPtr->flags & WIN_ISWIN32)
2010 SendMessageA(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
2011 wndPtr->dwStyle = style.styleNew;
2012 if (wndPtr->flags & WIN_ISWIN32)
2013 SendMessageA(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
2014 retval = style.styleOld;
2018 ptr = &wndPtr->userdata;
2021 style.styleOld = wndPtr->dwExStyle;
2022 style.styleNew = newval;
2023 if (wndPtr->flags & WIN_ISWIN32)
2024 SendMessageA(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
2025 wndPtr->dwExStyle = newval;
2026 if (wndPtr->flags & WIN_ISWIN32)
2027 SendMessageA(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
2028 retval = style.styleOld;
2032 WARN("Invalid offset %d\n", offset );
2034 /* Don't think this is right error but it should do */
2035 SetLastError( ERROR_OUTOFMEMORY );
2043 WIN_ReleaseWndPtr(wndPtr);
2048 /**********************************************************************
2049 * GetWindowLong (USER.135)
2051 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2053 return WIN_GetWindowLong( (HWND)hwnd, offset, WIN_PROC_16 );
2057 /**********************************************************************
2058 * GetWindowLongA (USER32.@)
2060 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2062 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2066 /**********************************************************************
2067 * GetWindowLongW (USER32.@)
2069 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2071 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2075 /**********************************************************************
2076 * SetWindowLong (USER.136)
2078 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2080 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
2084 /**********************************************************************
2085 * SetWindowLongA (USER32.@)
2087 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2089 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2093 /**********************************************************************
2094 * SetWindowLongW (USER32.@) Set window attribute
2096 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2097 * value in a window's extra memory.
2099 * The _hwnd_ parameter specifies the window. is the handle to a
2100 * window that has extra memory. The _newval_ parameter contains the
2101 * new attribute or extra memory value. If positive, the _offset_
2102 * parameter is the byte-addressed location in the window's extra
2103 * memory to set. If negative, _offset_ specifies the window
2104 * attribute to set, and should be one of the following values:
2106 * GWL_EXSTYLE The window's extended window style
2108 * GWL_STYLE The window's window style.
2110 * GWL_WNDPROC Pointer to the window's window procedure.
2112 * GWL_HINSTANCE The window's pplication instance handle.
2114 * GWL_ID The window's identifier.
2116 * GWL_USERDATA The window's user-specified data.
2118 * If the window is a dialog box, the _offset_ parameter can be one of
2119 * the following values:
2121 * DWL_DLGPROC The address of the window's dialog box procedure.
2123 * DWL_MSGRESULT The return value of a message
2124 * that the dialog box procedure processed.
2126 * DWL_USER Application specific information.
2130 * If successful, returns the previous value located at _offset_. Otherwise,
2135 * Extra memory for a window class is specified by a nonzero cbWndExtra
2136 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2137 * time of class creation.
2139 * Using GWL_WNDPROC to set a new window procedure effectively creates
2140 * a window subclass. Use CallWindowProc() in the new windows procedure
2141 * to pass messages to the superclass's window procedure.
2143 * The user data is reserved for use by the application which created
2146 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
2147 * instead, call the EnableWindow() function to change the window's
2150 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2151 * SetParent() instead.
2154 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2155 * it sends WM_STYLECHANGING before changing the settings
2156 * and WM_STYLECHANGED afterwards.
2157 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2161 * GWL_STYLE does not dispatch WM_STYLE... messages.
2168 LONG WINAPI SetWindowLongW(
2169 HWND hwnd, /* [in] window to alter */
2170 INT offset, /* [in] offset, in bytes, of location to alter */
2171 LONG newval /* [in] new value of location */
2173 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2177 /*******************************************************************
2178 * GetWindowText (USER.36)
2180 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
2182 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
2186 /*******************************************************************
2187 * GetWindowTextA (USER32.@)
2189 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2191 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount,
2195 /*******************************************************************
2196 * InternalGetWindowText (USER32.@)
2198 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2200 FIXME("(0x%08x,%p,0x%x),stub!\n",hwnd,lpString,nMaxCount);
2201 return GetWindowTextW(hwnd,lpString,nMaxCount);
2205 /*******************************************************************
2206 * GetWindowTextW (USER32.@)
2208 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2210 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount,
2215 /*******************************************************************
2216 * SetWindowText (USER.37)
2218 BOOL16 WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
2220 return (BOOL16)SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2224 /*******************************************************************
2225 * SetWindowText (USER32.@)
2227 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2229 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2233 /*******************************************************************
2234 * SetWindowTextW (USER32.@)
2236 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2238 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2242 /*******************************************************************
2243 * GetWindowTextLength (USER.38)
2245 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
2247 return (INT16)SendMessage16( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2251 /*******************************************************************
2252 * GetWindowTextLengthA (USER32.@)
2254 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2256 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2259 /*******************************************************************
2260 * GetWindowTextLengthW (USER32.@)
2262 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2264 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2268 /*******************************************************************
2269 * IsWindow (USER.47)
2271 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
2273 CURRENT_STACK16->es = USER_HeapSel;
2274 return IsWindow( hwnd );
2278 /*******************************************************************
2279 * IsWindow (USER32.@)
2281 BOOL WINAPI IsWindow( HWND hwnd )
2286 if(!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2287 retvalue = (wndPtr->dwMagic == WND_MAGIC);
2288 WIN_ReleaseWndPtr(wndPtr);
2294 /*****************************************************************
2295 * GetParent (USER.46)
2297 HWND16 WINAPI GetParent16( HWND16 hwnd )
2299 return (HWND16)GetParent( hwnd );
2303 /*****************************************************************
2304 * GetParent (USER32.@)
2306 HWND WINAPI GetParent( HWND hwnd )
2311 if(!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2312 if ((!(wndPtr->dwStyle & (WS_POPUP|WS_CHILD))))
2315 WIN_UpdateWndPtr(&wndPtr,((wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner));
2317 retvalue = wndPtr->hwndSelf;
2320 WIN_ReleaseWndPtr(wndPtr);
2325 /*****************************************************************
2328 * Get the top-level parent for a child window.
2329 * returns a locked pointer
2331 WND* WIN_GetTopParentPtr( WND* pWnd )
2333 WND *tmpWnd = WIN_LockWndPtr(pWnd);
2335 while( tmpWnd && (tmpWnd->dwStyle & WS_CHILD))
2337 WIN_UpdateWndPtr(&tmpWnd,tmpWnd->parent);
2342 /*****************************************************************
2345 * Get the top-level parent for a child window.
2347 HWND WIN_GetTopParent( HWND hwnd )
2350 WND *tmpPtr = WIN_FindWndPtr(hwnd);
2351 WND *wndPtr = WIN_GetTopParentPtr (tmpPtr );
2353 retvalue = wndPtr ? wndPtr->hwndSelf : 0;
2354 WIN_ReleaseWndPtr(tmpPtr);
2355 WIN_ReleaseWndPtr(wndPtr);
2360 /*****************************************************************
2361 * SetParent (USER.233)
2363 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
2365 return SetParent( hwndChild, hwndNewParent );
2369 /*****************************************************************
2370 * SetParent (USER32.@)
2372 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2379 if (hwnd == GetDesktopWindow()) /* sanity check */
2381 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2385 if (USER_Driver.pSetParent)
2386 return USER_Driver.pSetParent( hwnd, parent );
2388 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2390 dwStyle = wndPtr->dwStyle;
2392 if (!parent) parent = GetDesktopWindow();
2394 if (!(pWndParent = WIN_FindWndPtr(parent)))
2396 WIN_ReleaseWndPtr( wndPtr );
2400 /* Windows hides the window first, then shows it again
2401 * including the WM_SHOWWINDOW messages and all */
2402 if (dwStyle & WS_VISIBLE) ShowWindow( hwnd, SW_HIDE );
2404 retvalue = wndPtr->parent->hwndSelf; /* old parent */
2405 if (pWndParent != wndPtr->parent)
2407 WIN_UnlinkWindow(wndPtr->hwndSelf);
2408 wndPtr->parent = pWndParent;
2410 if (parent != GetDesktopWindow()) /* a child window */
2412 if( !( wndPtr->dwStyle & WS_CHILD ) )
2414 if( wndPtr->wIDmenu != 0)
2416 DestroyMenu( (HMENU) wndPtr->wIDmenu );
2417 wndPtr->wIDmenu = 0;
2421 WIN_LinkWindow(wndPtr->hwndSelf, HWND_TOP);
2423 WIN_ReleaseWndPtr( pWndParent );
2424 WIN_ReleaseWndPtr( wndPtr );
2426 /* SetParent additionally needs to make hwnd the topmost window
2427 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2428 WM_WINDOWPOSCHANGED notification messages.
2430 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2431 SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|
2432 ((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
2433 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2434 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2439 /*******************************************************************
2442 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
2444 return IsChild(parent,child);
2448 /*******************************************************************
2449 * IsChild (USER32.@)
2451 BOOL WINAPI IsChild( HWND parent, HWND child )
2453 WND * wndPtr = WIN_FindWndPtr( child );
2454 while (wndPtr && wndPtr->parent)
2456 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2457 if (wndPtr->hwndSelf == GetDesktopWindow()) break;
2458 if (wndPtr->hwndSelf == parent)
2460 WIN_ReleaseWndPtr(wndPtr);
2464 WIN_ReleaseWndPtr(wndPtr);
2469 /***********************************************************************
2470 * IsWindowVisible (USER.49)
2472 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
2474 return IsWindowVisible(hwnd);
2478 /***********************************************************************
2479 * IsWindowVisible (USER32.@)
2481 BOOL WINAPI IsWindowVisible( HWND hwnd )
2484 WND *wndPtr = WIN_FindWndPtr( hwnd );
2485 while (wndPtr && wndPtr->parent)
2487 if (!(wndPtr->dwStyle & WS_VISIBLE))
2489 WIN_ReleaseWndPtr(wndPtr);
2492 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2494 retval = (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
2495 WIN_ReleaseWndPtr(wndPtr);
2500 /***********************************************************************
2501 * WIN_IsWindowDrawable
2503 * hwnd is drawable when it is visible, all parents are not
2504 * minimized, and it is itself not minimized unless we are
2505 * trying to draw its default class icon.
2507 BOOL WIN_IsWindowDrawable( WND* wnd, BOOL icon )
2509 if (!(wnd->dwStyle & WS_VISIBLE)) return FALSE;
2510 if ((wnd->dwStyle & WS_MINIMIZE) &&
2511 icon && GetClassLongA( wnd->hwndSelf, GCL_HICON )) return FALSE;
2512 for(wnd = wnd->parent; wnd; wnd = wnd->parent)
2513 if( wnd->dwStyle & WS_MINIMIZE ||
2514 !(wnd->dwStyle & WS_VISIBLE) ) break;
2515 return (wnd == NULL);
2519 /*******************************************************************
2520 * GetTopWindow (USER.229)
2522 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
2524 return GetTopWindow(hwnd);
2528 /*******************************************************************
2529 * GetTopWindow (USER32.@)
2531 HWND WINAPI GetTopWindow( HWND hwnd )
2534 WND * wndPtr = (hwnd) ?
2535 WIN_FindWndPtr( hwnd ) : WIN_GetDesktop();
2537 if (wndPtr && wndPtr->child)
2538 retval = wndPtr->child->hwndSelf;
2540 WIN_ReleaseWndPtr(wndPtr);
2545 /*******************************************************************
2546 * GetWindow (USER.262)
2548 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
2550 return GetWindow( hwnd,rel );
2554 /*******************************************************************
2555 * GetWindow (USER32.@)
2557 HWND WINAPI GetWindow( HWND hwnd, WORD rel )
2561 WND * wndPtr = WIN_FindWndPtr( hwnd );
2562 if (!wndPtr) return 0;
2566 retval = wndPtr->parent ? wndPtr->parent->child->hwndSelf : 0;
2570 if (!wndPtr->parent)
2572 retval = 0; /* Desktop window */
2575 while (wndPtr->next)
2577 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2579 retval = wndPtr->hwndSelf;
2583 retval = wndPtr->next ? wndPtr->next->hwndSelf : 0;
2587 if (!wndPtr->parent)
2589 retval = 0; /* Desktop window */
2592 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent->child); /* First sibling */
2593 if (wndPtr->hwndSelf == hwnd)
2595 retval = 0; /* First in list */
2598 while (wndPtr->next)
2600 if (wndPtr->next->hwndSelf == hwnd)
2602 retval = wndPtr->hwndSelf;
2605 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2611 retval = wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
2615 retval = wndPtr->child ? wndPtr->child->hwndSelf : 0;
2620 WIN_ReleaseWndPtr(wndPtr);
2625 /*******************************************************************
2626 * GetNextWindow (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 * WIN_InternalShowOwnedPopups
2637 * Internal version of ShowOwnedPopups; Wine functions should use this
2638 * to avoid interfering with application calls to ShowOwnedPopups
2639 * and to make sure the application can't prevent showing/hiding.
2641 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2645 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2647 INT totalChild=0, count=0;
2649 WND **pWnd = WIN_BuildWinArray(WIN_GetDesktop(), 0, &totalChild);
2651 if (!pWnd) return TRUE;
2654 * Show windows Lowest first, Highest last to preserve Z-Order
2656 for (count = totalChild-1 ; count >=0; count--)
2658 if (pWnd[count]->owner && (pWnd[count]->owner->hwndSelf == owner) && (pWnd[count]->dwStyle & WS_POPUP))
2662 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2663 if (pWnd[count]->flags & WIN_NEEDS_INTERNALSOP)
2666 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2668 ShowWindow(pWnd[count]->hwndSelf,SW_SHOW);
2669 pWnd[count]->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2674 if ( IsWindowVisible(pWnd[count]->hwndSelf) && /* hide only if window is visible */
2675 !( pWnd[count]->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2676 !( unmanagedOnly && (pWnd[count]->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2679 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2681 ShowWindow(pWnd[count]->hwndSelf,SW_HIDE);
2682 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2683 pWnd[count]->flags |= WIN_NEEDS_INTERNALSOP;
2688 WIN_ReleaseDesktop();
2689 WIN_ReleaseWinArray(pWnd);
2694 /*******************************************************************
2695 * ShowOwnedPopups (USER.265)
2697 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2699 ShowOwnedPopups( owner, fShow );
2703 /*******************************************************************
2704 * ShowOwnedPopups (USER32.@)
2706 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2708 UINT totalChild=0, count=0;
2710 WND **pWnd = WIN_BuildWinArray(WIN_GetDesktop(), 0, &totalChild);
2712 if (!pWnd) return TRUE;
2714 for (; count < totalChild; count++)
2716 if (pWnd[count]->owner && (pWnd[count]->owner->hwndSelf == owner) && (pWnd[count]->dwStyle & WS_POPUP))
2720 if (pWnd[count]->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2723 * In Windows, ShowOwnedPopups(TRUE) generates WM_SHOWWINDOW messages with SW_PARENTOPENING,
2724 * regardless of the state of the owner
2726 SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2727 pWnd[count]->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2732 if (IsWindowVisible(pWnd[count]->hwndSelf))
2735 * In Windows, ShowOwnedPopups(FALSE) generates WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2736 * regardless of the state of the owner
2738 SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2739 pWnd[count]->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2745 WIN_ReleaseDesktop();
2746 WIN_ReleaseWinArray(pWnd);
2751 /*******************************************************************
2752 * GetLastActivePopup (USER.287)
2754 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2756 return GetLastActivePopup( hwnd );
2759 /*******************************************************************
2760 * GetLastActivePopup (USER32.@)
2762 HWND WINAPI GetLastActivePopup( HWND hwnd )
2765 WND *wndPtr =WIN_FindWndPtr(hwnd);
2766 if (!wndPtr) return hwnd;
2767 retval = wndPtr->hwndLastActive;
2768 WIN_ReleaseWndPtr(wndPtr);
2769 if ((retval != hwnd) && (!IsWindow(retval)))
2775 /*******************************************************************
2778 * Build an array of pointers to the children of a given window.
2779 * The array must be freed with WIN_ReleaseWinArray. Return NULL
2780 * when no windows are found.
2782 WND **WIN_BuildWinArray( WND *wndPtr, UINT bwaFlags, UINT* pTotal )
2784 /* Future: this function will lock all windows associated with this array */
2786 WND **list, **ppWnd;
2788 UINT count = 0, skipOwned, skipHidden;
2791 skipHidden = bwaFlags & BWA_SKIPHIDDEN;
2792 skipOwned = bwaFlags & BWA_SKIPOWNED;
2793 skipFlags = (bwaFlags & BWA_SKIPDISABLED) ? WS_DISABLED : 0;
2794 if( bwaFlags & BWA_SKIPICONIC ) skipFlags |= WS_MINIMIZE;
2796 /* First count the windows */
2799 wndPtr = WIN_GetDesktop();
2801 pWnd = WIN_LockWndPtr(wndPtr->child);
2804 if( !(pWnd->dwStyle & skipFlags) && !(skipOwned && pWnd->owner) &&
2805 (!skipHidden || (pWnd->dwStyle & WS_VISIBLE)) )
2807 WIN_UpdateWndPtr(&pWnd,pWnd->next);
2812 /* Now build the list of all windows */
2814 if ((list = (WND **)HeapAlloc( GetProcessHeap(), 0, sizeof(WND *) * (count + 1))))
2816 for (pWnd = WIN_LockWndPtr(wndPtr->child), ppWnd = list, count = 0; pWnd; WIN_UpdateWndPtr(&pWnd,pWnd->next))
2818 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) );
2819 else if( !skipHidden || pWnd->dwStyle & WS_VISIBLE )
2825 WIN_ReleaseWndPtr(pWnd);
2831 if( pTotal ) *pTotal = count;
2834 /*******************************************************************
2835 * WIN_ReleaseWinArray
2837 void WIN_ReleaseWinArray(WND **wndArray)
2839 /* Future: this function will also unlock all windows associated with wndArray */
2840 HeapFree( GetProcessHeap(), 0, wndArray );
2844 /*******************************************************************
2845 * EnumWindows (USER32.@)
2847 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2849 WND **list, **ppWnd;
2851 /* We have to build a list of all windows first, to avoid */
2852 /* unpleasant side-effects, for instance if the callback */
2853 /* function changes the Z-order of the windows. */
2855 if (!(list = WIN_BuildWinArray(WIN_GetDesktop(), 0, NULL )))
2857 WIN_ReleaseDesktop();
2861 /* Now call the callback function for every window */
2863 for (ppWnd = list; *ppWnd; ppWnd++)
2865 LRESULT lpEnumFuncRetval;
2867 /* Make sure that the window still exists */
2868 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2870 /* To avoid any deadlocks, all the locks on the windows
2871 structures must be suspended before the control
2872 is passed to the application */
2873 iWndsLocks = WIN_SuspendWndsLock();
2874 lpEnumFuncRetval = lpEnumFunc( (*ppWnd)->hwndSelf, lParam);
2875 WIN_RestoreWndsLock(iWndsLocks);
2877 if (!lpEnumFuncRetval) break;
2879 WIN_ReleaseWinArray(list);
2880 WIN_ReleaseDesktop();
2885 /**********************************************************************
2886 * WIN_EnumQueueWindows
2888 * Helper for EnumTaskWindows16 and EnumThreadWindows.
2890 static BOOL WIN_EnumQueueWindows( HQUEUE16 queue, WNDENUMPROC func, LPARAM lParam )
2892 WND **list, **ppWnd;
2894 /* This function is the same as EnumWindows(), */
2895 /* except for an added check on the window's task. */
2897 if (!(list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
2899 WIN_ReleaseDesktop();
2903 /* Now call the callback function for every window */
2905 for (ppWnd = list; *ppWnd; ppWnd++)
2909 /* Make sure that the window still exists */
2910 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2911 if ((*ppWnd)->hmemTaskQ != queue) continue;
2913 /* To avoid any deadlocks, all the locks on the windows
2914 structures must be suspended before the control
2915 is passed to the application */
2916 iWndsLocks = WIN_SuspendWndsLock();
2917 funcRetval = func( (*ppWnd)->hwndSelf, lParam );
2918 WIN_RestoreWndsLock(iWndsLocks);
2920 if (!funcRetval) break;
2922 WIN_ReleaseWinArray(list);
2923 WIN_ReleaseDesktop();
2928 /**********************************************************************
2929 * EnumTaskWindows16 (USER.225)
2931 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2934 HQUEUE16 queue = GetTaskQueue16( hTask );
2935 if (!queue) return FALSE;
2936 return WIN_EnumQueueWindows( queue, (WNDENUMPROC)func, lParam );
2940 /**********************************************************************
2941 * EnumThreadWindows (USER32.@)
2943 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2945 HQUEUE16 queue = GetThreadQueue16( id );
2946 if (!queue) return FALSE;
2947 return WIN_EnumQueueWindows( queue, func, lParam );
2951 /**********************************************************************
2952 * WIN_EnumChildWindows
2954 * Helper function for EnumChildWindows().
2956 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC func, LPARAM lParam )
2961 for ( ; *ppWnd; ppWnd++)
2965 /* Make sure that the window still exists */
2966 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2967 /* Build children list first */
2968 childList = WIN_BuildWinArray( *ppWnd, BWA_SKIPOWNED, NULL );
2970 /* To avoid any deadlocks, all the locks on the windows
2971 structures must be suspended before the control
2972 is passed to the application */
2973 iWndsLocks = WIN_SuspendWndsLock();
2974 ret = func( (*ppWnd)->hwndSelf, lParam );
2975 WIN_RestoreWndsLock(iWndsLocks);
2979 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2980 WIN_ReleaseWinArray(childList);
2982 if (!ret) return FALSE;
2988 /**********************************************************************
2989 * EnumChildWindows (USER32.@)
2991 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func,
2994 WND **list, *pParent;
2996 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
2997 if (!(list = WIN_BuildWinArray( pParent, BWA_SKIPOWNED, NULL )))
2999 WIN_ReleaseWndPtr(pParent);
3002 WIN_EnumChildWindows( list, func, lParam );
3003 WIN_ReleaseWinArray(list);
3004 WIN_ReleaseWndPtr(pParent);
3009 /*******************************************************************
3010 * AnyPopup (USER.52)
3012 BOOL16 WINAPI AnyPopup16(void)
3018 /*******************************************************************
3019 * AnyPopup (USER32.@)
3021 BOOL WINAPI AnyPopup(void)
3023 WND *wndPtr = WIN_LockWndPtr(pWndDesktop->child);
3028 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE))
3033 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
3037 WIN_ReleaseWndPtr(wndPtr);
3042 /*******************************************************************
3043 * FlashWindow (USER.105)
3045 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
3047 return FlashWindow( hWnd, bInvert );
3051 /*******************************************************************
3052 * FlashWindow (USER32.@)
3054 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
3056 WND *wndPtr = WIN_FindWndPtr(hWnd);
3058 TRACE("%04x\n", hWnd);
3060 if (!wndPtr) return FALSE;
3062 if (wndPtr->dwStyle & WS_MINIMIZE)
3064 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3066 HDC hDC = GetDC(hWnd);
3068 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
3069 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
3071 ReleaseDC( hWnd, hDC );
3072 wndPtr->flags |= WIN_NCACTIVATED;
3076 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
3077 wndPtr->flags &= ~WIN_NCACTIVATED;
3079 WIN_ReleaseWndPtr(wndPtr);
3085 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3086 else wparam = (hWnd == GetActiveWindow());
3088 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3089 WIN_ReleaseWndPtr(wndPtr);
3095 /*******************************************************************
3096 * SetSysModalWindow (USER.188)
3098 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
3100 HWND hWndOldModal = hwndSysModal;
3101 hwndSysModal = hWnd;
3102 FIXME("EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
3103 return hWndOldModal;
3107 /*******************************************************************
3108 * GetSysModalWindow (USER.189)
3110 HWND16 WINAPI GetSysModalWindow16(void)
3112 return hwndSysModal;
3116 /*******************************************************************
3117 * GetWindowContextHelpId (USER32.@)
3119 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3122 WND *wnd = WIN_FindWndPtr( hwnd );
3124 retval = wnd->helpContext;
3125 WIN_ReleaseWndPtr(wnd);
3130 /*******************************************************************
3131 * SetWindowContextHelpId (USER32.@)
3133 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3135 WND *wnd = WIN_FindWndPtr( hwnd );
3136 if (!wnd) return FALSE;
3137 wnd->helpContext = id;
3138 WIN_ReleaseWndPtr(wnd);
3143 /*******************************************************************
3146 * recursively find a child that contains spDragInfo->pt point
3147 * and send WM_QUERYDROPOBJECT
3149 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
3151 BOOL16 wParam, bResult = 0;
3153 LPDRAGINFO16 ptrDragInfo = MapSL(spDragInfo);
3154 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
3157 if( !ptrQueryWnd || !ptrDragInfo )
3160 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
3162 GetWindowRect(hQueryWnd,&tempRect);
3164 if( !PtInRect(&tempRect,pt) ||
3165 (ptrQueryWnd->dwStyle & WS_DISABLED) )
3168 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
3170 tempRect = ptrQueryWnd->rectClient;
3171 if(ptrQueryWnd->parent)
3172 MapWindowPoints( ptrQueryWnd->parent->hwndSelf, 0,
3173 (LPPOINT)&tempRect, 2 );
3175 if (PtInRect( &tempRect, pt))
3179 for (ptrWnd = WIN_LockWndPtr(ptrQueryWnd->child); ptrWnd ;WIN_UpdateWndPtr(&ptrWnd,ptrWnd->next))
3181 if( ptrWnd->dwStyle & WS_VISIBLE )
3183 GetWindowRect( ptrWnd->hwndSelf, &tempRect );
3184 if (PtInRect( &tempRect, pt )) break;
3190 TRACE_(msg)("hwnd = %04x, %d %d - %d %d\n",
3191 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
3192 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
3193 if( !(ptrWnd->dwStyle & WS_DISABLED) )
3194 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
3196 WIN_ReleaseWndPtr(ptrWnd);
3206 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
3208 ptrDragInfo->hScope = hQueryWnd;
3210 bResult = ( bNoSend )
3211 ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
3212 : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
3213 (WPARAM16)wParam ,(LPARAM) spDragInfo );
3215 CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3218 WIN_ReleaseWndPtr(ptrQueryWnd);
3223 /*******************************************************************
3224 * DragDetect (USER.465)
3226 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
3229 CONV_POINT16TO32( &pt, &pt32 );
3230 return DragDetect( hWnd, pt32 );
3233 /*******************************************************************
3234 * DragDetect (USER32.@)
3236 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3241 rect.left = pt.x - wDragWidth;
3242 rect.right = pt.x + wDragWidth;
3244 rect.top = pt.y - wDragHeight;
3245 rect.bottom = pt.y + wDragHeight;
3251 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3253 if( msg.message == WM_LBUTTONUP )
3258 if( msg.message == WM_MOUSEMOVE )
3261 tmp.x = LOWORD(msg.lParam);
3262 tmp.y = HIWORD(msg.lParam);
3263 if( !PtInRect( &rect, tmp ))
3275 /******************************************************************************
3276 * DragObject (USER.464)
3278 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3279 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3282 LPDRAGINFO16 lpDragInfo;
3284 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
3285 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO16));
3286 WND *wndPtr = WIN_FindWndPtr(hWnd);
3287 HCURSOR16 hCurrentCursor = 0;
3288 HWND16 hCurrentWnd = 0;
3290 lpDragInfo = (LPDRAGINFO16) GlobalLock16(hDragInfo);
3291 spDragInfo = K32WOWGlobalLock16(hDragInfo);
3293 if( !lpDragInfo || !spDragInfo )
3295 WIN_ReleaseWndPtr(wndPtr);
3299 hBummer = LoadCursorA(0, MAKEINTRESOURCEA(OCR_NO));
3301 if( !hBummer || !wndPtr )
3303 GlobalFree16(hDragInfo);
3304 WIN_ReleaseWndPtr(wndPtr);
3310 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
3312 GlobalFree16(hDragInfo);
3313 WIN_ReleaseWndPtr(wndPtr);
3317 if( hDragCursor == hCursor ) hDragCursor = 0;
3318 else hCursor = hDragCursor;
3320 hOldCursor = SetCursor(hDragCursor);
3323 lpDragInfo->hWnd = hWnd;
3324 lpDragInfo->hScope = 0;
3325 lpDragInfo->wFlags = wObj;
3326 lpDragInfo->hList = szList; /* near pointer! */
3327 lpDragInfo->hOfStruct = hOfStruct;
3335 do{ WaitMessage(); }
3336 while( !PeekMessageA(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) );
3338 *(lpDragInfo+1) = *lpDragInfo;
3340 lpDragInfo->pt.x = msg.pt.x;
3341 lpDragInfo->pt.y = msg.pt.y;
3343 /* update DRAGINFO struct */
3344 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
3346 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
3347 hCurrentCursor = hCursor;
3350 hCurrentCursor = hBummer;
3351 lpDragInfo->hScope = 0;
3353 if( hCurrentCursor )
3354 SetCursor(hCurrentCursor);
3356 /* send WM_DRAGLOOP */
3357 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3358 (LPARAM) spDragInfo );
3359 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3360 if( hCurrentWnd != lpDragInfo->hScope )
3363 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3364 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO16),
3365 HIWORD(spDragInfo)) );
3366 hCurrentWnd = lpDragInfo->hScope;
3368 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3372 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3374 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3377 ShowCursor( FALSE );
3381 SetCursor( hOldCursor );
3382 if (hDragCursor) DestroyCursor( hDragCursor );
3385 if( hCurrentCursor != hBummer )
3386 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3387 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3390 GlobalFree16(hDragInfo);
3391 WIN_ReleaseWndPtr(wndPtr);
3393 return (DWORD)(msg.lParam);
3397 /******************************************************************************
3398 * GetWindowModuleFileNameA (USER32.@)
3400 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3402 FIXME("GetWindowModuleFileNameA(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3403 hwnd, lpszFileName, cchFileNameMax);
3407 /******************************************************************************
3408 * GetWindowModuleFileNameW (USER32.@)
3410 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3412 FIXME("GetWindowModuleFileNameW(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3413 hwnd, lpszFileName, cchFileNameMax);