xref: /reactos/win32ss/user/user32/windows/window.c (revision 8540ab04)
1 /*
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)
8  * UPDATE HISTORY:
9  *      06-06-2001  CSH  Created
10  */
11 
12 #define DEBUG
13 #include <user32.h>
14 
15 WINE_DEFAULT_DEBUG_CHANNEL(user32);
16 
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);
19 
20 /* FUNCTIONS *****************************************************************/
21 
22 
23 NTSTATUS WINAPI
24 User32CallSendAsyncProcForKernel(PVOID Arguments, ULONG ArgumentLength)
25 {
26     PSENDASYNCPROC_CALLBACK_ARGUMENTS CallbackArgs;
27 
28     TRACE("User32CallSendAsyncProcKernel()\n");
29 
30     CallbackArgs = (PSENDASYNCPROC_CALLBACK_ARGUMENTS)Arguments;
31 
32     if (ArgumentLength != sizeof(SENDASYNCPROC_CALLBACK_ARGUMENTS))
33     {
34         return(STATUS_INFO_LENGTH_MISMATCH);
35     }
36 
37     CallbackArgs->Callback(CallbackArgs->Wnd,
38                            CallbackArgs->Msg,
39                            CallbackArgs->Context,
40                            CallbackArgs->Result);
41     return(STATUS_SUCCESS);
42 }
43 
44 
45 /*
46  * @implemented
47  */
48 BOOL WINAPI
49 AllowSetForegroundWindow(DWORD dwProcessId)
50 {
51     return NtUserxAllowSetForegroundWindow(dwProcessId);
52 }
53 
54 
55 /*
56  * @unimplemented
57  */
58 HDWP WINAPI
59 BeginDeferWindowPos(int nNumWindows)
60 {
61     return NtUserxBeginDeferWindowPos(nNumWindows);
62 }
63 
64 
65 /*
66  * @implemented
67  */
68 BOOL WINAPI
69 BringWindowToTop(HWND hWnd)
70 {
71     return NtUserSetWindowPos(hWnd,
72                               HWND_TOP,
73                               0,
74                               0,
75                               0,
76                               0,
77                               SWP_NOSIZE | SWP_NOMOVE);
78 }
79 
80 
81 VOID WINAPI
82 SwitchToThisWindow(HWND hwnd, BOOL fAltTab)
83 {
84     NtUserxSwitchToThisWindow(hwnd, fAltTab);
85 }
86 
87 
88 /*
89  * @implemented
90  */
91 HWND WINAPI
92 ChildWindowFromPoint(HWND hWndParent,
93                      POINT Point)
94 {
95     return (HWND) NtUserChildWindowFromPointEx(hWndParent, Point.x, Point.y, 0);
96 }
97 
98 
99 /*
100  * @implemented
101  */
102 HWND WINAPI
103 ChildWindowFromPointEx(HWND hwndParent,
104                        POINT pt,
105                        UINT uFlags)
106 {
107     return (HWND) NtUserChildWindowFromPointEx(hwndParent, pt.x, pt.y, uFlags);
108 }
109 
110 
111 /*
112  * @implemented
113  */
114 BOOL WINAPI
115 CloseWindow(HWND hWnd)
116 {
117     /* NOTE: CloseWindow does minimizes, and doesn't close. */
118     SetActiveWindow(hWnd);
119     return ShowWindow(hWnd, SW_SHOWMINIMIZED);
120 }
121 
122 FORCEINLINE
123 VOID
124 RtlInitLargeString(
125     OUT PLARGE_STRING plstr,
126     LPCVOID psz,
127     BOOL bUnicode)
128 {
129     if(bUnicode)
130     {
131         RtlInitLargeUnicodeString((PLARGE_UNICODE_STRING)plstr, (PWSTR)psz, 0);
132     }
133     else
134     {
135         RtlInitLargeAnsiString((PLARGE_ANSI_STRING)plstr, (PSTR)psz, 0);
136     }
137 }
138 
139 VOID
140 NTAPI
141 RtlFreeLargeString(
142     IN PLARGE_STRING LargeString)
143 {
144     if (LargeString->Buffer)
145     {
146         RtlFreeHeap(GetProcessHeap(), 0, LargeString->Buffer);
147         RtlZeroMemory(LargeString, sizeof(LARGE_STRING));
148     }
149 }
150 
151 HWND WINAPI
152 User32CreateWindowEx(DWORD dwExStyle,
153                      LPCSTR lpClassName,
154                      LPCSTR lpWindowName,
155                      DWORD dwStyle,
156                      int x,
157                      int y,
158                      int nWidth,
159                      int nHeight,
160                      HWND hWndParent,
161                      HMENU hMenu,
162                      HINSTANCE hInstance,
163                      LPVOID lpParam,
164                      DWORD dwFlags)
165 {
166     LARGE_STRING WindowName;
167     LARGE_STRING lstrClassName, *plstrClassName;
168     LARGE_STRING lstrClassVersion, *plstrClassVersion;
169     UNICODE_STRING ClassName;
170     UNICODE_STRING ClassVersion;
171     WNDCLASSEXA wceA;
172     WNDCLASSEXW wceW;
173     HMODULE hLibModule = NULL;
174     DWORD dwLastError;
175     BOOL Unicode, ClassFound = FALSE;
176     HWND Handle = NULL;
177     LPCWSTR lpszClsVersion;
178     LPCWSTR lpLibFileName = NULL;
179     HANDLE pCtx = NULL;
180 
181 #if 0
182     DbgPrint("[window] User32CreateWindowEx style %d, exstyle %d, parent %d\n", dwStyle, dwExStyle, hWndParent);
183 #endif
184 
185     if (!RegisterDefaultClasses)
186     {
187         TRACE("RegisterSystemControls\n");
188         RegisterSystemControls();
189     }
190 
191     Unicode = !(dwFlags & NUCWE_ANSI);
192 
193     if (IS_ATOM(lpClassName))
194     {
195         plstrClassName = (PVOID)lpClassName;
196     }
197     else
198     {
199         if (Unicode)
200         {
201             RtlInitUnicodeString(&ClassName, (PCWSTR)lpClassName);
202         }
203         else
204         {
205             if (!RtlCreateUnicodeStringFromAsciiz(&ClassName, (PCSZ)lpClassName))
206             {
207                 SetLastError(ERROR_OUTOFMEMORY);
208                 return NULL;
209             }
210         }
211 
212         /* Copy it to a LARGE_STRING */
213         lstrClassName.Buffer = ClassName.Buffer;
214         lstrClassName.Length = ClassName.Length;
215         lstrClassName.MaximumLength = ClassName.MaximumLength;
216         plstrClassName = &lstrClassName;
217     }
218 
219     /* Initialize a LARGE_STRING */
220     RtlInitLargeString(&WindowName, lpWindowName, Unicode);
221 
222     // HACK: The current implementation expects the Window name to be UNICODE
223     if (!Unicode)
224     {
225         NTSTATUS Status;
226         PSTR AnsiBuffer = WindowName.Buffer;
227         ULONG AnsiLength = WindowName.Length;
228 
229         WindowName.Length = 0;
230         WindowName.MaximumLength = AnsiLength * sizeof(WCHAR);
231         WindowName.Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
232                                             0,
233                                             WindowName.MaximumLength);
234         if (!WindowName.Buffer)
235         {
236             SetLastError(ERROR_OUTOFMEMORY);
237             goto cleanup;
238         }
239 
240         Status = RtlMultiByteToUnicodeN(WindowName.Buffer,
241                                         WindowName.MaximumLength,
242                                         &WindowName.Length,
243                                         AnsiBuffer,
244                                         AnsiLength);
245         if (!NT_SUCCESS(Status))
246         {
247             goto cleanup;
248         }
249     }
250 
251     if (!hMenu && (dwStyle & (WS_OVERLAPPEDWINDOW | WS_POPUP)))
252     {
253         if (Unicode)
254         {
255             wceW.cbSize = sizeof(wceW);
256             if (GetClassInfoExW(hInstance, (LPCWSTR)lpClassName, &wceW) && wceW.lpszMenuName)
257             {
258                 hMenu = LoadMenuW(hInstance, wceW.lpszMenuName);
259             }
260         }
261         else
262         {
263             wceA.cbSize = sizeof(wceA);
264             if (GetClassInfoExA(hInstance, lpClassName, &wceA) && wceA.lpszMenuName)
265             {
266                 hMenu = LoadMenuA(hInstance, wceA.lpszMenuName);
267             }
268         }
269     }
270 
271     if (!Unicode) dwExStyle |= WS_EX_SETANSICREATOR;
272 
273     lpszClsVersion = ClassNameToVersion(lpClassName, NULL, &lpLibFileName, &pCtx, !Unicode);
274     if (!lpszClsVersion)
275     {
276         plstrClassVersion = plstrClassName;
277     }
278     else
279     {
280         RtlInitUnicodeString(&ClassVersion, lpszClsVersion);
281         lstrClassVersion.Buffer = ClassVersion.Buffer;
282         lstrClassVersion.Length = ClassVersion.Length;
283         lstrClassVersion.MaximumLength = ClassVersion.MaximumLength;
284         plstrClassVersion = &lstrClassVersion;
285     }
286 
287     for (;;)
288     {
289         Handle = NtUserCreateWindowEx(dwExStyle,
290                                       plstrClassName,
291                                       plstrClassVersion,
292                                       &WindowName,
293                                       dwStyle,
294                                       x,
295                                       y,
296                                       nWidth,
297                                       nHeight,
298                                       hWndParent,
299                                       hMenu,
300                                       hInstance,
301                                       lpParam,
302                                       dwFlags,
303                                       NULL);
304         if (Handle) break;
305         if (!lpLibFileName) break;
306         if (!ClassFound)
307         {
308             dwLastError = GetLastError();
309             if (dwLastError == ERROR_CANNOT_FIND_WND_CLASS)
310             {
311                 ClassFound = VersionRegisterClass(ClassName.Buffer, lpLibFileName, pCtx, &hLibModule);
312                 if (ClassFound) continue;
313             }
314         }
315         if (hLibModule)
316         {
317             dwLastError = GetLastError();
318             FreeLibrary(hLibModule);
319             SetLastError(dwLastError);
320             hLibModule = NULL;
321         }
322         break;
323     }
324 
325 #if 0
326     DbgPrint("[window] NtUserCreateWindowEx() == %d\n", Handle);
327 #endif
328 
329 cleanup:
330     if (!Unicode)
331     {
332         if (!IS_ATOM(lpClassName))
333             RtlFreeUnicodeString(&ClassName);
334 
335         RtlFreeLargeString(&WindowName);
336     }
337 
338     return Handle;
339 }
340 
341 
342 /*
343  * @implemented
344  */
345 HWND
346 WINAPI
347 DECLSPEC_HOTPATCH
348 CreateWindowExA(DWORD dwExStyle,
349                 LPCSTR lpClassName,
350                 LPCSTR lpWindowName,
351                 DWORD dwStyle,
352                 int x,
353                 int y,
354                 int nWidth,
355                 int nHeight,
356                 HWND hWndParent,
357                 HMENU hMenu,
358                 HINSTANCE hInstance,
359                 LPVOID lpParam)
360 {
361     MDICREATESTRUCTA mdi;
362     HWND hwnd;
363 
364     if (!RegisterDefaultClasses)
365     {
366        TRACE("CreateWindowExA RegisterSystemControls\n");
367        RegisterSystemControls();
368     }
369 
370     if (dwExStyle & WS_EX_MDICHILD)
371     {
372         POINT mPos[2];
373         UINT id = 0;
374         HWND top_child;
375         PWND pWndParent;
376 
377         pWndParent = ValidateHwnd(hWndParent);
378 
379         if (!pWndParent) return NULL;
380 
381         if (pWndParent->fnid != FNID_MDICLIENT) // wine uses WIN_ISMDICLIENT
382         {
383            WARN("WS_EX_MDICHILD, but parent %p is not MDIClient\n", hWndParent);
384            return NULL;
385         }
386 
387         /* lpParams of WM_[NC]CREATE is different for MDI children.
388         * MDICREATESTRUCT members have the originally passed values.
389         */
390         mdi.szClass = lpClassName;
391         mdi.szTitle = lpWindowName;
392         mdi.hOwner = hInstance;
393         mdi.x = x;
394         mdi.y = y;
395         mdi.cx = nWidth;
396         mdi.cy = nHeight;
397         mdi.style = dwStyle;
398         mdi.lParam = (LPARAM)lpParam;
399 
400         lpParam = (LPVOID)&mdi;
401 
402         if (pWndParent->style & MDIS_ALLCHILDSTYLES)
403         {
404             if (dwStyle & WS_POPUP)
405             {
406                 WARN("WS_POPUP with MDIS_ALLCHILDSTYLES is not allowed\n");
407                 return(0);
408             }
409             dwStyle |= (WS_CHILD | WS_CLIPSIBLINGS);
410         }
411         else
412         {
413             dwStyle &= ~WS_POPUP;
414             dwStyle |= (WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION |
415                 WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX);
416         }
417 
418         top_child = GetWindow(hWndParent, GW_CHILD);
419 
420         if (top_child)
421         {
422             /* Restore current maximized child */
423             if((dwStyle & WS_VISIBLE) && IsZoomed(top_child))
424             {
425                 TRACE("Restoring current maximized child %p\n", top_child);
426                 SendMessageW( top_child, WM_SETREDRAW, FALSE, 0 );
427                 ShowWindow(top_child, SW_RESTORE);
428                 SendMessageW( top_child, WM_SETREDRAW, TRUE, 0 );
429             }
430         }
431 
432         MDI_CalcDefaultChildPos(hWndParent, -1, mPos, 0, &id);
433 
434         if (!(dwStyle & WS_POPUP)) hMenu = UlongToHandle(id);
435 
436         if (dwStyle & (WS_CHILD | WS_POPUP))
437         {
438             if (x == CW_USEDEFAULT || x == CW_USEDEFAULT16)
439             {
440                 x = mPos[0].x;
441                 y = mPos[0].y;
442             }
443             if (nWidth == CW_USEDEFAULT || nWidth == CW_USEDEFAULT16 || !nWidth)
444                 nWidth = mPos[1].x;
445             if (nHeight == CW_USEDEFAULT || nHeight == CW_USEDEFAULT16 || !nHeight)
446                 nHeight = mPos[1].y;
447         }
448     }
449 
450     hwnd = User32CreateWindowEx(dwExStyle,
451                                 lpClassName,
452                                 lpWindowName,
453                                 dwStyle,
454                                 x,
455                                 y,
456                                 nWidth,
457                                 nHeight,
458                                 hWndParent,
459                                 hMenu,
460                                 hInstance,
461                                 lpParam,
462                                 NUCWE_ANSI);
463     return hwnd;
464 }
465 
466 
467 /*
468  * @implemented
469  */
470 HWND
471 WINAPI
472 DECLSPEC_HOTPATCH
473 CreateWindowExW(DWORD dwExStyle,
474                 LPCWSTR lpClassName,
475                 LPCWSTR lpWindowName,
476                 DWORD dwStyle,
477                 int x,
478                 int y,
479                 int nWidth,
480                 int nHeight,
481                 HWND hWndParent,
482                 HMENU hMenu,
483                 HINSTANCE hInstance,
484                 LPVOID lpParam)
485 {
486     MDICREATESTRUCTW mdi;
487     HWND hwnd;
488 
489     if (!RegisterDefaultClasses)
490     {
491        ERR("CreateWindowExW RegisterSystemControls\n");
492        RegisterSystemControls();
493     }
494 
495     if (dwExStyle & WS_EX_MDICHILD)
496     {
497         POINT mPos[2];
498         UINT id = 0;
499         HWND top_child;
500         PWND pWndParent;
501 
502         pWndParent = ValidateHwnd(hWndParent);
503 
504         if (!pWndParent) return NULL;
505 
506         if (pWndParent->fnid != FNID_MDICLIENT)
507         {
508            WARN("WS_EX_MDICHILD, but parent %p is not MDIClient\n", hWndParent);
509            return NULL;
510         }
511 
512         /* lpParams of WM_[NC]CREATE is different for MDI children.
513         * MDICREATESTRUCT members have the originally passed values.
514         */
515         mdi.szClass = lpClassName;
516         mdi.szTitle = lpWindowName;
517         mdi.hOwner = hInstance;
518         mdi.x = x;
519         mdi.y = y;
520         mdi.cx = nWidth;
521         mdi.cy = nHeight;
522         mdi.style = dwStyle;
523         mdi.lParam = (LPARAM)lpParam;
524 
525         lpParam = (LPVOID)&mdi;
526 
527         if (pWndParent->style & MDIS_ALLCHILDSTYLES)
528         {
529             if (dwStyle & WS_POPUP)
530             {
531                 WARN("WS_POPUP with MDIS_ALLCHILDSTYLES is not allowed\n");
532                 return(0);
533             }
534             dwStyle |= (WS_CHILD | WS_CLIPSIBLINGS);
535         }
536         else
537         {
538             dwStyle &= ~WS_POPUP;
539             dwStyle |= (WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION |
540                 WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX);
541         }
542 
543         top_child = GetWindow(hWndParent, GW_CHILD);
544 
545         if (top_child)
546         {
547             /* Restore current maximized child */
548             if((dwStyle & WS_VISIBLE) && IsZoomed(top_child))
549             {
550                 TRACE("Restoring current maximized child %p\n", top_child);
551                 SendMessageW( top_child, WM_SETREDRAW, FALSE, 0 );
552                 ShowWindow(top_child, SW_RESTORE);
553                 SendMessageW( top_child, WM_SETREDRAW, TRUE, 0 );
554             }
555         }
556 
557         MDI_CalcDefaultChildPos(hWndParent, -1, mPos, 0, &id);
558 
559         if (!(dwStyle & WS_POPUP)) hMenu = UlongToHandle(id);
560 
561         if (dwStyle & (WS_CHILD | WS_POPUP))
562         {
563             if (x == CW_USEDEFAULT || x == CW_USEDEFAULT16)
564             {
565                 x = mPos[0].x;
566                 y = mPos[0].y;
567             }
568             if (nWidth == CW_USEDEFAULT || nWidth == CW_USEDEFAULT16 || !nWidth)
569                 nWidth = mPos[1].x;
570             if (nHeight == CW_USEDEFAULT || nHeight == CW_USEDEFAULT16 || !nHeight)
571                 nHeight = mPos[1].y;
572         }
573     }
574 
575     hwnd = User32CreateWindowEx(dwExStyle,
576                                 (LPCSTR)lpClassName,
577                                 (LPCSTR)lpWindowName,
578                                 dwStyle,
579                                 x,
580                                 y,
581                                 nWidth,
582                                 nHeight,
583                                 hWndParent,
584                                 hMenu,
585                                 hInstance,
586                                 lpParam,
587                                 0);
588     return hwnd;
589 }
590 
591 /*
592  * @unimplemented
593  */
594 HDWP WINAPI
595 DeferWindowPos(HDWP hWinPosInfo,
596                HWND hWnd,
597                HWND hWndInsertAfter,
598                int x,
599                int y,
600                int cx,
601                int cy,
602                UINT uFlags)
603 {
604     return NtUserDeferWindowPos(hWinPosInfo, hWnd, hWndInsertAfter, x, y, cx, cy, uFlags);
605 }
606 
607 
608 /*
609  * @unimplemented
610  */
611 BOOL WINAPI
612 EndDeferWindowPos(HDWP hWinPosInfo)
613 {
614     return NtUserEndDeferWindowPosEx(hWinPosInfo, 0);
615 }
616 
617 
618 /*
619  * @implemented
620  */
621 HWND WINAPI
622 GetDesktopWindow(VOID)
623 {
624     PWND Wnd;
625     HWND Ret = NULL;
626 
627     _SEH2_TRY
628     {
629         Wnd = GetThreadDesktopWnd();
630         if (Wnd != NULL)
631             Ret = UserHMGetHandle(Wnd);
632     }
633     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
634     {
635         /* Do nothing */
636     }
637     _SEH2_END;
638 
639     return Ret;
640 }
641 
642 
643 static BOOL
644 User32EnumWindows(HDESK hDesktop,
645                   HWND hWndparent,
646                   WNDENUMPROC lpfn,
647                   LPARAM lParam,
648                   DWORD dwThreadId,
649                   BOOL bChildren)
650 {
651     DWORD i, dwCount = 0;
652     HWND* pHwnd = NULL;
653     HANDLE hHeap;
654     NTSTATUS Status;
655 
656     if (!lpfn)
657     {
658         SetLastError ( ERROR_INVALID_PARAMETER );
659         return FALSE;
660     }
661 
662     /* FIXME instead of always making two calls, should we use some
663        sort of persistent buffer and only grow it ( requiring a 2nd
664        call ) when the buffer wasn't already big enough? */
665     /* first get how many window entries there are */
666     Status = NtUserBuildHwndList(hDesktop,
667                                  hWndparent,
668                                  bChildren,
669                                  dwThreadId,
670                                  lParam,
671                                  NULL,
672                                  &dwCount);
673     if (!NT_SUCCESS(Status))
674         return FALSE;
675 
676     if (!dwCount)
677     {
678        if (!dwThreadId)
679           return FALSE;
680        else
681           return TRUE;
682     }
683 
684     /* allocate buffer to receive HWND handles */
685     hHeap = GetProcessHeap();
686     pHwnd = HeapAlloc(hHeap, 0, sizeof(HWND)*(dwCount+1));
687     if (!pHwnd)
688     {
689         SetLastError ( ERROR_NOT_ENOUGH_MEMORY );
690         return FALSE;
691     }
692 
693     /* now call kernel again to fill the buffer this time */
694     Status = NtUserBuildHwndList(hDesktop,
695                                  hWndparent,
696                                  bChildren,
697                                  dwThreadId,
698                                  lParam,
699                                  pHwnd,
700                                  &dwCount);
701     if (!NT_SUCCESS(Status))
702     {
703         if (pHwnd)
704             HeapFree(hHeap, 0, pHwnd);
705         return FALSE;
706     }
707 
708     /* call the user's callback function until we're done or
709        they tell us to quit */
710     for ( i = 0; i < dwCount; i++ )
711     {
712         /* FIXME I'm only getting NULLs from Thread Enumeration, and it's
713          * probably because I'm not doing it right in NtUserBuildHwndList.
714          * Once that's fixed, we shouldn't have to check for a NULL HWND
715          * here
716          * This is now fixed in revision 50205. (jt)
717          */
718         if (!pHwnd[i]) /* don't enumerate a NULL HWND */
719             continue;
720         if (!(*lpfn)(pHwnd[i], lParam))
721         {
722             HeapFree ( hHeap, 0, pHwnd );
723             return FALSE;
724         }
725     }
726     if (pHwnd)
727         HeapFree(hHeap, 0, pHwnd);
728     return TRUE;
729 }
730 
731 
732 /*
733  * @implemented
734  */
735 BOOL WINAPI
736 EnumChildWindows(HWND hWndParent,
737                  WNDENUMPROC lpEnumFunc,
738                  LPARAM lParam)
739 {
740     if (!hWndParent)
741     {
742         return EnumWindows(lpEnumFunc, lParam);
743     }
744     return User32EnumWindows(NULL, hWndParent, lpEnumFunc, lParam, 0, TRUE);
745 }
746 
747 
748 /*
749  * @implemented
750  */
751 BOOL WINAPI
752 EnumThreadWindows(DWORD dwThreadId,
753                   WNDENUMPROC lpfn,
754                   LPARAM lParam)
755 {
756     if (!dwThreadId)
757         dwThreadId = GetCurrentThreadId();
758     return User32EnumWindows(NULL, NULL, lpfn, lParam, dwThreadId, FALSE);
759 }
760 
761 
762 /*
763  * @implemented
764  */
765 BOOL WINAPI
766 EnumWindows(WNDENUMPROC lpEnumFunc,
767             LPARAM lParam)
768 {
769     return User32EnumWindows(NULL, NULL, lpEnumFunc, lParam, 0, FALSE);
770 }
771 
772 
773 /*
774  * @implemented
775  */
776 BOOL WINAPI
777 EnumDesktopWindows(HDESK hDesktop,
778                    WNDENUMPROC lpfn,
779                    LPARAM lParam)
780 {
781     return User32EnumWindows(hDesktop, NULL, lpfn, lParam, 0, FALSE);
782 }
783 
784 
785 /*
786  * @implemented
787  */
788 HWND WINAPI
789 FindWindowExA(HWND hwndParent,
790               HWND hwndChildAfter,
791               LPCSTR lpszClass,
792               LPCSTR lpszWindow)
793 {
794     LPWSTR titleW = NULL;
795     HWND hwnd = 0;
796 
797     if (lpszWindow)
798     {
799         DWORD len = MultiByteToWideChar( CP_ACP, 0, lpszWindow, -1, NULL, 0 );
800         if (!(titleW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
801         MultiByteToWideChar( CP_ACP, 0, lpszWindow, -1, titleW, len );
802     }
803 
804     if (!IS_INTRESOURCE(lpszClass))
805     {
806         WCHAR classW[256];
807         if (MultiByteToWideChar( CP_ACP, 0, lpszClass, -1, classW, sizeof(classW)/sizeof(WCHAR) ))
808             hwnd = FindWindowExW( hwndParent, hwndChildAfter, classW, titleW );
809     }
810     else
811     {
812         hwnd = FindWindowExW( hwndParent, hwndChildAfter, (LPCWSTR)lpszClass, titleW );
813     }
814 
815     HeapFree( GetProcessHeap(), 0, titleW );
816     return hwnd;
817 }
818 
819 
820 /*
821  * @implemented
822  */
823 HWND WINAPI
824 FindWindowExW(HWND hwndParent,
825               HWND hwndChildAfter,
826               LPCWSTR lpszClass,
827               LPCWSTR lpszWindow)
828 {
829     UNICODE_STRING ucClassName, *pucClassName = NULL;
830     UNICODE_STRING ucWindowName, *pucWindowName = NULL;
831 
832     if (IS_ATOM(lpszClass))
833     {
834         ucClassName.Length = 0;
835         ucClassName.Buffer = (LPWSTR)lpszClass;
836         pucClassName = &ucClassName;
837     }
838     else if (lpszClass != NULL)
839     {
840         RtlInitUnicodeString(&ucClassName,
841                              lpszClass);
842         pucClassName = &ucClassName;
843     }
844 
845     if (lpszWindow != NULL)
846     {
847         RtlInitUnicodeString(&ucWindowName,
848                              lpszWindow);
849         pucWindowName = &ucWindowName;
850     }
851 
852     return NtUserFindWindowEx(hwndParent,
853                               hwndChildAfter,
854                               pucClassName,
855                               pucWindowName,
856                               0);
857 }
858 
859 
860 /*
861  * @implemented
862  */
863 HWND WINAPI
864 FindWindowA(LPCSTR lpClassName, LPCSTR lpWindowName)
865 {
866     //FIXME: FindWindow does not search children, but FindWindowEx does.
867     //       what should we do about this?
868     return FindWindowExA (NULL, NULL, lpClassName, lpWindowName);
869 }
870 
871 
872 /*
873  * @implemented
874  */
875 HWND WINAPI
876 FindWindowW(LPCWSTR lpClassName, LPCWSTR lpWindowName)
877 {
878     /*
879 
880     There was a FIXME here earlier, but I think it is just a documentation unclarity.
881 
882     FindWindow only searches top level windows. What they mean is that child
883     windows of other windows than the desktop can be searched.
884     FindWindowExW never does a recursive search.
885 
886     / Joakim
887     */
888 
889     return FindWindowExW(NULL, NULL, lpClassName, lpWindowName);
890 }
891 
892 
893 
894 /*
895  * @implemented
896  */
897 BOOL WINAPI
898 GetAltTabInfoA(HWND hwnd,
899                int iItem,
900                PALTTABINFO pati,
901                LPSTR pszItemText,
902                UINT cchItemText)
903 {
904     return NtUserGetAltTabInfo(hwnd,iItem,pati,(LPWSTR)pszItemText,cchItemText,TRUE);
905 }
906 
907 
908 /*
909  * @implemented
910  */
911 BOOL WINAPI
912 GetAltTabInfoW(HWND hwnd,
913                int iItem,
914                PALTTABINFO pati,
915                LPWSTR pszItemText,
916                UINT cchItemText)
917 {
918     return NtUserGetAltTabInfo(hwnd,iItem,pati,pszItemText,cchItemText,FALSE);
919 }
920 
921 
922 /*
923  * @implemented
924  */
925 HWND WINAPI
926 GetAncestor(HWND hwnd, UINT gaFlags)
927 {
928     HWND Ret = NULL;
929     PWND Ancestor, Wnd;
930 
931     Wnd = ValidateHwnd(hwnd);
932     if (!Wnd)
933         return NULL;
934 
935     _SEH2_TRY
936     {
937         Ancestor = NULL;
938         switch (gaFlags)
939         {
940             case GA_PARENT:
941                 if (Wnd->spwndParent != NULL)
942                     Ancestor = DesktopPtrToUser(Wnd->spwndParent);
943                 break;
944 
945             default:
946                 /* FIXME: Call win32k for now */
947                 Wnd = NULL;
948                 break;
949         }
950 
951         if (Ancestor != NULL)
952             Ret = UserHMGetHandle(Ancestor);
953     }
954     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
955     {
956         /* Do nothing */
957     }
958     _SEH2_END;
959 
960     if (!Wnd) /* Fall back */
961         Ret = NtUserGetAncestor(hwnd, gaFlags);
962 
963     return Ret;
964 }
965 
966 
967 /*
968  * @implemented
969  */
970 BOOL WINAPI
971 GetClientRect(HWND hWnd, LPRECT lpRect)
972 {
973     PWND Wnd = ValidateHwnd(hWnd);
974 
975     if (!Wnd) return FALSE;
976     if (Wnd->style & WS_MINIMIZED)
977     {
978        lpRect->left = lpRect->top = 0;
979        lpRect->right = GetSystemMetrics(SM_CXMINIMIZED);
980        lpRect->bottom = GetSystemMetrics(SM_CYMINIMIZED);
981        return TRUE;
982     }
983     if ( hWnd != GetDesktopWindow()) // Wnd->fnid != FNID_DESKTOP )
984     {
985 /*        lpRect->left = lpRect->top = 0;
986         lpRect->right = Wnd->rcClient.right - Wnd->rcClient.left;
987         lpRect->bottom = Wnd->rcClient.bottom - Wnd->rcClient.top;
988 */
989         *lpRect = Wnd->rcClient;
990         OffsetRect(lpRect, -Wnd->rcClient.left, -Wnd->rcClient.top);
991     }
992     else
993     {
994         lpRect->left = lpRect->top = 0;
995         lpRect->right = Wnd->rcClient.right;
996         lpRect->bottom = Wnd->rcClient.bottom;
997 /* Do this until Init bug is fixed. This sets 640x480, see InitMetrics.
998         lpRect->right = GetSystemMetrics(SM_CXSCREEN);
999         lpRect->bottom = GetSystemMetrics(SM_CYSCREEN);
1000 */    }
1001     return TRUE;
1002 }
1003 
1004 
1005 /*
1006  * @implemented
1007  */
1008 HWND WINAPI
1009 GetLastActivePopup(HWND hWnd)
1010 {
1011     PWND Wnd;
1012     HWND Ret = hWnd;
1013 
1014     Wnd = ValidateHwnd(hWnd);
1015     if (Wnd != NULL)
1016     {
1017         _SEH2_TRY
1018         {
1019             if (Wnd->spwndLastActive)
1020             {
1021                PWND LastActive = DesktopPtrToUser(Wnd->spwndLastActive);
1022                Ret = UserHMGetHandle(LastActive);
1023             }
1024         }
1025         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1026         {
1027             /* Do nothing */
1028         }
1029         _SEH2_END;
1030     }
1031     return Ret;
1032 }
1033 
1034 
1035 /*
1036  * @implemented
1037  */
1038 HWND WINAPI
1039 GetParent(HWND hWnd)
1040 {
1041     PWND Wnd, WndParent;
1042     HWND Ret = NULL;
1043 
1044     Wnd = ValidateHwnd(hWnd);
1045     if (Wnd != NULL)
1046     {
1047         _SEH2_TRY
1048         {
1049             WndParent = NULL;
1050             if (Wnd->style & WS_POPUP)
1051             {
1052                 if (Wnd->spwndOwner != NULL)
1053                     WndParent = DesktopPtrToUser(Wnd->spwndOwner);
1054             }
1055             else if (Wnd->style & WS_CHILD)
1056             {
1057                 if (Wnd->spwndParent != NULL)
1058                     WndParent = DesktopPtrToUser(Wnd->spwndParent);
1059             }
1060 
1061             if (WndParent != NULL)
1062                 Ret = UserHMGetHandle(WndParent);
1063         }
1064         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1065         {
1066             /* Do nothing */
1067         }
1068         _SEH2_END;
1069     }
1070 
1071     return Ret;
1072 }
1073 
1074 
1075 /*
1076  * @implemented
1077  */
1078 BOOL WINAPI
1079 GetProcessDefaultLayout(DWORD *pdwDefaultLayout)
1080 {
1081 return (BOOL)NtUserCallOneParam( (DWORD_PTR)pdwDefaultLayout, ONEPARAM_ROUTINE_GETPROCDEFLAYOUT);
1082 }
1083 
1084 
1085 /*
1086  * @implemented
1087  */
1088 HWND WINAPI
1089 GetWindow(HWND hWnd,
1090           UINT uCmd)
1091 {
1092     PWND Wnd, FoundWnd;
1093     HWND Ret = NULL;
1094 
1095     Wnd = ValidateHwnd(hWnd);
1096     if (!Wnd)
1097         return NULL;
1098 
1099     _SEH2_TRY
1100     {
1101         FoundWnd = NULL;
1102         switch (uCmd)
1103         {
1104             case GW_OWNER:
1105                 if (Wnd->spwndOwner != NULL)
1106                     FoundWnd = DesktopPtrToUser(Wnd->spwndOwner);
1107                 break;
1108 
1109             case GW_HWNDFIRST:
1110                 if(Wnd->spwndParent != NULL)
1111                 {
1112                     FoundWnd = DesktopPtrToUser(Wnd->spwndParent);
1113                     if (FoundWnd->spwndChild != NULL)
1114                         FoundWnd = DesktopPtrToUser(FoundWnd->spwndChild);
1115                 }
1116                 break;
1117             case GW_HWNDNEXT:
1118                 if (Wnd->spwndNext != NULL)
1119                     FoundWnd = DesktopPtrToUser(Wnd->spwndNext);
1120                 break;
1121 
1122             case GW_HWNDPREV:
1123                 if (Wnd->spwndPrev != NULL)
1124                     FoundWnd = DesktopPtrToUser(Wnd->spwndPrev);
1125                 break;
1126 
1127             case GW_CHILD:
1128                 if (Wnd->spwndChild != NULL)
1129                     FoundWnd = DesktopPtrToUser(Wnd->spwndChild);
1130                 break;
1131 
1132             case GW_HWNDLAST:
1133                 FoundWnd = Wnd;
1134                 while ( FoundWnd->spwndNext != NULL)
1135                     FoundWnd = DesktopPtrToUser(FoundWnd->spwndNext);
1136                 break;
1137 
1138             default:
1139                 Wnd = NULL;
1140                 break;
1141         }
1142 
1143         if (FoundWnd != NULL)
1144             Ret = UserHMGetHandle(FoundWnd);
1145     }
1146     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1147     {
1148         /* Do nothing */
1149     }
1150     _SEH2_END;
1151 
1152     return Ret;
1153 }
1154 
1155 
1156 /*
1157  * @implemented
1158  */
1159 HWND WINAPI
1160 GetTopWindow(HWND hWnd)
1161 {
1162     if (!hWnd) hWnd = GetDesktopWindow();
1163     return GetWindow(hWnd, GW_CHILD);
1164 }
1165 
1166 
1167 /*
1168  * @implemented
1169  */
1170 BOOL
1171 WINAPI
1172 DECLSPEC_HOTPATCH
1173 GetWindowInfo(HWND hWnd,
1174               PWINDOWINFO pwi)
1175 {
1176     PWND pWnd;
1177     PCLS pCls = NULL;
1178     SIZE Size = {0,0};
1179     BOOL Ret = FALSE;
1180 
1181     if ( !pwi || pwi->cbSize != sizeof(WINDOWINFO))
1182        SetLastError(ERROR_INVALID_PARAMETER); // Just set the error and go!
1183 
1184     pWnd = ValidateHwnd(hWnd);
1185     if (!pWnd)
1186         return Ret;
1187 
1188     UserGetWindowBorders(pWnd->style, pWnd->ExStyle, &Size, FALSE);
1189 
1190     _SEH2_TRY
1191     {
1192        pCls = DesktopPtrToUser(pWnd->pcls);
1193        pwi->rcWindow = pWnd->rcWindow;
1194        pwi->rcClient = pWnd->rcClient;
1195        pwi->dwStyle = pWnd->style;
1196        pwi->dwExStyle = pWnd->ExStyle;
1197        pwi->cxWindowBorders = Size.cx;
1198        pwi->cyWindowBorders = Size.cy;
1199        pwi->dwWindowStatus = 0;
1200        if (pWnd->state & WNDS_ACTIVEFRAME || (GetActiveWindow() == hWnd))
1201           pwi->dwWindowStatus = WS_ACTIVECAPTION;
1202        pwi->atomWindowType = (pCls ? pCls->atomClassName : 0 );
1203 
1204        if ( pWnd->state2 & WNDS2_WIN50COMPAT )
1205        {
1206           pwi->wCreatorVersion = 0x500;
1207        }
1208        else if ( pWnd->state2 & WNDS2_WIN40COMPAT )
1209        {
1210           pwi->wCreatorVersion = 0x400;
1211        }
1212        else if ( pWnd->state2 & WNDS2_WIN31COMPAT )
1213        {
1214           pwi->wCreatorVersion =  0x30A;
1215        }
1216        else
1217        {
1218           pwi->wCreatorVersion = 0x300;
1219        }
1220 
1221        Ret = TRUE;
1222     }
1223     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1224     {
1225         /* Do nothing */
1226     }
1227     _SEH2_END;
1228 
1229    return Ret;
1230 }
1231 
1232 
1233 /*
1234  * @implemented
1235  */
1236 UINT WINAPI
1237 GetWindowModuleFileNameA(HWND hwnd,
1238                          LPSTR lpszFileName,
1239                          UINT cchFileNameMax)
1240 {
1241     PWND Wnd = ValidateHwnd(hwnd);
1242 
1243     if (!Wnd)
1244         return 0;
1245 
1246     return GetModuleFileNameA(Wnd->hModule, lpszFileName, cchFileNameMax);
1247 }
1248 
1249 
1250 /*
1251  * @implemented
1252  */
1253 UINT WINAPI
1254 GetWindowModuleFileNameW(HWND hwnd,
1255                          LPWSTR lpszFileName,
1256                          UINT cchFileNameMax)
1257 {
1258        PWND Wnd = ValidateHwnd(hwnd);
1259 
1260     if (!Wnd)
1261         return 0;
1262 
1263     return GetModuleFileNameW( Wnd->hModule, lpszFileName, cchFileNameMax );
1264 }
1265 
1266 /*
1267  * @implemented
1268  */
1269 BOOL WINAPI
1270 GetWindowRect(HWND hWnd,
1271               LPRECT lpRect)
1272 {
1273     PWND Wnd = ValidateHwnd(hWnd);
1274 
1275     if (!Wnd) return FALSE;
1276     if ( hWnd != GetDesktopWindow()) // Wnd->fnid != FNID_DESKTOP )
1277     {
1278         *lpRect = Wnd->rcWindow;
1279     }
1280     else
1281     {
1282         lpRect->left = lpRect->top = 0;
1283         lpRect->right = Wnd->rcWindow.right;
1284         lpRect->bottom = Wnd->rcWindow.bottom;
1285 /* Do this until Init bug is fixed. This sets 640x480, see InitMetrics.
1286         lpRect->right = GetSystemMetrics(SM_CXSCREEN);
1287         lpRect->bottom = GetSystemMetrics(SM_CYSCREEN);
1288 */    }
1289     return TRUE;
1290 }
1291 
1292 /*
1293  * @implemented
1294  */
1295 int WINAPI
1296 GetWindowTextA(HWND hWnd, LPSTR lpString, int nMaxCount)
1297 {
1298     PWND Wnd;
1299     INT Length = 0;
1300 
1301     if (lpString == NULL || nMaxCount == 0)
1302         return 0;
1303 
1304     Wnd = ValidateHwnd(hWnd);
1305     if (!Wnd)
1306         return 0;
1307 
1308     lpString[0] = '\0';
1309 
1310     if (!TestWindowProcess(Wnd))
1311     {
1312         _SEH2_TRY
1313         {
1314             Length = DefWindowProcA(hWnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
1315         }
1316         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1317         {
1318             Length = 0;
1319         }
1320         _SEH2_END;
1321     }
1322     else
1323     {
1324         Length = SendMessageA(hWnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
1325     }
1326     //ERR("GWTA Len %d : %s\n",Length,lpString);
1327     return Length;
1328 }
1329 
1330 /*
1331  * @implemented
1332  */
1333 int WINAPI
1334 GetWindowTextLengthA(HWND hWnd)
1335 {
1336     PWND Wnd;
1337 
1338     Wnd = ValidateHwnd(hWnd);
1339     if (!Wnd)
1340         return 0;
1341 
1342     if (!TestWindowProcess(Wnd))
1343     {
1344         return DefWindowProcA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1345     }
1346     else
1347     {
1348         return SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1349     }
1350 }
1351 
1352 /*
1353  * @implemented
1354  */
1355 int WINAPI
1356 GetWindowTextLengthW(HWND hWnd)
1357 {
1358     PWND Wnd;
1359 
1360     Wnd = ValidateHwnd(hWnd);
1361     if (!Wnd)
1362         return 0;
1363 
1364     if (!TestWindowProcess(Wnd))
1365     {
1366         return DefWindowProcW(hWnd, WM_GETTEXTLENGTH, 0, 0);
1367     }
1368     else
1369     {
1370         return SendMessageW(hWnd, WM_GETTEXTLENGTH, 0, 0);
1371     }
1372 }
1373 
1374 /*
1375  * @implemented
1376  */
1377 int WINAPI
1378 GetWindowTextW(HWND hWnd, LPWSTR lpString, int nMaxCount)
1379 {
1380     PWND Wnd;
1381     INT Length = 0;
1382 
1383     if (lpString == NULL || nMaxCount == 0)
1384         return 0;
1385 
1386     Wnd = ValidateHwnd(hWnd);
1387     if (!Wnd)
1388         return 0;
1389 
1390     lpString[0] = L'\0';
1391 
1392     if (!TestWindowProcess(Wnd))
1393     {
1394         _SEH2_TRY
1395         {
1396             Length = DefWindowProcW(hWnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
1397         }
1398         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1399         {
1400             Length = 0;
1401         }
1402         _SEH2_END;
1403     }
1404     else
1405     {
1406         Length = SendMessageW(hWnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
1407     }
1408     //ERR("GWTW Len %d : %S\n",Length,lpString);
1409     return Length;
1410 }
1411 
1412 DWORD WINAPI
1413 GetWindowThreadProcessId(HWND hWnd,
1414                          LPDWORD lpdwProcessId)
1415 {
1416     DWORD Ret = 0;
1417     PTHREADINFO ti;
1418     PWND pWnd = ValidateHwnd(hWnd);
1419 
1420     if (!pWnd) return Ret;
1421 
1422     ti = pWnd->head.pti;
1423 
1424     if (ti)
1425     {
1426         if (ti == GetW32ThreadInfo())
1427         { // We are current.
1428           //FIXME("Current!\n");
1429             if (lpdwProcessId)
1430                 *lpdwProcessId = (DWORD_PTR)NtCurrentTeb()->ClientId.UniqueProcess;
1431             Ret = (DWORD_PTR)NtCurrentTeb()->ClientId.UniqueThread;
1432         }
1433         else
1434         { // Ask kernel for info.
1435           //FIXME("Kernel call!\n");
1436             if (lpdwProcessId)
1437                 *lpdwProcessId = NtUserQueryWindow(hWnd, QUERY_WINDOW_UNIQUE_PROCESS_ID);
1438             Ret = NtUserQueryWindow(hWnd, QUERY_WINDOW_UNIQUE_THREAD_ID);
1439         }
1440     }
1441     return Ret;
1442 }
1443 
1444 
1445 /*
1446  * @implemented
1447  */
1448 BOOL WINAPI
1449 IsChild(HWND hWndParent,
1450     HWND hWnd)
1451 {
1452     PWND WndParent, DesktopWnd,  Wnd;
1453     BOOL Ret = FALSE;
1454 
1455     WndParent = ValidateHwnd(hWndParent);
1456     if (!WndParent)
1457         return FALSE;
1458     Wnd = ValidateHwnd(hWnd);
1459     if (!Wnd)
1460         return FALSE;
1461 
1462     DesktopWnd = GetThreadDesktopWnd();
1463     if (!DesktopWnd)
1464         return FALSE;
1465 
1466     _SEH2_TRY
1467     {
1468         while (Wnd != NULL && ((Wnd->style & (WS_POPUP|WS_CHILD)) == WS_CHILD))
1469         {
1470             if (Wnd->spwndParent != NULL)
1471             {
1472                 Wnd = DesktopPtrToUser(Wnd->spwndParent);
1473 
1474                 if (Wnd == WndParent)
1475                 {
1476                     Ret = TRUE;
1477                     break;
1478                 }
1479             }
1480             else
1481                 break;
1482         }
1483     }
1484     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1485     {
1486         /* Do nothing */
1487     }
1488     _SEH2_END;
1489 
1490     return Ret;
1491 }
1492 
1493 
1494 /*
1495  * @implemented
1496  */
1497 BOOL WINAPI
1498 IsIconic(HWND hWnd)
1499 {
1500     PWND Wnd = ValidateHwnd(hWnd);
1501 
1502     if (Wnd != NULL)
1503         return (Wnd->style & WS_MINIMIZE) != 0;
1504 
1505     return FALSE;
1506 }
1507 
1508 
1509 /*
1510  * @implemented
1511  */
1512 BOOL WINAPI
1513 IsWindow(HWND hWnd)
1514 {
1515     PWND Wnd = ValidateHwndNoErr(hWnd);
1516     if (Wnd != NULL)
1517     {
1518         if (Wnd->state & WNDS_DESTROYED ||
1519             Wnd->state2 & WNDS2_INDESTROY)
1520            return FALSE;
1521         return TRUE;
1522     }
1523 
1524     return FALSE;
1525 }
1526 
1527 
1528 /*
1529  * @implemented
1530  */
1531 BOOL WINAPI
1532 IsWindowUnicode(HWND hWnd)
1533 {
1534     PWND Wnd = ValidateHwnd(hWnd);
1535 
1536     if (Wnd != NULL)
1537         return Wnd->Unicode;
1538 
1539     return FALSE;
1540 }
1541 
1542 
1543 /*
1544  * @implemented
1545  */
1546 BOOL WINAPI
1547 IsWindowVisible(HWND hWnd)
1548 {
1549     BOOL Ret = FALSE;
1550     PWND Wnd = ValidateHwnd(hWnd);
1551 
1552     if (Wnd != NULL)
1553     {
1554         _SEH2_TRY
1555         {
1556             Ret = TRUE;
1557 
1558             do
1559             {
1560                 if (!(Wnd->style & WS_VISIBLE))
1561                 {
1562                     Ret = FALSE;
1563                     break;
1564                 }
1565 
1566                 if (Wnd->spwndParent != NULL)
1567                     Wnd = DesktopPtrToUser(Wnd->spwndParent);
1568                 else
1569                     break;
1570 
1571             } while (Wnd != NULL);
1572         }
1573         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1574         {
1575             Ret = FALSE;
1576         }
1577         _SEH2_END;
1578     }
1579 
1580     return Ret;
1581 }
1582 
1583 
1584 /*
1585  * @implemented
1586  */
1587 BOOL WINAPI
1588 IsWindowEnabled(HWND hWnd)
1589 {
1590     // AG: I don't know if child windows are affected if the parent is
1591     // disabled. I think they stop processing messages but stay appearing
1592     // as enabled.
1593 
1594     return !(GetWindowLongPtrW(hWnd, GWL_STYLE) & WS_DISABLED);
1595 }
1596 
1597 
1598 /*
1599  * @implemented
1600  */
1601 BOOL WINAPI
1602 IsZoomed(HWND hWnd)
1603 {
1604     return (GetWindowLongPtrW(hWnd, GWL_STYLE) & WS_MAXIMIZE) != 0;
1605 }
1606 
1607 
1608 /*
1609  * @implemented
1610  */
1611 BOOL WINAPI
1612 LockSetForegroundWindow(UINT uLockCode)
1613 {
1614     return NtUserxLockSetForegroundWindow(uLockCode);
1615 }
1616 
1617 
1618 /*
1619  * @implemented
1620  */
1621 BOOL WINAPI
1622 AnimateWindow(HWND hwnd,
1623               DWORD dwTime,
1624               DWORD dwFlags)
1625 {
1626     /* FIXME Add animation code */
1627 
1628     /* If trying to show/hide and it's already   *
1629      * shown/hidden or invalid window, fail with *
1630      * invalid parameter                         */
1631 
1632     BOOL visible;
1633     visible = IsWindowVisible(hwnd);
1634     if(!IsWindow(hwnd) ||
1635        (visible && !(dwFlags & AW_HIDE)) ||
1636        (!visible && (dwFlags & AW_HIDE)))
1637     {
1638         SetLastError(ERROR_INVALID_PARAMETER);
1639         return FALSE;
1640     }
1641 
1642     ShowWindow(hwnd, (dwFlags & AW_HIDE) ? SW_HIDE : ((dwFlags & AW_ACTIVATE) ? SW_SHOW : SW_SHOWNA));
1643 
1644     return TRUE;
1645 }
1646 
1647 
1648 /*
1649  * @implemented
1650  */
1651 BOOL WINAPI
1652 OpenIcon(HWND hWnd)
1653 {
1654     if (!(GetWindowLongPtrW(hWnd, GWL_STYLE) & WS_MINIMIZE))
1655         return FALSE;
1656 
1657     ShowWindow(hWnd,SW_RESTORE);
1658     return TRUE;
1659 }
1660 
1661 
1662 /*
1663  * @implemented
1664  */
1665 HWND WINAPI
1666 RealChildWindowFromPoint(HWND hwndParent,
1667                          POINT ptParentClientCoords)
1668 {
1669     return NtUserRealChildWindowFromPoint(hwndParent, ptParentClientCoords.x, ptParentClientCoords.y);
1670 }
1671 
1672 /*
1673  * @unimplemented
1674  */
1675 BOOL WINAPI
1676 SetForegroundWindow(HWND hWnd)
1677 {
1678     return NtUserxSetForegroundWindow(hWnd);
1679 }
1680 
1681 
1682 /*
1683  * @implemented
1684  */
1685 BOOL WINAPI
1686 SetProcessDefaultLayout(DWORD dwDefaultLayout)
1687 {
1688 return NtUserCallOneParam( (DWORD_PTR)dwDefaultLayout, ONEPARAM_ROUTINE_SETPROCDEFLAYOUT);
1689 }
1690 
1691 
1692 /*
1693  * @implemented
1694  */
1695 BOOL
1696 WINAPI
1697 DECLSPEC_HOTPATCH
1698 SetWindowTextA(HWND hWnd,
1699                LPCSTR lpString)
1700 {
1701   PWND pwnd;
1702 
1703   pwnd = ValidateHwnd(hWnd);
1704   if (pwnd)
1705   {
1706      if (!TestWindowProcess(pwnd))
1707      {
1708         /* do not send WM_GETTEXT messages to other processes */
1709         return (DefWindowProcA(hWnd, WM_SETTEXT, 0, (LPARAM)lpString) >= 0);
1710      }
1711      return (SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)lpString) >= 0);
1712   }
1713   return FALSE;
1714 }
1715 
1716 
1717 /*
1718  * @implemented
1719  */
1720 BOOL
1721 WINAPI
1722 DECLSPEC_HOTPATCH
1723 SetWindowTextW(HWND hWnd,
1724                LPCWSTR lpString)
1725 {
1726   PWND pwnd;
1727 
1728   pwnd = ValidateHwnd(hWnd);
1729   if (pwnd)
1730   {
1731      if (!TestWindowProcess(pwnd))
1732      {
1733         /* do not send WM_GETTEXT messages to other processes */
1734         return (DefWindowProcW(hWnd, WM_SETTEXT, 0, (LPARAM)lpString) >= 0);
1735      }
1736      return (SendMessageW(hWnd, WM_SETTEXT, 0, (LPARAM)lpString) >= 0);
1737   }
1738   return FALSE;
1739 }
1740 
1741 
1742 /*
1743  * @implemented
1744  */
1745 BOOL WINAPI
1746 ShowOwnedPopups(HWND hWnd, BOOL fShow)
1747 {
1748     return NtUserxShowOwnedPopups(hWnd, fShow);
1749 }
1750 
1751 
1752 /*
1753  * @implemented
1754  */
1755 BOOL WINAPI
1756 UpdateLayeredWindow( HWND hwnd,
1757                      HDC hdcDst,
1758                      POINT *pptDst,
1759                      SIZE *psize,
1760                      HDC hdcSrc,
1761                      POINT *pptSrc,
1762                      COLORREF crKey,
1763                      BLENDFUNCTION *pbl,
1764                      DWORD dwFlags)
1765 {
1766   if (dwFlags & ULW_EX_NORESIZE)  /* only valid for UpdateLayeredWindowIndirect */
1767   {
1768      SetLastError( ERROR_INVALID_PARAMETER );
1769      return FALSE;
1770   }
1771   return NtUserUpdateLayeredWindow( hwnd,
1772                                     hdcDst,
1773                                     pptDst,
1774                                     psize,
1775                                     hdcSrc,
1776                                     pptSrc,
1777                                     crKey,
1778                                     pbl,
1779                                     dwFlags,
1780                                     NULL);
1781 }
1782 
1783 /*
1784  * @implemented
1785  */
1786 BOOL WINAPI
1787 UpdateLayeredWindowIndirect(HWND hwnd,
1788                             const UPDATELAYEREDWINDOWINFO *info)
1789 {
1790   if (info && info->cbSize == sizeof(*info))
1791   {
1792      return NtUserUpdateLayeredWindow( hwnd,
1793                                        info->hdcDst,
1794                                        (POINT *)info->pptDst,
1795                                        (SIZE *)info->psize,
1796                                        info->hdcSrc,
1797                                        (POINT *)info->pptSrc,
1798                                        info->crKey,
1799                                        (BLENDFUNCTION *)info->pblend,
1800                                        info->dwFlags,
1801                                        (RECT *)info->prcDirty);
1802   }
1803   SetLastError(ERROR_INVALID_PARAMETER);
1804   return FALSE;
1805 }
1806 
1807 /*
1808  * @implemented
1809  */
1810 BOOL WINAPI
1811 SetWindowContextHelpId(HWND hwnd,
1812                        DWORD dwContextHelpId)
1813 {
1814     return NtUserxSetWindowContextHelpId(hwnd, dwContextHelpId);
1815 }
1816 
1817 /*
1818  * @implemented
1819  */
1820 DWORD WINAPI
1821 GetWindowContextHelpId(HWND hwnd)
1822 {
1823     return NtUserxGetWindowContextHelpId(hwnd);
1824 }
1825 
1826 /*
1827  * @implemented
1828  */
1829 int WINAPI
1830 InternalGetWindowText(HWND hWnd, LPWSTR lpString, int nMaxCount)
1831 {
1832     INT Ret = NtUserInternalGetWindowText(hWnd, lpString, nMaxCount);
1833     if (Ret == 0 && lpString)
1834         *lpString = L'\0';
1835     return Ret;
1836 }
1837 
1838 /*
1839  * @implemented
1840  */
1841 BOOL WINAPI
1842 IsHungAppWindow(HWND hwnd)
1843 {
1844     return (NtUserQueryWindow(hwnd, QUERY_WINDOW_ISHUNG) != 0);
1845 }
1846 
1847 /*
1848  * @implemented
1849  */
1850 VOID WINAPI
1851 SetLastErrorEx(DWORD dwErrCode, DWORD dwType)
1852 {
1853     SetLastError(dwErrCode);
1854 }
1855 
1856 /*
1857  * @implemented
1858  */
1859 HWND WINAPI
1860 GetFocus(VOID)
1861 {
1862     return (HWND)NtUserGetThreadState(THREADSTATE_FOCUSWINDOW);
1863 }
1864 
1865 DWORD WINAPI
1866 GetRealWindowOwner(HWND hwnd)
1867 {
1868     return NtUserQueryWindow(hwnd, QUERY_WINDOW_REAL_ID);
1869 }
1870 
1871 /*
1872  * @implemented
1873  */
1874 HWND WINAPI
1875 SetTaskmanWindow(HWND hWnd)
1876 {
1877     return NtUserxSetTaskmanWindow(hWnd);
1878 }
1879 
1880 /*
1881  * @implemented
1882  */
1883 HWND WINAPI
1884 SetProgmanWindow(HWND hWnd)
1885 {
1886     return NtUserxSetProgmanWindow(hWnd);
1887 }
1888 
1889 /*
1890  * @implemented
1891  */
1892 HWND WINAPI
1893 GetProgmanWindow(VOID)
1894 {
1895     return (HWND)NtUserGetThreadState(THREADSTATE_PROGMANWINDOW);
1896 }
1897 
1898 /*
1899  * @implemented
1900  */
1901 HWND WINAPI
1902 GetTaskmanWindow(VOID)
1903 {
1904     return (HWND)NtUserGetThreadState(THREADSTATE_TASKMANWINDOW);
1905 }
1906 
1907 /*
1908  * @implemented
1909  */
1910 BOOL WINAPI
1911 ScrollWindow(HWND hWnd,
1912              int dx,
1913              int dy,
1914              CONST RECT *lpRect,
1915              CONST RECT *prcClip)
1916 {
1917     return NtUserScrollWindowEx(hWnd,
1918                                 dx,
1919                                 dy,
1920                                 lpRect,
1921                                 prcClip,
1922                                 0,
1923                                 NULL,
1924                                 (lpRect ? 0 : SW_SCROLLCHILDREN) | (SW_ERASE|SW_INVALIDATE|SW_SCROLLWNDDCE)) != ERROR;
1925 }
1926 
1927 /* ScrollWindow uses the window DC, ScrollWindowEx doesn't */
1928 
1929 /*
1930  * @implemented
1931  */
1932 INT WINAPI
1933 ScrollWindowEx(HWND hWnd,
1934                int dx,
1935                int dy,
1936                CONST RECT *prcScroll,
1937                CONST RECT *prcClip,
1938                HRGN hrgnUpdate,
1939                LPRECT prcUpdate,
1940                UINT flags)
1941 {
1942     if (flags & SW_SMOOTHSCROLL)
1943     {
1944        FIXME("SW_SMOOTHSCROLL not supported.");
1945        // Fall through....
1946     }
1947     return NtUserScrollWindowEx(hWnd,
1948                                 dx,
1949                                 dy,
1950                                 prcScroll,
1951                                 prcClip,
1952                                 hrgnUpdate,
1953                                 prcUpdate,
1954                                 flags);
1955 }
1956 
1957 /*
1958  * @implemented
1959  */
1960 BOOL WINAPI
1961 AnyPopup(VOID)
1962 {
1963     int i;
1964     BOOL retvalue;
1965     HWND *list = WIN_ListChildren( GetDesktopWindow() );
1966 
1967     if (!list) return FALSE;
1968     for (i = 0; list[i]; i++)
1969     {
1970         if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
1971     }
1972     retvalue = (list[i] != 0);
1973     HeapFree( GetProcessHeap(), 0, list );
1974     return retvalue;
1975 }
1976 
1977 /*
1978  * @implemented
1979  */
1980 BOOL WINAPI
1981 IsWindowInDestroy(HWND hWnd)
1982 {
1983     PWND pwnd;
1984     pwnd = ValidateHwnd(hWnd);
1985     if (!pwnd)
1986        return FALSE;
1987     return ((pwnd->state2 & WNDS2_INDESTROY) == WNDS2_INDESTROY);
1988 }
1989 
1990 /*
1991  * @implemented
1992  */
1993 VOID WINAPI
1994 DisableProcessWindowsGhosting(VOID)
1995 {
1996     NtUserxEnableProcessWindowGhosting(FALSE);
1997 }
1998 
1999 /* EOF */
2000 
2001