Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/krb5/src/windows/leash/LeashView.cpp
34889 views
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
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
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
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
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
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
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
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
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
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
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
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
410
VOID CLeashView::AssertValid() const
411
{
412
CListView::AssertValid();
413
}
414
415
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
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
440
INT CLeashView::OnCreate(LPCREATESTRUCT lpCreateStruct)
441
{
442
if (CListView::OnCreate(lpCreateStruct) == -1)
443
return -1;
444
return 0;
445
}
446
447
VOID CLeashView::OnClose(void)
448
{
449
printf("OnClose\n");
450
}
451
452
time_t CLeashView::LeashTime()
453
{
454
_tzset();
455
return time(0);
456
}
457
458
// Call while possessing a lock to ticketinfo.lockObj
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
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
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
497
VOID CLeashView::ApplicationInfoMissingMsg()
498
{
499
AfxMessageBox("There is a problem finding Leash application information!",
500
MB_OK|MB_ICONSTOP);
501
}
502
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
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
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
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
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
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
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
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
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
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 **
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
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
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
1020
BOOL CLeashView::IsExpired(TICKETINFO *info)
1021
{
1022
return LeashTime() > info->valid_until ? TRUE : FALSE;
1023
}
1024
1025
BOOL CLeashView::IsExpired(TicketList *ticket)
1026
{
1027
return LeashTime() > ticket->valid_until ? TRUE : FALSE;
1028
}
1029
1030
CCacheDisplayData *
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
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
1273
VOID CLeashView::OnSynTime()
1274
{
1275
LONG returnValue;
1276
returnValue = pLeash_timesync(1);
1277
}
1278
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?
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
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
1463
VOID CLeashView::OnRenewableUntil()
1464
{
1465
ToggleViewColumn(RENEWABLE_UNTIL);
1466
}
1467
1468
VOID CLeashView::OnUpdateRenewableUntil(CCmdUI *pCmdUI)
1469
{
1470
pCmdUI->SetCheck(sm_viewColumns[RENEWABLE_UNTIL].m_enabled);
1471
}
1472
1473
VOID CLeashView::OnShowTicketFlags()
1474
{
1475
ToggleViewColumn(TICKET_FLAGS);
1476
}
1477
1478
VOID CLeashView::OnUpdateShowTicketFlags(CCmdUI *pCmdUI)
1479
{
1480
pCmdUI->SetCheck(sm_viewColumns[TICKET_FLAGS].m_enabled);
1481
}
1482
1483
VOID CLeashView::OnTimeIssued()
1484
{
1485
ToggleViewColumn(TIME_ISSUED);
1486
}
1487
1488
VOID CLeashView::OnUpdateTimeIssued(CCmdUI *pCmdUI)
1489
{
1490
pCmdUI->SetCheck(sm_viewColumns[TIME_ISSUED].m_enabled);
1491
}
1492
1493
VOID CLeashView::OnValidUntil()
1494
{
1495
ToggleViewColumn(VALID_UNTIL);
1496
}
1497
1498
VOID CLeashView::OnUpdateValidUntil(CCmdUI *pCmdUI)
1499
{
1500
pCmdUI->SetCheck(sm_viewColumns[VALID_UNTIL].m_enabled);
1501
}
1502
1503
VOID CLeashView::OnEncryptionType()
1504
{
1505
ToggleViewColumn(ENCRYPTION_TYPE);
1506
}
1507
1508
VOID CLeashView::OnUpdateEncryptionType(CCmdUI *pCmdUI)
1509
{
1510
pCmdUI->SetCheck(sm_viewColumns[ENCRYPTION_TYPE].m_enabled);
1511
}
1512
1513
VOID CLeashView::OnCcacheName()
1514
{
1515
ToggleViewColumn(CACHE_NAME);
1516
}
1517
1518
VOID CLeashView::OnUpdateCcacheName(CCmdUI *pCmdUI)
1519
{
1520
pCmdUI->SetCheck(sm_viewColumns[CACHE_NAME].m_enabled);
1521
}
1522
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
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
1639
VOID CLeashView::OnUpdateKillTixOnExit(CCmdUI *pCmdUI)
1640
{
1641
pCmdUI->SetCheck(m_destroyTicketsOnExit);
1642
}
1643
1644
VOID CLeashView::OnUppercaseRealm()
1645
{
1646
m_upperCaseRealm = !m_upperCaseRealm;
1647
1648
pLeash_set_default_uppercaserealm(m_upperCaseRealm);
1649
}
1650
1651
VOID CLeashView::OnUpdateUppercaseRealm(CCmdUI *pCmdUI)
1652
{
1653
// description is now 'allow mixed case', so reverse logic
1654
pCmdUI->SetCheck(!m_upperCaseRealm);
1655
}
1656
1657
VOID CLeashView::ResetTreeNodes()
1658
{
1659
m_hPrincipalState = 0;
1660
m_hKerb5State = 0;
1661
}
1662
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
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
1694
VOID CLeashView::OnUpdateInitTicket(CCmdUI* pCmdUI)
1695
{
1696
if (!CLeashApp::m_hKrb5DLL)
1697
pCmdUI->Enable(FALSE);
1698
else
1699
pCmdUI->Enable(TRUE);
1700
}
1701
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
1718
LRESULT CLeashView::OnGoodbye(WPARAM wParam, LPARAM lParam)
1719
{
1720
m_pDebugWindow->DestroyWindow();
1721
return 0L;
1722
}
1723
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
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
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
1812
VOID CLeashView::OnAppAbout()
1813
{
1814
CLeashAboutBox leashAboutBox;
1815
// To debug loaded dlls:
1816
// leashAboutBox.m_bListModules = TRUE;
1817
leashAboutBox.DoModal();
1818
}
1819
1820
1821
VOID CLeashView::OnInitialUpdate()
1822
{
1823
CListView::OnInitialUpdate();
1824
CLeashApp::m_hProgram = ::FindWindow(_T("LEASH.0WNDCLASS"), NULL);
1825
EnableToolTips();
1826
}
1827
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
1841
VOID CLeashView::OnUpdateDebugMode(CCmdUI* pCmdUI)
1842
{
1843
pCmdUI->Enable(FALSE);
1844
}
1845
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
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
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
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
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
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
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
2179
VOID CLeashView::OnUpdateLowTicketAlarm(CCmdUI* pCmdUI)
2180
{
2181
pCmdUI->SetCheck(m_lowTicketAlarm);
2182
}
2183
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
2194
VOID CLeashView::OnUpdateAutoRenew(CCmdUI* pCmdUI)
2195
{
2196
pCmdUI->SetCheck(m_autoRenewTickets);
2197
}
2198
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
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
2232
VOID CLeashView::OnUpdateProperties(CCmdUI* pCmdUI)
2233
{
2234
if (CLeashApp::m_hKrb5DLL)
2235
pCmdUI->Enable();
2236
else
2237
pCmdUI->Enable(FALSE);
2238
}
2239
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
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
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
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
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 *
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
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
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
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
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
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
2482