1

I used this example to build a program that is creating memory-mapped file containing string value "Message from first process."

#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <tchar.h>

#define BUF_SIZE 256
TCHAR szName[] = TEXT("Local\\MyFileMappingObject");
TCHAR szMsg[] = TEXT("Message from first process.");

int _tmain()
{
    HANDLE hMapFile;
    LPCTSTR pBuf;

    hMapFile = CreateFileMapping(
        INVALID_HANDLE_VALUE,    // use paging file
        NULL,                    // default security
        PAGE_READWRITE,          // read/write access
        0,                       // maximum object size (high-order DWORD)
        BUF_SIZE,                // maximum object size (low-order DWORD)
        szName);                 // name of mapping object

    if (hMapFile == NULL)
    {
        _tprintf(TEXT("Could not create file mapping object (%d).\n"),
            GetLastError());
        return 1;
    }
    pBuf = (LPTSTR)MapViewOfFile(hMapFile,   // handle to map object
        FILE_MAP_ALL_ACCESS, // read/write permission
        0,
        0,
        BUF_SIZE);

    if (pBuf == NULL)
    {
        _tprintf(TEXT("Could not map view of file (%d).\n"),
            GetLastError());

        CloseHandle(hMapFile);

        return 1;
    }


    CopyMemory((PVOID)pBuf, szMsg, (_tcslen(szMsg) * sizeof(TCHAR)));
    _getch();

    UnmapViewOfFile(pBuf);

    CloseHandle(hMapFile);

    return 0;
}

I have problem in my Java application reading the value. String data = view.getString(0); gives me "java.lang.Error: Invalid memory access" when above demo application is running.

I know the function succeeds because failure (if the application is not running) results in a NullPointerException because this.h is null. So the Pointer is correct, but what am I doing wrong when trying to get the value?

package ACC;

import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.WinNT.HANDLE;
import com.sun.jna.win32.W32APIOptions;

public class ACCSharedMemory{
    private final MyKernel32 myKernel32;
    private HANDLE h;
    private Pointer view;
    
    public interface MyKernel32 extends Kernel32 {
        MyKernel32 INSTANCE = (MyKernel32)Native.load("kernel32", MyKernel32.class, W32APIOptions.DEFAULT_OPTIONS);
        HANDLE OpenFileMapping(int dwDesiredAccess, boolean bInheritHandle, String lpName);
    }
    
    public ACCSharedMemory() {
        myKernel32 = MyKernel32.INSTANCE;
    }

    public void test() {

        h = myKernel32.OpenFileMapping(983071, true, "Local\\MyFileMappingObject");
        view = h.getPointer();
        String data = view.getString(0);
    }
}

EDIT. Full working code below. Thanks Daniel & Drake.

public class ACCSharedMemory{
    private final MyKernel32 myKernel32;
    private HANDLE h;
    private Pointer view;
    
    public interface MyKernel32 extends Kernel32 {
        MyKernel32 INSTANCE = (MyKernel32)Native.load("kernel32", MyKernel32.class, W32APIOptions.DEFAULT_OPTIONS);
        HANDLE OpenFileMapping(int dwDesiredAccess, boolean bInheritHandle, String lpName);
    }
    
    public ACCSharedMemory() {
        myKernel32 = MyKernel32.INSTANCE;
    }

    public void test() {
        h = myKernel32.OpenFileMapping(0x4, true, "Local\\MyFileMappingObject");
        view = Kernel32.INSTANCE.MapViewOfFile (h, 0x4, 0, 0, 256);
        System.out.println(view.getWideString(0));
    }
    
}
3
  • 1
    Another brief note... you should be calling CloseHandle() on h to release the handle, as well as UnmapViewOfFile() on view to release that native memory. Commented Oct 27, 2020 at 1:49
  • Thx. One more question. When I have a struct in MyFileMappingObject i do: t.smVersion = view.getWideString(0); t.acVersion = view.getWideString(30); t.numberOfSessions = view.getInt(60); and so on. Do you think there is an easier way to map struct from memory on object in Java? Commented Oct 28, 2020 at 10:45
  • 1
    If using a JNA Structure, you could do this with a pointer constructor. This would tie the structure mapping to that shared memory, though, so might not be the best solution This other StackOverflow Q&A shows another possibility to map the bytes to an object. You 'd still need to map the strings to byte[] and use Native.toWideString() on them. Commented Oct 28, 2020 at 15:35

1 Answer 1

2

The problem is that you are treating the returned HANDLE as a pointer to the data. But it is not a plain pointer; it only has meaning to other File Mapping API functions.

The example at Creating Named Shared Memory shows how to use this returned handle in the second process. Note the native code there to deal with the retrieved handle value is to pass it to MapViewOfFile() specifying the starting offset and number of bytes to map, as well as permissions for the shared memory.

That function will return the actual pointer to the shared memory that you can then manipulate (e.g., retrieve the string).

Note that Windows strings are in UTF-16, but using Pointer.getString() will assume an 8-bit C string. You should use Pointer.getWideString(). To avoid reading beyond memory bounds, you should also ensure that the buffer at the Pointer you are reading from is large enough to include the null terminator.

Sign up to request clarification or add additional context in comments.

3 Comments

Any chance for small working code? Tried getWideString(). The same problem. Also tried: view = Kernel32.INSTANCE.MapViewOfFile (h, MyKernel32.FILE_READ_ONLY, 0, 0, 256); but view is null after this line.
@TomaszMakowski The read-only access of file map should be FILE_MAP_READ(0x4) not FILE_READ_ONLY(0x8). Did you get any error code after MapViewOfFile?
MapViewOfFile identify 0x8 as SECTION_MAP_EXECUTE. You did not specify PAGE_EXECUTE_* access in CreateFileMapping.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.