windows-vs2005b2-20050706
[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
217        if (OpenUtilLibrary())
218       {
219       const char *pszTextA = NULL;
220       afs_status_t status;
221       if (util_AdminErrorCodeTranslate (code, idLanguage, &pszTextA, &status) && (pszTextA))
222          {
223          CopyAnsiToString (pszText, pszTextA);
224          return TRUE;
225          }
226       CloseUtilLibrary();
227       }
228
229    return FALSE;
230 }
231
232
233 BOOL AfsAppLib_TranslateError (LPTSTR pszText, ULONG status, LANGID idLanguage)
234 {
235    LANGID idLangOld = TaLocale_GetLanguage();
236    TaLocale_SetLanguage (idLanguage);
237
238    BOOL rc = FormatError (pszText, TEXT("%s"), status);
239
240    TaLocale_SetLanguage (idLangOld);
241    return rc;
242 }
243
244
245 /*
246  * CELL LIST __________________________________________________________________
247  *
248  */
249
250 #define cREALLOC_CELLLIST   4
251
252 LPCELLLIST AfsAppLib_GetCellList (HKEY hkBase, LPTSTR pszRegPath)
253 {
254    LPCELLLIST lpcl = New (CELLLIST);
255    memset (lpcl, 0x00, sizeof(CELLLIST));
256
257    if (hkBase && pszRegPath)
258       {
259       lpcl->hkBase = hkBase;
260       lstrcpy (lpcl->szRegPath, pszRegPath);
261
262       HKEY hk;
263       if (RegOpenKey (hkBase, pszRegPath, &hk) == 0)
264          {
265          TCHAR szCell[ cchNAME ];
266          for (size_t ii = 0; RegEnumKey (hk, ii, szCell, cchNAME) == 0; ++ii)
267             {
268             if (REALLOC (lpcl->aCells, lpcl->nCells, 1+ii, cREALLOC_CELLLIST))
269                {
270                lpcl->aCells[ ii ] = CloneString (szCell);
271                }
272             }
273          RegCloseKey (hk);
274          }
275       }
276    else // Get cell list from AFS
277       {
278       // TODO
279       }
280
281    TCHAR szDefCell[ cchNAME ];
282    if (AfsAppLib_GetLocalCell (szDefCell))
283       {
284       size_t iclDef;
285       for (iclDef = 0; iclDef < lpcl->nCells; ++iclDef)
286          {
287          if (lpcl->aCells[ iclDef ] == NULL)
288             continue;
289          if (!lstrcmpi (lpcl->aCells[ iclDef ], szDefCell))
290             break;
291          }
292       if (iclDef == lpcl->nCells) // default cell not currently in list?
293          {
294          for (iclDef = 0; iclDef < lpcl->nCells; ++iclDef)
295             {
296             if (lpcl->aCells[ iclDef ] == NULL)
297                break;
298             }
299          if (REALLOC (lpcl->aCells, lpcl->nCells, 1+iclDef, cREALLOC_CELLLIST))
300             {
301             lpcl->aCells[iclDef] = CloneString (szDefCell);
302             }
303          }
304       if ((iclDef > 0) && (iclDef < lpcl->nCells) && (lpcl->aCells[ iclDef ]))
305          {
306          LPTSTR pszZero = lpcl->aCells[0];
307          lpcl->aCells[0] = lpcl->aCells[iclDef];
308          lpcl->aCells[iclDef] = pszZero;
309          }
310       }
311
312    for ( ; (lpcl->nCells != 0); (lpcl->nCells)--)
313       {
314       if (lpcl->aCells[ lpcl->nCells-1 ] != NULL)
315          break;
316       }
317
318    return lpcl;
319 }
320
321
322 LPCELLLIST AfsAppLib_GetCellList (LPCELLLIST lpclCopy)
323 {
324    LPCELLLIST lpcl = New (CELLLIST);
325    memset (lpcl, 0x00, sizeof(CELLLIST));
326
327    if (lpclCopy)
328       {
329       if (REALLOC (lpcl->aCells, lpcl->nCells, lpclCopy->nCells, cREALLOC_CELLLIST))
330          {
331          for (size_t icl = 0; icl < lpcl->nCells; ++icl)
332             {
333             if (lpclCopy->aCells[ icl ])
334                {
335                lpcl->aCells[ icl ] = CloneString (lpclCopy->aCells[ icl ]);
336                }
337             }
338          }
339       }
340
341    return lpcl;
342 }
343
344
345 void AfsAppLib_AddToCellList (LPCELLLIST lpcl, LPTSTR pszCell)
346 {
347    if (lpcl && lpcl->hkBase && lpcl->szRegPath[0])
348       {
349       TCHAR szPath[ MAX_PATH ];
350       wsprintf (szPath, TEXT("%s\\%s"), lpcl->szRegPath, pszCell);
351
352       HKEY hk;
353       if (RegCreateKey (lpcl->hkBase, szPath, &hk) == 0)
354          {
355          RegCloseKey (hk);
356          }
357       }
358 }
359
360
361 void AfsAppLib_FreeCellList (LPCELLLIST lpcl)
362 {
363    if (lpcl)
364       {
365       if (lpcl->aCells)
366          {
367          for (size_t icl = 0; icl < lpcl->nCells; ++icl)
368             {
369             if (lpcl->aCells[icl] != NULL)
370                FreeString (lpcl->aCells[icl]);
371             }
372          Free (lpcl->aCells);
373          }
374       Delete (lpcl);
375       }
376 }
377
378
379 /*
380  * TRULY MISCELLANEOUS ________________________________________________________
381  *
382  */
383
384 BOOL AfsAppLib_IsTimeInFuture (LPSYSTEMTIME pstTest)
385 {
386    SYSTEMTIME stNow;
387    GetSystemTime (&stNow);
388
389    FILETIME ftNowGMT;
390    SystemTimeToFileTime (&stNow, &ftNowGMT);
391
392    FILETIME ftTest;
393    SystemTimeToFileTime (pstTest, &ftTest);
394
395    if (CompareFileTime (&ftTest, &ftNowGMT) >= 0)
396       return TRUE;
397
398    return FALSE;
399 }
400
401
402 void AfsAppLib_UnixTimeToSystemTime (LPSYSTEMTIME pst, ULONG ut, BOOL fElapsed)
403 {
404    // A Unix time is the number of seconds since 1/1/1970.
405    // The first step in this conversion is to change that count-of-seconds
406    // into a count-of-100ns-intervals...
407    //
408    LARGE_INTEGER ldw;
409    ldw.QuadPart = (LONGLONG)10000000 * (LONGLONG)ut;
410
411    // Then adjust the count to be a count-of-100ns-intervals since
412    // 1/1/1601, instead of 1/1/1970. That means adding a *big* number...
413    //
414    ldw.QuadPart += (LONGLONG)0x019db1ded53e8000;
415
416    // Now the count is effectively a FILETIME, which we can convert
417    // to a SYSTEMTIME with a Win32 API.
418    //
419    FILETIME ft;
420    ft.dwHighDateTime = (DWORD)ldw.HighPart;
421    ft.dwLowDateTime = (DWORD)ldw.LowPart;
422    FileTimeToSystemTime (&ft, pst);
423
424    if (fElapsed)
425       {
426       pst->wYear -= 1970;
427       pst->wMonth -= 1;
428       pst->wDayOfWeek -= 1;
429       pst->wDay -= 1;
430       }
431 }
432
433
434 void AfsAppLib_SplitCredentials (LPTSTR pszCreds, LPTSTR pszCell, LPTSTR pszID)
435 {
436    LPTSTR pszSlash = (LPTSTR)lstrrchr (pszCreds, TEXT('/'));
437    if (pszSlash == NULL)
438       {
439       if (pszCell)
440          AfsAppLib_GetLocalCell (pszCell);
441       if (pszID)
442          lstrcpy (pszID, pszCreds);
443       }
444    else // a cell was specified
445       {
446       if (pszCell)
447          lstrzcpy (pszCell, pszCreds, pszSlash -pszCreds);
448       if (pszID)
449          lstrcpy (pszID, 1+pszSlash);
450       }
451 }
452
453
454 BOOL AfsAppLib_GetLocalCell (LPTSTR pszCell, ULONG *pStatus)
455 {
456    static TCHAR szCell[ cchRESOURCE ] = TEXT("");
457
458    BOOL rc = TRUE;
459    ULONG status = 0;    
460
461    if (szCell[0] == TEXT('\0'))
462       {
463       DWORD idClient;
464       if ((idClient = AfsAppLib_GetAdminServerClientID()) != 0)
465          {
466          rc = asc_LocalCellGet (idClient, szCell, &status);
467          }
468       else 
469           if (OpenClientLibrary())
470          {
471          char szCellNameA[ MAX_PATH ];
472          if ((rc = afsclient_LocalCellGet (szCellNameA, (afs_status_p)&status)) == TRUE)
473             {
474             CopyAnsiToString (szCell, szCellNameA);
475             }
476          CloseClientLibrary();
477          }
478       }
479
480    if (rc)
481       lstrcpy (pszCell, szCell);
482    else if (pStatus)
483       *pStatus = status;
484    return rc;
485 }
486
487
488 BOOL AfsAppLib_ReallocFunction (LPVOID *ppTarget, size_t cbElement, size_t *pcTarget, size_t cReq, size_t cInc)
489 {
490    LPVOID pNew;
491    size_t cNew;
492
493    if (cReq <= *pcTarget)
494       return TRUE;
495
496    if ((cNew = cInc * ((cReq + cInc-1) / cInc)) <= 0)
497       return FALSE;
498
499    if ((pNew = (LPVOID)Allocate (cbElement * cNew)) == NULL)
500       return FALSE;
501    memset (pNew, 0x00, cbElement * cNew);
502
503    if (*pcTarget != 0)
504       {
505       memcpy (pNew, *ppTarget, cbElement * (*pcTarget));
506       Free (*ppTarget);
507       }
508
509    *ppTarget = pNew;
510    *pcTarget = cNew;
511    return TRUE;
512 }
513
514
515 HFONT AfsAppLib_CreateFont (int idsFont)
516 {
517    TCHAR szFont[ cchRESOURCE ];
518    GetString (szFont, idsFont);
519
520    HFONT hf = (HFONT)GetStockObject (DEFAULT_GUI_FONT);
521
522    LOGFONT lf;
523    GetObject (hf, sizeof(lf), &lf);
524    lf.lfWeight = FW_NORMAL;
525
526    LPTSTR pszSection = szFont;
527    LPTSTR pszNextSection;
528    if ((pszNextSection = (LPTSTR)lstrchr (pszSection, TEXT(','))) != NULL)
529       *pszNextSection++ = TEXT('\0');
530    if (!pszSection || !*pszSection)
531       return NULL;
532
533    lstrcpy (lf.lfFaceName, pszSection);
534
535    pszSection = pszNextSection;
536    if ((pszNextSection = (LPTSTR)lstrchr (pszSection, TEXT(','))) != NULL)
537       *pszNextSection++ = TEXT('\0');
538    if (!pszSection || !*pszSection)
539       return NULL;
540
541    HDC hdc = GetDC (NULL);
542    lf.lfHeight = -MulDiv (_ttol(pszSection), GetDeviceCaps (hdc, LOGPIXELSY), 72);
543    ReleaseDC (NULL, hdc);
544
545    pszSection = pszNextSection;
546    if ((pszNextSection = (LPTSTR)lstrchr (pszSection, TEXT(','))) != NULL)
547       *pszNextSection++ = TEXT('\0');
548    if (pszSection && *pszSection)
549       {
550       if (lstrchr (pszSection, TEXT('b')) || lstrchr (pszSection, TEXT('B')))
551          lf.lfWeight = FW_BOLD;
552       if (lstrchr (pszSection, TEXT('i')) || lstrchr (pszSection, TEXT('I')))
553          lf.lfItalic = TRUE;
554       if (lstrchr (pszSection, TEXT('u')) || lstrchr (pszSection, TEXT('U')))
555          lf.lfUnderline = TRUE;
556       }
557
558    return CreateFontIndirect(&lf);
559 }
560