Implement NtQuerySystemInformation(SystemTimeOfDayInformation)

Felix Nawothnig felix.nawothnig at t-online.de
Tue May 17 16:06:51 CDT 2005


Hi.

This patch fully implements NtQuerySystemInformation 
(SystemTimeOfDayInformation) as discussed on #wh.

Before my patch kernel32 queried wineserver for the start time in ticks 
for the GetTickCount() calculation but this value wasn't usable for 
NtQuerySystemInformation due to 2 reasons:

First it was transferred as a 32bit tickcount which wraps every 49 days 
(but the boottime reported by NtQuerySystemInformation is 64bit) and 
second there seems to be no easy way to pass the value to ntdll.

And since there seemed to be no request which was a) called at the right 
time in ntdll and b) semantically at least somewhat matching I added a 
new one. I don't really like that - a better way would probably be 
moving most of the init code to ntll where it belongs (I think) and 
implementing NtCreateProcess() & co. so init_process could be used - but 
doing this for implementing an rarely used & undocumented API would 
probably be more overkill than this new request is (and since this is 
probably far in the future and will change the protocol again anyway 
there seems to be nothing wrong with doing it now). :)

ChangeLog:
  - Implement NtQuerySystemInformation(SystemTimeOfDayInformation)
  - Request server start time in ntdll using a new request and let
    kernel32 use NtQuerySystemInformation() to calculate tick-base.
-------------- next part --------------
Index: server/protocol.def
===================================================================
RCS file: /home/wine/wine/server/protocol.def,v
retrieving revision 1.136
diff -u -r1.136 protocol.def
--- server/protocol.def	11 May 2005 19:01:10 -0000	1.136
+++ server/protocol.def	17 May 2005 19:34:57 -0000
@@ -228,13 +228,19 @@
 @END
 
 
+/* Retrieve server start time */
+ at REQ(get_server_start_time)
+ at REPLY
+    time_t       server_start_time; /* time the server was started */
+ at END
+
+
 /* Initialize a process; called from the new process context */
 @REQ(init_process)
     void*        peb;          /* addr of PEB */
     void*        ldt_copy;     /* addr of LDT copy */
 @REPLY
     int          create_flags; /* creation flags */
-    unsigned int server_start; /* server start time (GetTickCount) */
     size_t       info_size;    /* total size of startup info */
     obj_handle_t exe_file;     /* file handle for main exe */
     obj_handle_t hstdin;       /* handle for stdin */
Index: server/request.c
===================================================================
RCS file: /home/wine/wine/server/request.c,v
retrieving revision 1.87
diff -u -r1.87 request.c
--- server/request.c	24 Apr 2005 17:35:52 -0000	1.87
+++ server/request.c	17 May 2005 19:34:58 -0000
@@ -111,8 +111,8 @@
 
 struct thread *current = NULL;  /* thread handling the current request */
 unsigned int global_error = 0;  /* global error code for when no thread is current */
-unsigned int server_start_ticks = 0;  /* tick count offset from server startup */
 
+static time_t server_start_time = 0; /* time the server was started */
 static struct master_socket *master_socket;  /* the master socket object */
 
 /* socket communication static structures */
@@ -453,7 +453,7 @@
 {
     struct timeval t;
     gettimeofday( &t, NULL );
-    return (t.tv_sec * 1000) + (t.tv_usec / 1000) - server_start_ticks;
+    return (t.tv_sec - server_start_time) * 1000 + (t.tv_usec / 1000);
 }
 
 static void master_socket_dump( struct object *obj, int verbose )
@@ -775,8 +775,13 @@
     msghdr.msg_iov     = &myiovec;
     msghdr.msg_iovlen  = 1;
 
-    /* init startup ticks */
-    server_start_ticks = get_tick_count();
+    /* init server start time */
+    server_start_time = time(NULL);
+}
+
+DECL_HANDLER(get_server_start_time)
+{
+    reply->server_start_time = server_start_time;
 }
 
 /* master socket timer expiration handler */
