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