- Fix a FIXME and fix the last test in wine Win test_ShowWindow.
[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 LPWSTR titleW = NULL;
748 HWND hwnd = 0;
749
750 if (lpszWindow)
751 {
752 DWORD len = MultiByteToWideChar( CP_ACP, 0, lpszWindow, -1, NULL, 0 );
753 if (!(titleW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
754 MultiByteToWideChar( CP_ACP, 0, lpszWindow, -1, titleW, len );
755 }
756
757 if (!IS_INTRESOURCE(lpszClass))
758 {
759 WCHAR classW[256];
760 if (MultiByteToWideChar( CP_ACP, 0, lpszClass, -1, classW, sizeof(classW)/sizeof(WCHAR) ))
761 hwnd = FindWindowExW( hwndParent, hwndChildAfter, classW, titleW );
762 }
763 else
764 {
765 hwnd = FindWindowExW( hwndParent, hwndChildAfter, (LPCWSTR)lpszClass, titleW );
766 }
767
768 HeapFree( GetProcessHeap(), 0, titleW );
769 return hwnd;
770 }
771
772
773 /*
774 * @implemented
775 */
776 HWND WINAPI
777 FindWindowExW(HWND hwndParent,
778 HWND hwndChildAfter,
779 LPCWSTR lpszClass,
780 LPCWSTR lpszWindow)
781 {
782 UNICODE_STRING ucClassName, *pucClassName = NULL;
783 UNICODE_STRING ucWindowName, *pucWindowName = NULL;
784
785 if (IS_ATOM(lpszClass))
786 {
787 ucClassName.Length = 0;
788 ucClassName.Buffer = (LPWSTR)lpszClass;
789 pucClassName = &ucClassName;
790 }
791 else if (lpszClass != NULL)
792 {
793 RtlInitUnicodeString(&ucClassName,
794 lpszClass);
795 pucClassName = &ucClassName;
796 }
797
798 if (lpszWindow != NULL)
799 {
800 RtlInitUnicodeString(&ucWindowName,
801 lpszWindow);
802 pucWindowName = &ucWindowName;
803 }
804
805 return NtUserFindWindowEx(hwndParent,
806 hwndChildAfter,
807 pucClassName,
808 pucWindowName,
809 0);
810 }
811
812
813 /*
814 * @implemented
815 */
816 HWND WINAPI
817 FindWindowA(LPCSTR lpClassName, LPCSTR lpWindowName)
818 {
819 //FIXME: FindWindow does not search children, but FindWindowEx does.
820 // what should we do about this?
821 return FindWindowExA (NULL, NULL, lpClassName, lpWindowName);
822 }
823
824
825 /*
826 * @implemented
827 */
828 HWND WINAPI
829 FindWindowW(LPCWSTR lpClassName, LPCWSTR lpWindowName)
830 {
831 /*
832
833 There was a FIXME here earlier, but I think it is just a documentation unclarity.
834
835 FindWindow only searches top level windows. What they mean is that child
836 windows of other windows than the desktop can be searched.
837 FindWindowExW never does a recursive search.
838
839 / Joakim
840 */
841
842 return FindWindowExW(NULL, NULL, lpClassName, lpWindowName);
843 }
844
845
846
847 /*
848 * @unimplemented
849 */
850 BOOL WINAPI
851 GetAltTabInfoA(HWND hwnd,
852 int iItem,
853 PALTTABINFO pati,
854 LPSTR pszItemText,
855 UINT cchItemText)
856 {
857 UNIMPLEMENTED;
858 return FALSE;
859 }
860
861
862 /*
863 * @unimplemented
864 */
865 BOOL WINAPI
866 GetAltTabInfoW(HWND hwnd,
867 int iItem,
868 PALTTABINFO pati,
869 LPWSTR pszItemText,
870 UINT cchItemText)
871 {
872 UNIMPLEMENTED;
873 return FALSE;
874 }
875
876
877 /*
878 * @implemented
879 */
880 HWND WINAPI
881 GetAncestor(HWND hwnd, UINT gaFlags)
882 {
883 HWND Ret = NULL;
884 PWND Ancestor, Wnd;
885
886 Wnd = ValidateHwnd(hwnd);
887 if (!Wnd)
888 return NULL;
889
890 _SEH2_TRY
891 {
892 Ancestor = NULL;
893 switch (gaFlags)
894 {
895 case GA_PARENT:
896 if (Wnd->spwndParent != NULL)
897 Ancestor = DesktopPtrToUser(Wnd->spwndParent);
898 break;
899
900 default:
901 /* FIXME: Call win32k for now */
902 Wnd = NULL;
903 break;
904 }
905
906 if (Ancestor != NULL)
907 Ret = UserHMGetHandle(Ancestor);
908 }
909 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
910 {
911 /* Do nothing */
912 }
913 _SEH2_END;
914
915 if (!Wnd) /* Fall back */
916 Ret = NtUserGetAncestor(hwnd, gaFlags);
917
918 return Ret;
919 }
920
921
922 /*
923 * @implemented
924 */
925 BOOL WINAPI
926 GetClientRect(HWND hWnd, LPRECT lpRect)
927 {
928 PWND Wnd = ValidateHwnd(hWnd);
929
930 if (!Wnd) return FALSE;
931 if (Wnd->style & WS_MINIMIZED)
932 {
933 lpRect->left = lpRect->top = 0;
934 lpRect->right = GetSystemMetrics(SM_CXMINIMIZED);
935 lpRect->bottom = GetSystemMetrics(SM_CYMINIMIZED);
936 return TRUE;
937 }
938 if ( hWnd != GetDesktopWindow()) // Wnd->fnid != FNID_DESKTOP )
939 {
940 /* lpRect->left = lpRect->top = 0;
941 lpRect->right = Wnd->rcClient.right - Wnd->rcClient.left;
942 lpRect->bottom = Wnd->rcClient.bottom - Wnd->rcClient.top;
943 */
944 *lpRect = Wnd->rcClient;
945 OffsetRect(lpRect, -Wnd->rcClient.left, -Wnd->rcClient.top);
946 }
947 else
948 {
949 lpRect->left = lpRect->top = 0;
950 lpRect->right = Wnd->rcClient.right;
951 lpRect->bottom = Wnd->rcClient.bottom;
952 /* Do this until Init bug is fixed. This sets 640x480, see InitMetrics.
953 lpRect->right = GetSystemMetrics(SM_CXSCREEN);
954 lpRect->bottom = GetSystemMetrics(SM_CYSCREEN);
955 */ }
956 return TRUE;
957 }
958
959
960 /*
961 * @implemented
962 */
963 HWND WINAPI
964 GetLastActivePopup(HWND hWnd)
965 {
966 PWND Wnd;
967 HWND Ret = hWnd;
968
969 Wnd = ValidateHwnd(hWnd);
970 if (Wnd != NULL)
971 {
972 _SEH2_TRY
973 {
974 if (Wnd->spwndLastActive)
975 {
976 PWND LastActive = DesktopPtrToUser(Wnd->spwndLastActive);
977 Ret = UserHMGetHandle(LastActive);
978 }
979 }
980 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
981 {
982 /* Do nothing */
983 }
984 _SEH2_END;
985 }
986 return Ret;
987 }
988
989
990 /*
991 * @implemented
992 */
993 HWND WINAPI
994 GetParent(HWND hWnd)
995 {
996 PWND Wnd, WndParent;
997 HWND Ret = NULL;
998
999 Wnd = ValidateHwnd(hWnd);
1000 if (Wnd != NULL)
1001 {
1002 _SEH2_TRY
1003 {
1004 WndParent = NULL;
1005 if (Wnd->style & WS_POPUP)
1006 {
1007 if (Wnd->spwndOwner != NULL)
1008 WndParent = DesktopPtrToUser(Wnd->spwndOwner);
1009 }
1010 else if (Wnd->style & WS_CHILD)
1011 {
1012 if (Wnd->spwndParent != NULL)
1013 WndParent = DesktopPtrToUser(Wnd->spwndParent);
1014 }
1015
1016 if (WndParent != NULL)
1017 Ret = UserHMGetHandle(WndParent);
1018 }
1019 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1020 {
1021 /* Do nothing */
1022 }
1023 _SEH2_END;
1024 }
1025
1026 return Ret;
1027 }
1028
1029
1030 /*
1031 * @implemented
1032 */
1033 BOOL WINAPI
1034 GetProcessDefaultLayout(DWORD *pdwDefaultLayout)
1035 {
1036 return (BOOL)NtUserCallOneParam( (DWORD_PTR)pdwDefaultLayout, ONEPARAM_ROUTINE_GETPROCDEFLAYOUT);
1037 }
1038
1039
1040 /*
1041 * @implemented
1042 */
1043 HWND WINAPI
1044 GetWindow(HWND hWnd,
1045 UINT uCmd)
1046 {
1047 PWND Wnd, FoundWnd;
1048 HWND Ret = NULL;
1049
1050 Wnd = ValidateHwnd(hWnd);
1051 if (!Wnd)
1052 return NULL;
1053
1054 _SEH2_TRY
1055 {
1056 FoundWnd = NULL;
1057 switch (uCmd)
1058 {
1059 case GW_OWNER:
1060 if (Wnd->spwndOwner != NULL)
1061 FoundWnd = DesktopPtrToUser(Wnd->spwndOwner);
1062 break;
1063
1064 case GW_HWNDFIRST:
1065 if(Wnd->spwndParent != NULL)
1066 {
1067 FoundWnd = DesktopPtrToUser(Wnd->spwndParent);
1068 if (FoundWnd->spwndChild != NULL)
1069 FoundWnd = DesktopPtrToUser(FoundWnd->spwndChild);
1070 }
1071 break;
1072 case GW_HWNDNEXT:
1073 if (Wnd->spwndNext != NULL)
1074 FoundWnd = DesktopPtrToUser(Wnd->spwndNext);
1075 break;
1076
1077 case GW_HWNDPREV:
1078 if (Wnd->spwndPrev != NULL)
1079 FoundWnd = DesktopPtrToUser(Wnd->spwndPrev);
1080 break;
1081
1082 case GW_CHILD:
1083 if (Wnd->spwndChild != NULL)
1084 FoundWnd = DesktopPtrToUser(Wnd->spwndChild);
1085 break;
1086
1087 case GW_HWNDLAST:
1088 FoundWnd = Wnd;
1089 while ( FoundWnd->spwndNext != NULL)
1090 FoundWnd = DesktopPtrToUser(FoundWnd->spwndNext);
1091 break;
1092
1093 default:
1094 Wnd = NULL;
1095 break;
1096 }
1097
1098 if (FoundWnd != NULL)
1099 Ret = UserHMGetHandle(FoundWnd);
1100 }
1101 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1102 {
1103 /* Do nothing */
1104 }
1105 _SEH2_END;
1106
1107 return Ret;
1108 }
1109
1110
1111 /*
1112 * @implemented
1113 */
1114 HWND WINAPI
1115 GetTopWindow(HWND hWnd)
1116 {
1117 if (!hWnd) hWnd = GetDesktopWindow();
1118 return GetWindow(hWnd, GW_CHILD);
1119 }
1120
1121
1122 /*
1123 * @implemented
1124 */
1125 BOOL WINAPI
1126 GetWindowInfo(HWND hWnd,
1127 PWINDOWINFO pwi)
1128 {
1129 PWND pWnd;
1130 PCLS pCls = NULL;
1131 SIZE Size = {0,0};
1132 BOOL Ret = FALSE;
1133
1134 if ( !pwi || pwi->cbSize != sizeof(WINDOWINFO))
1135 SetLastError(ERROR_INVALID_PARAMETER); // Just set the error and go!
1136
1137 pWnd = ValidateHwnd(hWnd);
1138 if (!pWnd)
1139 return Ret;
1140
1141 UserGetWindowBorders(pWnd->style, pWnd->ExStyle, &Size, FALSE);
1142
1143 _SEH2_TRY
1144 {
1145 pCls = DesktopPtrToUser(pWnd->pcls);
1146 pwi->rcWindow = pWnd->rcWindow;
1147 pwi->rcClient = pWnd->rcClient;
1148 pwi->dwStyle = pWnd->style;
1149 pwi->dwExStyle = pWnd->ExStyle;
1150 pwi->cxWindowBorders = Size.cx;
1151 pwi->cyWindowBorders = Size.cy;
1152 pwi->dwWindowStatus = 0;
1153 if (pWnd->state & WNDS_ACTIVEFRAME)
1154 pwi->dwWindowStatus = WS_ACTIVECAPTION;
1155 pwi->atomWindowType = (pCls ? pCls->atomClassName : 0 );
1156
1157 if ( pWnd->state2 & WNDS2_WIN50COMPAT )
1158 {
1159 pwi->wCreatorVersion = 0x500;
1160 }
1161 else if ( pWnd->state2 & WNDS2_WIN40COMPAT )
1162 {
1163 pwi->wCreatorVersion = 0x400;
1164 }
1165 else if ( pWnd->state2 & WNDS2_WIN31COMPAT )
1166 {
1167 pwi->wCreatorVersion = 0x30A;
1168 }
1169 else
1170 {
1171 pwi->wCreatorVersion = 0x300;
1172 }
1173
1174 Ret = TRUE;
1175 }
1176 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1177 {
1178 /* Do nothing */
1179 }
1180 _SEH2_END;
1181
1182 return Ret;
1183 }
1184
1185
1186 /*
1187 * @implemented
1188 */
1189 UINT WINAPI
1190 GetWindowModuleFileNameA(HWND hwnd,
1191 LPSTR lpszFileName,
1192 UINT cchFileNameMax)
1193 {
1194 PWND Wnd = ValidateHwnd(hwnd);
1195
1196 if (!Wnd)
1197 return 0;
1198
1199 return GetModuleFileNameA(Wnd->hModule, lpszFileName, cchFileNameMax);
1200 }
1201
1202
1203 /*
1204 * @implemented
1205 */
1206 UINT WINAPI
1207 GetWindowModuleFileNameW(HWND hwnd,
1208 LPWSTR lpszFileName,
1209 UINT cchFileNameMax)
1210 {
1211 PWND Wnd = ValidateHwnd(hwnd);
1212
1213 if (!Wnd)
1214 return 0;
1215
1216 return GetModuleFileNameW( Wnd->hModule, lpszFileName, cchFileNameMax );
1217 }
1218
1219
1220 /*
1221 * @implemented
1222 */
1223 BOOL WINAPI
1224 GetWindowRect(HWND hWnd,
1225 LPRECT lpRect)
1226 {
1227 PWND Wnd = ValidateHwnd(hWnd);
1228
1229 if (!Wnd) return FALSE;
1230 if ( hWnd != GetDesktopWindow()) // Wnd->fnid != FNID_DESKTOP )
1231 {
1232 *lpRect = Wnd->rcWindow;
1233 }
1234 else
1235 {
1236 lpRect->left = lpRect->top = 0;
1237 lpRect->right = Wnd->rcWindow.right;
1238 lpRect->bottom = Wnd->rcWindow.bottom;
1239 /* Do this until Init bug is fixed. This sets 640x480, see InitMetrics.
1240 lpRect->right = GetSystemMetrics(SM_CXSCREEN);
1241 lpRect->bottom = GetSystemMetrics(SM_CYSCREEN);
1242 */ }
1243 return TRUE;
1244 }
1245
1246
1247 /*
1248 * @implemented
1249 */
1250 int WINAPI
1251 GetWindowTextA(HWND hWnd, LPSTR lpString, int nMaxCount)
1252 {
1253 PWND Wnd;
1254 PCWSTR Buffer;
1255 INT Length = 0;
1256
1257 if (lpString == NULL)
1258 return 0;
1259
1260 Wnd = ValidateHwnd(hWnd);
1261 if (!Wnd)
1262 return 0;
1263
1264 _SEH2_TRY
1265 {
1266 if (!TestWindowProcess( Wnd))
1267 {
1268 if (nMaxCount > 0)
1269 {
1270 /* do not send WM_GETTEXT messages to other processes */
1271 Length = Wnd->strName.Length / sizeof(WCHAR);
1272 if (Length != 0)
1273 {
1274 Buffer = DesktopPtrToUser(Wnd->strName.Buffer);
1275 if (Buffer != NULL)
1276 {
1277 if (!WideCharToMultiByte(CP_ACP,
1278 0,
1279 Buffer,
1280 Length + 1,
1281 lpString,
1282 nMaxCount,
1283 NULL,
1284 NULL))
1285 {
1286 lpString[nMaxCount - 1] = '\0';
1287 }
1288 }
1289 else
1290 {
1291 Length = 0;
1292 lpString[0] = '\0';
1293 }
1294 }
1295 else
1296 lpString[0] = '\0';
1297 }
1298
1299 Wnd = NULL; /* Don't send a message */
1300 }
1301 }
1302 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1303 {
1304 lpString[0] = '\0';
1305 Length = 0;
1306 Wnd = NULL; /* Don't send a message */
1307 }
1308 _SEH2_END;
1309
1310 if (Wnd != NULL)
1311 Length = SendMessageA(hWnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
1312
1313 return Length;
1314 }
1315
1316
1317 /*
1318 * @implemented
1319 */
1320 int WINAPI
1321 GetWindowTextLengthA(HWND hWnd)
1322 {
1323 return(SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0));
1324 }
1325
1326
1327 /*
1328 * @implemented
1329 */
1330 int WINAPI
1331 GetWindowTextLengthW(HWND hWnd)
1332 {
1333 return(SendMessageW(hWnd, WM_GETTEXTLENGTH, 0, 0));
1334 }
1335
1336
1337 /*
1338 * @implemented
1339 */
1340 int WINAPI
1341 GetWindowTextW(HWND hWnd, LPWSTR lpString, int nMaxCount)
1342 {
1343 PWND Wnd;
1344 PCWSTR Buffer;
1345 INT Length = 0;
1346
1347 if (lpString == NULL)
1348 return 0;
1349
1350 Wnd = ValidateHwnd(hWnd);
1351 if (!Wnd)
1352 return 0;
1353
1354 _SEH2_TRY
1355 {
1356 if (!TestWindowProcess( Wnd))
1357 {
1358 if (nMaxCount > 0)
1359 {
1360 /* do not send WM_GETTEXT messages to other processes */
1361 Length = Wnd->strName.Length / sizeof(WCHAR);
1362 if (Length != 0)
1363 {
1364 Buffer = DesktopPtrToUser(Wnd->strName.Buffer);
1365 if (Buffer != NULL)
1366 {
1367 RtlCopyMemory(lpString,
1368 Buffer,
1369 (Length + 1) * sizeof(WCHAR));
1370 }
1371 else
1372 {
1373 Length = 0;
1374 lpString[0] = '\0';
1375 }
1376 }
1377 else
1378 lpString[0] = '\0';
1379 }
1380
1381 Wnd = NULL; /* Don't send a message */
1382 }
1383 }
1384 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1385 {
1386 lpString[0] = '\0';
1387 Length = 0;
1388 Wnd = NULL; /* Don't send a message */
1389 }
1390 _SEH2_END;
1391
1392 if (Wnd != NULL)
1393 Length = SendMessageW(hWnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
1394
1395 return Length;
1396 }
1397
1398 DWORD WINAPI
1399 GetWindowThreadProcessId(HWND hWnd,
1400 LPDWORD lpdwProcessId)
1401 {
1402 DWORD Ret = 0;
1403 PTHREADINFO ti;
1404 PWND pWnd = ValidateHwnd(hWnd);
1405
1406 if (!pWnd) return Ret;
1407
1408 ti = pWnd->head.pti;
1409
1410 if (ti)
1411 {
1412 if (ti == GetW32ThreadInfo())
1413 { // We are current.
1414 //FIXME("Current!\n");
1415 if (lpdwProcessId)
1416 *lpdwProcessId = (DWORD_PTR)NtCurrentTeb()->ClientId.UniqueProcess;
1417 Ret = (DWORD_PTR)NtCurrentTeb()->ClientId.UniqueThread;
1418 }
1419 else
1420 { // Ask kernel for info.
1421 //FIXME("Kernel call!\n");
1422 if (lpdwProcessId)
1423 *lpdwProcessId = NtUserQueryWindow(hWnd, QUERY_WINDOW_UNIQUE_PROCESS_ID);
1424 Ret = NtUserQueryWindow(hWnd, QUERY_WINDOW_UNIQUE_THREAD_ID);
1425 }
1426 }
1427 return Ret;
1428 }
1429
1430
1431 /*
1432 * @implemented
1433 */
1434 BOOL WINAPI
1435 IsChild(HWND hWndParent,
1436 HWND hWnd)
1437 {
1438 PWND WndParent, DesktopWnd, Wnd;
1439 BOOL Ret = FALSE;
1440
1441 WndParent = ValidateHwnd(hWndParent);
1442 if (!WndParent)
1443 return FALSE;
1444 Wnd = ValidateHwnd(hWnd);
1445 if (!Wnd)
1446 return FALSE;
1447
1448 DesktopWnd = GetThreadDesktopWnd();
1449 if (!DesktopWnd)
1450 return FALSE;
1451
1452 _SEH2_TRY
1453 {
1454 while (Wnd != NULL && ((Wnd->style & (WS_POPUP|WS_CHILD)) == WS_CHILD))
1455 {
1456 if (Wnd->spwndParent != NULL)
1457 {
1458 Wnd = DesktopPtrToUser(Wnd->spwndParent);
1459
1460 if (Wnd == WndParent)
1461 {
1462 Ret = TRUE;
1463 break;
1464 }
1465 }
1466 else
1467 break;
1468 }
1469 }
1470 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1471 {
1472 /* Do nothing */
1473 }
1474 _SEH2_END;
1475
1476 return Ret;
1477 }
1478
1479
1480 /*
1481 * @implemented
1482 */
1483 BOOL WINAPI
1484 IsIconic(HWND hWnd)
1485 {
1486 PWND Wnd = ValidateHwnd(hWnd);
1487
1488 if (Wnd != NULL)
1489 return (Wnd->style & WS_MINIMIZE) != 0;
1490
1491 return FALSE;
1492 }
1493
1494
1495 /*
1496 * @implemented
1497 */
1498 BOOL WINAPI
1499 IsWindow(HWND hWnd)
1500 {
1501 PWND Wnd = ValidateHwndNoErr(hWnd);
1502 if (Wnd != NULL)
1503 {
1504 if (Wnd->state & WNDS_DESTROYED ||
1505 Wnd->state2 & WNDS2_INDESTROY)
1506 return FALSE;
1507 return TRUE;
1508 }
1509
1510 return FALSE;
1511 }
1512
1513
1514 /*
1515 * @implemented
1516 */
1517 BOOL WINAPI
1518 IsWindowUnicode(HWND hWnd)
1519 {
1520 PWND Wnd = ValidateHwnd(hWnd);
1521
1522 if (Wnd != NULL)
1523 return Wnd->Unicode;
1524
1525 return FALSE;
1526 }
1527
1528
1529 /*
1530 * @implemented
1531 */
1532 BOOL WINAPI
1533 IsWindowVisible(HWND hWnd)
1534 {
1535 BOOL Ret = FALSE;
1536 PWND Wnd = ValidateHwnd(hWnd);
1537
1538 if (Wnd != NULL)
1539 {
1540 _SEH2_TRY
1541 {
1542 Ret = TRUE;
1543
1544 do
1545 {
1546 if (!(Wnd->style & WS_VISIBLE))
1547 {
1548 Ret = FALSE;
1549 break;
1550 }
1551
1552 if (Wnd->spwndParent != NULL)
1553 Wnd = DesktopPtrToUser(Wnd->spwndParent);
1554 else
1555 break;
1556
1557 } while (Wnd != NULL);
1558 }
1559 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1560 {
1561 Ret = FALSE;
1562 }
1563 _SEH2_END;
1564 }
1565
1566 return Ret;
1567 }
1568
1569
1570 /*
1571 * @implemented
1572 */
1573 BOOL WINAPI
1574 IsWindowEnabled(HWND hWnd)
1575 {
1576 // AG: I don't know if child windows are affected if the parent is
1577 // disabled. I think they stop processing messages but stay appearing
1578 // as enabled.
1579
1580 return !(GetWindowLongPtrW(hWnd, GWL_STYLE) & WS_DISABLED);
1581 }
1582
1583
1584 /*
1585 * @implemented
1586 */
1587 BOOL WINAPI
1588 IsZoomed(HWND hWnd)
1589 {
1590 return (GetWindowLongPtrW(hWnd, GWL_STYLE) & WS_MAXIMIZE) != 0;
1591 }
1592
1593
1594 /*
1595 * @implemented
1596 */
1597 BOOL WINAPI
1598 LockSetForegroundWindow(UINT uLockCode)
1599 {
1600 return NtUserxLockSetForegroundWindow(uLockCode);
1601 }
1602
1603
1604 /*
1605 * @implemented
1606 */
1607 BOOL WINAPI
1608 AnimateWindow(HWND hwnd,
1609 DWORD dwTime,
1610 DWORD dwFlags)
1611 {
1612 /* FIXME Add animation code */
1613
1614 /* If trying to show/hide and it's already *
1615 * shown/hidden or invalid window, fail with *
1616 * invalid parameter */
1617
1618 BOOL visible;
1619 visible = IsWindowVisible(hwnd);
1620 if(!IsWindow(hwnd) ||
1621 (visible && !(dwFlags & AW_HIDE)) ||
1622 (!visible && (dwFlags & AW_HIDE)))
1623 {
1624 SetLastError(ERROR_INVALID_PARAMETER);
1625 return FALSE;
1626 }
1627
1628 ShowWindow(hwnd, (dwFlags & AW_HIDE) ? SW_HIDE : ((dwFlags & AW_ACTIVATE) ? SW_SHOW : SW_SHOWNA));
1629
1630 return TRUE;
1631 }
1632
1633
1634 /*
1635 * @implemented
1636 */
1637 BOOL WINAPI
1638 OpenIcon(HWND hWnd)
1639 {
1640 if (!(GetWindowLongPtrW(hWnd, GWL_STYLE) & WS_MINIMIZE))
1641 return FALSE;
1642
1643 ShowWindow(hWnd,SW_RESTORE);
1644 return TRUE;
1645 }
1646
1647
1648 /*
1649 * @implemented
1650 */
1651 HWND WINAPI
1652 RealChildWindowFromPoint(HWND hwndParent,
1653 POINT ptParentClientCoords)
1654 {
1655 return NtUserRealChildWindowFromPoint(hwndParent, ptParentClientCoords.x, ptParentClientCoords.y);
1656 }
1657
1658 /*
1659 * @unimplemented
1660 */
1661 BOOL WINAPI
1662 SetForegroundWindow(HWND hWnd)
1663 {
1664 return NtUserxSetForegroundWindow(hWnd);
1665 }
1666
1667
1668 /*
1669 * @implemented
1670 */
1671 BOOL WINAPI
1672 SetProcessDefaultLayout(DWORD dwDefaultLayout)
1673 {
1674 return NtUserCallOneParam( (DWORD_PTR)dwDefaultLayout, ONEPARAM_ROUTINE_SETPROCDEFLAYOUT);
1675 }
1676
1677
1678 /*
1679 * @implemented
1680 */
1681 BOOL WINAPI
1682 SetWindowTextA(HWND hWnd,
1683 LPCSTR lpString)
1684 {
1685 PWND pwnd;
1686
1687 pwnd = ValidateHwnd(hWnd);
1688 if (pwnd)
1689 {
1690 if (!TestWindowProcess(pwnd))
1691 {
1692 /* do not send WM_GETTEXT messages to other processes */
1693 return (DefWindowProcA(hWnd, WM_SETTEXT, 0, (LPARAM)lpString) >= 0);
1694 }
1695 return (SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)lpString) >= 0);
1696 }
1697 return FALSE;
1698 }
1699
1700
1701 /*
1702 * @implemented
1703 */
1704 BOOL WINAPI
1705 SetWindowTextW(HWND hWnd,
1706 LPCWSTR lpString)
1707 {
1708 PWND pwnd;
1709
1710 pwnd = ValidateHwnd(hWnd);
1711 if (pwnd)
1712 {
1713 if (!TestWindowProcess(pwnd))
1714 {
1715 /* do not send WM_GETTEXT messages to other processes */
1716 return (DefWindowProcW(hWnd, WM_SETTEXT, 0, (LPARAM)lpString) >= 0);
1717 }
1718 return (SendMessageW(hWnd, WM_SETTEXT, 0, (LPARAM)lpString) >= 0);
1719 }
1720 return FALSE;
1721 }
1722
1723
1724 /*
1725 * @implemented
1726 */
1727 BOOL WINAPI
1728 ShowOwnedPopups(HWND hWnd, BOOL fShow)
1729 {
1730 return NtUserxShowOwnedPopups(hWnd, fShow);
1731 }
1732
1733
1734 /*
1735 * @implemented
1736 */
1737 BOOL WINAPI
1738 UpdateLayeredWindow( HWND hwnd,
1739 HDC hdcDst,
1740 POINT *pptDst,
1741 SIZE *psize,
1742 HDC hdcSrc,
1743 POINT *pptSrc,
1744 COLORREF crKey,
1745 BLENDFUNCTION *pbl,
1746 DWORD dwFlags)
1747 {
1748 if ( dwFlags & ULW_EX_NORESIZE)
1749 dwFlags = ~(ULW_EX_NORESIZE|ULW_OPAQUE|ULW_ALPHA|ULW_COLORKEY);
1750 return NtUserUpdateLayeredWindow( hwnd,
1751 hdcDst,
1752 pptDst,
1753 psize,
1754 hdcSrc,
1755 pptSrc,
1756 crKey,
1757 pbl,
1758 dwFlags,
1759 NULL);
1760 }
1761
1762 /*
1763 * @implemented
1764 */
1765 BOOL WINAPI
1766 UpdateLayeredWindowIndirect(HWND hwnd,
1767 const UPDATELAYEREDWINDOWINFO *info)
1768 {
1769 if (info && info->cbSize == sizeof(*info))
1770 {
1771 return NtUserUpdateLayeredWindow( hwnd,
1772 info->hdcDst,
1773 (POINT *)info->pptDst,
1774 (SIZE *)info->psize,
1775 info->hdcSrc,
1776 (POINT *)info->pptSrc,
1777 info->crKey,
1778 (BLENDFUNCTION *)info->pblend,
1779 info->dwFlags,
1780 (RECT *)info->prcDirty);
1781 }
1782 SetLastError(ERROR_INVALID_PARAMETER);
1783 return FALSE;
1784 }
1785
1786 /*
1787 * @implemented
1788 */
1789 BOOL WINAPI
1790 SetWindowContextHelpId(HWND hwnd,
1791 DWORD dwContextHelpId)
1792 {
1793 return NtUserxSetWindowContextHelpId(hwnd, dwContextHelpId);
1794 }
1795
1796 /*
1797 * @implemented
1798 */
1799 DWORD WINAPI
1800 GetWindowContextHelpId(HWND hwnd)
1801 {
1802 return NtUserxGetWindowContextHelpId(hwnd);
1803 }
1804
1805 /*
1806 * @implemented
1807 */
1808 int WINAPI
1809 InternalGetWindowText(HWND hWnd, LPWSTR lpString, int nMaxCount)
1810 {
1811 INT Ret = NtUserInternalGetWindowText(hWnd, lpString, nMaxCount);
1812 if (Ret == 0)
1813 *lpString = L'\0';
1814 return Ret;
1815 }
1816
1817 /*
1818 * @implemented
1819 */
1820 BOOL WINAPI
1821 IsHungAppWindow(HWND hwnd)
1822 {
1823 return (NtUserQueryWindow(hwnd, QUERY_WINDOW_ISHUNG) != 0);
1824 }
1825
1826 /*
1827 * @implemented
1828 */
1829 VOID WINAPI
1830 SetLastErrorEx(DWORD dwErrCode, DWORD dwType)
1831 {
1832 SetLastError(dwErrCode);
1833 }
1834
1835 /*
1836 * @implemented
1837 */
1838 HWND WINAPI
1839 GetFocus(VOID)
1840 {
1841 return (HWND)NtUserGetThreadState(THREADSTATE_FOCUSWINDOW);
1842 }
1843
1844 DWORD WINAPI
1845 GetRealWindowOwner(HWND hwnd)
1846 {
1847 return NtUserQueryWindow(hwnd, QUERY_WINDOW_REAL_ID);
1848 }
1849
1850 /*
1851 * @implemented
1852 */
1853 HWND WINAPI
1854 SetTaskmanWindow(HWND hWnd)
1855 {
1856 return NtUserxSetTaskmanWindow(hWnd);
1857 }
1858
1859 /*
1860 * @implemented
1861 */
1862 HWND WINAPI
1863 SetProgmanWindow(HWND hWnd)
1864 {
1865 return NtUserxSetProgmanWindow(hWnd);
1866 }
1867
1868 /*
1869 * @implemented
1870 */
1871 HWND WINAPI
1872 GetProgmanWindow(VOID)
1873 {
1874 return (HWND)NtUserGetThreadState(THREADSTATE_PROGMANWINDOW);
1875 }
1876
1877 /*
1878 * @implemented
1879 */
1880 HWND WINAPI
1881 GetTaskmanWindow(VOID)
1882 {
1883 return (HWND)NtUserGetThreadState(THREADSTATE_TASKMANWINDOW);
1884 }
1885
1886 /*
1887 * @implemented
1888 */
1889 BOOL WINAPI
1890 ScrollWindow(HWND hWnd,
1891 int dx,
1892 int dy,
1893 CONST RECT *lpRect,
1894 CONST RECT *prcClip)
1895 {
1896 return NtUserScrollWindowEx(hWnd,
1897 dx,
1898 dy,
1899 lpRect,
1900 prcClip,
1901 0,
1902 NULL,
1903 (lpRect ? 0 : SW_SCROLLCHILDREN) | SW_INVALIDATE) != ERROR;
1904 }
1905
1906
1907 /*
1908 * @implemented
1909 */
1910 INT WINAPI
1911 ScrollWindowEx(HWND hWnd,
1912 int dx,
1913 int dy,
1914 CONST RECT *prcScroll,
1915 CONST RECT *prcClip,
1916 HRGN hrgnUpdate,
1917 LPRECT prcUpdate,
1918 UINT flags)
1919 {
1920 return NtUserScrollWindowEx(hWnd,
1921 dx,
1922 dy,
1923 prcScroll,
1924 prcClip,
1925 hrgnUpdate,
1926 prcUpdate,
1927 flags);
1928 }
1929
1930 /*
1931 * @implemented
1932 */
1933 BOOL WINAPI
1934 AnyPopup(VOID)
1935 {
1936 int i;
1937 BOOL retvalue;
1938 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1939
1940 if (!list) return FALSE;
1941 for (i = 0; list[i]; i++)
1942 {
1943 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
1944 }
1945 retvalue = (list[i] != 0);
1946 HeapFree( GetProcessHeap(), 0, list );
1947 return retvalue;
1948 }
1949
1950 /*
1951 * @implemented
1952 */
1953 BOOL WINAPI
1954 IsWindowInDestroy(HWND hWnd)
1955 {
1956 PWND pwnd;
1957 pwnd = ValidateHwnd(hWnd);
1958 if (!pwnd)
1959 return FALSE;
1960 return ((pwnd->state2 & WNDS2_INDESTROY) == WNDS2_INDESTROY);
1961 }
1962
1963 /*
1964 * @implemented
1965 */
1966 VOID WINAPI
1967 DisableProcessWindowsGhosting(VOID)
1968 {
1969 NtUserxEnableProcessWindowGhosting(FALSE);
1970 }
1971
1972 /* EOF */
1973