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