From 1793a32f2464dc98ebada56908fe5b795ae00676 Mon Sep 17 00:00:00 2001
From: Jeffrey Altman <jaltman@secure-endpoints.com>
Date: Sun, 2 Apr 2006 04:28:26 +0000
Subject: [PATCH] Results from Kerberos Interop session:

 - 64-bit Windows compatibility

 - correct uninitialized variables

 - work without kerberos 4 libraries including krb524

 - add a mechanism to add and remove identities from
   the options dialog.   This allows a configuration
   to be specified using a separate file based ccache
   for each identity

 - work without availability of ccapi

 - force a renew of credentials on startup to support
   the case when MSLSA is the only credential cache

ticket: new

git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@17832 dc483132-0cff-0310-8789-dd5450dbe970
---
 src/windows/identity/kconfig/api.c            | 100 ++++++-----
 .../identity/kconfig/kconfiginternal.h        |   2 +-
 src/windows/identity/kcreddb/buf.c            |   2 +-
 src/windows/identity/kcreddb/identity.c       |  62 ++++---
 src/windows/identity/kcreddb/kcreddb.h        |   7 +
 src/windows/identity/kcreddb/type.c           |   2 +-
 src/windows/identity/kherr/kherr.c            |  42 +++--
 src/windows/identity/kherr/kherr.h            |  96 ++++++-----
 src/windows/identity/kherr/kherrinternal.h    |   4 +-
 src/windows/identity/kmm/kmm_registrar.c      |   4 +-
 src/windows/identity/kmm/kplugin.h            |   4 +-
 src/windows/identity/kmq/init.c               |  10 +-
 src/windows/identity/kmq/msgtype.c            |   2 +-
 .../identity/plugins/common/dynimport.c       |   2 +
 .../identity/plugins/common/krb5common.c      |  10 +-
 .../identity/plugins/krb4/errorfuncs.c        |   2 +-
 .../identity/plugins/krb4/krb4plugin.c        |   8 +
 .../identity/plugins/krb5/krb5configdlg.c     |  18 +-
 src/windows/identity/plugins/krb5/krb5funcs.c |  35 ++--
 .../identity/plugins/krb5/krb5identpro.c      |  34 +++-
 .../identity/plugins/krb5/krb5newcreds.c      |  17 +-
 src/windows/identity/ui/cfg_general_wnd.c     |  58 ++++++-
 src/windows/identity/ui/cfg_identities_wnd.c  | 155 ++++++++++++++++++
 src/windows/identity/ui/configwnd.c           |  34 +++-
 src/windows/identity/ui/credfuncs.c           |  55 +++++--
 src/windows/identity/ui/credfuncs.h           |   4 +-
 src/windows/identity/ui/credwnd.c             |  18 +-
 src/windows/identity/ui/htwnd.c               |  71 ++++----
 src/windows/identity/ui/lang/en_us/khapp.rc   |  34 +++-
 src/windows/identity/ui/main.c                |  10 +-
 src/windows/identity/ui/mainwnd.c             |   6 +-
 src/windows/identity/ui/newcredwnd.c          |   4 +-
 src/windows/identity/ui/resource.h            |  15 +-
 src/windows/identity/ui/statusbar.c           |  33 ++--
 src/windows/identity/uilib/configui.c         |  12 ++
 src/windows/identity/uilib/creddlg.c          |   4 +-
 src/windows/identity/uilib/khconfigui.h       |   5 +
 src/windows/identity/util/mstring.c           |   4 +-
 src/windows/identity/util/sync.c              |   8 +-
 39 files changed, 729 insertions(+), 264 deletions(-)

