Solved

Delphi7 SetEntriesInAcl Error 87

Posted on 2010-08-19
16
1,827 Views
Last Modified: 2012-05-10
Hi all.
For several day I try to set new permissions to file in Windows 7 / XP. (Allow All to Everyone)
I do it in Delphi 7.

In theory - everything is not so difficult:
const
 SECURITY_WORLD_SID_AUTHORITY: SID_IDENTIFIER_AUTHORITY = (Value: (0, 0, 0, 0, 0, 1));
 SECURITY_WORLD_RID = $0;
var
 ExplicitAccess: EXPLICIT_ACCESS_A;
 psidEveryOne: PSID;
 pSD: PSECURITY_DESCRIPTOR;
 ptACL: PACL;
 ErrNo: Cardinal;
begin
 psidEveryOne := nil;
 pSD := nil;
 ptACL := nil;
 try
   win32check(AllocateAndInitializeSid(SECURITY_WORLD_SID_AUTHORITY,
     1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, psidEveryone));

   try
     ZeroMemory(@ExplicitAccess, SizeOf(ExplicitAccess));
     with ExplicitAccess do
     begin
       grfAccessPermissions:= GENERIC_ALL;
       grfAccessMode:= GRANT_ACCESS;
       grfInheritance:= NO_INHERITANCE;
       Trustee.TrusteeForm:= TRUSTEE_IS_SID;
       Trustee.TrusteeType:= TRUSTEE_IS_WELL_KNOWN_GROUP;
       Trustee.ptstrName:= psidEveryone;
     end;
     
     ErrNo := SetEntriesInAcl(1, @ExplicitAccess, nil, ptACL);
     if ErrNo <> ERROR_SUCCESS then
       raise Exception.Create(Format('Error ¿ %u', [ErrNo]))
     // And so on....

Open in new window


But, function SetEntriesInAcl always return 87 error (ERROR_INVALID_PARAMETER).
Can anybody say to me what am i doing wrong?

P.S. This code perfectly works on Delphi 2010 without any errors. But I need to make it work in Delphi 7
0
Comment
Question by:ZeBriD
  • 6
  • 5
  • 4
16 Comments
 
LVL 13

Accepted Solution

by:
aflarin earned 250 total points
ID: 33475668
the size of EXPLICIT_ACCESS_A is 24, but it must be 32.

the problem happens because the delphi's enumeration type (ACCESS_MODE, TRUSTEE_FORM, TRUSTEE_TYPE) generates only one byte instead of 4.

What you can do. Copy Delphi7\Source\Rtl\Win\AccCtrl.pas to your project folder and rename it (to AccCtrl2.pas for example), then add {$MINENUMSIZE 4} to its header:

unit AccCtrl2;

{$WEAKPACKAGEUNIT}
{$MINENUMSIZE 4} <---------------------------------- this line

Don't forget to change AccCtrl to AccCtrl2 in your uses sections. Make sure that SizeOf(ExplicitAccess) is 32 now.

If it works, you can compile new version of AccCtrl and replace previous version into Delphi\Lib and Delphi\Lib\Debug dirs
0
 
LVL 9

Expert Comment

by:sas13
ID: 33476590
its working code from my defrager


// do this before
function TDefrag.LoadPrivelege: boolean;
var
  _token_handle: THandle;
  _priv: TTokenPrivileges;
