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