Mumble Link for Java using JNA?
A:
Thank you for your answers
I put those correction into again a short example… well the result is still…. a bunch of zeros…
Is it possible, that i ran into some permission/security issues?
import java.util.Arrays;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.WinBase;
import com.sun.jna.platform.win32.WinNT;
import com.sun.jna.platform.win32.WinNT.HANDLE;
public class JNATest {
private static final int MEM_MAP_SIZE = 5460;
private static final String MEM_MAP_NAME = "MumbleLink";
private final HANDLE sharedFile;
private Pointer sharedMemory;
public JNATest() throws InterruptedException {
int uiVersion = 0;
int uiTick = 0;
float[] fAvatarPosition = new float[0];
float[] fAvatarFront = new float[0];
float[] fAvatarTop = new float[0];
float[] fCameraPosition = new float[0];
float[] fCameraFront = new float[0];
float[] fCameraTop = new float[0];
char[] characterName = new char[0];
char[] gameName = new char[0];
int context_len = 0;
byte[] context = new byte[0];
this.sharedFile = Kernel32.INSTANCE.CreateFileMapping(WinBase.INVALID_HANDLE_VALUE, null, WinNT.PAGE_EXECUTE_READWRITE, 0, MEM_MAP_SIZE, MEM_MAP_NAME);
this.sharedMemory = Kernel32.INSTANCE.MapViewOfFile(this.sharedFile, WinNT.SECTION_MAP_READ, 0, 0, MEM_MAP_SIZE);
while (this.sharedMemory != null) {
uiVersion = this.sharedMemory.getInt(0);
uiTick = this.sharedMemory.getInt(4);
fAvatarPosition = this.sharedMemory.getFloatArray(8, 3);
fAvatarFront = this.sharedMemory.getFloatArray(20, 3);
fAvatarTop = this.sharedMemory.getFloatArray(32, 3);
gameName = this.sharedMemory.getCharArray(44, 256);
fCameraPosition = this.sharedMemory.getFloatArray(556, 3);
fCameraFront = this.sharedMemory.getFloatArray(568, 3);
fCameraTop = this.sharedMemory.getFloatArray(580, 3);
characterName = this.sharedMemory.getCharArray(592, 256);
context_len = this.sharedMemory.getInt(1104);
context = this.sharedMemory.getByteArray(1108, 256);
System.out.println("uiVersion: " + uiVersion);
System.out.println("uiTick: " + uiTick);
System.out.println("fAvatarPosition: " + Arrays.toString(fAvatarPosition));
System.out.println("fAvatarFront: " + Arrays.toString(fAvatarFront));
System.out.println("fAvatarTop: " + Arrays.toString(fAvatarTop));
System.out.println("gameName: " + Arrays.toString(gameName));
System.out.println("fCameraPosition: " + Arrays.toString(fCameraPosition));
System.out.println("fCameraFront: " + Arrays.toString(fCameraFront));
System.out.println("fCameraTop: " + Arrays.toString(fCameraTop));
System.out.println("identity: " + Arrays.toString(characterName));
System.out.println("context_len: " + context_len);
System.out.println("context: " + Arrays.toString(context));
System.out.println("#####################################################");
Thread.sleep(1000);
}
}
public static void main(String[] args) throws InterruptedException {
new JNATest();
}
}
Edit:
It turned out, that if mumble client first creates the mem mapped file and i start my java application after that file is already created, everything works….
Do i need some security settings to get the creation by my java app work?
Edit:
When using PAGE_EXECUTE_READWRITE it works as expected. -> altered code above
(edited by Lulan.8497)
Hello Guys,
since i got no answers here, i investigated the whole problem a bit more by myself.
I used Microsofts Process Explorer (http://technet.microsoft.com/en-us/sysinternals/bb896653.aspx) to check which memory mapped files are opened by which process.
I found out, that my java process has opened “\Sessions\1\BaseNamedObjects\MumbleLink” and the GW2 Process not.
Is that the expected behavior?
I executed my java app with elevated rights an got access to global scope…
that resulted in a ememory mapped file handle \BaseNamedObjects\MumbleLink … well… it didn’t worked out as well..
(edited by Lulan.8497)
I found out, that when there is a Mumble client running an i than start my java application, i’m able to retrieve the data i wish…. Any ideas why?
Edit:
Restartet IDE, Mumble, Eclipse and Java App —> it doesnt work again
(edited by Lulan.8497)
GW2 will not create MumbleLink. If it has been created and GW2 is logged in with a character, it will open and begin writing to it. If you’re in a scenario where GW2 is running and doesn’t have MumbleLink open, then either MumbleLink hasn’t been created or it’s been created in a way which GW2 cannot open and write to it.
Judging by the code in the first post, I see 3 errors.
1. Remove the / in “/MumbleLink”
2. Your mapping doesn’t allocate enough space, change each 48 to 5460
3. You’re not actually reading, change WinNT.SECTION_QUERY to WinNT.SECTION_MAP_READ
I compared the address and size of the memory mapped file that is created by the mumble client with the one created by my own.
0xFFFFF8A00A581810 vs. 0xFFFFF8A00A581810
They are the same….
Have you already tried to create the shared Memory section with just “MumbleLink” instead of “/MumbleLink”? – ah not fast enough…
Die Vollenstrecker [VS] – Elona Reach [DE]
https://gw2apicpp.codeplex.com – Gw2API C/C++ Project
I got it working with a few changes to you’re setup.
Here are a few lines from the working code:
final String name = “MumbleLink”;
sharedFile = Kernel32.INSTANCE.CreateFileMapping(
WinBase.INVALID_HANDLE_VALUE, null, WinNT.PAGE_READONLY, 0,
5460, name);
Pointer sharedMemory = Kernel32.INSTANCE.MapViewOfFile(sharedFile,
WinNT.SECTION_MAP_READ, 0, 0, 5460);
if (sharedMemory != null) {
uiVersion = sharedMemory.getInt(0);
uiTick = sharedMemory.getInt(4);
fAvatarPosition = sharedMemory.getFloatArray(8, 3);
fAvatarFront = sharedMemory.getFloatArray(20, 3);
fAvatarTop = sharedMemory.getFloatArray(32, 3);
name = sharedMemory.getCharArray(44, 256);
fCameraPosition = sharedMemory.getFloatArray(556, 3);
fCameraFront = sharedMemory.getFloatArray(568, 3);
fCameraTop = sharedMemory.getFloatArray(580, 3);
identity = sharedMemory.getCharArray(592, 256);
context_len = sharedMemory.getInt(1104);
context = sharedMemory.getByteArray(1108, 256);
}
If the code still returns a lot of “0” play the game for a few seconds and the values will change.
(edited by Much.2794)
Pointer sharedMemory = Kernel32.INSTANCE.MapViewOfFile(sharedFile,
WinNT.SECTION_MAP_WRITE, 0, 0, 5460);
That SECTION_MAP_WRITE means you’re opening the mapping with write/read access. It doesn’t really matter, but since you only need to read the data, that WRITE should be a READ.
Pointer sharedMemory = Kernel32.INSTANCE.MapViewOfFile(sharedFile,
WinNT.SECTION_MAP_WRITE, 0, 0, 5460);That SECTION_MAP_WRITE means you’re opening the mapping with write/read access. It doesn’t really matter, but since you only need to read the data, that WRITE should be a READ.
Edited in my post and also changed the Kernel32.INSTANCE.CreateFileMapping to readonly
It’s not really my expertise, since I only used it in c++ for CrossTalk yet before I switched over to the Qt variant, but imo
CreateFileMapping(
WinBase.INVALID_HANDLE_VALUE, null, WinNT.PAGE_READONLY, 0,
5460, name)
looks rather suspicious.
Aren’t you creating a File Mapping that’s protected for read-only access? I figure GW2 would not be able to write to that then.
Shouldn’t just recreating the exact same variant that Mumble Link itself uses:
Try to open file mapping, if not create file mapping (read/write access) be the way to go?
hMapObject = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, L"MumbleLink");
if (hMapObject == NULL) {
hMapObject = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(LinkedMem), L"MumbleLink");
bCreated = true;
if (hMapObject == NULL)
return false;
}
lm = static_cast<LinkedMem *>(MapViewOfFile(hMapObject, FILE_MAP_ALL_ACCESS, 0, 0, 0));
The access rights in OpenFileMapping and/or MapViewOfFile could probably indeed be opted to some sort of read access, unless you want to imitate Link’s unlock function, which I’d rather do not.
CrossTalk TS3 Addon Author
http://addons.teamspeak.com/directory/plugins/miscellaneous/CrossTalk.html
(edited by Wothor.4781)
You created it as a read only memory. You need to change it back to PAGE_EXECUTE_READWRITE, like you had originally.
CreateFileMapping(WinBase.INVALID_HANDLE_VALUE, null, WinNT.PAGE_EXECUTE_READWRITE, 0, MEM_MAP_SIZE, MEM_MAP_NAME);
HANDLE sharedFile = Kernel32.INSTANCE.CreateFileMapping(WinBase.INVALID_HANDLE_VALUE, null, WinNT.PAGE_EXECUTE_READWRITE, 0, 5460, “MumbleLink”);
Pointer sharedMemory = Kernel32.INSTANCE.MapViewOfFile(sharedFile, WinNT.SECTION_MAP_READ, 0, 0, 5460);
System.out.println(Arrays.toString(sharedMemory.getByteArray(0, 48)));
(edited by Healix.5819)
I’d still try to open it first, before I create it.
http://msdn.microsoft.com/en-us/library/windows/desktop/aa366537(v=vs.85).aspx
If the object exists before the function call, the function returns a handle to the existing object (with its current size, not the specified size), and GetLastError returns ERROR_ALREADY_EXISTS.
Just creating it would, as I read it, render it incompatible to simultaneously running applications, like the Mumble client or the CrossTalk TS3-Addon.
Also, I dunno why one would want to add execute to the standard implementation’s PAGE_READWRITE.
CrossTalk TS3 Addon Author
http://addons.teamspeak.com/directory/plugins/miscellaneous/CrossTalk.html
(edited by Wothor.4781)
PAGE_EXECUTE_READWRITE worked out
The problem with open is that the platform component of JNA does not provide the OpenFileMapping method…
JNA’s Open/CreateFileMapping is simplified. By default, it’s actually OpenFileMapping. If that fails, it becomes CreateFileMapping.
Ah I see, they reference to GetLastError returns ERROR_ALREADY_EXISTS for checks. Well then.
CrossTalk TS3 Addon Author
http://addons.teamspeak.com/directory/plugins/miscellaneous/CrossTalk.html
Okay nice As it finally works now im very grateful for your support! I think i will integrate it into my yagw2api project and publish it in the near future. if any one is interested in it before, just contact me