Implemented a bunch of large integer functions in ntdll.

diff --git a/dlls/ntdll/Makefile.in b/dlls/ntdll/Makefile.in
index e5e2481..e240706 100644
--- a/dlls/ntdll/Makefile.in
+++ b/dlls/ntdll/Makefile.in
@@ -12,6 +12,7 @@
 	exception.c \
 	error.c \
 	file.c \
+	large_int.c \
 	misc.c \
 	nt.c \
 	om.c \
diff --git a/dlls/ntdll/large_int.c b/dlls/ntdll/large_int.c
new file mode 100644
index 0000000..da32b39
--- /dev/null
+++ b/dlls/ntdll/large_int.c
@@ -0,0 +1,182 @@
+/*
+ * Large integer functions
+ *
+ * Copyright 2000 Alexandre Julliard
+ */
+
+#include "winnt.h"
+#include "ntddk.h"
+
+/*
+ * Note: we use LONGLONG instead of LARGE_INTEGER, because
+ * the latter is a structure and the calling convention for
+ * returning a structure would not be binary-compatible.
+ *
+ * FIXME: for platforms that don't have a native LONGLONG type,
+ * we should define LONGLONG as a structure similar to LARGE_INTEGER
+ * and do everything by hand. You are welcome to do it...
+ */
+
+/******************************************************************************
+ *        RtlLargeIntegerAdd   (NTDLL.@)
+ */
+LONGLONG WINAPI RtlLargeIntegerAdd( LONGLONG a, LONGLONG b )
+{
+    return a + b;
+}
+
+
+/******************************************************************************
+ *        RtlLargeIntegerSubtract   (NTDLL.@)
+ */
+LONGLONG WINAPI RtlLargeIntegerSubtract( LONGLONG a, LONGLONG b )
+{
+    return a - b;
+}
+
+
+/******************************************************************************
+ *        RtlLargeIntegerNegate   (NTDLL.@)
+ */
+LONGLONG WINAPI RtlLargeIntegerNegate( LONGLONG a )
+{
+    return -a;
+}
+
+
+/******************************************************************************
+ *        RtlLargeIntegerShiftLeft   (NTDLL.@)
+ */
+LONGLONG WINAPI RtlLargeIntegerShiftLeft( LONGLONG a, INT count )
+{
+    return a << count;
+}
+
+
+/******************************************************************************
+ *        RtlLargeIntegerShiftRight   (NTDLL.@)
+ */
+LONGLONG WINAPI RtlLargeIntegerShiftRight( LONGLONG a, INT count )
+{
+    return (ULONGLONG)a >> count;
+}
+
+
+/******************************************************************************
+ *        RtlLargeIntegerArithmeticShift   (NTDLL.@)
+ */
+LONGLONG WINAPI RtlLargeIntegerArithmeticShift( LONGLONG a, INT count )
+{
+    /* FIXME: gcc does arithmetic shift here, but it may not be true on all platforms */
+    return a >> count;
+}
+
+
+/******************************************************************************
+ *        RtlLargeIntegerDivide   (NTDLL.@)
+ *
+ * FIXME: should it be signed division instead?
+ */
+ULONGLONG WINAPI RtlLargeIntegerDivide( ULONGLONG a, ULONGLONG b, ULONGLONG *rem )
+{
+    ULONGLONG ret = a / b;
+    if (rem) *rem = a - ret * b;
+    return ret;
+}
+
+
+/******************************************************************************
+ *        RtlConvertLongToLargeInteger   (NTDLL.@)
+ */
+LONGLONG WINAPI RtlConvertLongToLargeInteger( LONG a )
+{
+    return a;
+}
+
+
+/******************************************************************************
+ *        RtlConvertUlongToLargeInteger   (NTDLL.@)
+ */
+ULONGLONG WINAPI RtlConvertUlongToLargeInteger( ULONG a )
+{
+    return a;
+}
+
+
+/******************************************************************************
+ *        RtlEnlargedIntegerMultiply   (NTDLL.@)
+ */
+LONGLONG WINAPI RtlEnlargedIntegerMultiply( INT a, INT b )
+{
+    return (LONGLONG)a * b;
+}
+
+
+/******************************************************************************
+ *        RtlEnlargedUnsignedMultiply   (NTDLL.@)
+ */
+LONGLONG WINAPI RtlEnlargedUnsignedMultiply( UINT a, UINT b )
+{
+    return (ULONGLONG)a * b;
+}
+
+
+/******************************************************************************
+ *        RtlEnlargedUnsignedDivide   (NTDLL.@)
+ */
+UINT WINAPI RtlEnlargedUnsignedDivide( ULONGLONG a, UINT b, UINT *remptr )
+{
+#if defined(__i386__) && defined(__GNUC__)
+    UINT ret, rem;
+    __asm__("div %4,%%eax"
+            : "=a" (ret), "=d" (rem)
+            : "0" (*(UINT*)&a), "1" (*((UINT*)&a+1)), "g" (b) );
+    if (remptr) *remptr = rem;
+    return ret;
+#else
+    UINT ret = a / b;
+    if (remptr) *remptr = a % b;
+    return ret;
+#endif
+}
+
+
+/******************************************************************************
+ *        RtlExtendedLargeIntegerDivide   (NTDLL.@)
+ */
+LONGLONG WINAPI RtlExtendedLargeIntegerDivide( LONGLONG a, INT b, INT *rem )
+{
+    LONGLONG ret = a / b;
+    if (rem) *rem = a - b * ret;
+    return ret;
+}
+
+
+/******************************************************************************
+ *        RtlExtendedIntegerMultiply   (NTDLL.@)
+ */
+LONGLONG WINAPI RtlExtendedIntegerMultiply( LONGLONG a, INT b )
+{
+    return a * b;
+}
+
+
+/******************************************************************************
+ *        RtlExtendedMagicDivide   (NTDLL.@)
+ *
+ * This function computes (a * b) >> (64 + shift)
+ *
+ * This allows replacing a division by a longlong constant
+ * by a multiplication by the inverse constant.
+ *
+ * If 'c' is the constant divisor, the constants 'b' and 'shift'
+ * must be chosen such that b = 2^(64+shift) / c.
+ * Then we have RtlExtendedMagicDivide(a,b,shift) == a * b / 2^(64+shift) == a / c.
+ *
+ * I'm too lazy to implement it right now...
+ */
+/* LONGLONG WINAPI RtlExtendedMagicDivide( LONGLONG a, LONGLONG b, INT shift )
+ * {
+ *     return 0;
+ * }
+ */
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec
index 53dcdeb..9928476 100644
--- a/dlls/ntdll/ntdll.spec
+++ b/dlls/ntdll/ntdll.spec
@@ -174,7 +174,7 @@
 @ stdcall NtQuerySymbolicLinkObject(long ptr ptr) NtQuerySymbolicLinkObject
 @ stub NtQuerySystemEnvironmentValue
 @ stdcall NtQuerySystemInformation(long long long long) NtQuerySystemInformation
