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