windows-nt/Source/XPSP1/NT/shell/osshell/cpls/access/access.c
2020-09-26 16:20:57 +08:00

1045 lines
31 KiB
C

// **************************************************************************
// Access.c
//
// Accessability Property sheet page creator
//
// **************************************************************************
#include "Access.h"
#ifdef UNICODE // Windows uses UNICODE
#define _UNICODE // but tchar.h uses _UNICODE
#endif
DWORD g_dwOrigFKFlags;
BOOL g_bFKOn;
#include <stdlib.h>
#include <stddef.h>
#include <tchar.h>
#define OLDDISABLED 32760
#ifndef FKF_VALID
#define FKF_VALID 0x0000007F
#endif
#ifndef SKF_VALID
#define SKF_VALID 0x000001FF
#endif
#ifndef MKF_VALID
#define MKF_VALID 0x000000FF
#endif
#ifndef ATF_VALID
#define ATF_VALID 0x00000003
#endif
#ifndef SSF_VALID
#define SSF_VALID 0x00000007
#endif
#ifndef TKF_VALID
#define TKF_VALID 0x0000003F
#endif
//////////////////////////////////////////////////////////////////////////
// collection of data that represents the saved accessability state
typedef struct ACCSTATE // as
{
// Keyboard property page
STICKYKEYS sk;
FILTERKEYS fk;
TOGGLEKEYS tk;
BOOL fExtraKeyboardHelp;
// Sound Property page
SOUNDSENTRY ss;
BOOL fShowSounds;
// Display Property page
HIGHCONTRAST hc;
TCHAR szDefaultScheme[256]; // hc.lpszDefaultScheme
CARET_SETTINGS cs;
// Mouse Property page
MOUSEKEYS mk;
// General Property page
BOOL fShowWarnMsgOnFeatureActivate;
BOOL fPlaySndOnFeatureActivate;
ACCESSTIMEOUT ato;
SERIALKEYS serk;
TCHAR szActivePort[MAX_PATH]; // serk.szActivePort
TCHAR szPort[MAX_PATH]; // serk.szPort
} ACCSTATE, *PACCSTATE;
//////////////////////////////////////////////////////////////////////////
extern BOOL g_SPISetValue = FALSE;
static ACCSTATE s_asOrg; // original settings from app start-up
static ACCSTATE s_asPrev; // previous saved settings
extern BOOL g_fWinNT = -1; // TRUE if we're running on NT and must
// disable some features
extern BOOL g_fSaveSettings = TRUE;
extern BOOL g_fShowWarnMsgOnFeatureActivate = TRUE;
extern BOOL g_fPlaySndOnFeatureActivate = TRUE;
extern BOOL g_fCopyToLogon = FALSE;
extern BOOL g_fCopyToDefault = FALSE;
// Keyboard property page
// extern STICKYKEYS g_sk = {0};
STICKYKEYS g_sk;
FILTERKEYS g_fk;
// g_dwLastBounceKeySetting, g_nLastRepeatDelay, g_nLastRepeatRate
// and g_nLastWait are part of FilterKeys
DWORD g_dwLastBounceKeySetting = 0;
DWORD g_nLastRepeatDelay = 0;
DWORD g_nLastRepeatRate = 0;
DWORD g_nLastWait = 0;
TOGGLEKEYS g_tk;
BOOL g_fExtraKeyboardHelp = TRUE;
// Sound Property page
SOUNDSENTRY g_ss;
BOOL g_fShowSounds;
// Display Property page
HIGHCONTRAST g_hc;
CARET_SETTINGS g_cs;
// Mouse Property page
MOUSEKEYS g_mk;
// General Property page
ACCESSTIMEOUT g_ato;
SERIALKEYS g_serk;
TCHAR g_szActivePort[MAX_PATH];
TCHAR g_szPort[MAX_PATH];
#define CONTROL_PANEL_DESKTOP TEXT("Control Panel\\Desktop")
#define CURSOR_BLINK_RATE TEXT("CursorBlinkRate")
#define DEFAULT_BLINK_RATE 530
//////////////////////////////////////////////////////////////////////////
void CopyHighContrast(LPHIGHCONTRAST phcDest, LPHIGHCONTRAST phcSrc)
{
LPTSTR lpszDefaultScheme = phcDest->lpszDefaultScheme;
memcpy(phcDest, phcSrc, sizeof(*phcDest));
phcDest->lpszDefaultScheme = lpszDefaultScheme;
if (NULL != phcDest->lpszDefaultScheme)
{
lstrcpy(phcDest->lpszDefaultScheme, phcSrc->lpszDefaultScheme);
}
}
//////////////////////////////////////////////////////////////////////////
BOOL IsHighContrastEqual(LPHIGHCONTRAST phcDest, LPHIGHCONTRAST phcSrc)
{
BOOL fIsEqual = FALSE;
LPTSTR lpszDefaultScheme = phcDest->lpszDefaultScheme;
// Temporarily make the pointers match
phcDest->lpszDefaultScheme = phcSrc->lpszDefaultScheme;
// match the bits of the structures and the pointed to data
fIsEqual = (0 == memcmp(phcDest, phcSrc, sizeof(*phcDest)) &&
0 == lstrcmp(lpszDefaultScheme, phcSrc->lpszDefaultScheme));
phcDest->lpszDefaultScheme = lpszDefaultScheme;
return(fIsEqual);
}
//////////////////////////////////////////////////////////////////////////
void CopySerialKeys(LPSERIALKEYS pskDest, LPSERIALKEYS pskSrc)
{
LPTSTR lpszActivePort = pskDest->lpszActivePort;
LPTSTR lpszPort = pskDest->lpszPort;
memcpy(pskDest, pskSrc, sizeof(*pskDest));
pskDest->lpszActivePort = lpszActivePort;
if (NULL != pskDest->lpszActivePort)
{
lstrcpy(pskDest->lpszActivePort, pskSrc->lpszActivePort);
}
pskDest->lpszPort = lpszPort;
if (NULL != pskDest->lpszPort)
{
lstrcpy(pskDest->lpszPort, pskSrc->lpszPort);
}
}
//////////////////////////////////////////////////////////////////////////
BOOL IsSerialKeysEqual(LPSERIALKEYS pskDest, LPSERIALKEYS pskSrc)
{
BOOL fIsEqual = FALSE;
LPTSTR lpszActivePort = pskDest->lpszActivePort;
LPTSTR lpszPort = pskDest->lpszPort;
// Temporarily make the pointers match
pskDest->lpszActivePort = pskSrc->lpszActivePort;
pskDest->lpszPort = pskSrc->lpszPort;
// match the bits of the structures and the pointed to data
fIsEqual = (0 == memcmp(pskDest, pskSrc, sizeof(*pskDest)) &&
(NULL == lpszActivePort ||
0 == lstrcmp(lpszActivePort, pskSrc->lpszActivePort)) &&
(NULL == lpszPort ||
0 == lstrcmp(lpszPort, pskSrc->lpszPort)));
pskDest->lpszActivePort = lpszActivePort;
pskDest->lpszPort = lpszPort;
return(fIsEqual);
}
//////////////////////////////////////////////////////////////////////////
BOOL IsAccStateEqual(PACCSTATE pasDest, PACCSTATE pasSrc)
{
BOOL fIsEqual = FALSE;
HIGHCONTRAST hc = pasDest->hc;
SERIALKEYS serk = pasDest->serk;
int nLen;
// Clear out the unused sections of the string buffers
nLen = lstrlen(pasDest->szDefaultScheme);
memset(&pasDest->szDefaultScheme[nLen], 0,
sizeof(pasDest->szDefaultScheme)-nLen*sizeof(*pasDest->szDefaultScheme));
nLen = lstrlen(pasDest->szActivePort);
memset(&pasDest->szActivePort[nLen], 0,
sizeof(pasDest->szActivePort)-nLen*sizeof(*pasDest->szActivePort));
nLen = lstrlen(pasDest->szPort);
memset(&pasDest->szPort[nLen], 0,
sizeof(pasDest->szPort)-nLen*sizeof(*pasDest->szPort));
nLen = lstrlen(pasSrc->szDefaultScheme);
memset(&pasSrc->szDefaultScheme[nLen], 0,
sizeof(pasSrc->szDefaultScheme)-nLen*sizeof(*pasSrc->szDefaultScheme));
nLen = lstrlen(pasSrc->szActivePort);
memset(&pasSrc->szActivePort[nLen], 0,
sizeof(pasSrc->szActivePort)-nLen*sizeof(*pasSrc->szActivePort));
nLen = lstrlen(pasSrc->szActivePort);
memset(&pasSrc->szPort[nLen], 0,
sizeof(pasSrc->szPort)-nLen*sizeof(*pasSrc->szPort));
// Temporarily make the elements with pointers match
pasDest->hc = pasSrc->hc;
pasDest->serk = pasSrc->serk;
// match the bits of the structures and the elements with pointers
fIsEqual = (0 == memcmp(pasDest, pasSrc, sizeof(*pasDest)) &&
IsHighContrastEqual(&hc, &pasSrc->hc) &&
IsSerialKeysEqual(&serk, &pasSrc->serk));
pasDest->hc = hc;
pasDest->serk = serk;
return(fIsEqual);
}
//////////////////////////////////////////////////////////////////////////
int WINAPI RegQueryInt (int nDefault, HKEY hkey, LPTSTR lpSubKey, LPTSTR lpValueName) {
DWORD dwType;
DWORD dwVal = nDefault;
DWORD cbData = sizeof(int);
if (ERROR_SUCCESS == RegOpenKeyEx(hkey, lpSubKey, 0, KEY_QUERY_VALUE, &hkey)) {
RegQueryValueEx(hkey, lpValueName, NULL, &dwType, (PBYTE) &dwVal, &cbData);
RegCloseKey(hkey);
}
return(dwVal);
}
//////////////////////////////////////////////////////////////////////////
BOOL WINAPI RegSetInt (HKEY hkey, LPTSTR lpSubKey, LPTSTR lpValueName, int nVal) {
BOOL fOk = FALSE;
DWORD dwDisposition;
LONG lRet;
if (ERROR_SUCCESS == RegCreateKeyEx(hkey, lpSubKey, 0, NULL, REG_OPTION_NON_VOLATILE,
KEY_SET_VALUE, NULL, &hkey, &dwDisposition)) {
lRet = RegSetValueEx(hkey, lpValueName, 0, REG_DWORD, (CONST BYTE *) &nVal, sizeof(nVal));
fOk = (ERROR_SUCCESS == lRet);
RegCloseKey(hkey);
}
return fOk;
}
//////////////////////////////////////////////////////////////////////////
void WINAPI RegQueryStr(
LPTSTR lpDefault,
HKEY hkey,
LPTSTR lpSubKey,
LPTSTR lpValueName,
LPTSTR lpszValue,
DWORD cbData) // note this is bytes, not characters.
{
DWORD dwType;
lstrcpy(lpszValue, lpDefault);
if (ERROR_SUCCESS == RegOpenKeyEx(hkey, lpSubKey, 0, KEY_QUERY_VALUE, &hkey)) {
RegQueryValueEx(hkey, lpValueName, NULL, &dwType, (PBYTE) lpszValue, &cbData);
RegCloseKey(hkey);
}
}
/***************************************************************************\
**AccessWriteProfileString
*
* History:
* 12-19-95 a-jimhar Created (was called AccessWriteProfileString)
* 02-08-95 a-jimhar revised and moved from accrare.c to access.c
\***************************************************************************/
BOOL RegSetStr(
HKEY hkey,
LPCTSTR lpSection,
LPCTSTR lpKeyName,
LPCTSTR lpString)
{
BOOL fRet = FALSE;
LONG lErr;
DWORD dwDisposition;
lErr = RegCreateKeyEx(
hkey,
lpSection,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_SET_VALUE,
NULL,
&hkey,
&dwDisposition);
if (ERROR_SUCCESS == lErr)
{
if (NULL != lpString)
{
lErr = RegSetValueEx(
hkey,
lpKeyName,
0,
REG_SZ,
(CONST BYTE *)lpString,
(lstrlen(lpString) + 1) * sizeof(*lpString));
}
else
{
lErr = RegSetValueEx(
hkey,
lpKeyName,
0,
REG_SZ,
(CONST BYTE *)__TEXT(""),
1 * sizeof(*lpString));
}
if (ERROR_SUCCESS == lErr)
{
fRet = TRUE;
}
RegCloseKey(hkey);
}
return(fRet);
}
DWORD WINAPI RegQueryStrDW(
DWORD dwDefault,
HKEY hkey,
LPTSTR lpSubKey,
LPTSTR lpValueName)
{
DWORD dwRet = dwDefault;
TCHAR szTemp[40];
TCHAR szDefault[40];
const LPTSTR pwszd = __TEXT("%d");
wsprintf(szDefault, pwszd, dwDefault);
RegQueryStr(
szDefault,
hkey,
lpSubKey,
lpValueName,
szTemp,
sizeof(szTemp));
dwRet = _ttol(szTemp);
return dwRet;
}
BOOL RegSetStrDW(
HKEY hkey,
LPTSTR lpSection,
LPCTSTR lpKeyName,
DWORD dwValue)
{
BOOL fRet;
TCHAR szTemp[40];
const LPTSTR pwszd = __TEXT("%d");
wsprintf(szTemp, pwszd, dwValue);
fRet = RegSetStr(hkey, lpSection, lpKeyName, szTemp);
return fRet;
}
//////////////////////////////////////////////////////////////////////////
/*------------------------------------------------------------------
* Function void KillAccStat()
*
* Purpose Check if accstat is already running. If it is we need
* to check to see if it should be. It should only be running
* if each feature that is on also has the 'show status on
* screen flag checked. If not we want to kill accstat.
*
* Params: None
*
* Return: TRUE if we had to kill accstat
* FALSE if accstat not running/valid session
*------------------------------------------------------------------*/
void KillAccStat (void) {
BOOL fCanTurnOff = FALSE; // Can we turn off accstat due to invalid feature?
BOOL fValidFeature = FALSE; // Are there any valid features?
// Accstat may be running. Determine if it should be running
// We need to check the FilterKeys, MouseKeys and StickyKeys
if (g_sk.dwFlags & SKF_STICKYKEYSON)
if (!(g_sk.dwFlags & SKF_INDICATOR))
fCanTurnOff = TRUE; // A mismatched flag - we MAY be able to turn off.
else
fValidFeature = TRUE; // A valid feature - we CAN't turn off accstat.
if (g_fk.dwFlags & FKF_FILTERKEYSON)
if (!(g_fk.dwFlags & FKF_INDICATOR))
fCanTurnOff = TRUE; // A mismatched flag - we MAY be able to turn off.
else
fValidFeature = TRUE; // A valid feature - we CAN't turn off accstat.
if (g_mk.dwFlags & MKF_MOUSEKEYSON)
if (!(g_mk.dwFlags & MKF_INDICATOR))
fCanTurnOff = TRUE; // A mismatched flag - we MAY be able to turn off.
else
fValidFeature = TRUE; // A valid feature - we CAN't turn off accstat.
// Now we have two flags: fCanTurnOff is TRUE if there is a mismatched flag set
// ie, feature on, indicator off. ValidFeature is TRUE if any feature has
// ON and INDICATOR set which implies accstat must remain active.
if (!fValidFeature && fCanTurnOff) {
TCHAR szBuf[256];
HWND hwndAccStat;
LoadString(g_hinst, IDS_ACCSTAT_WINDOW_TITLE, szBuf, ARRAY_SIZE(szBuf));
if (IsWindow(hwndAccStat = FindWindow(NULL, szBuf))) {
// Note sending 1 as the lParam tells accstat to shutup and
// go away NOW.
SendMessage(hwndAccStat, WM_SYSCOMMAND, SC_CLOSE, 1);
}
}
}
//////////////////////////////////////////////////////////////////////////
void WINAPI GetAccessibilitySettings (void) {
BOOL fUpdate;
if (g_fWinNT == -1) {
OSVERSIONINFO osvi;
osvi.dwOSVersionInfoSize = sizeof(osvi);
GetVersionEx(&osvi);
g_fWinNT = (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT);
}
g_fShowWarnMsgOnFeatureActivate = (BOOL) RegQueryInt(TRUE, HKEY_CURRENT_USER,
GENERAL_KEY, WARNING_SOUNDS);
s_asPrev.fShowWarnMsgOnFeatureActivate = g_fShowWarnMsgOnFeatureActivate;
// Query the Sound On Activation entry
g_fPlaySndOnFeatureActivate = (BOOL) RegQueryInt(TRUE, HKEY_CURRENT_USER,
GENERAL_KEY, SOUND_ON_ACTIVATION);
s_asPrev.fPlaySndOnFeatureActivate = g_fPlaySndOnFeatureActivate;
g_fSaveSettings = TRUE;
// Keyboard property page
g_sk.cbSize = sizeof(g_sk);
AccessSystemParametersInfo(SPI_GETSTICKYKEYS, sizeof(g_sk), &g_sk, 0);
s_asPrev.sk = g_sk;
g_fk.cbSize = sizeof(g_fk);
AccessSystemParametersInfo(SPI_GETFILTERKEYS, sizeof(g_fk), &g_fk, 0);
g_fk.dwFlags |= FKF_AVAILABLE;
// FILTERKEYS used to use OLDDISABLED as it's "unused" flag. This doesn't
// work very well on NT (SPI_SETFILTERKEYS calls fail). We now use 0
// for disabled values. Take this opertunity to change any OLDDISABLED
// values to 0 and save if needed.
fUpdate = FALSE;
if (OLDDISABLED == g_fk.iBounceMSec)
{
g_fk.iBounceMSec = 0;
fUpdate = TRUE;
}
if (OLDDISABLED == g_fk.iDelayMSec)
{
g_fk.iDelayMSec = 0;
fUpdate = TRUE;
}
if (OLDDISABLED == g_fk.iRepeatMSec)
{
g_fk.iRepeatMSec = 0;
fUpdate = TRUE;
}
if (OLDDISABLED == g_fk.iWaitMSec)
{
g_fk.iWaitMSec = 0;
fUpdate = TRUE;
}
if (fUpdate)
{
AccessSystemParametersInfo(
SPI_SETFILTERKEYS, sizeof(g_fk), &g_fk, SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE);
}
s_asPrev.fk = g_fk;
// fix Filter keys bug
g_dwOrigFKFlags = g_fk.dwFlags;
g_bFKOn = g_fk.dwFlags & FKF_FILTERKEYSON;
// g_dwLastBounceKeySetting, g_nLastRepeatDelay, g_nLastRepeatRate
// and g_nLastWait are part of FilterKeys
if (0 != g_fk.iBounceMSec) {
// Bounce keys enabeled
g_fk.iDelayMSec = 0;
g_fk.iRepeatMSec = 0;
g_fk.iWaitMSec = 0;
g_dwLastBounceKeySetting = g_fk.iBounceMSec;
g_nLastRepeatDelay = RegQueryInt(0, HKEY_CURRENT_USER, FILTER_KEY, LAST_REPEAT_DELAY);
g_nLastRepeatRate = RegQueryInt(0, HKEY_CURRENT_USER, FILTER_KEY, LAST_REPEAT_RATE);
g_nLastWait = RegQueryInt(0, HKEY_CURRENT_USER, FILTER_KEY, LAST_WAIT);
}
else
{
if (0 == g_fk.iDelayMSec)
{
g_fk.iRepeatMSec = 0;
}
g_dwLastBounceKeySetting = RegQueryInt(0, HKEY_CURRENT_USER, FILTER_KEY, LAST_BOUNCE_SETTING);
g_nLastRepeatDelay = RegQueryInt(0, HKEY_CURRENT_USER, FILTER_KEY, LAST_REPEAT_DELAY);
g_nLastRepeatRate = RegQueryInt(0, HKEY_CURRENT_USER, FILTER_KEY, LAST_REPEAT_RATE);
if (0 != g_fk.iWaitMSec)
{
g_nLastWait = g_fk.iWaitMSec;
}
else
{
g_nLastWait = RegQueryInt(0, HKEY_CURRENT_USER, FILTER_KEY, LAST_WAIT);
}
}
g_tk.cbSize = sizeof(g_tk);
AccessSystemParametersInfo(SPI_GETTOGGLEKEYS, sizeof(g_tk), &g_tk, 0);
s_asPrev.tk = g_tk;
AccessSystemParametersInfo(SPI_GETKEYBOARDPREF, 0, &g_fExtraKeyboardHelp, 0);
s_asPrev.fExtraKeyboardHelp = g_fExtraKeyboardHelp;
// Sound Property page
g_ss.cbSize = sizeof(g_ss);
AccessSystemParametersInfo(SPI_GETSOUNDSENTRY, sizeof(g_ss), &g_ss, 0);
s_asPrev.ss = g_ss;
SystemParametersInfo(SPI_GETSHOWSOUNDS, 0, &g_fShowSounds, 0);
// BUG, BUG GetSystemMetrics() is not updating value on reboot :a-anilk
// g_fShowSounds = GetSystemMetrics(SM_SHOWSOUNDS);
s_asPrev.fShowSounds = g_fShowSounds;
// Display Property page
g_hc.cbSize = sizeof(g_hc);
AccessSystemParametersInfo(SPI_GETHIGHCONTRAST, sizeof(g_hc), &g_hc, 0);
// Currently NT will not store these flags. We fake them so we
// can tell if they actually changed.
s_asPrev.hc.lpszDefaultScheme = s_asPrev.szDefaultScheme;
CopyHighContrast(&s_asPrev.hc, &g_hc);
SystemParametersInfo(SPI_GETCARETWIDTH, 0, (PVOID)&g_cs.dwCaretWidth, 0);
g_cs.dwCaretBlinkRate = RegQueryStrDW(
DEFAULT_BLINK_RATE
, HKEY_CURRENT_USER
, CONTROL_PANEL_DESKTOP
, CURSOR_BLINK_RATE);
if (g_cs.dwCaretBlinkRate == BLINK_OFF)
g_cs.dwCaretBlinkRate = CURSORMAX;
s_asPrev.cs.dwCaretBlinkRate = g_cs.dwCaretBlinkRate;
s_asPrev.cs.dwCaretWidth = g_cs.dwCaretWidth;
// Mouse Property page
g_mk.cbSize = sizeof(g_mk);
AccessSystemParametersInfo(SPI_GETMOUSEKEYS, sizeof(g_mk), &g_mk, 0);
s_asPrev.mk = g_mk;
// General Property page
g_ato.cbSize = sizeof(g_ato);
AccessSystemParametersInfo(SPI_GETACCESSTIMEOUT, sizeof(g_ato), &g_ato, 0);
s_asPrev.ato = g_ato;
g_serk.cbSize = sizeof(g_serk);
g_serk.lpszActivePort = g_szActivePort;
g_serk.lpszPort = g_szPort;
AccessSystemParametersInfo(SPI_GETSERIALKEYS, sizeof(g_serk), &g_serk, 0);
s_asPrev.serk.lpszActivePort = s_asPrev.szActivePort;
s_asPrev.serk.lpszPort = s_asPrev.szPort;
CopySerialKeys(&s_asPrev.serk, &g_serk);
if (NULL == s_asOrg.hc.lpszDefaultScheme)
{
// s_asOrg has not yet been initialized
s_asOrg = s_asPrev;
s_asOrg.hc.lpszDefaultScheme = s_asOrg.szDefaultScheme;
s_asOrg.serk.lpszActivePort = s_asOrg.szActivePort;
s_asOrg.serk.lpszPort = s_asOrg.szPort;
}
}
//////////////////////////////////////////////////////////////////////////
//a-anilk: Change, Admin options, Keyboard flags: 05/06/99
void WINAPI SetAccessibilitySettings (void) {
HKEY hkey;
DWORD dwDisposition;
UINT fWinIni = SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE;
BOOL fAnyNotifyChange = FALSE;
g_SPISetValue = TRUE;
SetCursor(LoadCursor(NULL, IDC_WAIT));
if (g_fShowWarnMsgOnFeatureActivate) {
g_hc.dwFlags |= HCF_CONFIRMHOTKEY;
g_fk.dwFlags |= FKF_CONFIRMHOTKEY;
g_sk.dwFlags |= SKF_CONFIRMHOTKEY;
g_mk.dwFlags |= MKF_CONFIRMHOTKEY;
g_tk.dwFlags |= TKF_CONFIRMHOTKEY;
} else {
g_hc.dwFlags &= ~HCF_CONFIRMHOTKEY;
g_fk.dwFlags &= ~FKF_CONFIRMHOTKEY;
g_sk.dwFlags &= ~SKF_CONFIRMHOTKEY;
g_mk.dwFlags &= ~MKF_CONFIRMHOTKEY;
g_tk.dwFlags &= ~TKF_CONFIRMHOTKEY;
}
if (g_fPlaySndOnFeatureActivate) {
g_hc.dwFlags |= HCF_HOTKEYSOUND;
g_fk.dwFlags |= FKF_HOTKEYSOUND;
g_sk.dwFlags |= SKF_HOTKEYSOUND;
g_mk.dwFlags |= MKF_HOTKEYSOUND;
g_tk.dwFlags |= TKF_HOTKEYSOUND;
g_ato.dwFlags |= ATF_ONOFFFEEDBACK;
} else {
g_hc.dwFlags &= ~HCF_HOTKEYSOUND;
g_fk.dwFlags &= ~FKF_HOTKEYSOUND;
g_sk.dwFlags &= ~SKF_HOTKEYSOUND;
g_mk.dwFlags &= ~MKF_HOTKEYSOUND;
g_tk.dwFlags &= ~TKF_HOTKEYSOUND;
g_ato.dwFlags &= ~ATF_ONOFFFEEDBACK;
}
// Keyboard property page
if (0 != memcmp(&g_sk, &s_asPrev.sk, sizeof(g_sk)))
{
if (g_fWinNT)
{
g_sk.dwFlags &= SKF_VALID;
}
AccessSystemParametersInfo(SPI_SETSTICKYKEYS, sizeof(g_sk), &g_sk, fWinIni);
s_asPrev.sk = g_sk;
fAnyNotifyChange = TRUE;
}
if (g_bFKOn)
g_fk.dwFlags |= FKF_FILTERKEYSON;
else
g_fk.dwFlags &= ~FKF_FILTERKEYSON;
g_dwOrigFKFlags = g_fk.dwFlags;
if (0 != memcmp(&g_fk, &s_asPrev.fk, sizeof(g_fk)))
{
if (g_fWinNT)
{
g_fk.dwFlags &= FKF_VALID;
}
// g_dwLastBounceKeySetting, g_nLastRepeatDelay, g_nLastRepeatRate
// and g_nLastWait are part of FilterKeys
if (0 != g_fk.iBounceMSec) {
// Bounce keys enabeled
g_fk.iDelayMSec = 0;
g_fk.iRepeatMSec = 0;
g_fk.iWaitMSec = 0;
g_dwLastBounceKeySetting = g_fk.iBounceMSec;
}
else
{
g_nLastWait = g_fk.iWaitMSec;
if (0 != g_fk.iDelayMSec)
{
// Slow key enabled
g_nLastRepeatDelay = g_fk.iDelayMSec;
g_nLastRepeatRate = g_fk.iRepeatMSec;
}
else
{
// neither Bounce or Slow
g_fk.iRepeatMSec = 0;
}
}
AccessSystemParametersInfo(SPI_SETFILTERKEYS, sizeof(g_fk), &g_fk, fWinIni);
s_asPrev.fk = g_fk;
fAnyNotifyChange = TRUE;
}
// always save these
RegSetInt(HKEY_CURRENT_USER, FILTER_KEY, LAST_BOUNCE_SETTING, g_dwLastBounceKeySetting);
RegSetInt(HKEY_CURRENT_USER, FILTER_KEY, LAST_REPEAT_DELAY, g_nLastRepeatDelay);
RegSetInt(HKEY_CURRENT_USER, FILTER_KEY, LAST_REPEAT_RATE, g_nLastRepeatRate);
RegSetInt(HKEY_CURRENT_USER, FILTER_KEY, LAST_WAIT, g_nLastWait);
if (0 != memcmp(&g_tk, &s_asPrev.tk, sizeof(g_tk)))
{
if (g_fWinNT)
{
g_tk.dwFlags &= TKF_VALID;
}
AccessSystemParametersInfo(SPI_SETTOGGLEKEYS, sizeof(g_tk), &g_tk, fWinIni);
s_asPrev.tk = g_tk;
fAnyNotifyChange = TRUE;
}
if (g_fExtraKeyboardHelp != s_asPrev.fExtraKeyboardHelp)
{
// Set this too. Some controls check this flag...0x100B
AccessSystemParametersInfo(SPI_SETKEYBOARDCUES, 0, IntToPtr(g_fExtraKeyboardHelp), fWinIni);
AccessSystemParametersInfo(SPI_SETKEYBOARDPREF, g_fExtraKeyboardHelp, 0, fWinIni);
s_asPrev.fExtraKeyboardHelp = g_fExtraKeyboardHelp;
fAnyNotifyChange = TRUE;
}
// Display Property page
// BUGBUG a-jimhar 03-22-96 verify changes to display property page save
// code when display page is added back in on NT
if (!IsHighContrastEqual(&g_hc, &s_asPrev.hc))
{
AccessSystemParametersInfo(SPI_SETHIGHCONTRAST, sizeof(g_hc), &g_hc, fWinIni);
if (ERROR_SUCCESS == RegCreateKeyEx(
HKEY_CURRENT_USER,
HC_KEY,
0,
__TEXT(""),
REG_OPTION_NON_VOLATILE,
KEY_SET_VALUE,
NULL,
&hkey,
&dwDisposition))
{
RegSetValueEx(hkey, HIGHCONTRAST_SCHEME, 0, REG_SZ, (PBYTE) g_hc.lpszDefaultScheme,
(lstrlen(g_hc.lpszDefaultScheme) + 1) * sizeof(*g_hc.lpszDefaultScheme));
RegSetValueEx(hkey, VOLATILE_SCHEME, 0, REG_SZ, (PBYTE) g_hc.lpszDefaultScheme,
(lstrlen(g_hc.lpszDefaultScheme) + 1) * sizeof(*g_hc.lpszDefaultScheme));
RegCloseKey(hkey);
hkey = NULL;
}
CopyHighContrast(&s_asPrev.hc, &g_hc);
fAnyNotifyChange = TRUE;
}
if (g_cs.dwCaretBlinkRate != s_asPrev.cs.dwCaretBlinkRate)
{
DWORD dwCaretBlinkRate = (g_cs.dwCaretBlinkRate < CURSORMAX)?g_cs.dwCaretBlinkRate:BLINK_OFF;
// Set the blink rate for this session
SetCaretBlinkTime(dwCaretBlinkRate);
// and persist it to the registry
RegSetStrDW(HKEY_CURRENT_USER, CONTROL_PANEL_DESKTOP, CURSOR_BLINK_RATE, dwCaretBlinkRate);
}
if (g_cs.dwCaretWidth != s_asPrev.cs.dwCaretWidth)
AccessSystemParametersInfo(SPI_SETCARETWIDTH, 0, IntToPtr(g_cs.dwCaretWidth), fWinIni);
s_asPrev.cs = g_cs;
// Mouse Property page
if (0 != memcmp(&g_mk, &s_asPrev.mk, sizeof(g_mk)))
{
if (g_fWinNT)
{
g_mk.dwFlags &= MKF_VALID;
}
AccessSystemParametersInfo(SPI_SETMOUSEKEYS, sizeof(g_mk), &g_mk, fWinIni);
s_asPrev.mk = g_mk;
fAnyNotifyChange = TRUE;
}
// General Property page
if (g_fPlaySndOnFeatureActivate) {
g_ato.dwFlags |= ATF_ONOFFFEEDBACK;
} else {
g_ato.dwFlags &= ~ATF_ONOFFFEEDBACK;
}
if (0 != memcmp(&g_ato, &s_asPrev.ato, sizeof(g_ato)))
{
if (g_fWinNT)
{
g_ato.dwFlags &= ATF_VALID;
}
AccessSystemParametersInfo(SPI_SETACCESSTIMEOUT, sizeof(g_ato), &g_ato, fWinIni);
s_asPrev.ato = g_ato;
fAnyNotifyChange = TRUE;
}
if (!IsSerialKeysEqual(&g_serk, &s_asPrev.serk))
{
AccessSystemParametersInfo(SPI_SETSERIALKEYS, sizeof(g_serk), &g_serk, fWinIni);
CopySerialKeys(&s_asPrev.serk, &g_serk);
fAnyNotifyChange = TRUE;
}
if (g_fSaveSettings) {
if (RegCreateKeyEx(HKEY_CURRENT_USER, GENERAL_KEY, 0, __TEXT(""), REG_OPTION_NON_VOLATILE,
KEY_SET_VALUE, NULL, &hkey, &dwDisposition) == ERROR_SUCCESS) {
// Save the Warning Sounds entry
if (g_fShowWarnMsgOnFeatureActivate != s_asPrev.fShowWarnMsgOnFeatureActivate)
{
RegSetValueEx(hkey, WARNING_SOUNDS, 0, REG_DWORD, (PBYTE) &g_fShowWarnMsgOnFeatureActivate,
sizeof(g_fShowWarnMsgOnFeatureActivate));
s_asPrev.fShowWarnMsgOnFeatureActivate = g_fShowWarnMsgOnFeatureActivate;
}
// Save the Sound On Activation entry
if (g_fPlaySndOnFeatureActivate != s_asPrev.fPlaySndOnFeatureActivate)
{
RegSetValueEx(hkey, SOUND_ON_ACTIVATION, 0, REG_DWORD, (PBYTE) &g_fPlaySndOnFeatureActivate,
sizeof(g_fPlaySndOnFeatureActivate));
s_asPrev.fPlaySndOnFeatureActivate = g_fPlaySndOnFeatureActivate;
}
RegCloseKey(hkey);
hkey = NULL;
}
}
// Sound Property page
if (0 != memcmp(&g_ss, &s_asPrev.ss, sizeof(g_ss)))
{
if (g_fWinNT)
{
g_ss.dwFlags &= SSF_VALID;
}
AccessSystemParametersInfo(SPI_SETSOUNDSENTRY, sizeof(g_ss), &g_ss, fWinIni);
s_asPrev.ss = g_ss;
fAnyNotifyChange = TRUE;
}
// We do the sound property page last because the SPI_SETSHOWSOUNDS call is used
// to send out notifications. We make this call if either g_fShowSounds changed
// or we need to send out notifications
// Changed Nov.18 '98 to send out WM_SETTINGSCHANGE Seperately.
if (g_fShowSounds != s_asPrev.fShowSounds /*||
(fAnyNotifyChange && g_fSaveSettings)*/)
{
// if (g_fSaveSettings) fWinIni |= SPIF_SENDWININICHANGE;
AccessSystemParametersInfo(SPI_SETSHOWSOUNDS, g_fShowSounds, NULL, fWinIni);
s_asPrev.fShowSounds = g_fShowSounds;
}
g_SPISetValue = FALSE;
// Do Admin options
SaveDefaultSettings(g_fCopyToLogon, g_fCopyToDefault);
SetCursor(LoadCursor(NULL, IDC_ARROW));
}
//////////////////////////////////////////////////////////////////////////
INT_PTR WINAPI KeyboardDlg (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
INT_PTR WINAPI SoundDlg (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
INT_PTR WINAPI GeneralDlg (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
INT_PTR WINAPI DisplayDlg (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
INT_PTR WINAPI MouseDlg (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
#define MAX_PAGES 10
// ************************************************************************
// OpenAccessPropertySheet
// Opens property sheet
// ************************************************************************
BOOL OpenAccessPropertySheet (HWND hwnd, int nID) {
HPROPSHEETPAGE rPages[MAX_PAGES];
PROPSHEETPAGE psp;
PROPSHEETHEADER psh;
INT_PTR nPsRet;
KillAccStat();
GetAccessibilitySettings();
// Simple errorchecking - only allow control to move to tabs 0-4.
// Any tab request greater than 4 is invalid - so default to tab 0
if ((nID < 0) || (nID > 4)) nID = 0;
// Initialize the property sheets
psh.dwSize = sizeof(psh);
// SteveDon 5-26-98
// no longer use PSH_PROPTITLE because we want it to read "Accessibility Options"
// rather than "Accessibility Properties" or "Properties for Accessibility"
psh.dwFlags = 0; // psh.dwFlags = PSH_PROPTITLE; // | PSH_PROPSHEETPAGE | PSP_USEICONID;
psh.hwndParent = hwnd;
psh.hInstance = g_hinst;
psh.pszCaption = MAKEINTRESOURCE(IDS_PROPERTY_TITLE); //ACCESSIBILITY);
psh.pszIcon = MAKEINTRESOURCE(IDI_ACCESS);
psh.nPages = 0;
psh.nStartPage = 0;
psh.phpage = rPages;
// Add First Sheet, keyboard
psp.dwSize = sizeof(psp);
psp.dwFlags = PSP_DEFAULT;
psp.hInstance = g_hinst;
psp.pszTemplate = MAKEINTRESOURCE(IDD_KEYBOARD);
psp.pfnDlgProc = KeyboardDlg;
psp.lParam = 0;
psh.phpage[psh.nPages] = CreatePropertySheetPage(&psp);
if (psh.phpage[psh.nPages]) psh.nPages++;
// Add second sheet, Sound
psp.dwSize = sizeof(psp);
psp.dwFlags = PSP_DEFAULT;
psp.hInstance = g_hinst;
psp.pszTemplate = MAKEINTRESOURCE(IDD_SOUND);
psp.pfnDlgProc = SoundDlg;
psp.lParam = 0;
psh.phpage[psh.nPages] = CreatePropertySheetPage(&psp);
if (psh.phpage[psh.nPages]) psh.nPages++;
// Add third sheet, Display
psp.dwSize = sizeof(psp);
psp.dwFlags = PSP_DEFAULT;
psp.hInstance = g_hinst;
psp.pszTemplate = MAKEINTRESOURCE(IDD_DISPLAY);
psp.pfnDlgProc = DisplayDlg;
psp.lParam = 0;
psh.phpage[psh.nPages] = CreatePropertySheetPage(&psp);
if (psh.phpage[psh.nPages]) psh.nPages++;
// Add fourth sheet, Mouse
psp.dwSize = sizeof(psp);
psp.dwFlags = PSP_DEFAULT;
psp.hInstance = g_hinst;
psp.pszTemplate = MAKEINTRESOURCE(IDD_MOUSE);
psp.pfnDlgProc = MouseDlg;
psp.lParam = 0;
psh.phpage[psh.nPages] = CreatePropertySheetPage(&psp);
if (psh.phpage[psh.nPages]) psh.nPages++;
// Add fifth sheet, General
psp.dwSize = sizeof(psp);
psp.dwFlags = PSP_DEFAULT;
psp.hInstance = g_hinst;
psp.pszTemplate = MAKEINTRESOURCE(IDD_GENERAL);
psp.pfnDlgProc = GeneralDlg;
psp.lParam = 0;
psh.phpage[psh.nPages] = CreatePropertySheetPage(&psp);
if (psh.phpage[psh.nPages]) psh.nPages++;
// Simple errorchecking - only allow control to move to tabs 0 to psh.nPages
// Any tab request greater than psh.nPages is invalid
if (0 <= nID && nID < (int)psh.nPages)
{
psh.nStartPage = nID;
}
nPsRet = PropertySheet(&psh);
if ( nPsRet <= 0 )
return FALSE;
else
return TRUE;
}
///////////////////////////////// End of File /////////////////////////////////