【发布时间】:2018-03-04 22:54:54
【问题描述】:
我正在尝试开发一个使用共享内存在两个进程之间进行通信的系统。一个进程是 32 位应用程序并使用 32 位 dll 进行通信。另一个进程是 64 位应用程序并使用 64 位 dll,其中包含用于创建/打开共享内存的完全相同的代码。我这样做了,每当一个进程打开内存的句柄并且无法打开它时,它就会自动尝试创建内存。然后另一个进程将尝试相同的操作,因此首先运行代码的进程将创建内存,而另一个进程将打开一个已存在内存的句柄。
当共享内存由 64 位进程/dll 创建时,代码运行良好,但每当 32 位 dll 创建它时,调用 MapViewOfFile 时返回错误 5 (ERROR_ACCESS_DENIED)。
我已经检查过传递给任何函数的大小是否不同,例如,因为其中一个结构的大小不同,具体取决于它是为 32 位还是 64 位编译的。但是,情况并非如此,两个进程的大小始终相同。
我还尝试了this 答案中建议的代码,但没有成功。 有谁知道为什么代码有时会因错误 5 而失败?
这是我的代码:
static LPVOID lpMappedInputData = nullptr,
lpMappedOutputData = nullptr;
static HANDLE hInputFileMapping = NULL,
hOutputFileMapping = NULL;
HANDLE createOrOpenFileMapping(DWORD size, LPCSTR lpName)
{
HANDLE hMapFile = OpenFileMappingA(FILE_MAP_READ | FILE_MAP_WRITE, FALSE, lpName);
if (!hMapFile)
DEBUG_LOG("OpenFileMapping failed! Error code: %i - Attempting to create the file mapping instead...\n", GetLastError());
if (!hMapFile)
{
hMapFile = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, size, lpName);
if (!hMapFile)
DEBUG_LOG("CreateFileMapping failed! Error code: %i\n", GetLastError());
}
return hMapFile;
}
LPVOID mapViewOfFile(HANDLE hFileMappingObject, DWORD size)
{
LPVOID lpMappedData = MapViewOfFile(hFileMappingObject, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, size);
if (!lpMappedData)
{
CloseHandle(hFileMappingObject);
DEBUG_LOG("MapViewOfFile failed! Error code: %i\n", GetLastError());
}
return lpMappedData;
}
bool Initialize()
{
DEBUG_LOG("Initializing the input file mapping...\n");
hInputFileMapping = createOrOpenFileMapping(sizeof(InputData), "Local\\InputData");
if (!hInputFileMapping)
return false;
lpMappedInputData = mapViewOfFile(hInputFileMapping, sizeof(InputData));
if (!lpMappedInputData)
return false;
DEBUG_LOG("Initializing the output file mapping...\n");
hOutputFileMapping = createOrOpenFileMapping(sizeof(OutputData), "Local\\OutputData");
if (!hOutputFileMapping)
return false;
lpMappedOutputData = mapViewOfFile(hOutputFileMapping, sizeof(OutputData));
if (!lpMappedOutputData)
return false;
return true;
}
void Deinitialize()
{
DEBUG_LOG("Deinitializing the file mappings...\n");
if (lpMappedInputData)
UnmapViewOfFile(lpMappedInputData);
if (hInputFileMapping)
CloseHandle(hInputFileMapping);
if (lpMappedOutputData)
UnmapViewOfFile(lpMappedOutputData);
if (hOutputFileMapping)
CloseHandle(hOutputFileMapping);
DEBUG_LOG("Successfully deinitialized the file mappings!\n");
}
【问题讨论】:
-
Bitness 没有任何作用,您需要关注控制这些进程的用户帐户或权限升级。您未在问题中提供的详细信息。
-
@HansPassant 那么你建议我怎么做?两个进程在完全相同的用户帐户下运行。
-
尝试只使用文件的标准路径名,看看问题是否消失。我担心 "WOW64"(允许运行基于 32 位 Windows 的应用程序的 x86 模拟器)对 "Local\\" 的作用。即使它是同一个用户,但它是不同的安全上下文(我认为)。
-
请注意,在调用
GetLastError()之前调用CloseHandle()是一个错误。始终在 API 函数失败时立即保存错误代码,因为调用其他 API 函数可以修改错误代码。 -
@RbMm 实际上,非常肯定。