MapViewOfFile返回错误5(ERROR_ACCESS_DENIED)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MapViewOfFile返回错误5(ERROR_ACCESS_DENIED)相关的知识,希望对你有一定的参考价值。

我正在尝试开发一个使用共享内存进行两个进程之间通信的系统。一个进程是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...
", GetLastError());

    if (!hMapFile)
    {
        hMapFile = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, size, lpName);

        if (!hMapFile)
            DEBUG_LOG("CreateFileMapping failed! Error code: %i
", 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
", GetLastError());
    }

    return lpMappedData;
}

bool Initialize()
{
    DEBUG_LOG("Initializing the input file mapping...
");

    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...
");

    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...
");

    if (lpMappedInputData)
        UnmapViewOfFile(lpMappedInputData);

    if (hInputFileMapping)
        CloseHandle(hInputFileMapping);

    if (lpMappedOutputData)
        UnmapViewOfFile(lpMappedOutputData);

    if (hOutputFileMapping)
        CloseHandle(hOutputFileMapping);

    DEBUG_LOG("Successfully deinitialized the file mappings!
");
}
答案

win32错误 - 这是从原始NTSTATUS本机api调用结果翻译的大多数演员。但是这种翻译不是单射的 - 有时许多不同的状态转换为相同的win32错误值。例如,相同的ERROR_ACCESS_DENIED转换至少18(!)不同的ntstatus。原来的错误可能不是STATUS_ACCESS_DENIED而是绝对的另一个,没有任何共同的真实访问被拒绝。因为这个,如果win32 api调用shell是本机调用 - 总是更好地调用RtlGetLastNtStatus获取原始错误状态代码或调用native api direct(ZwMapViewOfSection而不是MapViewOfFile

不幸的是我不知道ZwMapViewOfSection返回的原始状态,但我想这是STATUS_INVALID_VIEW_SIZE(尝试创建一个比该部分更大的部分的视图。)。

在创建和地图部分使用sizeof(InputData)sizeof(OutputData) - 代码中没有这种结构的定义,bat基于

当共享内存由64位进程/ dll创建时,代码工作得非常好,但是每当32位dll创建它时,我在调用ERROR_ACCESS_DENIED时返回错误5(MapViewOfFile)。

我想接下来 - 在32位代码InputDataOutputData有更小的尺寸)比较64位代码)。这只是解释所有。如果64位代码首先创建节,然后32位代码尝试映射较小的大小 - 这没关系。但如果32位代码首先创建部分然后64位代码尝试更大的部分大小的地图大小 - 我们得到STATUS_INVALID_VIEW_SIZE,其转换为ERROR_ACCESS_DENIED

但怎么样

我已经检查了尺寸..两个过程中的尺寸总是相同的。

不相信。我要复查了。

作为单独的笔记 - CreateFileMapping

为指定文件创建或打开命名或未命名的文件映射对象。

所以我们不需要特殊功能createOrOpenFileMapping并首先调用OpenFileMappingA - 只需调用CreateFileMappingW(使用A api?)。并且任何方式的createOrOpenFileMapping都有提升条件 - 两个进程都可以同时调用OpenFileMappingA并且都在这里失败。无论如何都要求CreateFileMappingA

但主要GetLastError()有时不是最好的和ERROR_ACCESS_DENIED并不总是STATUS_ACCESS_DENIED和真实访问被拒绝错误

以上是关于MapViewOfFile返回错误5(ERROR_ACCESS_DENIED)的主要内容,如果未能解决你的问题,请参考以下文章

如何模拟 CoralCall [call:error:] 方法返回错误

为啥我会收到“错误:序列化从 getStaticProps 返回的 ___ 时出错”?

Swift 5 LLDB 错误:警告:<EXPR>:12:9:警告:变量“$__lldb_error_result”的初始化从未使用过

/etc/aliases 使用管道运行脚本返回错误 (mailer=prog, dsn=5.3.0, stat=unknown mailer error 2)

文件映射 IPC 在 MapViewOfFile 调用上挂起

使用 MapViewOfFile 映射大文件