Path: blob/master/src/jdk.accessibility/windows/native/libjavaaccessbridge/AccessBridgeATInstance.cpp
40957 views
/*1* Copyright (c) 2005, 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/*26* A class to track key AT instance info from the JavaAccessBridge27*/2829#include "AccessBridgeDebug.h"30#include "AccessBridgeATInstance.h"31#include "AccessBridgeMessages.h"3233#include <windows.h>34#include <winbase.h>353637/**38* AccessBridgeATInstance constructor39*/40AccessBridgeATInstance::AccessBridgeATInstance(HWND ourABWindow, HWND winABWindow,41char *memoryFilename,42AccessBridgeATInstance *next) {43ourAccessBridgeWindow = ourABWindow;44winAccessBridgeWindow = winABWindow;45nextATInstance = next;46javaEventMask = 0;47accessibilityEventMask = 0;48strncpy(memoryMappedFileName, memoryFilename, cMemoryMappedNameSize);49}5051/**52* AccessBridgeATInstance descructor53*/54AccessBridgeATInstance::~AccessBridgeATInstance() {55PrintDebugString("[INFO]: in AccessBridgeATInstance::~AccessBridgeATInstance");5657// if IPC memory mapped file view is valid, unmap it58if (memoryMappedView != (char *) 0) {59PrintDebugString("[INFO]: unmapping memoryMappedView; view = %p", memoryMappedView);60UnmapViewOfFile(memoryMappedView);61memoryMappedView = (char *) 0;62}63// if IPC memory mapped file handle map is open, close it64if (memoryMappedFileMapHandle != (HANDLE) 0) {65PrintDebugString("[INFO]: closing memoryMappedFileMapHandle; handle = %p", memoryMappedFileMapHandle);66CloseHandle(memoryMappedFileMapHandle);67memoryMappedFileMapHandle = (HANDLE) 0;68}69}7071/**72* Sets up the memory-mapped file to do IPC messaging73* 1 files is created: to handle requests for information74* initiated from Windows AT. The package is placed into75* the memory-mapped file (char *memoryMappedView),76* and then a special SendMessage() is sent. When the77* JavaDLL returns from SendMessage() processing, the78* data will be in memoryMappedView. The SendMessage()79* return value tells us if all is right with the world.80*81* The set-up proces involves creating the memory-mapped82* file, and writing a special string to it so that the83* WindowsDLL so it knows about it as well.84*/85LRESULT86AccessBridgeATInstance::initiateIPC() {87DWORD errorCode;8889PrintDebugString("[INFO]: In AccessBridgeATInstance::initiateIPC()");9091// open Windows-initiated IPC filemap & map it to a ptr9293memoryMappedFileMapHandle = OpenFileMapping(FILE_MAP_READ | FILE_MAP_WRITE,94FALSE, memoryMappedFileName);95if (memoryMappedFileMapHandle == NULL) {96errorCode = GetLastError();97PrintDebugString("[ERROR]: Failed to CreateFileMapping for %s, error: %X", memoryMappedFileName, errorCode);98return errorCode;99} else {100PrintDebugString("[INFO]: CreateFileMapping worked - filename: %s", memoryMappedFileName);101}102103memoryMappedView = (char *) MapViewOfFile(memoryMappedFileMapHandle,104FILE_MAP_READ | FILE_MAP_WRITE,1050, 0, 0);106if (memoryMappedView == NULL) {107errorCode = GetLastError();108PrintDebugString("[ERROR]: Failed to MapViewOfFile for %s, error: %X", memoryMappedFileName, errorCode);109return errorCode;110} else {111PrintDebugString("[INFO]: MapViewOfFile worked - view: %p", memoryMappedView);112}113114115// look for the JavaDLL's answer to see if it could read the file116if (strcmp(memoryMappedView, AB_MEMORY_MAPPED_FILE_OK_QUERY) != 0) {117PrintDebugString("[ERROR]: JavaVM failed to write to memory mapped file %s",118memoryMappedFileName);119return -1;120} else {121PrintDebugString("[INFO]: JavaVM successfully wrote to file!");122}123124125// write some data to the memory mapped file for WindowsDLL to verify126strcpy(memoryMappedView, AB_MEMORY_MAPPED_FILE_OK_ANSWER);127128129return 0;130}131132133typedef struct EVENT_STRUCT134{135char *buffer;136int bufsize;137ABHWND64 winAccessBridgeWindow;138ABHWND64 ourAccessBridgeWindow;139}EVENT_STRUCT;140141142#include <process.h>143#define THREAD_PROC unsigned int __stdcall144typedef unsigned int (__stdcall *THREAD_ROUTINE)(LPVOID lpThreadParameter);145146static HANDLE BeginThread(THREAD_ROUTINE thread_func,DWORD *id,DWORD param)147{148HANDLE ret;149ret = (HANDLE) _beginthreadex(NULL,0,thread_func,(void *)param,0,(unsigned int *)id);150if(ret == INVALID_HANDLE_VALUE)151ret = NULL;152return(ret);153}154155DWORD JavaBridgeThreadId = 0;156157static THREAD_PROC JavaBridgeThread(LPVOID param1)158{159MSG msg;160DWORD rc = 0;161while (GetMessage(&msg, // message structure162NULL, // handle of window receiving the message1630, // lowest message to examine1640)) // highest message to examine165{166if(msg.message == WM_USER)167{168EVENT_STRUCT *event_struct = (EVENT_STRUCT *)msg.wParam;169COPYDATASTRUCT toCopy;170toCopy.dwData = 0; // 32-bits we could use for something...171toCopy.cbData = event_struct->bufsize;172toCopy.lpData = event_struct->buffer;173174LRESULT ret = SendMessage((HWND)ABLongToHandle(event_struct->winAccessBridgeWindow), WM_COPYDATA,175(WPARAM)event_struct->ourAccessBridgeWindow, (LPARAM) &toCopy);176delete event_struct->buffer;177delete event_struct;178}179if(msg.message == (WM_USER+1))180PostQuitMessage(0);181}182JavaBridgeThreadId = 0;183return(0);184}185186/*187* Handles one event188*/189static void do_event(char *buffer, int bufsize,HWND ourAccessBridgeWindow,HWND winAccessBridgeWindow)190{191EVENT_STRUCT *event_struct = new EVENT_STRUCT;192event_struct->bufsize = bufsize;193event_struct->buffer = new char[bufsize];194memcpy(event_struct->buffer,buffer,bufsize);195event_struct->ourAccessBridgeWindow = ABHandleToLong(ourAccessBridgeWindow);196event_struct->winAccessBridgeWindow = ABHandleToLong(winAccessBridgeWindow);197if(!JavaBridgeThreadId)198{199HANDLE JavaBridgeThreadHandle = BeginThread(JavaBridgeThread,&JavaBridgeThreadId,(DWORD)event_struct);200CloseHandle(JavaBridgeThreadHandle);201}202PostThreadMessage(JavaBridgeThreadId,WM_USER,(WPARAM)event_struct,0);203}204205206/**207* sendJavaEventPackage - uses SendMessage(WM_COPYDATA) to do208* IPC messaging with the Java AccessBridge DLL209* to propogate events to those ATs that want 'em210*211*/212LRESULT213AccessBridgeATInstance::sendJavaEventPackage(char *buffer, int bufsize, long eventID) {214215PrintDebugString("[INFO]: AccessBridgeATInstance::sendJavaEventPackage() eventID = %X", eventID);216PrintDebugString("[INFO]: AccessBridgeATInstance::sendJavaEventPackage() (using PostMessage) eventID = %X", eventID);217218if (eventID & javaEventMask) {219do_event(buffer,bufsize,ourAccessBridgeWindow,winAccessBridgeWindow);220return(0);221} else {222return -1;223}224}225226227/**228* uses SendMessage(WM_COPYDATA) to do229* IPC messaging with the Java AccessBridge DLL230* to propogate events to those ATs that want 'em231*232*/233LRESULT234AccessBridgeATInstance::sendAccessibilityEventPackage(char *buffer, int bufsize, long eventID) {235236PrintDebugString("[INFO]: AccessBridgeATInstance::sendAccessibilityEventPackage() eventID = %X", eventID);237238if (eventID & accessibilityEventMask) {239do_event(buffer,bufsize,ourAccessBridgeWindow,winAccessBridgeWindow);240return(0);241} else {242return -1;243}244}245246247/**248* findABATInstanceFromATHWND - walk through linked list from249* where we are. Return the250* AccessBridgeATInstance251* of the ABATInstance that252* matches the passed in vmID;253* no match: return 0254*/255AccessBridgeATInstance *256AccessBridgeATInstance::findABATInstanceFromATHWND(HWND window) {257// no need to recurse really258if (winAccessBridgeWindow == window) {259return this;260} else {261AccessBridgeATInstance *current = nextATInstance;262while (current != (AccessBridgeATInstance *) 0) {263if (current->winAccessBridgeWindow == window) {264return current;265}266current = current->nextATInstance;267}268}269return (AccessBridgeATInstance *) 0;270}271272273