-@ stdcall NtQuerySystemTime(ptr) GetSystemTimeAsFileTime
+@ stdcall NtQuerySystemTime(ptr) NtQuerySystemTime
 @ stub NtQueryTimer
 @ stdcall NtQueryTimerResolution(long long long) NtQueryTimerResolution
 @ stdcall NtQueryValueKey(long long long long long long) NtQueryValueKey
@@ -298,11 +298,11 @@
 @ stub RtlCompressBuffer
 @ stub RtlConsoleMultiByteToUnicodeN
 @ stub RtlConvertExclusiveToShared
-@ stub RtlConvertLongToLargeInteger
+@ stdcall64 RtlConvertLongToLargeInteger(long) RtlConvertLongToLargeInteger
 @ stub RtlConvertSharedToExclusive
 @ stdcall RtlConvertSidToUnicodeString(ptr ptr)RtlConvertSidToUnicodeString
 @ stub RtlConvertUiListToApiList
-@ stub RtlConvertUlongToLargeInteger
+@ stdcall64 RtlConvertUlongToLargeInteger(long) RtlConvertUlongToLargeInteger
 @ stub RtlCopyLuid
 @ stub RtlCopyLuidAndAttributesArray
 @ stub RtlCopySecurityDescriptor
@@ -345,9 +345,9 @@
 @ stdcall RtlDosPathNameToNtPathName_U(ptr ptr long long) RtlDosPathNameToNtPathName_U
 @ stub RtlDosSearchPath_U
 @ stdcall RtlDumpResource(ptr) RtlDumpResource
