使用 C++ 控制子对象的创建

可以使用容器对象的 DACL 来控制允许谁在容器中创建子对象。 这一点可能很重要,因为对象的创建者通常分配为对象的所有者,并且对象的所有者可以控制对对象的访问。

各种类型的容器对象具有特定的访问权限,用于控制创建子对象的能力。 例如,线程必须具有对注册表项KEY_CREATE_SUB_KEY访问权限,才能在注册表项下创建子项。 注册表项的 DACL 可以包含允许或拒绝此访问权限的 ACE。 同样,NTFS 支持FILE_ADD_FILE和FILE_ADD_SUBDIRECTORY访问权限,以控制在目录中创建文件或目录的能力。

ADS_RIGHT_DS_CREATE_CHILD访问权限控制在目录服务 (DS) 对象中创建子对象。 但是,DS 对象可以包含不同类型的对象,因此系统支持更精细的控制粒度。 可以使用 特定于对象的 ACE 允许或拒绝创建指定类型的子对象的权限。 可以允许用户创建一种类型的子对象,同时阻止用户创建其他类型的子对象。

以下示例使用 SetEntriesInAcl 函数将对象特定的 ACE 添加到 ACL。 ACE 授予创建指定类型的子对象的权限。 EXPLICIT_ACCESS 结构的 grfAccessPermissions 成员设置为 ADS_RIGHT_DS_CREATE_CHILD 以指示 ACE 控制子对象的创建。 OBJECTS_AND_SID 结构的 ObjectsPresent 成员设置为 ACE_OBJECT_TYPE_PRESENT 以指示 ObjectTypeGuid 成员包含有效的 GUID。 GUID 标识正在控制其创建的子对象的类型。

在以下示例中,pOldDACL 必须是指向现有 ACL 结构的有效指针。 有关如何为对象创建 ACL 结构的信息,请参阅 使用 C++ 为新对象创建安全描述符

DWORD dwRes;
PACL pOldDACL = NULL;
PACL pNewDACL = NULL;
GUID guidChildObjectType = GUID_NULL;   // GUID of object to control creation of
PSID pTrusteeSID = NULL;           // trustee for new ACE
EXPLICIT_ACCESS ea;
OBJECTS_AND_SID ObjectsAndSID;

// pOldDACL must be a valid pointer to an existing ACL structure.

// guidChildObjectType must be the GUID of an object type 
// that is a possible child of the object associated with pOldDACL.
 
// Initialize an OBJECTS_AND_SID structure with object type GUIDs and 
// the SID of the trustee for the new ACE. 

ZeroMemory(&ObjectsAndSID, sizeof(OBJECTS_AND_SID));
ObjectsAndSID.ObjectsPresent = ACE_OBJECT_TYPE_PRESENT;
ObjectsAndSID.ObjectTypeGuid = guidChildObjectType;
ObjectsAndSID.InheritedObjectTypeGuid  = GUID_NULL;
ObjectsAndSID.pSid = (SID *)pTrusteeSID;

// Initialize an EXPLICIT_ACCESS structure for the new ACE. 

ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS));
ea.grfAccessPermissions = ADS_RIGHT_DS_CREATE_CHILD;
ea.grfAccessMode = GRANT_ACCESS;
ea.grfInheritance= NO_INHERITANCE;
ea.Trustee.TrusteeForm = TRUSTEE_IS_OBJECTS_AND_SID;
ea.Trustee.ptstrName = (LPTSTR) &ObjectsAndSID;

// Create a new ACL that merges the new ACE
// into the existing DACL.

dwRes = SetEntriesInAcl(1, &ea, pOldDACL, &pNewDACL);