+#define COMPLAINED_READ (1 << 0)\r
+#define COMPLAINED_WRITE (1 << 1)\r
+#define COMPLAINED_ROTATE (1 << 2)\r
+\r
+static int dup_handle(HANDLE source_handle, HANDLE *dest_handle_ptr, TCHAR *source_description, TCHAR *dest_description, unsigned long flags) {\r
+ if (! dest_handle_ptr) return 1;\r
+\r
+ if (! DuplicateHandle(GetCurrentProcess(), source_handle, GetCurrentProcess(), dest_handle_ptr, 0, true, flags)) {\r
+ log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_DUPLICATEHANDLE_FAILED, source_description, dest_description, error_string(GetLastError()), 0);\r
+ return 2;\r
+ }\r
+ return 0;\r
+}\r
+\r
+static int dup_handle(HANDLE source_handle, HANDLE *dest_handle_ptr, TCHAR *source_description, TCHAR *dest_description) {\r
+ return dup_handle(source_handle, dest_handle_ptr, source_description, dest_description, DUPLICATE_SAME_ACCESS);\r
+}\r
+\r
+/*\r
+ read_handle: read from application\r
+ pipe_handle: stdout of application\r
+ write_handle: to file\r
+*/\r
+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 rotate_delay, unsigned long *tid_ptr, unsigned long *rotate_online, bool copy_and_truncate) {\r
+ *tid_ptr = 0;\r
+\r
+ /* Pipe between application's stdout/stderr and our logging handle. */\r
+ if (read_handle_ptr && ! *read_handle_ptr) {\r
+ if (pipe_handle_ptr && ! *pipe_handle_ptr) {\r
+ if (CreatePipe(read_handle_ptr, pipe_handle_ptr, 0, 0)) {\r
+ SetHandleInformation(*pipe_handle_ptr, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT);\r
+ }\r
+ else {\r
+ log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_CREATEPIPE_FAILED, service_name, path, error_string(GetLastError()));\r
+ return (HANDLE) 0;\r
+ }\r
+ }\r
+ }\r
+\r
+ logger_t *logger = (logger_t *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(logger_t));\r
+ if (! logger) {\r
+ log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, _T("logger"), _T("create_logging_thread()"), 0);\r
+ return (HANDLE) 0;\r
+ }\r
+\r
+ ULARGE_INTEGER size;\r
+ size.LowPart = rotate_bytes_low;\r
+ size.HighPart = rotate_bytes_high;\r
+\r
+ logger->service_name = service_name;\r
+ logger->path = path;\r
+ logger->sharing = sharing;\r
+ logger->disposition = disposition;\r
+ logger->flags = flags;\r
+ logger->read_handle = *read_handle_ptr;\r
+ logger->write_handle = *write_handle_ptr;\r
+ logger->size = (__int64) size.QuadPart;\r
+ logger->tid_ptr = tid_ptr;\r
+ logger->rotate_online = rotate_online;\r
+ logger->rotate_delay = rotate_delay;\r
+ logger->copy_and_truncate = copy_and_truncate;\r
+\r