900 lines
23 KiB
C
900 lines
23 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (c) 1999 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
access.c
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
Implements Win9x accessiblity conversion by hooking the physical registry type
|
||
|
and emulating the NT registry format.
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Jim Schmidt (jimschm) 29-Aug-2000
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
<alias> <date> <comments>
|
||
|
|
||
|
--*/
|
||
|
|
||
|
//
|
||
|
// Includes
|
||
|
//
|
||
|
|
||
|
#include "pch.h"
|
||
|
#include "logmsg.h"
|
||
|
|
||
|
#define DBG_ACCESS "Accessibility"
|
||
|
|
||
|
//
|
||
|
// Strings
|
||
|
//
|
||
|
|
||
|
#define S_ACCESSIBILITY_ROOT TEXT("HKCU\\Control Panel\\Accessibility")
|
||
|
|
||
|
//
|
||
|
// Constants
|
||
|
//
|
||
|
|
||
|
#define SPECIAL_INVERT_OPTION 0x80000000
|
||
|
|
||
|
//
|
||
|
// Macros
|
||
|
//
|
||
|
|
||
|
// none
|
||
|
|
||
|
//
|
||
|
// Types
|
||
|
//
|
||
|
|
||
|
typedef struct {
|
||
|
PCTSTR ValueName;
|
||
|
DWORD FlagVal;
|
||
|
} ACCESS_OPTION, *PACCESS_OPTION;
|
||
|
|
||
|
typedef struct {
|
||
|
PACCESS_OPTION AccessibilityMap;
|
||
|
PCTSTR Win9xSubKey;
|
||
|
PCTSTR NtSubKey;
|
||
|
} ACCESSIBILITY_MAPPINGS, *PACCESSIBILITY_MAPPINGS;
|
||
|
|
||
|
typedef struct {
|
||
|
MEMDB_ENUM EnumStruct;
|
||
|
DWORD RegType;
|
||
|
} ACCESSIBILITY_ENUM_STATE, *PACCESSIBILITY_ENUM_STATE;
|
||
|
|
||
|
|
||
|
//
|
||
|
// Globals
|
||
|
//
|
||
|
|
||
|
MIG_OBJECTTYPEID g_RegistryTypeId;
|
||
|
HASHTABLE g_ProhibitTable;
|
||
|
|
||
|
ACCESS_OPTION g_FilterKeys[] = {
|
||
|
TEXT("On"), FKF_FILTERKEYSON,
|
||
|
TEXT("Available"), FKF_AVAILABLE,
|
||
|
TEXT("HotKeyActive"), FKF_HOTKEYACTIVE,
|
||
|
TEXT("ConfirmHotKey"), FKF_CONFIRMHOTKEY,
|
||
|
TEXT("HotKeySound"), FKF_HOTKEYSOUND,
|
||
|
TEXT("ShowStatusIndicator"), FKF_INDICATOR,
|
||
|
TEXT("ClickOn"), FKF_CLICKON,
|
||
|
TEXT("OnOffFeedback"), 0,
|
||
|
NULL
|
||
|
};
|
||
|
|
||
|
ACCESS_OPTION g_MouseKeys[] = {
|
||
|
TEXT("On"), MKF_MOUSEKEYSON,
|
||
|
TEXT("Available"), MKF_AVAILABLE,
|
||
|
TEXT("HotKeyActive"), MKF_HOTKEYACTIVE,
|
||
|
TEXT("ConfirmHotKey"), MKF_CONFIRMHOTKEY,
|
||
|
TEXT("HotKeySound"), MKF_HOTKEYSOUND,
|
||
|
TEXT("ShowStatusIndicator"), MKF_INDICATOR,
|
||
|
TEXT("Modifiers"), MKF_MODIFIERS|SPECIAL_INVERT_OPTION,
|
||
|
TEXT("ReplaceNumbers"), MKF_REPLACENUMBERS,
|
||
|
TEXT("OnOffFeedback"), 0,
|
||
|
NULL
|
||
|
};
|
||
|
|
||
|
ACCESS_OPTION g_StickyKeys[] = {
|
||
|
TEXT("On"), SKF_STICKYKEYSON,
|
||
|
TEXT("Available"), SKF_AVAILABLE,
|
||
|
TEXT("HotKeyActive"), SKF_HOTKEYACTIVE,
|
||
|
TEXT("ConfirmHotKey"), SKF_CONFIRMHOTKEY,
|
||
|
TEXT("HotKeySound"), SKF_HOTKEYSOUND,
|
||
|
TEXT("ShowStatusIndicator"), SKF_INDICATOR,
|
||
|
TEXT("AudibleFeedback"), SKF_AUDIBLEFEEDBACK,
|
||
|
TEXT("TriState"), SKF_TRISTATE,
|
||
|
TEXT("TwoKeysOff"), SKF_TWOKEYSOFF,
|
||
|
TEXT("OnOffFeedback"), 0,
|
||
|
NULL
|
||
|
};
|
||
|
|
||
|
ACCESS_OPTION g_SoundSentry[] = {
|
||
|
TEXT("On"), SSF_SOUNDSENTRYON,
|
||
|
TEXT("Available"), SSF_AVAILABLE,
|
||
|
TEXT("ShowStatusIndicator"), SSF_INDICATOR,
|
||
|
NULL
|
||
|
};
|
||
|
|
||
|
ACCESS_OPTION g_TimeOut[] = {
|
||
|
TEXT("On"), ATF_TIMEOUTON,
|
||
|
TEXT("OnOffFeedback"), ATF_ONOFFFEEDBACK,
|
||
|
NULL
|
||
|
};
|
||
|
|
||
|
ACCESS_OPTION g_ToggleKeys[] = {
|
||
|
TEXT("On"), TKF_TOGGLEKEYSON,
|
||
|
TEXT("Available"), TKF_AVAILABLE,
|
||
|
TEXT("HotKeyActive"), TKF_HOTKEYACTIVE,
|
||
|
TEXT("ConfirmHotKey"), TKF_CONFIRMHOTKEY,
|
||
|
TEXT("HotKeySound"), TKF_HOTKEYSOUND,
|
||
|
TEXT("ShowStatusIndicator"), TKF_INDICATOR,
|
||
|
TEXT("OnOffFeedback"), 0,
|
||
|
NULL
|
||
|
};
|
||
|
|
||
|
ACCESS_OPTION g_HighContrast[] = {
|
||
|
TEXT("On"), HCF_HIGHCONTRASTON,
|
||
|
TEXT("Available"), HCF_AVAILABLE,
|
||
|
TEXT("HotKeyActive"), HCF_HOTKEYACTIVE,
|
||
|
TEXT("ConfirmHotKey"), HCF_CONFIRMHOTKEY,
|
||
|
TEXT("HotKeySound"), HCF_HOTKEYSOUND,
|
||
|
TEXT("ShowStatusIndicator"), HCF_INDICATOR,
|
||
|
TEXT("HotKeyAvailable"), HCF_HOTKEYAVAILABLE,
|
||
|
TEXT("OnOffFeedback"), 0,
|
||
|
NULL
|
||
|
};
|
||
|
|
||
|
|
||
|
ACCESSIBILITY_MAPPINGS g_AccessibilityMappings[] = {
|
||
|
{g_FilterKeys, TEXT("KeyboardResponse"), TEXT("Keyboard Response")},
|
||
|
{g_MouseKeys, TEXT("MouseKeys")},
|
||
|
{g_StickyKeys, TEXT("StickyKeys")},
|
||
|
{g_SoundSentry, TEXT("SoundSentry")},
|
||
|
{g_TimeOut, TEXT("TimeOut")},
|
||
|
{g_ToggleKeys, TEXT("ToggleKeys")},
|
||
|
{g_HighContrast, TEXT("HighContrast")},
|
||
|
{NULL}
|
||
|
};
|
||
|
|
||
|
|
||
|
//
|
||
|
// Macro expansion list
|
||
|
//
|
||
|
|
||
|
// none
|
||
|
|
||
|
//
|
||
|
// Private function prototypes
|
||
|
//
|
||
|
|
||
|
// none
|
||
|
|
||
|
//
|
||
|
// Macro expansion definition
|
||
|
//
|
||
|
|
||
|
// none
|
||
|
|
||
|
//
|
||
|
// Private prototypes
|
||
|
//
|
||
|
|
||
|
ETMINITIALIZE AccessibilityEtmInitialize;
|
||
|
MIG_PHYSICALENUMADD EmulatedEnumCallback;
|
||
|
MIG_PHYSICALACQUIREHOOK AcquireAccessibilityFlags;
|
||
|
MIG_PHYSICALACQUIREFREE ReleaseAccessibilityFlags;
|
||
|
|
||
|
//
|
||
|
// Code
|
||
|
//
|
||
|
|
||
|
VOID
|
||
|
pProhibit9xSetting (
|
||
|
IN PCTSTR Key,
|
||
|
IN PCTSTR ValueName OPTIONAL
|
||
|
)
|
||
|
{
|
||
|
MIG_OBJECTSTRINGHANDLE handle;
|
||
|
|
||
|
handle = IsmCreateObjectHandle (Key, ValueName);
|
||
|
MYASSERT (handle);
|
||
|
|
||
|
IsmProhibitPhysicalEnum (g_RegistryTypeId, handle, NULL, 0, NULL);
|
||
|
HtAddString (g_ProhibitTable, handle);
|
||
|
|
||
|
IsmDestroyObjectHandle (handle);
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
pStoreEmulatedSetting (
|
||
|
IN PCTSTR Key,
|
||
|
IN PCTSTR ValueName, OPTIONAL
|
||
|
IN DWORD Type,
|
||
|
IN PBYTE ValueData,
|
||
|
IN UINT ValueDataSize
|
||
|
)
|
||
|
{
|
||
|
MIG_OBJECTSTRINGHANDLE handle;
|
||
|
PCTSTR memdbNode;
|
||
|
BOOL stored = FALSE;
|
||
|
|
||
|
handle = IsmCreateObjectHandle (Key, ValueName);
|
||
|
memdbNode = JoinPaths (TEXT("~Accessibility"), handle);
|
||
|
IsmDestroyObjectHandle (handle);
|
||
|
|
||
|
if (MemDbAddKey (memdbNode)) {
|
||
|
if (ValueData) {
|
||
|
stored = (MemDbSetValue (memdbNode, Type) != 0);
|
||
|
stored &= (MemDbSetUnorderedBlob (memdbNode, 0, ValueData, ValueDataSize) != 0);
|
||
|
} else {
|
||
|
stored = TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
FreePathString (memdbNode);
|
||
|
|
||
|
return stored;
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
pMoveAccessibilityValue (
|
||
|
IN PCTSTR Win9xKey,
|
||
|
IN PCTSTR Win9xValue,
|
||
|
IN PCTSTR NtKey,
|
||
|
IN PCTSTR NtValue,
|
||
|
IN BOOL ForceDword
|
||
|
)
|
||
|
{
|
||
|
HKEY key;
|
||
|
PBYTE data = NULL;
|
||
|
PBYTE storeData;
|
||
|
DWORD conversionDword;
|
||
|
DWORD valueType;
|
||
|
DWORD valueSize;
|
||
|
MIG_OBJECTSTRINGHANDLE handle;
|
||
|
BOOL prohibited;
|
||
|
|
||
|
handle = IsmCreateObjectHandle (Win9xKey, Win9xValue);
|
||
|
prohibited = (HtFindString (g_ProhibitTable, handle) != NULL);
|
||
|
IsmDestroyObjectHandle (handle);
|
||
|
|
||
|
if (prohibited) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
key = OpenRegKeyStr (Win9xKey);
|
||
|
if (!key) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
__try {
|
||
|
if (!GetRegValueTypeAndSize (key, Win9xValue, &valueType, &valueSize)) {
|
||
|
__leave;
|
||
|
}
|
||
|
|
||
|
if (valueType != REG_SZ && valueType != REG_DWORD) {
|
||
|
__leave;
|
||
|
}
|
||
|
|
||
|
data = GetRegValueData (key, Win9xValue);
|
||
|
if (!data) {
|
||
|
__leave;
|
||
|
}
|
||
|
|
||
|
if (ForceDword && valueType == REG_SZ) {
|
||
|
storeData = (PBYTE) &conversionDword;
|
||
|
conversionDword = _ttoi ((PCTSTR) data);
|
||
|
valueType = REG_DWORD;
|
||
|
valueSize = sizeof (DWORD);
|
||
|
} else {
|
||
|
storeData = data;
|
||
|
}
|
||
|
|
||
|
if (pStoreEmulatedSetting (NtKey, NtValue, valueType, storeData, valueSize)) {
|
||
|
pProhibit9xSetting (Win9xKey, Win9xValue);
|
||
|
}
|
||
|
}
|
||
|
__finally {
|
||
|
CloseRegKey (key);
|
||
|
|
||
|
if (data) {
|
||
|
FreeAlloc (data);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
pMoveAccessibilityKey (
|
||
|
IN PCTSTR Win9xKey,
|
||
|
IN PCTSTR NtKey
|
||
|
)
|
||
|
{
|
||
|
HKEY key;
|
||
|
PBYTE data = NULL;
|
||
|
DWORD valueType;
|
||
|
DWORD valueSize;
|
||
|
LONG rc;
|
||
|
DWORD index = 0;
|
||
|
TCHAR valueName[MAX_REGISTRY_KEY];
|
||
|
DWORD valueNameSize;
|
||
|
GROWBUFFER value = INIT_GROWBUFFER;
|
||
|
MIG_OBJECTSTRINGHANDLE handle;
|
||
|
BOOL prohibited;
|
||
|
|
||
|
key = OpenRegKeyStr (Win9xKey);
|
||
|
if (!key) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
__try {
|
||
|
for (;;) {
|
||
|
|
||
|
valueNameSize = ARRAYSIZE(valueName);
|
||
|
valueSize = 0;
|
||
|
rc = RegEnumValue (key, index, valueName, &valueNameSize, NULL, &valueType, NULL, &valueSize);
|
||
|
|
||
|
if (rc != ERROR_SUCCESS) {
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
handle = IsmCreateObjectHandle (Win9xKey, valueName);
|
||
|
prohibited = (HtFindString (g_ProhibitTable, handle) != NULL);
|
||
|
IsmDestroyObjectHandle (handle);
|
||
|
|
||
|
if (!prohibited) {
|
||
|
|
||
|
value.End = 0;
|
||
|
data = GbGrow (&value, valueSize);
|
||
|
|
||
|
valueNameSize = ARRAYSIZE(valueName);
|
||
|
rc = RegEnumValue (key, index, valueName, &valueNameSize, NULL, &valueType, value.Buf, &valueSize);
|
||
|
|
||
|
if (rc != ERROR_SUCCESS) {
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (pStoreEmulatedSetting (NtKey, valueName, valueType, data, valueSize)) {
|
||
|
pProhibit9xSetting (Win9xKey, valueName);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
index++;
|
||
|
}
|
||
|
|
||
|
if (pStoreEmulatedSetting (NtKey, NULL, 0, NULL, 0)) {
|
||
|
pProhibit9xSetting (Win9xKey, NULL);
|
||
|
}
|
||
|
}
|
||
|
__finally {
|
||
|
CloseRegKey (key);
|
||
|
|
||
|
GbFree (&value);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
pTranslateAccessibilityKey (
|
||
|
IN PCTSTR Win9xSubKey,
|
||
|
IN PCTSTR NtSubKey,
|
||
|
IN PACCESS_OPTION AccessibilityMap
|
||
|
)
|
||
|
{
|
||
|
TCHAR full9xKey[MAX_REGISTRY_KEY];
|
||
|
TCHAR fullNtKey[MAX_REGISTRY_KEY];
|
||
|
MIG_OBJECTSTRINGHANDLE handle = NULL;
|
||
|
HKEY key = NULL;
|
||
|
PCTSTR data;
|
||
|
DWORD flags = 0;
|
||
|
DWORD thisFlag;
|
||
|
BOOL enabled;
|
||
|
TCHAR buffer[32];
|
||
|
|
||
|
__try {
|
||
|
StringCopy (full9xKey, S_ACCESSIBILITY_ROOT TEXT("\\"));
|
||
|
StringCopy (fullNtKey, full9xKey);
|
||
|
StringCat (full9xKey, Win9xSubKey);
|
||
|
StringCat (fullNtKey, NtSubKey);
|
||
|
|
||
|
key = OpenRegKeyStr (full9xKey);
|
||
|
if (!key) {
|
||
|
__leave;
|
||
|
}
|
||
|
|
||
|
while (AccessibilityMap->ValueName) {
|
||
|
//
|
||
|
// Prohibit enum of this value
|
||
|
//
|
||
|
|
||
|
handle = IsmCreateObjectHandle (full9xKey, AccessibilityMap->ValueName);
|
||
|
MYASSERT (handle);
|
||
|
|
||
|
IsmProhibitPhysicalEnum (g_RegistryTypeId, handle, NULL, 0, NULL);
|
||
|
HtAddString (g_ProhibitTable, handle);
|
||
|
|
||
|
IsmDestroyObjectHandle (handle);
|
||
|
handle = NULL;
|
||
|
|
||
|
//
|
||
|
// Update the emulated flags
|
||
|
//
|
||
|
|
||
|
data = GetRegValueString (key, AccessibilityMap->ValueName);
|
||
|
if (data) {
|
||
|
|
||
|
enabled = (_ttoi (data) != 0);
|
||
|
thisFlag = (AccessibilityMap->FlagVal & (~SPECIAL_INVERT_OPTION));
|
||
|
|
||
|
if (AccessibilityMap->FlagVal & SPECIAL_INVERT_OPTION) {
|
||
|
enabled = !enabled;
|
||
|
}
|
||
|
|
||
|
if (enabled) {
|
||
|
flags |= thisFlag;
|
||
|
}
|
||
|
|
||
|
FreeAlloc (data);
|
||
|
}
|
||
|
|
||
|
AccessibilityMap++;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Put the emulated value in the hash table
|
||
|
//
|
||
|
|
||
|
wsprintf (buffer, TEXT("%u"), flags);
|
||
|
pStoreEmulatedSetting (fullNtKey, TEXT("Flags"), REG_SZ, (PBYTE) buffer, SizeOfString (buffer));
|
||
|
}
|
||
|
__finally {
|
||
|
if (key) {
|
||
|
CloseRegKey (key);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
pFillTranslationTable (
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
PACCESSIBILITY_MAPPINGS mappings;
|
||
|
|
||
|
//
|
||
|
// Loop through all flags that need translation. Disable enumeration of
|
||
|
// the Win9x physical values and enable enumeration of the translated values
|
||
|
// via population of the hash table.
|
||
|
//
|
||
|
|
||
|
mappings = g_AccessibilityMappings;
|
||
|
|
||
|
while (mappings->AccessibilityMap) {
|
||
|
|
||
|
pTranslateAccessibilityKey (
|
||
|
mappings->Win9xSubKey,
|
||
|
mappings->NtSubKey ? mappings->NtSubKey : mappings->Win9xSubKey,
|
||
|
mappings->AccessibilityMap
|
||
|
);
|
||
|
|
||
|
mappings++;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Add all keys that have moved, ordered from most specific to least specific
|
||
|
//
|
||
|
|
||
|
// AutoRepeat values are transposed
|
||
|
pMoveAccessibilityValue (
|
||
|
S_ACCESSIBILITY_ROOT TEXT("\\KeyboardResponse"), TEXT("AutoRepeatDelay"),
|
||
|
S_ACCESSIBILITY_ROOT TEXT("\\Keyboard Response"), TEXT("AutoRepeatRate"),
|
||
|
FALSE
|
||
|
);
|
||
|
|
||
|
pMoveAccessibilityValue (
|
||
|
S_ACCESSIBILITY_ROOT TEXT("\\KeyboardResponse"), TEXT("AutoRepeatRate"),
|
||
|
S_ACCESSIBILITY_ROOT TEXT("\\Keyboard Response"), TEXT("AutoRepeatDelay"),
|
||
|
FALSE
|
||
|
);
|
||
|
|
||
|
// double c in DelayBeforeAcceptance value name
|
||
|
pMoveAccessibilityValue (
|
||
|
S_ACCESSIBILITY_ROOT TEXT("\\KeyboardResponse"), TEXT("DelayBeforeAcceptancce"),
|
||
|
S_ACCESSIBILITY_ROOT TEXT("\\Keyboard Response"), TEXT("DelayBeforeAcceptance"),
|
||
|
FALSE
|
||
|
);
|
||
|
|
||
|
// add a space to the key name for the rest of the values
|
||
|
pMoveAccessibilityKey (
|
||
|
S_ACCESSIBILITY_ROOT TEXT("\\KeyboardResponse"),
|
||
|
S_ACCESSIBILITY_ROOT TEXT("\\Keyboard Response")
|
||
|
);
|
||
|
|
||
|
// change BaudRate to Baud & convert to DWORD
|
||
|
pMoveAccessibilityValue (
|
||
|
S_ACCESSIBILITY_ROOT TEXT("\\SerialKeys"), TEXT("BaudRate"),
|
||
|
S_ACCESSIBILITY_ROOT TEXT("\\SerialKeys"), TEXT("Baud"),
|
||
|
TRUE
|
||
|
);
|
||
|
|
||
|
// convert Flags to DWORD
|
||
|
pMoveAccessibilityValue (
|
||
|
S_ACCESSIBILITY_ROOT TEXT("\\SerialKeys"), TEXT("Flags"),
|
||
|
S_ACCESSIBILITY_ROOT TEXT("\\SerialKeys"), TEXT("Flags"),
|
||
|
TRUE
|
||
|
);
|
||
|
|
||
|
// add space between high and contrast
|
||
|
pMoveAccessibilityValue (
|
||
|
S_ACCESSIBILITY_ROOT TEXT("\\HighContrast"), TEXT("Pre-HighContrast Scheme"),
|
||
|
S_ACCESSIBILITY_ROOT TEXT("\\HighContrast"), TEXT("Pre-High Contrast Scheme"),
|
||
|
FALSE
|
||
|
);
|
||
|
|
||
|
// move two values from the root into their own subkeys
|
||
|
pMoveAccessibilityValue (
|
||
|
S_ACCESSIBILITY_ROOT, TEXT("Blind Access"),
|
||
|
S_ACCESSIBILITY_ROOT TEXT("\\Blind Access"), TEXT("On"),
|
||
|
FALSE
|
||
|
);
|
||
|
|
||
|
pStoreEmulatedSetting (S_ACCESSIBILITY_ROOT TEXT("\\Blind Access"), NULL, 0, NULL, 0);
|
||
|
|
||
|
pMoveAccessibilityValue (
|
||
|
S_ACCESSIBILITY_ROOT, TEXT("Keyboard Preference"),
|
||
|
S_ACCESSIBILITY_ROOT TEXT("\\Keyboard Preference"), TEXT("On"),
|
||
|
FALSE
|
||
|
);
|
||
|
|
||
|
pStoreEmulatedSetting (S_ACCESSIBILITY_ROOT TEXT("\\Keyboard Preference"), NULL, 0, NULL, 0);
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
WINAPI
|
||
|
AccessibilityEtmInitialize (
|
||
|
IN MIG_PLATFORMTYPEID Platform,
|
||
|
IN PMIG_LOGCALLBACK LogCallback,
|
||
|
IN PVOID Reserved
|
||
|
)
|
||
|
{
|
||
|
MIG_OBJECTSTRINGHANDLE objectName;
|
||
|
BOOL b = TRUE;
|
||
|
|
||
|
LogReInit (NULL, NULL, NULL, (PLOGCALLBACK) LogCallback);
|
||
|
|
||
|
if (ISWIN9X()) {
|
||
|
g_RegistryTypeId = IsmGetObjectTypeId (S_REGISTRYTYPE);
|
||
|
MYASSERT (g_RegistryTypeId);
|
||
|
|
||
|
g_ProhibitTable = HtAlloc();
|
||
|
MYASSERT (g_ProhibitTable);
|
||
|
|
||
|
if (g_RegistryTypeId) {
|
||
|
//
|
||
|
// Add a callback for additional enumeration. If we are unable to do so, then
|
||
|
// someone else is already doing something different for this key.
|
||
|
//
|
||
|
|
||
|
objectName = IsmCreateObjectHandle (S_ACCESSIBILITY_ROOT, NULL);
|
||
|
|
||
|
b = IsmAddToPhysicalEnum (g_RegistryTypeId, objectName, EmulatedEnumCallback, 0);
|
||
|
|
||
|
IsmDestroyObjectHandle (objectName);
|
||
|
|
||
|
if (b) {
|
||
|
//
|
||
|
// Add a callback to acquire the data of the new physical objects
|
||
|
//
|
||
|
|
||
|
objectName = IsmCreateSimpleObjectPattern (
|
||
|
S_ACCESSIBILITY_ROOT,
|
||
|
TRUE,
|
||
|
NULL,
|
||
|
TRUE
|
||
|
);
|
||
|
|
||
|
b = IsmRegisterPhysicalAcquireHook (
|
||
|
g_RegistryTypeId,
|
||
|
objectName,
|
||
|
AcquireAccessibilityFlags,
|
||
|
ReleaseAccessibilityFlags,
|
||
|
0,
|
||
|
NULL
|
||
|
);
|
||
|
|
||
|
IsmDestroyObjectHandle (objectName);
|
||
|
}
|
||
|
|
||
|
if (b) {
|
||
|
|
||
|
//
|
||
|
// Now load memdb with the current registry values and
|
||
|
// prohibit the enumeration of Win9x values.
|
||
|
//
|
||
|
|
||
|
pFillTranslationTable ();
|
||
|
}
|
||
|
ELSE_DEBUGMSG ((DBG_WARNING, "Not allowed to translate accessibility key"));
|
||
|
}
|
||
|
|
||
|
HtFree (g_ProhibitTable);
|
||
|
g_ProhibitTable = NULL;
|
||
|
}
|
||
|
|
||
|
return b;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
WINAPI
|
||
|
EmulatedEnumCallback (
|
||
|
IN OUT PMIG_TYPEOBJECTENUM ObjectEnum,
|
||
|
IN MIG_OBJECTSTRINGHANDLE Pattern,
|
||
|
IN MIG_PARSEDPATTERN ParsedPattern,
|
||
|
IN ULONG_PTR Arg,
|
||
|
IN BOOL Abort
|
||
|
)
|
||
|
{
|
||
|
PACCESSIBILITY_ENUM_STATE state = (PACCESSIBILITY_ENUM_STATE) ObjectEnum->EtmHandle;
|
||
|
BOOL result = FALSE;
|
||
|
BOOL cleanUpMemdb = TRUE;
|
||
|
PCTSTR p;
|
||
|
|
||
|
for (;;) {
|
||
|
|
||
|
if (!Abort) {
|
||
|
|
||
|
//
|
||
|
// Begin or continue? If the EtmHandle is NULL, begin. Otherwise, continue.
|
||
|
//
|
||
|
|
||
|
if (!state) {
|
||
|
state = (PACCESSIBILITY_ENUM_STATE) MemAllocUninit (sizeof (ACCESSIBILITY_ENUM_STATE));
|
||
|
if (!state) {
|
||
|
MYASSERT (FALSE);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
ObjectEnum->EtmHandle = (LONG_PTR) state;
|
||
|
|
||
|
result = MemDbEnumFirst (
|
||
|
&state->EnumStruct,
|
||
|
TEXT("~Accessibility\\*"),
|
||
|
ENUMFLAG_NORMAL,
|
||
|
1,
|
||
|
MEMDB_LAST_LEVEL
|
||
|
);
|
||
|
|
||
|
} else {
|
||
|
result = MemDbEnumNext (&state->EnumStruct);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// If an item was found, populate the enum struct. Otherwise, set
|
||
|
// Abort to TRUE to clean up.
|
||
|
//
|
||
|
|
||
|
if (result) {
|
||
|
//
|
||
|
// Test against pattern
|
||
|
//
|
||
|
|
||
|
if (!IsmParsedPatternMatch (ParsedPattern, 0, state->EnumStruct.KeyName)) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
MYASSERT ((ObjectEnum->ObjectTypeId & (~PLATFORM_MASK)) == g_RegistryTypeId);
|
||
|
|
||
|
ObjectEnum->ObjectName = state->EnumStruct.KeyName;
|
||
|
state->RegType = state->EnumStruct.Value;
|
||
|
|
||
|
//
|
||
|
// Fill in node, leaf and details
|
||
|
//
|
||
|
|
||
|
IsmDestroyObjectString (ObjectEnum->ObjectNode);
|
||
|
IsmDestroyObjectString (ObjectEnum->ObjectLeaf);
|
||
|
IsmReleaseMemory (ObjectEnum->NativeObjectName);
|
||
|
|
||
|
IsmCreateObjectStringsFromHandle (
|
||
|
ObjectEnum->ObjectName,
|
||
|
&ObjectEnum->ObjectNode,
|
||
|
&ObjectEnum->ObjectLeaf
|
||
|
);
|
||
|
|
||
|
MYASSERT (ObjectEnum->ObjectNode);
|
||
|
|
||
|
ObjectEnum->Level = 0;
|
||
|
|
||
|
p = _tcschr (ObjectEnum->ObjectNode, TEXT('\\'));
|
||
|
while (p) {
|
||
|
ObjectEnum->Level++;
|
||
|
p = _tcschr (p + 1, TEXT('\\'));
|
||
|
}
|
||
|
|
||
|
ObjectEnum->SubLevel = 0;
|
||
|
|
||
|
if (ObjectEnum->ObjectLeaf) {
|
||
|
ObjectEnum->IsNode = FALSE;
|
||
|
ObjectEnum->IsLeaf = TRUE;
|
||
|
} else {
|
||
|
ObjectEnum->IsNode = TRUE;
|
||
|
ObjectEnum->IsLeaf = FALSE;
|
||
|
}
|
||
|
|
||
|
if (state->RegType) {
|
||
|
ObjectEnum->Details.DetailsSize = sizeof (state->RegType);
|
||
|
ObjectEnum->Details.DetailsData = &state->RegType;
|
||
|
} else {
|
||
|
ObjectEnum->Details.DetailsSize = 0;
|
||
|
ObjectEnum->Details.DetailsData = NULL;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Rely on base type to get the native object name
|
||
|
//
|
||
|
|
||
|
ObjectEnum->NativeObjectName = IsmGetNativeObjectName (
|
||
|
ObjectEnum->ObjectTypeId,
|
||
|
ObjectEnum->ObjectName
|
||
|
);
|
||
|
|
||
|
|
||
|
} else {
|
||
|
Abort = TRUE;
|
||
|
cleanUpMemdb = FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (Abort) {
|
||
|
//
|
||
|
// Clean up our enum struct
|
||
|
//
|
||
|
|
||
|
if (state) {
|
||
|
if (cleanUpMemdb) {
|
||
|
MemDbAbortEnum (&state->EnumStruct);
|
||
|
}
|
||
|
|
||
|
IsmDestroyObjectString (ObjectEnum->ObjectNode);
|
||
|
ObjectEnum->ObjectNode = NULL;
|
||
|
IsmDestroyObjectString (ObjectEnum->ObjectLeaf);
|
||
|
ObjectEnum->ObjectLeaf = NULL;
|
||
|
IsmReleaseMemory (ObjectEnum->NativeObjectName);
|
||
|
ObjectEnum->NativeObjectName = NULL;
|
||
|
FreeAlloc (state);
|
||
|
}
|
||
|
|
||
|
// return value ignored in Abort case, and ObjectEnum is zeroed by the ISM
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
WINAPI
|
||
|
AcquireAccessibilityFlags(
|
||
|
IN MIG_OBJECTSTRINGHANDLE ObjectName,
|
||
|
IN PMIG_CONTENT ObjectContent,
|
||
|
IN MIG_CONTENTTYPE ContentType,
|
||
|
IN UINT MemoryContentLimit,
|
||
|
OUT PMIG_CONTENT *NewObjectContent, CALLER_INITIALIZED OPTIONAL
|
||
|
IN BOOL ReleaseContent,
|
||
|
IN ULONG_PTR Arg
|
||
|
)
|
||
|
{
|
||
|
BOOL result = TRUE;
|
||
|
PDWORD details;
|
||
|
PMIG_CONTENT ourContent;
|
||
|
PCTSTR memdbNode;
|
||
|
|
||
|
//
|
||
|
// Is this object in our hash table?
|
||
|
//
|
||
|
|
||
|
if (ContentType == CONTENTTYPE_FILE) {
|
||
|
DEBUGMSG ((DBG_ERROR, "Accessibility content cannot be saved to a file"));
|
||
|
result = FALSE;
|
||
|
} else {
|
||
|
|
||
|
memdbNode = JoinPaths (TEXT("~Accessibility"), ObjectName);
|
||
|
|
||
|
if (MemDbTestKey (memdbNode)) {
|
||
|
|
||
|
//
|
||
|
// Alloc updated content struct
|
||
|
//
|
||
|
|
||
|
ourContent = MemAllocZeroed (sizeof (MIG_CONTENT) + sizeof (DWORD));
|
||
|
ourContent->EtmHandle = ourContent;
|
||
|
details = (PDWORD) (ourContent + 1);
|
||
|
|
||
|
//
|
||
|
// Get the content from memdb
|
||
|
//
|
||
|
|
||
|
ourContent->MemoryContent.ContentBytes = MemDbGetUnorderedBlob (
|
||
|
memdbNode,
|
||
|
0,
|
||
|
&ourContent->MemoryContent.ContentSize
|
||
|
);
|
||
|
|
||
|
if (ourContent->MemoryContent.ContentBytes) {
|
||
|
MemDbGetValue (memdbNode, details);
|
||
|
|
||
|
ourContent->Details.DetailsSize = sizeof (DWORD);
|
||
|
ourContent->Details.DetailsData = details;
|
||
|
|
||
|
} else {
|
||
|
ourContent->MemoryContent.ContentSize = 0;
|
||
|
|
||
|
ourContent->Details.DetailsSize = 0;
|
||
|
ourContent->Details.DetailsData = NULL;
|
||
|
}
|
||
|
|
||
|
ourContent->ContentInFile = FALSE;
|
||
|
|
||
|
//
|
||
|
// Pass it to ISM
|
||
|
//
|
||
|
|
||
|
*NewObjectContent = ourContent;
|
||
|
|
||
|
}
|
||
|
|
||
|
FreePathString (memdbNode);
|
||
|
}
|
||
|
|
||
|
return result; // always TRUE unless an error occurred
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
WINAPI
|
||
|
ReleaseAccessibilityFlags(
|
||
|
IN PMIG_CONTENT ObjectContent
|
||
|
)
|
||
|
{
|
||
|
//
|
||
|
// This callback is called to free the content we allocated above.
|
||
|
//
|
||
|
|
||
|
if (ObjectContent->MemoryContent.ContentBytes) {
|
||
|
MemDbReleaseMemory (ObjectContent->MemoryContent.ContentBytes);
|
||
|
}
|
||
|
|
||
|
FreeAlloc ((PMIG_CONTENT) ObjectContent->EtmHandle);
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
WINAPI
|
||
|
AccessibilitySourceInitialize (
|
||
|
IN PMIG_LOGCALLBACK LogCallback,
|
||
|
IN PVOID Reserved
|
||
|
)
|
||
|
{
|
||
|
LogReInit (NULL, NULL, NULL, (PLOGCALLBACK) LogCallback);
|
||
|
|
||
|
if (!g_RegistryTypeId) {
|
||
|
g_RegistryTypeId = IsmGetObjectTypeId (S_REGISTRYTYPE);
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|