more-rx-updates-20060504
[openafs.git] / src / WINNT / afsclass / internal.cpp
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 #include <winsock2.h>
11 #include <ws2tcpip.h>
12
13 extern "C" {
14 #include <afs/param.h>
15 #include <afs/stds.h>
16 }
17
18 #include <WINNT/afsclass.h>
19 #include "internal.h"
20
21 #define LOCAL_CRITSEC_COUNT
22
23
24 /*
25  * VARIABLES __________________________________________________________________
26  *
27  */
28
29 #ifdef LOCAL_CRITSEC_COUNT
30 size_t cs_EnterCount = 0;
31 DWORD cs_ThreadID = 0;
32 #endif
33
34 size_t cRefreshAllReq = 0;
35
36 CRITICAL_SECTION *pcs = NULL;
37 BOOL fLongServerNames = FALSE;
38
39 DWORD dwWant = 0;
40
41 static LPTSTR apszDays[] = {
42    TEXT("sun"), TEXT("mon"), TEXT("tue"),
43    TEXT("wed"), TEXT("thu"), TEXT("fri"), TEXT("sat")
44 };
45
46
47 /*
48  * PROTOTYPES _________________________________________________________________
49  *
50  */
51
52
53 /*
54  * ROUTINES ___________________________________________________________________
55  *
56  */
57
58 void AfsClass_InitCriticalSection (void)
59 {
60    if (pcs == NULL)
61       {
62       pcs = New (CRITICAL_SECTION);
63       InitializeCriticalSection (pcs);
64
65 #ifdef LOCAL_CRITSEC_COUNT
66       cs_EnterCount = 0;
67       cs_ThreadID = 0;
68 #endif
69       }
70 }
71
72 LPCRITICAL_SECTION AfsClass_GetCriticalSection (void)
73 {
74    AfsClass_InitCriticalSection();
75    return pcs;
76 }
77
78 void AfsClass_Enter (void)
79 {
80    AfsClass_InitCriticalSection();
81    EnterCriticalSection (pcs);
82
83 #ifdef LOCAL_CRITSEC_COUNT
84    cs_EnterCount++;
85    cs_ThreadID = GetCurrentThreadId();
86 #endif
87 }
88
89 void AfsClass_Leave (void)
90 {
91 #ifdef LOCAL_CRITSEC_COUNT
92    if (!ASSERT( cs_EnterCount > 0 ))
93       return;
94    if (!ASSERT( cs_ThreadID == GetCurrentThreadId() ))
95       return;
96    cs_EnterCount--;
97 #else
98    if (!ASSERT( pcs->RecursionCount > 0 ))
99       return;
100    if (!ASSERT( pcs->OwningThread == (PVOID)GetCurrentThreadId() ))
101       return;
102 #endif
103    LeaveCriticalSection (pcs);
104 }
105
106 int AfsClass_GetEnterCount (void)
107 {
108 #ifdef LOCAL_CRITSEC_COUNT
109    return (int)cs_EnterCount;
110 #else
111    return pcs->RecursionCount;
112 #endif
113 }
114
115 void AfsClass_UnixTimeToSystemTime (LPSYSTEMTIME pst, ULONG ut, BOOL fElapsed)
116 {
117    if (!ut)
118       {
119       memset (pst, 0x00, sizeof(SYSTEMTIME));
120       return;
121       }
122
123    // A Unix time is the number of seconds since 1/1/1970.
124    // The first step in this conversion is to change that count-of-seconds
125    // into a count-of-100ns-intervals...
126    //
127    LARGE_INTEGER ldw;
128    ldw.QuadPart = (LONGLONG)10000000 * (LONGLONG)ut;
129
130    // Then adjust the count to be a count-of-100ns-intervals since
131    // 1/1/1601, instead of 1/1/1970. That means adding a *big* number...
132    //
133    ldw.QuadPart += (LONGLONG)0x019DB1DED53E8000;
134
135    // Now the count is effectively a FILETIME, which we can convert
136    // to a SYSTEMTIME with a Win32 API.
137    //
138    FILETIME ft;
139    ft.dwHighDateTime = (DWORD)ldw.HighPart;
140    ft.dwLowDateTime = (DWORD)ldw.LowPart;
141    FileTimeToSystemTime (&ft, pst);
142
143    if (fElapsed)
144       {
145       pst->wYear -= 1970;
146       pst->wMonth -= 1;
147       pst->wDayOfWeek -= 1;
148       pst->wDay -= 1;
149       }
150 }
151
152
153 ULONG AfsClass_SystemTimeToUnixTime (LPSYSTEMTIME pst)
154 {
155    SYSTEMTIME st;
156    if (pst == NULL)
157       GetSystemTime (&st);
158    else
159       st = *pst;
160
161    if (st.wYear == 1970)
162       return 0;
163
164    FILETIME ft;
165    if (!SystemTimeToFileTime (&st, &ft))
166       return 0;
167
168    LARGE_INTEGER now;
169    now.HighPart = (LONG)ft.dwHighDateTime;
170    now.LowPart = (ULONG)ft.dwLowDateTime;
171
172    LARGE_INTEGER offset;
173    offset.HighPart = 0x019db1de;
174    offset.LowPart = 0xd53e8000;
175
176    LARGE_INTEGER result;
177    result.QuadPart = (now.QuadPart - offset.QuadPart) / 10000000;
178    return (ULONG)result.LowPart;
179 }
180
181
182 void AfsClass_ElapsedTimeToSeconds (ULONG *pcSeconds, LPSYSTEMTIME pet)
183 {
184    *pcSeconds = 0;
185    if (pet)
186       {
187       *pcSeconds += pet->wSecond;
188       *pcSeconds += pet->wMinute * 60L;
189       *pcSeconds += pet->wHour   * 60L * 60L;
190       *pcSeconds += pet->wDay    * 60L * 60L * 24L;
191       }
192 }
193
194
195 double AfsClass_FileTimeToDouble (FILETIME *pft)
196 {
197    double rc;
198    rc = (double)pft->dwHighDateTime * (double)0x100000000;
199    rc += (double)pft->dwLowDateTime;
200    return rc;
201 }
202
203
204 void AfsClass_RequestLongServerNames (BOOL fLong)
205 {
206    fLongServerNames = fLong;
207 }
208
209
210 void AfsClass_ParseRecurringTime (BOOL *pfEver, LPSYSTEMTIME pst, LPTSTR pszTime)
211 {
212    *pfEver = FALSE;
213    memset (pst, 0x00, sizeof(SYSTEMTIME));
214
215    if (lstrcmpi (pszTime, TEXT("never")))
216       {
217       *pfEver = TRUE;
218
219       if (!lstrncmpi (pszTime, TEXT("at"), lstrlen(TEXT("at"))))
220          pszTime += lstrlen(TEXT("at"));
221       while ((*pszTime == ' ') || (*pszTime == '\t'))
222          ++pszTime;
223
224       // first, does it start with a day-of-week?
225       //
226       pst->wDayOfWeek = (WORD)(-1); // daily until proven otherwise
227
228       for (WORD ii = 0; ii < 7; ++ii)
229          {
230          if (!lstrncmpi (apszDays[ii], pszTime, 3))
231             {
232             pst->wDayOfWeek = ii;
233             break;
234             }
235          }
236
237       // next, find the hour
238       //
239       while (*pszTime && !isdigit(*pszTime))
240          ++pszTime;
241
242       TCHAR szComponent[ cchRESOURCE ];
243       lstrcpy (szComponent, pszTime);
244       LPTSTR pch;
245       for (pch = szComponent; isdigit(*pch); ++pch)
246          ;
247       *pch = TEXT('\0');
248
249       pst->wHour = atoi(szComponent);
250
251       // next, find the minutes
252       //
253       while (isdigit(*pszTime))
254          ++pszTime;
255       while (*pszTime && !isdigit(*pszTime))
256          ++pszTime;
257
258       lstrcpy (szComponent, pszTime);
259       for (pch = szComponent; isdigit(*pch); ++pch)
260          ;
261       *pch = TEXT('\0');
262
263       pst->wMinute = atoi(szComponent);
264
265       // next, check for a 'am' or 'pm' marker
266       //
267       for ( ; *pszTime; ++pszTime)
268          {
269          if (tolower(*pszTime) == TEXT('p'))
270             {
271             if (pst->wHour < 12)
272                pst->wHour += 12;
273             break;
274             }
275          if (tolower(*pszTime) == TEXT('a'))
276             {
277             if (pst->wHour >= 12)
278                pst->wHour -= 12;
279             break;
280             }
281          }
282       }
283 }
284
285
286 void AfsClass_FormatRecurringTime (LPTSTR pszTarget, SYSTEMTIME *pst)
287 {
288    if (pst == NULL)
289       {
290       wsprintf (pszTarget, TEXT("never"));
291       }
292    else
293       {
294       WORD wHour = ((pst->wHour % 12) == 0) ? 12 : (pst->wHour % 12);
295       TCHAR szAMPM[3];
296       lstrcpy (szAMPM, (pst->wHour >= 12) ? TEXT("pm") : TEXT("am"));
297
298       if (pst->wDayOfWeek == (WORD)(-1))  // daily at specified time?
299          {
300          wsprintf (pszTarget, TEXT("%u:%02u %s"), wHour, pst->wMinute, szAMPM);
301          }
302       else // weekly on specified date at specified time?
303          {
304          wsprintf (pszTarget, TEXT("%s %u:%02u %s"), apszDays[ pst->wDayOfWeek ], wHour, pst->wMinute, szAMPM);
305          }
306       }
307 }
308
309
310 void AfsClass_SplitFilename (LPSTR pszDirectoryA, LPSTR pszFilenameA, LPTSTR pszFullName)
311 {
312    CopyStringToAnsi (pszDirectoryA, pszFullName);
313
314    LPSTR pszLastSlashA = NULL;
315    for (LPSTR pszA = pszDirectoryA; *pszA; ++pszA)
316       {
317       if ((*pszA == '/') || (*pszA == '\\'))
318          pszLastSlashA = pszA;
319       }
320
321    if (!pszLastSlashA)
322       {
323       strcpy (pszFilenameA, pszDirectoryA);
324       *pszDirectoryA = 0;
325       }
326    else
327       {
328       strcpy (pszFilenameA, 1+pszLastSlashA);
329       *pszLastSlashA = 0;
330       }
331 }
332
333
334 void AfsClass_SystemTimeToRestartTime (bos_RestartTime_p prt, BOOL fEnable, LPSYSTEMTIME pst)
335 {
336    memset (prt, 0x00, sizeof(bos_RestartTime_t));
337    if (!fEnable)
338       prt->mask = BOS_RESTART_TIME_NEVER;
339    else
340       {
341       prt->mask = (bos_RestartTimeFields_t)(BOS_RESTART_TIME_HOUR | BOS_RESTART_TIME_MINUTE);
342       prt->hour = pst->wHour;
343       prt->min = pst->wMinute;
344
345       if (pst->wDayOfWeek != (WORD)-1)
346          {
347          prt->mask = (bos_RestartTimeFields_t)(prt->mask | BOS_RESTART_TIME_DAY);
348          prt->day = pst->wDayOfWeek;
349          }
350       }
351 }
352
353
354 void AfsClass_RestartTimeToSystemTime (BOOL *pfEnable, LPSYSTEMTIME pst, bos_RestartTime_p prt)
355 {
356    memset (pst, 0x00, sizeof(SYSTEMTIME));
357
358    if ((!prt->mask) || (prt->mask & BOS_RESTART_TIME_NEVER))
359       {
360       *pfEnable = FALSE;
361       }
362    else
363       {
364       *pfEnable = TRUE;
365       pst->wHour = (prt->mask & BOS_RESTART_TIME_HOUR) ? prt->hour : 0;
366       pst->wMinute = (prt->mask & BOS_RESTART_TIME_MINUTE) ? prt->min : 0;
367       pst->wDayOfWeek = (prt->mask & BOS_RESTART_TIME_DAY) ? prt->day : (WORD)-1;
368       }
369 }
370
371
372 void AfsClass_IntToAddress (LPSOCKADDR_IN pAddr, int IntAddr)
373 {
374    memset (pAddr, 0x00, sizeof(SOCKADDR_IN));
375    pAddr->sin_family = AF_INET;
376    pAddr->sin_addr.s_addr = htonl(IntAddr);
377 }
378
379
380 void AfsClass_AddressToInt (int *pIntAddr, LPSOCKADDR_IN pAddr)
381 {
382    *pIntAddr = ntohl(pAddr->sin_addr.s_addr);
383 }
384
385
386 void AfsClass_SpecifyRefreshDomain (DWORD dwWantUser)
387 {
388    dwWant = dwWantUser;
389 }
390
391
392 BOOL AfsClass_Initialize (ULONG *pStatus)
393 {
394    if (!Worker_Initialize (pStatus))
395       return FALSE;
396
397    return TRUE;
398 }
399
400
401 void AfsClass_GenFullUserName (LPTSTR pszTarget, LPCTSTR pszPrincipal, LPCTSTR pszInstance)
402 {
403    lstrcpy (pszTarget, pszPrincipal);
404    if (pszInstance && *pszInstance)
405       wsprintf (&pszTarget[ lstrlen(pszTarget) ], TEXT(".%s"), pszInstance);
406 }
407