/* * Copyright 2000, International Business Machines Corporation and others. * All Rights Reserved. * * This software has been released under the terms of the IBM Public * License. For details, see the LICENSE file in the top-level source * directory or online at http://www.openafs.org/dl/license10.html */ #include #include extern "C" { #include #include #include #include #include "ipaddrchg.h" } #include "afscreds.h" #define SECURITY_WIN32 1 #include /* * DEFINITIONS ________________________________________________________________ * */ #define ID_REMIND_TIMER 1000 #define ID_SERVICE_TIMER 1001 #define cREALLOC_TABS 4 #define dwTABPARAM_MOUNT (LPTSTR)0 #define dwTABPARAM_ADVANCED (LPTSTR)1 #define ISCELLTAB(_psz) ((HIWORD((LONG)(_psz))) != 0) /* * PROTOTYPES _________________________________________________________________ * */ void Main_OnInitDialog (HWND hDlg); void Main_OnCheckMenuRemind (void); void Main_OnRemindTimer (void); void Main_OnMouseOver (void); void Main_OnSelectTab (void); void Main_OnCheckTerminate (void); HWND Main_CreateTabDialog (HWND hTab, size_t iTab); BOOL CALLBACK Terminate_DlgProc (HWND hDlg, UINT msg, WPARAM wp, LPARAM lp); void Terminate_OnInitDialog (HWND hDlg); void Terminate_OnOK (HWND hDlg); /* * ROUTINES ___________________________________________________________________ * */ BOOL CALLBACK Main_DlgProc (HWND hDlg, UINT msg, WPARAM wp, LPARAM lp) { static UINT msgCheckTerminate = 0; if (msgCheckTerminate == 0) msgCheckTerminate = RegisterWindowMessage (TEXT("AfsCredsCheckTerminate")); if (msg == msgCheckTerminate) { Main_OnCheckTerminate(); } else switch (msg) { case WM_INITDIALOG: g.hMain = hDlg; Main_OnInitDialog (hDlg); break; case WM_DESTROY: Creds_CloseLibraries(); ChangeTrayIcon (NIM_DELETE); break; case WM_ACTIVATEAPP: if (wp) { Main_RepopulateTabs (FALSE); } break; case WM_COMMAND: switch (LOWORD(wp)) { case IDOK: case IDCANCEL: Main_Show (FALSE); break; case M_ACTIVATE: if (g.fIsWinNT || IsServiceRunning()) { if (!lp) // Got here from "/show" parameter? switch tabs. { HWND hTab = GetDlgItem (g.hMain, IDC_TABS); TabCtrl_SetCurSel (hTab, 0); Main_OnSelectTab(); } Main_Show (TRUE); } else { Message (MB_ICONHAND, IDS_UNCONFIG_TITLE_95, IDS_UNCONFIG_DESC_95); } break; case M_TERMINATE: #ifndef UAC_COMPATIBLE if (g.fIsWinNT && IsServiceRunning()) ModalDialog (IDD_TERMINATE, NULL, (DLGPROC)Terminate_DlgProc); else #endif if (g.fIsWinNT) ModalDialog (IDD_TERMINATE_SMALL, NULL, (DLGPROC)Terminate_DlgProc); else // (!g.fIsWinNT) ModalDialog (IDD_TERMINATE_SMALL_95, NULL, (DLGPROC)Terminate_DlgProc); break; case M_TERMINATE_NOW: Quit(); break; case M_REMIND: Main_OnCheckMenuRemind(); break; } break; case WM_TIMER: Main_OnRemindTimer(); break; case WM_NOTIFY: switch (((NMHDR*)lp)->code) { case TCN_SELCHANGE: Main_OnSelectTab(); break; } break; case WM_TRAYICON: switch (lp) { case WM_LBUTTONDOWN: if (IsServiceRunning() || !IsServiceConfigured()) Main_Show (TRUE); else if (!g.fIsWinNT) Message (MB_ICONHAND, IDS_UNCONFIG_TITLE_95, IDS_UNCONFIG_DESC_95); else ShowStartupWizard(); break; case WM_RBUTTONDOWN: HMENU hm; if ((hm = TaLocale_LoadMenu (MENU_TRAYICON)) != 0) { POINT pt; GetCursorPos(&pt); HMENU hmDummy = CreateMenu(); InsertMenu (hmDummy, 0, MF_POPUP, (UINT)hm, NULL); BOOL fRemind = FALSE; lock_ObtainMutex(&g.credsLock); for (size_t iCreds = 0; iCreds < g.cCreds; ++iCreds) { if (g.aCreds[ iCreds ].fRemind) fRemind = TRUE; } lock_ReleaseMutex(&g.credsLock); CheckMenuItem (hm, M_REMIND, MF_BYCOMMAND | ((fRemind) ? MF_CHECKED : MF_UNCHECKED)); SetForegroundWindow(hDlg); TrackPopupMenu (GetSubMenu (hmDummy, 0), TPM_RIGHTALIGN | TPM_RIGHTBUTTON, pt.x, pt.y, NULL, hDlg, NULL); PostMessage(hDlg, WM_NULL, 0, 0); DestroyMenu (hmDummy); } break; case WM_MOUSEMOVE: Main_OnMouseOver(); break; } break; case WM_OBTAIN_TOKENS: if ( InterlockedIncrement (&g.fShowingMessage) != 1 ) InterlockedDecrement (&g.fShowingMessage); else ShowObtainCreds (wp, (char *)lp); GlobalFree((void *)lp); break; case WM_START_SERVICE: { SC_HANDLE hManager; if ((hManager = OpenSCManager ( NULL, NULL, SC_MANAGER_CONNECT | SC_MANAGER_ENUMERATE_SERVICE | SC_MANAGER_QUERY_LOCK_STATUS)) != NULL) { SC_HANDLE hService; if ((hService = OpenService ( hManager, TEXT("TransarcAFSDaemon"), SERVICE_QUERY_STATUS | SERVICE_START)) != NULL) { if (StartService (hService, 0, 0)) TestAndDoMapShare(SERVICE_START_PENDING); if ( KFW_is_available() && KFW_AFS_wait_for_service_start() ) { #ifdef USE_MS2MIT KFW_import_windows_lsa(); #endif /* USE_MS2MIT */ KFW_AFS_renew_tokens_for_all_cells(); } CloseServiceHandle (hService); } CloseServiceHandle (hManager); } if (KFW_AFS_wait_for_service_start()) ObtainTokensFromUserIfNeeded(g.hMain); } break; } return FALSE; } void Main_Show (BOOL fShow) { if (fShow) { ShowWindow (g.hMain, SW_SHOW); SetWindowPos (g.hMain, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); SetForegroundWindow (g.hMain); } else { SetWindowPos (g.hMain, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_HIDEWINDOW); } } void Main_OnInitDialog (HWND hDlg) { if (!g.fIsWinNT) { TCHAR szTitle[256]; GetString (szTitle, IDS_TITLE_95); SetWindowText (hDlg, szTitle); } TCHAR szVersion[256]; DWORD dwPatch = 0; TCHAR szUser[1024]; GetString (szVersion, IDS_UNKNOWN); GetString (szUser, IDS_UNKNOWN); HKEY hk; if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, AFSREG_CLT_SW_VERSION_SUBKEY, 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &hk) == 0) { DWORD dwSize = sizeof(szVersion); DWORD dwType = REG_SZ; RegQueryValueEx (hk, REGVAL_AFS_VERSION, NULL, &dwType, (PBYTE)szVersion, &dwSize); dwSize = sizeof(dwPatch); dwType = REG_DWORD; RegQueryValueEx (hk, REGVAL_AFS_PATCH, NULL, &dwType, (PBYTE)&dwPatch, &dwSize); RegCloseKey (hk); } DWORD dwUserLen = sizeof(szUser)/sizeof(TCHAR); if (!GetUserNameEx(NameUserPrincipal, szUser, &dwUserLen)) GetUserNameEx(NameSamCompatible, szUser, &dwUserLen); TCHAR szSource[ cchRESOURCE ]; TCHAR szTarget[ cchRESOURCE ]; GetString (szSource, (dwPatch) ? IDS_TITLE_VERSION : IDS_TITLE_VERSION_NOPATCH); wsprintf (szTarget, szSource, szVersion, dwPatch); SetDlgItemText (hDlg, IDC_TITLE_VERSION, szTarget); GetDlgItemText (hDlg, IDC_TITLE_NT, szSource, cchRESOURCE); wsprintf (szTarget, szSource, szUser); SetDlgItemText (hDlg, IDC_TITLE_NT, szTarget); } void Main_OnCheckMenuRemind (void) { BOOL fRemind = FALSE; lock_ObtainMutex(&g.credsLock); size_t iCreds; for (iCreds = 0; iCreds < g.cCreds; ++iCreds) { if (g.aCreds[ iCreds ].fRemind) fRemind = TRUE; } fRemind = !fRemind; for (iCreds = 0; iCreds < g.cCreds; ++iCreds) { if (g.aCreds[ iCreds ].fRemind != fRemind) { g.aCreds[ iCreds ].fRemind = fRemind; SaveRemind (iCreds); } } lock_ReleaseMutex(&g.credsLock); // Check the active tab, and fix its checkbox if necessary // HWND hTab = GetDlgItem (g.hMain, IDC_TABS); LPTSTR pszTab = (LPTSTR)GetTabParam (hTab, TabCtrl_GetCurSel(hTab)); if (ISCELLTAB(pszTab) && (*pszTab)) { HWND hDlg = GetTabChild (hTab); if (hDlg) CheckDlgButton (hDlg, IDC_CREDS_REMIND, fRemind); } // Make sure the reminder timer is going // Main_EnableRemindTimer (fRemind); } void Main_OnRemindTimer (void) { Main_RepopulateTabs (TRUE); // See if anything is close to expiring; if so, display a warning // dialog. Make sure we never display a warning more than once. // size_t iExpired; if ((iExpired = Main_FindExpiredCreds()) != -1) { if (InterlockedIncrement (&g.fShowingMessage) != 1) { InterlockedDecrement (&g.fShowingMessage); } else { char * rootcell = NULL; char password[PROBE_PASSWORD_LEN+1]; struct afsconf_cell cellconfig; BOOL serverReachable = FALSE; DWORD code; rootcell = (char *)GlobalAlloc(GPTR,MAXCELLCHARS+1); if (!rootcell) goto cleanup; code = KFW_AFS_get_cellconfig(g.aCreds[ iExpired ].szCell, (afsconf_cell*)&cellconfig, rootcell); if (code) goto cleanup; if (KFW_is_available()) { // If we can't use the FSProbe interface we can attempt to forge // a kinit and if we can back an invalid user error we know the // kdc is at least reachable serverReachable = KFW_probe_kdc(&cellconfig); } else { int i; for ( i=0 ; i cmsecMOUSEOVER) { Main_RepopulateTabs (TRUE); } } void Main_OnSelectTab (void) { HWND hTab = GetDlgItem (g.hMain, IDC_TABS); size_t iTab = TabCtrl_GetCurSel (hTab); HWND hDlgOld = GetTabChild (hTab); HWND hDlgNew; if ((hDlgNew = Main_CreateTabDialog (hTab, iTab)) != NULL) ShowWindow (hDlgNew, SW_SHOW); if (hDlgOld) DestroyWindow (hDlgOld); } void Main_OnCheckTerminate (void) { HKEY hk; BOOL bSuccess = FALSE; if (RegOpenKeyEx (HKEY_CURRENT_USER, AFSREG_USER_OPENAFS_SUBKEY, 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &hk) == 0) { DWORD dwSize = sizeof(g.fStartup); DWORD dwType = REG_DWORD; bSuccess = (RegQueryValueEx (hk, TEXT("ShowTrayIcon"), NULL, &dwType, (PBYTE)&g.fStartup, &dwSize) == 0); RegCloseKey (hk); } if (bSuccess && RegOpenKeyEx (HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY, 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &hk) == 0) { DWORD dwSize = sizeof(g.fStartup); DWORD dwType = REG_DWORD; RegQueryValueEx (hk, TEXT("ShowTrayIcon"), NULL, &dwType, (PBYTE)&g.fStartup, &dwSize); RegCloseKey (hk); } Shortcut_FixStartup (cszSHORTCUT_NAME, g.fStartup); if (!g.fStartup) Quit(); } HWND Main_CreateTabDialog (HWND hTab, size_t iTab) { HWND hDlg = NULL; LPTSTR psz = NULL; TC_ITEM Item; memset (&Item, 0x00, sizeof(Item)); Item.mask = TCIF_PARAM; if (TabCtrl_GetItem (hTab, iTab, &Item)) { psz = (LPTSTR)(Item.lParam); } if (psz == dwTABPARAM_ADVANCED) // Advanced tab { hDlg = ModelessDialog (IDD_TAB_ADVANCED, hTab, (DLGPROC)Advanced_DlgProc); } else if (psz == dwTABPARAM_MOUNT) // Mount Points tab { hDlg = ModelessDialog (IDD_TAB_MOUNT, hTab, (DLGPROC)Mount_DlgProc); } else if (ISCELLTAB(psz) && !*psz) // No Creds tab { hDlg = ModelessDialogParam (IDD_TAB_NOCREDS, hTab, (DLGPROC)Creds_DlgProc, (LPARAM)psz); } else if (ISCELLTAB(psz) && *psz) // Creds tab for a particular cell { hDlg = ModelessDialogParam (IDD_TAB_CREDS, hTab, (DLGPROC)Creds_DlgProc, (LPARAM)psz); } return hDlg; } static BOOL Main_ShowMountTab(void) { HKEY hk; BOOL bShow = FALSE; BOOL bSuccess = FALSE; if (RegOpenKeyEx (HKEY_CURRENT_USER, AFSREG_USER_OPENAFS_SUBKEY, 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &hk) == 0) { DWORD dwSize = sizeof(bShow); DWORD dwType = REG_DWORD; bSuccess = (RegQueryValueEx (hk, TEXT("ShowMountTab"), NULL, &dwType, (PBYTE)&bShow, &dwSize) == 0); RegCloseKey (hk); } if (!bSuccess && RegOpenKeyEx (HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY, 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &hk) == 0) { DWORD dwSize = sizeof(bShow); DWORD dwType = REG_DWORD; bSuccess = (RegQueryValueEx (hk, TEXT("ShowMountTab"), NULL, &dwType, (PBYTE)&bShow, &dwSize) == 0); RegCloseKey (hk); } return bShow; } void Main_RepopulateTabs (BOOL fDestroyInvalid) { static BOOL fInHere = FALSE; if (!fInHere) { fInHere = TRUE; if (IsWindowVisible (g.hMain)) fDestroyInvalid = FALSE; // First we'll have to look around and see what credentials we currently // have. This call just updates g.aCreds[]; it doesn't do anything else. // (void)GetCurrentCredentials(); // We want one tab on the main dialog for each g.aCredentials entry, // and one tab for Advanced. // HWND hTab = GetDlgItem (g.hMain, IDC_TABS); // Generate a list of the lParams we'll be giving tabs... // LPTSTR *aTabs = NULL; size_t cTabs = 0; size_t iTabOut = 0; size_t nCreds = 0; lock_ObtainMutex(&g.credsLock); size_t iCreds; for (iCreds = 0; iCreds < g.cCreds; ++iCreds) { if (g.aCreds[ iCreds ].szCell[0]) ++nCreds; } if (!nCreds) { fDestroyInvalid = TRUE; } if (!fDestroyInvalid) { int nTabs = TabCtrl_GetItemCount(hTab); for (int iTab = 0; iTab < nTabs; ++iTab) { LPTSTR pszTab = (LPTSTR)GetTabParam (hTab, iTab); if (ISCELLTAB(pszTab) && (*pszTab)) { if (REALLOC (aTabs, cTabs, 1+iTabOut, cREALLOC_TABS)) aTabs[ iTabOut++ ] = CloneString(pszTab); } } } if (nCreds == 0) { if (REALLOC (aTabs, cTabs, 1+iTabOut, cREALLOC_TABS)) aTabs[ iTabOut++ ] = CloneString (TEXT("")); } else for (iCreds = 0; iCreds < g.cCreds; ++iCreds) { if (g.aCreds[ iCreds ].szCell[0]) { size_t ii; for (ii = 0; ii < iTabOut; ++ii) { if (!ISCELLTAB (aTabs[ii])) continue; if (!lstrcmpi (g.aCreds[ iCreds ].szCell, aTabs[ ii ])) break; } if (ii == iTabOut) { if (REALLOC (aTabs, cTabs, 1+iTabOut, cREALLOC_TABS)) aTabs[ iTabOut++ ] = CloneString (g.aCreds[ iCreds ].szCell); } } } lock_ReleaseMutex(&g.credsLock); if (Main_ShowMountTab()) { if (REALLOC (aTabs, cTabs, 1+iTabOut, cREALLOC_TABS)) aTabs[ iTabOut++ ] = dwTABPARAM_MOUNT; } #ifndef UAC_COMPATIBLE if (g.fIsWinNT) { if (REALLOC (aTabs, cTabs, 1+iTabOut, cREALLOC_TABS)) aTabs[ iTabOut++ ] = dwTABPARAM_ADVANCED; } #endif // Now erase the current tabs, and re-add new ones. Remember which tab is // currently selected, so we can try to go back to it later. // int iTabSel = 0; if (TabCtrl_GetItemCount(hTab)) { LPTSTR pszTabSel = (LPTSTR)GetTabParam (hTab, TabCtrl_GetCurSel(hTab)); for (size_t iSel = 0; iSel < iTabOut; ++iSel) { if ((!ISCELLTAB(pszTabSel)) && (!ISCELLTAB(aTabs[iSel])) && (pszTabSel == aTabs[iSel])) iTabSel = iSel; else if (ISCELLTAB(pszTabSel) && ISCELLTAB(aTabs[iSel]) && !lstrcmpi (pszTabSel, aTabs[iSel])) iTabSel = iSel; } } int nTabs = TabCtrl_GetItemCount(hTab); for (int iTab = 0; iTab < nTabs; ++iTab) { LPTSTR pszTab = (LPTSTR)GetTabParam (hTab, iTab); if (ISCELLTAB(pszTab)) FreeString (pszTab); } TabCtrl_DeleteAllItems (hTab); for (size_t ii = 0; ii < iTabOut; ++ii) { TCHAR szTitle[cchRESOURCE]; if (aTabs[ii] == dwTABPARAM_ADVANCED) GetString (szTitle, IDS_ADVANCED); else if (aTabs[ii] == dwTABPARAM_MOUNT) GetString (szTitle, IDS_MOUNT); else if ((nCreds <= 1) || (aTabs[ii][0] == TEXT('\0'))) GetString (szTitle, IDS_CREDENTIALS); else lstrcpy (szTitle, aTabs[ii]); TC_ITEM Item; memset (&Item, 0x00, sizeof(Item)); Item.mask = TCIF_PARAM | TCIF_TEXT; Item.pszText = szTitle; Item.cchTextMax = cchRESOURCE; Item.lParam = (LPARAM)(aTabs[ii]); TabCtrl_InsertItem (hTab, ii, &Item); } if (aTabs != NULL) Free (aTabs); TabCtrl_SetCurSel (hTab, iTabSel); Main_OnSelectTab (); fInHere = FALSE; } } void Main_EnableRemindTimer (BOOL fEnable) { static BOOL bEnabled = FALSE; if ( fEnable == FALSE && bEnabled == TRUE ) { KillTimer (g.hMain, ID_REMIND_TIMER); bEnabled = FALSE; } else if ( fEnable == TRUE && bEnabled == FALSE ) { SetTimer (g.hMain, ID_REMIND_TIMER, (ULONG)cmsec1MINUTE * cminREMIND_TEST, NULL); bEnabled = TRUE; } } size_t Main_FindExpiredCreds (void) { size_t retval = (size_t) -1; static bool expirationCheck = false; lock_ObtainMutex(&g.expirationCheckLock); if (expirationCheck) { lock_ReleaseMutex(&g.expirationCheckLock); return -1; } expirationCheck = true; lock_ReleaseMutex(&g.expirationCheckLock); if ( KFW_is_available() ) { #ifdef USE_MS2MIT KFW_import_windows_lsa(); #endif /* USE_MS2MIT */ KFW_AFS_renew_expiring_tokens(); } lock_ObtainMutex(&g.credsLock); for (size_t iCreds = 0; iCreds < g.cCreds; ++iCreds) { if (!g.aCreds[ iCreds ].szCell[0]) continue; if (!g.aCreds[ iCreds ].fRemind) continue; SYSTEMTIME stNow; GetLocalTime (&stNow); FILETIME ftNow; SystemTimeToFileTime (&stNow, &ftNow); FILETIME ftExpires; SystemTimeToFileTime (&g.aCreds[ iCreds ].stExpires, &ftExpires); LONGLONG llNow = (((LONGLONG)ftNow.dwHighDateTime) << 32) + (LONGLONG)(ftNow.dwLowDateTime); LONGLONG llExpires = (((LONGLONG)ftExpires.dwHighDateTime) << 32) + (LONGLONG)(ftExpires.dwLowDateTime); llNow /= c100ns1SECOND; llExpires /= c100ns1SECOND; if (llExpires <= (llNow + (LONGLONG)cminREMIND_WARN * csec1MINUTE)) { if ( KFW_is_available() && KFW_AFS_renew_token_for_cell(g.aCreds[ iCreds ].szCell) ) continue; retval = (size_t) iCreds; break; } } lock_ReleaseMutex(&g.credsLock); lock_ObtainMutex(&g.expirationCheckLock); expirationCheck = false; lock_ReleaseMutex(&g.expirationCheckLock); return retval; } BOOL CALLBACK Terminate_DlgProc (HWND hDlg, UINT msg, WPARAM wp, LPARAM lp) { switch (msg) { case WM_INITDIALOG: Terminate_OnInitDialog (hDlg); break; case WM_COMMAND: switch (LOWORD(wp)) { case IDOK: Terminate_OnOK (hDlg); break; case IDCANCEL: EndDialog (hDlg, IDCANCEL); break; } break; } return FALSE; } void Terminate_OnInitDialog (HWND hDlg) { BOOL fPersistent = IsServicePersistent(); CheckDlgButton (hDlg, IDC_STARTUP, g.fStartup); CheckDlgButton (hDlg, IDC_LEAVE, fPersistent); CheckDlgButton (hDlg, IDC_STOP, !fPersistent); } void Terminate_OnOK (HWND hDlg) { if (IsServiceRunning()) { if (IsDlgButtonChecked (hDlg, IDC_STOP)) { SC_HANDLE hManager; if ((hManager = OpenSCManager (NULL, NULL, SC_MANAGER_CONNECT | SC_MANAGER_ENUMERATE_SERVICE | SC_MANAGER_QUERY_LOCK_STATUS)) != NULL) { SC_HANDLE hService; if ((hService = OpenService (hManager, TEXT("TransarcAFSDaemon"), SERVICE_QUERY_STATUS | SERVICE_START)) != NULL) { SERVICE_STATUS Status; ControlService (hService, SERVICE_CONTROL_STOP, &Status); CloseServiceHandle (hService); } CloseServiceHandle (hManager); } } } g.fStartup = IsDlgButtonChecked (hDlg, IDC_STARTUP); HKEY hk; if (RegCreateKeyEx (HKEY_CURRENT_USER, AFSREG_USER_OPENAFS_SUBKEY, 0, NULL, 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_WRITE, NULL, &hk, NULL) == 0) { DWORD dwSize = sizeof(g.fStartup); DWORD dwType = REG_DWORD; RegSetValueEx (hk, TEXT("ShowTrayIcon"), NULL, dwType, (PBYTE)&g.fStartup, dwSize); RegCloseKey (hk); } Shortcut_FixStartup (cszSHORTCUT_NAME, g.fStartup); Quit(); EndDialog (hDlg, IDOK); }