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