用的是内核对象semaphone。一个调用::CreateSemaphore(NULL, nInitialCount, nMaxCount, "aNameOfsSemphoneName”), 另外一个调用::OpenSemaphore( SEMAPHORE_MODIFY_STATE, TRUE, "aNameOfsSemphoneName”)。当我在控制台调试程式时,发现一切都很正常。但是当我把第一个调用CreateSemaphore的进程写成服务程式,部署好了,启动服务,然后再次调试那个调用OpenSemaphore的进程的时候,问题就出现了,返回的错误代码是5(决绝访问)。然后我再把那个服务程式以和我登录window的用户名一样的帐号运行,然后再次调试那个调用OpenSemaphore的进程,这时候就可以正常打开了。
以上情况表明,是window安全性原因,影响了OpenSemaphore的操作。察看msdn,发现如果CreateSemaphore时,第1参数为NULL。
The lpSecurityDescriptor member of the structure specifies a security descriptor for the new semaphore. If lpSemaphoreAttributes is NULL, the semaphore gets a default security descriptor. The ACLs in the default security descriptor for a semaphore come from the primary or impersonation token of the creator.
By default, the default DACL in the access token of a process allows access only to the user represented by the access token. If other users must access the object, you can either create a security descriptor with the appropriate access, or add ACEs to the DACL that grants access to a group of users.
因此,如果将服务部署为以system帐号运行,然后测试程式以administrator运行,结果就是测试程式不能打开OpenSemaphore,错误代码为5,拒绝访问。
基于此,我建立一个函数,让他返回一个很低安全性的lpSecurityDescriptor ,这样服务程式可以以system帐号,运行,而测试程式则以一般的帐号运行即可。不过这样就是牺牲了要建立的内核对象的安全性。选取与否可以择情参考。
HANDLE get_sa()
{
static SECURITY_ATTRIBUTES sa;
static SECURITY_DESCRIPTOR sd;
static PSECURITY_DESCRIPTOR pSA = NULL;
if( pSA == NULL )
{
pSA = &sa;
if ( ! InitializeSecurityDescriptor ( &sd, SECURITY_DESCRIPTOR_REVISION) )
{
return NULL;
}
if ( ! SetSecurityDescriptorDacl ( &sd, TRUE, ( PACL) NULL, FALSE) )
{
return NULL;
}
memset ( ( VOID *) &sa, 0, sizeof ( SECURITY_ATTRIBUTES) );
sa.bInheritHandle = TRUE;
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = &sd;
}
return pSA;
}