如何在进程之间共享内核对象

转载 2006年06月21日 15:53:00

      有时,服务必须创建可由运行在不同用户帐户下的进程访问的内核对象。要允许以这种方式共享对象,服务必须使用明确授权用户对象访问权限的安全描述符来创建对象。或者,安全描述符可以授予对整个用户组的访问权限。

本文中的示例代码非常特定,因为它授予经过身份验证的用户 组对互斥体的访问权限。这段代码使用了大量的安全 API 来构造互斥体的安全描述符。有关这些安全函数的完整文档,请参阅 MSDN Library 中 Platform SDK 文档的“Access Control”(访问控制)部分:

http://msdn.microsoft.com/library/en-us/security/hh/winbase/accctrl_2hf0.asp (http://msdn.microsoft.com/library/en-us/security/hh/winbase/accctrl_2hf0.asp)
您必须完全了解这些调用(通常情况下还包括访问控制技术),以便针对其他用户、组和内核对象改编代码。
 

示例代码

以下示例代码说明了如何构造安全描述符,以授予经过身份验证的用户 组 GENERIC_READ、GENERIC_WRITE 和 GENERIC_EXECUTE 权限。新构造的安全描述符随即应用于互斥体。

出于说明目的,此示例代码使用了通用访问权限。这些通用权限利用了可用于所有内核对象的通用映射。在实际的应用程序中,创建对象时最好使用对象特定的访问权限。

给定的资源管理器在映射到对象特定的访问权限时,可能会解释给定的通用权限集,以包括其他标准访问权限。例如,为互斥体指定 GENERIC_READ、GENERIC_WRITE 和 GENERIC_EXECUTE 权限相当于指定对象特定的权限 MUTEX_MODIFY_STATE 和 SYNCHRONIZE。因此,其他线程要想获得互斥体的句柄,只能通过在 OpenMutex() 中为 dwDesiredAccess 参数指定 MUTEX_MODIFY_STATE 和/或 SYNCHRONIZE。使用 MUTEX_ALL_ACCESS 打开互斥体的尝试将失败,并显示错误代码 5 (ERROR_ACCESS_DENIED)。

#include <windows.h>
#include <stdio.h>

// The following function initializes the supplied security descriptor
// with a DACL that grants the Authenticated Users group GENERIC_READ,
// GENERIC_WRITE, and GENERIC_EXECUTE access.
//
// The function returns NULL if any of the access control APIs fail.
// Otherwise, it returns a PVOID pointer that should be freed by calling
// FreeRestrictedSD() after the security descriptor has been used to
// create the object.

PVOID BuildRestrictedSD(PSECURITY_DESCRIPTOR pSD) {

   DWORD  dwAclLength;

   PSID   pAuthenticatedUsersSID = NULL;

   PACL   pDACL   = NULL;
   BOOL   bResult = FALSE;

   PACCESS_ALLOWED_ACE pACE = NULL;

   SID_IDENTIFIER_AUTHORITY siaNT = SECURITY_NT_AUTHORITY;
  
   SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION;
  
   __try {

      // initialize the security descriptor
      if (!InitializeSecurityDescriptor(pSD,
            SECURITY_DESCRIPTOR_REVISION)) {
         printf("InitializeSecurityDescriptor() failed with error %d/n",
               GetLastError());
         __leave;
      }

      // obtain a sid for the Authenticated Users Group
      if (!AllocateAndInitializeSid(&siaNT, 1,
            SECURITY_AUTHENTICATED_USER_RID, 0, 0, 0, 0, 0, 0, 0,
            &pAuthenticatedUsersSID)) {
         printf("AllocateAndInitializeSid() failed with error %d/n",
               GetLastError());
         __leave;
      }

      // NOTE:
      //
      // The Authenticated Users group includes all user accounts that
      // have been successfully authenticated by the system. If access
      // must be restricted to a specific user or group other than
      // Authenticated Users, the SID can be constructed using the
      // LookupAccountSid() API based on a user or group name.

      // calculate the DACL length
      dwAclLength = sizeof(ACL)
            // add space for Authenticated Users group ACE
            + sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)
            + GetLengthSid(pAuthenticatedUsersSID);

      // allocate memory for the DACL
      pDACL = (PACL) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
            dwAclLength);
      if (!pDACL) {
         printf("HeapAlloc() failed with error %d/n", GetLastError());
         __leave;
      }

      // initialize the DACL
      if (!InitializeAcl(pDACL, dwAclLength, ACL_REVISION)) {
         printf("InitializeAcl() failed with error %d/n",
               GetLastError());
         __leave;
      }
     
      // add the Authenticated Users group ACE to the DACL with
      // GENERIC_READ, GENERIC_WRITE, and GENERIC_EXECUTE access
      if (!AddAccessAllowedAce(pDACL, ACL_REVISION,
            GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE,
            pAuthenticatedUsersSID)) {
         printf("AddAccessAllowedAce() failed with error %d/n",
               GetLastError());
         __leave;
      }

      // set the DACL in the security descriptor
      if (!SetSecurityDescriptorDacl(pSD, TRUE, pDACL, FALSE)) {
         printf("SetSecurityDescriptorDacl() failed with error %d/n",
               GetLastError());
         __leave;
      }

      bResult = TRUE;
    
   } __finally {

      if (pAuthenticatedUsersSID) FreeSid(pAuthenticatedUsersSID);
   }

   if (bResult == FALSE) {
      if (pDACL) HeapFree(GetProcessHeap(), 0, pDACL);
      pDACL = NULL;
   }

   return (PVOID) pDACL;
}

