How to make a synchronization mutex with access by

2019-08-05 01:41发布

问题:

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?

回答1:

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;
}