2012-02-10 10 views
5

Voglio creare il mutex da un servizio di Windows e un exe con gli stessi nomi utilizzando la funzione CreateMutex. Se un mutex viene creato dal servizio Windows e quando l'exe tenta di creare un altro mutex con lo stesso nome, riesce senza errori come ERROR_ALREADY_EXIST.Stesso nome mutex per un servizio Windows ed exe in Windows 7

Ciò si verifica solo in Windows 7. Ma per Windows XP viene visualizzato ERROR_ALREADY_EXIST. Non riesco a capire il motivo di questa differenza nel sistema operativo e come correggere questo problema.

codice di esempio

Per Codice di servizio

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

Per il codice eseguibile (codice rimane lo stesso, Buc cambia solo in funzione principale)

int main() 
{ 
    muname[8]=a; 
    Win32Mutex(muname); 
    Sleep(SLEEP_TIME); 
    return 0; 
} 
+0

Che differenza vuoi dire? Hai detto che "ERROR_ALREADY_EXIST" appare in entrambi i casi (su entrambe le versioni di Windows). I processi possono condividere (denominato) mutex. Uno lo creerà (servizio nel tuo caso, poiché viene eseguito prima dell'applicazione indipendente) e un altro (la tua app) lo aprirà (con 'CreateMutex' che restituirà' ERROR_ALREADY_EXIST'). –

+0

@Bojan: No, ha detto che il codice gira su Win7 *** senza *** 'ERROR_ALREADY_EXIST'. –

+0

Oooups, il mio errore, aveva troppe finestre aperte, stavano facendo il multitasking, quindi ho trascurato la parola :) –

risposta

16

Su XP:

Il servizio, in esecuzione in sess ion zero, crea il mutex. L'applicazione, che è anche in esecuzione nella sessione zero, apre con successo un handle per il mutex esistente e l'ultimo errore è impostato su ERROR_ALREADY_EXISTS per farvi sapere cosa è successo.

In Windows 7:

Il servizio, in esecuzione in sessione a zero, crea il mutex. L'applicazione, che probabilmente è in esecuzione nella prima sessione, crea un nuovo mutex che ha lo stesso nome. I due mutex sono indipendenti. Ciò è possibile perché i nomi mutex sono associati alla sessione corrente.

Se si desidera che il mutex da condividere è necessario creare loro nello spazio dei nomi globale anteponendo al nome con il prefisso "Global \", vale a dire:

char muname[]={"Global\\NewMutex2"}; 

è possibile trovare ulteriori dettagli su session zero isolation qui .

+0

Grazie per la risposta. Una domanda successiva, come possiamo creare un singolo pezzo di codice, che funzioni sia su pre-Vista che su pos-Vista. Possiamo usare GLOBAL \ sia per il sistema operativo WIN sia per proteggere diversi tipi di mutex con la protezione dell'intestazione. Qual è il tuo consiglio? –

+0

Questo articolo implica che "Globale" è supportato da Windows 2000 in poi: http://msdn.microsoft.com/en-us/library/windows/desktop/ms684292%28v=vs.85%29.aspx – arx

+0

Grazie arx per la risposta. La soluzione ha funzionato per me – Baplix