I need to use a global mutex to synchronize access to a mutually shared file by several processes. I create the mutex as such:
HANDLE hMutex = ::CreateMutex(NULL, FALSE, L"Global\\MySpecialName");
And then use it in:
//Entering critical section
VERIFY(::WaitForSingleObject(hMutex, INFINITE) == WAIT_OBJECT_0);
and then:
//Leave critical section
VERIFY(::ReleaseMutex(hMutex));
The issue arises from the fact that the processes sharing this mutex are a local-system service and several user-mode processes running with credentials of a logged on user. So if the mutex is first created by the service, then when the user-mode process tries to open it, CreateMutex
fails with error code ERROR_ACCESS_DENIED
.
I was reading into specifying a security descriptor for the mutex before creating it but I can't seem to figure out how to make it accessible by everything
, I don't really need any complexity here?
Here's what I use, based on this article:
HANDLE hMutex = NULL;
DWORD dwError;
// Create a global mutex
pSecDesc = MakeAllowAllSecurityDescriptor();
if(pSecDesc)
{
SECURITY_ATTRIBUTES SecAttr;
SecAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
SecAttr.lpSecurityDescriptor = pSecDesc;
SecAttr.bInheritHandle = FALSE;
hMutex = CreateMutex(&SecAttr, TRUE, MUTEX_NAME);
dwError = GetLastError();
LocalFree(pSecDesc);
}
...
//
// From http://blogs.msdn.com/b/winsdk/archive/2009/11/10/access-denied-on-a-mutex.aspx
//
PSECURITY_DESCRIPTOR MakeAllowAllSecurityDescriptor(void)
{
WCHAR *pszStringSecurityDescriptor;
if(GetWindowsVersion(NULL) >= 6)
pszStringSecurityDescriptor = L"D:(A;;GA;;;WD)(A;;GA;;;AN)S:(ML;;NW;;;ME)";
else
pszStringSecurityDescriptor = L"D:(A;;GA;;;WD)(A;;GA;;;AN)";
PSECURITY_DESCRIPTOR pSecDesc;
if(!ConvertStringSecurityDescriptorToSecurityDescriptor(pszStringSecurityDescriptor, SDDL_REVISION_1, &pSecDesc, NULL))
return NULL;
return pSecDesc;
}