--- /dev/null
+#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 char *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));
+ }
+
+ return ret;
+}
+
+FARPROC get_import(HMODULE library, const char *function, unsigned long *error) {
+ *error = 0;
+
+ FARPROC ret = GetProcAddress(library, function);
+ if (! ret) {
+ *error = GetLastError();
+ log_event(EVENTLOG_WARNING_TYPE, NSSM_EVENT_GETPROCADDRESS_FAILED, function, error_string(*error));
+ }
+
+ return ret;
+}
+
+int get_imports() {
+ unsigned long error;
+
+ ZeroMemory(&imports, sizeof(imports));
+
+ imports.kernel32 = get_dll("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;
+ }
+ }
+ else if (error != ERROR_MOD_NOT_FOUND) return 1;
+
+ return 0;
+}
+
+void free_imports() {
+ if (imports.kernel32) FreeLibrary(imports.kernel32);
+ ZeroMemory(&imports, sizeof(imports));
+}
--- /dev/null
+#ifndef IMPORTS_H
+#define IMPORTS_H
+
+typedef BOOL (WINAPI *AttachConsole_ptr)(DWORD);
+
+typedef struct {
+ HMODULE kernel32;
+ AttachConsole_ptr AttachConsole;
+} imports_t;
+
+HMODULE get_dll(const char *, unsigned long *);
+FARPROC get_import(HMODULE, const char *, unsigned long *);
+int get_imports();
+void free_imports();
+
+#endif
Usually %3 will call TerminateProcess() as a last resort to ensure that the process is stopped but the registry value %4 has been set and not all process termination methods have been attempted.
It will no longer be possible to attempt to control the application and the service will report a stopped status.
.
+
+MessageId = +1
+SymbolicName = NSSM_EVENT_LOADLIBRARY_FAILED
+Severity = Warning
+Language = English
+Error loading the %1 DLL!
+LoadLibrary() failed:
+%2
+.
+Language = French
+Erreur à l'ouverture de la DLL %1!
+LoadLibrary() a échoué:
+%2
+.
+Language = Italian
+Errore apertura DLL %1!
+Chiamata a LoadLibrary() fallita:
+%2
+.
+
+MessageId = +1
+SymbolicName = NSSM_EVENT_GETPROCADDRESS_FAILED
+Severity = Warning
+Language = English
+GetProcAddress(%1) failed:
+%2
+.
+Language = French
+GetProcAddress(%1) a échoué:
+%2
+.
+Language = Italian
+Chiamata a GetProcAddress(%1) fallita:
+%2
+.
\r
extern unsigned long tls_index;\r
extern bool is_admin;\r
+extern imports_t imports;\r
\r
/* String function */\r
int str_equiv(const char *a, const char *b) {\r
This will save time when running with no arguments from a command prompt.\r
*/\r
if (_fileno(stdin) < 0) {\r
+ /* Set up function pointers. */\r
+ if (get_imports()) exit(111);\r
+\r
/* Start service magic */\r
SERVICE_TABLE_ENTRY table[] = { { NSSM, service_main }, { 0, 0 } };\r
if (! StartServiceCtrlDispatcher(table)) {\r
/* User probably ran nssm with no argument */\r
if (error == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT) exit(usage(1));\r
log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_DISPATCHER_FAILED, error_string(error), 0);\r
+ free_imports();\r
exit(100);\r
}\r
}\r
# End Source File\r
# Begin Source File\r
\r
+SOURCE=.\imports.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
SOURCE=.\io.cpp\r
# End Source File\r
# Begin Source File\r
# End Source File\r
# Begin Source File\r
\r
+SOURCE=.\imports.h\r
+# End Source File\r
+# Begin Source File\r
+\r
SOURCE=.\io.h\r
# End Source File\r
# Begin Source File\r
#include <stdio.h>\r
#include <windows.h>\r
#include "event.h"\r
+#include "imports.h"\r
#include "messages.h"\r
#include "process.h"\r
#include "registry.h"\r
/>\r
</FileConfiguration>\r
</File>\r
+ <File\r
+ RelativePath=".\imports.cpp"\r
+ >\r
+ </File>\r
<File\r
RelativePath=".\io.cpp"\r
>\r
RelativePath="gui.h"\r
>\r
</File>\r
+ <File\r
+ RelativePath=".\imports.h"\r
+ >\r
+ </File>\r
<File\r
RelativePath=".\io.h"\r
>\r
#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;
int kill_console(char *service_name, HANDLE process_handle, unsigned long pid) {
unsigned long ret;
+ /* Check we loaded AttachConsole(). */
+ if (! imports.AttachConsole) return 4;
+
/* Try to attach to the process's console. */
- if (! AttachConsole(pid)) {
+ if (! imports.AttachConsole(pid)) {
ret = GetLastError();
switch (ret) {
/* Fake a crash so pre-Vista service managers will run recovery actions. */\r
case NSSM_EXIT_UNCLEAN:\r
log_event(EVENTLOG_INFORMATION_TYPE, NSSM_EVENT_EXIT_UNCLEAN, service_name, code, exit_action_strings[action], 0);\r
- exit(stop_service(exitcode, false, default_action));\r
+ stop_service(exitcode, false, default_action);\r
+ free_imports();\r
+ exit(exitcode);\r
break;\r
}\r
}\r