-@ stub RtlEnlargedIntegerMultiply
-@ stub RtlEnlargedUnsignedDivide
-@ stub RtlEnlargedUnsignedMultiply
+@ stdcall64 RtlEnlargedIntegerMultiply(long long) RtlEnlargedIntegerMultiply
+@ stdcall RtlEnlargedUnsignedDivide(long long long ptr) RtlEnlargedUnsignedDivide
+@ stdcall64 RtlEnlargedUnsignedMultiply(long long) RtlEnlargedUnsignedMultiply
 @ stdcall RtlEnterCriticalSection(ptr) RtlEnterCriticalSection
 @ stub RtlEnumProcessHeaps
 @ stub RtlEnumerateGenericTable
@@ -362,8 +362,8 @@
 @ stdcall RtlEraseUnicodeString(ptr) RtlEraseUnicodeString
 @ stub RtlExpandEnvironmentStrings_U
 @ stub RtlExtendHeap
-@ stdcall RtlExtendedIntegerMultiply(long long long) RtlExtendedIntegerMultiply
-@ stdcall RtlExtendedLargeIntegerDivide(long long long ptr) RtlExtendedLargeIntegerDivide
+@ stdcall64 RtlExtendedIntegerMultiply(long long long) RtlExtendedIntegerMultiply
+@ stdcall64 RtlExtendedLargeIntegerDivide(long long long ptr) RtlExtendedLargeIntegerDivide
 @ stub RtlExtendedMagicDivide
 @ stdcall RtlFillMemory(ptr long long) RtlFillMemory
 @ stub RtlFillMemoryUlong
@@ -422,13 +422,13 @@
 @ stub RtlIsGenericTableEmpty
 @ stub RtlIsNameLegalDOS8Dot3
 @ stdcall RtlIsTextUnicode(ptr long ptr) RtlIsTextUnicode
-@ stub RtlLargeIntegerAdd
-@ stub RtlLargeIntegerArithmeticShift
-@ stub RtlLargeIntegerDivide
-@ stub RtlLargeIntegerNegate
-@ stub RtlLargeIntegerShiftLeft
-@ stub RtlLargeIntegerShiftRight
-@ stub RtlLargeIntegerSubtract
+@ stdcall64 RtlLargeIntegerAdd(long long long long) RtlLargeIntegerAdd
+@ stdcall64 RtlLargeIntegerArithmeticShift(long long long) RtlLargeIntegerArithmeticShift
+@ stdcall64 RtlLargeIntegerDivide(long long long long ptr) RtlLargeIntegerDivide
+@ stdcall64 RtlLargeIntegerNegate(long long) RtlLargeIntegerNegate
+@ stdcall64 RtlLargeIntegerShiftLeft(long long long) RtlLargeIntegerShiftLeft
+@ stdcall64 RtlLargeIntegerShiftRight(long long long) RtlLargeIntegerShiftRight
+@ stdcall64 RtlLargeIntegerSubtract(long long long long) RtlLargeIntegerSubtract
 @ stub RtlLargeIntegerToChar
 @ stdcall RtlLeaveCriticalSection(ptr) RtlLeaveCriticalSection
 @ stdcall RtlLengthRequiredSid(long) RtlLengthRequiredSid
