Get Registry Key ACL As Enum - Delphi
DarkCoderSc
Jean-Pierre LESUEUR
uses
System.SysUtils, Winapi.Windows, Generics.Collections;
// ...
type
TRegistryKeyPermission = (
rkpRead,
rkpWrite,
rkpExecute,
rkpQueryValue,
rkpSetValue,
rkpCreateSubKey,
rkpEnumerateSubKeys,
rkpNotify,
rkpDelete
);
TRegistryKeyPermissions = set of TRegistryKeyPermission;
// ...
procedure GetCurrentUserRegistryKeyAccess(const AHive : HKEY; const AKeyPath : String; out ARegistryKeyPermissions : TRegistryKeyPermissions);
begin
ARegistryKeyPermissions := [];
///
var AImpersonated := False;
var ASecurityDescriptorSize := DWORD(0);
var ptrSecurityDescriptor := PSecurityDescriptor(nil);
var hToken := THandle(0);
///
var AKeyHandle := HKEY(0);
try
var AResult := RegOpenKeyExW(AHive, PWideChar(AKeyPath), 0, READ_CONTROL, AKeyHandle);
if AResult <> ERROR_SUCCESS then
raise EWindowsException.Create('RegOpenKeyW', AResult);
///
AImpersonated := ImpersonateSelf(SecurityImpersonation);
if not OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, False, hToken) then
raise EWindowsException.Create('OpenProcessToken');
///
var AFlags := OWNER_SECURITY_INFORMATION or GROUP_SECURITY_INFORMATION or DACL_SECURITY_INFORMATION;
AResult := RegGetKeySecurity(AKeyHandle, AFlags, nil, ASecurityDescriptorSize);
if (AResult <> ERROR_SUCCESS) and (AResult <> 122) then
raise EWindowsException.Create('GetNamedSecurityInfoW', AResult);
GetMem(ptrSecurityDescriptor, ASecurityDescriptorSize);
AResult := RegGetKeySecurity(AKeyHandle, AFlags, ptrSecurityDescriptor, ASecurityDescriptorSize);
if AResult <> ERROR_SUCCESS then
raise EWindowsException.Create('GetNamedSecurityInfoW', AResult);
///
if AccessCheck(KEY_READ, hToken, ptrSecurityDescriptor) then
Include(ARegistryKeyPermissions, rkpRead);
if AccessCheck(KEY_WRITE, hToken, ptrSecurityDescriptor) then
Include(ARegistryKeyPermissions, rkpWrite);
if AccessCheck(KEY_EXECUTE, hToken, ptrSecurityDescriptor) then
Include(ARegistryKeyPermissions, rkpExecute);
if AccessCheck(KEY_QUERY_VALUE, hToken, ptrSecurityDescriptor) then
Include(ARegistryKeyPermissions, rkpQueryValue);
if AccessCheck(KEY_SET_VALUE, hToken, ptrSecurityDescriptor) then
Include(ARegistryKeyPermissions, rkpSetValue);
if AccessCheck(KEY_CREATE_SUB_KEY, hToken, ptrSecurityDescriptor) then
Include(ARegistryKeyPermissions, rkpCreateSubKey);
if AccessCheck(KEY_ENUMERATE_SUB_KEYS, hToken, ptrSecurityDescriptor) then
Include(ARegistryKeyPermissions, rkpEnumerateSubKeys);
if AccessCheck(KEY_NOTIFY, hToken, ptrSecurityDescriptor) then
Include(ARegistryKeyPermissions, rkpNotify);
if AccessCheck(_DELETE, hToken, ptrSecurityDescriptor) then
Include(ARegistryKeyPermissions, rkpDelete);
finally
if AKeyHandle <> 0 then
RegCloseKey(AKeyHandle);
if Assigned(ptrSecurityDescriptor) then
FreeMem(ptrSecurityDescriptor, ASecurityDescriptorSize);
if hToken <> 0 then
CloseHandle(hToken);
if AImpersonated then
RevertToSelf();
end;
end;
// ...
procedure PrintAccess(const ARegistryKeyPermissions : TRegistryKeyPermissions);
begin
var AList := TList<String>.Create();
try
if rkpRead in ARegistryKeypermissions then
AList.Add('Read');
if rkpWrite in ARegistryKeypermissions then
AList.Add('Write');
if rkpExecute in ARegistryKeypermissions then
AList.Add('Execute');
if rkpQueryValue in ARegistryKeypermissions then
AList.Add('Query Value');
if rkpSetValue in ARegistryKeypermissions then
AList.Add('Set Value');
if rkpCreateSubKey in ARegistryKeypermissions then
AList.Add('Create Sub Key');
if rkpEnumerateSubKeys in ARegistryKeypermissions then
AList.Add('Enumerate Sub Keys');
if rkpNotify in ARegistryKeypermissions then
AList.Add('Notify');
if rkpDelete in ARegistryKeypermissions then
AList.Add('Delete');
if AList.Count = 0 then
WriteLn('No access')
else
WriteLn(String.Join(',', AList.ToArray));
finally
FreeAndNil(AList);
end;
end;
begin
try
var ARegistryKeyPermissions : TRegistryKeyPermissions;
GetCurrentUserRegistryKeyAccess(HKEY_LOCAL_MACHINE, 'Software', ARegistryKeyPermissions);
WriteLn('HKLM\Software:');
PrintAccess(ARegistryKeyPermissions);
except
on e : Exception do
WriteLn(e.Message);
end;
// ...
Depends On
Implemented By Technique
Created
December 2, 2025
Last Revised
December 2, 2025
Windows Registry Enumeration