Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/windows/native/sun/bridge/AccessBridgeJavaVMInstance.cpp
32287 views
1
/*
2
* Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
/*
27
* A class to track key JVM instance info from the AT WinAccessBridge
28
*/
29
30
#include "AccessBridgeDebug.h"
31
#include "AccessBridgeJavaVMInstance.h"
32
#include "AccessBridgeMessages.h"
33
#include "AccessBridgePackages.h"
34
#include "accessBridgeResource.h" // for debugging messages
35
36
#include <winbase.h>
37
#include <jni.h>
38
39
// The initialization must only be done one time and to provide for that the initialization
40
// is now done in WinAccessBridge and the CRITICAL_SECTION memory has been moved to there.
41
// send memory lock
42
//CRITICAL_SECTION sendMemoryIPCLock;
43
extern CRITICAL_SECTION sendMemoryIPCLock;
44
45
// protects the javaVMs chain while in use
46
extern bool isVMInstanceChainInUse;
47
48
DEBUG_CODE(extern HWND theDialogWindow);
49
extern "C" {
50
DEBUG_CODE(void AppendToCallInfo(char *s));
51
}
52
53
54
/**
55
*
56
*
57
*/
58
AccessBridgeJavaVMInstance::AccessBridgeJavaVMInstance(HWND ourABWindow,
59
HWND javaABWindow,
60
long javaVMID,
61
AccessBridgeJavaVMInstance *next) {
62
goingAway = FALSE;
63
// This should be called once. Moved to WinAccessBridge c'tor
64
//InitializeCriticalSection(&sendMemoryIPCLock);
65
ourAccessBridgeWindow = ourABWindow;
66
javaAccessBridgeWindow = javaABWindow;
67
vmID = javaVMID;
68
nextJVMInstance = next;
69
memoryMappedFileMapHandle = (HANDLE) 0;
70
memoryMappedView = (char *) 0;
71
sprintf(memoryMappedFileName, "AccessBridge-%p-%p.mmf",
72
ourAccessBridgeWindow, javaAccessBridgeWindow);
73
}
74
75
/**
76
*
77
*
78
*/
79
AccessBridgeJavaVMInstance::~AccessBridgeJavaVMInstance() {
80
DEBUG_CODE(char buffer[256]);
81
82
DEBUG_CODE(AppendToCallInfo("***** in AccessBridgeJavaVMInstance::~AccessBridgeJavaVMInstance\r\n"));
83
EnterCriticalSection(&sendMemoryIPCLock);
84
85
// if IPC memory mapped file view is valid, unmap it
86
goingAway = TRUE;
87
if (memoryMappedView != (char *) 0) {
88
DEBUG_CODE(sprintf(buffer, " unmapping memoryMappedView; view = %p\r\n", memoryMappedView));
89
DEBUG_CODE(AppendToCallInfo(buffer));
90
UnmapViewOfFile(memoryMappedView);
91
memoryMappedView = (char *) 0;
92
}
93
// if IPC memory mapped file handle map is open, close it
94
if (memoryMappedFileMapHandle != (HANDLE) 0) {
95
DEBUG_CODE(sprintf(buffer, " closing memoryMappedFileMapHandle; handle = %p\r\n", memoryMappedFileMapHandle));
96
DEBUG_CODE(AppendToCallInfo(buffer));
97
CloseHandle(memoryMappedFileMapHandle);
98
memoryMappedFileMapHandle = (HANDLE) 0;
99
}
100
LeaveCriticalSection(&sendMemoryIPCLock);
101
102
}
103
104
/**
105
* initiateIPC - sets up the memory-mapped file to do IPC messaging
106
* 1 file is created: to handle requests for information
107
* initiated from Windows AT. The package is placed into
108
* the memory-mapped file (char *memoryMappedView),
109
* and then a special SendMessage() is sent. When the
110
* JavaDLL returns from SendMessage() processing, the
111
* data will be in memoryMappedView. The SendMessage()
112
* return value tells us if all is right with the world.
113
*
114
* The set-up proces involves creating the memory-mapped
115
* file, and handshaking with the JavaDLL so it knows
116
* about it as well.
117
*
118
*/
119
LRESULT
120
AccessBridgeJavaVMInstance::initiateIPC() {
121
DEBUG_CODE(char debugBuf[256]);
122
DWORD errorCode;
123
124
DEBUG_CODE(AppendToCallInfo(" in AccessBridgeJavaVMInstance::initiateIPC()\r\n"));
125
126
// create Windows-initiated IPC file & map it to a ptr
127
memoryMappedFileMapHandle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL,
128
PAGE_READWRITE, 0,
129
// 8 bytes for return code
130
sizeof(WindowsInitiatedPackages) + 8,
131
memoryMappedFileName);
132
if (memoryMappedFileMapHandle == NULL) {
133
errorCode = GetLastError();
134
DEBUG_CODE(sprintf(debugBuf, " Failed to CreateFileMapping for %s, error: %X", memoryMappedFileName, errorCode));
135
DEBUG_CODE(AppendToCallInfo(debugBuf));
136
return errorCode;
137
} else {
138
DEBUG_CODE(sprintf(debugBuf, " CreateFileMapping worked - filename: %s\r\n", memoryMappedFileName));
139
DEBUG_CODE(AppendToCallInfo(debugBuf));
140
}
141
142
memoryMappedView = (char *) MapViewOfFile(memoryMappedFileMapHandle,
143
FILE_MAP_READ | FILE_MAP_WRITE,
144
0, 0, 0);
145
if (memoryMappedView == NULL) {
146
errorCode = GetLastError();
147
DEBUG_CODE(sprintf(debugBuf, " Failed to MapViewOfFile for %s, error: %X", memoryMappedFileName, errorCode));
148
DEBUG_CODE(AppendToCallInfo(debugBuf));
149
return errorCode;
150
} else {
151
DEBUG_CODE(sprintf(debugBuf, " MapViewOfFile worked - view: %p\r\n", memoryMappedView));
152
DEBUG_CODE(AppendToCallInfo(debugBuf));
153
}
154
155
156
// write some data to the memory mapped file
157
strcpy(memoryMappedView, AB_MEMORY_MAPPED_FILE_OK_QUERY);
158
159
160
// inform the JavaDLL that we've a memory mapped file ready for it
161
char buffer[sizeof(PackageType) + sizeof(MemoryMappedFileCreatedPackage)];
162
PackageType *type = (PackageType *) buffer;
163
MemoryMappedFileCreatedPackage *pkg = (MemoryMappedFileCreatedPackage *) (buffer + sizeof(PackageType));
164
*type = cMemoryMappedFileCreatedPackage;
165
pkg->bridgeWindow = ABHandleToLong(ourAccessBridgeWindow);
166
strncpy(pkg->filename, memoryMappedFileName, cMemoryMappedNameSize);
167
sendPackage(buffer, sizeof(buffer));
168
169
170
// look for the JavaDLL's answer to see if it could read the file
171
if (strcmp(memoryMappedView, AB_MEMORY_MAPPED_FILE_OK_ANSWER) != 0) {
172
DEBUG_CODE(sprintf(debugBuf, " JavaVM failed to deal with memory mapped file %s\r\n",
173
memoryMappedFileName));
174
DEBUG_CODE(AppendToCallInfo(debugBuf));
175
return -1;
176
} else {
177
DEBUG_CODE(sprintf(debugBuf, " Success! JavaVM accpeted our file\r\n"));
178
DEBUG_CODE(AppendToCallInfo(debugBuf));
179
}
180
181
return 0;
182
}
183
184
// -----------------------
185
186
/**
187
* sendPackage - uses SendMessage(WM_COPYDATA) to do IPC messaging
188
* with the Java AccessBridge DLL
189
*
190
* NOTE: WM_COPYDATA is only for one-way IPC; there
191
* is no way to return parameters (especially big ones)
192
* Use sendMemoryPackage() to do that!
193
*/
194
LRESULT
195
AccessBridgeJavaVMInstance::sendPackage(char *buffer, long bufsize) {
196
COPYDATASTRUCT toCopy;
197
toCopy.dwData = 0; // 32-bits we could use for something...
198
toCopy.cbData = bufsize;
199
toCopy.lpData = buffer;
200
201
PrintDebugString("[INFO]: In AccessBridgeVMInstance::sendPackage");
202
PrintDebugString("[INFO]: javaAccessBridgeWindow: %p", javaAccessBridgeWindow);
203
/* This was SendMessage. Normally that is a blocking call. However, if
204
* SendMessage is sent to another process, e.g. another JVM and an incoming
205
* SendMessage is pending, control will be passed to the DialogProc to handle
206
* the incoming message. A bug occurred where this allowed an AB_DLL_GOING_AWAY
207
* message to be processed deleting an AccessBridgeJavaVMInstance object in
208
* the javaVMs chain. SendMessageTimeout with SMTO_BLOCK set will prevent the
209
* calling thread from processing other requests while waiting, i.e control
210
* will not be passed to the DialogProc. Also note that PostMessage or
211
* SendNotifyMessage can't be used. Although they don't allow transfer to
212
* the DialogProc they can't be used in cases where pointers are passed. This
213
* is because the referenced memory needs to be available when the other thread
214
* gets control.
215
*/
216
UINT flags = SMTO_BLOCK | SMTO_NOTIMEOUTIFNOTHUNG;
217
DWORD_PTR out; // not used
218
LRESULT lr = SendMessageTimeout( javaAccessBridgeWindow, WM_COPYDATA,
219
(WPARAM)ourAccessBridgeWindow, (LPARAM)&toCopy,
220
flags, 4000, &out );
221
return lr;
222
}
223
224
225
/**
226
* sendMemoryPackage - uses Memory-Mapped files to do IPC messaging
227
* with the Java AccessBridge DLL, informing the
228
* Java AccessBridge DLL via SendMessage that something
229
* is waiting for it in the shared file...
230
*
231
* In the SendMessage call, the third param (WPARAM) is
232
* the source HWND (ourAccessBridgeWindow in this case),
233
* and the fourth param (LPARAM) is the size in bytes of
234
* the package put into shared memory.
235
*
236
*/
237
BOOL
238
AccessBridgeJavaVMInstance::sendMemoryPackage(char *buffer, long bufsize) {
239
240
// Protect against race condition where the memory mapped file is
241
// deallocated before the memory package is being sent
242
if (goingAway) {
243
return FALSE;
244
}
245
BOOL retval = FALSE;
246
247
DEBUG_CODE(char outputBuf[256]);
248
DEBUG_CODE(sprintf(outputBuf, "AccessBridgeJavaVMInstance::sendMemoryPackage(, %d)", bufsize));
249
DEBUG_CODE(AppendToCallInfo(outputBuf));
250
251
DEBUG_CODE(PackageType *type = (PackageType *) buffer);
252
DEBUG_CODE(if (*type == cGetAccessibleTextRangePackage) {)
253
DEBUG_CODE(AppendToCallInfo(" 'buffer' contains:"));
254
DEBUG_CODE(GetAccessibleTextRangePackage *pkg = (GetAccessibleTextRangePackage *) (buffer + sizeof(PackageType)));
255
DEBUG_CODE(sprintf(outputBuf, " PackageType = %X", *type));
256
DEBUG_CODE(AppendToCallInfo(outputBuf));
257
DEBUG_CODE(sprintf(outputBuf, " GetAccessibleTextRange: start = %d, end = %d, rText = %ls",
258
pkg->start, pkg->end, pkg->rText));
259
DEBUG_CODE(AppendToCallInfo(outputBuf));
260
DEBUG_CODE(})
261
262
EnterCriticalSection(&sendMemoryIPCLock);
263
{
264
// copy the package into shared memory
265
if (!goingAway) {
266
memcpy(memoryMappedView, buffer, bufsize);
267
268
DEBUG_CODE(PackageType *type = (PackageType *) memoryMappedView);
269
DEBUG_CODE(if (*type == cGetAccessibleTextItemsPackage) {)
270
DEBUG_CODE(AppendToCallInfo(" 'memoryMappedView' now contains:"));
271
DEBUG_CODE(GetAccessibleTextItemsPackage *pkg = (GetAccessibleTextItemsPackage *) (buffer + sizeof(PackageType)));
272
DEBUG_CODE(sprintf(outputBuf, " PackageType = %X", *type));
273
DEBUG_CODE(AppendToCallInfo(outputBuf));
274
DEBUG_CODE(})
275
}
276
277
if (!goingAway) {
278
// Let the recipient know there is a package waiting for them. The unset byte
279
// at end of buffer which will only be set if message is properly received
280
char *done = &memoryMappedView[bufsize];
281
*done = 0;
282
283
PrintDebugString("[INFO]: javaAccessBridgeWindow: %p", javaAccessBridgeWindow);
284
// See the comment above the call to SendMessageTimeout in SendPackage method above.
285
UINT flags = SMTO_BLOCK | SMTO_NOTIMEOUTIFNOTHUNG;
286
DWORD_PTR out; // not used
287
SendMessageTimeout( javaAccessBridgeWindow, AB_MESSAGE_WAITING, (WPARAM)ourAccessBridgeWindow, (LPARAM)bufsize,
288
flags, 4000, &out );
289
290
// only succeed if message has been properly received
291
if(!goingAway) retval = (*done == 1);
292
}
293
294
// copy the package back from shared memory
295
if (!goingAway) {
296
memcpy(buffer, memoryMappedView, bufsize);
297
}
298
}
299
LeaveCriticalSection(&sendMemoryIPCLock);
300
return retval;
301
}
302
303
304
/**
305
* findAccessBridgeWindow - walk through linked list from where we are,
306
* return the HWND of the ABJavaVMInstance that
307
* matches the passed in vmID; no match: return 0
308
*
309
*/
310
HWND
311
AccessBridgeJavaVMInstance::findAccessBridgeWindow(long javaVMID) {
312
PrintDebugString("[INFO]: In findAccessBridgeWindow");
313
// no need to recurse really
314
if (vmID == javaVMID) {
315
return javaAccessBridgeWindow;
316
} else {
317
isVMInstanceChainInUse = true;
318
AccessBridgeJavaVMInstance *current = nextJVMInstance;
319
while (current != (AccessBridgeJavaVMInstance *) 0) {
320
if (current->vmID == javaVMID) {
321
isVMInstanceChainInUse = false;
322
return current->javaAccessBridgeWindow;
323
}
324
current = current->nextJVMInstance;
325
}
326
isVMInstanceChainInUse = false;
327
}
328
return 0;
329
}
330
331
/**
332
* findABJavaVMInstanceFromJavaHWND - walk through linked list from
333
* where we are. Return the
334
* AccessBridgeJavaVMInstance
335
* of the ABJavaVMInstance that
336
* matches the passed in vmID;
337
* no match: return 0
338
*/
339
AccessBridgeJavaVMInstance *
340
AccessBridgeJavaVMInstance::findABJavaVMInstanceFromJavaHWND(HWND window) {
341
PrintDebugString("[INFO]: In findABJavaInstanceFromJavaHWND");
342
// no need to recurse really
343
if (javaAccessBridgeWindow == window) {
344
return this;
345
} else {
346
isVMInstanceChainInUse = true;
347
AccessBridgeJavaVMInstance *current = nextJVMInstance;
348
while (current != (AccessBridgeJavaVMInstance *) 0) {
349
if (current->javaAccessBridgeWindow == window) {
350
isVMInstanceChainInUse = false;
351
return current;
352
}
353
current = current->nextJVMInstance;
354
}
355
}
356
isVMInstanceChainInUse = false;
357
return (AccessBridgeJavaVMInstance *) 0;
358
}
359
360