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