1 /*
2  * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 #include "jaccesswalker.h"
27 #include "AccessInfo.h"
28 
29 HWND ourHwnd;
30 HWND topLevelWindow;
31 int depth = -1;
32 FILE *logfile;
33 HMENU popupMenu;
34 
35 char theJaccesswalkerClassName[] = "JaccesswalkerWin";
36 char theAccessInfoClassName[] = "AccessInfoWin";
37 
38 HWND theJaccesswalkerWindow;
39 HWND theTreeControlWindow;
40 HINSTANCE theInstance;
41 Jaccesswalker *theJaccesswalker;
42 AccessibleNode *theSelectedNode;
43 AccessibleNode *thePopupNode;
44 AccessibleContext theSelectedAccessibleContext;
45 HWND hwndTV;    // handle of tree-view control
46 
WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)47 int APIENTRY WinMain(HINSTANCE hInstance,
48                      HINSTANCE hPrevInstance,
49                      LPSTR     lpCmdLine,
50                      int       nCmdShow)
51 {
52 
53     if (logfile == null) {
54         logfile = fopen(JACCESSWALKER_LOG, "w"); // overwrite existing log file
55         logString(logfile, "Starting jaccesswalker.exe %s\n", getTimeAndDate());
56     }
57 
58     theInstance = hInstance;
59 
60     // start Jaccesswalker
61     theJaccesswalker = new Jaccesswalker(nCmdShow);
62 
63     return 0;
64 }
65 
Jaccesswalker(int nCmdShow)66 Jaccesswalker::Jaccesswalker(int nCmdShow) {
67 
68     HWND hwnd;
69     static char szAppName[] = "jaccesswalker";
70     static char szMenuName[] = "JACCESSWALKERMENU";
71     MSG msg;
72     WNDCLASSEX wc;
73 
74     // jaccesswalker window
75     wc.cbSize = sizeof(wc);
76     wc.style = CS_HREDRAW | CS_VREDRAW;
77     wc.lpfnWndProc = WinProc;
78     wc.cbClsExtra = 0;
79     wc.cbWndExtra = 0;
80     wc.hInstance = theInstance;
81     wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
82     wc.hCursor = LoadCursor(NULL, IDI_APPLICATION);
83     wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
84     wc.lpszMenuName = szMenuName;
85     wc.lpszClassName = szAppName;
86     wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
87 
88     RegisterClassEx(&wc);
89 
90     // AccessInfo Window
91     wc.cbSize = sizeof(WNDCLASSEX);
92 
93     wc.hInstance = theInstance;
94     wc.lpszClassName = theAccessInfoClassName;
95     wc.lpfnWndProc = (WNDPROC)AccessInfoWindowProc;
96     wc.style = 0;
97 
98     wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
99     wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
100     wc.hCursor = LoadCursor(NULL, IDC_ARROW);
101 
102     wc.lpszMenuName = "";
103     wc.cbClsExtra = 0;
104     wc.cbWndExtra = 0;
105 
106     wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
107 
108     RegisterClassEx(&wc);
109 
110     // create the jaccesswalker window
111     hwnd = CreateWindow(szAppName,
112                         szAppName,
113                         WS_OVERLAPPEDWINDOW,
114                         CW_USEDEFAULT,
115                         CW_USEDEFAULT,
116                         CW_USEDEFAULT,
117                         CW_USEDEFAULT,
118                         NULL,
119                         NULL,
120                         theInstance,
121                         NULL);
122 
123     ourHwnd = hwnd;
124 
125     /* Initialize the common controls. */
126     INITCOMMONCONTROLSEX cc;
127     cc.dwSize = sizeof(INITCOMMONCONTROLSEX);
128     cc.dwICC = ICC_TREEVIEW_CLASSES;
129     InitCommonControlsEx(&cc);
130 
131     ShowWindow(hwnd, nCmdShow);
132 
133     UpdateWindow(hwnd);
134 
135     BOOL result = initializeAccessBridge();
136     if (result != FALSE) {
137         while (GetMessage(&msg, NULL, 0, 0)) {
138             TranslateMessage(&msg);
139             DispatchMessage(&msg);
140         }
141         shutdownAccessBridge();
142     }
143 }
144 
145 /*
146  * the jaccesswalker window proc
147  */
WinProc(HWND hwnd,UINT iMsg,WPARAM wParam,LPARAM lParam)148 LRESULT CALLBACK WinProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) {
149 
150     int command;
151     short width, height;
152 
153     switch(iMsg) {
154 
155     case WM_CREATE:
156         // create the accessibility tree view
157         theTreeControlWindow = CreateATreeView(hwnd);
158 
159         // load the popup menu
160         popupMenu = LoadMenu(theInstance, "PopupMenu");
161         popupMenu = GetSubMenu(popupMenu, 0);
162         break;
163 
164     case WM_CLOSE:
165         EndDialog(hwnd, TRUE);
166         PostQuitMessage (0);
167         break;
168 
169     case WM_SIZE:
170         width = LOWORD(lParam);
171         height = HIWORD(lParam);
172         SetWindowPos(theTreeControlWindow, NULL, 0, 0, width, height, 0);
173         return FALSE;  // let windows finish handling this
174 
175     case WM_COMMAND:
176         command = LOWORD(wParam);
177         switch(command) {
178 
179         case cExitMenuItem:
180             EndDialog(hwnd, TRUE);
181             PostQuitMessage (0);
182             break;
183 
184         case cRefreshTreeItem:
185             // update the accessibility tree
186             theJaccesswalker->buildAccessibilityTree();
187             break;
188 
189         case cAPIMenuItem:
190             // open a new window with the Accessibility API in it for the
191             // selected element in the tree
192             if (theSelectedNode != (AccessibleNode *) 0) {
193                 theSelectedNode->displayAPIWindow();
194             }
195             break;
196 
197         case cAPIPopupItem:
198             // open a new window with the Accessibility API in it for the
199             // element in the tree adjacent to the popup menu
200             if (thePopupNode != (AccessibleNode *) 0) {
201                 thePopupNode->displayAPIWindow();
202             }
203             break;
204 
205         }
206         break;
207 
208     case WM_NOTIFY:  // receive tree messages
209 
210         NMTREEVIEW *nmptr = (LPNMTREEVIEW) lParam;
211         switch (nmptr->hdr.code) {
212 
213         case TVN_SELCHANGED:
214             // get the selected tree node
215             theSelectedNode = (AccessibleNode *) nmptr->itemNew.lParam;
216             break;
217 
218         case NM_RCLICK:
219 
220             // display a popup menu over the tree node
221             POINT p;
222             GetCursorPos(&p);
223             TrackPopupMenu(popupMenu, 0, p.x, p.y, 0, hwnd, NULL);
224 
225             // get the tree node under the popup menu
226             TVHITTESTINFO hitinfo;
227             ScreenToClient(theTreeControlWindow, &p);
228             hitinfo.pt = p;
229             HTREEITEM node = TreeView_HitTest(theTreeControlWindow, &hitinfo);
230 
231             if (node != null) {
232                 TVITEMEX tvItem;
233                 tvItem.hItem = node;
234                 if (TreeView_GetItem(hwndTV, &tvItem) == TRUE) {
235                     thePopupNode = (AccessibleNode *)tvItem.lParam;
236                 }
237             }
238             break;
239         }
240     }
241     return DefWindowProc(hwnd, iMsg, wParam, lParam);
242 }
243 
244 /*
245  * Accessibility information window proc
246  */
AccessInfoWindowProc(HWND hWnd,UINT message,UINT wParam,LONG lParam)247 LRESULT CALLBACK AccessInfoWindowProc(HWND hWnd, UINT message,
248                                     UINT wParam, LONG lParam) {
249     short width, height;
250     HWND dlgItem;
251 
252     switch (message) {
253     case WM_CREATE:
254         RECT rcClient;    // dimensions of client area
255         HWND hwndEdit;    // handle of tree-view control
256 
257         // Get the dimensions of the parent window's client area,
258         // and create the edit control.
259         GetClientRect(hWnd, &rcClient);
260         hwndEdit = CreateWindow("Edit",
261                                 "",
262                                 WS_VISIBLE | WS_TABSTOP | WS_CHILD |
263                                 ES_MULTILINE | ES_AUTOVSCROLL |
264                                 ES_READONLY | WS_VSCROLL,
265                                 0, 0, rcClient.right, rcClient.bottom,
266                                 hWnd,
267                                 (HMENU) cAccessInfoText,
268                                 theInstance,
269                                 NULL);
270         break;
271 
272     case WM_CLOSE:
273         DestroyWindow(hWnd);
274         break;
275 
276     case WM_SIZE:
277         width = LOWORD(lParam);
278         height = HIWORD(lParam);
279         dlgItem = GetDlgItem(hWnd, cAccessInfoText);
280         SetWindowPos(dlgItem, NULL, 0, 0, width, height, 0);
281         return FALSE;  // let windows finish handling this
282         break;
283 
284     default:
285         return DefWindowProc(hWnd, message, wParam, lParam);
286     }
287 
288     return 0;
289 }
290 
291 /**
292  * Build a tree (and the treeview control) of all accessible Java components
293  *
294  */
buildAccessibilityTree()295 void Jaccesswalker::buildAccessibilityTree() {
296     TreeView_DeleteAllItems (theTreeControlWindow);
297     // have MS-Windows call EnumWndProc() with all of the top-level windows
298     EnumWindows((WNDENUMPROC) EnumWndProc, NULL);
299 }
300 
301 /**
302  * Create (and display) the accessible component nodes of a parent AccessibleContext
303  *
304  */
EnumWndProc(HWND hwnd,LPARAM lParam)305 BOOL CALLBACK EnumWndProc(HWND hwnd, LPARAM lParam) {
306     if (IsJavaWindow(hwnd)) {
307         long vmID;
308         AccessibleContext ac;
309         if (GetAccessibleContextFromHWND(hwnd, &vmID, &ac) == TRUE) {
310             theJaccesswalker->addComponentNodes(vmID, ac, (AccessibleNode *) NULL,
311                                          hwnd, TVI_ROOT, theTreeControlWindow);
312         }
313         topLevelWindow = hwnd;
314     } else {
315         char szClass [MAX_PATH] = {0};
316         ::GetClassNameA(hwnd, szClass, sizeof(szClass) - 1);
317         if ( ( 0 == ::strcmp(szClass, "IEFrame") )
318              || ( 0 == ::strcmp(szClass, "MozillaUIWindowClass") ) ) {
319             EnumChildWindows(hwnd, (WNDENUMPROC) EnumChildProc, NULL);
320         }
321     }
322     return TRUE;
323 }
324 
325 /*
326 Detects whether or not the specified Java window is one from which no useable
327 information can be obtained.
328 
329 This function tests for various scenarios I have seen in Java applets where the
330 Java applet had no meaningful accessible information.  It does not detect all
331 scenarios, just the most common ones.
332 */
IsInaccessibleJavaWindow(const HWND hwnd)333 BOOL IsInaccessibleJavaWindow(const HWND hwnd)
334 {
335     BOOL ret_val ( FALSE );
336     {
337         BOOL bT ( FALSE );
338         long vmIdWindow ( 0 );
339         AccessibleContext acWindow ( 0 );
340         bT = GetAccessibleContextFromHWND(hwnd, &vmIdWindow, &acWindow);
341         if ( ( bT ) && ( 0 != vmIdWindow ) && ( 0 != acWindow ) ) {
342             AccessibleContextInfo infoWindow = {0};
343             bT = GetAccessibleContextInfo(vmIdWindow, acWindow, &infoWindow);
344             if ( ( bT )
345                  && ( 0 == infoWindow.name [0] )
346                  && ( 0 == infoWindow.description [0] )
347                  && ( 0 == ::wcscmp(infoWindow.role_en_US, L"frame") ) ) {
348                 if ( 0 == infoWindow.childrenCount ) {
349                     ret_val = TRUE;
350                 } else if ( 1 == infoWindow.childrenCount ) {
351                     AccessibleContext acChild ( 0 );
352                     acChild =
353                         GetAccessibleChildFromContext(vmIdWindow, acWindow, 0);
354                     if ( NULL != acChild ) {
355                         AccessibleContextInfo infoChild = {0};
356                         bT = GetAccessibleContextInfo( vmIdWindow, acChild,
357                                                        &infoChild );
358                         if ( ( bT )
359                              && ( 0 == infoChild.name [0] )
360                              && ( 0 == infoChild.description [0] )
361                              && ( 0 == ::wcscmp(infoChild.role_en_US, L"panel") )
362                              && ( 1 == infoChild.childrenCount ) ) {
363                             AccessibleContext acChild1 ( 0 );
364                             acChild1 = GetAccessibleChildFromContext( vmIdWindow,
365                                                                       acChild, 0);
366                             if ( NULL != acChild1 ) {
367                                 AccessibleContextInfo infoChild1 = {0};
368                                 bT = GetAccessibleContextInfo( vmIdWindow,
369                                                                acChild1, &infoChild1 );
370                                 if ( ( bT )
371                                      && ( 0 == infoChild1.name [0] )
372                                      && ( 0 == infoChild1.description [0] )
373                                      && ( 0 == ::wcscmp(infoChild1.role_en_US, L"frame") )
374                                      && ( 0 == infoChild1.childrenCount ) ) {
375                                     ret_val = TRUE;
376                                 } else if ( ( bT )
377                                             && ( 0 == infoChild1.name [0] )
378                                             && ( 0 == infoChild1.description [0] )
379                                             && ( 0 == ::wcscmp( infoChild1.role_en_US,
380                                                                 L"panel") )
381                                             && ( 1 == infoChild1.childrenCount ) ) {
382                                     AccessibleContext acChild2 ( 0 );
383                                     acChild2 = GetAccessibleChildFromContext(
384                                                     vmIdWindow, acChild1, 0 );
385                                     if ( NULL != acChild2 ) {
386                                         AccessibleContextInfo infoChild2 = {0};
387                                         bT = GetAccessibleContextInfo(
388                                                 vmIdWindow, acChild2, &infoChild2 );
389                                         if ( ( bT )
390                                              && ( 0 == infoChild2.name [0] )
391                                              && ( 0 == infoChild2.description [0] )
392                                              && ( 0 == ::wcscmp( infoChild2.role_en_US,
393                                                                  L"frame") )
394                                              && ( 0 == infoChild2.childrenCount ) ) {
395                                             ret_val = TRUE;
396                                         }
397                                     }
398                                 }
399                             }
400                         } else if ( ( bT )
401                                     && ( 0 == infoChild.name [0] )
402                                     && ( 0 == infoChild.description [0] )
403                                     && ( 0 == ::wcscmp( infoChild.role_en_US,
404                                                         L"canvas") )
405                                     && ( 0 == infoChild.childrenCount ) ) {
406                             ret_val = TRUE;
407                         }
408                     }
409                 }
410             } else if ( ( bT )
411                         && ( 0 == infoWindow.name [0] )
412                         && ( 0 == infoWindow.description [0] )
413                         && ( 0 == ::wcscmp(infoWindow.role_en_US, L"panel") ) ) {
414                 if ( 1 == infoWindow.childrenCount ) {
415                     AccessibleContext acChild ( 0 );
416                     acChild = GetAccessibleChildFromContext( vmIdWindow,
417                                                              acWindow, 0 );
418                     if ( NULL != acChild ) {
419                         AccessibleContextInfo infoChild = {0};
420                         bT = GetAccessibleContextInfo( vmIdWindow,
421                                                        acChild, &infoChild );
422                         if ( ( bT )
423                              && ( 0 == infoChild.name [0] )
424                              && ( 0 == infoChild.description [0] )
425                              && ( 0 == ::wcscmp(infoChild.role_en_US, L"frame") )
426                              && ( 0 == infoChild.childrenCount ) ) {
427                                 ret_val = TRUE;
428                         } else if ( ( bT )
429                                     && ( 0 == infoChild.name [0] )
430                                     && ( 0 == infoChild.description [0] )
431                                     && ( 0 == ::wcscmp( infoChild.role_en_US,
432                                                         L"panel") )
433                                     && ( 1 == infoChild.childrenCount ) ) {
434                             AccessibleContext acChild1 ( 0 );
435                             acChild1 = GetAccessibleChildFromContext( vmIdWindow,
436                                                                       acChild, 0);
437                             if ( NULL != acChild1 ) {
438                                 AccessibleContextInfo infoChild1 = {0};
439                                 bT = GetAccessibleContextInfo( vmIdWindow,
440                                                                acChild1,
441                                                                &infoChild1 );
442                                 if ( ( bT )
443                                      && ( 0 == infoChild1.name [0] )
444                                      && ( 0 == infoChild1.description [0] )
445                                      && ( 0 == ::wcscmp( infoChild1.role_en_US,
446                                                          L"frame") )
447                                      && ( 0 == infoChild1.childrenCount ) ) {
448                                     ret_val = TRUE;
449                                 }
450                             }
451                         }
452                     }
453                 }
454             }
455         } else if ( FALSE == bT ) {
456             ret_val = TRUE;
457         }
458     }
459     return ret_val;
460 }
461 
EnumChildProc(HWND hwnd,LPARAM lParam)462 BOOL CALLBACK EnumChildProc(HWND hwnd, LPARAM lParam)
463 {
464     if ( ( IsJavaWindow(hwnd) )
465          && ( FALSE == IsInaccessibleJavaWindow(hwnd) ) ) {
466         long vmID ( 0 );
467         AccessibleContext ac ( 0 );
468         if ( TRUE == GetAccessibleContextFromHWND(hwnd, &vmID, &ac) ) {
469             theJaccesswalker->addComponentNodes(
470                 vmID, ac, (AccessibleNode *) NULL,
471                 hwnd, TVI_ROOT, theTreeControlWindow);
472         }
473         topLevelWindow = hwnd;
474     } else {
475         EnumChildWindows(hwnd, (WNDENUMPROC) EnumChildProc, NULL);
476     }
477     return TRUE;
478 }
479 
480 // CreateATreeView - creates a tree-view control.
481 // Returns the handle of the new control if successful or NULL
482 //     otherwise.
483 // hwndParent - handle of the control's parent window
CreateATreeView(HWND hwndParent)484 HWND CreateATreeView(HWND hwndParent) {
485     RECT rcClient;  // dimensions of client area
486 
487     // Get the dimensions of the parent window's client area, and create
488     // the tree-view control.
489     GetClientRect(hwndParent, &rcClient);
490     hwndTV = CreateWindow(WC_TREEVIEW,
491                           "",
492                           WS_VISIBLE | WS_TABSTOP | WS_CHILD |
493                           TVS_HASLINES | TVS_HASBUTTONS |
494                           TVS_LINESATROOT,
495                           0, 0, rcClient.right, rcClient.bottom,
496                           hwndParent,
497                           (HMENU) cTreeControl,
498                           theInstance,
499                           NULL);
500 
501     return hwndTV;
502 }
503 
504 /**
505  * Create (and display) the accessible component nodes of a parent AccessibleContext
506  *
507  */
addComponentNodes(long vmID,AccessibleContext context,AccessibleNode * parent,HWND hwnd,HTREEITEM treeNodeParent,HWND treeWnd)508 void Jaccesswalker::addComponentNodes(long vmID, AccessibleContext context,
509                                     AccessibleNode *parent, HWND hwnd,
510                                     HTREEITEM treeNodeParent, HWND treeWnd) {
511 
512     AccessibleNode *newNode = new AccessibleNode( vmID, context, parent, hwnd,
513                                                   treeNodeParent );
514 
515     AccessibleContextInfo info;
516     if (GetAccessibleContextInfo(vmID, context, &info) != FALSE) {
517         char s[LINE_BUFSIZE];
518 
519         wsprintf(s, "%ls", info.name);
520         newNode->setAccessibleName(s);
521         wsprintf(s, "%ls", info.role);
522         newNode->setAccessibleRole(s);
523 
524         wsprintf(s, "%ls [%ls]", info.name, info.role);
525 
526         TVITEM tvi;
527         tvi.mask = TVIF_PARAM | TVIF_TEXT;
528         tvi.pszText = (char *) s; // Accessible name and role
529         tvi.cchTextMax = (int)strlen(s);
530         tvi.lParam = (LPARAM) newNode; // Accessibility information
531 
532         TVINSERTSTRUCT tvis;
533         tvis.hParent = treeNodeParent;
534         tvis.hInsertAfter = TVI_LAST;
535         tvis.item = tvi;
536 
537         HTREEITEM treeNodeItem = TreeView_InsertItem(treeWnd, &tvis);
538 
539         for (int i = 0; i < info.childrenCount; i++) {
540             addComponentNodes(vmID, GetAccessibleChildFromContext(vmID, context, i),
541                               newNode, hwnd, treeNodeItem, treeWnd);
542         }
543     } else {
544         char s[LINE_BUFSIZE];
545         sprintf( s,
546             "ERROR calling GetAccessibleContextInfo; vmID = %X, context = %p",
547             vmID, (void*)context );
548 
549         TVITEM tvi;
550         tvi.mask = TVIF_PARAM | TVIF_TEXT;  // text and lParam are only valid parts
551         tvi.pszText = (char *) s;
552         tvi.cchTextMax = (int)strlen(s);
553         tvi.lParam = (LPARAM) newNode;
554 
555         TVINSERTSTRUCT tvis;
556         tvis.hParent = treeNodeParent;
557         tvis.hInsertAfter = TVI_LAST;  // make tree in order given
558         tvis.item = tvi;
559 
560         HTREEITEM treeNodeItem = TreeView_InsertItem(treeWnd, &tvis);
561     }
562 }
563 
564 // -----------------------------
565 
566 /**
567  * Create an AccessibleNode
568  *
569  */
AccessibleNode(long JavaVMID,AccessibleContext context,AccessibleNode * parent,HWND hwnd,HTREEITEM parentTreeNodeItem)570 AccessibleNode::AccessibleNode(long JavaVMID, AccessibleContext context,
571                                AccessibleNode *parent, HWND hwnd,
572                                HTREEITEM parentTreeNodeItem) {
573     vmID = JavaVMID;
574     ac = context;
575     parentNode = parent;
576     baseHWND = hwnd;
577     treeNodeParent = parentTreeNodeItem;
578 
579     // setting accessibleName and accessibleRole not done here,
580     // in order to minimize calls to the AccessBridge
581     // (since such a call is needed to enumerate children)
582 }
583 
584 /**
585  * Destroy an AccessibleNode
586  *
587  */
~AccessibleNode()588 AccessibleNode::~AccessibleNode() {
589     ReleaseJavaObject(vmID, ac);
590 }
591 
592 /**
593  * Set the accessibleName string
594  *
595  */
setAccessibleName(char * name)596 void AccessibleNode::setAccessibleName(char *name) {
597     strncpy(accessibleName, name, MAX_STRING_SIZE);
598 }
599 
600 /**
601  * Set the accessibleRole string
602  *
603  */
setAccessibleRole(char * role)604 void AccessibleNode::setAccessibleRole(char *role) {
605     strncpy(accessibleRole, role, SHORT_STRING_SIZE);
606 }
607 
608 
609 
610 
611 
612 
613 
614 /**
615  * Create an API window to show off the info for this AccessibleContext
616  */
displayAPIWindow()617 BOOL AccessibleNode::displayAPIWindow() {
618 
619     HWND apiWindow = CreateWindow(theAccessInfoClassName,
620                                   "Java Accessibility API view",
621                                   WS_OVERLAPPEDWINDOW,
622                                   CW_USEDEFAULT,
623                                   CW_USEDEFAULT,
624                                   600,
625                                   750,
626                                   HWND_DESKTOP,
627                                   NULL,
628                                   theInstance,
629                                   (void *) NULL);
630 
631     if (!apiWindow) {
632         printError("cannot create API window");
633         return FALSE;
634     }
635 
636     char buffer[HUGE_BUFSIZE];
637     buffer[0] = '\0';
638     getAccessibleInfo(vmID, ac, buffer, sizeof(buffer));
639     displayAndLog(apiWindow, cAccessInfoText, logfile, buffer);
640 
641     ShowWindow(apiWindow, SW_SHOWNORMAL);
642     UpdateWindow(apiWindow);
643 
644     return TRUE;
645 }
646 
647 
648 
649