1

I've the following code...

On one machine it throws ERROR_ACCESS_DENIED and on other it throws ERROR_ALREADY_EXISTS (Handle is not NULL). I'd like to understand why two different behaviors. On both the machines user is a domain user part of local system administrators group. I tried running three instances simultaneously.


#include <windows.h>
#include<iostream>
using namespace std;

void * _hMutex = NULL;

void createMyMutex()
{
    _hMutex = CreateMutex( 
            NULL,              // default security attributes
            false,             // initially not owned
            L"LockTest");      // named mutex

        if (_hMutex == NULL) 
        {
            cout<< GetLastError()<< " Error creating mutex handle"<<endl;
            Exit(0);
        }
        if(GetLastError() == ERROR_ALREADY_EXISTS)
        {
            cout<< GetLastError()<< " Mutex already created" <<endl;
        }   
}

void Lock()
{
    cout<<"Acquiring Lock..."<< endl;
    if(_hMutex != NULL)
        WaitForSingleObject(_hMutex, INFINITE);
    cout<< "Acquired Lock." <<endl;
}

void Unlock()
{
cout<< "Releasing Lock..." <<endl;
    if(_hMutex != NULL)
       ReleaseMutex(_hMutex);
}


int main(int argc, char* argv[])
{

    cout<<"Creating lock"<<endl;
    createMyMutex();
    cout<<"Lock create success"<<endl;

    cout<<"Taking lock"<<endl;
    Lock();
    cout<<"Got the lock"<<endl;

    cout<<"Waiting for 20 seconds"<<endl;
    Sleep(20000);
    cout<<"Wait over"<<endl;


    cout<<"Releasing lock"<<endl;
    Unlock();
    cout<<"Lock released successfully"<<endl;

    cout<<"exiting the program"<<endl;
    return 0;
    }

Lad
  • 11
  • 1
  • 2
  • 2
    `_hMutex` is a [reserved identifier](http://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an-underscore-in-a-c-identifier) in the global scope. – chris Aug 23 '12 at 22:16
  • I actually have that in as a class member, for simplicity, I wrote the program without using class. – Lad Aug 23 '12 at 22:28
  • That's ok, then. Just make sure your members don't begin with a capital letter following the underscore, though, as that is reserved in any scope. – chris Aug 23 '12 at 22:29
  • Were all three instances running in the same security context? Are they running elevated? What is different between the two machines, e.g., does one of them have UAC disabled? – Harry Johnston Aug 24 '12 at 03:56
  • there is not any difference and all run the same way. On one machine I get access denied and on the other I get already exists. – Lad Aug 24 '12 at 23:53

2 Answers2

3

From MSDN:

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.

So try using OpenMutex instead with just the SYNCHRONIZE access right.

Also note that the Windows type BOOL is different from the C++ type bool. So you should use the corresponding values TRUE and FALSE when calling Windows API functions that take BOOL, not true and false.

Adam Rosenfield
  • 390,455
  • 97
  • 512
  • 589
  • The problem is, sometimes even for the first run it throws access denied error with just once instance of the program is running. – Lad Aug 23 '12 at 22:27
  • The behavior should be consistent when the user permissions are same. would like to unserstand why there are two different behaviors? – Lad Aug 23 '12 at 22:30
1

I guess you're getting the ERROR_ALREADY_EXISTS when calling createMyMutex(); and the ERROR_ACCESS_DENIED when calling Lock();. I's suggest to choose an object name in the global namespace. So you better use something like

CreateMutex( NULL, FALSE, "Global\\LockTest" );

See Object Namespaces on MSDN for details.

Arno
  • 4,994
  • 3
  • 39
  • 63