From e4983ad839806d62c4fce982c5d5c24466adffa3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
Date: Thu, 9 Mar 2017 16:27:23 +0100
Subject: [PATCH] ntdll: Fill process kernel and user time.

---
 dlls/ntdll/nt.c         |  6 +++-
 dlls/ntdll/ntdll_misc.h |  5 +++
 dlls/ntdll/thread.c     | 84 ++++++++++++++++++++++++++++---------------------
 3 files changed, 58 insertions(+), 37 deletions(-)

diff --git a/dlls/ntdll/nt.c b/dlls/ntdll/nt.c
index 4f1ff61..454f209 100644
--- a/dlls/ntdll/nt.c
+++ b/dlls/ntdll/nt.c
@@ -2482,6 +2482,7 @@ NTSTATUS WINAPI NtQuerySystemInformation(
         {
             SYSTEM_PROCESS_INFORMATION* spi = SystemInformation;
             SYSTEM_PROCESS_INFORMATION* last = NULL;
+            unsigned long clk_tck = sysconf(_SC_CLK_TCK);
             HANDLE hSnap = 0;
             WCHAR procname[1024];
             WCHAR* exename;
@@ -2519,7 +2520,7 @@ NTSTATUS WINAPI NtQuerySystemInformation(
 
                         if (Length >= len + procstructlen)
                         {
-                            /* ftCreationTime, ftUserTime, ftKernelTime;
+                            /* ftCreationTime;
                              * vmCounters, ioCounters
                              */
  
@@ -2537,6 +2538,9 @@ NTSTATUS WINAPI NtQuerySystemInformation(
 
                             /* spi->ti will be set later on */
 
+                            if (reply->unix_pid != -1)
+                                read_process_time(reply->unix_pid, -1, clk_tck,
+                                                  &spi->KernelTime, &spi->UserTime);
                         }
                         len += procstructlen;
                     }
diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h
index ff2bb82..38f7f23 100644
--- a/dlls/ntdll/ntdll_misc.h
+++ b/dlls/ntdll/ntdll_misc.h
@@ -268,6 +268,10 @@ extern SYSTEM_CPU_INFORMATION cpu_info DECLSPEC_HIDDEN;
 NTSTATUS WINAPI RtlHashUnicodeString(PCUNICODE_STRING,BOOLEAN,ULONG,ULONG*);
 void     WINAPI LdrInitializeThunk(CONTEXT*,void**,ULONG_PTR,ULONG_PTR);
 
+/* process / thread time */
+extern BOOL read_process_time(int unix_pid, int unix_tid, unsigned long clk_tck,
+                              LARGE_INTEGER *kernel, LARGE_INTEGER *user) DECLSPEC_HIDDEN;
+
 /* string functions */
 int __cdecl NTDLL_tolower( int c );
 int __cdecl _stricmp( LPCSTR str1, LPCSTR str2 );
@@ -275,4 +279,5 @@ int __cdecl _stricmp( LPCSTR str1, LPCSTR str2 );
 /* time functions */
 ULONGLONG WINAPI get_tick_count64( void );
 #define NtGetTickCount get_tick_count64
+
 #endif
diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c
index 70320af..8dac113 100644
--- a/dlls/ntdll/thread.c
+++ b/dlls/ntdll/thread.c
@@ -149,6 +149,53 @@ static ULONG_PTR get_image_addr(void)
 }
 #endif
 
+
+BOOL read_process_time(int unix_pid, int unix_tid, unsigned long clk_tck,
+                       LARGE_INTEGER *kernel, LARGE_INTEGER *user)
+{
+#ifdef __linux__
+    unsigned long usr, sys;
+    char buf[512], *pos;
+    FILE *fp;
+    int i;
+
+    /* based on https://github.com/torvalds/linux/blob/master/fs/proc/array.c */
+    if (unix_tid != -1)
+        sprintf( buf, "/proc/%u/task/%u/stat", unix_pid, unix_tid );
+    else
+        sprintf( buf, "/proc/%u/stat", unix_pid );
+    if ((fp = fopen( buf, "r" )))
+    {
+        pos = fgets( buf, sizeof(buf), fp );
+        fclose( fp );
+
+        /* format of first chunk is "%d (%s) %c" - we have to skip to the last ')'
+         * to avoid misinterpreting the string. */
+        if (pos) pos = strrchr( pos, ')' );
+        if (pos) pos = strchr( pos + 1, ' ' );
+        if (pos) pos++;
+
+        /* skip over the following fields: state, ppid, pgid, sid, tty_nr, tty_pgrp,
+         * task->flags, min_flt, cmin_flt, maj_flt, cmaj_flt */
+        for (i = 0; (i < 11) && pos; i++)
+        {
+            pos = strchr( pos + 1, ' ' );
+            if (pos) pos++;
+        }
+
+        /* the next two values are user and system time */
+        if (pos && (sscanf( pos, "%lu %lu", &usr, &sys ) == 2))
+        {
+            kernel->QuadPart = (ULONGLONG)sys * 10000000 / clk_tck;
+            user->QuadPart   = (ULONGLONG)usr * 10000000 / clk_tck;
+            return TRUE;
+        }
+    }
+#endif
+    return FALSE;
+}
+
+
 /***********************************************************************
  *           thread_init
  *
@@ -902,42 +949,7 @@ NTSTATUS WINAPI NtQueryInformationThread( HANDLE handle, THREADINFOCLASS class,
 #ifdef __linux__
                 /* only /proc provides exact values for a specific thread */
                 if (unix_pid != -1 && unix_tid != -1)
-                {
-                    unsigned long usr, sys;
-                    char buf[512], *pos;
-                    FILE *fp;
-                    int i;
-
-                    /* based on https://github.com/torvalds/linux/blob/master/fs/proc/array.c */
-                    sprintf( buf, "/proc/%u/task/%u/stat", unix_pid, unix_tid );
-                    if ((fp = fopen( buf, "r" )))
-                    {
-                        pos = fgets( buf, sizeof(buf), fp );
-                        fclose( fp );
-
-                        /* format of first chunk is "%d (%s) %c" - we have to skip to the last ')'
-                         * to avoid misinterpreting the string. */
-                        if (pos) pos = strrchr( pos, ')' );
-                        if (pos) pos = strchr( pos + 1, ' ' );
-                        if (pos) pos++;
-
-                        /* skip over the following fields: state, ppid, pgid, sid, tty_nr, tty_pgrp,
-                         * task->flags, min_flt, cmin_flt, maj_flt, cmaj_flt */
-                        for (i = 0; (i < 11) && pos; i++)
-                        {
-                            pos = strchr( pos + 1, ' ' );
-                            if (pos) pos++;
-                        }
-
-                        /* the next two values are user and system time */
-                        if (pos && (sscanf( pos, "%lu %lu", &usr, &sys ) == 2))
-                        {
-                            kusrt.KernelTime.QuadPart = (ULONGLONG)sys * 10000000 / clk_tck;
-                            kusrt.UserTime.QuadPart   = (ULONGLONG)usr * 10000000 / clk_tck;
-                            filled_times = TRUE;
-                        }
-                    }
-                }
+                    filled_times = read_process_time(unix_pid, unix_tid, clk_tck, &kusrt.KernelTime, &kusrt.UserTime);
 #endif
 
                 /* get values for current process instead */
-- 
1.9.1

