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