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