Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Same mutex name for a Windows service and exe in Windows 7

Tags:

c++

windows

mutex

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;
}
like image 936
Baplix Avatar asked Feb 10 '12 13:02

Baplix


People also ask

How do I use mutex on Windows?

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.

How do you use named mutex?

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.

How do you make a mutex?

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()

What is OpenMutex?

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.


1 Answers

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.

like image 62
arx Avatar answered Sep 24 '22 00:09

arx