@@ -674,7 +674,7 @@
 @ stub ZwQuerySymbolicLinkObject
 @ stub ZwQuerySystemEnvironmentValue
 @ stdcall ZwQuerySystemInformation(long long long long) NtQuerySystemInformation
-@ stdcall ZwQuerySystemTime(ptr) GetSystemTimeAsFileTime
+@ stdcall ZwQuerySystemTime(ptr) NtQuerySystemTime
 @ stub ZwQueryTimer
 @ stub ZwQueryTimerResolution
 @ stub ZwQueryValueKey
diff --git a/dlls/ntdll/rtl.c b/dlls/ntdll/rtl.c
index 3097148..bd8e45d 100644
--- a/dlls/ntdll/rtl.c
+++ b/dlls/ntdll/rtl.c
@@ -370,49 +370,6 @@
     context->Esp -= context->Eax;
 }
 
-/******************************************************************************
- * RtlExtendedLargeIntegerDivide [NTDLL.359]
- */
-INT WINAPI RtlExtendedLargeIntegerDivide(
-	LARGE_INTEGER dividend,
-	DWORD divisor,
-	LPDWORD rest
-) {
-#if SIZEOF_LONG_LONG==8
-	long long x1 = *(long long*)&dividend;
-
-	if (*rest)
-		*rest = x1 % divisor;
-	return x1/divisor;
-#else
-	FIXME("((%ld<<32)+%ld,%ld,%p), implement this using normal integer arithmetic!\n",
-              dividend.s.HighPart,dividend.s.LowPart,divisor,rest);
-	return 0;
-#endif
-}
-
-/******************************************************************************
- * RtlExtendedIntegerMultiply [NTDLL.359]
- * Note: This even works, since gcc returns 64bit values in eax/edx just like
- * the caller expects. However... The relay code won't grok this I think.
- */
-LARGE_INTEGER WINAPI RtlExtendedIntegerMultiply(
-	LARGE_INTEGER factor1,
-	INT factor2) 
-{
-#if SIZEOF_LONG_LONG==8
-        long long result = (*(long long*)&factor1) * factor2;
-	return (*(LARGE_INTEGER*)&result);
-#else
-	LARGE_INTEGER result;
-	result.s.HighPart = 0;
-        result.s.LowPart = 0;
-        FIXME("((%ld<<32)+%ld,%d), implement this using normal integer arithmetic!\n",
-              factor1.s.HighPart,factor1.s.LowPart,factor2);
-	return result;
-#endif
-}
-
 /**************************************************************************
  *                 RtlDosPathNameToNtPathName_U		[NTDLL.338]
  *
diff --git a/dlls/ntdll/time.c b/dlls/ntdll/time.c
index c9f717e..1f7ad4e 100644
--- a/dlls/ntdll/time.c
+++ b/dlls/ntdll/time.c
@@ -9,11 +9,13 @@
  */
 
 #include <string.h>
+#include <time.h>
+#include <sys/time.h>
+#include <unistd.h>
 #include "ntddk.h"
 #include "debugtools.h"
-#include "file.h"
 
-DEFAULT_DEBUG_CHANNEL(ntdll)
+DEFAULT_DEBUG_CHANNEL(ntdll);
 
 #define TICKSPERSEC        10000000
 #define TICKSPERMSEC       10000
@@ -29,6 +31,12 @@
 #define DAYSPERLEAPYEAR    366
 #define MONSPERYEAR        12
 
