From caef99b21536d9e8c2f9c637fcf020b4e082db5d Mon Sep 17 00:00:00 2001 From: Sam Hartman Date: Wed, 28 Sep 2011 21:02:14 +0000 Subject: [PATCH] Initial import of KFW 3.2.2 Leash32 code Signed-off-by: Alexey Melnikov git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@25278 dc483132-0cff-0310-8789-dd5450dbe970 --- src/windows/leash/AfsProperties.cpp | 123 + src/windows/leash/AfsProperties.h | 56 + src/windows/leash/CLeashDragListBox.cpp | 215 ++ src/windows/leash/CLeashDragListBox.h | 45 + .../leash/Krb4AddToDomainRealmList.cpp | 107 + src/windows/leash/Krb4AddToDomainRealmList.h | 73 + src/windows/leash/Krb4AddToRealmHostList.cpp | 121 + src/windows/leash/Krb4AddToRealmHostList.h | 75 + .../leash/Krb4DomainRealmMaintenance.cpp | 268 ++ .../leash/Krb4DomainRealmMaintenance.h | 76 + src/windows/leash/Krb4EditDomainRealmList.cpp | 147 + src/windows/leash/Krb4EditDomainRealmList.h | 77 + src/windows/leash/Krb4EditRealmHostList.cpp | 193 ++ src/windows/leash/Krb4EditRealmHostList.h | 79 + src/windows/leash/Krb4Properties.cpp | 390 +++ src/windows/leash/Krb4Properties.h | 138 + .../leash/Krb4RealmHostMaintenance.cpp | 373 +++ src/windows/leash/Krb4RealmHostMaintenance.h | 86 + src/windows/leash/Krb5Properties.cpp | 644 ++++ src/windows/leash/Krb5Properties.h | 172 + src/windows/leash/KrbAddHostServer.cpp | 77 + src/windows/leash/KrbAddHostServer.h | 53 + src/windows/leash/KrbAddRealm.cpp | 88 + src/windows/leash/KrbAddRealm.h | 66 + src/windows/leash/KrbConfigOptions.cpp | 679 ++++ src/windows/leash/KrbConfigOptions.h | 89 + .../leash/KrbDomainRealmMaintenance.cpp | 435 +++ src/windows/leash/KrbDomainRealmMaintenance.h | 59 + src/windows/leash/KrbEditHostServer.cpp | 97 + src/windows/leash/KrbEditHostServer.h | 69 + src/windows/leash/KrbEditRealm.cpp | 99 + src/windows/leash/KrbEditRealm.h | 75 + src/windows/leash/KrbMiscConfigOpt.cpp | 1012 ++++++ src/windows/leash/KrbMiscConfigOpt.h | 173 + src/windows/leash/KrbProperties.cpp | 102 + src/windows/leash/KrbProperties.h | 89 + src/windows/leash/KrbRealmHostMaintenance.cpp | 1047 ++++++ src/windows/leash/KrbRealmHostMaintenance.h | 102 + src/windows/leash/Leash.cpp | 1618 ++++++++++ src/windows/leash/Leash.h | 156 + src/windows/leash/Leash.rc | 999 ++++++ src/windows/leash/LeashAboutBox.cpp | 363 +++ src/windows/leash/LeashAboutBox.h | 81 + src/windows/leash/LeashControlPanel.cpp | 43 + src/windows/leash/LeashControlPanel.h | 46 + src/windows/leash/LeashDebugWindow.cpp | 187 ++ src/windows/leash/LeashDebugWindow.h | 78 + src/windows/leash/LeashDoc.cpp | 94 + src/windows/leash/LeashDoc.h | 66 + src/windows/leash/LeashFileDialog.cpp | 75 + src/windows/leash/LeashFileDialog.h | 57 + src/windows/leash/LeashFrame.cpp | 119 + src/windows/leash/LeashFrame.h | 50 + src/windows/leash/LeashMessageBox.cpp | 83 + src/windows/leash/LeashMessageBox.h | 70 + src/windows/leash/LeashProperties.cpp | 202 ++ src/windows/leash/LeashProperties.h | 78 + src/windows/leash/LeashView.cpp | 2810 +++++++++++++++++ src/windows/leash/LeashView.h | 253 ++ src/windows/leash/Lglobals.cpp | 148 + src/windows/leash/Lglobals.h | 272 ++ src/windows/leash/MainFrm.cpp | 465 +++ src/windows/leash/MainFrm.h | 92 + src/windows/leash/StdAfx.cpp | 5 + src/windows/leash/StdAfx.h | 27 + src/windows/leash/VSroutines.c | 64 + src/windows/leash/reminder.h | 12 + src/windows/leash/res/Leash.ico | Bin 0 -> 25214 bytes src/windows/leash/res/Leash.rc2 | 14 + src/windows/leash/res/Leash2.ico | Bin 0 -> 766 bytes src/windows/leash/res/Leash_Doc.ico | Bin 0 -> 25214 bytes src/windows/leash/res/Leash_tickets_green.ico | Bin 0 -> 25214 bytes .../leash/res/Leash_tickets_orange.ico | Bin 0 -> 25214 bytes src/windows/leash/res/Leash_tickets_out.ico | Bin 0 -> 25214 bytes src/windows/leash/res/Leash_tickets_red.ico | Bin 0 -> 25214 bytes src/windows/leash/res/Leash_tkt_green.ico | Bin 0 -> 25214 bytes src/windows/leash/res/Leash_tkt_orange.ico | Bin 0 -> 25214 bytes src/windows/leash/res/Leash_tkt_red.ico | Bin 0 -> 25214 bytes src/windows/leash/res/Leash_toolbar.bmp | Bin 0 -> 1270 bytes src/windows/leash/res/Leash_user_green.ico | Bin 0 -> 25214 bytes src/windows/leash/res/Leash_user_orange.ico | Bin 0 -> 25214 bytes src/windows/leash/res/Leash_user_out.ico | Bin 0 -> 25214 bytes src/windows/leash/res/Leash_user_red.ico | Bin 0 -> 25214 bytes src/windows/leash/res/address.ico | Bin 0 -> 25214 bytes src/windows/leash/res/cursor1.cur | Bin 0 -> 326 bytes src/windows/leash/res/destroy.ico | Bin 0 -> 2862 bytes src/windows/leash/res/destroy_disabled.ico | Bin 0 -> 2862 bytes src/windows/leash/res/doghead_green.ico | Bin 0 -> 25214 bytes src/windows/leash/res/doghead_grey.ico | Bin 0 -> 25214 bytes src/windows/leash/res/doghead_orange.ico | Bin 0 -> 25214 bytes src/windows/leash/res/doghead_red.ico | Bin 0 -> 25214 bytes src/windows/leash/res/encryption.ico | Bin 0 -> 25214 bytes src/windows/leash/res/import.ico | Bin 0 -> 2862 bytes src/windows/leash/res/import_disabled.ico | Bin 0 -> 2862 bytes src/windows/leash/res/key.ico | Bin 0 -> 25214 bytes src/windows/leash/res/new.ico | Bin 0 -> 2862 bytes src/windows/leash/res/new_disabled.ico | Bin 0 -> 198 bytes src/windows/leash/res/password.ico | Bin 0 -> 2862 bytes src/windows/leash/res/password_disabled.ico | Bin 0 -> 198 bytes src/windows/leash/res/refresh.ico | Bin 0 -> 2862 bytes src/windows/leash/res/refresh_disabled.ico | Bin 0 -> 198 bytes src/windows/leash/res/renew.ico | Bin 0 -> 2862 bytes src/windows/leash/res/renew_disabled.ico | Bin 0 -> 2862 bytes src/windows/leash/res/sync.ico | Bin 0 -> 2862 bytes src/windows/leash/res/sync_disabled.ico | Bin 0 -> 198 bytes src/windows/leash/resource.h | 336 ++ 106 files changed, 16832 insertions(+) create mode 100644 src/windows/leash/AfsProperties.cpp create mode 100644 src/windows/leash/AfsProperties.h create mode 100644 src/windows/leash/CLeashDragListBox.cpp create mode 100644 src/windows/leash/CLeashDragListBox.h create mode 100644 src/windows/leash/Krb4AddToDomainRealmList.cpp create mode 100644 src/windows/leash/Krb4AddToDomainRealmList.h create mode 100644 src/windows/leash/Krb4AddToRealmHostList.cpp create mode 100644 src/windows/leash/Krb4AddToRealmHostList.h create mode 100644 src/windows/leash/Krb4DomainRealmMaintenance.cpp create mode 100644 src/windows/leash/Krb4DomainRealmMaintenance.h create mode 100644 src/windows/leash/Krb4EditDomainRealmList.cpp create mode 100644 src/windows/leash/Krb4EditDomainRealmList.h create mode 100644 src/windows/leash/Krb4EditRealmHostList.cpp create mode 100644 src/windows/leash/Krb4EditRealmHostList.h create mode 100644 src/windows/leash/Krb4Properties.cpp create mode 100644 src/windows/leash/Krb4Properties.h create mode 100644 src/windows/leash/Krb4RealmHostMaintenance.cpp create mode 100644 src/windows/leash/Krb4RealmHostMaintenance.h create mode 100644 src/windows/leash/Krb5Properties.cpp create mode 100644 src/windows/leash/Krb5Properties.h create mode 100644 src/windows/leash/KrbAddHostServer.cpp create mode 100644 src/windows/leash/KrbAddHostServer.h create mode 100644 src/windows/leash/KrbAddRealm.cpp create mode 100644 src/windows/leash/KrbAddRealm.h create mode 100644 src/windows/leash/KrbConfigOptions.cpp create mode 100644 src/windows/leash/KrbConfigOptions.h create mode 100644 src/windows/leash/KrbDomainRealmMaintenance.cpp create mode 100644 src/windows/leash/KrbDomainRealmMaintenance.h create mode 100644 src/windows/leash/KrbEditHostServer.cpp create mode 100644 src/windows/leash/KrbEditHostServer.h create mode 100644 src/windows/leash/KrbEditRealm.cpp create mode 100644 src/windows/leash/KrbEditRealm.h create mode 100644 src/windows/leash/KrbMiscConfigOpt.cpp create mode 100644 src/windows/leash/KrbMiscConfigOpt.h create mode 100644 src/windows/leash/KrbProperties.cpp create mode 100644 src/windows/leash/KrbProperties.h create mode 100644 src/windows/leash/KrbRealmHostMaintenance.cpp create mode 100644 src/windows/leash/KrbRealmHostMaintenance.h create mode 100644 src/windows/leash/Leash.cpp create mode 100644 src/windows/leash/Leash.h create mode 100644 src/windows/leash/Leash.rc create mode 100644 src/windows/leash/LeashAboutBox.cpp create mode 100644 src/windows/leash/LeashAboutBox.h create mode 100644 src/windows/leash/LeashControlPanel.cpp create mode 100644 src/windows/leash/LeashControlPanel.h create mode 100644 src/windows/leash/LeashDebugWindow.cpp create mode 100644 src/windows/leash/LeashDebugWindow.h create mode 100644 src/windows/leash/LeashDoc.cpp create mode 100644 src/windows/leash/LeashDoc.h create mode 100644 src/windows/leash/LeashFileDialog.cpp create mode 100644 src/windows/leash/LeashFileDialog.h create mode 100644 src/windows/leash/LeashFrame.cpp create mode 100644 src/windows/leash/LeashFrame.h create mode 100644 src/windows/leash/LeashMessageBox.cpp create mode 100644 src/windows/leash/LeashMessageBox.h create mode 100644 src/windows/leash/LeashProperties.cpp create mode 100644 src/windows/leash/LeashProperties.h create mode 100644 src/windows/leash/LeashView.cpp create mode 100644 src/windows/leash/LeashView.h create mode 100644 src/windows/leash/Lglobals.cpp create mode 100644 src/windows/leash/Lglobals.h create mode 100644 src/windows/leash/MainFrm.cpp create mode 100644 src/windows/leash/MainFrm.h create mode 100644 src/windows/leash/StdAfx.cpp create mode 100644 src/windows/leash/StdAfx.h create mode 100644 src/windows/leash/VSroutines.c create mode 100644 src/windows/leash/reminder.h create mode 100644 src/windows/leash/res/Leash.ico create mode 100644 src/windows/leash/res/Leash.rc2 create mode 100644 src/windows/leash/res/Leash2.ico create mode 100644 src/windows/leash/res/Leash_Doc.ico create mode 100644 src/windows/leash/res/Leash_tickets_green.ico create mode 100644 src/windows/leash/res/Leash_tickets_orange.ico create mode 100644 src/windows/leash/res/Leash_tickets_out.ico create mode 100644 src/windows/leash/res/Leash_tickets_red.ico create mode 100644 src/windows/leash/res/Leash_tkt_green.ico create mode 100644 src/windows/leash/res/Leash_tkt_orange.ico create mode 100644 src/windows/leash/res/Leash_tkt_red.ico create mode 100644 src/windows/leash/res/Leash_toolbar.bmp create mode 100644 src/windows/leash/res/Leash_user_green.ico create mode 100644 src/windows/leash/res/Leash_user_orange.ico create mode 100644 src/windows/leash/res/Leash_user_out.ico create mode 100644 src/windows/leash/res/Leash_user_red.ico create mode 100644 src/windows/leash/res/address.ico create mode 100644 src/windows/leash/res/cursor1.cur create mode 100644 src/windows/leash/res/destroy.ico create mode 100644 src/windows/leash/res/destroy_disabled.ico create mode 100644 src/windows/leash/res/doghead_green.ico create mode 100644 src/windows/leash/res/doghead_grey.ico create mode 100644 src/windows/leash/res/doghead_orange.ico create mode 100644 src/windows/leash/res/doghead_red.ico create mode 100644 src/windows/leash/res/encryption.ico create mode 100644 src/windows/leash/res/import.ico create mode 100644 src/windows/leash/res/import_disabled.ico create mode 100644 src/windows/leash/res/key.ico create mode 100644 src/windows/leash/res/new.ico create mode 100644 src/windows/leash/res/new_disabled.ico create mode 100644 src/windows/leash/res/password.ico create mode 100644 src/windows/leash/res/password_disabled.ico create mode 100644 src/windows/leash/res/refresh.ico create mode 100644 src/windows/leash/res/refresh_disabled.ico create mode 100644 src/windows/leash/res/renew.ico create mode 100644 src/windows/leash/res/renew_disabled.ico create mode 100644 src/windows/leash/res/sync.ico create mode 100644 src/windows/leash/res/sync_disabled.ico create mode 100644 src/windows/leash/resource.h diff --git a/src/windows/leash/AfsProperties.cpp b/src/windows/leash/AfsProperties.cpp new file mode 100644 index 000000000..dabcdfd91 --- /dev/null +++ b/src/windows/leash/AfsProperties.cpp @@ -0,0 +1,123 @@ +// AfsProperties.cpp : implementation file +// + +#include "stdafx.h" +#include "leash.h" +#include "AfsProperties.h" + +/* This should be set to something other than 0 or 1 (the valid values) */ +#define INVALID_AFS_STATUS_VALUE 2 +#define IS_INVALID_AFS_STATUS_VALUE(x) ((x != 0) && (x != 1)) + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CAfsProperties dialog + + +CAfsProperties::CAfsProperties(CWnd* pParent /*=NULL*/) + : CDialog(CAfsProperties::IDD, pParent) +{ + m_newAfsStatus = 0; + m_oldAfsStatus = 0; + + //{{AFX_DATA_INIT(CAfsProperties) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT +} + + +void CAfsProperties::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CAfsProperties) + // NOTE: the ClassWizard will add DDX an3d DDV calls here + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CAfsProperties, CDialog) + //{{AFX_MSG_MAP(CAfsProperties) + ON_BN_CLICKED(IDC_BUTTON_AFS_PROPERTIES, OnButtonAfsProperties) + ON_BN_CLICKED(IDC_RADIO_AFS_ENABLED, OnRadioAfsEnabled) + ON_BN_CLICKED(IDC_RADIO_AFS_DISABLED, OnRadioAfsDisabled) + ON_COMMAND(ID_HELP, OnHelp) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CAfsProperties message handlers + +BOOL +CAfsProperties::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // Get State* of Destroy Tickets On Exit + m_pApp = AfxGetApp(); + + m_oldAfsStatus = m_pApp->GetProfileInt("Settings", "AfsStatus", + INVALID_AFS_STATUS_VALUE); + if (IS_INVALID_AFS_STATUS_VALUE(m_oldAfsStatus)) + { + // set the default + m_pApp->WriteProfileInt("Settings", "AfsStatus", 1); + m_oldAfsStatus = 1; + } + + m_newAfsStatus = m_oldAfsStatus; + + int enabled = (m_oldAfsStatus != 0); + if (enabled) + CheckDlgButton(IDC_RADIO_AFS_ENABLED, TRUE); + else + CheckDlgButton(IDC_RADIO_AFS_DISABLED, TRUE); + + return TRUE; +} + +void CAfsProperties::OnButtonAfsProperties() +{ + if (32 >= (LRESULT) ShellExecute (NULL, NULL, "AFS_CONFIG.EXE", NULL, + NULL, SW_SHOW)) + { + MessageBox("Can't find file AFS_CONFIG.EXE", "Error", MB_OK); + } +} + +void CAfsProperties::OnOK() +{ + if (m_oldAfsStatus != m_newAfsStatus) + { + if (!m_pApp->WriteProfileInt("Settings", "AfsStatus", m_newAfsStatus)) + { + MessageBox("There was an error putting your entry into the " + "Registry!", "Error", MB_OK); + } + } + + CDialog::OnOK(); +} + +void CAfsProperties::OnRadioAfsEnabled() +{ + m_newAfsStatus = 1; +} + +void CAfsProperties::OnRadioAfsDisabled() +{ + m_newAfsStatus = 0; +} + +void CAfsProperties::OnHelp() +{ +#ifdef CALL_HTMLHELP + AfxGetApp()->HtmlHelp(HID_AFS_PROPERTIES_COMMAND); +#else + AfxGetApp()->WinHelp(HID_AFS_PROPERTIES_COMMAND); +#endif +} diff --git a/src/windows/leash/AfsProperties.h b/src/windows/leash/AfsProperties.h new file mode 100644 index 000000000..2c6e1edd7 --- /dev/null +++ b/src/windows/leash/AfsProperties.h @@ -0,0 +1,56 @@ +#if !defined(AFX_AFSPROPERTIES_H__FD135601_2FCB_11D3_96A2_0000861B8A3C__INCLUDED_) +#define AFX_AFSPROPERTIES_H__FD135601_2FCB_11D3_96A2_0000861B8A3C__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// AfsProperties.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CAfsProperties dialog + +class CAfsProperties : public CDialog +{ +// Construction +private: + UINT m_newAfsStatus; + UINT m_oldAfsStatus; + CWinApp *m_pApp; + +public: + CAfsProperties(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CAfsProperties) + enum { IDD = IDD_AFS_PROPERTIES }; + // NOTE: the ClassWizard will add data members here + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CAfsProperties) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CAfsProperties) + virtual BOOL OnInitDialog(); + afx_msg void OnButtonAfsProperties(); + virtual void OnOK(); + afx_msg void OnRadioAfsEnabled(); + afx_msg void OnRadioAfsDisabled(); + afx_msg void OnHelp(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_AFSPROPERTIES_H__FD135601_2FCB_11D3_96A2_0000861B8A3C__INCLUDED_) diff --git a/src/windows/leash/CLeashDragListBox.cpp b/src/windows/leash/CLeashDragListBox.cpp new file mode 100644 index 000000000..205889b86 --- /dev/null +++ b/src/windows/leash/CLeashDragListBox.cpp @@ -0,0 +1,215 @@ +#include "stdafx.h" +#include "CLeashDragListBox.h" +#include "leash.h" +#include "lglobals.h" + +///////////////////////////////////////////////////////////////////////////// +// CLeashDragListBox + +//IMPLEMENT_DYNAMIC(CLeashDragListBox, CDragListBox) + +CLeashDragListBox::CLeashDragListBox() + :CDragListBox() +{ + +} + +CLeashDragListBox::~CLeashDragListBox() +{ + DestroyWindow(); +} + +void CLeashDragListBox::initOtherListbox(CPropertyPage* pPage, CListBox* pOtherListBox) +{ + m_pPage = pPage; + m_pOtherListBox = pOtherListBox; +} + + +void CLeashDragListBox::PreSubclassWindow() +{ + ASSERT(::IsWindow(m_hWnd)); + ASSERT((GetStyle() & (LBS_MULTIPLESEL|LBS_SORT)) == 0); + MakeDragList(m_hWnd); +} + +BOOL CLeashDragListBox::BeginDrag(CPoint pt) +{ + m_nLast = -1; + DrawInsert(ItemFromPt(pt)); + return TRUE; +} + +void CLeashDragListBox::CancelDrag(CPoint) +{ + DrawInsert(-1); +} + +UINT CLeashDragListBox::Dragging(CPoint pt) +{ + int nIndex = ItemFromPt(pt, FALSE); // don't allow scrolling just yet + DrawInsert(nIndex); + ItemFromPt(pt); + return (nIndex == LB_ERR) ? DL_STOPCURSOR : DL_MOVECURSOR; +} + +void CLeashDragListBox::Dropped(int nSrcIndex, CPoint pt) +{ + ASSERT(!(GetStyle() & (LBS_OWNERDRAWFIXED|LBS_OWNERDRAWVARIABLE)) || + (GetStyle() & LBS_HASSTRINGS)); + + DrawInsert(-1); + int nDestIndex = ItemFromPt(pt); + + if (nSrcIndex == -1 || nDestIndex == -1) + return; + if (nDestIndex == nSrcIndex || nDestIndex == nSrcIndex+1) + return; //didn't move + CString str1, str2; + DWORD dwData; + GetText(nSrcIndex, str1); + GetText(nDestIndex, str2); + dwData = GetItemData(nSrcIndex); + DeleteString(nSrcIndex); + if (nSrcIndex < nDestIndex) + nDestIndex--; + nDestIndex = InsertString(nDestIndex, str1); + SetItemData(nDestIndex, dwData); + SetCurSel(nDestIndex); + + // Save new order of items to profile linklist + char theSection[REALM_SZ + 1]; + const char* adminServer[] = {"realms", theSection, ADMIN_SERVER, NULL}; + const char* Section[] = {"realms", theSection, NULL}; + const char** adminServ = adminServer; + const char** section = Section; + const char* valueSection[] = {"realms", theSection, "kdc", NULL}; + const char** valueSec = valueSection; + CString theValue; + CHAR hostServer[MAX_HSTNM]; + + if (LB_ERR == m_pOtherListBox->GetText(m_pOtherListBox->GetCurSel(), theSection)) + ASSERT(0); + + long retval = pprofile_rename_section(CLeashApp::m_krbv5_profile, + section, NULL); + if (retval) + { + MessageBox("Dropped::There is on error, profile will not be saved!!!\ + \nIf this error persist, contact your administrator.", + "Leash", MB_OK); + return; + } + + retval = pprofile_add_relation(CLeashApp::m_krbv5_profile, + section, NULL); + if (retval) + { + MessageBox("Dropped::There is on error, profile will not be saved!!!\ + \nIf this error persist, contact your administrator.", + "Leash", MB_OK); + return; + } + + for (INT maxItems = GetCount(), item = 0; item < maxItems; item++) + { + GetText(item, hostServer); + //strcpy(hostServer, theValue); + + if (strstr(hostServer, ADMIN_SERVER)) + { + char* pAdmin = strchr(hostServer, ' '); + if (pAdmin) + *pAdmin = 0; + else + ASSERT(0); + + retval = pprofile_add_relation(CLeashApp::m_krbv5_profile, + adminServ, hostServer); + if (retval) + { + MessageBox("Dropped::There is on error, profile will not be saved!!!\ + \nIf this error persist, contact your administrator.", + "Leash", MB_OK); + return; + } + } + + retval = pprofile_add_relation(CLeashApp::m_krbv5_profile, + valueSec, hostServer); + if (retval) + { + MessageBox("Dropped::There is on error, profile will not be saved!!!\ + \nIf this error persist, contact your administrator.", + "Leash", MB_OK); + return; + } + } + + m_pPage->SetModified(TRUE); +} + +void CLeashDragListBox::DrawInsert(int nIndex) +{ + if (m_nLast != nIndex) + { + DrawSingle(m_nLast); + DrawSingle(nIndex); + m_nLast = nIndex; + } +} + +void CLeashDragListBox::DrawSingle(int nIndex) +{ + if (nIndex == -1) + return; + CBrush* pBrush = CDC::GetHalftoneBrush(); + CRect rect; + GetClientRect(&rect); + CRgn rgn; + rgn.CreateRectRgnIndirect(&rect); + + CDC* pDC = GetDC(); + // prevent drawing outside of listbox + // this can happen at the top of the listbox since the listbox's DC is the + // parent's DC + pDC->SelectClipRgn(&rgn); + + GetItemRect(nIndex, &rect); + rect.bottom = rect.top+2; + rect.top -= 2; + CBrush* pBrushOld = pDC->SelectObject(pBrush); + //draw main line + pDC->PatBlt(rect.left, rect.top, rect.Width(), rect.Height(), PATINVERT); + + pDC->SelectObject(pBrushOld); + ReleaseDC(pDC); +} + +/* +BOOL CLeashDragListBox::OnChildNotify(UINT nMessage, WPARAM wParam, LPARAM lParam, LRESULT* pResult) +{ + if (nMessage != m_nMsgDragList) + return CListBox::OnChildNotify(nMessage, wParam, lParam, pResult); + + ASSERT(pResult != NULL); + LPDRAGLISTINFO pInfo = (LPDRAGLISTINFO)lParam; + ASSERT(pInfo != NULL); + switch (pInfo->uNotification) + { + case DL_BEGINDRAG: + *pResult = BeginDrag(pInfo->ptCursor); + break; + case DL_CANCELDRAG: + CancelDrag(pInfo->ptCursor); + break; + case DL_DRAGGING: + *pResult = Dragging(pInfo->ptCursor); + break; + case DL_DROPPED: + Dropped(GetCurSel(), pInfo->ptCursor); + break; + } + return TRUE; +} +*/ diff --git a/src/windows/leash/CLeashDragListBox.h b/src/windows/leash/CLeashDragListBox.h new file mode 100644 index 000000000..02179b274 --- /dev/null +++ b/src/windows/leash/CLeashDragListBox.h @@ -0,0 +1,45 @@ +#ifndef _LEASH_DRAGLISTBOX +#define _LEASH_DRAGLISTBOX + +///////////////////////////////////////////////////////////////////////////// +// CLeashDragListBox + +//#include "AFXCMN.h" + +class CLeashDragListBox : public CDragListBox +{ + //DECLARE_DYNAMIC(CDragListBoxCLeashDragListBox) + + CListBox* m_pOtherListBox; + CPropertyPage* m_pPage; + +// Constructors +public: + CLeashDragListBox(); + void initOtherListbox(CPropertyPage* pPage, CListBox* pOtherListBox); + +// Attributes + //int ItemFromPt(CPoint pt, BOOL bAutoScroll = TRUE) const; + +// Operations + virtual void DrawInsert(int nItem); + +// Overridables + virtual BOOL BeginDrag(CPoint pt); + virtual void CancelDrag(CPoint pt); + virtual UINT Dragging(CPoint pt); + virtual void Dropped(int nSrcIndex, CPoint pt); + +// Implementation +public: + int m_nLast; + void DrawSingle(int nIndex); + virtual void PreSubclassWindow(); + virtual ~CLeashDragListBox(); +protected: + //virtual BOOL OnChildNotify(UINT, WPARAM, LPARAM, LRESULT*); +}; + +//class CLeashDragListBox; + +#endif // _LEASH_DRAGLISTBOX diff --git a/src/windows/leash/Krb4AddToDomainRealmList.cpp b/src/windows/leash/Krb4AddToDomainRealmList.cpp new file mode 100644 index 000000000..9f119bdbe --- /dev/null +++ b/src/windows/leash/Krb4AddToDomainRealmList.cpp @@ -0,0 +1,107 @@ +// File: Krb4AddToDomainRealmList.cpp +// By: Arthur David Leather +// Created: 12/02/98 +// Copyright @1998 Massachusetts Institute of Technology - All rights reserved. +// Description: CPP file for Krb4AddToDomainRealmList.h. Contains variables and functions +// for Kerberos Four Properties +// +// History: +// +// MM/DD/YY Inits Description of Change +// 12/02/98 ADL Original +// ************************************************************************************** + + +#include "stdafx.h" +#include "leash.h" +#include "Krb4AddToDomainRealmList.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CKrb4AddToDomainRealmList dialog + + +CKrb4AddToDomainRealmList::CKrb4AddToDomainRealmList(CWnd* pParent /*=NULL*/) + : CDialog(CKrb4AddToDomainRealmList::IDD, pParent) +{ + m_newRealm = _T(""); + m_newDomainHost = _T(""); + m_startup = TRUE; + + + //{{AFX_DATA_INIT(CKrb4AddToDomainRealmList) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT +} + + +void CKrb4AddToDomainRealmList::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CKrb4AddToDomainRealmList) + // NOTE: the ClassWizard will add DDX and DDV calls here + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CKrb4AddToDomainRealmList, CDialog) + //{{AFX_MSG_MAP(CKrb4AddToDomainRealmList) + ON_WM_SHOWWINDOW() + ON_EN_CHANGE(IDC_EDIT_DOMAINHOSTNAME, OnChangeEditDomainhostname) + ON_EN_CHANGE(IDC_EDIT_DOMAINREALMNAME, OnChangeEditDomainrealmname) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CKrb4AddToDomainRealmList message handlers + +void CKrb4AddToDomainRealmList::OnChangeEditDomainhostname() +{ + if (!m_startup) + GetDlgItemText(IDC_EDIT_DOMAINHOSTNAME, m_newDomainHost); +} + +void CKrb4AddToDomainRealmList::OnChangeEditDomainrealmname() +{ + if (!m_startup) + GetDlgItemText(IDC_EDIT_DOMAINREALMNAME, m_newRealm); +} + +void CKrb4AddToDomainRealmList::OnOK() +{ + //if (m_newRealm.IsEmpty) + + m_newRealm.TrimLeft(); + m_newRealm.TrimRight(); + m_newDomainHost.TrimLeft(); + m_newDomainHost.TrimRight(); + + if (m_newRealm.IsEmpty() || m_newDomainHost.IsEmpty()) + { // stay + MessageBox("OnOK::Both Realm and Domain-Host fields must be filled in!", + "Leash", MB_OK); + } + else if (-1 != m_newRealm.Find(' ') || -1 != m_newDomainHost.Find(' ')) + { // stay + MessageBox("OnOK::Illegal space found!", "Leash", MB_OK); + } + else + CDialog::OnOK(); // exit +} + +void CKrb4AddToDomainRealmList::OnCancel() +{ + + CDialog::OnCancel(); +} + +void CKrb4AddToDomainRealmList::OnShowWindow(BOOL bShow, UINT nStatus) +{ + CDialog::OnShowWindow(bShow, nStatus); + m_startup = FALSE; +} diff --git a/src/windows/leash/Krb4AddToDomainRealmList.h b/src/windows/leash/Krb4AddToDomainRealmList.h new file mode 100644 index 000000000..8148c0d1f --- /dev/null +++ b/src/windows/leash/Krb4AddToDomainRealmList.h @@ -0,0 +1,73 @@ +// File: Krb4AddToDomainRealmList.h +// By: Arthur David Leather +// Created: 12/02/98 +// Copyright @1998 Massachusetts Institute of Technology - All rights reserved. +// Description: H file for Krb4AddToDomainRealmList.cpp. Contains variables and functions +// for Kerberos Four Properties +// +// History: +// +// MM/DD/YY Inits Description of Change +// 12/02/98 ADL Original +// ************************************************************************************** + + +#if !defined(AFX_KRB4ADDTODOMAINREALMLIST_H__F4D41683_96A4_11D2_94E2_0000861B8A3C__INCLUDED_) +#define AFX_KRB4ADDTODOMAINREALMLIST_H__F4D41683_96A4_11D2_94E2_0000861B8A3C__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// Krb4AddToDomainRealmList.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CKrb4AddToDomainRealmList dialog + +class CKrb4AddToDomainRealmList : public CDialog +{ +// Construction +private: + CString m_newRealm; + CString m_newDomainHost; + BOOL m_newAdmin; + BOOL m_startup; + +public: + CKrb4AddToDomainRealmList(CWnd* pParent = NULL); // standard constructor + + CString GetNewRealm() {return m_newRealm;} + CString GetNewDomainHost() {return m_newDomainHost;} + +// Dialog Data + //{{AFX_DATA(CKrb4AddToDomainRealmList) + enum { IDD = IDD_KRB4_ADD_DOMAINREALMNAME }; + // NOTE: the ClassWizard will add data members here + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CKrb4AddToDomainRealmList) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CKrb4AddToDomainRealmList) + virtual void OnOK(); + virtual void OnCancel(); + afx_msg void OnShowWindow(BOOL bShow, UINT nStatus); + afx_msg void OnChangeEditDomainhostname(); + afx_msg void OnChangeEditDomainrealmname(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_KRB4ADDTODOMAINREALMLIST_H__F4D41683_96A4_11D2_94E2_0000861B8A3C__INCLUDED_) diff --git a/src/windows/leash/Krb4AddToRealmHostList.cpp b/src/windows/leash/Krb4AddToRealmHostList.cpp new file mode 100644 index 000000000..e012aea02 --- /dev/null +++ b/src/windows/leash/Krb4AddToRealmHostList.cpp @@ -0,0 +1,121 @@ +// File: Krb4AddToRealmHostList.cpp +// By: Arthur David Leather +// Created: 12/02/98 +// Copyright @1998 Massachusetts Institute of Technology - All rights reserved. +// Description: CPP file for Krb4AddToRealmHostList.h. Contains variables and functions +// for Kerberos Four Properties +// +// History: +// +// MM/DD/YY Inits Description of Change +// 12/02/98 ADL Original +// ************************************************************************************** + + +#include "stdafx.h" +#include "leash.h" +#include "Krb4AddToRealmHostList.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CKrb4AddToRealmHostList dialog + + +CKrb4AddToRealmHostList::CKrb4AddToRealmHostList(CWnd* pParent /*=NULL*/) +: CDialog(CKrb4AddToRealmHostList::IDD, pParent) +{ + m_newRealm = _T(""); + m_newHost = _T(""); + m_newAdmin = TRUE; + m_startup = TRUE; + + //{{AFX_DATA_INIT(CKrb4AddToRealmHostList) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT +} + + +void CKrb4AddToRealmHostList::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CKrb4AddToRealmHostList) + // NOTE: the ClassWizard will add DDX and DDV calls here + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CKrb4AddToRealmHostList, CDialog) + //{{AFX_MSG_MAP(CKrb4AddToRealmHostList) + ON_EN_CHANGE(IDC_EDIT_DEFAULT_REALM, OnChangeEditDefaultRealm) + ON_EN_CHANGE(IDC_EDIT_REALM_HOSTNAME, OnChangeEditRealmHostname) + ON_WM_SHOWWINDOW() + ON_BN_CLICKED(IDC_RADIO_ADMIN_SERVER, OnRadioAdminServer) + ON_BN_CLICKED(IDC_RADIO_NO_ADMIN_SERVER, OnRadioNoAdminServer) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CKrb4AddToRealmHostList message handlers + +void CKrb4AddToRealmHostList::OnShowWindow(BOOL bShow, UINT nStatus) +{ + CDialog::OnShowWindow(bShow, nStatus); + m_startup = FALSE; +} + +void CKrb4AddToRealmHostList::OnChangeEditDefaultRealm() +{ + if (!m_startup) + GetDlgItemText(IDC_EDIT_DEFAULT_REALM, m_newRealm); +} + +void CKrb4AddToRealmHostList::OnChangeEditRealmHostname() +{ + if (!m_startup) + GetDlgItemText(IDC_EDIT_REALM_HOSTNAME, m_newHost); +} + +void CKrb4AddToRealmHostList::OnRadioAdminServer() +{ + m_newAdmin = TRUE; +} + +void CKrb4AddToRealmHostList::OnRadioNoAdminServer() +{ + m_newAdmin = FALSE; +} + +void CKrb4AddToRealmHostList::OnOK() +{ + m_newRealm.TrimLeft(); + m_newRealm.TrimRight(); + m_newHost.TrimLeft(); + m_newHost.TrimRight(); + + if (m_newRealm.IsEmpty() || m_newHost.IsEmpty()) + { // stay + MessageBox("OnOK::Both Realm and Host fields must be filled in!", + "Leash", MB_OK); + } + else if (-1 != m_newRealm.Find(' ') || -1 != m_newHost.Find(' ')) + { // stay + MessageBox("OnOK::Illegal space found!", "Leash", MB_OK); + } + + else + CDialog::OnOK(); // exit +} + +BOOL CKrb4AddToRealmHostList::OnInitDialog() +{ + CDialog::OnInitDialog(); + + CheckRadioButton(IDC_RADIO_ADMIN_SERVER, IDC_RADIO_NO_ADMIN_SERVER, IDC_RADIO_ADMIN_SERVER); + + return TRUE; +} diff --git a/src/windows/leash/Krb4AddToRealmHostList.h b/src/windows/leash/Krb4AddToRealmHostList.h new file mode 100644 index 000000000..1c813670b --- /dev/null +++ b/src/windows/leash/Krb4AddToRealmHostList.h @@ -0,0 +1,75 @@ +// ************************************************************************************** +// File: Krb4AddToRealmHostList.h +// By: Arthur David Leather +// Created: 12/02/98 +// Copyright @1998 Massachusetts Institute of Technology - All rights reserved. +// Description: H file for Krb4AddToRealmHostList.cpp Contains variables and functions +// for Kerberos Four Properties +// +// History: +// +// MM/DD/YY Inits Description of Change +// 12/02/98 ADL Original +// ************************************************************************************** + + +#if !defined(AFX_ADDTOREALMHOSTLIST_H__26A1E1F3_9117_11D2_94D0_0000861B8A3C__INCLUDED_) +#define AFX_ADDTOREALMHOSTLIST_H__26A1E1F3_9117_11D2_94D0_0000861B8A3C__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// AddToRealmHostList.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CKrb4AddToRealmHostList dialog + +class CKrb4AddToRealmHostList : public CDialog +{ +// Construction + CString m_newRealm; + CString m_newHost; + BOOL m_newAdmin; + BOOL m_startup; + +public: + CKrb4AddToRealmHostList(CWnd* pParent = NULL); // standard constructor + + CString GetNewRealm() {return m_newRealm;} + CString GetNewHost() {return m_newHost;} + BOOL GetNewAdmin() {return m_newAdmin;} + +// Dialog Data + //{{AFX_DATA(CKrb4AddToRealmHostList) + enum { IDD = IDD_KRB4_ADD_REALM }; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CKrb4AddToRealmHostList) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CKrb4AddToRealmHostList) + afx_msg void OnChangeEditDefaultRealm(); + afx_msg void OnChangeEditRealmHostname(); + afx_msg void OnShowWindow(BOOL bShow, UINT nStatus); + afx_msg void OnRadioAdminServer(); + afx_msg void OnRadioNoAdminServer(); + virtual void OnOK(); + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_ADDTOREALMHOSTLIST_H__26A1E1F3_9117_11D2_94D0_0000861B8A3C__INCLUDED_) diff --git a/src/windows/leash/Krb4DomainRealmMaintenance.cpp b/src/windows/leash/Krb4DomainRealmMaintenance.cpp new file mode 100644 index 000000000..466b31a4b --- /dev/null +++ b/src/windows/leash/Krb4DomainRealmMaintenance.cpp @@ -0,0 +1,268 @@ +// ************************************************************************************** +// File: Krb4DomainRealmMaintenance.cpp +// By: Arthur David Leather +// Created: 12/02/98 +// Copyright @1998 Massachusetts Institute of Technology - All rights reserved. +// Description: CPP file for Krb4DomainRealmMaintenance.h. Contains variables and functions +// for Kerberos Four Properties +// +// History: +// +// MM/DD/YY Inits Description of Change +// 12/02/98 ADL Original +// ************************************************************************************** + +#include "stdafx.h" +#include "leash.h" +#include "KrbProperties.h" +#include "Krb4Properties.h" +#include "Krb4AddToDomainRealmList.h" +#include "Krb4EditDomainRealmList.h" +#include "Krb4DomainRealmMaintenance.h" +#include "lglobals.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CKrb4DomainRealmMaintenance dialog + + +IMPLEMENT_DYNCREATE(CKrb4DomainRealmMaintenance, CPropertyPage) + +CKrb4DomainRealmMaintenance::CKrb4DomainRealmMaintenance() : + CPropertyPage(CKrb4DomainRealmMaintenance ::IDD) +{ + m_defectiveLines = 0; +} + +CKrb4DomainRealmMaintenance::~CKrb4DomainRealmMaintenance() +{ +} + +void CKrb4DomainRealmMaintenance::DoDataExchange(CDataExchange* pDX) +{ + CPropertyPage::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CKrb4DomainRealmMaintenance) + DDX_Control(pDX, IDC_LIST_DOMAINREALM, m_realmDomainList); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CKrb4DomainRealmMaintenance, CPropertyPage) + //{{AFX_MSG_MAP(CKrb4DomainRealmMaintenance) + ON_BN_CLICKED(IDC_BUTTON_REALM_HOST_ADD, OnButtonRealmHostAdd) + ON_BN_CLICKED(ID_BUTTON_REALM_HOST_REMOVE, OnButtonRealmHostRemove) + ON_BN_CLICKED(IDC_BUTTON_REALM_HOST_EDIT, OnButtonRealmHostEdit) + ON_LBN_SELCHANGE(IDC_LIST_DOMAINREALM, OnSelchangeListDomainrealm) + ON_LBN_DBLCLK(IDC_LIST_DOMAINREALM, OnDblclkListDomainrealm) + ON_BN_CLICKED(IDC_BUTTON_HOSTMAINT_HELP, OnButtonHostmaintHelp) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CKrb4DomainRealmMaintenance message handlers + +BOOL CKrb4DomainRealmMaintenance::OnApply() +{ + CStdioFile krbrealmCon; + if (!krbrealmCon.Open(CKrbProperties::m_krbrealmPath, CFile::modeCreate | + CFile::modeNoTruncate | + CFile::modeReadWrite)) + { + LeashErrorBox("OnApply::Can't open Configuration File", + CKrbProperties::m_krbrealmPath); + return TRUE; + } + + memset(lineBuf, '\0', sizeof(lineBuf)); + krbrealmCon.SetLength(0); + krbrealmCon.WriteString(lineBuf); + for (INT maxItems = m_realmDomainList.GetCount(), item = 0; item < maxItems; item++) + { + memset(lineBuf, '\0', sizeof(lineBuf)); + if (!m_realmDomainList.GetText(item, lineBuf)) + break; + + krbrealmCon.WriteString(lineBuf); + krbrealmCon.WriteString("\n"); + } + + krbrealmCon.Close(); + + return TRUE; +} + +BOOL CKrb4DomainRealmMaintenance::OnInitDialog() +{ + CPropertyPage::OnInitDialog(); + CStdioFile krbrealmCon; + + if (!krbrealmCon.Open(CKrbProperties::m_krbrealmPath, CFile::modeReadWrite)) + { // can't find file, so lets set some defaults + CString defaultStr; + defaultStr.Format("%s %s", "MIT.EDU", KRB_REALM); + m_realmDomainList.AddString(defaultStr); + } + else + { + while (TRUE) + { + if (!krbrealmCon.ReadString(lineBuf, sizeof(lineBuf))) + break; + + *(lineBuf + strlen(lineBuf) - 1) = 0; + + if (!strchr(lineBuf, ' ') && !strchr(lineBuf, '\t')) + { // found a defective line + m_defectiveLines++; + } + + if (LB_ERR == m_realmDomainList.AddString(lineBuf)) + { + LeashErrorBox("OnInitDialog::Can't read Configuration File", + CKrbProperties::m_krbrealmPath); + krbrealmCon.Close(); + return FALSE; + } + } + + krbrealmCon.Close(); + } + + m_realmDomainList.SetCurSel(0); + + if (!m_realmDomainList.GetCount()) + { + GetDlgItem(ID_BUTTON_REALM_HOST_REMOVE)->EnableWindow(FALSE); + GetDlgItem(IDC_BUTTON_REALM_HOST_EDIT)->EnableWindow(FALSE); + } + + return TRUE; +} + +void CKrb4DomainRealmMaintenance::OnButtonRealmHostAdd() +{ + CKrb4AddToDomainRealmList addToDomainRealmList; + if (IDOK == addToDomainRealmList.DoModal()) + { + if (addToDomainRealmList.GetNewRealm().IsEmpty()) + ASSERT(0); + + CString newLine; + newLine = addToDomainRealmList.GetNewDomainHost() + " " + addToDomainRealmList.GetNewRealm(); + + // We don't want duplicate items in Listbox + CString ckDups; + for (INT item = 0; item < m_realmDomainList.GetCount(); item++) + { + m_realmDomainList.GetText(item, ckDups); + if (0 == ckDups.CompareNoCase(newLine)) + { // found duplicate item in Listbox + LeashErrorBox("OnButtonRealmHostAdd::Found a Duplicate Item\nCan't add to List", + ckDups); + return; + } + } + + m_realmDomainList.InsertString(0, newLine); + m_realmDomainList.SetCurSel(0); + SetModified(TRUE); + + if (1 == m_realmDomainList.GetCount()) + { + GetDlgItem(ID_BUTTON_REALM_HOST_REMOVE)->EnableWindow();GetDlgItem(IDC_BUTTON_REALM_HOST_EDIT)->EnableWindow(); + } + } +} + +void CKrb4DomainRealmMaintenance::OnButtonRealmHostRemove() +{ + if (IDYES != AfxMessageBox("Your about to remove an item from the list!\n\nContinue?", + MB_YESNO)) + return; + + INT curSel = m_realmDomainList.GetCurSel(); + m_realmDomainList.DeleteString(curSel); // Single Sel Listbox + + if (-1 == m_realmDomainList.SetCurSel(curSel)) + m_realmDomainList.SetCurSel(curSel - 1); + + if (!m_realmDomainList.GetCount()) + { + GetDlgItem(ID_BUTTON_REALM_HOST_REMOVE)->EnableWindow(FALSE); + GetDlgItem(IDC_BUTTON_REALM_HOST_EDIT)->EnableWindow(FALSE); + } + + SetModified(TRUE); +} + +void CKrb4DomainRealmMaintenance::OnButtonRealmHostEdit() +{ + INT selItemIndex = m_realmDomainList.GetCurSel(); + LPSTR pSelItem = new char[m_realmDomainList.GetTextLen(selItemIndex) + 1]; + if (!pSelItem) + ASSERT(0); + + CString selItem; + m_realmDomainList.GetText(selItemIndex, selItem); + strcpy(pSelItem, selItem); + + CKrb4EditDomainRealmList editDomainRealmList(pSelItem); + delete [] pSelItem; + + if (IDOK == editDomainRealmList.DoModal()) + { + CString editedItem = editDomainRealmList.GetEditedItem(); + if (0 != selItem.CompareNoCase(editedItem) && + LB_ERR != m_realmDomainList.FindStringExact(-1, editedItem)) + { + LeashErrorBox("OnButtonRealmHostEdit::Found a Duplicate!\nCan't add to List", + editedItem); + + return; + } + + m_realmDomainList.DeleteString(selItemIndex); + m_realmDomainList.InsertString(selItemIndex, editDomainRealmList.GetEditedItem()); + m_realmDomainList.SetCurSel(selItemIndex); + SetModified(TRUE); + } +} + +void CKrb4DomainRealmMaintenance::OnSelchangeListDomainrealm() +{ + //SetModified(TRUE); +} + +void CKrb4DomainRealmMaintenance::OnDblclkListDomainrealm() +{ + OnButtonRealmHostEdit(); +} + +BOOL CKrb4DomainRealmMaintenance::PreTranslateMessage(MSG* pMsg) +{ + if (m_defectiveLines) + { + if (m_defectiveLines == 1) + LeashErrorBox("Found a defective entry in file", + CKrbProperties::m_krbrealmPath, "Warning"); + else if (m_defectiveLines > 1) + LeashErrorBox("Found more then one defective entry in file", + CKrbProperties::m_krbrealmPath, "Warning"); + } + + m_defectiveLines = 0; + return CPropertyPage::PreTranslateMessage(pMsg); +} + + + + +void CKrb4DomainRealmMaintenance::OnButtonHostmaintHelp() +{ + MessageBox("No Help Available!", "Leash", MB_OK); +} diff --git a/src/windows/leash/Krb4DomainRealmMaintenance.h b/src/windows/leash/Krb4DomainRealmMaintenance.h new file mode 100644 index 000000000..6bdba77c3 --- /dev/null +++ b/src/windows/leash/Krb4DomainRealmMaintenance.h @@ -0,0 +1,76 @@ +// ************************************************************************************** +// File: Krb4DomainRealmMaintenance.h +// By: Arthur David Leather +// Created: 12/02/98 +// Copyright @1998 Massachusetts Institute of Technology - All rights reserved. +// Description: H file for Krb4DomainRealmMaintenance.cpp. Contains variables and functions +// for Kerberos Four Properties +// +// History: +// +// MM/DD/YY Inits Description of Change +// 12/02/98 ADL Original +// ************************************************************************************** + + +#if !defined(AFX_REALMNAMEMAINTENANCE_H__9CA36918_8FC0_11D2_94CC_0000861B8A3C__INCLUDED_) +#define AFX_REALMNAMEMAINTENANCE_H__9CA36918_8FC0_11D2_94CC_0000861B8A3C__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// RealmNameMaintenance.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CKrb4DomainRealmMaintenance dialog + +class CKrb4DomainRealmMaintenance : public CPropertyPage +{ +// Construction +private: + DECLARE_DYNCREATE(CKrb4DomainRealmMaintenance) + CHAR lineBuf[MAXLINE]; + INT m_defectiveLines; + +public: + CKrb4DomainRealmMaintenance(); // standard constructor + virtual ~CKrb4DomainRealmMaintenance(); + +// Dialog Data + //{{AFX_DATA(CKrb4DomainRealmMaintenance) + enum { IDD = IDD_KRB4_DOMAINREALM_MAINT }; + CDragListBox m_realmDomainList; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CKrb4DomainRealmMaintenance) + public: + virtual BOOL PreTranslateMessage(MSG* pMsg); + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CKrb4DomainRealmMaintenance) + virtual BOOL OnInitDialog(); + virtual BOOL OnApply(); + afx_msg void OnButtonRealmHostAdd(); + afx_msg void OnButtonRealmHostRemove(); + afx_msg void OnButtonRealmHostEdit(); + afx_msg void OnSelchangeListDomainrealm(); + afx_msg void OnDblclkListDomainrealm(); + afx_msg void OnButtonHostmaintHelp(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_REALMNAMEMAINTENANCE_H__9CA36918_8FC0_11D2_94CC_0000861B8A3C__INCLUDED_) diff --git a/src/windows/leash/Krb4EditDomainRealmList.cpp b/src/windows/leash/Krb4EditDomainRealmList.cpp new file mode 100644 index 000000000..047044834 --- /dev/null +++ b/src/windows/leash/Krb4EditDomainRealmList.cpp @@ -0,0 +1,147 @@ +// ************************************************************************************** +// File: Krb4EditDomainRealmList.cpp +// By: Arthur David Leather +// Created: 12/02/98 +// Copyright @1998 Massachusetts Institute of Technology - All rights reserved. +// Description: CPP file for Krb4EditDomainRealmList.h. Contains variables and functions +// for Kerberos Four Properites +// +// History: +// +// MM/DD/YY Inits Description of Change +// 12/02/98 ADL Original +// ************************************************************************************** + + +#include "stdafx.h" +#include "leash.h" +#include "Krb4Properties.h" +#include "Krb4EditDomainRealmList.h" +#include "lglobals.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CKrb4EditDomainRealmList dialog + + +CKrb4EditDomainRealmList::CKrb4EditDomainRealmList(LPSTR editItem, CWnd* pParent) + : CDialog(CKrb4EditDomainRealmList::IDD, pParent) +{ + m_startup = TRUE; + m_editItem = _T(""); + + // Parse the passed in item + LPSTR pEditItem = editItem; + LPSTR findSpace = strchr(editItem, ' '); + if (findSpace) + *findSpace = 0; + else + { + LeashErrorBox("This is a defective entry in file", + CKrb4ConfigFileLocation::m_newKrbrealmFile); + ASSERT(0); + m_initDomainHost = m_newDomainHost = editItem; + m_initRealm = m_newRealm = _T(""); + return; + } + + m_initDomainHost = m_newDomainHost = editItem; // first token + + pEditItem = strchr(editItem, '\0'); + if (pEditItem) + { + pEditItem++; + findSpace++; + } + else + ASSERT(0); + + findSpace = strchr(pEditItem, ' '); + if (findSpace) + { + *findSpace = 0; + } + + m_initRealm = m_newRealm = pEditItem; // second token + + //{{AFX_DATA_INIT(CKrb4EditDomainRealmList) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT +} + +void CKrb4EditDomainRealmList::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CKrb4EditDomainRealmList) + // NOTE: the ClassWizard will add DDX and DDV calls here + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CKrb4EditDomainRealmList, CDialog) + //{{AFX_MSG_MAP(CKrb4EditDomainRealmList) + ON_WM_SHOWWINDOW() + ON_EN_CHANGE(IDC_EDIT_REALMNAME, OnChangeEditDefaultRealm) + ON_EN_CHANGE(IDC_EDIT_DOMAINHOST, OnChangeEditRealmHostname) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CKrb4EditDomainRealmList message handlers + + +void CKrb4EditDomainRealmList::OnShowWindow(BOOL bShow, UINT nStatus) +{ + CDialog::OnShowWindow(bShow, nStatus); + m_startup = FALSE; +} + +BOOL CKrb4EditDomainRealmList::OnInitDialog() +{ + CDialog::OnInitDialog(); + + SetDlgItemText(IDC_EDIT_REALMNAME, m_newRealm); + SetDlgItemText(IDC_EDIT_DOMAINHOST, m_newDomainHost); + + return TRUE; +} + +void CKrb4EditDomainRealmList::OnChangeEditDefaultRealm() +{ + if (!m_startup) + GetDlgItemText(IDC_EDIT_REALMNAME, m_newRealm); +} + +void CKrb4EditDomainRealmList::OnChangeEditRealmHostname() +{ + if (!m_startup) + GetDlgItemText(IDC_EDIT_DOMAINHOST, m_newDomainHost); +} + +void CKrb4EditDomainRealmList::OnOK() +{ + m_newRealm.TrimLeft(); + m_newRealm.TrimRight(); + m_newDomainHost.TrimLeft(); + m_newDomainHost.TrimRight(); + + if (m_newRealm.IsEmpty() || m_newDomainHost.IsEmpty()) + { // stay + MessageBox("OnOK::Both Domain-Host and Realm fields must be filled in!", + "Leash", MB_OK); + } + else if (-1 != m_newRealm.Find(' ') || -1 != m_newDomainHost.Find(' ')) + { // stay + MessageBox("OnOK::Illegal space found!", "Leash", MB_OK); + } + + else + CDialog::OnOK(); // exit + + m_editItem = m_newDomainHost + " " + m_newRealm; +} diff --git a/src/windows/leash/Krb4EditDomainRealmList.h b/src/windows/leash/Krb4EditDomainRealmList.h new file mode 100644 index 000000000..9f8a18f76 --- /dev/null +++ b/src/windows/leash/Krb4EditDomainRealmList.h @@ -0,0 +1,77 @@ +// ************************************************************************************** +// File: Krb4EditDomainRealmList.h +// By: Arthur David Leather +// Created: 12/02/98 +// Copyright @1998 Massachusetts Institute of Technology - All rights reserved. +// Description: H file for Krb4EditDomainRealmList.cpp. Contains variables and functions +// for Kerberos Four Properites +// +// History: +// +// MM/DD/YY Inits Description of Change +// 12/02/98 ADL Original +// ************************************************************************************** + + +#if !defined(AFX_KRB4EDITDOMAINREALMLIST_H__F4D41684_96A4_11D2_94E2_0000861B8A3C__INCLUDED_) +#define AFX_KRB4EDITDOMAINREALMLIST_H__F4D41684_96A4_11D2_94E2_0000861B8A3C__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// CKrb4EditDomainRealmList.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CKrb4EditDomainRealmList dialog + +class CKrb4EditDomainRealmList : public CDialog +{ +// Construction +private: + CString m_editItem; + CString m_initRealm; + CString m_newRealm; + CString m_initDomainHost; + CString m_newDomainHost; + BOOL m_startup; + + +public: + CKrb4EditDomainRealmList(LPSTR editItem, CWnd* pParent = NULL); + CString GetEditedItem() {return m_editItem;} + CString GetRealm() {return m_newRealm;} + CString GetDomainHost() {return m_newDomainHost;} + +// Dialog Data + //{{AFX_DATA(CKrb4EditDomainRealmList) + enum { IDD = IDD_KRB4_EDIT_DOMAINREALMNAME }; + // NOTE: the ClassWizard will add data members here + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CKrb4EditDomainRealmList) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CKrb4EditDomainRealmList) + afx_msg void OnShowWindow(BOOL bShow, UINT nStatus); + virtual BOOL OnInitDialog(); + afx_msg void OnChangeEditDefaultRealm(); + afx_msg void OnChangeEditRealmHostname(); + virtual void OnOK(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_KRB4EDITDOMAINREALMLIST_H__F4D41684_96A4_11D2_94E2_0000861B8A3C__INCLUDED_) diff --git a/src/windows/leash/Krb4EditRealmHostList.cpp b/src/windows/leash/Krb4EditRealmHostList.cpp new file mode 100644 index 000000000..840f6262e --- /dev/null +++ b/src/windows/leash/Krb4EditRealmHostList.cpp @@ -0,0 +1,193 @@ +// ************************************************************************************** +// File: Krb4EditRealmHostList.cpp +// By: Arthur David Leather +// Created: 12/02/98 +// Copyright @1998 Massachusetts Institute of Technology - All rights reserved. +// Description: CPP file for Krb4EditRealmHostList.h. Contains variables and functions +// for Kerberos Four Properties +// +// History: +// +// MM/DD/YY Inits Description of Change +// 12/02/98 ADL Original +// ************************************************************************************** + + +#include "stdafx.h" +#include "leash.h" +#include "Krb4Properties.h" +#include "Krb4EditRealmHostList.h" +#include "lglobals.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CKrb4EditRealmHostList dialog + +CKrb4EditRealmHostList::CKrb4EditRealmHostList(LPSTR editItem, CWnd* pParent) + : CDialog(CKrb4EditRealmHostList::IDD, pParent) +{ + m_startup = TRUE; + m_editItem = _T(""); + +/* + // Parse the passed in item + LPSTR pEditItem = editItem; + LPSTR findSpace = strchr(editItem, ' '); + if (findSpace) + *findSpace = 0; + else + { + LeashErrorBox("This is a defective entry in file", + CKrb4ConfigFileLocation::m_krbFile); + ASSERT(0); + m_initRealm = m_newRealm = editItem; + m_initHost = m_newHost = _T(""); + } + + m_initRealm = m_newRealm = editItem; // first token + + pEditItem = strchr(editItem, '\0'); + if (pEditItem) + { + pEditItem++; + findSpace++; + } + else + ASSERT(0); + + findSpace = strchr(pEditItem, ' '); + if (findSpace) + { + *findSpace = 0; + } + else + { + m_initAdmin = m_newAdmin = FALSE; + m_initHost = m_newHost = pEditItem; // second token + return; + } + + m_initHost = m_newHost = pEditItem; // second token + + findSpace++; + pEditItem = findSpace; + if (pEditItem) + { + if (strstr(pEditItem, "admin server")) + m_initAdmin = m_newAdmin = TRUE; + //else + //; It must be something else??? :( + } + else + ASSERT(0); +*/ + //{{AFX_DATA_INIT(CKrb4EditRealmHostList) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT +} + +void CKrb4EditRealmHostList::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CKrb4EditRealmHostList) + // NOTE: the ClassWizard will add DDX and DDV calls here + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CKrb4EditRealmHostList, CDialog) + //{{AFX_MSG_MAP(CKrb4EditRealmHostList) + ON_WM_SHOWWINDOW() + ON_EN_CHANGE(IDC_EDIT_DEFAULT_REALM, OnChangeEditDefaultRealm) + ON_EN_CHANGE(IDC_EDIT_REALM_HOSTNAME, OnChangeEditRealmHostname) + ON_BN_CLICKED(IDC_RADIO_ADMIN_SERVER, OnRadioAdminServer) + ON_BN_CLICKED(IDC_RADIO_NO_ADMIN_SERVER, OnRadioNoAdminServer) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CKrb4EditRealmHostList message handlers + +BOOL CKrb4EditRealmHostList::OnInitDialog() +{ + CDialog::OnInitDialog(); + + SetDlgItemText(IDC_EDIT_DEFAULT_REALM, m_newRealm); + SetDlgItemText(IDC_EDIT_REALM_HOSTNAME, m_newHost); + + if (m_initAdmin) + { // has Admin Server + CheckRadioButton(IDC_RADIO_ADMIN_SERVER, IDC_RADIO_NO_ADMIN_SERVER, IDC_RADIO_ADMIN_SERVER); + } + else + { // no Admin Server + CheckRadioButton(IDC_RADIO_ADMIN_SERVER, IDC_RADIO_NO_ADMIN_SERVER, IDC_RADIO_NO_ADMIN_SERVER); + } + + //GetDlgItem(IDC_EDIT_DEFAULT_REALM)->EnableWindow(); + //GetDlgItem(IDC_EDIT_DEFAULT_REALM)->SetFocus(); + + return TRUE; +} + +void CKrb4EditRealmHostList::OnShowWindow(BOOL bShow, UINT nStatus) +{ + CDialog::OnShowWindow(bShow, nStatus); + m_startup = FALSE; +} + +void CKrb4EditRealmHostList::OnChangeEditDefaultRealm() +{ + if (!m_startup) + GetDlgItemText(IDC_EDIT_DEFAULT_REALM, m_newRealm); +} + +void CKrb4EditRealmHostList::OnChangeEditRealmHostname() +{ + if (!m_startup) + GetDlgItemText(IDC_EDIT_REALM_HOSTNAME, m_newHost); +} + +void CKrb4EditRealmHostList::OnRadioAdminServer() +{ + m_newAdmin = TRUE; +} + +void CKrb4EditRealmHostList::OnRadioNoAdminServer() +{ + m_newAdmin = FALSE; +} + +void CKrb4EditRealmHostList::OnOK() +{ + m_newRealm.TrimLeft(); + m_newRealm.TrimRight(); + m_newHost.TrimLeft(); + m_newHost.TrimRight(); + + if (m_newRealm.IsEmpty() || m_newHost.IsEmpty()) + { // stay + MessageBox("OnOK::Both Realm and Host fields must be filled in!", + "Leash", MB_OK); + } + else if (-1 != m_newRealm.Find(' ') || -1 != m_newHost.Find(' ')) + { // stay + MessageBox("OnOK::Illegal space found!", "Leash", MB_OK); + } + + else + CDialog::OnOK(); // exit + + m_editItem = m_newRealm + " " + m_newHost; + + if (m_newAdmin) + { + m_editItem += " "; + m_editItem += ADMIN_SERVER; + } +} diff --git a/src/windows/leash/Krb4EditRealmHostList.h b/src/windows/leash/Krb4EditRealmHostList.h new file mode 100644 index 000000000..5ed386473 --- /dev/null +++ b/src/windows/leash/Krb4EditRealmHostList.h @@ -0,0 +1,79 @@ +// ************************************************************************************** +// File: Krb4EditRealmHostList.h +// By: Arthur David Leather +// Created: 12/02/98 +// Copyright @1998 Massachusetts Institute of Technology - All rights reserved. +// Description: H file for Krb4EditRealmHostList.cpp. Contains variables and functions +// for Kerberos Four Properties +// +// History: +// +// MM/DD/YY Inits Description of Change +// 12/02/98 ADL Original +// ************************************************************************************** + + + +#if !defined(AFX_EDITREALMHOSTLIST_H__26A1E1F7_9117_11D2_94D0_0000861B8A3C__INCLUDED_) +#define AFX_EDITREALMHOSTLIST_H__26A1E1F7_9117_11D2_94D0_0000861B8A3C__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// EditRealmHostList.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CKrb4EditRealmHostList dialog + +class CKrb4EditRealmHostList : public CDialog +{ +// Construction +private: + CString m_editItem; + CString m_initRealm; + CString m_newRealm; + CString m_initHost; + CString m_newHost; + BOOL m_initAdmin; + BOOL m_newAdmin; + BOOL m_startup; + +public: + CKrb4EditRealmHostList(LPSTR editItem, CWnd* pParent = NULL); + CString GetEditedItem() {return m_editItem;} + CString GetNewRealm() {return m_newRealm;} + +// Dialog Data + //{{AFX_DATA(CKrb4EditRealmHostList) + enum { IDD = IDD_KRB4_EDIT_REALM }; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CKrb4EditRealmHostList) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CKrb4EditRealmHostList) + afx_msg void OnShowWindow(BOOL bShow, UINT nStatus); + afx_msg void OnChangeEditDefaultRealm(); + afx_msg void OnChangeEditRealmHostname(); + afx_msg void OnRadioAdminServer(); + afx_msg void OnRadioNoAdminServer(); + virtual void OnOK(); + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_EDITREALMHOSTLIST_H__26A1E1F7_9117_11D2_94D0_0000861B8A3C__INCLUDED_) diff --git a/src/windows/leash/Krb4Properties.cpp b/src/windows/leash/Krb4Properties.cpp new file mode 100644 index 000000000..a26d585e5 --- /dev/null +++ b/src/windows/leash/Krb4Properties.cpp @@ -0,0 +1,390 @@ +// ************************************************************************************** +// File: Krb4Properties.cpp +// By: Arthur David Leather +// Created: 12/02/98 +// Copyright @1998 Massachusetts Institute of Technology - All rights reserved. +// Description: CPP file for KrbProperties.h. Contains variables and functions +// for Kerberos Four Properties +// +// History: +// +// MM/DD/YY Inits Description of Change +// 12/02/98 ADL Original +// ************************************************************************************** + + + +#include "stdafx.h" +#include "Leash.h" +#include "Krb4Properties.h" +#include "LeashFileDialog.h" +#include "LeashMessageBox.h" +#include "wshelper.h" +#include "lglobals.h" +#include +#include +#include "reminder.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +/////////////////////////////////////////////////////////////////////// +// CKrb4ConfigFileLocation property page + +IMPLEMENT_DYNCREATE(CKrb4ConfigFileLocation, CPropertyPage) + +CString CKrb4ConfigFileLocation::m_newKrbFile; +CString CKrb4ConfigFileLocation::m_newKrbrealmFile; + +CKrb4ConfigFileLocation::CKrb4ConfigFileLocation() : CPropertyPage(CKrb4ConfigFileLocation::IDD) +{ + m_newTicketFile = _T(""); + m_newKrbFile = _T(""); + m_newKrbrealmFile = _T(""); + m_initKrbFile = _T(""); + m_initKrbrealmFile = _T(""); + m_initTicketFile = _T(""); + m_noKrbrealmFileStartupWarning = FALSE; + m_noKrbFileStartupWarning = FALSE; + + m_startupPage1 = TRUE; + + //{{AFX_DATA_INIT(CKrb4ConfigFileLocation) + //}}AFX_DATA_INIT +} + +CKrb4ConfigFileLocation::~CKrb4ConfigFileLocation() +{ +} + +BOOL CKrb4ConfigFileLocation::OnInitDialog() +{ + CPropertyPage::OnInitDialog(); + + INT krbCreate = 0; + INT krbrealmCreate = 0; + CHAR krb_path[MAX_PATH]; + CHAR krbrealm_path[MAX_PATH]; + CHAR ticketName[MAX_PATH]; + unsigned int krb_path_sz = sizeof(krb_path); + unsigned int krbrealm_path_sz = sizeof(krbrealm_path); + CString strMessage; + + + // Set KRB.CON + memset(krb_path, '\0', sizeof(krb_path)); + if (!pkrb_get_krbconf2(krb_path, &krb_path_sz)) + { // Error has happened + m_noKrbFileStartupWarning = TRUE; + } + else + { // normal find + m_initKrbFile = krb_path; + m_newKrbFile = m_initKrbFile; + SetDlgItemText(IDC_EDIT_KRB_LOC, m_initKrbFile); + } + + // Set KRBREALM.CON + memset(krbrealm_path, '\0', sizeof(krbrealm_path)); + if (!pkrb_get_krbrealm2(krbrealm_path, &krbrealm_path_sz)) + { + // Error has happened + m_noKrbrealmFileStartupWarning = TRUE; + } + else + { + // normal find + m_initKrbrealmFile = krbrealm_path; + m_newKrbrealmFile = m_initKrbrealmFile; + SetDlgItemText(IDC_EDIT_KRBREALM_LOC, m_initKrbrealmFile); + } + + if (pLeash_get_lock_file_locations() || + getenv("KRB4_KRB.REALMS") || getenv("KRB4_KRB.CONF") || getenv("KRB4_CONFIG")) + { + GetDlgItem(IDC_EDIT_KRB_LOC)->EnableWindow(FALSE); + GetDlgItem(IDC_EDIT_KRBREALM_LOC)->EnableWindow(FALSE); + GetDlgItem(IDC_BUTTON_KRB_BROWSE)->EnableWindow(FALSE); + GetDlgItem(IDC_BUTTON_KRBREALM_BROWSE)->EnableWindow(FALSE); + } + else if ( !(getenv("KRB4_KRB.REALMS") || getenv("KRB4_KRB.CONF") || getenv("KRB4_CONFIG")) ) + { + GetDlgItem(IDC_STATIC_CONFILES)->ShowWindow(FALSE); + } + + + // Set TICKET.KRB file Editbox + *ticketName = NULL; + pkrb_set_tkt_string(0); + + char *pticketName = ptkt_string(); + if (pticketName) + strcpy(ticketName, pticketName); + + if (!*ticketName) + { + LeashErrorBox("OnInitDialog::Can't locate ticket file", TICKET_FILE); + } + else + { + m_initTicketFile = m_newTicketFile = ticketName; + m_ticketEditBox.ReplaceSel(m_initTicketFile); + } + + if (getenv("KRBTKFILE")) + GetDlgItem(IDC_EDIT_TICKET_FILE)->EnableWindow(FALSE); + else + GetDlgItem(IDC_STATIC_TXT)->ShowWindow(FALSE); + + return FALSE; +} + +BOOL CKrb4ConfigFileLocation::OnApply() +{ + // Krb.con + if (0 != m_initKrbFile.CompareNoCase(m_newKrbFile)) + { + // Commit changes + if (SetRegistryVariable("krb.conf", m_newKrbFile, + "Software\\MIT\\Kerberos4")) + { + MessageBox("Failed to set \"Krb.conf\"!", "Error", MB_OK); + } + + m_initKrbFile = m_newKrbFile; + } + + // Krbrealms.con + if (0 != m_initKrbrealmFile.CompareNoCase(m_newKrbrealmFile)) + { + // Commit changes + if (SetRegistryVariable("krb.realms", m_newKrbrealmFile, + "Software\\MIT\\Kerberos4")) + { + MessageBox("Failed to set \"krb.realms\"!", "Error", MB_OK); + } + + m_initKrbrealmFile = m_newKrbrealmFile; + } + + // Ticket file + if (0 != m_initTicketFile.CompareNoCase(m_newTicketFile)) + { + if (getenv("KRBTKFILE")) + { + // Just in case they set (somehow) KRBTKFILE while this box is up + MessageBox("OnApply::Ticket file is set in your System's\ + Environment!\nYou must first remove it.", + "Error", MB_OK); + + return TRUE; + } + + // Commit changes + if (SetRegistryVariable("ticketfile", m_newTicketFile, + "Software\\MIT\\Kerberos4")) + { + MessageBox("Failed to set \"ticketfile\"!", "Error", MB_OK); + } + + m_initTicketFile = m_newTicketFile; + } + + return TRUE; +} + +VOID CKrb4ConfigFileLocation::OnOK() +{ + CPropertyPage::OnOK(); +} + +VOID CKrb4ConfigFileLocation::DoDataExchange(CDataExchange* pDX) +{ + TRACE("Entering CKrb4ConfigFileLocation::DoDataExchange -- %d\n", + pDX->m_bSaveAndValidate); + CPropertyPage::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CKrb4ConfigFileLocation) + DDX_Control(pDX, IDC_EDIT_TICKET_FILE, m_ticketEditBox); + //}}AFX_DATA_MAP +} + + +VOID CKrb4ConfigFileLocation::OnButtonKrbBrowse() +{ + CString msg; + msg.Format("Select %s Location", KRB_FILE); + + CString krb_path = "*.*"; + CLeashFileDialog dlgFile(TRUE, NULL, krb_path, "Kerbereos Four Config. File (.con)"); + dlgFile.m_ofn.lpstrTitle = msg; + + if (IDOK == dlgFile.DoModal()) + { + //m_newKrbFile = dlgFile.GetSelectedFileName(); + m_newKrbFile= dlgFile.GetPathName(); + SetDlgItemText(IDC_EDIT_KRB_LOC, m_newKrbFile); + SetModified(TRUE); + } +} + +VOID CKrb4ConfigFileLocation::OnButtonKrbrealmBrowse() +{ + CString msg; + msg.Format("Select %s Location", KRBREALM_FILE); + + CString krbrealm_path = "*.*"; + CLeashFileDialog dlgFile(TRUE, NULL, krbrealm_path, "Kerbereos Four Config. File (.con)"); + dlgFile.m_ofn.lpstrTitle = msg; + + if (IDOK == dlgFile.DoModal()) + { + //m_krbrealmFile = dlgFile.GetSelectedFileName(); + m_newKrbrealmFile = dlgFile.GetPathName(); + SetDlgItemText(IDC_EDIT_KRB_KRBREALM_LOC, m_newKrbrealmFile); + SetModified(TRUE); + } +} + +/* +VOID CKrb4ConfigFileLocation::OnButtonTicketfileBrowse() +{ + CString ticketPath = *.*"; + CLeashFileDialog dlgFile(TRUE, NULL, ticketPath, "Kerberos Four Ticket File (.con)"); + CString msg; + msg.Format("Select Location/Ticket File (Default file = %s)", TICKET_FILE); + dlgFile.m_ofn.lpstrTitle = msg; + while (TRUE) + { + if (IDOK == dlgFile.DoModal()) + { + m_newTicketFile = dlgFile.GetPathName(); + SetDlgItemText(IDC_EDIT_TICKET_FILE, m_newTicketFile); + SetModified(TRUE); + break; + } + else + break; + } +} +*/ + +void CKrb4ConfigFileLocation::OnChangeEditKrbLoc() +{ + if (!m_startupPage1) + { + GetDlgItemText(IDC_EDIT_KRB_LOC, m_newKrbFile); + SetModified(TRUE); + } +} + +void CKrb4ConfigFileLocation::OnChangeEditKrbrealmLoc() +{ + if (!m_startupPage1) + { + GetDlgItemText(IDC_EDIT_KRBREALM_LOC, m_newKrbrealmFile); + SetModified(TRUE); + } +} + +void CKrb4ConfigFileLocation::OnChangeEditTicketFile() +{ + if (!m_startupPage1) + { + GetDlgItemText(IDC_EDIT_TICKET_FILE, m_newTicketFile); + SetModified(TRUE); + } +} + +VOID CKrb4ConfigFileLocation::OnShowWindow(BOOL bShow, UINT nStatus) +{ + CPropertyPage::OnShowWindow(bShow, nStatus); +} + +VOID CKrb4ConfigFileLocation::OnCancel() +{ + CPropertyPage::OnCancel(); +} + +void CKrb4ConfigFileLocation::OnHelp() +{ +#ifdef CALL_HTMLHELP + AfxGetApp()->HtmlHelp(HID_KRB4_PROPERTIES_COMMAND); +#else + AfxGetApp()->WinHelp(HID_KRB4_PROPERTIES_COMMAND); +#endif +} + +BOOL CKrb4ConfigFileLocation::PreTranslateMessage(MSG* pMsg) +{ + // TODO: Add your specialized code here and/or call the base class + CString wmsg; + if (m_startupPage1) + { + if (m_noKrbFileStartupWarning) + { + wmsg.Format("OnInitDialog::Can't locate configuration file: %s.", + KRB_FILE); + MessageBox(wmsg, "Leash", MB_OK); + m_noKrbFileStartupWarning = FALSE; + } + + if (m_noKrbrealmFileStartupWarning) + { + wmsg.Format("OnInitDialog::Can't locate configuration file: %s.", + KRBREALM_FILE); + MessageBox(wmsg, "Leash", MB_OK); + m_noKrbrealmFileStartupWarning = FALSE; + } + } + + m_startupPage1 = FALSE; + return CPropertyPage::PreTranslateMessage(pMsg); +} + + +BEGIN_MESSAGE_MAP(CKrb4ConfigFileLocation, CPropertyPage) + //{{AFX_MSG_MAP(CKrb4ConfigFileLocation) + ON_BN_CLICKED(IDC_BUTTON_KRB_BROWSE, OnButtonKrbBrowse) + ON_BN_CLICKED(IDC_BUTTON_KRBREALM_BROWSE, OnButtonKrbrealmBrowse) + ON_WM_SHOWWINDOW() + ON_EN_CHANGE(IDC_EDIT_TICKET_FILE, OnChangeEditTicketFile) + ON_COMMAND(ID_HELP, OnHelp) + ON_EN_CHANGE(IDC_EDIT_KRB_LOC, OnChangeEditKrbLoc) + ON_EN_CHANGE(IDC_EDIT_KRBREALM_LOC, OnChangeEditKrbrealmLoc) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + + +/////////////////////////////////////////////////////////////////////// +// CKrb4Properties + +IMPLEMENT_DYNAMIC(CKrb4Properties, CPropertySheet) +CKrb4Properties::CKrb4Properties(UINT nIDCaption, CWnd* pParentWnd, + UINT iSelectPage) +:CPropertySheet(nIDCaption, pParentWnd, iSelectPage) +{ +} + +CKrb4Properties::CKrb4Properties(LPCTSTR pszCaption, CWnd* pParentWnd, + UINT iSelectPage) +:CPropertySheet(pszCaption, pParentWnd, iSelectPage) +{ + AddPage(&m_fileLocation); +} + +CKrb4Properties::~CKrb4Properties() +{ +} + + +BEGIN_MESSAGE_MAP(CKrb4Properties, CPropertySheet) + //{{AFX_MSG_MAP(CKrb4Properties) + // NOTE - the ClassWizard will add and remove mapping macros here. + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +/////////////////////////////////////////////////////////////////////// +// CKrb4Properties message handlers diff --git a/src/windows/leash/Krb4Properties.h b/src/windows/leash/Krb4Properties.h new file mode 100644 index 000000000..016badc25 --- /dev/null +++ b/src/windows/leash/Krb4Properties.h @@ -0,0 +1,138 @@ +// ************************************************************************************** +// File: Krb4Properties.h +// By: Arthur David Leather +// Created: 12/02/98 +// Copyright @1998 Massachusetts Institute of Technology - All rights reserved. +// Description: H file for KrbProperties.cpp. Contains variables and functions +// for Kerberos Four Properties +// +// History: +// +// MM/DD/YY Inits Description of Change +// 12/02/98 ADL Original +// ************************************************************************************** + + +#if !defined(AFX_PROPERTY_H__CD702F99_7495_11D0_8FDC_00C04FC2A0C2__INCLUDED_) +#define AFX_PROPERTY_H__CD702F99_7495_11D0_8FDC_00C04FC2A0C2__INCLUDED_ + +#if _MSC_VER >= 1000 +#pragma once +#endif // _MSC_VER >= 1000 +// Krb4Properties.h : header file +// + +#include "Resource.h" +//#include "Krb4RealmHostMaintenance.h" +//#include "Krb4DomainRealmMaintenance.h" + +/////////////////////////////////////////////////////////////////////// +// CKrb4ConfigFileLocation dialog + +class CKrb4ConfigFileLocation : public CPropertyPage +{ +// Construction +private: + DECLARE_DYNCREATE(CKrb4ConfigFileLocation) + CString m_ticketFile; + CString m_newTicketFile; + static CString m_newKrbFile; + static CString m_newKrbrealmFile; // static for the CKrb4EditDomainRealmList class + CString m_initKrbFile; + CString m_initKrbrealmFile; + CString m_initTicketFile; + + BOOL m_noKrbFileStartupWarning; + BOOL m_noKrbrealmFileStartupWarning; + BOOL m_startupPage1; + +public: + CKrb4ConfigFileLocation(); + ~CKrb4ConfigFileLocation(); + +// Dialog Data + //{{AFX_DATA(CKrb4ConfigFileLocation) + enum { IDD = IDD_KRB4_PROP_LOCATION }; + CEdit m_ticketEditBox; + //}}AFX_DATA + + +// Overrides + // ClassWizard generate virtual function overrides + //{{AFX_VIRTUAL(CKrb4ConfigFileLocation) + public: + virtual VOID OnCancel(); + virtual BOOL PreTranslateMessage(MSG* pMsg); + protected: + virtual VOID DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + + virtual VOID OnOK(); + virtual BOOL OnApply(); + +// Implementation +protected: + // Generated message map functions + //{{AFX_MSG(CKrb4ConfigFileLocation) + virtual BOOL OnInitDialog(); + afx_msg VOID OnButtonKrbBrowse(); + afx_msg VOID OnButtonKrbrealmBrowse(); + afx_msg void OnShowWindow(BOOL bShow, UINT nStatus); + afx_msg void OnChangeEditTicketFile(); + afx_msg void OnHelp(); + afx_msg void OnChangeEditKrbLoc(); + afx_msg void OnChangeEditKrbrealmLoc(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + +}; + + +////////////////////////////////////////////////////////////////////// +// CKrb4Properties + +class CKrb4Properties : public CPropertySheet +{ +private: + DECLARE_DYNAMIC(CKrb4Properties) + +public: + CKrb4ConfigFileLocation m_fileLocation; + + static BOOL applyButtonEnabled; + +// Construction +public: + CKrb4Properties(UINT nIDCaption, CWnd* pParentWnd = NULL, + UINT iSelectPage = 0); + CKrb4Properties(LPCTSTR pszCaption, CWnd* pParentWnd = NULL, + UINT iSelectPage = 0); + +// Attributes +public: + +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CKrb4Properties) + //}}AFX_VIRTUAL + +// Implementation +public: + virtual ~CKrb4Properties(); + + // Generated message map functions +protected: + //{{AFX_MSG(CKrb4Properties) + // NOTE - the ClassWizard will add and remove member functions here. + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// +//{{AFX_INSERT_LOCATION}} +// Microsoft Developer Studio will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_PROPERTY_H__CD702F99_7495_11D0_8FDC_00C04FC2A0C2__INCLUDED_) diff --git a/src/windows/leash/Krb4RealmHostMaintenance.cpp b/src/windows/leash/Krb4RealmHostMaintenance.cpp new file mode 100644 index 000000000..7e8ad4f07 --- /dev/null +++ b/src/windows/leash/Krb4RealmHostMaintenance.cpp @@ -0,0 +1,373 @@ +// ************************************************************************************** +// File: Krb4RealmHostMaintenance.cpp +// By: Arthur David Leather +// Created: 12/02/98 +// Copyright @1998 Massachusetts Institute of Technology - All rights reserved. +// Description: CPP file for Krb4RealmHostMaintenance.h. Contains variables and functions +// for Kerberos Four Properties +// +// History: +// +// MM/DD/YY Inits Description of Change +// 12/02/98 ADL Original +// ************************************************************************************** + + +#include "stdafx.h" +#include "leash.h" +#include "KrbProperties.h" +#include "Krb4Properties.h" +#include "Krb4AddToRealmHostList.h" +#include "Krb4RealmHostMaintenance.h" +#include "Krb4EditRealmHostList.h" +#include "lglobals.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CKrb4RealmHostMaintenance dialog + + +IMPLEMENT_DYNCREATE(CKrb4RealmHostMaintenance, CPropertyPage) + +CKrb4RealmHostMaintenance::CKrb4RealmHostMaintenance() : CPropertyPage(CKrb4RealmHostMaintenance::IDD) +{ + m_defectiveLines = 0; + m_initDnsKdcLookup = m_newDnsKdcLookup = 0; +} + +CKrb4RealmHostMaintenance::~CKrb4RealmHostMaintenance() +{ +} + +void CKrb4RealmHostMaintenance::DoDataExchange(CDataExchange* pDX) +{ + CPropertyPage::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CKrb4RealmHostMaintenance) + DDX_Control(pDX, IDC_LIST_KRB4_REALM_HOST, m_RealmHostList); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CKrb4RealmHostMaintenance, CPropertyPage) + //{{AFX_MSG_MAP(CKrb4RealmHostMaintenance) + ON_BN_CLICKED(IDC_BUTTON_KRB4_REALM_HOST_ADD, OnButtonRealmHostAdd) + ON_BN_CLICKED(IDC_BUTTON_KRB4_REALM_HOST_EDIT, OnButtonRealmHostEdit) + ON_BN_CLICKED(ID_BUTTON_KRB4_REALM_HOST_REMOVE, OnButtonRealmHostRemove) + ON_LBN_SELCHANGE(IDC_LIST_KRB4_REALM_HOST, OnSelchangeListRemoveHost) + ON_LBN_DBLCLK(IDC_LIST_KRB4_REALM_HOST, OnDblclkListRemoveHost) + ON_BN_CLICKED(IDC_BUTTON_REALMHOST_MAINT_HELP2, OnButtonRealmhostMaintHelp2) + ON_BN_CLICKED(IDC_KRB4_DNS_KDC, OnCheckDnsKdcLookup) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CKrb4RealmHostMaintenance message handlers + +BOOL CKrb4RealmHostMaintenance::OnInitDialog() +{ + CPropertyPage::OnInitDialog(); + + CStdioFile krbCon; + if (!krbCon.Open(CKrbProperties::m_krbPath, CFile::modeReadWrite)) + { // can't find file, so lets set some defaults + + m_RealmHostList.AddString(KRB_REALM " " KRB_MASTER); + } + else + { + memset(lineBuf, '\0', sizeof(lineBuf)); + krbCon.ReadString(lineBuf, sizeof(lineBuf)); + while (TRUE) + { + if (!krbCon.ReadString(lineBuf, sizeof(lineBuf))) + break; + + *(lineBuf + strlen(lineBuf) - 1) = 0; + + if (!strchr(lineBuf, ' ') && !strchr(lineBuf, '\t')) + { // found a defective line + m_defectiveLines++; + } + + if ( !strncmp(".KERBEROS.OPTION.",lineBuf,17) ) { + char * p = &lineBuf[17]; + while (isspace(*p)) + p++; + if (!strcmp("dns",p)) + m_initDnsKdcLookup = m_newDnsKdcLookup = 1; + } else { + if (LB_ERR == m_RealmHostList.AddString(lineBuf)) + { + LeashErrorBox("OnInitDialog::Can't read Configuration File", + CKrbProperties::m_krbPath); + krbCon.Close(); + return FALSE; + } + } + } + + krbCon.Close(); + } + + m_RealmHostList.SetCurSel(0); + + if (!m_RealmHostList.GetCount()) + { + GetDlgItem(ID_BUTTON_KRB4_REALM_HOST_REMOVE)->EnableWindow(FALSE); + GetDlgItem(IDC_BUTTON_KRB4_REALM_HOST_EDIT)->EnableWindow(FALSE); + } + + return TRUE; +} + +BOOL CKrb4RealmHostMaintenance::OnApply() +{ + CStdioFile krbCon; + if (!krbCon.Open(CKrbProperties::m_krbPath, CFile::modeCreate | + CFile::modeNoTruncate | + CFile::modeReadWrite)) + { + LeashErrorBox("OnApply::Can't open Configuration File", + CKrbProperties::m_krbPath); + return TRUE; + } + + memset(lineBuf, '\0', sizeof(lineBuf)); + if (!krbCon.ReadString(lineBuf, sizeof(lineBuf))) + { +//-----ADL----///strcpy(lineBuf, CKrb4ConfigOptions::m_newDefaultRealm); + strcat(lineBuf, "\n"); + } + + krbCon.SetLength(0); + krbCon.WriteString(lineBuf); + for (INT maxItems = m_RealmHostList.GetCount(), item = 0; item < maxItems; item++) + { + memset(lineBuf, '\0', sizeof(lineBuf)); + if (!m_RealmHostList.GetText(item, lineBuf)) + break; + + krbCon.WriteString(lineBuf); + krbCon.WriteString("\n"); + } + + if ( m_newDnsKdcLookup ) + krbCon.WriteString(".KERBEROS.OPTION. dns\n"); + + krbCon.Close(); + return TRUE; +} + +void CKrb4RealmHostMaintenance::OnOK() +{ + CPropertyPage::OnOK(); +} + +void CKrb4RealmHostMaintenance::OnCancel() +{ + CPropertyPage::OnCancel(); +} + +void CKrb4RealmHostMaintenance::OnCheckDnsKdcLookup() +{ + m_newDnsKdcLookup = (BOOL)IsDlgButtonChecked(IDC_KRB4_DNS_KDC); + SetModified(TRUE); +} + +void CKrb4RealmHostMaintenance::ResetDefaultRealmComboBox() +{ // krb4 is loaded without krb5 + CHAR lineBuf[REALM_SZ + MAX_HSTNM + 20]; + + int maxItems = m_RealmHostList.GetCount(); + + CKrbConfigOptions::m_krbRealmEditbox.ResetContent(); + + for (int xItems = 0; xItems < maxItems; xItems++) + { + m_RealmHostList.GetText(xItems, lineBuf); + + LPSTR space = strchr(lineBuf, ' '); + if (space) + *space = 0; + else + ASSERT(0); + + if (CB_ERR == CKrbConfigOptions::m_krbRealmEditbox.FindStringExact(-1, lineBuf)) + { // no dups + if (LB_ERR == CKrbConfigOptions::m_krbRealmEditbox.AddString(lineBuf)) + { + MessageBox("OnInitDialog::Can't add to Kerberos Realm Combobox", + "Leash", MB_OK); + return; + } + } + } + + CHAR krbhst[MAX_HSTNM + 1]; + CHAR krbrlm[REALM_SZ + 1]; + + strcpy(krbrlm, CKrbConfigOptions::m_newDefaultRealm); + memset(krbhst, '\0', sizeof(krbhst)); + + // Check for Host + // don't use KRB4 - krb_get_krbhst - would have to re-logon, on file location + // change, to use this function + extern int krb_get_krbhst(char* h, char* r, int n); + if (KFAILURE == krb_get_krbhst(krbhst, krbrlm, 1)) + { + MessageBox("We can't find the Host Server for your Default Realm!!!", + "Leash", MB_OK); + return; + } + + CKrbConfigOptions::m_hostServer = krbhst; +} + +void CKrb4RealmHostMaintenance::OnButtonRealmHostAdd() +{ + CKrb4AddToRealmHostList addToRealmHostList; + + if (IDOK == addToRealmHostList.DoModal()) + { + if (addToRealmHostList.GetNewRealm().IsEmpty()) + ASSERT(0); + + CString newLine; + newLine = addToRealmHostList.GetNewRealm() + " " + addToRealmHostList.GetNewHost(); + + if (addToRealmHostList.GetNewAdmin()) + newLine += " admin server"; + + // We don't want duplicate items in Listbox + if (LB_ERR != m_RealmHostList.FindStringExact(-1, newLine)) + { // found duplicate item in Listbox + LeashErrorBox("OnButtonRealmHostAdd::Found a Duplicate Item!\nCan't add to List", + newLine); + return; + } + + + m_RealmHostList.InsertString(0, newLine); + m_RealmHostList.SetCurSel(0); + SetModified(TRUE); + + ResetDefaultRealmComboBox(); + + if (1 == m_RealmHostList.GetCount()) + { + GetDlgItem(ID_BUTTON_KRB4_REALM_HOST_REMOVE)->EnableWindow(); + GetDlgItem(IDC_BUTTON_KRB4_REALM_HOST_EDIT)->EnableWindow(); + } + } +} + +void CKrb4RealmHostMaintenance::OnButtonRealmHostEdit() +{ + INT selItemIndex = m_RealmHostList.GetCurSel(); + LPSTR pSelItem = new char[m_RealmHostList.GetTextLen(selItemIndex) + 1]; + if (!pSelItem) + ASSERT(0); + + CString selItem; + m_RealmHostList.GetText(selItemIndex, selItem); + strcpy(pSelItem, selItem); + + CKrb4EditRealmHostList editRealmHostList(pSelItem); + delete [] pSelItem; + + if (IDOK == editRealmHostList.DoModal()) + { + CString editedItem = editRealmHostList.GetEditedItem(); + if (0 != selItem.CompareNoCase(editedItem) && + LB_ERR != m_RealmHostList.FindStringExact(-1, editedItem)) + { + LeashErrorBox("OnButtonRealmHostEdit::Found a Duplicate!\nCan't add to List", + editedItem); + + return; + } + + m_RealmHostList.DeleteString(selItemIndex); + m_RealmHostList.InsertString(selItemIndex, editRealmHostList.GetEditedItem()); + m_RealmHostList.SetCurSel(selItemIndex); + SetModified(TRUE); + + ResetDefaultRealmComboBox(); + } +} + +void CKrb4RealmHostMaintenance::OnButtonRealmHostRemove() +{ + if (IDYES != AfxMessageBox("You are about to remove an item from the list!\n\nContinue?", + MB_YESNO)) + return; + + INT curSel = m_RealmHostList.GetCurSel(); + m_RealmHostList.DeleteString(curSel); // Single Sel Listbox + + if (-1 == m_RealmHostList.SetCurSel(curSel)) + m_RealmHostList.SetCurSel(curSel - 1); + + SetModified(TRUE); + + ResetDefaultRealmComboBox(); + + if (!m_RealmHostList.GetCount()) + { + GetDlgItem(ID_BUTTON_KRB4_REALM_HOST_REMOVE)->EnableWindow(FALSE); + GetDlgItem(IDC_BUTTON_KRB4_REALM_HOST_EDIT)->EnableWindow(FALSE); + } + + /* For Mult. Sel Listbox + const LONG MAX_SEL_BUF = m_RealmHostList.GetSelCount(); + LPINT selectBuf = new INT[MAX_SEL_BUF]; + + for (INT maxSelected = m_RealmHostList.GetSelItems(MAX_SEL_BUF, selectBuf), del=0, sel=0; + sel < maxSelected; sel++) + { + if (LB_ERR == m_RealmHostList.DeleteString(*(selectBuf + sel) - del)) + MessageBox("Help", "Error", MB_OK); + else + del++; + } + + delete selectBuf; + */ +} + +void CKrb4RealmHostMaintenance::OnSelchangeListRemoveHost() +{ + //SetModified(TRUE); +} + + +void CKrb4RealmHostMaintenance::OnDblclkListRemoveHost() +{ + OnButtonRealmHostEdit(); +} + +BOOL CKrb4RealmHostMaintenance::PreTranslateMessage(MSG* pMsg) +{ + if (m_defectiveLines) + { + if (m_defectiveLines == 1) + LeashErrorBox("Found a defective entry in file", + CKrbProperties::m_krbPath, "Warning"); + else if (m_defectiveLines > 1) + LeashErrorBox("Found more then one defective entry in file", + CKrbProperties::m_krbPath, "Warning"); + } + + m_defectiveLines = 0; + return CPropertyPage::PreTranslateMessage(pMsg); +} + +void CKrb4RealmHostMaintenance::OnButtonRealmhostMaintHelp2() +{ + MessageBox("No Help Available!", "Note", MB_OK); +} diff --git a/src/windows/leash/Krb4RealmHostMaintenance.h b/src/windows/leash/Krb4RealmHostMaintenance.h new file mode 100644 index 000000000..26881c6d4 --- /dev/null +++ b/src/windows/leash/Krb4RealmHostMaintenance.h @@ -0,0 +1,86 @@ +// ************************************************************************************** +// File: Krb4RealmHostMaintenance.h +// By: Arthur David Leather +// Created: 12/02/98 +// Copyright @1998 Massachusetts Institute of Technology - All rights reserved. +// Description: H file for Krb4RealmHostMaintenance.cpp. Contains variables and functions +// for Kerberos Four Properties +// +// History: +// +// MM/DD/YY Inits Description of Change +// 12/02/98 ADL Original +// ************************************************************************************** + + +#if !defined(AFX_REAMLHOSTMAINT_H__2FE711C3_8E9A_11D2_94C5_0000861B8A3C__INCLUDED_) +#define AFX_REAMLHOSTMAINT_H__2FE711C3_8E9A_11D2_94C5_0000861B8A3C__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// RemoveHostNameList.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CKrb4RealmHostMaintenance dialog + +#define MAXLINE 256 + +class CKrb4RealmHostMaintenance : public CPropertyPage +{ +// Construction +private: + DECLARE_DYNCREATE(CKrb4RealmHostMaintenance) + CHAR lineBuf[MAXLINE]; + INT m_defectiveLines; + BOOL m_initDnsKdcLookup; + BOOL m_newDnsKdcLookup; + + void ResetDefaultRealmComboBox(); + +public: + //CKrb4RealmHostMaintenance(CWnd* pParent = NULL); // standard constructor + CKrb4RealmHostMaintenance(); + virtual ~CKrb4RealmHostMaintenance(); + +// Dialog Data + //{{AFX_DATA(CKrb4RealmHostMaintenance) + enum { IDD = IDD_KRB4_REALMHOST_MAINT2 }; + CDragListBox m_RealmHostList; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CKrb4RealmHostMaintenance) + public: + virtual BOOL PreTranslateMessage(MSG* pMsg); + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CKrb4RealmHostMaintenance) + virtual BOOL OnInitDialog(); + virtual BOOL OnApply(); + virtual void OnOK(); + virtual void OnCancel(); + afx_msg void OnButtonRealmHostAdd(); + afx_msg void OnButtonRealmHostEdit(); + afx_msg void OnButtonRealmHostRemove(); + afx_msg void OnSelchangeListRemoveHost(); + afx_msg void OnDblclkListRemoveHost(); + afx_msg void OnButtonRealmhostMaintHelp2(); + afx_msg void OnCheckDnsKdcLookup(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_REAMLHOSTMAINT_H__2FE711C3_8E9A_11D2_94C5_0000861B8A3C__INCLUDED_) diff --git a/src/windows/leash/Krb5Properties.cpp b/src/windows/leash/Krb5Properties.cpp new file mode 100644 index 000000000..c4ffef2bf --- /dev/null +++ b/src/windows/leash/Krb5Properties.cpp @@ -0,0 +1,644 @@ +//**************************************************************************** +// File: Krb5Properties.cpp +// By: Arthur David Leather +// Created: 12/02/98 +// Copyright: 1998 Massachusetts Institute of Technology - All rights +// reserved. +// Description: CPP file for Krb5Properties.h. Contains variables and functions +// for Kerberos Five Properties +// +// History: +// +// MM/DD/YY Inits Description of Change +// 12/02/98 ADL Original +//***************************************************************************** + +#include "stdafx.h" +#include "leash.h" +#include "LeashFileDialog.h" +#include "Krb5Properties.h" +#include "win-mac.h" +#include "lglobals.h" +#include "LeashView.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + + +///////////////////////////////////////////////////////////////////////////// +// CKrb5ConfigFileLocation dialog + +IMPLEMENT_DYNCREATE(CKrb5ConfigFileLocation, CPropertyPage) + +CKrb5ConfigFileLocation::CKrb5ConfigFileLocation() + : CPropertyPage(CKrb5ConfigFileLocation::IDD) +{ + m_initConfigFile = _T(""); + m_initTicketFile = _T(""); + m_newConfigFile = _T(""); + m_newTicketFile = _T(""); + m_startupPage1 = TRUE; + + //{{AFX_DATA_INIT(CKrb5ConfigFileLocation) + //}}AFX_DATA_INIT +} + +void CKrb5ConfigFileLocation::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CKrb5ConfigFileLocation) + DDX_Control(pDX, IDC_EDIT_KRB5_TXT_FILE, m_ticketEditBox); + //}}AFX_DATA_MAP +} + +BEGIN_MESSAGE_MAP(CKrb5ConfigFileLocation, CDialog) + //{{AFX_MSG_MAP(CKrb5ConfigFileLocation) + ON_BN_CLICKED(IDC_BUTTON_KRB5INI_BROWSE, OnButtonKrb5iniBrowse) + ON_BN_CLICKED(IDC_BUTTON_KRB5_TICKETFILE_BROWSE, OnButtonKrb5TicketfileBrowse) + ON_EN_CHANGE(IDC_EDIT_KRB5_TXT_FILE, OnChangeEditKrb5TxtFile) + ON_EN_CHANGE(IDC_EDIT_KRB5INI_LOCATION, OnChangeEditKrb5iniLocation) + ON_WM_SHOWWINDOW() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + + +BOOL CKrb5ConfigFileLocation::OnApply() +{ + BOOL tooManySlashes = FALSE; + BOOL foundError = FALSE; + + if( getenv("RENEW_TILL") != NULL) + { + MessageBox("The ticket renewable time is being controlled by the environment" + "variable RENEW_TILL instead of the registry. Leash cannot modify" + "the environment. Use the System control panel instead.", + "Leash", MB_OK); + return(FALSE); + } + + if( getenv("RENEWABLE") != NULL) + { + MessageBox("Ticket renewability is being controlled by the environment" + "variable RENEWABLE instead of the registry. Leash cannot modify" + "the environment. Use the System control panel instead.", + "Leash", MB_OK); + return(FALSE); + } + + if( getenv("FORWARDABLE") != NULL) + { + MessageBox("Ticket forwarding is being controlled by the environment" + "variable FORWARDABLE instead of the registry. Leash cannot modify" + "the environment. Use the System control panel instead.", + "Leash", MB_OK); + return(FALSE); + } + + if( getenv("PROXIABLE") != NULL) + { + MessageBox("Ticket proxying is being controlled by the environment" + "variable PROXIABLE instead of the registry. Leash cannot modify" + "the environment. Use the System control panel instead.", + "Leash", MB_OK); + return(FALSE); + } + + if( getenv("NOADDRESSES") != NULL) + { + MessageBox("Addressless tickets are being controlled by the environment" + "variable NOADDRESSES instead of the registry. Leash cannot modify" + "the environment. Use the System control panel instead.", + "Leash", MB_OK); + return(FALSE); + } + + + // KRB5.INI file + if (!CLeashApp::m_krbv5_profile || + 0 != m_newConfigFile.CompareNoCase(m_initConfigFile)) + { // Different path for Krb5.ini + + if (IsDlgButtonChecked(IDC_CHECK_CONFIRM_KRB5_EXISTS)) + { + // Check for extra slashes at end of path + LPSTR pSlash = strrchr(m_newConfigFile.GetBuffer(0), '\\'); + if (pSlash && *(pSlash - 1) == '\\') + { // don't commit changes + tooManySlashes = TRUE; + } + else if (pSlash && *(pSlash + 1) == '\0') + { // commit changes, but take out slash at the end of path + *pSlash = 0; + } + + m_newConfigFile.ReleaseBuffer(-1); + + // Check for invalid path + Directory directory(m_newConfigFile); + if (tooManySlashes || !directory.IsValidFile()) + { // don't commit changes + foundError = TRUE; + + if (tooManySlashes) + LeashErrorBox("OnApply::Too Many Slashes At End of " + "Selected Directory", + m_newConfigFile); + else + LeashErrorBox("OnApply::Selected file doesn't exist", + m_newConfigFile); + + SetDlgItemText(IDC_EDIT_KRB5INI_LOCATION, m_initConfigFile); + } + else + { + // more error checking + CHAR confname[MAX_PATH]; + + const char *filenames[2]; + filenames[0] = m_newConfigFile; + filenames[1] = NULL; + + const char* rootSection[] = {"realms", NULL}; + const char** rootsec = rootSection; + char **sections = NULL; + + long retval = pprofile_init(filenames, &CLeashApp::m_krbv5_profile); + if (!retval) + retval = pprofile_get_subsection_names(CLeashApp::m_krbv5_profile, + rootsec, §ions + ); + if (retval || !*sections ) + { + foundError = TRUE; + MessageBox("Your file selection is either corrupt or not a Kerberos Five Config. file", + "Leash", MB_OK); + + pprofile_free_list(sections); + + // Restore old 'valid' config. file + if (CLeashApp::GetProfileFile(confname, sizeof(confname))) + { + foundError = TRUE; + MessageBox("Can't locate Kerberos Five Config. file!", + "Error", MB_OK); + return TRUE; + } + + filenames[0] = confname; + filenames[1] = NULL; + + retval = pprofile_init(filenames, &CLeashApp::m_krbv5_profile); + if (!retval) + retval = pprofile_get_subsection_names(CLeashApp::m_krbv5_profile, + rootsec, §ions); + if (retval || !*sections) + { + foundError = TRUE; + MessageBox("OnApply::There is a problem with your " + "Kerberos Five Config. file!\n" + "Contact your Administrator.", + "Leash", MB_OK); + } + + pprofile_free_list(sections); + SetDlgItemText(IDC_EDIT_KRB5INI_LOCATION, m_initConfigFile); + + pprofile_release(CLeashApp::m_krbv5_profile); + return TRUE; + } + + pprofile_free_list(sections); + } + } + + // Commit changes + if (!foundError) + { + if (SetRegistryVariable("config", m_newConfigFile, + "Software\\MIT\\Kerberos5")) + { + MessageBox("Failed to set \"Krb.conf\"!", "Error", MB_OK); + } + + m_initConfigFile = m_newConfigFile; + SetModified(TRUE); + } + } + + // Credential cache (ticket) file + // Ticket file + if (0 != m_initTicketFile.CompareNoCase(m_newTicketFile)) + { + if (getenv("KRB5_ENV_CCNAME")) + { + // Just in case they set (somehow) KRB5_ENV_CCNAME while this box is up + MessageBox("OnApply::Ticket file is set in your System's" + "Environment!\nYou must first remove it.", + "Error", MB_OK); + + return TRUE; + } + + // Commit changes + if (SetRegistryVariable("ccname", m_newTicketFile, + "Software\\MIT\\Kerberos5")) + { + MessageBox("Failed to set \"ccname\"!", "Error", MB_OK); + } + if ( CLeashApp::m_krbv5_context ) + pkrb5_cc_set_default_name(CLeashApp::m_krbv5_context,m_newTicketFile); + + m_initTicketFile = m_newTicketFile; + } + + return TRUE; +} + + +BOOL CKrb5ConfigFileLocation::OnInitDialog() +{ + CDialog::OnInitDialog(); + + CHAR confname[MAX_PATH]; + CHAR ticketName[MAX_PATH]; + + CheckDlgButton(IDC_CHECK_CONFIRM_KRB5_EXISTS, TRUE); + + // Config. file (Krb5.ini) + if (CLeashApp::GetProfileFile(confname, sizeof(confname))) + { + MessageBox("Can't locate Kerberos Five config. file!", "Error", MB_OK); + return TRUE; + } + + m_initConfigFile = m_newConfigFile = confname; + SetDlgItemText(IDC_EDIT_KRB5INI_LOCATION, m_initConfigFile); + + if (pLeash_get_lock_file_locations() || getenv("KRB5_CONFIG")) + { + GetDlgItem(IDC_EDIT_KRB5INI_LOCATION)->EnableWindow(FALSE); + GetDlgItem(IDC_BUTTON_KRB5INI_BROWSE)->EnableWindow(FALSE); + GetDlgItem(IDC_CHECK_CONFIRM_KRB5_EXISTS)->EnableWindow(FALSE); + } + else if ( !(getenv("KRB5_CONFIG")) ) + { + GetDlgItem(IDC_STATIC_INIFILES)->ShowWindow(FALSE); + } + + + // Set TICKET.KRB file Editbox + *ticketName = NULL; + if (CLeashApp::m_krbv5_context) + { + const char *pticketName = pkrb5_cc_default_name(CLeashApp::m_krbv5_context); + + if (pticketName) + strcpy(ticketName, pticketName); + } + + if (!*ticketName) + { + MessageBox("OnInitDialog::Can't locate Kerberos Five ticket file!", + "Error", MB_OK); + return TRUE; + } + else + { + m_initTicketFile = m_newTicketFile = ticketName; + SetDlgItemText(IDC_EDIT_KRB5_TXT_FILE, m_initTicketFile); + } + + if (getenv("KRB5CCNAME")) + GetDlgItem(IDC_EDIT_KRB5_TXT_FILE)->EnableWindow(FALSE); + else + GetDlgItem(IDC_STATIC_TICKETFILE)->ShowWindow(FALSE); + + return TRUE; +} + +void CKrb5ConfigFileLocation::OnButtonKrb5iniBrowse() +{ + CLeashFileDialog dlgFile(TRUE, NULL, "*.*", + "Kerbereos Five Config. File (.ini)"); + dlgFile.m_ofn.lpstrTitle = "Select the Kerberos Five Config. File"; + while (TRUE) + { + if (IDOK == dlgFile.DoModal()) + { + m_newConfigFile = dlgFile.GetPathName(); + SetDlgItemText(IDC_EDIT_KRB5INI_LOCATION, m_newConfigFile); + break; + } + else + break; + } +} + +void CKrb5ConfigFileLocation::OnButtonKrb5TicketfileBrowse() +{ + CString ticket_path = "*.*"; + CLeashFileDialog dlgFile(TRUE, NULL, ticket_path, + "Kerbereos Five Ticket File (Krb5cc)"); + dlgFile.m_ofn.lpstrTitle = "Select Credential Cache (Ticket) File"; + + if (IDOK == dlgFile.DoModal()) + { + m_newTicketFile = dlgFile.GetPathName(); + SetDlgItemText(IDC_EDIT_KRB5_TXT_FILE, m_newTicketFile); + } +} + +void CKrb5ConfigFileLocation::OnChangeEditKrb5iniLocation() +{ + if (!m_startupPage1) + { + GetDlgItemText(IDC_EDIT_KRB5INI_LOCATION, m_newConfigFile); + SetModified(TRUE); + } +} + +void CKrb5ConfigFileLocation::OnChangeEditKrb5TxtFile() +{ + if (!m_startupPage1) + { + GetDlgItemText(IDC_EDIT_KRB5_TXT_FILE, m_newTicketFile); + SetModified(TRUE); + } +} + +void CKrb5ConfigFileLocation::OnShowWindow(BOOL bShow, UINT nStatus) +{ + CDialog::OnShowWindow(bShow, nStatus); + m_startupPage1 = FALSE; +} + + +///////////////////////////////////////////////////////////////////////////// +// CKrb5ConfigOptions dialog + +IMPLEMENT_DYNCREATE(CKrb5ConfigOptions, CPropertyPage) + +CKrb5ConfigOptions::CKrb5ConfigOptions() + : CPropertyPage(CKrb5ConfigOptions::IDD) +{ + m_initForwardable = 0; + m_newForwardable = 0; + m_initProxiable = 0; + m_newProxiable = 0; + m_initRenewable = 0; + m_newRenewable = 0; + m_initNoAddress = 0; + m_newNoAddress = 0; + m_initIPAddress = 0; +#ifdef SET_PUBLIC_IP + m_newIPAddress = 0; +#endif /* SET_PUBLIC_IP */ + + //{{AFX_DATA_INIT(CKrb5ConfigOptions) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT +} + + +void CKrb5ConfigOptions::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + + //{{AFX_DATA_MAP(CKrb5ConfigOptions) + // NOTE: the ClassWizard will add DDX and DDV calls here + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CKrb5ConfigOptions, CDialog) + //{{AFX_MSG_MAP(CKrb5ConfigOptions) + ON_BN_CLICKED(IDC_CHECK_FORWARDABLE, OnCheckForwardable) + ON_BN_CLICKED(IDC_CHECK_PROXIABLE, OnCheckProxiable) + ON_BN_CLICKED(IDC_CHECK_RENEWABLE, OnCheckRenewable) + ON_BN_CLICKED(IDC_CHECK_NO_ADDRESS, OnCheckNoAddress) + ON_WM_HELPINFO() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + + +BOOL CKrb5ConfigOptions::OnApply() +{ +#ifdef SET_PUBLIC_IP + SendDlgItemMessage( IDC_IPADDRESS_PUBLIC, + IPM_GETADDRESS, + 0, + (LPARAM)(LPDWORD)&m_newIPAddress + ); +#endif /* SET_PUBLIC_IP */ + + if ((m_initForwardable == m_newForwardable) && + (m_initProxiable == m_newProxiable) && + (m_initRenewable == m_newRenewable) && + (m_initNoAddress == m_newNoAddress) +#ifdef SET_PUBLIC_IP + && (m_initIPAddress == m_newIPAddress) +#endif /* SET_PUBLIC_IP */ + ) + return TRUE; + + CWinApp *pApp = NULL; + pApp = AfxGetApp(); + if (!pApp) + { + MessageBox("There is a problem finding Leash application " + "information!", + "Error", MB_OK); + return FALSE; + } + + if ( m_newNoAddress == FALSE ) { + CHAR confname[MAX_PATH]; + if (!CLeashApp::GetProfileFile(confname, sizeof(confname))) + { + const char *filenames[2]; + char *value=NULL; + long retval, noaddresses = 1; + filenames[0] = confname; + filenames[1] = NULL; + retval = pprofile_init(filenames, &CLeashApp::m_krbv5_profile); + if (!retval) { + retval = pprofile_get_string(CLeashApp::m_krbv5_profile, "libdefaults","noaddresses", 0, "true", &value); + if ( value ) { + noaddresses = config_boolean_to_int(value); + pprofile_release_string(value); + } + pprofile_release(CLeashApp::m_krbv5_profile); + } + + if ( noaddresses ) + { + MessageBox("The No Addresses setting cannot be disabled unless the setting\n" + " noaddresses=false\n" + "is added to the [libdefaults] section of the KRB5.INI file.", + "Error", MB_OK); + return FALSE; + + } + } + } + + pLeash_set_default_forwardable(m_newForwardable); + pLeash_set_default_proxiable(m_newProxiable); + pLeash_set_default_renewable(m_newRenewable); + pLeash_set_default_noaddresses(m_newNoAddress); +#ifdef SET_PUBLIC_IP + pLeash_set_default_publicip(m_newIPAddress); +#endif /* SET_PUBLIC_IP */ + + CLeashView::m_forwardableTicket = m_initForwardable = m_newForwardable; + CLeashView::m_proxiableTicket = m_initProxiable = m_newProxiable; + CLeashView::m_renewableTicket = m_initRenewable = m_newRenewable; + CLeashView::m_noaddressTicket = m_initNoAddress = m_newNoAddress; +#ifdef SET_PUBLIC_IP + CLeashView::m_publicIPAddress = m_initIPAddress = m_newIPAddress; +#endif /* SET_PUBLIC_IP */ + return TRUE; +} + +BOOL CKrb5ConfigOptions::OnInitDialog() +{ + CDialog::OnInitDialog(); + + CWinApp *pApp = NULL; + pApp = AfxGetApp(); + if (!pApp) + { + MessageBox("There is a problem finding Leash application " + "information!", + "Error", MB_OK); + } + else + { + m_initForwardable = pLeash_get_default_forwardable(); + m_initProxiable = pLeash_get_default_proxiable(); + m_initRenewable = pLeash_get_default_renewable(); + m_initNoAddress = pLeash_get_default_noaddresses(); + m_initIPAddress = pLeash_get_default_publicip(); + } + + CheckDlgButton(IDC_CHECK_FORWARDABLE, m_initForwardable); + m_newForwardable = m_initForwardable; + + CheckDlgButton(IDC_CHECK_PROXIABLE, m_initProxiable); + m_newProxiable = m_initProxiable; + + CheckDlgButton(IDC_CHECK_RENEWABLE, m_initRenewable); + m_newRenewable = m_initRenewable; + + CheckDlgButton(IDC_CHECK_NO_ADDRESS, m_initNoAddress); + m_newNoAddress = m_initNoAddress; + + if ( m_initNoAddress ) { + // Disable the control - jaltman + + SendDlgItemMessage( IDC_IPADDRESS_PUBLIC, + IPM_CLEARADDRESS, + 0, + 0 + ); + } + else { + SendDlgItemMessage( IDC_IPADDRESS_PUBLIC, + IPM_SETADDRESS, + 0, + (LPARAM)m_initIPAddress + ); + } +#ifdef SET_PUBLIC_IP + m_newIPAddress = m_initIPAddress; +#endif /* SET_PUBLIC_IP */ + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void CKrb5ConfigOptions::OnCheckForwardable() +{ + m_newForwardable = (BOOL)IsDlgButtonChecked(IDC_CHECK_FORWARDABLE); + SetModified(TRUE); +} + +void CKrb5ConfigOptions::OnCheckProxiable() +{ + m_newProxiable = (BOOL)IsDlgButtonChecked(IDC_CHECK_PROXIABLE); + SetModified(TRUE); +} + +void CKrb5ConfigOptions::OnCheckRenewable() +{ + m_newRenewable = (BOOL)IsDlgButtonChecked(IDC_CHECK_RENEWABLE); + SetModified(TRUE); +} + +void CKrb5ConfigOptions::OnCheckNoAddress() +{ + m_newNoAddress = (BOOL)IsDlgButtonChecked(IDC_CHECK_NO_ADDRESS); + SetModified(TRUE); + + if ( m_newNoAddress ) { + // Disable the control - jaltman + + SendDlgItemMessage( IDC_IPADDRESS_PUBLIC, + IPM_CLEARADDRESS, + 0, + 0 + ); + } else { + // Enable the IP Address Control - jaltman + + SendDlgItemMessage( IDC_IPADDRESS_PUBLIC, + IPM_SETADDRESS, + 0, + (LPARAM)m_initIPAddress + ); + } +} + +/////////////////////////////////////////////////////////////////////// +// CKrb5Properties + +IMPLEMENT_DYNAMIC(CKrb5Properties, CPropertySheet) + +CKrb5Properties::CKrb5Properties(UINT nIDCaption, CWnd* pParentWnd, + UINT iSelectPage) + :CPropertySheet(nIDCaption, pParentWnd, iSelectPage) +{ +} + +CKrb5Properties::CKrb5Properties(LPCTSTR pszCaption, CWnd* pParentWnd, + UINT iSelectPage) + :CPropertySheet(pszCaption, pParentWnd, iSelectPage) +{ + AddPage(&m_fileLocation); + AddPage(&m_configOptions); +} + +CKrb5Properties::~CKrb5Properties() +{ +} + +void CKrb5Properties::OnHelp() +{ +#ifdef CALL_HTMLHELP + AfxGetApp()->HtmlHelp(HID_KRB5_PROPERTIES_COMMAND); +#else + AfxGetApp()->WinHelp(HID_KRB5_PROPERTIES_COMMAND); +#endif +} + + + +BEGIN_MESSAGE_MAP(CKrb5Properties, CPropertySheet) + //{{AFX_MSG_MAP(CKrb5Properties) + // NOTE - the ClassWizard will add and remove mapping macros here. + ON_COMMAND(ID_HELP, OnHelp) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() diff --git a/src/windows/leash/Krb5Properties.h b/src/windows/leash/Krb5Properties.h new file mode 100644 index 000000000..c091ddd55 --- /dev/null +++ b/src/windows/leash/Krb5Properties.h @@ -0,0 +1,172 @@ +// ************************************************************************************** +// File: Krb5Properties.h +// By: Arthur David Leather +// Created: 12/02/98 +// Copyright @1998 Massachusetts Institute of Technology - All rights reserved. +// Description: H file for Krb5Properties.cpp. Contains variables and functions +// for Kerberos Five Properties +// +// History: +// +// MM/DD/YY Inits Description of Change +// 12/02/98 ADL Original +// ************************************************************************************** + + +#if !defined(AFX_KRB5PROPERTIES_H__9011A0B3_6E92_11D2_9454_0000861B8A3C__INCLUDED_) +#define AFX_KRB5PROPERTIES_H__9011A0B3_6E92_11D2_9454_0000861B8A3C__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// Krb5Properties.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CKrb5ConfigOptions dialog + +class CKrb5ConfigFileLocation : public CPropertyPage +{ +// Construction +private: + DECLARE_DYNCREATE(CKrb5ConfigFileLocation) + CString m_initConfigFile; + CString m_initTicketFile; + CString m_newConfigFile; + CString m_newTicketFile; + BOOL m_startupPage1; + +public: + CKrb5ConfigFileLocation(); // standard constructor + +// Dialog Data + //{{AFX_DATA(CKrb5ConfigFileLocation) + enum { IDD = IDD_KRB5_PROP_LOCATION }; + CEdit m_ticketEditBox; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CKrb5ConfigFileLocation) + public: + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + + virtual BOOL OnApply(); + + // Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CKrb5ConfigFileLocation) + virtual BOOL OnInitDialog(); + afx_msg void OnButtonKrb5iniBrowse(); + afx_msg void OnButtonKrb5TicketfileBrowse(); + afx_msg void OnChangeEditKrb5TxtFile(); + afx_msg void OnChangeEditKrb5iniLocation(); + afx_msg void OnShowWindow(BOOL bShow, UINT nStatus); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + + +///////////////////////////////////////////////////////////////////////////// +// CKrb5ConfigOptions dialog + +class CKrb5ConfigOptions : public CPropertyPage +{ +// Construction +private: + DECLARE_DYNCREATE(CKrb5ConfigOptions) + INT m_initForwardable; + INT m_newForwardable; + INT m_initProxiable; + INT m_newProxiable; + INT m_initRenewable; + INT m_newRenewable; + INT m_initNoAddress; + INT m_newNoAddress; + DWORD m_initIPAddress; +#ifdef SET_PUBLIC_IP + DWORD m_newIPAddress; +#endif /* SET_PUBLIC_IP */ + +public: + CKrb5ConfigOptions(); // standard constructor + +// Dialog Data + //{{AFX_DATA(CKrb5ConfigOptions) + enum { IDD = IDD_KRB5_PROP_CONTENT }; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CKrb5ConfigOptions) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + + virtual BOOL OnApply(); + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CKrb5ConfigOptions) + virtual BOOL OnInitDialog(); + afx_msg void OnCheckForwardable(); + afx_msg void OnCheckProxiable(); + afx_msg void OnCheckRenewable(); + afx_msg void OnCheckNoAddress(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +class CKrb5Properties : public CPropertySheet +{ +private: + DECLARE_DYNAMIC(CKrb5Properties) + +public: + CKrb5ConfigFileLocation m_fileLocation; + CKrb5ConfigOptions m_configOptions; + +// Construction +public: + CKrb5Properties(UINT nIDCaption, CWnd* pParentWnd = NULL, + UINT iSelectPage = 0); + CKrb5Properties(LPCTSTR pszCaption, CWnd* pParentWnd = NULL, + UINT iSelectPage = 0); + +// Attributes +public: + +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CKrb5Properties) + //}}AFX_VIRTUAL + +// Implementation +public: + virtual ~CKrb5Properties(); + + // Generated message map functions +protected: + //{{AFX_MSG(CKrb5Properties) + // NOTE - the ClassWizard will add and remove member functions here. + afx_msg void OnHelp(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_KRB5PROPERTIES_H__9011A0B3_6E92_11D2_9454_0000861B8A3C__INCLUDED_) diff --git a/src/windows/leash/KrbAddHostServer.cpp b/src/windows/leash/KrbAddHostServer.cpp new file mode 100644 index 000000000..fc53e416a --- /dev/null +++ b/src/windows/leash/KrbAddHostServer.cpp @@ -0,0 +1,77 @@ +// KrbAddHostServer.cpp : implementation file +// + +#include "stdafx.h" +#include "leash.h" +#include "KrbAddHostServer.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CKrbAddHostServer dialog + + +CKrbAddHostServer::CKrbAddHostServer(CWnd* pParent /*=NULL*/) + : CDialog(CKrbAddHostServer::IDD, pParent) +{ + m_newHost = _T(""); + m_startup = TRUE; + + //{{AFX_DATA_INIT(CKrbAddHostServer) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT +} + + +void CKrbAddHostServer::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CKrbAddHostServer) + // NOTE: the ClassWizard will add DDX and DDV calls here + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CKrbAddHostServer, CDialog) + //{{AFX_MSG_MAP(CKrbAddHostServer) + ON_EN_CHANGE(IDC_EDIT_KDC_HOST, OnChangeEditKdcHost) + ON_WM_SHOWWINDOW() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CKrbAddHostServer message handlers + +void CKrbAddHostServer::OnOK() +{ + m_newHost.TrimLeft(); + m_newHost.TrimRight(); + + if (m_newHost.IsEmpty()) + { // stay + MessageBox("OnOK:: Server Hosting a KDC must be filled in!", + "Error", MB_OK); + } + else if (-1 != m_newHost.Find(' ')) + { // stay + MessageBox("OnOK::Illegal space found!", "Error", MB_OK); + } + else + CDialog::OnOK(); // exit +} + +void CKrbAddHostServer::OnChangeEditKdcHost() +{ + if (!m_startup) + GetDlgItemText(IDC_EDIT_KDC_HOST, m_newHost); +} + +void CKrbAddHostServer::OnShowWindow(BOOL bShow, UINT nStatus) +{ + CDialog::OnShowWindow(bShow, nStatus); + m_startup = FALSE; +} diff --git a/src/windows/leash/KrbAddHostServer.h b/src/windows/leash/KrbAddHostServer.h new file mode 100644 index 000000000..989d38893 --- /dev/null +++ b/src/windows/leash/KrbAddHostServer.h @@ -0,0 +1,53 @@ +#if !defined(AFX_KRBADDHOSTSERVER_H__1B6B6ED8_D26D_11D2_95AF_0000861B8A3C__INCLUDED_) +#define AFX_KRBADDHOSTSERVER_H__1B6B6ED8_D26D_11D2_95AF_0000861B8A3C__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// KrbAddHostServer.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CKrbAddHostServer dialog + +class CKrbAddHostServer : public CDialog +{ +// Construction + CString m_newHost; + BOOL m_startup; + +public: + CKrbAddHostServer(CWnd* pParent = NULL); // standard constructor + CString GetNewHost() {return m_newHost;} + + +// Dialog Data + //{{AFX_DATA(CKrbAddHostServer) + enum { IDD = IDD_KRB_ADD_KDC_HOSTSERVER}; + // NOTE: the ClassWizard will add data members here + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CKrbAddHostServer) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CKrbAddHostServer) + virtual void OnOK(); + afx_msg void OnChangeEditKdcHost(); + afx_msg void OnShowWindow(BOOL bShow, UINT nStatus); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_KRBADDHOSTSERVER_H__1B6B6ED8_D26D_11D2_95AF_0000861B8A3C__INCLUDED_) diff --git a/src/windows/leash/KrbAddRealm.cpp b/src/windows/leash/KrbAddRealm.cpp new file mode 100644 index 000000000..4527e4bcc --- /dev/null +++ b/src/windows/leash/KrbAddRealm.cpp @@ -0,0 +1,88 @@ +// File: KrbAddRealm.cpp +// By: Arthur David Leather +// Created: 12/02/98 +// Copyright @1998 Massachusetts Institute of Technology - All rights reserved. +// Description: CPP file for KrbAddRealm.h. Contains variables and functions +// for Kerberos Four and Five Properties +// +// History: +// +// MM/DD/YY Inits Description of Change +// 12/02/98 ADL Original +// ************************************************************************************** + + +#include "stdafx.h" +#include "leash.h" +#include "KrbAddRealm.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CKrbAddRealm dialog + + +CKrbAddRealm::CKrbAddRealm(CWnd* pParent /*=NULL*/) +: CDialog(CKrbAddRealm::IDD, pParent) +{ + m_newRealm = _T(""); + m_startup = TRUE; + + //{{AFX_DATA_INIT(CKrbAddRealm) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT +} + + +void CKrbAddRealm::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CKrbAddRealm) + // NOTE: the ClassWizard will add DDX and DDV calls here + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CKrbAddRealm, CDialog) + //{{AFX_MSG_MAP(CKrbAddRealm) + ON_WM_SHOWWINDOW() + ON_EN_CHANGE(IDC_EDIT_REALM, OnChangeEditRealm) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CKrbAddRealm message handlers + +void CKrbAddRealm::OnShowWindow(BOOL bShow, UINT nStatus) +{ + CDialog::OnShowWindow(bShow, nStatus); + m_startup = FALSE; +} + +void CKrbAddRealm::OnChangeEditRealm() +{ + if (!m_startup) + GetDlgItemText(IDC_EDIT_REALM, m_newRealm); +} + +void CKrbAddRealm::OnOK() +{ + m_newRealm.TrimLeft(); + m_newRealm.TrimRight(); + + if (m_newRealm.IsEmpty()) + { // stay + MessageBox("OnOK:: Kerberos Realm must be filled in!", + "Leash", MB_OK); + } + else if (-1 != m_newRealm.Find(' ')) + { // stay + MessageBox("OnOK::Illegal space found!", "Leash", MB_OK); + } + else + CDialog::OnOK(); // exit +} diff --git a/src/windows/leash/KrbAddRealm.h b/src/windows/leash/KrbAddRealm.h new file mode 100644 index 000000000..48ae4b76f --- /dev/null +++ b/src/windows/leash/KrbAddRealm.h @@ -0,0 +1,66 @@ +// ************************************************************************************** +// File: KrbAddRealm.h +// By: Arthur David Leather +// Created: 12/02/98 +// Copyright @1998 Massachusetts Institute of Technology - All rights reserved. +// Description: H file for KrbAddRealm.cpp Contains variables and functions +// for Kerberos Four and Five Properties +// +// History: +// +// MM/DD/YY Inits Description of Change +// 12/02/98 ADL Original +// ************************************************************************************** + + +#if !defined(AFX_ADDTOREALMHOSTLIST_H__26A1E1F3_9117_11D2_94D0_0000861B8A3C__INCLUDED_) +#define AFX_ADDTOREALMHOSTLIST_H__26A1E1F3_9117_11D2_94D0_0000861B8A3C__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// AddToRealmHostList.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CKrbAddRealm dialog + +class CKrbAddRealm : public CDialog +{ +// Construction + CString m_newRealm; + BOOL m_startup; + +public: + CKrbAddRealm(CWnd* pParent = NULL); // standard constructor + CString GetNewRealm() {return m_newRealm;} + +// Dialog Data + //{{AFX_DATA(CKrbAddRealm) + enum { IDD = IDD_KRB_ADD_REALM }; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CKrbAddRealm) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CKrbAddRealm) + afx_msg void OnShowWindow(BOOL bShow, UINT nStatus); + virtual void OnOK(); + afx_msg void OnChangeEditRealm(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_ADDTOREALMHOSTLIST_H__26A1E1F3_9117_11D2_94D0_0000861B8A3C__INCLUDED_) diff --git a/src/windows/leash/KrbConfigOptions.cpp b/src/windows/leash/KrbConfigOptions.cpp new file mode 100644 index 000000000..2e1599c28 --- /dev/null +++ b/src/windows/leash/KrbConfigOptions.cpp @@ -0,0 +1,679 @@ +// ************************************************************************************** +// File: KrbConfigOptions.cpp +// By: Arthur David Leather +// Created: 12/02/98 +// Copyright @1998 Massachusetts Institute of Technology - All rights reserved. +// Description: CPP file for KrbProperties.h. Contains variables and functions +// for Kerberos Four and Five Properties +// +// History: +// +// MM/DD/YY Inits Description of Change +// 2/01/98 ADL Original +// ************************************************************************************** + + +#include "stdafx.h" +#include "Leash.h" +#include "KrbProperties.h" +#include "KrbConfigOptions.h" +#include "LeashFileDialog.h" +#include "LeashMessageBox.h" +#include "wshelper.h" +#include "lglobals.h" +#include +#include +#include "reminder.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + + +/////////////////////////////////////////////////////////////////////// +// CKrbConfigOptions property page + +CString CKrbConfigOptions::m_newDefaultRealm; +CString CKrbConfigOptions::m_hostServer; +CComboBox CKrbConfigOptions::m_krbRealmEditbox; +BOOL CKrbConfigOptions::m_profileError; +BOOL CKrbConfigOptions::m_dupEntriesError; + +IMPLEMENT_DYNCREATE(CKrbConfigOptions, CPropertyPage) + +CKrbConfigOptions::CKrbConfigOptions() : CPropertyPage(CKrbConfigOptions::IDD) +{ + m_initDefaultRealm = _T(""); + m_newDefaultRealm = _T(""); + m_startupPage2 = TRUE; + m_noKrbFileError = FALSE; + m_noKrbhostWarning = FALSE; + m_dupEntriesError = FALSE; + m_profileError = FALSE; + m_noRealm = FALSE; + + //{{AFX_DATA_INIT(CKrbConfigOptions) + //}}AFX_DATA_INIT +} + +CKrbConfigOptions::~CKrbConfigOptions() +{ +} + +VOID CKrbConfigOptions::DoDataExchange(CDataExchange* pDX) +{ + TRACE("Entering CKrbConfigOptions::DoDataExchange -- %d\n", + pDX->m_bSaveAndValidate); + CPropertyPage::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CKrbConfigOptions) + DDX_Control(pDX, IDC_EDIT_DEFAULT_REALM, m_krbRealmEditbox); + //}}AFX_DATA_MAP +} + +static char far * near parse_str(char far*buffer,char far*result) +{ + while (isspace(*buffer)) + buffer++; + while (!isspace(*buffer)) + *result++=*buffer++; + *result='\0'; + return buffer; +} + +int krb_get_krbhst(char* h, char* r, int n) +{ + char lbstorage[BUFSIZ]; + char tr[REALM_SZ]; + static FILE *cnffile; /*XXX pbh added static because of MS bug in fgets() */ + static char FAR *linebuf; /*XXX pbh added static because of MS bug in fgets() */ + int i; + char *p; + + //static char buffer[80]; + //krb_get_krbconf(buffer); + memset(lbstorage, '\0', BUFSIZ ); /* 4-22-94 */ + linebuf = &lbstorage[0]; + + if ((cnffile = fopen(CKrbProperties::m_krbPath,"r")) == NULL) { + if (n==1) { + (void) strcpy(h,KRB_HOST); + return(KSUCCESS); + } else { + return(KFAILURE); + } + } + /* linebuf=(char FAR *)malloc(BUFSIZ); */ /*4-22-94*/ + if (fgets(linebuf,BUFSIZ,cnffile)==NULL) { + /* free(linebuf); */ /* 4-22-94 */ + + return(KFAILURE); + } + /* bzero( tr, sizeof(tr) ); */ /* pbh 2-24-93 */ + memset(tr, '\0', sizeof(tr) ); + parse_str(linebuf,tr); + if (*tr=='\0') { + return (KFAILURE); + } + /* run through the file, looking for the nth server for this realm */ + for (i = 1; i <= n;) { + if (fgets(linebuf, BUFSIZ, cnffile) == NULL) { + /* free(linebuf); */ /*4-22-94*/ + (void) fclose(cnffile); + return(KFAILURE); + } + /* bzero( tr, sizeof(tr) ); */ /* pbh 2-24-93 */ + memset(tr, '\0', sizeof(tr) ); + p=parse_str(linebuf,tr); + if (*tr=='\0') + continue; + memset(h, '\0', lstrlen(h) ); + parse_str(p,h); + if (*tr=='\0') + continue; + if (!lstrcmp(tr,r)) + i++; + } + /* free(linebuf); */ /*4-22-94*/ + (void) fclose(cnffile); + return(KSUCCESS); +} + +BOOL CKrbConfigOptions::OnInitDialog() +{ + m_initDefaultRealm = _T(""); + m_newDefaultRealm = _T(""); + m_noKrbFileError = FALSE; + m_noKrbhostWarning = FALSE; + m_dupEntriesError = FALSE; + m_profileError = FALSE; + m_noRealm = FALSE; + + CPropertyPage::OnInitDialog(); + + if (CLeashApp::m_hKrb4DLL && !CLeashApp::m_hKrb5DLL) + { // Krb4 NOT krb5 + // Fill in all edit boxes + char krbRealm[REALM_SZ + 1]; + char krbhst[MAX_HSTNM + 1]; + CStdioFile krbCon; + if (!krbCon.Open(CKrbProperties::m_krbPath, CFile::modeRead)) + { + SetDlgItemText(IDC_EDIT_DEFAULT_REALM, KRB_REALM); + SetDlgItemText(IDC_EDIT_REALM_HOSTNAME, KRB_MASTER); + //CheckRadioButton(IDC_RADIO_ADMIN_SERVER, IDC_RADIO_NO_ADMIN_SERVER, IDC_RADIO_NO_ADMIN_SERVER); + m_initDefaultRealm = m_newDefaultRealm = KRB_REALM; + } + else + { // place krbRealm in Edit box + memset(krbRealm, '\0', sizeof(krbRealm)); + if (!krbCon.ReadString(krbRealm, sizeof(krbRealm)) || '\r' == *krbRealm || + '\n' == *krbRealm || '\0' == *krbRealm) + { + SetDlgItemText(IDC_EDIT_DEFAULT_REALM, KRB_REALM); + SetDlgItemText(IDC_EDIT_REALM_HOSTNAME, KRB_MASTER); + m_initDefaultRealm = m_newDefaultRealm = KRB_REALM; + } + else + { + *(krbRealm + strlen(krbRealm) - 1) = 0; + LPSTR pSpace = strchr(krbRealm, ' '); + if (pSpace) + *pSpace = 0; + + m_initDefaultRealm = m_newDefaultRealm = krbRealm; + + memset(krbhst, '\0', sizeof(krbhst)); + krbCon.Close(); + + // Check for Host + // don't use KRB4 - krb_get_krbhst - would have to re-logon, on file location + // change, to use this function + if (KFAILURE == pkrb_get_krbhst(krbhst, krbRealm, 1)) + { + m_noKrbhostWarning = TRUE; + } + else + { // place hostname in Edit Box + //SetDlgItemText(IDC_EDIT_REALM_HOSTNAME, krbhst); + + m_hostServer = krbhst; + + // New suff to put realms in Combo Box + CStdioFile krbCon; + if (!krbCon.Open(CKrbProperties::m_krbPath, CFile::modeRead)) + { + m_noKrbFileError = TRUE; + m_noRealm = TRUE; + } else { + + LPSTR space = NULL; + CHAR lineBuf[REALM_SZ + MAX_HSTNM + 20]; + CHAR localRealm[REALM_SZ + MAX_HSTNM + 20]; + memset(lineBuf, '\0', sizeof(lineBuf)); + memset(localRealm, '\0', sizeof(localRealm)); + + if (krbCon.ReadString(localRealm, sizeof(localRealm))) + *(localRealm + strlen(localRealm) - 1) = 0; + else + return FALSE; + + space = strchr(localRealm, ' '); + if (space) + *space = 0; + + while (TRUE) + { + if (!krbCon.ReadString(lineBuf, sizeof(lineBuf))) + break; + + *(lineBuf + sizeof(lineBuf) - 1) = 0; + + if (strlen(lineBuf) == 0) + continue; + + space = strchr(lineBuf, ' '); + if (!space) space = strchr(lineBuf, '\t'); + if (space) + *space = 0; + else + ASSERT(0); + + // skip Kerberos Options + if ( !strncmp(".KERBEROS.OPTION.",lineBuf,17) ) + continue; + + if (CB_ERR == m_krbRealmEditbox.FindStringExact(-1, lineBuf)) + { // no dups + if (LB_ERR == m_krbRealmEditbox.AddString(lineBuf)) + { + MessageBox("OnInitDialog::Can't add to Kerberos Realm Combobox", + "Leash", MB_OK); + return FALSE; + } + } + } + + m_krbRealmEditbox.SelectString(-1, krbRealm); + + } // end of 'else' + } // end of 'place hostname in Edit Box' else statement + } // end of 'Check for Host' else statement + } // end of 'place krbRealm in Edit box' else + } + else if (CLeashApp::m_hKrb5DLL) + { // Krb5 OR krb5 AND krb4 + char *realm = NULL; + pkrb5_get_default_realm(CLeashApp::m_krbv5_context, &realm); + + if (!realm) + m_noRealm = TRUE; + + m_initDefaultRealm = m_newDefaultRealm = realm; + + if ( !CLeashApp::m_krbv5_profile ) { + CHAR confname[MAX_PATH]; + if (!CLeashApp::GetProfileFile(confname, sizeof(confname))) + { + const char *filenames[2]; + filenames[0] = confname; + filenames[1] = NULL; + pprofile_init(filenames, &CLeashApp::m_krbv5_profile); + } + } + + CHAR selRealm[REALM_SZ]; + strcpy(selRealm, m_newDefaultRealm); + const char* Section[] = {"realms", selRealm, "kdc", NULL}; + const char** section = Section; + char **values = NULL; + char * value = NULL; + + long retval = pprofile_get_values(CLeashApp::m_krbv5_profile, + section, &values); + + if (!retval && values) + m_hostServer = *values; + else { + int dns_in_use = 0; + // Determine if we are using DNS for KDC lookups + retval = pprofile_get_string(CLeashApp::m_krbv5_profile, "libdefaults", + "dns_lookup_kdc", 0, 0, &value); + if (value == 0 && retval == 0) + retval = pprofile_get_string(CLeashApp::m_krbv5_profile, "libdefaults", + "dns_fallback", 0, 0, &value); + if (value == 0) { +#if KRB5_DNS_LOOKUP_KDC + dns_in_use = 1; +#else + dns_in_use = 0; +#endif + } else { + dns_in_use = config_boolean_to_int(value); + pprofile_release_string(value); + } + if (dns_in_use) + m_hostServer = "DNS SRV record lookups will be used to find KDC"; + else { + m_hostServer = "No KDC information available"; + } + } + SetDlgItemText(IDC_EDIT_REALM_HOSTNAME, m_hostServer); + + if ( realm ) + pkrb5_free_default_realm(CLeashApp::m_krbv5_context, realm); + } + + // Set host and domain names in their Edit Boxes, respectively. + char hostName[80]=""; + char domainName[80]=""; + int ckHost = wsh_gethostname(hostName, sizeof(hostName)); + int ckdomain = wsh_getdomainname(domainName, sizeof(domainName)); + CString dot_DomainName = "."; + dot_DomainName += domainName; + + SetDlgItemText(IDC_EDIT_HOSTNAME, ckHost == 0 ? hostName : ""); + SetDlgItemText(IDC_EDIT_DOMAINNAME, ckdomain == 0 ? dot_DomainName : ""); + + return m_noRealm; +} + +BOOL CKrbConfigOptions::OnApply() +{ + // If no changes were made, quit this function + if (0 == m_initDefaultRealm.CompareNoCase(m_newDefaultRealm)) + return TRUE; + + m_newDefaultRealm.TrimLeft(); + m_newDefaultRealm.TrimRight(); + + if (m_newDefaultRealm.IsEmpty()) + { + MessageBox("OnApply::Your Kerberos Realm field must be filled in!", + "Leash", MB_OK); + m_newDefaultRealm = m_initDefaultRealm; + SetDlgItemText(IDC_EDIT_DEFAULT_REALM, m_newDefaultRealm); + return TRUE; + } + + CStdioFile krbCon; + if (!krbCon.Open(CKrbProperties::m_krbPath, CFile::modeCreate | + CFile::modeNoTruncate | + CFile::modeRead)) + { + LeashErrorBox("OnApply::Can't open configuration file", + CKrbProperties::m_krbPath); + return TRUE; + } + + CStdioFile krbCon2; + CString krbCon2File = CKrbProperties::m_krbPath; + krbCon2File += "___"; + if (!krbCon2.Open(krbCon2File, CFile::modeCreate | CFile::modeWrite)) + { + LeashErrorBox("OnApply:: Can't open configuration file", + CKrbProperties::m_krbPath); + return TRUE; + } + + CString readWrite; + krbCon.ReadString(readWrite); + krbCon2.WriteString(m_newDefaultRealm); + krbCon2.WriteString("\n"); + while (krbCon.ReadString(readWrite)) + { + krbCon2.WriteString(readWrite); + krbCon2.WriteString("\n"); + } + + krbCon.Close(); + krbCon2.Close(); + krbCon2.Remove(CKrbProperties::m_krbPath); + krbCon2.Rename(krbCon2File, CKrbProperties::m_krbPath); + + if (CLeashApp::m_hKrb5DLL) + { // Krb5 OR krb5 AND krb4 + if ( !CLeashApp::m_krbv5_profile ) { + CHAR confname[MAX_PATH]; + if (!CLeashApp::GetProfileFile(confname, sizeof(confname))) + { + const char *filenames[2]; + filenames[0] = confname; + filenames[1] = NULL; + pprofile_init(filenames, &CLeashApp::m_krbv5_profile); + } + } + + const char* Names[] = {"libdefaults", "default_realm", NULL}; + const char** names = Names; + + long retval = pprofile_update_relation(CLeashApp::m_krbv5_profile, + names, m_initDefaultRealm, m_newDefaultRealm); + + if (retval) + { + MessageBox("OnApply::The previous value cannot be found, the profile will not be saved!!!\ + \nIf this error persists after restarting Leash, contact your administrator.", + "Leash", MB_OK); + return TRUE; + } + + // Save to Kerberos Five config. file "Krb5.ini" + retval = pprofile_flush(CLeashApp::m_krbv5_profile); + } + + m_initDefaultRealm = m_newDefaultRealm; + return TRUE; +} + +void CKrbConfigOptions::OnSelchangeEditDefaultRealm() +{ + if (!m_startupPage2) + { + GetDlgItemText(IDC_EDIT_DEFAULT_REALM, m_newDefaultRealm); + SetModified(TRUE); + + if (CLeashApp::m_hKrb5DLL) + { + CHAR selRealm[REALM_SZ]; + strcpy(selRealm, m_newDefaultRealm); + const char* Section[] = {"realms", selRealm, "kdc", NULL}; + const char** section = Section; + char **values = NULL; + char * value = NULL; + + long retval = pprofile_get_values(CLeashApp::m_krbv5_profile, + section, &values); + + if (!retval && values) + SetDlgItemText(IDC_EDIT_REALM_HOSTNAME, *values); + else { + int dns_in_use = 0; + // Determine if we are using DNS for KDC lookups + retval = pprofile_get_string(CLeashApp::m_krbv5_profile, "libdefaults", + "dns_lookup_kdc", 0, 0, &value); + if (value == 0 && retval == 0) + retval = pprofile_get_string(CLeashApp::m_krbv5_profile, "libdefaults", + "dns_fallback", 0, 0, &value); + if (value == 0) { +#if KRB5_DNS_LOOKUP_KDC + dns_in_use = 1; +#else + dns_in_use = 0; +#endif + } else { + dns_in_use = config_boolean_to_int(value); + pprofile_release_string(value); + } + if (dns_in_use) + SetDlgItemText(IDC_EDIT_REALM_HOSTNAME, "DNS SRV record lookups will be used to find KDC"); + else + SetDlgItemText(IDC_EDIT_REALM_HOSTNAME, "No KDC information available"); + } + } + else + { + CHAR krbhst[MAX_HSTNM + 1]; + CHAR krbrlm[REALM_SZ + 1]; + + strcpy(krbrlm, CKrbConfigOptions::m_newDefaultRealm); + memset(krbhst, '\0', sizeof(krbhst)); + + // Check for Host + // don't use KRB4 - krb_get_krbhst - would have to re-logon, on file location + // change, to use this function + if (KFAILURE == pkrb_get_krbhst(krbhst, krbrlm, 1)) + { + MessageBox("OnSelchangeEditDefaultRealm::Unable to find the Host Server for your Default Realm!!!\ + \n 'Apply' your changes and try again.", + "Leash", MB_OK); + SetDlgItemText(IDC_EDIT_REALM_HOSTNAME, ""); + return; + } + + m_hostServer = krbhst; + if (strlen(krbhst)) + SetDlgItemText(IDC_EDIT_REALM_HOSTNAME, m_hostServer); + } + } +} + +void CKrbConfigOptions::OnEditchangeEditDefaultRealm() +{ + if (!m_startupPage2) + { + GetDlgItemText(IDC_EDIT_DEFAULT_REALM, m_newDefaultRealm); + SetModified(TRUE); + } +} + +void CKrbConfigOptions::OnShowWindow(BOOL bShow, UINT nStatus) +{ + CPropertyPage::OnShowWindow(bShow, nStatus); + + if (CLeashApp::m_hKrb5DLL) + ResetDefaultRealmComboBox(); + + SetDlgItemText(IDC_EDIT_REALM_HOSTNAME, m_hostServer); +} + +void CKrbConfigOptions::ResetDefaultRealmComboBox() +{ // Krb5 is loaded + // Reset Config Tab's Default Realm Combo Editbox + const char* rootSection[] = {"realms", NULL}; + const char** rootsec = rootSection; + char **sections = NULL, + **cpp = NULL, + *value = 0; + int dns; + + long retval = pprofile_get_string(CLeashApp::m_krbv5_profile, "libdefaults", + "dns_lookup_kdc", 0, 0, &value); + if (value == 0 && retval == 0) + retval = pprofile_get_string(CLeashApp::m_krbv5_profile, "libdefaults", + "dns_fallback", 0, 0, &value); + if (value == 0) { +#if KRB5_DNS_LOOKUP_KDC + dns = 1; +#else + dns = 0; +#endif + } else { + dns = config_boolean_to_int(value); + pprofile_release_string(value); + } + + retval = pprofile_get_subsection_names(CLeashApp::m_krbv5_profile, + rootsec , §ions); + + if (retval) + { + m_hostServer = _T(""); + + // This is not a fatal error if DNS KDC Lookup is being used. + // Determine the starting value for DNS KDC Lookup Checkbox + if ( dns ) + return; + + m_profileError = TRUE; + } + + m_krbRealmEditbox.ResetContent(); + + if ( !m_profileError ) { + for (cpp = sections; *cpp; cpp++) + { + if (CB_ERR == m_krbRealmEditbox.FindStringExact(-1, *cpp)) + { // no dups + if (CB_ERR == m_krbRealmEditbox.AddString(*cpp)) + { + ::MessageBox(NULL, "ResetDefaultRealmComboBox::Can't add to Kerberos Realm Combobox", + "Leash", MB_OK); + return; + } + } + else + m_dupEntriesError = TRUE; + } + } + + if (!m_newDefaultRealm.IsEmpty()) { + + if (CB_ERR == m_krbRealmEditbox.FindStringExact(-1, m_newDefaultRealm)) + { // no dups + m_krbRealmEditbox.AddString(m_newDefaultRealm); + } + m_krbRealmEditbox.SelectString(-1, m_newDefaultRealm); + + const char* Section[] = {"realms", m_newDefaultRealm, "kdc", NULL}; //theSection + const char** section = Section; + char **values = NULL; + + retval = pprofile_get_values(CLeashApp::m_krbv5_profile, + section, &values); + + if (!retval && values) + m_hostServer = *values; + else { + if (dns) + m_hostServer = "DNS SRV record lookups will be used to find KDC"; + else { + m_hostServer = "No KDC information available"; + } + } + } +} + +BOOL CKrbConfigOptions::PreTranslateMessage(MSG* pMsg) +{ + if (!m_startupPage2) + { + if (m_noKrbFileError) + { + LeashErrorBox("PreTranslateMessage::Unable to open configuration file", + !strlen(CKrbProperties::m_krbPath) ? KRB_FILE : + CKrbProperties::m_krbPath); + m_noKrbFileError = FALSE; + } + + if (m_noKrbhostWarning) + { + MessageBox("PreTranslateMessage::Unable to locate the Kerberos Host for your Kerberos Realm!", + "Leash", MB_OK); + m_noKrbhostWarning = FALSE; + } + + if (m_dupEntriesError) + { + MessageBox("PreTranslateMessage::Found duplicate entries in the Kerberos 5 Config. File!!!\ + \nPlease contact your Administrator.", + "Leash", MB_OK); + + m_dupEntriesError = FALSE; + } + + if (m_profileError) + { + MessageBox("PreTranslateMessage::Unable to open Kerberos 5 Config. File!!!\ + \nIf this error persists, contact your administrator.", + "Leash", MB_OK); + m_profileError = FALSE; + } + + if (m_noRealm) + { + MessageBox("PreTranslateMessage::Unable to determine the Default Realm.\ + \n Contact your Administrator!", + "Leash", MB_OK); + + m_noRealm = FALSE; + } + } + + m_startupPage2 = FALSE; + return CPropertyPage::PreTranslateMessage(pMsg); +} + + +BEGIN_MESSAGE_MAP(CKrbConfigOptions, CPropertyPage) + //{{AFX_MSG_MAP(CKrbConfigOptions) + ON_WM_SHOWWINDOW() + ON_CBN_EDITCHANGE(IDC_EDIT_DEFAULT_REALM, OnEditchangeEditDefaultRealm) + ON_CBN_SELCHANGE(IDC_EDIT_DEFAULT_REALM, OnSelchangeEditDefaultRealm) + ON_BN_CLICKED(IDC_BUTTON_KRB_HELP, OnButtonKrbHelp) + ON_BN_CLICKED(IDC_BUTTON_KRBREALM_HELP, OnButtonKrbrealmHelp) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + + + +void CKrbConfigOptions::OnButtonKrbHelp() +{ + MessageBox("No Help Available!", "Leash", MB_OK); +} + +void CKrbConfigOptions::OnButtonKrbrealmHelp() +{ + MessageBox("No Help Available!", "Leash", MB_OK); +} diff --git a/src/windows/leash/KrbConfigOptions.h b/src/windows/leash/KrbConfigOptions.h new file mode 100644 index 000000000..3169e71f5 --- /dev/null +++ b/src/windows/leash/KrbConfigOptions.h @@ -0,0 +1,89 @@ +// ************************************************************************************** +// File: KrbConfigOptions.h +// By: Arthur David Leather +// Created: 12/02/98 +// Copyright @1998 Massachusetts Institute of Technology - All rights reserved. +// Description: H file for KrbProperties.cpp. Contains variables and functions +// for Kerberos Four Properties +// +// History: +// +// MM/DD/YY Inits Description of Change +// 2/01/98 ADL Original +// ************************************************************************************** + + +#if !defined(AFX_CONFIGOPTIONS_H__CD702F99_7495_11D0_8FDC_00C04FC2A0C2__INCLUDED_) +#define AFX_CONFIGOPTIONS_H__CD702F99_7495_11D0_8FDC_00C04FC2A0C2__INCLUDED_ + +#if _MSC_VER >= 1000 +#pragma once +#endif // _MSC_VER >= 1000 +// Krb4Properties.h : header file +// + +#include "Resource.h" + + +/////////////////////////////////////////////////////////////////////// +// CKrbConfigOptions dialog + +class CKrbConfigOptions : public CPropertyPage +{ +// Construction +private: + DECLARE_DYNCREATE(CKrbConfigOptions) + BOOL m_startupPage2; + BOOL m_noKrbFileError; + BOOL m_noKrbhostWarning; + static BOOL m_profileError; + static BOOL m_dupEntriesError; + BOOL m_noRealm; + CString m_initDefaultRealm; + static CString m_newDefaultRealm; ///// also used for CKrb4DomainRealmMaintenance + static CString m_hostServer; + + static void ResetDefaultRealmComboBox(); + +public: + CKrbConfigOptions(); + ~CKrbConfigOptions(); + +// Dialog Data + //{{AFX_DATA(CKrbConfigOptions) + enum { IDD = IDD_KRB_PROP_CONTENT }; + static CComboBox m_krbRealmEditbox; + //}}AFX_DATA + + +// Overrides + // ClassWizard generate virtual function overrides + //{{AFX_VIRTUAL(CKrbConfigOptions) + public: + virtual BOOL PreTranslateMessage(MSG* pMsg); + protected: + virtual VOID DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + + virtual BOOL OnApply(); + +// Implementation +protected: + // Generated message map functions + //{{AFX_MSG(CKrbConfigOptions) + virtual BOOL OnInitDialog(); + afx_msg void OnShowWindow(BOOL bShow, UINT nStatus); + afx_msg void OnEditchangeEditDefaultRealm(); + afx_msg void OnSelchangeEditDefaultRealm(); + afx_msg void OnButtonKrbHelp(); + afx_msg void OnButtonKrbrealmHelp(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + +}; + +///////////////////////////////////////////////////////////////////////////// +//{{AFX_INSERT_LOCATION}} +// Microsoft Developer Studio will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_CONFIGOPTIONS_H__CD702F99_7495_11D0_8FDC_00C04FC2A0C2__INCLUDED_) diff --git a/src/windows/leash/KrbDomainRealmMaintenance.cpp b/src/windows/leash/KrbDomainRealmMaintenance.cpp new file mode 100644 index 000000000..cb13137d8 --- /dev/null +++ b/src/windows/leash/KrbDomainRealmMaintenance.cpp @@ -0,0 +1,435 @@ +// CKrbDomainRealmMaintenance.cpp : implementation file +// + +#include "stdafx.h" +#include "leash.h" +#include "KrbDomainRealmMaintenance.h" +#include "Krb4AddToDomainRealmList.h" +#include "Krb4EditDomainRealmList.h" +#include "KrbProperties.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CKrbDomainRealmMaintenance dialog + + +CKrbDomainRealmMaintenance::CKrbDomainRealmMaintenance(CWnd* pParent /*=NULL*/) + :CPropertyPage(CKrbDomainRealmMaintenance::IDD) +{ + m_dupEntiesError = FALSE; + //{{AFX_DATA_INIT(CKrbDomainRealmMaintenance) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT +} + + +void CKrbDomainRealmMaintenance::DoDataExchange(CDataExchange* pDX) +{ + CPropertyPage::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CKrbDomainRealmMaintenance) + DDX_Control(pDX, IDC_LIST_DOMAINREALM, m_KDCDomainList); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CKrbDomainRealmMaintenance, CPropertyPage) + //{{AFX_MSG_MAP(CKrbDomainRealmMaintenance) + ON_BN_CLICKED(IDC_BUTTON_HOST_ADD, OnButtonHostAdd) + ON_BN_CLICKED(IDC_BUTTON_HOST_EDIT, OnButtonHostEdit) + ON_BN_CLICKED(ID_BUTTON_HOST_REMOVE, OnButtonHostRemove) + ON_LBN_DBLCLK(IDC_LIST_DOMAINREALM, OnDblclkListDomainrealm) + ON_BN_CLICKED(IDC_BUTTON_HOSTMAINT_HELP, OnButtonHostmaintHelp) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CKrbDomainRealmMaintenance message handlers + +BOOL CKrbDomainRealmMaintenance::OnInitDialog() +{ + CPropertyPage::OnInitDialog(); + + char theName[REALM_SZ + 1]; + char theNameValue[REALM_SZ + MAX_HSTNM + 2]; + const char* Section[] = {"domain_realm", theName, NULL}; //theSection + const char** section = Section; + char **values = NULL, + **vpp = NULL; + + const char* rootSection[] = {"domain_realm", NULL}; + const char** rootsec = rootSection; + char **sections = NULL, + **cpp = NULL; + + long retval = pprofile_get_relation_names(CLeashApp::m_krbv5_profile, + rootsec, §ions); + + if (retval && PROF_NO_RELATION != retval) + { + MessageBox("OnInitDialog::There is on error, profile will not be saved!!!\ + \nIf this error persist, contact your administrator.", + "Leash", MB_OK); + return TRUE; + } + + + for (cpp = sections; *cpp; cpp++) + { + strcpy(theName, *cpp); + retval = pprofile_get_values(CLeashApp::m_krbv5_profile, + section, &values); + + for (vpp = values; *vpp; vpp++) + { + strcpy(theNameValue, theName); + strcat(theNameValue, " "); + strcat(theNameValue, *vpp); + + if (LB_ERR == m_KDCDomainList.FindStringExact(-1, theNameValue)) + { + if (LB_ERR == m_KDCDomainList.AddString(theNameValue)) + { + MessageBox("OnInitDialog::Can't add to Kerberos Domain Listbox", + "Leash", MB_OK); + return FALSE; + } + } + else + m_dupEntiesError = TRUE; + } + } + + m_KDCDomainList.SetCurSel(0); + + if (!m_KDCDomainList.GetCount()) + { + GetDlgItem(ID_BUTTON_HOST_REMOVE)->EnableWindow(FALSE); + GetDlgItem(IDC_BUTTON_HOST_EDIT)->EnableWindow(FALSE); + } + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +BOOL CKrbDomainRealmMaintenance::OnApply() +{ + if (!CLeashApp::m_krbv5_profile) { + CHAR confname[MAX_PATH]; + if (!CLeashApp::GetProfileFile(confname, sizeof(confname))) + { + const char *filenames[2]; + filenames[0] = confname; + filenames[1] = NULL; + pprofile_init(filenames, &CLeashApp::m_krbv5_profile); + } + } + + // Save to Kerberos Five config. file "Krb5.ini" + long retval = pprofile_flush(CLeashApp::m_krbv5_profile); + + if (retval && PROF_NO_RELATION != retval) + { + MessageBox("OnApply::There is on error, profile will not be saved!!!\ + \nIf this error persist, contact your administrator.", + "Leash", MB_OK); + return TRUE; + } + + // Save to Kerberos Four config. file "Krb.con" + CStdioFile krbrealmCon; + if (!krbrealmCon.Open(CKrbProperties::m_krbrealmPath, CFile::modeCreate | + CFile::modeNoTruncate | + CFile::modeReadWrite)) + { + LeashErrorBox("OnApply::Can't open Configuration File", + CKrbProperties::m_krbrealmPath); + return TRUE; + } + + krbrealmCon.SetLength(0); + + char theNameValue[REALM_SZ + MAX_HSTNM + 2]; + + for (INT maxItems = m_KDCDomainList.GetCount(), item = 0; item < maxItems; item++) + { + if (LB_ERR == m_KDCDomainList.GetText(item, theNameValue)) + ASSERT(0); + + krbrealmCon.WriteString(theNameValue); + krbrealmCon.WriteString("\n"); + } + + krbrealmCon.Close(); + return TRUE; +} + +void CKrbDomainRealmMaintenance::OnCancel() +{ + CHAR fileName[MAX_PATH]; + + if (CLeashApp::GetProfileFile(fileName, sizeof(fileName))) + { + MessageBox("Can't locate Kerberos Five Config. file!", "Error", MB_OK); + return; + } + + pprofile_abandon(CLeashApp::m_krbv5_profile); + + const char *filenames[2]; + filenames[0] = fileName; + filenames[1] = NULL; + pprofile_init(filenames, &CLeashApp::m_krbv5_profile); + + CPropertyPage::OnCancel(); +} + +void CKrbDomainRealmMaintenance::OnButtonHostAdd() +{ + CKrb4AddToDomainRealmList addToDomainRealmList; + if (IDOK == addToDomainRealmList.DoModal()) + { + char theName[MAX_HSTNM + 1]; + const char* Section[] = {"domain_realm", theName, NULL}; + const char** section = Section; + + if (addToDomainRealmList.GetNewRealm().IsEmpty()) + ASSERT(0); + + if (CheckForDupDomain(addToDomainRealmList.GetNewDomainHost())) + { + MessageBox("Can't have duplicate Host/Domains!\nYour entry will not be saved to list", + "Leash", MB_OK); + return; + } + + CString newLine; + newLine = addToDomainRealmList.GetNewDomainHost() + " " + addToDomainRealmList.GetNewRealm(); + + if (LB_ERR != m_KDCDomainList.FindStringExact(-1, newLine)) + { + MessageBox("We can't have duplicates!\nYour entry was not saved to list.", + "Leash", MB_OK); + return; + } + + CString newHost; // new section in the profile linklist + strcpy(theName, addToDomainRealmList.GetNewDomainHost()); + + long retval = pprofile_add_relation(CLeashApp::m_krbv5_profile, + section, addToDomainRealmList.GetNewRealm()); + + if (retval) + { + MessageBox("OnButtonHostAdd::There is on error, profile will not be saved!!!\ + \nIf this error persist, contact your administrator.", + "Leash", MB_OK); + } + + m_KDCDomainList.AddString(newLine); + SetModified(TRUE); + + if (1 == m_KDCDomainList.GetCount()) + { + GetDlgItem(ID_BUTTON_HOST_REMOVE)->EnableWindow(); + GetDlgItem(IDC_BUTTON_HOST_EDIT)->EnableWindow(); + } + } + +} + +void CKrbDomainRealmMaintenance::OnButtonHostEdit() +{ + INT selItemIndex = m_KDCDomainList.GetCurSel(); + LPSTR pSelItem = new char[m_KDCDomainList.GetTextLen(selItemIndex) + 1]; + if (!pSelItem) + ASSERT(0); + + CHAR theName[MAX_HSTNM + 1]; + char theNameValue[REALM_SZ + MAX_HSTNM + 2]; + CHAR OLD_VALUE[REALM_SZ + 1]; + m_KDCDomainList.GetText(selItemIndex, theName); + strcpy(pSelItem, theName); + + LPSTR pselItem = strchr(theName, ' '); + if (pselItem) + *pselItem = 0; + else + ASSERT(0); + + strcpy(OLD_VALUE, pselItem + 1); + strcpy(theNameValue, pSelItem); + + CKrb4EditDomainRealmList editDomainRealmList(pSelItem); + + if (IDOK == editDomainRealmList.DoModal()) + { + if (0 != strcmp(theName, editDomainRealmList.GetDomainHost()) + && CheckForDupDomain(editDomainRealmList.GetDomainHost())) + { // Duplicate Host/Domain Error + MessageBox("We can't have duplicate Host/Domains!\nYour entry will not be saved to list", + "Leash", MB_OK); + return; + } + + const char* Section[] = {"domain_realm", theName, NULL}; + const char** section = Section; + + CString editedHost = editDomainRealmList.GetEditedItem(); + + if (0 != editedHost.CompareNoCase(theNameValue) && + LB_ERR != m_KDCDomainList.FindStringExact(-1, editedHost)) + { + MessageBox("We can't have duplicate Realms!\nYour entry was not saved to list.", + "Leash", MB_OK); + delete [] pSelItem; + return; + } + + long retval = pprofile_update_relation(CLeashApp::m_krbv5_profile, + section, OLD_VALUE, NULL); + + if (retval) + { + MessageBox("OnButtonHostEdit::There is on error, profile will not be saved!!!\ + \nIf this error persist, contact your administrator.", + "Leash", MB_OK); + return; + } + + strcpy(theName, editDomainRealmList.GetDomainHost()); + + retval = pprofile_add_relation(CLeashApp::m_krbv5_profile, + section, editDomainRealmList.GetRealm()); + + + if (retval) + { // thsi might not be the best way to handle this type of error + MessageBox("OnButtonHostEdit::There is on error, profile will not be saved!!!\ + \nIf this error persist, contact your administrator.", + "Leash", MB_OK); + return; + } + + m_KDCDomainList.DeleteString(selItemIndex); + m_KDCDomainList.AddString(editedHost); + selItemIndex = m_KDCDomainList.FindStringExact(-1, editedHost); + m_KDCDomainList.SetCurSel(selItemIndex); + + SetModified(TRUE); + } + + delete [] pSelItem; +} + +void CKrbDomainRealmMaintenance::OnDblclkListDomainrealm() +{ + OnButtonHostEdit(); +} + +void CKrbDomainRealmMaintenance::OnButtonHostRemove() +{ + CHAR theName[MAX_HSTNM + 1]; + CHAR OLD_VALUE[REALM_SZ + 1]; + char theNameValue[REALM_SZ + MAX_HSTNM + 2]; + const char* Section[] = {"domain_realm", theName, NULL}; + const char** section = Section; + + INT curSel = m_KDCDomainList.GetCurSel(); + m_KDCDomainList.GetText(curSel, theNameValue); + + CString serverHostMsg; + CString serverHost; + serverHostMsg.Format("Your about to remove Host/Domain \"%s\" from the list!\n\nContinue?", + theNameValue); + + if (IDYES != AfxMessageBox(serverHostMsg, MB_YESNO)) + return; + + LPSTR pNameValue = strchr(theNameValue, ' '); + if (pNameValue) + { + *pNameValue = 0; + strcpy(theName, theNameValue); + pNameValue++; + strcpy(OLD_VALUE, pNameValue); + } + else + ASSERT(0); + + if (!m_KDCDomainList.GetCount()) + { + GetDlgItem(ID_BUTTON_HOSTNAME_REMOVE)->EnableWindow(FALSE); + GetDlgItem(IDC_BUTTON_HOSTNAME_EDIT)->EnableWindow(FALSE); + } + + long retval = pprofile_update_relation(CLeashApp::m_krbv5_profile, + section, OLD_VALUE, NULL); + + if (retval) + { + MessageBox("OnButtonHostRemove::There is on error, profile will not be saved!!!\ + \nIf this error persist, contact your administrator.", + "Leash", MB_OK); + return; + } + + m_KDCDomainList.DeleteString(curSel); // Single Sel Listbox + + if (-1 == m_KDCDomainList.SetCurSel(curSel)) + m_KDCDomainList.SetCurSel(curSel - 1); + + if (!m_KDCDomainList.GetCount()) + { + GetDlgItem(ID_BUTTON_HOST_REMOVE)->EnableWindow(FALSE); + GetDlgItem(IDC_BUTTON_HOST_EDIT)->EnableWindow(FALSE); + } + + SetModified(TRUE); +} + + +BOOL CKrbDomainRealmMaintenance::PreTranslateMessage(MSG* pMsg) +{ + if (m_dupEntiesError) + { + MessageBox("Found an error (duplicate items) in your Kerberos Five Config. File!!!\ + \nPlease contract your Administrator.", + "Leash", MB_OK); + + m_dupEntiesError = FALSE; + } + + return CPropertyPage::PreTranslateMessage(pMsg); +} + +BOOL CKrbDomainRealmMaintenance::CheckForDupDomain(CString& newDomainHost) +{ + char theName[REALM_SZ + MAX_HSTNM + 2]; + + for (INT maxItems = m_KDCDomainList.GetCount(), item = 0; item < maxItems; item++) + { + if (LB_ERR == m_KDCDomainList.GetText(item, theName)) + ASSERT(0); + + LPSTR pValue = strchr(theName, ' '); + if (pValue) + *pValue = 0; + else + ASSERT(0); + + if (0 == newDomainHost.CompareNoCase(theName)) + return TRUE; + } + + return FALSE; +} + +void CKrbDomainRealmMaintenance::OnButtonHostmaintHelp() +{ + MessageBox("No Help Available!", "Leash", MB_OK); +} diff --git a/src/windows/leash/KrbDomainRealmMaintenance.h b/src/windows/leash/KrbDomainRealmMaintenance.h new file mode 100644 index 000000000..e22e86e84 --- /dev/null +++ b/src/windows/leash/KrbDomainRealmMaintenance.h @@ -0,0 +1,59 @@ +#if !defined(AFX_KRBDOMAINREALMMAINTENANCE_H__6DB290A6_E14D_11D2_95CE_0000861B8A3C__INCLUDED_) +#define AFX_KRBDOMAINREALMMAINTENANCE_H__6DB290A6_E14D_11D2_95CE_0000861B8A3C__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// CKrbDomainRealmMaintenance.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CKrbDomainRealmMaintenance dialog + +class CKrbDomainRealmMaintenance : public CPropertyPage +{ +// Construction +private: + BOOL m_dupEntiesError; + BOOL CheckForDupDomain(CString& newDomainHost); + +public: + CKrbDomainRealmMaintenance(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CKrbDomainRealmMaintenance) + enum { IDD = IDD_KRB_DOMAINREALM_MAINT }; + CListBox m_KDCDomainList; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CKrbDomainRealmMaintenance) + public: + virtual BOOL PreTranslateMessage(MSG* pMsg); + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CKrbDomainRealmMaintenance) + virtual void OnCancel(); + virtual BOOL OnApply(); + virtual BOOL OnInitDialog(); + afx_msg void OnButtonHostAdd(); + afx_msg void OnButtonHostEdit(); + afx_msg void OnButtonHostRemove(); + afx_msg void OnDblclkListDomainrealm(); + afx_msg void OnButtonHostmaintHelp(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_KRBDOMAINREALMMAINTENANCE_H__6DB290A6_E14D_11D2_95CE_0000861B8A3C__INCLUDED_) diff --git a/src/windows/leash/KrbEditHostServer.cpp b/src/windows/leash/KrbEditHostServer.cpp new file mode 100644 index 000000000..4245c2b55 --- /dev/null +++ b/src/windows/leash/KrbEditHostServer.cpp @@ -0,0 +1,97 @@ +// ************************************************************************************** +// File: KrbEditHostServer.cpp +// By: Arthur David Leather +// Created: 12/02/98 +// Copyright @1998 Massachusetts Institute of Technology - All rights reserved. +// Description: CPP file for KrbEditHostServer.h. Contains variables and functions +// for Kerberos Four and Five Properties +// +// History: +// +// MM/DD/YY Inits Description of Change +// 12/02/98 ADL Original +// ************************************************************************************** + + +#include "stdafx.h" +#include "leash.h" +#include "Krb4Properties.h" +#include "KrbEditHostServer.h" +#include "lglobals.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CKrbEditHostServer dialog + +CKrbEditHostServer::CKrbEditHostServer(CString& editItem, CWnd* pParent) + : CDialog(CKrbEditHostServer::IDD, pParent) +{ + m_startup = TRUE; + m_newHost = editItem; + + //{{AFX_DATA_INIT(CKrbEditHostServer) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT +} + +void CKrbEditHostServer::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CKrbEditHostServer) + // NOTE: the ClassWizard will add DDX and DDV calls here + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CKrbEditHostServer, CDialog) + //{{AFX_MSG_MAP(CKrbEditHostServer) + ON_WM_SHOWWINDOW() + ON_EN_CHANGE(IDC_EDIT_KDC_HOST, OnChangeEditKdcHost) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CKrbEditHostServer message handlers + +BOOL CKrbEditHostServer::OnInitDialog() +{ + CDialog::OnInitDialog(); + + SetDlgItemText(IDC_EDIT_KDC_HOST, m_newHost); + return TRUE; +} + +void CKrbEditHostServer::OnShowWindow(BOOL bShow, UINT nStatus) +{ + CDialog::OnShowWindow(bShow, nStatus); + m_startup = FALSE; +} + +void CKrbEditHostServer::OnChangeEditKdcHost() +{ + if (!m_startup) + GetDlgItemText(IDC_EDIT_KDC_HOST, m_newHost); +} + +void CKrbEditHostServer::OnOK() +{ + m_newHost.TrimLeft(); + m_newHost.TrimRight(); + + if (m_newHost.IsEmpty()) + { // stay + MessageBox("OnOK::The Server field must be filled in!", + "Error", MB_OK); + } + else if (-1 != m_newHost.Find(' ')) + { // stay + MessageBox("OnOK::Illegal space found!", "Error", MB_OK); + } + else + CDialog::OnOK(); // exit +} diff --git a/src/windows/leash/KrbEditHostServer.h b/src/windows/leash/KrbEditHostServer.h new file mode 100644 index 000000000..5cbbd0334 --- /dev/null +++ b/src/windows/leash/KrbEditHostServer.h @@ -0,0 +1,69 @@ +// ************************************************************************************** +// File: KrbEditHostServer.h +// By: Arthur David Leather +// Created: 12/02/98 +// Copyright @1998 Massachusetts Institute of Technology - All rights reserved. +// Description: H file for KrbEditHostServer.cpp. Contains variables and functions +// for Kerberos Four and Five Properties +// +// History: +// +// MM/DD/YY Inits Description of Change +// 12/02/98 ADL Original +// ************************************************************************************** + + + +#if !defined(AFX_EDITHOST_H__26A1E1F7_9117_11D2_94D0_0000861B8A3C__INCLUDED_) +#define AFX_EDITHOST_H__26A1E1F7_9117_11D2_94D0_0000861B8A3C__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// EditRealmHostList.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CKrbEditHostServer dialog + +class CKrbEditHostServer : public CDialog +{ +// Construction +private: + CString m_newHost; + BOOL m_startup; + +public: + CKrbEditHostServer(CString& editItem, CWnd* pParent = NULL); + CString GetEditedItem() {return m_newHost;} + +// Dialog Data + //{{AFX_DATA(CKrbEditHostServer) + enum { IDD = IDD_KRB_EDIT_KDC_HOSTSERVER }; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CKrbEditHostServer) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CKrbEditHostServer) + afx_msg void OnShowWindow(BOOL bShow, UINT nStatus); + virtual void OnOK(); + virtual BOOL OnInitDialog(); + afx_msg void OnChangeEditKdcHost(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_EDITHOST_H__26A1E1F7_9117_11D2_94D0_0000861B8A3C__INCLUDED_) diff --git a/src/windows/leash/KrbEditRealm.cpp b/src/windows/leash/KrbEditRealm.cpp new file mode 100644 index 000000000..caa1e1553 --- /dev/null +++ b/src/windows/leash/KrbEditRealm.cpp @@ -0,0 +1,99 @@ +// ************************************************************************************** +// File: KrbEditRealm.cpp +// By: Arthur David Leather +// Created: 12/02/98 +// Copyright @1998 Massachusetts Institute of Technology - All rights reserved. +// Description: CPP file for KrbEditRealm.h. Contains variables and functions +// for Kerberos Four and Five Properties +// +// History: +// +// MM/DD/YY Inits Description of Change +// 12/02/98 ADL Original +// ************************************************************************************** + + +#include "stdafx.h" +#include "leash.h" +#include "Krb4Properties.h" +#include "KrbEditRealm.h" +#include "lglobals.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CKrbEditRealm dialog + +CKrbEditRealm::CKrbEditRealm(CString& editItem, CWnd* pParent) + : CDialog(CKrbEditRealm::IDD, pParent) +{ + m_startup = TRUE; + m_newRealm = editItem; + + + //{{AFX_DATA_INIT(CKrbEditRealm) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT +} + +void CKrbEditRealm::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CKrbEditRealm) + // NOTE: the ClassWizard will add DDX and DDV calls here + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CKrbEditRealm, CDialog) + //{{AFX_MSG_MAP(CKrbEditRealm) + ON_WM_SHOWWINDOW() + ON_EN_CHANGE(IDC_EDIT_REALM, OnChangeEditRealm) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CKrbEditRealm message handlers + +BOOL CKrbEditRealm::OnInitDialog() +{ + CDialog::OnInitDialog(); + + SetDlgItemText(IDC_EDIT_REALM, m_newRealm); + + return TRUE; +} + +void CKrbEditRealm::OnShowWindow(BOOL bShow, UINT nStatus) +{ + CDialog::OnShowWindow(bShow, nStatus); + m_startup = FALSE; +} + +void CKrbEditRealm::OnChangeEditRealm() +{ + if (!m_startup) + GetDlgItemText(IDC_EDIT_REALM, m_newRealm); +} + +void CKrbEditRealm::OnOK() +{ + m_newRealm.TrimLeft(); + m_newRealm.TrimRight(); + + if (m_newRealm.IsEmpty()) + { // stay + MessageBox("OnOK::The Realm field must be filled in!", + "Leash", MB_OK); + } + else if (-1 != m_newRealm.Find(' ')) + { // stay + MessageBox("OnOK::Illegal space found!", "Leash", MB_OK); + } + else + CDialog::OnOK(); // exit +} diff --git a/src/windows/leash/KrbEditRealm.h b/src/windows/leash/KrbEditRealm.h new file mode 100644 index 000000000..4bf5fdfab --- /dev/null +++ b/src/windows/leash/KrbEditRealm.h @@ -0,0 +1,75 @@ +// ************************************************************************************** +// File: KrbEditRealm.h +// By: Arthur David Leather +// Created: 12/02/98 +// Copyright @1998 Massachusetts Institute of Technology - All rights reserved. +// Description: H file for Krb4EditRealmHostList.cpp. Contains variables and functions +// for Kerberos Four Properties +// +// History: +// +// MM/DD/YY Inits Description of Change +// 12/02/98 ADL Original +// ************************************************************************************** + + + +#if !defined(AFX_EDITREALMHOSTLIST_H__26A1E1F7_9117_11D2_94D0_0000861B8A3C__INCLUDED_) +#define AFX_EDITREALMHOSTLIST_H__26A1E1F7_9117_11D2_94D0_0000861B8A3C__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// EditRealmHostList.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CKrbEditRealm dialog + +class CKrbEditRealm : public CDialog +{ +// Construction +private: + //CString m_editItem; + //CString m_initRealm; + CString m_newRealm; + //CString m_initHost; + //CString m_newHost; + //BOOL m_initAdmin; + //BOOL m_newAdmin; + BOOL m_startup; + +public: + CKrbEditRealm(CString& editItem, CWnd* pParent = NULL); + CString GetEditedItem() {return m_newRealm;} + +// Dialog Data + //{{AFX_DATA(CKrbEditRealm) + enum { IDD = IDD_KRB_EDIT_REALM }; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CKrbEditRealm) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CKrbEditRealm) + afx_msg void OnShowWindow(BOOL bShow, UINT nStatus); + afx_msg void OnChangeEditRealm(); + virtual void OnOK(); + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_EDITREALMHOSTLIST_H__26A1E1F7_9117_11D2_94D0_0000861B8A3C__INCLUDED_) diff --git a/src/windows/leash/KrbMiscConfigOpt.cpp b/src/windows/leash/KrbMiscConfigOpt.cpp new file mode 100644 index 000000000..cdb4c677d --- /dev/null +++ b/src/windows/leash/KrbMiscConfigOpt.cpp @@ -0,0 +1,1012 @@ +//***************************************************************************** +// File: KrbMiscConfigOpt.cpp +// By: Paul B. Hill +// Created: 08/12/1999 +// Copyright: @1999 Massachusetts Institute of Technology - All rights +// reserved. +// Description: CPP file for KrbMiscConfigOpt.cpp. Contains variables +// and functions for Kerberos Properties. +// +// History: +// +// MM/DD/YY Inits Description of Change +// 08/12/99 PBH Original +//***************************************************************************** + +#include "stdafx.h" +#include "Leash.h" +#include "KrbProperties.h" +#include "KrbMiscConfigOpt.h" +#include "LeashFileDialog.h" +#include "LeashMessageBox.h" +#include "lglobals.h" +#include +#include "reminder.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + + +/////////////////////////////////////////////////////////////////////// +// CKrbMiscConfigOpt property page + +UINT CKrbMiscConfigOpt::m_DefaultLifeTime; +CString CKrbMiscConfigOpt::m_initDefaultLifeTimeMin; +CString CKrbMiscConfigOpt::m_newDefaultLifeTimeMin; +CEdit CKrbMiscConfigOpt::m_krbLifeTimeMinEditbox; +CString CKrbMiscConfigOpt::m_initDefaultLifeTimeHr; +CString CKrbMiscConfigOpt::m_newDefaultLifeTimeHr; +CEdit CKrbMiscConfigOpt::m_krbLifeTimeHrEditbox; +CString CKrbMiscConfigOpt::m_initDefaultLifeTimeDay; +CString CKrbMiscConfigOpt::m_newDefaultLifeTimeDay; +CEdit CKrbMiscConfigOpt::m_krbLifeTimeDayEditbox; + +UINT CKrbMiscConfigOpt::m_DefaultRenewTill; +CString CKrbMiscConfigOpt::m_initDefaultRenewTillMin; +CString CKrbMiscConfigOpt::m_newDefaultRenewTillMin; +CEdit CKrbMiscConfigOpt::m_krbRenewTillMinEditbox; +CString CKrbMiscConfigOpt::m_initDefaultRenewTillHr; +CString CKrbMiscConfigOpt::m_newDefaultRenewTillHr; +CEdit CKrbMiscConfigOpt::m_krbRenewTillHrEditbox; +CString CKrbMiscConfigOpt::m_initDefaultRenewTillDay; +CString CKrbMiscConfigOpt::m_newDefaultRenewTillDay; +CEdit CKrbMiscConfigOpt::m_krbRenewTillDayEditbox; + +UINT CKrbMiscConfigOpt::m_DefaultLifeMin; +CString CKrbMiscConfigOpt::m_initDefaultLifeMinMin; +CString CKrbMiscConfigOpt::m_newDefaultLifeMinMin; +CEdit CKrbMiscConfigOpt::m_krbLifeMinMinEditbox; +CString CKrbMiscConfigOpt::m_initDefaultLifeMinHr; +CString CKrbMiscConfigOpt::m_newDefaultLifeMinHr; +CEdit CKrbMiscConfigOpt::m_krbLifeMinHrEditbox; +CString CKrbMiscConfigOpt::m_initDefaultLifeMinDay; +CString CKrbMiscConfigOpt::m_newDefaultLifeMinDay; +CEdit CKrbMiscConfigOpt::m_krbLifeMinDayEditbox; + +UINT CKrbMiscConfigOpt::m_DefaultLifeMax; +CString CKrbMiscConfigOpt::m_initDefaultLifeMaxMin; +CString CKrbMiscConfigOpt::m_newDefaultLifeMaxMin; +CEdit CKrbMiscConfigOpt::m_krbLifeMaxMinEditbox; +CString CKrbMiscConfigOpt::m_initDefaultLifeMaxHr; +CString CKrbMiscConfigOpt::m_newDefaultLifeMaxHr; +CEdit CKrbMiscConfigOpt::m_krbLifeMaxHrEditbox; +CString CKrbMiscConfigOpt::m_initDefaultLifeMaxDay; +CString CKrbMiscConfigOpt::m_newDefaultLifeMaxDay; +CEdit CKrbMiscConfigOpt::m_krbLifeMaxDayEditbox; + +UINT CKrbMiscConfigOpt::m_DefaultRenewMin; +CString CKrbMiscConfigOpt::m_initDefaultRenewMinMin; +CString CKrbMiscConfigOpt::m_newDefaultRenewMinMin; +CEdit CKrbMiscConfigOpt::m_krbRenewMinMinEditbox; +CString CKrbMiscConfigOpt::m_initDefaultRenewMinHr; +CString CKrbMiscConfigOpt::m_newDefaultRenewMinHr; +CEdit CKrbMiscConfigOpt::m_krbRenewMinHrEditbox; +CString CKrbMiscConfigOpt::m_initDefaultRenewMinDay; +CString CKrbMiscConfigOpt::m_newDefaultRenewMinDay; +CEdit CKrbMiscConfigOpt::m_krbRenewMinDayEditbox; + +UINT CKrbMiscConfigOpt::m_DefaultRenewMax; +CString CKrbMiscConfigOpt::m_initDefaultRenewMaxMin; +CString CKrbMiscConfigOpt::m_newDefaultRenewMaxMin; +CEdit CKrbMiscConfigOpt::m_krbRenewMaxMinEditbox; +CString CKrbMiscConfigOpt::m_initDefaultRenewMaxHr; +CString CKrbMiscConfigOpt::m_newDefaultRenewMaxHr; +CEdit CKrbMiscConfigOpt::m_krbRenewMaxHrEditbox; +CString CKrbMiscConfigOpt::m_initDefaultRenewMaxDay; +CString CKrbMiscConfigOpt::m_newDefaultRenewMaxDay; +CEdit CKrbMiscConfigOpt::m_krbRenewMaxDayEditbox; + + +IMPLEMENT_DYNCREATE(CKrbMiscConfigOpt, CPropertyPage) + +CKrbMiscConfigOpt::CKrbMiscConfigOpt() : CPropertyPage(CKrbMiscConfigOpt::IDD) +{ + m_noLifeTime = FALSE; + + m_DefaultLifeTime = 0; + m_DefaultRenewTill = 0; + m_DefaultLifeMin = 0; + m_DefaultLifeMax = 0; + m_DefaultRenewMin = 0; + m_DefaultRenewMax = 0; + m_initUseKrb4 = m_newUseKrb4 = 0; + m_initKinitPreserve = m_newKinitPreserve = 0; + + //{{AFX_DATA_INIT(CKrbConfigOptions) + //}}AFX_DATA_INIT +} + +CKrbMiscConfigOpt::~CKrbMiscConfigOpt() +{ +} + +VOID CKrbMiscConfigOpt::DoDataExchange(CDataExchange* pDX) +{ + TRACE("Entering CKrbMiscConfigOpt::DoDataExchange -- %d\n", + pDX->m_bSaveAndValidate); + CPropertyPage::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CKrbMscConfigOpt) + + DDX_Control(pDX, IDC_EDIT_LIFETIME_D, m_krbLifeTimeDayEditbox); + DDX_Control(pDX, IDC_EDIT_LIFETIME_H, m_krbLifeTimeHrEditbox); + DDX_Control(pDX, IDC_EDIT_LIFETIME_M, m_krbLifeTimeMinEditbox); + DDX_Control(pDX, IDC_EDIT_RENEWTILL_D, m_krbRenewTillDayEditbox); + DDX_Control(pDX, IDC_EDIT_RENEWTILL_H, m_krbRenewTillHrEditbox); + DDX_Control(pDX, IDC_EDIT_RENEWTILL_M, m_krbRenewTillMinEditbox); + DDX_Control(pDX, IDC_EDIT_LIFE_MIN_D, m_krbLifeMinDayEditbox); + DDX_Control(pDX, IDC_EDIT_LIFE_MIN_H, m_krbLifeMinHrEditbox); + DDX_Control(pDX, IDC_EDIT_LIFE_MIN_M, m_krbLifeMinMinEditbox); + DDX_Control(pDX, IDC_EDIT_LIFE_MAX_D, m_krbLifeMaxDayEditbox); + DDX_Control(pDX, IDC_EDIT_LIFE_MAX_H, m_krbLifeMaxHrEditbox); + DDX_Control(pDX, IDC_EDIT_LIFE_MAX_M, m_krbLifeMaxMinEditbox); + DDX_Control(pDX, IDC_EDIT_RENEW_MIN_D, m_krbRenewMinDayEditbox); + DDX_Control(pDX, IDC_EDIT_RENEW_MIN_H, m_krbRenewMinHrEditbox); + DDX_Control(pDX, IDC_EDIT_RENEW_MIN_M, m_krbRenewMinMinEditbox); + DDX_Control(pDX, IDC_EDIT_RENEW_MAX_D, m_krbRenewMaxDayEditbox); + DDX_Control(pDX, IDC_EDIT_RENEW_MAX_H, m_krbRenewMaxHrEditbox); + DDX_Control(pDX, IDC_EDIT_RENEW_MAX_M, m_krbRenewMaxMinEditbox); + //}}AFX_DATA_MAP +} + + +BOOL CKrbMiscConfigOpt::OnInitDialog() +{ + CPropertyPage::OnInitDialog(); + + DWORD tmp = m_DefaultLifeTime = pLeash_get_default_lifetime(); + if (tmp) + m_noLifeTime = FALSE; // We now have the value. + else + m_noLifeTime = TRUE; + + LPTSTR buf = m_initDefaultLifeTimeDay.GetBuffer(80); + _itoa(tmp/24/60, buf, 10); + tmp %= (24 * 60); + m_initDefaultLifeTimeDay.ReleaseBuffer(); + m_newDefaultLifeTimeDay = m_initDefaultLifeTimeDay; + + buf = m_initDefaultLifeTimeHr.GetBuffer(80); + _itoa(tmp/60, buf, 10); + tmp %= 60; + m_initDefaultLifeTimeHr.ReleaseBuffer(); + m_newDefaultLifeTimeHr = m_initDefaultLifeTimeHr; + + buf = m_initDefaultLifeTimeMin.GetBuffer(80); + _itoa(tmp, buf, 10); + m_initDefaultLifeTimeMin.ReleaseBuffer(); + m_newDefaultLifeTimeMin = m_initDefaultLifeTimeMin; + + tmp = m_DefaultRenewTill = pLeash_get_default_renew_till(); + buf = m_initDefaultRenewTillDay.GetBuffer(80); + _itoa(tmp/24/60, buf, 10); + tmp %= (24 * 60); + m_initDefaultRenewTillDay.ReleaseBuffer(); + m_newDefaultRenewTillDay = m_initDefaultRenewTillDay; + + buf = m_initDefaultRenewTillHr.GetBuffer(80); + _itoa(tmp/60, buf, 10); + tmp %= 60; + m_initDefaultRenewTillHr.ReleaseBuffer(); + m_newDefaultRenewTillHr = m_initDefaultRenewTillHr; + + buf = m_initDefaultRenewTillMin.GetBuffer(80); + _itoa(tmp, buf, 10); + m_initDefaultRenewTillMin.ReleaseBuffer(); + m_newDefaultRenewTillMin = m_initDefaultRenewTillMin; + + tmp = m_DefaultLifeMin = pLeash_get_default_life_min(); + buf = m_initDefaultLifeMinDay.GetBuffer(80); + _itoa(tmp/24/60, buf, 10); + tmp %= (24 * 60); + m_initDefaultLifeMinDay.ReleaseBuffer(); + m_newDefaultLifeMinDay = m_initDefaultLifeMinDay; + + buf = m_initDefaultLifeMinHr.GetBuffer(80); + _itoa(tmp/60, buf, 10); + tmp %= 60; + m_initDefaultLifeMinHr.ReleaseBuffer(); + m_newDefaultLifeMinHr = m_initDefaultLifeMinHr; + + buf = m_initDefaultLifeMinMin.GetBuffer(80); + _itoa(tmp, buf, 10); + m_initDefaultLifeMinMin.ReleaseBuffer(); + m_newDefaultLifeMinMin = m_initDefaultLifeMinMin; + + tmp = m_DefaultLifeMax = pLeash_get_default_life_max(); + buf = m_initDefaultLifeMaxDay.GetBuffer(80); + _itoa(tmp/24/60, buf, 10); + tmp %= (24 * 60); + m_initDefaultLifeMaxDay.ReleaseBuffer(); + m_newDefaultLifeMaxDay = m_initDefaultLifeMaxDay; + + buf = m_initDefaultLifeMaxHr.GetBuffer(80); + _itoa(tmp/60, buf, 10); + tmp %= 60; + m_initDefaultLifeMaxHr.ReleaseBuffer(); + m_newDefaultLifeMaxHr = m_initDefaultLifeMaxHr; + + buf = m_initDefaultLifeMaxMin.GetBuffer(80); + _itoa(tmp, buf, 10); + m_initDefaultLifeMaxMin.ReleaseBuffer(); + m_newDefaultLifeMaxMin = m_initDefaultLifeMaxMin; + + tmp = m_DefaultRenewMin = pLeash_get_default_renew_min(); + buf = m_initDefaultRenewMinDay.GetBuffer(80); + _itoa(tmp/24/60, buf, 10); + tmp %= (24 * 60); + m_initDefaultRenewMinDay.ReleaseBuffer(); + m_newDefaultRenewMinDay = m_initDefaultRenewMinDay; + + buf = m_initDefaultRenewMinHr.GetBuffer(80); + _itoa(tmp/60, buf, 10); + tmp %= 60; + m_initDefaultRenewMinHr.ReleaseBuffer(); + m_newDefaultRenewMinHr = m_initDefaultRenewMinHr; + + buf = m_initDefaultRenewMinMin.GetBuffer(80); + _itoa(tmp, buf, 10); + m_initDefaultRenewMinMin.ReleaseBuffer(); + m_newDefaultRenewMinMin = m_initDefaultRenewMinMin; + + tmp = m_DefaultRenewMax = pLeash_get_default_renew_max(); + buf = m_initDefaultRenewMaxDay.GetBuffer(80); + _itoa(tmp/24/60, buf, 10); + tmp %= (24 * 60); + m_initDefaultRenewMaxDay.ReleaseBuffer(); + m_newDefaultRenewMaxDay = m_initDefaultRenewMaxDay; + + buf = m_initDefaultRenewMaxHr.GetBuffer(80); + _itoa(tmp/60, buf, 10); + tmp %= 60; + m_initDefaultRenewMaxHr.ReleaseBuffer(); + m_newDefaultRenewMaxHr = m_initDefaultRenewMaxHr; + + buf = m_initDefaultRenewMaxMin.GetBuffer(80); + _itoa(tmp, buf, 10); + m_initDefaultRenewMaxMin.ReleaseBuffer(); + m_newDefaultRenewMaxMin = m_initDefaultRenewMaxMin; + + if (!CLeashApp::m_hKrb5DLL) + { + GetDlgItem(IDC_EDIT_RENEWTILL_D)->EnableWindow(FALSE); + GetDlgItem(IDC_EDIT_RENEWTILL_H)->EnableWindow(FALSE); + GetDlgItem(IDC_EDIT_RENEWTILL_M)->EnableWindow(FALSE); + GetDlgItem(IDC_EDIT_RENEW_MIN_D)->EnableWindow(FALSE); + GetDlgItem(IDC_EDIT_RENEW_MIN_H)->EnableWindow(FALSE); + GetDlgItem(IDC_EDIT_RENEW_MIN_M)->EnableWindow(FALSE); + GetDlgItem(IDC_EDIT_RENEW_MAX_D)->EnableWindow(FALSE); + GetDlgItem(IDC_EDIT_RENEW_MAX_H)->EnableWindow(FALSE); + GetDlgItem(IDC_EDIT_RENEW_MAX_M)->EnableWindow(FALSE); + } + + + m_initUseKrb4 = m_newUseKrb4 = (CLeashApp::m_hKrb4DLL ? pLeash_get_default_use_krb4() : 0); + CheckDlgButton(IDC_CHECK_REQUEST_KRB4, m_initUseKrb4); + if ( !CLeashApp::m_hKrb4DLL ) + GetDlgItem(IDC_CHECK_REQUEST_KRB4)->EnableWindow(FALSE); + + m_initKinitPreserve = m_newKinitPreserve = pLeash_get_default_preserve_kinit_settings(); + CheckDlgButton(IDC_CHECK_PRESERVE_KINIT_OPTIONS, m_initKinitPreserve); + + return(TRUE); +} + +BOOL CKrbMiscConfigOpt::OnApply() +{ + DWORD lifetime = ((atoi(m_newDefaultLifeTimeDay)*24 + atoi(m_newDefaultLifeTimeHr)) * 60) + atoi(m_newDefaultLifeTimeMin); + DWORD renewtill = ((atoi(m_newDefaultRenewTillDay)*24 + atoi(m_newDefaultRenewTillHr)) * 60) + atoi(m_newDefaultRenewTillMin); + DWORD lifemin = ((atoi(m_newDefaultLifeMinDay)*24 + atoi(m_newDefaultLifeMinHr)) * 60) + atoi(m_newDefaultLifeMinMin); + DWORD lifemax = ((atoi(m_newDefaultLifeMaxDay)*24 + atoi(m_newDefaultLifeMaxHr)) * 60) + atoi(m_newDefaultLifeMaxMin); + DWORD renewmin = ((atoi(m_newDefaultRenewMinDay)*24 + atoi(m_newDefaultRenewMinHr)) * 60) + atoi(m_newDefaultRenewMinMin); + DWORD renewmax = ((atoi(m_newDefaultRenewMaxDay)*24 + atoi(m_newDefaultRenewMaxHr)) * 60) + atoi(m_newDefaultRenewMaxMin); + + // If no changes were made, quit this function + if ( m_DefaultLifeTime == lifetime && + m_DefaultRenewTill == renewtill && + m_DefaultLifeMin == lifemin && + m_DefaultLifeMax == lifemax && + m_DefaultRenewMin == renewmin && + m_DefaultRenewMax == renewmax && + m_initUseKrb4 == m_newUseKrb4 && + m_initKinitPreserve == m_newKinitPreserve + ) + return TRUE; + + if ( lifemin > lifemax ) { + MessageBox("The Minimum Ticket Lifetime must be less than the Maximum Ticket Lifetime.", + "Leash", MB_OK); + return(FALSE); + } + + if (lifetime < lifemin || lifetime > lifemax) { + MessageBox("The default Ticket Lifetime must fall within the range specified by the " + "Minimum and Maximum Ticket Lifetime fields", + "Leash", MB_OK); + return(FALSE); + } + + if ( CLeashApp::m_hKrb5DLL && (renewmin > renewmax) ) { + MessageBox("The Minimum Ticket Renewable Lifetime must be less than the Maximum Ticket Renewable Lifetime.", + "Leash", MB_OK); + return(FALSE); + } + + if ( CLeashApp::m_hKrb5DLL && (renewmin < lifemin) ) { + MessageBox("The Minimum Renewable Ticket Lifetime must not be smaller than the Minimum Ticket Lifetime.", + "Leash", MB_OK); + } + + if ( CLeashApp::m_hKrb5DLL && (renewtill < renewmin || renewtill > renewmax) ) { + MessageBox("The default Renewable Ticket Lifetime must fall within the range specified by the " + "Minimum and Maximum Renewable Ticket Lifetime fields", + "Leash", MB_OK); + return(FALSE); + } + + m_DefaultLifeMin = lifemin; + pLeash_set_default_life_min(m_DefaultLifeMin); + m_initDefaultLifeMinDay = m_newDefaultLifeMinDay; + m_initDefaultLifeMinHr = m_newDefaultLifeMinHr ; + m_initDefaultLifeMinMin = m_newDefaultLifeMinMin; + + m_DefaultLifeMax = lifemax; + pLeash_set_default_life_max(m_DefaultLifeMax); + m_initDefaultLifeMaxDay = m_newDefaultLifeMaxDay; + m_initDefaultLifeMaxHr = m_newDefaultLifeMaxHr ; + m_initDefaultLifeMaxMin = m_newDefaultLifeMaxMin; + + m_DefaultRenewMin = renewmin; + pLeash_set_default_renew_min(m_DefaultRenewMin); + m_initDefaultRenewMinDay = m_newDefaultRenewMinDay; + m_initDefaultRenewMinHr = m_newDefaultRenewMinHr ; + m_initDefaultRenewMinMin = m_newDefaultRenewMinMin; + + m_DefaultRenewMax = renewmax; + pLeash_set_default_renew_max(m_DefaultRenewMax); + m_initDefaultRenewMaxDay = m_newDefaultRenewMaxDay; + m_initDefaultRenewMaxHr = m_newDefaultRenewMaxHr ; + m_initDefaultRenewMaxMin = m_newDefaultRenewMaxMin; + + m_DefaultRenewTill = renewtill; + pLeash_set_default_renew_till(m_DefaultRenewTill); + m_initDefaultRenewTillDay = m_newDefaultRenewTillDay; + m_initDefaultRenewTillHr = m_newDefaultRenewTillHr ; + m_initDefaultRenewTillMin = m_newDefaultRenewTillMin; + + if( getenv("LIFETIME") != NULL) + { + MessageBox("The ticket lifetime is being controlled by the environment " + "variable LIFETIME instead of the registry. Leash cannot modify " + "the environment. Use the System control panel instead.", + "Leash", MB_OK); + return(FALSE); + } + + m_DefaultLifeTime = lifetime; + pLeash_set_default_lifetime(m_DefaultLifeTime); + m_initDefaultLifeTimeDay = m_newDefaultLifeTimeDay; + m_initDefaultLifeTimeHr = m_newDefaultLifeTimeHr ; + m_initDefaultLifeTimeMin = m_newDefaultLifeTimeMin; + + // If we're using an environment variable tell the user that we + // can't use Leash to modify the value. + + if (!m_DefaultLifeTime) + { + MessageBox("A lifetime setting of 0 is special in that it means that " + "the application is free to pick whatever default it deems " + "appropriate", + "Leash", MB_OK); + } + + if ( m_initUseKrb4 != m_newUseKrb4 ) { + pLeash_set_default_use_krb4(m_newUseKrb4); + } + + if ( m_initKinitPreserve != m_newKinitPreserve ) { + pLeash_set_default_preserve_kinit_settings(m_newKinitPreserve); + } + + return TRUE; +} + +void CKrbMiscConfigOpt::OnSelchangeEditDefaultLifeTime() +{ + static int in_progress = 0; + if (!in_progress && !m_startupPage2) + { + in_progress = 1; + GetDlgItemText(IDC_EDIT_LIFETIME_D, m_newDefaultLifeTimeDay); + GetDlgItemText(IDC_EDIT_LIFETIME_H, m_newDefaultLifeTimeHr); + GetDlgItemText(IDC_EDIT_LIFETIME_M, m_newDefaultLifeTimeMin); + DWORD value = (((atoi(m_newDefaultLifeTimeDay)*24 + atoi(m_newDefaultLifeTimeHr)) * 60) + atoi(m_newDefaultLifeTimeMin)); + LPSTR buf = m_newDefaultLifeTimeDay.GetBuffer(80); + _itoa(value/24/60, buf, 10); + value %= (24 * 60); + m_newDefaultLifeTimeDay.ReleaseBuffer(); + buf = m_newDefaultLifeTimeHr.GetBuffer(80); + _itoa(value/60, buf, 10); + value %= 60; + m_newDefaultLifeTimeHr.ReleaseBuffer(); + buf = m_newDefaultLifeTimeMin.GetBuffer(80); + _itoa(value, buf, 10); + m_newDefaultLifeTimeMin.ReleaseBuffer(); + SetDlgItemText(IDC_EDIT_LIFETIME_D, m_newDefaultLifeTimeDay); + SetDlgItemText(IDC_EDIT_LIFETIME_H, m_newDefaultLifeTimeHr); + SetDlgItemText(IDC_EDIT_LIFETIME_M, m_newDefaultLifeTimeMin); + SetModified(TRUE); + in_progress = 0; + } +} + +void CKrbMiscConfigOpt::OnEditKillfocusEditDefaultLifeTime() +{ + static int in_progress = 0; + if (!in_progress && !m_startupPage2) + { + in_progress = 1; + GetDlgItemText(IDC_EDIT_LIFETIME_D, m_newDefaultLifeTimeDay); + GetDlgItemText(IDC_EDIT_LIFETIME_H, m_newDefaultLifeTimeHr); + GetDlgItemText(IDC_EDIT_LIFETIME_M, m_newDefaultLifeTimeMin); + DWORD value = (((atoi(m_newDefaultLifeTimeDay)*24 + atoi(m_newDefaultLifeTimeHr)) * 60) + atoi(m_newDefaultLifeTimeMin)); + LPSTR buf = m_newDefaultLifeTimeDay.GetBuffer(80); + _itoa(value/24/60, buf, 10); + value %= (24 * 60); + m_newDefaultLifeTimeDay.ReleaseBuffer(); + buf = m_newDefaultLifeTimeHr.GetBuffer(80); + _itoa(value/60, buf, 10); + value %= 60; + m_newDefaultLifeTimeHr.ReleaseBuffer(); + buf = m_newDefaultLifeTimeMin.GetBuffer(80); + _itoa(value, buf, 10); + m_newDefaultLifeTimeMin.ReleaseBuffer(); + SetDlgItemText(IDC_EDIT_LIFETIME_D, m_newDefaultLifeTimeDay); + SetDlgItemText(IDC_EDIT_LIFETIME_H, m_newDefaultLifeTimeHr); + SetDlgItemText(IDC_EDIT_LIFETIME_M, m_newDefaultLifeTimeMin); + + SetModified(TRUE); + in_progress = 0; + } +} + +void CKrbMiscConfigOpt::ResetDefaultLifeTimeEditBox() +{ + // Reset Config Tab's Default LifeTime Editbox + + DWORD tmp = m_DefaultLifeTime = pLeash_get_default_lifetime(); + LPSTR buf = m_newDefaultLifeTimeDay.GetBuffer(80); + _itoa(tmp/24/60, buf, 10); + tmp %= (24 * 60); + m_newDefaultLifeTimeDay.ReleaseBuffer(); + buf = m_newDefaultLifeTimeHr.GetBuffer(80); + _itoa(tmp/60, buf, 10); + tmp %= 60; + m_newDefaultLifeTimeHr.ReleaseBuffer(); + buf = m_newDefaultLifeTimeMin.GetBuffer(80); + _itoa(tmp, buf, 10); + m_newDefaultLifeTimeMin.ReleaseBuffer(); + + ::SetDlgItemText(::GetForegroundWindow(), IDC_EDIT_LIFETIME_D, m_newDefaultLifeTimeDay); + ::SetDlgItemText(::GetForegroundWindow(), IDC_EDIT_LIFETIME_H, m_newDefaultLifeTimeHr); + ::SetDlgItemText(::GetForegroundWindow(), IDC_EDIT_LIFETIME_M, m_newDefaultLifeTimeMin); +} + + +void CKrbMiscConfigOpt::OnSelchangeEditDefaultRenewTill() +{ + static int in_progress = 0; + if (!in_progress && !m_startupPage2) + { + in_progress = 1; + GetDlgItemText(IDC_EDIT_RENEWTILL_D, m_newDefaultRenewTillDay); + GetDlgItemText(IDC_EDIT_RENEWTILL_H, m_newDefaultRenewTillHr); + GetDlgItemText(IDC_EDIT_RENEWTILL_M, m_newDefaultRenewTillMin); + DWORD value = (((atoi(m_newDefaultRenewTillDay)*24 + atoi(m_newDefaultRenewTillHr)) * 60) + atoi(m_newDefaultRenewTillMin)); + LPSTR buf = m_newDefaultRenewTillDay.GetBuffer(80); + _itoa(value/24/60, buf, 10); + value %= (24 * 60); + m_newDefaultRenewTillDay.ReleaseBuffer(); + buf = m_newDefaultRenewTillHr.GetBuffer(80); + _itoa(value/60, buf, 10); + value %= 60; + m_newDefaultRenewTillHr.ReleaseBuffer(); + buf = m_newDefaultRenewTillMin.GetBuffer(80); + _itoa(value, buf, 10); + m_newDefaultRenewTillMin.ReleaseBuffer(); + SetDlgItemText(IDC_EDIT_RENEWTILL_D, m_newDefaultRenewTillDay); + SetDlgItemText(IDC_EDIT_RENEWTILL_H, m_newDefaultRenewTillHr); + SetDlgItemText(IDC_EDIT_RENEWTILL_M, m_newDefaultRenewTillMin); + SetModified(TRUE); + in_progress = 0; + } +} + +void CKrbMiscConfigOpt::OnEditKillfocusEditDefaultRenewTill() +{ + static int in_progress = 0; + if (!in_progress && !m_startupPage2) + { + in_progress = 1; + GetDlgItemText(IDC_EDIT_RENEWTILL_D, m_newDefaultRenewTillDay); + GetDlgItemText(IDC_EDIT_RENEWTILL_H, m_newDefaultRenewTillHr); + GetDlgItemText(IDC_EDIT_RENEWTILL_M, m_newDefaultRenewTillMin); + DWORD value = (((atoi(m_newDefaultRenewTillDay)*24 + atoi(m_newDefaultRenewTillHr)) * 60) + atoi(m_newDefaultRenewTillMin)); + LPSTR buf = m_newDefaultRenewTillDay.GetBuffer(80); + _itoa(value/24/60, buf, 10); + value %= (24 * 60); + m_newDefaultRenewTillDay.ReleaseBuffer(); + buf = m_newDefaultRenewTillHr.GetBuffer(80); + _itoa(value/60, buf, 10); + value %= 60; + m_newDefaultRenewTillHr.ReleaseBuffer(); + buf = m_newDefaultRenewTillMin.GetBuffer(80); + _itoa(value, buf, 10); + m_newDefaultRenewTillMin.ReleaseBuffer(); + SetDlgItemText(IDC_EDIT_RENEWTILL_D, m_newDefaultRenewTillDay); + SetDlgItemText(IDC_EDIT_RENEWTILL_H, m_newDefaultRenewTillHr); + SetDlgItemText(IDC_EDIT_RENEWTILL_M, m_newDefaultRenewTillMin); + + SetModified(TRUE); + in_progress = 0; + } +} + +void CKrbMiscConfigOpt::ResetDefaultRenewTillEditBox() +{ + // Reset Config Tab's Default RenewTill Editbox + + DWORD tmp = m_DefaultRenewTill = pLeash_get_default_lifetime(); + LPSTR buf = m_newDefaultRenewTillDay.GetBuffer(80); + _itoa(tmp/24/60, buf, 10); + tmp %= (24 * 60); + m_newDefaultRenewTillDay.ReleaseBuffer(); + buf = m_newDefaultRenewTillHr.GetBuffer(80); + _itoa(tmp/60, buf, 10); + tmp %= 60; + m_newDefaultRenewTillHr.ReleaseBuffer(); + buf = m_newDefaultRenewTillMin.GetBuffer(80); + _itoa(tmp, buf, 10); + m_newDefaultRenewTillMin.ReleaseBuffer(); + + ::SetDlgItemText(::GetForegroundWindow(), IDC_EDIT_RENEWTILL_D, m_newDefaultRenewTillDay); + ::SetDlgItemText(::GetForegroundWindow(), IDC_EDIT_RENEWTILL_H, m_newDefaultRenewTillHr); + ::SetDlgItemText(::GetForegroundWindow(), IDC_EDIT_RENEWTILL_M, m_newDefaultRenewTillMin); +} + + +void CKrbMiscConfigOpt::OnSelchangeEditDefaultLifeMin() +{ + static int in_progress = 0; + if (!in_progress && !m_startupPage2) + { + in_progress = 1; + GetDlgItemText(IDC_EDIT_LIFE_MIN_D, m_newDefaultLifeMinDay); + GetDlgItemText(IDC_EDIT_LIFE_MIN_H, m_newDefaultLifeMinHr); + GetDlgItemText(IDC_EDIT_LIFE_MIN_M, m_newDefaultLifeMinMin); + DWORD value = (((atoi(m_newDefaultLifeMinDay)*24 + atoi(m_newDefaultLifeMinHr)) * 60) + atoi(m_newDefaultLifeMinMin)); + LPSTR buf = m_newDefaultLifeMinDay.GetBuffer(80); + _itoa(value/24/60, buf, 10); + value %= (24 * 60); + m_newDefaultLifeMinDay.ReleaseBuffer(); + buf = m_newDefaultLifeMinHr.GetBuffer(80); + _itoa(value/60, buf, 10); + value %= 60; + m_newDefaultLifeMinHr.ReleaseBuffer(); + buf = m_newDefaultLifeMinMin.GetBuffer(80); + _itoa(value, buf, 10); + m_newDefaultLifeMinMin.ReleaseBuffer(); + SetDlgItemText(IDC_EDIT_LIFE_MIN_D, m_newDefaultLifeMinDay); + SetDlgItemText(IDC_EDIT_LIFE_MIN_H, m_newDefaultLifeMinHr); + SetDlgItemText(IDC_EDIT_LIFE_MIN_M, m_newDefaultLifeMinMin); + SetModified(TRUE); + in_progress = 0; + } +} + +void CKrbMiscConfigOpt::OnEditKillfocusEditDefaultLifeMin() +{ + static int in_progress = 0; + if (!in_progress && !m_startupPage2) + { + in_progress = 1; + GetDlgItemText(IDC_EDIT_LIFE_MIN_D, m_newDefaultLifeMinDay); + GetDlgItemText(IDC_EDIT_LIFE_MIN_H, m_newDefaultLifeMinHr); + GetDlgItemText(IDC_EDIT_LIFE_MIN_M, m_newDefaultLifeMinMin); + DWORD value = (((atoi(m_newDefaultLifeMinDay)*24 + atoi(m_newDefaultLifeMinHr)) * 60) + atoi(m_newDefaultLifeMinMin)); + LPSTR buf = m_newDefaultLifeMinDay.GetBuffer(80); + _itoa(value/24/60, buf, 10); + value %= (24 * 60); + m_newDefaultLifeMinDay.ReleaseBuffer(); + buf = m_newDefaultLifeMinHr.GetBuffer(80); + _itoa(value/60, buf, 10); + value %= 60; + m_newDefaultLifeMinHr.ReleaseBuffer(); + buf = m_newDefaultLifeMinMin.GetBuffer(80); + _itoa(value, buf, 10); + m_newDefaultLifeMinMin.ReleaseBuffer(); + SetDlgItemText(IDC_EDIT_LIFE_MIN_D, m_newDefaultLifeMinDay); + SetDlgItemText(IDC_EDIT_LIFE_MIN_H, m_newDefaultLifeMinHr); + SetDlgItemText(IDC_EDIT_LIFE_MIN_M, m_newDefaultLifeMinMin); + + SetModified(TRUE); + in_progress = 0; + } +} + +void CKrbMiscConfigOpt::ResetDefaultLifeMinEditBox() +{ + // Reset Config Tab's Default LifeMin Editbox + + DWORD tmp = m_DefaultLifeMin = pLeash_get_default_life_min(); + LPSTR buf = m_newDefaultLifeMinDay.GetBuffer(80); + _itoa(tmp/24/60, buf, 10); + tmp %= (24 * 60); + m_newDefaultLifeMinDay.ReleaseBuffer(); + buf = m_newDefaultLifeMinHr.GetBuffer(80); + _itoa(tmp/60, buf, 10); + tmp %= 60; + m_newDefaultLifeMinHr.ReleaseBuffer(); + buf = m_newDefaultLifeMinMin.GetBuffer(80); + _itoa(tmp, buf, 10); + m_newDefaultLifeMinMin.ReleaseBuffer(); + + ::SetDlgItemText(::GetForegroundWindow(), IDC_EDIT_LIFE_MIN_D, m_newDefaultLifeMinDay); + ::SetDlgItemText(::GetForegroundWindow(), IDC_EDIT_LIFE_MIN_H, m_newDefaultLifeMinHr); + ::SetDlgItemText(::GetForegroundWindow(), IDC_EDIT_LIFE_MIN_M, m_newDefaultLifeMinMin); +} + +void CKrbMiscConfigOpt::OnSelchangeEditDefaultLifeMax() +{ + static int in_progress = 0; + if (!in_progress && !m_startupPage2) + { + in_progress = 1; + GetDlgItemText(IDC_EDIT_LIFE_MAX_D, m_newDefaultLifeMaxDay); + GetDlgItemText(IDC_EDIT_LIFE_MAX_H, m_newDefaultLifeMaxHr); + GetDlgItemText(IDC_EDIT_LIFE_MAX_M, m_newDefaultLifeMaxMin); + DWORD value = (((atoi(m_newDefaultLifeMaxDay)*24 + atoi(m_newDefaultLifeMaxHr)) * 60) + atoi(m_newDefaultLifeMaxMin)); + LPSTR buf = m_newDefaultLifeMaxDay.GetBuffer(80); + _itoa(value/24/60, buf, 10); + value %= (24 * 60); + m_newDefaultLifeMaxDay.ReleaseBuffer(); + buf = m_newDefaultLifeMaxHr.GetBuffer(80); + _itoa(value/60, buf, 10); + value %= 60; + m_newDefaultLifeMaxHr.ReleaseBuffer(); + buf = m_newDefaultLifeMaxMin.GetBuffer(80); + _itoa(value, buf, 10); + m_newDefaultLifeMaxMin.ReleaseBuffer(); + SetDlgItemText(IDC_EDIT_LIFE_MAX_D, m_newDefaultLifeMaxDay); + SetDlgItemText(IDC_EDIT_LIFE_MAX_H, m_newDefaultLifeMaxHr); + SetDlgItemText(IDC_EDIT_LIFE_MAX_M, m_newDefaultLifeMaxMin); + + SetModified(TRUE); + in_progress = 0; + } +} + +void CKrbMiscConfigOpt::OnEditKillfocusEditDefaultLifeMax() +{ + static int in_progress = 0; + if (!in_progress && !m_startupPage2) + { + in_progress = 1; + GetDlgItemText(IDC_EDIT_LIFE_MAX_D, m_newDefaultLifeMaxDay); + GetDlgItemText(IDC_EDIT_LIFE_MAX_H, m_newDefaultLifeMaxHr); + GetDlgItemText(IDC_EDIT_LIFE_MAX_M, m_newDefaultLifeMaxMin); + DWORD value = (((atoi(m_newDefaultLifeMaxDay)*24 + atoi(m_newDefaultLifeMaxHr)) * 60) + atoi(m_newDefaultLifeMaxMin)); + LPSTR buf = m_newDefaultLifeMaxDay.GetBuffer(80); + _itoa(value/24/60, buf, 10); + value %= (24 * 60); + m_newDefaultLifeMaxDay.ReleaseBuffer(); + buf = m_newDefaultLifeMaxHr.GetBuffer(80); + _itoa(value/60, buf, 10); + value %= 60; + m_newDefaultLifeMaxHr.ReleaseBuffer(); + buf = m_newDefaultLifeMaxMin.GetBuffer(80); + _itoa(value, buf, 10); + m_newDefaultLifeMaxMin.ReleaseBuffer(); + SetDlgItemText(IDC_EDIT_LIFE_MAX_D, m_newDefaultLifeMaxDay); + SetDlgItemText(IDC_EDIT_LIFE_MAX_H, m_newDefaultLifeMaxHr); + SetDlgItemText(IDC_EDIT_LIFE_MAX_M, m_newDefaultLifeMaxMin); + + SetModified(TRUE); + in_progress = 0; + } +} + +void CKrbMiscConfigOpt::ResetDefaultLifeMaxEditBox() +{ + // Reset Config Tab's Default LifeMax Editbox + + DWORD tmp = m_DefaultLifeMax = pLeash_get_default_life_min(); + LPSTR buf = m_newDefaultLifeMaxDay.GetBuffer(80); + _itoa(tmp/24/60, buf, 10); + tmp %= (24 * 60); + m_newDefaultLifeMaxDay.ReleaseBuffer(); + buf = m_newDefaultLifeMaxHr.GetBuffer(80); + _itoa(tmp/60, buf, 10); + tmp %= 60; + m_newDefaultLifeMaxHr.ReleaseBuffer(); + buf = m_newDefaultLifeMaxMin.GetBuffer(80); + _itoa(tmp, buf, 10); + m_newDefaultLifeMaxMin.ReleaseBuffer(); + + ::SetDlgItemText(::GetForegroundWindow(), IDC_EDIT_LIFE_MAX_D, m_newDefaultLifeMaxDay); + ::SetDlgItemText(::GetForegroundWindow(), IDC_EDIT_LIFE_MAX_H, m_newDefaultLifeMaxHr); + ::SetDlgItemText(::GetForegroundWindow(), IDC_EDIT_LIFE_MAX_M, m_newDefaultLifeMaxMin); +} + +void CKrbMiscConfigOpt::OnSelchangeEditDefaultRenewMin() +{ + static int in_progress = 0; + if (!in_progress && !m_startupPage2) + { + in_progress = 1; + GetDlgItemText(IDC_EDIT_RENEW_MIN_D, m_newDefaultRenewMinDay); + GetDlgItemText(IDC_EDIT_RENEW_MIN_H, m_newDefaultRenewMinHr); + GetDlgItemText(IDC_EDIT_RENEW_MIN_M, m_newDefaultRenewMinMin); + DWORD value = (((atoi(m_newDefaultRenewMinDay)*24 + atoi(m_newDefaultRenewMinHr)) * 60) + atoi(m_newDefaultRenewMinMin)); + LPSTR buf = m_newDefaultRenewMinDay.GetBuffer(80); + _itoa(value/24/60, buf, 10); + value %= (24 * 60); + m_newDefaultRenewMinDay.ReleaseBuffer(); + buf = m_newDefaultRenewMinHr.GetBuffer(80); + _itoa(value/60, buf, 10); + value %= 60; + m_newDefaultRenewMinHr.ReleaseBuffer(); + buf = m_newDefaultRenewMinMin.GetBuffer(80); + _itoa(value, buf, 10); + m_newDefaultRenewMinMin.ReleaseBuffer(); + SetDlgItemText(IDC_EDIT_RENEW_MIN_D, m_newDefaultRenewMinDay); + SetDlgItemText(IDC_EDIT_RENEW_MIN_H, m_newDefaultRenewMinHr); + SetDlgItemText(IDC_EDIT_RENEW_MIN_M, m_newDefaultRenewMinMin); + + SetModified(TRUE); + in_progress = 0; + } +} + +void CKrbMiscConfigOpt::OnEditKillfocusEditDefaultRenewMin() +{ + static int in_progress = 0; + if (!in_progress && !m_startupPage2) + { + in_progress = 1; + GetDlgItemText(IDC_EDIT_RENEW_MIN_D, m_newDefaultRenewMinDay); + GetDlgItemText(IDC_EDIT_RENEW_MIN_H, m_newDefaultRenewMinHr); + GetDlgItemText(IDC_EDIT_RENEW_MIN_M, m_newDefaultRenewMinMin); + DWORD value = (((atoi(m_newDefaultRenewMinDay)*24 + atoi(m_newDefaultRenewMinHr)) * 60) + atoi(m_newDefaultRenewMinMin)); + LPSTR buf = m_newDefaultRenewMinDay.GetBuffer(80); + _itoa(value/24/60, buf, 10); + value %= (24 * 60); + m_newDefaultRenewMinDay.ReleaseBuffer(); + buf = m_newDefaultRenewMinHr.GetBuffer(80); + _itoa(value/60, buf, 10); + value %= 60; + m_newDefaultRenewMinHr.ReleaseBuffer(); + buf = m_newDefaultRenewMinMin.GetBuffer(80); + _itoa(value, buf, 10); + m_newDefaultRenewMinMin.ReleaseBuffer(); + SetDlgItemText(IDC_EDIT_RENEW_MIN_D, m_newDefaultRenewMinDay); + SetDlgItemText(IDC_EDIT_RENEW_MIN_H, m_newDefaultRenewMinHr); + SetDlgItemText(IDC_EDIT_RENEW_MIN_M, m_newDefaultRenewMinMin); + + SetModified(TRUE); + in_progress = 0; + } +} + +void CKrbMiscConfigOpt::ResetDefaultRenewMinEditBox() +{ + // Reset Config Tab's Default RenewMin Editbox + + DWORD tmp = m_DefaultRenewMin = pLeash_get_default_life_min(); + LPSTR buf = m_newDefaultRenewMinDay.GetBuffer(80); + _itoa(tmp/24/60, buf, 10); + tmp %= (24 * 60); + m_newDefaultRenewMinDay.ReleaseBuffer(); + buf = m_newDefaultRenewMinHr.GetBuffer(80); + _itoa(tmp/60, buf, 10); + tmp %= 60; + m_newDefaultRenewMinHr.ReleaseBuffer(); + buf = m_newDefaultRenewMinMin.GetBuffer(80); + _itoa(tmp, buf, 10); + m_newDefaultRenewMinMin.ReleaseBuffer(); + + ::SetDlgItemText(::GetForegroundWindow(), IDC_EDIT_RENEW_MIN_D, m_newDefaultRenewMinDay); + ::SetDlgItemText(::GetForegroundWindow(), IDC_EDIT_RENEW_MIN_H, m_newDefaultRenewMinHr); + ::SetDlgItemText(::GetForegroundWindow(), IDC_EDIT_RENEW_MIN_M, m_newDefaultRenewMinMin); +} + +void CKrbMiscConfigOpt::OnSelchangeEditDefaultRenewMax() +{ + static int in_progress = 0; + if (!in_progress && !m_startupPage2) + { + in_progress = 1; + GetDlgItemText(IDC_EDIT_RENEW_MAX_D, m_newDefaultRenewMaxDay); + GetDlgItemText(IDC_EDIT_RENEW_MAX_H, m_newDefaultRenewMaxHr); + GetDlgItemText(IDC_EDIT_RENEW_MAX_M, m_newDefaultRenewMaxMin); + DWORD value = (((atoi(m_newDefaultRenewMaxDay)*24 + atoi(m_newDefaultRenewMaxHr)) * 60) + atoi(m_newDefaultRenewMaxMin)); + LPSTR buf = m_newDefaultRenewMaxDay.GetBuffer(80); + _itoa(value/24/60, buf, 10); + value %= (24 * 60); + m_newDefaultRenewMaxDay.ReleaseBuffer(); + buf = m_newDefaultRenewMaxHr.GetBuffer(80); + _itoa(value/60, buf, 10); + value %= 60; + m_newDefaultRenewMaxHr.ReleaseBuffer(); + buf = m_newDefaultRenewMaxMin.GetBuffer(80); + _itoa(value, buf, 10); + m_newDefaultRenewMaxMin.ReleaseBuffer(); + SetDlgItemText(IDC_EDIT_RENEW_MAX_D, m_newDefaultRenewMaxDay); + SetDlgItemText(IDC_EDIT_RENEW_MAX_H, m_newDefaultRenewMaxHr); + SetDlgItemText(IDC_EDIT_RENEW_MAX_M, m_newDefaultRenewMaxMin); + + SetModified(TRUE); + in_progress = 0; + } +} + +void CKrbMiscConfigOpt::OnEditKillfocusEditDefaultRenewMax() +{ + static int in_progress = 0; + if (!in_progress && !m_startupPage2) + { + in_progress = 1; + GetDlgItemText(IDC_EDIT_RENEW_MAX_D, m_newDefaultRenewMaxDay); + GetDlgItemText(IDC_EDIT_RENEW_MAX_H, m_newDefaultRenewMaxHr); + GetDlgItemText(IDC_EDIT_RENEW_MAX_M, m_newDefaultRenewMaxMin); + DWORD value = (((atoi(m_newDefaultRenewMaxDay)*24 + atoi(m_newDefaultRenewMaxHr)) * 60) + atoi(m_newDefaultRenewMaxMin)); + LPSTR buf = m_newDefaultRenewMaxDay.GetBuffer(80); + _itoa(value/24/60, buf, 10); + value %= (24 * 60); + m_newDefaultRenewMaxDay.ReleaseBuffer(); + buf = m_newDefaultRenewMaxHr.GetBuffer(80); + _itoa(value/60, buf, 10); + value %= 60; + m_newDefaultRenewMaxHr.ReleaseBuffer(); + buf = m_newDefaultRenewMaxMin.GetBuffer(80); + _itoa(value, buf, 10); + m_newDefaultRenewMaxMin.ReleaseBuffer(); + SetDlgItemText(IDC_EDIT_RENEW_MAX_D, m_newDefaultRenewMaxDay); + SetDlgItemText(IDC_EDIT_RENEW_MAX_H, m_newDefaultRenewMaxHr); + SetDlgItemText(IDC_EDIT_RENEW_MAX_M, m_newDefaultRenewMaxMin); + + SetModified(TRUE); + in_progress = 0; + } +} + +void CKrbMiscConfigOpt::ResetDefaultRenewMaxEditBox() +{ + // Reset Config Tab's Default RenewMax Editbox + + DWORD tmp = m_DefaultRenewMax = pLeash_get_default_life_min(); + LPSTR buf = m_newDefaultRenewMaxDay.GetBuffer(80); + _itoa(tmp/24/60, buf, 10); + tmp %= (24 * 60); + m_newDefaultRenewMaxDay.ReleaseBuffer(); + buf = m_newDefaultRenewMaxHr.GetBuffer(80); + _itoa(tmp/60, buf, 10); + tmp %= 60; + m_newDefaultRenewMaxHr.ReleaseBuffer(); + buf = m_newDefaultRenewMaxMin.GetBuffer(80); + _itoa(tmp, buf, 10); + m_newDefaultRenewMaxMin.ReleaseBuffer(); + + ::SetDlgItemText(::GetForegroundWindow(), IDC_EDIT_RENEW_MAX_D, m_newDefaultRenewMaxDay); + ::SetDlgItemText(::GetForegroundWindow(), IDC_EDIT_RENEW_MAX_H, m_newDefaultRenewMaxHr); + ::SetDlgItemText(::GetForegroundWindow(), IDC_EDIT_RENEW_MAX_M, m_newDefaultRenewMaxMin); +} + +void CKrbMiscConfigOpt::OnCheckUseKrb4() +{ + m_newUseKrb4 = (BOOL)IsDlgButtonChecked(IDC_CHECK_REQUEST_KRB4); +} + +void CKrbMiscConfigOpt::OnCheckKinitPreserve() +{ + m_newKinitPreserve = (BOOL)IsDlgButtonChecked(IDC_CHECK_PRESERVE_KINIT_OPTIONS); +} + +void CKrbMiscConfigOpt::OnShowWindow(BOOL bShow, UINT nStatus) +{ + CPropertyPage::OnShowWindow(bShow, nStatus); + + if (CLeashApp::m_hKrb5DLL) + ResetDefaultLifeTimeEditBox(); + + SetDlgItemText(IDC_EDIT_LIFETIME_D, m_newDefaultLifeTimeDay); + SetDlgItemText(IDC_EDIT_LIFETIME_H, m_newDefaultLifeTimeHr); + SetDlgItemText(IDC_EDIT_LIFETIME_M, m_newDefaultLifeTimeMin); + SetDlgItemText(IDC_EDIT_RENEWTILL_D, m_newDefaultRenewTillDay); + SetDlgItemText(IDC_EDIT_RENEWTILL_H, m_newDefaultRenewTillHr); + SetDlgItemText(IDC_EDIT_RENEWTILL_M, m_newDefaultRenewTillMin); + SetDlgItemText(IDC_EDIT_LIFE_MIN_D, m_newDefaultLifeMinDay); + SetDlgItemText(IDC_EDIT_LIFE_MIN_H, m_newDefaultLifeMinHr); + SetDlgItemText(IDC_EDIT_LIFE_MIN_M, m_newDefaultLifeMinMin); + SetDlgItemText(IDC_EDIT_LIFE_MAX_D, m_newDefaultLifeMaxDay); + SetDlgItemText(IDC_EDIT_LIFE_MAX_H, m_newDefaultLifeMaxHr); + SetDlgItemText(IDC_EDIT_LIFE_MAX_M, m_newDefaultLifeMaxMin); + SetDlgItemText(IDC_EDIT_RENEW_MIN_D, m_newDefaultRenewMinDay); + SetDlgItemText(IDC_EDIT_RENEW_MIN_H, m_newDefaultRenewMinHr); + SetDlgItemText(IDC_EDIT_RENEW_MIN_M, m_newDefaultRenewMinMin); + SetDlgItemText(IDC_EDIT_RENEW_MAX_D, m_newDefaultRenewMaxDay); + SetDlgItemText(IDC_EDIT_RENEW_MAX_H, m_newDefaultRenewMaxHr); + SetDlgItemText(IDC_EDIT_RENEW_MAX_M, m_newDefaultRenewMaxMin); +} + +BOOL CKrbMiscConfigOpt::PreTranslateMessage(MSG* pMsg) +{ + if (!m_startupPage2) + { + if (m_noLifeTime) + { + MessageBox("A lifetime setting of 0 is special in that it means that " + "the application is free to pick whatever default it deems " + "appropriate", + "Leash", MB_OK); + m_noLifeTime = FALSE; + } + } + + m_startupPage2 = FALSE; + return CPropertyPage::PreTranslateMessage(pMsg); +} + + +BEGIN_MESSAGE_MAP(CKrbMiscConfigOpt, CPropertyPage) + //{{AFX_MSG_MAP(CKrbConfigOptions) + ON_WM_SHOWWINDOW() + + ON_EN_KILLFOCUS(IDC_EDIT_LIFETIME_D, OnEditKillfocusEditDefaultLifeTime) + ON_CBN_SELCHANGE(IDC_EDIT_LIFETIME_D, OnSelchangeEditDefaultLifeTime) + ON_EN_KILLFOCUS(IDC_EDIT_LIFETIME_H, OnEditKillfocusEditDefaultLifeTime) + ON_CBN_SELCHANGE(IDC_EDIT_LIFETIME_H, OnSelchangeEditDefaultLifeTime) + ON_EN_KILLFOCUS(IDC_EDIT_LIFETIME_M, OnEditKillfocusEditDefaultLifeTime) + ON_CBN_SELCHANGE(IDC_EDIT_LIFETIME_M, OnSelchangeEditDefaultLifeTime) + + ON_EN_KILLFOCUS(IDC_EDIT_RENEWTILL_D, OnEditKillfocusEditDefaultRenewTill) + ON_CBN_SELCHANGE(IDC_EDIT_RENEWTILL_D, OnSelchangeEditDefaultRenewTill) + ON_EN_KILLFOCUS(IDC_EDIT_RENEWTILL_H, OnEditKillfocusEditDefaultRenewTill) + ON_CBN_SELCHANGE(IDC_EDIT_RENEWTILL_H, OnSelchangeEditDefaultRenewTill) + ON_EN_KILLFOCUS(IDC_EDIT_RENEWTILL_M, OnEditKillfocusEditDefaultRenewTill) + ON_CBN_SELCHANGE(IDC_EDIT_RENEWTILL_M, OnSelchangeEditDefaultRenewTill) + + ON_EN_KILLFOCUS(IDC_EDIT_LIFE_MIN_D, OnEditKillfocusEditDefaultLifeMin) + ON_CBN_SELCHANGE(IDC_EDIT_LIFE_MIN_D, OnSelchangeEditDefaultLifeMin) + ON_EN_KILLFOCUS(IDC_EDIT_LIFE_MIN_H, OnEditKillfocusEditDefaultLifeMin) + ON_CBN_SELCHANGE(IDC_EDIT_LIFE_MIN_H, OnSelchangeEditDefaultLifeMin) + ON_EN_KILLFOCUS(IDC_EDIT_LIFE_MIN_M, OnEditKillfocusEditDefaultLifeMin) + ON_CBN_SELCHANGE(IDC_EDIT_LIFE_MIN_M, OnSelchangeEditDefaultLifeMin) + + ON_EN_KILLFOCUS(IDC_EDIT_LIFE_MAX_D, OnEditKillfocusEditDefaultLifeMax) + ON_CBN_SELCHANGE(IDC_EDIT_LIFE_MAX_D, OnSelchangeEditDefaultLifeMax) + ON_EN_KILLFOCUS(IDC_EDIT_LIFE_MAX_H, OnEditKillfocusEditDefaultLifeMax) + ON_CBN_SELCHANGE(IDC_EDIT_LIFE_MAX_H, OnSelchangeEditDefaultLifeMax) + ON_EN_KILLFOCUS(IDC_EDIT_LIFE_MAX_M, OnEditKillfocusEditDefaultLifeMax) + ON_CBN_SELCHANGE(IDC_EDIT_LIFE_MAX_M, OnSelchangeEditDefaultLifeMax) + + ON_EN_KILLFOCUS(IDC_EDIT_RENEW_MIN_D, OnEditKillfocusEditDefaultRenewMin) + ON_CBN_SELCHANGE(IDC_EDIT_RENEW_MIN_D, OnSelchangeEditDefaultRenewMin) + ON_EN_KILLFOCUS(IDC_EDIT_RENEW_MIN_H, OnEditKillfocusEditDefaultRenewMin) + ON_CBN_SELCHANGE(IDC_EDIT_RENEW_MIN_H, OnSelchangeEditDefaultRenewMin) + ON_EN_KILLFOCUS(IDC_EDIT_RENEW_MIN_M, OnEditKillfocusEditDefaultRenewMin) + ON_CBN_SELCHANGE(IDC_EDIT_RENEW_MIN_M, OnSelchangeEditDefaultRenewMin) + + ON_EN_KILLFOCUS(IDC_EDIT_RENEW_MAX_D, OnEditKillfocusEditDefaultRenewMax) + ON_CBN_SELCHANGE(IDC_EDIT_RENEW_MAX_D, OnSelchangeEditDefaultRenewMax) + ON_EN_KILLFOCUS(IDC_EDIT_RENEW_MAX_H, OnEditKillfocusEditDefaultRenewMax) + ON_CBN_SELCHANGE(IDC_EDIT_RENEW_MAX_H, OnSelchangeEditDefaultRenewMax) + ON_EN_KILLFOCUS(IDC_EDIT_RENEW_MAX_M, OnEditKillfocusEditDefaultRenewMax) + ON_CBN_SELCHANGE(IDC_EDIT_RENEW_MAX_M, OnSelchangeEditDefaultRenewMax) + + ON_BN_CLICKED(IDC_CHECK_REQUEST_KRB4, OnCheckUseKrb4) + ON_BN_CLICKED(IDC_CHECK_PRESERVE_KINIT_OPTIONS, OnCheckKinitPreserve) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() diff --git a/src/windows/leash/KrbMiscConfigOpt.h b/src/windows/leash/KrbMiscConfigOpt.h new file mode 100644 index 000000000..e2daf29a3 --- /dev/null +++ b/src/windows/leash/KrbMiscConfigOpt.h @@ -0,0 +1,173 @@ +//***************************************************************************** +// File: KrbMiscConfigOpt.h +// By: Paul B. Hill +// Created: 08/12/1999 +// Copyright: @1999 Massachusetts Institute of Technology - All rights +// reserved. +// Description: H file for KrbMiscConfigOpt.cpp. Contains variables +// and functions for Kerberos Properties. +// +// History: +// +// MM/DD/YY Inits Description of Change +// 08/12/99 PBH Original +//***************************************************************************** + + +#if !defined(AFX_MISCCONFIGOPT_H__CD702F99_7495_11D0_8FDC_00C04FC2A0C2__INCLUDED_) +#define AFX_MISCONFIGOPT_H__CD702F99_7495_11D0_8FDC_00C04FC2A0C2__INCLUDED_ + +#if _MSC_VER >= 1000 +#pragma once +#endif + + +#include "resource.h" + + +/////////////////////////////////////////////////////////////////////// +// CKrbMiscConfigOptions dialog + +class CKrbMiscConfigOpt : public CPropertyPage +{ +// Construction +private: + DECLARE_DYNCREATE(CKrbMiscConfigOpt) + BOOL m_startupPage2; + BOOL m_noLifeTime; + + static UINT m_DefaultLifeTime; + static CString m_initDefaultLifeTimeMin; + static CString m_newDefaultLifeTimeMin; + static CString m_initDefaultLifeTimeHr; + static CString m_newDefaultLifeTimeHr; + static CString m_initDefaultLifeTimeDay; + static CString m_newDefaultLifeTimeDay; + + static UINT m_DefaultRenewTill; + static CString m_initDefaultRenewTillMin; + static CString m_newDefaultRenewTillMin; + static CString m_initDefaultRenewTillHr; + static CString m_newDefaultRenewTillHr; + static CString m_initDefaultRenewTillDay; + static CString m_newDefaultRenewTillDay; + + static UINT m_DefaultLifeMin; + static CString m_initDefaultLifeMinMin; + static CString m_newDefaultLifeMinMin; + static CString m_initDefaultLifeMinHr; + static CString m_newDefaultLifeMinHr; + static CString m_initDefaultLifeMinDay; + static CString m_newDefaultLifeMinDay; + + static UINT m_DefaultLifeMax; + static CString m_initDefaultLifeMaxMin; + static CString m_newDefaultLifeMaxMin; + static CString m_initDefaultLifeMaxHr; + static CString m_newDefaultLifeMaxHr; + static CString m_initDefaultLifeMaxDay; + static CString m_newDefaultLifeMaxDay; + + static UINT m_DefaultRenewMin; + static CString m_initDefaultRenewMinMin; + static CString m_newDefaultRenewMinMin; + static CString m_initDefaultRenewMinHr; + static CString m_newDefaultRenewMinHr; + static CString m_initDefaultRenewMinDay; + static CString m_newDefaultRenewMinDay; + + static UINT m_DefaultRenewMax; + static CString m_initDefaultRenewMaxMin; + static CString m_newDefaultRenewMaxMin; + static CString m_initDefaultRenewMaxHr; + static CString m_newDefaultRenewMaxHr; + static CString m_initDefaultRenewMaxDay; + static CString m_newDefaultRenewMaxDay; + + static void ResetDefaultLifeTimeEditBox(); + static void ResetDefaultRenewTillEditBox(); + static void ResetDefaultLifeMinEditBox(); + static void ResetDefaultLifeMaxEditBox(); + static void ResetDefaultRenewMinEditBox(); + static void ResetDefaultRenewMaxEditBox(); + + BOOL m_initUseKrb4; + BOOL m_newUseKrb4; + BOOL m_initKinitPreserve; + BOOL m_newKinitPreserve; + +public: + CKrbMiscConfigOpt(); + ~CKrbMiscConfigOpt(); + +// Dialog Data + //{{AFX_DATA(CKrbMiscConfigOpt) + enum { IDD = IDD_KRB_PROP_MISC }; + static CEdit m_krbLifeTimeDayEditbox; + static CEdit m_krbLifeTimeMinEditbox; + static CEdit m_krbLifeTimeHrEditbox; + static CEdit m_krbRenewTillDayEditbox; + static CEdit m_krbRenewTillMinEditbox; + static CEdit m_krbRenewTillHrEditbox; + static CEdit m_krbRenewMaxDayEditbox; + static CEdit m_krbRenewMinDayEditbox; + static CEdit m_krbLifeMinDayEditbox; + static CEdit m_krbLifeMinMinEditbox; + static CEdit m_krbLifeMinHrEditbox; + static CEdit m_krbLifeMaxDayEditbox; + static CEdit m_krbLifeMaxMinEditbox; + static CEdit m_krbLifeMaxHrEditbox; + static CEdit m_krbRenewMinMinEditbox; + static CEdit m_krbRenewMinHrEditbox; + static CEdit m_krbRenewMaxMinEditbox; + static CEdit m_krbRenewMaxHrEditbox; + //}}AFX_DATA + + +// Overrides + // ClassWizard generate virtual function overrides + //{{AFX_VIRTUAL(CKrbConfigOptions) + public: + virtual BOOL PreTranslateMessage(MSG* pMsg); + protected: + virtual VOID DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + + virtual BOOL OnApply(); + +// Implementation +protected: + // Generated message map functions + //{{AFX_MSG(CKrbMiscConfigOpt) + virtual BOOL OnInitDialog(); + afx_msg void OnShowWindow(BOOL bShow, UINT nStatus); + afx_msg void OnEditKillfocusEditDefaultLifeTime(); + afx_msg void OnResetDefaultLifeTimeEditBox(); + afx_msg void OnSelchangeEditDefaultLifeTime(); + afx_msg void OnEditKillfocusEditDefaultRenewTill(); + afx_msg void OnResetDefaultRenewTillEditBox(); + afx_msg void OnSelchangeEditDefaultRenewTill(); + afx_msg void OnEditKillfocusEditDefaultLifeMin(); + afx_msg void OnResetDefaultLifeMinEditBox(); + afx_msg void OnSelchangeEditDefaultLifeMin(); + afx_msg void OnEditKillfocusEditDefaultLifeMax(); + afx_msg void OnResetDefaultLifeMaxEditBox(); + afx_msg void OnSelchangeEditDefaultLifeMax(); + afx_msg void OnEditKillfocusEditDefaultRenewMin(); + afx_msg void OnResetDefaultRenewMinEditBox(); + afx_msg void OnSelchangeEditDefaultRenewMin(); + afx_msg void OnEditKillfocusEditDefaultRenewMax(); + afx_msg void OnResetDefaultRenewMaxEditBox(); + afx_msg void OnSelchangeEditDefaultRenewMax(); + afx_msg void OnCheckUseKrb4(); + afx_msg void OnCheckKinitPreserve(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + +}; + +///////////////////////////////////////////////////////////////////////////// +//{{AFX_INSERT_LOCATION}} +// Microsoft Developer Studio will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_MISCONFIGOPT_H__CD702F99_7495_11D0_8FDC_00C04FC2A0C2__INCLUDED_) diff --git a/src/windows/leash/KrbProperties.cpp b/src/windows/leash/KrbProperties.cpp new file mode 100644 index 000000000..d26987e4a --- /dev/null +++ b/src/windows/leash/KrbProperties.cpp @@ -0,0 +1,102 @@ +// File: KrbProperties.cpp +// By: Arthur David Leather +// Created: 12/02/98 +// Copyright @1998 Massachusetts Institute of Technology - All rights reserved. +// Description: CPP file for KrbProperties.h. Contains variables and functions +// for Kerberos Four Properties +// +// History: +// +// MM/DD/YY Inits Description of Change +// 02/01/98 ADL Original +// ************************************************************************************** + + +#include "stdafx.h" +#include "KrbProperties.h" +#include "Krb4Properties.h" + +#include "Leash.h" +#include "wshelper.h" +#include "lglobals.h" +#include "reminder.h" + +CHAR CKrbProperties::m_krbPath[MAX_PATH]; +CHAR CKrbProperties::m_krbrealmPath[MAX_PATH]; +BOOL CKrbProperties::KrbPropertiesOn; + +/////////////////////////////////////////////////////////////////////// +// CKrbProperties + +IMPLEMENT_DYNAMIC(CKrbProperties, CPropertySheet) +CKrbProperties::CKrbProperties(UINT nIDCaption, CWnd* pParentWnd, + UINT iSelectPage) +:CPropertySheet(nIDCaption, pParentWnd, iSelectPage) +{ +} + +CKrbProperties::CKrbProperties(LPCTSTR pszCaption, CWnd* pParentWnd, + UINT iSelectPage) +:CPropertySheet(pszCaption, pParentWnd, iSelectPage) +{ + KrbPropertiesOn = FALSE; + +#ifdef COMMENT + // If this will not be fatal, then it does not need to be performed here. + if (CLeashApp::m_hKrb5DLL) + { + char *realm = NULL; + pkrb5_get_default_realm(CLeashApp::m_krbv5_context, &realm); + + if (!realm) + { + MessageBox("CKrbProperties::Unable to determine default Kerberos REALM.\ + \n Consult your Administrator!", + "Error", MB_OK); + // I don't think this is necessarily fatal. - jaltman + // return; + } + } +#endif /* COMMENT */ + + CLeashApp::GetKrb4ConFile(m_krbPath,sizeof(m_krbPath)); + CLeashApp::GetKrb4RealmFile(m_krbrealmPath,sizeof(m_krbrealmPath)); + + + AddPage(&m_configOptions); + AddPage(&m_miscConfigOpt); + + if (CLeashApp::m_hKrb4DLL && !CLeashApp::m_hKrb5DLL) + { + AddPage(&m_krb4RealmHostMaintenance); + AddPage(&m_krb4DomainRealmMaintenance); + } + else if (CLeashApp::m_hKrb5DLL) + { + AddPage(&m_realmHostMaintenance); + AddPage(&m_domainRealmMaintenance); + } + + KrbPropertiesOn = TRUE; +} + +CKrbProperties::~CKrbProperties() +{ + KrbPropertiesOn = FALSE; +} + +void CKrbProperties::OnHelp() +{ + AfxGetApp()->WinHelp(HID_KERBEROS_PROPERTIES_COMMAND); +} + + +BEGIN_MESSAGE_MAP(CKrbProperties, CPropertySheet) + //{{AFX_MSG_MAP(CKrbProperties) + // NOTE - the ClassWizard will add and remove mapping macros here. + ON_COMMAND(ID_HELP, OnHelp) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +/////////////////////////////////////////////////////////////////////// +// CKrbProperties message handlers diff --git a/src/windows/leash/KrbProperties.h b/src/windows/leash/KrbProperties.h new file mode 100644 index 000000000..c73ca6e68 --- /dev/null +++ b/src/windows/leash/KrbProperties.h @@ -0,0 +1,89 @@ +// ************************************************************************************** +// File: KrbProperties.h +// By: Arthur David Leather +// Created: 12/02/98 +// Copyright @1998 Massachusetts Institute of Technology - All rights reserved. +// Description: H file for KrbProperties.cpp. Contains variables and functions +// for Kerberos Four Properties +// +// History: +// +// MM/DD/YY Inits Description of Change +// 02/01/98 ADL Original +// ************************************************************************************** + + +#if !defined(AFX_KRB_PROPERTY_H__CD702F99_7495_11D0_8FDC_00C04FC2A0C2__INCLUDED_) +#define AFX_KRB_PROPERTY_H__CD702F99_7495_11D0_8FDC_00C04FC2A0C2__INCLUDED_ + +#if _MSC_VER >= 1000 +#pragma once +#endif // _MSC_VER >= 1000 +// KrbProperties.h : header file +// + +#include "KrbConfigOptions.h" +#include "KrbRealmHostMaintenance.h" +#include "KrbDomainRealmMaintenance.h" +#include "Krb4DomainRealmMaintenance.h" +#include "Krb4RealmHostMaintenance.h" +#include "KrbMiscConfigOpt.h" + +////////////////////////////////////////////////////////////////////// +// CKrbProperties + +class CKrbProperties : public CPropertySheet +{ +private: + DECLARE_DYNAMIC(CKrbProperties) + +public: + //CKrbConfigFileLocation m_fileLocation; + CKrbConfigOptions m_configOptions; + CKrb4RealmHostMaintenance m_krb4RealmHostMaintenance; + CKrbRealmHostMaintenance m_realmHostMaintenance; + CKrb4DomainRealmMaintenance m_krb4DomainRealmMaintenance; + CKrbDomainRealmMaintenance m_domainRealmMaintenance; + CKrbMiscConfigOpt m_miscConfigOpt; + + static BOOL KrbPropertiesOn; + static BOOL applyButtonEnabled; + static CHAR m_krbPath[MAX_PATH]; + static CHAR m_krbrealmPath[MAX_PATH]; + +// Construction +public: + CKrbProperties(UINT nIDCaption, CWnd* pParentWnd = NULL, + UINT iSelectPage = 0); + CKrbProperties(LPCTSTR pszCaption, CWnd* pParentWnd = NULL, + UINT iSelectPage = 0); + +// Attributes +public: + +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CKrbProperties) + //}}AFX_VIRTUAL + +// Implementation +public: + virtual ~CKrbProperties(); + + // Generated message map functions +protected: + //{{AFX_MSG(CKrbProperties) + // NOTE - the ClassWizard will add and remove member functions here. + afx_msg void OnHelp(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// +//{{AFX_INSERT_LOCATION}} +// Microsoft Developer Studio will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_KRB_PROPERTY_H__CD702F99_7495_11D0_8FDC_00C04FC2A0C2__INCLUDED_) diff --git a/src/windows/leash/KrbRealmHostMaintenance.cpp b/src/windows/leash/KrbRealmHostMaintenance.cpp new file mode 100644 index 000000000..7dac506f1 --- /dev/null +++ b/src/windows/leash/KrbRealmHostMaintenance.cpp @@ -0,0 +1,1047 @@ +// ************************************************************************************** +// File: KrbRealmHostMaintenance.cpp +// By: Arthur David Leather +// Created: 12/02/98 +// Copyright @1998 Massachusetts Institute of Technology - All rights reserved. +// Description: CPP file for KrbRealmHostMaintenance.h. Contains variables and functions +// for Kerberos Four and Five Properties +// +// History: +// +// MM/DD/YY Inits Description of Change +// 12/02/98 ADL Original +// ************************************************************************************** + + +#include "stdafx.h" +#include "leash.h" +#include "KrbProperties.h" +#include "Krb4Properties.h" +#include "KrbAddRealm.h" +#include "KrbAddHostServer.h" +#include "KrbRealmHostMaintenance.h" +#include "KrbEditRealm.h" +#include "KrbEditHostServer.h" +#include "KrbConfigOptions.h" + +#include "lglobals.h" +#include "MainFrm.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CKrbRealmHostMaintenance dialog + + +IMPLEMENT_DYNCREATE(CKrbRealmHostMaintenance, CPropertyPage) + +CKrbRealmHostMaintenance::CKrbRealmHostMaintenance() + : CPropertyPage(CKrbRealmHostMaintenance::IDD) +{ + m_isRealmListBoxInFocus = FALSE; + m_isStart = TRUE; + m_theAdminServer = _T(""); + m_theAdminServerMarked = _T(""); + m_initDnsKdcLookup = 0; + m_newDnsKdcLookup = 0; + + m_KDCHostList.initOtherListbox(this, &m_KDCRealmList); +} + +CKrbRealmHostMaintenance::~CKrbRealmHostMaintenance() +{ +} + +void CKrbRealmHostMaintenance::DoDataExchange(CDataExchange* pDX) +{ + CPropertyPage::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CKrbRealmHostMaintenance) + DDX_Control(pDX, IDC_LIST_KDC_REALM, m_KDCRealmList); + DDX_Control(pDX, IDC_LIST_KDC_HOST, m_KDCHostList); + //}}AFX_DATA_MAP +} + +BEGIN_MESSAGE_MAP(CKrbRealmHostMaintenance, CPropertyPage) + //{{AFX_MSG_MAP(CKrbRealmHostMaintenance) + ON_BN_CLICKED(IDC_BUTTON_REALM_HOST_ADD, OnButtonRealmHostAdd) + ON_BN_CLICKED(IDC_BUTTON_REALM_EDIT, OnButtonRealmHostEdit) + ON_BN_CLICKED(ID_BUTTON_REALM_REMOVE, OnButtonRealmHostRemove) + ON_LBN_SELCHANGE(IDC_LIST_KDC_REALM, OnSelchangeListKdcRealm) + ON_BN_CLICKED(IDC_BUTTON_ADMINSERVER, OnButtonAdminserver) + ON_LBN_SETFOCUS(IDC_LIST_KDC_REALM, OnSetfocusListKdcRealm) + ON_BN_CLICKED(IDC_BUTTON_KDCHOST_ADD, OnButtonKdchostAdd) + ON_BN_CLICKED(IDC_BUTTON_KDCHOST_REMOVE, OnButtonKdchostRemove) + ON_BN_CLICKED(IDC_BUTTON_REMOVE_ADMINSERVER, OnButtonRemoveAdminserver) + ON_LBN_SELCHANGE(IDC_LIST_KDC_HOST, OnSelchangeListKdcHost) + ON_BN_CLICKED(IDC_BUTTON_KDCHOST_EDIT, OnButtonKdchostEdit) + ON_LBN_DBLCLK(IDC_LIST_KDC_REALM, OnDblclkListKdcRealm) + ON_LBN_DBLCLK(IDC_LIST_KDC_HOST, OnDblclkListKdcHost) + ON_WM_KEYDOWN() + ON_WM_CANCELMODE() + ON_BN_CLICKED(IDC_BUTTON_REALMHOST_MAINT_HELP, OnButtonRealmhostMaintHelp) + ON_BN_CLICKED(IDC_DNS_KDC, OnCheckDnsKdcLookup) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CKrbRealmHostMaintenance message handlers + +BOOL CKrbRealmHostMaintenance::OnInitDialog() +{ + CPropertyPage::OnInitDialog(); + + const char* rootSection[] = {"realms", NULL}; + const char** rootsec = rootSection; + char **sections = NULL, + **cpp = NULL, + *value = NULL; + + long retval = pprofile_get_subsection_names(CLeashApp::m_krbv5_profile, + rootsec, §ions); + + if (retval && PROF_NO_RELATION != retval) + { + MessageBox("OnInitDialog::There is an error, profile will not be saved!!!\ + \nIf this error persist, contact your administrator.", + "Leash", MB_OK); + return TRUE; + } + + for (cpp = sections; *cpp; cpp++) + { + if (LB_ERR == m_KDCRealmList.AddString(*cpp)) + { + MessageBox("OnInitDialog::Can't add to Kerberos Realm Listbox", + "Leash", MB_OK); + return FALSE; + } + } + + pprofile_free_list(sections); + + // Determine the starting value for DNS KDC Lookup Checkbox + retval = pprofile_get_string(CLeashApp::m_krbv5_profile, "libdefaults", + "dns_lookup_kdc", 0, 0, &value); + if (value == 0 && retval == 0) + retval = pprofile_get_string(CLeashApp::m_krbv5_profile, "libdefaults", + "dns_fallback", 0, 0, &value); + if (value == 0) { +#if KRB5_DNS_LOOKUP_KDC + m_initDnsKdcLookup = m_newDnsKdcLookup = 1; +#else + m_initDnsKdcLookup = m_newDnsKdcLookup = 0; +#endif + } else { + m_initDnsKdcLookup = m_newDnsKdcLookup = config_boolean_to_int(value); + pprofile_release_string(value); + } + CheckDlgButton(IDC_DNS_KDC, m_initDnsKdcLookup); + + // Compaire Krb Four with what's in the Krb Five Profile Linklist + // and add to m_KDCRealmList if needed. + m_KDCRealmList.SetCurSel(0); + + if (!m_KDCRealmList.GetCount()) + { + GetDlgItem(IDC_BUTTON_REALM_EDIT)->EnableWindow(FALSE); + } + else if (1 >= m_KDCRealmList.GetCount()) + { + GetDlgItem(ID_BUTTON_REALM_REMOVE)->EnableWindow(FALSE); + } + else + { + GetDlgItem(ID_BUTTON_REALM_REMOVE)->EnableWindow(); + GetDlgItem(IDC_BUTTON_REALM_EDIT)->EnableWindow(); + } + + + if (!m_KDCHostList.GetCount()) + { + GetDlgItem(IDC_BUTTON_KDCHOST_REMOVE)->EnableWindow(FALSE); + GetDlgItem(IDC_BUTTON_KDCHOST_EDIT)->EnableWindow(FALSE); + } + else + { + GetDlgItem(IDC_BUTTON_KDCHOST_REMOVE)->EnableWindow(); + GetDlgItem(IDC_BUTTON_KDCHOST_EDIT)->EnableWindow(); + } + + + return TRUE; +} + +BOOL CKrbRealmHostMaintenance::OnApply() +{ + char theSection[REALM_SZ + 1]; + const char* adminServer[] = {"realms", theSection, ADMIN_SERVER, NULL}; + const char* Section[] = {"realms", theSection, "kdc", NULL}; //theSection + const char** section = Section; + const char** adminServ = adminServer; + + if (!CLeashApp::m_krbv5_profile) { + CHAR confname[MAX_PATH]; + if (!CLeashApp::GetProfileFile(confname, sizeof(confname))) + { + const char *filenames[2]; + filenames[0] = confname; + filenames[1] = NULL; + pprofile_init(filenames, &CLeashApp::m_krbv5_profile); + } + } + + /* + // Safety check for empty section (may not be need, but left it in anyway) + INT maxRealms = m_KDCRealmList.GetCount(); + for (INT realm = 0; realm < maxRealms; realm++) + { + m_KDCRealmList.GetText(realm, theSection); + long retval = pprofile_get_values(CLeashApp::m_krbv5_profile, + section, &values); + pprofile_free_list(values); + + if (PROF_NO_RELATION == retval) + { + if (IDYES == AfxMessageBox("One or more Realms do not have any corresponing Servers!!!\n\nContinue?", + MB_YESNO)) + break; + else + return TRUE; + } + + if (retval && PROF_NO_RELATION != retval) + { + MessageBox("OnApply::There is an error, profile will not be saved!!!\nIf this error persist, contact your administrator.", + "Error", MB_OK); + return TRUE; + } + } + */ + + long retval = pprofile_flush(CLeashApp::m_krbv5_profile); + + if (retval && PROF_NO_RELATION != retval) + { + MessageBox("OnApply::There is an error, profile will not be saved!!!\ + \nIf this error persist, contact your administrator.", + "Leash", MB_OK); + } + + + // Save to Kerberos Four config. file "Krb.con" + CStdioFile krbCon; + if (!krbCon.Open(CKrbProperties::m_krbPath, CFile::modeCreate | + CFile::modeNoTruncate | + CFile::modeReadWrite)) + { + LeashErrorBox("OnApply::Can't open Configuration File", + CKrbProperties::m_krbPath); + return TRUE; + } + + krbCon.SetLength(0); + + krbCon.WriteString(CKrbConfigOptions::m_newDefaultRealm); + krbCon.WriteString("\n"); + + for (INT maxItems = m_KDCRealmList.GetCount(), item = 0; item < maxItems; item++) + { + char **values = NULL, + **cpp = NULL, + **admin = NULL; + + if (LB_ERR == m_KDCRealmList.GetText(item, theSection)) + ASSERT(0); + + retval = pprofile_get_values(CLeashApp::m_krbv5_profile, + section, &values); + + if (retval && PROF_NO_RELATION != retval) + { + MessageBox("OnApply::There is an error, profile will not be saved!!!\ + \nIf this error persist, contact your administrator.", + "Leash", MB_OK); + } + + retval = pprofile_get_values(CLeashApp::m_krbv5_profile, + adminServ , &admin); + + if (retval && PROF_NO_RELATION != retval) + { + MessageBox("OnApply::There is an error, profile will not be saved!!!\ + \nIf this error persist, contact your administrator.", + "Leash", MB_OK); + } + + char* pSemiCl = NULL; + if (admin) + { + if (*admin) + { + if ((pSemiCl = strchr(*admin, ':'))) + *pSemiCl = 0; + } + } + + + char hostKdc[MAX_HSTNM]; + if (values) + for (cpp = values; *cpp; cpp++) + { + strcpy(hostKdc, *cpp); + + if ((pSemiCl = strchr(hostKdc, ':'))) + *pSemiCl = 0; + + if (admin) + { + if (*admin) + { + if (0 == stricmp(hostKdc, *admin)) + strcat(hostKdc, " admin server"); + } + } + + CString kdcHost = theSection; + kdcHost += " "; + kdcHost += hostKdc; + + krbCon.WriteString(kdcHost); + krbCon.WriteString("\n"); + } + + if (values) + pprofile_free_list(values); + + if (admin) + pprofile_free_list(admin); + } + + if ( m_newDnsKdcLookup ) + krbCon.WriteString(".KERBEROS.OPTION. dns\n"); + + krbCon. Close(); + return TRUE; +} + +void CKrbRealmHostMaintenance::OnCancel() +{ + CHAR fileName[MAX_PATH]; + if (CLeashApp::GetProfileFile(fileName, sizeof(fileName))) + { + MessageBox("Can't locate Kerberos Five Config. file!", "Error", MB_OK); + return; + } + + + long retval = 0; + if (CLeashApp::m_krbv5_profile) + pprofile_abandon(CLeashApp::m_krbv5_profile); + + /* + if (retval) + { + MessageBox("OnButtonRealmHostAdd::There is an error, profile will not be abandon!!!\ + \nIf this error persist, contact your administrator.", + "Leash", MB_OK); + return; + } + */ + + const char *filenames[2]; + filenames[0] = fileName; + filenames[1] = NULL; + retval = pprofile_init(filenames, &CLeashApp::m_krbv5_profile); + + if (retval) + { + MessageBox("OnButtonRealmHostAdd::There is an error, profile will not be initialized!!!\ + \nIf this error persist, contact your administrator.", + "Leash", MB_OK); + return; + } + + + CPropertyPage::OnCancel(); +} + +void CKrbRealmHostMaintenance::OnCheckDnsKdcLookup() +{ + const char* dnsLookupKdc[] = {"libdefaults","dns_lookup_kdc",NULL}; + + m_newDnsKdcLookup = (BOOL)IsDlgButtonChecked(IDC_DNS_KDC); + + long retval = pprofile_clear_relation(CLeashApp::m_krbv5_profile, + dnsLookupKdc); + + if (retval && PROF_NO_RELATION != retval) + { + MessageBox("OnButtonAdminserver::There is an error, profile will not be saved!!!\ + \nIf this error persist, contact your administrator.", + "Error", MB_OK); + return; + } + + retval = pprofile_add_relation(CLeashApp::m_krbv5_profile, + dnsLookupKdc, + m_newDnsKdcLookup ? "true" : "false"); + + if (retval) + { // this might not be a good way to handle this type of error + MessageBox("OnButtonAdminserver::There is an error, profile will not be saved!!!\ + \nIf this error persist, contact your administrator.", + "Error", MB_OK); + return; + } + SetModified(TRUE); +} + +void CKrbRealmHostMaintenance::OnButtonRealmHostAdd() +{ + m_KDCRealmList.SetFocus(); + + CKrbAddRealm addToRealmHostList; + if (IDOK == addToRealmHostList.DoModal()) + { + char theSection[REALM_SZ + 1]; + const char* Section[] = {"realms", theSection, NULL}; + const char** section = Section; + + + if (!CLeashApp::m_krbv5_profile) { + CHAR confname[MAX_PATH]; + if (!CLeashApp::GetProfileFile(confname, sizeof(confname))) + { + const char *filenames[2]; + filenames[0] = confname; + filenames[1] = NULL; + pprofile_init(filenames, &CLeashApp::m_krbv5_profile); + } + } + + CString newRealm; // new section in the profile linklist + newRealm = addToRealmHostList.GetNewRealm(); + + if (LB_ERR != m_KDCRealmList.FindStringExact(-1, newRealm)) + { + MessageBox("We can't have duplicate Realms!\nYour entry was not saved to list.", + "Leash", MB_OK); + return; + } + + if (addToRealmHostList.GetNewRealm().IsEmpty()) + ASSERT(0); + + strcpy(theSection, newRealm); + long retval = pprofile_add_relation(CLeashApp::m_krbv5_profile, + section, NULL); + + if (retval) + { + MessageBox("OnButtonRealmHostAdd::There is an error, profile will not be saved!!!\ + \nIf this error persist, contact your administrator.", + "Leash", MB_OK); + return; + } + + if (LB_ERR == m_KDCRealmList.AddString(newRealm)) + ASSERT(0); + + if (LB_ERR == m_KDCRealmList.SetCurSel(m_KDCRealmList.FindStringExact(-1, newRealm))) + ASSERT(0); + + MessageBox("You must now add a Kerberos Host Server or Realm you just added will be removed!!!", + "Leash", MB_OK); + + m_KDCHostList.ResetContent(); + if (OnButtonKdchostAddInternal()) + { // Cancel + + long retval = pprofile_rename_section(CLeashApp::m_krbv5_profile, + section, NULL); + + if (retval) + { + MessageBox("OnButtonRealmHostRemove::There is an error, profile will not be saved!!!\ + \nIf this error persist, contact your administrator.", + "Leash", MB_OK); + return; + } + + if (LB_ERR == m_KDCRealmList.DeleteString(m_KDCRealmList.GetCurSel())) + ASSERT(0); + + m_KDCRealmList.SetCurSel(0); + } + + OnSelchangeListKdcRealm(); + SetModified(TRUE); + } + + if (1 >= m_KDCRealmList.GetCount()) + { + GetDlgItem(ID_BUTTON_REALM_REMOVE)->EnableWindow(FALSE); + } + else + { + GetDlgItem(ID_BUTTON_REALM_REMOVE)->EnableWindow(); + GetDlgItem(IDC_BUTTON_REALM_EDIT)->EnableWindow(); + } +} + +void CKrbRealmHostMaintenance::OnButtonKdchostAdd() +{ + OnButtonKdchostAddInternal(); +} + +bool CKrbRealmHostMaintenance::OnButtonKdchostAddInternal() +{ + CString newHost; // new section in the profile linklist + CKrbAddHostServer addHostServer; + if (IDOK == addHostServer.DoModal()) + { // OK + char theSection[MAX_HSTNM + 1]; + const char* Section[] = {"realms", theSection, "kdc", NULL}; + const char** section = Section; + + if (addHostServer.GetNewHost().IsEmpty()) + ASSERT(0); + + newHost = addHostServer.GetNewHost(); + + if (LB_ERR != m_KDCHostList.FindStringExact(-1, newHost)) + { + MessageBox("We can't have duplicate Host Servers for the same Realm!\ + \nYour entry was not saved to list.", + "Leash", MB_OK); + return true; + } + + m_KDCRealmList.GetText(m_KDCRealmList.GetCurSel(), theSection); + long retval = pprofile_add_relation(CLeashApp::m_krbv5_profile, + section, addHostServer.GetNewHost()); + + if (retval) + { + MessageBox("OnButtonKdchostAdd::There is an error, profile will not be saved!!!\ + \nIf this error persist, contact your administrator.", + "Leash", MB_OK); + + return true; + } + + if (LB_ERR == m_KDCHostList.AddString(newHost)) + ASSERT(0); + + SetModified(TRUE); + } + else + return true; + + if (m_KDCHostList.GetCount() > 1) + { + m_KDCHostList.SetCurSel(m_KDCHostList.FindStringExact(-1, newHost)); + m_KDCHostList.SetFocus(); + OnSelchangeListKdcHost(); + + GetDlgItem(IDC_BUTTON_KDCHOST_REMOVE)->EnableWindow(); + } + + if (1 == m_KDCRealmList.GetCount()) + { + GetDlgItem(IDC_BUTTON_KDCHOST_REMOVE)->EnableWindow(); + GetDlgItem(IDC_BUTTON_KDCHOST_EDIT)->EnableWindow(); + } + + return false; +} + +void CKrbRealmHostMaintenance::OnButtonRealmHostEdit() +{ + INT selItemIndex = m_KDCRealmList.GetCurSel(); + CString selItem; + + m_KDCHostList.SetFocus(); + //m_KDCRealmList.SetFocus(); + //m_KDCHostList.SetCurSel(0); + m_KDCRealmList.GetText(selItemIndex, selItem); + + CKrbEditRealm editRealmHostList(selItem); + + if (IDOK == editRealmHostList.DoModal()) + { + char theSection[REALM_SZ + 1]; + const char* Section[] = {"realms", theSection, NULL}; + const char** section = Section; + + CString editedRealm = editRealmHostList.GetEditedItem(); + + if (0 != editedRealm.CompareNoCase(selItem) && + LB_ERR != m_KDCRealmList.FindStringExact(-1, editedRealm)) + { + MessageBox("We can't have duplicate Realms!\nYour entry was not saved to list.", + "Leash", MB_OK); + return; + } + + strcpy(theSection, selItem); + + long retval = pprofile_rename_section(CLeashApp::m_krbv5_profile, + section, editRealmHostList.GetEditedItem()); + + if (retval) + { + MessageBox("OnButtonRealmHostEdit::There is an error, profile will not be saved!!!\ + \nIf this error persist, contact your administrator.", + "Leash", MB_OK); + return; + } + + m_KDCRealmList.DeleteString(selItemIndex); + m_KDCRealmList.AddString(editedRealm); + selItemIndex = m_KDCRealmList.FindStringExact(-1, editedRealm); + m_KDCRealmList.SetCurSel(selItemIndex); + + CKrbConfigOptions::ResetDefaultRealmComboBox(); + SetModified(TRUE); + } +} + +void CKrbRealmHostMaintenance::OnDblclkListKdcRealm() +{ + OnButtonRealmHostEdit(); +} + +void CKrbRealmHostMaintenance::OnButtonKdchostEdit() +{ + INT selItemIndex = m_KDCHostList.GetCurSel(); + CHAR OLD_VALUE[MAX_HSTNM + 1]; + CString editedHostServer; + CString _adminServer; + + m_KDCHostList.SetFocus(); + m_KDCHostList.GetText(selItemIndex, OLD_VALUE); + + LPSTR pOLD_VALUE = strchr(OLD_VALUE, ' '); + if (pOLD_VALUE) + { + *pOLD_VALUE = 0; + _adminServer = pOLD_VALUE + 1; + } + + CString selItem = OLD_VALUE; + CKrbEditHostServer editHostServerList(selItem); + + if (IDOK == editHostServerList.DoModal()) + { + char theSection[REALM_SZ + 1]; + const char* adminServer[] = {"realms", theSection, ADMIN_SERVER, NULL}; + const char* Section[] = {"realms", theSection, "kdc", NULL}; + const char** section = Section; + const char** adminServ = adminServer; + + editedHostServer = editHostServerList.GetEditedItem(); + + if (0 != editedHostServer.CompareNoCase(selItem) && + LB_ERR != m_KDCHostList.FindStringExact(-1, editedHostServer)) + { + MessageBox("We can't have duplicate Host Servers for the same Realm!\ + \nYour entry was not saved to list.", + "Leash", MB_OK); + return; + } + + m_KDCHostList.DeleteString(selItemIndex); + m_KDCRealmList.GetText(m_KDCRealmList.GetCurSel(), theSection); + + if (!_adminServer.IsEmpty()) + { // there is a admin_server + editedHostServer += " "; + editedHostServer += _adminServer; + + long retval = pprofile_update_relation(CLeashApp::m_krbv5_profile, + adminServ, OLD_VALUE, editHostServerList.GetEditedItem()); + if (retval) + { + MessageBox("OnButtonKdchostEdit::There is an error, profile will not be saved!!!\ + \nIf this error persist, contact your administrator.", + "Leash", MB_OK); + return; + } + } + + long retval = pprofile_update_relation(CLeashApp::m_krbv5_profile, + section, OLD_VALUE, editHostServerList.GetEditedItem()); + + if (retval) + { + MessageBox("OnButtonKdchostEdit::There is an error, profile will not be saved!!!\ + \nIf this error persist, contact your administrator.", + "Leash", MB_OK); + return; + } + + m_KDCHostList.InsertString(selItemIndex, editedHostServer); + m_KDCHostList.SetCurSel(selItemIndex); + + OnSelchangeListKdcHost(); + SetModified(TRUE); + } +} + +void CKrbRealmHostMaintenance::OnDblclkListKdcHost() +{ + OnButtonKdchostEdit(); +} + +void CKrbRealmHostMaintenance::OnButtonRealmHostRemove() +{ + char theSection[REALM_SZ + 1]; + const char* Section[] = {"realms", theSection, NULL}; + const char** section = Section; + + m_KDCRealmList.SetFocus(); + m_KDCRealmList.GetText(m_KDCRealmList.GetCurSel(), theSection); + + CString RealmMsg; + RealmMsg.Format("Your about to remove a Realm, \"%s\", and all it's dependents from the list!\n\nContinue?", + theSection); + + if (IDYES != AfxMessageBox(RealmMsg, MB_YESNO)) + return; + + long retval = pprofile_rename_section(CLeashApp::m_krbv5_profile, + section, NULL); + + if (retval) + { + MessageBox("OnButtonRealmHostRemove::There is an error, profile will not be saved!!!\ + \nIf this error persist, contact your administrator.", + "Leash", MB_OK); + return; + } + + INT curSel = m_KDCRealmList.GetCurSel(); + + if (LB_ERR == m_KDCRealmList.DeleteString(curSel)) + ASSERT(0);// Single Sel Listbox + + if (-1 == m_KDCRealmList.SetCurSel(curSel)) + m_KDCRealmList.SetCurSel(curSel - 1); + + SetModified(TRUE); + + if (!m_KDCRealmList.GetCount()) + { + GetDlgItem(IDC_BUTTON_REALM_EDIT)->EnableWindow(FALSE); + } + if (1 >= m_KDCRealmList.GetCount()) + { + OnSelchangeListKdcRealm(); + GetDlgItem(ID_BUTTON_REALM_REMOVE)->EnableWindow(FALSE); + } + else + OnSelchangeListKdcRealm(); +} + +void CKrbRealmHostMaintenance::OnButtonKdchostRemove() +{ + char theSection[REALM_SZ + 1]; + const char* adminServer[] = {"realms", theSection, ADMIN_SERVER, NULL}; + const char* Section[] = {"realms", theSection, "kdc", NULL}; + const char** section = Section; + const char** adminServ = adminServer; + CHAR OLD_VALUE[MAX_HSTNM + 1]; + CString serverHostMsg; + CString serverHost; + CString _adminServer; + + m_KDCHostList.GetText(m_KDCHostList.GetCurSel(), serverHost); + serverHostMsg.Format("Your about to remove Server \"%s\" from the list!\n\nContinue?", + serverHost); + + if (IDYES != AfxMessageBox(serverHostMsg, MB_YESNO)) + return; + + m_KDCRealmList.GetText(m_KDCRealmList.GetCurSel(), theSection); + INT curSel = m_KDCHostList.GetCurSel(); + m_KDCHostList.GetText(curSel, OLD_VALUE); + + LPSTR pOLD_VALUE = strchr(OLD_VALUE, ' '); + if (pOLD_VALUE) + { + *pOLD_VALUE = 0; + _adminServer = pOLD_VALUE + 1; + } + + long retval = pprofile_update_relation(CLeashApp::m_krbv5_profile, + section, OLD_VALUE, NULL); + if (retval) + { + MessageBox("OnButtonKdchostRemove::There is an error, profile will not be saved!!!\ + \nIf this error persist, contact your administrator.", + "Leash", MB_OK); + return; + } + + if (!_adminServer.IsEmpty()) + { // there is a admin_server + retval = pprofile_update_relation(CLeashApp::m_krbv5_profile, + adminServ, OLD_VALUE, NULL); + if (retval) + { + MessageBox("OnButtonKdchostRemove::There is an error, profile will not be saved!!!\ + \nIf this error persist, contact your administrator.", + "Error", MB_OK); + return; + } + } + + m_KDCHostList.DeleteString(curSel); + + if (-1 == m_KDCHostList.SetCurSel(curSel)) + m_KDCHostList.SetCurSel(curSel - 1); + + SetModified(TRUE); + + if (!m_KDCHostList.GetCount()) + { + GetDlgItem(IDC_BUTTON_KDCHOST_REMOVE)->EnableWindow(FALSE); + GetDlgItem(IDC_BUTTON_KDCHOST_EDIT)->EnableWindow(FALSE); + GetDlgItem(IDC_BUTTON_ADMINSERVER)->EnableWindow(FALSE); + GetDlgItem(IDC_BUTTON_REMOVE_ADMINSERVER)->EnableWindow(FALSE); + } + else if (m_KDCHostList.GetCount() <= 1) + GetDlgItem(IDC_BUTTON_KDCHOST_REMOVE)->EnableWindow(FALSE); + + OnSelchangeListKdcHost(); +} + +BOOL CKrbRealmHostMaintenance::PreTranslateMessage(MSG* pMsg) +{ + if (m_isStart) + { + OnSelchangeListKdcRealm(); + m_isStart = FALSE; + } + + return CPropertyPage::PreTranslateMessage(pMsg); +} + +void CKrbRealmHostMaintenance::OnSelchangeListKdcRealm() +{ + char theSection[REALM_SZ + 1]; + const char* adminServer[] = {"realms", theSection, ADMIN_SERVER, NULL}; + const char* Section[] = {"realms", theSection, "kdc", NULL}; //theSection + const char** section = Section; + const char** adminServ = adminServer; + char **values = NULL, + **adminValue = NULL, + **cpp = NULL; + + m_KDCRealmList.GetText(m_KDCRealmList.GetCurSel(), theSection); + + long retval = pprofile_get_values(CLeashApp::m_krbv5_profile, + section, &values); + + if (retval && PROF_NO_RELATION != retval) + { + MessageBox("OnSelchangeListKdcRealm::There is an error, profile will not be saved!!!\ + \nIf this error persist, contact your administrator.", + "Error", MB_OK); + return; + } + + m_KDCHostList.ResetContent(); + + if ( !retval && values ) { + retval = pprofile_get_values(CLeashApp::m_krbv5_profile, + adminServ, &adminValue); + + if (retval && PROF_NO_RELATION != retval) + { + MessageBox("OnSelchangeListKdcRealm::There is an error, profile will not be saved!!!\ + \nIf this error persist, contact your administrator.", + "Error", MB_OK); + return; + } + + m_theAdminServer = _T(""); + m_theAdminServerMarked = _T(""); + + for (cpp = values; *cpp; cpp++) + { + CString kdcHost = *cpp; + + if (adminValue && 0 == strcmp(*adminValue, *cpp)) + { + m_theAdminServer = kdcHost; + kdcHost += " "; + kdcHost += ADMIN_SERVER; + + m_theAdminServerMarked = kdcHost; + } + + if (LB_ERR == m_KDCHostList.AddString(kdcHost)) + { + MessageBox("OnSelchangeListKdcRealm::Can't add Realm to Listbox", + "Error", MB_OK); + } + } + + pprofile_free_list(values); + } else { + GetDlgItem(IDC_BUTTON_REALM_HOST_ADD)->EnableWindow(TRUE); + GetDlgItem(ID_BUTTON_REALM_REMOVE)->EnableWindow(FALSE); + GetDlgItem(IDC_BUTTON_REALM_EDIT)->EnableWindow(FALSE); + } + CKrbConfigOptions::ResetDefaultRealmComboBox(); + + GetDlgItem(IDC_BUTTON_KDCHOST_REMOVE)->EnableWindow(FALSE); + GetDlgItem(IDC_BUTTON_KDCHOST_EDIT)->EnableWindow(FALSE); +} + +void CKrbRealmHostMaintenance::OnSelchangeListKdcHost() +{ + CString adminServer; + m_KDCHostList.GetText(m_KDCHostList.GetCurSel(), adminServer); + + if (-1 != adminServer.Find(ADMIN_SERVER)) + { + GetDlgItem(IDC_BUTTON_ADMINSERVER)->EnableWindow(FALSE); + GetDlgItem(IDC_BUTTON_REMOVE_ADMINSERVER)->EnableWindow(); + } + else + { + GetDlgItem(IDC_BUTTON_ADMINSERVER)->EnableWindow(); + GetDlgItem(IDC_BUTTON_REMOVE_ADMINSERVER)->EnableWindow(FALSE); + } + + if (m_KDCHostList.GetCount() > 1) + GetDlgItem(IDC_BUTTON_KDCHOST_REMOVE)->EnableWindow(); + + GetDlgItem(IDC_BUTTON_KDCHOST_EDIT)->EnableWindow(); +} + +void CKrbRealmHostMaintenance::OnSetfocusListKdcRealm() +{ + GetDlgItem(IDC_BUTTON_ADMINSERVER)->EnableWindow(FALSE); + GetDlgItem(IDC_BUTTON_REMOVE_ADMINSERVER)->EnableWindow(FALSE); +} + +void CKrbRealmHostMaintenance::OnButtonAdminserver() +{ + // Install new admin.server in profile linklist + char theSection[REALM_SZ + 1]; + const char* Section[] = {"realms", theSection, ADMIN_SERVER, NULL}; + const char** section = Section; + + m_KDCHostList.SetFocus(); + INT index1 = m_KDCHostList.GetCurSel(); + INT index2 = m_KDCHostList.FindStringExact(-1, m_theAdminServerMarked); + + if (-1 != index2) + { + m_KDCHostList.DeleteString(index2); + if (LB_ERR == m_KDCHostList.InsertString(index2, m_theAdminServer)) + { + MessageBox("OnButtonAdminserver::Can't add to list!!!", + "Error, MB_OK"); + } + } + + CString makeAdmin; + m_KDCHostList.GetText(index1, makeAdmin); + m_KDCHostList.DeleteString(index1); + m_theAdminServer = makeAdmin; + makeAdmin += " "; + makeAdmin += ADMIN_SERVER; + m_theAdminServerMarked = makeAdmin; + + if (LB_ERR == m_KDCHostList.InsertString(index1, makeAdmin)) + { + MessageBox("OnButtonAdminserver::Can't add to list!!!", + "Error, MB_OK"); + } + + m_KDCHostList.SetCurSel(m_KDCHostList.FindStringExact(-1, makeAdmin)); //index2 -1); + GetDlgItem(IDC_BUTTON_ADMINSERVER)->EnableWindow(FALSE); + GetDlgItem(IDC_BUTTON_REMOVE_ADMINSERVER)->EnableWindow(); + + m_KDCRealmList.GetText(m_KDCRealmList.GetCurSel(), theSection); + + long retval = pprofile_clear_relation(CLeashApp::m_krbv5_profile, + section); + + if (retval && PROF_NO_RELATION != retval) + { + MessageBox("OnButtonAdminserver::There is an error, profile will not be saved!!!\ + \nIf this error persist, contact your administrator.", + "Error", MB_OK); + return; + } + + retval = pprofile_add_relation(CLeashApp::m_krbv5_profile, + section, m_theAdminServer); + + if (retval) + { // this might not be a good way to handle this type of error + MessageBox("OnButtonAdminserver::There is an error, profile will not be saved!!!\ + \nIf this error persist, contact your administrator.", + "Error", MB_OK); + return; + } + + SetModified(TRUE); +} + +void CKrbRealmHostMaintenance::OnButtonRemoveAdminserver() +{ + // Remove admin.server from profile linklist + char theSection[REALM_SZ + 1]; + const char* Section[] = {"realms", theSection, ADMIN_SERVER, NULL}; + const char** section = Section; + + m_KDCHostList.SetFocus(); + m_KDCRealmList.GetText(m_KDCRealmList.GetCurSel(), theSection); + + long retval = pprofile_clear_relation(CLeashApp::m_krbv5_profile, + section); + + if (retval) + { + MessageBox("OnButtonRemoveAdminserver::There is an error, profile will not be saved!!!\ + \nIf this error persist, contact your administrator.", + "Error", MB_OK); + return; + } + + INT index = m_KDCHostList.GetCurSel(); + m_KDCHostList.DeleteString(index); + + if (LB_ERR == m_KDCHostList.InsertString(index, m_theAdminServer)) + { + MessageBox("OnButtonRemoveAdminserver::Can't add to list!!!", + "Error, MB_OK"); + + + } + + m_theAdminServerMarked = m_theAdminServer; + m_KDCHostList.SetCurSel(m_KDCHostList.FindStringExact(-1, m_theAdminServer)); + GetDlgItem(IDC_BUTTON_ADMINSERVER)->EnableWindow(); + GetDlgItem(IDC_BUTTON_REMOVE_ADMINSERVER)->EnableWindow(FALSE); + + SetModified(TRUE); +} + + + +void CKrbRealmHostMaintenance::OnButtonRealmhostMaintHelp() +{ + MessageBox("No Help Available!", "Note", MB_OK); +} diff --git a/src/windows/leash/KrbRealmHostMaintenance.h b/src/windows/leash/KrbRealmHostMaintenance.h new file mode 100644 index 000000000..c894e22a0 --- /dev/null +++ b/src/windows/leash/KrbRealmHostMaintenance.h @@ -0,0 +1,102 @@ +// ************************************************************************************** +// File: KrbRealmHostMaintenance.h +// By: Arthur David Leather +// Created: 12/02/98 +// Copyright @1998 Massachusetts Institute of Technology - All rights reserved. +// Description: H file for KrbRealmHostMaintenance.cpp. Contains variables and functions +// for Kerberos Four and Five Properties +// +// History: +// +// MM/DD/YY Inits Description of Change +// 12/02/98 ADL Original +// ************************************************************************************** + + +#if !defined(AFX_KRBREALMNAMEMAINTENANCE_H__2FE711C3_8E9A_11D2_94C5_0000861B8A3C__INCLUDED_) +#define AFX_KRBREALMNAMEMAINTENANCE_H__2FE711C3_8E9A_11D2_94C5_0000861B8A3C__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + + +///////////////////////////////////////////////////////////////////////////// +// CKrbRealmHostMaintenance dialog + +#include "resource.h" +#include "CLeashDragListBox.h" + +#define MAXLINE 256 + +class CKrbRealmHostMaintenance : public CPropertyPage +{ +// Construction +private: + DECLARE_DYNCREATE(CKrbRealmHostMaintenance) + CHAR lineBuf[MAXLINE]; + CString m_theAdminServerMarked; + CString m_theAdminServer; + BOOL m_isRealmListBoxInFocus; + BOOL m_isStart; + BOOL m_initDnsKdcLookup; + BOOL m_newDnsKdcLookup; + + bool OnButtonKdchostAddInternal(); + + //void ResetDefaultRealmComboBox(); + +public: + //CKrbRealmHostMaintenance(CWnd* pParent = NULL); // standard constructor + CKrbRealmHostMaintenance(); + virtual ~CKrbRealmHostMaintenance(); + +// Dialog Data + //{{AFX_DATA(CKrbRealmHostMaintenance) + enum { IDD = IDD_KRB_REALMHOST_MAINT }; + CListBox m_KDCRealmList; + CLeashDragListBox m_KDCHostList; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CKrbRealmHostMaintenance) + public: + virtual BOOL PreTranslateMessage(MSG* pMsg); + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CKrbRealmHostMaintenance) + virtual BOOL OnInitDialog(); + virtual BOOL OnApply(); + virtual void OnCancel(); + afx_msg void OnButtonRealmHostAdd(); + afx_msg void OnButtonRealmHostEdit(); + afx_msg void OnButtonRealmHostRemove(); + afx_msg void OnSelchangeListKdcRealm(); + afx_msg void OnButtonAdminserver(); + afx_msg void OnSetfocusListKdcRealm(); + afx_msg void OnButtonKdchostAdd(); + afx_msg void OnButtonKdchostRemove(); + afx_msg void OnButtonRemoveAdminserver(); + afx_msg void OnSelchangeListKdcHost(); + afx_msg void OnButtonKdchostEdit(); + afx_msg void OnDblclkListKdcRealm(); + afx_msg void OnDblclkListKdcHost(); + afx_msg void OnButtonRealmhostMaintHelp(); + afx_msg void OnCheckDnsKdcLookup(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_KRBREALMNAMEMAINTENANCE_H__2FE711C3_8E9A_11D2_94C5_0000861B8A3C__INCLUDED_) diff --git a/src/windows/leash/Leash.cpp b/src/windows/leash/Leash.cpp new file mode 100644 index 000000000..eb2c11026 --- /dev/null +++ b/src/windows/leash/Leash.cpp @@ -0,0 +1,1618 @@ +//************************************************************************** +// File: Leash.cpp +// By: Arthur David Leather +// Created: 12/02/98 +// Copyright: 1998 Massachusetts Institute of Technology - All rights +// reserved. +// +// Description: CPP file for Leash.h. Contains variables and functions +// for Leash +// +// History: +// +// MM/DD/YY Inits Description of Change +// 12/02/98 ADL Original +//************************************************************************** + +#include "stdafx.h" +#include "Leash.h" + +#include "MainFrm.h" +#include "LeashDoc.h" +#include "LeashView.h" +#include "LeashAboutBox.h" + +#include "reminder.h" +#include "mitwhich.h" +#include +#include "lglobals.h" +#include +#include + +#include + +#ifndef NO_AFS +#include "afscompat.h" +#endif + +#include + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +extern "C" int VScheckVersion(HWND hWnd, HANDLE hThisInstance); + +TicketInfoWrapper ticketinfo; +#ifndef KRB5_TC_NOTICKET /* test for krb5 1.4 and thread safety */ +HANDLE m_tgsReqMutex = 0; +#endif + +HWND CLeashApp::m_hProgram = 0; +HINSTANCE CLeashApp::m_hLeashDLL = 0; +HINSTANCE CLeashApp::m_hKrb4DLL = 0; +HINSTANCE CLeashApp::m_hKrb5DLL = 0; +HINSTANCE CLeashApp::m_hKrb5ProfileDLL= 0; +HINSTANCE CLeashApp::m_hAfsDLL = 0; +HINSTANCE CLeashApp::m_hPsapi = 0; +HINSTANCE CLeashApp::m_hToolHelp32 = 0; +krb5_context CLeashApp::m_krbv5_context = 0; +profile_t CLeashApp::m_krbv5_profile = 0; +HINSTANCE CLeashApp::m_hKrbLSA = 0; + +///////////////////////////////////////////////////////////////////////////// +// CLeashApp + + +BEGIN_MESSAGE_MAP(CLeashApp, CWinApp) + //{{AFX_MSG_MAP(CLeashApp) + //}}AFX_MSG_MAP + // Standard file based document commands + ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew) + ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen) +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CLeashApp construction +CLeashApp::CLeashApp() +{ + m_krbv5_context = NULL; + m_krbv5_profile = NULL; + // TODO: add construction code here, + // Place all significant initialization in InitInstance + + // Memory may not be initialized to zeros (in debug) + memset(&ticketinfo, 0, sizeof(ticketinfo)); + + ticketinfo.lockObj = CreateMutex(NULL, FALSE, NULL); +#ifndef KRB5_TC_NOTICKET + m_tgsReqMutex = CreateMutex(NULL, FALSE, NULL); +#endif + +#ifdef USE_HTMLHELP +#if _MSC_VER >= 1300 + EnableHtmlHelp(); +#endif +#endif +} + +CLeashApp::~CLeashApp() +{ + if ( m_krbv5_context ) { + pkrb5_free_context(m_krbv5_context); + m_krbv5_context = NULL; + } + + if ( m_krbv5_profile ) { + pprofile_release(m_krbv5_profile); + m_krbv5_profile = NULL; + } + +#ifdef COMMENT + /* Do not free the locking objects. Doing so causes an invalid handle access */ + CloseHandle(ticketinfo.lockObj); +#ifndef KRB5_TC_NOTICKET + CloseHandle(m_tgsReqMutex); +#endif +#endif + AfxFreeLibrary(m_hLeashDLL); + AfxFreeLibrary(m_hKrb4DLL); + AfxFreeLibrary(m_hKrb5DLL); + AfxFreeLibrary(m_hKrb5ProfileDLL); + AfxFreeLibrary(m_hAfsDLL); + AfxFreeLibrary(m_hPsapi); + AfxFreeLibrary(m_hToolHelp32); + AfxFreeLibrary(m_hKrbLSA); +} + +///////////////////////////////////////////////////////////////////////////// +// The one and only CLeashApp object + +CLeashApp theApp; + +///////////////////////////////////////////////////////////////////////////// +// CLeashApp initialization + +void CLeashApp::ParseParam (LPCTSTR lpszParam,BOOL bFlag,BOOL bLast) +{ + //CCommandLineInfo::ParseParam(lpszParam, bFlag, bLast) ; +} + +extern "C" { + LRESULT WINAPI LeashWindowProc( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) + { + switch ( Msg ) { + case WM_SYSCOMMAND: + if (SC_CLOSE == (wParam & 0xfff0)) { + wParam = (wParam & ~0xfff0) | SC_MINIMIZE; + } + break; + } + return ::DefWindowProc(hWnd, Msg, wParam, lParam); + } +} + +BOOL CLeashApp::InitInstance() +{ + // NOTE: Not used at this time + /// Set LEASH_DLL to the path where the Leash.exe is + char modulePath[MAX_PATH]; + DWORD result = GetModuleFileName(AfxGetInstanceHandle(), modulePath, MAX_PATH); + ASSERT(result); + + char* pPath = modulePath + strlen(modulePath) - 1; + while (*pPath != '\\') + { + *pPath = 0; + pPath--; + } + strcat(modulePath, LEASH_HELP_FILE); + m_helpFile = modulePath; + + ///strcat(dllFile, LEASH_DLL); + ///m_leashDLL = dllFile; + + BOOL autoInit = FALSE; + HWND hMsg = GetForegroundWindow(); + if (!InitDLLs()) + return FALSE; //exit program, can't load LEASHDLL + + // Check for args (switches) + LPCTSTR exeFile = __targv[0]; + LPCTSTR optionParam = __targv[1]; + + if (optionParam) + { + if (*optionParam == '-' || *optionParam == '/') + { + if (0 == stricmp(optionParam+1, "kinit") || + 0 == stricmp(optionParam+1, "i")) + { + LSH_DLGINFO_EX ldi; + char username[64]=""; + char realm[192]=""; + int i=0, j=0; + TicketList* ticketList = NULL; + if (WaitForSingleObject( ticketinfo.lockObj, INFINITE ) != WAIT_OBJECT_0) + throw("Unable to lock ticketinfo"); + + pLeashKRB5GetTickets(&ticketinfo.Krb5, &ticketList, + &CLeashApp::m_krbv5_context); + pLeashFreeTicketList(&ticketList); + pLeashKRB4GetTickets(&ticketinfo.Krb4, &ticketList); + pLeashFreeTicketList(&ticketList); + + if ( ticketinfo.Krb5.btickets && ticketinfo.Krb5.principal[0] ) { + for (; ticketinfo.Krb5.principal[i] && ticketinfo.Krb5.principal[i] != '@'; i++) + { + username[i] = ticketinfo.Krb5.principal[i]; + } + username[i] = '\0'; + if (ticketinfo.Krb5.principal[i]) { + for (i++ ; ticketinfo.Krb5.principal[i] ; i++, j++) + { + realm[j] = ticketinfo.Krb5.principal[i]; + } + } + realm[j] = '\0'; + } else if ( ticketinfo.Krb4.btickets && ticketinfo.Krb4.principal[0] ) { + for (; ticketinfo.Krb4.principal[i] && ticketinfo.Krb4.principal[i] != '@'; i++) + { + username[i] = ticketinfo.Krb4.principal[i]; + } + username[i] = '\0'; + if (ticketinfo.Krb4.principal[i]) { + for (i++ ; ticketinfo.Krb4.principal[i] ; i++, j++) + { + realm[j] = ticketinfo.Krb4.principal[i]; + } + } + realm[j] = '\0'; + } + ReleaseMutex(ticketinfo.lockObj); + + ldi.size = sizeof(ldi); + ldi.dlgtype = DLGTYPE_PASSWD; + ldi.title = "Initialize Ticket"; + ldi.username = username; + ldi.realm = realm; + ldi.dlgtype = DLGTYPE_PASSWD; + ldi.use_defaults = 1; + + if (!pLeash_kinit_dlg_ex(hMsg, &ldi)) + { + MessageBox(hMsg, "There was an error getting tickets!", + "Error", MB_OK); + return FALSE; + } + return TRUE; + } + else if (0 == stricmp(optionParam+1, "ms2mit") || + 0 == stricmp(optionParam+1, "import") || + 0 == stricmp(optionParam+1, "m")) + { + if (!pLeash_importable()) { + MessageBox(hMsg, + "The Microsoft Logon Session does not support importing Ticket Getting Tickets!", + "Error", MB_OK); + return FALSE; + } + + if (!pLeash_import()) + { + MessageBox(hMsg, + "There was an error importing tickets from the Microsoft Logon Session!", + "Error", MB_OK); + return FALSE; + } + return TRUE; + } + else if (0 == stricmp(optionParam+1, "destroy") || + 0 == stricmp(optionParam+1, "d")) + { + if (pLeash_kdestroy()) + { + MessageBox(hMsg, + "There was an error destroying tickets!", + "Error", MB_OK); + return FALSE; + } + return TRUE; + } + else if (0 == stricmp(optionParam+1, "renew") || + 0 == stricmp(optionParam+1, "r")) + { + if (!pLeash_renew()) + { + MessageBox(hMsg, + "There was an error renewing tickets!", + "Error", MB_OK); + return FALSE; + } + return TRUE; + } + else if (0 == stricmp(optionParam+1, "autoinit") || + 0 == stricmp(optionParam+1, "a")) + { + autoInit = TRUE; + } + else + { + MessageBox(hMsg, + "'-kinit' or '-i' to perform ticket initialization (and exit)\n" + "'-renew' or '-r' to perform ticket renewal (and exit)\n" + "'-destroy' or '-d' to perform ticket destruction (and exit)\n" + "'-autoinit' or '-a' to perform automatic ticket initialization\n" + "'-ms2mit' or '-import' or '-m' to perform ticket importation (and exit)", + "Leash Error", MB_OK); + return FALSE; + } + } + else + { + MessageBox(hMsg, + "'-kinit' or '-i' to perform ticket initialization (and exit)\n" + "'-renew' or '-r' to perform ticket renewal (and exit)\n" + "'-destroy' or '-d' to perform ticket destruction (and exit)\n" + "'-autoinit' or '-a' to perform automatic ticket initialization\n" + "'-ms2mit' or '-import' or '-m' to perform ticket importation (and exit)", + "Leash Error", MB_OK); + return FALSE; + } + } + + // Insure only one instance of Leash + if (!FirstInstance()) + return FALSE; + + //register our unique wnd class name to find it later + WNDCLASS wndcls; + memset(&wndcls, 0, sizeof(WNDCLASS)); + wndcls.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW; + wndcls.lpfnWndProc = ::LeashWindowProc; + wndcls.hInstance = AfxGetInstanceHandle(); + wndcls.hIcon = LoadIcon(IDR_MAINFRAME); + wndcls.hCursor = LoadCursor(IDC_ARROW); + wndcls.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + wndcls.lpszMenuName = NULL; + //now the wnd class name to find it + wndcls.lpszClassName = _T("LEASH.0WNDCLASS"); + + //register the new class + if(!AfxRegisterClass(&wndcls)) + { + TRACE("Class registration failed\n"); + return FALSE; + } + + AfxEnableControlContainer(); + + // Standard initialization + // If you are not using these features and wish to reduce the size + // of your final executable, you should remove from the following + // the specific initialization routines you do not need. + +#if _MSC_VER < 1300 +#ifdef _AFXDLL + Enable3dControls(); // Call this when using MFC in a shared DLL +#else + Enable3dControlsStatic(); // Call this when linking to MFC statically +#endif +#endif + + // Registry key under which our settings are stored. + if (m_pszAppName) + free((void*)m_pszAppName); + m_pszAppName = _tcsdup("Leash32"); + SetRegistryKey(_T("MIT")); + + LoadStdProfileSettings(); // Load standard INI file options (including MRU) + + // Register the application's document templates. Document templates + // serve as the connection between documents, frame windows and views. + + CSingleDocTemplate* pDocTemplate; + pDocTemplate = new CSingleDocTemplate( + IDR_MAINFRAME, + RUNTIME_CLASS(LeashDoc), + RUNTIME_CLASS(CMainFrame), // main SDI frame window + RUNTIME_CLASS(CLeashView)); + AddDocTemplate(pDocTemplate); + + // Parse command line for standard shell commands, DDE, file open + CCommandLineInfo cmdInfo; + ParseCommandLine(cmdInfo); + + // Dispatch commands specified on the command line + if (!ProcessShellCommand(cmdInfo)) + return FALSE; + + // Check to see if there are any tickets in the cache + // If not and the Windows Logon Session is Kerberos authenticated attempt an import + { + TicketList* ticketList = NULL; + if (WaitForSingleObject( ticketinfo.lockObj, INFINITE ) != WAIT_OBJECT_0) + throw("Unable to lock ticketinfo"); + pLeashKRB5GetTickets(&ticketinfo.Krb5, &ticketList, &CLeashApp::m_krbv5_context); + pLeashFreeTicketList(&ticketList); + pLeashKRB4GetTickets(&ticketinfo.Krb4, &ticketList); + pLeashFreeTicketList(&ticketList); + BOOL b_autoinit = !ticketinfo.Krb4.btickets && !ticketinfo.Krb5.btickets; + ReleaseMutex(ticketinfo.lockObj); + + DWORD dwMsLsaImport = pLeash_get_default_mslsa_import(); + + if ( b_autoinit && dwMsLsaImport && pLeash_importable() ) { + // We have the option of importing tickets from the MSLSA + // but should we? Do the tickets in the MSLSA cache belong + // to the default realm used by Leash? If so, import. + int import = 0; + + if ( dwMsLsaImport == 1 ) { /* always import */ + import = 1; + } else if ( dwMsLsaImport == 2 ) { /* import when realms match */ + krb5_error_code code; + krb5_ccache mslsa_ccache=0; + krb5_principal princ = 0; + char ms_realm[128] = "", *def_realm = 0, *r; + int i; + + if (code = pkrb5_cc_resolve(CLeashApp::m_krbv5_context, "MSLSA:", &mslsa_ccache)) + goto cleanup; + + if (code = pkrb5_cc_get_principal(CLeashApp::m_krbv5_context, mslsa_ccache, &princ)) + goto cleanup; + + for ( r=ms_realm, i=0; ilength; r++, i++ ) { + *r = krb5_princ_realm(CLeashApp::m_krb5v5_context, princ)->data[i]; + } + *r = '\0'; + + if (code = pkrb5_get_default_realm(CLeashApp::m_krbv5_context, &def_realm)) + goto cleanup; + + import = !strcmp(def_realm, ms_realm); + + cleanup: + if (def_realm) + pkrb5_free_default_realm(CLeashApp::m_krbv5_context, def_realm); + + if (princ) + pkrb5_free_principal(CLeashApp::m_krbv5_context, princ); + + if (mslsa_ccache) + pkrb5_cc_close(CLeashApp::m_krbv5_context, mslsa_ccache); + } + + if (import && pLeash_import()) { + CLeashView::m_importedTickets = 1; + ::PostMessage(m_pMainWnd->m_hWnd, WM_COMMAND, ID_UPDATE_DISPLAY, 0); + b_autoinit = FALSE; + } + } + + if (autoInit) { + if ( b_autoinit ) + AfxBeginThread(InitWorker, m_pMainWnd->m_hWnd); + + IpAddrChangeMonitorInit(m_pMainWnd->m_hWnd); + } + } + + VScheckVersion(m_pMainWnd->m_hWnd, AfxGetInstanceHandle()); + + // The one and only window has been initialized, so show and update it. + m_pMainWnd->SetWindowText("Leash"); + m_pMainWnd->UpdateWindow(); + m_pMainWnd->ShowWindow(SW_SHOW); + m_pMainWnd->SetForegroundWindow(); + + ValidateConfigFiles(); + + return TRUE; +} + + +///////////////////////////////////////////////////////////////////////////// +// CLeashApp commands + +// leash functions +DECL_FUNC_PTR(not_an_API_LeashKRB4GetTickets); +DECL_FUNC_PTR(not_an_API_LeashKRB5GetTickets); +DECL_FUNC_PTR(not_an_API_LeashAFSGetToken); +DECL_FUNC_PTR(not_an_API_LeashFreeTicketList); +DECL_FUNC_PTR(not_an_API_LeashGetTimeServerName); +DECL_FUNC_PTR(Leash_kdestroy); +DECL_FUNC_PTR(Leash_changepwd_dlg); +DECL_FUNC_PTR(Leash_changepwd_dlg_ex); +DECL_FUNC_PTR(Leash_kinit_dlg); +DECL_FUNC_PTR(Leash_kinit_dlg_ex); +DECL_FUNC_PTR(Leash_timesync); +DECL_FUNC_PTR(Leash_get_default_lifetime); +DECL_FUNC_PTR(Leash_set_default_lifetime); +DECL_FUNC_PTR(Leash_get_default_forwardable); +DECL_FUNC_PTR(Leash_set_default_forwardable); +DECL_FUNC_PTR(Leash_get_default_renew_till); +DECL_FUNC_PTR(Leash_set_default_renew_till); +DECL_FUNC_PTR(Leash_get_default_noaddresses); +DECL_FUNC_PTR(Leash_set_default_noaddresses); +DECL_FUNC_PTR(Leash_get_default_proxiable); +DECL_FUNC_PTR(Leash_set_default_proxiable); +DECL_FUNC_PTR(Leash_get_default_publicip); +DECL_FUNC_PTR(Leash_set_default_publicip); +DECL_FUNC_PTR(Leash_get_default_use_krb4); +DECL_FUNC_PTR(Leash_set_default_use_krb4); +DECL_FUNC_PTR(Leash_get_default_life_min); +DECL_FUNC_PTR(Leash_set_default_life_min); +DECL_FUNC_PTR(Leash_get_default_life_max); +DECL_FUNC_PTR(Leash_set_default_life_max); +DECL_FUNC_PTR(Leash_get_default_renew_min); +DECL_FUNC_PTR(Leash_set_default_renew_min); +DECL_FUNC_PTR(Leash_get_default_renew_max); +DECL_FUNC_PTR(Leash_set_default_renew_max); +DECL_FUNC_PTR(Leash_get_default_renewable); +DECL_FUNC_PTR(Leash_set_default_renewable); +DECL_FUNC_PTR(Leash_get_lock_file_locations); +DECL_FUNC_PTR(Leash_set_lock_file_locations); +DECL_FUNC_PTR(Leash_get_default_uppercaserealm); +DECL_FUNC_PTR(Leash_set_default_uppercaserealm); +DECL_FUNC_PTR(Leash_get_default_mslsa_import); +DECL_FUNC_PTR(Leash_set_default_mslsa_import); +DECL_FUNC_PTR(Leash_get_default_preserve_kinit_settings); +DECL_FUNC_PTR(Leash_set_default_preserve_kinit_settings); +DECL_FUNC_PTR(Leash_import); +DECL_FUNC_PTR(Leash_importable); +DECL_FUNC_PTR(Leash_renew); +DECL_FUNC_PTR(Leash_reset_defaults); + +FUNC_INFO leash_fi[] = { + MAKE_FUNC_INFO(not_an_API_LeashKRB4GetTickets), + MAKE_FUNC_INFO(not_an_API_LeashKRB5GetTickets), + MAKE_FUNC_INFO(not_an_API_LeashAFSGetToken), + MAKE_FUNC_INFO(not_an_API_LeashFreeTicketList), + MAKE_FUNC_INFO(not_an_API_LeashGetTimeServerName), + MAKE_FUNC_INFO(Leash_kdestroy), + MAKE_FUNC_INFO(Leash_changepwd_dlg), + MAKE_FUNC_INFO(Leash_changepwd_dlg_ex), + MAKE_FUNC_INFO(Leash_kinit_dlg), + MAKE_FUNC_INFO(Leash_kinit_dlg_ex), + MAKE_FUNC_INFO(Leash_timesync), + MAKE_FUNC_INFO(Leash_get_default_lifetime), + MAKE_FUNC_INFO(Leash_set_default_lifetime), + MAKE_FUNC_INFO(Leash_get_default_renew_till), + MAKE_FUNC_INFO(Leash_set_default_renew_till), + MAKE_FUNC_INFO(Leash_get_default_forwardable), + MAKE_FUNC_INFO(Leash_set_default_forwardable), + MAKE_FUNC_INFO(Leash_get_default_noaddresses), + MAKE_FUNC_INFO(Leash_set_default_noaddresses), + MAKE_FUNC_INFO(Leash_get_default_proxiable), + MAKE_FUNC_INFO(Leash_set_default_proxiable), + MAKE_FUNC_INFO(Leash_get_default_publicip), + MAKE_FUNC_INFO(Leash_set_default_publicip), + MAKE_FUNC_INFO(Leash_get_default_use_krb4), + MAKE_FUNC_INFO(Leash_set_default_use_krb4), + MAKE_FUNC_INFO(Leash_get_default_life_min), + MAKE_FUNC_INFO(Leash_set_default_life_min), + MAKE_FUNC_INFO(Leash_get_default_life_max), + MAKE_FUNC_INFO(Leash_set_default_life_max), + MAKE_FUNC_INFO(Leash_get_default_renew_min), + MAKE_FUNC_INFO(Leash_set_default_renew_min), + MAKE_FUNC_INFO(Leash_get_default_renew_max), + MAKE_FUNC_INFO(Leash_set_default_renew_max), + MAKE_FUNC_INFO(Leash_get_default_renewable), + MAKE_FUNC_INFO(Leash_set_default_renewable), + MAKE_FUNC_INFO(Leash_get_lock_file_locations), + MAKE_FUNC_INFO(Leash_set_lock_file_locations), + MAKE_FUNC_INFO(Leash_get_default_uppercaserealm), + MAKE_FUNC_INFO(Leash_set_default_uppercaserealm), + MAKE_FUNC_INFO(Leash_get_default_mslsa_import), + MAKE_FUNC_INFO(Leash_set_default_mslsa_import), + MAKE_FUNC_INFO(Leash_get_default_preserve_kinit_settings), + MAKE_FUNC_INFO(Leash_set_default_preserve_kinit_settings), + MAKE_FUNC_INFO(Leash_import), + MAKE_FUNC_INFO(Leash_importable), + MAKE_FUNC_INFO(Leash_renew), + MAKE_FUNC_INFO(Leash_reset_defaults), + END_FUNC_INFO +}; + +// krb4 functions +DECL_FUNC_PTR(set_krb_debug); +DECL_FUNC_PTR(set_krb_ap_req_debug); +DECL_FUNC_PTR(krb_get_krbconf2); +DECL_FUNC_PTR(krb_get_krbrealm2); +DECL_FUNC_PTR(tkt_string); +DECL_FUNC_PTR(krb_set_tkt_string); +DECL_FUNC_PTR(krb_realmofhost); +DECL_FUNC_PTR(krb_get_lrealm); +DECL_FUNC_PTR(krb_get_krbhst); +DECL_FUNC_PTR(tf_init); +DECL_FUNC_PTR(tf_close); +DECL_FUNC_PTR(krb_get_tf_realm); + +FUNC_INFO krb4_fi[] = { + MAKE_FUNC_INFO(set_krb_debug), + MAKE_FUNC_INFO(set_krb_ap_req_debug), + MAKE_FUNC_INFO(krb_get_krbconf2), + MAKE_FUNC_INFO(krb_get_krbrealm2), + MAKE_FUNC_INFO(tkt_string), + MAKE_FUNC_INFO(krb_set_tkt_string), + MAKE_FUNC_INFO(krb_realmofhost), + MAKE_FUNC_INFO(krb_get_lrealm), + MAKE_FUNC_INFO(krb_get_krbhst), + MAKE_FUNC_INFO(tf_init), + MAKE_FUNC_INFO(tf_close), + MAKE_FUNC_INFO(krb_get_tf_realm), + END_FUNC_INFO +}; + + +// psapi functions +DECL_FUNC_PTR(GetModuleFileNameExA); +DECL_FUNC_PTR(EnumProcessModules); + +FUNC_INFO psapi_fi[] = { + MAKE_FUNC_INFO(GetModuleFileNameExA), + MAKE_FUNC_INFO(EnumProcessModules), + END_FUNC_INFO +}; + +// toolhelp functions +DECL_FUNC_PTR(CreateToolhelp32Snapshot); +DECL_FUNC_PTR(Module32First); +DECL_FUNC_PTR(Module32Next); + +FUNC_INFO toolhelp_fi[] = { + MAKE_FUNC_INFO(CreateToolhelp32Snapshot), + MAKE_FUNC_INFO(Module32First), + MAKE_FUNC_INFO(Module32Next), + END_FUNC_INFO +}; + +// krb5 functions +DECL_FUNC_PTR(krb5_cc_default_name); +DECL_FUNC_PTR(krb5_cc_set_default_name); +DECL_FUNC_PTR(krb5_get_default_config_files); +DECL_FUNC_PTR(krb5_free_config_files); +DECL_FUNC_PTR(krb5_free_context); +DECL_FUNC_PTR(krb5_get_default_realm); +DECL_FUNC_PTR(krb5_free_default_realm); +DECL_FUNC_PTR(krb5_init_context); +DECL_FUNC_PTR(krb5_cc_default); +DECL_FUNC_PTR(krb5_parse_name); +DECL_FUNC_PTR(krb5_free_principal); +DECL_FUNC_PTR(krb5_cc_close); +DECL_FUNC_PTR(krb5_cc_get_principal); +DECL_FUNC_PTR(krb5_build_principal); +DECL_FUNC_PTR(krb5_c_random_make_octets); +DECL_FUNC_PTR(krb5_get_init_creds_password); +DECL_FUNC_PTR(krb5_free_cred_contents); +DECL_FUNC_PTR(krb5_cc_resolve); +DECL_FUNC_PTR(krb5_unparse_name); +DECL_FUNC_PTR(krb5_free_unparsed_name); + +FUNC_INFO krb5_fi[] = { + MAKE_FUNC_INFO(krb5_cc_default_name), + MAKE_FUNC_INFO(krb5_cc_set_default_name), + MAKE_FUNC_INFO(krb5_get_default_config_files), + MAKE_FUNC_INFO(krb5_free_config_files), + MAKE_FUNC_INFO(krb5_free_context), + MAKE_FUNC_INFO(krb5_get_default_realm), + MAKE_FUNC_INFO(krb5_free_default_realm), + MAKE_FUNC_INFO(krb5_init_context), + MAKE_FUNC_INFO(krb5_cc_default), + MAKE_FUNC_INFO(krb5_parse_name), + MAKE_FUNC_INFO(krb5_free_principal), + MAKE_FUNC_INFO(krb5_cc_close), + MAKE_FUNC_INFO(krb5_cc_get_principal), + MAKE_FUNC_INFO(krb5_build_principal), + MAKE_FUNC_INFO(krb5_c_random_make_octets), + MAKE_FUNC_INFO(krb5_get_init_creds_password), + MAKE_FUNC_INFO(krb5_free_cred_contents), + MAKE_FUNC_INFO(krb5_cc_resolve), + MAKE_FUNC_INFO(krb5_unparse_name), + MAKE_FUNC_INFO(krb5_free_unparsed_name), + END_FUNC_INFO +}; + +// profile functions +DECL_FUNC_PTR(profile_release); +DECL_FUNC_PTR(profile_init); +DECL_FUNC_PTR(profile_flush); +DECL_FUNC_PTR(profile_rename_section); +DECL_FUNC_PTR(profile_update_relation); +DECL_FUNC_PTR(profile_clear_relation); +DECL_FUNC_PTR(profile_add_relation); +DECL_FUNC_PTR(profile_get_relation_names); +DECL_FUNC_PTR(profile_get_subsection_names); +DECL_FUNC_PTR(profile_get_values); +DECL_FUNC_PTR(profile_free_list); +DECL_FUNC_PTR(profile_abandon); +DECL_FUNC_PTR(profile_get_string); +DECL_FUNC_PTR(profile_release_string); + +FUNC_INFO profile_fi[] = { + MAKE_FUNC_INFO(profile_release), + MAKE_FUNC_INFO(profile_init), + MAKE_FUNC_INFO(profile_flush), + MAKE_FUNC_INFO(profile_rename_section), + MAKE_FUNC_INFO(profile_update_relation), + MAKE_FUNC_INFO(profile_clear_relation), + MAKE_FUNC_INFO(profile_add_relation), + MAKE_FUNC_INFO(profile_get_relation_names), + MAKE_FUNC_INFO(profile_get_subsection_names), + MAKE_FUNC_INFO(profile_get_values), + MAKE_FUNC_INFO(profile_free_list), + MAKE_FUNC_INFO(profile_abandon), + MAKE_FUNC_INFO(profile_get_string), + MAKE_FUNC_INFO(profile_release_string), + END_FUNC_INFO +}; + +// Tries to load the .DLL files. If it works, we get some functions from them +// and return a TRUE. If it doesn't work, we return a FALSE. +BOOL CLeashApp::InitDLLs() +{ + m_hLeashDLL = AfxLoadLibrary(LEASHDLL); + m_hKrb4DLL = AfxLoadLibrary(KERB4DLL); + m_hKrb5DLL = AfxLoadLibrary(KERB5DLL); + m_hKrb5ProfileDLL = AfxLoadLibrary(KERB5_PPROFILE_DLL); + +#ifndef NO_AFS + afscompat_init(); + m_hAfsDLL = AfxLoadLibrary(AFSAuthentDLL()); +#endif + +#define PSAPIDLL "psapi.dll" +#define TOOLHELPDLL "kernel32.dll" + + m_hPsapi = AfxLoadLibrary(PSAPIDLL); + m_hToolHelp32 = AfxLoadLibrary(TOOLHELPDLL); + + HWND hwnd = GetForegroundWindow(); + if (!m_hLeashDLL) + { + // We couldn't load the m_hLeashDLL. + m_msgError = "Couldn't load the Leash DLL or one of its dependents."; + MessageBox(hwnd, m_msgError, "Error", MB_OK); + return FALSE; + } + + if (!LoadFuncs(LEASHDLL, leash_fi, 0, 0, 1, 0, 0)) + { + MessageBox(hwnd, + "Functions within the Leash DLL didn't load properly!", + "Error", MB_OK); + return FALSE; + } + + if (m_hKrb4DLL) + { + if (!LoadFuncs(KERB4DLL, krb4_fi, 0, 0, 1, 0, 0)) + { + MessageBox(hwnd, + "Unexpected error while loading " KERB4DLL ".\n" + "Kerberos 4 functionality will be disabled.\n", + "Error", MB_OK); + } + } + + if (m_hKrb5DLL) + { + if (!LoadFuncs(KERB5DLL, krb5_fi, 0, 0, 1, 0, 0)) + { + MessageBox(hwnd, + "Unexpected error while loading " KERB5DLL ".\n" + "Kerberos 5 functionality will be disabled.\n", + "Error", MB_OK); + AfxFreeLibrary(m_hKrb5DLL); + m_hKrb5DLL = 0; + } + else if (!m_hKrb5ProfileDLL || + !LoadFuncs(KERB5_PPROFILE_DLL, profile_fi, 0, 0, 1, 0, 0)) + { + MessageBox(hwnd, + "Unexpected error while loading "KERB5_PPROFILE_DLL".\n" + "Kerberos 5 functionality will be disabled.\n", + "Error", MB_OK); + AfxFreeLibrary(m_hKrb5ProfileDLL); + m_hKrb5ProfileDLL = 0; + // Use m_hKrb5DLL to undo LoadLibrary in loadfuncs... + UnloadFuncs(krb5_fi, m_hKrb5DLL); + AfxFreeLibrary(m_hKrb5DLL); + m_hKrb5DLL = 0; + } + + } + + OSVERSIONINFO osvi; + memset(&osvi, 0, sizeof(OSVERSIONINFO)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&osvi); + + // XXX: We should really use feature testing, first + // checking for CreateToolhelp32Snapshot. If that's + // not around, we try the psapi stuff. + // + // Only load LSA functions if on NT/2000/XP + if(osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) + { + // Windows 9x + AfxFreeLibrary(m_hPsapi); + m_hPsapi = NULL; + if (!m_hToolHelp32 || + !LoadFuncs(TOOLHELPDLL, toolhelp_fi, 0, 0, 1, 0, 0)) + { + MessageBox(hwnd, "Could not load " TOOLHELPDLL "!", "Error", + MB_OK); + return FALSE; + } + } + else if(osvi.dwPlatformId == VER_PLATFORM_WIN32_NT) + { + // Windows NT + AfxFreeLibrary(m_hToolHelp32); + m_hToolHelp32 = NULL; + if (!m_hPsapi || + !LoadFuncs(PSAPIDLL, psapi_fi, 0, 0, 1, 0, 0)) + { + MessageBox(hwnd, "Could not load " PSAPIDLL "!", "Error", MB_OK); + return FALSE; + } + + m_hKrbLSA = AfxLoadLibrary(SECUR32DLL); + } + else + { + MessageBox(hwnd, + "Unrecognized Operating System!", + "Error", MB_OK); + return FALSE; + } + + return TRUE; +} + + +BOOL CLeashApp::FirstInstance() +{ + CWnd* pWndprev; + CWnd* pWndchild; + + //find if it exists + pWndprev = CWnd::FindWindow(_T("LEASH.0WNDCLASS"), NULL); + if (pWndprev) + { + //if it has popups + pWndchild = pWndprev->GetLastActivePopup(); + //if iconic restore + if (pWndprev->IsIconic()) + pWndprev->ShowWindow(SW_RESTORE); + + //bring the wnd to foreground + pWndchild->SetForegroundWindow(); + + return FALSE; + } + //we could not find prev instance + else + return TRUE; +} + +void +CLeashApp::ValidateConfigFiles() +{ + CStdioFile krbCon; + char confname[257]; + char realm[256]=""; + + CWinApp * pApp = AfxGetApp(); + if (pApp) + if (!pApp->GetProfileInt("Settings", "CreateMissingConfig", FALSE_FLAG)) + return; + + if ( m_hKrb5DLL ) { + int krb_con_open = 0; + + // Create the empty KRB5.INI file + if (!GetProfileFile(confname,sizeof(confname))) { + const char *filenames[2]; + filenames[0] = confname; + filenames[1] = NULL; + long retval = pprofile_init(filenames, &m_krbv5_profile); + if (!retval) + return; + else if (retval == ENOENT) { + FILE * f = fopen(confname,"w"); + if (f != NULL) { + fclose(f); + retval = pprofile_init(filenames, &m_krbv5_profile); + } + } + + + if ( !GetKrb4ConFile(confname,sizeof(confname)) ) { + if (!krbCon.Open(confname, CFile::modeNoTruncate | CFile::modeRead)) + { + if (krbCon.Open(confname, CFile::modeCreate | CFile::modeWrite)) + { + krb_con_open = 1; + } + } + } + + const char* lookupKdc[] = {"libdefaults", "dns_lookup_kdc", NULL}; + const char* lookupRealm[] = {"libdefaults", "dns_lookup_realm", NULL}; + const char* defRealm[] = {"libdefaults", "default_realm", NULL}; + const char* noAddresses[] = {"libdefaults", "noaddresses", NULL}; + + // activate DNS KDC Lookups + const char** names = lookupKdc; + retval = pprofile_add_relation(m_krbv5_profile, + names, + "true"); + + // activate No Addresses + names = noAddresses; + retval = pprofile_add_relation(m_krbv5_profile, + names, + "true"); + + // Get Windows 2000/XP/2003 Kerberos config + if ( m_hKrbLSA && m_hKrb5DLL ) + { + char domain[256]=""; + HKEY hk=0; + DWORD dwType, dwSize, dwIndex; + + if ( !RegOpenKeyEx(HKEY_CURRENT_USER, + "Volatile Environment", 0, + KEY_READ, &hk) ) + { + dwSize = sizeof(domain); + RegQueryValueEx(hk, "USERDNSDOMAIN", 0, 0, (LPBYTE)domain, &dwSize); + RegCloseKey(hk); + } + else if (!RegOpenKeyEx(HKEY_LOCAL_MACHINE, + "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", + 0, KEY_READ, &hk)) + { + + dwSize = sizeof(domain); + RegQueryValueEx( hk, "DefaultDomainName", + NULL, &dwType, (unsigned char *)&domain, &dwSize); + RegCloseKey(hk); + } + + char realmkey[256]="SYSTEM\\CurrentControlSet\\Control\\Lsa\\Kerberos\\Domains\\"; + int keylen = strlen(realmkey)-1; + + if ( domain[0] ) { + strncpy(realm,domain,256); + realm[255] = '\0'; + if ( krb_con_open ) { + krbCon.WriteString(realm); + krbCon.WriteString("\n"); + } + strncat(realmkey,domain,256-strlen(realmkey)); + realmkey[255] = '\0'; + } + + if ( domain[0] && + !RegOpenKeyEx(HKEY_LOCAL_MACHINE, + realmkey, + 0, + KEY_READ, + &hk) + ) + { + RegCloseKey(hk); + + realmkey[keylen] = '\0'; + RegOpenKeyEx(HKEY_LOCAL_MACHINE, + realmkey, + 0, + KEY_READ|KEY_ENUMERATE_SUB_KEYS, + &hk); + + dwIndex = 0; + unsigned char subkey[256]; + FILETIME ft; + dwSize = 256; + while ( ERROR_SUCCESS == RegEnumKeyEx(hk,dwIndex++, + (char *)subkey, + &dwSize, + 0, + 0, + 0, + &ft) ) + { + HKEY hksub; + + if ( !RegOpenKeyEx(hk, + (char *)subkey, + 0, + KEY_READ, + &hksub) ) + { + unsigned char * lpszValue = NULL, *p; + dwSize = 0; + dwType = 0; + RegQueryValueEx( hksub, "KdcNames", + NULL, &dwType, lpszValue, &dwSize); + if ( dwSize > 0 ) { + lpszValue = (unsigned char *)malloc(dwSize+1); + dwSize += 1; + RegQueryValueEx( hksub, "KdcNames", + NULL, &dwType, lpszValue, &dwSize); + + p = lpszValue; + while ( *p ) { + const char* realmKdc[] = {"realms", (const char *)subkey, "kdc", NULL}; + names = realmKdc; + retval = pprofile_add_relation(m_krbv5_profile, + names, + (const char *)p); + + if ( krb_con_open ) { + krbCon.WriteString((const char *)subkey); + krbCon.WriteString("\t"); + krbCon.WriteString((const char *)p); + krbCon.WriteString("\n"); + } + + p += strlen((char*)p) + 1; + } + free(lpszValue); + } + RegCloseKey(hksub); + } + } + RegCloseKey(hk); + } + } else { + // activate DNS Realm Lookups (temporarily) + names = lookupRealm; + retval = pprofile_add_relation(m_krbv5_profile, + names, + "true"); + } + + // Save to Kerberos Five config. file "Krb5.ini" + retval = pprofile_flush(m_krbv5_profile); + + + // Use DNS to retrieve the realm (if possible) + if (!realm[0]) { + krb5_context ctx = 0; + krb5_principal me = 0; + krb5_error_code code = 0; + + code = pkrb5_init_context(&ctx); + if (code) goto no_k5_realm; + + code = pkrb5_parse_name(ctx, "foo", &me); + if (code) goto no_k5_realm; + + if ( krb5_princ_realm(ctx,me)->length < sizeof(realm) - 1) { + memcpy(realm, krb5_princ_realm(ctx,me)->data, + krb5_princ_realm(ctx,me)->length); + realm[krb5_princ_realm(ctx,me)->length] = '\0'; + } + + if ( krb_con_open ) { + krbCon.WriteString(realm); + krbCon.WriteString("\n"); + } + + no_k5_realm: + if ( me ) + pkrb5_free_principal(ctx,me); + if ( ctx ) + pkrb5_free_context(ctx); + } + + // disable DNS Realm Lookups + retval = pprofile_update_relation(m_krbv5_profile, + names, + "true", "false"); + + // save the default realm if it was discovered + if ( realm[0] ) { + names = defRealm; + retval = pprofile_add_relation(m_krbv5_profile, + names, + realm); + + // It would be nice to be able to generate a list of KDCs + // but to do so based upon the contents of DNS would be + // wrong for several reasons: + // . it would make static the values inserted into DNS SRV + // records + // . DNS cannot necessarily be trusted + } + + // Save to Kerberos Five config. file "Krb5.ini" + retval = pprofile_flush(m_krbv5_profile); + + pprofile_release(m_krbv5_profile); + m_krbv5_profile = NULL; + + // Close KRB.CON file + if ( krb_con_open ) { + krbCon.WriteString(".KERBEROS.OPTION. dns\n"); + krbCon.Close(); + } + + // Create the empty KRBREALM.CON file + if ( !GetKrb4RealmFile(confname,sizeof(confname)) ) { + if (!krbCon.Open(confname, CFile::modeNoTruncate | CFile::modeRead)) + { + if (krbCon.Open(confname, CFile::modeCreate | CFile::modeWrite)) + { + krbCon.Close(); + } + } else + krbCon.Close(); + } + + } + } else if ( m_hKrb4DLL ) { + if ( !realm[0] ) { + /* Open ticket file */ + char * file = ptkt_string(); + int k_errno; + + if (file != NULL && file[0]) { + if ((k_errno = ptf_init(file, R_TKT_FIL)) == KSUCCESS) { + /* Close ticket file */ + (void) ptf_close(); + + k_errno = pkrb_get_tf_realm(file, realm); + } + if (k_errno != KSUCCESS) { + k_errno = pkrb_get_lrealm(realm, 1); + } + } + } + + if ( !GetKrb4ConFile(confname,sizeof(confname)) ) { + if (!krbCon.Open(confname, CFile::modeNoTruncate | CFile::modeRead)) + { + if (krbCon.Open(confname, CFile::modeCreate | CFile::modeWrite)) + { + if ( realm[0] ) + krbCon.WriteString(realm); + krbCon.WriteString("\n.KERBEROS.OPTION. dns\n"); + krbCon.Close(); + } + } else + krbCon.Close(); + } + + if ( !GetKrb4RealmFile(confname,sizeof(confname)) ) { + if (!krbCon.Open(confname, CFile::modeNoTruncate | CFile::modeRead)) + { + if (krbCon.Open(confname, CFile::modeCreate | CFile::modeWrite)) + { + krbCon.Close(); + } + } else + krbCon.Close(); + } + } +} + +BOOL +CLeashApp::GetKrb4ConFile( + LPSTR confname, + UINT szConfname + ) +{ + if (m_hKrb5DLL && !m_hKrb4DLL) + { // hold krb.con where krb5.ini is located + CHAR krbConFile[MAX_PATH]=""; + //strcpy(krbConFile, CLeashApp::m_krbv5_profile->first_file->filename); + if (GetProfileFile(krbConFile, sizeof(krbConFile))) + { + GetWindowsDirectory(krbConFile,sizeof(krbConFile)); + krbConFile[MAX_PATH-1] = '\0'; + strncat(krbConFile,"\\KRB5.INI",sizeof(krbConFile)-strlen(krbConFile)-1); + krbConFile[MAX_PATH-1] = '\0'; + } + + LPSTR pFind = strrchr(krbConFile, '\\'); + if (pFind) + { + *pFind = 0; + strncat(krbConFile, "\\",MAX_PATH-1); + krbConFile[MAX_PATH-1] = '\0'; + strncat(krbConFile, KRB_FILE,MAX_PATH-1); + krbConFile[MAX_PATH-1] = '\0'; + } + else + ASSERT(0); + + strncpy(confname, krbConFile, szConfname); + confname[szConfname-1] = '\0'; + } + else if (m_hKrb4DLL) + { + unsigned int size = szConfname; + memset(confname, '\0', szConfname); + if (!pkrb_get_krbconf2(confname, &size)) + { // Error has happened + GetWindowsDirectory(confname,szConfname); + confname[szConfname-1] = '\0'; + strncat(confname, "\\",szConfname); + confname[szConfname-1] = '\0'; + strncat(confname,KRB_FILE,szConfname); + confname[szConfname-1] = '\0'; + } + } + return FALSE; +} + +BOOL +CLeashApp::GetKrb4RealmFile( + LPSTR confname, + UINT szConfname + ) +{ + if (m_hKrb5DLL && !m_hKrb4DLL) + { // hold krb.con where krb5.ini is located + CHAR krbRealmConFile[MAX_PATH]; + //strcpy(krbRealmConFile, CLeashApp::m_krbv5_profile->first_file->filename); + if (GetProfileFile(krbRealmConFile, sizeof(krbRealmConFile))) + { + GetWindowsDirectory(krbRealmConFile,sizeof(krbRealmConFile)); + krbRealmConFile[MAX_PATH-1] = '\0'; + strncat(krbRealmConFile,"\\KRB5.INI",sizeof(krbRealmConFile)-strlen(krbRealmConFile)); + krbRealmConFile[MAX_PATH-1] = '\0'; + } + + LPSTR pFind = strrchr(krbRealmConFile, '\\'); + if (pFind) + { + *pFind = 0; + strncat(krbRealmConFile, "\\",MAX_PATH-1-strlen(krbRealmConFile)); + krbRealmConFile[MAX_PATH-1] = '\0'; + strncat(krbRealmConFile, KRBREALM_FILE,MAX_PATH-1-strlen(krbRealmConFile)); + krbRealmConFile[MAX_PATH-1] = '\0'; + } + else + ASSERT(0); + + strncpy(confname, krbRealmConFile, szConfname); + confname[szConfname-1] = '\0'; + } + else if (m_hKrb4DLL) + { + unsigned int size = szConfname; + memset(confname, '\0', szConfname); + if (!pkrb_get_krbrealm2(confname, &size)) + { + GetWindowsDirectory(confname,szConfname); + confname[szConfname-1] = '\0'; + strncat(confname, "\\",szConfname-strlen(confname)); + confname[szConfname-1] = '\0'; + strncat(confname,KRBREALM_FILE,szConfname-strlen(confname)); + confname[szConfname-1] = '\0'; + return TRUE; + } + } + return FALSE; +} + +BOOL +CLeashApp::GetProfileFile( + LPSTR confname, + UINT szConfname + ) +{ + char **configFile = NULL; + if (!m_hKrb5DLL) + return NULL; + + if (pkrb5_get_default_config_files(&configFile)) + { + GetWindowsDirectory(confname,szConfname); + confname[szConfname-1] = '\0'; + strncat(confname,"\\KRB5.INI",szConfname-strlen(confname)); + confname[szConfname-1] = '\0'; + return FALSE; + } + + *confname = 0; + + if (configFile) + { + strncpy(confname, *configFile, szConfname); + confname[szConfname-1] = '\0'; + pkrb5_free_config_files(configFile); + } + + if (!*confname) + { + GetWindowsDirectory(confname,szConfname); + confname[szConfname-1] = '\0'; + strncat(confname,"\\KRB5.INI",szConfname-strlen(confname)); + confname[szConfname-1] = '\0'; + } + + return FALSE; +} + +#define PROBE_USERNAME "KERBEROS-KDC-PROBE" +#define PROBE_PASSWORD_LEN 16 + +BOOL +CLeashApp::ProbeKDC(void) +{ + krb5_context ctx=0; + krb5_ccache cc=0; + krb5_principal principal = 0; + krb5_principal probeprinc = 0; + krb5_creds creds; + krb5_error_code code; + krb5_data pwdata; + char password[PROBE_PASSWORD_LEN+1]; + long success = FALSE; + + if (!pkrb5_init_context) + return success; + + memset(&creds, 0, sizeof(creds)); + + code = pkrb5_init_context(&ctx); + if (code) + goto cleanup; + + code = pkrb5_cc_default(ctx, &cc); + if (code) + goto cleanup; + + code = pkrb5_cc_get_principal(ctx, cc, &principal); + if ( code ) + code = pkrb5_parse_name(ctx, "foo", &principal); + if ( code ) + goto cleanup; + + code = pkrb5_build_principal( ctx, &probeprinc, + krb5_princ_realm(ctx,principal)->length, + krb5_princ_realm(ctx,principal)->data, + PROBE_USERNAME, NULL, NULL); + if ( code ) + goto cleanup; + + pwdata.data = password; + pwdata.length = PROBE_PASSWORD_LEN; + code = pkrb5_c_random_make_octets(ctx, &pwdata); + if (code) { + int i; + for ( i=0 ; i + + +DWORD +CLeashApp::GetNumOfIpAddrs(void) +{ + PMIB_IPADDRTABLE pIpAddrTable = 0; + ULONG dwSize; + DWORD code; + DWORD index; + DWORD validAddrs = 0; + + dwSize = 0; + code = GetIpAddrTable(NULL, &dwSize, 0); + if (code == ERROR_INSUFFICIENT_BUFFER) { + pIpAddrTable = (PMIB_IPADDRTABLE) malloc(dwSize); + code = GetIpAddrTable(pIpAddrTable, &dwSize, 0); + if ( code == NO_ERROR ) { + for ( index=0; index < pIpAddrTable->dwNumEntries; index++ ) { + if (pIpAddrTable->table[index].dwAddr != 0) + validAddrs++; + } + } + free(pIpAddrTable); + } + return validAddrs; +} + +UINT +CLeashApp::IpAddrChangeMonitor(void * hWnd) +{ + DWORD Result; + DWORD prevNumOfAddrs = GetNumOfIpAddrs(); + DWORD NumOfAddrs; + + if ( !hWnd ) + return 0; + + while ( TRUE ) { + Result = NotifyAddrChange(NULL,NULL); + if ( Result != NO_ERROR ) { + // We do not have permission to open the device + return 0; + } + + NumOfAddrs = GetNumOfIpAddrs(); + if ( NumOfAddrs != prevNumOfAddrs ) { + // wait for the network state to stablize + Sleep(2000); + // this call should probably be mutex protected + ObtainTicketsViaUserIfNeeded((HWND)hWnd); + } + prevNumOfAddrs = NumOfAddrs; + } + + return 0; +} + + +DWORD +CLeashApp::IpAddrChangeMonitorInit(HWND hWnd) +{ + AfxBeginThread(IpAddrChangeMonitor, hWnd); + return 0; +} + +UINT +CLeashApp::InitWorker(void * hWnd) +{ +#ifndef KRB5_TC_NOTICKET + if (WaitForSingleObject( m_tgsReqMutex, INFINITE ) != WAIT_OBJECT_0) + throw("Unable to lock tgsReq"); +#endif + if ( ProbeKDC() ) { + LSH_DLGINFO_EX ldi; + ldi.size = sizeof(ldi); + ldi.dlgtype = DLGTYPE_PASSWD; + ldi.title = "Initialize Ticket"; + ldi.username = NULL; + ldi.realm = NULL; + ldi.use_defaults = 1; + +#ifndef KRB5_TC_NOTICKET + ReleaseMutex(m_tgsReqMutex); +#endif + pLeash_kinit_dlg_ex((HWND)hWnd, &ldi); + ::SendMessage((HWND)hWnd, WM_COMMAND, ID_UPDATE_DISPLAY, 0); + } +#ifndef KRB5_TC_NOTICKET + else + ReleaseMutex(m_tgsReqMutex); +#endif + return 0; +} + +#ifdef USE_HTMLHELP +#if _MSC_VER < 1300 +void +CLeashApp::WinHelp(DWORD dwData, UINT nCmd) +{ + switch (nCmd) + { + case HELP_CONTEXT: + ::HtmlHelp(GetDesktopWindow(), m_helpFile, HH_HELP_CONTEXT, dwData ); + break; + case HELP_FINDER: + ::HtmlHelp(GetDesktopWindow(), m_helpFile, HH_DISPLAY_TOPIC, 0); + break; + } +} +#endif +#endif diff --git a/src/windows/leash/Leash.h b/src/windows/leash/Leash.h new file mode 100644 index 000000000..74c9d5d0a --- /dev/null +++ b/src/windows/leash/Leash.h @@ -0,0 +1,156 @@ +// ************************************************************************************** +// File: Leash.h +// By: Arthur David Leather +// Created: 12/02/98 +// Copyright @1998 Massachusetts Institute of Technology - All rights reserved. +// Description: H file for Leash.cpp. Contains variables and functions +// for Leash +// +// History: +// +// MM/DD/YY Inits Description of Change +// 12/02/98 ADL Original +// ************************************************************************************** + + +#if !defined(AFX_Leash_H__6F45AD91_561B_11D0_8FCF_00C04FC2A0C2__INCLUDED_) +#define AFX_Leash_H__6F45AD91_561B_11D0_8FCF_00C04FC2A0C2__INCLUDED_ + +#if _MSC_VER >= 1000 +#pragma once +#endif // _MSC_VER >= 1000 + +#ifndef __AFXWIN_H__ + #error include 'stdafx.h' before including this file for PCH +#endif + +// Help +#define HID_GET_TICKETS_COMMAND 98312 +#define HID_DESTROY_TICKETS_COMMAND 98313 +#define HID_SYNCHRONIZE_TIME_OPTION 98314 +#define HID_CHANGE_PASSWORD_COMMAND 98315 +#define HID_UPDATE_DISPLAY_COMMAND 98316 +#define HID_DEBUG_WINDOW_OPTION 98317 +#define HID_LEASH_PROGRAM 98319 +#define HID_ABOUT_KERBEROS 98320 +#define HID_LARGE_ICONS_OPTION 98322 +#define HID_DESTROY_TICKETS_ON_EXIT 98321 +#define HID_UPPERCASE_REALM_OPTION 98323 +#define HID_RESET_WINDOW_OPTION 98326 +#define HID_AFS_PROPERTIES_COMMAND 98327 +#define HID_KRB4_PROPERTIES_COMMAND 98329 +#define HID_KRB5_PROPERTIES_COMMAND 98330 +#define HID_LEASH_PROPERTIES_COMMAND 98331 +#define HID_LOW_TICKET_ALARM_OPTION 98334 +#define HID_KRBCHECK_OPTION 98335 +#define HID_KERBEROS_PROPERTIES_COMMAND 98337 +#define HID_HELP_CONTENTS 98340 +#define HID_WHY_USE_LEASH32 98341 + +#define HID_ABOUT_LEASH32_COMMAND 123200 +#define HID_EXIT_COMMAND 123201 +#define HID_TOOLBAR_OPTION 124928 +#define HID_STATUS_BAR_OPTION 124929 +#define HID_LEASH_COMMANDS 131200 +#define HID_ABOUT_LEASH32_MODULES 131225 +#define HID_DEBUG_WINDOW 131229 +#define HID_KRB4_PROPERTIES_EDIT 131232 +#define HID_KERBEROS_PROPERTIES_EDIT 131233 +#define HID_LEASH_PROPERTIES_EDIT 131239 +#define HID_KRB5_PROPERTIES_FORWARDING 131240 +#define HID_KRB5_PROPERTIES_EDIT 131241 +#define HID_KERBEROS_PROPERTIES_LISTRLM 131250 +#define HID_KERBEROS_PROPERTIES_ADDRLM 131253 +#define HID_KERBEROS_PROPERTIES_EDITRLM 131254 +#define HID_KERBEROS_PROPERTIES_ADDDOM 131255 +#define HID_KERBEROS_PROPERTIES_EDITDOM 131256 +#define HID_KERBEROS_PROPERTIES_ADDHOST 131269 +#define HID_KERBEROS_PROPERTIES_EDITHOST 131271 +#define HID_KERBEROS_PROPERTIES_LISTDOM 131279 + +#define USE_HTMLHELP + +#ifdef USE_HTMLHELP +#if _MSC_VER >= 1300 +#define CALL_HTMLHELP +#endif +#endif + +#include "resource.h" // main symbols +#include "lglobals.h" + +///////////////////////////////////////////////////////////////////////////// +// CLeashApp: +// See Leash.cpp for the implementation of this class +// + +class CLeashApp : public CWinApp +{ +private: + CString m_leashDLL; + CString m_krbDLL; + CString m_helpFile; + CString m_msgError; + + BOOL InitDLLs(); + BOOL FirstInstance(); + +public: + static HWND m_hProgram; + static HINSTANCE m_hLeashDLL; + static HINSTANCE m_hKrb4DLL; + static HINSTANCE m_hKrb5DLL; + static HINSTANCE m_hKrb5ProfileDLL; + static HINSTANCE m_hAfsDLL; + static HINSTANCE m_hPsapi; + static HINSTANCE m_hToolHelp32; + static krb5_context m_krbv5_context; + static profile_t m_krbv5_profile; + static HINSTANCE m_hKrbLSA; + + CLeashApp(); + virtual ~CLeashApp(); + + static BOOL GetProfileFile(LPSTR confname, UINT szConfname); + static BOOL GetKrb4ConFile(LPSTR confname, UINT szConfname); + static BOOL GetKrb4RealmFile(LPSTR confname, UINT szConfname); + static void ValidateConfigFiles(); + static void ObtainTicketsViaUserIfNeeded(HWND hWnd); + static DWORD GetNumOfIpAddrs(void); + static UINT IpAddrChangeMonitor(void *); + DWORD IpAddrChangeMonitorInit(HWND hWnd); + static BOOL ProbeKDC(void); + static UINT InitWorker(void *); + + // Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CLeashApp) + public: + virtual BOOL InitInstance(); +#ifdef USE_HTMLHELP +#if _MSC_VER < 1300 + virtual void WinHelp(DWORD dwData, UINT nCmd); +#endif +#endif + //}}AFX_VIRTUAL + + virtual void ParseParam (LPCTSTR lpszParam,BOOL bFlag,BOOL bLast ); + + protected: +// Implementation + + //{{AFX_MSG(CLeashApp) + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +extern CLeashApp theApp; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Developer Studio will insert additional declarations immediately before the previous line. + + + +#endif // !defined(AFX_Leash_H__6F45AD91_561B_11D0_8FCF_00C04FC2A0C2__INCLUDED_) diff --git a/src/windows/leash/Leash.rc b/src/windows/leash/Leash.rc new file mode 100644 index 000000000..9594446c8 --- /dev/null +++ b/src/windows/leash/Leash.rc @@ -0,0 +1,999 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "#define _AFX_NO_SPLITTER_RESOURCES\r\n" + "#define _AFX_NO_OLE_RESOURCES\r\n" + "#define _AFX_NO_TRACKER_RESOURCES\r\n" + "#define _AFX_NO_PROPERTY_RESOURCES\r\n" + "\r\n" + "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n" + "#ifdef _WIN32\r\n" + "LANGUAGE 9, 1\r\n" + "#pragma code_page(1252)\r\n" + "#endif\r\n" + "#include ""res\\Leash.rc2"" // non-Microsoft Visual C++ edited resources\r\n" + "#include ""afxres.rc"" // Standard components\r\n" + "#endif\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDR_MAINFRAME ICON "res\\Leash.ico" +IDR_LeashTYPE ICON "res\\Leash_Doc.ico" +IDI_LEASH_PRINCIPAL_GOOD ICON "res\\Leash_user_green.ico" +IDI_LEASH_PRINCIPAL_LOW ICON "res\\Leash_user_orange.ico" +IDI_LEASH_PRINCIPAL_EXPIRED ICON "res\\Leash_user_red.ico" +IDI_LEASH_PRINCIPAL_NONE ICON "res\\Leash_user_out.ico" +IDI_LEASH ICON "res\\Leash.ico" +IDI_TICKETTYPE_GOOD ICON "res\\Leash_tickets_green.ico" +IDI_TICKETTYPE_LOW ICON "res\\Leash_tickets_orange.ico" +IDI_TICKETTYPE_EXPIRED ICON "res\\Leash_tickets_red.ico" +IDI_TICKETTYPE_NOTINSTALLED ICON "res\\Leash_tickets_out.ico" +IDI_TICKET_GOOD ICON "res\\Leash_tkt_green.ico" +IDI_TICKET_LOW ICON "res\\Leash_tkt_orange.ico" +IDI_TICKET_EXPIRED ICON "res\\Leash_tkt_red.ico" +IDI_LEASH_TRAY_GOOD ICON "res\\doghead_green.ico" +IDI_LEASH_TRAY_LOW ICON "res\\doghead_orange.ico" +IDI_LEASH_TRAY_EXPIRED ICON "res\\doghead_red.ico" +IDI_LEASH_TRAY_NONE ICON "res\\doghead_grey.ico" +IDI_LEASH_TICKET_ADDRESS ICON "res\\address.ico" +IDI_LEASH_TICKET_SESSION ICON "res\\key.ico" +IDI_LEASH_TICKET_ENCRYPTION ICON "res\\encryption.ico" +IDI_TOOLBAR_INIT ICON "res\\new.ico" +IDI_TOOLBAR_RENEW ICON "res\\renew.ico" +IDI_TOOLBAR_IMPORT ICON "res\\import.ico" +IDI_TOOLBAR_DESTROY ICON "res\\destroy.ico" +IDI_TOOLBAR_PASSWORD ICON "res\\password.ico" +IDI_TOOLBAR_REFRESH ICON "res\\refresh.ico" +IDI_TOOLBAR_SYNC ICON "res\\sync.ico" +IDI_TOOLBAR_INIT_DISABLED ICON "res\\new_disabled.ico" +IDI_TOOLBAR_RENEW_DISABLED ICON "res\\renew_disabled.ico" +IDI_TOOLBAR_IMPORT_DISABLED ICON "res\\import_disabled.ico" +IDI_TOOLBAR_DESTROY_DISABLED ICON "res\\destroy_disabled.ico" +IDI_TOOLBAR_PASSWORD_DISABLED ICON "res\\password_disabled.ico" +IDI_TOOLBAR_REFRESH_DISABLED ICON "res\\refresh_disabled.ico" +IDI_TOOLBAR_SYNC_DISABLED ICON "res\\sync_disabled.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDR_MAINFRAME MENU +BEGIN + POPUP "&File" + BEGIN + MENUITEM "E&xit", ID_APP_EXIT + END + POPUP "&Action" + BEGIN + MENUITEM "&Gew Ticket(s)/Token(s)\tCtrl+T", ID_INIT_TICKET + MENUITEM "&Renew Ticket(s)/Token(s)\tCtrl+R", ID_RENEW_TICKET + MENUITEM "&Import Ticket(s)/Token(s)\tCtrl+I", ID_IMPORT_TICKET + MENUITEM "&Destroy Ticket(s)/Token(s)\tCtrl+D", ID_DESTROY_TICKET + MENUITEM SEPARATOR + MENUITEM "&Change Password...", ID_CHANGE_PASSWORD + MENUITEM SEPARATOR + MENUITEM "&Reset Window Size/Pos", ID_RESET_WINDOW_SIZE + MENUITEM "&Synchronize Time", ID_SYN_TIME + MENUITEM "&Update Display\tF5", ID_UPDATE_DISPLAY + END + POPUP "&View" + BEGIN + MENUITEM "&Large Icons", ID_LARGE_ICONS + MENUITEM "&Toolbar", ID_VIEW_TOOLBAR + MENUITEM "&Status Bar", ID_VIEW_STATUS_BAR + MENUITEM "&Debug Window", ID_DEBUG_MODE + END + POPUP "&Options" + BEGIN + MENUITEM "Upper &Case Realm Name", ID_UPPERCASE_REALM + MENUITEM "&Automatic Ticket Renewal", ID_AUTO_RENEW + MENUITEM "&Expiration Alarm", ID_LOW_TICKET_ALARM + MENUITEM "&Destroy Tickets/Tokens on Exit", ID_KILL_TIX_ONEXIT + MENUITEM SEPARATOR + MENUITEM "&Leash Properties...\tCtrl+L", ID_LEASH_PROPERTIES + MENUITEM "&Kerberos Properties...\tCtrl+K", ID_PROPERTIES + MENUITEM "Kerberos v&4 Properties...\tCtrl+4", ID_KRB4_PROPERTIES + MENUITEM "Kerberos v&5 Properties...\tCtrl+5", ID_KRB5_PROPERTIES + MENUITEM "&AFS Properties\tCtrl+A", ID_AFS_CONTROL_PANEL + END + POPUP "&Help" + BEGIN + MENUITEM "Why Use Leash", ID_HELP_WHYUSELEASH32 + MENUITEM "About &Kerberos ", ID_HELP_KERBEROS_ + MENUITEM SEPARATOR + MENUITEM "&Contents", ID_HELP_LEASH32 + MENUITEM "&Index", ID_HELP_LEASH_ + MENUITEM SEPARATOR + MENUITEM "&About Leash", ID_APP_ABOUT + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Accelerator +// + +IDR_MAINFRAME ACCELERATORS +BEGIN + "4", ID_KRB4_PROPERTIES, VIRTKEY, CONTROL, NOINVERT + "5", ID_KRB5_PROPERTIES, VIRTKEY, CONTROL, NOINVERT + "A", ID_AFS_CONTROL_PANEL, VIRTKEY, CONTROL, NOINVERT + "C", ID_EDIT_COPY, VIRTKEY, CONTROL, NOINVERT + "D", ID_DESTROY_TICKET, VIRTKEY, CONTROL, NOINVERT + "I", ID_IMPORT_TICKET, VIRTKEY, CONTROL, NOINVERT + "K", ID_PROPERTIES, VIRTKEY, CONTROL, NOINVERT + "L", ID_LEASH_PROPERTIES, VIRTKEY, CONTROL, NOINVERT + "N", ID_FILE_NEW, VIRTKEY, CONTROL, NOINVERT + "O", ID_FILE_OPEN, VIRTKEY, CONTROL, NOINVERT + "R", ID_RENEW_TICKET, VIRTKEY, CONTROL, NOINVERT + "S", ID_FILE_SAVE, VIRTKEY, CONTROL, NOINVERT + "T", ID_INIT_TICKET, VIRTKEY, CONTROL, NOINVERT + "V", ID_EDIT_PASTE, VIRTKEY, CONTROL, NOINVERT + VK_BACK, ID_EDIT_UNDO, VIRTKEY, ALT, NOINVERT + VK_DELETE, ID_BUTTON_REALM_REMOVE, VIRTKEY, NOINVERT + VK_DELETE, ID_EDIT_CUT, VIRTKEY, SHIFT, NOINVERT + VK_F1, ID_HELP, VIRTKEY, NOINVERT + VK_F1, ID_CONTEXT_HELP, VIRTKEY, SHIFT, NOINVERT + VK_F5, ID_UPDATE_DISPLAY, VIRTKEY, NOINVERT + VK_F6, ID_NEXT_PANE, VIRTKEY, NOINVERT + VK_F6, ID_PREV_PANE, VIRTKEY, SHIFT, NOINVERT + VK_INSERT, ID_EDIT_COPY, VIRTKEY, CONTROL, NOINVERT + VK_INSERT, ID_EDIT_PASTE, VIRTKEY, SHIFT, NOINVERT + "X", ID_EDIT_CUT, VIRTKEY, CONTROL, NOINVERT + "Z", ID_EDIT_UNDO, VIRTKEY, CONTROL, NOINVERT +END + +IDD_KRB4_DOMAINREALM_MAINT ACCELERATORS +BEGIN + "F", ID_BUTTON_HOSTNAME_REMOVE, VIRTKEY, CONTROL, NOINVERT +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_FRAMEOWNER DIALOG 0, 0, 219, 49 +STYLE DS_SETFONT | WS_POPUP +FONT 8, "MS Sans Serif" +BEGIN +END + +IDD_LEASH_FORMVIEW DIALOG 0, 0, 219, 49 +STYLE DS_SETFONT | DS_3DLOOK | WS_CHILD +FONT 8, "MS Sans Serif" +BEGIN + CONTROL "Tree1",IDC_TREEVIEW,"SysTreeView32",TVS_HASBUTTONS | + TVS_HASLINES | TVS_LINESATROOT | TVS_DISABLEDRAGDROP | + WS_TABSTOP | 0x800,0,19,164,13 + LTEXT "Your Kerberos Tickets and AFS Tokens (Issued/Expires/[Renew]/Principal)", + IDC_LABEL_KERB_TICKETS,6,5,280,12 +END + +IDD_LEASH_ABOUTBOX DIALOG 0, 0, 310, 146 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "About Leash" +FONT 8, "MS Sans Serif" +BEGIN + CONTROL "Leash Modules",IDC_LEASH_MODULES,"Button", + BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,10,127,64,10 + CONTROL "Missing Modules",IDC_NOT_LOADED_MODULES,"Button", + BS_AUTORADIOBUTTON | WS_TABSTOP,77,127,68,10 + CONTROL "All Modules",IDC_ALL_MODULES,"Button", + BS_AUTORADIOBUTTON | WS_TABSTOP,148,127,52,10 + PUSHBUTTON "&Properties",IDC_PROPERTIES,209,125,56,14 + DEFPUSHBUTTON "&OK",IDOK,268,125,35,14 + LISTBOX IDC_LEASH_MODULE_LB,7,50,296,62,LBS_SORT | + LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_HSCROLL | + WS_TABSTOP + ICON IDR_MAINFRAME,IDC_STATIC_ABOUTBOX_LEASH,11,9,20,20 + LTEXT "Modules Loaded:",IDC_STATIC_MODULES_LOADED,8,40,56,8 + LTEXT "3",IDC_STATIC_NO_OF_MODULES,67,40,8,8 + EDITTEXT IDC_ABOUT_COPYRIGHT,40,19,263,11,ES_AUTOHSCROLL | + ES_READONLY | NOT WS_BORDER | WS_GROUP | NOT WS_TABSTOP + EDITTEXT IDC_ABOUT_VERSION,40,8,263,11,ES_AUTOHSCROLL | + ES_READONLY | NOT WS_BORDER | WS_GROUP | NOT WS_TABSTOP +END + +IDD_LEASH_DEBUG_WINDOW DIALOG 200, 200, 338, 197 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | + WS_SYSMENU +CAPTION "Leash Debug Window" +FONT 8, "MS Sans Serif" +BEGIN + PUSHBUTTON "Copy &All To Clipboard",IDC_COPY_TO_CLIPBOARD,181,179, + 96,14 + LISTBOX IDC_DEBUG_LISTBOX,7,7,324,162,LBS_NOINTEGRALHEIGHT | + WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "&Cancel",IDCANCEL,281,179,50,14 + LTEXT "Log File Location:",IDC_LOG_FILE_LOCATION_LABEL,10,182, + 57,8 + LTEXT "C:\\TEMP\\",IDC_LOG_FILE_LOCATION_TEXT,68,182,105,8 +END + +IDD_LEASH_MESSAGE_BOX DIALOG 0, 0, 257, 60 +STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | DS_CENTER | WS_POPUP | + WS_CAPTION +CAPTION "Leash Warning" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,104,42,50,14 + CTEXT "Leash Warning Here!!!",IDC_LEASH_WARNING_MSG,0,7,257,27 +END + +IDD_KRB4_PROP_LOCATION DIALOG 0, 0, 316, 191 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Client File Location" +FONT 8, "MS Sans Serif" +BEGIN + EDITTEXT IDC_EDIT_TICKET_FILE,64,24,239,12,ES_AUTOHSCROLL + EDITTEXT IDC_EDIT_KRB_LOC,64,110,203,12,ES_AUTOHSCROLL | WS_GROUP + PUSHBUTTON "Browse",IDC_BUTTON_KRB_BROWSE,271,109,31,14,WS_GROUP + PUSHBUTTON "Browse",IDC_BUTTON_KRBREALM_BROWSE,271,129,32,14, + WS_GROUP + LTEXT "Name:",IDC_STATIC_TICKET_FILEPATH,34,25,22,8 + GROUPBOX "Configuration File(s) Path",IDC_STATIC_CONFIG_FILES,7, + 92,301,93 + GROUPBOX "Ticket File",IDC_STATIC_TICKETFILE,7,8,301,71 + LTEXT "Config.:",IDC_STATIC_KRBCON,31,110,25,8 + LTEXT "Ticket file name is set in your computer's environment!\nTo edit, remove it from the environment.", + IDC_STATIC_TXT,12,54,283,19 + LTEXT "One or more Configuration file locations are set in your computer's environment!\nTo edit, remove all of them from the environment.", + IDC_STATIC_CONFILES,12,160,284,19 + EDITTEXT IDC_EDIT_KRBREALM_LOC,64,130,203,12,ES_AUTOHSCROLL | + WS_GROUP + LTEXT "Realms:",IDC_STATIC_KRBREALMS,30,130,26,8 +END + +IDD_KRB_PROP_CONTENT DIALOG 0, 0, 314, 172 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Default Realm Configuration" +FONT 8, "MS Sans Serif" +BEGIN + COMBOBOX IDC_EDIT_DEFAULT_REALM,12,28,289,84,CBS_DROPDOWNLIST | + CBS_SORT | WS_VSCROLL | WS_TABSTOP + EDITTEXT IDC_EDIT_REALM_HOSTNAME,12,57,289,12,ES_AUTOHSCROLL | + ES_READONLY | NOT WS_TABSTOP + LTEXT "Your Kerberos Realm:",IDC_STATIC_DEFAULT_REALM,12,17,70, + 8 + GROUPBOX "Kerberos Realm/Host Server",IDC_STATIC_KRB,7,3,300,77 + GROUPBOX "Computer Host/Domain Name",IDC_STATIC_KRBREALM,7,89,300, + 75 + LTEXT "Your Computer's Host Name",IDC_STATIC_HOST,12,101,90,8 + LTEXT "Your Computer's Domain Name:",IDC_STATIC_DOMAIN,12,129, + 101,8 + EDITTEXT IDC_EDIT_HOSTNAME,12,112,289,12,ES_AUTOHSCROLL | + ES_READONLY | NOT WS_TABSTOP + EDITTEXT IDC_EDIT_DOMAINNAME,12,140,289,12,ES_AUTOHSCROLL | + ES_READONLY | NOT WS_TABSTOP + LTEXT "Your Kerberos Server:",IDC_STATIC_REALM_HOSTNAME,12,46, + 70,8 +END + +IDD_LEASH_FILESPECIAL DIALOG 0, 0, 241, 112 +STYLE DS_SETFONT | WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS +FONT 8, "MS Sans Serif" +BEGIN + GROUPBOX "",stc32,7,7,227,98,NOT WS_VISIBLE +END + +IDD_LEASH_PROPERTIES DIALOGEX 0, 0, 305, 166 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Leash Properties" +FONT 8, "MS Sans Serif", 0, 0, 0x0 +BEGIN + EDITTEXT IDC_EDIT_TIME_SERVER,59,22,233,12,ES_AUTOHSCROLL + PUSHBUTTON "&Help",IDC_BUTTON_LEASHINI_HELP2,138,145,50,14 + DEFPUSHBUTTON "&OK",IDOK,242,145,50,14 + PUSHBUTTON "&Cancel",IDCANCEL,190,145,50,14 + LTEXT "Name:",IDC_STATIC_TIMESERVER,31,23,22,8 + GROUPBOX "Time Server",IDC_STATIC_OPTIONS,7,7,291,45 + LTEXT "Time server name is set in your computer's environment!\nTo edit, remove it from the environment.", + IDC_STATIC_TIMEHOST,31,22,201,21 + CONTROL "Create Configuration Files &Missing at Startup", + IDC_CHECK_CREATE_MISSING_CFG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,15,105,244,10 + PUSHBUTTON "&Restore Leash Defaults",IDC_RESET_DEFAULTS,31,126,243, + 14 + GROUPBOX "Miscellaneous Options",IDC_GROUP_LEASH_MISC,7,95,291,29 + GROUPBOX "Automatic MSLSA Ticket Importation",IDC_STATIC,7,52,291, + 40 + CONTROL "Never",IDC_RADIO_MSLSA_IMPORT_OFF,"Button", + BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,16,70,35,10 + CONTROL "Always",IDC_RADIO_MSLSA_IMPORT_ON,"Button", + BS_AUTORADIOBUTTON | WS_TABSTOP,62,70,48,10 + CONTROL "When MSLSA Principal matches Default Realm", + IDC_RADIO_MSLSA_IMPORT_MATCH,"Button",BS_AUTORADIOBUTTON | + WS_TABSTOP,116,71,165,10 +END + +IDD_KRB5_PROP_CONTENT DIALOG 0, 0, 321, 126 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Configuration Options" +FONT 8, "MS Sans Serif" +BEGIN + GROUPBOX "Ticket Options",IDC_STATIC_TICKET_OPTIONS,7,7,307,41 + CONTROL "&Forwardable",IDC_CHECK_FORWARDABLE,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,18,23,55,10 + CONTROL "&Proxiable",IDC_CHECK_PROXIABLE,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,94,23,45,10 + CONTROL "&Renewable",IDC_CHECK_RENEWABLE,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,160,23,52,10 + CONTROL "No &Addresses",IDC_CHECK_NO_ADDRESS,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,233,23,60,10 +END + +IDD_KRB5_PROP_LOCATION DIALOG 0, 0, 321, 173 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "File Location" +FONT 8, "MS Sans Serif" +BEGIN + GROUPBOX "&Ticket File",IDC_STATIC__KRB5_TICKETFILE,7,8,307,67 + EDITTEXT IDC_EDIT_KRB5_TXT_FILE,17,21,291,12,ES_AUTOHSCROLL + LTEXT "Ticket file name is set in your computer's environment!\nTo edit, remove it from the environment.", + IDC_STATIC_TICKETFILE,12,51,284,19 + GROUPBOX "&Configuration File",IDC_STATIC_TICKET_FILE,7,86,307,80 + EDITTEXT IDC_EDIT_KRB5INI_LOCATION,17,100,237,12,ES_AUTOHSCROLL | + WS_GROUP + PUSHBUTTON "&Browse",IDC_BUTTON_KRB5INI_BROWSE,259,99,50,14, + WS_GROUP + CONTROL "Confirm that new configuration file &exists.", + IDC_CHECK_CONFIRM_KRB5_EXISTS,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,12,123,143,10 + LTEXT "Configuration file location is set in your computer's environment!\nTo edit, remove it from the environment.", + IDC_STATIC_INIFILES,12,142,284,19 +END + +IDD_KRB_REALMHOST_MAINT DIALOG 0, 0, 316, 213 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Realm / Server Mapping" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "In&sert",IDC_BUTTON_REALM_HOST_ADD,27,190,34,14 + PUSHBUTTON "&Remove",ID_BUTTON_REALM_REMOVE,64,190,34,14 + PUSHBUTTON "Re&name",IDC_BUTTON_REALM_EDIT,102,190,34,14 + LISTBOX IDC_LIST_KDC_REALM,7,21,146,160,LBS_SORT | + LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP + LISTBOX IDC_LIST_KDC_HOST,163,21,146,78,LBS_NOINTEGRALHEIGHT | + WS_VSCROLL | WS_HSCROLL | WS_TABSTOP + LTEXT "Kerberos Realms",IDC_STATIC_REALM,8,11,54,8 + LTEXT "Servers Hosting a KDC",IDC_STATIC,163,11,74,8 + PUSHBUTTON "&Make Admin",IDC_BUTTON_ADMINSERVER,176,106,55,14, + WS_DISABLED + DEFPUSHBUTTON "Inser&t",IDC_BUTTON_KDCHOST_ADD,183,127,34,14 + PUSHBUTTON "Rem&ove",IDC_BUTTON_KDCHOST_REMOVE,220,127,34,14 + PUSHBUTTON "Ed&it",IDC_BUTTON_KDCHOST_EDIT,257,126,34,14 + PUSHBUTTON "R&emove Admin",IDC_BUTTON_REMOVE_ADMINSERVER,242,106,55, + 14,WS_DISABLED + CONTROL "Use DNS KDC Lookup",IDC_DNS_KDC,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,169,158,131,10 +END + +IDD_KRB4_DOMAINREALM_MAINT DIALOG 0, 0, 313, 213 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Domain-Host/Realm Maintenance" +FONT 8, "MS Sans Serif" +BEGIN + LISTBOX IDC_LIST_DOMAINREALM,7,7,299,174,LBS_NOINTEGRALHEIGHT | + WS_VSCROLL | WS_TABSTOP + DEFPUSHBUTTON "&Add",IDC_BUTTON_REALM_HOST_ADD,52,192,50,14 + PUSHBUTTON "&Remove",ID_BUTTON_REALM_HOST_REMOVE,106,192,50,14 + PUSHBUTTON "&Edit",IDC_BUTTON_REALM_HOST_EDIT,160,192,50,14 + PUSHBUTTON "&Help",IDC_BUTTON_HOSTMAINT_HELP,214,192,50,14 +END + +IDD_KRB_ADD_REALM DIALOG 0, 0, 295, 94 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Add a Kerberos Realm" +FONT 8, "MS Sans Serif" +BEGIN + EDITTEXT IDC_EDIT_REALM,70,39,213,12,ES_UPPERCASE | + ES_AUTOHSCROLL + PUSHBUTTON "&OK",IDOK,232,67,50,14 + PUSHBUTTON "&Cancel",IDCANCEL,179,67,50,14 + LTEXT "Kerberos Realm:",IDC_STATIC_REALM_HOSTNAME,12,41,53,8 + LTEXT "NOTE: You are about to add a Realm to the ""Kerberos Realm"" Listbox!!!", + IDC_STATIC_NOTE,11,15,271,8 +END + +IDD_KRB_EDIT_REALM DIALOG 0, 0, 295, 94 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Edit Kerberos Realm" +FONT 8, "MS Sans Serif" +BEGIN + EDITTEXT IDC_EDIT_REALM,70,39,213,12,ES_UPPERCASE | + ES_AUTOHSCROLL + PUSHBUTTON "&OK",IDOK,231,67,50,14 + PUSHBUTTON "&Cancel",IDCANCEL,179,67,50,14 + LTEXT "Kerberos Realm:",IDC_STATIC_DEFAULT_REALM,12,41,53,8 + LTEXT "NOTE: You are about to edit a Realm to the ""Kerberos Realm"" Listbox!!!", + IDC_STATIC_NOTE,11,15,267,8 +END + +IDD_KRB4_ADD_DOMAINREALMNAME DIALOG 0, 0, 295, 89 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Add Your Domain-Host/Kerberos Realm Names to List" +FONT 8, "MS Sans Serif" +BEGIN + EDITTEXT IDC_EDIT_DOMAINHOSTNAME,75,15,208,12,ES_AUTOHSCROLL + EDITTEXT IDC_EDIT_DOMAINREALMNAME,75,32,208,12,ES_UPPERCASE | + ES_AUTOHSCROLL + PUSHBUTTON "&OK",IDOK,232,62,50,14 + PUSHBUTTON "&Cancel",IDCANCEL,179,62,50,14 + LTEXT "Domain or Host: ",IDC_STATIC_DEFAULT_REALM,12,17,58,8 + LTEXT "Kerberos Realm:",IDC_STATIC_REALM_HOSTNAME,17,34,53,8 +END + +IDD_KRB4_EDIT_DOMAINREALMNAME DIALOG 0, 0, 295, 89 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Edit Your Domain-Host/Kerberos Realm Names to List" +FONT 8, "MS Sans Serif" +BEGIN + EDITTEXT IDC_EDIT_DOMAINHOST,75,15,208,12,ES_AUTOHSCROLL + EDITTEXT IDC_EDIT_REALMNAME,75,32,208,12,ES_UPPERCASE | + ES_AUTOHSCROLL + PUSHBUTTON "&OK",IDOK,232,62,50,14 + PUSHBUTTON "&Cancel",IDCANCEL,179,62,50,14 + LTEXT "Domain or Host: ",IDC_STATIC_DEFAULT_REALM,12,17,58,8 + LTEXT "Kerberos Realm:",IDC_STATIC_REALM_HOSTNAME,17,34,53,8 +END + +IDD_KRB_ADD_KDC_HOSTSERVER DIALOG 0, 0, 295, 94 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Add a Kerberos Host Server" +FONT 8, "MS Sans Serif" +BEGIN + EDITTEXT IDC_EDIT_KDC_HOST,70,39,213,12,ES_AUTOHSCROLL + DEFPUSHBUTTON "OK",IDOK,231,67,50,14 + PUSHBUTTON "Cancel",IDCANCEL,179,67,50,14 + LTEXT "Kerberos Server:",IDC_STATIC_DEFAULT_REALM,11,41,54,8 + LTEXT "NOTE: You are about to add a Server to the"" Server Hosting a KDC"" Listbox!!! ", + IDC_STATIC_NOTE,11,15,267,8 +END + +IDD_KRB_EDIT_KDC_HOSTSERVER DIALOG 0, 0, 295, 94 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Edit a Kerberos Server" +FONT 8, "MS Sans Serif" +BEGIN + EDITTEXT IDC_EDIT_KDC_HOST,70,39,213,12,ES_AUTOHSCROLL + PUSHBUTTON "&OK",IDOK,231,67,50,14 + PUSHBUTTON "&Cancel",IDCANCEL,180,67,50,14 + LTEXT "Kerberos Server:",IDC_STATIC_REALM,11,41,54,8 + LTEXT "NOTE: You are about to edit a Server to the"" Server Hosting a KDC"" Listbox!!! ", + IDC_STATIC_NOTE,11,15,267,8 +END + +IDD_KRB4_REALMHOST_MAINT2 DIALOG 0, 0, 313, 214 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Realm/Host Maintenance" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "&Add",IDC_BUTTON_KRB4_REALM_HOST_ADD,53,161,50,14 + PUSHBUTTON "&Remove",ID_BUTTON_KRB4_REALM_HOST_REMOVE,107,161,50,14 + PUSHBUTTON "&Edit",IDC_BUTTON_KRB4_REALM_HOST_EDIT,161,161,50,14 + PUSHBUTTON "&Help",IDC_BUTTON_REALMHOST_MAINT_HELP2,214,161,50,14 + LISTBOX IDC_LIST_REMOVE_HOST,7,7,299,149,LBS_NOINTEGRALHEIGHT | + WS_VSCROLL | WS_TABSTOP + CONTROL "Use DNS KDC Lookup",IDC_KRB4_DNS_KDC,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,18,186,89,10 +END + +IDD_KRB4_EDIT_REALM DIALOG 0, 0, 296, 113 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Edit Kerberos Realm/Kerberos Host Names" +FONT 8, "MS Sans Serif" +BEGIN + EDITTEXT IDC_EDIT_DEFAULT_REALM,70,23,213,12,ES_UPPERCASE | + ES_AUTOHSCROLL + EDITTEXT IDC_EDIT_REALM_HOSTNAME,70,41,213,12,ES_AUTOHSCROLL + CONTROL "Has Administrative Server",IDC_RADIO_ADMIN_SERVER, + "Button",BS_AUTORADIOBUTTON | WS_TABSTOP,50,61,96,12 + CONTROL "No Administrative Server",IDC_RADIO_NO_ADMIN_SERVER, + "Button",BS_AUTORADIOBUTTON | WS_TABSTOP,154,61,92,12 + PUSHBUTTON "&OK",IDOK,233,86,50,14 + PUSHBUTTON "&Cancel",IDCANCEL,181,86,50,14 + LTEXT "Kerberos Realm:",IDC_STATIC_DEFAULT_REALM,11,25,53,8 + LTEXT "Kerberos Host:",IDC_STATIC_REALM_HOSTNAME,16,43,48,8 +END + +IDD_KRB4_ADD_REALM DIALOG 0, 0, 296, 113 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Add Kerberos Realm/Kerberos Host Names" +FONT 8, "MS Sans Serif" +BEGIN + EDITTEXT IDC_EDIT_DEFAULT_REALM,70,23,213,12,ES_UPPERCASE | + ES_AUTOHSCROLL + EDITTEXT IDC_EDIT_REALM_HOSTNAME,70,41,213,12,ES_AUTOHSCROLL + CONTROL "Has Administrative Server",IDC_RADIO_ADMIN_SERVER, + "Button",BS_AUTORADIOBUTTON | WS_TABSTOP,50,61,95,12 + CONTROL "No Administrative Server",IDC_RADIO_NO_ADMIN_SERVER, + "Button",BS_AUTORADIOBUTTON | WS_TABSTOP,154,61,92,12 + PUSHBUTTON "&OK",IDOK,232,86,50,14 + PUSHBUTTON "&Cancel",IDCANCEL,179,86,50,14 + LTEXT "Kerberos Realm:",IDC_STATIC_DEFAULT_REALM,11,25,53,8 + LTEXT "Kerberos Host:",IDC_STATIC_REALM_HOSTNAME,16,43,48,8 +END + +IDD_KRB_DOMAINREALM_MAINT DIALOG 0, 0, 314, 213 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "DNS / Realm Mapping" +FONT 8, "MS Sans Serif" +BEGIN + LISTBOX IDC_LIST_DOMAINREALM,7,7,299,174,LBS_SORT | + LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP + DEFPUSHBUTTON "&Insert",IDC_BUTTON_HOST_ADD,77,192,50,14 + PUSHBUTTON "&Remove",ID_BUTTON_HOST_REMOVE,131,192,50,14 + PUSHBUTTON "&Edit",IDC_BUTTON_HOST_EDIT,185,192,50,14 +END + +IDD_AFS_PROPERTIES DIALOG 0, 0, 290, 68 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "AFS Properties" +FONT 8, "MS Sans Serif" +BEGIN + CONTROL "AFS Enabled",IDC_RADIO_AFS_ENABLED,"Button", + BS_AUTORADIOBUTTON,12,19,59,10 + CONTROL "AFS Disabled",IDC_RADIO_AFS_DISABLED,"Button", + BS_AUTORADIOBUTTON,80,19,59,10 + PUSHBUTTON "AFS Properties",IDC_BUTTON_AFS_PROPERTIES,11,47,70,14 + DEFPUSHBUTTON "&OK",IDOK,227,47,50,14 + PUSHBUTTON "&Cancel",IDCANCEL,173,47,50,14 + PUSHBUTTON "&Help",IDC_BUTTON_LEASHINI_HELP2,119,47,50,14 +END + +IDD_KRB_PROP_MISC DIALOGEX 0, 0, 314, 215 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Ticket Lifetime and Other Initialization Options" +FONT 8, "MS Sans Serif", 0, 0, 0x0 +BEGIN + GROUPBOX "Default Ticket Lifetime", + IDC_STATIC_KRB_DEFAULT_LIFETIME,7,7,147,39 + GROUPBOX "Ticket Lifetime Range",IDC_STATIC_LIFETIME_RANGE,7,47, + 148,97 + GROUPBOX "Ticket Renew Till Range",IDC_STATIC_RENEW_TILL_RANGE, + 155,47,152,97 + EDITTEXT IDC_EDIT_LIFETIME_D,21,23,20,14,ES_RIGHT | + ES_AUTOHSCROLL | ES_NUMBER + EDITTEXT IDC_EDIT_LIFETIME_H,59,23,21,14,ES_RIGHT | + ES_AUTOHSCROLL | ES_NUMBER + EDITTEXT IDC_EDIT_LIFETIME_M,97,23,21,14,ES_RIGHT | + ES_AUTOHSCROLL | ES_NUMBER + EDITTEXT IDC_EDIT_LIFE_MIN_D,23,77,20,14,ES_RIGHT | + ES_AUTOHSCROLL | ES_NUMBER + EDITTEXT IDC_EDIT_LIFE_MIN_H,59,77,21,14,ES_RIGHT | + ES_AUTOHSCROLL | ES_NUMBER + EDITTEXT IDC_EDIT_LIFE_MIN_M,98,77,21,14,ES_RIGHT | + ES_AUTOHSCROLL | ES_NUMBER + EDITTEXT IDC_EDIT_LIFE_MAX_D,23,109,20,14,ES_RIGHT | + ES_AUTOHSCROLL | ES_NUMBER + EDITTEXT IDC_EDIT_LIFE_MAX_H,59,109,20,14,ES_RIGHT | + ES_AUTOHSCROLL | ES_NUMBER + EDITTEXT IDC_EDIT_LIFE_MAX_M,99,109,20,14,ES_RIGHT | + ES_AUTOHSCROLL | ES_NUMBER + GROUPBOX "Minimum Lifetime",IDC_STATIC_LIFE_RANGE_MIN,16,64,132, + 32 + GROUPBOX "Maximum Lifetime",IDC_STATIC,16,99,132,30 + GROUPBOX "Minimum Renewable Lifetime",IDC_STATIC,161,64,136,31 + GROUPBOX "Maximum Renewable Lifetime",IDC_STATIC,162,98,136,31 + EDITTEXT IDC_EDIT_RENEWTILL_D,168,23,20,14,ES_RIGHT | + ES_AUTOHSCROLL | ES_NUMBER + EDITTEXT IDC_EDIT_RENEWTILL_H,206,23,21,14,ES_RIGHT | + ES_AUTOHSCROLL | ES_NUMBER + EDITTEXT IDC_EDIT_RENEWTILL_M,244,23,21,14,ES_RIGHT | + ES_AUTOHSCROLL | ES_NUMBER + EDITTEXT IDC_EDIT_RENEW_MIN_D,168,77,25,14,ES_RIGHT | + ES_AUTOHSCROLL | ES_NUMBER + EDITTEXT IDC_EDIT_RENEW_MIN_H,207,77,21,14,ES_RIGHT | + ES_AUTOHSCROLL | ES_NUMBER + EDITTEXT IDC_EDIT_RENEW_MIN_M,245,77,21,14,ES_RIGHT | + ES_AUTOHSCROLL | ES_NUMBER + EDITTEXT IDC_EDIT_RENEW_MAX_D,168,109,26,14,ES_RIGHT | + ES_AUTOHSCROLL | ES_NUMBER + EDITTEXT IDC_EDIT_RENEW_MAX_H,208,109,21,14,ES_RIGHT | + ES_AUTOHSCROLL | ES_NUMBER + EDITTEXT IDC_EDIT_RENEW_MAX_M,246,109,20,14,ES_RIGHT | + ES_AUTOHSCROLL | ES_NUMBER + LTEXT "d",IDC_STATIC,46,80,8,8 + LTEXT "h",IDC_STATIC,82,79,8,8 + LTEXT "m",IDC_STATIC,121,80,8,8 + LTEXT "d",IDC_STATIC,45,112,8,8 + LTEXT "h",IDC_STATIC,81,112,8,8 + LTEXT "m",IDC_STATIC,123,112,8,8 + LTEXT "d",IDC_STATIC,194,80,8,8 + LTEXT "h",IDC_STATIC,229,80,8,8 + LTEXT "m",IDC_STATIC,267,80,8,8 + LTEXT "d",IDC_STATIC,194,112,8,8 + LTEXT "h",IDC_STATIC,230,112,8,8 + LTEXT "m",IDC_STATIC,267,112,8,8 + LTEXT "d",IDC_STATIC,45,26,8,8 + LTEXT "h",IDC_STATIC,83,26,8,8 + LTEXT "m",IDC_STATIC,120,26,8,8 + GROUPBOX "Default Ticket Renewable Lifetime", + IDC_STATIC_KRB_DEFAULT_RENEWTILL,155,7,151,39 + LTEXT "d",IDC_STATIC,192,26,8,8 + LTEXT "h",IDC_STATIC,230,26,8,8 + LTEXT "m",IDC_STATIC,267,26,8,8 + GROUPBOX "Ticket Initialization Options",IDC_STATIC,7,151,300,59 + CONTROL "Request Kerberos 4 Tickets",IDC_CHECK_REQUEST_KRB4, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,19,167,203,10 + CONTROL "Preserve Ticket Initialization Dialog Options", + IDC_CHECK_PRESERVE_KINIT_OPTIONS,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,20,182,208,10 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_LEASH_FORMVIEW, DIALOG + BEGIN + RIGHTMARGIN, 217 + TOPMARGIN, 7 + BOTTOMMARGIN, 42 + END + + IDD_LEASH_ABOUTBOX, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 303 + TOPMARGIN, 7 + BOTTOMMARGIN, 139 + END + + IDD_LEASH_DEBUG_WINDOW, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 331 + TOPMARGIN, 7 + BOTTOMMARGIN, 190 + END + + IDD_KRB4_PROP_LOCATION, DIALOG + BEGIN + LEFTMARGIN, 6 + RIGHTMARGIN, 307 + TOPMARGIN, 6 + BOTTOMMARGIN, 184 + END + + IDD_KRB_PROP_CONTENT, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 307 + TOPMARGIN, 7 + BOTTOMMARGIN, 164 + END + + IDD_LEASH_FILESPECIAL, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 234 + TOPMARGIN, 7 + BOTTOMMARGIN, 105 + END + + IDD_LEASH_PROPERTIES, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 298 + TOPMARGIN, 7 + BOTTOMMARGIN, 159 + END + + IDD_KRB5_PROP_CONTENT, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 314 + TOPMARGIN, 7 + BOTTOMMARGIN, 55 + HORZGUIDE, 48 + END + + IDD_KRB5_PROP_LOCATION, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 314 + TOPMARGIN, 7 + BOTTOMMARGIN, 166 + END + + IDD_KRB_REALMHOST_MAINT, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 309 + TOPMARGIN, 7 + BOTTOMMARGIN, 206 + END + + IDD_KRB4_DOMAINREALM_MAINT, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 306 + TOPMARGIN, 7 + BOTTOMMARGIN, 206 + END + + IDD_KRB_ADD_REALM, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 288 + TOPMARGIN, 7 + BOTTOMMARGIN, 87 + END + + IDD_KRB_EDIT_REALM, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 288 + TOPMARGIN, 7 + BOTTOMMARGIN, 87 + END + + IDD_KRB4_ADD_DOMAINREALMNAME, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 288 + TOPMARGIN, 7 + BOTTOMMARGIN, 82 + END + + IDD_KRB4_EDIT_DOMAINREALMNAME, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 288 + TOPMARGIN, 7 + BOTTOMMARGIN, 82 + END + + IDD_KRB_ADD_KDC_HOSTSERVER, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 288 + TOPMARGIN, 7 + BOTTOMMARGIN, 87 + END + + IDD_KRB_EDIT_KDC_HOSTSERVER, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 288 + TOPMARGIN, 7 + BOTTOMMARGIN, 87 + END + + IDD_KRB4_REALMHOST_MAINT2, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 306 + TOPMARGIN, 7 + BOTTOMMARGIN, 206 + END + + IDD_KRB4_EDIT_REALM, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 289 + TOPMARGIN, 7 + BOTTOMMARGIN, 106 + END + + IDD_KRB4_ADD_REALM, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 289 + TOPMARGIN, 7 + BOTTOMMARGIN, 106 + END + + IDD_KRB_DOMAINREALM_MAINT, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 307 + TOPMARGIN, 7 + BOTTOMMARGIN, 206 + END + + IDD_AFS_PROPERTIES, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 283 + TOPMARGIN, 7 + BOTTOMMARGIN, 61 + END + + IDD_KRB_PROP_MISC, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 307 + TOPMARGIN, 7 + BOTTOMMARGIN, 210 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Toolbar +// + +IDR_MAINFRAME TOOLBAR 18, 18 +BEGIN + BUTTON ID_INIT_TICKET + BUTTON ID_RENEW_TICKET + BUTTON ID_IMPORT_TICKET + BUTTON ID_DESTROY_TICKET + SEPARATOR + BUTTON ID_CHANGE_PASSWORD + SEPARATOR + BUTTON ID_UPDATE_DISPLAY + BUTTON ID_SYN_TIME +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Bitmap +// + +IDR_MAINFRAME BITMAP "res\\Leash_toolbar.bmp" + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE +BEGIN + IDR_MAINFRAME "Leash32\n\nLeash32\n\n\nLeash32.Document\nLeash32 Document" +END + +STRINGTABLE +BEGIN + AFX_IDS_APP_TITLE "Leash" + AFX_IDS_IDLEMESSAGE "For Help, press F1" + AFX_IDS_HELPMODEMESSAGE "Select an object on which to get Help" +END + +STRINGTABLE +BEGIN + ID_VIEW_TOOLBAR "Show or hide the toolbar\nToggle ToolBar" + ID_VIEW_STATUS_BAR "Show or hide the status bar\nToggle StatusBar" +END + +STRINGTABLE +BEGIN + AFX_IDS_SCSIZE "Change the window size" + AFX_IDS_SCMOVE "Change the window position" + AFX_IDS_SCMINIMIZE "Reduce the window to an icon" + AFX_IDS_SCMAXIMIZE "Enlarge the window to full size" + AFX_IDS_SCNEXTWINDOW "Switch to the next document window" + AFX_IDS_SCPREVWINDOW "Switch to the previous document window" + AFX_IDS_SCCLOSE "Close the active window and prompts to save the documents" +END + +STRINGTABLE +BEGIN + AFX_IDS_SCRESTORE "Restore the window to normal size" + AFX_IDS_SCTASKLIST "Activate Task List" +END + +STRINGTABLE +BEGIN + ID_PROPERTIES "Enables you to change settings" + ID_IMPORT_TICKET "Convert MS Windows credentials into tickets/tokens\n Import Ticket(s) " + ID_INIT_TICKET "Activate all tickets/tokens\n Initialize Ticket(s) " + ID_AUTO_RENEW "Automatically attempt to renew tickets" +END + +STRINGTABLE +BEGIN + ID_RENEW_TICKET "Re-activate all tickets/tokens\n Renew Tickets(s) " + ID_DESTROY_TICKET "Dispose of all tickets/tokens\n Destroy Ticket(s) " + ID_SYN_TIME "Synchronize Time\n Synchronize Time " + ID_CHANGE_PASSWORD "Modify password\n Change Password " + ID_UPDATE_DISPLAY "Refresh ticket tree display\n Update Display " + ID_DEBUG_MODE "Show or hide the Debug window" + ID_CFG_FILES "Configure dialog" +END + +STRINGTABLE +BEGIN + ID_KILL_TIX_ONEXIT "Dispose of or keep tickets/tokens upon exiting Leash" + ID_LARGE_ICONS "Show large or small tree icons" + ID_UPPERCASE_REALM "Force upper or lower case realm name" + ID_OPTIONS_RESETWINDOWSIZE + "Puts Leash's main window back to it's default size " + ID_RESET_WINDOW_SIZE "Refresh Leash window to it's default size/position" + ID_AFS_CONTROL_PANEL "Enables you to change settings" + ID_SYSTEM_CONTROL_PANEL "Open your System Properties window" + ID_KRB4_PROPERTIES "Enables you to change settings" + ID_KRB5_PROPERTIES "Enables you to change settings" + ID_LEASH_PROPERTIES "Enables you to change settings" + ID_OPTIONS_LOWTICKETALARMSOUND + "Turn alarm off or on, when ticket time is low" + ID_LOW_TICKET_ALARM "Turn alarm on or off, on low ticket(s)/token(s) times" +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// +#define _AFX_NO_SPLITTER_RESOURCES +#define _AFX_NO_OLE_RESOURCES +#define _AFX_NO_TRACKER_RESOURCES +#define _AFX_NO_PROPERTY_RESOURCES + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE 9, 1 +#pragma code_page(1252) +#endif +#include "res\Leash.rc2" // non-Microsoft Visual C++ edited resources +#include "afxres.rc" // Standard components +#endif +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED diff --git a/src/windows/leash/LeashAboutBox.cpp b/src/windows/leash/LeashAboutBox.cpp new file mode 100644 index 000000000..972514fee --- /dev/null +++ b/src/windows/leash/LeashAboutBox.cpp @@ -0,0 +1,363 @@ +//***************************************************************************** +// File: LeashAboutBox.cpp +// By: Arthur David Leather +// Created: 12/02/98 +// Copyright: @1998 Massachusetts Institute of Technology - All rights +// reserved. +// Description: CPP file for LeashAboutBox.h. Contains variables and functions +// for the Leash About Box Dialog Box +// +// History: +// +// MM/DD/YY Inits Description of Change +// 12/02/98 ADL Original +//***************************************************************************** + + +#include "stdafx.h" +#include "leash.h" +#include "LeashAboutBox.h" +#include "reminder.h" +#include "lglobals.h" +#include "psapi.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CLeashAboutBox dialog + + +CLeashAboutBox::CLeashAboutBox(CWnd* pParent /*=NULL*/) + : CDialog(CLeashAboutBox::IDD, pParent) +{ + m_missingFileError = FALSE; + + //{{AFX_DATA_INIT(CLeashAboutBox) + m_fileItem = _T(""); + //}}AFX_DATA_INIT +} + + +void CLeashAboutBox::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CLeashAboutBox) + DDX_Control(pDX, IDC_PROPERTIES, m_propertiesButton); + DDX_Control(pDX, IDC_LEASH_MODULES, m_radio_LeashDLLs); + DDX_Control(pDX, IDC_LEASH_MODULE_LB, m_LB_DLLsLoaded); + DDX_LBString(pDX, IDC_LEASH_MODULE_LB, m_fileItem); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CLeashAboutBox, CDialog) + //{{AFX_MSG_MAP(CLeashAboutBox) + ON_WM_HSCROLL() + ON_LBN_SELCHANGE(IDC_LEASH_MODULE_LB, OnSelchangeLeashModuleLb) + ON_BN_CLICKED(IDC_ALL_MODULES, OnAllModules) + ON_BN_CLICKED(IDC_LEASH_MODULES, OnLeashModules) + ON_LBN_DBLCLK(IDC_LEASH_MODULE_LB, OnDblclkLeashModuleLb) + ON_BN_CLICKED(IDC_PROPERTIES, OnProperties) + ON_LBN_SETFOCUS(IDC_LEASH_MODULE_LB, OnSetfocusLeashModuleLb) + ON_BN_CLICKED(IDC_NOT_LOADED_MODULES, OnNotLoadedModules) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() +; +///////////////////////////////////////////////////////////////////////////// +// CLeashAboutBox message handlers + +void CLeashAboutBox::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) +{ + CDialog::OnHScroll(nSBCode, nPos, pScrollBar); +} + +BOOL CLeashAboutBox::GetModules95(DWORD processID, BOOL allModules) +{ + char szModNames[1024]; + MODULEENTRY32 me32 = {0}; + HANDLE hProcessSnap = NULL; + + hProcessSnap = pCreateToolhelp32Snapshot(TH32CS_SNAPMODULE, processID); + if (hProcessSnap == (HANDLE)-1) + return FALSE; + + me32.dwSize = sizeof(MODULEENTRY32); + if (pModule32First(hProcessSnap, &me32)) + { + do + { + lstrcpy(szModNames, me32.szExePath); + strupr(szModNames); + + if (!allModules) + { + if (!strstr(szModNames, "SYSTEM")) + m_LB_DLLsLoaded.AddString(me32.szExePath); + } + else + m_LB_DLLsLoaded.AddString(me32.szExePath); + } + while (pModule32Next(hProcessSnap, &me32)); + } + + return TRUE; +} + +void CLeashAboutBox::GetModulesNT(DWORD processID, BOOL allModules) +{ + char checkName[1024]; + HMODULE hMods[1024]; + HANDLE hProcess; + DWORD cbNeeded; + unsigned int i; + + // Get a list of all the modules in this process. + hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, + FALSE, processID); + + if (pEnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded)) + { + for (i = 0; i < (cbNeeded / sizeof(HMODULE)); i++) + { + char szModName[2048]; + + // Get the full path to the module's file. + if (pGetModuleFileNameEx(hProcess, hMods[i], szModName, + sizeof(szModName))) + { + lstrcpy(checkName, szModName); + strupr(checkName); + + if (!allModules) + { + if (!strstr(checkName, "SYSTEM32")) + m_LB_DLLsLoaded.AddString(szModName); + } + else + m_LB_DLLsLoaded.AddString(szModName); + } + } + } + + CloseHandle(hProcess); +} + +void CLeashAboutBox::HighlightFirstItem() +{ + UINT numModules = m_LB_DLLsLoaded.GetCount(); + CHAR numModulesBuffer [25]; + _itoa(numModules, numModulesBuffer, 10); + + if (numModules) + { + m_LB_DLLsLoaded.SetCurSel(0); + m_propertiesButton.EnableWindow(); + } + else + m_propertiesButton.EnableWindow(FALSE); + + GetDlgItem(IDC_STATIC_NO_OF_MODULES)->SetWindowText(numModulesBuffer); +} + +DWORD +CLeashAboutBox::SetVersionInfo( + UINT id_version, + UINT id_copyright + ) +{ + TCHAR filename[1024]; + DWORD dwVersionHandle; + LPVOID pVersionInfo = 0; + DWORD retval = 0; + LPDWORD pLangInfo = 0; + LPTSTR szVersion = 0; + LPTSTR szCopyright = 0; + UINT len = 0; + TCHAR sname_version[] = TEXT("FileVersion"); + TCHAR sname_copyright[] = TEXT("LegalCopyright"); + TCHAR szVerQ[(sizeof("\\StringFileInfo\\12345678\\") + + max(sizeof(sname_version) / sizeof(TCHAR), + sizeof(sname_copyright) / sizeof(TCHAR)))]; + TCHAR * cp = szVerQ; + + if (!GetModuleFileName(NULL, filename, sizeof(filename))) + return GetLastError(); + + DWORD size = GetFileVersionInfoSize(filename, &dwVersionHandle); + + if (!size) + return GetLastError(); + + pVersionInfo = malloc(size); + if (!pVersionInfo) + return ERROR_NOT_ENOUGH_MEMORY; + + if (!GetFileVersionInfo(filename, dwVersionHandle, size, pVersionInfo)) + { + retval = GetLastError(); + goto cleanup; + } + + if (!VerQueryValue(pVersionInfo, TEXT("\\VarFileInfo\\Translation"), + (LPVOID*)&pLangInfo, &len)) + { + retval = GetLastError(); + goto cleanup; + } + + + cp += wsprintf(szVerQ, + TEXT("\\StringFileInfo\\%04x%04x\\"), + LOWORD(*pLangInfo), HIWORD(*pLangInfo)); + + lstrcpy(cp, sname_version); + if (!VerQueryValue(pVersionInfo, szVerQ, (LPVOID*)&szVersion, &len)) + { + retval = GetLastError() || ERROR_NOT_ENOUGH_MEMORY; + goto cleanup; + } + TCHAR version[100]; + _sntprintf(version, sizeof(version), TEXT("Leash Version %s"), szVersion); + version[sizeof(version) - 1] = 0; + GetDlgItem(id_version)->SetWindowText(version); + + lstrcpy(cp, sname_copyright); + if (!VerQueryValue(pVersionInfo, szVerQ, (LPVOID*)&szCopyright, &len)) + { + retval = GetLastError() || ERROR_NOT_ENOUGH_MEMORY; + goto cleanup; + } + GetDlgItem(id_copyright)->SetWindowText(szCopyright); + + cleanup: + if (pVersionInfo) + free(pVersionInfo); + return retval; +} + +BOOL CLeashAboutBox::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // XXX - we need to add some sensible behavior on error. + SetVersionInfo(IDC_ABOUT_VERSION, IDC_ABOUT_COPYRIGHT); + + if (!CLeashApp::m_hToolHelp32 && !CLeashApp::m_hPsapi) + m_missingFileError = TRUE; + + m_radio_LeashDLLs.SetCheck(TRUE); + OnLeashModules(); + + // We need to get the version info and display it... + HighlightFirstItem(); + + if (!CLeashApp::m_hPsapi) + GetDlgItem(IDC_PROPERTIES)->EnableWindow(FALSE); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void CLeashAboutBox::OnSelchangeLeashModuleLb() +{ +} + +void CLeashAboutBox::OnAllModules() +{ + if (!CLeashApp::m_hToolHelp32 && !CLeashApp::m_hPsapi) + return; //error + + m_LB_DLLsLoaded.ResetContent(); + + if (!CLeashApp::m_hPsapi) + GetModules95(GetCurrentProcessId()); + //m_LB_DLLsLoaded.AddString("Doesn't work in Windows 95"); + else + GetModulesNT(GetCurrentProcessId()); + + HighlightFirstItem(); +} + +void CLeashAboutBox::OnLeashModules() +{ + if (!CLeashApp::m_hToolHelp32 && !CLeashApp::m_hPsapi) + return; // error + + m_LB_DLLsLoaded.ResetContent(); + + if (!CLeashApp::m_hPsapi) + GetModules95(GetCurrentProcessId(), FALSE); + //m_LB_DLLsLoaded.AddString("Doesn't work in Windows 95"); + else + GetModulesNT(GetCurrentProcessId(), FALSE); + + HighlightFirstItem(); +} + +void CLeashAboutBox::OnNotLoadedModules() +{ + m_LB_DLLsLoaded.ResetContent(); + + if (!CLeashApp::m_hKrb4DLL) + m_LB_DLLsLoaded.AddString(KERB4DLL); + + if (!CLeashApp::m_hKrb5DLL) + m_LB_DLLsLoaded.AddString(KERB5DLL); + + // NOTE: If the snippet below is commented back in, + // it should read + // if (!CLeashApp::m_hAfsDLL) + // m_LB_DLLsLoaded.AddString(AFSAuthentDLL()); + + //if (!CLeashApp::m_hAfsDLL) + //m_LB_DLLsLoaded.AddString(ASFDLL); + + HighlightFirstItem(); +} + +void CLeashAboutBox::OnDblclkLeashModuleLb() +{ + m_LB_DLLsLoaded.GetText(m_LB_DLLsLoaded.GetCurSel(), m_fileItem); + + SHELLEXECUTEINFO sei; + ZeroMemory(&sei,sizeof(sei)); + sei.cbSize = sizeof(sei); + sei.lpFile = m_fileItem; + sei.lpVerb = "properties"; + sei.fMask = SEE_MASK_INVOKEIDLIST; + + if (!ShellExecuteEx(&sei)) + { + MessageBox("Can't find selected file or Properties dialog", "Error", + MB_OK); + } +} + +void CLeashAboutBox::OnProperties() +{ + OnDblclkLeashModuleLb(); +} + +void CLeashAboutBox::OnSetfocusLeashModuleLb() +{ + if (m_LB_DLLsLoaded.GetCount()) + m_propertiesButton.EnableWindow(TRUE); +} + +BOOL CLeashAboutBox::PreTranslateMessage(MSG* pMsg) +{ + if (m_missingFileError) + { + ::MessageBox(NULL, "OnInitDialog::We can't find file\"PSAPI.DLL\" " + "or \"KERNEL32.DLL\"!!!\n" + "About Box will not work properly.", + "Error", MB_OK); + + m_missingFileError = FALSE; + } + return CDialog::PreTranslateMessage(pMsg); +} diff --git a/src/windows/leash/LeashAboutBox.h b/src/windows/leash/LeashAboutBox.h new file mode 100644 index 000000000..34e1dac31 --- /dev/null +++ b/src/windows/leash/LeashAboutBox.h @@ -0,0 +1,81 @@ +//***************************************************************************** +// File: LeashAboutBox.cpp +// By: Arthur David Leather +// Created: 12/02/98 +// Copyright: @1998 Massachusetts Institute of Technology - All rights +// reserved. +// Description: H file for LeashAboutBox.cpp. Contains variables and functions +// for the Leash About Box Dialog Box +// +// History: +// +// MM/DD/YY Inits Description of Change +// 12/02/98 ADL Original +//***************************************************************************** + + +#if !defined(AFX_LEASHABOUTBOX_H__B49E3501_4801_11D2_8F7D_0000861B8A3C__INCLUDED_) +#define AFX_LEASHABOUTBOX_H__B49E3501_4801_11D2_8F7D_0000861B8A3C__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// LeashAboutBox.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CLeashAboutBox dialog + +class CLeashAboutBox : public CDialog +{ + BOOL m_missingFileError; + DWORD SetVersionInfo(UINT id_ver, UINT id_copyright); + BOOL GetModules95(DWORD processID, BOOL allModules = TRUE); + void GetModulesNT(DWORD processID, BOOL allModules = TRUE); + void HighlightFirstItem(); + +// Construction +public: + CLeashAboutBox(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CLeashAboutBox) + enum { IDD = IDD_LEASH_ABOUTBOX }; + CButton m_propertiesButton; + CButton m_radio_LeashDLLs; + CListBox m_LB_DLLsLoaded; + CString m_fileItem; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CLeashAboutBox) +public: + virtual BOOL PreTranslateMessage(MSG* pMsg); +protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CLeashAboutBox) + afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar); + virtual BOOL OnInitDialog(); + afx_msg void OnSelchangeLeashModuleLb(); + afx_msg void OnAllModules(); + afx_msg void OnLeashModules(); + afx_msg void OnDblclkLeashModuleLb(); + afx_msg void OnProperties(); + afx_msg void OnSetfocusLeashModuleLb(); + afx_msg void OnNotLoadedModules(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_LEASHABOUTBOX_H__B49E3501_4801_11D2_8F7D_0000861B8A3C__INCLUDED_) diff --git a/src/windows/leash/LeashControlPanel.cpp b/src/windows/leash/LeashControlPanel.cpp new file mode 100644 index 000000000..47273a077 --- /dev/null +++ b/src/windows/leash/LeashControlPanel.cpp @@ -0,0 +1,43 @@ +// LeashControlPanel.cpp : implementation file +// + +#include "stdafx.h" +#include "leash.h" +#include "LeashControlPanel.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CLeashControlPanel dialog + + +CLeashControlPanel::CLeashControlPanel(CWnd* pParent /*=NULL*/) + : CDialog(CLeashControlPanel::IDD, pParent) +{ + //{{AFX_DATA_INIT(CLeashControlPanel) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT +} + + +void CLeashControlPanel::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CLeashControlPanel) + // NOTE: the ClassWizard will add DDX and DDV calls here + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CLeashControlPanel, CDialog) + //{{AFX_MSG_MAP(CLeashControlPanel) + // NOTE: the ClassWizard will add message map macros here + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CLeashControlPanel message handlers diff --git a/src/windows/leash/LeashControlPanel.h b/src/windows/leash/LeashControlPanel.h new file mode 100644 index 000000000..173dd6e78 --- /dev/null +++ b/src/windows/leash/LeashControlPanel.h @@ -0,0 +1,46 @@ +#if !defined(AFX_LEASHCONTROLPANEL_H__940146F3_6857_11D2_943C_0000861B8A3C__INCLUDED_) +#define AFX_LEASHCONTROLPANEL_H__940146F3_6857_11D2_943C_0000861B8A3C__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// LeashControlPanel.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CLeashControlPanel dialog + +class CLeashControlPanel : public CDialog +{ +// Construction +public: + CLeashControlPanel(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CLeashControlPanel) + enum { IDD = IDD_LEASH_CONTROL_PANEL }; + // NOTE: the ClassWizard will add data members here + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CLeashControlPanel) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CLeashControlPanel) + // NOTE: the ClassWizard will add member functions here + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_LEASHCONTROLPANEL_H__940146F3_6857_11D2_943C_0000861B8A3C__INCLUDED_) diff --git a/src/windows/leash/LeashDebugWindow.cpp b/src/windows/leash/LeashDebugWindow.cpp new file mode 100644 index 000000000..6e12903ae --- /dev/null +++ b/src/windows/leash/LeashDebugWindow.cpp @@ -0,0 +1,187 @@ +// ************************************************************************************** +// File: LeashDebugWindow.cpp +// By: Arthur David Leather +// Created: 12/02/98 +// Copyright @1998 Massachusetts Institute of Technology - All rights reserved. +// Description: CPP file for LeashDebugWindow.h. Contains variables and functions +// for the Leash Debug Window +// +// History: +// +// MM/DD/YY Inits Description of Change +// 12/02/98 ADL Original +// ************************************************************************************** + + + +#include "stdafx.h" +#include "leash.h" +#include "LeashDebugWindow.h" +#include "lglobals.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CLeashDebugWindow dialog + + +CLeashDebugWindow::CLeashDebugWindow(CWnd* pParent /*=NULL*/) + : CDialog(CLeashDebugWindow::IDD, pParent) +{ + //{{AFX_DATA_INIT(CLeashDebugWindow) + //}}AFX_DATA_INIT + + m_pView = NULL; +} + +CLeashDebugWindow::CLeashDebugWindow(CFormView* pView) +{ + m_pView = pView; +} + +void CLeashDebugWindow::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CLeashDebugWindow) + DDX_Control(pDX, IDC_DEBUG_LISTBOX, m_debugListBox); + DDX_Control(pDX, IDC_LOG_FILE_LOCATION_TEXT, m_debugFile); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CLeashDebugWindow, CDialog) + //{{AFX_MSG_MAP(CLeashDebugWindow) + ON_WM_SHOWWINDOW() + ON_BN_CLICKED(IDC_COPY_TO_CLIPBOARD, OnCopyToClipboard) + ON_WM_DESTROY() + ON_WM_CLOSE() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CLeashDebugWindow message handlers + + +BOOL CLeashDebugWindow::Create(const LPCSTR debugFilePath) +{ + m_debugFilePath = debugFilePath; + return CDialog::Create(CLeashDebugWindow::IDD); +} + + +void CLeashDebugWindow::OnCancel() +{ + if (m_pView != NULL) + { + CWinApp* pApp; + pApp = AfxGetApp(); + pApp->WriteProfileInt("Settings", "DebugWindow", FALSE_FLAG); + m_pView->PostMessage(WM_GOODBYE, IDCANCEL); // modeless case + pset_krb_debug(OFF); + pset_krb_ap_req_debug(OFF); + } + else + { + CDialog::OnCancel(); // modal case + } +} + +void CLeashDebugWindow::OnOK() +{ + if (m_pView != NULL) + { + // modeless case + UpdateData(TRUE); + m_pView->PostMessage(WM_GOODBYE, IDOK); + } + else + { + CDialog::OnOK(); // modal case + } +} + +BOOL CLeashDebugWindow::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // Set Debug flags + pset_krb_debug(ON); //(int)m_debugListBox.GetSafeHwnd() + pset_krb_ap_req_debug(ON); + + if (*m_debugFilePath != 0) + SetDlgItemText(IDC_LOG_FILE_LOCATION_TEXT, m_debugFilePath); + else + SetDlgItemText(IDC_LOG_FILE_LOCATION_TEXT, "Not Available"); + + if (!m_debugListBox.GetCount()) + GetDlgItem(IDC_COPY_TO_CLIPBOARD)->EnableWindow(FALSE); + + m_CopyButton = FALSE; + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void CLeashDebugWindow::OnShowWindow(BOOL bShow, UINT nStatus) +{ + CDialog::OnShowWindow(bShow, nStatus); +} + +void CLeashDebugWindow::OnCopyToClipboard() +{ + if (!OpenClipboard()) + { + MessageBox("Unable to open Clipboard!", "Error", MB_OK); + return; + } + + EmptyClipboard(); + + int maxItems = m_debugListBox.GetCount(); + const int MAX_MEM = maxItems * 90; // 90 chars per line seems safe like a safe bet + + HGLOBAL hDebugText = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, MAX_MEM); + if (NULL != hDebugText) + { + CString listboxItem; + LPSTR pDebugText = (LPSTR) GlobalLock(hDebugText); + if (!pDebugText) + { + MessageBox("Unable to write to Clipboard!", "Error", MB_OK); + ASSERT(pDebugText); + return; + } + + *pDebugText = 0; + for (int xItem = 0; xItem < maxItems; xItem++) + { + m_debugListBox.GetText(xItem, listboxItem); + strcat(pDebugText, listboxItem); + strcat(pDebugText, "\r\n"); + } + + GlobalUnlock(hDebugText); + } + + if (NULL != hDebugText) + SetClipboardData(CF_TEXT, hDebugText); + + CloseClipboard(); + MessageBox("Copy to Clipboard was Successful!\r\n Paste it in your favorite editor.", + "Note", MB_OK); +} + +BOOL CLeashDebugWindow::PreTranslateMessage(MSG* pMsg) +{ + if (!m_CopyButton && m_debugListBox.GetCount()) + { + m_CopyButton = TRUE; + GetDlgItem(IDC_COPY_TO_CLIPBOARD)->EnableWindow(TRUE); + } + + return CDialog::PreTranslateMessage(pMsg); +} diff --git a/src/windows/leash/LeashDebugWindow.h b/src/windows/leash/LeashDebugWindow.h new file mode 100644 index 000000000..49893702f --- /dev/null +++ b/src/windows/leash/LeashDebugWindow.h @@ -0,0 +1,78 @@ +// ************************************************************************************** +// File: LeashDebugWindow.h +// By: Arthur David Leather +// Created: 12/02/98 +// Copyright @1998 Massachusetts Institute of Technology - All rights reserved. +// Description: H file for LeashDebugWindow.cpp. Contains variables and functions +// for the Leash Debug Window +// +// History: +// +// MM/DD/YY Inits Description of Change +// 12/02/98 ADL Original +// ************************************************************************************** + + +#if !defined(AFX_LEASHDEBUGWINDOW_H__DB6F7EE8_570E_11D2_9460_0000861B8A3C__INCLUDED_) +#define AFX_LEASHDEBUGWINDOW_H__DB6F7EE8_570E_11D2_9460_0000861B8A3C__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// LeashDebugWindow.h +// + +///////////////////////////////////////////////////////////////////////////// +// CLeashDebugWindow dialog + +#define WM_GOODBYE WM_USER + 5 + +class CLeashDebugWindow : public CDialog +{ +private: + BOOL m_CopyButton; + CFormView* m_pView; + CString m_debugFilePath; + +// Construction +public: + CLeashDebugWindow(CWnd* pParent = NULL); + CLeashDebugWindow(CFormView* pView); + BOOL Create(const LPCSTR debugFilePath); + + +// Dialog Data + //{{AFX_DATA(CLeashDebugWindow) + enum { IDD = IDD_LEASH_DEBUG_WINDOW }; + CStatic m_debugFile; + CListBox m_debugListBox; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CLeashDebugWindow) + public: + virtual BOOL PreTranslateMessage(MSG* pMsg); + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CLeashDebugWindow) + virtual void OnCancel(); + virtual void OnOK(); + afx_msg void OnShowWindow(BOOL bShow, UINT nStatus); + afx_msg void OnCopyToClipboard(); + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_LEASHDEBUGWINDOW_H__DB6F7EE8_570E_11D2_9460_0000861B8A3C__INCLUDED_) diff --git a/src/windows/leash/LeashDoc.cpp b/src/windows/leash/LeashDoc.cpp new file mode 100644 index 000000000..af4a9b8f6 --- /dev/null +++ b/src/windows/leash/LeashDoc.cpp @@ -0,0 +1,94 @@ +// ************************************************************************************** +// File: LeashDoc.cpp +// By: Arthur David Leather +// Created: 12/02/98 +// Copyright @1998 Massachusetts Institute of Technology - All rights reserved. +// Description: CPP file for LeashDoc.h. Contains variables and functions +// for Leash +// +// History: +// +// MM/DD/YY Inits Description of Change +// 12/02/98 ADL Original +// ************************************************************************************** + + +#include "stdafx.h" +#include "Leash.h" + +#include "LeashDoc.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// LeashDoc + +IMPLEMENT_DYNCREATE(LeashDoc, CDocument) + +BEGIN_MESSAGE_MAP(LeashDoc, CDocument) + //{{AFX_MSG_MAP(LeashDoc) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// LeashDoc construction/destruction + +LeashDoc::LeashDoc() +{ + // TODO: add one-time construction code here + +} + +LeashDoc::~LeashDoc() +{ +} + +BOOL LeashDoc::OnNewDocument() +{ + if (!CDocument::OnNewDocument()) + return FALSE; + + // TODO: add reinitialization code here + // (SDI documents will reuse this document) + + return TRUE; +} + + + +///////////////////////////////////////////////////////////////////////////// +// LeashDoc serialization + +void LeashDoc::Serialize(CArchive& ar) +{ + if (ar.IsStoring()) + { + // TODO: add storing code here + } + else + { + // TODO: add loading code here + } +} + +///////////////////////////////////////////////////////////////////////////// +// LeashDoc diagnostics + +#ifdef _DEBUG +void LeashDoc::AssertValid() const +{ + CDocument::AssertValid(); +} + +void LeashDoc::Dump(CDumpContext& dc) const +{ + CDocument::Dump(dc); +} +#endif //_DEBUG + +///////////////////////////////////////////////////////////////////////////// +// LeashDoc commands diff --git a/src/windows/leash/LeashDoc.h b/src/windows/leash/LeashDoc.h new file mode 100644 index 000000000..33b2fd973 --- /dev/null +++ b/src/windows/leash/LeashDoc.h @@ -0,0 +1,66 @@ +// ************************************************************************************** +// File: LeashDoc.h +// By: Arthur David Leather +// Created: 12/02/98 +// Copyright @1998 Massachusetts Institute of Technology - All rights reserved. +// Description: H file for LeashDoc.cpp. Contains variables and functions +// for Leash +// +// History: +// +// MM/DD/YY Inits Description of Change +// 12/02/98 ADL Original +// ************************************************************************************** + + +#if !defined(AFX_LeashDOC_H__6F45AD97_561B_11D0_8FCF_00C04FC2A0C2__INCLUDED_) +#define AFX_LeashDOC_H__6F45AD97_561B_11D0_8FCF_00C04FC2A0C2__INCLUDED_ + +#if _MSC_VER >= 1000 +#pragma once +#endif // _MSC_VER >= 1000 + + +class LeashDoc : public CDocument +{ +protected: // create from serialization only + LeashDoc(); + DECLARE_DYNCREATE(LeashDoc) + +// Attributes +public: + +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(LeashDoc) + public: + virtual BOOL OnNewDocument(); + virtual void Serialize(CArchive& ar); + //}}AFX_VIRTUAL + +// Implementation +public: + virtual ~LeashDoc(); +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + +protected: + +// Generated message map functions +protected: + //{{AFX_MSG(LeashDoc) + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Developer Studio will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_LeashDOC_H__6F45AD97_561B_11D0_8FCF_00C04FC2A0C2__INCLUDED_) diff --git a/src/windows/leash/LeashFileDialog.cpp b/src/windows/leash/LeashFileDialog.cpp new file mode 100644 index 000000000..7e45f4211 --- /dev/null +++ b/src/windows/leash/LeashFileDialog.cpp @@ -0,0 +1,75 @@ +// ************************************************************************************** +// File: LeashFileDialog.cpp +// By: Arthur David Leather +// Created: 12/02/98 +// Copyright @1998 Massachusetts Institute of Technology - All rights reserved. +// Description: CPP file for LeashFileDialog.h. Contains variables and functions +// for the Leash File Dialog Box +// +// History: +// +// MM/DD/YY Inits Description of Change +// 12/02/98 ADL Original +// ************************************************************************************** + + +#include "stdafx.h" +#include "leash.h" +#include "LeashFileDialog.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CLeashFileDialog + +IMPLEMENT_DYNAMIC(CLeashFileDialog, CFileDialog) + + + +CLeashFileDialog::CLeashFileDialog(BOOL bOpenFileDialog, LPCTSTR lpszDefExt, LPCTSTR lpszFileName, + LPCTSTR lpszFilter, DWORD dwFlags, CWnd* pParentWnd) : + CFileDialog(bOpenFileDialog, lpszDefExt, lpszFileName, dwFlags, lpszFilter, pParentWnd) +{ + m_ofn.Flags |= OFN_ENABLETEMPLATE; + m_ofn.lpTemplateName = MAKEINTRESOURCE(IDD_FILESPECIAL); + m_ofn.lpstrFilter = lpszFilter; + m_ofn.lpstrFileTitle = m_lpstrFileTitle; + m_ofn.nMaxFileTitle = MAX_PATH; + *m_lpstrFileTitle = 0; + BOOL m_startup = TRUE; +} + + +BEGIN_MESSAGE_MAP(CLeashFileDialog, CFileDialog) + //{{AFX_MSG_MAP(CLeashFileDialog) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + + +BOOL CLeashFileDialog::OnInitDialog() +{ + BOOL bRet = CFileDialog::OnInitDialog(); + if (bRet == TRUE) + { + GetParent()->GetDlgItem(IDOK)->SetWindowText("&OK"); + //GetParent()->GetDlgItem(IDOK)->EnableWindow(FALSE); + } + + return bRet; +} + +void CLeashFileDialog::OnFileNameChange( ) +{ + if (!m_startup) + { //' keeps the OK button disabled until a real select is made + CString testString = GetFileName(); + if (-1 == testString.Find('*')) + GetParent()->GetDlgItem(IDOK)->EnableWindow(); + } + else + m_startup = FALSE; +} diff --git a/src/windows/leash/LeashFileDialog.h b/src/windows/leash/LeashFileDialog.h new file mode 100644 index 000000000..aef156d35 --- /dev/null +++ b/src/windows/leash/LeashFileDialog.h @@ -0,0 +1,57 @@ +// ************************************************************************************** +// File: LeashFileDialog.h +// By: Arthur David Leather +// Created: 12/02/98 +// Copyright @1998 Massachusetts Institute of Technology - All rights reserved. +// Description: H file for LeashFileDialog.cpp. Contains variables and functions +// for the Leash File Dialog Box +// +// History: +// +// MM/DD/YY Inits Description of Change +// 12/02/98 ADL Original +// ************************************************************************************** + + +#if !defined(AFX_LEASHFILEDIALOG_H__E74500E1_6B74_11D2_9448_0000861B8A3C__INCLUDED_) +#define AFX_LEASHFILEDIALOG_H__E74500E1_6B74_11D2_9448_0000861B8A3C__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// LeashFileDialog.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CLeashFileDialog dialog + +class CLeashFileDialog : public CFileDialog +{ + DECLARE_DYNAMIC(CLeashFileDialog) + +private: + CHAR m_lpstrFileTitle[MAX_PATH]; + BOOL m_startup; + +public: + CLeashFileDialog(BOOL bOpenFileDialog, // TRUE for FileOpen, FALSE for FileSaveAs + LPCTSTR lpszDefExt = NULL, + LPCTSTR lpszFileName = NULL, + LPCTSTR lpszFilter = NULL, + DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_FILEMUSTEXIST, + CWnd* pParentWnd = NULL); + + CString GetSelectedFileName() {return m_lpstrFileTitle;} + +protected: + //{{AFX_MSG(CLeashFileDialog) + virtual BOOL OnInitDialog(); + virtual void OnFileNameChange( ); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_LEASHFILEDIALOG_H__E74500E1_6B74_11D2_9448_0000861B8A3C__INCLUDED_) diff --git a/src/windows/leash/LeashFrame.cpp b/src/windows/leash/LeashFrame.cpp new file mode 100644 index 000000000..f7e4b56e8 --- /dev/null +++ b/src/windows/leash/LeashFrame.cpp @@ -0,0 +1,119 @@ +// ************************************************************************************** +// File: LeashFrame.cpp +// By: Arthur David Leather +// Created: 12/02/98 +// Copyright @1998 Massachusetts Institute of Technology - All rights reserved. +// Description: CPP file for LeashFrame.h. Contains variables and functions +// for Leash +// +// History: +// +// MM/DD/YY Inits Description of Change +// 12/02/98 ADL Original +// ************************************************************************************** + + +#include "stdafx.h" +#include "LeashFrame.h" + +#ifdef _DEBUG +#undef THIS_FILE +static char BASED_CODE THIS_FILE[] = __FILE__; +#endif +/////////////////////////////////////////////////////////////// +// CLeashFrame + +const CRect CLeashFrame::s_rectDefault(0, 0, 740, 400); // static public (l,t,r,b) +const char CLeashFrame::s_profileHeading[] = "Window size"; +const char CLeashFrame::s_profileRect[] = "Rect"; +const char CLeashFrame::s_profileIcon[] = "icon"; +const char CLeashFrame::s_profileMax[] = "max"; +const char CLeashFrame::s_profileTool[] = "tool"; +const char CLeashFrame::s_profileStatus[] = "status"; + +IMPLEMENT_DYNAMIC(CLeashFrame, CFrameWnd) + +BEGIN_MESSAGE_MAP(CLeashFrame, CFrameWnd) + //{{AFX_MSG_MAP(CLeashFrame) + ON_WM_DESTROY() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +/////////////////////////////////////////////////////////////// +CLeashFrame::CLeashFrame() +{ + m_bFirstTime = TRUE; +} + +/////////////////////////////////////////////////////////////// +CLeashFrame::~CLeashFrame() +{ +} + +/////////////////////////////////////////////////////////////// +void CLeashFrame::OnDestroy() +{ + CString strText; + BOOL bIconic, bMaximized; + + WINDOWPLACEMENT wndpl; + wndpl.length = sizeof(WINDOWPLACEMENT); + // gets current window position and + // iconized/maximized status + BOOL bRet = GetWindowPlacement(&wndpl); + if (wndpl.showCmd == SW_SHOWNORMAL) + { + bIconic = FALSE; + bMaximized = FALSE; + } + else if (wndpl.showCmd == SW_SHOWMAXIMIZED) + { + bIconic = FALSE; + bMaximized = TRUE; + } + else if (wndpl.showCmd == SW_SHOWMINIMIZED) + { + bIconic = TRUE; + if (wndpl.flags) + { + bMaximized = TRUE; + } + else + { + bMaximized = FALSE; + } + } + + strText.Format("%04d %04d %04d %04d", + wndpl.rcNormalPosition.left, + wndpl.rcNormalPosition.top, + wndpl.rcNormalPosition.right, + wndpl.rcNormalPosition.bottom); + + AfxGetApp()->WriteProfileString(s_profileHeading, + s_profileRect, strText); + + AfxGetApp()->WriteProfileInt(s_profileHeading, + s_profileIcon, bIconic); + + AfxGetApp()->WriteProfileInt(s_profileHeading, + s_profileMax, bMaximized); + + SaveBarState(AfxGetApp()->m_pszProfileName); + + CFrameWnd::OnDestroy(); +} + +/////////////////////////////////////////////////////////////// +void CLeashFrame::ActivateFrame(int nCmdShow) +{ + + if (m_bFirstTime) + { + m_bFirstTime = FALSE; + + LoadBarState(AfxGetApp()->m_pszProfileName); + } + + CFrameWnd::ActivateFrame(nCmdShow); +} diff --git a/src/windows/leash/LeashFrame.h b/src/windows/leash/LeashFrame.h new file mode 100644 index 000000000..6d45e7826 --- /dev/null +++ b/src/windows/leash/LeashFrame.h @@ -0,0 +1,50 @@ +// ************************************************************************************** +// File: LeashFrame.h +// By: Arthur David Leather +// Created: 12/02/98 +// Copyright @1998 Massachusetts Institute of Technology - All rights reserved. +// Description: H file for LeashFrame.cpp. Contains variables and functions +// for Leash +// +// History: +// +// MM/DD/YY Inits Description of Change +// 12/02/98 ADL Original +// ************************************************************************************** + + +#ifndef _LEASH_PERSISTENT_FRAME +#define _LEASH_PERSISTENT_FRAME + +class CLeashFrame : public CFrameWnd +{ // remembers where it was on the desktop + DECLARE_DYNAMIC(CLeashFrame) + static const CRect s_rectDefault; + static const char s_profileHeading[]; + static const char s_profileRect[]; + static const char s_profileIcon[]; + static const char s_profileMax[]; + static const char s_profileTool[]; + static const char s_profileStatus[]; + + private: + BOOL m_bFirstTime; + + protected: // Create from serialization only + CLeashFrame(); + ~CLeashFrame(); + + //{{AFX_VIRTUAL(CLeashFrame) + public: + virtual void ActivateFrame(int nCmdShow = -1); + protected: + //}}AFX_VIRTUAL + + //{{AFX_MSG(CLeashFrame) + afx_msg void OnDestroy(); + //}}AFX_MSG + + DECLARE_MESSAGE_MAP() +}; + +#endif // _LEASH_PERSISTENT_FRAME diff --git a/src/windows/leash/LeashMessageBox.cpp b/src/windows/leash/LeashMessageBox.cpp new file mode 100644 index 000000000..0fd218229 --- /dev/null +++ b/src/windows/leash/LeashMessageBox.cpp @@ -0,0 +1,83 @@ +// ************************************************************************************** +// File: LeashMessageBox.cpp +// By: Arthur David Leather +// Created: 12/02/98 +// Copyright @1998 Massachusetts Institute of Technology - All rights reserved. +// Description: CPP file for LeashMessageBox.h. Contains variables and functions +// for the Leash Special Message Dialog Box +// +// History: +// +// MM/DD/YY Inits Description of Change +// 12/02/98 ADL Original +// ************************************************************************************** + + + +#include "stdafx.h" +#include "leash.h" +#include "LeashMessageBox.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +DWORD CLeashMessageBox ::m_dwTime; + +///////////////////////////////////////////////////////////////////////////// +// CLeashMessageBox dialog + +CLeashMessageBox::CLeashMessageBox(CWnd* pParent, const CString msgText, DWORD dwTime) + : CDialog(CLeashMessageBox::IDD, pParent) +{ + m_dwTime = dwTime; + + //{{AFX_DATA_INIT(CLeashMessageBox) + m_messageText = _T(msgText); + //}}AFX_DATA_INIT +} + +CLeashMessageBox::~CLeashMessageBox() +{ +} + +void CLeashMessageBox::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CLeashMessageBox) + DDX_Text(pDX, IDC_LEASH_WARNING_MSG, m_messageText); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CLeashMessageBox, CDialog) + //{{AFX_MSG_MAP(CLeashMessageBox) + ON_WM_DESTROY() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CLeashMessageBox message handlers + +void CALLBACK CLeashMessageBox::MessageBoxTimer(HWND hwnd, UINT uiMsg, UINT idEvent, DWORD dwTime) +{ + ::KillTimer(hwnd, 2); + ::SendMessage(hwnd, WM_CLOSE, 0, 0); +} + +void CLeashMessageBox::OnOK() +{ + KillTimer(2); + SendMessage(WM_CLOSE, 0, 0); +} + +BOOL CLeashMessageBox::OnInitDialog() +{ + CDialog::OnInitDialog(); + UINT idTimer = SetTimer(2, m_dwTime, (TIMERPROC)MessageBoxTimer); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} diff --git a/src/windows/leash/LeashMessageBox.h b/src/windows/leash/LeashMessageBox.h new file mode 100644 index 000000000..57f1360a8 --- /dev/null +++ b/src/windows/leash/LeashMessageBox.h @@ -0,0 +1,70 @@ +// ************************************************************************************** +// File: LeashMessageBox.h +// By: Arthur David Leather +// Created: 12/02/98 +// Copyright @1998 Massachusetts Institute of Technology - All rights reserved. +// Description: H file for LeashMessageBox.cpp. Contains variables and functions +// for the Leash Special Message Dialog Box +// +// History: +// +// MM/DD/YY Inits Description of Change +// 12/02/98 ADL Original +// ************************************************************************************** + + +#if !defined(AFX_LEASHMESSAGEBOX_H__865865B6_56F6_11D2_945F_0000861B8A3C__INCLUDED_) +#define AFX_LEASHMESSAGEBOX_H__865865B6_56F6_11D2_945F_0000861B8A3C__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// LeashMessageBox.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CLeashMessageBox dialog + +#include "windows.h" + +class CLeashMessageBox : public CDialog +{ +private: + static DWORD m_dwTime; + static void CALLBACK MessageBoxTimer(HWND hwnd, UINT uiMsg, UINT idEvent, DWORD dwTime); + + // Construction +public: + CLeashMessageBox(CWnd* pParent = NULL, const CString msgText = "Place your message here!!!", + DWORD dwTime = 0); + ~CLeashMessageBox(); + +// Dialog Data + //{{AFX_DATA(CLeashMessageBox) + enum { IDD = IDD_MESSAGE_BOX }; + CString m_messageText; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CLeashMessageBox) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CLeashMessageBox) + virtual BOOL OnInitDialog(); + virtual void OnOK(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_LEASHMESSAGEBOX_H__865865B6_56F6_11D2_945F_0000861B8A3C__INCLUDED_) diff --git a/src/windows/leash/LeashProperties.cpp b/src/windows/leash/LeashProperties.cpp new file mode 100644 index 000000000..285423173 --- /dev/null +++ b/src/windows/leash/LeashProperties.cpp @@ -0,0 +1,202 @@ +// ************************************************************************************** +// File: LeashProperties.cpp +// By: Arthur David Leather +// Created: 12/02/98 +// Copyright @1998 Massachusetts Institute of Technology - All rights reserved. +// Description: CPP file for LeashProperties.h. Contains variables and functions +// for the Leash Properties Dialog Box +// +// History: +// +// MM/DD/YY Inits Description of Change +// 12/02/98 ADL Original +// ************************************************************************************** + +#include "stdafx.h" +#include "leash.h" +#include "LeashProperties.h" +#include "LeashMessageBox.h" +#include +#include "lglobals.h" +#include "reminder.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CLeashProperties dialog + +char CLeashProperties::timeServer[255] = {NULL}; + +CLeashProperties::CLeashProperties(CWnd* pParent /*=NULL*/) + : CDialog(CLeashProperties::IDD, pParent) +{ + m_initMissingFiles = m_newMissingFiles = 0; + dw_initMslsaImport = dw_newMslsaImport = 0; + + //{{AFX_DATA_INIT(CLeashProperties) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT +} + + +void CLeashProperties::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CLeashProperties) + // NOTE: the ClassWizard will add DDX and DDV calls here + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CLeashProperties, CDialog) + //{{AFX_MSG_MAP(CLeashProperties) + ON_BN_CLICKED(IDC_BUTTON_LEASHINI_HELP2, OnHelp) + ON_BN_CLICKED(IDC_CHECK_CREATE_MISSING_CFG, OnCheckMissingCfg) + ON_BN_CLICKED(IDC_RESET_DEFAULTS, OnButtonResetDefaults) + ON_BN_CLICKED(IDC_RADIO_MSLSA_IMPORT_OFF, OnRadioMslsaNever) + ON_BN_CLICKED(IDC_RADIO_MSLSA_IMPORT_ON, OnRadioMslsaAlways) + ON_BN_CLICKED(IDC_RADIO_MSLSA_IMPORT_MATCH, OnRadioMslsaMatchingRealm) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CLeashProperties message handlers + +BOOL CLeashProperties::OnInitDialog() +{ + CDialog::OnInitDialog(); + + pLeashGetTimeServerName(timeServer, TIMEHOST); + SetDlgItemText(IDC_EDIT_TIME_SERVER, timeServer); + + if (getenv(TIMEHOST)) + GetDlgItem(IDC_EDIT_TIME_SERVER)->EnableWindow(FALSE); + else + GetDlgItem(IDC_STATIC_TIMEHOST)->ShowWindow(FALSE); + + CWinApp * pApp = AfxGetApp(); + if (pApp) + m_initMissingFiles = m_newMissingFiles = + pApp->GetProfileInt("Settings", "CreateMissingConfig", FALSE_FLAG); + CheckDlgButton(IDC_CHECK_CREATE_MISSING_CFG, m_initMissingFiles); + + dw_initMslsaImport = dw_newMslsaImport = pLeash_get_default_mslsa_import(); + switch ( dw_initMslsaImport ) { + case 0: + CheckDlgButton(IDC_RADIO_MSLSA_IMPORT_OFF,TRUE); + break; + case 1: + CheckDlgButton(IDC_RADIO_MSLSA_IMPORT_ON,TRUE); + break; + case 2: + CheckDlgButton(IDC_RADIO_MSLSA_IMPORT_MATCH,TRUE); + break; + } + + return TRUE; +} + +void CLeashProperties::OnOK() +{ + CString timeServer_; + GetDlgItemText(IDC_EDIT_TIME_SERVER, timeServer_); + + if (getenv(TIMEHOST)) + { + // Check system for TIMEHOST, just in case it gets set (somehow) + MessageBox("Can't change the time host unless you remove it from the environment!", + "Error", MB_OK); + return; + } + + if( getenv("USEKRB4") != NULL) + { + MessageBox("Kerberos 4 ticket requests are being controlled by the environment" + "variable USEKRB4 instead of the registry. Leash cannot modify" + "the environment. Use the System control panel instead.", + "Leash", MB_OK); + return; + } + + if (SetRegistryVariable(TIMEHOST, timeServer_)) + { + MessageBox("There was an error putting your entry into the Registry!", + "Error", MB_OK); + } + + if ( m_initMissingFiles != m_newMissingFiles ) { + CWinApp * pApp = AfxGetApp(); + if (pApp) + pApp->WriteProfileInt("Settings", "CreateMissingConfig", + m_newMissingFiles ? TRUE_FLAG : FALSE_FLAG); + + if ( m_newMissingFiles ) + CLeashApp::ValidateConfigFiles(); + } + + if ( dw_initMslsaImport != dw_newMslsaImport ) { + pLeash_set_default_mslsa_import(dw_newMslsaImport); + } + + CDialog::OnOK(); +} + +void CLeashProperties::OnCheckMissingCfg() +{ + m_newMissingFiles = (BOOL)IsDlgButtonChecked(IDC_CHECK_CREATE_MISSING_CFG); +} + +void CLeashProperties::OnRadioMslsaNever() +{ + dw_newMslsaImport = 0; +} + +void CLeashProperties::OnRadioMslsaAlways() +{ + dw_newMslsaImport = 1; +} + +void CLeashProperties::OnRadioMslsaMatchingRealm() +{ + dw_newMslsaImport = 2; +} + +void CLeashProperties::OnHelp() +{ +#ifdef CALL_HTMLHELP + AfxGetApp()->HtmlHelp(HID_LEASH_PROPERTIES_COMMAND); +#else + AfxGetApp()->WinHelp(HID_LEASH_PROPERTIES_COMMAND); +#endif +} + +void CLeashProperties::OnButtonResetDefaults() +{ + if (IDYES != AfxMessageBox("You are about to reset all Leash settings to their default values!\n\nContinue?", + MB_YESNO)) + return; + + pLeash_reset_defaults(); + + HKEY hKey; + LONG rc; + + rc = RegOpenKeyEx(HKEY_CURRENT_USER, "SOFTWARE\\MIT\\Leash32\\Settings", + 0, KEY_WRITE, &hKey); + if (rc) + return; + + rc = RegDeleteValue(hKey, "AutoRenewTickets"); + rc = RegDeleteValue(hKey, "CreateMissingConfig"); + rc = RegDeleteValue(hKey, "DebugWindow"); + rc = RegDeleteValue(hKey, "LargeIcons"); + rc = RegDeleteValue(hKey, "TIMEHOST"); + rc = RegDeleteValue(hKey, "AfsStatus"); + rc = RegDeleteValue(hKey, "LowTicketAlarm"); + + RegCloseKey(hKey); +} diff --git a/src/windows/leash/LeashProperties.h b/src/windows/leash/LeashProperties.h new file mode 100644 index 000000000..314eba793 --- /dev/null +++ b/src/windows/leash/LeashProperties.h @@ -0,0 +1,78 @@ +// ************************************************************************************** +// File: LeashProperties.h +// By: Arthur David Leather +// Created: 12/02/98 +// Copyright @1998 Massachusetts Institute of Technology - All rights reserved. +// Description: H file for LeashProperties.cpp. Contains variables and functions +// for the Leash Properties Dialog Box +// +// History: +// +// MM/DD/YY Inits Description of Change +// 12/02/98 ADL Original +// ************************************************************************************** + +#if !defined(AFX_LEASHPROPERTIES_H__7E54E028_726E_11D2_945E_0000861B8A3C__INCLUDED_) +#define AFX_LEASHPROPERTIES_H__7E54E028_726E_11D2_945E_0000861B8A3C__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// LeashProperties.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CLeashProperties dialog + +#define TIMEHOST "TIMEHOST" + +class CLeashProperties : public CDialog +{ +private: + static char timeServer[255]; + CHAR sysDir[MAX_PATH]; + BOOL m_initMissingFiles; + BOOL m_newMissingFiles; + DWORD dw_initMslsaImport; + DWORD dw_newMslsaImport; + +// Construction +public: + CLeashProperties(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CLeashProperties) + enum { IDD = IDD_LEASH_PROPERTIES }; + // NOTE: the ClassWizard will add data members here + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CLeashProperties) + public: + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CLeashProperties) + virtual BOOL OnInitDialog(); + virtual void OnOK(); + afx_msg void OnHelp(); + afx_msg void OnCheckMissingCfg(); + afx_msg void OnRadioMslsaNever(); + afx_msg void OnRadioMslsaAlways(); + afx_msg void OnRadioMslsaMatchingRealm(); + afx_msg void OnButtonResetDefaults(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_LEASHPROPERTIES_H__7E54E028_726E_11D2_945E_0000861B8A3C__INCLUDED_) diff --git a/src/windows/leash/LeashView.cpp b/src/windows/leash/LeashView.cpp new file mode 100644 index 000000000..a2f93336b --- /dev/null +++ b/src/windows/leash/LeashView.cpp @@ -0,0 +1,2810 @@ +//***************************************************************************** +// File: LeashView.cpp +// By: Arthur David Leather +// Created: 12/02/98 +// Copyright @1998 Massachusetts Institute of Technology - All rights reserved. +// Description: CPP file for LeashView.h. Contains variables and functions +// for the Leash FormView +// +// History: +// +// MM/DD/YY Inits Description of Change +// 12/02/98 ADL Original +// 20030508 JEA Added +//***************************************************************************** + +#include "stdafx.h" +#include +#include "Leash.h" +#include "LeashDoc.h" +#include "LeashView.h" +#include "MainFrm.h" +#include "reminder.h" +#include "lglobals.h" +#include "LeashDebugWindow.h" +#include "LeashMessageBox.h" +#include "LeashAboutBox.h" +#include "Krb4Properties.h" +#include "Krb5Properties.h" +#include "LeashProperties.h" +#include "KrbProperties.h" +#include "AfsProperties.h" +#include + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static CHAR THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CLeashView + +IMPLEMENT_DYNCREATE(CLeashView, CFormView) + +BEGIN_MESSAGE_MAP(CLeashView, CFormView) + //{{AFX_MSG_MAP(CLeashView) + ON_MESSAGE(WM_GOODBYE, OnGoodbye) + ON_MESSAGE(WM_TRAYICON, OnTrayIcon) + ON_NOTIFY(TVN_ITEMEXPANDED, IDC_TREEVIEW, OnItemexpandedTreeview) + ON_WM_CREATE() + ON_WM_SHOWWINDOW() + ON_COMMAND(ID_INIT_TICKET, OnInitTicket) + ON_COMMAND(ID_RENEW_TICKET, OnRenewTicket) + ON_COMMAND(ID_IMPORT_TICKET, OnImportTicket) + ON_COMMAND(ID_DESTROY_TICKET, OnDestroyTicket) + ON_COMMAND(ID_CHANGE_PASSWORD, OnChangePassword) + ON_COMMAND(ID_UPDATE_DISPLAY, OnUpdateDisplay) + ON_COMMAND(ID_SYN_TIME, OnSynTime) + ON_COMMAND(ID_DEBUG_MODE, OnDebugMode) + ON_COMMAND(ID_LARGE_ICONS, OnLargeIcons) + ON_COMMAND(ID_UPPERCASE_REALM, OnUppercaseRealm) + ON_COMMAND(ID_KILL_TIX_ONEXIT, OnKillTixOnExit) + ON_WM_DESTROY() + ON_UPDATE_COMMAND_UI(ID_DESTROY_TICKET, OnUpdateDestroyTicket) + ON_UPDATE_COMMAND_UI(ID_IMPORT_TICKET, OnUpdateImportTicket) + ON_UPDATE_COMMAND_UI(ID_INIT_TICKET, OnUpdateInitTicket) + ON_UPDATE_COMMAND_UI(ID_RENEW_TICKET, OnUpdateRenewTicket) + ON_COMMAND(ID_APP_ABOUT, OnAppAbout) + ON_COMMAND(ID_AFS_CONTROL_PANEL, OnAfsControlPanel) + ON_UPDATE_COMMAND_UI(ID_DEBUG_MODE, OnUpdateDebugMode) + ON_UPDATE_COMMAND_UI(ID_CFG_FILES, OnUpdateCfgFiles) + ON_COMMAND(ID_KRB4_PROPERTIES, OnKrb4Properties) + ON_COMMAND(ID_KRB5_PROPERTIES, OnKrb5Properties) + ON_COMMAND(ID_LEASH_PROPERTIES, OnLeashProperties) + ON_COMMAND(ID_LEASH_RESTORE, OnLeashRestore) + ON_COMMAND(ID_LEASH_MINIMIZE, OnLeashMinimize) + ON_COMMAND(ID_LOW_TICKET_ALARM, OnLowTicketAlarm) + ON_COMMAND(ID_AUTO_RENEW, OnAutoRenew) + ON_UPDATE_COMMAND_UI(ID_KRB4_PROPERTIES, OnUpdateKrb4Properties) + ON_UPDATE_COMMAND_UI(ID_KRB5_PROPERTIES, OnUpdateKrb5Properties) + ON_UPDATE_COMMAND_UI(ID_AFS_CONTROL_PANEL, OnUpdateAfsControlPanel) + ON_COMMAND(ID_PROPERTIES, OnKrbProperties) + ON_UPDATE_COMMAND_UI(ID_PROPERTIES, OnUpdateProperties) + ON_COMMAND(ID_HELP_KERBEROS_, OnHelpKerberos) + ON_COMMAND(ID_HELP_LEASH32, OnHelpLeash32) + ON_COMMAND(ID_HELP_WHYUSELEASH32, OnHelpWhyuseleash32) + ON_WM_SIZE() + ON_WM_LBUTTONDOWN() + ON_WM_CLOSE() + ON_WM_HSCROLL() + ON_WM_VSCROLL() + ON_WM_SYSCOLORCHANGE() + ON_MESSAGE(ID_OBTAIN_TGT_WITH_LPARAM, OnObtainTGTWithParam) + //}}AFX_MSG_MAP + +END_MESSAGE_MAP() + + +LONG CLeashView::m_ticketTimeLeft = 0; // # of seconds left before tickets expire +INT CLeashView::m_forwardableTicket = 0; +INT CLeashView::m_proxiableTicket = 0; +INT CLeashView::m_renewableTicket = 0; +INT CLeashView::m_noaddressTicket = 0; +DWORD CLeashView::m_publicIPAddress = 0; +INT CLeashView::m_ticketStatusAfs = 0; // Defense Condition: are we low on tickets? +INT CLeashView::m_ticketStatusKrb4 = 0; // Defense Condition: are we low on tickets? +INT CLeashView::m_ticketStatusKrb5 = 0; // Defense Condition: are we low on tickets? +INT CLeashView::m_warningOfTicketTimeLeftAfs = 0; // Prevents warning box from coming up repeatively +INT CLeashView::m_warningOfTicketTimeLeftKrb4 = 0; // Prevents warning box from coming up repeatively +INT CLeashView::m_warningOfTicketTimeLeftKrb5 = 0; // Prevents warning box from coming up repeatively +INT CLeashView::m_warningOfTicketTimeLeftLockAfs = 0; +INT CLeashView::m_warningOfTicketTimeLeftLockKrb4 = 0; +INT CLeashView::m_warningOfTicketTimeLeftLockKrb5 = 0; +INT CLeashView::m_updateDisplayCount; +INT CLeashView::m_alreadyPlayedDisplayCount; +INT CLeashView::m_autoRenewTickets = 0; +BOOL CLeashView::m_lowTicketAlarmSound; +INT CLeashView::m_autoRenewalAttempted = 0; +BOOL CLeashView::m_importedTickets = 0; +LONG CLeashView::m_timerMsgNotInProgress = 1; + +bool change_icon_size = true; +#ifndef KRB5_TC_NOTICKET +extern HANDLE m_tgsReqMutex; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CLeashView construction/destruction + +CLeashView::CLeashView(): +CFormView(CLeashView::IDD) +{ + m_listKrb4 = NULL; + m_listKrb5 = NULL; + m_listAfs = NULL; + m_startup = TRUE; + m_warningOfTicketTimeLeftKrb4 = 0; + m_warningOfTicketTimeLeftKrb5 = 0; + m_warningOfTicketTimeLeftLockKrb4 = 0; + m_warningOfTicketTimeLeftLockKrb5 = 0; + m_largeIcons = 0; + m_destroyTicketsOnExit = 0; + m_debugWindow = 0; + m_upperCaseRealm = 0; + m_lowTicketAlarm = 0; + m_importedTickets = 0; + + m_pDebugWindow = NULL; + m_pDebugWindow = new CLeashDebugWindow(this); + if (!m_pDebugWindow) + { + AfxMessageBox("There is a problem with the Leash Debug Window!", + MB_OK|MB_ICONSTOP); + } + + m_debugStartUp = TRUE; + m_isMinimum = FALSE; + m_lowTicketAlarmSound = FALSE; + m_alreadyPlayed = FALSE; + ResetTreeNodes(); + m_pTree = NULL; + m_hMenu = NULL; + m_pApp = NULL; + m_pImageList = NULL; + m_forwardableTicket = 0; + m_proxiableTicket = 0; + m_renewableTicket = 0; + m_noaddressTicket = 0; + m_publicIPAddress = 0; + m_autoRenewTickets = 0; + m_autoRenewalAttempted = 0; + + m_bIconAdded = FALSE; + m_bIconDeleted = FALSE; +#ifndef KRB5_TC_NOTICKET + m_tgsReqMutex = CreateMutex(NULL, FALSE, NULL); +#endif +} + + +CLeashView::~CLeashView() +{ +#ifndef KRB5_TC_NOTICKET + CloseHandle(m_tgsReqMutex); +#endif + // destroys window if not already destroyed + if (m_pDebugWindow) + delete m_pDebugWindow; +} + +BOOL CLeashView::PreCreateWindow(CREATESTRUCT& cs) +{ + // TODO: Modify the Window class or styles here by modifying + // the CREATESTRUCT cs + + return CFormView::PreCreateWindow(cs); +} + +///////////////////////////////////////////////////////////////////////////// +// CLeashView diagnostics + +#ifdef _DEBUG +VOID CLeashView::AssertValid() const +{ + CFormView::AssertValid(); +} + +VOID CLeashView::Dump(CDumpContext& dc) const +{ + CFormView::Dump(dc); +} + +/* +LeashDoc* CLeashView::GetDocument() // non-debug version is inline +{ + ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(LeashDoc))); + return (LeashDoc*)m_pDocument; +} +*/ +#endif //_DEBUG + +///////////////////////////////////////////////////////////////////////////// +// CLeashView message handlers + +BOOL CLeashView::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, + DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, + UINT nID, CCreateContext* pContext) +{ + return CFormView::Create(lpszClassName, lpszWindowName, dwStyle, rect, + pParentWnd, nID, pContext); +} + +INT CLeashView::OnCreate(LPCREATESTRUCT lpCreateStruct) +{ + if (CFormView::OnCreate(lpCreateStruct) == -1) + return -1; + return 0; +} + +VOID CLeashView::OnClose(void) +{ + printf("OnClose\n"); +} + +LONG CLeashView::LeashTime() +{ + _tzset(); + return time(0); +} + +// Call while possessing a lock to ticketinfo.lockObj +INT CLeashView::GetLowTicketStatus(int ver) +{ + BOOL b_notix = (ver == 4 && !ticketinfo.Krb4.btickets) || + (ver == 5 && !ticketinfo.Krb5.btickets) || + (ver == 1 && !ticketinfo.Afs.btickets); + + if (b_notix) + return NO_TICKETS; + + if (m_ticketTimeLeft <= 0L) + return ZERO_MINUTES_LEFT; + + if (m_ticketTimeLeft <= 20 * 60) + return (INT)(m_ticketTimeLeft / 5 / 60) + 2 - + (m_ticketTimeLeft % (5 * 60) == 0 ? 1 : 0); + + return PLENTY_OF_TIME; +} + +VOID CLeashView::UpdateTicketTime(TICKETINFO& ti) +{ + if (!ti.btickets) + { + m_ticketTimeLeft = 0L; + return; + } + + m_ticketTimeLeft = ti.issue_date + ti.lifetime - + LeashTime(); + + if (m_ticketTimeLeft <= 0L) + ti.btickets = EXPIRED_TICKETS; +} + + +VOID CALLBACK EXPORT CLeashView::TimerProc(HWND hWnd, UINT nMsg, + UINT nIDEvent, DWORD dwTime) +{ + // All of the work is being done in the PreTranslateMessage method + // in order to have access to the object +} + +VOID CLeashView::ApplicationInfoMissingMsg() +{ + AfxMessageBox("There is a problem finding Leash application information!", + MB_OK|MB_ICONSTOP); +} + +VOID CLeashView::OnShowWindow(BOOL bShow, UINT nStatus) +{ + CFormView::OnShowWindow(bShow, nStatus); + + // Get State of Icons Size + m_pApp = AfxGetApp(); + if (!m_pApp) + { + ApplicationInfoMissingMsg(); + } + else + { + m_largeIcons = m_pApp->GetProfileInt("Settings", "LargeIcons", ON); + + // Get State of Destroy Tickets On Exit + m_destroyTicketsOnExit = m_pApp->GetProfileInt("Settings", "DestroyTicketsOnExit", OFF); + + // Get State of Low Ticket Alarm + m_lowTicketAlarm = m_pApp->GetProfileInt("Settings", "LowTicketAlarm", ON); + + // Get State of Auto Renew Tickets + m_autoRenewTickets = m_pApp->GetProfileInt("Settings", "AutoRenewTickets", ON); + + // Get State of Upper Case Realm + m_upperCaseRealm = pLeash_get_default_uppercaserealm(); + + // Forwardable flag + m_forwardableTicket = pLeash_get_default_forwardable(); + + // Proxiable flag + m_proxiableTicket = pLeash_get_default_proxiable(); + + // Renewable flag + m_renewableTicket = pLeash_get_default_renewable(); + + // No Address flag + m_noaddressTicket = pLeash_get_default_noaddresses(); + + // Public IP Address + m_publicIPAddress = pLeash_get_default_publicip(); + + OnLargeIcons(); + } + + SetTimer(1, ONE_SECOND, TimerProc); + + if (!CLeashApp::m_hKrb4DLL && !CLeashApp::m_hKrb5DLL && !CLeashApp::m_hAfsDLL) + { + AfxMessageBox("Neither Kerberos Four, Kerberos Five nor AFS is loaded!!!" + "\r\nYou will not be able to retrieve tickets and/or " + "tokens.", + MB_OK|MB_ICONWARNING); + } + + if (!CLeashApp::m_hAfsDLL) + { + // No AFS installed + SetDlgItemText(IDC_LABEL_KERB_TICKETS, + "Your Kerberos Tickets (Issued/Expires/[Renew]/Principal)"); + } else + { + // AFS installed + SetDlgItemText(IDC_LABEL_KERB_TICKETS, + "Your Kerberos Tickets and AFS Tokens (Issued/Expires/[Renew]/Principal)"); + + } + + // CLeashApp::m_krbv5_context = NULL; +} + +VOID CLeashView::OnInitTicket() +{ + try { + InitTicket(m_hWnd); + } + catch(...) { + AfxMessageBox("Ticket Getting operation already in progress", MB_OK, 0); + } +} + +UINT CLeashView::InitTicket(void * hWnd) +{ +#ifndef KRB5_TC_NOTICKET + if (WaitForSingleObject( m_tgsReqMutex, INFINITE ) != WAIT_OBJECT_0) + throw("Unable to lock TGS request mutex"); +#endif + m_importedTickets = 0; + + LSH_DLGINFO_EX ldi; + char username[64]; + char realm[192]; + int i=0, j=0; + if (WaitForSingleObject( ticketinfo.lockObj, INFINITE ) != WAIT_OBJECT_0) { +#ifndef KRB5_TC_NOTICKET + ReleaseMutex(m_tgsReqMutex); +#endif + throw("Unable to lock ticketinfo"); + } + + char * principal = ticketinfo.Krb5.principal; + if (!*principal) + principal = ticketinfo.Krb4.principal; + for (; principal[i] && principal[i] != '@'; i++) + { + username[i] = principal[i]; + } + username[i] = '\0'; + if (principal[i]) { + for (i++ ; principal[i] ; i++, j++) + { + realm[j] = principal[i]; + } + } + realm[j] = '\0'; + ReleaseMutex(ticketinfo.lockObj); + + ldi.size = sizeof(ldi); + ldi.dlgtype = DLGTYPE_PASSWD; + ldi.title = ldi.in.title; + strcpy(ldi.in.title,"Initialize Ticket"); + ldi.username = ldi.in.username; + strcpy(ldi.in.username,username); + ldi.realm = ldi.in.realm; + strcpy(ldi.in.realm,realm); + ldi.dlgtype = DLGTYPE_PASSWD; + ldi.use_defaults = 1; + + if (!hWnd) + { + AfxMessageBox("There is a problem finding the Leash Window!", + MB_OK|MB_ICONSTOP); +#ifndef KRB5_TC_NOTICKET + ReleaseMutex(m_tgsReqMutex); +#endif + return 0; + } + +#ifndef KRB5_TC_NOTICKET + ReleaseMutex(m_tgsReqMutex); +#endif + int result = pLeash_kinit_dlg_ex((HWND)hWnd, &ldi); + + if (-1 == result) + { + AfxMessageBox("There is a problem getting tickets!", + MB_OK|MB_ICONSTOP); + } + else if ( result ) + { +#ifndef KRB5_TC_NOTICKET + if (WaitForSingleObject( m_tgsReqMutex, INFINITE ) != WAIT_OBJECT_0) + throw("Unable to lock TGS request mutex"); +#endif + if (WaitForSingleObject( ticketinfo.lockObj, INFINITE ) != WAIT_OBJECT_0) { +#ifndef KRB5_TC_NOTICKET + ReleaseMutex(m_tgsReqMutex); +#endif + throw("Unable to lock ticketinfo"); + } + ticketinfo.Krb4.btickets = GOOD_TICKETS; + m_warningOfTicketTimeLeftKrb4 = 0; + m_warningOfTicketTimeLeftKrb5 = 0; + m_ticketStatusKrb4 = 0; + m_ticketStatusKrb5 = 0; + ReleaseMutex(ticketinfo.lockObj); + m_autoRenewalAttempted = 0; +#ifndef KRB5_TC_NOTICKET + ReleaseMutex(m_tgsReqMutex); +#endif + ::SendMessage((HWND)hWnd, WM_COMMAND, ID_UPDATE_DISPLAY, 0); + } + return 0; +} + +VOID CLeashView::OnImportTicket() +{ + try { + ImportTicket(m_hWnd); + } + catch(...) { + AfxMessageBox("Ticket Getting operation already in progress", MB_OK|MB_ICONWARNING, 0); + } +} + +UINT CLeashView::ImportTicket(void * hWnd) +{ + if ( !CLeashApp::m_hKrb5DLL ) + return 0; + +#ifndef KRB5_TC_NOTICKET + if (WaitForSingleObject( m_tgsReqMutex, INFINITE ) != WAIT_OBJECT_0) + throw("Unable to lock TGS request mutex"); +#endif + int import = 0; + int warning = 0; + + krb5_error_code code; + krb5_ccache mslsa_ccache=0; + krb5_principal princ = 0; + char * pname = 0; + LONG krb5Error = 0; + TicketList * tlist = NULL; + + if (code = pkrb5_cc_resolve(CLeashApp::m_krbv5_context, "MSLSA:", &mslsa_ccache)) + goto cleanup; + + if (code = pkrb5_cc_get_principal(CLeashApp::m_krbv5_context, mslsa_ccache, &princ)) + goto cleanup; + + if (code = pkrb5_unparse_name(CLeashApp::m_krbv5_context, princ, &pname)) + goto cleanup; + + if (WaitForSingleObject( ticketinfo.lockObj, INFINITE ) != WAIT_OBJECT_0) { +#ifndef KRB5_TC_NOTICKET + ReleaseMutex(m_tgsReqMutex); +#endif + throw("Unable to lock ticketinfo"); + } + krb5Error = pLeashKRB5GetTickets( &ticketinfo.Krb5, &tlist, + &CLeashApp::m_krbv5_context); + if ( tlist ) + pLeashFreeTicketList(&tlist); + + warning = strcmp(ticketinfo.Krb5.principal, pname) && ticketinfo.Krb5.btickets; + ReleaseMutex(ticketinfo.lockObj); + + cleanup: + if (pname) + pkrb5_free_unparsed_name(CLeashApp::m_krbv5_context, pname); + + if (princ) + pkrb5_free_principal(CLeashApp::m_krbv5_context, princ); + + if (mslsa_ccache) + pkrb5_cc_close(CLeashApp::m_krbv5_context, mslsa_ccache); + + if ( code == 0 ) { + if (warning) + { + INT whatToDo; +#ifndef KRB5_TC_NOTICKET + ReleaseMutex(m_tgsReqMutex); +#endif + if (!CLeashApp::m_hAfsDLL || !CLeashApp::m_hKrb4DLL) + whatToDo = AfxMessageBox("You are about to replace your existing ticket(s)\n" + "with a ticket imported from the Windows credential cache!", + MB_OKCANCEL, 0); + else + whatToDo = AfxMessageBox("You are about to replace your existing ticket(s)/token(s)" + "with ticket imported from the Windows credential cache!", + MB_OKCANCEL, 0); +#ifndef KRB5_TC_NOTICKET + if (WaitForSingleObject( m_tgsReqMutex, INFINITE ) != WAIT_OBJECT_0) + throw("Unable to lock tgsReqMutex"); +#endif + if (whatToDo == IDOK) + { + pLeash_kdestroy(); + import = 1; + } + } else { + import = 1; + } + + if ( import ) { + int result = pLeash_import(); + if (-1 == result) + { +#ifndef KRB5_TC_NOTICKET + ReleaseMutex(m_tgsReqMutex); +#endif + AfxMessageBox("There is a problem importing tickets!", + MB_OK|MB_ICONSTOP); + ::SendMessage((HWND)hWnd,WM_COMMAND, ID_UPDATE_DISPLAY, 0); + m_importedTickets = 0; + } + else + { + if (WaitForSingleObject( ticketinfo.lockObj, INFINITE ) != WAIT_OBJECT_0) { +#ifndef KRB5_TC_NOTICKET + ReleaseMutex(m_tgsReqMutex); +#endif + throw("Unable to lock ticketinfo"); + } + ticketinfo.Krb4.btickets = GOOD_TICKETS; + ticketinfo.Krb5.btickets = GOOD_TICKETS; + m_warningOfTicketTimeLeftKrb4 = 0; + m_warningOfTicketTimeLeftKrb5 = 0; + m_ticketStatusKrb4 = 0; + m_ticketStatusKrb5 = 0; + ReleaseMutex(ticketinfo.lockObj); +#ifndef KRB5_TC_NOTICKET + ReleaseMutex(m_tgsReqMutex); +#endif + ::SendMessage((HWND)hWnd, WM_COMMAND, ID_UPDATE_DISPLAY, 0); + +#ifndef KRB5_TC_NOTICKET + if (WaitForSingleObject( m_tgsReqMutex, INFINITE ) != WAIT_OBJECT_0) + throw("Unable to lock tgsReqMutex"); +#endif + if (WaitForSingleObject( ticketinfo.lockObj, INFINITE ) != WAIT_OBJECT_0) { +#ifndef KRB5_TC_NOTICKET + ReleaseMutex(m_tgsReqMutex); +#endif + throw("Unable to lock ticketinfo"); + } +#ifndef KRB5_TC_NOTICKET + ReleaseMutex(m_tgsReqMutex); +#endif + + if (ticketinfo.Krb5.btickets != GOOD_TICKETS) { + ReleaseMutex(ticketinfo.lockObj); + AfxBeginThread(InitTicket,hWnd); + } else { + ReleaseMutex(ticketinfo.lockObj); + m_importedTickets = 1; + m_autoRenewalAttempted = 0; + } + } + } +#ifndef KRB5_TC_NOTICKET + else { + ReleaseMutex(m_tgsReqMutex); + } +#endif + } +#ifndef KRB5_TC_NOTICKET + else { + ReleaseMutex(m_tgsReqMutex); + } +#endif + return 0; +} + +VOID CLeashView::OnRenewTicket() +{ + if ( !CLeashApp::m_hKrb5DLL ) + return; + + try { + RenewTicket(m_hWnd); + } + catch(...) { + AfxMessageBox("Ticket Getting operation already in progress", MB_OK|MB_ICONWARNING, 0); + } +} + +UINT CLeashView::RenewTicket(void * hWnd) +{ + if ( !CLeashApp::m_hKrb5DLL ) + return 0; + +#ifndef KRB5_TC_NOTICKET + if (WaitForSingleObject( m_tgsReqMutex, INFINITE ) != WAIT_OBJECT_0) + throw("Unable to lock TGS request mutex"); +#endif + + // Try to renew + BOOL b_renewed = pLeash_renew(); + TicketList * tlist = NULL; + if (WaitForSingleObject( ticketinfo.lockObj, INFINITE ) != WAIT_OBJECT_0) { +#ifndef KRB5_TC_NOTICKET + ReleaseMutex(m_tgsReqMutex); +#endif + throw("Unable to lock ticketinfo"); + } + LONG krb5Error = pLeashKRB5GetTickets(&ticketinfo.Krb5, &tlist, + &CLeashApp::m_krbv5_context); + pLeashFreeTicketList(&tlist); + if ( b_renewed ) { + if (!krb5Error && ticketinfo.Krb5.btickets == GOOD_TICKETS) { + ticketinfo.Krb4.btickets = GOOD_TICKETS; + m_warningOfTicketTimeLeftKrb4 = 0; + m_warningOfTicketTimeLeftKrb5 = 0; + m_ticketStatusKrb4 = 0; + m_ticketStatusKrb5 = 0; + m_autoRenewalAttempted = 0; + ReleaseMutex(ticketinfo.lockObj); +#ifndef KRB5_TC_NOTICKET + ReleaseMutex(m_tgsReqMutex); +#endif + ::SendMessage((HWND)hWnd, WM_COMMAND, ID_UPDATE_DISPLAY, 0); + return 0; + } + } + + krb5_error_code code; + krb5_ccache mslsa_ccache=0; + krb5_principal princ = 0; + char * pname = 0; + + if (code = pkrb5_cc_resolve(CLeashApp::m_krbv5_context, "MSLSA:", &mslsa_ccache)) + goto cleanup; + + if (code = pkrb5_cc_get_principal(CLeashApp::m_krbv5_context, mslsa_ccache, &princ)) + goto cleanup; + + if (code = pkrb5_unparse_name(CLeashApp::m_krbv5_context, princ, &pname)) + goto cleanup; + + if ( !strcmp(ticketinfo.Krb5.principal, pname) ) + m_importedTickets = 1; + + cleanup: + ReleaseMutex(ticketinfo.lockObj); + + if (pname) + pkrb5_free_unparsed_name(CLeashApp::m_krbv5_context, pname); + + if (princ) + pkrb5_free_principal(CLeashApp::m_krbv5_context, princ); + + if (mslsa_ccache) + pkrb5_cc_close(CLeashApp::m_krbv5_context, mslsa_ccache); + +#ifndef KRB5_TC_NOTICKET + ReleaseMutex(m_tgsReqMutex); +#endif + // If imported from Kerberos LSA, re-import + // Otherwise, init the tickets + if ( m_importedTickets ) + AfxBeginThread(ImportTicket,hWnd); + else + AfxBeginThread(InitTicket,hWnd); + + return 0; +} + +VOID CLeashView::OnDestroyTicket() +{ + if (WaitForSingleObject( ticketinfo.lockObj, INFINITE ) != WAIT_OBJECT_0) + throw("Unable to lock ticketinfo"); + BOOL b_destroy =ticketinfo.Krb4.btickets || ticketinfo.Krb5.btickets || ticketinfo.Afs.btickets; + ReleaseMutex(ticketinfo.lockObj); + + if (b_destroy) + { + INT whatToDo; + + if (!CLeashApp::m_hAfsDLL) + whatToDo = AfxMessageBox("You are about to destroy your ticket(s)!", + MB_OKCANCEL, 0); + else + whatToDo = AfxMessageBox("You are about to destroy your ticket(s)/token(s)!", + MB_OKCANCEL, 0); + + if (whatToDo == IDOK) + { + pLeash_kdestroy(); + ResetTreeNodes(); + SendMessage(WM_COMMAND, ID_UPDATE_DISPLAY, 0); + } + } + m_importedTickets = 0; + m_autoRenewalAttempted = 0; +} + +VOID CLeashView::OnChangePassword() +{ + if (!m_hWnd) + { + AfxMessageBox("There is a problem finding the Leash Window!", + MB_OK|MB_ICONSTOP); + return; + } + + if (WaitForSingleObject( ticketinfo.lockObj, INFINITE ) != WAIT_OBJECT_0) + throw("Unable to lock ticketinfo"); + + LSH_DLGINFO_EX ldi; + char username[64]; + char realm[192]; + char * principal = ticketinfo.Krb5.principal; + if (!*principal) + principal = ticketinfo.Krb4.principal; + int i=0, j=0; + for (; principal[i] && principal[i] != '@'; i++) + { + username[i] = principal[i]; + } + username[i] = '\0'; + if (principal[i]) { + for (i++ ; principal[i] ; i++, j++) + { + realm[j] = principal[i]; + } + } + realm[j] = '\0'; + ReleaseMutex(ticketinfo.lockObj); + + ldi.size = sizeof(ldi); + ldi.dlgtype = DLGTYPE_CHPASSWD; + ldi.title = ldi.in.title; + strcpy(ldi.in.title,"Change Password"); + ldi.username = ldi.in.username; + strcpy(ldi.in.username,username); + ldi.realm = ldi.in.realm; + strcpy(ldi.in.realm,realm); + ldi.use_defaults = 1; + + int result = pLeash_changepwd_dlg_ex(m_hWnd, &ldi); + if (-1 == result) + { + AfxMessageBox("There is a problem changing password!", + MB_OK|MB_ICONSTOP); + } +} + +VOID CLeashView::OnUpdateDisplay() +{ + BOOL AfsEnabled = m_pApp->GetProfileInt("Settings", "AfsStatus", 1); + + m_pTree = (CTreeCtrl*) GetDlgItem(IDC_TREEVIEW); + if (!m_pTree) + { + AfxMessageBox("There is a problem finding the Ticket Tree!", + MB_OK|MB_ICONSTOP); + return; + } + + m_pImageList = &m_imageList; + if (!m_pImageList) + { + AfxMessageBox("There is a problem finding images for the Ticket Tree!", + MB_OK|MB_ICONSTOP); + return; + } + + m_pTree->SetImageList(&m_imageList, TVSIL_NORMAL); + + TV_INSERTSTRUCT m_tvinsert; + + INT ticketIconStatusKrb4; + INT ticketIconStatus_SelectedKrb4; + INT iconStatusKrb4; + + INT ticketIconStatusKrb5; + INT ticketIconStatus_SelectedKrb5; + INT iconStatusKrb5; + + INT ticketIconStatusAfs; + INT ticketIconStatus_SelectedAfs; + INT iconStatusAfs; + + LONG krb4Error; + LONG krb5Error; + LONG afsError; + + if (WaitForSingleObject( ticketinfo.lockObj, 100 ) != WAIT_OBJECT_0) + throw("Unable to lock ticketinfo"); + + // Get Kerb 4 tickets in list + krb4Error = pLeashKRB4GetTickets(&ticketinfo.Krb4, &m_listKrb4); + + // Get Kerb 5 tickets in list + krb5Error = pLeashKRB5GetTickets(&ticketinfo.Krb5, &m_listKrb5, + &CLeashApp::m_krbv5_context); + if (!krb5Error || krb5Error == KRB5_FCC_NOFILE) + { + if (CLeashApp::m_hKrb5DLL && !CLeashApp::m_krbv5_profile) + { + CHAR confname[MAX_PATH]; + if (CLeashApp::GetProfileFile(confname, sizeof(confname))) + { + AfxMessageBox("Can't locate Kerberos Five Config. file!", + MB_OK|MB_ICONSTOP); + } + + const char *filenames[2]; + filenames[0] = confname; + filenames[1] = NULL; + pprofile_init(filenames, &CLeashApp::m_krbv5_profile); + } + } + + // Get AFS Tokens in list + if (CLeashApp::m_hAfsDLL) { + char * principal; + if ( ticketinfo.Krb5.principal[0] ) + principal = ticketinfo.Krb5.principal; + else if ( ticketinfo.Krb4.principal[0] ) + principal = ticketinfo.Krb4.principal; + else + principal = ""; + afsError = pLeashAFSGetToken(&ticketinfo.Afs, &m_listAfs, principal); + } + + /* + * Update Ticket Status for Krb4 and Krb5 so that we may use their state + * to select the appropriate Icon for the Parent Node + */ + + /* Krb4 */ + UpdateTicketTime(ticketinfo.Krb4); + m_ticketStatusKrb4 = GetLowTicketStatus(4); + if (!m_listKrb4 || EXPIRED_TICKETS == ticketinfo.Krb4.btickets || + m_ticketStatusKrb4 == ZERO_MINUTES_LEFT) + { + ticketIconStatusKrb4 = EXPIRED_CLOCK; + ticketIconStatus_SelectedKrb4 = EXPIRED_CLOCK; + iconStatusKrb4 = EXPIRED_TICKET; + } + else if (TICKETS_LOW == ticketinfo.Krb4.btickets || + m_ticketStatusKrb4 == FIVE_MINUTES_LEFT || + m_ticketStatusKrb4 == TEN_MINUTES_LEFT || + m_ticketStatusKrb4 == FIFTEEN_MINUTES_LEFT) + { + ticketIconStatusKrb4 = LOW_CLOCK; + ticketIconStatus_SelectedKrb4 = LOW_CLOCK; + iconStatusKrb4 = LOW_TICKET; + } + else if ( CLeashApp::m_hKrb4DLL ) + { + ticketIconStatusKrb4 = ACTIVE_CLOCK; + ticketIconStatus_SelectedKrb4 = ACTIVE_CLOCK; + iconStatusKrb4 = ACTIVE_TICKET; + } else { + ticketIconStatusKrb4 = EXPIRED_CLOCK; + ticketIconStatus_SelectedKrb4 = EXPIRED_CLOCK; + iconStatusKrb4 = TICKET_NOT_INSTALLED; + } + + /* Krb5 */ + UpdateTicketTime(ticketinfo.Krb5); + m_ticketStatusKrb5 = GetLowTicketStatus(5); + if (!m_listKrb5 || EXPIRED_TICKETS == ticketinfo.Krb5.btickets || + m_ticketStatusKrb5 == ZERO_MINUTES_LEFT) + { + ticketIconStatusKrb5 = EXPIRED_CLOCK; + ticketIconStatus_SelectedKrb5 = EXPIRED_CLOCK; + iconStatusKrb5 = EXPIRED_TICKET; + } + else if (TICKETS_LOW == ticketinfo.Krb5.btickets || + m_ticketStatusKrb5 == FIVE_MINUTES_LEFT || + m_ticketStatusKrb5 == TEN_MINUTES_LEFT || + m_ticketStatusKrb5 == FIFTEEN_MINUTES_LEFT) + { + ticketIconStatusKrb5 = LOW_CLOCK; + ticketIconStatus_SelectedKrb5 = LOW_CLOCK; + iconStatusKrb5 = LOW_TICKET; + } + else if ( CLeashApp::m_hKrb5DLL ) + { + ticketIconStatusKrb5 = ACTIVE_CLOCK; + ticketIconStatus_SelectedKrb5 = ACTIVE_CLOCK; + iconStatusKrb5 = ACTIVE_TICKET; + } else + { + ticketIconStatusKrb5 = EXPIRED_CLOCK; + ticketIconStatus_SelectedKrb5 = EXPIRED_CLOCK; + iconStatusKrb5 = TICKET_NOT_INSTALLED; + } + + /* Afs */ + UpdateTicketTime(ticketinfo.Afs); + m_ticketStatusAfs = GetLowTicketStatus(1); + if (!m_listAfs || EXPIRED_TICKETS == ticketinfo.Afs.btickets || + m_ticketStatusAfs == ZERO_MINUTES_LEFT) + { + ticketIconStatusAfs = EXPIRED_CLOCK; + ticketIconStatus_SelectedAfs = EXPIRED_CLOCK; + iconStatusAfs = EXPIRED_TICKET; + } + else if (TICKETS_LOW == ticketinfo.Afs.btickets || + m_ticketStatusAfs == FIVE_MINUTES_LEFT || + m_ticketStatusAfs == TEN_MINUTES_LEFT || + m_ticketStatusAfs == FIFTEEN_MINUTES_LEFT) + { + ticketIconStatusAfs = LOW_CLOCK; + ticketIconStatus_SelectedAfs = LOW_CLOCK; + iconStatusAfs = LOW_TICKET; + } + else if ( CLeashApp::m_hAfsDLL ) + { + ticketIconStatusAfs = ACTIVE_CLOCK; + ticketIconStatus_SelectedAfs = ACTIVE_CLOCK; + iconStatusAfs = ACTIVE_TICKET; + } else + { + ticketIconStatusAfs = EXPIRED_CLOCK; + ticketIconStatus_SelectedAfs = EXPIRED_CLOCK; + iconStatusAfs = TICKET_NOT_INSTALLED; + } + + // Tree Structure common values + m_pTree->DeleteAllItems(); + + m_tvinsert.hParent = NULL; + m_tvinsert.hInsertAfter = TVI_LAST; + m_tvinsert.item.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_TEXT; + m_tvinsert.item.hItem = NULL; + m_tvinsert.item.state = 0; + m_tvinsert.item.stateMask = 0; //TVIS_EXPANDED; + m_tvinsert.item.cchTextMax = 6; + + if (CLeashApp::m_hKrb5DLL && m_listKrb5) { + m_tvinsert.item.pszText = ticketinfo.Krb5.principal; + switch ( iconStatusKrb5 ) { + case ACTIVE_TICKET: + m_tvinsert.item.iSelectedImage = ACTIVE_PARENT_NODE; + break; + case LOW_TICKET: + m_tvinsert.item.iSelectedImage = LOW_PARENT_NODE; + break; + case EXPIRED_TICKET: + m_tvinsert.item.iSelectedImage = EXPIRED_PARENT_NODE; + break; + } + } else if (CLeashApp::m_hKrb4DLL && m_listKrb4) { + m_tvinsert.item.pszText = ticketinfo.Krb4.principal; + switch ( iconStatusKrb4 ) { + case ACTIVE_TICKET: + m_tvinsert.item.iSelectedImage = ACTIVE_PARENT_NODE; + break; + case LOW_TICKET: + m_tvinsert.item.iSelectedImage = LOW_PARENT_NODE; + break; + case EXPIRED_TICKET: + m_tvinsert.item.iSelectedImage = EXPIRED_PARENT_NODE; + break; + } + } else { + m_tvinsert.item.iSelectedImage = NONE_PARENT_NODE; + } + m_tvinsert.item.iImage = m_tvinsert.item.iSelectedImage; + m_tvinsert.item.cChildren = 0; + m_tvinsert.item.lParam = 0; + m_tvinsert.hParent = NULL; + m_hPrincipal = m_pTree->InsertItem(&m_tvinsert); + + SetTrayIcon(NIM_MODIFY, m_tvinsert.item.iImage); + + // Krb5 + m_tvinsert.hParent = m_hPrincipal; + + if (CLeashApp::m_hKrb5DLL) + { + // kerb5 installed + m_tvinsert.item.pszText = "Kerberos Five Tickets"; + m_tvinsert.item.iImage = iconStatusKrb5; + m_tvinsert.item.iSelectedImage = iconStatusKrb5; + } + else + { + // kerb5 not installed + ticketinfo.Krb5.btickets = NO_TICKETS; + m_tvinsert.item.pszText = "Kerberos Five Tickets (Not Available)"; + m_tvinsert.item.iImage = TICKET_NOT_INSTALLED; + m_tvinsert.item.iSelectedImage = TICKET_NOT_INSTALLED; + } + + m_hKerb5 = m_pTree->InsertItem(&m_tvinsert); + + TicketList* tempList = m_listKrb5, *killList; + while (tempList) + { + m_tvinsert.hParent = m_hKerb5; + m_tvinsert.item.iImage = ticketIconStatusKrb5; + m_tvinsert.item.iSelectedImage = ticketIconStatus_SelectedKrb5; + m_tvinsert.item.pszText = tempList->theTicket; + m_hk5tkt = m_pTree->InsertItem(&m_tvinsert); + + if ( tempList->tktEncType ) { + m_tvinsert.hParent = m_hk5tkt; + m_tvinsert.item.iImage = TKT_ENCRYPTION; + m_tvinsert.item.iSelectedImage = TKT_ENCRYPTION; + m_tvinsert.item.pszText = tempList->tktEncType; + m_pTree->InsertItem(&m_tvinsert); + } + if ( tempList->keyEncType ) { + m_tvinsert.hParent = m_hk5tkt; + m_tvinsert.item.iImage = TKT_SESSION; + m_tvinsert.item.iSelectedImage = TKT_SESSION; + m_tvinsert.item.pszText = tempList->keyEncType; + m_pTree->InsertItem(&m_tvinsert); + } + + if ( tempList->addrCount && tempList->addrList ) { + for ( int n=0; naddrCount; n++ ) { + m_tvinsert.hParent = m_hk5tkt; + m_tvinsert.item.iImage = TKT_ADDRESS; + m_tvinsert.item.iSelectedImage = TKT_ADDRESS; + m_tvinsert.item.pszText = tempList->addrList[n]; + m_pTree->InsertItem(&m_tvinsert); + } + } + tempList = tempList->next; + } + + pLeashFreeTicketList(&m_listKrb5); + + if (m_hKerb5State == NODE_IS_EXPANDED) + m_pTree->Expand(m_hKerb5, TVE_EXPAND); + + // Krb4 + m_tvinsert.hParent = m_hPrincipal; + + if (CLeashApp::m_hKrb4DLL) + { + m_tvinsert.item.pszText = "Kerberos Four Tickets"; + m_tvinsert.item.iImage = iconStatusKrb4; + m_tvinsert.item.iSelectedImage = iconStatusKrb4; + } + else + { + ticketinfo.Krb4.btickets = NO_TICKETS; + m_tvinsert.item.pszText = "Kerberos Four Tickets (Not Available)"; + m_tvinsert.item.iImage = TICKET_NOT_INSTALLED; + m_tvinsert.item.iSelectedImage = TICKET_NOT_INSTALLED; + } + + m_hKerb4 = m_pTree ->InsertItem(&m_tvinsert); + + if (m_hPrincipalState == NODE_IS_EXPANDED) + m_pTree->Expand(m_hPrincipal, TVE_EXPAND); + + m_tvinsert.hParent = m_hKerb4; + m_tvinsert.item.iImage = ticketIconStatusKrb4; + m_tvinsert.item.iSelectedImage = ticketIconStatus_SelectedKrb4; + + tempList = m_listKrb4, *killList; + while (tempList) + { + m_tvinsert.item.pszText = tempList->theTicket; + m_pTree->InsertItem(&m_tvinsert); + tempList = tempList->next; + } + + pLeashFreeTicketList(&m_listKrb4); + + if (m_hKerb4State == NODE_IS_EXPANDED) + m_pTree->Expand(m_hKerb4, TVE_EXPAND); + + + // AFS + m_tvinsert.hParent = m_hPrincipal; + + if (!CLeashApp::m_hAfsDLL) + { // AFS service not started or just no tickets + m_tvinsert.item.pszText = "AFS Tokens (Not Available)"; + m_tvinsert.item.iImage = TICKET_NOT_INSTALLED; + m_tvinsert.item.iSelectedImage = TICKET_NOT_INSTALLED; + } + + if (!afsError && CLeashApp::m_hAfsDLL && m_tvinsert.item.pszText) + { // AFS installed + + if (AfsEnabled) + { + m_tvinsert.item.pszText = "AFS Tokens"; + m_tvinsert.item.iImage = iconStatusAfs; + m_tvinsert.item.iSelectedImage = iconStatusAfs; + } + else + { + m_tvinsert.item.pszText = "AFS Tokens (Disabled)"; + m_tvinsert.item.iImage = TICKET_NOT_INSTALLED; + m_tvinsert.item.iSelectedImage = TICKET_NOT_INSTALLED; + } + + m_hAFS = m_pTree->InsertItem(&m_tvinsert); + + m_tvinsert.hParent = m_hAFS; + m_tvinsert.item.iImage = ticketIconStatusAfs; + m_tvinsert.item.iSelectedImage = ticketIconStatus_SelectedAfs; + + tempList = m_listAfs, *killList; + while (tempList) + { + m_tvinsert.item.pszText = tempList->theTicket; + m_pTree->InsertItem(&m_tvinsert); + tempList = tempList->next; + } + + pLeashFreeTicketList(&m_listAfs); + + if (m_hAFSState == NODE_IS_EXPANDED) + m_pTree->Expand(m_hAFS, TVE_EXPAND); + } + else if (!afsError && CLeashApp::m_hAfsDLL && !m_tvinsert.item.pszText) + { + m_tvinsert.item.pszText = "AFS Tokens"; + m_tvinsert.item.iImage = EXPIRED_TICKET;; + m_tvinsert.item.iSelectedImage = EXPIRED_TICKET; + } + + if (m_startup) + { + //m_startup = FALSE; + UpdateTicketTime(ticketinfo.Krb4); + } + + CString sPrincipal = ticketinfo.Krb5.principal; + if (sPrincipal.IsEmpty()) + sPrincipal = ticketinfo.Krb4.principal; + + // if no tickets + if (!ticketinfo.Krb4.btickets && !ticketinfo.Krb5.btickets) + sPrincipal = " No Tickets "; + + // if no tickets and tokens + if (!ticketinfo.Krb4.btickets && !ticketinfo.Krb5.btickets && !ticketinfo.Afs.btickets) //&& sPrincipal.IsEmpty()) + { + // No tickets + m_pTree->DeleteAllItems(); + + m_tvinsert.hParent = NULL; + m_tvinsert.item.pszText = " No Tickets/Tokens "; + m_tvinsert.item.iImage = NONE_PARENT_NODE; + m_tvinsert.item.iSelectedImage = NONE_PARENT_NODE; + m_hPrincipal = m_pTree->InsertItem(&m_tvinsert); + + if (CMainFrame::m_wndToolBar) + { + CToolBarCtrl *_toolBar = NULL; + CToolBarCtrl& toolBar = CMainFrame::m_wndToolBar.GetToolBarCtrl(); + _toolBar = &toolBar; + if (_toolBar) + { + toolBar.SetState(ID_DESTROY_TICKET, TBSTATE_INDETERMINATE); + } + else + { + AfxMessageBox("There is a problem with the Leash Toolbar!", + MB_OK|MB_ICONSTOP); + } + } + } + else + { + // We have some tickets + m_pTree->SetItemText(m_hPrincipal, sPrincipal); + + if (CMainFrame::m_wndToolBar) + { + CToolBarCtrl *_toolBar = NULL; + CToolBarCtrl& toolBar = CMainFrame::m_wndToolBar.GetToolBarCtrl(); + _toolBar = &toolBar; + if (_toolBar) + { + toolBar.SetState(ID_DESTROY_TICKET, TBSTATE_ENABLED); + } + else + { + AfxMessageBox("There is a problem with the Leash Toolbar!", MB_OK|MB_ICONSTOP); + } + } + } + ReleaseMutex(ticketinfo.lockObj); +} + +VOID CLeashView::OnSynTime() +{ + LONG returnValue; + returnValue = pLeash_timesync(1); +} + +VOID CLeashView::OnActivateView(BOOL bActivate, CView* pActivateView, + CView* pDeactiveView) +{ + UINT check = NULL; + + if (m_alreadyPlayed) + { + CFormView::OnActivateView(bActivate, pActivateView, pDeactiveView); + return; + } + + // The following code has put here because at the time + // 'checking and unchecking' a menuitem with the + // 'OnUpdate.....(CCmdUI* pCmdUI) functions' were unreliable + // in CLeashView -->> Better done in CMainFrame + if( CLeashApp::m_hProgram != 0 ) + { + m_hMenu = ::GetMenu(CLeashApp::m_hProgram); + } else { + return; + } + if( m_hMenu == NULL ) + { + AfxMessageBox("There is a problem finding the Leash main menu!", + MB_OK|MB_ICONSTOP); + return; + } + if (!m_largeIcons) + check = CheckMenuItem(m_hMenu, ID_LARGE_ICONS, MF_CHECKED); + else + check = CheckMenuItem(m_hMenu, ID_LARGE_ICONS, MF_UNCHECKED); + + if( check != MF_CHECKED || check != MF_UNCHECKED ) + { + m_debugStartUp = 1; + } + + if (!m_destroyTicketsOnExit) + check = CheckMenuItem(m_hMenu, ID_KILL_TIX_ONEXIT, MF_UNCHECKED); + else + check = CheckMenuItem(m_hMenu, ID_KILL_TIX_ONEXIT, MF_CHECKED); + + if (!m_upperCaseRealm) + check = CheckMenuItem(m_hMenu, ID_UPPERCASE_REALM, MF_UNCHECKED); + else + check = CheckMenuItem(m_hMenu, ID_UPPERCASE_REALM, MF_CHECKED); + + if (!m_lowTicketAlarm) + { + m_lowTicketAlarmSound = FALSE; + + if (m_hMenu) + CheckMenuItem(m_hMenu, ID_LOW_TICKET_ALARM, MF_UNCHECKED); + } + else + { + m_lowTicketAlarmSound = TRUE; + if (m_hMenu) + CheckMenuItem(m_hMenu, ID_LOW_TICKET_ALARM, MF_CHECKED); + } + + if (!m_autoRenewTickets) + { + if (m_hMenu) + CheckMenuItem(m_hMenu, ID_AUTO_RENEW, MF_UNCHECKED); + } + else + { + if (m_hMenu) + CheckMenuItem(m_hMenu, ID_AUTO_RENEW, MF_CHECKED); + } + + m_debugWindow = m_pApp->GetProfileInt("Settings", "DebugWindow", 0); + if (!m_debugWindow) + check = CheckMenuItem(m_hMenu, ID_DEBUG_MODE, MF_UNCHECKED); + else + check = CheckMenuItem(m_hMenu, ID_DEBUG_MODE, MF_CHECKED); + + m_alreadyPlayed = TRUE; + if (m_pApp) + { + m_debugWindow = m_pApp->GetProfileInt("Settings", "DebugWindow", 0); + + if (m_hMenu) + { + if (!m_debugWindow) + { + CheckMenuItem(m_hMenu, ID_DEBUG_MODE, MF_UNCHECKED); + } + else + { + CheckMenuItem(m_hMenu, ID_DEBUG_MODE, MF_CHECKED); + } + } + } + else + { + ApplicationInfoMissingMsg(); + } + + m_alreadyPlayed = TRUE; + + if (!CKrbProperties::KrbPropertiesOn) + SendMessage(WM_COMMAND, ID_UPDATE_DISPLAY, 0); + + if (m_debugStartUp) + { + OnDebugMode(); + } + + m_debugStartUp = FALSE; + + CFormView::OnActivateView(bActivate, pActivateView, pDeactiveView); +} + +VOID CLeashView::OnDebugMode() +{ + if (!pset_krb_debug) + return; + + if (!m_pDebugWindow) + { + AfxMessageBox("There is a problem with the Leash Debug Window!", + MB_OK|MB_ICONSTOP); + return; + } + + + // Check all possible 'KRB' system varables, then reset (delete) debug file + CHAR* Env[] = {"TEMP", "TMP", "HOME", NULL}; + CHAR** pEnv = Env; + CHAR debugFilePath[MAX_PATH]; + *debugFilePath = 0; + + while (*pEnv) + { + CHAR* ptestenv = getenv(*pEnv); + if (ptestenv) + { + // reset debug file + strcpy(debugFilePath, ptestenv); + strcat(debugFilePath, "\\LshDebug.log"); + remove(debugFilePath); + break; + } + + pEnv++; + } + + if (!m_debugStartUp) + { + if (m_debugWindow%2 == 0) + m_debugWindow = ON; + else + m_debugWindow = OFF; + } + + if (!m_pApp) + { + ApplicationInfoMissingMsg(); + } + else if (!m_debugWindow) + { + if (m_hMenu) + CheckMenuItem(m_hMenu, ID_DEBUG_MODE, MF_UNCHECKED); + + m_pApp->WriteProfileInt("Settings", "DebugWindow", FALSE_FLAG); + m_pDebugWindow->DestroyWindow(); + pset_krb_debug(OFF); + pset_krb_ap_req_debug(OFF); + return; + } + else + { + if (m_hMenu) + CheckMenuItem(m_hMenu, ID_DEBUG_MODE, MF_CHECKED); + + m_pApp->WriteProfileInt("Settings", "DebugWindow", TRUE_FLAG); + } + + // Creates the Debug dialog if not created already + if (m_pDebugWindow->GetSafeHwnd() == 0) + { // displays the Debug Window + m_pDebugWindow->Create(debugFilePath); + } +} + +VOID CLeashView::OnLargeIcons() +{ + INT x, y, n; + + if (change_icon_size) + { + if (m_largeIcons%2 == 0) + m_largeIcons = ON; + else + m_largeIcons = OFF; + } + else + { + if (m_largeIcons%2 == 0) + m_largeIcons = OFF; + else + m_largeIcons = ON; + } + + x = y = SMALL_ICONS; + + if (!m_pApp) + ApplicationInfoMissingMsg(); + else + { + if (!m_largeIcons) + { + if (m_hMenu) + CheckMenuItem(m_hMenu, ID_LARGE_ICONS, MF_CHECKED); + + x = y = LARGE_ICONS; + + if (!m_startup) + { + m_pApp->WriteProfileInt("Settings", "LargeIcons", TRUE_FLAG); + } + } + else + { + if (m_hMenu) + CheckMenuItem(m_hMenu, ID_LARGE_ICONS, MF_UNCHECKED); + + x = y = SMALL_ICONS; + + if (!m_startup) + { + m_pApp->WriteProfileInt("Settings", "LargeIcons", FALSE_FLAG); + } + } + } + + HICON hIcon[IMAGE_COUNT]; + for (n = 0; n < IMAGE_COUNT; n++) + { + hIcon[n] = NULL; + } + + m_imageList.DeleteImageList( ); + + UINT bitsPerPixel = GetDeviceCaps( ::GetDC(::GetDesktopWindow()), BITSPIXEL); + UINT ilcColor; + if ( bitsPerPixel >= 32 ) + ilcColor = ILC_COLOR32; + else if ( bitsPerPixel >= 24 ) + ilcColor = ILC_COLOR24; + else if ( bitsPerPixel >= 16 ) + ilcColor = ILC_COLOR16; + else if ( bitsPerPixel >= 8 ) + ilcColor = ILC_COLOR8; + else + ilcColor = ILC_COLOR; + m_imageList.Create(x, y, ilcColor | ILC_MASK, IMAGE_COUNT, 1); + m_imageList.SetBkColor(GetSysColor(COLOR_WINDOW)); + + hIcon[ACTIVE_TRAY_ICON] = AfxGetApp()->LoadIcon(IDI_LEASH_TRAY_GOOD); + hIcon[LOW_TRAY_ICON] = AfxGetApp()->LoadIcon(IDI_LEASH_TRAY_LOW); + hIcon[EXPIRED_TRAY_ICON] = AfxGetApp()->LoadIcon(IDI_LEASH_TRAY_EXPIRED); + hIcon[NONE_TRAY_ICON] = AfxGetApp()->LoadIcon(IDI_LEASH_TRAY_NONE); + hIcon[ACTIVE_PARENT_NODE] = AfxGetApp()->LoadIcon(IDI_LEASH_PRINCIPAL_GOOD); + hIcon[LOW_PARENT_NODE] = AfxGetApp()->LoadIcon(IDI_LEASH_PRINCIPAL_LOW); + hIcon[EXPIRED_PARENT_NODE] = AfxGetApp()->LoadIcon(IDI_LEASH_PRINCIPAL_EXPIRED); + hIcon[NONE_PARENT_NODE] = AfxGetApp()->LoadIcon(IDI_LEASH_PRINCIPAL_NONE); + hIcon[ACTIVE_TICKET] = AfxGetApp()->LoadIcon(IDI_TICKETTYPE_GOOD); + hIcon[LOW_TICKET] = AfxGetApp()->LoadIcon(IDI_TICKETTYPE_LOW); + hIcon[EXPIRED_TICKET] = AfxGetApp()->LoadIcon(IDI_TICKETTYPE_EXPIRED); + hIcon[TICKET_NOT_INSTALLED] = AfxGetApp()->LoadIcon(IDI_TICKETTYPE_NOTINSTALLED); + hIcon[ACTIVE_CLOCK] = AfxGetApp()->LoadIcon(IDI_TICKET_GOOD); + hIcon[LOW_CLOCK] = AfxGetApp()->LoadIcon(IDI_TICKET_LOW); + hIcon[EXPIRED_CLOCK] = AfxGetApp()->LoadIcon(IDI_TICKET_EXPIRED); + hIcon[TKT_ADDRESS] = AfxGetApp()->LoadIcon(IDI_LEASH_TICKET_ADDRESS); + hIcon[TKT_SESSION] = AfxGetApp()->LoadIcon(IDI_LEASH_TICKET_SESSION); + hIcon[TKT_ENCRYPTION] = AfxGetApp()->LoadIcon(IDI_LEASH_TICKET_ENCRYPTION); + + for (n = 0; n < IMAGE_COUNT; n++) + { + if ( !hIcon[n] ) { + AfxMessageBox("Can't find one or more images in the Leash Ticket Tree!", + MB_OK|MB_ICONSTOP); + return; + } + m_imageList.Add(hIcon[n]); + } + + m_pTree = (CTreeCtrl*) GetDlgItem(IDC_TREEVIEW); + m_pTree->SetItemHeight(y+2); + + if (!m_startup) + SendMessage(WM_COMMAND, ID_UPDATE_DISPLAY, 0); +} + +VOID CLeashView::OnKillTixOnExit() +{ + if (m_destroyTicketsOnExit%2 == 0) + m_destroyTicketsOnExit = ON; + else + m_destroyTicketsOnExit = OFF; + + if (m_pApp) + { + if (!m_destroyTicketsOnExit) + { + if (m_hMenu) + CheckMenuItem(m_hMenu, ID_KILL_TIX_ONEXIT, MF_UNCHECKED); + + AfxMessageBox("Tickets will be not be destroyed upon exiting Leash!!!", + MB_OK|MB_ICONWARNING); + m_pApp->WriteProfileInt("Settings", "DestroyTicketsOnExit", + FALSE_FLAG); + } + else + { + if (m_hMenu) + CheckMenuItem(m_hMenu, ID_KILL_TIX_ONEXIT, MF_CHECKED); + + AfxMessageBox("All tickets/tokens will be destroyed upon exiting Leash!!!", + MB_OK|MB_ICONWARNING); + m_pApp->WriteProfileInt("Settings", "DestroyTicketsOnExit", TRUE_FLAG); + } + } + else + { + ApplicationInfoMissingMsg(); + } +} + +VOID CLeashView::OnUppercaseRealm() +{ + if (m_upperCaseRealm%2 == 0) + m_upperCaseRealm = ON; + else + m_upperCaseRealm = OFF; + + if (!m_pApp) + { + ApplicationInfoMissingMsg(); + } + else if (!m_upperCaseRealm) + { + pLeash_set_default_uppercaserealm(FALSE_FLAG); + + if (m_hMenu) + CheckMenuItem(m_hMenu, ID_UPPERCASE_REALM, MF_UNCHECKED); + } + else + { + pLeash_set_default_uppercaserealm(TRUE_FLAG); + + if (m_hMenu) + CheckMenuItem(m_hMenu, ID_UPPERCASE_REALM, MF_CHECKED); + } +} + +VOID CLeashView::ResetTreeNodes() +{ + m_hPrincipalState = 0; + m_hKerb4State = 0; + m_hKerb5State = 0; + m_hAFSState = 0; +} + +VOID CLeashView::OnDestroy() +{ + SetTrayIcon(NIM_DELETE); + + CFormView::OnDestroy(); + if (WaitForSingleObject( ticketinfo.lockObj, INFINITE ) != WAIT_OBJECT_0) + throw("Unable to lock ticketinfo"); + BOOL b_destroy = m_destroyTicketsOnExit && (ticketinfo.Krb4.btickets || ticketinfo.Krb5.btickets); + ReleaseMutex(ticketinfo.lockObj); + + if (b_destroy) + { + if (pLeash_kdestroy()) + { + AfxMessageBox("There is a problem destroying tickets!", + MB_OK|MB_ICONSTOP); + } + } +} + +VOID CLeashView::OnUpdateDestroyTicket(CCmdUI* pCmdUI) +{ + if (!CLeashApp::m_hAfsDLL) + pCmdUI->SetText("&Destroy Ticket(s)\tCtrl+D"); + else + pCmdUI->SetText("&Destroy Ticket(s)/Token(s)\tCtrl+D"); + + if (WaitForSingleObject( ticketinfo.lockObj, INFINITE ) != WAIT_OBJECT_0) + throw("Unable to lock ticketinfo"); + BOOL b_enable =!ticketinfo.Krb4.btickets && !ticketinfo.Krb5.btickets && !ticketinfo.Afs.btickets; + ReleaseMutex(ticketinfo.lockObj); + + if (b_enable) + pCmdUI->Enable(FALSE); + else + pCmdUI->Enable(TRUE); +} + +VOID CLeashView::OnUpdateInitTicket(CCmdUI* pCmdUI) +{ + if (!CLeashApp::m_hAfsDLL) + pCmdUI->SetText("&Get Ticket(s)\tCtrl+T"); + else + pCmdUI->SetText("&Get Ticket(s)/Token(s)\tCtrl+T"); + + if (!CLeashApp::m_hKrb4DLL && !CLeashApp::m_hKrb5DLL && + !CLeashApp::m_hAfsDLL) + pCmdUI->Enable(FALSE); + else + pCmdUI->Enable(TRUE); +} + +VOID CLeashView::OnUpdateRenewTicket(CCmdUI* pCmdUI) +{ + if (!CLeashApp::m_hAfsDLL) + pCmdUI->SetText("&Renew Ticket(s)\tCtrl+R"); + else + pCmdUI->SetText("&Renew Ticket(s)/Token(s)\tCtrl+R"); + + if (WaitForSingleObject( ticketinfo.lockObj, INFINITE ) != WAIT_OBJECT_0) + throw("Unable to lock ticketinfo"); + BOOL b_enable = !(ticketinfo.Krb4.btickets || ticketinfo.Krb5.btickets) || + !CLeashApp::m_hKrb4DLL && !CLeashApp::m_hKrb5DLL && !CLeashApp::m_hAfsDLL; + ReleaseMutex(ticketinfo.lockObj); + + if (b_enable) + pCmdUI->Enable(FALSE); + else + pCmdUI->Enable(TRUE); +} + +VOID CLeashView::OnUpdateImportTicket(CCmdUI* pCmdUI) +{ + bool ccIsMSLSA = false; + +#ifndef KRB5_TC_NOTICKET + if (WaitForSingleObject( m_tgsReqMutex, INFINITE ) != WAIT_OBJECT_0) + throw("Unable to lock TGS request mutex"); +#endif + if (CLeashApp::m_krbv5_context) + { + const char *ccName = pkrb5_cc_default_name(CLeashApp::m_krbv5_context); + + if (ccName) + ccIsMSLSA = !strcmp(ccName, "MSLSA:"); + } + + if (!CLeashApp::m_hKrbLSA || !pLeash_importable() || ccIsMSLSA) + pCmdUI->Enable(FALSE); + else + pCmdUI->Enable(TRUE); +#ifndef KRB5_TC_NOTICKET + ReleaseMutex(m_tgsReqMutex); +#endif +} + +LRESULT CLeashView::OnGoodbye(WPARAM wParam, LPARAM lParam) +{ + m_pDebugWindow->DestroyWindow(); + return 0L; +} + +VOID CLeashView::OnLeashRestore() +{ + if ( CMainFrame::m_isMinimum ) { + CMainFrame * frame = (CMainFrame *)GetParentFrame(); + frame->ShowTaskBarButton(TRUE); + frame->ShowWindow(SW_SHOWNORMAL); + } +} + +VOID CLeashView::OnLeashMinimize() +{ + if ( !CMainFrame::m_isMinimum ) { + CMainFrame * frame = (CMainFrame *)GetParentFrame(); + // frame->ShowTaskBarButton(FALSE); + frame->ShowWindow(SW_HIDE); + frame->ShowWindow(SW_MINIMIZE); + } +} + +LRESULT CLeashView::OnTrayIcon(WPARAM wParam, LPARAM lParam) +{ + switch ( lParam ) { + case WM_LBUTTONDOWN: + if ( CMainFrame::m_isMinimum ) + OnLeashRestore(); + else + OnLeashMinimize(); + break; + case WM_RBUTTONDOWN: + { + int nFlags; + CMenu * menu = new CMenu(); + menu->CreatePopupMenu(); + if ( !CMainFrame::m_isMinimum ) + menu->AppendMenu(MF_STRING, ID_LEASH_MINIMIZE, "&Close Leash Window"); + else + menu->AppendMenu(MF_STRING, ID_LEASH_RESTORE, "&Open Leash Window"); + menu->AppendMenu(MF_SEPARATOR); + menu->AppendMenu(MF_STRING, ID_INIT_TICKET, "&Get Tickets"); +#ifndef KRB5_TC_NOTICKET + if (WaitForSingleObject( m_tgsReqMutex, INFINITE ) != WAIT_OBJECT_0) + throw("Unable to lock TGS request mutex"); +#endif + if (WaitForSingleObject( ticketinfo.lockObj, INFINITE ) != WAIT_OBJECT_0) + throw("Unable to lock ticketinfo"); + if (!(ticketinfo.Krb4.btickets || ticketinfo.Krb5.btickets) || + !CLeashApp::m_hKrb4DLL && !CLeashApp::m_hKrb5DLL && + !CLeashApp::m_hAfsDLL) + nFlags = MF_STRING | MF_GRAYED; + else + nFlags = MF_STRING; + menu->AppendMenu(nFlags, ID_RENEW_TICKET, "&Renew Tickets"); + if (!CLeashApp::m_hKrbLSA || !pLeash_importable()) + nFlags = MF_STRING | MF_GRAYED; + else + nFlags = MF_STRING; + menu->AppendMenu(MF_STRING, ID_IMPORT_TICKET, "&Import Tickets"); + if (!ticketinfo.Krb4.btickets && !ticketinfo.Krb5.btickets && !ticketinfo.Afs.btickets) + nFlags = MF_STRING | MF_GRAYED; + else + nFlags = MF_STRING; + ReleaseMutex(ticketinfo.lockObj); +#ifndef KRB5_TC_NOTICKET + ReleaseMutex(m_tgsReqMutex); +#endif + menu->AppendMenu(MF_STRING, ID_DESTROY_TICKET, "&Destroy Tickets"); + menu->AppendMenu(MF_STRING, ID_CHANGE_PASSWORD, "&Change Password"); + + menu->AppendMenu(MF_SEPARATOR); + if ( m_autoRenewTickets ) + nFlags = MF_STRING | MF_CHECKED; + else + nFlags = MF_STRING | MF_UNCHECKED; + menu->AppendMenu(nFlags, ID_AUTO_RENEW, "&Automatic Ticket Renewal"); + if ( m_lowTicketAlarm ) + nFlags = MF_STRING | MF_CHECKED; + else + nFlags = MF_STRING | MF_UNCHECKED; + menu->AppendMenu(nFlags, ID_LOW_TICKET_ALARM, "&Expiration Alarm"); + menu->AppendMenu(MF_SEPARATOR); + menu->AppendMenu(MF_STRING, ID_APP_EXIT, "E&xit"); + menu->SetDefaultItem(ID_LEASH_RESTORE); + + POINT pt; + GetCursorPos(&pt); + + SetForegroundWindow(); + menu->TrackPopupMenu(TPM_RIGHTALIGN | TPM_RIGHTBUTTON, + pt.x, pt.y, GetParentFrame()); + PostMessage(WM_NULL, 0, 0); + menu->DestroyMenu(); + delete menu; + } + break; + case WM_MOUSEMOVE: + // SendMessage(WM_COMMAND, ID_UPDATE_DISPLAY, 0); + break; + } + return 0L; +} + +VOID CLeashView::OnAppAbout() +{ + CLeashAboutBox leashAboutBox; + leashAboutBox.DoModal(); +} + + +VOID CLeashView::OnAfsControlPanel() +{ + CAfsProperties afsProperties; + afsProperties.DoModal(); +} + +VOID CLeashView::OnInitialUpdate() +{ + CFormView::OnInitialUpdate(); + CLeashApp::m_hProgram = ::FindWindow(_T("LEASH.0WNDCLASS"), NULL); + EnableToolTips(); +} + +VOID CLeashView::OnItemexpandedTreeview(NMHDR* pNMHDR, LRESULT* pResult) +{ + NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR; + + if (m_hPrincipal == pNMTreeView->itemNew.hItem) + m_hPrincipalState = pNMTreeView->action; + else if (m_hKerb4 == pNMTreeView->itemNew.hItem) + m_hKerb4State = pNMTreeView->action; + else if (m_hKerb5 == pNMTreeView->itemNew.hItem) + m_hKerb5State = pNMTreeView->action; + else if (m_hAFS == pNMTreeView->itemNew.hItem) + m_hAFSState = pNMTreeView->action; + + CMainFrame::m_isBeingResized = TRUE; + *pResult = 0; +} + +VOID CLeashView::OnUpdateDebugMode(CCmdUI* pCmdUI) +{ + if (!pset_krb_debug) + pCmdUI->Enable(FALSE); + else + pCmdUI->Enable(TRUE); +} + +VOID CLeashView::OnUpdateCfgFiles(CCmdUI* pCmdUI) +{ + if (!pkrb_get_krbconf2) + pCmdUI->Enable(FALSE); + else + pCmdUI->Enable(TRUE); +} + +VOID CLeashView::OnLeashProperties() +{ + CLeashProperties leashProperties; + leashProperties.DoModal(); +} + +VOID CLeashView::OnKrbProperties() +{ + CKrbProperties krbProperties("Kerberos Properties"); + krbProperties.DoModal(); +} + +VOID CLeashView::OnKrb4Properties() +{ + CKrb4Properties krb4Properties("Kerberos Four Properties"); + krb4Properties.DoModal(); +} + +VOID CLeashView::OnKrb5Properties() +{ + CKrb5Properties krb5Properties("Kerberos Five Properties"); + krb5Properties.DoModal(); +} + +/* +void CLeashView::GetRowWidthHeight(CDC* pDC, LPCSTR theString, int& nRowWidth, + int& nRowHeight, int& nCharWidth) +{ + TEXTMETRIC tm; + + //CEx29aDoc* pDoc = GetDocument(); + pDC->GetTextMetrics(&tm); + nCharWidth = tm.tmAveCharWidth + 1; + nRowWidth = strlen(theString); + + //int nFields = theString.GetLength(); + + //for(int i = 0; i < nFields; i++) + //{ + // nRowWidth += nCharWidth; + //} + + nRowWidth *= nCharWidth; + nRowHeight = tm.tmHeight; +} +*/ + +void CLeashView::SetTrayText(int nim, CString tip) +{ + if ( (nim == NIM_MODIFY) && (m_bIconDeleted) ) + return; + if ( (nim == NIM_MODIFY) && (!m_bIconAdded) ) + nim = NIM_ADD; + + if ( (nim != NIM_DELETE) || IsWindow(m_hWnd) ) + { + NOTIFYICONDATA nid; + memset (&nid, 0x00, sizeof(NOTIFYICONDATA)); + nid.cbSize = sizeof(NOTIFYICONDATA); + nid.hWnd = m_hWnd; + nid.uID = 0; + nid.uFlags = NIF_MESSAGE | NIF_TIP; + nid.uCallbackMessage = WM_TRAYICON; + strncpy(nid.szTip, (LPCTSTR) tip, sizeof(nid.szTip)); + nid.szTip[sizeof(nid.szTip)-1] = '\0'; + Shell_NotifyIcon (nim, &nid); + } + + if ( nim == NIM_ADD ) + m_bIconAdded = TRUE; + if ( nim == NIM_DELETE ) + m_bIconDeleted = TRUE; +} + +void CLeashView::SetTrayIcon(int nim, int state) +{ + static HICON hIcon[IMAGE_COUNT]; + static BOOL bIconInit = FALSE; + + if ( (nim == NIM_MODIFY) && (m_bIconDeleted) ) + return; + if ( (nim == NIM_MODIFY) && (!m_bIconAdded) ) + nim = NIM_ADD; + + if ( (nim != NIM_DELETE) || IsWindow(m_hWnd) ) + { + if ( !bIconInit ) { + // The state is reported as the parent node value although + // we want to use the Tray Version of the icons + hIcon[ACTIVE_PARENT_NODE] = AfxGetApp()->LoadIcon(IDI_LEASH_TRAY_GOOD); + hIcon[LOW_PARENT_NODE] = AfxGetApp()->LoadIcon(IDI_LEASH_TRAY_LOW); + hIcon[EXPIRED_PARENT_NODE] = AfxGetApp()->LoadIcon(IDI_LEASH_TRAY_EXPIRED); + hIcon[NONE_PARENT_NODE] = AfxGetApp()->LoadIcon(IDI_LEASH_TRAY_NONE); + bIconInit = TRUE; + } + + NOTIFYICONDATA nid; + memset (&nid, 0x00, sizeof(NOTIFYICONDATA)); + nid.cbSize = sizeof(NOTIFYICONDATA); + nid.hWnd = m_hWnd; + nid.uID = 0; + nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP; + nid.uCallbackMessage = WM_TRAYICON; + nid.hIcon = hIcon[state]; + Shell_NotifyIcon (nim, &nid); + } + + if ( nim == NIM_ADD ) + m_bIconAdded = TRUE; + if ( nim == NIM_DELETE ) + m_bIconDeleted = TRUE; +} + +BOOL CLeashView::PreTranslateMessage(MSG* pMsg) +{ + if ( pMsg->message == ID_OBTAIN_TGT_WITH_LPARAM ) + { + OutputDebugString("Obtain TGT with LParam\n"); + } + + if ( pMsg->message == WM_TIMER ) { + try { + if (InterlockedDecrement(&m_timerMsgNotInProgress) == 0) { + + CString ticketStatusKrb4 = TCHAR(NOT_INSTALLED); + CString ticketStatusKrb5 = TCHAR(NOT_INSTALLED); + CString ticketStatusAfs = TCHAR(NOT_INSTALLED); + CString strTimeDate; + CString lowTicketWarningKrb4; + CString lowTicketWarningKrb5; + CString lowTicketWarningAfs; + + timer_start: + if (WaitForSingleObject( ticketinfo.lockObj, 100 ) != WAIT_OBJECT_0) + throw("Unable to lock ticketinfo"); + if (CLeashApp::m_hKrb5DLL) + { + // KRB5 + UpdateTicketTime(ticketinfo.Krb5); + + if (!ticketinfo.Krb5.btickets) + { + ticketStatusKrb5 = "Kerb-5: No Tickets"; + } + else if (EXPIRED_TICKETS == ticketinfo.Krb5.btickets) + { + ticketStatusKrb5 = "Kerb-5: Expired Ticket(s)"; + m_ticketTimeLeft = 0; + lowTicketWarningKrb5 = "Your Kerberos Five ticket(s) have expired"; + if (!m_warningOfTicketTimeLeftLockKrb5) + m_warningOfTicketTimeLeftKrb5 = 0; + m_warningOfTicketTimeLeftLockKrb5 = ZERO_MINUTES_LEFT; + } + else + { + m_ticketStatusKrb5 = GetLowTicketStatus(5); + switch (m_ticketStatusKrb5) + { + case TWENTY_MINUTES_LEFT: + break; + case FIFTEEN_MINUTES_LEFT: + ticketinfo.Krb5.btickets = TICKETS_LOW; + lowTicketWarningKrb5 = "Less then 15 minutes left on your Kerberos Five ticket(s)"; + break; + case TEN_MINUTES_LEFT: + ticketinfo.Krb5.btickets = TICKETS_LOW; + lowTicketWarningKrb5 = "Less then 10 minutes left on your Kerberos Five ticket(s)"; + if (!m_warningOfTicketTimeLeftLockKrb5) + m_warningOfTicketTimeLeftKrb5 = 0; + m_warningOfTicketTimeLeftLockKrb5 = TEN_MINUTES_LEFT; + break; + case FIVE_MINUTES_LEFT: + ticketinfo.Krb5.btickets = TICKETS_LOW; + if (m_warningOfTicketTimeLeftLockKrb5 == TEN_MINUTES_LEFT) + m_warningOfTicketTimeLeftKrb5 = 0; + m_warningOfTicketTimeLeftLockKrb5 = FIVE_MINUTES_LEFT; + lowTicketWarningKrb5 = "Less then 5 minutes left on your Kerberos Five ticket(s)"; + break; + default: + m_ticketStatusKrb5 = 0; + break; + } + } + + if (CMainFrame::m_isMinimum) + { + // minimized dispay + ticketStatusKrb5.Format("Kerb-5: %02d:%02d Left", + (m_ticketTimeLeft / 60L / 60L), + (m_ticketTimeLeft / 60L % 60L)); + } + else + { + // normal display + if (GOOD_TICKETS == ticketinfo.Krb5.btickets || TICKETS_LOW == ticketinfo.Krb5.btickets) + { + if ( m_ticketTimeLeft >= 60 ) { + ticketStatusKrb5.Format("Kerb-5 Ticket Life: %02d:%02d", + (m_ticketTimeLeft / 60L / 60L), + (m_ticketTimeLeft / 60L % 60L)); + } else { + ticketStatusKrb5.Format("Kerb-5 Ticket Life: < 1 min"); + } + } + + if (CMainFrame::m_wndStatusBar) + { + CMainFrame::m_wndStatusBar.SetPaneInfo(1, 111112, SBPS_NORMAL, 130); + CMainFrame::m_wndStatusBar.SetPaneText(1, ticketStatusKrb5, SBT_POPOUT); + } + } + } + else + { + // not installed + ticketStatusKrb5.Format("Kerb-5: Not Available"); + + if (CMainFrame::m_wndStatusBar) + { + CMainFrame::m_wndStatusBar.SetPaneInfo(1, 111112, SBPS_NORMAL, 130); + CMainFrame::m_wndStatusBar.SetPaneText(1, ticketStatusKrb5, SBT_POPOUT); + } + } + //KRB5 + + if (CLeashApp::m_hKrb4DLL) + { + // KRB4 + UpdateTicketTime(ticketinfo.Krb4); + if (!ticketinfo.Krb4.btickets) + { + ticketStatusKrb4 = "Kerb-4: No Tickets"; + } + else if (EXPIRED_TICKETS == ticketinfo.Krb4.btickets) + { +#ifndef NO_KRB5 + if (ticketinfo.Krb5.btickets && + EXPIRED_TICKETS != ticketinfo.Krb5.btickets && + m_autoRenewTickets && + !m_autoRenewalAttempted && + ticketinfo.Krb5.renew_till && + (ticketinfo.Krb5.issue_date + ticketinfo.Krb5.renew_till -LeashTime() > 20 * 60) && + pLeash_get_default_use_krb4() + ) + { + m_autoRenewalAttempted = 1; + ReleaseMutex(ticketinfo.lockObj); + AfxBeginThread(RenewTicket,m_hWnd); + goto timer_start; + } +#endif /* NO_KRB5 */ + ticketStatusKrb4 = "Kerb-4: Expired Tickets"; + lowTicketWarningKrb4 = "Your Kerberos Four ticket(s) have expired"; + if (!m_warningOfTicketTimeLeftLockKrb4) + m_warningOfTicketTimeLeftKrb4 = 0; + m_warningOfTicketTimeLeftLockKrb4 = ZERO_MINUTES_LEFT; + m_ticketTimeLeft = 0; + } + else if ( pLeash_get_default_use_krb4() ) + { + m_ticketStatusKrb4 = GetLowTicketStatus(4); + switch (m_ticketStatusKrb4) + { + case FIFTEEN_MINUTES_LEFT: + ticketinfo.Krb4.btickets = TICKETS_LOW; + lowTicketWarningKrb4 = "Less then 15 minutes left on your Kerberos Four ticket(s)"; + break; + case TEN_MINUTES_LEFT: + ticketinfo.Krb4.btickets = TICKETS_LOW; + lowTicketWarningKrb4 = "Less then 10 minutes left on your Kerberos Four ticket(s)"; + if (!m_warningOfTicketTimeLeftLockKrb4) + m_warningOfTicketTimeLeftKrb4 = 0; + m_warningOfTicketTimeLeftLockKrb4 = TEN_MINUTES_LEFT; + break; + case FIVE_MINUTES_LEFT: + ticketinfo.Krb4.btickets = TICKETS_LOW; + if (m_warningOfTicketTimeLeftLockKrb4 == TEN_MINUTES_LEFT) + m_warningOfTicketTimeLeftKrb4 = 0; + m_warningOfTicketTimeLeftLockKrb4 = FIVE_MINUTES_LEFT; + lowTicketWarningKrb4 = "Less then 5 minutes left on your Kerberos Four ticket(s)"; + break; + default: + m_ticketStatusKrb4 = 0; + break; + } + + } + + if (CMainFrame::m_isMinimum) + { + // minimized dispay + ticketStatusKrb4.Format("Kerb-4: %02d:%02d Left", + (m_ticketTimeLeft / 60L / 60L), + (m_ticketTimeLeft / 60L % 60L)); + } + else + { + // normal display + if (GOOD_TICKETS == ticketinfo.Krb4.btickets || + TICKETS_LOW == ticketinfo.Krb4.btickets) + { + if ( m_ticketTimeLeft >= 60 ) { + ticketStatusKrb4.Format("Kerb-4 Ticket Life: %02d:%02d", + (m_ticketTimeLeft / 60L / 60L), + (m_ticketTimeLeft / 60L % 60L)); + } else { + ticketStatusKrb4.Format("Kerb-4 Ticket Life: < 1 min"); + } + } + + if (CMainFrame::m_wndStatusBar) + { + CMainFrame::m_wndStatusBar.SetPaneInfo(2, 111111, SBPS_NORMAL, 130); + CMainFrame::m_wndStatusBar.SetPaneText(2, ticketStatusKrb4, SBT_POPOUT); + } + } + } + else + { + // not installed + ticketStatusKrb4.Format("Kerb-4: Not Available"); + + if (CMainFrame::m_wndStatusBar) + { + CMainFrame::m_wndStatusBar.SetPaneInfo(2, 111111, SBPS_NORMAL, 130); + CMainFrame::m_wndStatusBar.SetPaneText(2, ticketStatusKrb4, SBT_POPOUT); + } + } + // KRB4 + + if (CLeashApp::m_hAfsDLL) + { + // AFS + UpdateTicketTime(ticketinfo.Afs); + if (!ticketinfo.Afs.btickets) + { + BOOL AfsEnabled = m_pApp->GetProfileInt("Settings", "AfsStatus", 1); + if ( AfsEnabled ) + ticketStatusAfs = "AFS: No Tickets"; + else + ticketStatusAfs = "AFS: Disabled"; + } + else if (EXPIRED_TICKETS == ticketinfo.Afs.btickets) + { +#ifndef NO_KRB5 + if (ticketinfo.Krb5.btickets && + EXPIRED_TICKETS != ticketinfo.Krb5.btickets && + m_autoRenewTickets && + !m_autoRenewalAttempted && + ticketinfo.Krb5.renew_till && + (ticketinfo.Krb5.issue_date + ticketinfo.Krb5.renew_till -LeashTime() > 20 * 60) && + !stricmp(ticketinfo.Krb5.principal,ticketinfo.Afs.principal) + ) + { + m_autoRenewalAttempted = 1; + ReleaseMutex(ticketinfo.lockObj); + AfxBeginThread(RenewTicket,m_hWnd); + goto timer_start; + } +#endif /* NO_KRB5 */ + ticketStatusAfs = "AFS: Expired Tickets"; + lowTicketWarningAfs = "Your AFS token(s) have expired"; + if (!m_warningOfTicketTimeLeftLockAfs) + m_warningOfTicketTimeLeftAfs = 0; + m_warningOfTicketTimeLeftLockAfs = ZERO_MINUTES_LEFT; + m_ticketTimeLeft = 0; + } + else + { + m_ticketStatusAfs = GetLowTicketStatus(1); + switch (m_ticketStatusAfs) + { + case FIFTEEN_MINUTES_LEFT: + ticketinfo.Afs.btickets = TICKETS_LOW; + + lowTicketWarningAfs = "Less then 15 minutes left on your AFStoken(s)"; + break; + case TEN_MINUTES_LEFT: + ticketinfo.Afs.btickets = TICKETS_LOW; + + lowTicketWarningAfs = "Less then 10 minutes left on your AFS token(s)"; + + if (!m_warningOfTicketTimeLeftLockAfs) + m_warningOfTicketTimeLeftAfs = 0; + + m_warningOfTicketTimeLeftLockAfs = TEN_MINUTES_LEFT; + break; + case FIVE_MINUTES_LEFT: + ticketinfo.Afs.btickets = TICKETS_LOW; + if (m_warningOfTicketTimeLeftLockAfs == TEN_MINUTES_LEFT) + m_warningOfTicketTimeLeftAfs = 0; + + m_warningOfTicketTimeLeftLockAfs = FIVE_MINUTES_LEFT; + + lowTicketWarningAfs = "Less then 5 minutes left on your AFS token(s)"; + break; + default: + m_ticketStatusAfs = 0; + break; + } + + } + + if (CMainFrame::m_isMinimum) + { + // minimized dispay + ticketStatusAfs.Format("AFS: %02d:%02d Left", + (m_ticketTimeLeft / 60L / 60L), + (m_ticketTimeLeft / 60L % 60L)); + } + else + { + // normal display + if (GOOD_TICKETS == ticketinfo.Afs.btickets || + TICKETS_LOW == ticketinfo.Afs.btickets) + { + if ( m_ticketTimeLeft >= 60 ) { + ticketStatusAfs.Format("AFS Token Life: %02d:%02d", + (m_ticketTimeLeft / 60L / 60L), + (m_ticketTimeLeft / 60L % 60L)); + } else { + ticketStatusAfs.Format("AFS Token Life: < 1 min"); + } + } + + if (CMainFrame::m_wndStatusBar) + { + CMainFrame::m_wndStatusBar.SetPaneInfo(3, 111113, SBPS_NORMAL, 130); + CMainFrame::m_wndStatusBar.SetPaneText(3, ticketStatusAfs, SBT_POPOUT); + } + } + } +#ifdef COMMENT + // we do not set this field because the field does not exist when AfsDLL is NULL + else + { + // not installed + ticketStatusAfs.Format("AFS: Not Available"); + + if (CMainFrame::m_wndStatusBar) + { + CMainFrame::m_wndStatusBar.SetPaneInfo(3, 111113, SBPS_NORMAL, 130); + CMainFrame::m_wndStatusBar.SetPaneText(3, ticketStatusAfs, SBT_POPOUT); + } + } +#endif /* COMMENT */ + // AFS + +#ifndef NO_KRB5 + if ( m_ticketStatusKrb5 == TWENTY_MINUTES_LEFT && + m_autoRenewTickets && !m_autoRenewalAttempted && ticketinfo.Krb5.renew_till && + (ticketinfo.Krb5.issue_date + ticketinfo.Krb5.renew_till - LeashTime() > 20 * 60)) + { + m_autoRenewalAttempted = 1; + ReleaseMutex(ticketinfo.lockObj); + AfxBeginThread(RenewTicket,m_hWnd); + goto timer_start; + } +#endif /* NO_KRB5 */ + + BOOL warningKrb5 = m_ticketStatusKrb5 > NO_TICKETS && + m_ticketStatusKrb5 < TWENTY_MINUTES_LEFT && + !m_warningOfTicketTimeLeftKrb5; + BOOL warningKrb4 = m_ticketStatusKrb4 > NO_TICKETS && + m_ticketStatusKrb4 < TWENTY_MINUTES_LEFT && + !m_warningOfTicketTimeLeftKrb4; + BOOL warningAfs = m_ticketStatusAfs > NO_TICKETS && + m_ticketStatusAfs < TWENTY_MINUTES_LEFT && + !m_warningOfTicketTimeLeftAfs; + + // Play warning message only once per each case statement above + if (warningKrb4 || warningKrb5 || warningAfs) + { + + CString lowTicketWarning = ""; + int warnings = 0; + + if (warningKrb5) { + lowTicketWarning += lowTicketWarningKrb5; + m_warningOfTicketTimeLeftKrb5 = ON; + warnings++; + } + if (warningKrb4) { + if ( warnings ) + lowTicketWarning += "\n"; + lowTicketWarning += lowTicketWarningKrb4; + m_warningOfTicketTimeLeftKrb4 = ON; + warnings++; + } + if (warningAfs) { + if ( warnings ) + lowTicketWarning += "\n"; + lowTicketWarning += lowTicketWarningAfs; + m_warningOfTicketTimeLeftAfs = ON; + warnings++; + } + + ReleaseMutex(ticketinfo.lockObj); + AlarmBeep(); + CLeashMessageBox leashMessageBox(!CMainFrame::m_isMinimum ? GetDesktopWindow() : NULL, + lowTicketWarning, 100000); + leashMessageBox.DoModal(); + if (WaitForSingleObject( ticketinfo.lockObj, 100 ) != WAIT_OBJECT_0) + throw("Unable to lock ticketinfo"); + } + + CTime tTimeDate = CTime::GetCurrentTime(); + + if (CMainFrame::m_isMinimum) + { + if ( CLeashApp::m_hAfsDLL ) + strTimeDate = ( "Leash - " + "[" + ticketStatusKrb5 + "] - " + + "[" + ticketStatusKrb4 + "] - " + + "[" + ticketStatusAfs + "] - " + + "[" + ticketinfo.Krb5.principal + "]" + " - " + + tTimeDate.Format("%A, %B %d, %Y %H:%M ")); + else + strTimeDate = ( "Leash - " + "[" + ticketStatusKrb5 + "] - " + + "[" + ticketStatusKrb4 + "] - " + + "[" + ticketinfo.Krb5.principal + "]" + " - " + + tTimeDate.Format("%A, %B %d, %Y %H:%M ")); + } + else + { + strTimeDate = ("Leash - " + + tTimeDate.Format("%A, %B %d, %Y %H:%M ") + //timeDate.Format("%d %b %y %H:%M:%S - ") + ); + } + ::SetWindowText(CLeashApp::m_hProgram, strTimeDate); + + if (CLeashApp::m_hKrb5DLL) { + if ( ticketinfo.Krb5.btickets ) + strTimeDate = ( "Leash: " + "[" + ticketStatusKrb5 + "]" + + " - [" + ticketinfo.Krb5.principal + "]"); + else + strTimeDate = "Leash: Kerb-5 No Tickets"; + } else { + if ( ticketinfo.Krb4.btickets ) + strTimeDate = ( "Leash: " + "[" + ticketStatusKrb4 + "]" + + " - [" + ticketinfo.Krb4.principal + "]"); + else + strTimeDate = "Leash: Kerb-4 No Tickets"; + } + ReleaseMutex(ticketinfo.lockObj); + + SetTrayText(NIM_MODIFY, strTimeDate); + + m_updateDisplayCount++; + m_alreadyPlayedDisplayCount++; + } + } catch (...) { + } + InterlockedIncrement(&m_timerMsgNotInProgress); + } // WM_TIMER + + + if (UPDATE_DISPLAY_TIME == m_updateDisplayCount) + { + m_updateDisplayCount = 0; + SendMessage(WM_COMMAND, ID_UPDATE_DISPLAY, 0); + } + + if (m_alreadyPlayedDisplayCount > 2) + { + m_alreadyPlayedDisplayCount = 0; + m_alreadyPlayed = FALSE; + } + + if (CMainFrame::m_isBeingResized) + { + WINDOWPLACEMENT headingWndpl; + headingWndpl.length = sizeof(WINDOWPLACEMENT); + + CWnd *heading = GetDlgItem(IDC_LABEL_KERB_TICKETS); + if (!heading->GetWindowPlacement(&headingWndpl)) + { + AfxMessageBox("There is a problem getting Leash Heading size!", + MB_OK|MB_ICONSTOP); + return CFormView::PreTranslateMessage(pMsg);; + } + + m_pTree = (CTreeCtrl*) GetDlgItem(IDC_TREEVIEW); + VERIFY(m_pTree); + if (!m_pTree) + { + AfxMessageBox("There is a problem finding the Ticket Tree!", + MB_OK|MB_ICONSTOP); + return CFormView::PreTranslateMessage(pMsg); + } + + CRect rect; + GetClientRect(&rect); + + WINDOWPLACEMENT wndpl; + wndpl.length = sizeof(WINDOWPLACEMENT); + + if (!GetWindowPlacement(&wndpl)) + { + AfxMessageBox("There is a problem getting Leash Window size!", + MB_OK|MB_ICONSTOP); + return CFormView::PreTranslateMessage(pMsg); + } + + + wndpl.rcNormalPosition.top = rect.top + headingWndpl.rcNormalPosition.bottom; + wndpl.rcNormalPosition.right = rect.right; + wndpl.rcNormalPosition.bottom = rect.bottom; + + m_startup = FALSE; + + if (!m_pTree->SetWindowPlacement(&wndpl)) + { + AfxMessageBox("There is a problem setting Leash ticket Tree size!", + MB_OK|MB_ICONSTOP); + } + + + UpdateWindow(); + +#ifdef COOL_SCROLL + // The follow code creates a cool scroll bar on the MainFrame + m_pTree = (CTreeCtrl*) GetDlgItem(IDC_TREEVIEW); + CWnd *pLabel = GetDlgItem(IDC_LABEL_KERB_TICKETS); + + VERIFY(m_pTree); + + // Sync Tree Frame with Main Frame + // WINDOWPLACEMENT wndpl; + WINDOWPLACEMENT wndplTree; + WINDOWPLACEMENT wndplLabel; + wndpl.length = sizeof(WINDOWPLACEMENT); + wndplTree.length = sizeof(WINDOWPLACEMENT); + wndplLabel.length = sizeof(WINDOWPLACEMENT); + GetWindowPlacement(&wndpl); + m_pTree->GetWindowPlacement(&wndplTree); + pLabel->GetWindowPlacement(&wndplLabel); + + if (!m_startup) + { + if (ticketinfo.Krb4.btickets || ticketinfo.Krb5.btickets) + { // control scroll bars to TreeView + #define TICKET_LABEL_TOP 8 + #define TICKET_LABEL_BOTTOM 28 + #define TICKET_LABEL_RIGHT 398 + #define RIGHT_FRAME_ADJUSTMENT 13 + #define BOTTOM_FRAME_ADJUSTMENT 72 + #define STRETCH_FACTOR 3 + + char theText[MAX_K_NAME_SZ+40]; + int longestLine = 0; + int theHeight = 0; + BOOL disableScrollHorz = FALSE; + BOOL disableScrollVert = FALSE; + RECT rect; + + HTREEITEM xTree; + TV_ITEM item; + item.mask = TVIF_HANDLE | TVIF_TEXT; + item.cchTextMax = sizeof(theText); + + xTree = m_hKerb4; + do + { + item.hItem = xTree; + item.pszText = theText; + VERIFY(m_pTree->GetItem(&item)); + + UINT offSet = m_pTree->GetIndent(); + if (!m_pTree->GetItemRect(xTree, &rect, TRUE)) + { + longestLine = 0; + theHeight = 0; + break; + } + + if (rect.right > longestLine) + longestLine = rect.right + RIGHT_FRAME_ADJUSTMENT; + + theHeight = rect.bottom + BOTTOM_FRAME_ADJUSTMENT; + } + while ((xTree = m_pTree->GetNextItem(xTree, TVGN_NEXTVISIBLE))); + + + // Horz + if (longestLine < wndpl.rcNormalPosition.right) + { // disable scroll + disableScrollHorz = TRUE; + SetScrollPos(SB_HORZ, 0, TRUE); + EnableScrollBar(SB_HORZ, ESB_DISABLE_BOTH); + } + else + { // enable scroll + EnableScrollBar(SB_HORZ, ESB_ENABLE_BOTH); + SetScrollRange(SB_HORZ, 0, longestLine , TRUE); + } + + // Vert + if (theHeight < wndpl.rcNormalPosition.bottom) + { // disable scroll + disableScrollVert = TRUE; + SetScrollPos(SB_VERT, 0, TRUE); + EnableScrollBar(SB_VERT, ESB_DISABLE_BOTH); + } + else + { // enable scroll + EnableScrollBar(SB_VERT, ESB_ENABLE_BOTH); + SetScrollRange(SB_VERT, 0, theHeight, TRUE); + } + + + if (!disableScrollHorz) + { + wndpl.rcNormalPosition.left = + wndplTree.rcNormalPosition.left; + + wndplLabel.rcNormalPosition.left = + wndpl.rcNormalPosition.left + 8; + } + + if (!disableScrollVert) + { + wndpl.rcNormalPosition.top = + wndplTree.rcNormalPosition.top; + } + else + { + wndplLabel.rcNormalPosition.left = + wndpl.rcNormalPosition.left + 8; + + wndplLabel.rcNormalPosition.top = TICKET_LABEL_TOP; + wndplLabel.rcNormalPosition.bottom = TICKET_LABEL_BOTTOM; + wndplLabel.rcNormalPosition.right = TICKET_LABEL_RIGHT; + } + + wndpl.rcNormalPosition.right *= STRETCH_FACTOR; + wndpl.rcNormalPosition.bottom *= STRETCH_FACTOR; + } + } + + m_startup = FALSE; + + m_pTree->SetWindowPlacement(&wndpl); + pLabel->SetWindowPlacement(&wndplLabel); +#endif /* COOL_SCROLL */ + + CMainFrame::m_isBeingResized = FALSE; + } + + if (::IsWindow(pMsg->hwnd)) + return CFormView::PreTranslateMessage(pMsg); + else + return FALSE; +} + +VOID CLeashView::OnLowTicketAlarm() +{ + if (m_lowTicketAlarm%2 == 0) + m_lowTicketAlarm = ON; + else + m_lowTicketAlarm = OFF; + + + if (!m_pApp) + { + ApplicationInfoMissingMsg(); + } + else if (!m_lowTicketAlarm) + { + if (m_hMenu) + CheckMenuItem(m_hMenu, ID_LOW_TICKET_ALARM, MF_UNCHECKED); + + m_pApp->WriteProfileInt("Settings", "LowTicketAlarm", FALSE_FLAG); + } + else + { + if (m_hMenu) + CheckMenuItem(m_hMenu, ID_LOW_TICKET_ALARM, MF_CHECKED); + + m_pApp->WriteProfileInt("Settings", "LowTicketAlarm", TRUE_FLAG); + } +} + +VOID CLeashView::OnAutoRenew() +{ + if (m_autoRenewTickets%2 == 0) + m_autoRenewTickets = ON; + else + m_autoRenewTickets = OFF; + + + if (!m_pApp) + { + ApplicationInfoMissingMsg(); + } + else if (!m_autoRenewTickets) + { + if (m_hMenu) + CheckMenuItem(m_hMenu, ID_AUTO_RENEW, MF_UNCHECKED); + + m_pApp->WriteProfileInt("Settings", "AutoRenewTickets", FALSE_FLAG); + m_autoRenewTickets = FALSE; + } + else + { + if (m_hMenu) + CheckMenuItem(m_hMenu, ID_AUTO_RENEW, MF_CHECKED); + + m_pApp->WriteProfileInt("Settings", "AutoRenewTickets", TRUE_FLAG); + m_autoRenewTickets = TRUE; + } + m_autoRenewalAttempted = 0; +} + +VOID CLeashView::AlarmBeep() +{ + if (m_lowTicketAlarmSound) + { + ::Beep(2000, 200); + ::Beep(200, 200); + ::Beep(700, 200); + } +} + +VOID CLeashView::OnUpdateProperties(CCmdUI* pCmdUI) +{ + if (CLeashApp::m_hKrb5DLL || CLeashApp::m_hKrb4DLL) + pCmdUI->Enable(); + else + pCmdUI->Enable(FALSE); +} + +VOID CLeashView::OnUpdateKrb4Properties(CCmdUI* pCmdUI) +{ + if (CLeashApp::m_hKrb4DLL) + pCmdUI->Enable(); + else + pCmdUI->Enable(FALSE); +} + +VOID CLeashView::OnUpdateKrb5Properties(CCmdUI* pCmdUI) +{ + if (CLeashApp::m_hKrb5DLL) + pCmdUI->Enable(); + else + pCmdUI->Enable(FALSE); +} + +VOID CLeashView::OnUpdateAfsControlPanel(CCmdUI* pCmdUI) +{ + // need Krb 4 to get AFS tokens + if (CLeashApp::m_hAfsDLL && CLeashApp::m_hKrb4DLL) + pCmdUI->Enable(); + else + pCmdUI->m_pMenu->DeleteMenu(pCmdUI->m_nID, MF_BYCOMMAND); +} + +void CLeashView::OnHelpLeash32() +{ +#ifdef CALL_HTMLHELP + AfxGetApp()->HtmlHelp(HID_LEASH_PROGRAM); +#else + AfxGetApp()->WinHelp(HID_LEASH_PROGRAM); +#endif +} + +void CLeashView::OnHelpKerberos() +{ +#ifdef CALL_HTMLHELP + AfxGetApp()->HtmlHelp(HID_ABOUT_KERBEROS); +#else + AfxGetApp()->WinHelp(HID_ABOUT_KERBEROS); +#endif +} + +void CLeashView::OnHelpWhyuseleash32() +{ +#ifdef CALL_HTMLHELP + AfxGetApp()->HtmlHelp(HID_WHY_USE_LEASH32); +#else + AfxGetApp()->WinHelp(HID_WHY_USE_LEASH32); +#endif +} + +void CLeashView::OnSysColorChange() +{ + change_icon_size = FALSE; + CWnd::OnSysColorChange(); + OnLargeIcons(); + m_imageList.SetBkColor(GetSysColor(COLOR_WINDOW)); + change_icon_size = TRUE; +} + + +LRESULT +CLeashView::OnObtainTGTWithParam(WPARAM wParam, LPARAM lParam) +{ + LRESULT res = 0; + char * param = (char *) GlobalLock((HGLOBAL) lParam); + LSH_DLGINFO_EX ldi; + ldi.size = sizeof(ldi); + ldi.dlgtype = DLGTYPE_PASSWD; + ldi.use_defaults = 1; + ldi.title = ldi.in.title; + ldi.username = ldi.in.username; + ldi.realm = ldi.in.realm; + if ( param ) { + if ( *param ) + strcpy(ldi.in.title,param); + param += strlen(param) + 1; + if ( *param ) + strcpy(ldi.in.username,param); + param += strlen(param) + 1; + if ( *param ) + strcpy(ldi.in.realm,param); + param += strlen(param) + 1; + if ( *param ) + strcpy(ldi.in.ccache,param); + } else { + strcpy(ldi.in.title,"Initialize Ticket"); + } + + res = pLeash_kinit_dlg_ex(m_hWnd, &ldi); + GlobalUnlock((HGLOBAL) lParam); + ::SendMessage(m_hWnd, WM_COMMAND, ID_UPDATE_DISPLAY, 0); + return res; +} diff --git a/src/windows/leash/LeashView.h b/src/windows/leash/LeashView.h new file mode 100644 index 000000000..591bc426f --- /dev/null +++ b/src/windows/leash/LeashView.h @@ -0,0 +1,253 @@ +// ************************************************************************************** +// File: LeashView.h +// By: Arthur David Leather +// Created: 12/02/98 +// Copyright @1998 Massachusetts Institute of Technology - All rights reserved. +// Description: H file for LeashView.cpp. Contains variables and functions +// for the Leash FormView +// +// History: +// +// MM/DD/YY Inits Description of Change +// 12/02/98 ADL Original +// ************************************************************************************** + + +#if !defined(AFX_LeashVIEW_H__6F45AD99_561B_11D0_8FCF_00C04FC2A0C2__INCLUDED_) +#define AFX_LeashVIEW_H__6F45AD99_561B_11D0_8FCF_00C04FC2A0C2__INCLUDED_ + +#if _MSC_VER >= 1000 +#pragma once +#endif // _MSC_VER >= 1000 + +#define GOOD_TICKETS 1 // Don't change this value +#define EXPIRED_TICKETS 2 // Don't change this value +#define TICKETS_LOW 3 +#define ONE_SECOND 1000 +#define SMALL_ICONS 16 +#define LARGE_ICONS 32 + +#define UPDATE_DISPLAY_TIME 60 //seconds + +#define ACTIVE_CLOCK 0 +#define LOW_CLOCK 1 +#define EXPIRED_CLOCK 2 +#define ACTIVE_TICKET 3 +#define LOW_TICKET 4 +#define EXPIRED_TICKET 5 +#define TICKET_NOT_INSTALLED 6 +#define ACTIVE_PARENT_NODE 7 +#define LOW_PARENT_NODE 8 +#define EXPIRED_PARENT_NODE 9 +#define NONE_PARENT_NODE 10 +#define LOW_TRAY_ICON 11 +#define EXPIRED_TRAY_ICON 12 +#define ACTIVE_TRAY_ICON 13 +#define NONE_TRAY_ICON 14 +#define TKT_ADDRESS 15 +#define TKT_SESSION 16 +#define TKT_ENCRYPTION 17 +#define IMAGE_COUNT 18 + +#define NODE_IS_EXPANDED 2 + +#define CX_BORDER 1 +#define CY_BORDER 1 + +#ifdef NO_TICKETS +#undef NO_TICKETS // XXX - this is evil but necessary thanks to silliness... +#endif + +#define WM_TRAYICON (WM_USER+100) + +enum ticketTimeLeft{NO_TICKETS, ZERO_MINUTES_LEFT, FIVE_MINUTES_LEFT, TEN_MINUTES_LEFT, + FIFTEEN_MINUTES_LEFT, TWENTY_MINUTES_LEFT, PLENTY_OF_TIME, + NOT_INSTALLED}; +// Don't change 'NO_TICKET's' value + +class CLeashDebugWindow; + +class CLeashView : public CFormView +{ +private: + TicketList* m_listKrb4; + TicketList* m_listKrb5; + TicketList* m_listAfs; + CLeashDebugWindow* m_pDebugWindow; + CImageList m_imageList; + CImageList *m_pImageList; + CTreeCtrl* m_pTree; + CWinApp* m_pApp; + HTREEITEM m_hPrincipal; + HTREEITEM m_hKerb4; + HTREEITEM m_hKerb5; + HTREEITEM m_hk5tkt; + HTREEITEM m_hAFS; + TV_INSERTSTRUCT m_tvinsert; + HMENU m_hMenu; + BOOL m_startup; + BOOL m_isMinimum; + BOOL m_debugStartUp; + BOOL m_alreadyPlayed; + INT m_upperCaseRealm; + INT m_destroyTicketsOnExit; + INT m_debugWindow; + INT m_largeIcons; + INT m_lowTicketAlarm; + INT m_hPrincipalState; + INT m_hKerb4State; + INT m_hKerb5State; + INT m_hAFSState; + BOOL m_bIconAdded; + BOOL m_bIconDeleted; + + static INT m_autoRenewTickets; + static INT m_ticketStatusAfs; + static INT m_ticketStatusKrb4; + static INT m_ticketStatusKrb5; + static INT m_autoRenewalAttempted; + static INT m_warningOfTicketTimeLeftAfs; + static INT m_warningOfTicketTimeLeftKrb4; + static INT m_warningOfTicketTimeLeftKrb5; + static INT m_warningOfTicketTimeLeftLockAfs; + static INT m_warningOfTicketTimeLeftLockKrb4; + static INT m_warningOfTicketTimeLeftLockKrb5; + static INT m_updateDisplayCount; + static INT m_alreadyPlayedDisplayCount; + static LONG m_ticketTimeLeft; + static BOOL m_lowTicketAlarmSound; + static LONG m_timerMsgNotInProgress; + + VOID ResetTreeNodes(); + VOID ApplicationInfoMissingMsg(); + VOID GetScrollBarState(CSize sizeClient, CSize& needSb, + CSize& sizeRange, CPoint& ptMove, + BOOL bInsideClient); + VOID UpdateBars(); + VOID GetScrollBarSizes(CSize& sizeSb); + BOOL GetTrueClientSize(CSize& size, CSize& sizeSb); + + //void GetRowWidthHeight(CDC* pDC, LPCSTR theString, int& nRowWidth, + // int& nRowHeight, int& nCharWidth); + static VOID AlarmBeep(); + static VOID CALLBACK EXPORT TimerProc(HWND hWnd, UINT nMsg, UINT nIDEvent, + DWORD dwTime); + static VOID UpdateTicketTime(TICKETINFO& ticketinfo); + static INT GetLowTicketStatus(int); + static LONG LeashTime(); + + void SetTrayIcon(int nim, int state=0); + void SetTrayText(int nim, CString tip); + + BOOL UpdateDisplay(); + static UINT InitTicket(void *); + static UINT RenewTicket(void *); + static UINT ImportTicket(void *); + +protected: // create from serialization only + DECLARE_DYNCREATE(CLeashView) + +// Attributes +public: + static INT m_forwardableTicket; + static INT m_proxiableTicket; + static INT m_renewableTicket; + static INT m_noaddressTicket; + static DWORD m_publicIPAddress; + static BOOL m_importedTickets; + + CLeashView(); + //LeashDoc* GetDocument(); + + //{{AFX_DATA(CLeashView) + enum { IDD = IDD_DIALOG1 }; + // NOTE: the ClassWizard will add data members here + //}}AFX_DATA + +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CLeashView) + public: + virtual BOOL PreCreateWindow(CREATESTRUCT& cs); + virtual BOOL Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext = NULL); + virtual VOID OnInitialUpdate(); + virtual BOOL PreTranslateMessage(MSG* pMsg); + protected: + virtual VOID OnActivateView(BOOL bActivate, CView* pActivateView, CView* pDeactiveView); + //}}AFX_VIRTUAL + +// Implementation +public: + virtual ~CLeashView(); + +#ifdef _DEBUG + virtual VOID AssertValid() const; + virtual VOID Dump(CDumpContext& dc) const; +#endif + +// Generated message map functions +protected: + //{{AFX_MSG(CLeashView) + afx_msg VOID OnItemexpandedTreeview(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg INT OnCreate(LPCREATESTRUCT lpCreateStruct); + afx_msg VOID OnShowWindow(BOOL bShow, UINT nStatus); + afx_msg VOID OnClose(void); + afx_msg VOID OnInitTicket(); + afx_msg VOID OnRenewTicket(); + afx_msg VOID OnImportTicket(); + afx_msg VOID OnDestroyTicket(); + afx_msg VOID OnChangePassword(); + afx_msg VOID OnUpdateDisplay(); + afx_msg VOID OnSynTime(); + afx_msg VOID OnDebugMode(); + afx_msg VOID OnLargeIcons(); + afx_msg VOID OnUppercaseRealm(); + afx_msg VOID OnKillTixOnExit(); + afx_msg VOID OnDestroy(); + afx_msg VOID OnUpdateDestroyTicket(CCmdUI* pCmdUI); + afx_msg VOID OnUpdateImportTicket(CCmdUI* pCmdUI); + afx_msg VOID OnUpdateInitTicket(CCmdUI* pCmdUI); + afx_msg VOID OnUpdateRenewTicket(CCmdUI* pCmdUI); + afx_msg VOID OnAppAbout(); + afx_msg VOID OnAfsControlPanel(); + afx_msg VOID OnUpdateDebugMode(CCmdUI* pCmdUI); + afx_msg VOID OnUpdateCfgFiles(CCmdUI* pCmdUI); + afx_msg VOID OnKrb4Properties(); + afx_msg VOID OnKrb5Properties(); + afx_msg void OnLeashProperties(); + afx_msg void OnLeashRestore(); + afx_msg void OnLeashMinimize(); + afx_msg void OnLowTicketAlarm(); + afx_msg void OnUpdateKrb4Properties(CCmdUI* pCmdUI); + afx_msg void OnUpdateKrb5Properties(CCmdUI* pCmdUI); + afx_msg void OnUpdateAfsControlPanel(CCmdUI* pCmdUI); + afx_msg void OnKrbProperties(); + afx_msg void OnUpdateProperties(CCmdUI* pCmdUI); + afx_msg void OnHelpKerberos(); + afx_msg void OnHelpLeash32(); + afx_msg void OnHelpWhyuseleash32(); + afx_msg void OnSysColorChange(); + afx_msg void OnAutoRenew(); + afx_msg LRESULT OnGoodbye(WPARAM wParam, LPARAM lParam); + afx_msg LRESULT OnTrayIcon(WPARAM wParam, LPARAM lParam); + afx_msg LRESULT OnObtainTGTWithParam(WPARAM wParam, LPARAM lParam); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +/* +#ifndef _DEBUG // debug version in CLeashView.cpp +inline LeashDoc* CLeashView::GetDocument() + { return (LeashDoc*)m_pDocument; } +#endif +*/ + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Developer Studio will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_LeashVIEW_H__6F45AD99_561B_11D0_8FCF_00C04FC2A0C2__INCLUDED_) diff --git a/src/windows/leash/Lglobals.cpp b/src/windows/leash/Lglobals.cpp new file mode 100644 index 000000000..861255e6c --- /dev/null +++ b/src/windows/leash/Lglobals.cpp @@ -0,0 +1,148 @@ +//***************************************************************************** +// File: lgobals.cpp +// By: Arthur David Leather +// Created: 12/02/98 +// Copyright: @1998 Massachusetts Institute of Technology - All rights +// reserved. +// Description: CPP file for lgobals.cpp. Contains global variables and helper +// functions +// +// History: +// +// MM/DD/YY Inits Description of Change +// 02/02/98 ADL Original +//***************************************************************************** + +#include "stdafx.h" +#include "leash.h" +#include +#include "lglobals.h" + +static const char *const conf_yes[] = { + "y", "yes", "true", "t", "1", "on", + 0, +}; + +static const char *const conf_no[] = { + "n", "no", "false", "nil", "0", "off", + 0, +}; + +int +config_boolean_to_int(const char *s) +{ + const char *const *p; + + for(p=conf_yes; *p; p++) { + if (!strcasecmp(*p,s)) + return 1; + } + + for(p=conf_no; *p; p++) { + if (!strcasecmp(*p,s)) + return 0; + } + + /* Default to "no" */ + return 0; +} + + +// Global Function for deleting or putting a value in the Registry +BOOL SetRegistryVariable(const CString& regVariable, + const CString& regValue, + const char* regSubKey) +{ + // Set Register Variable + HKEY hKey = NULL; + LONG err = 0L; + + + if (ERROR_SUCCESS != (err = RegOpenKeyEx(HKEY_CURRENT_USER, + regSubKey, + 0, KEY_ALL_ACCESS, &hKey))) + { + if ((err = RegCreateKeyEx(HKEY_CURRENT_USER, regSubKey, 0, 0, 0, + KEY_ALL_ACCESS, 0, &hKey, 0))) + { + // Error + return TRUE; + } + } + + if (ERROR_SUCCESS == err && hKey) + { + if (regValue.IsEmpty()) + { + // Delete + RegDeleteValue(hKey, regVariable); + } + else + { + // Insure that Name (Variable) is in the Registry and set + // it's new value + char nVariable[MAX_PATH+1]; + char* pVARIABLE = nVariable; + strncpy(pVARIABLE, regValue, MAX_PATH); + + if (ERROR_SUCCESS != + RegSetValueEx(hKey, regVariable, 0, + REG_SZ, (const unsigned char*)pVARIABLE, + lstrlen(regValue))) + { + // Error + return FALSE; + } + } + + RegCloseKey(hKey); + + // Send this message to all top-level windows in the system + ::PostMessage(HWND_BROADCAST, WM_WININICHANGE, 0L, (LPARAM) regSubKey); + return FALSE; + } + + return TRUE; +} + +VOID LeashErrorBox(LPCSTR errorMsg, LPCSTR insertedString, LPCSTR errorFlag) +{ + CString strMessage; + strMessage = errorMsg; + strMessage += ": "; + strMessage += insertedString; + + MessageBox(CLeashApp::m_hProgram, strMessage, errorFlag, MB_OK); + + //if (*errorFlag == 'E') + //ASSERT(0); // on error condition only +} + +Directory::Directory(LPCSTR pathToValidate) +{ + m_pathToValidate = pathToValidate; + _getdcwd(_getdrive(), m_savCurPath, sizeof(m_savCurPath)); +} + +Directory::~Directory() +{ + if (-1 == _chdir(m_savCurPath)) + ASSERT(0); +} + +BOOL Directory::IsValidDirectory() +{ + if (-1 == _chdir(m_pathToValidate)) + return FALSE; + + return TRUE; +} + +BOOL Directory::IsValidFile() +{ + CFileFind fileFind; + if (!fileFind.FindFile(m_pathToValidate)) + return FALSE; + + return TRUE; +} diff --git a/src/windows/leash/Lglobals.h b/src/windows/leash/Lglobals.h new file mode 100644 index 000000000..7407b3b81 --- /dev/null +++ b/src/windows/leash/Lglobals.h @@ -0,0 +1,272 @@ +//***************************************************************************** +// File: lgobals.h +// By: Arthur David Leather +// Created: 12/02/98 +// Copyright: @1998 Massachusetts Institute of Technology - All rights +// reserved. +// Description: H file for lgobals.cpp. Contains global variables and helper +// functions +// +// History: +// +// MM/DD/YY Inits Description of Change +// 02/02/98 ADL Original +//***************************************************************************** + +#if !defined LEASHGLOBALS_H +#define LEASHGLOBALS_H + +#include +#include +#include +#include +#include + +typedef struct TicketList +{ + char* theTicket; + TicketList* next; + char* tktEncType; + char* keyEncType; + int addrCount; + char ** addrList; + char * name; + char * inst; + char * realm; +} TicketList; + +// toolhelp functions +TYPEDEF_FUNC( + HANDLE, + WINAPI, + CreateToolhelp32Snapshot, + (DWORD, DWORD) + ); +TYPEDEF_FUNC( + BOOL, + WINAPI, + Module32First, + (HANDLE, LPMODULEENTRY32) + ); +TYPEDEF_FUNC( + BOOL, + WINAPI, + Module32Next, + (HANDLE, LPMODULEENTRY32) + ); + +// psapi functions +TYPEDEF_FUNC( + DWORD, + WINAPI, + GetModuleFileNameExA, + (HANDLE, HMODULE, LPSTR, DWORD) + ); +TYPEDEF_FUNC( + BOOL, + WINAPI, + EnumProcessModules, + (HANDLE, HMODULE*, DWORD, LPDWORD) + ); + +#define pGetModuleFileNameEx pGetModuleFileNameExA + +// leash functions +TYPEDEF_FUNC( + long, + WINAPIV, + not_an_API_LeashKRB4GetTickets, + (TICKETINFO *, TicketList **) + ); +TYPEDEF_FUNC( + long, + WINAPIV, + not_an_API_LeashKRB5GetTickets, + (TICKETINFO *, TicketList **, krb5_context *) + ); +TYPEDEF_FUNC( + long, + WINAPIV, + not_an_API_LeashAFSGetToken, + (TICKETINFO *, TicketList **, char *) + ); +TYPEDEF_FUNC( + long, + WINAPIV, + not_an_API_LeashFreeTicketList, + (TicketList**) + ); +TYPEDEF_FUNC( + long, + WINAPIV, + not_an_API_LeashGetTimeServerName, + (char *, const char*) + ); + +extern DECL_FUNC_PTR(not_an_API_LeashKRB4GetTickets); +extern DECL_FUNC_PTR(not_an_API_LeashKRB5GetTickets); +extern DECL_FUNC_PTR(not_an_API_LeashAFSGetToken); +extern DECL_FUNC_PTR(not_an_API_LeashFreeTicketList); +extern DECL_FUNC_PTR(not_an_API_LeashGetTimeServerName); +extern DECL_FUNC_PTR(Leash_kdestroy); +extern DECL_FUNC_PTR(Leash_changepwd_dlg); +extern DECL_FUNC_PTR(Leash_changepwd_dlg_ex); +extern DECL_FUNC_PTR(Leash_kinit_dlg); +extern DECL_FUNC_PTR(Leash_kinit_dlg_ex); +extern DECL_FUNC_PTR(Leash_timesync); +extern DECL_FUNC_PTR(Leash_get_default_lifetime); +extern DECL_FUNC_PTR(Leash_set_default_lifetime); +extern DECL_FUNC_PTR(Leash_get_default_forwardable); +extern DECL_FUNC_PTR(Leash_set_default_forwardable); +extern DECL_FUNC_PTR(Leash_get_default_renew_till); +extern DECL_FUNC_PTR(Leash_set_default_renew_till); +extern DECL_FUNC_PTR(Leash_get_default_noaddresses); +extern DECL_FUNC_PTR(Leash_set_default_noaddresses); +extern DECL_FUNC_PTR(Leash_get_default_proxiable); +extern DECL_FUNC_PTR(Leash_set_default_proxiable); +extern DECL_FUNC_PTR(Leash_get_default_publicip); +extern DECL_FUNC_PTR(Leash_set_default_publicip); +extern DECL_FUNC_PTR(Leash_get_default_use_krb4); +extern DECL_FUNC_PTR(Leash_set_default_use_krb4); +extern DECL_FUNC_PTR(Leash_get_default_life_min); +extern DECL_FUNC_PTR(Leash_set_default_life_min); +extern DECL_FUNC_PTR(Leash_get_default_life_max); +extern DECL_FUNC_PTR(Leash_set_default_life_max); +extern DECL_FUNC_PTR(Leash_get_default_renew_min); +extern DECL_FUNC_PTR(Leash_set_default_renew_min); +extern DECL_FUNC_PTR(Leash_get_default_renew_max); +extern DECL_FUNC_PTR(Leash_set_default_renew_max); +extern DECL_FUNC_PTR(Leash_get_default_renewable); +extern DECL_FUNC_PTR(Leash_set_default_renewable); +extern DECL_FUNC_PTR(Leash_get_lock_file_locations); +extern DECL_FUNC_PTR(Leash_set_lock_file_locations); +extern DECL_FUNC_PTR(Leash_get_default_uppercaserealm); +extern DECL_FUNC_PTR(Leash_set_default_uppercaserealm); +extern DECL_FUNC_PTR(Leash_get_default_mslsa_import); +extern DECL_FUNC_PTR(Leash_set_default_mslsa_import); +extern DECL_FUNC_PTR(Leash_get_default_preserve_kinit_settings); +extern DECL_FUNC_PTR(Leash_set_default_preserve_kinit_settings); +extern DECL_FUNC_PTR(Leash_import); +extern DECL_FUNC_PTR(Leash_importable); +extern DECL_FUNC_PTR(Leash_renew); +extern DECL_FUNC_PTR(Leash_reset_defaults); + +#define pLeashKRB4GetTickets pnot_an_API_LeashKRB4GetTickets +#define pLeashKRB5GetTickets pnot_an_API_LeashKRB5GetTickets +#define pLeashAFSGetToken pnot_an_API_LeashAFSGetToken +#define pLeashFreeTicketList pnot_an_API_LeashFreeTicketList +#define pLeashGetTimeServerName pnot_an_API_LeashGetTimeServerName + +// krb4 functions +extern DECL_FUNC_PTR(set_krb_debug); +extern DECL_FUNC_PTR(set_krb_ap_req_debug); +extern DECL_FUNC_PTR(krb_get_krbconf2); +extern DECL_FUNC_PTR(krb_get_krbrealm2); +extern DECL_FUNC_PTR(tkt_string); +extern DECL_FUNC_PTR(krb_set_tkt_string); +extern DECL_FUNC_PTR(krb_realmofhost); +extern DECL_FUNC_PTR(krb_get_lrealm); +extern DECL_FUNC_PTR(krb_get_krbhst); + +// psapi functions +extern DECL_FUNC_PTR(GetModuleFileNameExA); +extern DECL_FUNC_PTR(EnumProcessModules); + +// toolhelp functions +extern DECL_FUNC_PTR(CreateToolhelp32Snapshot); +extern DECL_FUNC_PTR(Module32First); +extern DECL_FUNC_PTR(Module32Next); + +// krb5 functions +extern DECL_FUNC_PTR(krb5_cc_default_name); +extern DECL_FUNC_PTR(krb5_cc_set_default_name); +extern DECL_FUNC_PTR(krb5_get_default_config_files); +extern DECL_FUNC_PTR(krb5_free_config_files); +extern DECL_FUNC_PTR(krb5_free_context); +extern DECL_FUNC_PTR(krb5_get_default_realm); +extern DECL_FUNC_PTR(krb5_free_default_realm); +extern DECL_FUNC_PTR(krb5_cc_get_principal); +extern DECL_FUNC_PTR(krb5_build_principal); +extern DECL_FUNC_PTR(krb5_c_random_make_octets); +extern DECL_FUNC_PTR(krb5_get_init_creds_password); +extern DECL_FUNC_PTR(krb5_free_cred_contents); +extern DECL_FUNC_PTR(krb5_cc_resolve); +extern DECL_FUNC_PTR(krb5_unparse_name); +extern DECL_FUNC_PTR(krb5_free_unparsed_name); +extern DECL_FUNC_PTR(krb5_free_principal); +extern DECL_FUNC_PTR(krb5_cc_close); +// extern DECL_FUNC_PTR(krb5_get_host_realm); + +// profile functions +extern DECL_FUNC_PTR(profile_release); +extern DECL_FUNC_PTR(profile_init); +extern DECL_FUNC_PTR(profile_flush); +extern DECL_FUNC_PTR(profile_rename_section); +extern DECL_FUNC_PTR(profile_update_relation); +extern DECL_FUNC_PTR(profile_clear_relation); +extern DECL_FUNC_PTR(profile_add_relation); +extern DECL_FUNC_PTR(profile_get_relation_names); +extern DECL_FUNC_PTR(profile_get_subsection_names); +extern DECL_FUNC_PTR(profile_get_values); +extern DECL_FUNC_PTR(profile_free_list); +extern DECL_FUNC_PTR(profile_abandon); +extern DECL_FUNC_PTR(profile_get_string); +extern DECL_FUNC_PTR(profile_release_string); + +#define SKIP_MINSIZE 0 +#define LEFT_SIDE 1 +#define RIGHT_SIDE 2 +#define TOP_SIDE 3 +#define RESET_MINSIZE 4 +#define BOTTOM_SIDE 6 + +#define ADMIN_SERVER "admin_server" + +#define ON 1 +#define OFF 0 +#define TRUE_FLAG 1 +#define FALSE_FLAG 0 +#define LEASHDLL "leashw32.dll" +#define KERB4DLL "krbv4w32.dll" +#define KERB5DLL "krb5_32.dll" +#define KERB5_PPROFILE_DLL "xpprof32.dll" +#define SECUR32DLL "secur32.dll" + +#define KRB_FILE "KRB.CON" +#define KRBREALM_FILE "KRBREALM.CON" +#define TICKET_FILE "TICKET.KRB" +#define WIN95_AUTOEXEC "C:\\AUTOEXEC.BAT" + +#define LEASH_HELP_FILE "leash32.chm" + +extern int config_boolean_to_int(const char *); +extern BOOL SetRegistryVariable(const CString& regVariable, + const CString& regValue, + const char* regSubKey = "Software\\MIT\\Leash32\\Settings"); +extern VOID LeashErrorBox(LPCSTR errorMsg, LPCSTR insertedString, + LPCSTR errorFlag = "Error"); + + +class Directory +{ + CHAR m_savCurPath[MAX_PATH]; + CString m_pathToValidate; + +public: + Directory(LPCSTR pathToValidate); + virtual ~Directory(); + + BOOL IsValidDirectory(); + BOOL IsValidFile(); +}; + +class TicketInfoWrapper { + public: + HANDLE lockObj; + TICKETINFO Krb4; + TICKETINFO Krb5; + TICKETINFO Afs; +}; +extern TicketInfoWrapper ticketinfo; + +#endif diff --git a/src/windows/leash/MainFrm.cpp b/src/windows/leash/MainFrm.cpp new file mode 100644 index 000000000..b2d20cc1a --- /dev/null +++ b/src/windows/leash/MainFrm.cpp @@ -0,0 +1,465 @@ +// ************************************************************************************** +// File: MainFrm.cpp +// By: Arthur David Leather +// Created: 12/02/98 +// Copyright @1998 Massachusetts Institute of Technology - All rights reserved. +// Description: CPP file for MainFrm.h. Contains variables and functions +// for Leash +// +// History: +// +// MM/DD/YY Inits Description of Change +// 12/02/98 ADL Original +// ************************************************************************************** + + +#include "stdafx.h" +#include "Leash.h" +#include "MainFrm.h" +#include "lglobals.h" +//#include "KrbRealmHostMaintenance.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CMainFrame + +#define MIN_LEFT 179 +#define MIN_TOP 61 +#define MIN_RIGHT 530 +#define MIN_BOTTOM 280 + +CStatusBar CMainFrame::m_wndStatusBar; +CToolBar CMainFrame::m_wndToolBar; +CImageList CMainFrame::m_imageList; +CImageList CMainFrame::m_disabledImageList; +BOOL CMainFrame::m_isMinimum; +BOOL CMainFrame::m_isBeingResized; +int CMainFrame::m_whatSide; + +IMPLEMENT_DYNCREATE(CMainFrame, CLeashFrame) + +BEGIN_MESSAGE_MAP(CMainFrame, CLeashFrame) + //{{AFX_MSG_MAP(CMainFrame) + ON_WM_CREATE() + ON_COMMAND(ID_RESET_WINDOW_SIZE, OnResetWindowSize) + ON_WM_SIZING() + ON_WM_CLOSE() + ON_WM_GETMINMAXINFO() + ON_COMMAND(ID_APP_EXIT, OnClose) + //}}AFX_MSG_MAP + // Global help commands + ON_COMMAND(ID_HELP_LEASH_, CMainFrame::OnHelpFinder) + ON_COMMAND(ID_HELP, CMainFrame::OnHelp) + ON_COMMAND(ID_CONTEXT_HELP, CMainFrame::OnContextHelp) +END_MESSAGE_MAP() + +static UINT indicators[] = +{ + ID_SEPARATOR, // status line indicator + ID_SEPARATOR, + ID_SEPARATOR, + ID_SEPARATOR +}; + + +///////////////////////////////////////////////////////////////////////////// +// CMainFrame construction/destruction + +CMainFrame::CMainFrame() +{ + m_winRectLeft = 0; + m_winRectTop = 0; + m_winRectRight = 0; + m_winRectBottom = 0; + m_whatSide = RESET_MINSIZE; + m_isMinimum = FALSE; + m_isBeingResized = FALSE; + m_bOwnerCreated = FALSE; +} + +CMainFrame::~CMainFrame() +{ +} + +int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) +{ + if (CLeashFrame::OnCreate(lpCreateStruct) == -1) + return -1; + + ShowWindow(SW_HIDE); + +/* NT4 and NT5 aren't shipped with a version of MFC that supports +// 'CreateEx()' as of 2/1/99 +#if _MFC_VER > 0x0421 + + if (!m_wndToolBar.CreateEx(this) || + !m_wndToolBar.LoadToolBar(IDR_MAINFRAME)) + { + TRACE0("Failed to create toolbar\n"); + return -1; // fail to create + } + +#else + + if (!m_wndToolBar.Create(this) || + !m_wndToolBar.LoadToolBar(IDR_MAINFRAME)) + { + TRACE0("Failed to create toolbar\n"); + return -1; // fail to create + } + +#endif +*/ + + if (!m_wndToolBar.Create(this) || + !m_wndToolBar.LoadToolBar(IDR_MAINFRAME)) + { + MessageBox("There is problem creating the Leash Toolbar!", + "Error", MB_OK); + TRACE0("Failed to create toolbar\n"); + return -1; // fail to create + } + + // Create an image list of Icons so that we can use the best color + // depth available on the system and then assign this new list to + // be used instead of the single bitmap file assigned to the toolbar + // in the resource file + CToolBarCtrl *_toolBar = NULL; + CToolBarCtrl& toolBar = CMainFrame::m_wndToolBar.GetToolBarCtrl(); + HICON hIcon[7]; + int n; + + for (n = 0; n < 7; n++) + { + hIcon[n] = NULL; + } + + UINT bitsPerPixel = GetDeviceCaps( ::GetDC(::GetDesktopWindow()), BITSPIXEL); + UINT ilcColor; + if ( bitsPerPixel >= 32 ) + ilcColor = ILC_COLOR32; + else if ( bitsPerPixel >= 24 ) + ilcColor = ILC_COLOR24; + else if ( bitsPerPixel >= 16 ) + ilcColor = ILC_COLOR16; + else if ( bitsPerPixel >= 8 ) + ilcColor = ILC_COLOR8; + else + ilcColor = ILC_COLOR; + + m_imageList.Create(18, 18, ilcColor | ILC_MASK, 8, 4); + m_imageList.SetBkColor(GetSysColor(COLOR_BTNFACE)); + + hIcon[0] = AfxGetApp()->LoadIcon(IDI_TOOLBAR_INIT); + hIcon[1] = AfxGetApp()->LoadIcon(IDI_TOOLBAR_RENEW); + hIcon[2] = AfxGetApp()->LoadIcon(IDI_TOOLBAR_IMPORT); + hIcon[3] = AfxGetApp()->LoadIcon(IDI_TOOLBAR_DESTROY); + hIcon[4] = AfxGetApp()->LoadIcon(IDI_TOOLBAR_PASSWORD); + hIcon[5] = AfxGetApp()->LoadIcon(IDI_TOOLBAR_REFRESH); + hIcon[6] = AfxGetApp()->LoadIcon(IDI_TOOLBAR_SYNC); + + for (n = 0; n < 7; n++) + { + m_imageList.Add(hIcon[n]); + } + toolBar.SetImageList(&m_imageList); + + m_disabledImageList.Create(18, 18, ilcColor | ILC_MASK, 8, 4); + m_disabledImageList.SetBkColor(GetSysColor(COLOR_INACTIVECAPTIONTEXT)); + + hIcon[0] = AfxGetApp()->LoadIcon(IDI_TOOLBAR_INIT_DISABLED); + hIcon[1] = AfxGetApp()->LoadIcon(IDI_TOOLBAR_RENEW_DISABLED); + hIcon[2] = AfxGetApp()->LoadIcon(IDI_TOOLBAR_IMPORT_DISABLED); + hIcon[3] = AfxGetApp()->LoadIcon(IDI_TOOLBAR_DESTROY_DISABLED); + hIcon[4] = AfxGetApp()->LoadIcon(IDI_TOOLBAR_PASSWORD_DISABLED); + hIcon[5] = AfxGetApp()->LoadIcon(IDI_TOOLBAR_REFRESH_DISABLED); + hIcon[6] = AfxGetApp()->LoadIcon(IDI_TOOLBAR_SYNC_DISABLED); + + for (n = 0; n < 7; n++) + { + m_disabledImageList.Add(hIcon[n]); + } + toolBar.SetDisabledImageList(&m_disabledImageList); + + if (!m_wndStatusBar.Create(this) || + !m_wndStatusBar.SetIndicators(indicators, + (CLeashApp::m_hAfsDLL ? 4 : 3))) + { + MessageBox("There is problem creating the Leash Status Bar!", + "Error", MB_OK); + TRACE0("Failed to create status bar\n"); + return -1; // fail to create + } + + // TODO: Remove this if you don't want tool tips or a resizeable toolbar + m_wndToolBar.SetBarStyle(m_wndToolBar.GetBarStyle() | + CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC); + + // TODO: Delete these three lines if you don't want the toolbar to + // be dockable + m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY); + EnableDocking(CBRS_ALIGN_ANY); + //DockControlBar(&m_wndToolBar); + + return 0; +} + +BOOL CMainFrame::PreTranslateMessage(MSG* pMsg) +{ + if ( pMsg->message == WM_SYSCOMMAND && (pMsg->wParam & 0xfff0) == SC_CLOSE ) + { + return TRUE; + } + return CLeashFrame::PreTranslateMessage(pMsg); +} + +BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) +{ + // Use the specific class name we established earlier + // Remove the Minimize and Maximize buttons + cs.style &= ~WS_MINIMIZEBOX; + cs.style &= ~WS_MAXIMIZEBOX; + // Initialize the extended window style to display a TaskBar entry with WS_EX_APPWINDOW + cs.dwExStyle |= WS_EX_APPWINDOW; + cs.dwExStyle |= WS_EX_OVERLAPPEDWINDOW ; + cs.lpszClass = _T("LEASH.0WNDCLASS"); + cs.lpszName = _T("Leash32"); + + CString strText = AfxGetApp()->GetProfileString(CLeashFrame::s_profileHeading, + CLeashFrame::s_profileRect); + if (!strText.IsEmpty()) + { + CRect rect; + + rect.left = atoi((const char*) strText); + rect.top = atoi((const char*) strText + 5); + rect.right = atoi((const char*) strText + 10); + rect.bottom = atoi((const char*) strText + 15); + + cs.x = rect.left; + cs.y = rect.top; + cs.cx = rect.right - rect.left; + cs.cy = rect.bottom - rect.top; + + if ( cs.x < 0 ) + cs.x = CW_USEDEFAULT; + if ( cs.y < 0 ) + cs.y = CW_USEDEFAULT; + if ( cs.cx <= 0 ) + cs.cx = CLeashFrame::s_rectDefault.right; + if ( cs.cy <= 0 ) + cs.cy = CLeashFrame::s_rectDefault.bottom; + } + else + { + cs.cx = CLeashFrame::s_rectDefault.right; + cs.cy = CLeashFrame::s_rectDefault.bottom; + cs.y = CW_USEDEFAULT; + cs.x = CW_USEDEFAULT; + } + + // Change the following line to call + // CLeashFrame::PreCreateWindow(cs) if this is an SDI application. + if (!CLeashFrame::PreCreateWindow(cs)) + return FALSE; + + // We create a parent window for our application to ensure that + // it has an owner. This way we can disable the TaskBar entry + // by removing the WS_EX_APPWINDOW style later on. + if ( !m_bOwnerCreated ) + { + m_bOwnerCreated = m_MainFrameOwner.Create(IDD_FRAMEOWNER); + if ( m_bOwnerCreated ) + m_MainFrameOwner.ShowWindow(SW_HIDE); + } + if ( m_bOwnerCreated ) + cs.hwndParent = m_MainFrameOwner.GetSafeHwnd(); + + return TRUE; +} + + +BOOL CMainFrame::ShowTaskBarButton(BOOL bVisible) +{ + if (!m_bOwnerCreated) + return FALSE; + + if (bVisible) { + ShowWindow(SW_HIDE); + ModifyStyleEx(0, WS_EX_APPWINDOW); + ShowWindow(SW_SHOW); + } else { + ShowWindow(SW_HIDE); + ModifyStyleEx(WS_EX_APPWINDOW, 0); + ShowWindow(SW_SHOW); + } + return TRUE; +} + +///////////////////////////////////////////////////////////////////////////// +// CMainFrame diagnostics + +#ifdef _DEBUG +void CMainFrame::AssertValid() const +{ + CLeashFrame::AssertValid(); +} + +void CMainFrame::Dump(CDumpContext& dc) const +{ + CLeashFrame::Dump(dc); +} + +#endif //_DEBUG + +///////////////////////////////////////////////////////////////////////////// +// CMainFrame message handlers + +void CMainFrame::OnResetWindowSize() +{ + WINDOWPLACEMENT wndpl; + wndpl.length = sizeof(WINDOWPLACEMENT); + + if (!GetWindowPlacement(&wndpl)) + { + MessageBox("There is a problem getting Leash Window size!", + "Error", MB_OK); + return; + } + + wndpl.rcNormalPosition = CLeashFrame::s_rectDefault; + + m_whatSide = SKIP_MINSIZE; + + if (!SetWindowPlacement(&wndpl)) + { + MessageBox("There is a problem setting Leash Window size!", + "Error", MB_OK); + } + + m_whatSide = RESET_MINSIZE; +} + +void CMainFrame::OnSizing(UINT fwSide, LPRECT pRect) +{ // Keeps track of Leash window size for function CMainFrame::RecalcLayout + m_winRectLeft = pRect->left; + m_winRectTop = pRect->top; + m_winRectRight = pRect->right; + m_winRectBottom = pRect->bottom; + + if (m_whatSide) + m_whatSide = fwSide; + + CLeashFrame::OnSizing(fwSide, pRect); +} + +void CMainFrame::RecalcLayout(BOOL bNotify) +{ // MINSIZE - Insurance that we have a minimum Leash window size + int width = MIN_RIGHT - MIN_LEFT; + int height = MIN_BOTTOM - MIN_TOP; + + BOOL change = FALSE; + WINDOWPLACEMENT wndpl; + wndpl.length = sizeof(WINDOWPLACEMENT); + + if (!GetWindowPlacement(&wndpl)) + { + MessageBox("There is a problem getting Leash Window size!", + "Error", MB_OK); + return; + } + + if (m_whatSide) + { + if ((m_winRectRight - m_winRectLeft) < width) + { + if (m_whatSide == LEFT_SIDE) { + wndpl.rcNormalPosition.left = wndpl.rcNormalPosition.right - width; + change = TRUE; + } else if (m_whatSide == RIGHT_SIDE) { + wndpl.rcNormalPosition.right = wndpl.rcNormalPosition.left + width; + change = TRUE; + } + } + else if ((m_winRectBottom - m_winRectTop) < height) + { + if (m_whatSide == TOP_SIDE) { + wndpl.rcNormalPosition.top = wndpl.rcNormalPosition.bottom - height; + change = TRUE; + } else if (m_whatSide == BOTTOM_SIDE) { + wndpl.rcNormalPosition.bottom = wndpl.rcNormalPosition.top + height; + change = TRUE; + } + } + } + + if ( change ) { + if (!SetWindowPlacement(&wndpl)) + { + MessageBox("There is a problem setting Leash Window size!", + "Error", MB_OK); + } + } + m_isBeingResized = TRUE; + + CLeashFrame::RecalcLayout(bNotify); +} + + +void CMainFrame::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI) +{ + lpMMI->ptMinTrackSize.x = 650; + lpMMI->ptMinTrackSize.y = 240; + CLeashFrame::OnGetMinMaxInfo(lpMMI); +} + +void CMainFrame::OnClose(void) +{ + CLeashFrame::OnClose(); +} + +LRESULT CMainFrame::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) +{ + BOOL oldMin = m_isMinimum; + switch(message) + { + case WM_SIZE: + switch ( wParam ) { + case SIZE_MINIMIZED: + m_isMinimum = TRUE; + break; + case SIZE_MAXIMIZED: + case SIZE_RESTORED: + m_isMinimum = FALSE; + break; + } + break; + } + + if ( oldMin != m_isMinimum ) { + if ( m_isMinimum ) { + ShowTaskBarButton(FALSE); + ShowWindow(SW_HIDE); + } + } + return CLeashFrame::WindowProc(message, wParam, lParam); +} + +/* +void CMainFrame::OnHelp() +{ + +} +*/ + +/* +void CMainFrame::OnContextHelp() +{ + +} +*/ \ No newline at end of file diff --git a/src/windows/leash/MainFrm.h b/src/windows/leash/MainFrm.h new file mode 100644 index 000000000..1ccfcfd6b --- /dev/null +++ b/src/windows/leash/MainFrm.h @@ -0,0 +1,92 @@ +// ************************************************************************************** +// File: MainFrm.h +// By: Arthur David Leather +// Created: 12/02/98 +// Copyright @1998 Massachusetts Institute of Technology - All rights reserved. +// Description: H file for MainFrm.cpp. Contains variables and functions +// for Leash +// +// History: +// +// MM/DD/YY Inits Description of Change +// 12/02/98 ADL Original +// ************************************************************************************** + + +#if !defined(AFX_MAINFRM_H__6F45AD95_561B_11D0_8FCF_00C04FC2A0C2__INCLUDED_) +#define AFX_MAINFRM_H__6F45AD95_561B_11D0_8FCF_00C04FC2A0C2__INCLUDED_ + +#if _MSC_VER >= 1000 +#pragma once +#endif // _MSC_VER >= 1000 + +#include "LeashFrame.h" + +class CMainFrame : public CLeashFrame +{ +private: + int m_winRectLeft; + int m_winRectTop; + int m_winRectRight; + int m_winRectBottom; + BOOL m_bOwnerCreated; + CDialog m_MainFrameOwner; + +protected: // create from serialization only + CMainFrame(); + DECLARE_DYNCREATE(CMainFrame) + +// Attributes +public: + static int m_whatSide; + static CStatusBar m_wndStatusBar; + static CToolBar m_wndToolBar; + static BOOL m_isMinimum; + static BOOL m_isBeingResized; + static CImageList m_imageList; + static CImageList m_disabledImageList; + +// Operations +public: +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CMainFrame) + public: + virtual BOOL PreCreateWindow(CREATESTRUCT& cs); + virtual void RecalcLayout(BOOL bNotify = TRUE); + virtual BOOL PreTranslateMessage(MSG* pMsg); + protected: + virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam); + //}}AFX_VIRTUAL + +// Implementation +public: + virtual ~CMainFrame(); +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + BOOL ShowTaskBarButton(BOOL bVisible); + +protected: // control bar embedded members + + +// Generated message map functions +protected: + //{{AFX_MSG(CMainFrame) + afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); + afx_msg void OnResetWindowSize(); + afx_msg void OnSizing(UINT fwSide, LPRECT pRect); + afx_msg void OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI); + afx_msg void OnClose(void); + //afx_msg void OnContextHelp(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Developer Studio will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_MAINFRM_H__6F45AD95_561B_11D0_8FCF_00C04FC2A0C2__INCLUDED_) diff --git a/src/windows/leash/StdAfx.cpp b/src/windows/leash/StdAfx.cpp new file mode 100644 index 000000000..ef6942b3d --- /dev/null +++ b/src/windows/leash/StdAfx.cpp @@ -0,0 +1,5 @@ +// stdafx.cpp : source file that includes just the standard includes +// Leash.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" diff --git a/src/windows/leash/StdAfx.h b/src/windows/leash/StdAfx.h new file mode 100644 index 000000000..6b8d0684a --- /dev/null +++ b/src/windows/leash/StdAfx.h @@ -0,0 +1,27 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#if _MSC_VER >= 1000 +#pragma once +#endif // _MSC_VER >= 1000 + +#if !defined(AFX_STDAFX_H__6F45AD93_561B_11D0_8FCF_00C04FC2A0C2__INCLUDED_) +#define AFX_STDAFX_H__6F45AD93_561B_11D0_8FCF_00C04FC2A0C2__INCLUDED_ + +#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers + +#include // MFC core and standard components +#include // MFC extensions +#include // MFC OLE automation classes +#ifndef _AFX_NO_AFXCMN_SUPPORT +#include // MFC support for Windows Common Controls +#include "htmlhelp.h" + +#endif // _AFX_NO_AFXCMN_SUPPORT + +//{{AFX_INSERT_LOCATION}} +// Microsoft Developer Studio will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_STDAFX_H__6F45AD93_561B_11D0_8FCF_00C04FC2A0C2__INCLUDED_) diff --git a/src/windows/leash/VSroutines.c b/src/windows/leash/VSroutines.c new file mode 100644 index 000000000..63f0b4ae1 --- /dev/null +++ b/src/windows/leash/VSroutines.c @@ -0,0 +1,64 @@ +#include +#include + +#if 0 +//#ifdef USE_VS +#include + +#define ININAME "leash.ini" + +int VScheckVersion(HWND hWnd, HANDLE hThisInstance) +{ + VS_Request vrequest; + VS_Status status; + BOOL ok_to_continue; + HCURSOR hcursor; + char szFilename[255]; + char szVerQ[90]; + char *cp; + LPSTR lpAppVersion; + LPSTR lpAppName; + LONG FAR *lpLangInfo; + DWORD hVersionInfoID; + DWORD size; + GLOBALHANDLE hVersionInfo; + LPSTR lpVersionInfo; + int dumint; + int retval; + + GetModuleFileName(hThisInstance, (LPSTR)szFilename, 255); + size = GetFileVersionInfoSize((LPSTR) szFilename, &hVersionInfoID); + hVersionInfo = GlobalAlloc(GHND, size); + lpVersionInfo = GlobalLock(hVersionInfo); + retval = GetFileVersionInfo(szFilename, hVersionInfoID, size, + lpVersionInfo); + retval = VerQueryValue(lpVersionInfo, "\\VarFileInfo\\Translation", + (LPSTR FAR *)&lpLangInfo, &dumint); + wsprintf(szVerQ, "\\StringFileInfo\\%04x%04x\\", + LOWORD(*lpLangInfo), HIWORD(*lpLangInfo)); + cp = szVerQ + lstrlen(szVerQ); + lstrcpy(cp, "ProductName"); + retval = VerQueryValue(lpVersionInfo, szVerQ, &lpAppName, &dumint); + lstrcpy(cp, "ProductVersion"); + + retval = VerQueryValue(lpVersionInfo, szVerQ, &lpAppVersion, &dumint); + hcursor = SetCursor(LoadCursor((HINSTANCE)NULL, IDC_WAIT)); + vrequest = VSFormRequest(lpAppName, lpAppVersion, ININAME, NULL, hWnd, + V_CHECK_AND_LOG); + if ((ok_to_continue = (ReqStatus(vrequest) != V_E_CANCEL)) + && v_complain((status = VSProcessRequest(vrequest)), ININAME)) + WinVSReportRequest(vrequest, hWnd, "Version Server Status Report"); + if (ok_to_continue && status == V_REQUIRED) + ok_to_continue = FALSE; + VSDestroyRequest(vrequest); + SetCursor(hcursor); + GlobalUnlock(hVersionInfo); + GlobalFree(hVersionInfo); + return(ok_to_continue); +} +#else +int VScheckVersion(HWND hWnd, HANDLE hThisInstance) +{ + return(1); +} +#endif diff --git a/src/windows/leash/reminder.h b/src/windows/leash/reminder.h new file mode 100644 index 000000000..05dd4bddd --- /dev/null +++ b/src/windows/leash/reminder.h @@ -0,0 +1,12 @@ +#ifndef __REMINDER_H__ +#define __REMINDER_H__ + +#define Stringize( L ) #L +#define MakeString( M, L ) M(L) +#define $LINE MakeString( Stringize, __LINE__ ) +#define Reminder __FILE__ "(" $LINE ") : Reminder: " + +#endif + +//Put this in your .cpp file where ever you need it (NOTE: Don't end this statement with a ';' char) +//i.e. -->> #pragma message(Reminder "Your message reminder here!!!") diff --git a/src/windows/leash/res/Leash.ico b/src/windows/leash/res/Leash.ico new file mode 100644 index 0000000000000000000000000000000000000000..9ef4f96ffcb8230f5111a031e4a4bbf17481f5b9 GIT binary patch literal 25214 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 Iwf~sD0eXUYg#Z8m literal 0 HcmV?d00001 diff --git a/src/windows/leash/res/Leash_Doc.ico b/src/windows/leash/res/Leash_Doc.ico new file mode 100644 index 0000000000000000000000000000000000000000..323cd6183e744efd08d27bd4e5f5d93b54ea10bd GIT binary patch literal 25214 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 B^d$fQ literal 0 HcmV?d00001 diff --git a/src/windows/leash/res/Leash_tickets_green.ico b/src/windows/leash/res/Leash_tickets_green.ico new file mode 100644 index 0000000000000000000000000000000000000000..0d2f04e5b5634883b95c669852f619bd71cefade GIT binary patch literal 25214 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 F{|CYmUmn2abBnZ&K=qilu%+^j{!EIA}l@ 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 literal 0 HcmV?d00001 diff --git a/src/windows/leash/res/Leash_tickets_out.ico b/src/windows/leash/res/Leash_tickets_out.ico new file mode 100644 index 0000000000000000000000000000000000000000..7a9b377dd44ef8b47f494b25a99c2637164d1870 GIT binary patch literal 25214 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 G{r>}D=}egb literal 0 HcmV?d00001 diff --git a/src/windows/leash/res/Leash_tickets_red.ico b/src/windows/leash/res/Leash_tickets_red.ico new file mode 100644 index 0000000000000000000000000000000000000000..a1eb326d24cae48aaa9a534f8140e7538f7409d3 GIT binary patch literal 25214 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 literal 0 HcmV?d00001 diff --git a/src/windows/leash/res/Leash_tkt_red.ico b/src/windows/leash/res/Leash_tkt_red.ico new file mode 100644 index 0000000000000000000000000000000000000000..596a7bb6bef50d7acbe87544e03bf0c1cab5db72 GIT binary patch literal 25214 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 literal 0 HcmV?d00001 diff --git a/src/windows/leash/res/Leash_toolbar.bmp b/src/windows/leash/res/Leash_toolbar.bmp new file mode 100644 index 0000000000000000000000000000000000000000..0293306bcbe44bdee9c4d224dac65e9b4b302415 GIT binary patch literal 1270 zcmbtT!D<^Z5LLmT+-jG?X6d0}DI_=3^x&M$f_*9djY2QG&XSQ?s5T{_1s}qm5}*1D zg&rKx#h>I;<(v9OD~D1@pmbJRJ!bUuMk8tZ@z+2EyTbnr{VVz_^cSKJG%*g>U)BhL zCYq)n@COvz?G_^kd}zXZM(Ft1g&+N&f#1lu#4{kyC?L)Th8X0d1Ot&#F^OjY^M^!5 zTt`wdZ`(BO`Q&@24S%S2p(J8$@`(8LapqLZAli!`EEVx?%-o-=S=`wGhnrYCjjP;hC+h>F#r5u zq|)AZw`H2}n$XvtlLN~|@aPHP5B+AENB*&Q(64{ghBVW%>>OD!A0>jUT%zJ8gg7A@ zBBE?Q$Sw5!VEWekWg_aIHCd;3a&c}{rUB@3D1`Pqx$J0}a468}1n0;6cY*Ky*n0(i z3uD#A8BuEhNKqj;p)$SiP})cj=dV`zbPhh@>fUw^}l)jCGP*F_xn>ptdDGIaZ0op1CYF&G>*YCMQH%4U^6)@REzVA{7=Y#cHr-6 zF+t{Iy$An+8tnnP?jHI816(*+_`e9Ob@$G^^ZCj4+kUm|1XHXRt8t31i1o)hQQ#0^4cJo0T o8EihwP8ie{&x%2LN98btP(L)(uYbP$ep~DoJwDyI?!OP>Hw_Rv*8l(j literal 0 HcmV?d00001 diff --git a/src/windows/leash/res/Leash_user_green.ico b/src/windows/leash/res/Leash_user_green.ico new file mode 100644 index 0000000000000000000000000000000000000000..903616dd4d01d5e282238e341d6f953f0ad9d2ee GIT binary patch literal 25214 zcmeI33w%`7wf~Rz(;8x-piQ~TYeL=`5&|I)2#+Cb5J6| zqGD^UwY7JARvhh(Z}B;(m0F9nRS*Sr5C}l&whLM;U<{SRQFnV}4Y*?7jIKwaw z#T%42C_l*9@@2#L@|U!Hgdb!W&z`5{!~Ci*8pe{OX!%5AOR8aPPmh*|r`*-^qvaEg zRbMcS;Y$o70}M1_EQJ);i9bFwex>y20EI-nMNUkMs#;v>0X0iy?!# z9n2FRo&4v`U6y2vTUC-*yxhOK+P~ahnle0LL5V$(lzT;zas4uVkx*Qgkh*$NaY;(K zv}k2#@%+NeEPw*uCDQ zB*a^_y4+_k^(`nasSeCq=wA`WW5j)VVZ!DW?F&km5BFCrOr2$49mZqCZ7lOwRQoIV zAaz+;LV1NZCl@@%nzal0T(Q{gWeKy(9Bs)d;4$LXtVo>&_Uh6=S#e3;m78fd*-Mvy zvX*ASGrYoHUH->4L%qq#UdkJB*R51hP?;Cs7^>NyYeS%))+&*Np0F+8dz9eyrR9hWMfraoWb)pv%f}M)gphp zy(D2n6{Yq0jRm{WanSE%Yx>C@I}XC4HX%C>0@;SA`#I zyWU)Fw`whNUbL~^tVQe3-~})TyA`P)^I#|HRwG8F&ydH&U<6OvqiZdtIYsA&t(S`*z(dvz%LjB;pzMU6k%%jL}sP~*UZ;r9%N6S|D7T9~$uj)hn z8xv-grj{>_7LUqp?S|sg_KI0mCqA#b3DxwkSl93QcKh;#)rGyfv%3@Zz(3;(drY%}lrt~0vY@H3a3 ze(Q`kH)-9EQWli*=fgH{ZlV3_)snJKtga47VEx8*XI5jHS!ovfsw=!+?}Vz&nC6A4 z6~!xj7Uu0bgSpSTvM^sg3W{VS`meJud3o_4dCU8@jHC(1patQt;aNY{ z#jW)(D-X|3>OW_xan16CTf&ojsLCg<+P=En{G9S*lO|Mc2>2Go%IB=B@+~Y6MEDlU zt*u_YIa=Q2Oa1l zVb5uV%&MdxCujyy-TIGFh@lx|zmBygxcd9ATaTpqvH_!f|pUP3fLv~69>TfZ}0Hmf0!VYf;paBEI{Vu1qMVwZ<;f8lx+g)76Z7nuD)|N_-wc6#e1_UyM_hOyn;woZARF&RJqjHYR zsB96Va;agdY^k(Vu5ob{OQm7h;BA%QsT6?>JEb8PB#_~Nhg^_Ah7%rgK>`_Wc*q3_ zWO(2`m4jW7K!#Ai@Lnp*gew)cR2mM$WjOMLt6_0?D=qLAN3n1u`{8@$cYE?f;e z@9mB_m)%h=c6bN8gZB={EyC4s!aI5IK#4exeTx!jIL;)eIYd*D3|E(c1lA684h>{JS33egm=P2 z0vT?2H#{Ve;eq$SLjoCsWFY-dAj8;cR6;IDAj1L=xgdcI8$9HK1TyUKkP8yXaKJ+@ zNFc)r54j+L3^zRFf&?-=@Q@1<$PjqhIoJgW#Hdz-w8XHWJ&?;HZDNrm!zQaLZBpv8 zv5-NAT^J|vy6mF=EifFEhg=T2<&a#%DeaX`DRVg~4;gOCyCuivmSy4=yWycc-&pGe->!}5on&A&!%e8G@Ymk-0z ze{19Ix&Bjp5bcIpzP6^|)aCaK9=vCW{-X^nITaugO44J9@`Gw}Pl;!k)~*Dk593b- zNb4VF{%QHz+EW4Q-CxRocq%}B%Nw0{W~T_zMG1cTKJS%=*C3 z@S2z+^{ZC*D(^2?A5Ycc(prE1u>7<0^eQqtWtFIA;C5)j9Vh)l)vA|EB(+ z&9UlR3;J~y01JC|Q68QbfAJ_csj#HLL z`p4nt)||ThrsK*sWJy0=Q{;W{8y~7MF`F22Qt6*qzP5H#&0@vGH0(32VnXR#zba__ zl7d_{WhX;_V*ON8i^0O$3{d<8{NZL}#wLd1_|1uUj=wqi-M@bMzss44c6azsPA-mr zKmC6#0gY1=p_$M>5T~vqPTfYF+CrS_B2FbP#80+cD~VHG#HoaC@D6wfJn<@VDscw9 z6W$5$hIhle;oa~acn`b>-UBc20x$3aj~C8=l`exv>YZEQEbtb13%m{925*Bu9;bo_ z-p+dm?;X5%z&qfb@J@Iqyc6CH?}m57yWu_X9(WJD2VUR>UicGu0u16*@HoKZ01vzc z-U4rdx53-sZSXdDJG>p<4sVBdz&qd_@D6wy82i^nkffsmz z7kGguLLp8Cj|)8fS>P@37I+K14c-QCgSWxk;qCBtcsslU-U07`r%K{f@W4Cao$zjW zH@q9(4ex>Xz%1PIx!G8{Q4?hWEgG;63mjc!3vqftQ_(o`40A76AwM7C>4A9Pl=H z8@vtP4sVCI!`tB<@D6wfyaV0|?}T^4JK^2%Zg@Am8{Px&f%m|B1Wn;yxZkmZuvGX> zf>uIzLjs{$eB!(D8{3aBdWO1phFND(HXh;&A74d$r!H z|FO;$obWy}{)3_sd_lD9edQCCP3z*5zmJZ-zn5^RAtv8weBHPCp9zvV{Hu~aJVBDbnjneid_~4W ziD#b^CcTHooO8BGmUGVG%Db=dJb`Z#&X!d8QNzxO$~uOB+>eVS>nBq`le`U|O4|o- z$essplRLjrCYR=nmbs~ka$$0cTnP3H$By9&jU6o)ju|Bvjv66zMxQ6MMx86uM*OEt z9(kVR^K2s5>=7fxdhU5L?z|C_dEQ9wM{v(|#7G%8a)e}2ZXD&tjX00{Q8Iq?D9N>) zC%K6hNgFw~AO7!u?>gz|=#Z}VfOLBO5^D8HsKqN?CbdeS>6myM4v6ogx8?8)56P2` zRkF&Kjoe2`MM^3(RxSYheC-1?-va*8Bf&pHW<$l`DS`?{jg*OC9}kU#vcRjP{ZRa2 zUi){RjHe&tDX-TF$YWCCNGMSmAYE+`{pf6Mlg^e_2{pBf z|44)Q_wSOHKW~*ce|?ku_@WtdVah1EI5kZwQj-`5OALPndZhU0LM4#mp9)O|OP+}z zxvFf>i(Jk7bK%d8Vb1~k1mv!ii%#Yt6UCo3roa5px@wf1iaL%S75|}+#rwf_+4JOY z<(Dff<$UIW)lPng=OB^M6W0OuBf2gTNd`Aw+u>*gT!*4z*&#k*gR!tgb>du1n6uAf; z(mt5@En)og#-KycZ1B$*IZ~$3hkUNNT*r?*S0>Ph3FbYRBlkJ*6HS?qM&8IBozF+^ z`C~0oFg97TN1vYjL(Of{cJzoe*MA_s-LK28dpFAs=g*J}7}tx_!($NDq4_F*boK(M z94cijW}pvKp~=k0JgyVz(?oPCO1bd4l*^^RdC0v0xfg)FU~HlkVBZRol4VLtx=f-E z5qlrAKSRHrC||icWkAyR!Dhd-H#Li|@e}dy`-|**@nQMRH@_~6(wM8*(D|v!G7tHm zZ`#pOGLL?hgQINpXy))}v4LChPvtrpoOy~B{3bkoq~Sn zE71p~NtB(0&Z)jkNlZf5Q)D9RN?uB`*uY&S0YzZ<3 zIu0!oY&s;N`VU#pUXvY<{6c>EjS8_(NS4a9(J~+WW#FGho5kQM2LBB7XxgaJrv6L= zcae!dJO%|Sb0~^`hRQo7MGCQLMXZly$mFu|nR3ITx$@$#*2@!j-*S5RSrdZZcIjYE z>u5eI!NUinYc7+mo7T$P58N*MUwcfB?tDeOAOBTC zhwJ6#r=L76{LNix0tEon}b_yY@}{HI}(CRxY%r%GwL2$s>;C^6q1|O8p-mmWH>U zkcM~N((=h)#8+ zOSY_8BFiV`NJ(-k@?;DYJGO8N_H;7yx{!HYgk3C1N=4UGWKP-`xuVc2cP?Kj@7#O4 zwES_a`0#OkAN@(Z_=^7h?=!|9OUIG@wAX|!_sMI|K7U&HbsZ4qa3^y(sD9nCW)r{f z!25FKUB&+^x$oOc_&TUsDb->{PTbB}o6 zeGSYz#kYTt_zr#~zC-(@z2P9(8}S{FNT|70y8RvU+H)_Q9)A2%6F>5g;tw9K6aRtT z()`{l^1<)#k~@}F;?G%SMrx)^Ne3(Tdm6IVwZ9O%Xk(2o#wO0gKl)~2t~|Z|8fkpx z0cqRyvK;ZeCr1u_D!#*q#NT*`YlEoI7-+^`gFVEY>-Go5{cL~y1=Xc8`KCDoQsGTy z_|)i+>OT}Xh7G0e4q}2<+CBWvR@w2uZF2qjHrB3mWNekGnaMIe4O^a^&RC>l)6=Ak zb#wuC{o2_D^2~>L@)-JFrerpo=Q@GENqO?qz&Gl>9{`hNtYU0=UrKhcvc@mOtu6p0Y zeOD_y`rk=iL1Z6d?gsILeEZ&&BY%EQ-f`Y6>%V@1RAgFZ7T9h0S<^C7q&N-P6WlKtDClw+T~gN}b<>UTibbgvgu+e{nCD1@EUv5ry~a#j4>PJ;jQ z`47~GOoGTKz4i_FW$L9eppc=7h6;0f^k-vovHY(5PFnJej+1T zuAG)DkN@yH^6``R%As8^N%O&-%$-BhiOzI2V~bnRS8#?Dr^?wIH2b0WqtxRkw(aOT zZTSa}wPOpwPYe^R|5W^Y-jSWP_sK1ne@!l(m?iVGGG)#<w&PL}zZSu!sx2j4tPimhSUm(T~Bb(~zBl`aomvrP7F zy-$vO_=Yqc+#}w`dUG6AZ$kLAU9Di#wFMg&#cYm)Vx~XlGrd>+IZgZ_bh6`U3-QZA zX(tbH@b#zU5p?46-0?CuV}g`h$IC46+DzGJiitnnDwk$w$y3$W%Ar3!E{()(ZFL7E z(0CNwt>6mldl$N+_PNW4kAl5Z>`}QZcC#<4|Nnsg^t7t(9K&YRNe4LUUVA{C-?PgC zY)xrqwv;k&i?Ne4;nn`=94Jo7kR^H9^6aMX%i$d_O6&f;rrw8+9FuP5Q@74j?2KYn z-48~vY7D5jqZGsc56s`57HlSKmiNFu@nb(ediGax+Z7kdytFiAZN=_jqi&!N&UgD2<9%uta68-j`l#B*c!zTc4(&Jr!UKjCdkXbT*n&y3Vsdv zng3m^A)P9JunQPf-d*TT7yg0bjLu)h9~}d=Ki$D@dG+~M`mJA|$9{HVH~sij&3oPy z4>`n#tF9C~x>1IWQC%+q^DHo{-JFTdpP5O2c($B4Ai~;!eYU za^?9f#%AU0eEIW3o2BLbHyFP|W-hf8JJyXK*rWKOr23;6;d>%uV)iTAhtI(O;63+B zC>RpKf9S-|?9{Qu9(1!FcHx5r)m9v7X3hOT_H4UP9=dL+TwPEg^O&=?oDA?Y2gsky z!e^MJ_=!hmX3>X?RQYCkk?ef@m*U&=Cwv|7W5YU|+Du>2)E&hNsorSY-PqBX%ynGA zZ;r!f;D6}9?vLQ_>Se!l?NFZqe}vpy2R@;%ez$mDeMq)kyF{+awUV z?EP4=jl)l7EiPd#p2r@+di#9Y`^qEY`*fGIvv!2=Kf0+?WpBz^F(R){bf;7GU-3s} z{yFhKeE;vHGlZ{3{wMaWu7}L~PHbGTxg+e?Htv;Ue|u5>a&L{?zH}Zw8S55)WeN7O zjCI$B&P*SNPG#Xo@a&4BG1${DmAj zpZkj^Wy|JoEff#Fb(`mJ;;%nI%nWwcT+{YrdrbMOU!(Yuz1q+ovkze#+8c{$KL?n< zzyF=fl)qqK&2p-b5z=)%$Xx3p_ttfo*rH*dG}XN;jk{iv_aDDo9{cesaV)UO3hex4 ztiNAl9k^^_y4<#Ef&A&wpUbiL{~!V8eF(cBJc_@=SPK4v%HQ;9Xh-!%sY`7neb9F* zyU&ZicFSYZ8R!(ve~Q)-#jb6r{B?~Xf7{dK6F>I5xskldft|#CuS(rZ56Bz8{E;}X zUMx2+DwlN?#d7zzFO?4-zeA3ZZ}Ow}A>uTh{~>(M5PnoQ{zBCDn0qD2+|+-aqw2%a zUKGE!Z}vmq4Iuv~T>ow2H}ju5hGsqC@6`9!b+H?J-DBn*&?9WAzy6SP9Na7Zy*s37 z$4l}NYr@-)-Y##sZkK(p{~rJJEouMs1F#>It|LdKOMOlJoq*ai;-IMQ*SQ#AzCcn7t=W^%fpUYjh|3ZF!$6fN9U;Ik$x$|!M?OpfCeZO|fgTK9B z9=`V>aXqj_9((9fQ9G`-dQK}5nhBj@-f?sC-&s6Pg0i9U|0L43w9RPSE4knFPbO_M>8$wp zp5mFsGI#D=nOi zWX-#Gef*|8^@HWIcp~RehKOs{tM%MTCg*?j z3{WO#f2{E1Mx4v_T&^P}XAEZxXzxpd&Wg1^hW*!%_Usku>|t%xT&Bj*UTG&M(*DWc z{|}hemk*kJLgJ1 zdip-Odin&p02y4s_@B?7o1Vj%%bsn?X!bxk15gANAm`ZG3$RT>M+!LW5It{^$NstI zfX+T^P)z=boNMrW%z<9q2Gd80`I>qz0Y8eEqLp~!o;8YJ?dg~*#-tZL!jpe3L$M@&kktc&3#tdE#$0#o~gU8e1`nt z{>_q~GcMNuB=#`}l7FDhC++x=LCz=nK6*=bK6IR;Oc@H_>ze>TR3CG)KuXmvK&3$prb7+o({n&%s@F&(T zmBr*?rt2Q8xepEo_P}-jdj|b3qCbUsZ(`R2R=&P84>fB5wVIq=4Ri_h~mdCCSU z$jghhpUhtQK<%r)8B&`-ETCu14w2`7xn_+l$;px#?49Z!b`fJSg?;QI`ccS!r0&Vv z^Rwj9AAL&>y!1QqzW=hc?j=V=9Msv=K%Cqrg?ahM+vn`qK<#U6WwuX_v!lTy&E!b7 z-t;}Wgm`=kb730$xKqsYIGkx6X$lYx75YH zVHbN@lY6zF0_K6*H~UYl5YT-`>S?0=`>wg1ef)GOA}2PD{j4f(r5qV*O9S9v<9(0Q<`yF`mYIossxY^IQSW z6m;kr#eMI|?x+7tt}VB5&LNFGBy@l?e!7QxF?q(H{htN0=ec`11NAPpn|()Oo(|oQ z#h&ZAO^uOt4?y=k3-XV*pGy062M(I;_Yhl!V>bM3GX~Q07{pHX`{eLnUXm@}Un!N$ zonrQ)bsugzdCXbl2k%;XsqA~kNe=q2*bB}8>0Tc3n4YWAJeRrGMr^1ti{>B;d-Xq! zT-`wO4}m{;lz4OBZrOhSFXUUrlgZtsn|o=Rho8zm@+$Vw-nnO!9RBciX>0tHe2(Ve zu^SqT5*M1WuEy$+**^U*?A8Aa_Cg10U*p`+k%Myd?bqav_58I zyL~JBF$1+9B)`(Wf4A&@@(x)(HD6}wez)%7fO&dahRmV=4{+|fjXlF4c`%*Zntw6# zT#@`mw0*^-F|Ova`?QZt2WnsEZ3}s}Cu^AVob}Ru7~RX5$r?6;aVsYez2$~)iw{2~ z$bN4Zwo=mr19p)Q?cIL1HEY23{hXtE|LNbzO&8B4m#q6ix)-5& zeBFai<(zq{Ji&RQ0B1FHthE2J{2BdJ`D-rI%q?&Y>wn+&$D>azS)x!jg3uim#&I`;2meI^e`{!-7On0=*vGiR^k51!AG|HKKj&;GZ{ zzen*>-pozv-W)luR{EyrP@4brl)U{pdZ;e!Ue8$Fkq^sqFs*^6Zxb`=WF}4t^S@x&sHK?$bIsq_qE#)E}sq zhPrxbtZR@X4UN!YIm-U~G3IhBW8x*Z>qmC&>OUX@Jp<8AE>ri~rxZ-q_RaV+E-tPo z2|rH#Fq80ylA#pNbE|I>C0(aeIlq>sg#M=!N9fv>i7m9U7N{N1;*5#flbr1FqVsAJ zebe#HpOk0XyrRM>QZ#w03>h+{M`K?|;zDu~9+J zr#Y{?f^+4gWd$KwU=3H3gAD@(O+6wspk2pI|yj4gH zeElWm^7_5Ei1))cPx<}f9nZ_M>65|B8ENou_{K$YZ1-E(E7rr#u72Mue9fDyFV)>t zFHdh?Cnfm6Q#pfw=T%FHGj_1o#vTmsHJ**gFV_Fw_#1X?lU2pjIVYSXOJ_`$LvKEZ z?Zt+w@2$2P6Y^Q#zd;;Xj{jR|NtSCW%JI*4hu3=3hGTqA@%<+IB{GdMDnM@6RnBEE z@nhERh|e-W`_cY)uvfWd-PN)n8y_%bjBL5NinSk^@m=(+L$CH@`lH{QF+P5|o>AWQ z+!p!cBXGz!x4mdO1V*8C3_gLkR` literal 0 HcmV?d00001 diff --git a/src/windows/leash/res/Leash_user_orange.ico b/src/windows/leash/res/Leash_user_orange.ico new file mode 100644 index 0000000000000000000000000000000000000000..57075fc89bd04feeafeb96d4c3ddfadab194fc83 GIT binary patch literal 25214 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 literal 0 HcmV?d00001 diff --git a/src/windows/leash/res/address.ico b/src/windows/leash/res/address.ico new file mode 100644 index 0000000000000000000000000000000000000000..1c4e81f4ba4748c8c22ed00460852b82cf7a3976 GIT binary patch literal 25214 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 literal 0 HcmV?d00001 diff --git a/src/windows/leash/res/destroy_disabled.ico b/src/windows/leash/res/destroy_disabled.ico new file mode 100644 index 0000000000000000000000000000000000000000..7cc6eabd0b079aa3e3f354cdbbcc9d89308d16b7 GIT binary patch literal 2862 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 LhAcjB4vzbOrMMoN literal 0 HcmV?d00001 diff --git a/src/windows/leash/res/encryption.ico b/src/windows/leash/res/encryption.ico new file mode 100644 index 0000000000000000000000000000000000000000..65323ce64ea9d910b058ed6cfdd63aa9db00af91 GIT binary patch literal 25214 zcmeI43v`^tmFG(~(9Hrd0b&;NXlD`<5D-vi88#tjo4hug*<^N;L$k3BH0EhA0r8X! z#@)z9(m)dPG`4v(nE`{_VDTn4cv=%61Z==E5)a$Z<_+Ot0k&J%mTG_hs;=&@MccrM zeP;KZlytlLeqTNQb?erxd+YloV;ank=HP>OCEw0W+`*Wc#+Wf#m;P zx51d#cQlkYl#iQRKWEJ6c2fB=A2;T{y;R=w6Sp_!n7<3<$Cz99G3HO-4CUb|clysm z`7vhVcE*f8#+ZG`qAu=a$G27O{=d`dwn3=Vp=*oDN%bpo^5F{F;%I(-rC&4 z4{c2!cDn_!lHz2h!6?XvKa8;gxxpugt^8K{Wuws;?yh+!6YJz}83 zxhm?ChUEE&*vG)xL%+kmC7qh|1TwNCmGst{us(0}Pc8{J2b3?X-6I-rP0! zHKqY~y42xE>RK`Gy0tB>t^Qt%zii@8K-968RqYe&IC|aP>~Hqe@V3=0iSewdppbL^)4(J6=Q6^@cimwtQW=$$0y1l8&RDa-P&p(x=TczPKTG<0QBG zlIh3Z50Tq`M8BHcYM&Vc9S(iMK4Z1B=(oJju(Pnc@WDRQ?Y`CSGumxPZp-0Y+%0Ea z@u?-IO=PxDIaUx0pd-R}YHyfPxi34`Y(`ai>`|<_%Cj(8f0@dC>=o;x<~|FkdLMI4 zf$IHMT5E}EiTl**SI>+N8EQ0D-IJIi)?daiNE*mwn-K^+-MRZ6ELqPxn=(W4!laaF zhXS!tC0Ok5K-MqXbEUAE0ofHAV6(CVnCTgOYSUz)Zx5USeq~(L0YcKkX>|;Xp59c% zZKlpPaE*oTthn|{b&r+pRBhP}nGXz*q!$ZDgIx&o$|MR+I=*R3%3AI-XDO3u&YMie$`B{u6Yz=5 z44Z&YW=g4KCYDcTM%g5MIx~<;b3dIq*QVh!@EPuBGRBgd9DFVVo=nW;~ zYzvuAQ_QrciqtQ1znIycO06lI0T1^r^-aDL^szi-O&&b(i9C4n#zH2U??@%N57{Jq zI-gCY;nVqMn}*MDKSOQELMBK3T)rirgNIBZ-;yfiJM#s~7vPIX0?HTjowk_AuE9h6 zu=nIUjp^-AL3zkRCegb(1?3?NnIwF&w>uA6$fSF_Q&1kVkjeBiU%kv%FZ0#Qe8J~> zkxwspdco7ne8EE&GDUbOU+hJH;4QrE9i4|P#H=D4{NRLbO(kqcK7oQK;FGpFmE>NM zjVy`IrrZ+Mk3)o{eExO8aPb#*E5m%z(`ho#YJdGn?c#XF5&6w5AG%_AwR( z)UHVRqG`<+aT|+<_PJ-Z4K$jRX^iJhW2ZH&pG0FUm1tyrG&288(2$GaA&`L6ut@$}JtUl6CstGMZjC{j?GkjLF{9Uiq$aVq3X=u!LJ zQhO=yDIT-$=UpqYSR2~r;3G=l7**(Mw^ki-IOG$&PyY}r_2lO-@HJfft^#eLOO%D2 zjyUg}Dq|0k*ysD<3XC5C?a{i*sq2pxl5KFq?OWiL zN09jG(w5Xeu00?1LjKO^yrm8-vt`4J3U5lRH4U| zn&^XGs)j73wOf{@*G;W2_v1v#RCV!G~NXy=9Qw-AJfzq!PCTI zDa+o=Q?dt&8-VnOjiM`39@|jH)3uD&wYnS_Kd}O4#zt&?d~C_|v1l2AmnN!%{z&Hn z9Mi?_7Shxhl0nIfWsupH9rC1cbH^*RUGBv?8>D$v&%y1 zyF}t~>f_5wFMVlWBOaUY%Ey{Y8g0A7U)DCE;>Ss!S`Lx<2j6~^EWcJ36;zzog~ds; zQkI@dW%X=I$@Dl==v&uR@#}yKO8IMBSwtGHv{^faYkirYC$B%Q7L_ESfCozp7|GHB zQgPLExHaaoME!6r@D2TAFjb+vz?KOSRa{r9VtSg&DiLeTv)toe2HbE(TpvO9?iR+- zCqm&^DmHa2Hj#CVF8Jhtl)o!$udH6GA^)~g?2vI|k5p|cPSf69lcq+?m%Fm)(bQP1 zsi`T|bO@bNvoyb4acsTvp&mI)vx%xW2dYBbasYMwZi&<#EVpMlT7=iqbj zIrtoW0lolVfG@xo;fwG^_#(W8x9}F;!sCVWlgb+|afdk75T~YyQ}e{BmN?ZAr>2Ng z!2_R$Ps69-)9@Mi415MY1D}J>!RO#}@CEn+d;z`yUxY8h7vYQW7T&^Jel0u!25~BQ zGT_O82R;FxfG1`pP6ZEq5}TX+jkY)YI8o;-N?O~5DM6YvT6BzzJ+37>>d!>8fX@M-uAdPs9DEKw2cLs4z!%^P@CEoHd=b6~U$kfn z-!0#l5~TV#)e@&dv!SK5@8VS2XVNl6jXC%nN}hwy!582Q@CEn+d=b6~UxY8}^u#R) z4h|ZTcOzqLMBa_a8$JP_fKR|D;ggLi;?#cP)SGnJM4ak=iBsJ-K1uq@WqtdEAhlHL zX%7+Ru;5SCIcrl(CAM@sJlJse+3@BsU^^tVt#?13!Vi|?COCE4Z*P+q;v9>*_uIyn zZy_Znuempi+Zo2acy6W9eIczk~uI|QL`_YbLM|Bqf^|Z%q zQ>lHf3zj%YQt~lm+4JaWw_|(cnaEzTdl>=Hm&mugfPkJ#DthJ3bV0dv$zjd;uXNfg|;4fCmxf0=_zKuLG|Z@aUEu zNCPf$TLX|=O!FYXZ^Gj?{kFf2?#s6su94r?)dN89a_;Ab0yjSVFaGqyVp2>IJ)3WcN?6Z}ev+t_YK$nIg?@=wg_NV&$Ty$)Zy6>Dz z9^X{l!8THyBe$B=<+VdGQ0W+XbE&4W?1D%FJRhE5E>UzWOxsYGn7 zyYTUv@HzM#d=5SbUw|*b7vKx< zMff6o5x!{ufA&+}A7;@?oFxQz!E$tj`HS#v{ayL_5#C}tqxWq)_PXXihZi(cNgOzE zSllif#9r3cFZ14Gbxhzk<`Uh}AqQ{nKFzTSYWsDMhjEIu-}J=Wbad8+Esy1U*dof- zpHA2++-9NrY`WgsQ}%te7(h&mkJGsrHy`He)_ZO_hSut*haP&!Y>r-j`PCmyotm{1 zC!V@?`SQL*{T4pe)q^P||8uL;rI%i6Hb;*<^2oeww#`2O{0cjN{(L)W(y#4t#~nX+ z_U!98aQ#f_a7x=9c7JrMlG;qAh(GJlQAZtR?z!il=P$f4W8Zu4y$_`!y}iBm4}Vx_ zFTS|Lo_z8|jpc?pbFSb2Q;cMr;eYnoXH7lYv}uz$`|NY=lqpk(-hTV-kDh$;NxN)W z&)|n2ez=je>CHFaw0GTgx0QaKa>}VTot|*-v}qR~wwbYPGyLd?sYmGh9#f`V$a@{< zuirp={P87L^u!ZS+NYm>dT`~+Rhx!}hD3wK;%Ym0?yYVtC!Ton`s0s3;WFy)9U03u z!_PYtrXDR_`oz(aZ7z4?z}mHIH$C>)V|K}srS{1upR!LqC0eHWuq#)t9DL)AH#VVO zL(t&z<;(4yIoG3FY08(r^re4fEL&CgwU*T8l~-PA>d~W*{`vZjj(@gy z-+fQ%rI%hBdhD^s3ALYa*n4`GTj6~A>0Y-c^!=G3iS%9%H(ySMo-_62KSd+qf>>5lBC)+8uHJ`BN;k0l#6r zw>?4kdsw?q*ReY*-P&EX>IG+av}Wt!mkrw5^z)zp+(Zfddrq4+-A*`}_pF4~-4!7twl|IpFB_ugyoyYD`G|NVc!KlHS4 z;X=D`;Uc?e(IWf60}t3jp)izAr=1<%ZMWSwB8S68-~H})O_XNLxa?^8%-3Ff{rV3+ z_+X=SUu#!BgVwL)AJ(n*ta`dHy%BB^>z_T~P5ahcf3bJmaYqF|va$XBoE<{=gpSs( zU1!&=TW8m=UvCEn1}uAdg|w$nojTRw|H2o(@IgZZFKI$w|N7T!2)(&RYxlnU?q4r| zpx(Y)U-$jKCEF9lk8cF_x61haJ}eyy*rWJ`TU08QYVdE^uuzLVp|NSd;;DHC4 zGtOwE2)oyv6>iU!zaZV$+Vy(#n$w*ie{4a;4~ohk9j)LG zx>G9E>W=VB{=`cTKe(6dw9`&T6vfZlZD?(sEWcqRbG}}-((8WJZhGAhdcUF~`zU_d zOzHjWufOi(FWJBI&O5|AcUAOX@|Wy|AOF0f_tKrH-V=HVJ7LDq#v_h6!qwkyyX_td z_!EhQ2?YNCEZvzsdrpb|2DE0q&!BbdeYT+cLH5CCC>D#(?~(k4U)b^eBKY4WURYMa zFWXa<{g&`M-FIU+^w9t6>a%XU_t;|(BieoU-7AFLQ^J4eop-H&_ucn43VRiQu$%Ii zC4aB`wfMc=53(PQAD`NOoOo}w@YCNqVqE;5Cn`Rt*B|fm1YbY+ z3?94pnYDLCbw~KMcHepDT`T!(jbkS&Sor%0^xxZ^FoumAD>`Gf7d1BSUnwuy2kgW1 zQ%;%0BlnAR-hkh;+}X|G^MrUS*dF8&-`mc5_=R2c-g|58Lk~Sv(Ie>t>(5?r z!3A#r)t<{<>-Ot|4m#Lwzy0?56D@~-_ucn++&z}kQDK?F7+AYIqyP4X8*&?w1AfC( zH9m86-`$+<2iqUTuf6N-x8JE?4|ZSi!Owp7v#4CR^nDFu$Og>OeB{WHMuflr9qG>9 zci&xNuiqg2BH7TY?)bGU*$3V6dsfh$m!0ho>o)9NvYkQp0e@J#@_UFs+#CcsNAjnH z8yW*uWFEz@>q?xbwFp1{<~r6WYd82j(OCUi=PwJpbf;>20)Fo=3%B%Mv9IJW{L&kd zxBK4i1iwdmuQi~wX3ZMyKbnh=r6}(3Jrp|j*a`OwKmN;Ft=+J1NpC`|Th)DG_jV`P z{i^MGtp>YnPmsN^4aXl{yKVq{Oqz6>&WlF`Y#|Srqj|V@{P8Eg#QC3W#X9MXfSRe#gVT|Q?Nf6$%kzE$-%H3uP`dFEN@Y#-Z{_c22r#T~u}{5r$L z9uKjnmxSBnudn;{@M}F*@ylQKKBv~M?0!{uyw4!rk?e!dBm9GdI>NK=%nST~7qDT2 z%+5RST$faavOBf3OvXRIYk;|Sw&y8)2hBsUo7%U$-LLAs)^70GYVmvQl6{bWeckbX zgM1$0m*1m=4%^dC`*mdvd=h@*_5UK>|MQ<8TmRg1&%5&;+5O>mr)oESoEU7rkGFix zBHJmw3A&@bOY#@~;I9SQ2i+Hb`JBqb99(_%Onb~R={3l9$4|n4!U-o#32T@2TDCpH zKiuc>c2j3m+H@J^Deq*8gu>jTI}agRrdq_5U&LM9=mkM+Z~TzevfRYa7*seefbSl-Txrsb5?a< za*xI|0*%3(&Ta;~6ZA(qFOu8?e)(->pI_797PQWD>S5QlqmNEc=DF6Id+)t(2)ViQhUnV$ zb~CzmgYE>`d%X`aOBKIlUn~EBKg27+_EfQNu#$a5{)3#~TlC|hV2g(5#~gF)?daDg zFb`l~oZk?9HpPn1JQLL&*?x~-Hliwj#aljJ4F0Cq9gjckSpk2*?PXup9m!qtFUO0L z|KL?uT`l~V4aXh$qjt92W6Kdjr}^UG(5V%Odq z@JnyJ?$pLx!{uMbub6RAy3c-mbig}2$7lZN;)~n0=Sz3oSto0_y!ZMsgy$1}?~Tge zpEHMeU4Gke{IZ?0o1V5DZw2|6V=l=*tlhncc}+di_`168pvqtg8>Z(!`2X+dnH*Fc z@^W5X@fjrhsP85{s_tFh_wlyJ+n=cI39=9CHmqIQ&VXI|Q{DrHR9^N|wkO2v!}E(S zYID!qZnow?d-ROF@&?^--T(5JzwFLVe)5x_nD2b&JMK1fwd;~4 zPb43FaPj}R{`wo5Z@zi%4UBOq&%=t7C!asSTHn;%e3l#2g`9I~%o<-Hja$#?MZ}5g z*<<|y0^^d7B3i~J^79E+30q}cxiat0+wg1bgbBypJREo6fBfSge+)n8z2>^>t~1l7 zO>^%R=-GgtX^a^&#_YD+Zu0d;LjP&eqQzgm=9*dGzwELr{@dxNH%}w}xsLOT+vx9Q zoddwH)i~t~%Qw{cI9s)|X3d7?*qd*@#re4Mov8GdCrL^o^(6@<$P>k-)X0v{@j^op1th6^IC?O&!Near+lR6#>~HMYn#q{Be(CT zK8DlYd++Vy$!&pOZE_Adf|zJ~aE_Qa@3!qzsUr^s|JTNkKk9o&9{GPJjvIH>xjZ+S zH-7xl^LTgS{!>q#WEq>AuS+iZjaz@(yJpY6cK?G8I>>B}h7vX_nelf!KG#285%2z` zg#N>f{z-yzpEj54-*zZ{Qr_>2mH*#N`Twzu+$S> zx81g2!i_in-ktS5^2ncfhi8&K_Soa*-hA_|`$e(H?x^p-=G_a`pDK7q4w8*54ZaAA0Da zCJ<-RbLIEQ?`5n*8o$Qt{rzyhuXjmabaSya`akTj!%UzHF1T>H*1r5ajobGhe0Be9 zYUN7bzn;ykTG^)IY#ZPOfv zv17;TjJ)#PK0LDz&+8w2@IhNB6zsnH?i(;44)!s7?X{N?5v%=A^{=>w7=ix%vq{DI z)v>Q~=R@k>Kg)Z=J&%wK&O7hCay(gm?i-C`@KK%FIQZa$L;qAWX2%_ObVMvX>o>po zozp$~9MV~*&S%5egWeU1vtH(G#K*PO{`LGy@ob32@sFMD4l!)7S^Mt0UrqlG1RoP7 z9RIlNs$v&`#N*O`psQoTPxb@%)%^sjRajXjJ%a&BSAjQMKa{)vZ5 z?87>rLifY_OnRnWyY4hUitUH@KW^MO7Ym2+uUqHGAMIN*;JN6>`VYFVd0nw$W#pWy zwtuZV#kJDC@GM1VY8wBjQKQ^5_Gtg1Z^i0*NBW=s>3^+PS*Q>_=f>|pK)R=MA>{3J zPxeQ;r}2k%uel%Izs@wI`)XG*2>ol`m53j7URvb-u8^MFsO+)P{*iq%@5H(1<Ujf;nCdtb9_Am^5>Yc$DiW4+l*-6dPZ38f9W6p_>j&=Wp^X} zKUecC)7za_+}czBntSaP{v64#`#=5ZQTNO;nM~Tl4?o<=h39x@(a)Ihyd#>Udm~Od z>Ev}~8{_)c`U~qWJkyYjweExNhjaAMf0%day-0DqlJ4`2`W}rl+Hd&&@WYROQSqqG zmt^<6-Kpxm`uBPt&SYP$oW*MV((TQy`*3D2JH~nBi;OiM`VBepF#o>upWQPT>73?1 z=so*@^8+>ZaGn%&&z~jv=YKi_lidpEr{3=P_dT2t_>kQo*1JP;h$h*+>#x7T*(!}) z{Ue8p&6n<}u77_J)i2kCR%?=k`b{of7Mc(WEbwe_dd;&J0lG8 zug<^M{h)i=cdBQB@49CY8oMZJbHmw<>zt2y^YYmBzP)ODH%4|x^<;M?Z@vloa;VNE{s=SeT`N8CA#URo9(~-Tfymr zY<`%_D7H`YUA7oIxNLae;=!bIqXsAr?Ro31`EOrw#Z~{v8Px^Z>_s!N4G&@;`Fnwr z-{e{7&{=1lZ55x%Uh8io6eCJ!rTd#pnqS(vqF(>s|Ni$)dwaW?JbAJ?<&;y*FMjb0 zqxbB8^rIg+zxZok`u}+F}H@eRJS|#+i$-` z$ES|ebc@%=Cz8s}oH{ob+GnhP*)M z|I<);u4eOxmP>+d53vmI2|GV}&6+jNX31`ef^V(5B6L@>|4?I>zo7c^2}1q%IGYG{ zht~(=0n~pmI`*RTDPD2)Ifrq!cMJ88knF?W9I(qS-iR*A|D8E=rrS%v>S8VYE6K)T zC%fo}Km6e$#j}!Kh~X8-$VS|B(@iz+esR8K=UjcYBaNLjn}11LQ2)Uv)&8V?QTvhF z2>ZiYVxN#yFVwGB_ci=^zgKQ>veTX=8H7arE6VkC;MERgbq$&g&BBlQ4d>(63crZw zvahSnkSKGW>Tiyoo;MGF=b42wvss%u;)o*W;oaMf7@>v!J17Z_R^5lqVb~r|S##m? otobbm%kM(VZMNYlXt^~Feb$V8j(i1#Za2ILy<|5vY}fpM0oy@=@Bjb+ literal 0 HcmV?d00001 diff --git a/src/windows/leash/res/import.ico b/src/windows/leash/res/import.ico new file mode 100644 index 0000000000000000000000000000000000000000..dd6ed298a605a57b42ba55b89fa2eea9b87fc6a3 GIT binary patch literal 2862 zcmb`JTZmNI6^2(^mQ~_-4JaeQZb-(_(vE3HW59<}#D_d+e3%mz!4ee}VoQ@~$^m<- z6lul4^n?i$GX!d6q}APO3yNuPsd7TZQHdHGudP+mUhvkmw<)!af4+U%8B~(DoT~5a z_3w4o-fORO&aN`6u!s#BG>EphjjAyFnHk#9aa$TSn@3-duCk@Q&5rgl8|ANoD)4b{ zAKvE=Nu0Cc*Rok}K{kpREfflL`5vzEmvL>_n4*}>OxIIJ@W<11+R4V2Qq8CJ%v^k?ZV-~Zc*>2i$rU^?B! zbO&2EZ1B?_%=<|i)j>j~OovJXOPNxnG_YW$NWtFv(36c6BH4kmJh`Red}RVOM#b$U*PLVF?Gb-c-3GGPKsB@}=IrO+8PI1pG4olC58w8|yw zERW77(vDWNRzw#Qb&gg=w9rbF9j%n06oCQ@%8phRbXg_35>2a0bTT*?Bm?pZ4k{VQ zQb9+M3Q7(HmI(?0I1pG44K5dC1(px80l0i%0xL3GF^D=4n9xFluvwr5;6PxN=*mpg zfv_!!1_uI5p;P!l*p@+q1A*nxIs71O%cH@8z>4T1eh@Z6zmk78mg;(RCP_f z+!Sw$`#mO38T4^Oxg3u-yEF8#3#wdRi`>=XFX)oGYB+*9&AZs;$w(iLqEm{WX|Wb> z1+Ki7#z*^p#TwR*9bJPz-lNOqzkEnG;c(vHaCCFr#qPze#f*f;{_A)=-cmo-k4`{$ z_dh4ZVjstGzS7-3$RAzRWY?i_k^kR5TNTdo-%iYDD^{!sS+{PT<9Dx<>wfO9oiu5Z z#bPn*)vK3Hn>Nh`4<2ldjg7Ws$r4++a;4SR*ZZYgLqmgY;Adj-;>8zs?%b&Z2M%cU z>eVj?3>fe=!*KJ>rcRyuKjSxU+!&5Kd-m*ao0^*BoYU#kr*-}Mb@7|X_LO-^UVf~1 z{akO)zhJ=vTextc&6qJmd-m*+A7l6K-8yvWP&iJxT=sR<;lqbDbLPx%Cr_SSzi82- z@AIEBWr|))|shxYB;r+hxIW5a)kazw|EAJ^HlXVu=`9@gW|ojZE;=usFyX3Uts z`}mx`qt2Z>r>j@5>c)*5x_9qh80$~ebBk{( zD)`a;#X8xTU&@A5^}LEar1(QFT)3c8sia%CZiTVMVo_C9RTuI9q-Pj2))LmYxw%*?E>^l_R_vLFp3+v(6d-LW^b#`{@ z$&)8x4#{Nl#;jSh!uTJ~ocW@Ecema<`#^vD=9JE#KOfe6)ffB1n)+D3_6H9h=-D%W z%O&2aPyHGg;Dg>zp1gSX&YfpVKKke}@6}88Ms3=(N&ENjm(Tshix*+c>nCb9Ys82V zKE4y!+%?$0gUgmJv+2{P+sKh4tzW->Kjpe#!y0HBK79B;@ZFp{ckaK(jT>hZCr-2u rHnLJi{GWq}R4~;PEauzqs3}BTOBP?YBBVN7vA&5vxeX&Cz3cu1z6D#l literal 0 HcmV?d00001 diff --git a/src/windows/leash/res/import_disabled.ico b/src/windows/leash/res/import_disabled.ico new file mode 100644 index 0000000000000000000000000000000000000000..9364bda80a0535ab8d5f0f76f5270d64ca9d40dd GIT binary patch literal 2862 zcmb`JU2GFq7ROJ3?aWKnJns4>JO+zs3DBwnA!{oh(26P&(p1Vz%szk+0?F#CjD=7< zaYSrUf*&bgbznn+u3;lUh;M8_dHMd;0+0Vo(8E1Q^l0D&iJ*ylQ_v(4EZu&b2!}FSqEEoR z;sjIQuaj$+^!`O{?PZr_D`WrO)rrbbowv72@z7H=ttwi)&=W6Z#LKC8zO;D0*Mg>1 zkOcmOM?Riv!uwQ`UcpOxJtpY|3X<^x4@|}r1t~Hc7*LQh8cdn-v{FOYyqEz6QM95# zv00#aU_e1y&@Gvm0mYUC8Vo2%5}m{kiY*y57*LQRx`-bXTgqrKpddAL4L>M0LF9uU zC@}d@88I;fiY+Z@FrXj_bOJvpwj|MDKtVF-41Q2-DWbuEf|Su^{GixULxTYYQMBR* z#TKcOPnArn)Tc^5=$0z=sZt+w0u2TfB#BPq2gQ~Q8Vo2%5naR&iY;X{7*LQJx`rPV zTNDij)Y@c0rZH*JnAd_03X)LrK!YamC-EoIpdcCiU_dkYi};IZP>?cyFra1pHT*R+ zC~z9d0ef^5l-kUJ<>a&lMwy?J4F=do<`?EigMyUtg8?n$ui>wuLBUgO5Q($KIQt)G z|Krpf4F(h>flkC@<3DL^aA3fGlZheF#@hTMW%GOYo>OPsz5{-}9Pi~s`>#^N@C#>V z{lm$w&~>}Jo%XhRYc3iUmgsTKkkkIM-lp2t7rI04u88%`mUC zySb;QC)3u}_5;@-eOsX)Qt&y3wq+j2|a!Kw4OV6PS2k|ug8xc*FAgo=%!7Zw6n8Q=gpg^bLY<0j*gC} zjrc{278MU1I1t61I(16VoH-N4UcP);uU)&QH*Va}t5>h;$&)8__wL=gcI{f56Nf6Q z{pVd>T@@Q={kA=O_H2~Pl`B{D`t|F2^X5&xbLWoUzkgpJJb0kCPM+s&e;2>9x3~AX zop$+sgl2taY!HgL*`i~tu7OnTtp+kHN`ZSlz>9%d#qB(5b?c28_|Aq}4bmhvG!;M(m z(s$9$YiqZC`*z*3WlL1Q!NI{OzOi<@7ybSH(f+ZQ_AEs?Fz$Q1Uv@pEQYos_b<->Bde+DcYF8l{m=05@Xx=E4L)+lgC>4HPU3h$Q@aZK bEnz6UXN7l~OtplrOzq~ET)nm8OiTR&FjlE! literal 0 HcmV?d00001 diff --git a/src/windows/leash/res/key.ico b/src/windows/leash/res/key.ico new file mode 100644 index 0000000000000000000000000000000000000000..34bd815a8ba469f251de1808dbf97ba44906f132 GIT binary patch literal 25214 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 literal 0 HcmV?d00001 diff --git a/src/windows/leash/res/new.ico b/src/windows/leash/res/new.ico new file mode 100644 index 0000000000000000000000000000000000000000..6362690f02add66afc4e815ef4365d4a12b6020e GIT binary patch literal 2862 zcmai$ZD^F)701sc>Wu7Q)GxL|P4I*0h%2GC7A#Dx_^pai9u%aFRjUiFk`GFxtIXKi zAX3mTec9SF!n%Q6O*fzzcSk#;vZ;=4V%8`cqZ1on>U%Wms1yD7cc0jHUApv1e$PGs zd+xdS-19thXUrm2Y2(L_ryXU}BWB+AaQRd#NBV_T!CoNdpxTb0V6e3FeutCY>|p4ZSoKf0Y| zvRq#8&K`Kb&FgY@D5;$qV6FbtfcmTYQ~j0wRe9^L%-hJH(fTW0>ERyX9-$nOk^5A7 z-mX(D9RJph+WO0HiCMz`H+7;iRA=Ot&-dligN0^u$%F~4KA`{{s2-g{g9CwO(3!+0 zN2^St!E)$aqS4Wc){5w2qQMmtyH!Lhkqwk+b4rw@1SJW|fdx@#K~@$tST(vjXm{1< zYIHK#9VCM`mqaInq}2xlL4DBgKwzmLAAkd;0<#RWWrDN=VOuUp2f4r;2&{;|7{nb2 zOlYA&*lf@Oa3HX1bag83K-iW7ZPjRSAh0Ali64Y*^=NP)uoOClAB1fgG&m4g4xPgf!nPtB90*Kk z;Rj)x^^i{wneVr4T1 zeh{_^4G!dOvLMsARVyA;V}rnwA`dhuiN79yJsJd-!VeCV!k@vPL4&|@_`!j4_>1_9 zXb=R#2Aw$rqBh@#HRSXGoMC?6Y;eG1WPW3QGzct*9~>x$zlgtx20!27KuXVx_mbYD>S0S<`>J zW|c~@W-4E*o#CTq)y5d$V&|DTMi~@sD#c3sVzF*comzD1BUf^<*m-{l4R#a;o65h5 zIrrCYPI*(IoOWgBx>~wpG5dH>o#k?8p|!Q#`Ej?;7v0&>(a~9EwwTxI?CkhkN1?SV zhTnI*@t27TKE}z3&hj;7;Llj_ zXYALVvo(H^|9O$AZP>6OWZSlFj_8GD+^XAR3$Bi3zoN0LYW(yW9_}cg# zJ9dQgE?c(jS#xuIE|KvY^{(QgJ=_^*O(7}TT)zZ=u z&f~}Pkk!@IrQY6Ny?psHoX6izpFXX1>(=#R+Kd@9Y~sX;zu&rbtNi}=@87ROhYl&1 z%jx9Flj`p7)}>3AbnV(T-M)QWj~_n{=OOPGK7P`qNj7@)==`p|`}E^OUHVhoVI4kv zSjUbXQ=w4MxpU{#*Vh-;N zgSHc=eZ{dapQ*W-MbgY`WyA!OYCZUsP1nyH@AFn^3?SRKOuhI@pt|C z)G5upIiw$+zORcHFRH)4U$<`E3S*1KqH1btE)oB(-Ow+>mtaVJkzV~})aS2X|Fq+x z-n})*hgzEQkLO|S{NC^0y&J|8_u=~W>#eeq7kEeo8&(goitLvve#ZxO|M2Td^f#Wp zP)|>fE?>T^fq?N;gKl|_Xee2gB_hMN1<@bB@=1o0#@IX(WJ`Hn7 zCX+XoE?sKu|NHFo9OE7^$4l}Uey8`<7d~#nt5>SKUJ7IV-XA@Bq!%yzBPYj-id}vW z)PD{2_q8gL$0YWmpv8UkbKW1{|FbV1YIt}!jQR478ZMnOWeSzlkC@{R{xigylc>jK z+PZ1erdj15kNwg%AI~#(D>U0 fYHl{4jtf literal 0 HcmV?d00001 diff --git a/src/windows/leash/res/new_disabled.ico b/src/windows/leash/res/new_disabled.ico new file mode 100644 index 0000000000000000000000000000000000000000..3bbfa4485c5813f2c30d17c9b04fd302367383ee GIT binary patch literal 198 zcmZQzU<5(|0VW0z*Z{<0K&%180zj+)#2|SPXaJL##Q*>QQ3Vr#Tp1wN17bfQHUnZG zAhrPF6+j#V#5Pd621oVcRah?yA}4gkeq7{~;J2B0_ygPhXCF9C0EQ=3x+77?bmxZjo`e?qrXIa1JtQ~R8+x=RP2Q63q#D?O)VDm6mxgVQqwcNIC`B;J2($5c zOe$rlNoCY_Cpja`$fW*D$E^_eOg=yhcPj^DIZI+HE^*wcER!VQY7Der&hH*2R6g znQrOgU~kh%>qtA3-sk(o&agZ4!+8ALcyzq~gJN08pkd(v5j;d!Xoz4?jfPkkGuOqb znqn53;v{l*gKqI5f zP>m0<4z24D)P&stu?fLVkXo+RhAe_X>FP!UJIkh23J}4d9GzEL1QV-7Lj;3{=pjCs zSQQ!~7*wNcd@!*ZG(<3{MYs51VwzYFK5#>l=Vzm$&~$>vL19kWq+pZ54uD{1cQd?AwHN` z6&fNKRHJKrFtHjmL@=mDxA zT;bRFH5v?R@F9X5{1(4OgMp`wH4q;hfZ3aO;S<*M4ID5(Pc}s0V`P3YKN<{b@F9X5 z{1(4OgMlZR`KeREJr;ca1)qPxexo6RK_$8@vg4Vv@1H$Of64UFn0nLtI+fPAT>Xaol;cnfLc66Mu1cUfSyi4=(E7zh=TE>x%22bY#lf)Ynry z56Ps_9n<0HtIz(w@7WD@_wvD&*#6bfJA+@8-OE?4U#_G7Px_ze*4ww1y;U^*JRSFb zr=R~uuh!h(K+5T74&T9-e^}eUk|Ouf*L*)e@p=DC`g!p6aX-gv_M86nxW4?4{h#;! ztDeu-pRWJGsy&N!=ly@*_oBB-eBPh0Qv13!_ix{(<<)1}$Cu?7bA7zZ`MR3q_5R|u zm-D?|ti3Fk=C~}soa^UV<$P65f31Gqi|4-Q%3S)jcG&TPUvTc}a@{XEJO;n#j>DF{ PyE%i&By8O!xAy5@cO*&h literal 0 HcmV?d00001 diff --git a/src/windows/leash/res/password_disabled.ico b/src/windows/leash/res/password_disabled.ico new file mode 100644 index 0000000000000000000000000000000000000000..d2a098bacffbbd7437cf3ad845adb69a79a3f1f1 GIT binary patch literal 198 zcmZQzU<5(|0VW0z*Z{<0K&%180zj+)#2|SPXaJL##Q*>QF$GB!`Tv}O0gN9rFiZei gHvy<0ME?i!VRHAY85lyn7#R8tAsEC4iGi#K0FWUWJ^%m! literal 0 HcmV?d00001 diff --git a/src/windows/leash/res/refresh.ico b/src/windows/leash/res/refresh.ico new file mode 100644 index 0000000000000000000000000000000000000000..310d92497194139e94f1b432e05efb362ac6ef13 GIT binary patch literal 2862 zcmbW3&u<%55XYw?uzO3+zBm`8YNZ?;en>sQ{sTEdx57cHRUtJcA}B}*yCh^?Bb+^< zP~ZR;R}ccc9C8Fog?-|Hf=VFegtQWbQaEi7RU|?+d}f_BP6$ZJ+Mk{I?!1{d`}TQd zkyG-3jE#+9N96P=k;g^Qg7)RogCgg-*4N{5X+-4fheS@>7#Ii3JA7Eo4prsc%)ioX zng`7iZmHMnamlVQ#)dIAH=-rn5?3rgKQa>{k7h}dTzKx>sM+M1hq22^(tc_*TV8I| zlQ*#S>F~LmU)ex@d5qASpT}4vJ3_{SXHQp%c0>ss*z%7q#Hr*{9VAp9tZ}e6FHz z%YW&`IlZ#9m~(aI&D<7s7B4pr)Ug_tGn{W@-+60gz`Ivh^lj=`t)kBC%nWsA@;;8r z|Ky_&b(oJ=KTxAzV}Uvg`}t>&od3r4&vlqDzxXV#XEm%B%kSUI%#rzD-MFsb-TZby zQR~yS)x3|QhTX$a{eQo8Q+Iy(d4Scj8rH{f5C4^a`_~;c_V)hFt<@@OSP!Q!GiVw7#JLY#*l(RdZ+;a D49E)9 literal 0 HcmV?d00001 diff --git a/src/windows/leash/res/renew.ico b/src/windows/leash/res/renew.ico new file mode 100644 index 0000000000000000000000000000000000000000..31127c078d4c9c3299c446948f78d2806d9106db GIT binary patch literal 2862 zcmb`JYitzP6~~WRmK{D6kEtaZDq+`-YO~akbs@x})j|-W9|}ThM$lTxQj8!{1=^;d zMHSAj9pt#QiiuQJrB$^-LB?G3EDs@Sw2Mm-;vukbd5N-%%tJhkjCm{&!s+i0!6m5u z*0Fzc&;Oo#&YXK@c6LRIBp|NqG7gvOB9S*m(1Ld4{h-Ku%stoT^8RpJb_2@hH*u)tFfITqoio zoR1QTL|j(+V@Mn=Amj1k!P<)IL`aHjs}jv`#6>Hs62IyQ6>IIsi9|!ZSStvtAbl-k zZ3zF;#0ORAhqbMhDO*WpMTKgc_Gy>olYN>m&L{JMd~sItfvi0LOEKEr&^}9mMp*p6 z6z6OpRrK{fIV^nTpttt0Tk>o;mzeHhVFf8aUc6CK?t6iG|ez0~$jo(O^J9 z(&%(}m0{F$I4&7E*v+x@Sx_<8m{#;{D#qRrE0iC#H;nhYcS$fC`cI^ zOqo}yWnPs;y@y`ZOPQ#r3KH}ByqK3apdd*v>wy7HdMQbh4Gbtq1`Q_TrIb-}=$scc zpdgA?G$=M36b}q2NEx~;88o2S5=Dan1&N_!_(8EHi3S4-l18WTgJMet4F(h>htA;# z#U_Y)@BSilKZXVcN#X|sn#7;RpGJd%WblIl z&EU`B&!Itqr;!@4j~@r6H{XXP)U+OslbCPGegv(rw9Y?lbSP-u1> z{7lGzx^Agk;?_CaogQ0?TT&WoDb%^HzaDpKq@`e-DRu9%n&49RXQuh%cE>Gwu3fje z;C$#fd@pRb3z)a*Tk2fCG^B>~b;fbFzvZ^zwh7$Qk|`m#qz>h4R#1V9XP}1a`gBs@ z|M#9P_pkEbPFzn`tXSc*X3ZKy6?a(omR&n-+B6A;LNaXFFqt)LmXwr~NLyQ*EM2-( zR<2wrjg5_VC(_c=BCV~hvSi7Ub6dA=)&2YT>+033pN$$ds+%<2e36+mXa3LlwQJY< zc^52L@UXqTU5zn%>eMN{a^;HhoyhAc`HZ@3uGj3fUcLUJMT?}Np+V-(ovXWc?NXa# z$BrG^)z#(a;W?m8)dL3(=)8IJ9!{S=y>ap4#Y6Sam@&idwR+*gg}Qt9Zr!|jv!BPV zKYaMGo;-O{FI>2wPo6yS^Vrj|W5;yavSk-AW&HT@GJ5prKQuKpsonpUEn9T&-o2X1 zWc0|9Bihr`qvy|`*UOhL>x~;XbZ~Ic&qLjhZTy%qVc`7_zkmO}juxWhvMzCVxK$v{8-!G_rG*~ zuHRiZO(*{TZM}Bwn%=o{M;|3&;;#c$BzBSoH=u@ z)z{a5Icd@)nL2f<^zmNICzaoG5KzsEMzRvJqo#m&Q$zy169WS(Md%`QkyGIJTp=46 G9{)GLVjV~T literal 0 HcmV?d00001 diff --git a/src/windows/leash/res/renew_disabled.ico b/src/windows/leash/res/renew_disabled.ico new file mode 100644 index 0000000000000000000000000000000000000000..672baed7d56fec2ff9fb0bc28407d7c8029cea0a GIT binary patch literal 2862 zcmb`ITWD146~|YI?cNj)$ER{SFXNNQ=sZNF4I<2G5nFvz*wBD;J89 zt#5s6Ut-o^jW&7mWX4H0t-r&#MGvui&zo95QQ6mW6>eL0`I zB=I*N{aQZnEXc<&W94$0DL2C!w~V#XV2WYJm@&Ppk%H@8&*EG(wttcO9Y!sa>0bO! z`c)>ADa@X&pD}uwP8Aq4-dc5c7uwp|+CM2|+L`a^X1>tYu6DfLnN`uUcJK2ZbQ|+M zBbhc#uczk1&C8L$y}3K1SNeIrntP?{$JJc5vHEe@s*PnE|H(62L*8hgYvK6c24*7i z4b{ec!}t5-yCZ%7qPOmHM{}KVzaRQUXXwuOpK|#x<^0I4UJFwR6IeQ-076h2okK$i z$|Z7EL>CjOkWs}%x0TSPL?&buqgBuqG@~ksHdEr0Kxiepr9{CjXb&vt4lO7M+v4bW zPzd9}h~h!UQb8?91(`4vNU5ON(!r}B9aKXQSS~0B5Q1_+-il;{5Cm32mx6o zAg~I$f**u!LPH30HdRn*%;Jg#acmG+O4NY{rSPZmr_ms=9DWEvIs8TZMKlPkgdajs z34aBD1q}k8Mry#ma|c9kX2EZ%X*=8@KTkGMmpND?v9|kWeHThl0 z!@lni__d_QJg?L1tocLy7zYqAwYVFLKGbfqb1%H4J_%+OdDexm`fGDm$l6}d>jT`^E zY}qo+oH(;G)*8CA%uFqgG&=CC?CP97w{DA`pzGiQ&TenWsq6G^U zXx6M*6S-c#e0h}hJ769B9)1B)E$rX1fB$}6zkXe(PoLI_6DQQ$+p8^GwrKV0)ln{2 z*YxSrzwPMgcu3q{*a*@7$z<{i_Se;`S9R{(IbFPXF|u7g{x7SquTML6?2tR(oH=te zn}4x$=gu8*@m!xSUAnaF*0{A7E?m&1OP6%*+BI>0-Me>B4AK%_~=~6!AKE@ZiMRT`yhl+?iec(9n>cK7AU+K7RaI8#Zhh-nDDjL2~>JhTY!o zZ0FCPpEy?eEN`*s~UawLj(^}Bv7U%tGr-gj4{+vCuoLs8HF^Xx9))~#E$ZQC}v zJzf8H@7}E?OO`yS$Gcv-T3zp4tn0svyK&=2boP2L+}`dSuBL?x7wXutWB+tH-1Bz) z_;KC5c{8fLe&3yT`CR=wckYbN?#}OWcXf5S-VfJnaQE4r+wFPx?%j!g6^ljf+qW<3 z2hXmm)oMf-hHn2i^?2^>ckUij`+M@dcQy6*_v_TDQ_;O29v+tC?c29{^X5%7$1^&y ze?1T9`_A>qJu~>f<~e^wul~GZ#fr-M_3Qu6^F6}5@h|p&Uyms_s-?^u;P`ZW^zt_P gQ6Af2rmQu#B&{*&8*dua@(qP-z9BhQZJgBhZ?N6T%K!iX literal 0 HcmV?d00001 diff --git a/src/windows/leash/res/sync.ico b/src/windows/leash/res/sync.ico new file mode 100644 index 0000000000000000000000000000000000000000..a3f067006496e8b1c7bdf25f755bbaa3363fea4b GIT binary patch literal 2862 zcmb`JO>9)x6~~Wd+Be;dSQHgCi(ye!=~Sp1Rj#V4(o{*a$TAI2icQE1a#fiKft|$Q zm1p9p!|)X+l0$?lGf^6`xaC7BRK+Uc4IyMv5LKk%D-^~dav^-$qOtH+ROY&Dw4L{Q1~<_Gp{guguVfPFc_Q%$}ofS}(Gmd1fDd-|SJJ z1B<|qd${?SZ<4qclYc7~y$8iKZn|2n(&c-|@oD5H#+1fQ(?eIYTpnhYCN_`r>$PhK z29~S2E(n6PM69>BckO`69LRbt7#6e&cW&;PR5RZw+Vb#UqxMJdU;`K1?Kwv@(4Z>%ER8gRw0`EwH zdeE6d+JW#bj|K+90)9r&JzdWTZ9G&0xO^k#6kF0L4yN<#pswg2;b^xa3CL8mDJdu z8ug$vHTI{*{-E<{a3HV<9T5lNTLBFY1Xe*;h=cGgMuP)^)zNk0Abb-V9LW1rL8WQS zC>>_-L11}N2O5+o9ubewAg}^)aG(P53h@dW1Qrtq2a1W;iPzB};BBM^{G&%f?9DIX zPt>#(jxs-QHaOrhGQTlD8Uz*-2M3CY*NNBBAP9vIW?9yl<@slM{#o`L4GsjBN9VKY z$uE_D_wBd+Cz&w}^kaQ}iSqTe&N&W%!H(SGAn-?lZygGQ!J*FF87WO$`NN0@|C&l?5qicy~HJ9xZqt@6Z;5XxJ^l0&{cyno@$K}j^DKS#S*=;KM%C&; z9X|Y#4jnqAIIe2nzA^3EwOjAJ^H;t8`Wt%csXr)+qFHnF^z`VJSB7-%+&P^&b7qFq zr$14xR@0FqN3?(c``Wp4m$q%IXvvaLt5>g{nd8TgJfew-|LMw=E4qC7a$>JtyQZsG zuj=#9FX{aG&vfF%34QqCVZHa>-?eq?U$lU=(EPWp-rTZ9ckkZSojZ5KAup3C#gmnShl`1il~m-0Uw({F#ePrv!eKNEbvpUc-WH8rJAKRwU={-Zs6 z_Gl^3mmd$hdGn@Eo74Opt>)Kv`}S>Jx^y|&Uw*5|KeM4%U)9NzCtGQ=tgqw2=GWo( zVq#)KJ9g|y>fgY7wRi8{2h(Q!-~D`S#&0=(9oMg4*Plxzm4Ig5-QCGPw{lwc$&UA1 z?kww{t$*gUaNvN>o;{oF_pMvEcyCT=$IhL4?D5CdvtosxcFx!b`(Ar( zSi{4^+O&DI%H?vhPyRFgU{1?#W~A|;BUfz?RBV%{gWrXmmbuB~V76Sy3C}^*;P;-7 S52mW^$5Z1$X?rs>ulFlzqP*1r literal 0 HcmV?d00001 diff --git a/src/windows/leash/res/sync_disabled.ico b/src/windows/leash/res/sync_disabled.ico new file mode 100644 index 0000000000000000000000000000000000000000..0d806ab2afe86e364b789d327aab86f38beaa26d GIT binary patch literal 198 zcmZQzU<5(|0VW0z*Z{<0K&%180zj+)#2|SPXaJL##Q*>QQ3N@FJdhc73JeT&1q=)c vKY%n0{{e~v*&uBHfq_B(0Z<_jJm3dncAy>1Kn$@CB7uhlsXG8v57Gw!g%K5r literal 0 HcmV?d00001 diff --git a/src/windows/leash/resource.h b/src/windows/leash/resource.h new file mode 100644 index 000000000..629a75cec --- /dev/null +++ b/src/windows/leash/resource.h @@ -0,0 +1,336 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by Leash.rc +// +#define IDD_ABOUTBOX 100 +#define IDD_TEST2_FORM 102 +#define ID_HELLO_WORLD 114 +#define IDR_MAINFRAME 128 +#define IDR_LeashTYPE 129 +#define IDD_DIALOG1 130 +#define IDD_FORMVIEW 130 +#define IDD_LEASH_FORMVIEW 130 +#define IDI_TICKET_EXPIRED 141 +#define IDI_LEASH 143 +#define IDI_TICKETTYPE_GOOD 144 +#define IDI_TICKET_GOOD 145 +#define IDI_TICKET_LOW 146 +#define IDI_TICKETTYPE_NOTINSTALLED 147 +#define IDI_TICKETTYPE_EXPIRED 148 +#define IDI_TICKETTYPE_LOW 149 +#define IDD_LEASH_ABOUTBOX 153 +#define IDD_DIALOG2 154 +#define IDD_MESSAGE_BOX 154 +#define IDD_LEASH_MESSAGE_BOX 154 +#define IDD_DIALOG3 155 +#define IDD_DIALOG4 156 +#define IDD_DEBUG_WINDOW 157 +#define IDD_LEASH_DEBUG_WINDOW 157 +#define IDD_PAGE1 160 +#define IDD_KRB4_PROP_LOCATION 160 +#define IDD_PAGE2 161 +#define IDD_KRB4_PROP_CONTENT 161 +#define IDD_KRB_PROP_CONTENT 161 +#define IDD_LEASH_PROPERTIES 167 +#define IDD_KERB5_PAGE_PROP 168 +#define IDD_KRB5_PROP_CONTENT 168 +#define IDD_KRB5_PROP_LOCATION 169 +#define IDD_KRB4_REALMHOST_MAINT 178 +#define IDD_KRB_REALMHOST_MAINT 178 +#define IDC_CURSOR1 179 +#define IDD_KRB4_DOMAINREALM_MAINT 180 +#define IDD_KRB4_ADD_REALMHOSTNAMES 181 +#define IDD_KRB_ADD_REALM 181 +#define IDD_KRB4_EDIT_REALMHOSTNAMES 182 +#define IDD_KRB_EDIT_REALM 182 +#define IDD_KRB4_ADD_DOMAINREALMNAME 183 +#define IDD_KRB4_EDIT_DOMAINREALMNAME 184 +#define IDD_DIALOG5 187 +#define IDD_KRB_ADD_KDC_HOSTSERVER 197 +#define IDD_KRB_EDIT_KDC_HOSTSERVER 199 +#define IDD_KRB4_REALMHOST_MAINT2 203 +#define IDD_KRB4_EDIT_REALM 204 +#define IDD_KRB4_ADD_REALM 205 +#define IDD_DIALOG6 207 +#define IDD_KRB_DOMAINREALM_MAINT 207 +#define IDD_DIALOG7 210 +#define IDI_ICON1 221 +#define IDD_AFS_PROPERTIES 224 +#define IDD_AUTHENTICATE 229 +#define IDI_LEASH_PRINCIPAL_GOOD 230 +#define IDI_LEASH_PRINCIPAL_LOW 231 +#define IDI_LEASH_PRINCIPAL_EXPIRED 232 +#define IDI_LEASH_PRINCIPAL_NONE 233 +#define IDB_BITMAP1 239 +#define IDI_TOOLBAR_INIT 240 +#define IDI_TOOLBAR_RENEW 241 +#define IDI_TOOLBAR_IMPORT 242 +#define IDI_TOOLBAR_DESTROY 243 +#define IDI_TOOLBAR_PASSWORD 244 +#define IDI_TOOLBAR_REFRESH 245 +#define IDI_TOOLBAR_SYNC 246 +#define IDI_TOOLBAR_INIT_DISABLED 247 +#define IDI_TOOLBAR_RENEW_DISABLED 248 +#define IDI_TOOLBAR_IMPORT_DISABLED 249 +#define IDI_TOOLBAR_DESTROY_DISABLED 250 +#define IDI_TOOLBAR_PASSWORD_DISABLED 251 +#define IDI_TOOLBAR_REFRESH_DISABLED 252 +#define IDI_TOOLBAR_SYNC_DISABLED 253 +#define MENU_TRAYICON 254 +#define ID_LEASH_RESTORE 255 +#define IDD_FRAMEOWNER 256 +#define ID_LEASH_MINIMIZE 257 +#define IDI_LEASH_TRAY_GOOD 258 +#define IDI_LEASH_TRAY_LOW 259 +#define IDI_LEASH_TRAY_EXPIRED 260 +#define IDI_LEASH_TRAY_NONE 261 +#define IDI_LEASH_TICKET_ADDRESS 262 +#define IDI_LEASH_TICKET_SESSION 263 +#define IDI_LEASH_TICKET_ENCRYPTION 264 +#define IDC_PROGRESS1 1000 +#define IDC_TRACKBAR1 1001 +#define IDC_TRACKBAR2 1002 +#define IDC_BUDDY_SPIN1 1003 +#define IDC_SPIN1 1004 +#define IDC_LISTVIEW1 1005 +#define IDC_TREEVIEW1 1006 +#define IDC_TREEVIEW 1006 +#define IDC_STATIC_TRACK1 1007 +#define IDC_STATIC_TRACK2 1008 +#define IDC_STATIC_LISTVIEW1 1009 +#define IDC_STATIC_TREEVIEW1 1010 +#define IDC_LABEL_KERB_TICKETS 1011 +#define IDC_LIST1 1012 +#define IDC_LEASH_MODULE_LB 1012 +#define IDC_LIST_KRB4_REALM_HOST 1012 +#define IDC_LIST_UTILITY 1012 +#define IDC_LIST_KDC_REALM 1012 +#define IDC_LIST_REMOVE_HOST 1012 +#define IDC_LISTBOX_DLL_LOADED 1013 +#define IDC_STATIC_ABOUTBOX_LEASH 1014 +#define IDC_STATIC_VERSION 1015 +#define IDC_STATIC_COPYRIGHT 1016 +#define IDC_STATIC_MODULES_LOADED 1018 +#define IDC_LEASH_WARNING_MSG 1019 +#define IDC_DEBUG_LISTBOX 1022 +#define IDC_COPY_TO_CLIPBOARD 1023 +#define IDC_LOG_FILE_LOCATION_LABEL 1024 +#define IDC_LOG_FILE_LOCATION_TEXT 1025 +#define IDC_LEASH_MODULES 1029 +#define IDC_ALL_MODULES 1030 +#define IDC_PROPERTIES 1031 +#define IDC_STATIC_NO_OF_MODULES 1036 +#define IDC_BUTTON_LEASHINI_DETAILS 1037 +#define IDC_BUTTON_LEASHINI_HELP 1037 +#define IDC_STATIC_LEASHINI_LOCATION 1038 +#define IDC_BUTTON_LEASHINI_HELP2 1039 +#define IDC_EDIT_LEASHINI 1040 +#define IDC_EDIT_KRB_LOCATION 1041 +#define IDC_EDIT_KRBREALM_LOCATION 1042 +#define IDC_STATIC_KRBCON_LOCATION 1043 +#define IDC_STATIC_KRBREALM_LOCATION 1044 +#define IDC_EDIT_KRB_KRBREALM_LOC 1045 +#define IDC_EDIT_KRB_LOC 1045 +#define IDC_EDIT_KRBREALM_LOC 1046 +#define IDC_BUTTON_KRB_BROWSE 1047 +#define IDC_BUTTON_KRBREALM_BROWSE 1048 +#define IDC_STATIC_LEASH 1049 +#define IDC_STATIC_KRB 1050 +#define IDC_EDITKRB5_LOCATION 1051 +#define IDC_STATIC_KRB5_LOCATION 1052 +#define IDC_STATIC_KRB5INI_LOCATION 1052 +#define IDC_BUTTON_KRB_DETAILS 1053 +#define IDC_BUTTON_KRBFILES_HELP 1053 +#define IDC_BUTTON_KRBTKT_HELP 1054 +#define IDC_STATIC_NDIR 1055 +#define IDC_EDIT_NDIR 1056 +#define IDC_STATIC_LEASH_PROPERTIES 1057 +#define IDC_STATIC_DEFAULT_REALM 1058 +#define IDC_EDIT_DEFAULT_REALM 1059 +#define IDC_EDIT_REALM_HOSTNAME 1060 +#define IDC_RADIO_ADMIN_SERVER 1062 +#define IDC_RADIO_NO_ADMIN_SERVER 1063 +#define IDC_EDIT_KRBTKFILE 1064 +#define IDC_STATIC_KRBTKFILE 1065 +#define IDC_NOT_LOADED_MODULES 1066 +#define IDC_STATIC_TICKET_FILE 1067 +#define IDC_EDIT_TICKET_FILE 1068 +#define IDC_STATIC_KRB5_TICKET_FILE 1068 +#define IDC_BUTTON_TICKETFILE_BROWSE 1069 +#define IDC_EDIT_KRB5_TXT_FILE 1069 +#define IDC_STATIC_CONFIG_FILES 1070 +#define IDC_BUTTON_KRB5_TICKETFILE_BROWSE 1070 +#define IDC_STATIC_TICKETFILE 1071 +#define IDC_CHECK_PROXIABLE 1073 +#define IDC_CHECK_FORWARDABLE 1074 +#define IDC_EDIT_KRB5INI_LOCATION 1076 +#define IDC_BUTTON_KRB5INI_BROWSE 1077 +#define IDC_BUTTON_KRB5INI_HELP 1078 +#define IDC_STATIC__KRB5_TICKETFILE 1079 +#define IDC_BUTTON_KRB5TKT_HELP 1080 +#define IDC_EDIT_TIME_SERVER 1081 +#define IDC_STATIC_TIMESERVER 1082 +#define IDC_STATIC_OPTIONS 1083 +#define IDC_STATIC_TICKET_OPTIONS 1085 +#define IDC_BUTTON1 1086 +#define IDC_BUTTON_AFS_PROPERTIES 1086 +#define IDC_RESET_DEFAULTS 1086 +#define IDC_BUTTON_KRB_HELP 1087 +#define IDC_STATIC_KRBREALM 1088 +#define IDC_BUTTON_KRBREALM_HELP 1089 +#define IDC_STATIC_HOST 1092 +#define IDC_STATIC_DOMAIN 1093 +#define IDC_EDIT_HOSTNAME 1096 +#define IDC_EDIT_DOMAINNAME 1097 +#define IDC_STATIC_REALM_HOSTNAME 1098 +#define ID_BUTTON_HOSTNAME_REMOVE 1100 +#define IDC_STATIC_CFG_LOCATION 1103 +#define IDC_BUTTON_HOSTNAME_ADD 1104 +#define IDC_BUTTON_HOSTMAINT_HELP 1105 +#define IDC_BUTTON_HOSTNAME_EDIT 1106 +#define IDC_STATIC_HAS_ADMINSERVER_ 1107 +#define IDC_STATIC_NO_ADMINSERVER 1108 +#define IDC_BUTTON_REALM_HOST_ADD 1110 +#define ID_BUTTON_REALM_HOST_REMOVE 1111 +#define ID_BUTTON_REALM_REMOVE 1111 +#define IDC_BUTTON_REALM_HOST_EDIT 1112 +#define IDC_BUTTON_REALM_EDIT 1112 +#define IDC_BUTTON_REALMHOST_MAINT_HELP 1113 +#define IDC_EDIT_DOMAINHOSTNAME 1115 +#define IDC_LIST_DOMAINREALM 1116 +#define IDC_EDIT_DOMAINHOST 1117 +#define IDC_BUTTON_KDCHOST_ADD 1117 +#define IDC_EDIT_REALMNAME 1118 +#define IDC_BUTTON_KDCHOST_REMOVE 1118 +#define stc32 0x045f +#define IDC_EDIT_DOMAINREALMNAME 1119 +#define IDC_BUTTON_KDCHOST_EDIT 1119 +#define IDC_STATIC_TICKET_FILEPATH 1120 +#define IDC_LIST_KDC_HOST 1123 +#define IDC_STATIC_REALM 1124 +#define IDC_BUTTON_ADMINSERVER 1125 +#define IDC_BUTTON_REMOVE_ADMINSERVER 1126 +#define IDC_STATIC_NOTE 1129 +#define IDC_EDIT_KDC_HOST 1130 +#define IDC_EDIT_REALM 1131 +#define IDC_BUTTON_KRB4_REALM_HOST_ADD 1133 +#define ID_BUTTON_KRB4_REALM_HOST_REMOVE 1134 +#define IDC_BUTTON_KRB4_REALM_HOST_EDIT 1135 +#define IDC_BUTTON_REALMHOST_MAINT_HELP2 1136 +#define IDC_BUTTON_HOST_ADD 1138 +#define ID_BUTTON_HOST_REMOVE 1139 +#define IDC_BUTTON_HOST_EDIT 1140 +#define IDC_STATIC_KRBCON 1141 +#define IDC_STATIC_KRBCON_LABEL 1142 +#define IDC_STATIC_KRBREALM_LABEL 1143 +#define IDC_STATIC_TXT 1145 +#define IDC_STATIC_TIMEHOST 1147 +#define IDC_STATIC_CONFILES 1148 +#define IDC_STATIC_KRBREALMS 1149 +#define IDC_STATIC_INIFILES 1150 +#define IDC_CHECK_CONFIRM_KRB5_EXISTS 1151 +#define IDC_RADIO_AFS_ENABLED 1152 +#define IDC_RADIO_AFS_DISABLED 1153 +#define IDC_STATIC_KRB_DEFAULT_LIFETIME 1154 +#define IDC_STATIC_TIME_UNITS 1155 +#define IDC_STATIC_KRB_DEFAULT_RENEWTILL 1155 +#define IDC_EDIT_DEFAULT_LIFETIME 1156 +#define IDC_ABOUT_COPYRIGHT 1158 +#define IDC_ABOUT_VERSION 1159 +#define IDC_CHECK_RENEWABLE 1159 +#define IDC_CHECK_NO_ADDRESS 1160 +#define IDC_IPADDRESS_PUBLIC 1162 +#define IDC_STATIC_IPADDR 1163 +#define IDC_STATIC_NAME 1164 +#define IDC_STATIC_PWD 1165 +#define IDC_EDIT1 1166 +#define IDC_EDIT_LIFE_MIN_D 1166 +#define IDC_COMBO1 1167 +#define IDC_EDIT_LIFETIME_D 1167 +#define IDC_EDIT2 1168 +#define IDC_EDIT_LIFE_MIN_H 1168 +#define IDC_STATIC_LIFETIME 1169 +#define IDC_EDIT_RENEWTILL_D 1169 +#define IDC_SLIDER1 1170 +#define IDC_EDIT_LIFETIME_H 1170 +#define IDC_STATIC_KRB5 1171 +#define IDC_EDIT_RENEWTILL_H 1171 +#define IDC_CHECK1 1172 +#define IDC_CHECK_REQUEST_KRB4 1172 +#define IDC_CHECK2 1173 +#define IDC_CHECK_PRESERVE_KINIT_OPTIONS 1173 +#define IDC_CHECK3 1174 +#define IDC_SLIDER2 1175 +#define IDC_STATIC_LIFETIME_VALUE 1176 +#define IDC_STATIC_RENEW_TILL_VALUE 1177 +#define IDC_PICTURE 1179 +#define IDC_DNS_KDC 1180 +#define IDC_KRB4_DNS_KDC 1181 +#define IDC_CHECK_CREATE_MISSING_CFG 1182 +#define IDC_GROUP_LEASH_MISC 1183 +#define IDC_STATIC_LIFETIME_RANGE 1184 +#define IDC_STATIC_RENEW_TILL_RANGE 1185 +#define IDC_EDIT_LIFE_MIN_M 1190 +#define IDC_EDIT_LIFE_MAX_D 1191 +#define IDC_EDIT_LIFE_MAX_H 1192 +#define IDC_EDIT_LIFE_MAX_M 1193 +#define IDC_STATIC_LIFE_RANGE_MIN 1194 +#define IDC_EDIT_RENEW_MIN_D 1195 +#define IDC_EDIT_RENEW_MIN_H 1196 +#define IDC_EDIT_RENEW_MIN_M 1197 +#define IDC_EDIT_RENEW_MAX_D 1198 +#define IDC_EDIT_RENEW_MAX_H 1199 +#define IDC_EDIT_RENEW_MAX_M 1200 +#define IDC_EDIT_LIFETIME_M 1201 +#define IDC_EDIT_RENEWTILL_M 1202 +#define IDC_RADIO_MSLSA_IMPORT_OFF 1203 +#define IDC_RADIO_MSLSA_IMPORT_ON 1204 +#define IDC_RADIO_MSLSA_IMPORT_MATCH 1205 +#define IDC_STATIC_LEASH_MSLSA 1206 +#define IDD_FILESPECIAL 1536 +#define IDD_LEASH_FILESPECIAL 1536 +#define IDD_KRB_PROP_MISC 1537 +#define ID_RENEW_TICKET 32776 +#define ID_DESTROY_TICKET 32777 +#define ID_SYN_TIME 32778 +#define ID_CHANGE_PASSWORD 32779 +#define ID_UPDATE_DISPLAY 32780 +#define ID_DEBUG_MODE 32781 +#define ID_CFG_FILES 32782 +#define ID_HELP_LEASH_ 32783 +#define ID_HELP_KERBEROS_ 32784 +#define ID_KILL_TIX_ONEXIT 32785 +#define ID_LARGE_ICONS 32786 +#define ID_UPPERCASE_REALM 32787 +#define ID_OPTIONS_RESETWINDOWSIZE 32789 +#define ID_RESET_WINDOW_SIZE 32790 +#define ID_AFS_CONTROL_PANEL 32791 +#define ID_SYSTEM_CONTROL_PANEL 32792 +#define ID_KRB4_PROPERTIES 32793 +#define ID_KRB5_PROPERTIES 32794 +#define ID_LEASH_PROPERTIES 32795 +#define ID_OPTIONS_LOWTICKETALARMSOUND 32796 +#define ID_LOW_TICKET_ALARM 32798 +#define ID_KRBCHECK 32799 +#define ID_PROPERTIES 32801 +#define ID_NEW_ITEM 32802 +#define ID_HELP_CONTENTS 32803 +#define ID_HELP_FIND 32803 +#define ID_HELP_LEASH32 32804 +#define ID_HELP_WHYUSELEASH32 32805 +#define ID_IMPORT_TICKET 32806 +#define ID_INIT_TICKET 32807 +#define ID_AUTO_RENEW 32808 +#define ID_OBTAIN_TGT_WITH_LPARAM 32809 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_3D_CONTROLS 1 +#define _APS_NEXT_RESOURCE_VALUE 241 +#define _APS_NEXT_COMMAND_VALUE 32810 +#define _APS_NEXT_CONTROL_VALUE 1207 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif -- 2.26.2