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