Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

wow.c

Go to the documentation of this file.
00001 /****************************** Module Header ******************************\ 00002 * Module Name: wow.c 00003 * 00004 * Copyright (c) 1985 - 1999, Microsoft Corporation 00005 * 00006 * This module contains shared code between USER32 and USER16 00007 * No New CODE should be added to this file, unless its shared 00008 * with USER16. 00009 * 00010 * History: 00011 * 29-DEC-93 NanduriR shared user32/user16 code. 00012 \***************************************************************************/ 00013 00014 #include "wow.h" 00015 00016 00017 #ifdef _USERK_ 00018 #define CHECK_RESTRICTED() \ 00019 if (((PTHREADINFO)W32GetCurrentThread())->TIF_flags & TIF_RESTRICTED) { \ 00020 if (!ValidateHandleSecure(h)) \ 00021 pobj = NULL; \ 00022 } \ 00023 00024 #else 00025 #define CHECK_RESTRICTED() \ 00026 if (pci && (pci->dwTIFlags & TIF_RESTRICTED) && pobj) { \ 00027 if (!NtUserValidateHandleSecure(h)) \ 00028 pobj = NULL; \ 00029 } \ 00030 00031 #endif 00032 00033 00034 00035 #ifdef _USERK_ 00036 #define GET_CURRENT_CLIENTINFO() \ 00037 { \ 00038 PW32THREAD pW32Thread; \ 00039 \ 00040 pW32Thread = W32GetCurrentThread(); \ 00041 \ 00042 if (pW32Thread) { \ 00043 pci = ((PTHREADINFO)pW32Thread)->pClientInfo; \ 00044 } else { \ 00045 pci = NULL; \ 00046 } \ 00047 } 00048 00049 #else 00050 #define GET_CURRENT_CLIENTINFO() \ 00051 pci = GetClientInfo(); 00052 00053 #endif // _USERK_ 00054 00055 00056 /* 00057 * We have two types of desktop validation: 00058 * 00059 */ 00060 00061 #ifdef _USERK_ 00062 00063 #define DESKTOPVALIDATE(pci, pobj) \ 00064 UNREFERENCED_PARAMETER(pci); 00065 00066 #define DESKTOPVALIDATECCX(pci, pobj) \ 00067 if ( ((PVOID)pobj >= pci->pDeskInfo->pvDesktopBase) && \ 00068 ((PVOID)pobj < pci->pDeskInfo->pvDesktopLimit)) { \ 00069 pobj = (PBYTE)pobj - pci->ulClientDelta; \ 00070 } \ 00071 00072 #define SHAREDVALIDATE(pobj) 00073 00074 #else 00075 00076 #define DESKTOPVALIDATE(pci, pobj) \ 00077 if ( pci->pDeskInfo && \ 00078 pobj >= pci->pDeskInfo->pvDesktopBase && \ 00079 pobj < pci->pDeskInfo->pvDesktopLimit) { \ 00080 pobj = (KERNEL_PVOID)((KERNEL_ULONG_PTR)pobj - pci->ulClientDelta); \ 00081 } else { \ 00082 pobj = (KERNEL_PVOID)NtUserCallOneParam((ULONG_PTR)h, \ 00083 SFI__MAPDESKTOPOBJECT); \ 00084 } \ 00085 00086 #define SHAREDVALIDATE(pobj) \ 00087 pobj = REBASESHAREDPTRALWAYS(pobj); 00088 00089 #endif // _USERK_ 00090 00091 00092 /* 00093 * Keep the general path through validation straight without jumps - that 00094 * means tunneling if()'s for this routine - this'll make validation fastest 00095 * because of instruction caching. 00096 * 00097 * In order to have the validation code in one place only, we define 00098 * the *ValidateHandleMacro macros which are to be included by the 00099 * HMValidateHanlde* routines. We don't make these into functions 00100 * because we're optimizing on time, not size. 00101 */ 00102 #define ValidateHandleMacro(pci, pobj, h, bType) \ 00103 StartValidateHandleMacro(h) \ 00104 BeginAliveValidateHandleMacro() \ 00105 BeginTypeValidateHandleMacro(pobj, bType) \ 00106 DESKTOPVALIDATE(pci, pobj) \ 00107 EndTypeValidateHandleMacro \ 00108 EndAliveValidateHandleMacro() \ 00109 EndValidateHandleMacro 00110 00111 #ifdef _USERK_ 00112 #define ValidateCatHandleMacro(pci, pobj, h, bType) \ 00113 StartValidateHandleMacro(h) \ 00114 BeginTypeValidateHandleMacro(pobj, bType) \ 00115 DESKTOPVALIDATE(pci, pobj) \ 00116 EndTypeValidateHandleMacro \ 00117 EndValidateHandleMacro 00118 #define ValidateCatHandleMacroCcx(pci, pobj, h, bType) \ 00119 StartValidateHandleMacro(h) \ 00120 BeginTypeValidateHandleMacro(pobj, bType) \ 00121 DESKTOPVALIDATECCX(pci, pobj) \ 00122 EndTypeValidateHandleMacro \ 00123 EndValidateHandleMacro 00124 #endif 00125 00126 #define ValidateSharedHandleMacro(pobj, h, bType) \ 00127 StartValidateHandleMacro(h) \ 00128 BeginAliveValidateHandleMacro() \ 00129 BeginTypeValidateHandleMacro(pobj, bType) \ 00130 SHAREDVALIDATE(pobj) \ 00131 EndTypeValidateHandleMacro \ 00132 EndAliveValidateHandleMacro() \ 00133 EndValidateHandleMacro 00134 00135 00136 /* 00137 * The handle validation routines should be optimized for time, not size, 00138 * since they get called so often. 00139 */ 00140 #pragma optimize("t", on) 00141 00142 /***************************************************************************\ 00143 * HMValidateHandle 00144 * 00145 * This routine validates a handle manager handle. 00146 * 00147 * 01-22-92 ScottLu Created. 00148 \***************************************************************************/ 00149 00150 PVOID FASTCALL HMValidateHandle( 00151 HANDLE h, 00152 BYTE bType) 00153 { 00154 DWORD dwError; 00155 KERNEL_PVOID pobj = NULL; 00156 PCLIENTINFO pci; 00157 00158 GET_CURRENT_CLIENTINFO(); 00159 00160 #if DBG != 0 && !defined(_USERK_) 00161 /* 00162 * We don't want 32 bit apps passing 16 bit handles 00163 * we should consider failing this before we get 00164 * stuck supporting it (Some VB apps do this). 00165 */ 00166 if (pci && (h != NULL) 00167 && (HMUniqFromHandle(h) == 0) 00168 && !(pci->dwTIFlags & TIF_16BIT)) { 00169 RIPMSG3(RIP_WARNING, "HMValidateHandle: 32bit process [%d] using 16 bit handle [%#p] bType:%#lx", 00170 HandleToUlong(NtCurrentTeb()->ClientId.UniqueProcess), h, (DWORD)bType); 00171 } 00172 #endif 00173 00174 /* 00175 * Object can't be located in shared memory. 00176 */ 00177 UserAssert(bType != TYPE_MONITOR); 00178 00179 /* 00180 * Validation macro. Falls through if the handle is invalid. 00181 */ 00182 ValidateHandleMacro(pci, pobj, h, bType); 00183 00184 /* 00185 * check for secure process 00186 */ 00187 CHECK_RESTRICTED(); 00188 00189 if (pobj != NULL) { 00190 return pobj; 00191 } 00192 00193 switch (bType) { 00194 00195 case TYPE_WINDOW: 00196 dwError = ERROR_INVALID_WINDOW_HANDLE; 00197 break; 00198 00199 case TYPE_MENU: 00200 dwError = ERROR_INVALID_MENU_HANDLE; 00201 break; 00202 00203 case TYPE_CURSOR: 00204 dwError = ERROR_INVALID_CURSOR_HANDLE; 00205 break; 00206 00207 case TYPE_ACCELTABLE: 00208 dwError = ERROR_INVALID_ACCEL_HANDLE; 00209 break; 00210 00211 case TYPE_HOOK: 00212 dwError = ERROR_INVALID_HOOK_HANDLE; 00213 break; 00214 00215 case TYPE_SETWINDOWPOS: 00216 dwError = ERROR_INVALID_DWP_HANDLE; 00217 break; 00218 00219 default: 00220 dwError = ERROR_INVALID_HANDLE; 00221 break; 00222 } 00223 00224 RIPERR2(dwError, 00225 RIP_WARNING, 00226 "HMValidateHandle: Invalid:%#p Type:%#lx", 00227 h, (DWORD)bType); 00228 00229 /* 00230 * If we get here, it's an error. 00231 */ 00232 return NULL; 00233 } 00234 00235 /***************************************************************************\ 00236 * HMValidateHandleNoSecure 00237 * 00238 * This routine validates a handle manager handle. 00239 * 00240 * 01-22-92 ScottLu Created. 00241 \***************************************************************************/ 00242 PVOID FASTCALL HMValidateHandleNoSecure( 00243 HANDLE h, 00244 BYTE bType) 00245 { 00246 KERNEL_PVOID pobj = NULL; 00247 PCLIENTINFO pci; 00248 00249 GET_CURRENT_CLIENTINFO(); 00250 00251 #if !defined(_USERK_) 00252 /* 00253 * We don't want 32 bit apps passing 16 bit handles 00254 * we should consider failing this before we get 00255 * stuck supporting it (Some VB apps do this). 00256 */ 00257 if (pci && (h != NULL) 00258 && (HMUniqFromHandle(h) == 0) 00259 && !(pci->dwTIFlags & TIF_16BIT)) { 00260 RIPMSG3(RIP_WARNING, "HMValidateHandle: 32bit process [%d] using 16 bit handle [%#p] bType:%#lx", 00261 HandleToUlong(NtCurrentTeb()->ClientId.UniqueProcess), h, (DWORD)bType); 00262 } 00263 #endif 00264 00265 /* 00266 * Object can't be located in shared memory. 00267 */ 00268 UserAssert(bType != TYPE_MONITOR); 00269 00270 /* 00271 * Validation macro. 00272 */ 00273 ValidateHandleMacro(pci, pobj, h, bType); 00274 00275 return pobj; 00276 } 00277 00278 #if defined(_USERK_) 00279 PVOID FASTCALL HMValidateCatHandleNoSecure( 00280 HANDLE h, 00281 BYTE bType) 00282 { 00283 PVOID pobj = NULL; 00284 PCLIENTINFO pci; 00285 00286 GET_CURRENT_CLIENTINFO(); 00287 00288 /* 00289 * Object can't be located in shared memory. 00290 */ 00291 UserAssert(bType != TYPE_MONITOR); 00292 00293 /* 00294 * Validation macro. 00295 */ 00296 ValidateCatHandleMacro(pci, pobj, h, bType); 00297 00298 return pobj; 00299 } 00300 PVOID FASTCALL HMValidateCatHandleNoSecureCCX( 00301 HANDLE h, 00302 BYTE bType, 00303 PCLIENTINFO ccxPci) 00304 { 00305 PVOID pobj = NULL; 00306 00307 /* 00308 * Object can't be located in shared memory. 00309 */ 00310 UserAssert(bType != TYPE_MONITOR); 00311 00312 /* 00313 * Validation macro. 00314 */ 00315 ValidateCatHandleMacroCcx(ccxPci, pobj, h, bType); 00316 00317 return pobj; 00318 } 00319 00320 PVOID FASTCALL HMValidateCatHandleNoRip( 00321 HANDLE h, 00322 BYTE bType) 00323 { 00324 PVOID pobj = NULL; 00325 PCLIENTINFO pci; 00326 00327 /* 00328 * This is the fastest way way to do validation, because 00329 * unlike HMValidateHandle, this function doesn't set the 00330 * last error. 00331 * 00332 * Validation macro. Falls through if the handle is invalid. 00333 */ 00334 00335 GET_CURRENT_CLIENTINFO(); 00336 00337 /* 00338 * Object can't be located in shared memory. 00339 */ 00340 UserAssert(bType != TYPE_MONITOR); 00341 00342 ValidateCatHandleMacro(pci, pobj, h, bType); 00343 00344 /* 00345 * check for secure process 00346 */ 00347 CHECK_RESTRICTED(); 00348 00349 return pobj; 00350 } 00351 #endif 00352 00353 PVOID FASTCALL HMValidateHandleNoRip( 00354 HANDLE h, 00355 BYTE bType) 00356 { 00357 KERNEL_PVOID pobj = NULL; 00358 PCLIENTINFO pci; 00359 00360 /* 00361 * This is the fastest way way to do validation, because 00362 * unlike HMValidateHandle, this function doesn't set the 00363 * last error. 00364 * 00365 * Validation macro. Falls through if the handle is invalid. 00366 */ 00367 00368 GET_CURRENT_CLIENTINFO(); 00369 00370 /* 00371 * Object can't be located in shared memory. 00372 */ 00373 UserAssert(bType != TYPE_MONITOR); 00374 00375 ValidateHandleMacro(pci, pobj, h, bType); 00376 00377 /* 00378 * check for secure process 00379 */ 00380 CHECK_RESTRICTED(); 00381 00382 return pobj; 00383 } 00384 00385 #if DBG != 0 && !defined(_USERK_) 00386 /* 00387 * HMValidateHandleNoDesktop is a debug-client-side only function 00388 * used to verify a given handle without calling DESKTOPVALIDATE. 00389 * If the handle is valid, it returns the object's kernel pointer 00390 * which can be used as a BOOL value only. 00391 * Use this function to verify handles for which corresponding phe->phead 00392 * is a pool allocation (as opposed to desktop-heap allocations). 00393 */ 00394 KERNEL_PVOID FASTCALL HMValidateHandleNoDesktop( 00395 HANDLE h, 00396 BYTE bType) 00397 { 00398 KERNEL_PVOID pobj = NULL; 00399 00400 StartValidateHandleMacro(h) 00401 BeginTypeValidateHandleMacro(pobj, bType) 00402 EndTypeValidateHandleMacro 00403 EndValidateHandleMacro 00404 return pobj; 00405 } 00406 #endif 00407 00408 00409 /***************************************************************************\ 00410 * HMValidateSharedHandle 00411 * 00412 * This routine validates a handle manager handle allocated in 00413 * shared memory. 00414 * 00415 * History: 00416 * 02-Apr-1997 adams Created. 00417 \***************************************************************************/ 00418 00419 PVOID FASTCALL HMValidateSharedHandle( 00420 HANDLE h, 00421 BYTE bType) 00422 { 00423 DWORD dwError; 00424 KERNEL_PVOID pobj = NULL; 00425 00426 #if DBG != 0 && !defined(_USERK_) 00427 00428 /* 00429 * We don't want 32 bit apps passing 16 bit handles 00430 * we should consider failing this before we get 00431 * stuck supporting it (Some VB apps do this). 00432 */ 00433 if ((h != NULL) 00434 && (HMUniqFromHandle(h) == 0) 00435 && !(GetClientInfo()->dwTIFlags & TIF_16BIT)) { 00436 RIPMSG3(RIP_WARNING, "HMValidateHandle: 32bit process [%d] using 16 bit handle [%#p] bType:%#lx", 00437 HandleToUlong(NtCurrentTeb()->ClientId.UniqueProcess), h, (DWORD)bType); 00438 } 00439 #endif 00440 00441 /* 00442 * Validation macro. Falls through if the handle is invalid. 00443 */ 00444 ValidateSharedHandleMacro(pobj, h, bType); 00445 00446 if (pobj != NULL) 00447 return pobj; 00448 00449 switch (bType) { 00450 case TYPE_MONITOR: 00451 dwError = ERROR_INVALID_MONITOR_HANDLE; 00452 break; 00453 00454 default: 00455 UserAssertMsg0(0, "Logic error in HMValidateSharedHandle"); 00456 break; 00457 } 00458 00459 RIPERR2(dwError, 00460 RIP_WARNING, 00461 "HMValidateSharedHandle: Invalid:%#p Type:%#lx", 00462 h, (DWORD)bType); 00463 00464 /* 00465 * If we get here, it's an error. 00466 */ 00467 return NULL; 00468 } 00469 00470 00471 /* 00472 * Switch back to default optimization. 00473 */ 00474 #pragma optimize("", on) 00475 00476 /***************************************************************************\ 00477 * MNLookUpItem 00478 * 00479 * Return a pointer to the menu item specified by wCmd and wFlags 00480 * 00481 * History: 00482 * 10-11-90 JimA Translated from ASM 00483 * 01-07-93 FritzS Ported from Chicago 00484 \***************************************************************************/ 00485 00486 PITEM MNLookUpItem( 00487 PMENU pMenu, 00488 UINT wCmd, 00489 BOOL fByPosition, 00490 PMENU *ppMenuItemIsOn) 00491 { 00492 PITEM pItem; 00493 PITEM pItemRet = NULL; 00494 PITEM pItemMaybe; 00495 PMENU pMenuMaybe = NULL; 00496 int i; 00497 00498 if (ppMenuItemIsOn != NULL) 00499 *ppMenuItemIsOn = NULL; 00500 00501 if (pMenu == NULL || !pMenu->cItems || wCmd == MFMWFP_NOITEM) { 00502 // RIPERR0(ERROR_INVALID_PARAMETER, RIP_WARNING, "MNLookUpItem: invalid item"); 00503 return NULL; 00504 } 00505 00506 /* 00507 * dwFlags determines how we do the search 00508 */ 00509 if (fByPosition) { 00510 if (wCmd < (UINT)pMenu->cItems) { 00511 pItemRet = &((PITEM)REBASEALWAYS(pMenu, rgItems))[wCmd]; 00512 if (ppMenuItemIsOn != NULL) 00513 *ppMenuItemIsOn = pMenu; 00514 return (pItemRet); 00515 } else 00516 return NULL; 00517 } 00518 /* 00519 * Walk down the menu and try to find an item with an ID of wCmd. 00520 * The search procedes from the end of the menu (as was done in 00521 * assembler). 00522 */ 00523 00524 /* this is the Chicago code, which walks from the front of the menu -- Fritz */ 00525 00526 00527 // for (pItem = &pMenu->rgItems[i - 1]; pItemRet == NULL && i--; --pItem) { 00528 for (i = 0, pItem = REBASEALWAYS(pMenu, rgItems); i < (int)pMenu->cItems; 00529 i++, pItem++) { 00530 00531 /* 00532 * If the item is a popup, recurse down the tree 00533 */ 00534 if (pItem->spSubMenu != NULL) { 00535 // 00536 // COMPAT: 00537 // Allow apps to pass in menu handle as ID in menu APIs. We 00538 // remember that this popup had a menu handle with the same ID 00539 // value. This is a 2nd choice though. We still want to see 00540 // if there's some actual command that has this ID value first. 00541 // 00542 if (pItem->wID == wCmd) { 00543 pMenuMaybe = pMenu; 00544 pItemMaybe = pItem; 00545 } 00546 00547 pItemRet = MNLookUpItem((PMENU)REBASEPTR(pMenu, pItem->spSubMenu), 00548 wCmd, FALSE, ppMenuItemIsOn); 00549 if (pItemRet != NULL) 00550 return pItemRet; 00551 } else if (pItem->wID == wCmd) { 00552 00553 /* 00554 * Found the item, now save things for later 00555 */ 00556 if (ppMenuItemIsOn != NULL) 00557 *ppMenuItemIsOn = pMenu; 00558 return pItem; 00559 } 00560 } 00561 00562 if (pMenuMaybe) { 00563 // no non popup menu match found -- use the 2nd choice popup menu 00564 // match 00565 if (ppMenuItemIsOn != NULL) 00566 *ppMenuItemIsOn = pMenuMaybe; 00567 return(pItemMaybe); 00568 } 00569 00570 return(NULL); 00571 } 00572 00573 /***************************************************************************\ 00574 * GetMenuState 00575 * 00576 * Either returns the state of a menu item or the state and item count 00577 * of a popup. 00578 * 00579 * History: 00580 * 10-11-90 JimA Translated from ASM 00581 \***************************************************************************/ 00582 00583 UINT _GetMenuState( 00584 PMENU pMenu, 00585 UINT wId, 00586 UINT dwFlags) 00587 { 00588 PITEM pItem; 00589 DWORD fFlags; 00590 00591 /* 00592 * If the item does not exist, leave 00593 */ 00594 if ((pItem = MNLookUpItem(pMenu, wId, (BOOL) (dwFlags & MF_BYPOSITION), NULL)) == NULL) 00595 return (UINT)-1; 00596 00597 fFlags = pItem->fState | pItem->fType; 00598 00599 #ifndef _USERK_ 00600 /* 00601 * Add old MFT_BITMAP flag to keep old apps happy 00602 */ 00603 if ((pItem->hbmp != NULL) && (pItem->lpstr == NULL)) { 00604 fFlags |= MFT_BITMAP; 00605 } 00606 #endif 00607 00608 if (pItem->spSubMenu != NULL) { 00609 /* 00610 * If the item is a popup, return item count in high byte and 00611 * popup flags in low byte 00612 */ 00613 00614 fFlags = ((fFlags | MF_POPUP) & 0x00FF) + 00615 (((PMENU)REBASEPTR(pMenu, pItem->spSubMenu))->cItems << 8); 00616 } 00617 00618 return fFlags; 00619 } 00620 00621 00622 /***************************************************************************\ 00623 * GetPrevPwnd 00624 * 00625 * 00626 * 00627 * History: 00628 * 11-05-90 darrinm Ported from Win 3.0 sources. 00629 \***************************************************************************/ 00630 00631 PWND GetPrevPwnd( 00632 PWND pwndList, 00633 PWND pwndFind) 00634 { 00635 PWND pwndFound, pwndNext; 00636 00637 if (pwndList == NULL) 00638 return NULL; 00639 00640 if (pwndList->spwndParent == NULL) 00641 return NULL; 00642 00643 pwndNext = REBASEPWND(pwndList, spwndParent); 00644 pwndNext = REBASEPWND(pwndNext, spwndChild); 00645 pwndFound = NULL; 00646 00647 while (pwndNext != NULL) { 00648 if (pwndNext == pwndFind) 00649 break; 00650 pwndFound = pwndNext; 00651 pwndNext = REBASEPWND(pwndNext, spwndNext); 00652 } 00653 00654 return (pwndNext == pwndFind) ? pwndFound : NULL; 00655 } 00656 00657 00658 /***************************************************************************\ 00659 * _GetWindow (API) 00660 * 00661 * 00662 * History: 00663 * 11-05-90 darrinm Ported from Win 3.0 sources. 00664 * 02-19-91 JimA Added enum access check 00665 * 05-04-02 DarrinM Removed enum access check and moved to USERRTL.DLL 00666 \***************************************************************************/ 00667 00668 PWND _GetWindow( 00669 PWND pwnd, 00670 UINT cmd) 00671 { 00672 PWND pwndT; 00673 BOOL fRebase = FALSE; 00674 00675 /* 00676 * If this is a desktop window, return NULL for sibling or 00677 * parent information. 00678 */ 00679 if (GETFNID(pwnd) == FNID_DESKTOP) { 00680 switch (cmd) { 00681 case GW_CHILD: 00682 break; 00683 00684 default: 00685 return NULL; 00686 break; 00687 } 00688 } 00689 00690 /* 00691 * Rebase the returned window at the end of the routine 00692 * to avoid multiple test for pwndT == NULL. 00693 */ 00694 pwndT = NULL; 00695 switch (cmd) { 00696 case GW_HWNDNEXT: 00697 pwndT = pwnd->spwndNext; 00698 fRebase = TRUE; 00699 break; 00700 00701 case GW_HWNDFIRST: 00702 if (pwnd->spwndParent) { 00703 pwndT = REBASEPWND(pwnd, spwndParent); 00704 pwndT = REBASEPWND(pwndT, spwndChild); 00705 if (GetAppCompatFlags(NULL) & GACF_IGNORETOPMOST) { 00706 while (pwndT != NULL) { 00707 if (!TestWF(pwndT, WEFTOPMOST)) 00708 break; 00709 pwndT = REBASEPWND(pwndT, spwndNext); 00710 } 00711 } 00712 } 00713 break; 00714 00715 case GW_HWNDLAST: 00716 pwndT = GetPrevPwnd(pwnd, NULL); 00717 break; 00718 00719 case GW_HWNDPREV: 00720 pwndT = GetPrevPwnd(pwnd, pwnd); 00721 break; 00722 00723 case GW_OWNER: 00724 pwndT = pwnd->spwndOwner; 00725 fRebase = TRUE; 00726 break; 00727 00728 case GW_CHILD: 00729 pwndT = pwnd->spwndChild; 00730 fRebase = TRUE; 00731 break; 00732 00733 #if !defined(_USERK_) 00734 case GW_ENABLEDPOPUP: 00735 pwndT = (PWND)NtUserCallHwnd(PtoHq(pwnd), SFI_DWP_GETENABLEDPOPUP); 00736 fRebase = TRUE; 00737 break; 00738 #endif 00739 00740 default: 00741 RIPERR0(ERROR_INVALID_GW_COMMAND, RIP_VERBOSE, ""); 00742 return NULL; 00743 } 00744 00745 if (pwndT != NULL && fRebase) 00746 pwndT = REBASEPTR(pwnd, pwndT); 00747 00748 return pwndT; 00749 } 00750 00751 /***************************************************************************\ 00752 * _GetParent (API) 00753 * 00754 * 00755 * 00756 * History: 00757 * 11-12-90 darrinm Ported. 00758 * 02-19-91 JimA Added enum access check 00759 * 05-04-92 DarrinM Removed enum access check and moved to USERRTL.DLL 00760 \***************************************************************************/ 00761 00762 PWND _GetParent( 00763 PWND pwnd) 00764 { 00765 /* 00766 * For 1.03 compatibility reasons, we should return NULL 00767 * for top level "tiled" windows and owner for other popups. 00768 * pwndOwner is set to NULL in xxxCreateWindow for top level 00769 * "tiled" windows. 00770 */ 00771 if (!(TestwndTiled(pwnd))) { 00772 if (TestwndChild(pwnd)) 00773 pwnd = REBASEPWND(pwnd, spwndParent); 00774 else 00775 pwnd = REBASEPWND(pwnd, spwndOwner); 00776 return pwnd; 00777 } 00778 00779 /* 00780 * The window was not a child window; they may have been just testing 00781 * if it was 00782 */ 00783 return NULL; 00784 } 00785 00786 00787 /***************************************************************************\ 00788 * GetSubMenu 00789 * 00790 * Return the handle of a popup menu. 00791 * 00792 * History: 00793 * 10-11-90 JimA Translated from ASM 00794 \***************************************************************************/ 00795 00796 PMENU _GetSubMenu( 00797 PMENU pMenu, 00798 int nPos) 00799 { 00800 PITEM pItem; 00801 PMENU pPopup = NULL; 00802 00803 /* 00804 * Make sure nPos refers to a valid popup 00805 */ 00806 if ((UINT)nPos < (UINT)((PMENU)pMenu)->cItems) { 00807 pItem = &((PITEM)REBASEALWAYS(pMenu, rgItems))[nPos]; 00808 if (pItem->spSubMenu != NULL) 00809 pPopup = (PMENU)REBASEPTR(pMenu, pItem->spSubMenu); 00810 00811 } 00812 00813 return (PVOID)pPopup; 00814 } 00815 00816 00817 /***************************************************************************\ 00818 * _IsChild (API) 00819 * 00820 * 00821 * 00822 * History: 00823 * 11-07-90 darrinm Translated from Win 3.0 ASM code. 00824 \***************************************************************************/ 00825 00826 BOOL _IsChild( 00827 PWND pwndParent, 00828 PWND pwnd) 00829 { 00830 /* 00831 * Don't need a test to get out of the loop because the 00832 * desktop is not a child. 00833 */ 00834 while (pwnd != NULL) { 00835 if (!TestwndChild(pwnd)) 00836 return FALSE; 00837 00838 pwnd = REBASEPWND(pwnd, spwndParent); 00839 if (pwndParent == pwnd) 00840 return TRUE; 00841 } 00842 return FALSE; 00843 } 00844 00845 00846 00847 /***************************************************************************\ 00848 * _IsWindowVisible (API) 00849 * 00850 * IsWindowVisible returns the TRUEVIS state of a window, rather than just 00851 * the state of its WFVISIBLE flag. According to this routine, a window is 00852 * considered visible when it and all the windows on its parent chain are 00853 * visible (WFVISIBLE flag set). A special case hack was put in that causes 00854 * any icon window being dragged to be considered as visible. 00855 * 00856 * History: 00857 * 11-12-90 darrinm Ported. 00858 \***************************************************************************/ 00859 00860 BOOL _IsWindowVisible( 00861 PWND pwnd) 00862 { 00863 /* 00864 * Check if this is the iconic window being moved around with a mouse 00865 * If so, return a TRUE, though, strictly speaking, it is hidden. 00866 * This helps the Tracer guys from going crazy! 00867 * Fix for Bug #57 -- SANKAR -- 08-08-89 -- 00868 */ 00869 if (pwnd == NULL) 00870 return TRUE; 00871 00872 for (;;) { 00873 if (!TestWF(pwnd, WFVISIBLE)) 00874 return FALSE; 00875 if (GETFNID(pwnd) == FNID_DESKTOP) 00876 break; 00877 pwnd = REBASEPWND(pwnd, spwndParent); 00878 } 00879 00880 return TRUE; 00881 } 00882 00883 00884 /***************************************************************************\ 00885 * _ClientToScreen (API) 00886 * 00887 * Map a point from client to screen-relative coordinates. 00888 * 00889 * History: 00890 * 11-12-90 darrinm Translated from Win 3.0 ASM code. 00891 \***************************************************************************/ 00892 00893 VOID _ClientToScreen( 00894 PWND pwnd, 00895 PPOINT ppt) 00896 { 00897 /* 00898 * Client and screen coordinates are the same for the 00899 * desktop window. 00900 */ 00901 if (GETFNID(pwnd) != FNID_DESKTOP) { 00902 #ifdef USE_MIRRORING 00903 if (TestWF(pwnd, WEFLAYOUTRTL)) { 00904 ppt->x = pwnd->rcClient.right - ppt->x; 00905 } else 00906 #endif 00907 { 00908 ppt->x += pwnd->rcClient.left; 00909 } 00910 ppt->y += pwnd->rcClient.top; 00911 } 00912 } 00913 00914 00915 /***************************************************************************\ 00916 * _GetClientRect (API) 00917 * 00918 * 00919 * 00920 * History: 00921 * 26-Oct-1990 DarrinM Implemented. 00922 \***************************************************************************/ 00923 00924 VOID _GetClientRect( 00925 PWND pwnd, 00926 LPRECT prc) 00927 { 00928 /* 00929 * If this is a 3.1 app, and it's minimized, then we need to return 00930 * a rectangle other than the real-client-rect. This is necessary since 00931 * there is no client-rect-size in Win4.0. Apps such as PackRat 1.0 00932 * will GPF if returned a empty-rect. 00933 */ 00934 if (TestWF(pwnd, WFMINIMIZED) && !TestWF(pwnd, WFWIN40COMPAT)) { 00935 prc->left = 0; 00936 prc->top = 0; 00937 prc->right = SYSMETRTL(CXMINIMIZED); 00938 prc->bottom = SYSMETRTL(CYMINIMIZED); 00939 00940 } else { 00941 00942 if (GETFNID(pwnd) != FNID_DESKTOP) { 00943 *prc = pwnd->rcClient; 00944 OffsetRect(prc, -pwnd->rcClient.left, -pwnd->rcClient.top); 00945 } else { 00946 /* 00947 * For compatibility, return the rect of the primary 00948 * monitor for the desktop window. 00949 */ 00950 prc->left = prc->top = 0; 00951 prc->right = SYSMETRTL(CXSCREEN); 00952 prc->bottom = SYSMETRTL(CYSCREEN); 00953 } 00954 } 00955 } 00956 00957 00958 /***************************************************************************\ 00959 * _GetWindowRect (API) 00960 * 00961 * 00962 * 00963 * History: 00964 * 26-Oct-1990 DarrinM Implemented. 00965 \***************************************************************************/ 00966 00967 VOID _GetWindowRect( 00968 PWND pwnd, 00969 LPRECT prc) 00970 { 00971 00972 if (GETFNID(pwnd) != FNID_DESKTOP) { 00973 *prc = pwnd->rcWindow; 00974 } else { 00975 /* 00976 * For compatibility, return the rect of the primary 00977 * monitor for the desktop window. 00978 */ 00979 prc->left = 0; 00980 prc->top = 0; 00981 prc->right = SYSMETRTL(CXSCREEN); 00982 prc->bottom = SYSMETRTL(CYSCREEN); 00983 } 00984 } 00985 00986 /***************************************************************************\ 00987 * _ScreenToClient (API) 00988 * 00989 * Map a point from screen to client-relative coordinates. 00990 * 00991 * History: 00992 * 11-12-90 darrinm Translated from Win 3.0 ASM code. 00993 \***************************************************************************/ 00994 00995 VOID _ScreenToClient( 00996 PWND pwnd, 00997 PPOINT ppt) 00998 { 00999 /* 01000 * Client and screen coordinates are the same for the 01001 * desktop window. 01002 */ 01003 if (GETFNID(pwnd) != FNID_DESKTOP) { 01004 #ifdef USE_MIRRORING 01005 if (TestWF(pwnd, WEFLAYOUTRTL)) { 01006 ppt->x = pwnd->rcClient.right - ppt->x; 01007 } else 01008 #endif 01009 { 01010 ppt->x -= pwnd->rcClient.left; 01011 } 01012 ppt->y -= pwnd->rcClient.top; 01013 } 01014 } 01015 /***************************************************************************\ 01016 * PhkNextValid 01017 * 01018 * This helper routine walk the phkNext chain looking for the next valid 01019 * hook (i.e., not marked as destroyed). If the end of the local (or 01020 * thread specific) hook chain is reached, then it jumps to the global 01021 * (or desktop) chain. 01022 * 01023 * Once a hook is destroyed, we don't want anymore activity on it; however, 01024 * if the hook is locked at destroy time (= someone is calling it), then 01025 * we keep it in the list so CallNextHook will work properly 01026 * 01027 * History: 01028 * 03/24/96 GerardoB Moved to rtl and added *Valid stuff. 01029 * 01-30-91 DavidPe Created. 01030 \***************************************************************************/ 01031 PHOOK PhkNextValid(PHOOK phk) 01032 { 01033 01034 #if DBG 01035 int iHook = phk->iHook; 01036 #ifdef _USERK_ 01037 CheckCritInShared(); 01038 #endif 01039 #endif 01040 01041 do { 01042 /* 01043 * If this hook is marked as destroyed, it must be either 01044 * locked or we should be in the process of destroying it 01045 */ 01046 UserAssert(!(phk->flags & HF_DESTROYED) 01047 || (((PHEAD)phk)->cLockObj != 0) 01048 || (phk->flags & HF_INCHECKWHF)); 01049 /* 01050 * Get the next hook 01051 */ 01052 if (phk->phkNext != NULL) { 01053 phk = REBASEALWAYS(phk, phkNext); 01054 } else if (!(phk->flags & HF_GLOBAL)) { 01055 #ifdef _USERK_ 01056 phk = PtiCurrent()->pDeskInfo->aphkStart[phk->iHook + 1]; 01057 #else 01058 PCLIENTINFO pci = GetClientInfo(); 01059 phk = pci->pDeskInfo->aphkStart[phk->iHook + 1]; 01060 /* 01061 * If it found a pointer, rebase it. 01062 */ 01063 if (phk != NULL) { 01064 (KPBYTE)phk -= pci->ulClientDelta; 01065 } 01066 #endif 01067 UserAssert((phk == NULL) || (phk->flags & HF_GLOBAL)); 01068 } else { 01069 return NULL; 01070 } 01071 /* 01072 * If destroyed, keep looking. 01073 */ 01074 } while ((phk != NULL) && (phk->flags & HF_DESTROYED)); 01075 01076 #ifdef _USERK_ 01077 DbgValidateHooks(phk, iHook); 01078 #endif 01079 01080 return phk; 01081 }

Generated on Sat May 15 19:42:27 2004 for test by doxygen 1.3.7