+extern imports_t imports;
+
+int get_process_creation_time(HANDLE process_handle, FILETIME *ft) {
+ FILETIME creation_time, exit_time, kernel_time, user_time;
+
+ if (! GetProcessTimes(process_handle, &creation_time, &exit_time, &kernel_time, &user_time)) {
+ log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_GETPROCESSTIMES_FAILED, error_string(GetLastError()), 0);
+ return 1;
+ }
+
+ memmove(ft, &creation_time, sizeof(creation_time));
+
+ return 0;
+}
+
+int get_process_exit_time(HANDLE process_handle, FILETIME *ft) {
+ FILETIME creation_time, exit_time, kernel_time, user_time;
+
+ if (! GetProcessTimes(process_handle, &creation_time, &exit_time, &kernel_time, &user_time)) {
+ log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_GETPROCESSTIMES_FAILED, error_string(GetLastError()), 0);
+ return 1;
+ }
+
+ memmove(ft, &exit_time, sizeof(exit_time));
+
+ return 0;
+}
+
+int check_parent(nssm_service_t *service, PROCESSENTRY32 *pe, unsigned long ppid) {
+ /* Check parent process ID matches. */
+ if (pe->th32ParentProcessID != ppid) return 1;
+
+ /*
+ Process IDs can be reused so do a sanity check by making sure the child
+ has been running for less time than the parent.
+ Though unlikely, it's possible that the parent exited and its process ID
+ was already reused, so we'll also compare against its exit time.
+ */
+ HANDLE process_handle = OpenProcess(PROCESS_QUERY_INFORMATION, false, pe->th32ProcessID);
+ if (! process_handle) {
+ TCHAR pid_string[16];
+ _sntprintf_s(pid_string, _countof(pid_string), _TRUNCATE, _T("%lu"), pe->th32ProcessID);
+ log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OPENPROCESS_FAILED, pid_string, service->name, error_string(GetLastError()), 0);
+ return 2;
+ }
+
+ FILETIME ft;
+ if (get_process_creation_time(process_handle, &ft)) {
+ CloseHandle(process_handle);
+ return 3;
+ }
+
+ CloseHandle(process_handle);
+
+ /* Verify that the parent's creation time is not later. */
+ if (CompareFileTime(&service->creation_time, &ft) > 0) return 4;
+
+ /* Verify that the parent's exit time is not earlier. */
+ if (CompareFileTime(&service->exit_time, &ft) < 0) return 5;
+
+ return 0;
+}
+