this patch removes the DOSFS_ specific time related conversion routine,
and makes use of the ntdll equivalent.
A+
--
Eric Pouech
diff -u -N -r -x '*~' -x '.#*' -x CVS dlls/ntdll34/time.c dlls/ntdll/time.c
--- dlls/ntdll34/time.c 2003-08-19 18:34:08.000000000 +0200
+++ dlls/ntdll/time.c 2003-08-19 21:26:06.000000000 +0200
@@ -515,6 +515,9 @@
*/
BOOLEAN WINAPI RtlTimeToSecondsSince1970( const LARGE_INTEGER *Time, LPDWORD Seconds )
{
+ /* if needed, there used to be a version of his function without long long support
+ * in files/dos_fs.c
+ */
ULONGLONG tmp = ((ULONGLONG)Time->s.HighPart << 32) | Time->s.LowPart;
tmp = RtlLargeIntegerDivide( tmp, 10000000, NULL );
tmp -= SECS_1601_TO_1970;
@@ -538,6 +541,9 @@
*/
BOOLEAN WINAPI RtlTimeToSecondsSince1980( const LARGE_INTEGER *Time, LPDWORD Seconds )
{
+ /* if needed, there used to be a version of his function without long long support
+ * in files/dos_fs.c
+ */
ULONGLONG tmp = ((ULONGLONG)Time->s.HighPart << 32) | Time->s.LowPart;
tmp = RtlLargeIntegerDivide( tmp, 10000000, NULL );
tmp -= SECS_1601_TO_1980;
diff -u -N -r -x '*~' -x '.#*' -x CVS files34/dos_fs.c files/dos_fs.c
--- files34/dos_fs.c 2003-08-19 18:34:25.000000000 +0200
+++ files/dos_fs.c 2003-08-19 21:25:13.000000000 +0200
@@ -40,6 +40,8 @@
# include <unistd.h>
#endif
+#define NONAMELESSUNION
+#define NONAMELESSSTRUCT
#include "windef.h"
#include "winerror.h"
#include "wingdi.h"
@@ -2239,225 +2241,6 @@
}
/***********************************************************************
- * DOSFS_UnixTimeToFileTime
- *
- * Convert a Unix time to FILETIME format.
- * The FILETIME structure is a 64-bit value representing the number of
- * 100-nanosecond intervals since January 1, 1601, 0:00.
- * 'remainder' is the nonnegative number of 100-ns intervals
- * corresponding to the time fraction smaller than 1 second that
- * couldn't be stored in the time_t value.
- */
-void DOSFS_UnixTimeToFileTime( time_t unix_time, FILETIME *filetime,
- DWORD remainder )
-{
- /* NOTES:
-
- CONSTANTS:
- The time difference between 1 January 1601, 00:00:00 and
- 1 January 1970, 00:00:00 is 369 years, plus the leap years
- from 1604 to 1968, excluding 1700, 1800, 1900.
- This makes (1968 - 1600) / 4 - 3 = 89 leap days, and a total
- of 134774 days.
-
- Any day in that period had 24 * 60 * 60 = 86400 seconds.
-
- The time difference is 134774 * 86400 * 10000000, which can be written
- 116444736000000000
- 27111902 * 2^32 + 3577643008
- 413 * 2^48 + 45534 * 2^32 + 54590 * 2^16 + 32768
-
- If you find that these constants are buggy, please change them in all
- instances in both conversion functions.
-
- VERSIONS:
- There are two versions, one of them uses long long variables and
- is presumably faster but not ISO C. The other one uses standard C
- data types and operations but relies on the assumption that negative
- numbers are stored as 2's complement (-1 is 0xffff....). If this
- assumption is violated, dates before 1970 will not convert correctly.
- This should however work on any reasonable architecture where WINE
- will run.
-
- DETAILS:
-
- Take care not to remove the casts. I have tested these functions
- (in both versions) for a lot of numbers. I would be interested in
- results on other compilers than GCC.
-
- The operations have been designed to account for the possibility
- of 64-bit time_t in future UNICES. Even the versions without
- internal long long numbers will work if time_t only is 64 bit.
- A 32-bit shift, which was necessary for that operation, turned out
- not to work correctly in GCC, besides giving the warning. So I
- used a double 16-bit shift instead. Numbers are in the ISO version
- represented by three limbs, the most significant with 32 bit, the
- other two with 16 bit each.
-
- As the modulo-operator % is not well-defined for negative numbers,
- negative divisors have been avoided in DOSFS_FileTimeToUnixTime.
-
- There might be quicker ways to do this in C. Certainly so in
- assembler.
-
- Claus Fischer, fischer@iue.tuwien.ac.at
- */
-
-#if SIZEOF_LONG_LONG >= 8
-# define USE_LONG_LONG 1
-#else
-# define USE_LONG_LONG 0
-#endif
-
-#if USE_LONG_LONG /* gcc supports long long type */
-
- long long int t = unix_time;
- t *= 10000000;
- t += 116444736000000000LL;
- t += remainder;
- filetime->dwLowDateTime = (UINT)t;
- filetime->dwHighDateTime = (UINT)(t >> 32);
-
-#else /* ISO version */
-
- UINT a0; /* 16 bit, low bits */
- UINT a1; /* 16 bit, medium bits */
- UINT a2; /* 32 bit, high bits */
-
- /* Copy the unix time to a2/a1/a0 */
- a0 = unix_time & 0xffff;
- a1 = (unix_time >> 16) & 0xffff;
- /* This is obsolete if unix_time is only 32 bits, but it does not hurt.
- Do not replace this by >> 32, it gives a compiler warning and it does
- not work. */
- a2 = (unix_time >= 0 ? (unix_time >> 16) >> 16 :
- ~((~unix_time >> 16) >> 16));
-
- /* Multiply a by 10000000 (a = a2/a1/a0)
- Split the factor into 10000 * 1000 which are both less than 0xffff. */
- a0 *= 10000;
- a1 = a1 * 10000 + (a0 >> 16);
- a2 = a2 * 10000 + (a1 >> 16);
- a0 &= 0xffff;
- a1 &= 0xffff;
-
- a0 *= 1000;
- a1 = a1 * 1000 + (a0 >> 16);
- a2 = a2 * 1000 + (a1 >> 16);
- a0 &= 0xffff;
- a1 &= 0xffff;
-
- /* Add the time difference and the remainder */
- a0 += 32768 + (remainder & 0xffff);
- a1 += 54590 + (remainder >> 16 ) + (a0 >> 16);
- a2 += 27111902 + (a1 >> 16);
- a0 &= 0xffff;
- a1 &= 0xffff;
-
- /* Set filetime */
- filetime->dwLowDateTime = (a1 << 16) + a0;
- filetime->dwHighDateTime = a2;
-#endif
-}
-
-
-/***********************************************************************
- * DOSFS_FileTimeToUnixTime
- *
- * Convert a FILETIME format to Unix time.
- * If not NULL, 'remainder' contains the fractional part of the filetime,
- * in the range of [0..9999999] (even if time_t is negative).
- */
-time_t DOSFS_FileTimeToUnixTime( const FILETIME *filetime, DWORD *remainder )
-{
- /* Read the comment in the function DOSFS_UnixTimeToFileTime. */
-#if USE_LONG_LONG
-
- long long int t = filetime->dwHighDateTime;
- t <<= 32;
- t += (UINT)filetime->dwLowDateTime;
- t -= 116444736000000000LL;
- if (t < 0)
- {
- if (remainder) *remainder = 9999999 - (-t - 1) % 10000000;
- return -1 - ((-t - 1) / 10000000);
- }
- else
- {
- if (remainder) *remainder = t % 10000000;
- return t / 10000000;
- }
-
-#else /* ISO version */
-
- UINT a0; /* 16 bit, low bits */
- UINT a1; /* 16 bit, medium bits */
- UINT a2; /* 32 bit, high bits */
- UINT r; /* remainder of division */
- unsigned int carry; /* carry bit for subtraction */
- int negative; /* whether a represents a negative value */
-
- /* Copy the time values to a2/a1/a0 */
- a2 = (UINT)filetime->dwHighDateTime;
- a1 = ((UINT)filetime->dwLowDateTime ) >> 16;
- a0 = ((UINT)filetime->dwLowDateTime ) & 0xffff;
-
- /* Subtract the time difference */
- if (a0 >= 32768 ) a0 -= 32768 , carry = 0;
- else a0 += (1 << 16) - 32768 , carry = 1;
-
- if (a1 >= 54590 + carry) a1 -= 54590 + carry, carry = 0;
- else a1 += (1 << 16) - 54590 - carry, carry = 1;
-
- a2 -= 27111902 + carry;
-
- /* If a is negative, replace a by (-1-a) */
- negative = (a2 >= ((UINT)1) << 31);
- if (negative)
- {
- /* Set a to -a - 1 (a is a2/a1/a0) */
- a0 = 0xffff - a0;
- a1 = 0xffff - a1;
- a2 = ~a2;
- }
-
- /* Divide a by 10000000 (a = a2/a1/a0), put the rest into r.
- Split the divisor into 10000 * 1000 which are both less than 0xffff. */
- a1 += (a2 % 10000) << 16;
- a2 /= 10000;
- a0 += (a1 % 10000) << 16;
- a1 /= 10000;
- r = a0 % 10000;
- a0 /= 10000;
-
- a1 += (a2 % 1000) << 16;
- a2 /= 1000;
- a0 += (a1 % 1000) << 16;
- a1 /= 1000;
- r += (a0 % 1000) * 10000;
- a0 /= 1000;
-
- /* If a was negative, replace a by (-1-a) and r by (9999999 - r) */
- if (negative)
- {
- /* Set a to -a - 1 (a is a2/a1/a0) */
- a0 = 0xffff - a0;
- a1 = 0xffff - a1;
- a2 = ~a2;
-
- r = 9999999 - r;
- }
-
- if (remainder) *remainder = r;
-
- /* Do not replace this by << 32, it gives a compiler warning and it does
- not work. */
- return ((((time_t)a2) << 16) << 16) + (a1 << 16) + a0;
-#endif
-}
-
-
-/***********************************************************************
* MulDiv (KERNEL32.@)
* RETURNS
* Result of multiplication and division
@@ -2545,8 +2328,16 @@
BOOL WINAPI FileTimeToDosDateTime( const FILETIME *ft, LPWORD fatdate,
LPWORD fattime )
{
- time_t unixtime = DOSFS_FileTimeToUnixTime( ft, NULL );
- struct tm *tm = gmtime( &unixtime );
+ LARGE_INTEGER li;
+ ULONG t;
+ time_t unixtime;
+ struct tm* tm;
+
+ li.s.LowPart = ft->dwLowDateTime;
+ li.s.HighPart = ft->dwHighDateTime;
+ RtlTimeToSecondsSince1970( &li, &t );
+ unixtime = t;
+ tm = gmtime( &unixtime );
if (fattime)
*fattime = (tm->tm_hour << 11) + (tm->tm_min << 5) + (tm->tm_sec / 2);
if (fatdate)
diff -u -N -r -x '*~' -x '.#*' -x CVS include34/file.h include/file.h
--- include34/file.h 2003-08-19 18:34:27.000000000 +0200
+++ include/file.h 2003-08-19 21:25:14.000000000 +0200
@@ -94,9 +94,6 @@
DOS_FULL_NAME *full_name, BOOL win32 );
/* files/dos_fs.c */
-extern void DOSFS_UnixTimeToFileTime( time_t unixtime, LPFILETIME ft,
- DWORD remainder );
-extern time_t DOSFS_FileTimeToUnixTime( const FILETIME *ft, DWORD *remainder );
extern BOOL DOSFS_ToDosFCBFormat( LPCWSTR name, LPWSTR buffer );
extern const DOS_DEVICE *DOSFS_GetDevice( LPCWSTR name );
extern const DOS_DEVICE *DOSFS_GetDeviceByHandle( HANDLE hFile );