Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

817 lines
19 KiB

/****************************** Module Header ******************************\
* Module Name: wow.c
*
* Copyright (c) 1985 - 1999, Microsoft Corporation
*
* This module contains shared code between USER32 and USER16
* No New CODE should be added to this file, unless its shared
* with USER16.
*
* History:
* 29-DEC-93 NanduriR shared user32/user16 code.
\***************************************************************************/
#include "precomp.h"
#pragma hdrstop
/***************************************************************************\
* ValidateHwnd
*
* Verify that the handle is valid. If the handle is invalid or access
* cannot be granted fail.
*
* History:
* 03-18-92 DarrinM Created from pieces of misc server-side funcs.
\***************************************************************************/
PWND FASTCALL ValidateHwnd(
HWND hwnd)
{
PCLIENTINFO pci = GetClientInfo();
/*
* Attempt fast window validation.
*/
if (hwnd != NULL && hwnd == pci->CallbackWnd.hwnd) {
return pci->CallbackWnd.pwnd;
}
/*
* Validate that the handle is of the proper type.
*/
return HMValidateHandle(hwnd, TYPE_WINDOW);
}
PWND FASTCALL ValidateHwndNoRip(
HWND hwnd)
{
PCLIENTINFO pci = GetClientInfo();
/*
* Attempt fast window validation.
*/
if (hwnd != NULL && hwnd == pci->CallbackWnd.hwnd) {
return pci->CallbackWnd.pwnd;
}
/*
* Validate the handle is of the proper type.
*/
return HMValidateHandleNoRip(hwnd, TYPE_WINDOW);
}
FUNCLOG3(LOG_GENERAL, int, WINAPI, GetClassNameA, HWND, hwnd, LPSTR, lpClassName, int, nMaxCount)
int WINAPI GetClassNameA(
HWND hwnd,
LPSTR lpClassName,
int nMaxCount)
{
PCLS pcls;
LPSTR lpszClassNameSrc;
PWND pwnd;
int cchSrc;
pwnd = ValidateHwnd(hwnd);
if (pwnd == NULL)
return FALSE;
try {
if (nMaxCount != 0) {
pcls = (PCLS)REBASEALWAYS(pwnd, pcls);
lpszClassNameSrc = REBASEPTR(pwnd, pcls->lpszAnsiClassName);
cchSrc = lstrlenA(lpszClassNameSrc);
nMaxCount = min(cchSrc, nMaxCount - 1);
RtlCopyMemory(lpClassName, lpszClassNameSrc, nMaxCount);
lpClassName[nMaxCount] = '\0';
}
} except (W32ExceptionHandler(FALSE, RIP_WARNING)) {
nMaxCount = 0;
}
return nMaxCount;
}
/***************************************************************************\
* _GetDesktopWindow (API)
*
* History:
* 11-07-90 darrinm Implemented.
\***************************************************************************/
PWND _GetDesktopWindow(
VOID)
{
PCLIENTINFO pci;
ConnectIfNecessary(0);
pci = GetClientInfo();
return (PWND)((KERNEL_ULONG_PTR)pci->pDeskInfo->spwnd - pci->ulClientDelta);
}
HWND GetDesktopWindow(
VOID)
{
PWND pwnd = _GetDesktopWindow();
PCLIENTINFO pci = GetClientInfo();
/*
* Validate the parent window's handle if a restricted process.
*/
if (pci && (pci->dwTIFlags & TIF_RESTRICTED)) {
if (ValidateHwnd(HW(pwnd)) == NULL) {
return NULL;
}
}
return HW(pwnd);
}
PWND _GetDlgItem(
PWND pwnd,
int id)
{
if (pwnd != NULL) {
pwnd = REBASEPWND(pwnd, spwndChild);
while (pwnd != NULL) {
if (PtrToLong(pwnd->spmenu) == id) {
break;
}
pwnd = REBASEPWND(pwnd, spwndNext);
}
}
return pwnd;
}
FUNCLOG2(LOG_GENERAL, HWND, DUMMYCALLINGTYPE, GetDlgItem, HWND, hwnd, int, id)
HWND GetDlgItem(
HWND hwnd,
int id)
{
PWND pwnd;
HWND hwndRet;
pwnd = ValidateHwnd(hwnd);
if (pwnd == NULL) {
return NULL;
}
pwnd = _GetDlgItem(pwnd, id);
hwndRet = HW(pwnd);
if (hwndRet == (HWND)0) {
RIPERR0(ERROR_CONTROL_ID_NOT_FOUND, RIP_VERBOSE, "");
}
return hwndRet;
}
FUNCLOG1(LOG_GENERAL, HMENU, DUMMYCALLINGTYPE, GetMenu, HWND, hwnd)
HMENU GetMenu(
HWND hwnd)
{
PWND pwnd;
PMENU pmenu;
pwnd = ValidateHwnd(hwnd);
if (pwnd == NULL) {
return 0;
}
/*
* Some ill-behaved apps use GetMenu to get the child id, so
* only map to the handle for non-child windows.
*/
if (!TestwndChild(pwnd)) {
pmenu = REBASE(pwnd, spmenu);
return (HMENU)PtoH(pmenu);
} else {
return (HMENU)KPVOID_TO_PVOID(pwnd->spmenu);
}
}
/***************************************************************************\
* GetMenuItemCount
*
* Returns a count of the number of items in the menu. Returns -1 if
* invalid menu.
*
* History:
\***************************************************************************/
FUNCLOG1(LOG_GENERAL, int, DUMMYCALLINGTYPE, GetMenuItemCount, HMENU, hMenu)
int GetMenuItemCount(
HMENU hMenu)
{
PMENU pMenu;
pMenu = VALIDATEHMENU(hMenu);
if (pMenu == NULL) {
return -1;
}
return pMenu->cItems;
}
/***************************************************************************\
* GetMenuItemID
*
* Return the ID of a menu item at the specified position.
*
* History:
\***************************************************************************/
FUNCLOG2(LOG_GENERAL, UINT, DUMMYCALLINGTYPE, GetMenuItemID, HMENU, hMenu, int, nPos)
UINT GetMenuItemID(
HMENU hMenu,
int nPos)
{
PMENU pMenu;
PITEM pItem;
pMenu = VALIDATEHMENU(hMenu);
if (pMenu == NULL) {
return (UINT)-1;
}
/*
* If the position is valid and the item is not a popup, get the ID
* Don't allow negative indexes, because that'll cause an access violation.
*/
if (nPos < (int)pMenu->cItems && nPos >= 0) {
pItem = &((PITEM)REBASEALWAYS(pMenu, rgItems))[nPos];
if (pItem->spSubMenu == NULL) {
return pItem->wID;
}
}
return (UINT)-1;
}
FUNCLOG3(LOG_GENERAL, UINT, DUMMYCALLINGTYPE, GetMenuState, HMENU, hMenu, UINT, uId, UINT, uFlags)
UINT GetMenuState(
HMENU hMenu,
UINT uId,
UINT uFlags)
{
PMENU pMenu;
pMenu = VALIDATEHMENU(hMenu);
if (pMenu == NULL || (uFlags & ~MF_VALID) != 0) {
return (UINT)-1;
}
return _GetMenuState(pMenu, uId, uFlags);
}
FUNCLOG1(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, IsWindow, HWND, hwnd)
BOOL IsWindow(
HWND hwnd)
{
PWND pwnd;
/*
* Validate the handle is of type window
*/
pwnd = ValidateHwndNoRip(hwnd);
/*
* And validate this handle is valid for this desktop by trying to read it
*/
if (pwnd != NULL) {
try {
if (pwnd->fnid & FNID_DELETED_BIT) {
pwnd = 0;
}
} except (W32ExceptionHandler(FALSE, RIP_WARNING)) {
RIPMSG1(RIP_WARNING, "IsWindow: Window %#p not of this desktop",
pwnd);
pwnd = 0;
}
}
return !!pwnd;
}
FUNCLOG2(LOG_GENERAL, HWND, DUMMYCALLINGTYPE, GetWindow, HWND, hwnd, UINT, wCmd)
HWND GetWindow(
HWND hwnd,
UINT wCmd)
{
PWND pwnd;
pwnd = ValidateHwnd(hwnd);
if (pwnd == NULL) {
return NULL;
}
pwnd = _GetWindow(pwnd, wCmd);
return HW(pwnd);
}
FUNCLOG1(LOG_GENERAL, HWND, DUMMYCALLINGTYPE, GetParent, HWND, hwnd)
HWND GetParent(
HWND hwnd)
{
PWND pwnd;
PCLIENTINFO pci;
pwnd = ValidateHwnd(hwnd);
if (pwnd == NULL) {
return NULL;
}
try {
pwnd = _GetParent(pwnd);
hwnd = HW(pwnd);
} except (W32ExceptionHandler(FALSE, RIP_WARNING)) {
hwnd = NULL;
}
pci = GetClientInfo();
/*
* validate the parent window's handle if a restricted process
*/
if (pci && (pci->dwTIFlags & TIF_RESTRICTED)) {
if (ValidateHwnd(hwnd) == NULL) {
return NULL;
}
}
return hwnd;
}
FUNCLOG2(LOG_GENERAL, HMENU, DUMMYCALLINGTYPE, GetSubMenu, HMENU, hMenu, int, nPos)
HMENU GetSubMenu(
HMENU hMenu,
int nPos)
{
PMENU pMenu;
pMenu = VALIDATEHMENU(hMenu);
if (pMenu == NULL) {
return 0;
}
pMenu = _GetSubMenu(pMenu, nPos);
return (HMENU)PtoH(pMenu);
}
FUNCLOG1(LOG_GENERAL, DWORD, DUMMYCALLINGTYPE, GetSysColor, int, nIndex)
DWORD GetSysColor(
int nIndex)
{
/*
* Return 0 if the index is out of range.
*/
if (nIndex < 0 || nIndex >= COLOR_MAX) {
RIPERR1(ERROR_INVALID_PARAMETER,
RIP_WARNING,
"Invalid parameter \"nIndex\" (%ld) to GetSysColor",
nIndex);
return 0;
}
return gpsi->argbSystem[nIndex];
}
FUNCLOG1(LOG_GENERAL, int, DUMMYCALLINGTYPE, GetSystemMetrics, int, index)
int GetSystemMetrics(
int index)
{
int ret;
BEGIN_USERAPIHOOK()
ret = guah.pfnGetSystemMetrics(index);
END_USERAPIHOOK()
return ret;
}
int RealGetSystemMetrics(
int index)
{
ConnectIfNecessary(0);
/*
* First check for values that aren't in the aiSysMet array.
*/
switch (index) {
case SM_REMOTESESSION:
return ISREMOTESESSION();
}
/*
* If it's in the BOOLEAN system metric range then do our magic.
*/
if (index >= SM_STARTBOOLRANGE && index <= SM_ENDBOOLRANGE) {
return SYSMETBOOL2(index);
}
if (index < 0 || index >= SM_CMETRICS) {
return 0;
}
switch (index) {
case SM_DBCSENABLED:
#ifdef FE_SB
return TEST_SRVIF(SRVIF_DBCS);
#else
return FALSE;
#endif
case SM_IMMENABLED:
#ifdef FE_IME
return TEST_SRVIF(SRVIF_IME);
#else
return FALSE;
#endif
case SM_MIDEASTENABLED:
return TEST_SRVIF(SRVIF_MIDEAST);
}
if (!Is400Compat(GetClientInfo()->dwExpWinVer)) {
/*
* SCROLL BAR
* before 4.0, the scroll bars and the border overlapped by a pixel. Many apps
* rely on this overlap when they compute dimensions. Now, in 4.0, this pixel
* overlap is no longer there. So for old apps, we lie and pretend the overlap
* is there by making the scroll bar widths one bigger.
*
* DLGFRAME
* In Win3.1, SM_CXDLGFRAME & SM_CYDLGFRAME were border space MINUS 1
* In Win4.0, they are border space
*
* CAPTION
* In Win3.1, SM_CYCAPTION was the caption height PLUS 1
* In Win4.0, SM_CYCAPTION is the caption height
*
* MENU
* In Win3.1, SM_CYMENU was the menu height MINUS 1
* In Win4.0, SM_CYMENU is the menu height
*/
switch (index) {
case SM_CXDLGFRAME:
case SM_CYDLGFRAME:
case SM_CYMENU:
case SM_CYFULLSCREEN:
return gpsi->aiSysMet[index] - 1;
case SM_CYCAPTION:
case SM_CXVSCROLL:
case SM_CYHSCROLL:
return gpsi->aiSysMet[index] + 1;
}
}
return gpsi->aiSysMet[index];
}
/***************************************************************************\
* GetTopWindow (API)
*
* This poorly named API should really be called 'GetFirstChild', which is
* what it does.
*
* History:
* 11-12-90 darrinm Ported.
* 02-19-91 JimA Added enum access check
* 05-04-02 DarrinM Removed enum access check and moved to USERRTL.DLL
\***************************************************************************/
FUNCLOG1(LOG_GENERAL, HWND, DUMMYCALLINGTYPE, GetTopWindow, HWND, hwnd)
HWND GetTopWindow(
HWND hwnd)
{
PWND pwnd;
/*
* Allow a NULL hwnd to go through here.
*/
if (hwnd == NULL) {
pwnd = _GetDesktopWindow();
} else {
pwnd = ValidateHwnd(hwnd);
}
if (pwnd == NULL) {
return NULL;
}
pwnd = REBASEPWND(pwnd, spwndChild);
return HW(pwnd);
}
FUNCLOG2(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, IsChild, HWND, hwndParent, HWND, hwnd)
BOOL IsChild(
HWND hwndParent,
HWND hwnd)
{
PWND pwnd, pwndParent;
pwnd = ValidateHwnd(hwnd);
if (pwnd == NULL) {
return FALSE;
}
pwndParent = ValidateHwnd(hwndParent);
if (pwndParent == NULL) {
return FALSE;
}
return _IsChild(pwndParent, pwnd);
}
FUNCLOG1(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, IsIconic, HWND, hwnd)
BOOL IsIconic(
HWND hwnd)
{
PWND pwnd;
pwnd = ValidateHwnd(hwnd);
if (pwnd == NULL) {
return FALSE;
}
return _IsIconic(pwnd);
}
FUNCLOG1(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, IsWindowEnabled, HWND, hwnd)
BOOL IsWindowEnabled(
HWND hwnd)
{
PWND pwnd;
pwnd = ValidateHwnd(hwnd);
if (pwnd == NULL) {
return FALSE;
}
return _IsWindowEnabled(pwnd);
}
FUNCLOG1(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, IsWindowVisible, HWND, hwnd)
BOOL IsWindowVisible(
HWND hwnd)
{
PWND pwnd;
BOOL bRet;
pwnd = ValidateHwnd(hwnd);
if (pwnd == NULL) {
bRet = FALSE;
} else {
try {
bRet = _IsWindowVisible(pwnd);
} except (W32ExceptionHandler(FALSE, RIP_WARNING)) {
bRet = FALSE;
}
}
return bRet;
}
FUNCLOG1(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, IsZoomed, HWND, hwnd)
BOOL IsZoomed(
HWND hwnd)
{
PWND pwnd;
pwnd = ValidateHwnd(hwnd);
if (pwnd == NULL) {
return FALSE;
}
return _IsZoomed(pwnd);
}
FUNCLOG2(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, ClientToScreen, HWND, hwnd, LPPOINT, ppoint)
BOOL ClientToScreen(
HWND hwnd,
LPPOINT ppoint)
{
PWND pwnd;
pwnd = ValidateHwnd(hwnd);
if (pwnd == NULL) {
return FALSE;
}
_ClientToScreen(pwnd, ppoint);
return TRUE;
}
FUNCLOG2(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, GetClientRect, HWND, hwnd, LPRECT, prect)
BOOL GetClientRect(
HWND hwnd,
LPRECT prect)
{
PWND pwnd;
pwnd = ValidateHwnd(hwnd);
if (pwnd == NULL) {
return FALSE;
}
_GetClientRect(pwnd, prect);
return TRUE;
}
FUNCLOG1(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, GetCursorPos, LPPOINT, lpPoint)
BOOL GetCursorPos(
LPPOINT lpPoint)
{
return (BOOL)NtUserCallOneParam((ULONG_PTR)lpPoint, SFI_XXXGETCURSORPOS);
}
FUNCLOG2(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, GetWindowRect, HWND, hwnd, LPRECT, prect)
BOOL GetWindowRect(
HWND hwnd,
LPRECT prect)
{
PWND pwnd;
pwnd = ValidateHwnd(hwnd);
if (pwnd == NULL) {
return FALSE;
}
_GetWindowRect(pwnd, prect);
return TRUE;
}
FUNCLOG2(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, ScreenToClient, HWND, hwnd, LPPOINT, ppoint)
BOOL ScreenToClient(
HWND hwnd,
LPPOINT ppoint)
{
PWND pwnd;
pwnd = ValidateHwnd(hwnd);
if (pwnd == NULL) {
return FALSE;
}
_ScreenToClient(pwnd, ppoint);
return TRUE;
}
FUNCLOG3(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, EnableMenuItem, HMENU, hMenu, UINT, uIDEnableItem, UINT, uEnable)
BOOL EnableMenuItem(
HMENU hMenu,
UINT uIDEnableItem,
UINT uEnable)
{
PMENU pMenu;
PITEM pItem;
pMenu = VALIDATEHMENU(hMenu);
if (pMenu == NULL) {
return (BOOL)-1;
}
/*
* Get a pointer the the menu item.
*/
if ((pItem = MNLookUpItem(pMenu, uIDEnableItem, (BOOL) (uEnable & MF_BYPOSITION), NULL)) == NULL) {
return (DWORD)-1;
}
/*
* If the item is already in the state we're
* trying to set, just return.
*/
if ((pItem->fState & MFS_GRAYED) == (uEnable & MFS_GRAYED)) {
return pItem->fState & MFS_GRAYED;
}
return NtUserEnableMenuItem(hMenu, uIDEnableItem, uEnable);
}
/***************************************************************************\
* CallNextHookEx
*
* This routine is called to call the next hook in the hook chain.
*
* 05-09-91 ScottLu Created.
\***************************************************************************/
FUNCLOG4(LOG_GENERAL, LRESULT, WINAPI, CallNextHookEx, HHOOK, hhk, int, nCode, WPARAM, wParam, LPARAM, lParam)
LRESULT WINAPI CallNextHookEx(
HHOOK hhk,
int nCode,
WPARAM wParam,
LPARAM lParam)
{
LRESULT nRet;
BOOL bAnsi;
DWORD dwHookCurrent;
PCLIENTINFO pci;
ULONG_PTR dwHookData;
ULONG_PTR dwFlags;
UNREFERENCED_PARAMETER(hhk);
ConnectIfNecessary(0);
pci = GetClientInfo();
dwHookCurrent = pci->dwHookCurrent;
bAnsi = LOWORD(dwHookCurrent);
/*
* If this is the last hook in the hook chain then return 0; we're done.
*/
if (PhkNextValid((PHOOK)((KERNEL_ULONG_PTR)pci->phkCurrent - pci->ulClientDelta)) == NULL) {
return 0;
}
switch ((INT)(SHORT)HIWORD(dwHookCurrent)) {
case WH_CALLWNDPROC:
case WH_CALLWNDPROCRET:
/*
* This is the hardest of the hooks because we need to thunk through
* the message hooks in order to deal with synchronously sent messages
* that point to structures - to get the structures passed across
* alright, etc.
*
* This will call a special kernel-side routine that'll rebundle the
* arguments and call the hook in the right format.
*
* Currently, the message thunk callbacks to the client-side don't take
* enough parameters to pass wParam (which == fInterThread send msg).
* To do this, save the state of wParam in the CLIENTINFO structure.
*/
dwFlags = KERNEL_ULONG_PTR_TO_ULONG_PTR(pci->CI_flags) & CI_INTERTHREAD_HOOK;
dwHookData = KERNEL_ULONG_PTR_TO_ULONG_PTR(pci->dwHookData);
if (wParam) {
pci->CI_flags |= CI_INTERTHREAD_HOOK;
} else {
pci->CI_flags &= ~CI_INTERTHREAD_HOOK;
}
if ((INT)(SHORT)HIWORD(dwHookCurrent) == WH_CALLWNDPROC) {
nRet = CsSendMessage(
((LPCWPSTRUCT)lParam)->hwnd,
((LPCWPSTRUCT)lParam)->message,
((LPCWPSTRUCT)lParam)->wParam,
((LPCWPSTRUCT)lParam)->lParam,
0, FNID_HKINLPCWPEXSTRUCT, bAnsi);
} else {
pci->dwHookData = ((LPCWPRETSTRUCT)lParam)->lResult;
nRet = CsSendMessage(
((LPCWPRETSTRUCT)lParam)->hwnd,
((LPCWPRETSTRUCT)lParam)->message,
((LPCWPRETSTRUCT)lParam)->wParam,
((LPCWPRETSTRUCT)lParam)->lParam,
0, FNID_HKINLPCWPRETEXSTRUCT, bAnsi);
}
/*
* Restore previous hook state.
*/
pci->CI_flags ^= ((pci->CI_flags ^ dwFlags) & CI_INTERTHREAD_HOOK);
pci->dwHookData = dwHookData;
break;
default:
nRet = NtUserCallNextHookEx(nCode, wParam, lParam, bAnsi);
}
return nRet;
}