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