2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS user32.dll
4 * FILE: win32ss/user/user32/windows/window.c
5 * PURPOSE: Window management
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
9 * 06-06-2001 CSH Created
15 WINE_DEFAULT_DEBUG_CHANNEL(user32
);
17 void MDI_CalcDefaultChildPos( HWND hwndClient
, INT total
, LPPOINT lpPos
, INT delta
, UINT
*id
);
18 extern LPCWSTR FASTCALL
ClassNameToVersion(const void *lpszClass
, LPCWSTR lpszMenuName
, LPCWSTR
*plpLibFileName
, HANDLE
*pContext
, BOOL bAnsi
);
20 /* FUNCTIONS *****************************************************************/
24 User32CallSendAsyncProcForKernel(PVOID Arguments
, ULONG ArgumentLength
)
26 PSENDASYNCPROC_CALLBACK_ARGUMENTS CallbackArgs
;
28 TRACE("User32CallSendAsyncProcKernel()\n");
30 CallbackArgs
= (PSENDASYNCPROC_CALLBACK_ARGUMENTS
)Arguments
;
32 if (ArgumentLength
!= sizeof(SENDASYNCPROC_CALLBACK_ARGUMENTS
))
34 return(STATUS_INFO_LENGTH_MISMATCH
);
37 CallbackArgs
->Callback(CallbackArgs
->Wnd
,
39 CallbackArgs
->Context
,
40 CallbackArgs
->Result
);
41 return(STATUS_SUCCESS
);
49 AllowSetForegroundWindow(DWORD dwProcessId
)
51 return NtUserxAllowSetForegroundWindow(dwProcessId
);
59 BeginDeferWindowPos(int nNumWindows
)
61 return NtUserxBeginDeferWindowPos(nNumWindows
);
69 BringWindowToTop(HWND hWnd
)
71 return NtUserSetWindowPos(hWnd
,
77 SWP_NOSIZE
| SWP_NOMOVE
);
82 SwitchToThisWindow(HWND hwnd
, BOOL fAltTab
)
88 PostMessageW(hwnd
, WM_SYSCOMMAND
, SC_RESTORE
, 0);
89 SetForegroundWindow(hwnd
);
93 hwndFG
= GetForegroundWindow();
94 PostMessageW(hwnd
, WM_SYSCOMMAND
, SC_RESTORE
, 0);
95 SetWindowPos(hwnd
, hwndFG
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
);
96 SetWindowPos(hwndFG
, hwnd
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
);
105 ChildWindowFromPoint(HWND hWndParent
,
108 return (HWND
) NtUserChildWindowFromPointEx(hWndParent
, Point
.x
, Point
.y
, 0);
116 ChildWindowFromPointEx(HWND hwndParent
,
120 return (HWND
) NtUserChildWindowFromPointEx(hwndParent
, pt
.x
, pt
.y
, uFlags
);
128 CloseWindow(HWND hWnd
)
130 return PostMessageW(hWnd
, WM_SYSCOMMAND
, SC_MINIMIZE
, 0);
136 OUT PLARGE_STRING plstr
,
142 RtlInitLargeUnicodeString((PLARGE_UNICODE_STRING
)plstr
, (PWSTR
)psz
, 0);
146 RtlInitLargeAnsiString((PLARGE_ANSI_STRING
)plstr
, (PSTR
)psz
, 0);
153 IN PLARGE_STRING LargeString
)
155 if (LargeString
->Buffer
)
157 RtlFreeHeap(GetProcessHeap(), 0, LargeString
->Buffer
);
158 RtlZeroMemory(LargeString
, sizeof(LARGE_STRING
));
163 User32CreateWindowEx(DWORD dwExStyle
,
177 LARGE_STRING WindowName
;
178 LARGE_STRING lstrClassName
, *plstrClassName
;
179 LARGE_STRING lstrClassVersion
, *plstrClassVersion
;
180 UNICODE_STRING ClassName
;
181 UNICODE_STRING ClassVersion
;
184 HMODULE hLibModule
= NULL
;
186 BOOL Unicode
, ClassFound
= FALSE
;
188 LPCWSTR lpszClsVersion
;
189 LPCWSTR lpLibFileName
= NULL
;
193 DbgPrint("[window] User32CreateWindowEx style %d, exstyle %d, parent %d\n", dwStyle
, dwExStyle
, hWndParent
);
196 if (!RegisterDefaultClasses
)
198 TRACE("RegisterSystemControls\n");
199 RegisterSystemControls();
202 Unicode
= !(dwFlags
& NUCWE_ANSI
);
204 if (IS_ATOM(lpClassName
))
206 plstrClassName
= (PVOID
)lpClassName
;
212 RtlInitUnicodeString(&ClassName
, (PCWSTR
)lpClassName
);
216 if (!RtlCreateUnicodeStringFromAsciiz(&ClassName
, (PCSZ
)lpClassName
))
218 SetLastError(ERROR_OUTOFMEMORY
);
223 /* Copy it to a LARGE_STRING */
224 lstrClassName
.Buffer
= ClassName
.Buffer
;
225 lstrClassName
.Length
= ClassName
.Length
;
226 lstrClassName
.MaximumLength
= ClassName
.MaximumLength
;
227 plstrClassName
= &lstrClassName
;
230 /* Initialize a LARGE_STRING */
231 RtlInitLargeString(&WindowName
, lpWindowName
, Unicode
);
233 // HACK: The current implementation expects the Window name to be UNICODE
237 PSTR AnsiBuffer
= WindowName
.Buffer
;
238 ULONG AnsiLength
= WindowName
.Length
;
240 WindowName
.Length
= 0;
241 WindowName
.MaximumLength
= AnsiLength
* sizeof(WCHAR
);
242 WindowName
.Buffer
= RtlAllocateHeap(RtlGetProcessHeap(),
244 WindowName
.MaximumLength
);
245 if (!WindowName
.Buffer
)
247 SetLastError(ERROR_OUTOFMEMORY
);
251 Status
= RtlMultiByteToUnicodeN(WindowName
.Buffer
,
252 WindowName
.MaximumLength
,
256 if (!NT_SUCCESS(Status
))
262 if (!hMenu
&& (dwStyle
& (WS_OVERLAPPEDWINDOW
| WS_POPUP
)))
266 wceW
.cbSize
= sizeof(wceW
);
267 if (GetClassInfoExW(hInstance
, (LPCWSTR
)lpClassName
, &wceW
) && wceW
.lpszMenuName
)
269 hMenu
= LoadMenuW(hInstance
, wceW
.lpszMenuName
);
274 wceA
.cbSize
= sizeof(wceA
);
275 if (GetClassInfoExA(hInstance
, lpClassName
, &wceA
) && wceA
.lpszMenuName
)
277 hMenu
= LoadMenuA(hInstance
, wceA
.lpszMenuName
);
282 if (!Unicode
) dwExStyle
|= WS_EX_SETANSICREATOR
;
284 lpszClsVersion
= ClassNameToVersion(lpClassName
, NULL
, &lpLibFileName
, &pCtx
, !Unicode
);
287 plstrClassVersion
= plstrClassName
;
291 RtlInitUnicodeString(&ClassVersion
, lpszClsVersion
);
292 lstrClassVersion
.Buffer
= ClassVersion
.Buffer
;
293 lstrClassVersion
.Length
= ClassVersion
.Length
;
294 lstrClassVersion
.MaximumLength
= ClassVersion
.MaximumLength
;
295 plstrClassVersion
= &lstrClassVersion
;
300 Handle
= NtUserCreateWindowEx(dwExStyle
,
316 if (!lpLibFileName
) break;
319 dwLastError
= GetLastError();
320 if (dwLastError
== ERROR_CANNOT_FIND_WND_CLASS
)
322 ClassFound
= VersionRegisterClass(ClassName
.Buffer
, lpLibFileName
, pCtx
, &hLibModule
);
323 if (ClassFound
) continue;
328 dwLastError
= GetLastError();
329 FreeLibrary(hLibModule
);
330 SetLastError(dwLastError
);
337 DbgPrint("[window] NtUserCreateWindowEx() == %d\n", Handle
);
343 if (!IS_ATOM(lpClassName
))
344 RtlFreeUnicodeString(&ClassName
);
346 RtlFreeLargeString(&WindowName
);
359 CreateWindowExA(DWORD dwExStyle
,
372 MDICREATESTRUCTA mdi
;
375 if (!RegisterDefaultClasses
)
377 TRACE("CreateWindowExA RegisterSystemControls\n");
378 RegisterSystemControls();
381 if (dwExStyle
& WS_EX_MDICHILD
)
388 pWndParent
= ValidateHwnd(hWndParent
);
390 if (!pWndParent
) return NULL
;
392 if (pWndParent
->fnid
!= FNID_MDICLIENT
) // wine uses WIN_ISMDICLIENT
394 WARN("WS_EX_MDICHILD, but parent %p is not MDIClient\n", hWndParent
);
398 /* lpParams of WM_[NC]CREATE is different for MDI children.
399 * MDICREATESTRUCT members have the originally passed values.
401 mdi
.szClass
= lpClassName
;
402 mdi
.szTitle
= lpWindowName
;
403 mdi
.hOwner
= hInstance
;
409 mdi
.lParam
= (LPARAM
)lpParam
;
411 lpParam
= (LPVOID
)&mdi
;
413 if (pWndParent
->style
& MDIS_ALLCHILDSTYLES
)
415 if (dwStyle
& WS_POPUP
)
417 WARN("WS_POPUP with MDIS_ALLCHILDSTYLES is not allowed\n");
420 dwStyle
|= (WS_CHILD
| WS_CLIPSIBLINGS
);
424 dwStyle
&= ~WS_POPUP
;
425 dwStyle
|= (WS_CHILD
| WS_VISIBLE
| WS_CLIPSIBLINGS
| WS_CAPTION
|
426 WS_SYSMENU
| WS_THICKFRAME
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
);
429 top_child
= GetWindow(hWndParent
, GW_CHILD
);
433 /* Restore current maximized child */
434 if((dwStyle
& WS_VISIBLE
) && IsZoomed(top_child
))
436 TRACE("Restoring current maximized child %p\n", top_child
);
437 SendMessageW( top_child
, WM_SETREDRAW
, FALSE
, 0 );
438 ShowWindow(top_child
, SW_RESTORE
);
439 SendMessageW( top_child
, WM_SETREDRAW
, TRUE
, 0 );
443 MDI_CalcDefaultChildPos(hWndParent
, -1, mPos
, 0, &id
);
445 if (!(dwStyle
& WS_POPUP
)) hMenu
= UlongToHandle(id
);
447 if (dwStyle
& (WS_CHILD
| WS_POPUP
))
449 if (x
== CW_USEDEFAULT
|| x
== CW_USEDEFAULT16
)
454 if (nWidth
== CW_USEDEFAULT
|| nWidth
== CW_USEDEFAULT16
|| !nWidth
)
456 if (nHeight
== CW_USEDEFAULT
|| nHeight
== CW_USEDEFAULT16
|| !nHeight
)
461 hwnd
= User32CreateWindowEx(dwExStyle
,
484 CreateWindowExW(DWORD dwExStyle
,
486 LPCWSTR lpWindowName
,
497 MDICREATESTRUCTW mdi
;
500 if (!RegisterDefaultClasses
)
502 ERR("CreateWindowExW RegisterSystemControls\n");
503 RegisterSystemControls();
506 if (dwExStyle
& WS_EX_MDICHILD
)
513 pWndParent
= ValidateHwnd(hWndParent
);
515 if (!pWndParent
) return NULL
;
517 if (pWndParent
->fnid
!= FNID_MDICLIENT
)
519 WARN("WS_EX_MDICHILD, but parent %p is not MDIClient\n", hWndParent
);
523 /* lpParams of WM_[NC]CREATE is different for MDI children.
524 * MDICREATESTRUCT members have the originally passed values.
526 mdi
.szClass
= lpClassName
;
527 mdi
.szTitle
= lpWindowName
;
528 mdi
.hOwner
= hInstance
;
534 mdi
.lParam
= (LPARAM
)lpParam
;
536 lpParam
= (LPVOID
)&mdi
;
538 if (pWndParent
->style
& MDIS_ALLCHILDSTYLES
)
540 if (dwStyle
& WS_POPUP
)
542 WARN("WS_POPUP with MDIS_ALLCHILDSTYLES is not allowed\n");
545 dwStyle
|= (WS_CHILD
| WS_CLIPSIBLINGS
);
549 dwStyle
&= ~WS_POPUP
;
550 dwStyle
|= (WS_CHILD
| WS_VISIBLE
| WS_CLIPSIBLINGS
| WS_CAPTION
|
551 WS_SYSMENU
| WS_THICKFRAME
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
);
554 top_child
= GetWindow(hWndParent
, GW_CHILD
);
558 /* Restore current maximized child */
559 if((dwStyle
& WS_VISIBLE
) && IsZoomed(top_child
))
561 TRACE("Restoring current maximized child %p\n", top_child
);
562 SendMessageW( top_child
, WM_SETREDRAW
, FALSE
, 0 );
563 ShowWindow(top_child
, SW_RESTORE
);
564 SendMessageW( top_child
, WM_SETREDRAW
, TRUE
, 0 );
568 MDI_CalcDefaultChildPos(hWndParent
, -1, mPos
, 0, &id
);
570 if (!(dwStyle
& WS_POPUP
)) hMenu
= UlongToHandle(id
);
572 if (dwStyle
& (WS_CHILD
| WS_POPUP
))
574 if (x
== CW_USEDEFAULT
|| x
== CW_USEDEFAULT16
)
579 if (nWidth
== CW_USEDEFAULT
|| nWidth
== CW_USEDEFAULT16
|| !nWidth
)
581 if (nHeight
== CW_USEDEFAULT
|| nHeight
== CW_USEDEFAULT16
|| !nHeight
)
586 hwnd
= User32CreateWindowEx(dwExStyle
,
588 (LPCSTR
)lpWindowName
,
606 DeferWindowPos(HDWP hWinPosInfo
,
608 HWND hWndInsertAfter
,
615 return NtUserDeferWindowPos(hWinPosInfo
, hWnd
, hWndInsertAfter
, x
, y
, cx
, cy
, uFlags
);
623 EndDeferWindowPos(HDWP hWinPosInfo
)
625 return NtUserEndDeferWindowPosEx(hWinPosInfo
, 0);
633 GetDesktopWindow(VOID
)
640 Wnd
= GetThreadDesktopWnd();
642 Ret
= UserHMGetHandle(Wnd
);
644 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
655 User32EnumWindows(HDESK hDesktop
,
662 DWORD i
, dwCount
= 0;
669 SetLastError ( ERROR_INVALID_PARAMETER
);
673 /* FIXME instead of always making two calls, should we use some
674 sort of persistent buffer and only grow it ( requiring a 2nd
675 call ) when the buffer wasn't already big enough? */
676 /* first get how many window entries there are */
677 Status
= NtUserBuildHwndList(hDesktop
,
684 if (!NT_SUCCESS(Status
))
695 /* allocate buffer to receive HWND handles */
696 hHeap
= GetProcessHeap();
697 pHwnd
= HeapAlloc(hHeap
, 0, sizeof(HWND
)*(dwCount
+1));
700 SetLastError ( ERROR_NOT_ENOUGH_MEMORY
);
704 /* now call kernel again to fill the buffer this time */
705 Status
= NtUserBuildHwndList(hDesktop
,
712 if (!NT_SUCCESS(Status
))
715 HeapFree(hHeap
, 0, pHwnd
);
719 /* call the user's callback function until we're done or
720 they tell us to quit */
721 for ( i
= 0; i
< dwCount
; i
++ )
723 /* FIXME I'm only getting NULLs from Thread Enumeration, and it's
724 * probably because I'm not doing it right in NtUserBuildHwndList.
725 * Once that's fixed, we shouldn't have to check for a NULL HWND
727 * This is now fixed in revision 50205. (jt)
729 if (!pHwnd
[i
]) /* don't enumerate a NULL HWND */
731 if (!(*lpfn
)(pHwnd
[i
], lParam
))
733 HeapFree ( hHeap
, 0, pHwnd
);
738 HeapFree(hHeap
, 0, pHwnd
);
747 EnumChildWindows(HWND hWndParent
,
748 WNDENUMPROC lpEnumFunc
,
753 return EnumWindows(lpEnumFunc
, lParam
);
755 return User32EnumWindows(NULL
, hWndParent
, lpEnumFunc
, lParam
, 0, TRUE
);
763 EnumThreadWindows(DWORD dwThreadId
,
768 dwThreadId
= GetCurrentThreadId();
769 return User32EnumWindows(NULL
, NULL
, lpfn
, lParam
, dwThreadId
, FALSE
);
777 EnumWindows(WNDENUMPROC lpEnumFunc
,
780 return User32EnumWindows(NULL
, NULL
, lpEnumFunc
, lParam
, 0, FALSE
);
788 EnumDesktopWindows(HDESK hDesktop
,
792 return User32EnumWindows(hDesktop
, NULL
, lpfn
, lParam
, 0, FALSE
);
800 FindWindowExA(HWND hwndParent
,
805 LPWSTR titleW
= NULL
;
810 DWORD len
= MultiByteToWideChar( CP_ACP
, 0, lpszWindow
, -1, NULL
, 0 );
811 if (!(titleW
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) ))) return 0;
812 MultiByteToWideChar( CP_ACP
, 0, lpszWindow
, -1, titleW
, len
);
815 if (!IS_INTRESOURCE(lpszClass
))
818 if (MultiByteToWideChar( CP_ACP
, 0, lpszClass
, -1, classW
, sizeof(classW
)/sizeof(WCHAR
) ))
819 hwnd
= FindWindowExW( hwndParent
, hwndChildAfter
, classW
, titleW
);
823 hwnd
= FindWindowExW( hwndParent
, hwndChildAfter
, (LPCWSTR
)lpszClass
, titleW
);
826 HeapFree( GetProcessHeap(), 0, titleW
);
835 FindWindowExW(HWND hwndParent
,
840 UNICODE_STRING ucClassName
, *pucClassName
= NULL
;
841 UNICODE_STRING ucWindowName
, *pucWindowName
= NULL
;
843 if (IS_ATOM(lpszClass
))
845 ucClassName
.Length
= 0;
846 ucClassName
.Buffer
= (LPWSTR
)lpszClass
;
847 pucClassName
= &ucClassName
;
849 else if (lpszClass
!= NULL
)
851 RtlInitUnicodeString(&ucClassName
,
853 pucClassName
= &ucClassName
;
856 if (lpszWindow
!= NULL
)
858 RtlInitUnicodeString(&ucWindowName
,
860 pucWindowName
= &ucWindowName
;
863 return NtUserFindWindowEx(hwndParent
,
875 FindWindowA(LPCSTR lpClassName
, LPCSTR lpWindowName
)
877 //FIXME: FindWindow does not search children, but FindWindowEx does.
878 // what should we do about this?
879 return FindWindowExA (NULL
, NULL
, lpClassName
, lpWindowName
);
887 FindWindowW(LPCWSTR lpClassName
, LPCWSTR lpWindowName
)
891 There was a FIXME here earlier, but I think it is just a documentation unclarity.
893 FindWindow only searches top level windows. What they mean is that child
894 windows of other windows than the desktop can be searched.
895 FindWindowExW never does a recursive search.
900 return FindWindowExW(NULL
, NULL
, lpClassName
, lpWindowName
);
909 GetAltTabInfoA(HWND hwnd
,
915 return NtUserGetAltTabInfo(hwnd
,iItem
,pati
,(LPWSTR
)pszItemText
,cchItemText
,TRUE
);
923 GetAltTabInfoW(HWND hwnd
,
929 return NtUserGetAltTabInfo(hwnd
,iItem
,pati
,pszItemText
,cchItemText
,FALSE
);
937 GetAncestor(HWND hwnd
, UINT gaFlags
)
942 Wnd
= ValidateHwnd(hwnd
);
952 if (Wnd
->spwndParent
!= NULL
)
953 Ancestor
= DesktopPtrToUser(Wnd
->spwndParent
);
957 /* FIXME: Call win32k for now */
962 if (Ancestor
!= NULL
)
963 Ret
= UserHMGetHandle(Ancestor
);
965 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
971 if (!Wnd
) /* Fall back */
972 Ret
= NtUserGetAncestor(hwnd
, gaFlags
);
982 GetClientRect(HWND hWnd
, LPRECT lpRect
)
984 PWND Wnd
= ValidateHwnd(hWnd
);
986 if (!Wnd
) return FALSE
;
987 if (Wnd
->style
& WS_MINIMIZED
)
989 lpRect
->left
= lpRect
->top
= 0;
990 lpRect
->right
= GetSystemMetrics(SM_CXMINIMIZED
);
991 lpRect
->bottom
= GetSystemMetrics(SM_CYMINIMIZED
);
994 if ( hWnd
!= GetDesktopWindow()) // Wnd->fnid != FNID_DESKTOP )
996 /* lpRect->left = lpRect->top = 0;
997 lpRect->right = Wnd->rcClient.right - Wnd->rcClient.left;
998 lpRect->bottom = Wnd->rcClient.bottom - Wnd->rcClient.top;
1000 *lpRect
= Wnd
->rcClient
;
1001 OffsetRect(lpRect
, -Wnd
->rcClient
.left
, -Wnd
->rcClient
.top
);
1005 lpRect
->left
= lpRect
->top
= 0;
1006 lpRect
->right
= Wnd
->rcClient
.right
;
1007 lpRect
->bottom
= Wnd
->rcClient
.bottom
;
1008 /* Do this until Init bug is fixed. This sets 640x480, see InitMetrics.
1009 lpRect->right = GetSystemMetrics(SM_CXSCREEN);
1010 lpRect->bottom = GetSystemMetrics(SM_CYSCREEN);
1020 GetLastActivePopup(HWND hWnd
)
1025 Wnd
= ValidateHwnd(hWnd
);
1030 if (Wnd
->spwndLastActive
)
1032 PWND LastActive
= DesktopPtrToUser(Wnd
->spwndLastActive
);
1033 Ret
= UserHMGetHandle(LastActive
);
1036 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1050 GetParent(HWND hWnd
)
1052 PWND Wnd
, WndParent
;
1055 Wnd
= ValidateHwnd(hWnd
);
1061 if (Wnd
->style
& WS_POPUP
)
1063 if (Wnd
->spwndOwner
!= NULL
)
1064 WndParent
= DesktopPtrToUser(Wnd
->spwndOwner
);
1066 else if (Wnd
->style
& WS_CHILD
)
1068 if (Wnd
->spwndParent
!= NULL
)
1069 WndParent
= DesktopPtrToUser(Wnd
->spwndParent
);
1072 if (WndParent
!= NULL
)
1073 Ret
= UserHMGetHandle(WndParent
);
1075 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1090 GetProcessDefaultLayout(DWORD
*pdwDefaultLayout
)
1092 return (BOOL
)NtUserCallOneParam( (DWORD_PTR
)pdwDefaultLayout
, ONEPARAM_ROUTINE_GETPROCDEFLAYOUT
);
1100 GetWindow(HWND hWnd
,
1106 Wnd
= ValidateHwnd(hWnd
);
1116 if (Wnd
->spwndOwner
!= NULL
)
1117 FoundWnd
= DesktopPtrToUser(Wnd
->spwndOwner
);
1121 if(Wnd
->spwndParent
!= NULL
)
1123 FoundWnd
= DesktopPtrToUser(Wnd
->spwndParent
);
1124 if (FoundWnd
->spwndChild
!= NULL
)
1125 FoundWnd
= DesktopPtrToUser(FoundWnd
->spwndChild
);
1129 if (Wnd
->spwndNext
!= NULL
)
1130 FoundWnd
= DesktopPtrToUser(Wnd
->spwndNext
);
1134 if (Wnd
->spwndPrev
!= NULL
)
1135 FoundWnd
= DesktopPtrToUser(Wnd
->spwndPrev
);
1139 if (Wnd
->spwndChild
!= NULL
)
1140 FoundWnd
= DesktopPtrToUser(Wnd
->spwndChild
);
1145 while ( FoundWnd
->spwndNext
!= NULL
)
1146 FoundWnd
= DesktopPtrToUser(FoundWnd
->spwndNext
);
1154 if (FoundWnd
!= NULL
)
1155 Ret
= UserHMGetHandle(FoundWnd
);
1157 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1171 GetTopWindow(HWND hWnd
)
1173 if (!hWnd
) hWnd
= GetDesktopWindow();
1174 return GetWindow(hWnd
, GW_CHILD
);
1184 GetWindowInfo(HWND hWnd
,
1192 if ( !pwi
|| pwi
->cbSize
!= sizeof(WINDOWINFO
))
1193 SetLastError(ERROR_INVALID_PARAMETER
); // Just set the error and go!
1195 pWnd
= ValidateHwnd(hWnd
);
1199 UserGetWindowBorders(pWnd
->style
, pWnd
->ExStyle
, &Size
, FALSE
);
1203 pCls
= DesktopPtrToUser(pWnd
->pcls
);
1204 pwi
->rcWindow
= pWnd
->rcWindow
;
1205 pwi
->rcClient
= pWnd
->rcClient
;
1206 pwi
->dwStyle
= pWnd
->style
;
1207 pwi
->dwExStyle
= pWnd
->ExStyle
;
1208 pwi
->cxWindowBorders
= Size
.cx
;
1209 pwi
->cyWindowBorders
= Size
.cy
;
1210 pwi
->dwWindowStatus
= 0;
1211 if (pWnd
->state
& WNDS_ACTIVEFRAME
|| (GetActiveWindow() == hWnd
))
1212 pwi
->dwWindowStatus
= WS_ACTIVECAPTION
;
1213 pwi
->atomWindowType
= (pCls
? pCls
->atomClassName
: 0 );
1215 if ( pWnd
->state2
& WNDS2_WIN50COMPAT
)
1217 pwi
->wCreatorVersion
= 0x500;
1219 else if ( pWnd
->state2
& WNDS2_WIN40COMPAT
)
1221 pwi
->wCreatorVersion
= 0x400;
1223 else if ( pWnd
->state2
& WNDS2_WIN31COMPAT
)
1225 pwi
->wCreatorVersion
= 0x30A;
1229 pwi
->wCreatorVersion
= 0x300;
1234 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1248 GetWindowModuleFileNameA(HWND hwnd
,
1250 UINT cchFileNameMax
)
1252 PWND Wnd
= ValidateHwnd(hwnd
);
1257 return GetModuleFileNameA(Wnd
->hModule
, lpszFileName
, cchFileNameMax
);
1265 GetWindowModuleFileNameW(HWND hwnd
,
1266 LPWSTR lpszFileName
,
1267 UINT cchFileNameMax
)
1269 PWND Wnd
= ValidateHwnd(hwnd
);
1274 return GetModuleFileNameW( Wnd
->hModule
, lpszFileName
, cchFileNameMax
);
1281 GetWindowRect(HWND hWnd
,
1284 PWND Wnd
= ValidateHwnd(hWnd
);
1286 if (!Wnd
) return FALSE
;
1287 if ( hWnd
!= GetDesktopWindow()) // Wnd->fnid != FNID_DESKTOP )
1289 *lpRect
= Wnd
->rcWindow
;
1293 lpRect
->left
= lpRect
->top
= 0;
1294 lpRect
->right
= Wnd
->rcWindow
.right
;
1295 lpRect
->bottom
= Wnd
->rcWindow
.bottom
;
1296 /* Do this until Init bug is fixed. This sets 640x480, see InitMetrics.
1297 lpRect->right = GetSystemMetrics(SM_CXSCREEN);
1298 lpRect->bottom = GetSystemMetrics(SM_CYSCREEN);
1307 GetWindowTextA(HWND hWnd
, LPSTR lpString
, int nMaxCount
)
1312 if (lpString
== NULL
|| nMaxCount
== 0)
1315 Wnd
= ValidateHwnd(hWnd
);
1321 if (!TestWindowProcess(Wnd
))
1325 Length
= DefWindowProcA(hWnd
, WM_GETTEXT
, nMaxCount
, (LPARAM
)lpString
);
1327 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1335 Length
= SendMessageA(hWnd
, WM_GETTEXT
, nMaxCount
, (LPARAM
)lpString
);
1337 //ERR("GWTA Len %d : %s\n",Length,lpString);
1345 GetWindowTextLengthA(HWND hWnd
)
1349 Wnd
= ValidateHwnd(hWnd
);
1353 if (!TestWindowProcess(Wnd
))
1355 return DefWindowProcA(hWnd
, WM_GETTEXTLENGTH
, 0, 0);
1359 return SendMessageA(hWnd
, WM_GETTEXTLENGTH
, 0, 0);
1367 GetWindowTextLengthW(HWND hWnd
)
1371 Wnd
= ValidateHwnd(hWnd
);
1375 if (!TestWindowProcess(Wnd
))
1377 return DefWindowProcW(hWnd
, WM_GETTEXTLENGTH
, 0, 0);
1381 return SendMessageW(hWnd
, WM_GETTEXTLENGTH
, 0, 0);
1389 GetWindowTextW(HWND hWnd
, LPWSTR lpString
, int nMaxCount
)
1394 if (lpString
== NULL
|| nMaxCount
== 0)
1397 Wnd
= ValidateHwnd(hWnd
);
1401 lpString
[0] = L
'\0';
1403 if (!TestWindowProcess(Wnd
))
1407 Length
= DefWindowProcW(hWnd
, WM_GETTEXT
, nMaxCount
, (LPARAM
)lpString
);
1409 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1417 Length
= SendMessageW(hWnd
, WM_GETTEXT
, nMaxCount
, (LPARAM
)lpString
);
1419 //ERR("GWTW Len %d : %S\n",Length,lpString);
1424 GetWindowThreadProcessId(HWND hWnd
,
1425 LPDWORD lpdwProcessId
)
1429 PWND pWnd
= ValidateHwnd(hWnd
);
1431 if (!pWnd
) return Ret
;
1433 ti
= pWnd
->head
.pti
;
1437 if (ti
== GetW32ThreadInfo())
1438 { // We are current.
1439 //FIXME("Current!\n");
1441 *lpdwProcessId
= (DWORD_PTR
)NtCurrentTeb()->ClientId
.UniqueProcess
;
1442 Ret
= (DWORD_PTR
)NtCurrentTeb()->ClientId
.UniqueThread
;
1445 { // Ask kernel for info.
1446 //FIXME("Kernel call!\n");
1448 *lpdwProcessId
= NtUserQueryWindow(hWnd
, QUERY_WINDOW_UNIQUE_PROCESS_ID
);
1449 Ret
= NtUserQueryWindow(hWnd
, QUERY_WINDOW_UNIQUE_THREAD_ID
);
1460 IsChild(HWND hWndParent
,
1463 PWND WndParent
, DesktopWnd
, Wnd
;
1466 WndParent
= ValidateHwnd(hWndParent
);
1469 Wnd
= ValidateHwnd(hWnd
);
1473 DesktopWnd
= GetThreadDesktopWnd();
1479 while (Wnd
!= NULL
&& ((Wnd
->style
& (WS_POPUP
|WS_CHILD
)) == WS_CHILD
))
1481 if (Wnd
->spwndParent
!= NULL
)
1483 Wnd
= DesktopPtrToUser(Wnd
->spwndParent
);
1485 if (Wnd
== WndParent
)
1495 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1511 PWND Wnd
= ValidateHwnd(hWnd
);
1514 return (Wnd
->style
& WS_MINIMIZE
) != 0;
1526 PWND Wnd
= ValidateHwndNoErr(hWnd
);
1529 if (Wnd
->state
& WNDS_DESTROYED
||
1530 Wnd
->state2
& WNDS2_INDESTROY
)
1543 IsWindowUnicode(HWND hWnd
)
1545 PWND Wnd
= ValidateHwnd(hWnd
);
1548 return Wnd
->Unicode
;
1558 IsWindowVisible(HWND hWnd
)
1561 PWND Wnd
= ValidateHwnd(hWnd
);
1571 if (!(Wnd
->style
& WS_VISIBLE
))
1577 if (Wnd
->spwndParent
!= NULL
)
1578 Wnd
= DesktopPtrToUser(Wnd
->spwndParent
);
1582 } while (Wnd
!= NULL
);
1584 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1599 IsWindowEnabled(HWND hWnd
)
1601 // AG: I don't know if child windows are affected if the parent is
1602 // disabled. I think they stop processing messages but stay appearing
1605 return !(GetWindowLongPtrW(hWnd
, GWL_STYLE
) & WS_DISABLED
);
1615 return (GetWindowLongPtrW(hWnd
, GWL_STYLE
) & WS_MAXIMIZE
) != 0;
1623 LockSetForegroundWindow(UINT uLockCode
)
1625 return NtUserxLockSetForegroundWindow(uLockCode
);
1633 AnimateWindow(HWND hwnd
,
1637 /* FIXME Add animation code */
1639 /* If trying to show/hide and it's already *
1640 * shown/hidden or invalid window, fail with *
1641 * invalid parameter */
1644 visible
= IsWindowVisible(hwnd
);
1645 if(!IsWindow(hwnd
) ||
1646 (visible
&& !(dwFlags
& AW_HIDE
)) ||
1647 (!visible
&& (dwFlags
& AW_HIDE
)))
1649 SetLastError(ERROR_INVALID_PARAMETER
);
1653 ShowWindow(hwnd
, (dwFlags
& AW_HIDE
) ? SW_HIDE
: ((dwFlags
& AW_ACTIVATE
) ? SW_SHOW
: SW_SHOWNA
));
1665 if (!(GetWindowLongPtrW(hWnd
, GWL_STYLE
) & WS_MINIMIZE
))
1668 ShowWindow(hWnd
,SW_RESTORE
);
1677 RealChildWindowFromPoint(HWND hwndParent
,
1678 POINT ptParentClientCoords
)
1680 return NtUserRealChildWindowFromPoint(hwndParent
, ptParentClientCoords
.x
, ptParentClientCoords
.y
);
1687 SetForegroundWindow(HWND hWnd
)
1689 return NtUserxSetForegroundWindow(hWnd
);
1697 SetProcessDefaultLayout(DWORD dwDefaultLayout
)
1699 return NtUserCallOneParam( (DWORD_PTR
)dwDefaultLayout
, ONEPARAM_ROUTINE_SETPROCDEFLAYOUT
);
1709 SetWindowTextA(HWND hWnd
,
1714 pwnd
= ValidateHwnd(hWnd
);
1717 if (!TestWindowProcess(pwnd
))
1719 /* do not send WM_GETTEXT messages to other processes */
1720 return (DefWindowProcA(hWnd
, WM_SETTEXT
, 0, (LPARAM
)lpString
) >= 0);
1722 return (SendMessageA(hWnd
, WM_SETTEXT
, 0, (LPARAM
)lpString
) >= 0);
1734 SetWindowTextW(HWND hWnd
,
1739 pwnd
= ValidateHwnd(hWnd
);
1742 if (!TestWindowProcess(pwnd
))
1744 /* do not send WM_GETTEXT messages to other processes */
1745 return (DefWindowProcW(hWnd
, WM_SETTEXT
, 0, (LPARAM
)lpString
) >= 0);
1747 return (SendMessageW(hWnd
, WM_SETTEXT
, 0, (LPARAM
)lpString
) >= 0);
1757 ShowOwnedPopups(HWND hWnd
, BOOL fShow
)
1759 return NtUserxShowOwnedPopups(hWnd
, fShow
);
1767 UpdateLayeredWindow( HWND hwnd
,
1777 if (dwFlags
& ULW_EX_NORESIZE
) /* only valid for UpdateLayeredWindowIndirect */
1779 SetLastError( ERROR_INVALID_PARAMETER
);
1782 return NtUserUpdateLayeredWindow( hwnd
,
1798 UpdateLayeredWindowIndirect(HWND hwnd
,
1799 const UPDATELAYEREDWINDOWINFO
*info
)
1801 if (info
&& info
->cbSize
== sizeof(*info
))
1803 return NtUserUpdateLayeredWindow( hwnd
,
1805 (POINT
*)info
->pptDst
,
1806 (SIZE
*)info
->psize
,
1808 (POINT
*)info
->pptSrc
,
1810 (BLENDFUNCTION
*)info
->pblend
,
1812 (RECT
*)info
->prcDirty
);
1814 SetLastError(ERROR_INVALID_PARAMETER
);
1822 SetWindowContextHelpId(HWND hwnd
,
1823 DWORD dwContextHelpId
)
1825 return NtUserxSetWindowContextHelpId(hwnd
, dwContextHelpId
);
1832 GetWindowContextHelpId(HWND hwnd
)
1834 return NtUserxGetWindowContextHelpId(hwnd
);
1841 InternalGetWindowText(HWND hWnd
, LPWSTR lpString
, int nMaxCount
)
1843 INT Ret
= NtUserInternalGetWindowText(hWnd
, lpString
, nMaxCount
);
1844 if (Ret
== 0 && lpString
)
1853 IsHungAppWindow(HWND hwnd
)
1855 return (NtUserQueryWindow(hwnd
, QUERY_WINDOW_ISHUNG
) != 0);
1862 SetLastErrorEx(DWORD dwErrCode
, DWORD dwType
)
1864 SetLastError(dwErrCode
);
1873 return (HWND
)NtUserGetThreadState(THREADSTATE_FOCUSWINDOW
);
1877 GetRealWindowOwner(HWND hwnd
)
1879 return NtUserQueryWindow(hwnd
, QUERY_WINDOW_REAL_ID
);
1886 SetTaskmanWindow(HWND hWnd
)
1888 return NtUserxSetTaskmanWindow(hWnd
);
1895 SetProgmanWindow(HWND hWnd
)
1897 return NtUserxSetProgmanWindow(hWnd
);
1904 GetProgmanWindow(VOID
)
1906 return (HWND
)NtUserGetThreadState(THREADSTATE_PROGMANWINDOW
);
1913 GetTaskmanWindow(VOID
)
1915 return (HWND
)NtUserGetThreadState(THREADSTATE_TASKMANWINDOW
);
1922 ScrollWindow(HWND hWnd
,
1926 CONST RECT
*prcClip
)
1928 return NtUserScrollWindowEx(hWnd
,
1935 (lpRect
? 0 : SW_SCROLLCHILDREN
) | (SW_ERASE
|SW_INVALIDATE
|SW_SCROLLWNDDCE
)) != ERROR
;
1938 /* ScrollWindow uses the window DC, ScrollWindowEx doesn't */
1944 ScrollWindowEx(HWND hWnd
,
1947 CONST RECT
*prcScroll
,
1948 CONST RECT
*prcClip
,
1953 if (flags
& SW_SMOOTHSCROLL
)
1955 FIXME("SW_SMOOTHSCROLL not supported.");
1958 return NtUserScrollWindowEx(hWnd
,
1976 HWND
*list
= WIN_ListChildren( GetDesktopWindow() );
1978 if (!list
) return FALSE
;
1979 for (i
= 0; list
[i
]; i
++)
1981 if (IsWindowVisible( list
[i
] ) && GetWindow( list
[i
], GW_OWNER
)) break;
1983 retvalue
= (list
[i
] != 0);
1984 HeapFree( GetProcessHeap(), 0, list
);
1992 IsWindowInDestroy(HWND hWnd
)
1995 pwnd
= ValidateHwnd(hWnd
);
1998 return ((pwnd
->state2
& WNDS2_INDESTROY
) == WNDS2_INDESTROY
);
2005 DisableProcessWindowsGhosting(VOID
)
2007 NtUserxEnableProcessWindowGhosting(FALSE
);