+/* 1601 to 1970 is 369 years plus 89 leap days */
+#define SECS_1601_TO_1970  ((369 * 365 + 89) * 86400ULL)
+/* 1601 to 1980 is 379 years plus 91 leap days */
+#define SECS_1601_to_1980  ((379 * 365 + 91) * 86400ULL)
+
+
 static const int YearLengths[2] = {DAYSPERNORMALYEAR, DAYSPERLEAPYEAR};
 static const int MonthLengths[2][MONSPERYEAR] =
 {
@@ -182,41 +190,43 @@
 /******************************************************************************
  *  RtlTimeToSecondsSince1970		[NTDLL] 
  */
-BOOLEAN WINAPI RtlTimeToSecondsSince1970(
-	LPFILETIME ft,
-	LPDWORD timeret) 
+BOOLEAN WINAPI RtlTimeToSecondsSince1970( const FILETIME *time, LPDWORD res )
 {
-    *timeret = DOSFS_FileTimeToUnixTime(ft,NULL);
+    ULONGLONG tmp = RtlLargeIntegerDivide( ((LARGE_INTEGER *)time)->QuadPart, 10000000LL, NULL );
+    tmp -= SECS_1601_TO_1970;
+    if (tmp > 0xffffffff) return FALSE;
+    *res = (DWORD)tmp;
     return TRUE;
 }
 
 /******************************************************************************
  *  RtlTimeToSecondsSince1980		[NTDLL] 
  */
-BOOLEAN WINAPI RtlTimeToSecondsSince1980(
-	LPFILETIME ft,
-	LPDWORD timeret) 
+BOOLEAN WINAPI RtlTimeToSecondsSince1980( const FILETIME *time, LPDWORD res )
 {
-    /* 1980 = 1970+10*365 days +  29. februar 1972 + 29.februar 1976 */
-    if (!RtlTimeToSecondsSince1970( ft, timeret )) return FALSE;
-    *timeret -= (10*365+2)*24*60*60;
+    ULONGLONG tmp = RtlLargeIntegerDivide( ((LARGE_INTEGER *)time)->QuadPart, 10000000LL, NULL );
+    tmp -= SECS_1601_to_1980;
+    if (tmp > 0xffffffff) return FALSE;
+    *res = (DWORD)tmp;
     return TRUE;
 }
 
 /******************************************************************************
  *  RtlSecondsSince1970ToTime		[NTDLL] 
  */
-void WINAPI RtlSecondsSince1970ToTime( DWORD time, LPFILETIME ft )
+void WINAPI RtlSecondsSince1970ToTime( DWORD time, FILETIME *res )
 {
-    DOSFS_UnixTimeToFileTime( time, ft, 0 );
+    LONGLONG secs = time + SECS_1601_TO_1970;
+    ((LARGE_INTEGER *)res)->QuadPart = RtlExtendedIntegerMultiply( secs, 10000000 );
 }
 
 /******************************************************************************
  *  RtlSecondsSince1980ToTime		[NTDLL] 
  */
-void WINAPI RtlSecondsSince1980ToTime( DWORD time, LPFILETIME ft )
+void WINAPI RtlSecondsSince1980ToTime( DWORD time, FILETIME *res )
 {
-    RtlSecondsSince1970ToTime( time + (10*365+2)*24*60*60, ft );
+    LONGLONG secs = time + SECS_1601_to_1980;
+    ((LARGE_INTEGER *)res)->QuadPart = RtlExtendedIntegerMultiply( secs, 10000000 );
 }
 
 /******************************************************************************
@@ -229,3 +239,16 @@
 {
 	FIXME("(%p,%p): stub\n",liTime,TimeFields);
 }
+
+/***********************************************************************
+ *      NtQuerySystemTime   (NTDLL.@)
+ */
+void WINAPI NtQuerySystemTime( LARGE_INTEGER *time )
+{
+    LONGLONG secs;
+    struct timeval now;
+
+    gettimeofday( &now, 0 );
+    secs = now.tv_sec + SECS_1601_TO_1970;
+    time->QuadPart = RtlExtendedIntegerMultiply( secs, 10000000 ) + now.tv_usec * 10;
+}