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