Setup.SecurityFunc.pas 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. unit Setup.SecurityFunc;
  2. {
  3. Inno Setup
  4. Copyright (C) 1997-2026 Jordan Russell
  5. Portions by Martijn Laan
  6. For conditions of distribution and use, see LICENSE.TXT.
  7. Functions for altering ACLs on files & registry keys
  8. }
  9. interface
  10. uses
  11. Windows, Shared.CommonFunc, Shared.Struct;
  12. function GrantPermissionOnFile(Filename: String;
  13. const Entries: TGrantPermissionEntry; const EntryCount: Integer): Boolean;
  14. function GrantPermissionOnKey(const RegView: TRegView; const RootKey: HKEY;
  15. const Subkey: String; const Entries: TGrantPermissionEntry;
  16. const EntryCount: Integer): Boolean;
  17. implementation
  18. uses
  19. SetupLdrAndSetup.Messages,
  20. Setup.InstFunc, Setup.LoggingFunc;
  21. function InternalGrantPermission(const ObjectType: DWORD; const ObjectName: String;
  22. const Entries: TGrantPermissionEntry; const EntryCount: Integer;
  23. const Inheritance: DWORD): DWORD;
  24. { Grants the specified access to the specified object. Returns ERROR_SUCCESS if
  25. successful. }
  26. type
  27. PPSID = ^PSID;
  28. PPACL = ^PACL;
  29. PTrusteeW = ^TTrusteeW;
  30. TTrusteeW = record
  31. pMultipleTrustee: PTrusteeW;
  32. MultipleTrusteeOperation: DWORD; { MULTIPLE_TRUSTEE_OPERATION }
  33. TrusteeForm: DWORD; { TRUSTEE_FORM }
  34. TrusteeType: DWORD; { TRUSTEE_TYPE }
  35. ptstrName: PWideChar;
  36. end;
  37. TExplicitAccessW = record
  38. grfAccessPermissions: DWORD;
  39. grfAccessMode: DWORD; { ACCESS_MODE }
  40. grfInheritance: DWORD;
  41. Trustee: TTrusteeW;
  42. end;
  43. PArrayOfExplicitAccessW = ^TArrayOfExplicitAccessW;
  44. TArrayOfExplicitAccessW = array[0..999999] of TExplicitAccessW;
  45. const
  46. GRANT_ACCESS = 1;
  47. TRUSTEE_IS_SID = 0;
  48. TRUSTEE_IS_UNKNOWN = 0;
  49. var
  50. AdvApiHandle: HMODULE;
  51. GetNamedSecurityInfoW: function(pObjectName: PWideChar; ObjectType: DWORD;
  52. SecurityInfo: SECURITY_INFORMATION; ppsidOwner, ppsidGroup: PPSID;
  53. ppDacl, ppSacl: PPACL; var ppSecurityDescriptor: PSECURITY_DESCRIPTOR): DWORD;
  54. stdcall;
  55. SetNamedSecurityInfoW: function(pObjectName: PWideChar; ObjectType: DWORD;
  56. SecurityInfo: SECURITY_INFORMATION; ppsidOwner, ppsidGroup: PSID;
  57. ppDacl, ppSacl: PACL): DWORD; stdcall;
  58. SetEntriesInAclW: function(cCountOfExplicitEntries: ULONG;
  59. const pListOfExplicitEntries: TExplicitAccessW; OldAcl: PACL;
  60. var NewAcl: PACL): DWORD; stdcall;
  61. SD: PSECURITY_DESCRIPTOR;
  62. Dacl, NewDacl: PACL;
  63. ExplicitAccess: PArrayOfExplicitAccessW;
  64. E: ^TGrantPermissionEntry;
  65. I: Integer;
  66. Sid: PSID;
  67. begin
  68. AdvApiHandle := GetModuleHandle(advapi32);
  69. GetNamedSecurityInfoW := GetProcAddress(AdvApiHandle, PAnsiChar('GetNamedSecurityInfoW'));
  70. SetNamedSecurityInfoW := GetProcAddress(AdvApiHandle, PAnsiChar('SetNamedSecurityInfoW'));
  71. SetEntriesInAclW := GetProcAddress(AdvApiHandle, PAnsiChar('SetEntriesInAclW'));
  72. if (@GetNamedSecurityInfoW = nil) or (@SetNamedSecurityInfoW = nil) or
  73. (@SetEntriesInAclW = nil) then begin
  74. Result := ERROR_PROC_NOT_FOUND;
  75. Exit;
  76. end;
  77. ExplicitAccess := nil;
  78. Result := GetNamedSecurityInfoW(PChar(ObjectName), ObjectType,
  79. DACL_SECURITY_INFORMATION, nil, nil, @Dacl, nil, SD);
  80. if Result <> ERROR_SUCCESS then
  81. Exit;
  82. try
  83. { Note: Dacl will be nil if GetNamedSecurityInfo is called on a FAT partition.
  84. Be careful not to dereference a nil pointer. }
  85. ExplicitAccess := AllocMem(EntryCount * SizeOf(ExplicitAccess[0]));
  86. E := @Entries;
  87. for I := 0 to EntryCount-1 do begin
  88. if not AllocateAndInitializeSid(E.Sid.Authority, E.Sid.SubAuthCount,
  89. E.Sid.SubAuth[0], E.Sid.SubAuth[1], 0, 0, 0, 0, 0, 0, Sid) then begin
  90. Result := GetLastError;
  91. if Result = ERROR_SUCCESS then { just in case... }
  92. Result := ERROR_INVALID_PARAMETER;
  93. Exit;
  94. end;
  95. ExplicitAccess[I].grfAccessPermissions := E.AccessMask;
  96. ExplicitAccess[I].grfAccessMode := GRANT_ACCESS;
  97. ExplicitAccess[I].grfInheritance := Inheritance;
  98. ExplicitAccess[I].Trustee.TrusteeForm := TRUSTEE_IS_SID;
  99. ExplicitAccess[I].Trustee.TrusteeType := TRUSTEE_IS_UNKNOWN;
  100. PSID(ExplicitAccess[I].Trustee.ptstrName) := Sid;
  101. Inc(E);
  102. end;
  103. Result := SetEntriesInAclW(ULONG(EntryCount), ExplicitAccess[0], Dacl, NewDacl);
  104. if Result <> ERROR_SUCCESS then
  105. Exit;
  106. try
  107. Result := SetNamedSecurityInfoW(PChar(ObjectName), ObjectType,
  108. DACL_SECURITY_INFORMATION, nil, nil, NewDacl, nil);
  109. finally
  110. LocalFree(HLOCAL(NewDacl));
  111. end;
  112. finally
  113. if Assigned(ExplicitAccess) then begin
  114. for I := EntryCount-1 downto 0 do begin
  115. Sid := PSID(ExplicitAccess[I].Trustee.ptstrName);
  116. if Assigned(Sid) then
  117. FreeSid(Sid);
  118. end;
  119. FreeMem(ExplicitAccess);
  120. end;
  121. LocalFree(HLOCAL(SD));
  122. end;
  123. end;
  124. const
  125. OBJECT_INHERIT_ACE = 1;
  126. CONTAINER_INHERIT_ACE = 2;
  127. function GrantPermissionOnFile(Filename: String;
  128. const Entries: TGrantPermissionEntry; const EntryCount: Integer): Boolean;
  129. { Grants the specified access to the specified file/directory. Returns True if
  130. successful. On failure, the thread's last error code is set. }
  131. const
  132. SE_FILE_OBJECT = 1;
  133. var
  134. Attr, Inheritance, ErrorCode: DWORD;
  135. begin
  136. Attr := GetFileAttributes(PChar(Filename));
  137. if Attr = INVALID_FILE_ATTRIBUTES then begin
  138. Result := False;
  139. Exit;
  140. end;
  141. if Attr and FILE_ATTRIBUTE_DIRECTORY <> 0 then
  142. Inheritance := OBJECT_INHERIT_ACE or CONTAINER_INHERIT_ACE
  143. else
  144. Inheritance := 0;
  145. ErrorCode := InternalGrantPermission(SE_FILE_OBJECT, Filename, Entries,
  146. EntryCount, Inheritance);
  147. SetLastError(ErrorCode);
  148. Result := (ErrorCode = ERROR_SUCCESS);
  149. end;
  150. function GrantPermissionOnKey(const RegView: TRegView; const RootKey: HKEY;
  151. const Subkey: String; const Entries: TGrantPermissionEntry;
  152. const EntryCount: Integer): Boolean;
  153. { Grants the specified access to the specified registry key. Returns True if
  154. successful. On failure, the thread's last error code is set. }
  155. const
  156. SE_REGISTRY_KEY = 4;
  157. SE_REGISTRY_WOW64_32KEY = 12;
  158. SE_REGISTRY_WOW64_64KEY = 13;
  159. begin
  160. var ObjType: DWORD := SE_REGISTRY_KEY;
  161. case RegView of
  162. {$IFDEF WIN64}
  163. rv32Bit: ObjType := SE_REGISTRY_WOW64_32KEY;
  164. {$ELSE}
  165. rv64Bit: ObjType := SE_REGISTRY_WOW64_64KEY;
  166. {$ENDIF}
  167. end;
  168. var ObjName: String;
  169. case RegRootKeyToUInt32(RootKey) of
  170. UInt32(HKEY_CLASSES_ROOT): ObjName := 'CLASSES_ROOT';
  171. UInt32(HKEY_CURRENT_USER): ObjName := 'CURRENT_USER';
  172. UInt32(HKEY_LOCAL_MACHINE): ObjName := 'MACHINE';
  173. UInt32(HKEY_USERS): ObjName := 'USERS';
  174. else
  175. { Other root keys are not supported by Get/SetNamedSecurityInfo }
  176. SetLastError(ERROR_INVALID_PARAMETER);
  177. Result := False;
  178. Exit;
  179. end;
  180. ObjName := ObjName + '\' + Subkey;
  181. const ErrorCode = InternalGrantPermission(ObjType, ObjName,
  182. Entries, EntryCount, CONTAINER_INHERIT_ACE);
  183. SetLastError(ErrorCode);
  184. Result := (ErrorCode = ERROR_SUCCESS);
  185. end;
  186. end.