diff --git a/src/windows/identity/kconfig/api.c b/src/windows/identity/kconfig/api.c
index 72a20acbc..83aa0657c 100644
--- a/src/windows/identity/kconfig/api.c
+++ b/src/windows/identity/kconfig/api.c
@@ -166,33 +166,34 @@ khcint_handle_dup(kconf_handle * o)
 
 void 
 khcint_space_hold(kconf_conf_space * s) {
-    InterlockedIncrement(&(s->refcount));
+    EnterCriticalSection(&cs_conf_global);
+    s->refcount ++;
+    LeaveCriticalSection(&cs_conf_global);
 }
 
 void 
 khcint_space_release(kconf_conf_space * s) {
-    LONG l = InterlockedDecrement(&(s->refcount));
-    if(!l) {
-        EnterCriticalSection(&cs_conf_global);
+    khm_int32 l;
 
-        /* check again */
-        if (!l) {
-            if(s->regkey_machine)
-                RegCloseKey(s->regkey_machine);
-            if(s->regkey_user)
-                RegCloseKey(s->regkey_user);
-            s->regkey_machine = NULL;
-            s->regkey_user = NULL;
-
-            if (s->flags &
-                (KCONF_SPACE_FLAG_DELETE_M |
-                 KCONF_SPACE_FLAG_DELETE_U)) {
-                khcint_remove_space(s, s->flags);
-            }
-        }
+    EnterCriticalSection(&cs_conf_global);
 
-        LeaveCriticalSection(&cs_conf_global);
+    l = -- s->refcount;
+    if (l == 0) {
+        if(s->regkey_machine)
+            RegCloseKey(s->regkey_machine);
+        if(s->regkey_user)
+            RegCloseKey(s->regkey_user);
+        s->regkey_machine = NULL;
+        s->regkey_user = NULL;
+
+        if (s->flags &
+            (KCONF_SPACE_FLAG_DELETE_M |
+             KCONF_SPACE_FLAG_DELETE_U)) {
+            khcint_remove_space(s, s->flags);
+        }
     }
+
+    LeaveCriticalSection(&cs_conf_global);
 }
 
 /* case sensitive replacement for RegOpenKeyEx */
@@ -211,7 +212,7 @@ khcint_RegOpenKeyEx(HKEY hkey, LPCWSTR sSubKey, DWORD ulOptions,
     t = sSubKey;
 
     /* check for case insensitive prefix first */
-    if (!wcsnicmp(sSubKey, CONFIG_REGPATHW, ARRAYLENGTH(CONFIG_REGPATHW) - 1)) {
+    if (!_wcsnicmp(sSubKey, CONFIG_REGPATHW, ARRAYLENGTH(CONFIG_REGPATHW) - 1)) {
         HKEY hkt;
 
         t = sSubKey + (ARRAYLENGTH(CONFIG_REGPATHW) - 1);
@@ -378,7 +379,7 @@ khcint_RegCreateKeyEx(HKEY hKey,
     t = lpSubKey;
 
     /* check for case insensitive prefix first */
-    if (!wcsnicmp(lpSubKey, CONFIG_REGPATHW, ARRAYLENGTH(CONFIG_REGPATHW) - 1)) {
+    if (!_wcsnicmp(lpSubKey, CONFIG_REGPATHW, ARRAYLENGTH(CONFIG_REGPATHW) - 1)) {
         HKEY hkt;
 
         t = lpSubKey + (ARRAYLENGTH(CONFIG_REGPATHW) - 1);
@@ -475,7 +476,7 @@ khcint_RegCreateKeyEx(HKEY hKey,
             }
         }
 
-        if (!wcsnicmp(sk_name, t, cch) &&
+        if (!_wcsnicmp(sk_name, t, cch) &&
             (sk_name[cch] == L'\0' ||
              sk_name[cch] == L'~')) {
             long new_idx;
@@ -668,9 +669,9 @@ khcint_free_space(kconf_conf_space * r) {
 }
 
 khm_int32 
-khcint_open_space_int(kconf_conf_space * parent, 
-                      const wchar_t * sname, size_t n_sname, 
-                      khm_int32 flags, kconf_conf_space **result) {
+khcint_open_space(kconf_conf_space * parent, 
+                  const wchar_t * sname, size_t n_sname, 
+                  khm_int32 flags, kconf_conf_space **result) {
     kconf_conf_space * p;
     kconf_conf_space * c;
     HKEY pkey = NULL;
@@ -685,14 +686,14 @@ khcint_open_space_int(kconf_conf_space * parent,
     if(n_sname >= KCONF_MAXCCH_NAME || n_sname <= 0)
         return KHM_ERROR_INVALID_PARAM;
 
-    /*SAFE: buf: buffer size == KCONF_MAXCCH_NAME * wchar_t >
-      n_sname * wchar_t */
+    /* SAFE: buf: buffer size == KCONF_MAXCCH_NAME * wchar_t >
+       n_sname * wchar_t */
     wcsncpy(buf, sname, n_sname);
     buf[n_sname] = L'\0';
 
     /* see if there is already a config space by this name. if so,
-    return it.  Note that if the configuration space is specified in a
-    schema, we would find it here. */
+       return it.  Note that if the configuration space is specified
+       in a schema, we would find it here. */
     EnterCriticalSection(&cs_conf_global);
     c = TFIRSTCHILD(p);
     while(c) {
@@ -704,6 +705,18 @@ khcint_open_space_int(kconf_conf_space * parent,
     LeaveCriticalSection(&cs_conf_global);
 
     if(c) {
+
+        if (c->flags & KCONF_SPACE_FLAG_DELETED) {
+            if (flags & KHM_FLAG_CREATE) {
+                c->flags &= ~(KCONF_SPACE_FLAG_DELETED |
+                              KCONF_SPACE_FLAG_DELETE_M |
+                              KCONF_SPACE_FLAG_DELETE_U);
+            } else {
+                *result = NULL;
+                return KHM_ERROR_NOT_FOUND;
+            }
+        }
+
         khcint_space_hold(c);
         *result = c;
         return KHM_ERROR_SUCCESS;
@@ -842,7 +855,7 @@ khc_open_space(khm_handle parent, const wchar_t * cspace, khm_int32 flags,
                                              validated above */
         }
 
-        rv = khcint_open_space_int(p, str, end - str, flags, &c);
+        rv = khcint_open_space(p, str, end - str, flags, &c);
 
         if(KHM_SUCCEEDED(rv) && (*end == L'\\'
 #if 0
@@ -1756,7 +1769,7 @@ khc_get_type(khm_handle conf, wchar_t * value) {
     HKEY hku = NULL;
     kconf_conf_space * c;
     khm_int32 rv;
-    LONG hr;
+    LONG hr = ERROR_SUCCESS;
     DWORD type = 0;
 
     if(!khc_is_config_running())
@@ -1913,7 +1926,7 @@ khcint_remove_space(kconf_conf_space * c, khm_int32 flags) {
 #endif
     if (!p)
         return KHM_ERROR_INVALID_OPERATION;
-            
+
     cc = TFIRSTCHILD(c);
     while (cc) {
         cn = LNEXT(cc);
@@ -1931,6 +1944,21 @@ khcint_remove_space(kconf_conf_space * c, khm_int32 flags) {
         c->flags |= (flags &
                      (KCONF_SPACE_FLAG_DELETE_M |
                       KCONF_SPACE_FLAG_DELETE_U));
+
+        /* if all the registry spaces have been marked as deleted and
+           there is no schema, we should mark the space as deleted as
+           well.  Note that ideally we only need to check for stores
+           which have data corresponding to this configuration space,
+           but this is a bit problematic since we don't monitor the
+           registry for changes. */
+        if ((c->flags &
+             (KCONF_SPACE_FLAG_DELETE_M |
+              KCONF_SPACE_FLAG_DELETE_U)) ==
+            (KCONF_SPACE_FLAG_DELETE_M |
+             KCONF_SPACE_FLAG_DELETE_U) &&
+            (!c->schema || c->nSchema == 0))
+
+            c->flags |= KCONF_SPACE_FLAG_DELETED;
     }
 
     if (c->regpath && p->regpath) {
@@ -1969,8 +1997,6 @@ khc_remove_space(khm_handle conf) {
          space has any children left.  If there are none, check if the
          parent space is also marked for deletion.
     */
-    HKEY hku = NULL;
-    HKEY hkm = NULL;
     kconf_conf_space * c;
     khm_int32 rv = KHM_ERROR_SUCCESS;
     khm_int32 flags = 0;
@@ -2076,7 +2102,7 @@ khcint_load_schema_i(khm_handle parent, kconf_schema * schema,
     int state = 0;
     int end_found = 0;
     kconf_conf_space * thisconf = NULL;
-    khm_handle h;
+    khm_handle h = NULL;
 
     i=begin;
     while(!end_found) {
@@ -2158,7 +2184,7 @@ khcint_unload_schema_i(khm_handle parent, kconf_schema * schema,
     int state = 0;
     int end_found = 0;
     kconf_conf_space * thisconf = NULL;
-    khm_handle h;
+    khm_handle h = NULL;
 
     i=begin;
     while(!end_found) {
diff --git a/src/windows/identity/kconfig/kconfiginternal.h b/src/windows/identity/kconfig/kconfiginternal.h
index 64068f4a9..24929a989 100644
--- a/src/windows/identity/kconfig/kconfiginternal.h
+++ b/src/windows/identity/kconfig/kconfiginternal.h
@@ -62,9 +62,9 @@ typedef struct kconf_conf_space_t {
     TDCL(struct kconf_conf_space_t);
 } kconf_conf_space;
 
-//#define KCONF_SPACE_FLAG_SCHEMA 0x00000020
 #define KCONF_SPACE_FLAG_DELETE_U 0x00000040
 #define KCONF_SPACE_FLAG_DELETE_M 0x00000080
+#define KCONF_SPACE_FLAG_DELETED  0x00000100
 
 typedef struct kconf_conf_handle_t {
     khm_int32   magic;
diff --git a/src/windows/identity/kcreddb/buf.c b/src/windows/identity/kcreddb/buf.c
index 1811bc126..07a65a1b0 100644
--- a/src/windows/identity/kcreddb/buf.c
+++ b/src/windows/identity/kcreddb/buf.c
@@ -134,7 +134,7 @@ void kcdb_buf_alloc(kcdb_buf * buf, khm_size slot, khm_ui_2 id, khm_size cbsize)
         }
 
         if(buf->cb_used > f->offset + cbold) {
-            int i;
+            khm_size i;
 
             memmove(
                 ((BYTE *) buf->buffer) + (f->offset + cbnew),
diff --git a/src/windows/identity/kcreddb/identity.c b/src/windows/identity/kcreddb/identity.c
index b9b8194b1..07ceb5812 100644
--- a/src/windows/identity/kcreddb/identity.c
+++ b/src/windows/identity/kcreddb/identity.c
@@ -616,8 +616,12 @@ kcdb_identity_get_config(khm_handle vid,
                             flags | KCONF_FLAG_NOPARSENAME,
                             &hident);
 
-        if(KHM_FAILED(rv))
+        if(KHM_FAILED(rv)) {
+            EnterCriticalSection(&cs_ident);
+            id->flags &= ~KCDB_IDENT_FLAG_CONFIG;
+            LeaveCriticalSection(&cs_ident);
             goto _exit;
+        }
 
         EnterCriticalSection(&cs_ident);
         id->flags |= KCDB_IDENT_FLAG_CONFIG;
@@ -646,11 +650,16 @@ kcdbint_ident_post_message(khm_int32 op, kcdb_identity * id) {
 KHMEXP khm_int32 KHMAPI 
 kcdb_identity_hold(khm_handle vid) {
     kcdb_identity * id;
+
+    EnterCriticalSection(&cs_ident);
     if(kcdb_is_active_identity(vid)) {
         id = vid;
-        InterlockedIncrement(&(id->refcount));
-    } else
+        id->refcount++;
+    } else {
+        LeaveCriticalSection(&cs_ident);
         return KHM_ERROR_INVALID_PARAM;
+    }
+    LeaveCriticalSection(&cs_ident);
     return ERROR_SUCCESS;
 }
 
@@ -659,20 +668,23 @@ KHMEXP khm_int32 KHMAPI
 kcdb_identity_release(khm_handle vid) {
     kcdb_identity * id;
     khm_int32 refcount;
+
+    EnterCriticalSection(&cs_ident);
     if(kcdb_is_identity(vid)) {
         id = vid;
-        refcount = InterlockedDecrement(&(id->refcount));
+        refcount = --id->refcount;
         if(refcount == 0) {
-            EnterCriticalSection(&cs_ident);
             /* We only delete identities which do not have a
                configuration. */
             if (id->refcount == 0 &&
                 !(id->flags & KCDB_IDENT_FLAG_CONFIG))
                 kcdb_identity_delete(vid);
-            LeaveCriticalSection(&cs_ident);
         }
-    } else
+    } else {
+        LeaveCriticalSection(&cs_ident);
         return KHM_ERROR_INVALID_PARAM;
+    }
+    LeaveCriticalSection(&cs_ident);
     return ERROR_SUCCESS;
 }
 
@@ -1031,8 +1043,7 @@ kcdb_identity_get_attrib(khm_handle vid,
 }
 
 KHMEXP khm_int32 KHMAPI 
-kcdb_identity_get_attr_string(
-                              khm_handle vid,
+kcdb_identity_get_attr_string(khm_handle vid,
                               khm_int32 attr_id,
                               wchar_t * buffer,
                               khm_size * pcbbuf,
@@ -1285,15 +1296,16 @@ kcdb_identpro_compare_name(const wchar_t * name1,
     kcdb_ident_name_xfer namex;
     khm_int32 rv = 0;
 
+    /* Generally in kcdb_identpro_* functions we don't emulate
+       any behavior if the provider is not available, but lacking
+       a way to make this known, we emulate here */
+    rv = wcscmp(name1, name2);
+
     EnterCriticalSection(&cs_ident);
     if(kcdb_ident_sub != NULL) {
         sub = kcdb_ident_sub;
     } else {
         sub = NULL;
-        /* Generally in kcdb_identpro_* functions we don't emulate
-           any behavior if the provider is not available, but lacking
-           a way to make this known, we emulate here */
-        rv = wcscmp(name1, name2);
     }
     LeaveCriticalSection(&cs_ident);
 
@@ -1301,6 +1313,7 @@ kcdb_identpro_compare_name(const wchar_t * name1,
         ZeroMemory(&namex, sizeof(namex));
         namex.name_src = name1;
         namex.name_alt = name2;
+        namex.result = rv;
 
         kmq_send_sub_msg(sub,
                          KMSG_IDENT,
@@ -1310,7 +1323,7 @@ kcdb_identpro_compare_name(const wchar_t * name1,
 
         rv = namex.result;
     }
-    
+
     return rv;
 }
 
@@ -1334,8 +1347,7 @@ kcdb_identpro_set_default(khm_handle identity)
     LeaveCriticalSection(&cs_ident);
 
     if(sub != NULL) {
-        rv = kmq_send_sub_msg(
-                              sub,
+        rv = kmq_send_sub_msg(sub,
                               KMSG_IDENT,
                               KMSG_IDENT_SET_DEFAULT,
                               (identity != NULL),
@@ -1346,8 +1358,7 @@ kcdb_identpro_set_default(khm_handle identity)
 }
 
 KHMEXP khm_int32 KHMAPI 
-kcdb_identpro_set_searchable(
-                             khm_handle identity,
+kcdb_identpro_set_searchable(khm_handle identity,
                              khm_boolean searchable)
 {
     khm_handle sub;
@@ -1437,7 +1448,8 @@ kcdb_identpro_notify_create(khm_handle identity)
     return rv;
 }
 
-KHMEXP khm_int32 KHMAPI kcdb_identpro_get_ui_cb(void * rock)
+KHMEXP khm_int32 KHMAPI 
+kcdb_identpro_get_ui_cb(void * rock)
 {
     khm_handle sub;
     khm_int32 rv = KHM_ERROR_SUCCESS;
@@ -1463,12 +1475,12 @@ KHMEXP khm_int32 KHMAPI kcdb_identpro_get_ui_cb(void * rock)
     return rv;
 }
 
-KHMEXP khm_int32 KHMAPI kcdb_identity_enum(
-    khm_int32 and_flags,
-    khm_int32 eq_flags,
-    wchar_t * name_buf,
-    khm_size * pcb_buf,
-    khm_size * pn_idents)
+KHMEXP khm_int32 KHMAPI 
+kcdb_identity_enum(khm_int32 and_flags,
+                   khm_int32 eq_flags,
+                   wchar_t * name_buf,
+                   khm_size * pcb_buf,
+                   khm_size * pn_idents)
 {
     kcdb_identity * id;
     khm_int32 rv = KHM_ERROR_SUCCESS;
diff --git a/src/windows/identity/kcreddb/kcreddb.h b/src/windows/identity/kcreddb/kcreddb.h
index 7826a82c0..63d16252d 100644
--- a/src/windows/identity/kcreddb/kcreddb.h
+++ b/src/windows/identity/kcreddb/kcreddb.h
@@ -524,6 +524,13 @@ kcdb_identity_get_default(khm_handle * pvid);
 
 /*! \brief Get the configuration space for the identity. 
 
+    If the configuration space for the identity does not exist and the
+    flags parameter does not specify ::KHM_FLAG_CREATE, then the
+    function will return a failure code as specified in
+    ::khc_open_space().  Depending on whether or not a configuration
+    space was found, the ::KCDB_IDENT_FLAG_CONFIG flag will be set or
+    reset for the identity.
+
     \param[in] id Identity for which the configuraiton space is requested
 
     \param[in] flags Flags used when calling khc_open_space().  If \a
diff --git a/src/windows/identity/kcreddb/type.c b/src/windows/identity/kcreddb/type.c
index 30771c07a..baf5f9730 100644
--- a/src/windows/identity/kcreddb/type.c
+++ b/src/windows/identity/kcreddb/type.c
@@ -1275,7 +1275,7 @@ int _iv_is_in_spec(wchar_t *s, int n, wchar_t * spec)
         if(!e)
             e = b + wcslen(b);
     
-        if((e - b) == n  && !wcsnicmp(b, s, n)) {
+        if((e - b) == n  && !_wcsnicmp(b, s, n)) {
             return TRUE;
         }
 
diff --git a/src/windows/identity/kherr/kherr.c b/src/windows/identity/kherr/kherr.c
index 3b7a5d453..feecbe06c 100644
--- a/src/windows/identity/kherr/kherr.c
+++ b/src/windows/identity/kherr/kherr.c
@@ -281,22 +281,22 @@ void free_event_params(kherr_event * e) {
     if(parm_type(e->p1) == KEPT_STRINGT) {
         assert((void *) parm_data(e->p1));
         PFREE((void*) parm_data(e->p1));
-        e->p1 = (kherr_param) 0;
+        ZeroMemory(&e->p1, sizeof(e->p1));
     }
     if(parm_type(e->p2) == KEPT_STRINGT) {
         assert((void *) parm_data(e->p2));
         PFREE((void*) parm_data(e->p2));
-        e->p2 = (kherr_param) 0;
+        ZeroMemory(&e->p2, sizeof(e->p2));
     }
     if(parm_type(e->p3) == KEPT_STRINGT) {
         assert((void *) parm_data(e->p3));
         PFREE((void*) parm_data(e->p3));
-        e->p3 = (kherr_param) 0;
+        ZeroMemory(&e->p3, sizeof(e->p3));
     }
     if(parm_type(e->p4) == KEPT_STRINGT) {
         assert((void *) parm_data(e->p4));
         PFREE((void*) parm_data(e->p4));
-        e->p4 = (kherr_param) 0;
+        ZeroMemory(&e->p4, sizeof(e->p4));
     }
 }
 
@@ -460,7 +460,7 @@ void pick_err_event(kherr_context * c)
 static void arg_from_param(DWORD_PTR ** parm, kherr_param p) {
     int t;
 
-    if (p != 0) {
+    if (p.type != KEPT_NONE) {
         t = parm_type(p);
         if (t == KEPT_INT32 ||
             t == KEPT_UINT32 ||
@@ -493,8 +493,8 @@ static void resolve_string_resource(kherr_event * e,
                                     khm_int32 or_flag) {
     wchar_t tfmt[KHERR_MAXCCH_STRING];
     wchar_t tbuf[KHERR_MAXCCH_STRING];
-    size_t chars;
-    size_t bytes;
+    size_t chars = 0;
+    size_t bytes = 0;
 
     if(e->flags & if_flag) {
         if(e->h_module != NULL)
@@ -537,8 +537,8 @@ static void resolve_msg_resource(kherr_event * e,
                                 khm_int32 if_flag,
                                 khm_int32 or_flag) {
     wchar_t tbuf[KHERR_MAXCCH_STRING];
-    size_t chars;
-    size_t bytes;
+    size_t chars = 0;
+    size_t bytes = 0;
     DWORD_PTR args[8];
 
     if(e->flags & if_flag) {
@@ -725,7 +725,8 @@ kherr_reportf(const wchar_t * long_desc_fmt, ...) {
 
     e = kherr_report(KHERR_DEBUG_1,
                      NULL, NULL, NULL, buf, NULL, 0,
-                     KHERR_SUGGEST_NONE, 0, 0, 0, 0, KHERR_RF_CSTR_LONG_DESC
+                     KHERR_SUGGEST_NONE, _vnull(), _vnull(), _vnull(), _vnull(),
+                     KHERR_RF_CSTR_LONG_DESC
 #ifdef _WIN32
                      ,NULL
 #endif
@@ -757,7 +758,11 @@ kherr_reportf_ex(enum kherr_severity severity,
     va_end(vl);
 
     e = kherr_report(severity, NULL, facility, NULL, buf, NULL, facility_id,
-                     KHERR_SUGGEST_NONE, 0, 0, 0, 0, KHERR_RF_CSTR_LONG_DESC
+                     KHERR_SUGGEST_NONE,
+                     _vnull(),
+                     _vnull(),
+                     _vnull(),
+                     _vnull(), KHERR_RF_CSTR_LONG_DESC
 #ifdef _WIN32
                      ,hModule
 #endif
@@ -1024,7 +1029,7 @@ KHMEXP void KHMAPI kherr_push_new_context(khm_int32 flags)
 kherr_param dup_parm(kherr_param p) {
     if(parm_type(p) == KEPT_STRINGT) {
         wchar_t * d = PWCSDUP((wchar_t *)parm_data(p));
-        return kherr_val(KEPT_STRINGT, d);
+        return kherr_val(KEPT_STRINGT, (khm_ui_8) d);
     } else
         return p;
 }
@@ -1288,7 +1293,7 @@ KHMEXP kherr_param kherr_dup_string(const wchar_t * s)
     size_t cb_s;
 
     if (s == NULL)
-        return (kherr_param) 0;
+        return _vnull();
 
     if (FAILED(StringCbLength(s, KHERR_MAXCB_STRING, &cb_s)))
         cb_s = KHERR_MAXCB_STRING;
@@ -1303,3 +1308,14 @@ KHMEXP kherr_param kherr_dup_string(const wchar_t * s)
 
     return _tstr(dest);
 }
+
+
+#if 0
+KHMEXP kherr_param kherr_val(khm_octet ptype, khm_ui_8 pvalue) {
+    kherr_param p;
+    p.type = ptype;
+    p.data = pvalue;
+
+    return p;
+}
+#endif
diff --git a/src/windows/identity/kherr/kherr.h b/src/windows/identity/kherr/kherr.h
index 99e785622..795058764 100644
--- a/src/windows/identity/kherr/kherr.h
+++ b/src/windows/identity/kherr/kherr.h
@@ -92,21 +92,22 @@
 /*! \brief Parameter types
  */
 enum kherr_parm_types {
-  KEPT_INT32 = 1,
-  KEPT_UINT32,
-  KEPT_INT64,
-  KEPT_UINT64,
-  KEPT_STRINGC,                 /*!< String constant */
-  KEPT_STRINGT,                 /*!< String.  Will be freed using
-                                     free() when the event is freed */
-  KEPT_PTR                      /*!< Pointer type. */
+    KEPT_NONE = 0,
+    KEPT_INT32 = 1,
+    KEPT_UINT32,
+    KEPT_INT64,
+    KEPT_UINT64,
+    KEPT_STRINGC,               /*!< String constant */
+    KEPT_STRINGT,               /*!< String.  Will be freed using
+                                  free() when the event is freed */
+    KEPT_PTR                    /*!< Pointer type. */
 };
 
-#ifdef _WIN32
-typedef khm_ui_8 kherr_param;
-#else
-#error kherr_param undefined
-#endif
+
+typedef struct tag_kherr_param {
+    khm_octet type;
+    khm_ui_8  data;
+} kherr_param;
 
 /*! \brief Severity levels
 
@@ -637,33 +638,40 @@ kherr_reportf(const wchar_t * long_desc_fmt,
  */
 KHMEXP kherr_param kherr_dup_string(const wchar_t * s);
 
-/* convenience macros for specifying parameters for kherr_report */
-#define kherr_val(type,val) \
-    ((((kherr_param)(type)) << ((sizeof(kherr_param)-1)*8)) | (kherr_param) (val))
-
-#define _int32(i)   kherr_val(KEPT_INT32, i)
-#define _uint32(ui) kherr_val(KEPT_UINT32, ui)
-#define _int64(i)   kherr_val(KEPT_INT64, i)
-#define _uint64(ui) kherr_val(KEPT_UINT64, ui)
-#define _cstr(cs)   kherr_val(KEPT_STRINGC, cs)
-#define _tstr(ts)   kherr_val(KEPT_STRINGT, ts)
-#define _cptr(p)    kherr_val(KEPT_PTR, p)
+__inline KHMEXP kherr_param
+kherr_val(khm_octet ptype, khm_ui_8 pvalue) {
+    kherr_param p;
+
+    p.type = ptype;
+    p.data = pvalue;
+
+    return p;
+}
+
+#define _int32(i)   kherr_val(KEPT_INT32, (khm_ui_8) i)
+#define _uint32(ui) kherr_val(KEPT_UINT32, (khm_ui_8) ui)
+#define _int64(i)   kherr_val(KEPT_INT64, (khm_ui_8) i)
+#define _uint64(ui) kherr_val(KEPT_UINT64, (khm_ui_8) ui)
+#define _cstr(cs)   kherr_val(KEPT_STRINGC, (khm_ui_8) cs)
+#define _tstr(ts)   kherr_val(KEPT_STRINGT, (khm_ui_8) ts)
+#define _cptr(p)    kherr_val(KEPT_PTR, (khm_ui_8) p)
+#define _vnull()    kherr_val(KEPT_NONE, 0)
 #define _dupstr(s)  kherr_dup_string(s)
 
 /* convenience macros for calling kherr_report */
 #ifdef KHERR_HMODULE
 
 #define _report_cs0(severity, long_description)                 \
-    kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_description), NULL, KHERR_FACILITY_ID, 0, 0, 0, 0, 0, 0, KHERR_HMODULE)
+    kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_description), NULL, KHERR_FACILITY_ID, 0, _vnull(), _vnull(), _vnull(), _vnull(), 0, KHERR_HMODULE)
 
 #define _report_cs1(severity, long_description, p1)             \
-    kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_description), NULL, KHERR_FACILITY_ID, 0, p1, 0, 0, 0, 0, KHERR_HMODULE)
+    kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_description), NULL, KHERR_FACILITY_ID, 0, p1, _vnull(), _vnull(), _vnull(), 0, KHERR_HMODULE)
 
 #define _report_cs2(severity, long_description, p1, p2)         \
-    kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_description), NULL, KHERR_FACILITY_ID, 0, p1, p2, 0, 0, 0, KHERR_HMODULE)
+    kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_description), NULL, KHERR_FACILITY_ID, 0, p1, p2, _vnull(), _vnull(), 0, KHERR_HMODULE)
 
 #define _report_cs3(severity, long_description, p1, p2, p3)     \
-    kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_description), NULL, KHERR_FACILITY_ID, 0, p1, p2, p3, 0, 0, KHERR_HMODULE)
+    kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_description), NULL, KHERR_FACILITY_ID, 0, p1, p2, p3, _vnull(), 0, KHERR_HMODULE)
 
 #define _report_cs4(severity, long_description, p1, p2, p3, p4) \
     kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_description), NULL, KHERR_FACILITY_ID, 0, p1, p2, p3, p4, 0, KHERR_HMODULE)
@@ -671,16 +679,16 @@ KHMEXP kherr_param kherr_dup_string(const wchar_t * s);
 #else
 
 #define _report_cs0(severity, long_description)                 \
-    kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_description), NULL, KHERR_FACILITY_ID, 0, 0, 0, 0, 0, 0, NULL)
+    kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_description), NULL, KHERR_FACILITY_ID, 0, _vnull(), _vnull(), _vnull(), _vnull(), 0, NULL)
 
 #define _report_cs1(severity, long_description, p1)             \
-    kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_description), NULL, KHERR_FACILITY_ID, 0, p1, 0, 0, 0, 0, NULL)
+    kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_description), NULL, KHERR_FACILITY_ID, 0, p1, _vnull(), _vnull(), _vnull(), 0, NULL)
 
 #define _report_cs2(severity, long_description, p1, p2)         \
-    kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_description), NULL, KHERR_FACILITY_ID, 0, p1, p2, 0, 0, 0, NULL)
+    kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_description), NULL, KHERR_FACILITY_ID, 0, p1, p2, _vnull(), _vnull(), 0, NULL)
 
 #define _report_cs3(severity, long_description, p1, p2, p3)     \
-    kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_description), NULL, KHERR_FACILITY_ID, 0, p1, p2, p3, 0, 0, NULL)
+    kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_description), NULL, KHERR_FACILITY_ID, 0, p1, p2, p3, _vnull(), 0, NULL)
 
 #define _report_cs4(severity, long_description, p1, p2, p3, p4) \
     kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_description), NULL, KHERR_FACILITY_ID, 0, p1, p2, p3, p4, 0, NULL)
