[2 days left] What’s wrong with your cloud strategy? Learn why multicloud solutions matter with Nimble Storage.Register Now

x
?
Solved

Delphi7 SetEntriesInAcl Error 87

Posted on 2010-08-19
16
Medium Priority
?
2,026 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 6
  • 5
  • 4
16 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
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
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

Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Question has a verified solution.

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

Configuring Remote Assistance for use with SCCM
When asking a question in a forum or creating documentation, screenshots are vital tools that can convey a lot more information and save you and your reader a lot of time
With the advent of Windows 10, Microsoft is pushing a Get Windows 10 icon into the notification area (system tray) of qualifying computers. There are many reasons for wanting to remove this icon. This two-part Experts Exchange video Micro Tutorial s…
The Task Scheduler is a powerful tool that is built into Windows. It allows you to schedule tasks (actions) on a recurring basis, such as hourly, daily, weekly, monthly, at log on, at startup, on idle, etc. This video Micro Tutorial is a brief intro…

649 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