begin
 Result := false;
 if OpenProcessToken(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, _token_handle) then begin
  if LookupPrivilegeValue(nil, PChar('SeTakeOwnershipPrivilege'), _priv.Privileges[0].Luid) then begin
   _priv.PrivilegeCount := 1;
   _priv.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
   Result := AdjustTokenPrivileges(_token_handle, false, _priv, 0, PTokenPrivileges(nil)^, PDWord(nil)^)
  end;
  if LookupPrivilegeValue(nil, PChar('SeManageVolumePrivilege'), _priv.Privileges[0].Luid) then begin
   _priv.PrivilegeCount := 1;
   _priv.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
   Result := AdjustTokenPrivileges(_token_handle, false, _priv, 0, PTokenPrivileges(nil)^, PDWord(nil)^)
  end;
  if LookupPrivilegeValue(nil, PChar('SeSecurityPrivilege'), _priv.Privileges[0].Luid) then begin
   _priv.PrivilegeCount := 1;
   _priv.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
   Result := AdjustTokenPrivileges(_token_handle, false, _priv, 0, PTokenPrivileges(nil)^, PDWord(nil)^)
  end;
  if LookupPrivilegeValue(nil, PChar('SeBackupPrivilege'), _priv.Privileges[0].Luid) then begin
   _priv.PrivilegeCount := 1;
   _priv.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
   Result := AdjustTokenPrivileges(_token_handle, false, _priv, 0, PTokenPrivileges(nil)^, PDWord(nil)^)
  end;
  if LookupPrivilegeValue(nil, PChar('SeCreatePagefilePrivilege'), _priv.Privileges[0].Luid) then begin
   _priv.PrivilegeCount := 1;
   _priv.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
   Result := AdjustTokenPrivileges(_token_handle, false, _priv, 0, PTokenPrivileges(nil)^, PDWord(nil)^)
  end;
  if LookupPrivilegeValue(nil, PChar('SeDebugPrivilege'), _priv.Privileges[0].Luid) then begin
   _priv.PrivilegeCount := 1;
   _priv.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
   Result := AdjustTokenPrivileges(_token_handle, false, _priv, 0, PTokenPrivileges(nil)^, PDWord(nil)^)
  end;
  if LookupPrivilegeValue(nil, PChar('SeShutdownPrivilege'), _priv.Privileges[0].Luid) then begin
   _priv.PrivilegeCount := 1;
   _priv.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
   Result := AdjustTokenPrivileges(_token_handle, false, _priv, 0, PTokenPrivileges(nil)^, PDWord(nil)^)
  end;
  CloseHandle(_token_handle)
 end
end;

function TDefrDrive.TakeOwnership(const APath: PAnsiChar): boolean;
var
  _ea: EXPLICIT_ACCESS;
  _old_ACL: PACL;
  _new_ACL: PACL;
  _sd: pointer;
  _err: cardinal;
begin
 Result := false;      
 if GetNamedSecurityInfo(APath, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, nil, nil, @_old_ACL, nil, _sd) = ERROR_SUCCESS then begin
  ZeroMemory(@_ea, SizeOf(EXPLICIT_ACCESS));
  _ea.grfAccessPermissions := GENERIC_ALL;
  _ea.grfAccessMode := SET_ACCESS;
  _ea.grfInheritance := SUB_CONTAINERS_AND_OBJECTS_INHERIT;
  _ea.Trustee.TrusteeForm := TRUSTEE_IS_NAME;
  _ea.Trustee.TrusteeType := TRUSTEE_IS_USER;
  _ea.Trustee.ptstrName := 'CURRENT_USER';
  _new_ACL := nil;
  _err := SetEntriesInAcl(1, @_ea, _old_ACL, _new_ACL);
  if _err = ERROR_SUCCESS then begin
   Result := SetNamedSecurityInfo(APath, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, nil, nil, _new_ACL, nil) = ERROR_SUCCESS;
   LocalFree(cardinal(_new_ACL));
  end;
  LocalFree(cardinal(_sd))
 end
end;

Open in new window

0
 

Author Comment

by:ZeBriD
ID: 33481910
>{$MINENUMSIZE 4} <---------------------------------- this line
Already tried. Still not working.
0
 
LVL 13

Expert Comment

by:aflarin
ID: 33482406
>> Already tried. Still not working.

I've checked it under D7.  It works.

Make sure that SizeOf(ExplicitAccess) is 32.
0
 
LVL 9

Assisted Solution

by:sas13
sas13 earned 250 total points
ID: 33482957
modules AccAPI.pas & AccCtrl.pas attached.
they worked in Delphi 7
AclAPI.zip
0
 
LVL 13

Expert Comment

by:aflarin
ID: 33483011
>> modules AccAPI.pas & AccCtrl.pas attached.

sas31, there is no sense to add {$MINENUMSIZE 4} to AccAPI, because there is not any enumeration type there.
0
 

Author Comment

by:ZeBriD
ID: 33508863
>Make sure that SizeOf(ExplicitAccess) is 32.
Checked. It is 32.

>modules AccAPI.pas & AccCtrl.pas attached
I've tried use your units. Now there is no error.
BUT now there is no access rights (look at image bellow. it is in russian, but I hope you will understand the error)
dLjX2Maj31.png
0
How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

 
LVL 9

Expert Comment

by:sas13
ID: 33508908
where is function "SetNamedSecurityInfo" which set security object  ptACL after call "SetEntriesInAcl"?