Index: server/object.h
===================================================================
RCS file: /home/wine/wine/server/object.h,v
retrieving revision 1.60
diff -u -r1.60 object.h
--- server/object.h	11 May 2005 18:25:27 -0000	1.60
+++ server/object.h	17 May 2005 19:34:58 -0000
@@ -168,9 +168,6 @@
 extern int foreground;
 extern const char *server_argv0;
 
-  /* server start time used for GetTickCount() */
-extern unsigned int server_start_ticks;
-
 /* name space for synchronization objects */
 extern struct namespace *sync_namespace;
 
Index: server/process.c
===================================================================
RCS file: /home/wine/wine/server/process.c,v
retrieving revision 1.127
diff -u -r1.127 process.c
--- server/process.c	10 May 2005 15:15:50 -0000	1.127
+++ server/process.c	17 May 2005 19:35:00 -0000
@@ -401,7 +401,6 @@
         info->thread  = (struct thread *)grab_object( current );
     }
     reply->create_flags = process->create_flags;
-    reply->server_start = server_start_ticks;
     return info ? (struct startup_info *)grab_object( info ) : NULL;
 }
 
Index: dlls/kernel/process.c
===================================================================
RCS file: /home/wine/wine/dlls/kernel/process.c,v
retrieving revision 1.87
diff -u -r1.87 process.c
--- dlls/kernel/process.c	20 Apr 2005 15:43:36 -0000	1.87
+++ dlls/kernel/process.c	17 May 2005 19:35:04 -0000
@@ -65,7 +65,7 @@
 static DWORD shutdown_priority = 0x280;
 static DWORD process_dword;
 
-static unsigned int server_startticks;
+static LARGE_INTEGER boot_time;
 int main_create_flags = 0;
 HMODULE kernel32_handle = 0;
 
@@ -909,6 +909,7 @@
     static const WCHAR kernel32W[] = {'k','e','r','n','e','l','3','2',0};
     BOOL ret;
     size_t info_size = 0;
+    SYSTEM_TIMEOFDAY_INFORMATION sys_time_info;
     RTL_USER_PROCESS_PARAMETERS *params;
     PEB *peb = NtCurrentTeb()->Peb;
     HANDLE hstdin, hstdout, hstderr;
@@ -932,7 +933,6 @@
             main_exe_file     = reply->exe_file;
             main_create_flags = reply->create_flags;
             info_size         = reply->info_size;
-            server_startticks = reply->server_start;
             hstdin            = reply->hstdin;
             hstdout           = reply->hstdout;
             hstderr           = reply->hstderr;
@@ -941,6 +941,9 @@
     SERVER_END_REQ;
     if (!ret) return FALSE;
 
