How do I programmatically set *inheritable* permissions on registry keys?

From: Malcolm Ferguson (Malcolm_Ferguson_at_NO_SPAM_PLEASEyahoo.com)
Date: 01/28/05


Date: Fri, 28 Jan 2005 13:51:11 -0500

I'm struggling to find a way to programmatically set inheritable
permissions on registry keys. The only examples I've seen set them on a
specified key and advise one to apply it recursively. This is fine if
that part of the registry is static... but useless if new keys are to be
created in the future as they won't inherit the new permissions.

I've cobbled together two code examples that do what I describe. How
would I modify them to make them inheritable? I read somewhere about
CONTAINER_INHERIT, but I don't know it's value, and nor where I should
apply it.

BOOL setPermissionsExample1()
{
        // Resets permissions on a key so that they are Full Access to special
        // group INTERACTIVE. Appears to only set permissions for the specified
        // key and not for subkeys as well.

        HKEY hKey = NULL;
        TCHAR szSubkeyName[] = _T("SOFTWARE\\MyKey");
        if (ERROR_SUCCESS != ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, szSubkeyName,
0, WRITE_DAC, &hKey))
        {
                return FALSE;
        }
        
        SID_IDENTIFIER_AUTHORITY SecIA = SECURITY_NT_AUTHORITY;
        PSID pSid = NULL;
        
        if (FALSE == ::AllocateAndInitializeSid(&SecIA, 1,
SECURITY_INTERACTIVE_RID, 0, 0, 0, 0, 0, 0, 0, &pSid))
        {
                return FALSE;
        }
        
        BOOL bSuccess = FALSE;
        
        DWORD dwAclSize = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) +
::GetLengthSid(pSid) - sizeof(DWORD);
        PACL pDacl = (PACL) new BYTE[dwAclSize];
        
        if (TRUE == ::InitializeAcl(pDacl, dwAclSize, ACL_REVISION))
        {
                if (TRUE == ::AddAccessAllowedAce(pDacl, ACL_REVISION, KEY_ALL_ACCESS,
pSid))
                {
                        SECURITY_DESCRIPTOR SecDesc;
                        if (TRUE == ::InitializeSecurityDescriptor(&SecDesc,
SECURITY_DESCRIPTOR_REVISION))
                        {
                                if (TRUE == ::SetSecurityDescriptorDacl(&SecDesc, TRUE, pDacl, FALSE))
                                {
                                        bSuccess = (ERROR_SUCCESS == ::RegSetKeySecurity(hKey,
(SECURITY_INFORMATION)DACL_SECURITY_INFORMATION, &SecDesc));
                                }
                        }
                }
        }
        
        ::RegCloseKey(hKey);
        delete[] (BYTE*) pDacl;
        if (pSid != NULL)
        {
                ::FreeSid(pSid);
        }

        return bSuccess;
}

void setPermissionsExample2()
{
        // Resets permissions on a key so that they are Full Access to special
        // group EVERYONE. Appears to only set permissions for the specified
        // key and not for subkeys as well.

        TCHAR szSubkeyName[] = _T("SOFTWARE\\MyKey");
        HKEY myKey;
        unsigned char *p = new unsigned char[9000];
        PSECURITY_DESCRIPTOR psecdesc = (PSECURITY_DESCRIPTOR)p;
        DWORD sts = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, szSubkeyName, 0,
KEY_ALL_ACCESS, &myKey);

        if (sts == ERROR_SUCCESS)
        {
                sts = InitializeSecurityDescriptor(psecdesc,
SECURITY_DESCRIPTOR_REVISION);
                sts = SetSecurityDescriptorDacl(psecdesc, TRUE, NULL, TRUE);
                sts = ::RegSetKeySecurity(myKey, DACL_SECURITY_INFORMATION, psecdesc);
                sts = ::RegCloseKey(myKey);
        }
        delete [] p;
}