【问题标题】:System Error 0x5: CreateFileMapping()系统错误 0x5:CreateFileMapping()
【发布时间】:2011-04-29 06:55:09
【问题描述】:

我希望使用命名共享内存实现IPC。

为此,其中一个步骤是使用 CreateFileMapping() 获取 映射内存对象 的句柄。

我完全按照 MSDN 网站的建议:http://msdn.microsoft.com/en-us/library/aa366551(v=VS.85).aspx:

hFileMappingHandle = CreateFileMapping
    (
        INVALID_HANDLE_VALUE,      // use paging file
        NULL,                      // default security 
        PAGE_READWRITE,            // read/write access
        0,            // maximum object size (high-order DWORD) 
        256,            // maximum object size (low-order DWORD)  
        "Global\\MyFileMappingObject"          // name of mapping object
    ); 
DWORD dwError = GetLastError();

但是,返回的句柄始终是0x0,返回的系统错误代码是:0x5 (Access Denied.)

  • 仅需要命名内存共享(不是文件共享)。
  • Windows 7 x64 位操作系统
  • 管理员的可用用户权限
  • 开发的应用程序:64 位插件应用程序(.dll)

有没有人有同样的经历,求解决方法?我使用 MSDN 站点作为参考,所以我不认为代码有问题。

【问题讨论】:

  • 不确定是不是这个原因,但你不需要将最大对象大小设置为内存页的倍数(4096字节)吗?
  • 嗨 Eugene,不,问题是我没有设置 SeCreateGlobalPriviledge。

标签: c++ windows winapi windows-7 memory-mapped-files


【解决方案1】:

这是一个非常古老的问题,标记为已回答。但是通过相同的 MSDN 文章并基于它构建示例,我能够在没有任何特殊权限的情况下成功。

只需去掉名称中的“Global\”部分即可。令人惊讶的是,对于信号量和事件,它不能以这种方式工作,您将得到“0x2 ERROR_FILE_NOT_FOUND”。但是对于内存映射共享内存它工作得很好。我能够在服务器上创建读/写共享内存,并在客户端上打开它。

【讨论】:

    【解决方案2】:

    使用安全属性和 DACL。 示例:

    ZeroMemory(&attributes, sizeof(attributes));
    attributes.nLength = sizeof(attributes);
    ConvertStringSecurityDescriptorToSecurityDescriptorA(
                "D:P(A;OICI;GA;;;SY)(A;OICI;GA;;;BA)(A;OICI;GWGR;;;IU)",
                SDDL_REVISION_1,
                &attributes.lpSecurityDescriptor,
                NULL);
    hMapObject = CreateFileMappingA(
                INVALID_HANDLE_VALUE,
                &attributes,
                PAGE_READWRITE,
                0,
                1024,
                "mySMobject");
    

    【讨论】:

      【解决方案3】:

      关于全局命名空间的文档中对终端服务的引用有点误导,因为这意味着您只有在遇到异常情况时才需要担心这一点。

      事实上,IIS 和系统服务都在会话 0 中运行,而第一个/唯一登录的用户在会话 1 中运行 - 因此您必须使用全局命名空间在 IIS 或服务与普通程序之间进行通信。

      【讨论】:

        【解决方案4】:

        默认情况下,管理员、服务和网络服务具有 SeCreateGlobalPrivilege。不过,您必须记住,Windows7/Vista 不会以管理员身份运行所有内容。因此,使用“以管理员身份启动”使“全局\”适用于您的应用程序。如果您正在调试,请以管理员身份启动 Visual Studio。

        【讨论】:

        • 非常感谢!默认情况下,Windows 10 下的 Visual Studio 不是管理员。那是我的问题。
        • 如果我们想为没有管理员权限的用户使用 CreateFileMapping 怎么办?
        【解决方案5】:

        要创建全局文件映射,您需要SeCreateGlobalPrivilege 权限 - 您有吗?拒绝访问意味着这是一个权限问题,当然。

        【讨论】:

        • 嗨史蒂夫,这是我的问题。谢谢你。我现在以不同的方式解决了这个问题,但是如果我想设置权限,可以在我的应用程序中以编程方式完成吗?
        • 您可以使用AdjustTokenPrivileges 执行此操作,如下所示:msdn.microsoft.com/en-us/library/aa446619(v=VS.85).aspx。令牌句柄来自OpenProcessToken,必须使用(至少)TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY 调用
        【解决方案6】:

        您似乎没有足够的权限。

        来自 MSDN:

        在 来自会话其他的全局命名空间 比会话零需要 SeCreateGlobalPrivilege 特权。为了 更多信息,请参阅内核对象 命名空间。

        ...

        文件映射对象的创建 在全局命名空间中,通过使用 CreateFileMapping,来自会话 除了会话零以外 特权操作。因为这, 任意运行的应用程序 远程桌面会话主机(RD 会话主机)服务器会话必须有 SeCreateGlobalPrivilege 在中启用 为了创建一个文件映射对象 在全局命名空间中成功。 权限检查仅限于 创建文件映射对象,以及 不适用于打开现有的 那些。例如,如果一个服务或 系统创建一个文件映射对象, 在任何会话中运行的任何进程都可以 访问该文件映射对象 前提是用户拥有 必要的访问权限。

        【讨论】:

        • 嗨,尤金,这正是我的问题。我从映射对象的名称中删除了前缀“Global\\”,显然这解决了问题。我不打算处理终端服务,因此该解决方案现在应该可以接受。我阅读了有关 SeCreateGlobalPriviledge 的文档,但我不清楚是否可以由应用程序本身分配权限,或者我是否必须从 Windows 资源管理器中手动调整权限?
        • 权限由启动应用程序的用户帐户定义。您可以尝试使用此处讨论的 AdjustTokenPrivilege 函数:delphi.about.com/b/2008/09/26/…,但这并不能保证结果。一般来说,尝试搜索SeCreateGlobalPrivilege,结果包含一些有趣的信息来源
        猜你喜欢
        • 2015-12-18
        • 2010-12-25
        • 2012-08-05
        • 2017-11-15
        • 2014-11-29
        • 1970-01-01
        • 1970-01-01
        • 2018-02-20
        • 2011-05-31
        相关资源
        最近更新 更多