CreateMutex - “访问被拒绝”

时间:2012-04-13 11:27:58

标签: c++ winapi

以下代码有时会毫无问题地工作,有时会抛出“访问被拒绝”错误。行为不一致。

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

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

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

谢谢, 下摆

4 个答案:

答案 0 :(得分:2)

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

但是,如果呼叫者具有有限的访问权限,则该功能将失败并显示ERROR_ACCESS_DENIED,并且呼叫者应使用 OpenMutex 功能。

MSDN

答案 1 :(得分:1)

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

有关详情,请参阅MSDN。一个有用的片段:

  

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

答案 2 :(得分:0)

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

答案 3 :(得分:0)

今天我遇到了类似的问题,但会话不同。 互斥体已命名并具有前缀 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);

源链接: