Reputation: 739
The following code works without any problem sometimes and at other times it throws "Access is denied" error. The behavior is not consistent.
_hMutex = CreateMutex(NULL, FALSE, MutexName);
if (_hMutex == NULL)
{
throw MY_ERROR(GetLastError(), L"Error creating mutex handle");
}
I run my standalone executable which has this code, do the operation and exit. It is not a multithreaded application. I logon with the same user credential every time I run this.
Could you help me resolve this?
Thanks, Hem
Upvotes: 3
Views: 7983
Reputation: 1718
Today I had a similar issue, but with different sessions.
The mutex is named and has the prefix Global\
.
When one application created the named global mutex no other application of different user accounts was allowed to synchronize with the same mutex.
CreateMutex always returned the error ERROR_ACCESS_DENIED
. OpenMutex succeeded, but the mutex couldn't be used for synchronization.
The solution is that each application must access the global mutex with CreateMutexEx
(with only SYNCHRONIZE
requested) AND you must specify the SecurityAttributes. The default SecurityAttributes disallows sharing between user accounts.
A working code looks like:
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);
Source links:
Upvotes: 2
Reputation: 739
I found it finally. There is a service that runs with system account that creates the mutex and an exe run by user trying to access it. It was due to the permission.
Upvotes: 0
Reputation: 3143
If the mutex is a named mutex, and the object existed before this function call, the return value is a handle to the existing object, GetLastError returns ERROR_ALREADY_EXISTS
, bInitialOwner is ignored, and the calling thread is not granted ownership.
However, if the caller has limited access rights, the function will fail with ERROR_ACCESS_DENIED
and the caller should use the OpenMutex function.
Upvotes: 3
Reputation: 49386
This is probably because a mutex with MutexName
already exists. You're creating the mutex with default security descriptor, which (depending on how you're using this mutex) may not permit other uses of it.
For more, see MSDN. A useful snippet:
If the mutex is a named mutex and the object existed before this function call, [elided], if the caller has limited access rights, the function will fail with
ERROR_ACCESS_DENIED
and the caller should use the OpenMutex function.
Upvotes: 1