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