From 24f4eced42fb95328a05cff0370139efe55b98aa Mon Sep 17 00:00:00 2001
From: Ryan Cumming <ryan@completely.kicks-ass.org>
Date: Mon, 25 Nov 2002 01:33:38 +0000
Subject: [PATCH] Partially implement GetThreadTimes.

---
 include/wine/server_protocol.h |  4 +++-
 scheduler/thread.c             | 28 ++++++++++++++++++++++------
 server/protocol.def            | 16 +++++++++-------
 server/thread.c                | 16 +++++++++++-----
 server/thread.h                |  2 ++
 server/trace.c                 |  4 +++-
 6 files changed, 50 insertions(+), 20 deletions(-)

diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
index 15997ac75de..466c7e543a1 100644
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -394,6 +394,8 @@ struct get_thread_info_reply
     void*        teb;
     int          exit_code;
     int          priority;
+    time_t       creation_time;
+    time_t       exit_time;
 };
 
 
@@ -3460,6 +3462,6 @@ union generic_reply
     struct get_next_hook_reply get_next_hook_reply;
 };
 
-#define SERVER_PROTOCOL_VERSION 90
+#define SERVER_PROTOCOL_VERSION 91
 
 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */
diff --git a/scheduler/thread.c b/scheduler/thread.c
index d52ced35bbb..86234934812 100644
--- a/scheduler/thread.c
+++ b/scheduler/thread.c
@@ -677,9 +677,6 @@ DWORD WINAPI QueueUserAPC( PAPCFUNC func, HANDLE hthread, ULONG_PTR data )
 /**********************************************************************
  * GetThreadTimes [KERNEL32.@]  Obtains timing information.
  *
- * NOTES
- *    What are the fields where these values are stored?
- *
  * RETURNS
  *    Success: TRUE
  *    Failure: FALSE
@@ -691,9 +688,28 @@ BOOL WINAPI GetThreadTimes(
     LPFILETIME kerneltime,   /* [out] Time thread spent in kernel mode */
     LPFILETIME usertime)     /* [out] Time thread spent in user mode */
 {
-    FIXME("(0x%p): stub\n",thread);
-    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-    return FALSE;
+    BOOL ret = TRUE;
+
+    if (creationtime || exittime)
+    {
+        /* We need to do a server call to get the creation time or exit time */
+        /* This works on any thread */
+
+        SERVER_START_REQ( get_thread_info )
+        {
+            req->handle = thread;
+            req->tid_in = 0;
+            if ((ret = !wine_server_call_err( req )))
+            {
+                if (creationtime)
+                    RtlSecondsSince1970ToTime( reply->creation_time, (LARGE_INTEGER*)creationtime );
+                if (exittime)
+                    RtlSecondsSince1970ToTime( reply->exit_time, (LARGE_INTEGER*)exittime );
+            }
+        }
+        SERVER_END_REQ;
+    }
+    return ret;
 }
 
 
diff --git a/server/protocol.def b/server/protocol.def
index bd5177f4195..1b15d85d646 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -336,13 +336,15 @@ typedef struct
 
 /* Retrieve information about a thread */
 @REQ(get_thread_info)
-    obj_handle_t handle;       /* thread handle */
-    thread_id_t  tid_in;       /* thread id (optional) */
-@REPLY
-    thread_id_t  tid;          /* server thread id */
-    void*        teb;          /* thread teb pointer */
-    int          exit_code;    /* thread exit code */
-    int          priority;     /* thread priority level */
+    obj_handle_t handle;        /* thread handle */
+    thread_id_t  tid_in;        /* thread id (optional) */
+@REPLY
+    thread_id_t  tid;           /* server thread id */
+    void*        teb;           /* thread teb pointer */
+    int          exit_code;     /* thread exit code */
+    int          priority;      /* thread priority level */
+    time_t       creation_time; /* thread creation time */
+    time_t       exit_time;     /* thread exit time */
 @END
 
 
diff --git a/server/thread.c b/server/thread.c
index c29ba46dcf1..f8396e09436 100644
--- a/server/thread.c
+++ b/server/thread.c
@@ -31,7 +31,7 @@
 #include <string.h>
 #include <sys/types.h>
 #include <unistd.h>
-#include <stdarg.h>
+#include <time.h>
 
 #include "winbase.h"
 
@@ -132,6 +132,8 @@ inline static void init_thread_structure( struct thread *thread )
     thread->priority        = THREAD_PRIORITY_NORMAL;
     thread->affinity        = 1;
     thread->suspend         = 0;
+    thread->creation_time   = time(NULL);
+    thread->exit_time       = 0;
 
     for (i = 0; i < MAX_INFLIGHT_FDS; i++)
         thread->inflight[i].server = thread->inflight[i].client = -1;
@@ -706,6 +708,7 @@ void kill_thread( struct thread *thread, int violent_death )
 {
     if (thread->state == TERMINATED) return;  /* already killed */
     thread->state = TERMINATED;
+    thread->exit_time = time(NULL);
     if (current == thread) current = NULL;
     if (debug_level)
         fprintf( stderr,"%08x: *killed* exit_code=%d\n",
@@ -878,10 +881,13 @@ DECL_HANDLER(get_thread_info)
 
     if (thread)
     {
-        reply->tid       = get_thread_id( thread );
-        reply->teb       = thread->teb;
-        reply->exit_code = (thread->state == TERMINATED) ? thread->exit_code : STILL_ACTIVE;
-        reply->priority  = thread->priority;
+        reply->tid            = get_thread_id( thread );
+        reply->teb            = thread->teb;
+        reply->exit_code      = (thread->state == TERMINATED) ? thread->exit_code : STILL_ACTIVE;
+        reply->priority       = thread->priority;
+        reply->creation_time  = thread->creation_time;
+        reply->exit_time      = thread->exit_time;
+
         release_object( thread );
     }
 }
diff --git a/server/thread.h b/server/thread.h
index 0c029014d85..218a7b3a4b2 100644
--- a/server/thread.h
+++ b/server/thread.h
@@ -92,6 +92,8 @@ struct thread
     int                    priority;      /* priority level */
     int                    affinity;      /* affinity mask */
     int                    suspend;       /* suspend count */
+    time_t                 creation_time; /* Thread creation time */
+    time_t                 exit_time;     /* Thread exit time */
 };
 
 struct thread_snapshot
diff --git a/server/trace.c b/server/trace.c
index 49f486b835e..368cca27734 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -515,7 +515,9 @@ static void dump_get_thread_info_reply( const struct get_thread_info_reply *req
     fprintf( stderr, " tid=%08x,", req->tid );
     fprintf( stderr, " teb=%p,", req->teb );
     fprintf( stderr, " exit_code=%d,", req->exit_code );
-    fprintf( stderr, " priority=%d", req->priority );
+    fprintf( stderr, " priority=%d,", req->priority );
+    fprintf( stderr, " creation_time=%ld,", req->creation_time );
+    fprintf( stderr, " exit_time=%ld", req->exit_time );
 }
 
 static void dump_set_thread_info_request( const struct set_thread_info_request *req )
-- 
GitLab