JDK14/Java14源码在线阅读

/*
 * Copyright (c) 2005, 2019, 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 DLL which is loaded by Windows executables to handle communication
 * between Java VMs purposes of Accessbility.
 */

#include "AccessBridgeDebug.h"
#include "WinAccessBridge.h"
#include "accessBridgeResource.h"
#include "accessBridgeCallbacks.h"
#include "AccessBridgeMessages.h"
#include "AccessBridgeMessageQueue.h"

#include <windows.h>
#include <jni.h>
#include <stdio.h>

// send memory lock
//
// This lock is need to serialize access to the buffer used by sendMemoryPackage.
// If a JVM goes away while the associated memory buffer is in use, a thread switch
// allows a call to JavaVMDestroyed and deallocation of the memory buffer.
CRITICAL_SECTION sendMemoryIPCLock;

// registry paths to newly found JVMs that don't have the bridge installed
char **newJVMs;

WinAccessBridge *theWindowsAccessBridge;
HWND theDialogWindow;

// unique broadcast msg. IDs gotten dymanically
extern UINT theFromJavaHelloMsgID;
extern UINT theFromWindowsHelloMsgID;

// protects the javaVMs chain while in use
bool isVMInstanceChainInUse;

/* =================================================================================== */



/**
 * Proc for "New JVM Found" dialog
 */
BOOL CALLBACK newJVMFoundDialogProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam) {

    switch (message) {
    case WM_COMMAND:
        // PrintDebugString("    newJVMDialogProc: LOWORD(wParam) = %d", LOWORD(wParam));

        switch (LOWORD(wParam)) {

            // Remind user later that a new JVM was installed
        case cRemindThereIsNewJVM:
            PrintDebugString("[INFO]:    newJVMDialogProc: cRemindThereIsNewJVM");
            // do nothing
            EndDialog(hwndDlg, wParam);
            return TRUE;

            // Do not remind user later that a new JVM was installed
            /*
        case cDoNotRemindThereIsNewJVM:
            PrintDebugString("    newJVMDialogProc: cDoNotRemindThereIsNewJVM");
            // remember to not remind the user there are new JVMs
            PrintDebugString("theWindowsAccessBridge = %x", theWindowsAccessBridge);
            if (theWindowsAccessBridge != NULL) {
                dontRemindUser(newJVMs);
            }
            EndDialog(hwndDlg, wParam);
            return TRUE;
            */

            // Run the AccessBridge installer
            /*
        case cInstallAccessBridge:
            PrintDebugString("    newJVMDialogProc: cInstallAccessBridge");
            // start the installer
            if (theWindowsAccessBridge != NULL) {
                startInstaller(newJVMs);
            }
            EndDialog(hwndDlg, wParam);
            return TRUE;
            */

        default:
            ;
        }
    default:
        ;
    }
    return FALSE;
}



/* =========================================================================== */

// ---------------------------------------------------------------------------

extern "C" {
    /**
     * DllMain - where Windows executables will load/unload us
     *
     */
    BOOL WINAPI DllMain(HINSTANCE hinstDll, DWORD fdwReason, LPVOID lpvReserved) {

        switch (fdwReason) {
        case DLL_PROCESS_ATTACH:        // A Windows executable loaded us
            initializeFileLogger("windows_access_bridge");
            PrintDebugString("[INFO]: DLL_PROCESS_ATTACH");
            theWindowsAccessBridge = new WinAccessBridge(hinstDll);
            break;

        case DLL_PROCESS_DETACH:        // A Windows executable unloaded us
            if (theWindowsAccessBridge != (WinAccessBridge *) 0) {
                PrintDebugString("[INFO]: *** AccessBridgeDialogProc -> deleting theWindowsAccessBridge");
                delete theWindowsAccessBridge;
            }
            break;
        }

        return(TRUE);
    }

    /**
     * Append debug info to dialog
     *
     * replaced with code to send output to debug file
     *
     */
    void AppendToCallInfo(char *s) {

        /*
          _CrtDbgReport(_CRT_WARN, (const char *) NULL, NULL, (const char *) NULL,
          (const char *) "WinAccessBridge: %s", s);
        */

        char buf[1024];
        sprintf(buf, "WinAccessBridge: %s", s);
        OutputDebugString(buf);
    }

    /**
     * Our window proc
     *
     */
    BOOL CALLBACK AccessBridgeDialogProc(HWND hDlg, UINT message, UINT wParam, LONG lParam) {
        COPYDATASTRUCT *sentToUs;
        char *package;

        switch (message) {
        case WM_INITDIALOG:
            PrintDebugString("[INFO]: AccessBridgeDialogProc -> Initializing");
            break;

            // call from Java with data for us to deliver
        case WM_COPYDATA:
            if (theDialogWindow == (HWND) wParam) {
                PrintDebugString("[INFO]: AccessBridgeDialogProc -> Got WM_COPYDATA from Java Bridge DLL");
            } else {
                PrintDebugString("[INFO]: AccessBridgeDialogProc -> Got WM_COPYDATA from HWND %p", wParam);
                sentToUs = (COPYDATASTRUCT *) lParam;
                package = (char *) sentToUs->lpData;
                theWindowsAccessBridge->preProcessPackage(package, sentToUs->cbData);
            }
            break;

            // message to ourselves -> de-queue messages and send 'em
        case AB_MESSAGE_QUEUED:
            PrintDebugString("[INFO]: AccessBridgeDialogProc -> Got AB_MESSAGE_QUEUED from ourselves");
            theWindowsAccessBridge->receiveAQueuedPackage();
            break;

            // a JavaAccessBridge DLL is going away
            //
            // When JavaVMDestroyed is called a AccessBridgeJavaVMInstance in the
            // javaVMs chain will be removed.  If that chain is in use this will
            // cause a crash.  One way AB_DLL_GOING_AWAY can arrive is on any
            // outgoing SendMessage call.  SendMessage normally spins waiting for
            // a response.  However, if there is an incoming SendMessage, e.g. for
            // AB_DLL_GOING_AWAY Windows will send that request to this DialogProc.
            // One seemingly easy way to combat that is to use SendMessageTimeout
            // with the SMTO_BLOCK flag set.  However, it has been the case that
            // even after using that technique AB_DLL_GOING_AWAY can still arrive
            // in the middle of processing the javaVMs chain.  An alternative that
            // was tried was to use a critical section around any access ot the
            // javaVMs chain but unfortunately the AB_DLL_GOING_AWAY message arrives
            // on the same thread and thus the use of a critical section is ineffective.
            // The solution then is to set a flag whenever the javaVMs chain is being
            // used and if that flag is set at this point the message will be posted
            // to the message queue.  That would delay the destruction of the instance
            // until the chain is not being traversed.
        case AB_DLL_GOING_AWAY:
            PrintDebugString("[INFO]: ***** AccessBridgeDialogProc -> Got AB_DLL_GOING_AWAY message");
            if (isVMInstanceChainInUse) {
                PrintDebugString("[INFO]:   javaVMs chain in use, calling PostMessage");
                PostMessage(hDlg, AB_DLL_GOING_AWAY, wParam, (LPARAM)0);
            } else {
                PrintDebugString("[INFO]:   calling javaVMDestroyed");
                theWindowsAccessBridge->JavaVMDestroyed((HWND) wParam);
            }
            break;

        default:
            // the JavaVM is saying "hi"!
            // wParam == sourceHwnd; lParam == JavaVMID
            if (message == theFromJavaHelloMsgID) {
                PrintDebugString("[INFO]: AccessBridgeDialogProc -> Got theFromJavaHelloMsgID; wParam = %p, lParam = %p", wParam, lParam);
                theWindowsAccessBridge->rendezvousWithNewJavaDLL((HWND) wParam, (long ) lParam);
            }
            break;
        }

        return (FALSE);
    }

}




// ---------------------------------------------------------------------------

/**
 * Initialize the WinAccessBridge
 *
 */
WinAccessBridge::WinAccessBridge(HINSTANCE hInstance) {

    PrintDebugString("[INFO]: WinAccessBridge ctor");

    //  IntializeCriticalSection should only be called once.
    InitializeCriticalSection(&sendMemoryIPCLock);
    windowsInstance = hInstance;
    javaVMs = (AccessBridgeJavaVMInstance *) 0;
    eventHandler = new AccessBridgeEventHandler();
    messageQueue = new AccessBridgeMessageQueue();
    initBroadcastMessageIDs();          // get the unique to us broadcast msg. IDs
    theWindowsAccessBridge = this;
    isVMInstanceChainInUse = false;

    ShowWindow(theDialogWindow, SW_SHOW);
}



/**
 * Destroy the WinAccessBridge
 *
 */
WinAccessBridge::~WinAccessBridge() {
    // inform all other AccessBridges that we're going away
    //  -> shut down all event listening
    //  -> release all objects held in the JVM by us

    PrintDebugString("[INFO]: *****in WinAccessBridge::~WinAccessBridge()");

    // send a broadcast msg.; let other AccessBridge DLLs know we're going away
    AccessBridgeJavaVMInstance *current = javaVMs;
    while (current != (AccessBridgeJavaVMInstance *) 0) {
        PrintDebugString("[INFO]:   telling %p we're going away", current->javaAccessBridgeWindow);
        SendMessage(current->javaAccessBridgeWindow,
                    AB_DLL_GOING_AWAY, (WPARAM) dialogWindow, (LPARAM) 0);
        current = current->nextJVMInstance;
    }

    PrintDebugString("[INFO]:   finished telling JVMs about our demise");

    delete eventHandler;
    delete messageQueue;
    delete javaVMs;

    PrintDebugString("[INFO]:   finished deleting eventHandler, messageQueue, and javaVMs");
    PrintDebugString("[INFO]: GOODBYE CRUEL WORLD...");
    finalizeFileLogger();
    DestroyWindow(theDialogWindow);
}


/**
 * Bring up our window; make a connection to the rest of the world
 *
 */
BOOL
WinAccessBridge::initWindow() {
    theDialogWindow = CreateDialog(windowsInstance,
                                   "ACCESSBRIDGESTATUSWINDOW", NULL,
                                   (DLGPROC) AccessBridgeDialogProc);

    // If window could not be created, return "failure".
    if (!theDialogWindow)
        return (FALSE);

    dialogWindow = theDialogWindow;

    // Make the window visible, update its client area, & return "success".
    // DEBUG_CODE(ShowWindow (theDialogWindow, SW_SHOWNORMAL));
    // DEBUG_CODE(UpdateWindow (theDialogWindow));

    // post a broadcast msg.; let other AccessBridge DLLs know we exist
    PostMessage(HWND_BROADCAST, theFromWindowsHelloMsgID, (WPARAM) dialogWindow, (LPARAM) 0);

    return (TRUE);
}

// -----------------------

/**
 * rendezvousWithNewJavaDLL
 *              - Build AccessBridgeJavaVMInstance data structure
 *                (including setting up Memory-Mapped file info)
 *
 */
LRESULT
WinAccessBridge::rendezvousWithNewJavaDLL(HWND JavaBridgeDLLwindow, long vmID) {
    LRESULT returnVal;

    PrintDebugString("[INFO]: in WinAccessBridge::rendezvousWithNewJavaDLL(%p, %X)",
                     JavaBridgeDLLwindow, vmID);

    isVMInstanceChainInUse = true;
    AccessBridgeJavaVMInstance *newVM =
        new AccessBridgeJavaVMInstance(dialogWindow, JavaBridgeDLLwindow, vmID, javaVMs);
    javaVMs = newVM;
    isVMInstanceChainInUse = false;

    returnVal = javaVMs->initiateIPC();
    if (returnVal == 0) {

        // tell the newly created JavaVM what events we're interested in, if any
        long javaEventMask = eventHandler->getJavaEventMask();
        long accessibilityEventMask = eventHandler->getAccessibilityEventMask();

        PrintDebugString("[INFO]:   Setting Java event mask to: %X", javaEventMask);

        if (javaEventMask != 0) {
            addJavaEventNotification(javaEventMask);
        }

        PrintDebugString("[INFO]:   Setting Accessibility event mask to: %X", accessibilityEventMask);

        if (accessibilityEventMask != 0) {
            addAccessibilityEventNotification(accessibilityEventMask);
        }
    } else {
        PrintDebugString("[ERROR]: Failed to initiate IPC with newly created JavaVM!!!");
        return FALSE;
    }

    PrintDebugString("[INFO]:   Success!!  We rendezvoused with the JavaDLL");
    return returnVal;
}

// -----------------------

/**
 * sendPackage - uses SendMessage(WM_COPYDATA) to do IPC messaging
 *               with the Java AccessBridge DLL
 *
 *               NOTE: WM_COPYDATA is only for one-way IPC; there
 *               is now way to return parameters (especially big ones)
 *               Use sendMemoryPackage() to do that!
 */
void
WinAccessBridge::sendPackage(char *buffer, long bufsize, HWND destWindow) {
    COPYDATASTRUCT toCopy;
    toCopy.dwData = 0;          // 32-bits we could use for something...
    toCopy.cbData = bufsize;
    toCopy.lpData = buffer;

    SendMessage(destWindow, WM_COPYDATA, (WPARAM) dialogWindow, (LPARAM) &toCopy);
}


/**
 * sendMemoryPackage - uses Memory-Mapped files to do IPC messaging
 *                     with the Java AccessBridge DLL, informing the
 *                     Java AccessBridge DLL via SendMessage that something
 *                     is waiting for it in the shared file...
 *
 *                     In the SendMessage call, the third param (WPARAM) is
 *                     the source HWND (theDialogWindow in this case), and
 *                     the fourth param (LPARAM) is the size in bytes of
 *                     the package put into shared memory.
 *
 */
BOOL
WinAccessBridge::sendMemoryPackage(char *buffer, long bufsize, HWND destWindow) {
    if ((AccessBridgeJavaVMInstance *) 0 == javaVMs) {
        return FALSE;
    }
    AccessBridgeJavaVMInstance *ourABJavaVMInstance;
    ourABJavaVMInstance = javaVMs->findABJavaVMInstanceFromJavaHWND(destWindow);
    if (ourABJavaVMInstance != (AccessBridgeJavaVMInstance *) 0) {
        if (!ourABJavaVMInstance->sendMemoryPackage(buffer, bufsize)) {
            // return falue to the caller
            memset(buffer, 0, bufsize);
            return FALSE;
        }
    } else {
        PrintDebugString("[ERROR]: sending memory package: couldn't find destWindow");
        return FALSE;
    }
    return TRUE;
}


/**
 * queuePackage - put a package onto the queue for latter processing
 *
 */
BOOL
WinAccessBridge::queuePackage(char *buffer, long bufsize) {
    PrintDebugString("[INFO]:  in WinAccessBridge::queuePackage(%p, %d)", buffer, bufsize);

    AccessBridgeQueueElement *element = new AccessBridgeQueueElement(buffer, bufsize);

    messageQueue->add(element);
    PostMessage(dialogWindow, AB_MESSAGE_QUEUED, (WPARAM) 0, (LPARAM) 0);
    return TRUE;
}


/**
 * receiveAQueuedPackage - remove a pending packge from the queue and
 *                         handle it. If the queue is busy, post a
 *                         message to self to retrieve it later
 *
 */
BOOL
WinAccessBridge::receiveAQueuedPackage() {
    AccessBridgeQueueElement *element = NULL;

    PrintDebugString("[INFO]: in WinAccessBridge::receiveAQueuedPackage()");

    // ensure against re-entrancy problems...
    if (messageQueue->getRemoveLockSetting() == FALSE) {
        messageQueue->setRemoveLock(TRUE);

        PrintDebugString("[INFO]:  dequeueing message");

        QueueReturns result = messageQueue->remove(&element);

        switch (result) {

        case cQueueBroken:
            PrintDebugString("[ERROR]: Queue seems to be broken!");
            messageQueue->setRemoveLock(FALSE);
            return FALSE;

        case cMoreMessages:
        case cQueueEmpty:
            if (element != (AccessBridgeQueueElement *) 0) {
                PrintDebugString("[INFO]:  found one; sending it!");
                processPackage(element->buffer, element->bufsize);
                delete element;
            } else {
                PrintDebugString("[WARN]:   ODD... element == 0!");
                return FALSE;
            }
            break;

        case cQueueInUse:
            PrintDebugString("[WARN]:  Queue in use, will try again later...");
            PostMessage(dialogWindow, AB_MESSAGE_QUEUED, (WPARAM) 0, (LPARAM) 0);
            break;

        default:
            messageQueue->setRemoveLock(FALSE);
            return FALSE;       // should never get something we don't recognize!
        }
    } else {
        PrintDebugString("[WARN]:  unable to dequeue message; remove lock is set");
        PostMessage(dialogWindow, AB_MESSAGE_QUEUED, (WPARAM) 0, (LPARAM) 0); // Fix for 6995891
    }

    messageQueue->setRemoveLock(FALSE);
    return TRUE;
}

// -----------------------

/**
 * preProcessPackage
 *              - do triage on incoming packages; queue some, deal with others
 *
 */
void
WinAccessBridge::preProcessPackage(char *buffer, long bufsize) {
    PrintDebugString("[INFO]: PreProcessing package sent from Java:");

    PackageType *type = (PackageType *) buffer;

    switch (*type) {

    PrintDebugString("[INFO]:    type == %X", *type);

    // event packages all get queued for later handling
    //case cPropertyChangePackage:
    case cJavaShutdownPackage:
    case cFocusGainedPackage:
    case cFocusLostPackage:
    case cCaretUpdatePackage:
    case cMouseClickedPackage:
    case cMouseEnteredPackage:
    case cMouseExitedPackage:
    case cMousePressedPackage:
    case cMouseReleasedPackage:
    case cMenuCanceledPackage:
    case cMenuDeselectedPackage:
    case cMenuSelectedPackage:
    case cPopupMenuCanceledPackage:
    case cPopupMenuWillBecomeInvisiblePackage:
    case cPopupMenuWillBecomeVisiblePackage:

    case cPropertyCaretChangePackage:
    case cPropertyDescriptionChangePackage:
    case cPropertyNameChangePackage:
    case cPropertySelectionChangePackage:
    case cPropertyStateChangePackage:
    case cPropertyTextChangePackage:
    case cPropertyValueChangePackage:
    case cPropertyVisibleDataChangePackage:
    case cPropertyChildChangePackage:
    case cPropertyActiveDescendentChangePackage:

    case cPropertyTableModelChangePackage:

        queuePackage(buffer, bufsize);
        break;

        // perhaps there will be some other packages to process at some point... //

    default:
        PrintDebugString("[ERROR]:   processing FAILED!! -> don't know how to handle type = %X", *type);
        break;
    }

    PrintDebugString("[INFO]:    package preprocessing completed");
}


