text: /*
   * Copyright (c) 2005, 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.
   */
  
  /*
   * A class to track key AT instance info from the JavaAccessBridge
   */
  
  #include "AccessBridgeDebug.h"
  #include "AccessBridgeATInstance.h"
  #include "AccessBridgeMessages.h"
  
  #include <windows.h>
  #include <winbase.h>
  
  
  /**
   *  AccessBridgeATInstance constructor
   */
  AccessBridgeATInstance::AccessBridgeATInstance(HWND ourABWindow, HWND winABWindow,
                                                 char *memoryFilename,
                                                 AccessBridgeATInstance *next) {
      ourAccessBridgeWindow = ourABWindow;
      winAccessBridgeWindow = winABWindow;
      nextATInstance = next;
      javaEventMask = 0;
      accessibilityEventMask = 0;
      strncpy(memoryMappedFileName, memoryFilename, cMemoryMappedNameSize);
  }
  
  /**
   * AccessBridgeATInstance descructor
   */
  AccessBridgeATInstance::~AccessBridgeATInstance() {
      PrintDebugString("[INFO]: in AccessBridgeATInstance::~AccessBridgeATInstance");
  
      // if IPC memory mapped file view is valid, unmap it
      if (memoryMappedView != (char *) 0) {
          PrintDebugString("[INFO]:   unmapping memoryMappedView; view = %p", memoryMappedView);
          UnmapViewOfFile(memoryMappedView);
          memoryMappedView = (char *) 0;
      }
      // if IPC memory mapped file handle map is open, close it
      if (memoryMappedFileMapHandle != (HANDLE) 0) {
          PrintDebugString("[INFO]:   closing memoryMappedFileMapHandle; handle = %p", memoryMappedFileMapHandle);
          CloseHandle(memoryMappedFileMapHandle);
          memoryMappedFileMapHandle = (HANDLE) 0;
      }
  }
  
  /**
   * Sets up the memory-mapped file to do IPC messaging
   * 1 files is created: to handle requests for information
   * initiated from Windows AT.  The package is placed into
   * the memory-mapped file (char *memoryMappedView),
   * and then a special SendMessage() is sent.  When the
   * JavaDLL returns from SendMessage() processing, the
   * data will be in memoryMappedView.  The SendMessage()
   * return value tells us if all is right with the world.
   *
   * The set-up proces involves creating the memory-mapped
   * file, and writing a special string to it so that the
   * WindowsDLL so it knows about it as well.
   */
  LRESULT
  AccessBridgeATInstance::initiateIPC() {
      DWORD errorCode;
  
      PrintDebugString("[INFO]: In AccessBridgeATInstance::initiateIPC()");
  
      // open Windows-initiated IPC filemap & map it to a ptr
  
      memoryMappedFileMapHandle = OpenFileMapping(FILE_MAP_READ | FILE_MAP_WRITE,
                                                  FALSE, memoryMappedFileName);
      if (memoryMappedFileMapHandle == NULL) {
          errorCode = GetLastError();
          PrintDebugString("[ERROR]:   Failed to CreateFileMapping for %s, error: %X", memoryMappedFileName, errorCode);
          return errorCode;
      } else {
          PrintDebugString("[INFO]:   CreateFileMapping worked - filename: %s", memoryMappedFileName);
      }
  
      memoryMappedView = (char *) MapViewOfFile(memoryMappedFileMapHandle,
                                                FILE_MAP_READ | FILE_MAP_WRITE,
                                                0, 0, 0);
      if (memoryMappedView == NULL) {
          errorCode = GetLastError();
          PrintDebugString("[ERROR]:   Failed to MapViewOfFile for %s, error: %X", memoryMappedFileName, errorCode);
          return errorCode;
      } else {
          PrintDebugString("[INFO]:   MapViewOfFile worked - view: %p", memoryMappedView);
      }
  
  
      // look for the JavaDLL's answer to see if it could read the file
      if (strcmp(memoryMappedView, AB_MEMORY_MAPPED_FILE_OK_QUERY) != 0) {
          PrintDebugString("[ERROR]:   JavaVM failed to write to memory mapped file %s",
                           memoryMappedFileName);
          return -1;
      } else {
          PrintDebugString("[INFO]:   JavaVM successfully wrote to file!");
      }
  
  
      // write some data to the memory mapped file for WindowsDLL to verify
      strcpy(memoryMappedView, AB_MEMORY_MAPPED_FILE_OK_ANSWER);
  
  
      return 0;
  }
  
  
  typedef struct EVENT_STRUCT
  {
      char *buffer;
      int bufsize;
      ABHWND64 winAccessBridgeWindow;
      ABHWND64 ourAccessBridgeWindow;
  }EVENT_STRUCT;
  
  
  #include <process.h>
  #define THREAD_PROC unsigned int __stdcall
  typedef unsigned int (__stdcall *THREAD_ROUTINE)(LPVOID lpThreadParameter);
  
  static HANDLE BeginThread(THREAD_ROUTINE thread_func,DWORD *id,DWORD param)
  {
      HANDLE ret;
      ret = (HANDLE) _beginthreadex(NULL,0,thread_func,(void *)param,0,(unsigned int *)id);
      if(ret == INVALID_HANDLE_VALUE)
          ret = NULL;
      return(ret);
  }
  
  DWORD JavaBridgeThreadId = 0;
  
  static THREAD_PROC JavaBridgeThread(LPVOID param1)
  {
      MSG msg;
      DWORD rc = 0;
      while (GetMessage(&msg,        // message structure
                        NULL,                  // handle of window receiving the message
                        0,                  // lowest message to examine
                        0))                 // highest message to examine
          {
              if(msg.message == WM_USER)
                  {
                      EVENT_STRUCT *event_struct = (EVENT_STRUCT *)msg.wParam;
                      COPYDATASTRUCT toCopy;
                      toCopy.dwData = 0;          // 32-bits we could use for something...
                      toCopy.cbData = event_struct->bufsize;
                      toCopy.lpData = event_struct->buffer;
  
                      LRESULT ret = SendMessage((HWND)ABLongToHandle(event_struct->winAccessBridgeWindow), WM_COPYDATA,
                                                (WPARAM)event_struct->ourAccessBridgeWindow, (LPARAM) &toCopy);
                      delete event_struct->buffer;
                      delete event_struct;
                  }
              if(msg.message == (WM_USER+1))
                  PostQuitMessage(0);
          }
      JavaBridgeThreadId = 0;
      return(0);
  }
  
  /*
   * Handles one event
   */
  static void do_event(char *buffer, int bufsize,HWND ourAccessBridgeWindow,HWND winAccessBridgeWindow)
  {
      EVENT_STRUCT *event_struct = new EVENT_STRUCT;
      event_struct->bufsize = bufsize;
      event_struct->buffer = new char[bufsize];
      memcpy(event_struct->buffer,buffer,bufsize);
      event_struct->ourAccessBridgeWindow = ABHandleToLong(ourAccessBridgeWindow);
      event_struct->winAccessBridgeWindow = ABHandleToLong(winAccessBridgeWindow);
      if(!JavaBridgeThreadId)
          {
              HANDLE JavaBridgeThreadHandle = BeginThread(JavaBridgeThread,&JavaBridgeThreadId,(DWORD)event_struct);
              CloseHandle(JavaBridgeThreadHandle);
          }
      PostThreadMessage(JavaBridgeThreadId,WM_USER,(WPARAM)event_struct,0);
  }
  
  
  /**
   * sendJavaEventPackage - uses SendMessage(WM_COPYDATA) to do
   *                        IPC messaging with the Java AccessBridge DLL
   *                        to propogate events to those ATs that want 'em
   *
   */
  LRESULT
  AccessBridgeATInstance::sendJavaEventPackage(char *buffer, int bufsize, long eventID) {
  
      PrintDebugString("[INFO]: AccessBridgeATInstance::sendJavaEventPackage() eventID = %X", eventID);
      PrintDebugString("[INFO]: AccessBridgeATInstance::sendJavaEventPackage() (using PostMessage) eventID = %X", eventID);
  
      if (eventID & javaEventMask) {
          do_event(buffer,bufsize,ourAccessBridgeWindow,winAccessBridgeWindow);
          return(0);
      } else {
          return -1;
      }
  }
  
  
  /**
   * uses SendMessage(WM_COPYDATA) to do
   * IPC messaging with the Java AccessBridge DLL
   * to propogate events to those ATs that want 'em
   *
   */
  LRESULT
  AccessBridgeATInstance::sendAccessibilityEventPackage(char *buffer, int bufsize, long eventID) {
  
      PrintDebugString("[INFO]: AccessBridgeATInstance::sendAccessibilityEventPackage() eventID = %X", eventID);
  
      if (eventID & accessibilityEventMask) {
          do_event(buffer,bufsize,ourAccessBridgeWindow,winAccessBridgeWindow);
          return(0);
      } else {
          return -1;
      }
  }
  
  
  /**
   * findABATInstanceFromATHWND - walk through linked list from
   *                              where we are.  Return the
   *                              AccessBridgeATInstance
   *                              of the ABATInstance that
   *                              matches the passed in vmID;
   *                              no match: return 0
   */
  AccessBridgeATInstance *
  AccessBridgeATInstance::findABATInstanceFromATHWND(HWND window) {
      // no need to recurse really
      if (winAccessBridgeWindow == window) {
          return this;
      } else {
          AccessBridgeATInstance *current = nextATInstance;
          while (current != (AccessBridgeATInstance *) 0) {
              if (current->winAccessBridgeWindow == window) {
                  return current;
              }
              current = current->nextATInstance;
          }
      }
      return (AccessBridgeATInstance *) 0;
  }
  