xref: /freebsd/crypto/krb5/src/windows/leash/LeashView.cpp (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
1 //*****************************************************************************
2 // File:	LeashView.cpp
3 // By:		Arthur David Leather
4 // Created:	12/02/98
5 // Copyright	@1998 Massachusetts Institute of Technology - All rights reserved.
6 // Description:	CPP file for LeashView.h. Contains variables and functions
7 //		for the Leash FormView
8 //
9 // History:
10 //
11 // MM/DD/YY	Inits	Description of Change
12 // 12/02/98	ADL		Original
13 // 20030508     JEA     Added
14 //*****************************************************************************
15 
16 #include "stdafx.h"
17 #include <afxpriv.h>
18 #include "Leash.h"
19 #include "LeashDoc.h"
20 #include "LeashView.h"
21 #include "MainFrm.h"
22 #include "reminder.h"
23 #include "lglobals.h"
24 #include "LeashDebugWindow.h"
25 #include "LeashMessageBox.h"
26 #include "LeashAboutBox.h"
27 #include <krb5.h>
28 
29 #ifdef _DEBUG
30 #define new DEBUG_NEW
31 #undef THIS_FILE
32 static CHAR THIS_FILE[] = __FILE__;
33 #endif
34 
35 #pragma comment(lib, "uxtheme")
36 /////////////////////////////////////////////////////////////////////////////
37 // CLeashView
38 
39 IMPLEMENT_DYNCREATE(CLeashView, CListView)
40 
41 BEGIN_MESSAGE_MAP(CLeashView, CListView)
42 	//{{AFX_MSG_MAP(CLeashView)
43     ON_MESSAGE(WM_WARNINGPOPUP, OnWarningPopup)
44 	ON_MESSAGE(WM_GOODBYE, OnGoodbye)
45     ON_MESSAGE(WM_TRAYICON, OnTrayIcon)
46     ON_NOTIFY(TVN_ITEMEXPANDED, IDC_TREEVIEW, OnItemexpandedTreeview)
47 	ON_WM_CREATE()
48 	ON_WM_SHOWWINDOW()
49 	ON_COMMAND(ID_INIT_TICKET, OnInitTicket)
50 	ON_COMMAND(ID_RENEW_TICKET, OnRenewTicket)
51 	ON_COMMAND(ID_DESTROY_TICKET, OnDestroyTicket)
52 	ON_COMMAND(ID_CHANGE_PASSWORD, OnChangePassword)
53 	ON_COMMAND(ID_MAKE_DEFAULT, OnMakeDefault)
54 	ON_COMMAND(ID_UPDATE_DISPLAY, OnUpdateDisplay)
55 	ON_COMMAND(ID_SYN_TIME, OnSynTime)
56 	ON_COMMAND(ID_DEBUG_MODE, OnDebugMode)
57 	ON_COMMAND(ID_LARGE_ICONS, OnLargeIcons)
58 	ON_COMMAND(ID_TIME_ISSUED, OnTimeIssued)
59 	ON_COMMAND(ID_VALID_UNTIL, OnValidUntil)
60 	ON_COMMAND(ID_RENEWABLE_UNTIL, OnRenewableUntil)
61 	ON_COMMAND(ID_SHOW_TICKET_FLAGS, OnShowTicketFlags)
62 	ON_COMMAND(ID_ENCRYPTION_TYPE, OnEncryptionType)
63 	ON_COMMAND(ID_CCACHE_NAME, OnCcacheName)
64 	ON_UPDATE_COMMAND_UI(ID_TIME_ISSUED, OnUpdateTimeIssued)
65 	ON_UPDATE_COMMAND_UI(ID_VALID_UNTIL, OnUpdateValidUntil)
66 	ON_UPDATE_COMMAND_UI(ID_RENEWABLE_UNTIL, OnUpdateRenewableUntil)
67 	ON_UPDATE_COMMAND_UI(ID_SHOW_TICKET_FLAGS, OnUpdateShowTicketFlags)
68 	ON_UPDATE_COMMAND_UI(ID_ENCRYPTION_TYPE, OnUpdateEncryptionType)
69 	ON_UPDATE_COMMAND_UI(ID_CCACHE_NAME, OnUpdateCcacheName)
70 	ON_COMMAND(ID_UPPERCASE_REALM, OnUppercaseRealm)
71 	ON_COMMAND(ID_KILL_TIX_ONEXIT, OnKillTixOnExit)
72 	ON_UPDATE_COMMAND_UI(ID_UPPERCASE_REALM, OnUpdateUppercaseRealm)
73 	ON_UPDATE_COMMAND_UI(ID_KILL_TIX_ONEXIT, OnUpdateKillTixOnExit)
74 	ON_WM_DESTROY()
75 	ON_UPDATE_COMMAND_UI(ID_DESTROY_TICKET, OnUpdateDestroyTicket)
76 	ON_UPDATE_COMMAND_UI(ID_INIT_TICKET, OnUpdateInitTicket)
77 	ON_UPDATE_COMMAND_UI(ID_RENEW_TICKET, OnUpdateRenewTicket)
78 	ON_COMMAND(ID_APP_ABOUT, OnAppAbout)
79 	ON_UPDATE_COMMAND_UI(ID_DEBUG_MODE, OnUpdateDebugMode)
80 	ON_UPDATE_COMMAND_UI(ID_CFG_FILES, OnUpdateCfgFiles)
81     ON_COMMAND(ID_LEASH_RESTORE, OnLeashRestore)
82     ON_COMMAND(ID_LEASH_MINIMIZE, OnLeashMinimize)
83 	ON_COMMAND(ID_LOW_TICKET_ALARM, OnLowTicketAlarm)
84 	ON_COMMAND(ID_AUTO_RENEW, OnAutoRenew)
85 	ON_UPDATE_COMMAND_UI(ID_LOW_TICKET_ALARM, OnUpdateLowTicketAlarm)
86 	ON_UPDATE_COMMAND_UI(ID_AUTO_RENEW, OnUpdateAutoRenew)
87 	ON_UPDATE_COMMAND_UI(ID_MAKE_DEFAULT, OnUpdateMakeDefault)
88 	ON_UPDATE_COMMAND_UI(ID_PROPERTIES, OnUpdateProperties)
89 	ON_COMMAND(ID_HELP_KERBEROS_, OnHelpKerberos)
90 	ON_COMMAND(ID_HELP_LEASH32, OnHelpLeash32)
91 	ON_COMMAND(ID_HELP_WHYUSELEASH32, OnHelpWhyuseleash32)
92 	ON_WM_SIZE()
93 	ON_WM_LBUTTONDOWN()
94 	ON_WM_CLOSE()
95 	ON_WM_HSCROLL()
96 	ON_WM_VSCROLL()
97     ON_WM_SYSCOLORCHANGE()
98     ON_MESSAGE(ID_OBTAIN_TGT_WITH_LPARAM, OnObtainTGTWithParam)
99     ON_NOTIFY(HDN_ITEMCHANGED, 0, OnItemChanged)
100 	//}}AFX_MSG_MAP
101 
102     ON_NOTIFY_REFLECT(LVN_ITEMCHANGING, &CLeashView::OnLvnItemchanging)
103     ON_NOTIFY_REFLECT(LVN_ITEMACTIVATE, &CLeashView::OnLvnItemActivate)
104     ON_NOTIFY_REFLECT(LVN_KEYDOWN, &CLeashView::OnLvnKeydown)
105     ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, &CLeashView::OnNMCustomdraw)
106 END_MESSAGE_MAP()
107 
108 
109 time_t CLeashView::m_ticketTimeLeft = 0;  // # of seconds left before tickets expire
110 INT  CLeashView::m_ticketStatusKrb5 = 0; // Defense Condition: are we low on tickets?
111 INT  CLeashView::m_warningOfTicketTimeLeftKrb5 = 0; // Prevents warning box from coming up repeatively
112 INT  CLeashView::m_warningOfTicketTimeLeftLockKrb5 = 0;
113 INT  CLeashView::m_updateDisplayCount;
114 INT  CLeashView::m_alreadyPlayedDisplayCount;
115 INT  CLeashView::m_autoRenewTickets = 0;
116 BOOL CLeashView::m_lowTicketAlarmSound;
117 INT  CLeashView::m_autoRenewalAttempted = 0;
118 LONG CLeashView::m_timerMsgNotInProgress = 1;
119 ViewColumnInfo CLeashView::sm_viewColumns[] =
120 {
121     {"Principal", true, -1, 200},                        // PRINCIPAL
122     {"Issued", false, ID_TIME_ISSUED, 100},              // TIME_ISSUED
123     {"Renewable Until", false, ID_RENEWABLE_UNTIL, 100}, // RENEWABLE_UNTIL
124     {"Valid Until", true, ID_VALID_UNTIL, 100},          // VALID_UNTIL
125     {"Encryption Type", false, ID_ENCRYPTION_TYPE, 100}, // ENCRYPTION_TYPE
126     {"Flags", false, ID_SHOW_TICKET_FLAGS, 100},         // TICKET_FLAGS
127     {"Credential Cache", false, ID_CCACHE_NAME, 105},    // CACHE_NAME
128 };
129 
130 static struct TicketFlag {
131     unsigned long m_flag;
132     const LPTSTR m_description;
133 } sm_TicketFlags[] =
134 {
135     {TKT_FLG_FORWARDABLE, _T("Forwardable")},
136     {TKT_FLG_FORWARDED, _T("Forwarded")},
137     {TKT_FLG_PROXIABLE, _T("Proxiable")},
138     {TKT_FLG_PROXY, _T("Proxy")},
139     {TKT_FLG_RENEWABLE, _T("Renewable")},
140 };
141 
krb5TicketFlagsToString(unsigned long flags,LPTSTR * outStr)142 static void krb5TicketFlagsToString(unsigned long flags, LPTSTR *outStr)
143 {
144     const int numFlags = sizeof(sm_TicketFlags) / sizeof(sm_TicketFlags[0]);
145     int strSize = 1;
146     LPTSTR str;
147     // pass 1: compute size
148     for (int i = 0; i < numFlags; i++) {
149         if (flags & sm_TicketFlags[i].m_flag) {
150             if (strSize > 1)
151                 strSize += 2;
152             strSize += strlen(sm_TicketFlags[i].m_description);
153         }
154     }
155     // allocate
156     str = (LPSTR)malloc(strSize);
157     if (str != NULL) {
158         *str = 0;
159         // pass 2: construct string
160         for (int i = 0; i < numFlags; i++) {
161             if (flags & sm_TicketFlags[i].m_flag) {
162                 if (str[0])
163                     _tcscat_s(str, strSize, _T(", "));
164                 _tcscat_s(str, strSize, sm_TicketFlags[i].m_description);
165             }
166         }
167     }
168     *outStr = str;
169 }
170 
171 
CreateBoldFont(HFONT font)172 static HFONT CreateBoldFont(HFONT font)
173 {
174     // @TODO: Should probably enumerate fonts here instead since this
175     // does not actually seem to guarantee returning a new font
176     // distinguishable from the original.
177     LOGFONT fontAttributes = { 0 };
178     ::GetObject(font, sizeof(fontAttributes), &fontAttributes);
179     fontAttributes.lfWeight = FW_BOLD;
180     HFONT boldFont = ::CreateFontIndirect(&fontAttributes);
181     return boldFont;
182 }
183 
CreateItalicFont(HFONT font)184 static HFONT CreateItalicFont(HFONT font)
185 {
186     LOGFONT fontAttributes = { 0 };
187     ::GetObject(font, sizeof(fontAttributes), &fontAttributes);
188     fontAttributes.lfItalic = TRUE;
189     HFONT italicFont = ::CreateFontIndirect(&fontAttributes);
190     return italicFont;
191 }
192 
CreateBoldItalicFont(HFONT font)193 static HFONT CreateBoldItalicFont(HFONT font)
194 {
195     LOGFONT fontAttributes = { 0 };
196     ::GetObject(font, sizeof(fontAttributes), &fontAttributes);
197     fontAttributes.lfWeight = FW_BOLD;
198     fontAttributes.lfItalic = TRUE;
199     HFONT boldItalicFont = ::CreateFontIndirect(&fontAttributes);
200     return boldItalicFont;
201 }
202 
203 bool change_icon_size = true;
204 
TimestampToFileTime(time_t t,LPFILETIME pft)205 void TimestampToFileTime(time_t t, LPFILETIME pft)
206 {
207     // Note that LONGLONG is a 64-bit value
208     ULONGLONG ll;
209 
210     ll = UInt32x32To64((DWORD)t, 10000000) + 116444736000000000;
211     pft->dwLowDateTime = (DWORD)ll;
212     pft->dwHighDateTime = ll >> 32;
213 }
214 
215 // allocate outstr
TimestampToLocalizedString(time_t t,LPTSTR * outStr)216 void TimestampToLocalizedString(time_t t, LPTSTR *outStr)
217 {
218     FILETIME ft, lft;
219     SYSTEMTIME st;
220     TimestampToFileTime(t, &ft);
221     FileTimeToLocalFileTime(&ft, &lft);
222     FileTimeToSystemTime(&lft, &st);
223     TCHAR timeFormat[80]; // 80 is max required for LOCALE_STIMEFORMAT
224     GetLocaleInfo(LOCALE_SYSTEM_DEFAULT,
225                   LOCALE_STIMEFORMAT,
226                   timeFormat,
227                   sizeof(timeFormat) / sizeof(timeFormat[0]));
228 
229     int timeSize = GetTimeFormat(LOCALE_SYSTEM_DEFAULT,
230                                  TIME_NOSECONDS,
231                                  &st,
232                                  timeFormat,
233                                  NULL,
234                                  0);
235     // Using dateFormat prevents localization of Month/day order,
236     // but there is no other way AFAICT to suppress the year
237     TCHAR * dateFormat = "MMM dd'  '";
238     int dateSize = GetDateFormat(LOCALE_SYSTEM_DEFAULT,
239         0, // flags
240         &st,
241         dateFormat, // format
242         NULL, // date string
243         0);
244 
245     if (*outStr)
246         free(*outStr);
247 
248     // Allocate string for combined date and time,
249     // but only need one terminating NULL
250     LPTSTR str = (LPSTR)malloc((dateSize + timeSize - 1) * sizeof(TCHAR));
251     if (!str) {
252         // LeashWarn allocation failure
253         *outStr = NULL;
254         return;
255     }
256     GetDateFormat(LOCALE_SYSTEM_DEFAULT,
257         0, // flags
258         &st,
259         dateFormat, // format
260         &str[0],
261         dateSize);
262 
263     GetTimeFormat(LOCALE_SYSTEM_DEFAULT,
264                     TIME_NOSECONDS,
265                     &st,
266                     timeFormat,
267                     &str[dateSize - 1],
268                     timeSize);
269     *outStr = str;
270 }
271 
272 #define SECONDS_PER_MINUTE (60)
273 #define SECONDS_PER_HOUR (60 * SECONDS_PER_MINUTE)
274 #define SECONDS_PER_DAY (24 * SECONDS_PER_HOUR)
275 #define MAX_DURATION_STR 255
276 // convert time in seconds to string
DurationToString(long delta,LPTSTR * outStr)277 void DurationToString(long delta, LPTSTR *outStr)
278 {
279     int days;
280     int hours;
281     int minutes;
282     TCHAR minutesStr[MAX_DURATION_STR+1];
283     TCHAR hoursStr[MAX_DURATION_STR+1];
284 
285     if (*outStr)
286         free(*outStr);
287     *outStr = (LPSTR)malloc((MAX_DURATION_STR + 1)* sizeof(TCHAR));
288     if (!(*outStr))
289         return;
290 
291     days = delta / SECONDS_PER_DAY;
292     delta -= days * SECONDS_PER_DAY;
293     hours = delta / SECONDS_PER_HOUR;
294     delta -= hours * SECONDS_PER_HOUR;
295     minutes = delta / SECONDS_PER_MINUTE;
296 
297     _snprintf(minutesStr, MAX_DURATION_STR, "%d m", minutes);
298     minutesStr[MAX_DURATION_STR] = 0;
299 
300     _snprintf(hoursStr, MAX_DURATION_STR, "%d h", hours);
301     hoursStr[MAX_DURATION_STR] = 0;
302 
303     if (days > 0) {
304         _snprintf(*outStr, MAX_DURATION_STR, "(%d d, %s remaining)", days,
305                   hoursStr);
306     } else if (hours > 0) {
307         _snprintf(*outStr, MAX_DURATION_STR, "(%s, %s remaining)", hoursStr,
308                   minutesStr);
309     } else {
310         _snprintf(*outStr, MAX_DURATION_STR, "(%s remaining)", minutesStr);
311     }
312     (*outStr)[MAX_DURATION_STR] = 0;
313 }
314 
315 /////////////////////////////////////////////////////////////////////////////
316 // CLeashView construction/destruction
317 
CLeashView()318 CLeashView::CLeashView()
319 {
320 ////@#+Need removing as well!
321     m_startup = TRUE;
322     m_warningOfTicketTimeLeftKrb5 = 0;
323     m_warningOfTicketTimeLeftLockKrb5 = 0;
324     m_largeIcons = 0;
325     m_destroyTicketsOnExit = 0;
326     m_debugWindow = 0;
327     m_upperCaseRealm = 0;
328     m_lowTicketAlarm = 0;
329 
330     m_pDebugWindow = NULL;
331     m_pDebugWindow = new CLeashDebugWindow(this);
332     if (!m_pDebugWindow)
333     {
334         AfxMessageBox("There is a problem with the Leash Debug Window!",
335                    MB_OK|MB_ICONSTOP);
336     }
337 
338     m_debugStartUp = TRUE;
339     m_isMinimum = FALSE;
340     m_lowTicketAlarmSound = FALSE;
341     m_alreadyPlayed = FALSE;
342     ResetTreeNodes();
343     m_hMenu = NULL;
344     m_pApp = NULL;
345     m_ccacheDisplay = NULL;
346     m_autoRenewTickets = 0;
347     m_autoRenewalAttempted = 0;
348     m_pWarningMessage = NULL;
349     m_bIconAdded = FALSE;
350     m_bIconDeleted = FALSE;
351     m_BaseFont = NULL;
352     m_BoldFont = NULL;
353     m_ItalicFont = NULL;
354     m_aListItemInfo = NULL;
355 }
356 
357 
~CLeashView()358 CLeashView::~CLeashView()
359 {
360     CCacheDisplayData *elem = m_ccacheDisplay;
361     while (elem) {
362         CCacheDisplayData *next = elem->m_next;
363         delete elem;
364         elem = next;
365     }
366     m_ccacheDisplay = NULL;
367     // destroys window if not already destroyed
368     if (m_pDebugWindow)
369         delete m_pDebugWindow;
370     if (m_BoldFont)
371         DeleteObject(m_BoldFont);
372     if (m_ItalicFont)
373         DeleteObject(m_ItalicFont);
374     if (m_aListItemInfo)
375         delete[] m_aListItemInfo;
376 }
377 
OnItemChanged(NMHDR * pNmHdr,LRESULT * pResult)378 void CLeashView::OnItemChanged(NMHDR* pNmHdr, LRESULT* pResult)
379 {
380     NMHEADER* pHdr = (NMHEADER*)pNmHdr;
381     if (!pHdr->pitem)
382         return;
383     if (!pHdr->pitem->mask & HDI_WIDTH)
384         return;
385 
386     // Sync column width and save to registry
387     for (int i = 0, columnIndex = 0; i < NUM_VIEW_COLUMNS; i++) {
388         ViewColumnInfo &info = sm_viewColumns[i];
389         if ((info.m_enabled) && (columnIndex++ == pHdr->iItem)) {
390             info.m_columnWidth = pHdr->pitem->cxy;
391             if (m_pApp)
392                 m_pApp->WriteProfileInt("ColumnWidths", info.m_name, info.m_columnWidth);
393             break;
394         }
395     }
396 }
397 
PreCreateWindow(CREATESTRUCT & cs)398 BOOL CLeashView::PreCreateWindow(CREATESTRUCT& cs)
399 {
400     // TODO: Modify the Window class or styles here by modifying
401     //  the CREATESTRUCT cs
402 
403     return CListView::PreCreateWindow(cs);
404 }
405 
406 /////////////////////////////////////////////////////////////////////////////
407 // CLeashView diagnostics
408 
409 #ifdef _DEBUG
AssertValid() const410 VOID CLeashView::AssertValid() const
411 {
412     CListView::AssertValid();
413 }
414 
Dump(CDumpContext & dc) const415 VOID CLeashView::Dump(CDumpContext& dc) const
416 {
417     CListView::Dump(dc);
418 }
419 
420 /*
421 LeashDoc* CLeashView::GetDocument() // non-debug version is inline
422 {
423     ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(LeashDoc)));
424     return (LeashDoc*)m_pDocument;
425 }
426 */
427 #endif //_DEBUG
428 
429 /////////////////////////////////////////////////////////////////////////////
430 // CLeashView message handlers
431 
Create(LPCTSTR lpszClassName,LPCTSTR lpszWindowName,DWORD dwStyle,const RECT & rect,CWnd * pParentWnd,UINT nID,CCreateContext * pContext)432 BOOL CLeashView::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName,
433                         DWORD dwStyle, const RECT& rect, CWnd* pParentWnd,
434                         UINT nID, CCreateContext* pContext)
435 {
436     return CListView::Create(lpszClassName, lpszWindowName, dwStyle, rect,
437                              pParentWnd, nID, pContext);
438 }
439 
OnCreate(LPCREATESTRUCT lpCreateStruct)440 INT CLeashView::OnCreate(LPCREATESTRUCT lpCreateStruct)
441 {
442     if (CListView::OnCreate(lpCreateStruct) == -1)
443         return -1;
444     return 0;
445 }
446 
OnClose(void)447 VOID CLeashView::OnClose(void)
448 {
449     printf("OnClose\n");
450 }
451 
LeashTime()452 time_t CLeashView::LeashTime()
453 {
454     _tzset();
455     return time(0);
456 }
457 
458 // Call while possessing a lock to ticketinfo.lockObj
GetLowTicketStatus(int ver)459 INT CLeashView::GetLowTicketStatus(int ver)
460 {
461     BOOL b_notix = (ver == 5 && !ticketinfo.Krb5.btickets);
462 
463     if (b_notix)
464         return NO_TICKETS;
465 
466     if (m_ticketTimeLeft <= 0L)
467         return ZERO_MINUTES_LEFT;
468 
469     if (m_ticketTimeLeft <= 20 * 60)
470         return (INT)(m_ticketTimeLeft / 5 / 60) + 2 -
471             (m_ticketTimeLeft % (5 * 60) == 0 ? 1 : 0);
472 
473     return PLENTY_OF_TIME;
474 }
475 
UpdateTicketTime(TICKETINFO & ti)476 VOID CLeashView::UpdateTicketTime(TICKETINFO& ti)
477 {
478     if (!ti.btickets) {
479         m_ticketTimeLeft = 0L;
480         return;
481     }
482 
483     m_ticketTimeLeft = ti.valid_until - LeashTime();
484 
485     if (m_ticketTimeLeft <= 0L)
486         ti.btickets = EXPIRED_TICKETS;
487 }
488 
489 
TimerProc(HWND hWnd,UINT nMsg,UINT_PTR nIDEvent,DWORD dwTime)490 VOID CALLBACK EXPORT CLeashView::TimerProc(HWND hWnd, UINT nMsg,
491                                            UINT_PTR nIDEvent, DWORD dwTime)
492 {
493     // All of the work is being done in the PreTranslateMessage method
494     // in order to have access to the object
495 }
496 
ApplicationInfoMissingMsg()497 VOID  CLeashView::ApplicationInfoMissingMsg()
498 {
499     AfxMessageBox("There is a problem finding Leash application information!",
500                MB_OK|MB_ICONSTOP);
501 }
502 
OnShowWindow(BOOL bShow,UINT nStatus)503 VOID CLeashView::OnShowWindow(BOOL bShow, UINT nStatus)
504 {
505     CListView::OnShowWindow(bShow, nStatus);
506 
507     // Get State of Icons Size
508     m_pApp = AfxGetApp();
509     if (!m_pApp)
510     {
511         ApplicationInfoMissingMsg();
512     }
513     else
514     {
515         m_largeIcons = m_pApp->GetProfileInt("Settings", "LargeIcons", ON);
516 
517         // Get State of Destroy Tickets On Exit
518         m_destroyTicketsOnExit = m_pApp->GetProfileInt("Settings", "DestroyTicketsOnExit", OFF);
519 
520         // Get State of Low Ticket Alarm
521         m_lowTicketAlarm = m_pApp->GetProfileInt("Settings", "LowTicketAlarm", ON);
522 
523         // Get State of Auto Renew Tickets
524         m_autoRenewTickets = m_pApp->GetProfileInt("Settings", "AutoRenewTickets", ON);
525 
526         // Get State of Upper Case Realm
527         m_upperCaseRealm = pLeash_get_default_uppercaserealm();
528 
529         // UI main display column widths
530         for (int i=0; i<NUM_VIEW_COLUMNS; i++) {
531             ViewColumnInfo &info = sm_viewColumns[i];
532             info.m_enabled = m_pApp->GetProfileInt("Settings",
533                                                    info.m_name,
534                                                    info.m_enabled);
535             info.m_columnWidth = m_pApp->GetProfileInt("ColumnWidths",
536                                                    info.m_name,
537                                                    info.m_columnWidth);
538         }
539 
540         OnLargeIcons();
541     }
542 
543     SetTimer(1, ONE_SECOND, TimerProc);
544 
545     if (!CLeashApp::m_hKrb5DLL)
546     {
547 ////Update not to mention K4
548         AfxMessageBox("Kerberos Five is not loaded!!!"
549                    "\r\nYou will not be able to retrieve tickets and/or "
550                    "tokens.",
551                    MB_OK|MB_ICONWARNING);
552     }
553 
554     SetDlgItemText(IDC_LABEL_KERB_TICKETS,
555 		   "Your Kerberos Tickets (Issued/Expires/[Renew]/Principal)");
556 
557     // CLeashApp::m_krbv5_context = NULL;
558 }
559 
OnInitTicket()560 VOID CLeashView::OnInitTicket()
561 {
562     try {
563         InitTicket(m_hWnd);
564     }
565     catch(...) {
566         AfxMessageBox("Ticket Getting operation already in progress", MB_OK, 0);
567     }
568 }
569 
InitTicket(void * hWnd)570 UINT CLeashView::InitTicket(void * hWnd)
571 {
572     LSH_DLGINFO_EX ldi;
573     char username[64];
574     char realm[192];
575     int i=0, j=0;
576     if (WaitForSingleObject( ticketinfo.lockObj, INFINITE ) != WAIT_OBJECT_0) {
577         throw("Unable to lock ticketinfo");
578     }
579     LeashKRB5ListDefaultTickets(&ticketinfo.Krb5);
580     char * principal = ticketinfo.Krb5.principal;
581     if (principal)
582         for (; principal[i] && principal[i] != '@'; i++)
583             username[i] = principal[i];
584     username[i] = '\0';
585     if (principal && principal[i]) {
586         for (i++ ; principal[i] ; i++, j++)
587         {
588             realm[j] = principal[i];
589         }
590     }
591     realm[j] = '\0';
592     LeashKRB5FreeTicketInfo(&ticketinfo.Krb5);
593     ReleaseMutex(ticketinfo.lockObj);
594 
595     ldi.size = sizeof(ldi);
596     ldi.dlgtype = DLGTYPE_PASSWD;
597     ldi.title = ldi.in.title;
598     strcpy_s(ldi.in.title,"MIT Kerberos: Get Ticket");
599     ldi.username = ldi.in.username;
600     strcpy(ldi.in.username,username);
601     ldi.realm = ldi.in.realm;
602     strcpy(ldi.in.realm,realm);
603     ldi.dlgtype = DLGTYPE_PASSWD;
604     ldi.use_defaults = 1;
605 
606     if (!hWnd)
607     {
608         AfxMessageBox("There is a problem finding the Leash Window!",
609                    MB_OK|MB_ICONSTOP);
610         return 0;
611     }
612 
613     int result = pLeash_kinit_dlg_ex((HWND)hWnd, &ldi);
614 
615     if (-1 == result)
616     {
617         AfxMessageBox("There is a problem getting tickets!",
618                    MB_OK|MB_ICONSTOP);
619     }
620     else if ( result )
621     {
622         if (WaitForSingleObject( ticketinfo.lockObj, INFINITE ) != WAIT_OBJECT_0) {
623             throw("Unable to lock ticketinfo");
624         }
625         m_warningOfTicketTimeLeftKrb5 = 0;
626         m_ticketStatusKrb5 = 0;
627         ReleaseMutex(ticketinfo.lockObj);
628         m_autoRenewalAttempted = 0;
629         ::SendMessage((HWND)hWnd, WM_COMMAND, ID_UPDATE_DISPLAY, 0);
630     }
631     return 0;
632 }
633 
krenew(void * param)634 static UINT krenew(void *param)
635 {
636     char *ccache_name = (char *)param;
637     krb5_context ctx = 0;
638     krb5_ccache ccache = NULL;
639     krb5_principal me = 0;
640     krb5_principal server = 0;
641     krb5_creds my_creds;
642     krb5_data *realm = 0;
643 
644     memset(&my_creds, 0, sizeof(krb5_creds));
645     if (ccache_name == NULL)
646         // Bad param
647         goto cleanup;
648 
649     krb5_error_code code = pkrb5_init_context(&ctx);
650     if (code) {
651         // TODO: spew error
652         goto cleanup;
653     }
654     code = pkrb5_cc_resolve(ctx, ccache_name, &ccache);
655     if (code) {
656         // TODO: spew error
657         goto cleanup;
658     }
659 
660     code = pkrb5_cc_get_principal(ctx, ccache, &me);
661     if (code)
662         goto cleanup;
663 
664     realm = krb5_princ_realm(ctx, me);
665 
666     code = pkrb5_build_principal_ext(ctx, &server,
667                                     realm->length, realm->data,
668                                     KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME,
669                                     realm->length, realm->data,
670                                     0);
671     if (code)
672         goto cleanup;
673 
674     my_creds.client = me;
675     my_creds.server = server;
676 
677 #ifdef KRB5_TC_NOTICKET
678     pkrb5_cc_set_flags(ctx, ccache, 0);
679 #endif
680     code = pkrb5_get_renewed_creds(ctx, &my_creds, me, ccache, NULL);
681 #ifdef KRB5_TC_NOTICKET
682     pkrb5_cc_set_flags(ctx, ccache, KRB5_TC_NOTICKET);
683 #endif
684     if (code) {
685 /* TODO
686         if (code != KRB5KDC_ERR_ETYPE_NOSUPP || code != KRB5_KDC_UNREACH)
687             Leash_krb5_error(code, "krb5_get_renewed_creds()", 0, &ctx,
688                              &ccache);
689 */
690         goto cleanup;
691     }
692 
693     code = pkrb5_cc_initialize(ctx, ccache, me);
694     if (code)
695         goto cleanup;
696 
697     code = pkrb5_cc_store_cred(ctx, ccache, &my_creds);
698     if (code)
699         goto cleanup;
700 
701 cleanup:
702     if (my_creds.client == me)
703         my_creds.client = 0;
704     if (my_creds.server == server)
705         my_creds.server = 0;
706     pkrb5_free_cred_contents(ctx, &my_creds);
707     if (me != NULL)
708         pkrb5_free_principal(ctx, me);
709     if (server != NULL)
710         pkrb5_free_principal(ctx, server);
711     if (ccache != NULL)
712         pkrb5_cc_close(ctx, ccache);
713     if (ctx != NULL)
714         pkrb5_free_context(ctx);
715     if (ccache_name != NULL)
716         free(ccache_name);
717 
718     CLeashApp::m_bUpdateDisplay = TRUE;
719     return 0;
720 }
721 
OnRenewTicket()722 VOID CLeashView::OnRenewTicket()
723 {
724     if ( !CLeashApp::m_hKrb5DLL )
725         return;
726 
727     // @TODO: grab list mutex
728     CCacheDisplayData *elem = m_ccacheDisplay;
729     while (elem != NULL) {
730         if (elem->m_selected) {
731             char *ccache_name = strdup(elem->m_ccacheName);
732             if (ccache_name)
733                 AfxBeginThread(krenew, (void *)ccache_name);
734         }
735         elem = elem->m_next;
736     }
737     // release list mutex
738 }
739 
RenewTicket(void * hWnd)740 UINT CLeashView::RenewTicket(void * hWnd)
741 {
742     if ( !CLeashApp::m_hKrb5DLL )
743         return 0;
744 
745     // Try to renew
746     BOOL b_renewed = pLeash_renew();
747     if ( b_renewed ) {
748         m_warningOfTicketTimeLeftKrb5 = 0;
749         m_ticketStatusKrb5 = 0;
750         m_autoRenewalAttempted = 0;
751         ReleaseMutex(ticketinfo.lockObj);
752         ::SendMessage((HWND)hWnd, WM_COMMAND, ID_UPDATE_DISPLAY, 0);
753         return 0;
754     }
755 
756     AfxBeginThread(InitTicket,hWnd);
757 
758     return 0;
759 }
760 
kdestroy(const char * ccache_name)761 static void kdestroy(const char *ccache_name)
762 {
763     krb5_context ctx;
764     krb5_ccache ccache=NULL;
765     int code = pkrb5_init_context(&ctx);
766     if (code) {
767         // TODO: spew error
768         goto cleanup;
769     }
770     code = pkrb5_cc_resolve(ctx, ccache_name, &ccache);
771     if (code) {
772         // TODO: spew error
773         goto cleanup;
774     }
775     code = pkrb5_cc_destroy(ctx, ccache);
776     if (code) {
777         goto cleanup;
778     }
779 cleanup:
780     if (ctx)
781         pkrb5_free_context(ctx);
782 }
783 
784 
OnDestroyTicket()785 VOID CLeashView::OnDestroyTicket()
786 {
787     // @TODO: grab mutex
788     BOOL destroy = FALSE;
789     CCacheDisplayData *elem = m_ccacheDisplay;
790     while (elem) {
791         if (elem->m_selected) {
792             // @TODO add princ to msg text
793             destroy = TRUE;
794         }
795         elem = elem->m_next;
796     }
797     // release mutex
798 
799     if (destroy)
800     {
801         INT whatToDo;
802 
803         whatToDo = AfxMessageBox("Are you sure you want to destroy these tickets?",
804                                     MB_ICONEXCLAMATION|MB_YESNO, 0);
805 
806         if (whatToDo == IDYES)
807         {
808             // grab list mutex
809             elem = m_ccacheDisplay;
810             while (elem) {
811                 if (elem->m_selected)
812                     kdestroy(elem->m_ccacheName);
813                 elem = elem->m_next;
814             }
815             // release list mutex
816             SendMessage(WM_COMMAND, ID_UPDATE_DISPLAY, 0);
817         }
818     }
819     m_autoRenewalAttempted = 0;
820 }
821 
OnMakeDefault()822 VOID CLeashView::OnMakeDefault()
823 {
824     CCacheDisplayData *elem = m_ccacheDisplay;
825     int code = 0;
826     krb5_context ctx;
827     krb5_ccache cc;
828     while (elem) {
829         if (elem->m_selected) {
830             pkrb5_init_context(&ctx);
831             code = pkrb5_cc_resolve(ctx, elem->m_ccacheName, &cc);
832             if (!code)
833                 code = pkrb5_cc_switch(ctx, cc);
834             if (!code) {
835                 const char *cctype = pkrb5_cc_get_type(ctx, cc);
836                 if (cctype != NULL) {
837                     char defname[20];
838                     sprintf_s(defname, "%s:", cctype);
839                     code = pkrb5int_cc_user_set_default_name(ctx, defname);
840                 }
841             }
842             pkrb5_free_context(ctx);
843             CLeashApp::m_bUpdateDisplay = TRUE;
844             break;
845         }
846         elem = elem->m_next;
847     }
848 }
849 
OnChangePassword()850 VOID CLeashView::OnChangePassword()
851 {
852     krb5_context ctx = 0;
853     krb5_ccache ccache = 0;
854     krb5_principal princ = 0;
855     char *pname = NULL;
856     char *username = NULL;
857     char *realm = NULL;
858     int code = 0;
859 
860     CCacheDisplayData *elem = m_ccacheDisplay;
861     while (elem != NULL) {
862         if (elem->m_selected) {
863             if (elem->m_ccacheName)
864                 break;
865         }
866         elem = elem->m_next;
867     }
868     if (elem != NULL) {
869         code = pkrb5_init_context(&ctx);
870         if (code) {
871             // TODO: spew error
872             goto cleanup;
873         }
874         code = pkrb5_cc_resolve(ctx, elem->m_ccacheName, &ccache);
875         if (code) {
876             // TODO: spew error
877             goto cleanup;
878         }
879         code = pkrb5_cc_get_principal(ctx, ccache, &princ);
880         if (code) {
881             goto cleanup;
882         }
883         code = pkrb5_unparse_name(ctx, princ, &pname);
884         if (code) {
885             goto cleanup;
886         }
887     }
888 
889     LSH_DLGINFO_EX ldi;
890     if (pname != NULL) {
891         username = pname;
892         realm = strchr(pname, '@');
893         if (realm != NULL)
894             *realm++ = '\0';
895     }
896     ldi.size = sizeof(ldi);
897     ldi.dlgtype = DLGTYPE_CHPASSWD;
898     ldi.title = ldi.in.title;
899     strcpy_s(ldi.in.title, "MIT Kerberos: Change Password");
900     ldi.username = ldi.in.username;
901     strcpy_s(ldi.in.username, username ? username : "");
902     ldi.realm = ldi.in.realm;
903     strcpy_s(ldi.in.realm, realm ? realm : "");
904     ldi.use_defaults = 1;
905 
906     int result = pLeash_changepwd_dlg_ex(m_hWnd, &ldi);
907     if (-1 == result) {
908         AfxMessageBox("There is a problem changing password!",
909                    MB_OK|MB_ICONSTOP);
910     }
911 cleanup:
912     if (pname != NULL)
913         pkrb5_free_unparsed_name(ctx, pname);
914     if (princ != NULL)
915         pkrb5_free_principal(ctx, princ);
916     if (ccache != NULL)
917         pkrb5_cc_close(ctx, ccache);
918     if (ctx != NULL)
919         pkrb5_free_context(ctx);
920 }
921 
922 static CCacheDisplayData **
FindCCacheDisplayData(const char * ccacheName,CCacheDisplayData ** pList)923 FindCCacheDisplayData(const char * ccacheName, CCacheDisplayData **pList)
924 {
925     CCacheDisplayData *elem;
926     while ((elem = *pList)) {
927         if (strcmp(ccacheName, elem->m_ccacheName)==0)
928             return pList;
929         pList = &elem->m_next;
930     }
931     return NULL;
932 }
933 
AddDisplayItem(CListCtrl & list,CCacheDisplayData * elem,int iItem,char * principal,time_t issued,time_t valid_until,time_t renew_until,char * encTypes,unsigned long flags,char * ccache_name)934 void CLeashView::AddDisplayItem(CListCtrl &list,
935                                 CCacheDisplayData *elem,
936                                 int iItem,
937                                 char *principal,
938                                 time_t issued,
939                                 time_t valid_until,
940                                 time_t renew_until,
941                                 char *encTypes,
942                                 unsigned long flags,
943                                 char *ccache_name)
944 {
945     TCHAR* localTimeStr=NULL;
946     TCHAR* durationStr=NULL;
947     TCHAR* flagsStr=NULL;
948     TCHAR tempStr[MAX_DURATION_STR+1];
949     time_t now = LeashTime();
950 
951     list.InsertItem(iItem, principal, -1);
952 
953     int iSubItem = 1;
954     if (sm_viewColumns[TIME_ISSUED].m_enabled) {
955         if (issued == 0) {
956             list.SetItemText(iItem, iSubItem++, "Unknown");
957         } else {
958             TimestampToLocalizedString(issued, &localTimeStr);
959             list.SetItemText(iItem, iSubItem++, localTimeStr);
960         }
961     }
962     if (sm_viewColumns[RENEWABLE_UNTIL].m_enabled) {
963         if (valid_until == 0) {
964             list.SetItemText(iItem, iSubItem++, "Unknown");
965         } else if (valid_until < now) {
966             list.SetItemText(iItem, iSubItem++, "Expired");
967         } else if (renew_until) {
968             TimestampToLocalizedString(renew_until, &localTimeStr);
969             DurationToString(renew_until - now, &durationStr);
970             if (localTimeStr && durationStr) {
971                 _snprintf(tempStr, MAX_DURATION_STR, "%s %s", localTimeStr, durationStr);
972                 tempStr[MAX_DURATION_STR] = 0;
973                 list.SetItemText(iItem, iSubItem++, tempStr);
974             }
975         } else {
976             list.SetItemText(iItem, iSubItem++, "Not renewable");
977         }
978     }
979     if (sm_viewColumns[VALID_UNTIL].m_enabled) {
980         if (valid_until == 0) {
981             list.SetItemText(iItem, iSubItem++, "Unknown");
982         } else if (valid_until < now) {
983             list.SetItemText(iItem, iSubItem++, "Expired");
984         } else {
985             TimestampToLocalizedString(valid_until, &localTimeStr);
986             DurationToString(valid_until - now, &durationStr);
987             if (localTimeStr && durationStr) {
988                 _snprintf(tempStr, MAX_DURATION_STR, "%s %s", localTimeStr, durationStr);
989                 tempStr[MAX_DURATION_STR] = 0;
990                 list.SetItemText(iItem, iSubItem++, tempStr);
991             }
992         }
993     }
994 
995     if (sm_viewColumns[ENCRYPTION_TYPE].m_enabled) {
996         list.SetItemText(iItem, iSubItem++, encTypes);
997     }
998     if (sm_viewColumns[TICKET_FLAGS].m_enabled) {
999         krb5TicketFlagsToString(flags, &flagsStr);
1000         list.SetItemText(iItem, iSubItem++, flagsStr);
1001     }
1002     if (sm_viewColumns[CACHE_NAME].m_enabled) {
1003         list.SetItemText(iItem, iSubItem++, ccache_name);
1004     }
1005     if (flagsStr)
1006         free(flagsStr);
1007     if (localTimeStr)
1008         free(localTimeStr);
1009     if (durationStr)
1010         free(durationStr);
1011 }
1012 
IsExpanded(TICKETINFO * info)1013 BOOL CLeashView::IsExpanded(TICKETINFO *info)
1014 {
1015     CCacheDisplayData **pElem = FindCCacheDisplayData(info->ccache_name,
1016                                                       &m_ccacheDisplay);
1017     return (pElem && (*pElem)->m_expanded) ? TRUE : FALSE;
1018 }
1019 
IsExpired(TICKETINFO * info)1020 BOOL CLeashView::IsExpired(TICKETINFO *info)
1021 {
1022     return LeashTime() > info->valid_until ? TRUE : FALSE;
1023 }
1024 
IsExpired(TicketList * ticket)1025 BOOL CLeashView::IsExpired(TicketList *ticket)
1026 {
1027     return LeashTime() > ticket->valid_until ? TRUE : FALSE;
1028 }
1029 
1030 CCacheDisplayData *
FindCCacheDisplayElem(CCacheDisplayData * pElem,int itemIndex)1031 FindCCacheDisplayElem(CCacheDisplayData *pElem, int itemIndex)
1032 {
1033     while (pElem != NULL) {
1034         if (pElem->m_index == itemIndex)
1035             return pElem;
1036         pElem = pElem->m_next;
1037     }
1038     return NULL;
1039 }
1040 
OnUpdateDisplay()1041 VOID CLeashView::OnUpdateDisplay()
1042 {
1043     CListCtrl& list = GetListCtrl();
1044     // @TODO: there is probably a more sensible place to initialize these...
1045     if ((m_BaseFont == NULL) && (list.GetFont())) {
1046         m_BaseFont = *list.GetFont();
1047         m_BoldFont = CreateBoldFont(m_BaseFont);
1048         m_ItalicFont = CreateItalicFont(m_BaseFont);
1049         m_BoldItalicFont = CreateBoldItalicFont(m_BaseFont);
1050     }
1051     // Determine currently focused item
1052     int focusItem = list.GetNextItem(-1, LVNI_FOCUSED);
1053     CCacheDisplayData *elem = m_ccacheDisplay;
1054     while (elem) {
1055         if (focusItem >= elem->m_index) {
1056             elem->m_focus = focusItem - elem->m_index;
1057             focusItem = -1;
1058         } else {
1059             elem->m_focus = -1;
1060         }
1061         elem = elem->m_next;
1062     }
1063 
1064     list.DeleteAllItems();
1065     ModifyStyle(LVS_TYPEMASK, LVS_REPORT);
1066 	UpdateWindow();
1067     // Delete all of the columns.
1068     while (list.DeleteColumn(0));
1069 
1070     list.SetImageList(&m_imageList, LVSIL_SMALL);
1071 
1072     // Reconstruct based on current options
1073     int columnIndex = 0;
1074     int itemIndex = 0;
1075     for (int i = 0; i < NUM_VIEW_COLUMNS; i++) {
1076         ViewColumnInfo &info = sm_viewColumns[i];
1077         if (info.m_enabled) {
1078             list.InsertColumn(columnIndex++,
1079                 (info.m_name), // @LOCALIZEME!
1080                 LVCFMT_LEFT,
1081                 info.m_columnWidth,
1082                 itemIndex++);
1083         }
1084     }
1085 
1086     INT ticketIconStatusKrb5;
1087     INT ticketIconStatus_SelectedKrb5;
1088     INT iconStatusKrb5;
1089 
1090     if (WaitForSingleObject( ticketinfo.lockObj, 100 ) != WAIT_OBJECT_0)
1091         throw("Unable to lock ticketinfo");
1092 
1093     // Get Kerb 5 tickets in list
1094     LeashKRB5ListDefaultTickets(&ticketinfo.Krb5);
1095     if (CLeashApp::m_hKrb5DLL && !CLeashApp::m_krbv5_profile)
1096     {
1097         CHAR confname[MAX_PATH];
1098         if (CLeashApp::GetProfileFile(confname, sizeof(confname)))
1099         {
1100             AfxMessageBox("Can't locate Kerberos Five Config. file!",
1101                         MB_OK|MB_ICONSTOP);
1102         }
1103 
1104         const char *filenames[2];
1105         filenames[0] = confname;
1106         filenames[1] = NULL;
1107         pprofile_init(filenames, &CLeashApp::m_krbv5_profile);
1108     }
1109 
1110     /*
1111      * Update Ticket Status for Krb5 so that we may use their state
1112      * to select the appropriate Icon for the Parent Node
1113      */
1114 
1115     /* Krb5 */
1116     UpdateTicketTime(ticketinfo.Krb5);
1117     m_ticketStatusKrb5 = GetLowTicketStatus(5);
1118     if ((!ticketinfo.Krb5.btickets) ||
1119         EXPIRED_TICKETS == ticketinfo.Krb5.btickets ||
1120         m_ticketStatusKrb5 == ZERO_MINUTES_LEFT)
1121     {
1122         ticketIconStatusKrb5 = EXPIRED_CLOCK;
1123         ticketIconStatus_SelectedKrb5 = EXPIRED_CLOCK;
1124         iconStatusKrb5 = EXPIRED_TICKET;
1125     }
1126     else if (TICKETS_LOW == ticketinfo.Krb5.btickets ||
1127              m_ticketStatusKrb5 == FIVE_MINUTES_LEFT ||
1128              m_ticketStatusKrb5 == TEN_MINUTES_LEFT ||
1129              m_ticketStatusKrb5 == FIFTEEN_MINUTES_LEFT)
1130     {
1131         ticketIconStatusKrb5 = LOW_CLOCK;
1132         ticketIconStatus_SelectedKrb5 = LOW_CLOCK;
1133         iconStatusKrb5 = LOW_TICKET;
1134     }
1135     else if ( CLeashApp::m_hKrb5DLL )
1136     {
1137         ticketIconStatusKrb5 = ACTIVE_CLOCK;
1138         ticketIconStatus_SelectedKrb5 = ACTIVE_CLOCK;
1139         iconStatusKrb5 = ACTIVE_TICKET;
1140     } else
1141     {
1142         ticketIconStatusKrb5 = EXPIRED_CLOCK;
1143         ticketIconStatus_SelectedKrb5 = EXPIRED_CLOCK;
1144         iconStatusKrb5 = TICKET_NOT_INSTALLED;
1145     }
1146 
1147     int trayIcon = NONE_PARENT_NODE;
1148     if (CLeashApp::m_hKrb5DLL && ticketinfo.Krb5.btickets) {
1149         switch ( iconStatusKrb5 ) {
1150         case ACTIVE_TICKET:
1151             trayIcon = ACTIVE_PARENT_NODE;
1152             break;
1153         case LOW_TICKET:
1154             trayIcon = LOW_PARENT_NODE;
1155             break;
1156         case EXPIRED_TICKET:
1157             trayIcon = EXPIRED_PARENT_NODE;
1158             break;
1159         }
1160     }
1161     SetTrayIcon(NIM_MODIFY, trayIcon);
1162 
1163     CCacheDisplayData* prevCCacheDisplay = m_ccacheDisplay;
1164     m_ccacheDisplay = NULL;
1165 
1166     const char *def_ccache_name = ticketinfo.Krb5.ccache_name;
1167     TICKETINFO *principallist = NULL;
1168     LeashKRB5ListAllTickets(&principallist);
1169     int iItem = 0;
1170     TicketList* tempList;
1171     TICKETINFO *principal = principallist;
1172     while (principal != NULL) {
1173         CCacheDisplayData **pOldElem;
1174         pOldElem = FindCCacheDisplayData(principal->ccache_name,
1175                                          &prevCCacheDisplay);
1176         if (pOldElem) {
1177             // remove from old list
1178             elem = *pOldElem;
1179             *pOldElem = elem->m_next;
1180             elem->m_next = NULL;
1181         } else {
1182             elem = new CCacheDisplayData(principal->ccache_name);
1183         }
1184         elem->m_isDefault = def_ccache_name &&
1185                             (strcmp(def_ccache_name, elem->m_ccacheName) == 0);
1186         elem->m_isRenewable = principal->renew_until != 0;
1187 
1188         elem->m_next = m_ccacheDisplay;
1189         m_ccacheDisplay = elem;
1190         elem->m_index = iItem;
1191 
1192         AddDisplayItem(list,
1193                        elem,
1194                        iItem++,
1195                        principal->principal,
1196                        principal->issued,
1197                        principal->valid_until,
1198                        principal->renew_until,
1199                        "",
1200                        principal->flags,
1201                        principal->ccache_name);
1202         if (elem->m_expanded) {
1203             for (tempList = principal->ticket_list;
1204                  tempList != NULL;
1205                  tempList = tempList->next) {
1206                 AddDisplayItem(list,
1207                                elem,
1208                                iItem++,
1209                                tempList->service,
1210                                tempList->issued,
1211                                tempList->valid_until,
1212                                tempList->renew_until,
1213                                tempList->encTypes,
1214                                tempList->flags,
1215                                principal->ccache_name);
1216             }
1217         }
1218         if ((elem->m_focus >= 0) &&
1219             (iItem > elem->m_index + elem->m_focus)) {
1220             list.SetItemState(elem->m_index + elem->m_focus, LVIS_FOCUSED,
1221                               LVIS_FOCUSED);
1222         }
1223         if (elem->m_selected)
1224             list.SetItemState(elem->m_index, LVIS_SELECTED, LVIS_SELECTED);
1225 
1226         principal = principal->next;
1227     }
1228 
1229     // create list item font data array
1230     if (m_aListItemInfo != NULL)
1231         delete[] m_aListItemInfo;
1232     m_aListItemInfo = new ListItemInfo[iItem];
1233     iItem = 0;
1234     for (principal = principallist; principal != NULL;
1235          principal = principal->next) {
1236         //
1237         HFONT font, durationFont;
1238         elem = FindCCacheDisplayElem(m_ccacheDisplay, iItem);
1239         if (elem != NULL && elem->m_isDefault) {
1240             font = m_BoldFont;
1241             durationFont = IsExpired(principal) ? m_BoldItalicFont : m_BoldFont;
1242         } else {
1243             font = m_BaseFont;
1244             durationFont = IsExpired(principal) ? m_ItalicFont : m_BaseFont;
1245         }
1246         m_aListItemInfo[iItem].m_font = font;
1247         m_aListItemInfo[iItem++].m_durationFont = durationFont;
1248 
1249         if (IsExpanded(principal)) {
1250             for (TicketList *ticket = principal->ticket_list;
1251                  ticket != NULL; ticket = ticket->next) {
1252                 font = m_BaseFont;
1253                 durationFont = IsExpired(ticket) ? m_ItalicFont : m_BaseFont;
1254                 m_aListItemInfo[iItem].m_font = font;
1255                 m_aListItemInfo[iItem++].m_durationFont = durationFont;
1256             }
1257         }
1258     }
1259 
1260     // delete ccache items that no longer exist
1261     while (prevCCacheDisplay != NULL) {
1262         CCacheDisplayData *next = prevCCacheDisplay->m_next;
1263         delete prevCCacheDisplay;
1264         prevCCacheDisplay = next;
1265     }
1266 
1267     LeashKRB5FreeTicketInfo(&ticketinfo.Krb5);
1268     LeashKRB5FreeTickets(&principallist);
1269 
1270     ReleaseMutex(ticketinfo.lockObj);
1271 }
1272 
OnSynTime()1273 VOID CLeashView::OnSynTime()
1274 {
1275     LONG returnValue;
1276     returnValue = pLeash_timesync(1);
1277 }
1278 
OnActivateView(BOOL bActivate,CView * pActivateView,CView * pDeactiveView)1279 VOID CLeashView::OnActivateView(BOOL bActivate, CView* pActivateView,
1280                                 CView* pDeactiveView)
1281 {
1282     UINT check = NULL;
1283 
1284     if (m_alreadyPlayed)
1285     {
1286         CListView::OnActivateView(bActivate, pActivateView, pDeactiveView);
1287         return;
1288     }
1289 
1290     // The following code has put here because at the time
1291     // 'checking and unchecking' a menuitem with the
1292     // 'OnUpdate.....(CCmdUI* pCmdUI) functions' were unreliable
1293     // in CLeashView -->> Better done in CMainFrame
1294     if( CLeashApp::m_hProgram != 0 )
1295     {
1296         m_hMenu = ::GetMenu(CLeashApp::m_hProgram);
1297     } else {
1298         return;
1299     }
1300 
1301     if (m_hMenu) {
1302         if (!m_largeIcons)
1303             check = CheckMenuItem(m_hMenu, ID_LARGE_ICONS, MF_CHECKED);
1304         else
1305             check = CheckMenuItem(m_hMenu, ID_LARGE_ICONS, MF_UNCHECKED);
1306 
1307         if( check != MF_CHECKED || check != MF_UNCHECKED )
1308         {
1309             m_debugStartUp = 1;
1310         }
1311 
1312         if (!m_destroyTicketsOnExit)
1313             check = CheckMenuItem(m_hMenu, ID_KILL_TIX_ONEXIT, MF_UNCHECKED);
1314         else
1315             check = CheckMenuItem(m_hMenu, ID_KILL_TIX_ONEXIT, MF_CHECKED);
1316 
1317         if (!m_upperCaseRealm)
1318             check = CheckMenuItem(m_hMenu, ID_UPPERCASE_REALM, MF_UNCHECKED);
1319         else
1320             check = CheckMenuItem(m_hMenu, ID_UPPERCASE_REALM, MF_CHECKED);
1321 
1322         for (int i=0; i<NUM_VIEW_COLUMNS; i++) {
1323             ViewColumnInfo &info = sm_viewColumns[i];
1324             if (info.m_id >= 0)
1325                 CheckMenuItem(m_hMenu, info.m_id,
1326                               info.m_enabled ? MF_CHECKED : MF_UNCHECKED);
1327         }
1328 
1329         if (!m_lowTicketAlarm)
1330             CheckMenuItem(m_hMenu, ID_LOW_TICKET_ALARM, MF_UNCHECKED);
1331         else
1332             CheckMenuItem(m_hMenu, ID_LOW_TICKET_ALARM, MF_CHECKED);
1333 
1334         if (!m_autoRenewTickets)
1335             CheckMenuItem(m_hMenu, ID_AUTO_RENEW, MF_UNCHECKED);
1336         else
1337             CheckMenuItem(m_hMenu, ID_AUTO_RENEW, MF_CHECKED);
1338 
1339         m_debugWindow = m_pApp->GetProfileInt("Settings", "DebugWindow", 0);
1340         if (!m_debugWindow)
1341             check = CheckMenuItem(m_hMenu, ID_DEBUG_MODE, MF_UNCHECKED);
1342         else
1343             check = CheckMenuItem(m_hMenu, ID_DEBUG_MODE, MF_CHECKED);
1344     }
1345     m_lowTicketAlarmSound = !!m_lowTicketAlarm;
1346     m_alreadyPlayed = TRUE;
1347     if (m_pApp)
1348     {
1349         m_debugWindow = m_pApp->GetProfileInt("Settings", "DebugWindow", 0);
1350 
1351         if (m_hMenu)
1352         {
1353             if (!m_debugWindow)
1354             {
1355                 CheckMenuItem(m_hMenu, ID_DEBUG_MODE, MF_UNCHECKED);
1356             }
1357             else
1358             {
1359                 CheckMenuItem(m_hMenu, ID_DEBUG_MODE, MF_CHECKED);
1360             }
1361         }
1362     }
1363     else
1364     {
1365         ApplicationInfoMissingMsg();
1366     }
1367 
1368     m_alreadyPlayed = TRUE;
1369 
1370     if (m_debugStartUp)
1371     {
1372         OnDebugMode();
1373     }
1374 
1375     m_debugStartUp = FALSE;
1376 
1377     CListView::OnActivateView(bActivate, pActivateView, pDeactiveView);
1378 }
1379 
1380 ////@#+Is this KRB4 only?
OnDebugMode()1381 VOID CLeashView::OnDebugMode()
1382 {
1383     if (!m_pDebugWindow)
1384     {
1385         AfxMessageBox("There is a problem with the Leash Debug Window!",
1386                    MB_OK|MB_ICONSTOP);
1387         return;
1388     }
1389 
1390 
1391     // Check all possible 'KRB' system variables, then delete debug file
1392     CHAR*  Env[] = {"TEMP", "TMP", "HOME", NULL};
1393     CHAR** pEnv = Env;
1394     CHAR debugFilePath[MAX_PATH];
1395     *debugFilePath = 0;
1396 
1397     while (*pEnv)
1398     {
1399         CHAR* ptestenv = getenv(*pEnv);
1400         if (ptestenv)
1401         {
1402             // reset debug file
1403             strcpy(debugFilePath, ptestenv);
1404             strcat(debugFilePath, "\\LshDebug.log");
1405             remove(debugFilePath);
1406             break;
1407         }
1408 
1409         pEnv++;
1410     }
1411 
1412     if (!m_debugStartUp)
1413     {
1414         if (m_debugWindow%2 == 0)
1415             m_debugWindow = ON;
1416         else
1417             m_debugWindow = OFF;
1418     }
1419 
1420     if (!m_pApp)
1421     {
1422         ApplicationInfoMissingMsg();
1423     }
1424     else if (!m_debugWindow)
1425     {
1426         if (m_hMenu)
1427             CheckMenuItem(m_hMenu, ID_DEBUG_MODE, MF_UNCHECKED);
1428 
1429         m_pApp->WriteProfileInt("Settings", "DebugWindow", FALSE_FLAG);
1430         m_pDebugWindow->DestroyWindow();
1431         return;
1432     }
1433     else
1434     {
1435         if (m_hMenu)
1436             CheckMenuItem(m_hMenu, ID_DEBUG_MODE, MF_CHECKED);
1437 
1438         m_pApp->WriteProfileInt("Settings", "DebugWindow", TRUE_FLAG);
1439     }
1440 
1441     // Creates the Debug dialog if not created already
1442     if (m_pDebugWindow->GetSafeHwnd() == 0)
1443     { // displays the Debug Window
1444         m_pDebugWindow->Create(debugFilePath);
1445     }
1446 }
1447 
ToggleViewColumn(eViewColumn viewOption)1448 void CLeashView::ToggleViewColumn(eViewColumn viewOption)
1449 {
1450     if ((viewOption < 0) || (viewOption >= NUM_VIEW_COLUMNS)) {
1451         //LeashWarn("ToggleViewColumn(): invalid view option index %i", viewOption);
1452         return;
1453     }
1454     ViewColumnInfo &info = sm_viewColumns[viewOption];
1455     info.m_enabled = !info.m_enabled;
1456     if (m_pApp)
1457         m_pApp->WriteProfileInt("Settings", info.m_name, info.m_enabled);
1458     // Don't update display immediately; wait for next idle so our
1459     // checkbox controls will be more responsive
1460     CLeashApp::m_bUpdateDisplay = TRUE;
1461 }
1462 
OnRenewableUntil()1463 VOID CLeashView::OnRenewableUntil()
1464 {
1465     ToggleViewColumn(RENEWABLE_UNTIL);
1466 }
1467 
OnUpdateRenewableUntil(CCmdUI * pCmdUI)1468 VOID CLeashView::OnUpdateRenewableUntil(CCmdUI *pCmdUI)
1469 {
1470     pCmdUI->SetCheck(sm_viewColumns[RENEWABLE_UNTIL].m_enabled);
1471 }
1472 
OnShowTicketFlags()1473 VOID CLeashView::OnShowTicketFlags()
1474 {
1475     ToggleViewColumn(TICKET_FLAGS);
1476 }
1477 
OnUpdateShowTicketFlags(CCmdUI * pCmdUI)1478 VOID CLeashView::OnUpdateShowTicketFlags(CCmdUI *pCmdUI)
1479 {
1480     pCmdUI->SetCheck(sm_viewColumns[TICKET_FLAGS].m_enabled);
1481 }
1482 
OnTimeIssued()1483 VOID CLeashView::OnTimeIssued()
1484 {
1485     ToggleViewColumn(TIME_ISSUED);
1486 }
1487 
OnUpdateTimeIssued(CCmdUI * pCmdUI)1488 VOID CLeashView::OnUpdateTimeIssued(CCmdUI *pCmdUI)
1489 {
1490     pCmdUI->SetCheck(sm_viewColumns[TIME_ISSUED].m_enabled);
1491 }
1492 
OnValidUntil()1493 VOID CLeashView::OnValidUntil()
1494 {
1495     ToggleViewColumn(VALID_UNTIL);
1496 }
1497 
OnUpdateValidUntil(CCmdUI * pCmdUI)1498 VOID CLeashView::OnUpdateValidUntil(CCmdUI *pCmdUI)
1499 {
1500     pCmdUI->SetCheck(sm_viewColumns[VALID_UNTIL].m_enabled);
1501 }
1502 
OnEncryptionType()1503 VOID CLeashView::OnEncryptionType()
1504 {
1505     ToggleViewColumn(ENCRYPTION_TYPE);
1506 }
1507 
OnUpdateEncryptionType(CCmdUI * pCmdUI)1508 VOID CLeashView::OnUpdateEncryptionType(CCmdUI *pCmdUI)
1509 {
1510     pCmdUI->SetCheck(sm_viewColumns[ENCRYPTION_TYPE].m_enabled);
1511 }
1512 
OnCcacheName()1513 VOID CLeashView::OnCcacheName()
1514 {
1515     ToggleViewColumn(CACHE_NAME);
1516 }
1517 
OnUpdateCcacheName(CCmdUI * pCmdUI)1518 VOID CLeashView::OnUpdateCcacheName(CCmdUI *pCmdUI)
1519 {
1520     pCmdUI->SetCheck(sm_viewColumns[CACHE_NAME].m_enabled);
1521 }
1522 
OnLargeIcons()1523 VOID CLeashView::OnLargeIcons()
1524 {
1525     INT x, y, n;
1526 
1527     if (change_icon_size)
1528     {
1529         if (m_largeIcons%2 == 0)
1530             m_largeIcons = ON;
1531         else
1532             m_largeIcons = OFF;
1533     }
1534     else
1535     {
1536         if (m_largeIcons%2 == 0)
1537             m_largeIcons = OFF;
1538         else
1539             m_largeIcons = ON;
1540     }
1541 
1542     x = y = SMALL_ICONS;
1543 
1544     if (!m_pApp)
1545         ApplicationInfoMissingMsg();
1546     else
1547     {
1548         if (!m_largeIcons)
1549         {
1550             if (m_hMenu)
1551                 CheckMenuItem(m_hMenu, ID_LARGE_ICONS, MF_CHECKED);
1552 
1553             x = y = LARGE_ICONS;
1554 
1555 	    if (!m_startup)
1556 	    {
1557                 m_pApp->WriteProfileInt("Settings", "LargeIcons", TRUE_FLAG);
1558 	    }
1559         }
1560         else
1561         {
1562             if (m_hMenu)
1563                 CheckMenuItem(m_hMenu, ID_LARGE_ICONS, MF_UNCHECKED);
1564 
1565             x = y = SMALL_ICONS;
1566 
1567             if (!m_startup)
1568             {
1569                 m_pApp->WriteProfileInt("Settings", "LargeIcons", FALSE_FLAG);
1570             }
1571         }
1572     }
1573 
1574     HICON hIcon[IMAGE_COUNT];
1575     for (n = 0; n < IMAGE_COUNT; n++)
1576     {
1577         hIcon[n] = NULL;
1578     }
1579 
1580     m_imageList.DeleteImageList( );
1581 
1582     UINT bitsPerPixel = GetDeviceCaps( ::GetDC(::GetDesktopWindow()), BITSPIXEL);
1583     UINT ilcColor;
1584     if ( bitsPerPixel >= 32 )
1585         ilcColor = ILC_COLOR32;
1586     else if ( bitsPerPixel >= 24 )
1587         ilcColor = ILC_COLOR24;
1588     else if ( bitsPerPixel >= 16 )
1589         ilcColor = ILC_COLOR16;
1590     else if ( bitsPerPixel >= 8 )
1591         ilcColor = ILC_COLOR8;
1592     else
1593         ilcColor = ILC_COLOR;
1594     m_imageList.Create(x, y, ilcColor | ILC_MASK, IMAGE_COUNT, 1);
1595     m_imageList.SetBkColor(GetSysColor(COLOR_WINDOW));
1596 
1597     hIcon[ACTIVE_TRAY_ICON] = AfxGetApp()->LoadIcon(IDI_LEASH_TRAY_GOOD);
1598     hIcon[LOW_TRAY_ICON] = AfxGetApp()->LoadIcon(IDI_LEASH_TRAY_LOW);
1599     hIcon[EXPIRED_TRAY_ICON] = AfxGetApp()->LoadIcon(IDI_LEASH_TRAY_EXPIRED);
1600     hIcon[NONE_TRAY_ICON]  = AfxGetApp()->LoadIcon(IDI_LEASH_TRAY_NONE);
1601     hIcon[ACTIVE_PARENT_NODE] = AfxGetApp()->LoadIcon(IDI_LEASH_PRINCIPAL_GOOD);
1602     hIcon[LOW_PARENT_NODE] = AfxGetApp()->LoadIcon(IDI_LEASH_PRINCIPAL_LOW);
1603     hIcon[EXPIRED_PARENT_NODE] = AfxGetApp()->LoadIcon(IDI_LEASH_PRINCIPAL_EXPIRED);
1604     hIcon[NONE_PARENT_NODE]  = AfxGetApp()->LoadIcon(IDI_LEASH_PRINCIPAL_NONE);
1605     hIcon[ACTIVE_TICKET] = AfxGetApp()->LoadIcon(IDI_TICKETTYPE_GOOD);
1606     hIcon[LOW_TICKET] = AfxGetApp()->LoadIcon(IDI_TICKETTYPE_LOW);
1607     hIcon[EXPIRED_TICKET] = AfxGetApp()->LoadIcon(IDI_TICKETTYPE_EXPIRED);
1608     hIcon[TICKET_NOT_INSTALLED] = AfxGetApp()->LoadIcon(IDI_TICKETTYPE_NOTINSTALLED);
1609     hIcon[ACTIVE_CLOCK] = AfxGetApp()->LoadIcon(IDI_TICKET_GOOD);
1610     hIcon[LOW_CLOCK] = AfxGetApp()->LoadIcon(IDI_TICKET_LOW);
1611     hIcon[EXPIRED_CLOCK] = AfxGetApp()->LoadIcon(IDI_TICKET_EXPIRED);
1612     hIcon[TKT_ADDRESS] = AfxGetApp()->LoadIcon(IDI_LEASH_TICKET_ADDRESS);
1613     hIcon[TKT_SESSION] = AfxGetApp()->LoadIcon(IDI_LEASH_TICKET_SESSION);
1614     hIcon[TKT_ENCRYPTION] = AfxGetApp()->LoadIcon(IDI_LEASH_TICKET_ENCRYPTION);
1615 
1616     for (n = 0; n < IMAGE_COUNT; n++)
1617     {
1618         if ( !hIcon[n] ) {
1619             AfxMessageBox("Can't find one or more images in the Leash Ticket Tree!",
1620                         MB_OK|MB_ICONSTOP);
1621             return;
1622         }
1623         m_imageList.Add(hIcon[n]);
1624     }
1625 
1626     if (!m_startup)
1627         SendMessage(WM_COMMAND, ID_UPDATE_DISPLAY, 0);
1628 }
1629 
OnKillTixOnExit()1630 VOID CLeashView::OnKillTixOnExit()
1631 {
1632     m_destroyTicketsOnExit = !m_destroyTicketsOnExit;
1633 
1634     if (m_pApp)
1635         m_pApp->WriteProfileInt("Settings", "DestroyTicketsOnExit",
1636                                 m_destroyTicketsOnExit);
1637 }
1638 
OnUpdateKillTixOnExit(CCmdUI * pCmdUI)1639 VOID CLeashView::OnUpdateKillTixOnExit(CCmdUI *pCmdUI)
1640 {
1641     pCmdUI->SetCheck(m_destroyTicketsOnExit);
1642 }
1643 
OnUppercaseRealm()1644 VOID CLeashView::OnUppercaseRealm()
1645 {
1646     m_upperCaseRealm = !m_upperCaseRealm;
1647 
1648     pLeash_set_default_uppercaserealm(m_upperCaseRealm);
1649 }
1650 
OnUpdateUppercaseRealm(CCmdUI * pCmdUI)1651 VOID CLeashView::OnUpdateUppercaseRealm(CCmdUI *pCmdUI)
1652 {
1653     // description is now 'allow mixed case', so reverse logic
1654     pCmdUI->SetCheck(!m_upperCaseRealm);
1655 }
1656 
ResetTreeNodes()1657 VOID CLeashView::ResetTreeNodes()
1658 {
1659     m_hPrincipalState = 0;
1660     m_hKerb5State = 0;
1661 }
1662 
OnDestroy()1663 VOID CLeashView::OnDestroy()
1664 {
1665     CCacheDisplayData *elem;
1666     SetTrayIcon(NIM_DELETE);
1667 
1668     if (m_destroyTicketsOnExit) {
1669         elem = m_ccacheDisplay;
1670         while (elem != NULL) {
1671             kdestroy(elem->m_ccacheName);
1672             elem = elem->m_next;
1673         }
1674     }
1675     CListView::OnDestroy();
1676 }
1677 
OnUpdateDestroyTicket(CCmdUI * pCmdUI)1678 VOID CLeashView::OnUpdateDestroyTicket(CCmdUI* pCmdUI)
1679 {
1680     // @TODO: mutex
1681     BOOL enable = FALSE;
1682     CCacheDisplayData *elem = m_ccacheDisplay;
1683     while (elem != NULL) {
1684         if (elem->m_selected) {
1685             enable = TRUE;
1686             break;
1687         }
1688         elem = elem->m_next;
1689     }
1690 
1691     pCmdUI->Enable(enable);
1692 }
1693 
OnUpdateInitTicket(CCmdUI * pCmdUI)1694 VOID CLeashView::OnUpdateInitTicket(CCmdUI* pCmdUI)
1695 {
1696   if (!CLeashApp::m_hKrb5DLL)
1697         pCmdUI->Enable(FALSE);
1698     else
1699         pCmdUI->Enable(TRUE);
1700 }
1701 
OnUpdateRenewTicket(CCmdUI * pCmdUI)1702 VOID CLeashView::OnUpdateRenewTicket(CCmdUI* pCmdUI)
1703 {
1704     // @TODO: mutex
1705     BOOL enable = FALSE;
1706     CCacheDisplayData *elem = m_ccacheDisplay;
1707     while (elem != NULL) {
1708         if (elem->m_selected) { // @TODO: && elem->m_renewable
1709             enable = TRUE;
1710             break;
1711         }
1712         elem = elem->m_next;
1713     }
1714 
1715     pCmdUI->Enable(enable);
1716 }
1717 
OnGoodbye(WPARAM wParam,LPARAM lParam)1718 LRESULT CLeashView::OnGoodbye(WPARAM wParam, LPARAM lParam)
1719 {
1720     m_pDebugWindow->DestroyWindow();
1721     return 0L;
1722 }
1723 
OnLeashRestore()1724 VOID CLeashView::OnLeashRestore()
1725 {
1726     if ( CMainFrame::m_isMinimum ) {
1727         CMainFrame * frame = (CMainFrame *)GetParentFrame();
1728         frame->ShowTaskBarButton(TRUE);
1729         frame->ShowWindow(SW_SHOWNORMAL);
1730     }
1731 }
1732 
OnLeashMinimize()1733 VOID CLeashView::OnLeashMinimize()
1734 {
1735     if ( !CMainFrame::m_isMinimum ) {
1736         CMainFrame * frame = (CMainFrame *)GetParentFrame();
1737         // frame->ShowTaskBarButton(FALSE);
1738         frame->ShowWindow(SW_HIDE);
1739         frame->ShowWindow(SW_MINIMIZE);
1740     }
1741 }
1742 
OnTrayIcon(WPARAM wParam,LPARAM lParam)1743 LRESULT CLeashView::OnTrayIcon(WPARAM wParam, LPARAM lParam)
1744 {
1745     switch ( lParam ) {
1746     case WM_LBUTTONDOWN:
1747         if ( CMainFrame::m_isMinimum )
1748             OnLeashRestore();
1749         else
1750             OnLeashMinimize();
1751         break;
1752     case WM_RBUTTONDOWN:
1753         {
1754             int nFlags;
1755             CMenu * menu = new CMenu();
1756             menu->CreatePopupMenu();
1757             if ( !CMainFrame::m_isMinimum )
1758                 menu->AppendMenu(MF_STRING, ID_LEASH_MINIMIZE, "&Close MIT Kerberos Window");
1759             else
1760                 menu->AppendMenu(MF_STRING, ID_LEASH_RESTORE, "&Open MIT Kerberos Window");
1761             menu->AppendMenu(MF_SEPARATOR);
1762             menu->AppendMenu(MF_STRING, ID_INIT_TICKET, "&Get Tickets");
1763             if (WaitForSingleObject( ticketinfo.lockObj, INFINITE ) != WAIT_OBJECT_0)
1764                 throw("Unable to lock ticketinfo");
1765             if (!ticketinfo.Krb5.btickets ||
1766 		!CLeashApp::m_hKrb5DLL)
1767                 nFlags = MF_STRING | MF_GRAYED;
1768             else
1769                 nFlags = MF_STRING;
1770             menu->AppendMenu(nFlags, ID_RENEW_TICKET, "&Renew Tickets");
1771             if (!ticketinfo.Krb5.btickets)
1772                 nFlags = MF_STRING | MF_GRAYED;
1773             else
1774                 nFlags = MF_STRING;
1775             ReleaseMutex(ticketinfo.lockObj);
1776             menu->AppendMenu(MF_STRING, ID_DESTROY_TICKET, "&Destroy Tickets");
1777             menu->AppendMenu(MF_STRING, ID_CHANGE_PASSWORD, "&Change Password");
1778 
1779             menu->AppendMenu(MF_SEPARATOR);
1780             if ( m_autoRenewTickets )
1781                 nFlags = MF_STRING | MF_CHECKED;
1782             else
1783                 nFlags = MF_STRING | MF_UNCHECKED;
1784             menu->AppendMenu(nFlags, ID_AUTO_RENEW, "&Automatic Ticket Renewal");
1785             if ( m_lowTicketAlarm )
1786                 nFlags = MF_STRING | MF_CHECKED;
1787             else
1788                 nFlags = MF_STRING | MF_UNCHECKED;
1789             menu->AppendMenu(nFlags, ID_LOW_TICKET_ALARM, "&Expiration Alarm");
1790             menu->AppendMenu(MF_SEPARATOR);
1791             menu->AppendMenu(MF_STRING, ID_APP_EXIT, "E&xit");
1792             menu->SetDefaultItem(ID_LEASH_RESTORE);
1793 
1794             POINT pt;
1795             GetCursorPos(&pt);
1796 
1797 	    SetForegroundWindow();
1798             menu->TrackPopupMenu(TPM_RIGHTALIGN | TPM_RIGHTBUTTON,
1799                                 pt.x, pt.y, GetParentFrame());
1800 	    PostMessage(WM_NULL, 0, 0);
1801             menu->DestroyMenu();
1802             delete menu;
1803         }
1804         break;
1805     case WM_MOUSEMOVE:
1806         // SendMessage(WM_COMMAND, ID_UPDATE_DISPLAY, 0);
1807         break;
1808     }
1809     return 0L;
1810 }
1811 
OnAppAbout()1812 VOID CLeashView::OnAppAbout()
1813 {
1814     CLeashAboutBox leashAboutBox;
1815     // To debug loaded dlls:
1816     // leashAboutBox.m_bListModules = TRUE;
1817     leashAboutBox.DoModal();
1818 }
1819 
1820 
OnInitialUpdate()1821 VOID CLeashView::OnInitialUpdate()
1822 {
1823     CListView::OnInitialUpdate();
1824     CLeashApp::m_hProgram = ::FindWindow(_T("LEASH.0WNDCLASS"), NULL);
1825     EnableToolTips();
1826 }
1827 
OnItemexpandedTreeview(NMHDR * pNMHDR,LRESULT * pResult)1828 VOID CLeashView::OnItemexpandedTreeview(NMHDR* pNMHDR, LRESULT* pResult)
1829 {
1830     NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
1831 
1832     if (m_hPrincipal == pNMTreeView->itemNew.hItem)
1833         m_hPrincipalState = pNMTreeView->action;
1834     else if (m_hKerb5 == pNMTreeView->itemNew.hItem)
1835         m_hKerb5State = pNMTreeView->action;
1836 
1837     CMainFrame::m_isBeingResized = TRUE;
1838     *pResult = 0;
1839 }
1840 
OnUpdateDebugMode(CCmdUI * pCmdUI)1841 VOID CLeashView::OnUpdateDebugMode(CCmdUI* pCmdUI)
1842 {
1843         pCmdUI->Enable(FALSE);
1844 }
1845 
OnUpdateCfgFiles(CCmdUI * pCmdUI)1846 VOID CLeashView::OnUpdateCfgFiles(CCmdUI* pCmdUI)
1847 {
1848         pCmdUI->Enable(FALSE);
1849 }
1850 
1851 /*
1852 void CLeashView::GetRowWidthHeight(CDC* pDC, LPCSTR theString, int& nRowWidth,
1853                                    int& nRowHeight, int& nCharWidth)
1854 {
1855     TEXTMETRIC tm;
1856 
1857     //CEx29aDoc* pDoc = GetDocument();
1858 	pDC->GetTextMetrics(&tm);
1859     nCharWidth = tm.tmAveCharWidth + 1;
1860     nRowWidth = strlen(theString);
1861 
1862     //int nFields = theString.GetLength();
1863 
1864     //for(int i = 0; i < nFields; i++)
1865     //{
1866 	//    nRowWidth += nCharWidth;
1867 	//}
1868 
1869     nRowWidth *= nCharWidth;
1870     nRowHeight = tm.tmHeight;
1871 }
1872 */
1873 
SetTrayText(int nim,CString tip)1874 void CLeashView::SetTrayText(int nim, CString tip)
1875 {
1876     if ( (nim == NIM_MODIFY) && (m_bIconDeleted) )
1877         return;
1878     if ( (nim == NIM_MODIFY) && (!m_bIconAdded) )
1879         nim = NIM_ADD;
1880 
1881     if ( (nim != NIM_DELETE) || IsWindow(m_hWnd) )
1882     {
1883         NOTIFYICONDATA nid;
1884         memset (&nid, 0x00, sizeof(NOTIFYICONDATA));
1885         nid.cbSize = sizeof(NOTIFYICONDATA);
1886         nid.hWnd = m_hWnd;
1887         nid.uID = 0;
1888         nid.uFlags = NIF_MESSAGE | NIF_TIP;
1889         nid.uCallbackMessage = WM_TRAYICON;
1890         strncpy(nid.szTip, (LPCTSTR) tip, sizeof(nid.szTip));
1891         nid.szTip[sizeof(nid.szTip)-1] = '\0';
1892         Shell_NotifyIcon (nim, &nid);
1893     }
1894 
1895     if ( nim == NIM_ADD )
1896         m_bIconAdded = TRUE;
1897     if ( nim == NIM_DELETE )
1898         m_bIconDeleted = TRUE;
1899 }
1900 
SetTrayIcon(int nim,int state)1901 void CLeashView::SetTrayIcon(int nim, int state)
1902 {
1903     static HICON hIcon[IMAGE_COUNT];
1904     static BOOL bIconInit = FALSE;
1905 
1906     if ( (nim == NIM_MODIFY) && (m_bIconDeleted) )
1907         return;
1908     if ( (nim == NIM_MODIFY) && (!m_bIconAdded) )
1909         nim = NIM_ADD;
1910 
1911     if ( (nim != NIM_DELETE) || IsWindow(m_hWnd) )
1912     {
1913         if ( !bIconInit ) {
1914             // The state is reported as the parent node value although
1915             // we want to use the Tray Version of the icons
1916             hIcon[ACTIVE_PARENT_NODE] = AfxGetApp()->LoadIcon(IDI_LEASH_TRAY_GOOD);
1917             hIcon[LOW_PARENT_NODE] = AfxGetApp()->LoadIcon(IDI_LEASH_TRAY_LOW);
1918             hIcon[EXPIRED_PARENT_NODE] = AfxGetApp()->LoadIcon(IDI_LEASH_TRAY_EXPIRED);
1919             hIcon[NONE_PARENT_NODE]  = AfxGetApp()->LoadIcon(IDI_LEASH_TRAY_NONE);
1920             bIconInit = TRUE;
1921         }
1922 
1923         NOTIFYICONDATA nid;
1924         memset (&nid, 0x00, sizeof(NOTIFYICONDATA));
1925         nid.cbSize = sizeof(NOTIFYICONDATA);
1926         nid.hWnd = m_hWnd;
1927         nid.uID = 0;
1928         nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
1929         nid.uCallbackMessage = WM_TRAYICON;
1930         nid.hIcon = hIcon[state];
1931         Shell_NotifyIcon (nim, &nid);
1932     }
1933 
1934     if ( nim == NIM_ADD )
1935         m_bIconAdded = TRUE;
1936     if ( nim == NIM_DELETE )
1937         m_bIconDeleted = TRUE;
1938 }
1939 
PostWarningMessage(const CString & message)1940 BOOL CLeashView::PostWarningMessage(const CString& message)
1941 {
1942     if (m_pWarningMessage)
1943     {
1944         return FALSE; // can't post more than one warning at a time
1945     }
1946     m_pWarningMessage = new CString(message);
1947     PostMessage(WM_WARNINGPOPUP);
1948     return TRUE;
1949 }
1950 
OnWarningPopup(WPARAM wParam,LPARAM lParam)1951 LRESULT CLeashView::OnWarningPopup(WPARAM wParam, LPARAM lParam)
1952 {
1953     CLeashMessageBox leashMessageBox(CMainFrame::m_isMinimum ? GetDesktopWindow() : NULL,
1954                                         *m_pWarningMessage, 100000);
1955     leashMessageBox.DoModal();
1956     delete m_pWarningMessage;
1957     m_pWarningMessage = NULL;
1958     return 0L;
1959 }
1960 
PreTranslateMessage(MSG * pMsg)1961 BOOL CLeashView::PreTranslateMessage(MSG* pMsg)
1962 {
1963 	if ( pMsg->message == ID_OBTAIN_TGT_WITH_LPARAM )
1964 	{
1965 		OutputDebugString("Obtain TGT with LParam\n");
1966 	}
1967 
1968     if ( pMsg->message == WM_TIMER ) {
1969         try {
1970         if (InterlockedDecrement(&m_timerMsgNotInProgress) == 0) {
1971 
1972             CString ticketStatusKrb5 = TCHAR(NOT_INSTALLED);
1973             CString strTimeDate;
1974             CString lowTicketWarningKrb5;
1975 
1976           timer_start:
1977             if (WaitForSingleObject( ticketinfo.lockObj, 100 ) != WAIT_OBJECT_0)
1978                 throw("Unable to lock ticketinfo");
1979             if (CLeashApp::m_hKrb5DLL)
1980             {
1981                 // KRB5
1982                 UpdateTicketTime(ticketinfo.Krb5);
1983 
1984                 if (!ticketinfo.Krb5.btickets)
1985                 {
1986                     ticketStatusKrb5 = "Kerb-5: No Tickets";
1987                 }
1988                 else if (EXPIRED_TICKETS == ticketinfo.Krb5.btickets)
1989                 {
1990                     ticketStatusKrb5 = "Kerb-5: Expired Ticket(s)";
1991                     m_ticketTimeLeft = 0;
1992                     lowTicketWarningKrb5 = "Your Kerberos Five ticket(s) have expired";
1993                     if (!m_warningOfTicketTimeLeftLockKrb5)
1994                         m_warningOfTicketTimeLeftKrb5 = 0;
1995                     m_warningOfTicketTimeLeftLockKrb5 = ZERO_MINUTES_LEFT;
1996                 }
1997                 else
1998                 {
1999                     m_ticketStatusKrb5 = GetLowTicketStatus(5);
2000                     switch (m_ticketStatusKrb5)
2001                     {
2002                     case TWENTY_MINUTES_LEFT:
2003                         break;
2004                     case FIFTEEN_MINUTES_LEFT:
2005                         ticketinfo.Krb5.btickets = TICKETS_LOW;
2006                         lowTicketWarningKrb5 = "Less then 15 minutes left on your Kerberos Five ticket(s)";
2007                         break;
2008                     case TEN_MINUTES_LEFT:
2009                         ticketinfo.Krb5.btickets = TICKETS_LOW;
2010                         lowTicketWarningKrb5 = "Less then 10 minutes left on your Kerberos Five ticket(s)";
2011                         if (!m_warningOfTicketTimeLeftLockKrb5)
2012                             m_warningOfTicketTimeLeftKrb5 = 0;
2013                         m_warningOfTicketTimeLeftLockKrb5 = TEN_MINUTES_LEFT;
2014                         break;
2015                     case FIVE_MINUTES_LEFT:
2016                         ticketinfo.Krb5.btickets = TICKETS_LOW;
2017                         if (m_warningOfTicketTimeLeftLockKrb5 == TEN_MINUTES_LEFT)
2018                             m_warningOfTicketTimeLeftKrb5 = 0;
2019                         m_warningOfTicketTimeLeftLockKrb5 = FIVE_MINUTES_LEFT;
2020                         lowTicketWarningKrb5 = "Less then 5 minutes left on your Kerberos Five ticket(s)";
2021                         break;
2022                     default:
2023                         m_ticketStatusKrb5 = 0;
2024                         break;
2025                     }
2026                 }
2027 
2028                 if (CMainFrame::m_isMinimum)
2029                 {
2030                     // minimized display
2031                     ticketStatusKrb5.Format("Kerb-5: %02d:%02d Left",
2032                                              (m_ticketTimeLeft / 60L / 60L),
2033                                              (m_ticketTimeLeft / 60L % 60L));
2034                 }
2035                 else
2036                 {
2037                     // normal display
2038                     if (GOOD_TICKETS == ticketinfo.Krb5.btickets || TICKETS_LOW == ticketinfo.Krb5.btickets)
2039                     {
2040                         if ( m_ticketTimeLeft >= 60 ) {
2041                             ticketStatusKrb5.Format("Kerb-5 Ticket Life: %02d:%02d",
2042                                                      (m_ticketTimeLeft / 60L / 60L),
2043                                                      (m_ticketTimeLeft / 60L % 60L));
2044                         } else {
2045                             ticketStatusKrb5.Format("Kerb-5 Ticket Life: < 1 min");
2046                         }
2047                     }
2048 #ifndef NO_STATUS_BAR
2049                     if (CMainFrame::m_wndStatusBar)
2050                     {
2051                         CMainFrame::m_wndStatusBar.SetPaneInfo(1, 111112, SBPS_NORMAL, 130);
2052                         CMainFrame::m_wndStatusBar.SetPaneText(1, ticketStatusKrb5, SBT_POPOUT);
2053                     }
2054 #endif
2055                 }
2056             }
2057             else
2058             {
2059                 // not installed
2060                 ticketStatusKrb5.Format("Kerb-5: Not Available");
2061 #ifndef NO_STATUS_BAR
2062                 if (CMainFrame::m_wndStatusBar)
2063                 {
2064                     CMainFrame::m_wndStatusBar.SetPaneInfo(1, 111112, SBPS_NORMAL, 130);
2065                     CMainFrame::m_wndStatusBar.SetPaneText(1, ticketStatusKrb5, SBT_POPOUT);
2066                 }
2067 #endif
2068             }
2069             //KRB5
2070 
2071             if ( m_ticketStatusKrb5 == TWENTY_MINUTES_LEFT &&
2072                  m_autoRenewTickets && !m_autoRenewalAttempted && ticketinfo.Krb5.renew_until &&
2073                  (ticketinfo.Krb5.renew_until - LeashTime() > 20 * 60))
2074             {
2075                 m_autoRenewalAttempted = 1;
2076                 ReleaseMutex(ticketinfo.lockObj);
2077                 AfxBeginThread(RenewTicket,m_hWnd);
2078                 goto timer_start;
2079             }
2080 
2081             BOOL warningKrb5 = m_ticketStatusKrb5 > NO_TICKETS &&
2082                 m_ticketStatusKrb5 < TWENTY_MINUTES_LEFT &&
2083                     !m_warningOfTicketTimeLeftKrb5;
2084 
2085             // Play warning message only once per each case statement above
2086             if (warningKrb5)
2087             {
2088 
2089                 CString lowTicketWarning = "";
2090                 int warnings = 0;
2091 
2092                 if (warningKrb5) {
2093                     lowTicketWarning += lowTicketWarningKrb5;
2094                     m_warningOfTicketTimeLeftKrb5 = ON;
2095                     warnings++;
2096                 }
2097 
2098                 ReleaseMutex(ticketinfo.lockObj);
2099                 AlarmBeep();
2100                 PostWarningMessage(lowTicketWarning);
2101                 if (WaitForSingleObject( ticketinfo.lockObj, 100 ) != WAIT_OBJECT_0)
2102                     throw("Unable to lock ticketinfo");
2103             }
2104 
2105             CTime tTimeDate = CTime::GetCurrentTime();
2106 
2107             if (CMainFrame::m_isMinimum)
2108             {
2109 	      strTimeDate = ( "MIT Kerberos - "
2110 			      "[" + ticketStatusKrb5 + "] - " +
2111 			      "[" + ticketinfo.Krb5.principal + "]" + " - " +
2112 			      tTimeDate.Format("%A, %B %d, %Y  %H:%M "));
2113             }
2114             else
2115             {
2116                 strTimeDate = ("MIT Kerberos - " +
2117                                 tTimeDate.Format("%A, %B %d, %Y  %H:%M ")
2118                                 //timeDate.Format("%d %b %y %H:%M:%S - ")
2119                                 );
2120             }
2121             ::SetWindowText(CLeashApp::m_hProgram, strTimeDate);
2122 
2123             if (CLeashApp::m_hKrb5DLL) {
2124                 if ( ticketinfo.Krb5.btickets )
2125                     strTimeDate = ( "MIT Kerberos: "
2126                                     "[" + ticketStatusKrb5 + "]" +
2127                                     " - [" + ticketinfo.Krb5.principal + "]");
2128                 else
2129                     strTimeDate = "MIT Kerberos: No Tickets";
2130             }
2131             ReleaseMutex(ticketinfo.lockObj);
2132 
2133             SetTrayText(NIM_MODIFY, strTimeDate);
2134 
2135             m_updateDisplayCount++;
2136             m_alreadyPlayedDisplayCount++;
2137         }
2138         } catch (...) {
2139         }
2140         InterlockedIncrement(&m_timerMsgNotInProgress);
2141     }  // WM_TIMER
2142 
2143 
2144     if (UPDATE_DISPLAY_TIME == m_updateDisplayCount)
2145     {
2146         m_updateDisplayCount = 0;
2147         SendMessage(WM_COMMAND, ID_UPDATE_DISPLAY, 0);
2148     }
2149 
2150     if (m_alreadyPlayedDisplayCount > 2)
2151     {
2152         m_alreadyPlayedDisplayCount = 0;
2153         m_alreadyPlayed = FALSE;
2154     }
2155 
2156     if (CMainFrame::m_isBeingResized)
2157     {
2158         m_startup = FALSE;
2159 
2160         UpdateWindow();
2161 
2162         CMainFrame::m_isBeingResized = FALSE;
2163     }
2164 
2165 	if (::IsWindow(pMsg->hwnd))
2166 		return CListView::PreTranslateMessage(pMsg);
2167 	else
2168 		return FALSE;
2169 }
2170 
OnLowTicketAlarm()2171 VOID CLeashView::OnLowTicketAlarm()
2172 {
2173     m_lowTicketAlarm = !m_lowTicketAlarm;
2174 
2175     if (m_pApp)
2176         m_pApp->WriteProfileInt("Settings", "LowTicketAlarm", m_lowTicketAlarm);
2177 }
2178 
OnUpdateLowTicketAlarm(CCmdUI * pCmdUI)2179 VOID CLeashView::OnUpdateLowTicketAlarm(CCmdUI* pCmdUI)
2180 {
2181     pCmdUI->SetCheck(m_lowTicketAlarm);
2182 }
2183 
OnAutoRenew()2184 VOID CLeashView::OnAutoRenew()
2185 {
2186     m_autoRenewTickets = !m_autoRenewTickets;
2187 
2188     if (m_pApp)
2189         m_pApp->WriteProfileInt("Settings", "AutoRenewTickets", m_autoRenewTickets);
2190 
2191     m_autoRenewalAttempted = 0;
2192 }
2193 
OnUpdateAutoRenew(CCmdUI * pCmdUI)2194 VOID CLeashView::OnUpdateAutoRenew(CCmdUI* pCmdUI)
2195 {
2196     pCmdUI->SetCheck(m_autoRenewTickets);
2197 }
2198 
OnUpdateMakeDefault(CCmdUI * pCmdUI)2199 VOID CLeashView::OnUpdateMakeDefault(CCmdUI* pCmdUI)
2200 {
2201     // enable if exactly one principal is selected and that principal is not
2202     // the default principal
2203     BOOL enable = FALSE;
2204     CCacheDisplayData *elem = m_ccacheDisplay;
2205     while (elem != NULL) {
2206         if (elem->m_selected) {
2207             if (enable) {
2208                 // multiple selection; disable button
2209                 enable = FALSE;
2210                 break;
2211             }
2212             if (elem->m_isDefault)
2213                 break;
2214 
2215             enable = TRUE;
2216         }
2217         elem = elem->m_next;
2218     }
2219     pCmdUI->Enable(enable);
2220 }
2221 
AlarmBeep()2222 VOID CLeashView::AlarmBeep()
2223 {
2224 	if (m_lowTicketAlarmSound)
2225 	{
2226 		::Beep(2000, 200);
2227 		::Beep(200, 200);
2228 		::Beep(700, 200);
2229 	}
2230 }
2231 
OnUpdateProperties(CCmdUI * pCmdUI)2232 VOID CLeashView::OnUpdateProperties(CCmdUI* pCmdUI)
2233 {
2234     if (CLeashApp::m_hKrb5DLL)
2235         pCmdUI->Enable();
2236     else
2237         pCmdUI->Enable(FALSE);
2238 }
2239 
OnHelpLeash32()2240 void CLeashView::OnHelpLeash32()
2241 {
2242 #ifdef CALL_HTMLHELP
2243 	AfxGetApp()->HtmlHelp(HID_LEASH_PROGRAM);
2244 #else
2245     AfxGetApp()->WinHelp(HID_LEASH_PROGRAM);
2246 #endif
2247 }
2248 
OnHelpKerberos()2249 void CLeashView::OnHelpKerberos()
2250 {
2251 #ifdef CALL_HTMLHELP
2252     AfxGetApp()->HtmlHelp(HID_ABOUT_KERBEROS);
2253 #else
2254     AfxGetApp()->WinHelp(HID_ABOUT_KERBEROS);
2255 #endif
2256 }
2257 
OnHelpWhyuseleash32()2258 void CLeashView::OnHelpWhyuseleash32()
2259 {
2260 #ifdef CALL_HTMLHELP
2261     AfxGetApp()->HtmlHelp(HID_WHY_USE_LEASH32);
2262 #else
2263     AfxGetApp()->WinHelp(HID_WHY_USE_LEASH32);
2264 #endif
2265 }
2266 
OnSysColorChange()2267 void CLeashView::OnSysColorChange()
2268 {
2269     change_icon_size = FALSE;
2270     CWnd::OnSysColorChange();
2271     OnLargeIcons();
2272     m_imageList.SetBkColor(GetSysColor(COLOR_WINDOW));
2273     change_icon_size = TRUE;
2274 }
2275 
2276 
2277 LRESULT
OnObtainTGTWithParam(WPARAM wParam,LPARAM lParam)2278 CLeashView::OnObtainTGTWithParam(WPARAM wParam, LPARAM lParam)
2279 {
2280     LRESULT res = 0;
2281     char *param = 0;
2282     LSH_DLGINFO_EX ldi;
2283     ldi.size = sizeof(ldi);
2284     ldi.dlgtype = DLGTYPE_PASSWD;
2285     ldi.use_defaults = 1;
2286     ldi.title = ldi.in.title;
2287     ldi.username = ldi.in.username;
2288     ldi.realm = ldi.in.realm;
2289 
2290     if (lParam)
2291         param = (char *) MapViewOfFile((HANDLE)lParam,
2292                                        FILE_MAP_ALL_ACCESS,
2293                                        0,
2294                                        0,
2295                                        4096);
2296 
2297     if ( param ) {
2298         if ( *param )
2299             strcpy_s(ldi.in.title,param);
2300         param += strlen(param) + 1;
2301         if ( *param )
2302             strcpy_s(ldi.in.username,param);
2303         param += strlen(param) + 1;
2304         if ( *param )
2305             strcpy_s(ldi.in.realm,param);
2306         param += strlen(param) + 1;
2307 	if ( *param )
2308 	    strcpy_s(ldi.in.ccache,param);
2309     } else {
2310         strcpy_s(ldi.in.title, "MIT Kerberos: Get Ticket");
2311     }
2312 
2313     if (strlen(ldi.username) > 0 && strlen(ldi.realm) > 0)
2314         ldi.dlgtype |= DLGFLAG_READONLYPRINC;
2315 
2316     res = pLeash_kinit_dlg_ex(m_hWnd, &ldi);
2317     if (param)
2318         UnmapViewOfFile(param);
2319     if (lParam)
2320         CloseHandle((HANDLE )lParam);
2321     ::SendMessage(m_hWnd, WM_COMMAND, ID_UPDATE_DISPLAY, 0);
2322     return res;
2323 }
2324 
2325 
2326 // Find the CCacheDisplayData corresponding to the specified item, if it exists
2327 static CCacheDisplayData *
FindCCacheDisplayData(int item,CCacheDisplayData * elem)2328 FindCCacheDisplayData(int item, CCacheDisplayData *elem)
2329 {
2330     while (elem != NULL) {
2331         if (elem->m_index == item)
2332             break;
2333         elem = elem->m_next;
2334     }
2335     return elem;
2336 }
2337 
2338 
OnLvnItemActivate(NMHDR * pNMHDR,LRESULT * pResult)2339 void CLeashView::OnLvnItemActivate(NMHDR *pNMHDR, LRESULT *pResult)
2340 {
2341     LPNMITEMACTIVATE pNMIA = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
2342     // TODO: Add your control notification handler code here
2343     CCacheDisplayData *elem = FindCCacheDisplayData(pNMIA->iItem,
2344                                                     m_ccacheDisplay);
2345     if (elem != NULL) {
2346         elem->m_expanded = !elem->m_expanded;
2347         OnUpdateDisplay();
2348     }
2349     *pResult = 0;
2350 }
2351 
2352 
OnLvnKeydown(NMHDR * pNMHDR,LRESULT * pResult)2353 void CLeashView::OnLvnKeydown(NMHDR *pNMHDR, LRESULT *pResult)
2354 {
2355     LPNMLVKEYDOWN pLVKeyDow = reinterpret_cast<LPNMLVKEYDOWN>(pNMHDR);
2356     int expand = -1; // -1 = unchanged; 0 = collapse; 1 = expand
2357     switch (pLVKeyDow->wVKey) {
2358     case VK_RIGHT:
2359         // expand focus item
2360         expand = 1;
2361         break;
2362     case VK_LEFT:
2363         // collapse focus item
2364         expand = 0;
2365         break;
2366     default:
2367         break;
2368     }
2369     if (expand >= 0) {
2370         int focusedItem = GetListCtrl().GetNextItem(-1, LVNI_FOCUSED);
2371         if (focusedItem >= 0) {
2372             CCacheDisplayData *elem = FindCCacheDisplayData(focusedItem,
2373                                                             m_ccacheDisplay);
2374             if (elem != NULL) {
2375                 if (elem->m_expanded != expand) {
2376                     elem->m_expanded = expand;
2377                     OnUpdateDisplay();
2378                 }
2379             }
2380         }
2381     }
2382     *pResult = 0;
2383 }
2384 
OnLvnItemchanging(NMHDR * pNMHDR,LRESULT * pResult)2385 void CLeashView::OnLvnItemchanging(NMHDR *pNMHDR, LRESULT *pResult)
2386 {
2387     CCacheDisplayData *elem;
2388     LRESULT result = 0;
2389     LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
2390     // TODO: Add your control notification handler code here
2391     if ((pNMLV->uNewState ^ pNMLV->uOldState) & LVIS_SELECTED) {
2392         // selection state changing
2393         elem = FindCCacheDisplayData(pNMLV->iItem, m_ccacheDisplay);
2394         if (elem == NULL) {
2395             // this is an individual ticket, not a cache, so prevent selection
2396             if (pNMLV->uNewState & LVIS_SELECTED) {
2397                 unsigned int newState =  pNMLV->uNewState & ~LVIS_SELECTED;
2398                 result = 1; // suppress changes
2399                 if (newState != pNMLV->uOldState) {
2400                     // but need to make other remaining changes still
2401                     GetListCtrl().SetItemState(pNMLV->iItem, newState,
2402                                                newState ^ pNMLV->uOldState);
2403                 }
2404             }
2405         } else {
2406             elem->m_selected = (pNMLV->uNewState & LVIS_SELECTED) ? 1 : 0;
2407         }
2408     }
2409     *pResult = result;
2410 }
2411 
GetSubItemFont(int iItem,int iSubItem)2412 HFONT CLeashView::GetSubItemFont(int iItem, int iSubItem)
2413 {
2414     HFONT retval = m_BaseFont;
2415     int iColumn, columnSubItem = 0;
2416 
2417     // Translate subitem to column index
2418     for (iColumn = 0; iColumn < NUM_VIEW_COLUMNS; iColumn++) {
2419         if (sm_viewColumns[iColumn].m_enabled) {
2420             if (columnSubItem == iSubItem)
2421                 break;
2422             else
2423                 columnSubItem++;
2424         }
2425     }
2426     switch (iColumn) {
2427     case RENEWABLE_UNTIL:
2428     case VALID_UNTIL:
2429         retval = m_aListItemInfo[iItem].m_durationFont;
2430         break;
2431     default:
2432         retval = m_aListItemInfo[iItem].m_font;
2433         break;
2434     }
2435     return retval;
2436 }
2437 
OnNMCustomdraw(NMHDR * pNMHDR,LRESULT * pResult)2438 void CLeashView::OnNMCustomdraw(NMHDR *pNMHDR, LRESULT *pResult)
2439 {
2440     HFONT font;
2441     CCacheDisplayData *pElem;
2442     *pResult = CDRF_DODEFAULT;
2443     int iItem;
2444 
2445     LPNMLVCUSTOMDRAW pNMLVCD = reinterpret_cast<LPNMLVCUSTOMDRAW>(pNMHDR);
2446     switch (pNMLVCD->nmcd.dwDrawStage) {
2447     case CDDS_PREPAINT:
2448         *pResult = CDRF_NOTIFYITEMDRAW;
2449         break;
2450     case CDDS_ITEMPREPAINT:
2451         *pResult = CDRF_NOTIFYSUBITEMDRAW;
2452         break;
2453     case CDDS_SUBITEM | CDDS_ITEMPREPAINT:
2454         iItem = pNMLVCD->nmcd.dwItemSpec;
2455         pElem = FindCCacheDisplayElem(m_ccacheDisplay, iItem);
2456         font = GetSubItemFont(iItem, pNMLVCD->iSubItem);
2457         SelectObject(pNMLVCD->nmcd.hdc, font);
2458         if (pElem != NULL && pNMLVCD->iSubItem == 0) {
2459             CListCtrl &list = GetListCtrl();
2460             CRect drawRect, nextRect;
2461             if (list.GetSubItemRect(iItem, 0, LVIR_BOUNDS, drawRect)) {
2462                 HTHEME hTheme = OpenThemeData(pNMLVCD->nmcd.hdr.hwndFrom,
2463                                               L"Explorer::TreeView");
2464                 drawRect.right = drawRect.left +
2465                                  (drawRect.bottom - drawRect.top);
2466                 // @TODO: need hot states, too: TVP_HOTGLYPH, HGLPS_OPENED,
2467                 //        HGLPS_CLOSED
2468                 int state = pElem->m_expanded ? GLPS_OPENED : GLPS_CLOSED;
2469                 DrawThemeBackground(hTheme,
2470                                     pNMLVCD->nmcd.hdc,
2471                                     TVP_GLYPH, state,
2472                                     &drawRect, NULL);
2473             }
2474         }
2475         *pResult = CDRF_NEWFONT;
2476         break;
2477     default:
2478         break;
2479     }
2480 }
2481