【问题标题】:CreateMutex -- "Access is denied"CreateMutex -- “访问被拒绝”
【发布时间】:2021-03-15 23:49:30
【问题描述】:

以下代码有时可以正常工作,有时会引发“访问被拒绝”错误。行为不一致。

_hMutex = CreateMutex(NULL, FALSE, MutexName);
    if (_hMutex == NULL) 
{
  throw MY_ERROR(GetLastError(), L"Error creating mutex handle");
}

我运行具有此代码的独立可执行文件,执行操作并退出。它不是多线程应用程序。每次运行此程序时,我都使用相同的用户凭据登录。

你能帮我解决这个问题吗?

谢谢, 下摆

【问题讨论】:

  • “它不是多线程应用程序”,如果是这种情况,为什么需要 Mutex?
  • 如果不是多线程的,你为什么要标记你的问题multithreading
  • @Als:基于 OP 正在尝试创建命名互斥锁这一事实,我想说有多个进程试图共享受互斥锁保护的资源。 OP 的可执行文件不是多线程的这一事实可能与此无关。
  • @Gabe:我们实际上可以猜测任何我们选择的东西,但这真的不能最终解决问题。如果需要准确的答案而不是仅仅是猜测,那么他们需要提供准确的细节,而不是措辞模糊的问题。
  • 会不会是CreateMutex成功的时候,mutex不存在了?当它失败时,互斥体已经存在并且您的应用访问权限有限?

标签: c++ winapi


【解决方案1】:

如果互斥体是命名互斥体,并且该对象在此函数调用之前存在,则返回值是现有对象的句柄,GetLastError返回ERROR_ALREADY_EXISTS,忽略bInitialOwner,并且调用线程未被授予所有权。

但是,如果调用者的访问权限有限,则函数将失败并显示ERROR_ACCESS_DENIED,调用者应使用 OpenMutex 函数。

MSDN

【讨论】:

  • 我在 MSDN 网站上读到过,但是是什么原因导致访问权限受限?该用户具有管理员权限。
  • 有人能说明一下“有限的访问权限”吗?我正在使用属于机器管理员组的域帐户。谢谢。
【解决方案2】:

今天我遇到了类似的问题,但会话不同。 互斥体被命名并具有前缀Global\。 当一个应用程序创建命名的全局互斥锁时,不允许不同用户帐户的其他应用程序与同一个互斥锁同步。 CreateMutex 总是返回错误ERROR_ACCESS_DENIED。 OpenMutex 成功,但互斥量无法用于同步。

解决方案是每个应用程序必须使用CreateMutexEx 访问全局互斥锁(仅请求SYNCHRONIZE)并且您必须指定SecurityAttributes。默认的 SecurityAttributes 不允许在用户帐户之间共享。

工作代码如下所示:

