Même nom de mutex pour un service Windows et exe dans Windows 7

Je veux créer un mutex par un service Windows et un exe avec les mêmes noms en utilisant la fonction CreateMutex. Si un mutex est créé par le service Windows et que l’exe tente de créer un autre mutex portant le même nom, il réussit sans erreur, comme ERROR_ALREADY_EXIST.

Cela se produit uniquement sous Windows 7. Mais pour Windows XP, ERROR_ALREADY_EXIST est affiché. Je ne suis pas capable de comprendre la raison de cette différence de système d’exploitation et comment corriger ce problème.

Exemple de code

Pour le code de service

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

Pour le code exécutable (le code rest le même, ne change que la fonction principale)

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

Sur XP:

Le service, exécuté dans la session zéro, crée le mutex. L’application, qui s’exécute également dans la session zéro, ouvre avec succès un handle au mutex existant et la dernière erreur est définie sur ERROR_ALREADY_EXISTS pour vous permettre de savoir ce qui s’est passé.

Sur Windows 7:

Le service, exécuté dans la session zéro, crée le mutex. L’application, qui tourne probablement dans la première session, crée un nouveau mutex qui porte le même nom. Les deux mutex sont indépendants. Cela est possible parce que les noms de mutex sont étendus à la session en cours.

Si vous souhaitez que les mutex soient partagés, vous devez les créer dans l’espace de noms Global en préfixant le nom avec le préfixe “Global \”, à savoir:

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

Vous pouvez trouver plus de détails sur l’ isolement de session zéro ici.