test: wow.c Source File

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 }