MapViewOfFile returns 错误 5 (ERROR_ACCESS_DENIED)
MapViewOfFile returns Error 5 (ERROR_ACCESS_DENIED)
我正在尝试开发一个使用共享内存在两个进程之间进行通信的系统。一个进程是 32 位应用程序并使用 32 位 dll 进行通信。另一个进程是一个 64 位应用程序并使用一个 64 位 dll,其中包含用于 creating/opening 共享内存的完全相同的代码。我这样做是为了每当一个进程打开内存句柄但无法打开它时,它会自动尝试创建内存。然后另一个进程将尝试相同的操作,因此无论哪个进程首先运行代码都将创建内存,而另一个进程将打开一个已存在内存的句柄。
当共享内存由 64 位 process/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");
}
win32 错误 - 这是从原始 NTSTATUS
本地 api 调用结果翻译而来的大多数转换。但这种翻译不是单射的——有时许多不同的状态转换为相同的 win32 错误值。例如,相同的 ERROR_ACCESS_DENIED
转换至少 18(!) 个不同的 ntstatus。所以原始错误可能不是 STATUS_ACCESS_DENIED
,而是绝对的另一个错误,与实际访问被拒绝没有任何共同点。因为这个,如果 win32 api 调用是 shell 而不是本机调用 - 最好调用 RtlGetLastNtStatus
获取原始错误状态代码或直接调用本机 api(ZwMapViewOfSection
相反 MapViewOfFile
)
不幸的是,我不知道 ZwMapViewOfSection
返回的原始状态,但我猜这是 STATUS_INVALID_VIEW_SIZE
(试图为一个部分创建视图比节大.).
在创建和映射部分使用了 sizeof(InputData)
和 sizeof(OutputData)
- 代码中没有定义此结构,bat 基于
The code works absolutely fine when the shared memory is created by
the 64 bit process/dll but whenever the 32 bit dll creates it, I get
error 5 (ERROR_ACCESS_DENIED
) returned when calling MapViewOfFile
.
我想接下来 - 在 32 位代码中 InputData
或 OutputData
具有较小的大小)比较 64 位代码)。这只是说明了一切。如果 64 位代码首先创建部分,然后 32 位代码尝试映射更小的尺寸 - 这没问题。但是如果 32 位代码首先创建部分,然后 64 位代码尝试映射大小大于该部分大小 - 我们得到 STATUS_INVALID_VIEW_SIZE
转换为 ERROR_ACCESS_DENIED
但是
I already checked if the size .. the size is always the same in both
processes.
不相信。我要重新检查。
作为单独的注释 - CreateFileMapping
Creates or opens a named or unnamed file mapping object for a
specified file.
所以我们不需要特殊函数 createOrOpenFileMapping
并先调用 OpenFileMappingA
- 只需调用 CreateFileMappingW
(A
api 有什么用?)。 createOrOpenFileMapping
的任何方式代码都有引发条件 - 两个进程都可以并发调用 OpenFileMappingA
并且都在这里失败。无论如何都调用 CreateFileMappingA
但主要 GetLastError()
有时不是最好的并且 ERROR_ACCESS_DENIED
并不总是 STATUS_ACCESS_DENIED
并且与实际访问被拒绝错误有关
我正在尝试开发一个使用共享内存在两个进程之间进行通信的系统。一个进程是 32 位应用程序并使用 32 位 dll 进行通信。另一个进程是一个 64 位应用程序并使用一个 64 位 dll,其中包含用于 creating/opening 共享内存的完全相同的代码。我这样做是为了每当一个进程打开内存句柄但无法打开它时,它会自动尝试创建内存。然后另一个进程将尝试相同的操作,因此无论哪个进程首先运行代码都将创建内存,而另一个进程将打开一个已存在内存的句柄。
当共享内存由 64 位 process/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");
}
win32 错误 - 这是从原始 NTSTATUS
本地 api 调用结果翻译而来的大多数转换。但这种翻译不是单射的——有时许多不同的状态转换为相同的 win32 错误值。例如,相同的 ERROR_ACCESS_DENIED
转换至少 18(!) 个不同的 ntstatus。所以原始错误可能不是 STATUS_ACCESS_DENIED
,而是绝对的另一个错误,与实际访问被拒绝没有任何共同点。因为这个,如果 win32 api 调用是 shell 而不是本机调用 - 最好调用 RtlGetLastNtStatus
获取原始错误状态代码或直接调用本机 api(ZwMapViewOfSection
相反 MapViewOfFile
)
不幸的是,我不知道 ZwMapViewOfSection
返回的原始状态,但我猜这是 STATUS_INVALID_VIEW_SIZE
(试图为一个部分创建视图比节大.).
在创建和映射部分使用了 sizeof(InputData)
和 sizeof(OutputData)
- 代码中没有定义此结构,bat 基于
The code works absolutely fine when the shared memory is created by the 64 bit process/dll but whenever the 32 bit dll creates it, I get error 5 (
ERROR_ACCESS_DENIED
) returned when callingMapViewOfFile
.
我想接下来 - 在 32 位代码中 InputData
或 OutputData
具有较小的大小)比较 64 位代码)。这只是说明了一切。如果 64 位代码首先创建部分,然后 32 位代码尝试映射更小的尺寸 - 这没问题。但是如果 32 位代码首先创建部分,然后 64 位代码尝试映射大小大于该部分大小 - 我们得到 STATUS_INVALID_VIEW_SIZE
转换为 ERROR_ACCESS_DENIED
但是
I already checked if the size .. the size is always the same in both processes.
不相信。我要重新检查。
作为单独的注释 - CreateFileMapping
Creates or opens a named or unnamed file mapping object for a specified file.
所以我们不需要特殊函数 createOrOpenFileMapping
并先调用 OpenFileMappingA
- 只需调用 CreateFileMappingW
(A
api 有什么用?)。 createOrOpenFileMapping
的任何方式代码都有引发条件 - 两个进程都可以并发调用 OpenFileMappingA
并且都在这里失败。无论如何都调用 CreateFileMappingA
但主要 GetLastError()
有时不是最好的并且 ERROR_ACCESS_DENIED
并不总是 STATUS_ACCESS_DENIED
并且与实际访问被拒绝错误有关