see may example above (function "TakeOwnership").
0
 

Author Comment

by:ZeBriD
ID: 33509178
Well... I set permissions to crypto container.
Full current code in attach.
const

  SECURITY_WORLD_SID_AUTHORITY: SID_IDENTIFIER_AUTHORITY = (Value: (0, 0, 0, 0, 0, 1));

  SECURITY_WORLD_RID = $0;



var

  ExplicitAccess: EXPLICIT_ACCESS;

  psidEveryOne: PSID;

  pSD: PSECURITY_DESCRIPTOR;

  ptACL: PACL;

  ErrFunc: String;

  ErrNo: Cardinal;

  lpName,lpDomain : PAnsiChar;

  cbName,cbDomain : Cardinal;

  peUse : Cardinal;

begin

  psidEveryOne := nil;

  pSD := nil;

  ptACL := nil;

  try



    win32check(AllocateAndInitializeSid(SECURITY_WORLD_SID_AUTHORITY,

      1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, psidEveryone));



    cbName:=64;

    cbDomain:=64;



    GetMem(lpName,cbName*SizeOf(WideChar));

    GetMem(lpDomain,cbDomain*SizeOf(WideChar));



    if not LookupAccountSid(nil, psidEveryOne, lpName, cbName, lpDomain, cbDomain, peUse)

       and (GetLastError=122) then

    begin



      ReAllocMem(lpName,cbName*SizeOf(WideChar));

      ReAllocMem(lpDomain,cbDomain*SizeOf(WideChar));



      if not LookupAccountSid(nil, psidEveryOne, lpName, cbName, lpDomain, cbDomain, peUse) then

        raise Exception.Create(SysErrorMessage(GetLastError));

    end;



    ZeroMemory(@ExplicitAccess, SizeOf(ExplicitAccess));

     //BuildExplicitAccessWithNameW(@ExplicitAccess, PAnsiChar(WideCharToString(lpName)), GENERIC_ALL, SET_ACCESS, NO_INHERITANCE);

    BuildExplicitAccessWithName(@ExplicitAccess, lpName, GENERIC_ALL, SET_ACCESS, NO_INHERITANCE);



    try

      ErrNo := SetEntriesInAcl(1, @ExplicitAccess, nil, ptACL);

      if ErrNo <> ERROR_SUCCESS then

        raise Exception.Create(Format('SetEntriesInAcl error: %s', [SysErrorMessage(ErrNo)]));



      try

        pSD:= Pointer(LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH));

        try

          win32check(InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION));

          win32check(SetSecurityDescriptorDacl(pSD, false, ptACL, false));

          win32check(CryptSetProvParam(AhProv, PP_KEYSET_SEC_DESCR, pSD, DACL_SECURITY_INFORMATION));

        finally

          LocalFree(Cardinal(pSD));

        end;

      finally

        LocalFree(Cardinal(ptACL));

      end;

    finally

      FreeSid(psidEveryOne);

    end;

Open in new window

0
 

Author Comment

by:ZeBriD
ID: 33509198
I've tryed to create ExplicitAccess by two ways:

BuildExplicitAccessWithName(@ExplicitAccess, lpName, GENERIC_ALL, SET_ACCESS, NO_INHERITANCE);

and

with ExplicitAccess do
begin
  grfAccessPermissions := GENERIC_ALL;
  grfAccessMode := SET_ACCESS;
  grfInheritance := NO_INHERITANCE;
  Trustee.TrusteeForm := TRUSTEE_IS_SID;
  Trustee.TrusteeType := TRUSTEE_IS_GROUP;
  Trustee.ptstrName := psidEveryone;
end;
0
 
LVL 9

Expert Comment

by:sas13
ID: 33509287
sorry, i didnt work with crypto containers.
i can expect what problem might be in "CryptSetProvParam" function, may be some parameter is invalid or something else.
try to change some parameters...
may be AhProv opened with restrictions to change security...
0
 
LVL 13

Expert Comment

by:aflarin
ID: 33509312
>>modules AccAPI.pas & AccCtrl.pas attached
>I've tried use your units. Now there is no error.

It's interesting. Those are the Delphi's unit with {$MINENUMSIZE 4} added. But as I said before there is no sense to add {$MINENUMSIZE 4} to AccAPI.
0
 
LVL 13

Expert Comment

by:aflarin
ID: 33509381
btw, It would be better to ask one question per thread
http://www.experts-exchange.com/help.jsp#hs=23&hi=23
0
 

