| /* |
| * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. Oracle designates this |
| * particular file as subject to the "Classpath" exception as provided |
| * by Oracle in the LICENSE file that accompanied this code. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| #include <stdio.h> |
| #include <string.h> |
| #include <stdlib.h> |
| #include <ctype.h> |
| #include <Windows.h> |
| #include <tchar.h> |
| |
| // This is the default buffer size used for RegQueryValue values. |
| #define DEFAULT_ALLOC MAX_PATH |
| // only allocate a buffer as big as MAX_ALLOC for RegQueryValue values. |
| #define MAX_ALLOC 262144 |
| |
| static LPCTSTR ACCESSIBILITY_USER_KEY = |
| _T("Software\\Microsoft\\Windows NT\\CurrentVersion\\Accessibility"); |
| static LPCTSTR ACCESSIBILITY_SYSTEM_KEY = |
| _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Accessibility\\Session"); |
| static LPCTSTR ACCESSIBILITY_CONFIG = |
| _T("Configuration"); |
| static LPCTSTR STR_ACCESSBRIDGE = |
| _T("oracle_javaaccessbridge"); |
| |
| // Note: There are senarios where more than one extension can be specified on the |
| // asssistive_technologies= |
| // line but this code only deals with the case of |
| // assistive_technologies=com.sun.java.accessibility.AccessBridge |
| // assuming that if additional extensions are desired the user knows how edit the file. |
| |
| FILE* origFile; |
| FILE* tempFile; |
| |
| bool isXP() |
| { |
| static bool isXPFlag = false; |
| OSVERSIONINFO osvi; |
| |
| // Initialize the OSVERSIONINFO structure. |
| ZeroMemory( &osvi, sizeof( osvi ) ); |
| osvi.dwOSVersionInfoSize = sizeof( osvi ); |
| |
| GetVersionEx( &osvi ); |
| |
| if ( osvi.dwMajorVersion == 5 ) // For Windows XP and Windows 2000 |
| isXPFlag = true; |
| |
| return isXPFlag ; |
| } |
| |
| void enableJAB() { |
| // Copy lines from orig to temp modifying the line containing |
| // assistive_technologies= |
| // There are various scenarios: |
| // 1) If the line exists exactly as |
| // #assistive_technologies=com.sun.java.accessibility.AccessBridge |
| // replace it with |
| // assistive_technologies=com.sun.java.accessibility.AccessBridge |
| // 2) else if the line exists exactly as |
| // assistive_technologies=com.sun.java.accessibility.AccessBridge |
| // use it as is |
| // 3) else if a line containing "assistive_technologies" exits |
| // a) if it's already commented out, us it as is (jab will be enabled in step 4) |
| // b) else if it's not commented out, comment it out and add a new line with |
| // assistive_technologies=com.sun.java.accessibility.AccessBridge |
| // 4) If the line doesn't exist (or case 3a), add |
| // assistive_technologies=com.sun.java.accessibility.AccessBridge |
| // Do the same for screen_magnifier_present= |
| char line[512]; |
| char commentLine[512] = "#"; |
| char jabLine[] = "assistive_technologies=com.sun.java.accessibility.AccessBridge\n"; |
| char magLine[] = "screen_magnifier_present=true\n"; |
| bool foundJabLine = false; |
| bool foundMagLine = false; |
| while (!feof(origFile)) { |
| if (fgets(line, 512, origFile) != NULL) { |
| if (_stricmp(line, "#assistive_technologies=com.sun.java.accessibility.AccessBridge\n") == 0) { |
| fputs(jabLine, tempFile); |
| foundJabLine = true; |
| } else if (_stricmp(line, jabLine) == 0) { |
| fputs(line, tempFile); |
| foundJabLine = true; |
| } else if (strstr(line, "assistive_technologies") != NULL) { |
| char* context; |
| char* firstNonSpaceChar = strtok_s(line, " ", &context); |
| if (*firstNonSpaceChar == '#') { |
| fputs(line, tempFile); |
| } else { |
| strcat_s(commentLine, line); |
| fputs(commentLine, tempFile); |
| fputs(jabLine, tempFile); |
| foundJabLine = true; |
| } |
| } else if (_stricmp(line, "#screen_magnifier_present=true\n") == 0) { |
| fputs(magLine, tempFile); |
| foundMagLine = true; |
| } else if (_stricmp(line, magLine) == 0) { |
| fputs(line, tempFile); |
| foundMagLine = true; |
| } else if (strstr(line, "screen_magnifier_present") != NULL) { |
| char* context; |
| char* firstNonSpaceChar = strtok_s(line, " ", &context); |
| if (*firstNonSpaceChar == '#') { |
| fputs(line, tempFile); |
| } else { |
| strcat_s(commentLine, line); |
| fputs(commentLine, tempFile); |
| fputs(magLine, tempFile); |
| foundMagLine = true; |
| } |
| } else { |
| fputs(line, tempFile); |
| } |
| } |
| } |
| if (!foundJabLine) { |
| fputs(jabLine, tempFile); |
| } |
| if (!foundMagLine) { |
| fputs(magLine, tempFile); |
| } |
| } |
| |
| void disableJAB() { |
| // Copy lines from orig to temp modifying the line containing |
| // assistive_technologies= |
| // There are various scenarios: |
| // 1) If the uncommented line exists, comment it out |
| // 2) If the line exists but is preceeded by a #, nothing to do |
| // 3) If the line doesn't exist, nothing to do |
| // Do the same for screen_magnifier_present= |
| char line[512]; |
| char commentLine[512]; |
| while (!feof(origFile)) { |
| if (fgets(line, 512, origFile) != NULL) { |
| if (strstr(line, "assistive_technologies") != NULL) { |
| char* context; |
| char* firstNonSpaceChar = strtok_s(line, " ", &context); |
| if (*firstNonSpaceChar != '#') { |
| strcpy_s(commentLine, "#"); |
| strcat_s(commentLine, line); |
| fputs(commentLine, tempFile); |
| } else { |
| fputs(line, tempFile); |
| } |
| } else if (strstr(line, "screen_magnifier_present") != NULL) { |
| char* context; |
| char* firstNonSpaceChar = strtok_s(line, " ", &context); |
| if (*firstNonSpaceChar != '#') { |
| strcpy_s(commentLine, "#"); |
| strcat_s(commentLine, line); |
| fputs(commentLine, tempFile); |
| } else { |
| fputs(line, tempFile); |
| } |
| } else { |
| fputs(line, tempFile); |
| } |
| } |
| } |
| } |
| |
| int modify(bool enable) { |
| errno_t error = 0; |
| char path[_MAX_PATH]; |
| char tempPath[_MAX_PATH]; |
| // Get the path for %USERPROFILE% |
| char *profilePath; |
| size_t len; |
| error = _dupenv_s(&profilePath, &len, "USERPROFILE" ); |
| if (error) { |
| printf("Error fetching USERPROFILE.\n"); |
| perror("Error"); |
| return error; |
| } |
| const char acc_props1[] = "\\.accessibility.properties"; |
| const char acc_props2[] = "\\.acce$$ibility.properties"; |
| // len must be 234 or less (233 characters) |
| // sizeof(path) is 260 (room for 259 characters) |
| // sizeof(acc_props1) is 27 (26 characters) |
| // path will hold 233 path characters plus 26 file characters plus 1 null character) |
| // if len - 1 > 233 then error |
| if ( len - 1 > sizeof(path) - sizeof(acc_props1) || |
| len - 1 > sizeof(tempPath) - sizeof(acc_props2) ) { |
| printf("The USERPROFILE environment variable is too long.\n"); |
| printf("It must be no longer than 233 characters.\n"); |
| return 123; |
| } |
| path[0] = 0; |
| strcat_s(path, _MAX_PATH, profilePath); |
| strcat_s(path, acc_props1); |
| tempPath[0] = 0; |
| strcat_s(tempPath, _MAX_PATH, profilePath); |
| strcat_s(tempPath, acc_props2); |
| free(profilePath); |
| profilePath = 0; |
| // Open the original file. If it doesn't exist and this is an enable request then create it. |
| error = fopen_s(&origFile, path, "r"); |
| if (error) { |
| if (enable) { |
| error = fopen_s(&origFile, path, "w"); |
| if (error) { |
| printf("Couldn't create file: %s\n", path); |
| perror("Error"); |
| } else { |
| char str[100] = "assistive_technologies=com.sun.java.accessibility.AccessBridge\n"; |
| strcat_s(str, "screen_magnifier_present=true\n"); |
| fprintf(origFile, str); |
| fclose(origFile); |
| } |
| } else { |
| // It's OK if the file isn't there for a -disable |
| error = 0; |
| } |
| } else { |
| // open a temp file |
| error = fopen_s(&tempFile, tempPath, "w"); |
| if (error) { |
| printf("Couldn't open temp file: %s\n", tempPath); |
| perror("Error"); |
| return error; |
| } |
| if (enable) { |
| enableJAB(); |
| } else { |
| disableJAB(); |
| } |
| fclose(origFile); |
| fclose(tempFile); |
| // delete the orig file and rename the temp file |
| if (remove(path) != 0) { |
| printf("Couldn't remove file: %s\n", path); |
| perror("Error"); |
| return errno; |
| } |
| if (rename(tempPath, path) != 0) { |
| printf("Couldn't rename %s to %s.\n", tempPath, path); |
| perror("Error"); |
| return errno; |
| } |
| } |
| return error; |
| } |
| |
| void printUsage() { |
| printf("\njabswitch [/enable | /disable | /version | /?]\n\n"); |
| printf("Description:\n"); |
| printf(" jabswitch enables or disables the Java Access Bridge.\n\n"); |
| printf("Parameters:\n"); |
| printf(" /enable Enable the Java Accessibility Bridge.\n"); |
| printf(" /disable Disable the Java Accessibility Bridge.\n"); |
| printf(" /version Display the version.\n"); |
| printf(" /? Display this usage information.\n"); |
| printf("\nNote:\n"); |
| printf(" The Java Access Bridge can also be enabled with the\n"); |
| printf(" Windows Ease of Access control panel (which can be\n"); |
| printf(" activated by pressing Windows + U). The Ease of Access\n"); |
| printf(" control panel has a Java Access Bridge checkbox. Please\n"); |
| printf(" be aware that unchecking the checkbox has no effect and\n"); |
| printf(" in order to disable the Java Access Bridge you must run\n"); |
| printf(" jabswitch.exe from the command line.\n"); |
| } |
| |
| void printVersion() { |
| TCHAR executableFileName[_MAX_PATH]; |
| if (!GetModuleFileName(0, executableFileName, _MAX_PATH)) { |
| printf("Unable to get executable file name.\n"); |
| return; |
| } |
| DWORD nParam; |
| DWORD nVersionSize = GetFileVersionInfoSize(executableFileName, &nParam); |
| if (!nVersionSize) { |
| printf("Unable to get version info size.\n"); |
| return; |
| } |
| char* pVersionData = new char[nVersionSize]; |
| if (!GetFileVersionInfo(executableFileName, 0, nVersionSize, pVersionData)) { |
| printf("Unable to get version info.\n"); |
| return; |
| } |
| LPVOID pVersionInfo; |
| UINT nSize; |
| if (!VerQueryValue(pVersionData, _T("\\"), &pVersionInfo, &nSize)) { |
| printf("Unable to query version value.\n"); |
| return; |
| } |
| VS_FIXEDFILEINFO *pVSInfo = (VS_FIXEDFILEINFO *)pVersionInfo; |
| char versionString[100]; |
| sprintf_s( versionString, "version %i.%i.%i.%i", |
| pVSInfo->dwProductVersionMS >> 16, |
| pVSInfo->dwProductVersionMS & 0xFFFF, |
| pVSInfo->dwProductVersionLS >> 16, |
| pVSInfo->dwProductVersionLS & 0xFFFF ); |
| char outputString[100]; |
| strcpy_s(outputString, "jabswitch "); |
| strcat_s(outputString, versionString); |
| strcat_s(outputString, "\njabswitch enables or disables the Java Access Bridge.\n"); |
| printf(outputString); |
| } |
| |
| int regEnable() { |
| HKEY hKey; |
| DWORD retval = -1; |
| LSTATUS err; |
| err = RegOpenKeyEx(HKEY_CURRENT_USER, ACCESSIBILITY_USER_KEY, NULL, KEY_READ|KEY_WRITE, &hKey); |
| if (err == ERROR_SUCCESS) { |
| DWORD dataType = REG_SZ; |
| DWORD dataLength = DEFAULT_ALLOC; |
| TCHAR dataBuffer[DEFAULT_ALLOC]; |
| TCHAR *data = dataBuffer; |
| bool freeData = false; |
| err = RegQueryValueEx(hKey, ACCESSIBILITY_CONFIG, 0, &dataType, (BYTE *)data, &dataLength); |
| if (err == ERROR_MORE_DATA) { |
| if (dataLength > 0 && dataLength < MAX_ALLOC) { |
| data = new TCHAR[dataLength]; |
| err = RegQueryValueEx(hKey, ACCESSIBILITY_CONFIG, 0, &dataType, (BYTE *)data, &dataLength); |
| } |
| } |
| if (err == ERROR_SUCCESS) { |
| err = _tcslwr_s(dataBuffer, DEFAULT_ALLOC); |
| if (err) { |
| return -1; |
| } |
| if (_tcsstr(dataBuffer, STR_ACCESSBRIDGE) != NULL) { |
| return 0; // This is OK, e.g. ran enable twice and the value is there. |
| } else { |
| // add oracle_javaaccessbridge to Config key for HKCU |
| dataLength = dataLength + (_tcslen(STR_ACCESSBRIDGE) + 1) * sizeof(TCHAR); |
| TCHAR *newStr = new TCHAR[dataLength]; |
| if (newStr != NULL) { |
| wsprintf(newStr, L"%s,%s", dataBuffer, STR_ACCESSBRIDGE); |
| RegSetValueEx(hKey, ACCESSIBILITY_CONFIG, 0, REG_SZ, (BYTE *)newStr, dataLength); |
| } |
| } |
| } |
| RegCloseKey(hKey); |
| } |
| return err; |
| } |
| |
| int regDeleteValue(HKEY hFamilyKey, LPCWSTR lpSubKey) |
| { |
| HKEY hKey; |
| DWORD retval = -1; |
| LSTATUS err; |
| err = RegOpenKeyEx(hFamilyKey, lpSubKey, NULL, KEY_READ|KEY_WRITE|KEY_WOW64_64KEY, &hKey); |
| if (err != ERROR_SUCCESS) |
| err = RegOpenKeyEx(hFamilyKey, lpSubKey, NULL, KEY_READ|KEY_WRITE, &hKey); |
| |
| if (err == ERROR_SUCCESS) { |
| DWORD dataType = REG_SZ; |
| DWORD dataLength = DEFAULT_ALLOC; |
| TCHAR dataBuffer[DEFAULT_ALLOC]; |
| TCHAR searchBuffer[DEFAULT_ALLOC]; |
| TCHAR *data = dataBuffer; |
| bool freeData = false; |
| err = RegQueryValueEx(hKey, ACCESSIBILITY_CONFIG, 0, &dataType, (BYTE *)data, &dataLength); |
| if (err == ERROR_MORE_DATA) { |
| if (dataLength > 0 && dataLength < MAX_ALLOC) { |
| data = new TCHAR[dataLength]; |
| err = RegQueryValueEx(hKey, ACCESSIBILITY_CONFIG, 0, &dataType, (BYTE *)data, &dataLength); |
| } |
| } |
| if (err == ERROR_SUCCESS) { |
| err = _tcslwr_s(dataBuffer, DEFAULT_ALLOC); |
| if (err) { |
| return -1; |
| } |
| if (_tcsstr(dataBuffer, STR_ACCESSBRIDGE) == NULL) { |
| return 0; // This is OK, e.g. ran disable twice and the value is not there. |
| } else { |
| // remove oracle_javaaccessbridge from Config key |
| TCHAR *newStr = new TCHAR[dataLength]; |
| TCHAR *nextToken; |
| LPTSTR tok, beg1 = dataBuffer; |
| bool first = true; |
| _tcscpy_s(newStr, dataLength, L""); |
| tok = _tcstok_s(beg1, L",", &nextToken); |
| while (tok != NULL) { |
| _tcscpy_s(searchBuffer, DEFAULT_ALLOC, tok); |
| err = _tcslwr_s(searchBuffer, DEFAULT_ALLOC); |
| if (err) { |
| return -1; |
| } |
| if (_tcsstr(searchBuffer, STR_ACCESSBRIDGE) == NULL) { |
| if (!first) { |
| _tcscat_s(newStr, dataLength, L","); |
| } |
| first = false; |
| _tcscat_s(newStr, dataLength, tok); |
| } |
| tok = _tcstok_s(NULL, L",", &nextToken); |
| } |
| dataLength = (_tcslen(newStr) + 1) * sizeof(TCHAR); |
| RegSetValueEx(hKey, ACCESSIBILITY_CONFIG, 0, REG_SZ, (BYTE *)newStr, dataLength); |
| } |
| } |
| RegCloseKey(hKey); |
| } |
| return err; |
| } |
| |
| int regDisable() |
| { |
| LSTATUS err; |
| // Update value for HKCU |
| err=regDeleteValue(HKEY_CURRENT_USER, ACCESSIBILITY_USER_KEY); |
| // Update value for HKLM for Session |
| TCHAR dataBuffer[DEFAULT_ALLOC]; |
| DWORD dwSessionId ; |
| ProcessIdToSessionId(GetCurrentProcessId(),&dwSessionId ) ; |
| if( dwSessionId >= 0 ) |
| { |
| wsprintf(dataBuffer, L"%s%d", ACCESSIBILITY_SYSTEM_KEY, dwSessionId); |
| err=regDeleteValue(HKEY_LOCAL_MACHINE, dataBuffer); |
| } |
| return err; |
| } |
| |
| void main(int argc, char* argv[]) { |
| bool enableWasRequested = false; |
| bool disableWasRequested = false; |
| bool badParams = true; |
| int error = 0; |
| if (argc == 2) { |
| if (_stricmp(argv[1], "-?") == 0 || _stricmp(argv[1], "/?") == 0) { |
| printUsage(); |
| badParams = false; |
| } else if (_stricmp(argv[1], "-version") == 0 || _stricmp(argv[1], "/version") == 0) { |
| printVersion(); |
| badParams = false; |
| } else { |
| if (_stricmp(argv[1], "-enable") == 0 || _stricmp(argv[1], "/enable") == 0) { |
| badParams = false; |
| enableWasRequested = true; |
| error = modify(true); |
| if (error == 0) { |
| if( !isXP() ) |
| regEnable(); |
| } |
| } else if (_stricmp(argv[1], "-disable") == 0 || _stricmp(argv[1], "/disable") == 0) { |
| badParams = false; |
| disableWasRequested = true; |
| error = modify(false); |
| if (error == 0) { |
| if( !isXP() ) |
| regDisable(); |
| } |
| } |
| } |
| } |
| if (badParams) { |
| printUsage(); |
| } else if (enableWasRequested || disableWasRequested) { |
| if (error != 0) { |
| printf("There was an error.\n\n"); |
| } |
| printf("The Java Access Bridge has "); |
| if (error != 0) { |
| printf("not "); |
| } |
| printf("been "); |
| if (enableWasRequested) { |
| printf("enabled.\n"); |
| } else { |
| printf("disabled.\n"); |
| } |
| // Use exit so test case can sense for error. |
| if (error != 0) { |
| exit(error); |
| } |
| } |
| } |