|
|
/****************************** Module Header ******************************\
* Module Name: rare.c * * Copyright (c) 1985 - 1999, Microsoft Corporation * * History: * 06-28-91 MikeHar Created. \***************************************************************************/
#include "precomp.h"
#pragma hdrstop
/*
* MetricsRecalc flags */ #define CALC_RESIZE 0x0001
#define CALC_FRAME 0x0002
#define CALC_MINIMIZE 0x0004
/*
* NormalizeRect flags */ #define NORMALIZERECT_NORMAL 0
#define NORMALIZERECT_MAXIMIZED 1
#define NORMALIZERECT_FULLSCREEN 2
/***************************************************************************\
* SnapshotMonitorRects * * This is called from ResetDisplay to memorize the monitor positions so * DesktopRecalcEx will know where to move stuff. * * Returns the MONITORRECTS if succeeded, NULL otherwise. * * History: * 09-Dec-1996 adams Created. \***************************************************************************/ PMONITORRECTS SnapshotMonitorRects( VOID) { PMONITOR pMonitor; PMONITORRECTS pmr; PMONITORPOS pmp; #if DBG
ULONG cVisMon = 0; #endif
pmr = UserAllocPool(sizeof(MONITORRECTS) + sizeof(MONITORPOS) * (gpDispInfo->cMonitors - 1), TAG_MONITORRECTS);
if (!pmr) { RIPERR0(ERROR_OUTOFMEMORY, RIP_WARNING, "Out of memory in SnapshotMonitorRects"); return NULL; }
pmp = pmr->amp; for (pMonitor = gpDispInfo->pMonitorFirst; pMonitor; pMonitor = pMonitor->pMonitorNext) {
if (!(pMonitor->dwMONFlags & MONF_VISIBLE)) { continue; } #if DBG
cVisMon++; #endif
CopyRect(&pmp->rcMonitor, &pMonitor->rcMonitor); CopyRect(&pmp->rcWork, &pMonitor->rcWork);
/*
* If the device for this monitor object is not active, don't store * the pointer to it in the list. This way the windows on the inactive * monitor will be later moved to the default one. */ if (HdevFromMonitor(pMonitor) == -1) { pmp->pMonitor = NULL; } else { pmp->pMonitor = pMonitor; }
pmp++; } UserAssert(cVisMon == gpDispInfo->cMonitors);
pmr->cMonitor = (int)(pmp - pmr->amp);
return pmr; }
/***************************************************************************\
* UpdateMonitorRectsSnapShot * * Updates a Monitor rects snapshot. Every pMonitor in MONITORPOS is checked * to still be a valid monitor. If the pMonitor is no loger valid (deleted * by a ChangeDisplaySettings. it is zeroed so that its windows will be * repositioned on the primary monitor. This code is only used on by the * reconnect in TS scenario and is there for cases that are not happening * today: today reconnect always happens from disconnected state where we go * from 1 monitor (the disconnected display driver) to n monitors and this * monitor (starting in (0,0) never gets deleted because it alway matches one * of the new n monitors (the one starting in (0,0). So this code is just in * case of future changes. * * History: \***************************************************************************/ VOID UpdateMonitorRectsSnapShot( PMONITORRECTS pmr) { int i; PMONITORPOS pmp = pmr->amp;
for (i = 0; i < pmr->cMonitor; i++) { if (pmp->pMonitor != NULL) { if (!IsValidMonitor(pmp->pMonitor)) { pmp->pMonitor = NULL; } }
pmp++; } }
BOOL IsValidMonitor( PMONITOR pMonitor) { PMONITOR pMonitorNext = gpDispInfo->pMonitorFirst;
while (pMonitorNext != NULL) { if (pMonitorNext == pMonitor) { return TRUE; }
pMonitorNext = pMonitorNext->pMonitorNext; }
return FALSE; }
/***************************************************************************\
* NormalizeRect * * Adjusts a window rectangle when the working area changes. This can be * because of a tray move, with the resolution staying the same, or * because of a dynamic resolution change, with the tray staying the same * relatively. * * History: \***************************************************************************/ PMONITOR NormalizeRect( LPRECT lprcDest, LPRECT lprcSrc, PMONITORRECTS pmrOld, int iOldMonitor, int codeFullScreen, DWORD style) { LPCRECT lprcOldMonitor; LPCRECT lprcOldWork; LPRECT lprcNewWork; PMONITOR pMonitor; int cxOldMonitor; int cyOldMonitor; int cxNewMonitor; int cyNewMonitor; int dxOrg, dyOrg;
/*
* Track the window so it stays in the same place on the same monitor. * If the old monitor is no longer active then pick a default. */ if ((pMonitor = pmrOld->amp[iOldMonitor].pMonitor) == NULL) { pMonitor = GetPrimaryMonitor(); }
lprcOldMonitor = &pmrOld->amp[iOldMonitor].rcMonitor; lprcOldWork = &pmrOld->amp[iOldMonitor].rcWork;
/*
* If is a fullscreen app just make it fullscreen at the new location. */ if (codeFullScreen != NORMALIZERECT_NORMAL) { LPCRECT lprcOldSnap, lprcNewSnap;
/*
* If it is a maximized window snap it to the work area. Otherwise * it is a rude app so snap it to the screen. */ if (codeFullScreen == NORMALIZERECT_MAXIMIZED) { lprcOldSnap = lprcOldWork; lprcNewSnap = &pMonitor->rcWork; } else { lprcOldSnap = lprcOldMonitor; lprcNewSnap = &pMonitor->rcMonitor; }
lprcDest->left = lprcSrc->left + lprcNewSnap->left - lprcOldSnap->left;
lprcDest->top = lprcSrc->top + lprcNewSnap->top - lprcOldSnap->top;
lprcDest->right = lprcSrc->right + lprcNewSnap->right - lprcOldSnap->right;
lprcDest->bottom = lprcSrc->bottom + lprcNewSnap->bottom - lprcOldSnap->bottom;
goto AllDone; }
/*
* Offset the window by the change in desktop origin. */ dxOrg = pMonitor->rcMonitor.left - lprcOldMonitor->left; dyOrg = pMonitor->rcMonitor.top - lprcOldMonitor->top;
/*
* Calculate the change in screen size (we need it in more than one place). */ cxOldMonitor = lprcOldMonitor->right - lprcOldMonitor->left; cyOldMonitor = lprcOldMonitor->bottom - lprcOldMonitor->top; cxNewMonitor = pMonitor->rcMonitor.right - pMonitor->rcMonitor.left; cyNewMonitor = pMonitor->rcMonitor.bottom - pMonitor->rcMonitor.top;
/*
* If the monitor resolution has changed (or we moved to a new monitor) * then factor in the size change. */ if (cxNewMonitor != cxOldMonitor || cyNewMonitor != cyOldMonitor) { int xWnd = lprcSrc->left - lprcOldMonitor->left; int yWnd = lprcSrc->top - lprcOldMonitor->top;
dxOrg += MultDiv(xWnd, cxNewMonitor - cxOldMonitor, cxOldMonitor); dyOrg += MultDiv(yWnd, cyNewMonitor - cyOldMonitor, cyOldMonitor); }
/*
* Compute the initial new position. */ CopyOffsetRect(lprcDest, lprcSrc, dxOrg, dyOrg); lprcNewWork = &pMonitor->rcWork;
/*
* Fit horizontally. Try to fit so that the window isn't out of the * working area horizontally. Keep left edge visible always. */ if (lprcDest->right > lprcNewWork->right) { OffsetRect(lprcDest, lprcNewWork->right - lprcDest->right, 0); }
if (lprcDest->left < lprcNewWork->left) { OffsetRect(lprcDest, lprcNewWork->left - lprcDest->left, 0); }
/*
* Fit vertically. Try to fit so that the window isn't out of the * working area vertically. Keep top edge visible always. */ if (lprcDest->bottom > lprcNewWork->bottom) { OffsetRect(lprcDest, 0, lprcNewWork->bottom - lprcDest->bottom); }
if (lprcDest->top < lprcNewWork->top) { OffsetRect(lprcDest, 0, lprcNewWork->top - lprcDest->top); }
/*
* If the window is sizeable then shrink it if necessary. */ if (style & WS_THICKFRAME) { int cSnap = 0;
if (lprcDest->right > lprcNewWork->right) { lprcDest->right = lprcNewWork->right; cSnap++; }
if (lprcDest->bottom > lprcNewWork->bottom) { lprcDest->bottom = lprcNewWork->bottom; cSnap++; }
/*
* Now make sure we didn't turn this normal window into a * fullscreen window. This is a complete hack but it is much * better than changing from 800x600 to 640x480 and ending up with * a bunch of fullscreen apps... */ if (cSnap == 2) { InflateRect(lprcDest, -1, -1); } }
AllDone: return pMonitor; }
#if DBG
/***************************************************************************\
* SetRipFlags * * Sets the debug rip flags. * * History: * 16-Aug-1996 adams Created. \***************************************************************************/ VOID SetRipFlags( DWORD dwRipFlags) { if (gpsi) { if (!(dwRipFlags & ~RIPF_VALIDUSERFLAGS)) { gpsi->dwRIPFlags = ((gpsi->dwRIPFlags & ~RIPF_VALIDUSERFLAGS) | dwRipFlags); } } }
/***************************************************************************\
* SetDbgTag * * Sets debugging level for a tag. * * History: * 16-Aug-1996 adams Created. \***************************************************************************/ VOID SetDbgTag( int tag, DWORD dwDBGTAGFlags) { if (tag > DBGTAG_Max || tag < 0) { return; }
if (gpsi && tag < DBGTAG_Max && !(dwDBGTAGFlags & ~DBGTAG_VALIDUSERFLAGS)) { COPY_FLAG(gpsi->adwDBGTAGFlags[tag], dwDBGTAGFlags, DBGTAG_VALIDUSERFLAGS); } }
/***************************************************************************\
* SetDbgTagCount * * Sets the number of tags. This is necessary because one can use a * userkdx.dll that was built in an enlistment with N tags, but use it against * a system that has M tags (where N != M), which causes obvious problems. * * History: * 05-Oct-2001 JasonSch Created. \***************************************************************************/ VOID SetDbgTagCount( DWORD dwCount) { gpsi->dwTagCount = dwCount; } #endif
/***************************************************************************\
* UpdateWinIniInt * * History: * 18-Apr-1994 mikeke Created \***************************************************************************/ BOOL UpdateWinIniInt( PUNICODE_STRING pProfileUserName, UINT idSection, UINT wKeyNameId, int value) { WCHAR szTemp[40]; WCHAR szKeyName[40];
swprintf(szTemp, L"%d", value);
ServerLoadString(hModuleWin, wKeyNameId, szKeyName, ARRAY_SIZE(szKeyName));
return FastWriteProfileStringW(pProfileUserName, idSection, szKeyName, szTemp); }
/***************************************************************************\
* SetDesktopMetrics * * History: * 31-Jan-1994 mikeke Ported \***************************************************************************/ VOID SetDesktopMetrics( VOID) { LPRECT lprcWork;
lprcWork = &GetPrimaryMonitor()->rcWork;
SYSMET(CXFULLSCREEN) = lprcWork->right - lprcWork->left; SYSMET(CXMAXIMIZED) = lprcWork->right - lprcWork->left + 2 * SYSMET(CXSIZEFRAME);
SYSMET(CYFULLSCREEN) = lprcWork->bottom - lprcWork->top - SYSMET(CYCAPTION); SYSMET(CYMAXIMIZED) = lprcWork->bottom - lprcWork->top + 2 * SYSMET(CYSIZEFRAME); }
/***************************************************************************\
* xxxMetricsRecalc (Win95: MetricsRecalc) * * Does work to size/position all minimized or nonminimized * windows. Called when frame metrics or min metrics are changed. * * Note that you can NOT do DeferWindowPos() with this function. SWP doesn't * work when you do parents and children at the same time--it's only for * peer windows. Thus we must do SetWindowPos() for each window. * * History: * 06-28-91 MikeHar Ported. \***************************************************************************/ VOID xxxMetricsRecalc( UINT wFlags, int dx, int dy, int dyCaption, int dyMenu) { PHWND phwnd; PWND pwnd; RECT rc; PCHECKPOINT pcp; TL tlpwnd; BOOL fResized; PBWL pbwl; PTHREADINFO ptiCurrent; int c;
ptiCurrent = PtiCurrent(); pbwl = BuildHwndList(GETDESKINFO(ptiCurrent)->spwnd->spwndChild, BWL_ENUMLIST | BWL_ENUMCHILDREN, NULL);
if (!pbwl) { return; }
UserAssert(*pbwl->phwndNext == (HWND) 1); c = (int)(pbwl->phwndNext - pbwl->rghwnd); for (phwnd = pbwl->rghwnd; c > 0; c--, phwnd++) { pwnd = RevalidateHwnd(*phwnd); if (!pwnd) { continue; }
ThreadLockAlwaysWithPti(ptiCurrent, pwnd, &tlpwnd);
fResized = FALSE;
if ((wFlags & CALC_MINIMIZE) && TestWF(pwnd, WFMINIMIZED)) { /*
* We're changing the minimized window dimensions. We need to * resize. Note that we do NOT move. */ CopyRect(&rc, (&pwnd->rcWindow)); rc.right += dx; rc.bottom += dy;
goto PositionWnd; }
/*
* We're changing the size of the window because the sizing border * changed. */ if ((wFlags & CALC_RESIZE) && TestWF(pwnd, WFSIZEBOX)) { pcp = (PCHECKPOINT)_GetProp(pwnd, PROP_CHECKPOINT, PROPF_INTERNAL);
/*
* Update maximized position to account for sizing border * We do this for DOS box also. This way client of max'ed windows * stays in same relative position. */ if (pcp && (pcp->fMaxInitialized)) { pcp->ptMax.x -= dx; pcp->ptMax.y -= dy; }
if (TestWF(pwnd, WFMINIMIZED)) { if (pcp) { InflateRect(&pcp->rcNormal, dx, dy); } } else { CopyInflateRect(&rc, (&pwnd->rcWindow), dx, dy); if (TestWF(pwnd, WFCPRESENT)) { rc.bottom += dyCaption; } if (TestWF(pwnd, WFMPRESENT)) { rc.bottom += dyMenu; }
PositionWnd: fResized = TRUE;
/*
* Remember SWP expects values in PARENT CLIENT coordinates. */ if (pwnd->spwndParent != PWNDDESKTOP(pwnd)) { OffsetRect(&rc, -pwnd->spwndParent->rcClient.left, -pwnd->spwndParent->rcClient.top); }
xxxSetWindowPos(pwnd, PWND_TOP, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOCOPYBITS | SWP_FRAMECHANGED | SWP_NOREDRAW); } }
/*
* We're changing the nonclient widgets, so recalculate the client. */ if (wFlags & CALC_FRAME) { /*
* Delete any cached small icons. */ if (dyCaption) { xxxSendMessage(pwnd, WM_SETICON, ICON_RECREATE, 0); }
if (!TestWF(pwnd, WFMINIMIZED) && !fResized) { CopyRect(&rc, &(pwnd->rcWindow)); if (TestWF(pwnd, WFMPRESENT)) { rc.bottom += dyMenu; }
if (TestWF(pwnd, WFCPRESENT)) { rc.bottom += dyCaption;
/*
* Maximized MDI child windows position their caption * outside their parent's client area (negative y). If * the caption has changed, they need to be repositioned. */ if (TestWF(pwnd, WFMAXIMIZED) && TestWF(pwnd, WFCHILD) && (GETFNID(pwnd->spwndParent) == FNID_MDICLIENT)) {
xxxSetWindowPos(pwnd, PWND_TOP, rc.left - pwnd->spwndParent->rcWindow.left, rc.top - pwnd->spwndParent->rcWindow.top - dyCaption, rc.right - rc.left, rc.bottom - rc.top, SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED | SWP_NOREDRAW); goto LoopCleanup; } }
xxxSetWindowPos(pwnd, PWND_TOP, 0, 0, rc.right-rc.left, rc.bottom-rc.top, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED | SWP_NOCOPYBITS | SWP_NOREDRAW); } }
LoopCleanup: ThreadUnlock(&tlpwnd); }
FreeHwndList(pbwl); }
/***************************************************************************\
* FindOldMonitor * * Returns the index of the monitor in "pmr" which has the greatest * overlap with a rectangle. This function is used to determine which * monitor a window was on after one or more monitor rectangles have * changed. * * History: * 11-Sep-1996 adams Created. \***************************************************************************/ int FindOldMonitor( LPCRECT lprc, PMONITORRECTS pmr) { DWORD dwClosest; int iClosest, i; int cxRect, cyRect; PMONITORPOS pmp;
iClosest = -1; dwClosest = 0;
cxRect = (lprc->right - lprc->left); cyRect = (lprc->bottom - lprc->top);
for (i = 0, pmp = pmr->amp; i < pmr->cMonitor; pmp++, i++) { RECT rcT;
if (IntersectRect(&rcT, lprc, &pmp->rcMonitor)) { DWORD dwT;
/*
* Convert to width/height. */ rcT.right -= rcT.left; rcT.bottom -= rcT.top;
/*
* If fully enclosed, we're done. */ if (rcT.right == cxRect && rcT.bottom == cyRect) { return i; }
/*
* Use largest area. */ dwT = (DWORD)rcT.right * (DWORD)rcT.bottom; if (dwT > dwClosest) { dwClosest = dwT; iClosest = i; } } }
return iClosest; }
/***************************************************************************\
* xxxDesktopRecalc * * Moves all top-level nonpopup windows into free desktop area, * attempting to keep them in the same position relative to the monitor * they were on. Also resets minimized info (so that when a window is * subsequently minimized it will go to the correct location). * * History: * 11-Sep-1996 adams Created. \***************************************************************************/ VOID xxxDesktopRecalc( PMONITORRECTS pmrOld) { PWND pwndDesktop; PSMWP psmwp; PHWND phwnd; PBWL pbwl; PWND pwnd; CHECKPOINT * pcp; int iOldMonitor; int codeFullScreen; UINT flags = SWP_NOACTIVATE | SWP_NOZORDER;
/*
* We never want CSRSS to position windows synchronously because it * might get blocked by a hung app. CSRSS needs to reposition windows * in the TS reconnect and disconnect path as part of changing display * setting to switch display drivers or to match new client resolution. */ if (ISCSRSS()) { flags |= SWP_ASYNCWINDOWPOS; }
UserVerify(pwndDesktop = _GetDesktopWindow()); if ((pbwl = BuildHwndList(pwndDesktop->spwndChild, BWL_ENUMLIST, NULL)) == NULL) { return; }
if ((psmwp = InternalBeginDeferWindowPos(4)) != NULL) { for (phwnd = pbwl->rghwnd; *phwnd != (HWND)1 && psmwp; phwnd++) { /*
* Make sure this hwnd is still around. */ if ((pwnd = RevalidateHwnd(*phwnd)) == NULL || TestWF(pwnd, WEFTOOLWINDOW)) { continue; }
codeFullScreen = TestWF(pwnd, WFFULLSCREEN) ? NORMALIZERECT_FULLSCREEN : NORMALIZERECT_NORMAL;
pcp = (PCHECKPOINT)_GetProp(pwnd, PROP_CHECKPOINT, PROPF_INTERNAL); if (pcp) { /*
* We don't need to blow away saved maximized positions * anymore, since the max position is always (for top level * windows) relative to the origin of the monitor's working * area. And for child windows, we shouldn't do it period * anyway. */ pcp->fMinInitialized = FALSE;
/*
* Figure out which monitor the position was on before things * got shuffled around and try to keep it on that monitor. If * it was never visible on a monitor then leave it alone. */ iOldMonitor = FindOldMonitor(&pcp->rcNormal, pmrOld); if (iOldMonitor != (UINT)-1) { NormalizeRect(&pcp->rcNormal, &pcp->rcNormal, pmrOld, iOldMonitor, codeFullScreen, pwnd->style); } }
/*
* Figure out which monitor the position was on before things got * shuffled around and try to keep it on that monitor. If it * was never visible on a monitor then leave it alone. */ iOldMonitor = FindOldMonitor(&pwnd->rcWindow, pmrOld); if (iOldMonitor != -1) { PMONITOR pMonitorDst; RECT rc;
/*
* Check for maximized apps that are truly maximized (as * opposed to apps that manage their owm maximized rect). */ if (TestWF(pwnd, WFMAXIMIZED)) { LPRECT lprcOldWork = &pmrOld->amp[iOldMonitor].rcWork;
if ( (pwnd->rcWindow.right - pwnd->rcWindow.left >= lprcOldWork->right - lprcOldWork->left) && (pwnd->rcWindow.bottom - pwnd->rcWindow.top >= lprcOldWork->bottom - lprcOldWork->top)) {
codeFullScreen = NORMALIZERECT_MAXIMIZED; } }
pMonitorDst = NormalizeRect(&rc, &pwnd->rcWindow, pmrOld, iOldMonitor, codeFullScreen, pwnd->style);
if (TestWF(pwnd, WFMAXFAKEREGIONAL)) { UserAssert(pMonitorDst->hrgnMonitor); pwnd->hrgnClip = pMonitorDst->hrgnMonitor; }
psmwp = _DeferWindowPos(psmwp, pwnd, (PWND)HWND_TOP, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, flags); } }
if (psmwp) { xxxEndDeferWindowPosEx(psmwp, TRUE); } }
FreeHwndList(pbwl); }
/***************************************************************************\
* SetWindowMetricInt * * History: * 25-Feb-96 BradG Added Pixel -> TWIPS conversion \***************************************************************************/ BOOL SetWindowMetricInt( PUNICODE_STRING pProfileUserName, WORD wKeyNameId, int iIniValue) { /*
* If you change the below list of STR_* make sure you make a * corresponding change in FastGetProfileIntFromID. */ switch (wKeyNameId) { case STR_BORDERWIDTH: case STR_SCROLLWIDTH: case STR_SCROLLHEIGHT: case STR_CAPTIONWIDTH: case STR_CAPTIONHEIGHT: case STR_SMCAPTIONWIDTH: case STR_SMCAPTIONHEIGHT: case STR_MENUWIDTH: case STR_MENUHEIGHT: case STR_ICONHORZSPACING: case STR_ICONVERTSPACING: case STR_MINWIDTH: case STR_MINHORZGAP: case STR_MINVERTGAP: /*
* Always store window metrics in TWIPS */ iIniValue = -MultDiv(iIniValue, 72*20, gpsi->dmLogPixels); break; }
return UpdateWinIniInt(pProfileUserName, PMAP_METRICS, wKeyNameId, iIniValue); }
/***************************************************************************\
* SetWindowMetricFont * * History: \***************************************************************************/ BOOL SetWindowMetricFont( PUNICODE_STRING pProfileUserName, UINT idKey, LPLOGFONT lplf) { return FastWriteProfileValue(pProfileUserName, PMAP_METRICS, (LPWSTR)UIntToPtr(idKey), REG_BINARY, (LPBYTE)lplf, sizeof(LOGFONTW)); }
/***************************************************************************\
* SetAndDrawNCMetrics * * History: \***************************************************************************/ BOOL xxxSetAndDrawNCMetrics( PUNICODE_STRING pProfileUserName, int clNewBorder, LPNONCLIENTMETRICS lpnc) { int dl; int dxMinOld; int dyMinOld; int cxBorder; int cyBorder; int dyCaption; int dyMenu;
dl = clNewBorder - gpsi->gclBorder; dxMinOld = SYSMET(CXMINIMIZED); dyMinOld = SYSMET(CYMINIMIZED); cxBorder = SYSMET(CXBORDER); cyBorder = SYSMET(CYBORDER);
/*
* Do we need to recalculate? */ if (lpnc == NULL && !dl) { return FALSE; }
if (lpnc) { dyCaption = (int)lpnc->iCaptionHeight - SYSMET(CYSIZE); dyMenu = (int)lpnc->iMenuHeight - SYSMET(CYMENUSIZE); } else { dyCaption = dyMenu = 0; }
/*
* Recalculate the system metrics. */ xxxSetWindowNCMetrics(pProfileUserName, lpnc, TRUE, clNewBorder);
/*
* Reset our saved menu size/position info. */ MenuRecalc();
/*
* Reset window sized, positions, frames */ xxxMetricsRecalc(CALC_FRAME | (dl ? CALC_RESIZE : 0), dl * cxBorder, dl * cyBorder, dyCaption, dyMenu);
dxMinOld = SYSMET(CXMINIMIZED) - dxMinOld; dyMinOld = SYSMET(CYMINIMIZED) - dyMinOld; if (dxMinOld || dyMinOld) { xxxMetricsRecalc(CALC_MINIMIZE, dxMinOld, dyMinOld, 0, 0); }
xxxRedrawScreen();
return TRUE; }
/***************************************************************************\
* xxxSetAndDrawMinMetrics * * History: * 13-May-1994 mikeke mikeke Ported \***************************************************************************/ BOOL xxxSetAndDrawMinMetrics( PUNICODE_STRING pProfileUserName, LPMINIMIZEDMETRICS lpmin) { /*
* Save minimized window dimensions. */ int dxMinOld = SYSMET(CXMINIMIZED); int dyMinOld = SYSMET(CYMINIMIZED);
SetMinMetrics(pProfileUserName,lpmin);
/*
* Do we need to adjust minimized size? */ dxMinOld = SYSMET(CXMINIMIZED) - dxMinOld; dyMinOld = SYSMET(CYMINIMIZED) - dyMinOld;
if (dxMinOld || dyMinOld) { xxxMetricsRecalc(CALC_MINIMIZE, dxMinOld, dyMinOld, 0, 0); }
xxxRedrawScreen();
return TRUE; }
/***************************************************************************\
* xxxSPISetNCMetrics * * History: * 13-May-1994 mikeke mikeke Ported \***************************************************************************/ BOOL xxxSPISetNCMetrics( PUNICODE_STRING pProfileUserName, LPNONCLIENTMETRICS lpnc, BOOL fAlterWinIni) { BOOL fWriteAllowed = !fAlterWinIni; BOOL fChanged = FALSE;
lpnc->iBorderWidth = max(lpnc->iBorderWidth, 1); lpnc->iBorderWidth = min(lpnc->iBorderWidth, 50);
if (fAlterWinIni) { fChanged = SetWindowMetricInt(pProfileUserName, STR_BORDERWIDTH, lpnc->iBorderWidth); fChanged &= SetWindowMetricInt(pProfileUserName, STR_SCROLLWIDTH, lpnc->iScrollWidth); fChanged &= SetWindowMetricInt(pProfileUserName, STR_SCROLLHEIGHT, lpnc->iScrollHeight); fChanged &= SetWindowMetricInt(pProfileUserName, STR_CAPTIONWIDTH, lpnc->iCaptionWidth); fChanged &= SetWindowMetricInt(pProfileUserName, STR_CAPTIONHEIGHT, lpnc->iCaptionHeight); fChanged &= SetWindowMetricInt(pProfileUserName, STR_SMCAPTIONWIDTH, lpnc->iSmCaptionWidth); fChanged &= SetWindowMetricInt(pProfileUserName, STR_SMCAPTIONHEIGHT, lpnc->iSmCaptionHeight); fChanged &= SetWindowMetricInt(pProfileUserName, STR_MENUWIDTH, lpnc->iMenuWidth); fChanged &= SetWindowMetricInt(pProfileUserName, STR_MENUHEIGHT, lpnc->iMenuHeight);
fChanged &= SetWindowMetricFont(pProfileUserName, STR_CAPTIONFONT, &lpnc->lfCaptionFont); fChanged &= SetWindowMetricFont(pProfileUserName, STR_SMCAPTIONFONT, &lpnc->lfSmCaptionFont); fChanged &= SetWindowMetricFont(pProfileUserName, STR_MENUFONT, &lpnc->lfMenuFont); fChanged &= SetWindowMetricFont(pProfileUserName, STR_STATUSFONT, &lpnc->lfStatusFont); fChanged &= SetWindowMetricFont(pProfileUserName, STR_MESSAGEFONT, &lpnc->lfMessageFont);
fWriteAllowed = fChanged; }
if (fWriteAllowed) { xxxSetAndDrawNCMetrics(pProfileUserName, lpnc->iBorderWidth, lpnc); }
return fChanged; }
/***************************************************************************\
* xxxSPISetMinMetrics * * History: * 13-May-1994 mikeke mikeke Ported \***************************************************************************/ BOOL xxxSPISetMinMetrics( PUNICODE_STRING pProfileUserName, LPMINIMIZEDMETRICS lpmin, BOOL fAlterWinIni) { BOOL fWriteAllowed = !fAlterWinIni; BOOL fChanged = FALSE;
if (fAlterWinIni) { fChanged = SetWindowMetricInt(pProfileUserName, STR_MINWIDTH, lpmin->iWidth); fChanged &= SetWindowMetricInt(pProfileUserName, STR_MINHORZGAP, lpmin->iHorzGap); fChanged &= SetWindowMetricInt(pProfileUserName, STR_MINVERTGAP, lpmin->iVertGap); fChanged &= SetWindowMetricInt(pProfileUserName, STR_MINARRANGE, lpmin->iArrange);
fWriteAllowed = fChanged; }
if (fWriteAllowed) { xxxSetAndDrawMinMetrics(pProfileUserName, lpmin); }
return fChanged; }
/***************************************************************************\
* SPISetIconMetrics * * History: * 13-May-1994 mikeke mikeke Ported \***************************************************************************/ BOOL SPISetIconMetrics( PUNICODE_STRING pProfileUserName, LPICONMETRICS lpicon, BOOL fAlterWinIni) { BOOL fWriteAllowed = !fAlterWinIni; BOOL fChanged = FALSE;
if (fAlterWinIni) { fChanged = SetWindowMetricInt(pProfileUserName, STR_ICONHORZSPACING, lpicon->iHorzSpacing); fChanged &= SetWindowMetricInt(pProfileUserName, STR_ICONVERTSPACING, lpicon->iVertSpacing); fChanged &= SetWindowMetricInt(pProfileUserName, STR_ICONTITLEWRAP, lpicon->iTitleWrap); fChanged &= SetWindowMetricFont(pProfileUserName, STR_ICONFONT, &lpicon->lfFont);
fWriteAllowed = fChanged; }
if (fWriteAllowed) { SetIconMetrics(pProfileUserName,lpicon); xxxRedrawScreen(); }
return fChanged; }
/***************************************************************************\
* SPISetIconTitleFont * * History: * 13-May-1994 mikeke mikeke Ported \***************************************************************************/ BOOL SPISetIconTitleFont( PUNICODE_STRING pProfileUserName, LPLOGFONT lplf, BOOL fAlterWinIni) { HFONT hfnT; BOOL fWriteAllowed = !fAlterWinIni; BOOL fWinIniChanged = FALSE;
if (hfnT = CreateFontFromWinIni(pProfileUserName,lplf, STR_ICONFONT)) { if (fAlterWinIni) { if (lplf) { LOGFONT lf;
GreExtGetObjectW(hfnT, sizeof(LOGFONTW), &lf); fWinIniChanged = SetWindowMetricFont(pProfileUserName, STR_ICONFONT, &lf); } else { /*
* !lParam so go back to current win.ini settings. */ fWinIniChanged = TRUE; }
fWriteAllowed = fWinIniChanged; }
if (fWriteAllowed) { if (ghIconFont) { GreMarkDeletableFont(ghIconFont); GreDeleteObject(ghIconFont); }
ghIconFont = hfnT; } else { GreMarkDeletableFont(hfnT); GreDeleteObject(hfnT); } }
return fWinIniChanged; }
/***************************************************************************\
* xxxSetSPIMetrics * * History: * 13-May-1994 mikeke mikeke Ported \***************************************************************************/ BOOL xxxSetSPIMetrics( PUNICODE_STRING pProfileUserName, DWORD wFlag, LPVOID lParam, BOOL fAlterWinIni) { BOOL fWinIniChanged;
switch (wFlag) { case SPI_SETANIMATION: if (fAlterWinIni) { fWinIniChanged = SetWindowMetricInt(pProfileUserName, STR_MINANIMATE, (int)((LPANIMATIONINFO)lParam)->iMinAnimate);
if (!fWinIniChanged) { return FALSE; } } else { fWinIniChanged = FALSE; }
SET_OR_CLEAR_PUDF(PUDF_ANIMATE, ((LPANIMATIONINFO)lParam)->iMinAnimate); return fWinIniChanged;
case SPI_SETNONCLIENTMETRICS: return xxxSPISetNCMetrics(pProfileUserName, (LPNONCLIENTMETRICS)lParam, fAlterWinIni);
case SPI_SETICONMETRICS: return SPISetIconMetrics(pProfileUserName, (LPICONMETRICS)lParam, fAlterWinIni);
case SPI_SETMINIMIZEDMETRICS: return xxxSPISetMinMetrics(pProfileUserName, (LPMINIMIZEDMETRICS)lParam, fAlterWinIni);
case SPI_SETICONTITLELOGFONT: return SPISetIconTitleFont(pProfileUserName, (LPLOGFONT)lParam, fAlterWinIni);
default: RIPERR1(ERROR_INVALID_PARAMETER, RIP_WARNING, "SetSPIMetrics. Invalid wFlag: 0x%x", wFlag); return FALSE; } }
/***************************************************************************\
* SetFilterKeys * * History: * 10-12-94 JimA Created. \***************************************************************************/ BOOL SetFilterKeys( PUNICODE_STRING pProfileUserName, LPFILTERKEYS pFilterKeys) { LPWSTR pwszd = L"%d"; BOOL fWinIniChanged; WCHAR szTemp[40];
swprintf(szTemp, pwszd, pFilterKeys->dwFlags); fWinIniChanged = FastWriteProfileStringW(pProfileUserName, PMAP_KEYBOARDRESPONSE, L"Flags", szTemp);
swprintf(szTemp, pwszd, pFilterKeys->iWaitMSec); fWinIniChanged &= FastWriteProfileStringW(pProfileUserName, PMAP_KEYBOARDRESPONSE, L"DelayBeforeAcceptance", szTemp);
swprintf(szTemp, pwszd, pFilterKeys->iDelayMSec); fWinIniChanged &= FastWriteProfileStringW(pProfileUserName, PMAP_KEYBOARDRESPONSE, L"AutoRepeatDelay", szTemp);
swprintf(szTemp, pwszd, pFilterKeys->iRepeatMSec); fWinIniChanged &= FastWriteProfileStringW(pProfileUserName, PMAP_KEYBOARDRESPONSE, L"AutoRepeatRate", szTemp);
swprintf(szTemp, pwszd, pFilterKeys->iBounceMSec); fWinIniChanged &= FastWriteProfileStringW(pProfileUserName, PMAP_KEYBOARDRESPONSE, L"BounceTime", szTemp);
return fWinIniChanged; }
/***************************************************************************\
* SetMouseKeys * * History: * 10-12-94 JimA Created. \***************************************************************************/ BOOL SetMouseKeys( PUNICODE_STRING pProfileUserName, LPMOUSEKEYS pMK) { LPWSTR pwszd = L"%d"; BOOL fWinIniChanged; WCHAR szTemp[40];
swprintf(szTemp, pwszd, pMK->dwFlags); fWinIniChanged = FastWriteProfileStringW(pProfileUserName, PMAP_MOUSEKEYS, L"Flags", szTemp);
swprintf(szTemp, pwszd, pMK->iMaxSpeed); fWinIniChanged &= FastWriteProfileStringW(pProfileUserName, PMAP_MOUSEKEYS, L"MaximumSpeed", szTemp);
swprintf(szTemp, pwszd, pMK->iTimeToMaxSpeed); fWinIniChanged &= FastWriteProfileStringW(pProfileUserName, PMAP_MOUSEKEYS, L"TimeToMaximumSpeed", szTemp);
return fWinIniChanged; }
/***************************************************************************\
* SetSoundSentry * * History: * 10-12-94 JimA Created. \***************************************************************************/ BOOL SetSoundSentry( PUNICODE_STRING pProfileUserName, LPSOUNDSENTRY pSS) { LPWSTR pwszd = L"%d"; BOOL fWinIniChanged; WCHAR szTemp[40];
swprintf(szTemp, pwszd, pSS->dwFlags); fWinIniChanged = FastWriteProfileStringW(pProfileUserName, PMAP_SOUNDSENTRY, L"Flags", szTemp);
swprintf(szTemp, pwszd, pSS->iFSTextEffect); fWinIniChanged &= FastWriteProfileStringW(pProfileUserName, PMAP_SOUNDSENTRY, L"TextEffect", szTemp);
swprintf(szTemp, pwszd, pSS->iWindowsEffect); fWinIniChanged &= FastWriteProfileStringW(pProfileUserName, PMAP_SOUNDSENTRY, L"WindowsEffect", szTemp);
return fWinIniChanged; }
/***************************************************************************\
* CalculateMouseSensitivity * * The resultant table looks like this... * * Sens | Sensitivity Adjustment * 0 | 0 * SENS_SCALAR ALGORITHM 0<=NUM<=2 * 1 | 1/32 * SENS_SCALAR (NUM/32)*SENS_SCALAR * 2 | 1/16 * SENS_SCALAR * 3 | 1/8 * SENS_SCALAR ALGORITHM 3<=NUM<=10 * 4 | 1/4 (2/8) * SENS_SCALAR ((NUM-2)/8)*SENS_SCALAR * 5 | 3/8 * SENS_SCALAR * 6 | 1/2 (4/8) * SENS_SCALAR * 7 | 5/8 * SENS_SCALAR * 8 | 3/4 (6/8) * SENS_SCALAR * 9 | 7/8 * SENS_SCALAR * 10 | 1 * SENS_SCALAR * 11 | 5/4 * SENS_SCALAR ALGORITHM NUM>=11 * 12 | 3/2 (6/4) * SENS_SCALAR ((NUM-6)/4)*SENS_SCALAR * 13 | 7/4 * SENS_SCALAR * 14 | 2 (8/4) * SENS_SCALAR * 15 | 9/4 * SENS_SCALAR * 16 | 5/2 (10/4) * SENS_SCALAR * 17 | 11/4 * SENS_SCALAR * 18 | 3 (12/4) * SENS_SCALAR * 19 | 13/4 * SENS_SCALAR * 20 | 7/2 (14/4) * SENS_SCALAR * * COMMENTS: Sensitivities are constrained to be between 1 and 20. * * History: * 09-27-96 jparsons Created. \***************************************************************************/ LONG CalculateMouseSensitivity( LONG lSens) { LONG lSenFactor;
if (lSens <= 2) { lSenFactor = lSens * 256 / 32; } else if (lSens >= 3 && lSens <= 10 ) { lSenFactor = (lSens - 2) * 256 /8; } else { lSenFactor= (lSens - 6) * 256 / 4; }
return lSenFactor; }
/***************************************************************************\
* xxxSystemParametersInfo * * SPI_GETBEEP: wParam is not used. lParam is long pointer to a boolean which * gets true if beep on, false if beep off. * * SPI_SETBEEP: wParam is a bool which sets beep on (true) or off (false). * lParam is not used. * * SPI_GETMOUSE: wParam is not used. lParam is long pointer to an integer * array where rgw[0] gets xMouseThreshold, rgw[1] gets * yMouseThreshold, and rgw[2] gets gMouseSpeed. * * SPI_SETMOUSE: wParam is not used. lParam is long pointer to an integer * array as described above. User's values are set to values * in array. * * SPI_GETBORDER: wParam is not used. lParam is long pointer to an integer * which gets the value of clBorder (border multiplier factor). * * SPI_SETBORDER: wParam is an integer which sets gpsi->gclBorder. * lParam is not used. * * SPI_GETKEYBOARDDELAY: wParam is not used. lParam is a long pointer to an int * which gets the current keyboard repeat delay setting. * * SPI_SETKEYBOARDDELAY: wParam is the new keyboard delay setting. * lParam is not used. * * SPI_GETKEYBOARDSPEED: wParam is not used. lParam is a long pointer * to an int which gets the current keyboard repeat * speed setting. * * SPI_SETKEYBOARDSPEED: wParam is the new keyboard speed setting. * lParam is not used. * * SPI_KANJIMENU: wParam contains: * 1 - Mouse accelerator * 2 - ASCII accelerator * 3 - Kana accelerator * lParam is not used. The wParam value is stored in the global * KanjiMenu for use in accelerator displaying & searching. * * SPI_LANGDRIVER: wParam is not used. * lParam contains a LPSTR to the new language driver filename. * * SPI_ICONHORIZONTALSPACING: wParam is the width in pixels of an icon cell. * * SPI_ICONVERTICALSPACING: wParam is the height in pixels of an icon cell. * * SPI_GETSCREENSAVETIMEOUT: wParam is not used * lParam is a pointer to an int which gets the screen saver * timeout value. * * SPI_SETSCREENSAVETIMEOUT: wParam is the time in seconds for the system * to be idle before screensaving. * * SPI_GETSCREENSAVEACTIVE: lParam is a pointer to a BOOL which gets TRUE * if the screensaver is active else gets false. * * SPI_SETSCREENSAVEACTIVE: if wParam is TRUE, screensaving is activated * else it is deactivated. * * * SPI_SETBLOCKSENDINPUTRESETS: * SPI_GETBLOCKSENDINPUTRESETS: * wParam is BOOL signifying if this is active or not. * * SPI_GETLOWPOWERTIMEOUT: * SPI_GETPOWEROFFTIMEOUT: wParam is not used * lParam is a pointer to an int which gets the appropriate * power saving screen blanker timeout value. * * SPI_SETLOWPOWERTIMEOUT: * SPI_SETPOWEROFFTIMEOUT: wParam is the time in seconds for the system * to be idle before power saving screen blanking. * * SPI_GETLOWPOWERACTIVE: * SPI_GETPOWEROFFACTIVE: lParam is a pointer to a BOOL which gets TRUE * if the power saving screen blanker is active else gets false. * * SPI_SETLOWPOWERACTIVE: * SPI_SETPOWEROFFACTIVE: if wParam is TRUE, power saving screen blanking is * activated else it is deactivated. * * SPI_GETGRIDGRANULARITY: Obsolete. Returns 1 always. * * SPI_SETGRIDGRANULARITY: Obsolete. Does nothing. * * SPI_SETDESKWALLPAPER: wParam is not used; lParam is a long ptr to a string * that holds the name of the bitmap file to be used as the * desktop wall paper. * * SPI_SETDESKPATTERN: Both wParam and lParam are not used; USER will read the * "pattern=" from WIN.INI and make it as the current desktop * pattern; * * SPI_GETICONTITLEWRAP: lParam is LPINT which gets 0 if wrapping if off * else gets 1. * * SPI_SETICONTITLEWRAP: wParam specifies TRUE to turn wrapping on else false * * SPI_GETMENUDROPALIGNMENT: lParam is LPINT which gets 0 specifies if menus * drop left aligned else 1 if drop right aligned. * * SPI_SETMENUDROPALIGNMENT: wParam 0 specifies if menus drop left aligned else * the drop right aligned. * * SPI_SETDOUBLECLKWIDTH: wParam specifies the width of the rectangle * within which the second click of a double click must fall * for it to be registered as a double click. * * SPI_SETDOUBLECLKHEIGHT: wParam specifies the height of the rectangle * within which the second click of a double click must fall * for it to be registered as a double click. * * SPI_GETICONTITLELOGFONT: lParam is a pointer to a LOGFONT struct which * gets the logfont for the current icon title font. wParam * specifies the size of the logfont struct. * * SPI_SETDOUBLECLICKTIME: wParm specifies the double click time * * SPI_SETMOUSEBUTTONSWAP: if wParam is 1, swap mouse buttons else if wParam * is 0, don't swap buttons * SPI_SETDRAGFULLWINDOWS: wParam = fSet. * SPI_GETDRAGFULLWINDOWS: returns fSet. * * SPI_GETFILTERKEYS: lParam is a pointer to a FILTERKEYS struct. wParam * specifies the size of the filterkeys struct. * * SPI_SETFILTERKEYS: lParam is a pointer to a FILTERKEYS struct. wParam * is not used. * * SPI_GETSTICKYKEYS: lParam is a pointer to a STICKYKEYS struct. wParam * specifies the size of the stickykeys struct. * * SPI_SETSTICKYKEYS: lParam is a pointer to a STICKYKEYS struct. wParam * is not used. * * SPI_GETMOUSEKEYS: lParam is a pointer to a MOUSEKEYS struct. wParam * specifies the size of the mousekeys struct. * * SPI_SETMOUSEKEYS: lParam is a pointer to a MOUSEKEYS struct. wParam * is not used. * * SPI_GETACCESSTIMEOUT: lParam is a pointer to an ACCESSTIMEOUT struct. * wParam specifies the size of the accesstimeout struct. * * SPI_SETACCESSTIMEOUT: lParam is a pointer to a ACCESSTIMEOUT struct. * wParam is not used. * * SPI_GETTOGGLEKEYS: lParam is a pointer to a TOGGLEKEYS struct. wParam * specifies the size of the togglekeys struct. * * SPI_SETTOGGLEKEYS: lParam is a pointer to a TOGGLEKEYS struct. wParam * is not used. * * SPI_GETKEYBOARDPREF: lParam is a pointer to a BOOL. * wParam is not used. * * SPI_SETKEYBOARDPREF: wParam is a BOOL. * lParam is not used. * * SPI_GETSCREENREADER: lParam is a pointer to a BOOL. * wParam is not used. * * SPI_SETSCREENREADER: wParam is a BOOL. * lParam is not used. * * SPI_GETSHOWSOUNDS: lParam is a pointer to a SHOWSOUNDS struct. wParam * specifies the size of the showsounds struct. * * SPI_SETSHOWSOUNDS: lParam is a pointer to a SHOWSOUNDS struct. wParam * is not used. * * SPI_GETNONCLIENTMETRICS: lParam is a pointer to a NONCLIENTMETRICSW struct. * wPAram is not used. * * SPI_GETSNAPTODEFBUTTON: lParam is a pointer to a BOOL which gets TRUE * if the snap to default push button is active else gets false. * * SPI_SETSNAPTODEFBUTTON: if wParam is TRUE, dialog boxes will snap the mouse * pointer to the default push button when created. * * SPI_GETFONTSMOOTHING: * wParam is unused * lParam is LPINT for boolean fFontSmoothing * * SPI_SETFONTSMOOTHING: * wParam is INT for boolean fFontSmoothing * * SPI_GETWHEELSCROLLLINES: lParam is a pointer to a ULONG to receive the * suggested number of lines to scroll when the wheel is * rotated. wParam is unused. * * SPI_SETWHEELSCROLLLINES: wParam is a ULONG containing the suggested number * of lines to scroll when the wheel is rotated. lParam is * unused. * * SPI_SETSCREENSAVERRUNNING / SPI_SCREENSAVERRUNNING: not supported on NT. * SPI_GETSCREENSAVERRUNNING: wParam - Not used. lParam a pointer to a BOOL which * will receive TRUE is a screen saver is running or FALSE otherwise. * * SPI_SETSHOWIMEUI wParam is TRUE or FALSE * SPI_GETSHOWIMEUI neither wParam or lParam used * * History: * 06-28-91 MikeHar Ported. * 12-8-93 SanfordS Added SPI_SET/GETDRAGFULLWINDOWS * 20-May-1996 adams Added SPI_SET/GETWHEELSCROLLLINES * 02-Feb-2002 MMcCr Added SPI_SET/GETBLOCKSENDINPUTRESETS \***************************************************************************/ BOOL xxxSystemParametersInfo( UINT wFlag, DWORD wParam, PVOID lParam, UINT flags) { PPROCESSINFO ppi = PpiCurrent(); LPWSTR pwszd = L"%d"; WCHAR szSection[40]; WCHAR szTemp[40]; WCHAR szPat[MAX_PATH]; BOOL fWinIniChanged = FALSE; BOOL fAlterWinIni = ((flags & SPIF_UPDATEINIFILE) != 0); BOOL fSendWinIniChange = ((flags & SPIF_SENDCHANGE) != 0); BOOL fWriteAllowed = !fAlterWinIni; ACCESS_MASK amRequest; LARGE_UNICODE_STRING strSection; int *piTimeOut; int iResID; TL tlName; PUNICODE_STRING pProfileUserName = NULL;
UserAssert(IsWinEventNotifyDeferredOK());
/*
* CONSIDER(adams): Many of the SPI_GET* could be implemented * on the client side (SnapTo, WheelScrollLines, etc.). */
/*
* Features not implemented. */ switch (wFlag) { case SPI_TIMEOUTS: case SPI_KANJIMENU: case SPI_LANGDRIVER: case SPI_UNUSED39: case SPI_UNUSED40: case SPI_SETPENWINDOWS:
case SPI_GETWINDOWSEXTENSION: case SPI_SETSCREENSAVERRUNNING: // same as SPI_SCREENSAVERRUNNING
case SPI_GETSERIALKEYS: case SPI_SETSERIALKEYS: RIPERR1(ERROR_INVALID_PARAMETER, RIP_WARNING, "SPI_ 0x%lx parameter not supported", wFlag);
return FALSE; }
/*
* Perform access check. Always grant access to CSR. */ if (ppi->Process != gpepCSRSS) { switch (wFlag) { case SPI_SETBEEP: case SPI_SETMOUSE: case SPI_SETBORDER: case SPI_SETKEYBOARDSPEED: case SPI_SETDEFAULTINPUTLANG: case SPI_SETSCREENSAVETIMEOUT: case SPI_SETSCREENSAVEACTIVE: case SPI_SETBLOCKSENDINPUTRESETS: case SPI_SETLOWPOWERTIMEOUT: case SPI_SETPOWEROFFTIMEOUT: case SPI_SETLOWPOWERACTIVE: case SPI_SETPOWEROFFACTIVE: case SPI_SETGRIDGRANULARITY: case SPI_SETDESKWALLPAPER: case SPI_SETDESKPATTERN: case SPI_SETKEYBOARDDELAY: case SPI_SETICONTITLEWRAP: case SPI_SETMENUDROPALIGNMENT: case SPI_SETDOUBLECLKWIDTH: case SPI_SETDOUBLECLKHEIGHT: case SPI_SETDOUBLECLICKTIME: case SPI_SETMOUSEBUTTONSWAP: case SPI_SETICONTITLELOGFONT: case SPI_SETFASTTASKSWITCH: case SPI_SETFILTERKEYS: case SPI_SETTOGGLEKEYS: case SPI_SETMOUSEKEYS: case SPI_SETSHOWSOUNDS: case SPI_SETSTICKYKEYS: case SPI_SETACCESSTIMEOUT: case SPI_SETSOUNDSENTRY: case SPI_SETKEYBOARDPREF: case SPI_SETSCREENREADER: case SPI_SETSNAPTODEFBUTTON: case SPI_SETANIMATION: case SPI_SETNONCLIENTMETRICS: case SPI_SETICONMETRICS: case SPI_SETMINIMIZEDMETRICS: case SPI_SETWORKAREA:
case SPI_SETFONTSMOOTHING: case SPI_SETMOUSEHOVERWIDTH: case SPI_SETMOUSEHOVERHEIGHT: case SPI_SETMOUSEHOVERTIME: case SPI_SETWHEELSCROLLLINES: case SPI_SETMENUSHOWDELAY: case SPI_SETHIGHCONTRAST: case SPI_SETDRAGFULLWINDOWS: case SPI_SETDRAGWIDTH: case SPI_SETDRAGHEIGHT: case SPI_SETCURSORS: case SPI_SETICONS: case SPI_SETLANGTOGGLE: amRequest = WINSTA_WRITEATTRIBUTES; break;
case SPI_ICONHORIZONTALSPACING: case SPI_ICONVERTICALSPACING: if (IS_PTR(lParam)) { amRequest = WINSTA_READATTRIBUTES; } else if (wParam) { amRequest = WINSTA_WRITEATTRIBUTES; } else { return TRUE; } break;
default: if ((wFlag & SPIF_RANGETYPEMASK) && (wFlag & SPIF_SET)) { amRequest = WINSTA_WRITEATTRIBUTES; } else { amRequest = WINSTA_READATTRIBUTES; } break; }
if (amRequest == WINSTA_READATTRIBUTES) { RETURN_IF_ACCESS_DENIED(ppi->amwinsta, amRequest, FALSE); } else { UserAssert(amRequest == WINSTA_WRITEATTRIBUTES); if (!CheckWinstaWriteAttributesAccess()) { return FALSE; } }
/*
* If we're reading, then set the write flag to ensure that the * return value will be TRUE. */ if (amRequest == WINSTA_READATTRIBUTES) { fWriteAllowed = TRUE; } } else { fWriteAllowed = TRUE; }
/*
* Make sure the section buffer is terminated. */ szSection[0] = 0;
switch (wFlag) { case SPI_GETBEEP: (*(BOOL *)lParam) = TEST_BOOL_PUDF(PUDF_BEEP); break;
case SPI_SETBEEP: if (fAlterWinIni) { ServerLoadString(hModuleWin, (wParam ? STR_BEEPYES : STR_BEEPNO), (LPWSTR)szTemp, 10);
fWinIniChanged = FastUpdateWinIni(NULL, PMAP_BEEP, STR_BEEP, szTemp);
fWriteAllowed = fWinIniChanged; }
if (fWriteAllowed) { SET_OR_CLEAR_PUDF(PUDF_BEEP, wParam); }
break;
case SPI_SETMOUSESPEED: if (((LONG_PTR) lParam < MOUSE_SENSITIVITY_MIN) || ((LONG_PTR) lParam > MOUSE_SENSITIVITY_MAX)) { return FALSE; }
if (fAlterWinIni) { swprintf(szTemp, pwszd, lParam); fWinIniChanged = FastUpdateWinIni(NULL, PMAP_MOUSE, STR_MOUSESENSITIVITY, szTemp);
fWriteAllowed = fWinIniChanged; }
if (fWriteAllowed) { gMouseSensitivity = PtrToLong(lParam); gMouseSensitivityFactor = CalculateMouseSensitivity(PtrToLong(lParam));
#ifdef SUBPIXEL_MOUSE
ResetMouseAccelerationCurves(); #endif // SUBPIXEL_MOUSE
} break;
case SPI_GETMOUSESPEED: *((LPINT)lParam) = gMouseSensitivity; break;
case SPI_SETMOUSETRAILS: if (fAlterWinIni) { swprintf(szTemp, pwszd, wParam); fWinIniChanged = FastUpdateWinIni(NULL, PMAP_MOUSE, STR_MOUSETRAILS, szTemp); fWriteAllowed = fWinIniChanged; }
if (fWriteAllowed) { SetMouseTrails(wParam); } break;
case SPI_GETMOUSETRAILS: *((LPINT)lParam) = gMouseTrails ? gMouseTrails + 1 : gMouseTrails; break;
case SPI_GETMOUSE: ((LPINT)lParam)[0] = gMouseThresh1; ((LPINT)lParam)[1] = gMouseThresh2; ((LPINT)lParam)[2] = gMouseSpeed; break;
case SPI_SETMOUSE: if (fAlterWinIni) { BOOL bWritten1, bWritten2, bWritten3;
pProfileUserName = CreateProfileUserName(&tlName); bWritten1 = UpdateWinIniInt(pProfileUserName, PMAP_MOUSE, STR_MOUSETHRESH1, ((LPINT)lParam)[0]); bWritten2 = UpdateWinIniInt(pProfileUserName, PMAP_MOUSE, STR_MOUSETHRESH2, ((LPINT)lParam)[1]); bWritten3 = UpdateWinIniInt(pProfileUserName, PMAP_MOUSE, STR_MOUSESPEED, ((LPINT)lParam)[2]); if (bWritten1 && bWritten2 && bWritten3) { fWinIniChanged = TRUE; } else { /*
* Attempt to backout any changes. */ if (bWritten1) { UpdateWinIniInt(pProfileUserName, PMAP_MOUSE, STR_MOUSETHRESH1, gMouseThresh1); } if (bWritten2) { UpdateWinIniInt(pProfileUserName, PMAP_MOUSE, STR_MOUSETHRESH2, gMouseThresh2); } if (bWritten3) { UpdateWinIniInt(pProfileUserName, PMAP_MOUSE, STR_MOUSESPEED, gMouseSpeed); } } fWriteAllowed = fWinIniChanged; FreeProfileUserName(pProfileUserName, &tlName); }
if (fWriteAllowed) { gMouseThresh1 = ((LPINT)lParam)[0]; gMouseThresh2 = ((LPINT)lParam)[1]; gMouseSpeed = ((LPINT)lParam)[2]; } break;
case SPI_GETSNAPTODEFBUTTON: (*(LPBOOL)lParam) = TEST_BOOL_PUSIF(PUSIF_SNAPTO); break;
case SPI_SETSNAPTODEFBUTTON: wParam = (wParam != 0);
if (fAlterWinIni) { fWinIniChanged = UpdateWinIniInt(NULL, PMAP_MOUSE, STR_SNAPTO, wParam); fWriteAllowed = fWinIniChanged; }
if (fWriteAllowed) { SET_OR_CLEAR_PUSIF(PUSIF_SNAPTO, wParam); }
break;
case SPI_GETBORDER: (*(LPINT)lParam) = gpsi->gclBorder; break;
case SPI_SETBORDER: wParam = max((int)wParam, 1); wParam = min(wParam, 50);
if (wParam == gpsi->gclBorder) { /*
* If border size doesn't change, don't waste time. */ break; }
pProfileUserName = CreateProfileUserName(&tlName);
if (fAlterWinIni) { fWinIniChanged = SetWindowMetricInt(pProfileUserName, STR_BORDERWIDTH, wParam); fWriteAllowed = fWinIniChanged; }
if (fWriteAllowed) { xxxSetAndDrawNCMetrics(pProfileUserName, wParam, NULL);
/*
* Nice magic number of 3. So if the border is set to 1, there * are actualy 4 pixels in the border. */ bSetDevDragWidth(gpDispInfo->hDev, gpsi->gclBorder + BORDER_EXTRA); }
FreeProfileUserName(pProfileUserName, &tlName); break;
case SPI_GETFONTSMOOTHING: (*(LPINT)lParam) = !!(GreGetFontEnumeration() & FE_AA_ON); break;
case SPI_SETFONTSMOOTHING: if (CheckDesktopPolicy(NULL, (PCWSTR)STR_FONTSMOOTHING)) { fAlterWinIni = FALSE; fWriteAllowed = FALSE; }
wParam = (wParam ? FE_AA_ON : 0); if (fAlterWinIni) { fWinIniChanged = UpdateWinIniInt(NULL,PMAP_DESKTOP, STR_FONTSMOOTHING, wParam); fWriteAllowed = fWinIniChanged; }
if (fWriteAllowed) { GreSetFontEnumeration(wParam | FE_SET_AA); } break;
case SPI_GETKEYBOARDSPEED: (*(int *)lParam) = (gnKeyboardSpeed & KSPEED_MASK); break;
case SPI_SETKEYBOARDSPEED: /*
* Limit the range to max value; SetKeyboardRate takes both speed * and delay. */ if (wParam > KSPEED_MASK) { // KSPEED_MASK == KSPEED_MAX
wParam = KSPEED_MASK; }
if (fAlterWinIni) { fWinIniChanged = UpdateWinIniInt(NULL,PMAP_KEYBOARD, STR_KEYSPEED, wParam); fWriteAllowed = fWinIniChanged; }
if (fWriteAllowed) { gnKeyboardSpeed = (gnKeyboardSpeed & ~KSPEED_MASK) | wParam; SetKeyboardRate(gnKeyboardSpeed); } break;
case SPI_GETKEYBOARDDELAY: (*(int *)lParam) = (gnKeyboardSpeed & KDELAY_MASK) >> KDELAY_SHIFT; break;
case SPI_SETKEYBOARDDELAY: if (fAlterWinIni) { fWinIniChanged = UpdateWinIniInt(NULL,PMAP_KEYBOARD, STR_KEYDELAY, wParam); fWriteAllowed = fWinIniChanged; } if (fWriteAllowed) { gnKeyboardSpeed = (gnKeyboardSpeed & ~KDELAY_MASK) | (wParam << KDELAY_SHIFT); SetKeyboardRate(gnKeyboardSpeed); } break;
case SPI_SETLANGTOGGLE:
/*
* wParam unused, lParam unused. Simply reread the registry setting. */ return GetKbdLangSwitch(NULL);
break;
case SPI_GETDEFAULTINPUTLANG: /*
* wParam unused. lParam is a pointer to buffer to store hkl. */ UserAssert(gspklBaseLayout != NULL); (*(HKL *)lParam) = gspklBaseLayout->hkl; break;
case SPI_SETDEFAULTINPUTLANG: { PKL pkl; /*
* wParam unused. lParam is new language of hkl (depending on * whether the hiword is set). */ pkl = HKLtoPKL(PtiCurrent(), *(HKL *)lParam); if (pkl == NULL) { return FALSE; } if (fWriteAllowed) { Lock(&gspklBaseLayout, pkl); } break; }
case SPI_ICONHORIZONTALSPACING: if (IS_PTR(lParam)) { *(LPINT)lParam = SYSMET(CXICONSPACING); } else if (wParam) {
/*
* Make sure icon spacing is reasonable. */ wParam = max(wParam, (DWORD)SYSMET(CXICON));
if (fAlterWinIni) { fWinIniChanged = SetWindowMetricInt(NULL, STR_ICONHORZSPACING, wParam ); fWriteAllowed = fWinIniChanged; }
if (fWriteAllowed) { SYSMET(CXICONSPACING) = (UINT)wParam; } } break;
case SPI_ICONVERTICALSPACING: if (IS_PTR(lParam)) { *(LPINT)lParam = SYSMET(CYICONSPACING); } else if (wParam) { wParam = max(wParam, (DWORD)SYSMET(CYICON));
if (fAlterWinIni) { fWinIniChanged = SetWindowMetricInt(NULL, STR_ICONVERTSPACING, wParam); fWriteAllowed = fWinIniChanged; }
if (fWriteAllowed) { SYSMET(CYICONSPACING) = (UINT)wParam; } } break;
case SPI_GETSCREENSAVETIMEOUT: piTimeOut = &giScreenSaveTimeOutMs; goto HandleGetTimeouts;
case SPI_GETLOWPOWERTIMEOUT: if (!NT_SUCCESS(DrvGetMonitorPowerState(gpDispInfo->pmdev, PowerDeviceD1))) { return FALSE; } piTimeOut = &giLowPowerTimeOutMs; goto HandleGetTimeouts;
case SPI_GETPOWEROFFTIMEOUT: if (!NT_SUCCESS(DrvGetMonitorPowerState(gpDispInfo->pmdev, PowerDeviceD3))) { return FALSE; } piTimeOut = &giPowerOffTimeOutMs;
HandleGetTimeouts: /*
* If the screen saver is disabled, store this fact as a negative * time out value (we give the Control Panel the absolute value * of the screen saver time out). We store this in milliseconds. */ if (*piTimeOut < 0) { (*(int *)lParam) = -*piTimeOut / 1000; } else { (*(int *)lParam) = *piTimeOut / 1000; } break;
case SPI_SETSCREENSAVETIMEOUT: piTimeOut = &giScreenSaveTimeOutMs; iResID = STR_SCREENSAVETIMEOUT; goto HandleSetTimeouts;
case SPI_SETLOWPOWERTIMEOUT: if (!NT_SUCCESS(DrvGetMonitorPowerState(gpDispInfo->pmdev, PowerDeviceD1))) { return FALSE; } piTimeOut = &giLowPowerTimeOutMs; iResID = STR_LOWPOWERTIMEOUT; goto HandleSetTimeouts;
case SPI_SETPOWEROFFTIMEOUT: if (!NT_SUCCESS(DrvGetMonitorPowerState(gpDispInfo->pmdev, PowerDeviceD3))) { return FALSE; } piTimeOut = &giPowerOffTimeOutMs; iResID = STR_POWEROFFTIMEOUT;
HandleSetTimeouts: if (gfSwitchInProgress) { return FALSE; }
/*
* Maintain the screen save active/inactive state when setting the * time out value. Timeout value is given in seconds but stored * in milliseconds */ if (CheckDesktopPolicy(NULL, (PCWSTR)IntToPtr(iResID))) { fAlterWinIni = FALSE; fWriteAllowed = FALSE; } if (fAlterWinIni) { fWinIniChanged = UpdateWinIniInt(NULL,PMAP_DESKTOP, iResID, wParam); fWriteAllowed = fWinIniChanged; } if (fWriteAllowed) { if (glinp.dwFlags & LINP_POWERTIMEOUTS) { // Call video driver here to exit power down mode.
// KdPrint(("Exit video power down mode\n"));
DrvSetMonitorPowerState(gpDispInfo->pmdev, PowerDeviceD0); } glinp.dwFlags &= ~LINP_INPUTTIMEOUTS; if (!gbBlockSendInputResets) { glinp.timeLastInputMessage = NtGetTickCount(); }
if (*piTimeOut < 0) { *piTimeOut = -((int)wParam); } else { *piTimeOut = wParam; } *piTimeOut *= 1000; } break;
case SPI_GETBLOCKSENDINPUTRESETS: (*(BOOL *)lParam) = (gbBlockSendInputResets != 0); break;
case SPI_GETSCREENSAVEACTIVE: (*(BOOL *)lParam) = (giScreenSaveTimeOutMs > 0); break;
case SPI_GETLOWPOWERACTIVE: if (!NT_SUCCESS(DrvGetMonitorPowerState(gpDispInfo->pmdev, PowerDeviceD1))) { return FALSE; } (*(BOOL *)lParam) = (giLowPowerTimeOutMs > 0); break;
case SPI_GETPOWEROFFACTIVE: if (!NT_SUCCESS(DrvGetMonitorPowerState(gpDispInfo->pmdev, PowerDeviceD3))) { return FALSE; } (*(BOOL *)lParam) = (giPowerOffTimeOutMs > 0); break;
case SPI_SETSCREENSAVEACTIVE: piTimeOut = &giScreenSaveTimeOutMs; iResID = STR_SCREENSAVEACTIVE; goto HandleSetActive;
case SPI_SETLOWPOWERACTIVE: if (!NT_SUCCESS(DrvGetMonitorPowerState(gpDispInfo->pmdev, PowerDeviceD1))) { return FALSE; } piTimeOut = &giLowPowerTimeOutMs; iResID = STR_LOWPOWERACTIVE; goto HandleSetActive;
case SPI_SETPOWEROFFACTIVE: if (!NT_SUCCESS(DrvGetMonitorPowerState(gpDispInfo->pmdev, PowerDeviceD3))) { return FALSE; } piTimeOut = &giPowerOffTimeOutMs; iResID = STR_POWEROFFACTIVE;
HandleSetActive: if (gfSwitchInProgress) { return FALSE; }
wParam = (wParam != 0);
if (CheckDesktopPolicy(NULL, (PCWSTR)IntToPtr(iResID))) { fAlterWinIni = FALSE; fWriteAllowed = FALSE; } if (fAlterWinIni) { fWinIniChanged = UpdateWinIniInt(NULL,PMAP_DESKTOP, iResID, wParam); fWriteAllowed = fWinIniChanged; } if (fWriteAllowed) { if (glinp.dwFlags & LINP_POWERTIMEOUTS) { // Call video driver here to exit power down mode.
// KdPrint(("Exit video power down mode\n"));
DrvSetMonitorPowerState(gpDispInfo->pmdev, PowerDeviceD0); } glinp.dwFlags &= ~LINP_INPUTTIMEOUTS;
if (!gbBlockSendInputResets) { glinp.timeLastInputMessage = NtGetTickCount(); }
if ((*piTimeOut < 0 && wParam) || (*piTimeOut >= 0 && !wParam)) { *piTimeOut = -*piTimeOut; } } break;
case SPI_SETBLOCKSENDINPUTRESETS: wParam = (wParam != 0); if (CheckDesktopPolicy(NULL, (PCWSTR)IntToPtr(STR_BLOCKSENDINPUTRESETS))) { fAlterWinIni = FALSE; fWriteAllowed = FALSE; } if (fAlterWinIni) { fWinIniChanged = UpdateWinIniInt(NULL,PMAP_DESKTOP, STR_BLOCKSENDINPUTRESETS, wParam); fWriteAllowed = fWinIniChanged; } if (fWriteAllowed) { gbBlockSendInputResets = wParam; } break;
case SPI_SETDESKWALLPAPER: pProfileUserName = CreateProfileUserName(&tlName); if (CheckDesktopPolicy(pProfileUserName, (PCWSTR)STR_DTBITMAP)) { fAlterWinIni = FALSE; fWriteAllowed = FALSE; }
if (fAlterWinIni) { if (wParam != (WPARAM)-1) { /*
* Save current wallpaper in case of failure. * * Unlike the rest of the per-user settings that got updated * in xxxUpdatePerUserSystemParameters, the wallpaper is * being updated via a direct call to SystemParametersInfo * from UpdatePerUserSystemParameters. Force remote settings * check in this case. */ FastGetProfileStringFromIDW(pProfileUserName, PMAP_DESKTOP, STR_DTBITMAP, TEXT(""), szPat, ARRAY_SIZE(szPat), POLICY_REMOTE);
fWinIniChanged = FastUpdateWinIni(pProfileUserName, PMAP_DESKTOP, STR_DTBITMAP, (LPWSTR)lParam);
fWriteAllowed = fWinIniChanged; } else { fWriteAllowed = TRUE; } }
if (fWriteAllowed) { if (xxxSetDeskWallpaper(pProfileUserName,(LPWSTR)lParam)) { if (grpdeskRitInput) { xxxInternalInvalidate(grpdeskRitInput->pDeskInfo->spwnd, HRGN_FULL, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN); } } else if (fAlterWinIni && (wParam != 0xFFFFFFFF)) { /*
* Backout any change to win.ini. */ FastUpdateWinIni(pProfileUserName,PMAP_DESKTOP, STR_DTBITMAP, szPat); fWinIniChanged = FALSE; fWriteAllowed = fWinIniChanged; } else if (!fAlterWinIni) { /*
* Bug 304109 - joejo * Make sure we return a 0 retval if we didn't do anything! */ fWinIniChanged = FALSE; fWriteAllowed = fWinIniChanged; } } FreeProfileUserName(pProfileUserName, &tlName); break;
case SPI_GETDESKWALLPAPER: /*
* Get the string from the gobal var, not the registry, as it's * more current. */ if (gpszWall != NULL) { /*
* Copy the global wallpaper name ONLY if noni-null. */ wcscpy(lParam, gpszWall); } else { /*
* Null out the string so no garbage can corrupt the user's * buffer. */ (*(LPWSTR)lParam) = (WCHAR)0; } break;
case SPI_SETDESKPATTERN: { BOOL fRet;
if (wParam == -1 && lParam != 0) { return FALSE; }
pProfileUserName = CreateProfileUserName(&tlName); if (CheckDesktopPolicy(pProfileUserName, (PCWSTR)STR_DESKPATTERN)) { fAlterWinIni = FALSE; fWriteAllowed = FALSE; }
if (fAlterWinIni && wParam != -1) { /*
* Save the current pattern in case of failure. */ FastGetProfileStringFromIDW(pProfileUserName, PMAP_DESKTOP, STR_DESKPATTERN, TEXT(""), szPat, ARRAY_SIZE(szPat), 0);
fWinIniChanged = FastUpdateWinIni(pProfileUserName, PMAP_DESKTOP, STR_DESKPATTERN, (LPWSTR)lParam);
fWriteAllowed = fWinIniChanged; }
if (fWriteAllowed) { fRet = xxxSetDeskPattern(pProfileUserName, wParam == -1 ? (LPWSTR)-1 : (LPWSTR)lParam, FALSE);
if (!fRet) { /*
* Back out any change to win.ini. */ if (fAlterWinIni && wParam != -1) { FastUpdateWinIni(pProfileUserName, PMAP_DESKTOP, STR_DESKPATTERN, szPat); }
FreeProfileUserName(pProfileUserName, &tlName); return FALSE; } } } FreeProfileUserName(pProfileUserName, &tlName); break;
case SPI_GETICONTITLEWRAP: *((int *)lParam) = TEST_BOOL_PUDF(PUDF_ICONTITLEWRAP); break;
case SPI_SETICONTITLEWRAP: wParam = (wParam != 0); if (fAlterWinIni) { fWinIniChanged = SetWindowMetricInt(NULL, STR_ICONTITLEWRAP, wParam); fWriteAllowed = fWinIniChanged; } if (fWriteAllowed) { SET_OR_CLEAR_PUDF(PUDF_ICONTITLEWRAP, wParam); xxxMetricsRecalc(CALC_FRAME, 0, 0, 0, 0); } break;
case SPI_SETDRAGWIDTH: if (CheckDesktopPolicy(NULL, (PCWSTR)STR_DRAGWIDTH)) { fAlterWinIni = FALSE; fWriteAllowed = FALSE; } if (fAlterWinIni) { fWinIniChanged = UpdateWinIniInt(NULL, PMAP_DESKTOP, STR_DRAGWIDTH, wParam); fWriteAllowed = fWinIniChanged; } if (fWriteAllowed) { SYSMET(CXDRAG) = wParam; } break;
case SPI_SETDRAGHEIGHT: if (CheckDesktopPolicy(NULL, (PCWSTR)STR_DRAGHEIGHT)) { fAlterWinIni = FALSE; fWriteAllowed = FALSE; } if (fAlterWinIni) { fWinIniChanged = UpdateWinIniInt(NULL, PMAP_DESKTOP, STR_DRAGHEIGHT, wParam); fWriteAllowed = fWinIniChanged; } if (fWriteAllowed) { SYSMET(CYDRAG) = wParam; } break;
case SPI_GETMENUDROPALIGNMENT: (*(int *)lParam) = (SYSMET(MENUDROPALIGNMENT)); break;
case SPI_SETMENUDROPALIGNMENT: if (fAlterWinIni) { fWinIniChanged = UpdateWinIniInt(NULL, PMAP_WINDOWSU, STR_MENUDROPALIGNMENT, wParam); fWriteAllowed = fWinIniChanged; } if (fWriteAllowed) { SYSMET(MENUDROPALIGNMENT) = (BOOL)(wParam != 0); } break;
case SPI_SETDOUBLECLKWIDTH: if (fAlterWinIni) { fWinIniChanged = UpdateWinIniInt(NULL, PMAP_MOUSE, STR_DOUBLECLICKWIDTH, wParam); fWriteAllowed = fWinIniChanged; } if (fWriteAllowed) { SYSMET(CXDOUBLECLK) = wParam; } break;
case SPI_SETDOUBLECLKHEIGHT: if (fAlterWinIni) { fWinIniChanged = UpdateWinIniInt(NULL, PMAP_MOUSE, STR_DOUBLECLICKHEIGHT, wParam); fWriteAllowed = fWinIniChanged; } if (fWriteAllowed) { SYSMET(CYDOUBLECLK) = wParam; } break;
case SPI_GETICONTITLELOGFONT: GreExtGetObjectW(ghIconFont, sizeof(LOGFONTW), lParam); break;
case SPI_SETICONTITLELOGFONT: { if (lParam != NULL) { if (wParam != sizeof(LOGFONTW)) { return FALSE; } } else if (wParam) { return FALSE; }
pProfileUserName = CreateProfileUserName(&tlName); fWinIniChanged = xxxSetSPIMetrics(pProfileUserName, wFlag, lParam, fAlterWinIni); FreeProfileUserName(pProfileUserName, &tlName); if (fAlterWinIni) { fWriteAllowed = fWinIniChanged; } break; }
case SPI_SETDOUBLECLICKTIME: if (fAlterWinIni) { fWinIniChanged = UpdateWinIniInt(NULL,PMAP_MOUSE, STR_DBLCLKSPEED, wParam); fWriteAllowed = fWinIniChanged; } if (fWriteAllowed) { _SetDoubleClickTime((UINT)wParam); } break;
case SPI_GETANIMATION: { LPANIMATIONINFO lpai = (LPANIMATIONINFO) lParam;
if (lpai == NULL || wParam != sizeof(ANIMATIONINFO)) { return FALSE; }
lpai->cbSize = sizeof(ANIMATIONINFO); lpai->iMinAnimate = TEST_BOOL_PUDF(PUDF_ANIMATE);
break; }
case SPI_GETNONCLIENTMETRICS: { LPNONCLIENTMETRICS lpnc = (LPNONCLIENTMETRICS) lParam; if (lpnc == NULL) { return FALSE; }
GetWindowNCMetrics(lpnc); break; }
case SPI_GETMINIMIZEDMETRICS: { LPMINIMIZEDMETRICS lpmin = (LPMINIMIZEDMETRICS)lParam;
lpmin->cbSize = sizeof(MINIMIZEDMETRICS);
lpmin->iWidth = SYSMET(CXMINIMIZED) - 2 * SYSMET(CXFIXEDFRAME); lpmin->iHorzGap = SYSMET(CXMINSPACING) - SYSMET(CXMINIMIZED); lpmin->iVertGap = SYSMET(CYMINSPACING) - SYSMET(CYMINIMIZED); lpmin->iArrange = SYSMET(ARRANGE);
break; }
case SPI_GETICONMETRICS: { LPICONMETRICS lpicon = (LPICONMETRICS)lParam;
lpicon->cbSize = sizeof(ICONMETRICS);
lpicon->iHorzSpacing = SYSMET(CXICONSPACING); lpicon->iVertSpacing = SYSMET(CYICONSPACING); lpicon->iTitleWrap = TEST_BOOL_PUDF(PUDF_ICONTITLEWRAP); GreExtGetObjectW(ghIconFont, sizeof(LOGFONTW), &(lpicon->lfFont));
break; }
case SPI_SETANIMATION: case SPI_SETNONCLIENTMETRICS: case SPI_SETICONMETRICS: case SPI_SETMINIMIZEDMETRICS: { fWinIniChanged = xxxSetSPIMetrics(NULL, wFlag, lParam, fAlterWinIni); if (fAlterWinIni) { fWriteAllowed = fWinIniChanged; } ServerLoadString(hModuleWin, STR_METRICS, szSection, ARRAY_SIZE(szSection)); break; } case SPI_SETMOUSEBUTTONSWAP: if (fAlterWinIni) { fWinIniChanged = UpdateWinIniInt(NULL, PMAP_MOUSE, STR_SWAPBUTTONS, wParam); fWriteAllowed = fWinIniChanged; } if (fWriteAllowed) { _SwapMouseButton((wParam != 0)); } break;
case SPI_GETFASTTASKSWITCH: *((PINT)lParam) = TRUE; // Do the work so we don't anger anybody.
case SPI_SETFASTTASKSWITCH: RIPMSG0(RIP_WARNING,"SPI_SETFASTTASKSWITCH and SPI_GETFASTTASKSWITCH are obsolete actions."); break;
case SPI_GETWORKAREA: CopyRect((LPRECT)lParam, &GetPrimaryMonitor()->rcWork); break;
case SPI_SETWORKAREA: { RECT rcNewWork; LPRECT lprcNewWork; PMONITOR pMonitorWork;
lprcNewWork = (LPRECT)lParam;
/*
* Validate Rectangle. */ if (lprcNewWork != NULL && (lprcNewWork->right < lprcNewWork->left || lprcNewWork->bottom < lprcNewWork->top)) {
RIPMSG0(RIP_WARNING, "Bad work rectangle passed to SystemParametersInfo(SPI_SETWORKAREA, ...)\n"); return FALSE; }
/*
* Figure out which monitor has the working area. */ if (!lprcNewWork) { pMonitorWork = GetPrimaryMonitor(); lprcNewWork = &pMonitorWork->rcMonitor; } else { pMonitorWork = _MonitorFromRect(lprcNewWork, MONITOR_DEFAULTTOPRIMARY); }
/*
* Get new working area, clipped to monitor of course. */ if (!IntersectRect(&rcNewWork, lprcNewWork, &pMonitorWork->rcMonitor) || !EqualRect(&rcNewWork, lprcNewWork)) { /*
* Complain. */ RIPERR4( ERROR_INVALID_PARAMETER, RIP_WARNING, "Bad work rectangle passed to SystemParametersInfo(SPI_SETWORKAREA, ...) %d, %d, %d, %d", lprcNewWork->left, lprcNewWork->top, lprcNewWork->right, lprcNewWork->bottom); return FALSE; }
if (!EqualRect(&pMonitorWork->rcWork, &rcNewWork)) { PMONITORRECTS pmr;
/*
* If we are going to reposition windows, remember the old * monitor positions for xxxDesktopRecalc. */ if (wParam) { pmr = SnapshotMonitorRects(); if (!pmr) { return FALSE; } }
pMonitorWork->rcWork = rcNewWork; if (pMonitorWork == GetPrimaryMonitor()) { SetDesktopMetrics(); }
/*
* Reposition windows. */ if (wParam) { TL tlPool;
ThreadLockPool(PtiCurrent(), pmr, &tlPool); xxxDesktopRecalc(pmr); ThreadUnlockAndFreePool(PtiCurrent(), &tlPool); }
fWinIniChanged = TRUE; }
fWriteAllowed = TRUE; break; }
case SPI_SETDRAGFULLWINDOWS: if (CheckDesktopPolicy(NULL, (PCWSTR)STR_DRAGFULLWINDOWS)) { fAlterWinIni = FALSE; fWriteAllowed = FALSE; } wParam = (wParam == 1); if (fAlterWinIni) { fWinIniChanged = UpdateWinIniInt(NULL, PMAP_DESKTOP, STR_DRAGFULLWINDOWS, wParam); fWriteAllowed = fWinIniChanged; } if (fWriteAllowed) { SET_OR_CLEAR_PUDF(PUDF_DRAGFULLWINDOWS, wParam); } break;
case SPI_GETDRAGFULLWINDOWS: *((PINT)lParam) = TEST_BOOL_PUDF(PUDF_DRAGFULLWINDOWS); break;
case SPI_GETFILTERKEYS: { LPFILTERKEYS pFK = (LPFILTERKEYS)lParam; int cbSkip = sizeof(gFilterKeys.cbSize);
if (wParam != 0 && wParam != sizeof(FILTERKEYS)) { return FALSE; }
if (!pFK || pFK->cbSize != sizeof(FILTERKEYS)) { return FALSE; }
/*
* In the future we may support multiple sizes of this data * structure. Don't change the cbSize field of the data * structure passed in. */ RtlCopyMemory((LPVOID)((LPBYTE)pFK + cbSkip), (LPVOID)((LPBYTE)&gFilterKeys + cbSkip), pFK->cbSize - cbSkip); } break;
case SPI_SETFILTERKEYS: { LPFILTERKEYS pFK = (LPFILTERKEYS)lParam;
if (wParam != 0 && wParam != sizeof(FILTERKEYS)) { return FALSE; }
if (!pFK || pFK->cbSize != sizeof(FILTERKEYS)) { return FALSE; }
/*
* SlowKeys and BounceKeys cannot both be active simultaneously */ if (pFK->iWaitMSec && pFK->iBounceMSec) { return FALSE; }
/*
* Do some parameter validation. We will fail on unsupported and * undefined bits being set. */ if ((pFK->dwFlags & FKF_VALID) != pFK->dwFlags) { return FALSE; }
/*
* FKF_AVAILABLE can't be set via API. Use registry value. */ if (TEST_ACCESSFLAG(FilterKeys, FKF_AVAILABLE)) { pFK->dwFlags |= FKF_AVAILABLE; } else { pFK->dwFlags &= ~FKF_AVAILABLE; }
if (pFK->iWaitMSec > 20000 || pFK->iDelayMSec > 20000 || pFK->iRepeatMSec > 20000 || pFK->iBounceMSec > 20000) { return FALSE; }
if (fAlterWinIni) { pProfileUserName = CreateProfileUserName(&tlName); fWinIniChanged = SetFilterKeys(pProfileUserName, pFK); fWriteAllowed = fWinIniChanged; if (!fWinIniChanged) { /*
* Back out any changes to win.ini. */ SetFilterKeys(pProfileUserName, &gFilterKeys); }
FreeProfileUserName(pProfileUserName, &tlName); }
if (fWriteAllowed) { RtlCopyMemory(&gFilterKeys, pFK, pFK->cbSize);
/*
* Don't allow user to change cbSize field. */ gFilterKeys.cbSize = sizeof(FILTERKEYS);
if (!TEST_ACCESSFLAG(FilterKeys, FKF_FILTERKEYSON)) { StopFilterKeysTimers(); } SetAccessEnabledFlag(); if (FCallHookTray()) { xxxCallHook(HSHELL_ACCESSIBILITYSTATE, ACCESS_FILTERKEYS, 0, WH_SHELL); } PostShellHookMessages(HSHELL_ACCESSIBILITYSTATE, ACCESS_FILTERKEYS); } } break;
case SPI_GETSTICKYKEYS: { LPSTICKYKEYS pSK = (LPSTICKYKEYS)lParam; int cbSkip = sizeof(gStickyKeys.cbSize);
if (wParam != 0 && wParam != sizeof(STICKYKEYS)) { return FALSE; }
if (!pSK || pSK->cbSize != sizeof(STICKYKEYS)) { return FALSE; }
/*
* In the future we may support multiple sizes of this data * structure. Don't change the cbSize field of the data * structure passed in. */ RtlCopyMemory((LPVOID)((LPBYTE)pSK + cbSkip), (LPVOID)((LPBYTE)&gStickyKeys + cbSkip), pSK->cbSize - cbSkip);
pSK->dwFlags &= ~SKF_STATEINFO; pSK->dwFlags |= (gLatchBits&0xff) <<24;
#if SKF_LALTLATCHED != 0x10000000
#error SKF_LALTLATCHED value is incorrect
#endif
#if SKF_LCTLLATCHED != 0x04000000
#error SKF_LCTLLATCHED value is incorrect
#endif
#if SKF_LSHIFTLATCHED != 0x01000000
#error SKF_LSHIFTLATCHED value is incorrect
#endif
#if SKF_RALTLATCHED != 0x20000000
#error SKF_RALTLATCHED value is incorrect
#endif
#if SKF_RCTLLATCHED != 0x08000000
#error SKF_RCTLLATCHED value is incorrect
#endif
#if SKF_RSHIFTLATCHED != 0x02000000
#error SKF_RSHIFTLATCHED value is incorrect
#endif
pSK->dwFlags |= (gLockBits&0xff) <<16; #if SKF_LALTLOCKED != 0x00100000
#error SKF_LALTLOCKED value is incorrect
#endif
#if SKF_LCTLLOCKED != 0x00040000
#error SKF_LCTLLOCKED value is incorrect
#endif
#if SKF_LSHIFTLOCKED != 0x00010000
#error SKF_LSHIFTLOCKED value is incorrect
#endif
#if SKF_RALTLOCKED != 0x00200000
#error SKF_RALTLOCKED value is incorrect
#endif
#if SKF_RCTLLOCKED != 0x00080000
#error SKF_RCTLLOCKED value is incorrect
#endif
#if SKF_RSHIFTLOCKED != 0x00020000
#error SKF_RSHIFTLOCKED value is incorrect
#endif
}
break;
case SPI_SETSTICKYKEYS: { LPSTICKYKEYS pSK = (LPSTICKYKEYS)lParam; BOOL fWasOn;
fWasOn = TEST_BOOL_ACCESSFLAG(StickyKeys, SKF_STICKYKEYSON); if (wParam != 0 && wParam != sizeof(STICKYKEYS)) { return FALSE; }
if (!pSK || pSK->cbSize != sizeof(STICKYKEYS)) { return FALSE; }
/*
* Do some parameter validation. We will fail on unsupported and * undefined bits being set. * * Don't penalize them for using data from SPI_GETSTICKYKEYS, * though. */ pSK->dwFlags &= ~SKF_STATEINFO; if ((pSK->dwFlags & SKF_VALID) != pSK->dwFlags) { return FALSE; }
/*
* SKF_AVAILABLE can't be set via API. Use registry value. */ if (TEST_ACCESSFLAG(StickyKeys, SKF_AVAILABLE)) { pSK->dwFlags |= SKF_AVAILABLE; } else { pSK->dwFlags &= ~SKF_AVAILABLE; }
if (fAlterWinIni) { swprintf(szTemp, pwszd, pSK->dwFlags); fWinIniChanged = FastWriteProfileStringW(NULL, PMAP_STICKYKEYS, L"Flags", szTemp); fWriteAllowed = fWinIniChanged; } if (fWriteAllowed) { RtlCopyMemory(&gStickyKeys, pSK, pSK->cbSize);
/*
* Don't allow user to change cbSize field. */ gStickyKeys.cbSize = sizeof(STICKYKEYS); if (!TEST_ACCESSFLAG(StickyKeys, SKF_STICKYKEYSON) && fWasOn) { xxxTurnOffStickyKeys(); }
SetAccessEnabledFlag(); if (FCallHookTray()) { xxxCallHook(HSHELL_ACCESSIBILITYSTATE, ACCESS_STICKYKEYS, 0, WH_SHELL); } PostShellHookMessages(HSHELL_ACCESSIBILITYSTATE, ACCESS_STICKYKEYS); } } break;
case SPI_GETTOGGLEKEYS: { LPTOGGLEKEYS pTK = (LPTOGGLEKEYS)lParam; int cbSkip = sizeof(gToggleKeys.cbSize);
if (wParam != 0 && wParam != sizeof(TOGGLEKEYS)) { return FALSE; }
if (!pTK || pTK->cbSize != sizeof(TOGGLEKEYS)) { return FALSE; }
/*
* In the future we may support multiple sizes of this data * structure. Don't change the cbSize field of the data * structure passed in. */ RtlCopyMemory((LPVOID)((LPBYTE)pTK + cbSkip), (LPVOID)((LPBYTE)&gToggleKeys + cbSkip), pTK->cbSize - cbSkip); } break;
case SPI_SETTOGGLEKEYS: { LPTOGGLEKEYS pTK = (LPTOGGLEKEYS)lParam;
if (wParam != 0 && wParam != sizeof(TOGGLEKEYS)) { return FALSE; }
if (!pTK || pTK->cbSize != sizeof(TOGGLEKEYS)) { return FALSE; }
/*
* Do some parameter validation. We will fail on unsupported and * undefined bits being set. */ if ((pTK->dwFlags & TKF_VALID) != pTK->dwFlags) { return FALSE; }
/*
* TKF_AVAILABLE can't be set via API. Use registry value. */ if (TEST_ACCESSFLAG(ToggleKeys, TKF_AVAILABLE)) { pTK->dwFlags |= TKF_AVAILABLE; } else { pTK->dwFlags &= ~TKF_AVAILABLE; }
if (fAlterWinIni) { swprintf(szTemp, pwszd, pTK->dwFlags); fWinIniChanged = FastWriteProfileStringW(NULL, PMAP_TOGGLEKEYS, L"Flags", szTemp); fWriteAllowed = fWinIniChanged; }
if (fWriteAllowed) { RtlCopyMemory(&gToggleKeys, pTK, pTK->cbSize);
/*
* Don't allow user to change cbSize field. */ gToggleKeys.cbSize = sizeof(TOGGLEKEYS);
SetAccessEnabledFlag(); } } break;
case SPI_GETMOUSEKEYS: { LPMOUSEKEYS pMK = (LPMOUSEKEYS)lParam; int cbSkip = sizeof(gMouseKeys.cbSize);
if (wParam != 0 && wParam != sizeof(MOUSEKEYS)) { return FALSE; }
if (!pMK || pMK->cbSize != sizeof(MOUSEKEYS)) { return FALSE; }
/*
* In the future we may support multiple sizes of this data * structure. Don't change the cbSize field of the data * structure passed in. */ RtlCopyMemory((LPVOID)((LPBYTE)pMK + cbSkip), (LPVOID)((LPBYTE)&gMouseKeys + cbSkip), pMK->cbSize - cbSkip);
pMK->dwFlags &= ~MKF_STATEINFO; if (gbMKMouseMode) { pMK->dwFlags |= MKF_MOUSEMODE; }
pMK->dwFlags |= (gwMKButtonState & 3) << 24; #if MOUSE_BUTTON_LEFT != 0x01
#error MOUSE_BUTTON_LEFT value is incorrect
#endif
#if MOUSE_BUTTON_RIGHT != 0x02
#error MOUSE_BUTTON_RIGHT value is incorrect
#endif
#if MKF_LEFTBUTTONDOWN != 0x01000000
#error MKF_LEFTBUTTONDOWN value is incorrect
#endif
#if MKF_RIGHTBUTTONDOWN != 0x02000000
#error MKF_RIGHTBUTTONDOWN value is incorrect
#endif
pMK->dwFlags |= (gwMKCurrentButton & 3)<< 28; #if MKF_LEFTBUTTONSEL != 0x10000000
#error MKF_LEFTBUTTONSEL value is incorrect
#endif
#if MKF_RIGHTBUTTONSEL != 0x20000000
#error MKF_RIGHTBUTTONSEL value is incorrect
#endif
} break;
case SPI_SETMOUSEKEYS: { LPMOUSEKEYS pMK = (LPMOUSEKEYS)lParam;
if (wParam != 0 && wParam != sizeof(MOUSEKEYS)) { return FALSE; }
if (!pMK || pMK->cbSize != sizeof(MOUSEKEYS)) { return FALSE; }
/*
* Do some parameter validation. We will fail on unsupported and * undefined bits being set. * * Don't penalize them for using data from SPI_GETMOUSEKEYS. */ pMK->dwFlags &= ~MKF_STATEINFO; if ((pMK->dwFlags & MKF_VALID) != pMK->dwFlags) { return FALSE; }
/*
* MKF_AVAILABLE can't be set via API. Use registry value. */ if (TEST_ACCESSFLAG(MouseKeys, MKF_AVAILABLE)) { pMK->dwFlags |= MKF_AVAILABLE; } else { pMK->dwFlags &= ~MKF_AVAILABLE; }
if (pMK->iMaxSpeed < MAXSPEED_MIN || pMK->iMaxSpeed > MAXSPEED_MAX) { return FALSE; }
if (pMK->iTimeToMaxSpeed < TIMETOMAXSPEED_MIN || pMK->iTimeToMaxSpeed > TIMETOMAXSPEED_MAX) { return FALSE; }
if (fAlterWinIni) { pProfileUserName = CreateProfileUserName(&tlName); fWinIniChanged = SetMouseKeys(pProfileUserName, pMK); fWriteAllowed = fWinIniChanged; if (!fWinIniChanged) { /*
* Back out any changes to win.ini. */ SetMouseKeys(pProfileUserName, &gMouseKeys); }
FreeProfileUserName(pProfileUserName, &tlName); }
if (fWriteAllowed) { RtlCopyMemory(&gMouseKeys, pMK, pMK->cbSize); /*
* Don't allow user to change cbSize field. */ gMouseKeys.cbSize = sizeof(MOUSEKEYS);
CalculateMouseTable();
if (TEST_ACCESSFLAG(MouseKeys, MKF_MOUSEKEYSON)) { if ((TestAsyncKeyStateToggle(gNumLockVk) != 0) ^ (TEST_ACCESSFLAG(MouseKeys, MKF_REPLACENUMBERS) != 0)) { gbMKMouseMode = TRUE; } else { gbMKMouseMode = FALSE; } MKShowMouseCursor(); } else { MKHideMouseCursor(); }
SetAccessEnabledFlag();
if (FCallHookTray()) { xxxCallHook(HSHELL_ACCESSIBILITYSTATE, ACCESS_MOUSEKEYS, 0, WH_SHELL); } PostShellHookMessages(HSHELL_ACCESSIBILITYSTATE, ACCESS_MOUSEKEYS); } } break;
case SPI_GETHIGHCONTRAST: { LPHIGHCONTRAST pHC = (LPHIGHCONTRAST)lParam;
/*
* In the future we may support multiple sizes of this data * structure. Don't change the cbSize field of the data * structure passed in. */
pHC->dwFlags = gHighContrast.dwFlags;
/*
* A hostile app could deallocate the memory using a second thread, * so shelter the copy with a try. */ try { RtlCopyMemory(pHC->lpszDefaultScheme, gHighContrastDefaultScheme, MAX_SCHEME_NAME_SIZE * sizeof(WCHAR)); } except (W32ExceptionHandler(FALSE, RIP_WARNING)) { } }
break;
case SPI_SETHIGHCONTRAST: { LPINTERNALSETHIGHCONTRAST pHC = (LPINTERNALSETHIGHCONTRAST)lParam; WCHAR wcDefaultScheme[MAX_SCHEME_NAME_SIZE];
if (pHC->usDefaultScheme.Length >= MAX_SCHEME_NAME_SIZE*sizeof(WCHAR)) { return FALSE; }
if (pHC->usDefaultScheme.Buffer) { /*
* Only set the scheme if the user specifies a scheme. An * empty buffer is ignored. We do the copy here so that we * don't need to put a try/except around the * WriteProfileString code. */
try { RtlCopyMemory(wcDefaultScheme, pHC->usDefaultScheme.Buffer, pHC->usDefaultScheme.Length); } except (W32ExceptionHandler(TRUE, RIP_WARNING)) { return FALSE; } } wcDefaultScheme[pHC->usDefaultScheme.Length / sizeof(WCHAR)] = 0;
if (fAlterWinIni) { pProfileUserName = CreateProfileUserName(&tlName); swprintf(szTemp, pwszd, pHC->dwFlags); fWinIniChanged = FastWriteProfileStringW(pProfileUserName, PMAP_HIGHCONTRAST, L"Flags", szTemp );
fWriteAllowed = fWinIniChanged;
/*
* Note -- we do not write anything if there is no default * scheme from the app. This is consistent with Win95/Win98 * behavior. */ if (pHC->usDefaultScheme.Buffer) { fWinIniChanged |= FastWriteProfileStringW(pProfileUserName, PMAP_HIGHCONTRAST, TEXT("High Contrast Scheme"), wcDefaultScheme); }
FreeProfileUserName(pProfileUserName, &tlName); }
if (fWriteAllowed) { DWORD dwFlagsOld = gHighContrast.dwFlags; LPARAM lp = fAlterWinIni ? 0 : ACCESS_HIGHCONTRASTNOREG;
#if (ACCESS_HIGHCONTRASTNOREG | ACCESS_HIGHCONTRASTOFF) != ACCESS_HIGHCONTRASTOFFNOREG
#error ACCESS_HIGHCONTRASTOFF value is incorrect
#endif
#if (ACCESS_HIGHCONTRASTNOREG | ACCESS_HIGHCONTRASTON) != ACCESS_HIGHCONTRASTONNOREG
#error ACCESS_HIGHCONTRASTON value is incorrect
#endif
#if (ACCESS_HIGHCONTRASTNOREG | ACCESS_HIGHCONTRASTCHANGE) != ACCESS_HIGHCONTRASTCHANGENOREG
#error ACCESS_HIGHCONTRASTCHANGE value is incorrect
#endif
/*
* If a NULL is specified in the lpszDefaultScheme, then it * is not changed. This is consistent with Win95/Win98 * behavior. */ if (pHC->usDefaultScheme.Buffer) { wcscpy(gHighContrastDefaultScheme, wcDefaultScheme); }
gHighContrast.dwFlags = pHC->dwFlags;
SetAccessEnabledFlag();
/*
* Now, post message to turn high contrast on or off. */ if (pHC->dwFlags & HCF_HIGHCONTRASTON) { _PostMessage(gspwndLogonNotify, WM_LOGONNOTIFY, LOGON_ACCESSNOTIFY, (dwFlagsOld & HCF_HIGHCONTRASTON) ? (ACCESS_HIGHCONTRASTCHANGE | lp) : (ACCESS_HIGHCONTRASTON | lp)); } else { _PostMessage(gspwndLogonNotify, WM_LOGONNOTIFY, LOGON_ACCESSNOTIFY, ACCESS_HIGHCONTRASTOFF | lp); }
}
break; }
case SPI_GETACCESSTIMEOUT: { LPACCESSTIMEOUT pTO = (LPACCESSTIMEOUT)lParam; int cbSkip = sizeof(gAccessTimeOut.cbSize);
if (wParam != 0 && wParam != sizeof(ACCESSTIMEOUT)) { return FALSE; }
if (!pTO || pTO->cbSize != sizeof(ACCESSTIMEOUT)) { return FALSE; }
/*
* In the future we may support multiple sizes of this data * structure. Don't change the cbSize field of the data * structure passed in. */ RtlCopyMemory((LPVOID)((LPBYTE)pTO + cbSkip), (LPVOID)((LPBYTE)&gAccessTimeOut + cbSkip), pTO->cbSize - cbSkip); } break;
case SPI_SETACCESSTIMEOUT: { LPACCESSTIMEOUT pTO = (LPACCESSTIMEOUT)lParam;
if (wParam != 0 && wParam != sizeof(ACCESSTIMEOUT)) { return FALSE; }
if (!pTO || pTO->cbSize != sizeof(ACCESSTIMEOUT)) { return FALSE; }
/*
* Do some parameter validation. We will fail on unsupported and * undefined bits being set. */ if ((pTO->dwFlags & ATF_VALID) != pTO->dwFlags) { return FALSE; }
if (pTO->iTimeOutMSec > 3600000) { return FALSE; }
if (fAlterWinIni) { pProfileUserName = CreateProfileUserName(&tlName); swprintf(szTemp, pwszd, pTO->dwFlags); fWinIniChanged = FastWriteProfileStringW(pProfileUserName, PMAP_TIMEOUT, L"Flags", szTemp);
swprintf(szTemp, pwszd, pTO->iTimeOutMSec); fWinIniChanged = FastWriteProfileStringW(pProfileUserName, PMAP_TIMEOUT, L"TimeToWait", szTemp);
fWriteAllowed = fWinIniChanged; if (!fWinIniChanged) { /*
* Back out any changes to win.ini. */ swprintf(szTemp, pwszd, gAccessTimeOut.dwFlags); fWinIniChanged = FastWriteProfileStringW(pProfileUserName, PMAP_TIMEOUT, L"Flags", szTemp);
swprintf(szTemp, pwszd, gAccessTimeOut.iTimeOutMSec); fWinIniChanged = FastWriteProfileStringW(pProfileUserName, PMAP_TIMEOUT, L"TimeToWait", szTemp); }
FreeProfileUserName(pProfileUserName, &tlName); } if (fWriteAllowed) { RtlCopyMemory(&gAccessTimeOut, pTO, pTO->cbSize);
/*
* Don't allow user to change cbSize field. */ gAccessTimeOut.cbSize = sizeof(ACCESSTIMEOUT);
SetAccessEnabledFlag();
AccessTimeOutReset(); } } break;
case SPI_SETSHOWSOUNDS: if (fAlterWinIni) { swprintf(szTemp, pwszd, (wParam == 1)); fWinIniChanged = FastWriteProfileStringW(NULL, PMAP_SHOWSOUNDS, L"On", szTemp);
fWriteAllowed = fWinIniChanged; }
if (fWriteAllowed) { SET_OR_CLEAR_ACCF(ACCF_SHOWSOUNDSON, wParam == 1); SetAccessEnabledFlag();
/*
* Update the System Metrics Info. */ SYSMET(SHOWSOUNDS) = TEST_BOOL_ACCF(ACCF_SHOWSOUNDSON); } break;
case SPI_GETSHOWSOUNDS: { PINT pint = (int *)lParam;
*pint = TEST_BOOL_ACCF(ACCF_SHOWSOUNDSON); } break;
case SPI_GETKEYBOARDPREF: { PBOOL pfKeyboardPref = (PBOOL)lParam;
*pfKeyboardPref = TEST_BOOL_ACCF(ACCF_KEYBOARDPREF); } break;
case SPI_SETKEYBOARDPREF: { BOOL fKeyboardPref = (BOOL)wParam;
if (fAlterWinIni) { fWinIniChanged = FastWriteProfileStringW(NULL, PMAP_KEYBOARDPREF, L"On", fKeyboardPref ? L"1" : L"0");
fWriteAllowed = fWinIniChanged; }
if (fWriteAllowed) { SET_OR_CLEAR_ACCF(ACCF_KEYBOARDPREF, wParam); } } break;
case SPI_GETSCREENREADER: { PBOOL pfScreenReader = (PBOOL)lParam;
*pfScreenReader = TEST_BOOL_ACCF(ACCF_SCREENREADER); } break;
case SPI_SETSCREENREADER: { BOOL fScreenReader = (BOOL)wParam;
if (fAlterWinIni) { fWinIniChanged = FastWriteProfileStringW(NULL, PMAP_SCREENREADER, L"On", fScreenReader ? L"1" : L"0"); fWriteAllowed = fWinIniChanged; }
if (fWriteAllowed) { SET_OR_CLEAR_ACCF(ACCF_SCREENREADER, wParam); } } break;
case SPI_GETSOUNDSENTRY: { LPSOUNDSENTRY pSS = (LPSOUNDSENTRY)lParam; int cbSkip = sizeof(gSoundSentry.cbSize);
if (wParam != 0 && wParam != sizeof(SOUNDSENTRY)) { return FALSE; }
if (!pSS || pSS->cbSize != sizeof(SOUNDSENTRY)) { return FALSE; }
/*
* In the future we may support multiple sizes of this data * structure. Don't change the cbSize field of the data * structure passed in. */ RtlCopyMemory((LPVOID)((LPBYTE)pSS + cbSkip), (LPVOID)((LPBYTE)&gSoundSentry + cbSkip), pSS->cbSize - cbSkip); } break;
case SPI_SETSOUNDSENTRY: { LPSOUNDSENTRY pSS = (LPSOUNDSENTRY)lParam;
if (wParam != 0 && wParam != sizeof(SOUNDSENTRY)) { return FALSE; }
if (!pSS || pSS->cbSize != sizeof(SOUNDSENTRY)) { return FALSE; }
/*
* Do some parameter validation. We will fail on unsupported and * undefined bits being set. */ if ((pSS->dwFlags & SSF_VALID) != pSS->dwFlags) { return FALSE; }
/*
* We don't support SSWF_CUSTOM. */ if (pSS->iWindowsEffect > SSWF_DISPLAY) { return FALSE; }
/*
* No support for non-windows apps. */ if (pSS->iFSTextEffect != SSTF_NONE) { return FALSE; } if (pSS->iFSGrafEffect != SSGF_NONE) { return FALSE; }
/*
* SSF_AVAILABLE can't be set via API. Use registry value. */ if (TEST_ACCESSFLAG(SoundSentry, SSF_AVAILABLE)) { pSS->dwFlags |= SSF_AVAILABLE; } else { pSS->dwFlags &= ~SSF_AVAILABLE; }
if (fAlterWinIni) { pProfileUserName = CreateProfileUserName(&tlName); fWinIniChanged = SetSoundSentry(pProfileUserName, pSS); fWriteAllowed = fWinIniChanged; if (!fWinIniChanged) {
/*
* Back out any changes to win.ini */ SetSoundSentry(pProfileUserName, &gSoundSentry); } FreeProfileUserName(pProfileUserName, &tlName); } if (fWriteAllowed) { RtlCopyMemory(&gSoundSentry, pSS, pSS->cbSize);
/*
* Don't allow user to change cbSize field. */ gSoundSentry.cbSize = sizeof(SOUNDSENTRY);
SetAccessEnabledFlag(); } } break;
case SPI_SETCURSORS: pProfileUserName = CreateProfileUserName(&tlName); xxxUpdateSystemCursorsFromRegistry(pProfileUserName); FreeProfileUserName(pProfileUserName, &tlName);
break;
case SPI_SETICONS: pProfileUserName = CreateProfileUserName(&tlName); xxxUpdateSystemIconsFromRegistry(pProfileUserName); FreeProfileUserName(pProfileUserName, &tlName);
break;
case SPI_GETMOUSEHOVERWIDTH: *((UINT *)lParam) = gcxMouseHover; break;
case SPI_SETMOUSEHOVERWIDTH: if (fAlterWinIni) { fWinIniChanged = UpdateWinIniInt(NULL, PMAP_MOUSE, STR_MOUSEHOVERWIDTH, wParam); fWriteAllowed = fWinIniChanged; } if (fWriteAllowed) { gcxMouseHover = wParam; } break;
case SPI_GETMOUSEHOVERHEIGHT: *((UINT *)lParam) = gcyMouseHover; break;
case SPI_SETMOUSEHOVERHEIGHT: if (fAlterWinIni) { fWinIniChanged = UpdateWinIniInt(NULL, PMAP_MOUSE, STR_MOUSEHOVERHEIGHT, wParam); fWriteAllowed = fWinIniChanged; } if (fWriteAllowed) { gcyMouseHover = wParam; } break;
case SPI_GETMOUSEHOVERTIME: *((UINT *)lParam) = gdtMouseHover; break;
case SPI_SETMOUSEHOVERTIME: if (fAlterWinIni) { fWinIniChanged = UpdateWinIniInt(NULL, PMAP_MOUSE, STR_MOUSEHOVERTIME, wParam); fWriteAllowed = fWinIniChanged; } if (fWriteAllowed) { gdtMouseHover = wParam; } break;
case SPI_GETWHEELSCROLLLINES: (*(LPDWORD)lParam) = gpsi->ucWheelScrollLines; break;
case SPI_SETWHEELSCROLLLINES: if (CheckDesktopPolicy(NULL, (PCWSTR)STR_WHEELSCROLLLINES)) { fAlterWinIni = FALSE; fWriteAllowed = FALSE; } if (fAlterWinIni) { fWinIniChanged = UpdateWinIniInt(NULL, PMAP_DESKTOP, STR_WHEELSCROLLLINES, wParam); fWriteAllowed = fWinIniChanged; }
if (fWriteAllowed) gpsi->ucWheelScrollLines = (UINT)wParam; break;
case SPI_GETMENUSHOWDELAY: (*(LPDWORD)lParam) = gdtMNDropDown; break;
case SPI_SETMENUSHOWDELAY: if (CheckDesktopPolicy(NULL, (PCWSTR)STR_MENUSHOWDELAY)) { fAlterWinIni = FALSE; fWriteAllowed = FALSE; } if (fAlterWinIni) { fWinIniChanged = UpdateWinIniInt(NULL, PMAP_DESKTOP, STR_MENUSHOWDELAY, wParam); fWriteAllowed = fWinIniChanged; } if (fWriteAllowed) gdtMNDropDown = wParam; break;
case SPI_GETSCREENSAVERRUNNING: (*(LPBOOL)lParam) = gppiScreenSaver != NULL; break;
case SPI_SETSHOWIMEUI: return xxxSetIMEShowStatus(!!wParam);
case SPI_GETSHOWIMEUI: (*(LPBOOL)lParam) = _GetIMEShowStatus(); break;
default:
#define ppvi (UPDWORDPointer(wFlag))
#define uDataRead ((UINT)fWinIniChanged)
if (wFlag < SPI_MAX) { RIPERR1(ERROR_INVALID_SPI_VALUE, RIP_WARNING, "xxxSystemParamtersInfo: Invalid SPI_: 0x%x", wFlag); return FALSE; }
UserAssert(wFlag & SPIF_RANGETYPEMASK);
if (!(wFlag & SPIF_SET)) {
if ((wFlag & SPIF_RANGETYPEMASK) == SPIF_BOOL) { BOOL fDisable, fDisableValue;
UserAssert(UPIsBOOLRange(wFlag)); /*
* Handle settings that can be disabled by additional conditions. */ fDisable = fDisableValue = FALSE; if (wFlag < SPI_GETUIEFFECTS) { if (!TestUP(UIEFFECTS)) { switch (wFlag) { case SPI_GETACTIVEWNDTRKZORDER: case SPI_GETACTIVEWINDOWTRACKING: #ifdef MOUSE_IP
case SPI_GETMOUSESONAR: #endif
case SPI_GETMOUSECLICKLOCK: break;
case SPI_GETKEYBOARDCUES: fDisableValue = TRUE; /* Fall Through */
default: fDisable = TRUE; break; } } else { switch (wFlag) { case SPI_GETKEYBOARDCUES: if (TEST_BOOL_ACCF(ACCF_KEYBOARDPREF)) { fDisableValue = TRUE; fDisable = TRUE; } break;
case SPI_GETGRADIENTCAPTIONS: case SPI_GETSELECTIONFADE: case SPI_GETMENUFADE: case SPI_GETTOOLTIPFADE: case SPI_GETCURSORSHADOW: if (gbDisableAlpha) { fDisable = TRUE; } break; } } } /*
* Give them the disabled value or read the actual one. */ if (fDisable) { *((BOOL *)lParam) = fDisableValue; } else if (wFlag == SPI_GETUIEFFECTS && IsRemoteConnection()) { /*
* Fix for 689707. * In remote connections, lie about the SPI_GETUIEFFECTS. * We look at a certain subset of the uieffects array. * If all the subset bits are off, * we return FALSE, otherwise TRUE. */ *((BOOL *)lParam) = !!(TestUP(CURSORSHADOW) | TestUP(MENUANIMATION) | TestUP(MENUFADE) | TestUP(TOOLTIPANIMATION) | TestUP(TOOLTIPFADE) | TestUP(COMBOBOXANIMATION) | TestUP(LISTBOXSMOOTHSCROLLING)); } else { *((BOOL *)lParam) = !!TestUPBOOL(gpdwCPUserPreferencesMask, wFlag); } } else { UserAssert(UPIsDWORDRange(wFlag)); *((DWORD *)lParam) = UPDWORDValue(wFlag); switch(wFlag) { case SPI_GETFONTSMOOTHINGCONTRAST: /*
* If the contrast value was never set by the user, * we will return the default value from the display * driver */ if (*((DWORD *)lParam) == 0) { *((DWORD *)lParam) = GreGetFontContrast(); } break; default: break; } } } else { pProfileUserName = CreateProfileUserName(&tlName);
if ((wFlag & SPIF_RANGETYPEMASK) == SPIF_BOOL) { DWORD pdwValue [SPI_BOOLMASKDWORDSIZE];
UserAssert(UPIsBOOLRange(wFlag)); UserAssert(sizeof(pdwValue) == sizeof(gpdwCPUserPreferencesMask));
if (gpviCPUserPreferences->uSection == PMAP_DESKTOP) { if (CheckDesktopPolicy(pProfileUserName, gpviCPUserPreferences->pwszKeyName)) { fAlterWinIni = FALSE; fWriteAllowed = FALSE; } } if (fAlterWinIni) { /*
* We only need to set/clear the bit passed in, however, * we write the whole bit mask to the registry. Since * the info in gpdwCPUserPreferencesMask might not match * what it is in the registry, we need to read the * registry before we write to it. */ uDataRead = FastGetProfileValue(pProfileUserName, gpviCPUserPreferences->uSection, gpviCPUserPreferences->pwszKeyName, NULL, (LPBYTE)pdwValue, sizeof(pdwValue), 0);
/*
* If some bits are not in the registry, get them from * gpdwCPUserPreferencesMask. */ UserAssert(uDataRead <= sizeof(gpdwCPUserPreferencesMask)); RtlCopyMemory(pdwValue + uDataRead, gpdwCPUserPreferencesMask + uDataRead, sizeof(gpdwCPUserPreferencesMask) - uDataRead);
/*
* Set/Clear the new state and write it. */ if (lParam) { SetUPBOOL(pdwValue, wFlag); } else { ClearUPBOOL(pdwValue, wFlag); }
fWinIniChanged = FastWriteProfileValue(pProfileUserName, gpviCPUserPreferences->uSection, gpviCPUserPreferences->pwszKeyName, REG_BINARY, (LPBYTE)pdwValue, sizeof(pdwValue));
fWriteAllowed = fWinIniChanged; }
if (fWriteAllowed) { if (lParam) { SetUPBOOL(gpdwCPUserPreferencesMask, wFlag); } else { ClearUPBOOL(gpdwCPUserPreferencesMask, wFlag); }
/*
* Propagate gpsi flags. */ switch (wFlag) { case SPI_SETUIEFFECTS: PropagetUPBOOLTogpsi(UIEFFECTS); SetPointer(TRUE);
/*
* Fall through. */
case SPI_SETGRADIENTCAPTIONS: CreateBitmapStrip(); xxxRedrawScreen(); break;
case SPI_SETCOMBOBOXANIMATION: PropagetUPBOOLTogpsi(COMBOBOXANIMATION); break;
case SPI_SETLISTBOXSMOOTHSCROLLING: PropagetUPBOOLTogpsi(LISTBOXSMOOTHSCROLLING); break;
case SPI_SETKEYBOARDCUES: PropagetUPBOOLTogpsi(KEYBOARDCUES); break;
case SPI_SETCURSORSHADOW: SetPointer(TRUE); break;
case SPI_SETFLATMENU: xxxRedrawScreen(); break;
} } } else {
UserAssert(UPIsDWORDRange(wFlag));
if (ppvi->uSection == PMAP_DESKTOP) { if (CheckDesktopPolicy(pProfileUserName, ppvi->pwszKeyName)) { fAlterWinIni = FALSE; fWriteAllowed = FALSE; } } if (fAlterWinIni) { fWinIniChanged = FastWriteProfileValue(pProfileUserName, ppvi->uSection, ppvi->pwszKeyName, REG_DWORD, (LPBYTE)&lParam, sizeof(DWORD));
fWriteAllowed = fWinIniChanged; }
if (fWriteAllowed) { ppvi->dwValue = PtrToUlong(lParam);
switch(wFlag) { case SPI_SETCARETWIDTH: gpsi->uCaretWidth = ppvi->dwValue; break;
case SPI_SETFOCUSBORDERWIDTH: if (ppvi->dwValue) { SYSMET(CXFOCUSBORDER) = ppvi->dwValue; } break;
case SPI_SETFOCUSBORDERHEIGHT: if (ppvi->dwValue) { SYSMET(CYFOCUSBORDER) = ppvi->dwValue; } break;
case SPI_SETFONTSMOOTHINGTYPE: GreSetFontEnumeration((ppvi->dwValue & FE_FONTSMOOTHINGCLEARTYPE) ? FE_CT_ON | FE_SET_CT : FE_SET_CT); break; case SPI_SETFONTSMOOTHINGCONTRAST: GreSetFontContrast(ppvi->dwValue); break; case SPI_SETFONTSMOOTHINGORIENTATION: GreSetLCDOrientation(ppvi->dwValue); break; default: break; } } }
FreeProfileUserName(pProfileUserName, &tlName); }
break; #undef ppvi
#undef uDataRead
}
if (fWinIniChanged && fSendWinIniChange) { ULONG_PTR dwResult;
RtlInitLargeUnicodeString(&strSection, szSection, (UINT)-1); xxxSendMessageTimeout(PWND_BROADCAST, WM_SETTINGCHANGE, wFlag, (LPARAM)&strSection, SMTO_NORMAL, 100, &dwResult); }
return fWriteAllowed; }
/***************************************************************************\
* _RegisterShellHookWindow * * History: \***************************************************************************/ BOOL _RegisterShellHookWindow( PWND pwnd) { PDESKTOPINFO pdeskinfo;
if (pwnd->head.rpdesk == NULL) { return FALSE; }
pdeskinfo = pwnd->head.rpdesk->pDeskInfo;
/*
* Add pwnd to the desktop's Volatile Window Pointer List (VWPL) of * ShellHook windows. If this call initializes the VWPL, set the * (re)allocation threshhold to 2 PWNDs (we know we never have more than * 2 windows in this list anyway) */ if (VWPLAdd(&(pdeskinfo->pvwplShellHook), pwnd, 2)) { SetWF(pwnd, WFSHELLHOOKWND); return TRUE; }
return FALSE; }
/***************************************************************************\
* _DeregisterShellHookWindow * * History: \***************************************************************************/ BOOL _DeregisterShellHookWindow( PWND pwnd) { PDESKTOPINFO pdeskinfo;
if (pwnd->head.rpdesk == NULL) { return FALSE; }
pdeskinfo = pwnd->head.rpdesk->pDeskInfo;
if (VWPLRemove(&(pdeskinfo->pvwplShellHook), pwnd)) { ClrWF(pwnd, WFSHELLHOOKWND); }
return TRUE; }
/***************************************************************************\
* xxxSendMinRectMessages * * History: \***************************************************************************/ BOOL xxxSendMinRectMessages( PWND pwnd, RECT *lpRect) { BOOL fRet = FALSE; HWND hwnd = HW(pwnd); PTHREADINFO pti = PtiCurrent(); PDESKTOPINFO pdeskinfo; DWORD nPwndShellHook; PWND pwndShellHook;
if (IsHooked(pti, WHF_SHELL)) { xxxCallHook(HSHELL_GETMINRECT, (WPARAM)hwnd, (LPARAM)lpRect, WH_SHELL); fRet = TRUE; }
pdeskinfo = GETDESKINFO(pti); if (pdeskinfo->pvwplShellHook == NULL) { return fRet; }
nPwndShellHook = 0; pwndShellHook = NULL; while (pwndShellHook = VWPLNext(pdeskinfo->pvwplShellHook, pwndShellHook, &nPwndShellHook)) { TL tlpwnd; ULONG_PTR dwRes;
ThreadLock(pwndShellHook, &tlpwnd); if (xxxSendMessageTimeout(pwndShellHook, WM_KLUDGEMINRECT, (WPARAM)(hwnd), (LPARAM)lpRect, SMTO_NORMAL, 100, &dwRes)) fRet = TRUE;
/*
* pdeskinfo->pvwplShellHook may have been realloced to a different * location and size during the WM_KLUDGEMINRECT callback. */ ThreadUnlock(&tlpwnd); } return fRet; }
/***************************************************************************\
* PostShellHookMessages * * History: \***************************************************************************/ VOID PostShellHookMessages( UINT message, LPARAM lParam) { PDESKTOPINFO pdeskinfo = GETDESKINFO(PtiCurrent()); DWORD nPwndShellHook; PWND pwndShellHook;
nPwndShellHook = 0; pwndShellHook = NULL;
/*
* We want to allow anyone who's listening for these WM_APPCOMMAND * messages to be able to take the foreground. I.E., pressing mail will * launch outlook AND bring it to the foreground. We set the token to * null so anyone can steal the foreground - else it isn't clear who * should have the right to steal it - only one person gets the right. * We let them fight it out to decide who gets foreground if more than * one listener will try make a foreground change. */ if (HSHELL_APPCOMMAND == message) { TAGMSG0(DBGTAG_FOREGROUND, "PostShellHookMessages cleared last input token - open foreground.");
glinp.ptiLastWoken = NULL; }
/*
* Loop through all the windows registered to listen for shell hooks and * post the message to them. */ while (pwndShellHook = VWPLNext(pdeskinfo->pvwplShellHook, pwndShellHook, &nPwndShellHook)) { if (pwndShellHook == pdeskinfo->spwndProgman) { switch (message) { case HSHELL_WINDOWCREATED: _PostMessage(pwndShellHook, gpsi->uiShellMsg, guiOtherWindowCreated, lParam); break; case HSHELL_WINDOWDESTROYED: _PostMessage(pwndShellHook, gpsi->uiShellMsg, guiOtherWindowDestroyed, lParam); break; } } else { _PostMessage(pwndShellHook, gpsi->uiShellMsg, message, lParam); } }
}
/***************************************************************************\
* _ResetDblClk * * History: \***************************************************************************/ VOID _ResetDblClk( VOID) { PtiCurrent()->pq->timeDblClk = 0L; }
/***************************************************************************\
* SetMsgBox * * History: \***************************************************************************/ VOID SetMsgBox( PWND pwnd) { pwnd->head.rpdesk->pDeskInfo->cntMBox++; SetWF(pwnd, WFMSGBOX); }
/***************************************************************************\
* xxxSimulateShiftF10 * * This routine is called to convert a WM_CONTEXTHELP message back to a * SHIFT-F10 sequence for old applications. It is called from the default * window procedure. * * History: * 22-Aug-95 BradG Ported from Win95 (rare.asm) \***************************************************************************/ VOID xxxSimulateShiftF10( VOID) { /*
* VK_SHIFT down */ xxxKeyEvent(VK_LSHIFT, 0x2A | SCANCODE_SIMULATED, NtGetTickCount(), 0, #ifdef GENERIC_INPUT
NULL, NULL, #endif
FALSE);
/*
* VK_F10 down */ xxxKeyEvent(VK_F10, 0x44 | SCANCODE_SIMULATED, NtGetTickCount(), 0, #ifdef GENERIC_INPUT
NULL, NULL, #endif
FALSE);
/*
* VK_F10 up */ xxxKeyEvent(VK_F10 | KBDBREAK, 0x44 | SCANCODE_SIMULATED, NtGetTickCount(), 0, #ifdef GENERIC_INPUT
NULL, NULL, #endif
FALSE);
/*
* VK_SHIFT up */ xxxKeyEvent(VK_LSHIFT | KBDBREAK, 0x2A | SCANCODE_SIMULATED, NtGetTickCount(), 0, #ifdef GENERIC_INPUT
NULL, NULL, #endif
FALSE); }
/*
* VWPL (Volatile Window Pointer List) Implementation details. * =========================================================== * Volatile Window Pointer Lists are used to keep a list of windows that we want * to send messages to, where the list may get altered during each of those send * message callbacks. * * The list is volatile in that it can change its size, contents and location * while we continue to traverse the list. * * Examples of use: * - hungapp redraw code in hungapp.c * - xxxSendMinRectMessages stuff in rare.c * * Members of the VWPL struct: * cPwnd * The number of pwnds in the list, not including NULLs * cElem * The size of the list, including NULLs. * cThreshhold * When growing, the number of extra spaces to add to the list. * When (cElem - cPwnd) > cThreshhold, that's when we reallocate to shrink. * apwnd[] * An array of pwnds. * The array may have some empty slots, but they will all be at the end. * * VWPL Internal Invariants: * - no pwnd appears more than once. * - cPwnd <= cElem * - number of unused slots (cElem - cPwnd) < cThreshhold * - all unused slots are at the end of the aPwnd[] array * * Restrictions on use of VWPLs: * - NULL pwnd is not allowed (except in unused slots) * - all pwnds in the list must be valid: pwnds must be explicitly removed from * the list in their xxxFreeWindow. */
#if DBG_VWPL
BOOL DbgCheckVWPL( PVWPL pvwpl) { DWORD ixPwnd;
if (!pvwpl) { return TRUE; }
UserAssert(pvwpl->cElem >= pvwpl->cPwnd);
/*
* Check that cElem is not too big. */ UserAssert(pvwpl->cElem < 1000);
/*
* Check that the pwnds are all in the first cPwnd slots. */ for (ixPwnd = 0; ixPwnd < pvwpl->cPwnd; ixPwnd++) { UserAssert(pvwpl->aPwnd[ixPwnd] != NULL); }
#if ZERO_INIT_VWPL
/*
* Check that the NULLs are all in the last few slots. */ for (ixPwnd = pvwpl->cPwnd; ixPwnd < pvwpl->cElem; ixPwnd++) { UserAssert(pvwpl->aPwnd[ixPwnd] == NULL); } #endif
/*
* Check that no pwnds appears twice. */ for (ixPwnd = 0; ixPwnd < pvwpl->cPwnd; ixPwnd++) { DWORD ix2; for (ix2 = ixPwnd + 1; ix2 < pvwpl->cPwnd; ix2++) { UserAssert(pvwpl->aPwnd[ixPwnd] != pvwpl->aPwnd[ix2]); } } } #else
#define DbgCheckVWPL(foo)
#endif
/*****************************************************************************\
* VWPLAdd * * Adds a pwnd to a VWPL (Volatile Window Pointer List). Allocates or * reallocates memory as required. * * History: * 98-01-30 IanJa Created. \*****************************************************************************/ BOOL VWPLAdd( PVWPL *ppvwpl, PWND pwnd, DWORD dwThreshhold) { PVWPL pvwpl; DWORD ixPwnd;
TAGMSG2(DBGTAG_VWPL, "VWPL %#p + %#p", *ppvwpl, pwnd); UserAssert(pwnd);
if (*ppvwpl == NULL) { /*
* Initialize the VWPL. */ UserAssert(dwThreshhold >= 2); // could be 1, but that would be silly
pvwpl = (PVWPL)UserAllocPool(sizeof(VWPL) + (sizeof(PWND) * dwThreshhold), TAG_VWPL); if (pvwpl == NULL) { RIPMSG1(RIP_WARNING, "VWPLAdd fail to allocate initial %lx", sizeof(VWPL) + (sizeof(PWND) * dwThreshhold)); DbgCheckVWPL(*ppvwpl); return FALSE; } pvwpl->cElem = dwThreshhold; pvwpl->cThreshhold = dwThreshhold; #if ZERO_INIT_VWPL
RtlZeroMemory(&(pvwpl->aPwnd[0]), (sizeof(PWND) * dwThreshhold)); #endif
pvwpl->cPwnd = 0; *ppvwpl = pvwpl; ixPwnd = 0; goto AddPwnd; } else { pvwpl = *ppvwpl; for (ixPwnd = 0; ixPwnd < pvwpl->cElem; ixPwnd++) { if (pwnd == pvwpl->aPwnd[ixPwnd]) { DbgCheckVWPL(*ppvwpl); return FALSE; // callers require FALSE this case
} }
if (pvwpl->cPwnd >= pvwpl->cElem ) { /*
* Didn't find it already there, and no space so grow the VWPL. */ DWORD dwSize; DWORD dwSizeNew;
dwSize = sizeof(VWPL) + (sizeof(PWND) * pvwpl->cElem); dwSizeNew = dwSize + (sizeof(PWND) * pvwpl->cThreshhold); pvwpl = (PVWPL)UserReAllocPool(pvwpl, dwSize, dwSizeNew, TAG_VWPL); if (pvwpl == NULL) { RIPMSG2(RIP_WARNING, "VWPLAdd fail to reallocate %lx to %lx", dwSize, dwSizeNew); DbgCheckVWPL(*ppvwpl); return FALSE; } #if ZERO_INIT_VWPL
RtlZeroMemory(&(pvwpl->aPwnd[pvwpl->cPwnd]), (sizeof(PWND) * dwThreshhold)); #endif
pvwpl->cElem += pvwpl->cThreshhold; *ppvwpl = pvwpl; } }
AddPwnd: ixPwnd = pvwpl->cPwnd; pvwpl->aPwnd[ixPwnd] = pwnd; pvwpl->cPwnd++; DbgCheckVWPL(*ppvwpl); return TRUE; }
/*****************************************************************************\
* VWPLRemove * * Removes a pwnd from a VWPL list of pwnds. Reallocates memory as required. * * Returns FALSE if the pwnd was not found. * * History: * 98-01-30 IanJa Created. \*****************************************************************************/ BOOL VWPLRemove( PVWPL *ppvwpl, PWND pwnd) { PVWPL pvwpl = *ppvwpl; DWORD ixPwnd;
TAGMSG2(DBGTAG_VWPL, "VWPL %#p - %#p", *ppvwpl, pwnd); UserAssert(pwnd);
if (!pvwpl) { return FALSE; }
for (ixPwnd = 0; ixPwnd < pvwpl->cElem; ixPwnd++) { if (pwnd == pvwpl->aPwnd[ixPwnd]) { goto PwndIsFound; } } DbgCheckVWPL(*ppvwpl); return FALSE;
PwndIsFound: pvwpl->aPwnd[ixPwnd] = NULL; pvwpl->cPwnd--;
if (pvwpl->cPwnd == 0) { UserFreePool(pvwpl); *ppvwpl = NULL; return TRUE; }
/*
* Compact the VWPL to keep all the empty slots at the end. If these * free slots exceeds the threshhold, realloc to shrink. It doesn't * matter that we change the order. */ pvwpl->aPwnd[ixPwnd] = pvwpl->aPwnd[pvwpl->cPwnd]; #if ZERO_INIT_VWPL
pvwpl->aPwnd[pvwpl->cPwnd] = NULL; #endif
if ((pvwpl->cElem - pvwpl->cPwnd) >= pvwpl->cThreshhold) { DWORD dwSize; DWORD dwSizeNew;
dwSize = sizeof(VWPL) + (sizeof(PWND) * pvwpl->cElem); dwSizeNew = sizeof(VWPL) + (sizeof(PWND) * pvwpl->cPwnd); pvwpl = (PVWPL)UserReAllocPool(pvwpl, dwSize, dwSizeNew, TAG_VWPL); if (pvwpl == NULL) { RIPMSG2(RIP_WARNING, "VWPLRemove fail to reallocate %lx to %lx", dwSize, dwSizeNew); DbgCheckVWPL(*ppvwpl); return TRUE; } pvwpl->cElem = pvwpl->cPwnd; *ppvwpl = pvwpl; }
DbgCheckVWPL(*ppvwpl); return TRUE; }
/*****************************************************************************\
* VWPLNext * * Returns the next pwnd from a VWPL (Volatile Window Pointer List). * * Setting *pnPrev to 0 will return the first pwnd in the VWPL, and gets a new * value in *pnPrev which is to be used in a subsequent call to VWPLNext to * obtain the next pwnd. * Returns NULL when the last pwnd has been obtained, and sets *pnPrev back to 0 * * History: * 98-01-30 IanJa Created. \*****************************************************************************/ PWND VWPLNext( PVWPL pvwpl, PWND pwndPrev, DWORD *pnPrev) { DbgCheckVWPL(pvwpl);
if (!pvwpl) { TAGMSG1(DBGTAG_VWPL, "VWPL %#p => NULL (empty)", pvwpl); return NULL; }
if (*pnPrev >= pvwpl->cPwnd) { goto NoMorePwnds; }
/*
* If our previous pwnd is still there, advance to the next slot * (else it has gone, so return the one now occupying its slot). */ if (pvwpl->aPwnd[*pnPrev] == pwndPrev) { (*pnPrev)++; }
if (*pnPrev < pvwpl->cPwnd) { UserAssert(pvwpl->aPwnd[*pnPrev] != pwndPrev); TAGMSG2(DBGTAG_VWPL, "VWPL %#p => %#p", pvwpl, pvwpl->aPwnd[*pnPrev]); return pvwpl->aPwnd[*pnPrev]; }
/*
* We came to the end. */ NoMorePwnds: TAGMSG1(DBGTAG_VWPL, "VWPL 0x%p => NULL (end)", pvwpl); *pnPrev = 0; return NULL; }
/*****************************************************************************\
* RestoreMonitorsAndWindowsRects * * Restore a windows sizes and positions previously captured in a WMSNAPSHOT * structure. Capture happens when disconnecting from local console and * restore happens when connecting back to local console. \*****************************************************************************/ NTSTATUS RestoreMonitorsAndWindowsRects( VOID) { PMONITORRECTS pmr; int i; int j; BOOL bFound; PSMWP psmwp; PWND pwnd; NTSTATUS Status; PWPSNAPSHOT pwps = NULL;
/*
* Don't do anything if not multimon. */ if (!IsMultimon()) { return STATUS_SUCCESS; }
/*
* Nothing to do if we don't currently have captured monitors or * windows snapshots. */ if (gwms.pmr == NULL || gwms.pwps == NULL) { Status = STATUS_UNSUCCESSFUL; goto Exit; }
/*
* Get Current monitors layout. */ pmr = SnapshotMonitorRects(); if (pmr == NULL) { Status = STATUS_NO_MEMORY; goto Exit; }
/*
* make sure monitors we captured are still there. */
Status = STATUS_SUCCESS; for (i = 0; i < gwms.pmr->cMonitor; i++) { bFound = FALSE; for (j = 0; j < pmr->cMonitor; j++) { if (EqualRect(&gwms.pmr->amp[i].rcMonitor, &pmr->amp[j].rcMonitor)) { bFound = TRUE; break; } } if (!bFound) { Status = STATUS_UNSUCCESSFUL; break; } } UserFreePool(pmr);
/*
* Position Windows now. */ if (NT_SUCCESS(Status)) { if ((psmwp = InternalBeginDeferWindowPos(4)) != NULL) { for (i = 0, pwps = gwms.pwps; (i < gwms.cWindows) && (psmwp != NULL) ; i++, pwps++) { /*
* Make sure this hwnd is still here. */ if ((pwnd = RevalidateHwnd(pwps->hwnd)) == NULL || TestWF(pwnd, WEFTOOLWINDOW)) { continue; }
psmwp = _DeferWindowPos(psmwp, pwnd, (PWND)HWND_TOP, pwps->rcWindow.left, pwps->rcWindow.top, pwps->rcWindow.right - pwps->rcWindow.left, pwps->rcWindow.bottom - pwps->rcWindow.top, SWP_NOACTIVATE | SWP_NOZORDER); }
if (psmwp != NULL) { xxxEndDeferWindowPosEx(psmwp, TRUE); } else{ Status = STATUS_NO_MEMORY; } } } Exit: CleanupMonitorsAndWindowsSnapShot();
return Status; }
/*****************************************************************************\
* SnapShotMonitorsAndWindowsRects * * Captures windows sizes and positions in a WMSNAPSHOT structure. Capture * happens when disconnecting from local console. \*****************************************************************************/ NTSTATUS SnapShotMonitorsAndWindowsRects( VOID)
{ /*
* First, cleanup anything left over from previous captures. */ if (gwms.pmr != NULL || gwms.pwps != NULL) { CleanupMonitorsAndWindowsSnapShot(); }
/*
* Get a snaphot of current monitors configuration. */ if ((gwms.pmr = SnapshotMonitorRects()) == NULL) { return STATUS_NO_MEMORY; }
/*
* Get a snaphsot of windows positions. */ if ((gwms.pwps = SnapshotWindowRects(&gwms.cWindows)) == NULL) { CleanupMonitorsAndWindowsSnapShot(); return STATUS_NO_MEMORY; }
return STATUS_SUCCESS; }
/*****************************************************************************\
* CleanupMonitorsAndWindowsSnapShot * * Frees memory allocated to capture windows sizes and positions a WMSNAPSHOT * structure. \*****************************************************************************/ VOID CleanupMonitorsAndWindowsSnapShot( VOID) { PWPSNAPSHOT pwps = gwms.pwps;
if (gwms.pmr != NULL) { UserFreePool(gwms.pmr); gwms.pmr = NULL; }
if (pwps != NULL) { UserFreePool(gwms.pwps); gwms.pwps = NULL; }
gwms.cWindows = 0; }
/*****************************************************************************\
* SnapshotWindowRects * * Allocates memory to capture window sizes and positions in a WMSNAPSHOT * structure. \*****************************************************************************/ PWPSNAPSHOT SnapshotWindowRects( int *pnWindows) { PWND pwndDesktop; PHWND phwnd; PBWL pbwl; PWND pwnd; int nWindows = 0; PWPSNAPSHOT pwps = NULL; PWPSNAPSHOT pReturnedpwps = NULL;
/*
* Initialize captured windows count. */
*pnWindows = 0;
/*
* Build a list of top windows. */
UserVerify(pwndDesktop = _GetDesktopWindow()); if ((pbwl = BuildHwndList(pwndDesktop->spwndChild, BWL_ENUMLIST, NULL)) == NULL) { return NULL; }
/*
* Count maximum captured windows to allocate WPSNAPSHOT array. */ phwnd = pbwl->rghwnd; while (*phwnd != (HWND)1) { nWindows++; phwnd++; }
if (nWindows != 0) { pwps = UserAllocPoolWithQuotaZInit(sizeof(WPSNAPSHOT) * nWindows, TAG_SWP); }
if (pwps == NULL) { FreeHwndList(pbwl); return NULL; } pReturnedpwps = pwps;
for (phwnd = pbwl->rghwnd; *phwnd != (HWND)1; phwnd++) { /*
* Make sure this hwnd is still around. */ if ((pwnd = RevalidateHwnd(*phwnd)) == NULL || TestWF(pwnd, WEFTOOLWINDOW) ) { continue; }
pwps->hwnd = *phwnd; CopyRect(&pwps->rcWindow, &pwnd->rcWindow); (*pnWindows)++; pwps++;
}
if (*pnWindows != 0) { return pReturnedpwps; } else { UserFreePool(pReturnedpwps); return NULL; } }
|