diff --git a/CHANGELOG b/CHANGELOG index c277aacf66..f2539e8094 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -216,8 +216,7 @@ v2.0.0-alpha1 (2014-02-28) * added collection status "loading" -v1.4.11 (XXXX-XX-XX) --------------------- +v1.4.11 (2014-02-27) * added SHORTEST_PATH AQL function diff --git a/CMakeLists.txt b/CMakeLists.txt index 24cae72968..2a43ef3fa9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -251,11 +251,16 @@ include_directories(${PROJECT_SOURCE_DIR}) macro (generate_root_config name) FILE(READ ${PROJECT_SOURCE_DIR}/etc/arangodb/${name}.conf.in FileContent) - - STRING(REPLACE "@PKGDATADIR@" "@ROOTDIR@/share/arangodb" + SET(SHARE_DIR "@ROOTDIR@/share/arangodb") + SET(VAR_DIR "@ROOTDIR@/var") + if (MSVC) + SET(SHARE_DIR "@ROOTDIR@/share/arangodb") + SET(VAR_DIR "@ROOTDIR@/var") + endif () + STRING(REPLACE "@PKGDATADIR@" ${SHARE_DIR} FileContent "${FileContent}") - STRING(REPLACE "@LOCALSTATEDIR@" "@ROOTDIR@/var" + STRING(REPLACE "@LOCALSTATEDIR@" ${VAR_DIR} FileContent "${FileContent}") if (MSVC) @@ -748,22 +753,32 @@ if (MSVC) ############################################################################## set(CPACK_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/Installation/Windows/Templates") + set(CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL 1) + set(BITS 64) IF(CMAKE_CL_64) SET(CPACK_NSIS_INSTALL_ROOT "$PROGRAMFILES64") SET(CPACK_PACKAGE_INSTALL_REGISTRY_KEY "${CPACK_PACKAGE_NAME} ${CPACK_PACKAGE_VERSION}") - SET(CPACK_NSIS_EXTRA_PREINSTALL_COMMANDS "SetRegView 64") - # this variable was defined by eld and included in NSIS.template.in - SET(CPACK_NSIS_EXTRA_PREUNINSTALL_COMMANDS "SetRegView 64") + SET(BITS 64) ELSE() SET(CPACK_NSIS_INSTALL_ROOT "$PROGRAMFILES") SET(CPACK_PACKAGE_INSTALL_REGISTRY_KEY "${CPACK_PACKAGE_NAME} ${CPACK_PACKAGE_VERSION}") - SET(CPACK_NSIS_EXTRA_PREINSTALL_COMMANDS "SetRegView 32") - SET(CPACK_NSIS_EXTRA_PREUNINSTALL_COMMANDS "SetRegView 32") + SET(BITS 32) ENDIF() - file(TO_NATIVE_PATH "${PROJECT_SOURCE_DIR}/Installation/Windows/arangodb.bmp" ARANGO_IMG) - file(TO_NATIVE_PATH "${PROJECT_SOURCE_DIR}/Installation/Windows/arangodb.ico" ARANGO_ICON) + SET(CPACK_NSIS_EXTRA_PREINSTALL_COMMANDS "SetRegView ${BITS}") + # SetRegView controlls where die regkeys are written to + # SetRegView 32 writes the keys into Wow6432 + # this variable was defined by eld and included in NSIS.template.in + SET(CPACK_NSIS_EXTRA_PREUNINSTALL_COMMANDS + " SetRegView ${BITS} + SimpleSC::StopService 'ArangoDB' 0 30 + SimpleSC::RemoveService 'ArangoDB' + " + ) + + file(TO_NATIVE_PATH "${PROJECT_SOURCE_DIR}/Installation/Windows/Icons/arangodb.bmp" ARANGO_IMG) + file(TO_NATIVE_PATH "${PROJECT_SOURCE_DIR}/Installation/Windows/Icons/arangodb.ico" ARANGO_ICON) STRING(REGEX REPLACE "\\\\" "\\\\\\\\" ARANGO_IMG "${ARANGO_IMG}") STRING(REGEX REPLACE "\\\\" "\\\\\\\\" ARANGO_ICON "${ARANGO_ICON}") @@ -772,7 +787,7 @@ if (MSVC) message(STATUS "ARANGO_ICON: ${ARANGO_ICON}") install( - DIRECTORY "${PROJECT_SOURCE_DIR}/Installation/Windows/" + DIRECTORY "${PROJECT_SOURCE_DIR}/Installation/Windows/Icons" DESTINATION ${TRI_RESOURCEDIR}) set(CPACK_PACKAGE_ICON ${ARANGO_ICON}) @@ -783,12 +798,12 @@ if (MSVC) set(CPACK_NSIS_INSTALLED_ICON_NAME ${ARANGO_ICON}) set(CPACK_NSIS_CREATE_ICONS_EXTRA - "CreateShortCut '$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\Arango Shell.lnk' '$INSTDIR\\\\bin\\\\arangosh.exe' '' '$INSTDIR\\\\Uninstall.exe' + "CreateShortCut '$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\Arango Shell.lnk' '$INSTDIR\\\\bin\\\\arangosh.exe' '' '$INSTDIR\\\\resources\\\\arangodb.ico' '0' SW_SHOWMAXIMIZED CreateShortCut '$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\Arango Server.lnk' '$INSTDIR\\\\bin\\\\arangod.exe' '' '$INSTDIR\\\\resources\\\\arangodb.ico' '0' SW_SHOWMAXIMIZED ") - # Note, short cuts are created in $SMPROGRAMS\$STARTMENU_FOLDER but - # they are deleted from '$SMPROGRAMS\$MUI_TEMP +# Note, short cuts are created in $SMPROGRAMS\$STARTMENU_FOLDER but +# they are deleted from '$SMPROGRAMS\$MUI_TEMP set(CPACK_NSIS_DELETE_ICONS_EXTRA "Delete '$SMPROGRAMS\\\\$MUI_TEMP\\\\Arango Server.lnk' Delete '$SMPROGRAMS\\\\$MUI_TEMP\\\\Arango Shell.lnk' diff --git a/Installation/Windows/arangodb.bmp b/Installation/Windows/Icons/arangodb.bmp similarity index 100% rename from Installation/Windows/arangodb.bmp rename to Installation/Windows/Icons/arangodb.bmp diff --git a/Installation/Windows/arangodb.ico b/Installation/Windows/Icons/arangodb.ico similarity index 100% rename from Installation/Windows/arangodb.ico rename to Installation/Windows/Icons/arangodb.ico diff --git a/Installation/Windows/Plugins/NSIS_Simple_Service_Plugin_1.30/License.txt b/Installation/Windows/Plugins/NSIS_Simple_Service_Plugin_1.30/License.txt new file mode 100644 index 0000000000..1d2b6f4e11 --- /dev/null +++ b/Installation/Windows/Plugins/NSIS_Simple_Service_Plugin_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/Installation/Windows/Plugins/NSIS_Simple_Service_Plugin_1.30/Readme.txt b/Installation/Windows/Plugins/NSIS_Simple_Service_Plugin_1.30/Readme.txt new file mode 100644 index 0000000000..e8fe6bcf27 --- /dev/null +++ b/Installation/Windows/Plugins/NSIS_Simple_Service_Plugin_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/Installation/Windows/Plugins/NSIS_Simple_Service_Plugin_1.30/SimpleSC.dll b/Installation/Windows/Plugins/NSIS_Simple_Service_Plugin_1.30/SimpleSC.dll new file mode 100644 index 0000000000..d61a12b662 Binary files /dev/null and b/Installation/Windows/Plugins/NSIS_Simple_Service_Plugin_1.30/SimpleSC.dll differ diff --git a/Installation/Windows/Plugins/NSIS_Simple_Service_Plugin_1.30/Source/LSASecurityControl.pas b/Installation/Windows/Plugins/NSIS_Simple_Service_Plugin_1.30/Source/LSASecurityControl.pas new file mode 100644 index 0000000000..e199b891ee --- /dev/null +++ b/Installation/Windows/Plugins/NSIS_Simple_Service_Plugin_1.30/Source/LSASecurityControl.pas @@ -0,0 +1,258 @@ +{ +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 Budde (http://www.speed-soft.de). + +SimpleSC - NSIS Service Control Plugin is written, published and maintaned by +Rainer Budde (rainer@speed-soft.de). +} +unit LSASecurityControl; + +interface + +uses + Windows, SysUtils; + + 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, PChar(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, PChar(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/Installation/Windows/Plugins/NSIS_Simple_Service_Plugin_1.30/Source/NSIS.pas b/Installation/Windows/Plugins/NSIS_Simple_Service_Plugin_1.30/Source/NSIS.pas new file mode 100644 index 0000000000..356d26cbde --- /dev/null +++ b/Installation/Windows/Plugins/NSIS_Simple_Service_Plugin_1.30/Source/NSIS.pas @@ -0,0 +1,126 @@ +{ + Original Code from + (C) 2001 - Peter Windridge + + Code in seperate 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 + windows; + +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; + 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; + +procedure Init(const hwndParent: HWND; const string_size: integer; const variables: PChar; const stacktop: pointer); +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); +begin + g_stringsize := string_size; + g_hwndParent := hwndParent; + g_stacktop := stacktop; + g_variables := variables; +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); +begin + MessageBox(g_hwndParent, PChar(text), PChar(caption), buttons); +end; + +begin +end. diff --git a/Installation/Windows/Plugins/NSIS_Simple_Service_Plugin_1.30/Source/ServiceControl.pas b/Installation/Windows/Plugins/NSIS_Simple_Service_Plugin_1.30/Source/ServiceControl.pas new file mode 100644 index 0000000000..4e3ef9e4f8 --- /dev/null +++ b/Installation/Windows/Plugins/NSIS_Simple_Service_Plugin_1.30/Source/ServiceControl.pas @@ -0,0 +1,1525 @@ +{ +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 Budde (http://www.speed-soft.de). + +SimpleSC - NSIS Service Control Plugin is written, published and maintaned by +Rainer Budde (rainer@speed-soft.de). +} +unit ServiceControl; + +interface + +uses + Windows, SysUtils, WinSvc, 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 := Windows.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) + 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 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 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 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: PQueryServiceConfig; +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: PQueryServiceConfig; +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; +const + SERVICE_CONFIG_DESCRIPTION = 1; +type + TServiceDescription = record + lpDescription: PAnsiChar; + end; + PServiceDescription = ^TServiceDescription; +var + QueryServiceConfig2: function(hService: SC_HANDLE; dwInfoLevel: DWORD; pBuffer: Pointer; cbBufSize: DWORD; var cbBytesNeeded: Cardinal): BOOL; stdcall; + ManagerHandle: SC_HANDLE; + ServiceHandle: SC_HANDLE; + LockHandle: SC_LOCK; + ServiceDescription: PServiceDescription; + BytesNeeded: Cardinal; +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 + @QueryServiceConfig2 := GetProcAddress(GetModuleHandle(advapi32), 'QueryServiceConfig2A'); + + if Assigned(@QueryServiceConfig2) 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, ServiceDescription, BytesNeeded, BytesNeeded) then + Description := ServiceDescription.lpDescription + else + Result := System.GetLastError; + + FreeMem(ServiceDescription); + end + else + Result := System.GetLastError; + + 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: PQueryServiceConfig; +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; +const + SERVICE_CONFIG_FAILURE_ACTIONS = 2; +type + TServiceAction = record + aType: DWORD; + Delay: DWORD; + end; + + TServiceActions = array[0..2] of TServiceAction; + + TServiceFailureAction = record + dwResetPeriod: DWORD; + lpRebootMsg: PWideChar; + lpCommand: PWideChar; + cActions: DWORD; + lpsaActions: ^TServiceActions; + end; + PServiceFailureAction = ^TServiceFailureAction; +var + QueryServiceConfig2: function(hService: SC_HANDLE; dwInfoLevel: DWORD; pBuffer: Pointer; cbBufSize: DWORD; var cbBytesNeeded: Cardinal): BOOL; stdcall; + ManagerHandle: SC_HANDLE; + ServiceHandle: SC_HANDLE; + LockHandle: SC_LOCK; + ServiceFailureAction: PServiceFailureAction; + BytesNeeded: Cardinal; +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 + // Unicode must be used because the ANSI function returns an invalid buffer + @QueryServiceConfig2 := GetProcAddress(GetModuleHandle(advapi32), 'QueryServiceConfig2W'); + + if Assigned(@QueryServiceConfig2) 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, ServiceFailureAction, BytesNeeded, BytesNeeded) then + begin + ResetPeriod := ServiceFailureAction.dwResetPeriod; + RebootMessage := ServiceFailureAction.lpRebootMsg; + Command :=ServiceFailureAction.lpCommand; + + if ServiceFailureAction.cActions >= 1 then + begin + Action1 := ServiceFailureAction.lpsaActions[0].aType; + ActionDelay1 := ServiceFailureAction.lpsaActions[0].Delay; + end; + + if ServiceFailureAction.cActions >= 2 then + begin + Action2 := ServiceFailureAction.lpsaActions[1].aType; + ActionDelay2 := ServiceFailureAction.lpsaActions[1].Delay; + end; + + if ServiceFailureAction.cActions >= 3 then + begin + Action3 := ServiceFailureAction.lpsaActions[2].aType; + ActionDelay3 := ServiceFailureAction.lpsaActions[2].Delay; + end; + end + else + Result := System.GetLastError; + + FreeMem(ServiceFailureAction); + end + else + Result := System.GetLastError; + + 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; +const + SERVICE_CONFIG_FAILURE_ACTIONS_FLAG = 4; +type + + TServiceFailureActionsFlag = record + fFailureActionsOnNonCrashFailures: BOOL; + end; + PServiceFailureActionsFlag = ^TServiceFailureActionsFlag; + +var + QueryServiceConfig2: function(hService: SC_HANDLE; dwInfoLevel: DWORD; pBuffer: Pointer; cbBufSize: DWORD; var cbBytesNeeded: Cardinal): BOOL; stdcall; + ManagerHandle: SC_HANDLE; + ServiceHandle: SC_HANDLE; + LockHandle: SC_LOCK; + ServiceFailureActionsFlag: PServiceFailureActionsFlag; + BytesNeeded: Cardinal; +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 + // Unicode must be used because the ANSI function returns an invalid buffer + @QueryServiceConfig2 := GetProcAddress(GetModuleHandle(advapi32), 'QueryServiceConfig2W'); + + if Assigned(@QueryServiceConfig2) 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, ServiceFailureActionsFlag, BytesNeeded, BytesNeeded) then + FailureActionsOnNonCrashFailures := Boolean(ServiceFailureActionsFlag.fFailureActionsOnNonCrashFailures) + else + Result := System.GetLastError; + + FreeMem(ServiceFailureActionsFlag); + end + else + Result := System.GetLastError; + + 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; +const + SERVICE_CONFIG_DELAYED_AUTO_START_INFO = 3; +type + + TServiceDelayedAutoStartInfo = record + fDelayedAutostart: BOOL; + end; + PServiceDelayedAutoStartInfo = ^TServiceDelayedAutoStartInfo; + +var + QueryServiceConfig2: function(hService: SC_HANDLE; dwInfoLevel: DWORD; pBuffer: Pointer; cbBufSize: DWORD; var cbBytesNeeded: Cardinal): BOOL; stdcall; + ManagerHandle: SC_HANDLE; + ServiceHandle: SC_HANDLE; + LockHandle: SC_LOCK; + ServiceDelayedAutoStartInfo: PServiceDelayedAutoStartInfo; + BytesNeeded: Cardinal; +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 + // Unicode must be used because the ANSI function returns an invalid buffer + @QueryServiceConfig2 := GetProcAddress(GetModuleHandle(advapi32), 'QueryServiceConfig2W'); + + if Assigned(@QueryServiceConfig2) 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, ServiceDelayedAutoStartInfo, BytesNeeded, BytesNeeded) then + DelayedAutostart := Boolean(ServiceDelayedAutoStartInfo.fDelayedAutostart) + else + Result := System.GetLastError; + + FreeMem(ServiceDelayedAutoStartInfo); + end + else + Result := System.GetLastError; + + 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; +const + SERVICE_CONFIG_DESCRIPTION = 1; +var + ChangeServiceConfig2: function(hService: SC_HANDLE; dwInfoLevel: DWORD; lpInfo: Pointer): BOOL; stdcall; + 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 + @ChangeServiceConfig2 := GetProcAddress(GetModuleHandle(advapi32), 'ChangeServiceConfig2A'); + + if Assigned(@ChangeServiceConfig2) then + begin + if not ChangeServiceConfig2(ServiceHandle, SERVICE_CONFIG_DESCRIPTION, @Description) then + Result := System.GetLastError; + 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 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; +const + SERVICE_CONFIG_FAILURE_ACTIONS = 2; + SC_ACTION_RESTART = 1; +type + + TServiceAction = record + aType: DWORD; + Delay: DWORD; + end; + + TServiceActions = array[0..2] of TServiceAction; + + TServiceFailureAction = record + dwResetPeriod: DWORD; + lpRebootMsg: PAnsiChar; + lpCommand: PAnsiChar; + cActions: DWORD; + lpsaActions: ^TServiceActions; + end; + +var + ChangeServiceConfig2: function(hService: SC_HANDLE; dwInfoLevel: DWORD; lpInfo: Pointer): BOOL; stdcall; + ManagerHandle: SC_HANDLE; + ServiceHandle: SC_HANDLE; + LockHandle: SC_LOCK; + ServiceFailureAction: TServiceFailureAction; + ServiceActions: TServiceActions; + ServiceAccessType: Integer; +begin + Result := 0; + + if (Action1 = SC_ACTION_RESTART) or (Action2 = SC_ACTION_RESTART) or (Action3 = SC_ACTION_RESTART) then + ServiceAccessType := SERVICE_CHANGE_CONFIG or SERVICE_START + else + ServiceAccessType := SERVICE_CHANGE_CONFIG; + + ServiceActions[0].aType := Action1; + ServiceActions[0].Delay := ActionDelay1; + ServiceActions[1].aType := Action2; + ServiceActions[1].Delay := ActionDelay2; + ServiceActions[2].aType := Action3; + ServiceActions[2].Delay := ActionDelay3; + + ServiceFailureAction.dwResetPeriod := ResetPeriod; + ServiceFailureAction.lpRebootMsg := PAnsiChar(RebootMessage); + ServiceFailureAction.lpCommand := PAnsiChar(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 + @ChangeServiceConfig2 := GetProcAddress(GetModuleHandle(advapi32), 'ChangeServiceConfig2A'); + + if Assigned(@ChangeServiceConfig2) then + begin + if not ChangeServiceConfig2(ServiceHandle, SERVICE_CONFIG_FAILURE_ACTIONS, @ServiceFailureAction) then + Result := System.GetLastError; + 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 SetServiceFailureFlag(ServiceName: String; FailureActionsOnNonCrashFailures: Boolean): Integer; +const + SERVICE_CONFIG_FAILURE_ACTIONS_FLAG = 4; +type + + TServiceFailureActionsFlag = record + fFailureActionsOnNonCrashFailures: BOOL; + end; + +var + ChangeServiceConfig2: function(hService: SC_HANDLE; dwInfoLevel: DWORD; lpInfo: Pointer): BOOL; stdcall; + ManagerHandle: SC_HANDLE; + ServiceHandle: SC_HANDLE; + LockHandle: SC_LOCK; + ServiceFailureActionsFlag: TServiceFailureActionsFlag; +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 + @ChangeServiceConfig2 := GetProcAddress(GetModuleHandle(advapi32), 'ChangeServiceConfig2A'); + + if Assigned(@ChangeServiceConfig2) then + begin + if not ChangeServiceConfig2(ServiceHandle, SERVICE_CONFIG_FAILURE_ACTIONS_FLAG, @ServiceFailureActionsFlag) then + Result := System.GetLastError; + 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 SetServiceDelayedAutoStartInfo(ServiceName: String; DelayedAutostart: Boolean): Integer; +const + SERVICE_CONFIG_DELAYED_AUTO_START_INFO = 3; +type + + TServiceDelayedAutoStartInfo = record + fDelayedAutostart: BOOL; + end; + +var + ChangeServiceConfig2: function(hService: SC_HANDLE; dwInfoLevel: DWORD; lpInfo: Pointer): BOOL; stdcall; + ManagerHandle: SC_HANDLE; + ServiceHandle: SC_HANDLE; + LockHandle: SC_LOCK; + ServiceDelayedAutoStartInfo: TServiceDelayedAutoStartInfo; +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 + @ChangeServiceConfig2 := GetProcAddress(GetModuleHandle(advapi32), 'ChangeServiceConfig2A'); + + if Assigned(@ChangeServiceConfig2) then + begin + if not ChangeServiceConfig2(ServiceHandle, SERVICE_CONFIG_DELAYED_AUTO_START_INFO, @ServiceDelayedAutoStartInfo) then + Result := System.GetLastError; + 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 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 + PUsername := PChar(Username); + + 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/Installation/Windows/Plugins/NSIS_Simple_Service_Plugin_1.30/Source/SimpleSC.cfg b/Installation/Windows/Plugins/NSIS_Simple_Service_Plugin_1.30/Source/SimpleSC.cfg new file mode 100644 index 0000000000..123914e50f --- /dev/null +++ b/Installation/Windows/Plugins/NSIS_Simple_Service_Plugin_1.30/Source/SimpleSC.cfg @@ -0,0 +1,35 @@ +-$A8 +-$B- +-$C+ +-$D+ +-$E- +-$F- +-$G+ +-$H+ +-$I+ +-$J- +-$K- +-$L+ +-$M- +-$N+ +-$O- +-$P+ +-$Q- +-$R- +-$S- +-$T- +-$U- +-$V+ +-$W- +-$X+ +-$YD +-$Z1 +-cg +-AWinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; +-H+ +-W+ +-M +-$M16384,1048576 +-K$00400000 +-LE"c:\programme\borland\delphi6\Projects\Bpl" +-LN"c:\programme\borland\delphi6\Projects\Bpl" diff --git a/Installation/Windows/Plugins/NSIS_Simple_Service_Plugin_1.30/Source/SimpleSC.dof b/Installation/Windows/Plugins/NSIS_Simple_Service_Plugin_1.30/Source/SimpleSC.dof new file mode 100644 index 0000000000..19d14a66bd --- /dev/null +++ b/Installation/Windows/Plugins/NSIS_Simple_Service_Plugin_1.30/Source/SimpleSC.dof @@ -0,0 +1,92 @@ +[FileVersion] +Version=6.0 +[Compiler] +A=8 +B=0 +C=1 +D=1 +E=0 +F=0 +G=1 +H=1 +I=1 +J=0 +K=0 +L=1 +M=0 +N=1 +O=0 +P=1 +Q=0 +R=0 +S=0 +T=0 +U=0 +V=1 +W=0 +X=1 +Y=1 +Z=1 +ShowHints=1 +ShowWarnings=1 +UnitAliases=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; +[Linker] +MapFile=0 +OutputObjs=0 +ConsoleApp=1 +DebugInfo=0 +RemoteSymbols=0 +MinStackSize=16384 +MaxStackSize=1048576 +ImageBase=4194304 +ExeDescription= +[Directories] +OutputDir= +UnitOutputDir= +PackageDLLOutputDir= +PackageDCPOutputDir= +SearchPath= +Packages=vcl;rtl;vclx;VclSmp;vclshlctrls;dbrtl;adortl;vcldb;qrpt;bdertl;vcldbx;dsnap;cds;bdecds;teeui;teedb;tee;teeqr;ibxpress;visualclx;visualdbclx;vclie;xmlrtl;inet;inetdbbde;inetdbxpress;inetdb;nmfast;dbexpress;dbxcds;dclOffice2k;soaprtl;Jcl;VirtualTreesD6;VirtualShellToolsD6;VirtualExplorerListviewExD6;ThemeManagerD6;JclVcl;JvCoreD6R;JvSystemD6R;JvStdCtrlsD6R;JvAppFrmD6R;JvBandsD6R;JvDBD6R;JvDlgsD6R;JvBDED6R;JvCmpD6R;JvCryptD6R;JvCtrlsD6R;JvCustomD6R;JvDockingD6R;JvDotNetCtrlsD6R;JvEDID6R;JvGlobusD6R;JvHMID6R;JvInterpreterD6R;JvJansD6R;JvManagedThreadsD6R;JvMMD6R;JvNetD6R;JvPageCompsD6R;JvPluginD6R;JvPrintPreviewD6R;JvRuntimeDesignD6R;JvTimeFrameworkD6R;JvUIBD6R;JvValidatorsD6R;JvWizardD6R;JvXPCtrlsD6R;FModPackage;NetBrowserPackage;ThreadCopyPackage;TMSMenusD6;DSPack_D6;SNTPServer +Conditionals= +DebugSourceDirs= +UsePackages=0 +[Parameters] +RunParams= +HostApplication=C:\Programme\Borland\Delphi6\Lib\Usr\RB\NSIS Simple Service Control\Project1.exe +Launcher= +UseLauncher=0 +DebugCWD= +[Language] +ActiveLang= +ProjectLang= +RootDir= +[Version Info] +IncludeVerInfo=0 +AutoIncBuild=0 +MajorVer=1 +MinorVer=0 +Release=0 +Build=0 +Debug=0 +PreRelease=0 +Special=0 +Private=0 +DLL=0 +Locale=1031 +CodePage=1252 +[Version Info Keys] +CompanyName= +FileDescription= +FileVersion=1.0.0.0 +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion=1.0.0.0 +Comments= +[Excluded Packages] +c:\programme\borland\delphi6\Projects\Bpl\SNTPServer.bpl=(Unbenannt) +[HistoryLists\hlUnitAliases] +Count=1 +Item0=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; diff --git a/Installation/Windows/Plugins/NSIS_Simple_Service_Plugin_1.30/Source/SimpleSC.dpr b/Installation/Windows/Plugins/NSIS_Simple_Service_Plugin_1.30/Source/SimpleSC.dpr new file mode 100644 index 0000000000..1ef6494735 --- /dev/null +++ b/Installation/Windows/Plugins/NSIS_Simple_Service_Plugin_1.30/Source/SimpleSC.dpr @@ -0,0 +1,601 @@ +library SimpleSC; + +uses + NSIS, Windows, ServiceControl, LSASecurityControl, SysUtils; + +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 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 ExistsService; +exports GrantServiceLogonPrivilege; +exports RemoveServiceLogonPrivilege; +exports GetErrorMessage; + +end. diff --git a/Installation/Windows/Plugins/Readme.txt b/Installation/Windows/Plugins/Readme.txt new file mode 100644 index 0000000000..c7a2429053 --- /dev/null +++ b/Installation/Windows/Plugins/Readme.txt @@ -0,0 +1,7 @@ +Every sub directory has to be a plugin directory which is +inlcluded in to the installation script of arango. + +The plugins are NOT needed for compilation of any arango component + +At moment we use only the plugin SimpleSerice whic help us to start +as service diff --git a/Installation/Windows/Templates/NSIS.InstallOptions.ini.in b/Installation/Windows/Templates/NSIS.InstallOptions.ini.in new file mode 100755 index 0000000000..a8d4a47280 --- /dev/null +++ b/Installation/Windows/Templates/NSIS.InstallOptions.ini.in @@ -0,0 +1,46 @@ +[Settings] +NumFields=5 + +[Field 1] +Type=label +Text=By default @CPACK_PACKAGE_INSTALL_DIRECTORY@ does not add its directory to the system PATH. +Left=0 +Right=-1 +Top=0 +Bottom=20 + +[Field 2] +Type=radiobutton +Text=Install @CPACK_PACKAGE_NAME@ as Service into default directory +Left=0 +Right=-1 +Top=30 +Bottom=40 +State=1 + +[Field 3] +Type=radiobutton +Text=Install @CPACK_PACKAGE_NAME@ as into configurable directory +Left=0 +Right=-1 +Top=40 +Bottom=50 +State=0 + +[Field 4] +Type=radiobutton +Text=install @CPACK_PACKAGE_NAME@ for current user +Left=0 +Right=-1 +Top=50 +Bottom=60 +State=0 + +[Field 5] +Type=CheckBox +Text=Create @CPACK_PACKAGE_NAME@ Desktop Icon +Left=0 +Right=-1 +Top=80 +Bottom=90 +State=0 diff --git a/Installation/Windows/Templates/NSIS.template.in b/Installation/Windows/Templates/NSIS.template.in index 098802f4d2..496dda4674 100755 --- a/Installation/Windows/Templates/NSIS.template.in +++ b/Installation/Windows/Templates/NSIS.template.in @@ -1,4 +1,11 @@ ; CPack install script designed for a nmake build +;!addplugindir 'c:\\\\Program Files (x86)\\\\NSIS\Plugins\\\\Simple_Service' +!addplugindir '..\..\..\..\Installation\Windows\Plugins\NSIS_Simple_Service_Plugin_1.30' + +;-------------------------------- +; Include LogicLib for more readable code + !include "LogicLib.nsh" + ;-------------------------------- ; You must define these values @@ -19,6 +26,9 @@ Var ADD_TO_PATH_CURRENT_USER Var INSTALL_DESKTOP Var IS_DEFAULT_INSTALLDIR +; Variables for definition of instdir + VAR TRI_INSTALL_AS_SERVICE + VAR TRI_INSTALL_SINGLE_USER ;-------------------------------- ;Include Modern UI @@ -551,6 +561,7 @@ FunctionEnd !insertmacro MUI_PAGE_LICENSE "@CPACK_RESOURCE_FILE_LICENSE@" Page custom InstallOptionsPage + !define MUI_PAGE_CUSTOMFUNCTION_PRE default_installation_directory !insertmacro MUI_PAGE_DIRECTORY ;Start Menu Folder Page Configuration @@ -721,7 +732,14 @@ Section "-Core installation" !insertmacro MUI_STARTMENU_WRITE_END + @CPACK_NSIS_EXTRA_INSTALL_COMMANDS@ + StrCmp $TRI_INSTALL_AS_SERVICE '1' 0 nothing + SimpleSC::StopService 'ArangoDB' 0 30 + SimpleSC::RemoveService 'ArangoDB' + SimpleSC::InstallService 'ArangoDB' 'ArangoDB' '16' '2' '"$INSTDIR\bin\arangod.exe" --start-service' '' '' '' + SimpleSC::StartService 'ArangoDB' '' 30 + nothing: SectionEnd @@ -740,31 +758,68 @@ Function InstallOptionsPage !insertmacro MUI_INSTALLOPTIONS_DISPLAY "NSIS.InstallOptions.ini" FunctionEnd +;------------------------ +; Create +Function ArangoPreInstallationOptionsPage + !insertmacro MUI_HEADER_TEXT "@CPACK_NSIS_PACKAGE_NAME@ als Service?" "Install @CPACK_NSIS_PACKAGE_NAME@ as Service?" + !insertmacro MUI_INSTALLOPTIONS_DISPLAY "NSIS.ArangoDB.ini" +FunctionEnd + +;-------------------------------- +Function default_installation_directory +; Read variables which defines if arango should be installed as Service + !insertmacro MUI_INSTALLOPTIONS_READ $TRI_INSTALL_AS_SERVICE "NSIS.InstallOptions.ini" "Field 2" "State" + !insertmacro MUI_INSTALLOPTIONS_READ $0 "NSIS.InstallOptions.ini" "Field 2" "State" + !insertmacro MUI_INSTALLOPTIONS_READ $TRI_INSTALL_SINGLE_USER "NSIS.InstallOptions.ini" "Field 4" "State" + + StrCmp $TRI_INSTALL_AS_SERVICE '1' 0 checkSingleUser + WriteRegExpandStr HKCC "Software\@CPACK_NSIS_PACKAGE_NAME@" "type" "Service" + SetShellVarContext all + Abort + checkSingleUser: + StrCmp $TRI_INSTALL_SINGLE_USER '1' 0 all_users + WriteRegExpandStr HKCC "Software\@CPACK_NSIS_PACKAGE_NAME@" "type" "SingleUser" + SetShellVarContext current + StrCpy $INSTDIR "$DOCUMENTS\@CPACK_PACKAGE_INSTALL_DIRECTORY@" + Return + all_users: + WriteRegExpandStr HKCC "Software\@CPACK_NSIS_PACKAGE_NAME@" "type" "Service" + SetShellVarContext all + StrCpy $TRI_INSTALL_AS_SERVICE '1' +FunctionEnd + ;-------------------------------- ; determine admin versus local install Function un.onInit - ClearErrors - UserInfo::GetName - IfErrors noLM - Pop $0 - UserInfo::GetAccountType - Pop $1 - StrCmp $1 "Admin" 0 +3 +; ClearErrors +; UserInfo::GetName +; IfErrors noLM +; Pop $0 +; UserInfo::GetAccountType +; Pop $1 +; StrCmp $1 "Admin" 0 +3 +; SetShellVarContext all +; MessageBox MB_OK 'User "$0" is in the Admin group' +; Goto done +; StrCmp $1 "Power" 0 +3 +; SetShellVarContext all +; MessageBox MB_OK 'User "$0" is in the Power Users group' +; Goto done +; +; noLM: +; ;Get installation folder from registry if available +; +; done: + + ReadRegStr $0 HKCC "Software\@CPACK_NSIS_PACKAGE_NAME@" "type" + StrCmp $0 "Service" 0 +3 SetShellVarContext all - ;MessageBox MB_OK 'User "$0" is in the Admin group' - Goto done - StrCmp $1 "Power" 0 +3 - SetShellVarContext all - ;MessageBox MB_OK 'User "$0" is in the Power Users group' - Goto done - - noLM: - ;Get installation folder from registry if available - - done: - + Goto tri_done + SetShellVarContext current + tri_done: + FunctionEnd ;--- Add/Remove callback functions: --- @@ -823,6 +878,17 @@ Section "Uninstall" ;MessageBox MB_OK "Install to desktop: $INSTALL_DESKTOP " @CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS@ + StrCmp $TRI_INSTALL_AS_SERVICE '1' 0 nothing + SimpleSC::StopService 'ArangoDB' 0 30 + SimpleSC::RemoveService 'ArangoDB' + Pop $0 ; returns an errorcode (<>0) otherwise success (0) + IntCmp $0 0 Done +1 +1 + Push $0 + SimpleSC::GetErrorMessage + Pop $0 + MessageBox MB_OK 'Stopping ArangoDB fails - Reason: $0' + Done: + nothing: ;Remove files we installed. ;Keep the list of directories here in sync with the File commands above. @@ -886,6 +952,7 @@ Section "Uninstall" secondStartMenuDeleteLoopDone: DeleteRegKey /ifempty SHCTX "Software\@CPACK_PACKAGE_VENDOR@\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" + DeleteRegKey HKCC "Software\@CPACK_NSIS_PACKAGE_NAME@" Push $INSTDIR\bin StrCmp $DO_NOT_ADD_TO_PATH_ "1" doNotRemoveFromPath 0 diff --git a/arangod/V8Server/V8PeriodicJob.cpp b/arangod/V8Server/V8PeriodicJob.cpp index 6dfe58cae7..6b66126ae0 100644 --- a/arangod/V8Server/V8PeriodicJob.cpp +++ b/arangod/V8Server/V8PeriodicJob.cpp @@ -134,7 +134,7 @@ bool V8PeriodicJob::beginShutdown () { /// {@inheritDoc} //////////////////////////////////////////////////////////////////////////////// -void V8PeriodicJob::handleError (triagens::basics::TriagensError const& ex) { +void V8PeriodicJob::handleError (TriagensError const& ex) { } // ----------------------------------------------------------------------------- diff --git a/lib/BasicsC/files.c b/lib/BasicsC/files.c index 461331c198..669b283fe8 100644 --- a/lib/BasicsC/files.c +++ b/lib/BasicsC/files.c @@ -1969,14 +1969,13 @@ void TRI_SetUserTempPath (char* path) { } //////////////////////////////////////////////////////////////////////////////// -/// @brief locate the installation directory -/// +/// @brief locate the installation directory in the given rootKey +/// @param rootKey should be: either HKEY_CURRENT_USER or HKEY_LOCAL_MASCHINE /// Will always end in a directory separator. //////////////////////////////////////////////////////////////////////////////// #if _WIN32 - -char* TRI_LocateInstallDirectory () { +char * __LocateInstallDirectory_In(HKEY rootKey) { DWORD dwType; char szPath[1023]; DWORD dwDataSize; @@ -1987,25 +1986,45 @@ char* TRI_LocateInstallDirectory () { // open the key for reading long lResult = RegOpenKeyEx( - HKEY_LOCAL_MACHINE, - "SOFTWARE\\triAGENS GmbH\\ArangoDB " TRI_VERSION, - 0, - KEY_READ, - &key); + rootKey, + "SOFTWARE\\triAGENS GmbH\\ArangoDB " TRI_VERSION, + 0, + KEY_READ, + &key); if (lResult == ERROR_SUCCESS) { + // read the version value + lResult = RegQueryValueEx(key, "", NULL, &dwType, (BYTE*)szPath, &dwDataSize); - // read the version value - lResult = RegQueryValueEx(key, "", NULL, &dwType, (BYTE*)szPath, &dwDataSize); + if (lResult == ERROR_SUCCESS) { + return TRI_Concatenate2String(szPath, "\\"); // TODO check if it already ends in \\ or / + } - if (lResult == ERROR_SUCCESS) { - return TRI_Concatenate2String(szPath, "\\"); // TODO check if it already ends in \\ or / + RegCloseKey(key); } - RegCloseKey(key); - } - return NULL; + +} +#endif + +//////////////////////////////////////////////////////////////////////////////// +/// @brief locate the installation directory +/// we look for the configuration first in HKEY_CURRENT_USER (arango was installed +/// for a single user) +/// when we don't find anything when look in HKEY_LOCAL_MACHINE (arango was +/// installed as service) +/// Will always end in a directory separator. +//////////////////////////////////////////////////////////////////////////////// + +#if _WIN32 +char* TRI_LocateInstallDirectory () { + char * directory = __LocateInstallDirectory_In(HKEY_CURRENT_USER); + + if (!directory) { + directory = __LocateInstallDirectory_In(HKEY_LOCAL_MACHINE); + } + return directory; } #else