{ License Agreement This content is subject to the Mozilla Public License Version 1.1 (the "License"); You may not use this plugin except in compliance with the License. You may obtain a copy of the License at http://www.mozilla.org/MPL. Alternatively, you may redistribute this library, use and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. You may obtain a copy of the LGPL at www.gnu.org/copyleft. Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License. The original code is LSASecurityControl.pas, released April 16, 2007. The initial developer of the original code is Rainer Döpke (Formerly: Rainer Budde) (https://www.speed-soft.de). SimpleSC - NSIS Service Control Plugin is written, published and maintained by Rainer Döpke (rainer@speed-soft.de). } unit LSASecurityControl; interface uses Winapi.Windows; function GrantPrivilege(AccountName: String; PrivilegeName: String): Integer; function RemovePrivilege(AccountName: String; PrivilegeName: String): Integer; function EnablePrivilege(PrivilegeName: String): Integer; function DisablePrivilege(PrivilegeName: String): Integer; implementation type LSA_HANDLE = Pointer; TLSAHandle = LSA_HANDLE; LSA_UNICODE_STRING = record Length: Word; MaximumLength: Word; Buffer: PWideChar; end; TLSAUnicodeString = LSA_UNICODE_STRING; PLSAUnicodeString = ^TLSAUnicodeString; LSA_OBJECT_ATTRIBUTES = record Length: ULONG; RootDirectory: THandle; ObjectName: PLSAUnicodeString; Attributes: ULONG; SecurityDescriptor: Pointer; SecurityQualityOfService: Pointer; end; TLsaObjectAttributes = LSA_OBJECT_ATTRIBUTES; PLsaObjectAttributes = ^TLsaObjectAttributes; function LsaOpenPolicy(SystemName: PLSAUnicodeString; var ObjectAttributes: TLsaObjectAttributes; DesiredAccess: ACCESS_MASK; var PolicyHandle: LSA_HANDLE): DWORD; stdcall; external 'advapi32.dll'; function LsaAddAccountRights(PolicyHandle: LSA_HANDLE; AccountSid: PSID; UserRights: PLSAUnicodeString; CountOfRights: ULONG): DWORD; stdcall; external 'advapi32.dll'; function LsaRemoveAccountRights(PolicyHandle: LSA_HANDLE; AccountSid: PSID; AllRights: Boolean; UserRights: PLSAUnicodeString; CountOfRights: ULONG): DWORD; stdcall; external 'advapi32.dll'; function LsaClose(ObjectHandle: LSA_HANDLE): DWORD; stdcall; external 'advapi32.dll'; function GetAccountSid(const AccountName: String; var Sid: PSID): Integer; var DomainSize: LongWord; SidSize: LongWord; Domain: String; Use: SID_NAME_USE; begin Result := 0; SidSize := 0; DomainSize := 0; if not LookupAccountName(nil, PChar(AccountName), nil, SidSize, nil, DomainSize, Use) and (GetLastError = ERROR_INSUFFICIENT_BUFFER) then begin SetLength(Domain, DomainSize); Sid := AllocMem(SidSize); if not LookupAccountName(nil, PChar(AccountName), Sid, SidSize, PChar(Domain), DomainSize, Use) then begin Result := GetLastError; FreeMem(Sid); Sid := nil; end; end else Result := GetLastError; end; function GrantPrivilege(AccountName: String; PrivilegeName: String): Integer; const UNICODE_NULL = WCHAR(0); POLICY_CREATE_ACCOUNT = $00000010; POLICY_LOOKUP_NAMES = $00000800; var SID: PSID; PolicyHandle: TLSAHandle; LSAPrivilegeName: TLSAUnicodeString; LSAObjectAttributes: TLsaObjectAttributes; pwszPrivilegeName: PWideChar; PrivilegeNameLength: Cardinal; Status: DWORD; begin Result := 0; GetMem(pwszPrivilegeName, Length(PrivilegeName) * SizeOf(WideChar) + 1); StringToWideChar(PrivilegeName, pwszPrivilegeName, Length(PrivilegeName) * SizeOf(WideChar) + 1); ZeroMemory(@LSAObjectAttributes, SizeOf(TLsaObjectAttributes)); PrivilegeNameLength := Length(pwszPrivilegeName); if PrivilegeNameLength > 0 then begin Result := GetAccountSid(AccountName, SID); if Result = 0 then begin LSAPrivilegeName.Length := PrivilegeNameLength * SizeOf(WideChar); LSAPrivilegeName.MaximumLength := LSAPrivilegeName.Length + SizeOf(UNICODE_NULL); LSAPrivilegeName.Buffer := pwszPrivilegeName; Status := LsaOpenPolicy(nil, LSAObjectAttributes, POLICY_LOOKUP_NAMES or POLICY_CREATE_ACCOUNT, PolicyHandle); try if Status = 0 then Result := LsaAddAccountRights(PolicyHandle, Sid, @LSAPrivilegeName, 1) else Result := Status; finally LsaClose(PolicyHandle); end; end; end; FreeMem(pwszPrivilegeName); end; function RemovePrivilege(AccountName: String; PrivilegeName: String): Integer; const UNICODE_NULL = WCHAR(0); POLICY_CREATE_ACCOUNT = $00000010; POLICY_LOOKUP_NAMES = $00000800; var SID: PSID; PolicyHandle: TLSAHandle; LSAPrivilegeName: TLSAUnicodeString; LSAObjectAttributes: TLsaObjectAttributes; pwszPrivilegeName: PWideChar; PrivilegeNameLength: Cardinal; Status: DWORD; begin Result := 0; GetMem(pwszPrivilegeName, Length(PrivilegeName) * SizeOf(WideChar) + 1); StringToWideChar(PrivilegeName, pwszPrivilegeName, Length(PrivilegeName) * SizeOf(WideChar) + 1); ZeroMemory(@LSAObjectAttributes, SizeOf(TLsaObjectAttributes)); PrivilegeNameLength := Length(pwszPrivilegeName); if PrivilegeNameLength > 0 then begin Result := GetAccountSid(AccountName, SID); if Result = 0 then begin LSAPrivilegeName.Length := PrivilegeNameLength * SizeOf(WideChar); LSAPrivilegeName.MaximumLength := LSAPrivilegeName.Length + SizeOf(UNICODE_NULL); LSAPrivilegeName.Buffer := pwszPrivilegeName; Status := LsaOpenPolicy(nil, LSAObjectAttributes, POLICY_LOOKUP_NAMES or POLICY_CREATE_ACCOUNT, PolicyHandle); try if Status = 0 then Result := LsaRemoveAccountRights(PolicyHandle, Sid, False, @LSAPrivilegeName, 1) else Result := Status; finally LsaClose(PolicyHandle); end; end; end; FreeMem(pwszPrivilegeName); end; function EnablePrivilege(PrivilegeName: String): Integer; var TokenHandle: THandle; TokenPrivileges: TOKEN_PRIVILEGES; PreviousState: TOKEN_PRIVILEGES; ReturnLength: Cardinal; begin Result := 0; if OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, TokenHandle) then begin try if LookupPrivilegeValue(nil, PWideChar(PrivilegeName), TokenPrivileges.Privileges[0].Luid) then begin TokenPrivileges.PrivilegeCount := 1; TokenPrivileges.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED; if not AdjustTokenPrivileges(TokenHandle, False, TokenPrivileges, SizeOf(TokenPrivileges), PreviousState, ReturnLength) then Result := System.GetLastError; end else Result := System.GetLastError; finally CloseHandle(TokenHandle); end; end else Result := System.GetLastError; end; function DisablePrivilege(PrivilegeName: String): Integer; var TokenHandle: THandle; TokenPrivileges: TOKEN_PRIVILEGES; PreviousState: TOKEN_PRIVILEGES; ReturnLength: Cardinal; begin Result := 0; if OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, TokenHandle) then begin try if LookupPrivilegeValue(nil, PWideChar(PrivilegeName), TokenPrivileges.Privileges[0].Luid) then begin TokenPrivileges.PrivilegeCount := 1; TokenPrivileges.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED; if not AdjustTokenPrivileges(TokenHandle, False, TokenPrivileges, SizeOf(TokenPrivileges), PreviousState, ReturnLength) then Result := System.GetLastError; end else Result := System.GetLastError; finally CloseHandle(TokenHandle); end; end else Result := System.GetLastError; end; end.