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