Protected Registry key access under Vista.
I have code which works on 2k and XP, which, when run under an administrators
account, changes the permissions on a hardware/enum key in the registry so
that we can make changes to a value for our device. Normally the local
administrator does not have this access but creating a new DACL for the
account, then opening the key with WRITE_DAC access and setting the new access
allows opening the final key with write permissions.
This has stopped working in Vista. Everything about the procedure including
AllocateAndInitializeSid, InitializeAcl, AddAccessAllowedAce,
InitializeSecurityDescriptor, SetSecurityDescriptorDacl goes off without a
hitch just like under 2k and XP but then RegOpenKeyEx with WRITE_DAC access
fails with Error 5 (Acess Denied) exactly as if nothing above had done
anything at all.
Anyone know what might have changed in Vista administrator ACLS or the
registry permissions themselves that might have caused this? The registry
permissions for the key look the same in Vista as XP as far as I can tell.
Code:
//
// Create a security descriptor that has full permissions to the administrators group
//
SID_IDENTIFIER_AUTHORITY sia = SECURITY_NT_AUTHORITY;
PSID pAdministratorsSid = NULL;
SECURITY_DESCRIPTOR sd;
PACL pDacl = NULL;
DWORD dwAclSize;
// Preprare a Sid representing the well-known admin group
if(!AllocateAndInitializeSid(
&sia,
2,
SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS,
0, 0, 0, 0, 0, 0,
&pAdministratorsSid
))
{
PrintError("AllocateAndInitializeSid (Admins) failed:", GetLastError());
goto final_cleanup;
}
// Compute size of new acl
dwAclSize = sizeof(ACL) +
1 * ( sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) ) +
GetLengthSid(pAdministratorsSid);
// Allocate storage for Acl
pDacl = (PACL)HeapAlloc(GetProcessHeap(), 0, dwAclSize);
if(pDacl == NULL) goto final_cleanup;
if(!InitializeAcl(pDacl, dwAclSize, ACL_REVISION))
{
PrintError("InitializeAcl failed: ", GetLastError());
goto final_cleanup;
}
// Grant the Administrators Sid KEY_ALL_ACCESS access to the perf key
if(!AddAccessAllowedAce(
pDacl,
ACL_REVISION,
KEY_ALL_ACCESS,
pAdministratorsSid
))
{
PrintError("AddAccessAllowedAce (Admins) failed: ", GetLastError());
goto final_cleanup;
}
// Initialize and set the security descriptor and DACL
if(!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION))
{
PrintError("InitializeSecurityDescriptor", GetLastError());
goto final_cleanup;
}
if(!SetSecurityDescriptorDacl(&sd, TRUE, pDacl, FALSE))
{
PrintError("SetSecurityDescriptorDacl", GetLastError());
goto final_cleanup;
}
//
// Now we can open the registry to the Enum/HID/<MSR VID/PID> key and enumerate installed MSRs
//
// Open the registry to the Enum\HID\Vid_04b4&Pid_210 key
HKEY hKey, hDeviceKey;
DWORD dwErr;
if ((dwErr = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
g_szKeyboardDeviceSearchPath,
0,
KEY_ENUMERATE_SUB_KEYS,
&hKey)) != ERROR_SUCCESS)
{
PrintError(_T("Failed to open the Enum/HID registry key for enumeration: "), dwErr);
goto final_cleanup;
}
// Enum all the keys under the Vid_04b4&Pid_210 key
TCHAR szKey[256];
int nIdx = 0;
unsigned char *pSDOld = 0;
while (RegEnumKey(hKey, nIdx, szKey, 256) == ERROR_SUCCESS)
{
TCHAR szDeviceKey[MAX_PATH];
_tcscpy(szDeviceKey, g_szKeyboardDeviceSearchPath);
_tcscat(szDeviceKey, _T("\\"));
_tcscat(szDeviceKey, szKey);
hDeviceKey = 0;
// Open the enumed key for WRITE_DAC and READ_CONTROL access
if ((dwErr = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
szDeviceKey,
0,
WRITE_DAC | READ_CONTROL,
&hDeviceKey)) != ERROR_SUCCESS)
{
PrintError("Failed to open the device key for WRITE_DAC access: ", dwErr);
goto cleanup;
}
[SNIP]
The call to RegOpenKeyEx with WRITE_DAC access fails with error 5 Access Denied on Vista
when run from a local administrators account but not 2k or XP.

