I want to create mutex by a Windows Service and an exe with same names using CreateMutex function. If a mutex is created by the Windows Service and when the exe tries to create another mutex with the same name it succeeds without any error like ERROR_ALREADY_EXIST.
This happens only in Windows 7. But for Windows XP ERROR_ALREADY_EXIST is shown. I am not able to make out the reason for this difference in OS and how to correct this problem.
Sample Code
For Service Code
#include<iostream>
#include<windows.h>
#include<winbase.h>
using namespace std;
#define SLEEP_TIME 50000
typedef void* handle;
typedef WINADVAPI BOOL (WINAPI *PInitializeSecurityDescriptor)(PSECURITY_DESCRIPTOR, DWORD);
typedef WINADVAPI BOOL (WINAPI *PSetSecurityDescriptorDacl)(PSECURITY_DESCRIPTOR, BOOL, PACL, BOOL);
#define LOGFILE "D:\\result.txt"
handle temp=NULL;
static int a=65;
char muname[]={"NewMutex2"};
int errNm;
char *str;
FILE* log;
SECURITY_ATTRIBUTES *g_pSaCms;
SERVICE_STATUS ServiceStatus;
SERVICE_STATUS_HANDLE hStatus;
void ServiceMain(int argc, char** argv);
void ControlHandler(DWORD request);
int InitService();
bool Win32Mutex(char muname[8])
{
HINSTANCE hAdvApi = LoadLibrary("Advapi32.DLL");
PInitializeSecurityDescriptor pInitializeSecurityDescriptor = 0;
PSetSecurityDescriptorDacl pSetSecurityDescriptorDacl = 0;
PSECURITY_DESCRIPTOR pSD = 0;
g_pSaCms = new SECURITY_ATTRIBUTES;
if (g_pSaCms == 0)
{
prinerr();
return 1;
}
memset(g_pSaCms,0X0, sizeof(*g_pSaCms));
g_pSaCms->nLength = sizeof(*g_pSaCms);
g_pSaCms->bInheritHandle = 1;
pSD = new SECURITY_DESCRIPTOR;
if (pSD == 0)
{
printerr();
goto LABEL_CSA_ERROR;
}
pInitializeSecurityDescriptor = (PInitializeSecurityDescriptor)GetProcAddress(hAdvApi,"InitializeSecurityDescriptor");
if (pInitializeSecurityDescriptor == 0)
{
printerr();
goto LABEL_CSA_ERROR;
}
pSetSecurityDescriptorDacl = (PSetSecurityDescriptorDacl)GetProcAddress(hAdvApi, "SetSecurityDescriptorDacl");
if (pSetSecurityDescriptorDacl == 0)
{
goto LABEL_CSA_ERROR;
}
if (!(*pInitializeSecurityDescriptor)(pSD, SECURITY_DESCRIPTOR_REVISION)
|| (!(*pSetSecurityDescriptorDacl)(pSD, TRUE, (PACL)0, FALSE)))
{
goto LABEL_CSA_ERROR;
}
(void)FreeLibrary(hAdvApi);
g_pSaCms->lpSecurityDescriptor=pSD;
goto LABEL_CSA_PASS;
LABEL_CSA_ERROR:
(void)FreeLibrary(hAdvApi);
if (pSD != 0)
{
delete pSD;
pSD = 0;
}
if (g_pSaCms != 0)
{
delete g_pSaCms;
g_pSaCms = 0;
}
LABEL_CSA_PASS:
temp=::CreateMutex(g_pSaCms,0,muname); //for icdcomm
errNm=GetLastError();
if (!temp)
{
print_err();
}
else
{
print_err();
}
if ((!temp) || errNm == ERROR_ALREADY_EXISTS)
{
if(temp)
{
(void)CloseHandle(temp);
a++;
muname[8]=a;
Win32Mutex(muname);
}
else
{
printInf()
}
return 0;
}
return 1;
}
int main()
{
SERVICE_TABLE_ENTRY ServiceTable[2];
ServiceTable[0].lpServiceName = "MemoryStatus";
ServiceTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceMain;
ServiceTable[1].lpServiceName = NULL;
ServiceTable[1].lpServiceProc = NULL;
StartServiceCtrlDispatcher(ServiceTable);
return 0;
}
void ServiceMain(int argc, char** argv)
{
int error;
ServiceStatus.dwServiceType = SERVICE_WIN32;
ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
ServiceStatus.dwWin32ExitCode = 0;
ServiceStatus.dwServiceSpecificExitCode = 0;
ServiceStatus.dwCheckPoint = 0;
ServiceStatus.dwWaitHint = 0;
hStatus = RegisterServiceCtrlHandler(
"MemoryStatus",
(LPHANDLER_FUNCTION)ControlHandler);
if (hStatus == (SERVICE_STATUS_HANDLE)0)
{
// Registering Control Handler failed
return;
}
// Initialize Service
error = InitService();
if (error)
{
// Initialization failed
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
ServiceStatus.dwWin32ExitCode = -1;
SetServiceStatus(hStatus, &ServiceStatus);
return;
}
// My service
muname[8]=a;
Win32Mutex(muname);
// We report the running status to SCM.
ServiceStatus.dwCurrentState = SERVICE_RUNNING;
SetServiceStatus (hStatus, &ServiceStatus);
// The worker loop of a service
while (ServiceStatus.dwCurrentState == SERVICE_RUNNING)
{
Sleep(SLEEP_TIME);
}
return;
}
// Control handler function
void ControlHandler(DWORD request)
{
switch(request)
{
case SERVICE_CONTROL_STOP:
ServiceStatus.dwWin32ExitCode = 0;
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
SetServiceStatus (hStatus, &ServiceStatus);
return;
case SERVICE_CONTROL_SHUTDOWN:
ServiceStatus.dwWin32ExitCode = 0;
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
SetServiceStatus (hStatus, &ServiceStatus);
return;
default:
break;
}
// Report current status
SetServiceStatus (hStatus, &ServiceStatus);
return;
}
For executable code (Code remains same, buc only change in main function)
int main()
{
muname[8]=a;
Win32Mutex(muname);
Sleep(SLEEP_TIME);
return 0;
}
You can use a mutex object to protect a shared resource from simultaneous access by multiple threads or processes. Each thread must wait for ownership of the mutex before it can execute the code that accesses the shared resource.
Mutex is a synchronization primitive that grants exclusive access to the shared resource to only one thread. If a thread acquires a mutex, the second thread that wants to acquire that mutex is suspended until the first thread releases the mutex. This type implements the IDisposable interface.
After the mutex attribute object has been created, the mutex can be created with the pthread_mutex_init() function. While using mutexes as the locking device, the following functions can be used: pthread_mutex_lock() pthread_mutex_unlock()
The OpenMutex function enables multiple processes to open handles of the same mutex object. The function succeeds only if some process has already created the mutex by using the CreateMutex function.
On XP:
The service, running in session zero, creates the mutex. The application, which is also running in session zero, successfully opens a handle to the existing mutex and the last error is set to ERROR_ALREADY_EXISTS to let you know what happened.
On Windows 7:
The service, running in session zero, creates the mutex. The application, which is probably running in session one, creates a new mutex which happens to have the same name. The two mutexes are independent. This is possible because mutex names are scoped to the current session.
If you want the mutexes to be shared you need to create them in the Global namespace by prefixing the name with the "Global\" prefix, i.e.:
char muname[]={"Global\\NewMutex2"};
You can find more details about session zero isolation here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With