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.
 
 
 
 
 
 

515 lines
17 KiB

/****************************** Module Header ******************************\
* Module Name: getsetc.c
*
* Copyright (c) 1985 - 1999, Microsoft Corporation
*
* This module contains window manager information routines
*
* History:
* 10-Mar-1993 JerrySh Pulled functions from user\server.
\***************************************************************************/
#include "precomp.h"
#pragma hdrstop
/***************************************************************************\
* _GetWindowWord (supports the GetWindowWord API)
*
* Return a window word. Positive index values return application window words
* while negative index values return system window words. The negative
* indices are published in WINDOWS.H.
*
* History:
* 11-26-90 darrinm Wrote.
\***************************************************************************/
WORD _GetWindowWord(
PWND pwnd,
int index)
{
if (GETFNID(pwnd) != 0) {
if ((index >= 0) && (index <
(int)(CBFNID(pwnd->fnid)-sizeof(WND)))) {
switch (GETFNID(pwnd)) {
case FNID_MDICLIENT:
if (index == 0)
break;
goto DoDefault;
case FNID_BUTTON:
/*
* CorelDraw does a get/set on the first button window word.
* Allow it to.
*/
if (index == 0) {
/*
* Since we now use a lookaside buffer for the control's
* private data, we need to indirect into this structure.
*/
PBUTN pbutn = ((PBUTNWND)pwnd)->pbutn;
if (!pbutn || (LONG_PTR)pbutn == (LONG_PTR)-1) {
return 0;
} else {
return (WORD)(pbutn->buttonState);
}
}
goto DoDefault;
case FNID_DIALOG:
if (index == DWLP_USER)
return LOWORD(((PDIALOG)pwnd)->unused);
if (index == DWLP_USER+2)
return HIWORD(((PDIALOG)pwnd)->unused);
goto DoDefault;
default:
DoDefault:
RIPERR3(ERROR_INVALID_INDEX,
RIP_WARNING,
"GetWindowWord: Trying to read private server data pwnd=(%#p) index=(%ld) fnid=(%lX)",
pwnd, index, (DWORD)pwnd->fnid);
return 0;
break;
}
}
}
if (index == GWLP_USERDATA)
return (WORD)pwnd->dwUserData;
if ((index < 0) || ((UINT)index + sizeof(WORD) > (UINT)pwnd->cbwndExtra)) {
RIPERR0(ERROR_INVALID_INDEX, RIP_VERBOSE, "");
return 0;
} else {
return *((WORD UNALIGNED * KPTR_MODIFIER)((KPBYTE)(pwnd + 1) + index));
}
}
ULONG_PTR GetWindowData(PWND pwnd, int index, BOOL bAnsi);
/***************************************************************************\
* _GetWindowLong (supports GetWindowLongA/W API)
*
* Return a window long. Positive index values return application window longs
* while negative index values return system window longs. The negative
* indices are published in WINDOWS.H.
*
* History:
* 11-26-90 darrinm Wrote.
\***************************************************************************/
ULONG_PTR _GetWindowLongPtr(
PWND pwnd,
int index,
BOOL bAnsi)
{
ULONG_PTR dwProc;
DWORD dwCPDType = 0;
ULONG_PTR UNALIGNED * KPTR_MODIFIER pudw;
/*
* If it's a dialog window, only a few indices are permitted.
*/
if (GETFNID(pwnd) != 0) {
if (TestWF(pwnd, WFDIALOGWINDOW)) {
switch (index) {
case DWLP_DLGPROC: // See similar case GWLP_WNDGPROC
/*
* Hide the window proc from other processes
*/
if (!TestWindowProcess(pwnd)) {
RIPERR1(ERROR_ACCESS_DENIED,
RIP_WARNING,
"Access denied to \"pwnd\" (%#p) in _GetWindowLong",
pwnd);
return 0;
}
dwProc = (ULONG_PTR)PDLG(pwnd)->lpfnDlg;
/*
* If a proc exists check it to see if we need a translation
*/
if (dwProc) {
/*
* May need to return a CallProc handle if there is an
* Ansi/Unicode transition
*/
if (bAnsi != ((PDLG(pwnd)->flags & DLGF_ANSI) ? TRUE : FALSE)) {
dwCPDType |= bAnsi ? CPD_ANSI_TO_UNICODE : CPD_UNICODE_TO_ANSI;
}
if (dwCPDType) {
ULONG_PTR cpd;
cpd = GetCPD(pwnd, dwCPDType | CPD_DIALOG, dwProc);
if (cpd) {
dwProc = cpd;
} else {
RIPMSG0(RIP_WARNING, "GetWindowLong unable to alloc CPD returning handle\n");
}
}
}
/*
* return proc (or CPD handle)
*/
return dwProc;
case DWLP_MSGRESULT:
return (ULONG_PTR)((PDIALOG)pwnd)->resultWP;
case DWLP_USER:
return (ULONG_PTR)((PDIALOG)pwnd)->unused;
default:
if (index >= 0 && index < DLGWINDOWEXTRA) {
RIPERR0(ERROR_PRIVATE_DIALOG_INDEX, RIP_VERBOSE, "");
return 0;
}
}
} else {
if (index >= 0 &&
(index < (int)(CBFNID(pwnd->fnid)-sizeof(WND)))) {
switch (GETFNID(pwnd)) {
case FNID_MDICLIENT:
/*
* Allow the 0 index (which is reserved) to be set/get.
* Quattro Pro 1.0 uses this index!
*/
if (index != 0)
break;
goto GetData;
break;
case FNID_EDIT:
if (index != 0)
break;
/*
* If we get to this point we need to return the first
* entry in the lookaside. This will provide backward
* compatibilty for 3.51 that allowed edit-controls to
* do this. PeachTree is one app which required this.
*/
pudw = (ULONG_PTR UNALIGNED * KPTR_MODIFIER)((KPBYTE)(pwnd + 1));
/*
* Do not dereference the pointer if we are not in
* the proper address space. Apps like Spyxx like to
* do this on other process' windows
*/
return (TestWindowProcess(pwnd) ? *(ULONG_PTR UNALIGNED *)*pudw : (ULONG_PTR)pudw);
}
RIPERR3(ERROR_INVALID_INDEX,
RIP_WARNING,
"GetWindowLong: Trying to read private server data pwnd=(%#p) index=(%ld) fnid (%lX)",
pwnd, index, (DWORD)pwnd->fnid);
return 0;
}
}
}
if (index < 0) {
return GetWindowData(pwnd, index, bAnsi);
} else {
if ((UINT)index + sizeof(ULONG_PTR) > (UINT)pwnd->cbwndExtra) {
RIPERR0(ERROR_INVALID_INDEX, RIP_VERBOSE, "");
return 0;
} else {
GetData:
pudw = (ULONG_PTR UNALIGNED * KPTR_MODIFIER)((KPBYTE)(pwnd + 1) + index);
return *pudw;
}
}
}
#ifdef _WIN64
DWORD _GetWindowLong(
PWND pwnd,
int index,
BOOL bAnsi)
{
DWORD UNALIGNED * KPTR_MODIFIER pudw;
/*
* If it's a dialog window, only a few indices are permitted.
*/
if (GETFNID(pwnd) != 0) {
if (TestWF(pwnd, WFDIALOGWINDOW)) {
switch (index) {
case DWLP_DLGPROC: // See similar case GWLP_WNDPROC
RIPERR1(ERROR_INVALID_INDEX, RIP_WARNING, "GetWindowLong: invalid index %d", index);
return 0;
case DWLP_MSGRESULT:
return (DWORD)((PDIALOG)pwnd)->resultWP;
case DWLP_USER:
return (DWORD)((PDIALOG)pwnd)->unused;
default:
if (index >= 0 && index < DLGWINDOWEXTRA) {
RIPERR0(ERROR_PRIVATE_DIALOG_INDEX, RIP_VERBOSE, "");
return 0;
}
}
} else {
if (index >= 0 &&
(index < (int)(CBFNID(pwnd->fnid)-sizeof(WND)))) {
switch (GETFNID(pwnd)) {
case FNID_MDICLIENT:
/*
* Allow the 0 index (which is reserved) to be set/get.
* Quattro Pro 1.0 uses this index!
*/
if (index != 0)
break;
goto GetData;
break;
case FNID_EDIT:
if (index != 0)
break;
/*
* If we get to this point we need to return the first
* entry in the lookaside. This will provide backward
* compatibilty for 3.51 that allowed edit-controls to
* do this. PeachTree is one app which required this.
*/
pudw = (DWORD UNALIGNED * KPTR_MODIFIER)((KPBYTE)(pwnd + 1));
/*
* Do not dereference the pointer if we are not in
* the proper address space. Apps like Spyxx like to
* do this on other process' windows
*/
return (TestWindowProcess(pwnd) ? *(DWORD UNALIGNED *)*(ULONG_PTR UNALIGNED *)pudw : PtrToUlong(pudw));
}
RIPERR3(ERROR_INVALID_INDEX,
RIP_WARNING,
"GetWindowLong: Trying to read private server data pwnd=(%#p) index=(%ld) fnid (%lX)",
pwnd, index, (DWORD)pwnd->fnid);
return 0;
}
}
}
if (index < 0) {
if ((index != GWL_STYLE) && (index != GWL_EXSTYLE) && (index != GWL_ID) && (index != GWLP_USERDATA)) {
RIPERR1(ERROR_INVALID_INDEX, RIP_WARNING, "GetWindowLong: invalid index %d", index);
return 0;
}
return (DWORD)GetWindowData(pwnd, index, bAnsi);
} else {
if ((UINT)index + sizeof(DWORD) > (UINT)pwnd->cbwndExtra) {
RIPERR0(ERROR_INVALID_INDEX, RIP_VERBOSE, "");
return 0;
} else {
GetData:
pudw = (DWORD UNALIGNED * KPTR_MODIFIER)((KPBYTE)(pwnd + 1) + index);
return *pudw;
}
}
}
#endif
/***************************************************************************\
* GetWindowData
*
* History:
* 11-26-90 darrinm Wrote.
\***************************************************************************/
ULONG_PTR GetWindowData(
PWND pwnd,
int index,
BOOL bAnsi)
{
KERNEL_ULONG_PTR dwProc;
DWORD dwCPDType = 0;
PWND pwndParent;
switch (index) {
case GWLP_USERDATA:
return KERNEL_ULONG_PTR_TO_ULONG_PTR(pwnd->dwUserData);
case GWL_EXSTYLE:
/*
* Apps should not mess with unused bits. We use them privately
*/
return pwnd->ExStyle & WS_EX_ALLVALID;
case GWL_STYLE:
return pwnd->style;
case GWLP_ID:
if (TestwndChild(pwnd)) {
return (ULONG_PTR)pwnd->spmenu;
} else if (pwnd->spmenu != NULL) {
PMENU pmenu;
pmenu = REBASEALWAYS(pwnd, spmenu);
return (ULONG_PTR)PtoH(pmenu);
}
return 0;
case GWLP_HINSTANCE:
return (ULONG_PTR)pwnd->hModule;
case GWLP_WNDPROC: // See similar case DWLP_DLGPROC
/*
* Hide the window proc from other processes
*/
if (!TestWindowProcess(pwnd)) {
RIPERR1(ERROR_ACCESS_DENIED, RIP_WARNING, "Can not subclass another process's window %#p", pwnd);
return 0;
}
/*
* If the client queries a server-side winproc we return the
* address of the client-side winproc (expecting ANSI or Unicode
* depending on bAnsi)
*/
if (TestWF(pwnd, WFSERVERSIDEPROC)) {
dwProc = MapServerToClientPfn((KERNEL_ULONG_PTR)pwnd->lpfnWndProc, bAnsi);
if (dwProc == 0)
RIPMSG1(RIP_WARNING, "GetWindowLong: GWL_WNDPROC: Kernel-side wndproc can't be mapped for pwnd=%#p", pwnd);
} else {
/*
* Keep edit control behavior compatible with NT 3.51.
*/
if (GETFNID(pwnd) == FNID_EDIT) {
dwProc = (ULONG_PTR)MapKernelClientFnToClientFn(pwnd->lpfnWndProc);
goto CheckAnsiUnicodeMismatch;
} else {
PCLS pcls = REBASEALWAYS(pwnd, pcls);
dwProc = MapClientNeuterToClientPfn(pcls, (KERNEL_ULONG_PTR)pwnd->lpfnWndProc, bAnsi);
}
/*
* If the client mapping didn't change the window proc then see if
* we need a callproc handle.
*/
if (dwProc == (KERNEL_ULONG_PTR)pwnd->lpfnWndProc) {
CheckAnsiUnicodeMismatch:
/*
* Need to return a CallProc handle if there is an Ansi/Unicode mismatch
*/
if (bAnsi != (TestWF(pwnd, WFANSIPROC) ? TRUE : FALSE)) {
dwCPDType |= bAnsi ? CPD_ANSI_TO_UNICODE : CPD_UNICODE_TO_ANSI;
}
}
if (dwCPDType) {
ULONG_PTR cpd;
cpd = GetCPD(pwnd, dwCPDType | CPD_WND, KERNEL_ULONG_PTR_TO_ULONG_PTR(dwProc));
if (cpd) {
dwProc = cpd;
} else {
RIPMSG0(RIP_WARNING, "GetWindowLong unable to alloc CPD returning handle\n");
}
}
}
/*
* return proc (or CPD handle)
*/
return KERNEL_ULONG_PTR_TO_ULONG_PTR(dwProc);
case GWLP_HWNDPARENT:
/*
* If the window is the desktop window, return
* NULL to keep it compatible with Win31 and
* to prevent any access to the desktop owner
* window.
*/
if (GETFNID(pwnd) == FNID_DESKTOP) {
return 0;
}
/*
* Special case for pre-1.1 versions of Windows
* Set/GetWindowWord(GWL_HWNDPARENT) needs to be mapped
* to the hwndOwner for top level windows.
*
* Note that we find the desktop window through the
* pti because the PWNDDESKTOP macro only works in
* the server.
*/
/*
* Remove this test when we later add a test for WFDESTROYED
* in Client handle validation.
*/
if (pwnd->spwndParent == NULL) {
return 0;
}
pwndParent = REBASEALWAYS(pwnd, spwndParent);
if (GETFNID(pwndParent) == FNID_DESKTOP) {
pwnd = REBASEPWND(pwnd, spwndOwner);
return (ULONG_PTR)HW(pwnd);
}
return (ULONG_PTR)HW(pwndParent);
/*
* WOW uses a pointer straight into the window structure.
*/
case GWLP_WOWWORDS:
return (ULONG_PTR) &pwnd->state;
}
RIPERR0(ERROR_INVALID_INDEX, RIP_VERBOSE, "");
return 0;
}
#ifdef GENERIC_INPUT
FUNCLOG3(LOG_GENERAL, UINT, DUMMYCALLINGTYPE, GetRawInputBuffer, PRAWINPUT, pData, PUINT, pcbSize, UINT, cbSizeHeader)
UINT GetRawInputBuffer(PRAWINPUT pData, PUINT pcbSize, UINT cbSizeHeader)
{
CLIENTTHREADINFO *pcti;
pcti = GETCLIENTTHREADINFO();
// Validate parameters
if (pcbSize == NULL || cbSizeHeader != sizeof(RAWINPUTHEADER)) {
RIPERR0(ERROR_INVALID_PARAMETER, RIP_VERBOSE, "");
return -1;
}
// Don't even go into the kernel if there's no reason to
if (pcti == NULL || (pcti->fsWakeBits & QS_RAWINPUT) == 0) {
*pcbSize = 0;
return 0;
}
return NtUserGetRawInputBuffer(pData, pcbSize, cbSizeHeader);
}
#endif // GENERIC_INPUT