#define DISPATCH_EVENT_PACKAGE(packageID, eventPackage, fireEventMethod)            \
    case packageID:                                                                 \
        if (bufsize == sizeof(PackageType) + sizeof(eventPackage)) {                \
            eventPackage *pkg =                                                     \
                (eventPackage *) (buffer + sizeof(PackageType));                    \
            PrintDebugString("[INFO]:    begin callback to AT, type == %X", *type);         \
                theWindowsAccessBridge->eventHandler->fireEventMethod(              \
                    pkg->vmID, pkg->Event, pkg->AccessibleContextSource);           \
                PrintDebugString("[INFO]:    event callback complete!");                    \
        } else {                                                                    \
            PrintDebugString("[ERROR]:   processing FAILED!! -> bufsize = %d; expectation = %d", \
                bufsize, sizeof(PackageType) + sizeof(eventPackage));               \
        }                                                                           \
        break;

#define DISPATCH_PROPERTY_CHANGE_PACKAGE(packageID, eventPackage, fireEventMethod, oldValue, newValue) \
    case packageID:                                                                 \
        if (bufsize == sizeof(PackageType) + sizeof(eventPackage)) {                \
            eventPackage *pkg =                                                     \
                (eventPackage *) (buffer + sizeof(PackageType));                    \
            PrintDebugString("[INFO]:    begin callback to AT, type == %X", *type);         \
            theWindowsAccessBridge->eventHandler->fireEventMethod(                  \
                pkg->vmID, pkg->Event, pkg->AccessibleContextSource,                \
                pkg->oldValue, pkg->newValue);                                      \
            PrintDebugString("[INFO]:    event callback complete!");                        \
        } else {                                                                    \
            PrintDebugString("[ERROR]:   processing FAILED!! -> bufsize = %d; expectation = %d", \
                bufsize, sizeof(PackageType) + sizeof(eventPackage));               \
        }                                                                           \
        break;

#define DISPATCH_PROPERTY_TABLE_MODEL_CHANGE_PACKAGE(packageID, eventPackage, fireEventMethod, oldValue, newValue) \
    case packageID:                                                                 \
        if (bufsize == sizeof(PackageType) + sizeof(eventPackage)) {                \
            eventPackage *pkg =                                                     \
                (eventPackage *) (buffer + sizeof(PackageType));                    \
            PrintDebugString("[INFO]:    begin callback to AT, type == %X", *type);         \
            theWindowsAccessBridge->eventHandler->fireEventMethod(                  \
                pkg->vmID, pkg->Event, pkg->AccessibleContextSource,                \
                pkg->oldValue, pkg->newValue);                                      \
            PrintDebugString("[INFO]:    event callback complete!");                        \
        } else {                                                                    \
            PrintDebugString("[ERROR]:    processing FAILED!! -> bufsize = %d; expectation = %d", \
                bufsize, sizeof(PackageType) + sizeof(eventPackage));                \
        }                                                                            \
        break;

/**
 * processPackage - processes the output of SendMessage(WM_COPYDATA)
 *                  to do IPC messaging with the Java AccessBridge DLL
 *
 */
void
WinAccessBridge::processPackage(char *buffer, long bufsize) {
    PrintDebugString("[INFO]: WinAccessBridge::Processing package sent from Java:");

    PackageType *type = (PackageType *) buffer;

    switch (*type) {

    PrintDebugString("[INFO]:    type == %X", *type);

    case cJavaShutdownPackage:
        PrintDebugString("[INFO]:    type == cJavaShutdownPackage");
        if (bufsize == sizeof(PackageType) + sizeof(JavaShutdownPackage)) {
            JavaShutdownPackage *pkg =
                (JavaShutdownPackage *) (buffer + sizeof(PackageType));
            theWindowsAccessBridge->eventHandler->fireJavaShutdown(pkg->vmID);
            PrintDebugString("[INFO]:    event callback complete!");
            PrintDebugString("[INFO]:    event fired!");
        } else {
            PrintDebugString("[ERROR]:    processing FAILED!! -> bufsize = %d; expectation = %d",
                             bufsize, sizeof(PackageType) + sizeof(JavaShutdownPackage));
        }
        break;


        DISPATCH_EVENT_PACKAGE(cFocusGainedPackage, FocusGainedPackage, fireFocusGained);
        DISPATCH_EVENT_PACKAGE(cFocusLostPackage, FocusLostPackage, fireFocusLost);

        DISPATCH_EVENT_PACKAGE(cCaretUpdatePackage, CaretUpdatePackage, fireCaretUpdate);

        DISPATCH_EVENT_PACKAGE(cMouseClickedPackage, MouseClickedPackage, fireMouseClicked);
        DISPATCH_EVENT_PACKAGE(cMouseEnteredPackage, MouseEnteredPackage, fireMouseEntered);
        DISPATCH_EVENT_PACKAGE(cMouseExitedPackage, MouseExitedPackage, fireMouseExited);
        DISPATCH_EVENT_PACKAGE(cMousePressedPackage, MousePressedPackage, fireMousePressed);
        DISPATCH_EVENT_PACKAGE(cMouseReleasedPackage, MouseReleasedPackage, fireMouseReleased);

        DISPATCH_EVENT_PACKAGE(cMenuCanceledPackage, MenuCanceledPackage, fireMenuCanceled);
        DISPATCH_EVENT_PACKAGE(cMenuDeselectedPackage, MenuDeselectedPackage, fireMenuDeselected);
        DISPATCH_EVENT_PACKAGE(cMenuSelectedPackage, MenuSelectedPackage, fireMenuSelected);
        DISPATCH_EVENT_PACKAGE(cPopupMenuCanceledPackage, PopupMenuCanceledPackage, firePopupMenuCanceled);
        DISPATCH_EVENT_PACKAGE(cPopupMenuWillBecomeInvisiblePackage, PopupMenuWillBecomeInvisiblePackage, firePopupMenuWillBecomeInvisible);
        DISPATCH_EVENT_PACKAGE(cPopupMenuWillBecomeVisiblePackage, PopupMenuWillBecomeVisiblePackage, firePopupMenuWillBecomeVisible);

        DISPATCH_PROPERTY_CHANGE_PACKAGE(cPropertyNameChangePackage,
                                         PropertyNameChangePackage,
                                         firePropertyNameChange, oldName, newName)
            DISPATCH_PROPERTY_CHANGE_PACKAGE(cPropertyDescriptionChangePackage,
                                             PropertyDescriptionChangePackage,
                                             firePropertyDescriptionChange,
                                             oldDescription, newDescription)
            DISPATCH_PROPERTY_CHANGE_PACKAGE(cPropertyStateChangePackage,
                                             PropertyStateChangePackage,
                                             firePropertyStateChange, oldState, newState)
            DISPATCH_PROPERTY_CHANGE_PACKAGE(cPropertyValueChangePackage,
                                             PropertyValueChangePackage,
                                             firePropertyValueChange, oldValue, newValue)
            DISPATCH_EVENT_PACKAGE(cPropertySelectionChangePackage,
                                   PropertySelectionChangePackage, firePropertySelectionChange)
            DISPATCH_EVENT_PACKAGE(cPropertyTextChangePackage,
                                   PropertyTextChangePackage, firePropertyTextChange)
            DISPATCH_PROPERTY_CHANGE_PACKAGE(cPropertyCaretChangePackage,
                                             PropertyCaretChangePackage,
                                             firePropertyCaretChange, oldPosition, newPosition)
            DISPATCH_EVENT_PACKAGE(cPropertyVisibleDataChangePackage,
                                   PropertyVisibleDataChangePackage, firePropertyVisibleDataChange)
            DISPATCH_PROPERTY_CHANGE_PACKAGE(cPropertyChildChangePackage,
                                             PropertyChildChangePackage,
                                             firePropertyChildChange,
                                             oldChildAccessibleContext,
                                             newChildAccessibleContext)
            DISPATCH_PROPERTY_CHANGE_PACKAGE(cPropertyActiveDescendentChangePackage,
                                             PropertyActiveDescendentChangePackage,
                                             firePropertyActiveDescendentChange,
                                             oldActiveDescendentAccessibleContext,
                                             newActiveDescendentAccessibleContext)

            DISPATCH_PROPERTY_TABLE_MODEL_CHANGE_PACKAGE(cPropertyTableModelChangePackage,
                                                         PropertyTableModelChangePackage,
                                                         firePropertyTableModelChange,
                                                         oldValue, newValue)


            default:
        PrintDebugString("[ERROR]:    processing FAILED!! -> don't know how to handle type = %X", *type);
        break;
    }

    PrintDebugString("[INFO]:    package processing completed");
}


// -----------------------------

void
WinAccessBridge::JavaVMDestroyed(HWND VMBridgeDLLWindow) {
    PrintDebugString("[INFO]: ***** WinAccessBridge::JavaVMDestroyed(%p)", VMBridgeDLLWindow);

    if ((AccessBridgeJavaVMInstance *) 0 == javaVMs) {
        return;
    }

    isVMInstanceChainInUse = true;
    AccessBridgeJavaVMInstance *currentVM = javaVMs;
    AccessBridgeJavaVMInstance *previousVM = javaVMs;
    if (javaVMs->javaAccessBridgeWindow == VMBridgeDLLWindow) {
        javaVMs = javaVMs->nextJVMInstance;
        delete currentVM;

        PrintDebugString("[INFO]:   data structures successfully removed");

        // [[[FIXME]]] inform Windows AT that a JVM went away,
        // and that any jobjects it's got lying around for that JVM
        // are now invalid

    } else {
        while (currentVM != (AccessBridgeJavaVMInstance *) 0) {
            if (currentVM->javaAccessBridgeWindow == VMBridgeDLLWindow) {
                previousVM->nextJVMInstance = currentVM->nextJVMInstance;
                delete currentVM;

                PrintDebugString("[INFO]:   data structures successfully removed");

                // [[[FIXME]]] inform Windows AT that a JVM went away,
                // and that any jobjects it's got lying around for that JVM
                // are now invalid
                isVMInstanceChainInUse = false;
                return;
            } else {
                previousVM = currentVM;
                currentVM = currentVM->nextJVMInstance;
            }
        }
        PrintDebugString("[ERROR]: couldn't find matching data structures!");
    }
    isVMInstanceChainInUse = false;
}

// -----------------------

/**
 * releaseJavaObject - lets the JavaVM know it can release the Java Object
 *
 * Note: once you have made this call, the JavaVM will garbage collect
 * the jobject you pass in.  If you later use that jobject in another
 * call, you will cause all maner of havoc!
 *
 */
void
WinAccessBridge::releaseJavaObject(long vmID, JOBJECT64 object) {
#ifdef ACCESSBRIDGE_ARCH_LEGACY // JOBJECT64 is jobject (32 bit pointer)
    PrintDebugString("[INFO]: WinAccessBridge::releaseJavaObject(%X, %p)", vmID, object);
#else // JOBJECT64 is jlong (64 bit)
    PrintDebugString("[INFO]: WinAccessBridge::releaseJavaObject(%X, %016I64X)", vmID, object);
#endif
    if ((AccessBridgeJavaVMInstance *) 0 == javaVMs) {
        return;
    }
    char buffer[sizeof(PackageType) + sizeof(ReleaseJavaObjectPackage)];
    PackageType *type = (PackageType *) buffer;
    ReleaseJavaObjectPackage *pkg = (ReleaseJavaObjectPackage *) (buffer + sizeof(PackageType));
    *type = cReleaseJavaObjectPackage;
    pkg->vmID = vmID;
    pkg->object = object;

    HWND destABWindow = javaVMs->findAccessBridgeWindow(vmID);
    if (destABWindow != (HWND) 0) {
        sendPackage(buffer, sizeof(buffer), destABWindow);              // no return values!
    }
}

// -----------------------

/**
 * getVersionInfo - fill the AccessBridgeVersionInfo struct
 *
 */
BOOL
WinAccessBridge::getVersionInfo(long vmID, AccessBridgeVersionInfo *info) {
    if ((AccessBridgeJavaVMInstance *) 0 == javaVMs) {
        return FALSE;
    }
    char buffer[sizeof(PackageType) + sizeof(GetAccessBridgeVersionPackage)];
    PackageType *type = (PackageType *) buffer;
    GetAccessBridgeVersionPackage *pkg = (GetAccessBridgeVersionPackage *) (buffer + sizeof(PackageType));
    *type = cGetAccessBridgeVersionPackage;
    pkg->vmID = vmID;

    PrintDebugString("[INFO]: WinAccessBridge::getVersionInfo(%X, )", vmID);
    HWND destABWindow = javaVMs->findAccessBridgeWindow(vmID);
    if (destABWindow != (HWND) 0) {
        if (sendMemoryPackage(buffer, sizeof(buffer), destABWindow) == TRUE) {
            memcpy(info, &(pkg->rVersionInfo), sizeof(AccessBridgeVersionInfo));
            PrintDebugString("[INFO]:   VMversion: %ls\n"\
                             "          bridgeJavaClassVersion: %ls\n"\
                             "          bridgeJavaDLLVersion: %ls\n"\
                             "          bridgeWinDLLVersion: %ls\n"\
            , info->VMversion, info->bridgeJavaClassVersion, info->bridgeJavaDLLVersion, info->bridgeWinDLLVersion);
            return TRUE;
        }
    }
    return FALSE;
}


/********** Window-related routines ***********************************/

/**
 * isJavaWindow - returns TRUE if the HWND is a top-level Java Window
 *
 * Note: just because the Windnow is a top-level Java window, that doesn't
 * mean that it is accessible.  Call getAccessibleContextFromHWND(HWND) to get the
 * AccessibleContext, if any, for an HWND that is a Java Window.
 *
 */
BOOL
WinAccessBridge::isJavaWindow(HWND window) {
    HWND hwnd;

    if ((AccessBridgeJavaVMInstance *) 0 == javaVMs) {
        return FALSE;
    }

    // quick check to see if 'window' is top-level; if not, it's not interesting...
    // [[[FIXME]]] is this for sure an OK optimization?
    hwnd = getTopLevelHWND(window);
    if (hwnd == (HWND) NULL) {
        return FALSE;
    }

    PrintDebugString("[INFO]: In WinAccessBridge::isJavaWindow");



    char buffer[sizeof(PackageType) + sizeof(IsJavaWindowPackage)];
    PackageType *type = (PackageType *) buffer;
    IsJavaWindowPackage *pkg = (IsJavaWindowPackage *) (buffer + sizeof(PackageType));
    *type = cIsJavaWindowPackage;
    pkg->window = (jint) window;

    PrintDebugString("[INFO]: WinAccessBridge::isJavaWindow(%p)", window);

    isVMInstanceChainInUse = true;
    AccessBridgeJavaVMInstance *current = javaVMs;
    while (current != (AccessBridgeJavaVMInstance *) 0) {
        if (sendMemoryPackage(buffer, sizeof(buffer), current->javaAccessBridgeWindow) == TRUE) {
            if (pkg->rResult != 0) {
                isVMInstanceChainInUse = false;
                return TRUE;
            }
        }
        current = current->nextJVMInstance;
    }
    isVMInstanceChainInUse = false;
    return FALSE;


    /*
      char classname[256];
      HWND hwnd;

      hwnd = getTopLevelHWND(window);
      if (hwnd == (HWND) NULL) {
      return FALSE;
      }
      GetClassName(hwnd, classname, 256);

      if (strstr(classname, "AwtFrame") != 0) {
      return TRUE;
      } else if (strstr(classname, "AwtWindow") != 0) {
      return TRUE;
      } else if (strstr(classname, "AwtDialog") != 0) {
      return TRUE;
      }
    */
    // JDK 1.4 introduces new (and changes old) classnames
    /*
      else if (strstr(classname, "SunAwtToolkit") != 0) {
      return TRUE;
      } else if (strstr(classname, "javax.swing.JFrame") != 0) {
      return TRUE;
      }
    */

    return FALSE;
}

/**
 * isSameObject - returns TRUE if the two object references refer to
 *     the same object. Otherwise, this method returns FALSE:
 */
BOOL
WinAccessBridge::isSameObject(long vmID, JOBJECT64 obj1, JOBJECT64 obj2) {

#ifdef ACCESSBRIDGE_ARCH_LEGACY // JOBJECT64 is jobject (32 bit pointer)
    PrintDebugString("[INFO]: WinAccessBridge::isSameObject(%p %p)", obj1, obj2);
#else // JOBJECT64 is jlong (64 bit)
    PrintDebugString("[INFO]: WinAccessBridge::isSameObject(%016I64X %016I64X)", obj1, obj2);
#endif

    if ((AccessBridgeJavaVMInstance *) 0 == javaVMs) {
        return FALSE;
    }

    char buffer[sizeof(PackageType) + sizeof(IsSameObjectPackage)];
    PackageType *type = (PackageType *) buffer;
    IsSameObjectPackage *pkg = (IsSameObjectPackage *) (buffer + sizeof(PackageType));
    *type = cIsSameObjectPackage;
    pkg->vmID = vmID;
    pkg->obj1 = obj1;
    pkg->obj2 = obj2;

    HWND destABWindow = javaVMs->findAccessBridgeWindow(pkg->vmID);
    if (sendMemoryPackage(buffer, sizeof(buffer), destABWindow) == TRUE) {
        if (pkg->rResult != 0) {
            PrintDebugString("[INFO]:   WinAccessBridge::isSameObject returning TRUE (same object)");
            return TRUE;
        } else {
            PrintDebugString("[INFO]:   WinAccessBridge::isSameObject returning FALSE (different object)");
            return FALSE;
        }
    }
    PrintDebugString("[ERROR]:   WinAccessBridge::isSameObject returning FALSE (sendMemoryPackage failed)");
    return FALSE;
}

