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