@@ -688,16 +696,16 @@ KHMEXP kherr_param kherr_dup_string(const wchar_t * s);
 
 #ifdef _WIN32
 #define _report_sr0(severity, long_desc_id)                     \
-    kherr_report((severity), NULL, KHERR_FACILITY, NULL, MAKEINTRESOURCE(long_desc_id), NULL, KHERR_FACILITY_ID, 0, 0, 0, 0, 0, KHERR_RF_RES_LONG_DESC, KHERR_HMODULE)
+    kherr_report((severity), NULL, KHERR_FACILITY, NULL, MAKEINTRESOURCE(long_desc_id), NULL, KHERR_FACILITY_ID, 0, _vnull(), _vnull(), _vnull(), _vnull(), KHERR_RF_RES_LONG_DESC, KHERR_HMODULE)
 
 #define _report_sr1(severity, long_desc_id, p1)                 \
-    kherr_report((severity), NULL, KHERR_FACILITY, NULL, MAKEINTRESOURCE(long_desc_id), NULL, KHERR_FACILITY_ID, 0, p1, 0, 0, 0, KHERR_RF_RES_LONG_DESC, KHERR_HMODULE)
+    kherr_report((severity), NULL, KHERR_FACILITY, NULL, MAKEINTRESOURCE(long_desc_id), NULL, KHERR_FACILITY_ID, 0, p1, _vnull(), _vnull(), _vnull(), KHERR_RF_RES_LONG_DESC, KHERR_HMODULE)
 
 #define _report_sr2(severity, long_desc_id, p1, p2)             \
-    kherr_report((severity), NULL, KHERR_FACILITY, NULL, MAKEINTRESOURCE(long_desc_id), NULL, KHERR_FACILITY_ID, 0, p1, p2, 0, 0, KHERR_RF_RES_LONG_DESC, KHERR_HMODULE)
+    kherr_report((severity), NULL, KHERR_FACILITY, NULL, MAKEINTRESOURCE(long_desc_id), NULL, KHERR_FACILITY_ID, 0, p1, p2, _vnull(), _vnull(), KHERR_RF_RES_LONG_DESC, KHERR_HMODULE)
 
 #define _report_sr3(severity, long_desc_id, p1, p2, p3)         \
-    kherr_report((severity), NULL, KHERR_FACILITY, NULL, MAKEINTRESOURCE(long_desc_id), NULL, KHERR_FACILITY_ID, 0, p1, p2, p3, 0, KHERR_RF_RES_LONG_DESC, KHERR_HMODULE)
+    kherr_report((severity), NULL, KHERR_FACILITY, NULL, MAKEINTRESOURCE(long_desc_id), NULL, KHERR_FACILITY_ID, 0, p1, p2, p3, _vnull(), KHERR_RF_RES_LONG_DESC, KHERR_HMODULE)
 
 #define _report_sr4(severity, long_desc_id, p1, p2, p3, p4)     \
     kherr_report((severity), NULL, KHERR_FACILITY, NULL, MAKEINTRESOURCE(long_desc_id), NULL, KHERR_FACILITY_ID, 0, p1, p2, p3, p4, KHERR_RF_RES_LONG_DESC, KHERR_HMODULE)
@@ -705,32 +713,32 @@ KHMEXP kherr_param kherr_dup_string(const wchar_t * s);
 
 #ifdef _WIN32
 #define _report_mr0(severity, long_desc_msg_id)                     \
-    kherr_report((severity), NULL, KHERR_FACILITY, NULL, (wchar_t *)(long_desc_msg_id), NULL, KHERR_FACILITY_ID, 0, 0, 0, 0, 0, KHERR_RF_MSG_LONG_DESC, KHERR_HMODULE)
+    kherr_report((severity), NULL, KHERR_FACILITY, NULL, (wchar_t *)(long_desc_msg_id), NULL, KHERR_FACILITY_ID, 0, _vnull(), _vnull(), _vnull(), _vnull(), KHERR_RF_MSG_LONG_DESC, KHERR_HMODULE)
 
 #define _report_mr1(severity, long_desc_msg_id, p1)                 \
-    kherr_report((severity), NULL, KHERR_FACILITY, NULL, (wchar_t *)(long_desc_msg_id), NULL, KHERR_FACILITY_ID, 0, p1, 0, 0, 0, KHERR_RF_MSG_LONG_DESC, KHERR_HMODULE)
+    kherr_report((severity), NULL, KHERR_FACILITY, NULL, (wchar_t *)(long_desc_msg_id), NULL, KHERR_FACILITY_ID, 0, p1, _vnull(), _vnull(), _vnull(), KHERR_RF_MSG_LONG_DESC, KHERR_HMODULE)
 
 #define _report_mr2(severity, long_desc_msg_id, p1, p2)             \
-    kherr_report((severity), NULL, KHERR_FACILITY, NULL, (wchar_t *)(long_desc_msg_id), NULL, KHERR_FACILITY_ID, 0, p1, p2, 0, 0, KHERR_RF_MSG_LONG_DESC, KHERR_HMODULE)
+    kherr_report((severity), NULL, KHERR_FACILITY, NULL, (wchar_t *)(long_desc_msg_id), NULL, KHERR_FACILITY_ID, 0, p1, p2, _vnull(), _vnull(), KHERR_RF_MSG_LONG_DESC, KHERR_HMODULE)
 
 #define _report_mr3(severity, long_desc_msg_id, p1, p2, p3)         \
-    kherr_report((severity), NULL, KHERR_FACILITY, NULL, (wchar_t *)(long_desc_msg_id), NULL, KHERR_FACILITY_ID, 0, p1, p2, p3, 0, KHERR_RF_MSG_LONG_DESC, KHERR_HMODULE)
+    kherr_report((severity), NULL, KHERR_FACILITY, NULL, (wchar_t *)(long_desc_msg_id), NULL, KHERR_FACILITY_ID, 0, p1, p2, p3, _vnull(), KHERR_RF_MSG_LONG_DESC, KHERR_HMODULE)
 
 #define _report_mr4(severity, long_desc_msg_id, p1, p2, p3, p4)     \
     kherr_report((severity), NULL, KHERR_FACILITY, NULL, (wchar_t *)(long_desc_msg_id), NULL, KHERR_FACILITY_ID, 0, p1, p2, p3, p4, KHERR_RF_MSG_LONG_DESC, KHERR_HMODULE)
 #endif
 
 #define _report_ts0(severity, long_desc_ptr)                     \
-    kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_desc_ptr), NULL, KHERR_FACILITY_ID, 0, 0, 0, 0, 0, KHERR_RF_FREE_LONG_DESC, NULL)
+    kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_desc_ptr), NULL, KHERR_FACILITY_ID, 0, _vnull(), _vnull(), _vnull(), _vnull(), KHERR_RF_FREE_LONG_DESC, NULL)
 
 #define _report_ts1(severity, long_desc_ptr, p1)                 \
-    kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_desc_ptr), NULL, KHERR_FACILITY_ID, 0, p1, 0, 0, 0, KHERR_RF_FREE_LONG_DESC, NULL)
+    kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_desc_ptr), NULL, KHERR_FACILITY_ID, 0, p1, _vnull(), _vnull(), _vnull(), KHERR_RF_FREE_LONG_DESC, NULL)
 
 #define _report_ts2(severity, long_desc_ptr, p1, p2)             \
