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