Added files to the windows/cns directory
authorKeith Vetter <keithv@fusion.com>
Wed, 22 Mar 1995 20:17:41 +0000 (20:17 +0000)
committerKeith Vetter <keithv@fusion.com>
Wed, 22 Mar 1995 20:17:41 +0000 (20:17 +0000)
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@5189 dc483132-0cff-0310-8789-dd5450dbe970

24 files changed:
src/windows/cns/clock00.ico [new file with mode: 0644]
src/windows/cns/clock05.ico [new file with mode: 0644]
src/windows/cns/clock10.ico [new file with mode: 0644]
src/windows/cns/clock15.ico [new file with mode: 0644]
src/windows/cns/clock20.ico [new file with mode: 0644]
src/windows/cns/clock25.ico [new file with mode: 0644]
src/windows/cns/clock30.ico [new file with mode: 0644]
src/windows/cns/clock35.ico [new file with mode: 0644]
src/windows/cns/clock40.ico [new file with mode: 0644]
src/windows/cns/clock45.ico [new file with mode: 0644]
src/windows/cns/clock50.ico [new file with mode: 0644]
src/windows/cns/clock55.ico [new file with mode: 0644]
src/windows/cns/clock60.ico [new file with mode: 0644]
src/windows/cns/clockexp.ico [new file with mode: 0644]
src/windows/cns/clocktkt.ico [new file with mode: 0644]
src/windows/cns/cns.c [new file with mode: 0644]
src/windows/cns/cns.def [new file with mode: 0644]
src/windows/cns/cns.h [new file with mode: 0644]
src/windows/cns/cns.ico [new file with mode: 0644]
src/windows/cns/cns.rc [new file with mode: 0644]
src/windows/cns/krbini.h [new file with mode: 0644]
src/windows/cns/makefile [new file with mode: 0644]
src/windows/cns/tktlist.c [new file with mode: 0644]
src/windows/cns/tktlist.h [new file with mode: 0644]