+    NtQuerySystemInformation(SystemTimeOfDayInformation, &sys_time_info, sizeof(sys_time_info), 0);
+    boot_time = sys_time_info.liKeBootTime;
+
     if (info_size == 0)
     {
         params = peb->ProcessParameters;
@@ -2909,15 +2912,15 @@
  *  The current tick count.
  *
  * NOTES
- *  -The value returned will wrap arounf every 2^32 milliseconds.
- *  -Under Windows, tick 0 is the moment at which the system is rebooted.
- *  Under Wine, tick 0 begins at the moment the wineserver process is started,
+ *  - The value returned will wrap around every 2^32 milliseconds.
+ *  - Under Windows, tick 0 is the moment at which the system is rebooted.
+ *    Under Wine, tick 0 is the moment the wineserver process is started.
  */
 DWORD WINAPI GetTickCount(void)
 {
-    struct timeval t;
-    gettimeofday( &t, NULL );
-    return ((t.tv_sec * 1000) + (t.tv_usec / 1000)) - server_startticks;
+    LARGE_INTEGER system_time;
+    NtQuerySystemTime(&system_time);
+    return (system_time.QuadPart - boot_time.QuadPart) / 10000;
 }
 
 
Index: dlls/ntdll/thread.c
===================================================================
RCS file: /home/wine/wine/dlls/ntdll/thread.c,v
retrieving revision 1.26
diff -u -r1.26 thread.c
--- dlls/ntdll/thread.c	27 Apr 2005 08:18:20 -0000	1.26
+++ dlls/ntdll/thread.c	17 May 2005 19:35:05 -0000
@@ -52,6 +52,7 @@
 static RTL_BITMAP tls_expansion_bitmap;
 static LIST_ENTRY tls_links;
 
+extern LARGE_INTEGER NTDLL_BootTime;
 
 /***********************************************************************
  *           alloc_teb
@@ -156,6 +157,14 @@
         MESSAGE( "wine: failed to create the process heap\n" );
         exit(1);
     }
+    
+    /* initialize boot time for NtQuerySystemInformation() */
+    SERVER_START_REQ( get_server_start_time )
+    {
+        if (!wine_server_call( req ))
+            RtlSecondsSince1970ToTime(reply->server_start_time, &NTDLL_BootTime);
+    }
+    SERVER_END_REQ;
 }
 
 
Index: dlls/ntdll/nt.c
===================================================================
RCS file: /home/wine/wine/dlls/ntdll/nt.c,v
retrieving revision 1.82
diff -u -r1.82 nt.c
--- dlls/ntdll/nt.c	13 May 2005 13:55:51 -0000	1.82
+++ dlls/ntdll/nt.c	17 May 2005 19:35:06 -0000
@@ -37,8 +37,7 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
 
-/* FIXME: fixed at 2005/2/22 */
-static LONGLONG boottime = (LONGLONG)1275356510 * 100000000;
+LARGE_INTEGER NTDLL_BootTime;
 
 /* Structures used by NtConnectPort */
 
@@ -556,7 +555,7 @@
 
     if (!Counter) return STATUS_ACCESS_VIOLATION;
     NtQuerySystemTime( &time );
-    time.QuadPart -= boottime;
+    time.QuadPart -= NTDLL_BootTime.QuadPart;
     /* convert a counter that increments at a rate of 10 MHz
      * to one of 1193182 Hz, with some care for arithmetic
      * overflow ( will not overflow until 3396 or so ) and
@@ -657,11 +656,21 @@
             SYSTEM_TIMEOFDAY_INFORMATION* sti = (SYSTEM_TIMEOFDAY_INFORMATION*)SystemInformation;
             if (Length >= sizeof(*sti))
             {
-                sti->liKeBootTime.QuadPart = boottime;
-                sti->liKeSystemTime.QuadPart = 0; /* FIXME */
-                sti->liExpTimeZoneBias.QuadPart  = 0; /* FIXME */
-                sti->uCurrentTimeZoneId = 0; /* FIXME */
-                sti->dwReserved = 0;
+                TIME_ZONE_INFORMATION tzi;
+                LARGE_INTEGER sys_time, local_time, local_diff;
+
+                NtQuerySystemTime(&sys_time);
+                RtlSystemTimeToLocalTime(&sys_time, &local_time);
+                /* liExpTimeZoneBias is not the same as tzi.Bias since it takes
+                 * disabled DST correction into account (tested on WinXP). */
+                local_diff.QuadPart = sys_time.QuadPart - local_time.QuadPart;
+
+                sti->liKeBootTime       = NTDLL_BootTime;
+                sti->liKeSystemTime     = sys_time;
+                sti->liExpTimeZoneBias  = local_diff;
+                sti->uCurrentTimeZoneId = RtlQueryTimeZoneInformation(&tzi);
+                sti->dwReserved         = 0;
+                
                 len = sizeof(*sti);
             }
             else ret = STATUS_INFO_LENGTH_MISMATCH;


More information about the wine-patches mailing list