MapViewOfFile shared between 32bit and 64bit processes
32bit-64bit, 64-bit, c++, memory-mapped-files, windows
Solution
When you call CreateFile in the 32-bit application, you're passing `0` for the sharing parameter, which means no sharing is allowed. Changing that to `FILE_SHARE_READ | FiLE_SHARE_WRITE` would probably be a step in the right direction.
Edit: I just whipped together a demo that works (at least for me):
#include <windows.h>
#include <iostream>
static const char map_name[] = "FileMapping1";
static const char event1_name[] = "EventName1";
static const char event2_name[] = "EventName2";
int main() {
HANDLE mapping = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, map_name);
if (NULL == mapping) {
std::cout << "Calling CreateFile\n";
HANDLE file = CreateFile("MappedFile",
FILE_ALL_ACCESS,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_ALWAYS,
0,
NULL);
std::cout << "Creating File mapping\n";
mapping = CreateFileMapping(file, NULL, PAGE_READWRITE, 0, 65536, map_name);
std::cout << "Closing file handle\n";
CloseHandle(file);
}
std::cout << "Mapping view of file\n";
char *memory = (char *)MapViewOfFile(mapping, FILE_MAP_ALL_ACCESS, 0, 0, 65536);
if (memory == NULL) {
std::cerr << "Mapping Failed.\n";
return 1;
}
std::cout << "Mapping succeeded\n";
HANDLE event = CreateEvent(NULL, false, false, event1_name);
if (GetLastError()==ERROR_ALREADY_EXISTS) {
std::cout <<"Waiting to receive string:\n";
WaitForSingleObject(event, INFINITE);
std::cout << "Received: " << memory;
HANDLE event2 = CreateEvent(NULL, false, false, event2_name);
SetEvent(event2);
}
else {
char string[] = "This is the shared string";
std::cout << "Sending string: " << string << "\n";
strncpy(memory, string, sizeof(string));
SetEvent(event);
HANDLE event2 = CreateEvent(NULL, false, false, event2_name);
WaitForSingleObject(event2, INFINITE);
}
return 0;
}
Any combination of 32- or 64-bit executables seems to work fine.
Edit2: Note, however, that this is purely demo-level code. Just for example, the name of each shared object should normally contain a GUID-string to ensure against accidental collision with other programs. I've also skipped quite a bit of error checking, not to mention the minor detail that this code doesn't accomplish anything useful.
Problem
I'm trying to use MapViewOfFile in a 64 bit process on a file that is already mapped to memory of another 32 bit process. It fails and gives me an "access denied" error. Is this a known Windows limitation or am I doing something wrong? Same code works fine with 2 32bit processes. The code sort of looks like this: ``` hMapFile = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, szShmName); if (NULL == hMapFile) { /* failed to open - create new (this happens in the 32 bit app) */ SECURITY_ATTRIBUTES sa; sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.bInheritHandle = FALSE; /* give access to members of administrators group */ BOOL success = ConvertStringSecurityDescriptorToSecurityDescriptor( "D:(A;OICI;GA;;;BA)", SDDL_REVISION_1, &(sa.lpSecurityDescriptor), NULL); HANDLE hShmFile = CreateFile(FILE_XXX_SHM, FILE_ALL_ACCESS, 0, &sa, OPEN_ALWAYS, 0, NULL); hMapFile = CreateFileMapping(hShmFile, &sa, PAGE_READWRITE, 0, SHM_SIZE, szShmName); CloseHandle(hShmFile); } // this one fails in 64 bit app pShm = MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, SHM_SIZE); ```