Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

386 lines
11 KiB

/****************************** Module Header ******************************\
* Module Name: getset.c
*
* Copyright (c) 1985-91, Microsoft Corporation
*
* This module contains window manager information routines
*
* History:
* 10-22-90 MikeHar Ported functions from Win 3.0 sources.
* 13-Feb-1991 mikeke Added Revalidation code (None)
* 08-Feb-1991 IanJa Unicode/ANSI aware and neutral
\***************************************************************************/
DWORD MapServerToClientPfn(DWORD dw, BOOL bAnsi);
DWORD 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.
\***************************************************************************/
DWORD _GetWindowLong(
PWND pwnd,
int index,
BOOL bAnsi)
{
DWORD dwProc;
DWORD dwCPDType = 0;
DWORD UNALIGNED *pudw;
/*
* If it's a dialog window, only a few indices are permitted.
*/
if (GETFNID(pwnd) != 0) {
if (TestWF(pwnd, WFDIALOGWINDOW)) {
switch (index) {
case DWL_DLGPROC: // See similar case GWL_WNDGPROC
/*
* Hide the window proc from other processes
*/
if (!TestWindowProcess(pwnd)) {
RIPERR1(ERROR_ACCESS_DENIED,
RIP_WARNING,
"Access denied to \"pwnd\" (%#lx) in _GetWindowLong",
pwnd);
return 0;
}
dwProc = (DWORD)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) {
DWORD cpd;
cpd = (DWORD)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 DWL_MSGRESULT:
return (DWORD)((PDIALOG)pwnd)->resultWP;
case DWL_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 *)((BYTE *)(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 *)*pudw : (DWORD)pudw);
}
#ifndef _USERK_
RIPERR3(ERROR_INVALID_INDEX,
RIP_WARNING,
"GetWindowLong: Trying to read private server data pwnd=(%lX) index=(%ld) fnid (%lX)",
pwnd, index, (DWORD)pwnd->fnid);
return 0;
#endif
}
}
}
if (index < 0) {
return GetWindowData(pwnd, index, bAnsi);
} else {
if (index + (int)sizeof(DWORD) > pwnd->cbwndExtra) {
RIPERR0(ERROR_INVALID_INDEX, RIP_VERBOSE, "");
return 0;
} else {
GetData:
pudw = (DWORD UNALIGNED *)((BYTE *)(pwnd + 1) + index);
return *pudw;
}
}
}
/***************************************************************************\
* GetWindowData
*
* History:
* 11-26-90 darrinm Wrote.
\***************************************************************************/
DWORD GetWindowData(
PWND pwnd,
int index,
BOOL bAnsi)
{
DWORD dwProc;
DWORD dwCPDType = 0;
PWND pwndParent;
switch (index) {
case GWL_USERDATA:
return pwnd->dwUserData;
case GWL_EXSTYLE:
return pwnd->ExStyle;
case GWL_STYLE:
return pwnd->style;
case GWL_ID:
if (TestwndChild(pwnd)) {
return (DWORD)pwnd->spmenu;
} else if (pwnd->spmenu != NULL) {
PMENU pmenu;
pmenu = REBASEALWAYS(pwnd, spmenu);
return (DWORD)PtoH(pmenu);
}
return 0;
case GWL_HINSTANCE:
return (DWORD)pwnd->hModule;
case GWL_WNDPROC: // See similar case DWL_DLGPROC
/*
* Hide the window proc from other processes
*/
if (!TestWindowProcess(pwnd)) {
RIPERR1(ERROR_ACCESS_DENIED, RIP_WARNING, "Can not subclass another process's window %lX", 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 = (DWORD)MapServerToClientPfn((DWORD)pwnd->lpfnWndProc, bAnsi);
if (dwProc == 0)
RIPMSG1(RIP_WARNING, "GetWindowLong: GWL_WNDPROC: Kernel-side wndproc can't be mapped for pwnd=0x%X", pwnd);
} else {
/*
* Keep edit control behavior compatible with NT 3.51.
*/
if (GETFNID(pwnd) == FNID_EDIT) {
dwProc = (DWORD)pwnd->lpfnWndProc;
} else {
PCLS pcls = REBASEALWAYS(pwnd, pcls);
dwProc = MapClientNeuterToClientPfn(pcls, (DWORD)pwnd->lpfnWndProc, bAnsi);
}
/*
* If the client mapping didn't change the window proc then see if
* we need a callproc handle.
*/
if (dwProc == (DWORD)pwnd->lpfnWndProc) {
/*
* 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) {
DWORD cpd;
cpd = (DWORD)GetCPD(pwnd, dwCPDType | CPD_WND, 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 GWL_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 (DWORD)HW(pwnd);
}
return (DWORD)HW(pwndParent);
/*
* WOW uses a pointer straight into the window structure.
*/
case GWL_WOWWORDS:
return (DWORD) pwnd->adwWOW;
case GWL_WOWDWORD1:
return (DWORD) pwnd->adwWOW[0];
case GWL_WOWDWORD2:
return (DWORD) pwnd->adwWOW[1];
case GWL_WOWDWORD3:
return (DWORD) pwnd->adwWOW[2];
}
RIPERR0(ERROR_INVALID_INDEX, RIP_VERBOSE, "");
return 0;
}
/***************************************************************************\
* MapServerToClientPfn
*
* Returns the client wndproc representing the server wndproc passed in
*
* 01-13-92 ScottLu Created.
\***************************************************************************/
DWORD MapServerToClientPfn(
DWORD dw,
BOOL bAnsi)
{
int i;
for (i = FNID_WNDPROCSTART; i <= FNID_WNDPROCEND; i++) {
if ((WNDPROC_PWND)dw == STOCID(i)) {
if (bAnsi) {
return FNID_TO_CLIENT_PFNA(i);
} else {
return FNID_TO_CLIENT_PFNW(i);
}
}
}
return 0;
}
/***************************************************************************\
* MapClientNeuterToClientPfn
*
* Maps client Neuter routines like editwndproc to Ansi or Unicode versions
* and back again.
*
* 01-13-92 ScottLu Created.
\***************************************************************************/
DWORD MapClientNeuterToClientPfn(
PCLS pcls,
DWORD dw,
BOOL bAnsi)
{
/*
* Default to the class window proc.
*/
if (dw == 0) {
dw = (DWORD)pcls->lpfnWndProc;
}
/*
* If this is one of our controls and it hasn't been subclassed, try
* to return the correct ANSI/Unicode function.
*/
if (pcls->fnid >= FNID_CONTROLSTART && pcls->fnid <= FNID_CONTROLEND) {
if (!bAnsi) {
if (FNID_TO_CLIENT_PFNA(pcls->fnid) == dw)
return FNID_TO_CLIENT_PFNW(pcls->fnid);
} else {
if (FNID_TO_CLIENT_PFNW(pcls->fnid) == dw)
return FNID_TO_CLIENT_PFNA(pcls->fnid);
}
}
return dw;
}