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