diff --git a/desktop/tauri/src-tauri/tauri.conf.json5 b/desktop/tauri/src-tauri/tauri.conf.json5 index 00a9cced..52b2f25a 100644 --- a/desktop/tauri/src-tauri/tauri.conf.json5 +++ b/desktop/tauri/src-tauri/tauri.conf.json5 @@ -118,7 +118,7 @@ "windows": { "nsis": { "installMode": "perMachine", - "installerHooks": "templates/nsis_install_hooks.nsh", + "installerHooks": "templates/nsis/install_hooks.nsh", "installerIcon": "../../../assets/data/icons/pm_light.ico" }, "wix": { diff --git a/desktop/tauri/src-tauri/templates/NSIS_Simple_Service_Plugin_Unicode_1.30/License.txt b/desktop/tauri/src-tauri/templates/NSIS_Simple_Service_Plugin_Unicode_1.30/License.txt new file mode 100644 index 00000000..71e0f2a0 --- /dev/null +++ b/desktop/tauri/src-tauri/templates/NSIS_Simple_Service_Plugin_Unicode_1.30/License.txt @@ -0,0 +1,27 @@ +SimpleSC - NSIS Service Control Plugin - License Agreement + +This plugin 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. + +Copyright + +Portions of this software are Copyright (C) 2001 - Peter Windridge, 2003 by +Bernhard Mayer, Fixed and formatted by Brett Dever http://editor.nfscheats.com/ + +The original code is ServiceControl.pas, released April 16, 2007. + +The initial developer of the original code is Rainer Budde (http://www.speed-soft.de). + +SimpleSC - NSIS Service Control Plugin is written, published and maintaned by +Rainer Budde (rainer@speed-soft.de). \ No newline at end of file diff --git a/desktop/tauri/src-tauri/templates/NSIS_Simple_Service_Plugin_Unicode_1.30/Readme.txt b/desktop/tauri/src-tauri/templates/NSIS_Simple_Service_Plugin_Unicode_1.30/Readme.txt new file mode 100644 index 00000000..1854869a --- /dev/null +++ b/desktop/tauri/src-tauri/templates/NSIS_Simple_Service_Plugin_Unicode_1.30/Readme.txt @@ -0,0 +1,335 @@ +NSIS Simple Service Plugin + +This plugin contains basic service functions like start, stop the +service or checking the service status. It also contains advanced +service functions for example setting the service description, changed +the logon account, granting or removing the service logon privilege. + + + + +== Short Reference == + + +SimpleSC::InstallService [name_of_service] [display_name] [service_type] [start_type] [binary_path] [dependencies] [account] [password] +SimpleSC::RemoveService [name_of_service] + +SimpleSC::StartService [name_of_service] [arguments] [timeout] +SimpleSC::StopService [name_of_service] [wait_for_file_release] [timeout] +SimpleSC::PauseService [name_of_service] [timeout] +SimpleSC::ContinueService [name_of_service] [timeout] +SimpleSC::RestartService [name_of_service] [arguments] [timeout] +SimpleSC::ExistsService [name_of_service] + +SimpleSC::GetServiceDisplayName [name_of_service] +SimpleSC::GetServiceName [display_name] +SimpleSC::GetServiceStatus [name_of_service] +SimpleSC::GetServiceDescription [name_of_service] +SimpleSC::GetServiceStartType [name_of_service] +SimpleSC::GetServiceBinaryPath [name_of_service] +SimpleSC::GetServiceLogon [name_of_service] +SimpleSC::GetServiceFailure [name_of_service] +SimpleSC::GetServiceFailureFlag [name_of_service] +SimpleSC::GetServiceDelayedAutoStartInfo [name_of_service] + +SimpleSC::SetServiceDescription [name_of_service] [service_description] +SimpleSC::SetServiceStartType [name_of_service] [start_type] +SimpleSC::SetServiceBinaryPath [name_of_service] [binary_path] +SimpleSC::SetServiceLogon [name_of_service] [account] [password] +SimpleSC::SetServiceFailure [name_of_service] [reset_period] [reboot_message] [command] [action_type_1] [action_delay_1] [action_type_2] [action_delay_2] [action_type_3] [action_delay_3] +SimpleSC::SetServiceFailureFlag [name_of_service] [failure_actions_on_non_crash_failures] +SimpleSC::SetServiceDelayedAutoStartInfo [name_of_service] [delayed_autostart] + +SimpleSC::GrantServiceLogonPrivilege [account] +SimpleSC::RemoveServiceLogonPrivilege [account] + +SimpleSC::ServiceIsPaused [name_of_service] +SimpleSC::ServiceIsRunning [name_of_service] +SimpleSC::ServiceIsStopped [name_of_service] + +SimpleSC::GetErrorMessage [error_code] + + +Parameters: + +name_of_service - The name of the service used for Start/Stop commands and all further commands + +display_name - The name as shown in the service control manager applet in system control + +service_type - One of the following codes + 1 - SERVICE_KERNEL_DRIVER - Driver service. + 2 - SERVICE_FILE_SYSTEM_DRIVER - File system driver service. + 16 - SERVICE_WIN32_OWN_PROCESS - Service that runs in its own process. (Should be used in most cases) + 32 - SERVICE_WIN32_SHARE_PROCESS - Service that shares a process with one or more other services. + 256 - SERVICE_INTERACTIVE_PROCESS - The service can interact with the desktop. + Note: If you specify either SERVICE_WIN32_OWN_PROCESS or SERVICE_WIN32_SHARE_PROCESS, + and the service is running in the context of the LocalSystem account, + you can also specify this value. + Example: SERVICE_WIN32_OWN_PROCESS or SERVICE_INTERACTIVE_PROCESS - (16 or 256) = 272 + Note: Services cannot directly interact with a user as of Windows Vista. + Therefore, this technique should not be used in new code. + See for more information: http://msdn2.microsoft.com/en-us/library/ms683502(VS.85).aspx + +start_type - one of the following codes + 0 - SERVICE_BOOT_START - Driver boot stage start + 1 - SERVICE_SYSTEM_START - Driver scm stage start + 2 - SERVICE_AUTO_START - Service auto start (Should be used in most cases) + 3 - SERVICE_DEMAND_START - Driver/service manual start + 4 - SERVICE_DISABLED - Driver/service disabled + +service_status - one of the following codes + 1 - SERVICE_STOPPED + 2 - SERVICE_START_PENDING + 3 - SERVICE_STOP_PENDING + 4 - SERVICE_RUNNING + 5 - SERVICE_CONTINUE_PENDING + 6 - SERVICE_PAUSE_PENDING + 7 - SERVICE_PAUSED + +binary_path - The path to the binary including all necessary parameters + +dependencies - Needed services, controls which services have to be started before this one; use the forward slash "/" to add more more than one service + +account - The username/account which should be used + +password - Password of the aforementioned account to be able to logon as a service + Note: If you do not specify account/password, the local system account will be used to run the service + +arguments - Arguments passed to the service main function. + Note: Driver services do not receive these arguments. + +reset_period - The time after which to reset the failure count to zero if there are no failures, in seconds. Specify 0 (INFINITE) to indicate that this value should never be reset + +reboot_message - The message to be broadcast to server users before rebooting + +command - The command line of the process to execute in response to the SC_ACTION_RUN_COMMAND service controller action. This process runs under the same account as the service + +timeout - Timeout in seconds of the function + +action_type_x - one of the following codes for the action to be performed + 0 - SC_ACTION_NONE - No action + 1 - SC_ACTION_RESTART - Restart the service + 2 - SC_ACTION_REBOOT - Reboot the computer (Note: The service user must have the SE_SHUTDOWN_NAME privilege) + 3 - SC_ACTION_RUN_COMMAND - Run a command + +action_delay_x - The time to wait before performing the specified action, in milliseconds + +failure_actions_on_non_crash_failures - This setting determines when failure actions are to be executed + 0 - The failure actions executed only if the service terminates without reporting a status of SERVICE_STOPPED + 1 - The failure actions executed if the status of a service is SERVICE_STOPPED but the exit code of the service is not 0 + +delayed_autostart - The delayed auto-start setting of an auto-start service + 0 - The service will be started during system boot. + 1 - The service will be started after other auto-start services are started plus a short delay + +error_code - Error code of a function + +service_description - The description as shown in the service control manager applet in system control + +wait_for_file_release - Wait for file release after the service is stopped. This is useful if the binary file will be overwritten after stopping the service. + 0 - NO_WAIT - No wait for file release + 1 - WAIT - Wait for file release + Note: If SERVICE_WIN32_OWN_PROCESS is used this option should be set to WAIT. + If SERVICE_WIN32_SHARE_PROCESS is used this option should only be set to WAIT if the last service + in the process is stopped. + + + + +== The Sample Script == + + +; Install a service - ServiceType own process - StartType automatic - NoDependencies - Logon as System Account + SimpleSC::InstallService "MyService" "My Service Display Name" "16" "2" "C:\MyPath\MyService.exe" "" "" "" + Pop $0 ; returns an errorcode (<>0) otherwise success (0) + +; Install a service - ServiceType interact with desktop - StartType automatic - Dependencies on "Windows Time Service" (w32time) and "WWW Publishing Service" (w3svc) - Logon as System Account + SimpleSC::InstallService "MyService" "My Service Display Name" "272" "2" "C:\MyPath\MyService.exe" "w32time/w3svc" "" "" + Pop $0 ; returns an errorcode (<>0) otherwise success (0) + +; Remove a service + SimpleSC::RemoveService "MyService" + Pop $0 ; returns an errorcode (<>0) otherwise success (0) + +; Start a service + SimpleSC::StartService "MyService" "" 30 + Pop $0 ; returns an errorcode (<>0) otherwise success (0) + +; Start a service with two arguments "/param1=true" "/param2=1" + SimpleSC::StartService "MyService" "/param1=true /param2=1" 30 + Pop $0 ; returns an errorcode (<>0) otherwise success (0) + +; Start a service with two arguments "-p param1" "-param2" + SimpleSC::StartService "MyService" '"-p param1" -param2' 30 + Pop $0 ; returns an errorcode (<>0) otherwise success (0) + +; Stop a service and waits for file release + SimpleSC::StopService "MyService" 1 30 + Pop $0 ; returns an errorcode (<>0) otherwise success (0) + +; Stops two services and waits for file release after the last service is stopped + SimpleSC::StopService "MyService1" 0 30 + Pop $0 ; returns an errorcode (<>0) otherwise success (0) + SimpleSC::StopService "MyService2" 1 30 + Pop $0 ; returns an errorcode (<>0) otherwise success (0) + +; Pause a service + SimpleSC::PauseService "MyService" 30 + Pop $0 ; returns an errorcode (<>0) otherwise success (0) + +; Continue a service + SimpleSC::ContinueService "MyService" 30 + Pop $0 ; returns an errorcode (<>0) otherwise success (0) + +; Restart a service + SimpleSC::RestartService "MyService" "" 30 + Pop $0 ; returns an errorcode (<>0) otherwise success (0) + +; Restart a service with two arguments "/param1=true" "/param2=1" + SimpleSC::RestartService "MyService" "/param1=true /param2=1" 30 + Pop $0 ; returns an errorcode (<>0) otherwise success (0) + +; Start a service with two arguments "-p param1" "-param2" + SimpleSC::RestartService "MyService" '"-p param1" -param2' 30 + Pop $0 ; returns an errorcode (<>0) otherwise success (0) + +; Check if the service exists + SimpleSC::ExistsService "MyService" + Pop $0 ; returns an errorcode if the service doesn´t exists (<>0)/service exists (0) + +; Get the displayname of a service + SimpleSC::GetServiceDisplayName "MyService" + Pop $0 ; returns an errorcode (<>0) otherwise success (0) + Pop $1 ; returns the displayname of the service + +; Get the servicename of a service by the displayname + SimpleSC::GetServiceName "MyService" + Pop $0 ; returns an errorcode (<>0) otherwise success (0) + Pop $1 ; returns the servicename of the service + +; Get the current status of a service + SimpleSC::GetServiceStatus "MyService" + Pop $0 ; returns an errorcode (<>0) otherwise success (0) + Pop $1 ; return the status of the service (See "service_status" in the parameters) + +; Get the description of a service + SimpleSC::GetServiceDescription "MyService" + Pop $0 ; returns an errorcode (<>0) otherwise success (0) + Pop $1 ; returns the description of the service + +; Get the start type of the service + SimpleSC::GetServiceStartType "MyService" + Pop $0 ; returns an errorcode (<>0) otherwise success (0) + Pop $1 ; returns the start type of the service (see "start_type" in the parameters) + +; Get the binary path of a service + SimpleSC::GetServiceBinaryPath "MyService" + Pop $0 ; returns an errorcode (<>0) otherwise success (0) + Pop $1 ; returns the binary path of the service + +; Get the logon user of the service + SimpleSC::GetServiceLogon "MyService" + Pop $0 ; returns an errorcode (<>0) otherwise success (0) + Pop $1 ; returns the logon username of the service + +; Get the failure configuration of a service + SimpleSC::GetServiceFailure "MyService" + Pop $0 ; returns an errorcode (<>0) otherwise success (0) + Pop $1 ; returns the reset period + Pop $2 ; returns the reboot message + Pop $3 ; returns the command + Pop $4 ; returns the first action (See "action_type_x" in the parameters) + Pop $5 ; returns the first action delay + Pop $6 ; returns the second action (See "action_type_x" in the parameters) + Pop $7 ; returns the second action delay + Pop $8 ; returns the third action (See "action_type_x" in the parameters) + Pop $9 ; returns the third action delay + +; Get the failure flag configuration of a service + SimpleSC::GetServiceFailureFlag "MyService" + Pop $0 ; returns an errorcode (<>0) otherwise success (0) + Pop $1 ; returns the service flag + +; Get the delayed auto-start configuration of a service + SimpleSC::GetServiceDelayedAutoStartInfo "MyService" + Pop $0 ; returns an errorcode (<>0) otherwise success (0) + Pop $1 ; returns the delayed auto-start configuration + +; Set the description of a service + SimpleSC::SetServiceDescription "MyService" "Sample Description" + Pop $0 ; returns an errorcode (<>0) otherwise success (0) + +; Set the starttype to automatic of a service + SimpleSC::SetServiceStartType "MyService" "2" + Pop $0 ; returns an errorcode (<>0) otherwise success (0) + +; Sets the service binary path + SimpleSC::SetServiceBinaryPath "MyService" "C:\MySoftware\MyService.exe" + Pop $0 ; returns an errorcode (<>0) otherwise success (0) + +; Sets the service logon to a user and grant the user the "SeServiceLogonPrivilege" + SimpleSC::SetServiceLogon "MyService" "MyServiceUser" "MyServiceUserPassword" + Pop $0 ; returns an errorcode (<>0) otherwise success (0) + IntCmp $0 0 +1 Done Done ; If successful grant the service logon privilege to "MyServiceUser" + ; Note: Every serviceuser must have the ServiceLogonPrivilege to start the service + SimpleSC::GrantServiceLogonPrivilege "MyServiceUser" + Pop $0 ; returns an errorcode (<>0) otherwise success (0) + Done: + +; Sets the service failure configuration - First action: Restart the service after one minute - Second action: Reboot the computer after five minutes + SimpleSC::SetServiceFailure "MyService" "0" "" "" "1" "60000" "2" "300000" "0" "0" + Pop $0 ; returns an errorcode (<>0) otherwise success (0) + +; Sets the failure flag configuration of a service + SimpleSC::SetServiceFailureFlag "MyService" "1" + Pop $0 ; returns an errorcode (<>0) otherwise success (0) + +; Sets the delayed auto-start configuration of a service + SimpleSC::SetServiceDelayedAutoStartInfo "MyService" "1" + Pop $0 ; returns an errorcode (<>0) otherwise success (0) + +; Remove the "SeServiceLogonPrivilege" from a user + SimpleSC::RemoveServiceLogonPrivilege "MyServiceUser" + Pop $0 ; returns an errorcode (<>0) otherwise success (0) + +; Check if the service is paused + SimpleSC::ServiceIsPaused "MyService" + Pop $0 ; returns an errorcode (<>0) otherwise success (0) + Pop $1 ; returns 1 (service is paused) - returns 0 (service is not paused) + +; Check if the service is running + SimpleSC::ServiceIsRunning "MyService" + Pop $0 ; returns an errorcode (<>0) otherwise success (0) + Pop $1 ; returns 1 (service is running) - returns 0 (service is not running) + +; Check if the service is stopped + SimpleSC::ServiceIsStopped "MyService" + Pop $0 ; returns an errorcode (<>0) otherwise success (0) + Pop $1 ; returns 1 (service is stopped) - returns 0 (service is not stopped) + +; Show the error message if a function fails + SimpleSC::StopService "MyService" 1 30 + Pop $0 ; returns an errorcode (<>0) otherwise success (0) + IntCmp $0 0 Done +1 +1 + Push $0 + SimpleSC::GetErrorMessage + Pop $0 + MessageBox MB_OK|MB_ICONSTOP "Stopping fails - Reason: $0" + Done: + + + + +== Important Notes == +- The function "SetServiceLogon" only works if the servicetype is + "SERVICE_WIN32_OWN_PROCESS". +- The functions "GetServiceDescription", "SetServiceDescription", "GetServiceFailure" and + "SetServiceFailure" are only available on systems higher than Windows NT. +- The function "GetServiceFailureFlag", "SetServiceFailureFlag", "GetServiceDelayedAutoStartInfo" and + "SetServiceDelayedAutoStartInfo" are only available on systems higher than Windows 2003. +- If you change the logon of an service to a new user you have to grant him + the Service Logon Privilege. Otherwise the service cannot be started by + the user you have assigned. +- The functions StartService, StopService, PauseService and ContinueService uses + a timeout of 30 seconds. This means the function must be executed within 30 seconds, + otherwise the functions will return an error. \ No newline at end of file diff --git a/desktop/tauri/src-tauri/templates/NSIS_Simple_Service_Plugin_Unicode_1.30/SimpleSC.dll b/desktop/tauri/src-tauri/templates/NSIS_Simple_Service_Plugin_Unicode_1.30/SimpleSC.dll new file mode 100644 index 00000000..edf0291a Binary files /dev/null and b/desktop/tauri/src-tauri/templates/NSIS_Simple_Service_Plugin_Unicode_1.30/SimpleSC.dll differ diff --git a/desktop/tauri/src-tauri/templates/NSIS_Simple_Service_Plugin_Unicode_1.30/Source/LSASecurityControl.pas b/desktop/tauri/src-tauri/templates/NSIS_Simple_Service_Plugin_Unicode_1.30/Source/LSASecurityControl.pas new file mode 100644 index 00000000..f005d878 --- /dev/null +++ b/desktop/tauri/src-tauri/templates/NSIS_Simple_Service_Plugin_Unicode_1.30/Source/LSASecurityControl.pas @@ -0,0 +1,259 @@ +{ +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. diff --git a/desktop/tauri/src-tauri/templates/NSIS_Simple_Service_Plugin_Unicode_1.30/Source/NSIS Plugins.groupproj b/desktop/tauri/src-tauri/templates/NSIS_Simple_Service_Plugin_Unicode_1.30/Source/NSIS Plugins.groupproj new file mode 100644 index 00000000..7cc69ccb --- /dev/null +++ b/desktop/tauri/src-tauri/templates/NSIS_Simple_Service_Plugin_Unicode_1.30/Source/NSIS Plugins.groupproj @@ -0,0 +1,36 @@ + + + {0AF40426-B62C-4F43-8B49-19A70AEA0832} + + + + + + + + Default.Personality.12 + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/desktop/tauri/src-tauri/templates/NSIS_Simple_Service_Plugin_Unicode_1.30/Source/NSIS.pas b/desktop/tauri/src-tauri/templates/NSIS_Simple_Service_Plugin_Unicode_1.30/Source/NSIS.pas new file mode 100644 index 00000000..91629df9 --- /dev/null +++ b/desktop/tauri/src-tauri/templates/NSIS_Simple_Service_Plugin_Unicode_1.30/Source/NSIS.pas @@ -0,0 +1,209 @@ +{ + Original Code from + (C) 2001 - Peter Windridge + + Code in separate unit and some changes + 2003 by Bernhard Mayer + + Fixed and formatted by Brett Dever + http://editor.nfscheats.com/ + + simply include this unit in your plugin project and export + functions as needed +} + +unit nsis; + +interface + +uses + Winapi.Windows, Winapi.CommCtrl, System.SysUtils; + +type + VarConstants = ( + INST_0, // $0 + INST_1, // $1 + INST_2, // $2 + INST_3, // $3 + INST_4, // $4 + INST_5, // $5 + INST_6, // $6 + INST_7, // $7 + INST_8, // $8 + INST_9, // $9 + INST_R0, // $R0 + INST_R1, // $R1 + INST_R2, // $R2 + INST_R3, // $R3 + INST_R4, // $R4 + INST_R5, // $R5 + INST_R6, // $R6 + INST_R7, // $R7 + INST_R8, // $R8 + INST_R9, // $R9 + INST_CMDLINE, // $CMDLINE + INST_INSTDIR, // $INSTDIR + INST_OUTDIR, // $OUTDIR + INST_EXEDIR, // $EXEDIR + INST_LANG, // $LANGUAGE + __INST_LAST + ); + TVariableList = INST_0..__INST_LAST; + +type + PluginCallbackMessages = ( + NSPIM_UNLOAD, // This is the last message a plugin gets, do final cleanup + NSPIM_GUIUNLOAD // Called after .onGUIEnd + ); + TNSPIM = NSPIM_UNLOAD..NSPIM_GUIUNLOAD; + + //TPluginCallback = function (const NSPIM: Integer): Pointer; cdecl; + + TExecuteCodeSegment = function (const funct_id: Integer; const parent: HWND): Integer; stdcall; + Tvalidate_filename = procedure (const filename: PChar); stdcall; + TRegisterPluginCallback = function (const DllInstance: HMODULE; const CallbackFunction: Pointer): Integer; stdcall; + + pexec_flags_t = ^exec_flags_t; + exec_flags_t = record + autoclose: Integer; + all_user_var: Integer; + exec_error: Integer; + abort: Integer; + exec_reboot: Integer; + reboot_called: Integer; + XXX_cur_insttype: Integer; + plugin_api_version: Integer; + silent: Integer; + instdir_error: Integer; + rtl: Integer; + errlvl: Integer; + alter_reg_view: Integer; + status_update: Integer; + end; + + pextrap_t = ^extrap_t; + extrap_t = record + exec_flags: Pointer; // exec_flags_t; + exec_code_segment: TExecuteCodeSegment; // TFarProc; + validate_filename: Pointer; // Tvalidate_filename; + RegisterPluginCallback: Pointer; //TRegisterPluginCallback; + end; + + pstack_t = ^stack_t; + stack_t = record + next: pstack_t; + text: PChar; + end; + +var + g_stringsize: integer; + g_stacktop: ^pstack_t; + g_variables: PChar; + g_hwndParent: HWND; + g_hwndList: HWND; + g_hwndLogList: HWND; + g_extraparameters: pextrap_t; + +procedure Init(const hwndParent: HWND; const string_size: integer; const variables: PChar; const stacktop: pointer; const extraparameters: pointer = nil); + +function LogMessage(Msg : String): BOOL; +function Call(NSIS_func : String) : Integer; +function PopString(): string; +procedure PushString(const str: string=''); +function GetUserVariable(const varnum: TVariableList): string; +procedure SetUserVariable(const varnum: TVariableList; const value: string); +procedure NSISDialog(const text, caption: string; const buttons: integer); + +implementation + +procedure Init(const hwndParent: HWND; const string_size: integer; const variables: PChar; const stacktop: pointer; const extraparameters: pointer = nil); +begin + g_stringsize := string_size; + g_hwndParent := hwndParent; + g_stacktop := stacktop; + g_variables := variables; + g_hwndList := FindWindowEx(FindWindowEx(g_hwndParent, 0, '#32770', nil), 0,'SysListView32', nil); + g_extraparameters := extraparameters; +end; + + +function Call(NSIS_func : String) : Integer; +var + codeoffset: Integer; //The ID of nsis function +begin + Result := 0; + codeoffset := StrToIntDef(NSIS_func, 0); + if (codeoffset <> 0) and (g_extraparameters <> nil) then + begin + codeoffset := codeoffset - 1; + Result := g_extraparameters.exec_code_segment(codeoffset, g_hwndParent); + end; +end; + +function LogMessage(Msg : String): BOOL; +var + ItemCount : Integer; + item: TLVItem; +begin + Result := FAlse; + if g_hwndList = 0 then exit; + FillChar( item, sizeof(item), 0 ); + ItemCount := SendMessage(g_hwndList, LVM_GETITEMCOUNT, 0, 0); + item.iItem := ItemCount; + item.mask := LVIF_TEXT; + item.pszText := PChar(Msg); + ListView_InsertItem(g_hwndList, item); + ListView_EnsureVisible(g_hwndList, ItemCount, TRUE); +end; + +function PopString(): string; +var + th: pstack_t; +begin + if integer(g_stacktop^) <> 0 then begin + th := g_stacktop^; + Result := PChar(@th.text); + g_stacktop^ := th.next; + GlobalFree(HGLOBAL(th)); + end; +end; + +procedure PushString(const str: string=''); +var + th: pstack_t; +begin + if integer(g_stacktop) <> 0 then begin + th := pstack_t(GlobalAlloc(GPTR, SizeOf(stack_t) + g_stringsize)); + lstrcpyn(@th.text, PChar(str), g_stringsize); + th.next := g_stacktop^; + g_stacktop^ := th; + end; +end; + +function GetUserVariable(const varnum: TVariableList): string; +begin + if (integer(varnum) >= 0) and (integer(varnum) < integer(__INST_LAST)) then + Result := g_variables + integer(varnum) * g_stringsize + else + Result := ''; +end; + +procedure SetUserVariable(const varnum: TVariableList; const value: string); +begin + if (value <> '') and (integer(varnum) >= 0) and (integer(varnum) < integer(__INST_LAST)) then + lstrcpy(g_variables + integer(varnum) * g_stringsize, PChar(value)) +end; + +procedure NSISDialog(const text, caption: string; const buttons: integer); +var + hwndOwner: HWND; +begin + hwndOwner := g_hwndParent; + if not IsWindow(g_hwndParent) then hwndOwner := 0; // g_hwndParent is not valid in NSPIM_[GUI]UNLOAD + MessageBox(hwndOwner, PChar(text), PChar(caption), buttons); +end; + +begin + +end. + diff --git a/desktop/tauri/src-tauri/templates/NSIS_Simple_Service_Plugin_Unicode_1.30/Source/ServiceControl.pas b/desktop/tauri/src-tauri/templates/NSIS_Simple_Service_Plugin_Unicode_1.30/Source/ServiceControl.pas new file mode 100644 index 00000000..f36ccf3a --- /dev/null +++ b/desktop/tauri/src-tauri/templates/NSIS_Simple_Service_Plugin_Unicode_1.30/Source/ServiceControl.pas @@ -0,0 +1,1382 @@ +{ +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 ServiceControl.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 ServiceControl; + +interface + +uses + Winapi.Windows, Winapi.WinSvc, System.SysUtils, System.DateUtils; + + function InstallService(ServiceName, DisplayName: String; ServiceType: DWORD; StartType: DWORD; BinaryPathName: String; Dependencies: String; Username: String; Password: String): Integer; + function RemoveService(ServiceName: String): Integer; + function GetServiceName(DisplayName: String; var Name: String): Integer; + function GetServiceDisplayName(ServiceName: String; var Name: String): Integer; + function GetServiceStatus(ServiceName: String; var Status: DWORD): Integer; + function GetServiceBinaryPath(ServiceName: String; var BinaryPath: String): Integer; + function GetServiceStartType(ServiceName: String; var StartType: DWORD): Integer; + function GetServiceDescription(ServiceName: String; var Description: String): Integer; + function GetServiceLogon(ServiceName: String; var Username: String): Integer; + function GetServiceFailure(ServiceName: String; var ResetPeriod: DWORD; var RebootMessage: String; var Command: String; var Action1: Integer; var ActionDelay1: DWORD; var Action2: Integer; var ActionDelay2: DWORD; var Action3: Integer; var ActionDelay3: DWORD): Integer; + function GetServiceFailureFlag(ServiceName: String; var FailureActionsOnNonCrashFailures: Boolean): Integer; + function GetServiceDelayedAutoStartInfo(ServiceName: String; var DelayedAutostart: Boolean): Integer; + function SetServiceStartType(ServiceName: String; StartType: DWORD): Integer; + function SetServiceDescription(ServiceName: String; Description: String): Integer; + function SetServiceLogon(ServiceName: String; Username: String; Password: String): Integer; + function SetServiceBinaryPath(ServiceName: String; BinaryPath: String): Integer; + function SetServiceFailure(ServiceName: String; ResetPeriod: DWORD; RebootMessage: String; Command: String; Action1: Integer; ActionDelay1: DWORD; Action2: Integer; ActionDelay2: DWORD; Action3: Integer; ActionDelay3: DWORD): Integer; + function SetServiceFailureFlag(ServiceName: String; FailureActionsOnNonCrashFailures: Boolean): Integer; + function SetServiceDelayedAutoStartInfo(ServiceName: String; DelayedAutostart: Boolean): Integer; + function ServiceIsRunning(ServiceName: String; var IsRunning: Boolean): Integer; + function ServiceIsStopped(ServiceName: String; var IsStopped: Boolean): Integer; + function ServiceIsPaused(ServiceName: String; var IsPaused: Boolean): Integer; + function StartService(ServiceName: String; ServiceArguments: String; Timeout: Integer): Integer; + function StopService(ServiceName: String; WaitForFileRelease: Boolean; Timeout: Integer): Integer; + function PauseService(ServiceName: String; Timeout: Integer): Integer; + function ContinueService(ServiceName: String; Timeout: Integer): Integer; + function RestartService(ServiceName: String; ServiceArguments: String; Timeout: Integer): Integer; + function ExistsService(ServiceName: String): Integer; + function GetErrorMessage(ErrorCode: Integer): String; + function WaitForFileRelease(ServiceName: String; Timeout: Integer): Integer; + function WaitForStatus(ServiceName: String; Status: DWORD; Timeout: Integer): Integer; + +implementation + +function WaitForFileRelease(ServiceName: String; Timeout: Integer): Integer; + + function GetFilename(ServiceFileName: String): String; + var + FilePath: String; + FileName: String; + const + ParameterDelimiter = ' '; + begin + FilePath := ExtractFilePath(ServiceFileName); + + FileName := Copy(ServiceFileName, Length(FilePath) + 1, Length(ServiceFileName) - Length(FilePath)); + + if Pos(ParameterDelimiter, Filename) <> 0 then + FileName := Copy(FileName, 0, Pos(ParameterDelimiter, Filename) - Length(ParameterDelimiter)); + + Result := FilePath + FileName; + end; + +var + StatusReached: Boolean; + TimeOutReached: Boolean; + TimeoutDate: TDateTime; + ServiceResult: Integer; + ServiceFileName: String; + FileName: String; + FileHandle: Cardinal; +const + WAIT_TIMEOUT = 250; +begin + Result := 0; + + StatusReached := False; + TimeOutReached := False; + + ServiceResult := GetServiceBinaryPath(ServiceName, ServiceFileName); + + if ServiceResult = 0 then + begin + + Filename := GetFilename(ServiceFileName); + + if FileExists(FileName) then + begin + TimeoutDate := IncSecond(Now, Timeout); + + while not StatusReached and not TimeOutReached do + begin + FileHandle := CreateFile(PChar(FileName), GENERIC_READ or GENERIC_WRITE, 0, + nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); + + if FileHandle <> INVALID_HANDLE_VALUE then + begin + CloseHandle(FileHandle); + StatusReached := True; + end; + + if not StatusReached and (TimeoutDate < Now) then + begin + TimeOutReached := True; + Result := WAIT_TIMEOUT; + end; + end; + + end; + + end + else + Result := ServiceResult; + +end; + +function WaitForStatus(ServiceName: String; Status: DWORD; Timeout: Integer): Integer; +var + CurrentStatus: DWORD; + StatusResult: Integer; + StatusReached: Boolean; + TimeOutReached: Boolean; + ErrorOccured: Boolean; + TimeoutDate: TDateTime; +const + WAIT_TIMEOUT = 250; +begin + Result := 0; + + StatusReached := False; + TimeOutReached := False; + ErrorOccured := False; + + TimeoutDate := IncSecond(Now, Timeout); + + while not StatusReached and not ErrorOccured and not TimeOutReached do + begin + StatusResult := GetServiceStatus(ServiceName, CurrentStatus); + + if StatusResult = 0 then + begin + if Status = CurrentStatus then + StatusReached := True + else + Sleep(WAIT_TIMEOUT); + end + else + begin + ErrorOccured := True; + Result := StatusResult; + end; + + if not StatusReached and not ErrorOccured and (TimeoutDate < Now) then + begin + TimeOutReached := True; + Result := ERROR_SERVICE_REQUEST_TIMEOUT; + end; + end; + +end; + +function ExistsService(ServiceName: String): Integer; +var + ManagerHandle: SC_HANDLE; + ServiceHandle: SC_HANDLE; +begin + Result := 0; + + ManagerHandle := OpenSCManager('', nil, SC_MANAGER_CONNECT); + + if ManagerHandle > 0 then + begin + ServiceHandle := OpenService(ManagerHandle, PChar(ServiceName), SERVICE_QUERY_CONFIG); + + if ServiceHandle > 0 then + CloseServiceHandle(ServiceHandle) + else + Result := System.GetLastError; + + CloseServiceHandle(ManagerHandle); + end + else + Result := System.GetLastError; +end; + +function StartService(ServiceName: String; ServiceArguments: String; Timeout: Integer): Integer; +type + TArguments = Array of PChar; +var + ManagerHandle: SC_HANDLE; + ServiceHandle: SC_HANDLE; + ServiceArgVectors: TArguments; + NumServiceArgs: DWORD; +const + ArgDelimitterQuote: String = '"'; + ArgDelimitterWhiteSpace: String = ' '; + + procedure GetServiceArguments(ServiceArguments: String; var NumServiceArgs: DWORD; var ServiceArgVectors: TArguments); + var + Param: String; + Split: Boolean; + Quoted: Boolean; + CharIsDelimitter: Boolean; + begin + ServiceArgVectors := nil; + NumServiceArgs := 0; + + Quoted := False; + + while Length(ServiceArguments) > 0 do + begin + Split := False; + CharIsDelimitter := False; + + if ServiceArguments[1] = ' ' then + if not Quoted then + begin + CharIsDelimitter := True; + Split := True; + end; + + if ServiceArguments[1] = '"' then + begin + Quoted := not Quoted; + CharIsDelimitter := True; + + if not Quoted then + Split := True; + end; + + if not CharIsDelimitter then + Param := Param + ServiceArguments[1]; + + if Split or (Length(ServiceArguments) = 1) then + begin + SetLength(ServiceArgVectors, Length(ServiceArgVectors) + 1); + GetMem(ServiceArgVectors[Length(ServiceArgVectors) -1], Length(Param) * SizeOf(Char) + 1); + StrPCopy(ServiceArgVectors[Length(ServiceArgVectors) -1], Param); + + Param := ''; + + Delete(ServiceArguments, 1, 1); + ServiceArguments := Trim(ServiceArguments); + end + else + Delete(ServiceArguments, 1, 1); + + end; + + if Length(ServiceArgVectors) > 0 then + NumServiceArgs := Length(ServiceArgVectors); + end; + + procedure FreeServiceArguments(ServiceArgVectors: TArguments); + var + i: Integer; + begin + if Length(ServiceArgVectors) > 0 then + for i := 0 to Length(ServiceArgVectors) -1 do + FreeMem(ServiceArgVectors[i]); + end; + +begin + ManagerHandle := OpenSCManager('', nil, SC_MANAGER_CONNECT); + + if ManagerHandle > 0 then + begin + ServiceHandle := OpenService(ManagerHandle, PChar(ServiceName), SERVICE_START); + + if ServiceHandle > 0 then + begin + GetServiceArguments(ServiceArguments, NumServiceArgs, ServiceArgVectors); + + if Winapi.WinSvc.StartService(ServiceHandle, NumServiceArgs, ServiceArgVectors[0]) then + Result := WaitForStatus(ServiceName, SERVICE_RUNNING, Timeout) + else + Result := System.GetLastError; + + FreeServiceArguments(ServiceArgVectors); + + CloseServiceHandle(ServiceHandle); + end + else + Result := System.GetLastError; + + + CloseServiceHandle(ManagerHandle); + end + else + Result := System.GetLastError; +end; + +function StopService(ServiceName: String; WaitForFileRelease: Boolean; Timeout: Integer): Integer; +var + ManagerHandle: SC_HANDLE; + ServiceHandle: SC_HANDLE; + ServiceStatus: TServiceStatus; + Dependencies: PEnumServiceStatus; + BytesNeeded: Cardinal; + ServicesReturned: Cardinal; + ServicesEnumerated: Boolean; + EnumerationSuccess: Boolean; + i: Cardinal; +begin + Result := 0; + + BytesNeeded := 0; + ServicesReturned := 0; + + Dependencies := nil; + ServicesEnumerated := False; + + ManagerHandle := OpenSCManager('', nil, SC_MANAGER_CONNECT or SC_MANAGER_ENUMERATE_SERVICE); + + if ManagerHandle > 0 then + begin + ServiceHandle := OpenService(ManagerHandle, PChar(ServiceName), SERVICE_STOP or SERVICE_ENUMERATE_DEPENDENTS); + + if ServiceHandle > 0 then + begin + if not EnumDependentServices(ServiceHandle, SERVICE_ACTIVE, Dependencies^, 0, BytesNeeded, ServicesReturned) then + begin + ServicesEnumerated := True; + GetMem(Dependencies, BytesNeeded); + + EnumerationSuccess := EnumDependentServices(ServiceHandle, SERVICE_ACTIVE, Dependencies^, BytesNeeded, BytesNeeded, ServicesReturned); + + if EnumerationSuccess and (ServicesReturned > 0) then + begin + for i := 1 to ServicesReturned do + begin + Result := StopService(Dependencies.lpServiceName, False, Timeout); + + if Result <> 0 then + Break; + + Inc(Dependencies); + end; + end + else + Result := System.GetLastError; + end; + + if (ServicesEnumerated and (Result = 0)) or not ServicesEnumerated then + begin + if ControlService(ServiceHandle, SERVICE_CONTROL_STOP, ServiceStatus) then + Result := WaitForStatus(ServiceName, SERVICE_STOPPED, Timeout) + else + Result := System.GetLastError + end; + + CloseServiceHandle(ServiceHandle); + end + else + Result := System.GetLastError; + + CloseServiceHandle(ManagerHandle); + end + else + Result := System.GetLastError; + + if (Result = 0) and WaitForFileRelease then + Result := ServiceControl.WaitForFileRelease(ServiceName, Timeout); +end; + +function PauseService(ServiceName: String; Timeout: Integer): Integer; +var + ManagerHandle: SC_HANDLE; + ServiceHandle: SC_HANDLE; + ServiceStatus: TServiceStatus; +begin + ManagerHandle := OpenSCManager('', nil, SC_MANAGER_CONNECT); + + if ManagerHandle > 0 then + begin + ServiceHandle := OpenService(ManagerHandle, PChar(ServiceName), SERVICE_PAUSE_CONTINUE); + + if ServiceHandle > 0 then + begin + + if ControlService(ServiceHandle, SERVICE_CONTROL_PAUSE, ServiceStatus) then + Result := WaitForStatus(ServiceName, SERVICE_PAUSED, Timeout) + else + Result := System.GetLastError; + + CloseServiceHandle(ServiceHandle); + end + else + Result := System.GetLastError; + + CloseServiceHandle(ManagerHandle); + end + else + Result := System.GetLastError; +end; + +function ContinueService(ServiceName: String; Timeout: Integer): Integer; +var + ManagerHandle: SC_HANDLE; + ServiceHandle: SC_HANDLE; + ServiceStatus: TServiceStatus; +begin + ManagerHandle := OpenSCManager('', nil, SC_MANAGER_CONNECT); + + if ManagerHandle > 0 then + begin + ServiceHandle := OpenService(ManagerHandle, PChar(ServiceName), SERVICE_PAUSE_CONTINUE); + + if ServiceHandle > 0 then + begin + + if ControlService(ServiceHandle, SERVICE_CONTROL_CONTINUE, ServiceStatus) then + Result := WaitForStatus(ServiceName, SERVICE_RUNNING, Timeout) + else + Result := System.GetLastError; + + CloseServiceHandle(ServiceHandle); + end + else + Result := System.GetLastError; + + CloseServiceHandle(ManagerHandle); + end + else + Result := System.GetLastError; +end; + +function GetServiceName(DisplayName: String; var Name: String): Integer; +var + ManagerHandle: SC_HANDLE; + ServiceName: PChar; + ServiceBuffer: Cardinal; +begin + Result := 0; + + ServiceBuffer := 255; + ServiceName := StrAlloc(ServiceBuffer+1); + + ManagerHandle := OpenSCManager('', nil, SC_MANAGER_CONNECT); + + if ManagerHandle > 0 then + begin + if Winapi.WinSvc.GetServiceKeyName(ManagerHandle, PChar(DisplayName), ServiceName, ServiceBuffer) then + Name := ServiceName + else + Result := System.GetLastError; + + CloseServiceHandle(ManagerHandle); + end + else + Result := System.GetLastError; +end; + +function GetServiceDisplayName(ServiceName: String; var Name: String): Integer; +var + ManagerHandle: SC_HANDLE; + DisplayName: PChar; + ServiceBuffer: Cardinal; +begin + Result := 0; + + ServiceBuffer := 255; + DisplayName := StrAlloc(ServiceBuffer+1); + + ManagerHandle := OpenSCManager('', nil, SC_MANAGER_CONNECT); + + if ManagerHandle > 0 then + begin + if Winapi.WinSvc.GetServiceDisplayName(ManagerHandle, PChar(ServiceName), DisplayName, ServiceBuffer) then + Name := DisplayName + else + Result := System.GetLastError; + + CloseServiceHandle(ManagerHandle); + end + else + Result := System.GetLastError; +end; + +function GetServiceStatus(ServiceName: String; var Status: DWORD): Integer; +var + ManagerHandle: SC_HANDLE; + ServiceHandle: SC_HANDLE; + ServiceStatus: TServiceStatus; +begin + Result := 0; + + ManagerHandle := OpenSCManager('', nil, SC_MANAGER_CONNECT); + + if ManagerHandle > 0 then + begin + ServiceHandle := OpenService(ManagerHandle, PChar(ServiceName), SERVICE_QUERY_STATUS); + + if ServiceHandle > 0 then + begin + if QueryServiceStatus(ServiceHandle, ServiceStatus) then + Status := ServiceStatus.dwCurrentState + else + Result := System.GetLastError; + + CloseServiceHandle(ServiceHandle); + end + else + Result := System.GetLastError; + + CloseServiceHandle(ManagerHandle); + end + else + Result := System.GetLastError; +end; + +function GetServiceBinaryPath(ServiceName: String; var BinaryPath: String): Integer; +var + ManagerHandle: SC_HANDLE; + ServiceHandle: SC_HANDLE; + BytesNeeded: DWORD; + ServiceConfig: LPQUERY_SERVICE_CONFIG; +begin + Result := 0; + ServiceConfig := nil; + + ManagerHandle := OpenSCManager('', nil, SC_MANAGER_CONNECT); + + if ManagerHandle > 0 then + begin + ServiceHandle := OpenService(ManagerHandle, PChar(ServiceName), SERVICE_QUERY_CONFIG); + + if ServiceHandle > 0 then + begin + + if not QueryServiceConfig(ServiceHandle, ServiceConfig, 0, BytesNeeded) and (System.GetLastError = ERROR_INSUFFICIENT_BUFFER) then + begin + GetMem(ServiceConfig, BytesNeeded); + + if QueryServiceConfig(ServiceHandle, ServiceConfig, BytesNeeded, BytesNeeded) then + BinaryPath := ServiceConfig^.lpBinaryPathName + else + Result := System.GetLastError; + + FreeMem(ServiceConfig); + end + else + Result := System.GetLastError; + + CloseServiceHandle(ServiceHandle); + end + else + Result := System.GetLastError; + + CloseServiceHandle(ManagerHandle); + end + else + Result := System.GetLastError; +end; + +function GetServiceStartType(ServiceName: String; var StartType: DWORD): Integer; +var + ManagerHandle: SC_HANDLE; + ServiceHandle: SC_HANDLE; + BytesNeeded: DWORD; + ServiceConfig: LPQUERY_SERVICE_CONFIG; +begin + Result := 0; + ServiceConfig := nil; + + ManagerHandle := OpenSCManager('', nil, SC_MANAGER_CONNECT); + + if ManagerHandle > 0 then + begin + ServiceHandle := OpenService(ManagerHandle, PChar(ServiceName), SERVICE_QUERY_CONFIG); + + if ServiceHandle > 0 then + begin + + if not QueryServiceConfig(ServiceHandle, ServiceConfig, 0, BytesNeeded) and (System.GetLastError = ERROR_INSUFFICIENT_BUFFER) then + begin + GetMem(ServiceConfig, BytesNeeded); + + if QueryServiceConfig(ServiceHandle, ServiceConfig, BytesNeeded, BytesNeeded) then + StartType := ServiceConfig^.dwStartType + else + Result := System.GetLastError; + + FreeMem(ServiceConfig); + end + else + Result := System.GetLastError; + + CloseServiceHandle(ServiceHandle); + end + else + Result := System.GetLastError; + + CloseServiceHandle(ManagerHandle); + end + else + Result := System.GetLastError; +end; + +function GetServiceDescription(ServiceName: String; var Description: String): Integer; +var + ManagerHandle: SC_HANDLE; + ServiceHandle: SC_HANDLE; + LockHandle: SC_LOCK; + BytesNeeded: DWORD; + ServiceDescription: LPSERVICE_DESCRIPTION; +begin + Result := 0; + + ManagerHandle := OpenSCManager('', nil, SC_MANAGER_LOCK); + + if ManagerHandle > 0 then + begin + ServiceHandle := OpenService(ManagerHandle, PChar(ServiceName), SERVICE_QUERY_CONFIG); + + if ServiceHandle > 0 then + begin + LockHandle := LockServiceDatabase(ManagerHandle); + + if LockHandle <> nil then + begin + + if not QueryServiceConfig2(ServiceHandle, SERVICE_CONFIG_DESCRIPTION, nil, 0, @BytesNeeded) and (System.GetLastError = ERROR_INSUFFICIENT_BUFFER) then + begin + GetMem(ServiceDescription, BytesNeeded); + + if QueryServiceConfig2(ServiceHandle, SERVICE_CONFIG_DESCRIPTION, PByte(ServiceDescription), BytesNeeded, @BytesNeeded) then + Description := ServiceDescription.lpDescription + else + Result := System.GetLastError; + + FreeMem(ServiceDescription); + end + else + Result := System.GetLastError; + + UnlockServiceDatabase(LockHandle); + end + else + Result := System.GetLastError; + + CloseServiceHandle(ServiceHandle); + end + else + Result := System.GetLastError; + + CloseServiceHandle(ManagerHandle); + end + else + Result := System.GetLastError; +end; + +function GetServiceLogon(ServiceName: String; var Username: String): Integer; +var + ManagerHandle: SC_HANDLE; + ServiceHandle: SC_HANDLE; + BytesNeeded: DWORD; + ServiceConfig: LPQUERY_SERVICE_CONFIG; +begin + Result := 0; + ServiceConfig := nil; + + ManagerHandle := OpenSCManager('', nil, SC_MANAGER_CONNECT); + + if ManagerHandle > 0 then + begin + ServiceHandle := OpenService(ManagerHandle, PChar(ServiceName), SERVICE_QUERY_CONFIG); + + if ServiceHandle > 0 then + begin + + if not QueryServiceConfig(ServiceHandle, ServiceConfig, 0, BytesNeeded) and (System.GetLastError = ERROR_INSUFFICIENT_BUFFER) then + begin + GetMem(ServiceConfig, BytesNeeded); + + if QueryServiceConfig(ServiceHandle, ServiceConfig, BytesNeeded, BytesNeeded) then + Username := ServiceConfig^.lpServiceStartName + else + Result := System.GetLastError; + + FreeMem(ServiceConfig); + end + else + Result := System.GetLastError; + + CloseServiceHandle(ServiceHandle); + end + else + Result := System.GetLastError; + + CloseServiceHandle(ManagerHandle); + end + else + Result := System.GetLastError; +end; + +function GetServiceFailure(ServiceName: String; var ResetPeriod: DWORD; + var RebootMessage: String; var Command: String; var Action1: Integer; var ActionDelay1: DWORD; + var Action2: Integer; var ActionDelay2: DWORD; var Action3: Integer; var ActionDelay3: DWORD): Integer; +var + ManagerHandle: SC_HANDLE; + ServiceHandle: SC_HANDLE; + LockHandle: SC_LOCK; + BytesNeeded: DWORD; + ServiceFailureAction: LPSERVICE_FAILURE_ACTIONS; +begin + Result := 0; + + ManagerHandle := OpenSCManager('', nil, SC_MANAGER_LOCK); + + if ManagerHandle > 0 then + begin + ServiceHandle := OpenService(ManagerHandle, PChar(ServiceName), SERVICE_QUERY_CONFIG); + + if ServiceHandle > 0 then + begin + LockHandle := LockServiceDatabase(ManagerHandle); + + if LockHandle <> nil then + begin + + if not QueryServiceConfig2(ServiceHandle, SERVICE_CONFIG_FAILURE_ACTIONS, nil, 0, @BytesNeeded) and (System.GetLastError = ERROR_INSUFFICIENT_BUFFER) then + begin + GetMem(ServiceFailureAction, BytesNeeded); + + if QueryServiceConfig2(ServiceHandle, SERVICE_CONFIG_FAILURE_ACTIONS, PByte(ServiceFailureAction), BytesNeeded, @BytesNeeded) then + begin + ResetPeriod := ServiceFailureAction.dwResetPeriod; + RebootMessage := ServiceFailureAction.lpRebootMsg; + Command := ServiceFailureAction.lpCommand; + + if ServiceFailureAction.cActions >= 1 then + begin + Action1 := Integer(ServiceFailureAction.lpsaActions.&Type); + ActionDelay1 := ServiceFailureAction.lpsaActions.Delay; + end; + + if ServiceFailureAction.cActions >= 2 then + begin + Inc(ServiceFailureAction.lpsaActions); + Action2 := Integer(ServiceFailureAction.lpsaActions.&Type); + ActionDelay2 := ServiceFailureAction.lpsaActions.Delay; + end; + + if ServiceFailureAction.cActions >= 3 then + begin + Inc(ServiceFailureAction.lpsaActions); + Action3 := Integer(ServiceFailureAction.lpsaActions.&Type); + ActionDelay3 := ServiceFailureAction.lpsaActions.Delay; + end; + end + else + Result := System.GetLastError; + + FreeMem(ServiceFailureAction); + end + else + Result := System.GetLastError; + + UnlockServiceDatabase(LockHandle); + end + else + Result := System.GetLastError; + + CloseServiceHandle(ServiceHandle); + end + else + Result := System.GetLastError; + + CloseServiceHandle(ManagerHandle); + end + else + Result := System.GetLastError; + +end; + +function GetServiceFailureFlag(ServiceName: String; var FailureActionsOnNonCrashFailures: Boolean): Integer; +var + ManagerHandle: SC_HANDLE; + ServiceHandle: SC_HANDLE; + LockHandle: SC_LOCK; + BytesNeeded: DWORD; + ServiceFailureActionsFlag: LPSERVICE_FAILURE_ACTIONS_FLAG; +begin + Result := 0; + + ManagerHandle := OpenSCManager('', nil, SC_MANAGER_LOCK); + + if ManagerHandle > 0 then + begin + ServiceHandle := OpenService(ManagerHandle, PChar(ServiceName), SERVICE_QUERY_CONFIG); + + if ServiceHandle > 0 then + begin + LockHandle := LockServiceDatabase(ManagerHandle); + + if LockHandle <> nil then + begin + + if not QueryServiceConfig2(ServiceHandle, SERVICE_CONFIG_FAILURE_ACTIONS_FLAG, nil, 0, @BytesNeeded) and (System.GetLastError = ERROR_INSUFFICIENT_BUFFER) then + begin + GetMem(ServiceFailureActionsFlag, BytesNeeded); + + if QueryServiceConfig2(ServiceHandle, SERVICE_CONFIG_FAILURE_ACTIONS_FLAG, PByte(ServiceFailureActionsFlag), BytesNeeded, @BytesNeeded) then + FailureActionsOnNonCrashFailures := ServiceFailureActionsFlag.fFailureActionsOnNonCrashFailures + else + Result := System.GetLastError; + + FreeMem(ServiceFailureActionsFlag); + end + else + Result := System.GetLastError; + + UnlockServiceDatabase(LockHandle); + end + else + Result := System.GetLastError; + + CloseServiceHandle(ServiceHandle); + end + else + Result := System.GetLastError; + + CloseServiceHandle(ManagerHandle); + end + else + Result := System.GetLastError; + +end; + +function GetServiceDelayedAutoStartInfo(ServiceName: String; var DelayedAutostart: Boolean): Integer; +var + ManagerHandle: SC_HANDLE; + ServiceHandle: SC_HANDLE; + LockHandle: SC_LOCK; + BytesNeeded: DWORD; + ServiceDelayedAutoStartInfo: LPSERVICE_DELAYED_AUTO_START_INFO; +begin + Result := 0; + + ManagerHandle := OpenSCManager('', nil, SC_MANAGER_LOCK); + + if ManagerHandle > 0 then + begin + ServiceHandle := OpenService(ManagerHandle, PChar(ServiceName), SERVICE_QUERY_CONFIG); + + if ServiceHandle > 0 then + begin + LockHandle := LockServiceDatabase(ManagerHandle); + + if LockHandle <> nil then + begin + + if not QueryServiceConfig2(ServiceHandle, SERVICE_CONFIG_DELAYED_AUTO_START_INFO, nil, 0, @BytesNeeded) and (System.GetLastError = ERROR_INSUFFICIENT_BUFFER) then + begin + GetMem(ServiceDelayedAutoStartInfo, BytesNeeded); + + if QueryServiceConfig2(ServiceHandle, SERVICE_CONFIG_DELAYED_AUTO_START_INFO, PByte(ServiceDelayedAutoStartInfo), BytesNeeded, @BytesNeeded) then + DelayedAutostart := Boolean(ServiceDelayedAutoStartInfo.fDelayedAutostart) + else + Result := System.GetLastError; + + FreeMem(ServiceDelayedAutoStartInfo); + end + else + Result := System.GetLastError; + + UnlockServiceDatabase(LockHandle); + end + else + Result := System.GetLastError; + + CloseServiceHandle(ServiceHandle); + end + else + Result := System.GetLastError; + + CloseServiceHandle(ManagerHandle); + end + else + Result := System.GetLastError; + +end; + +function SetServiceDescription(ServiceName: String; Description: String): Integer; +var + ManagerHandle: SC_HANDLE; + ServiceHandle: SC_HANDLE; + LockHandle: SC_LOCK; +begin + Result := 0; + + ManagerHandle := OpenSCManager('', nil, SC_MANAGER_LOCK); + + if ManagerHandle > 0 then + begin + ServiceHandle := OpenService(ManagerHandle, PChar(ServiceName), SERVICE_CHANGE_CONFIG); + + if ServiceHandle > 0 then + begin + LockHandle := LockServiceDatabase(ManagerHandle); + + if LockHandle <> nil then + begin + if not ChangeServiceConfig2(ServiceHandle, SERVICE_CONFIG_DESCRIPTION, @Description) then + Result := System.GetLastError; + + UnlockServiceDatabase(LockHandle); + end + else + Result := System.GetLastError; + + CloseServiceHandle(ServiceHandle); + end + else + Result := System.GetLastError; + + CloseServiceHandle(ManagerHandle); + end + else + Result := System.GetLastError; +end; + +function SetServiceStartType(ServiceName: String; StartType: DWORD): Integer; +var + ManagerHandle: SC_HANDLE; + ServiceHandle: SC_HANDLE; + LockHandle: SC_LOCK; +begin + Result := 0; + + ManagerHandle := OpenSCManager('', nil, SC_MANAGER_LOCK); + + if ManagerHandle > 0 then + begin + ServiceHandle := OpenService(ManagerHandle, PChar(ServiceName), SERVICE_CHANGE_CONFIG); + + if ServiceHandle > 0 then + begin + LockHandle := LockServiceDatabase(ManagerHandle); + + if LockHandle <> nil then + begin + if not ChangeServiceConfig(ServiceHandle, SERVICE_NO_CHANGE, StartType, SERVICE_NO_CHANGE, nil, nil, nil, nil, nil, nil, nil) then + Result := System.GetLastError; + + UnlockServiceDatabase(LockHandle); + end + else + Result := System.GetLastError; + + CloseServiceHandle(ServiceHandle); + end + else + Result := System.GetLastError; + + CloseServiceHandle(ManagerHandle); + end + else + Result := System.GetLastError; +end; + +function SetServiceLogon(ServiceName: String; Username: String; Password: String): Integer; +var + ManagerHandle: SC_HANDLE; + ServiceHandle: SC_HANDLE; + LockHandle: SC_LOCK; +begin + Result := 0; + + ManagerHandle := OpenSCManager('', nil, SC_MANAGER_LOCK); + + if Pos('\', Username) = 0 then + Username := '.\' + Username; + + if ManagerHandle > 0 then + begin + ServiceHandle := OpenService(ManagerHandle, PChar(ServiceName), SERVICE_CHANGE_CONFIG); + + if ServiceHandle > 0 then + begin + LockHandle := LockServiceDatabase(ManagerHandle); + + if LockHandle <> nil then + begin + if not ChangeServiceConfig(ServiceHandle, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, nil, nil, nil, nil, PChar(Username), PChar(Password), nil) then + Result := System.GetLastError; + + UnlockServiceDatabase(LockHandle); + end + else + Result := System.GetLastError; + + CloseServiceHandle(ServiceHandle); + end + else + Result := System.GetLastError; + + CloseServiceHandle(ManagerHandle); + end + else + Result := System.GetLastError; +end; + +function SetServiceBinaryPath(ServiceName: String; BinaryPath: String): Integer; +var + ManagerHandle: SC_HANDLE; + ServiceHandle: SC_HANDLE; + LockHandle: SC_LOCK; +begin + Result := 0; + + ManagerHandle := OpenSCManager('', nil, SC_MANAGER_LOCK); + + if ManagerHandle > 0 then + begin + ServiceHandle := OpenService(ManagerHandle, PChar(ServiceName), SERVICE_CHANGE_CONFIG); + + if ServiceHandle > 0 then + begin + LockHandle := LockServiceDatabase(ManagerHandle); + + if LockHandle <> nil then + begin + if not ChangeServiceConfig(ServiceHandle, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, PChar(BinaryPath), nil, nil, nil, nil, nil, nil) then + Result := System.GetLastError; + + UnlockServiceDatabase(LockHandle); + end + else + Result := System.GetLastError; + + CloseServiceHandle(ServiceHandle); + end + else + Result := System.GetLastError; + + CloseServiceHandle(ManagerHandle); + end + else + Result := System.GetLastError; +end; + +function SetServiceFailure(ServiceName: String; ResetPeriod: DWORD; + RebootMessage: String; Command: String; Action1: Integer; ActionDelay1: DWORD; + Action2: Integer; ActionDelay2: DWORD; Action3: Integer; ActionDelay3: DWORD): Integer; +var + ManagerHandle: SC_HANDLE; + ServiceHandle: SC_HANDLE; + LockHandle: SC_LOCK; + ServiceFailureAction: SERVICE_FAILURE_ACTIONS; + ServiceActions: array[0..2] of SC_ACTION; + ServiceAccessType: Integer; +begin + Result := 0; + + if (SC_ACTION_TYPE(Action1) = SC_ACTION_RESTART) or (SC_ACTION_TYPE(Action2) = SC_ACTION_RESTART) or (SC_ACTION_TYPE(Action3) = SC_ACTION_RESTART) then + ServiceAccessType := SERVICE_CHANGE_CONFIG or SERVICE_START + else + ServiceAccessType := SERVICE_ALL_ACCESS; + + ServiceActions[0].&Type := SC_ACTION_TYPE(Action1); + ServiceActions[0].Delay := ActionDelay1; + ServiceActions[1].&Type := SC_ACTION_TYPE(Action2); + ServiceActions[1].Delay := ActionDelay2; + ServiceActions[2].&Type := SC_ACTION_TYPE(Action3); + ServiceActions[2].Delay := ActionDelay3; + + ServiceFailureAction.dwResetPeriod := ResetPeriod; + ServiceFailureAction.lpRebootMsg := PChar(RebootMessage); + ServiceFailureAction.lpCommand := PChar(Command); + ServiceFailureAction.cActions := Length(ServiceActions); + ServiceFailureAction.lpsaActions := @ServiceActions; + + ManagerHandle := OpenSCManager('', nil, SC_MANAGER_LOCK); + + if ManagerHandle > 0 then + begin + ServiceHandle := OpenService(ManagerHandle, PChar(ServiceName), ServiceAccessType); + + if ServiceHandle > 0 then + begin + LockHandle := LockServiceDatabase(ManagerHandle); + + if LockHandle <> nil then + begin + if not ChangeServiceConfig2W(ServiceHandle, SERVICE_CONFIG_FAILURE_ACTIONS, @ServiceFailureAction) then + Result := System.GetLastError; + + UnlockServiceDatabase(LockHandle); + end + else + Result := System.GetLastError; + + CloseServiceHandle(ServiceHandle); + end + else + Result := System.GetLastError; + + CloseServiceHandle(ManagerHandle); + end + else + Result := System.GetLastError; + +end; + +function SetServiceFailureFlag(ServiceName: String; FailureActionsOnNonCrashFailures: Boolean): Integer; +var + ManagerHandle: SC_HANDLE; + ServiceHandle: SC_HANDLE; + LockHandle: SC_LOCK; + ServiceFailureActionsFlag: SERVICE_FAILURE_ACTIONS_FLAG; +begin + Result := 0; + + DWORD(ServiceFailureActionsFlag.fFailureActionsOnNonCrashFailures) := DWORD(FailureActionsOnNonCrashFailures); + + ManagerHandle := OpenSCManager('', nil, SC_MANAGER_LOCK); + + if ManagerHandle > 0 then + begin + ServiceHandle := OpenService(ManagerHandle, PChar(ServiceName), SERVICE_CHANGE_CONFIG); + + if ServiceHandle > 0 then + begin + LockHandle := LockServiceDatabase(ManagerHandle); + + if LockHandle <> nil then + begin + if not ChangeServiceConfig2(ServiceHandle, SERVICE_CONFIG_FAILURE_ACTIONS_FLAG, @ServiceFailureActionsFlag) then + Result := System.GetLastError; + + UnlockServiceDatabase(LockHandle); + end + else + Result := System.GetLastError; + + CloseServiceHandle(ServiceHandle); + end + else + Result := System.GetLastError; + + CloseServiceHandle(ManagerHandle); + end + else + Result := System.GetLastError; + +end; + +function SetServiceDelayedAutoStartInfo(ServiceName: String; DelayedAutostart: Boolean): Integer; +var + ManagerHandle: SC_HANDLE; + ServiceHandle: SC_HANDLE; + LockHandle: SC_LOCK; + ServiceDelayedAutoStartInfo: SERVICE_DELAYED_AUTO_START_INFO; +begin + Result := 0; + + DWORD(ServiceDelayedAutoStartInfo.fDelayedAutostart) := DWORD(DelayedAutostart); + + ManagerHandle := OpenSCManager('', nil, SC_MANAGER_LOCK); + + if ManagerHandle > 0 then + begin + ServiceHandle := OpenService(ManagerHandle, PChar(ServiceName), SERVICE_CHANGE_CONFIG); + + if ServiceHandle > 0 then + begin + LockHandle := LockServiceDatabase(ManagerHandle); + + if LockHandle <> nil then + begin + if not ChangeServiceConfig2(ServiceHandle, SERVICE_CONFIG_DELAYED_AUTO_START_INFO, @ServiceDelayedAutoStartInfo) then + Result := System.GetLastError; + + UnlockServiceDatabase(LockHandle); + end + else + Result := System.GetLastError; + + CloseServiceHandle(ServiceHandle); + end + else + Result := System.GetLastError; + + CloseServiceHandle(ManagerHandle); + end + else + Result := System.GetLastError; + +end; + +function ServiceIsRunning(ServiceName: String; var IsRunning: Boolean): Integer; +var + Status: DWORD; +begin + Result := GetServiceStatus(ServiceName, Status); + + if Result = 0 then + IsRunning := Status = SERVICE_RUNNING + else + IsRunning := False; +end; + +function ServiceIsStopped(ServiceName: String; var IsStopped: Boolean): Integer; +var + Status: DWORD; +begin + Result := GetServiceStatus(ServiceName, Status); + + if Result = 0 then + IsStopped := Status = SERVICE_STOPPED + else + IsStopped := False; +end; + +function ServiceIsPaused(ServiceName: String; var IsPaused: Boolean): Integer; +var + Status: DWORD; +begin + Result := GetServiceStatus(ServiceName, Status); + + if Result = 0 then + IsPaused := Status = SERVICE_PAUSED + else + IsPaused := False; +end; + +function RestartService(ServiceName: String; ServiceArguments: String; Timeout: Integer): Integer; +begin + Result := StopService(ServiceName, False, Timeout); + + if Result = 0 then + Result := StartService(ServiceName, ServiceArguments, Timeout); +end; + +function InstallService(ServiceName, DisplayName: String; ServiceType: DWORD; + StartType: DWORD; BinaryPathName: String; Dependencies: String; + Username: String; Password: String): Integer; +var + ManagerHandle: SC_HANDLE; + ServiceHandle: SC_HANDLE; + PDependencies: PChar; + PUsername: PChar; + PPassword: PChar; +const + ReplaceDelimitter: String = '/'; + + function Replace(Value: String): String; + begin + while Pos(ReplaceDelimitter, Value) <> 0 do + begin + Result := Result + Copy(Value, 1, Pos(ReplaceDelimitter, Value) -1) + Chr(0); + Delete(Value, 1, Pos(ReplaceDelimitter, Value)); + end; + + Result := Result + Value + Chr(0) + Chr(0); + + end; + +begin + Result := 0; + + if Dependencies = '' then + PDependencies := nil + else + PDependencies := PChar(Replace(Dependencies)); + + if UserName = '' then + PUsername := nil + else + begin + if Pos('\', Username) = 0 then + Username := '.\' + Username; + + PUsername := PChar(Username); + end; + + if Password = '' then + PPassword := nil + else + PPassword := PChar(Password); + + ManagerHandle := OpenSCManager('', nil, SC_MANAGER_ALL_ACCESS); + + if ManagerHandle > 0 then + begin + ServiceHandle := CreateService(ManagerHandle, + PChar(ServiceName), + PChar(DisplayName), + SERVICE_START or SERVICE_QUERY_STATUS or _DELETE, + ServiceType, + StartType, + SERVICE_ERROR_NORMAL, + PChar(BinaryPathName), + nil, + nil, + PDependencies, + PUsername, + PPassword); + + if ServiceHandle <> 0 then + CloseServiceHandle(ServiceHandle) + else + Result := System.GetLastError; + + CloseServiceHandle(ManagerHandle); + end + else + Result := System.GetLastError; +end; + +function RemoveService(ServiceName: String): Integer; +var + ManagerHandle: SC_HANDLE; + ServiceHandle: SC_HANDLE; + LockHandle: SC_LOCK; + Deleted: Boolean; +begin + Result := 0; + + ManagerHandle := OpenSCManager('', nil, SC_MANAGER_ALL_ACCESS); + + if ManagerHandle > 0 then + begin + ServiceHandle := OpenService(ManagerHandle, PChar(ServiceName), SERVICE_ALL_ACCESS); + + if ServiceHandle > 0 then + begin + LockHandle := LockServiceDatabase(ManagerHandle); + + if LockHandle <> nil then + begin + Deleted := DeleteService(ServiceHandle); + + if not Deleted then + Result := System.GetLastError; + + UnlockServiceDatabase(LockHandle); + end + else + Result := System.GetLastError; + + CloseServiceHandle(ServiceHandle); + end + else + Result := System.GetLastError; + + CloseServiceHandle(ManagerHandle); + end + else + Result := System.GetLastError; +end; + +function GetErrorMessage(ErrorCode: Integer): String; +begin + Result := SysErrorMessage(ErrorCode); +end; + +end. diff --git a/desktop/tauri/src-tauri/templates/NSIS_Simple_Service_Plugin_Unicode_1.30/Source/SimpleSC.dpr b/desktop/tauri/src-tauri/templates/NSIS_Simple_Service_Plugin_Unicode_1.30/Source/SimpleSC.dpr new file mode 100644 index 00000000..079111a4 --- /dev/null +++ b/desktop/tauri/src-tauri/templates/NSIS_Simple_Service_Plugin_Unicode_1.30/Source/SimpleSC.dpr @@ -0,0 +1,609 @@ +library SimpleSC; + +uses + Winapi.Windows, + System.SysUtils, + NSIS in 'NSIS.pas', + ServiceControl in 'ServiceControl.pas', + LSASecurityControl in 'LSASecurityControl.pas'; + +function BoolToStr(Value: Boolean): String; +begin + if Value then + Result := '1' + else + Result := '0'; +end; + +function StrToBool(Value: String): Boolean; +begin + Result := Value = '1'; +end; + +procedure InstallService(const hwndParent: HWND; const string_size: integer; + const variables: PChar; const stacktop: pointer); cdecl; +var + ServiceName: String; + DisplayName: String; + ServiceType: Cardinal; + StartType: Cardinal; + BinaryPath: String; + Dependencies: String; + Username: String; + Password: String; + ServiceResult: String; +begin + Init(hwndParent, string_size, variables, stacktop); + + ServiceName := PopString; + DisplayName := PopString; + ServiceType := StrToInt(PopString); + StartType := StrToInt(PopString); + BinaryPath := PopString; + Dependencies := PopString; + Username := PopString; + Password := PopString; + + ServiceResult := IntToStr(ServiceControl.InstallService(ServiceName, DisplayName, ServiceType, StartType, BinaryPath, Dependencies, Username, Password)); + PushString(ServiceResult); +end; + +procedure RemoveService(const hwndParent: HWND; const string_size: integer; + const variables: PChar; const stacktop: pointer); cdecl; +var + ServiceName: String; + ServiceResult: String; +begin + Init(hwndParent, string_size, variables, stacktop); + + ServiceName := PopString; + + ServiceResult := IntToStr(ServiceControl.RemoveService(ServiceName)); + PushString(ServiceResult); +end; + +procedure StartService(const hwndParent: HWND; const string_size: integer; + const variables: PChar; const stacktop: pointer); cdecl; +var + ServiceName: String; + ServiceArguments: String; + Timeout: Integer; + ServiceResult: String; +begin + Init(hwndParent, string_size, variables, stacktop); + + ServiceName := PopString; + ServiceArguments := PopString; + Timeout := StrToInt(PopString); + + ServiceResult := IntToStr(ServiceControl.StartService(ServiceName, ServiceArguments, Timeout)); + + PushString(ServiceResult); +end; + +procedure StopService(const hwndParent: HWND; const string_size: integer; + const variables: PChar; const stacktop: pointer); cdecl; +var + ServiceName: String; + WaitForFileRelease: Boolean; + Timeout: Integer; + ServiceResult: String; +begin + Init(hwndParent, string_size, variables, stacktop); + + ServiceName := PopString; + + WaitForFileRelease := StrToBool(PopString); + Timeout := StrToInt(PopString); + + ServiceResult := IntToStr(ServiceControl.StopService(ServiceName, WaitForFileRelease, Timeout)); + PushString(ServiceResult); +end; + +procedure PauseService(const hwndParent: HWND; const string_size: integer; + const variables: PChar; const stacktop: pointer); cdecl; +var + ServiceName: String; + Timeout: Integer; + ServiceResult: String; +begin + Init(hwndParent, string_size, variables, stacktop); + + ServiceName := PopString; + Timeout := StrToInt(PopString); + ServiceResult := IntToStr(ServiceControl.PauseService(ServiceName, Timeout)); + PushString(ServiceResult) +end; + +procedure ContinueService(const hwndParent: HWND; const string_size: integer; + const variables: PChar; const stacktop: pointer); cdecl; +var + ServiceName: String; + Timeout: Integer; + ServiceResult: String; +begin + Init(hwndParent, string_size, variables, stacktop); + + ServiceName := PopString; + Timeout := StrToInt(PopString); + ServiceResult := IntToStr(ServiceControl.ContinueService(ServiceName, Timeout)); + PushString(ServiceResult) +end; + +procedure GetServiceName(const hwndParent: HWND; const string_size: integer; + const variables: PChar; const stacktop: pointer); cdecl; +Var + DisplayName: String; + ServiceResult: String; + ServiceName: String; +begin + Init(hwndParent, string_size, variables, stacktop); + + DisplayName := PopString; + ServiceResult := IntToStr(ServiceControl.GetServiceName(DisplayName, ServiceName)); + PushString(ServiceName); + PushString(ServiceResult); +end; + +procedure GetServiceDisplayName(const hwndParent: HWND; const string_size: integer; + const variables: PChar; const stacktop: pointer); cdecl; +Var + ServiceName: String; + DisplayName: String; + ServiceResult: String; +begin + Init(hwndParent, string_size, variables, stacktop); + + ServiceName := PopString; + ServiceResult := IntToStr(ServiceControl.GetServiceDisplayName(ServiceName, DisplayName)); + PushString(DisplayName); + PushString(ServiceResult); +end; + +procedure GetServiceStatus(const hwndParent: HWND; const string_size: integer; + const variables: PChar; const stacktop: pointer); cdecl; +var + ServiceName: String; + Status: DWORD; + ServiceResult: String; +begin + Init(hwndParent, string_size, variables, stacktop); + + ServiceName := PopString; + ServiceResult := IntToStr(ServiceControl.GetServiceStatus(ServiceName, Status)); + PushString(IntToStr(Status)); + PushString(ServiceResult); +end; + +procedure GetServiceBinaryPath(const hwndParent: HWND; const string_size: integer; + const variables: PChar; const stacktop: pointer); cdecl; +var + ServiceName: String; + BinaryPath: String; + ServiceResult: String; +begin + Init(hwndParent, string_size, variables, stacktop); + + ServiceName := PopString; + ServiceResult := IntToStr(ServiceControl.GetServiceBinaryPath(ServiceName, BinaryPath)); + PushString(BinaryPath); + PushString(ServiceResult); +end; + +procedure GetServiceDescription(const hwndParent: HWND; const string_size: integer; + const variables: PChar; const stacktop: pointer); cdecl; +var + ServiceName: String; + Description: String; + ServiceResult: String; +begin + Init(hwndParent, string_size, variables, stacktop); + + ServiceName := PopString; + ServiceResult := IntToStr(ServiceControl.GetServiceDescription(ServiceName, Description)); + PushString(Description); + PushString(ServiceResult); +end; + +procedure GetServiceStartType(const hwndParent: HWND; const string_size: integer; + const variables: PChar; const stacktop: pointer); cdecl; +var + ServiceName: String; + StartType: DWORD; + ServiceResult: String; +begin + Init(hwndParent, string_size, variables, stacktop); + + ServiceName := PopString; + ServiceResult := IntToStr(ServiceControl.GetServiceStartType(ServiceName, StartType)); + PushString(IntToStr(StartType)); + PushString(ServiceResult); +end; + +procedure GetServiceLogon(const hwndParent: HWND; const string_size: integer; + const variables: PChar; const stacktop: pointer); cdecl; +var + ServiceName: String; + Username: String; + ServiceResult: String; +begin + Init(hwndParent, string_size, variables, stacktop); + + ServiceName := PopString; + ServiceResult := IntToStr(ServiceControl.GetServiceLogon(ServiceName, Username)); + PushString(Username); + PushString(ServiceResult); +end; + +procedure GetServiceFailure(const hwndParent: HWND; const string_size: integer; + const variables: PChar; const stacktop: pointer); cdecl; +var + ServiceName: String; + ResetPeriod: DWORD; + RebootMessage: String; + Command: String; + Action1: Integer; + ActionDelay1: DWORD; + Action2: Integer; + ActionDelay2: DWORD; + Action3: Integer; + ActionDelay3: DWORD; + ServiceResult: String; +begin + Init(hwndParent, string_size, variables, stacktop); + + ServiceName := PopString; + ServiceResult := IntToStr(ServiceControl.GetServiceFailure(ServiceName, ResetPeriod, RebootMessage, Command, Action1, ActionDelay1, Action2, ActionDelay2, Action3, ActionDelay3)); + PushString(IntToStr(ActionDelay3)); + PushString(IntToStr(Action3)); + PushString(IntToStr(ActionDelay2)); + PushString(IntToStr(Action2)); + PushString(IntToStr(ActionDelay1)); + PushString(IntToStr(Action1)); + PushString(Command); + PushString(RebootMessage); + PushString(IntToStr(ResetPeriod)); + PushString(ServiceResult); +end; + +procedure GetServiceFailureFlag(const hwndParent: HWND; const string_size: integer; + const variables: PChar; const stacktop: pointer); cdecl; +var + ServiceName: String; + FailureActionsOnNonCrashFailures: Boolean; + ServiceResult: String; +begin + Init(hwndParent, string_size, variables, stacktop); + + ServiceName := PopString; + ServiceResult := IntToStr(ServiceControl.GetServiceFailureFlag(ServiceName, FailureActionsOnNonCrashFailures)); + PushString(BoolToStr(FailureActionsOnNonCrashFailures)); + PushString(ServiceResult); +end; + +procedure GetServiceDelayedAutoStartInfo(const hwndParent: HWND; const string_size: integer; + const variables: PChar; const stacktop: pointer); cdecl; +var + ServiceName: String; + DelayedAutostart: Boolean; + ServiceResult: String; +begin + Init(hwndParent, string_size, variables, stacktop); + + ServiceName := PopString; + ServiceResult := IntToStr(ServiceControl.GetServiceDelayedAutoStartInfo(ServiceName, DelayedAutostart)); + PushString(BoolToStr(DelayedAutostart)); + PushString(ServiceResult); +end; + +procedure SetServiceDescription(const hwndParent: HWND; const string_size: integer; + const variables: PChar; const stacktop: pointer); cdecl; +var + ServiceName: String; + Description: String; + ServiceResult: String; +begin + Init(hwndParent, string_size, variables, stacktop); + + ServiceName := PopString; + Description := PopString; + ServiceResult := IntToStr(ServiceControl.SetServiceDescription(ServiceName, Description)); + PushString(ServiceResult); +end; + +procedure SetServiceStartType(const hwndParent: HWND; const string_size: integer; + const variables: PChar; const stacktop: pointer); cdecl; +var + ServiceName: String; + ServiceStartType: DWORD; + ServiceResult: String; +begin + Init(hwndParent, string_size, variables, stacktop); + + ServiceName := PopString; + ServiceStartType := StrToInt(PopString); + ServiceResult := IntToStr(ServiceControl.SetServiceStartType(ServiceName, ServiceStartType)); + PushString(ServiceResult); +end; + +procedure SetServiceLogon(const hwndParent: HWND; const string_size: integer; + const variables: PChar; const stacktop: pointer); cdecl; +var + ServiceName: String; + Username: String; + Password: String; + ServiceResult: String; +begin + Init(hwndParent, string_size, variables, stacktop); + + ServiceName := PopString; + Username := PopString; + Password := PopString; + + ServiceResult := IntToStr(ServiceControl.SetServiceLogon(ServiceName, Username, Password)); + PushString(ServiceResult); +end; + +procedure SetServiceBinaryPath(const hwndParent: HWND; const string_size: integer; + const variables: PChar; const stacktop: pointer); cdecl; +var + ServiceName: String; + BinaryPath: String; + ServiceResult: String; +begin + Init(hwndParent, string_size, variables, stacktop); + + ServiceName := PopString; + BinaryPath := PopString; + + ServiceResult := IntToStr(ServiceControl.SetServiceBinaryPath(ServiceName, BinaryPath)); + PushString(ServiceResult); +end; + +procedure SetServiceFailure(const hwndParent: HWND; const string_size: integer; + const variables: PChar; const stacktop: pointer); cdecl; +var + ServiceName: String; + ResetPeriod: DWORD; + RebootMessage: String; + Command: String; + Action1: Integer; + ActionDelay1: DWORD; + Action2: Integer; + ActionDelay2: DWORD; + Action3: Integer; + ActionDelay3: DWORD; + ServiceResult: Integer; + PrivilegeResult: Integer; +const + SE_SHUTDOWN_PRIVILEGE = 'SeShutdownPrivilege'; + SC_ACTION_REBOOT = 2; +begin + Init(hwndParent, string_size, variables, stacktop); + + ServiceName := PopString; + ResetPeriod := StrToInt(PopString); + RebootMessage := PopString; + Command := PopString; + Action1 := StrToInt(PopString); + ActionDelay1 := StrToInt(PopString); + Action2 := StrToInt(PopString); + ActionDelay2 := StrToInt(PopString); + Action3 := StrToInt(PopString); + ActionDelay3 := StrToInt(PopString); + + if (Action1 = SC_ACTION_REBOOT) or (Action2 = SC_ACTION_REBOOT) or (Action3 = SC_ACTION_REBOOT) then + begin + PrivilegeResult := LSASecurityControl.EnablePrivilege(SE_SHUTDOWN_PRIVILEGE); + + if not PrivilegeResult = 0 then + begin + PushString(IntToStr(PrivilegeResult)); + Exit; + end; + end; + + ServiceResult := ServiceControl.SetServiceFailure(ServiceName, ResetPeriod, RebootMessage, Command, Action1, ActionDelay1, + Action2, ActionDelay2, Action3, ActionDelay3); + + + if (Action1 = SC_ACTION_REBOOT) or (Action2 = SC_ACTION_REBOOT) or (Action3 = SC_ACTION_REBOOT) then + begin + PrivilegeResult := LSASecurityControl.DisablePrivilege(SE_SHUTDOWN_PRIVILEGE); + + if not PrivilegeResult = 0 then + begin + PushString(IntToStr(PrivilegeResult)); + Exit; + end; + end; + + PushString(IntToStr(ServiceResult)); + +end; + +procedure SetServiceFailureFlag(const hwndParent: HWND; const string_size: integer; + const variables: PChar; const stacktop: pointer); cdecl; +var + ServiceName: String; + FailureActionsOnNonCrashFailures: Boolean; + ServiceResult: String; +begin + Init(hwndParent, string_size, variables, stacktop); + + ServiceName := PopString; + FailureActionsOnNonCrashFailures := StrToBool(PopString); + ServiceResult := IntToStr(ServiceControl.SetServiceFailureFlag(ServiceName, FailureActionsOnNonCrashFailures)); + PushString(ServiceResult) +end; + +procedure SetServiceDelayedAutoStartInfo(const hwndParent: HWND; const string_size: integer; + const variables: PChar; const stacktop: pointer); cdecl; +var + ServiceName: String; + DelayedAutostart: Boolean; + ServiceResult: String; +begin + Init(hwndParent, string_size, variables, stacktop); + + ServiceName := PopString; + DelayedAutostart := StrToBool(PopString); + ServiceResult := IntToStr(ServiceControl.SetServiceDelayedAutoStartInfo(ServiceName, DelayedAutostart)); + PushString(ServiceResult) +end; + +procedure ServiceIsRunning(const hwndParent: HWND; const string_size: integer; + const variables: PChar; const stacktop: pointer); cdecl; +var + ServiceName: String; + IsRunning: Boolean; + ServiceResult: String; +begin + Init(hwndParent, string_size, variables, stacktop); + + ServiceName := PopString; + ServiceResult := IntToStr(ServiceControl.ServiceIsRunning(ServiceName, IsRunning)); + PushString(BoolToStr(IsRunning)); + PushString(ServiceResult); +end; + +procedure ServiceIsStopped(const hwndParent: HWND; const string_size: integer; + const variables: PChar; const stacktop: pointer); cdecl; +var + ServiceName: String; + IsStopped: Boolean; + ServiceResult: String; +begin + Init(hwndParent, string_size, variables, stacktop); + + ServiceName := PopString; + ServiceResult := IntToStr(ServiceControl.ServiceIsStopped(ServiceName, IsStopped)); + PushString(BoolToStr(IsStopped)); + PushString(ServiceResult); +end; + +procedure ServiceIsPaused(const hwndParent: HWND; const string_size: integer; + const variables: PChar; const stacktop: pointer); cdecl; +var + ServiceName: String; + IsPaused: Boolean; + ServiceResult: String; +begin + Init(hwndParent, string_size, variables, stacktop); + + ServiceName := PopString; + ServiceResult := IntToStr(ServiceControl.ServiceIsPaused(ServiceName, IsPaused)); + PushString(BoolToStr(IsPaused)); + PushString(ServiceResult); +end; + +procedure RestartService(const hwndParent: HWND; const string_size: integer; + const variables: PChar; const stacktop: pointer); cdecl; +var + ServiceName: String; + ServiceArguments: String; + Timeout: Integer; + ServiceResult: String; +begin + Init(hwndParent, string_size, variables, stacktop); + + ServiceName := PopString; + ServiceArguments := PopString; + Timeout := StrToInt(PopString); + ServiceResult := IntToStr(ServiceControl.RestartService(ServiceName, ServiceArguments, Timeout)); + PushString(ServiceResult); +end; + +procedure ExistsService(const hwndParent: HWND; const string_size: integer; + const variables: PChar; const stacktop: pointer); cdecl; +var + ServiceName: String; + ServiceResult: String; +begin + Init(hwndParent, string_size, variables, stacktop); + + ServiceName := PopString; + + ServiceResult := IntToStr(ServiceControl.ExistsService(ServiceName)); + PushString(ServiceResult); +end; + +procedure GrantServiceLogonPrivilege(const hwndParent: HWND; const string_size: integer; + const variables: PChar; const stacktop: pointer); cdecl; +var + AccountName: String; + LSAResult: String; +const + SE_SERVICE_LOGON_RIGHT = 'SeServiceLogonRight'; +begin + Init(hwndParent, string_size, variables, stacktop); + + AccountName := PopString; + + LSAResult := IntToStr(LSASecurityControl.GrantPrivilege(AccountName, SE_SERVICE_LOGON_RIGHT)); + PushString(LSAResult); +end; + +procedure RemoveServiceLogonPrivilege(const hwndParent: HWND; const string_size: integer; + const variables: PChar; const stacktop: pointer); cdecl; +var + AccountName: String; + LSAResult: String; +const + SE_SERVICE_LOGON_RIGHT = 'SeServiceLogonRight'; +begin + Init(hwndParent, string_size, variables, stacktop); + + AccountName := PopString; + + LSAResult := IntToStr(LSASecurityControl.RemovePrivilege(AccountName, SE_SERVICE_LOGON_RIGHT)); + PushString(LSAResult); +end; + +procedure GetErrorMessage(const hwndParent: HWND; const string_size: integer; + const variables: PChar; const stacktop: pointer); cdecl; +var + ErrorCode: Integer; + ErrorMessage: String; +begin + Init(hwndParent, string_size, variables, stacktop); + + ErrorCode := StrToInt(PopString); + + ErrorMessage := ServiceControl.GetErrorMessage(ErrorCode); + PushString(ErrorMessage); +end; + +exports InstallService; +exports ExistsService; +exports RemoveService; +exports StartService; +exports StopService; +exports PauseService; +exports ContinueService; +exports GetServiceName; +exports GetServiceDisplayName; +exports GetServiceStatus; +exports GetServiceBinaryPath; +exports GetServiceDescription; +exports GetServiceStartType; +exports GetServiceLogon; +exports GetServiceFailure; +exports GetServiceFailureFlag; +exports GetServiceDelayedAutoStartInfo; +exports SetServiceDescription; +exports SetServiceStartType; +exports SetServiceLogon; +exports SetServiceBinaryPath; +exports SetServiceFailure; +exports SetServiceFailureFlag; +exports SetServiceDelayedAutoStartInfo; +exports ServiceIsRunning; +exports ServiceIsStopped; +exports ServiceIsPaused; +exports RestartService; +exports GrantServiceLogonPrivilege; +exports RemoveServiceLogonPrivilege; +exports GetErrorMessage; + +end. diff --git a/desktop/tauri/src-tauri/templates/NSIS_Simple_Service_Plugin_Unicode_1.30/Source/SimpleSC.dproj b/desktop/tauri/src-tauri/templates/NSIS_Simple_Service_Plugin_Unicode_1.30/Source/SimpleSC.dproj new file mode 100644 index 00000000..e657efa9 --- /dev/null +++ b/desktop/tauri/src-tauri/templates/NSIS_Simple_Service_Plugin_Unicode_1.30/Source/SimpleSC.dproj @@ -0,0 +1,910 @@ + + + {9A1C1FE1-FB44-40C4-9E22-99CAE6325532} + 18.8 + None + SimpleSC.dpr + True + Release + Win32 + 1 + Library + + + true + + + true + Base + true + + + true + Base + true + + + true + Base + true + + + true + Cfg_2 + true + true + + + bindcompfmx;fmx;rtl;dbrtl;IndySystem;DbxClientDriver;bindcomp;inetdb;DBXInterBaseDriver;DataSnapCommon;DataSnapClient;DataSnapServer;DataSnapProviderClient;xmlrtl;DbxCommonDriver;IndyProtocols;DBXMySQLDriver;dbxcds;bindengine;soaprtl;DBXOracleDriver;dsnap;DBXInformixDriver;IndyCore;fmxase;DBXFirebirdDriver;inet;fmxobj;inetdbxpress;DBXSybaseASADriver;fmxdae;dbexpress;DataSnapIndy10ServerTransport;IPIndyImpl;$(DCC_UsePackage) + System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace) + true + .\$(Platform)\$(Config) + .\$(Platform)\$(Config) + false + false + false + false + false + SimpleSC + + + None + C:\Developing\NSIS Simple Service Control - Unicode\ + C:\Developing\NSIS Simple Service Control - Unicode\ + Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) + frx16;TeeDB;Rave100VCL;vclib;Tee;inetdbbde;DBXOdbcDriver;svnui;ibxpress;DBXSybaseASEDriver;vclimg;frxDB16;intrawebdb_120_160;fmi;fs16;TeeUI;vclactnband;FMXTee;vcldb;vcldsnap;bindcompvcl;vclie;vcltouch;Intraweb_120_160;DBXDb2Driver;websnap;vclribbon;frxe16;fsDB16;vcl;DataSnapConnectors;CloudService;DBXMSSQLDriver;FmxTeeUI;dsnapcon;vclx;webdsnap;svn;bdertl;CodeSiteExpressPkg;adortl;vcldbx;VclSmp;$(DCC_UsePackage) + 1033 + CompanyName=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName);FileDescription=$(MSBuildProjectName);ProductName=$(MSBuildProjectName) + + + DBXOdbcDriver;DBXSybaseASEDriver;vclimg;vclactnband;vcldb;vcldsnap;bindcompvcl;vclie;vcltouch;DBXDb2Driver;websnap;vcl;DBXMSSQLDriver;dsnapcon;vclx;webdsnap;VclSmp;$(DCC_UsePackage) + + + None + CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments= + false + 1031 + false + 0 + 0 + + + C:\Developing\NSIS Simple Service Control - Unicode\ + C:\Developing\NSIS Simple Service Control - Unicode\ + 1033 + (Ohne) + + + + MainSource + + + + + + Cfg_2 + Base + + + Base + + + + Delphi.Personality.12 + + + + + False + False + 1 + 0 + 0 + 0 + False + False + False + False + False + 1031 + 1252 + + + + + 1.0.0.0 + + + + + + 1.0.0.0 + + + + SimpleSC.dpr + + + Microsoft Office 2000 Beispiele für gekapselte Komponenten für Automatisierungsserver + Microsoft Office XP Beispiele für gekapselte Komponenten für Automation Server + + + + + + true + + + + + true + + + + + true + + + + + 1 + + + 0 + + + + + classes + 1 + + + classes + 1 + + + + + res\xml + 1 + + + res\xml + 1 + + + + + library\lib\armeabi-v7a + 1 + + + + + library\lib\armeabi + 1 + + + library\lib\armeabi + 1 + + + + + library\lib\armeabi-v7a + 1 + + + + + library\lib\mips + 1 + + + library\lib\mips + 1 + + + + + library\lib\armeabi-v7a + 1 + + + library\lib\arm64-v8a + 1 + + + + + library\lib\armeabi-v7a + 1 + + + + + res\drawable + 1 + + + res\drawable + 1 + + + + + res\values + 1 + + + res\values + 1 + + + + + res\values-v21 + 1 + + + res\values-v21 + 1 + + + + + res\values + 1 + + + res\values + 1 + + + + + res\drawable + 1 + + + res\drawable + 1 + + + + + res\drawable-xxhdpi + 1 + + + res\drawable-xxhdpi + 1 + + + + + res\drawable-ldpi + 1 + + + res\drawable-ldpi + 1 + + + + + res\drawable-mdpi + 1 + + + res\drawable-mdpi + 1 + + + + + res\drawable-hdpi + 1 + + + res\drawable-hdpi + 1 + + + + + res\drawable-xhdpi + 1 + + + res\drawable-xhdpi + 1 + + + + + res\drawable-mdpi + 1 + + + res\drawable-mdpi + 1 + + + + + res\drawable-hdpi + 1 + + + res\drawable-hdpi + 1 + + + + + res\drawable-xhdpi + 1 + + + res\drawable-xhdpi + 1 + + + + + res\drawable-xxhdpi + 1 + + + res\drawable-xxhdpi + 1 + + + + + res\drawable-xxxhdpi + 1 + + + res\drawable-xxxhdpi + 1 + + + + + res\drawable-small + 1 + + + res\drawable-small + 1 + + + + + res\drawable-normal + 1 + + + res\drawable-normal + 1 + + + + + res\drawable-large + 1 + + + res\drawable-large + 1 + + + + + res\drawable-xlarge + 1 + + + res\drawable-xlarge + 1 + + + + + res\values + 1 + + + res\values + 1 + + + + + 1 + + + 1 + + + 0 + + + + + 1 + .framework + + + 1 + .framework + + + 0 + + + + + 1 + .dylib + + + 1 + .dylib + + + 0 + .dll;.bpl + + + + + 1 + .dylib + + + 1 + .dylib + + + 1 + .dylib + + + 1 + .dylib + + + 1 + .dylib + + + 0 + .bpl + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 1 + + + 1 + + + 1 + + + + + 1 + + + 1 + + + 1 + + + + + 1 + + + 1 + + + 1 + + + + + 1 + + + 1 + + + 1 + + + + + 1 + + + 1 + + + 1 + + + + + 1 + + + 1 + + + 1 + + + + + 1 + + + 1 + + + 1 + + + + + 1 + + + 1 + + + 1 + + + + + 1 + + + 1 + + + 1 + + + + + 1 + + + 1 + + + 1 + + + + + 1 + + + 1 + + + 1 + + + + + 1 + + + 1 + + + 1 + + + + + 1 + + + 1 + + + 1 + + + + + 1 + + + 1 + + + 1 + + + + + 1 + + + 1 + + + 1 + + + + + 1 + + + 1 + + + 1 + + + + + 1 + + + 1 + + + 1 + + + + + 1 + + + 1 + + + 1 + + + + + 1 + + + 1 + + + 1 + + + + + 1 + + + 1 + + + 1 + + + + + 1 + + + 1 + + + 1 + + + + + 1 + + + 1 + + + 1 + + + + + 1 + + + 1 + + + 1 + + + + + 1 + + + 1 + + + 1 + + + + + 1 + + + 1 + + + + + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF + 1 + + + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF + 1 + + + + + + + + 1 + + + 1 + + + 1 + + + + + + + + Contents\Resources + 1 + + + Contents\Resources + 1 + + + + + library\lib\armeabi-v7a + 1 + + + library\lib\arm64-v8a + 1 + + + 1 + + + 1 + + + 1 + + + 1 + + + 1 + + + 1 + + + 0 + + + + + library\lib\armeabi-v7a + 1 + + + + + 1 + + + 1 + + + + + Assets + 1 + + + Assets + 1 + + + + + Assets + 1 + + + Assets + 1 + + + + + + + + + + + + + + + True + False + + False + + 12 + + + + + diff --git a/desktop/tauri/src-tauri/templates/NSIS_Simple_Service_Plugin_Unicode_1.30/Source/SimpleSC.res b/desktop/tauri/src-tauri/templates/NSIS_Simple_Service_Plugin_Unicode_1.30/Source/SimpleSC.res new file mode 100644 index 00000000..74359957 Binary files /dev/null and b/desktop/tauri/src-tauri/templates/NSIS_Simple_Service_Plugin_Unicode_1.30/Source/SimpleSC.res differ diff --git a/desktop/tauri/src-tauri/templates/nsis/install_hooks.nsh b/desktop/tauri/src-tauri/templates/nsis/install_hooks.nsh new file mode 100644 index 00000000..77596f57 --- /dev/null +++ b/desktop/tauri/src-tauri/templates/nsis/install_hooks.nsh @@ -0,0 +1,126 @@ +!include LogicLib.nsh + +!addplugindir "..\..\..\..\templates\NSIS_Simple_Service_Plugin_Unicode_1.30" + +var oldInstallationDir +var dataDir + +!macro NSIS_HOOK_PREINSTALL + + ; Abort if old service is running + SimpleSC::ServiceIsStopped "PortmasterCore" + Pop $0 + Pop $1 + ${If} $0 == 0 + ${If} $1 == 0 + MessageBox MB_OK "Portmaster service is running. Stop it and run the installer again." + Abort + ${EndIf} + ${EndIf} + + File "..\..\..\..\binary\index.json" + File "..\..\..\..\binary\portmaster-core.exe" + File "..\..\..\..\binary\portmaster-kext.sys" + File "..\..\..\..\binary\portmaster-core.dll" + File "..\..\..\..\binary\WebView2Loader.dll" + File "..\..\..\..\binary\portmaster.zip" + File "..\..\..\..\binary\assets.zip" + + SetOutPath "$COMMONPROGRAMDATA\Portmaster\intel" + + File "..\..\..\..\intel\index.json" + File "..\..\..\..\intel\base.dsdl" + File "..\..\..\..\intel\geoipv4.mmdb" + File "..\..\..\..\intel\geoipv6.mmdb" + File "..\..\..\..\intel\index.dsd" + File "..\..\..\..\intel\intermediate.dsdl" + File "..\..\..\..\intel\urgent.dsdl" + + ; restire previous state + SetOutPath "$INSTDIR" + +!macroend + +;-------------------------------------------------- +; Post-install hook: +; - Remove old service +; - Installs the service +!macro NSIS_HOOK_POSTINSTALL + DetailPrint "Installing service" + ; Remove old service + SimpleSC::RemoveService "PortmasterCore" + Pop $0 + ${If} $0 != 0 + DetailPrint "Failed to remove PortmasterCore service. Error: $0" + ${EndIf} + + ; Install the service: + ; Parameters: + ; 1. Service Name: "PortmasterCore" + ; 2. Display Name: "Portmaster Core" + ; 3. Service Type: "16" for SERVICE_WIN32_OWN_PROCESS + ; 4. Start Type: "2" for SERVICE_AUTO_START + ; 5. Binary Path: Executable with arguments. + ; 6 & 7. Dependencies and account info (empty uses defaults). + SimpleSC::InstallService "PortmasterCore" "Portmaster Core" "16" "2" "$INSTDIR\portmaster-core.exe --log-dir=%PROGRAMDATA%\Portmaster\logs" "" "" "" + Pop $0 ; returns error code (0 on success) + ${If} $0 != 0 + SimpleSC::GetErrorMessage $installErr + Pop $0 + MessageBox MB_OK "Service creation failed. Error: $errorMsg" + Abort + ${EndIf} + + StrCpy $oldInstallationDir "$COMMONPROGRAMDATA\Safing\Portmaster" + StrCpy $dataDir "$COMMONPROGRAMDATA\Portmaster" + + ; Check if the folder exists + IfFileExists "$oldInstallationDir\*.*" 0 Finish + + ; Stop if the migration flag(file) already exists. + IfFileExists "$oldInstallationDir\migrated.txt" Finish 0 + + ; Copy files + DetailPrint "Migrating config from old installation: $oldInstallationDir" + + CreateDirectory "$dataDir" + CreateDirectory "$dataDir\databases" + CopyFiles "$oldInstallationDir\config.json" "$dataDir" + CopyFiles "$oldInstallationDir\databases\*.*" "$dataDir\databases" + + ; Create empty file to indicate that the data has already been migrated. + FileOpen $0 "$oldInstallationDir\migrated.txt" w + FileClose $0 + + ; Delete v1 shortcuts + RMDir /r "$SMPROGRAMS\Portmaster" + Delete "$SMSTARTUP\Portmaster Notifier.lnk" + + Finish: + +!macroend + +;-------------------------------------------------- +; Pre-uninstall hook: +; - Stops and removes the service. +!macro NSIS_HOOK_PREUNINSTALL + + DetailPrint "Stopping service" + SimpleSC::StopService "PortmasterCore" "1" "30" + Pop $0 + ${If} $0 != 0 + DetailPrint "Failed to stop PortmasterCore service. Error: $0" + ${Else} + DetailPrint "Service PortmasterCore stopped successfully." + ${EndIf} + + DetailPrint "Removing service" + SimpleSC::RemoveService "PortmasterCore" + Pop $0 + ${If} $0 != 0 + DetailPrint "Failed to remove PortmasterCore service. Error: $0" + ${Else} + DetailPrint "Service PortmasterCore removed successfully." + ${EndIf} +!macroend + diff --git a/desktop/tauri/src-tauri/templates/nsis_install_hooks.nsh b/desktop/tauri/src-tauri/templates/nsis_install_hooks.nsh deleted file mode 100644 index cc6ea2f2..00000000 --- a/desktop/tauri/src-tauri/templates/nsis_install_hooks.nsh +++ /dev/null @@ -1,37 +0,0 @@ -!macro NSIS_HOOK_PREINSTALL - ; Current working directory is \desktop\tauri\src-tauri\target\release\nsis\x64 - - SetOutPath "$INSTDIR" - - File "..\..\..\..\binary\index.json" - File "..\..\..\..\binary\portmaster-core.exe" - File "..\..\..\..\binary\portmaster-kext.sys" - File "..\..\..\..\binary\portmaster-core.dll" - File "..\..\..\..\binary\WebView2Loader.dll" - File "..\..\..\..\binary\portmaster.zip" - File "..\..\..\..\binary\assets.zip" - - SetOutPath "$COMMONPROGRAMDATA\Portmaster\intel" - - File "..\..\..\..\intel\index.json" - File "..\..\..\..\intel\base.dsdl" - File "..\..\..\..\intel\geoipv4.mmdb" - File "..\..\..\..\intel\geoipv6.mmdb" - File "..\..\..\..\intel\index.dsd" - File "..\..\..\..\intel\intermediate.dsdl" - File "..\..\..\..\intel\urgent.dsdl" - - ; restire previous state - SetOutPath "$INSTDIR" - -!macroend - -!macro NSIS_HOOK_POSTINSTALL - ExecWait 'sc.exe create PortmasterCore binPath= "$INSTDIR\portmaster-core.exe --log-dir=%PROGRAMDATA%\Portmaster\logs"' -!macroend - -!macro NSIS_HOOK_PREUNINSTALL - ExecWait 'sc.exe stop PortmasterCore' - ExecWait 'sc.exe delete PortmasterCore' -!macroend - diff --git a/packaging/windows/generate_windows_installers.ps1 b/packaging/windows/generate_windows_installers.ps1 index 6fec1212..905ea617 100644 --- a/packaging/windows/generate_windows_installers.ps1 +++ b/packaging/windows/generate_windows_installers.ps1 @@ -20,11 +20,13 @@ if (-not (Test-Path -Path $binaryDir)) { } Write-Output "Copying binary files" -Copy-Item -Force -Path "dist/download/windows_amd64/portmaster-core.exe" -Destination "$binaryDir/portmaster-core.exe" Copy-Item -Force -Path "dist/download/windows_amd64/portmaster-kext.sys" -Destination "$binaryDir/portmaster-kext.sys" -Copy-Item -Force -Path "dist/download/windows_amd64/portmaster-kext.dll" -Destination "$binaryDir/portmaster-kext.dll" +Copy-Item -Force -Path "dist/download/windows_amd64/portmaster-core.dll" -Destination "$binaryDir/portmaster-kext.dll" +Copy-Item -Force -Path "dist/binary/windows_amd64/portmaster-core.exe" -Destination "$binaryDir/portmaster-core.exe" +Copy-Item -Force -Path "dist/binary/windows_amd64/WebView2Loader.dll" -Destination "$binaryDir/WebView2Loader.dll" Copy-Item -Force -Path "dist/binary/all/portmaster.zip" -Destination "$binaryDir/portmaster.zip" Copy-Item -Force -Path "dist/binary/all/assets.zip" -Destination "$binaryDir/assets.zip" +Copy-Item -Force -Path "dist/binary/index.json" -Destination "$binaryDir/index.json" # Make sure target folder exists. if (-not (Test-Path -Path $targetDir)) { @@ -52,8 +54,7 @@ if (-not (Get-Command cargo -ErrorAction SilentlyContinue)) { } Write-Output "Downloading tauri-cli" - -Invoke-WebRequest -Uri https://github.com/tauri-apps/tauri/releases/download/tauri-cli-v2.1.0/cargo-tauri-x86_64-pc-windows-msvc.zip -OutFile tauri-cli.zip +Invoke-WebRequest -Uri https://github.com/tauri-apps/tauri/releases/download/tauri-cli-v2.2.7/cargo-tauri-x86_64-pc-windows-msvc.zip -OutFile tauri-cli.zip Expand-Archive -Force tauri-cli.zip ./tauri-cli/cargo-tauri.exe bundle