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