Make reindent
[krb5.git] / src / windows / identity / ui / newcredwnd.c
index 6852846fb410679f518ba74c64fa8a4842c6dca4..e0c60f5c0ab7eda3aaa001bf5959a968a06b485f 100644 (file)
-/*\r
- * Copyright (c) 2005 Massachusetts Institute of Technology\r
- *\r
- * Permission is hereby granted, free of charge, to any person\r
- * obtaining a copy of this software and associated documentation\r
- * files (the "Software"), to deal in the Software without\r
- * restriction, including without limitation the rights to use, copy,\r
- * modify, merge, publish, distribute, sublicense, and/or sell copies\r
- * of the Software, and to permit persons to whom the Software is\r
- * furnished to do so, subject to the following conditions:\r
- *\r
- * The above copyright notice and this permission notice shall be\r
- * included in all copies or substantial portions of the Software.\r
- *\r
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
- * SOFTWARE.\r
- */\r
-\r
-/* $Id$ */\r
-\r
-#include<khmapp.h>\r
-#include<assert.h>\r
-\r
-ATOM khui_newcredwnd_cls;\r
-\r
-/* forward dcl */\r
-static void\r
-nc_position_credtext(khui_nc_wnd_data * d);\r
-\r
-/* Common dialog procedure.  Be careful.  This is used by more than\r
-   one dialog. */\r
-static INT_PTR CALLBACK \r
-nc_common_dlg_proc(HWND hwnd,\r
-                   UINT uMsg,\r
-                   WPARAM wParam,\r
-                   LPARAM lParam)\r
-{\r
-    switch(uMsg) {\r
-    case WM_INITDIALOG:\r
-\r
-#pragma warning(push)\r
-#pragma warning(disable: 4244)\r
-        SetWindowLongPtr(hwnd, DWLP_USER, lParam);\r
-#pragma warning(pop)\r
-\r
-        return TRUE;\r
-\r
-    case WM_COMMAND:\r
-        {\r
-            int ctrl_id;\r
-\r
-            ctrl_id = LOWORD(wParam);\r
-            if (ctrl_id < KHUI_CW_ID_MIN ||\r
-                ctrl_id > KHUI_CW_ID_MAX) {\r
-                /* pump it to the parent */\r
-                PostMessage(GetParent(hwnd), WM_COMMAND, wParam, lParam);\r
-                return TRUE;\r
-            } /* else we allow the message to fall through and get\r
-                 passed into the identity provider's message\r
-                 handler. */\r
-        }\r
-        break;\r
-\r
-#if 0\r
-        /* someday this will be used to draw custom tab buttons.  But\r
-           that's not today */\r
-    case WM_DRAWITEM:\r
-        {\r
-            khui_nc_wnd_data * d;\r
-            int id;\r
-            LPDRAWITEMSTRUCT ds;\r
-\r
-            d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, DWLP_USER);\r
-            id = wParam;\r
-            ds = (LPDRAWITEMSTRUCT) lParam;\r
-\r
-            if(id >= NC_TS_CTRL_ID_MIN && id <= NC_TS_CTRL_ID_MAX) {\r
-                /*TODO: custom draw the buttons */\r
-            }\r
-            else\r
-                return FALSE;\r
-        }\r
-        break;\r
-#endif\r
-\r
-    case KHUI_WM_NC_NOTIFY:\r
-        {\r
-            khui_nc_wnd_data * d;\r
-            d = (khui_nc_wnd_data *)(LONG_PTR) \r
-                GetWindowLongPtr(hwnd, DWLP_USER);\r
-\r
-            /* message sent by parent to notify us of something */\r
-            switch(HIWORD(wParam)) {\r
-            case WMNC_DIALOG_EXPAND:\r
-                if(hwnd == d->dlg_main) {\r
-                    HWND hw;\r
-                        \r
-                    if(hw = GetDlgItem(hwnd, IDOK))\r
-                        ShowWindow(hw, SW_HIDE);\r
-                    if(hw = GetDlgItem(hwnd, IDCANCEL))\r
-                        ShowWindow(hw, SW_HIDE);\r
-                    if(hw = GetDlgItem(hwnd, IDC_NC_OPTIONS))\r
-                        ShowWindow(hw, SW_HIDE);\r
-\r
-                    d->r_credtext.bottom = d->r_area.bottom;\r
-\r
-                    nc_position_credtext(d);\r
-\r
-                    return TRUE;\r
-                }\r
-            }\r
-        }\r
-        return TRUE;\r
-    }\r
-\r
-    /* check if we have a wnd_data, and if so pass the message on to\r
-       the identity provider callback. */\r
-    {\r
-        khui_nc_wnd_data * d;\r
-\r
-        d = (khui_nc_wnd_data *) (LONG_PTR)\r
-            GetWindowLongPtr(hwnd, DWLP_USER);\r
-\r
-        if (d && d->nc && d->nc->ident_cb) {\r
-            return d->nc->ident_cb(d->nc, WMNC_IDENT_WMSG, hwnd, uMsg, \r
-                                   wParam, lParam);\r
-        }\r
-    }\r
-\r
-    return FALSE;\r
-}\r
-\r
-static void\r
-nc_position_credtext(khui_nc_wnd_data * d)\r
-{\r
-    HWND hw;\r
-\r
-    hw = GetDlgItem(d->dlg_main, IDC_NC_CREDTEXT);\r
-#ifdef DEBUG\r
-    assert(hw);\r
-#endif\r
-\r
-    if (d->r_credtext.bottom < d->r_credtext.top + d->r_row.bottom * 2) {\r
-        /* not enough room */\r
-        if (d->nc->mode == KHUI_NC_MODE_MINI &&\r
-            d->nc->subtype != KMSG_CRED_PASSWORD) {\r
-            PostMessage(d->nc->hwnd, KHUI_WM_NC_NOTIFY,\r
-                        MAKEWPARAM(0, WMNC_DIALOG_EXPAND), 0);\r
-            return;\r
-        } else {\r
-            ShowWindow(hw, SW_HIDE);\r
-            return;\r
-        }\r
-    } else {\r
-        ShowWindow(hw, SW_SHOW);\r
-    }\r
-\r
-    SetWindowPos(hw, NULL,\r
-                 d->r_credtext.left + d->r_n_input.left, /* x */\r
-                 d->r_credtext.top, /* y */\r
-                 d->r_n_input.right - d->r_n_input.left, /* width */\r
-                 d->r_credtext.bottom - d->r_credtext.top, /* height */\r
-                 SWP_NOACTIVATE | SWP_NOOWNERZORDER | \r
-                 SWP_NOZORDER);\r
-\r
-    hw = GetDlgItem(d->dlg_main, IDC_NC_CREDTEXT_LABEL);\r
-\r
-    SetWindowPos(hw, NULL,\r
-                 d->r_credtext.left + d->r_n_label.left, /* x */\r
-                 d->r_credtext.top, /* y */\r
-                 d->r_n_label.right - d->r_n_label.left, /* width */\r
-                 d->r_n_label.bottom - d->r_n_label.top, /* height */\r
-                 SWP_NOACTIVATE | SWP_NOOWNERZORDER |\r
-                 SWP_NOZORDER);\r
-}\r
-\r
-/* sorts tab buttons */\r
-static int __cdecl \r
-nc_tab_sort_func(const void * v1, const void * v2)\r
-{\r
-    /* v1 and v2 and of type : khui_new_creds_by_type ** */\r
-    khui_new_creds_by_type *t1, *t2;\r
-\r
-    t1 = *((khui_new_creds_by_type **) v1);\r
-    t2 = *((khui_new_creds_by_type **) v2);\r
-\r
-    if(t1->ordinal > 0) {\r
-        if(t2->ordinal > 0) {\r
-            if(t1->ordinal == t2->ordinal)\r
-                return wcscmp(t1->name, t2->name);\r
-            else\r
-                /* safe to convert to an int here */\r
-                return (int) (t1->ordinal - t2->ordinal);\r
-        } else\r
-            return -1;\r
-    } else {\r
-        if(t2->ordinal > 0)\r
-            return 1;\r
-        else if (t1->name && t2->name)\r
-            return wcscmp(t1->name, t2->name);\r
-        else\r
-            return 0;\r
-    }\r
-}\r
-\r
-static void \r
-nc_notify_types_async(khui_new_creds * c, UINT uMsg,\r
-                      WPARAM wParam, LPARAM lParam)\r
-{\r
-    khm_size i;\r
-\r
-    for(i=0; i<c->n_types; i++) {\r
-        PostMessage(c->types[i]->hwnd_panel, uMsg, wParam, lParam);\r
-    }\r
-}\r
-\r
-static void \r
-nc_notify_types(khui_new_creds * c, UINT uMsg,\r
-                WPARAM wParam, LPARAM lParam)\r
-{\r
-    khm_size i;\r
-\r
-    for(i=0; i<c->n_types; i++) {\r
-        SendMessage(c->types[i]->hwnd_panel, uMsg, wParam, lParam);\r
-    }\r
-}\r
-\r
-#define NC_MAXCCH_CREDTEXT 16384\r
-#define NC_MAXCB_CREDTEXT (NC_MAXCCH_CREDTEXT * sizeof(wchar_t))\r
-\r
-static void \r
-nc_update_credtext(khui_nc_wnd_data * d) \r
-{\r
-    wchar_t * ctbuf = NULL;\r
-    wchar_t * buf;\r
-    BOOL okEnable = FALSE;\r
-    BOOL validId = FALSE;\r
-    HWND hw = NULL;\r
-    size_t cch = 0;\r
-\r
-    ctbuf = PMALLOC(NC_MAXCB_CREDTEXT);\r
-\r
-    assert(ctbuf != NULL);\r
-\r
-    LoadString(khm_hInstance, IDS_NC_CREDTEXT_TABS, ctbuf, NC_MAXCCH_CREDTEXT);\r
-    StringCchLength(ctbuf, NC_MAXCCH_CREDTEXT, &cch);\r
-    buf = ctbuf + cch;\r
-    nc_notify_types(d->nc, KHUI_WM_NC_NOTIFY, \r
-                    MAKEWPARAM(0, WMNC_UPDATE_CREDTEXT), 0);\r
-\r
-    /* hopefully all the types have updated their credential texts */\r
-    if(d->nc->n_identities == 1) {\r
-        wchar_t main_fmt[256];\r
-        wchar_t id_fmt[256];\r
-        wchar_t id_name[KCDB_IDENT_MAXCCH_NAME];\r
-        wchar_t id_string[KCDB_IDENT_MAXCCH_NAME + 256];\r
-        khm_size cbbuf;\r
-        khm_int32 flags;\r
-\r
-\r
-        LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_ONE, \r
-                   main_fmt, (int) ARRAYLENGTH(main_fmt));\r
-\r
-        cbbuf = sizeof(id_name);\r
-        kcdb_identity_get_name(d->nc->identities[0], id_name, &cbbuf);\r
-\r
-        kcdb_identity_get_flags(d->nc->identities[0], &flags);\r
-        if (flags & KCDB_IDENT_FLAG_INVALID) {\r
-            LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_INVALID, \r
-                       id_fmt, (int) ARRAYLENGTH(id_fmt));\r
-        } else if(flags & KCDB_IDENT_FLAG_VALID) {\r
-            LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_VALID, \r
-                       id_fmt, (int) ARRAYLENGTH(id_fmt));\r
-        } else if(d->nc->subtype == KMSG_CRED_NEW_CREDS) {\r
-            LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_CHECKING, \r
-                       id_fmt, (int) ARRAYLENGTH(id_fmt));\r
-        } else {\r
-            LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_UNCHECKED, \r
-                       id_fmt, (int) ARRAYLENGTH(id_fmt));\r
-        }\r
-\r
-        StringCbPrintf(id_string, sizeof(id_string), id_fmt, id_name);\r
-\r
-        StringCbPrintf(buf, NC_MAXCB_CREDTEXT - cch*sizeof(wchar_t), \r
-                       main_fmt, id_string);\r
-\r
-    } else if(d->nc->n_identities > 1) {\r
-        wchar_t *ids_string;\r
-        khm_size cb_ids_string;\r
-\r
-        wchar_t id_name[KCDB_IDENT_MAXCCH_NAME];\r
-        wchar_t id_fmt[256];\r
-        wchar_t id_string[KCDB_IDENT_MAXCCH_NAME + 256];\r
-\r
-        wchar_t main_fmt[256];\r
-        khm_size cbbuf;\r
-\r
-        LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_MANY, \r
-                   main_fmt, (int) ARRAYLENGTH(main_fmt));\r
-\r
-        /* we are going to concatenate all the identity names into\r
-           a comma separated string */\r
-\r
-        /* d->nc->n_identities is at least 2 */\r
-        ids_string = PMALLOC((KCDB_IDENT_MAXCB_NAME + sizeof(id_fmt)) * \r
-                            (d->nc->n_identities - 1));\r
-        cb_ids_string = \r
-            (KCDB_IDENT_MAXCB_NAME + sizeof(id_fmt)) * \r
-            (d->nc->n_identities - 1);\r
-\r
-        assert(ids_string != NULL);\r
-\r
-        ids_string[0] = 0;\r
-\r
-        {\r
-            khm_size i;\r
-            khm_int32 flags;\r
-\r
-            for(i=1; i<d->nc->n_identities; i++) {\r
-                if(i>1) {\r
-                    StringCbCat(ids_string, cb_ids_string, L",");\r
-                }\r
-\r
-                flags = 0;\r
-\r
-                cbbuf = sizeof(id_name);\r
-                kcdb_identity_get_name(d->nc->identities[i], id_name, &cbbuf);\r
-                kcdb_identity_get_flags(d->nc->identities[i], &flags);\r
-                if(flags & KCDB_IDENT_FLAG_INVALID) {\r
-                    LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_INVALID, \r
-                               id_fmt, (int) ARRAYLENGTH(id_fmt));\r
-                } else if(flags & KCDB_IDENT_FLAG_VALID) {\r
-                    LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_VALID, \r
-                               id_fmt, (int) ARRAYLENGTH(id_fmt));\r
-                } else {\r
-                    LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_UNCHECKED, \r
-                               id_fmt, (int) ARRAYLENGTH(id_fmt));\r
-                }\r
-\r
-                StringCbPrintf(id_string, sizeof(id_string), id_fmt, id_name);\r
-                StringCbCat(ids_string, cb_ids_string, id_string);\r
-            }\r
-\r
-            cbbuf = sizeof(id_name);\r
-            kcdb_identity_get_name(d->nc->identities[0], id_name, &cbbuf);\r
-            kcdb_identity_get_flags(d->nc->identities[0], &flags);\r
-            if(flags & KCDB_IDENT_FLAG_INVALID) {\r
-                LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_INVALID, \r
-                           id_fmt, (int) ARRAYLENGTH(id_fmt));\r
-            } else if(flags & KCDB_IDENT_FLAG_VALID) {\r
-                LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_VALID, \r
-                           id_fmt, (int) ARRAYLENGTH(id_fmt));\r
-            } else {\r
-                LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_UNCHECKED, \r
-                           id_fmt, (int) ARRAYLENGTH(id_fmt));\r
-            }\r
-            StringCbPrintf(id_string, sizeof(id_string), id_fmt, id_name);\r
-\r
-            StringCbPrintf(buf, NC_MAXCB_CREDTEXT - cch*sizeof(wchar_t), \r
-                           main_fmt, id_string, ids_string);\r
-\r
-            PFREE(ids_string);\r
-        }\r
-    } else {\r
-        LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_NONE, \r
-                   buf, (int)(NC_MAXCCH_CREDTEXT - cch));\r
-    }\r
-\r
-    /* now, append the credtext string from each of the cred types */\r
-    {\r
-        khm_size i;\r
-        size_t cb;\r
-        wchar_t * buf;\r
-\r
-        cb = NC_MAXCB_CREDTEXT;\r
-        buf = ctbuf;\r
-\r
-        for(i=0; i<d->nc->n_types; i++) {\r
-            if(d->nc->types[i]->credtext != NULL) {\r
-                StringCbCatEx(buf, cb, \r
-                              d->nc->types[i]->credtext,\r
-                              &buf, &cb,\r
-                              0);\r
-            }\r
-        }\r
-    }\r
-\r
-    SetDlgItemText(d->dlg_main, IDC_NC_CREDTEXT, ctbuf);\r
-\r
-    PFREE(ctbuf);\r
-\r
-    /* so depending on whether the primary identity was found to be\r
-       invalid, we need to disable the Ok button and set the title to\r
-       reflect this */\r
-\r
-    if(d->nc->n_identities > 0) {\r
-        khm_int32 flags = 0;\r
-\r
-        if(KHM_SUCCEEDED(kcdb_identity_get_flags(d->nc->identities[0], \r
-                                               &flags)) &&\r
-           (flags & KCDB_IDENT_FLAG_VALID)) {\r
-            validId = TRUE;\r
-        }\r
-    }\r
-\r
-    if (d->nc->window_title == NULL) {\r
-        if(validId) {\r
-            wchar_t wpostfix[256];\r
-            wchar_t wtitle[KCDB_IDENT_MAXCCH_NAME + 256];\r
-            khm_size cbsize;\r
-\r
-            cbsize = sizeof(wtitle);\r
-            kcdb_identity_get_name(d->nc->identities[0], wtitle, &cbsize);\r
-\r
-            if (d->nc->subtype == KMSG_CRED_PASSWORD)\r
-                LoadString(khm_hInstance, IDS_WTPOST_PASSWORD,\r
-                           wpostfix, (int) ARRAYLENGTH(wpostfix));\r
-            else\r
-                LoadString(khm_hInstance, IDS_WTPOST_NEW_CREDS, \r
-                           wpostfix, (int) ARRAYLENGTH(wpostfix));\r
-\r
-            StringCbCat(wtitle, sizeof(wtitle), wpostfix);\r
-\r
-            SetWindowText(d->nc->hwnd, wtitle);\r
-        } else {\r
-            wchar_t wtitle[256];\r
-\r
-            if (d->nc->subtype == KMSG_CRED_PASSWORD)\r
-                LoadString(khm_hInstance, IDS_WT_PASSWORD,\r
-                           wtitle, (int) ARRAYLENGTH(wtitle));\r
-            else\r
-                LoadString(khm_hInstance, IDS_WT_NEW_CREDS, \r
-                           wtitle, (int) ARRAYLENGTH(wtitle));\r
-\r
-            SetWindowText(d->nc->hwnd, wtitle);\r
-        }\r
-    }\r
-\r
-    if(validId || d->nc->subtype == KMSG_CRED_PASSWORD) {\r
-        /* TODO: check if all the required fields have valid values\r
-           before enabling the Ok button */\r
-        okEnable = TRUE;\r
-    }\r
-\r
-    hw = GetDlgItem(d->dlg_main, IDOK);\r
-    EnableWindow(hw, okEnable);\r
-    hw = GetDlgItem(d->dlg_bb, IDOK);\r
-    EnableWindow(hw, okEnable);\r
-}\r
-\r
-#define CW_PARAM DWLP_USER\r
-\r
-static LRESULT \r
-nc_handle_wm_create(HWND hwnd,\r
-                    UINT uMsg,\r
-                    WPARAM wParam,\r
-                    LPARAM lParam)\r
-{\r
-    LPCREATESTRUCT lpc;\r
-    khui_new_creds * c;\r
-    khui_nc_wnd_data * ncd;\r
-    int x, y;\r
-    int width, height;\r
-    RECT r;\r
-\r
-    lpc = (LPCREATESTRUCT) lParam;\r
-\r
-    ncd = PMALLOC(sizeof(*ncd));\r
-    ZeroMemory(ncd, sizeof(*ncd));\r
-\r
-    c = (khui_new_creds *) lpc->lpCreateParams;\r
-    ncd->nc = c;\r
-    c->hwnd = hwnd;\r
-\r
-#pragma warning(push)\r
-#pragma warning(disable: 4244)\r
-    SetWindowLongPtr(hwnd, CW_PARAM, (LONG_PTR) ncd);\r
-#pragma warning(pop)\r
-\r
-    /* first try to create the main dialog panel */\r
-    \r
-    assert(c->subtype == KMSG_CRED_NEW_CREDS ||\r
-           c->subtype == KMSG_CRED_PASSWORD);\r
-\r
-    ncd->dlg_main = CreateDialogParam(khm_hInstance,\r
-                                      MAKEINTRESOURCE(IDD_NC_PASSWORD),\r
-                                      hwnd,\r
-                                      nc_common_dlg_proc,\r
-                                      (LPARAM) ncd);\r
-#ifdef DEBUG\r
-    assert(ncd->dlg_main);\r
-#endif\r
-\r
-    {\r
-        RECT r_main;\r
-        RECT r_area;\r
-        RECT r_row;\r
-        HWND hw;\r
-            \r
-        /* pick out metrics for use by the custom prompter stuff */\r
-        GetWindowRect(ncd->dlg_main, &r_main);\r
-\r
-        hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_PANEL);\r
-#ifdef DEBUG\r
-        assert(hw);\r
-#endif\r
-        GetWindowRect(hw, &r_area);\r
-        OffsetRect(&r_area,-r_main.left, -r_main.top);\r
-        CopyRect(&ncd->r_area, &r_area);\r
-\r
-        hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_ROW);\r
-#ifdef DEBUG\r
-        assert(hw);\r
-#endif\r
-        GetWindowRect(hw, &r);\r
-        CopyRect(&r_row, &r);\r
-        OffsetRect(&r,-r.left, -r.top);\r
-        CopyRect(&ncd->r_row, &r);\r
-\r
-        hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_LABEL);\r
-#ifdef DEBUG\r
-        assert(hw);\r
-#endif\r
-        GetWindowRect(hw, &r);\r
-        OffsetRect(&r,-r_row.left, -r_row.top);\r
-        CopyRect(&ncd->r_n_label, &r);\r
-\r
-        hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_INPUT);\r
-#ifdef DEBUG\r
-        assert(hw);\r
-#endif\r
-        GetWindowRect(hw, &r);\r
-        OffsetRect(&r, -r_row.left, -r_row.top);\r
-        CopyRect(&ncd->r_n_input, &r);\r
-\r
-        hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_ROW_LG);\r
-#ifdef DEBUG\r
-        assert(hw);\r
-#endif\r
-        GetWindowRect(hw, &r_row);\r
-\r
-        hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_LABEL_LG);\r
-#ifdef DEBUG\r
-        assert(hw);\r
-#endif\r
-        GetWindowRect(hw, &r);\r
-        OffsetRect(&r, -r_row.left, -r_row.top);\r
-        CopyRect(&ncd->r_e_label, &r);\r
-\r
-        hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_INPUT_LG);\r
-#ifdef DEBUG\r
-        assert(hw);\r
-#endif\r
-        GetWindowRect(hw, &r);\r
-        OffsetRect(&r, -r_row.left, -r_row.top);\r
-        CopyRect(&ncd->r_e_input, &r);\r
-\r
-        CopyRect(&ncd->r_credtext, &ncd->r_area);\r
-        CopyRect(&ncd->r_idspec, &ncd->r_area);\r
-\r
-        ncd->r_idspec.bottom = ncd->r_idspec.top;\r
-\r
-        hw = GetDlgItem(ncd->dlg_main, IDC_NC_CREDTEXT);\r
-#ifdef DEBUG\r
-        assert(hw);\r
-#endif\r
-        GetWindowRect(hw, &r);\r
-        OffsetRect(&r, -r_main.left, -r_main.top);\r
-        ncd->r_credtext.bottom = r.bottom;\r
-    }\r
-\r
-    /* if the mode is 'mini'*/\r
-    r.left = 0;\r
-    r.top = 0;\r
-    if(c->mode == KHUI_NC_MODE_MINI) {\r
-        r.right = NCDLG_WIDTH;\r
-        r.bottom = NCDLG_HEIGHT;\r
-    } else {\r
-        r.right = NCDLG_WIDTH + NCDLG_BBAR_WIDTH;\r
-        r.bottom = NCDLG_HEIGHT + NCDLG_TAB_HEIGHT;\r
-    }\r
-\r
-    MapDialogRect(ncd->dlg_main, &r);\r
-\r
-    ncd->r_main.left = 0;\r
-    ncd->r_main.top = 0;\r
-    ncd->r_main.right = NCDLG_WIDTH;\r
-    ncd->r_main.bottom = NCDLG_HEIGHT;\r
-\r
-    ncd->r_ts.left = 0;\r
-    ncd->r_ts.top = ncd->r_main.bottom;\r
-    ncd->r_ts.right = ncd->r_main.right;\r
-    ncd->r_ts.bottom = ncd->r_ts.top + NCDLG_TAB_HEIGHT;\r
-\r
-    ncd->r_bb.left = ncd->r_main.right;\r
-    ncd->r_bb.top = 0;\r
-    ncd->r_bb.right = ncd->r_bb.left + NCDLG_BBAR_WIDTH;\r
-    ncd->r_bb.bottom = ncd->r_ts.bottom;\r
-\r
-    MapDialogRect(ncd->dlg_main, &(ncd->r_main));\r
-    MapDialogRect(ncd->dlg_main, &(ncd->r_ts));\r
-    MapDialogRect(ncd->dlg_main, &(ncd->r_bb));\r
-\r
-    /* center the new creds window over the main NetIDMgr window */\r
-    width = r.right - r.left;\r
-    height = r.bottom - r.top;\r
-\r
-    /* adjust width and height to accomodate NC area */\r
-    {\r
-        RECT wr,cr;\r
-\r
-        GetWindowRect(hwnd, &wr);\r
-        GetClientRect(hwnd, &cr);\r
-\r
-        /* the non-client and client areas have already been calculated\r
-           at this point.  We just use the difference to adjust the width\r
-           and height */\r
-        width += (wr.right - wr.left) - (cr.right - cr.left);\r
-        height += (wr.bottom - wr.top) - (cr.bottom - cr.top);\r
-    }\r
-\r
-    GetWindowRect(lpc->hwndParent, &r);\r
-    x = (r.right + r.left)/2 - width / 2;\r
-    y = (r.top + r.bottom)/2 - height / 2;\r
-\r
-    MoveWindow(hwnd, x, y, width, height, FALSE);\r
-\r
-    SetWindowPos(ncd->dlg_main, \r
-                 NULL, \r
-                 ncd->r_main.left, \r
-                 ncd->r_main.top,\r
-                 ncd->r_main.right - ncd->r_main.left,\r
-                 ncd->r_main.bottom - ncd->r_main.top,\r
-                 SWP_DEFERERASE | SWP_NOACTIVATE | SWP_NOOWNERZORDER | \r
-                 SWP_NOREDRAW | SWP_NOZORDER);\r
-\r
-    /* IDD_NC_BBAR is the button bar that sits on the right of the\r
-       dialog when the new creds window is in 'expanded' mode. */\r
-\r
-    ncd->dlg_bb = CreateDialogParam(khm_hInstance,\r
-                                    MAKEINTRESOURCE(IDD_NC_BBAR),\r
-                                    hwnd,\r
-                                    nc_common_dlg_proc,\r
-                                    (LPARAM) ncd);\r
-\r
-#ifdef DEBUG\r
-    assert(ncd->dlg_bb);\r
-#endif\r
-\r
-    SetWindowPos(ncd->dlg_bb, \r
-                 NULL, \r
-                 ncd->r_bb.left, \r
-                 ncd->r_bb.top,\r
-                 ncd->r_bb.right - ncd->r_bb.left,\r
-                 ncd->r_bb.bottom - ncd->r_bb.top,\r
-                 SWP_DEFERERASE | SWP_NOACTIVATE | SWP_NOOWNERZORDER | \r
-                 SWP_NOREDRAW | SWP_NOZORDER);\r
-\r
-    /* IDD_NC_TS is the tab strip that sits below the main panel when\r
-       the new creds window is in 'expanded' mode */\r
-\r
-    ncd->dlg_ts = CreateDialogParam(khm_hInstance,\r
-                                    MAKEINTRESOURCE(IDD_NC_TS),\r
-                                    hwnd,\r
-                                    nc_common_dlg_proc,\r
-                                    (LPARAM) ncd);\r
-\r
-#ifdef DEBUG\r
-    assert(ncd->dlg_ts);\r
-#endif\r
-\r
-    SetWindowPos(ncd->dlg_ts, \r
-                 NULL, \r
-                 ncd->r_ts.left, \r
-                 ncd->r_ts.top,\r
-                 ncd->r_ts.right - ncd->r_ts.left,\r
-                 ncd->r_ts.bottom - ncd->r_ts.top,\r
-                 SWP_DEFERERASE | SWP_NOACTIVATE | SWP_NOOWNERZORDER | \r
-                 SWP_NOREDRAW | SWP_NOZORDER);\r
-\r
-    if(c->mode == KHUI_NC_MODE_MINI) {\r
-        /* hide and show stuff */\r
-        ShowWindow(ncd->dlg_main, SW_SHOW);\r
-        ShowWindow(ncd->dlg_bb, SW_HIDE);\r
-        ShowWindow(ncd->dlg_ts, SW_HIDE);\r
-\r
-        nc_position_credtext(ncd);\r
-    } else {\r
-        /* hide and show stuff */\r
-        ShowWindow(ncd->dlg_main, SW_SHOW);\r
-        ShowWindow(ncd->dlg_bb, SW_SHOW);\r
-        ShowWindow(ncd->dlg_ts, SW_SHOW);\r
-\r
-        PostMessage(ncd->dlg_main, KHUI_WM_NC_NOTIFY, \r
-                    MAKEWPARAM(0, WMNC_DIALOG_EXPAND), 0);\r
-    }\r
-\r
-    /* Call the identity provider callback to set the identity\r
-       selector controls */\r
-    c->ident_cb(c, WMNC_IDENT_INIT, NULL, 0, 0, (LPARAM) ncd->dlg_main);\r
-\r
-    /* we defer the creation of the tab buttons for later */\r
-\r
-    /* add this to the dialog chain */\r
-    khm_add_dialog(hwnd);\r
-\r
-    return TRUE;\r
-}\r
-\r
-static void\r
-nc_add_control_row(khui_nc_wnd_data * d, \r
-                   HWND label,\r
-                   HWND input,\r
-                   khui_control_size size)\r
-{\r
-    RECT r_row;\r
-    RECT r_label;\r
-    RECT r_input;\r
-    HFONT hf;\r
-\r
-    hf = (HFONT) SendMessage(d->dlg_main, WM_GETFONT, 0, 0);\r
-    SendMessage(label, WM_SETFONT, (WPARAM) hf, FALSE);\r
-    SendMessage(input, WM_SETFONT, (WPARAM) hf, FALSE);\r
-\r
-    CopyRect(&r_row, &d->r_row);\r
-    OffsetRect(&r_row, d->r_idspec.left, d->r_idspec.bottom);\r
-\r
-    if (size == KHUI_CTRLSIZE_SMALL) {\r
-        CopyRect(&r_label, &d->r_n_label);\r
-        CopyRect(&r_input, &d->r_n_input);\r
-        OffsetRect(&r_label, r_row.left, r_row.top);\r
-        OffsetRect(&r_input, r_row.left, r_row.top);\r
-    } else if (size == KHUI_CTRLSIZE_HALF) {\r
-        CopyRect(&r_label, &d->r_e_label);\r
-        CopyRect(&r_input, &d->r_e_input);\r
-        OffsetRect(&r_label, r_row.left, r_row.top);\r
-        OffsetRect(&r_input, r_row.left, r_row.top);\r
-    } else if (size == KHUI_CTRLSIZE_FULL) {\r
-        CopyRect(&r_label, &d->r_n_label);\r
-        r_label.right = d->r_row.right;\r
-        CopyRect(&r_input, &d->r_n_input);\r
-        OffsetRect(&r_input, r_row.left, r_row.top);\r
-        OffsetRect(&r_input, 0, r_input.bottom);\r
-        r_row.bottom += r_input.bottom;\r
-        OffsetRect(&r_label, r_row.left, r_row.top);\r
-    } else {\r
-#ifdef DEBUG\r
-        assert(FALSE);\r
-#else\r
-        return;\r
-#endif\r
-    }\r
-\r
-    SetWindowPos(label,\r
-                 ((d->hwnd_last_idspec != NULL)?\r
-                  d->hwnd_last_idspec:\r
-                  HWND_TOP),\r
-                 r_label.left, r_label.top,\r
-                 r_label.right - r_label.left,\r
-                 r_label.bottom - r_label.top,\r
-                 SWP_DEFERERASE | SWP_NOACTIVATE |\r
-                 SWP_NOOWNERZORDER);\r
-\r
-    SetWindowPos(input,\r
-                 label,\r
-                 r_input.left, r_input.top,\r
-                 r_input.right - r_input.left,\r
-                 r_input.bottom - r_input.top,\r
-                 SWP_DEFERERASE | SWP_NOACTIVATE |\r
-                 SWP_NOOWNERZORDER);\r
-\r
-    d->hwnd_last_idspec = input;\r
-\r
-    d->r_idspec.bottom = r_row.bottom;\r
-\r
-    d->r_credtext.top = r_row.bottom;\r
-\r
-    nc_position_credtext(d);\r
-}\r
-\r
-\r
-static LRESULT \r
-nc_handle_wm_destroy(HWND hwnd,\r
-                     UINT uMsg,\r
-                     WPARAM wParam,\r
-                     LPARAM lParam)\r
-{\r
-    khui_nc_wnd_data * d;\r
-    khm_size i;\r
-\r
-    /* remove self from dialog chain */\r
-    khm_del_dialog(hwnd);\r
-\r
-    d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM);\r
-\r
-    d->nc->ident_cb(d->nc, WMNC_IDENT_EXIT, NULL, 0, 0, 0);\r
-\r
-    if(d->hwnd_tc_main)\r
-        DestroyWindow(d->hwnd_tc_main);\r
-    for(i=0;i<d->nc->n_types;i++) {\r
-        if(d->nc->types[i]->hwnd_tc) {\r
-            DestroyWindow(d->nc->types[i]->hwnd_tc);\r
-            d->nc->types[i]->hwnd_tc = NULL;\r
-        }\r
-    }\r
-\r
-    if(d->dlg_bb)\r
-        DestroyWindow(d->dlg_bb);\r
-    if(d->dlg_main)\r
-        DestroyWindow(d->dlg_main);\r
-    if(d->dlg_ts)\r
-        DestroyWindow(d->dlg_ts);\r
-\r
-    d->dlg_bb = NULL;\r
-    d->dlg_main = NULL;\r
-    d->dlg_ts = NULL;\r
-\r
-    PFREE(d);\r
-\r
-    return TRUE;\r
-}\r
-\r
-static LRESULT \r
-nc_handle_wm_command(HWND hwnd,\r
-                     UINT uMsg,\r
-                     WPARAM wParam,\r
-                     LPARAM lParam)\r
-{\r
-    khui_nc_wnd_data * d;\r
-    int id;\r
-\r
-    d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM);\r
-\r
-    switch(HIWORD(wParam)) {\r
-    case BN_CLICKED:\r
-        switch(LOWORD(wParam)) {\r
-\r
-        case IDOK:\r
-            d->nc->result = KHUI_NC_RESULT_GET_CREDS;\r
-\r
-            /* fallthrough */\r
-\r
-        case IDCANCEL:\r
-            /* the default value for d->nc->result is set to\r
-               KHUI_NC_RESULT_CANCEL */\r
-            d->nc->response = 0;\r
-\r
-            nc_notify_types(d->nc, \r
-                            KHUI_WM_NC_NOTIFY, \r
-                            MAKEWPARAM(0,WMNC_DIALOG_PREPROCESS), \r
-                            0);\r
-\r
-            khui_cw_sync_prompt_values(d->nc);\r
-\r
-            khm_cred_dispatch_process_message(d->nc);\r
-\r
-            /* we won't know whether to abort or not until we get\r
-               feedback from the plugins, even if the command was\r
-               to cancel */\r
-            {\r
-                HWND hw;\r
-\r
-                hw = GetDlgItem(d->dlg_main, IDOK);\r
-                EnableWindow(hw, FALSE);\r
-                hw = GetDlgItem(d->dlg_main, IDCANCEL);\r
-                EnableWindow(hw, FALSE);\r
-                hw = GetDlgItem(d->dlg_bb, IDOK);\r
-                EnableWindow(hw, FALSE);\r
-                hw = GetDlgItem(d->dlg_bb, IDCANCEL);\r
-                EnableWindow(hw, FALSE);\r
-            }\r
-            return FALSE;\r
-\r
-        case IDC_NC_OPTIONS: \r
-            /* the Options button in the main window was clicked.  we\r
-               respond by expanding the dialog. */\r
-            PostMessage(hwnd, KHUI_WM_NC_NOTIFY, \r
-                        MAKEWPARAM(0, WMNC_DIALOG_EXPAND), 0);\r
-            return FALSE;\r
-\r
-        case IDC_NC_CREDTEXT: /* credtext link activated */\r
-            {\r
-                khui_htwnd_link * l;\r
-                wchar_t sid[KHUI_MAXCCH_HTLINK_FIELD];\r
-                wchar_t sparam[KHUI_MAXCCH_HTLINK_FIELD];\r
-                wchar_t * colon;\r
-\r
-                l = (khui_htwnd_link *) lParam;\r
-\r
-                /* do we have a valid link? */\r
-                if(l->id == NULL || l->id_len >= ARRAYLENGTH(sid))\r
-                    return TRUE; /* nope */\r
-\r
-                StringCchCopyN(sid, ARRAYLENGTH(sid), l->id, l->id_len);\r
-                sid[l->id_len] = L'\0'; /* just make sure */\r
-\r
-                if(l->param != NULL && \r
-                   l->param_len < ARRAYLENGTH(sparam) &&\r
-                   l->param_len > 0) {\r
-\r
-                    wcsncpy(sparam, l->param, l->param_len);\r
-                    sparam[l->param_len] = L'\0';\r
-\r
-                } else {\r
-                    sparam[0] = L'\0';\r
-                }\r
-\r
-                /* If the ID is of the form '<credtype>:<link_tag>'\r
-                   and <credtype> is a valid name of a credentials\r
-                   type that is participating in the credentials\r
-                   acquisition process, then we forward the message to\r
-                   the panel that is providing the UI for that cred\r
-                   type.  We also switch to that panel first. */\r
-\r
-                colon = wcschr(sid, L':');\r
-                if (colon != NULL) {\r
-                    khm_int32 credtype;\r
-                    khui_new_creds_by_type * t;\r
-\r
-                    *colon = L'\0';\r
-                    if (KHM_SUCCEEDED(kcdb_credtype_get_id(sid, &credtype)) &&\r
-                        KHM_SUCCEEDED(khui_cw_find_type(d->nc, credtype, &t))){\r
-                        *colon = L':';\r
-\r
-                        if (t->ordinal != d->ctab)\r
-                            PostMessage(hwnd,\r
-                                        KHUI_WM_NC_NOTIFY,\r
-                                        MAKEWPARAM(t->ordinal,\r
-                                                   WMNC_DIALOG_SWITCH_PANEL),\r
-                                        0);\r
-\r
-                        return SendMessage(t->hwnd_panel,\r
-                                           KHUI_WM_NC_NOTIFY,\r
-                                           MAKEWPARAM(0, WMNC_CREDTEXT_LINK),\r
-                                           lParam);\r
-                    }\r
-                }\r
-\r
-                /* if it was for us, then we need to process the message */\r
-                if(!wcsicmp(sid, CTLINKID_SWITCH_PANEL)) {\r
-                    khm_int32 credtype;\r
-                    khui_new_creds_by_type * t;\r
-\r
-                    if (KHM_SUCCEEDED(kcdb_credtype_get_id(sparam, \r
-                                                           &credtype)) &&\r
-                        KHM_SUCCEEDED(khui_cw_find_type(d->nc,\r
-                                                        credtype, &t))) {\r
-                        if (t->ordinal != d->ctab)\r
-                            PostMessage(hwnd,\r
-                                        KHUI_WM_NC_NOTIFY,\r
-                                        MAKEWPARAM(t->ordinal,\r
-                                                   WMNC_DIALOG_SWITCH_PANEL),\r
-                                        0);\r
-                    }\r
-                }\r
-            }\r
-            return FALSE;\r
-\r
-        default:\r
-            /* if one of the tab strip buttons were pressed, then\r
-               we should switch to that panel */\r
-            id = LOWORD(wParam);\r
-            if(id >= NC_TS_CTRL_ID_MIN && id <= NC_TS_CTRL_ID_MAX) {\r
-                id -= NC_TS_CTRL_ID_MIN;\r
-                PostMessage(hwnd, KHUI_WM_NC_NOTIFY, \r
-                            MAKEWPARAM(id, WMNC_DIALOG_SWITCH_PANEL),0);\r
-                return FALSE;\r
-            }\r
-        }\r
-        break;\r
-    }\r
-\r
-    return TRUE;\r
-}\r
-\r
-static LRESULT nc_handle_wm_moving(HWND hwnd,\r
-                                   UINT uMsg,\r
-                                   WPARAM wParam,\r
-                                   LPARAM lParam)\r
-{\r
-    khui_nc_wnd_data * d;\r
-\r
-    d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM);\r
-\r
-    nc_notify_types(d->nc, KHUI_WM_NC_NOTIFY, \r
-                    MAKEWPARAM(0, WMNC_DIALOG_MOVE), 0);\r
-\r
-    return FALSE;\r
-}\r
-\r
-static LRESULT nc_handle_wm_nc_notify(HWND hwnd,\r
-                               UINT uMsg,\r
-                               WPARAM wParam,\r
-                               LPARAM lParam)\r
-{\r
-    khui_nc_wnd_data * d;\r
-    RECT r;\r
-    int width, height;\r
-    khm_size id;\r
-\r
-    d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM);\r
-\r
-    switch(HIWORD(wParam)) {\r
-\r
-    case WMNC_DIALOG_SWITCH_PANEL:\r
-        id = LOWORD(wParam);\r
-        if(id >= 0 && id <= d->nc->n_types) {\r
-            /* one of the tab buttons were pressed */\r
-            if(d->ctab == id) {\r
-                return TRUE; /* nothign to do */\r
-            }\r
-\r
-            if(d->ctab == 0) {\r
-                ShowWindow(d->dlg_main, SW_HIDE);\r
-                SendMessage(d->hwnd_tc_main, \r
-                            BM_SETCHECK, BST_UNCHECKED, 0);\r
-            } else {\r
-                ShowWindow(d->nc->types[d->ctab - 1]->hwnd_panel, SW_HIDE);\r
-                SendMessage(d->nc->types[d->ctab - 1]->hwnd_tc, \r
-                            BM_SETCHECK, BST_UNCHECKED, 0);\r
-            }\r
-\r
-            d->ctab = id;\r
-\r
-            if(d->ctab == 0) {\r
-                ShowWindow(d->dlg_main, SW_SHOW);\r
-                SendMessage(d->hwnd_tc_main, \r
-                            BM_SETCHECK, BST_CHECKED, 0);\r
-            } else {\r
-                ShowWindow(d->nc->types[id - 1]->hwnd_panel, SW_SHOW);\r
-                SendMessage(d->nc->types[id - 1]->hwnd_tc, \r
-                            BM_SETCHECK, BST_CHECKED, 0);\r
-            }\r
-        }\r
-\r
-        if(d->nc->mode == KHUI_NC_MODE_EXPANDED)\r
-            return TRUE;\r
-        /*else*/\r
-        /* fallthrough */\r
-\r
-    case WMNC_DIALOG_EXPAND:\r
-        /* we are expanding the dialog box */\r
-\r
-        /* nothing to do? */\r
-        if (d->nc->mode == KHUI_NC_MODE_EXPANDED)\r
-            break;\r
-\r
-        d->nc->mode = KHUI_NC_MODE_EXPANDED;\r
-\r
-        r.top = 0;\r
-        r.left = 0;\r
-        r.right = NCDLG_WIDTH + NCDLG_BBAR_WIDTH;\r
-        r.bottom = NCDLG_HEIGHT + NCDLG_TAB_HEIGHT;\r
-\r
-        MapDialogRect(d->dlg_main, &r);\r
-\r
-        width = r.right - r.left;\r
-        height = r.bottom - r.top;\r
-\r
-        /* adjust width and height to accomodate NC area */\r
-        {\r
-            RECT wr,cr;\r
-\r
-            GetWindowRect(hwnd, &wr);\r
-            GetClientRect(hwnd, &cr);\r
-\r
-            /* the non-client and client areas have already been\r
-               calculated at this point.  We just use the difference\r
-               to adjust the width and height */\r
-            width += (wr.right - wr.left) - (cr.right - cr.left);\r
-            height += (wr.bottom - wr.top) - (cr.bottom - cr.top);\r
-        }\r
-\r
-        SendMessage(d->dlg_main, \r
-                    KHUI_WM_NC_NOTIFY, \r
-                    MAKEWPARAM(0,WMNC_DIALOG_EXPAND), \r
-                    0);\r
-\r
-        SetWindowPos(hwnd, \r
-                     NULL, \r
-                     0, 0, \r
-                     width, height, \r
-                     SWP_NOCOPYBITS | SWP_NOMOVE | SWP_NOOWNERZORDER | \r
-                     SWP_NOZORDER);\r
-\r
-        ShowWindow(d->dlg_bb, SW_SHOW);\r
-        ShowWindow(d->dlg_ts, SW_SHOW);\r
-        break;\r
-\r
-    case WMNC_DIALOG_SETUP:\r
-        if(d->nc->n_types > 0) {\r
-            khm_size i;\r
-            for(i=0; i < d->nc->n_types;i++) {\r
-\r
-                if (d->nc->types[i]->dlg_proc == NULL) {\r
-                    d->nc->types[i]->hwnd_panel = NULL;\r
-                } else {\r
-                    /* Create the dialog panel */ \r
-                    d->nc->types[i]->hwnd_panel = \r
-                        CreateDialogParam(d->nc->types[i]->h_module,\r
-                                          d->nc->types[i]->dlg_template,\r
-                                          d->nc->hwnd,\r
-                                          d->nc->types[i]->dlg_proc,\r
-                                          (LPARAM) d->nc);\r
-\r
-#ifdef DEBUG\r
-                    assert(d->nc->types[i]->hwnd_panel);\r
-#endif\r
-                }\r
-            }\r
-        }\r
-        break;\r
-\r
-    case WMNC_DIALOG_ACTIVATE:\r
-        {\r
-            int x,y,width,height;\r
-            RECT r;\r
-            int id;\r
-            wchar_t wbuf[256];\r
-            HFONT hf;\r
-\r
-            /* now we create all the tab strip controls */\r
-            r.left = 0;\r
-            r.top = 0;\r
-            r.right = NCDLG_TAB_WIDTH;\r
-            r.bottom = NCDLG_TAB_HEIGHT;\r
-            MapDialogRect(d->dlg_main, &r);\r
-\r
-            width = r.right - r.left;\r
-            height = r.bottom - r.top;\r
-\r
-            x = 0;\r
-            y = 0;\r
-\r
-            id = NC_TS_CTRL_ID_MIN;\r
-\r
-            khui_cw_lock_nc(d->nc);\r
-\r
-            /* first, the control for the main panel */\r
-            LoadString(khm_hInstance, IDS_NC_IDENTITY, \r
-                       wbuf, ARRAYLENGTH(wbuf));\r
-\r
-            d->hwnd_tc_main = \r
-                CreateWindow(L"BUTTON",\r
-                             wbuf,\r
-                             WS_VISIBLE | WS_CHILD | WS_TABSTOP |\r
-                             BS_PUSHLIKE | BS_CHECKBOX | BS_TEXT,\r
-                             x,y,width,height,\r
-                             d->dlg_ts,\r
-                             (HMENU)(INT_PTR) id,\r
-                             khm_hInstance,\r
-                             NULL);\r
-\r
-            hf = (HFONT) SendMessage(d->dlg_main, WM_GETFONT, 0, 0);\r
-            SendMessage(d->hwnd_tc_main, WM_SETFONT, (WPARAM) hf, 0);\r
-            SendMessage(d->hwnd_tc_main, BM_SETCHECK, BST_CHECKED, 0);\r
-\r
-            id++;\r
-            x += width;\r
-\r
-            if(d->nc->n_types > 0) {\r
-                khm_size i;\r
-                /* we should sort the tabs first */\r
-                qsort(d->nc->types, \r
-                      d->nc->n_types, \r
-                      sizeof(*(d->nc->types)), \r
-                      nc_tab_sort_func);\r
-\r
-                for(i=0; i < d->nc->n_types;i++) {\r
-                    wchar_t * name;\r
-\r
-                    d->nc->types[i]->ordinal = i + 1;\r
-\r
-                    if(d->nc->types[i]->name)\r
-                        name = d->nc->types[i]->name;\r
-                    else {\r
-                        khm_size cbsize;\r
-\r
-                        if(kcdb_credtype_describe\r
-                           (d->nc->types[i]->type, \r
-                            NULL, \r
-                            &cbsize, \r
-                            KCDB_TS_SHORT) == KHM_ERROR_TOO_LONG) {\r
-\r
-                            name = PMALLOC(cbsize);\r
-                            kcdb_credtype_describe(d->nc->types[i]->type, \r
-                                                   name, \r
-                                                   &cbsize, \r
-                                                   KCDB_TS_SHORT);\r
-                        } else {\r
-#ifdef DEBUG\r
-                            assert(FALSE);\r
-#else\r
-                            continue;\r
-#endif\r
-                        }\r
-                    }\r
-\r
-                    d->nc->types[i]->hwnd_tc = \r
-                        CreateWindow(L"BUTTON",\r
-                                     name,\r
-                                     WS_VISIBLE | WS_CHILD | WS_TABSTOP |\r
-                                     BS_PUSHLIKE | BS_CHECKBOX | BS_TEXT |\r
-                                     ((d->nc->types[i]->hwnd_panel == NULL)? \r
-                                      WS_DISABLED : 0),\r
-                                     x,y,width,height,\r
-                                     d->dlg_ts,\r
-                                     (HMENU)(INT_PTR) id,\r
-                                     khm_hInstance,\r
-                                     NULL);\r
-\r
-                    SendMessage(d->nc->types[i]->hwnd_tc, WM_SETFONT, \r
-                                (WPARAM)hf, 0);\r
-\r
-#if 0\r
-                    if(d->nc->types[i]->flags & KHUI_NCT_FLAG_DISABLED)\r
-                        SendMessage(d->nc->types[i]->hwnd_tc, \r
-                                    BM_SETIMAGE, \r
-                                    IMAGE_ICON, \r
-                                    LoadIcon(khm_hInstance, MAKEINTRESOURCE(IDI_DISABLED)));\r
-                    else\r
-                        SendMessage(d->nc->types[i]->hwnd_tc, \r
-                                    BM_SETIMAGE, \r
-                                    IMAGE_ICON, \r
-                                    LoadIcon(khm_hInstance, MAKEINTRESOURCE(IDI_ENABLED)));\r
-#endif\r
-\r
-                    id++;\r
-                    x += width;\r
-\r
-                    if(!(d->nc->types[i]->name))\r
-                        PFREE(name);\r
-\r
-                    /* Now set the position of the type panel */\r
-                    ShowWindow(d->nc->types[i]->hwnd_panel, SW_HIDE);\r
-                    SetWindowPos(d->nc->types[i]->hwnd_panel, \r
-                                 NULL,\r
-                                 d->r_main.left, \r
-                                 d->r_main.top,\r
-                                 d->r_main.right - d->r_main.left,\r
-                                 d->r_main.bottom - d->r_main.top,\r
-                                 SWP_DEFERERASE | SWP_NOACTIVATE | \r
-                                 SWP_NOOWNERZORDER | SWP_NOREDRAW | \r
-                                 SWP_NOZORDER);\r
-\r
-                }\r
-            }\r
-\r
-            khui_cw_unlock_nc(d->nc);\r
-\r
-            nc_update_credtext(d);\r
-\r
-            ShowWindow(hwnd, SW_SHOW);\r
-            SetFocus(hwnd);\r
-\r
-            if (d->nc->n_identities == 0)\r
-                break;\r
-            /* else */\r
-            /*   fallthrough */\r
-        }\r
-\r
-    case WMNC_IDENTITY_CHANGE:\r
-        {\r
-            BOOL okEnable = FALSE;\r
-\r
-            nc_notify_types(d->nc, KHUI_WM_NC_NOTIFY,\r
-                            MAKEWPARAM(0, WMNC_IDENTITY_CHANGE), 0);\r
-            nc_update_credtext(d);\r
-        }\r
-        break;\r
-\r
-    case WMNC_TYPE_STATE:\r
-        /* fallthrough */\r
-    case WMNC_UPDATE_CREDTEXT:\r
-        nc_update_credtext(d);\r
-        break;\r
-\r
-    case WMNC_CLEAR_PROMPTS:\r
-        {\r
-            khm_size i;\r
-\r
-            khui_cw_lock_nc(d->nc);\r
-\r
-            if(d->hwnd_banner != NULL) {\r
-                DestroyWindow(d->hwnd_banner);\r
-                d->hwnd_banner = NULL;\r
-            }\r
-\r
-            if(d->hwnd_name != NULL) {\r
-                DestroyWindow(d->hwnd_name);\r
-                d->hwnd_name = NULL;\r
-            }\r
-\r
-            for(i=0;i<d->nc->n_prompts;i++) {\r
-                if(!(d->nc->prompts[i]->flags & \r
-                     KHUI_NCPROMPT_FLAG_STOCK)) {\r
-                    if(d->nc->prompts[i]->hwnd_static != NULL)\r
-                        DestroyWindow(d->nc->prompts[i]->hwnd_static);\r
-\r
-                    if(d->nc->prompts[i]->hwnd_edit != NULL)\r
-                        DestroyWindow(d->nc->prompts[i]->hwnd_edit);\r
-                }\r
-\r
-                d->nc->prompts[i]->hwnd_static = NULL;\r
-                d->nc->prompts[i]->hwnd_edit = NULL;\r
-            }\r
-\r
-            khui_cw_unlock_nc(d->nc);\r
-\r
-            d->r_credtext.top = d->r_idspec.bottom;\r
-\r
-            nc_position_credtext(d);\r
-        }\r
-        break;\r
-\r
-    case WMNC_SET_PROMPTS:\r
-        {\r
-            khm_size i;\r
-            int  y;\r
-            HWND hw, hw_prev;\r
-            HFONT hf, hfold;\r
-            HDC hdc;\r
-\r
-            /* we assume that WMNC_CLEAR_PROMPTS has already been\r
-               received */\r
-\r
-            khui_cw_lock_nc(d->nc);\r
-\r
-#if 0\r
-            /* special case, we have one prompt and it is a password\r
-               prompt.  very common */\r
-            if(d->nc->n_prompts == 1 && \r
-               d->nc->prompts[0]->type == KHUI_NCPROMPT_TYPE_PASSWORD) {\r
-\r
-                hw = GetDlgItem(d->dlg_main, IDC_NC_PASSWORD);\r
-                EnableWindow(hw, TRUE);\r
-\r
-                d->nc->prompts[0]->flags |= KHUI_NCPROMPT_FLAG_STOCK;\r
-                d->nc->prompts[0]->hwnd_edit = hw;\r
-                d->nc->prompts[0]->hwnd_static = NULL; /* don't care */\r
-\r
-                khui_cw_unlock_nc(d->nc);\r
-                break;\r
-            }\r
-#endif\r
-            /* for everything else */\r
-\r
-            /* hide the stock password controls */\r
-#if 0\r
-            /* TAGREMOVE */\r
-            hw = GetDlgItem(d->dlg_main, IDC_NC_PASSWORD);\r
-            ShowWindow(hw, SW_HIDE);\r
-            hw = GetDlgItem(d->dlg_main, IDC_NC_PASSWORD_LABEL);\r
-            ShowWindow(hw, SW_HIDE);\r
-#endif\r
-\r
-            y = d->r_idspec.bottom;\r
-\r
-            hf = (HFONT) SendMessage(d->dlg_main, WM_GETFONT, 0, 0);\r
-\r
-            if (d->nc->pname != NULL) {\r
-                hw =\r
-                    CreateWindowEx\r
-                    (0,\r
-                     L"STATIC",\r
-                     d->nc->pname,\r
-                     SS_SUNKEN | WS_CHILD,\r
-                     d->r_area.left, y,\r
-                     d->r_row.right, \r
-                     d->r_n_label.bottom - d->r_n_label.top,\r
-                     d->dlg_main,\r
-                     NULL,\r
-                     khm_hInstance,\r
-                     NULL);\r
-\r
-#ifdef DEBUG\r
-                assert(hw);\r
-#endif\r
-                d->hwnd_name = hw;\r
-                SendMessage(hw, WM_SETFONT, (WPARAM)hf, (LPARAM) TRUE);\r
-                ShowWindow(hw, SW_SHOW);\r
-\r
-                y += d->r_n_label.bottom - d->r_n_label.top;\r
-            }\r
-\r
-            if (d->nc->banner != NULL) {\r
-                hw = \r
-                    CreateWindowEx\r
-                    (0,\r
-                     L"STATIC",\r
-                     d->nc->banner,\r
-                     WS_CHILD,\r
-                     d->r_area.left, y,\r
-                     d->r_row.right, d->r_row.bottom,\r
-                     d->dlg_main,\r
-                     NULL,\r
-                     khm_hInstance,\r
-                     NULL);\r
-#ifdef DEBUG\r
-                assert(hw);\r
-#endif\r
-                d->hwnd_banner = hw;\r
-                SendMessage(hw, WM_SETFONT, (WPARAM)hf, (LPARAM)TRUE);\r
-                ShowWindow(hw, SW_SHOW);\r
-                y += d->r_row.bottom;\r
-            }\r
-\r
-            hw_prev = d->hwnd_last_idspec;\r
-\r
-            hdc = GetWindowDC(d->dlg_main);\r
-            hfold = SelectObject(hdc,hf);\r
-\r
-            for(i=0; i<d->nc->n_prompts; i++) {\r
-                RECT pr, er;\r
-                SIZE s;\r
-                int dy;\r
-\r
-                if(d->nc->prompts[i]->prompt != NULL) {\r
-                    GetTextExtentPoint32(hdc, \r
-                                         d->nc->prompts[i]->prompt, \r
-                                         (int) wcslen(d->nc->prompts[i]->prompt),\r
-                                         &s);\r
-                    if(s.cx < d->r_n_label.right - d->r_n_label.left) {\r
-                        CopyRect(&pr, &d->r_n_label);\r
-                        CopyRect(&er, &d->r_n_input);\r
-                        dy = d->r_row.bottom;\r
-                    } else if(s.cx < \r
-                              d->r_e_label.right - d->r_e_label.left) {\r
-                        CopyRect(&pr, &d->r_e_label);\r
-                        CopyRect(&er, &d->r_e_input);\r
-                        dy = d->r_row.bottom;\r
-                    } else {\r
-                        /* oops. the prompt doesn't fit in our\r
-                           controls.  we need to use up two lines */\r
-                        pr.left = 0;\r
-                        pr.right = d->r_row.right;\r
-                        pr.top = 0;\r
-                        pr.bottom = d->r_n_label.bottom - \r
-                            d->r_n_label.top;\r
-                        CopyRect(&er, &d->r_n_input);\r
-                        OffsetRect(&er, 0, pr.bottom);\r
-                        dy = er.bottom + (d->r_row.bottom - \r
-                                          d->r_n_input.bottom);\r
-                    }\r
-                } else {\r
-                    SetRectEmpty(&pr);\r
-                    CopyRect(&er, &d->r_n_input);\r
-                    dy = d->r_row.bottom;\r
-                }\r
-\r
-                if(IsRectEmpty(&pr)) {\r
-                    d->nc->prompts[i]->hwnd_static = NULL;\r
-                } else {\r
-                    OffsetRect(&pr, d->r_area.left, y);\r
-\r
-                    hw = CreateWindowEx\r
-                        (0,\r
-                         L"STATIC",\r
-                         d->nc->prompts[i]->prompt,\r
-                         WS_CHILD,\r
-                         pr.left, pr.top,\r
-                         pr.right - pr.left, pr.bottom - pr.top,\r
-                         d->dlg_main,\r
-                         NULL,\r
-                         khm_hInstance,\r
-                         NULL);\r
-#ifdef DEBUG\r
-                    assert(hw);\r
-#endif\r
-\r
-                    SendMessage(hw, WM_SETFONT, \r
-                                (WPARAM) hf, (LPARAM) TRUE);\r
-\r
-                    SetWindowPos(hw, hw_prev,\r
-                                 0, 0, 0, 0,\r
-                                 SWP_NOACTIVATE | SWP_NOMOVE |\r
-                                 SWP_NOOWNERZORDER | SWP_NOSIZE |\r
-                                 SWP_SHOWWINDOW);\r
-\r
-                    d->nc->prompts[i]->hwnd_static = hw;\r
-                    hw_prev = hw;\r
-                }\r
-\r
-                OffsetRect(&er, d->r_area.left, y);\r
-\r
-                hw = CreateWindowEx\r
-                    (0,\r
-                     L"EDIT",\r
-                     (d->nc->prompts[i]->def ? \r
-                      d->nc->prompts[i]->def : L""),\r
-                     WS_CHILD | WS_TABSTOP |\r
-                     WS_BORDER |\r
-                     ((d->nc->prompts[i]->flags & \r
-                       KHUI_NCPROMPT_FLAG_HIDDEN)? ES_PASSWORD:0),\r
-                     er.left, er.top,\r
-                     er.right - er.left, er.bottom - er.top,\r
-                     d->dlg_main,\r
-                     NULL,\r
-                     khm_hInstance,\r
-                     NULL);\r
-\r
-#ifdef DEBUG\r
-                assert(hw);\r
-#endif\r
-\r
-                SendMessage(hw, WM_SETFONT, \r
-                            (WPARAM) hf, (LPARAM) TRUE);\r
-\r
-                SetWindowPos(hw, hw_prev,\r
-                             0, 0, 0, 0, \r
-                             SWP_NOACTIVATE | SWP_NOMOVE | \r
-                             SWP_NOOWNERZORDER | SWP_NOSIZE | \r
-                             SWP_SHOWWINDOW);\r
-                                \r
-                d->nc->prompts[i]->hwnd_edit = hw;\r
-\r
-                hw_prev = hw;\r
-\r
-                y += dy;\r
-            }\r
-\r
-            SelectObject(hdc, hfold);\r
-            ReleaseDC(d->dlg_main, hdc);\r
-\r
-            khui_cw_unlock_nc(d->nc);\r
-\r
-            d->r_credtext.top = y;\r
-\r
-            nc_position_credtext(d);\r
-        }\r
-        break;\r
-\r
-    case WMNC_DIALOG_PROCESS_COMPLETE:\r
-        {\r
-            khui_new_creds * nc;\r
-\r
-            nc = d->nc;\r
-\r
-            /* reset state */\r
-            nc->result = KHUI_NC_RESULT_CANCEL;\r
-\r
-            if(nc->response & KHUI_NC_RESPONSE_NOEXIT) {\r
-                HWND hw;\r
-\r
-                hw = GetDlgItem(d->dlg_main, IDOK);\r
-                EnableWindow(hw, TRUE);\r
-                hw = GetDlgItem(d->dlg_main, IDCANCEL);\r
-                EnableWindow(hw, TRUE);\r
-                hw = GetDlgItem(d->dlg_bb, IDOK);\r
-                EnableWindow(hw, TRUE);\r
-                hw = GetDlgItem(d->dlg_bb, IDCANCEL);\r
-                EnableWindow(hw, TRUE);\r
-\r
-                return TRUE;\r
-            }\r
-\r
-            DestroyWindow(hwnd);\r
-\r
-            kmq_post_message(KMSG_CRED, KMSG_CRED_END, 0, (void *) nc);\r
-        }\r
-        break;\r
-\r
-        /* MUST be called with SendMessage */\r
-    case WMNC_ADD_CONTROL_ROW:\r
-        {\r
-            khui_control_row * row;\r
-\r
-            row = (khui_control_row *) lParam;\r
-\r
-#ifdef DEBUG\r
-            assert(row->label);\r
-            assert(row->input);\r
-#endif\r
-\r
-            nc_add_control_row(d, row->label, row->input, row->size);\r
-        }\r
-        break;\r
-    } /* switch(HIWORD(wParam)) */\r
-\r
-    return TRUE;\r
-}\r
-\r
-\r
-static LRESULT CALLBACK nc_window_proc(HWND hwnd,\r
-                                       UINT uMsg,\r
-                                       WPARAM wParam,\r
-                                       LPARAM lParam)\r
-{\r
-    switch(uMsg) {\r
-    case WM_CREATE:\r
-        return nc_handle_wm_create(hwnd, uMsg, wParam, lParam);\r
-\r
-    case WM_DESTROY:\r
-        return nc_handle_wm_destroy(hwnd, uMsg, wParam, lParam);\r
-\r
-    case WM_COMMAND:\r
-        return nc_handle_wm_command(hwnd, uMsg, wParam, lParam);\r
-\r
-    case WM_MOVE:\r
-    case WM_MOVING:\r
-        return nc_handle_wm_moving(hwnd, uMsg, wParam, lParam);\r
-\r
-    case KHUI_WM_NC_NOTIFY:\r
-        return nc_handle_wm_nc_notify(hwnd, uMsg, wParam, lParam);\r
-    }\r
-\r
-    /* Note that this is technically a dialog box */\r
-    return DefDlgProc(hwnd, uMsg, wParam, lParam);\r
-}\r
-\r
-void khm_register_newcredwnd_class(void)\r
-{\r
-    WNDCLASSEX wcx;\r
-\r
-    wcx.cbSize = sizeof(wcx);\r
-    wcx.style = CS_DBLCLKS | CS_OWNDC;\r
-    wcx.lpfnWndProc = nc_window_proc;\r
-    wcx.cbClsExtra = 0;\r
-    wcx.cbWndExtra = DLGWINDOWEXTRA + sizeof(LONG_PTR);\r
-    wcx.hInstance = khm_hInstance;\r
-    wcx.hIcon = LoadIcon(khm_hInstance, MAKEINTRESOURCE(IDI_MAIN_APP));\r
-    wcx.hCursor = LoadCursor((HINSTANCE) NULL, IDC_ARROW);\r
-    wcx.hbrBackground = (HBRUSH) (COLOR_BACKGROUND + 1);\r
-    wcx.lpszMenuName = NULL;\r
-    wcx.lpszClassName = KHUI_NEWCREDWND_CLASS;\r
-    wcx.hIconSm = NULL;\r
-\r
-    khui_newcredwnd_cls = RegisterClassEx(&wcx);\r
-}\r
-\r
-void khm_unregister_newcredwnd_class(void)\r
-{\r
-    UnregisterClass((LPWSTR) khui_newcredwnd_cls, khm_hInstance);\r
-}\r
-\r
-HWND khm_create_newcredwnd(HWND parent, khui_new_creds * c)\r
-{\r
-    wchar_t wtitle[256];\r
-    HWND hwnd;\r
-\r
-    if (c->window_title == NULL) {\r
-        if (c->subtype == KMSG_CRED_PASSWORD)\r
-            LoadString(khm_hInstance, \r
-                       IDS_WT_PASSWORD,\r
-                       wtitle,\r
-                       ARRAYLENGTH(wtitle));\r
-        else\r
-            LoadString(khm_hInstance, \r
-                       IDS_WT_NEW_CREDS,\r
-                       wtitle,\r
-                       ARRAYLENGTH(wtitle));\r
-    }\r
-\r
-    hwnd = CreateWindowEx(WS_EX_DLGMODALFRAME | WS_EX_CONTEXTHELP,\r
-                          MAKEINTATOM(khui_newcredwnd_cls),\r
-                          ((c->window_title)?c->window_title: wtitle),\r
-                          WS_DLGFRAME | WS_POPUPWINDOW | WS_CLIPCHILDREN,\r
-                          0,0,400,400,    /* bogus values.  the window\r
-                                             is going to resize and\r
-                                             reposition itself\r
-                                             anyway */\r
-                          parent,\r
-                          NULL,\r
-                          khm_hInstance,\r
-                          (LPVOID) c);\r
-\r
-#ifdef DEBUG\r
-    assert(hwnd != NULL);\r
-#endif\r
-\r
-    /* note that the window is not visible yet.  That's because, at\r
-       this point we don't know what the panels are */\r
-\r
-    return hwnd;\r
-}\r
-\r
-void khm_prep_newcredwnd(HWND hwnd)\r
-{\r
-    SendMessage(hwnd, KHUI_WM_NC_NOTIFY, \r
-                MAKEWPARAM(0, WMNC_DIALOG_SETUP), 0);\r
-}\r
-\r
-void khm_show_newcredwnd(HWND hwnd)\r
-{\r
-    /* add all the panels in and prep UI */\r
-    SendMessage(hwnd, KHUI_WM_NC_NOTIFY, \r
-                MAKEWPARAM(0, WMNC_DIALOG_ACTIVATE), 0);\r
-}\r
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ * Copyright (c) 2007 Secure Endpoints Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+/* Include the OEMRESOURCE constants for locating standard icon
+   resources. */
+#define OEMRESOURCE
+
+#include<khmapp.h>
+#if _WIN32_WINNT >= 0x0501
+#include<uxtheme.h>
+#endif
+#include<assert.h>
+
+ATOM khui_newcredwnd_cls;
+
+/* forward dcl */
+static void
+nc_position_credtext(khui_nc_wnd_data * d);
+
+/* Common dialog procedure used by the main credential panel
+   (IDD_NC_NEWCRED) and the button bar (IDC_NC_BBAR). */
+
+static void
+nc_layout_main_panel(khui_nc_wnd_data * d);
+
+static void
+nc_layout_new_cred_window(khui_nc_wnd_data * d);
+
+static INT_PTR CALLBACK
+nc_common_dlg_proc(HWND hwnd,
+                   UINT uMsg,
+                   WPARAM wParam,
+                   LPARAM lParam)
+{
+    switch(uMsg) {
+    case WM_INITDIALOG:
+        {
+            khui_nc_wnd_data * d;
+
+            d = (khui_nc_wnd_data *) lParam;
+
+#pragma warning(push)
+#pragma warning(disable: 4244)
+            SetWindowLongPtr(hwnd, DWLP_USER, lParam);
+#pragma warning(pop)
+
+            if (d->nc->subtype == KMSG_CRED_PASSWORD) {
+                ShowWindow(GetDlgItem(hwnd, IDC_NC_ADVANCED),
+                           SW_HIDE);
+            }
+        }
+        return TRUE;
+
+    case WM_COMMAND:
+        {
+            int ctrl_id;
+
+            ctrl_id = LOWORD(wParam);
+            if (ctrl_id < KHUI_CW_ID_MIN ||
+                ctrl_id > KHUI_CW_ID_MAX) {
+                /* pump it to the parent */
+                PostMessage(GetParent(hwnd), WM_COMMAND, wParam, lParam);
+                return TRUE;
+            } /* else we allow the message to fall through and get
+                 passed into the identity provider's message
+                 handler. */
+        }
+        break;
+
+    case KHUI_WM_NC_NOTIFY:
+        {
+            khui_nc_wnd_data * d;
+            d = (khui_nc_wnd_data *)(LONG_PTR)
+                GetWindowLongPtr(hwnd, DWLP_USER);
+            if (d == NULL)
+                break;
+
+            /* message sent by parent to notify us of something */
+            switch(HIWORD(wParam)) {
+            case WMNC_DIALOG_EXPAND:
+                /* fallthrough */
+            case WMNC_UPDATE_LAYOUT:
+                if(hwnd == d->dlg_main) {
+
+                    nc_layout_main_panel(d);
+
+                    return TRUE;
+                }
+                break;          /* nop */
+            }
+        }
+        return TRUE;
+    }
+
+    /* check if we have a wnd_data, and if so pass the message on to
+       the identity provider callback. */
+    {
+        khui_nc_wnd_data * d;
+
+        d = (khui_nc_wnd_data *) (LONG_PTR)
+            GetWindowLongPtr(hwnd, DWLP_USER);
+
+        /* TODO: filter out and forward only the messages that
+           originated or pertain to the identity selection
+           controls. */
+        if (d && d->nc && d->nc->ident_cb) {
+            return d->nc->ident_cb(d->nc, WMNC_IDENT_WMSG, hwnd, uMsg,
+                                   wParam, lParam);
+        }
+    }
+
+    return FALSE;
+}
+
+static void
+nc_notify_clear(khui_nc_wnd_data * d) {
+
+    if (d->notif_type == NC_NOTIFY_NONE)
+        /* there are no notifications anyway. */
+        return;
+
+    if (d->hwnd_notif_label)
+        DestroyWindow(d->hwnd_notif_label);
+
+    if (d->hwnd_notif_aux)
+        DestroyWindow(d->hwnd_notif_aux);
+
+    d->hwnd_notif_label = NULL;
+    d->hwnd_notif_aux = NULL;
+
+    SetRectEmpty(&d->r_notif);
+
+    d->notif_type = NC_NOTIFY_NONE;
+
+    /* Note that we must call nc_layout_main_panel() after calling
+       this to adjust the layout of the main panel.  However we aren't
+       calling it here since we might want to add another set of
+       notifications or make other changes to the main panel content
+       before calling nc_layout_main_panel(). */
+}
+
+static void
+nc_notify_marquee(khui_nc_wnd_data * d, const wchar_t * label) {
+
+#if (_WIN32_IE >= 0x0600)
+    HDC hdc;
+    size_t length;
+    SIZE label_size;
+#endif
+
+    RECT r_label;
+    RECT r_mq;
+    RECT r_row;
+    HFONT hfont;
+    HWND hwnd;
+    HDWP hdefer;
+
+    /* Clear the notification area.  We only support one notification
+       at a time. */
+    nc_notify_clear(d);
+
+#ifdef DEBUG
+    assert(d->dlg_main);
+#endif
+
+#if (_WIN32_IE >= 0x0600)
+
+    /* We can only show the marquee control if the comctl32 DLL is
+       version 6.0 or later.  Otherwise we only show the label. */
+
+    if (FAILED(StringCchLength(label, KHUI_MAXCCH_SHORT_DESC, &length))) {
+#ifdef DEBUG
+        assert(FALSE);
+#endif
+        length = KHUI_MAXCCH_SHORT_DESC;
+    }
+
+    /* See how big the notification control needs to be. */
+
+    hdc = GetDC(d->dlg_main);
+#ifdef DEBUG
+    assert(hdc != NULL);
+#endif
+
+    GetTextExtentPoint32(hdc, label, (int) length, &label_size);
+
+    ReleaseDC(d->dlg_main, hdc);
+
+    CopyRect(&r_row, &d->r_row);
+
+    if (label_size.cx > d->r_e_label.right - d->r_e_label.left) {
+        /* using an entire row */
+        CopyRect(&r_label, &d->r_row);
+        CopyRect(&r_mq, &d->r_n_input);
+        OffsetRect(&r_mq, 0, r_row.bottom - r_row.top);
+        r_row.bottom += r_row.bottom - r_row.top;
+    } else if (label_size.cx > d->r_n_label.right - d->r_n_label.left) {
+        /* using large labels */
+        CopyRect(&r_label, &d->r_e_label);
+        CopyRect(&r_mq, &d->r_e_input);
+    } else {
+        /* normal labels */
+        CopyRect(&r_label, &d->r_n_label);
+        CopyRect(&r_mq, &d->r_n_input);
+    }
+
+    InflateRect(&r_mq, 0, - ((r_mq.bottom - r_mq.top) / 4));
+
+#else  /* _WIN32_IE < 0x0600 */
+
+    /* We are just showing the label */
+    CopyRect(&r_row, &d->r_row);
+    CopyRect(&r_label, &r_row);
+    SetRectEmpty(&r_mq);
+
+#endif /* _WIN32_IE >= 0x0600 */
+
+    {
+        long y;
+
+        if (IsRectEmpty(&d->r_custprompt)) {
+            y = d->r_idspec.bottom;
+        } else {
+            y = d->r_custprompt.bottom;
+        }
+
+        OffsetRect(&r_row, d->r_area.left, y);
+        OffsetRect(&r_label, r_row.left, r_row.top);
+        OffsetRect(&r_mq, r_row.left, r_row.top);
+    }
+
+    hfont = (HFONT) SendMessage(d->dlg_main, WM_GETFONT, 0, 0);
+
+    hdefer = BeginDeferWindowPos(2);
+
+    /* the label */
+    hwnd = CreateWindowEx(0,
+                          L"STATIC",
+                          label,
+                          WS_CHILD | SS_ENDELLIPSIS,
+                          r_label.left, r_label.top,
+                          r_label.right - r_label.left,
+                          r_label.bottom - r_label.top,
+                          d->dlg_main,
+                          NULL, NULL, NULL);
+#ifdef DEBUG
+    assert(hwnd != NULL);
+#endif
+    SendMessage(hwnd, WM_SETFONT, (WPARAM) hfont, (LPARAM) TRUE);
+
+    DeferWindowPos(hdefer, hwnd, NULL,
+                   0, 0, 0, 0,
+                   SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER |
+                   SWP_NOSIZE | SWP_SHOWWINDOW);
+
+    d->hwnd_notif_label = hwnd;
+
+    /* and the marquee */
+
+#if (_WIN32_IE >= 0x0600)
+
+    /* unfortunately, the marquee is only available on comctl32
+       version 6.0 or later.  On previous versions, we only display
+       the message label. */
+
+    hwnd = CreateWindowEx(0,
+                          PROGRESS_CLASS,
+                          L"",
+                          WS_CHILD | PBS_MARQUEE,
+                          r_mq.left, r_mq.top,
+                          r_mq.right - r_mq.left,
+                          r_mq.bottom - r_mq.top,
+                          d->dlg_main,
+                          NULL, NULL, NULL);
+#ifdef DEBUG
+    assert(hwnd != NULL);
+#endif
+
+    SendMessage(hwnd, PBM_SETMARQUEE, TRUE, 100);
+
+    DeferWindowPos(hdefer, hwnd, NULL,
+                   0, 0, 0, 0,
+                   SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER |
+                   SWP_NOSIZE | SWP_SHOWWINDOW);
+
+    d->hwnd_notif_aux = hwnd;
+
+#endif /* _WIN32_IE >= 0x0600 */
+
+    EndDeferWindowPos(hdefer);
+
+    CopyRect(&d->r_notif, &r_row);
+
+    d->notif_type = NC_NOTIFY_MARQUEE;
+
+    /* Note that we must call nc_layout_main_panel() after calling
+       this to adjust the layout of the main panel.  However we aren't
+       calling it here since we might want to add another set of
+       notifications or make other changes to the main panel content
+       before calling nc_layout_main_panel(). */
+}
+
+static void
+nc_notify_message(khui_nc_wnd_data * d,
+                  kherr_severity severity,
+                  const wchar_t * message) {
+
+    SIZE icon_size;
+    LPCTSTR icon_res;
+    HICON h_icon;
+    HWND hwnd;
+    HFONT hfont;
+    HDWP hdefer;
+
+    RECT r_row;
+    RECT r_label;
+    RECT r_icon;
+
+    nc_notify_clear(d);
+
+    icon_size.cx = GetSystemMetrics(SM_CXSMICON);
+    icon_size.cy = GetSystemMetrics(SM_CYSMICON);
+
+    switch(severity) {
+    case KHERR_INFO:
+        icon_res = MAKEINTRESOURCE(OIC_INFORMATION);
+        break;
+
+    case KHERR_WARNING:
+        icon_res = MAKEINTRESOURCE(OIC_WARNING);
+        break;
+
+    case KHERR_ERROR:
+        icon_res = MAKEINTRESOURCE(OIC_ERROR);
+        break;
+
+    default:
+        icon_res = NULL;
+    }
+
+    if (icon_res != NULL) {
+        h_icon = (HICON) LoadImage(NULL,
+                                   icon_res,
+                                   IMAGE_ICON,
+                                   icon_size.cx,
+                                   icon_size.cy,
+                                   LR_DEFAULTCOLOR | LR_SHARED);
+    } else {
+        h_icon = NULL;
+    }
+
+    CopyRect(&r_row, &d->r_row);
+
+#define CENTERVALUE(w,v) ((w)/2 - (v)/2)
+
+    SetRect(&r_icon,
+            0, CENTERVALUE(r_row.bottom - r_row.top, icon_size.cy),
+            icon_size.cx,
+            CENTERVALUE(r_row.bottom - r_row.top, icon_size.cy) + icon_size.cy);
+
+#undef CENTERVALUE
+
+    CopyRect(&r_label, &r_row);
+    OffsetRect(&r_label, -r_label.left, -r_label.top);
+    r_label.left += (icon_size.cx * 3) / 2;
+
+    {
+        long y;
+
+        if (IsRectEmpty(&d->r_custprompt)) {
+            y = d->r_idspec.bottom;
+        } else {
+            y = d->r_custprompt.bottom;
+        }
+
+        OffsetRect(&r_row, d->r_area.left, y);
+        OffsetRect(&r_label, r_row.left, r_row.top);
+        OffsetRect(&r_icon, r_row.left, r_row.top);
+    }
+
+    hfont = (HFONT) SendMessage(d->dlg_main, WM_GETFONT, 0, 0);
+
+    hdefer = BeginDeferWindowPos(2);
+
+    hwnd = CreateWindowEx(0,
+                          L"STATIC",
+                          message,
+                          WS_CHILD | SS_ENDELLIPSIS | SS_CENTER,
+                          r_label.left, r_label.top,
+                          r_label.right - r_label.left,
+                          r_label.bottom - r_label.top,
+                          d->dlg_main,
+                          NULL, NULL, NULL);
+#ifdef DEBUG
+    assert(hwnd != NULL);
+#endif
+    SendMessage(hwnd, WM_SETFONT, (WPARAM) hfont, (LPARAM) TRUE);
+
+    DeferWindowPos(hdefer, hwnd, NULL,
+                   0, 0, 0, 0,
+                   SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER |
+                   SWP_NOSIZE | SWP_SHOWWINDOW);
+
+    d->hwnd_notif_label = hwnd;
+
+    hwnd = CreateWindowEx(0,
+                          L"STATIC",
+                          NULL,
+                          WS_CHILD | SS_ICON |
+#if (_WIN32_IE >= 0x0600)
+                          SS_REALSIZECONTROL
+#else
+                          0
+#endif
+                          ,
+                          r_icon.left, r_icon.top,
+                          r_icon.right - r_icon.left,
+                          r_icon.bottom - r_icon.top,
+                          d->dlg_main,
+                          NULL, NULL, NULL);
+#ifdef DEBUG
+    assert(hwnd != NULL);
+#endif
+
+    if (h_icon && hwnd)
+        SendMessage(hwnd, STM_SETICON, (WPARAM) h_icon, 0);
+
+    DeferWindowPos(hdefer, hwnd, NULL,
+                   0, 0, 0, 0,
+                   SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER |
+                   SWP_NOSIZE | SWP_SHOWWINDOW | SWP_NOZORDER);
+
+    d->hwnd_notif_aux = hwnd;
+
+    EndDeferWindowPos(hdefer);
+
+    CopyRect(&d->r_notif, &r_row);
+
+    d->notif_type = NC_NOTIFY_MESSAGE;
+
+    /* Note that we must call nc_layout_main_panel() after calling
+       this to adjust the layout of the main panel.  However we aren't
+       calling it here since we might want to add another set of
+       notifications or make other changes to the main panel content
+       before calling nc_layout_main_panel(). */
+}
+
+static void
+nc_layout_main_panel(khui_nc_wnd_data * d)
+{
+    RECT r_main;
+    HWND hw_ct;
+    HWND hw_ct_label;
+    HDWP hdwp;
+    RECT r_used;                /* extent used by identity specifiers,
+                                   custom prompts and notificaiton
+                                   controls. */
+
+    RECT r_wmain;              /* extents of the main window in screen
+                                  coordinates. */
+
+    r_main.left = 0;
+    r_main.top = 0;
+    r_main.bottom = NCDLG_HEIGHT;
+    r_main.right = NCDLG_WIDTH;
+
+    MapDialogRect(d->dlg_main, &r_main);
+
+    CopyRect(&r_used, &d->r_idspec);
+
+    GetWindowRect(d->dlg_main, &r_wmain);
+
+    hdwp = BeginDeferWindowPos(7);
+
+    /* check if the notification area and the custom prompt area are
+       overlapping. */
+
+    if (d->notif_type != NC_NOTIFY_NONE) {
+        long delta_y = 0;
+        RECT r;
+
+        CopyRect(&r, &d->r_custprompt);
+
+        if (IsRectEmpty(&d->r_custprompt)) {
+            /* if there are no custom prompts, then the notification
+               area should be immediately below the identitify
+               specifers. */
+
+            delta_y = d->r_idspec.bottom - d->r_notif.top;
+        } else {
+            /* otherwise, the notification area should be immediately
+               below the custom prompt area */
+
+            delta_y = d->r_custprompt.bottom - d->r_notif.top;
+        }
+
+        if (delta_y != 0) {
+            RECT r_lbl;
+            RECT r_aux;
+
+            if (d->hwnd_notif_label) {
+                GetWindowRect(d->hwnd_notif_label, &r_lbl);
+                OffsetRect(&r_lbl, -r_wmain.left, delta_y - r_wmain.top);
+
+                DeferWindowPos(hdwp, d->hwnd_notif_label, NULL,
+                               r_lbl.left, r_lbl.top, 0, 0,
+                               SWP_NOACTIVATE | SWP_NOOWNERZORDER |
+                               SWP_NOZORDER | SWP_NOSIZE);
+            }
+
+            if (d->hwnd_notif_aux) {
+                GetWindowRect(d->hwnd_notif_aux, &r_aux);
+                OffsetRect(&r_aux, -r_wmain.left, delta_y - r_wmain.top);
+
+                DeferWindowPos(hdwp, d->hwnd_notif_aux, NULL,
+                               r_aux.left, r_aux.top, 0, 0,
+                               SWP_NOACTIVATE | SWP_NOOWNERZORDER |
+                               SWP_NOZORDER | SWP_NOSIZE);
+            }
+
+            OffsetRect(&d->r_notif, 0, delta_y);
+        }
+    }
+
+    if (!IsRectEmpty(&d->r_custprompt)) {
+        r_used.bottom = max(d->r_custprompt.bottom,
+                            r_used.bottom);
+    }
+
+    if (!IsRectEmpty(&d->r_notif)) {
+        r_used.bottom = max(d->r_notif.bottom,
+                            r_used.bottom);
+    }
+
+    if (d->nc->mode == KHUI_NC_MODE_MINI) {
+        RECT r_ok;
+        RECT r_cancel;
+        RECT r_advanced;
+        HWND hw;
+
+        hw = GetDlgItem(d->dlg_main, IDOK);
+#ifdef DEBUG
+        assert(hw != NULL);
+#endif
+        GetWindowRect(hw, &r_ok);
+        OffsetRect(&r_ok, -r_wmain.left, -r_ok.top + r_used.bottom);
+
+        DeferWindowPos(hdwp, hw, NULL,
+                       r_ok.left, r_ok.top, 0, 0,
+                       SWP_NOACTIVATE | SWP_NOOWNERZORDER |
+                       SWP_NOZORDER | SWP_NOSIZE | SWP_SHOWWINDOW);
+
+        hw = GetDlgItem(d->dlg_main, IDCANCEL);
+#ifdef DEBUG
+        assert(hw != NULL);
+#endif
+        GetWindowRect(hw, &r_cancel);
+        OffsetRect(&r_cancel, -r_wmain.left, -r_cancel.top + r_used.bottom);
+
+        DeferWindowPos(hdwp, hw, NULL,
+                       r_cancel.left, r_cancel.top, 0, 0,
+                       SWP_NOACTIVATE | SWP_NOOWNERZORDER |
+                       SWP_NOZORDER | SWP_NOSIZE | SWP_SHOWWINDOW);
+
+        hw = GetDlgItem(d->dlg_main, IDC_NC_ADVANCED);
+#ifdef DEBUG
+        assert(hw != NULL);
+#endif
+        GetWindowRect(hw, &r_advanced);
+        OffsetRect(&r_advanced, -r_wmain.left, -r_advanced.top + r_used.bottom);
+
+        DeferWindowPos(hdwp, hw, NULL,
+                       r_advanced.left, r_advanced.top, 0, 0,
+                       SWP_NOACTIVATE | SWP_NOOWNERZORDER |
+                       SWP_NOZORDER | SWP_NOSIZE | SWP_SHOWWINDOW);
+
+        /* and now update the extents of the main panel */
+        r_main.bottom = r_used.bottom + (r_ok.bottom - r_ok.top) + d->r_area.top;
+
+        CopyRect(&d->r_main, &r_main);
+
+    } else {
+
+        HWND hw;
+
+        hw = GetDlgItem(d->dlg_main, IDOK);
+#ifdef DEBUG
+        assert(hw != NULL);
+#endif
+        if (IsWindowVisible(hw))
+            DeferWindowPos(hdwp, hw, NULL,
+                           0, 0, 0, 0,
+                           SWP_HIDEWINDOW | SWP_NOMOVE | SWP_NOSIZE |
+                           SWP_NOOWNERZORDER | SWP_NOZORDER);
+
+        hw = GetDlgItem(d->dlg_main, IDCANCEL);
+#ifdef DEBUG
+        assert(hw != NULL);
+#endif
+        if (IsWindowVisible(hw))
+            DeferWindowPos(hdwp, hw, NULL,
+                           0, 0, 0, 0,
+                           SWP_HIDEWINDOW | SWP_NOMOVE | SWP_NOSIZE |
+                           SWP_NOOWNERZORDER | SWP_NOZORDER);
+
+        hw = GetDlgItem(d->dlg_main, IDC_NC_ADVANCED);
+#ifdef DEBUG
+        assert(hw != NULL);
+#endif
+        if (IsWindowVisible(hw))
+            DeferWindowPos(hdwp, hw, NULL,
+                           0, 0, 0, 0,
+                           SWP_HIDEWINDOW | SWP_NOMOVE | SWP_NOSIZE |
+                           SWP_NOOWNERZORDER | SWP_NOZORDER);
+
+        d->r_credtext.top = r_used.bottom;
+
+        CopyRect(&d->r_main, &r_main);
+    }
+
+    /* now update the layout of the credentials text window */
+
+    hw_ct = GetDlgItem(d->dlg_main, IDC_NC_CREDTEXT);
+    hw_ct_label = GetDlgItem(d->dlg_main, IDC_NC_CREDTEXT_LABEL);
+#ifdef DEBUG
+    assert(hw_ct != NULL);
+    assert(hw_ct_label != NULL);
+#endif
+
+    if (d->nc->mode == KHUI_NC_MODE_MINI ||
+        d->r_credtext.bottom < d->r_credtext.top + d->r_row.bottom * 2) {
+
+        /* either we aren't supposed to show the credentials text
+           window, or we don't have enough room. */
+        if (IsWindowVisible(hw_ct) || IsWindowVisible(hw_ct_label)) {
+
+            DeferWindowPos(hdwp, hw_ct, NULL,
+                           0, 0, 0, 0,
+                           SWP_HIDEWINDOW | SWP_NOOWNERZORDER |
+                           SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE);
+
+            DeferWindowPos(hdwp, hw_ct_label, NULL,
+                           0, 0, 0, 0,
+                           SWP_HIDEWINDOW | SWP_NOOWNERZORDER |
+                           SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE);
+
+        }
+
+    } else {
+
+        DeferWindowPos(hdwp,
+                       hw_ct, NULL,
+                       d->r_credtext.left + d->r_n_input.left, /* x */
+                       d->r_credtext.top, /* y */
+                       d->r_n_input.right - d->r_n_input.left, /* width */
+                       d->r_credtext.bottom - d->r_credtext.top, /* height */
+                       SWP_NOACTIVATE | SWP_NOOWNERZORDER |
+                       SWP_NOZORDER | SWP_SHOWWINDOW);
+
+        DeferWindowPos(hdwp,
+                       hw_ct_label, NULL,
+                       d->r_credtext.left + d->r_n_label.left, /* x */
+                       d->r_credtext.top, /* y */
+                       d->r_n_label.right - d->r_n_label.left, /* width */
+                       d->r_n_label.bottom - d->r_n_label.top, /* height */
+                       SWP_NOACTIVATE | SWP_NOOWNERZORDER |
+                       SWP_NOZORDER | SWP_SHOWWINDOW);
+    }
+
+    EndDeferWindowPos(hdwp);
+
+    /* NOTE: although we updated d->r_main, if the new credentials
+       window is in mini mode, we must call
+       nc_layout_new_cred_window() to adjust the size of the new
+       credentials window to fit the main panel.  We don't do it here
+       because we need to keep these two operations separate. */
+}
+
+/* Credential type panel comparison function.  Tabs are sorted based
+   on the following criteria:
+
+   1) By ordinal - Panels with ordinal -1 will be ranked after panels
+      whose ordinal is not -1.
+
+   2) By name - Case insensitive comparison of the name.  If the panel
+      does not have a name (i.e. the ->name member is NULL, it will be
+      ranked after panels which have a name.
+ */
+static int __cdecl
+nc_tab_sort_func(const void * v1, const void * v2)
+{
+    /* v1 and v2 and of type : khui_new_creds_by_type ** */
+    khui_new_creds_by_type *t1, *t2;
+
+    t1 = *((khui_new_creds_by_type **) v1);
+    t2 = *((khui_new_creds_by_type **) v2);
+
+    if(t1->ordinal !=  -1) {
+        if(t2->ordinal != -1) {
+            if(t1->ordinal == t2->ordinal) {
+                if (t1->name && t2->name)
+                    return _wcsicmp(t1->name, t2->name);
+                else if (t1->name)
+                    return -1;
+                else if (t2->name)
+                    return 1;
+                else
+                    return 0;
+            } else {
+                /* safe to convert to an int here */
+                return (int) (t1->ordinal - t2->ordinal);
+            }
+        } else
+            return -1;
+    } else {
+        if(t2->ordinal != -1)
+            return 1;
+        else if (t1->name && t2->name)
+            return wcscmp(t1->name, t2->name);
+        else if (t1->name)
+            return -1;
+        else if (t2->name)
+            return 1;
+        else
+            return 0;
+    }
+}
+
+static void
+nc_notify_types(khui_new_creds * c, UINT uMsg,
+                WPARAM wParam, LPARAM lParam, BOOL sync)
+{
+    khm_size i;
+
+    for(i=0; i<c->n_types; i++) {
+
+        if (c->types[i]->hwnd_panel == NULL)
+            continue;
+
+        if (sync)
+            SendMessage(c->types[i]->hwnd_panel, uMsg, wParam, lParam);
+        else
+            PostMessage(c->types[i]->hwnd_panel, uMsg, wParam, lParam);
+    }
+}
+
+static void
+nc_clear_password_fields(khui_nc_wnd_data * d)
+{
+    khm_size i;
+    khm_boolean need_sync = FALSE;
+
+    khui_cw_lock_nc(d->nc);
+
+    for (i=0; i < d->nc->n_prompts; i++) {
+        if ((d->nc->prompts[i]->flags & KHUI_NCPROMPT_FLAG_HIDDEN) &&
+            d->nc->prompts[i]->hwnd_edit) {
+            SetWindowText(d->nc->prompts[i]->hwnd_edit,
+                          L"");
+            need_sync = TRUE;
+        }
+    }
+
+    khui_cw_unlock_nc(d->nc);
+
+    if (need_sync) {
+        khui_cw_sync_prompt_values(d->nc);
+    }
+}
+
+/* used by nc_enable_controls */
+
+struct nc_enum_wnd_data {
+    khui_nc_wnd_data * d;
+    khm_boolean enable;
+};
+
+static
+BOOL CALLBACK
+nc_enum_wnd_proc(HWND hwnd,
+                 LPARAM lParam)
+{
+    struct nc_enum_wnd_data * wd;
+
+    wd = (struct nc_enum_wnd_data *) lParam;
+
+    EnableWindow(hwnd, wd->enable);
+
+    return TRUE;
+}
+
+static void
+nc_enable_controls(khui_nc_wnd_data * d, khm_boolean enable)
+{
+    struct nc_enum_wnd_data wd;
+
+    ZeroMemory(&wd, sizeof(wd));
+
+    wd.d = d;
+    wd.enable = enable;
+
+    EnumChildWindows(d->dlg_main, nc_enum_wnd_proc, (LPARAM) &wd);
+}
+
+#define NC_MAXCCH_CREDTEXT 16384
+#define NC_MAXCB_CREDTEXT (NC_MAXCCH_CREDTEXT * sizeof(wchar_t))
+
+static void
+nc_update_credtext(khui_nc_wnd_data * d)
+{
+    wchar_t * ctbuf = NULL;
+    wchar_t * buf;
+    BOOL okEnable = FALSE;
+    BOOL validId = FALSE;
+    HWND hw = NULL;
+    size_t cch = 0;
+
+    ctbuf = PMALLOC(NC_MAXCB_CREDTEXT);
+
+    assert(ctbuf != NULL);
+
+    LoadString(khm_hInstance, IDS_NC_CREDTEXT_TABS, ctbuf, NC_MAXCCH_CREDTEXT);
+    StringCchLength(ctbuf, NC_MAXCCH_CREDTEXT, &cch);
+    buf = ctbuf + cch;
+    nc_notify_types(d->nc, KHUI_WM_NC_NOTIFY,
+                    MAKEWPARAM(0, WMNC_UPDATE_CREDTEXT), (LPARAM) d->nc, TRUE);
+
+    /* hopefully all the types have updated their credential texts */
+
+    /* if the dialog is in the mini mode, we have to display
+       exceptions using a notification. */
+    if (d->nc->mode == KHUI_NC_MODE_MINI) {
+        BOOL need_layout = FALSE;
+        if (d->nc->n_identities == 0) {
+
+            /* There are no identities selected. We don't show any
+               notifications here. */
+            if (d->notif_type != NC_NOTIFY_NONE) {
+                nc_notify_clear(d);
+                need_layout = TRUE;
+            }
+
+        } else {
+
+            wchar_t id_name[KCDB_IDENT_MAXCCH_NAME];
+            wchar_t format[256];
+            wchar_t msg[ARRAYLENGTH(format) + ARRAYLENGTH(id_name)];
+            khm_size cbbuf;
+            khm_int32 flags;
+
+            kcdb_identity_get_flags(d->nc->identities[0], &flags);
+
+            cbbuf = sizeof(id_name);
+            kcdb_identity_get_name(d->nc->identities[0], id_name, &cbbuf);
+
+            if (flags & KCDB_IDENT_FLAG_INVALID) {
+
+                /* identity is invalid */
+                LoadString(khm_hInstance, IDS_NCN_IDENT_INVALID,
+                           format, ARRAYLENGTH(format));
+                StringCbPrintf(msg, sizeof(msg), format, id_name);
+
+                nc_notify_message(d, KHERR_ERROR, msg);
+
+                need_layout = TRUE;
+
+            } else if ((flags & KCDB_IDENT_FLAG_VALID) ||
+                       d->nc->subtype == KMSG_CRED_PASSWORD) {
+                /* special case: If we are going to change the
+                   password, we don't expect the identity provider to
+                   validate the identity in real time.  As such, we
+                   assume that the identity is valid. */
+
+               /* identity is valid */
+                if (d->notif_type != NC_NOTIFY_NONE) {
+                    nc_notify_clear(d);
+                    need_layout = TRUE;
+                }
+
+            } else if (flags & KCDB_IDENT_FLAG_UNKNOWN) {
+
+                /* unknown state */
+                LoadString(khm_hInstance, IDS_NCN_IDENT_UNKNOWN,
+                           format, ARRAYLENGTH(format));
+                StringCbPrintf(msg, sizeof(msg), format, id_name);
+
+                nc_notify_message(d, KHERR_WARNING, msg);
+
+                need_layout = TRUE;
+
+            } else {
+
+                /* still checking */
+                LoadString(khm_hInstance, IDS_NCN_IDENT_CHECKING,
+                           format, ARRAYLENGTH(format));
+                StringCbPrintf(msg, sizeof(msg), format, id_name);
+
+                nc_notify_marquee(d, msg);
+
+                need_layout = TRUE;
+
+            }
+        }
+
+        if (need_layout) {
+            nc_layout_main_panel(d);
+            nc_layout_new_cred_window(d);
+        }
+    }
+
+    if(d->nc->n_identities == 1) {
+        wchar_t main_fmt[256];
+        wchar_t id_fmt[256];
+        wchar_t id_name[KCDB_IDENT_MAXCCH_NAME];
+        wchar_t id_string[KCDB_IDENT_MAXCCH_NAME + 256];
+        khm_size cbbuf;
+        khm_int32 flags;
+
+        LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_ONE,
+                   main_fmt, (int) ARRAYLENGTH(main_fmt));
+
+        cbbuf = sizeof(id_name);
+        kcdb_identity_get_name(d->nc->identities[0], id_name, &cbbuf);
+
+        kcdb_identity_get_flags(d->nc->identities[0], &flags);
+
+        if (flags & KCDB_IDENT_FLAG_INVALID) {
+            LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_INVALID,
+                       id_fmt, (int) ARRAYLENGTH(id_fmt));
+        } else if(flags & KCDB_IDENT_FLAG_VALID) {
+            LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_VALID,
+                       id_fmt, (int) ARRAYLENGTH(id_fmt));
+        } else if(flags & KCDB_IDENT_FLAG_UNKNOWN) {
+            LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_UNCHECKED,
+                       id_fmt, (int) ARRAYLENGTH(id_fmt));
+        } else if(d->nc->subtype == KMSG_CRED_NEW_CREDS) {
+            LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_CHECKING,
+                       id_fmt, (int) ARRAYLENGTH(id_fmt));
+        } else {
+            LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_UNCHECKED,
+                       id_fmt, (int) ARRAYLENGTH(id_fmt));
+        }
+
+        StringCbPrintf(id_string, sizeof(id_string), id_fmt, id_name);
+
+        StringCbPrintf(buf, NC_MAXCB_CREDTEXT - cch*sizeof(wchar_t),
+                       main_fmt, id_string);
+
+        if (flags & KCDB_IDENT_FLAG_VALID) {
+            if (flags & KCDB_IDENT_FLAG_DEFAULT)
+                LoadString(khm_hInstance, IDS_NC_ID_DEF,
+                           id_string, ARRAYLENGTH(id_string));
+            else if (d->nc->set_default)
+                LoadString(khm_hInstance, IDS_NC_ID_WDEF,
+                           id_string, ARRAYLENGTH(id_string));
+            else
+                LoadString(khm_hInstance, IDS_NC_ID_NDEF,
+                           id_string, ARRAYLENGTH(id_string));
+
+            StringCbCat(buf, NC_MAXCB_CREDTEXT - cch * sizeof(wchar_t),
+                        id_string);
+        }
+
+    } else if(d->nc->n_identities > 1) {
+        wchar_t *ids_string;
+        khm_size cb_ids_string;
+
+        wchar_t id_name[KCDB_IDENT_MAXCCH_NAME];
+        wchar_t id_fmt[256];
+        wchar_t id_string[KCDB_IDENT_MAXCCH_NAME + 256];
+
+        wchar_t main_fmt[256];
+        khm_size cbbuf;
+
+        LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_MANY,
+                   main_fmt, (int) ARRAYLENGTH(main_fmt));
+
+        /* we are going to concatenate all the identity names into
+           a comma separated string */
+
+        /* d->nc->n_identities is at least 2 */
+        ids_string = PMALLOC((KCDB_IDENT_MAXCB_NAME + sizeof(id_fmt)) *
+                            (d->nc->n_identities - 1));
+        cb_ids_string =
+            (KCDB_IDENT_MAXCB_NAME + sizeof(id_fmt)) *
+            (d->nc->n_identities - 1);
+
+        assert(ids_string != NULL);
+
+        ids_string[0] = 0;
+
+        {
+            khm_size i;
+            khm_int32 flags;
+
+            for(i=1; i<d->nc->n_identities; i++) {
+                if(i>1) {
+                    StringCbCat(ids_string, cb_ids_string, L",");
+                }
+
+                flags = 0;
+
+                cbbuf = sizeof(id_name);
+                kcdb_identity_get_name(d->nc->identities[i], id_name, &cbbuf);
+                kcdb_identity_get_flags(d->nc->identities[i], &flags);
+                if(flags & KCDB_IDENT_FLAG_INVALID) {
+                    LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_INVALID,
+                               id_fmt, (int) ARRAYLENGTH(id_fmt));
+                } else if(flags & KCDB_IDENT_FLAG_VALID) {
+                    LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_VALID,
+                               id_fmt, (int) ARRAYLENGTH(id_fmt));
+                } else {
+                    LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_UNCHECKED,
+                               id_fmt, (int) ARRAYLENGTH(id_fmt));
+                }
+
+                StringCbPrintf(id_string, sizeof(id_string), id_fmt, id_name);
+                StringCbCat(ids_string, cb_ids_string, id_string);
+            }
+
+            cbbuf = sizeof(id_name);
+            kcdb_identity_get_name(d->nc->identities[0], id_name, &cbbuf);
+            kcdb_identity_get_flags(d->nc->identities[0], &flags);
+            if(flags & KCDB_IDENT_FLAG_INVALID) {
+                LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_INVALID,
+                           id_fmt, (int) ARRAYLENGTH(id_fmt));
+            } else if(flags & KCDB_IDENT_FLAG_VALID) {
+                LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_VALID,
+                           id_fmt, (int) ARRAYLENGTH(id_fmt));
+            } else {
+                LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_UNCHECKED,
+                           id_fmt, (int) ARRAYLENGTH(id_fmt));
+            }
+            StringCbPrintf(id_string, sizeof(id_string), id_fmt, id_name);
+
+            StringCbPrintf(buf, NC_MAXCB_CREDTEXT - cch*sizeof(wchar_t),
+                           main_fmt, id_string, ids_string);
+
+            PFREE(ids_string);
+        }
+    } else {
+        LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_NONE,
+                   buf, (int)(NC_MAXCCH_CREDTEXT - cch));
+    }
+
+    /* now, append the credtext string from each of the cred types */
+    {
+        khm_size i;
+        size_t cb;
+        wchar_t * buf;
+
+        cb = NC_MAXCB_CREDTEXT;
+        buf = ctbuf;
+
+        for(i=0; i<d->nc->n_types; i++) {
+            if(d->nc->types[i]->credtext != NULL) {
+                StringCbCatEx(buf, cb,
+                              d->nc->types[i]->credtext,
+                              &buf, &cb,
+                              0);
+            }
+        }
+    }
+
+    SetDlgItemText(d->dlg_main, IDC_NC_CREDTEXT, ctbuf);
+
+    PFREE(ctbuf);
+
+    /* so depending on whether the primary identity was found to be
+       invalid, we need to disable the Ok button and set the title to
+       reflect this */
+
+    if(d->nc->n_identities > 0) {
+        khm_int32 flags = 0;
+
+        if(KHM_SUCCEEDED(kcdb_identity_get_flags(d->nc->identities[0],
+                                               &flags)) &&
+           (flags & KCDB_IDENT_FLAG_VALID)) {
+            validId = TRUE;
+        }
+    }
+
+    if (d->nc->window_title == NULL) {
+        if(validId) {
+            wchar_t wpostfix[256];
+            wchar_t wtitle[KCDB_IDENT_MAXCCH_NAME + 256];
+            khm_size cbsize;
+
+            cbsize = sizeof(wtitle);
+            kcdb_identity_get_name(d->nc->identities[0], wtitle, &cbsize);
+
+            if (d->nc->subtype == KMSG_CRED_PASSWORD)
+                LoadString(khm_hInstance, IDS_WTPOST_PASSWORD,
+                           wpostfix, (int) ARRAYLENGTH(wpostfix));
+            else
+                LoadString(khm_hInstance, IDS_WTPOST_NEW_CREDS,
+                           wpostfix, (int) ARRAYLENGTH(wpostfix));
+
+            StringCbCat(wtitle, sizeof(wtitle), wpostfix);
+
+            SetWindowText(d->nc->hwnd, wtitle);
+        } else {
+            wchar_t wtitle[256];
+
+            if (d->nc->subtype == KMSG_CRED_PASSWORD)
+                LoadString(khm_hInstance, IDS_WT_PASSWORD,
+                           wtitle, (int) ARRAYLENGTH(wtitle));
+            else
+                LoadString(khm_hInstance, IDS_WT_NEW_CREDS,
+                           wtitle, (int) ARRAYLENGTH(wtitle));
+
+            SetWindowText(d->nc->hwnd, wtitle);
+        }
+    }
+
+    if (!(d->nc->response & KHUI_NC_RESPONSE_PROCESSING)) {
+        if(validId ||
+           d->nc->subtype == KMSG_CRED_PASSWORD) {
+            /* TODO: check if all the required fields have valid values
+               before enabling the Ok button */
+            okEnable = TRUE;
+        }
+
+        hw = GetDlgItem(d->dlg_main, IDOK);
+        EnableWindow(hw, okEnable);
+        hw = GetDlgItem(d->dlg_bb, IDOK);
+        EnableWindow(hw, okEnable);
+    }
+}
+
+static void
+nc_layout_new_cred_window(khui_nc_wnd_data * ncd) {
+    khui_new_creds * c;
+    RECT r_main;
+    RECT r_ncdialog;
+    HDWP hdefer;
+
+    c = ncd->nc;
+
+    r_main.left = 0;
+    r_main.top = 0;
+    r_main.right = NCDLG_WIDTH;
+    r_main.bottom = NCDLG_HEIGHT;
+
+    MapDialogRect(ncd->dlg_main, &r_main);
+
+    hdefer = BeginDeferWindowPos(5);
+
+    if (c->mode == KHUI_NC_MODE_MINI) {
+
+        if (IsWindowVisible(ncd->tab_wnd)) {
+            DeferWindowPos(hdefer,
+                           ncd->tab_wnd, NULL,
+                           0, 0, 0, 0,
+                           SWP_HIDEWINDOW |
+                           SWP_NOMOVE | SWP_NOOWNERZORDER |
+                           SWP_NOSIZE | SWP_NOZORDER);
+        }
+
+        if (IsWindowVisible(ncd->dlg_bb)) {
+            DeferWindowPos(hdefer,
+                           ncd->dlg_bb, NULL,
+                           0, 0, 0, 0,
+                           SWP_HIDEWINDOW |
+                           SWP_NOMOVE | SWP_NOOWNERZORDER |
+                           SWP_NOSIZE | SWP_NOZORDER);
+        }
+
+        DeferWindowPos(hdefer, ncd->dlg_main, NULL,
+                       r_main.left, r_main.top,
+                       r_main.right - r_main.left,
+                       r_main.bottom - r_main.top,
+                       SWP_NOACTIVATE | SWP_NOOWNERZORDER |
+                       SWP_NOZORDER | SWP_SHOWWINDOW);
+
+        /* note that the ncd->r_main.bottom may not be the same as
+           r_main.bottom because ncd->r_main.bottom is set dynamically
+           depending on custom controls. ncd->r_main is valid only
+           once nc_layout_main_panel() is called.*/
+        CopyRect(&ncd->r_required, &ncd->r_main);
+
+    } else {
+        RECT r_tabctrl;
+        RECT r_displayarea;
+        RECT r_bbar;
+        khm_size i;
+
+        /* calculate the size of the tab control so that it fits
+           snugly around the expanded main panel. */
+        CopyRect(&r_tabctrl, &r_main);
+        TabCtrl_AdjustRect(ncd->tab_wnd, TRUE, &r_tabctrl);
+
+        if (r_tabctrl.left < 0 ||
+            r_tabctrl.top < 0) {
+
+            OffsetRect(&r_tabctrl,
+                       (r_tabctrl.left < 0)? -r_tabctrl.left : 0,
+                       (r_tabctrl.top < 0)? -r_tabctrl.top : 0);
+
+        }
+
+#ifdef DEBUG
+        assert(r_tabctrl.left == 0);
+        assert(r_tabctrl.top == 0);
+#endif
+
+        OffsetRect(&r_tabctrl, 0, ncd->r_area.top);
+
+        /* and now calculate the rectangle where the main panel should
+           be inside the tab control. */
+        CopyRect(&r_displayarea, &r_tabctrl);
+        TabCtrl_AdjustRect(ncd->tab_wnd, FALSE, &r_displayarea);
+
+        DeferWindowPos(hdefer,
+                       ncd->tab_wnd, HWND_BOTTOM,
+                       r_tabctrl.left, r_tabctrl.top,
+                       r_tabctrl.right - r_tabctrl.left,
+                       r_tabctrl.bottom - r_tabctrl.top,
+                       SWP_NOACTIVATE | SWP_NOOWNERZORDER |
+                       SWP_SHOWWINDOW);
+
+        /* we have to place the button bar just to the right of the
+           tab panel. */
+        r_bbar.left = 0;
+        r_bbar.top = 0;
+        r_bbar.right = NCDLG_BBAR_WIDTH;
+        r_bbar.bottom = NCDLG_BBAR_HEIGHT;
+
+        MapDialogRect(ncd->dlg_main, &r_bbar);
+
+        OffsetRect(&r_bbar, r_tabctrl.right, 0);
+
+        DeferWindowPos(hdefer,
+                       ncd->dlg_bb, NULL,
+                       r_bbar.left, r_bbar.top,
+                       r_bbar.right - r_bbar.left,
+                       r_bbar.bottom - r_bbar.top,
+                       SWP_NOACTIVATE | SWP_NOOWNERZORDER |
+                       SWP_NOZORDER | SWP_SHOWWINDOW);
+
+        /* move the main panel inside the tab control... */
+        DeferWindowPos(hdefer,
+                       ncd->dlg_main, NULL,
+                       r_displayarea.left, r_displayarea.top,
+                       r_displayarea.right - r_displayarea.left,
+                       r_displayarea.bottom - r_displayarea.top,
+                       SWP_NOACTIVATE | SWP_NOOWNERZORDER |
+                       SWP_NOZORDER |
+                       (ncd->current_panel == 0 ? SWP_SHOWWINDOW : SWP_HIDEWINDOW));
+
+        /* and also move all the credential type panels (if they have
+           been created) inside the tab control too. */
+        khui_cw_lock_nc(c);
+
+        for (i=0; i < c->n_types; i++) {
+            if (c->types[i]->hwnd_panel != NULL) {
+                DeferWindowPos(hdefer,
+                               c->types[i]->hwnd_panel, NULL,
+                               r_displayarea.left, r_displayarea.top,
+                               r_displayarea.right - r_displayarea.left,
+                               r_displayarea.bottom - r_displayarea.top,
+                               SWP_NOACTIVATE | SWP_NOOWNERZORDER |
+                               SWP_NOZORDER |
+                               (ncd->current_panel == c->types[i]->ordinal ?
+                                SWP_SHOWWINDOW : SWP_HIDEWINDOW));
+            }
+        }
+
+        khui_cw_unlock_nc(c);
+
+        /* then update the required size of the new credentials
+           dialog. */
+        ncd->r_required.left = 0;
+        ncd->r_required.top = 0;
+        ncd->r_required.right = r_bbar.right;
+        ncd->r_required.bottom = max(r_tabctrl.bottom, r_bbar.bottom) + ncd->r_area.top;
+    }
+
+    /* commit all the window moves, resizes and hides/shows we did*/
+    EndDeferWindowPos(hdefer);
+
+    /* now we have to see if the client area of the new credentials
+       window is the right size. */
+
+    GetClientRect(c->hwnd, &r_ncdialog);
+
+    if (
+
+        ((r_ncdialog.right - r_ncdialog.left !=
+          ncd->r_required.right - ncd->r_required.left)
+
+         ||
+
+         (r_ncdialog.bottom - r_ncdialog.top !=
+          ncd->r_required.bottom - ncd->r_required.top))
+
+        &&
+
+        /* we don't bother if the new creds window is already in the
+           process of changing the size. */
+        !ncd->size_changing) {
+
+        /* if not, notify the window that the size needs adjusting. */
+        if (IsWindowVisible(c->hwnd))
+            PostMessage(c->hwnd, KHUI_WM_NC_NOTIFY,
+                        MAKEWPARAM(0, WMNC_UPDATE_LAYOUT), 0);
+        else
+            SendMessage(c->hwnd, KHUI_WM_NC_NOTIFY,
+                        MAKEWPARAM(0, WMNC_UPDATE_LAYOUT), 0);
+    }
+}
+
+#define CW_PARAM DWLP_USER
+
+static LRESULT
+nc_handle_wm_create(HWND hwnd,
+                    UINT uMsg,
+                    WPARAM wParam,
+                    LPARAM lParam)
+{
+    LPCREATESTRUCT lpc;
+    khui_new_creds * c;
+    khui_nc_wnd_data * ncd;
+    int x, y;
+    int width, height;
+    RECT r;
+    HFONT hf_main;
+
+    lpc = (LPCREATESTRUCT) lParam;
+
+    ncd = PMALLOC(sizeof(*ncd));
+    ZeroMemory(ncd, sizeof(*ncd));
+
+    c = (khui_new_creds *) lpc->lpCreateParams;
+    ncd->nc = c;
+    c->hwnd = hwnd;
+
+#ifdef DEBUG
+    assert(c->subtype == KMSG_CRED_NEW_CREDS ||
+           c->subtype == KMSG_CRED_PASSWORD);
+#endif
+
+#pragma warning(push)
+#pragma warning(disable: 4244)
+    SetWindowLongPtr(hwnd, CW_PARAM, (LONG_PTR) ncd);
+#pragma warning(pop)
+
+    /* first, create the tab control that will house the main dialog
+       panel as well as the plug-in specific panels */
+    ncd->tab_wnd = CreateWindowEx(0, /* extended style */
+                                  WC_TABCONTROL,
+                                  L"TabControloxxrz", /* window name */
+                                  TCS_HOTTRACK | TCS_RAGGEDRIGHT |
+                                  TCS_SINGLELINE | TCS_TABS |
+                                  WS_CHILD | WS_TABSTOP | WS_CLIPSIBLINGS,
+                                  0, 0, 100, 100, /* x,y,width height.
+                                                     We'll be changing
+                                                     these later
+                                                     anyway. */
+                                  hwnd,
+                                  (HMENU) IDC_NC_TABS,
+                                  NULL,
+                                  0);
+
+#ifdef DEBUG
+    assert(ncd->tab_wnd != NULL);
+#endif
+
+    /* try to create the main dialog panel */
+
+    ncd->dlg_main = CreateDialogParam(khm_hInstance,
+                                      MAKEINTRESOURCE(IDD_NC_NEWCRED),
+                                      hwnd,
+                                      nc_common_dlg_proc,
+                                      (LPARAM) ncd);
+#ifdef DEBUG
+    assert(ncd->dlg_main != NULL);
+#endif
+
+    hf_main = (HFONT) SendMessage(ncd->dlg_main, WM_GETFONT, 0, 0);
+    if (hf_main)
+        SendMessage(ncd->tab_wnd, WM_SETFONT, (WPARAM) hf_main, FALSE);
+
+#if _WIN32_WINNT >= 0x0501
+    EnableThemeDialogTexture(ncd->dlg_main,
+                             ETDT_ENABLETAB);
+#endif
+
+    {
+        RECT r_main;
+        RECT r_area;
+        RECT r_row;
+        HWND hw;
+
+        /* During the operation of the new credentials window, we will
+           need to dynamically change the layout of the controls as a
+           result of custom prompting from credentials providers and
+           identity selectors from identity providers.  In order to
+           guide the dynamic layout, we pick out a few metrics from
+           the dialog template for the main panel. The metrics come
+           from hidden STATIC controls in the dialog template. */
+
+        GetWindowRect(ncd->dlg_main, &r_main);
+
+        /* IDC_NC_TPL_PANEL spans the full extent of the dialog that
+           we can populate with custom controls. */
+        hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_PANEL);
+#ifdef DEBUG
+        assert(hw);
+#endif
+        GetWindowRect(hw, &r_area);
+        OffsetRect(&r_area,-r_main.left, -r_main.top);
+        CopyRect(&ncd->r_area, &r_area);
+
+        /* IDC_NC_TPL_ROW spans the extent of a row of normal sized
+           custom controls.  A row of custom controls typicall consist
+           of a text label and an input control. */
+        hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_ROW);
+#ifdef DEBUG
+        assert(hw);
+#endif
+        GetWindowRect(hw, &r);
+        CopyRect(&r_row, &r);
+        OffsetRect(&r,-r.left, -r.top);
+        CopyRect(&ncd->r_row, &r);
+
+        /* IDC_NC_TPL_LABEL spans the extent that a normal sized
+           label.  The control overlaps IDC_NC_TPL_ROW so we can get
+           coordinates relative to the row extents. */
+        hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_LABEL);
+#ifdef DEBUG
+        assert(hw);
+#endif
+        GetWindowRect(hw, &r);
+        OffsetRect(&r,-r_row.left, -r_row.top);
+        CopyRect(&ncd->r_n_label, &r);
+
+        /* IDC_NC_TPL_INPUT spans the extent of a normal sized input
+           control in a custom control row.  The control overlaps
+           IDC_NC_TPL_ROW so we can get relative coordinates. */
+        hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_INPUT);
+#ifdef DEBUG
+        assert(hw);
+#endif
+        GetWindowRect(hw, &r);
+        OffsetRect(&r, -r_row.left, -r_row.top);
+        CopyRect(&ncd->r_n_input, &r);
+
+        /* IDC_NC_TPL_ROW_LG spans the extent of a row of large sized
+           controls. */
+        hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_ROW_LG);
+#ifdef DEBUG
+        assert(hw);
+#endif
+        GetWindowRect(hw, &r_row);
+
+        /* IDC_NC_TPL_LABEL_LG is a large sized label.  The control
+           overlaps IDC_NC_TPL_ROW_LG. */
+        hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_LABEL_LG);
+#ifdef DEBUG
+        assert(hw);
+#endif
+        GetWindowRect(hw, &r);
+        OffsetRect(&r, -r_row.left, -r_row.top);
+        CopyRect(&ncd->r_e_label, &r);
+
+        /* IDC_NC_TPL_INPUT_LG is a large sized input control.
+           Overlaps IDC_NC_TPL_ROW_LG. */
+        hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_INPUT_LG);
+#ifdef DEBUG
+        assert(hw);
+#endif
+        GetWindowRect(hw, &r);
+        OffsetRect(&r, -r_row.left, -r_row.top);
+        CopyRect(&ncd->r_e_input, &r);
+
+        CopyRect(&ncd->r_credtext, &ncd->r_area);
+        CopyRect(&ncd->r_idspec, &ncd->r_area);
+
+        ncd->r_idspec.bottom = ncd->r_idspec.top;
+
+        /* And finally the credential text window.  The only metric we
+           take from here is the Y coordinate of the bottom of the
+           control since the actual size and position of the
+           credentials window will change depending on the custom
+           controls being displayed. */
+        hw = GetDlgItem(ncd->dlg_main, IDC_NC_CREDTEXT);
+#ifdef DEBUG
+        assert(hw);
+#endif
+        GetWindowRect(hw, &r);
+        OffsetRect(&r, -r_main.left, -r_main.top);
+        ncd->r_credtext.bottom = r.bottom;
+    }
+
+    /* if the mode is 'mini'*/
+    r.left = 0;
+    r.top = 0;
+
+    if(c->mode == KHUI_NC_MODE_MINI) {
+        r.right = NCDLG_WIDTH;
+        r.bottom = NCDLG_HEIGHT;
+    } else {
+        r.right = NCDLG_WIDTH + NCDLG_BBAR_WIDTH;
+        r.bottom = NCDLG_BBAR_HEIGHT;
+    }
+
+    MapDialogRect(ncd->dlg_main, &r);
+
+    /* position the new credentials dialog */
+    width = r.right - r.left;
+    height = r.bottom - r.top;
+
+    /* adjust width and height to accomodate NC area */
+    {
+        RECT wr,cr;
+
+        GetWindowRect(hwnd, &wr);
+        GetClientRect(hwnd, &cr);
+
+        /* the non-client and client areas have already been calculated
+           at this point.  We just use the difference to adjust the width
+           and height */
+        width += (wr.right - wr.left) - (cr.right - cr.left);
+        height += (wr.bottom - wr.top) - (cr.bottom - cr.top);
+    }
+
+    /* if the parent window is visible, we center the new credentials
+       dialog over the parent.  Otherwise, we center it on the primary
+       display. */
+
+    if (IsWindowVisible(lpc->hwndParent)) {
+        GetWindowRect(lpc->hwndParent, &r);
+    } else {
+        if(!SystemParametersInfo(SPI_GETWORKAREA, 0, (PVOID) &r, 0)) {
+            /* failover to the window coordinates */
+            GetWindowRect(lpc->hwndParent, &r);
+        }
+    }
+    x = (r.right + r.left)/2 - width / 2;
+    y = (r.top + r.bottom)/2 - height / 2;
+
+    /* we want to check if the entire rect is visible on the screen.
+       If the main window is visible and in basic mode, we might end
+       up with a rect that is partially outside the screen. */
+    {
+        RECT r;
+
+        SetRect(&r, x, y, x + width, y + height);
+        khm_adjust_window_dimensions_for_display(&r, 0);
+
+        x = r.left;
+        y = r.top;
+        width = r.right - r.left;
+        height = r.bottom - r.top;
+    }
+
+    MoveWindow(hwnd, x, y, width, height, FALSE);
+
+    ncd->dlg_bb = CreateDialogParam(khm_hInstance,
+                                    MAKEINTRESOURCE(IDD_NC_BBAR),
+                                    hwnd,
+                                    nc_common_dlg_proc,
+                                    (LPARAM) ncd);
+
+#ifdef DEBUG
+    assert(ncd->dlg_bb);
+#endif
+
+    /* Call the identity provider callback to set the identity
+       selector controls.  These controls need to be there before we
+       layout the main panel. */
+    c->ident_cb(c, WMNC_IDENT_INIT, NULL, 0, 0, (LPARAM) ncd->dlg_main);
+
+    if (c->mode == KHUI_NC_MODE_EXPANDED) {
+        SendMessage(ncd->dlg_main, KHUI_WM_NC_NOTIFY,
+                    MAKEWPARAM(0, WMNC_DIALOG_EXPAND), 0);
+    } else {
+        /* we don't call nc_layout_main_panel() if the dialog is
+           expanded because posting WMNC_DIALOG_EXPAND to the main
+           panel results in it getting called anyway. */
+        nc_layout_main_panel(ncd);
+    }
+
+    nc_layout_new_cred_window(ncd);
+
+    /* add this to the dialog chain */
+    khm_add_dialog(hwnd);
+
+    return TRUE;
+}
+
+/* add a control row supplied by an identity provider */
+static void
+nc_add_control_row(khui_nc_wnd_data * d,
+                   HWND label,
+                   HWND input,
+                   khui_control_size size)
+{
+    RECT r_row;
+    RECT r_label;
+    RECT r_input;
+    HFONT hf;
+    HDWP hdefer;
+
+    hf = (HFONT) SendMessage(d->dlg_main, WM_GETFONT, 0, 0);
+    SendMessage(label, WM_SETFONT, (WPARAM) hf, FALSE);
+    SendMessage(input, WM_SETFONT, (WPARAM) hf, FALSE);
+
+    CopyRect(&r_row, &d->r_row);
+    OffsetRect(&r_row, d->r_idspec.left, d->r_idspec.bottom);
+
+    if (size == KHUI_CTRLSIZE_SMALL) {
+        CopyRect(&r_label, &d->r_n_label);
+        CopyRect(&r_input, &d->r_n_input);
+        OffsetRect(&r_label, r_row.left, r_row.top);
+        OffsetRect(&r_input, r_row.left, r_row.top);
+    } else if (size == KHUI_CTRLSIZE_HALF) {
+        CopyRect(&r_label, &d->r_e_label);
+        CopyRect(&r_input, &d->r_e_input);
+        OffsetRect(&r_label, r_row.left, r_row.top);
+        OffsetRect(&r_input, r_row.left, r_row.top);
+    } else if (size == KHUI_CTRLSIZE_FULL) {
+        CopyRect(&r_label, &d->r_n_label);
+        r_label.right = d->r_row.right;
+        CopyRect(&r_input, &d->r_n_input);
+        OffsetRect(&r_input, r_row.left, r_row.top);
+        OffsetRect(&r_input, 0, r_input.bottom);
+        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);
+#endif
+        return;
+    }
+
+    hdefer = BeginDeferWindowPos(2);
+
+    if (label)
+        DeferWindowPos(hdefer, label,
+                       ((d->hwnd_last_idspec != NULL)?
+                        d->hwnd_last_idspec:
+                        HWND_TOP),
+                       r_label.left, r_label.top,
+                       r_label.right - r_label.left,
+                       r_label.bottom - r_label.top,
+                       SWP_NOACTIVATE | SWP_NOOWNERZORDER);
+
+    if (input)
+        DeferWindowPos(hdefer, input,
+                       (label ? label : ((d->hwnd_last_idspec != NULL)?
+                                         d->hwnd_last_idspec:
+                                         HWND_TOP)),
+                       r_input.left, r_input.top,
+                       r_input.right - r_input.left,
+                       r_input.bottom - r_input.top,
+                       SWP_NOACTIVATE | SWP_NOOWNERZORDER);
+
+    EndDeferWindowPos(hdefer);
+
+    d->hwnd_last_idspec = (input ? input : label);
+
+    d->r_idspec.bottom = r_row.bottom;
+
+    /* we don't update the layout of the main panel yet, since these
+       control additions happen before the main panel is displayed.  A
+       call to nc_layout_main_panel() will be made before the main
+       panel is shown anyway. */
+
+}
+
+
+static LRESULT
+nc_handle_wm_destroy(HWND hwnd,
+                     UINT uMsg,
+                     WPARAM wParam,
+                     LPARAM lParam)
+{
+    khui_nc_wnd_data * d;
+
+    /* remove self from dialog chain */
+    khm_del_dialog(hwnd);
+
+    d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM);
+    if (d == NULL)
+        return TRUE;
+
+    d->nc->ident_cb(d->nc, WMNC_IDENT_EXIT, NULL, 0, 0, 0);
+
+    if (d->hwnd_notif_label)
+        DestroyWindow(d->hwnd_notif_label);
+    if (d->hwnd_notif_aux)
+        DestroyWindow(d->hwnd_notif_aux);
+
+    if(d->dlg_bb)
+        DestroyWindow(d->dlg_bb);
+    if(d->dlg_main)
+        DestroyWindow(d->dlg_main);
+
+    d->dlg_bb = NULL;
+    d->dlg_main = NULL;
+
+    PFREE(d);
+    SetWindowLongPtr(hwnd, CW_PARAM, 0);
+
+    return TRUE;
+}
+
+static LRESULT
+nc_handle_wm_command(HWND hwnd,
+                     UINT uMsg,
+                     WPARAM wParam,
+                     LPARAM lParam)
+{
+    khui_nc_wnd_data * d;
+
+    d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM);
+    if (d == NULL)
+        return 0;
+
+    switch(HIWORD(wParam)) {
+    case BN_CLICKED:
+        switch(LOWORD(wParam)) {
+
+        case IDOK:
+            d->nc->result = KHUI_NC_RESULT_PROCESS;
+
+            /* fallthrough */
+
+        case IDCANCEL:
+            /* the default value for d->nc->result is set to
+               KHUI_NC_RESULT_CANCEL */
+            d->nc->response = KHUI_NC_RESPONSE_PROCESSING;
+
+            nc_enable_controls(d, FALSE);
+
+            nc_notify_types(d->nc,
+                            KHUI_WM_NC_NOTIFY,
+                            MAKEWPARAM(0,WMNC_DIALOG_PREPROCESS),
+                            (LPARAM) d->nc,
+                            TRUE);
+
+            khui_cw_sync_prompt_values(d->nc);
+
+            khm_cred_dispatch_process_message(d->nc);
+
+            /* we won't know whether to abort or not until we get
+               feedback from the plugins, even if the command was
+               to cancel */
+            {
+                HWND hw;
+
+                hw = GetDlgItem(d->dlg_main, IDOK);
+                EnableWindow(hw, FALSE);
+                hw = GetDlgItem(d->dlg_main, IDCANCEL);
+                EnableWindow(hw, FALSE);
+                hw = GetDlgItem(d->dlg_main, IDC_NC_ADVANCED);
+                EnableWindow(hw, FALSE);
+                hw = GetDlgItem(d->dlg_bb, IDOK);
+                EnableWindow(hw, FALSE);
+                hw = GetDlgItem(d->dlg_bb, IDCANCEL);
+                EnableWindow(hw, FALSE);
+            }
+            return FALSE;
+
+        case IDC_NC_HELP:
+            khm_html_help(hwnd, NULL, HH_HELP_CONTEXT, IDH_ACTION_NEW_ID);
+            return FALSE;
+
+        case IDC_NC_BASIC:
+        case IDC_NC_ADVANCED:
+            /* the Options button in the main window was clicked.  we
+               respond by expanding the dialog. */
+            PostMessage(hwnd, KHUI_WM_NC_NOTIFY,
+                        MAKEWPARAM(0, WMNC_DIALOG_EXPAND), 0);
+            return FALSE;
+
+        case IDC_NC_CREDTEXT: /* credtext link activated */
+            {
+                khui_htwnd_link * l;
+                wchar_t sid[KHUI_MAXCCH_HTLINK_FIELD];
+                wchar_t sparam[KHUI_MAXCCH_HTLINK_FIELD];
+                wchar_t * colon;
+
+                l = (khui_htwnd_link *) lParam;
+
+                /* do we have a valid link? */
+                if(l->id == NULL || l->id_len >= ARRAYLENGTH(sid))
+                    return TRUE; /* nope */
+
+                StringCchCopyN(sid, ARRAYLENGTH(sid), l->id, l->id_len);
+                sid[l->id_len] = L'\0'; /* just make sure */
+
+                if(l->param != NULL &&
+                   l->param_len < ARRAYLENGTH(sparam) &&
+                   l->param_len > 0) {
+
+                    StringCchCopyN(sparam, ARRAYLENGTH(sparam),
+                                   l->param, l->param_len);
+                    sparam[l->param_len] = L'\0';
+
+                } else {
+                    sparam[0] = L'\0';
+                }
+
+                /* If the ID is of the form '<credtype>:<link_tag>'
+                   and <credtype> is a valid name of a credentials
+                   type that is participating in the credentials
+                   acquisition process, then we forward the message to
+                   the panel that is providing the UI for that cred
+                   type.  We also switch to that panel first, unless
+                   the link is of the form '<credtype>:!<link_tag>'. */
+
+                colon = wcschr(sid, L':');
+                if (colon != NULL) {
+                    khm_int32 credtype;
+                    khui_new_creds_by_type * t;
+
+                    *colon = L'\0';
+                    if (KHM_SUCCEEDED(kcdb_credtype_get_id(sid, &credtype)) &&
+                        KHM_SUCCEEDED(khui_cw_find_type(d->nc, credtype, &t))){
+                        *colon = L':';
+
+                        if (t->ordinal != d->current_panel &&
+                            *(colon + 1) != L'!')
+                            PostMessage(hwnd,
+                                        KHUI_WM_NC_NOTIFY,
+                                        MAKEWPARAM(t->ordinal,
+                                                   WMNC_DIALOG_SWITCH_PANEL),
+                                        0);
+
+                        return SendMessage(t->hwnd_panel,
+                                           KHUI_WM_NC_NOTIFY,
+                                           MAKEWPARAM(0, WMNC_CREDTEXT_LINK),
+                                           lParam);
+                    } else {
+                        *colon = L':';
+                    }
+                }
+
+                /* if it was for us, then we need to process the message */
+                if(!_wcsicmp(sid, CTLINKID_SWITCH_PANEL)) {
+                    khm_int32 credtype;
+                    khui_new_creds_by_type * t;
+
+                    if (KHM_SUCCEEDED(kcdb_credtype_get_id(sparam,
+                                                           &credtype)) &&
+                        KHM_SUCCEEDED(khui_cw_find_type(d->nc,
+                                                        credtype, &t))) {
+                        if (t->ordinal != d->current_panel)
+                            PostMessage(hwnd,
+                                        KHUI_WM_NC_NOTIFY,
+                                        MAKEWPARAM(t->ordinal,
+                                                   WMNC_DIALOG_SWITCH_PANEL),
+                                        0);
+                    }
+                } else if (!_wcsicmp(sid, L"NotDef")) {
+                    d->nc->set_default = FALSE;
+                    nc_update_credtext(d);
+                } else if (!_wcsicmp(sid, L"MakeDef")) {
+                    d->nc->set_default = TRUE;
+                    nc_update_credtext(d);
+                }
+            }
+            return FALSE;
+
+#if 0
+        case NC_BN_SET_DEF_ID:
+            {
+                d->nc->set_default =
+                    (IsDlgButtonChecked(d->dlg_main, NC_BN_SET_DEF_ID)
+                     == BST_CHECKED);
+            }
+            return FALSE;
+#endif
+        }
+        break;
+    }
+
+    return TRUE;
+}
+
+static LRESULT nc_handle_wm_moving(HWND hwnd,
+                                   UINT uMsg,
+                                   WPARAM wParam,
+                                   LPARAM lParam)
+{
+    khui_nc_wnd_data * d;
+
+    d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM);
+    if (d == NULL)
+        return FALSE;
+
+    nc_notify_types(d->nc, KHUI_WM_NC_NOTIFY,
+                    MAKEWPARAM(0, WMNC_DIALOG_MOVE), (LPARAM) d->nc, TRUE);
+
+    return FALSE;
+}
+
+static LRESULT nc_handle_wm_nc_notify(HWND hwnd,
+                               UINT uMsg,
+                               WPARAM wParam,
+                               LPARAM lParam)
+{
+    khui_nc_wnd_data * d;
+    int id;
+
+    d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM);
+    if (d == NULL)
+        return FALSE;
+
+    switch(HIWORD(wParam)) {
+
+    case WMNC_DIALOG_SWITCH_PANEL:
+        id = LOWORD(wParam);
+        if(id >= 0 && id <= (int) d->nc->n_types) {
+            /* one of the tab buttons were pressed */
+            if(d->current_panel == id) {
+                return TRUE; /* nothing to do */
+            }
+
+            d->current_panel = id;
+
+            TabCtrl_SetCurSel(d->tab_wnd, id);
+        }
+
+        if(d->nc->mode == KHUI_NC_MODE_EXPANDED) {
+            nc_layout_new_cred_window(d);
+            return TRUE;
+        }
+        /*else*/
+        /* fallthrough */
+
+    case WMNC_DIALOG_EXPAND:
+        /* we are switching from basic to advanced or vice versa */
+
+        if (d->nc->mode == KHUI_NC_MODE_EXPANDED) {
+
+            if (d->current_panel != 0) {
+                d->current_panel = 0;
+                TabCtrl_SetCurSel(d->tab_wnd, 0);
+                nc_layout_new_cred_window(d);
+            }
+
+            d->nc->mode = KHUI_NC_MODE_MINI;
+        } else {
+            d->nc->mode = KHUI_NC_MODE_EXPANDED;
+        }
+
+        /* if we are switching to the advanced mode, we clear any
+           notifications because we now have a credential text area
+           for that. */
+        if (d->nc->mode == KHUI_NC_MODE_EXPANDED)
+            nc_notify_clear(d);
+
+        nc_layout_main_panel(d);
+
+        nc_layout_new_cred_window(d);
+
+        break;
+
+    case WMNC_DIALOG_SETUP:
+
+        if(d->nc->n_types > 0) {
+            khm_size i;
+            for(i=0; i < d->nc->n_types;i++) {
+
+                if (d->nc->types[i]->dlg_proc == NULL) {
+                    d->nc->types[i]->hwnd_panel = NULL;
+                } else {
+                    /* Create the dialog panel */
+                    d->nc->types[i]->hwnd_panel =
+                        CreateDialogParam(d->nc->types[i]->h_module,
+                                          d->nc->types[i]->dlg_template,
+                                          d->nc->hwnd,
+                                          d->nc->types[i]->dlg_proc,
+                                          (LPARAM) d->nc);
+
+#ifdef DEBUG
+                    assert(d->nc->types[i]->hwnd_panel);
+#endif
+#if _WIN32_WINNT >= 0x0501
+                    if (d->nc->types[i]->hwnd_panel) {
+                        EnableThemeDialogTexture(d->nc->types[i]->hwnd_panel,
+                                                 ETDT_ENABLETAB);
+                    }
+#endif
+                }
+            }
+        }
+
+        break;
+
+    case WMNC_DIALOG_ACTIVATE:
+        {
+            wchar_t wname[KCDB_MAXCCH_NAME];
+            TCITEM tabitem;
+            khm_int32 t;
+
+            /* About to activate the window. We should add all the
+               panels to the tab control.  */
+
+#ifdef DEBUG
+            assert(d->tab_wnd != NULL);
+#endif
+
+            ZeroMemory(&tabitem, sizeof(tabitem));
+
+            tabitem.mask = TCIF_PARAM | TCIF_TEXT;
+
+            LoadString(khm_hInstance, IDS_NC_IDENTITY,
+                       wname, ARRAYLENGTH(wname));
+
+            tabitem.pszText = wname;
+            tabitem.lParam = 0; /* ordinal */
+
+            TabCtrl_InsertItem(d->tab_wnd, 0, &tabitem);
+
+            khui_cw_lock_nc(d->nc);
+
+            if(d->nc->n_types > 0) {
+                khm_size i;
+
+                /* We should sort the tabs first.  See
+                   nc_tab_sort_func() for sort criteria. */
+                qsort(d->nc->types,
+                      d->nc->n_types,
+                      sizeof(*(d->nc->types)),
+                      nc_tab_sort_func);
+
+                for(i=0; i < d->nc->n_types;i++) {
+
+                    d->nc->types[i]->ordinal = i + 1;
+
+                    if(d->nc->types[i]->name)
+                        tabitem.pszText = d->nc->types[i]->name;
+                    else {
+                        khm_size cbsize;
+
+                        cbsize = sizeof(wname);
+
+                        if(KHM_FAILED
+                           (kcdb_credtype_describe
+                            (d->nc->types[i]->type,
+                             wname,
+                             &cbsize,
+                             KCDB_TS_SHORT))) {
+
+#ifdef DEBUG
+                            assert(FALSE);
+#endif
+                            wname[0] = L'\0';
+
+                        }
+
+                        tabitem.pszText = wname;
+
+                    }
+
+                    tabitem.lParam = d->nc->types[i]->ordinal;
+
+                    TabCtrl_InsertItem(d->tab_wnd, d->nc->types[i]->ordinal,
+                                       &tabitem);
+                }
+            }
+
+            khui_cw_unlock_nc(d->nc);
+
+            nc_update_credtext(d);
+
+            TabCtrl_SetCurSel(d->tab_wnd, 0); /* the first selected
+                                                 tab is the main
+                                                 panel. */
+
+            /* we don't enable animations until a specific timeout
+               elapses after showing the window.  We don't need to
+               animate any size changes if the user has barely had a
+               chance to notice the original size. This prevents the
+               new cred window from appearing in an animated state. */
+            SetTimer(hwnd, NC_TIMER_ENABLEANIMATE, ENABLEANIMATE_TIMEOUT, NULL);
+
+            ShowWindow(hwnd, SW_SHOWNORMAL);
+
+            /* bring the window to the top, if necessary */
+            if (KHM_SUCCEEDED(khc_read_int32(NULL,
+                                             L"CredWindow\\Windows\\NewCred\\ForceToTop",
+                                             &t)) &&
+
+                t != 0) {
+
+                BOOL sfw = FALSE;
+
+                /* it used to be that the above condition also called
+                   !khm_is_dialog_active() to find out whether there
+                   was a dialog active.  If there was, we wouldn't try
+                   to bring the new cred window to the foreground. But
+                   that was not the behavior we want. */
+
+                /* if the main window is not visible, then the SetWindowPos()
+                   call is sufficient to bring the new creds window to the
+                   top.  However, if the main window is visible but not
+                   active, the main window needs to be activated before a
+                   child window can be activated. */
+
+                SetActiveWindow(hwnd);
+
+                sfw = SetForegroundWindow(hwnd);
+
+                if (!sfw) {
+                    FLASHWINFO fi;
+
+                    ZeroMemory(&fi, sizeof(fi));
+
+                    fi.cbSize = sizeof(fi);
+                    fi.hwnd = hwnd;
+                    fi.dwFlags = FLASHW_ALL;
+                    fi.uCount = 3;
+                    fi.dwTimeout = 0; /* use the default cursor blink rate */
+
+                    FlashWindowEx(&fi);
+
+                    d->flashing_enabled = TRUE;
+                }
+
+            } else {
+                SetFocus(hwnd);
+            }
+
+            if (d->nc->n_identities == 0)
+                break;
+            /* else */
+            /*   fallthrough */
+        }
+
+    case WMNC_IDENTITY_CHANGE:
+        {
+            BOOL okEnable = FALSE;
+
+            nc_notify_types(d->nc, KHUI_WM_NC_NOTIFY,
+                            MAKEWPARAM(0, WMNC_IDENTITY_CHANGE), (LPARAM) d->nc,
+                            TRUE);
+
+            if (d->nc->subtype == KMSG_CRED_NEW_CREDS &&
+                d->nc->n_identities > 0 &&
+                d->nc->identities[0]) {
+                khm_int32 f = 0;
+
+                kcdb_identity_get_flags(d->nc->identities[0], &f);
+
+                if (!(f & KCDB_IDENT_FLAG_DEFAULT)) {
+                    d->nc->set_default = FALSE;
+                }
+            }
+
+            nc_update_credtext(d);
+
+        }
+        break;
+
+    case WMNC_TYPE_STATE:
+        /* fallthrough */
+    case WMNC_UPDATE_CREDTEXT:
+        nc_update_credtext(d);
+        break;
+
+    case WMNC_CLEAR_PROMPTS:
+        {
+            khm_size i;
+
+            khui_cw_lock_nc(d->nc);
+
+            if(d->hwnd_banner != NULL) {
+                DestroyWindow(d->hwnd_banner);
+                d->hwnd_banner = NULL;
+            }
+
+            if(d->hwnd_name != NULL) {
+                DestroyWindow(d->hwnd_name);
+                d->hwnd_name = NULL;
+            }
+
+            for(i=0;i<d->nc->n_prompts;i++) {
+                if(!(d->nc->prompts[i]->flags &
+                     KHUI_NCPROMPT_FLAG_STOCK)) {
+                    if(d->nc->prompts[i]->hwnd_static != NULL)
+                        DestroyWindow(d->nc->prompts[i]->hwnd_static);
+
+                    if(d->nc->prompts[i]->hwnd_edit != NULL)
+                        DestroyWindow(d->nc->prompts[i]->hwnd_edit);
+                }
+
+                d->nc->prompts[i]->hwnd_static = NULL;
+                d->nc->prompts[i]->hwnd_edit = NULL;
+            }
+
+            khui_cw_unlock_nc(d->nc);
+
+            SetRectEmpty(&d->r_custprompt);
+
+            nc_layout_main_panel(d);
+
+            nc_layout_new_cred_window(d);
+        }
+        break;
+
+    case WMNC_SET_PROMPTS:
+        {
+            khm_size i;
+            int  y;
+            HWND hw, hw_prev;
+            HFONT hf, hfold;
+            HDC hdc;
+            BOOL use_large_lables = FALSE;
+
+            /* we assume that WMNC_CLEAR_PROMPTS has already been
+               received */
+
+#ifdef DEBUG
+            assert(IsRectEmpty(&d->r_custprompt));
+#endif
+
+            khui_cw_lock_nc(d->nc);
+
+#if 0
+            /* special case, we have one prompt and it is a password
+               prompt.  very common */
+            if(d->nc->n_prompts == 1 &&
+               d->nc->prompts[0]->type == KHUI_NCPROMPT_TYPE_PASSWORD) {
+
+                hw = GetDlgItem(d->dlg_main, IDC_NC_PASSWORD);
+                EnableWindow(hw, TRUE);
+
+                d->nc->prompts[0]->flags |= KHUI_NCPROMPT_FLAG_STOCK;
+                d->nc->prompts[0]->hwnd_edit = hw;
+                d->nc->prompts[0]->hwnd_static = NULL; /* don't care */
+
+                khui_cw_unlock_nc(d->nc);
+                break;
+            }
+#endif
+            /* for everything else */
+
+            y = d->r_idspec.bottom;
+
+            d->r_custprompt.left = d->r_area.left;
+            d->r_custprompt.right = d->r_area.right;
+            d->r_custprompt.top = y;
+
+            hf = (HFONT) SendMessage(d->dlg_main, WM_GETFONT, 0, 0);
+
+            if (d->nc->pname != NULL) {
+                hw =
+                    CreateWindowEx
+                    (0,
+                     L"STATIC",
+                     d->nc->pname,
+                     SS_SUNKEN | WS_CHILD,
+                     d->r_area.left, y,
+                     d->r_row.right,
+                     d->r_n_label.bottom - d->r_n_label.top,
+                     d->dlg_main,
+                     NULL,
+                     khm_hInstance,
+                     NULL);
+
+#ifdef DEBUG
+                assert(hw);
+#endif
+                d->hwnd_name = hw;
+                SendMessage(hw, WM_SETFONT, (WPARAM)hf, (LPARAM) TRUE);
+                ShowWindow(hw, SW_SHOW);
+
+                y += d->r_n_label.bottom - d->r_n_label.top;
+            }
+
+            if (d->nc->banner != NULL) {
+                hw =
+                    CreateWindowEx
+                    (0,
+                     L"STATIC",
+                     d->nc->banner,
+                     WS_CHILD,
+                     d->r_area.left, y,
+                     d->r_row.right, d->r_row.bottom,
+                     d->dlg_main,
+                     NULL,
+                     khm_hInstance,
+                     NULL);
+#ifdef DEBUG
+                assert(hw);
+#endif
+                d->hwnd_banner = hw;
+                SendMessage(hw, WM_SETFONT, (WPARAM)hf, (LPARAM)TRUE);
+                ShowWindow(hw, SW_SHOW);
+                y += d->r_row.bottom;
+            }
+
+            hw_prev = d->hwnd_last_idspec;
+
+            hdc = GetWindowDC(d->dlg_main);
+            hfold = SelectObject(hdc,hf);
+
+            /* first do a trial run and see if we should use the
+               larger text labels or not.  This is so that all the
+               labels and input controls align properly. */
+            for (i=0; i < d->nc->n_prompts; i++) {
+                if (d->nc->prompts[i]->prompt != NULL) {
+                    SIZE s;
+
+                    GetTextExtentPoint32(hdc,
+                                         d->nc->prompts[i]->prompt,
+                                         (int) wcslen(d->nc->prompts[i]->prompt),
+                                         &s);
+
+                    if(s.cx >= d->r_n_label.right - d->r_n_label.left) {
+                        use_large_lables = TRUE;
+                        break;
+                    }
+                }
+            }
+
+            for(i=0; i<d->nc->n_prompts; i++) {
+                RECT pr, er;
+                SIZE s;
+                int dy;
+
+                if(d->nc->prompts[i]->prompt != NULL) {
+                    GetTextExtentPoint32(hdc,
+                                         d->nc->prompts[i]->prompt,
+                                         (int) wcslen(d->nc->prompts[i]->prompt),
+                                         &s);
+                    if(s.cx < d->r_n_label.right - d->r_n_label.left &&
+                       !use_large_lables) {
+                        CopyRect(&pr, &d->r_n_label);
+                        CopyRect(&er, &d->r_n_input);
+                        dy = d->r_row.bottom;
+                    } else if(s.cx <
+                              d->r_e_label.right - d->r_e_label.left) {
+                        CopyRect(&pr, &d->r_e_label);
+                        CopyRect(&er, &d->r_e_input);
+                        dy = d->r_row.bottom;
+                    } else {
+                        /* oops. the prompt doesn't fit in our
+                           controls.  we need to use up two lines */
+                        pr.left = 0;
+                        pr.right = d->r_row.right;
+                        pr.top = 0;
+                        pr.bottom = d->r_n_label.bottom -
+                            d->r_n_label.top;
+                        CopyRect(&er, &d->r_n_input);
+                        OffsetRect(&er, 0, pr.bottom);
+                        dy = er.bottom + (d->r_row.bottom -
+                                          d->r_n_input.bottom);
+                    }
+                } else {
+                    SetRectEmpty(&pr);
+                    CopyRect(&er, &d->r_n_input);
+                    dy = d->r_row.bottom;
+                }
+
+                if(IsRectEmpty(&pr)) {
+                    d->nc->prompts[i]->hwnd_static = NULL;
+                } else {
+                    OffsetRect(&pr, d->r_area.left, y);
+
+                    hw = CreateWindowEx
+                        (0,
+                         L"STATIC",
+                         d->nc->prompts[i]->prompt,
+                         WS_CHILD,
+                         pr.left, pr.top,
+                         pr.right - pr.left, pr.bottom - pr.top,
+                         d->dlg_main,
+                         NULL,
+                         khm_hInstance,
+                         NULL);
+#ifdef DEBUG
+                    assert(hw);
+#endif
+
+                    SendMessage(hw, WM_SETFONT,
+                                (WPARAM) hf, (LPARAM) TRUE);
+
+                    SetWindowPos(hw, hw_prev,
+                                 0, 0, 0, 0,
+                                 SWP_NOACTIVATE | SWP_NOMOVE |
+                                 SWP_NOOWNERZORDER | SWP_NOSIZE |
+                                 SWP_SHOWWINDOW);
+
+                    d->nc->prompts[i]->hwnd_static = hw;
+                    hw_prev = hw;
+                }
+
+                OffsetRect(&er, d->r_area.left, y);
+
+                hw = CreateWindowEx
+                    (0,
+                     L"EDIT",
+                     (d->nc->prompts[i]->def ?
+                      d->nc->prompts[i]->def : L""),
+                     WS_CHILD | WS_TABSTOP |
+                     WS_BORDER | ES_AUTOHSCROLL |
+                     ((d->nc->prompts[i]->flags &
+                       KHUI_NCPROMPT_FLAG_HIDDEN)? ES_PASSWORD:0),
+                     er.left, er.top,
+                     er.right - er.left, er.bottom - er.top,
+                     d->dlg_main,
+                     NULL,
+                     khm_hInstance,
+                     NULL);
+
+#ifdef DEBUG
+                assert(hw);
+#endif
+
+                SendMessage(hw, WM_SETFONT,
+                            (WPARAM) hf, (LPARAM) TRUE);
+
+                SetWindowPos(hw, hw_prev,
+                             0, 0, 0, 0,
+                             SWP_NOACTIVATE | SWP_NOMOVE |
+                             SWP_NOOWNERZORDER | SWP_NOSIZE |
+                             SWP_SHOWWINDOW);
+
+                SendMessage(hw, EM_SETLIMITTEXT,
+                            KHUI_MAXCCH_PROMPT_VALUE -1,
+                            0);
+
+                d->nc->prompts[i]->hwnd_edit = hw;
+
+                hw_prev = hw;
+
+                y += dy;
+            }
+
+            if (d->nc->n_prompts > 0 &&
+                d->nc->prompts[0]->hwnd_edit) {
+
+                PostMessage(d->dlg_main, WM_NEXTDLGCTL,
+                            (WPARAM) d->nc->prompts[0]->hwnd_edit,
+                            MAKELPARAM(TRUE, 0));
+
+            }
+
+            SelectObject(hdc, hfold);
+            ReleaseDC(d->dlg_main, hdc);
+
+            khui_cw_unlock_nc(d->nc);
+
+            d->r_custprompt.bottom = y;
+
+            if (d->r_custprompt.bottom == d->r_custprompt.top)
+                SetRectEmpty(&d->r_custprompt);
+
+            nc_layout_main_panel(d);
+
+            nc_layout_new_cred_window(d);
+        }
+        break;
+
+    case WMNC_DIALOG_PROCESS_COMPLETE:
+        {
+            khui_new_creds * nc;
+
+            nc = d->nc;
+
+            nc->response &= ~KHUI_NC_RESPONSE_PROCESSING;
+
+            if(nc->response & KHUI_NC_RESPONSE_NOEXIT) {
+                HWND hw;
+
+                nc_enable_controls(d, TRUE);
+
+                /* reset state */
+                nc->result = KHUI_NC_RESULT_CANCEL;
+
+                hw = GetDlgItem(d->dlg_main, IDOK);
+                EnableWindow(hw, TRUE);
+                hw = GetDlgItem(d->dlg_main, IDCANCEL);
+                EnableWindow(hw, TRUE);
+                hw = GetDlgItem(d->dlg_main, IDC_NC_ADVANCED);
+                EnableWindow(hw, TRUE);
+                hw = GetDlgItem(d->dlg_bb, IDOK);
+                EnableWindow(hw, TRUE);
+                hw = GetDlgItem(d->dlg_bb, IDCANCEL);
+                EnableWindow(hw, TRUE);
+
+                nc_clear_password_fields(d);
+
+                return TRUE;
+            }
+
+            DestroyWindow(hwnd);
+
+            kmq_post_message(KMSG_CRED, KMSG_CRED_END, 0, (void *) nc);
+        }
+        break;
+
+        /* MUST be called with SendMessage */
+    case WMNC_ADD_CONTROL_ROW:
+        {
+            khui_control_row * row;
+
+            row = (khui_control_row *) lParam;
+
+#ifdef DEBUG
+            assert(row->label);
+            assert(row->input);
+#endif
+
+            nc_add_control_row(d, row->label, row->input, row->size);
+        }
+        break;
+
+    case WMNC_UPDATE_LAYOUT:
+        {
+
+            RECT r_client;
+            khm_int32 animate;
+            khm_int32 steps;
+            khm_int32 timeout;
+
+            /* We are already adjusting the size of the window.  The
+               next time the timer fires, it will notice if the target
+               size has changed. */
+            if (d->size_changing)
+                return TRUE;
+
+            GetClientRect(hwnd, &r_client);
+
+            if ((r_client.right - r_client.left ==
+                 d->r_required.right - d->r_required.left) &&
+                (r_client.bottom - r_client.top ==
+                 d->r_required.bottom - d->r_required.top)) {
+
+                /* the window is already at the right size */
+                return TRUE;
+
+            }
+
+            if (!IsWindowVisible(hwnd)) {
+                /* The window is not visible yet.  There's no need to
+                   animate anything. */
+
+                animate = FALSE;
+
+            } else if (KHM_FAILED(khc_read_int32(NULL,
+                                                 L"CredWindow\\Windows\\NewCred\\AnimateSizeChanges",
+                                                 &animate))) {
+#ifdef DEBUG
+                assert(FALSE);
+#endif
+                animate = TRUE;
+            }
+
+            /* if we aren't animating the window resize, then we just
+               do it in one call. */
+            if (!animate || !d->animation_enabled) {
+                RECT r_window;
+
+                CopyRect(&r_window, &d->r_required);
+                AdjustWindowRectEx(&r_window, NC_WINDOW_STYLES, FALSE,
+                                   NC_WINDOW_EX_STYLES);
+
+                SetWindowPos(hwnd, NULL, 0, 0,
+                             r_window.right - r_window.left,
+                             r_window.bottom - r_window.top,
+                             SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER |
+                             SWP_NOZORDER);
+
+                return TRUE;
+            }
+
+            if (KHM_FAILED(khc_read_int32(NULL,
+                                          L"CredWindow\\Windows\\NewCred\\AnimationSteps",
+                                          &steps))) {
+#ifdef DEBUG
+                assert(FALSE);
+#endif
+                steps = NC_SZ_STEPS_DEF;
+            } else {
+
+                if (steps < NC_SZ_STEPS_MIN)
+                    steps = NC_SZ_STEPS_MIN;
+                else if (steps > NC_SZ_STEPS_MAX)
+                    steps = NC_SZ_STEPS_MAX;
+
+            }
+
+            if (KHM_FAILED(khc_read_int32(NULL,
+                                          L"CredWindow\\Windows\\NewCred\\AnimationStepTimeout",
+                                          &timeout))) {
+#ifdef DEBUG
+                assert(FALSE);
+#endif
+                timeout = NC_SZ_TIMEOUT_DEF;
+            } else {
+
+                if (timeout < NC_SZ_TIMEOUT_MIN)
+                    timeout = NC_SZ_TIMEOUT_MIN;
+                else if (timeout > NC_SZ_TIMEOUT_MAX)
+                    timeout = NC_SZ_TIMEOUT_MAX;
+
+            }
+
+            CopyRect(&d->sz_ch_source, &r_client);
+            OffsetRect(&d->sz_ch_source, -d->sz_ch_source.left, -d->sz_ch_source.top);
+            CopyRect(&d->sz_ch_target, &d->r_required);
+            OffsetRect(&d->sz_ch_target, -d->sz_ch_target.left, -d->sz_ch_target.top);
+            d->sz_ch_increment = 0;
+            d->sz_ch_max = steps;
+            d->sz_ch_timeout = timeout;
+            d->size_changing = TRUE;
+
+            SetTimer(hwnd, NC_TIMER_SIZER, timeout, NULL);
+        }
+        break;
+    } /* switch(HIWORD(wParam)) */
+
+    return TRUE;
+}
+
+static LRESULT nc_handle_wm_timer(HWND hwnd,
+                                  UINT uMsg,
+                                  WPARAM wParam,
+                                  LPARAM lParam) {
+    khui_nc_wnd_data * d;
+
+    d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM);
+    if (d == NULL)
+        return FALSE;
+
+    if (wParam == NC_TIMER_SIZER) {
+
+        RECT r_now;
+
+        /* are we done with this sizing operation? */
+        if (!d->size_changing ||
+            d->sz_ch_increment >= d->sz_ch_max) {
+
+            d->size_changing = FALSE;
+            KillTimer(hwnd, NC_TIMER_SIZER);
+            return 0;
+        }
+
+        /* have the requirements changed while we were processing the
+           sizing operation? */
+        if ((d->r_required.right - d->r_required.left !=
+             d->sz_ch_target.right)
+
+            ||
+
+            (d->r_required.bottom - d->r_required.top !=
+             d->sz_ch_target.bottom)) {
+
+            /* the target size has changed.  we need to restart the
+               sizing operation. */
+
+            RECT r_client;
+
+            GetClientRect(hwnd, &r_client);
+
+            CopyRect(&d->sz_ch_source, &r_client);
+            OffsetRect(&d->sz_ch_source, -d->sz_ch_source.left, -d->sz_ch_source.top);
+            CopyRect(&d->sz_ch_target, &d->r_required);
+            OffsetRect(&d->sz_ch_target, -d->sz_ch_target.left, -d->sz_ch_target.top);
+            d->sz_ch_increment = 0;
+
+            /* leave the other fields alone */
+
+#ifdef DEBUG
+            assert(d->sz_ch_max >= NC_SZ_STEPS_MIN);
+            assert(d->sz_ch_max <= NC_SZ_STEPS_MAX);
+            assert(d->sz_ch_timeout >= NC_SZ_TIMEOUT_MIN);
+            assert(d->sz_ch_timeout <= NC_SZ_TIMEOUT_MAX);
+            assert(d->size_changing);
+#endif
+        }
+
+        /* we are going to do the next increment */
+        d->sz_ch_increment ++;
+
+        /* now, figure out the size of the client area for this
+           step */
+
+        r_now.left = 0;
+        r_now.top = 0;
+
+#define PROPORTION(v1, v2, i, s) (((v1) * ((s) - (i)) + (v2) * (i)) / (s))
+
+        r_now.right = PROPORTION(d->sz_ch_source.right, d->sz_ch_target.right,
+                                 d->sz_ch_increment, d->sz_ch_max);
+
+        r_now.bottom = PROPORTION(d->sz_ch_source.bottom, d->sz_ch_target.bottom,
+                                  d->sz_ch_increment, d->sz_ch_max);
+
+#undef  PROPORTION
+
+#ifdef DEBUG
+        {
+            long dx = ((r_now.right - r_now.left) - d->sz_ch_target.right) *
+                (d->sz_ch_source.right - d->sz_ch_target.right);
+
+            long dy = ((r_now.bottom - r_now.top) - d->sz_ch_target.bottom) *
+                (d->sz_ch_source.bottom - d->sz_ch_target.bottom);
+
+            if (dx < 0 || dy < 0) {
+                KillTimer(hwnd, NC_TIMER_SIZER);
+                assert(dx >= 0);
+                assert(dy >= 0);
+                SetTimer(hwnd, NC_TIMER_SIZER, d->sz_ch_timeout, NULL);
+            }
+        }
+#endif
+
+        AdjustWindowRectEx(&r_now, NC_WINDOW_STYLES, FALSE,
+                           NC_WINDOW_EX_STYLES);
+
+        {
+            RECT r;
+
+            GetWindowRect(hwnd, &r);
+            OffsetRect(&r_now, r.left - r_now.left, r.top - r_now.top);
+        }
+
+        khm_adjust_window_dimensions_for_display(&r_now, 0);
+
+        SetWindowPos(hwnd, NULL,
+                     r_now.left, r_now.top,
+                     r_now.right - r_now.left,
+                     r_now.bottom - r_now.top,
+                     SWP_NOACTIVATE | SWP_NOOWNERZORDER |
+                     SWP_NOZORDER);
+
+        /* and now we wait for the next timer message */
+
+        return 0;
+    } else if (wParam == NC_TIMER_ENABLEANIMATE) {
+
+        d->animation_enabled = TRUE;
+        KillTimer(hwnd, NC_TIMER_ENABLEANIMATE);
+    }
+
+    return 0;
+}
+
+static LRESULT nc_handle_wm_notify(HWND hwnd,
+                                   UINT uMsg,
+                                   WPARAM wParam,
+                                   LPARAM lParam) {
+
+    LPNMHDR nmhdr;
+    khui_nc_wnd_data * d;
+
+    d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM);
+    if (d == NULL)
+        return FALSE;
+
+    nmhdr = (LPNMHDR) lParam;
+
+    if (nmhdr->code == TCN_SELCHANGE) {
+        /* the current tab has changed. */
+        int idx;
+        TCITEM tcitem;
+
+        idx = TabCtrl_GetCurSel(d->tab_wnd);
+        ZeroMemory(&tcitem, sizeof(tcitem));
+
+        tcitem.mask = TCIF_PARAM;
+        TabCtrl_GetItem(d->tab_wnd, idx, &tcitem);
+
+        d->current_panel = (int) tcitem.lParam;
+
+        nc_layout_new_cred_window(d);
+
+        return TRUE;
+    }
+
+    return FALSE;
+}
+
+static LRESULT nc_handle_wm_help(HWND hwnd,
+                                 UINT uMsg,
+                                 WPARAM wParam,
+                                 LPARAM lParam) {
+    static DWORD ctxids[] = {
+        NC_TS_CTRL_ID_MIN, IDH_NC_TABMAIN,
+        NC_TS_CTRL_ID_MIN + 1, IDH_NC_TABBUTTON,
+        NC_TS_CTRL_ID_MIN + 2, IDH_NC_TABBUTTON,
+        NC_TS_CTRL_ID_MIN + 3, IDH_NC_TABBUTTON,
+        NC_TS_CTRL_ID_MIN + 4, IDH_NC_TABBUTTON,
+        NC_TS_CTRL_ID_MIN + 5, IDH_NC_TABBUTTON,
+        NC_TS_CTRL_ID_MIN + 6, IDH_NC_TABBUTTON,
+        NC_TS_CTRL_ID_MIN + 7, IDH_NC_TABBUTTON,
+        IDOK, IDH_NC_OK,
+        IDCANCEL, IDH_NC_CANCEL,
+        IDC_NC_HELP, IDH_NC_HELP,
+        IDC_NC_ADVANCED, IDH_NC_ADVANCED,
+        IDC_NC_CREDTEXT, IDH_NC_CREDWND,
+        0
+    };
+
+    HELPINFO * hlp;
+    HWND hw = NULL;
+    HWND hw_ctrl;
+    khui_nc_wnd_data * d;
+
+    d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM);
+    if (d == NULL)
+        return FALSE;
+
+    hlp = (HELPINFO *) lParam;
+
+    if (d->nc->subtype != KMSG_CRED_NEW_CREDS &&
+        d->nc->subtype != KMSG_CRED_PASSWORD)
+        return TRUE;
+
+    if (hlp->iContextType != HELPINFO_WINDOW)
+        return TRUE;
+
+    if (hlp->hItemHandle != NULL &&
+        hlp->hItemHandle != hwnd) {
+        DWORD id;
+        int i;
+
+        hw_ctrl =hlp->hItemHandle;
+
+        id = GetWindowLong(hw_ctrl, GWL_ID);
+        for (i=0; ctxids[i] != 0; i += 2)
+            if (ctxids[i] == id)
+                break;
+
+        if (ctxids[i] != 0)
+            hw = khm_html_help(hw_ctrl,
+                               ((d->nc->subtype == KMSG_CRED_NEW_CREDS)?
+                                L"::popups_newcreds.txt":
+                                L"::popups_password.txt"),
+                               HH_TP_HELP_WM_HELP,
+                               (DWORD_PTR) ctxids);
+    }
+
+    if (hw == NULL) {
+        khm_html_help(hwnd, NULL, HH_HELP_CONTEXT,
+                      ((d->nc->subtype == KMSG_CRED_NEW_CREDS)?
+                       IDH_ACTION_NEW_ID: IDH_ACTION_PASSWD_ID));
+    }
+
+    return TRUE;
+}
+
+static LRESULT nc_handle_wm_activate(HWND hwnd,
+                                     UINT uMsg,
+                                     WPARAM wParam,
+                                     LPARAM lParam) {
+    if (uMsg == WM_MOUSEACTIVATE ||
+        wParam == WA_ACTIVE || wParam == WA_CLICKACTIVE) {
+
+        FLASHWINFO fi;
+        khui_nc_wnd_data * d;
+        DWORD_PTR ex_style;
+
+        d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM);
+
+        if (d && d->flashing_enabled) {
+            ZeroMemory(&fi, sizeof(fi));
+
+            fi.cbSize = sizeof(fi);
+            fi.hwnd = hwnd;
+            fi.dwFlags = FLASHW_STOP;
+
+            FlashWindowEx(&fi);
+
+            d->flashing_enabled = FALSE;
+        }
+
+        ex_style = GetWindowLongPtr(hwnd, GWL_EXSTYLE);
+
+        if (ex_style & WS_EX_TOPMOST) {
+            SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0,
+                         SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
+        }
+    }
+
+    return (uMsg == WM_MOUSEACTIVATE)? MA_ACTIVATE : 0;
+}
+
+static LRESULT CALLBACK nc_window_proc(HWND hwnd,
+                                       UINT uMsg,
+                                       WPARAM wParam,
+                                       LPARAM lParam)
+{
+    switch(uMsg) {
+    case WM_MOUSEACTIVATE:
+    case WM_ACTIVATE:
+        return nc_handle_wm_activate(hwnd, uMsg, wParam, lParam);
+
+    case WM_CREATE:
+        return nc_handle_wm_create(hwnd, uMsg, wParam, lParam);
+
+    case WM_DESTROY:
+        return nc_handle_wm_destroy(hwnd, uMsg, wParam, lParam);
+
+    case WM_COMMAND:
+        return nc_handle_wm_command(hwnd, uMsg, wParam, lParam);
+
+    case WM_NOTIFY:
+        return nc_handle_wm_notify(hwnd, uMsg, wParam, lParam);
+
+    case WM_MOVE:
+    case WM_MOVING:
+        return nc_handle_wm_moving(hwnd, uMsg, wParam, lParam);
+
+    case WM_TIMER:
+        return nc_handle_wm_timer(hwnd, uMsg, wParam, lParam);
+
+    case WM_HELP:
+        return nc_handle_wm_help(hwnd, uMsg, wParam, lParam);
+
+    case KHUI_WM_NC_NOTIFY:
+        return nc_handle_wm_nc_notify(hwnd, uMsg, wParam, lParam);
+    }
+
+    /* Note that this is technically a dialog box */
+    return DefDlgProc(hwnd, uMsg, wParam, lParam);
+}
+
+void khm_register_newcredwnd_class(void)
+{
+    WNDCLASSEX wcx;
+
+    wcx.cbSize = sizeof(wcx);
+    wcx.style = CS_DBLCLKS | CS_OWNDC;
+    wcx.lpfnWndProc = nc_window_proc;
+    wcx.cbClsExtra = 0;
+    wcx.cbWndExtra = DLGWINDOWEXTRA + sizeof(LONG_PTR);
+    wcx.hInstance = khm_hInstance;
+    wcx.hIcon = LoadIcon(khm_hInstance, MAKEINTRESOURCE(IDI_MAIN_APP));
+    wcx.hCursor = LoadCursor((HINSTANCE) NULL, IDC_ARROW);
+    wcx.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1);
+    wcx.lpszMenuName = NULL;
+    wcx.lpszClassName = KHUI_NEWCREDWND_CLASS;
+    wcx.hIconSm = NULL;
+
+    khui_newcredwnd_cls = RegisterClassEx(&wcx);
+}
+
+void khm_unregister_newcredwnd_class(void)
+{
+    UnregisterClass(MAKEINTATOM(khui_newcredwnd_cls), khm_hInstance);
+}
+
+HWND khm_create_newcredwnd(HWND parent, khui_new_creds * c)
+{
+    wchar_t wtitle[256];
+    HWND hwnd;
+    khm_int32 force_topmost = 0;
+
+    if (c->window_title == NULL) {
+        if (c->subtype == KMSG_CRED_PASSWORD)
+            LoadString(khm_hInstance,
+                       IDS_WT_PASSWORD,
+                       wtitle,
+                       ARRAYLENGTH(wtitle));
+        else
+            LoadString(khm_hInstance,
+                       IDS_WT_NEW_CREDS,
+                       wtitle,
+                       ARRAYLENGTH(wtitle));
+    }
+
+    khc_read_int32(NULL, L"CredWindow\\Windows\\NewCred\\ForceToTop", &force_topmost);
+
+    hwnd = CreateWindowEx(NC_WINDOW_EX_STYLES | (force_topmost ? WS_EX_TOPMOST : 0),
+                          MAKEINTATOM(khui_newcredwnd_cls),
+                          ((c->window_title)?c->window_title: wtitle),
+                          NC_WINDOW_STYLES,
+                          0,0,400,400,    /* bogus values.  the window
+                                             is going to resize and
+                                             reposition itself
+                                             anyway */
+                          parent,
+                          NULL,
+                          khm_hInstance,
+                          (LPVOID) c);
+
+#ifdef DEBUG
+    assert(hwnd != NULL);
+#endif
+
+    /* note that the window is not visible yet.  That's because, at
+       this point we don't know what the panels are */
+
+    return hwnd;
+}
+
+void khm_prep_newcredwnd(HWND hwnd)
+{
+    SendMessage(hwnd, KHUI_WM_NC_NOTIFY,
+                MAKEWPARAM(0, WMNC_DIALOG_SETUP), 0);
+}
+
+void khm_show_newcredwnd(HWND hwnd)
+{
+    /* add all the panels in and prep UI */
+    PostMessage(hwnd, KHUI_WM_NC_NOTIFY,
+                MAKEWPARAM(0, WMNC_DIALOG_ACTIVATE), 0);
+}