Windows: conditionally set tray icon state
[openafs.git] / src / WINNT / client_creds / window.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 <roken.h>
17 #include <afs/stds.h>
18 #include <afs/afskfw.h>
19 #include "ipaddrchg.h"
20 }
21
22 #include "afscreds.h"
23
24 #define SECURITY_WIN32 1
25 #include <security.h>
26
27 /*
28  * DEFINITIONS ________________________________________________________________
29  *
30  */
31
32 #define ID_REMIND_TIMER      1000
33 #define ID_SERVICE_TIMER     1001
34
35 #define cREALLOC_TABS        4
36
37 #define dwTABPARAM_MOUNT     (LPTSTR)0
38 #define dwTABPARAM_ADVANCED  (LPTSTR)1
39 #define ISCELLTAB(_psz)      ((HIWORD((LONG)(_psz))) != 0)
40
41
42 /*
43  * PROTOTYPES _________________________________________________________________
44  *
45  */
46
47 void Main_OnInitDialog (HWND hDlg);
48 void Main_OnCheckMenuRemind (void);
49 void Main_OnRemindTimer (void);
50 void Main_OnMouseOver (void);
51 void Main_OnSelectTab (void);
52 void Main_OnCheckTerminate (void);
53 HWND Main_CreateTabDialog (HWND hTab, size_t iTab);
54
55 BOOL CALLBACK Terminate_DlgProc (HWND hDlg, UINT msg, WPARAM wp, LPARAM lp);
56 void Terminate_OnInitDialog (HWND hDlg);
57 void Terminate_OnOK (HWND hDlg);
58
59
60 /*
61  * ROUTINES ___________________________________________________________________
62  *
63  */
64
65 BOOL CALLBACK Main_DlgProc (HWND hDlg, UINT msg, WPARAM wp, LPARAM lp)
66 {
67    static UINT msgCheckTerminate = 0;
68    if (msgCheckTerminate == 0)
69       msgCheckTerminate = RegisterWindowMessage (TEXT("AfsCredsCheckTerminate"));
70
71    if (msg == msgCheckTerminate)
72       {
73       Main_OnCheckTerminate();
74       }
75    else switch (msg)
76       {
77       case WM_INITDIALOG:
78          g.hMain = hDlg;
79          Main_OnInitDialog (hDlg);
80          break;
81
82       case WM_DESTROY:
83          Creds_CloseLibraries();
84          ChangeTrayIcon (NIM_DELETE);
85          break;
86
87       case WM_ACTIVATEAPP:
88          if (wp)
89             {
90             Main_RepopulateTabs (FALSE);
91             }
92          break;
93
94       case WM_COMMAND:
95          switch (LOWORD(wp))
96             {
97             case IDOK:
98             case IDCANCEL:
99                Main_Show (FALSE);
100                break;
101
102             case M_ACTIVATE:
103                if (g.fIsWinNT || IsServiceRunning())
104                   {
105                   if (!lp) // Got here from "/show" parameter? switch tabs.
106                      {
107                      HWND hTab = GetDlgItem (g.hMain, IDC_TABS);
108                      TabCtrl_SetCurSel (hTab, 0);
109                      Main_OnSelectTab();
110                      }
111                   Main_Show (TRUE);
112                   }
113                else
114                   {
115                   Message (MB_ICONHAND, IDS_UNCONFIG_TITLE_95, IDS_UNCONFIG_DESC_95);
116                   }
117                break;
118
119             case M_TERMINATE:
120 #ifndef UAC_COMPATIBLE
121                if (g.fIsWinNT && IsServiceRunning())
122                   ModalDialog (IDD_TERMINATE, NULL, (DLGPROC)Terminate_DlgProc);
123                else
124 #endif
125                if (g.fIsWinNT)
126                   ModalDialog (IDD_TERMINATE_SMALL, NULL, (DLGPROC)Terminate_DlgProc);
127                else // (!g.fIsWinNT)
128                   ModalDialog (IDD_TERMINATE_SMALL_95, NULL, (DLGPROC)Terminate_DlgProc);
129                break;
130
131             case M_TERMINATE_NOW:
132                Quit();
133                break;
134
135             case M_REMIND:
136                Main_OnCheckMenuRemind();
137                break;
138             }
139          break;
140
141       case WM_TIMER:
142          Main_OnRemindTimer();
143          break;
144
145       case WM_NOTIFY:
146          switch (((NMHDR*)lp)->code)
147             {
148             case TCN_SELCHANGE:
149                Main_OnSelectTab();
150                break;
151             }
152          break;
153
154       case WM_TRAYICON:
155          switch (lp)
156             {
157             case WM_LBUTTONDOWN:
158                if (IsServiceRunning() || !IsServiceConfigured())
159                   Main_Show (TRUE);
160                else if (!g.fIsWinNT)
161                   Message (MB_ICONHAND, IDS_UNCONFIG_TITLE_95, IDS_UNCONFIG_DESC_95);
162                else
163                   ShowStartupWizard();
164                break;
165
166             case WM_RBUTTONDOWN:
167                HMENU hm;
168                if ((hm = TaLocale_LoadMenu (MENU_TRAYICON)) != 0)
169                   {
170                   POINT pt;
171                   GetCursorPos(&pt);
172
173                   HMENU hmDummy = CreateMenu();
174                   InsertMenu (hmDummy, 0, MF_POPUP, (UINT)hm, NULL);
175
176                   BOOL fRemind = FALSE;
177                   lock_ObtainMutex(&g.credsLock);
178                   for (size_t iCreds = 0; iCreds < g.cCreds; ++iCreds)
179                      {
180                      if (g.aCreds[ iCreds ].fRemind)
181                         fRemind = TRUE;
182                      }
183                   lock_ReleaseMutex(&g.credsLock);
184                   CheckMenuItem (hm, M_REMIND, MF_BYCOMMAND | ((fRemind) ? MF_CHECKED : MF_UNCHECKED));
185                   SetForegroundWindow(hDlg);
186                   TrackPopupMenu (GetSubMenu (hmDummy, 0),
187                                   TPM_RIGHTALIGN | TPM_RIGHTBUTTON,
188                                   pt.x, pt.y, NULL, hDlg, NULL);
189                   PostMessage(hDlg, WM_NULL, 0, 0);
190                   DestroyMenu (hmDummy);
191                   }
192                break;
193
194             case WM_MOUSEMOVE:
195                Main_OnMouseOver();
196                break;
197             }
198          break;
199       case WM_OBTAIN_TOKENS:
200           if ( InterlockedIncrement (&g.fShowingMessage) != 1 )
201               InterlockedDecrement (&g.fShowingMessage);
202           else
203               ShowObtainCreds (wp, (char *)lp);
204           GlobalFree((void *)lp);
205           break;
206
207       case WM_START_SERVICE:
208           {
209               SC_HANDLE hManager;
210               if ((hManager = OpenSCManager ( NULL, NULL, 
211                                               SC_MANAGER_CONNECT |
212                                               SC_MANAGER_ENUMERATE_SERVICE |
213                                               SC_MANAGER_QUERY_LOCK_STATUS)) != NULL)
214               {
215                   SC_HANDLE hService;
216                   if ((hService = OpenService ( hManager, TEXT("TransarcAFSDaemon"), 
217                                                 SERVICE_QUERY_STATUS | SERVICE_START)) != NULL)
218                   {
219                       if (StartService (hService, 0, 0))
220                           TestAndDoMapShare(SERVICE_START_PENDING);
221                       if ( KFW_is_available() && KFW_AFS_wait_for_service_start() ) {
222 #ifdef USE_MS2MIT
223                           KFW_import_windows_lsa();
224 #endif /* USE_MS2MIT */
225                           KFW_AFS_renew_tokens_for_all_cells();
226                       }
227
228                       CloseServiceHandle (hService);
229                   }
230
231                   CloseServiceHandle (hManager);
232               }
233               if (KFW_AFS_wait_for_service_start())
234                   ObtainTokensFromUserIfNeeded(g.hMain);
235           }
236           break;
237       }
238
239    return FALSE;
240 }
241
242
243 void Main_Show (BOOL fShow)
244 {
245    if (fShow)
246       {
247       ShowWindow (g.hMain, SW_SHOW);
248       SetWindowPos (g.hMain, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
249       SetForegroundWindow (g.hMain);
250       }
251    else
252       {
253       SetWindowPos (g.hMain, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_HIDEWINDOW);
254       }
255 }
256
257
258 void Main_OnInitDialog (HWND hDlg)
259 {
260     if (!g.fIsWinNT)
261     {
262         TCHAR szTitle[256];
263         GetString (szTitle, IDS_TITLE_95);
264         SetWindowText (hDlg, szTitle);
265     }
266
267     TCHAR szVersion[256];
268     DWORD dwPatch = 0;
269     TCHAR szUser[1024];
270     GetString (szVersion, IDS_UNKNOWN);
271     GetString (szUser, IDS_UNKNOWN);
272
273     HKEY hk;
274     if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, AFSREG_CLT_SW_VERSION_SUBKEY, 0,
275                        (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &hk) == 0)
276     {
277         DWORD dwSize = sizeof(szVersion);
278         DWORD dwType = REG_SZ;
279         RegQueryValueEx (hk, REGVAL_AFS_VERSION, NULL, &dwType, (PBYTE)szVersion, &dwSize);
280
281         dwSize = sizeof(dwPatch);
282         dwType = REG_DWORD;
283         RegQueryValueEx (hk, REGVAL_AFS_PATCH, NULL, &dwType, (PBYTE)&dwPatch, &dwSize);
284         RegCloseKey (hk);
285     }
286
287     DWORD dwUserLen =  sizeof(szUser)/sizeof(TCHAR);
288     if (!GetUserNameEx(NameUserPrincipal, szUser, &dwUserLen))
289         GetUserNameEx(NameSamCompatible, szUser, &dwUserLen);
290
291     TCHAR szSource[ cchRESOURCE ];
292     TCHAR szTarget[ cchRESOURCE ];
293
294     GetString (szSource, (dwPatch) ? IDS_TITLE_VERSION : IDS_TITLE_VERSION_NOPATCH);
295     wsprintf (szTarget, szSource, szVersion, dwPatch);
296     SetDlgItemText (hDlg, IDC_TITLE_VERSION, szTarget);
297
298     GetDlgItemText (hDlg, IDC_TITLE_NT, szSource, cchRESOURCE);
299     wsprintf (szTarget, szSource, szUser);
300     SetDlgItemText (hDlg, IDC_TITLE_NT, szTarget);
301 }
302
303
304 void Main_OnCheckMenuRemind (void)
305 {
306    BOOL fRemind = FALSE;
307    lock_ObtainMutex(&g.credsLock);
308    size_t iCreds;
309    for (iCreds = 0; iCreds < g.cCreds; ++iCreds)
310       {
311       if (g.aCreds[ iCreds ].fRemind)
312          fRemind = TRUE;
313       }
314
315    fRemind = !fRemind;
316    for (iCreds = 0; iCreds < g.cCreds; ++iCreds)
317       {
318       if (g.aCreds[ iCreds ].fRemind != fRemind)
319          {
320          g.aCreds[ iCreds ].fRemind = fRemind;
321          SaveRemind (iCreds);
322          }
323       }
324    lock_ReleaseMutex(&g.credsLock);
325
326    // Check the active tab, and fix its checkbox if necessary
327    //
328    HWND hTab = GetDlgItem (g.hMain, IDC_TABS);
329    LPTSTR pszTab = (LPTSTR)GetTabParam (hTab, TabCtrl_GetCurSel(hTab));
330    if (ISCELLTAB(pszTab) && (*pszTab))
331       {
332       HWND hDlg = GetTabChild (hTab);
333       if (hDlg)
334          CheckDlgButton (hDlg, IDC_CREDS_REMIND, fRemind);
335       }
336
337    // Make sure the reminder timer is going
338    //
339    Main_EnableRemindTimer (fRemind);
340 }
341
342
343 void Main_OnRemindTimer (void)
344 {
345    Main_RepopulateTabs (TRUE);
346
347    // See if anything is close to expiring; if so, display a warning
348    // dialog. Make sure we never display a warning more than once.
349    //
350    size_t iExpired;
351    if ((iExpired = Main_FindExpiredCreds()) != -1) {
352        if (InterlockedIncrement (&g.fShowingMessage) != 1) {
353            InterlockedDecrement (&g.fShowingMessage);
354        } else { 
355            char * rootcell = NULL;
356            char   password[PROBE_PASSWORD_LEN+1];
357            struct afsconf_cell cellconfig;
358            BOOL   serverReachable = FALSE;
359            DWORD  code;
360
361            rootcell = (char *)GlobalAlloc(GPTR,MAXCELLCHARS+1);
362            if (!rootcell) 
363                goto cleanup;
364
365            code = KFW_AFS_get_cellconfig(g.aCreds[ iExpired ].szCell, 
366                                          (afsconf_cell*)&cellconfig, rootcell);
367            if (code) 
368                goto cleanup;
369
370            if (KFW_is_available()) {
371                // If we can't use the FSProbe interface we can attempt to forge
372                // a kinit and if we can back an invalid user error we know the
373                // kdc is at least reachable
374                serverReachable = KFW_probe_kdc(&cellconfig);
375            } else {
376                int i;
377
378                for ( i=0 ; i<PROBE_PASSWORD_LEN ; i++ )
379                    password[i] = 'x';
380
381                code = ObtainNewCredentials(rootcell, PROBE_USERNAME, password, TRUE);
382                switch ( code ) {
383                case INTK_BADPW:
384                case KERB_ERR_PRINCIPAL_UNKNOWN:
385                case KERB_ERR_SERVICE_EXP:
386                case RD_AP_TIME:
387                    serverReachable = TRUE;
388                    break;
389                default:
390                    serverReachable = FALSE;
391                }
392            }
393          cleanup:
394            if (rootcell)
395                GlobalFree(rootcell);
396
397            if (serverReachable)
398                ShowObtainCreds (TRUE, g.aCreds[ iExpired ].szCell);
399            else
400                InterlockedDecrement (&g.fShowingMessage);
401        }
402    }
403 }
404
405
406 void Main_OnMouseOver (void)
407 {
408    if ((GetTickCount() - g.tickLastRetest) > cmsecMOUSEOVER)
409       {
410       Main_RepopulateTabs (TRUE);
411       }
412 }
413
414
415 void Main_OnSelectTab (void)
416 {
417    HWND hTab = GetDlgItem (g.hMain, IDC_TABS);
418    size_t iTab = TabCtrl_GetCurSel (hTab);
419
420    HWND hDlgOld = GetTabChild (hTab);
421
422    HWND hDlgNew;
423    if ((hDlgNew = Main_CreateTabDialog (hTab, iTab)) != NULL)
424       ShowWindow (hDlgNew, SW_SHOW);
425
426    if (hDlgOld)
427       DestroyWindow (hDlgOld);
428 }
429
430
431 void Main_OnCheckTerminate (void)
432 {
433     HKEY hk;
434     BOOL bSuccess = FALSE;
435
436     if (RegOpenKeyEx (HKEY_CURRENT_USER, AFSREG_USER_OPENAFS_SUBKEY, 0,
437                       (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &hk) == 0)
438     {
439         DWORD dwSize = sizeof(g.fStartup);
440         DWORD dwType = REG_DWORD;
441         bSuccess = (RegQueryValueEx (hk, TEXT("ShowTrayIcon"), NULL, &dwType, (PBYTE)&g.fStartup, &dwSize) == 0);
442         RegCloseKey (hk);
443     }
444
445     if (bSuccess &&
446         RegOpenKeyEx (HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY, 0,
447                       (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &hk) == 0)
448     {
449         DWORD dwSize = sizeof(g.fStartup);
450         DWORD dwType = REG_DWORD;
451         RegQueryValueEx (hk, TEXT("ShowTrayIcon"), NULL, &dwType, (PBYTE)&g.fStartup, &dwSize);
452         RegCloseKey (hk);
453     }
454
455     Shortcut_FixStartup (cszSHORTCUT_NAME, g.fStartup);
456
457     if (!g.fStartup)
458         Quit();
459 }
460
461
462 HWND Main_CreateTabDialog (HWND hTab, size_t iTab)
463 {
464    HWND hDlg = NULL;
465    LPTSTR psz = NULL;
466
467    TC_ITEM Item;
468    memset (&Item, 0x00, sizeof(Item));
469    Item.mask = TCIF_PARAM;
470    if (TabCtrl_GetItem (hTab, iTab, &Item))
471       {
472       psz = (LPTSTR)(Item.lParam);
473       }
474
475    if (psz == dwTABPARAM_ADVANCED)    // Advanced tab
476       {
477       hDlg = ModelessDialog (IDD_TAB_ADVANCED, hTab, (DLGPROC)Advanced_DlgProc);
478       }
479    else if (psz == dwTABPARAM_MOUNT)  // Mount Points tab
480       {
481       hDlg = ModelessDialog (IDD_TAB_MOUNT, hTab, (DLGPROC)Mount_DlgProc);
482       }
483    else if (ISCELLTAB(psz) && !*psz)  // No Creds tab
484       {
485       hDlg = ModelessDialogParam (IDD_TAB_NOCREDS, hTab, (DLGPROC)Creds_DlgProc, (LPARAM)psz);
486       }
487    else if (ISCELLTAB(psz) && *psz)   // Creds tab for a particular cell
488       {
489       hDlg = ModelessDialogParam (IDD_TAB_CREDS, hTab, (DLGPROC)Creds_DlgProc, (LPARAM)psz);
490       }
491
492    return hDlg;
493 }
494
495 static BOOL Main_ShowMountTab(void)
496 {
497     HKEY hk;
498     BOOL bShow = FALSE;
499     BOOL bSuccess = FALSE;
500
501     if (RegOpenKeyEx (HKEY_CURRENT_USER, AFSREG_USER_OPENAFS_SUBKEY, 0,
502                        (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &hk) == 0)
503     {
504         DWORD dwSize = sizeof(bShow);
505         DWORD dwType = REG_DWORD;
506         bSuccess = (RegQueryValueEx (hk, TEXT("ShowMountTab"), NULL, &dwType, (PBYTE)&bShow, &dwSize) == 0);
507         RegCloseKey (hk);
508     }
509
510     if (!bSuccess &&
511         RegOpenKeyEx (HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY, 0,
512                       (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &hk) == 0)
513     {
514         DWORD dwSize = sizeof(bShow);
515         DWORD dwType = REG_DWORD;
516         bSuccess = (RegQueryValueEx (hk, TEXT("ShowMountTab"), NULL, &dwType, (PBYTE)&bShow, &dwSize) == 0);
517         RegCloseKey (hk);
518     }
519
520     return bShow;
521 }
522
523 void Main_RepopulateTabs (BOOL fDestroyInvalid)
524 {
525    static BOOL fInHere = FALSE;
526    if (!fInHere)
527       {
528       fInHere = TRUE;
529
530       if (IsWindowVisible (g.hMain))
531          fDestroyInvalid = FALSE;
532
533       // First we'll have to look around and see what credentials we currently
534       // have. This call just updates g.aCreds[]; it doesn't do anything else.
535       //
536       (void)GetCurrentCredentials();
537
538       // We want one tab on the main dialog for each g.aCredentials entry,
539       // and one tab for Advanced.
540       //
541       HWND hTab = GetDlgItem (g.hMain, IDC_TABS);
542
543       // Generate a list of the lParams we'll be giving tabs...
544       //
545       LPTSTR *aTabs = NULL;
546       size_t cTabs = 0;
547       size_t iTabOut = 0;
548
549       size_t nCreds = 0;
550       lock_ObtainMutex(&g.credsLock);
551       size_t iCreds;
552       for (iCreds = 0; iCreds < g.cCreds; ++iCreds)
553          {
554          if (g.aCreds[ iCreds ].szCell[0])
555             ++nCreds;
556          }
557       if (!nCreds)
558          {
559          fDestroyInvalid = TRUE;
560          }
561
562       if (!fDestroyInvalid)
563          {
564          int nTabs = TabCtrl_GetItemCount(hTab);
565          for (int iTab = 0; iTab < nTabs; ++iTab)
566             {
567             LPTSTR pszTab = (LPTSTR)GetTabParam (hTab, iTab);
568             if (ISCELLTAB(pszTab) && (*pszTab))
569                {
570                if (REALLOC (aTabs, cTabs, 1+iTabOut, cREALLOC_TABS))
571                   aTabs[ iTabOut++ ] = CloneString(pszTab);
572                }
573             }
574          }
575
576       if (nCreds == 0)
577          {
578          if (REALLOC (aTabs, cTabs, 1+iTabOut, cREALLOC_TABS))
579             aTabs[ iTabOut++ ] = CloneString (TEXT(""));
580          }
581       else for (iCreds = 0; iCreds < g.cCreds; ++iCreds)
582          {
583          if (g.aCreds[ iCreds ].szCell[0])
584             {
585             size_t ii;
586             for (ii = 0; ii < iTabOut; ++ii)
587                {
588                if (!ISCELLTAB (aTabs[ii]))
589                   continue;
590                if (!lstrcmpi (g.aCreds[ iCreds ].szCell, aTabs[ ii ]))
591                   break;
592                }
593             if (ii == iTabOut)
594                {
595                if (REALLOC (aTabs, cTabs, 1+iTabOut, cREALLOC_TABS))
596                   aTabs[ iTabOut++ ] = CloneString (g.aCreds[ iCreds ].szCell);
597                }
598             }
599          }
600       lock_ReleaseMutex(&g.credsLock);
601
602       if (Main_ShowMountTab())
603          {
604          if (REALLOC (aTabs, cTabs, 1+iTabOut, cREALLOC_TABS))
605             aTabs[ iTabOut++ ] = dwTABPARAM_MOUNT;
606          }
607
608 #ifndef UAC_COMPATIBLE
609       if (g.fIsWinNT)
610          {
611          if (REALLOC (aTabs, cTabs, 1+iTabOut, cREALLOC_TABS))
612             aTabs[ iTabOut++ ] = dwTABPARAM_ADVANCED;
613          }
614 #endif
615       // Now erase the current tabs, and re-add new ones. Remember which tab is
616       // currently selected, so we can try to go back to it later.
617       //
618       int iTabSel = 0;
619       if (TabCtrl_GetItemCount(hTab))
620          {
621          LPTSTR pszTabSel = (LPTSTR)GetTabParam (hTab, TabCtrl_GetCurSel(hTab));
622          for (size_t iSel = 0; iSel < iTabOut; ++iSel)
623             {
624             if ((!ISCELLTAB(pszTabSel))  && (!ISCELLTAB(aTabs[iSel])) && (pszTabSel == aTabs[iSel]))
625                iTabSel = iSel;
626             else if (ISCELLTAB(pszTabSel) && ISCELLTAB(aTabs[iSel]) && !lstrcmpi (pszTabSel, aTabs[iSel]))
627                iTabSel = iSel;
628             }
629          }
630
631       int nTabs = TabCtrl_GetItemCount(hTab);
632       for (int iTab = 0; iTab < nTabs; ++iTab)
633          {
634          LPTSTR pszTab = (LPTSTR)GetTabParam (hTab, iTab);
635          if (ISCELLTAB(pszTab))
636             FreeString (pszTab);
637          }
638       TabCtrl_DeleteAllItems (hTab);
639
640       for (size_t ii = 0; ii < iTabOut; ++ii)
641          {
642          TCHAR szTitle[cchRESOURCE];
643          if (aTabs[ii] == dwTABPARAM_ADVANCED)
644             GetString (szTitle, IDS_ADVANCED);
645          else if (aTabs[ii] == dwTABPARAM_MOUNT)
646             GetString (szTitle, IDS_MOUNT);
647          else if ((nCreds <= 1) || (aTabs[ii][0] == TEXT('\0')))
648             GetString (szTitle, IDS_CREDENTIALS);
649          else
650             lstrcpy (szTitle, aTabs[ii]);
651
652          TC_ITEM Item;
653          memset (&Item, 0x00, sizeof(Item));
654          Item.mask = TCIF_PARAM | TCIF_TEXT;
655          Item.pszText = szTitle;
656          Item.cchTextMax = cchRESOURCE;
657          Item.lParam = (LPARAM)(aTabs[ii]);
658
659          TabCtrl_InsertItem (hTab, ii, &Item);
660          }
661
662       if (aTabs != NULL)
663          Free (aTabs);
664
665       TabCtrl_SetCurSel (hTab, iTabSel);
666       Main_OnSelectTab ();
667
668       fInHere = FALSE;
669       }
670 }
671
672
673 void Main_EnableRemindTimer (BOOL fEnable)
674 {
675    static BOOL bEnabled = FALSE;
676
677    if ( fEnable == FALSE && bEnabled == TRUE ) {
678        KillTimer (g.hMain, ID_REMIND_TIMER);
679        bEnabled = FALSE;
680    } else if ( fEnable == TRUE && bEnabled == FALSE ) {
681       SetTimer (g.hMain, ID_REMIND_TIMER, (ULONG)cmsec1MINUTE * cminREMIND_TEST, NULL);
682       bEnabled = TRUE;
683    }
684 }
685
686
687 size_t Main_FindExpiredCreds (void)
688 {
689    size_t retval = (size_t) -1;
690    static bool expirationCheck = false;
691    lock_ObtainMutex(&g.expirationCheckLock);
692    if (expirationCheck) {
693        lock_ReleaseMutex(&g.expirationCheckLock);
694        return -1;
695    }
696    expirationCheck = true;
697    lock_ReleaseMutex(&g.expirationCheckLock);
698
699    if ( KFW_is_available() )
700        KFW_AFS_renew_expiring_tokens();
701    
702    lock_ObtainMutex(&g.credsLock);
703    for (size_t iCreds = 0; iCreds < g.cCreds; ++iCreds)
704       {
705       if (!g.aCreds[ iCreds ].szCell[0])
706          continue;
707       if (!g.aCreds[ iCreds ].fRemind)
708          continue;
709
710       SYSTEMTIME stNow;
711       GetLocalTime (&stNow);
712
713       FILETIME ftNow;
714       SystemTimeToFileTime (&stNow, &ftNow);
715
716       FILETIME ftExpires;
717       SystemTimeToFileTime (&g.aCreds[ iCreds ].stExpires, &ftExpires);
718
719       LONGLONG llNow = (((LONGLONG)ftNow.dwHighDateTime) << 32) + (LONGLONG)(ftNow.dwLowDateTime);
720       LONGLONG llExpires = (((LONGLONG)ftExpires.dwHighDateTime) << 32) + (LONGLONG)(ftExpires.dwLowDateTime);
721
722       llNow /= c100ns1SECOND;
723       llExpires /= c100ns1SECOND;
724
725       if (llExpires <= (llNow + (LONGLONG)cminREMIND_WARN * csec1MINUTE))
726          {
727          if ( KFW_is_available() &&
728               KFW_AFS_renew_token_for_cell(g.aCreds[ iCreds ].szCell) )
729              continue;
730          retval = (size_t) iCreds;
731          break;
732          }
733       }
734    
735    lock_ReleaseMutex(&g.credsLock);
736
737    lock_ObtainMutex(&g.expirationCheckLock);
738    expirationCheck = false;
739    lock_ReleaseMutex(&g.expirationCheckLock);
740
741    return retval;
742 }
743
744
745 BOOL CALLBACK Terminate_DlgProc (HWND hDlg, UINT msg, WPARAM wp, LPARAM lp)
746 {
747    switch (msg)
748       {
749       case WM_INITDIALOG:
750          Terminate_OnInitDialog (hDlg);
751          break;
752
753       case WM_COMMAND:
754          switch (LOWORD(wp))
755             {
756             case IDOK:
757                Terminate_OnOK (hDlg);
758                break;
759
760             case IDCANCEL:
761                EndDialog (hDlg, IDCANCEL);
762                break;
763             }
764          break;
765       }
766
767    return FALSE;
768 }
769
770
771 void Terminate_OnInitDialog (HWND hDlg)
772 {
773    BOOL fPersistent = IsServicePersistent();
774
775    CheckDlgButton (hDlg, IDC_STARTUP, g.fStartup);
776    CheckDlgButton (hDlg, IDC_LEAVE, fPersistent);
777    CheckDlgButton (hDlg, IDC_STOP, !fPersistent);
778 }
779
780
781 void Terminate_OnOK (HWND hDlg)
782 {
783    if (IsServiceRunning())
784       {
785       if (IsDlgButtonChecked (hDlg, IDC_STOP))
786          {
787          SC_HANDLE hManager;
788              if ((hManager = OpenSCManager (NULL, NULL, 
789                                             SC_MANAGER_CONNECT |
790                                             SC_MANAGER_ENUMERATE_SERVICE |
791                                             SC_MANAGER_QUERY_LOCK_STATUS)) != NULL)
792             {
793             SC_HANDLE hService;
794             if ((hService = OpenService (hManager, TEXT("TransarcAFSDaemon"), 
795                                          SERVICE_QUERY_STATUS | SERVICE_START)) != NULL)
796                {
797                SERVICE_STATUS Status;
798                ControlService (hService, SERVICE_CONTROL_STOP, &Status);
799
800                CloseServiceHandle (hService);
801                }
802
803             CloseServiceHandle (hManager);
804             }
805          }
806       }
807
808    g.fStartup = IsDlgButtonChecked (hDlg, IDC_STARTUP);
809
810     HKEY hk;
811     if (RegCreateKeyEx (HKEY_CURRENT_USER, AFSREG_USER_OPENAFS_SUBKEY, 0, NULL, 0,
812                          (IsWow64()?KEY_WOW64_64KEY:0)|KEY_WRITE, NULL, &hk, NULL) == 0)
813     {
814         DWORD dwSize = sizeof(g.fStartup);
815         DWORD dwType = REG_DWORD;
816         RegSetValueEx (hk, TEXT("ShowTrayIcon"), NULL, dwType, (PBYTE)&g.fStartup, dwSize);
817         RegCloseKey (hk);
818     }
819
820    Shortcut_FixStartup (cszSHORTCUT_NAME, g.fStartup);
821
822    Quit();
823    EndDialog (hDlg, IDOK);
824 }
825