Author Comment

by:ZeBriD
ID: 33509577
yippee
It's work. Error was in func SetSecurityDescriptorDacl(pSD, false, ptACL, false).
Second parametr needs to be 'true'.
So, what was done.

Since the user can use not only in eng windows version, user group named 'Everyone' may be called differently, such as '¿¿¿' for russian version. But the SID of the group is always the same. Thats why I get SID at first. Then, using the function LookupAccountSid I get the name of this group. And only then, with the name of group 'Everyone', I create object ExplicitAccess and set these new rights to crypto-container.
I attached the working code below.
Thanks everyone.
procedure TInetSession.SetProvPermiss(AhProv: HCRYPTPROV);
const
  SECURITY_WORLD_SID_AUTHORITY: SID_IDENTIFIER_AUTHORITY = (Value: (0, 0, 0, 0, 0, 1));
  SECURITY_WORLD_RID = $0;

var
  ExplicitAccess: EXPLICIT_ACCESS;
  psidEveryOne: PSID;
  pSD: PSECURITY_DESCRIPTOR;
  ptACL: PACL;
  ErrNo: Cardinal;
  lpName,lpDomain : PAnsiChar;
  cbName,cbDomain : Cardinal;
  peUse : Cardinal;
begin
  psidEveryOne := nil;
  pSD := nil;
  ptACL := nil;
  cbName := 0;
  cbDomain := 0;

  try
    win32check(AllocateAndInitializeSid(SECURITY_WORLD_SID_AUTHORITY,
      1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, psidEveryone));

    LookupAccountSid(nil, psidEveryOne, nil, cbName, nil, cbDomain, peUse);
    GetMem(lpName,cbName*SizeOf(WideChar));
    GetMem(lpDomain,cbDomain*SizeOf(WideChar));
    try
      win32check(LookupAccountSid(nil, psidEveryOne, lpName, cbName, lpDomain, cbDomain, peUse));
    finally
      FreeMem(lpName);
      FreeMem(lpDomain);
    end;

    ZeroMemory(@ExplicitAccess, SizeOf(ExplicitAccess));
    BuildExplicitAccessWithName(@ExplicitAccess, lpName, GENERIC_ALL, SET_ACCESS, NO_INHERITANCE);

    try
      ErrFunc := 'SetEntriesInAcl';
      ErrNo := SetEntriesInAcl(1, @ExplicitAccess, nil, ptACL);
      if ErrNo <> ERROR_SUCCESS then
        raise Exception.Create(Format('System Error.  Code: %u'#13#10'%s', [ErrNo, SysErrorMessage(ErrNo)]));

      try
        pSD:= Pointer(LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH));
        try
          win32check(InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION));
          win32check(SetSecurityDescriptorDacl(pSD, true, ptACL, false));
          win32check(CryptSetProvParam(AhProv, PP_KEYSET_SEC_DESCR, pSD, DACL_SECURITY_INFORMATION));
        finally
          LocalFree(Cardinal(pSD));
        end;
      finally
        LocalFree(Cardinal(ptACL));
      end;
    finally
      FreeSid(psidEveryOne);
    end;
  except
    on E: Exception do
    begin
      do something...
      Exit;
    end;
  end;
end;

Open in new window

0
 

Author Closing Comment

by:ZeBriD
ID: 33509616
Only one problem was solved by experts.
Second I solved by my self.
0

Featured Post

Shouldn't all users have the same email signature?

You wouldn't let your users design their own business cards, would you? So, why do you let them design their own email signatures? Think of the damage they could be doing to your brand reputation! Choose the easy way to manage set up and add email signatures for all users.

Join & Write a Comment

The use of stolen credentials is a hot commodity this year allowing threat actors to move laterally within the network in order to avoid breach detection.
Sometimes drives fill up and we don't know why.  If you don't understand the best way to use the tools available, you may end up being stumped as to why your drive says it's not full when you have no space left!  Here's how you can find out...
This video Micro Tutorial explains how to clone a hard drive using a commercial software product for Windows systems called Casper from Future Systems Solutions (FSS). Cloning makes an exact, complete copy of one hard disk drive (HDD) onto another d…
The viewer will learn how to successfully create a multiboot device using the SARDU utility on Windows 7. Start the SARDU utility: Change the image directory to wherever you store your ISOs, this will prevent you from having 2 copies of an ISO wit…

757 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now