|
|
/*--
Copyright (c) 1998 Microsoft Corporation
Module Name:
kerbtray.c
Abstract:
Displays a dialog with list of Kerberos tickets for the current user.
Author:
14-Dec-1998 (jbrezak)
Environment:
User mode only. Requires ANSI C extensions: slash-slash comments, long external names.
Revision History:
--*/
#define UNICODE
#define _UNICODE
#define STRICT
#include <windows.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <shellapi.h>
#include <shlwapi.h>
#include <commctrl.h>
#include <commdlg.h>
#include <time.h>
#include <assert.h>
#include <string.h>
#include <malloc.h>
#define SECURITY_WIN32
#include <security.h>
#include <ntsecapi.h>
#ifndef NO_CRYPTDLL
#include "cryptdll.h"
#endif
#include "kerbtray.h"
#define SEC_SUCCESS(Status) ((Status) >= 0)
#define TSIZE(b) (sizeof(b)/sizeof(TCHAR))
#define IDI_FIRST_CLOCK IDI_0_MIN
#define IDI_LAST_CLOCK IDI_TICKET
#define MAX_ICONS (IDI_LAST_CLOCK - IDI_FIRST_CLOCK + 1)
#define KWIN_UPDATE_PERIOD 60000 // Every 60 seconds update the screen
#define PPAGE_NAMES 0
#define PPAGE_TIMES 1
#define PPAGE_FLAGS 2
#define PPAGE_ETYPES 3
#define C_PAGES 4
#define CX_ICON 20
#define CY_ICON 20
#define TPS (10*1000*1000)
typedef struct { HWND hwndTab; HWND hwndDisplay; RECT rcDisplay; DLGTEMPLATE *apRes[C_PAGES]; PKERB_QUERY_TKT_CACHE_RESPONSE Tickets; } DLGTABHDR;
OSVERSIONINFO osvers; HWND hWnd, hDlgTickets; HINSTANCE hInstance; HANDLE hModule; #define SHORTSTRING 40
#define LONGSTRING 256
TCHAR progname[SHORTSTRING]; ULONG PackageId; HANDLE LogonHandle = NULL; HWND hWndUsers; HIMAGELIST himl; HTREEITEM tgt = NULL;
static HICON kwin_icons[MAX_ICONS]; // Icons depicting time
static INT domain_icon; static LPCTSTR dt_output_dhms = TEXT("%d %s %02d:%02d:%02d"); static LPCTSTR dt_day_plural = TEXT("days"); static LPCTSTR dt_day_singular = TEXT("day"); static LPCTSTR dt_output_donly = TEXT("%d %s"); static LPCTSTR dt_output_hms = TEXT("%d:%02d:%02d"); static LPCTSTR ftime_default_fmt = TEXT("%02d/%02d/%02d %02d:%02d");
#define WM_NOTIFY_ICON (WM_APP+100)
#ifndef NO_CRYPTDLL
typedef NTSTATUS (NTAPI *CDLOCATECSYSTEM)(ULONG dwEtype, PCRYPTO_SYSTEM * ppcsSystem);
CDLOCATECSYSTEM pCDLocateCSystem; #endif
LRESULT CALLBACK MainWndProc(HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK AboutProc(HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK TicketsProc(HWND, UINT, WPARAM, LPARAM); void About(void); void Tickets(void); void PurgeCache(void); void PropsheetDisplay(HWND hDlg); void SelectTicket(HWND hDlg); void FillinTicket(HWND hDlg); LPTSTR etype_string(int enctype); LPTSTR GetStringRes(int);
#ifdef DEBUG
#define DPRINTF(s) dprintf s
int debug = 1;
void dprintf(LPCTSTR fmt, ...) { TCHAR szTemp[512]; va_list ap;
if (!debug) return;
va_start (ap, fmt); wvsprintf(szTemp, fmt, ap); OutputDebugString(szTemp); va_end (ap); } #else
#define DPRINTF(s)
#endif
void ShowMessage(int level, LPCTSTR msg) /*++
Routine Description:
Arguments:
Return Value:
--*/ { if (level) MessageBeep(level); MessageBox(NULL, msg, progname, level | MB_OK | MB_TASKMODAL | MB_SETFOREGROUND); }
void Error(LPCTSTR fmt, ...) /*++
Routine Description:
Arguments:
Return Value:
--*/ { TCHAR szTemp[512];
va_list ap; va_start (ap, fmt); #ifdef UNICODE
_vsnwprintf(szTemp, sizeof(szTemp), fmt, ap); #else
_vsnprintf(szTemp, sizeof(szTemp), fmt, ap); #endif
OutputDebugString(szTemp); ShowMessage(MB_ICONINFORMATION, szTemp); va_end (ap); }
void ErrorExit(LPCTSTR lpszMessage) /*++
Routine Description:
Arguments:
Return Value:
--*/ { MessageBox(hWnd, lpszMessage, TEXT("Error"), MB_OK); ExitProcess(0); }
int GetIconIndex(long dt) /*++
Routine Description:
Arguments:
Return Value:
--*/ { int ixicon;
dt = dt / 60; // convert to minutes
if (dt <= 0) ixicon = IDI_EXPIRED - IDI_FIRST_CLOCK; else if (dt > 60) ixicon = IDI_TICKET - IDI_FIRST_CLOCK; else ixicon = (int)(dt / 5);
return ixicon; }
void SetTray( HWND hwnd, HICON hIcon, LPCTSTR tip ) /*++
Routine Description:
Arguments:
Return Value:
--*/ { static tray_inited = 0; NOTIFYICONDATA tnd;
tnd.cbSize = sizeof(NOTIFYICONDATA); tnd.hWnd = hwnd; tnd.uID = IDI_KDC; tnd.uFlags = NIF_MESSAGE|NIF_ICON|NIF_TIP; tnd.uCallbackMessage = WM_NOTIFY_ICON; tnd.hIcon = hIcon; StrNCpy(tnd.szTip, tip, TSIZE(tnd.szTip)); Shell_NotifyIcon((tray_inited)?NIM_MODIFY:NIM_ADD, &tnd); if (tray_inited == 0) tray_inited++; DestroyIcon(tnd.hIcon); }
void DeleteTray(HWND hwnd) /*++
Routine Description:
Arguments:
Return Value:
--*/ { NOTIFYICONDATA tnd;
tnd.cbSize = sizeof(NOTIFYICONDATA); tnd.hWnd = hwnd; tnd.uID = IDI_KDC; tnd.uFlags = NIF_MESSAGE|NIF_ICON|NIF_TIP; tnd.uCallbackMessage = WM_NOTIFY_ICON; tnd.hIcon = NULL; tnd.szTip[0] = '\0'; Shell_NotifyIcon(NIM_DELETE, &tnd); }
int UpdateTray(HWND hwnd) /*++
Routine Description:
Arguments:
Return Value:
--*/ { HICON hicon; TCHAR buf[SHORTSTRING]; int expired = FALSE; long dt = 0L; NTSTATUS Status, SubStatus; KERB_QUERY_TKT_CACHE_REQUEST CacheRequest; PKERB_RETRIEVE_TKT_RESPONSE TicketEntry = NULL; PKERB_EXTERNAL_TICKET Ticket; ULONG ResponseSize; FILETIME CurrentFileTime; LARGE_INTEGER Quad;
CacheRequest.MessageType = KerbRetrieveTicketMessage; CacheRequest.LogonId.LowPart = 0; CacheRequest.LogonId.HighPart = 0;
StrNCpy(buf, progname, TSIZE(buf));
Status = LsaCallAuthenticationPackage(LogonHandle, PackageId, &CacheRequest, sizeof(CacheRequest), (PVOID *) &TicketEntry, &ResponseSize, &SubStatus); if (!SEC_SUCCESS(Status) || !SEC_SUCCESS(SubStatus)) { hicon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_KDC)); StrCatBuff(buf, GetStringRes(IDS_NO_CREDS), TSIZE(buf)); } else { Ticket = &(TicketEntry->Ticket);
GetSystemTimeAsFileTime(&CurrentFileTime);
Quad.LowPart = CurrentFileTime.dwLowDateTime; Quad.HighPart = CurrentFileTime.dwHighDateTime;
dt = (long)((Ticket->EndTime.QuadPart - Quad.QuadPart) / TPS);
LsaFreeReturnBuffer(TicketEntry);
hicon = kwin_icons[GetIconIndex(dt)];
StrCatBuff(buf, TEXT(" - "), TSIZE(buf));
if (dt <= 0) { StrCatBuff(buf, GetStringRes(IDS_EXPIRED), TSIZE(buf)); expired = TRUE; } else { int days, hours, minutes, seconds; DWORD tt; TCHAR buf2[SHORTSTRING];
days = (int) (dt / (24*3600l)); tt = dt % (24*3600l); hours = (int) (tt / 3600); tt %= 3600; minutes = (int) (tt / 60); seconds = (int) (tt % 60);
if (days) { if (hours || minutes || seconds) { _snwprintf(buf2, TSIZE(buf2), dt_output_dhms, days, (days > 1) ? dt_day_plural : dt_day_singular, hours, minutes, seconds); } else { _snwprintf(buf2, TSIZE(buf2), dt_output_donly, days, (days > 1) ? dt_day_plural : dt_day_singular); } } else { _snwprintf(buf2, TSIZE(buf2), dt_output_hms, hours, minutes, seconds); } _snwprintf(buf, TSIZE(buf), TEXT("%s %s"), progname, buf2); } } SetTray(hwnd, hicon, buf); return(expired); }
BOOL InitializeApp( HANDLE hInstance, int nCmdShow ) /*++
Routine Description:
Arguments:
Return Value:
--*/ { LSA_STRING Name; NTSTATUS Status; WNDCLASSEX wc; HWND hwnd; int i;
// Check for an existing instance
hwnd = FindWindow(TEXT("MainWindowClass"), TEXT("KerbTray")); if (hwnd) { // Popup the tickets dialog, if one found
// Run only one instance of kerbtray
SendMessage(hwnd, WM_NOTIFY_ICON, 0, WM_LBUTTONDBLCLK); ExitProcess(0); }
hModule = GetModuleHandle(NULL); InitCommonControls();
LoadString(hInstance, IDS_KRB5_NAME, progname, TSIZE(progname));
Status = LsaConnectUntrusted(&LogonHandle); if (!SEC_SUCCESS(Status)) { Error(TEXT("Failed to register as a logon process: 0x%x"), Status); return FALSE; }
Name.Buffer = MICROSOFT_KERBEROS_NAME_A; Name.Length = (USHORT) strlen(Name.Buffer); Name.MaximumLength = Name.Length + 1;
Status = LsaLookupAuthenticationPackage( LogonHandle, &Name, &PackageId ); if (!SEC_SUCCESS(Status)){ printf("Failed to lookup package %Z: 0x%x\n",&Name, Status); return FALSE; }
// Create the image list.
if ((himl = ImageList_Create(CX_ICON, CY_ICON, ILC_COLOR, MAX_ICONS, 0)) == NULL) return FALSE;
ImageList_SetBkColor(himl, CLR_NONE);
for (i = IDI_FIRST_CLOCK; i <= IDI_LAST_CLOCK; i++) { #if 1
kwin_icons[i - IDI_FIRST_CLOCK] = LoadIcon(hInstance, MAKEINTRESOURCE(i)); #else
kwin_icons[i - IDI_FIRST_CLOCK] = LoadImage(hInstance, MAKEINTRESOURCE(i), IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR|LR_DEFAULTSIZE|LR_LOADTRANSPARENT|LR_LOADMAP3DCOLORS); #endif
(void) ImageList_AddIcon(himl, kwin_icons[i - IDI_FIRST_CLOCK]); }
#if 1
domain_icon = ImageList_AddIcon(himl, LoadIcon(hInstance, MAKEINTRESOURCE(IDI_DOMAIN))); #else
domain_icon = ImageList_AddIcon(himl, LoadImage(hInstance, MAKEINTRESOURCE(IDI_DOMAIN), IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR|LR_DEFAULTSIZE|LR_LOADTRANSPARENT|LR_LOADMAP3DCOLORS)); #endif
// Register a window class for the main window.
wc.cbSize = sizeof(WNDCLASSEX); wc.style = CS_HREDRAW|CS_VREDRAW; wc.lpfnWndProc = MainWndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = LoadIcon(hModule, MAKEINTRESOURCE(IDI_EXPIRED)); wc.hIconSm = LoadIcon(hModule, MAKEINTRESOURCE(IDI_EXPIRED)); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wc.lpszMenuName = 0; wc.lpszClassName = TEXT("MainWindowClass");
if (! RegisterClassEx(&wc)) { Error(TEXT("RegisterClassEx failed")); return FALSE; }
/* Create the main window. */ hWnd = CreateWindowEx(WS_EX_APPWINDOW, TEXT("MainWindowClass"), TEXT("KerbTray"), WS_OVERLAPPEDWINDOW, 0, 0, 5, 5, NULL, NULL, hModule, NULL); if (hWnd == NULL) { Error(TEXT("CreateWindowEx failed")); return FALSE; }
ShowWindow(hWnd, SW_HIDE);
return TRUE; }
int WINAPI WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpszCmdLn, int nShowCmd ) /*++
Routine Description:
Arguments:
Return Value:
--*/ { MSG msg; HANDLE hAccelTable, hCryptDll;
hInstance = hInst; hModule = GetModuleHandle(NULL);
osvers.dwOSVersionInfoSize = sizeof(osvers); GetVersionEx(&osvers);
#ifndef NO_CRYPTDLL
hCryptDll = LoadLibrary(TEXT("CRYPTDLL.DLL")); if (!hCryptDll) ErrorExit(TEXT("Unable to load cryptdll.dll"));
pCDLocateCSystem = (CDLOCATECSYSTEM) GetProcAddress(hCryptDll, "CDLocateCSystem"); if (!pCDLocateCSystem) ErrorExit(TEXT("Unable to link cryptdll.dll::CDLocateCSystem")); #endif
if (! InitializeApp(hInst, nShowCmd)) ErrorExit(TEXT("InitializeApp failure"));
hAccelTable = LoadAccelerators(hInst, TEXT("KerbTray"));
while (GetMessage(&msg, NULL, 0, 0)) { if (!IsDialogMessage(hDlgTickets, &msg)) { if (!TranslateAccelerator (msg.hwnd, hAccelTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } } return 1;
UNREFERENCED_PARAMETER(hPrevInst); UNREFERENCED_PARAMETER(lpszCmdLn); }
LRESULT CALLBACK MainWndProc(HWND hwnd, UINT uiMessage, WPARAM wParam, LPARAM lParam) /*++
Routine Description:
Arguments:
Return Value:
--*/ { POINT pos; static HMENU hPopupMenu;
switch (uiMessage) {
case WM_NOTIFY_ICON: switch (lParam) {
case WM_LBUTTONDBLCLK: Tickets(); return 0L;
case WM_RBUTTONDOWN: if (hPopupMenu) { if (GetCursorPos(&pos)) { if (TrackPopupMenu(hPopupMenu, TPM_RIGHTALIGN|TPM_LEFTBUTTON, pos.x, pos.y, 0, hwnd, NULL) == 0) Error(TEXT("TrackPopupMenuFailed: 0x%x"), GetLastError()); } } return 0L; } break;
/* Create a client windows */
case WM_CREATE: hPopupMenu = LoadMenu(hInstance, MAKEINTRESOURCE(IDR_MENU)); if (!hPopupMenu) Error(TEXT("LoadMenu failed %d"), GetLastError()); hPopupMenu = GetSubMenu(hPopupMenu, 0); if (!hPopupMenu) Error(TEXT("LoadMenu failed %d"), GetLastError());
(void) UpdateTray(hwnd);
/* Start timer for watching the TGT */ if (!SetTimer(hwnd, 1, KWIN_UPDATE_PERIOD, NULL)) { ErrorExit(TEXT("SetTimer failed")); } return 0L;
case WM_TIMER: (void) UpdateTray(hwnd); return(0L);
case WM_ENDSESSION: return(0L);
/*
* Close the main window. First set fKillAll to TRUE to * terminate all threads. Then wait for the threads to exit * before passing a close message to a default handler. If you * don't wait for threads to terminate, process terminates * with no chance for thread cleanup. */
case WM_CLOSE: exit:; { DeleteTray(hWnd); KillTimer(hWnd, 1); PostQuitMessage(0); return 0L; }
/* Terminate the process. */
case WM_DESTROY: PostQuitMessage(0); return 0L;
/* Handle the menu commands. */
case WM_COMMAND: switch (LOWORD(wParam)) {
case ID_ABOUT: About(); return 0L;
case ID_TICKETS: Tickets(); return 0L;
case ID_PURGE: PurgeCache(); return 0L;
case ID_EXIT: goto exit; } } return DefWindowProc(hwnd, uiMessage, wParam, lParam); }
LPTSTR GetStringRes(int id) /*++
Routine Description:
Arguments:
Return Value:
--*/ { static TCHAR buffer[MAX_PATH];
buffer[0] = 0; LoadString (GetModuleHandle (NULL), id, buffer, MAX_PATH); return buffer; }
LRESULT CALLBACK AboutProc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam ) /*++
Routine Description:
Arguments:
Return Value:
--*/ { static HFONT hfontDlg; // Font for dialog text
DWORD dwVerInfoSize; // Size of version information block
LPTSTR lpVersion; // String pointer to 'version' text
DWORD dwVerHnd = 0; // An 'ignored' parameter, always '0'
UINT uVersionLen; DWORD wRootLen; BOOL bRetCode; int i; TCHAR szFullPath[LONGSTRING]; TCHAR szResult[LONGSTRING]; TCHAR szGetName[LONGSTRING]; TCHAR szVersion[SHORTSTRING]; DWORD dwResult; int resmap[6] = { IDC_COMPANY, IDC_FILEDESC, IDC_PRODVER, IDC_COPYRIGHT, IDC_OSVERSION, };
switch (message) { case WM_INITDIALOG: ShowWindow(hDlg, SW_HIDE); hfontDlg = CreateFont(14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, VARIABLE_PITCH | FF_SWISS, TEXT("")); GetModuleFileName(hInstance, szFullPath, TSIZE(szFullPath));
/* Now lets dive in and pull out the version information: */ dwVerInfoSize = GetFileVersionInfoSize(szFullPath, &dwVerHnd); if (dwVerInfoSize) { LPSTR lpstrVffInfo; HANDLE hMem;
hMem = GlobalAlloc(GMEM_MOVEABLE, dwVerInfoSize); if (!hMem) { ErrorExit(TEXT("Unable to allocate memory")); } lpstrVffInfo = GlobalLock(hMem); if (!lpstrVffInfo) { ErrorExit(TEXT("Unable to lock memory")); } GetFileVersionInfo(szFullPath, dwVerHnd, dwVerInfoSize, lpstrVffInfo); /*
* The below 'hex' value looks a little confusing, but * essentially what it is, is the hexidecimal representation * of a couple different values that represent the language * and character set that we are wanting string values for. * 040904E4 is a very common one, because it means: * US English, Windows MultiLingual characterset * Or to pull it all apart: * 04------ = SUBLANG_ENGLISH_USA * --09---- = LANG_ENGLISH * ----04E4 = 1252 = Codepage for Windows:Multilingual */
StrNCpy(szGetName, GetStringRes(IDS_VER_INFO_LANG), TSIZE(szGetName));
wRootLen = lstrlen(szGetName); /* Save this position */
/* Set the title of the dialog: */ StrCatBuff(szGetName, TEXT("ProductName"), TSIZE(szGetName)); bRetCode = VerQueryValue((LPVOID)lpstrVffInfo, (LPTSTR)szGetName, (LPVOID)&lpVersion, (UINT *)&uVersionLen); StrNCpy(szResult, TEXT("About "), TSIZE(szResult)); StrCatBuff(szResult, lpVersion, TSIZE(szResult)); SetWindowText(hDlg, szResult);
/* Walk through the dialog items that we want to replace: */ for (i = 0; i <= 6; i++) { GetDlgItemText(hDlg, resmap[i], szResult, TSIZE(szResult)); szGetName[wRootLen] = TEXT('\0'); StrCatBuff(szGetName, szResult, TSIZE(szGetName)); uVersionLen = 0; lpVersion = NULL; bRetCode = VerQueryValue((LPVOID)lpstrVffInfo, (LPTSTR)szGetName, (LPVOID)&lpVersion, (UINT *)&uVersionLen);
if ( bRetCode && uVersionLen && lpVersion) { /* Replace dialog item text with version info */ StrNCpy(szResult, lpVersion, TSIZE(szResult)); SetDlgItemText(hDlg, resmap[i], szResult); } else { dwResult = GetLastError(); _snwprintf(szResult, TSIZE(szResult), TEXT("Error %lu"), dwResult); SetDlgItemText (hDlg, resmap[i], szResult); } SendMessage(GetDlgItem(hDlg, resmap[i]), WM_SETFONT, (WPARAM)hfontDlg, TRUE); } GlobalUnlock(hMem); GlobalFree(hMem);
} else { /* No version information available. */ }
SendMessage(GetDlgItem (hDlg, IDC_LABEL), WM_SETFONT, (WPARAM)hfontDlg,(LPARAM)TRUE);
_snwprintf(szVersion, TSIZE(szVersion), TEXT("Microsoft Windows %u.%u (Build: %u)"), osvers.dwMajorVersion, osvers.dwMinorVersion, osvers.dwBuildNumber);
SetWindowText(GetDlgItem(hDlg, IDC_OSVERSION), szVersion); ShowWindow(hDlg, SW_SHOW); return TRUE;
case WM_COMMAND: switch (LOWORD(wParam)) { case IDOK: case IDCANCEL: EndDialog(hDlg, 0); break; } } return FALSE; }
void About(void) /*++
Routine Description:
Arguments:
Return Value:
--*/ { DialogBox(hInstance, MAKEINTRESOURCE(IDD_ABOUT), hWnd, AboutProc); }
#define CheckDlgButtonFlag(b, f) \
CheckDlgButton(hDlg, b, (flags & f)?BST_CHECKED:BST_UNCHECKED)
VOID ShowFlags(HWND hDlg, ULONG flags) /*++
Routine Description:
Arguments:
Return Value:
--*/ { CheckDlgButtonFlag(IDC_FORWARDABLE, KERB_TICKET_FLAGS_forwardable); CheckDlgButtonFlag(IDC_FORWARDED, KERB_TICKET_FLAGS_forwarded); CheckDlgButtonFlag(IDC_PROXIABLE, KERB_TICKET_FLAGS_proxiable); CheckDlgButtonFlag(IDC_PROXY, KERB_TICKET_FLAGS_proxy); CheckDlgButtonFlag(IDC_MAY_POSTDATE, KERB_TICKET_FLAGS_may_postdate); CheckDlgButtonFlag(IDC_POSTDATED, KERB_TICKET_FLAGS_postdated); CheckDlgButtonFlag(IDC_INVALID, KERB_TICKET_FLAGS_invalid); CheckDlgButtonFlag(IDC_RENEWABLE, KERB_TICKET_FLAGS_renewable); CheckDlgButtonFlag(IDC_INITIAL, KERB_TICKET_FLAGS_initial); CheckDlgButtonFlag(IDC_HWAUTH, KERB_TICKET_FLAGS_hw_authent); CheckDlgButtonFlag(IDC_PREAUTH, KERB_TICKET_FLAGS_pre_authent); CheckDlgButtonFlag(IDC_OK_AS_DELEGATE, KERB_TICKET_FLAGS_ok_as_delegate); }
LPTSTR etype_string( int enctype ) /*++
Routine Description:
Arguments:
Return Value:
--*/ { #ifndef NO_CRYPTDLL
static PCRYPTO_SYSTEM pcsSystem; static TCHAR buf[12];
if (pCDLocateCSystem(enctype, &pcsSystem) == S_OK) return pcsSystem->Name; else { _snwprintf(buf, TSIZE(buf), TEXT("etype %d"), enctype); return buf; } #else
static TCHAR buf[12];
switch (enctype) { case KERB_ETYPE_NULL: return TEXT("NULL"); break; case KERB_ETYPE_DES_CBC_CRC: return TEXT("Kerberos DES-CBC-CRC"); break; case KERB_ETYPE_DES_CBC_MD5: return TEXT("Kerberos DES-CBC-MD5"); break; case KERB_ETYPE_RC4_MD4: return TEXT("RSADSI RC4-MD4"); break; case KERB_ETYPE_RC4_PLAIN2: return TEXT("RSADSI RC4-PLAIN"); break; case KERB_ETYPE_RC4_LM: return TEXT("RSADSI RC4-LM"); break; case KERB_ETYPE_DES_PLAIN: return TEXT("Kerberos DES-Plain"); break; #ifdef KERB_ETYPE_RC4_HMAC
case KERB_ETYPE_RC4_HMAC: return TEXT("RSADSI RC4-HMAC"); break; #endif
case KERB_ETYPE_RC4_PLAIN: return TEXT("RSADSI RC4"); break; #ifdef KERB_ETYPE_RC4_HMAC_EXP
case KERB_ETYPE_RC4_HMAC_EXP: return TEXT("RSADSI RC4-HMAC(Export)"); break; #endif
case KERB_ETYPE_RC4_PLAIN_EXP: return TEXT("RSADSI RC4(Export)"); break; case KERB_ETYPE_DES_CBC_MD5_EXP: return TEXT("Kerberos DES-CBC-MD5-EXP(Export)"); break; case KERB_ETYPE_DES_PLAIN_EXP: return TEXT("Kerberos DES-Plain(Export)"); break; default: _snwprintf(buf, TSIZE(buf), TEXT("etype %d"), enctype); return buf; break; } #endif
}
LPTSTR timestring(TimeStamp ConvertTime) /*++
Routine Description:
Arguments:
Return Value:
--*/ { SYSTEMTIME SystemTime; FILETIME LocalFileTime; static TCHAR buf[LONGSTRING];
if (ConvertTime.HighPart == 0x7FFFFFFF && ConvertTime.LowPart == 0xFFFFFFFF) { return(GetStringRes(IDS_INFINITE)); }
if (FileTimeToLocalFileTime( (PFILETIME) &ConvertTime, &LocalFileTime) && FileTimeToSystemTime( &LocalFileTime, &SystemTime)) { _snwprintf(buf, TSIZE(buf), ftime_default_fmt, SystemTime.wMonth, SystemTime.wDay, SystemTime.wYear, SystemTime.wHour, SystemTime.wMinute); } else return(GetStringRes(IDS_INVALID));
return(buf); }
// DoLockDlgRes - loads and locks a dialog template resource.
// Returns the address of the locked resource.
// lpszResName - name of the resource
DLGTEMPLATE * WINAPI DoLockDlgRes(LPCTSTR lpszResName) /*++
Routine Description:
Arguments:
Return Value:
--*/ { HRSRC hrsrc; HGLOBAL hglb; DLGTEMPLATE *pDlg;
hrsrc = FindResource(NULL, lpszResName, RT_DIALOG); if (!hrsrc) { Error(TEXT("Unable to locate resource '%s'"), lpszResName); ExitProcess(0); }
hglb = LoadResource(hInstance, hrsrc); if (!hglb) { Error(TEXT("Unable to load resource '%s'"), lpszResName); ExitProcess(0); }
pDlg = (DLGTEMPLATE *)LockResource(hglb); if (!pDlg) { Error(TEXT("Unable to lock resource '%s'"), lpszResName); ExitProcess(0); }
return pDlg; }
void PurgeCache(void) /*++
Routine Description:
Arguments:
Return Value:
--*/ { KERB_PURGE_TKT_CACHE_REQUEST CacheRequest; PVOID Response; ULONG ResponseSize; NTSTATUS Status, SubStatus;
memset(&CacheRequest, 0, sizeof(CacheRequest));
CacheRequest.MessageType = KerbPurgeTicketCacheMessage;
Status = LsaCallAuthenticationPackage(LogonHandle, PackageId, &CacheRequest, sizeof(CacheRequest), &Response, &ResponseSize, &SubStatus);
if (SEC_SUCCESS(Status) && SEC_SUCCESS(SubStatus)) { ShowMessage(MB_ICONINFORMATION, GetStringRes(IDS_PURGED)); } else { Error(TEXT("Failed to purge ticket cache - 0x%x"), Status); }
if (Response != NULL) { LsaFreeReturnBuffer(Response); } }
HTREEITEM AddOneItem( HTREEITEM hParent, LPTSTR szText, HTREEITEM hInsAfter, int iImage, HWND hwndTree, LPARAM lParam ) { HTREEITEM hItem; TV_ITEM tvI; TV_INSERTSTRUCT tvIns;
tvI.mask = TVIF_TEXT|TVIF_IMAGE|TVIF_SELECTEDIMAGE|TVIF_PARAM; tvI.pszText = szText; tvI.cchTextMax = lstrlen(szText); tvI.lParam = lParam; tvI.iImage = iImage; tvI.iSelectedImage = iImage;
tvIns.item = tvI; tvIns.hInsertAfter = hInsAfter; tvIns.hParent = hParent;
hItem = TreeView_InsertItem(hwndTree, &tvIns); return(hItem); }
HTREEITEM FindDomainByName(LPTSTR name) { HTREEITEM dom = NULL; TVITEM item; TCHAR buf[LONGSTRING];
dom = TreeView_GetRoot(hWndUsers); if (!dom) return NULL;
do {
item.mask = TVIF_TEXT; item.pszText = buf; item.cchTextMax = sizeof(buf); item.hItem = dom; if (TreeView_GetItem(hWndUsers, &item)) { if (wcscmp(name, buf) == 0) { return dom; } } } while (dom = TreeView_GetNextSibling(hWndUsers, dom));
return NULL; }
HTREEITEM AddDomain( LPTSTR name ) { HTREEITEM hItem;
if (!(hItem = FindDomainByName(name))) { hItem = AddOneItem(NULL, _wcsdup(name), TVI_ROOT, domain_icon, hWndUsers, 0); } return(hItem); }
HTREEITEM FindTicketByName(HTREEITEM lip, LPTSTR name) { HTREEITEM tick = NULL; TVITEM item; TCHAR buf[LONGSTRING];
tick = TreeView_GetChild(hWndUsers, lip); if (!tick) return NULL;
do { item.mask = TVIF_TEXT; item.pszText = buf; item.cchTextMax = sizeof(buf); item.hItem = tick; if (TreeView_GetItem(hWndUsers, &item)) { if (wcscmp(name, buf) == 0) { return tick; } } } while (tick = TreeView_GetNextSibling(hWndUsers, tick));
return NULL; }
HTREEITEM AddTicket( HTREEITEM dom, LPTSTR name, int idx, LPARAM lParam ) { HTREEITEM hItem;
hItem = AddOneItem(dom, name, TVI_SORT, idx, hWndUsers, lParam); TreeView_Expand(hWndUsers, dom, TVE_EXPAND); return(hItem); }
void ShowTicket( HWND hDlg, PKERB_TICKET_CACHE_INFO tix, int i ) /*++
Routine Description:
Arguments:
Return Value:
--*/ { TCHAR sname[LONGSTRING]; HTREEITEM dom, tick; FILETIME CurrentFileTime; LARGE_INTEGER Quad; long dt = 0L;
memset(sname, 0, sizeof(sname));
swprintf(sname, TEXT("%wZ"), &tix->RealmName); dom = AddDomain(sname); swprintf(sname, TEXT("%wZ"), &tix->ServerName);
GetSystemTimeAsFileTime(&CurrentFileTime);
Quad.LowPart = CurrentFileTime.dwLowDateTime; Quad.HighPart = CurrentFileTime.dwHighDateTime;
dt = (long)((tix->EndTime.QuadPart - Quad.QuadPart) / TPS);
// 14
tick = AddTicket(dom, sname, GetIconIndex(dt), (LPARAM)tix); if (tix->TicketFlags & KERB_TICKET_FLAGS_initial) tgt = tick; }
void DisplayCreds( HWND hDlg ) /*++
Routine Description:
Arguments:
Return Value:
--*/ { KERB_QUERY_TKT_CACHE_REQUEST CacheRequest; PKERB_RETRIEVE_TKT_RESPONSE TicketEntry = NULL; PKERB_EXTERNAL_TICKET Ticket; NTSTATUS Status, SubStatus; ULONG ResponseSize; DWORD i; DLGTABHDR *pHdr; TCITEM tie; DWORD dwDlgBase = GetDialogBaseUnits(); int cxMargin = LOWORD(dwDlgBase) / 4; int cyMargin = HIWORD(dwDlgBase) / 8; RECT rcTab;
pHdr = (DLGTABHDR *) LocalAlloc(LPTR|LMEM_ZEROINIT, sizeof(DLGTABHDR)); if (!pHdr) ErrorExit(TEXT("Unable to allocate memory"));
// Save a pointer to the DLGHDR structure.
SetWindowLongPtr(hDlg, GWLP_USERDATA, (LONG_PTR)pHdr);
pHdr->hwndTab = GetDlgItem(hDlg, IDC_TAB_ATTRIBUTES);
hWndUsers = GetDlgItem(hDlg, IDC_TICKETS);
// Associate the image list with the tree view control.
//TreeView_SetImageList(hWndUsers, himl, TVSIL_NORMAL);
CacheRequest.MessageType = KerbRetrieveTicketMessage; CacheRequest.LogonId.LowPart = 0; CacheRequest.LogonId.HighPart = 0;
Status = LsaCallAuthenticationPackage(LogonHandle, PackageId, &CacheRequest, sizeof(CacheRequest), (PVOID *) &TicketEntry, &ResponseSize, &SubStatus);
if (SEC_SUCCESS(Status) && SEC_SUCCESS(SubStatus)) { static TCHAR princ[LONGSTRING];
Ticket = &(TicketEntry->Ticket); memset(princ, 0, sizeof(princ)); swprintf(princ, TEXT("%wZ@%wZ"), &Ticket->ClientName->Names[0], &Ticket->DomainName); SetDlgItemText(hDlg, IDC_PRINC_LABEL, princ); } else { SetDlgItemText(hDlg, IDC_PRINC_LABEL, GetStringRes(IDS_NO_NET_CREDS)); SetDlgItemText(hDlg, IDC_PRINC_START, TEXT(""));
if (TicketEntry) LsaFreeReturnBuffer(TicketEntry);
return; }
// Add a tab for each of the three child dialog boxes.
tie.mask = TCIF_TEXT | TCIF_IMAGE; tie.iImage = -1; tie.pszText = GetStringRes(IDS_LNAMES); TabCtrl_InsertItem(pHdr->hwndTab, PPAGE_NAMES, &tie); tie.pszText = GetStringRes(IDS_LTIMES); TabCtrl_InsertItem(pHdr->hwndTab, PPAGE_TIMES, &tie); tie.pszText = GetStringRes(IDS_LFLAGS); TabCtrl_InsertItem(pHdr->hwndTab, PPAGE_FLAGS, &tie); tie.pszText = GetStringRes(IDS_LENCTYPE); TabCtrl_InsertItem(pHdr->hwndTab, PPAGE_ETYPES, &tie);
// Lock the resources for the three child dialog boxes.
pHdr->apRes[PPAGE_NAMES] = DoLockDlgRes(MAKEINTRESOURCE(IDD_PROP_NAMES)); pHdr->apRes[PPAGE_TIMES] = DoLockDlgRes(MAKEINTRESOURCE(IDD_PROP_TIMES)); pHdr->apRes[PPAGE_FLAGS] = DoLockDlgRes(MAKEINTRESOURCE(IDD_PROP_TKT_FLAGS)); pHdr->apRes[PPAGE_ETYPES] = DoLockDlgRes(MAKEINTRESOURCE(IDD_PROP_ENCTYPES));
// Determine the bounding rectangle for all child dialog boxes.
SetRectEmpty(&rcTab); for (i = 0; i < C_PAGES; i++) { if (pHdr->apRes[i]->cx > rcTab.right) rcTab.right = pHdr->apRes[i]->cx; if (pHdr->apRes[i]->cy > rcTab.bottom) rcTab.bottom = pHdr->apRes[i]->cy; } rcTab.right = rcTab.right * LOWORD(dwDlgBase) / 4; rcTab.bottom = rcTab.bottom * HIWORD(dwDlgBase) / 8;
// Calculate how large to make the tab control, so
// the display area can accommodate all the child dialog boxes.
TabCtrl_AdjustRect(pHdr->hwndTab, TRUE, &rcTab); OffsetRect(&rcTab, cxMargin - rcTab.left, cyMargin - rcTab.top);
// Calculate the display rectangle.
CopyRect(&pHdr->rcDisplay, &rcTab); TabCtrl_AdjustRect(pHdr->hwndTab, FALSE, &pHdr->rcDisplay);
CacheRequest.MessageType = KerbQueryTicketCacheMessage; CacheRequest.LogonId.LowPart = 0; CacheRequest.LogonId.HighPart = 0;
Status = LsaCallAuthenticationPackage(LogonHandle, PackageId, &CacheRequest, sizeof(CacheRequest), (PVOID *) &pHdr->Tickets, &ResponseSize, &SubStatus); if (SEC_SUCCESS(Status) && SEC_SUCCESS(SubStatus)) { for (i = 0; i < pHdr->Tickets->CountOfTickets; i++) { ShowTicket(hDlg, &pHdr->Tickets->Tickets[i], i); } LsaFreeReturnBuffer(TicketEntry); } if (tgt) TreeView_SelectItem(hWndUsers, tgt); PropsheetDisplay(hDlg); SelectTicket(hDlg); }
LRESULT CALLBACK PropSheetProc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam ) /*++
Routine Description:
Arguments:
Return Value:
--*/ { DLGTABHDR *pHdr; HWND hwndParent = GetParent(hDlg);
hwndParent = GetParent(hwndParent); pHdr = (DLGTABHDR *) GetWindowLongPtr(hwndParent, GWLP_USERDATA);
switch (message) { case WM_INITDIALOG: SetWindowPos(hDlg, HWND_TOP, pHdr->rcDisplay.left, pHdr->rcDisplay.top, 0, 0, SWP_NOSIZE); return TRUE; }
return FALSE; }
void PropsheetDisplay(HWND hDlg) /*++
Routine Description:
Arguments:
Return Value:
--*/ { DLGTABHDR *pHdr = (DLGTABHDR *) GetWindowLongPtr(hDlg, GWLP_USERDATA); int iSel = TabCtrl_GetCurSel(pHdr->hwndTab);
// Destroy the current child dialog box, if any.
if (pHdr->hwndDisplay != NULL) DestroyWindow(pHdr->hwndDisplay);
// Create the new child dialog box.
pHdr->hwndDisplay = CreateDialogIndirect(hInstance, pHdr->apRes[iSel], pHdr->hwndTab, PropSheetProc);
}
INT UnparseExternalName( PKERB_EXTERNAL_NAME iName, PUNICODE_STRING *np ) { int len, cnt; PUNICODE_STRING name;
for (len = 0, cnt = 0; cnt < iName->NameCount; cnt++) { len += iName->Names[cnt].Length; if ((cnt + 1) < iName->NameCount) len += 2; }
name = malloc(sizeof(UNICODE_STRING)); if (!name) return -1;
name->Buffer = malloc(len + 2); if (!name->Buffer) { free(name); return -1; } name->Length = 0; name->MaximumLength = len+2; memset(name->Buffer, 0, len + 2);
for (cnt = 0; cnt < iName->NameCount; cnt++) { wcsncat(name->Buffer, iName->Names[cnt].Buffer, iName->Names[cnt].Length/2); name->Length += iName->Names[cnt].Length; if ((cnt + 1) < iName->NameCount) { wcsncat(name->Buffer, L"/", 1); name->Length += 2; } } *np = name;
return 0; }
VOID FreeUnicodeString( PUNICODE_STRING ustr ) { if (ustr) { free(ustr->Buffer); free(ustr); } }
void SelectTicket(HWND hDlg) /*++
Routine Description:
Arguments:
Return Value:
--*/ { DLGTABHDR *pHdr = (DLGTABHDR *) GetWindowLongPtr(hDlg, GWLP_USERDATA); int iSel = TabCtrl_GetCurSel(pHdr->hwndTab); HTREEITEM hItem = TreeView_GetSelection(hWndUsers); TVITEM item; TCHAR sname[LONGSTRING]; PKERB_TICKET_CACHE_INFO tix; FILETIME CurrentFileTime; LARGE_INTEGER Quad; long dt = 0L;
if (!hItem) return;
item.hItem = hItem; item.mask = TVIF_PARAM; item.lParam = 0;
TreeView_GetItem(hWndUsers, &item);
if (!item.lParam) { SetDlgItemText(hDlg, IDC_SERVICE_PRINC_LABEL, GetStringRes(IDS_DOMAIN)); SetDlgItemText(hDlg, IDC_SERVICE_PRINC, TEXT("")); FillinTicket(hDlg); return; }
SetDlgItemText(hDlg, IDC_SERVICE_PRINC_LABEL, GetStringRes(IDS_SERVICE_PRINCIPAL));
tix = (PKERB_TICKET_CACHE_INFO)item.lParam;
GetSystemTimeAsFileTime(&CurrentFileTime);
Quad.LowPart = CurrentFileTime.dwLowDateTime; Quad.HighPart = CurrentFileTime.dwHighDateTime;
dt = (long)((tix->EndTime.QuadPart - Quad.QuadPart) / TPS);
if (dt > 0) { swprintf(sname, TEXT("%wZ@%wZ"), &tix->ServerName, &tix->RealmName);
SetDlgItemText(hDlg, IDC_SERVICE_PRINC, sname); } else { SetDlgItemText(hDlg, IDC_SERVICE_PRINC_LABEL, GetStringRes(IDS_EXPIRED)); SetDlgItemText(hDlg, IDC_SERVICE_PRINC, TEXT("")); }
FillinTicket(hDlg); }
void FillinTicket(HWND hDlg) /*++
Routine Description:
Arguments:
Return Value:
--*/ { PKERB_TICKET_CACHE_INFO tix; DLGTABHDR *pHdr = (DLGTABHDR *) GetWindowLongPtr(hDlg, GWLP_USERDATA); int iSel = TabCtrl_GetCurSel(pHdr->hwndTab); HTREEITEM hItem = TreeView_GetSelection(hWndUsers); TVITEM item; PKERB_RETRIEVE_TKT_REQUEST TicketRequest; ULONG ResponseSize; NTSTATUS Status, SubStatus; PKERB_EXTERNAL_TICKET ticket; int sz; TCHAR sname[LONGSTRING]; PUNICODE_STRING svc;
if (!hItem) return;
item.hItem = hItem; item.mask = TVIF_PARAM; item.lParam = 0;
TreeView_GetItem(hWndUsers, &item);
switch(iSel) { case PPAGE_NAMES: SetDlgItemText(pHdr->hwndDisplay, IDC_SERVICENAME, TEXT("")); SetDlgItemText(pHdr->hwndDisplay, IDC_TARGETNAME, TEXT("")); SetDlgItemText(pHdr->hwndDisplay, IDC_CLIENTNAME, TEXT("")); break;
case PPAGE_TIMES: SetDlgItemText(pHdr->hwndDisplay, IDC_STARTTIME, TEXT("")); SetDlgItemText(pHdr->hwndDisplay, IDC_ENDTIME, TEXT("")); SetDlgItemText(pHdr->hwndDisplay, IDC_RENEW_UNTIL, TEXT("")); break;
case PPAGE_ETYPES: SetDlgItemText(pHdr->hwndDisplay, IDC_TKT_ENCTYPE, TEXT("")); SetDlgItemText(pHdr->hwndDisplay, IDC_KEY_ENCTYPE, TEXT("")); break;
case PPAGE_FLAGS: ShowFlags(pHdr->hwndDisplay, 0); break; }
if (!item.lParam) { return; }
tix = (PKERB_TICKET_CACHE_INFO)item.lParam;
swprintf(sname, TEXT("%wZ@%wZ"), &tix->ServerName, &tix->RealmName);
sz = sizeof(WCHAR)*(wcslen(sname) + 1); TicketRequest = LocalAlloc(LMEM_ZEROINIT, sizeof(KERB_RETRIEVE_TKT_REQUEST) + sz);
if (!TicketRequest) ErrorExit(TEXT("Unable to allocate memory"));
TicketRequest->MessageType = KerbRetrieveEncodedTicketMessage; TicketRequest->LogonId.LowPart = 0; TicketRequest->LogonId.HighPart = 0; TicketRequest->TargetName.Length = wcslen(sname) * sizeof(WCHAR); TicketRequest->TargetName.MaximumLength = TicketRequest->TargetName.Length + sizeof(WCHAR); TicketRequest->TargetName.Buffer = (LPWSTR) (TicketRequest + 1); wcsncpy(TicketRequest->TargetName.Buffer, sname, wcslen(sname)); TicketRequest->CacheOptions = KERB_RETRIEVE_TICKET_USE_CACHE_ONLY; TicketRequest->EncryptionType = 0L; TicketRequest->TicketFlags = 0L;
Status = LsaCallAuthenticationPackage(LogonHandle, PackageId, TicketRequest, (sizeof(KERB_RETRIEVE_TKT_REQUEST) + sz), (PVOID *)&ticket, &ResponseSize, &SubStatus); LocalFree(TicketRequest); if (SEC_SUCCESS(Status) && SEC_SUCCESS(SubStatus)) {
#if 0
if (ticket->TargetName && ticket->TargetDomainName.Length && !UnparseExternalName(ticket->TargetName, &svc)) { swprintf(sname, TEXT("%wZ@%wZ"), svc, &ticket->TargetDomainName); SetDlgItemText(hDlg, IDC_SERVICE_PRINC, sname); SetDlgItemText(hDlg, IDC_SERVICE_PRINC_LABEL, GetStringRes(IDS_TARGET_NAME)); FreeUnicodeString(svc); } #endif
switch(iSel) { case PPAGE_NAMES: if (ticket->ServiceName && ticket->DomainName.Length && !UnparseExternalName(ticket->ServiceName, &svc)) { swprintf(sname, TEXT("%wZ@%wZ"), svc, &ticket->DomainName); SetDlgItemText(pHdr->hwndDisplay, IDC_SERVICENAME, sname); FreeUnicodeString(svc); } if (ticket->ClientName && ticket->DomainName.Length && !UnparseExternalName(ticket->ClientName, &svc)) { swprintf(sname, TEXT("%wZ@%wZ"), svc, &ticket->DomainName); SetDlgItemText(pHdr->hwndDisplay, IDC_CLIENTNAME, sname); FreeUnicodeString(svc); } if (ticket->TargetName && ticket->TargetDomainName.Length && !UnparseExternalName(ticket->TargetName, &svc)) { swprintf(sname, TEXT("%wZ@%wZ"), svc, &ticket->TargetDomainName); SetDlgItemText(pHdr->hwndDisplay, IDC_TARGETNAME, sname); FreeUnicodeString(svc); } break;
case PPAGE_TIMES: SetDlgItemText(pHdr->hwndDisplay, IDC_STARTTIME, timestring(tix->StartTime)); SetDlgItemText(pHdr->hwndDisplay, IDC_ENDTIME, timestring(tix->EndTime)); if (tix->TicketFlags & KERB_TICKET_FLAGS_renewable) { SetDlgItemText(pHdr->hwndDisplay, IDC_RENEW_UNTIL, timestring(tix->RenewTime)); ShowWindow(GetDlgItem(pHdr->hwndDisplay, IDC_RENEW_UNTIL), SW_SHOW); } else { ShowWindow(GetDlgItem(pHdr->hwndDisplay, IDC_RENEW_UNTIL), SW_HIDE); } break;
case PPAGE_ETYPES: SetDlgItemText(pHdr->hwndDisplay, IDC_TKT_ENCTYPE, etype_string(tix->EncryptionType)); SetDlgItemText(pHdr->hwndDisplay, IDC_KEY_ENCTYPE, etype_string(ticket->SessionKey.KeyType)); break;
case PPAGE_FLAGS: ShowFlags(pHdr->hwndDisplay, tix->TicketFlags); break; }
LsaFreeReturnBuffer(ticket); } }
LRESULT CALLBACK TicketsProc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam ) /*++
Routine Description:
Arguments:
Return Value:
--*/ { LPNMHDR nm; DLGTABHDR *pHdr;
switch (message) { case WM_INITDIALOG: DisplayCreds(hDlg); ShowWindow(hDlg, SW_SHOW); return TRUE;
case WM_NOTIFY: { nm = (LPNMHDR)lParam; switch (nm->code) { case TCN_SELCHANGING: return FALSE;
case TCN_SELCHANGE: PropsheetDisplay(hDlg); FillinTicket(hDlg); return TRUE;
case TVN_SELCHANGED: SelectTicket(hDlg); break; } } break;
case WM_SYSCOMMAND: switch (wParam) { case SC_CLOSE: goto close_tix; } break;
case WM_COMMAND: switch (LOWORD(wParam)) { case IDC_CLOSE: close_tix: pHdr = (DLGTABHDR *) GetWindowLongPtr(hDlg, GWLP_USERDATA); if (pHdr->hwndDisplay != NULL) DestroyWindow(pHdr->hwndDisplay); DestroyWindow(hDlgTickets); LsaFreeReturnBuffer(pHdr->Tickets); LocalFree(pHdr); hDlgTickets = NULL; break; } break; }
return FALSE; }
void Tickets(void) /*++
Routine Description:
Arguments:
Return Value:
--*/ { if (!hDlgTickets) hDlgTickets = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_TICKETS), hWnd, TicketsProc); else { ShowWindow(hDlgTickets, SW_SHOW); SetForegroundWindow(hDlgTickets); } }
|