Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/windows/native/sun/bridge/jabswitch.cpp
32287 views
/*1* Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425#include <stdio.h>26#include <string.h>27#include <stdlib.h>28#include <ctype.h>29#include <Windows.h>30#include <tchar.h>3132// This is the default buffer size used for RegQueryValue values.33#define DEFAULT_ALLOC MAX_PATH34// only allocate a buffer as big as MAX_ALLOC for RegQueryValue values.35#define MAX_ALLOC 2621443637static LPCTSTR ACCESSIBILITY_USER_KEY =38_T("Software\\Microsoft\\Windows NT\\CurrentVersion\\Accessibility");39static LPCTSTR ACCESSIBILITY_SYSTEM_KEY =40_T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Accessibility\\Session");41static LPCTSTR ACCESSIBILITY_CONFIG =42_T("Configuration");43static LPCTSTR STR_ACCESSBRIDGE =44_T("oracle_javaaccessbridge");4546// Note: There are senarios where more than one extension can be specified on the47// asssistive_technologies=48// line but this code only deals with the case of49// assistive_technologies=com.sun.java.accessibility.AccessBridge50// assuming that if additional extensions are desired the user knows how edit the file.5152FILE* origFile;53FILE* tempFile;5455bool isXP()56{57static bool isXPFlag = false;58OSVERSIONINFO osvi;5960// Initialize the OSVERSIONINFO structure.61ZeroMemory( &osvi, sizeof( osvi ) );62osvi.dwOSVersionInfoSize = sizeof( osvi );6364GetVersionEx( &osvi );6566if ( osvi.dwMajorVersion == 5 ) // For Windows XP and Windows 200067isXPFlag = true;6869return isXPFlag ;70}7172void enableJAB() {73// Copy lines from orig to temp modifying the line containing74// assistive_technologies=75// There are various scenarios:76// 1) If the line exists exactly as77// #assistive_technologies=com.sun.java.accessibility.AccessBridge78// replace it with79// assistive_technologies=com.sun.java.accessibility.AccessBridge80// 2) else if the line exists exactly as81// assistive_technologies=com.sun.java.accessibility.AccessBridge82// use it as is83// 3) else if a line containing "assistive_technologies" exits84// a) if it's already commented out, us it as is (jab will be enabled in step 4)85// b) else if it's not commented out, comment it out and add a new line with86// assistive_technologies=com.sun.java.accessibility.AccessBridge87// 4) If the line doesn't exist (or case 3a), add88// assistive_technologies=com.sun.java.accessibility.AccessBridge89// Do the same for screen_magnifier_present=90char line[512];91char commentLine[512] = "#";92char jabLine[] = "assistive_technologies=com.sun.java.accessibility.AccessBridge\n";93char magLine[] = "screen_magnifier_present=true\n";94bool foundJabLine = false;95bool foundMagLine = false;96while (!feof(origFile)) {97if (fgets(line, 512, origFile) != NULL) {98if (_stricmp(line, "#assistive_technologies=com.sun.java.accessibility.AccessBridge\n") == 0) {99fputs(jabLine, tempFile);100foundJabLine = true;101} else if (_stricmp(line, jabLine) == 0) {102fputs(line, tempFile);103foundJabLine = true;104} else if (strstr(line, "assistive_technologies") != NULL) {105char* context;106char* firstNonSpaceChar = strtok_s(line, " ", &context);107if (*firstNonSpaceChar == '#') {108fputs(line, tempFile);109} else {110strcat_s(commentLine, line);111fputs(commentLine, tempFile);112fputs(jabLine, tempFile);113foundJabLine = true;114}115} else if (_stricmp(line, "#screen_magnifier_present=true\n") == 0) {116fputs(magLine, tempFile);117foundMagLine = true;118} else if (_stricmp(line, magLine) == 0) {119fputs(line, tempFile);120foundMagLine = true;121} else if (strstr(line, "screen_magnifier_present") != NULL) {122char* context;123char* firstNonSpaceChar = strtok_s(line, " ", &context);124if (*firstNonSpaceChar == '#') {125fputs(line, tempFile);126} else {127strcat_s(commentLine, line);128fputs(commentLine, tempFile);129fputs(magLine, tempFile);130foundMagLine = true;131}132} else {133fputs(line, tempFile);134}135}136}137if (!foundJabLine) {138fputs(jabLine, tempFile);139}140if (!foundMagLine) {141fputs(magLine, tempFile);142}143}144145void disableJAB() {146// Copy lines from orig to temp modifying the line containing147// assistive_technologies=148// There are various scenarios:149// 1) If the uncommented line exists, comment it out150// 2) If the line exists but is preceeded by a #, nothing to do151// 3) If the line doesn't exist, nothing to do152// Do the same for screen_magnifier_present=153char line[512];154char commentLine[512];155while (!feof(origFile)) {156if (fgets(line, 512, origFile) != NULL) {157if (strstr(line, "assistive_technologies") != NULL) {158char* context;159char* firstNonSpaceChar = strtok_s(line, " ", &context);160if (*firstNonSpaceChar != '#') {161strcpy_s(commentLine, "#");162strcat_s(commentLine, line);163fputs(commentLine, tempFile);164} else {165fputs(line, tempFile);166}167} else if (strstr(line, "screen_magnifier_present") != NULL) {168char* context;169char* firstNonSpaceChar = strtok_s(line, " ", &context);170if (*firstNonSpaceChar != '#') {171strcpy_s(commentLine, "#");172strcat_s(commentLine, line);173fputs(commentLine, tempFile);174} else {175fputs(line, tempFile);176}177} else {178fputs(line, tempFile);179}180}181}182}183184int modify(bool enable) {185errno_t error = 0;186char path[_MAX_PATH];187char tempPath[_MAX_PATH];188// Get the path for %USERPROFILE%189char *profilePath;190size_t len;191error = _dupenv_s(&profilePath, &len, "USERPROFILE" );192if (error) {193printf("Error fetching USERPROFILE.\n");194perror("Error");195return error;196}197const char acc_props1[] = "\\.accessibility.properties";198const char acc_props2[] = "\\.acce$$ibility.properties";199// len must be 234 or less (233 characters)200// sizeof(path) is 260 (room for 259 characters)201// sizeof(acc_props1) is 27 (26 characters)202// path will hold 233 path characters plus 26 file characters plus 1 null character)203// if len - 1 > 233 then error204if ( len - 1 > sizeof(path) - sizeof(acc_props1) ||205len - 1 > sizeof(tempPath) - sizeof(acc_props2) ) {206printf("The USERPROFILE environment variable is too long.\n");207printf("It must be no longer than 233 characters.\n");208return 123;209}210path[0] = 0;211strcat_s(path, _MAX_PATH, profilePath);212strcat_s(path, acc_props1);213tempPath[0] = 0;214strcat_s(tempPath, _MAX_PATH, profilePath);215strcat_s(tempPath, acc_props2);216free(profilePath);217profilePath = 0;218// Open the original file. If it doesn't exist and this is an enable request then create it.219error = fopen_s(&origFile, path, "r");220if (error) {221if (enable) {222error = fopen_s(&origFile, path, "w");223if (error) {224printf("Couldn't create file: %s\n", path);225perror("Error");226} else {227char str[100] = "assistive_technologies=com.sun.java.accessibility.AccessBridge\n";228strcat_s(str, "screen_magnifier_present=true\n");229fprintf(origFile, str);230fclose(origFile);231}232} else {233// It's OK if the file isn't there for a -disable234error = 0;235}236} else {237// open a temp file238error = fopen_s(&tempFile, tempPath, "w");239if (error) {240printf("Couldn't open temp file: %s\n", tempPath);241perror("Error");242return error;243}244if (enable) {245enableJAB();246} else {247disableJAB();248}249fclose(origFile);250fclose(tempFile);251// delete the orig file and rename the temp file252if (remove(path) != 0) {253printf("Couldn't remove file: %s\n", path);254perror("Error");255return errno;256}257if (rename(tempPath, path) != 0) {258printf("Couldn't rename %s to %s.\n", tempPath, path);259perror("Error");260return errno;261}262}263return error;264}265266void printUsage() {267printf("\njabswitch [/enable | /disable | /version | /?]\n\n");268printf("Description:\n");269printf(" jabswitch enables or disables the Java Access Bridge.\n\n");270printf("Parameters:\n");271printf(" /enable Enable the Java Accessibility Bridge.\n");272printf(" /disable Disable the Java Accessibility Bridge.\n");273printf(" /version Display the version.\n");274printf(" /? Display this usage information.\n");275printf("\nNote:\n");276printf(" The Java Access Bridge can also be enabled with the\n");277printf(" Windows Ease of Access control panel (which can be\n");278printf(" activated by pressing Windows + U). The Ease of Access\n");279printf(" control panel has a Java Access Bridge checkbox. Please\n");280printf(" be aware that unchecking the checkbox has no effect and\n");281printf(" in order to disable the Java Access Bridge you must run\n");282printf(" jabswitch.exe from the command line.\n");283}284285void printVersion() {286TCHAR executableFileName[_MAX_PATH];287if (!GetModuleFileName(0, executableFileName, _MAX_PATH)) {288printf("Unable to get executable file name.\n");289return;290}291DWORD nParam;292DWORD nVersionSize = GetFileVersionInfoSize(executableFileName, &nParam);293if (!nVersionSize) {294printf("Unable to get version info size.\n");295return;296}297char* pVersionData = new char[nVersionSize];298if (!GetFileVersionInfo(executableFileName, 0, nVersionSize, pVersionData)) {299printf("Unable to get version info.\n");300return;301}302LPVOID pVersionInfo;303UINT nSize;304if (!VerQueryValue(pVersionData, _T("\\"), &pVersionInfo, &nSize)) {305printf("Unable to query version value.\n");306return;307}308VS_FIXEDFILEINFO *pVSInfo = (VS_FIXEDFILEINFO *)pVersionInfo;309char versionString[100];310sprintf_s( versionString, "version %i.%i.%i.%i",311pVSInfo->dwProductVersionMS >> 16,312pVSInfo->dwProductVersionMS & 0xFFFF,313pVSInfo->dwProductVersionLS >> 16,314pVSInfo->dwProductVersionLS & 0xFFFF );315char outputString[100];316strcpy_s(outputString, "jabswitch ");317strcat_s(outputString, versionString);318strcat_s(outputString, "\njabswitch enables or disables the Java Access Bridge.\n");319printf(outputString);320}321322int regEnable() {323HKEY hKey;324DWORD retval = -1;325LSTATUS err;326err = RegOpenKeyEx(HKEY_CURRENT_USER, ACCESSIBILITY_USER_KEY, NULL, KEY_READ|KEY_WRITE, &hKey);327if (err == ERROR_SUCCESS) {328DWORD dataType = REG_SZ;329DWORD dataLength = DEFAULT_ALLOC;330TCHAR dataBuffer[DEFAULT_ALLOC];331TCHAR *data = dataBuffer;332bool freeData = false;333err = RegQueryValueEx(hKey, ACCESSIBILITY_CONFIG, 0, &dataType, (BYTE *)data, &dataLength);334if (err == ERROR_MORE_DATA) {335if (dataLength > 0 && dataLength < MAX_ALLOC) {336data = new TCHAR[dataLength];337err = RegQueryValueEx(hKey, ACCESSIBILITY_CONFIG, 0, &dataType, (BYTE *)data, &dataLength);338}339}340if (err == ERROR_SUCCESS) {341err = _tcslwr_s(dataBuffer, DEFAULT_ALLOC);342if (err) {343return -1;344}345if (_tcsstr(dataBuffer, STR_ACCESSBRIDGE) != NULL) {346return 0; // This is OK, e.g. ran enable twice and the value is there.347} else {348// add oracle_javaaccessbridge to Config key for HKCU349dataLength = dataLength + (_tcslen(STR_ACCESSBRIDGE) + 1) * sizeof(TCHAR);350TCHAR *newStr = new TCHAR[dataLength];351if (newStr != NULL) {352wsprintf(newStr, L"%s,%s", dataBuffer, STR_ACCESSBRIDGE);353RegSetValueEx(hKey, ACCESSIBILITY_CONFIG, 0, REG_SZ, (BYTE *)newStr, dataLength);354}355}356}357RegCloseKey(hKey);358}359return err;360}361362int regDeleteValue(HKEY hFamilyKey, LPCWSTR lpSubKey)363{364HKEY hKey;365DWORD retval = -1;366LSTATUS err;367err = RegOpenKeyEx(hFamilyKey, lpSubKey, NULL, KEY_READ|KEY_WRITE|KEY_WOW64_64KEY, &hKey);368if (err != ERROR_SUCCESS)369err = RegOpenKeyEx(hFamilyKey, lpSubKey, NULL, KEY_READ|KEY_WRITE, &hKey);370371if (err == ERROR_SUCCESS) {372DWORD dataType = REG_SZ;373DWORD dataLength = DEFAULT_ALLOC;374TCHAR dataBuffer[DEFAULT_ALLOC];375TCHAR searchBuffer[DEFAULT_ALLOC];376TCHAR *data = dataBuffer;377bool freeData = false;378err = RegQueryValueEx(hKey, ACCESSIBILITY_CONFIG, 0, &dataType, (BYTE *)data, &dataLength);379if (err == ERROR_MORE_DATA) {380if (dataLength > 0 && dataLength < MAX_ALLOC) {381data = new TCHAR[dataLength];382err = RegQueryValueEx(hKey, ACCESSIBILITY_CONFIG, 0, &dataType, (BYTE *)data, &dataLength);383}384}385if (err == ERROR_SUCCESS) {386err = _tcslwr_s(dataBuffer, DEFAULT_ALLOC);387if (err) {388return -1;389}390if (_tcsstr(dataBuffer, STR_ACCESSBRIDGE) == NULL) {391return 0; // This is OK, e.g. ran disable twice and the value is not there.392} else {393// remove oracle_javaaccessbridge from Config key394TCHAR *newStr = new TCHAR[dataLength];395TCHAR *nextToken;396LPTSTR tok, beg1 = dataBuffer;397bool first = true;398_tcscpy_s(newStr, dataLength, L"");399tok = _tcstok_s(beg1, L",", &nextToken);400while (tok != NULL) {401_tcscpy_s(searchBuffer, DEFAULT_ALLOC, tok);402err = _tcslwr_s(searchBuffer, DEFAULT_ALLOC);403if (err) {404return -1;405}406if (_tcsstr(searchBuffer, STR_ACCESSBRIDGE) == NULL) {407if (!first) {408_tcscat_s(newStr, dataLength, L",");409}410first = false;411_tcscat_s(newStr, dataLength, tok);412}413tok = _tcstok_s(NULL, L",", &nextToken);414}415dataLength = (_tcslen(newStr) + 1) * sizeof(TCHAR);416RegSetValueEx(hKey, ACCESSIBILITY_CONFIG, 0, REG_SZ, (BYTE *)newStr, dataLength);417}418}419RegCloseKey(hKey);420}421return err;422}423424int regDisable()425{426LSTATUS err;427// Update value for HKCU428err=regDeleteValue(HKEY_CURRENT_USER, ACCESSIBILITY_USER_KEY);429// Update value for HKLM for Session430TCHAR dataBuffer[DEFAULT_ALLOC];431DWORD dwSessionId ;432ProcessIdToSessionId(GetCurrentProcessId(),&dwSessionId ) ;433if( dwSessionId >= 0 )434{435wsprintf(dataBuffer, L"%s%d", ACCESSIBILITY_SYSTEM_KEY, dwSessionId);436err=regDeleteValue(HKEY_LOCAL_MACHINE, dataBuffer);437}438return err;439}440441void main(int argc, char* argv[]) {442bool enableWasRequested = false;443bool disableWasRequested = false;444bool badParams = true;445int error = 0;446if (argc == 2) {447if (_stricmp(argv[1], "-?") == 0 || _stricmp(argv[1], "/?") == 0) {448printUsage();449badParams = false;450} else if (_stricmp(argv[1], "-version") == 0 || _stricmp(argv[1], "/version") == 0) {451printVersion();452badParams = false;453} else {454if (_stricmp(argv[1], "-enable") == 0 || _stricmp(argv[1], "/enable") == 0) {455badParams = false;456enableWasRequested = true;457error = modify(true);458if (error == 0) {459if( !isXP() )460regEnable();461}462} else if (_stricmp(argv[1], "-disable") == 0 || _stricmp(argv[1], "/disable") == 0) {463badParams = false;464disableWasRequested = true;465error = modify(false);466if (error == 0) {467if( !isXP() )468regDisable();469}470}471}472}473if (badParams) {474printUsage();475} else if (enableWasRequested || disableWasRequested) {476if (error != 0) {477printf("There was an error.\n\n");478}479printf("The Java Access Bridge has ");480if (error != 0) {481printf("not ");482}483printf("been ");484if (enableWasRequested) {485printf("enabled.\n");486} else {487printf("disabled.\n");488}489// Use exit so test case can sense for error.490if (error != 0) {491exit(error);492}493}494}495496497