+ if (si->hStdOutput && close_stdout) CloseHandle(si->hStdOutput);\r
+ if (si->hStdError && close_stderr) CloseHandle(si->hStdError);\r
+}\r
+\r
+void close_output_handles(STARTUPINFO *si) {\r
+ return close_output_handles(si, true, true);\r
+}\r
+\r
+/* Wrapper to be called in a new thread for logging. */\r
+unsigned long WINAPI log_and_rotate(void *arg) {\r
+ logger_t *logger = (logger_t *) arg;\r
+ if (! logger) return 1;\r
+\r
+ __int64 size;\r
+ BY_HANDLE_FILE_INFORMATION info;\r
+\r
+ /* Find initial file size. */\r
+ if (! GetFileInformationByHandle(logger->write_handle, &info)) logger->size = 0LL;\r
+ else {\r
+ ULARGE_INTEGER l;\r
+ l.HighPart = info.nFileSizeHigh;\r
+ l.LowPart = info.nFileSizeLow;\r
+ size = l.QuadPart;\r
+ }\r
+\r
+ char buffer[80];\r
+ void *address;\r
+ unsigned long in, out;\r
+ while (true) {\r
+ /* Read data from the pipe. */\r
+ address = &buffer;\r
+ if (! ReadFile(logger->read_handle, address, sizeof(buffer), &in, 0)) {\r
+ log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_READFILE_FAILED, logger->service_name, logger->path, error_string(GetLastError()), 0);\r
+ return 2;\r
+ }\r
+\r
+ if (size + (__int64) in >= logger->size) {\r
+ /* Look for newline. */\r
+ unsigned long i;\r
+ for (i = 0; i < in; i++) {\r
+ if (buffer[i] == '\n') {\r
+ unsigned char unicode = IsTextUnicode(address, sizeof(buffer), 0);\r
+ if (unicode) i += sizeof(wchar_t);\r
+ else i += sizeof(char);\r
+\r
+ /* Write up to the newline. */\r
+ if (! WriteFile(logger->write_handle, address, i, &out, 0)) {\r
+ log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_WRITEFILE_FAILED, logger->service_name, logger->path, error_string(GetLastError()), 0);\r
+ return 3;\r
+ }\r
+\r
+ /* Rotate. */\r
+ TCHAR rotated[MAX_PATH];\r
+ rotated_filename(logger->path, rotated, _countof(rotated), 0);\r
+\r
+ /*\r
+ Ideally we'd try the rename first then close the handle but\r
+ MoveFile() will fail if the handle is still open so we must\r
+ risk losing everything.\r
+ */\r
+ CloseHandle(logger->write_handle);\r
+ if (! MoveFile(logger->path, rotated)) {\r
+ unsigned long error = GetLastError();\r
+ if (error != ERROR_FILE_NOT_FOUND) {\r
+ log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_ROTATE_FILE_FAILED, logger->service_name, logger->path, _T("MoveFile()"), rotated, error_string(error), 0);\r
+ /* We can at least try to re-open the existing file. */\r
+ logger->disposition = OPEN_ALWAYS;\r
+ }\r
+ }\r
+\r
+ /* Reopen. */\r
+ logger->write_handle = append_to_file(logger->path, logger->sharing, 0, logger->disposition, logger->flags);\r
+ if (! logger->write_handle) {\r
+ log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_CREATEFILE_FAILED, logger->path, error_string(GetLastError()), 0);\r
+ /* Oh dear. Now we can't log anything further. */\r
+ return 4;\r
+ }\r
+\r
+ /* Unicode files need a new BOM. */\r
+ if (unicode) write_bom(logger);\r
+\r
+ /* Resume writing after the newline. */\r
+ size = 0LL;\r
+ address = (void *) ((char *) address + i);\r
+ in -= i;\r
+\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ else if (! size) {\r
+ /* Write a BOM to the new file. */\r
+ if (IsTextUnicode(address, sizeof(buffer), 0)) write_bom(logger);\r
+ }\r
+\r
+ /* Write the data. */\r
+ if (! WriteFile(logger->write_handle, address, in, &out, 0)) {\r
+ log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_WRITEFILE_FAILED, logger->service_name, logger->path, error_string(GetLastError()), 0);\r
+ return 3;\r
+ }\r
+\r
+ size += (__int64) out;\r
+ }\r
+\r
+ return 0;\r