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