3620bd2658ffd39475b8f5bd21a9e54e2c43d8e6
[openafs.git] / src / WINNT / afsapplib / al_misc.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/afsapplib.h>
16 #include "al_dynlink.h"
17 #include <WINNT/TaAfsAdmSvrClient.h>
18
19
20 /*
21  * DEFINITIONS ________________________________________________________________
22  *
23  */
24
25 #define GWD_ANIMATIONFRAME  TEXT("afsapplib/al_misc.cpp - next animation frame")
26
27
28 /*
29  * PROTOTYPES _________________________________________________________________
30  *
31  */
32
33 BOOL CALLBACK AfsAppLib_TranslateErrorFunc (LPTSTR pszText, ULONG code, LANGID idLanguage);
34
35
36 /*
37  * STARTUP ____________________________________________________________________
38  *
39  */
40
41 static HINSTANCE g_hInst = NULL;
42 static HINSTANCE g_hInstApp = NULL;
43
44 HINSTANCE AfsAppLib_GetInstance (void)
45 {
46    return g_hInst;
47 }
48
49
50 EXPORTED HINSTANCE AfsAppLib_GetAppInstance (void)
51 {
52    if (!g_hInstApp)
53       g_hInstApp = GetModuleHandle(NULL);
54    return g_hInstApp;
55 }
56
57
58 EXPORTED void AfsAppLib_SetAppInstance (HINSTANCE hInst)
59 {
60    g_hInstApp = hInst;
61 }
62
63
64 extern "C" BOOLEAN _stdcall DllEntryPoint (HANDLE hInst, DWORD dwReason, PVOID pReserved)
65 {
66    switch (dwReason)
67       {
68       case DLL_PROCESS_ATTACH:
69          if (!g_hInst)
70             {
71             g_hInst = (HINSTANCE)hInst;
72             TaLocale_LoadCorrespondingModule (g_hInst);
73             SetErrorTranslationFunction ((LPERRORPROC)AfsAppLib_TranslateErrorFunc);
74
75             InitCommonControls();
76             RegisterSpinnerClass();
77             RegisterElapsedClass();
78             RegisterTimeClass();
79             RegisterDateClass();
80             RegisterSockAddrClass();
81             RegisterCheckListClass();
82             RegisterFastListClass();
83             }
84          break;
85       }
86    return TRUE;
87 }
88
89
90 /*
91  * IMAGE LISTS ________________________________________________________________
92  *
93  */
94
95 HIMAGELIST AfsAppLib_CreateImageList (BOOL fLarge)
96 {
97    HIMAGELIST hil;
98    hil = ImageList_Create ((fLarge)?32:16, (fLarge)?32:16, TRUE, 4, 0);
99
100    AfsAppLib_AddToImageList (hil, IDI_SERVER,           fLarge);
101    AfsAppLib_AddToImageList (hil, IDI_SERVER_ALERT,     fLarge);
102    AfsAppLib_AddToImageList (hil, IDI_SERVER_UNMON,     fLarge);
103    AfsAppLib_AddToImageList (hil, IDI_SERVICE,          fLarge);
104    AfsAppLib_AddToImageList (hil, IDI_SERVICE_ALERT,    fLarge);
105    AfsAppLib_AddToImageList (hil, IDI_SERVICE_STOPPED,  fLarge);
106    AfsAppLib_AddToImageList (hil, IDI_AGGREGATE,        fLarge);
107    AfsAppLib_AddToImageList (hil, IDI_AGGREGATE_ALERT,  fLarge);
108    AfsAppLib_AddToImageList (hil, IDI_FILESET,          fLarge);
109    AfsAppLib_AddToImageList (hil, IDI_FILESET_ALERT,    fLarge);
110    AfsAppLib_AddToImageList (hil, IDI_FILESET_LOCKED,   fLarge);
111    AfsAppLib_AddToImageList (hil, IDI_BOSSERVICE,       fLarge);
112    AfsAppLib_AddToImageList (hil, IDI_CELL,             fLarge);
113    AfsAppLib_AddToImageList (hil, IDI_SERVER_KEY,       fLarge);
114    AfsAppLib_AddToImageList (hil, IDI_USER,             fLarge);
115    AfsAppLib_AddToImageList (hil, IDI_GROUP,            fLarge);
116
117    return hil;
118 }
119
120
121 void AfsAppLib_AddToImageList (HIMAGELIST hil, int idi, BOOL fLarge)
122 {
123    HICON hi = TaLocale_LoadIcon (idi);
124    ImageList_AddIcon (hil, hi);
125 }
126
127
128 /*
129  * ANIMATION __________________________________________________________________
130  *
131  */
132
133 void AfsAppLib_AnimateIcon (HWND hIcon, int *piFrameLast)
134 {
135    static HICON hiStop;
136    static HICON hiFrame[8];
137    static BOOL fLoaded = FALSE;
138
139    if (!fLoaded)
140       {
141       hiStop     = TaLocale_LoadIcon (IDI_SPINSTOP);
142       hiFrame[0] = TaLocale_LoadIcon (IDI_SPIN1);
143       hiFrame[1] = TaLocale_LoadIcon (IDI_SPIN2);
144       hiFrame[2] = TaLocale_LoadIcon (IDI_SPIN3);
145       hiFrame[3] = TaLocale_LoadIcon (IDI_SPIN4);
146       hiFrame[4] = TaLocale_LoadIcon (IDI_SPIN5);
147       hiFrame[5] = TaLocale_LoadIcon (IDI_SPIN6);
148       hiFrame[6] = TaLocale_LoadIcon (IDI_SPIN7);
149       hiFrame[7] = TaLocale_LoadIcon (IDI_SPIN8);
150       fLoaded = TRUE;
151       }
152
153    if (piFrameLast)
154       {
155       *piFrameLast = (*piFrameLast == 7) ? 0 : (1+*piFrameLast);
156       }
157
158    SendMessage (hIcon, STM_SETICON, (WPARAM)((piFrameLast) ? hiFrame[ *piFrameLast ] : hiStop), 0);
159 }
160
161
162 BOOL CALLBACK AnimationHook (HWND hIcon, UINT msg, WPARAM wp, LPARAM lp)
163 {
164    PVOID oldProc = Subclass_FindNextHook (hIcon, AnimationHook);
165
166    switch (msg)
167       {
168       case WM_TIMER:
169          int iFrame;
170          iFrame = GetWindowData (hIcon, GWD_ANIMATIONFRAME);
171          AfsAppLib_AnimateIcon (hIcon, &iFrame);
172          SetWindowData (hIcon, GWD_ANIMATIONFRAME, iFrame);
173          break;
174
175       case WM_DESTROY:
176          Subclass_RemoveHook (hIcon, AnimationHook);
177          break;
178       }
179
180    if (oldProc)
181       return CallWindowProc ((WNDPROC)oldProc, hIcon, msg, wp, lp);
182    else
183       return DefWindowProc (hIcon, msg, wp, lp);
184 }
185
186
187 void AfsAppLib_StartAnimation (HWND hIcon, int fps)
188 {
189    Subclass_AddHook (hIcon, AnimationHook);
190    SetTimer (hIcon, 0, 1000/((fps) ? fps : 8), NULL);
191    AfsAppLib_AnimateIcon (hIcon);
192 }
193
194
195 void AfsAppLib_StopAnimation (HWND hIcon)
196 {
197    KillTimer (hIcon, 0);
198    AfsAppLib_AnimateIcon (hIcon);
199    Subclass_RemoveHook (hIcon, AnimationHook);
200 }
201
202
203 /*
204  * ERROR TRANSLATION __________________________________________________________
205  *
206  */
207
208 BOOL CALLBACK AfsAppLib_TranslateErrorFunc (LPTSTR pszText, ULONG code, LANGID idLanguage)
209 {
210    DWORD idClient;
211    if ((idClient = AfsAppLib_GetAdminServerClientID()) != 0)
212       {
213       ULONG status;
214       return asc_ErrorCodeTranslate (idClient, code, idLanguage, pszText, &status);
215       }
216    else if (OpenUtilLibrary())
217       {
218       const char *pszTextA = NULL;
219       afs_status_t status;
220       if (util_AdminErrorCodeTranslate (code, idLanguage, &pszTextA, &status) && (pszTextA))
221          {
222          CopyAnsiToString (pszText, pszTextA);
223          return TRUE;
224          }
225       CloseUtilLibrary();
226       }
227
228    return FALSE;
229 }
230
231
232 BOOL AfsAppLib_TranslateError (LPTSTR pszText, ULONG status, LANGID idLanguage)
233 {
234    LANGID idLangOld = TaLocale_GetLanguage();
235    TaLocale_SetLanguage (idLanguage);
236
237    BOOL rc = FormatError (pszText, TEXT("%s"), status);
238
239    TaLocale_SetLanguage (idLangOld);
240    return rc;
241 }
242
243
244 /*
245  * CELL LIST __________________________________________________________________
246  *
247  */
248
249 #define cREALLOC_CELLLIST   4
250
251 LPCELLLIST AfsAppLib_GetCellList (HKEY hkBase, LPTSTR pszRegPath)
252 {
253    LPCELLLIST lpcl = New (CELLLIST);
254    memset (lpcl, 0x00, sizeof(CELLLIST));
255
256    if (hkBase && pszRegPath)
257       {
258       lpcl->hkBase = hkBase;
259       lstrcpy (lpcl->szRegPath, pszRegPath);
260
261       HKEY hk;
262       if (RegOpenKey (hkBase, pszRegPath, &hk) == 0)
263          {
264          TCHAR szCell[ cchNAME ];
265          for (size_t ii = 0; RegEnumKey (hk, ii, szCell, cchNAME) == 0; ++ii)
266             {
267             if (REALLOC (lpcl->aCells, lpcl->nCells, 1+ii, cREALLOC_CELLLIST))
268                {
269                lpcl->aCells[ ii ] = CloneString (szCell);
270                }
271             }
272          RegCloseKey (hk);
273          }
274       }
275    else // Get cell list from AFS
276       {
277       // TODO
278       }
279
280    TCHAR szDefCell[ cchNAME ];
281    if (AfsAppLib_GetLocalCell (szDefCell))
282       {
283       for (size_t iclDef = 0; iclDef < lpcl->nCells; ++iclDef)
284          {
285          if (lpcl->aCells[ iclDef ] == NULL)
286             continue;
287          if (!lstrcmpi (lpcl->aCells[ iclDef ], szDefCell))
288             break;
289          }
290       if (iclDef == lpcl->nCells) // default cell not currently in list?
291          {
292          for (iclDef = 0; iclDef < lpcl->nCells; ++iclDef)
293             {
294             if (lpcl->aCells[ iclDef ] == NULL)
295                break;
296             }
297          if (REALLOC (lpcl->aCells, lpcl->nCells, 1+iclDef, cREALLOC_CELLLIST))
298             {
299             lpcl->aCells[iclDef] = CloneString (szDefCell);
300             }
301          }
302       if ((iclDef > 0) && (iclDef < lpcl->nCells) && (lpcl->aCells[ iclDef ]))
303          {
304          LPTSTR pszZero = lpcl->aCells[0];
305          lpcl->aCells[0] = lpcl->aCells[iclDef];
306          lpcl->aCells[iclDef] = pszZero;
307          }
308       }
309
310    for ( ; (lpcl->nCells != 0); (lpcl->nCells)--)
311       {
312       if (lpcl->aCells[ lpcl->nCells-1 ] != NULL)
313          break;
314       }
315
316    return lpcl;
317 }
318
319
320 LPCELLLIST AfsAppLib_GetCellList (LPCELLLIST lpclCopy)
321 {
322    LPCELLLIST lpcl = New (CELLLIST);
323    memset (lpcl, 0x00, sizeof(CELLLIST));
324
325    if (lpclCopy)
326       {
327       if (REALLOC (lpcl->aCells, lpcl->nCells, lpclCopy->nCells, cREALLOC_CELLLIST))
328          {
329          for (size_t icl = 0; icl < lpcl->nCells; ++icl)
330             {
331             if (lpclCopy->aCells[ icl ])
332                {
333                lpcl->aCells[ icl ] = CloneString (lpclCopy->aCells[ icl ]);
334                }
335             }
336          }
337       }
338
339    return lpcl;
340 }
341
342
343 void AfsAppLib_AddToCellList (LPCELLLIST lpcl, LPTSTR pszCell)
344 {
345    if (lpcl && lpcl->hkBase && lpcl->szRegPath[0])
346       {
347       TCHAR szPath[ MAX_PATH ];
348       wsprintf (szPath, TEXT("%s\\%s"), lpcl->szRegPath, pszCell);
349
350       HKEY hk;
351       if (RegCreateKey (lpcl->hkBase, szPath, &hk) == 0)
352          {
353          RegCloseKey (hk);
354          }
355       }
356 }
357
358
359 void AfsAppLib_FreeCellList (LPCELLLIST lpcl)
360 {
361    if (lpcl)
362       {
363       if (lpcl->aCells)
364          {
365          for (size_t icl = 0; icl < lpcl->nCells; ++icl)
366             {
367             if (lpcl->aCells[icl] != NULL)
368                FreeString (lpcl->aCells[icl]);
369             }
370          Free (lpcl->aCells);
371          }
372       Delete (lpcl);
373       }
374 }
375
376
377 /*
378  * TRULY MISCELLANEOUS ________________________________________________________
379  *
380  */
381
382 BOOL AfsAppLib_IsTimeInFuture (LPSYSTEMTIME pstTest)
383 {
384    SYSTEMTIME stNow;
385    GetSystemTime (&stNow);
386
387    FILETIME ftNowGMT;
388    SystemTimeToFileTime (&stNow, &ftNowGMT);
389
390    FILETIME ftTest;
391    SystemTimeToFileTime (pstTest, &ftTest);
392
393    if (CompareFileTime (&ftTest, &ftNowGMT) >= 0)
394       return TRUE;
395
396    return FALSE;
397 }
398
399
400 void AfsAppLib_UnixTimeToSystemTime (LPSYSTEMTIME pst, ULONG ut, BOOL fElapsed)
401 {
402    // A Unix time is the number of seconds since 1/1/1970.
403    // The first step in this conversion is to change that count-of-seconds
404    // into a count-of-100ns-intervals...
405    //
406    LARGE_INTEGER ldw;
407    ldw.QuadPart = (LONGLONG)10000000 * (LONGLONG)ut;
408
409    // Then adjust the count to be a count-of-100ns-intervals since
410    // 1/1/1601, instead of 1/1/1970. That means adding a *big* number...
411    //
412    ldw.QuadPart += (LONGLONG)0x019db1ded53e8000;
413
414    // Now the count is effectively a FILETIME, which we can convert
415    // to a SYSTEMTIME with a Win32 API.
416    //
417    FILETIME ft;
418    ft.dwHighDateTime = (DWORD)ldw.HighPart;
419    ft.dwLowDateTime = (DWORD)ldw.LowPart;
420    FileTimeToSystemTime (&ft, pst);
421
422    if (fElapsed)
423       {
424       pst->wYear -= 1970;
425       pst->wMonth -= 1;
426       pst->wDayOfWeek -= 1;
427       pst->wDay -= 1;
428       }
429 }
430
431
432 void AfsAppLib_SplitCredentials (LPTSTR pszCreds, LPTSTR pszCell, LPTSTR pszID)
433 {
434    LPTSTR pszSlash = (LPTSTR)lstrrchr (pszCreds, TEXT('/'));
435    if (pszSlash == NULL)
436       {
437       if (pszCell)
438          AfsAppLib_GetLocalCell (pszCell);
439       if (pszID)
440          lstrcpy (pszID, pszCreds);
441       }
442    else // a cell was specified
443       {
444       if (pszCell)
445          lstrzcpy (pszCell, pszCreds, pszSlash -pszCreds);
446       if (pszID)
447          lstrcpy (pszID, 1+pszSlash);
448       }
449 }
450
451
452 BOOL AfsAppLib_GetLocalCell (LPTSTR pszCell, ULONG *pStatus)
453 {
454    static TCHAR szCell[ cchRESOURCE ] = TEXT("");
455
456    BOOL rc = TRUE;
457    ULONG status = 0;    
458
459    if (szCell[0] == TEXT('\0'))
460       {
461       DWORD idClient;
462       if ((idClient = AfsAppLib_GetAdminServerClientID()) != 0)
463          {
464          rc = asc_LocalCellGet (idClient, szCell, &status);
465          }
466       else if (OpenClientLibrary())
467          {
468          char szCellNameA[ MAX_PATH ];
469          if ((rc = afsclient_LocalCellGet (szCellNameA, (afs_status_p)&status)) == TRUE)
470             {
471             CopyAnsiToString (szCell, szCellNameA);
472             }
473          CloseClientLibrary();
474          }
475       }
476
477    if (rc)
478       lstrcpy (pszCell, szCell);
479    else if (pStatus)
480       *pStatus = status;
481    return rc;
482 }
483
484
485 BOOL AfsAppLib_ReallocFunction (LPVOID *ppTarget, size_t cbElement, size_t *pcTarget, size_t cReq, size_t cInc)
486 {
487    LPVOID pNew;
488    size_t cNew;
489
490    if (cReq <= *pcTarget)
491       return TRUE;
492
493    if ((cNew = cInc * ((cReq + cInc-1) / cInc)) <= 0)
494       return FALSE;
495
496    if ((pNew = (LPVOID)Allocate (cbElement * cNew)) == NULL)
497       return FALSE;
498    memset (pNew, 0x00, cbElement * cNew);
499
500    if (*pcTarget != 0)
501       {
502       memcpy (pNew, *ppTarget, cbElement * (*pcTarget));
503       Free (*ppTarget);
504       }
505
506    *ppTarget = pNew;
507    *pcTarget = cNew;
508    return TRUE;
509 }
510
511
512 HFONT AfsAppLib_CreateFont (int idsFont)
513 {
514    TCHAR szFont[ cchRESOURCE ];
515    GetString (szFont, idsFont);
516
517    HFONT hf = (HFONT)GetStockObject (DEFAULT_GUI_FONT);
518
519    LOGFONT lf;
520    GetObject (hf, sizeof(lf), &lf);
521    lf.lfWeight = FW_NORMAL;
522
523    LPTSTR pszSection = szFont;
524    LPTSTR pszNextSection;
525    if ((pszNextSection = (LPTSTR)lstrchr (pszSection, TEXT(','))) != NULL)
526       *pszNextSection++ = TEXT('\0');
527    if (!pszSection || !*pszSection)
528       return NULL;
529
530    lstrcpy (lf.lfFaceName, pszSection);
531
532    pszSection = pszNextSection;
533    if ((pszNextSection = (LPTSTR)lstrchr (pszSection, TEXT(','))) != NULL)
534       *pszNextSection++ = TEXT('\0');
535    if (!pszSection || !*pszSection)
536       return NULL;
537
538    HDC hdc = GetDC (NULL);
539    lf.lfHeight = -MulDiv (_ttol(pszSection), GetDeviceCaps (hdc, LOGPIXELSY), 72);
540    ReleaseDC (NULL, hdc);
541
542    pszSection = pszNextSection;
543    if ((pszNextSection = (LPTSTR)lstrchr (pszSection, TEXT(','))) != NULL)
544       *pszNextSection++ = TEXT('\0');
545    if (pszSection && *pszSection)
546       {
547       if (lstrchr (pszSection, TEXT('b')) || lstrchr (pszSection, TEXT('B')))
548          lf.lfWeight = FW_BOLD;
549       if (lstrchr (pszSection, TEXT('i')) || lstrchr (pszSection, TEXT('I')))
550          lf.lfItalic = TRUE;
551       if (lstrchr (pszSection, TEXT('u')) || lstrchr (pszSection, TEXT('U')))
552          lf.lfUnderline = TRUE;
553       }
554
555    return CreateFontIndirect(&lf);
556 }
557