Windows服务的互斥对象名称与Windows 7中的exe名称相同

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

本文关键字:Windows 中的 exe 对象 服务      更新时间:2023-10-16

我想使用CreateMutex函数通过Windows服务和同名的exe创建互斥。如果一个互斥对象是由Windows服务创建的,并且当exe尝试创建另一个同名互斥对象时,它成功了,没有出现任何错误,如error_ALREADY_EXIST。

这种情况仅在Windows7中发生。但对于Windows XP,显示ERROR_ALREADY_EXIST。我不知道操作系统出现这种差异的原因以及如何纠正这个问题。

样本代码

对于服务代码

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

对于可执行代码(代码保持不变,buc仅更改主要功能)

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

在XP:上

在会话0中运行的服务创建互斥对象。该应用程序也在会话0中运行,它成功地打开了现有互斥对象的句柄,最后一个错误设置为error_ALREADY_EXISTS,让您知道发生了什么。

在Windows 7上:

在会话0中运行的服务创建互斥对象。可能在会话一中运行的应用程序创建了一个新的互斥对象,该互斥对象恰好具有相同的名称。这两个互斥对象是独立的。这是可能的,因为互斥对象名称的作用域是当前会话。

如果您想要共享互斥,您需要在全局名称空间中创建它们,方法是在名称前面加上"Global\"前缀,即:

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

您可以在此处找到有关会话零隔离的更多详细信息。