+char *service_control_text(unsigned long control) {\r
+ switch (control) {\r
+ /* HACK: there is no SERVICE_CONTROL_START constant */\r
+ case 0: return "START";\r
+ case SERVICE_CONTROL_STOP: return "STOP";\r
+ case SERVICE_CONTROL_SHUTDOWN: return "SHUTDOWN";\r
+ case SERVICE_CONTROL_PAUSE: return "PAUSE";\r
+ case SERVICE_CONTROL_CONTINUE: return "CONTINUE";\r
+ case SERVICE_CONTROL_INTERROGATE: return "INTERROGATE";\r
+ default: return 0;\r
+ }\r
+}\r
+\r
+void log_service_control(char *service_name, unsigned long control, bool handled) {\r
+ char *text = service_control_text(control);\r
+ unsigned long event;\r
+\r
+ if (! text) {\r
+ /* "0x" + 8 x hex + NULL */\r
+ text = (char *) HeapAlloc(GetProcessHeap(), 0, 11);\r
+ if (! text) {\r
+ log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, "control code", "log_service_control", 0);\r
+ return;\r
+ }\r
+ if (_snprintf(text, 11, "0x%08x", control) < 0) {\r
+ log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, "control code", "log_service_control", 0);\r
+ HeapFree(GetProcessHeap(), 0, text);\r
+ return;\r
+ }\r
+\r
+ event = NSSM_EVENT_SERVICE_CONTROL_UNKNOWN;\r
+ }\r
+ else if (handled) event = NSSM_EVENT_SERVICE_CONTROL_HANDLED;\r
+ else event = NSSM_EVENT_SERVICE_CONTROL_NOT_HANDLED;\r
+\r
+ log_event(EVENTLOG_INFORMATION_TYPE, event, service_name, text, 0);\r
+\r
+ if (event == NSSM_EVENT_SERVICE_CONTROL_UNKNOWN) {\r
+ HeapFree(GetProcessHeap(), 0, text);\r
+ }\r
+}\r
+\r