我有一个有趣的问题,我希望有人能解释一下。我们正在做以下事情:
- 创建一个注册表项。
- 使用 SetSecurityDescriptorDacl 将 ACCESS_ALLOWED_ACE 添加到 DACL。
- 在 Regedit 中查看密钥(权限看起来不错)
- 在 Regedit 中,添加一个新的子键。
- 查看子键的权限。
Regedit 报告权限排序不正确(并且似乎添加了一些意外权限)。
然而。
如果您在 Regedit 而不是以编程方式创建第一个键,然后重复步骤 3-5,则正确创建子键。
使用一些附加代码(未包含在下面),我比较了 Regedit 创建的密钥和以编程方式创建的密钥的 DACL,它们是相同的。但是,如果您通过代码创建密钥,那么似乎出了点问题。
下面是一些创建密钥和修改访问权限的示例代码。它基本上是一个 MSDN 示例,只是进行了调整以修改注册表项。同样,它正确地创建了密钥,但子密钥不正确。
任何线索将不胜感激。
#include "stdafx.h"
#include <Windows.h>
#include <Sddl.h>
BOOL AddAceToKey(HKEY hKey, PSID psid)
{
ACCESS_ALLOWED_ACE *pace = NULL;
ACL_SIZE_INFORMATION aclSizeInfo;
BOOL bDaclExist;
BOOL bDaclPresent;
BOOL bSuccess = FALSE;
DWORD dwNewAclSize;
DWORD dwSidSize = 0;
DWORD dwSdSizeNeeded = 0;
PACL pacl;
PACL pNewAcl = NULL;
PSECURITY_DESCRIPTOR psd = NULL;
PSECURITY_DESCRIPTOR psdNew = NULL;
PVOID pTempAce;
SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION;
unsigned int i;
__try
{
// Obtain the DACL for the key.
LONG lResult = RegGetKeySecurity
( hKey
, si
, 0
, &dwSdSizeNeeded
);
if ( lResult != ERROR_SUCCESS )
if ( lResult == ERROR_INSUFFICIENT_BUFFER)
{
psd = (PSECURITY_DESCRIPTOR)HeapAlloc(
GetProcessHeap(),
HEAP_ZERO_MEMORY,
dwSdSizeNeeded);
if (psd == NULL)
__leave;
psdNew = (PSECURITY_DESCRIPTOR)HeapAlloc(
GetProcessHeap(),
HEAP_ZERO_MEMORY,
dwSdSizeNeeded);
if (psdNew == NULL)
__leave;
dwSidSize = dwSdSizeNeeded;
if (RegGetKeySecurity(
hKey,
si,
psd,
&dwSdSizeNeeded) != ERROR_SUCCESS
)
__leave;
}
else
__leave;
// Create a new DACL.
if (!InitializeSecurityDescriptor(
psdNew,
SECURITY_DESCRIPTOR_REVISION)
)
__leave;
// Get the DACL from the security descriptor.
if (!GetSecurityDescriptorDacl(
psd,
&bDaclPresent,
&pacl,
&bDaclExist)
)
__leave;
// Initialize the ACL.
ZeroMemory(&aclSizeInfo, sizeof(ACL_SIZE_INFORMATION));
aclSizeInfo.AclBytesInUse = sizeof(ACL);
// Call only if the DACL is not NULL.
if (pacl != NULL)
{
// get the file ACL size info
if (!GetAclInformation(
pacl,
(LPVOID)&aclSizeInfo,
sizeof(ACL_SIZE_INFORMATION),
AclSizeInformation)
)
__leave;
}
// Compute the size of the new ACL.
dwNewAclSize = aclSizeInfo.AclBytesInUse +
sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(psid) - sizeof(DWORD);
// Allocate memory for the new ACL.
pNewAcl = (PACL)HeapAlloc(
GetProcessHeap(),
HEAP_ZERO_MEMORY,
dwNewAclSize);
if (pNewAcl == NULL)
__leave;
// Initialize the new DACL.
if (!InitializeAcl(pNewAcl, dwNewAclSize, ACL_REVISION))
__leave;
// Add the ACE to the key
pace = (ACCESS_ALLOWED_ACE *)HeapAlloc(
GetProcessHeap(),
HEAP_ZERO_MEMORY,
sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(psid) -
sizeof(DWORD));
if (pace == NULL)
__leave;
pace->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
pace->Header.AceFlags = CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE;
pace->Header.AceSize = LOWORD(sizeof(ACCESS_ALLOWED_ACE) +
GetLengthSid(psid) - sizeof(DWORD));
pace->Mask = KEY_ALL_ACCESS;
if (!CopySid(GetLengthSid(psid), &pace->SidStart, psid))
__leave;
if (!AddAce(
pNewAcl,
ACL_REVISION,
MAXDWORD,
(LPVOID)pace,
pace->Header.AceSize)
)
__leave;
// If DACL is present, copy it to a new DACL.
if (bDaclPresent)
{
// Copy the ACEs to the new ACL.
if (aclSizeInfo.AceCount)
{
for (i=0; i < aclSizeInfo.AceCount; i++)
{
// Get an ACE.
if (!GetAce(pacl, i, &pTempAce))
__leave;
// Add the ACE to the new ACL.
if (!AddAce(
pNewAcl,
ACL_REVISION,
MAXDWORD,
pTempAce,
((PACE_HEADER)pTempAce)->AceSize)
)
__leave;
}
}
}
// Set a new DACL for the security descriptor.
if (!SetSecurityDescriptorDacl(
psdNew,
TRUE,
pNewAcl,
FALSE)
)
__leave;
// Set the new security descriptor for the window station.
if (RegSetKeySecurity( hKey, si, psdNew ) != ERROR_SUCCESS)
__leave;
// Indicate success.
bSuccess = TRUE;
}
__finally
{
// Free the allocated buffers.
if (pace != NULL)
HeapFree(GetProcessHeap(), 0, (LPVOID)pace);
if (pNewAcl != NULL)
HeapFree(GetProcessHeap(), 0, (LPVOID)pNewAcl);
if (psd != NULL)
HeapFree(GetProcessHeap(), 0, (LPVOID)psd);
if (psdNew != NULL)
HeapFree(GetProcessHeap(), 0, (LPVOID)psdNew);
}
return bSuccess;
}
int _tmain(int argc, _TCHAR* argv[])
{
HKEY hKey;
DWORD dwDisposition;
LONG lResult = RegCreateKeyEx
( HKEY_LOCAL_MACHINE
, L"SOFTWARE\\MyCompany"
, 0
, NULL
, REG_OPTION_NON_VOLATILE
, KEY_ALL_ACCESS | KEY_WOW64_64KEY
, NULL
, &hKey
, &dwDisposition
);
if ( lResult != ERROR_SUCCESS )
{
return 1;
}
PSID pSid;
// The 'Users' SID.
ConvertStringSidToSid( L"S-1-5-32-545", &pSid );
AddAceToKey( hKey, pSid );
LocalFree( pSid );
RegCloseKey( hKey );
return 0;
}