Newsgroups : Borland : borland.public.delphi.rtl.win32 : 2006 Jan : EditSecurity(), RegGetKeySecurity() woes!
| Subject: | EditSecurity(), RegGetKeySecurity() woes! |
| Posted by: | "Lloyd Kinsella" (lloydkinsel..@gmail.com) |
| Date: | 21 Jan 2006 09:27:31 |
Hi,
I'm using EditSecurity() in the hopes of being able to edit the
security descriptor returned by RegGetKeySecurity().
However I'm having some issues:
1. I get a dialog telling me I don't have permission, even though I'm
logged in as Administrator.
2. There seems to be no default users/groups set for the descriptor.
3. The permissions are screwed up with odd values that look like random
memory?
Below is the code I'm using. I use the JwaAclUi.pas from the JEDI Win32
API conversion.
Any insights into this would be most appreciated.
- Lloyd K
//----------------------------------------------------------------------
unit Unit2;
interface
uses Windows, SysUtils, Classes, JwaAccCtrl, JwaWinNT, JwaWinUser,
JwaWinType, JwaAclUI;
type
TSecurityInformation = class(TInterfacedObject, ISecurityInformation)
private
FKey: THandle;
protected
function GetObjectInformation(out pObjectInfo: SI_OBJECT_INFO):
HRESULT; stdcall;
function GetSecurity(RequestedInformation: SECURITY_INFORMATION;
out ppSecurityDescriptor: PSECURITY_DESCRIPTOR; fDefault:
BOOL): HRESULT; stdcall;
function SetSecurity(SecurityInformation: SECURITY_INFORMATION;
pSecurityDescriptor: PSECURITY_DESCRIPTOR): HRESULT; stdcall;
function GetAccessRights(pguidObjectType: LPGUID; dwFlags: DWORD;
out ppAccess: PSI_ACCESS; out pcAccesses, piDefaultAccess:
ULONG): HRESULT; stdcall;
function MapGeneric(pguidObjectType: LPGUID; pAceFlags: PUCHAR;
pMask: PACCESS_MASK): HRESULT; stdcall;
function GetInheritTypes(out ppInheritTypes: PSI_INHERIT_TYPE;
out pcInheritTypes: ULONG): HRESULT; stdcall;
function PropertySheetPageCallback(hwnd: HWND; uMsg: UINT;
uPage: SI_PAGE_TYPE): HRESULT; stdcall;
public
constructor Create(AKey: THandle);
end;
implementation
const
GUID_NULL: TGUID = '{00000000-0000-0000-0000-000000000000}';
IDS_ACCESS_FULLCONTROL = 'Full Control';
IDS_ACCESS_READ = 'Read';
IDS_ACCESS_QUERYVALUE = 'Query Value';
IDS_ACCESS_SETVALUE = 'Set Value';
IDS_ACCESS_CREATESUBKEY = 'Create Subkey';
IDS_ACCESS_ENUMERATESUBKEYS = 'Enumerate Subkeys';
IDS_ACCESS_NOTIFY = 'Notify';
IDS_ACCESS_CREATELINK = 'Create Link';
IDS_ACCESS_DELETE = 'Delete';
IDS_ACCESS_WRITEDAC = 'Write DAC';
IDS_ACCESS_WRITEOWNER = 'Write Owner';
IDS_ACCESS_READCONTROL = 'Read Control';
IDS_INHERIT_THISKEYONLY = 'This key only';
IDS_INHERIT_THISKEYANDSUBKEYS = 'This key and subkeys';
IDS_INHERIT_SUBKEYSONLY = 'Subkeys only';
{
var
RegAccess: array of SI_ACCESS;
}
const
RegAccess: array [0..11] of SI_ACCESS = (
(
pguid: @GUID_NULL;
mask: KEY_ALL_ACCESS;
pszName:
IDS_ACCESS_FULLCONTROL;
dwFlags: SI_ACCESS_GENERAL
or SI_ACCESS_SPECIFIC
),
(
pguid: @GUID_NULL;
mask: KEY_READ;
pszName: IDS_ACCESS_READ;
dwFlags: SI_ACCESS_GENERAL
),
(
pguid: @GUID_NULL;
mask: KEY_QUERY_VALUE;
pszName:
IDS_ACCESS_QUERYVALUE;
dwFlags: SI_ACCESS_SPECIFIC
),
(
pguid: @GUID_NULL;
mask: KEY_SET_VALUE;
pszName: IDS_ACCESS_SETVALUE;
dwFlags: SI_ACCESS_SPECIFIC
),
(
pguid: @GUID_NULL;
mask: KEY_CREATE_SUB_KEY;
pszName:
IDS_ACCESS_CREATESUBKEY;
dwFlags: SI_ACCESS_SPECIFIC
),
(
pguid: @GUID_NULL;
mask: KEY_ENUMERATE_SUB_KEYS;
pszName:
IDS_ACCESS_ENUMERATESUBKEYS;
dwFlags: SI_ACCESS_SPECIFIC
),
(
pguid: @GUID_NULL;
mask: KEY_NOTIFY;
pszName: IDS_ACCESS_NOTIFY;
dwFlags: SI_ACCESS_SPECIFIC
),
(
pguid: @GUID_NULL;
mask: KEY_CREATE_LINK;
pszName:
IDS_ACCESS_CREATELINK;
dwFlags: SI_ACCESS_SPECIFIC
),
(
pguid: @GUID_NULL;
mask: DELETE;
pszName: IDS_ACCESS_DELETE;
dwFlags: SI_ACCESS_SPECIFIC
),
(
pguid: @GUID_NULL;
mask: WRITE_DAC;
pszName: IDS_ACCESS_WRITEDAC;
dwFlags: SI_ACCESS_SPECIFIC
),
(
pguid: @GUID_NULL;
mask: WRITE_OWNER;
pszName:
IDS_ACCESS_WRITEOWNER;
dwFlags: SI_ACCESS_SPECIFIC
),
(
pguid: @GUID_NULL;
mask: READ_CONTROL;
pszName:
IDS_ACCESS_READCONTROL;
dwFlags: SI_ACCESS_SPECIFIC
)
);
RegDefaultAccess: DWORD = 1; // KEY_READ
RegAccessMasks: Windows.GENERIC_MAPPING = (
GenericRead: KEY_READ;
GenericWrite: KEY_WRITE;
GenericExecute:
KEY_EXECUTE;
GenericAll: KEY_ALL_ACCESS
);
RegInheritTypes: array [0..2] of SI_INHERIT_TYPE = (
(
pguid:
@GUID_NULL;
dwFlags: 0;
pszName:
IDS_INHERIT_THISKEYONLY;
),
(
pguid:
@GUID_NULL;
dwFlags:
CONTAINER_INHERIT_ACE;
pszName:
IDS_INHERIT_THISKEYANDSUBKEYS;
),
(
pguid:
@GUID_NULL;
dwFlags:
INHERIT_ONLY_ACE or CONTAINER_INHERIT_ACE;
pszName:
IDS_INHERIT_SUBKEYSONLY;
)
);
constructor TSecurityInformation.Create(AKey: THandle);
begin
inherited Create;
FKey := AKey;
end;
function TSecurityInformation.GetObjectInformation(out pObjectInfo:
SI_OBJECT_INFO): HRESULT;
begin
ZeroMemory(@pObjectInfo,SizeOf(SI_OBJECT_INFO));
pObjectInfo.dwFlags := SI_EDIT_ALL or SI_ADVANCED or SI_CONTAINER;
pObjectInfo.hInstance := SysInit.HInstance;
Result := S_OK;
end;
function TSecurityInformation.GetSecurity(RequestedInformation:
SECURITY_INFORMATION;
out ppSecurityDescriptor: PSECURITY_DESCRIPTOR; fDefault: BOOL):
HRESULT;
var
DescriptorSize: DWORD;
SecurityDescriptor: Windows.PSecurityDescriptor;
ErrorCode: LongInt;
begin
Result := E_ACCESSDENIED;
ErrorCode :=
RegGetKeySecurity(FKey,RequestedInformation,nil,DescriptorSize);
if ErrorCode = ERROR_INSUFFICIENT_BUFFER then
begin
SecurityDescriptor :=
Windows.PSecurityDescriptor(LocalAlloc(LMEM_FIXED,DescriptorSize));
if Assigned(SecurityDescriptor) then
begin
if
RegGetKeySecurity(FKey,RequestedInformation,SecurityDescriptor,Descripto
rSize) = ERROR_SUCCESS then
begin
ppSecurityDescriptor :=
PSECURITY_DESCRIPTOR(SecurityDescriptor);
Result := S_OK;
end
else
LocalFree(THandle(SecurityDescriptor));
end
else
Result := E_OUTOFMEMORY;
end;
end;
function TSecurityInformation.SetSecurity(SecurityInformation:
SECURITY_INFORMATION;
pSecurityDescriptor: PSECURITY_DESCRIPTOR): HRESULT;
begin
Result := E_NOTIMPL;
end;
function TSecurityInformation.GetAccessRights(pguidObjectType: LPGUID;
dwFlags: DWORD;
out ppAccess: PSI_ACCESS; out pcAccesses, piDefaultAccess: ULONG):
HRESULT;
begin
ppAccess := @RegAccess[0];
pcAccesses := SizeOf(RegAccess);
piDefaultAccess := RegDefaultAccess;
Result := S_OK;
end;
function TSecurityInformation.MapGeneric(pguidObjectType: LPGUID;
pAceFlags: PUCHAR;
pMask: PACCESS_MASK): HRESULT;
begin
MapGenericMask(pMask^,RegAccessMasks);
pMask^ := pMask^ and (not SYNCHRONIZE);
Result := S_OK;
end;
function TSecurityInformation.GetInheritTypes(out ppInheritTypes:
PSI_INHERIT_TYPE;
out pcInheritTypes: ULONG): HRESULT;
begin
ppInheritTypes := @RegInheritTypes;
pcInheritTypes := SizeOf(RegInheritTypes);
Result := S_OK;
end;
function TSecurityInformation.PropertySheetPageCallback(hwnd: HWND;
uMsg: UINT;
uPage: SI_PAGE_TYPE): HRESULT;
begin
Result := E_NOTIMPL;
end;
{
function IDSToStrW(IDS: WideString): PWideChar;
begin
GetMem(Result,(Length(IDS) + 1) * SizeOf(WideChar));
Move(IDS[1],Result^,Length(IDS) * SizeOf(WideChar));
end;
procedure Init;
begin
SetLength(RegAccess,12);
RegAccess[0].pguid := @GUID_NULL;
RegAccess[0].mask:= KEY_ALL_ACCESS;
RegAccess[0].pszName:= IDSToStrW(IDS_ACCESS_FULLCONTROL);
RegAccess[0].dwFlags:= SI_ACCESS_GENERAL or SI_ACCESS_SPECIFIC;
RegAccess[1].pguid:= @GUID_NULL;
RegAccess[1].mask:= KEY_READ;
RegAccess[1].pszName:= IDSToStrW(IDS_ACCESS_READ);
RegAccess[1].dwFlags:= SI_ACCESS_GENERAL;
RegAccess[2].pguid:= @GUID_NULL;
RegAccess[2].mask:= KEY_QUERY_VALUE;
RegAccess[2].pszName:= IDSToStrW(IDS_ACCESS_QUERYVALUE);
RegAccess[2].dwFlags:= SI_ACCESS_SPECIFIC;
RegAccess[3].pguid:= @GUID_NULL;
RegAccess[3].mask:= KEY_SET_VALUE;
RegAccess[3].pszName:= IDSToStrW(IDS_ACCESS_SETVALUE);
RegAccess[3].dwFlags:= SI_ACCESS_SPECIFIC;
RegAccess[4].pguid:= @GUID_NULL;
RegAccess[4].mask:= KEY_CREATE_SUB_KEY;
RegAccess[4].pszName:= IDSToStrW(IDS_ACCESS_CREATESUBKEY);
RegAccess[4].dwFlags:= SI_ACCESS_SPECIFIC;
RegAccess[5].pguid:= @GUID_NULL;
RegAccess[5].mask:= KEY_ENUMERATE_SUB_KEYS;
RegAccess[5].pszName:= IDSToStrW(IDS_ACCESS_ENUMERATESUBKEYS);
RegAccess[5].dwFlags:= SI_ACCESS_SPECIFIC;
RegAccess[6].pguid:= @GUID_NULL;
RegAccess[6].mask:= KEY_NOTIFY;
RegAccess[6].pszName:= IDSToStrW(IDS_ACCESS_NOTIFY);
RegAccess[6].dwFlags:= SI_ACCESS_SPECIFIC;
RegAccess[7].pguid:= @GUID_NULL;
RegAccess[7].mask:= KEY_CREATE_LINK;
RegAccess[7].pszName:= IDSToStrW(IDS_ACCESS_CREATELINK);
RegAccess[7].dwFlags:= SI_ACCESS_SPECIFIC;
RegAccess[8].pguid:= @GUID_NULL;
RegAccess[8].mask:= DELETE;
RegAccess[8].pszName:= IDSToStrW(IDS_ACCESS_DELETE);
RegAccess[8].dwFlags:= SI_ACCESS_SPECIFIC;
RegAccess[9].pguid:= @GUID_NULL;
RegAccess[9].mask:= WRITE_DAC;
RegAccess[9].pszName:= IDSToStrW(IDS_ACCESS_WRITEDAC);
RegAccess[9].dwFlags:= SI_ACCESS_SPECIFIC;
RegAccess[10].pguid:= @GUID_NULL;
RegAccess[10].mask:= WRITE_OWNER;
RegAccess[10].pszName:= IDSToStrW(IDS_ACCESS_WRITEOWNER);
RegAccess[10].dwFlags:= SI_ACCESS_SPECIFIC;
RegAccess[11].pguid:= @GUID_NULL;
RegAccess[11].mask:= READ_CONTROL;
RegAccess[11].pszName:= IDSToStrW(IDS_ACCESS_READCONTROL);
RegAccess[11].dwFlags:= SI_ACCESS_SPECIFIC;
end;
initialization
Init;
}
end.
//----------------------------------------------------------------------
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls,
Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
btnGo: TButton;
procedure btnGoClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
uses Unit2, JwaAclUI;
const
RegRoot = HKEY_LOCAL_MACHINE;
RegPath = 'SOFTWARE\Workshell\ClipShare\1.0\CipherProviders';
procedure TForm1.btnGoClick(Sender: TObject);
var
Key: HKEY;
SI: ISecurityInformation;
begin
if RegOpenKeyEx(RegRoot,RegPath,0,KEY_ALL_ACCESS,Key) <>
ERROR_SUCCESS then
begin
ShowMessage('Cannot open Registry key.');
Exit;
end;
try
SI := TSecurityInformation.Create(Key);
try
if not EditSecurity(Handle,SI) then
begin
ShowMessage('Could not edit security information.');
Exit;
end;
finally
SI := nil;
end;
finally
RegCloseKey(Key);
end;
end;
end.