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 Wnd->state2 & WNDS2_INDESTROY) 1554 return FALSE; 1555 return TRUE; 1556 } 1557 1558 return FALSE; 1559 } 1560 1561 1562 /* 1563 * @implemented 1564 */ 1565 BOOL WINAPI 1566 IsWindowUnicode(HWND hWnd) 1567 { 1568 PWND Wnd = ValidateHwnd(hWnd); 1569 1570 if (Wnd != NULL) 1571 return Wnd->Unicode; 1572 1573 return FALSE; 1574 } 1575 1576 1577 /* 1578 * @implemented 1579 */ 1580 BOOL WINAPI 1581 IsWindowVisible(HWND hWnd) 1582 { 1583 BOOL Ret = FALSE; 1584 PWND Wnd = ValidateHwnd(hWnd); 1585 1586 if (Wnd != NULL) 1587 { 1588 _SEH2_TRY 1589 { 1590 Ret = TRUE; 1591 1592 do 1593 { 1594 if (!(Wnd->style & WS_VISIBLE)) 1595 { 1596 Ret = FALSE; 1597 break; 1598 } 1599 1600 if (Wnd->spwndParent != NULL) 1601 Wnd = DesktopPtrToUser(Wnd->spwndParent); 1602 else 1603 break; 1604 1605 } while (Wnd != NULL); 1606 } 1607 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1608 { 1609 Ret = FALSE; 1610 } 1611 _SEH2_END; 1612 } 1613 1614 return Ret; 1615 } 1616 1617 1618 /* 1619 * @implemented 1620 */ 1621 BOOL WINAPI 1622 IsWindowEnabled(HWND hWnd) 1623 { 1624 // AG: I don't know if child windows are affected if the parent is 1625 // disabled. I think they stop processing messages but stay appearing 1626 // as enabled. 1627 1628 return !(GetWindowLongPtrW(hWnd, GWL_STYLE) & WS_DISABLED); 1629 } 1630 1631 1632 /* 1633 * @implemented 1634 */ 1635 BOOL WINAPI 1636 IsZoomed(HWND hWnd) 1637 { 1638 return (GetWindowLongPtrW(hWnd, GWL_STYLE) & WS_MAXIMIZE) != 0; 1639 } 1640 1641 1642 /* 1643 * @implemented 1644 */ 1645 BOOL WINAPI 1646 LockSetForegroundWindow(UINT uLockCode) 1647 { 1648 return NtUserxLockSetForegroundWindow(uLockCode); 1649 } 1650 1651 1652 /* 1653 * @implemented 1654 */ 1655 BOOL WINAPI 1656 AnimateWindow(HWND hwnd, 1657 DWORD dwTime, 1658 DWORD dwFlags) 1659 { 1660 /* FIXME Add animation code */ 1661 1662 /* If trying to show/hide and it's already * 1663 * shown/hidden or invalid window, fail with * 1664 * invalid parameter */ 1665 1666 BOOL visible; 1667 visible = IsWindowVisible(hwnd); 1668 if(!IsWindow(hwnd) || 1669 (visible && !(dwFlags & AW_HIDE)) || 1670 (!visible && (dwFlags & AW_HIDE))) 1671 { 1672 SetLastError(ERROR_INVALID_PARAMETER); 1673 return FALSE; 1674 } 1675 1676 ShowWindow(hwnd, (dwFlags & AW_HIDE) ? SW_HIDE : ((dwFlags & AW_ACTIVATE) ? SW_SHOW : SW_SHOWNA)); 1677 1678 return TRUE; 1679 } 1680 1681 1682 /* 1683 * @implemented 1684 */ 1685 BOOL WINAPI 1686 OpenIcon(HWND hWnd) 1687 { 1688 if (!(GetWindowLongPtrW(hWnd, GWL_STYLE) & WS_MINIMIZE)) 1689 return FALSE; 1690 1691 ShowWindow(hWnd,SW_RESTORE); 1692 return TRUE; 1693 } 1694 1695 1696 /* 1697 * @implemented 1698 */ 1699 HWND WINAPI 1700 RealChildWindowFromPoint(HWND hwndParent, 1701 POINT ptParentClientCoords) 1702 { 1703 return NtUserRealChildWindowFromPoint(hwndParent, ptParentClientCoords.x, ptParentClientCoords.y); 1704 } 1705 1706 /* 1707 * @unimplemented 1708 */ 1709 BOOL WINAPI 1710 SetForegroundWindow(HWND hWnd) 1711 { 1712 return NtUserxSetForegroundWindow(hWnd); 1713 } 1714 1715 1716 /* 1717 * @implemented 1718 */ 1719 BOOL WINAPI 1720 SetProcessDefaultLayout(DWORD dwDefaultLayout) 1721 { 1722 return NtUserCallOneParam( (DWORD_PTR)dwDefaultLayout, ONEPARAM_ROUTINE_SETPROCDEFLAYOUT); 1723 } 1724 1725 1726 /* 1727 * @implemented 1728 */ 1729 BOOL 1730 WINAPI 1731 DECLSPEC_HOTPATCH 1732 SetWindowTextA(HWND hWnd, 1733 LPCSTR lpString) 1734 { 1735 PWND pwnd; 1736 1737 pwnd = ValidateHwnd(hWnd); 1738 if (pwnd) 1739 { 1740 if (!TestWindowProcess(pwnd)) 1741 { 1742 /* do not send WM_GETTEXT messages to other processes */ 1743 return (DefWindowProcA(hWnd, WM_SETTEXT, 0, (LPARAM)lpString) >= 0); 1744 } 1745 return (SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)lpString) >= 0); 1746 } 1747 return FALSE; 1748 } 1749 1750 1751 /* 1752 * @implemented 1753 */ 1754 BOOL 1755 WINAPI 1756 DECLSPEC_HOTPATCH 1757 SetWindowTextW(HWND hWnd, 1758 LPCWSTR lpString) 1759 { 1760 PWND pwnd; 1761 1762 pwnd = ValidateHwnd(hWnd); 1763 if (pwnd) 1764 { 1765 if (!TestWindowProcess(pwnd)) 1766 { 1767 /* do not send WM_GETTEXT messages to other processes */ 1768 return (DefWindowProcW(hWnd, WM_SETTEXT, 0, (LPARAM)lpString) >= 0); 1769 } 1770 return (SendMessageW(hWnd, WM_SETTEXT, 0, (LPARAM)lpString) >= 0); 1771 } 1772 return FALSE; 1773 } 1774 1775 1776 /* 1777 * @implemented 1778 */ 1779 BOOL WINAPI 1780 ShowOwnedPopups(HWND hWnd, BOOL fShow) 1781 { 1782 return NtUserxShowOwnedPopups(hWnd, fShow); 1783 } 1784 1785 1786 /* 1787 * @implemented 1788 */ 1789 BOOL WINAPI 1790 UpdateLayeredWindow( HWND hwnd, 1791 HDC hdcDst, 1792 POINT *pptDst, 1793 SIZE *psize, 1794 HDC hdcSrc, 1795 POINT *pptSrc, 1796 COLORREF crKey, 1797 BLENDFUNCTION *pbl, 1798 DWORD dwFlags) 1799 { 1800 if (dwFlags & ULW_EX_NORESIZE) /* only valid for UpdateLayeredWindowIndirect */ 1801 { 1802 SetLastError( ERROR_INVALID_PARAMETER ); 1803 return FALSE; 1804 } 1805 return NtUserUpdateLayeredWindow( hwnd, 1806 hdcDst, 1807 pptDst, 1808 psize, 1809 hdcSrc, 1810 pptSrc, 1811 crKey, 1812 pbl, 1813 dwFlags, 1814 NULL); 1815 } 1816 1817 /* 1818 * @implemented 1819 */ 1820 BOOL WINAPI 1821 UpdateLayeredWindowIndirect(HWND hwnd, 1822 const UPDATELAYEREDWINDOWINFO *info) 1823 { 1824 if (info && info->cbSize == sizeof(*info)) 1825 { 1826 return NtUserUpdateLayeredWindow( hwnd, 1827 info->hdcDst, 1828 (POINT *)info->pptDst, 1829 (SIZE *)info->psize, 1830 info->hdcSrc, 1831 (POINT *)info->pptSrc, 1832 info->crKey, 1833 (BLENDFUNCTION *)info->pblend, 1834 info->dwFlags, 1835 (RECT *)info->prcDirty); 1836 } 1837 SetLastError(ERROR_INVALID_PARAMETER); 1838 return FALSE; 1839 } 1840 1841 /* 1842 * @implemented 1843 */ 1844 BOOL WINAPI 1845 SetWindowContextHelpId(HWND hwnd, 1846 DWORD dwContextHelpId) 1847 { 1848 return NtUserxSetWindowContextHelpId(hwnd, dwContextHelpId); 1849 } 1850 1851 /* 1852 * @implemented 1853 */ 1854 DWORD WINAPI 1855 GetWindowContextHelpId(HWND hwnd) 1856 { 1857 return NtUserxGetWindowContextHelpId(hwnd); 1858 } 1859 1860 /* 1861 * @implemented 1862 */ 1863 int WINAPI 1864 InternalGetWindowText(HWND hWnd, LPWSTR lpString, int nMaxCount) 1865 { 1866 INT Ret = NtUserInternalGetWindowText(hWnd, lpString, nMaxCount); 1867 if (Ret == 0 && lpString) 1868 *lpString = L'\0'; 1869 return Ret; 1870 } 1871 1872 /* 1873 * @implemented 1874 */ 1875 BOOL WINAPI 1876 IsHungAppWindow(HWND hwnd) 1877 { 1878 return !!NtUserQueryWindow(hwnd, QUERY_WINDOW_ISHUNG); 1879 } 1880 1881 /* 1882 * @implemented 1883 */ 1884 VOID WINAPI 1885 SetLastErrorEx(DWORD dwErrCode, DWORD dwType) 1886 { 1887 SetLastError(dwErrCode); 1888 } 1889 1890 /* 1891 * @implemented 1892 */ 1893 HWND WINAPI 1894 GetFocus(VOID) 1895 { 1896 return (HWND)NtUserGetThreadState(THREADSTATE_FOCUSWINDOW); 1897 } 1898 1899 DWORD WINAPI 1900 GetRealWindowOwner(HWND hwnd) 1901 { 1902 return NtUserQueryWindow(hwnd, QUERY_WINDOW_REAL_ID); 1903 } 1904 1905 /* 1906 * @implemented 1907 */ 1908 HWND WINAPI 1909 SetTaskmanWindow(HWND hWnd) 1910 { 1911 return NtUserxSetTaskmanWindow(hWnd); 1912 } 1913 1914 /* 1915 * @implemented 1916 */ 1917 HWND WINAPI 1918 SetProgmanWindow(HWND hWnd) 1919 { 1920 return NtUserxSetProgmanWindow(hWnd); 1921 } 1922 1923 /* 1924 * @implemented 1925 */ 1926 HWND WINAPI 1927 GetProgmanWindow(VOID) 1928 { 1929 return (HWND)NtUserGetThreadState(THREADSTATE_PROGMANWINDOW); 1930 } 1931 1932 /* 1933 * @implemented 1934 */ 1935 HWND WINAPI 1936 GetTaskmanWindow(VOID) 1937 { 1938 return (HWND)NtUserGetThreadState(THREADSTATE_TASKMANWINDOW); 1939 } 1940 1941 /* 1942 * @implemented 1943 */ 1944 BOOL WINAPI 1945 ScrollWindow(HWND hWnd, 1946 int dx, 1947 int dy, 1948 CONST RECT *lpRect, 1949 CONST RECT *prcClip) 1950 { 1951 return NtUserScrollWindowEx(hWnd, 1952 dx, 1953 dy, 1954 lpRect, 1955 prcClip, 1956 0, 1957 NULL, 1958 (lpRect ? 0 : SW_SCROLLCHILDREN) | (SW_ERASE|SW_INVALIDATE|SW_SCROLLWNDDCE)) != ERROR; 1959 } 1960 1961 /* ScrollWindow uses the window DC, ScrollWindowEx doesn't */ 1962 1963 /* 1964 * @implemented 1965 */ 1966 INT WINAPI 1967 ScrollWindowEx(HWND hWnd, 1968 int dx, 1969 int dy, 1970 CONST RECT *prcScroll, 1971 CONST RECT *prcClip, 1972 HRGN hrgnUpdate, 1973 LPRECT prcUpdate, 1974 UINT flags) 1975 { 1976 if (flags & SW_SMOOTHSCROLL) 1977 { 1978 FIXME("SW_SMOOTHSCROLL not supported.\n"); 1979 // Fall through.... 1980 } 1981 return NtUserScrollWindowEx(hWnd, 1982 dx, 1983 dy, 1984 prcScroll, 1985 prcClip, 1986 hrgnUpdate, 1987 prcUpdate, 1988 flags); 1989 } 1990 1991 /* 1992 * @implemented 1993 */ 1994 BOOL WINAPI 1995 AnyPopup(VOID) 1996 { 1997 int i; 1998 BOOL retvalue; 1999 HWND *list = WIN_ListChildren( GetDesktopWindow() ); 2000 2001 if (!list) return FALSE; 2002 for (i = 0; list[i]; i++) 2003 { 2004 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break; 2005 } 2006 retvalue = (list[i] != 0); 2007 HeapFree( GetProcessHeap(), 0, list ); 2008 return retvalue; 2009 } 2010 2011 /* 2012 * @implemented 2013 */ 2014 BOOL WINAPI 2015 IsWindowInDestroy(HWND hWnd) 2016 { 2017 PWND pwnd; 2018 pwnd = ValidateHwnd(hWnd); 2019 if (!pwnd) 2020 return FALSE; 2021 return ((pwnd->state2 & WNDS2_INDESTROY) == WNDS2_INDESTROY); 2022 } 2023 2024 /* 2025 * @implemented 2026 */ 2027 VOID WINAPI 2028 DisableProcessWindowsGhosting(VOID) 2029 { 2030 NtUserxEnableProcessWindowGhosting(FALSE); 2031 } 2032 2033 /* EOF */ 2034 2035