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