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