/**
 * FromHWND - returns the AccessibleContext jobject for the HWND
 *
 * Note: this routine can return null, even if the HWND is a Java Window,
 * because the Java Window may not be accessible.
 *
 */
BOOL
WinAccessBridge::getAccessibleContextFromHWND(HWND window, long *vmID, JOBJECT64 *AccessibleContext) {
    if ((AccessBridgeJavaVMInstance *) 0 == javaVMs) {
        return FALSE;
    }

    char buffer[sizeof(PackageType) + sizeof(GetAccessibleContextFromHWNDPackage)];
    PackageType *type = (PackageType *) buffer;
    GetAccessibleContextFromHWNDPackage *pkg = (GetAccessibleContextFromHWNDPackage *) (buffer + sizeof(PackageType));
    *type = cGetAccessibleContextFromHWNDPackage;
    pkg->window = (jint) window;

    PrintDebugString("[INFO]: WinAccessBridge::getAccessibleContextFromHWND(%p, )", window);

    DEBUG_CODE(pkg->rVMID = (long ) 0x01010101);
    DEBUG_CODE(pkg->rAccessibleContext = (JOBJECT64) 0x01010101);

    isVMInstanceChainInUse = true;
    AccessBridgeJavaVMInstance *current = javaVMs;
    while (current != (AccessBridgeJavaVMInstance *) 0) {

        if (sendMemoryPackage(buffer, sizeof(buffer), current->javaAccessBridgeWindow) == TRUE) {
            if (pkg->rAccessibleContext != 0) {
                *vmID = pkg->rVMID;
                *AccessibleContext = (JOBJECT64)pkg->rAccessibleContext;
                PrintDebugString("[INFO]:     current->vmID = %X, pkg->rVMID = %X", current->vmID, pkg->rVMID);
#ifdef ACCESSBRIDGE_ARCH_LEGACY // JOBJECT64 is jobject (32 bit pointer)
                PrintDebugString("[INFO]:     pkg->rAccessibleContext = %p", pkg->rAccessibleContext);
#else // JOBJECT64 is jlong (64 bit)
                PrintDebugString("[INFO]:     pkg->rAccessibleContext = %016I64X", pkg->rAccessibleContext);
#endif
                if (pkg->rVMID != current->vmID) {
                    PrintDebugString("[ERROR]: getAccessibleContextFromHWND vmIDs don't match!");
                    isVMInstanceChainInUse = false;
                    return FALSE;
                }
                isVMInstanceChainInUse = false;
                return TRUE;
            }
        }
        current = current->nextJVMInstance;
    }
    isVMInstanceChainInUse = false;

    // This isn't really an error; it just means that the HWND was for a non-Java
    // window.  It's also possible the HWND was for a Java window but the JVM has
    // since been shut down and sendMemoryPackage returned FALSE.
    PrintDebugString("[ERROR]: getAccessibleContextFromHWND no matching HWND found!");
    return FALSE;
}

/**
 * Returns the HWND for an AccessibleContext.  Returns (HWND)0 on error.
 */
HWND
WinAccessBridge::getHWNDFromAccessibleContext(long vmID, JOBJECT64 accessibleContext) {
    PrintDebugString("[INFO]:   in WinAccessBridge::getHWNDFromAccessibleContext");
    if ((AccessBridgeJavaVMInstance *) 0 == javaVMs) {
        return (HWND)0;
    }

    char buffer[sizeof(PackageType) + sizeof(GetHWNDFromAccessibleContextPackage)];
    PackageType *type = (PackageType *) buffer;
    GetHWNDFromAccessibleContextPackage *pkg = (GetHWNDFromAccessibleContextPackage *) (buffer + sizeof(PackageType));
    *type = cGetHWNDFromAccessibleContextPackage;
    pkg->accessibleContext = accessibleContext;

#ifdef ACCESSBRIDGE_ARCH_LEGACY // JOBJECT64 is jobject (32 bit pointer)
    PrintDebugString("[INFO]: WinAccessBridge::getHWNDFromAccessibleContext(%p)", accessibleContext);
#else // JOBJECT64 is jlong (64 bit)
    PrintDebugString("[INFO]: WinAccessBridge::getHWNDFromAccessibleContext(%016I64X)", accessibleContext);
#endif

    HWND destABWindow = javaVMs->findAccessBridgeWindow(vmID);
    if (destABWindow != (HWND) 0) {
        if (sendMemoryPackage(buffer, sizeof(buffer), destABWindow) == TRUE) {
            return ((HWND)ABLongToHandle(pkg->rHWND));
        }
    }
    return (HWND)0;
}

/********** AccessibleContext routines ***********************************/

/**
 * Walk through Java Windows, in front-to-back Z-order.
 * If NULL is passed it, this function starts at the top.
 *
 */
HWND
WinAccessBridge::getNextJavaWindow(HWND previous) {
    HWND current = previous;
    if (current == NULL) {
        current = GetTopWindow(NULL);
    } else {
        current = GetNextWindow(current, GW_HWNDNEXT);
    }
    while (current != NULL) {
        if (isJavaWindow(current)) {
            return current;
        }
        current = GetNextWindow(current, GW_HWNDNEXT);
    }
    return NULL;
}


/**
 * getAccessibleContextAt - performs the Java code:
 *   Accessible a = EventQueueMonitor.getAccessibleAt(x, y);
 *       return a.getAccessibleContext();
 *
 * Note: this call explicitly goes through the AccessBridge,
 * so that the AccessBridge can hide expected changes in how this functions
 * between JDK 1.1.x w/AccessibilityUtility classes, and JDK 1.2, when some
 * of this functionality may be built into the platform
 *
 */
BOOL
WinAccessBridge::getAccessibleContextAt(long vmID, JOBJECT64 AccessibleContextParent,
                                        jint x, jint y, JOBJECT64 *AccessibleContext) {
    if ((AccessBridgeJavaVMInstance *) 0 == javaVMs) {
        return FALSE;
    }

    char buffer[sizeof(PackageType) + sizeof(GetAccessibleContextAtPackage)];
    PackageType *type = (PackageType *) buffer;
    GetAccessibleContextAtPackage *pkg = (GetAccessibleContextAtPackage *) (buffer + sizeof(PackageType));
    *type = cGetAccessibleContextAtPackage;
    pkg->vmID = vmID;
    pkg->AccessibleContext = AccessibleContextParent;
    pkg->x = x;
    pkg->y = y;

    PrintDebugString("[INFO]: WinAccessBridge::getAccessibleContextAt(%X, %p, %d, %c)", vmID, AccessibleContextParent, x, y);
    HWND destABWindow = javaVMs->findAccessBridgeWindow(pkg->vmID);
    if (sendMemoryPackage(buffer, sizeof(buffer), destABWindow) == TRUE) {
        *AccessibleContext = pkg->rAccessibleContext;
        return TRUE;
    }

    return FALSE;
}


/**
 * getAccessibleContextWithFocus - performs the Java code:
 *   Accessible a = Translator.getAccessible(SwingEventMonitor.getComponentWithFocus());
 *   return a.getAccessibleContext();
 *
 * Note: this call explicitly goes through the AccessBridge,
 * so that the AccessBridge can hide expected changes in how this functions
 * between JDK 1.1.x w/AccessibilityUtility classes, and JDK 1.2, when some
 * of this functionality may be built into the platform
 *
 */
BOOL
WinAccessBridge::getAccessibleContextWithFocus(HWND window, long *vmID, JOBJECT64 *AccessibleContext) {

    if ((AccessBridgeJavaVMInstance *) 0 == javaVMs) {
        return FALSE;
    }
    char buffer[sizeof(PackageType) + sizeof(GetAccessibleContextWithFocusPackage)];
    PackageType *type = (PackageType *) buffer;
    GetAccessibleContextWithFocusPackage *pkg = (GetAccessibleContextWithFocusPackage *) (buffer + sizeof(PackageType));
    *type = cGetAccessibleContextWithFocusPackage;

    PrintDebugString("[INFO]: WinAccessBridge::getAccessibleContextWithFocus(%p, %X, )", window, vmID);
    // find vmID, etc. from HWND; ask that VM for the AC w/Focus
    HWND pkgVMID;
    if (getAccessibleContextFromHWND(window, (long *)&(pkgVMID), &(pkg->rAccessibleContext)) == TRUE) {
        HWND destABWindow = javaVMs->findAccessBridgeWindow((long)pkgVMID);     // ineffecient [[[FIXME]]]
        if (sendMemoryPackage(buffer, sizeof(buffer), destABWindow) == TRUE) {
            *vmID = pkg->rVMID;
            *AccessibleContext = pkg->rAccessibleContext;
            return TRUE;
        }
    }

    return FALSE;
}

/**
 * getAccessibleContextInfo - fills a struct with a bunch of information
 * contained in the Java Accessibility API
 *
 *
 * Note: if the AccessibleContext parameter is bogus, this call will blow up
 */
BOOL
WinAccessBridge::getAccessibleContextInfo(long vmID,
                                          JOBJECT64 accessibleContext,
                                          AccessibleContextInfo *info) {
    if ((AccessBridgeJavaVMInstance *) 0 == javaVMs) {
        return FALSE;
    }
    char buffer[sizeof(PackageType) + sizeof(GetAccessibleContextInfoPackage)];
    PackageType *type = (PackageType *) buffer;
    GetAccessibleContextInfoPackage *pkg = (GetAccessibleContextInfoPackage *) (buffer + sizeof(PackageType));
    *type = cGetAccessibleContextInfoPackage;
    pkg->vmID = vmID;
    pkg->AccessibleContext = accessibleContext;

#ifdef ACCESSBRIDGE_ARCH_LEGACY // JOBJECT64 is jobject (32 bit pointer)
    PrintDebugString("[INFO]: WinAccessBridge::getAccessibleContextInfo(%X, %p, )", vmID, accessibleContext);
#else // JOBJECT64 is jlong (64 bit)
    PrintDebugString("[INFO]: WinAccessBridge::getAccessibleContextInfo(%X, %016I64X, )", vmID, accessibleContext);
#endif
    // need to call only the HWND/VM that contains this AC
    HWND destABWindow = javaVMs->findAccessBridgeWindow(vmID);
    if (destABWindow != (HWND) 0) {
        if (sendMemoryPackage(buffer, sizeof(buffer), destABWindow) == TRUE) {
            memcpy(info, &(pkg->rAccessibleContextInfo), sizeof(AccessibleContextInfo));
            PrintDebugString("[INFO]:   name: %ls\n"\
                             "          description: %ls\n"\
                             "          role: %ls\n"\
                             "          role_en_US: %ls\n"\
                             "          states: %ls\n"\
                             "          states_en_US: %ls\n"\
            , info->name, info->description, info->role, info->role_en_US, info->states, info->states_en_US);
            return TRUE;
        }
    }

    return FALSE;
}

/**
 * getAccessibleChildFromContext - performs the Java code:
 *   Accessible child = ac.getAccessibleChild(i);
 *   return child.getAccessibleContext();
 *
 * Note: this call explicitly goes through the AccessBridge,
 * so that the AccessBridge can hide expected changes in how this functions
 * between JDK 1.1.x w/AccessibilityUtility classes, and JDK 1.2, when some
 * of this functionality may be built into the platform
 *
 */
JOBJECT64
WinAccessBridge::getAccessibleChildFromContext(long vmID,
                                               JOBJECT64 AccessibleContext,
                                               jint childIndex) {
    if ((AccessBridgeJavaVMInstance *) 0 == javaVMs) {
        return (JOBJECT64)0;
    }
    char buffer[sizeof(PackageType) + sizeof(GetAccessibleChildFromContextPackage)];
    PackageType *type = (PackageType *) buffer;
    GetAccessibleChildFromContextPackage *pkg = (GetAccessibleChildFromContextPackage *) (buffer + sizeof(PackageType));
    *type = cGetAccessibleChildFromContextPackage;
    pkg->vmID = vmID;
    pkg->AccessibleContext = AccessibleContext;
    pkg->childIndex = childIndex;

#ifdef ACCESSBRIDGE_ARCH_LEGACY // JOBJECT64 is jobject (32 bit pointer)
    PrintDebugString("[INFO]: WinAccessBridge::getAccessibleChildFromContext(%X, %p, %d)", vmID, AccessibleContext, childIndex);
#else // JOBJECT64 is jlong (64 bit)
    PrintDebugString("[INFO]: WinAccessBridge::getAccessibleChildFromContext(%X, %016I64X, %d)", vmID, AccessibleContext, childIndex);
#endif
    // need to call only the HWND/VM that contains this AC
    HWND destABWindow = javaVMs->findAccessBridgeWindow(vmID);
    if (destABWindow != (HWND) 0) {
        if (sendMemoryPackage(buffer, sizeof(buffer), destABWindow) == TRUE) {
            return pkg->rAccessibleContext;
        }
    }

    return (JOBJECT64) 0;
}

/**
 * getAccessibleParentFromContext - returns the parent AccessibleContext jobject
 *
 * Note: this may be null, if the AccessibleContext passed in is a top-level
 * window, then it has no parent.
 *
 */
JOBJECT64
WinAccessBridge::getAccessibleParentFromContext(long vmID,
                                                JOBJECT64 AccessibleContext) {
    if ((AccessBridgeJavaVMInstance *) 0 == javaVMs) {
        return (JOBJECT64)0;
    }
    char buffer[sizeof(PackageType) + sizeof(GetAccessibleParentFromContextPackage)];
    PackageType *type = (PackageType *) buffer;
    GetAccessibleParentFromContextPackage *pkg = (GetAccessibleParentFromContextPackage *) (buffer + sizeof(PackageType));
    *type = cGetAccessibleParentFromContextPackage;
    pkg->vmID = vmID;
    pkg->AccessibleContext = AccessibleContext;

    PrintDebugString("[INFO]: WinAccessBridge::getAccessibleParentFromContext(%X, %p)", vmID, AccessibleContext);
    // need to call only the HWND/VM that contains this AC
    HWND destABWindow = javaVMs->findAccessBridgeWindow(vmID);
    if (destABWindow != (HWND) 0) {
        if (sendMemoryPackage(buffer, sizeof(buffer), destABWindow) == TRUE) {
            return pkg->rAccessibleContext;
        }
    }

    return (JOBJECT64) 0;
}

/********** AccessibleTable routines ***********************************/

BOOL
WinAccessBridge::getAccessibleTableInfo(long vmID,
                                        JOBJECT64 accessibleContext,
                                        AccessibleTableInfo *tableInfo) {

#ifdef ACCESSBRIDGE_ARCH_LEGACY // JOBJECT64 is jobject (32 bit pointer)
    PrintDebugString("[INFO]: ##### WinAccessBridge::getAccessibleTableInfo(%X, %p, %p)", vmID, accessibleContext,
                     tableInfo);
#else // JOBJECT64 is jlong (64 bit)
    PrintDebugString("[INFO]: ##### WinAccessBridge::getAccessibleTableInfo(%X, %016I64X, %p)", vmID, accessibleContext,
                     tableInfo);
#endif

    if ((AccessBridgeJavaVMInstance *) 0 == javaVMs) {
        return FALSE;
    }
    char buffer[sizeof(PackageType) + sizeof(GetAccessibleTableInfoPackage)];
    PackageType *type = (PackageType *) buffer;
    GetAccessibleTableInfoPackage *pkg = (GetAccessibleTableInfoPackage *) (buffer + sizeof(PackageType));
    *type = cGetAccessibleTableInfoPackage;
    pkg->vmID = vmID;
    pkg->accessibleContext = accessibleContext;

    // need to call only the HWND/VM that contains this AC
    HWND destABWindow = javaVMs->findAccessBridgeWindow(vmID);
    if (destABWindow != (HWND) 0) {
        if (sendMemoryPackage(buffer, sizeof(buffer), destABWindow) == TRUE) {
            memcpy(tableInfo, &(pkg->rTableInfo), sizeof(AccessibleTableInfo));
            if (pkg->rTableInfo.rowCount != -1) {
                PrintDebugString("[INFO]:   ##### WinAccessBridge::getAccessibleTableInfo succeeded");
                return TRUE;
            }
        }
    }
    PrintDebugString("[ERROR]:   ##### WinAccessBridge::getAccessibleTableInfo failed");
    return FALSE;
}

BOOL
WinAccessBridge::getAccessibleTableCellInfo(long vmID, JOBJECT64 accessibleTable,
                                            jint row, jint column,
                                            AccessibleTableCellInfo *tableCellInfo) {

    PrintDebugString("[INFO]: ##### WinAccessBridge::getAccessibleTableCellInfo(%X, %p, %d, %d, %p)", vmID,
                     accessibleTable, row, column, tableCellInfo);

    if ((AccessBridgeJavaVMInstance *) 0 == javaVMs) {
        return FALSE;
    }

    char buffer[sizeof(PackageType) + sizeof(GetAccessibleTableCellInfoPackage)];
    PackageType *type = (PackageType *) buffer;
    GetAccessibleTableCellInfoPackage *pkg = (GetAccessibleTableCellInfoPackage *) (buffer + sizeof(PackageType));
    *type = cGetAccessibleTableCellInfoPackage;
    pkg->vmID = vmID;
    pkg->accessibleTable = accessibleTable;
    pkg->row = row;
    pkg->column = column;
    HWND destABWindow = javaVMs->findAccessBridgeWindow(vmID);

    if (destABWindow != (HWND) 0) {
        if (sendMemoryPackage(buffer, sizeof(buffer), destABWindow) == TRUE) {
            PrintDebugString("[INFO]:   XXXX pkg->rTableCellInfo.accessibleContext = %p", pkg->rTableCellInfo.accessibleContext);
            memcpy(tableCellInfo, &(pkg->rTableCellInfo), sizeof(AccessibleTableCellInfo));
            PrintDebugString("[INFO]:   ##### WinAccessBridge::getAccessibleTableCellInfo succeeded");
            return TRUE;
        }
    }
    PrintDebugString("[ERROR]:   ##### WinAccessBridge::getAccessibleTableCellInfo failed");
    return FALSE;
}


