xref: /reactos/win32ss/user/user32/windows/window.c (revision 1734f297)
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             Wnd->state2 & WNDS2_INDESTROY)
1554            return FALSE;
1555         return TRUE;
1556     }
1557 
1558     return FALSE;
1559 }
1560 
1561 
1562 /*
1563  * @implemented
1564  */
1565 BOOL WINAPI
1566 IsWindowUnicode(HWND hWnd)
1567 {
1568     PWND Wnd = ValidateHwnd(hWnd);
1569 
1570     if (Wnd != NULL)
1571         return Wnd->Unicode;
1572 
1573     return FALSE;
1574 }
1575 
1576 
1577 /*
1578  * @implemented
1579  */
1580 BOOL WINAPI
1581 IsWindowVisible(HWND hWnd)
1582 {
1583     BOOL Ret = FALSE;
1584     PWND Wnd = ValidateHwnd(hWnd);
1585 
1586     if (Wnd != NULL)
1587     {
1588         _SEH2_TRY
1589         {
1590             Ret = TRUE;
1591 
1592             do
1593             {
1594                 if (!(Wnd->style & WS_VISIBLE))
1595                 {
1596                     Ret = FALSE;
1597                     break;
1598                 }
1599 
1600                 if (Wnd->spwndParent != NULL)
1601                     Wnd = DesktopPtrToUser(Wnd->spwndParent);
1602                 else
1603                     break;
1604 
1605             } while (Wnd != NULL);
1606         }
1607         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1608         {
1609             Ret = FALSE;
1610         }
1611         _SEH2_END;
1612     }
1613 
1614     return Ret;
1615 }
1616 
1617 
1618 /*
1619  * @implemented
1620  */
1621 BOOL WINAPI
1622 IsWindowEnabled(HWND hWnd)
1623 {
1624     // AG: I don't know if child windows are affected if the parent is
1625     // disabled. I think they stop processing messages but stay appearing
1626     // as enabled.
1627 
1628     return !(GetWindowLongPtrW(hWnd, GWL_STYLE) & WS_DISABLED);
1629 }
1630 
1631 
1632 /*
1633  * @implemented
1634  */
1635 BOOL WINAPI
1636 IsZoomed(HWND hWnd)
1637 {
1638     return (GetWindowLongPtrW(hWnd, GWL_STYLE) & WS_MAXIMIZE) != 0;
1639 }
1640 
1641 
1642 /*
1643  * @implemented
1644  */
1645 BOOL WINAPI
1646 LockSetForegroundWindow(UINT uLockCode)
1647 {
1648     return NtUserxLockSetForegroundWindow(uLockCode);
1649 }
1650 
1651 
1652 /*
1653  * @implemented
1654  */
1655 BOOL WINAPI
1656 AnimateWindow(HWND hwnd,
1657               DWORD dwTime,
1658               DWORD dwFlags)
1659 {
1660     /* FIXME Add animation code */
1661 
1662     /* If trying to show/hide and it's already   *
1663      * shown/hidden or invalid window, fail with *
1664      * invalid parameter                         */
1665 
1666     BOOL visible;
1667     visible = IsWindowVisible(hwnd);
1668     if(!IsWindow(hwnd) ||
1669        (visible && !(dwFlags & AW_HIDE)) ||
1670        (!visible && (dwFlags & AW_HIDE)))
1671     {
1672         SetLastError(ERROR_INVALID_PARAMETER);
1673         return FALSE;
1674     }
1675 
1676     ShowWindow(hwnd, (dwFlags & AW_HIDE) ? SW_HIDE : ((dwFlags & AW_ACTIVATE) ? SW_SHOW : SW_SHOWNA));
1677 
1678     return TRUE;
1679 }
1680 
1681 
1682 /*
1683  * @implemented
1684  */
1685 BOOL WINAPI
1686 OpenIcon(HWND hWnd)
1687 {
1688     if (!(GetWindowLongPtrW(hWnd, GWL_STYLE) & WS_MINIMIZE))
1689         return FALSE;
1690 
1691     ShowWindow(hWnd,SW_RESTORE);
1692     return TRUE;
1693 }
1694 
1695 
1696 /*
1697  * @implemented
1698  */
1699 HWND WINAPI
1700 RealChildWindowFromPoint(HWND hwndParent,
1701                          POINT ptParentClientCoords)
1702 {
1703     return NtUserRealChildWindowFromPoint(hwndParent, ptParentClientCoords.x, ptParentClientCoords.y);
1704 }
1705 
1706 /*
1707  * @unimplemented
1708  */
1709 BOOL WINAPI
1710 SetForegroundWindow(HWND hWnd)
1711 {
1712     return NtUserxSetForegroundWindow(hWnd);
1713 }
1714 
1715 
1716 /*
1717  * @implemented
1718  */
1719 BOOL WINAPI
1720 SetProcessDefaultLayout(DWORD dwDefaultLayout)
1721 {
1722 return NtUserCallOneParam( (DWORD_PTR)dwDefaultLayout, ONEPARAM_ROUTINE_SETPROCDEFLAYOUT);
1723 }
1724 
1725 
1726 /*
1727  * @implemented
1728  */
1729 BOOL
1730 WINAPI
1731 DECLSPEC_HOTPATCH
1732 SetWindowTextA(HWND hWnd,
1733                LPCSTR lpString)
1734 {
1735   PWND pwnd;
1736 
1737   pwnd = ValidateHwnd(hWnd);
1738   if (pwnd)
1739   {
1740      if (!TestWindowProcess(pwnd))
1741      {
1742         /* do not send WM_GETTEXT messages to other processes */
1743         return (DefWindowProcA(hWnd, WM_SETTEXT, 0, (LPARAM)lpString) >= 0);
1744      }
1745      return (SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)lpString) >= 0);
1746   }
1747   return FALSE;
1748 }
1749 
1750 
1751 /*
1752  * @implemented
1753  */
1754 BOOL
1755 WINAPI
1756 DECLSPEC_HOTPATCH
1757 SetWindowTextW(HWND hWnd,
1758                LPCWSTR lpString)
1759 {
1760   PWND pwnd;
1761 
1762   pwnd = ValidateHwnd(hWnd);
1763   if (pwnd)
1764   {
1765      if (!TestWindowProcess(pwnd))
1766      {
1767         /* do not send WM_GETTEXT messages to other processes */
1768         return (DefWindowProcW(hWnd, WM_SETTEXT, 0, (LPARAM)lpString) >= 0);
1769      }
1770      return (SendMessageW(hWnd, WM_SETTEXT, 0, (LPARAM)lpString) >= 0);
1771   }
1772   return FALSE;
1773 }
1774 
1775 
1776 /*
1777  * @implemented
1778  */
1779 BOOL WINAPI
1780 ShowOwnedPopups(HWND hWnd, BOOL fShow)
1781 {
1782     return NtUserxShowOwnedPopups(hWnd, fShow);
1783 }
1784 
1785 
1786 /*
1787  * @implemented
1788  */
1789 BOOL WINAPI
1790 UpdateLayeredWindow( HWND hwnd,
1791                      HDC hdcDst,
1792                      POINT *pptDst,
1793                      SIZE *psize,
1794                      HDC hdcSrc,
1795                      POINT *pptSrc,
1796                      COLORREF crKey,
1797                      BLENDFUNCTION *pbl,
1798                      DWORD dwFlags)
1799 {
1800   if (dwFlags & ULW_EX_NORESIZE)  /* only valid for UpdateLayeredWindowIndirect */
1801   {
1802      SetLastError( ERROR_INVALID_PARAMETER );
1803      return FALSE;
1804   }
1805   return NtUserUpdateLayeredWindow( hwnd,
1806                                     hdcDst,
1807                                     pptDst,
1808                                     psize,
1809                                     hdcSrc,
1810                                     pptSrc,
1811                                     crKey,
1812                                     pbl,
1813                                     dwFlags,
1814                                     NULL);
1815 }
1816 
1817 /*
1818  * @implemented
1819  */
1820 BOOL WINAPI
1821 UpdateLayeredWindowIndirect(HWND hwnd,
1822                             const UPDATELAYEREDWINDOWINFO *info)
1823 {
1824   if (info && info->cbSize == sizeof(*info))
1825   {
1826      return NtUserUpdateLayeredWindow( hwnd,
1827                                        info->hdcDst,
1828                                        (POINT *)info->pptDst,
1829                                        (SIZE *)info->psize,
1830                                        info->hdcSrc,
1831                                        (POINT *)info->pptSrc,
1832                                        info->crKey,
1833                                        (BLENDFUNCTION *)info->pblend,
1834                                        info->dwFlags,
1835                                        (RECT *)info->prcDirty);
1836   }
1837   SetLastError(ERROR_INVALID_PARAMETER);
1838   return FALSE;
1839 }
1840 
1841 /*
1842  * @implemented
1843  */
1844 BOOL WINAPI
1845 SetWindowContextHelpId(HWND hwnd,
1846                        DWORD dwContextHelpId)
1847 {
1848     return NtUserxSetWindowContextHelpId(hwnd, dwContextHelpId);
1849 }
1850 
1851 /*
1852  * @implemented
1853  */
1854 DWORD WINAPI
1855 GetWindowContextHelpId(HWND hwnd)
1856 {
1857     return NtUserxGetWindowContextHelpId(hwnd);
1858 }
1859 
1860 /*
1861  * @implemented
1862  */
1863 int WINAPI
1864 InternalGetWindowText(HWND hWnd, LPWSTR lpString, int nMaxCount)
1865 {
1866     INT Ret = NtUserInternalGetWindowText(hWnd, lpString, nMaxCount);
1867     if (Ret == 0 && lpString)
1868         *lpString = L'\0';
1869     return Ret;
1870 }
1871 
1872 /*
1873  * @implemented
1874  */
1875 BOOL WINAPI
1876 IsHungAppWindow(HWND hwnd)
1877 {
1878     return !!NtUserQueryWindow(hwnd, QUERY_WINDOW_ISHUNG);
1879 }
1880 
1881 /*
1882  * @implemented
1883  */
1884 VOID WINAPI
1885 SetLastErrorEx(DWORD dwErrCode, DWORD dwType)
1886 {
1887     SetLastError(dwErrCode);
1888 }
1889 
1890 /*
1891  * @implemented
1892  */
1893 HWND WINAPI
1894 GetFocus(VOID)
1895 {
1896     return (HWND)NtUserGetThreadState(THREADSTATE_FOCUSWINDOW);
1897 }
1898 
1899 DWORD WINAPI
1900 GetRealWindowOwner(HWND hwnd)
1901 {
1902     return NtUserQueryWindow(hwnd, QUERY_WINDOW_REAL_ID);
1903 }
1904 
1905 /*
1906  * @implemented
1907  */
1908 HWND WINAPI
1909 SetTaskmanWindow(HWND hWnd)
1910 {
1911     return NtUserxSetTaskmanWindow(hWnd);
1912 }
1913 
1914 /*
1915  * @implemented
1916  */
1917 HWND WINAPI
1918 SetProgmanWindow(HWND hWnd)
1919 {
1920     return NtUserxSetProgmanWindow(hWnd);
1921 }
1922 
1923 /*
1924  * @implemented
1925  */
1926 HWND WINAPI
1927 GetProgmanWindow(VOID)
1928 {
1929     return (HWND)NtUserGetThreadState(THREADSTATE_PROGMANWINDOW);
1930 }
1931 
1932 /*
1933  * @implemented
1934  */
1935 HWND WINAPI
1936 GetTaskmanWindow(VOID)
1937 {
1938     return (HWND)NtUserGetThreadState(THREADSTATE_TASKMANWINDOW);
1939 }
1940 
1941 /*
1942  * @implemented
1943  */
1944 BOOL WINAPI
1945 ScrollWindow(HWND hWnd,
1946              int dx,
1947              int dy,
1948              CONST RECT *lpRect,
1949              CONST RECT *prcClip)
1950 {
1951     return NtUserScrollWindowEx(hWnd,
1952                                 dx,
1953                                 dy,
1954                                 lpRect,
1955                                 prcClip,
1956                                 0,
1957                                 NULL,
1958                                 (lpRect ? 0 : SW_SCROLLCHILDREN) | (SW_ERASE|SW_INVALIDATE|SW_SCROLLWNDDCE)) != ERROR;
1959 }
1960 
1961 /* ScrollWindow uses the window DC, ScrollWindowEx doesn't */
1962 
1963 /*
1964  * @implemented
1965  */
1966 INT WINAPI
1967 ScrollWindowEx(HWND hWnd,
1968                int dx,
1969                int dy,
1970                CONST RECT *prcScroll,
1971                CONST RECT *prcClip,
1972                HRGN hrgnUpdate,
1973                LPRECT prcUpdate,
1974                UINT flags)
1975 {
1976     if (flags & SW_SMOOTHSCROLL)
1977     {
1978        FIXME("SW_SMOOTHSCROLL not supported.\n");
1979        // Fall through....
1980     }
1981     return NtUserScrollWindowEx(hWnd,
1982                                 dx,
1983                                 dy,
1984                                 prcScroll,
1985                                 prcClip,
1986                                 hrgnUpdate,
1987                                 prcUpdate,
1988                                 flags);
1989 }
1990 
1991 /*
1992  * @implemented
1993  */
1994 BOOL WINAPI
1995 AnyPopup(VOID)
1996 {
1997     int i;
1998     BOOL retvalue;
1999     HWND *list = WIN_ListChildren( GetDesktopWindow() );
2000 
2001     if (!list) return FALSE;
2002     for (i = 0; list[i]; i++)
2003     {
2004         if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
2005     }
2006     retvalue = (list[i] != 0);
2007     HeapFree( GetProcessHeap(), 0, list );
2008     return retvalue;
2009 }
2010 
2011 /*
2012  * @implemented
2013  */
2014 BOOL WINAPI
2015 IsWindowInDestroy(HWND hWnd)
2016 {
2017     PWND pwnd;
2018     pwnd = ValidateHwnd(hWnd);
2019     if (!pwnd)
2020        return FALSE;
2021     return ((pwnd->state2 & WNDS2_INDESTROY) == WNDS2_INDESTROY);
2022 }
2023 
2024 /*
2025  * @implemented
2026  */
2027 VOID WINAPI
2028 DisableProcessWindowsGhosting(VOID)
2029 {
2030     NtUserxEnableProcessWindowGhosting(FALSE);
2031 }
2032 
2033 /* EOF */
2034 
2035