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