BOOL
WinAccessBridge::getAccessibleTableRowHeader(long vmID, JOBJECT64 accessibleContext, AccessibleTableInfo *tableInfo) {

#ifdef ACCESSBRIDGE_ARCH_LEGACY // JOBJECT64 is jobject (32 bit pointer)
    PrintDebugString("[INFO]: ##### WinAccessBridge::getAccessibleTableRowHeader(%X, %p)", vmID, accessibleContext);
#else // JOBJECT64 is jlong (64 bit)
    PrintDebugString("[INFO]: ##### WinAccessBridge::getAccessibleTableRowHeader(%X, %016I64X)", vmID, accessibleContext);
#endif

    if ((AccessBridgeJavaVMInstance *) 0 == javaVMs) {
        return FALSE;
    }
    char buffer[sizeof(PackageType) + sizeof(GetAccessibleTableRowHeaderPackage)];
    PackageType *type = (PackageType *) buffer;
    GetAccessibleTableRowHeaderPackage *pkg = (GetAccessibleTableRowHeaderPackage *) (buffer + sizeof(PackageType));
    *type = cGetAccessibleTableRowHeaderPackage;
    pkg->vmID = vmID;
    pkg->accessibleContext = accessibleContext;

    // need to call only the HWND/VM that contains this AC
    HWND destABWindow = javaVMs->findAccessBridgeWindow(vmID);
    if (destABWindow != (HWND) 0) {
        if (sendMemoryPackage(buffer, sizeof(buffer), destABWindow) == TRUE) {
            PrintDebugString("[INFO]:   ##### WinAccessBridge::getAccessibleTableRowHeader succeeded");
            memcpy(tableInfo, &(pkg->rTableInfo), sizeof(AccessibleTableInfo));
            return TRUE;
        }
    }
    PrintDebugString("[ERROR]:   ##### WinAccessBridge::getAccessibleTableRowHeader failed");
    return FALSE;
}

BOOL
WinAccessBridge::getAccessibleTableColumnHeader(long vmID, JOBJECT64 accessibleContext, AccessibleTableInfo *tableInfo) {

#ifdef ACCESSBRIDGE_ARCH_LEGACY // JOBJECT64 is jobject (32 bit pointer)
    PrintDebugString("[INFO]: ##### WinAccessBridge::getAccessibleTableColumnHeader(%X, %p)", vmID, accessibleContext);
#else // JOBJECT64 is jlong (64 bit)
    PrintDebugString("[INFO]: ##### WinAccessBridge::getAccessibleTableColumnHeader(%X, %016I64X)", vmID, accessibleContext);
#endif

    if ((AccessBridgeJavaVMInstance *) 0 == javaVMs) {
        return FALSE;
    }
    char buffer[sizeof(PackageType) + sizeof(GetAccessibleTableColumnHeaderPackage)];
    PackageType *type = (PackageType *) buffer;
    GetAccessibleTableColumnHeaderPackage *pkg = (GetAccessibleTableColumnHeaderPackage *) (buffer + sizeof(PackageType));
    *type = cGetAccessibleTableColumnHeaderPackage;
    pkg->vmID = vmID;
    pkg->accessibleContext = accessibleContext;

    // need to call only the HWND/VM that contains this AC
    HWND destABWindow = javaVMs->findAccessBridgeWindow(vmID);
    if (destABWindow != (HWND) 0) {
        if (sendMemoryPackage(buffer, sizeof(buffer), destABWindow) == TRUE) {
            PrintDebugString("[INFO]:   ##### WinAccessBridge::getAccessibleTableColumnHeader succeeded");
            memcpy(tableInfo, &(pkg->rTableInfo), sizeof(AccessibleTableInfo));
            return TRUE;
        }
    }
    PrintDebugString("[ERROR]:   ##### WinAccessBridge::getAccessibleTableColumnHeader failed");
    return FALSE;
}

JOBJECT64
WinAccessBridge::getAccessibleTableRowDescription(long vmID,
                                                  JOBJECT64 accessibleContext,
                                                  jint row) {

#ifdef ACCESSBRIDGE_ARCH_LEGACY // JOBJECT64 is jobject (32 bit pointer)
    PrintDebugString("[INFO]: ##### WinAccessBridge::getAccessibleTableRowDescription(%X, %p, %d)", vmID, accessibleContext,
                     row);
#else // JOBJECT64 is jlong (64 bit)
    PrintDebugString("[INFO]: ##### WinAccessBridge::getAccessibleTableRowDescription(%X, %016I64X, %d)", vmID, accessibleContext,
                     row);
#endif

    if ((AccessBridgeJavaVMInstance *) 0 == javaVMs) {
        return FALSE;
    }
    char buffer[sizeof(PackageType) + sizeof(GetAccessibleTableRowDescriptionPackage)];
    PackageType *type = (PackageType *) buffer;
    GetAccessibleTableRowDescriptionPackage *pkg = (GetAccessibleTableRowDescriptionPackage *) (buffer + sizeof(PackageType));
    *type = cGetAccessibleTableRowDescriptionPackage;
    pkg->vmID = vmID;
    pkg->row = row;
    pkg->accessibleContext = accessibleContext;

    // need to call only the HWND/VM that contains this AC
    HWND destABWindow = javaVMs->findAccessBridgeWindow(vmID);
    if (destABWindow != (HWND) 0) {
        if (sendMemoryPackage(buffer, sizeof(buffer), destABWindow) == TRUE) {
            PrintDebugString("[INFO]:   ##### WinAccessBridge::getAccessibleTableRowDescription succeeded");
            return pkg->rAccessibleContext;
        }
    }
    PrintDebugString("[ERROR]:   ##### WinAccessBridge::getAccessibleTableRowDescription failed");
    return (JOBJECT64)0;
}

JOBJECT64
WinAccessBridge::getAccessibleTableColumnDescription(long vmID,
                                                     JOBJECT64 accessibleContext,
                                                     jint column) {

#ifdef ACCESSBRIDGE_ARCH_LEGACY // JOBJECT64 is jobject (32 bit pointer)
    PrintDebugString("[INFO]: ##### WinAccessBridge::getAccessibleTableColumnDescription(%X, %p, %d)", vmID, accessibleContext,
                     column);
#else // JOBJECT64 is jlong (64 bit)
    PrintDebugString("[INFO]: ##### WinAccessBridge::getAccessibleTableColumnDescription(%X, %016I64X, %d)", vmID, accessibleContext,
                     column);
#endif

    if ((AccessBridgeJavaVMInstance *) 0 == javaVMs) {
        return FALSE;
    }
    char buffer[sizeof(PackageType) + sizeof(GetAccessibleTableColumnDescriptionPackage)];
    PackageType *type = (PackageType *) buffer;
    GetAccessibleTableColumnDescriptionPackage *pkg =
        (GetAccessibleTableColumnDescriptionPackage *) (buffer + sizeof(PackageType));
    *type = cGetAccessibleTableColumnDescriptionPackage;
    pkg->vmID = vmID;
    pkg->column = column;
    pkg->accessibleContext = accessibleContext;

    // need to call only the HWND/VM that contains this AC
    HWND destABWindow = javaVMs->findAccessBridgeWindow(vmID);
    if (destABWindow != (HWND) 0) {
        if (sendMemoryPackage(buffer, sizeof(buffer), destABWindow) == TRUE) {
            PrintDebugString("[INFO]:   ##### WinAccessBridge::getAccessibleTableColumnDescription succeeded");
            return pkg->rAccessibleContext;
        }
    }
    PrintDebugString("[ERROR]:   ##### WinAccessBridge::getAccessibleTableColumnDescription failed");
    return (JOBJECT64)0;
}

jint
WinAccessBridge::getAccessibleTableRowSelectionCount(long vmID, JOBJECT64 accessibleTable) {

#ifdef ACCESSBRIDGE_ARCH_LEGACY // JOBJECT64 is jobject (32 bit pointer)
    PrintDebugString("[INFO]: ##### WinAccessBridge::getAccessibleTableRowSelectionCount(%X, %p)", vmID, accessibleTable);
#else // JOBJECT64 is jlong (64 bit)
    PrintDebugString("[INFO]: ##### WinAccessBridge::getAccessibleTableRowSelectionCount(%X, %016I64X)", vmID, accessibleTable);
#endif

    if ((AccessBridgeJavaVMInstance *) 0 == javaVMs) {
        return 0;
    }
    char buffer[sizeof(PackageType) + sizeof(GetAccessibleTableRowSelectionCountPackage)];
    PackageType *type = (PackageType *) buffer;
    GetAccessibleTableRowSelectionCountPackage *pkg =
        (GetAccessibleTableRowSelectionCountPackage *) (buffer + sizeof(PackageType));
    *type = cGetAccessibleTableRowSelectionCountPackage;
    pkg->vmID = vmID;
    pkg->accessibleTable = accessibleTable;

    // need to call only the HWND/VM that contains this AC
    HWND destABWindow = javaVMs->findAccessBridgeWindow(vmID);
    if (destABWindow != (HWND) 0) {
        if (sendMemoryPackage(buffer, sizeof(buffer), destABWindow) == TRUE) {
            PrintDebugString("[INFO]:   ##### WinAccessBridge::getAccessibleTableRowSelectionCount succeeded");
            return pkg->rCount;
        }
    }
    PrintDebugString("[ERROR]:   ##### WinAccessBridge::getAccessibleTableRowSelectionCount failed");
    return 0;
}

BOOL
WinAccessBridge::isAccessibleTableRowSelected(long vmID, JOBJECT64 accessibleTable, jint row) {

#ifdef ACCESSBRIDGE_ARCH_LEGACY // JOBJECT64 is jobject (32 bit pointer)
    PrintDebugString("[INFO]: ##### WinAccessBridge::isAccessibleTableRowSelected(%X, %p)", vmID, accessibleTable);
#else // JOBJECT64 is jlong (64 bit)
    PrintDebugString("[INFO]: ##### WinAccessBridge::isAccessibleTableRowSelected(%X, %016I64X)", vmID, accessibleTable);
#endif

    if ((AccessBridgeJavaVMInstance *) 0 == javaVMs) {
        return FALSE;
    }
    char buffer[sizeof(PackageType) + sizeof(IsAccessibleTableRowSelectedPackage)];
    PackageType *type = (PackageType *) buffer;
    IsAccessibleTableRowSelectedPackage *pkg = (IsAccessibleTableRowSelectedPackage *) (buffer + sizeof(PackageType));
    *type = cIsAccessibleTableRowSelectedPackage;
    pkg->vmID = vmID;
    pkg->accessibleTable = accessibleTable;
    pkg->row = row;

    // need to call only the HWND/VM that contains this AC
    HWND destABWindow = javaVMs->findAccessBridgeWindow(vmID);
    if (destABWindow != (HWND) 0) {
        if (sendMemoryPackage(buffer, sizeof(buffer), destABWindow) == TRUE) {
            PrintDebugString("[INFO]:   ##### WinAccessBridge::isAccessibleTableRowSelected succeeded");
            return pkg->rResult;
        }
    }
    PrintDebugString("[ERROR]:   ##### WinAccessBridge::isAccessibleTableRowSelected failed");
    return FALSE;
}

BOOL
WinAccessBridge::getAccessibleTableRowSelections(long vmID, JOBJECT64 accessibleTable, jint count, jint *selections) {

#ifdef ACCESSBRIDGE_ARCH_LEGACY // JOBJECT64 is jobject (32 bit pointer)
    PrintDebugString("[INFO]: ##### WinAccessBridge::getAccessibleTableRowSelections(%X, %p)", vmID, accessibleTable);
#else // JOBJECT64 is jlong (64 bit)
    PrintDebugString("[INFO]: ##### WinAccessBridge::getAccessibleTableRowSelections(%X, %016I64X)", vmID, accessibleTable);
#endif

    if ((AccessBridgeJavaVMInstance *) 0 == javaVMs) {
        return FALSE;
    }
    char buffer[sizeof(PackageType) + sizeof(GetAccessibleTableRowSelectionsPackage)];
    PackageType *type = (PackageType *) buffer;
    GetAccessibleTableRowSelectionsPackage *pkg =
        (GetAccessibleTableRowSelectionsPackage *) (buffer + sizeof(PackageType));
    *type = cGetAccessibleTableRowSelectionsPackage;
    pkg->vmID = vmID;
    pkg->accessibleTable = accessibleTable;
    pkg->count = count;

    // need to call only the HWND/VM that contains this AC
    HWND destABWindow = javaVMs->findAccessBridgeWindow(vmID);
    if (destABWindow != (HWND) 0) {
        if (sendMemoryPackage(buffer, sizeof(buffer), destABWindow) == TRUE) {
            PrintDebugString("[INFO]:   ##### WinAccessBridge::getAccessibleTableRowSelections succeeded");
            memcpy(selections, pkg->rSelections, count * sizeof(jint));
            return TRUE;
        }
    }
    PrintDebugString("[ERROR]:   ##### WinAccessBridge::getAccessibleTableRowSelections failed");
    return FALSE;
}


jint
WinAccessBridge::getAccessibleTableColumnSelectionCount(long vmID, JOBJECT64 accessibleTable) {

#ifdef ACCESSBRIDGE_ARCH_LEGACY // JOBJECT64 is jobject (32 bit pointer)
    PrintDebugString("[INFO]: ##### WinAccessBridge::getAccessibleTableColumnSelectionCount(%X, %p)", vmID,
                     accessibleTable);
#else // JOBJECT64 is jlong (64 bit)
    PrintDebugString("[INFO]: ##### WinAccessBridge::getAccessibleTableColumnSelectionCount(%X, %016I64X)", vmID,
                     accessibleTable);
#endif

    if ((AccessBridgeJavaVMInstance *) 0 == javaVMs) {
        return FALSE;
    }
    char buffer[sizeof(PackageType) + sizeof(GetAccessibleTableColumnSelectionCountPackage)];
    PackageType *type = (PackageType *) buffer;
    GetAccessibleTableColumnSelectionCountPackage *pkg =
        (GetAccessibleTableColumnSelectionCountPackage *) (buffer + sizeof(PackageType));
    *type = cGetAccessibleTableColumnSelectionCountPackage;
    pkg->vmID = vmID;
    pkg->accessibleTable = accessibleTable;

    // need to call only the HWND/VM that contains this AC
    HWND destABWindow = javaVMs->findAccessBridgeWindow(vmID);
    if (destABWindow != (HWND) 0) {
        if (sendMemoryPackage(buffer, sizeof(buffer), destABWindow) == TRUE) {
            PrintDebugString("[INFO]:   ##### WinAccessBridge::getAccessibleTableColumnSelectionCount succeeded");
            return pkg->rCount;
        }
    }
    PrintDebugString("[ERROR]:   ##### WinAccessBridge::getAccessibleTableColumnSelectionCount failed");
    return 0;
}

BOOL
WinAccessBridge::isAccessibleTableColumnSelected(long vmID, JOBJECT64 accessibleTable, jint column) {
#ifdef ACCESSBRIDGE_ARCH_LEGACY // JOBJECT64 is jobject (32 bit pointer)
    PrintDebugString("[INFO]: ##### WinAccessBridge::isAccessibleTableColumnSelected(%X, %p)", vmID, accessibleTable);
#else // JOBJECT64 is jlong (64 bit)
    PrintDebugString("[INFO]: ##### WinAccessBridge::isAccessibleTableColumnSelected(%X, %016I64X)", vmID, accessibleTable);
#endif

    if ((AccessBridgeJavaVMInstance *) 0 == javaVMs) {
        return FALSE;
    }
    char buffer[sizeof(PackageType) + sizeof(IsAccessibleTableColumnSelectedPackage)];
    PackageType *type = (PackageType *) buffer;
    IsAccessibleTableColumnSelectedPackage *pkg = (IsAccessibleTableColumnSelectedPackage *) (buffer + sizeof(PackageType));
    *type = cIsAccessibleTableColumnSelectedPackage;
    pkg->vmID = vmID;
    pkg->accessibleTable = accessibleTable;
    pkg->column = column;

    // need to call only the HWND/VM that contains this AC
    HWND destABWindow = javaVMs->findAccessBridgeWindow(vmID);
    if (destABWindow != (HWND) 0) {
        if (sendMemoryPackage(buffer, sizeof(buffer), destABWindow) == TRUE) {
            PrintDebugString("[INFO]:   ##### WinAccessBridge::isAccessibleTableColumnSelected succeeded");
            return pkg->rResult;
        }
    }
    PrintDebugString("[ERROR]:   ##### WinAccessBridge::isAccessibleTableColumnSelected failed");
    return FALSE;
}

BOOL
WinAccessBridge::getAccessibleTableColumnSelections(long vmID, JOBJECT64 accessibleTable, jint count,
                                                    jint *selections) {

#ifdef ACCESSBRIDGE_ARCH_LEGACY // JOBJECT64 is jobject (32 bit pointer)
    PrintDebugString("[INFO]: ##### WinAccessBridge::getAccessibleTableColumnSelections(%X, %p)", vmID, accessibleTable);
#else // JOBJECT64 is jlong (64 bit)
    PrintDebugString("[ERROR]: ##### WinAccessBridge::getAccessibleTableColumnSelections(%X, %016I64X)", vmID, accessibleTable);
#endif

    if ((AccessBridgeJavaVMInstance *) 0 == javaVMs) {
        return FALSE;
    }
    char buffer[sizeof(PackageType) + sizeof(GetAccessibleTableColumnSelectionsPackage)];
    PackageType *type = (PackageType *) buffer;
    GetAccessibleTableColumnSelectionsPackage *pkg =
        (GetAccessibleTableColumnSelectionsPackage *) (buffer + sizeof(PackageType));
    *type = cGetAccessibleTableColumnSelectionsPackage;
    pkg->vmID = vmID;
    pkg->count = count;
    pkg->accessibleTable = accessibleTable;

    // need to call only the HWND/VM that contains this AC
    HWND destABWindow = javaVMs->findAccessBridgeWindow(vmID);
    if (destABWindow != (HWND) 0) {
        if (sendMemoryPackage(buffer, sizeof(buffer), destABWindow) == TRUE) {
            PrintDebugString("[INFO]:   ##### WinAccessBridge::getAccessibleTableColumnSelections succeeded");
            memcpy(selections, pkg->rSelections, count * sizeof(jint));
            return TRUE;
        }
    }
    PrintDebugString("[ERROR]:   ##### WinAccessBridge::getAccessibleTableColumnSelections failed");
    return FALSE;
}

