summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeith Vetter <keithv@fusion.com>1995-03-22 20:17:41 +0000
committerKeith Vetter <keithv@fusion.com>1995-03-22 20:17:41 +0000
commitc3f88158d5a194b7e3fe1c655d45799521895847 (patch)
treeb17a500398c28db0436e7962c1e1c23685d4bac6
parent43e4214cf96717848a5b68b970eaab83f80591da (diff)
downloadkrb5-c3f88158d5a194b7e3fe1c655d45799521895847.tar.gz
krb5-c3f88158d5a194b7e3fe1c655d45799521895847.tar.xz
krb5-c3f88158d5a194b7e3fe1c655d45799521895847.zip
Added files to the windows/cns directory
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@5189 dc483132-0cff-0310-8789-dd5450dbe970
-rw-r--r--src/windows/cns/clock00.icobin0 -> 1086 bytes
-rw-r--r--src/windows/cns/clock05.icobin0 -> 1086 bytes
-rw-r--r--src/windows/cns/clock10.icobin0 -> 1086 bytes
-rw-r--r--src/windows/cns/clock15.icobin0 -> 1086 bytes
-rw-r--r--src/windows/cns/clock20.icobin0 -> 1086 bytes
-rw-r--r--src/windows/cns/clock25.icobin0 -> 1086 bytes
-rw-r--r--src/windows/cns/clock30.icobin0 -> 1086 bytes
-rw-r--r--src/windows/cns/clock35.icobin0 -> 1086 bytes
-rw-r--r--src/windows/cns/clock40.icobin0 -> 1086 bytes
-rw-r--r--src/windows/cns/clock45.icobin0 -> 1086 bytes
-rw-r--r--src/windows/cns/clock50.icobin0 -> 1086 bytes
-rw-r--r--src/windows/cns/clock55.icobin0 -> 1086 bytes
-rw-r--r--src/windows/cns/clock60.icobin0 -> 1086 bytes
-rw-r--r--src/windows/cns/clockexp.icobin0 -> 1086 bytes
-rw-r--r--src/windows/cns/clocktkt.icobin0 -> 1086 bytes
-rw-r--r--src/windows/cns/cns.c2878
-rw-r--r--src/windows/cns/cns.def9
-rw-r--r--src/windows/cns/cns.h136
-rw-r--r--src/windows/cns/cns.icobin0 -> 1086 bytes
-rw-r--r--src/windows/cns/cns.rc105
-rw-r--r--src/windows/cns/krbini.h23
-rw-r--r--src/windows/cns/makefile79
-rw-r--r--src/windows/cns/tktlist.c427
-rw-r--r--src/windows/cns/tktlist.h35
24 files changed, 3692 insertions, 0 deletions
diff --git a/src/windows/cns/clock00.ico b/src/windows/cns/clock00.ico
new file mode 100644
index 0000000000..1c2e424c83
--- /dev/null
+++ b/src/windows/cns/clock00.ico
Binary files differ
diff --git a/src/windows/cns/clock05.ico b/src/windows/cns/clock05.ico
new file mode 100644
index 0000000000..1e092832be
--- /dev/null
+++ b/src/windows/cns/clock05.ico
Binary files differ
diff --git a/src/windows/cns/clock10.ico b/src/windows/cns/clock10.ico
new file mode 100644
index 0000000000..15e00b24af
--- /dev/null
+++ b/src/windows/cns/clock10.ico
Binary files differ
diff --git a/src/windows/cns/clock15.ico b/src/windows/cns/clock15.ico
new file mode 100644
index 0000000000..93a52866c8
--- /dev/null
+++ b/src/windows/cns/clock15.ico
Binary files differ
diff --git a/src/windows/cns/clock20.ico b/src/windows/cns/clock20.ico
new file mode 100644
index 0000000000..5fd55dad65
--- /dev/null
+++ b/src/windows/cns/clock20.ico
Binary files differ
diff --git a/src/windows/cns/clock25.ico b/src/windows/cns/clock25.ico
new file mode 100644
index 0000000000..fc163fa23d
--- /dev/null
+++ b/src/windows/cns/clock25.ico
Binary files differ
diff --git a/src/windows/cns/clock30.ico b/src/windows/cns/clock30.ico
new file mode 100644
index 0000000000..3dfd8458d2
--- /dev/null
+++ b/src/windows/cns/clock30.ico
Binary files differ
diff --git a/src/windows/cns/clock35.ico b/src/windows/cns/clock35.ico
new file mode 100644
index 0000000000..b508e881d6
--- /dev/null
+++ b/src/windows/cns/clock35.ico
Binary files differ
diff --git a/src/windows/cns/clock40.ico b/src/windows/cns/clock40.ico
new file mode 100644
index 0000000000..d7e64a3984
--- /dev/null
+++ b/src/windows/cns/clock40.ico
Binary files differ
diff --git a/src/windows/cns/clock45.ico b/src/windows/cns/clock45.ico
new file mode 100644
index 0000000000..e35b2008df
--- /dev/null
+++ b/src/windows/cns/clock45.ico
Binary files differ
diff --git a/src/windows/cns/clock50.ico b/src/windows/cns/clock50.ico
new file mode 100644
index 0000000000..b1eaa1c829
--- /dev/null
+++ b/src/windows/cns/clock50.ico
Binary files differ
diff --git a/src/windows/cns/clock55.ico b/src/windows/cns/clock55.ico
new file mode 100644
index 0000000000..845a7b3d78
--- /dev/null
+++ b/src/windows/cns/clock55.ico
Binary files differ
diff --git a/src/windows/cns/clock60.ico b/src/windows/cns/clock60.ico
new file mode 100644
index 0000000000..0e9d6ebd14
--- /dev/null
+++ b/src/windows/cns/clock60.ico
Binary files differ
diff --git a/src/windows/cns/clockexp.ico b/src/windows/cns/clockexp.ico
new file mode 100644
index 0000000000..6a22b90b94
--- /dev/null
+++ b/src/windows/cns/clockexp.ico
Binary files differ
diff --git a/src/windows/cns/clocktkt.ico b/src/windows/cns/clocktkt.ico
new file mode 100644
index 0000000000..dc4d246f4a
--- /dev/null
+++ b/src/windows/cns/clocktkt.ico
Binary files differ
diff --git a/src/windows/cns/cns.c b/src/windows/cns/cns.c
new file mode 100644
index 0000000000..3fc8913dc4
--- /dev/null
+++ b/src/windows/cns/cns.c
@@ -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
index 0000000000..d0f2032c73
--- /dev/null
+++ b/src/windows/cns/cns.def
@@ -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
index 0000000000..006804d12c
--- /dev/null
+++ b/src/windows/cns/cns.h
@@ -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
index 0000000000..645efa5ba0
--- /dev/null
+++ b/src/windows/cns/cns.ico
Binary files differ
diff --git a/src/windows/cns/cns.rc b/src/windows/cns/cns.rc
new file mode 100644
index 0000000000..f7d6d2c4cc
--- /dev/null
+++ b/src/windows/cns/cns.rc
@@ -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
index 0000000000..da5aa88b4c
--- /dev/null
+++ b/src/windows/cns/krbini.h
@@ -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
index 0000000000..8dc8e54360
--- /dev/null
+++ b/src/windows/cns/makefile
@@ -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
index 0000000000..8eb94a52f6
--- /dev/null
+++ b/src/windows/cns/tktlist.c
@@ -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
index 0000000000..1ebd146a75
--- /dev/null
+++ b/src/windows/cns/tktlist.h
@@ -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