|
|
/****************************** 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
|