jint
WinAccessBridge::getAccessibleTableRow(long vmID, JOBJECT64 accessibleTable, jint index) {

#ifdef ACCESSBRIDGE_ARCH_LEGACY // JOBJECT64 is jobject (32 bit pointer)
    PrintDebugString("[INFO]: ##### WinAccessBridge::getAccessibleTableRow(%X, %p, index=%d)", vmID,
                     accessibleTable, index);
#else // JOBJECT64 is jlong (64 bit)
    PrintDebugString("[INFO]: ##### WinAccessBridge::getAccessibleTableRow(%X, %016I64X, index=%d)", vmID,
                     accessibleTable, index);
#endif

    if ((AccessBridgeJavaVMInstance *) 0 == javaVMs) {
        return FALSE;
    }
    char buffer[sizeof(PackageType) + sizeof(GetAccessibleTableRowPackage)];
    PackageType *type = (PackageType *) buffer;
    GetAccessibleTableRowPackage *pkg =
        (GetAccessibleTableRowPackage *) (buffer + sizeof(PackageType));
    *type = cGetAccessibleTableRowPackage;
    pkg->vmID = vmID;
    pkg->accessibleTable = accessibleTable;
    pkg->index = index;

    // need to call only the HWND/VM that contains this AC
    HWND destABWindow = javaVMs->findAccessBridgeWindow(vmID);
    if (destABWindow != (HWND) 0) {
        if (sendMemoryPackage(buffer, sizeof(buffer), destABWindow) == TRUE) {
            PrintDebugString("[INFO]:   ##### WinAccessBridge::getAccessibleTableRow succeeded");
            return pkg->rRow;
        }
    }
    PrintDebugString("[ERROR]:   ##### WinAccessBridge::getAccessibleTableRow failed");
    return 0;
}

jint
WinAccessBridge::getAccessibleTableColumn(long vmID, JOBJECT64 accessibleTable, jint index) {

#ifdef ACCESSBRIDGE_ARCH_LEGACY // JOBJECT64 is jobject (32 bit pointer)
    PrintDebugString("[INFO]: ##### WinAccessBridge::getAccessibleTableColumn(%X, %p, index=%d)", vmID,
                     accessibleTable, index);
#else // JOBJECT64 is jlong (64 bit)
    PrintDebugString("[INFO]: ##### WinAccessBridge::getAccessibleTableColumn(%X, %016I64X, index=%d)", vmID,
                     accessibleTable, index);
#endif

    if ((AccessBridgeJavaVMInstance *) 0 == javaVMs) {
        return FALSE;
    }
    char buffer[sizeof(PackageType) + sizeof(GetAccessibleTableColumnPackage)];
    PackageType *type = (PackageType *) buffer;
    GetAccessibleTableColumnPackage *pkg =
        (GetAccessibleTableColumnPackage *) (buffer + sizeof(PackageType));
    *type = cGetAccessibleTableColumnPackage;
    pkg->vmID = vmID;
    pkg->accessibleTable = accessibleTable;
    pkg->index = index;

    // need to call only the HWND/VM that contains this AC
    HWND destABWindow = javaVMs->findAccessBridgeWindow(vmID);
    if (destABWindow != (HWND) 0) {
        if (sendMemoryPackage(buffer, sizeof(buffer), destABWindow) == TRUE) {
            PrintDebugString("[INFO]:   ##### WinAccessBridge::getAccessibleTableColumn succeeded");
            return pkg->rColumn;
        }
    }
    PrintDebugString("[ERROR]:   ##### WinAccessBridge::getAccessibleTableColumn failed");
    return 0;
}

jint
WinAccessBridge::getAccessibleTableIndex(long vmID, JOBJECT64 accessibleTable, jint row, jint column) {

#ifdef ACCESSBRIDGE_ARCH_LEGACY // JOBJECT64 is jobject (32 bit pointer)
    PrintDebugString("[INFO]: ##### WinAccessBridge::getAccessibleTableIndex(%X, %p, row=%d, col=%d)", vmID,
                     accessibleTable, row, column);
#else // JOBJECT64 is jlong (64 bit)
    PrintDebugString("[INFO]: ##### WinAccessBridge::getAccessibleTableIndex(%X, %016I64X, row=%d, col=%d)", vmID,
                     accessibleTable, row, column);
#endif

    if ((AccessBridgeJavaVMInstance *) 0 == javaVMs) {
        return FALSE;
    }
    char buffer[sizeof(PackageType) + sizeof(GetAccessibleTableIndexPackage)];
    PackageType *type = (PackageType *) buffer;
    GetAccessibleTableIndexPackage *pkg =
        (GetAccessibleTableIndexPackage *) (buffer + sizeof(PackageType));
    *type = cGetAccessibleTableIndexPackage;
    pkg->vmID = vmID;
    pkg->accessibleTable = accessibleTable;
    pkg->row = row;
    pkg->column = column;

    // need to call only the HWND/VM that contains this AC
    HWND destABWindow = javaVMs->findAccessBridgeWindow(vmID);
    if (destABWindow != (HWND) 0) {
        if (sendMemoryPackage(buffer, sizeof(buffer), destABWindow) == TRUE) {
            PrintDebugString("[INFO]:   ##### WinAccessBridge::getAccessibleTableIndex succeeded");
            return pkg->rIndex;
        }
    }
    PrintDebugString("[ERROR]:   ##### WinAccessBridge::getAccessibleTableIndex failed");
    return 0;
}

/********** end AccessibleTable routines ******************************/

BOOL
WinAccessBridge::getAccessibleRelationSet(long vmID, JOBJECT64 accessibleContext,
                                          AccessibleRelationSetInfo *relationSetInfo) {

#ifdef ACCESSBRIDGE_ARCH_LEGACY // JOBJECT64 is jobject (32 bit pointer)
    PrintDebugString("[INFO]: ##### WinAccessBridge::getAccessibleRelationSet(%X, %p, %X)", vmID,
                     accessibleContext, relationSetInfo);
#else // JOBJECT64 is jlong (64 bit)
    PrintDebugString("[INFO]: ##### WinAccessBridge::getAccessibleRelationSet(%X, %016I64X, %X)", vmID,
                     accessibleContext, relationSetInfo);
#endif

    if ((AccessBridgeJavaVMInstance *) 0 == javaVMs) {
        return FALSE;
    }

    char buffer[sizeof(PackageType) + sizeof(GetAccessibleRelationSetPackage)];
    PackageType *type = (PackageType *) buffer;
    GetAccessibleRelationSetPackage *pkg = (GetAccessibleRelationSetPackage *) (buffer + sizeof(PackageType));
    *type = cGetAccessibleRelationSetPackage;
    pkg->vmID = vmID;
    pkg->accessibleContext = accessibleContext;

    HWND destABWindow = javaVMs->findAccessBridgeWindow(vmID);
    if (destABWindow != (HWND) 0) {
        if (sendMemoryPackage(buffer, sizeof(buffer), destABWindow) == TRUE) {
            PrintDebugString("[INFO]:   ##### pkg->rAccessibleRelationSetInfo.relationCount = %X",
                             pkg->rAccessibleRelationSetInfo.relationCount);
            memcpy(relationSetInfo, &(pkg->rAccessibleRelationSetInfo), sizeof(AccessibleRelationSetInfo));
            PrintDebugString("[INFO]:   ##### WinAccessBridge::getAccessibleRelationSet succeeded");
            return TRUE;
        }
    }
    PrintDebugString("[ERROR]:   ##### WinAccessBridge::getAccessibleRelationSet failed");
    return FALSE;
}


/********** AccessibleHypertext routines ***********/

BOOL
WinAccessBridge::getAccessibleHypertext(long vmID, JOBJECT64 accessibleContext,
                                        AccessibleHypertextInfo *hypertextInfo) {

#ifdef ACCESSBRIDGE_ARCH_LEGACY // JOBJECT64 is jobject (32 bit pointer)
    PrintDebugString("[INFO]: ##### WinAccessBridge::getAccessibleHypertext(%X, %p, %X)", vmID,
                     accessibleContext, hypertextInfo);
#else // JOBJECT64 is jlong (64 bit)
    PrintDebugString("[INFO]: ##### WinAccessBridge::getAccessibleHypertext(%X, %016I64X, %X)", vmID,
                     accessibleContext, hypertextInfo);
#endif

    if ((AccessBridgeJavaVMInstance *) 0 == javaVMs) {
        return FALSE;
    }

    char buffer[sizeof(PackageType) + sizeof(GetAccessibleHypertextPackage)];
    PackageType *type = (PackageType *) buffer;
    GetAccessibleHypertextPackage *pkg = (GetAccessibleHypertextPackage *) (buffer + sizeof(PackageType));
    *type = cGetAccessibleHypertextPackage;
    pkg->vmID = vmID;
    pkg->accessibleContext = accessibleContext;

    HWND destABWindow = javaVMs->findAccessBridgeWindow(vmID);
    if (destABWindow != (HWND) 0) {
        if (sendMemoryPackage(buffer, sizeof(buffer), destABWindow) == TRUE) {
            memcpy(hypertextInfo, &(pkg->rAccessibleHypertextInfo), sizeof(AccessibleHypertextInfo));

            PrintDebugString("[INFO]:   ##### hypertextInfo.linkCount = %d", hypertextInfo->linkCount);
            PrintDebugString("[INFO]:   ##### WinAccessBridge::getAccessibleHypertext succeeded");

            return TRUE;
        }
    }
    PrintDebugString("[ERROR]:   ##### WinAccessBridge::getAccessibleHypertext failed");
    return FALSE;
}


BOOL
WinAccessBridge::activateAccessibleHyperlink(long vmID, JOBJECT64 accessibleContext,
                                             JOBJECT64 accessibleHyperlink) {

#ifdef ACCESSBRIDGE_ARCH_LEGACY // JOBJECT64 is jobject (32 bit pointer)
    PrintDebugString("[INFO]: WinAccessBridge::activateAccessibleHyperlink(%p %p)", accessibleContext,
                     accessibleHyperlink);
#else // JOBJECT64 is jlong (64 bit)
    PrintDebugString("[INFO]: WinAccessBridge::activateAccessibleHyperlink(%016I64X %016I64X)", accessibleContext,
                     accessibleHyperlink);
#endif

    if ((AccessBridgeJavaVMInstance *) 0 == javaVMs) {
        return FALSE;
    }

    char buffer[sizeof(PackageType) + sizeof(ActivateAccessibleHyperlinkPackage)];
    PackageType *type = (PackageType *) buffer;
    ActivateAccessibleHyperlinkPackage *pkg = (ActivateAccessibleHyperlinkPackage *) (buffer + sizeof(PackageType));
    *type = cActivateAccessibleHyperlinkPackage;
    pkg->vmID = vmID;
    pkg->accessibleContext = accessibleContext;
    pkg->accessibleHyperlink = accessibleHyperlink;

    HWND destABWindow = javaVMs->findAccessBridgeWindow(pkg->vmID);
    if (sendMemoryPackage(buffer, sizeof(buffer), destABWindow) == TRUE) {
        return pkg->rResult;
    }
    PrintDebugString("[ERROR]:  WinAccessBridge::activateAccessibleHyperlink returning FALSE (sendMemoryPackage failed)");
    return FALSE;
}

/*
 * Returns the number of hyperlinks in a component
 * Maps to AccessibleHypertext.getLinkCount.
 * Returns -1 on error.
 */
jint
WinAccessBridge::getAccessibleHyperlinkCount(const long vmID,
                                             const AccessibleContext accessibleContext) {

#ifdef ACCESSBRIDGE_ARCH_LEGACY // JOBJECT64 is jobject (32 bit pointer)
    PrintDebugString("[INFO]: ##### WinAccessBridge::getAccessibleHyperlinkCount(%X, %p)",
                     vmID, accessibleContext);
#else // JOBJECT64 is jlong (64 bit)
    PrintDebugString("[INFO]: ##### WinAccessBridge::getAccessibleHyperlinkCount(%X, %016I64X)",
                     vmID, accessibleContext);
#endif

    if ((AccessBridgeJavaVMInstance *) 0 == javaVMs) {
        return FALSE;
    }

    char buffer[sizeof(PackageType) + sizeof(GetAccessibleHyperlinkCountPackage)];
    PackageType *type = (PackageType *) buffer;
    GetAccessibleHyperlinkCountPackage *pkg = (GetAccessibleHyperlinkCountPackage *) (buffer + sizeof(PackageType));
    *type = cGetAccessibleHyperlinkCountPackage;
    pkg->vmID = vmID;
    pkg->accessibleContext = accessibleContext;

    HWND destABWindow = javaVMs->findAccessBridgeWindow(vmID);
    if (destABWindow != (HWND) 0) {
        if (sendMemoryPackage(buffer, sizeof(buffer), destABWindow) == TRUE) {
            PrintDebugString("[INFO]:   ##### hypetext link count = %d", pkg->rLinkCount);
            PrintDebugString("[INFO]:  ##### WinAccessBridge::getAccessibleHyperlinkCount succeeded");
            return pkg->rLinkCount;
        }
    }
    PrintDebugString("[ERROR]:   ##### WinAccessBridge::getAccessibleHyperlinkCount failed");
    return -1;
}

/*
 * This method is used to iterate through the hyperlinks in a component.  It
 * returns hypertext information for a component starting at hyperlink index
 * nStartIndex.  No more than MAX_HYPERLINKS AccessibleHypertextInfo objects will
 * be returned for each call to this method.
 * returns FALSE on error.
 */
BOOL
WinAccessBridge::getAccessibleHypertextExt(const long vmID,
                                           const AccessibleContext accessibleContext,
                                           const jint startIndex,
                                           /* OUT */ AccessibleHypertextInfo *hypertextInfo) {

#ifdef ACCESSBRIDGE_ARCH_LEGACY // JOBJECT64 is jobject (32 bit pointer)
    PrintDebugString("[INFO]: ##### WinAccessBridge::getAccessibleHypertextExt(%X, %p %p)", vmID,
                     accessibleContext, hypertextInfo);
#else // JOBJECT64 is jlong (64 bit)
    PrintDebugString("[INFO]: ##### WinAccessBridge::getAccessibleHypertextExt(%X, %016I64X %p)", vmID,
                     accessibleContext, hypertextInfo);
#endif

    if ((AccessBridgeJavaVMInstance *) 0 == javaVMs) {
        return FALSE;
    }

    char buffer[sizeof(PackageType) + sizeof(GetAccessibleHypertextExtPackage)];
    PackageType *type = (PackageType *) buffer;
    GetAccessibleHypertextExtPackage *pkg = (GetAccessibleHypertextExtPackage *) (buffer + sizeof(PackageType));
    *type = cGetAccessibleHypertextExtPackage;
    pkg->vmID = vmID;
    pkg->accessibleContext = accessibleContext;
    pkg->startIndex = startIndex;

    HWND destABWindow = javaVMs->findAccessBridgeWindow(vmID);
    if (destABWindow != (HWND) 0) {
        if (sendMemoryPackage(buffer, sizeof(buffer), destABWindow) == TRUE) {
            PrintDebugString("[INFO]:   ##### pkg->rSuccess = %d", pkg->rSuccess);

            memcpy(hypertextInfo, &(pkg->rAccessibleHypertextInfo), sizeof(AccessibleHypertextInfo));
            if (pkg->rSuccess == TRUE) {
                PrintDebugString("[INFO]:   ##### hypertextInfo.linkCount = %d", hypertextInfo->linkCount);
            } else {
                PrintDebugString("[ERROR]:   ##### WinAccessBridge::getAccessibleHypertextExt failed");
            }
            return pkg->rSuccess;
        }
    }
    PrintDebugString("[ERROR]:  ##### WinAccessBridge::getAccessibleHypertextExt failed");
    return FALSE;
}


/*
 * Returns the index into an array of hyperlinks that is associated with
 * a character index in document;
 * Maps to AccessibleHypertext.getLinkIndex.
 * Returns -1 on error.
 */
jint
WinAccessBridge::getAccessibleHypertextLinkIndex(const long vmID,
                                                 const AccessibleHyperlink hypertext,
                                                 const jint charIndex) {

#ifdef ACCESSBRIDGE_ARCH_LEGACY // JOBJECT64 is jobject (32 bit pointer)
    PrintDebugString("[INFO]: ##### WinAccessBridge::getAccessibleHypertextLinkIndex(%X, %p)",
                     vmID, hypertext);
#else // JOBJECT64 is jlong (64 bit)
    PrintDebugString("[INFO]: ##### WinAccessBridge::getAccessibleHypertextLinkIndex(%X, %016I64X)",
                     vmID, hypertext);
#endif

    if ((AccessBridgeJavaVMInstance *) 0 == javaVMs) {
        return FALSE;
    }

    char buffer[sizeof(PackageType) + sizeof(GetAccessibleHypertextLinkIndexPackage)];
    PackageType *type = (PackageType *) buffer;
    GetAccessibleHypertextLinkIndexPackage *pkg = (GetAccessibleHypertextLinkIndexPackage *) (buffer + sizeof(PackageType));
    *type = cGetAccessibleHypertextLinkIndexPackage;
    pkg->vmID = vmID;
    pkg->hypertext = hypertext;
    pkg->charIndex = charIndex;

    HWND destABWindow = javaVMs->findAccessBridgeWindow(vmID);
    if (destABWindow != (HWND) 0) {
        if (sendMemoryPackage(buffer, sizeof(buffer), destABWindow) == TRUE) {
            PrintDebugString("[INFO]:   ##### hypetext link index = %d", pkg->rLinkIndex);
            PrintDebugString("[INFO]:   ##### WinAccessBridge::getAccessibleHypertextLinkIndex  succeeded");
            return pkg->rLinkIndex;
        }
    }
    PrintDebugString("[ERROR]  ##### WinAccessBridge::getAccessibleHypertextLinkIndex  failed");
    return -1;
}