HANDLE hMutex;
{
    DWORD dwRes, dwDisposition;
    PSID pEveryoneSID = NULL;
    PACL pACL = NULL;
    PSECURITY_DESCRIPTOR pSD = NULL;
    EXPLICIT_ACCESS ea[1];
    SID_IDENTIFIER_AUTHORITY SIDAuthWorld =
            SECURITY_WORLD_SID_AUTHORITY;
    SECURITY_ATTRIBUTES sa;
    LONG lRes;

    // Create a well-known SID for the Everyone group.
    if(!AllocateAndInitializeSid(&SIDAuthWorld, 1,
                     SECURITY_WORLD_RID,
                     0, 0, 0, 0, 0, 0, 0,
                     &pEveryoneSID))
    {
        _tprintf(_T("AllocateAndInitializeSid Error %u\n"), GetLastError());
        goto Cleanup;
    }

    // Initialize an EXPLICIT_ACCESS structure for an ACE.
    // The ACE will allow Everyone read access to the key.
    ZeroMemory(&ea, 1 * sizeof(EXPLICIT_ACCESS));
    ea[0].grfAccessPermissions = SYNCHRONIZE;
    ea[0].grfAccessMode = SET_ACCESS;
    ea[0].grfInheritance= NO_INHERITANCE;
    ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID;
    ea[0].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
    ea[0].Trustee.ptstrName  = (LPTSTR) pEveryoneSID;
    
    // Create a new ACL that contains the new ACEs.
    dwRes = SetEntriesInAcl(1, ea, NULL, &pACL);
    if (ERROR_SUCCESS != dwRes) 
    {
        _tprintf(_T("SetEntriesInAcl Error %u\n"), GetLastError());
        goto Cleanup;
    }

    // Initialize a security descriptor.  
    pSD = (PSECURITY_DESCRIPTOR) LocalAlloc(LPTR, 
                             SECURITY_DESCRIPTOR_MIN_LENGTH); 
    if (NULL == pSD) 
    { 
        _tprintf(_T("LocalAlloc Error %u\n"), GetLastError());
        goto Cleanup; 
    } 
 
    if (!InitializeSecurityDescriptor(pSD,
            SECURITY_DESCRIPTOR_REVISION)) 
    {  
        _tprintf(_T("InitializeSecurityDescriptor Error %u\n"),
                                GetLastError());
        goto Cleanup; 
    } 
 
    // Add the ACL to the security descriptor. 
    if (!SetSecurityDescriptorDacl(pSD, 
            TRUE,     // bDaclPresent flag   
            pACL, 
            FALSE))   // not a default DACL 
    {  
        _tprintf(_T("SetSecurityDescriptorDacl Error %u\n"),
                GetLastError());
        goto Cleanup; 
    } 

    // Initialize a security attributes structure.
    sa.nLength = sizeof (SECURITY_ATTRIBUTES);
    sa.lpSecurityDescriptor = pSD;
    sa.bInheritHandle = FALSE;

    hMutex = CreateMutexExW(&sa, L"Global\\MyNamedMutex", 0, SYNCHRONIZE);

Cleanup:

    if (pEveryoneSID) 
        FreeSid(pEveryoneSID);
    if (pAdminSID) 
        FreeSid(pAdminSID);
    if (pACL) 
        LocalFree(pACL);
    if (pSD) 
        LocalFree(pSD);
}

// Do something with hMutex
WaitForSingleObject(hMutex, INFINITE);

CloseHandle(hMutex);

来源链接:

【讨论】:

    【解决方案3】:

    这可能是因为MutexName 的互斥体已经存在。您正在使用默认安全描述符创建互斥锁,这(取决于您使用此互斥锁的方式)可能不允许其他用途。

    有关更多信息,请参阅MSDN。一个有用的sn-p:

    如果互斥体是命名互斥体并且对象在此之前存在 函数调用,[省略],如果 调用者的访问权限有限,该函数将失败 ERROR_ACCESS_DENIED 调用者应该使用 OpenMutex 函数。

    【讨论】:

    • 谢谢。我不确定“有限访问权限”是什么意思。你能在这里放点光吗?该应用程序由具有管理员权限的 Windows 用户运行。我该如何摆脱困境?
    • 安全令牌确定不同上下文中的进程/服务如何访问互斥锁。你想用这个做什么?您是否使用了其他人可能选择的通用名称?
    • 我相信这个名字是猜不出来的,它是单词的组合。此外,没有其他应用程序正在运行。我会检查安全令牌。
    • 当不再需要 Mutex 的句柄时,是否通过 CloseHandle 关闭它?
    【解决方案4】:

    我终于找到了。有一个使用系统帐户运行的服务,它创建互斥锁和一个由尝试访问它的用户运行的 exe。这是由于许可。

    【讨论】:

    • 对于 UNIX 程序员来说,假设一个线性的权限层次结构是一个常见的错误,其中 root/Administrator/SYSTEM 位于顶部。在 Windows 上,AdministratorSYSTEM 都没有所有权限,而且它们绝对是不同的帐户。
    猜你喜欢
    • 1970-01-01
    • 2014-08-10
    • 2021-03-06
    • 2011-05-15
    • 2010-09-06
    • 2014-03-22
    • 2013-08-10
    • 2018-04-20
    • 2012-08-23
    相关资源
    最近更新 更多