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