From: Iain Patterson Date: Tue, 12 Nov 2013 10:50:21 +0000 (+0000) Subject: AttachConsole() isn't available in Windows 2000. X-Git-Tag: v2.17~3 X-Git-Url: http://git.iain.cx/?a=commitdiff_plain;h=e42e6900a5dad50b952d92c57344fdea2e13646e;p=nssm.git AttachConsole() isn't available in Windows 2000. Instead of calling AttachConsole() directory use a function pointer in the new global imports struct. It's safe to skip any attempt to attach to the console when the function isn't available. --- diff --git a/imports.cpp b/imports.cpp new file mode 100644 index 0000000..49483d4 --- /dev/null +++ b/imports.cpp @@ -0,0 +1,56 @@ +#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)); +} diff --git a/imports.h b/imports.h new file mode 100644 index 0000000..f731ad6 --- /dev/null +++ b/imports.h @@ -0,0 +1,16 @@ +#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 diff --git a/messages.mc b/messages.mc index 0aea1ae..8b6c984 100644 --- a/messages.mc +++ b/messages.mc @@ -1270,3 +1270,38 @@ The service %1 is stopping but PID %2 is still running. 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 +. diff --git a/nssm.cpp b/nssm.cpp index 1ee38bd..0ce8664 100644 --- a/nssm.cpp +++ b/nssm.cpp @@ -2,6 +2,7 @@ extern unsigned long tls_index; extern bool is_admin; +extern imports_t imports; /* String function */ int str_equiv(const char *a, const char *b) { @@ -69,6 +70,9 @@ int main(int argc, char **argv) { This will save time when running with no arguments from a command prompt. */ if (_fileno(stdin) < 0) { + /* Set up function pointers. */ + if (get_imports()) exit(111); + /* Start service magic */ SERVICE_TABLE_ENTRY table[] = { { NSSM, service_main }, { 0, 0 } }; if (! StartServiceCtrlDispatcher(table)) { @@ -76,6 +80,7 @@ int main(int argc, char **argv) { /* 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); } } diff --git a/nssm.dsp b/nssm.dsp index a643e4d..2ac2b34 100644 --- a/nssm.dsp +++ b/nssm.dsp @@ -96,6 +96,10 @@ SOURCE=.\gui.cpp # End Source File # Begin Source File +SOURCE=.\imports.cpp +# End Source File +# Begin Source File + SOURCE=.\io.cpp # End Source File # Begin Source File @@ -128,6 +132,10 @@ SOURCE=.\gui.h # End Source File # Begin Source File +SOURCE=.\imports.h +# End Source File +# Begin Source File + SOURCE=.\io.h # End Source File # Begin Source File diff --git a/nssm.h b/nssm.h index afff8c4..d297527 100644 --- a/nssm.h +++ b/nssm.h @@ -7,6 +7,7 @@ #include #include #include "event.h" +#include "imports.h" #include "messages.h" #include "process.h" #include "registry.h" diff --git a/nssm.vcproj b/nssm.vcproj index 2b16220..040039d 100755 --- a/nssm.vcproj +++ b/nssm.vcproj @@ -466,6 +466,10 @@ /> + + @@ -627,6 +631,10 @@ RelativePath="gui.h" > + + diff --git a/process.cpp b/process.cpp index 4c00e64..ee88af3 100644 --- a/process.cpp +++ b/process.cpp @@ -1,5 +1,7 @@ #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; @@ -186,8 +188,11 @@ int kill_process(char *service_name, unsigned long stop_method, HANDLE process_h 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) { diff --git a/service.cpp b/service.cpp index f82b9bd..fcb1c5a 100644 --- a/service.cpp +++ b/service.cpp @@ -538,7 +538,9 @@ void CALLBACK end_service(void *arg, unsigned char why) { /* 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); - exit(stop_service(exitcode, false, default_action)); + stop_service(exitcode, false, default_action); + free_imports(); + exit(exitcode); break; } }