Fixed some ANSI C violations.
[wine] / dlls / ntdll / time.c
1 /*
2  * Conversion between Time and TimeFields
3  *
4  * RtlTimeToTimeFields, RtlTimeFieldsToTime and defines are taken from ReactOS and 
5  * adapted to wine with special permissions of the author  
6  * Rex Jolliff (rex@lvcablemodem.com)
7  * 
8  * 
9  */
10
11 #include <string.h>
12 #include "ntddk.h"
13 #include "debugtools.h"
14 #include "file.h"
15
16 DEFAULT_DEBUG_CHANNEL(ntdll)
17
18 #define TICKSPERSEC        10000000
19 #define TICKSPERMSEC       10000
20 #define SECSPERDAY         86400
21 #define SECSPERHOUR        3600
22 #define SECSPERMIN         60
23 #define MINSPERHOUR        60
24 #define HOURSPERDAY        24
25 #define EPOCHWEEKDAY       0
26 #define DAYSPERWEEK        7
27 #define EPOCHYEAR          1601
28 #define DAYSPERNORMALYEAR  365
29 #define DAYSPERLEAPYEAR    366
30 #define MONSPERYEAR        12
31
32 static const int YearLengths[2] = {DAYSPERNORMALYEAR, DAYSPERLEAPYEAR};
33 static const int MonthLengths[2][MONSPERYEAR] =
34 {
35         { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
36         { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
37 };
38
39 static inline int IsLeapYear(int Year)
40 {
41         return Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0) ? 1 : 0;
42 }
43
44 static inline void NormalizeTimeFields(CSHORT *FieldToNormalize, CSHORT *CarryField,int Modulus)
45 {
46         *FieldToNormalize = (CSHORT) (*FieldToNormalize - Modulus);
47         *CarryField = (CSHORT) (*CarryField + 1);
48 }
49
50 /******************************************************************************
51  *  RtlTimeToTimeFields         [NTDLL.265] 
52  *
53  */
54
55 VOID WINAPI RtlTimeToTimeFields(
56         PLARGE_INTEGER liTime,
57         PTIME_FIELDS TimeFields)
58 {
59         const int *Months;
60         int LeapSecondCorrections, SecondsInDay, CurYear;
61         int LeapYear, CurMonth, GMTOffset;
62         long int Days;
63         long long int Time = *(long long int *)&liTime;
64
65         /* Extract millisecond from time and convert time into seconds */
66         TimeFields->Milliseconds = (CSHORT) ((Time % TICKSPERSEC) / TICKSPERMSEC);
67         Time = Time / TICKSPERSEC;
68
69         /* FIXME: Compute the number of leap second corrections here */
70         LeapSecondCorrections = 0;
71
72         /* FIXME: get the GMT offset here */
73         GMTOffset = 0;
74
75         /* Split the time into days and seconds within the day */
76         Days = Time / SECSPERDAY;
77         SecondsInDay = Time % SECSPERDAY;
78
79         /* Adjust the values for GMT and leap seconds */
80         SecondsInDay += (GMTOffset - LeapSecondCorrections);
81         while (SecondsInDay < 0) 
82         { SecondsInDay += SECSPERDAY;
83           Days--;
84         }
85         while (SecondsInDay >= SECSPERDAY) 
86         { SecondsInDay -= SECSPERDAY;
87           Days++;
88         }
89
90         /* compute time of day */
91         TimeFields->Hour = (CSHORT) (SecondsInDay / SECSPERHOUR);
92         SecondsInDay = SecondsInDay % SECSPERHOUR;
93         TimeFields->Minute = (CSHORT) (SecondsInDay / SECSPERMIN);
94         TimeFields->Second = (CSHORT) (SecondsInDay % SECSPERMIN);
95
96         /* FIXME: handle the possibility that we are on a leap second (i.e. Second = 60) */
97
98         /* compute day of week */
99         TimeFields->Weekday = (CSHORT) ((EPOCHWEEKDAY + Days) % DAYSPERWEEK);
100
101         /* compute year */
102         CurYear = EPOCHYEAR;
103         /* FIXME: handle calendar modifications */
104         while (1)
105         { LeapYear = IsLeapYear(CurYear);
106           if (Days < (long) YearLengths[LeapYear])
107           { break;
108           }
109           CurYear++;
110           Days = Days - (long) YearLengths[LeapYear];
111         }
112         TimeFields->Year = (CSHORT) CurYear;
113
114         /* Compute month of year */
115         Months = MonthLengths[LeapYear];
116         for (CurMonth = 0; Days >= (long) Months[CurMonth]; CurMonth++)
117           Days = Days - (long) Months[CurMonth];
118         TimeFields->Month = (CSHORT) (CurMonth + 1);
119         TimeFields->Day = (CSHORT) (Days + 1);
120 }
121 /******************************************************************************
122  *  RtlTimeFieldsToTime         [NTDLL.265] 
123  *
124  */
125 BOOLEAN WINAPI RtlTimeFieldsToTime(
126         PTIME_FIELDS tfTimeFields,
127         PLARGE_INTEGER Time)
128 {
129         int CurYear, CurMonth;
130         long long int rcTime;
131         TIME_FIELDS TimeFields = *tfTimeFields;
132
133         rcTime = 0;
134
135         /* FIXME: normalize the TIME_FIELDS structure here */
136         while (TimeFields.Second >= SECSPERMIN)
137         { NormalizeTimeFields(&TimeFields.Second, &TimeFields.Minute, SECSPERMIN);
138         }
139         while (TimeFields.Minute >= MINSPERHOUR)
140         { NormalizeTimeFields(&TimeFields.Minute, &TimeFields.Hour, MINSPERHOUR);
141         }
142         while (TimeFields.Hour >= HOURSPERDAY)
143         { NormalizeTimeFields(&TimeFields.Hour, &TimeFields.Day, HOURSPERDAY);
144         }
145         while (TimeFields.Day > MonthLengths[IsLeapYear(TimeFields.Year)][TimeFields.Month - 1])
146         { NormalizeTimeFields(&TimeFields.Day, &TimeFields.Month, SECSPERMIN);
147         }
148         while (TimeFields.Month > MONSPERYEAR)
149         { NormalizeTimeFields(&TimeFields.Month, &TimeFields.Year, MONSPERYEAR);
150         }
151
152         /* FIXME: handle calendar corrections here */
153         for (CurYear = EPOCHYEAR; CurYear < TimeFields.Year; CurYear++)
154         { rcTime += YearLengths[IsLeapYear(CurYear)];
155         }
156         for (CurMonth = 1; CurMonth < TimeFields.Month; CurMonth++)
157         { rcTime += MonthLengths[IsLeapYear(CurYear)][CurMonth - 1];
158         }
159         rcTime += TimeFields.Day - 1;
160         rcTime *= SECSPERDAY;
161         rcTime += TimeFields.Hour * SECSPERHOUR + TimeFields.Minute * SECSPERMIN + TimeFields.Second;
162         rcTime *= TICKSPERSEC;
163         rcTime += TimeFields.Milliseconds * TICKSPERMSEC;
164         *Time = *(LARGE_INTEGER *)&rcTime;
165
166         return TRUE;
167 }
168 /************* end of code by Rex Jolliff (rex@lvcablemodem.com) *******************/
169
170 /******************************************************************************
171  *  RtlSystemTimeToLocalTime    [NTDLL] 
172  */
173 VOID WINAPI RtlSystemTimeToLocalTime(
174         IN  PLARGE_INTEGER SystemTime,
175         OUT PLARGE_INTEGER LocalTime)
176 {
177         FIXME("(%p, %p),stub!\n",SystemTime,LocalTime);
178
179         memcpy (LocalTime, SystemTime, sizeof (PLARGE_INTEGER));
180 }
181 /******************************************************************************
182  *  RtlTimeToSecondsSince1980           [NTDLL] 
183  */
184 BOOLEAN WINAPI RtlTimeToSecondsSince1980(
185         LPFILETIME ft,
186         LPDWORD timeret) 
187 {
188         /* 1980 = 1970+10*365 days +  29. februar 1972 + 29.februar 1976 */
189         *timeret = DOSFS_FileTimeToUnixTime(ft,NULL) - (10*365+2)*24*3600;
190         return 1;
191 }
192
193 /******************************************************************************
194  *  RtlTimeToSecondsSince1970           [NTDLL] 
195  */
196 BOOLEAN WINAPI RtlTimeToSecondsSince1970(
197         LPFILETIME ft,
198         LPDWORD timeret) 
199 {
200         *timeret = DOSFS_FileTimeToUnixTime(ft,NULL);
201         return 1;
202 }
203
204 /******************************************************************************
205  * RtlTimeToElapsedTimeFields [NTDLL.502]
206  * FIXME: prototype guessed
207  */
208 VOID WINAPI RtlTimeToElapsedTimeFields(
209         PLARGE_INTEGER liTime,
210         PTIME_FIELDS TimeFields)
211 {
212         FIXME("(%p,%p): stub\n",liTime,TimeFields);
213 }