/*
 * Returns the nth hyperlink in a document.
 * Maps to AccessibleHypertext.getLink.
 * Returns -1 on error
 */
BOOL
WinAccessBridge::getAccessibleHyperlink(const long vmID,
                                        const AccessibleHyperlink hypertext,
                                        const jint linkIndex,
                                        /* OUT */ AccessibleHyperlinkInfo *hyperlinkInfo) {

#ifdef ACCESSBRIDGE_ARCH_LEGACY // JOBJECT64 is jobject (32 bit pointer)
    PrintDebugString("[INFO]: ##### WinAccessBridge::getAccessibleHyperlink(%X, %p, %p)", vmID,
                     hypertext, hyperlinkInfo);
#else // JOBJECT64 is jlong (64 bit)
    PrintDebugString("[INFO]: ##### WinAccessBridge::getAccessibleHyperlink(%X, %016I64X, %p)", vmID,
                     hypertext, hyperlinkInfo);
#endif

    if ((AccessBridgeJavaVMInstance *) 0 == javaVMs) {
        return FALSE;
    }

    char buffer[sizeof(PackageType) + sizeof(GetAccessibleHyperlinkPackage)];
    PackageType *type = (PackageType *) buffer;
    GetAccessibleHyperlinkPackage *pkg = (GetAccessibleHyperlinkPackage *) (buffer + sizeof(PackageType));
    *type = cGetAccessibleHyperlinkPackage;
    pkg->vmID = vmID;
    pkg->hypertext = hypertext;
    pkg->linkIndex = linkIndex;

    HWND destABWindow = javaVMs->findAccessBridgeWindow(vmID);
    if (destABWindow != (HWND) 0) {
        if (sendMemoryPackage(buffer, sizeof(buffer), destABWindow) == TRUE) {
            memcpy(hyperlinkInfo, &(pkg->rAccessibleHyperlinkInfo),
                   sizeof(AccessibleHyperlinkInfo));
            PrintDebugString("[INFO]:   ##### WinAccessBridge::getAccessibleHypertext succeeded");
            return TRUE;
        }
    }
    PrintDebugString("[ERROR]:   ##### WinAccessBridge::getAccessibleHypertext failed");
    return FALSE;
}


/********** AccessibleKeyBinding routines ***********/

BOOL
WinAccessBridge::getAccessibleKeyBindings(long vmID, JOBJECT64 accessibleContext,
                                          AccessibleKeyBindings *keyBindings) {

#ifdef ACCESSBRIDGE_ARCH_LEGACY // JOBJECT64 is jobject (32 bit pointer)
    PrintDebugString("[INFO]: ##### WinAccessBridge::getAccessibleKeyBindings(%X, %p, %p)", vmID,
                     accessibleContext, keyBindings);
#else // JOBJECT64 is jlong (64 bit)
    PrintDebugString("[INFO]: ##### WinAccessBridge::getAccessibleKeyBindings(%X, %016I64X, %p)", vmID,
                     accessibleContext, keyBindings);
#endif

    if ((AccessBridgeJavaVMInstance *) 0 == javaVMs) {
        return FALSE;
    }

    char buffer[sizeof(PackageType) + sizeof(GetAccessibleKeyBindingsPackage)];
    PackageType *type = (PackageType *) buffer;
    GetAccessibleKeyBindingsPackage *pkg = (GetAccessibleKeyBindingsPackage *) (buffer + sizeof(PackageType));
    *type = cGetAccessibleKeyBindingsPackage;
    pkg->vmID = vmID;
    pkg->accessibleContext = accessibleContext;

    HWND destABWindow = javaVMs->findAccessBridgeWindow(vmID);
    if (destABWindow != (HWND) 0) {
        if (sendMemoryPackage(buffer, sizeof(buffer), destABWindow) == TRUE) {
            memcpy(keyBindings, &(pkg->rAccessibleKeyBindings), sizeof(AccessibleKeyBindings));

            PrintDebugString("[INFO]:   ##### keyBindings.keyBindingsCount = %d", keyBindings->keyBindingsCount);
            for (int i = 0; i < keyBindings->keyBindingsCount; ++i) {
                PrintDebugString("[INFO]:   Key Binding # %d"\
                "                           Modifiers: 0x%x"\
                "                           Character (hex):  0x%x"\
                "                           Character (wide char):  %lc"\
                , i+1, keyBindings->keyBindingInfo[i].modifiers, keyBindings->keyBindingInfo[i].character, keyBindings->keyBindingInfo[i].character);
            }
            PrintDebugString("[INFO]:   ##### WinAccessBridge::getAccessibleKeyBindings succeeded");

            return TRUE;
        }
    }
    PrintDebugString("[INFO]:   ##### WinAccessBridge::getAccessibleKeyBindings failed");
    return FALSE;
}

BOOL
WinAccessBridge::getAccessibleIcons(long vmID, JOBJECT64 accessibleContext, AccessibleIcons *icons) {

#ifdef ACCESSBRIDGE_ARCH_LEGACY // JOBJECT64 is jobject (32 bit pointer)
    PrintDebugString("[INFO]: ##### WinAccessBridge::getAccessibleIcons(%X, %p, %p)", vmID,
                     accessibleContext, icons);
#else // JOBJECT64 is jlong (64 bit)
    PrintDebugString("[INFO]: ##### WinAccessBridge::getAccessibleIcons(%X, %016I64X, %p)", vmID,
                     accessibleContext, icons);
#endif

    if ((AccessBridgeJavaVMInstance *) 0 == javaVMs) {
        return FALSE;
    }

    char buffer[sizeof(PackageType) + sizeof(GetAccessibleIconsPackage)];
    PackageType *type = (PackageType *) buffer;
    GetAccessibleIconsPackage *pkg = (GetAccessibleIconsPackage *) (buffer + sizeof(PackageType));
    *type = cGetAccessibleIconsPackage;
    pkg->vmID = vmID;
    pkg->accessibleContext = accessibleContext;

    HWND destABWindow = javaVMs->findAccessBridgeWindow(vmID);
    if (destABWindow != (HWND) 0) {
        if (sendMemoryPackage(buffer, sizeof(buffer), destABWindow) == TRUE) {
            memcpy(icons, &(pkg->rAccessibleIcons), sizeof(AccessibleIcons));

            PrintDebugString("[INFO]:   ##### icons.iconsCount = %d", icons->iconsCount);
            PrintDebugString("[INFO]:   ##### WinAccessBridge::getAccessibleIcons succeeded");

            return TRUE;
        }
    }
    PrintDebugString("[ERROR]:   ##### WinAccessBridge::getAccessibleIcons failed");
    return FALSE;
}

BOOL
WinAccessBridge::getAccessibleActions(long vmID, JOBJECT64 accessibleContext, AccessibleActions *actions) {

#ifdef ACCESSBRIDGE_ARCH_LEGACY // JOBJECT64 is jobject (32 bit pointer)
    PrintDebugString("[INFO]: ##### WinAccessBridge::getAccessibleActions(%X, %p, %p)", vmID,
                     accessibleContext, actions);
#else // JOBJECT64 is jlong (64 bit)
    PrintDebugString("[INFO]: ##### WinAccessBridge::getAccessibleActions(%X, %016I64X, %p)", vmID,
                     accessibleContext, actions);
#endif

    if ((AccessBridgeJavaVMInstance *) 0 == javaVMs) {
        return FALSE;
    }

    char buffer[sizeof(PackageType) + sizeof(GetAccessibleActionsPackage)];
    PackageType *type = (PackageType *) buffer;
    GetAccessibleActionsPackage *pkg = (GetAccessibleActionsPackage *) (buffer + sizeof(PackageType));
    *type = cGetAccessibleActionsPackage;
    pkg->vmID = vmID;
    pkg->accessibleContext = accessibleContext;

    HWND destABWindow = javaVMs->findAccessBridgeWindow(vmID);
    if (destABWindow != (HWND) 0) {
        if (sendMemoryPackage(buffer, sizeof(buffer), destABWindow) == TRUE) {
            memcpy(actions, &(pkg->rAccessibleActions), sizeof(AccessibleActions));

            PrintDebugString("[INFO]:   ##### actions.actionsCount = %d", actions->actionsCount);
            PrintDebugString("[INFO]:   ##### WinAccessBridge::getAccessibleActions succeeded");

            return TRUE;
        }
    }
    PrintDebugString("[ERROR]:   ##### WinAccessBridge::getAccessibleActions failed");
    return FALSE;
}

BOOL
WinAccessBridge::doAccessibleActions(long vmID, JOBJECT64 accessibleContext,
                                     AccessibleActionsToDo *actionsToDo, jint *failure) {

#ifdef ACCESSBRIDGE_ARCH_LEGACY // JOBJECT64 is jobject (32 bit pointer)
    PrintDebugString("[INFO]: WinAccessBridge::doAccessibleActions(%p #actions %d %ls)", accessibleContext,
                     actionsToDo->actionsCount,
                     actionsToDo->actions[0].name);
#else // JOBJECT64 is jlong (64 bit)
    PrintDebugString("[INFO]: WinAccessBridge::doAccessibleActions(%016I64X #actions %d %ls)", accessibleContext,
                     actionsToDo->actionsCount,
                     actionsToDo->actions[0].name);
#endif

    if ((AccessBridgeJavaVMInstance *) 0 == javaVMs) {
        return FALSE;
    }
    char buffer[sizeof(PackageType) + sizeof(DoAccessibleActionsPackage)];
    PackageType *type = (PackageType *) buffer;
    DoAccessibleActionsPackage *pkg = (DoAccessibleActionsPackage *) (buffer + sizeof(PackageType));
    *type = cDoAccessibleActionsPackage;
    pkg->vmID = vmID;
    pkg->accessibleContext = accessibleContext;
    memcpy((void *)(&(pkg->actionsToDo)), (void *)actionsToDo, sizeof(AccessibleActionsToDo));
    pkg->failure = -1;

    HWND destABWindow = javaVMs->findAccessBridgeWindow(pkg->vmID);
    if (sendMemoryPackage(buffer, sizeof(buffer), destABWindow) == TRUE) {
        *failure = pkg->failure;
        return pkg->rResult;
    }
    PrintDebugString("[ERROR]:   WinAccessBridge::doAccessibleActions returning FALSE (sendMemoryPackage failed)");
    return FALSE;
}

/* ====== Utility methods ====== */

/**
 * Sets a text field to the specified string. Returns whether successful.
 */
BOOL
WinAccessBridge::setTextContents (const long vmID, const AccessibleContext accessibleContext,
                                  const wchar_t *text) {

    if ((AccessBridgeJavaVMInstance *) 0 == javaVMs) {
        return FALSE;
    }
    char buffer[sizeof(PackageType) + sizeof(SetTextContentsPackage)];
    PackageType *type = (PackageType *) buffer;
    SetTextContentsPackage *pkg = (SetTextContentsPackage *) (buffer + sizeof(PackageType));
    *type = cSetTextContentsPackage;
    pkg->vmID = vmID;
    pkg->accessibleContext = accessibleContext;
    wcsncpy(pkg->text, text, sizeof(pkg->text)/sizeof(wchar_t)); // wide character copy

#ifdef ACCESSBRIDGE_ARCH_LEGACY // JOBJECT64 is jobject (32 bit pointer)
    PrintDebugString("[INFO]: WinAccessBridge::setTextContents(%X, %016I64X %ls)", vmID, accessibleContext, text);
#else // JOBJECT64 is jlong (64 bit)
    PrintDebugString("[INFO]: WinAccessBridge::setTextContents(%X, %p %ls)", vmID, accessibleContext, text);
#endif
    // need to call only the HWND/VM that contains this AC
    HWND destABWindow = javaVMs->findAccessBridgeWindow(vmID);
    if (destABWindow != (HWND) 0) {
        if (sendMemoryPackage(buffer, sizeof(buffer), destABWindow) == TRUE) {
            return pkg->rResult;
        }
    }
    return FALSE;
}

/**
 * Returns the Accessible Context of a Page Tab object that is the
 * ancestor of a given object.  If the object is a Page Tab object
 * or a Page Tab ancestor object was found, returns the object
 * AccessibleContext.
 * If there is no ancestor object that has an Accessible Role of Page Tab,
 * returns (AccessibleContext)0.
 */
AccessibleContext
WinAccessBridge::getParentWithRole (const long vmID, const AccessibleContext accessibleContext, const wchar_t *role) {

    if ((AccessBridgeJavaVMInstance *) 0 == javaVMs) {
        return (JOBJECT64)0;
    }
    char buffer[sizeof(PackageType) + sizeof(GetParentWithRolePackage)];
    PackageType *type = (PackageType *) buffer;
    GetParentWithRolePackage *pkg = (GetParentWithRolePackage *) (buffer + sizeof(PackageType));
    *type = cGetParentWithRolePackage;
    pkg->vmID = vmID;
    pkg->accessibleContext = accessibleContext;
    memcpy((void *)(&(pkg->role)), (void *)role, sizeof(pkg->role));

#ifdef ACCESSBRIDGE_ARCH_LEGACY // JOBJECT64 is jobject (32 bit pointer)
    PrintDebugString("[INFO]: WinAccessBridge::getParentWithRole(%X, %p)", vmID, accessibleContext);
#else // JOBJECT64 is jlong (64 bit)
    PrintDebugString("[INFO]: WinAccessBridge::getParentWithRole(%X, %016I64X)", vmID, accessibleContext);
#endif
    PrintDebugString("[INFO]:   pkg->vmID: %X"\
                     "          pkg->accessibleContext: %p"\
                     "          pkg->role: %ls"\
                     , pkg->vmID, pkg->accessibleContext, pkg->role);
    // need to call only the HWND/VM that contains this AC
    HWND destABWindow = javaVMs->findAccessBridgeWindow(vmID);
    if (destABWindow != (HWND) 0) {
        if (sendMemoryPackage(buffer, sizeof(buffer), destABWindow) == TRUE) {
            PrintDebugString("[INFO]:   pkg->rAccessibleContext: %p", pkg->rAccessibleContext);
            return pkg->rAccessibleContext;
        }
    }
    return (JOBJECT64) 0;
}


/**
 * Returns the Accessible Context for the top level object in
 * a Java Window.  This is same Accessible Context that is obtained
 * from GetAccessibleContextFromHWND for that window.  Returns
 * (AccessibleContext)0 on error.
 */
AccessibleContext
WinAccessBridge::getTopLevelObject (const long vmID, const AccessibleContext accessibleContext) {

    if ((AccessBridgeJavaVMInstance *) 0 == javaVMs) {
        return (JOBJECT64)0;
    }
    char buffer[sizeof(PackageType) + sizeof(GetTopLevelObjectPackage)];
    PackageType *type = (PackageType *) buffer;
    GetTopLevelObjectPackage *pkg = (GetTopLevelObjectPackage *) (buffer + sizeof(PackageType));
    *type = cGetTopLevelObjectPackage;
    pkg->vmID = vmID;
    pkg->accessibleContext = accessibleContext;

#ifdef ACCESSBRIDGE_ARCH_LEGACY // JOBJECT64 is jobject (32 bit pointer)
    PrintDebugString("[INFO]: WinAccessBridge::getTopLevelObject(%X, %p)", vmID, accessibleContext);
#else // JOBJECT64 is jlong (64 bit)
    PrintDebugString("[INFO]: WinAccessBridge::getTopLevelObject(%X, %016I64X)", vmID, accessibleContext);
#endif
    // need to call only the HWND/VM that contains this AC
    HWND destABWindow = javaVMs->findAccessBridgeWindow(vmID);
    if (destABWindow != (HWND) 0) {
        if (sendMemoryPackage(buffer, sizeof(buffer), destABWindow) == TRUE) {
            return pkg->rAccessibleContext;
        }
    }
    return (JOBJECT64) 0;
}

/**
 * If there is an Ancestor object that has an Accessible Role of
 * Internal Frame, returns the Accessible Context of the Internal
 * Frame object.  Otherwise, returns the top level object for that
 * Java Window.  Returns (AccessibleContext)0 on error.
 */
AccessibleContext
WinAccessBridge::getParentWithRoleElseRoot (const long vmID, const AccessibleContext accessibleContext, const wchar_t *role) {

    if ((AccessBridgeJavaVMInstance *) 0 == javaVMs) {
        return (JOBJECT64)0;
    }
    char buffer[sizeof(PackageType) + sizeof(GetParentWithRoleElseRootPackage)];
    PackageType *type = (PackageType *) buffer;
    GetParentWithRoleElseRootPackage *pkg = (GetParentWithRoleElseRootPackage *) (buffer + sizeof(PackageType));
    *type = cGetParentWithRoleElseRootPackage;
    pkg->vmID = vmID;
    pkg->accessibleContext = accessibleContext;
    memcpy((void *)(&(pkg->role)), (void *)role, sizeof(pkg->role));

#ifdef ACCESSBRIDGE_ARCH_LEGACY // JOBJECT64 is jobject (32 bit pointer)
    PrintDebugString("[INFO]: WinAccessBridge::getParentWithRoleElseRoot(%X, %p)", vmID, accessibleContext);
#else // JOBJECT64 is jlong (64 bit)
    PrintDebugString("[INFO]: WinAccessBridge::getParentWithRoleElseRoot(%X, %016I64X)", vmID, accessibleContext);
#endif
    // need to call only the HWND/VM that contains this AC
    HWND destABWindow = javaVMs->findAccessBridgeWindow(vmID);
    if (destABWindow != (HWND) 0) {
        if (sendMemoryPackage(buffer, sizeof(buffer), destABWindow) == TRUE) {
            return pkg->rAccessibleContext;
        }
    }
    return (JOBJECT64) 0;
}

/**
 * Returns how deep in the object hierarchy a given object is.
 * The top most object in the object hierarchy has an object depth of 0.
 * Returns -1 on error.
 */
