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