-    kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_desc_ptr), NULL, KHERR_FACILITY_ID, 0, p1, p2, 0, 0, KHERR_RF_FREE_LONG_DESC, NULL)
+    kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_desc_ptr), NULL, KHERR_FACILITY_ID, 0, p1, p2, _vnull(), _vnull(), KHERR_RF_FREE_LONG_DESC, NULL)
 
 #define _report_ts3(severity, long_desc_ptr, p1, p2, p3)         \
-    kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_desc_ptr), NULL, KHERR_FACILITY_ID, 0, p1, p2, p3, 0, KHERR_RF_FREE_LONG_DESC, NULL)
+    kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_desc_ptr), NULL, KHERR_FACILITY_ID, 0, p1, p2, p3, _vnull(), KHERR_RF_FREE_LONG_DESC, NULL)
 
 #define _report_ts4(severity, long_desc_ptr, p1, p2, p3, p4)     \
     kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_desc_ptr), NULL, KHERR_FACILITY_ID, 0, p1, p2, p3, p4, KHERR_RF_FREE_LONG_DESC, NULL)
diff --git a/src/windows/identity/kherr/kherrinternal.h b/src/windows/identity/kherr/kherrinternal.h
index 2b43fd7f4..da33c596e 100644
--- a/src/windows/identity/kherr/kherrinternal.h
+++ b/src/windows/identity/kherr/kherrinternal.h
@@ -60,8 +60,8 @@ extern kherr_event * evt_free_list;
 extern kherr_handler_node * ctx_handlers;
 extern khm_size n_ctx_handlers;
 
-#define parm_type(p) ((int) (((p)>>((sizeof(kherr_param) - 1) * 8)) & 0xff))
-#define parm_data(p) ((p) & ~(((kherr_param)0xff)<<((sizeof(kherr_param) - 1) * 8)))
+#define parm_type(p) ((p).type)
+#define parm_data(p) ((p).data)
 
 void resolve_event_strings(kherr_event *);
 void attach_this_thread(void);
diff --git a/src/windows/identity/kmm/kmm_registrar.c b/src/windows/identity/kmm/kmm_registrar.c
index 73651d44c..742ccc7d7 100644
--- a/src/windows/identity/kmm/kmm_registrar.c
+++ b/src/windows/identity/kmm/kmm_registrar.c
@@ -861,8 +861,8 @@ void kmmint_init_module(kmm_module_i * m) {
                          KHERR_FACILITY_ID,
                          KHERR_SUGGEST_NONE,
                          _cstr(m->name),
-                         ((warn_e)? _cstr(warn_e->long_desc):0),
-                         0,0,
+                         ((warn_e)? _cstr(warn_e->long_desc):_vnull()),
+                         _vnull(),_vnull(),
                          KHERR_RF_MSG_SHORT_DESC |
                          ((warn_e)? KHERR_RF_MSG_SUGGEST: 0),
                          KHERR_HMODULE);
diff --git a/src/windows/identity/kmm/kplugin.h b/src/windows/identity/kmm/kplugin.h
index 99f94f1f4..e4e6003ee 100644
--- a/src/windows/identity/kmm/kplugin.h
+++ b/src/windows/identity/kmm/kplugin.h
@@ -90,7 +90,7 @@ KHMEXP khm_int32 KHMAPI init_module(kmm_module h_module);
 typedef khm_int32 (KHMAPI *init_module_t)(kmm_module);
 
 #if defined(_WIN64)
-#define EXP_INIT_MODULE "_init_module@8"
+#define EXP_INIT_MODULE "init_module"
 #elif defined(_WIN32)
 #define EXP_INIT_MODULE "_init_module@4"
 #else
@@ -133,7 +133,7 @@ KHMEXP khm_int32 KHMAPI exit_module(kmm_module h_module);
 typedef khm_int32 (KHMAPI *exit_module_t)(kmm_module);
 
 #if defined(_WIN64)
-#define EXP_EXIT_MODULE "_exit_module@8"
+#define EXP_EXIT_MODULE "exit_module"
 #elif defined(_WIN32)
 #define EXP_EXIT_MODULE "_exit_module@4"
 #else
