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