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