Click here to Skip to main content
15,892,809 members
Articles / Desktop Programming / MFC
Article

CreateMutexwithatwist

Rate me:
Please Sign up or sign in to vote.
3.75/5 (7 votes)
1 Dec 20041 min read 29.1K   9   1
CreateMutex with a twist…. some non default arguments.

Introduction

This is just a brief follow-up on the excellent article submitted by Liviu Birjega: Windows-based application over Terminal Services using WtsAPI32.

In my own experience, under WTS, the function CreateMutex can be called simply like this:

hMutex = CreateMutex(NULL, FALSE, csAppName);

BUT, doing so for a 2nd and subsequent sessions resolves with a return error 5 (ERROR_ACCESS_DENIED) when calling GetLastError().

On further reading the MSDN documentation, it provides some explanation as follows:

“… Pointer to a security descriptor for the object that controls the sharing of it. If NULL is specified for this member, the object is assigned the default security descriptor of the calling process.

This is not the same as granting access to everyone by assigning a null DACL.

The default security descriptor is based on the default DACL of the access token belonging to the calling process. By default, the default DACL in the access token of a process allows access only to the user represented by the access token. If other users must access the object, you can either create a security descriptor with a null DACL, or add ACEs to the DACL that grants access to a group of users.”

This is explained in more detail in Rob Manderson’s excellent article: Using Access Control Lists to secure access to your objects.

So, in order to get back the desired result (183 = ERROR_ALREADY_EXISTS) when calling GetLastError() you will have to actually do something like this…

BOOL IsAnotherWTSUserLoggedIn(LPCTSTR sAppName)
{
   if(GetSystemMetrics(SM_REMOTESESSION))
   {
      HANDLE hMutex = NULL;
      SECURITY_DESCRIPTOR sd;
 
      InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);

      SetSecurityDescriptorDacl(&sd, TRUE, 0, FALSE);

      SECURITY_ATTRIBUTES sa = { sizeof sa, &sd, FALSE };

      CString csAppName;
      csAppName.Format(_T("Global\\%s"), sAppName);

      hMutex = ::CreateMutex(&sa, FALSE, csAppName);

      if( GetLastError() == ERROR_ALREADY_EXISTS )
      {
          CloseHandle(hMutex);
          return TRUE;
      }
   }

   return FALSE;
}

Yes, and just one more little comment for Liviu, it seems that the correct “Verb” to use is “Global” – not “Session” as suggested – this is also supported in the MSDN documentation. Hope someone finds some use for all this, I know I did.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
Australia Australia
Born in Romania in 1945, lived for some 30 years in Israel and moved to join the family in Australia in 1985.

Started programming in 1973 (yes, the stone age…) on WANG, with BASIC, Assembler, then some Fortran around 1979, in 1981 got my first home “Personal Computer” – A Dragon 32 (had it connected to a TV monitor and a cassette deck for data / program storage)..

Later on PDP-11 , Data General AOS/VS for some 8 years, IBM 32/34/36 with RPG II and III, real “Fun” language to work with (NOT).

In 1985 moved to Australia, started a love affair with dBase III, then Clipper 87 and finally in 1991 switched 100% to work in C and later in C++

In my “Spare time” I build and fly Radio Control Model Airplanes.

Comments and Discussions

 
GeneralMy vote of 1 Pin
kustt11020-Apr-09 21:50
kustt11020-Apr-09 21:50 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.