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