Iain Patterson [Fri, 15 Jul 2016 13:27:31 +0000 (14:27 +0100)]
Added nssm_exe().
New function to retrieve argv[0].
Iain Patterson [Thu, 14 Jul 2016 16:44:14 +0000 (17:44 +0100)]
Redirect hooks' output.
If AppRedirectHook is 1 and stdout and/or stderr are being redirected,
also redirect the output of hooks.
Doing so requires using a logging thread and so implies online rotation
if log rotation is used.
Thanks Nabil Redmann.
Iain Patterson [Thu, 14 Jul 2016 16:07:28 +0000 (17:07 +0100)]
Added dup_handle().
New wrapper around DuplicateHandle().
Iain Patterson [Tue, 5 Jul 2016 09:05:08 +0000 (10:05 +0100)]
David Bremner committed some fixes.
David Bremner [Mon, 4 Jul 2016 21:47:25 +0000 (14:47 -0700)]
CreateFile returns INVALID_HANDLE_VALUE on failure https://msdn.microsoft.com/en-us/library/windows/desktop/
aa363858(v=vs.85).aspx
David Bremner [Mon, 4 Jul 2016 21:36:19 +0000 (14:36 -0700)]
CreateToolhelp32Snapshot returns INVALID_HANDLE_VALUE on failure https://msdn.microsoft.com/en-us/library/windows/desktop/ms682489(v=vs.85).aspx
David Bremner [Mon, 4 Jul 2016 21:35:06 +0000 (14:35 -0700)]
service->passwordlen is a count of TCHARs, fix SecureZeroMemory for UNICODE
David Bremner [Mon, 4 Jul 2016 21:32:04 +0000 (14:32 -0700)]
move misplaced return
David Bremner [Mon, 4 Jul 2016 21:31:26 +0000 (14:31 -0700)]
remove dead breaks and returns
Iain Patterson [Fri, 17 Jun 2016 14:38:00 +0000 (15:38 +0100)]
Try to create messages at install time.
If the service was never run under a privileged account we might not
have been able to set the message source in the registry.
Set the message source when installing the service, as we are guaranteed
to have the necessary rights.
Iain Patterson [Thu, 21 Apr 2016 09:18:53 +0000 (10:18 +0100)]
Compiler food.
SetConsoleCtrlHandler() returns BOOL which is not bool.
Iain Patterson [Wed, 20 Apr 2016 21:25:36 +0000 (22:25 +0100)]
Added list command to enumerate NSSM services.
Use "nssm list" to print all services which are managed by NSSM.
Iain Patterson [Thu, 31 Mar 2016 07:34:33 +0000 (08:34 +0100)]
Technically we should stop ignoring Control-C.
Before signalling our application we implement a null Control-C handler
so we don't get killed ourselves when signalling the process group. We
should probably restore the default behaviour after signalling.
Iain Patterson [Sun, 20 Mar 2016 09:20:40 +0000 (09:20 +0000)]
Don't ignore must_exist in open_registry().
A typo meant that we were passing true to the overloaded open_registry()
which also takes an HKEY as a parameter.
As a result we would end up spamming ERROR_FILE_NOT_FOUND when updating
a service via the GUI if there were no hooks to update, ironically in a
section of code whose purpose was to check that it didn't need to do or
report anything.
Thanks Igor Zenkov and James Gleason.
Iain Patterson [Tue, 1 Mar 2016 10:22:28 +0000 (10:22 +0000)]
Not an error if no hook found in the registry.
Hooks are optional so we shouldn't log an error if one wasn't found.
Thanks Mathias Breiner.
Iain Patterson [Tue, 1 Mar 2016 10:19:13 +0000 (10:19 +0000)]
Alternative open_registry_key() signature.
Allow passing a pointer to an HKEY and having the function return the
result of RegCreateKeyEx()/RegOpenKeyEx(). Existing functions wrap the
new invocation so no code changes are needed.
The new function can be used to handle ERROR_FILE_NOT_FOUND as success
when must_exist is false.
Iain Patterson [Sun, 28 Feb 2016 09:01:09 +0000 (09:01 +0000)]
Help git figure out how to diff .mc and .rc files.
Visual Studio wants .mc and .rc files to be UTF-16LE, which git thinks
are binary. Use .gitattributes to force treating them as text only when
diffing, explicitly not handling them as text when submitting as they
must retain their encoding to keep Visual Studio happy.
Thanks to Mathias Breiner for proposing the use of .gitattributes in the
repo. I had the rules in .git/info/exclude in my working copy for a
long time and forgot about the issue!
Iain Patterson [Sun, 28 Feb 2016 08:59:11 +0000 (08:59 +0000)]
Use CRLF consistently.
The mismatch of line endings has long been an annoyance.
Thanks Mathias Breiner for advocating finally doing something about it.
Iain Patterson [Sun, 28 Feb 2016 08:46:49 +0000 (08:46 +0000)]
Use service_registry_path() in create_exit_action().
As a result of registry function refactoring we were constructing the
default path to AppExit incorrectly. Using the function created for the
purpose works correctly, unsurprisingly.
Thanks Igor Zenkov.
Mathias Breiner [Thu, 11 Feb 2016 18:31:26 +0000 (19:31 +0100)]
Workaround for Resource Compiler warnings/errors under VS2010.
VS2010 RC.exe yielded lots of warnings and some errors when including some (unnecessary) platform header files via nssm.h. So now including only what is really required.
This includes a workaround for error RC2247 found here: http://stackoverflow.com/a/
18317658
Iain Patterson [Tue, 23 Feb 2016 13:41:28 +0000 (13:41 +0000)]
Fix compilation on VS2015.
Paul Baxter and Mathias Breiner independently reported fixes to get the
project to compile on Visual Studio 2015.
Iain Patterson [Mon, 22 Feb 2016 13:15:44 +0000 (13:15 +0000)]
EventMessageFile should be unquoted.
We were writing a quoted message source path to the registry.
Stefan and Michael Scherer point out that it should be unquoted.
Iain Patterson [Wed, 17 Feb 2016 11:39:00 +0000 (11:39 +0000)]
Compiler food.
Iain Patterson [Wed, 17 Feb 2016 09:42:16 +0000 (09:42 +0000)]
Fix crash on Windows XP.
The pointer returned by GetEnvironmentStrings() on Unicode versions of
Windows XP was to the raw environment block, not a copy as described in
the documentation. Retrieving it into service->initial_env and keeping
it around for the lifetime of the service could cause a crash. Instead
we now copy the memory and immediately call FreeEnvironmentStrings().
Thanks Scott Ware.
Iain Patterson [Sun, 8 Mar 2015 17:24:58 +0000 (17:24 +0000)]
Clean up Parameters properly.
If create_parameters() failed to write Application, AppParameters or
AppDirectory it would try to clean up by deleting the Parameters key.
The method used to do so was flawed. It would attempt to delete the key
defined by the NSSM_REGISTRY macro but that macro contains a printf
control string and is not suitable for standalone use.
Iain Patterson [Sun, 8 Mar 2015 17:21:53 +0000 (17:21 +0000)]
Incorrect capitalisation of AppStderrCopyAndTruncate.
Iain Patterson [Sun, 8 Mar 2015 17:21:09 +0000 (17:21 +0000)]
Describe startup environment in the README.
Iain Patterson [Sun, 8 Mar 2015 16:45:55 +0000 (16:45 +0000)]
Abstracted open_registry().
Added service_registry_path() to construct a registry path for a service
which may contain the Parameters subkey and optional sub-subkey. If no
Parameters subkey is needed the constructed path references the native
service parameters.
The open_registry() function is now a wrapper around the new
open_registry_key() function which opens an arbitrary key.
The new open_service_resgistry() function also wraps open_registry_key()
to access native parameters.
Iain Patterson [Mon, 2 Mar 2015 11:03:59 +0000 (11:03 +0000)]
Use nssm_imagepath().
We were calling GetModuleFileName() in a number of places. Use
nssm_imagepath() instead.
Ensure that a quoted path is used for the service image path when
creating the service, thus avoiding a theoretical security vulnerability
whereby the service manager could be tricked into launching the wrong
program.
When setting the path to NSSM in the environment for event hooks we
still use the unquoted path, as environment variables are typically
unquoted.
Thanks Gerald Haider.
Iain Patterson [Mon, 2 Mar 2015 11:02:06 +0000 (11:02 +0000)]
Added nssm_imagepath() and nssm_unquoted_imagepath().
Functions to retrieve the path to nssm.exe both with and without path
quoting.
Iain Patterson [Tue, 24 Feb 2015 13:37:17 +0000 (13:37 +0000)]
Save the environment.
Before the previous two commits we used to read the environment from the
registry and set it using an optimisation which modified the retrieved
block in-place.
Now we need to set the environment twice after querying the registry -
once in get_parameters() and once just before CreateProcess(), which
means we can't use the in-place optimisation and must copy the block
before operating on it.
Additionally, nssm_hook() cleans the environment so we have to reinstate
it immediately prior to launching the application.
Iain Patterson [Mon, 23 Feb 2015 21:47:01 +0000 (21:47 +0000)]
Compiler food.
Missing header from previous commit.
Iain Patterson [Mon, 23 Feb 2015 21:22:22 +0000 (21:22 +0000)]
Set the environment before querying the registry.
Handle AppEnvironment and AppEnvironmentExtra before querying registry
parameters. Doing so allows paths and arguments passed to the service
to reference such environment variables.
Thanks Yuriy Lesiuk.
Iain Patterson [Mon, 23 Feb 2015 21:17:58 +0000 (21:17 +0000)]
Formatting.
Iain Patterson [Fri, 2 Jan 2015 16:59:28 +0000 (16:59 +0000)]
Start service in a new thread so we don't block stop controls.
Iain Patterson [Thu, 1 Jan 2015 19:01:54 +0000 (19:01 +0000)]
Run hooks in response to certain events.
User-configurable hooks will be run before and/or after certain events,
eg after the application starts successfully.
Hooks will run with the environment of the application, with additional
environment variables providing information about the service status and
the hook which has been called.
Iain Patterson [Fri, 2 Jan 2015 13:16:54 +0000 (13:16 +0000)]
Don't create registry keys needlessly.
Don't log an error when trying to access a registry key which doesn't
exist when it's expected that it might not be present.
Don't open a key with RegCreateKeyEx() when we are potentially going to
delete a value. Instead try RegOpenKeyEx() and return success if it
already isn't present.
Iain Patterson [Fri, 2 Jan 2015 11:31:19 +0000 (11:31 +0000)]
Fixed permissions check in open_registry().
We were checking for the presence of KEY_WRITE in the SAM to decide
whether to call RegCreateKeyEx() or RegOpenKeyEx(). KEY_WRITE is an
alias for STANDARD_RIGHTS_WRITE | KEY_SET_VALUE | KEY_CREATE_SUB_KEY so
the function was incorrectly calling RegCreateKeyEx() even when
RegOpenKeyEx() would be more appropriate.
Iain Patterson [Wed, 31 Dec 2014 14:33:57 +0000 (14:33 +0000)]
Don't time out waiting for service status change.
Wait for service to start (or fail to start) or stop instead of timing
out after five seconds.
An NSSM service which doesn't start properly and temporarily enters
paused state may end up reporting running state in response to a stop
control. Therefore we now consider SERVICE_RUNNING to be a valid
response to SERVICE_CONTROL_STOP.
Iain Patterson [Wed, 31 Dec 2014 15:11:05 +0000 (15:11 +0000)]
RegisterPowerSettingNotification is unnecessary.
We were importing RegisterPowerSettingNotification but not actually
calling it. This didn't matter because including
SERVICE_ACCEPT_POWEREVENT in the accepted controls list is sufficient to
receive power notifications.
Iain Patterson [Wed, 31 Dec 2014 13:16:24 +0000 (13:16 +0000)]
Restrict acceptance of service controls.
Don't accept a pause/continue control unless the service is marked as
paused.
Don't accept any control until startup is pending.
Don't accept any control after processing a stop control.
Iain Patterson [Wed, 31 Dec 2014 13:15:10 +0000 (13:15 +0000)]
More StringFileInfo parameters.
The CompanyName and OriginalFileName parameters are mandatory according
to the spec, so we now provide them.
Iain Patterson [Tue, 30 Dec 2014 11:05:12 +0000 (11:05 +0000)]
Refactor kill functions to be independent of services.
Removed most explicit references to service data in kill functions so
they can be used to kill arbitrary process trees.
The function to wait for service status change has been renamed
await_single_handle() to reflect that it can wait for any single object
not just a service's process handle.
Iain Patterson [Mon, 15 Dec 2014 22:50:38 +0000 (22:50 +0000)]
Single waiting function.
Use a single function to wait for service status to change, regardless
of if we are waiting for the service to run for a minimum period of time
to be unthrottled or for it to shut down..
Iain Patterson [Mon, 15 Dec 2014 14:05:55 +0000 (14:05 +0000)]
Allow slow service startup again.
Previously we enforced a maximum delay in reporting to the service
manager that the service was started, and waited for the application to
become unthrottled in the background.
Users may prefer that the service not report a started state until the
application is unthrottled. Therefore we now loop and increment the
status checkpoint and wait hint to satisfy the service manager that we
aren't hung.
Thanks Tom Saul.
Iain Patterson [Mon, 15 Dec 2014 22:54:58 +0000 (22:54 +0000)]
Typo millisencondes.
Iain Patterson [Mon, 15 Dec 2014 13:58:39 +0000 (13:58 +0000)]
Don't try to operate on freed data structure.
We were calling HeapFree() on the logger structure then trying to
call CloseHandle() on one of its elements.
Iain Patterson [Thu, 18 Sep 2014 07:28:21 +0000 (08:28 +0100)]
Copy/truncate file rotation.
Some processes, notably Logstash, open files for reading without setting
the FILE_SHARE_READ share mode. If NSSM is using such a file for I/O
redirection and it tries to rotate the file, its MoveFile() call will
fail.
If the new (REG_DWORD) value(s) AppStdoutCopyAndTruncate and/or
AppStderrCopyAndTruncate are non-zero, NSSM will instead try to rotate
the file(s) by calling CopyFile() to create a copy of the file then
calling SetEndOfFile() to truncate the original file to zero size.
Doing so allows the rotation to succeed at the cost of time and disk
space to create a full copy of the file.
If the new (REG_DWORD) value AppRotateDelay is non-zero, NSSM will sleep
for the given number of milliseconds after rotation, regardless of the
rotation method used. Testing with Logstash specifically has shown that
introducing a delay of 1000ms may be sufficient to avoid an issue
whereby the reading application loses the final line of input from the
old file due to not noticing that it has been truncated.
Thanks Miguel Angel Terrón.
Iain Patterson [Sat, 13 Sep 2014 07:01:18 +0000 (08:01 +0100)]
Allow skipping kill_process_tree().
Don't try to kill the application's process tree - just the application
itself - if the REG_DWORD value AppKillProcessTree is 0.
Thanks Barrett Lewis.
Iain Patterson [Wed, 7 May 2014 07:33:56 +0000 (08:33 +0100)]
Import RegisterPowerSettingNotification().
Iain Patterson [Wed, 7 May 2014 07:33:35 +0000 (08:33 +0100)]
Restart in response to PBT_APMRESUMEAUTOMATIC event.
Iain Patterson [Sun, 31 Aug 2014 15:32:58 +0000 (16:32 +0100)]
NSSM 2.24.
Iain Patterson [Sun, 31 Aug 2014 15:08:56 +0000 (16:08 +0100)]
Terminate the correct process.
We were calling TerminateProcess() on the service process handle in
instead of the handle passed to kill_process().
Thanks Sam Townsend.
Iain Patterson [Sun, 29 Jun 2014 10:37:43 +0000 (11:37 +0100)]
NSSM 2.23.
Iain Patterson [Sun, 29 Jun 2014 10:24:36 +0000 (11:24 +0100)]
Use CloseServiceHandle() on service handles.
We were incorrectly calling CloseHandle() to close service handles.
CloseServiceHandle() is not only for service manager handles and should
be used on service handles as well.
Iain Patterson [Sun, 29 Jun 2014 10:10:37 +0000 (11:10 +0100)]
Fixed some typos and whitespace errors.
Iain Patterson [Sun, 29 Jun 2014 10:09:07 +0000 (11:09 +0100)]
Fixed running service under local username.
Trying to set a local account to run the service would fail with
LsaLookupNames() complaining that the name could not be looked up.
Thanks Allen Vailliencourt.
Iain Patterson [Wed, 4 Jun 2014 18:20:44 +0000 (19:20 +0100)]
Suppress ERROR_PROC_NOT_FOUND events.
Don't log "The specified procedure could not be found" if
GetProcAddress() fails. ERROR_PROC_NOT_FOUND is expected when running a
version of Windows which doesn't support the desired. function
Thanks Alain Douangpraseuth.
Gildas le Nadan [Sun, 25 May 2014 10:22:50 +0000 (11:22 +0100)]
Typos.
Signed-off-by: Iain Patterson <me@iain.cx>
Iain Patterson [Fri, 16 May 2014 13:51:04 +0000 (14:51 +0100)]
NSSM 2.22.
Gildas le Nadan [Fri, 16 May 2014 13:49:53 +0000 (14:49 +0100)]
Latest French translations.
Signed-off-by: Iain Patterson <me@iain.cx>
Iain Patterson [Mon, 14 Apr 2014 18:25:38 +0000 (19:25 +0100)]
Disable console window's close menu item.
We can't trap Control-C in a service context but we can grey out the
close window button on the console window. Doing so goes some way
toward preventing accidental closure.
Thanks Hadrien Kohl.
Iain Patterson [Tue, 1 Apr 2014 21:20:21 +0000 (22:20 +0100)]
Fixed broken environment on restart.
We were calling duplicate_environment() to copy the service's initial
environment prior to restarting it. However the duplicate_environment()
function modified its input by replacing = characters with NULLs. That
is not allowed; the memory returned by GetEnvironmentStrings() must be
treated as readonly.
After two restarts the application would run with a null environment and
probably crash.
We now copy the initial environment on to the heap and operate on the
copy, ensuring that the corruption does not occur.
Thanks Alessandro Gherardi.
Iain Patterson [Sun, 2 Mar 2014 18:29:45 +0000 (18:29 +0000)]
Allow editing service dependencies.
Service dependencies can now be queried or set on the command line via
the DependOnService and DependOnGroup parameters, or via the GUI in the
new Dependencies tab.
Service dependencies can be set using either their key name or display
name. For example:
nssm set <servicename> DependOnService RpcSs
which is equivalent to:
nssm set <servicename> DependOnService "Remote Procedure Call (RPC)"
Group dependencies can be set with or without the group identifier
prefix, which for some reason is not actually described in the
documentation; instead readers are invited to consult the header files
for the value of SC_GROUP_IDENTIFIER, which it turns out is the +
symbol. For example:
nssm set <servicename> DependOnGroup +UIGroup
which is equivalent to:
nssm set <servicename> DependOnGroup UIGroup
The prefix is always printed when query group dependencies.
The GUI presents a editbox into which either service or group
dependencies can be typed. The group prefix is mandatory when editing
dependencies via the GUI.
Iain Patterson [Sun, 2 Mar 2014 14:22:53 +0000 (14:22 +0000)]
Really get canonical name in open_service().
The open_service() function would return the canonical service name if
passed a display name but would return the requested name as-is when
called with a valid service name. We now retrieve the display name and
map back to the key name so that the returned string is capitalised
exactly as it appears in the services database.
Iain Patterson [Sun, 2 Mar 2014 12:28:46 +0000 (12:28 +0000)]
HeapFree() before GetLastError().
Successful HeapFree() will set the last error to 0 so the GetLastError()
call will not be meaningful.
Iain Patterson [Sun, 2 Mar 2014 11:48:56 +0000 (11:48 +0000)]
Correct CloseHandle() call.
Closing a service handle is done with CloseHandle() not
CloseServiceHandle().
Iain Patterson [Sat, 1 Mar 2014 12:58:55 +0000 (12:58 +0000)]
Skip blank lines in format_double_null().
Ignore blank lines when formatting, so the user doesn't need to worry
about entering environment variables or dependency names in the exactly
correct format.
Iain Patterson [Sat, 1 Mar 2014 11:42:21 +0000 (11:42 +0000)]
Renamed un/format_environment().
The format_environment() and unformat_environment() functions could be
used to format any double null-terminated string list, and are not
specificially tied to formatting environment blocks.
Iain Patterson [Thu, 13 Feb 2014 18:52:55 +0000 (18:52 +0000)]
Don't crash when installing a service.
install_service() calls edit_service() with a null username, causing
well_known_username() to segfault.
Thanks Czenda Czendov.
Iain Patterson [Thu, 6 Feb 2014 21:30:06 +0000 (21:30 +0000)]
UAC awareness.
Relaunch NSSM with administrator privileges if an attempt to install,
edit or remove a service fails.
The new process won't inherit the original console so its output won't
be visible. For that reason we don't attempt to elevate for operations
which need to be able to display messages, such as controlling a service
or editing parameters.
Thanks to various people for requesting the feature but mainly to Marco
Certelli for advice on the implementation.
Iain Patterson [Tue, 4 Feb 2014 21:42:45 +0000 (21:42 +0000)]
Open services with minimal privileges.
Ask for the minimal access rights required to manage a service, so
users don't need to be administrators to perform operations permitted by
the service (manager) ACL.
Iain Patterson [Tue, 4 Feb 2014 08:01:20 +0000 (08:01 +0000)]
Argument consistency.
Use "<args> ..." in the usage message to indicate that the arguments are
not the literal string "args" and that there can be an arbitrary number
of them.
The Italian message was already like this but the English and French
were not.
Marco Cartelli [Tue, 4 Feb 2014 08:00:23 +0000 (08:00 +0000)]
Latest Italian translations.
Signed-off-by: Iain Patterson <me@iain.cx>
Iain Patterson [Tue, 4 Feb 2014 07:53:26 +0000 (07:53 +0000)]
Tidy up Edit Service buttons.
The French and Italian versions of Edit Service didn't fit as well as
the English version.
Iain Patterson [Mon, 3 Feb 2014 18:40:27 +0000 (18:40 +0000)]
Don't complain if the service has no ObjectName.
Not all service types run under an account.
Iain Patterson [Mon, 3 Feb 2014 18:30:25 +0000 (18:30 +0000)]
Format the exit action dropdown.
The longer messages didn't fully fit in the exit actions dropdown. Make
it wide enough to accommodate them.
Iain Patterson [Sun, 2 Feb 2014 23:21:44 +0000 (23:21 +0000)]
Credit for latest Italian translations.
Iain Patterson [Sun, 2 Feb 2014 23:19:05 +0000 (23:19 +0000)]
Removed redundant NSSM_EVENT_STDIN_CREATEPIPE_FAILED.
We aren't faking stdin with a pipe any longer so the message isn't
needed.
Iain Patterson [Sun, 2 Feb 2014 23:16:28 +0000 (23:16 +0000)]
Command arguments no longer called options.
The things appended to a program path in order to make a command line
are more appropriately called Arguments than Options.
Thanks Marco Certelli.
Marco Cartelli [Sun, 2 Feb 2014 23:15:52 +0000 (23:15 +0000)]
Latest Italian translations.
Signed-off-by: Iain Patterson <me@iain.cx>
Iain Patterson [Thu, 30 Jan 2014 20:49:43 +0000 (20:49 +0000)]
Use well-known account aliases.
Jump through a few hoops to make the Windows service control panel to
localise service ObjectNames if they are set to LocalSystem,
LocalService or NetworkService.
Those aren't the canonical names of the accounts as returned by
LsaLookupSids() so attempting to call ChangeServiceConfig() with a
username of, eg, NetworkService will fail, even though writing
NetworkService directly to the registry would work. Calling
ChangeServiceConfig() with a username of "NT Authority\Network Service"
will work, since that's the canonical name returned by LsaLookupSids()
but it won't be localised in the control panel.
The solution is to write "NT Authority\NetworkService" to the registry
and it will appear correctly.
At this point I'm not sure whether to label it a bug or a feature that
"nssm get <service> ObjectName" will return the actual value in the
registry and not the localised name.
Thanks Marco Certelli.
Iain Patterson [Wed, 29 Jan 2014 20:30:55 +0000 (20:30 +0000)]
Handle well-known account names.
Certain well-known accounts can be used to start a service without
entering a password.
"LocalSystem" is the default value of ObjectName in the registry. It is
not a real account but is an alias for the "NT Authority\System"
account.
"NT Authority\Local Service" has minimal local and no network
privileges.
"NT Authority\Network Service" has minimal local and network privileges.
NSSM now recognises these well-known accounts and will accept them as
ObjectName parameters without complaining that no password was enter.
With the exception of LocalSystem, each can be specified without the "NT
Authority" pseudo-domain prefix.
Iain Patterson [Tue, 28 Jan 2014 22:56:02 +0000 (22:56 +0000)]
Added CreateWellKnownSid and IsWellKnownSid imports.
Visual Studio 2008 doesn't recognise the functions so we need to load
them to the imports table.
Iain Patterson [Tue, 28 Jan 2014 22:42:37 +0000 (22:42 +0000)]
Fixed argument parsing for setting ObjectName.
Setting ObjectName needs a username and password, except when it
doesn't. We can't make the extra argument mandatory because it isn't.
Iain Patterson [Mon, 27 Jan 2014 22:28:55 +0000 (22:28 +0000)]
Correct label on file rotation GUI.
AppRotateBytes is, as the name implies, a measure of bytes. The GUI
incorrectly said kB.
Thanks Marco Certelli.
Iain Patterson [Mon, 27 Jan 2014 22:21:15 +0000 (22:21 +0000)]
Kill process tree from the top down.
On Windows 8.1 (and maybe other versions), attempting to kill
conhost.exe before its parent cmd.exe will cause the attempt to kill the
latter to fail and the console window to remain active after the service
ends.
We now kill the members of the process tree in reverse order, so the
problem doesn't occur.
Thanks Czenda Czendov.
Iain Patterson [Mon, 27 Jan 2014 22:17:45 +0000 (22:17 +0000)]
Ensure we have a valid service exit time.
Sometimes GetProcessTimes() will succeed but return 0 for the process
exit time, leading check_parent() to conclude that the service had
exited before a child process had started, and thus that the child
process was not part of the service's tree.
We now use initialise the service exit time to the current time before
attempting to get the real exit time, and only override the value if
it's valid.
Thanks Czenda Czendov.
Iain Patterson [Mon, 27 Jan 2014 21:13:31 +0000 (21:13 +0000)]
Send Control-C to the right window.
We were always trying to send Control-C to the console of the parent
process rather than any subprocesses found in kill_process_tree().
Iain Patterson [Mon, 27 Jan 2014 19:05:46 +0000 (19:05 +0000)]
Enough with the small buffers already.
Sledgehammer, meet nut.
Iain Patterson [Mon, 27 Jan 2014 18:46:32 +0000 (18:46 +0000)]
Fixed service context detection when built with VS2013.
Visual Studio 2013 includes a C runtime which assigns stdin, stdout and
stderr the file descriptors 0, 1 and 2 - just like UNIX does - even if
there are no streams available. Thus we can no longer use "_fileno(stdin)
< 0" as a check for running in a service context.
Instead we check for "GetStdHandle(STD_INPUT_HANDLE) == 0" which works
when compiled with older or newer versions of Visual Studio.
Thanks Czenda Czendov.
Iain Patterson [Sun, 26 Jan 2014 16:22:26 +0000 (16:22 +0000)]
Don't expand parameters when editing a service.
Environment variables were still being expanded when retrieving strings
to display in the GUI.
Iain Patterson [Sun, 26 Jan 2014 16:12:11 +0000 (16:12 +0000)]
Really fix warning when file disposition isn't set.
If AppStdoutDisposition and AppStderrDisposition are both missing from
the registry, the service editing GUI would still incorrectly complain
that the current configuration couldn't be represented in the interface
even though a previous commit claimed to fix that.
Iain Patterson [Sun, 26 Jan 2014 14:11:57 +0000 (14:11 +0000)]
Split get_output_handles() into get_io_parameters().
Separate retrieving parameters from the registry and opening output
handles.
Restart throttling happens after calling get_output_handles(), so if the
service was throttled we'd end up with a useless console window
appearing during the pause.
Iain Patterson [Sun, 26 Jan 2014 14:21:41 +0000 (14:21 +0000)]
Moved console functions to a new file.
Functions for allocating and setting up a console are moved to
console.cpp.
Iain Patterson [Sat, 25 Jan 2014 21:45:56 +0000 (21:45 +0000)]
Allocate new console by default.
Since the whole purpose of NSSM is to be able to make services out of
applications which expect to have a standard desktop environment, let's
simply allocate a new console for each one rather than do so only when
we try to redirect I/O.
A funky ASCII art banner identifies the console as belonging to the
service. NSSM itself will detach from the console as soon as possible,
so if the service runs a graphical application the console may never be
seen.
The console can be suppressed by setting the REG_DWORD value
AppNoConsole to 1.
Note that services running console applications on Windows 2000 may
fail if the console is disabled.
Iain Patterson [Sat, 25 Jan 2014 21:59:57 +0000 (21:59 +0000)]
Allocate a new console for stdin.
Allocate a new console for processes which require stdin instead of
using the pipe hack.
Iain Patterson [Sat, 25 Jan 2014 11:22:11 +0000 (11:22 +0000)]
Fixed CreateFile() flags when opening log files.
Opening a file with FILE_APPEND_DATA access is not appropriate when not
truncating existing files or opening new files. Redirected I/O would be
buffered and output would not be immediately visible to readers.
Iain Patterson [Thu, 23 Jan 2014 21:19:32 +0000 (21:19 +0000)]
Revamped environment variables again.
A previous commit changed how environment variables were managed.
Initially we were calling SetEnvironmentVariable() on each variable
defined in AppEnvironmentExtra prior to starting the service. That
behaviour was changed because it was technically incorrect, potentially
resulting in NSSM's own environment being harmed.
Unfortunately the changed method, creating a new environment block by
calling GetEnvironmentStrings() (or using the block from AppEnvironment
if that and AppEnvironmentExtra were both defined), failed if users did
something like set AppEnvironmentExtra to PATH=C:\bin;%PATH%. That
would result in the process being started with a block which included
TWO occurrences of the PATH variable; the system-defined one and the
appended one. The latter would be ignored, possibly causing the
application to fail to start.
For this third attempt we now call GetEnvironmentStrings() once at
startup, storing the block in a new variable which is only freed at
exit. Immediately prior to calling CreateProcess() to start the service
we use the new environment functions duplicate_environment() (on
AppEnvironment) and set_environment_block() (on AppEnvironmentExtra) to
set the variables. Then immediately after calling CreateProcess() we
call duplicate_environment() again to restore the original block.
Because they are passed to expand_environment_string(), the environment
blocks are subject to expansion. That means that setting PATH as
described in the example above would work. Trying to append items to
the PATH by setting AppEnvironment in a similar way will probably not
work.
Thanks Bryan Senseman.
Iain Patterson [Thu, 23 Jan 2014 21:12:43 +0000 (21:12 +0000)]
Added more environment functions.
useful_environment() skips the uninteresting variables at the start of
an environment block, returning a pointer to the first useful variable.
expand_environment_string() expands a string with
ExpandEnvironmentStrings() and returns a pointer to the expanded string,
which must be freed after use.
set_environment_block() iterates through all the variables in an
environment block, expands each one with expand_environment_string() and
calls SetEnvironmentVariable() with the expanded value.
clear_environment() removes all variables from the current environment.
duplicate_environment() duplicates an environment block by first calling
clear_environment() then set_environment_block() with the source block.
Thus it ensures that the variables in the block - and only those - are
set in the current environment.