int
WinAccessBridge::getObjectDepth (const long vmID, const AccessibleContext accessibleContext) {

    if ((AccessBridgeJavaVMInstance *) 0 == javaVMs) {
        return -1;
    }
    char buffer[sizeof(PackageType) + sizeof(GetObjectDepthPackage)];
    PackageType *type = (PackageType *) buffer;
    GetObjectDepthPackage *pkg = (GetObjectDepthPackage *) (buffer + sizeof(PackageType));
    *type = cGetObjectDepthPackage;
    pkg->vmID = vmID;
    pkg->accessibleContext = accessibleContext;

#ifdef ACCESSBRIDGE_ARCH_LEGACY // JOBJECT64 is jobject (32 bit pointer)
    PrintDebugString("[INFO]: WinAccessBridge::getObjectDepth(%X, %p)", vmID, accessibleContext);
#else // JOBJECT64 is jlong (64 bit)
    PrintDebugString("[INFO]: WinAccessBridge::getObjectDepth(%X, %016I64X)", vmID, accessibleContext);
#endif
    // need to call only the HWND/VM that contains this AC
    HWND destABWindow = javaVMs->findAccessBridgeWindow(vmID);
    if (destABWindow != (HWND) 0) {
        if (sendMemoryPackage(buffer, sizeof(buffer), destABWindow) == TRUE) {
            return pkg->rResult;
        }
    }
    return -1;
}

/**
 * Returns the Accessible Context of the currently ActiveDescendent of an object.
 * Returns (AccessibleContext)0 on error.
 */
AccessibleContext
WinAccessBridge::getActiveDescendent (const long vmID, const AccessibleContext accessibleContext) {

    if ((AccessBridgeJavaVMInstance *) 0 == javaVMs) {
        return (JOBJECT64)0;
    }
    char buffer[sizeof(PackageType) + sizeof(GetActiveDescendentPackage)];
    PackageType *type = (PackageType *) buffer;
    GetActiveDescendentPackage *pkg = (GetActiveDescendentPackage *) (buffer + sizeof(PackageType));
    *type = cGetActiveDescendentPackage;
    pkg->vmID = vmID;
    pkg->accessibleContext = accessibleContext;

#ifdef ACCESSBRIDGE_ARCH_LEGACY // JOBJECT64 is jobject (32 bit pointer)
    PrintDebugString("[INFO]: WinAccessBridge::getActiveDescendent(%X, %p)", vmID, accessibleContext);
#else // JOBJECT64 is jlong (64 bit)
    PrintDebugString("[INFO]: WinAccessBridge::getActiveDescendent(%X, %016I64X)", vmID, accessibleContext);
#endif
    // need to call only the HWND/VM that contains this AC
    HWND destABWindow = javaVMs->findAccessBridgeWindow(vmID);
    if (destABWindow != (HWND) 0) {
        if (sendMemoryPackage(buffer, sizeof(buffer), destABWindow) == TRUE) {
            return pkg->rAccessibleContext;
        }
    }
    return (JOBJECT64) 0;
}

/**
 * Additional methods for Teton
 */

/**
 * Gets the AccessibleName for a component based upon the JAWS algorithm. Returns
 * whether successful.
 *
 * Bug ID 4916682 - Implement JAWS AccessibleName policy
 */
BOOL
WinAccessBridge::getVirtualAccessibleName(long vmID, AccessibleContext accessibleContext,
                                          wchar_t *name, int len) {

    if ((AccessBridgeJavaVMInstance *) 0 == javaVMs) {
        return FALSE;
    }
    char buffer[sizeof(PackageType) + sizeof(GetVirtualAccessibleNamePackage)];
    PackageType *type = (PackageType *) buffer;
    GetVirtualAccessibleNamePackage *pkg = (GetVirtualAccessibleNamePackage *) (buffer + sizeof(PackageType));
    *type = cGetVirtualAccessibleNamePackage;
    pkg->vmID = vmID;
    pkg->accessibleContext = accessibleContext;
    size_t max = (len > sizeof(pkg->rName)) ? sizeof(pkg->rName) : len;
    pkg->len = (int)max;

#ifdef ACCESSBRIDGE_ARCH_LEGACY // JOBJECT64 is jobject (32 bit pointer)
    PrintDebugString("[INFO]: WinAccessBridge::getVirtualAccessibleName(%X, %p)", vmID, accessibleContext);
#else // JOBJECT64 is jlong (64 bit)
    PrintDebugString("[INFO]: WinAccessBridge::getVirtualAccessibleName(%X, %016I64X)", vmID, accessibleContext);
#endif
    // need to call only the HWND/VM that contains this AC
    HWND destABWindow = javaVMs->findAccessBridgeWindow(vmID);
    if (destABWindow != (HWND) 0) {
        if (sendMemoryPackage(buffer, sizeof(buffer), destABWindow) == TRUE) {
            wcsncpy(name, pkg->rName, max);
            PrintDebugString("[INFO]:     WinAccessBridge::getVirtualAccessibleName: Virtual name = %ls", name);
            return TRUE;
        }
    }
    return FALSE;
}

/**
 * Request focus for a component. Returns whether successful;
 *
 * Bug ID 4944757 - requestFocus method needed
 */
BOOL
WinAccessBridge::requestFocus(long vmID, AccessibleContext accessibleContext) {

    if ((AccessBridgeJavaVMInstance *) 0 == javaVMs) {
        return FALSE;
    }
    char buffer[sizeof(PackageType) + sizeof(RequestFocusPackage)];
    PackageType *type = (PackageType *) buffer;
    RequestFocusPackage *pkg = (RequestFocusPackage *) (buffer + sizeof(PackageType));
    *type = cRequestFocusPackage;
    pkg->vmID = vmID;
    pkg->accessibleContext = accessibleContext;

#ifdef ACCESSBRIDGE_ARCH_LEGACY // JOBJECT64 is jobject (32 bit pointer)
    PrintDebugString("[INFO]: WinAccessBridge::requestFocus(%X, %p)", vmID, accessibleContext);
#else // JOBJECT64 is jlong (64 bit)
    PrintDebugString("[INFO]: WinAccessBridge::requestFocus(%X, %016I64X)", vmID, accessibleContext);
#endif
    // need to call only the HWND/VM that contains this AC
    HWND destABWindow = javaVMs->findAccessBridgeWindow(vmID);
    if (destABWindow != (HWND) 0) {
        if (sendMemoryPackage(buffer, sizeof(buffer), destABWindow) == TRUE) {
            return TRUE;
        }
    }
    return FALSE;
}

/**
 * Selects text between two indices.  Selection includes the text at the start index
 * and the text at the end index. Returns whether successful;
 *
 * Bug ID 4944758 - selectTextRange method needed
 */
BOOL
WinAccessBridge::selectTextRange(long vmID, AccessibleContext accessibleContext, int startIndex, int endIndex) {
    if ((AccessBridgeJavaVMInstance *) 0 == javaVMs) {
        return FALSE;
    }
    char buffer[sizeof(PackageType) + sizeof(SelectTextRangePackage)];
    PackageType *type = (PackageType *) buffer;
    SelectTextRangePackage *pkg = (SelectTextRangePackage *) (buffer + sizeof(PackageType));
    *type = cSelectTextRangePackage;
    pkg->vmID = vmID;
    pkg->accessibleContext = accessibleContext;
    pkg->startIndex = startIndex;
    pkg->endIndex = endIndex;

#ifdef ACCESSBRIDGE_ARCH_LEGACY // JOBJECT64 is jobject (32 bit pointer)
    PrintDebugString("[INFO]:     WinAccessBridge::selectTextRange(%X, %p %d %d)", vmID, accessibleContext,
                     startIndex, endIndex);
#else // JOBJECT64 is jlong (64 bit)
    PrintDebugString("[INFO]:     WinAccessBridge::selectTextRange(%X, %016I64X %d %d)", vmID, accessibleContext,
                     startIndex, endIndex);
#endif
    // need to call only the HWND/VM that contains this AC
    HWND destABWindow = javaVMs->findAccessBridgeWindow(vmID);
    if (destABWindow != (HWND) 0) {
        if (sendMemoryPackage(buffer, sizeof(buffer), destABWindow) == TRUE) {
            return TRUE;
        }
    }
    return FALSE;
}

/**
 * Get text attributes between two indices.  The attribute list includes the text at the
 * start index and the text at the end index. Returns whether successful;
 *
 * Bug ID 4944761 - getTextAttributes between two indices method needed
 */
BOOL
WinAccessBridge::getTextAttributesInRange(long vmID, AccessibleContext accessibleContext,
                                          int startIndex, int endIndex,
                                          AccessibleTextAttributesInfo *attributes, short *len) {

    if ((AccessBridgeJavaVMInstance *) 0 == javaVMs) {
        return FALSE;
    }
    char buffer[sizeof(PackageType) + sizeof(GetTextAttributesInRangePackage)];
    PackageType *type = (PackageType *) buffer;
    GetTextAttributesInRangePackage *pkg = (GetTextAttributesInRangePackage *) (buffer + sizeof(PackageType));
    *type = cGetTextAttributesInRangePackage;
    pkg->vmID = vmID;
    pkg->accessibleContext = accessibleContext;
    pkg->startIndex = startIndex;
    pkg->endIndex = endIndex;
    memcpy(&(pkg->attributes), attributes, sizeof(AccessibleTextAttributesInfo));


#ifdef ACCESSBRIDGE_ARCH_LEGACY // JOBJECT64 is jobject (32 bit pointer)
    PrintDebugString("[INFO]:     WinAccessBridge::getTextAttributesInRange(%X, %p %d %d)", vmID, accessibleContext,
                     startIndex, endIndex);
#else // JOBJECT64 is jlong (64 bit)
    PrintDebugString("[INFO]:     WinAccessBridge::getTextAttributesInRange(%X, %016I64X %d %d)", vmID, accessibleContext,
                     startIndex, endIndex);
#endif
    // need to call only the HWND/VM that contains this AC
    HWND destABWindow = javaVMs->findAccessBridgeWindow(vmID);
    if (destABWindow != (HWND) 0) {
        if (sendMemoryPackage(buffer, sizeof(buffer), destABWindow) == TRUE) {
            *attributes = pkg->attributes;
            *len = pkg->rLength;
            return TRUE;
        }
    }
    return FALSE;
}

/**
 * Gets the number of visible children of a component. Returns -1 on error.
 *
 * Bug ID 4944762- getVisibleChildren for list-like components needed
 */
int
WinAccessBridge::getVisibleChildrenCount(long vmID, AccessibleContext accessibleContext) {

    if ((AccessBridgeJavaVMInstance *) 0 == javaVMs) {
        return -1;
    }
    char buffer[sizeof(PackageType) + sizeof(GetVisibleChildrenCountPackage)];
    PackageType *type = (PackageType *) buffer;
    GetVisibleChildrenCountPackage *pkg = (GetVisibleChildrenCountPackage *) (buffer + sizeof(PackageType));
    *type = cGetVisibleChildrenCountPackage;
    pkg->vmID = vmID;
    pkg->accessibleContext = accessibleContext;

#ifdef ACCESSBRIDGE_ARCH_LEGACY // JOBJECT64 is jobject (32 bit pointer)
    PrintDebugString("[INFO]: WinAccessBridge::getVisibleChildrenCount(%X, %p)", vmID, accessibleContext);
#else // JOBJECT64 is jlong (64 bit)
    PrintDebugString("[INFO]: WinAccessBridge::getVisibleChildrenCount(%X, %016I64X)", vmID, accessibleContext);
#endif
    // need to call only the HWND/VM that contains this AC
    HWND destABWindow = javaVMs->findAccessBridgeWindow(vmID);
    if (destABWindow != (HWND) 0) {
        if (sendMemoryPackage(buffer, sizeof(buffer), destABWindow) == TRUE) {
            return pkg->rChildrenCount;
        }
    }
    return -1;
}

/**
 * Gets the visible children of an AccessibleContext. Returns whether successful;
 *
 * Bug ID 4944762- getVisibleChildren for list-like components needed
 */
BOOL
WinAccessBridge::getVisibleChildren(long vmID, AccessibleContext accessibleContext, int startIndex,
                                    VisibleChildrenInfo *visibleChildrenInfo) {

    if ((AccessBridgeJavaVMInstance *) 0 == javaVMs) {
        return FALSE;
    }
    char buffer[sizeof(PackageType) + sizeof(GetVisibleChildrenPackage)];
    PackageType *type = (PackageType *) buffer;
    GetVisibleChildrenPackage *pkg = (GetVisibleChildrenPackage *) (buffer + sizeof(PackageType));
    *type = cGetVisibleChildrenPackage;
    pkg->vmID = vmID;
    pkg->accessibleContext = accessibleContext;
    pkg->startIndex = startIndex;

#ifdef ACCESSBRIDGE_ARCH_LEGACY // JOBJECT64 is jobject (32 bit pointer)
    PrintDebugString("[INFO]: WinAccessBridge::getVisibleChildren(%X, %p)", vmID, accessibleContext);
#else // JOBJECT64 is jlong (64 bit)
    PrintDebugString("[INFO]: WinAccessBridge::getVisibleChildren(%X, %016I64X)", vmID, accessibleContext);
#endif
    // need to call only the HWND/VM that contains this AC
    HWND destABWindow = javaVMs->findAccessBridgeWindow(vmID);
    if (destABWindow != (HWND) 0) {
        if (sendMemoryPackage(buffer, sizeof(buffer), destABWindow) == TRUE) {
            memcpy(visibleChildrenInfo, &(pkg->rVisibleChildrenInfo), sizeof(pkg->rVisibleChildrenInfo));
            return pkg->rSuccess;
        }
    }
    return FALSE;
}

/**
 * Set the caret to a text position. Returns whether successful;
 *
 * Bug ID 4944770 - setCaretPosition method needed
 */
BOOL
WinAccessBridge::setCaretPosition(long vmID, AccessibleContext accessibleContext, int position) {

    if ((AccessBridgeJavaVMInstance *) 0 == javaVMs) {
        return FALSE;
    }
    char buffer[sizeof(PackageType) + sizeof(SetCaretPositionPackage)];
    PackageType *type = (PackageType *) buffer;
    SetCaretPositionPackage *pkg = (SetCaretPositionPackage *) (buffer + sizeof(PackageType));
    *type = cSetCaretPositionPackage;
    pkg->vmID = vmID;
    pkg->accessibleContext = accessibleContext;
    pkg->position = position;

#ifdef ACCESSBRIDGE_ARCH_LEGACY // JOBJECT64 is jobject (32 bit pointer)
    PrintDebugString("[INFO]: WinAccessBridge::setCaretPosition(%X, %p %ls)", vmID, accessibleContext);
#else // JOBJECT64 is jlong (64 bit)
    PrintDebugString("[INFO]: WinAccessBridge::setCaretPosition(%X, %016I64X %ls)", vmID, accessibleContext);
#endif
    // need to call only the HWND/VM that contains this AC
    HWND destABWindow = javaVMs->findAccessBridgeWindow(vmID);
    if (destABWindow != (HWND) 0) {
        if (sendMemoryPackage(buffer, sizeof(buffer), destABWindow) == TRUE) {
            return TRUE;
        }
    }
    return FALSE;
}


/********** AccessibleText routines ***********************************/

/**
 * getAccessibleTextInfo - fills a struct with a bunch of information
 * contained in the Java Accessibility AccessibleText API
 *
 *
 * Note: if the AccessibleContext parameter is bogus, this call will blow up
 */
BOOL
WinAccessBridge::getAccessibleTextInfo(long vmID,
                                       JOBJECT64 AccessibleContext,
                                       AccessibleTextInfo *textInfo,
                                       jint x, jint y) {
    if ((AccessBridgeJavaVMInstance *) 0 == javaVMs) {
        return FALSE;
    }
    char buffer[sizeof(PackageType) + sizeof(GetAccessibleTextInfoPackage)];
    PackageType *type = (PackageType *) buffer;
    GetAccessibleTextInfoPackage *pkg = (GetAccessibleTextInfoPackage *) (buffer + sizeof(PackageType));
    *type = cGetAccessibleTextInfoPackage;
    pkg->vmID = vmID;
    pkg->AccessibleContext = AccessibleContext;
    pkg->x = x;
    pkg->y = y;

#ifdef ACCESSBRIDGE_ARCH_LEGACY // JOBJECT64 is jobject (32 bit pointer)
    PrintDebugString("[INFO]: WinAccessBridge::getAccessibleTextInfo(%X, %p, %p, %d, %d)", vmID, AccessibleContext, textInfo, x, y);
#else // JOBJECT64 is jlong (64 bit)
    PrintDebugString("[INFO]: WinAccessBridge::getAccessibleTextInfo(%X, %016I64X, %p, %d, %d)", vmID, AccessibleContext, textInfo, x, y);
#endif
    // need to call only the HWND/VM that contains this AC
    HWND destABWindow = javaVMs->findAccessBridgeWindow(vmID);
    if (destABWindow != (HWND) 0) {
        if (sendMemoryPackage(buffer, sizeof(buffer), destABWindow) == TRUE) {
            memcpy(textInfo, &(pkg->rTextInfo), sizeof(AccessibleTextInfo));
            if (pkg->rTextInfo.charCount != -1) {
                PrintDebugString("[INFO]:   charCount: %d"\
                                 "          caretIndex: %d"\
                                 "          indexAtPoint: %d"\
                                 , textInfo->charCount, textInfo->caretIndex, textInfo->indexAtPoint);
                return TRUE;
            }
        }
    }

    return FALSE;
}

/**
 * getAccessibleTextItems - fills a struct with letter, word, and sentence info
 * of the AccessibleText interface at a given index
 *
 * Note: if the AccessibleContext parameter is bogus, this call will blow up
 */