diff --git a/src/windows/identity/kmq/init.c b/src/windows/identity/kmq/init.c
index 77b8dd0e1..00b8f6f4f 100644
--- a/src/windows/identity/kmq/init.c
+++ b/src/windows/identity/kmq/init.c
@@ -49,8 +49,14 @@ void kmqint_init(void) {
     khc_load_schema(NULL, schema_kmqconfig);
     khc_open_space(NULL, KMQ_CONF_SPACE_NAME, KHM_PERM_READ, &hconfig);
     if(hconfig) {
-        khc_read_int32(hconfig, KMQ_CONF_QUEUE_DEAD_TIMEOUT_NAME, &kmq_queue_dead_timeout);
-        khc_read_int32(hconfig, KMQ_CONF_CALL_DEAD_TIMEOUT_NAME, &kmq_call_dead_timeout);
+        khm_int32 t = 0;
+
+        khc_read_int32(hconfig, KMQ_CONF_QUEUE_DEAD_TIMEOUT_NAME, &t);
+        kmq_queue_dead_timeout = t;
+
+        khc_read_int32(hconfig, KMQ_CONF_CALL_DEAD_TIMEOUT_NAME, &t);
+        kmq_call_dead_timeout = t;
+
         khc_close_space(hconfig);
     }
     kmqint_init_msg_types();
diff --git a/src/windows/identity/kmq/msgtype.c b/src/windows/identity/kmq/msgtype.c
index 62a0133d2..3fd31ec17 100644
--- a/src/windows/identity/kmq/msgtype.c
+++ b/src/windows/identity/kmq/msgtype.c
@@ -252,7 +252,7 @@ void kmqint_msg_type_del_sub(kmq_msg_subscription *s) {
     \note Obtains ::cs_kmq_types
 */
 kmq_msg_subscription * kmqint_msg_type_del_sub_hwnd(khm_int32 t, HWND hwnd) {
-    kmq_msg_subscription *s;
+    kmq_msg_subscription *s = NULL;
 
     if(t < 0 || t > KMQ_MSG_TYPE_MAX)
         return NULL;
diff --git a/src/windows/identity/plugins/common/dynimport.c b/src/windows/identity/plugins/common/dynimport.c
index 016af86e9..7eecc7549 100644
--- a/src/windows/identity/plugins/common/dynimport.c
+++ b/src/windows/identity/plugins/common/dynimport.c
@@ -364,8 +364,10 @@ khm_int32 init_imports(void) {
 
 #define CKRV if(!imp_rv) goto _err_ret
 
+#ifndef _WIN64
     imp_rv = LoadFuncs(KRB4_DLL, k4_fi, &hKrb4, 0, 1, 0, 0);
     CKRV;
+#endif
 
     imp_rv = LoadFuncs(KRB5_DLL, k5_fi, &hKrb5, 0, 1, 0, 0);
     CKRV;
diff --git a/src/windows/identity/plugins/common/krb5common.c b/src/windows/identity/plugins/common/krb5common.c
index cb9d86bc5..de1cea4ab 100644
--- a/src/windows/identity/plugins/common/krb5common.c
+++ b/src/windows/identity/plugins/common/krb5common.c
@@ -91,7 +91,7 @@ khm_krb5_initialize(khm_handle ident,
 
     LPCSTR          functionName;
     int             freeContextFlag;
-    krb5_error_code	rc;
+    krb5_error_code	rc = 0;
     krb5_flags          flags = 0;
 
     if (pkrb5_init_context == NULL)
@@ -289,6 +289,12 @@ khm_krb5_find_ccache_for_identity(khm_handle ident, krb5_context *pctx,
 
     ctx = *pctx;
 
+    if (!pcc_initialize ||
+        !pcc_get_NC_info ||
+        !pcc_free_NC_info ||
+        !pcc_shutdown)
+        goto _skip_cc_iter;
+
     code = pcc_initialize(&cc_ctx, CC_API_VER_2, NULL, NULL);
     if (code)
         goto _exit;
@@ -337,6 +343,8 @@ khm_krb5_find_ccache_for_identity(khm_handle ident, krb5_context *pctx,
         cache = 0;
     }
 
+ _skip_cc_iter:
+
     if (KHM_SUCCEEDED(kmm_get_plugins_config(0, &csp_plugins))) {
         khc_open_space(csp_plugins, L"Krb5Cred\\Parameters",  0, &csp_params);
         khc_close_space(csp_plugins);
diff --git a/src/windows/identity/plugins/krb4/errorfuncs.c b/src/windows/identity/plugins/krb4/errorfuncs.c
index dba9f5dc6..5adc66b91 100644
--- a/src/windows/identity/plugins/krb4/errorfuncs.c
+++ b/src/windows/identity/plugins/krb4/errorfuncs.c
@@ -62,7 +62,7 @@ extern LPSTR (*Lerror_table_name)(long);
 
 HWND GetRootParent (HWND Child)
 {
-    HWND Last;
+    HWND Last = NULL;
     while (Child)
     {
         Last = Child;
diff --git a/src/windows/identity/plugins/krb4/krb4plugin.c b/src/windows/identity/plugins/krb4/krb4plugin.c
index 972ed4a01..fb6a88307 100644
--- a/src/windows/identity/plugins/krb4/krb4plugin.c
+++ b/src/windows/identity/plugins/krb4/krb4plugin.c
@@ -49,6 +49,9 @@ krb4_msg_system(khm_int32 msg_type, khm_int32 msg_subtype,
     switch(msg_subtype) {
     case KMSG_SYSTEM_INIT:
         {
+#ifdef _WIN64
+            return KHM_ERROR_NOT_IMPLEMENTED;
+#else
             kcdb_credtype ct;
             wchar_t buf[KCDB_MAXCCH_SHORT_DESC];
             size_t cbsize;
@@ -200,10 +203,14 @@ krb4_msg_system(khm_int32 msg_type, khm_int32 msg_subtype,
                                              &attr_id_krb5_flags))) {
                 rv = KHM_ERROR_UNKNOWN;
             }
+#endif
         }
         break;
 
     case KMSG_SYSTEM_EXIT:
+#ifdef _WIN64
+        return 0;
+#else
         if(credtype_id_krb4 >= 0)
             {
                 /* basically just unregister the credential type */
@@ -212,6 +219,7 @@ krb4_msg_system(khm_int32 msg_type, khm_int32 msg_subtype,
                 kcdb_credset_delete(krb4_credset);
             }
         break;
+#endif
     }
 
     return rv;
diff --git a/src/windows/identity/plugins/krb5/krb5configdlg.c b/src/windows/identity/plugins/krb5/krb5configdlg.c
index 0cb8b2ab7..ad64d4883 100644
--- a/src/windows/identity/plugins/krb5/krb5configdlg.c
+++ b/src/windows/identity/plugins/krb5/krb5configdlg.c
@@ -713,9 +713,9 @@ k5_write_config_data(k5_config_data * d) {
                         if (d->realms[r].kdcs[k].master)
                             pprofile_add_relation(profile, sec_master,
                                                   host);
-                        else
-                            pprofile_add_relation(profile, sec_kdcs,
-                                                  host);
+
+                        pprofile_add_relation(profile, sec_kdcs,
+                                              host);
 
                         if (d->realms[r].kdcs[k].admin)
                             pprofile_add_relation(profile, sec_admin,
@@ -836,9 +836,9 @@ k5_write_config_data(k5_config_data * d) {
                         if (d->realms[r].kdcs[k].master)
                             pprofile_add_relation(profile, sec_master,
                                                   host);
-                        else
-                            pprofile_add_relation(profile, sec_kdcs,
-                                                  host);
+
+                        pprofile_add_relation(profile, sec_kdcs,
+                                              host);
 
                         if (d->realms[r].kdcs[k].admin)
                             pprofile_add_relation(profile, sec_admin,
@@ -850,10 +850,6 @@ k5_write_config_data(k5_config_data * d) {
 
                     if (d->realms[r].kdcs[k].flags & K5_RKFLAG_MOD_MASTER) {
                         if (!d->realms[r].kdcs[k].master) {
-                            pprofile_update_relation(profile, sec_kdcs,
-                                                     host, NULL);
-                            pprofile_add_relation(profile, sec_kdcs,
-                                                  host);
                             pprofile_update_relation(profile, sec_master,
                                                      host, NULL);
                         } else {
@@ -861,8 +857,6 @@ k5_write_config_data(k5_config_data * d) {
                                                      host, NULL);
                             pprofile_add_relation(profile, sec_master,
                                                   host);
-                            pprofile_update_relation(profile, sec_kdcs,
-                                                     host, NULL);
                         }
 
                         d->realms[r].kdcs[k].flags &= ~K5_RKFLAG_MOD_MASTER;
diff --git a/src/windows/identity/plugins/krb5/krb5funcs.c b/src/windows/identity/plugins/krb5/krb5funcs.c
index af2d997c8..dab522c5d 100644
--- a/src/windows/identity/plugins/krb5/krb5funcs.c
+++ b/src/windows/identity/plugins/krb5/krb5funcs.c
@@ -568,12 +568,12 @@ _exit:
     return code;
 }
 
-long 
+long
 khm_krb5_list_tickets(krb5_context *krbv5Context)
 {
-    krb5_context	ctx;
+    krb5_context	ctx = NULL;
     krb5_ccache		cache = 0;
-    krb5_error_code	code;
+    krb5_error_code	code = 0;
     apiCB *             cc_ctx = 0;
     struct _infoNC **   pNCi = NULL;
     int                 i;
@@ -581,11 +581,20 @@ khm_krb5_list_tickets(krb5_context *krbv5Context)
     wchar_t *           ms = NULL;
     khm_size            cb;
 
-    ctx = NULL;
-    cache = NULL;
-
     kcdb_credset_flush(krb5_credset);
 
+    if((*krbv5Context == 0) && (code = (*pkrb5_init_context)(krbv5Context))) {
+        goto _exit;
+    }
+
+    ctx = (*krbv5Context);
+
+    if (!pcc_initialize ||
+        !pcc_get_NC_info ||
+        !pcc_free_NC_info ||
+        !pcc_shutdown)
+        goto _skip_cc_iter;
+
     code = pcc_initialize(&cc_ctx, CC_API_VER_2, NULL, NULL);
     if (code)
         goto _exit;
@@ -594,12 +603,6 @@ khm_krb5_list_tickets(krb5_context *krbv5Context)
     if (code) 
         goto _exit;
 
-    if((*krbv5Context == 0) && (code = (*pkrb5_init_context)(krbv5Context))) {
-        goto _exit;
-    }
-
-    ctx = (*krbv5Context);
-
     for(i=0; pNCi[i]; i++) {
         char ccname[KRB5_MAXCCH_CCNAME];
 
@@ -623,6 +626,8 @@ khm_krb5_list_tickets(krb5_context *krbv5Context)
         cache = 0;
     }
 
+ _skip_cc_iter:
+
     if (KHM_SUCCEEDED(khc_read_int32(csp_params, L"MsLsaList", &t)) && t) {
         code = (*pkrb5_cc_resolve)(ctx, "MSLSA:", &cache);
 
@@ -730,11 +735,11 @@ khm_krb5_renew_ident(khm_handle identity)
     krb5_creds          my_creds;
     krb5_data           *realm = 0;
 
+    memset(&my_creds, 0, sizeof(krb5_creds));
+
     if ( !pkrb5_init_context )
         goto cleanup;
 
-    memset(&my_creds, 0, sizeof(krb5_creds));
-
     code = khm_krb5_initialize(identity, &ctx, &cc);
     if (code) 
         goto cleanup;
@@ -1620,7 +1625,7 @@ khm_krb5_ms2mit(BOOL save_creds)
     return(FALSE);
 #else /* NO_KRB5 */
     krb5_context kcontext = 0;
-    krb5_error_code code;
+    krb5_error_code code = 0;
     krb5_ccache ccache=0;
     krb5_ccache mslsa_ccache=0;
     krb5_creds creds;
diff --git a/src/windows/identity/plugins/krb5/krb5identpro.c b/src/windows/identity/plugins/krb5/krb5identpro.c
index f12e6a9b9..f52e3441d 100644
--- a/src/windows/identity/plugins/krb5/krb5identpro.c
+++ b/src/windows/identity/plugins/krb5/krb5identpro.c
@@ -1248,6 +1248,28 @@ k5_ident_exit(khm_int32 msg_type,
     return KHM_ERROR_SUCCESS;
 }
 
+/* forward dcl */
+khm_int32 KHMAPI
+k5_ident_name_comp_func(const void * dl, khm_size cb_dl,
+                        const void * dr, khm_size cb_dr);
+
+static khm_int32
+k5_ident_compare_name(khm_int32 msg_type,
+                      khm_int32 msg_subtype,
+                      khm_ui_4 uparam,
+                      void * vparam) {
+    kcdb_ident_name_xfer *px;
+
+    px = (kcdb_ident_name_xfer *) vparam;
+
+    /* note that k5_ident_name_comp_func() ignores the size
+       specifiers.  So we can just pass in 0's. */
+    px->result = k5_ident_name_comp_func(px->name_src, 0,
+                                         px->name_alt, 0);
+
+    return KHM_ERROR_SUCCESS;
+}
+
 #if 0
 /* copy and paste template for ident provider messages */
 static khm_int32
@@ -1292,8 +1314,10 @@ k5_msg_ident(khm_int32 msg_type,
         break;
 
     case KMSG_IDENT_COMPARE_NAME:
-        /* TODO: handle KMSG_IDENT_COMPARE_NAME */
-        break;
+        return k5_ident_compare_name(msg_type,
+                                     msg_subtype,
+                                     uparam,
+                                     vparam);
 
     case KMSG_IDENT_SET_DEFAULT:
         return k5_ident_set_default(msg_type,
@@ -1335,6 +1359,12 @@ k5_msg_ident(khm_int32 msg_type,
     return KHM_ERROR_SUCCESS;
 }
 
+/* note that we are ignoring the size specifiers.  We can do that
+   because we are guaranteed that dl and dr point to NULL terminated
+   unicode strings when used with credential data buffers.  We also
+   use the fact that we are ignoring the size specifiers when we call
+   this function from k5_ident_compare_name() to avoid calculating the
+   length of the string. */
 khm_int32 KHMAPI
 k5_ident_name_comp_func(const void * dl, khm_size cb_dl,
                         const void * dr, khm_size cb_dr) {
diff --git a/src/windows/identity/plugins/krb5/krb5newcreds.c b/src/windows/identity/plugins/krb5/krb5newcreds.c
index c89653779..daa80b845 100644
--- a/src/windows/identity/plugins/krb5/krb5newcreds.c
+++ b/src/windows/identity/plugins/krb5/krb5newcreds.c
@@ -1109,11 +1109,16 @@ k5_read_dlg_params(khm_handle conf,
 {
     khm_int32 i;
 
-    khc_read_int32(conf, L"Renewable", &d->renewable);
-    khc_read_int32(conf, L"Forwardable", &d->forwardable);
-    khc_read_int32(conf, L"Proxiable", &d->proxiable);
-    khc_read_int32(conf, L"Addressless", &d->addressless);
-    khc_read_int32(conf, L"PublicIP", &d->publicIP);
+    khc_read_int32(conf, L"Renewable", &i);
+    d->renewable = i;
+    khc_read_int32(conf, L"Forwardable", &i);
+    d->forwardable = i;
+    khc_read_int32(conf, L"Proxiable", &i);
+    d->proxiable = i;
+    khc_read_int32(conf, L"Addressless", &i);
+    d->addressless = i;
+    khc_read_int32(conf, L"PublicIP", &i);
+    d->publicIP = i;
 
     khc_read_int32(conf, L"DefaultLifetime", &i);
     d->tc_lifetime.current = i;
@@ -1712,7 +1717,7 @@ k5_msg_cred_dialog(khm_int32 msg_type,
             khui_new_creds_by_type * nct;
             k5_dlg_data * d;
 
-            khm_int32 r;
+            khm_int32 r = 0;
 
             nc = (khui_new_creds *) vparam;
 
diff --git a/src/windows/identity/ui/cfg_general_wnd.c b/src/windows/identity/ui/cfg_general_wnd.c
index 03c430060..71edb2688 100644
--- a/src/windows/identity/ui/cfg_general_wnd.c
+++ b/src/windows/identity/ui/cfg_general_wnd.c
@@ -24,6 +24,7 @@
 
 /* $Id$ */
 
+#include<shlwapi.h>
 #include<khmapp.h>
 #include<assert.h>
 
@@ -267,8 +268,61 @@ khm_cfg_general_proc(HWND hwnd,
         d = (dlg_data *) (DWORD_PTR) GetWindowLongPtr(hwnd, DWLP_USER);
 
         if (HIWORD(wParam) == BN_CLICKED) {
-            refresh_data(hwnd, d);
-            check_for_modification(d);
+            if (LOWORD(wParam) == IDC_CFG_SHOWLOG) {
+                /* we need to display the logfile */
+                wchar_t buf[512];
+
+                buf[0] = L'\0';
+                khm_get_file_log_path(sizeof(buf), buf);
+
+                if (!buf[0] ||
+                    !PathFileExists(buf)) {
+
+                    wchar_t title[256];
+                    wchar_t msg[550];
+                    wchar_t fmt[256];
+
+                    LoadString(khm_hInstance, IDS_CFG_LOGF_CS,
+                               title, ARRAYLENGTH(title));
+                    LoadString(khm_hInstance, IDS_CFG_LOGF_CSR,
+                               fmt, ARRAYLENGTH(fmt));
+
+                    StringCbPrintf(msg, sizeof(msg), fmt, buf);
+
+                    MessageBox(hwnd, title, msg, MB_OK);
+                    
+                } else {
+                    wchar_t cmdline[550];
+                    STARTUPINFO si;
+                    PROCESS_INFORMATION pi;
+
+                    StringCbCopy(cmdline, sizeof(cmdline), L"notepad.exe ");
+                    StringCbCat(cmdline, sizeof(cmdline), L"\"");
+                    StringCbCat(cmdline, sizeof(cmdline), buf);
+                    StringCbCat(cmdline, sizeof(cmdline), L"\"");
+
+                    ZeroMemory(&si, sizeof(si));
+                    si.cb = sizeof(si);
+                    ZeroMemory(&pi, sizeof(pi));
+
+                    CreateProcess(NULL,
+                                  cmdline,
+                                  NULL, NULL,
+                                  FALSE,
+                                  0, NULL, NULL,
+                                  &si,
+                                  &pi);
+
+                    if (pi.hProcess)
+                        CloseHandle(pi.hProcess);
+                    if (pi.hThread)
+                        CloseHandle(pi.hThread);
+
+                }
+            } else {
+                refresh_data(hwnd, d);
+                check_for_modification(d);
+            }
         }
 
         khm_set_dialog_result(hwnd, 0);
diff --git a/src/windows/identity/ui/cfg_identities_wnd.c b/src/windows/identity/ui/cfg_identities_wnd.c
index 26a60e5e0..3297b05be 100644
--- a/src/windows/identity/ui/cfg_identities_wnd.c
+++ b/src/windows/identity/ui/cfg_identities_wnd.c
@@ -429,9 +429,22 @@ write_params_ident(ident_data * d) {
     }
 
     if (d->removed) {
+        khm_handle h = NULL;
 
         khc_remove_space(csp_ident);
 
+        /* calling kcdb_identity_get_config() will update the
+           KCDB_IDENT_FLAG_CONFIG flag for the identity to reflect the
+           fact that it nolonger has a configuration. */
+        kcdb_identity_get_config(d->ident, 0, &h);
+        if (h) {
+            /* what the ? */
+#ifdef DEBUG
+            assert(FALSE);
+#endif
+            khc_close_space(h);
+        }
+
     } else {
 
         if (d->saved.monitor != d->work.monitor)
@@ -699,6 +712,136 @@ refresh_view_idents_state(HWND hwnd) {
                             KHUI_CNFLAG_APPLIED | KHUI_CNFLAG_MODIFIED);
 }
 
+/* dialog box procedure for the "Add new identity" dialog */
+INT_PTR CALLBACK
+khm_cfg_add_ident_proc(HWND hwnd,
+                       UINT umsg,
+                       WPARAM wParam,
+                       LPARAM lparam) {
+    switch(umsg) {
+    case WM_INITDIALOG:
+        /* set the max length of the edit control first */
+        SendDlgItemMessage(hwnd, IDC_CFG_IDNAME,
+                           EM_SETLIMITTEXT,
+                           KCDB_IDENT_MAXCCH_NAME - 1,
+                           0);
+        break;
+
+    case WM_DESTROY:
+        /* nor do we have to do anything here */
+        break;
+
+    case WM_COMMAND:
+        if (LOWORD(wParam) == IDOK) {
+            wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
+            khm_int32 rv = KHM_ERROR_SUCCESS;
+            khm_handle ident = NULL;
+            khm_handle csp_ident = NULL;
+            khm_size i;
+            wchar_t err_msg[512] = L"";
+
+            GetDlgItemText(hwnd, IDC_CFG_IDNAME, idname,
+                           ARRAYLENGTH(idname));
+
+            idname[ARRAYLENGTH(idname) - 1] = L'\0';
+            if (KHM_FAILED(rv = kcdb_identpro_validate_name(idname)) &&
+                rv != KHM_ERROR_NO_PROVIDER &&
+                rv != KHM_ERROR_NOT_IMPLEMENTED) {
+                /* the supplied name was invalid or something */
+
+                wchar_t fmt[256];
+
+                LoadString(khm_hInstance, IDS_CFG_IDNAME_INV,
+                           fmt, ARRAYLENGTH(fmt));
+                StringCbPrintf(err_msg, sizeof(err_msg), fmt, idname);
+
+                goto show_failure;
+            }
+
+            /* now check if this is actually a new identity */
+            for (i=0; i < cfg_idents.n_idents; i++) {
+                if (!kcdb_identpro_compare_name(cfg_idents.idents[i].idname,
+                                                idname))
+                    break;
+            }
+
+            if (i < cfg_idents.n_idents) {
+                wchar_t fmt[256];
+
+                LoadString(khm_hInstance, IDS_CFG_IDNAME_EXT,
+                           fmt, ARRAYLENGTH(fmt));
+                StringCbPrintf(err_msg, sizeof(err_msg), fmt, idname);
+
+                goto show_failure;
+            }
+
+            /* ok.  now we are all set to add the new identity */
+            if (KHM_FAILED(rv = kcdb_identity_create(idname,
+                                                     KCDB_IDENT_FLAG_CREATE,
+                                                     &ident))) {
+                /* oops */
+                wchar_t fmt[256];
+
+                LoadString(khm_hInstance, IDS_CFG_IDNAME_CCR,
+                           fmt, ARRAYLENGTH(fmt));
+                StringCbPrintf(err_msg, sizeof(err_msg), fmt, rv);
+
+                goto show_failure;
+            }
+
+            /* now we have to create the identity configuration. */
+            if (KHM_FAILED(rv = kcdb_identity_get_config(ident,
+                                                         KHM_FLAG_CREATE,
+                                                         &csp_ident))) {
+                wchar_t fmt[256];
+
+                LoadString(khm_hInstance, IDS_CFG_IDNAME_CCC,
+                           fmt, ARRAYLENGTH(fmt));
+                StringCbPrintf(err_msg, sizeof(err_msg), fmt, rv);
+
+                kcdb_identity_release(ident);
+
+                goto show_failure;
+            }
+
+            khm_refresh_config();
+
+            kcdb_identity_release(ident);
+            khc_close_space(csp_ident);
+
+            EndDialog(hwnd, 0);
+            break;
+
+        show_failure:
+            {
+                wchar_t title[512];
+                wchar_t fmt[256];
+
+                if (!err_msg[0])
+                    break;
+
+                LoadString(khm_hInstance, IDS_CFG_IDNAME_PRB,
+                           fmt, ARRAYLENGTH(fmt));
+                StringCbPrintf(title, sizeof(title), fmt, idname);
+
+                MessageBox(hwnd, err_msg, title, MB_OK | MB_ICONSTOP);
+
+                /* don't end the dialog yet */
+                break;
+            }
+            break;
+            
+        } else if (LOWORD(wParam) == IDCANCEL) {
+            EndDialog(hwnd, 1);
+        }
+        break;
+    }
+
+    return FALSE;
+}
+
+/* dialog procedure for the "general" pane of the "identities"
+   configuration node. */
 INT_PTR CALLBACK
 khm_cfg_ids_tab_proc(HWND hwnd,
                     UINT umsg,
@@ -795,6 +938,14 @@ khm_cfg_ids_tab_proc(HWND hwnd,
             case IDC_CFG_STICKY:
                 refresh_data_idents(hwnd);
                 break;
+
+            case IDC_CFG_ADDIDENT:
+                DialogBoxParam(khm_hInstance,
+                               MAKEINTRESOURCE(IDD_CFG_ADDIDENT),
+                               hwnd,
+                               khm_cfg_add_ident_proc,
+                               (LPARAM) hwnd);
+                break;
             }
 
             refresh_view_idents_state(hwnd);
@@ -834,6 +985,7 @@ khm_cfg_ids_tab_proc(HWND hwnd,
     return FALSE;
 }
 
+/* dialog procedure for the "Identities" configuration node */
 INT_PTR CALLBACK
 khm_cfg_identities_proc(HWND hwnd,
                         UINT uMsg,
@@ -960,6 +1112,8 @@ refresh_data_ident(HWND hwnd, khui_config_init_data * idata) {
     }
 }
 
+/* dialog procedure for the "general" pane of individual identity
+   configuration nodes. */
 INT_PTR CALLBACK
 khm_cfg_id_tab_proc(HWND hwnd,
                     UINT umsg,
@@ -1061,6 +1215,7 @@ khm_cfg_id_tab_proc(HWND hwnd,
     return FALSE;
 }
 
+/* dialog procedure for individual identity configuration nodes */
 INT_PTR CALLBACK
 khm_cfg_identity_proc(HWND hwnd,
                       UINT uMsg,
diff --git a/src/windows/identity/ui/configwnd.c b/src/windows/identity/ui/configwnd.c
index a7da44677..5059dba28 100644
--- a/src/windows/identity/ui/configwnd.c
+++ b/src/windows/identity/ui/configwnd.c
@@ -402,13 +402,16 @@ static void
 cfgui_apply_settings(khui_config_node node) {
     HWND hwnd;
     khui_config_node c;
+    khm_int32 flags;
 
     hwnd = khui_cfg_get_hwnd(node);
+    flags = khui_cfg_get_flags(node);
 
-    if (hwnd)
+    if (hwnd && (flags & KHUI_CNFLAG_MODIFIED)) {
         SendMessage(hwnd, KHUI_WM_CFG_NOTIFY,
                     MAKEWPARAM(0, WMCFG_APPLY),
                     (LPARAM) node);
+    }
 
     if (KHM_FAILED(khui_cfg_get_first_child(node, &c)))
         return;
@@ -664,7 +667,12 @@ cfgui_dlgproc(HWND hwnd,
             cfgui_update_state(hwnd, LOWORD(wParam), 
                                (khui_config_node) lParam);
             break;
+
+        case WMCFG_SYNC_NODE_LIST:
+            /*TODO: synchronize the node lists here */
+            break;
         }
+
         return TRUE;
     }
 
@@ -717,6 +725,7 @@ void khm_refresh_config(void) {
     int n_tries = 0;
     khui_config_node cfg_ids = NULL;
     khui_config_node cfg_r = NULL;
+    khui_config_node cfg_iter = NULL;
     khui_menu_def * omenu;
     khm_boolean refresh_menu = FALSE;
 
@@ -794,6 +803,29 @@ void khm_refresh_config(void) {
         }
     }
 
+    for (khui_cfg_get_first_child(cfg_ids, &cfg_iter);
+         cfg_iter;
+         khui_cfg_get_next_release(&cfg_iter)) {
+
+        wchar_t cfgname[KCDB_IDENT_MAXCCH_NAME];
+        khm_size cb;
+        khm_handle tident = NULL;
+        khm_int32 tflags = 0;
+
+        cb = sizeof(cfgname);
+        khui_cfg_get_name(cfg_iter, cfgname, &cb);
+
+        if (KHM_FAILED(kcdb_identity_create(cfgname, 0, &tident)) ||
+            KHM_FAILED(kcdb_identity_get_flags(tident, &tflags)) ||
+            !(tflags & KCDB_IDENT_FLAG_ACTIVE) ||
+            !(tflags & KCDB_IDENT_FLAG_CONFIG)) {
+
+            /* this configuration node needs to be removed */
+
+            khui_cfg_remove(cfg_iter);
+        }
+    }
+
     /* Now iterate through the root level configuration nodes and make
        sure we have a menu item for each of them. */
     if (KHM_FAILED(khui_cfg_get_first_child(NULL, &cfg_r)))
diff --git a/src/windows/identity/ui/credfuncs.c b/src/windows/identity/ui/credfuncs.c
index e09791e7b..937e82ff9 100644
--- a/src/windows/identity/ui/credfuncs.c
+++ b/src/windows/identity/ui/credfuncs.c
@@ -805,7 +805,7 @@ khm_cred_dispatch_process_message(khui_new_creds *nc)
 }
 
 void
-khm_cred_process_commandline(void) {
+khm_cred_process_startup_actions(void) {
     khm_handle defident = NULL;
 
     if (!khm_startup.processing)
@@ -818,6 +818,11 @@ khm_cred_process_commandline(void) {
         kcdb_identity_get_default(&defident);
     }
 
+    /* For asynchronous actions, we trigger the action and then exit
+       the loop.  Once the action completes, the completion handler
+       will trigger a continuation message which will result in this
+       function getting called again.  Then we can proceed with the
+       rest of the startup actions. */
     do {
         if (khm_startup.init) {
             if (defident)
@@ -841,21 +846,34 @@ khm_cred_process_commandline(void) {
         }
 
         if (khm_startup.renew) {
-            if (defident)
-                khui_context_set(KHUI_SCOPE_IDENT,
-                                 defident,
-                                 KCDB_CREDTYPE_INVALID,
-                                 NULL, NULL, 0,
-                                 NULL);
-            else
-                khui_context_reset();
+            khm_size count;
+
+            kcdb_credset_get_size(NULL, &count);
+
+            /* if there are no credentials, we just skip over the
+               renew action. */
 
-            khm_cred_renew_creds();
             khm_startup.renew = FALSE;
-            break;
+
+            if (count != 0) {
+                if (defident)
+                    khui_context_set(KHUI_SCOPE_IDENT,
+                                     defident,
+                                     KCDB_CREDTYPE_INVALID,
+                                     NULL, NULL, 0,
+                                     NULL);
+                else
+                    khui_context_reset();
+
+                khm_cred_renew_creds();
+                break;
+            }
         }
 
         if (khm_startup.destroy) {
+
+            khm_startup.destroy = FALSE;
+
             if (defident) {
                 khui_context_set(KHUI_SCOPE_IDENT,
                                  defident,
@@ -864,15 +882,15 @@ khm_cred_process_commandline(void) {
                                  NULL);
 
                 khm_cred_destroy_creds(FALSE, FALSE);
+                break;
             }
-
-            khm_startup.destroy = FALSE;
-            break;
         }
 
         if (khm_startup.autoinit) {
             khm_size count;
 
+            khm_startup.autoinit = FALSE;
+
             kcdb_credset_get_size(NULL, &count);
 
             if (count == 0) {
@@ -886,9 +904,8 @@ khm_cred_process_commandline(void) {
                     khui_context_reset();
 
                 khm_cred_obtain_new_creds(NULL);
+                break;
             }
-            khm_startup.autoinit = FALSE;
-            break;
         }
 
         if (khm_startup.exit) {
@@ -899,6 +916,8 @@ khm_cred_process_commandline(void) {
             break;
         }
 
+        /* when we get here, then we are all done with the command
+           line stuff */
         khm_startup.processing = FALSE;
     } while(FALSE);
 
@@ -907,7 +926,7 @@ khm_cred_process_commandline(void) {
 }
 
 void
-khm_cred_begin_commandline(void) {
+khm_cred_begin_startup_actions(void) {
     khm_handle csp_cw;
 
     if (khm_startup.seen)
@@ -932,7 +951,7 @@ khm_cred_begin_commandline(void) {
     khm_startup.seen = TRUE;
     khm_startup.processing = TRUE;
 
-    khm_cred_process_commandline();
+    khm_cred_process_startup_actions();
 }
 
 void
diff --git a/src/windows/identity/ui/credfuncs.h b/src/windows/identity/ui/credfuncs.h
index fe8ed6c25..677d27945 100644
--- a/src/windows/identity/ui/credfuncs.h
+++ b/src/windows/identity/ui/credfuncs.h
@@ -66,10 +66,10 @@ khm_cred_wait_for_dialog(DWORD timeout, khm_int32 * result,
                          wchar_t * ident, khm_size cb_ident);
 
 void
-khm_cred_begin_commandline(void);
+khm_cred_begin_startup_actions(void);
 
 void
-khm_cred_process_commandline(void);
+khm_cred_process_startup_actions(void);
 
 void
 khm_cred_refresh(void);
diff --git a/src/windows/identity/ui/credwnd.c b/src/windows/identity/ui/credwnd.c
index 1289561e4..b68a3f953 100644
--- a/src/windows/identity/ui/credwnd.c
+++ b/src/windows/identity/ui/credwnd.c
@@ -399,7 +399,6 @@ cw_load_view(khui_credwnd_tbl * tbl, wchar_t * view, HWND hwnd) {
     wchar_t buf[KCONF_MAXCCH_NAME];
     wchar_t * clist = NULL;
     khm_size cbsize;
-    wchar_t * cstr = NULL;
     wchar_t * iter = NULL;
     int i;
     HDC hdc;
@@ -1539,7 +1538,7 @@ cw_get_cell_height(HDC hdc, HFONT hf) {
     SIZE size;
     size_t cbbuf;
     wchar_t buf[64];
-    HFONT hfold;
+    HFONT hfold = NULL;
 
     if (hf)
         hfold = SelectFont(hdc, hf);
@@ -1717,7 +1716,7 @@ cw_erase_rect(HDC hdc,
             break;
 
         default:
-                return;
+            return;
         }
 
         if(tbl->kbm_logo_shade.cx != -1 && type == CW_ER_BLANK) {
@@ -1727,6 +1726,8 @@ cw_erase_rect(HDC hdc,
             rlogo.bottom = r_wnd->bottom;
             rie = IntersectRect(&ri, r_erase, &rlogo);
         } else {
+            ZeroMemory(&rlogo, sizeof(rlogo));
+            ZeroMemory(&ri, sizeof(ri));
             rie = FALSE;
         }
 
@@ -1737,7 +1738,7 @@ cw_erase_rect(HDC hdc,
             HBITMAP hbmold = SelectObject(hdcb, tbl->kbm_logo_shade.hbmp);
 
             BitBlt(hdc, ri.left, ri.top, ri.right - ri.left, ri.bottom - ri.top,
-                hdcb, ri.left - rlogo.left, ri.top - rlogo.top, SRCCOPY);
+                   hdcb, ri.left - rlogo.left, ri.top - rlogo.top, SRCCOPY);
             
             SelectObject(hdcb, hbmold);
             DeleteDC(hdcb);
@@ -2145,6 +2146,7 @@ cw_handle_header_msg(khui_credwnd_tbl * tbl, LPNMHEADER ph) {
                     Header_SetItem(tbl->hwnd_header, hidx, &hi);
                 }
 
+#if 0
             } else if (tbl->cols[idx].flags &
                        (KHUI_CW_COL_SORT_INC |
                         KHUI_CW_COL_SORT_DEC)) {
@@ -2167,7 +2169,7 @@ cw_handle_header_msg(khui_credwnd_tbl * tbl, LPNMHEADER ph) {
                     hidx = Header_OrderToIndex(tbl->hwnd_header, i);
                     Header_SetItem(tbl->hwnd_header, hidx, &hi);
                 }
-
+#endif
             } else {
                 int i;
                 int sort_index = 0;
@@ -2327,7 +2329,7 @@ cw_wm_paint(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
     HDC hdc;
     PAINTSTRUCT ps;
     RECT r,rh;
-    HFONT hf_old;
+    HFONT hf_old = NULL;
     int row_s, row_e;
     int col_s, col_e;
     int i,j,x,y,xs,xe,ys,ye;
@@ -4244,7 +4246,7 @@ cw_wm_command(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
     case KHUI_PACTION_UP_TOGGLE:
         { /* cursor up */
             khm_int32 new_row;
-            WPARAM wp;
+            WPARAM wp = 0;
 
             new_row = tbl->cursor_row - 1;
 
@@ -4303,7 +4305,7 @@ cw_wm_command(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
     case KHUI_PACTION_DOWN_TOGGLE:
         { /* cursor down */
             khm_int32 new_row;
-            WPARAM wp;
+            WPARAM wp = 0;
 
             new_row = tbl->cursor_row + 1;
 
diff --git a/src/windows/identity/ui/htwnd.c b/src/windows/identity/ui/htwnd.c
index 0ad9c880f..a9472585b 100644
--- a/src/windows/identity/ui/htwnd.c
+++ b/src/windows/identity/ui/htwnd.c
@@ -143,7 +143,7 @@ static LONG table_lookup(struct tx_tbl_t * tbl, int n, wchar_t * v, int len)
     int i;
 
     for(i=0; i<n; i++) {
-        if(!wcsnicmp(tbl[i].string, v, len))
+        if(!_wcsnicmp(tbl[i].string, v, len))
             return tbl[i].value;
     }
 
@@ -344,7 +344,7 @@ static int htw_parse_tag(
     /* start initially points to the starting '<' */
     c = token_end(++start);
 
-    if(!wcsnicmp(start,L"a",c-start)) {
+    if(!_wcsnicmp(start,L"a",c-start)) {
         /* start of an 'a' tag */
         wchar_t * id_start = NULL;
         int id_len = 0;
@@ -368,9 +368,9 @@ static int htw_parse_tag(
             if(c==e)
                 break;
 
-            if(!wcsnicmp(c,L"id",e-c)) {
+            if(!_wcsnicmp(c,L"id",e-c)) {
                 c = read_attr(e, &id_start, &id_len);
-            } else if(!wcsnicmp(c,L"param",e-c)) {
+            } else if(!_wcsnicmp(c,L"param",e-c)) {
                 c = read_attr(e, &param_start, &param_len);
             }
         }
@@ -421,7 +421,7 @@ static int htw_parse_tag(
             d->n_links++;
         }
 
-    } else if(!wcsnicmp(start, L"/a", c - start)) {
+    } else if(!_wcsnicmp(start, L"/a", c - start)) {
         khui_htwnd_link * l;
 
         c = wcschr(c,L'>');
@@ -435,15 +435,15 @@ static int htw_parse_tag(
             l->r.right = p_abs->x;
             l->r.bottom = p_abs->y + lh;
         }
-    } else if(!wcsnicmp(start, L"p", c - start)) {
+    } else if(!_wcsnicmp(start, L"p", c - start)) {
         wchar_t * e;
         wchar_t * align_s = NULL;
-        int align_len;
+        int align_len = 0;
 
         c = skip_ws(c);
         e = token_end(c);
 
-        if(c != e && !wcsnicmp(c,L"align",e-c)) {
+        if(c != e && !_wcsnicmp(c,L"align",e-c)) {
             c = read_attr(e, &align_s, &align_len);
         }
 
@@ -458,57 +458,56 @@ static int htw_parse_tag(
             *align = ALIGN_LEFT;
 
         n = 1;
-    } else if(!wcsnicmp(start, L"b", c - start)) {
+    } else if(!_wcsnicmp(start, L"b", c - start)) {
         format_push(s,d, HTW_DEFAULT, FV_BOLD, HTW_DEFAULT);
-    } else if(!wcsnicmp(start, L"/b", c - start)) {
+    } else if(!_wcsnicmp(start, L"/b", c - start)) {
         format_pop(s);
-    } else if(!wcsnicmp(start, L"u", c - start)) {
+    } else if(!_wcsnicmp(start, L"u", c - start)) {
         format_push(s,d, HTW_DEFAULT, FV_UNDERLINE, HTW_DEFAULT);
-    } else if(!wcsnicmp(start, L"/u", c - start)) {
+    } else if(!_wcsnicmp(start, L"/u", c - start)) {
         format_pop(s);
-    } else if(!wcsnicmp(start, L"large", c - start)) {
+    } else if(!_wcsnicmp(start, L"large", c - start)) {
         format_push(s,d,-MulDiv(HTW_LARGE_SIZE, d->l_pixel_y, 72), HTW_DEFAULT, HTW_DEFAULT);
-    } else if(!wcsnicmp(start, L"/large", c - start)) {
+    } else if(!_wcsnicmp(start, L"/large", c - start)) {
         format_pop(s);
-    } else if(!wcsnicmp(start, L"huge", c - start)) {
+    } else if(!_wcsnicmp(start, L"huge", c - start)) {
         format_push(s,d,-MulDiv(HTW_HUGE_SIZE, d->l_pixel_y, 72), HTW_DEFAULT, HTW_DEFAULT);
-    } else if(!wcsnicmp(start, L"/huge", c - start)) {
+    } else if(!_wcsnicmp(start, L"/huge", c - start)) {
         format_pop(s);
-    } else if(!wcsnicmp(start, L"center", c - start)) {
+    } else if(!_wcsnicmp(start, L"center", c - start)) {
         c = wcschr(c, L'>');
         if(!c)
             c = c + wcslen(c);
         *align = ALIGN_CENTER;
         n = 1;
-    } else if(!wcsnicmp(start, L"left", c - start) ||
-        !wcsnicmp(start, L"p", c - start)) 
+    } else if(!_wcsnicmp(start, L"left", c - start) ||
+        !_wcsnicmp(start, L"p", c - start)) 
     {
         c = wcschr(c, L'>');
         if(!c)
             c = c + wcslen(c);
         *align = ALIGN_LEFT;
         n = 1;
-    } else if(!wcsnicmp(start, L"right", c - start)) {
+    } else if(!_wcsnicmp(start, L"right", c - start)) {
         c = wcschr(c, L'>');
         if(!c)
             c = c + wcslen(c);
         *align = ALIGN_RIGHT;
         n = 1;
-    } else if(!wcsnicmp(start, L"/center", c - start) ||
-        !wcsnicmp(start, L"/left", c - start) ||
-        !wcsnicmp(start, L"/right", c - start) ||
-        !wcsnicmp(start, L"/p", c - start))
-    {
+    } else if(!_wcsnicmp(start, L"/center", c - start) ||
+              !_wcsnicmp(start, L"/left", c - start) ||
+              !_wcsnicmp(start, L"/right", c - start) ||
+              !_wcsnicmp(start, L"/p", c - start)) {
         c = wcschr(c, L'>');
         if(!c)
             c = c + wcslen(c);
         *align = ALIGN_LEFT;
         n = 1;
-    } else if(!wcsnicmp(start, L"font", c - start)) {
+    } else if(!_wcsnicmp(start, L"font", c - start)) {
         wchar_t * color_s = NULL;
-        int color_len;
+        int color_len = 0;
         wchar_t * size_s = NULL;
-        int size_len;
+        int size_len = 0;
         LONG color = HTW_DEFAULT;
         LONG h = HTW_DEFAULT;
 
@@ -521,9 +520,9 @@ static int htw_parse_tag(
             if(c==e)
                 break;
 
-            if(!wcsnicmp(c,L"color",e-c)) {
+            if(!_wcsnicmp(c,L"color",e-c)) {
                 c = read_attr(e, &color_s, &color_len);
-            } else if(!wcsnicmp(c,L"size",e-c)) {
+            } else if(!_wcsnicmp(c,L"size",e-c)) {
                 c = read_attr(e, &size_s, &size_len);
             }
         }
@@ -539,9 +538,9 @@ static int htw_parse_tag(
         }
 
         format_push(s,d,h,HTW_DEFAULT,color);
-    } else if(!wcsnicmp(start, L"/font", c - start)) {
+    } else if(!_wcsnicmp(start, L"/font", c - start)) {
         format_pop(s);
-    } else if(!wcsnicmp(start, L"settab", c - start)) {
+    } else if(!_wcsnicmp(start, L"settab", c - start)) {
         wchar_t * e;
         wchar_t * pos_s = NULL;
         int pos_len;
@@ -549,7 +548,7 @@ static int htw_parse_tag(
         c = skip_ws(c);
         e = token_end(c);
 
-        if(c != e && !wcsnicmp(c,L"pos",e-c)) {
+        if(c != e && !_wcsnicmp(c,L"pos",e-c)) {
             c = read_attr(e, &pos_s, &pos_len);
         }
 
@@ -570,7 +569,7 @@ static int htw_parse_tag(
 
             d->tabs[d->n_tabs++] = MulDiv(dx, bx, 4);
         }
-    } else if(!wcsnicmp(start, L"tab", c - start)) {
+    } else if(!_wcsnicmp(start, L"tab", c - start)) {
         int i;
 
         if(!dry_run) {
@@ -1051,7 +1050,7 @@ void khm_register_htwnd_class(void)
 
 void khm_unregister_htwnd_class(void)
 {
-    UnregisterClass((LPWSTR) khui_htwnd_cls, khm_hInstance);
+    UnregisterClass(MAKEINTATOM(khui_htwnd_cls), khm_hInstance);
 }
 
 HWND khm_create_htwnd(HWND parent, LPWSTR text, int x, int y, int width, int height, DWORD ex_style, DWORD style)
@@ -1059,7 +1058,7 @@ HWND khm_create_htwnd(HWND parent, LPWSTR text, int x, int y, int width, int hei
 
     return CreateWindowEx(
         ex_style,
-        (LPWSTR) khui_htwnd_cls,
+        MAKEINTATOM(khui_htwnd_cls),
         text,
         style | WS_CHILD,
         x,y,width,height,
diff --git a/src/windows/identity/ui/lang/en_us/khapp.rc b/src/windows/identity/ui/lang/en_us/khapp.rc
index ceba01f5a..5a795dd99 100644
--- a/src/windows/identity/ui/lang/en_us/khapp.rc
+++ b/src/windows/identity/ui/lang/en_us/khapp.rc
@@ -287,8 +287,9 @@ BEGIN
     CONTROL         "Log trace events to trace log at the following location:",
                     IDC_CFG_LOGTOFILE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
                     16,113,225,10
-    EDITTEXT        IDC_CFG_LOGPATH,16,127,225,14,ES_AUTOHSCROLL | 
+    EDITTEXT        IDC_CFG_LOGPATH,16,127,173,14,ES_AUTOHSCROLL | 
                     ES_READONLY
+    PUSHBUTTON      "Show log ...",IDC_CFG_SHOWLOG,193,127,50,14
     CONTROL         "A&utomatically import Windows logon identity",
                     IDC_CFG_AUTOIMPORT,"Button",BS_AUTOCHECKBOX | NOT 
                     WS_VISIBLE | WS_TABSTOP,16,158,165,10
@@ -382,6 +383,7 @@ BEGIN
     CONTROL         "Always show in the credentials list (Pinned)",
                     IDC_CFG_STICKY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,
                     34,151,10
+    PUSHBUTTON      "&Add new identity...",IDC_CFG_ADDIDENT,17,120,86,14
 END
 
 IDD_CFG_ID_TAB DIALOGEX 0, 0, 235, 151
@@ -396,8 +398,7 @@ BEGIN
                     BS_AUTOCHECKBOX | WS_TABSTOP,7,7,107,10
     CONTROL         "Automatically renew",IDC_CFG_RENEW,"Button",
                     BS_AUTOCHECKBOX | WS_TABSTOP,7,20,81,10
-    PUSHBUTTON      "Remove identity ...",IDC_CFG_REMOVE,139,122,78,14,NOT 
-                    WS_VISIBLE
+    PUSHBUTTON      "Remove identity ...",IDC_CFG_REMOVE,139,122,78,14
 END
 
 IDD_ABOUT DIALOGEX 0, 0, 268, 170
@@ -442,6 +443,18 @@ BEGIN
     PUSHBUTTON      "&Revert to default",IDC_CFG_REVERT,168,122,72,14
 END
 
+IDD_CFG_ADDIDENT DIALOGEX 0, 0, 325, 70
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | 
+    WS_SYSMENU
+CAPTION "Add new identity"
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+    LTEXT           "&Identity name",IDC_STATIC,7,10,46,8
+    EDITTEXT        IDC_CFG_IDNAME,67,7,195,14,ES_AUTOHSCROLL
+    DEFPUSHBUTTON   "OK",IDOK,268,7,50,14
+    PUSHBUTTON      "Cancel",IDCANCEL,268,24,50,14
+END
+
 
 /////////////////////////////////////////////////////////////////////////////
 //
@@ -578,6 +591,14 @@ BEGIN
         TOPMARGIN, 7
         BOTTOMMARGIN, 175
     END
+
+    IDD_CFG_ADDIDENT, DIALOG
+    BEGIN
+        LEFTMARGIN, 7
+        RIGHTMARGIN, 318
+        TOPMARGIN, 7
+        BOTTOMMARGIN, 63
+    END
 END
 #endif    // APSTUDIO_INVOKED
 
@@ -786,6 +807,13 @@ BEGIN
     IDS_CFG_APPEAR_LONG     "Appearance"
     IDS_ACTION_OPT_APPEAR   "Appearance ..."
     IDS_APR_SAMPLE_TEXT_SEL "Sample text (selected). 01234567890"
+    IDS_CFG_IDNAME_INV      "The identity name %s is invalid."
+    IDS_CFG_IDNAME_PRB      "Can't add new identity %s"
+    IDS_CFG_IDNAME_EXT      "The identity name %s already exists."
+    IDS_CFG_IDNAME_CCR      "Can't create new identity.  This may be caused by lack of resources or an unknown failure.  The code returned was %d."
+    IDS_CFG_IDNAME_CCC      "Can't create identity configuration.  This may be caused by lack or resources or not having the correct permissions to create the configuration space.  The code returned was %d."
+    IDS_CFG_LOGF_CS         "Can't show log file"
+    IDS_CFG_LOGF_CSR        "The log file %s does not exist."
 END
 
 #endif    // English (U.S.) resources
diff --git a/src/windows/identity/ui/main.c b/src/windows/identity/ui/main.c
index 6987db3ef..cad5dc566 100644
--- a/src/windows/identity/ui/main.c
+++ b/src/windows/identity/ui/main.c
@@ -118,6 +118,12 @@ void khm_parse_commandline(void) {
             break;
         }
     }
+
+    /* special: always enable renew when other options aren't specified */
+    if (!khm_startup.exit &&
+        !khm_startup.destroy &&
+        !khm_startup.init)
+        khm_startup.renew = TRUE;
 }
 
 void khm_register_window_classes(void) {
@@ -552,9 +558,9 @@ int WINAPI WinMain(HINSTANCE hInstance,
         xfer = MapViewOfFile(hmap, FILE_MAP_WRITE, 0, 0,
                              sizeof(query_app_version));
 
-        if (xfer) {
-            ZeroMemory(&query_app_version, sizeof(query_app_version));
+        ZeroMemory(&query_app_version, sizeof(query_app_version));
 
+        if (xfer) {
             query_app_version.magic = KHM_QUERY_APP_VER_MAGIC;
             query_app_version.code = KHM_ERROR_NOT_IMPLEMENTED;
             query_app_version.ver_caller = app_version;
diff --git a/src/windows/identity/ui/mainwnd.c b/src/windows/identity/ui/mainwnd.c
index 81886fa8e..bc9b1cec7 100644
--- a/src/windows/identity/ui/mainwnd.c
+++ b/src/windows/identity/ui/mainwnd.c
@@ -522,10 +522,10 @@ khm_main_wnd_proc(HWND hwnd,
                 khm_update_standard_toolbar();
             } else if (m->type == KMSG_ACT &&
                        m->subtype == KMSG_ACT_BEGIN_CMDLINE) {
-                khm_cred_begin_commandline();
+                khm_cred_begin_startup_actions();
             } else if (m->type == KMSG_ACT &&
                        m->subtype == KMSG_ACT_CONTINUE_CMDLINE) {
-                khm_cred_process_commandline();
+                khm_cred_process_startup_actions();
             } else if (m->type == KMSG_ACT &&
                        m->subtype == KMSG_ACT_SYNC_CFG) {
                 khm_refresh_config();
@@ -594,7 +594,7 @@ khm_main_wnd_proc(HWND hwnd,
             khm_startup.seen = FALSE;
             khm_startup.processing = FALSE;
 
-            khm_cred_begin_commandline();
+            khm_cred_begin_startup_actions();
         }
         break;
 
diff --git a/src/windows/identity/ui/newcredwnd.c b/src/windows/identity/ui/newcredwnd.c
index 3730a3c6e..56c79294b 100644
--- a/src/windows/identity/ui/newcredwnd.c
+++ b/src/windows/identity/ui/newcredwnd.c
@@ -803,6 +803,8 @@ nc_add_control_row(khui_nc_wnd_data * d,
         r_row.bottom += r_input.bottom;
         OffsetRect(&r_label, r_row.left, r_row.top);
     } else {
+        SetRectEmpty(&r_label);
+        SetRectEmpty(&r_input);
 #ifdef DEBUG
         assert(FALSE);
 #else
@@ -1250,7 +1252,7 @@ static LRESULT nc_handle_wm_nc_notify(HWND hwnd,
                       nc_tab_sort_func);
 
                 for(i=0; i < d->nc->n_types;i++) {
-                    wchar_t * name;
+                    wchar_t * name = NULL;
 
                     d->nc->types[i]->ordinal = i + 1;
 
diff --git a/src/windows/identity/ui/resource.h b/src/windows/identity/ui/resource.h
index 30f67755a..77e9dcee1 100644
--- a/src/windows/identity/ui/resource.h
+++ b/src/windows/identity/ui/resource.h
@@ -215,6 +215,7 @@
 #define IDS_PISTATE_PLACEHOLD           210
 #define IDD_CFG_APPEAR                  210
 #define IDS_PISTATE_REG                 211
+#define IDD_CFG_ADDIDENT                211
 #define IDS_PISTATE_HOLD                212
 #define IDS_PISTATE_INIT                213
 #define IDS_PISTATE_RUN                 214
@@ -267,6 +268,13 @@
 #define IDS_CFG_APPEAR_LONG             261
 #define IDS_ACTION_OPT_APPEAR           262
 #define IDS_APR_SAMPLE_TEXT_SEL         263
+#define IDS_CFG_IDNAME_INV              264
+#define IDS_CFG_IDNAME_PRB              265
+#define IDS_CFG_IDNAME_EXT              266
+#define IDS_CFG_IDNAME_CCR              267
+#define IDS_CFG_IDNAME_CCC              268
+#define IDS_CFG_LOGF_CS                 269
+#define IDS_CFG_LOGF_CSR                270
 #define IDC_NC_USERNAME                 1007
 #define IDC_NC_PASSWORD                 1008
 #define IDC_NC_CREDTEXT_LABEL           1009
@@ -361,6 +369,9 @@
 #define IDC_CFG_SIZE                    1130
 #define IDC_CFG_BOLD                    1131
 #define IDC_CFG_ITALICS                 1132
+#define IDC_CFG_ADDIDENT                1133
+#define IDC_CFG_IDNAME                  1134
+#define IDC_CFG_SHOWLOG                 1135
 #define IDA_ACTIVATE_MENU               40003
 #define IDA_UP                          40004
 #define IDA_DOWN                        40005
@@ -373,9 +384,9 @@
 // 
 #ifdef APSTUDIO_INVOKED
 #ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE        211
+#define _APS_NEXT_RESOURCE_VALUE        212
 #define _APS_NEXT_COMMAND_VALUE         40010
-#define _APS_NEXT_CONTROL_VALUE         1133
+#define _APS_NEXT_CONTROL_VALUE         1136
 #define _APS_NEXT_SYMED_VALUE           101
 #endif
 #endif
diff --git a/src/windows/identity/ui/statusbar.c b/src/windows/identity/ui/statusbar.c
index 9a2f8e79c..5bcf2c2a5 100644
--- a/src/windows/identity/ui/statusbar.c
+++ b/src/windows/identity/ui/statusbar.c
@@ -25,6 +25,9 @@
 /* $Id$ */
 
 #include<khmapp.h>
+#ifdef DEBUG
+#include<assert.h>
+#endif
 
 khm_statusbar_part khm_statusbar_parts[] = {
     {KHUI_SBPART_INFO, 0, KHUI_SB_WTYPE_FILLER},
@@ -88,19 +91,25 @@ khui_statusbar_set_parts(HWND parent) {
 
     lastx = 0;
     for(i=0;i<khm_n_statusbar_parts;i++) {
-        int w;
+        int w = 0;
         switch(khm_statusbar_parts[i].wtype) {
-            case KHUI_SB_WTYPE_ABSOLUTE:
-                w = khm_statusbar_parts[i].width;
-                break;
-
-            case KHUI_SB_WTYPE_RELATIVE:
-                w = (khm_statusbar_parts[i].width * width) / 100;
-                break;
-
-            case KHUI_SB_WTYPE_FILLER:
-                w = fillerwidth;
-                break;
+        case KHUI_SB_WTYPE_ABSOLUTE:
+            w = khm_statusbar_parts[i].width;
+            break;
+
+        case KHUI_SB_WTYPE_RELATIVE:
+            w = (khm_statusbar_parts[i].width * width) / 100;
+            break;
+
+        case KHUI_SB_WTYPE_FILLER:
+            w = fillerwidth;
+            break;
+
+        default:
+            w = 0;
+#ifdef DEBUG
+            assert(FALSE);
+#endif
         }
         lastx += w;
 
diff --git a/src/windows/identity/uilib/configui.c b/src/windows/identity/uilib/configui.c
index ae8cd2f7c..9aa88cd28 100644
--- a/src/windows/identity/uilib/configui.c
+++ b/src/windows/identity/uilib/configui.c
@@ -190,6 +190,12 @@ khui_cfg_register(khui_config_node vparent,
 
     EnterCriticalSection(&cs_cfgui);
     TADDCHILD(parent, node);
+
+    if (hwnd_cfgui) {
+        SendMessage(hwnd_cfgui, KHUI_WM_CFG_NOTIFY,
+                    MAKEWPARAM(0, WMCFG_SYNC_NODE_LIST), 0);
+    }
+
     LeaveCriticalSection(&cs_cfgui);
 
     /* when the root config list changes, we need to notify the UI.
@@ -254,6 +260,12 @@ khui_cfg_remove(khui_config_node vnode) {
     EnterCriticalSection(&cs_cfgui);
     node = cfgui_node_i_from_handle(vnode);
     node->flags |= KHUI_CN_FLAG_DELETED;
+
+    if (hwnd_cfgui) {
+        SendMessage(hwnd_cfgui, KHUI_WM_CFG_NOTIFY,
+                    MAKEWPARAM(0, WMCFG_SYNC_NODE_LIST), 0);
+    }
+
     LeaveCriticalSection(&cs_cfgui);
 
     return KHM_ERROR_SUCCESS;
diff --git a/src/windows/identity/uilib/creddlg.c b/src/windows/identity/uilib/creddlg.c
index 082f9f257..154ed18eb 100644
--- a/src/windows/identity/uilib/creddlg.c
+++ b/src/windows/identity/uilib/creddlg.c
@@ -322,8 +322,8 @@ cw_create_prompt(khm_size idx,
                  khm_int32 flags)
 {
     khui_new_creds_prompt * p;
-    size_t cb_prompt;
-    size_t cb_def;
+    size_t cb_prompt = 0;
+    size_t cb_def = 0;
 
     if(prompt && FAILED(StringCbLength(prompt, KHUI_MAXCB_PROMPT, &cb_prompt)))
         return NULL;
diff --git a/src/windows/identity/uilib/khconfigui.h b/src/windows/identity/uilib/khconfigui.h
index f124b513f..1d09fae9e 100644
--- a/src/windows/identity/uilib/khconfigui.h
+++ b/src/windows/identity/uilib/khconfigui.h
@@ -77,6 +77,11 @@ enum khui_wm_cfg_notifications {
       'Apply' button or the 'Ok' button.  The panels are responsible
       for applying the configuration changes and updating their flags
       using khui_cfg_set_flags(). */
+
+    WMCFG_SYNC_NODE_LIST = 4,
+    /*!< Sent from the UI library to the configuration window to
+      notify the window that the node list has changed.  This message
+      is sent synchronously before the node is removed. */
 };
 
 /*! \brief Registration information for a configuration node
diff --git a/src/windows/identity/util/mstring.c b/src/windows/identity/util/mstring.c
index 75bab0174..b642d1af8 100644
--- a/src/windows/identity/util/mstring.c
+++ b/src/windows/identity/util/mstring.c
@@ -190,12 +190,12 @@ multi_string_find(const wchar_t * ms,
 
         if(flags & KHM_PREFIX) {
             if(((flags & KHM_CASE_SENSITIVE) && !wcsncmp(s, str, cch_s)) ||
-                (!(flags & KHM_CASE_SENSITIVE) && !wcsnicmp(s, str, cch_s)))
+                (!(flags & KHM_CASE_SENSITIVE) && !_wcsnicmp(s, str, cch_s)))
                 return (wchar_t *) s;
         } else {
             if((cch == cch_s) &&
 				((flags & KHM_CASE_SENSITIVE) && !wcsncmp(s, str, cch)) ||
-                (!(flags & KHM_CASE_SENSITIVE) && !wcsnicmp(s, str, cch)))
+                (!(flags & KHM_CASE_SENSITIVE) && !_wcsnicmp(s, str, cch)))
                 return (wchar_t *) s;
         }
 
diff --git a/src/windows/identity/util/sync.c b/src/windows/identity/util/sync.c
index d686a8e80..d811eb99d 100644
--- a/src/windows/identity/util/sync.c
+++ b/src/windows/identity/util/sync.c
@@ -49,11 +49,15 @@ KHMEXP void KHMAPI InitializeRwLock(PRWLOCK pLock)
 
 KHMEXP void KHMAPI DeleteRwLock(PRWLOCK pLock)
 {
-    DeleteCriticalSection(&(pLock->cs));
+    EnterCriticalSection(&pLock->cs);
+
     CloseHandle(pLock->readwx);
     CloseHandle(pLock->writewx);
     pLock->readwx = NULL;
     pLock->writewx = NULL;
+
+    LeaveCriticalSection(&pLock->cs);
+    DeleteCriticalSection(&(pLock->cs));
 }
 
 KHMEXP void KHMAPI LockObtainRead(PRWLOCK pLock)
@@ -93,7 +97,6 @@ KHMEXP void KHMAPI LockObtainWrite(PRWLOCK pLock)
        pLock->writer == GetCurrentThreadId()) {
         pLock->locks++;
         LeaveCriticalSection(&(pLock->cs));
-        assert(FALSE);
         return;
     }
     LeaveCriticalSection(&(pLock->cs));
@@ -108,6 +111,7 @@ KHMEXP void KHMAPI LockObtainWrite(PRWLOCK pLock)
     pLock->locks++;
     pLock->writer = GetCurrentThreadId();
     ResetEvent(pLock->readwx);
+    ResetEvent(pLock->writewx);
     LeaveCriticalSection(&(pLock->cs));
 }
 
-- 
2.26.2