Delphi7 SetEntriesInAcl Error 87

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
ZeBriDAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

aflarinCommented:
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

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
sas13Commented:
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
ZeBriDAuthor Commented:
>{$MINENUMSIZE 4} <---------------------------------- this line
Already tried. Still not working.
0
Rowby Goren Makes an Impact on Screen and Online

Learn about longtime user Rowby Goren and his great contributions to the site. We explore his method for posing questions that are likely to yield a solution, and take a look at how his career transformed from a Hollywood writer to a website entrepreneur.

aflarinCommented:
>> Already tried. Still not working.

I've checked it under D7.  It works.

Make sure that SizeOf(ExplicitAccess) is 32.
0
sas13Commented:
modules AccAPI.pas & AccCtrl.pas attached.
they worked in Delphi 7
AclAPI.zip
0
aflarinCommented:
>> 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
ZeBriDAuthor Commented:
>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
sas13Commented:
where is function "SetNamedSecurityInfo" which set security object  ptACL after call "SetEntriesInAcl"?

see may example above (function "TakeOwnership").
0
ZeBriDAuthor Commented:
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
ZeBriDAuthor Commented:
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
sas13Commented:
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
aflarinCommented:
>>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
aflarinCommented:
btw, It would be better to ask one question per thread
http://www.experts-exchange.com/help.jsp#hs=23&hi=23
0
ZeBriDAuthor Commented:
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
ZeBriDAuthor Commented:
Only one problem was solved by experts.
Second I solved by my self.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Delphi

From novice to tech pro — start learning today.