// The following function frees memory allocated in the
// BuildRestrictedSD() function
VOID FreeRestrictedSD(PVOID ptr) {

   if (ptr) HeapFree(GetProcessHeap(), 0, ptr);

   return;
}

void main(void)
{
   SECURITY_ATTRIBUTES sa;
   SECURITY_DESCRIPTOR sd;

   PVOID  ptr;
   HANDLE hMutex;

   // build a restricted security descriptor
   ptr = BuildRestrictedSD(&sd);
   if (!ptr) {
      printf("BuildRestrictedSD() failed/n");
      return;
   }

   // create a mutex using the security descriptor
   sa.nLength = sizeof(sa);
   sa.lpSecurityDescriptor = &sd;
   sa.bInheritHandle = FALSE;

   hMutex = CreateMutex(&sa, FALSE, "RestrictedMutex");
   if (!hMutex)
      printf("CreateMutex() failed with error %d/n", GetLastError());

   // free the memory allocated by BuildRestrictedSD
   FreeRestrictedSD(ptr);

   // use the mutex ...

   printf("Press the return key to close the mutex handle.../n");
   getchar();

   // close the mutex handle
   CloseHandle(hMutex);
}

本文来自:http://support.microsoft.com/kb/CHS106387/ZH-CN/#appliesto

跨进程共享内核对象方法:命名对象

下面的所有函数都可以创建命名的内核对象: CreateMutex,CreateEvent,CreateFileMapping, CreateSemaphore,CreateWaitableTime...
  • tpnndhqc
  • tpnndhqc
  • 2016年08月29日 13:53
  • 802

不同进程间的共享问题

不同进程间的共享问题一直是编程人员常常需要面对,但又不容易解决的问题。我在写程序的工程中也深受其害,从而想到将自己遇到的情况做一下总结,也就促成了这篇文章。文章中重点论述有关数据和内核句柄的共享问题。...
  • welcome_ck
  • welcome_ck
  • 2004年12月24日 16:05
  • 3973

windows操作系统之跨进程边界共享内核对象

内核对象:用来管理进程,线程,文件等诸多种类的大量资源。 内核对象只是一个内存块,由操作系统分配,并只能由操作系统访问。 内核对象的句柄表(由进程中的所有线程访问): 索引 指...
  • w1012747007
  • w1012747007
  • 2017年08月13日 15:56
  • 81

Windows进程共享内核对象的3种方法

转载的:http://www.51testing.com/html/51/n-821751.html Windows内核对象是什么我这里就不介绍了,任何一本关于windows编程的书都会介绍,...
  • darkbus111
  • darkbus111
  • 2015年11月18日 14:39
  • 462

进程、线程及内核对象

进程、线程及内核对象   内核对象 每个内核对象只是内核分配的一个内存块,并且只能由该内核访问,这个内存块是一种数据结构,他的成员负责维护该对象的各种信息,如进程对象有一个进程ID、一个基本优先...
  • zh852
  • zh852
  • 2014年08月07日 15:02
  • 1270

内核对象及句柄的本质区别

本章讨论的是相对抽象的概念,不涉及任何具体的内核对象的细节而是讨论所有内核对象的共有特性。 首先让我们来了解一下什么是内核对象。内核对象通过API来创建,每个内核对象是一个数据结构,它对应一块内...
  • dotneterbj
  • dotneterbj
  • 2014年08月20日 17:23
  • 1088

互斥量与条件变量在进程间通信的应用——生产者与消费者问题

一、互斥量和条件变量          互斥量是一个可以处于两种状态之一的特殊变量:解锁和加锁,用于线程(进程)间互斥的进入临界区。其实互斥量是信号量的简化版本,信号量也是一种用于线程间互斥的进入临...
  • wang_dong001
  • wang_dong001
  • 2016年12月29日 20:15
  • 277

多个线程之间共享数据的方式探讨(七)

l如果每个线程执行的代码相同,可以使用同一个Runnable对象,这个Runnable对象中有那个共享数据,例如,买票系统就可以这么做。 l如果每个线程执行的代码不同,这时候需要用不同的Runnab...
  • lijinhua7602
  • lijinhua7602
  • 2015年01月31日 22:29
  • 1034

遍历 进程 内的内核对象

#ifndef UNICODE #define UNICODE #endif #include #include #define NT_SUCCESS(x) ((x) >= 0) #defin...
  • sz76211822
  • sz76211822
  • 2015年01月22日 09:14
  • 492

多线程并发库高级应用 之 多个线程之间共享数据的方式探讨

笔记摘要:            多个线程之间共享数据,按照每个线程执行代码是否相同,我们可以采取不同的处理方式,这里通过简单的卖票示例说明了当每个线程执行相同代码的情况,          ...
  • xushuaic
  • xushuaic
  • 2012年12月05日 13:08
  • 1121
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:如何在进程之间共享内核对象
举报原因:
原因补充:

(最多只允许输入30个字)