BOOL
WinAccessBridge::getAccessibleTextItems(long vmID,
                                        JOBJECT64 AccessibleContext,
                                        AccessibleTextItemsInfo *textItems,
                                        jint index) {
    if ((AccessBridgeJavaVMInstance *) 0 == javaVMs) {
        return FALSE;
    }
    char buffer[sizeof(PackageType) + sizeof(GetAccessibleTextItemsPackage)];
    PackageType *type = (PackageType *) buffer;
    GetAccessibleTextItemsPackage *pkg = (GetAccessibleTextItemsPackage *) (buffer + sizeof(PackageType));
    *type = cGetAccessibleTextItemsPackage;
    pkg->vmID = vmID;
    pkg->AccessibleContext = AccessibleContext;
    pkg->index = index;
    // zero things out, in case the call fails
    pkg->rTextItemsInfo.letter = '\0';
    pkg->rTextItemsInfo.word[0] = '\0';
    pkg->rTextItemsInfo.sentence[0] = '\0';

#ifdef ACCESSBRIDGE_ARCH_LEGACY // JOBJECT64 is jobject (32 bit pointer)
    PrintDebugString("[INFO]: WinAccessBridge::getAccessibleTextItems(%X, %p, %p, %d)", vmID, AccessibleContext, textItems, index);
#else // JOBJECT64 is jlong (64 bit)
    PrintDebugString("[INFO]: WinAccessBridge::getAccessibleTextItems(%X, %016I64X, %p, %d)", vmID, AccessibleContext, textItems, index);
#endif
    // need to call only the HWND/VM that contains this AC
    HWND destABWindow = javaVMs->findAccessBridgeWindow(vmID);
    if (destABWindow != (HWND) 0) {
        if (sendMemoryPackage(buffer, sizeof(buffer), destABWindow) == TRUE) {
            memcpy(textItems, &(pkg->rTextItemsInfo), sizeof(AccessibleTextItemsInfo));
            if (pkg->rTextItemsInfo.letter != '/0') {
                return TRUE;
            }
        }
    }

    return FALSE;
}

/**
 * getAccessibleTextSelectionInfo - returns information about the selected
 * text of the object implementing AccessibleText
 *
 * Note: if the AccessibleContext parameter is bogus, this call will blow up
 */
BOOL
WinAccessBridge::getAccessibleTextSelectionInfo(long vmID,
                                                JOBJECT64 AccessibleContext,
                                                AccessibleTextSelectionInfo *selectionInfo) {
    if ((AccessBridgeJavaVMInstance *) 0 == javaVMs) {
        return FALSE;
    }
    char buffer[sizeof(PackageType) + sizeof(GetAccessibleTextSelectionInfoPackage)];
    PackageType *type = (PackageType *) buffer;
    GetAccessibleTextSelectionInfoPackage *pkg = (GetAccessibleTextSelectionInfoPackage *) (buffer + sizeof(PackageType));
    *type = cGetAccessibleTextSelectionInfoPackage;
    pkg->vmID = vmID;
    pkg->AccessibleContext = AccessibleContext;

#ifdef ACCESSBRIDGE_ARCH_LEGACY // JOBJECT64 is jobject (32 bit pointer)
    PrintDebugString("[INFO]: WinAccessBridge::getAccessibleTextSelectionInfo(%X, %p, %p)", vmID, AccessibleContext, selectionInfo);
#else // JOBJECT64 is jlong (64 bit)
    PrintDebugString("[INFO]: WinAccessBridge::getAccessibleTextSelectionInfo(%X, %016I64X, %p)", vmID, AccessibleContext, selectionInfo);
#endif
    // need to call only the HWND/VM that contains this AC
    HWND destABWindow = javaVMs->findAccessBridgeWindow(vmID);
    if (destABWindow != (HWND) 0) {
        if (sendMemoryPackage(buffer, sizeof(buffer), destABWindow) == TRUE) {
            memcpy(selectionInfo, &(pkg->rTextSelectionItemsInfo), sizeof(AccessibleTextSelectionInfo));
            // [[[FIXME]]] should test to see if valid info returned; return FALSE if not
            return TRUE;
        }
    }

    return FALSE;
}

/**
 * getAccessibleTextAttributes - performs the Java code:
 *   ...[[[FIXME]]] fill in this comment...
 *
 * Note: if the AccessibleContext parameter is bogus, this call will blow up
 */
BOOL
WinAccessBridge::getAccessibleTextAttributes(long vmID,
                                             JOBJECT64 AccessibleContext,
                                             jint index,
                                             AccessibleTextAttributesInfo *attributes) {
    if ((AccessBridgeJavaVMInstance *) 0 == javaVMs) {
        return FALSE;
    }
    char buffer[sizeof(PackageType) + sizeof(GetAccessibleTextAttributeInfoPackage)];
    PackageType *type = (PackageType *) buffer;
    GetAccessibleTextAttributeInfoPackage *pkg = (GetAccessibleTextAttributeInfoPackage *) (buffer + sizeof(PackageType));
    *type = cGetAccessibleTextAttributeInfoPackage;
    pkg->vmID = vmID;
    pkg->AccessibleContext = AccessibleContext;
    pkg->index = index;

#ifdef ACCESSBRIDGE_ARCH_LEGACY // JOBJECT64 is jobject (32 bit pointer)
    PrintDebugString("[INFO]: WinAccessBridge::getAccessibleTextAttributes(%X, %p, %d, %p)", vmID, AccessibleContext, index, attributes);
#else // JOBJECT64 is jlong (64 bit)
    PrintDebugString("[INFO]: WinAccessBridge::getAccessibleTextAttributes(%X, %016I64X, %d, %p)", vmID, AccessibleContext, index, attributes);
#endif
    // need to call only the HWND/VM that contains this AC
    HWND destABWindow = javaVMs->findAccessBridgeWindow(vmID);
    if (destABWindow != (HWND) 0) {
        if (sendMemoryPackage(buffer, sizeof(buffer), destABWindow) == TRUE) {
            memcpy(attributes, &(pkg->rAttributeInfo), sizeof(AccessibleTextAttributesInfo));
            return TRUE;
        }
    }

    return FALSE;
}

/**
 * getAccessibleTextRect - gets the text bounding rectangle
 *
 * Note: if the AccessibleContext parameter is bogus, this call will blow up
 */
BOOL
WinAccessBridge::getAccessibleTextRect(long vmID,
                                       JOBJECT64 AccessibleContext,
                                       AccessibleTextRectInfo *rectInfo,
                                       jint index) {
    if ((AccessBridgeJavaVMInstance *) 0 == javaVMs) {
        return FALSE;
    }
    char buffer[sizeof(PackageType) + sizeof(GetAccessibleTextRectInfoPackage)];
    PackageType *type = (PackageType *) buffer;
    GetAccessibleTextRectInfoPackage *pkg = (GetAccessibleTextRectInfoPackage *) (buffer + sizeof(PackageType));
    *type = cGetAccessibleTextRectInfoPackage;
    pkg->vmID = vmID;
    pkg->AccessibleContext = AccessibleContext;
    pkg->index = index;

#ifdef ACCESSBRIDGE_ARCH_LEGACY // JOBJECT64 is jobject (32 bit pointer)
    PrintDebugString("[INFO]: WinAccessBridge::getAccessibleTextRect(%X, %p, %p, %d)", vmID, AccessibleContext, rectInfo, index);
#else // JOBJECT64 is jlong (64 bit)
    PrintDebugString("[INFO]: WinAccessBridge::getAccessibleTextRect(%X, %016I64X, %p, %d)", vmID, AccessibleContext, rectInfo, index);
#endif
    // need to call only the HWND/VM that contains this AC
    HWND destABWindow = javaVMs->findAccessBridgeWindow(vmID);
    if (destABWindow != (HWND) 0) {
        if (sendMemoryPackage(buffer, sizeof(buffer), destABWindow) == TRUE) {
            memcpy(rectInfo, (&pkg->rTextRectInfo), sizeof(AccessibleTextRectInfo));
            // [[[FIXME]]] should test to see if valid info returned; return FALSE if not
            return TRUE;
        }
    }

    return FALSE;
}


/**
 * getAccessibleTextRect - gets the text bounding rectangle
 *
 * Note: if the AccessibleContext parameter is bogus, this call will blow up
 */
BOOL
WinAccessBridge::getCaretLocation(long vmID,
                                       JOBJECT64 AccessibleContext,
                                       AccessibleTextRectInfo *rectInfo,
                                       jint index) {
    if ((AccessBridgeJavaVMInstance *) 0 == javaVMs) {
        return FALSE;
    }
    char buffer[sizeof(PackageType) + sizeof(GetCaretLocationPackage)];
    PackageType *type = (PackageType *) buffer;
    GetCaretLocationPackage *pkg = (GetCaretLocationPackage *) (buffer + sizeof(PackageType));
    *type = cGetCaretLocationPackage;
    pkg->vmID = vmID;
    pkg->AccessibleContext = AccessibleContext;
    pkg->index = index;

#ifdef ACCESSBRIDGE_ARCH_LEGACY // JOBJECT64 is jobject (32 bit pointer)
    PrintDebugString("[INFO]: WinAccessBridge::getCaretLocation(%X, %p, %p, %d)", vmID, AccessibleContext, rectInfo, index);
#else // JOBJECT64 is jlong (64 bit)
    PrintDebugString("[INFO]: WinAccessBridge::getCaretLocation(%X, %016I64X, %p, %d)", vmID, AccessibleContext, rectInfo, index);
#endif
    // need to call only the HWND/VM that contains this AC
    HWND destABWindow = javaVMs->findAccessBridgeWindow(vmID);
    if (destABWindow != (HWND) 0) {
        if (sendMemoryPackage(buffer, sizeof(buffer), destABWindow) == TRUE) {
            memcpy(rectInfo, (&pkg->rTextRectInfo), sizeof(AccessibleTextRectInfo));
            return TRUE;
        }
    }

    return FALSE;
}


/**
 * getEventsWaiting - gets the number of events waiting to fire
 *
 * Note: if the AccessibleContext parameter is bogus, this call will blow up
 */
int
WinAccessBridge::getEventsWaiting() {
    if(messageQueue) {
        return(messageQueue->getEventsWaiting());
    }
    return(0);
}


/**
 * getAccessibleTextLineBounds - gets the bounding rectangle for the text line
 *
 * Note: if the AccessibleContext parameter is bogus, this call will blow up
 */
BOOL
WinAccessBridge::getAccessibleTextLineBounds(long vmID,
                                             JOBJECT64 AccessibleContext,
                                             jint index, jint *startIndex, jint *endIndex) {
    if ((AccessBridgeJavaVMInstance *) 0 == javaVMs) {
        return FALSE;
    }
    char buffer[sizeof(PackageType) + sizeof(GetAccessibleTextLineBoundsPackage)];
    PackageType *type = (PackageType *) buffer;
    GetAccessibleTextLineBoundsPackage *pkg = (GetAccessibleTextLineBoundsPackage *) (buffer + sizeof(PackageType));
    *type = cGetAccessibleTextLineBoundsPackage;
    pkg->vmID = vmID;
    pkg->AccessibleContext = AccessibleContext;
    pkg->index = index;

#ifdef ACCESSBRIDGE_ARCH_LEGACY // JOBJECT64 is jobject (32 bit pointer)
    PrintDebugString("[INFO]: WinAccessBridge::getAccessibleTextLineBounds(%X, %p, %d, )", vmID, AccessibleContext, index);
#else // JOBJECT64 is jlong (64 bit)
    PrintDebugString("[INFO]: WinAccessBridge::getAccessibleTextLineBounds(%X, %016I64X, %d, )", vmID, AccessibleContext, index);
#endif
    // need to call only the HWND/VM that contains this AC
    HWND destABWindow = javaVMs->findAccessBridgeWindow(vmID);
    if (destABWindow != (HWND) 0) {
        if (sendMemoryPackage(buffer, sizeof(buffer), destABWindow) == TRUE) {
            *startIndex = pkg->rLineStart;
            *endIndex = pkg->rLineEnd;
            // [[[FIXME]]] should test to see if valid info returned; return FALSE if not
            return TRUE;
        }
    }

    return FALSE;
}


/**
 * getAccessibleTextLineBounds - performs the Java code:
 *   ...[[[FIXME]]] fill in this comment...
 *
 * Note: if the AccessibleContext parameter is bogus, this call will blow up
 */
BOOL
WinAccessBridge::getAccessibleTextRange(long vmID,
                                        JOBJECT64 AccessibleContext,
                                        jint start, jint end, wchar_t *text, short len) {
    if ((AccessBridgeJavaVMInstance *) 0 == javaVMs) {
        return FALSE;
    }
    char buffer[sizeof(PackageType) + sizeof(GetAccessibleTextRangePackage)];
    PackageType *type = (PackageType *) buffer;
    GetAccessibleTextRangePackage *pkg = (GetAccessibleTextRangePackage *) (buffer + sizeof(PackageType));
    *type = cGetAccessibleTextRangePackage;
    pkg->vmID = vmID;
    pkg->AccessibleContext = AccessibleContext;
    pkg->start = start;
    pkg->end = end;

#ifdef ACCESSBRIDGE_ARCH_LEGACY // JOBJECT64 is jobject (32 bit pointer)
    PrintDebugString("[INFO]: WinAccessBridge::getAccessibleTextRange(%X, %p, %d, %d, )", vmID, AccessibleContext, start, end);
#else // JOBJECT64 is jlong (64 bit)
    PrintDebugString("[INFO]: WinAccessBridge::getAccessibleTextRange(%X, %016I64X, %d, %d, )", vmID, AccessibleContext, start, end);
#endif
    // need to call only the HWND/VM that contains this AC
    HWND destABWindow = javaVMs->findAccessBridgeWindow(vmID);
    if (destABWindow != (HWND) 0) {
        if (sendMemoryPackage(buffer, sizeof(buffer), destABWindow) == TRUE) {
            wcsncpy(text, pkg->rText, len);
            // [[[FIXME]]] should test to see if valid info returned; return FALSE if not
            return TRUE;
        }
    }

    return FALSE;
}




/********** AccessibleValue routines ***************/

BOOL
WinAccessBridge::getCurrentAccessibleValueFromContext(long vmID,
                                                      JOBJECT64 AccessibleContext,
                                                      wchar_t *value, short len) {
    if ((AccessBridgeJavaVMInstance *) 0 == javaVMs) {
        return FALSE;
    }
    char buffer[sizeof(PackageType) + sizeof(GetCurrentAccessibleValueFromContextPackage)];
    PackageType *type = (PackageType *) buffer;
    GetCurrentAccessibleValueFromContextPackage *pkg = (GetCurrentAccessibleValueFromContextPackage *) (buffer + sizeof(PackageType));
    *type = cGetCurrentAccessibleValueFromContextPackage;
    pkg->vmID = vmID;
    pkg->AccessibleContext = AccessibleContext;

    // need to call only the HWND/VM that contains this AC
    HWND destABWindow = javaVMs->findAccessBridgeWindow(vmID);
    if (destABWindow != (HWND) 0) {
        if (sendMemoryPackage(buffer, sizeof(buffer), destABWindow) == TRUE) {
            wcsncpy(value, pkg->rValue, len);
            // [[[FIXME]]] should test to see if valid info returned; return FALSE if not
            return TRUE;
        }
    }

    return FALSE;
}

BOOL
WinAccessBridge::getMaximumAccessibleValueFromContext(long vmID,
                                                      JOBJECT64 AccessibleContext,
                                                      wchar_t *value, short len) {
    if ((AccessBridgeJavaVMInstance *) 0 == javaVMs) {
        return FALSE;
    }
    char buffer[sizeof(PackageType) + sizeof(GetMaximumAccessibleValueFromContextPackage)];
    PackageType *type = (PackageType *) buffer;
    GetMaximumAccessibleValueFromContextPackage *pkg = (GetMaximumAccessibleValueFromContextPackage *) (buffer + sizeof(PackageType));
    *type = cGetMaximumAccessibleValueFromContextPackage;
    pkg->vmID = vmID;
    pkg->AccessibleContext = AccessibleContext;

    // need to call only the HWND/VM that contains this AC
    HWND destABWindow = javaVMs->findAccessBridgeWindow(vmID);
    if (destABWindow != (HWND) 0) {
        if (sendMemoryPackage(buffer, sizeof(buffer), destABWindow) == TRUE) {
            wcsncpy(value, pkg->rValue, len);
            // [[[FIXME]]] should test to see if valid info returned; return FALSE if not
            return TRUE;
        }
    }

    return FALSE;
}

BOOL
WinAccessBridge::getMinimumAccessibleValueFromContext(long vmID,
                                                      JOBJECT64 AccessibleContext,
                                                      wchar_t *value, short len) {
    if ((AccessBridgeJavaVMInstance *) 0 == javaVMs) {
        return FALSE;
    }
    char buffer[sizeof(PackageType) + sizeof(GetMinimumAccessibleValueFromContextPackage)];
    PackageType *type = (PackageType *) buffer;
    GetMinimumAccessibleValueFromContextPackage *pkg = (GetMinimumAccessibleValueFromContextPackage *) (buffer + sizeof(PackageType));
    *type = cGetMinimumAccessibleValueFromContextPackage;
    pkg->vmID = vmID;
    pkg->AccessibleContext = AccessibleContext;

    // need to call only the HWND/VM that contains this AC
    HWND destABWindow = javaVMs->findAccessBridgeWindow(vmID);
    if (destABWindow != (HWND) 0) {
        if (sendMemoryPackage(buffer, sizeof(buffer), destABWindow) == TRUE) {
            wcsncpy(value, pkg->rValue, len);
            // [[[FIXME]]] should test to see if valid info returned; return FALSE if not
            return TRUE;
        }
    }

    return FALSE;
}


/********** AccessibleSelection routines ***************/

void
WinAccessBridge::addAccessibleSelectionFromContext(long vmID,
                                                   JOBJECT64 AccessibleContext, int i) {
    if ((AccessBridgeJavaVMInstance *) 0 == javaVMs) {
        return;
    }
    char buffer[sizeof(PackageType) + sizeof(AddAccessibleSelectionFromContextPackage)];
    PackageType *type = (PackageType *) buffer;
    AddAccessibleSelectionFromContextPackage *pkg = (AddAccessibleSelectionFromContextPackage *) (buffer + sizeof(PackageType));
    *type = cAddAccessibleSelectionFromContextPackage;
    pkg->vmID = vmID;
    pkg->AccessibleContext = AccessibleContext;
    pkg->index = i;

    // need to call only the HWND/VM that contains this AC
    HWND destABWindow = javaVMs->findAccessBridgeWindow(vmID);
    if (destABWindow != (HWND) 0) {
        sendMemoryPackage(buffer, sizeof(buffer), destABWindow);
    }
}

void

/**代码未完, 请加载全部代码(NowJava.com).**/
展开阅读全文

关注时代Java

关注时代Java