?
Solved

Delphi7 SetEntriesInAcl Error 87

Posted on 2010-08-19
16
Medium Priority
?
2,071 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
15 Comments
 
LVL 13

Accepted Solution

by:
aflarin earned 1000 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
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
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 1000 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
 
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

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article shows how to use a free utility called 'Parkdale' to easily test the performance and benchmark any Hard Drive(s) installed in your computer. We also look at RAM Disks and their speed comparisons.
MS Outlook undoubtedly is the most widely used email client.Its user-friendliness, cost effectiveness, and availability with Microsoft Office Suite make it the most popular email application.  Its compatibility with Microsoft applications like Exch…
As developers, we are not limited to the functions provided by the VBA language. In addition, we can call the functions that are part of the Windows operating system. These functions are part of the Windows API (Application Programming Interface). U…
Windows 10 is mostly good. However the one thing that annoys me is how many clicks you have to do to dial a VPN connection. You have to go to settings from the start menu, (2 clicks), Network and Internet (1 click), Click VPN (another click) then fi…

755 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