diff --git a/API-Server/api-server.py b/Controller/check_alive_time.py similarity index 100% rename from API-Server/api-server.py rename to Controller/check_alive_time.py diff --git a/Services/alive_check.exe b/Services/alive_check.exe deleted file mode 100644 index 1eedb9b..0000000 Binary files a/Services/alive_check.exe and /dev/null differ diff --git a/Services/entpacktes_verzeichnis/nssm-2.24/ChangeLog.txt b/Services/entpacktes_verzeichnis/nssm-2.24/ChangeLog.txt deleted file mode 100644 index ea2b5ff..0000000 --- a/Services/entpacktes_verzeichnis/nssm-2.24/ChangeLog.txt +++ /dev/null @@ -1,241 +0,0 @@ -Changes since 2.23 ------------------- - * NSSM once again calls TerminateProcess() correctly. - -Changes since 2.22 ------------------- - * NSSM no longer clutters the event log with "The specified - procedure could not be found" on legacy Windows releases. - - * Fixed failure to set a local username to run the service. - -Changes since 2.21 ------------------- - * Existing services can now be managed using the GUI - or on the command line. - - * NSSM can now set the priority class and processor - affinity of the managed application. - - * NSSM can now apply an unconditional delay before - restarting the application. - - * NSSM can now optionally rotate existing files when - redirecting I/O. - - * Unqualified path names are now relative to the - application startup directory when redirecting I/O. - - * NSSM can now set the service display name, description, - startup type and log on details. - - * All services now receive a standard console window, - allowing them to read input correctly (if running in - interactive mode). - -Changes since 2.20 ------------------- - * Services installed from the GUI no longer have incorrect - AppParameters set in the registry. - -Changes since 2.19 ------------------- - * Services installed from the commandline without using the - GUI no longer have incorrect AppStopMethod* registry - entries set. - -Changes since 2.18 ------------------- - * Support AppEnvironmentExtra to append to the environment - instead of replacing it. - - * The GUI is significantly less sucky. - -Changes since 2.17 ------------------- - * Timeouts for each shutdown method can be configured in - the registry. - - * The GUI is slightly less sucky. - -Changes since 2.16 ------------------- - * NSSM can now redirect the service's I/O streams to any path - capable of being opened by CreateFile(). - - * Allow building on Visual Studio Express. - - * Silently ignore INTERROGATE control. - - * Try to send Control-C events to console applications when - shutting them down. - -Changes since 2.15 ------------------- - * Fixed case where NSSM could kill unrelated processes when - shutting down. - -Changes since 2.14 ------------------- - * NSSM is now translated into Italian. - - * Fixed GUI not allowing paths longer than 256 characters. - -Changes since 2.13 ------------------- - * Fixed default GUI language being French not English. - -Changes since 2.12 ------------------- - * Fixed failure to run on Windows 2000. - -Changes since 2.11 ------------------- - * NSSM is now translated into French. - - * Really ensure systems recovery actions can happen. - - The change supposedly introduced in v2.4 to allow service recovery - actions to be activated when the application exits gracefully with - a non-zero error code didn't actually work. - -Changes since 2.10 ------------------- - * Support AppEnvironment for compatibility with srvany. - -Changes since 2.9 ------------------ - * Fixed failure to compile messages.mc in paths containing spaces. - - * Fixed edge case with CreateProcess(). - - Correctly handle the case where the application executable is under - a path which contains space and an executable sharing the initial - part of that path (up to a space) exists. - -Changes since 2.8 ------------------ - * Fixed failure to run on Windows versions prior to Vista. - -Changes since 2.7 ------------------ - * Read Application, AppDirectory and AppParameters before each restart so - a change to any one doesn't require restarting NSSM itself. - - * Fixed messages not being sent to the event log correctly in some - cases. - - * Try to handle (strictly incorrect) quotes in AppDirectory. - - Windows directories aren't allowed to contain quotes so CreateProcess() - will fail if the AppDirectory is quoted. Note that it succeeds even if - Application itself is quoted as the application plus parameters are - interpreted as a command line. - - * Fixed failed to write full arguments to AppParameters when - installing a service. - - * Throttle restarts. - - Back off from restarting the application immediately if it starts - successfully but exits too soon. The default value of "too soon" is - 1500 milliseconds. This can be configured by adding a DWORD value - AppThrottle to the registry. - - Handle resume messages from the service console to restart the - application immediately even if it is throttled. - - * Try to kill the process tree gracefully. - - Before calling TerminateProcess() on all processes assocatiated with - the monitored application, enumerate all windows and threads and - post appropriate messages to them. If the application bothers to - listen for such messages it has a chance to shut itself down gracefully. - -Changes since 2.6 ------------------ - * Handle missing registry values. - - Warn if AppParameters is missing. Warn if AppDirectory is missing or - unset and choose a fallback directory. - First try to find the parent directory of the application. If that - fails, eg because the application path is just "notepad" or something, - start in the Windows directory. - - * Kill process tree when stopping service. - - Ensure that all child processes of the monitored application are - killed when the service stops by recursing through all running - processes and terminating those whose parent is the application - or one of its descendents. - -Changes since 2.5 ------------------ - * Removed incorrect ExpandEnvironmentStrings() error. - - A log_event() call was inadvertently left in the code causing an error - to be set to the eventlog saying that ExpandEnvironmentStrings() had - failed when it had actually succeeded. - -Changes since 2.4 ------------------ - * Allow use of REG_EXPAND_SZ values in the registry. - - * Don't suicide on exit status 0 by default. - - Suiciding when the application exits 0 will cause recovery actions to be - taken. Usually this is inappropriate. Only suicide if there is an - explicit AppExit value for 0 in the registry. - - Technically such behaviour could be abused to do something like run a - script after successful completion of a service but in most cases a - suicide is undesirable when no actual failure occurred. - - * Don't hang if startup parameters couldn't be determined. - Instead, signal that the service entered the STOPPED state. - Set START_PENDING state prior to actual startup. - -Changes since 2.3 ------------------ - * Ensure systems recovery actions can happen. - - In Windows versions earlier than Vista the service manager would only - consider a service failed (and hence eligible for recovery action) if - the service exited without setting its state to SERVICE_STOPPED, even if - it signalled an error exit code. - In Vista and later the service manager can be configured to treat a - graceful shutdown with error code as a failure but this is not the - default behaviour. - - Try to configure the service manager to use the new behaviour when - starting the service so users who set AppExit to Exit can use recovery - actions as expected. - - Also recognise the new AppExit option Suicide for use on pre-Vista - systems. When AppExit is Suicide don't stop the service but exit - inelegantly, which should be seen as a failure. - -Changes since 2.2 ------------------ - * Send properly formatted messages to the event log. - - * Fixed truncation of very long path lengths in the registry. - -Changes since 2.1 ------------------ - * Decide how to handle application exit. - - When the service exits with exit code n look in - HKLM\SYSTEM\CurrentControlSet\Services\\Parameters\AppExit\, - falling back to the unnamed value if no such code is listed. Parse the - (string) value of this entry as follows: - - Restart: Start the application again (NSSM default). - Ignore: Do nothing (srvany default). - Exit: Stop the service. - -Changes since 2.0 ------------------ - * Added support for building a 64-bit executable. - - * Added project files for newer versions of Visual Studio. diff --git a/Services/entpacktes_verzeichnis/nssm-2.24/README.txt b/Services/entpacktes_verzeichnis/nssm-2.24/README.txt deleted file mode 100644 index 11fbac1..0000000 --- a/Services/entpacktes_verzeichnis/nssm-2.24/README.txt +++ /dev/null @@ -1,692 +0,0 @@ -NSSM: The Non-Sucking Service Manager -Version 2.24, 2014-08-31 - -NSSM is a service helper program similar to srvany and cygrunsrv. It can -start any application as an NT service and will restart the service if it -fails for any reason. - -NSSM also has a graphical service installer and remover. - -Full documentation can be found online at - - http://nssm.cc/ - -Since version 2.0, the GUI can be bypassed by entering all appropriate -options on the command line. - -Since version 2.1, NSSM can be compiled for x64 platforms. -Thanks Benjamin Mayrargue. - -Since version 2.2, NSSM can be configured to take different actions -based on the exit code of the managed application. - -Since version 2.3, NSSM logs to the Windows event log more elegantly. - -Since version 2.5, NSSM respects environment variables in its parameters. - -Since version 2.8, NSSM tries harder to shut down the managed application -gracefully and throttles restart attempts if the application doesn't run -for a minimum amount of time. - -Since version 2.11, NSSM respects srvany's AppEnvironment parameter. - -Since version 2.13, NSSM is translated into French. -Thanks François-Régis Tardy. - -Since version 2.15, NSSM is translated into Italian. -Thanks Riccardo Gusmeroli. - -Since version 2.17, NSSM can try to shut down console applications by -simulating a Control-C keypress. If they have installed a handler routine -they can clean up and shut down gracefully on receipt of the event. - -Since version 2.17, NSSM can redirect the managed application's I/O streams -to an arbitrary path. - -Since version 2.18, NSSM can be configured to wait a user-specified amount -of time for the application to exit when shutting down. - -Since version 2.19, many more service options can be configured with the -GUI installer as well as via the registry. - -Since version 2.19, NSSM can add to the service's environment by setting -AppEnvironmentExtra in place of or in addition to the srvany-compatible -AppEnvironment. - -Since version 2.22, NSSM can set the managed application's process priority -and CPU affinity. - -Since version 2.22, NSSM can apply an unconditional delay before restarting -an application which has exited. - -Since version 2.22, NSSM can rotate existing output files when redirecting I/O. - -Since version 2.22, NSSM can set service display name, description, startup -type, log on details and dependencies. - -Since version 2.22, NSSM can manage existing services. - - -Usage ------ -In the usage notes below, arguments to the program may be written in angle -brackets and/or square brackets. means you must insert the -appropriate string and [] means the string is optional. See the -examples below... - -Note that everywhere appears you may substitute the -service's display name. - - -Installation using the GUI --------------------------- -To install a service, run - - nssm install - -You will be prompted to enter the full path to the application you wish -to run and any command line options to pass to that application. - -Use the system service manager (services.msc) to control advanced service -properties such as startup method and desktop interaction. NSSM may -support these options at a later time... - - -Installation using the command line ------------------------------------ -To install a service, run - - nssm install [] - -NSSM will then attempt to install a service which runs the named application -with the given options (if you specified any). - -Don't forget to enclose paths in "quotes" if they contain spaces! - -If you want to include quotes in the options you will need to """quote""" the -quotes. - - -Managing the service --------------------- -NSSM will launch the application listed in the registry when you send it a -start signal and will terminate it when you send a stop signal. So far, so -much like srvany. But NSSM is the Non-Sucking service manager and can take -action if/when the application dies. - -With no configuration from you, NSSM will try to restart itself if it notices -that the application died but you didn't send it a stop signal. NSSM will -keep trying, pausing between each attempt, until the service is successfully -started or you send it a stop signal. - -NSSM will pause an increasingly longer time between subsequent restart attempts -if the service fails to start in a timely manner, up to a maximum of four -minutes. This is so it does not consume an excessive amount of CPU time trying -to start a failed application over and over again. If you identify the cause -of the failure and don't want to wait you can use the Windows service console -(where the service will be shown in Paused state) to send a continue signal to -NSSM and it will retry within a few seconds. - -By default, NSSM defines "a timely manner" to be within 1500 milliseconds. -You can change the threshold for the service by setting the number of -milliseconds as a REG_DWORD value in the registry at -HKLM\SYSTEM\CurrentControlSet\Services\\Parameters\AppThrottle. - -Alternatively, NSSM can pause for a configurable amount of time before -attempting to restart the application even if it successfully ran for the -amount of time specified by AppThrottle. NSSM will consult the REG_DWORD value -at HKLM\SYSTEM\CurrentControlSet\Services\\Parameters\AppRestartDelay -for the number of milliseconds to wait before attempting a restart. If -AppRestartDelay is set and the application is determined to be subject to -throttling, NSSM will pause the service for whichever is longer of the -configured restart delay and the calculated throttle period. - -If AppRestartDelay is missing or invalid, only throttling will be applied. - -NSSM will look in the registry under -HKLM\SYSTEM\CurrentControlSet\Services\\Parameters\AppExit for -string (REG_EXPAND_SZ) values corresponding to the exit code of the application. -If the application exited with code 1, for instance, NSSM will look for a -string value under AppExit called "1" or, if it does not find it, will -fall back to the AppExit (Default) value. You can find out the exit code -for the application by consulting the system event log. NSSM will log the -exit code when the application exits. - -Based on the data found in the registry, NSSM will take one of three actions: - -If the value data is "Restart" NSSM will try to restart the application as -described above. This is its default behaviour. - -If the value data is "Ignore" NSSM will not try to restart the application -but will continue running itself. This emulates the (usually undesirable) -behaviour of srvany. The Windows Services console would show the service -as still running even though the application has exited. - -If the value data is "Exit" NSSM will exit gracefully. The Windows Services -console would show the service as stopped. If you wish to provide -finer-grained control over service recovery you should use this code and -edit the failure action manually. Please note that Windows versions prior -to Vista will not consider such an exit to be a failure. On older versions -of Windows you should use "Suicide" instead. - -If the value data is "Suicide" NSSM will simulate a crash and exit without -informing the service manager. This option should only be used for -pre-Vista systems where you wish to apply a service recovery action. Note -that if the monitored application exits with code 0, NSSM will only honour a -request to suicide if you explicitly configure a registry key for exit code 0. -If only the default action is set to Suicide NSSM will instead exit gracefully. - - -Application priority --------------------- -NSSM can set the priority class of the managed application. NSSM will look in -the registry under HKLM\SYSTEM\CurrentControlSet\Services\\Parameters -for the REG_DWORD entry AppPriority. Valid values correspond to arguments to -SetPriorityClass(). If AppPriority() is missing or invalid the -application will be launched with normal priority. - - -Processor affinity ------------------- -NSSM can set the CPU affinity of the managed application. NSSM will look in -the registry under HKLM\SYSTEM\CurrentControlSet\Services\\Parameters -for the REG_SZ entry AppAffinity. It should specify a comma-separated listed -of zero-indexed processor IDs. A range of processors may optionally be -specified with a dash. No other characters are allowed in the string. - -For example, to specify the first; second; third and fifth CPUs, an appropriate -AppAffinity would be 0-2,4. - -If AppAffinity is missing or invalid, NSSM will not attempt to restrict the -application to specific CPUs. - -Note that the 64-bit version of NSSM can configure a maximum of 64 CPUs in this -way and that the 32-bit version can configure a maxium of 32 CPUs even when -running on 64-bit Windows. - - -Stopping the service --------------------- -When stopping a service NSSM will attempt several different methods of killing -the monitored application, each of which can be disabled if necessary. - -First NSSM will attempt to generate a Control-C event and send it to the -application's console. Batch scripts or console applications may intercept -the event and shut themselves down gracefully. GUI applications do not have -consoles and will not respond to this method. - -Secondly NSSM will enumerate all windows created by the application and send -them a WM_CLOSE message, requesting a graceful exit. - -Thirdly NSSM will enumerate all threads created by the application and send -them a WM_QUIT message, requesting a graceful exit. Not all applications' -threads have message queues; those which do not will not respond to this -method. - -Finally NSSM will call TerminateProcess() to request that the operating -system forcibly terminate the application. TerminateProcess() cannot be -trapped or ignored, so in most circumstances the application will be killed. -However, there is no guarantee that it will have a chance to perform any -tidyup operations before it exits. - -Any or all of the methods above may be disabled. NSSM will look for the -HKLM\SYSTEM\CurrentControlSet\Services\\Parameters\AppStopMethodSkip -registry value which should be of type REG_DWORD set to a bit field describing -which methods should not be applied. - - If AppStopMethodSkip includes 1, Control-C events will not be generated. - If AppStopMethodSkip includes 2, WM_CLOSE messages will not be posted. - If AppStopMethodSkip includes 4, WM_QUIT messages will not be posted. - If AppStopMethodSkip includes 8, TerminateProcess() will not be called. - -If, for example, you knew that an application did not respond to Control-C -events and did not have a thread message queue, you could set AppStopMethodSkip -to 5 and NSSM would not attempt to use those methods to stop the application. - -Take great care when including 8 in the value of AppStopMethodSkip. If NSSM -does not call TerminateProcess() it is possible that the application will not -exit when the service stops. - -By default NSSM will allow processes 1500ms to respond to each of the methods -described above before proceeding to the next one. The timeout can be -configured on a per-method basis by creating REG_DWORD entries in the -registry under HKLM\SYSTEM\CurrentControlSet\Services\\Parameters. - - AppStopMethodConsole - AppStopMethodWindow - AppStopMethodThreads - -Each value should be set to the number of milliseconds to wait. Please note -that the timeout applies to each process in the application's process tree, -so the actual time to shutdown may be longer than the sum of all configured -timeouts if the application spawns multiple subprocesses. - - -Console window --------------- -By default, NSSM will create a console window so that applications which -are capable of reading user input can do so - subject to the service being -allowed to interact with the desktop. - -Creation of the console can be suppressed by setting the integer (REG_DWORD) -HKLM\SYSTEM\CurrentControlSet\Services\\Parameters\AppNoConsole -registry value to 1. - - -I/O redirection ---------------- -NSSM can redirect the managed application's I/O to any path capable of being -opened by CreateFile(). This enables, for example, capturing the log output -of an application which would otherwise only write to the console or accepting -input from a serial port. - -NSSM will look in the registry under -HKLM\SYSTEM\CurrentControlSet\Services\\Parameters for the keys -corresponding to arguments to CreateFile(). All are optional. If no path is -given for a particular stream it will not be redirected. If a path is given -but any of the other values are omitted they will be receive sensible defaults. - - AppStdin: Path to receive input. - AppStdout: Path to receive output. - AppStderr: Path to receive error output. - -Parameters for CreateFile() are providing with the "AppStdinShareMode", -"AppStdinCreationDisposition" and "AppStdinFlagsAndAttributes" values (and -analogously for stdout and stderr). - -In general, if you want the service to log its output, set AppStdout and -AppStderr to the same path, eg C:\Users\Public\service.log, and it should -work. Remember, however, that the path must be accessible to the user -running the service. - - -File rotation -------------- -When using I/O redirection, NSSM can rotate existing output files prior to -opening stdout and/or stderr. An existing file will be renamed with a -suffix based on the file's last write time, to millisecond precision. For -example, the file nssm.log might be rotated to nssm-20131221T113939.457.log. - -NSSM will look in the registry under -HKLM\SYSTEM\CurrentControlSet\Services\\Parameters for REG_DWORD -entries which control how rotation happens. - -If AppRotateFiles is missing or set to 0, rotation is disabled. Any non-zero -value enables rotation. - -If AppRotateSeconds is non-zero, a file will not be rotated if its last write -time is less than the given number of seconds in the past. - -If AppRotateBytes is non-zero, a file will not be rotated if it is smaller -than the given number of bytes. 64-bit file sizes can be handled by setting -a non-zero value of AppRotateBytesHigh. - -Rotation is independent of the CreateFile() parameters used to open the files. -They will be rotated regardless of whether NSSM would otherwise have appended -or replaced them. - -NSSM can also rotate files which hit the configured size threshold while the -service is running. Additionally, you can trigger an on-demand rotation by -running the command - - nssm rotate - -On-demand rotations will happen after the next line of data is read from -the managed application, regardless of the value of AppRotateBytes. Be aware -that if the application is not particularly verbose the rotation may not -happen for some time. - -To enable online and on-demand rotation, set AppRotateOnline to a non-zero -value. - -Note that online rotation requires NSSM to intercept the application's I/O -and create the output files on its behalf. This is more complex and -error-prone than simply redirecting the I/O streams before launching the -application. Therefore online rotation is not enabled by default. - - -Environment variables ---------------------- -NSSM can replace or append to the managed application's environment. Two -multi-valued string (REG_MULTI_SZ) registry values are recognised under -HKLM\SYSTEM\CurrentControlSet\Services\\Parameters. - -AppEnvironment defines a list of environment variables which will override -the service's environment. AppEnvironmentExtra defines a list of -environment variables which will be added to the service's environment. - -Each entry in the list should be of the form KEY=VALUE. It is possible to -omit the VALUE but the = symbol is mandatory. - -Environment variables listed in both AppEnvironment and AppEnvironmentExtra -are subject to normal expansion, so it is possible, for example, to update the -system path by setting "PATH=C:\bin;%PATH%" in AppEnvironmentExtra. Variables -are expanded in the order in which they appear, so if you want to include the -value of one variable in another variable you should declare the dependency -first. - -Because variables defined in AppEnvironment override the existing -environment it is not possible to refer to any variables which were previously -defined. - -For example, the following AppEnvironment block: - - PATH=C:\Windows\System32;C:\Windows - PATH=C:\bin;%PATH% - -Would result in a PATH of "C:\bin;C:\Windows\System32;C:\Windows" as expected. - -Whereas the following AppEnvironment block: - - PATH=C:\bin;%PATH% - -Would result in a path containing only C:\bin and probably cause the -application to fail to start. - -Most people will want to use AppEnvironmentExtra exclusively. srvany only -supports AppEnvironment. - - -Managing services using the GUI -------------------------------- -NSSM can edit the settings of existing services with the same GUI that is -used to install them. Run - - nssm edit - -to bring up the GUI. - -NSSM offers limited editing capabilities for services other than those which -run NSSM itself. When NSSM is asked to edit a service which does not have -the App* registry settings described above, the GUI will allow editing only -system settings such as the service display name and description. - - -Managing services using the command line ----------------------------------------- -NSSM can retrieve or set individual service parameters from the command line. -In general the syntax is as follows, though see below for exceptions. - - nssm get - - nssm set - -Parameters can also be reset to their default values. - - nssm reset - -The parameter names recognised by NSSM are the same as the registry entry -names described above, eg AppDirectory. - -NSSM offers limited editing capabilities for Services other than those which -run NSSM itself. The parameters recognised are as follows: - - Description: Service description. - DisplayName: Service display name. - ImagePath: Path to the service executable. - ObjectName: User account which runs the service. - Name: Service key name. - Start: Service startup type. - Type: Service type. - -These correspond to the registry values under the service's key -HKLM\SYSTEM\CurrentControlSet\Services\. - - -Note that NSSM will concatenate all arguments passed on the command line -with spaces to form the value to set. Thus the following two invocations -would have the same effect. - - nssm set Description "NSSM managed service" - - nssm set Description NSSM managed service - - -Non-standard parameters ------------------------ -The AppEnvironment and AppEnvironmentExtra parameters recognise an -additional argument when querying the environment. The following syntax -will print all extra environment variables configured for a service - - nssm get AppEnvironmentExtra - -whereas the syntax below will print only the value of the CLASSPATH -variable if it is configured in the environment block, or the empty string -if it is not configured. - - nssm get AppEnvironmentExtra CLASSPATH - -When setting an environment block, each variable should be specified as a -KEY=VALUE pair in separate command line arguments. For example: - - nssm set AppEnvironment CLASSPATH=C:\Classes TEMP=C:\Temp - - -The AppExit parameter requires an additional argument specifying the exit -code to get or set. The default action can be specified with the string -Default. - -For example, to get the default exit action for a service you should run - - nssm get AppExit Default - -To get the exit action when the application exits with exit code 2, run - - nssm get AppExit 2 - -Note that if no explicit action is configured for a specified exit code, -NSSM will print the default exit action. - -To set configure the service to stop when the application exits with an -exit code of 2, run - - nssm set AppExit 2 Exit - - -The AppPriority parameter is used to set the priority class of the -managed application. Valid priorities are as follows: - - REALTIME_PRIORITY_CLASS - HIGH_PRIORITY_CLASS - ABOVE_NORMAL_PRIORITY_CLASS - NORMAL_PRIORITY_CLASS - BELOW_NORMAL_PRIORITY_CLASS - IDLE_PRIORITY_CLASS - - -The DependOnGroup and DependOnService parameters are used to query or set -the dependencies for the service. When setting dependencies, each service -or service group (preceded with the + symbol) should be specified in -separate command line arguments. For example: - - nssm set DependOnService RpcSs LanmanWorkstation - - -The Name parameter can only be queried, not set. It returns the service's -registry key name. This may be useful to know if you take advantage of -the fact that you can substitute the service's display name anywhere where -the syntax calls for . - - -The ObjectName parameter requires an additional argument only when setting -a username. The additional argument is the password of the user. - -To retrieve the username, run - - nssm get ObjectName - -To set the username and password, run - - nssm set ObjectName - -Note that the rules of argument concatenation still apply. The following -invocation is valid and will have the expected effect. - - nssm set ObjectName correct horse battery staple - -The following well-known usernames do not need a password. The password -parameter can be omitted when using them: - - "LocalSystem" aka "System" aka "NT Authority\System" - "LocalService" aka "Local Service" aka "NT Authority\Local Service" - "NetworkService" aka "Network Service" aka "NT Authority\Network Service" - - -The Start parameter is used to query or set the startup type of the service. -Valid service startup types are as follows: - - SERVICE_AUTO_START: Automatic startup at boot. - SERVICE_DELAYED_START: Delayed startup at boot. - SERVICE_DEMAND_START: Manual service startup. - SERVICE_DISABLED: The service is disabled. - -Note that SERVICE_DELAYED_START is not supported on versions of Windows prior -to Vista. NSSM will set the service to automatic startup if delayed start is -unavailable. - - -The Type parameter is used to query or set the service type. NSSM recognises -all currently documented service types but will only allow setting one of two -types: - - SERVICE_WIN32_OWN_PROCESS: A standalone service. This is the default. - SERVICE_INTERACTIVE_PROCESS: A service which can interact with the desktop. - -Note that a service may only be configured as interactive if it runs under -the LocalSystem account. The safe way to configure an interactive service -is in two stages as follows. - - nssm reset ObjectName - nssm set Type SERVICE_INTERACTIVE_PROCESS - - -Controlling services using the command line -------------------------------------------- -NSSM offers rudimentary service control features. - - nssm start - - nssm restart - - nssm stop - - nssm status - - -Removing services using the GUI -------------------------------- -NSSM can also remove services. Run - - nssm remove - -to remove a service. You will prompted for confirmation before the service -is removed. Try not to remove essential system services... - - -Removing service using the command line ---------------------------------------- -To remove a service without confirmation from the GUI, run - - nssm remove confirm - -Try not to remove essential system services... - - -Logging -------- -NSSM logs to the Windows event log. It registers itself as an event log source -and uses unique event IDs for each type of message it logs. New versions may -add event types but existing event IDs will never be changed. - -Because of the way NSSM registers itself you should be aware that you may not -be able to replace the NSSM binary if you have the event viewer open and that -running multiple instances of NSSM from different locations may be confusing if -they are not all the same version. - - -Example usage -------------- -To install an Unreal Tournament server: - - nssm install UT2004 c:\games\ut2004\system\ucc.exe server - -To run the server as the "games" user: - - nssm set UT2004 ObjectName games password - -To configure the server to log to a file: - - nssm set UT2004 AppStdout c:\games\ut2004\service.log - -To restrict the server to a single CPU: - - nssm set UT2004 AppAffinity 0 - -To remove the server: - - nssm remove UT2004 confirm - -To find out the service name of a service with a display name: - - nssm get "Background Intelligent Transfer Service" Name - - -Building NSSM from source -------------------------- -NSSM is known to compile with Visual Studio 2008 and later. Older Visual -Studio releases may or may not work if you install an appropriate SDK and -edit the nssm.vcproj and nssm.sln files to set a lower version number. -They are known not to work with default settings. - -NSSM will also compile with Visual Studio 2010 but the resulting executable -will not run on versions of Windows older than XP SP2. If you require -compatiblity with older Windows releases you should change the Platform -Toolset to v90 in the General section of the project's Configuration -Properties. - - -Credits -------- -Thanks to Bernard Loh for finding a bug with service recovery. -Thanks to Benjamin Mayrargue (www.softlion.com) for adding 64-bit support. -Thanks to Joel Reingold for spotting a command line truncation bug. -Thanks to Arve Knudsen for spotting that child processes of the monitored -application could be left running on service shutdown, and that a missing -registry value for AppDirectory confused NSSM. -Thanks to Peter Wagemans and Laszlo Keresztfalvi for suggesting throttling -restarts. -Thanks to Eugene Lifshitz for finding an edge case in CreateProcess() and for -advising how to build messages.mc correctly in paths containing spaces. -Thanks to Rob Sharp for pointing out that NSSM did not respect the -AppEnvironment registry value used by srvany. -Thanks to Szymon Nowak for help with Windows 2000 compatibility. -Thanks to François-Régis Tardy and Gildas le Nadan for French translation. -Thanks to Emilio Frini for spotting that French was inadvertently set as -the default language when the user's display language was not translated. -Thanks to Riccardo Gusmeroli and Marco Certelli for Italian translation. -Thanks to Eric Cheldelin for the inspiration to generate a Control-C event -on shutdown. -Thanks to Brian Baxter for suggesting how to escape quotes from the command -prompt. -Thanks to Russ Holmann for suggesting that the shutdown timeout be configurable. -Thanks to Paul Spause for spotting a bug with default registry entries. -Thanks to BUGHUNTER for spotting more GUI bugs. -Thanks to Doug Watson for suggesting file rotation. -Thanks to Арслан Сайдуганов for suggesting setting process priority. -Thanks to Robert Middleton for suggestion and draft implementation of process -affinity support. -Thanks to Andrew RedzMax for suggesting an unconditional restart delay. -Thanks to Bryan Senseman for noticing that applications with redirected stdout -and/or stderr which attempt to read from stdin would fail. -Thanks to Czenda Czendov for help with Visual Studio 2013 and Server 2012R2. -Thanks to Alessandro Gherardi for reporting and draft fix of the bug whereby -the second restart of the application would have a corrupted environment. -Thanks to Hadrien Kohl for suggesting to disable the console window's menu. -Thanks to Allen Vailliencourt for noticing bugs with configuring the service to -run under a local user account. -Thanks to Sam Townsend for noticing a regression with TerminateProcess(). - -Licence -------- -NSSM is public domain. You may unconditionally use it and/or its source code -for any purpose you wish. diff --git a/Services/entpacktes_verzeichnis/nssm-2.24/src/account.cpp b/Services/entpacktes_verzeichnis/nssm-2.24/src/account.cpp deleted file mode 100644 index 70bfa3e..0000000 --- a/Services/entpacktes_verzeichnis/nssm-2.24/src/account.cpp +++ /dev/null @@ -1,346 +0,0 @@ -#include "nssm.h" - -#include - -extern imports_t imports; - -/* Open Policy object. */ -int open_lsa_policy(LSA_HANDLE *policy) { - LSA_OBJECT_ATTRIBUTES attributes; - ZeroMemory(&attributes, sizeof(attributes)); - - NTSTATUS status = LsaOpenPolicy(0, &attributes, POLICY_ALL_ACCESS, policy); - if (status) { - print_message(stderr, NSSM_MESSAGE_LSAOPENPOLICY_FAILED, error_string(LsaNtStatusToWinError(status))); - return 1; - } - - return 0; -} - -/* Look up SID for an account. */ -int username_sid(const TCHAR *username, SID **sid, LSA_HANDLE *policy) { - LSA_HANDLE handle; - if (! policy) { - policy = &handle; - if (open_lsa_policy(policy)) return 1; - } - - /* - LsaLookupNames() can't look up .\username but can look up - %COMPUTERNAME%\username. ChangeServiceConfig() writes .\username to the - registry when %COMPUTERNAME%\username is a passed as a parameter. We - need to preserve .\username when calling ChangeServiceConfig() without - changing the username, but expand to %COMPUTERNAME%\username when calling - LsaLookupNames(). - */ - TCHAR *expanded; - unsigned long expandedlen; - if (_tcsnicmp(_T(".\\"), username, 2)) { - expandedlen = (unsigned long) (_tcslen(username) + 1) * sizeof(TCHAR); - expanded = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, expandedlen); - if (! expanded) { - print_message(stderr, NSSM_MESSAGE_OUT_OF_MEMORY, _T("expanded"), _T("username_sid")); - if (policy == &handle) LsaClose(handle); - return 2; - } - memmove(expanded, username, expandedlen); - } - else { - TCHAR computername[MAX_COMPUTERNAME_LENGTH + 1]; - expandedlen = _countof(computername); - GetComputerName(computername, &expandedlen); - expandedlen += (unsigned long) _tcslen(username); - - expanded = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, expandedlen * sizeof(TCHAR)); - if (! expanded) { - print_message(stderr, NSSM_MESSAGE_OUT_OF_MEMORY, _T("expanded"), _T("username_sid")); - if (policy == &handle) LsaClose(handle); - return 2; - } - _sntprintf_s(expanded, expandedlen, _TRUNCATE, _T("%s\\%s"), computername, username + 2); - } - - LSA_UNICODE_STRING lsa_username; -#ifdef UNICODE - lsa_username.Buffer = (wchar_t *) expanded; - lsa_username.Length = (unsigned short) _tcslen(expanded) * sizeof(TCHAR); - lsa_username.MaximumLength = lsa_username.Length + sizeof(TCHAR); -#else - size_t buflen; - mbstowcs_s(&buflen, NULL, 0, expanded, _TRUNCATE); - lsa_username.MaximumLength = (unsigned short) buflen * sizeof(wchar_t); - lsa_username.Length = lsa_username.MaximumLength - sizeof(wchar_t); - lsa_username.Buffer = (wchar_t *) HeapAlloc(GetProcessHeap(), 0, lsa_username.MaximumLength); - if (lsa_username.Buffer) mbstowcs_s(&buflen, lsa_username.Buffer, lsa_username.MaximumLength, expanded, _TRUNCATE); - else { - if (policy == &handle) LsaClose(handle); - HeapFree(GetProcessHeap(), 0, expanded); - print_message(stderr, NSSM_MESSAGE_OUT_OF_MEMORY, _T("LSA_UNICODE_STRING"), _T("username_sid()")); - return 4; - } -#endif - - LSA_REFERENCED_DOMAIN_LIST *translated_domains; - LSA_TRANSLATED_SID *translated_sid; - NTSTATUS status = LsaLookupNames(*policy, 1, &lsa_username, &translated_domains, &translated_sid); -#ifndef UNICODE - HeapFree(GetProcessHeap(), 0, lsa_username.Buffer); -#endif - HeapFree(GetProcessHeap(), 0, expanded); - if (policy == &handle) LsaClose(handle); - if (status) { - LsaFreeMemory(translated_domains); - LsaFreeMemory(translated_sid); - print_message(stderr, NSSM_MESSAGE_LSALOOKUPNAMES_FAILED, username, error_string(LsaNtStatusToWinError(status))); - return 5; - } - - if (translated_sid->Use != SidTypeUser && translated_sid->Use != SidTypeWellKnownGroup) { - LsaFreeMemory(translated_domains); - LsaFreeMemory(translated_sid); - print_message(stderr, NSSM_GUI_INVALID_USERNAME, username); - return 6; - } - - LSA_TRUST_INFORMATION *trust = &translated_domains->Domains[translated_sid->DomainIndex]; - if (! trust || ! IsValidSid(trust->Sid)) { - LsaFreeMemory(translated_domains); - LsaFreeMemory(translated_sid); - print_message(stderr, NSSM_GUI_INVALID_USERNAME, username); - return 7; - } - - /* GetSidSubAuthority*() return pointers! */ - unsigned char *n = GetSidSubAuthorityCount(trust->Sid); - - /* Convert translated SID to SID. */ - *sid = (SID *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, GetSidLengthRequired(*n + 1)); - if (! *sid) { - LsaFreeMemory(translated_domains); - LsaFreeMemory(translated_sid); - print_message(stderr, NSSM_MESSAGE_OUT_OF_MEMORY, _T("SID"), _T("username_sid")); - return 8; - } - - unsigned long error; - if (! InitializeSid(*sid, GetSidIdentifierAuthority(trust->Sid), *n + 1)) { - error = GetLastError(); - HeapFree(GetProcessHeap(), 0, *sid); - LsaFreeMemory(translated_domains); - LsaFreeMemory(translated_sid); - print_message(stderr, NSSM_MESSAGE_INITIALIZESID_FAILED, username, error_string(error)); - return 9; - } - - for (unsigned char i = 0; i <= *n; i++) { - unsigned long *sub = GetSidSubAuthority(*sid, i); - if (i < *n) *sub = *GetSidSubAuthority(trust->Sid, i); - else *sub = translated_sid->RelativeId; - } - - int ret = 0; - if (translated_sid->Use == SidTypeWellKnownGroup && ! well_known_sid(*sid)) { - print_message(stderr, NSSM_GUI_INVALID_USERNAME, username); - ret = 10; - } - - LsaFreeMemory(translated_domains); - LsaFreeMemory(translated_sid); - - return ret; -} - -int username_sid(const TCHAR *username, SID **sid) { - return username_sid(username, sid, 0); -} - -int canonicalise_username(const TCHAR *username, TCHAR **canon) { - LSA_HANDLE policy; - if (open_lsa_policy(&policy)) return 1; - - SID *sid; - if (username_sid(username, &sid, &policy)) return 2; - PSID sids = { sid }; - - LSA_REFERENCED_DOMAIN_LIST *translated_domains; - LSA_TRANSLATED_NAME *translated_name; - NTSTATUS status = LsaLookupSids(policy, 1, &sids, &translated_domains, &translated_name); - if (status) { - LsaFreeMemory(translated_domains); - LsaFreeMemory(translated_name); - print_message(stderr, NSSM_MESSAGE_LSALOOKUPSIDS_FAILED, error_string(LsaNtStatusToWinError(status))); - return 3; - } - - LSA_TRUST_INFORMATION *trust = &translated_domains->Domains[translated_name->DomainIndex]; - LSA_UNICODE_STRING lsa_canon; - lsa_canon.Length = translated_name->Name.Length + trust->Name.Length + sizeof(wchar_t); - lsa_canon.MaximumLength = lsa_canon.Length + sizeof(wchar_t); - lsa_canon.Buffer = (wchar_t *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, lsa_canon.MaximumLength); - if (! lsa_canon.Buffer) { - LsaFreeMemory(translated_domains); - LsaFreeMemory(translated_name); - print_message(stderr, NSSM_MESSAGE_OUT_OF_MEMORY, _T("lsa_canon"), _T("username_sid")); - return 9; - } - - /* Buffer is wchar_t but Length is in bytes. */ - memmove((char *) lsa_canon.Buffer, trust->Name.Buffer, trust->Name.Length); - memmove((char *) lsa_canon.Buffer + trust->Name.Length, L"\\", sizeof(wchar_t)); - memmove((char *) lsa_canon.Buffer + trust->Name.Length + sizeof(wchar_t), translated_name->Name.Buffer, translated_name->Name.Length); - -#ifdef UNICODE - *canon = lsa_canon.Buffer; -#else - size_t buflen; - wcstombs_s(&buflen, NULL, 0, lsa_canon.Buffer, _TRUNCATE); - *canon = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, buflen); - if (! *canon) { - LsaFreeMemory(translated_domains); - LsaFreeMemory(translated_name); - print_message(stderr, NSSM_MESSAGE_OUT_OF_MEMORY, _T("canon"), _T("username_sid")); - return 10; - } - wcstombs_s(&buflen, *canon, buflen, lsa_canon.Buffer, _TRUNCATE); - HeapFree(GetProcessHeap(), 0, lsa_canon.Buffer); -#endif - - LsaFreeMemory(translated_domains); - LsaFreeMemory(translated_name); - - return 0; -} - -/* Do two usernames map to the same SID? */ -int username_equiv(const TCHAR *a, const TCHAR *b) { - SID *sid_a, *sid_b; - if (username_sid(a, &sid_a)) return 0; - - if (username_sid(b, &sid_b)) { - FreeSid(sid_a); - return 0; - } - - int ret = 0; - if (EqualSid(sid_a, sid_b)) ret = 1; - - FreeSid(sid_a); - FreeSid(sid_b); - - return ret; -} - -/* Does the username represent the LocalSystem account? */ -int is_localsystem(const TCHAR *username) { - if (str_equiv(username, NSSM_LOCALSYSTEM_ACCOUNT)) return 1; - if (! imports.IsWellKnownSid) return 0; - - SID *sid; - if (username_sid(username, &sid)) return 0; - - int ret = 0; - if (imports.IsWellKnownSid(sid, WinLocalSystemSid)) ret = 1; - - FreeSid(sid); - - return ret; -} - -/* - Get well-known alias for LocalSystem and friends. - Returns a pointer to a static string. DO NOT try to free it. -*/ -const TCHAR *well_known_sid(SID *sid) { - if (! imports.IsWellKnownSid) return 0; - if (imports.IsWellKnownSid(sid, WinLocalSystemSid)) return NSSM_LOCALSYSTEM_ACCOUNT; - if (imports.IsWellKnownSid(sid, WinLocalServiceSid)) return NSSM_LOCALSERVICE_ACCOUNT; - if (imports.IsWellKnownSid(sid, WinNetworkServiceSid)) return NSSM_NETWORKSERVICE_ACCOUNT; - return 0; -} - -const TCHAR *well_known_username(const TCHAR *username) { - if (! username) return NSSM_LOCALSYSTEM_ACCOUNT; - if (str_equiv(username, NSSM_LOCALSYSTEM_ACCOUNT)) return NSSM_LOCALSYSTEM_ACCOUNT; - SID *sid; - if (username_sid(username, &sid)) return 0; - - const TCHAR *well_known = well_known_sid(sid); - FreeSid(sid); - - return well_known; -} - -int grant_logon_as_service(const TCHAR *username) { - if (! username) return 0; - - /* Open Policy object. */ - LSA_OBJECT_ATTRIBUTES attributes; - ZeroMemory(&attributes, sizeof(attributes)); - - LSA_HANDLE policy; - NTSTATUS status; - - if (open_lsa_policy(&policy)) return 1; - - /* Look up SID for the account. */ - SID *sid; - if (username_sid(username, &sid, &policy)) { - LsaClose(policy); - return 2; - } - - /* - Shouldn't happen because it should have been checked before callling this function. - */ - if (well_known_sid(sid)) { - LsaClose(policy); - return 3; - } - - /* Check if the SID has the "Log on as a service" right. */ - LSA_UNICODE_STRING lsa_right; - lsa_right.Buffer = NSSM_LOGON_AS_SERVICE_RIGHT; - lsa_right.Length = (unsigned short) wcslen(lsa_right.Buffer) * sizeof(wchar_t); - lsa_right.MaximumLength = lsa_right.Length + sizeof(wchar_t); - - LSA_UNICODE_STRING *rights; - unsigned long count = ~0; - status = LsaEnumerateAccountRights(policy, sid, &rights, &count); - if (status) { - /* - If the account has no rights set LsaEnumerateAccountRights() will return - STATUS_OBJECT_NAME_NOT_FOUND and set count to 0. - */ - unsigned long error = LsaNtStatusToWinError(status); - if (error != ERROR_FILE_NOT_FOUND) { - FreeSid(sid); - LsaClose(policy); - print_message(stderr, NSSM_MESSAGE_LSAENUMERATEACCOUNTRIGHTS_FAILED, username, error_string(error)); - return 4; - } - } - - for (unsigned long i = 0; i < count; i++) { - if (rights[i].Length != lsa_right.Length) continue; - if (_wcsnicmp(rights[i].Buffer, lsa_right.Buffer, lsa_right.MaximumLength)) continue; - /* The SID has the right. */ - FreeSid(sid); - LsaFreeMemory(rights); - LsaClose(policy); - return 0; - } - LsaFreeMemory(rights); - - /* Add the right. */ - status = LsaAddAccountRights(policy, sid, &lsa_right, 1); - FreeSid(sid); - LsaClose(policy); - if (status) { - print_message(stderr, NSSM_MESSAGE_LSAADDACCOUNTRIGHTS_FAILED, error_string(LsaNtStatusToWinError(status))); - return 5; - } - - print_message(stdout, NSSM_MESSAGE_GRANTED_LOGON_AS_SERVICE, username); - return 0; -} diff --git a/Services/entpacktes_verzeichnis/nssm-2.24/src/account.h b/Services/entpacktes_verzeichnis/nssm-2.24/src/account.h deleted file mode 100644 index e6b40f0..0000000 --- a/Services/entpacktes_verzeichnis/nssm-2.24/src/account.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef ACCOUNT_H -#define ACCOUNT_H - -#include - -/* Not really an account. The canonical name is NT Authority\System. */ -#define NSSM_LOCALSYSTEM_ACCOUNT _T("LocalSystem") -/* Other well-known accounts which can start a service without a password. */ -#define NSSM_LOCALSERVICE_ACCOUNT _T("NT Authority\\LocalService") -#define NSSM_NETWORKSERVICE_ACCOUNT _T("NT Authority\\NetworkService") -/* This is explicitly a wide string. */ -#define NSSM_LOGON_AS_SERVICE_RIGHT L"SeServiceLogonRight" - -int open_lsa_policy(LSA_HANDLE *); -int username_sid(const TCHAR *, SID **, LSA_HANDLE *); -int username_sid(const TCHAR *, SID **); -int username_equiv(const TCHAR *, const TCHAR *); -int canonicalise_username(const TCHAR *, TCHAR **); -int is_localsystem(const TCHAR *); -const TCHAR *well_known_sid(SID *); -const TCHAR *well_known_username(const TCHAR *); -int grant_logon_as_service(const TCHAR *); - -#endif diff --git a/Services/entpacktes_verzeichnis/nssm-2.24/src/console.cpp b/Services/entpacktes_verzeichnis/nssm-2.24/src/console.cpp deleted file mode 100644 index 66c99ea..0000000 --- a/Services/entpacktes_verzeichnis/nssm-2.24/src/console.cpp +++ /dev/null @@ -1,175 +0,0 @@ -#include "nssm.h" - -/* See if we were launched from a console window. */ -void check_console() { - /* If we're running in a service context there will be no console window. */ - HWND console = GetConsoleWindow(); - if (! console) return; - - unsigned long pid; - if (! GetWindowThreadProcessId(console, &pid)) return; - - /* - If the process associated with the console window handle is the same as - this process, we were not launched from an existing console. The user - probably double-clicked our executable. - */ - if (GetCurrentProcessId() != pid) return; - - /* We close our new console so that subsequent messages appear in a popup. */ - FreeConsole(); -} - -/* Helpers for drawing the banner. */ -static inline void block(unsigned int a, short x, short y, unsigned long n) { - HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE); - TCHAR s = _T(' '); - - unsigned long out; - COORD c = { x, y }; - FillConsoleOutputAttribute(h, a, n, c, &out); - FillConsoleOutputCharacter(h, s, n, c, &out); -} - -static inline void R(short x, short y, unsigned long n) { - block(BACKGROUND_RED | BACKGROUND_INTENSITY, x, y, n); -} - -static inline void r(short x, short y, unsigned long n) { - block(BACKGROUND_RED, x, y, n); -} - -static inline void b(short x, short y, unsigned long n) { - block(0, x, y, n); -} - -void alloc_console(nssm_service_t *service) { - if (service->no_console) return; - - AllocConsole(); - - /* Disable accidental closure. */ - HWND window = GetConsoleWindow(); - HMENU menu = GetSystemMenu(window, false); - EnableMenuItem(menu, SC_CLOSE, MF_GRAYED); - - /* Set a title like "[NSSM] Jenkins" */ - TCHAR displayname[SERVICE_NAME_LENGTH]; - unsigned long len = _countof(displayname); - SC_HANDLE services = open_service_manager(SC_MANAGER_CONNECT); - if (services) { - if (! GetServiceDisplayName(services, service->name, displayname, &len)) ZeroMemory(displayname, sizeof(displayname)); - CloseServiceHandle(services); - } - if (! displayname[0]) _sntprintf_s(displayname, _countof(displayname), _TRUNCATE, _T("%s"), service->name); - - TCHAR title[65535]; - _sntprintf_s(title, _countof(title), _TRUNCATE, _T("[%s] %s"), NSSM, displayname); - SetConsoleTitle(title); - - /* Draw the NSSM logo on the console window. */ - short y = 0; - - b(0, y, 80); - y++; - - b(0, y, 80); - y++; - - b(0, y, 80); - y++; - - b(0, y, 80); - y++; - - b(0, y, 80); - r(18, y, 5); r(28, y, 4); r(41, y, 4); r(68, y, 1); - R(6, y, 5); R(19, y, 4); R(29, y, 1); R(32, y, 3); R(42, y, 1); R(45, y, 3); R(52, y, 5); R(69, y, 4); - y++; - - b(0, y, 80); - r(8, y, 4); r(20, y, 1); r(28, y, 1); r(33, y, 3); r(41, y, 1); r(46, y, 3); r (57, y, 1); - R(9, y, 2); R(21, y, 1); R(27, y, 1); R(34, y, 1); R(40, y, 1); R(47, y, 1); R(54, y, 3); R(68, y, 3); - y++; - - b(0, y, 80); - r(12, y, 1); r(20, y, 1); r(26, y, 1); r(34, y, 2); r(39, y, 1); r(47, y, 2); r(67, y, 2); - R(9, y, 3); R(21, y, 1); R(27, y, 1); R(40, y, 1); R(54, y, 1); R(56, y, 2); R(67, y, 1); R(69, y, 2); - y++; - - b(0, y, 80); - r(9, y, 1); r(20, y, 1); r(26, y, 1); r (35, y, 1); r(39, y, 1); r(48, y, 1); r(58, y, 1); - R(10, y, 3); R(21, y, 1); R(27, y, 1); R(40, y, 1); R(54, y, 1); R(56, y, 2); R(67, y, 1); R(69, y, 2); - y++; - - b(0, y, 80); - r(9, y, 1); r(56, y, 1); r(66, y, 2); - R(11, y, 3); R(21, y, 1); R(26, y, 2); R(39, y, 2); R(54, y, 1); R(57, y, 2); R(69, y, 2); - y++; - - b(0, y, 80); - r(9, y, 1); r(26, y, 1); r(39, y, 1); r(59, y, 1); - R(12, y, 3); R(21, y, 1); R(27, y, 2); R(40, y, 2); R(54, y, 1); R(57, y, 2); R(66, y, 1); R(69, y, 2); - y++; - - b(0, y, 80); - r(9, y, 1); r(12, y, 4); r(30, y, 1); r(43, y, 1); r(57, y, 1); r(65, y, 2); - R(13, y, 2); R(21, y, 1); R(27, y, 3); R(40, y, 3); R(54, y, 1); R(58, y, 2); R(69, y, 2); - y++; - - b(0, y, 80); - r(9, y, 1); r(13, y, 4); r(27, y, 7); r(40, y, 7); - R(14, y, 2); R(21, y, 1); R(28, y, 5); R(41, y, 5); R(54, y, 1); R(58, y, 2); R(65, y, 1); R(69, y, 2); - y++; - - b(0, y, 80); - r(9, y, 1); r(60, y, 1); r(65, y, 1); - R(14, y, 3); R(21, y, 1); R(29, y, 6); R(42, y, 6); R(54, y, 1); R(58, y, 2); R(69, y, 2); - y++; - - b(0, y, 80); - r(9, y, 1); r(31, y, 1); r(44, y, 1); r(58, y, 1); r(64, y, 1); - R(15, y, 3); R(21, y, 1); R(32, y, 4); R(45, y, 4); R(54, y, 1); R(59, y, 2); R(69, y, 2); - y++; - - b(0, y, 80); - r(9, y, 1); r(33, y, 1); r(46, y, 1); r(61, y, 1); r(64, y, 1); - R(16, y, 3); R(21, y, 1); R(34, y, 2); R(47, y, 2); R(54, y, 1); R(59, y, 2); R(69, y, 2); - y++; - - b(0, y, 80); - r(9, y, 1); r(16, y, 4); r(36, y, 1); r(49, y, 1); r(59, y, 1); r(63, y, 1); - R(17, y, 2); R(21, y, 1); R(34, y, 2); R(47, y, 2); R(54, y, 1); R(60, y, 2); R(69, y, 2); - y++; - - b(0, y, 80); - r(9, y, 1); r(17, y, 4); r(26, y, 1); r(36, y, 1); r(39, y, 1); r(49, y, 1); - R(18, y, 2); R(21, y, 1); R(35, y, 1); R(48, y, 1); R(54, y, 1); R(60, y, 2); R(63, y, 1); R(69, y, 2); - y++; - - b(0, y, 80); - r(26, y, 2); r(39, y, 2); r(63, y, 1); - R(9, y, 1); R(18, y, 4); R(35, y, 1); R(48, y, 1); R(54, y, 1); R(60, y, 3); R(69, y, 2); - y++; - - b(0, y, 80); - r(34, y, 1); r(47, y, 1); r(60, y, 1); - R(9, y, 1); R(19, y, 3); R(26, y, 2); R(35, y, 1); R(39, y, 2); R(48, y, 1); R(54, y, 1); R(61, y, 2); R(69, y, 2); - y++; - - b(0, y, 80); - r(8, y, 1); r(35, y, 1); r(48, y, 1); r(62, y, 1); r(71, y, 1); - R(9, y, 1); R(20, y, 2); R(26, y, 3); R(34, y, 1); R(39, y, 3); R(47, y, 1); R(54, y, 1); R(61, y, 1); R(69, y, 2); - y++; - - b(0, y, 80); - r(11, y, 1); r(26, y, 1); r(28, y, 5); r(39, y, 1); r(41, y, 5); r(51, y, 7); r(61, y, 1); r(66, y, 8); - R(7, y, 4); R(21, y, 1); R(29, y, 1); R(33, y, 1); R(42, y, 1); R(46, y, 1); R(52, y, 5); R(67, y, 7); - y++; - - b(0, y, 80); - y++; - - b(0, y, 80); - y++; -} diff --git a/Services/entpacktes_verzeichnis/nssm-2.24/src/console.h b/Services/entpacktes_verzeichnis/nssm-2.24/src/console.h deleted file mode 100644 index 8aa8966..0000000 --- a/Services/entpacktes_verzeichnis/nssm-2.24/src/console.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef CONSOLE_H -#define CONSOLE_H - -void check_console(); -void alloc_console(nssm_service_t *); - -#endif diff --git a/Services/entpacktes_verzeichnis/nssm-2.24/src/env.cpp b/Services/entpacktes_verzeichnis/nssm-2.24/src/env.cpp deleted file mode 100644 index 063b60f..0000000 --- a/Services/entpacktes_verzeichnis/nssm-2.24/src/env.cpp +++ /dev/null @@ -1,173 +0,0 @@ -#include "nssm.h" - -/* Copy an environment block. */ -TCHAR *copy_environment_block(TCHAR *env) { - unsigned long len; - - if (! env) return 0; - for (len = 0; env[len]; len++) while (env[len]) len++; - if (! len++) return 0; - - TCHAR *newenv = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, len * sizeof(TCHAR)); - if (! newenv) { - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, _T("environment"), _T("copy_environment_block()"), 0); - return 0; - } - - memmove(newenv, env, len * sizeof(TCHAR)); - return newenv; -} - -/* - The environment block starts with variables of the form - =C:=C:\Windows\System32 which we ignore. -*/ -TCHAR *useful_environment(TCHAR *rawenv) { - TCHAR *env = rawenv; - - if (env) { - while (*env == _T('=')) { - for ( ; *env; env++); - env++; - } - } - - return env; -} - -/* Expand an environment variable. Must call HeapFree() on the result. */ -TCHAR *expand_environment_string(TCHAR *string) { - unsigned long len; - - len = ExpandEnvironmentStrings(string, 0, 0); - if (! len) { - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_EXPANDENVIRONMENTSTRINGS_FAILED, string, error_string(GetLastError()), 0); - return 0; - } - - TCHAR *ret = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, len * sizeof(TCHAR)); - if (! ret) { - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, _T("ExpandEnvironmentStrings()"), _T("expand_environment_string"), 0); - return 0; - } - - if (! ExpandEnvironmentStrings(string, ret, len)) { - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_EXPANDENVIRONMENTSTRINGS_FAILED, string, error_string(GetLastError()), 0); - HeapFree(GetProcessHeap(), 0, ret); - return 0; - } - - return ret; -} - -/* - Set all the environment variables from an environment block in the current - environment or remove all the variables in the block from the current - environment. -*/ -static int set_environment_block(TCHAR *env, bool set) { - int ret = 0; - - TCHAR *s, *t; - for (s = env; *s; s++) { - for (t = s; *t && *t != _T('='); t++); - if (*t == _T('=')) { - *t = _T('\0'); - if (set) { - TCHAR *expanded = expand_environment_string(++t); - if (expanded) { - if (! SetEnvironmentVariable(s, expanded)) ret++; - HeapFree(GetProcessHeap(), 0, expanded); - } - else { - if (! SetEnvironmentVariable(s, t)) ret++; - } - } - else { - if (! SetEnvironmentVariable(s, NULL)) ret++; - } - for (t++ ; *t; t++); - } - s = t; - } - - return ret; -} - -int set_environment_block(TCHAR *env) { - return set_environment_block(env, true); -} - -static int unset_environment_block(TCHAR *env) { - return set_environment_block(env, false); -} - -/* Remove all variables from the process environment. */ -int clear_environment() { - TCHAR *rawenv = GetEnvironmentStrings(); - TCHAR *env = useful_environment(rawenv); - - int ret = unset_environment_block(env); - - if (rawenv) FreeEnvironmentStrings(rawenv); - - return ret; -} - -/* Set the current environment to exactly duplicate an environment block. */ -int duplicate_environment(TCHAR *rawenv) { - int ret = clear_environment(); - TCHAR *env = useful_environment(rawenv); - ret += set_environment_block(env); - return ret; -} - -/* - Verify an environment block. - Returns: 1 if environment is invalid. - 0 if environment is OK. - -1 on error. -*/ -int test_environment(TCHAR *env) { - TCHAR path[PATH_LENGTH]; - GetModuleFileName(0, path, _countof(path)); - STARTUPINFO si; - ZeroMemory(&si, sizeof(si)); - si.cb = sizeof(si); - PROCESS_INFORMATION pi; - ZeroMemory(&pi, sizeof(pi)); - unsigned long flags = CREATE_SUSPENDED; -#ifdef UNICODE - flags |= CREATE_UNICODE_ENVIRONMENT; -#endif - - /* - Try to relaunch ourselves but with the candidate environment set. - Assuming no solar flare activity, the only reason this would fail is if - the environment were invalid. - */ - if (CreateProcess(0, path, 0, 0, 0, flags, env, 0, &si, &pi)) { - TerminateProcess(pi.hProcess, 0); - } - else { - unsigned long error = GetLastError(); - if (error == ERROR_INVALID_PARAMETER) return 1; - else return -1; - } - - return 0; -} - -/* - Duplicate an environment block returned by GetEnvironmentStrings(). - Since such a block is by definition readonly, and duplicate_environment() - modifies its inputs, this function takes a copy of the input and operates - on that. -*/ -void duplicate_environment_strings(TCHAR *env) { - TCHAR *newenv = copy_environment_block(env); - if (! newenv) return; - - duplicate_environment(newenv); - HeapFree(GetProcessHeap(), 0, newenv); -} diff --git a/Services/entpacktes_verzeichnis/nssm-2.24/src/env.h b/Services/entpacktes_verzeichnis/nssm-2.24/src/env.h deleted file mode 100644 index 021ff4f..0000000 --- a/Services/entpacktes_verzeichnis/nssm-2.24/src/env.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef ENV_H -#define ENV_H - -TCHAR *copy_environment_block(TCHAR *); -TCHAR *useful_environment(TCHAR *); -TCHAR *expand_environment_string(TCHAR *); -int set_environment_block(TCHAR *); -int clear_environment(); -int duplicate_environment(TCHAR *); -int test_environment(TCHAR *); -void duplicate_environment_strings(TCHAR *); - -#endif diff --git a/Services/entpacktes_verzeichnis/nssm-2.24/src/event.cpp b/Services/entpacktes_verzeichnis/nssm-2.24/src/event.cpp deleted file mode 100644 index cbe7fe6..0000000 --- a/Services/entpacktes_verzeichnis/nssm-2.24/src/event.cpp +++ /dev/null @@ -1,111 +0,0 @@ -#include "nssm.h" - -#define NSSM_SOURCE _T("nssm") -#define NSSM_ERROR_BUFSIZE 65535 -#define NSSM_NUM_EVENT_STRINGS 16 -unsigned long tls_index; - -/* Convert error code to error string - must call LocalFree() on return value */ -TCHAR *error_string(unsigned long error) { - /* Thread-safe buffer */ - TCHAR *error_message = (TCHAR *) TlsGetValue(tls_index); - if (! error_message) { - error_message = (TCHAR *) LocalAlloc(LPTR, NSSM_ERROR_BUFSIZE); - if (! error_message) return _T(""); - TlsSetValue(tls_index, (void *) error_message); - } - - if (! FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0, error, GetUserDefaultLangID(), (TCHAR *) error_message, NSSM_ERROR_BUFSIZE, 0)) { - if (! FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0, error, 0, (TCHAR *) error_message, NSSM_ERROR_BUFSIZE, 0)) { - if (_sntprintf_s(error_message, NSSM_ERROR_BUFSIZE, _TRUNCATE, _T("system error %lu"), error) < 0) return 0; - } - } - return error_message; -} - -/* Convert message code to format string */ -TCHAR *message_string(unsigned long error) { - TCHAR *ret; - if (! FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_IGNORE_INSERTS, 0, error, GetUserDefaultLangID(), (LPTSTR) &ret, NSSM_ERROR_BUFSIZE, 0)) { - if (! FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_IGNORE_INSERTS, 0, error, 0, (LPTSTR) &ret, NSSM_ERROR_BUFSIZE, 0)) { - ret = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, 32 * sizeof(TCHAR)); - if (_sntprintf_s(ret, NSSM_ERROR_BUFSIZE, _TRUNCATE, _T("system error %lu"), error) < 0) return 0; - } - } - return ret; -} - -/* Log a message to the Event Log */ -void log_event(unsigned short type, unsigned long id, ...) { - va_list arg; - int count; - TCHAR *s; - TCHAR *strings[NSSM_NUM_EVENT_STRINGS]; - - /* Open event log */ - HANDLE handle = RegisterEventSource(0, NSSM_SOURCE); - if (! handle) return; - - /* Log it */ - count = 0; - va_start(arg, id); - while ((s = va_arg(arg, TCHAR *)) && count < NSSM_NUM_EVENT_STRINGS - 1) strings[count++] = s; - strings[count] = 0; - va_end(arg); - ReportEvent(handle, type, 0, id, 0, count, 0, (const TCHAR **) strings, 0); - - /* Close event log */ - DeregisterEventSource(handle); -} - -/* Log a message to the console */ -void print_message(FILE *file, unsigned long id, ...) { - va_list arg; - - TCHAR *format = message_string(id); - if (! format) return; - - va_start(arg, id); - _vftprintf(file, format, arg); - va_end(arg); - - LocalFree(format); -} - -/* Show a GUI dialogue */ -int popup_message(HWND owner, unsigned int type, unsigned long id, ...) { - va_list arg; - - TCHAR *format = message_string(id); - if (! format) { - return MessageBox(0, _T("The message which was supposed to go here is missing!"), NSSM, MB_OK | MB_ICONEXCLAMATION); - } - - TCHAR blurb[NSSM_ERROR_BUFSIZE]; - va_start(arg, id); - if (_vsntprintf_s(blurb, _countof(blurb), _TRUNCATE, format, arg) < 0) { - va_end(arg); - LocalFree(format); - return MessageBox(0, _T("The message which was supposed to go here is too big!"), NSSM, MB_OK | MB_ICONEXCLAMATION); - } - va_end(arg); - - MSGBOXPARAMS params; - ZeroMemory(¶ms, sizeof(params)); - params.cbSize = sizeof(params); - params.hInstance = GetModuleHandle(0); - params.hwndOwner = owner; - params.lpszText = blurb; - params.lpszCaption = NSSM; - params.dwStyle = type; - if (type == MB_OK) { - params.dwStyle |= MB_USERICON; - params.lpszIcon = MAKEINTRESOURCE(IDI_NSSM); - } - - int ret = MessageBoxIndirect(¶ms); - - LocalFree(format); - - return ret; -} diff --git a/Services/entpacktes_verzeichnis/nssm-2.24/src/event.h b/Services/entpacktes_verzeichnis/nssm-2.24/src/event.h deleted file mode 100644 index 858cc49..0000000 --- a/Services/entpacktes_verzeichnis/nssm-2.24/src/event.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef EVENT_H -#define EVENT_H - -TCHAR *error_string(unsigned long); -TCHAR *message_string(unsigned long); -void log_event(unsigned short, unsigned long, ...); -void print_message(FILE *, unsigned long, ...); -int popup_message(HWND, unsigned int, unsigned long, ...); - -#endif diff --git a/Services/entpacktes_verzeichnis/nssm-2.24/src/gui.cpp b/Services/entpacktes_verzeichnis/nssm-2.24/src/gui.cpp deleted file mode 100644 index f3d26ca..0000000 --- a/Services/entpacktes_verzeichnis/nssm-2.24/src/gui.cpp +++ /dev/null @@ -1,1176 +0,0 @@ -#include "nssm.h" - -static enum { NSSM_TAB_APPLICATION, NSSM_TAB_DETAILS, NSSM_TAB_LOGON, NSSM_TAB_DEPENDENCIES, NSSM_TAB_PROCESS, NSSM_TAB_SHUTDOWN, NSSM_TAB_EXIT, NSSM_TAB_IO, NSSM_TAB_ROTATION, NSSM_TAB_ENVIRONMENT, NSSM_NUM_TABS }; -static HWND tablist[NSSM_NUM_TABS]; -static int selected_tab; - -static HWND dialog(const TCHAR *templ, HWND parent, DLGPROC function, LPARAM l) { - /* The caller will deal with GetLastError()... */ - HRSRC resource = FindResourceEx(0, RT_DIALOG, templ, GetUserDefaultLangID()); - if (! resource) { - if (GetLastError() != ERROR_RESOURCE_LANG_NOT_FOUND) return 0; - resource = FindResourceEx(0, RT_DIALOG, templ, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL)); - if (! resource) return 0; - } - - HGLOBAL ret = LoadResource(0, resource); - if (! ret) return 0; - - return CreateDialogIndirectParam(0, (DLGTEMPLATE *) ret, parent, function, l); -} - -static HWND dialog(const TCHAR *templ, HWND parent, DLGPROC function) { - return dialog(templ, parent, function, 0); -} - -int nssm_gui(int resource, nssm_service_t *service) { - /* Create window */ - HWND dlg = dialog(MAKEINTRESOURCE(resource), 0, nssm_dlg, (LPARAM) service); - if (! dlg) { - popup_message(0, MB_OK, NSSM_GUI_CREATEDIALOG_FAILED, error_string(GetLastError())); - return 1; - } - - /* Load the icon. */ - HANDLE icon = LoadImage(GetModuleHandle(0), MAKEINTRESOURCE(IDI_NSSM), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0); - if (icon) SendMessage(dlg, WM_SETICON, ICON_SMALL, (LPARAM) icon); - icon = LoadImage(GetModuleHandle(0), MAKEINTRESOURCE(IDI_NSSM), IMAGE_ICON, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), 0); - if (icon) SendMessage(dlg, WM_SETICON, ICON_BIG, (LPARAM) icon); - - /* Remember what the window is for. */ - SetWindowLongPtr(dlg, GWLP_USERDATA, (LONG_PTR) resource); - - /* Display the window */ - centre_window(dlg); - ShowWindow(dlg, SW_SHOW); - - /* Set service name if given */ - if (service->name[0]) { - SetDlgItemText(dlg, IDC_NAME, service->name); - /* No point making user click remove if the name is already entered */ - if (resource == IDD_REMOVE) { - HWND button = GetDlgItem(dlg, IDC_REMOVE); - if (button) { - SendMessage(button, WM_LBUTTONDOWN, 0, 0); - SendMessage(button, WM_LBUTTONUP, 0, 0); - } - } - } - - if (resource == IDD_EDIT) { - /* We'll need the service handle later. */ - SetWindowLongPtr(dlg, DWLP_USER, (LONG_PTR) service); - - /* Service name can't be edited. */ - EnableWindow(GetDlgItem(dlg, IDC_NAME), 0); - SetFocus(GetDlgItem(dlg, IDOK)); - - /* Set existing details. */ - HWND combo; - HWND list; - - /* Application tab. */ - if (service->native) SetDlgItemText(tablist[NSSM_TAB_APPLICATION], IDC_PATH, service->image); - else SetDlgItemText(tablist[NSSM_TAB_APPLICATION], IDC_PATH, service->exe); - SetDlgItemText(tablist[NSSM_TAB_APPLICATION], IDC_DIR, service->dir); - SetDlgItemText(tablist[NSSM_TAB_APPLICATION], IDC_FLAGS, service->flags); - - /* Details tab. */ - SetDlgItemText(tablist[NSSM_TAB_DETAILS], IDC_DISPLAYNAME, service->displayname); - SetDlgItemText(tablist[NSSM_TAB_DETAILS], IDC_DESCRIPTION, service->description); - combo = GetDlgItem(tablist[NSSM_TAB_DETAILS], IDC_STARTUP); - SendMessage(combo, CB_SETCURSEL, service->startup, 0); - - /* Log on tab. */ - if (service->username) { - CheckRadioButton(tablist[NSSM_TAB_LOGON], IDC_LOCALSYSTEM, IDC_ACCOUNT, IDC_ACCOUNT); - SetDlgItemText(tablist[NSSM_TAB_LOGON], IDC_USERNAME, service->username); - EnableWindow(GetDlgItem(tablist[NSSM_TAB_LOGON], IDC_INTERACT), 0); - EnableWindow(GetDlgItem(tablist[NSSM_TAB_LOGON], IDC_USERNAME), 1); - EnableWindow(GetDlgItem(tablist[NSSM_TAB_LOGON], IDC_PASSWORD1), 1); - EnableWindow(GetDlgItem(tablist[NSSM_TAB_LOGON], IDC_PASSWORD2), 1); - } - else { - CheckRadioButton(tablist[NSSM_TAB_LOGON], IDC_LOCALSYSTEM, IDC_ACCOUNT, IDC_LOCALSYSTEM); - if (service->type & SERVICE_INTERACTIVE_PROCESS) SendDlgItemMessage(tablist[NSSM_TAB_LOGON], IDC_INTERACT, BM_SETCHECK, BST_CHECKED, 0); - } - - /* Dependencies tab. */ - if (service->dependencieslen) { - TCHAR *formatted; - unsigned long newlen; - if (format_double_null(service->dependencies, service->dependencieslen, &formatted, &newlen)) { - popup_message(dlg, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("dependencies"), _T("nssm_dlg()")); - } - else { - SetDlgItemText(tablist[NSSM_TAB_DEPENDENCIES], IDC_DEPENDENCIES, formatted); - HeapFree(GetProcessHeap(), 0, formatted); - } - } - - /* Process tab. */ - if (service->priority) { - int priority = priority_constant_to_index(service->priority); - combo = GetDlgItem(tablist[NSSM_TAB_PROCESS], IDC_PRIORITY); - SendMessage(combo, CB_SETCURSEL, priority, 0); - } - - if (service->affinity) { - list = GetDlgItem(tablist[NSSM_TAB_PROCESS], IDC_AFFINITY); - SendDlgItemMessage(tablist[NSSM_TAB_PROCESS], IDC_AFFINITY_ALL, BM_SETCHECK, BST_UNCHECKED, 0); - EnableWindow(GetDlgItem(tablist[NSSM_TAB_PROCESS], IDC_AFFINITY), 1); - - DWORD_PTR affinity, system_affinity; - if (GetProcessAffinityMask(GetCurrentProcess(), &affinity, &system_affinity)) { - if ((service->affinity & (__int64) system_affinity) != service->affinity) popup_message(dlg, MB_OK | MB_ICONWARNING, NSSM_GUI_WARN_AFFINITY); - } - - for (int i = 0; i < num_cpus(); i++) { - if (! (service->affinity & (1LL << (__int64) i))) SendMessage(list, LB_SETSEL, 0, i); - } - } - - if (service->no_console) { - SendDlgItemMessage(tablist[NSSM_TAB_PROCESS], IDC_CONSOLE, BM_SETCHECK, BST_UNCHECKED, 0); - } - - /* Shutdown tab. */ - if (! (service->stop_method & NSSM_STOP_METHOD_CONSOLE)) { - SendDlgItemMessage(tablist[NSSM_TAB_SHUTDOWN], IDC_METHOD_CONSOLE, BM_SETCHECK, BST_UNCHECKED, 0); - EnableWindow(GetDlgItem(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_CONSOLE), 0); - } - SetDlgItemInt(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_CONSOLE, service->kill_console_delay, 0); - if (! (service->stop_method & NSSM_STOP_METHOD_WINDOW)) { - SendDlgItemMessage(tablist[NSSM_TAB_SHUTDOWN], IDC_METHOD_WINDOW, BM_SETCHECK, BST_UNCHECKED, 0); - EnableWindow(GetDlgItem(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_WINDOW), 0); - } - SetDlgItemInt(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_WINDOW, service->kill_window_delay, 0); - if (! (service->stop_method & NSSM_STOP_METHOD_THREADS)) { - SendDlgItemMessage(tablist[NSSM_TAB_SHUTDOWN], IDC_METHOD_THREADS, BM_SETCHECK, BST_UNCHECKED, 0); - EnableWindow(GetDlgItem(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_THREADS), 0); - } - SetDlgItemInt(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_THREADS, service->kill_threads_delay, 0); - if (! (service->stop_method & NSSM_STOP_METHOD_TERMINATE)) { - SendDlgItemMessage(tablist[NSSM_TAB_SHUTDOWN], IDC_METHOD_TERMINATE, BM_SETCHECK, BST_UNCHECKED, 0); - } - - /* Restart tab. */ - SetDlgItemInt(tablist[NSSM_TAB_EXIT], IDC_THROTTLE, service->throttle_delay, 0); - combo = GetDlgItem(tablist[NSSM_TAB_EXIT], IDC_APPEXIT); - SendMessage(combo, CB_SETCURSEL, service->default_exit_action, 0); - SetDlgItemInt(tablist[NSSM_TAB_EXIT], IDC_RESTART_DELAY, service->restart_delay, 0); - - /* I/O tab. */ - SetDlgItemText(tablist[NSSM_TAB_IO], IDC_STDIN, service->stdin_path); - SetDlgItemText(tablist[NSSM_TAB_IO], IDC_STDOUT, service->stdout_path); - SetDlgItemText(tablist[NSSM_TAB_IO], IDC_STDERR, service->stderr_path); - - /* Rotation tab. */ - if (service->stdout_disposition == CREATE_ALWAYS) SendDlgItemMessage(tablist[NSSM_TAB_ROTATION], IDC_TRUNCATE, BM_SETCHECK, BST_CHECKED, 0); - if (service->rotate_files) { - SendDlgItemMessage(tablist[NSSM_TAB_ROTATION], IDC_ROTATE, BM_SETCHECK, BST_CHECKED, 0); - EnableWindow(GetDlgItem(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_ONLINE), 1); - EnableWindow(GetDlgItem(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_SECONDS), 1); - EnableWindow(GetDlgItem(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_BYTES_LOW), 1); - } - if (service->rotate_stdout_online || service->rotate_stderr_online) SendDlgItemMessage(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_ONLINE, BM_SETCHECK, BST_CHECKED, 0); - SetDlgItemInt(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_SECONDS, service->rotate_seconds, 0); - if (! service->rotate_bytes_high) SetDlgItemInt(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_BYTES_LOW, service->rotate_bytes_low, 0); - - /* Check if advanced settings are in use. */ - if (service->stdout_disposition != service->stderr_disposition || (service->stdout_disposition && service->stdout_disposition != NSSM_STDOUT_DISPOSITION && service->stdout_disposition != CREATE_ALWAYS) || (service->stderr_disposition && service->stderr_disposition != NSSM_STDERR_DISPOSITION && service->stderr_disposition != CREATE_ALWAYS)) popup_message(dlg, MB_OK | MB_ICONWARNING, NSSM_GUI_WARN_STDIO); - if (service->rotate_bytes_high) popup_message(dlg, MB_OK | MB_ICONWARNING, NSSM_GUI_WARN_ROTATE_BYTES); - - /* Environment tab. */ - TCHAR *env; - unsigned long envlen; - if (service->env_extralen) { - env = service->env_extra; - envlen = service->env_extralen; - } - else { - env = service->env; - envlen = service->envlen; - if (envlen) SendDlgItemMessage(tablist[NSSM_TAB_ENVIRONMENT], IDC_ENVIRONMENT_REPLACE, BM_SETCHECK, BST_CHECKED, 0); - } - - if (envlen) { - TCHAR *formatted; - unsigned long newlen; - if (format_double_null(env, envlen, &formatted, &newlen)) { - popup_message(dlg, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("environment"), _T("nssm_dlg()")); - } - else { - SetDlgItemText(tablist[NSSM_TAB_ENVIRONMENT], IDC_ENVIRONMENT, formatted); - HeapFree(GetProcessHeap(), 0, formatted); - } - } - if (service->envlen && service->env_extralen) popup_message(dlg, MB_OK | MB_ICONWARNING, NSSM_GUI_WARN_ENVIRONMENT); - } - - /* Go! */ - MSG message; - while (GetMessage(&message, 0, 0, 0)) { - if (IsDialogMessage(dlg, &message)) continue; - TranslateMessage(&message); - DispatchMessage(&message); - } - - return (int) message.wParam; -} - -void centre_window(HWND window) { - HWND desktop; - RECT size, desktop_size; - unsigned long x, y; - - if (! window) return; - - /* Find window size */ - if (! GetWindowRect(window, &size)) return; - - /* Find desktop window */ - desktop = GetDesktopWindow(); - if (! desktop) return; - - /* Find desktop window size */ - if (! GetWindowRect(desktop, &desktop_size)) return; - - /* Centre window */ - x = (desktop_size.right - size.right) / 2; - y = (desktop_size.bottom - size.bottom) / 2; - MoveWindow(window, x, y, size.right - size.left, size.bottom - size.top, 0); -} - -static inline void check_stop_method(nssm_service_t *service, unsigned long method, unsigned long control) { - if (SendDlgItemMessage(tablist[NSSM_TAB_SHUTDOWN], control, BM_GETCHECK, 0, 0) & BST_CHECKED) return; - service->stop_method &= ~method; -} - -static inline void check_number(HWND tab, unsigned long control, unsigned long *timeout) { - BOOL translated; - unsigned long configured = GetDlgItemInt(tab, control, &translated, 0); - if (translated) *timeout = configured; -} - -static inline void set_timeout_enabled(unsigned long control, unsigned long dependent) { - unsigned char enabled = 0; - if (SendDlgItemMessage(tablist[NSSM_TAB_SHUTDOWN], control, BM_GETCHECK, 0, 0) & BST_CHECKED) enabled = 1; - EnableWindow(GetDlgItem(tablist[NSSM_TAB_SHUTDOWN], dependent), enabled); -} - -static inline void set_logon_enabled(unsigned char enabled) { - EnableWindow(GetDlgItem(tablist[NSSM_TAB_LOGON], IDC_INTERACT), ! enabled); - EnableWindow(GetDlgItem(tablist[NSSM_TAB_LOGON], IDC_USERNAME), enabled); - EnableWindow(GetDlgItem(tablist[NSSM_TAB_LOGON], IDC_PASSWORD1), enabled); - EnableWindow(GetDlgItem(tablist[NSSM_TAB_LOGON], IDC_PASSWORD2), enabled); -} - -static inline void set_affinity_enabled(unsigned char enabled) { - EnableWindow(GetDlgItem(tablist[NSSM_TAB_PROCESS], IDC_AFFINITY), enabled); -} - -static inline void set_rotation_enabled(unsigned char enabled) { - EnableWindow(GetDlgItem(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_ONLINE), enabled); - EnableWindow(GetDlgItem(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_SECONDS), enabled); - EnableWindow(GetDlgItem(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_BYTES_LOW), enabled); -} - -static inline void check_io(HWND owner, TCHAR *name, TCHAR *buffer, unsigned long len, unsigned long control) { - if (! SendMessage(GetDlgItem(tablist[NSSM_TAB_IO], control), WM_GETTEXTLENGTH, 0, 0)) return; - if (GetDlgItemText(tablist[NSSM_TAB_IO], control, buffer, (int) len)) return; - popup_message(owner, MB_OK | MB_ICONEXCLAMATION, NSSM_MESSAGE_PATH_TOO_LONG, name); - ZeroMemory(buffer, len * sizeof(TCHAR)); -} - -/* Set service parameters. */ -int configure(HWND window, nssm_service_t *service, nssm_service_t *orig_service) { - if (! service) return 1; - - set_nssm_service_defaults(service); - - if (orig_service) { - service->native = orig_service->native; - service->handle = orig_service->handle; - } - - /* Get service name. */ - if (! GetDlgItemText(window, IDC_NAME, service->name, _countof(service->name))) { - popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_MISSING_SERVICE_NAME); - cleanup_nssm_service(service); - return 2; - } - - /* Get executable name */ - if (! service->native) { - if (! GetDlgItemText(tablist[NSSM_TAB_APPLICATION], IDC_PATH, service->exe, _countof(service->exe))) { - popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_MISSING_PATH); - return 3; - } - - /* Get startup directory. */ - if (! GetDlgItemText(tablist[NSSM_TAB_APPLICATION], IDC_DIR, service->dir, _countof(service->dir))) { - _sntprintf_s(service->dir, _countof(service->dir), _TRUNCATE, _T("%s"), service->exe); - strip_basename(service->dir); - } - - /* Get flags. */ - if (SendMessage(GetDlgItem(tablist[NSSM_TAB_APPLICATION], IDC_FLAGS), WM_GETTEXTLENGTH, 0, 0)) { - if (! GetDlgItemText(tablist[NSSM_TAB_APPLICATION], IDC_FLAGS, service->flags, _countof(service->flags))) { - popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INVALID_OPTIONS); - return 4; - } - } - } - - /* Get details. */ - if (SendMessage(GetDlgItem(tablist[NSSM_TAB_DETAILS], IDC_DISPLAYNAME), WM_GETTEXTLENGTH, 0, 0)) { - if (! GetDlgItemText(tablist[NSSM_TAB_DETAILS], IDC_DISPLAYNAME, service->displayname, _countof(service->displayname))) { - popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INVALID_DISPLAYNAME); - return 5; - } - } - - if (SendMessage(GetDlgItem(tablist[NSSM_TAB_DETAILS], IDC_DESCRIPTION), WM_GETTEXTLENGTH, 0, 0)) { - if (! GetDlgItemText(tablist[NSSM_TAB_DETAILS], IDC_DESCRIPTION, service->description, _countof(service->description))) { - popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INVALID_DESCRIPTION); - return 5; - } - } - - HWND combo = GetDlgItem(tablist[NSSM_TAB_DETAILS], IDC_STARTUP); - service->startup = (unsigned long) SendMessage(combo, CB_GETCURSEL, 0, 0); - if (service->startup == CB_ERR) service->startup = 0; - - /* Get logon stuff. */ - if (SendDlgItemMessage(tablist[NSSM_TAB_LOGON], IDC_LOCALSYSTEM, BM_GETCHECK, 0, 0) & BST_CHECKED) { - if (SendDlgItemMessage(tablist[NSSM_TAB_LOGON], IDC_INTERACT, BM_GETCHECK, 0, 0) & BST_CHECKED) { - service->type |= SERVICE_INTERACTIVE_PROCESS; - } - if (service->username) HeapFree(GetProcessHeap(), 0, service->username); - service->username = 0; - service->usernamelen = 0; - if (service->password) { - SecureZeroMemory(service->password, service->passwordlen); - HeapFree(GetProcessHeap(), 0, service->password); - } - service->password = 0; - service->passwordlen = 0; - } - else { - /* Username. */ - service->usernamelen = SendMessage(GetDlgItem(tablist[NSSM_TAB_LOGON], IDC_USERNAME), WM_GETTEXTLENGTH, 0, 0); - if (! service->usernamelen) { - popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_MISSING_USERNAME); - return 6; - } - service->usernamelen++; - - service->username = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, service->usernamelen * sizeof(TCHAR)); - if (! service->username) { - popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("account name"), _T("install()")); - return 6; - } - if (! GetDlgItemText(tablist[NSSM_TAB_LOGON], IDC_USERNAME, service->username, (int) service->usernamelen)) { - HeapFree(GetProcessHeap(), 0, service->username); - service->username = 0; - service->usernamelen = 0; - popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INVALID_USERNAME); - return 6; - } - - /* - Special case for well-known accounts. - Ignore the password if we're editing and the username hasn't changed. - */ - const TCHAR *well_known = well_known_username(service->username); - if (well_known) { - if (str_equiv(well_known, NSSM_LOCALSYSTEM_ACCOUNT)) { - HeapFree(GetProcessHeap(), 0, service->username); - service->username = 0; - service->usernamelen = 0; - } - else { - service->usernamelen = _tcslen(well_known) + 1; - service->username = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, service->usernamelen * sizeof(TCHAR)); - if (! service->username) { - print_message(stderr, NSSM_MESSAGE_OUT_OF_MEMORY, _T("canon"), _T("install()")); - return 6; - } - memmove(service->username, well_known, service->usernamelen * sizeof(TCHAR)); - } - } - else { - /* Password. */ - service->passwordlen = SendMessage(GetDlgItem(tablist[NSSM_TAB_LOGON], IDC_PASSWORD1), WM_GETTEXTLENGTH, 0, 0); - size_t passwordlen = SendMessage(GetDlgItem(tablist[NSSM_TAB_LOGON], IDC_PASSWORD2), WM_GETTEXTLENGTH, 0, 0); - - if (! orig_service || ! orig_service->username || ! str_equiv(service->username, orig_service->username) || service->passwordlen || passwordlen) { - if (! service->passwordlen) { - popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_MISSING_PASSWORD); - return 6; - } - if (passwordlen != service->passwordlen) { - popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_MISSING_PASSWORD); - return 6; - } - service->passwordlen++; - - /* Temporary buffer for password validation. */ - TCHAR *password = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, service->passwordlen * sizeof(TCHAR)); - if (! password) { - HeapFree(GetProcessHeap(), 0, service->username); - service->username = 0; - service->usernamelen = 0; - popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("password confirmation"), _T("install()")); - return 6; - } - - /* Actual password buffer. */ - service->password = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, service->passwordlen * sizeof(TCHAR)); - if (! service->password) { - HeapFree(GetProcessHeap(), 0, password); - HeapFree(GetProcessHeap(), 0, service->username); - service->username = 0; - service->usernamelen = 0; - popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("password"), _T("install()")); - return 6; - } - - /* Get first password. */ - if (! GetDlgItemText(tablist[NSSM_TAB_LOGON], IDC_PASSWORD1, service->password, (int) service->passwordlen)) { - HeapFree(GetProcessHeap(), 0, password); - SecureZeroMemory(service->password, service->passwordlen); - HeapFree(GetProcessHeap(), 0, service->password); - service->password = 0; - service->passwordlen = 0; - HeapFree(GetProcessHeap(), 0, service->username); - service->username = 0; - service->usernamelen = 0; - popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INVALID_PASSWORD); - return 6; - } - - /* Get confirmation. */ - if (! GetDlgItemText(tablist[NSSM_TAB_LOGON], IDC_PASSWORD2, password, (int) service->passwordlen)) { - SecureZeroMemory(password, service->passwordlen); - HeapFree(GetProcessHeap(), 0, password); - SecureZeroMemory(service->password, service->passwordlen); - HeapFree(GetProcessHeap(), 0, service->password); - service->password = 0; - service->passwordlen = 0; - HeapFree(GetProcessHeap(), 0, service->username); - service->username = 0; - service->usernamelen = 0; - popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INVALID_PASSWORD); - return 6; - } - - /* Compare. */ - if (_tcsncmp(password, service->password, service->passwordlen)) { - popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_MISSING_PASSWORD); - SecureZeroMemory(password, service->passwordlen); - HeapFree(GetProcessHeap(), 0, password); - SecureZeroMemory(service->password, service->passwordlen); - HeapFree(GetProcessHeap(), 0, service->password); - service->password = 0; - service->passwordlen = 0; - HeapFree(GetProcessHeap(), 0, service->username); - service->username = 0; - service->usernamelen = 0; - return 6; - } - } - } - } - - /* Get dependencies. */ - unsigned long dependencieslen = (unsigned long) SendMessage(GetDlgItem(tablist[NSSM_TAB_DEPENDENCIES], IDC_DEPENDENCIES), WM_GETTEXTLENGTH, 0, 0); - if (dependencieslen) { - TCHAR *dependencies = (TCHAR *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (dependencieslen + 2) * sizeof(TCHAR)); - if (! dependencies) { - popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("dependencies"), _T("install()")); - cleanup_nssm_service(service); - return 6; - } - - if (! GetDlgItemText(tablist[NSSM_TAB_DEPENDENCIES], IDC_DEPENDENCIES, dependencies, dependencieslen + 1)) { - popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INVALID_DEPENDENCIES); - HeapFree(GetProcessHeap(), 0, dependencies); - cleanup_nssm_service(service); - return 6; - } - - if (unformat_double_null(dependencies, dependencieslen, &service->dependencies, &service->dependencieslen)) { - HeapFree(GetProcessHeap(), 0, dependencies); - popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("dependencies"), _T("install()")); - cleanup_nssm_service(service); - return 6; - } - - HeapFree(GetProcessHeap(), 0, dependencies); - } - - /* Remaining tabs are only for services we manage. */ - if (service->native) return 0; - - /* Get process stuff. */ - combo = GetDlgItem(tablist[NSSM_TAB_PROCESS], IDC_PRIORITY); - service->priority = priority_index_to_constant((unsigned long) SendMessage(combo, CB_GETCURSEL, 0, 0)); - - service->affinity = 0LL; - if (! (SendDlgItemMessage(tablist[NSSM_TAB_PROCESS], IDC_AFFINITY_ALL, BM_GETCHECK, 0, 0) & BST_CHECKED)) { - HWND list = GetDlgItem(tablist[NSSM_TAB_PROCESS], IDC_AFFINITY); - int selected = (int) SendMessage(list, LB_GETSELCOUNT, 0, 0); - int count = (int) SendMessage(list, LB_GETCOUNT, 0, 0); - if (! selected) { - popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_WARN_AFFINITY_NONE); - return 5; - } - else if (selected < count) { - for (int i = 0; i < count; i++) { - if (SendMessage(list, LB_GETSEL, i, 0)) service->affinity |= (1LL << (__int64) i); - } - } - } - - if (SendDlgItemMessage(tablist[NSSM_TAB_PROCESS], IDC_CONSOLE, BM_GETCHECK, 0, 0) & BST_CHECKED) service->no_console = 0; - else service->no_console = 1; - - /* Get stop method stuff. */ - check_stop_method(service, NSSM_STOP_METHOD_CONSOLE, IDC_METHOD_CONSOLE); - check_stop_method(service, NSSM_STOP_METHOD_WINDOW, IDC_METHOD_WINDOW); - check_stop_method(service, NSSM_STOP_METHOD_THREADS, IDC_METHOD_THREADS); - check_stop_method(service, NSSM_STOP_METHOD_TERMINATE, IDC_METHOD_TERMINATE); - check_number(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_CONSOLE, &service->kill_console_delay); - check_number(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_WINDOW, &service->kill_window_delay); - check_number(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_THREADS, &service->kill_threads_delay); - - /* Get exit action stuff. */ - check_number(tablist[NSSM_TAB_EXIT], IDC_THROTTLE, &service->throttle_delay); - combo = GetDlgItem(tablist[NSSM_TAB_EXIT], IDC_APPEXIT); - service->default_exit_action = (unsigned long) SendMessage(combo, CB_GETCURSEL, 0, 0); - if (service->default_exit_action == CB_ERR) service->default_exit_action = 0; - check_number(tablist[NSSM_TAB_EXIT], IDC_RESTART_DELAY, &service->restart_delay); - - /* Get I/O stuff. */ - check_io(window, _T("stdin"), service->stdin_path, _countof(service->stdin_path), IDC_STDIN); - check_io(window, _T("stdout"), service->stdout_path, _countof(service->stdout_path), IDC_STDOUT); - check_io(window, _T("stderr"), service->stderr_path, _countof(service->stderr_path), IDC_STDERR); - - /* Override stdout and/or stderr. */ - if (SendDlgItemMessage(tablist[NSSM_TAB_ROTATION], IDC_TRUNCATE, BM_GETCHECK, 0, 0) & BST_CHECKED) { - if (service->stdout_path[0]) service->stdout_disposition = CREATE_ALWAYS; - if (service->stderr_path[0]) service->stderr_disposition = CREATE_ALWAYS; - } - - /* Get rotation stuff. */ - if (SendDlgItemMessage(tablist[NSSM_TAB_ROTATION], IDC_ROTATE, BM_GETCHECK, 0, 0) & BST_CHECKED) { - service->rotate_files = true; - if (SendDlgItemMessage(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_ONLINE, BM_GETCHECK, 0, 0) & BST_CHECKED) service->rotate_stdout_online = service->rotate_stderr_online = NSSM_ROTATE_ONLINE; - check_number(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_SECONDS, &service->rotate_seconds); - check_number(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_BYTES_LOW, &service->rotate_bytes_low); - } - - /* Get environment. */ - unsigned long envlen = (unsigned long) SendMessage(GetDlgItem(tablist[NSSM_TAB_ENVIRONMENT], IDC_ENVIRONMENT), WM_GETTEXTLENGTH, 0, 0); - if (envlen) { - TCHAR *env = (TCHAR *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (envlen + 2) * sizeof(TCHAR)); - if (! env) { - popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("environment"), _T("install()")); - cleanup_nssm_service(service); - return 5; - } - - if (! GetDlgItemText(tablist[NSSM_TAB_ENVIRONMENT], IDC_ENVIRONMENT, env, envlen + 1)) { - popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INVALID_ENVIRONMENT); - HeapFree(GetProcessHeap(), 0, env); - cleanup_nssm_service(service); - return 5; - } - - TCHAR *newenv; - unsigned long newlen; - if (unformat_double_null(env, envlen, &newenv, &newlen)) { - HeapFree(GetProcessHeap(), 0, env); - popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("environment"), _T("install()")); - cleanup_nssm_service(service); - return 5; - } - - HeapFree(GetProcessHeap(), 0, env); - env = newenv; - envlen = newlen; - - /* Test the environment is valid. */ - if (test_environment(env)) { - popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INVALID_ENVIRONMENT); - HeapFree(GetProcessHeap(), 0, env); - cleanup_nssm_service(service); - return 5; - } - - if (SendDlgItemMessage(tablist[NSSM_TAB_ENVIRONMENT], IDC_ENVIRONMENT_REPLACE, BM_GETCHECK, 0, 0) & BST_CHECKED) { - service->env = env; - service->envlen = envlen; - } - else { - service->env_extra = env; - service->env_extralen = envlen; - } - } - - return 0; -} - -/* Install the service. */ -int install(HWND window) { - if (! window) return 1; - - nssm_service_t *service = alloc_nssm_service(); - if (service) { - int ret = configure(window, service, 0); - if (ret) return ret; - } - - /* See if it works. */ - switch (install_service(service)) { - case 1: - popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("service"), _T("install()")); - cleanup_nssm_service(service); - return 1; - - case 2: - popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_MESSAGE_OPEN_SERVICE_MANAGER_FAILED); - cleanup_nssm_service(service); - return 2; - - case 3: - popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_MESSAGE_PATH_TOO_LONG, NSSM); - cleanup_nssm_service(service); - return 3; - - case 4: - popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_OUT_OF_MEMORY_FOR_IMAGEPATH); - cleanup_nssm_service(service); - return 4; - - case 5: - popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INSTALL_SERVICE_FAILED); - cleanup_nssm_service(service); - return 5; - - case 6: - popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_CREATE_PARAMETERS_FAILED); - cleanup_nssm_service(service); - return 6; - } - - popup_message(window, MB_OK, NSSM_MESSAGE_SERVICE_INSTALLED, service->name); - cleanup_nssm_service(service); - return 0; -} - -/* Remove the service */ -int remove(HWND window) { - if (! window) return 1; - - /* See if it works */ - nssm_service_t *service = alloc_nssm_service(); - if (service) { - /* Get service name */ - if (! GetDlgItemText(window, IDC_NAME, service->name, _countof(service->name))) { - popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_MISSING_SERVICE_NAME); - cleanup_nssm_service(service); - return 2; - } - - /* Confirm */ - if (popup_message(window, MB_YESNO, NSSM_GUI_ASK_REMOVE_SERVICE, service->name) != IDYES) { - cleanup_nssm_service(service); - return 0; - } - } - - switch (remove_service(service)) { - case 1: - popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("service"), _T("remove()")); - cleanup_nssm_service(service); - return 1; - - case 2: - popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_MESSAGE_OPEN_SERVICE_MANAGER_FAILED); - cleanup_nssm_service(service); - return 2; - - case 3: - popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_SERVICE_NOT_INSTALLED); - return 3; - cleanup_nssm_service(service); - - case 4: - popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_REMOVE_SERVICE_FAILED); - cleanup_nssm_service(service); - return 4; - } - - popup_message(window, MB_OK, NSSM_MESSAGE_SERVICE_REMOVED, service->name); - cleanup_nssm_service(service); - return 0; -} - -int edit(HWND window, nssm_service_t *orig_service) { - if (! window) return 1; - - nssm_service_t *service = alloc_nssm_service(); - if (service) { - int ret = configure(window, service, orig_service); - if (ret) return ret; - } - - switch (edit_service(service, true)) { - case 1: - popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("service"), _T("edit()")); - cleanup_nssm_service(service); - return 1; - - case 3: - popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_MESSAGE_PATH_TOO_LONG, NSSM); - cleanup_nssm_service(service); - return 3; - - case 4: - popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_OUT_OF_MEMORY_FOR_IMAGEPATH); - cleanup_nssm_service(service); - return 4; - - case 5: - case 6: - popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_EDIT_PARAMETERS_FAILED); - cleanup_nssm_service(service); - return 6; - } - - popup_message(window, MB_OK, NSSM_MESSAGE_SERVICE_EDITED, service->name); - cleanup_nssm_service(service); - return 0; -} - -static TCHAR *browse_filter(int message) { - switch (message) { - case NSSM_GUI_BROWSE_FILTER_APPLICATIONS: return _T("*.exe;*.bat;*.cmd"); - case NSSM_GUI_BROWSE_FILTER_DIRECTORIES: return _T("."); - case NSSM_GUI_BROWSE_FILTER_ALL_FILES: /* Fall through. */ - default: return _T("*.*"); - } -} - -UINT_PTR CALLBACK browse_hook(HWND dlg, UINT message, WPARAM w, LPARAM l) { - switch (message) { - case WM_INITDIALOG: - return 1; - } - - return 0; -} - -/* Browse for application */ -void browse(HWND window, TCHAR *current, unsigned long flags, ...) { - if (! window) return; - - va_list arg; - size_t bufsize = 256; - size_t len = bufsize; - int i; - - OPENFILENAME ofn; - ZeroMemory(&ofn, sizeof(ofn)); - ofn.lStructSize = sizeof(ofn); - ofn.lpstrFilter = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, bufsize * sizeof(TCHAR)); - /* XXX: Escaping nulls with FormatMessage is tricky */ - if (ofn.lpstrFilter) { - ZeroMemory((void *) ofn.lpstrFilter, bufsize); - len = 0; - /* "Applications" + NULL + "*.exe" + NULL */ - va_start(arg, flags); - while (i = va_arg(arg, int)) { - TCHAR *localised = message_string(i); - _sntprintf_s((TCHAR *) ofn.lpstrFilter + len, bufsize, _TRUNCATE, localised); - len += _tcslen(localised) + 1; - LocalFree(localised); - TCHAR *filter = browse_filter(i); - _sntprintf_s((TCHAR *) ofn.lpstrFilter + len, bufsize - len, _TRUNCATE, _T("%s"), filter); - len += _tcslen(filter) + 1; - } - va_end(arg); - /* Remainder of the buffer is already zeroed */ - } - ofn.lpstrFile = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, PATH_LENGTH * sizeof(TCHAR)); - if (ofn.lpstrFile) { - if (flags & OFN_NOVALIDATE) { - /* Directory hack. */ - _sntprintf_s(ofn.lpstrFile, PATH_LENGTH, _TRUNCATE, _T(":%s:"), message_string(NSSM_GUI_BROWSE_FILTER_DIRECTORIES)); - ofn.nMaxFile = DIR_LENGTH; - } - else { - _sntprintf_s(ofn.lpstrFile, PATH_LENGTH, _TRUNCATE, _T("%s"), current); - ofn.nMaxFile = PATH_LENGTH; - } - } - ofn.lpstrTitle = message_string(NSSM_GUI_BROWSE_TITLE); - ofn.Flags = OFN_EXPLORER | OFN_HIDEREADONLY | OFN_PATHMUSTEXIST | flags; - - if (GetOpenFileName(&ofn)) { - /* Directory hack. */ - if (flags & OFN_NOVALIDATE) strip_basename(ofn.lpstrFile); - SendMessage(window, WM_SETTEXT, 0, (LPARAM) ofn.lpstrFile); - } - if (ofn.lpstrFilter) HeapFree(GetProcessHeap(), 0, (void *) ofn.lpstrFilter); - if (ofn.lpstrFile) HeapFree(GetProcessHeap(), 0, ofn.lpstrFile); -} - -INT_PTR CALLBACK tab_dlg(HWND tab, UINT message, WPARAM w, LPARAM l) { - switch (message) { - case WM_INITDIALOG: - return 1; - - /* Button was pressed or control was controlled. */ - case WM_COMMAND: - HWND dlg; - TCHAR buffer[PATH_LENGTH]; - unsigned char enabled; - - switch (LOWORD(w)) { - /* Browse for application. */ - case IDC_BROWSE: - dlg = GetDlgItem(tab, IDC_PATH); - GetDlgItemText(tab, IDC_PATH, buffer, _countof(buffer)); - browse(dlg, buffer, OFN_FILEMUSTEXIST, NSSM_GUI_BROWSE_FILTER_APPLICATIONS, NSSM_GUI_BROWSE_FILTER_ALL_FILES, 0); - /* Fill in startup directory if it wasn't already specified. */ - GetDlgItemText(tab, IDC_DIR, buffer, _countof(buffer)); - if (! buffer[0]) { - GetDlgItemText(tab, IDC_PATH, buffer, _countof(buffer)); - strip_basename(buffer); - SetDlgItemText(tab, IDC_DIR, buffer); - } - break; - - /* Browse for startup directory. */ - case IDC_BROWSE_DIR: - dlg = GetDlgItem(tab, IDC_DIR); - GetDlgItemText(tab, IDC_DIR, buffer, _countof(buffer)); - browse(dlg, buffer, OFN_NOVALIDATE, NSSM_GUI_BROWSE_FILTER_DIRECTORIES, 0); - break; - - /* Log on. */ - case IDC_LOCALSYSTEM: - set_logon_enabled(0); - break; - - case IDC_ACCOUNT: - set_logon_enabled(1); - break; - - /* Affinity. */ - case IDC_AFFINITY_ALL: - if (SendDlgItemMessage(tab, LOWORD(w), BM_GETCHECK, 0, 0) & BST_CHECKED) enabled = 0; - else enabled = 1; - set_affinity_enabled(enabled); - break; - - /* Shutdown methods. */ - case IDC_METHOD_CONSOLE: - set_timeout_enabled(LOWORD(w), IDC_KILL_CONSOLE); - break; - - case IDC_METHOD_WINDOW: - set_timeout_enabled(LOWORD(w), IDC_KILL_WINDOW); - break; - - case IDC_METHOD_THREADS: - set_timeout_enabled(LOWORD(w), IDC_KILL_THREADS); - break; - - /* Browse for stdin. */ - case IDC_BROWSE_STDIN: - dlg = GetDlgItem(tab, IDC_STDIN); - GetDlgItemText(tab, IDC_STDIN, buffer, _countof(buffer)); - browse(dlg, buffer, 0, NSSM_GUI_BROWSE_FILTER_ALL_FILES, 0); - break; - - /* Browse for stdout. */ - case IDC_BROWSE_STDOUT: - dlg = GetDlgItem(tab, IDC_STDOUT); - GetDlgItemText(tab, IDC_STDOUT, buffer, _countof(buffer)); - browse(dlg, buffer, 0, NSSM_GUI_BROWSE_FILTER_ALL_FILES, 0); - /* Fill in stderr if it wasn't already specified. */ - GetDlgItemText(tab, IDC_STDERR, buffer, _countof(buffer)); - if (! buffer[0]) { - GetDlgItemText(tab, IDC_STDOUT, buffer, _countof(buffer)); - SetDlgItemText(tab, IDC_STDERR, buffer); - } - break; - - /* Browse for stderr. */ - case IDC_BROWSE_STDERR: - dlg = GetDlgItem(tab, IDC_STDERR); - GetDlgItemText(tab, IDC_STDERR, buffer, _countof(buffer)); - browse(dlg, buffer, 0, NSSM_GUI_BROWSE_FILTER_ALL_FILES, 0); - break; - - /* Rotation. */ - case IDC_ROTATE: - if (SendDlgItemMessage(tab, LOWORD(w), BM_GETCHECK, 0, 0) & BST_CHECKED) enabled = 1; - else enabled = 0; - set_rotation_enabled(enabled); - break; - } - return 1; - } - - return 0; -} - -/* Install/remove dialogue callback */ -INT_PTR CALLBACK nssm_dlg(HWND window, UINT message, WPARAM w, LPARAM l) { - nssm_service_t *service; - - switch (message) { - /* Creating the dialogue */ - case WM_INITDIALOG: - service = (nssm_service_t *) l; - - SetFocus(GetDlgItem(window, IDC_NAME)); - - HWND tabs; - HWND combo; - HWND list; - int i, n; - tabs = GetDlgItem(window, IDC_TAB1); - if (! tabs) return 0; - - /* Set up tabs. */ - TCITEM tab; - ZeroMemory(&tab, sizeof(tab)); - tab.mask = TCIF_TEXT; - - selected_tab = 0; - - /* Application tab. */ - if (service->native) tab.pszText = message_string(NSSM_GUI_TAB_NATIVE); - else tab.pszText = message_string(NSSM_GUI_TAB_APPLICATION); - tab.cchTextMax = (int) _tcslen(tab.pszText); - SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_APPLICATION, (LPARAM) &tab); - if (service->native) { - tablist[NSSM_TAB_APPLICATION] = dialog(MAKEINTRESOURCE(IDD_NATIVE), window, tab_dlg); - EnableWindow(tablist[NSSM_TAB_APPLICATION], 0); - EnableWindow(GetDlgItem(tablist[NSSM_TAB_APPLICATION], IDC_PATH), 0); - } - else tablist[NSSM_TAB_APPLICATION] = dialog(MAKEINTRESOURCE(IDD_APPLICATION), window, tab_dlg); - ShowWindow(tablist[NSSM_TAB_APPLICATION], SW_SHOW); - - /* Details tab. */ - tab.pszText = message_string(NSSM_GUI_TAB_DETAILS); - tab.cchTextMax = (int) _tcslen(tab.pszText); - SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_DETAILS, (LPARAM) &tab); - tablist[NSSM_TAB_DETAILS] = dialog(MAKEINTRESOURCE(IDD_DETAILS), window, tab_dlg); - ShowWindow(tablist[NSSM_TAB_DETAILS], SW_HIDE); - - /* Set defaults. */ - combo = GetDlgItem(tablist[NSSM_TAB_DETAILS], IDC_STARTUP); - SendMessage(combo, CB_INSERTSTRING, NSSM_STARTUP_AUTOMATIC, (LPARAM) message_string(NSSM_GUI_STARTUP_AUTOMATIC)); - SendMessage(combo, CB_INSERTSTRING, NSSM_STARTUP_DELAYED, (LPARAM) message_string(NSSM_GUI_STARTUP_DELAYED)); - SendMessage(combo, CB_INSERTSTRING, NSSM_STARTUP_MANUAL, (LPARAM) message_string(NSSM_GUI_STARTUP_MANUAL)); - SendMessage(combo, CB_INSERTSTRING, NSSM_STARTUP_DISABLED, (LPARAM) message_string(NSSM_GUI_STARTUP_DISABLED)); - SendMessage(combo, CB_SETCURSEL, NSSM_STARTUP_AUTOMATIC, 0); - - /* Logon tab. */ - tab.pszText = message_string(NSSM_GUI_TAB_LOGON); - tab.cchTextMax = (int) _tcslen(tab.pszText); - SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_LOGON, (LPARAM) &tab); - tablist[NSSM_TAB_LOGON] = dialog(MAKEINTRESOURCE(IDD_LOGON), window, tab_dlg); - ShowWindow(tablist[NSSM_TAB_LOGON], SW_HIDE); - - /* Set defaults. */ - CheckRadioButton(tablist[NSSM_TAB_LOGON], IDC_LOCALSYSTEM, IDC_ACCOUNT, IDC_LOCALSYSTEM); - set_logon_enabled(0); - - /* Dependencies tab. */ - tab.pszText = message_string(NSSM_GUI_TAB_DEPENDENCIES); - tab.cchTextMax = (int) _tcslen(tab.pszText); - SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_DEPENDENCIES, (LPARAM) &tab); - tablist[NSSM_TAB_DEPENDENCIES] = dialog(MAKEINTRESOURCE(IDD_DEPENDENCIES), window, tab_dlg); - ShowWindow(tablist[NSSM_TAB_DEPENDENCIES], SW_HIDE); - - /* Remaining tabs are only for services we manage. */ - if (service->native) return 1; - - /* Process tab. */ - tab.pszText = message_string(NSSM_GUI_TAB_PROCESS); - tab.cchTextMax = (int) _tcslen(tab.pszText); - SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_PROCESS, (LPARAM) &tab); - tablist[NSSM_TAB_PROCESS] = dialog(MAKEINTRESOURCE(IDD_PROCESS), window, tab_dlg); - ShowWindow(tablist[NSSM_TAB_PROCESS], SW_HIDE); - - /* Set defaults. */ - combo = GetDlgItem(tablist[NSSM_TAB_PROCESS], IDC_PRIORITY); - SendMessage(combo, CB_INSERTSTRING, NSSM_REALTIME_PRIORITY, (LPARAM) message_string(NSSM_GUI_REALTIME_PRIORITY_CLASS)); - SendMessage(combo, CB_INSERTSTRING, NSSM_HIGH_PRIORITY, (LPARAM) message_string(NSSM_GUI_HIGH_PRIORITY_CLASS)); - SendMessage(combo, CB_INSERTSTRING, NSSM_ABOVE_NORMAL_PRIORITY, (LPARAM) message_string(NSSM_GUI_ABOVE_NORMAL_PRIORITY_CLASS)); - SendMessage(combo, CB_INSERTSTRING, NSSM_NORMAL_PRIORITY, (LPARAM) message_string(NSSM_GUI_NORMAL_PRIORITY_CLASS)); - SendMessage(combo, CB_INSERTSTRING, NSSM_BELOW_NORMAL_PRIORITY, (LPARAM) message_string(NSSM_GUI_BELOW_NORMAL_PRIORITY_CLASS)); - SendMessage(combo, CB_INSERTSTRING, NSSM_IDLE_PRIORITY, (LPARAM) message_string(NSSM_GUI_IDLE_PRIORITY_CLASS)); - SendMessage(combo, CB_SETCURSEL, NSSM_NORMAL_PRIORITY, 0); - - SendDlgItemMessage(tablist[NSSM_TAB_PROCESS], IDC_CONSOLE, BM_SETCHECK, BST_CHECKED, 0); - - list = GetDlgItem(tablist[NSSM_TAB_PROCESS], IDC_AFFINITY); - n = num_cpus(); - SendMessage(list, LB_SETCOLUMNWIDTH, 16, 0); - for (i = 0; i < n; i++) { - TCHAR buffer[3]; - _sntprintf_s(buffer, _countof(buffer), _TRUNCATE, _T("%d"), i); - SendMessage(list, LB_ADDSTRING, 0, (LPARAM) buffer); - } - - /* - Size to fit. - The box is high enough for four rows. It is wide enough for eight - columns without scrolling. With scrollbars it shrinks to two rows. - Note that the above only holds if we set the column width BEFORE - adding the strings. - */ - if (n < 32) { - int columns = (n - 1) / 4; - RECT rect; - GetWindowRect(list, &rect); - int width = rect.right - rect.left; - width -= (7 - columns) * 16; - int height = rect.bottom - rect.top; - if (n < 4) height -= (int) SendMessage(list, LB_GETITEMHEIGHT, 0, 0) * (4 - n); - SetWindowPos(list, 0, 0, 0, width, height, SWP_NOMOVE | SWP_NOOWNERZORDER); - } - SendMessage(list, LB_SELITEMRANGE, 1, MAKELPARAM(0, n)); - - SendDlgItemMessage(tablist[NSSM_TAB_PROCESS], IDC_AFFINITY_ALL, BM_SETCHECK, BST_CHECKED, 0); - set_affinity_enabled(0); - - /* Shutdown tab. */ - tab.pszText = message_string(NSSM_GUI_TAB_SHUTDOWN); - tab.cchTextMax = (int) _tcslen(tab.pszText); - SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_SHUTDOWN, (LPARAM) &tab); - tablist[NSSM_TAB_SHUTDOWN] = dialog(MAKEINTRESOURCE(IDD_SHUTDOWN), window, tab_dlg); - ShowWindow(tablist[NSSM_TAB_SHUTDOWN], SW_HIDE); - - /* Set defaults. */ - SendDlgItemMessage(tablist[NSSM_TAB_SHUTDOWN], IDC_METHOD_CONSOLE, BM_SETCHECK, BST_CHECKED, 0); - SetDlgItemInt(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_CONSOLE, NSSM_KILL_CONSOLE_GRACE_PERIOD, 0); - SendDlgItemMessage(tablist[NSSM_TAB_SHUTDOWN], IDC_METHOD_WINDOW, BM_SETCHECK, BST_CHECKED, 0); - SetDlgItemInt(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_WINDOW, NSSM_KILL_WINDOW_GRACE_PERIOD, 0); - SendDlgItemMessage(tablist[NSSM_TAB_SHUTDOWN], IDC_METHOD_THREADS, BM_SETCHECK, BST_CHECKED, 0); - SetDlgItemInt(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_THREADS, NSSM_KILL_THREADS_GRACE_PERIOD, 0); - SendDlgItemMessage(tablist[NSSM_TAB_SHUTDOWN], IDC_METHOD_TERMINATE, BM_SETCHECK, BST_CHECKED, 0); - - /* Restart tab. */ - tab.pszText = message_string(NSSM_GUI_TAB_EXIT); - tab.cchTextMax = (int) _tcslen(tab.pszText); - SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_EXIT, (LPARAM) &tab); - tablist[NSSM_TAB_EXIT] = dialog(MAKEINTRESOURCE(IDD_APPEXIT), window, tab_dlg); - ShowWindow(tablist[NSSM_TAB_EXIT], SW_HIDE); - - /* Set defaults. */ - SetDlgItemInt(tablist[NSSM_TAB_EXIT], IDC_THROTTLE, NSSM_RESET_THROTTLE_RESTART, 0); - combo = GetDlgItem(tablist[NSSM_TAB_EXIT], IDC_APPEXIT); - SendMessage(combo, CB_INSERTSTRING, NSSM_EXIT_RESTART, (LPARAM) message_string(NSSM_GUI_EXIT_RESTART)); - SendMessage(combo, CB_INSERTSTRING, NSSM_EXIT_IGNORE, (LPARAM) message_string(NSSM_GUI_EXIT_IGNORE)); - SendMessage(combo, CB_INSERTSTRING, NSSM_EXIT_REALLY, (LPARAM) message_string(NSSM_GUI_EXIT_REALLY)); - SendMessage(combo, CB_INSERTSTRING, NSSM_EXIT_UNCLEAN, (LPARAM) message_string(NSSM_GUI_EXIT_UNCLEAN)); - SendMessage(combo, CB_SETCURSEL, NSSM_EXIT_RESTART, 0); - SetDlgItemInt(tablist[NSSM_TAB_EXIT], IDC_RESTART_DELAY, 0, 0); - - /* I/O tab. */ - tab.pszText = message_string(NSSM_GUI_TAB_IO); - tab.cchTextMax = (int) _tcslen(tab.pszText) + 1; - SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_IO, (LPARAM) &tab); - tablist[NSSM_TAB_IO] = dialog(MAKEINTRESOURCE(IDD_IO), window, tab_dlg); - ShowWindow(tablist[NSSM_TAB_IO], SW_HIDE); - - /* Rotation tab. */ - tab.pszText = message_string(NSSM_GUI_TAB_ROTATION); - tab.cchTextMax = (int) _tcslen(tab.pszText) + 1; - SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_ROTATION, (LPARAM) &tab); - tablist[NSSM_TAB_ROTATION] = dialog(MAKEINTRESOURCE(IDD_ROTATION), window, tab_dlg); - ShowWindow(tablist[NSSM_TAB_ROTATION], SW_HIDE); - - /* Set defaults. */ - SendDlgItemMessage(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_ONLINE, BM_SETCHECK, BST_UNCHECKED, 0); - SetDlgItemInt(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_SECONDS, 0, 0); - SetDlgItemInt(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_BYTES_LOW, 0, 0); - set_rotation_enabled(0); - - /* Environment tab. */ - tab.pszText = message_string(NSSM_GUI_TAB_ENVIRONMENT); - tab.cchTextMax = (int) _tcslen(tab.pszText) + 1; - SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_ENVIRONMENT, (LPARAM) &tab); - tablist[NSSM_TAB_ENVIRONMENT] = dialog(MAKEINTRESOURCE(IDD_ENVIRONMENT), window, tab_dlg); - ShowWindow(tablist[NSSM_TAB_ENVIRONMENT], SW_HIDE); - - return 1; - - /* Tab change. */ - case WM_NOTIFY: - NMHDR *notification; - - notification = (NMHDR *) l; - switch (notification->code) { - case TCN_SELCHANGE: - HWND tabs; - int selection; - - tabs = GetDlgItem(window, IDC_TAB1); - if (! tabs) return 0; - - selection = (int) SendMessage(tabs, TCM_GETCURSEL, 0, 0); - if (selection != selected_tab) { - ShowWindow(tablist[selected_tab], SW_HIDE); - ShowWindow(tablist[selection], SW_SHOWDEFAULT); - SetFocus(GetDlgItem(window, IDOK)); - selected_tab = selection; - } - return 1; - } - - return 0; - - /* Button was pressed or control was controlled */ - case WM_COMMAND: - switch (LOWORD(w)) { - /* OK button */ - case IDOK: - if ((int) GetWindowLongPtr(window, GWLP_USERDATA) == IDD_EDIT) { - if (! edit(window, (nssm_service_t *) GetWindowLongPtr(window, DWLP_USER))) PostQuitMessage(0); - } - else if (! install(window)) PostQuitMessage(0); - break; - - /* Cancel button */ - case IDCANCEL: - DestroyWindow(window); - break; - - /* Remove button */ - case IDC_REMOVE: - if (! remove(window)) PostQuitMessage(0); - break; - } - return 1; - - /* Window closing */ - case WM_CLOSE: - DestroyWindow(window); - return 0; - case WM_DESTROY: - PostQuitMessage(0); - } - return 0; -} diff --git a/Services/entpacktes_verzeichnis/nssm-2.24/src/gui.h b/Services/entpacktes_verzeichnis/nssm-2.24/src/gui.h deleted file mode 100644 index 7c13c25..0000000 --- a/Services/entpacktes_verzeichnis/nssm-2.24/src/gui.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef GUI_H -#define GUI_H - -#include -#include -#include -#include "resource.h" - -int nssm_gui(int, nssm_service_t *); -void centre_window(HWND); -int configure(HWND, nssm_service_t *, nssm_service_t *); -int install(HWND); -int remove(HWND); -int edit(HWND, nssm_service_t *); -void browse(HWND); -INT_PTR CALLBACK nssm_dlg(HWND, UINT, WPARAM, LPARAM); - -#endif diff --git a/Services/entpacktes_verzeichnis/nssm-2.24/src/imports.cpp b/Services/entpacktes_verzeichnis/nssm-2.24/src/imports.cpp deleted file mode 100644 index 6257131..0000000 --- a/Services/entpacktes_verzeichnis/nssm-2.24/src/imports.cpp +++ /dev/null @@ -1,92 +0,0 @@ -#include "nssm.h" - -imports_t imports; - -/* - Try to set up function pointers. - In this first implementation it is not an error if we can't load them - because we aren't currently trying to load any functions which we - absolutely need. If we later add some indispensible imports we can - return non-zero here to force an application exit. -*/ -HMODULE get_dll(const TCHAR *dll, unsigned long *error) { - *error = 0; - - HMODULE ret = LoadLibrary(dll); - if (! ret) { - *error = GetLastError(); - log_event(EVENTLOG_WARNING_TYPE, NSSM_EVENT_LOADLIBRARY_FAILED, dll, error_string(*error), 0); - } - - return ret; -} - -FARPROC get_import(HMODULE library, const char *function, unsigned long *error) { - *error = 0; - - FARPROC ret = GetProcAddress(library, function); - if (! ret) { - *error = GetLastError(); - TCHAR *function_name; -#ifdef UNICODE - size_t buflen; - mbstowcs_s(&buflen, NULL, 0, function, _TRUNCATE); - function_name = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, buflen * sizeof(TCHAR)); - if (function_name) mbstowcs_s(&buflen, function_name, buflen * sizeof(TCHAR), function, _TRUNCATE); -#else - function_name = (TCHAR *) function; -#endif - if (*error != ERROR_PROC_NOT_FOUND) log_event(EVENTLOG_WARNING_TYPE, NSSM_EVENT_GETPROCADDRESS_FAILED, function_name, error_string(*error), 0); -#ifdef UNICODE - if (function_name) HeapFree(GetProcessHeap(), 0, function_name); -#endif - } - - return ret; -} - -int get_imports() { - unsigned long error; - - ZeroMemory(&imports, sizeof(imports)); - - imports.kernel32 = get_dll(_T("kernel32.dll"), &error); - if (imports.kernel32) { - imports.AttachConsole = (AttachConsole_ptr) get_import(imports.kernel32, "AttachConsole", &error); - if (! imports.AttachConsole) { - if (error != ERROR_PROC_NOT_FOUND) return 2; - } - - imports.SleepConditionVariableCS = (SleepConditionVariableCS_ptr) get_import(imports.kernel32, "SleepConditionVariableCS", &error); - if (! imports.SleepConditionVariableCS) { - if (error != ERROR_PROC_NOT_FOUND) return 3; - } - - imports.WakeConditionVariable = (WakeConditionVariable_ptr) get_import(imports.kernel32, "WakeConditionVariable", &error); - if (! imports.WakeConditionVariable) { - if (error != ERROR_PROC_NOT_FOUND) return 4; - } - } - else if (error != ERROR_MOD_NOT_FOUND) return 1; - - imports.advapi32 = get_dll(_T("advapi32.dll"), &error); - if (imports.advapi32) { - imports.CreateWellKnownSid = (CreateWellKnownSid_ptr) get_import(imports.advapi32, "CreateWellKnownSid", &error); - if (! imports.CreateWellKnownSid) { - if (error != ERROR_PROC_NOT_FOUND) return 6; - } - imports.IsWellKnownSid = (IsWellKnownSid_ptr) get_import(imports.advapi32, "IsWellKnownSid", &error); - if (! imports.IsWellKnownSid) { - if (error != ERROR_PROC_NOT_FOUND) return 7; - } - } - else if (error != ERROR_MOD_NOT_FOUND) return 5; - - return 0; -} - -void free_imports() { - if (imports.kernel32) FreeLibrary(imports.kernel32); - if (imports.advapi32) FreeLibrary(imports.advapi32); - ZeroMemory(&imports, sizeof(imports)); -} diff --git a/Services/entpacktes_verzeichnis/nssm-2.24/src/imports.h b/Services/entpacktes_verzeichnis/nssm-2.24/src/imports.h deleted file mode 100644 index 03e2df1..0000000 --- a/Services/entpacktes_verzeichnis/nssm-2.24/src/imports.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef IMPORTS_H -#define IMPORTS_H - -typedef BOOL (WINAPI *AttachConsole_ptr)(DWORD); -typedef BOOL (WINAPI *SleepConditionVariableCS_ptr)(PCONDITION_VARIABLE, PCRITICAL_SECTION, DWORD); -typedef void (WINAPI *WakeConditionVariable_ptr)(PCONDITION_VARIABLE); -typedef BOOL (WINAPI *CreateWellKnownSid_ptr)(WELL_KNOWN_SID_TYPE, SID *, SID *, unsigned long *); -typedef BOOL (WINAPI *IsWellKnownSid_ptr)(SID *, WELL_KNOWN_SID_TYPE); - -typedef struct { - HMODULE kernel32; - HMODULE advapi32; - AttachConsole_ptr AttachConsole; - SleepConditionVariableCS_ptr SleepConditionVariableCS; - WakeConditionVariable_ptr WakeConditionVariable; - CreateWellKnownSid_ptr CreateWellKnownSid; - IsWellKnownSid_ptr IsWellKnownSid; -} imports_t; - -HMODULE get_dll(const TCHAR *, unsigned long *); -FARPROC get_import(HMODULE, const char *, unsigned long *); -int get_imports(); -void free_imports(); - -#endif diff --git a/Services/entpacktes_verzeichnis/nssm-2.24/src/io.cpp b/Services/entpacktes_verzeichnis/nssm-2.24/src/io.cpp deleted file mode 100644 index d311274..0000000 --- a/Services/entpacktes_verzeichnis/nssm-2.24/src/io.cpp +++ /dev/null @@ -1,560 +0,0 @@ -#include "nssm.h" - -#define COMPLAINED_READ (1 << 0) -#define COMPLAINED_WRITE (1 << 1) -#define COMPLAINED_ROTATE (1 << 2) - -static HANDLE create_logging_thread(TCHAR *service_name, TCHAR *path, unsigned long sharing, unsigned long disposition, unsigned long flags, HANDLE *read_handle_ptr, HANDLE *pipe_handle_ptr, HANDLE *write_handle_ptr, unsigned long rotate_bytes_low, unsigned long rotate_bytes_high, unsigned long *tid_ptr, unsigned long *rotate_online) { - *tid_ptr = 0; - - /* Pipe between application's stdout/stderr and our logging handle. */ - if (read_handle_ptr && ! *read_handle_ptr) { - if (pipe_handle_ptr && ! *pipe_handle_ptr) { - if (CreatePipe(read_handle_ptr, pipe_handle_ptr, 0, 0)) { - SetHandleInformation(*pipe_handle_ptr, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT); - } - else { - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_CREATEPIPE_FAILED, service_name, path, error_string(GetLastError())); - return (HANDLE) 0; - } - } - } - - logger_t *logger = (logger_t *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(logger_t)); - if (! logger) { - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, _T("logger"), _T("create_logging_thread()"), 0); - return (HANDLE) 0; - } - - ULARGE_INTEGER size; - size.LowPart = rotate_bytes_low; - size.HighPart = rotate_bytes_high; - - logger->service_name = service_name; - logger->path = path; - logger->sharing = sharing; - logger->disposition = disposition; - logger->flags = flags; - logger->read_handle = *read_handle_ptr; - logger->write_handle = *write_handle_ptr; - logger->size = (__int64) size.QuadPart; - logger->tid_ptr = tid_ptr; - logger->rotate_online = rotate_online; - - HANDLE thread_handle = CreateThread(NULL, 0, log_and_rotate, (void *) logger, 0, logger->tid_ptr); - if (! thread_handle) { - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_CREATETHREAD_FAILED, error_string(GetLastError()), 0); - HeapFree(GetProcessHeap(), 0, logger); - } - - return thread_handle; -} - -static inline unsigned long guess_charsize(void *address, unsigned long bufsize) { - if (IsTextUnicode(address, bufsize, 0)) return (unsigned long) sizeof(wchar_t); - else return (unsigned long) sizeof(char); -} - -static inline void write_bom(logger_t *logger, unsigned long *out) { - wchar_t bom = L'\ufeff'; - if (! WriteFile(logger->write_handle, (void *) &bom, sizeof(bom), out, 0)) { - log_event(EVENTLOG_WARNING_TYPE, NSSM_EVENT_SOMEBODY_SET_UP_US_THE_BOM, logger->service_name, logger->path, error_string(GetLastError()), 0); - } -} - -/* Get path, share mode, creation disposition and flags for a stream. */ -int get_createfile_parameters(HKEY key, TCHAR *prefix, TCHAR *path, unsigned long *sharing, unsigned long default_sharing, unsigned long *disposition, unsigned long default_disposition, unsigned long *flags, unsigned long default_flags) { - TCHAR value[NSSM_STDIO_LENGTH]; - - /* Path. */ - if (_sntprintf_s(value, _countof(value), _TRUNCATE, _T("%s"), prefix) < 0) { - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, prefix, _T("get_createfile_parameters()"), 0); - return 1; - } - switch (expand_parameter(key, value, path, PATH_LENGTH, true, false)) { - case 0: if (! path[0]) return 0; break; /* OK. */ - default: return 2; /* Error. */ - } - - /* ShareMode. */ - if (_sntprintf_s(value, _countof(value), _TRUNCATE, _T("%s%s"), prefix, NSSM_REG_STDIO_SHARING) < 0) { - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, NSSM_REG_STDIO_SHARING, _T("get_createfile_parameters()"), 0); - return 3; - } - switch (get_number(key, value, sharing, false)) { - case 0: *sharing = default_sharing; break; /* Missing. */ - case 1: break; /* Found. */ - case -2: return 4; break; /* Error. */ - } - - /* CreationDisposition. */ - if (_sntprintf_s(value, _countof(value), _TRUNCATE, _T("%s%s"), prefix, NSSM_REG_STDIO_DISPOSITION) < 0) { - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, NSSM_REG_STDIO_DISPOSITION, _T("get_createfile_parameters()"), 0); - return 5; - } - switch (get_number(key, value, disposition, false)) { - case 0: *disposition = default_disposition; break; /* Missing. */ - case 1: break; /* Found. */ - case -2: return 6; break; /* Error. */ - } - - /* Flags. */ - if (_sntprintf_s(value, _countof(value), _TRUNCATE, _T("%s%s"), prefix, NSSM_REG_STDIO_FLAGS) < 0) { - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, NSSM_REG_STDIO_FLAGS, _T("get_createfile_parameters()"), 0); - return 7; - } - switch (get_number(key, value, flags, false)) { - case 0: *flags = default_flags; break; /* Missing. */ - case 1: break; /* Found. */ - case -2: return 8; break; /* Error. */ - } - - return 0; -} - -int set_createfile_parameter(HKEY key, TCHAR *prefix, TCHAR *suffix, unsigned long number) { - TCHAR value[NSSM_STDIO_LENGTH]; - - if (_sntprintf_s(value, _countof(value), _TRUNCATE, _T("%s%s"), prefix, suffix) < 0) { - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, suffix, _T("set_createfile_parameter()"), 0); - return 1; - } - - return set_number(key, value, number); -} - -int delete_createfile_parameter(HKEY key, TCHAR *prefix, TCHAR *suffix) { - TCHAR value[NSSM_STDIO_LENGTH]; - - if (_sntprintf_s(value, _countof(value), _TRUNCATE, _T("%s%s"), prefix, suffix) < 0) { - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, suffix, _T("delete_createfile_parameter()"), 0); - return 1; - } - - if (RegDeleteValue(key, value)) return 0; - return 1; -} - -HANDLE write_to_file(TCHAR *path, unsigned long sharing, SECURITY_ATTRIBUTES *attributes, unsigned long disposition, unsigned long flags) { - HANDLE ret = CreateFile(path, FILE_WRITE_DATA, sharing, attributes, disposition, flags, 0); - if (ret) { - if (SetFilePointer(ret, 0, 0, FILE_END) != INVALID_SET_FILE_POINTER) SetEndOfFile(ret); - return ret; - } - - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_CREATEFILE_FAILED, path, error_string(GetLastError()), 0); - return ret; -} - -static void rotated_filename(TCHAR *path, TCHAR *rotated, unsigned long rotated_len, SYSTEMTIME *st) { - if (! st) { - SYSTEMTIME now; - st = &now; - GetSystemTime(st); - } - - TCHAR buffer[PATH_LENGTH]; - memmove(buffer, path, sizeof(buffer)); - TCHAR *ext = PathFindExtension(buffer); - TCHAR extension[PATH_LENGTH]; - _sntprintf_s(extension, _countof(extension), _TRUNCATE, _T("-%04u%02u%02uT%02u%02u%02u.%03u%s"), st->wYear, st->wMonth, st->wDay, st->wHour, st->wMinute, st->wSecond, st->wMilliseconds, ext); - *ext = _T('\0'); - _sntprintf_s(rotated, rotated_len, _TRUNCATE, _T("%s%s"), buffer, extension); -} - -void rotate_file(TCHAR *service_name, TCHAR *path, unsigned long seconds, unsigned long low, unsigned long high) { - unsigned long error; - - /* Now. */ - SYSTEMTIME st; - GetSystemTime(&st); - - BY_HANDLE_FILE_INFORMATION info; - - /* Try to open the file to check if it exists and to get attributes. */ - HANDLE file = CreateFile(path, 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); - if (file) { - /* Get file attributes. */ - if (! GetFileInformationByHandle(file, &info)) { - /* Reuse current time for rotation timestamp. */ - seconds = low = high = 0; - SystemTimeToFileTime(&st, &info.ftLastWriteTime); - } - - CloseHandle(file); - } - else { - error = GetLastError(); - if (error == ERROR_FILE_NOT_FOUND) return; - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_ROTATE_FILE_FAILED, service_name, path, _T("CreateFile()"), path, error_string(error), 0); - /* Reuse current time for rotation timestamp. */ - seconds = low = high = 0; - SystemTimeToFileTime(&st, &info.ftLastWriteTime); - } - - /* Check file age. */ - if (seconds) { - FILETIME ft; - SystemTimeToFileTime(&st, &ft); - - ULARGE_INTEGER s; - s.LowPart = ft.dwLowDateTime; - s.HighPart = ft.dwHighDateTime; - s.QuadPart -= seconds * 10000000LL; - ft.dwLowDateTime = s.LowPart; - ft.dwHighDateTime = s.HighPart; - if (CompareFileTime(&info.ftLastWriteTime, &ft) > 0) return; - } - - /* Check file size. */ - if (low || high) { - if (info.nFileSizeHigh < high) return; - if (info.nFileSizeHigh == high && info.nFileSizeLow < low) return; - } - - /* Get new filename. */ - FileTimeToSystemTime(&info.ftLastWriteTime, &st); - - TCHAR rotated[PATH_LENGTH]; - rotated_filename(path, rotated, _countof(rotated), &st); - - /* Rotate. */ - if (MoveFile(path, rotated)) { - log_event(EVENTLOG_INFORMATION_TYPE, NSSM_EVENT_ROTATED, service_name, path, rotated, 0); - return; - } - error = GetLastError(); - - if (error == ERROR_FILE_NOT_FOUND) return; - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_ROTATE_FILE_FAILED, service_name, path, _T("MoveFile()"), rotated, error_string(error), 0); - return; -} - -int get_output_handles(nssm_service_t *service, STARTUPINFO *si) { - if (! si) return 1; - - /* Allocate a new console so we get a fresh stdin, stdout and stderr. */ - alloc_console(service); - - /* stdin */ - if (service->stdin_path[0]) { - si->hStdInput = CreateFile(service->stdin_path, FILE_READ_DATA, service->stdin_sharing, 0, service->stdin_disposition, service->stdin_flags, 0); - if (! si->hStdInput) { - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_CREATEFILE_FAILED, service->stdin_path, error_string(GetLastError()), 0); - return 2; - } - } - - /* stdout */ - if (service->stdout_path[0]) { - if (service->rotate_files) rotate_file(service->name, service->stdout_path, service->rotate_seconds, service->rotate_bytes_low, service->rotate_bytes_high); - HANDLE stdout_handle = write_to_file(service->stdout_path, service->stdout_sharing, 0, service->stdout_disposition, service->stdout_flags); - if (! stdout_handle) return 4; - - if (service->rotate_files && service->rotate_stdout_online) { - service->stdout_pipe = si->hStdOutput = 0; - service->stdout_thread = create_logging_thread(service->name, service->stdout_path, service->stdout_sharing, service->stdout_disposition, service->stdout_flags, &service->stdout_pipe, &si->hStdOutput, &stdout_handle, service->rotate_bytes_low, service->rotate_bytes_high, &service->stdout_tid, &service->rotate_stdout_online); - if (! service->stdout_thread) { - CloseHandle(service->stdout_pipe); - CloseHandle(si->hStdOutput); - } - } - else service->stdout_thread = 0; - - if (! service->stdout_thread) { - if (! DuplicateHandle(GetCurrentProcess(), stdout_handle, GetCurrentProcess(), &si->hStdOutput, 0, true, DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) { - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_DUPLICATEHANDLE_FAILED, NSSM_REG_STDOUT, _T("stdout"), error_string(GetLastError()), 0); - return 4; - } - service->rotate_stdout_online = NSSM_ROTATE_OFFLINE; - } - } - - /* stderr */ - if (service->stderr_path[0]) { - /* Same as stdout? */ - if (str_equiv(service->stderr_path, service->stdout_path)) { - service->stderr_sharing = service->stdout_sharing; - service->stderr_disposition = service->stdout_disposition; - service->stderr_flags = service->stdout_flags; - service->rotate_stderr_online = NSSM_ROTATE_OFFLINE; - - /* Two handles to the same file will create a race. */ - if (! DuplicateHandle(GetCurrentProcess(), si->hStdOutput, GetCurrentProcess(), &si->hStdError, 0, true, DUPLICATE_SAME_ACCESS)) { - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_DUPLICATEHANDLE_FAILED, NSSM_REG_STDOUT, _T("stderr"), error_string(GetLastError()), 0); - return 6; - } - } - else { - if (service->rotate_files) rotate_file(service->name, service->stderr_path, service->rotate_seconds, service->rotate_bytes_low, service->rotate_bytes_high); - HANDLE stderr_handle = write_to_file(service->stderr_path, service->stderr_sharing, 0, service->stderr_disposition, service->stderr_flags); - if (! stderr_handle) return 7; - - if (service->rotate_files && service->rotate_stderr_online) { - service->stderr_pipe = si->hStdError = 0; - service->stderr_thread = create_logging_thread(service->name, service->stderr_path, service->stderr_sharing, service->stderr_disposition, service->stderr_flags, &service->stderr_pipe, &si->hStdError, &stderr_handle, service->rotate_bytes_low, service->rotate_bytes_high, &service->stderr_tid, &service->rotate_stderr_online); - if (! service->stderr_thread) { - CloseHandle(service->stderr_pipe); - CloseHandle(si->hStdError); - } - } - else service->stderr_thread = 0; - - if (! service->stderr_thread) { - if (! DuplicateHandle(GetCurrentProcess(), stderr_handle, GetCurrentProcess(), &si->hStdError, 0, true, DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) { - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_DUPLICATEHANDLE_FAILED, NSSM_REG_STDERR, _T("stderr"), error_string(GetLastError()), 0); - return 7; - } - service->rotate_stderr_online = NSSM_ROTATE_OFFLINE; - } - } - } - - /* - We need to set the startup_info flags to make the new handles - inheritable by the new process. - */ - si->dwFlags |= STARTF_USESTDHANDLES; - - if (service->no_console) return 0; - - /* Redirect other handles. */ - if (! si->hStdInput) { - if (! DuplicateHandle(GetCurrentProcess(), GetStdHandle(STD_INPUT_HANDLE), GetCurrentProcess(), &si->hStdInput, 0, true, DUPLICATE_SAME_ACCESS)) { - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_DUPLICATEHANDLE_FAILED, _T("STD_INPUT_HANDLE"), _T("stdin"), error_string(GetLastError()), 0); - return 8; - } - } - if (! si->hStdOutput) { - if (! DuplicateHandle(GetCurrentProcess(), GetStdHandle(STD_OUTPUT_HANDLE), GetCurrentProcess(), &si->hStdOutput, 0, true, DUPLICATE_SAME_ACCESS)) { - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_DUPLICATEHANDLE_FAILED, _T("STD_OUTPUT_HANDLE"), _T("stdout"), error_string(GetLastError()), 0); - return 9; - } - } - if (! si->hStdError) { - if (! DuplicateHandle(GetCurrentProcess(), GetStdHandle(STD_ERROR_HANDLE), GetCurrentProcess(), &si->hStdError, 0, true, DUPLICATE_SAME_ACCESS)) { - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_DUPLICATEHANDLE_FAILED, _T("STD_ERROR_HANDLE"), _T("stderr"), error_string(GetLastError()), 0); - return 10; - } - } - - return 0; -} - -void close_output_handles(STARTUPINFO *si) { - if (si->hStdInput) CloseHandle(si->hStdInput); - if (si->hStdOutput) CloseHandle(si->hStdOutput); - if (si->hStdError) CloseHandle(si->hStdError); -} - -/* - Try multiple times to read from a file. - Returns: 0 on success. - 1 on non-fatal error. - -1 on fatal error. -*/ -static int try_read(logger_t *logger, void *address, unsigned long bufsize, unsigned long *in, int *complained) { - int ret = 1; - unsigned long error; - for (int tries = 0; tries < 5; tries++) { - if (ReadFile(logger->read_handle, address, bufsize, in, 0)) return 0; - - error = GetLastError(); - switch (error) { - /* Other end closed the pipe. */ - case ERROR_BROKEN_PIPE: - ret = -1; - goto complain_read; - - /* Couldn't lock the buffer. */ - case ERROR_NOT_ENOUGH_QUOTA: - Sleep(2000 + tries * 3000); - ret = 1; - continue; - - /* Write was cancelled by the other end. */ - case ERROR_OPERATION_ABORTED: - ret = 1; - goto complain_read; - - default: - ret = -1; - } - } - -complain_read: - /* Ignore the error if we've been requested to exit anyway. */ - if (*logger->rotate_online != NSSM_ROTATE_ONLINE) return ret; - if (! (*complained & COMPLAINED_READ)) log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_READFILE_FAILED, logger->service_name, logger->path, error_string(error), 0); - *complained |= COMPLAINED_READ; - return ret; -} - -/* - Try multiple times to write to a file. - Returns: 0 on success. - 1 on non-fatal error. - -1 on fatal error. -*/ -static int try_write(logger_t *logger, void *address, unsigned long bufsize, unsigned long *out, int *complained) { - int ret = 1; - unsigned long error; - for (int tries = 0; tries < 5; tries++) { - if (WriteFile(logger->write_handle, address, bufsize, out, 0)) return 0; - - error = GetLastError(); - if (error == ERROR_IO_PENDING) { - /* Operation was successful pending flush to disk. */ - return 0; - } - - switch (error) { - /* Other end closed the pipe. */ - case ERROR_BROKEN_PIPE: - ret = -1; - goto complain_write; - - /* Couldn't lock the buffer. */ - case ERROR_NOT_ENOUGH_QUOTA: - /* Out of disk space. */ - case ERROR_DISK_FULL: - Sleep(2000 + tries * 3000); - ret = 1; - continue; - - default: - /* We'll lose this line but try to read and write subsequent ones. */ - ret = 1; - } - } - -complain_write: - if (! (*complained & COMPLAINED_WRITE)) log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_WRITEFILE_FAILED, logger->service_name, logger->path, error_string(error), 0); - *complained |= COMPLAINED_WRITE; - return ret; -} - -/* Wrapper to be called in a new thread for logging. */ -unsigned long WINAPI log_and_rotate(void *arg) { - logger_t *logger = (logger_t *) arg; - if (! logger) return 1; - - __int64 size; - BY_HANDLE_FILE_INFORMATION info; - - /* Find initial file size. */ - if (! GetFileInformationByHandle(logger->write_handle, &info)) logger->size = 0LL; - else { - ULARGE_INTEGER l; - l.HighPart = info.nFileSizeHigh; - l.LowPart = info.nFileSizeLow; - size = l.QuadPart; - } - - char buffer[1024]; - void *address; - unsigned long in, out; - unsigned long charsize = 0; - unsigned long error; - int ret; - int complained = 0; - - while (true) { - /* Read data from the pipe. */ - address = &buffer; - ret = try_read(logger, address, sizeof(buffer), &in, &complained); - if (ret < 0) { - CloseHandle(logger->read_handle); - CloseHandle(logger->write_handle); - HeapFree(GetProcessHeap(), 0, logger); - return 2; - } - else if (ret) continue; - - if (*logger->rotate_online == NSSM_ROTATE_ONLINE_ASAP || (logger->size && size + (__int64) in >= logger->size)) { - /* Look for newline. */ - unsigned long i; - for (i = 0; i < in; i++) { - if (buffer[i] == '\n') { - if (! charsize) charsize = guess_charsize(address, in); - i += charsize; - - /* Write up to the newline. */ - ret = try_write(logger, address, i, &out, &complained); - if (ret < 0) { - HeapFree(GetProcessHeap(), 0, logger); - CloseHandle(logger->read_handle); - CloseHandle(logger->write_handle); - return 3; - } - size += (__int64) out; - - /* Rotate. */ - *logger->rotate_online = NSSM_ROTATE_ONLINE; - TCHAR rotated[PATH_LENGTH]; - rotated_filename(logger->path, rotated, _countof(rotated), 0); - - /* - Ideally we'd try the rename first then close the handle but - MoveFile() will fail if the handle is still open so we must - risk losing everything. - */ - CloseHandle(logger->write_handle); - if (MoveFile(logger->path, rotated)) { - log_event(EVENTLOG_INFORMATION_TYPE, NSSM_EVENT_ROTATED, logger->service_name, logger->path, rotated, 0); - size = 0LL; - } - else { - error = GetLastError(); - if (error != ERROR_FILE_NOT_FOUND) { - if (! (complained & COMPLAINED_ROTATE)) log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_ROTATE_FILE_FAILED, logger->service_name, logger->path, _T("MoveFile()"), rotated, error_string(error), 0); - complained |= COMPLAINED_ROTATE; - /* We can at least try to re-open the existing file. */ - logger->disposition = OPEN_ALWAYS; - } - } - - /* Reopen. */ - logger->write_handle = write_to_file(logger->path, logger->sharing, 0, logger->disposition, logger->flags); - if (! logger->write_handle) { - error = GetLastError(); - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_CREATEFILE_FAILED, logger->path, error_string(error), 0); - /* Oh dear. Now we can't log anything further. */ - HeapFree(GetProcessHeap(), 0, logger); - CloseHandle(logger->read_handle); - CloseHandle(logger->write_handle); - return 4; - } - - /* Resume writing after the newline. */ - address = (void *) ((char *) address + i); - in -= i; - } - } - } - - if (! size) { - /* Write a BOM to the new file. */ - if (! charsize) charsize = guess_charsize(address, in); - if (charsize == sizeof(wchar_t)) write_bom(logger, &out); - size += (__int64) out; - } - - /* Write the data, if any. */ - if (! in) continue; - - ret = try_write(logger, address, in, &out, &complained); - size += (__int64) out; - if (ret < 0) { - HeapFree(GetProcessHeap(), 0, logger); - CloseHandle(logger->read_handle); - CloseHandle(logger->write_handle); - return 3; - } - } - - HeapFree(GetProcessHeap(), 0, logger); - CloseHandle(logger->read_handle); - CloseHandle(logger->write_handle); - return 0; -} diff --git a/Services/entpacktes_verzeichnis/nssm-2.24/src/io.h b/Services/entpacktes_verzeichnis/nssm-2.24/src/io.h deleted file mode 100644 index cba380b..0000000 --- a/Services/entpacktes_verzeichnis/nssm-2.24/src/io.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef IO_H -#define IO_H - -#define NSSM_STDIN_SHARING FILE_SHARE_WRITE -#define NSSM_STDIN_DISPOSITION OPEN_EXISTING -#define NSSM_STDIN_FLAGS FILE_ATTRIBUTE_NORMAL -#define NSSM_STDOUT_SHARING (FILE_SHARE_READ | FILE_SHARE_WRITE) -#define NSSM_STDOUT_DISPOSITION OPEN_ALWAYS -#define NSSM_STDOUT_FLAGS FILE_ATTRIBUTE_NORMAL -#define NSSM_STDERR_SHARING (FILE_SHARE_READ | FILE_SHARE_WRITE) -#define NSSM_STDERR_DISPOSITION OPEN_ALWAYS -#define NSSM_STDERR_FLAGS FILE_ATTRIBUTE_NORMAL - -typedef struct { - TCHAR *service_name; - TCHAR *path; - unsigned long sharing; - unsigned long disposition; - unsigned long flags; - HANDLE read_handle; - HANDLE write_handle; - __int64 size; - unsigned long *tid_ptr; - unsigned long *rotate_online; -} logger_t; - -int get_createfile_parameters(HKEY, TCHAR *, TCHAR *, unsigned long *, unsigned long, unsigned long *, unsigned long, unsigned long *, unsigned long); -int set_createfile_parameter(HKEY, TCHAR *, TCHAR *, unsigned long); -int delete_createfile_parameter(HKEY, TCHAR *, TCHAR *); -HANDLE write_to_file(TCHAR *, unsigned long, SECURITY_ATTRIBUTES *, unsigned long, unsigned long); -void rotate_file(TCHAR *, TCHAR *, unsigned long, unsigned long, unsigned long); -int get_output_handles(nssm_service_t *, STARTUPINFO *); -void close_output_handles(STARTUPINFO *); -unsigned long WINAPI log_and_rotate(void *); - -#endif diff --git a/Services/entpacktes_verzeichnis/nssm-2.24/src/messages.mc b/Services/entpacktes_verzeichnis/nssm-2.24/src/messages.mc deleted file mode 100644 index 8a06c12..0000000 Binary files a/Services/entpacktes_verzeichnis/nssm-2.24/src/messages.mc and /dev/null differ diff --git a/Services/entpacktes_verzeichnis/nssm-2.24/src/nssm.cpp b/Services/entpacktes_verzeichnis/nssm-2.24/src/nssm.cpp deleted file mode 100644 index 260ee21..0000000 --- a/Services/entpacktes_verzeichnis/nssm-2.24/src/nssm.cpp +++ /dev/null @@ -1,187 +0,0 @@ -#include "nssm.h" - -extern unsigned long tls_index; -extern bool is_admin; -extern imports_t imports; - -/* Are two strings case-insensitively equivalent? */ -int str_equiv(const TCHAR *a, const TCHAR *b) { - size_t len = _tcslen(a); - if (_tcslen(b) != len) return 0; - if (_tcsnicmp(a, b, len)) return 0; - return 1; -} - -/* Convert a string to a number. */ -int str_number(const TCHAR *string, unsigned long *number, TCHAR **bogus) { - if (! string) return 1; - - *number = _tcstoul(string, bogus, 0); - if (**bogus) return 2; - - return 0; -} - -int str_number(const TCHAR *string, unsigned long *number) { - TCHAR *bogus; - return str_number(string, number, &bogus); -} - -/* Remove basename of a path. */ -void strip_basename(TCHAR *buffer) { - size_t len = _tcslen(buffer); - size_t i; - for (i = len; i && buffer[i] != _T('\\') && buffer[i] != _T('/'); i--); - /* X:\ is OK. */ - if (i && buffer[i - 1] == _T(':')) i++; - buffer[i] = _T('\0'); -} - -/* How to use me correctly */ -int usage(int ret) { - if (GetConsoleWindow()) print_message(stderr, NSSM_MESSAGE_USAGE, NSSM_VERSION, NSSM_CONFIGURATION, NSSM_DATE); - else popup_message(0, MB_OK, NSSM_MESSAGE_USAGE, NSSM_VERSION, NSSM_CONFIGURATION, NSSM_DATE); - return(ret); -} - -void check_admin() { - is_admin = false; - - /* Lifted from MSDN examples */ - PSID AdministratorsGroup; - SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY; - if (! AllocateAndInitializeSid(&NtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &AdministratorsGroup)) return; - CheckTokenMembership(0, AdministratorsGroup, /*XXX*/(PBOOL) &is_admin); - FreeSid(AdministratorsGroup); -} - -static int elevate(int argc, TCHAR **argv, unsigned long message) { - print_message(stderr, message); - - SHELLEXECUTEINFO sei; - ZeroMemory(&sei, sizeof(sei)); - sei.cbSize = sizeof(sei); - sei.lpVerb = _T("runas"); - sei.lpFile = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, PATH_LENGTH); - if (! sei.lpFile) { - print_message(stderr, NSSM_MESSAGE_OUT_OF_MEMORY, _T("GetModuleFileName()"), _T("elevate()")); - return 111; - } - GetModuleFileName(0, (TCHAR *) sei.lpFile, PATH_LENGTH); - - TCHAR *args = (TCHAR *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, EXE_LENGTH * sizeof(TCHAR)); - if (! args) { - HeapFree(GetProcessHeap(), 0, (void *) sei.lpFile); - print_message(stderr, NSSM_MESSAGE_OUT_OF_MEMORY, _T("GetCommandLine()"), _T("elevate()")); - return 111; - } - - /* Get command line, which includes the path to NSSM, and skip that part. */ - _sntprintf_s(args, EXE_LENGTH, _TRUNCATE, _T("%s"), GetCommandLine()); - size_t s = _tcslen(argv[0]) + 1; - if (args[0] == _T('"')) s += 2; - while (isspace(args[s])) s++; - - sei.lpParameters = args + s; - sei.nShow = SW_SHOW; - - unsigned long exitcode = 0; - if (! ShellExecuteEx(&sei)) exitcode = 100; - - HeapFree(GetProcessHeap(), 0, (void *) sei.lpFile); - HeapFree(GetProcessHeap(), 0, (void *) args); - return exitcode; -} - -int num_cpus() { - DWORD_PTR i, affinity, system_affinity; - if (! GetProcessAffinityMask(GetCurrentProcess(), &affinity, &system_affinity)) return 64; - for (i = 0; system_affinity & (1LL << i); i++); - return (int) i; -} - -int _tmain(int argc, TCHAR **argv) { - check_console(); - -#ifdef UNICODE - /* - Ensure we write in UTF-16 mode, so that non-ASCII characters don't get - mangled. If we were compiled in ANSI mode it won't work. - */ - _setmode(_fileno(stdout), _O_U16TEXT); - _setmode(_fileno(stderr), _O_U16TEXT); -#endif - - /* Remember if we are admin */ - check_admin(); - - /* Set up function pointers. */ - if (get_imports()) exit(111); - - /* Elevate */ - if (argc > 1) { - /* - Valid commands are: - start, stop, pause, continue, install, edit, get, set, reset, unset, remove - */ - if (str_equiv(argv[1], _T("start"))) exit(control_service(NSSM_SERVICE_CONTROL_START, argc - 2, argv + 2)); - if (str_equiv(argv[1], _T("stop"))) exit(control_service(SERVICE_CONTROL_STOP, argc - 2, argv + 2)); - if (str_equiv(argv[1], _T("restart"))) { - int ret = control_service(SERVICE_CONTROL_STOP, argc - 2, argv + 2); - if (ret) exit(ret); - exit(control_service(NSSM_SERVICE_CONTROL_START, argc - 2, argv + 2)); - } - if (str_equiv(argv[1], _T("pause"))) exit(control_service(SERVICE_CONTROL_PAUSE, argc - 2, argv + 2)); - if (str_equiv(argv[1], _T("continue"))) exit(control_service(SERVICE_CONTROL_CONTINUE, argc - 2, argv + 2)); - if (str_equiv(argv[1], _T("status"))) exit(control_service(SERVICE_CONTROL_INTERROGATE, argc - 2, argv + 2)); - if (str_equiv(argv[1], _T("rotate"))) exit(control_service(NSSM_SERVICE_CONTROL_ROTATE, argc - 2, argv + 2)); - if (str_equiv(argv[1], _T("install"))) { - if (! is_admin) exit(elevate(argc, argv, NSSM_MESSAGE_NOT_ADMINISTRATOR_CANNOT_INSTALL)); - exit(pre_install_service(argc - 2, argv + 2)); - } - if (str_equiv(argv[1], _T("edit")) || str_equiv(argv[1], _T("get")) || str_equiv(argv[1], _T("set")) || str_equiv(argv[1], _T("reset")) || str_equiv(argv[1], _T("unset"))) { - int ret = pre_edit_service(argc - 1, argv + 1); - if (ret == 3 && ! is_admin && argc == 3) exit(elevate(argc, argv, NSSM_MESSAGE_NOT_ADMINISTRATOR_CANNOT_EDIT)); - /* There might be a password here. */ - for (int i = 0; i < argc; i++) SecureZeroMemory(argv[i], _tcslen(argv[i]) * sizeof(TCHAR)); - exit(ret); - } - if (str_equiv(argv[1], _T("remove"))) { - if (! is_admin) exit(elevate(argc, argv, NSSM_MESSAGE_NOT_ADMINISTRATOR_CANNOT_REMOVE)); - exit(pre_remove_service(argc - 2, argv + 2)); - } - } - - /* Thread local storage for error message buffer */ - tls_index = TlsAlloc(); - - /* Register messages */ - if (is_admin) create_messages(); - - /* - Optimisation for Windows 2000: - When we're run from the command line the StartServiceCtrlDispatcher() call - will time out after a few seconds on Windows 2000. On newer versions the - call returns instantly. Check for stdin first and only try to call the - function if there's no input stream found. Although it's possible that - we're running with input redirected it's much more likely that we're - actually running as a service. - This will save time when running with no arguments from a command prompt. - */ - if (! GetStdHandle(STD_INPUT_HANDLE)) { - /* Start service magic */ - SERVICE_TABLE_ENTRY table[] = { { NSSM, service_main }, { 0, 0 } }; - if (! StartServiceCtrlDispatcher(table)) { - unsigned long error = GetLastError(); - /* User probably ran nssm with no argument */ - if (error == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT) exit(usage(1)); - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_DISPATCHER_FAILED, error_string(error), 0); - free_imports(); - exit(100); - } - } - else exit(usage(1)); - - /* And nothing more to do */ - exit(0); -} diff --git a/Services/entpacktes_verzeichnis/nssm-2.24/src/nssm.h b/Services/entpacktes_verzeichnis/nssm-2.24/src/nssm.h deleted file mode 100644 index 9dc1486..0000000 --- a/Services/entpacktes_verzeichnis/nssm-2.24/src/nssm.h +++ /dev/null @@ -1,136 +0,0 @@ -#ifndef NSSM_H -#define NSSM_H - -/* - MSDN says, basically, that the maximum length of a path is 260 characters, - which is represented by the constant MAX_PATH. Except when it isn't. - - The maximum length of a directory path is MAX_PATH - 12 because it must be - possible to create a file in 8.3 format under any valid directory. - - Unicode versions of filesystem API functions accept paths up to 32767 - characters if the first four (wide) characters are L"\\?\" and each component - of the path, separated by L"\", does not exceed the value of - lpMaximumComponentLength returned by GetVolumeInformation(), which is - probably 255. But might not be. - - Relative paths are always limited to MAX_PATH because the L"\\?\" prefix - is not valid for a relative path. - - Note that we don't care about the last two paragraphs because we're only - concerned with allocating buffers big enough to store valid paths. If the - user tries to store invalid paths they will fit in the buffers but the - application will fail. The reason for the failure will end up in the - event log and the user will realise the mistake. - - So that's that cleared up, then. -*/ -#ifdef UNICODE -#define PATH_LENGTH 32767 -#else -#define PATH_LENGTH MAX_PATH -#endif -#define DIR_LENGTH PATH_LENGTH - 12 - -#define _WIN32_WINNT 0x0500 -#include -#include -#include -#include -#include -#include -#include -#include "service.h" -#include "account.h" -#include "console.h" -#include "env.h" -#include "event.h" -#include "imports.h" -#include "messages.h" -#include "process.h" -#include "registry.h" -#include "settings.h" -#include "io.h" -#include "gui.h" - -int str_equiv(const TCHAR *, const TCHAR *); -void strip_basename(TCHAR *); -int str_number(const TCHAR *, unsigned long *, TCHAR **); -int str_number(const TCHAR *, unsigned long *); -int num_cpus(); -int usage(int); - -#define NSSM _T("NSSM") -#ifdef _WIN64 -#define NSSM_ARCHITECTURE _T("64-bit") -#else -#define NSSM_ARCHITECTURE _T("32-bit") -#endif -#ifdef _DEBUG -#define NSSM_DEBUG _T(" debug") -#else -#define NSSM_DEBUG _T("") -#endif -#define NSSM_CONFIGURATION NSSM_ARCHITECTURE NSSM_DEBUG -#include "version.h" - -/* - Throttle the restart of the service if it stops before this many - milliseconds have elapsed since startup. Override in registry. -*/ -#define NSSM_RESET_THROTTLE_RESTART 1500 - -/* - How many milliseconds to wait for the application to die after sending - a Control-C event to its console. Override in registry. -*/ -#define NSSM_KILL_CONSOLE_GRACE_PERIOD 1500 -/* - How many milliseconds to wait for the application to die after posting to - its windows' message queues. Override in registry. -*/ -#define NSSM_KILL_WINDOW_GRACE_PERIOD 1500 -/* - How many milliseconds to wait for the application to die after posting to - its threads' message queues. Override in registry. -*/ -#define NSSM_KILL_THREADS_GRACE_PERIOD 1500 - -/* Margin of error for service status wait hints in milliseconds. */ -#define NSSM_WAITHINT_MARGIN 2000 - -/* Methods used to try to stop the application. */ -#define NSSM_STOP_METHOD_CONSOLE (1 << 0) -#define NSSM_STOP_METHOD_WINDOW (1 << 1) -#define NSSM_STOP_METHOD_THREADS (1 << 2) -#define NSSM_STOP_METHOD_TERMINATE (1 << 3) - -/* Startup types. */ -#define NSSM_STARTUP_AUTOMATIC 0 -#define NSSM_STARTUP_DELAYED 1 -#define NSSM_STARTUP_MANUAL 2 -#define NSSM_STARTUP_DISABLED 3 - -/* Exit actions. */ -#define NSSM_EXIT_RESTART 0 -#define NSSM_EXIT_IGNORE 1 -#define NSSM_EXIT_REALLY 2 -#define NSSM_EXIT_UNCLEAN 3 -#define NSSM_NUM_EXIT_ACTIONS 4 - -/* Process priority. */ -#define NSSM_REALTIME_PRIORITY 0 -#define NSSM_HIGH_PRIORITY 1 -#define NSSM_ABOVE_NORMAL_PRIORITY 2 -#define NSSM_NORMAL_PRIORITY 3 -#define NSSM_BELOW_NORMAL_PRIORITY 4 -#define NSSM_IDLE_PRIORITY 5 - -/* How many milliseconds to wait before updating service status. */ -#define NSSM_SERVICE_STATUS_DEADLINE 20000 - -/* User-defined service controls can be in the range 128-255. */ -#define NSSM_SERVICE_CONTROL_START 0 -#define NSSM_SERVICE_CONTROL_ROTATE 128 - -#endif diff --git a/Services/entpacktes_verzeichnis/nssm-2.24/src/nssm.ico b/Services/entpacktes_verzeichnis/nssm-2.24/src/nssm.ico deleted file mode 100644 index 0b1db25..0000000 Binary files a/Services/entpacktes_verzeichnis/nssm-2.24/src/nssm.ico and /dev/null differ diff --git a/Services/entpacktes_verzeichnis/nssm-2.24/src/nssm.rc b/Services/entpacktes_verzeichnis/nssm-2.24/src/nssm.rc deleted file mode 100644 index 2d13624..0000000 Binary files a/Services/entpacktes_verzeichnis/nssm-2.24/src/nssm.rc and /dev/null differ diff --git a/Services/entpacktes_verzeichnis/nssm-2.24/src/nssm.sln b/Services/entpacktes_verzeichnis/nssm-2.24/src/nssm.sln deleted file mode 100644 index f154427..0000000 --- a/Services/entpacktes_verzeichnis/nssm-2.24/src/nssm.sln +++ /dev/null @@ -1,26 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 10.00 -# Visual Studio 2008 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nssm", "nssm.vcproj", "{32995E05-606F-4D83-A2E6-C2B361B34DF1}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Release|win64 = Release|win64 - Release|win32 = Release|win32 - Debug|win64 = Debug|win64 - Debug|win32 = Debug|win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {32995E05-606F-4D83-A2E6-C2B361B34DF1}.Release|win64.ActiveCfg = Release|x64 - {32995E05-606F-4D83-A2E6-C2B361B34DF1}.Release|win64.Build.0 = Release|x64 - {32995E05-606F-4D83-A2E6-C2B361B34DF1}.Release|win32.ActiveCfg = Release|Win32 - {32995E05-606F-4D83-A2E6-C2B361B34DF1}.Release|win32.Build.0 = Release|Win32 - {32995E05-606F-4D83-A2E6-C2B361B34DF1}.Debug|win64.ActiveCfg = Debug|x64 - {32995E05-606F-4D83-A2E6-C2B361B34DF1}.Debug|win64.Build.0 = Debug|x64 - {32995E05-606F-4D83-A2E6-C2B361B34DF1}.Debug|win32.ActiveCfg = Debug|Win32 - {32995E05-606F-4D83-A2E6-C2B361B34DF1}.Debug|win32.Build.0 = Debug|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/Services/entpacktes_verzeichnis/nssm-2.24/src/nssm.vcproj b/Services/entpacktes_verzeichnis/nssm-2.24/src/nssm.vcproj deleted file mode 100644 index c6a933c..0000000 --- a/Services/entpacktes_verzeichnis/nssm-2.24/src/nssm.vcproj +++ /dev/null @@ -1,793 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Services/entpacktes_verzeichnis/nssm-2.24/src/process.cpp b/Services/entpacktes_verzeichnis/nssm-2.24/src/process.cpp deleted file mode 100644 index 624111c..0000000 --- a/Services/entpacktes_verzeichnis/nssm-2.24/src/process.cpp +++ /dev/null @@ -1,308 +0,0 @@ -#include "nssm.h" - -extern imports_t imports; - -int get_process_creation_time(HANDLE process_handle, FILETIME *ft) { - FILETIME creation_time, exit_time, kernel_time, user_time; - - if (! GetProcessTimes(process_handle, &creation_time, &exit_time, &kernel_time, &user_time)) { - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_GETPROCESSTIMES_FAILED, error_string(GetLastError()), 0); - return 1; - } - - memmove(ft, &creation_time, sizeof(creation_time)); - - return 0; -} - -int get_process_exit_time(HANDLE process_handle, FILETIME *ft) { - FILETIME creation_time, exit_time, kernel_time, user_time; - - if (! GetProcessTimes(process_handle, &creation_time, &exit_time, &kernel_time, &user_time)) { - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_GETPROCESSTIMES_FAILED, error_string(GetLastError()), 0); - return 1; - } - - if (! (exit_time.dwLowDateTime || exit_time.dwHighDateTime)) return 2; - memmove(ft, &exit_time, sizeof(exit_time)); - - return 0; -} - -int check_parent(nssm_service_t *service, PROCESSENTRY32 *pe, unsigned long ppid) { - /* Check parent process ID matches. */ - if (pe->th32ParentProcessID != ppid) return 1; - - /* - Process IDs can be reused so do a sanity check by making sure the child - has been running for less time than the parent. - Though unlikely, it's possible that the parent exited and its process ID - was already reused, so we'll also compare against its exit time. - */ - HANDLE process_handle = OpenProcess(PROCESS_QUERY_INFORMATION, false, pe->th32ProcessID); - if (! process_handle) { - TCHAR pid_string[16]; - _sntprintf_s(pid_string, _countof(pid_string), _TRUNCATE, _T("%lu"), pe->th32ProcessID); - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OPENPROCESS_FAILED, pid_string, service->name, error_string(GetLastError()), 0); - return 2; - } - - FILETIME ft; - if (get_process_creation_time(process_handle, &ft)) { - CloseHandle(process_handle); - return 3; - } - - CloseHandle(process_handle); - - /* Verify that the parent's creation time is not later. */ - if (CompareFileTime(&service->creation_time, &ft) > 0) return 4; - - /* Verify that the parent's exit time is not earlier. */ - if (CompareFileTime(&service->exit_time, &ft) < 0) return 5; - - return 0; -} - -/* Send some window messages and hope the window respects one or more. */ -int CALLBACK kill_window(HWND window, LPARAM arg) { - kill_t *k = (kill_t *) arg; - - unsigned long pid; - if (! GetWindowThreadProcessId(window, &pid)) return 1; - if (pid != k->pid) return 1; - - /* First try sending WM_CLOSE to request that the window close. */ - k->signalled |= PostMessage(window, WM_CLOSE, k->exitcode, 0); - - /* - Then tell the window that the user is logging off and it should exit - without worrying about saving any data. - */ - k->signalled |= PostMessage(window, WM_ENDSESSION, 1, ENDSESSION_CLOSEAPP | ENDSESSION_CRITICAL | ENDSESSION_LOGOFF); - - return 1; -} - -/* - Try to post a message to the message queues of threads associated with the - given process ID. Not all threads have message queues so there's no - guarantee of success, and we don't want to be left waiting for unsignalled - processes so this function returns only true if at least one thread was - successfully prodded. -*/ -int kill_threads(TCHAR *service_name, kill_t *k) { - int ret = 0; - - /* Get a snapshot of all threads in the system. */ - HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); - if (! snapshot) { - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_CREATETOOLHELP32SNAPSHOT_THREAD_FAILED, service_name, error_string(GetLastError()), 0); - return 0; - } - - THREADENTRY32 te; - ZeroMemory(&te, sizeof(te)); - te.dwSize = sizeof(te); - - if (! Thread32First(snapshot, &te)) { - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_THREAD_ENUMERATE_FAILED, service_name, error_string(GetLastError()), 0); - CloseHandle(snapshot); - return 0; - } - - /* This thread belongs to the doomed process so signal it. */ - if (te.th32OwnerProcessID == k->pid) { - ret |= PostThreadMessage(te.th32ThreadID, WM_QUIT, k->exitcode, 0); - } - - while (true) { - /* Try to get the next thread. */ - if (! Thread32Next(snapshot, &te)) { - unsigned long error = GetLastError(); - if (error == ERROR_NO_MORE_FILES) break; - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_THREAD_ENUMERATE_FAILED, service_name, error_string(GetLastError()), 0); - CloseHandle(snapshot); - return ret; - } - - if (te.th32OwnerProcessID == k->pid) { - ret |= PostThreadMessage(te.th32ThreadID, WM_QUIT, k->exitcode, 0); - } - } - - CloseHandle(snapshot); - - return ret; -} - -/* Give the process a chance to die gracefully. */ -int kill_process(nssm_service_t *service, HANDLE process_handle, unsigned long pid, unsigned long exitcode) { - /* Shouldn't happen. */ - if (! service) return 1; - if (! pid) return 1; - if (! process_handle) return 1; - - unsigned long ret; - if (GetExitCodeProcess(process_handle, &ret)) { - if (ret != STILL_ACTIVE) return 1; - } - - kill_t k = { pid, exitcode, 0 }; - - /* Try to send a Control-C event to the console. */ - if (service->stop_method & NSSM_STOP_METHOD_CONSOLE) { - if (! kill_console(service, &k)) return 1; - } - - /* - Try to post messages to the windows belonging to the given process ID. - If the process is a console application it won't have any windows so there's - no guarantee of success. - */ - if (service->stop_method & NSSM_STOP_METHOD_WINDOW) { - EnumWindows((WNDENUMPROC) kill_window, (LPARAM) &k); - if (k.signalled) { - if (! await_shutdown(service, _T(__FUNCTION__), service->kill_window_delay)) return 1; - } - } - - /* - Try to post messages to any thread message queues associated with the - process. Console applications might have them (but probably won't) so - there's still no guarantee of success. - */ - if (service->stop_method & NSSM_STOP_METHOD_THREADS) { - if (kill_threads(service->name, &k)) { - if (! await_shutdown(service, _T(__FUNCTION__), service->kill_threads_delay)) return 1; - } - } - - /* We tried being nice. Time for extreme prejudice. */ - if (service->stop_method & NSSM_STOP_METHOD_TERMINATE) { - return TerminateProcess(process_handle, exitcode); - } - - return 0; -} - -/* Simulate a Control-C event to our console (shared with the app). */ -int kill_console(nssm_service_t *service, kill_t *k) { - unsigned long ret; - - if (! service) return 1; - - /* Check we loaded AttachConsole(). */ - if (! imports.AttachConsole) return 4; - - /* Try to attach to the process's console. */ - if (! imports.AttachConsole(k->pid)) { - ret = GetLastError(); - - switch (ret) { - case ERROR_INVALID_HANDLE: - /* The app doesn't have a console. */ - return 1; - - case ERROR_GEN_FAILURE: - /* The app already exited. */ - return 2; - - case ERROR_ACCESS_DENIED: - default: - /* We already have a console. */ - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_ATTACHCONSOLE_FAILED, service->name, error_string(ret), 0); - return 3; - } - } - - /* Ignore the event ourselves. */ - ret = 0; - if (! SetConsoleCtrlHandler(0, TRUE)) { - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_SETCONSOLECTRLHANDLER_FAILED, service->name, error_string(GetLastError()), 0); - ret = 4; - } - - /* Send the event. */ - if (! ret) { - if (! GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0)) { - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_GENERATECONSOLECTRLEVENT_FAILED, service->name, error_string(GetLastError()), 0); - ret = 5; - } - } - - /* Detach from the console. */ - if (! FreeConsole()) { - log_event(EVENTLOG_WARNING_TYPE, NSSM_EVENT_FREECONSOLE_FAILED, service->name, error_string(GetLastError()), 0); - } - - /* Wait for process to exit. */ - if (await_shutdown(service, _T(__FUNCTION__), service->kill_console_delay)) ret = 6; - - return ret; -} - -void kill_process_tree(nssm_service_t *service, unsigned long pid, unsigned long exitcode, unsigned long ppid) { - /* Shouldn't happen unless the service failed to start. */ - if (! pid) return; - - TCHAR pid_string[16], code[16]; - _sntprintf_s(pid_string, _countof(pid_string), _TRUNCATE, _T("%lu"), pid); - _sntprintf_s(code, _countof(code), _TRUNCATE, _T("%lu"), exitcode); - log_event(EVENTLOG_INFORMATION_TYPE, NSSM_EVENT_KILLING, service->name, pid_string, code, 0); - - /* We will need a process handle in order to call TerminateProcess() later. */ - HANDLE process_handle = OpenProcess(SYNCHRONIZE | PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_TERMINATE, false, pid); - if (process_handle) { - /* Kill this process first, then its descendents. */ - TCHAR ppid_string[16]; - _sntprintf_s(ppid_string, _countof(ppid_string), _TRUNCATE, _T("%lu"), ppid); - log_event(EVENTLOG_INFORMATION_TYPE, NSSM_EVENT_KILL_PROCESS_TREE, pid_string, ppid_string, service->name, 0); - if (! kill_process(service, process_handle, pid, exitcode)) { - /* Maybe it already died. */ - unsigned long ret; - if (! GetExitCodeProcess(process_handle, &ret) || ret == STILL_ACTIVE) { - if (service->stop_method & NSSM_STOP_METHOD_TERMINATE) log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_TERMINATEPROCESS_FAILED, pid_string, service->name, error_string(GetLastError()), 0); - else log_event(EVENTLOG_WARNING_TYPE, NSSM_EVENT_PROCESS_STILL_ACTIVE, service->name, pid_string, NSSM, NSSM_REG_STOP_METHOD_SKIP, 0); - } - } - - CloseHandle(process_handle); - } - else log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OPENPROCESS_FAILED, pid_string, service->name, error_string(GetLastError()), 0); - - /* Get a snapshot of all processes in the system. */ - HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); - if (! snapshot) { - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_CREATETOOLHELP32SNAPSHOT_PROCESS_FAILED, service->name, error_string(GetLastError()), 0); - return; - } - - PROCESSENTRY32 pe; - ZeroMemory(&pe, sizeof(pe)); - pe.dwSize = sizeof(pe); - - if (! Process32First(snapshot, &pe)) { - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_PROCESS_ENUMERATE_FAILED, service->name, error_string(GetLastError()), 0); - CloseHandle(snapshot); - return; - } - - /* This is a child of the doomed process so kill it. */ - if (! check_parent(service, &pe, pid)) kill_process_tree(service, pe.th32ProcessID, exitcode, ppid); - - while (true) { - /* Try to get the next process. */ - if (! Process32Next(snapshot, &pe)) { - unsigned long ret = GetLastError(); - if (ret == ERROR_NO_MORE_FILES) break; - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_PROCESS_ENUMERATE_FAILED, service->name, error_string(GetLastError()), 0); - CloseHandle(snapshot); - return; - } - - if (! check_parent(service, &pe, pid)) kill_process_tree(service, pe.th32ProcessID, exitcode, ppid); - } - - CloseHandle(snapshot); -} diff --git a/Services/entpacktes_verzeichnis/nssm-2.24/src/process.h b/Services/entpacktes_verzeichnis/nssm-2.24/src/process.h deleted file mode 100644 index a79f9fd..0000000 --- a/Services/entpacktes_verzeichnis/nssm-2.24/src/process.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef PROCESS_H -#define PROCESS_H - -#include - -typedef struct { - unsigned long pid; - unsigned long exitcode; - int signalled; -} kill_t; - -int get_process_creation_time(HANDLE, FILETIME *); -int get_process_exit_time(HANDLE, FILETIME *); -int check_parent(TCHAR *, PROCESSENTRY32 *, unsigned long, FILETIME *, FILETIME *); -int CALLBACK kill_window(HWND, LPARAM); -int kill_threads(nssm_service_t *, kill_t *); -int kill_console(nssm_service_t *, kill_t *); -int kill_process(nssm_service_t *, HANDLE, unsigned long, unsigned long); -void kill_process_tree(nssm_service_t *, unsigned long, unsigned long, unsigned long); - -#endif diff --git a/Services/entpacktes_verzeichnis/nssm-2.24/src/registry.cpp b/Services/entpacktes_verzeichnis/nssm-2.24/src/registry.cpp deleted file mode 100644 index 1c8f694..0000000 --- a/Services/entpacktes_verzeichnis/nssm-2.24/src/registry.cpp +++ /dev/null @@ -1,714 +0,0 @@ -#include "nssm.h" - -extern const TCHAR *exit_action_strings[]; - -int create_messages() { - HKEY key; - - TCHAR registry[KEY_LENGTH]; - if (_sntprintf_s(registry, _countof(registry), _TRUNCATE, _T("SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\%s"), NSSM) < 0) { - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, _T("eventlog registry"), _T("create_messages()"), 0); - return 1; - } - - if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, registry, 0, 0, REG_OPTION_NON_VOLATILE, KEY_WRITE, 0, &key, 0) != ERROR_SUCCESS) { - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OPENKEY_FAILED, registry, error_string(GetLastError()), 0); - return 2; - } - - /* Get path of this program */ - TCHAR path[PATH_LENGTH]; - GetModuleFileName(0, path, _countof(path)); - - /* Try to register the module but don't worry so much on failure */ - RegSetValueEx(key, _T("EventMessageFile"), 0, REG_SZ, (const unsigned char *) path, (unsigned long) (_tcslen(path) + 1) * sizeof(TCHAR)); - unsigned long types = EVENTLOG_INFORMATION_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_ERROR_TYPE; - RegSetValueEx(key, _T("TypesSupported"), 0, REG_DWORD, (const unsigned char *) &types, sizeof(types)); - - return 0; -} - -int create_parameters(nssm_service_t *service, bool editing) { - /* Try to open the registry */ - HKEY key = open_registry(service->name, KEY_WRITE); - if (! key) return 1; - - /* Try to create the parameters */ - if (set_expand_string(key, NSSM_REG_EXE, service->exe)) { - RegDeleteKey(HKEY_LOCAL_MACHINE, NSSM_REGISTRY); - RegCloseKey(key); - return 2; - } - if (set_expand_string(key, NSSM_REG_FLAGS, service->flags)) { - RegDeleteKey(HKEY_LOCAL_MACHINE, NSSM_REGISTRY); - RegCloseKey(key); - return 3; - } - if (set_expand_string(key, NSSM_REG_DIR, service->dir)) { - RegDeleteKey(HKEY_LOCAL_MACHINE, NSSM_REGISTRY); - RegCloseKey(key); - return 4; - } - - /* Other non-default parameters. May fail. */ - if (service->priority != NORMAL_PRIORITY_CLASS) set_number(key, NSSM_REG_PRIORITY, service->priority); - else if (editing) RegDeleteValue(key, NSSM_REG_PRIORITY); - if (service->affinity) { - TCHAR *string; - if (! affinity_mask_to_string(service->affinity, &string)) { - if (RegSetValueEx(key, NSSM_REG_AFFINITY, 0, REG_SZ, (const unsigned char *) string, (unsigned long) (_tcslen(string) + 1) * sizeof(TCHAR)) != ERROR_SUCCESS) { - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_SETVALUE_FAILED, NSSM_REG_AFFINITY, error_string(GetLastError()), 0); - HeapFree(GetProcessHeap(), 0, string); - return 5; - } - } - if (string) HeapFree(GetProcessHeap(), 0, string); - } - else if (editing) RegDeleteValue(key, NSSM_REG_AFFINITY); - unsigned long stop_method_skip = ~service->stop_method; - if (stop_method_skip) set_number(key, NSSM_REG_STOP_METHOD_SKIP, stop_method_skip); - else if (editing) RegDeleteValue(key, NSSM_REG_STOP_METHOD_SKIP); - if (service->default_exit_action < NSSM_NUM_EXIT_ACTIONS) create_exit_action(service->name, exit_action_strings[service->default_exit_action], editing); - if (service->restart_delay) set_number(key, NSSM_REG_RESTART_DELAY, service->restart_delay); - else if (editing) RegDeleteValue(key, NSSM_REG_RESTART_DELAY); - if (service->throttle_delay != NSSM_RESET_THROTTLE_RESTART) set_number(key, NSSM_REG_THROTTLE, service->throttle_delay); - else if (editing) RegDeleteValue(key, NSSM_REG_THROTTLE); - if (service->kill_console_delay != NSSM_KILL_CONSOLE_GRACE_PERIOD) set_number(key, NSSM_REG_KILL_CONSOLE_GRACE_PERIOD, service->kill_console_delay); - else if (editing) RegDeleteValue(key, NSSM_REG_KILL_CONSOLE_GRACE_PERIOD); - if (service->kill_window_delay != NSSM_KILL_WINDOW_GRACE_PERIOD) set_number(key, NSSM_REG_KILL_WINDOW_GRACE_PERIOD, service->kill_window_delay); - else if (editing) RegDeleteValue(key, NSSM_REG_KILL_WINDOW_GRACE_PERIOD); - if (service->kill_threads_delay != NSSM_KILL_THREADS_GRACE_PERIOD) set_number(key, NSSM_REG_KILL_THREADS_GRACE_PERIOD, service->kill_threads_delay); - else if (editing) RegDeleteValue(key, NSSM_REG_KILL_THREADS_GRACE_PERIOD); - if (service->stdin_path[0] || editing) { - if (service->stdin_path[0]) set_expand_string(key, NSSM_REG_STDIN, service->stdin_path); - else if (editing) RegDeleteValue(key, NSSM_REG_STDIN); - if (service->stdin_sharing != NSSM_STDIN_SHARING) set_createfile_parameter(key, NSSM_REG_STDIN, NSSM_REG_STDIO_SHARING, service->stdin_sharing); - else if (editing) delete_createfile_parameter(key, NSSM_REG_STDIN, NSSM_REG_STDIO_SHARING); - if (service->stdin_disposition != NSSM_STDIN_DISPOSITION) set_createfile_parameter(key, NSSM_REG_STDIN, NSSM_REG_STDIO_DISPOSITION, service->stdin_disposition); - else if (editing) delete_createfile_parameter(key, NSSM_REG_STDIN, NSSM_REG_STDIO_DISPOSITION); - if (service->stdin_flags != NSSM_STDIN_FLAGS) set_createfile_parameter(key, NSSM_REG_STDIN, NSSM_REG_STDIO_FLAGS, service->stdin_flags); - else if (editing) delete_createfile_parameter(key, NSSM_REG_STDIN, NSSM_REG_STDIO_FLAGS); - } - if (service->stdout_path[0] || editing) { - if (service->stdout_path[0]) set_expand_string(key, NSSM_REG_STDOUT, service->stdout_path); - else if (editing) RegDeleteValue(key, NSSM_REG_STDOUT); - if (service->stdout_sharing != NSSM_STDOUT_SHARING) set_createfile_parameter(key, NSSM_REG_STDOUT, NSSM_REG_STDIO_SHARING, service->stdout_sharing); - else if (editing) delete_createfile_parameter(key, NSSM_REG_STDOUT, NSSM_REG_STDIO_SHARING); - if (service->stdout_disposition != NSSM_STDOUT_DISPOSITION) set_createfile_parameter(key, NSSM_REG_STDOUT, NSSM_REG_STDIO_DISPOSITION, service->stdout_disposition); - else if (editing) delete_createfile_parameter(key, NSSM_REG_STDOUT, NSSM_REG_STDIO_DISPOSITION); - if (service->stdout_flags != NSSM_STDOUT_FLAGS) set_createfile_parameter(key, NSSM_REG_STDOUT, NSSM_REG_STDIO_FLAGS, service->stdout_flags); - else if (editing) delete_createfile_parameter(key, NSSM_REG_STDOUT, NSSM_REG_STDIO_FLAGS); - } - if (service->stderr_path[0] || editing) { - if (service->stderr_path[0]) set_expand_string(key, NSSM_REG_STDERR, service->stderr_path); - else if (editing) RegDeleteValue(key, NSSM_REG_STDERR); - if (service->stderr_sharing != NSSM_STDERR_SHARING) set_createfile_parameter(key, NSSM_REG_STDERR, NSSM_REG_STDIO_SHARING, service->stderr_sharing); - else if (editing) delete_createfile_parameter(key, NSSM_REG_STDERR, NSSM_REG_STDIO_SHARING); - if (service->stderr_disposition != NSSM_STDERR_DISPOSITION) set_createfile_parameter(key, NSSM_REG_STDERR, NSSM_REG_STDIO_DISPOSITION, service->stderr_disposition); - else if (editing) delete_createfile_parameter(key, NSSM_REG_STDERR, NSSM_REG_STDIO_DISPOSITION); - if (service->stderr_flags != NSSM_STDERR_FLAGS) set_createfile_parameter(key, NSSM_REG_STDERR, NSSM_REG_STDIO_FLAGS, service->stderr_flags); - else if (editing) delete_createfile_parameter(key, NSSM_REG_STDERR, NSSM_REG_STDIO_FLAGS); - } - if (service->rotate_files) set_number(key, NSSM_REG_ROTATE, 1); - else if (editing) RegDeleteValue(key, NSSM_REG_ROTATE); - if (service->rotate_stdout_online) set_number(key, NSSM_REG_ROTATE_ONLINE, 1); - else if (editing) RegDeleteValue(key, NSSM_REG_ROTATE_ONLINE); - if (service->rotate_seconds) set_number(key, NSSM_REG_ROTATE_SECONDS, service->rotate_seconds); - else if (editing) RegDeleteValue(key, NSSM_REG_ROTATE_SECONDS); - if (service->rotate_bytes_low) set_number(key, NSSM_REG_ROTATE_BYTES_LOW, service->rotate_bytes_low); - else if (editing) RegDeleteValue(key, NSSM_REG_ROTATE_BYTES_LOW); - if (service->rotate_bytes_high) set_number(key, NSSM_REG_ROTATE_BYTES_HIGH, service->rotate_bytes_high); - else if (editing) RegDeleteValue(key, NSSM_REG_ROTATE_BYTES_HIGH); - if (service->no_console) set_number(key, NSSM_REG_NO_CONSOLE, 1); - else if (editing) RegDeleteValue(key, NSSM_REG_NO_CONSOLE); - - /* Environment */ - if (service->env) { - if (RegSetValueEx(key, NSSM_REG_ENV, 0, REG_MULTI_SZ, (const unsigned char *) service->env, (unsigned long) service->envlen * sizeof(TCHAR)) != ERROR_SUCCESS) { - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_SETVALUE_FAILED, NSSM_REG_ENV, error_string(GetLastError()), 0); - } - } - else if (editing) RegDeleteValue(key, NSSM_REG_ENV); - if (service->env_extra) { - if (RegSetValueEx(key, NSSM_REG_ENV_EXTRA, 0, REG_MULTI_SZ, (const unsigned char *) service->env_extra, (unsigned long) service->env_extralen * sizeof(TCHAR)) != ERROR_SUCCESS) { - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_SETVALUE_FAILED, NSSM_REG_ENV_EXTRA, error_string(GetLastError()), 0); - } - } - else if (editing) RegDeleteValue(key, NSSM_REG_ENV_EXTRA); - - /* Close registry. */ - RegCloseKey(key); - - return 0; -} - -int create_exit_action(TCHAR *service_name, const TCHAR *action_string, bool editing) { - /* Get registry */ - TCHAR registry[KEY_LENGTH]; - if (_sntprintf_s(registry, _countof(registry), _TRUNCATE, NSSM_REGISTRY _T("\\%s"), service_name, NSSM_REG_EXIT) < 0) { - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, _T("NSSM_REG_EXIT"), _T("create_exit_action()"), 0); - return 1; - } - - /* Try to open the registry */ - HKEY key; - unsigned long disposition; - if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, registry, 0, 0, REG_OPTION_NON_VOLATILE, KEY_WRITE, 0, &key, &disposition) != ERROR_SUCCESS) { - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OPENKEY_FAILED, registry, error_string(GetLastError()), 0); - return 2; - } - - /* Do nothing if the key already existed */ - if (disposition == REG_OPENED_EXISTING_KEY && ! editing) { - RegCloseKey(key); - return 0; - } - - /* Create the default value */ - if (RegSetValueEx(key, 0, 0, REG_SZ, (const unsigned char *) action_string, (unsigned long) (_tcslen(action_string) + 1) * sizeof(TCHAR)) != ERROR_SUCCESS) { - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_SETVALUE_FAILED, NSSM_REG_EXIT, error_string(GetLastError()), 0); - RegCloseKey(key); - return 3; - } - - /* Close registry */ - RegCloseKey(key); - - return 0; -} - -int get_environment(TCHAR *service_name, HKEY key, TCHAR *value, TCHAR **env, unsigned long *envlen) { - unsigned long type = REG_MULTI_SZ; - - /* Dummy test to find buffer size */ - unsigned long ret = RegQueryValueEx(key, value, 0, &type, NULL, envlen); - if (ret != ERROR_SUCCESS) { - *env = 0; - *envlen = 0; - /* The service probably doesn't have any environment configured */ - if (ret == ERROR_FILE_NOT_FOUND) return 0; - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_QUERYVALUE_FAILED, value, error_string(GetLastError()), 0); - return 1; - } - - if (type != REG_MULTI_SZ) { - *env = 0; - *envlen = 0; - log_event(EVENTLOG_WARNING_TYPE, NSSM_EVENT_INVALID_ENVIRONMENT_STRING_TYPE, value, service_name, 0); - return 2; - } - - /* Probably not possible */ - if (! *envlen) return 0; - - /* Previously initialised? */ - if (*env) HeapFree(GetProcessHeap(), 0, *env); - - *env = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, *envlen); - if (! *env) { - *envlen = 0; - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, value, _T("get_environment()"), 0); - return 3; - } - - /* Actually get the strings */ - ret = RegQueryValueEx(key, value, 0, &type, (unsigned char *) *env, envlen); - if (ret != ERROR_SUCCESS) { - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_QUERYVALUE_FAILED, value, error_string(GetLastError()), 0); - HeapFree(GetProcessHeap(), 0, *env); - *env = 0; - *envlen = 0; - return 4; - } - - return 0; -} - - -int get_string(HKEY key, TCHAR *value, TCHAR *data, unsigned long datalen, bool expand, bool sanitise, bool must_exist) { - TCHAR *buffer = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, datalen); - if (! buffer) { - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, value, _T("get_string()"), 0); - return 1; - } - - ZeroMemory(data, datalen); - - unsigned long type = REG_EXPAND_SZ; - unsigned long buflen = datalen; - - unsigned long ret = RegQueryValueEx(key, value, 0, &type, (unsigned char *) buffer, &buflen); - if (ret != ERROR_SUCCESS) { - unsigned long error = GetLastError(); - HeapFree(GetProcessHeap(), 0, buffer); - - if (ret == ERROR_FILE_NOT_FOUND) { - if (! must_exist) return 0; - } - - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_QUERYVALUE_FAILED, value, error_string(error), 0); - return 2; - } - - /* Paths aren't allowed to contain quotes. */ - if (sanitise) PathUnquoteSpaces(buffer); - - /* Do we want to expand the string? */ - if (! expand) { - if (type == REG_EXPAND_SZ) type = REG_SZ; - } - - /* Technically we shouldn't expand environment strings from REG_SZ values */ - if (type != REG_EXPAND_SZ) { - memmove(data, buffer, buflen); - HeapFree(GetProcessHeap(), 0, buffer); - return 0; - } - - ret = ExpandEnvironmentStrings((TCHAR *) buffer, data, datalen); - if (! ret || ret > datalen) { - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_EXPANDENVIRONMENTSTRINGS_FAILED, buffer, error_string(GetLastError()), 0); - HeapFree(GetProcessHeap(), 0, buffer); - return 3; - } - - HeapFree(GetProcessHeap(), 0, buffer); - return 0; -} - -int get_string(HKEY key, TCHAR *value, TCHAR *data, unsigned long datalen, bool sanitise) { - return get_string(key, value, data, datalen, false, sanitise, true); -} - -int expand_parameter(HKEY key, TCHAR *value, TCHAR *data, unsigned long datalen, bool sanitise, bool must_exist) { - return get_string(key, value, data, datalen, true, sanitise, must_exist); -} - -int expand_parameter(HKEY key, TCHAR *value, TCHAR *data, unsigned long datalen, bool sanitise) { - return expand_parameter(key, value, data, datalen, sanitise, true); -} - -/* - Sets a string in the registry. - Returns: 0 if it was set. - 1 on error. -*/ -int set_string(HKEY key, TCHAR *value, TCHAR *string, bool expand) { - unsigned long type = expand ? REG_EXPAND_SZ : REG_SZ; - if (RegSetValueEx(key, value, 0, type, (const unsigned char *) string, (unsigned long) (_tcslen(string) + 1) * sizeof(TCHAR)) == ERROR_SUCCESS) return 0; - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_SETVALUE_FAILED, value, error_string(GetLastError()), 0); - return 1; -} - -int set_string(HKEY key, TCHAR *value, TCHAR *string) { - return set_string(key, value, string, false); - return 1; -} - -int set_expand_string(HKEY key, TCHAR *value, TCHAR *string) { - return set_string(key, value, string, true); - return 1; -} - -/* - Set an unsigned long in the registry. - Returns: 0 if it was set. - 1 on error. -*/ -int set_number(HKEY key, TCHAR *value, unsigned long number) { - if (RegSetValueEx(key, value, 0, REG_DWORD, (const unsigned char *) &number, sizeof(number)) == ERROR_SUCCESS) return 0; - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_SETVALUE_FAILED, value, error_string(GetLastError()), 0); - return 1; -} - -/* - Query an unsigned long from the registry. - Returns: 1 if a number was retrieved. - 0 if none was found and must_exist is false. - -1 if none was found and must_exist is true. - -2 otherwise. -*/ -int get_number(HKEY key, TCHAR *value, unsigned long *number, bool must_exist) { - unsigned long type = REG_DWORD; - unsigned long number_len = sizeof(unsigned long); - - int ret = RegQueryValueEx(key, value, 0, &type, (unsigned char *) number, &number_len); - if (ret == ERROR_SUCCESS) return 1; - - if (ret == ERROR_FILE_NOT_FOUND) { - if (! must_exist) return 0; - } - - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_QUERYVALUE_FAILED, value, error_string(GetLastError()), 0); - if (ret == ERROR_FILE_NOT_FOUND) return -1; - - return -2; -} - -int get_number(HKEY key, TCHAR *value, unsigned long *number) { - return get_number(key, value, number, true); -} - -/* Replace NULL with CRLF. Leave NULL NULL as the end marker. */ -int format_double_null(TCHAR *dn, unsigned long dnlen, TCHAR **formatted, unsigned long *newlen) { - unsigned long i, j; - *newlen = dnlen; - - if (! *newlen) { - *formatted = 0; - return 0; - } - - for (i = 0; i < dnlen; i++) if (! dn[i] && dn[i + 1]) ++*newlen; - - *formatted = (TCHAR *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *newlen * sizeof(TCHAR)); - if (! *formatted) { - *newlen = 0; - return 1; - } - - for (i = 0, j = 0; i < dnlen; i++) { - (*formatted)[j] = dn[i]; - if (! dn[i]) { - if (dn[i + 1]) { - (*formatted)[j] = _T('\r'); - (*formatted)[++j] = _T('\n'); - } - } - j++; - } - - return 0; -} - -/* Strip CR and replace LF with NULL. */ -int unformat_double_null(TCHAR *dn, unsigned long dnlen, TCHAR **unformatted, unsigned long *newlen) { - unsigned long i, j; - *newlen = 0; - - if (! dnlen) { - *unformatted = 0; - return 0; - } - - for (i = 0; i < dnlen; i++) if (dn[i] != _T('\r')) ++*newlen; - - /* Skip blank lines. */ - for (i = 0; i < dnlen; i++) { - if (dn[i] == _T('\r') && dn[i + 1] == _T('\n')) { - /* This is the last CRLF. */ - if (i >= dnlen - 2) break; - - /* - Strip at the start of the block or if the next characters are - CRLF too. - */ - if (! i || (dn[i + 2] == _T('\r') && dn[i + 3] == _T('\n'))) { - for (j = i + 2; j < dnlen; j++) dn[j - 2] = dn[j]; - dn[dnlen--] = _T('\0'); - dn[dnlen--] = _T('\0'); - i--; - --*newlen; - } - } - } - - /* Must end with two NULLs. */ - *newlen += 2; - - *unformatted = (TCHAR *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *newlen * sizeof(TCHAR)); - if (! *unformatted) return 1; - - for (i = 0, j = 0; i < dnlen; i++) { - if (dn[i] == _T('\r')) continue; - if (dn[i] == _T('\n')) (*unformatted)[j] = _T('\0'); - else (*unformatted)[j] = dn[i]; - j++; - } - - return 0; -} - -void override_milliseconds(TCHAR *service_name, HKEY key, TCHAR *value, unsigned long *buffer, unsigned long default_value, unsigned long event) { - unsigned long type = REG_DWORD; - unsigned long buflen = sizeof(unsigned long); - bool ok = false; - unsigned long ret = RegQueryValueEx(key, value, 0, &type, (unsigned char *) buffer, &buflen); - if (ret != ERROR_SUCCESS) { - if (ret != ERROR_FILE_NOT_FOUND) { - if (type != REG_DWORD) { - TCHAR milliseconds[16]; - _sntprintf_s(milliseconds, _countof(milliseconds), _TRUNCATE, _T("%lu"), default_value); - log_event(EVENTLOG_WARNING_TYPE, event, service_name, value, milliseconds, 0); - } - else log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_QUERYVALUE_FAILED, value, error_string(GetLastError()), 0); - } - } - else ok = true; - - if (! ok) *buffer = default_value; -} - -HKEY open_registry(const TCHAR *service_name, const TCHAR *sub, REGSAM sam) { - /* Get registry */ - TCHAR registry[KEY_LENGTH]; - HKEY key; - int ret; - - if (sub) ret = _sntprintf_s(registry, _countof(registry), _TRUNCATE, NSSM_REGISTRY _T("\\%s"), service_name, sub); - else ret = _sntprintf_s(registry, _countof(registry), _TRUNCATE, NSSM_REGISTRY, service_name); - if (ret < 0) { - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, _T("NSSM_REGISTRY"), _T("open_registry()"), 0); - return 0; - } - - if (sam & KEY_WRITE) { - if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, registry, 0, 0, REG_OPTION_NON_VOLATILE, sam, 0, &key, 0) != ERROR_SUCCESS) { - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OPENKEY_FAILED, registry, error_string(GetLastError()), 0); - return 0; - } - } - else { - if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, registry, 0, sam, &key) != ERROR_SUCCESS) { - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OPENKEY_FAILED, registry, error_string(GetLastError()), 0); - return 0; - } - } - - return key; -} - -HKEY open_registry(const TCHAR *service_name, REGSAM sam) { - return open_registry(service_name, 0, sam); -} - -int get_io_parameters(nssm_service_t *service, HKEY key) { - /* stdin */ - if (get_createfile_parameters(key, NSSM_REG_STDIN, service->stdin_path, &service->stdin_sharing, NSSM_STDIN_SHARING, &service->stdin_disposition, NSSM_STDIN_DISPOSITION, &service->stdin_flags, NSSM_STDIN_FLAGS)) { - service->stdin_sharing = service->stdin_disposition = service->stdin_flags = 0; - ZeroMemory(service->stdin_path, _countof(service->stdin_path) * sizeof(TCHAR)); - return 1; - } - - /* stdout */ - if (get_createfile_parameters(key, NSSM_REG_STDOUT, service->stdout_path, &service->stdout_sharing, NSSM_STDOUT_SHARING, &service->stdout_disposition, NSSM_STDOUT_DISPOSITION, &service->stdout_flags, NSSM_STDOUT_FLAGS)) { - service->stdout_sharing = service->stdout_disposition = service->stdout_flags = 0; - ZeroMemory(service->stdout_path, _countof(service->stdout_path) * sizeof(TCHAR)); - return 2; - } - - /* stderr */ - if (get_createfile_parameters(key, NSSM_REG_STDERR, service->stderr_path, &service->stderr_sharing, NSSM_STDERR_SHARING, &service->stderr_disposition, NSSM_STDERR_DISPOSITION, &service->stderr_flags, NSSM_STDERR_FLAGS)) { - service->stderr_sharing = service->stderr_disposition = service->stderr_flags = 0; - ZeroMemory(service->stderr_path, _countof(service->stderr_path) * sizeof(TCHAR)); - return 3; - } - - return 0; -} - -int get_parameters(nssm_service_t *service, STARTUPINFO *si) { - unsigned long ret; - - /* Try to open the registry */ - HKEY key = open_registry(service->name, KEY_READ); - if (! key) return 1; - - /* Don't expand parameters when retrieving for the GUI. */ - bool expand = si ? true : false; - - /* Try to get executable file - MUST succeed */ - if (get_string(key, NSSM_REG_EXE, service->exe, sizeof(service->exe), expand, false, true)) { - RegCloseKey(key); - return 3; - } - - /* Try to get flags - may fail and we don't care */ - if (get_string(key, NSSM_REG_FLAGS, service->flags, sizeof(service->flags), expand, false, true)) { - log_event(EVENTLOG_WARNING_TYPE, NSSM_EVENT_NO_FLAGS, NSSM_REG_FLAGS, service->name, service->exe, 0); - ZeroMemory(service->flags, sizeof(service->flags)); - } - - /* Try to get startup directory - may fail and we fall back to a default */ - if (get_string(key, NSSM_REG_DIR, service->dir, sizeof(service->dir), expand, true, true) || ! service->dir[0]) { - _sntprintf_s(service->dir, _countof(service->dir), _TRUNCATE, _T("%s"), service->exe); - strip_basename(service->dir); - if (service->dir[0] == _T('\0')) { - /* Help! */ - ret = GetWindowsDirectory(service->dir, sizeof(service->dir)); - if (! ret || ret > sizeof(service->dir)) { - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_NO_DIR_AND_NO_FALLBACK, NSSM_REG_DIR, service->name, 0); - RegCloseKey(key); - return 4; - } - } - log_event(EVENTLOG_WARNING_TYPE, NSSM_EVENT_NO_DIR, NSSM_REG_DIR, service->name, service->dir, 0); - } - - /* Try to get processor affinity - may fail. */ - TCHAR buffer[512]; - if (get_string(key, NSSM_REG_AFFINITY, buffer, sizeof(buffer), false, false, false) || ! buffer[0]) service->affinity = 0LL; - else if (affinity_string_to_mask(buffer, &service->affinity)) { - log_event(EVENTLOG_WARNING_TYPE, NSSM_EVENT_BOGUS_AFFINITY_MASK, service->name, buffer); - service->affinity = 0LL; - } - else { - DWORD_PTR affinity, system_affinity; - - if (GetProcessAffinityMask(GetCurrentProcess(), &affinity, &system_affinity)) { - _int64 effective_affinity = service->affinity & system_affinity; - if (effective_affinity != service->affinity) { - TCHAR *system = 0; - if (! affinity_mask_to_string(system_affinity, &system)) { - TCHAR *effective = 0; - if (! affinity_mask_to_string(effective_affinity, &effective)) { - log_event(EVENTLOG_WARNING_TYPE, NSSM_EVENT_EFFECTIVE_AFFINITY_MASK, service->name, buffer, system, effective, 0); - } - HeapFree(GetProcessHeap(), 0, effective); - } - HeapFree(GetProcessHeap(), 0, system); - } - } - } - - /* Try to get environment variables - may fail */ - get_environment(service->name, key, NSSM_REG_ENV, &service->env, &service->envlen); - /* Environment variables to add to existing rather than replace - may fail. */ - get_environment(service->name, key, NSSM_REG_ENV_EXTRA, &service->env_extra, &service->env_extralen); - - /* Try to get priority - may fail. */ - unsigned long priority; - if (get_number(key, NSSM_REG_PRIORITY, &priority, false) == 1) { - if (priority == (priority & priority_mask())) service->priority = priority; - else log_event(EVENTLOG_WARNING_TYPE, NSSM_EVENT_BOGUS_PRIORITY, service->name, NSSM_REG_PRIORITY, 0); - } - - /* Try to get file rotation settings - may fail. */ - unsigned long rotate_files; - if (get_number(key, NSSM_REG_ROTATE, &rotate_files, false) == 1) { - if (rotate_files) service->rotate_files = true; - else service->rotate_files = false; - } - else service->rotate_files = false; - if (get_number(key, NSSM_REG_ROTATE_ONLINE, &rotate_files, false) == 1) { - if (rotate_files) service->rotate_stdout_online = service->rotate_stderr_online = true; - else service->rotate_stdout_online = service->rotate_stderr_online = false; - } - else service->rotate_stdout_online = service->rotate_stderr_online = false; - if (get_number(key, NSSM_REG_ROTATE_SECONDS, &service->rotate_seconds, false) != 1) service->rotate_seconds = 0; - if (get_number(key, NSSM_REG_ROTATE_BYTES_LOW, &service->rotate_bytes_low, false) != 1) service->rotate_bytes_low = 0; - if (get_number(key, NSSM_REG_ROTATE_BYTES_HIGH, &service->rotate_bytes_high, false) != 1) service->rotate_bytes_high = 0; - - /* Try to get force new console setting - may fail. */ - if (get_number(key, NSSM_REG_NO_CONSOLE, &service->no_console, false) != 1) service->no_console = 0; - - /* Change to startup directory in case stdout/stderr are relative paths. */ - TCHAR cwd[PATH_LENGTH]; - GetCurrentDirectory(_countof(cwd), cwd); - SetCurrentDirectory(service->dir); - - /* Try to get stdout and stderr */ - if (get_io_parameters(service, key)) { - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_GET_OUTPUT_HANDLES_FAILED, service->name, 0); - RegCloseKey(key); - SetCurrentDirectory(cwd); - return 5; - } - - /* Change back in case the startup directory needs to be deleted. */ - SetCurrentDirectory(cwd); - - /* Try to get mandatory restart delay */ - override_milliseconds(service->name, key, NSSM_REG_RESTART_DELAY, &service->restart_delay, 0, NSSM_EVENT_BOGUS_RESTART_DELAY); - - /* Try to get throttle restart delay */ - override_milliseconds(service->name, key, NSSM_REG_THROTTLE, &service->throttle_delay, NSSM_RESET_THROTTLE_RESTART, NSSM_EVENT_BOGUS_THROTTLE); - - /* Try to get service stop flags. */ - unsigned long type = REG_DWORD; - unsigned long stop_method_skip; - unsigned long buflen = sizeof(stop_method_skip); - bool stop_ok = false; - ret = RegQueryValueEx(key, NSSM_REG_STOP_METHOD_SKIP, 0, &type, (unsigned char *) &stop_method_skip, &buflen); - if (ret != ERROR_SUCCESS) { - if (ret != ERROR_FILE_NOT_FOUND) { - if (type != REG_DWORD) { - log_event(EVENTLOG_WARNING_TYPE, NSSM_EVENT_BOGUS_STOP_METHOD_SKIP, service->name, NSSM_REG_STOP_METHOD_SKIP, NSSM, 0); - } - else log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_QUERYVALUE_FAILED, NSSM_REG_STOP_METHOD_SKIP, error_string(GetLastError()), 0); - } - } - else stop_ok = true; - - /* Try all methods except those requested to be skipped. */ - service->stop_method = ~0; - if (stop_ok) service->stop_method &= ~stop_method_skip; - - /* Try to get kill delays - may fail. */ - override_milliseconds(service->name, key, NSSM_REG_KILL_CONSOLE_GRACE_PERIOD, &service->kill_console_delay, NSSM_KILL_CONSOLE_GRACE_PERIOD, NSSM_EVENT_BOGUS_KILL_CONSOLE_GRACE_PERIOD); - override_milliseconds(service->name, key, NSSM_REG_KILL_WINDOW_GRACE_PERIOD, &service->kill_window_delay, NSSM_KILL_WINDOW_GRACE_PERIOD, NSSM_EVENT_BOGUS_KILL_WINDOW_GRACE_PERIOD); - override_milliseconds(service->name, key, NSSM_REG_KILL_THREADS_GRACE_PERIOD, &service->kill_threads_delay, NSSM_KILL_THREADS_GRACE_PERIOD, NSSM_EVENT_BOGUS_KILL_THREADS_GRACE_PERIOD); - - /* Try to get default exit action. */ - bool default_action; - service->default_exit_action = NSSM_EXIT_RESTART; - TCHAR action_string[ACTION_LEN]; - if (! get_exit_action(service->name, 0, action_string, &default_action)) { - for (int i = 0; exit_action_strings[i]; i++) { - if (! _tcsnicmp((const TCHAR *) action_string, exit_action_strings[i], ACTION_LEN)) { - service->default_exit_action = i; - break; - } - } - } - - /* Close registry */ - RegCloseKey(key); - - return 0; -} - -/* - Sets the string for the exit action corresponding to the exit code. - - ret is a pointer to an unsigned long containing the exit code. - If ret is NULL, we retrieve the default exit action unconditionally. - - action is a buffer which receives the string. - - default_action is a pointer to a bool which is set to false if there - was an explicit string for the given exit code, or true if we are - returning the default action. - - Returns: 0 on success. - 1 on error. -*/ -int get_exit_action(const TCHAR *service_name, unsigned long *ret, TCHAR *action, bool *default_action) { - /* Are we returning the default action or a status-specific one? */ - *default_action = ! ret; - - /* Try to open the registry */ - HKEY key = open_registry(service_name, NSSM_REG_EXIT, KEY_READ); - if (! key) return 1; - - unsigned long type = REG_SZ; - unsigned long action_len = ACTION_LEN; - - TCHAR code[16]; - if (! ret) code[0] = _T('\0'); - else if (_sntprintf_s(code, _countof(code), _TRUNCATE, _T("%lu"), *ret) < 0) { - RegCloseKey(key); - return get_exit_action(service_name, 0, action, default_action); - } - if (RegQueryValueEx(key, code, 0, &type, (unsigned char *) action, &action_len) != ERROR_SUCCESS) { - RegCloseKey(key); - /* Try again with * as the key if an exit code was defined */ - if (ret) return get_exit_action(service_name, 0, action, default_action); - return 0; - } - - /* Close registry */ - RegCloseKey(key); - - return 0; -} diff --git a/Services/entpacktes_verzeichnis/nssm-2.24/src/registry.h b/Services/entpacktes_verzeichnis/nssm-2.24/src/registry.h deleted file mode 100644 index cb2b208..0000000 --- a/Services/entpacktes_verzeichnis/nssm-2.24/src/registry.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef REGISTRY_H -#define REGISTRY_H - -#define NSSM_REGISTRY _T("SYSTEM\\CurrentControlSet\\Services\\%s\\Parameters") -#define NSSM_REGISTRY_GROUPS _T("SYSTEM\\CurrentControlSet\\Control\\ServiceGroupOrder") -#define NSSM_REG_GROUPS _T("List") -#define NSSM_REG_EXE _T("Application") -#define NSSM_REG_FLAGS _T("AppParameters") -#define NSSM_REG_DIR _T("AppDirectory") -#define NSSM_REG_ENV _T("AppEnvironment") -#define NSSM_REG_ENV_EXTRA _T("AppEnvironmentExtra") -#define NSSM_REG_EXIT _T("AppExit") -#define NSSM_REG_RESTART_DELAY _T("AppRestartDelay") -#define NSSM_REG_THROTTLE _T("AppThrottle") -#define NSSM_REG_STOP_METHOD_SKIP _T("AppStopMethodSkip") -#define NSSM_REG_KILL_CONSOLE_GRACE_PERIOD _T("AppStopMethodConsole") -#define NSSM_REG_KILL_WINDOW_GRACE_PERIOD _T("AppStopMethodWindow") -#define NSSM_REG_KILL_THREADS_GRACE_PERIOD _T("AppStopMethodThreads") -#define NSSM_REG_STDIN _T("AppStdin") -#define NSSM_REG_STDOUT _T("AppStdout") -#define NSSM_REG_STDERR _T("AppStderr") -#define NSSM_REG_STDIO_SHARING _T("ShareMode") -#define NSSM_REG_STDIO_DISPOSITION _T("CreationDisposition") -#define NSSM_REG_STDIO_FLAGS _T("FlagsAndAttributes") -#define NSSM_REG_ROTATE _T("AppRotateFiles") -#define NSSM_REG_ROTATE_ONLINE _T("AppRotateOnline") -#define NSSM_REG_ROTATE_SECONDS _T("AppRotateSeconds") -#define NSSM_REG_ROTATE_BYTES_LOW _T("AppRotateBytes") -#define NSSM_REG_ROTATE_BYTES_HIGH _T("AppRotateBytesHigh") -#define NSSM_REG_PRIORITY _T("AppPriority") -#define NSSM_REG_AFFINITY _T("AppAffinity") -#define NSSM_REG_NO_CONSOLE _T("AppNoConsole") -#define NSSM_STDIO_LENGTH 29 - -HKEY open_registry(const TCHAR *, const TCHAR *, REGSAM sam); -HKEY open_registry(const TCHAR *, REGSAM sam); -int create_messages(); -int create_parameters(nssm_service_t *, bool); -int create_exit_action(TCHAR *, const TCHAR *, bool); -int get_environment(TCHAR *, HKEY, TCHAR *, TCHAR **, unsigned long *); -int get_string(HKEY, TCHAR *, TCHAR *, unsigned long, bool, bool, bool); -int get_string(HKEY, TCHAR *, TCHAR *, unsigned long, bool); -int expand_parameter(HKEY, TCHAR *, TCHAR *, unsigned long, bool, bool); -int expand_parameter(HKEY, TCHAR *, TCHAR *, unsigned long, bool); -int set_string(HKEY, TCHAR *, TCHAR *, bool); -int set_string(HKEY, TCHAR *, TCHAR *); -int set_expand_string(HKEY, TCHAR *, TCHAR *); -int set_number(HKEY, TCHAR *, unsigned long); -int get_number(HKEY, TCHAR *, unsigned long *, bool); -int get_number(HKEY, TCHAR *, unsigned long *); -int format_double_null(TCHAR *, unsigned long, TCHAR **, unsigned long *); -int unformat_double_null(TCHAR *, unsigned long, TCHAR **, unsigned long *); -void override_milliseconds(TCHAR *, HKEY, TCHAR *, unsigned long *, unsigned long, unsigned long); -int get_io_parameters(nssm_service_t *, HKEY); -int get_parameters(nssm_service_t *, STARTUPINFO *); -int get_exit_action(const TCHAR *, unsigned long *, TCHAR *, bool *); - -#endif diff --git a/Services/entpacktes_verzeichnis/nssm-2.24/src/resource.h b/Services/entpacktes_verzeichnis/nssm-2.24/src/resource.h deleted file mode 100644 index 1e3500a..0000000 --- a/Services/entpacktes_verzeichnis/nssm-2.24/src/resource.h +++ /dev/null @@ -1,78 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Developer Studio generated include file. -// Used by nssm.rc -// -#define IDC_STATIC (-1) -#define IDI_NSSM 101 -#define IDD_INSTALL 102 -#define IDD_REMOVE 103 -#define IDD_EDIT 104 -#define IDD_APPLICATION 105 -#define IDD_DETAILS 106 -#define IDD_LOGON 107 -#define IDD_IO 108 -#define IDD_ROTATION 109 -#define IDD_APPEXIT 110 -#define IDD_SHUTDOWN 111 -#define IDD_ENVIRONMENT 112 -#define IDD_NATIVE 113 -#define IDD_PROCESS 114 -#define IDD_DEPENDENCIES 115 -#define IDC_PATH 1000 -#define IDC_TAB1 1001 -#define IDC_CANCEL 1002 -#define IDC_BROWSE 1003 -#define IDC_FLAGS 1004 -#define IDC_NAME 1005 -#define IDC_REMOVE 1007 -#define IDC_METHOD_CONSOLE 1008 -#define IDC_METHOD_WINDOW 1009 -#define IDC_METHOD_THREADS 1010 -#define IDC_METHOD_TERMINATE 1011 -#define IDC_KILL_CONSOLE 1012 -#define IDC_KILL_WINDOW 1013 -#define IDC_KILL_THREADS 1014 -#define IDC_STDIN 1015 -#define IDC_STDOUT 1016 -#define IDC_STDERR 1017 -#define IDC_BROWSE_STDIN 1018 -#define IDC_BROWSE_STDOUT 1019 -#define IDC_BROWSE_STDERR 1020 -#define IDC_THROTTLE 1021 -#define IDC_APPEXIT 1022 -#define IDC_RESTART_DELAY 1023 -#define IDC_DIR 1024 -#define IDC_BROWSE_DIR 1025 -#define IDC_ENVIRONMENT 1026 -#define IDC_ENVIRONMENT_REPLACE 1027 -#define IDC_TRUNCATE 1028 -#define IDC_ROTATE 1029 -#define IDC_ROTATE_ONLINE 1030 -#define IDC_ROTATE_SECONDS 1031 -#define IDC_ROTATE_BYTES_LOW 1032 -#define IDC_DISPLAYNAME 1033 -#define IDC_DESCRIPTION 1034 -#define IDC_STARTUP 1035 -#define IDC_LOCALSYSTEM 1036 -#define IDC_INTERACT 1037 -#define IDC_ACCOUNT 1038 -#define IDC_USERNAME 1039 -#define IDC_PASSWORD1 1040 -#define IDC_PASSWORD2 1041 -#define IDC_PRIORITY 1042 -#define IDC_AFFINITY_ALL 1043 -#define IDC_AFFINITY 1044 -#define IDC_CONSOLE 1045 -#define IDC_DEPENDENCIES 1046 - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 115 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1047 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif - diff --git a/Services/entpacktes_verzeichnis/nssm-2.24/src/service.cpp b/Services/entpacktes_verzeichnis/nssm-2.24/src/service.cpp deleted file mode 100644 index 0bb5ff6..0000000 --- a/Services/entpacktes_verzeichnis/nssm-2.24/src/service.cpp +++ /dev/null @@ -1,1976 +0,0 @@ -#include "nssm.h" - -bool is_admin; -bool use_critical_section; - -extern imports_t imports; -extern settings_t settings[]; - -const TCHAR *exit_action_strings[] = { _T("Restart"), _T("Ignore"), _T("Exit"), _T("Suicide"), 0 }; -const TCHAR *startup_strings[] = { _T("SERVICE_AUTO_START"), _T("SERVICE_DELAYED_AUTO_START"), _T("SERVICE_DEMAND_START"), _T("SERVICE_DISABLED"), 0 }; -const TCHAR *priority_strings[] = { _T("REALTIME_PRIORITY_CLASS"), _T("HIGH_PRIORITY_CLASS"), _T("ABOVE_NORMAL_PRIORITY_CLASS"), _T("NORMAL_PRIORITY_CLASS"), _T("BELOW_NORMAL_PRIORITY_CLASS"), _T("IDLE_PRIORITY_CLASS"), 0 }; - -typedef struct { - int first; - int last; -} list_t; - -/* - Check the status in response to a control. - Returns: 1 if the status is expected, eg STOP following CONTROL_STOP. - 0 if the status is desired, eg STOPPED following CONTROL_STOP. - -1 if the status is undesired, eg STOPPED following CONTROL_START. -*/ -static inline int service_control_response(unsigned long control, unsigned long status) { - switch (control) { - case NSSM_SERVICE_CONTROL_START: - switch (status) { - case SERVICE_START_PENDING: - return 1; - - case SERVICE_RUNNING: - return 0; - - default: - return -1; - } - - case SERVICE_CONTROL_STOP: - case SERVICE_CONTROL_SHUTDOWN: - switch (status) { - case SERVICE_STOP_PENDING: - return 1; - - case SERVICE_STOPPED: - return 0; - - default: - return -1; - } - - case SERVICE_CONTROL_PAUSE: - switch (status) { - case SERVICE_PAUSE_PENDING: - return 1; - - case SERVICE_PAUSED: - return 0; - - default: - return -1; - } - - case SERVICE_CONTROL_CONTINUE: - switch (status) { - case SERVICE_CONTINUE_PENDING: - return 1; - - case SERVICE_RUNNING: - return 0; - - default: - return -1; - } - - case SERVICE_CONTROL_INTERROGATE: - return 0; - } - - return 0; -} - -static inline int await_service_control_response(unsigned long control, SC_HANDLE service_handle, SERVICE_STATUS *service_status, unsigned long initial_status) { - int tries = 0; - while (QueryServiceStatus(service_handle, service_status)) { - int response = service_control_response(control, service_status->dwCurrentState); - /* Alas we can't WaitForSingleObject() on an SC_HANDLE. */ - if (! response) return response; - if (response > 0 || service_status->dwCurrentState == initial_status) { - if (++tries > 10) return response; - Sleep(50 * tries); - } - else return response; - } - return -1; -} - -int affinity_mask_to_string(__int64 mask, TCHAR **string) { - if (! string) return 1; - if (! mask) { - *string = 0; - return 0; - } - - __int64 i, n; - - /* SetProcessAffinityMask() accepts a mask of up to 64 processors. */ - list_t set[64]; - for (n = 0; n < _countof(set); n++) set[n].first = set[n].last = -1; - - for (i = 0, n = 0; i < _countof(set); i++) { - if (mask & (1LL << i)) { - if (set[n].first == -1) set[n].first = set[n].last = (int) i; - else if (set[n].last == (int) i - 1) set[n].last = (int) i; - else { - n++; - set[n].first = set[n].last = (int) i; - } - } - } - - /* Worst case is 2x2 characters for first and last CPU plus - and/or , */ - size_t len = (size_t) (n + 1) * 6; - *string = (TCHAR *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof(TCHAR)); - if (! string) return 2; - - size_t s = 0; - int ret; - for (i = 0; i <= n; i++) { - if (i) (*string)[s++] = _T(','); - ret = _sntprintf_s(*string + s, 3, _TRUNCATE, _T("%u"), set[i].first); - if (ret < 0) { - HeapFree(GetProcessHeap(), 0, *string); - *string = 0; - return 3; - } - else s += ret; - if (set[i].last != set[i].first) { - ret =_sntprintf_s(*string + s, 4, _TRUNCATE, _T("%c%u"), (set[i].last == set[i].first + 1) ? _T(',') : _T('-'), set[i].last); - if (ret < 0) { - HeapFree(GetProcessHeap(), 0, *string); - *string = 0; - return 4; - } - else s += ret; - } - } - - return 0; -} - -int affinity_string_to_mask(TCHAR *string, __int64 *mask) { - if (! mask) return 1; - - *mask = 0LL; - if (! string) return 0; - - list_t set[64]; - - TCHAR *s = string; - TCHAR *end; - int ret; - int i; - int n = 0; - unsigned long number; - - for (n = 0; n < _countof(set); n++) set[n].first = set[n].last = -1; - n = 0; - - while (*s) { - ret = str_number(s, &number, &end); - s = end; - if (ret == 0 || ret == 2) { - if (number >= _countof(set)) return 2; - set[n].first = set[n].last = (int) number; - - switch (*s) { - case 0: - break; - - case _T(','): - n++; - s++; - break; - - case _T('-'): - if (! *(++s)) return 3; - ret = str_number(s, &number, &end); - if (ret == 0 || ret == 2) { - s = end; - if (! *s || *s == _T(',')) { - set[n].last = (int) number; - if (! *s) break; - n++; - s++; - } - else return 3; - } - else return 3; - break; - - default: - return 3; - } - } - else return 4; - } - - for (i = 0; i <= n; i++) { - for (int j = set[i].first; j <= set[i].last; j++) (__int64) *mask |= (1LL << (__int64) j); - } - - return 0; -} - -inline unsigned long priority_mask() { - return REALTIME_PRIORITY_CLASS | HIGH_PRIORITY_CLASS | ABOVE_NORMAL_PRIORITY_CLASS | NORMAL_PRIORITY_CLASS | BELOW_NORMAL_PRIORITY_CLASS | IDLE_PRIORITY_CLASS; -} - -int priority_constant_to_index(unsigned long constant) { - switch (constant & priority_mask()) { - case REALTIME_PRIORITY_CLASS: return NSSM_REALTIME_PRIORITY; - case HIGH_PRIORITY_CLASS: return NSSM_HIGH_PRIORITY; - case ABOVE_NORMAL_PRIORITY_CLASS: return NSSM_ABOVE_NORMAL_PRIORITY; - case BELOW_NORMAL_PRIORITY_CLASS: return NSSM_BELOW_NORMAL_PRIORITY; - case IDLE_PRIORITY_CLASS: return NSSM_IDLE_PRIORITY; - } - return NSSM_NORMAL_PRIORITY; -} - -unsigned long priority_index_to_constant(int index) { - switch (index) { - case NSSM_REALTIME_PRIORITY: return REALTIME_PRIORITY_CLASS; - case NSSM_HIGH_PRIORITY: return HIGH_PRIORITY_CLASS; - case NSSM_ABOVE_NORMAL_PRIORITY: return ABOVE_NORMAL_PRIORITY_CLASS; - case NSSM_BELOW_NORMAL_PRIORITY: return BELOW_NORMAL_PRIORITY_CLASS; - case NSSM_IDLE_PRIORITY: return IDLE_PRIORITY_CLASS; - } - return NORMAL_PRIORITY_CLASS; -} - -static inline unsigned long throttle_milliseconds(unsigned long throttle) { - /* pow() operates on doubles. */ - unsigned long ret = 1; for (unsigned long i = 1; i < throttle; i++) ret *= 2; - return ret * 1000; -} - -/* - Wrapper to be called in a new thread so that we can acknowledge a STOP - control immediately. -*/ -static unsigned long WINAPI shutdown_service(void *arg) { - return stop_service((nssm_service_t *) arg, 0, true, true); -} - -/* Connect to the service manager */ -SC_HANDLE open_service_manager(unsigned long access) { - SC_HANDLE ret = OpenSCManager(0, SERVICES_ACTIVE_DATABASE, access); - if (! ret) { - if (is_admin) log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OPENSCMANAGER_FAILED, 0); - return 0; - } - - return ret; -} - -/* Open a service by name or display name. */ -SC_HANDLE open_service(SC_HANDLE services, TCHAR *service_name, unsigned long access, TCHAR *canonical_name, unsigned long canonical_namelen) { - SC_HANDLE service_handle = OpenService(services, service_name, access); - if (service_handle) { - if (canonical_name && canonical_name != service_name) { - TCHAR displayname[SERVICE_NAME_LENGTH]; - unsigned long displayname_len = (unsigned long) _countof(displayname); - GetServiceDisplayName(services, service_name, displayname, &displayname_len); - unsigned long keyname_len = canonical_namelen; - GetServiceKeyName(services, displayname, canonical_name, &keyname_len); - } - return service_handle; - } - - unsigned long error = GetLastError(); - if (error != ERROR_SERVICE_DOES_NOT_EXIST) { - print_message(stderr, NSSM_MESSAGE_OPENSERVICE_FAILED, error_string(GetLastError())); - return 0; - } - - /* We can't look for a display name because there's no buffer to store it. */ - if (! canonical_name) { - print_message(stderr, NSSM_MESSAGE_OPENSERVICE_FAILED, error_string(GetLastError())); - return 0; - } - - unsigned long bufsize, required, count, i; - unsigned long resume = 0; - EnumServicesStatus(services, SERVICE_DRIVER | SERVICE_FILE_SYSTEM_DRIVER | SERVICE_KERNEL_DRIVER | SERVICE_WIN32, SERVICE_STATE_ALL, 0, 0, &required, &count, &resume); - error = GetLastError(); - if (error != ERROR_MORE_DATA) { - print_message(stderr, NSSM_MESSAGE_ENUMSERVICESSTATUS_FAILED, error_string(GetLastError())); - return 0; - } - - ENUM_SERVICE_STATUS *status = (ENUM_SERVICE_STATUS *) HeapAlloc(GetProcessHeap(), 0, required); - if (! status) { - print_message(stderr, NSSM_MESSAGE_OUT_OF_MEMORY, _T("ENUM_SERVICE_STATUS"), _T("open_service()")); - return 0; - } - - bufsize = required; - while (true) { - /* - EnumServicesStatus() returns: - 1 when it retrieved data and there's no more data to come. - 0 and sets last error to ERROR_MORE_DATA when it retrieved data and - there's more data to come. - 0 and sets last error to something else on error. - */ - int ret = EnumServicesStatus(services, SERVICE_DRIVER | SERVICE_FILE_SYSTEM_DRIVER | SERVICE_KERNEL_DRIVER | SERVICE_WIN32, SERVICE_STATE_ALL, status, bufsize, &required, &count, &resume); - if (! ret) { - error = GetLastError(); - if (error != ERROR_MORE_DATA) { - HeapFree(GetProcessHeap(), 0, status); - print_message(stderr, NSSM_MESSAGE_ENUMSERVICESSTATUS_FAILED, error_string(GetLastError())); - return 0; - } - } - - for (i = 0; i < count; i++) { - if (str_equiv(status[i].lpDisplayName, service_name)) { - if (_sntprintf_s(canonical_name, canonical_namelen, _TRUNCATE, _T("%s"), status[i].lpServiceName) < 0) { - HeapFree(GetProcessHeap(), 0, status); - print_message(stderr, NSSM_MESSAGE_OUT_OF_MEMORY, _T("canonical_name"), _T("open_service()")); - return 0; - } - - HeapFree(GetProcessHeap(), 0, status); - return open_service(services, canonical_name, access, 0, 0); - } - } - - if (ret) break; - } - - /* Recurse so we can get an error message. */ - return open_service(services, service_name, access, 0, 0); -} - -QUERY_SERVICE_CONFIG *query_service_config(const TCHAR *service_name, SC_HANDLE service_handle) { - QUERY_SERVICE_CONFIG *qsc; - unsigned long bufsize; - unsigned long error; - - QueryServiceConfig(service_handle, 0, 0, &bufsize); - error = GetLastError(); - if (error == ERROR_INSUFFICIENT_BUFFER) { - qsc = (QUERY_SERVICE_CONFIG *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, bufsize); - if (! qsc) { - print_message(stderr, NSSM_MESSAGE_OUT_OF_MEMORY, _T("QUERY_SERVICE_CONFIG"), _T("query_service_config()"), 0); - return 0; - } - } - else { - print_message(stderr, NSSM_MESSAGE_QUERYSERVICECONFIG_FAILED, service_name, error_string(error), 0); - return 0; - } - - if (! QueryServiceConfig(service_handle, qsc, bufsize, &bufsize)) { - HeapFree(GetProcessHeap(), 0, qsc); - print_message(stderr, NSSM_MESSAGE_QUERYSERVICECONFIG_FAILED, service_name, error_string(GetLastError()), 0); - return 0; - } - - return qsc; -} - -int set_service_dependencies(const TCHAR *service_name, SC_HANDLE service_handle, TCHAR *buffer) { - TCHAR *dependencies = _T(""); - unsigned long num_dependencies = 0; - - if (buffer && buffer[0]) { - SC_HANDLE services = open_service_manager(SC_MANAGER_CONNECT | SC_MANAGER_ENUMERATE_SERVICE); - if (! services) { - print_message(stderr, NSSM_MESSAGE_OPEN_SERVICE_MANAGER_FAILED); - return 1; - } - - /* - Count the dependencies then allocate a buffer big enough for their - canonical names, ie n * SERVICE_NAME_LENGTH. - */ - TCHAR *s; - TCHAR *groups = 0; - for (s = buffer; *s; s++) { - num_dependencies++; - if (*s == SC_GROUP_IDENTIFIER) groups = s; - while (*s) s++; - } - - /* At least one dependency is a group so we need to verify them. */ - if (groups) { - HKEY key; - if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, NSSM_REGISTRY_GROUPS, 0, KEY_READ, &key)) { - _ftprintf(stderr, _T("%s: %s\n"), NSSM_REGISTRY_GROUPS, error_string(GetLastError())); - return 2; - } - - unsigned long type; - unsigned long groupslen; - unsigned long ret = RegQueryValueEx(key, NSSM_REG_GROUPS, 0, &type, NULL, &groupslen); - if (ret == ERROR_SUCCESS) { - groups = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, groupslen); - if (! groups) { - print_message(stderr, NSSM_MESSAGE_OUT_OF_MEMORY, _T("groups"), _T("set_service_dependencies()")); - return 3; - } - - ret = RegQueryValueEx(key, NSSM_REG_GROUPS, 0, &type, (unsigned char *) groups, &groupslen); - if (ret != ERROR_SUCCESS) { - _ftprintf(stderr, _T("%s\\%s: %s"), NSSM_REGISTRY_GROUPS, NSSM_REG_GROUPS, error_string(GetLastError())); - HeapFree(GetProcessHeap(), 0, groups); - RegCloseKey(key); - return 4; - } - } - else if (ret != ERROR_FILE_NOT_FOUND) { - _ftprintf(stderr, _T("%s\\%s: %s"), NSSM_REGISTRY_GROUPS, NSSM_REG_GROUPS, error_string(GetLastError())); - RegCloseKey(key); - return 4; - } - - RegCloseKey(key); - - } - - unsigned long dependencieslen = (num_dependencies * SERVICE_NAME_LENGTH) + 2; - dependencies = (TCHAR *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dependencieslen * sizeof(TCHAR)); - size_t i = 0; - - TCHAR dependency[SERVICE_NAME_LENGTH]; - for (s = buffer; *s; s++) { - /* Group? */ - if (*s == SC_GROUP_IDENTIFIER) { - TCHAR *group = s + 1; - - bool ok = false; - if (*group) { - for (TCHAR *g = groups; *g; g++) { - if (str_equiv(g, group)) { - ok = true; - /* Set canonical name. */ - memmove(group, g, _tcslen(g) * sizeof(TCHAR)); - break; - } - - while (*g) g++; - } - } - - if (ok) _sntprintf_s(dependency, _countof(dependency), _TRUNCATE, _T("%s"), s); - else { - HeapFree(GetProcessHeap(), 0, dependencies); - if (groups) HeapFree(GetProcessHeap(), 0, groups); - _ftprintf(stderr, _T("%s: %s"), s, error_string(ERROR_SERVICE_DEPENDENCY_DELETED)); - return 5; - } - } - else { - SC_HANDLE dependency_handle = open_service(services, s, SERVICE_QUERY_STATUS, dependency, _countof(dependency)); - if (! dependency_handle) { - HeapFree(GetProcessHeap(), 0, dependencies); - if (groups) HeapFree(GetProcessHeap(), 0, groups); - CloseServiceHandle(services); - _ftprintf(stderr, _T("%s: %s"), s, error_string(ERROR_SERVICE_DEPENDENCY_DELETED)); - return 5; - } - } - - size_t len = _tcslen(dependency) + 1; - memmove(dependencies + i, dependency, len * sizeof(TCHAR)); - i += len; - - while (*s) s++; - } - - if (groups) HeapFree(GetProcessHeap(), 0, groups); - CloseServiceHandle(services); - } - - if (! ChangeServiceConfig(service_handle, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, 0, 0, 0, dependencies, 0, 0, 0)) { - if (num_dependencies) HeapFree(GetProcessHeap(), 0, dependencies); - print_message(stderr, NSSM_MESSAGE_CHANGESERVICECONFIG_FAILED, error_string(GetLastError())); - return -1; - } - - if (num_dependencies) HeapFree(GetProcessHeap(), 0, dependencies); - return 0; -} - -int get_service_dependencies(const TCHAR *service_name, SC_HANDLE service_handle, TCHAR **buffer, unsigned long *bufsize, int type) { - if (! buffer) return 1; - if (! bufsize) return 2; - - *buffer = 0; - *bufsize = 0; - - QUERY_SERVICE_CONFIG *qsc = query_service_config(service_name, service_handle); - if (! qsc) return 3; - - if (! qsc->lpDependencies) return 0; - if (! qsc->lpDependencies[0]) return 0; - - /* lpDependencies is doubly NULL terminated. */ - while (qsc->lpDependencies[*bufsize]) { - while (qsc->lpDependencies[*bufsize]) ++*bufsize; - ++*bufsize; - } - - *bufsize += 2; - - *buffer = (TCHAR *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *bufsize * sizeof(TCHAR)); - if (! *buffer) { - *bufsize = 0; - print_message(stderr, NSSM_MESSAGE_OUT_OF_MEMORY, _T("lpDependencies"), _T("get_service_dependencies()")); - return 4; - } - - if (type == DEPENDENCY_ALL) memmove(*buffer, qsc->lpDependencies, *bufsize * sizeof(TCHAR)); - else { - TCHAR *s; - size_t i = 0; - *bufsize = 0; - for (s = qsc->lpDependencies; *s; s++) { - /* Only copy the appropriate type of dependency. */ - if ((*s == SC_GROUP_IDENTIFIER && type & DEPENDENCY_GROUPS) || (*s != SC_GROUP_IDENTIFIER && type & DEPENDENCY_SERVICES)) { - size_t len = _tcslen(s) + 1; - *bufsize += (unsigned long) len; - memmove(*buffer + i, s, len * sizeof(TCHAR)); - i += len; - } - - while (*s) s++; - } - ++*bufsize; - } - - HeapFree(GetProcessHeap(), 0, qsc); - - return 0; -} - -int get_service_dependencies(const TCHAR *service_name, SC_HANDLE service_handle, TCHAR **buffer, unsigned long *bufsize) { - return get_service_dependencies(service_name, service_handle, buffer, bufsize, DEPENDENCY_ALL); -} - -int set_service_description(const TCHAR *service_name, SC_HANDLE service_handle, TCHAR *buffer) { - SERVICE_DESCRIPTION description; - ZeroMemory(&description, sizeof(description)); - /* - lpDescription must be NULL if we aren't changing, the new description - or "". - */ - if (buffer && buffer[0]) description.lpDescription = buffer; - else description.lpDescription = _T(""); - - if (ChangeServiceConfig2(service_handle, SERVICE_CONFIG_DESCRIPTION, &description)) return 0; - - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_SERVICE_CONFIG_DESCRIPTION_FAILED, service_name, error_string(GetLastError()), 0); - return 1; -} - -int get_service_description(const TCHAR *service_name, SC_HANDLE service_handle, unsigned long len, TCHAR *buffer) { - if (! buffer) return 1; - - unsigned long bufsize; - QueryServiceConfig2(service_handle, SERVICE_CONFIG_DESCRIPTION, 0, 0, &bufsize); - unsigned long error = GetLastError(); - if (error == ERROR_INSUFFICIENT_BUFFER) { - SERVICE_DESCRIPTION *description = (SERVICE_DESCRIPTION *) HeapAlloc(GetProcessHeap(), 0, bufsize); - if (! description) { - print_message(stderr, NSSM_MESSAGE_OUT_OF_MEMORY, _T("SERVICE_CONFIG_DESCRIPTION"), _T("get_service_description()")); - return 2; - } - - if (QueryServiceConfig2(service_handle, SERVICE_CONFIG_DESCRIPTION, (unsigned char *) description, bufsize, &bufsize)) { - if (description->lpDescription) _sntprintf_s(buffer, len, _TRUNCATE, _T("%s"), description->lpDescription); - else ZeroMemory(buffer, len * sizeof(TCHAR)); - HeapFree(GetProcessHeap(), 0, description); - return 0; - } - else { - HeapFree(GetProcessHeap(), 0, description); - print_message(stderr, NSSM_MESSAGE_QUERYSERVICECONFIG2_FAILED, service_name, _T("SERVICE_CONFIG_DESCRIPTION"), error_string(error)); - return 3; - } - } - else { - print_message(stderr, NSSM_MESSAGE_QUERYSERVICECONFIG2_FAILED, service_name, _T("SERVICE_CONFIG_DESCRIPTION"), error_string(error)); - return 4; - } - - return 0; -} - -int get_service_startup(const TCHAR *service_name, SC_HANDLE service_handle, const QUERY_SERVICE_CONFIG *qsc, unsigned long *startup) { - if (! qsc) return 1; - - switch (qsc->dwStartType) { - case SERVICE_DEMAND_START: *startup = NSSM_STARTUP_MANUAL; break; - case SERVICE_DISABLED: *startup = NSSM_STARTUP_DISABLED; break; - default: *startup = NSSM_STARTUP_AUTOMATIC; - } - - if (*startup != NSSM_STARTUP_AUTOMATIC) return 0; - - /* Check for delayed start. */ - unsigned long bufsize; - unsigned long error; - QueryServiceConfig2(service_handle, SERVICE_CONFIG_DELAYED_AUTO_START_INFO, 0, 0, &bufsize); - error = GetLastError(); - if (error == ERROR_INSUFFICIENT_BUFFER) { - SERVICE_DELAYED_AUTO_START_INFO *info = (SERVICE_DELAYED_AUTO_START_INFO *) HeapAlloc(GetProcessHeap(), 0, bufsize); - if (! info) { - print_message(stderr, NSSM_MESSAGE_OUT_OF_MEMORY, _T("SERVICE_DELAYED_AUTO_START_INFO"), _T("get_service_startup()")); - return 2; - } - - if (QueryServiceConfig2(service_handle, SERVICE_CONFIG_DELAYED_AUTO_START_INFO, (unsigned char *) info, bufsize, &bufsize)) { - if (info->fDelayedAutostart) *startup = NSSM_STARTUP_DELAYED; - HeapFree(GetProcessHeap(), 0, info); - return 0; - } - else { - error = GetLastError(); - if (error != ERROR_INVALID_LEVEL) { - print_message(stderr, NSSM_MESSAGE_QUERYSERVICECONFIG2_FAILED, service_name, _T("SERVICE_CONFIG_DELAYED_AUTO_START_INFO"), error_string(error)); - return 3; - } - } - } - else if (error != ERROR_INVALID_LEVEL) { - print_message(stderr, NSSM_MESSAGE_QUERYSERVICECONFIG2_FAILED, service_name, _T("SERVICE_DELAYED_AUTO_START_INFO"), error_string(error)); - return 3; - } - - return 0; -} - -int get_service_username(const TCHAR *service_name, const QUERY_SERVICE_CONFIG *qsc, TCHAR **username, size_t *usernamelen) { - if (! username) return 1; - if (! usernamelen) return 1; - - *username = 0; - *usernamelen = 0; - - if (! qsc) return 1; - - if (qsc->lpServiceStartName[0]) { - if (is_localsystem(qsc->lpServiceStartName)) return 0; - - size_t len = _tcslen(qsc->lpServiceStartName); - *username = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(TCHAR)); - if (! *username) { - print_message(stderr, NSSM_MESSAGE_OUT_OF_MEMORY, _T("username"), _T("get_service_username()")); - return 2; - } - - memmove(*username, qsc->lpServiceStartName, (len + 1) * sizeof(TCHAR)); - *usernamelen = len; - } - - return 0; -} - -/* Set default values which aren't zero. */ -void set_nssm_service_defaults(nssm_service_t *service) { - if (! service) return; - - service->type = SERVICE_WIN32_OWN_PROCESS; - service->priority = NORMAL_PRIORITY_CLASS; - service->stdin_sharing = NSSM_STDIN_SHARING; - service->stdin_disposition = NSSM_STDIN_DISPOSITION; - service->stdin_flags = NSSM_STDIN_FLAGS; - service->stdout_sharing = NSSM_STDOUT_SHARING; - service->stdout_disposition = NSSM_STDOUT_DISPOSITION; - service->stdout_flags = NSSM_STDOUT_FLAGS; - service->stderr_sharing = NSSM_STDERR_SHARING; - service->stderr_disposition = NSSM_STDERR_DISPOSITION; - service->stderr_flags = NSSM_STDERR_FLAGS; - service->throttle_delay = NSSM_RESET_THROTTLE_RESTART; - service->stop_method = ~0; - service->kill_console_delay = NSSM_KILL_CONSOLE_GRACE_PERIOD; - service->kill_window_delay = NSSM_KILL_WINDOW_GRACE_PERIOD; - service->kill_threads_delay = NSSM_KILL_THREADS_GRACE_PERIOD; -} - -/* Allocate and zero memory for a service. */ -nssm_service_t *alloc_nssm_service() { - nssm_service_t *service = (nssm_service_t *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(nssm_service_t)); - if (! service) log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, _T("service"), _T("alloc_nssm_service()"), 0); - return service; -} - -/* Free memory for a service. */ -void cleanup_nssm_service(nssm_service_t *service) { - if (! service) return; - if (service->username) HeapFree(GetProcessHeap(), 0, service->username); - if (service->password) { - SecureZeroMemory(service->password, service->passwordlen); - HeapFree(GetProcessHeap(), 0, service->password); - } - if (service->dependencies) HeapFree(GetProcessHeap(), 0, service->dependencies); - if (service->env) HeapFree(GetProcessHeap(), 0, service->env); - if (service->env_extra) HeapFree(GetProcessHeap(), 0, service->env_extra); - if (service->handle) CloseServiceHandle(service->handle); - if (service->process_handle) CloseHandle(service->process_handle); - if (service->wait_handle) UnregisterWait(service->wait_handle); - if (service->throttle_section_initialised) DeleteCriticalSection(&service->throttle_section); - if (service->throttle_timer) CloseHandle(service->throttle_timer); - if (service->initial_env) FreeEnvironmentStrings(service->initial_env); - HeapFree(GetProcessHeap(), 0, service); -} - -/* About to install the service */ -int pre_install_service(int argc, TCHAR **argv) { - nssm_service_t *service = alloc_nssm_service(); - set_nssm_service_defaults(service); - if (argc) _sntprintf_s(service->name, _countof(service->name), _TRUNCATE, _T("%s"), argv[0]); - - /* Show the dialogue box if we didn't give the service name and path */ - if (argc < 2) return nssm_gui(IDD_INSTALL, service); - - if (! service) { - print_message(stderr, NSSM_MESSAGE_OUT_OF_MEMORY, _T("service"), _T("pre_install_service()")); - return 1; - } - _sntprintf_s(service->exe, _countof(service->exe), _TRUNCATE, _T("%s"), argv[1]); - - /* Arguments are optional */ - size_t flagslen = 0; - size_t s = 0; - int i; - for (i = 2; i < argc; i++) flagslen += _tcslen(argv[i]) + 1; - if (! flagslen) flagslen = 1; - if (flagslen > _countof(service->flags)) { - print_message(stderr, NSSM_MESSAGE_FLAGS_TOO_LONG); - return 2; - } - - for (i = 2; i < argc; i++) { - size_t len = _tcslen(argv[i]); - memmove(service->flags + s, argv[i], len * sizeof(TCHAR)); - s += len; - if (i < argc - 1) service->flags[s++] = _T(' '); - } - - /* Work out directory name */ - _sntprintf_s(service->dir, _countof(service->dir), _TRUNCATE, _T("%s"), service->exe); - strip_basename(service->dir); - - int ret = install_service(service); - cleanup_nssm_service(service); - return ret; -} - -/* About to edit the service. */ -int pre_edit_service(int argc, TCHAR **argv) { - /* Require service name. */ - if (argc < 2) return usage(1); - - /* Are we editing on the command line? */ - enum { MODE_EDITING, MODE_GETTING, MODE_SETTING, MODE_RESETTING } mode = MODE_EDITING; - const TCHAR *verb = argv[0]; - const TCHAR *service_name = argv[1]; - bool getting = false; - bool unsetting = false; - - /* Minimum number of arguments. */ - int mandatory = 2; - /* Index of first value. */ - int remainder = 3; - int i; - if (str_equiv(verb, _T("get"))) { - mandatory = 3; - mode = MODE_GETTING; - } - else if (str_equiv(verb, _T("set"))) { - mandatory = 4; - mode = MODE_SETTING; - } - else if (str_equiv(verb, _T("reset")) || str_equiv(verb, _T("unset"))) { - mandatory = 3; - mode = MODE_RESETTING; - } - if (argc < mandatory) return usage(1); - - const TCHAR *parameter = 0; - settings_t *setting = 0; - TCHAR *additional; - - /* Validate the parameter. */ - if (mandatory > 2) { - bool additional_mandatory = false; - - parameter = argv[2]; - for (i = 0; settings[i].name; i++) { - setting = &settings[i]; - if (! str_equiv(setting->name, parameter)) continue; - if (((setting->additional & ADDITIONAL_GETTING) && mode == MODE_GETTING) || ((setting->additional & ADDITIONAL_SETTING) && mode == MODE_SETTING) || ((setting->additional & ADDITIONAL_RESETTING) && mode == MODE_RESETTING)) { - additional_mandatory = true; - mandatory++; - } - break; - } - if (! settings[i].name) { - print_message(stderr, NSSM_MESSAGE_INVALID_PARAMETER, parameter); - for (i = 0; settings[i].name; i++) _ftprintf(stderr, _T("%s\n"), settings[i].name); - return 1; - } - - additional = 0; - if (additional_mandatory) { - if (argc < mandatory) { - print_message(stderr, NSSM_MESSAGE_MISSING_SUBPARAMETER, parameter); - return 1; - } - additional = argv[3]; - remainder = 4; - } - else if (str_equiv(setting->name, NSSM_NATIVE_OBJECTNAME) && mode == MODE_SETTING) { - additional = argv[3]; - remainder = 4; - } - else { - additional = argv[remainder]; - if (argc < mandatory) return usage(1); - } - } - - nssm_service_t *service = alloc_nssm_service(); - _sntprintf_s(service->name, _countof(service->name), _TRUNCATE, _T("%s"), service_name); - - /* Open service manager */ - SC_HANDLE services = open_service_manager(SC_MANAGER_CONNECT | SC_MANAGER_ENUMERATE_SERVICE); - if (! services) { - print_message(stderr, NSSM_MESSAGE_OPEN_SERVICE_MANAGER_FAILED); - return 2; - } - - /* Try to open the service */ - unsigned long access = SERVICE_QUERY_CONFIG; - if (mode != MODE_GETTING) access |= SERVICE_CHANGE_CONFIG; - service->handle = open_service(services, service->name, access, service->name, _countof(service->name)); - if (! service->handle) { - CloseServiceHandle(services); - return 3; - } - - /* Get system details. */ - QUERY_SERVICE_CONFIG *qsc = query_service_config(service->name, service->handle); - if (! qsc) { - CloseServiceHandle(service->handle); - CloseServiceHandle(services); - return 4; - } - - service->type = qsc->dwServiceType; - if (! (service->type & SERVICE_WIN32_OWN_PROCESS)) { - if (mode != MODE_GETTING) { - HeapFree(GetProcessHeap(), 0, qsc); - CloseServiceHandle(service->handle); - CloseServiceHandle(services); - print_message(stderr, NSSM_MESSAGE_CANNOT_EDIT, service->name, NSSM_WIN32_OWN_PROCESS, 0); - return 3; - } - } - - if (get_service_startup(service->name, service->handle, qsc, &service->startup)) { - if (mode != MODE_GETTING) { - HeapFree(GetProcessHeap(), 0, qsc); - CloseServiceHandle(service->handle); - CloseServiceHandle(services); - return 4; - } - } - - if (get_service_username(service->name, qsc, &service->username, &service->usernamelen)) { - if (mode != MODE_GETTING) { - HeapFree(GetProcessHeap(), 0, qsc); - CloseServiceHandle(service->handle); - CloseServiceHandle(services); - return 5; - } - } - - _sntprintf_s(service->displayname, _countof(service->displayname), _TRUNCATE, _T("%s"), qsc->lpDisplayName); - - /* Get the canonical service name. We open it case insensitively. */ - unsigned long bufsize = _countof(service->name); - GetServiceKeyName(services, service->displayname, service->name, &bufsize); - - /* Remember the executable in case it isn't NSSM. */ - _sntprintf_s(service->image, _countof(service->image), _TRUNCATE, _T("%s"), qsc->lpBinaryPathName); - HeapFree(GetProcessHeap(), 0, qsc); - - /* Get extended system details. */ - if (get_service_description(service->name, service->handle, _countof(service->description), service->description)) { - if (mode != MODE_GETTING) { - CloseServiceHandle(service->handle); - CloseServiceHandle(services); - return 6; - } - } - - if (get_service_dependencies(service->name, service->handle, &service->dependencies, &service->dependencieslen)) { - if (mode != MODE_GETTING) { - CloseServiceHandle(service->handle); - CloseServiceHandle(services); - return 7; - } - } - - /* Get NSSM details. */ - get_parameters(service, 0); - - CloseServiceHandle(services); - - if (! service->exe[0]) { - service->native = true; - if (mode != MODE_GETTING) print_message(stderr, NSSM_MESSAGE_INVALID_SERVICE, service->name, NSSM, service->image); - } - - /* Editing with the GUI. */ - if (mode == MODE_EDITING) { - nssm_gui(IDD_EDIT, service); - return 0; - } - - /* Trying to manage App* parameters for a non-NSSM service. */ - if (! setting->native && service->native) { - CloseServiceHandle(service->handle); - print_message(stderr, NSSM_MESSAGE_NATIVE_PARAMETER, setting->name, NSSM); - return 1; - } - - HKEY key; - value_t value; - int ret; - - if (mode == MODE_GETTING) { - if (! service->native) { - key = open_registry(service->name, KEY_READ); - if (! key) return 4; - } - - if (setting->native) ret = get_setting(service->name, service->handle, setting, &value, additional); - else ret = get_setting(service->name, key, setting, &value, additional); - if (ret < 0) { - CloseServiceHandle(service->handle); - return 5; - } - - switch (setting->type) { - case REG_EXPAND_SZ: - case REG_MULTI_SZ: - case REG_SZ: - _tprintf(_T("%s\n"), value.string ? value.string : _T("")); - HeapFree(GetProcessHeap(), 0, value.string); - break; - - case REG_DWORD: - _tprintf(_T("%u\n"), value.numeric); - break; - } - - if (! service->native) RegCloseKey(key); - CloseServiceHandle(service->handle); - return 0; - } - - /* Build the value. */ - if (mode == MODE_RESETTING) { - /* Unset the parameter. */ - value.string = 0; - } - else if (remainder == argc) { - value.string = 0; - } - else { - /* Set the parameter. */ - size_t len = 0; - size_t delimiterlen = (setting->additional & ADDITIONAL_CRLF) ? 2 : 1; - for (i = remainder; i < argc; i++) len += _tcslen(argv[i]) + delimiterlen; - len++; - - value.string = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, len * sizeof(TCHAR)); - if (! value.string) { - print_message(stderr, NSSM_MESSAGE_OUT_OF_MEMORY, _T("value"), _T("edit_service()")); - CloseServiceHandle(service->handle); - return 2; - } - - size_t s = 0; - for (i = remainder; i < argc; i++) { - size_t len = _tcslen(argv[i]); - memmove(value.string + s, argv[i], len * sizeof(TCHAR)); - s += len; - if (i < argc - 1) { - if (setting->additional & ADDITIONAL_CRLF) { - value.string[s++] = _T('\r'); - value.string[s++] = _T('\n'); - } - else value.string[s++] = _T(' '); - } - } - value.string[s] = _T('\0'); - } - - if (! service->native) { - key = open_registry(service->name, KEY_WRITE); - if (! key) { - if (value.string) HeapFree(GetProcessHeap(), 0, value.string); - return 4; - } - } - - if (setting->native) ret = set_setting(service->name, service->handle, setting, &value, additional); - else ret = set_setting(service->name, key, setting, &value, additional); - if (value.string) HeapFree(GetProcessHeap(), 0, value.string); - if (ret < 0) { - if (! service->native) RegCloseKey(key); - CloseServiceHandle(service->handle); - return 6; - } - - if (! service->native) RegCloseKey(key); - CloseServiceHandle(service->handle); - - return 0; -} - -/* About to remove the service */ -int pre_remove_service(int argc, TCHAR **argv) { - nssm_service_t *service = alloc_nssm_service(); - set_nssm_service_defaults(service); - if (argc) _sntprintf_s(service->name, _countof(service->name), _TRUNCATE, _T("%s"), argv[0]); - - /* Show dialogue box if we didn't pass service name and "confirm" */ - if (argc < 2) return nssm_gui(IDD_REMOVE, service); - if (str_equiv(argv[1], _T("confirm"))) { - int ret = remove_service(service); - cleanup_nssm_service(service); - return ret; - } - print_message(stderr, NSSM_MESSAGE_PRE_REMOVE_SERVICE); - return 100; -} - -/* Install the service */ -int install_service(nssm_service_t *service) { - if (! service) return 1; - - /* Open service manager */ - SC_HANDLE services = open_service_manager(SC_MANAGER_CONNECT | SC_MANAGER_CREATE_SERVICE); - if (! services) { - print_message(stderr, NSSM_MESSAGE_OPEN_SERVICE_MANAGER_FAILED); - cleanup_nssm_service(service); - return 2; - } - - /* Get path of this program */ - GetModuleFileName(0, service->image, _countof(service->image)); - - /* Create the service - settings will be changed in edit_service() */ - service->handle = CreateService(services, service->name, service->name, SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_NORMAL, service->image, 0, 0, 0, 0, 0); - if (! service->handle) { - print_message(stderr, NSSM_MESSAGE_CREATESERVICE_FAILED, error_string(GetLastError())); - CloseServiceHandle(services); - return 5; - } - - if (edit_service(service, false)) { - DeleteService(service->handle); - CloseServiceHandle(services); - return 6; - } - - print_message(stdout, NSSM_MESSAGE_SERVICE_INSTALLED, service->name); - - /* Cleanup */ - CloseServiceHandle(services); - - return 0; -} - -/* Edit the service. */ -int edit_service(nssm_service_t *service, bool editing) { - if (! service) return 1; - - /* - The only two valid flags for service type are SERVICE_WIN32_OWN_PROCESS - and SERVICE_INTERACTIVE_PROCESS. - */ - service->type &= SERVICE_INTERACTIVE_PROCESS; - service->type |= SERVICE_WIN32_OWN_PROCESS; - - /* Startup type. */ - unsigned long startup; - switch (service->startup) { - case NSSM_STARTUP_MANUAL: startup = SERVICE_DEMAND_START; break; - case NSSM_STARTUP_DISABLED: startup = SERVICE_DISABLED; break; - default: startup = SERVICE_AUTO_START; - } - - /* Display name. */ - if (! service->displayname[0]) _sntprintf_s(service->displayname, _countof(service->displayname), _TRUNCATE, _T("%s"), service->name); - - /* - Username must be NULL if we aren't changing or an account name. - We must explicitly use LOCALSYSTEM to change it when we are editing. - Password must be NULL if we aren't changing, a password or "". - Empty passwords are valid but we won't allow them in the GUI. - */ - TCHAR *username = 0; - TCHAR *canon = 0; - TCHAR *password = 0; - if (service->usernamelen) { - username = service->username; - if (canonicalise_username(username, &canon)) return 5; - if (service->passwordlen) password = service->password; - } - else if (editing) username = canon = NSSM_LOCALSYSTEM_ACCOUNT; - - if (well_known_username(canon)) password = _T(""); - else { - if (grant_logon_as_service(canon)) { - if (canon != username) HeapFree(GetProcessHeap(), 0, canon); - print_message(stderr, NSSM_MESSAGE_GRANT_LOGON_AS_SERVICE_FAILED, username); - return 5; - } - } - - TCHAR *dependencies = _T(""); - if (service->dependencieslen) dependencies = 0; /* Change later. */ - - if (! ChangeServiceConfig(service->handle, service->type, startup, SERVICE_NO_CHANGE, 0, 0, 0, dependencies, canon, password, service->displayname)) { - if (canon != username) HeapFree(GetProcessHeap(), 0, canon); - print_message(stderr, NSSM_MESSAGE_CHANGESERVICECONFIG_FAILED, error_string(GetLastError())); - return 5; - } - if (canon != username) HeapFree(GetProcessHeap(), 0, canon); - - if (service->dependencieslen) { - if (set_service_dependencies(service->name, service->handle, service->dependencies)) return 5; - } - - if (service->description[0] || editing) { - set_service_description(service->name, service->handle, service->description); - } - - SERVICE_DELAYED_AUTO_START_INFO delayed; - ZeroMemory(&delayed, sizeof(delayed)); - if (service->startup == NSSM_STARTUP_DELAYED) delayed.fDelayedAutostart = 1; - else delayed.fDelayedAutostart = 0; - /* Delayed startup isn't supported until Vista. */ - if (! ChangeServiceConfig2(service->handle, SERVICE_CONFIG_DELAYED_AUTO_START_INFO, &delayed)) { - unsigned long error = GetLastError(); - /* Pre-Vista we expect to fail with ERROR_INVALID_LEVEL */ - if (error != ERROR_INVALID_LEVEL) { - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_SERVICE_CONFIG_DELAYED_AUTO_START_INFO_FAILED, service->name, error_string(error), 0); - } - } - - /* Don't mess with parameters which aren't ours. */ - if (! service->native) { - /* Now we need to put the parameters into the registry */ - if (create_parameters(service, editing)) { - print_message(stderr, NSSM_MESSAGE_CREATE_PARAMETERS_FAILED); - return 6; - } - - set_service_recovery(service); - } - - return 0; -} - -/* Control a service. */ -int control_service(unsigned long control, int argc, TCHAR **argv) { - if (argc < 1) return usage(1); - TCHAR *service_name = argv[0]; - TCHAR canonical_name[SERVICE_NAME_LENGTH]; - - SC_HANDLE services = open_service_manager(SC_MANAGER_CONNECT | SC_MANAGER_ENUMERATE_SERVICE); - if (! services) { - print_message(stderr, NSSM_MESSAGE_OPEN_SERVICE_MANAGER_FAILED); - return 2; - } - - unsigned long access = SERVICE_QUERY_STATUS; - switch (control) { - case NSSM_SERVICE_CONTROL_START: - access |= SERVICE_START; - break; - - case SERVICE_CONTROL_CONTINUE: - case SERVICE_CONTROL_PAUSE: - access |= SERVICE_PAUSE_CONTINUE; - break; - - case SERVICE_CONTROL_STOP: - access |= SERVICE_STOP; - break; - - case NSSM_SERVICE_CONTROL_ROTATE: - access |= SERVICE_USER_DEFINED_CONTROL; - break; - } - - SC_HANDLE service_handle = open_service(services, service_name, access, canonical_name, _countof(canonical_name)); - if (! service_handle) { - CloseServiceHandle(services); - return 3; - } - - int ret; - unsigned long error; - SERVICE_STATUS service_status; - if (control == NSSM_SERVICE_CONTROL_START) { - unsigned long initial_status = SERVICE_STOPPED; - ret = StartService(service_handle, (unsigned long) argc, (const TCHAR **) argv); - error = GetLastError(); - CloseServiceHandle(services); - - if (error == ERROR_IO_PENDING) { - /* - Older versions of Windows return immediately with ERROR_IO_PENDING - indicate that the operation is still in progress. Newer versions - will return it if there really is a delay. - */ - ret = 1; - error = ERROR_SUCCESS; - } - - if (ret) { - int response = await_service_control_response(control, service_handle, &service_status, initial_status); - CloseServiceHandle(service_handle); - - if (response) { - print_message(stderr, NSSM_MESSAGE_BAD_CONTROL_RESPONSE, canonical_name, service_status_text(service_status.dwCurrentState), service_control_text(control)); - return 1; - } - else _tprintf(_T("%s: %s: %s"), canonical_name, service_control_text(control), error_string(error)); - return 0; - } - else { - CloseServiceHandle(service_handle); - _ftprintf(stderr, _T("%s: %s: %s"), canonical_name, service_control_text(control), error_string(error)); - return 1; - } - } - else if (control == SERVICE_CONTROL_INTERROGATE) { - /* - We could actually send an INTERROGATE control but that won't return - any information if the service is stopped and we don't care about - the extra details it might give us in any case. So we'll fake it. - */ - ret = QueryServiceStatus(service_handle, &service_status); - error = GetLastError(); - - if (ret) { - _tprintf(_T("%s\n"), service_status_text(service_status.dwCurrentState)); - return 0; - } - else { - _ftprintf(stderr, _T("%s: %s\n"), canonical_name, error_string(error)); - return 1; - } - } - else { - ret = ControlService(service_handle, control, &service_status); - unsigned long initial_status = service_status.dwCurrentState; - error = GetLastError(); - CloseServiceHandle(services); - - if (error == ERROR_IO_PENDING) { - ret = 1; - error = ERROR_SUCCESS; - } - - if (ret) { - int response = await_service_control_response(control, service_handle, &service_status, initial_status); - CloseServiceHandle(service_handle); - - if (response) { - print_message(stderr, NSSM_MESSAGE_BAD_CONTROL_RESPONSE, canonical_name, service_status_text(service_status.dwCurrentState), service_control_text(control)); - return 1; - } - else _tprintf(_T("%s: %s: %s"), canonical_name, service_control_text(control), error_string(error)); - return 0; - } - else { - CloseServiceHandle(service_handle); - _ftprintf(stderr, _T("%s: %s: %s"), canonical_name, service_control_text(control), error_string(error)); - if (error == ERROR_SERVICE_NOT_ACTIVE) { - if (control == SERVICE_CONTROL_SHUTDOWN || control == SERVICE_CONTROL_STOP) return 0; - } - return 1; - } - } -} - -/* Remove the service */ -int remove_service(nssm_service_t *service) { - if (! service) return 1; - - /* Open service manager */ - SC_HANDLE services = open_service_manager(SC_MANAGER_CONNECT | SC_MANAGER_ENUMERATE_SERVICE); - if (! services) { - print_message(stderr, NSSM_MESSAGE_OPEN_SERVICE_MANAGER_FAILED); - return 2; - } - - /* Try to open the service */ - service->handle = open_service(services, service->name, DELETE, service->name, _countof(service->name)); - if (! service->handle) { - CloseServiceHandle(services); - return 3; - } - - /* Get the canonical service name. We open it case insensitively. */ - unsigned long bufsize = _countof(service->displayname); - GetServiceDisplayName(services, service->name, service->displayname, &bufsize); - bufsize = _countof(service->name); - GetServiceKeyName(services, service->displayname, service->name, &bufsize); - - /* Try to delete the service */ - if (! DeleteService(service->handle)) { - print_message(stderr, NSSM_MESSAGE_DELETESERVICE_FAILED); - CloseServiceHandle(services); - return 4; - } - - /* Cleanup */ - CloseServiceHandle(services); - - print_message(stdout, NSSM_MESSAGE_SERVICE_REMOVED, service->name); - return 0; -} - -/* Service initialisation */ -void WINAPI service_main(unsigned long argc, TCHAR **argv) { - nssm_service_t *service = alloc_nssm_service(); - if (! service) return; - - if (_sntprintf_s(service->name, _countof(service->name), _TRUNCATE, _T("%s"), argv[0]) < 0) { - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, _T("service->name"), _T("service_main()"), 0); - return; - } - - /* We can use a condition variable in a critical section on Vista or later. */ - if (imports.SleepConditionVariableCS && imports.WakeConditionVariable) use_critical_section = true; - else use_critical_section = false; - - /* Initialise status */ - ZeroMemory(&service->status, sizeof(service->status)); - service->status.dwServiceType = SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS; - service->status.dwControlsAccepted = SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE; - service->status.dwWin32ExitCode = NO_ERROR; - service->status.dwServiceSpecificExitCode = 0; - service->status.dwCheckPoint = 0; - service->status.dwWaitHint = NSSM_WAITHINT_MARGIN; - - /* Signal we AREN'T running the server */ - service->process_handle = 0; - service->pid = 0; - - /* Register control handler */ - service->status_handle = RegisterServiceCtrlHandlerEx(NSSM, service_control_handler, (void *) service); - if (! service->status_handle) { - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_REGISTERSERVICECTRLHANDER_FAILED, error_string(GetLastError()), 0); - return; - } - - log_service_control(service->name, 0, true); - - service->status.dwCurrentState = SERVICE_START_PENDING; - service->status.dwWaitHint = service->throttle_delay + NSSM_WAITHINT_MARGIN; - SetServiceStatus(service->status_handle, &service->status); - - if (is_admin) { - /* Try to create the exit action parameters; we don't care if it fails */ - create_exit_action(service->name, exit_action_strings[0], false); - - SC_HANDLE services = open_service_manager(SC_MANAGER_CONNECT); - if (services) { - service->handle = open_service(services, service->name, SERVICE_CHANGE_CONFIG, 0, 0); - set_service_recovery(service); - CloseServiceHandle(services); - } - } - - /* Used for signalling a resume if the service pauses when throttled. */ - if (use_critical_section) { - InitializeCriticalSection(&service->throttle_section); - service->throttle_section_initialised = true; - } - else { - service->throttle_timer = CreateWaitableTimer(0, 1, 0); - if (! service->throttle_timer) { - log_event(EVENTLOG_WARNING_TYPE, NSSM_EVENT_CREATEWAITABLETIMER_FAILED, service->name, error_string(GetLastError()), 0); - } - } - - /* Remember our initial environment. */ - service->initial_env = GetEnvironmentStrings(); - - monitor_service(service); -} - -/* Make sure service recovery actions are taken where necessary */ -void set_service_recovery(nssm_service_t *service) { - SERVICE_FAILURE_ACTIONS_FLAG flag; - ZeroMemory(&flag, sizeof(flag)); - flag.fFailureActionsOnNonCrashFailures = true; - - /* This functionality was added in Vista so the call may fail */ - if (! ChangeServiceConfig2(service->handle, SERVICE_CONFIG_FAILURE_ACTIONS_FLAG, &flag)) { - unsigned long error = GetLastError(); - /* Pre-Vista we expect to fail with ERROR_INVALID_LEVEL */ - if (error != ERROR_INVALID_LEVEL) { - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_SERVICE_CONFIG_FAILURE_ACTIONS_FAILED, service->name, error_string(error), 0); - } - } -} - -int monitor_service(nssm_service_t *service) { - /* Set service status to started */ - int ret = start_service(service); - if (ret) { - TCHAR code[16]; - _sntprintf_s(code, _countof(code), _TRUNCATE, _T("%d"), ret); - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_START_SERVICE_FAILED, service->exe, service->name, ret, 0); - return ret; - } - log_event(EVENTLOG_INFORMATION_TYPE, NSSM_EVENT_STARTED_SERVICE, service->exe, service->flags, service->name, service->dir, 0); - - /* Monitor service */ - if (! RegisterWaitForSingleObject(&service->wait_handle, service->process_handle, end_service, (void *) service, INFINITE, WT_EXECUTEONLYONCE | WT_EXECUTELONGFUNCTION)) { - log_event(EVENTLOG_WARNING_TYPE, NSSM_EVENT_REGISTERWAITFORSINGLEOBJECT_FAILED, service->name, service->exe, error_string(GetLastError()), 0); - } - - return 0; -} - -TCHAR *service_control_text(unsigned long control) { - switch (control) { - /* HACK: there is no SERVICE_CONTROL_START constant */ - case NSSM_SERVICE_CONTROL_START: return _T("START"); - case SERVICE_CONTROL_STOP: return _T("STOP"); - case SERVICE_CONTROL_SHUTDOWN: return _T("SHUTDOWN"); - case SERVICE_CONTROL_PAUSE: return _T("PAUSE"); - case SERVICE_CONTROL_CONTINUE: return _T("CONTINUE"); - case SERVICE_CONTROL_INTERROGATE: return _T("INTERROGATE"); - case NSSM_SERVICE_CONTROL_ROTATE: return _T("ROTATE"); - default: return 0; - } -} - -TCHAR *service_status_text(unsigned long status) { - switch (status) { - case SERVICE_STOPPED: return _T("SERVICE_STOPPED"); - case SERVICE_START_PENDING: return _T("SERVICE_START_PENDING"); - case SERVICE_STOP_PENDING: return _T("SERVICE_STOP_PENDING"); - case SERVICE_RUNNING: return _T("SERVICE_RUNNING"); - case SERVICE_CONTINUE_PENDING: return _T("SERVICE_CONTINUE_PENDING"); - case SERVICE_PAUSE_PENDING: return _T("SERVICE_PAUSE_PENDING"); - case SERVICE_PAUSED: return _T("SERVICE_PAUSED"); - default: return 0; - } -} - -void log_service_control(TCHAR *service_name, unsigned long control, bool handled) { - TCHAR *text = service_control_text(control); - unsigned long event; - - if (! text) { - /* "0x" + 8 x hex + NULL */ - text = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, 11 * sizeof(TCHAR)); - if (! text) { - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, _T("control code"), _T("log_service_control()"), 0); - return; - } - if (_sntprintf_s(text, 11, _TRUNCATE, _T("0x%08x"), control) < 0) { - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, _T("control code"), _T("log_service_control()"), 0); - HeapFree(GetProcessHeap(), 0, text); - return; - } - - event = NSSM_EVENT_SERVICE_CONTROL_UNKNOWN; - } - else if (handled) event = NSSM_EVENT_SERVICE_CONTROL_HANDLED; - else event = NSSM_EVENT_SERVICE_CONTROL_NOT_HANDLED; - - log_event(EVENTLOG_INFORMATION_TYPE, event, service_name, text, 0); - - if (event == NSSM_EVENT_SERVICE_CONTROL_UNKNOWN) { - HeapFree(GetProcessHeap(), 0, text); - } -} - -/* Service control handler */ -unsigned long WINAPI service_control_handler(unsigned long control, unsigned long event, void *data, void *context) { - nssm_service_t *service = (nssm_service_t *) context; - - switch (control) { - case SERVICE_CONTROL_INTERROGATE: - /* We always keep the service status up-to-date so this is a no-op. */ - return NO_ERROR; - - case SERVICE_CONTROL_SHUTDOWN: - case SERVICE_CONTROL_STOP: - log_service_control(service->name, control, true); - /* - We MUST acknowledge the stop request promptly but we're committed to - waiting for the application to exit. Spawn a new thread to wait - while we acknowledge the request. - */ - if (! CreateThread(NULL, 0, shutdown_service, context, 0, NULL)) { - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_CREATETHREAD_FAILED, error_string(GetLastError()), 0); - - /* - We couldn't create a thread to tidy up so we'll have to force the tidyup - to complete in time in this thread. - */ - service->kill_console_delay = NSSM_KILL_CONSOLE_GRACE_PERIOD; - service->kill_window_delay = NSSM_KILL_WINDOW_GRACE_PERIOD; - service->kill_threads_delay = NSSM_KILL_THREADS_GRACE_PERIOD; - - stop_service(service, 0, true, true); - } - return NO_ERROR; - - case SERVICE_CONTROL_CONTINUE: - log_service_control(service->name, control, true); - service->throttle = 0; - if (use_critical_section) imports.WakeConditionVariable(&service->throttle_condition); - else { - if (! service->throttle_timer) return ERROR_CALL_NOT_IMPLEMENTED; - ZeroMemory(&service->throttle_duetime, sizeof(service->throttle_duetime)); - SetWaitableTimer(service->throttle_timer, &service->throttle_duetime, 0, 0, 0, 0); - } - /* We can't continue if the application is running! */ - if (! service->process_handle) service->status.dwCurrentState = SERVICE_CONTINUE_PENDING; - service->status.dwWaitHint = throttle_milliseconds(service->throttle) + NSSM_WAITHINT_MARGIN; - log_event(EVENTLOG_INFORMATION_TYPE, NSSM_EVENT_RESET_THROTTLE, service->name, 0); - SetServiceStatus(service->status_handle, &service->status); - return NO_ERROR; - - case SERVICE_CONTROL_PAUSE: - /* - We don't accept pause messages but it isn't possible to register - only for continue messages so we have to handle this case. - */ - log_service_control(service->name, control, false); - return ERROR_CALL_NOT_IMPLEMENTED; - - case NSSM_SERVICE_CONTROL_ROTATE: - log_service_control(service->name, control, true); - if (service->rotate_stdout_online == NSSM_ROTATE_ONLINE) service->rotate_stdout_online = NSSM_ROTATE_ONLINE_ASAP; - if (service->rotate_stderr_online == NSSM_ROTATE_ONLINE) service->rotate_stderr_online = NSSM_ROTATE_ONLINE_ASAP; - return NO_ERROR; - } - - /* Unknown control */ - log_service_control(service->name, control, false); - return ERROR_CALL_NOT_IMPLEMENTED; -} - -/* Start the service */ -int start_service(nssm_service_t *service) { - service->stopping = false; - service->allow_restart = true; - - if (service->process_handle) return 0; - - /* Allocate a STARTUPINFO structure for a new process */ - STARTUPINFO si; - ZeroMemory(&si, sizeof(si)); - si.cb = sizeof(si); - - /* Allocate a PROCESSINFO structure for the process */ - PROCESS_INFORMATION pi; - ZeroMemory(&pi, sizeof(pi)); - - /* Get startup parameters */ - int ret = get_parameters(service, &si); - if (ret) { - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_GET_PARAMETERS_FAILED, service->name, 0); - return stop_service(service, 2, true, true); - } - - /* Launch executable with arguments */ - TCHAR cmd[CMD_LENGTH]; - if (_sntprintf_s(cmd, _countof(cmd), _TRUNCATE, _T("\"%s\" %s"), service->exe, service->flags) < 0) { - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, _T("command line"), _T("start_service"), 0); - return stop_service(service, 2, true, true); - } - - throttle_restart(service); - - /* Set the environment. */ - if (service->env) duplicate_environment(service->env); - if (service->env_extra) set_environment_block(service->env_extra); - - /* Set up I/O redirection. */ - if (get_output_handles(service, &si)) { - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_GET_OUTPUT_HANDLES_FAILED, service->name, 0); - if (! service->no_console) FreeConsole(); - close_output_handles(&si); - return stop_service(service, 4, true, true); - } - - bool inherit_handles = false; - if (si.dwFlags & STARTF_USESTDHANDLES) inherit_handles = true; - unsigned long flags = service->priority & priority_mask(); - if (service->affinity) flags |= CREATE_SUSPENDED; - if (! CreateProcess(0, cmd, 0, 0, inherit_handles, flags, 0, service->dir, &si, &pi)) { - unsigned long exitcode = 3; - unsigned long error = GetLastError(); - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_CREATEPROCESS_FAILED, service->name, service->exe, error_string(error), 0); - close_output_handles(&si); - duplicate_environment_strings(service->initial_env); - return stop_service(service, exitcode, true, true); - } - service->process_handle = pi.hProcess; - service->pid = pi.dwProcessId; - - if (get_process_creation_time(service->process_handle, &service->creation_time)) ZeroMemory(&service->creation_time, sizeof(service->creation_time)); - - close_output_handles(&si); - - if (! service->no_console) FreeConsole(); - - /* Restore our environment. */ - duplicate_environment_strings(service->initial_env); - - if (service->affinity) { - /* - We are explicitly storing service->affinity as a 64-bit unsigned integer - so that we can parse it regardless of whether we're running in 32-bit - or 64-bit mode. The arguments to SetProcessAffinityMask(), however, are - defined as type DWORD_PTR and hence limited to 32 bits on a 32-bit system - (or when running the 32-bit NSSM). - - The result is a lot of seemingly-unnecessary casting throughout the code - and potentially confusion when we actually try to start the service. - Having said that, however, it's unlikely that we're actually going to - run in 32-bit mode on a system which has more than 32 CPUs so the - likelihood of seeing a confusing situation is somewhat diminished. - */ - DWORD_PTR affinity, system_affinity; - - if (GetProcessAffinityMask(service->process_handle, &affinity, &system_affinity)) affinity = service->affinity & system_affinity; - else { - affinity = (DWORD_PTR) service->affinity; - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_GETPROCESSAFFINITYMASK_FAILED, service->name, error_string(GetLastError()), 0); - } - - if (! SetProcessAffinityMask(service->process_handle, affinity)) { - log_event(EVENTLOG_WARNING_TYPE, NSSM_EVENT_SETPROCESSAFFINITYMASK_FAILED, service->name, error_string(GetLastError()), 0); - } - - ResumeThread(pi.hThread); - } - - /* - Wait for a clean startup before changing the service status to RUNNING - but be mindful of the fact that we are blocking the service control manager - so abandon the wait before too much time has elapsed. - */ - unsigned long delay = service->throttle_delay; - if (delay > NSSM_SERVICE_STATUS_DEADLINE) { - TCHAR delay_milliseconds[16]; - _sntprintf_s(delay_milliseconds, _countof(delay_milliseconds), _TRUNCATE, _T("%lu"), delay); - TCHAR deadline_milliseconds[16]; - _sntprintf_s(deadline_milliseconds, _countof(deadline_milliseconds), _TRUNCATE, _T("%lu"), NSSM_SERVICE_STATUS_DEADLINE); - log_event(EVENTLOG_WARNING_TYPE, NSSM_EVENT_STARTUP_DELAY_TOO_LONG, service->name, delay_milliseconds, NSSM, deadline_milliseconds, 0); - delay = NSSM_SERVICE_STATUS_DEADLINE; - } - unsigned long deadline = WaitForSingleObject(service->process_handle, delay); - - /* Signal successful start */ - service->status.dwCurrentState = SERVICE_RUNNING; - SetServiceStatus(service->status_handle, &service->status); - - /* Continue waiting for a clean startup. */ - if (deadline == WAIT_TIMEOUT) { - if (service->throttle_delay > delay) { - if (WaitForSingleObject(service->process_handle, service->throttle_delay - delay) == WAIT_TIMEOUT) service->throttle = 0; - } - else service->throttle = 0; - } - - /* Ensure the restart delay is always applied. */ - if (service->restart_delay && ! service->throttle) service->throttle++; - - return 0; -} - -/* Stop the service */ -int stop_service(nssm_service_t *service, unsigned long exitcode, bool graceful, bool default_action) { - service->allow_restart = false; - if (service->wait_handle) { - UnregisterWait(service->wait_handle); - service->wait_handle = 0; - } - - service->rotate_stdout_online = service->rotate_stderr_online = NSSM_ROTATE_OFFLINE; - - if (default_action && ! exitcode && ! graceful) { - log_event(EVENTLOG_INFORMATION_TYPE, NSSM_EVENT_GRACEFUL_SUICIDE, service->name, service->exe, exit_action_strings[NSSM_EXIT_UNCLEAN], exit_action_strings[NSSM_EXIT_UNCLEAN], exit_action_strings[NSSM_EXIT_UNCLEAN], exit_action_strings[NSSM_EXIT_REALLY], 0); - graceful = true; - } - - /* Signal we are stopping */ - if (graceful) { - service->status.dwCurrentState = SERVICE_STOP_PENDING; - service->status.dwWaitHint = NSSM_WAITHINT_MARGIN; - SetServiceStatus(service->status_handle, &service->status); - } - - /* Nothing to do if service isn't running */ - if (service->pid) { - /* Shut down service */ - log_event(EVENTLOG_INFORMATION_TYPE, NSSM_EVENT_TERMINATEPROCESS, service->name, service->exe, 0); - kill_process(service, service->process_handle, service->pid, 0); - } - else log_event(EVENTLOG_INFORMATION_TYPE, NSSM_EVENT_PROCESS_ALREADY_STOPPED, service->name, service->exe, 0); - - end_service((void *) service, true); - - /* Signal we stopped */ - if (graceful) { - service->status.dwCurrentState = SERVICE_STOPPED; - if (exitcode) { - service->status.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR; - service->status.dwServiceSpecificExitCode = exitcode; - } - else { - service->status.dwWin32ExitCode = NO_ERROR; - service->status.dwServiceSpecificExitCode = 0; - } - SetServiceStatus(service->status_handle, &service->status); - } - - return exitcode; -} - -/* Callback function triggered when the server exits */ -void CALLBACK end_service(void *arg, unsigned char why) { - nssm_service_t *service = (nssm_service_t *) arg; - - if (service->stopping) return; - - service->stopping = true; - - service->rotate_stdout_online = service->rotate_stderr_online = NSSM_ROTATE_OFFLINE; - - /* Use now as a dummy exit time. */ - GetSystemTimeAsFileTime(&service->exit_time); - - /* Check exit code */ - unsigned long exitcode = 0; - TCHAR code[16]; - if (service->process_handle) { - GetExitCodeProcess(service->process_handle, &exitcode); - /* Check real exit time. */ - if (exitcode != STILL_ACTIVE) get_process_exit_time(service->process_handle, &service->exit_time); - CloseHandle(service->process_handle); - } - - service->process_handle = 0; - - /* - Log that the service ended BEFORE logging about killing the process - tree. See below for the possible values of the why argument. - */ - if (! why) { - _sntprintf_s(code, _countof(code), _TRUNCATE, _T("%lu"), exitcode); - log_event(EVENTLOG_INFORMATION_TYPE, NSSM_EVENT_ENDED_SERVICE, service->exe, service->name, code, 0); - } - - /* Clean up. */ - if (exitcode == STILL_ACTIVE) exitcode = 0; - if (service->pid) kill_process_tree(service, service->pid, exitcode, service->pid); - service->pid = 0; - - /* - The why argument is true if our wait timed out or false otherwise. - Our wait is infinite so why will never be true when called by the system. - If it is indeed true, assume we were called from stop_service() because - this is a controlled shutdown, and don't take any restart action. - */ - if (why) return; - if (! service->allow_restart) return; - - /* What action should we take? */ - int action = NSSM_EXIT_RESTART; - TCHAR action_string[ACTION_LEN]; - bool default_action; - if (! get_exit_action(service->name, &exitcode, action_string, &default_action)) { - for (int i = 0; exit_action_strings[i]; i++) { - if (! _tcsnicmp((const TCHAR *) action_string, exit_action_strings[i], ACTION_LEN)) { - action = i; - break; - } - } - } - - switch (action) { - /* Try to restart the service or return failure code to service manager */ - case NSSM_EXIT_RESTART: - log_event(EVENTLOG_INFORMATION_TYPE, NSSM_EVENT_EXIT_RESTART, service->name, code, exit_action_strings[action], service->exe, 0); - while (monitor_service(service)) { - log_event(EVENTLOG_WARNING_TYPE, NSSM_EVENT_RESTART_SERVICE_FAILED, service->exe, service->name, 0); - Sleep(30000); - } - break; - - /* Do nothing, just like srvany would */ - case NSSM_EXIT_IGNORE: - log_event(EVENTLOG_INFORMATION_TYPE, NSSM_EVENT_EXIT_IGNORE, service->name, code, exit_action_strings[action], service->exe, 0); - Sleep(INFINITE); - break; - - /* Tell the service manager we are finished */ - case NSSM_EXIT_REALLY: - log_event(EVENTLOG_INFORMATION_TYPE, NSSM_EVENT_EXIT_REALLY, service->name, code, exit_action_strings[action], 0); - stop_service(service, exitcode, true, default_action); - break; - - /* Fake a crash so pre-Vista service managers will run recovery actions. */ - case NSSM_EXIT_UNCLEAN: - log_event(EVENTLOG_INFORMATION_TYPE, NSSM_EVENT_EXIT_UNCLEAN, service->name, code, exit_action_strings[action], 0); - stop_service(service, exitcode, false, default_action); - free_imports(); - exit(exitcode); - break; - } -} - -void throttle_restart(nssm_service_t *service) { - /* This can't be a restart if the service is already running. */ - if (! service->throttle++) return; - - unsigned long ms; - unsigned long throttle_ms = throttle_milliseconds(service->throttle); - TCHAR threshold[8], milliseconds[8]; - - if (service->restart_delay > throttle_ms) ms = service->restart_delay; - else ms = throttle_ms; - - if (service->throttle > 7) service->throttle = 8; - - _sntprintf_s(milliseconds, _countof(milliseconds), _TRUNCATE, _T("%lu"), ms); - - if (service->throttle == 1 && service->restart_delay > throttle_ms) log_event(EVENTLOG_INFORMATION_TYPE, NSSM_EVENT_RESTART_DELAY, service->name, milliseconds, 0); - else { - _sntprintf_s(threshold, _countof(threshold), _TRUNCATE, _T("%lu"), service->throttle_delay); - log_event(EVENTLOG_WARNING_TYPE, NSSM_EVENT_THROTTLED, service->name, threshold, milliseconds, 0); - } - - if (use_critical_section) EnterCriticalSection(&service->throttle_section); - else if (service->throttle_timer) { - ZeroMemory(&service->throttle_duetime, sizeof(service->throttle_duetime)); - service->throttle_duetime.QuadPart = 0 - (ms * 10000LL); - SetWaitableTimer(service->throttle_timer, &service->throttle_duetime, 0, 0, 0, 0); - } - - service->status.dwCurrentState = SERVICE_PAUSED; - SetServiceStatus(service->status_handle, &service->status); - - if (use_critical_section) { - imports.SleepConditionVariableCS(&service->throttle_condition, &service->throttle_section, ms); - LeaveCriticalSection(&service->throttle_section); - } - else { - if (service->throttle_timer) WaitForSingleObject(service->throttle_timer, INFINITE); - else Sleep(ms); - } -} - -/* - When responding to a stop (or any other) request we need to set dwWaitHint to - the number of milliseconds we expect the operation to take, and optionally - increase dwCheckPoint. If dwWaitHint milliseconds elapses without the - operation completing or dwCheckPoint increasing, the system will consider the - service to be hung. - - However the system will consider the service to be hung after 30000 - milliseconds regardless of the value of dwWaitHint if dwCheckPoint has not - changed. Therefore if we want to wait longer than that we must periodically - increase dwCheckPoint. - - Furthermore, it will consider the service to be hung after 60000 milliseconds - regardless of the value of dwCheckPoint unless dwWaitHint is increased every - time dwCheckPoint is also increased. - - Our strategy then is to retrieve the initial dwWaitHint and wait for - NSSM_SERVICE_STATUS_DEADLINE milliseconds. If the process is still running - and we haven't finished waiting we increment dwCheckPoint and add whichever is - smaller of NSSM_SERVICE_STATUS_DEADLINE or the remaining timeout to - dwWaitHint. - - Only doing both these things will prevent the system from killing the service. - - Returns: 1 if the wait timed out. - 0 if the wait completed. - -1 on error. -*/ -int await_shutdown(nssm_service_t *service, TCHAR *function_name, unsigned long timeout) { - unsigned long interval; - unsigned long waithint; - unsigned long ret; - unsigned long waited; - TCHAR interval_milliseconds[16]; - TCHAR timeout_milliseconds[16]; - TCHAR waited_milliseconds[16]; - TCHAR *function = function_name; - - /* Add brackets to function name. */ - size_t funclen = _tcslen(function_name) + 3; - TCHAR *func = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, funclen * sizeof(TCHAR)); - if (func) { - if (_sntprintf_s(func, funclen, _TRUNCATE, _T("%s()"), function_name) > -1) function = func; - } - - _sntprintf_s(timeout_milliseconds, _countof(timeout_milliseconds), _TRUNCATE, _T("%lu"), timeout); - - waithint = service->status.dwWaitHint; - waited = 0; - while (waited < timeout) { - interval = timeout - waited; - if (interval > NSSM_SERVICE_STATUS_DEADLINE) interval = NSSM_SERVICE_STATUS_DEADLINE; - - service->status.dwCurrentState = SERVICE_STOP_PENDING; - service->status.dwWaitHint += interval; - service->status.dwCheckPoint++; - SetServiceStatus(service->status_handle, &service->status); - - if (waited) { - _sntprintf_s(waited_milliseconds, _countof(waited_milliseconds), _TRUNCATE, _T("%lu"), waited); - _sntprintf_s(interval_milliseconds, _countof(interval_milliseconds), _TRUNCATE, _T("%lu"), interval); - log_event(EVENTLOG_INFORMATION_TYPE, NSSM_EVENT_AWAITING_SHUTDOWN, function, service->name, waited_milliseconds, interval_milliseconds, timeout_milliseconds, 0); - } - - switch (WaitForSingleObject(service->process_handle, interval)) { - case WAIT_OBJECT_0: - ret = 0; - goto awaited; - - case WAIT_TIMEOUT: - ret = 1; - break; - - default: - ret = -1; - goto awaited; - } - - waited += interval; - } - -awaited: - if (func) HeapFree(GetProcessHeap(), 0, func); - - return ret; -} diff --git a/Services/entpacktes_verzeichnis/nssm-2.24/src/service.h b/Services/entpacktes_verzeichnis/nssm-2.24/src/service.h deleted file mode 100644 index 4c9ba35..0000000 --- a/Services/entpacktes_verzeichnis/nssm-2.24/src/service.h +++ /dev/null @@ -1,146 +0,0 @@ -#ifndef SERVICE_H -#define SERVICE_H - -/* - MSDN says the commandline in CreateProcess() is limited to 32768 characters - and the application name to MAX_PATH. - A service name and service display name are limited to 256 characters. - A registry key is limited to 255 characters. - A registry value is limited to 16383 characters. - Therefore we limit the service name to accommodate the path under HKLM. -*/ -#define EXE_LENGTH PATH_LENGTH -#define CMD_LENGTH 32768 -#define KEY_LENGTH 255 -#define VALUE_LENGTH 16383 -#define SERVICE_NAME_LENGTH 256 - -#define ACTION_LEN 16 - -#define NSSM_KERNEL_DRIVER _T("SERVICE_KERNEL_DRIVER") -#define NSSM_FILE_SYSTEM_DRIVER _T("SERVICE_FILE_SYSTEM_DRIVER") -#define NSSM_WIN32_OWN_PROCESS _T("SERVICE_WIN32_OWN_PROCESS") -#define NSSM_WIN32_SHARE_PROCESS _T("SERVICE_WIN32_SHARE_PROCESS") -#define NSSM_INTERACTIVE_PROCESS _T("SERVICE_INTERACTIVE_PROCESS") -#define NSSM_SHARE_INTERACTIVE_PROCESS NSSM_WIN32_SHARE_PROCESS _T("|") NSSM_INTERACTIVE_PROCESS -#define NSSM_UNKNOWN _T("?") - -#define NSSM_ROTATE_OFFLINE 0 -#define NSSM_ROTATE_ONLINE 1 -#define NSSM_ROTATE_ONLINE_ASAP 2 - -typedef struct { - bool native; - TCHAR name[SERVICE_NAME_LENGTH]; - TCHAR displayname[SERVICE_NAME_LENGTH]; - TCHAR description[VALUE_LENGTH]; - unsigned long startup; - TCHAR *username; - size_t usernamelen; - TCHAR *password; - size_t passwordlen; - unsigned long type; - TCHAR image[PATH_LENGTH]; - TCHAR exe[EXE_LENGTH]; - TCHAR flags[VALUE_LENGTH]; - TCHAR dir[DIR_LENGTH]; - TCHAR *env; - __int64 affinity; - TCHAR *dependencies; - unsigned long dependencieslen; - unsigned long envlen; - TCHAR *env_extra; - unsigned long env_extralen; - unsigned long priority; - unsigned long no_console; - TCHAR stdin_path[PATH_LENGTH]; - unsigned long stdin_sharing; - unsigned long stdin_disposition; - unsigned long stdin_flags; - TCHAR stdout_path[PATH_LENGTH]; - unsigned long stdout_sharing; - unsigned long stdout_disposition; - unsigned long stdout_flags; - HANDLE stdout_pipe; - HANDLE stdout_thread; - unsigned long stdout_tid; - TCHAR stderr_path[PATH_LENGTH]; - unsigned long stderr_sharing; - unsigned long stderr_disposition; - unsigned long stderr_flags; - HANDLE stderr_pipe; - HANDLE stderr_thread; - unsigned long stderr_tid; - bool rotate_files; - unsigned long rotate_stdout_online; - unsigned long rotate_stderr_online; - unsigned long rotate_seconds; - unsigned long rotate_bytes_low; - unsigned long rotate_bytes_high; - unsigned long default_exit_action; - unsigned long restart_delay; - unsigned long throttle_delay; - unsigned long stop_method; - unsigned long kill_console_delay; - unsigned long kill_window_delay; - unsigned long kill_threads_delay; - SC_HANDLE handle; - SERVICE_STATUS status; - SERVICE_STATUS_HANDLE status_handle; - HANDLE process_handle; - unsigned long pid; - HANDLE wait_handle; - bool stopping; - bool allow_restart; - unsigned long throttle; - CRITICAL_SECTION throttle_section; - bool throttle_section_initialised; - CONDITION_VARIABLE throttle_condition; - HANDLE throttle_timer; - LARGE_INTEGER throttle_duetime; - FILETIME creation_time; - FILETIME exit_time; - TCHAR *initial_env; -} nssm_service_t; - -void WINAPI service_main(unsigned long, TCHAR **); -TCHAR *service_control_text(unsigned long); -TCHAR *service_status_text(unsigned long); -void log_service_control(TCHAR *, unsigned long, bool); -unsigned long WINAPI service_control_handler(unsigned long, unsigned long, void *, void *); - -int affinity_mask_to_string(__int64, TCHAR **); -int affinity_string_to_mask(TCHAR *, __int64 *); -unsigned long priority_mask(); -int priority_constant_to_index(unsigned long); -unsigned long priority_index_to_constant(int); - -nssm_service_t *alloc_nssm_service(); -void set_nssm_service_defaults(nssm_service_t *); -void cleanup_nssm_service(nssm_service_t *); -SC_HANDLE open_service_manager(unsigned long); -SC_HANDLE open_service(SC_HANDLE, TCHAR *, unsigned long, TCHAR *, unsigned long); -QUERY_SERVICE_CONFIG *query_service_config(const TCHAR *, SC_HANDLE); -int set_service_dependencies(const TCHAR *, SC_HANDLE, TCHAR *); -int get_service_dependencies(const TCHAR *, SC_HANDLE, TCHAR **, unsigned long *, int); -int get_service_dependencies(const TCHAR *, SC_HANDLE, TCHAR **, unsigned long *); -int set_service_description(const TCHAR *, SC_HANDLE, TCHAR *); -int get_service_description(const TCHAR *, SC_HANDLE, unsigned long, TCHAR *); -int get_service_startup(const TCHAR *, SC_HANDLE, const QUERY_SERVICE_CONFIG *, unsigned long *); -int get_service_username(const TCHAR *, const QUERY_SERVICE_CONFIG *, TCHAR **, size_t *); -int pre_install_service(int, TCHAR **); -int pre_remove_service(int, TCHAR **); -int pre_edit_service(int, TCHAR **); -int install_service(nssm_service_t *); -int remove_service(nssm_service_t *); -int edit_service(nssm_service_t *, bool); -int control_service(unsigned long, int, TCHAR **); -void set_service_recovery(nssm_service_t *); -int monitor_service(nssm_service_t *); -int start_service(nssm_service_t *); -int stop_service(nssm_service_t *, unsigned long, bool, bool); -void CALLBACK end_service(void *, unsigned char); -void throttle_restart(nssm_service_t *); -int await_shutdown(nssm_service_t *, TCHAR *, unsigned long); - -#endif diff --git a/Services/entpacktes_verzeichnis/nssm-2.24/src/settings.cpp b/Services/entpacktes_verzeichnis/nssm-2.24/src/settings.cpp deleted file mode 100644 index 14b279a..0000000 --- a/Services/entpacktes_verzeichnis/nssm-2.24/src/settings.cpp +++ /dev/null @@ -1,1061 +0,0 @@ -#include "nssm.h" -/* XXX: (value && value->string) is probably bogus because value is probably never null */ - -/* Affinity. */ -#define NSSM_AFFINITY_ALL _T("All") - -extern const TCHAR *exit_action_strings[]; -extern const TCHAR *startup_strings[]; -extern const TCHAR *priority_strings[]; - -/* Does the parameter refer to the default value of the setting? */ -static inline int is_default(const TCHAR *value) { - return (str_equiv(value, _T("default")) || str_equiv(value, _T("*")) || ! value[0]); -} - -static int value_from_string(const TCHAR *name, value_t *value, const TCHAR *string) { - size_t len = _tcslen(string); - if (! len++) { - value->string = 0; - return 0; - } - - value->string = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, len * sizeof(TCHAR)); - if (! value->string) { - print_message(stderr, NSSM_MESSAGE_OUT_OF_MEMORY, name, _T("value_from_string()")); - return -1; - } - - if (_sntprintf_s(value->string, len, _TRUNCATE, _T("%s"), string) < 0) { - HeapFree(GetProcessHeap(), 0, value->string); - print_message(stderr, NSSM_MESSAGE_OUT_OF_MEMORY, name, _T("value_from_string()")); - return -1; - } - - return 1; -} - -/* Functions to manage NSSM-specific settings in the registry. */ -static int setting_set_number(const TCHAR *service_name, void *param, const TCHAR *name, void *default_value, value_t *value, const TCHAR *additional) { - HKEY key = (HKEY) param; - if (! key) return -1; - - unsigned long number; - long error; - - /* Resetting to default? */ - if (! value || ! value->string) { - error = RegDeleteValue(key, name); - if (error == ERROR_SUCCESS || error == ERROR_FILE_NOT_FOUND) return 0; - print_message(stderr, NSSM_MESSAGE_REGDELETEVALUE_FAILED, name, service_name, error_string(error)); - return -1; - } - if (str_number(value->string, &number)) return -1; - - if (default_value && number == (unsigned long) default_value) { - error = RegDeleteValue(key, name); - if (error == ERROR_SUCCESS || error == ERROR_FILE_NOT_FOUND) return 0; - print_message(stderr, NSSM_MESSAGE_REGDELETEVALUE_FAILED, name, service_name, error_string(error)); - return -1; - } - - if (set_number(key, (TCHAR *) name, number)) return -1; - - return 1; -} - -static int setting_get_number(const TCHAR *service_name, void *param, const TCHAR *name, void *default_value, value_t *value, const TCHAR *additional) { - HKEY key = (HKEY) param; - return get_number(key, (TCHAR *) name, &value->numeric, false); -} - -static int setting_set_string(const TCHAR *service_name, void *param, const TCHAR *name, void *default_value, value_t *value, const TCHAR *additional) { - HKEY key = (HKEY) param; - if (! key) return -1; - - long error; - - /* Resetting to default? */ - if (! value || ! value->string) { - if (default_value) value->string = (TCHAR *) default_value; - else { - error = RegDeleteValue(key, name); - if (error == ERROR_SUCCESS || error == ERROR_FILE_NOT_FOUND) return 0; - print_message(stderr, NSSM_MESSAGE_REGDELETEVALUE_FAILED, name, service_name, error_string(error)); - return -1; - } - } - if (default_value && _tcslen((TCHAR *) default_value) && str_equiv(value->string, (TCHAR *) default_value)) { - error = RegDeleteValue(key, name); - if (error == ERROR_SUCCESS || error == ERROR_FILE_NOT_FOUND) return 0; - print_message(stderr, NSSM_MESSAGE_REGDELETEVALUE_FAILED, name, service_name, error_string(error)); - return -1; - } - - if (set_expand_string(key, (TCHAR *) name, value->string)) return -1; - - return 1; -} - -static int setting_get_string(const TCHAR *service_name, void *param, const TCHAR *name, void *default_value, value_t *value, const TCHAR *additional) { - HKEY key = (HKEY) param; - TCHAR buffer[VALUE_LENGTH]; - - if (get_string(key, (TCHAR *) name, (TCHAR *) buffer, (unsigned long) sizeof(buffer), false, false, false)) return -1; - - return value_from_string(name, value, buffer); -} - -static int setting_set_exit_action(const TCHAR *service_name, void *param, const TCHAR *name, void *default_value, value_t *value, const TCHAR *additional) { - unsigned long exitcode; - TCHAR *code; - TCHAR action_string[ACTION_LEN]; - - if (additional) { - /* Default action? */ - if (is_default(additional)) code = 0; - else { - if (str_number(additional, &exitcode)) return -1; - code = (TCHAR *) additional; - } - } - - HKEY key = open_registry(service_name, name, KEY_WRITE); - if (! key) return -1; - - long error; - int ret = 1; - - /* Resetting to default? */ - if (value && value->string) _sntprintf_s(action_string, _countof(action_string), _TRUNCATE, _T("%s"), value->string); - else { - if (code) { - /* Delete explicit action. */ - error = RegDeleteValue(key, code); - RegCloseKey(key); - if (error == ERROR_SUCCESS || error == ERROR_FILE_NOT_FOUND) return 0; - print_message(stderr, NSSM_MESSAGE_REGDELETEVALUE_FAILED, code, service_name, error_string(error)); - return -1; - } - else { - /* Explicitly keep the default action. */ - if (default_value) _sntprintf_s(action_string, _countof(action_string), _TRUNCATE, _T("%s"), (TCHAR *) default_value); - ret = 0; - } - } - - /* Validate the string. */ - for (int i = 0; exit_action_strings[i]; i++) { - if (! _tcsnicmp((const TCHAR *) action_string, exit_action_strings[i], ACTION_LEN)) { - if (default_value && str_equiv(action_string, (TCHAR *) default_value)) ret = 0; - if (RegSetValueEx(key, code, 0, REG_SZ, (const unsigned char *) exit_action_strings[i], (unsigned long) (_tcslen(action_string) + 1) * sizeof(TCHAR)) != ERROR_SUCCESS) { - print_message(stderr, NSSM_MESSAGE_SETVALUE_FAILED, code, service_name, error_string(GetLastError())); - RegCloseKey(key); - return -1; - } - - RegCloseKey(key); - return ret; - } - } - - print_message(stderr, NSSM_MESSAGE_INVALID_EXIT_ACTION, action_string); - for (int i = 0; exit_action_strings[i]; i++) _ftprintf(stderr, _T("%s\n"), exit_action_strings[i]); - - return -1; -} - -static int setting_get_exit_action(const TCHAR *service_name, void *param, const TCHAR *name, void *default_value, value_t *value, const TCHAR *additional) { - unsigned long exitcode = 0; - unsigned long *code = 0; - - if (additional) { - if (! is_default(additional)) { - if (str_number(additional, &exitcode)) return -1; - code = &exitcode; - } - } - - TCHAR action_string[ACTION_LEN]; - bool default_action; - if (get_exit_action(service_name, code, action_string, &default_action)) return -1; - - value_from_string(name, value, action_string); - - if (default_action && ! _tcsnicmp((const TCHAR *) action_string, (TCHAR *) default_value, ACTION_LEN)) return 0; - return 1; -} - -static int setting_set_affinity(const TCHAR *service_name, void *param, const TCHAR *name, void *default_value, value_t *value, const TCHAR *additional) { - HKEY key = (HKEY) param; - if (! key) return -1; - - long error; - __int64 mask; - __int64 system_affinity = 0LL; - - if (value && value->string) { - DWORD_PTR affinity; - if (! GetProcessAffinityMask(GetCurrentProcess(), &affinity, (DWORD_PTR *) &system_affinity)) system_affinity = ~0; - - if (is_default(value->string) || str_equiv(value->string, NSSM_AFFINITY_ALL)) mask = 0LL; - else if (affinity_string_to_mask(value->string, &mask)) { - print_message(stderr, NSSM_MESSAGE_BOGUS_AFFINITY_MASK, value->string, num_cpus() - 1); - return -1; - } - } - else mask = 0LL; - - if (! mask) { - error = RegDeleteValue(key, name); - if (error == ERROR_SUCCESS || error == ERROR_FILE_NOT_FOUND) return 0; - print_message(stderr, NSSM_MESSAGE_REGDELETEVALUE_FAILED, name, service_name, error_string(error)); - return -1; - } - - /* Canonicalise. */ - TCHAR *canon = 0; - if (affinity_mask_to_string(mask, &canon)) canon = value->string; - - __int64 effective_affinity = mask & system_affinity; - if (effective_affinity != mask) { - /* Requested CPUs did not intersect with available CPUs? */ - if (! effective_affinity) mask = effective_affinity = system_affinity; - - TCHAR *system = 0; - if (! affinity_mask_to_string(system_affinity, &system)) { - TCHAR *effective = 0; - if (! affinity_mask_to_string(effective_affinity, &effective)) { - print_message(stderr, NSSM_MESSAGE_EFFECTIVE_AFFINITY_MASK, value->string, system, effective); - HeapFree(GetProcessHeap(), 0, effective); - } - HeapFree(GetProcessHeap(), 0, system); - } - } - - if (RegSetValueEx(key, name, 0, REG_SZ, (const unsigned char *) canon, (unsigned long) (_tcslen(canon) + 1) * sizeof(TCHAR)) != ERROR_SUCCESS) { - if (canon != value->string) HeapFree(GetProcessHeap(), 0, canon); - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_SETVALUE_FAILED, name, error_string(GetLastError()), 0); - return -1; - } - - if (canon != value->string) HeapFree(GetProcessHeap(), 0, canon); - return 1; -} - -static int setting_get_affinity(const TCHAR *service_name, void *param, const TCHAR *name, void *default_value, value_t *value, const TCHAR *additional) { - HKEY key = (HKEY) param; - if (! key) return -1; - - unsigned long type; - TCHAR *buffer = 0; - unsigned long buflen = 0; - - int ret = RegQueryValueEx(key, name, 0, &type, 0, &buflen); - if (ret == ERROR_FILE_NOT_FOUND) { - if (value_from_string(name, value, NSSM_AFFINITY_ALL) == 1) return 0; - return -1; - } - if (ret != ERROR_SUCCESS) return -1; - - if (type != REG_SZ) return -1; - - buffer = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, buflen); - if (! buffer) { - print_message(stderr, NSSM_MESSAGE_OUT_OF_MEMORY, _T("affinity"), _T("setting_get_affinity")); - return -1; - } - - if (get_string(key, (TCHAR *) name, buffer, buflen, false, false, true)) { - HeapFree(GetProcessHeap(), 0, buffer); - return -1; - } - - __int64 affinity; - if (affinity_string_to_mask(buffer, &affinity)) { - print_message(stderr, NSSM_MESSAGE_BOGUS_AFFINITY_MASK, buffer, num_cpus() - 1); - HeapFree(GetProcessHeap(), 0, buffer); - return -1; - } - - HeapFree(GetProcessHeap(), 0, buffer); - - /* Canonicalise. */ - if (affinity_mask_to_string(affinity, &buffer)) { - if (buffer) HeapFree(GetProcessHeap(), 0, buffer); - return -1; - } - - ret = value_from_string(name, value, buffer); - HeapFree(GetProcessHeap(), 0, buffer); - return ret; -} - -static int setting_set_environment(const TCHAR *service_name, void *param, const TCHAR *name, void *default_value, value_t *value, const TCHAR *additional) { - HKEY key = (HKEY) param; - if (! param) return -1; - - if (! value || ! value->string || ! value->string[0]) { - long error = RegDeleteValue(key, name); - if (error == ERROR_SUCCESS || error == ERROR_FILE_NOT_FOUND) return 0; - print_message(stderr, NSSM_MESSAGE_REGDELETEVALUE_FAILED, name, service_name, error_string(error)); - return -1; - } - - unsigned long envlen = (unsigned long) _tcslen(value->string) + 1; - TCHAR *unformatted = 0; - unsigned long newlen; - if (unformat_double_null(value->string, envlen, &unformatted, &newlen)) return -1; - - if (test_environment(unformatted)) { - HeapFree(GetProcessHeap(), 0, unformatted); - print_message(stderr, NSSM_GUI_INVALID_ENVIRONMENT); - return -1; - } - - if (RegSetValueEx(key, name, 0, REG_MULTI_SZ, (const unsigned char *) unformatted, (unsigned long) newlen * sizeof(TCHAR)) != ERROR_SUCCESS) { - if (newlen) HeapFree(GetProcessHeap(), 0, unformatted); - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_SETVALUE_FAILED, NSSM_REG_ENV, error_string(GetLastError()), 0); - return -1; - } - - if (newlen) HeapFree(GetProcessHeap(), 0, unformatted); - return 1; -} - -static int setting_get_environment(const TCHAR *service_name, void *param, const TCHAR *name, void *default_value, value_t *value, const TCHAR *additional) { - HKEY key = (HKEY) param; - if (! param) return -1; - - TCHAR *env = 0; - unsigned long envlen; - if (get_environment((TCHAR *) service_name, key, (TCHAR *) name, &env, &envlen)) return -1; - if (! envlen) return 0; - - TCHAR *formatted; - unsigned long newlen; - if (format_double_null(env, envlen, &formatted, &newlen)) return -1; - - int ret; - if (additional) { - /* Find named environment variable. */ - TCHAR *s; - size_t len = _tcslen(additional); - for (s = env; *s; s++) { - /* Look for = NULL NULL */ - if (! _tcsnicmp(s, additional, len) && s[len] == _T('=')) { - /* Strip = */ - s += len + 1; - ret = value_from_string(name, value, s); - HeapFree(GetProcessHeap(), 0, env); - return ret; - } - - /* Skip this string. */ - for ( ; *s; s++); - } - HeapFree(GetProcessHeap(), 0, env); - return 0; - } - - HeapFree(GetProcessHeap(), 0, env); - - ret = value_from_string(name, value, formatted); - if (newlen) HeapFree(GetProcessHeap(), 0, formatted); - return ret; -} - -static int setting_set_priority(const TCHAR *service_name, void *param, const TCHAR *name, void *default_value, value_t *value, const TCHAR *additional) { - HKEY key = (HKEY) param; - if (! param) return -1; - - TCHAR *priority_string; - int i; - long error; - - if (value && value->string) priority_string = value->string; - else if (default_value) priority_string = (TCHAR *) default_value; - else { - error = RegDeleteValue(key, name); - if (error == ERROR_SUCCESS || error == ERROR_FILE_NOT_FOUND) return 0; - print_message(stderr, NSSM_MESSAGE_REGDELETEVALUE_FAILED, name, service_name, error_string(error)); - return -1; - } - - for (i = 0; priority_strings[i]; i++) { - if (! str_equiv(priority_strings[i], priority_string)) continue; - - if (default_value && str_equiv(priority_string, (TCHAR *) default_value)) { - error = RegDeleteValue(key, name); - if (error == ERROR_SUCCESS || error == ERROR_FILE_NOT_FOUND) return 0; - print_message(stderr, NSSM_MESSAGE_REGDELETEVALUE_FAILED, name, service_name, error_string(error)); - return -1; - } - - if (set_number(key, (TCHAR *) name, priority_index_to_constant(i))) return -1; - return 1; - } - - print_message(stderr, NSSM_MESSAGE_INVALID_PRIORITY, priority_string); - for (i = 0; priority_strings[i]; i++) _ftprintf(stderr, _T("%s\n"), priority_strings[i]); - - return -1; -} - -static int setting_get_priority(const TCHAR *service_name, void *param, const TCHAR *name, void *default_value, value_t *value, const TCHAR *additional) { - HKEY key = (HKEY) param; - if (! param) return -1; - - unsigned long constant; - switch (get_number(key, (TCHAR *) name, &constant, false)) { - case 0: return value_from_string(name, value, (const TCHAR *) default_value); - case -1: return -1; - } - - return value_from_string(name, value, priority_strings[priority_constant_to_index(constant)]); -} - -/* Functions to manage native service settings. */ -static int native_set_dependongroup(const TCHAR *service_name, void *param, const TCHAR *name, void *default_value, value_t *value, const TCHAR *additional) { - SC_HANDLE service_handle = (SC_HANDLE) param; - if (! service_handle) return -1; - - /* - Get existing service dependencies because we must set both types together. - */ - TCHAR *buffer; - unsigned long buflen; - if (get_service_dependencies(service_name, service_handle, &buffer, &buflen, DEPENDENCY_SERVICES)) return -1; - - if (! value || ! value->string || ! value->string[0]) { - if (! ChangeServiceConfig(service_handle, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, 0, 0, 0, buffer, 0, 0, 0)) { - print_message(stderr, NSSM_MESSAGE_CHANGESERVICECONFIG_FAILED, error_string(GetLastError())); - if (buffer) HeapFree(GetProcessHeap(), 0, buffer); - return -1; - } - - if (buffer) HeapFree(GetProcessHeap(), 0, buffer); - return 0; - } - - unsigned long len = (unsigned long) _tcslen(value->string) + 1; - TCHAR *unformatted = 0; - unsigned long newlen; - if (unformat_double_null(value->string, len, &unformatted, &newlen)) { - if (buffer) HeapFree(GetProcessHeap(), 0, buffer); - return -1; - } - - /* Prepend group identifier. */ - unsigned long missing = 0; - TCHAR *canon = unformatted; - size_t canonlen = 0; - TCHAR *s; - for (s = unformatted; *s; s++) { - if (*s != SC_GROUP_IDENTIFIER) missing++; - size_t len = _tcslen(s); - canonlen += len + 1; - s += len; - } - - if (missing) { - /* Missing identifiers plus double NULL terminator. */ - canonlen += missing + 1; - newlen = (unsigned long) canonlen; - - canon = (TCHAR *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, canonlen * sizeof(TCHAR)); - if (! canon) { - print_message(stderr, NSSM_MESSAGE_OUT_OF_MEMORY, _T("canon"), _T("native_set_dependongroup")); - if (unformatted) HeapFree(GetProcessHeap(), 0, unformatted); - if (buffer) HeapFree(GetProcessHeap(), 0, buffer); - return -1; - } - - size_t i = 0; - for (s = unformatted; *s; s++) { - if (*s != SC_GROUP_IDENTIFIER) canon[i++] = SC_GROUP_IDENTIFIER; - size_t len = _tcslen(s); - memmove(canon + i, s, (len + 1) * sizeof(TCHAR)); - i += len + 1; - s += len; - } - } - - TCHAR *dependencies; - if (buflen > 2) { - dependencies = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, (newlen + buflen) * sizeof(TCHAR)); - if (! dependencies) { - print_message(stderr, NSSM_MESSAGE_OUT_OF_MEMORY, _T("dependencies"), _T("native_set_dependongroup")); - if (canon != unformatted) HeapFree(GetProcessHeap(), 0, canon); - if (unformatted) HeapFree(GetProcessHeap(), 0, unformatted); - if (buffer) HeapFree(GetProcessHeap(), 0, buffer); - return -1; - } - - memmove(dependencies, buffer, buflen * sizeof(TCHAR)); - memmove(dependencies + buflen - 1, canon, newlen * sizeof(TCHAR)); - } - else dependencies = canon; - - int ret = 1; - if (set_service_dependencies(service_name, service_handle, dependencies)) ret = -1; - if (dependencies != unformatted) HeapFree(GetProcessHeap(), 0, dependencies); - if (canon != unformatted) HeapFree(GetProcessHeap(), 0, canon); - if (unformatted) HeapFree(GetProcessHeap(), 0, unformatted); - if (buffer) HeapFree(GetProcessHeap(), 0, buffer); - - return ret; -} - -static int native_get_dependongroup(const TCHAR *service_name, void *param, const TCHAR *name, void *default_value, value_t *value, const TCHAR *additional) { - SC_HANDLE service_handle = (SC_HANDLE) param; - if (! service_handle) return -1; - - TCHAR *buffer; - unsigned long buflen; - if (get_service_dependencies(service_name, service_handle, &buffer, &buflen, DEPENDENCY_GROUPS)) return -1; - - int ret; - if (buflen) { - TCHAR *formatted; - unsigned long newlen; - if (format_double_null(buffer, buflen, &formatted, &newlen)) { - HeapFree(GetProcessHeap(), 0, buffer); - return -1; - } - - ret = value_from_string(name, value, formatted); - HeapFree(GetProcessHeap(), 0, formatted); - HeapFree(GetProcessHeap(), 0, buffer); - } - else { - value->string = 0; - ret = 0; - } - - return ret; -} - -static int native_set_dependonservice(const TCHAR *service_name, void *param, const TCHAR *name, void *default_value, value_t *value, const TCHAR *additional) { - SC_HANDLE service_handle = (SC_HANDLE) param; - if (! service_handle) return -1; - - /* - Get existing group dependencies because we must set both types together. - */ - TCHAR *buffer; - unsigned long buflen; - if (get_service_dependencies(service_name, service_handle, &buffer, &buflen, DEPENDENCY_GROUPS)) return -1; - - if (! value || ! value->string || ! value->string[0]) { - if (! ChangeServiceConfig(service_handle, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, 0, 0, 0, buffer, 0, 0, 0)) { - print_message(stderr, NSSM_MESSAGE_CHANGESERVICECONFIG_FAILED, error_string(GetLastError())); - if (buffer) HeapFree(GetProcessHeap(), 0, buffer); - return -1; - } - - if (buffer) HeapFree(GetProcessHeap(), 0, buffer); - return 0; - } - - unsigned long len = (unsigned long) _tcslen(value->string) + 1; - TCHAR *unformatted = 0; - unsigned long newlen; - if (unformat_double_null(value->string, len, &unformatted, &newlen)) { - if (buffer) HeapFree(GetProcessHeap(), 0, buffer); - return -1; - } - - TCHAR *dependencies; - if (buflen > 2) { - dependencies = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, (newlen + buflen) * sizeof(TCHAR)); - if (! dependencies) { - print_message(stderr, NSSM_MESSAGE_OUT_OF_MEMORY, _T("dependencies"), _T("native_set_dependonservice")); - if (unformatted) HeapFree(GetProcessHeap(), 0, unformatted); - if (buffer) HeapFree(GetProcessHeap(), 0, buffer); - return -1; - } - - memmove(dependencies, buffer, buflen * sizeof(TCHAR)); - memmove(dependencies + buflen - 1, unformatted, newlen * sizeof(TCHAR)); - } - else dependencies = unformatted; - - int ret = 1; - if (set_service_dependencies(service_name, service_handle, dependencies)) ret = -1; - if (dependencies != unformatted) HeapFree(GetProcessHeap(), 0, dependencies); - if (unformatted) HeapFree(GetProcessHeap(), 0, unformatted); - if (buffer) HeapFree(GetProcessHeap(), 0, buffer); - - return ret; -} - -static int native_get_dependonservice(const TCHAR *service_name, void *param, const TCHAR *name, void *default_value, value_t *value, const TCHAR *additional) { - SC_HANDLE service_handle = (SC_HANDLE) param; - if (! service_handle) return -1; - - TCHAR *buffer; - unsigned long buflen; - if (get_service_dependencies(service_name, service_handle, &buffer, &buflen, DEPENDENCY_SERVICES)) return -1; - - int ret; - if (buflen) { - TCHAR *formatted; - unsigned long newlen; - if (format_double_null(buffer, buflen, &formatted, &newlen)) { - HeapFree(GetProcessHeap(), 0, buffer); - return -1; - } - - ret = value_from_string(name, value, formatted); - HeapFree(GetProcessHeap(), 0, formatted); - HeapFree(GetProcessHeap(), 0, buffer); - } - else { - value->string = 0; - ret = 0; - } - - return ret; -} - -int native_set_description(const TCHAR *service_name, void *param, const TCHAR *name, void *default_value, value_t *value, const TCHAR *additional) { - SC_HANDLE service_handle = (SC_HANDLE) param; - if (! service_handle) return -1; - - TCHAR *description = 0; - if (value) description = value->string; - if (set_service_description(service_name, service_handle, description)) return -1; - - if (description && description[0]) return 1; - - return 0; -} - -int native_get_description(const TCHAR *service_name, void *param, const TCHAR *name, void *default_value, value_t *value, const TCHAR *additional) { - SC_HANDLE service_handle = (SC_HANDLE) param; - if (! service_handle) return -1; - - TCHAR buffer[VALUE_LENGTH]; - if (get_service_description(service_name, service_handle, _countof(buffer), buffer)) return -1; - - if (buffer[0]) return value_from_string(name, value, buffer); - value->string = 0; - - return 0; -} - -int native_set_displayname(const TCHAR *service_name, void *param, const TCHAR *name, void *default_value, value_t *value, const TCHAR *additional) { - SC_HANDLE service_handle = (SC_HANDLE) param; - if (! service_handle) return -1; - - TCHAR *displayname = 0; - if (value && value->string) displayname = value->string; - else displayname = (TCHAR *) service_name; - - if (! ChangeServiceConfig(service_handle, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, 0, 0, 0, 0, 0, 0, displayname)) { - print_message(stderr, NSSM_MESSAGE_CHANGESERVICECONFIG_FAILED, error_string(GetLastError())); - return -1; - } - - /* - If the display name and service name differ only in case, - ChangeServiceConfig() will return success but the display name will be - set to the service name, NOT the value passed to the function. - This appears to be a quirk of Windows rather than a bug here. - */ - if (displayname != service_name && ! str_equiv(displayname, service_name)) return 1; - - return 0; -} - -int native_get_displayname(const TCHAR *service_name, void *param, const TCHAR *name, void *default_value, value_t *value, const TCHAR *additional) { - SC_HANDLE service_handle = (SC_HANDLE) param; - if (! service_handle) return -1; - - QUERY_SERVICE_CONFIG *qsc = query_service_config(service_name, service_handle); - if (! qsc) return -1; - - int ret = value_from_string(name, value, qsc->lpDisplayName); - HeapFree(GetProcessHeap(), 0, qsc); - - return ret; -} - -int native_set_imagepath(const TCHAR *service_name, void *param, const TCHAR *name, void *default_value, value_t *value, const TCHAR *additional) { - SC_HANDLE service_handle = (SC_HANDLE) param; - if (! service_handle) return -1; - - /* It makes no sense to try to reset the image path. */ - if (! value || ! value->string) { - print_message(stderr, NSSM_MESSAGE_NO_DEFAULT_VALUE, name); - return -1; - } - - if (! ChangeServiceConfig(service_handle, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, value->string, 0, 0, 0, 0, 0, 0)) { - print_message(stderr, NSSM_MESSAGE_CHANGESERVICECONFIG_FAILED, error_string(GetLastError())); - return -1; - } - - return 1; -} - -int native_get_imagepath(const TCHAR *service_name, void *param, const TCHAR *name, void *default_value, value_t *value, const TCHAR *additional) { - SC_HANDLE service_handle = (SC_HANDLE) param; - if (! service_handle) return -1; - - QUERY_SERVICE_CONFIG *qsc = query_service_config(service_name, service_handle); - if (! qsc) return -1; - - int ret = value_from_string(name, value, qsc->lpBinaryPathName); - HeapFree(GetProcessHeap(), 0, qsc); - - return ret; -} - -int native_set_name(const TCHAR *service_name, void *param, const TCHAR *name, void *default_value, value_t *value, const TCHAR *additional) { - print_message(stderr, NSSM_MESSAGE_CANNOT_RENAME_SERVICE); - return -1; -} - -int native_get_name(const TCHAR *service_name, void *param, const TCHAR *name, void *default_value, value_t *value, const TCHAR *additional) { - return value_from_string(name, value, service_name); -} - -int native_set_objectname(const TCHAR *service_name, void *param, const TCHAR *name, void *default_value, value_t *value, const TCHAR *additional) { - SC_HANDLE service_handle = (SC_HANDLE) param; - if (! service_handle) return -1; - - /* - Logical syntax is: nssm set ObjectName - That means the username is actually passed in the additional parameter. - */ - bool localsystem = false; - TCHAR *username = NSSM_LOCALSYSTEM_ACCOUNT; - TCHAR *password = 0; - if (additional) { - username = (TCHAR *) additional; - if (value && value->string) password = value->string; - } - else if (value && value->string) username = value->string; - - const TCHAR *well_known = well_known_username(username); - size_t passwordsize = 0; - if (well_known) { - if (str_equiv(well_known, NSSM_LOCALSYSTEM_ACCOUNT)) localsystem = true; - username = (TCHAR *) well_known; - password = _T(""); - } - else if (! password) { - /* We need a password if the account requires it. */ - print_message(stderr, NSSM_MESSAGE_MISSING_PASSWORD, name); - return -1; - } - else passwordsize = _tcslen(password) * sizeof(TCHAR); - - /* - ChangeServiceConfig() will fail to set the username if the service is set - to interact with the desktop. - */ - unsigned long type = SERVICE_NO_CHANGE; - if (! localsystem) { - QUERY_SERVICE_CONFIG *qsc = query_service_config(service_name, service_handle); - if (! qsc) { - if (passwordsize) SecureZeroMemory(password, passwordsize); - return -1; - } - - type = qsc->dwServiceType & ~SERVICE_INTERACTIVE_PROCESS; - HeapFree(GetProcessHeap(), 0, qsc); - } - - if (! well_known) { - if (grant_logon_as_service(username)) { - if (passwordsize) SecureZeroMemory(password, passwordsize); - print_message(stderr, NSSM_MESSAGE_GRANT_LOGON_AS_SERVICE_FAILED, username); - return -1; - } - } - - if (! ChangeServiceConfig(service_handle, type, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, 0, 0, 0, 0, username, password, 0)) { - if (passwordsize) SecureZeroMemory(password, passwordsize); - print_message(stderr, NSSM_MESSAGE_CHANGESERVICECONFIG_FAILED, error_string(GetLastError())); - return -1; - } - - if (passwordsize) SecureZeroMemory(password, passwordsize); - - if (localsystem) return 0; - - return 1; -} - -int native_get_objectname(const TCHAR *service_name, void *param, const TCHAR *name, void *default_value, value_t *value, const TCHAR *additional) { - SC_HANDLE service_handle = (SC_HANDLE) param; - if (! service_handle) return -1; - - QUERY_SERVICE_CONFIG *qsc = query_service_config(service_name, service_handle); - if (! qsc) return -1; - - int ret = value_from_string(name, value, qsc->lpServiceStartName); - HeapFree(GetProcessHeap(), 0, qsc); - - return ret; -} - -int native_set_startup(const TCHAR *service_name, void *param, const TCHAR *name, void *default_value, value_t *value, const TCHAR *additional) { - SC_HANDLE service_handle = (SC_HANDLE) param; - if (! service_handle) return -1; - - /* It makes no sense to try to reset the startup type. */ - if (! value || ! value->string) { - print_message(stderr, NSSM_MESSAGE_NO_DEFAULT_VALUE, name); - return -1; - } - - /* Map NSSM_STARTUP_* constant to Windows SERVICE_*_START constant. */ - int service_startup = -1; - int i; - for (i = 0; startup_strings[i]; i++) { - if (str_equiv(value->string, startup_strings[i])) { - service_startup = i; - break; - } - } - - if (service_startup < 0) { - print_message(stderr, NSSM_MESSAGE_INVALID_SERVICE_STARTUP, value->string); - for (i = 0; startup_strings[i]; i++) _ftprintf(stderr, _T("%s\n"), startup_strings[i]); - return -1; - } - - unsigned long startup; - switch (service_startup) { - case NSSM_STARTUP_MANUAL: startup = SERVICE_DEMAND_START; break; - case NSSM_STARTUP_DISABLED: startup = SERVICE_DISABLED; break; - default: startup = SERVICE_AUTO_START; - } - - if (! ChangeServiceConfig(service_handle, SERVICE_NO_CHANGE, startup, SERVICE_NO_CHANGE, 0, 0, 0, 0, 0, 0, 0)) { - print_message(stderr, NSSM_MESSAGE_CHANGESERVICECONFIG_FAILED, error_string(GetLastError())); - return -1; - } - - SERVICE_DELAYED_AUTO_START_INFO delayed; - ZeroMemory(&delayed, sizeof(delayed)); - if (service_startup == NSSM_STARTUP_DELAYED) delayed.fDelayedAutostart = 1; - else delayed.fDelayedAutostart = 0; - if (! ChangeServiceConfig2(service_handle, SERVICE_CONFIG_DELAYED_AUTO_START_INFO, &delayed)) { - unsigned long error = GetLastError(); - /* Pre-Vista we expect to fail with ERROR_INVALID_LEVEL */ - if (error != ERROR_INVALID_LEVEL) { - log_event(EVENTLOG_ERROR_TYPE, NSSM_MESSAGE_SERVICE_CONFIG_DELAYED_AUTO_START_INFO_FAILED, service_name, error_string(error), 0); - } - } - - return 1; -} - -int native_get_startup(const TCHAR *service_name, void *param, const TCHAR *name, void *default_value, value_t *value, const TCHAR *additional) { - SC_HANDLE service_handle = (SC_HANDLE) param; - if (! service_handle) return -1; - - QUERY_SERVICE_CONFIG *qsc = query_service_config(service_name, service_handle); - if (! qsc) return -1; - - unsigned long startup; - int ret = get_service_startup(service_name, service_handle, qsc, &startup); - HeapFree(GetProcessHeap(), 0, qsc); - - if (ret) return -1; - - unsigned long i; - for (i = 0; startup_strings[i]; i++); - if (startup >= i) return -1; - - return value_from_string(name, value, startup_strings[startup]); -} - -int native_set_type(const TCHAR *service_name, void *param, const TCHAR *name, void *default_value, value_t *value, const TCHAR *additional) { - SC_HANDLE service_handle = (SC_HANDLE) param; - if (! service_handle) return -1; - - /* It makes no sense to try to reset the service type. */ - if (! value || ! value->string) { - print_message(stderr, NSSM_MESSAGE_NO_DEFAULT_VALUE, name); - return -1; - } - - /* - We can only manage services of type SERVICE_WIN32_OWN_PROCESS - and SERVICE_INTERACTIVE_PROCESS. - */ - unsigned long type = SERVICE_WIN32_OWN_PROCESS; - if (str_equiv(value->string, NSSM_INTERACTIVE_PROCESS)) type |= SERVICE_INTERACTIVE_PROCESS; - else if (! str_equiv(value->string, NSSM_WIN32_OWN_PROCESS)) { - print_message(stderr, NSSM_MESSAGE_INVALID_SERVICE_TYPE, value->string); - _ftprintf(stderr, _T("%s\n"), NSSM_WIN32_OWN_PROCESS); - _ftprintf(stderr, _T("%s\n"), NSSM_INTERACTIVE_PROCESS); - return -1; - } - - /* - ChangeServiceConfig() will fail if the service runs under an account - other than LOCALSYSTEM and we try to make it interactive. - */ - if (type & SERVICE_INTERACTIVE_PROCESS) { - QUERY_SERVICE_CONFIG *qsc = query_service_config(service_name, service_handle); - if (! qsc) return -1; - - if (! str_equiv(qsc->lpServiceStartName, NSSM_LOCALSYSTEM_ACCOUNT)) { - HeapFree(GetProcessHeap(), 0, qsc); - print_message(stderr, NSSM_MESSAGE_INTERACTIVE_NOT_LOCALSYSTEM, value->string, service_name, NSSM_LOCALSYSTEM_ACCOUNT); - return -1; - } - - HeapFree(GetProcessHeap(), 0, qsc); - } - - if (! ChangeServiceConfig(service_handle, type, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, 0, 0, 0, 0, 0, 0, 0)) { - print_message(stderr, NSSM_MESSAGE_CHANGESERVICECONFIG_FAILED, error_string(GetLastError())); - return -1; - } - - return 1; -} - -int native_get_type(const TCHAR *service_name, void *param, const TCHAR *name, void *default_value, value_t *value, const TCHAR *additional) { - SC_HANDLE service_handle = (SC_HANDLE) param; - if (! service_handle) return -1; - - QUERY_SERVICE_CONFIG *qsc = query_service_config(service_name, service_handle); - if (! qsc) return -1; - - value->numeric = qsc->dwServiceType; - HeapFree(GetProcessHeap(), 0, qsc); - - const TCHAR *string; - switch (value->numeric) { - case SERVICE_KERNEL_DRIVER: string = NSSM_KERNEL_DRIVER; break; - case SERVICE_FILE_SYSTEM_DRIVER: string = NSSM_FILE_SYSTEM_DRIVER; break; - case SERVICE_WIN32_OWN_PROCESS: string = NSSM_WIN32_OWN_PROCESS; break; - case SERVICE_WIN32_SHARE_PROCESS: string = NSSM_WIN32_SHARE_PROCESS; break; - case SERVICE_WIN32_OWN_PROCESS|SERVICE_INTERACTIVE_PROCESS: string = NSSM_INTERACTIVE_PROCESS; break; - case SERVICE_WIN32_SHARE_PROCESS|SERVICE_INTERACTIVE_PROCESS: string = NSSM_SHARE_INTERACTIVE_PROCESS; break; - default: string = NSSM_UNKNOWN; - } - - return value_from_string(name, value, string); -} - -int set_setting(const TCHAR *service_name, HKEY key, settings_t *setting, value_t *value, const TCHAR *additional) { - if (! key) return -1; - int ret; - - if (setting->set) ret = setting->set(service_name, (void *) key, setting->name, setting->default_value, value, additional); - else ret = -1; - - if (! ret) print_message(stdout, NSSM_MESSAGE_RESET_SETTING, setting->name, service_name); - else if (ret > 0) print_message(stdout, NSSM_MESSAGE_SET_SETTING, setting->name, service_name); - else print_message(stderr, NSSM_MESSAGE_SET_SETTING_FAILED, setting->name, service_name); - - return ret; -} - -int set_setting(const TCHAR *service_name, SC_HANDLE service_handle, settings_t *setting, value_t *value, const TCHAR *additional) { - if (! service_handle) return -1; - - int ret; - if (setting->set) ret = setting->set(service_name, service_handle, setting->name, setting->default_value, value, additional); - else ret = -1; - - if (! ret) print_message(stdout, NSSM_MESSAGE_RESET_SETTING, setting->name, service_name); - else if (ret > 0) print_message(stdout, NSSM_MESSAGE_SET_SETTING, setting->name, service_name); - else print_message(stderr, NSSM_MESSAGE_SET_SETTING_FAILED, setting->name, service_name); - - return ret; -} - -/* - Returns: 1 if the value was retrieved. - 0 if the default value was retrieved. - -1 on error. -*/ -int get_setting(const TCHAR *service_name, HKEY key, settings_t *setting, value_t *value, const TCHAR *additional) { - if (! key) return -1; - int ret; - - switch (setting->type) { - case REG_EXPAND_SZ: - case REG_MULTI_SZ: - case REG_SZ: - value->string = (TCHAR *) setting->default_value; - if (setting->get) ret = setting->get(service_name, (void *) key, setting->name, setting->default_value, value, additional); - else ret = -1; - break; - - case REG_DWORD: - value->numeric = (unsigned long) setting->default_value; - if (setting->get) ret = setting->get(service_name, (void *) key, setting->name, setting->default_value, value, additional); - else ret = -1; - break; - - default: - ret = -1; - break; - } - - if (ret < 0) print_message(stderr, NSSM_MESSAGE_GET_SETTING_FAILED, setting->name, service_name); - - return ret; -} - -int get_setting(const TCHAR *service_name, SC_HANDLE service_handle, settings_t *setting, value_t *value, const TCHAR *additional) { - if (! service_handle) return -1; - return setting->get(service_name, service_handle, setting->name, 0, value, additional); -} - -settings_t settings[] = { - { NSSM_REG_EXE, REG_EXPAND_SZ, (void *) _T(""), false, 0, setting_set_string, setting_get_string }, - { NSSM_REG_FLAGS, REG_EXPAND_SZ, (void *) _T(""), false, 0, setting_set_string, setting_get_string }, - { NSSM_REG_DIR, REG_EXPAND_SZ, (void *) _T(""), false, 0, setting_set_string, setting_get_string }, - { NSSM_REG_EXIT, REG_SZ, (void *) exit_action_strings[NSSM_EXIT_RESTART], false, ADDITIONAL_MANDATORY, setting_set_exit_action, setting_get_exit_action }, - { NSSM_REG_AFFINITY, REG_SZ, 0, false, 0, setting_set_affinity, setting_get_affinity }, - { NSSM_REG_ENV, REG_MULTI_SZ, NULL, false, ADDITIONAL_CRLF, setting_set_environment, setting_get_environment }, - { NSSM_REG_ENV_EXTRA, REG_MULTI_SZ, NULL, false, ADDITIONAL_CRLF, setting_set_environment, setting_get_environment }, - { NSSM_REG_NO_CONSOLE, REG_DWORD, 0, false, 0, setting_set_number, setting_get_number }, - { NSSM_REG_PRIORITY, REG_SZ, (void *) priority_strings[NSSM_NORMAL_PRIORITY], false, 0, setting_set_priority, setting_get_priority }, - { NSSM_REG_RESTART_DELAY, REG_DWORD, 0, false, 0, setting_set_number, setting_get_number }, - { NSSM_REG_STDIN, REG_EXPAND_SZ, NULL, false, 0, setting_set_string, setting_get_string }, - { NSSM_REG_STDIN NSSM_REG_STDIO_SHARING, REG_DWORD, (void *) NSSM_STDIN_SHARING, false, 0, setting_set_number, setting_get_number }, - { NSSM_REG_STDIN NSSM_REG_STDIO_DISPOSITION, REG_DWORD, (void *) NSSM_STDIN_DISPOSITION, false, 0, setting_set_number, setting_get_number }, - { NSSM_REG_STDIN NSSM_REG_STDIO_FLAGS, REG_DWORD, (void *) NSSM_STDIN_FLAGS, false, 0, setting_set_number, setting_get_number }, - { NSSM_REG_STDOUT, REG_EXPAND_SZ, NULL, false, 0, setting_set_string, setting_get_string }, - { NSSM_REG_STDOUT NSSM_REG_STDIO_SHARING, REG_DWORD, (void *) NSSM_STDOUT_SHARING, false, 0, setting_set_number, setting_get_number }, - { NSSM_REG_STDOUT NSSM_REG_STDIO_DISPOSITION, REG_DWORD, (void *) NSSM_STDOUT_DISPOSITION, false, 0, setting_set_number, setting_get_number }, - { NSSM_REG_STDOUT NSSM_REG_STDIO_FLAGS, REG_DWORD, (void *) NSSM_STDOUT_FLAGS, false, 0, setting_set_number, setting_get_number }, - { NSSM_REG_STDERR, REG_EXPAND_SZ, NULL, false, 0, setting_set_string, setting_get_string }, - { NSSM_REG_STDERR NSSM_REG_STDIO_SHARING, REG_DWORD, (void *) NSSM_STDERR_SHARING, false, 0, setting_set_number, setting_get_number }, - { NSSM_REG_STDERR NSSM_REG_STDIO_DISPOSITION, REG_DWORD, (void *) NSSM_STDERR_DISPOSITION, false, 0, setting_set_number, setting_get_number }, - { NSSM_REG_STDERR NSSM_REG_STDIO_FLAGS, REG_DWORD, (void *) NSSM_STDERR_FLAGS, false, 0, setting_set_number, setting_get_number }, - { NSSM_REG_STOP_METHOD_SKIP, REG_DWORD, 0, false, 0, setting_set_number, setting_get_number }, - { NSSM_REG_KILL_CONSOLE_GRACE_PERIOD, REG_DWORD, (void *) NSSM_KILL_CONSOLE_GRACE_PERIOD, false, 0, setting_set_number, setting_get_number }, - { NSSM_REG_KILL_WINDOW_GRACE_PERIOD, REG_DWORD, (void *) NSSM_KILL_WINDOW_GRACE_PERIOD, false, 0, setting_set_number, setting_get_number }, - { NSSM_REG_KILL_THREADS_GRACE_PERIOD, REG_DWORD, (void *) NSSM_KILL_THREADS_GRACE_PERIOD, false, 0, setting_set_number, setting_get_number }, - { NSSM_REG_THROTTLE, REG_DWORD, (void *) NSSM_RESET_THROTTLE_RESTART, false, 0, setting_set_number, setting_get_number }, - { NSSM_REG_ROTATE, REG_DWORD, 0, false, 0, setting_set_number, setting_get_number }, - { NSSM_REG_ROTATE_ONLINE, REG_DWORD, 0, false, 0, setting_set_number, setting_get_number }, - { NSSM_REG_ROTATE_SECONDS, REG_DWORD, 0, false, 0, setting_set_number, setting_get_number }, - { NSSM_REG_ROTATE_BYTES_LOW, REG_DWORD, 0, false, 0, setting_set_number, setting_get_number }, - { NSSM_REG_ROTATE_BYTES_HIGH, REG_DWORD, 0, false, 0, setting_set_number, setting_get_number }, - { NSSM_NATIVE_DEPENDONGROUP, REG_MULTI_SZ, NULL, true, ADDITIONAL_CRLF, native_set_dependongroup, native_get_dependongroup }, - { NSSM_NATIVE_DEPENDONSERVICE, REG_MULTI_SZ, NULL, true, ADDITIONAL_CRLF, native_set_dependonservice, native_get_dependonservice }, - { NSSM_NATIVE_DESCRIPTION, REG_SZ, _T(""), true, 0, native_set_description, native_get_description }, - { NSSM_NATIVE_DISPLAYNAME, REG_SZ, NULL, true, 0, native_set_displayname, native_get_displayname }, - { NSSM_NATIVE_IMAGEPATH, REG_EXPAND_SZ, NULL, true, 0, native_set_imagepath, native_get_imagepath }, - { NSSM_NATIVE_OBJECTNAME, REG_SZ, NSSM_LOCALSYSTEM_ACCOUNT, true, 0, native_set_objectname, native_get_objectname }, - { NSSM_NATIVE_NAME, REG_SZ, NULL, true, 0, native_set_name, native_get_name }, - { NSSM_NATIVE_STARTUP, REG_SZ, NULL, true, 0, native_set_startup, native_get_startup }, - { NSSM_NATIVE_TYPE, REG_SZ, NULL, true, 0, native_set_type, native_get_type }, - { NULL, NULL, NULL, NULL, NULL } -}; diff --git a/Services/entpacktes_verzeichnis/nssm-2.24/src/settings.h b/Services/entpacktes_verzeichnis/nssm-2.24/src/settings.h deleted file mode 100644 index a629839..0000000 --- a/Services/entpacktes_verzeichnis/nssm-2.24/src/settings.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef SETTINGS_H -#define SETTINGS_H - -#define NSSM_NATIVE_DEPENDONGROUP _T("DependOnGroup") -#define NSSM_NATIVE_DEPENDONSERVICE _T("DependOnService") -#define NSSM_NATIVE_DESCRIPTION _T("Description") -#define NSSM_NATIVE_DISPLAYNAME _T("DisplayName") -#define NSSM_NATIVE_IMAGEPATH _T("ImagePath") -#define NSSM_NATIVE_NAME _T("Name") -#define NSSM_NATIVE_OBJECTNAME _T("ObjectName") -#define NSSM_NATIVE_STARTUP _T("Start") -#define NSSM_NATIVE_TYPE _T("Type") - -/* Are additional arguments needed? */ -#define ADDITIONAL_GETTING (1 << 0) -#define ADDITIONAL_SETTING (1 << 1) -#define ADDITIONAL_RESETTING (1 << 2) -#define ADDITIONAL_CRLF (1 << 3) -#define ADDITIONAL_MANDATORY ADDITIONAL_GETTING|ADDITIONAL_SETTING|ADDITIONAL_RESETTING - -#define DEPENDENCY_SERVICES (1 << 0) -#define DEPENDENCY_GROUPS (1 << 1) -#define DEPENDENCY_ALL (DEPENDENCY_SERVICES|DEPENDENCY_GROUPS) - -typedef union { - unsigned long numeric; - TCHAR *string; -} value_t; - -typedef int (*setting_function_t)(const TCHAR *, void *, const TCHAR *, void *, value_t *, const TCHAR *); - -typedef struct { - const TCHAR *name; - unsigned long type; - void *default_value; - bool native; - int additional; - setting_function_t set; - setting_function_t get; -} settings_t; - -int set_setting(const TCHAR *, HKEY, settings_t *, value_t *, const TCHAR *); -int set_setting(const TCHAR *, SC_HANDLE, settings_t *, value_t *, const TCHAR *); -int get_setting(const TCHAR *, HKEY, settings_t *, value_t *, const TCHAR *); -int get_setting(const TCHAR *, SC_HANDLE, settings_t *, value_t *, const TCHAR *); - -#endif diff --git a/Services/entpacktes_verzeichnis/nssm-2.24/src/version.cmd b/Services/entpacktes_verzeichnis/nssm-2.24/src/version.cmd deleted file mode 100644 index b16e7d4..0000000 --- a/Services/entpacktes_verzeichnis/nssm-2.24/src/version.cmd +++ /dev/null @@ -1,49 +0,0 @@ -@rem Set default version in case git isn't available. -set description=0.0-0-prerelease -@rem Get canonical version from git tags, eg v2.21-24-g2c60e53. -for /f %%v in ('git describe --tags --long') do set description=%%v - -@rem Strip leading v if present, eg 2.21-24-g2c60e53. -set description=%description:v=% -set version=%description% - -@rem Get the number of commits and commit hash, eg 24-g2c60e53. -set n=%version:*-=% -set commit=%n:*-=% -call set n=%%n:%commit%=%% -set n=%n:~0,-1% - -@rem Strip n and commit, eg 2.21. -call set version=%%version:%n%-%commit%=%% -set version=%version:~0,-1% - -@rem Find major and minor. -set minor=%version:*.=% -call set major=%%version:.%minor%=%% - -@rem Build flags. -set flags=0L - -@rem Don't include n and commit if we match a tag exactly. -if "%n%" == "0" (set description=%major%.%minor%) else set flags=VS_FF_PRERELEASE -@rem Maybe we couldn't get the git tag. -if "%commit%" == "prerelease" set flags=VS_FF_PRERELEASE - -@rem Ignore the build number if this isn't Jenkins. -if "%BUILD_NUMBER%" == "" set BUILD_NUMBER=0 - -@rem Copyright year provided by Jenkins. -set md=%BUILD_ID:*-=% -call set year=%%BUILD_ID:%md%=%% -set year=%year:~0,-1% -if "%BUILD_ID%" == "" set year= - -@rem Create version.h. -@echo>version.h.new #define NSSM_VERSION _T("%description%") -@echo>>version.h.new #define NSSM_VERSIONINFO %major%,%minor%,%n%,%BUILD_NUMBER% -@echo>>version.h.new #define NSSM_DATE _T("%DATE%") -@echo>>version.h.new #define NSSM_FILEFLAGS %flags% -@echo>>version.h.new #define NSSM_COPYRIGHT _T("Public Domain; Author Iain Patterson 2003-%year%") - -fc version.h version.h.new >NUL: 2>NUL: -if %ERRORLEVEL% == 0 (del version.h.new) else (move /y version.h.new version.h) diff --git a/Services/entpacktes_verzeichnis/nssm-2.24/win32/nssm.exe b/Services/entpacktes_verzeichnis/nssm-2.24/win32/nssm.exe deleted file mode 100644 index 8faee45..0000000 Binary files a/Services/entpacktes_verzeichnis/nssm-2.24/win32/nssm.exe and /dev/null differ diff --git a/Services/entpacktes_verzeichnis/nssm-2.24/win64/nssm.exe b/Services/entpacktes_verzeichnis/nssm-2.24/win64/nssm.exe deleted file mode 100644 index 6ccfe3c..0000000 Binary files a/Services/entpacktes_verzeichnis/nssm-2.24/win64/nssm.exe and /dev/null differ diff --git a/alive_check.sh b/alive_check.sh new file mode 100644 index 0000000..18b51b2 --- /dev/null +++ b/alive_check.sh @@ -0,0 +1,32 @@ +#!/bin/bash +## Ordner anlegen +mkdir /root/REPORTS +cd /root/REPORTS + +## APT UPDATE +apt update +apt install python3-pip git -y + +## Add Crontab +if [ -f ".crontab" ]; then + echo "Gibt es" + next +else + crontab -l | { cat; echo "30 0 * * * /root/REPORTS/setup-info.sh"; } | crontab - + echo "Gibt es nicht" + touch ".crontab" +fi + +## Add GIT +git init +git remote add orgin https://gitlab.stines.de/sebastian.serfling/REPORTS.git +git fetch +git pull orgin main + +## Install Python +python3 -m pip install virtualenv +python3 -m virtualenv venv +source venv/bin/activate +python3 -m pip install requests +python3 Service/alive_check.py +deactivate \ No newline at end of file