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