我正在尝试开发一个使用共享内存进行两个进程之间通信的系统。一个进程是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");
}
答案 0 :(得分:0)
win32错误 - 这是从原始NTSTATUS
原生api调用结果翻译的大多数演员。但是这种翻译不是单射的 - 有时许多不同的状态转换为相同的win32错误值。例如,相同的ERROR_ACCESS_DENIED
转换了至少18(!)个不同的ntstatus。所以原始错误不是STATUS_ACCESS_DENIED
而是绝对错误,没有任何共同的真实访问被拒绝。因为这样,如果win32 api调用是本机调用的shell - 总是更好地调用RtlGetLastNtStatus
获取原始错误状态代码或直接调用native api(ZwMapViewOfSection
而不是MapViewOfFile
)
很遗憾,我不知道ZwMapViewOfSection
返回的原始状态,但我想这是STATUS_INVALID_VIEW_SIZE
(尝试创建一个更大的部分的视图而不是该部分。)。
在使用sizeof(InputData)
和sizeof(OutputData)
的创建和地图部分中 - 代码中没有此结构的定义,基于
创建共享内存时,代码工作正常 64位进程/ dll,但每当32位dll创建它时,我得到 调用
ERROR_ACCESS_DENIED
时返回错误5(MapViewOfFile
)。
我猜下一个 - 在32位代码InputData
或OutputData
中具有更小的尺寸)比较64位代码)。这只是解释所有。如果64位代码首先创建节,然后32位代码尝试映射较小的大小 - 这没关系。但如果32位代码首先创建部分然后64位代码尝试更大的部分大小的地图大小 - 我们得到STATUS_INVALID_VIEW_SIZE
,其转换为ERROR_ACCESS_DENIED
但是怎么样
不相信。我要复查了。我已经检查了尺寸..尺寸在两者中总是相同的 过程
作为单独的注释 - CreateFileMapping
为a创建或打开命名或未命名的文件映射对象 指定的文件。
所以我们不需要特殊功能createOrOpenFileMapping
并先致电OpenFileMappingA
- 只需致电CreateFileMappingW
(使用A
api?)。并且createOrOpenFileMapping
的任何代码都会提高条件 - 两个进程都可以同时调用OpenFileMappingA
并且都在这里失败。无论如何都要拨打CreateFileMappingA
但主要GetLastError()
有时不是最好的ERROR_ACCESS_DENIED
并不总是STATUS_ACCESS_DENIED
且与实际访问被拒绝错误有关