1/* 2 * Copyright (c) 2005, 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/* 27 * A class to track key AT instance info from the JavaAccessBridge 28 */ 29 30#include "AccessBridgeDebug.h" 31#include "AccessBridgeATInstance.h" 32#include "AccessBridgeMessages.h" 33 34#include <windows.h> 35#include <winbase.h> 36 37 38/** 39 * AccessBridgeATInstance constructor 40 */ 41AccessBridgeATInstance::AccessBridgeATInstance(HWND ourABWindow, HWND winABWindow, 42 char *memoryFilename, 43 AccessBridgeATInstance *next) { 44 ourAccessBridgeWindow = ourABWindow; 45 winAccessBridgeWindow = winABWindow; 46 nextATInstance = next; 47 javaEventMask = 0; 48 accessibilityEventMask = 0; 49 strncpy(memoryMappedFileName, memoryFilename, cMemoryMappedNameSize); 50} 51 52/** 53 * AccessBridgeATInstance descructor 54 */ 55AccessBridgeATInstance::~AccessBridgeATInstance() { 56 PrintDebugString("\r\nin AccessBridgeATInstance::~AccessBridgeATInstance"); 57 58 // if IPC memory mapped file view is valid, unmap it 59 if (memoryMappedView != (char *) 0) { 60 PrintDebugString(" unmapping memoryMappedView; view = %p", memoryMappedView); 61 UnmapViewOfFile(memoryMappedView); 62 memoryMappedView = (char *) 0; 63 } 64 // if IPC memory mapped file handle map is open, close it 65 if (memoryMappedFileMapHandle != (HANDLE) 0) { 66 PrintDebugString(" closing memoryMappedFileMapHandle; handle = %p", memoryMappedFileMapHandle); 67 CloseHandle(memoryMappedFileMapHandle); 68 memoryMappedFileMapHandle = (HANDLE) 0; 69 } 70} 71 72/** 73 * Sets up the memory-mapped file to do IPC messaging 74 * 1 files is created: to handle requests for information 75 * initiated from Windows AT. The package is placed into 76 * the memory-mapped file (char *memoryMappedView), 77 * and then a special SendMessage() is sent. When the 78 * JavaDLL returns from SendMessage() processing, the 79 * data will be in memoryMappedView. The SendMessage() 80 * return value tells us if all is right with the world. 81 * 82 * The set-up proces involves creating the memory-mapped 83 * file, and writing a special string to it so that the 84 * WindowsDLL so it knows about it as well. 85 */ 86LRESULT 87AccessBridgeATInstance::initiateIPC() { 88 DWORD errorCode; 89 90 PrintDebugString("\r\nIn AccessBridgeATInstance::initiateIPC()"); 91 92 // open Windows-initiated IPC filemap & map it to a ptr 93 94 memoryMappedFileMapHandle = OpenFileMapping(FILE_MAP_READ | FILE_MAP_WRITE, 95 FALSE, memoryMappedFileName); 96 if (memoryMappedFileMapHandle == NULL) { 97 errorCode = GetLastError(); 98 PrintDebugString(" Failed to CreateFileMapping for %s, error: %X", memoryMappedFileName, errorCode); 99 return errorCode; 100 } else { 101 PrintDebugString(" CreateFileMapping worked - filename: %s", memoryMappedFileName); 102 } 103 104 memoryMappedView = (char *) MapViewOfFile(memoryMappedFileMapHandle, 105 FILE_MAP_READ | FILE_MAP_WRITE, 106 0, 0, 0); 107 if (memoryMappedView == NULL) { 108 errorCode = GetLastError(); 109 PrintDebugString(" Failed to MapViewOfFile for %s, error: %X", memoryMappedFileName, errorCode); 110 return errorCode; 111 } else { 112 PrintDebugString(" MapViewOfFile worked - view: %p", memoryMappedView); 113 } 114 115 116 // look for the JavaDLL's answer to see if it could read the file 117 if (strcmp(memoryMappedView, AB_MEMORY_MAPPED_FILE_OK_QUERY) != 0) { 118 PrintDebugString(" JavaVM failed to write to memory mapped file %s", 119 memoryMappedFileName); 120 return -1; 121 } else { 122 PrintDebugString(" JavaVM successfully wrote to file!"); 123 } 124 125 126 // write some data to the memory mapped file for WindowsDLL to verify 127 strcpy(memoryMappedView, AB_MEMORY_MAPPED_FILE_OK_ANSWER); 128 129 130 return 0; 131} 132 133 134typedef struct EVENT_STRUCT 135{ 136 char *buffer; 137 int bufsize; 138 ABHWND64 winAccessBridgeWindow; 139 ABHWND64 ourAccessBridgeWindow; 140}EVENT_STRUCT; 141 142 143#include <process.h> 144#define THREAD_PROC unsigned int __stdcall 145typedef unsigned int (__stdcall *THREAD_ROUTINE)(LPVOID lpThreadParameter); 146 147static HANDLE BeginThread(THREAD_ROUTINE thread_func,DWORD *id,DWORD param) 148{ 149 HANDLE ret; 150 ret = (HANDLE) _beginthreadex(NULL,0,thread_func,(void *)param,0,(unsigned int *)id); 151 if(ret == INVALID_HANDLE_VALUE) 152 ret = NULL; 153 return(ret); 154} 155 156DWORD JavaBridgeThreadId = 0; 157 158static THREAD_PROC JavaBridgeThread(LPVOID param1) 159{ 160 MSG msg; 161 DWORD rc = 0; 162 while (GetMessage(&msg, // message structure 163 NULL, // handle of window receiving the message 164 0, // lowest message to examine 165 0)) // highest message to examine 166 { 167 if(msg.message == WM_USER) 168 { 169 EVENT_STRUCT *event_struct = (EVENT_STRUCT *)msg.wParam; 170 COPYDATASTRUCT toCopy; 171 toCopy.dwData = 0; // 32-bits we could use for something... 172 toCopy.cbData = event_struct->bufsize; 173 toCopy.lpData = event_struct->buffer; 174 175 LRESULT ret = SendMessage((HWND)ABLongToHandle(event_struct->winAccessBridgeWindow), WM_COPYDATA, 176 (WPARAM)event_struct->ourAccessBridgeWindow, (LPARAM) &toCopy); 177 delete event_struct->buffer; 178 delete event_struct; 179 } 180 if(msg.message == (WM_USER+1)) 181 PostQuitMessage(0); 182 } 183 JavaBridgeThreadId = 0; 184 return(0); 185} 186 187/* 188 * Handles one event 189 */ 190static void do_event(char *buffer, int bufsize,HWND ourAccessBridgeWindow,HWND winAccessBridgeWindow) 191{ 192 EVENT_STRUCT *event_struct = new EVENT_STRUCT; 193 event_struct->bufsize = bufsize; 194 event_struct->buffer = new char[bufsize]; 195 memcpy(event_struct->buffer,buffer,bufsize); 196 event_struct->ourAccessBridgeWindow = ABHandleToLong(ourAccessBridgeWindow); 197 event_struct->winAccessBridgeWindow = ABHandleToLong(winAccessBridgeWindow); 198 if(!JavaBridgeThreadId) 199 { 200 HANDLE JavaBridgeThreadHandle = BeginThread(JavaBridgeThread,&JavaBridgeThreadId,(DWORD)event_struct); 201 CloseHandle(JavaBridgeThreadHandle); 202 } 203 PostThreadMessage(JavaBridgeThreadId,WM_USER,(WPARAM)event_struct,0); 204} 205 206 207/** 208 * sendJavaEventPackage - uses SendMessage(WM_COPYDATA) to do 209 * IPC messaging with the Java AccessBridge DLL 210 * to propogate events to those ATs that want 'em 211 * 212 */ 213LRESULT 214AccessBridgeATInstance::sendJavaEventPackage(char *buffer, int bufsize, long eventID) { 215 216 PrintDebugString("AccessBridgeATInstance::sendJavaEventPackage() eventID = %X", eventID); 217 PrintDebugString("AccessBridgeATInstance::sendJavaEventPackage() (using PostMessage) eventID = %X", eventID); 218 219 if (eventID & javaEventMask) { 220 do_event(buffer,bufsize,ourAccessBridgeWindow,winAccessBridgeWindow); 221 return(0); 222 } else { 223 return -1; 224 } 225} 226 227 228/** 229 * uses SendMessage(WM_COPYDATA) to do 230 * IPC messaging with the Java AccessBridge DLL 231 * to propogate events to those ATs that want 'em 232 * 233 */ 234LRESULT 235AccessBridgeATInstance::sendAccessibilityEventPackage(char *buffer, int bufsize, long eventID) { 236 237 PrintDebugString("AccessBridgeATInstance::sendAccessibilityEventPackage() eventID = %X", eventID); 238 239 if (eventID & accessibilityEventMask) { 240 do_event(buffer,bufsize,ourAccessBridgeWindow,winAccessBridgeWindow); 241 return(0); 242 } else { 243 return -1; 244 } 245} 246 247 248/** 249 * findABATInstanceFromATHWND - walk through linked list from 250 * where we are. Return the 251 * AccessBridgeATInstance 252 * of the ABATInstance that 253 * matches the passed in vmID; 254 * no match: return 0 255 */ 256AccessBridgeATInstance * 257AccessBridgeATInstance::findABATInstanceFromATHWND(HWND window) { 258 // no need to recurse really 259 if (winAccessBridgeWindow == window) { 260 return this; 261 } else { 262 AccessBridgeATInstance *current = nextATInstance; 263 while (current != (AccessBridgeATInstance *) 0) { 264 if (current->winAccessBridgeWindow == window) { 265 return current; 266 } 267 current = current->nextATInstance; 268 } 269 } 270 return (AccessBridgeATInstance *) 0; 271} 272