diff --git a/src/windows/cns/clock00.ico b/src/windows/cns/clock00.ico
new file mode 100644 (file)
index 0000000..1c2e424
Binary files /dev/null and b/src/windows/cns/clock00.ico differ
diff --git a/src/windows/cns/clock05.ico b/src/windows/cns/clock05.ico
new file mode 100644 (file)
index 0000000..1e09283
Binary files /dev/null and b/src/windows/cns/clock05.ico differ
diff --git a/src/windows/cns/clock10.ico b/src/windows/cns/clock10.ico
new file mode 100644 (file)
index 0000000..15e00b2
Binary files /dev/null and b/src/windows/cns/clock10.ico differ
diff --git a/src/windows/cns/clock15.ico b/src/windows/cns/clock15.ico
new file mode 100644 (file)
index 0000000..93a5286
Binary files /dev/null and b/src/windows/cns/clock15.ico differ
diff --git a/src/windows/cns/clock20.ico b/src/windows/cns/clock20.ico
new file mode 100644 (file)
index 0000000..5fd55da
Binary files /dev/null and b/src/windows/cns/clock20.ico differ
diff --git a/src/windows/cns/clock25.ico b/src/windows/cns/clock25.ico
new file mode 100644 (file)
index 0000000..fc163fa
Binary files /dev/null and b/src/windows/cns/clock25.ico differ
diff --git a/src/windows/cns/clock30.ico b/src/windows/cns/clock30.ico
new file mode 100644 (file)
index 0000000..3dfd845
Binary files /dev/null and b/src/windows/cns/clock30.ico differ
diff --git a/src/windows/cns/clock35.ico b/src/windows/cns/clock35.ico
new file mode 100644 (file)
index 0000000..b508e88
Binary files /dev/null and b/src/windows/cns/clock35.ico differ
diff --git a/src/windows/cns/clock40.ico b/src/windows/cns/clock40.ico
new file mode 100644 (file)
index 0000000..d7e64a3
Binary files /dev/null and b/src/windows/cns/clock40.ico differ
diff --git a/src/windows/cns/clock45.ico b/src/windows/cns/clock45.ico
new file mode 100644 (file)
index 0000000..e35b200
Binary files /dev/null and b/src/windows/cns/clock45.ico differ
diff --git a/src/windows/cns/clock50.ico b/src/windows/cns/clock50.ico
new file mode 100644 (file)
index 0000000..b1eaa1c
Binary files /dev/null and b/src/windows/cns/clock50.ico differ
diff --git a/src/windows/cns/clock55.ico b/src/windows/cns/clock55.ico
new file mode 100644 (file)
index 0000000..845a7b3
Binary files /dev/null and b/src/windows/cns/clock55.ico differ
diff --git a/src/windows/cns/clock60.ico b/src/windows/cns/clock60.ico
new file mode 100644 (file)
index 0000000..0e9d6eb
Binary files /dev/null and b/src/windows/cns/clock60.ico differ
diff --git a/src/windows/cns/clockexp.ico b/src/windows/cns/clockexp.ico
new file mode 100644 (file)
index 0000000..6a22b90
Binary files /dev/null and b/src/windows/cns/clockexp.ico differ
diff --git a/src/windows/cns/clocktkt.ico b/src/windows/cns/clocktkt.ico
new file mode 100644 (file)
index 0000000..dc4d246
Binary files /dev/null and b/src/windows/cns/clocktkt.ico differ
diff --git a/src/windows/cns/cns.c b/src/windows/cns/cns.c
new file mode 100644 (file)
index 0000000..3fc8913
--- /dev/null
@@ -0,0 +1,2878 @@
+/*
+ * cns.c
+ *
+ * Tabs 4
+ *
+ * Main routine of the Kerberos user interface.  Also handles
+ * all dialog level management functions.
+ *
+ * Copyright 1994 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#if !defined(KRB5) && !defined(KRB4)
+       #define KRB5 1
+#endif
+
+#include <windows.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <string.h>
+#include <malloc.h>
+#include <ctype.h>
+#include <time.h>
+
+#ifdef KRB4
+       #define DEFINE_SOCKADDR
+       #include "mit-copyright.h"
+       #include "krb.h"
+       #include "kadm.h"
+       #include "org.h"
+#endif
+
+#ifdef KRB5
+       #define NEED_SOCKETS
+       #include "krb5.h"
+       #include "krbini.h"
+       #include "com_err.h"
+
+       #define DEFAULT_TKT_LIFE    120
+       #define ANAME_SZ                40
+       #define REALM_SZ                40
+       #define SNAME_SZ                40
+       #define INST_SZ                 40
+       #define MAX_KPW_LEN             128
+       /* include space for '.' and '@' */
+       #define MAX_K_NAME_SZ       (ANAME_SZ + INST_SZ + REALM_SZ + 2)
+       #define ORGANIZATION        "Cygnus Support"
+
+    #define CREDENTIALS         char
+#endif
+
+#include "cns.h"
+#include "tktlist.h"
+
+/*
+ * Constants
+ */
+#define BLOCK_MAX_SEC 30                               /* Blocking timeout duration */
+#define KWIN_UPDATE_PERIOD 30000               /* Every 30 seconds update the screen */
+#define TIME_BUFFER    300                                     /* Pop-up time buffer in seconds */
+#define WM_KWIN_SETNAME (WM_USER+100)  /* Sets the name fields in the dialog */
+
+enum {                                                                 /* Actions after login */
+       LOGIN_AND_EXIT,
+       LOGIN_AND_MINIMIZE,
+       LOGIN_AND_RUN,
+};
+
+/*
+ * Globals
+ */
+static HICON kwin_icons[MAX_ICONS];            /* Icons depicting time */
+static HFONT hfontdialog = NULL;               /* Font in which the dialog is drawn. */
+static HFONT hfonticon = NULL;                 /* Font for icon label */
+static HINSTANCE hinstance;
+static int dlgncmdshow;                                        /* ncmdshow from WinMain */
+static char confname[FILENAME_MAX];            /* current krb.conf location */
+static char realmsname[FILENAME_MAX];  /* current krb.realms location */
+static UINT wm_kerberos_changed;               /* Registered message for cache changing */
+static int action;                                             /* After login actions */
+static UINT kwin_timer_id;                             /* Timer being used for update */
+static BOOL alert;                                             /* Actions on ticket expiration */
+static BOOL beep;
+static BOOL alerted;                                   /* TRUE when user already alerted */
+static BOOL isblocking = FALSE;                        /* TRUE when blocked in WinSock */
+static DWORD blocking_end_time;                        /* Ending tick count for blocking timeout */
+static FARPROC hook_instance;                  /* Intance handle for blocking hook function */
+
+#ifdef KRB5
+       krb5_context k5_context;
+       krb5_ccache k5_ccache;
+#endif
+
+/*+
+ * Function: Called during blocking operations.  Implement a timeout
+ *     if nothing occurs within the specified time, cancel the blocking
+ *     operation.  Also permit the user to press escape in order to
+ *     cancel the blocking operation.
+ *
+ * Returns: TRUE if we got and dispatched a message, FALSE otherwise.
+ */
+BOOL __export CALLBACK
+blocking_hook_proc (void)
+{
+       MSG msg;
+       BOOL rc;
+
+       if (GetTickCount() > blocking_end_time) {
+               WSACancelBlockingCall();
+               return FALSE;
+       }
+
+       rc = (BOOL) PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
+       if (!rc)
+               return FALSE;
+
+       if (msg.message == WM_KEYDOWN && msg.wParam == VK_ESCAPE) {
+               WSACancelBlockingCall();
+               blocking_end_time = msg.time - 1;
+               return FALSE;
+       }
+
+       TranslateMessage(&msg);
+       DispatchMessage(&msg);
+
+       return TRUE;
+
+} /* blocking_hook_proc */
+
+
+/*+
+ * Function: Set up a blocking hook function.
+ *
+ * Parameters:
+ *     timeout - # of seconds to block for before cancelling.
+ */
+static void
+start_blocking_hook (
+       int timeout)
+{
+       FARPROC proc;
+
+       if (isblocking)
+               return;
+
+       isblocking = TRUE;
+       blocking_end_time = GetTickCount() + (1000 * timeout);
+       hook_instance = MakeProcInstance(blocking_hook_proc, hinstance);
+       proc = WSASetBlockingHook(hook_instance);
+       assert(proc != NULL);
+
+} /* start_blocking_hook */
+
+
+/*+
+ * Function: End the blocking hook fuction set up above.
+ */
+static void
+end_blocking_hook (void)
+{
+
+       FreeProcInstance(hook_instance);
+       WSAUnhookBlockingHook();
+       isblocking = FALSE;
+
+} /* end_blocking_hook */
+
+
+/*+
+ * Function: Centers the specified window on the screen.
+ *
+ * Parameters:
+ *             hwnd - the window to center on the screen.
+ */
+static void
+center_dialog (
+       HWND hwnd)
+{
+       int scrwidth, scrheight;
+       int dlgwidth, dlgheight;
+       RECT r;
+       HDC hdc;
+
+       if (hwnd == NULL)
+               return;
+
+       GetWindowRect(hwnd, &r);
+       dlgwidth = r.right  - r.left;
+       dlgheight = r.bottom - r.top ;
+       hdc = GetDC(NULL);
+       scrwidth = GetDeviceCaps(hdc, HORZRES);
+       scrheight = GetDeviceCaps(hdc, VERTRES);
+       ReleaseDC(NULL, hdc);
+       r.left = (scrwidth - dlgwidth) / 2;
+       r.top  = (scrheight - dlgheight) / 2;
+       MoveWindow(hwnd, r.left, r.top, dlgwidth, dlgheight, TRUE);
+
+} /* center_dialog */
+
+
+/*+
+ * Function: Positions the kwin dialog either to the saved location
+ *     or the center of the screen if no saved location.
+ *
+ * Parameters:
+ *             hwnd - the window to center on the screen.
+ */
+static void
+position_dialog (
+       HWND hwnd)
+{
+       int n;
+       int scrwidth, scrheight;
+       HDC hdc;
+       char position[256];
+       int x, y, cx, cy;
+
+       if (hwnd == NULL)
+               return;
+
+       hdc = GetDC(NULL);
+       scrwidth = GetDeviceCaps(hdc, HORZRES);
+       scrheight = GetDeviceCaps(hdc, VERTRES);
+       ReleaseDC(NULL, hdc);
+       GetPrivateProfileString(INI_DEFAULTS, INI_POSITION, "",
+               position, sizeof(position), KERBEROS_INI);
+
+       n = sscanf(position, " [%d , %d , %d , %d", &x, &y, &cx, &cy);
+       if (n != 4 ||
+               x > scrwidth ||
+               y > scrheight ||
+               x + cx < 0 ||
+               y + cy < 0)
+               center_dialog(hwnd);
+       else
+               MoveWindow(hwnd, x, y, cx, cy, TRUE);
+
+} /* position_dialog */
+
+
+/*+
+ * Function: Set font of all dialog items.
+ *
+ * Parameters:
+ *             hwnd - the dialog to set the font of
+ */
+static void
+set_dialog_font (
+       HWND hwnd,
+       HFONT hfont)
+{
+       hwnd = GetWindow(hwnd, GW_CHILD);
+
+       while (hwnd != NULL) {
+               SendMessage(hwnd, WM_SETFONT, (WPARAM) hfont, 0);
+               hwnd = GetWindow(hwnd, GW_HWNDNEXT);
+       }
+
+} /* set_dialog_font */
+
+
+/*+
+ * Function: Trim leading and trailing white space from a string.
+ *
+ * Parameters:
+ *     s - the string to trim.
+ */
+void
+trim (
+       char *s)
+{
+       int l;
+       int i;
+
+       for (i = 0; s[i]; i++)
+               if (s[i] != ' ' && s[i] != '\t')
+                       break;
+
+       l = strlen(&s[i]);
+       memmove(s, &s[i], l + 1);
+
+       for (l--; l >= 0; l--) {
+               if (s[l] != ' ' && s[l] != '\t')
+                       break;
+       }
+       s[l + 1] = 0;
+
+} /* trim */
+
+
+/*+
+ * Function: This routine figures out the current time epoch and
+ * returns the conversion factor.  It exists because Microloss
+ * screwed the pooch on the time() and _ftime() calls in its release
+ * 7.0 libraries.  They changed the epoch to Dec 31, 1899!
+ */
+time_t
+kwin_get_epoch (void)
+{
+       static struct tm jan_1_70 = {0, 0, 0, 1, 0, 70};
+       time_t epoch = 0;
+
+       epoch = -mktime(&jan_1_70);             /* Seconds til 1970 localtime */
+       epoch += _timezone;                             /* Seconds til 1970 GMT */
+
+       return epoch;
+
+} /* kwin_get_epoch */
+
+
+/*+
+ * Function: Save the credentials for later restoration.
+ *
+ * Parameters:
+ *     c - Returned pointer to saved credential cache.
+ *
+ *     pname - Returned as principal name of session.
+ *
+ *     pinstance - Returned as principal instance of session.
+ *
+ *     ncred - Returned number of credentials saved.
+ */
+static void
+push_credentials (
+       CREDENTIALS **cp,
+       char *pname,
+       char *pinstance,
+       int *ncred)
+{
+#ifdef KRB4
+       int i;
+    char service[ANAME_SZ];
+    char instance[INST_SZ];
+    char realm[REALM_SZ];
+       CREDENTIALS *c;
+
+       if (krb_get_tf_fullname ((char *) 0, pname, pinstance, (char *) 0) != KSUCCESS) {
+               pname[0] = 0;
+
+               pinstance[0] = 0;
+       }
+
+       *ncred = krb_get_num_cred();
+       if (*ncred <= 0)
+               return;
+
+       c= malloc(*ncred * sizeof(CREDENTIALS));
+       assert(c != NULL);
+       if (c == NULL) {
+               *ncred = 0;
+
+               return;
+       }
+
+       for (i = 0; i < *ncred; i++) {
+               krb_get_nth_cred(service, instance, realm, i + 1);
+               krb_get_cred(service, instance, realm, &c[i]);
+       }
+
+       *cp = c;
+#endif
+
+#ifdef KRB5     /* FIXME */
+    return;
+#endif
+
+} /* push_credentials */
+
+
+/*+
+ * Function: Restore the saved credentials.
+ *
+ *     c - Pointer to saved credential cache.
+ *
+ *     pname - Principal name of session.
+ *
+ *     pinstance - Principal instance of session.
+ *
+ *     ncred - Number of credentials saved.
+ */
+static void
+pop_credentials (
+       CREDENTIALS *c,
+       char *pname,
+       char *pinstance,
+       int ncred)
+{
+#ifdef KRB4
+       int i;
+
+       if (pname[0])
+               in_tkt(pname, pinstance);
+       else
+               dest_tkt();
+
+       if (ncred <= 0)
+               return;
+
+       for (i = 0; i < ncred; i++) {
+               krb_save_credentials(c[i].service, c[i].instance, c[i].realm,
+                       c[i].session, c[i].lifetime, c[i].kvno, &(c[i].ticket_st),
+                       c[i].issue_date);
+       }
+
+       free(c);
+#endif
+#ifdef KRB5     /* FIXME */
+    return;
+#endif
+
+} /* pop_credentials */
+
+
+/*+
+ * Function: Changes the password.
+ *
+ * Parameters:
+ *     hwnd - the current window from which command was invoked.
+ *
+ *     name - name of user to change password for
+ *
+ *     instance - instance of user to change password for
+ *
+ *     realm - realm in which to change password
+ *
+ *     oldpw - the old password
+ *
+ *     newpw - the new password to change to
+ *
+ * Returns: TRUE if change took place, FALSE otherwise.
+ */
+static BOOL
+change_password (
+       HWND hwnd,
+       char *name,
+       char *instance,
+       char *realm,
+       char *oldpw,
+       char *newpw)
+{
+#ifdef KRB4
+    des_cblock new_key;
+    char *ret_st;
+       int krc;
+       char *p;
+       CREDENTIALS *c;
+       int ncred;
+    char pname[ANAME_SZ];
+    char pinstance[INST_SZ];
+
+       push_credentials(&c, pname, pinstance, &ncred);
+       krc = krb_get_pw_in_tkt(
+               name, instance, realm, PWSERV_NAME, KADM_SINST, 1, oldpw);
+
+       if (krc != KSUCCESS) {
+               if (krc == INTK_BADPW)
+                       p = "Old password is incorrect";
+               else
+                       p = krb_get_err_text(krc);
+               pop_credentials(c, pname, pinstance, ncred);
+               MessageBox(hwnd, p, "", MB_OK | MB_ICONEXCLAMATION);
+
+               return FALSE;
+    }
+
+       krc = kadm_init_link(PWSERV_NAME, KRB_MASTER, realm);
+
+       if (krc != KSUCCESS) {
+               pop_credentials(c, pname, pinstance, ncred);
+               MessageBox(hwnd, kadm_get_err_text(krc), "", MB_OK | MB_ICONEXCLAMATION);
+
+               return FALSE;
+       }
+
+       des_string_to_key(newpw, new_key);
+       krc = kadm_change_pw2(new_key, newpw, &ret_st);
+       pop_credentials(c, pname, pinstance, ncred);
+
+       if (ret_st != NULL)
+               free(ret_st);
+
+       if (krc != KSUCCESS) {
+               MessageBox(hwnd, kadm_get_err_text(krc), "", MB_OK | MB_ICONEXCLAMATION);
+
+               return FALSE;
+       }
+
+       return TRUE;
+#endif
+
+#ifdef KRB5     /* FIXME */
+    MessageBox (NULL, "Changing passwords is not yet implemented", "", MB_ICONEXCLAMATION);
+       return TRUE;
+#endif
+
+} /* change_password */
+
+/*+
+ * Function: Process WM_COMMAND messages for the password dialog.
+ *
+ * Parameters:
+ *     hwnd - the window recieving the message.
+ *
+ *     wparam - id of the command item
+ *
+ *     lparam - LOWORD=hwnd of control, HIWORD=notification message.
+ *
+ * Returns: TRUE if initialized sucessfully, false otherwise.
+ */
+static LONG
+password_command (
+       HWND hwnd,
+       WPARAM wparam,
+       LPARAM lparam)
+{
+       char name[ANAME_SZ];
+       char instance[INST_SZ];
+       char realm[REALM_SZ];
+    char oldpw[MAX_KPW_LEN];
+    char newpw1[MAX_KPW_LEN];
+    char newpw2[MAX_KPW_LEN];
+       HCURSOR hcursor;
+       BOOL b;
+       int id;
+
+       if (HIWORD(lparam) != BN_CLICKED) {
+               GetDlgItemText(hwnd, IDD_PASSWORD_NAME, name, sizeof(name));
+               trim(name);
+               GetDlgItemText(hwnd, IDD_PASSWORD_REALM, realm, sizeof(realm));
+               trim(realm);
+               GetDlgItemText(hwnd, IDD_OLD_PASSWORD, oldpw, sizeof(oldpw));
+               GetDlgItemText(hwnd, IDD_NEW_PASSWORD1, newpw1, sizeof(newpw1));
+               GetDlgItemText(hwnd, IDD_NEW_PASSWORD2, newpw2, sizeof(newpw2));
+               b = strlen(name) && strlen(realm) && strlen(oldpw) &&
+                       strlen(newpw1) && strlen(newpw2);
+               EnableWindow(GetDlgItem(hwnd, IDOK), b);
+               id = (b) ? IDOK : IDD_PASSWORD_CR;
+               SendMessage(hwnd, DM_SETDEFID, id, 0);
+
+               return FALSE;
+       }
+
+       switch (wparam) {
+       case IDOK:
+               if (isblocking)
+                       return TRUE;
+
+               GetDlgItemText(hwnd, IDD_PASSWORD_NAME, name, sizeof(name));
+               trim(name);
+        GetDlgItemText(hwnd, IDD_PASSWORD_INSTANCE, instance, sizeof(instance));
+        trim(instance);
+               GetDlgItemText(hwnd, IDD_PASSWORD_REALM, realm, sizeof(realm));
+               trim(realm);
+               GetDlgItemText(hwnd, IDD_OLD_PASSWORD, oldpw, sizeof(oldpw));
+               GetDlgItemText(hwnd, IDD_NEW_PASSWORD1, newpw1, sizeof(newpw1));
+               GetDlgItemText(hwnd, IDD_NEW_PASSWORD2, newpw2, sizeof(newpw2));
+
+               if (strcmp(newpw1, newpw2) != 0) {
+                       MessageBox(hwnd, "The two passwords you entered don't match!", "",
+                               MB_OK | MB_ICONEXCLAMATION);
+                       SetDlgItemText(hwnd, IDD_NEW_PASSWORD1, "");
+                       SetDlgItemText(hwnd, IDD_NEW_PASSWORD2, "");
+                       PostMessage(hwnd, WM_NEXTDLGCTL,
+                               GetDlgItem(hwnd, IDD_NEW_PASSWORD1), MAKELONG(1, 0));
+
+                       return TRUE;
+               }
+
+               hcursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
+               start_blocking_hook(BLOCK_MAX_SEC);
+
+               if (change_password(hwnd, name, instance, realm, oldpw, newpw1))
+                       EndDialog(hwnd, IDOK);
+               else
+                       PostMessage(hwnd, WM_NEXTDLGCTL,
+                               GetDlgItem(hwnd, IDD_OLD_PASSWORD), MAKELONG(1, 0));
+
+               end_blocking_hook();
+               SetCursor(hcursor);
+
+               return TRUE;
+
+       case IDCANCEL:
+               if (isblocking)
+                       WSACancelBlockingCall();
+               EndDialog(hwnd, IDCANCEL);
+
+               return TRUE;
+
+       case IDD_PASSWORD_CR:
+               id = GetDlgCtrlID(GetFocus());
+               assert(id != 0);
+
+               if (id == IDD_NEW_PASSWORD2)
+                       PostMessage(hwnd, WM_NEXTDLGCTL,
+                               GetDlgItem(hwnd, IDD_PASSWORD_NAME), MAKELONG(1, 0));
+               else
+                       PostMessage(hwnd, WM_NEXTDLGCTL, 0, 0);
+
+               return TRUE;
+
+       }
+
+       return FALSE;
+
+} /* password_command */
+
+
+/*+
+ * Function: Process WM_INITDIALOG messages for the password dialog.
+ *     Set up all initial dialog values from the parent dialog.
+ *
+ * Parameters:
+ *     hwnd - the window recieving the message.
+ *
+ *     wparam - handle of the control for focus.
+ *
+ *     lparam - lparam from dialog box call.
+ *
+ * Returns: TRUE if we didn't set the focus here,
+ *     FALSE if we did.
+ */
+static BOOL
+password_initdialog (
+       HWND hwnd,
+       WPARAM wparam,
+       LPARAM lparam)
+{
+       char name[ANAME_SZ];
+       char instance[INST_SZ];
+       char realm[REALM_SZ];
+       HWND hwndparent;
+       int id;
+
+       center_dialog(hwnd);
+       set_dialog_font(hwnd, hfontdialog);
+
+       hwndparent = GetParent(hwnd);
+       assert(hwndparent != NULL);
+
+       GetDlgItemText(hwndparent, IDD_LOGIN_NAME, name, sizeof(name));
+       trim(name);
+       SetDlgItemText(hwnd, IDD_PASSWORD_NAME, name);
+
+    GetDlgItemText(hwndparent, IDD_LOGIN_INSTANCE, instance, sizeof(instance));
+       trim(instance);
+       SetDlgItemText(hwnd, IDD_PASSWORD_INSTANCE, instance);
+
+       GetDlgItemText(hwndparent, IDD_LOGIN_REALM, realm, sizeof(realm));
+       trim(realm);
+       SetDlgItemText(hwnd, IDD_PASSWORD_REALM, realm);
+
+       if (strlen(name) == 0)
+               id = IDD_PASSWORD_NAME;
+       else if (strlen(realm) == 0)
+               id = IDD_PASSWORD_REALM;
+       else
+               id = IDD_OLD_PASSWORD;
+
+       SetFocus(GetDlgItem(hwnd, id));
+
+       return FALSE;
+
+} /* password_initdialog */
+
+
+/*+
+ * Function: Process dialog specific messages for the password dialog.
+ *
+ * Parameters:
+ *     hwnd - the dialog receiving the message.
+ *
+ *     message - the message to process.
+ *
+ *     wparam - wparam of the message.
+ *
+ *     lparam - lparam of the message.
+ *
+ * Returns: TRUE if message handled locally, FALSE otherwise.
+ */
+static BOOL CALLBACK
+password_dlg_proc (
+       HWND hwnd,
+       UINT message,
+       WPARAM wparam,
+       LPARAM lparam)
+{
+       LRESULT rc;
+
+       switch (message) {
+
+       case WM_INITDIALOG:
+               return password_initdialog(hwnd, wparam, lparam);
+
+       case WM_COMMAND:
+               password_command(hwnd, wparam, lparam);
+               return (BOOL) rc;
+
+       case WM_SETCURSOR:
+               if (isblocking) {
+                       SetCursor(LoadCursor(NULL, IDC_WAIT));
+                       SetWindowLong(hwnd, DWL_MSGRESULT, TRUE);
+
+                       return TRUE;
+               }
+               break;
+       }
+
+       return FALSE;
+
+} /* password_dlg_proc */
+
+
+/*+
+ * Function: Display and process the password dialog.
+ *
+ * Parameters:
+ *     hwnd - the parent window for the dialog
+ *
+ * Returns: TRUE if the dialog completed successfully, FALSE otherwise.
+ */
+static BOOL
+password_dialog (
+       HWND hwnd)
+{
+       DLGPROC dlgproc;
+       int rc;
+
+       dlgproc = (FARPROC) MakeProcInstance(password_dlg_proc, hinstance);
+       assert(dlgproc != NULL);
+
+       if (dlgproc == NULL)
+               return FALSE;
+
+       rc = DialogBox(hinstance, MAKEINTRESOURCE(ID_PASSWORD), hwnd, dlgproc);
+       assert(rc != -1);
+
+       FreeProcInstance((FARPROC) dlgproc);
+
+       return rc == IDOK;
+
+} /* password_dialog */
+
+
+/*+
+ * Function: Process WM_INITDIALOG messages for the options dialog.
+ *     Set up all initial dialog values from the KERBEROS_INI file.
+ *
+ * Parameters:
+ *     hwnd - the window recieving the message.
+ *
+ *     wparam - handle of the control for focus.
+ *
+ *     lparam - lparam from dialog box call.
+ *
+ * Returns: TRUE if we didn't set the focus here,
+ *     FALSE if we did.
+ */
+static LONG
+opts_initdialog (
+       HWND hwnd,
+       WPARAM wparam,
+       LPARAM lparam)
+{
+       char defname[FILENAME_MAX];
+       UINT rc;
+       int lifetime;
+
+       center_dialog(hwnd);
+       set_dialog_font(hwnd, hfontdialog);
+
+       /* krb.conf file */
+       rc = GetWindowsDirectory(defname, sizeof(defname));
+       assert(rc > 0);
+
+       strcat(defname, "\\");
+       strcat(defname, DEF_KRB_CONF);
+       GetPrivateProfileString(INI_FILES, INI_KRB_CONF, defname,
+               confname, sizeof(confname), KERBEROS_INI);
+       _strupr(confname);
+       SetDlgItemText(hwnd, IDD_CONF, confname);
+
+       /* krb.realms file */
+       rc = GetWindowsDirectory(defname, sizeof(defname));
+       assert(rc > 0);
+
+       strcat(defname, "\\");
+       strcat(defname, DEF_KRB_REALMS);
+       GetPrivateProfileString(INI_FILES, INI_KRB_REALMS, defname,
+               realmsname, sizeof(realmsname), KERBEROS_INI);
+       _strupr(realmsname);
+       SetDlgItemText(hwnd, IDD_REALMS, realmsname);
+
+       /* Ticket duration */
+       lifetime = GetPrivateProfileInt(INI_OPTIONS, INI_DURATION,
+               DEFAULT_TKT_LIFE * 5, KERBEROS_INI);
+       SetDlgItemInt(hwnd, IDD_LIFETIME, lifetime, FALSE);
+
+       /* Expiration action */
+       GetPrivateProfileString(INI_EXPIRATION, INI_ALERT, "No",
+               defname, sizeof(defname), KERBEROS_INI);
+       alert = _stricmp(defname, "Yes") == 0;
+       SendDlgItemMessage(hwnd, IDD_ALERT, BM_SETCHECK, alert, 0);
+       GetPrivateProfileString(INI_EXPIRATION, INI_BEEP, "No",
+               defname, sizeof(defname), KERBEROS_INI);
+       beep = _stricmp(defname, "Yes") == 0;
+       SendDlgItemMessage(hwnd, IDD_BEEP, BM_SETCHECK, beep, 0);
+
+       return TRUE;
+
+} /* opts_initdialog */
+
+
+/*+
+ * Function: Process WM_COMMAND messages for the options dialog.
+ *
+ * Parameters:
+ *     hwnd - the window recieving the message.
+ *
+ *     wparam - id of the command item
+ *
+ *     lparam - LOWORD=hwnd of control, HIWORD=notification message.
+ *
+ * Returns: TRUE if initialized sucessfully, false otherwise.
+ */
+static LONG
+opts_command (
+       HWND hwnd,
+       WPARAM wparam,
+       LPARAM lparam)
+{
+       char defname[FILENAME_MAX];
+       char *p;
+       BOOL b;
+       int lifetime;
+       int rc;
+
+       switch (wparam) {
+
+       case IDOK:
+               /* Ticket duration */
+               lifetime = GetDlgItemInt(hwnd, IDD_LIFETIME, &b, FALSE);
+
+               if (!b) {
+                       MessageBox(hwnd, "Lifetime must be a number!", "", MB_OK | MB_ICONEXCLAMATION);
+
+                       return TRUE;
+               }
+
+               _itoa(lifetime, defname, 10);
+               b = WritePrivateProfileString(INI_OPTIONS, INI_DURATION, defname, KERBEROS_INI);
+               assert(b);
+
+               /* krb.conf file */
+               GetDlgItemText(hwnd, IDD_CONF, confname, sizeof(confname));
+               trim(confname);
+               rc = GetWindowsDirectory(defname, sizeof(defname));
+               assert(rc > 0);
+
+               strcat(defname, "\\");
+               strcat(defname, DEF_KRB_CONF);
+               if (_stricmp(confname, defname) == 0 || !defname[0])
+                       p = NULL;
+               else
+                       p = confname;
+               b = WritePrivateProfileString(INI_FILES, INI_KRB_CONF, p, KERBEROS_INI);
+               assert(b);
+
+               /* krb.realms file */
+               GetDlgItemText(hwnd, IDD_REALMS, realmsname, sizeof(realmsname));
+               trim(realmsname);
+               rc = GetWindowsDirectory(defname, sizeof(defname));
+               assert(rc > 0);
+
+               strcat(defname, "\\");
+               strcat(defname, DEF_KRB_REALMS);
+               if (_stricmp(realmsname, defname) == 0 || !defname[0])
+                       p = NULL;
+               else
+                       p = defname;
+               b = WritePrivateProfileString(INI_FILES, INI_KRB_REALMS, p, KERBEROS_INI);
+               assert(b);
+
+               /* Expiration action */
+               alert = (BOOL) SendDlgItemMessage(hwnd, IDD_ALERT, BM_GETCHECK, 0, 0);
+               p = (alert) ? "Yes" : "No";
+               b = WritePrivateProfileString(INI_EXPIRATION, INI_ALERT, p, KERBEROS_INI);
+               assert(b);
+
+               beep = (BOOL) SendDlgItemMessage(hwnd, IDD_BEEP, BM_GETCHECK, 0, 0);
+               p = (beep) ? "Yes" : "No";
+               b = WritePrivateProfileString(INI_EXPIRATION, INI_BEEP, p, KERBEROS_INI);
+               assert(b);
+
+               EndDialog(hwnd, IDOK);
+
+               return TRUE;
+
+       case IDCANCEL:
+               EndDialog(hwnd, IDCANCEL);
+
+               return TRUE;
+       }
+
+       return FALSE;
+
+} /* opts_command */
+
+
+/*+
+ * Function: Process dialog specific messages for the opts dialog.
+ *
+ * Parameters:
+ *     hwnd - the dialog receiving the message.
+ *
+ *     message - the message to process.
+ *
+ *     wparam - wparam of the message.
+ *
+ *     lparam - lparam of the message.
+ *
+ * Returns: TRUE if message handled locally, FALSE otherwise.
+ */
+static BOOL CALLBACK
+opts_dlg_proc (
+       HWND hwnd,
+       UINT message,
+       WPARAM wparam,
+       LPARAM lparam)
+{
+       LRESULT rc;
+
+       switch (message) {
+
+       case WM_INITDIALOG:
+               rc = opts_initdialog(hwnd, wparam, lparam);
+
+               return (BOOL) rc;
+
+       case WM_COMMAND:
+               rc = opts_command(hwnd, wparam, lparam);
+
+               return (BOOL) rc;
+       }
+
+       return FALSE;
+
+} /* opts_dlg_proc */
+
+
+/*+
+ * Function: Display and process the options dialog.
+ *
+ * Parameters:
+ *     hwnd - the parent window for the dialog
+ *
+ * Returns: TRUE if the dialog completed successfully, FALSE otherwise.
+ */
+static BOOL
+opts_dialog (
+       HWND hwnd)
+{
+       DLGPROC dlgproc;
+       int rc;
+
+       dlgproc = (FARPROC) MakeProcInstance(opts_dlg_proc, hinstance);
+       assert(dlgproc != NULL);
+
+       if (dlgproc == NULL)
+               return FALSE;
+
+       rc = DialogBox(hinstance, MAKEINTRESOURCE(ID_OPTS), hwnd, dlgproc);
+       assert(rc != -1);
+
+       FreeProcInstance((FARPROC) dlgproc);
+
+       return rc == IDOK;
+
+} /* opts_dialog */
+
+
+/*+
+ * Function: Save most recent login triplets for placement on the
+ *     bottom of the file menu.
+ *
+ * Parameters:
+ *     hwnd - the handle of the window containing the menu to edit.
+ *
+ *     name - A login name to save in the recent login list
+ *
+ *     instance - An instance to save in the recent login list
+ *
+ *     realm - A realm to save in the recent login list
+ */
+static void
+kwin_push_login (
+       HWND hwnd,
+       char *name,
+       char *instance,
+       char *realm)
+{
+       HMENU hmenu;
+       int i;
+       int id;
+       int ctitems;
+       char fullname[MAX_K_NAME_SZ + 3];
+       char menuitem[MAX_K_NAME_SZ + 3];
+       BOOL rc;
+
+       strcpy(fullname, "&x ");
+       strcat(fullname, name);
+    strcat(fullname, ".");
+    strcat(fullname, instance);
+       strcat(fullname, "@");
+       strcat(fullname, realm);
+
+       hmenu = GetMenu(hwnd);
+       assert(hmenu != NULL);
+
+       hmenu = GetSubMenu(hmenu, 0);
+       assert(hmenu != NULL);
+
+       ctitems = GetMenuItemCount(hmenu);
+       assert(ctitems >= FILE_MENU_ITEMS);
+
+       if (ctitems == FILE_MENU_ITEMS) {
+               rc = AppendMenu(hmenu, MF_SEPARATOR, 0, NULL);
+               assert(rc);
+
+               ctitems++;
+       }
+
+       for (i = FILE_MENU_ITEMS + 1; i < ctitems; i++) {
+               GetMenuString(hmenu, i, menuitem, sizeof(menuitem), MF_BYPOSITION);
+
+               if (strcmp(&fullname[3], &menuitem[3]) == 0) {
+                       rc = RemoveMenu(hmenu, i, MF_BYPOSITION);
+                       assert(rc);
+
+                       ctitems--;
+
+                       break;
+               }
+       }
+
+       rc = InsertMenu(hmenu, FILE_MENU_ITEMS + 1, MF_BYPOSITION, 1, fullname);
+       assert(rc);
+
+       ctitems++;
+       if (ctitems - FILE_MENU_ITEMS - 1 > FILE_MENU_MAX_LOGINS) {
+               RemoveMenu(hmenu, ctitems - 1, MF_BYPOSITION);
+
+               ctitems--;
+       }
+
+       id = 0;
+       for (i = FILE_MENU_ITEMS + 1; i < ctitems; i++) {
+               GetMenuString(hmenu, i, menuitem, sizeof(menuitem), MF_BYPOSITION);
+
+               rc = RemoveMenu(hmenu, i, MF_BYPOSITION);
+               assert(rc);
+
+               menuitem[1] = '1' + id;
+               rc = InsertMenu(hmenu, i, MF_BYPOSITION, IDM_FIRST_LOGIN + id, menuitem);
+               assert(rc);
+
+               id++;
+       }
+
+} /* kwin_push_login */
+
+
+/*+
+ * Function: Initialize the logins on the file menu form the KERBEROS.INI
+ *     file.
+ *
+ * Parameters:
+ *     hwnd - handle of the dialog containing the file menu.
+ */
+static void
+kwin_init_file_menu (
+       HWND hwnd)
+{
+       HMENU hmenu;
+       int i;
+       char login[sizeof(INI_LOGIN)+1];
+       char menuitem[MAX_K_NAME_SZ + 3];
+       int id;
+       BOOL rc;
+
+       hmenu = GetMenu(hwnd);
+       assert(hmenu != NULL);
+
+       hmenu = GetSubMenu(hmenu, 0);
+       assert(hmenu != NULL);
+
+       strcpy(login, INI_LOGIN);
+       id = 0;
+       for (i = 0; i < FILE_MENU_MAX_LOGINS; i++) {
+               login[sizeof(INI_LOGIN) - 1] = '1' + i;
+               login[sizeof(INI_LOGIN)] = 0;
+               GetPrivateProfileString(INI_RECENT_LOGINS, login, "",
+                       &menuitem[3], sizeof(menuitem) - 3, KERBEROS_INI);
+               if (!menuitem[3])
+                       continue;
+
+               menuitem[0] = '&';
+               menuitem[1] = '1' + id;
+               menuitem[2] = ' ';
+
+               if (id == 0) {
+                       rc = AppendMenu(hmenu, MF_SEPARATOR, 0, NULL);
+                       assert(rc);
+               }
+               AppendMenu(hmenu, MF_STRING, IDM_FIRST_LOGIN + id, menuitem);
+
+               id++;
+       }
+
+} /* kwin_init_file_menu */
+
+
+/*+
+ * Function: Save the items on the file menu in the KERBEROS.INI file.
+ *
+ * Parameters:
+ *     hwnd - handle of the dialog containing the file menu.
+ */
+static void
+kwin_save_file_menu (
+       HWND hwnd)
+{
+       HMENU hmenu;
+       int i;
+       int id;
+       int ctitems;
+       char menuitem[MAX_K_NAME_SZ + 3];
+       char login[sizeof(INI_LOGIN)+1];
+       BOOL rc;
+
+       hmenu = GetMenu(hwnd);
+       assert(hmenu != NULL);
+
+       hmenu = GetSubMenu(hmenu, 0);
+       assert(hmenu != NULL);
+
+       strcpy(login, INI_LOGIN);
+       ctitems = GetMenuItemCount(hmenu);
+       assert(ctitems >= FILE_MENU_ITEMS);
+
+       id = 0;
+       for (i = FILE_MENU_ITEMS + 1; i < ctitems; i++) {
+               GetMenuString(hmenu, i, menuitem, sizeof(menuitem), MF_BYPOSITION);
+               login[sizeof(INI_LOGIN) - 1] = '1' + id;
+               login[sizeof(INI_LOGIN)] = 0;
+
+               rc = WritePrivateProfileString(INI_RECENT_LOGINS, login, &menuitem[3], KERBEROS_INI);
+               assert(rc);
+
+               id++;
+       }
+
+} /* kwin_save_file_menu */
+
+
+
+/*+
+ * Function: Given an expiration time, choose an appropriate
+ *     icon to display.
+ *
+ * Parameters:
+ *     expiration time of expiration in time() compatible units
+ *
+ * Returns: Handle of icon to display
+ */
+HICON
+kwin_get_icon (
+       time_t expiration)
+{
+       int ixicon;
+       time_t dt;
+
+       dt = expiration - time(NULL);
+       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 kwin_icons[ixicon];
+
+} /* kwin_get_icon */
+
+
+/*+
+ * Function: Intialize name fields in the Kerberos dialog.
+ *
+ * Parameters:
+ *     hwnd - the window recieving the message.
+ *
+ *     fullname - the full kerberos name to initialize with
+ */
+static void
+kwin_init_name (
+       HWND hwnd,
+       char *fullname)
+{
+    char name[ANAME_SZ];
+    char instance[INST_SZ];
+    char realm[REALM_SZ];
+       int krc;
+
+       if (fullname == NULL || fullname[0] == 0) {
+               #ifdef KRB4
+                       strcpy(name, krb_get_default_user());
+            GetPrivateProfileString(INI_DEFAULTS, INI_INSTANCE, "",
+                instance, sizeof(instance), KERBEROS_INI);
+                       krc = krb_get_lrealm(realm, 1);
+                       if (krc != KSUCCESS)
+                               realm[0] = 0;
+               #endif
+
+
+               #ifdef KRB5
+        {
+            krb5_error_code code;
+            char *ptr;
+
+            GetPrivateProfileString (INI_DEFAULTS, INI_USER, "",
+                name, sizeof(name), KERBEROS_INI);
+            //GetPrivateProfileString(INI_DEFAULTS, INI_INSTANCE, "",
+            //    instance, sizeof(instance), KERBEROS_INI);
+            *instance = '\0';
+
+            *realm = '\0';
+            code = krb5_get_default_realm (k5_context, &ptr);
+            if (! code) {
+                strcpy (realm, ptr);
+                free (ptr);
+            }
+        }
+               #endif
+
+               GetPrivateProfileString(INI_DEFAULTS, INI_REALM, realm,
+                       realm, sizeof(realm), KERBEROS_INI);
+       } else {
+               #ifdef KRB4
+                       kname_parse(name, instance, realm, fullname);
+               #endif
+
+               #ifdef KRB5
+                       krc = k5_kname_parse(name, realm, fullname);
+            *instance = '\0';
+               #endif
+       }
+
+       SetDlgItemText(hwnd, IDD_LOGIN_NAME, name);
+       name[0] = 0;
+       GetDlgItemText(hwnd, IDD_LOGIN_NAME, name, sizeof(name));
+       SetDlgItemText(hwnd, IDD_LOGIN_INSTANCE, instance);
+       SetDlgItemText(hwnd, IDD_LOGIN_REALM, realm);
+
+} /* kwin_init_name */
+
+
+/*+
+ * Function: Set the focus to the name control if no name
+ *     exists, the realm control if no realm exists or the
+ *     password control.  Uses PostMessage not SetFocus.
+ *
+ * Parameters:
+ *     hwnd - the Window handle of the parent.
+ */
+void
+kwin_set_default_focus (
+       HWND hwnd)
+{
+       char name[ANAME_SZ];
+       char realm[REALM_SZ];
+       HWND hwnditem;
+
+       GetDlgItemText(hwnd, IDD_LOGIN_NAME, name, sizeof(name));
+
+       trim(name);
+       if (strlen(name) <= 0)
+               hwnditem = GetDlgItem(hwnd, IDD_LOGIN_NAME);
+       else {
+               GetDlgItemText(hwnd, IDD_LOGIN_REALM, realm, sizeof(realm));
+               trim(realm);
+
+               if (strlen(realm) <= 0)
+                       hwnditem = GetDlgItem(hwnd, IDD_LOGIN_REALM);
+               else
+                       hwnditem = GetDlgItem(hwnd, IDD_LOGIN_PASSWORD);
+       }
+
+       PostMessage(hwnd, WM_NEXTDLGCTL, hwnditem, MAKELONG(1, 0));
+
+} /* kwin_set_default_focus */
+
+
+/*+
+ * Function: Save the values which live in the KERBEROS.INI file.
+ *
+ * Parameters:
+ *     hwnd - the window handle of the dialog containing fields to
+ *             be saved
+ */
+static void
+kwin_save_name (
+       HWND hwnd)
+{
+       char name[ANAME_SZ];
+       char instance[INST_SZ];
+       char realm[REALM_SZ];
+
+       GetDlgItemText(hwnd, IDD_LOGIN_NAME, name, sizeof(name));
+       trim(name);
+
+       #ifdef KRB4
+               krb_set_default_user(name);
+        GetDlgItemText(hwnd, IDD_LOGIN_INSTANCE, instance, sizeof(instance));
+        trim(instance);
+        WritePrivateProfileString(INI_DEFAULTS, INI_INSTANCE, instance, KERBEROS_INI);
+       #endif
+
+       #ifdef KRB5
+        WritePrivateProfileString(INI_DEFAULTS, INI_USER, name, KERBEROS_INI);
+        *instance = '\0';
+       #endif
+
+       GetDlgItemText(hwnd, IDD_LOGIN_REALM, realm, sizeof(realm));
+       trim(realm);
+       WritePrivateProfileString(INI_DEFAULTS, INI_REALM, realm, KERBEROS_INI);
+
+       kwin_push_login(hwnd, name, instance, realm);
+
+} /* kwin_save_name */
+
+
+/*+
+ * Function: Process WM_INITDIALOG messages.  Set the fonts
+ *     for all items on the dialog and populate the ticket list.
+ *     Also set the default values for user, instance and realm.
+ *
+ * Parameters:
+ *     hwnd - the window recieving the message.
+ *
+ *     wparam - handle of the control for focus.
+ *
+ *     lparam - lparam from dialog box call.
+ *
+ * Returns: TRUE if we didn't set the focus here,
+ *     FALSE if we did.
+ */
+static BOOL
+kwin_initdialog (
+       HWND hwnd,
+       WPARAM wparam,
+       LPARAM lparam)
+{
+       LOGFONT lf;
+       HDC hdc;
+       char name[ANAME_SZ];
+
+       position_dialog(hwnd);
+       ticket_init_list(GetDlgItem(hwnd, IDD_TICKET_LIST));
+       kwin_init_file_menu(hwnd);
+       kwin_init_name(hwnd, (char *) lparam);
+       hdc = GetDC(NULL);
+       assert(hdc != NULL);
+
+       memset(&lf, 0, sizeof(lf));
+       lf.lfHeight = -MulDiv(9, GetDeviceCaps(hdc, LOGPIXELSY), 72);
+       strcpy(lf.lfFaceName, "Arial");
+       hfontdialog = CreateFontIndirect(&lf);
+       assert(hfontdialog != NULL);
+
+       if (hfontdialog == NULL) {
+               ReleaseDC(NULL, hdc);
+
+               return TRUE;
+       }
+
+       lf.lfHeight = -MulDiv(8, GetDeviceCaps(hdc, LOGPIXELSY), 72);
+       hfonticon = CreateFontIndirect(&lf);
+       assert(hfonticon != NULL);
+
+       if (hfonticon == NULL) {
+               ReleaseDC(NULL, hdc);
+
+               return TRUE;
+       }
+
+       ReleaseDC(NULL, hdc);
+
+       set_dialog_font(hwnd, hfontdialog);
+       GetDlgItemText(hwnd, IDD_LOGIN_NAME, name, sizeof(name));
+       trim(name);
+
+       if (strlen(name) > 0)
+               SetFocus(GetDlgItem(hwnd, IDD_LOGIN_PASSWORD));
+       else
+               SetFocus(GetDlgItem(hwnd, IDD_LOGIN_NAME));
+
+       ShowWindow(hwnd, dlgncmdshow);
+       kwin_timer_id = SetTimer(hwnd, 1, KWIN_UPDATE_PERIOD, NULL);
+       assert(kwin_timer_id != 0);
+
+       return FALSE;
+
+} /* kwin_initdialog */
+
+
+/*+
+ * Function: Process WM_DESTROY messages.  Delete the font
+ *     created for use by the controls.
+ *
+ * Parameters:
+ *     hwnd - the window recieving the message.
+ *
+ *     wparam - none
+ *
+ *     lparam - none
+ *
+ * Returns: 0
+ */
+static LONG
+kwin_destroy (
+       HWND hwnd,
+       WPARAM wparam,
+       LPARAM lparam)
+{
+       char position[256];
+       RECT r;
+       BOOL b;
+
+       ticket_destroy(GetDlgItem(hwnd, IDD_TICKET_LIST));
+
+       if (hfontdialog != NULL)
+               DeleteObject(hfontdialog);
+
+       if (hfonticon != NULL)
+               DeleteObject(hfonticon);
+
+       kwin_save_file_menu(hwnd);
+       GetWindowRect(hwnd, &r);
+       sprintf(position, "[%d,%d,%d,%d]", r.left, r.top,
+               r.right - r.left, r.bottom - r.top);
+       b = WritePrivateProfileString(INI_DEFAULTS, INI_POSITION, position, KERBEROS_INI);
+       assert(b);
+
+       KillTimer(hwnd, kwin_timer_id);
+
+       return 0;
+
+} /* kwin_destroy */
+
+
+/*+
+ * Function: Retrievs item WindowRect in hwnd client
+ *     coordiate system.
+ *
+ * Parameters:
+ *     hwnditem - the item to retrieve
+ *
+ *     item - dialog in which into which to translate
+ *
+ *     r - rectangle returned
+ */
+static void
+windowrect (
+       HWND hwnditem,
+       HWND hwnd,
+       RECT *r)
+{
+       GetWindowRect(hwnditem, r);
+       ScreenToClient(hwnd, (LPPOINT) &(r->left));
+       ScreenToClient(hwnd, (LPPOINT) &(r->right));
+
+} /* windowrect */
+
+
+/*+
+ * Function: Process WM_SIZE messages.  Resize the
+ *     list and position the buttons attractively.
+ *
+ * Parameters:
+ *     hwnd - the window receiving the message.
+ *
+ *     wparam - type of resize occuring
+ *
+ *     lparam - LOWORD=width of client area,
+ *             HIWORD=height of client area.
+ *
+ * Returns: 0
+ */
+static LONG
+kwin_size (
+       HWND hwnd,
+       WPARAM wparam,
+       LPARAM lparam)
+{
+       #define listgap 8
+       RECT r;
+       RECT rdlg;
+       int hmargin, vmargin;
+       HWND hwnditem;
+       int cx, cy;
+       int cxdlg, cydlg;
+       int i;
+       int titlebottom;
+       int editbottom;
+       int listbottom;
+       int gap;
+       int left;
+       int titleleft[IDD_MAX_TITLE - IDD_MIN_TITLE + 1];
+
+       if (wparam == SIZE_MINIMIZED)
+               return 0;
+
+       GetClientRect(hwnd, &rdlg);
+       cxdlg = LOWORD(lparam);
+       cydlg = HIWORD(lparam);
+
+       /*
+        * The ticket list title
+        */
+       hwnditem = GetDlgItem(hwnd, IDD_TICKET_LIST_TITLE);
+
+       if (hwnditem == NULL)
+               return 0;
+
+       windowrect(hwnditem, hwnd, &r);
+       hmargin = r.left;
+       vmargin = r.top;
+       cx = cxdlg - 2 * hmargin;
+       cy = r.bottom - r.top;
+       MoveWindow(hwnditem, r.left, r.top, cx, cy, TRUE);
+
+       /*
+        * The buttons
+        */
+       cx = 0;
+
+       for (i = IDD_MIN_BUTTON; i <= IDD_MAX_BUTTON; i++) {
+               hwnditem = GetDlgItem(hwnd, i);
+               windowrect(hwnditem, hwnd, &r);
+               if (i == IDD_MIN_BUTTON)
+                       hmargin = r.left;
+
+               cx += r.right - r.left;
+       }
+
+       gap = (cxdlg - 2 * hmargin - cx) / (IDD_MAX_BUTTON - IDD_MIN_BUTTON);
+       left = hmargin;
+       for (i = IDD_MIN_BUTTON; i <= IDD_MAX_BUTTON; i++) {
+               hwnditem = GetDlgItem(hwnd, i);
+               windowrect(hwnditem, hwnd, &r);
+               editbottom = -r.top;
+               cx = r.right - r.left;
+               cy = r.bottom - r.top;
+               r.top = rdlg.bottom - vmargin - cy;
+               MoveWindow(hwnditem, left, r.top, cx, cy, TRUE);
+
+               left += cx + gap;
+       }
+
+       /*
+        * Edit fields
+        */
+       editbottom += r.top;
+
+       cx = 0;
+       for (i = IDD_MIN_EDIT; i <= IDD_MAX_EDIT; i++) {
+               hwnditem = GetDlgItem(hwnd, i);
+               windowrect(hwnditem, hwnd, &r);
+
+               if (i == IDD_MIN_EDIT) {
+                       gap = r.right;
+                       hmargin = r.left;
+                       editbottom += r.bottom;
+                       titlebottom = -r.top;
+               }
+               if (i == IDD_MIN_EDIT + 1)
+                       gap = r.left - gap;
+
+               cx += r.right - r.left;
+       }
+
+       cx = cxdlg - 2 * hmargin - (IDD_MAX_EDIT - IDD_MIN_EDIT) * gap;
+       cx = cx / (IDD_MAX_EDIT - IDD_MIN_EDIT + 1);
+       left = hmargin;
+
+       for (i = IDD_MIN_EDIT; i <= IDD_MAX_EDIT; i++) {
+               hwnditem = GetDlgItem(hwnd, i);
+               windowrect(hwnditem, hwnd, &r);
+               cy = r.bottom - r.top;
+               r.top = editbottom - cy;
+               MoveWindow(hwnditem, left, r.top, cx, cy, TRUE);
+               titleleft[i-IDD_MIN_EDIT] = left;
+
+               left += cx + gap;
+       }
+
+       /*
+        * Edit field titles
+        */
+       titlebottom += r.top;
+       windowrect(GetDlgItem(hwnd, IDD_MIN_TITLE), hwnd, &r);
+       titlebottom += r.bottom;
+       listbottom = -r.top;
+
+       for (i = IDD_MIN_TITLE; i <= IDD_MAX_TITLE; i++) {
+               hwnditem = GetDlgItem(hwnd, i);
+               windowrect(hwnditem, hwnd, &r);
+               cx = r.right - r.left;
+               cy = r.bottom - r.top;
+               r.top = titlebottom - cy;
+               MoveWindow(hwnditem, titleleft[i-IDD_MIN_TITLE], r.top, cx, cy, TRUE);
+       }
+
+       /*
+        * The list
+        */
+       listbottom = r.top - listgap;
+       hwnditem = GetDlgItem(hwnd, IDD_TICKET_LIST);
+       windowrect(hwnditem, hwnd, &r);
+       hmargin = r.left;
+       cx = cxdlg - 2 * hmargin;
+       cy = listbottom - r.top;
+       MoveWindow(hwnditem, r.left, r.top, cx, cy, TRUE);
+
+       return 0;
+
+} /* kwin_size */
+
+
+/*+
+ * Function: Process WM_GETMINMAXINFO messages
+ *
+ * Parameters:
+ *     hwnd - the window recieving the message.
+ *
+ *     wparam - none.
+ *
+ *     lparam - LPMINMAXINFO
+ *
+ * Returns: 0
+ */
+static LONG
+kwin_getminmaxinfo (
+       HWND hwnd,
+       WPARAM wparam,
+       LPARAM lparam)
+{
+       MINMAXINFO *lpmmi;
+
+       lpmmi = (MINMAXINFO *) lparam;
+       lpmmi->ptMinTrackSize.x = (KWIN_MIN_WIDTH * LOWORD(GetDialogBaseUnits())) / 4;
+       lpmmi->ptMinTrackSize.y = (KWIN_MIN_HEIGHT * HIWORD(GetDialogBaseUnits())) / 8;
+
+       return 0;
+
+} /*  kwin_getminmaxinfo */
+
+
+/*+
+ * Function: Process WM_TIMER messages
+ *
+ * Parameters:
+ *     hwnd - the window recieving the message.
+ *
+ *     wparam - the timer id.
+ * 
+ *     lparam - timer callback proceedure
+ *
+ * Returns: 0
+ */
+static LONG
+kwin_timer (
+       HWND hwnd,
+       WPARAM wparam,
+       LPARAM lparam)
+{
+       HWND hwndfocus;
+       time_t t;
+       time_t expiration;
+       BOOL expired;
+    #ifdef KRB4
+        CREDENTIALS c;
+           int ncred;
+           int i;
+           char service[ANAME_SZ];
+           char instance[INST_SZ];
+           char realm[REALM_SZ];
+    #endif
+    #ifdef KRB5
+        krb5_error_code code;
+        krb5_cc_cursor cursor;
+        krb5_creds cred;
+        int n;
+        char *s;
+    #endif
+
+       if (wparam != 1)
+               return DefDlgProc(hwnd, WM_TIMER, wparam, lparam);
+
+       expired = FALSE;
+       ticket_init_list(GetDlgItem(hwnd, IDD_TICKET_LIST));
+
+       if (alerted) {
+               if (IsIconic(hwnd))
+                       InvalidateRect(hwnd, NULL, TRUE);
+
+               return 0;
+       }
+
+    #ifdef KRB4
+           ncred = krb_get_num_cred();
+           for (i = 1; i <= ncred; i++) {
+                   krb_get_nth_cred(service, instance, realm, i);
+
+                   if (_stricmp(service, "krbtgt") == 0) {
+                /* Warn if ticket will expire w/i TIME_BUFFER seconds */
+                           krb_get_cred(service, instance, realm, &c);
+                           expiration = c.issue_date + (long) c.lifetime * 5L * 60L;
+                           t = TIME_BUFFER + time(NULL);
+
+                           if (t >= expiration) {
+                                   expired = TRUE;
+                    /* Don't alert because of stale tickets */
+                                   if (t >= expiration + KWIN_UPDATE_PERIOD / 1000) {
+                                           alerted = TRUE;
+
+                                           if (IsIconic(hwnd))
+                                                   InvalidateRect(hwnd, NULL, TRUE);
+                                           return 0;
+                                   }
+                                   break;
+                           }
+                   }
+           }
+    #endif
+
+    #ifdef KRB5
+        code = krb5_cc_start_seq_get (k5_context, k5_ccache, &cursor);
+
+        while (code == 0) {
+            code = krb5_cc_next_cred(k5_context, k5_ccache, &cursor, &cred);
+            if (code)
+                break;
+            n = krb5_princ_component(k5_context, cred.server, 0)->length;
+            s = krb5_princ_component(k5_context, cred.server, 0)->data;
+            if (n != KRB5_TGS_NAME_SIZE)
+                continue;
+            if (memcmp (KRB5_TGS_NAME, s, KRB5_TGS_NAME_SIZE))
+                continue;
+
+            /* Warn if ticket will expire w/i TIME_BUFFER seconds */
+            expiration = cred.times.endtime;
+            t = TIME_BUFFER + time(NULL);
+
+            if (t >= expiration) {
+                expired = TRUE;
+                /* Don't alert because of stale tickets */
+                if (t >= expiration + KWIN_UPDATE_PERIOD / 1000) {
+                    alerted = TRUE;
+
+                    if (IsIconic(hwnd))
+                        InvalidateRect(hwnd, NULL, TRUE);
+                    return 0;
+                }
+                break;
+            }
+        }
+        krb5_cc_end_seq_get(k5_context, k5_ccache, &cursor);
+    
+    #endif
+
+       if (!expired) {
+               if (IsIconic(hwnd))
+                       InvalidateRect(hwnd, NULL, TRUE);
+
+               return 0;
+       }
+
+       alerted = TRUE;
+
+       if (beep)
+               MessageBeep(MB_ICONEXCLAMATION);
+
+       if (alert) {
+               if (IsIconic(hwnd)) {
+                       hwndfocus = GetFocus();
+                       ShowWindow(hwnd, SW_RESTORE);
+                       SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0,
+                               SWP_NOACTIVATE | SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE);
+                       SetFocus(hwndfocus);
+               }
+
+               SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0,
+                       SWP_NOACTIVATE | SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE);
+
+               return 0;
+       }
+
+    if (IsIconic(hwnd))
+        InvalidateRect(hwnd, NULL, TRUE);
+
+    return 0;
+
+} /*  kwin_timer */
+
+
+/*+
+ * Function: Process WM_COMMAND messages
+ *
+ * Parameters:
+ *     hwnd - the window recieving the message.
+ *
+ *     wparam - id of the command item
+ *
+ *     lparam - LOWORD=hwnd of control, HIWORD=notification message.
+ *
+ * Returns: TRUE if initialized sucessfully, false otherwise.
+ */
+static LONG
+kwin_command (
+       HWND hwnd,
+       WPARAM wparam,
+       LPARAM lparam)
+{
+    char name[ANAME_SZ];
+    char instance[INST_SZ];
+    char realm[REALM_SZ];
+    char password[MAX_KPW_LEN];
+       HCURSOR hcursor;
+       BOOL blogin;
+       HMENU hmenu;
+       char menuitem[MAX_K_NAME_SZ + 3];
+       char copyright[128];
+       #ifdef KRB4
+        int lifetime;
+               int krc;
+       #endif
+       #ifdef KRB5
+        long lifetime;
+               krb5_error_code code;
+        krb5_principal principal;
+               krb5_creds creds;
+               krb5_principal server;
+               krb5_timestamp now;
+       #endif
+
+       #ifdef KRB4
+               EnableWindow(GetDlgItem(hwnd, IDD_TICKET_DELETE), krb_get_num_cred() > 0);
+       #endif
+
+       #ifdef KRB5
+               EnableWindow(GetDlgItem(hwnd, IDD_TICKET_DELETE), k5_get_num_cred() > 0);
+       #endif
+
+       GetDlgItemText(hwnd, IDD_LOGIN_NAME, name, sizeof(name));
+       trim(name);
+       blogin = strlen(name) > 0;
+
+       if (blogin) {
+               GetDlgItemText(hwnd, IDD_LOGIN_REALM, realm, sizeof(realm));
+               trim(realm);
+               blogin = strlen(realm) > 0;
+       }
+
+       if (blogin) {
+               GetDlgItemText(hwnd, IDD_LOGIN_PASSWORD, password, sizeof(password));
+               blogin = strlen(password) > 0;
+       }
+
+       EnableWindow(GetDlgItem(hwnd, IDD_LOGIN), blogin);
+
+       if (HIWORD(lparam) != BN_CLICKED && HIWORD(lparam) != 0 && HIWORD(lparam) != 1)
+               return FALSE;
+
+       if (wparam >= IDM_FIRST_LOGIN && wparam < IDM_FIRST_LOGIN + FILE_MENU_MAX_LOGINS) {
+               hmenu = GetMenu(hwnd);
+               assert(hmenu != NULL);
+
+               hmenu = GetSubMenu(hmenu, 0);
+               assert(hmenu != NULL);
+
+               if (!GetMenuString(hmenu, wparam, menuitem, sizeof(menuitem), MF_BYCOMMAND))
+                       return TRUE;
+
+               if (menuitem[0])
+                       kwin_init_name(hwnd, &menuitem[3]);
+
+               return TRUE;
+       }
+
+       switch (wparam) {
+       case IDM_EXIT:
+               if (isblocking)
+                       WSACancelBlockingCall();
+               WinHelp(hwnd, KERBEROS_HLP, HELP_QUIT, 0);
+               PostQuitMessage(0);
+
+               return TRUE;
+
+       case IDD_LOGIN:
+               if (isblocking)
+                       return TRUE;
+
+               GetDlgItemText(hwnd, IDD_LOGIN_NAME, name, sizeof(name));
+               trim(name);
+               GetDlgItemText(hwnd, IDD_LOGIN_INSTANCE, instance, sizeof(instance));
+               trim(instance);
+               GetDlgItemText(hwnd, IDD_LOGIN_REALM, realm, sizeof(realm));
+               trim(realm);
+               GetDlgItemText(hwnd, IDD_LOGIN_PASSWORD, password, sizeof(password));
+               trim(password);
+
+               hcursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
+               lifetime = GetPrivateProfileInt(INI_OPTIONS, INI_DURATION,
+                       DEFAULT_TKT_LIFE * 5, KERBEROS_INI);
+               start_blocking_hook(BLOCK_MAX_SEC);
+
+               #ifdef KRB4
+                       lifetime = (lifetime + 4) / 5;
+                       krc = krb_get_pw_in_tkt(name, instance, realm, "krbtgt", realm,
+                               lifetime, password);
+               #endif
+
+               #ifdef KRB5
+            code = krb5_parse_name(k5_context, name, &principal);
+                       code = krb5_cc_initialize(k5_context, k5_ccache, principal);
+                       memset(&creds, 0, sizeof(creds));
+                       creds.client = principal;
+
+                       code = krb5_build_principal_ext(k5_context, &server,
+                               krb5_princ_realm(k5_context, principal)->length,
+                               krb5_princ_realm(k5_context, principal)->data,
+                KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME,
+                               krb5_princ_realm(k5_context, principal)->length,
+                               krb5_princ_realm(k5_context, principal)->data, 0);
+
+                       creds.server = server;
+
+                       //code = krb5_os_localaddr(&address);
+                       code = krb5_timeofday(k5_context, &now);
+
+                       creds.times.starttime = 0;
+                       creds.times.endtime = now + 60L * lifetime;
+                       creds.times.renew_till = 0;
+
+                       code = krb5_get_in_tkt_with_password(k5_context, 0, NULL, NULL, 
+                               NULL, password, k5_ccache, &creds, 0);
+
+                       krb5_free_principal(k5_context, server);
+                       //krb5_free_addresses(k5_context, address);
+
+               #endif
+
+               end_blocking_hook();
+               SetCursor(hcursor);
+               kwin_set_default_focus(hwnd);
+
+               #ifdef KRB4
+                       if (krc != KSUCCESS) {
+                               MessageBox(hwnd, krb_get_err_text(krc), "",
+                                       MB_OK | MB_ICONEXCLAMATION);
+
+                               return TRUE;
+                       }
+               #endif
+
+               #ifdef KRB5
+                       if (code) {
+                               com_err (NULL, code, "while logging in");
+                               return TRUE;
+                       }
+            // ticket_init_list(GetDlgItem(hwnd, IDD_TICKET_LIST));
+
+               #endif
+
+               SetDlgItemText(hwnd, IDD_LOGIN_PASSWORD, "");
+               kwin_save_name(hwnd);
+               alerted = FALSE;
+
+               switch (action) {
+               case LOGIN_AND_EXIT:
+                       SendMessage(hwnd, WM_COMMAND, IDM_EXIT, 0);
+                       break;
+
+               case LOGIN_AND_MINIMIZE:
+                       ShowWindow(hwnd, SW_MINIMIZE);
+                       break;
+               }
+
+               return TRUE;
+
+       case IDD_TICKET_DELETE:
+               if (isblocking)
+                       return TRUE;
+
+               #ifdef KRB4
+               krc = dest_tkt();
+                       if (krc != KSUCCESS)
+                               MessageBox(hwnd, krb_get_err_text(krc), "",
+                                       MB_OK | MB_ICONEXCLAMATION);
+               #endif
+
+               #ifdef KRB5
+            code = k5_dest_tkt ();
+               // ticket_init_list(GetDlgItem(hwnd, IDD_TICKET_LIST));
+               #endif
+
+               kwin_set_default_focus(hwnd);
+               alerted = FALSE;
+
+               return TRUE;
+
+       case IDD_CHANGE_PASSWORD:
+               if (isblocking)
+                       return TRUE;
+               password_dialog(hwnd);
+               kwin_set_default_focus(hwnd);
+
+               return TRUE;
+
+       case IDM_OPTIONS:
+               if (isblocking)
+                       return TRUE;
+               opts_dialog(hwnd);
+
+               return TRUE;
+
+       case IDM_HELP_INDEX:
+               WinHelp(hwnd, KERBEROS_HLP, HELP_INDEX, 0);
+
+               return TRUE;
+
+    case 1234:
+               ticket_init_list(GetDlgItem(hwnd, IDD_TICKET_LIST));
+
+        return TRUE;
+
+       case IDM_ABOUT:
+               if (isblocking)
+                       return TRUE;
+
+               strcpy(copyright, "        Kerberos for Windows\n");
+               strcat(copyright, "\n                Version 1.00\n\n");
+               strcat(copyright, "          For support, contact:\n");
+               strcat(copyright, ORGANIZATION);
+               strcat(copyright, " - (415) 903-1400");
+               MessageBox(hwnd, copyright, "Kerberos", MB_OK);
+
+               return TRUE;
+       }
+
+       return FALSE;
+
+} /* kwin_command */
+
+
+/*+
+ * Function: Process WM_SYSCOMMAND messages by setting
+ *     the focus to the password or name on restore.
+ *
+ * Parameters:
+ *     hwnd - the window recieving the message.
+ *
+ *     wparam - the syscommand option.
+ *
+ *     lparam -
+ *
+ * Returns: 0
+ */
+static LONG
+kwin_syscommand (
+       HWND hwnd,
+       WPARAM wparam,
+       LPARAM lparam)
+{
+       if ((wparam & 0xFFF0) == SC_RESTORE)
+               kwin_set_default_focus(hwnd);
+
+       if ((wparam & 0xFFF0) == SC_CLOSE) {
+               SendMessage(hwnd, WM_COMMAND, IDM_EXIT, 0);
+
+               return 0;
+       }
+
+       return DefDlgProc(hwnd, WM_SYSCOMMAND, wparam, lparam);
+
+} /* kwin_syscommand */
+
+
+/*+
+ * Function: Process WM_PAINT messages by displaying an
+ *     informative icon when we are iconic.
+ *
+ * Parameters:
+ *     hwnd - the window recieving the message.
+ *
+ *     wparam - none
+ *
+ *     lparam - none
+ *
+ * Returns: 0
+ */
+static LONG
+kwin_paint (
+       HWND hwnd,
+       WPARAM wparam,
+       LPARAM lparam)
+{
+       HDC hdc;
+       PAINTSTRUCT ps;
+       HICON hicon;
+       time_t expiration = 0;
+       time_t dt;
+       char buf[20];
+       RECT r;
+       #ifdef KRB4
+               int i;
+               int ncred;
+               char service[ANAME_SZ];
+               char instance[INST_SZ];
+               char realm[REALM_SZ];
+               CREDENTIALS c;
+       #endif
+       #ifdef KRB5
+        krb5_error_code code;
+        krb5_cc_cursor cursor;
+        krb5_creds c;
+        int n;
+        char *service;
+       #endif
+
+       if (!IsIconic(hwnd))
+               return DefDlgProc(hwnd, WM_PAINT, wparam, lparam);
+
+       #ifdef KRB4
+               ncred = krb_get_num_cred();
+
+               for (i = 1; i <= ncred; i++) {
+                       krb_get_nth_cred(service, instance, realm, i);
+                       krb_get_cred(service, instance, realm, &c);
+                       if (_stricmp(c.service, "krbtgt") == 0) {
+                               expiration = c.issue_date - kwin_get_epoch() + (long) c.lifetime * 5L * 60L;
+                               break;
+                       }
+               }
+       #endif
+
+       #ifdef KRB5
+        code = krb5_cc_start_seq_get (k5_context, k5_ccache, &cursor);
+
+        while (code == 0) {
+            code = krb5_cc_next_cred(k5_context, k5_ccache, &cursor, &c);
+            if (code)
+                break;
+            n = krb5_princ_component(k5_context, c.server, 0)->length;
+            service = krb5_princ_component(k5_context, c.server, 0)->data;
+            if (n != KRB5_TGS_NAME_SIZE)
+                continue;
+            if (memcmp (KRB5_TGS_NAME, service, KRB5_TGS_NAME_SIZE))
+                continue;
+            expiration = c.times.endtime;
+            break;
+                
+        }
+        krb5_cc_end_seq_get(k5_context, k5_ccache, &cursor);
+       #endif
+
+       hdc = BeginPaint(hwnd, &ps);
+       GetClientRect(hwnd, &r);
+       DefWindowProc(hwnd, WM_ICONERASEBKGND, hdc, 0);
+
+       if (expiration == 0) {
+               strcpy(buf, KWIN_DIALOG_NAME);
+               hicon = LoadIcon(hinstance, MAKEINTRESOURCE(IDI_KWIN));
+       }
+       else {
+               hicon = kwin_get_icon(expiration);
+               dt = (expiration - time(NULL)) / 60;
+
+               if (dt <= 0)
+                       sprintf(buf, "%s - %s", KWIN_DIALOG_NAME, "Expired");
+               else if (dt < 60) {
+                       dt %= 60;
+                       sprintf(buf, "%s - %ld min", KWIN_DIALOG_NAME, dt);
+               }
+               else {
+                       dt /= 60;
+                       sprintf(buf, "%s - %ld hr", KWIN_DIALOG_NAME, dt);
+               }
+
+               if (dt > 1)
+                       strcat(buf, "s");
+       }
+
+       DrawIcon(hdc, r.left, r.top, hicon);
+       EndPaint(hwnd, &ps);
+       SetWindowText(hwnd, buf);
+
+       return 0;
+
+} /* kwin_paint */
+
+
+/*+
+ * Function: Window proceedure for the Kerberos control panel dialog.
+ *
+ * Parameters:
+ *     hwnd - the window receiving the message.
+ *
+ *     message - the message to process.
+ *
+ *     wparam - wparam of the message.
+ *
+ *     lparam - lparam of the message.
+ *
+ * Returns: message dependent value.
+ */
+LRESULT __export CALLBACK
+kwin_wnd_proc (
+       HWND hwnd,
+       UINT message,
+       WPARAM wparam,
+       LPARAM lparam)
+{
+       LRESULT rc;
+    int n;
+
+       if (message == wm_kerberos_changed) {       /* Message from the ccache */
+               n = ticket_init_list(GetDlgItem(hwnd, IDD_TICKET_LIST));
+        EnableWindow(GetDlgItem(hwnd, IDD_TICKET_DELETE), n > 0);
+
+               return 0;
+       }
+
+       switch (message) {
+       case WM_GETMINMAXINFO:
+               rc = kwin_getminmaxinfo(hwnd, wparam, lparam);
+               return rc;
+
+       case WM_DESTROY:
+               rc = kwin_destroy(hwnd, wparam, lparam);
+               return rc;
+
+       case WM_MEASUREITEM:
+               if (wparam == IDD_TICKET_LIST) {
+                       rc = ticket_measureitem(hwnd, wparam, lparam);
+                       return rc;
+               }
+               break;
+
+       case WM_DRAWITEM:
+               if (wparam == IDD_TICKET_LIST) {
+                       rc = ticket_drawitem(hwnd, wparam, lparam);
+                       return rc;
+               }
+               break;
+
+       case WM_SETCURSOR:
+               if (isblocking) {
+                       SetCursor(LoadCursor(NULL, IDC_WAIT));
+                       return TRUE;
+               }
+               break;
+
+       case WM_SIZE:
+               rc = kwin_size(hwnd, wparam, lparam);
+               return rc;
+
+       case WM_SYSCOMMAND:
+               rc = kwin_syscommand(hwnd, wparam, lparam);
+               return rc;
+
+       case WM_TIMER:
+               rc = kwin_timer(hwnd, wparam, lparam);
+               return 0;
+
+       case WM_PAINT:
+               rc = kwin_paint(hwnd, wparam, lparam);
+               return rc;
+
+       case WM_ERASEBKGND:
+               if (!IsIconic(hwnd))
+                       break;
+               return 0;
+
+       case WM_KWIN_SETNAME:
+               kwin_init_name(hwnd, (char *) lparam);
+       }
+
+       return DefDlgProc(hwnd, message, wparam, lparam);
+
+} /* kwin_wnd_proc */
+
+
+/*+
+ * Function: Dialog procedure called by the dialog manager
+ *     to process dialog specific messages.
+ *
+ * Parameters:
+ *     hwnd - the dialog receiving the message.
+ *
+ *     message - the message to process.
+ *
+ *     wparam - wparam of the message.
+ *
+ *     lparam - lparam of the message.
+ *
+ * Returns: TRUE if message handled locally, FALSE otherwise.
+ */
+static BOOL CALLBACK
+kwin_dlg_proc (
+       HWND hwnd,
+       UINT message,
+       WPARAM wparam,
+       LPARAM lparam)
+{
+       LRESULT rc;
+
+       switch (message) {
+       case WM_INITDIALOG:
+               return kwin_initdialog(hwnd, wparam, lparam);
+
+       case WM_COMMAND:
+               rc = kwin_command(hwnd, wparam, lparam);
+               return TRUE;
+       }
+
+       return FALSE;
+
+} /* kwin_dlg_proc */
+
+
+/*+
+ * Function: Initialize the kwin dialog class.
+ *
+ * Parameters:
+ *     hinstance - the instance to initialize
+ *
+ * Returns: TRUE if dialog class registration is sucessfully, false otherwise.
+ */
+static BOOL
+kwin_init (
+       HINSTANCE hinstance)
+{
+       WNDCLASS class;
+       ATOM rc;
+
+       class.style = CS_HREDRAW | CS_VREDRAW;
+       class.lpfnWndProc = (WNDPROC) kwin_wnd_proc;
+       class.cbClsExtra = 0;
+       class.cbWndExtra = DLGWINDOWEXTRA;
+       class.hInstance = hinstance;
+       class.hIcon = NULL;
+//             LoadIcon(hinstance, MAKEINTRESOURCE(IDI_KWIN));
+       class.hCursor = NULL;
+       class.hbrBackground = NULL;
+       class.lpszMenuName = NULL;
+       class.lpszClassName = KWIN_DIALOG_CLASS;
+
+       rc = RegisterClass (&class);
+       assert(rc);
+
+       return rc;
+
+} /* kwin_init */
+
+
+/*+
+ * Function: Initialize the KWIN application.  This routine should
+ *     only be called if no previous instance of the application
+ *     exists.  Currently it only registers a class for the kwin
+ *     dialog type.
+ *
+ * Parameters:
+ *     hinstance - the instance to initialize
+ *
+ * Returns: TRUE if initialized sucessfully, false otherwise.
+ */
+static BOOL
+init_application (
+       HINSTANCE hinstance)
+{
+       BOOL rc;
+
+       #ifdef KRB4
+               wm_kerberos_changed = krb_get_notification_message();
+       #endif
+
+       #ifdef KRB5
+               wm_kerberos_changed = krb5_get_notification_message();
+       #endif
+
+       rc = kwin_init(hinstance);
+
+       return rc;
+
+} /* init_application */
+
+
+/*+
+ * Function: Quits the KWIN application.  This routine should
+ *     be called when the last application instance exits.
+ *
+ * Parameters:
+ *     hinstance - the instance which is quitting.
+ *
+ * Returns: TRUE if initialized sucessfully, false otherwise.
+ */
+static BOOL
+quit_application (
+       HINSTANCE hinstance)
+{
+       return TRUE;
+} /* quit_application */
+
+
+/*+
+ * Function: Initialize the current instance of the KWIN application.
+ *
+ * Parameters:
+ *     hinstance - the instance to initialize
+ *
+ *     ncmdshow - show flag to indicate wheather to come up minimized
+ *             or not.
+ *
+ * Returns: TRUE if initialized sucessfully, false otherwise.
+ */
+static BOOL
+init_instance (
+       HINSTANCE hinstance,
+       int ncmdshow)
+{
+    WORD versionrequested;
+    WSADATA wsadata;
+    int rc;
+       char buf[20];
+       int i;
+
+       versionrequested = 0x0101;                      /* We need version 1.1 */
+       rc = WSAStartup(versionrequested, &wsadata);
+    if (rc != 0) {
+               MessageBox(NULL, "Couldn't initialize Winsock library", "", MB_OK | MB_ICONSTOP);
+
+               return FALSE;
+       }
+
+    if (versionrequested != wsadata.wVersion) {
+               WSACleanup();
+               MessageBox(NULL, "Winsock version 1.1 not available", "", MB_OK | MB_ICONSTOP);
+
+               return FALSE;
+    }
+
+       /*
+        * Set up expiration action
+        */
+       GetPrivateProfileString(INI_EXPIRATION, INI_ALERT, "No",
+               buf, sizeof(buf), KERBEROS_INI);
+       alert = _stricmp(buf, "Yes") == 0;
+       GetPrivateProfileString(INI_EXPIRATION, INI_BEEP, "No",
+               buf, sizeof(buf), KERBEROS_INI);
+       beep = _stricmp(buf, "Yes") == 0;
+
+       /*
+        * Load clock icons
+        */
+       for (i = IDI_FIRST_CLOCK; i <= IDI_LAST_CLOCK; i++)
+               kwin_icons[i - IDI_FIRST_CLOCK] = LoadIcon(hinstance, MAKEINTRESOURCE(i));
+
+       #ifdef KRB4
+           krb_start_session(NULL);
+       #endif
+
+       #ifdef KRB5
+               krb5_init_context(&k5_context);
+               krb5_init_ets(k5_context);
+               krb5_cc_default(k5_context, &k5_ccache);
+       #endif
+
+       return TRUE;
+
+} /* init_instance */
+
+
+/*+
+ * Function: Quits the current instance of the KWIN application.
+ *
+ * Parameters:
+ *     hinstance - the instance to quit.
+ *
+ * Returns: TRUE if termination was sucessfully, false otherwise.
+ */
+static BOOL
+quit_instance (
+       HINSTANCE hinstance)
+{
+       int i;
+
+       #ifdef KRB4
+           krb_end_session((char *) NULL);
+       #endif
+
+    #ifdef KRB5     /* FIXME */
+        krb5_cc_close (k5_context, k5_ccache);
+    #endif
+
+       WSACleanup();
+
+       /*
+        * Unload clock icons
+        */
+       for (i = IDI_FIRST_CLOCK; i <= IDI_LAST_CLOCK; i++)
+               DestroyIcon(kwin_icons[i - IDI_FIRST_CLOCK]);
+
+       return TRUE;
+
+} /* quit_instance */
+
+
+/*+
+ * Function: Main routine called on program invocation.
+ *
+ * Parameters:
+ *     hinstance - the current instance
+ *
+ *     hprevinstance - previous instance if one exists or NULL.
+ *
+ *     cmdline - the command line string passed by Windows.
+ *
+ *     ncmdshow - show flag to indicate wheather to come up minimized
+ *             or not.
+ *
+ * Returns: TRUE if initialized sucessfully, false otherwise.
+ */
+int PASCAL
+WinMain (
+       HINSTANCE hinst,
+       HINSTANCE hprevinstance,
+       LPSTR cmdline,
+       int ncmdshow)
+{
+       DLGPROC dlgproc;
+       HWND hwnd;
+       HACCEL haccel;
+       MSG msg;
+       char *p;
+       char buf[MAX_K_NAME_SZ + 9];
+       char name[MAX_K_NAME_SZ];
+
+       strcpy(buf, cmdline);
+       action = LOGIN_AND_RUN;
+       name[0] = 0;
+       p = strtok(buf, " ,");
+
+       while (p != NULL) {
+               if (_stricmp(p, "/exit") == 0)
+                       action = LOGIN_AND_EXIT;
+               else if (_stricmp(p, "/minimize") == 0)
+                       action = LOGIN_AND_MINIMIZE;
+               else
+                       strcpy(name, p);
+
+               p = strtok(NULL, " ,");
+       }
+
+       dlgncmdshow = ncmdshow;
+       hinstance = hinst;
+
+       /*
+        * If a previous instance of this application exits, bring it
+        * to the front and exit.
+        */
+       if (hprevinstance != NULL) {
+               hwnd = FindWindow(KWIN_DIALOG_CLASS, NULL);
+
+               if (IsWindow(hwnd) && IsWindowVisible(hwnd)) {
+                       if (GetWindowWord(hwnd, GWW_HINSTANCE) == hprevinstance) {
+                               if (name[0])
+                                       SendMessage(hwnd, WM_KWIN_SETNAME, 0, (LONG) name);
+
+                ShowWindow(hwnd, ncmdshow);
+                               SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0,
+                                       SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE);
+
+                               return FALSE;
+                       }
+               }
+       }
+
+       if (hprevinstance == NULL)
+               if (!init_application(hinstance))
+                       return FALSE;
+
+       if (!init_instance(hinstance, ncmdshow))
+               return FALSE;
+
+       dlgproc = (FARPROC) MakeProcInstance(kwin_dlg_proc, hinstance);
+       assert(dlgproc != NULL);
+
+       if (dlgproc == NULL)
+               return 1;
+
+       hwnd = CreateDialogParam(hinstance, MAKEINTRESOURCE (ID_KWIN),
+                               HWND_DESKTOP, dlgproc, (LONG) name);
+       assert(hwnd != NULL);
+
+       if (hwnd == NULL)
+               return 1;
+       haccel = LoadAccelerators(hinstance, MAKEINTRESOURCE(IDA_KWIN));
+       assert(hwnd != NULL);
+
+    while (GetMessage(&msg, NULL, 0, 0)) {
+               if (!TranslateAccelerator(hwnd, haccel, &msg) &&
+                       !IsDialogMessage(hwnd, &msg)) {
+               TranslateMessage(&msg);
+                       DispatchMessage(&msg);
+               }
+       }
+
+       DestroyWindow(hwnd);
+       FreeProcInstance((FARPROC) dlgproc);
+
+       return 0;
+
+} /* WinMain */
+
+
+#if 0
+
+       #define WM_ASYNC_COMPLETED (WM_USER + 1)
+       #define GETHOSTBYNAME_CLASS "krb_gethostbyname"
+       static HTASK htaskasync;                        /* Asynchronos call in progress */
+       static BOOL iscompleted;                        /* True when async call is completed */
+
+       /*
+       * This routine is called to cancel a blocking hook call within
+       * the Kerberos library.  The need for this routine arises due
+       * to bugs which exist in existing WINSOCK implementations.  We
+       * blocking gethostbyname with WSAASyncGetHostByName.  In order
+       * to cancel such an operation, this routine must be called.
+       * Applications may call this routine in addition to calls to
+       * WSACancelBlockingCall to get any sucy Async calls canceled.
+       * Return values are as they would be for WSACancelAsyncRequest.
+       */
+       int
+       krb_cancel_blocking_call(void)
+       {
+               if (htaskasync == NULL)
+                       return 0;
+               iscompleted = TRUE;
+
+               return WSACancelAsyncRequest(htask);
+
+       } /* krb_cancel_blocking_call */
+
+
+       /*
+       * Window proceedure for temporary Windows created in
+       * krb_gethostbyname.  Fields completion messages.
+       */
+       LRESULT __export CALLBACK krb_gethostbyname_wnd_proc(
+               HWND hwnd,
+               UINT message,
+               WPARAM wparam,
+               LPARAM lparam)
+       {
+               if (message == WM_ASYNC_COMPLETED) {
+                       iscompleted = TRUE;
+                       return 0;
+               }
+
+               return DefWindowProc(hwnd, message, wparam, lparam);
+
+       } /* krb_gethostbyname_wnd_proc */
+
+
+       /*
+       * The WINSOCK routine gethostbyname has a bug in both FTP and NetManage
+       * implementations which causes the blocking hook, if any, not to be
+       * called.  This routine attempts to work around the problem by using
+       * the async routines to emulate the functionality of the synchronous
+       * routines
+       */
+       struct hostent FAR *PASCAL FAR
+       krb_gethostbyname(
+               const char FAR *name)
+       {
+               HWND hwnd;
+               char buf[MAXGETHOSTSTRUCT];
+               BOOL FARPROC blockinghook;
+               WNDCLASS wc;
+               static BOOL isregistered;
+
+               blockinghook = WSASetBlockingHook(NULL);
+               WSASetBlockingHook(blockinghook);
+
+               if (blockinghook == NULL)
+                       return gethostbyname(name);
+
+               if (RegisterWndClass() == NULL)
+                       return gethostbyname(name);
+
+               if (!isregistered) {
+                       wc.style = 0;
+                       wc.lpfnWndProc = gethostbyname_wnd_proc;
+                       wc.cbClsExtra = 0;
+                       wc.cbWndExtra = 0;
+                       wc.hInstance = hlibinstance;
+                       wc.hIcon = NULL;
+                       wc.hCursor = NULL;
+                       wc.hbrBackground = NULL;
+                       wc.lpszMenuName  = NULL;
+                       wc.lpszClassName = GETHOSTBYNAME_CLASS;
+
+                       if (!RegisterClass(&wc))
+                               return gethostbyname(name);
+
+                       isregistered = TRUE;
+               }
+
+               hwnd = CreateWindow(GETHOSTBYNAME_CLASS, "", WS_OVERLAPPED,
+                       -100, -100, 0, 0, HWND_DESKTOP, NULL, hlibinstance, NULL);
+               if (hwnd == NULL)
+                       return gethostbyname(name);
+
+               htaskasync =
+                       WSAAsyncGetHostByName(hwnd, WM_ASYNC_COMPLETED, name, buf, sizeof(buf));
+               b = blockinghook(NULL);
+
+       } /* krb_gethostbyname */
+
+#endif
+
+#ifdef KRB5
+
+void
+debugbox () {
+    MessageBox (NULL, "foobar", "FOOBAR", IDOK | MB_ICONINFORMATION);
+}
+
+/*+
+ * Function: destroys all tickets in a k5 ccache
+ *
+ * Parameters:
+ *  none
+ *
+ * Returns: K5 error code (0 == success)
+ */
+static krb5_error_code
+k5_dest_tkt (void) {
+    krb5_error_code code;
+    krb5_principal princ;
+    char *defname;                              /* Name of cache */
+
+    if (code = krb5_cc_get_principal(k5_context, k5_ccache, &princ)) {
+        com_err (NULL, code, "while retrieving principal name");
+        return code;
+    }
+    if (code = krb5_unparse_name(k5_context, princ, &defname)) {
+        com_err (NULL, code, "while unparsing principal name");
+        return code;
+    }
+
+    code = krb5_cc_initialize (k5_context, k5_ccache, princ);
+    if (code != 0) {
+        com_err (NULL, code, "when re-initializing cache");
+        return code;
+    }
+
+    return code;
+}
+
+/*+
+ * 
+ * k5_get_num_cred
+ * 
+ * Returns: number of creds in the credential cache
+ * 
+ */
+static int
+k5_get_num_cred () {
+    krb5_error_code code;
+    krb5_cc_cursor cursor;
+    krb5_creds c;
+    int ncreds = 0;
+
+    if (code = krb5_cc_start_seq_get(k5_context, k5_ccache, &cursor)) {
+        if (code != KRB5_FCC_NOFILE)
+            com_err (NULL, code, "while starting to retrieve tickets");
+        return 0;
+    }
+
+    while (1) {
+        code = krb5_cc_next_cred(k5_context, k5_ccache, &cursor, &c);
+        if (code)
+            break;
+        ++ncreds;
+    }
+
+    if (code == KRB5_CC_END) {               /* End of ccache */
+        if (code = krb5_cc_end_seq_get(k5_context, k5_ccache, &cursor))
+            com_err (NULL, code, "while finishing ticket retrieval");
+    } else {
+        com_err (NULL, code, "while retrieving a ticket");
+        return 0;
+    }
+
+    return ncreds;
+}
+
+static int
+k5_get_num_cred2 () {
+    krb5_error_code code;
+    krb5_cc_cursor cursor;
+    krb5_creds c;
+    int ncreds = 0;
+
+    code = krb5_cc_start_seq_get (k5_context, k5_ccache, &cursor);
+    if (code == KRB5_FCC_NOFILE)
+        return 0;
+
+    while (1) {
+        code = krb5_cc_next_cred(k5_context, k5_ccache, &cursor, &c);
+        if (code)
+            break;
+        ++ncreds;
+    }
+    krb5_cc_end_seq_get(k5_context, k5_ccache, &cursor);
+
+    return ncreds;
+}
+
+/*+
+ * Function: Parses fullname into name, instance and realm
+ *
+ * Parameters:
+ *  name - buffer filled with name of user
+ *
+ *  realm - buffer filled with realm of user
+ *
+ *  fullname - string in form name.instance@realm
+ *
+ * Returns: 0
+ */
+static int
+k5_kname_parse (char *name, char *realm, char *fullname) {
+    char *ptr;                                  /* For parsing */
+
+    ptr = strchr (fullname, '@');               /* Name, realm separator */
+
+    if (ptr != NULL) {                          /* Get the name */
+        strncpy (name, fullname, ptr - fullname);
+        name[ptr - fullname] = '\0';
+    } else
+        strcpy (name, fullname);
+
+    if (ptr != NULL)                            /* Get realm */
+        strcpy (realm, ptr + 1);
+    else
+        *realm = '\0';
+
+    return 0;
+}
+#endif /* KRB5 */
diff --git a/src/windows/cns/cns.def b/src/windows/cns/cns.def
new file mode 100644 (file)
index 0000000..d0f2032
--- /dev/null
@@ -0,0 +1,9 @@
+NAME KWIN
+DESCRIPTION 'KWIN'
+EXETYPE WINDOWS
+STUB 'WINSTUB.EXE'
+SEGMENTS _TEXT CLASS 'CODE' PRELOAD
+CODE DISCARDABLE
+DATA PRELOAD MULTIPLE MOVEABLE
+HEAPSIZE 20480
+STACKSIZE 20480
diff --git a/src/windows/cns/cns.h b/src/windows/cns/cns.h
new file mode 100644 (file)
index 0000000..006804d
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * cns.h
+ *
+ * Public Domain -- written by Cygnus Support.
+ */
+
+/* Only one time, please */
+#ifndef        KWIN_DEFS
+#define KWIN_DEFS
+
+/*
+ * Menu items
+ */
+#define FILE_MENU_ITEMS 3
+#define FILE_MENU_MAX_LOGINS 5
+#define IDM_KWIN 1000
+       #define IDM_OPTIONS 1001
+       #define IDM_EXIT 1002
+       #define IDM_FIRST_LOGIN 1003
+
+       #define IDM_HELP_INDEX 1020
+       #define IDM_ABOUT 1021
+
+/*
+ * Accelerator
+ */
+#define IDA_KWIN 2000
+
+/*
+ * Dialog and dialog item ids
+ */
+#define KWIN_DIALOG_CLASS "KERBEROS"   /* class for kerberos dialog */
+#define KWIN_DIALOG_NAME "Kerberos"            /* name for kerberos dialog */
+
+#define ID_KWIN 100                                            /* the main kerberos dialog */
+       #define IDD_KWIN_FIRST 101
+               #define IDD_TICKET_LIST_TITLE 101
+               #define IDD_TICKET_LIST 102
+
+       #define IDD_MIN_TITLE 103
+               #define IDD_LOGIN_NAME_TITLE 103
+               #define IDD_LOGIN_INSTANCE_TITLE 104
+               #define IDD_LOGIN_REALM_TITLE 105
+               #define IDD_LOGIN_PASSWORD_TITLE 106
+       #define IDD_MAX_TITLE 106
+
+       #define IDD_MIN_EDIT 107
+               #define IDD_LOGIN_NAME 107
+               #define IDD_LOGIN_INSTANCE 108
+               #define IDD_LOGIN_REALM 109
+               #define IDD_LOGIN_PASSWORD 110
+       #define IDD_MAX_EDIT 110
+
+       #define IDD_MIN_BUTTON 111
+               #define IDD_CHANGE_PASSWORD 111
+               #define IDD_TICKET_DELETE 112
+               #define IDD_LOGIN 113
+       #define IDD_MAX_BUTTON 113
+
+       #define IDD_KWIN_LAST 113
+
+
+#define ID_PASSWORD 200
+       #define IDD_PASSWORD_NAME 204
+       #define IDD_PASSWORD_INSTANCE 205
+       #define IDD_PASSWORD_REALM 206
+       #define IDD_OLD_PASSWORD 207
+       #define IDD_NEW_PASSWORD1 208
+       #define IDD_NEW_PASSWORD2 209
+       #define IDD_PASSWORD_CR 210
+
+
+#define ID_OPTS 300
+       #define IDD_CONF 301
+       #define IDD_REALMS 302
+       #define IDD_LIFETIME 303
+       #define IDD_BEEP 304
+       #define IDD_ALERT 305
+
+/*
+ * Dialog dimensions
+ */
+#define KWIN_MIN_WIDTH 180
+#define KWIN_MIN_HEIGHT 110
+
+/*
+ * Icons
+ */
+#define IDI_KWIN 1             /* The program icon */
+
+#define ICON_WIDTH 30  /* Width used with icons */
+#define ICON_HEIGHT 20 /* Height used with icons */
+
+#define IDI_FIRST_CLOCK 2
+#define IDI_0_MIN 2            /* < 5 minutes left */
+#define IDI_5_MIN 3
+#define IDI_10_MIN 4
+#define IDI_15_MIN 5
+#define IDI_20_MIN 6
+#define IDI_25_MIN 7
+#define IDI_30_MIN 8
+#define IDI_35_MIN 9
+#define IDI_40_MIN 10
+#define IDI_45_MIN 11
+#define IDI_50_MIN 12
+#define IDI_55_MIN 13
+#define IDI_60_MIN 14
+#define IDI_EXPIRED 15
+#define IDI_TICKET 16
+#define IDI_LAST_CLOCK 16
+#define MAX_ICONS (IDI_LAST_CLOCK - IDI_FIRST_CLOCK + 1)
+
+#ifndef RC_INVOKED
+
+#ifdef KRB5
+       extern krb5_context k5_context;
+       extern krb5_ccache k5_ccache;
+#endif
+
+/*
+ * Prototypes
+ */
+
+time_t kwin_get_epoch(void);
+#ifdef KRB5
+   static krb5_error_code k5_dest_tkt (void);
+   static int k5_get_num_cred (void);
+   static int k5_kname_parse (char *name, char *realm, char *fullname);
+   static int k5_get_lrealm (char *realm);
+#endif
+
+HICON kwin_get_icon(time_t expiration);
+
+#endif /* RC_INVOKED */
+
+#endif
diff --git a/src/windows/cns/cns.ico b/src/windows/cns/cns.ico
new file mode 100644 (file)
index 0000000..645efa5
Binary files /dev/null and b/src/windows/cns/cns.ico differ
diff --git a/src/windows/cns/cns.rc b/src/windows/cns/cns.rc
new file mode 100644 (file)
index 0000000..f7d6d2c
--- /dev/null
@@ -0,0 +1,105 @@
+#include <windows.h>
+#include "cns.h"
+
+IDI_KWIN ICON PRELOAD cns.ico
+IDI_0_MIN ICON PRELOAD clock00.ico
+IDI_5_MIN ICON PRELOAD clock05.ico
+IDI_10_MIN ICON PRELOAD clock10.ico
+IDI_15_MIN ICON PRELOAD clock15.ico
+IDI_20_MIN ICON PRELOAD clock20.ico
+IDI_25_MIN ICON PRELOAD clock25.ico
+IDI_30_MIN ICON PRELOAD clock30.ico
+IDI_35_MIN ICON PRELOAD clock35.ico
+IDI_40_MIN ICON PRELOAD clock40.ico
+IDI_45_MIN ICON PRELOAD clock45.ico
+IDI_50_MIN ICON PRELOAD clock50.ico
+IDI_55_MIN ICON PRELOAD clock55.ico
+IDI_60_MIN ICON PRELOAD clock60.ico
+IDI_EXPIRED ICON PRELOAD clockexp.ico
+IDI_TICKET ICON PRELOAD clocktkt.ico
+
+IDM_KWIN MENU PRELOAD
+BEGIN
+       POPUP "&File"
+       BEGIN
+               MENUITEM "&Options...", IDM_OPTIONS
+               MENUITEM SEPARATOR
+               MENUITEM "E&xit", IDM_EXIT
+       END
+
+       POPUP "&Help"
+       BEGIN
+               MENUITEM "&Index\tF1", IDM_HELP_INDEX
+               MENUITEM "&Debug",     1234
+               MENUITEM SEPARATOR
+               MENUITEM "&About Kerberos...", IDM_ABOUT
+       END
+END
+
+IDA_KWIN ACCELERATORS PRELOAD
+BEGIN
+       VK_F1, IDM_HELP_INDEX, VIRTKEY
+END
+
+ID_KWIN DIALOG PRELOAD MOVEABLE DISCARDABLE 0, 0, 276, 114
+STYLE WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX
+CLASS KWIN_DIALOG_CLASS
+CAPTION KWIN_DIALOG_NAME
+MENU IDM_KWIN
+FONT 8, "Arial"
+BEGIN
+       CONTROL "      Start Time        End Time          Ticket", IDD_TICKET_LIST_TITLE, "STATIC", SS_LEFT | WS_CHILD | WS_VISIBLE | WS_GROUP, 16, 7, 240, 8
+       CONTROL "", IDD_TICKET_LIST, "LISTBOX", LBS_NOTIFY | LBS_DISABLENOSCROLL | LBS_OWNERDRAWFIXED | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_VSCROLL, 8, 18, 261, 52
+       CONTROL "&Name", IDD_LOGIN_NAME_TITLE, "STATIC", SS_LEFT | WS_CHILD | WS_VISIBLE | WS_GROUP, 6, 69, 27, 8
+       CONTROL "&Instance", IDD_LOGIN_INSTANCE_TITLE, "STATIC", SS_LEFT | WS_CHILD | WS_VISIBLE | WS_GROUP, 73, 69, 36, 8
+       CONTROL "&Realm", IDD_LOGIN_REALM_TITLE, "STATIC", SS_LEFT | WS_CHILD | WS_VISIBLE | WS_GROUP, 140, 69, 26, 8
+       CONTROL "&Password", IDD_LOGIN_PASSWORD_TITLE, "STATIC", SS_LEFT | WS_CHILD | WS_VISIBLE | WS_GROUP, 207, 69, 36, 8
+       CONTROL "", IDD_LOGIN_NAME, "EDIT", ES_LEFT | ES_AUTOHSCROLL | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 6, 79, 62, 12
+       CONTROL "", IDD_LOGIN_INSTANCE, "EDIT", ES_LEFT | ES_AUTOHSCROLL | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 73, 79, 62, 12
+       CONTROL "", IDD_LOGIN_REALM, "EDIT", ES_LEFT | ES_AUTOHSCROLL | ES_UPPERCASE | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 140, 79, 62, 12
+       CONTROL "", IDD_LOGIN_PASSWORD, "EDIT", ES_LEFT | ES_AUTOHSCROLL | ES_PASSWORD | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 207, 79, 62, 12
+       CONTROL "&Change Password...", IDD_CHANGE_PASSWORD, "BUTTON", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 6, 96, 74, 14
+       CONTROL "&Delete", IDD_TICKET_DELETE, "BUTTON", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 122, 96, 52, 14
+       CONTROL "&Login", IDD_LOGIN, "BUTTON", BS_DEFPUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 216, 96, 52, 14
+END
+
+ID_PASSWORD DIALOG 96, 50, 143, 129
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Change Password"
+FONT 8, "Arial"
+BEGIN
+       CONTROL "&Name:", -1, "STATIC", SS_LEFT | WS_CHILD | WS_VISIBLE, 5, 9, 53, 8
+       CONTROL "", IDD_PASSWORD_NAME, "EDIT", ES_LEFT | ES_AUTOHSCROLL | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_GROUP | WS_TABSTOP, 61, 6, 76, 12
+       CONTROL "&Instance:", -1, "STATIC", SS_LEFT | WS_CHILD | WS_VISIBLE, 5, 26, 53, 8
+       CONTROL "", IDD_PASSWORD_INSTANCE, "EDIT", ES_LEFT | ES_AUTOHSCROLL | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 61, 23, 76, 12
+       CONTROL "&Realm:", -1, "STATIC", SS_LEFT | WS_CHILD | WS_VISIBLE, 5, 43, 53, 8
+       CONTROL "", IDD_PASSWORD_REALM, "EDIT", ES_LEFT | ES_AUTOHSCROLL | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 61, 40, 76, 12
+       CONTROL "&Old Password:", -1, "STATIC", SS_LEFT | WS_CHILD | WS_VISIBLE, 5, 60, 53, 8
+       CONTROL "", IDD_OLD_PASSWORD, "EDIT", ES_LEFT | ES_AUTOHSCROLL | ES_PASSWORD | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 61, 57, 76, 12
+       CONTROL "&New Password:", -1, "STATIC", SS_LEFT | WS_CHILD | WS_VISIBLE, 5, 77, 53, 8
+       CONTROL "", IDD_NEW_PASSWORD1, "EDIT", ES_LEFT | ES_AUTOHSCROLL | ES_PASSWORD | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 61, 74, 76, 12
+       CONTROL "&New Password:", -1, "STATIC", SS_LEFT | WS_CHILD | WS_VISIBLE, 5, 94, 53, 8
+       CONTROL "", IDD_NEW_PASSWORD2, "EDIT", ES_LEFT | ES_AUTOHSCROLL | ES_PASSWORD | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 61, 91, 76, 12
+       CONTROL "", IDD_PASSWORD_CR, "BUTTON", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE, 5000, 5000, 0, 0
+       CONTROL "OK", IDOK, "BUTTON", BS_DEFPUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_GROUP | WS_TABSTOP, 13, 110, 52, 14
+       CONTROL "Cancel", IDCANCEL, "BUTTON", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 77, 110, 52, 14
+END
+
+ID_OPTS DIALOG 97, 52, 148, 107
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Kerberos Options"
+FONT 8, "Arial"
+BEGIN
+       CONTROL "&conf file:", -1, "STATIC", SS_LEFT | WS_CHILD | WS_VISIBLE, 5, 9, 40, 8
+       CONTROL "", IDD_CONF, "EDIT", ES_LEFT | ES_AUTOHSCROLL | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 60, 6, 82, 12
+       CONTROL "&realms file:", -1, "STATIC", SS_LEFT | WS_CHILD | WS_VISIBLE, 5, 26, 40, 8
+       CONTROL "", IDD_REALMS, "EDIT", ES_LEFT | ES_AUTOHSCROLL | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 60, 23, 82, 12
+       CONTROL "&Ticket lifetime:", -1, "STATIC", SS_LEFT | WS_CHILD | WS_VISIBLE, 5, 43, 53, 8
+       CONTROL "", IDD_LIFETIME, "EDIT", ES_LEFT | ES_AUTOHSCROLL | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 60, 40, 20, 12
+       CONTROL "minutes", -1, "STATIC", SS_LEFT | WS_CHILD | WS_VISIBLE, 85, 43, 46, 8
+       CONTROL "Action when login expires", 209, "BUTTON", BS_GROUPBOX | WS_CHILD | WS_VISIBLE | WS_GROUP, 5, 56, 138, 23
+       CONTROL "&Alert ", IDD_ALERT, "BUTTON", BS_AUTOCHECKBOX | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 31, 65, 28, 12
+       CONTROL "&Beep", IDD_BEEP, "BUTTON", BS_AUTOCHECKBOX | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 80, 65, 39, 12
+       CONTROL "OK", IDOK, "BUTTON", BS_DEFPUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 17, 87, 52, 14
+       CONTROL "Cancel", IDCANCEL, "BUTTON", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 81, 87, 52, 14
+END
diff --git a/src/windows/cns/krbini.h b/src/windows/cns/krbini.h
new file mode 100644 (file)
index 0000000..da5aa88
--- /dev/null
@@ -0,0 +1,23 @@
+/* Kerberos changed window message */
+#define WM_KERBEROS_CHANGED "Kerberos Changed"
+
+/* Kerberos Windows initialization file */
+#define KERBEROS_INI    "kerberos.ini"
+#define KERBEROS_HLP    "kerberos.hlp"
+#define INI_DEFAULTS    "Defaults"
+#define INI_USER        "User"            /* Default user */
+#define INI_INSTANCE    "Instance"        /* Default instance */
+#define INI_REALM       "Realm"           /* Default realm */
+#define INI_POSITION    "Position"
+#define INI_OPTIONS     "Options"
+#define INI_DURATION    "Duration"        /* Ticket duration in minutes */
+#define INI_EXPIRATION  "Expiration"      /* Action on expiration (alert or beep) */
+#define INI_ALERT       "Alert"
+#define INI_BEEP        "Beep"
+#define INI_FILES       "Files"
+#define INI_KRB_CONF    "krb.conf"        /* Location of krb.conf file */
+#define DEF_KRB_CONF    "krb.con"         /* Default name for krb.conf file */
+#define INI_KRB_REALMS  "krb.realms"      /* Location of krb.realms file */
+#define DEF_KRB_REALMS  "krb.rea"         /* Default name for krb.realms file */
+#define INI_RECENT_LOGINS "Recent Logins"    
+#define INI_LOGIN       "Login"
diff --git a/src/windows/cns/makefile b/src/windows/cns/makefile
new file mode 100644 (file)
index 0000000..8dc8e54
--- /dev/null
@@ -0,0 +1,79 @@
+# makefile: Constructs the Kerberos for Windows ticket manager
+# Works for both k4 and k5 releases.
+#
+NAME    = cns
+OBJS    = cns.obj tktlist.obj
+
+##### Options
+DEBUG   = 1
+!IF ! defined(KVERSION)
+KVERSION = 5
+!endif
+KRB     = KRB$(KVERSION)
+
+!if $(KVERSION) == 4
+BUILDTOP = ..
+LIBDIR          = $(BUILDTOP)\lib\krb
+KLIB    = $(LIBDIR)\kerberos.lib 
+WLIB    = $(LIBDIR)\winsock.lib
+INCLUDES = /I$(BUILDTOP)\include
+!endif
+
+!if $(KVERSION) == 5
+BUILDTOP        =..\..
+LIBDIR  = $(BUILDTOP)\lib
+KLIB    = $(LIBDIR)\libkrb5.lib
+WLIB    = $(LIBDIR)\winsock.lib
+INCLUDES = /I$(BUILDTOP)\include /I$(BUILDTOP)\include\krb5
+
+RM      = $(BUILDTOP)\config\rm.bat
+WHAT    = windows
+OBJEXT  = obj
+!endif
+
+##### C Compiler
+CC      = cl
+CFLAGS_RELEASE = /f- /nologo /W3 /AL /Gw /Gy /Zp /O2 /DNDEBUG=1
+CFLAGS_DEBUG   = /f  /nologo /W3 /AL /Gw /Gy /Zp /O2 /Od /Zi
+!if $(DEBUG)
+CFLAGS          = $(CFLAGS_DEBUG) $(INCLUDES) /D$(KRB)=1
+!else
+CFLAGS          = $(CFLAGS_RELEASE) $(INCLUDES) /D$(KRB)=1
+!endif
+
+##### RC Compiler
+RC      = rc
+RFLAGS          = /nologo $(INCLUDES)
+
+##### Linker
+LINK    = link
+LIBS    = $(KLIB) $(WLIB)
+SYSLIBS  = libw llibcew
+!if $(DEBUG)
+LFLAGS          = /co /nologo /nod /nopackcode /map:full
+!else
+LFLAGS          = /nologo /nod /nopackcode
+!endif
+
+all:: makefile $(NAME).exe
+
+$(NAME).exe: $*.def $*.res $(OBJS) $(LIBS)
+       $(LINK) $(LFLAGS) $(OBJS), $@, $*.map, $(LIBS) $(SYSLIBS), $*.def
+       $(RC) $(RFLAGS) /k $*.res $@
+
+$(OBJS) cns.res: cns.h tktlist.h
+
+install:
+       copy cns.exe ..\floppy
+
+clean:: tidy
+       if exist *.exe del *.exe
+       if exist ..\floppy\cns.exe del ..\floppy\cns.exe
+
+tidy::
+       if exist *.obj del *.obj
+       if exist *.res del *.res
+       if exist *.map del *.map
+       if exist *.pdb del *.pdb
+       if exist *.err del *.err
+
diff --git a/src/windows/cns/tktlist.c b/src/windows/cns/tktlist.c
new file mode 100644 (file)
index 0000000..8eb94a5
--- /dev/null
@@ -0,0 +1,427 @@
+/*
+ * tktlist.c
+ *
+ * Handle all actions of the Kerberos ticket list.
+ *
+ * Copyright 1994 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#if !defined(KRB5) && !defined(KRB4)
+       #define KRB5 1
+#endif
+
+#include <windows.h>
+#include <stdio.h>
+#include <assert.h>
+#include <malloc.h>
+#include <string.h>
+#include <time.h>
+
+#ifdef KRB4
+       #include "mit-copyright.h"
+       #include "kerberos.h"
+#endif
+
+#ifdef KRB5
+       #define NEED_SOCKETS
+       #include "krb5.h"
+       #include "krbini.h"
+    #include "com_err.h"
+
+       #define DEFAULT_TKT_LIFE 120
+       #define         ANAME_SZ        40
+       #define         REALM_SZ        40
+       #define         SNAME_SZ        40
+       #define         INST_SZ         40
+       #define         MAX_KPW_LEN     128
+       /* include space for '.' and '@' */
+       #define         MAX_K_NAME_SZ   (ANAME_SZ + INST_SZ + REALM_SZ + 2)
+       #define ORGANIZATION "Cygnus Support"
+#endif
+
+#include "cns.h"
+#include "tktlist.h"
+
+/*
+ * Ticket information for a list line
+ */
+typedef struct {
+       BOOL ticket;            /* TRUE if this is a real ticket */
+    time_t issue_time; /* time_t of issue */
+       long lifetime;          /* Lifetime for ticket in 5 minute intervals */
+       char buf[0];            /* String to display */
+} TICKETINFO, *LPTICKETINFO;
+
+/*+
+ * Function: Returns a standard ctime date with day of week and year
+ *     removed.
+ *
+ * Parameters:
+ *     t - time_t date to convert
+ *
+ * Returns: A pointer to the adjusted time value.
+ */
+static char *
+short_date (long t) {
+       static char buf[26 - 4];
+       char *p;
+
+       p = ctime(&t);
+       assert(p != NULL);
+
+       strcpy (buf, p + 4);
+       buf[12] = '\0';
+
+       return buf;
+
+} /* short_date */
+
+
+/*++
+ * Function: Initializes and populates the ticket list with all existing
+ *     Kerberos tickets.
+ *
+ * Parameters:
+ *     hwnd - the window handle of the ticket window.
+ *
+ * Returns: Number of elements in the list or -1 on error
+ */
+int
+ticket_init_list (
+       HWND hwnd)
+{
+       int ncred;
+       LRESULT rc;
+       int l;
+       LPTICKETINFO lpinfo;
+    char buf[26+2 + 26+2 + ANAME_SZ+1 + INST_SZ+1 + REALM_SZ + 22];
+       #ifdef KRB4
+               int i;
+               time_t expiration;
+               char service[ANAME_SZ];
+               char instance[INST_SZ];
+               char realm[REALM_SZ];
+               CREDENTIALS c;
+       #endif
+       #ifdef KRB5
+               krb5_cc_cursor cursor;
+               krb5_error_code code;
+               krb5_creds c;
+        krb5_flags flags;
+        char *sname;                            /* Name of the service */
+       #endif
+
+       SendMessage(hwnd, WM_SETREDRAW, FALSE, 0);
+
+       rc = SendMessage(hwnd, LB_GETCOUNT, 0, 0);
+       assert(rc != LB_ERR);
+
+       if (rc > 0)
+               ticket_destroy(hwnd);
+
+       while (--rc >= 0)
+               SendMessage(hwnd, LB_DELETESTRING, (WPARAM) rc, 0);
+
+       #ifdef KRB4
+
+               ncred = krb_get_num_cred();
+               for (i = 1; i <= ncred; i++) {
+                       krb_get_nth_cred(service, instance, realm, i);
+                       krb_get_cred(service, instance, realm, &c);
+                       strcpy(buf, " ");
+                       strcat(buf, short_date(c.issue_date - kwin_get_epoch()));
+                       expiration = c.issue_date - kwin_get_epoch() + (long) c.lifetime * 5L * 60L;
+                       strcat(buf, "  ");
+                       strcat(buf, short_date(expiration));
+                       l = strlen(buf);
+                       sprintf(&buf[l], "  %s%s%s%s%s (%d)",
+                               c.service, (c.instance[0] ? "." : ""), c.instance,
+                               (c.realm[0] ? "@" : ""), c.realm, c.kvno);
+                       l = strlen(buf);
+
+                       lpinfo = (LPTICKETINFO) malloc(sizeof(TICKETINFO) + l + 1);
+                       assert(lpinfo != NULL);
+
+                       if (lpinfo == NULL)
+                               return -1;
+
+                       lpinfo->ticket = TRUE;
+                       lpinfo->issue_time = c.issue_date - kwin_get_epoch(); /* back to system time */
+                       lpinfo->lifetime = (long) c.lifetime * 5L * 60L;
+                       strcpy(lpinfo->buf, buf);
+
+                       rc = SendMessage(hwnd, LB_ADDSTRING, 0, (LPARAM) lpinfo);
+                       assert(rc >= 0);
+
+                       if (rc < 0)
+                               return -1;
+               }
+
+       #endif
+
+       #ifdef KRB5
+
+               ncred = 0;
+        flags = 0;
+        if (code = krb5_cc_set_flags(k5_context, k5_ccache, flags)) {
+            if (code != KRB5_FCC_NOFILE) {
+                com_err (NULL, code,
+                    "while setting cache flags (ticket cache %s)",
+                    krb5_cc_get_name(k5_context, k5_ccache));
+                return -1;
+            }
+        } else {
+            if (code = krb5_cc_start_seq_get(k5_context, k5_ccache, &cursor)) {
+                com_err (NULL, code, "while starting to retrieve tickets");
+                return -1;
+            }
+
+                   while (1) {
+                       code = krb5_cc_next_cred(k5_context, k5_ccache, &cursor, &c);
+                       if (code != 0)
+                               break;
+
+                       ncred++;
+                strcpy (buf, "  ");
+                strcat (buf, short_date (c.times.starttime - kwin_get_epoch()));
+                strcat (buf, "  ");
+                strcat (buf, short_date (c.times.endtime - kwin_get_epoch()));
+                strcat (buf, "  ");
+
+                code = krb5_unparse_name (k5_context, c.server, &sname);
+                if (code) {
+                    com_err (NULL, code, "while unparsing server name");
+                    break;
+                }
+                strcat (buf, sname);
+                free (sname);
+
+                       l = strlen(buf);
+                           lpinfo = (LPTICKETINFO) malloc(sizeof(TICKETINFO) + l + 1);
+                       assert(lpinfo != NULL);
+        
+                       if (lpinfo == NULL)
+                               return -1;
+
+                       lpinfo->ticket = TRUE;
+                       lpinfo->issue_time = c.times.starttime - kwin_get_epoch();
+                       lpinfo->lifetime = c.times.endtime - c.times.starttime;
+                       strcpy(lpinfo->buf, buf);
+
+                       rc = SendMessage(hwnd, LB_ADDSTRING, 0, (LPARAM) lpinfo);
+                       assert(rc >= 0);
+
+                       if (rc < 0)
+                               return -1;
+               }
+
+            if (code == KRB5_CC_END) {               /* End of ccache */
+                if (code = krb5_cc_end_seq_get(k5_context, k5_ccache, &cursor)) {
+                    com_err(NULL, code, "while finishing ticket retrieval");
+                    return -1;
+                }
+                flags = KRB5_TC_OPENCLOSE;          /* turns on OPENCLOSE mode */
+                if (code = krb5_cc_set_flags(k5_context, k5_ccache, flags)) {
+                    com_err(NULL, code, "while closing ccache");
+                    return -1;
+                }
+            } else {
+                com_err(NULL, code, "while retrieving a ticket");
+                return -1;
+            }
+        }
+       #endif
+
+       if (ncred <= 0) {
+               strcpy(buf, " No Tickets");
+               lpinfo = (LPTICKETINFO) malloc(sizeof(TICKETINFO) + strlen(buf) + 1);
+               assert(lpinfo != NULL);
+
+               if (lpinfo == NULL)
+                       return -1;
+
+               lpinfo->ticket = FALSE;
+               strcpy (lpinfo->buf, buf);
+               rc = SendMessage(hwnd, LB_ADDSTRING, 0, (LPARAM) lpinfo);
+               assert(rc >= 0);
+       }
+
+       SendMessage(hwnd, WM_SETREDRAW, TRUE, 0);
+
+       return ncred;
+
+} /* ticket_init_list */
+
+
+/*+
+ * Function: Destroy the ticket list.  Make sure to delete all
+ *     ticket entries created during ticket initialization.
+ *
+ * Parameters:
+ *     hwnd - the window handle of the ticket window.
+ */
+void
+ticket_destroy (
+       HWND hwnd)
+{
+       int i;
+       int n;
+       LRESULT rc;
+
+       n = (int) SendMessage(hwnd, LB_GETCOUNT, 0, 0);
+
+       for (i = 0; i < n; i++) {
+               rc = SendMessage(hwnd, LB_GETITEMDATA, i, 0);
+               assert(rc != LB_ERR);
+
+               if (rc != LB_ERR)
+                       free ((void *) rc);
+       }
+
+} /* ticket_destroy */
+
+
+/*+
+ * Function: Respond to the WM_MEASUREITEM message for the ticket list
+ *     by setting each list item up at 1/4" hight.
+ *
+ * Parameters:
+ *     hwnd - the window handle of the ticket window.
+ *
+ *     wparam - control id of the ticket list.
+ *
+ *     lparam - pointer to the MEASUREITEMSTRUCT.
+ *
+ * Returns: TRUE if message process, FALSE otherwise.
+ */
+LONG
+ticket_measureitem (
+       HWND hwnd,
+       WPARAM wparam,
+       LPARAM lparam)
+{
+       int logpixelsy;
+       LPMEASUREITEMSTRUCT lpmi;
+       HDC hdc;
+
+       lpmi = (LPMEASUREITEMSTRUCT) lparam;
+       hdc = GetDC(HWND_DESKTOP);
+       logpixelsy = GetDeviceCaps(hdc, LOGPIXELSY);
+       ReleaseDC(HWND_DESKTOP, hdc);
+       lpmi->itemHeight = logpixelsy / 4;      /* 1/4 inch */
+
+       return TRUE;
+
+} /* ticket_measureitem */
+
+
+/*+
+ * Function: Respond to the WM_DRAWITEM message for the ticket list
+ *     by displaying a single list item.
+ *
+ * Parameters:
+ *     hwnd - the window handle of the ticket window.
+ *
+ *     wparam - control id of the ticket list.
+ *
+ *     lparam - pointer to the DRAWITEMSTRUCT.
+ *
+ * Returns: TRUE if message process, FALSE otherwise.
+ */
+LONG ticket_drawitem(
+       HWND hwnd,
+       WPARAM wparam,
+       LPARAM lparam)
+{
+       LPDRAWITEMSTRUCT lpdi;
+       BOOL rc;
+       COLORREF bkcolor;
+       HBRUSH hbrush;
+       UINT textheight;
+       UINT alignment;
+       int left, top;
+       BOOL b;
+       LPTICKETINFO lpinfo;
+       HICON hicon;
+       #if 0
+               COLORREF textcolor;
+               COLORREF orgbkcolor;
+               COLORREF orgtextcolor;
+       #endif
+
+       lpdi = (LPDRAWITEMSTRUCT) lparam;
+       lpinfo = (LPTICKETINFO) lpdi->itemData;
+
+       if (lpdi->itemAction == ODA_FOCUS)
+               return TRUE;
+
+       #if 0
+               if (lpdi->itemState & ODS_SELECTED) {
+                       textcolor = GetSysColor(COLOR_HIGHLIGHTTEXT);
+                       bkcolor = GetSysColor(COLOR_HIGHLIGHT);
+
+                       orgtextcolor = SetTextColor(lpdi->hDC, textcolor);
+               assert(textcolor != 0x80000000);
+
+                       orgbkcolor = SetBkColor(lpdi->hDC, bkcolor);
+               assert(bkcolor != 0x80000000);
+               }
+               else
+       #endif
+
+       bkcolor = GetBkColor(lpdi->hDC);
+       hbrush = CreateSolidBrush(bkcolor);
+       assert(hbrush != NULL);
+
+       FillRect(lpdi->hDC, &(lpdi->rcItem), hbrush);
+       DeleteObject(hbrush);
+
+       /*
+        * Display the appropriate icon
+        */
+       if (lpinfo->ticket) {
+               hicon = kwin_get_icon(lpinfo->issue_time + lpinfo->lifetime);
+               left = lpdi->rcItem.left - (32 - ICON_WIDTH) / 2;
+               top = lpdi->rcItem.top;
+               top += (lpdi->rcItem.bottom - lpdi->rcItem.top - 32) / 2;
+
+               b = DrawIcon(lpdi->hDC, left, top, hicon);
+               assert(b);
+       }
+
+       /*
+        * Display centered string
+        */
+       textheight = HIWORD(GetTextExtent(lpdi->hDC, "X", 1));
+       alignment = SetTextAlign(lpdi->hDC, TA_TOP | TA_LEFT);
+
+       if (lpinfo->ticket)
+               left = lpdi->rcItem.left + ICON_WIDTH;
+       else
+               left = lpdi->rcItem.left;
+
+       top = lpdi->rcItem.top;
+       top += (lpdi->rcItem.bottom - lpdi->rcItem.top - textheight) / 2;
+       rc = TextOut(lpdi->hDC, left, top, (LPSTR) lpinfo->buf,
+                       strlen((LPSTR) lpinfo->buf));
+       assert(rc);
+
+       alignment = SetTextAlign(lpdi->hDC, alignment);
+
+       #if 0
+               if (lpdi->itemState & ODS_SELECTED) {
+                       textcolor = SetTextColor(lpdi->hDC, orgtextcolor);
+               assert(textcolor != 0x80000000);
+
+                       bkcolor = SetBkColor(lpdi->hDC, orgbkcolor);
+               assert(bkcolor != 0x80000000);
+               }
+
+       #endif
+
+       return TRUE;
+
+} /* ticket_drawitem */
diff --git a/src/windows/cns/tktlist.h b/src/windows/cns/tktlist.h
new file mode 100644 (file)
index 0000000..1ebd146
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * tktlist.h
+ *
+ * Handle all actions of the Kerberos ticket list.
+ *
+ * Copyright 1994 by the Massachusetts Institute of Technology. 
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>. 
+ */
+
+/* Only one time, please */
+#ifndef        TKTLIST_DEFS
+#define TKTLIST_DEFS
+
+/*
+ * Prototypes
+ */
+BOOL ticket_init_list(
+       HWND hwnd);
+
+void ticket_destroy(
+       HWND hwnd);
+
+LONG ticket_measureitem(
+       HWND hwnd,
+       WPARAM wparam,
+       LPARAM lparam);
+
+LONG ticket_drawitem(
+       HWND hwnd,
+       WPARAM wparam,
+       LPARAM lparam);
+
+#endif