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