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