近些天在开发一个项目的时候,需要在2个进程间通讯,当一个进程读好共享数据时告诉另外一个进程,以便进行同步操作。
用的是内核对象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;
}






 

posted on 2008-03-26 14:37  Frodo  阅读(985)  评论(0编辑  收藏  举报