From: Tom Yu Date: Thu, 12 Apr 2007 21:30:33 +0000 (+0000) Subject: pull up r19440 from trunk X-Git-Tag: krb5-1.6.1-beta1~3 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=4f91d87cb04653f3a33398a60f20d7e81d974791;p=krb5.git pull up r19440 from trunk r19440@cathode-dark-space: jaltman | 2007-04-12 17:19:33 -0400 ticket: new subject: NIM - Fix taskbar button visibility on Vista component: windows tags: pullup Although the Platform SDK docs suggest using ITaskbarList to add/remove a taskbar button on the fly, it doesn't work on Vista. Instead we will just set the window style to use WS_EX_APPWINDOW and be done with it. No change in the NIM version number. ticket: 5526 version_fixed: 1.6.1 git-svn-id: svn://anonsvn.mit.edu/krb5/branches/krb5-1-6@19441 dc483132-0cff-0310-8789-dd5450dbe970 --- diff --git a/src/windows/identity/ui/mainwnd.c b/src/windows/identity/ui/mainwnd.c index 159255f1c..d177b114c 100644 --- a/src/windows/identity/ui/mainwnd.c +++ b/src/windows/identity/ui/mainwnd.c @@ -1,1364 +1,1358 @@ -/* - * 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 -#include -#include - -ATOM khm_main_window_class; -ATOM khm_null_window_class; -HWND khm_hwnd_null; -HWND khm_hwnd_main; -HWND khm_hwnd_rebar; -HWND khm_hwnd_main_cred; - -int khm_main_wnd_mode = KHM_MAIN_WND_NORMAL; - -#define MW_RESIZE_TIMER 1 -#define MW_RESIZE_TIMEOUT 2000 -#define MW_REFRESH_TIMER 2 -#define MW_REFRESH_TIMEOUT 600 - -void -khm_set_dialog_result(HWND hwnd, LRESULT lr) { -#pragma warning(push) -#pragma warning(disable: 4244) - SetWindowLongPtr(hwnd, DWLP_MSGRESULT, lr); -#pragma warning(pop) -} - -static void -mw_restart_refresh_timer(HWND hwnd) { - khm_handle csp_cw; - khm_int32 timeout; - - KillTimer(hwnd, MW_REFRESH_TIMER); - if (KHM_SUCCEEDED(khc_open_space(NULL, - L"CredWindow", - KHM_PERM_READ, - &csp_cw))) { - if (KHM_FAILED(khc_read_int32(csp_cw, - L"RefreshTimeout", - &timeout))) - timeout = MW_REFRESH_TIMEOUT; - khc_close_space(csp_cw); - } else { - timeout = MW_REFRESH_TIMEOUT; - } - - timeout *= 1000; /* convert to milliseconds */ - - SetTimer(hwnd, MW_REFRESH_TIMER, timeout, NULL); -} - -khm_int32 KHMAPI -mw_select_cred(khm_handle cred, void * rock) { - if (cred) - kcdb_cred_set_flags(cred, - KCDB_CRED_FLAG_SELECTED, - KCDB_CRED_FLAG_SELECTED); - - return KHM_ERROR_SUCCESS; -} - -/* perform shutdown operations */ -static void -khm_pre_shutdown(void) { - khm_handle csp_cw = NULL; - khm_handle credset = NULL; - khm_int32 t; - khm_size s; - - khm_taskbar_remove_window(khm_hwnd_main); - - /* Check if we should destroy all credentials on exit... */ - - if (KHM_FAILED(khc_open_space(NULL, L"CredWindow", 0, &csp_cw))) - return; - - if (KHM_FAILED(khc_read_int32(csp_cw, L"DestroyCredsOnExit", &t)) || - !t) - goto _cleanup; - - if (KHM_FAILED(kcdb_credset_create(&credset))) - goto _cleanup; - - if (KHM_FAILED(kcdb_credset_extract(credset, NULL, NULL, - KCDB_TYPE_INVALID))) - goto _cleanup; - - if (KHM_FAILED(kcdb_credset_get_size(credset, &s)) || - s == 0) - goto _cleanup; - - kcdb_credset_apply(credset, mw_select_cred, NULL); - - khui_context_set(KHUI_SCOPE_GROUP, - NULL, - KCDB_CREDTYPE_INVALID, - NULL, - NULL, - 0, - credset); - - khm_cred_destroy_creds(TRUE, TRUE); - - _cleanup: - - if (credset) - kcdb_credset_delete(credset); - - if (csp_cw) - khc_close_space(csp_cw); -} - -void -khm_process_query_app_ver(khm_query_app_version * papp_ver) { - - if (!papp_ver || papp_ver->magic != KHM_QUERY_APP_VER_MAGIC) - return; - - papp_ver->ver_remote = app_version; - - /* the remote instance has requested swapping in. we check the - version numbers and if the remote instance is newer than us, - then we exit and let the remote instance take over. */ - if (papp_ver->request_swap) { - khm_version ver_caller = papp_ver->ver_caller; - - if (ver_caller.major > app_version.major || - - (ver_caller.major == app_version.major && - ver_caller.minor > app_version.minor) || - - (ver_caller.major == app_version.major && - ver_caller.minor == app_version.minor && - ver_caller.aux > app_version.aux) || - - (ver_caller.major == app_version.major && - ver_caller.minor == app_version.minor && - ver_caller.aux == app_version.aux && - ver_caller.patch > app_version.patch)) { - - papp_ver->request_swap = TRUE; - - if (khm_hwnd_main) - DestroyWindow(khm_hwnd_main); - - } else { - - papp_ver->request_swap = FALSE; - - } - } - - papp_ver->code = KHM_ERROR_SUCCESS; -} - -static void -khm_ui_cb(LPARAM lParam) { - khui_ui_callback_data * pcbdata; - - pcbdata = (khui_ui_callback_data *) lParam; - - if (pcbdata == NULL || pcbdata->magic != KHUI_UICBDATA_MAGIC) { -#ifdef DEBUG - assert(FALSE); -#endif - return; - } - -#ifdef DEBUG - assert(pcbdata->cb); -#endif - - /* make the call */ - if (!IsBadCodePtr(pcbdata->cb)) - pcbdata->rv = (*pcbdata->cb)(khm_hwnd_main, pcbdata->rock); - else { -#ifdef DEBUG - assert(FALSE); -#endif - pcbdata->rv = KHM_ERROR_INVALID_PARAM; - } -} - -LRESULT CALLBACK -khm_main_wnd_proc(HWND hwnd, - UINT uMsg, - WPARAM wParam, - LPARAM lParam) -{ - LPNMHDR lpnm; - - switch(uMsg) { - case WM_CREATE: - khm_create_main_window_controls(hwnd); - kmq_subscribe_hwnd(KMSG_CRED, hwnd); - kmq_subscribe_hwnd(KMSG_ACT, hwnd); - kmq_subscribe_hwnd(KMSG_KMM, hwnd); - mw_restart_refresh_timer(hwnd); - - /* if the plug-ins finished loading before the window was - created, we would have missed the KMSG_KMM_I_DONE message. - So we check if the module load is complete and if so, fire - off KMSG_ACT_BEGIN_CMDLINE. */ - if (!kmm_load_pending()) - kmq_post_message(KMSG_ACT, KMSG_ACT_BEGIN_CMDLINE, 0, 0); - break; - - case WM_DESTROY: - khm_pre_shutdown(); - kmq_unsubscribe_hwnd(KMSG_ACT, hwnd); - kmq_unsubscribe_hwnd(KMSG_CRED, hwnd); - kmq_unsubscribe_hwnd(KMSG_KMM, hwnd); - HtmlHelp(NULL, NULL, HH_CLOSE_ALL, 0); - PostQuitMessage(0); - break; - - case WM_NOTIFY: - lpnm = (LPNMHDR) lParam; - if(lpnm->hwndFrom == khui_main_menu_toolbar) { - return khm_menu_notify_main(lpnm); - } else if(lpnm->hwndFrom == khui_hwnd_standard_toolbar) { - return khm_toolbar_notify(lpnm); - } else if(lpnm->hwndFrom == khm_hwnd_rebar) { - return khm_rebar_notify(lpnm); - } else if(lpnm->hwndFrom == khm_hwnd_statusbar) { - return khm_statusbar_notify(lpnm); - } - break; - - case WM_HELP: - khm_html_help(khm_hwnd_main, NULL, HH_HELP_CONTEXT, IDH_WELCOME); - break; - - case WM_COMMAND: - switch(LOWORD(wParam)) { - /* general actions */ - case KHUI_ACTION_VIEW_REFRESH: - khm_cred_refresh(); - InvalidateRect(khm_hwnd_main_cred, NULL, FALSE); - return 0; - - case KHUI_ACTION_PASSWD_ID: - if (khm_startup.processing) - return 0; - - khm_cred_change_password(NULL); - return 0; - - case KHUI_ACTION_NEW_CRED: - if (khm_startup.processing) - return 0; - - khm_cred_obtain_new_creds(NULL); - return 0; - - case KHUI_ACTION_RENEW_CRED: - if (khm_startup.processing) - return 0; - - khm_cred_renew_creds(); - return 0; - - case KHUI_ACTION_DESTROY_CRED: - if (khm_startup.processing) - return 0; - - khm_cred_destroy_creds(FALSE, FALSE); - return 0; - - case KHUI_ACTION_SET_DEF_ID: - if (khm_startup.processing) - return 0; - - khm_cred_set_default(); - return 0; - - case KHUI_ACTION_EXIT: - DestroyWindow(hwnd); - return 0; - - case KHUI_ACTION_OPEN_APP: - khm_show_main_window(); - return 0; - - case KHUI_ACTION_CLOSE_APP: - khm_hide_main_window(); - return 0; - - case KHUI_ACTION_OPT_KHIM: { - khui_config_node node = NULL; - - khui_cfg_open(NULL, L"KhmGeneral", &node); - khm_show_config_pane(node); - } - return 0; - - case KHUI_ACTION_OPT_IDENTS: { - khui_config_node node = NULL; - - khui_cfg_open(NULL, L"KhmIdentities", &node); - khm_show_config_pane(node); - } - return 0; - - case KHUI_ACTION_OPT_APPEAR: { - khui_config_node node = NULL; - - khui_cfg_open(NULL, L"KhmAppear", &node); - khm_show_config_pane(node); - } - return 0; - - case KHUI_ACTION_OPT_NOTIF: { - khui_config_node node = NULL; - - khui_cfg_open(NULL, L"KhmNotifications", &node); - khm_show_config_pane(node); - } - return 0; - - case KHUI_ACTION_OPT_PLUGINS: { - khui_config_node node = NULL; - - khui_cfg_open(NULL, L"KhmPlugins", &node); - khm_show_config_pane(node); - } - return 0; - - case KHUI_ACTION_HELP_CTX: - khm_html_help(khm_hwnd_main, NULL, HH_HELP_CONTEXT, IDH_WELCOME); - return 0; - - case KHUI_ACTION_HELP_CONTENTS: - khm_html_help(khm_hwnd_main, NULL, HH_DISPLAY_TOC, 0); - return 0; - - case KHUI_ACTION_HELP_INDEX: - khm_html_help(khm_hwnd_main, NULL, HH_DISPLAY_INDEX, (DWORD_PTR) L""); - return 0; - - case KHUI_ACTION_HELP_ABOUT: - khm_create_about_window(); - return 0; - - case KHUI_ACTION_IMPORT: - khm_cred_import(); - return 0; - - case KHUI_ACTION_PROPERTIES: - /* properties are not handled by the main window. - Just bounce it to credwnd. However, use SendMessage - instead of PostMessage so we don't lose context */ - return SendMessage(khm_hwnd_main_cred, uMsg, - wParam, lParam); - - case KHUI_ACTION_UICB: - khm_ui_cb(lParam); - return 0; - - /* layout control */ - case KHUI_ACTION_LAYOUT_MINI: - if (khm_main_wnd_mode == KHM_MAIN_WND_MINI) { - khm_set_main_window_mode(KHM_MAIN_WND_NORMAL); - } else { - khm_set_main_window_mode(KHM_MAIN_WND_MINI); - } - return SendMessage(khm_hwnd_main_cred, uMsg, - wParam, lParam); - - case KHUI_ACTION_LAYOUT_RELOAD: - return SendMessage(khm_hwnd_main_cred, uMsg, - wParam, lParam); - - case KHUI_ACTION_LAYOUT_ID: - case KHUI_ACTION_LAYOUT_TYPE: - case KHUI_ACTION_LAYOUT_LOC: - case KHUI_ACTION_LAYOUT_CUST: - khm_set_main_window_mode(KHM_MAIN_WND_NORMAL); - return SendMessage(khm_hwnd_main_cred, uMsg, - wParam, lParam); - - /* menu commands */ - case KHUI_PACTION_MENU: - if(HIWORD(lParam) == 1) - mm_last_hot_item = LOWORD(lParam); - return khm_menu_activate(MENU_ACTIVATE_DEFAULT); - - case KHUI_PACTION_ESC: - /* if esc is pressed while no menu is active, we close the - main window */ - if (mm_last_hot_item == -1) { - khm_close_main_window(); - return 0; - } - - /* generic, retargetting */ - case KHUI_PACTION_UP: - case KHUI_PACTION_UP_TOGGLE: - case KHUI_PACTION_UP_EXTEND: - case KHUI_PACTION_PGUP: - case KHUI_PACTION_PGUP_EXTEND: - case KHUI_PACTION_DOWN: - case KHUI_PACTION_DOWN_TOGGLE: - case KHUI_PACTION_DOWN_EXTEND: - case KHUI_PACTION_PGDN: - case KHUI_PACTION_PGDN_EXTEND: - case KHUI_PACTION_LEFT: - case KHUI_PACTION_RIGHT: - case KHUI_PACTION_ENTER: - /* menu tracking */ - if(mm_last_hot_item != -1) { - switch(LOWORD(wParam)) { - case KHUI_PACTION_LEFT: - khm_menu_activate(MENU_ACTIVATE_LEFT); - break; - - case KHUI_PACTION_RIGHT: - khm_menu_activate(MENU_ACTIVATE_RIGHT); - break; - - case KHUI_PACTION_ESC: - case KHUI_PACTION_ENTER: - khm_menu_activate(MENU_ACTIVATE_NONE); - break; - - case KHUI_PACTION_DOWN: - khm_menu_track_current(); - break; - } - return 0; - } - - /*FALLTHROUGH*/ - case KHUI_PACTION_DELETE: - - case KHUI_PACTION_SELALL: - /* otherwise fallthrough and bounce to the creds window */ - return SendMessage(khm_hwnd_main_cred, uMsg, - wParam, lParam); - - default: - /* handle custom actions here */ - { - khui_action * act; - - /* check if this is an identity menu action. (custom - actions that were created for renewing or - destroying specific identities). */ - if (khm_check_identity_menu_action(LOWORD(wParam))) - break; - - act = khui_find_action(LOWORD(wParam)); - if (act && act->listener) { - kmq_post_sub_msg(act->listener, KMSG_ACT, KMSG_ACT_ACTIVATE, act->cmd, NULL); - return 0; - } - } - } - break; /* WM_COMMAND */ - - case WM_SYSCOMMAND: - switch(wParam & 0xfff0) { - case SC_MINIMIZE: - khm_hide_main_window(); - return 0; - - case SC_CLOSE: - khm_close_main_window(); - return 0; - } - break; - - case WM_MEASUREITEM: - /* sent to measure the bitmaps associated with a menu item */ - if(!wParam) /* sent by menu */ - return khm_menu_measure_item(wParam, lParam); - break; - - case WM_DRAWITEM: - /* sent to draw a menu item */ - if(!wParam) - return khm_menu_draw_item(wParam, lParam); - break; - - case WM_ERASEBKGND: - /* Don't erase the background. The whole client area is - covered with children. It doesn't need to be erased */ - return TRUE; - break; - - case WM_SIZE: - if(hwnd == khm_hwnd_main && - (wParam == SIZE_MAXIMIZED || wParam == SIZE_RESTORED)) { - int cwidth, cheight; - RECT r_rebar, r_status; - - cwidth = LOWORD(lParam); - cheight = HIWORD(lParam); - - /* resize the rebar control */ - SendMessage(khm_hwnd_rebar, WM_SIZE, 0, 0); - - khm_update_statusbar(hwnd); - - GetWindowRect(khm_hwnd_rebar, &r_rebar); - GetWindowRect(khm_hwnd_statusbar, &r_status); - - /* the cred window fills the area between the rebar - and the status bar */ - MoveWindow(khm_hwnd_main_cred, 0, - r_rebar.bottom - r_rebar.top, - r_status.right - r_status.left, - r_status.top - r_rebar.bottom, TRUE); - - SetTimer(hwnd, - MW_RESIZE_TIMER, - MW_RESIZE_TIMEOUT, - NULL); - return 0; - } - break; - - case WM_MOVE: - { - SetTimer(hwnd, - MW_RESIZE_TIMER, - MW_RESIZE_TIMEOUT, - NULL); - - return 0; - } - break; - - case WM_MOVING: - { - RECT * r; - - r = (RECT *) lParam; - khm_adjust_window_dimensions_for_display(r, - KHM_DOCK_AUTO | KHM_DOCKF_XBORDER); - } - return TRUE; - - case WM_TIMER: - if (wParam == MW_RESIZE_TIMER) { - RECT r; - khm_handle csp_cw; - khm_handle csp_mw; - const wchar_t * wconfig; - - if (khm_main_wnd_mode == KHM_MAIN_WND_MINI) - wconfig = L"Windows\\MainMini"; - else - wconfig = L"Windows\\Main"; - - KillTimer(hwnd, wParam); - - GetWindowRect(hwnd, &r); - - if (KHM_SUCCEEDED(khc_open_space(NULL, - L"CredWindow", - KHM_PERM_WRITE, - &csp_cw))) { - if (KHM_SUCCEEDED(khc_open_space(csp_cw, - wconfig, - KHM_PERM_WRITE, - &csp_mw))) { - khm_int32 t; - - khc_write_int32(csp_mw, L"XPos", r.left); - khc_write_int32(csp_mw, L"YPos", r.top); - khc_write_int32(csp_mw, L"Width", - r.right - r.left); - khc_write_int32(csp_mw, L"Height", - r.bottom - r.top); - - if (KHM_SUCCEEDED(khc_read_int32(csp_mw, L"Dock", &t)) && - t != KHM_DOCK_NONE) { - khc_write_int32(csp_mw, L"Dock", KHM_DOCK_AUTO); - } - - khc_close_space(csp_mw); - } - khc_close_space(csp_cw); - } - - return 0; - - } else if (wParam == MW_REFRESH_TIMER) { - kmq_post_message(KMSG_CRED, KMSG_CRED_REFRESH, 0, 0); - - return 0; - - } - break; - - case WM_MENUSELECT: - return khm_menu_handle_select(wParam, lParam); - - case KMQ_WM_DISPATCH: - { - kmq_message * m; - khm_int32 rv = KHM_ERROR_SUCCESS; - - kmq_wm_begin(lParam, &m); - if (m->type == KMSG_ACT && - m->subtype == KMSG_ACT_REFRESH) { - khm_menu_refresh_items(); - khm_update_standard_toolbar(); - } else if (m->type == KMSG_ACT && - m->subtype == KMSG_ACT_BEGIN_CMDLINE) { - khm_cred_begin_startup_actions(); - } else if (m->type == KMSG_ACT && - m->subtype == KMSG_ACT_CONTINUE_CMDLINE) { - khm_cred_process_startup_actions(); - } else if (m->type == KMSG_ACT && - m->subtype == KMSG_ACT_END_CMDLINE) { - /* nothing yet */ - } else if (m->type == KMSG_ACT && - m->subtype == KMSG_ACT_SYNC_CFG) { - khm_refresh_config(); - } else if (m->type == KMSG_ACT && - m->subtype == KMSG_ACT_ACTIVATE) { - /* some custom action fired */ - - khm_int32 action; - khui_action * paction; - - action = m->uparam; - paction = khui_find_action(action); - if (paction && paction->data == (void *) CFGACTION_MAGIC) { - /* a custom configuration needs to be invoked */ - khui_config_node node; - - if (KHM_SUCCEEDED(khui_cfg_open(NULL, paction->name, &node))) { - khm_show_config_pane(node); - khui_cfg_release(node); - } - } - } else if (m->type == KMSG_CRED && - m->subtype == KMSG_CRED_REFRESH) { - mw_restart_refresh_timer(hwnd); - } else if (m->type == KMSG_CRED && - m->subtype == KMSG_CRED_ADDR_CHANGE) { - khm_cred_addr_change(); - } else if (m->type == KMSG_CRED && - m->subtype == KMSG_CRED_ROOTDELTA) { - khm_refresh_identity_menus(); - } else if (m->type == KMSG_KMM && - m->subtype == KMSG_KMM_I_DONE) { - kmq_post_message(KMSG_ACT, KMSG_ACT_BEGIN_CMDLINE, 0, 0); - } - - return kmq_wm_end(m, rv); - } - return 0; - - case WM_KHUI_ASSIGN_COMMANDLINE_V1: - { - HANDLE hmap; - void * xfer; - wchar_t mapname[256]; - struct tag_khm_startup_options_v1 * pv1opt; - int code = KHM_ERROR_SUCCESS; - - StringCbPrintf(mapname, sizeof(mapname), - COMMANDLINE_MAP_FMT, (DWORD) lParam); - - hmap = OpenFileMapping(FILE_MAP_READ, FALSE, mapname); - - if (hmap == NULL) - return 1; - - xfer = MapViewOfFile(hmap, FILE_MAP_READ, 0, 0, - sizeof(*pv1opt)); - - if (xfer) { - pv1opt = (struct tag_khm_startup_options_v1 *) xfer; - - khm_startup.init = pv1opt->init; - khm_startup.import = pv1opt->import; - khm_startup.renew = pv1opt->renew; - khm_startup.destroy = pv1opt->destroy; - - khm_startup.autoinit = pv1opt->autoinit; - khm_startup.error_exit = FALSE; - - khm_startup.no_main_window = FALSE; - khm_startup.remote_exit = FALSE; - - UnmapViewOfFile(xfer); - } else { - code = KHM_ERROR_NOT_FOUND; - } - - CloseHandle(hmap); - - if(InSendMessage()) - ReplyMessage(code); - - if (code == KHM_ERROR_SUCCESS) { - khm_startup.exit = FALSE; - - khm_startup.seen = FALSE; - khm_startup.remote = TRUE; -#ifdef DEBUG - assert(!khm_startup.processing); -#endif - khm_startup.processing = FALSE; - - khm_cred_begin_startup_actions(); - } - - return code; - } - - case WM_KHUI_ASSIGN_COMMANDLINE_V2: - { - HANDLE hmap; - void * xfer; - wchar_t mapname[256]; - struct tag_khm_startup_options_v2 *pv2opt; - int code = KHM_ERROR_SUCCESS; - - StringCbPrintf(mapname, sizeof(mapname), - COMMANDLINE_MAP_FMT, (DWORD) lParam); - - hmap = OpenFileMapping(FILE_MAP_WRITE, FALSE, mapname); - - if (hmap == NULL) - return 1; - - xfer = MapViewOfFile(hmap, FILE_MAP_WRITE, 0, 0, - sizeof(*pv2opt)); - - if (xfer) { - pv2opt = (struct tag_khm_startup_options_v2 *) xfer; - - if (pv2opt->magic != STARTUP_OPTIONS_MAGIC || - pv2opt->cb_size != sizeof(*pv2opt)) { - code = KHM_ERROR_INVALID_PARAM; - goto done_with_v2_opt; - } - - khm_startup.init = pv2opt->init; - khm_startup.import = pv2opt->import; - khm_startup.renew = pv2opt->renew; - khm_startup.destroy = pv2opt->destroy; - - khm_startup.autoinit = pv2opt->autoinit; - khm_startup.exit = pv2opt->remote_exit; - - pv2opt->code = KHM_ERROR_SUCCESS; - - done_with_v2_opt: - UnmapViewOfFile(xfer); - } else { - code = KHM_ERROR_NOT_FOUND; - } - - CloseHandle(hmap); - - if(InSendMessage()) - ReplyMessage(code); - - if (code == KHM_ERROR_SUCCESS) { - khm_startup.seen = FALSE; - khm_startup.remote = TRUE; -#ifdef DEBUG - assert(!khm_startup.processing); -#endif - khm_startup.processing = FALSE; - - khm_cred_begin_startup_actions(); - } - - return code; - } - - case WM_KHUI_QUERY_APP_VERSION: - { - HANDLE hmap; - void * xfer; - wchar_t mapname[256]; - - StringCbPrintf(mapname, sizeof(mapname), - QUERY_APP_VER_MAP_FMT, (DWORD) lParam); - - hmap = OpenFileMapping(FILE_MAP_READ | FILE_MAP_WRITE, - FALSE, mapname); - - if (hmap == NULL) - return 1; - - xfer = MapViewOfFile(hmap, FILE_MAP_WRITE, 0, 0, - sizeof(khm_query_app_version)); - - if (xfer) { - khm_process_query_app_ver((khm_query_app_version *) xfer); - - UnmapViewOfFile(xfer); - } - - CloseHandle(hmap); - } - return 0; - - } - return DefWindowProc(hwnd,uMsg,wParam,lParam); -} - -LRESULT CALLBACK -khm_null_wnd_proc(HWND hwnd, - UINT uMsg, - WPARAM wParam, - LPARAM lParam) { - return DefWindowProc(hwnd, uMsg, wParam, lParam); -} - -LRESULT -khm_rebar_notify(LPNMHDR lpnm) { - switch(lpnm->code) { -#if (_WIN32_WINNT >= 0x0501) - case RBN_AUTOBREAK: - { - LPNMREBARAUTOBREAK lpra = (LPNMREBARAUTOBREAK) lpnm; - lpra->fAutoBreak = TRUE; - } - break; -#endif - case RBN_BEGINDRAG: - { - LPNMREBAR lprb = (LPNMREBAR) lpnm; - if ((lprb->dwMask & RBNM_ID) && - lprb->wID == 0) - return 1; - else - return 0; - } - break; - - case NM_CUSTOMDRAW: - return CDRF_DODEFAULT; - break; - } - - return 1; -} - -void -khm_create_main_window_controls(HWND hwnd_main) { - REBARINFO rbi; - HWND hwRebar; - - khm_menu_create_main(hwnd_main); - - hwRebar = - CreateWindowEx(WS_EX_TOOLWINDOW, - REBARCLASSNAME, - L"Rebar", - WS_CHILD | - WS_VISIBLE| - WS_CLIPSIBLINGS | - WS_CLIPCHILDREN | - CCS_NODIVIDER | - RBS_VARHEIGHT | - RBS_FIXEDORDER, - 0,0,0,0, - hwnd_main, - NULL, - khm_hInstance, - NULL); - - if(!hwRebar) { - DWORD dwe = GetLastError(); - return; - } - - khm_hwnd_rebar = hwRebar; - - rbi.cbSize = sizeof(rbi); - rbi.fMask = 0; - rbi.himl = (HIMAGELIST) NULL; - if(!SendMessage(hwRebar, RB_SETBARINFO, 0, (LPARAM) &rbi)) - return; - - /* self attach */ - khm_create_standard_toolbar(hwRebar); - khm_create_statusbar(hwnd_main); - - /* manual attach */ - khm_hwnd_main_cred = khm_create_credwnd(hwnd_main); -} - -void -khm_adjust_window_dimensions_for_display(RECT * pr, int dock) { - - HMONITOR hmon; - RECT rm; - long x, y, width, height; - - x = pr->left; - y = pr->top; - width = pr->right - pr->left; - height = pr->bottom - pr->top; - - /* if the rect doesn't intersect with the display area of any - monitor, we just default to the primary monitor. */ - hmon = MonitorFromRect(pr, MONITOR_DEFAULTTOPRIMARY); - - if (hmon == NULL) { - /* huh? we'll just center this on the primary screen */ - goto nomonitor; - } else { - MONITORINFO mi; - - ZeroMemory(&mi, sizeof(mi)); - mi.cbSize = sizeof(mi); - - if (!GetMonitorInfo(hmon, &mi)) - goto nomonitor; - - CopyRect(&rm, &mi.rcWork); - - goto adjust_dims; - } - - nomonitor: - /* for some reason we couldn't get a handle on a monitor or we - couldn't get the metrics for that monitor. We default to - setting things up on the primary monitor. */ - - SetRectEmpty(&rm); - if (!SystemParametersInfo(SPI_GETWORKAREA, 0, (PVOID) &rm, 0)) - goto done_with_monitor; - - adjust_dims: - - if (width > (rm.right - rm.left)) - width = rm.right - rm.left; - if (height > (rm.bottom - rm.top)) - height = rm.bottom - rm.top; - - switch (dock & KHM_DOCKF_DOCKHINT) { - case KHM_DOCK_TOPLEFT: - x = rm.left; - y = rm.top; - break; - - case KHM_DOCK_TOPRIGHT: - x = rm.right - width; - y = rm.top; - break; - - case KHM_DOCK_BOTTOMRIGHT: - x = rm.right - width; - y = rm.bottom - height; - break; - - case KHM_DOCK_BOTTOMLEFT: - x = rm.left; - y = rm.bottom - height; - break; - - case KHM_DOCK_AUTO: - { - int cxt, cyt; - - cxt = GetSystemMetrics(SM_CXDRAG); - cyt = GetSystemMetrics(SM_CYDRAG); - - if (x > rm.left && (x - rm.left) < cxt) - x = rm.left; - else if ((x + width) < rm.right && (rm.right - (x + width)) < cxt) - x = rm.right - width; - - if (y > rm.top && (y - rm.top) < cyt) - y = rm.top; - else if ((y + height) < rm.bottom && (rm.bottom - (y + height)) < cyt) - y = rm.bottom - height; - } - break; - } - - if (!(dock & KHM_DOCKF_XBORDER)) { - if (x < rm.left) - x = rm.left; - if (x + width > rm.right) - x = rm.right - width; - if (y < rm.top) - y = rm.top; - if (y + height > rm.bottom) - y = rm.bottom - height; - } - - done_with_monitor: - pr->left = x; - pr->top = y; - pr->right = x + width; - pr->bottom = y + height; - -} - -void -khm_get_main_window_rect(RECT * pr) { - khm_handle csp_mw = NULL; - int x,y,width,height,dock; - RECT r; - const wchar_t * wconfig; - - x = CW_USEDEFAULT; - y = CW_USEDEFAULT; - width = CW_USEDEFAULT; - height = CW_USEDEFAULT; - dock = KHM_DOCK_NONE; - - if (khm_main_wnd_mode == KHM_MAIN_WND_MINI) - wconfig = L"CredWindow\\Windows\\MainMini"; - else - wconfig = L"CredWindow\\Windows\\Main"; - - if (KHM_SUCCEEDED(khc_open_space(NULL, - wconfig, - KHM_PERM_READ, - &csp_mw))) { - khm_int32 t; - - if (KHM_SUCCEEDED(khc_read_int32(csp_mw, L"XPos", &t))) - x = t; - if (KHM_SUCCEEDED(khc_read_int32(csp_mw, L"YPos", &t))) - y = t; - if (KHM_SUCCEEDED(khc_read_int32(csp_mw, L"Width", &t))) - width = t; - if (KHM_SUCCEEDED(khc_read_int32(csp_mw, L"Height", &t))) - height = t; - if (KHM_SUCCEEDED(khc_read_int32(csp_mw, L"Dock", &t))) - dock = t; - - khc_close_space(csp_mw); - } - - /* If there were no default values, we default to using 1/4 of the - work area centered on the primary monitor. If there were any - docking hints, then the next call to - khm_adjust_window_dimensions_for_display() will reposition the - window. */ - if (width == CW_USEDEFAULT || x == CW_USEDEFAULT) { - RECT wr; - - SetRectEmpty(&wr); - SystemParametersInfo(SPI_GETWORKAREA, 0, &wr, 0); - - if (width == CW_USEDEFAULT) { - width = (wr.right - wr.left) / 2; - height = (wr.bottom - wr.top) / 2; - } - - if (x == CW_USEDEFAULT) { - x = (wr.left + wr.right) / 2 - width / 2; - y = (wr.top + wr.bottom) / 2 - height / 2; - } - } - - /* The saved dimensions might not actually be visible if the user - has changed the resolution of the display or if it's a multiple - monitor system where the monitor on which the Network Identity - Manager window was on previously is no longer connected. We - have to check for that and adjust the dimensions if needed. */ - SetRect(&r, x, y, x + width, y + height); - khm_adjust_window_dimensions_for_display(&r, dock); - - *pr = r; -} - -void -khm_set_main_window_mode(int mode) { - - RECT r; - khm_handle csp_cw; - - if (mode == khm_main_wnd_mode) - return; - - khui_check_action(KHUI_ACTION_LAYOUT_MINI, - ((mode == KHM_MAIN_WND_MINI)? FALSE : TRUE)); - khui_enable_action(KHUI_MENU_LAYOUT, - ((mode == KHM_MAIN_WND_MINI)? FALSE : TRUE)); - khui_enable_action(KHUI_MENU_COLUMNS, - ((mode == KHM_MAIN_WND_MINI)? FALSE : TRUE)); - - khui_refresh_actions(); - - khm_main_wnd_mode = mode; - if (khm_hwnd_main) { - khm_get_main_window_rect(&r); - - SetWindowPos(khm_hwnd_main, - NULL, - r.left, r.top, - r.right - r.left, r.bottom - r.top, - SWP_NOACTIVATE | SWP_NOOWNERZORDER | - SWP_NOZORDER); - } - - if (KHM_SUCCEEDED(khc_open_space(NULL, L"CredWindow", KHM_PERM_WRITE, - &csp_cw))) { - - khc_write_int32(csp_cw, L"DefaultWindowMode", mode); - khc_close_space(csp_cw); - - } - - khm_cred_refresh(); -} - -void -khm_create_main_window(void) { - wchar_t buf[1024]; - khm_handle csp_cw = NULL; - RECT r; - - LoadString(khm_hInstance, IDS_MAIN_WINDOW_TITLE, - buf, ARRAYLENGTH(buf)); - - khm_hwnd_null = - CreateWindow(MAKEINTATOM(khm_null_window_class), - buf, - 0, /* Style */ - 0, 0, /* x, y */ - 100, 100, /* width, height */ - NULL, /* parent */ - NULL, /* menu */ - NULL, /* HINSTANCE */ - 0); /* lparam */ - - if (!khm_hwnd_null) - return; - - if (KHM_SUCCEEDED(khc_open_space(NULL, L"CredWindow", - KHM_PERM_READ, - &csp_cw))) { - khm_int32 t; - - if (KHM_SUCCEEDED(khc_read_int32(csp_cw, L"DefaultWindowMode", &t))) { - khm_set_main_window_mode(t); - } - - khc_close_space(csp_cw); - } - - khm_get_main_window_rect(&r); - - khm_hwnd_main = - CreateWindowEx(WS_EX_OVERLAPPEDWINDOW, - MAKEINTATOM(khm_main_window_class), - buf, - WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | - WS_CLIPSIBLINGS, - r.left, r.top, - r.right - r.left, - r.bottom - r.top, - khm_hwnd_null, - NULL, - NULL, - NULL); - - khui_set_main_window(khm_hwnd_main); -} - -void -khm_show_main_window(void) { - - if (khm_nCmdShow == SW_RESTORE) { - HWND hw; - - hw = GetForegroundWindow(); - if (hw != khm_hwnd_main) - SetForegroundWindow(khm_hwnd_main); - } - - if (khm_nCmdShow == SW_SHOWMINIMIZED || - khm_nCmdShow == SW_SHOWMINNOACTIVE || - khm_nCmdShow == SW_MINIMIZE) { - khm_hide_main_window(); - } else { - ShowWindow(khm_hwnd_main, khm_nCmdShow); - UpdateWindow(khm_hwnd_main); - - khm_taskbar_add_window(khm_hwnd_main); - - khm_cred_refresh(); - } - - khm_nCmdShow = SW_RESTORE; -} - -void -khm_activate_main_window(void) { - - if (!SetForegroundWindow(khm_hwnd_main)) { - FLASHWINFO finfo; - - SetActiveWindow(khm_hwnd_main); - - ZeroMemory(&finfo, sizeof(finfo)); - finfo.cbSize = sizeof(finfo); - finfo.hwnd = khm_hwnd_main; - finfo.dwFlags = FLASHW_ALL; - finfo.uCount = 3; - finfo.dwTimeout = 0; - - FlashWindowEx(&finfo); - } -} - -void -khm_close_main_window(void) { - khm_handle csp_cw; - BOOL keep_running = FALSE; - - if (KHM_SUCCEEDED(khc_open_space(NULL, L"CredWindow", - KHM_PERM_READ, &csp_cw))) { - khm_int32 t; - - if (KHM_SUCCEEDED(khc_read_int32(csp_cw, L"KeepRunning", - &t))) { - keep_running = t; - } else { -#ifdef DEBUG - assert(FALSE); -#endif - } - - khc_close_space(csp_cw); - } else { -#ifdef DEBUG - assert(FALSE); -#endif - } - - if (keep_running) - khm_hide_main_window(); - else - DestroyWindow(khm_hwnd_main); -} - -void -khm_hide_main_window(void) { - khm_handle csp_notices = NULL; - khm_int32 show_warning = FALSE; - - if (khm_nCmdShow != SW_MINIMIZE && - KHM_SUCCEEDED(khc_open_space(NULL, L"CredWindow\\Notices", - KHM_PERM_WRITE, &csp_notices)) && - KHM_SUCCEEDED(khc_read_int32(csp_notices, L"MinimizeWarning", - &show_warning)) && - show_warning != 0) { - - khui_alert * alert; - wchar_t title[KHUI_MAXCCH_TITLE]; - wchar_t msg[KHUI_MAXCCH_MESSAGE]; - - LoadString(khm_hInstance, IDS_WARN_WM_TITLE, - title, ARRAYLENGTH(title)); - LoadString(khm_hInstance, IDS_WARN_WM_MSG, - msg, ARRAYLENGTH(msg)); - - khui_alert_create_simple(title, msg, KHERR_INFO, &alert); - khui_alert_set_flags(alert, KHUI_ALERT_FLAG_REQUEST_BALLOON, - KHUI_ALERT_FLAG_REQUEST_BALLOON); - - khui_alert_show(alert); - - khc_write_int32(csp_notices, L"MinimizeWarning", 0); - } - - if (csp_notices != NULL) - khc_close_space(csp_notices); - - ShowWindow(khm_hwnd_main, SW_HIDE); - - khm_taskbar_remove_window(khm_hwnd_main); -} - -BOOL -khm_is_main_window_visible(void) { - return IsWindowVisible(khm_hwnd_main); -} - -BOOL -khm_is_main_window_active(void) { - if (!IsWindowVisible(khm_hwnd_main)) - return FALSE; - if (GetForegroundWindow() == khm_hwnd_main) - return TRUE; - return khm_is_dialog_active(); -} - -void -khm_register_main_wnd_class(void) { - WNDCLASSEX wc; - - wc.cbSize = sizeof(WNDCLASSEX); - wc.style = 0; - wc.lpfnWndProc = khm_null_wnd_proc; - wc.cbClsExtra = 0; - wc.cbWndExtra = 0; - wc.hInstance = khm_hInstance; - wc.hIcon = LoadIcon(khm_hInstance, MAKEINTRESOURCE(IDI_MAIN_APP)); - wc.hCursor = LoadCursor((HINSTANCE) NULL, MAKEINTRESOURCE(IDC_ARROW)); - wc.hIconSm = LoadImage(khm_hInstance, MAKEINTRESOURCE(IDI_MAIN_APP), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE); - wc.hbrBackground = (HBRUSH) (COLOR_APPWORKSPACE); - wc.lpszMenuName = NULL; - wc.lpszClassName = KHUI_NULL_WINDOW_CLASS; - - khm_null_window_class = RegisterClassEx(&wc); - - wc.cbSize = sizeof(WNDCLASSEX); - wc.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW; - wc.lpfnWndProc = khm_main_wnd_proc; - wc.cbClsExtra = 0; - wc.cbWndExtra = 0; - wc.hInstance = khm_hInstance; - wc.hIcon = LoadIcon(khm_hInstance, MAKEINTRESOURCE(IDI_MAIN_APP)); - wc.hCursor = LoadCursor((HINSTANCE) NULL, MAKEINTRESOURCE(IDC_ARROW)); - wc.hIconSm = LoadImage(khm_hInstance, MAKEINTRESOURCE(IDI_MAIN_APP), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE); - wc.hbrBackground = (HBRUSH) (COLOR_APPWORKSPACE); - wc.lpszMenuName = NULL; - wc.lpszClassName = KHUI_MAIN_WINDOW_CLASS; - - khm_main_window_class = RegisterClassEx(&wc); -} - -void -khm_unregister_main_wnd_class(void) { - UnregisterClass(MAKEINTATOM(khm_main_window_class),khm_hInstance); - UnregisterClass(MAKEINTATOM(khm_null_window_class),khm_hInstance); -} +/* + * 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 +#include +#include + +ATOM khm_main_window_class; +ATOM khm_null_window_class; +HWND khm_hwnd_null; +HWND khm_hwnd_main; +HWND khm_hwnd_rebar; +HWND khm_hwnd_main_cred; + +int khm_main_wnd_mode = KHM_MAIN_WND_NORMAL; + +#define MW_RESIZE_TIMER 1 +#define MW_RESIZE_TIMEOUT 2000 +#define MW_REFRESH_TIMER 2 +#define MW_REFRESH_TIMEOUT 600 + +void +khm_set_dialog_result(HWND hwnd, LRESULT lr) { +#pragma warning(push) +#pragma warning(disable: 4244) + SetWindowLongPtr(hwnd, DWLP_MSGRESULT, lr); +#pragma warning(pop) +} + +static void +mw_restart_refresh_timer(HWND hwnd) { + khm_handle csp_cw; + khm_int32 timeout; + + KillTimer(hwnd, MW_REFRESH_TIMER); + if (KHM_SUCCEEDED(khc_open_space(NULL, + L"CredWindow", + KHM_PERM_READ, + &csp_cw))) { + if (KHM_FAILED(khc_read_int32(csp_cw, + L"RefreshTimeout", + &timeout))) + timeout = MW_REFRESH_TIMEOUT; + khc_close_space(csp_cw); + } else { + timeout = MW_REFRESH_TIMEOUT; + } + + timeout *= 1000; /* convert to milliseconds */ + + SetTimer(hwnd, MW_REFRESH_TIMER, timeout, NULL); +} + +khm_int32 KHMAPI +mw_select_cred(khm_handle cred, void * rock) { + if (cred) + kcdb_cred_set_flags(cred, + KCDB_CRED_FLAG_SELECTED, + KCDB_CRED_FLAG_SELECTED); + + return KHM_ERROR_SUCCESS; +} + +/* perform shutdown operations */ +static void +khm_pre_shutdown(void) { + khm_handle csp_cw = NULL; + khm_handle credset = NULL; + khm_int32 t; + khm_size s; + + /* Check if we should destroy all credentials on exit... */ + + if (KHM_FAILED(khc_open_space(NULL, L"CredWindow", 0, &csp_cw))) + return; + + if (KHM_FAILED(khc_read_int32(csp_cw, L"DestroyCredsOnExit", &t)) || + !t) + goto _cleanup; + + if (KHM_FAILED(kcdb_credset_create(&credset))) + goto _cleanup; + + if (KHM_FAILED(kcdb_credset_extract(credset, NULL, NULL, + KCDB_TYPE_INVALID))) + goto _cleanup; + + if (KHM_FAILED(kcdb_credset_get_size(credset, &s)) || + s == 0) + goto _cleanup; + + kcdb_credset_apply(credset, mw_select_cred, NULL); + + khui_context_set(KHUI_SCOPE_GROUP, + NULL, + KCDB_CREDTYPE_INVALID, + NULL, + NULL, + 0, + credset); + + khm_cred_destroy_creds(TRUE, TRUE); + + _cleanup: + + if (credset) + kcdb_credset_delete(credset); + + if (csp_cw) + khc_close_space(csp_cw); +} + +void +khm_process_query_app_ver(khm_query_app_version * papp_ver) { + + if (!papp_ver || papp_ver->magic != KHM_QUERY_APP_VER_MAGIC) + return; + + papp_ver->ver_remote = app_version; + + /* the remote instance has requested swapping in. we check the + version numbers and if the remote instance is newer than us, + then we exit and let the remote instance take over. */ + if (papp_ver->request_swap) { + khm_version ver_caller = papp_ver->ver_caller; + + if (ver_caller.major > app_version.major || + + (ver_caller.major == app_version.major && + ver_caller.minor > app_version.minor) || + + (ver_caller.major == app_version.major && + ver_caller.minor == app_version.minor && + ver_caller.aux > app_version.aux) || + + (ver_caller.major == app_version.major && + ver_caller.minor == app_version.minor && + ver_caller.aux == app_version.aux && + ver_caller.patch > app_version.patch)) { + + papp_ver->request_swap = TRUE; + + if (khm_hwnd_main) + DestroyWindow(khm_hwnd_main); + + } else { + + papp_ver->request_swap = FALSE; + + } + } + + papp_ver->code = KHM_ERROR_SUCCESS; +} + +static void +khm_ui_cb(LPARAM lParam) { + khui_ui_callback_data * pcbdata; + + pcbdata = (khui_ui_callback_data *) lParam; + + if (pcbdata == NULL || pcbdata->magic != KHUI_UICBDATA_MAGIC) { +#ifdef DEBUG + assert(FALSE); +#endif + return; + } + +#ifdef DEBUG + assert(pcbdata->cb); +#endif + + /* make the call */ + if (!IsBadCodePtr(pcbdata->cb)) + pcbdata->rv = (*pcbdata->cb)(khm_hwnd_main, pcbdata->rock); + else { +#ifdef DEBUG + assert(FALSE); +#endif + pcbdata->rv = KHM_ERROR_INVALID_PARAM; + } +} + +LRESULT CALLBACK +khm_main_wnd_proc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) +{ + LPNMHDR lpnm; + + switch(uMsg) { + case WM_CREATE: + khm_create_main_window_controls(hwnd); + kmq_subscribe_hwnd(KMSG_CRED, hwnd); + kmq_subscribe_hwnd(KMSG_ACT, hwnd); + kmq_subscribe_hwnd(KMSG_KMM, hwnd); + mw_restart_refresh_timer(hwnd); + + /* if the plug-ins finished loading before the window was + created, we would have missed the KMSG_KMM_I_DONE message. + So we check if the module load is complete and if so, fire + off KMSG_ACT_BEGIN_CMDLINE. */ + if (!kmm_load_pending()) + kmq_post_message(KMSG_ACT, KMSG_ACT_BEGIN_CMDLINE, 0, 0); + break; + + case WM_DESTROY: + khm_pre_shutdown(); + kmq_unsubscribe_hwnd(KMSG_ACT, hwnd); + kmq_unsubscribe_hwnd(KMSG_CRED, hwnd); + kmq_unsubscribe_hwnd(KMSG_KMM, hwnd); + HtmlHelp(NULL, NULL, HH_CLOSE_ALL, 0); + PostQuitMessage(0); + break; + + case WM_NOTIFY: + lpnm = (LPNMHDR) lParam; + if(lpnm->hwndFrom == khui_main_menu_toolbar) { + return khm_menu_notify_main(lpnm); + } else if(lpnm->hwndFrom == khui_hwnd_standard_toolbar) { + return khm_toolbar_notify(lpnm); + } else if(lpnm->hwndFrom == khm_hwnd_rebar) { + return khm_rebar_notify(lpnm); + } else if(lpnm->hwndFrom == khm_hwnd_statusbar) { + return khm_statusbar_notify(lpnm); + } + break; + + case WM_HELP: + khm_html_help(khm_hwnd_main, NULL, HH_HELP_CONTEXT, IDH_WELCOME); + break; + + case WM_COMMAND: + switch(LOWORD(wParam)) { + /* general actions */ + case KHUI_ACTION_VIEW_REFRESH: + khm_cred_refresh(); + InvalidateRect(khm_hwnd_main_cred, NULL, FALSE); + return 0; + + case KHUI_ACTION_PASSWD_ID: + if (khm_startup.processing) + return 0; + + khm_cred_change_password(NULL); + return 0; + + case KHUI_ACTION_NEW_CRED: + if (khm_startup.processing) + return 0; + + khm_cred_obtain_new_creds(NULL); + return 0; + + case KHUI_ACTION_RENEW_CRED: + if (khm_startup.processing) + return 0; + + khm_cred_renew_creds(); + return 0; + + case KHUI_ACTION_DESTROY_CRED: + if (khm_startup.processing) + return 0; + + khm_cred_destroy_creds(FALSE, FALSE); + return 0; + + case KHUI_ACTION_SET_DEF_ID: + if (khm_startup.processing) + return 0; + + khm_cred_set_default(); + return 0; + + case KHUI_ACTION_EXIT: + DestroyWindow(hwnd); + return 0; + + case KHUI_ACTION_OPEN_APP: + khm_show_main_window(); + return 0; + + case KHUI_ACTION_CLOSE_APP: + khm_hide_main_window(); + return 0; + + case KHUI_ACTION_OPT_KHIM: { + khui_config_node node = NULL; + + khui_cfg_open(NULL, L"KhmGeneral", &node); + khm_show_config_pane(node); + } + return 0; + + case KHUI_ACTION_OPT_IDENTS: { + khui_config_node node = NULL; + + khui_cfg_open(NULL, L"KhmIdentities", &node); + khm_show_config_pane(node); + } + return 0; + + case KHUI_ACTION_OPT_APPEAR: { + khui_config_node node = NULL; + + khui_cfg_open(NULL, L"KhmAppear", &node); + khm_show_config_pane(node); + } + return 0; + + case KHUI_ACTION_OPT_NOTIF: { + khui_config_node node = NULL; + + khui_cfg_open(NULL, L"KhmNotifications", &node); + khm_show_config_pane(node); + } + return 0; + + case KHUI_ACTION_OPT_PLUGINS: { + khui_config_node node = NULL; + + khui_cfg_open(NULL, L"KhmPlugins", &node); + khm_show_config_pane(node); + } + return 0; + + case KHUI_ACTION_HELP_CTX: + khm_html_help(khm_hwnd_main, NULL, HH_HELP_CONTEXT, IDH_WELCOME); + return 0; + + case KHUI_ACTION_HELP_CONTENTS: + khm_html_help(khm_hwnd_main, NULL, HH_DISPLAY_TOC, 0); + return 0; + + case KHUI_ACTION_HELP_INDEX: + khm_html_help(khm_hwnd_main, NULL, HH_DISPLAY_INDEX, (DWORD_PTR) L""); + return 0; + + case KHUI_ACTION_HELP_ABOUT: + khm_create_about_window(); + return 0; + + case KHUI_ACTION_IMPORT: + khm_cred_import(); + return 0; + + case KHUI_ACTION_PROPERTIES: + /* properties are not handled by the main window. + Just bounce it to credwnd. However, use SendMessage + instead of PostMessage so we don't lose context */ + return SendMessage(khm_hwnd_main_cred, uMsg, + wParam, lParam); + + case KHUI_ACTION_UICB: + khm_ui_cb(lParam); + return 0; + + /* layout control */ + case KHUI_ACTION_LAYOUT_MINI: + if (khm_main_wnd_mode == KHM_MAIN_WND_MINI) { + khm_set_main_window_mode(KHM_MAIN_WND_NORMAL); + } else { + khm_set_main_window_mode(KHM_MAIN_WND_MINI); + } + return SendMessage(khm_hwnd_main_cred, uMsg, + wParam, lParam); + + case KHUI_ACTION_LAYOUT_RELOAD: + return SendMessage(khm_hwnd_main_cred, uMsg, + wParam, lParam); + + case KHUI_ACTION_LAYOUT_ID: + case KHUI_ACTION_LAYOUT_TYPE: + case KHUI_ACTION_LAYOUT_LOC: + case KHUI_ACTION_LAYOUT_CUST: + khm_set_main_window_mode(KHM_MAIN_WND_NORMAL); + return SendMessage(khm_hwnd_main_cred, uMsg, + wParam, lParam); + + /* menu commands */ + case KHUI_PACTION_MENU: + if(HIWORD(lParam) == 1) + mm_last_hot_item = LOWORD(lParam); + return khm_menu_activate(MENU_ACTIVATE_DEFAULT); + + case KHUI_PACTION_ESC: + /* if esc is pressed while no menu is active, we close the + main window */ + if (mm_last_hot_item == -1) { + khm_close_main_window(); + return 0; + } + + /* generic, retargetting */ + case KHUI_PACTION_UP: + case KHUI_PACTION_UP_TOGGLE: + case KHUI_PACTION_UP_EXTEND: + case KHUI_PACTION_PGUP: + case KHUI_PACTION_PGUP_EXTEND: + case KHUI_PACTION_DOWN: + case KHUI_PACTION_DOWN_TOGGLE: + case KHUI_PACTION_DOWN_EXTEND: + case KHUI_PACTION_PGDN: + case KHUI_PACTION_PGDN_EXTEND: + case KHUI_PACTION_LEFT: + case KHUI_PACTION_RIGHT: + case KHUI_PACTION_ENTER: + /* menu tracking */ + if(mm_last_hot_item != -1) { + switch(LOWORD(wParam)) { + case KHUI_PACTION_LEFT: + khm_menu_activate(MENU_ACTIVATE_LEFT); + break; + + case KHUI_PACTION_RIGHT: + khm_menu_activate(MENU_ACTIVATE_RIGHT); + break; + + case KHUI_PACTION_ESC: + case KHUI_PACTION_ENTER: + khm_menu_activate(MENU_ACTIVATE_NONE); + break; + + case KHUI_PACTION_DOWN: + khm_menu_track_current(); + break; + } + return 0; + } + + /*FALLTHROUGH*/ + case KHUI_PACTION_DELETE: + + case KHUI_PACTION_SELALL: + /* otherwise fallthrough and bounce to the creds window */ + return SendMessage(khm_hwnd_main_cred, uMsg, + wParam, lParam); + + default: + /* handle custom actions here */ + { + khui_action * act; + + /* check if this is an identity menu action. (custom + actions that were created for renewing or + destroying specific identities). */ + if (khm_check_identity_menu_action(LOWORD(wParam))) + break; + + act = khui_find_action(LOWORD(wParam)); + if (act && act->listener) { + kmq_post_sub_msg(act->listener, KMSG_ACT, KMSG_ACT_ACTIVATE, act->cmd, NULL); + return 0; + } + } + } + break; /* WM_COMMAND */ + + case WM_SYSCOMMAND: + switch(wParam & 0xfff0) { + case SC_MINIMIZE: + khm_hide_main_window(); + return 0; + + case SC_CLOSE: + khm_close_main_window(); + return 0; + } + break; + + case WM_MEASUREITEM: + /* sent to measure the bitmaps associated with a menu item */ + if(!wParam) /* sent by menu */ + return khm_menu_measure_item(wParam, lParam); + break; + + case WM_DRAWITEM: + /* sent to draw a menu item */ + if(!wParam) + return khm_menu_draw_item(wParam, lParam); + break; + + case WM_ERASEBKGND: + /* Don't erase the background. The whole client area is + covered with children. It doesn't need to be erased */ + return TRUE; + break; + + case WM_SIZE: + if(hwnd == khm_hwnd_main && + (wParam == SIZE_MAXIMIZED || wParam == SIZE_RESTORED)) { + int cwidth, cheight; + RECT r_rebar, r_status; + + cwidth = LOWORD(lParam); + cheight = HIWORD(lParam); + + /* resize the rebar control */ + SendMessage(khm_hwnd_rebar, WM_SIZE, 0, 0); + + khm_update_statusbar(hwnd); + + GetWindowRect(khm_hwnd_rebar, &r_rebar); + GetWindowRect(khm_hwnd_statusbar, &r_status); + + /* the cred window fills the area between the rebar + and the status bar */ + MoveWindow(khm_hwnd_main_cred, 0, + r_rebar.bottom - r_rebar.top, + r_status.right - r_status.left, + r_status.top - r_rebar.bottom, TRUE); + + SetTimer(hwnd, + MW_RESIZE_TIMER, + MW_RESIZE_TIMEOUT, + NULL); + return 0; + } + break; + + case WM_MOVE: + { + SetTimer(hwnd, + MW_RESIZE_TIMER, + MW_RESIZE_TIMEOUT, + NULL); + + return 0; + } + break; + + case WM_MOVING: + { + RECT * r; + + r = (RECT *) lParam; + khm_adjust_window_dimensions_for_display(r, + KHM_DOCK_AUTO | KHM_DOCKF_XBORDER); + } + return TRUE; + + case WM_TIMER: + if (wParam == MW_RESIZE_TIMER) { + RECT r; + khm_handle csp_cw; + khm_handle csp_mw; + const wchar_t * wconfig; + + if (khm_main_wnd_mode == KHM_MAIN_WND_MINI) + wconfig = L"Windows\\MainMini"; + else + wconfig = L"Windows\\Main"; + + KillTimer(hwnd, wParam); + + GetWindowRect(hwnd, &r); + + if (KHM_SUCCEEDED(khc_open_space(NULL, + L"CredWindow", + KHM_PERM_WRITE, + &csp_cw))) { + if (KHM_SUCCEEDED(khc_open_space(csp_cw, + wconfig, + KHM_PERM_WRITE, + &csp_mw))) { + khm_int32 t; + + khc_write_int32(csp_mw, L"XPos", r.left); + khc_write_int32(csp_mw, L"YPos", r.top); + khc_write_int32(csp_mw, L"Width", + r.right - r.left); + khc_write_int32(csp_mw, L"Height", + r.bottom - r.top); + + if (KHM_SUCCEEDED(khc_read_int32(csp_mw, L"Dock", &t)) && + t != KHM_DOCK_NONE) { + khc_write_int32(csp_mw, L"Dock", KHM_DOCK_AUTO); + } + + khc_close_space(csp_mw); + } + khc_close_space(csp_cw); + } + + return 0; + + } else if (wParam == MW_REFRESH_TIMER) { + kmq_post_message(KMSG_CRED, KMSG_CRED_REFRESH, 0, 0); + + return 0; + + } + break; + + case WM_MENUSELECT: + return khm_menu_handle_select(wParam, lParam); + + case KMQ_WM_DISPATCH: + { + kmq_message * m; + khm_int32 rv = KHM_ERROR_SUCCESS; + + kmq_wm_begin(lParam, &m); + if (m->type == KMSG_ACT && + m->subtype == KMSG_ACT_REFRESH) { + khm_menu_refresh_items(); + khm_update_standard_toolbar(); + } else if (m->type == KMSG_ACT && + m->subtype == KMSG_ACT_BEGIN_CMDLINE) { + khm_cred_begin_startup_actions(); + } else if (m->type == KMSG_ACT && + m->subtype == KMSG_ACT_CONTINUE_CMDLINE) { + khm_cred_process_startup_actions(); + } else if (m->type == KMSG_ACT && + m->subtype == KMSG_ACT_END_CMDLINE) { + /* nothing yet */ + } else if (m->type == KMSG_ACT && + m->subtype == KMSG_ACT_SYNC_CFG) { + khm_refresh_config(); + } else if (m->type == KMSG_ACT && + m->subtype == KMSG_ACT_ACTIVATE) { + /* some custom action fired */ + + khm_int32 action; + khui_action * paction; + + action = m->uparam; + paction = khui_find_action(action); + if (paction && paction->data == (void *) CFGACTION_MAGIC) { + /* a custom configuration needs to be invoked */ + khui_config_node node; + + if (KHM_SUCCEEDED(khui_cfg_open(NULL, paction->name, &node))) { + khm_show_config_pane(node); + khui_cfg_release(node); + } + } + } else if (m->type == KMSG_CRED && + m->subtype == KMSG_CRED_REFRESH) { + mw_restart_refresh_timer(hwnd); + } else if (m->type == KMSG_CRED && + m->subtype == KMSG_CRED_ADDR_CHANGE) { + khm_cred_addr_change(); + } else if (m->type == KMSG_CRED && + m->subtype == KMSG_CRED_ROOTDELTA) { + khm_refresh_identity_menus(); + } else if (m->type == KMSG_KMM && + m->subtype == KMSG_KMM_I_DONE) { + kmq_post_message(KMSG_ACT, KMSG_ACT_BEGIN_CMDLINE, 0, 0); + } + + return kmq_wm_end(m, rv); + } + return 0; + + case WM_KHUI_ASSIGN_COMMANDLINE_V1: + { + HANDLE hmap; + void * xfer; + wchar_t mapname[256]; + struct tag_khm_startup_options_v1 * pv1opt; + int code = KHM_ERROR_SUCCESS; + + StringCbPrintf(mapname, sizeof(mapname), + COMMANDLINE_MAP_FMT, (DWORD) lParam); + + hmap = OpenFileMapping(FILE_MAP_READ, FALSE, mapname); + + if (hmap == NULL) + return 1; + + xfer = MapViewOfFile(hmap, FILE_MAP_READ, 0, 0, + sizeof(*pv1opt)); + + if (xfer) { + pv1opt = (struct tag_khm_startup_options_v1 *) xfer; + + khm_startup.init = pv1opt->init; + khm_startup.import = pv1opt->import; + khm_startup.renew = pv1opt->renew; + khm_startup.destroy = pv1opt->destroy; + + khm_startup.autoinit = pv1opt->autoinit; + khm_startup.error_exit = FALSE; + + khm_startup.no_main_window = FALSE; + khm_startup.remote_exit = FALSE; + + UnmapViewOfFile(xfer); + } else { + code = KHM_ERROR_NOT_FOUND; + } + + CloseHandle(hmap); + + if(InSendMessage()) + ReplyMessage(code); + + if (code == KHM_ERROR_SUCCESS) { + khm_startup.exit = FALSE; + + khm_startup.seen = FALSE; + khm_startup.remote = TRUE; +#ifdef DEBUG + assert(!khm_startup.processing); +#endif + khm_startup.processing = FALSE; + + khm_cred_begin_startup_actions(); + } + + return code; + } + + case WM_KHUI_ASSIGN_COMMANDLINE_V2: + { + HANDLE hmap; + void * xfer; + wchar_t mapname[256]; + struct tag_khm_startup_options_v2 *pv2opt; + int code = KHM_ERROR_SUCCESS; + + StringCbPrintf(mapname, sizeof(mapname), + COMMANDLINE_MAP_FMT, (DWORD) lParam); + + hmap = OpenFileMapping(FILE_MAP_WRITE, FALSE, mapname); + + if (hmap == NULL) + return 1; + + xfer = MapViewOfFile(hmap, FILE_MAP_WRITE, 0, 0, + sizeof(*pv2opt)); + + if (xfer) { + pv2opt = (struct tag_khm_startup_options_v2 *) xfer; + + if (pv2opt->magic != STARTUP_OPTIONS_MAGIC || + pv2opt->cb_size != sizeof(*pv2opt)) { + code = KHM_ERROR_INVALID_PARAM; + goto done_with_v2_opt; + } + + khm_startup.init = pv2opt->init; + khm_startup.import = pv2opt->import; + khm_startup.renew = pv2opt->renew; + khm_startup.destroy = pv2opt->destroy; + + khm_startup.autoinit = pv2opt->autoinit; + khm_startup.exit = pv2opt->remote_exit; + + pv2opt->code = KHM_ERROR_SUCCESS; + + done_with_v2_opt: + UnmapViewOfFile(xfer); + } else { + code = KHM_ERROR_NOT_FOUND; + } + + CloseHandle(hmap); + + if(InSendMessage()) + ReplyMessage(code); + + if (code == KHM_ERROR_SUCCESS) { + khm_startup.seen = FALSE; + khm_startup.remote = TRUE; +#ifdef DEBUG + assert(!khm_startup.processing); +#endif + khm_startup.processing = FALSE; + + khm_cred_begin_startup_actions(); + } + + return code; + } + + case WM_KHUI_QUERY_APP_VERSION: + { + HANDLE hmap; + void * xfer; + wchar_t mapname[256]; + + StringCbPrintf(mapname, sizeof(mapname), + QUERY_APP_VER_MAP_FMT, (DWORD) lParam); + + hmap = OpenFileMapping(FILE_MAP_READ | FILE_MAP_WRITE, + FALSE, mapname); + + if (hmap == NULL) + return 1; + + xfer = MapViewOfFile(hmap, FILE_MAP_WRITE, 0, 0, + sizeof(khm_query_app_version)); + + if (xfer) { + khm_process_query_app_ver((khm_query_app_version *) xfer); + + UnmapViewOfFile(xfer); + } + + CloseHandle(hmap); + } + return 0; + + } + return DefWindowProc(hwnd,uMsg,wParam,lParam); +} + +LRESULT CALLBACK +khm_null_wnd_proc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) { + return DefWindowProc(hwnd, uMsg, wParam, lParam); +} + +LRESULT +khm_rebar_notify(LPNMHDR lpnm) { + switch(lpnm->code) { +#if (_WIN32_WINNT >= 0x0501) + case RBN_AUTOBREAK: + { + LPNMREBARAUTOBREAK lpra = (LPNMREBARAUTOBREAK) lpnm; + lpra->fAutoBreak = TRUE; + } + break; +#endif + case RBN_BEGINDRAG: + { + LPNMREBAR lprb = (LPNMREBAR) lpnm; + if ((lprb->dwMask & RBNM_ID) && + lprb->wID == 0) + return 1; + else + return 0; + } + break; + + case NM_CUSTOMDRAW: + return CDRF_DODEFAULT; + break; + } + + return 1; +} + +void +khm_create_main_window_controls(HWND hwnd_main) { + REBARINFO rbi; + HWND hwRebar; + + khm_menu_create_main(hwnd_main); + + hwRebar = + CreateWindowEx(WS_EX_TOOLWINDOW, + REBARCLASSNAME, + L"Rebar", + WS_CHILD | + WS_VISIBLE| + WS_CLIPSIBLINGS | + WS_CLIPCHILDREN | + CCS_NODIVIDER | + RBS_VARHEIGHT | + RBS_FIXEDORDER, + 0,0,0,0, + hwnd_main, + NULL, + khm_hInstance, + NULL); + + if(!hwRebar) { + DWORD dwe = GetLastError(); + return; + } + + khm_hwnd_rebar = hwRebar; + + rbi.cbSize = sizeof(rbi); + rbi.fMask = 0; + rbi.himl = (HIMAGELIST) NULL; + if(!SendMessage(hwRebar, RB_SETBARINFO, 0, (LPARAM) &rbi)) + return; + + /* self attach */ + khm_create_standard_toolbar(hwRebar); + khm_create_statusbar(hwnd_main); + + /* manual attach */ + khm_hwnd_main_cred = khm_create_credwnd(hwnd_main); +} + +void +khm_adjust_window_dimensions_for_display(RECT * pr, int dock) { + + HMONITOR hmon; + RECT rm; + long x, y, width, height; + + x = pr->left; + y = pr->top; + width = pr->right - pr->left; + height = pr->bottom - pr->top; + + /* if the rect doesn't intersect with the display area of any + monitor, we just default to the primary monitor. */ + hmon = MonitorFromRect(pr, MONITOR_DEFAULTTOPRIMARY); + + if (hmon == NULL) { + /* huh? we'll just center this on the primary screen */ + goto nomonitor; + } else { + MONITORINFO mi; + + ZeroMemory(&mi, sizeof(mi)); + mi.cbSize = sizeof(mi); + + if (!GetMonitorInfo(hmon, &mi)) + goto nomonitor; + + CopyRect(&rm, &mi.rcWork); + + goto adjust_dims; + } + + nomonitor: + /* for some reason we couldn't get a handle on a monitor or we + couldn't get the metrics for that monitor. We default to + setting things up on the primary monitor. */ + + SetRectEmpty(&rm); + if (!SystemParametersInfo(SPI_GETWORKAREA, 0, (PVOID) &rm, 0)) + goto done_with_monitor; + + adjust_dims: + + if (width > (rm.right - rm.left)) + width = rm.right - rm.left; + if (height > (rm.bottom - rm.top)) + height = rm.bottom - rm.top; + + switch (dock & KHM_DOCKF_DOCKHINT) { + case KHM_DOCK_TOPLEFT: + x = rm.left; + y = rm.top; + break; + + case KHM_DOCK_TOPRIGHT: + x = rm.right - width; + y = rm.top; + break; + + case KHM_DOCK_BOTTOMRIGHT: + x = rm.right - width; + y = rm.bottom - height; + break; + + case KHM_DOCK_BOTTOMLEFT: + x = rm.left; + y = rm.bottom - height; + break; + + case KHM_DOCK_AUTO: + { + int cxt, cyt; + + cxt = GetSystemMetrics(SM_CXDRAG); + cyt = GetSystemMetrics(SM_CYDRAG); + + if (x > rm.left && (x - rm.left) < cxt) + x = rm.left; + else if ((x + width) < rm.right && (rm.right - (x + width)) < cxt) + x = rm.right - width; + + if (y > rm.top && (y - rm.top) < cyt) + y = rm.top; + else if ((y + height) < rm.bottom && (rm.bottom - (y + height)) < cyt) + y = rm.bottom - height; + } + break; + } + + if (!(dock & KHM_DOCKF_XBORDER)) { + if (x < rm.left) + x = rm.left; + if (x + width > rm.right) + x = rm.right - width; + if (y < rm.top) + y = rm.top; + if (y + height > rm.bottom) + y = rm.bottom - height; + } + + done_with_monitor: + pr->left = x; + pr->top = y; + pr->right = x + width; + pr->bottom = y + height; + +} + +void +khm_get_main_window_rect(RECT * pr) { + khm_handle csp_mw = NULL; + int x,y,width,height,dock; + RECT r; + const wchar_t * wconfig; + + x = CW_USEDEFAULT; + y = CW_USEDEFAULT; + width = CW_USEDEFAULT; + height = CW_USEDEFAULT; + dock = KHM_DOCK_NONE; + + if (khm_main_wnd_mode == KHM_MAIN_WND_MINI) + wconfig = L"CredWindow\\Windows\\MainMini"; + else + wconfig = L"CredWindow\\Windows\\Main"; + + if (KHM_SUCCEEDED(khc_open_space(NULL, + wconfig, + KHM_PERM_READ, + &csp_mw))) { + khm_int32 t; + + if (KHM_SUCCEEDED(khc_read_int32(csp_mw, L"XPos", &t))) + x = t; + if (KHM_SUCCEEDED(khc_read_int32(csp_mw, L"YPos", &t))) + y = t; + if (KHM_SUCCEEDED(khc_read_int32(csp_mw, L"Width", &t))) + width = t; + if (KHM_SUCCEEDED(khc_read_int32(csp_mw, L"Height", &t))) + height = t; + if (KHM_SUCCEEDED(khc_read_int32(csp_mw, L"Dock", &t))) + dock = t; + + khc_close_space(csp_mw); + } + + /* If there were no default values, we default to using 1/4 of the + work area centered on the primary monitor. If there were any + docking hints, then the next call to + khm_adjust_window_dimensions_for_display() will reposition the + window. */ + if (width == CW_USEDEFAULT || x == CW_USEDEFAULT) { + RECT wr; + + SetRectEmpty(&wr); + SystemParametersInfo(SPI_GETWORKAREA, 0, &wr, 0); + + if (width == CW_USEDEFAULT) { + width = (wr.right - wr.left) / 2; + height = (wr.bottom - wr.top) / 2; + } + + if (x == CW_USEDEFAULT) { + x = (wr.left + wr.right) / 2 - width / 2; + y = (wr.top + wr.bottom) / 2 - height / 2; + } + } + + /* The saved dimensions might not actually be visible if the user + has changed the resolution of the display or if it's a multiple + monitor system where the monitor on which the Network Identity + Manager window was on previously is no longer connected. We + have to check for that and adjust the dimensions if needed. */ + SetRect(&r, x, y, x + width, y + height); + khm_adjust_window_dimensions_for_display(&r, dock); + + *pr = r; +} + +void +khm_set_main_window_mode(int mode) { + + RECT r; + khm_handle csp_cw; + + if (mode == khm_main_wnd_mode) + return; + + khui_check_action(KHUI_ACTION_LAYOUT_MINI, + ((mode == KHM_MAIN_WND_MINI)? FALSE : TRUE)); + khui_enable_action(KHUI_MENU_LAYOUT, + ((mode == KHM_MAIN_WND_MINI)? FALSE : TRUE)); + khui_enable_action(KHUI_MENU_COLUMNS, + ((mode == KHM_MAIN_WND_MINI)? FALSE : TRUE)); + + khui_refresh_actions(); + + khm_main_wnd_mode = mode; + if (khm_hwnd_main) { + khm_get_main_window_rect(&r); + + SetWindowPos(khm_hwnd_main, + NULL, + r.left, r.top, + r.right - r.left, r.bottom - r.top, + SWP_NOACTIVATE | SWP_NOOWNERZORDER | + SWP_NOZORDER); + } + + if (KHM_SUCCEEDED(khc_open_space(NULL, L"CredWindow", KHM_PERM_WRITE, + &csp_cw))) { + + khc_write_int32(csp_cw, L"DefaultWindowMode", mode); + khc_close_space(csp_cw); + + } + + khm_cred_refresh(); +} + +void +khm_create_main_window(void) { + wchar_t buf[1024]; + khm_handle csp_cw = NULL; + RECT r; + + LoadString(khm_hInstance, IDS_MAIN_WINDOW_TITLE, + buf, ARRAYLENGTH(buf)); + + khm_hwnd_null = + CreateWindow(MAKEINTATOM(khm_null_window_class), + buf, + 0, /* Style */ + 0, 0, /* x, y */ + 100, 100, /* width, height */ + NULL, /* parent */ + NULL, /* menu */ + NULL, /* HINSTANCE */ + 0); /* lparam */ + + if (!khm_hwnd_null) + return; + + if (KHM_SUCCEEDED(khc_open_space(NULL, L"CredWindow", + KHM_PERM_READ, + &csp_cw))) { + khm_int32 t; + + if (KHM_SUCCEEDED(khc_read_int32(csp_cw, L"DefaultWindowMode", &t))) { + khm_set_main_window_mode(t); + } + + khc_close_space(csp_cw); + } + + khm_get_main_window_rect(&r); + + khm_hwnd_main = + CreateWindowEx(WS_EX_OVERLAPPEDWINDOW | WS_EX_APPWINDOW, + MAKEINTATOM(khm_main_window_class), + buf, + WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | + WS_CLIPSIBLINGS, + r.left, r.top, + r.right - r.left, + r.bottom - r.top, + khm_hwnd_null, + NULL, + NULL, + NULL); + + khui_set_main_window(khm_hwnd_main); +} + +void +khm_show_main_window(void) { + + if (khm_nCmdShow == SW_RESTORE) { + HWND hw; + + hw = GetForegroundWindow(); + if (hw != khm_hwnd_main) + SetForegroundWindow(khm_hwnd_main); + } + + if (khm_nCmdShow == SW_SHOWMINIMIZED || + khm_nCmdShow == SW_SHOWMINNOACTIVE || + khm_nCmdShow == SW_MINIMIZE) { + khm_hide_main_window(); + } else { + ShowWindow(khm_hwnd_main, khm_nCmdShow); + UpdateWindow(khm_hwnd_main); + + khm_cred_refresh(); + } + + khm_nCmdShow = SW_RESTORE; +} + +void +khm_activate_main_window(void) { + + if (!SetForegroundWindow(khm_hwnd_main)) { + FLASHWINFO finfo; + + SetActiveWindow(khm_hwnd_main); + + ZeroMemory(&finfo, sizeof(finfo)); + finfo.cbSize = sizeof(finfo); + finfo.hwnd = khm_hwnd_main; + finfo.dwFlags = FLASHW_ALL; + finfo.uCount = 3; + finfo.dwTimeout = 0; + + FlashWindowEx(&finfo); + } +} + +void +khm_close_main_window(void) { + khm_handle csp_cw; + BOOL keep_running = FALSE; + + if (KHM_SUCCEEDED(khc_open_space(NULL, L"CredWindow", + KHM_PERM_READ, &csp_cw))) { + khm_int32 t; + + if (KHM_SUCCEEDED(khc_read_int32(csp_cw, L"KeepRunning", + &t))) { + keep_running = t; + } else { +#ifdef DEBUG + assert(FALSE); +#endif + } + + khc_close_space(csp_cw); + } else { +#ifdef DEBUG + assert(FALSE); +#endif + } + + if (keep_running) + khm_hide_main_window(); + else + DestroyWindow(khm_hwnd_main); +} + +void +khm_hide_main_window(void) { + khm_handle csp_notices = NULL; + khm_int32 show_warning = FALSE; + + if (khm_nCmdShow != SW_MINIMIZE && + KHM_SUCCEEDED(khc_open_space(NULL, L"CredWindow\\Notices", + KHM_PERM_WRITE, &csp_notices)) && + KHM_SUCCEEDED(khc_read_int32(csp_notices, L"MinimizeWarning", + &show_warning)) && + show_warning != 0) { + + khui_alert * alert; + wchar_t title[KHUI_MAXCCH_TITLE]; + wchar_t msg[KHUI_MAXCCH_MESSAGE]; + + LoadString(khm_hInstance, IDS_WARN_WM_TITLE, + title, ARRAYLENGTH(title)); + LoadString(khm_hInstance, IDS_WARN_WM_MSG, + msg, ARRAYLENGTH(msg)); + + khui_alert_create_simple(title, msg, KHERR_INFO, &alert); + khui_alert_set_flags(alert, KHUI_ALERT_FLAG_REQUEST_BALLOON, + KHUI_ALERT_FLAG_REQUEST_BALLOON); + + khui_alert_show(alert); + + khc_write_int32(csp_notices, L"MinimizeWarning", 0); + } + + if (csp_notices != NULL) + khc_close_space(csp_notices); + + ShowWindow(khm_hwnd_main, SW_HIDE); +} + +BOOL +khm_is_main_window_visible(void) { + return IsWindowVisible(khm_hwnd_main); +} + +BOOL +khm_is_main_window_active(void) { + if (!IsWindowVisible(khm_hwnd_main)) + return FALSE; + if (GetForegroundWindow() == khm_hwnd_main) + return TRUE; + return khm_is_dialog_active(); +} + +void +khm_register_main_wnd_class(void) { + WNDCLASSEX wc; + + wc.cbSize = sizeof(WNDCLASSEX); + wc.style = 0; + wc.lpfnWndProc = khm_null_wnd_proc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = khm_hInstance; + wc.hIcon = LoadIcon(khm_hInstance, MAKEINTRESOURCE(IDI_MAIN_APP)); + wc.hCursor = LoadCursor((HINSTANCE) NULL, MAKEINTRESOURCE(IDC_ARROW)); + wc.hIconSm = LoadImage(khm_hInstance, MAKEINTRESOURCE(IDI_MAIN_APP), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE); + wc.hbrBackground = (HBRUSH) (COLOR_APPWORKSPACE); + wc.lpszMenuName = NULL; + wc.lpszClassName = KHUI_NULL_WINDOW_CLASS; + + khm_null_window_class = RegisterClassEx(&wc); + + wc.cbSize = sizeof(WNDCLASSEX); + wc.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW; + wc.lpfnWndProc = khm_main_wnd_proc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = khm_hInstance; + wc.hIcon = LoadIcon(khm_hInstance, MAKEINTRESOURCE(IDI_MAIN_APP)); + wc.hCursor = LoadCursor((HINSTANCE) NULL, MAKEINTRESOURCE(IDC_ARROW)); + wc.hIconSm = LoadImage(khm_hInstance, MAKEINTRESOURCE(IDI_MAIN_APP), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE); + wc.hbrBackground = (HBRUSH) (COLOR_APPWORKSPACE); + wc.lpszMenuName = NULL; + wc.lpszClassName = KHUI_MAIN_WINDOW_CLASS; + + khm_main_window_class = RegisterClassEx(&wc); +} + +void +khm_unregister_main_wnd_class(void) { + UnregisterClass(MAKEINTATOM(khm_main_window_class),khm_hInstance); + UnregisterClass(MAKEINTATOM(khm_null_window_class),khm_hInstance); +} diff --git a/src/windows/identity/ui/newcredwnd.c b/src/windows/identity/ui/newcredwnd.c index d4d9a785c..6c8ea6094 100644 --- a/src/windows/identity/ui/newcredwnd.c +++ b/src/windows/identity/ui/newcredwnd.c @@ -1,2912 +1,2908 @@ -/* - * 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 -#include - -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); - - /* 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; in_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; inc->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; inc->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); - - { - 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; - - 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); - - khm_taskbar_add_window(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); - - khm_taskbar_remove_window(hwnd); - - d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM); - - 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); - - 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); - - 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 ':' - and 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 ':!'. */ - - 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); - - 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); - - 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) { - 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 - } - } - } - - 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. */ - - /* bring the window to the top, if necessary */ - if (KHM_SUCCEEDED(khc_read_int32(NULL, - L"CredWindow\\Windows\\NewCred\\ForceToTop", - &t)) && - - t != 0) { - /* 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. */ - khm_activate_main_window(); - - SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, - (SWP_NOMOVE | SWP_NOSIZE)); - } - - ShowWindow(hwnd, SW_SHOWNOACTIVATE); - - /* 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); - - 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;inc->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; inc->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 | - ((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 (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 - d->sz_ch_target.right) * - (d->sz_ch_source.right - d->sz_ch_target.right); - - long dy = (r_now.bottom - 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); - - SetWindowPos(hwnd, NULL, - 0, 0, - r_now.right - r_now.left, - r_now.bottom - r_now.top, - SWP_NOACTIVATE | SWP_NOMOVE | 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); - 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); - - 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 CALLBACK nc_window_proc(HWND hwnd, - UINT uMsg, - WPARAM wParam, - LPARAM lParam) -{ - switch(uMsg) { - 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((LPWSTR) khui_newcredwnd_cls, khm_hInstance); -} - -HWND khm_create_newcredwnd(HWND parent, khui_new_creds * c) -{ - wchar_t wtitle[256]; - HWND hwnd; - - 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)); - } - - hwnd = CreateWindowEx(NC_WINDOW_EX_STYLES, - 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); -} +/* + * 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 +#include + +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); + + /* 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; in_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; inc->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; inc->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); + + { + 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; + + 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); + + 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); + + 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); + + 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 ':' + and 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 ':!'. */ + + 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); + + 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); + + 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) { + 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 + } + } + } + + 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. */ + + /* bring the window to the top, if necessary */ + if (KHM_SUCCEEDED(khc_read_int32(NULL, + L"CredWindow\\Windows\\NewCred\\ForceToTop", + &t)) && + + t != 0) { + /* 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. */ + khm_activate_main_window(); + + SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, + (SWP_NOMOVE | SWP_NOSIZE)); + } + + ShowWindow(hwnd, SW_SHOWNOACTIVATE); + + /* 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); + + 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;inc->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; inc->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 | + ((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 (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 - d->sz_ch_target.right) * + (d->sz_ch_source.right - d->sz_ch_target.right); + + long dy = (r_now.bottom - 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); + + SetWindowPos(hwnd, NULL, + 0, 0, + r_now.right - r_now.left, + r_now.bottom - r_now.top, + SWP_NOACTIVATE | SWP_NOMOVE | 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); + 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); + + 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 CALLBACK nc_window_proc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) +{ + switch(uMsg) { + 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((LPWSTR) khui_newcredwnd_cls, khm_hInstance); +} + +HWND khm_create_newcredwnd(HWND parent, khui_new_creds * c) +{ + wchar_t wtitle[256]; + HWND hwnd; + + 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)); + } + + hwnd = CreateWindowEx(NC_WINDOW_EX_STYLES, + 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); +} diff --git a/src/windows/identity/ui/newcredwnd.h b/src/windows/identity/ui/newcredwnd.h index 939cf0141..22819a693 100644 --- a/src/windows/identity/ui/newcredwnd.h +++ b/src/windows/identity/ui/newcredwnd.h @@ -1,189 +1,189 @@ -/* - * Copyright (c) 2005 Massachusetts Institute of Technology - * - * 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$ */ - -#ifndef __KHIMAIRA_NEWCREDWND_H -#define __KHIMAIRA_NEWCREDWND_H - -#include - -#define KHUI_NEWCREDWND_CLASS L"KhmNewCredWnd" - -typedef enum tag_nc_notification_types { - NC_NOTIFY_NONE = 0, /* no notification */ - NC_NOTIFY_MARQUEE, /* marquee type notification */ - NC_NOTIFY_PROGRESS, /* progress notification */ - NC_NOTIFY_MESSAGE, /* a message */ -} nc_notification_type; - -typedef struct khui_nc_wnd_data_t { - khui_new_creds * nc; - - /* The tab control */ - - HWND tab_wnd; /* tab control */ - int current_panel; /* ordinal of the current panel being - displayed. */ - - /* The main panel */ - HWND dlg_main; /* main dialog */ - RECT r_main; /* the extent of the main panel that - we have used so far. The rect - includes the size of the area used - by the identity selector controls, - the custom controls added by - credentials providers and the - buttons that may be required when - in the mini mode. */ - RECT r_required; /* required size of the main window */ - - /* The button bar */ - - HWND dlg_bb; /* button bar */ - - /* Sizing the new credentials window */ - - BOOL animation_enabled; /* Flag indicating whether animation - is enabled for the dialg. If this - flag is off, we don't animate size - changes even if the configuration - says so. */ - BOOL size_changing; /* flag indicating that the size of - the main window is being - adjusted. */ - RECT sz_ch_source; /* Source size, from which we are - going towards target size in - sz_ch_max steps. The RECT is self - relative (i.e. left=0 and top=0)*/ - RECT sz_ch_target; /* If we are doing an incremental size - change, this holds the target size - that we were going for. Note that - the target size might change while - we are adjusting the size. So this - helps keep track of whether we need - to start the size change again. The - RECT is self relative (i.e. left=0 - and top=0). */ - int sz_ch_increment; /* Current step of the incremental - size change operation. */ - int sz_ch_max; /* Max number of steps in the size - change operation. */ - int sz_ch_timeout; /* Milliseconds between each increment */ - - /* Custom controls and identity specifiers */ - - HWND hwnd_banner; /* static control for banner */ - HWND hwnd_name; /* static control for name */ - - HWND hwnd_last_idspec; /* last identity specifier control */ - - /* Notification windows */ - - nc_notification_type notif_type; /* Type of notification */ - HWND hwnd_notif_label; /* Label for notifications */ - HWND hwnd_notif_aux; /* Other control for notifications */ - - /* Areas of the main panel */ - - RECT r_idspec; /* Area used by identity specifiers - (relative to client) */ - RECT r_custprompt; /* Area used by custom controls (relative - to client) */ - RECT r_notif; /* Area used for notifications. */ - - /* Metrics for custom prompts and identity specifiers */ - - RECT r_row; /* Metrics for a control row (left=0, - top=0, right=width, bottom=height) */ - RECT r_area; /* Area available for controls (relative - to client) */ - RECT r_n_label; /* coords of the static control (relative - to row) */ - RECT r_n_input; /* coords of the edit control (relative to - row) */ - RECT r_e_label; /* coords of the extended edit control - (relative to row) */ - RECT r_e_input; /* coords of the extended edit control - (relative to row) */ - RECT r_credtext; /* Area for credtext window (relative to - row) */ -} khui_nc_wnd_data; - -void khm_register_newcredwnd_class(void); -void khm_unregister_newcredwnd_class(void); -HWND khm_create_newcredwnd(HWND parent, khui_new_creds * c); -void khm_prep_newcredwnd(HWND hwnd); -void khm_show_newcredwnd(HWND hwnd); - -/* Width of the button bar in dialog units */ -#define NCDLG_BBAR_WIDTH 66 -/* Height of the button bar in dialog units */ -#define NCDLG_BBAR_HEIGHT 190 - -/* Control identifier for the tab control in the new credentials - dialog. We declare this here since we will be creating the control - manually. */ -#define IDC_NC_TABS 8001 - -/* This is the first control ID that is created in the custom tabstrip - control buttons. Subsequent buttons get consecutive IDs starting - from this one. */ -#define NC_TS_CTRL_ID_MIN 8002 - -/* Maximum number of controls */ -#define NC_TS_MAX_CTRLS 8 - -/* Maximum control ID */ -#define NC_TS_CTRL_ID_MAX (NC_TS_CTRL_ID_MIN + NC_TS_MAX_CTRLS - 1) - -#define NC_BN_SET_DEF_ID 8012 - -/* the first control ID that may be used by an identity provider */ -#define NC_IS_CTRL_ID_MIN 8016 - -/* the maximum number of controls that may be created by an identity - provider*/ -#define NC_IS_CTRL_MAX_CTRLS 8 - -/* the maximum control ID that may be used by an identity provider */ -#define NC_IS_CTRL_ID_MAX (NC_IS_CTRL_ID_MIN + NC_IS_MAX_CTRLS - 1) - -#define NC_WINDOW_EX_STYLES (WS_EX_DLGMODALFRAME | WS_EX_CONTEXTHELP) -#define NC_WINDOW_STYLES (WS_DLGFRAME | WS_POPUPWINDOW | WS_CLIPCHILDREN) - -#define NC_SZ_STEPS_MIN 3 -#define NC_SZ_STEPS_DEF 10 -#define NC_SZ_STEPS_MAX 100 - -#define NC_SZ_TIMEOUT_MIN 5 -#define NC_SZ_TIMEOUT_DEF 10 -#define NC_SZ_TIMEOUT_MAX 500 - -#define NC_TIMER_SIZER 1001 -#define NC_TIMER_ENABLEANIMATE 1002 - -#define ENABLEANIMATE_TIMEOUT 400 - -#endif +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * 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$ */ + +#ifndef __KHIMAIRA_NEWCREDWND_H +#define __KHIMAIRA_NEWCREDWND_H + +#include + +#define KHUI_NEWCREDWND_CLASS L"KhmNewCredWnd" + +typedef enum tag_nc_notification_types { + NC_NOTIFY_NONE = 0, /* no notification */ + NC_NOTIFY_MARQUEE, /* marquee type notification */ + NC_NOTIFY_PROGRESS, /* progress notification */ + NC_NOTIFY_MESSAGE, /* a message */ +} nc_notification_type; + +typedef struct khui_nc_wnd_data_t { + khui_new_creds * nc; + + /* The tab control */ + + HWND tab_wnd; /* tab control */ + int current_panel; /* ordinal of the current panel being + displayed. */ + + /* The main panel */ + HWND dlg_main; /* main dialog */ + RECT r_main; /* the extent of the main panel that + we have used so far. The rect + includes the size of the area used + by the identity selector controls, + the custom controls added by + credentials providers and the + buttons that may be required when + in the mini mode. */ + RECT r_required; /* required size of the main window */ + + /* The button bar */ + + HWND dlg_bb; /* button bar */ + + /* Sizing the new credentials window */ + + BOOL animation_enabled; /* Flag indicating whether animation + is enabled for the dialg. If this + flag is off, we don't animate size + changes even if the configuration + says so. */ + BOOL size_changing; /* flag indicating that the size of + the main window is being + adjusted. */ + RECT sz_ch_source; /* Source size, from which we are + going towards target size in + sz_ch_max steps. The RECT is self + relative (i.e. left=0 and top=0)*/ + RECT sz_ch_target; /* If we are doing an incremental size + change, this holds the target size + that we were going for. Note that + the target size might change while + we are adjusting the size. So this + helps keep track of whether we need + to start the size change again. The + RECT is self relative (i.e. left=0 + and top=0). */ + int sz_ch_increment; /* Current step of the incremental + size change operation. */ + int sz_ch_max; /* Max number of steps in the size + change operation. */ + int sz_ch_timeout; /* Milliseconds between each increment */ + + /* Custom controls and identity specifiers */ + + HWND hwnd_banner; /* static control for banner */ + HWND hwnd_name; /* static control for name */ + + HWND hwnd_last_idspec; /* last identity specifier control */ + + /* Notification windows */ + + nc_notification_type notif_type; /* Type of notification */ + HWND hwnd_notif_label; /* Label for notifications */ + HWND hwnd_notif_aux; /* Other control for notifications */ + + /* Areas of the main panel */ + + RECT r_idspec; /* Area used by identity specifiers + (relative to client) */ + RECT r_custprompt; /* Area used by custom controls (relative + to client) */ + RECT r_notif; /* Area used for notifications. */ + + /* Metrics for custom prompts and identity specifiers */ + + RECT r_row; /* Metrics for a control row (left=0, + top=0, right=width, bottom=height) */ + RECT r_area; /* Area available for controls (relative + to client) */ + RECT r_n_label; /* coords of the static control (relative + to row) */ + RECT r_n_input; /* coords of the edit control (relative to + row) */ + RECT r_e_label; /* coords of the extended edit control + (relative to row) */ + RECT r_e_input; /* coords of the extended edit control + (relative to row) */ + RECT r_credtext; /* Area for credtext window (relative to + row) */ +} khui_nc_wnd_data; + +void khm_register_newcredwnd_class(void); +void khm_unregister_newcredwnd_class(void); +HWND khm_create_newcredwnd(HWND parent, khui_new_creds * c); +void khm_prep_newcredwnd(HWND hwnd); +void khm_show_newcredwnd(HWND hwnd); + +/* Width of the button bar in dialog units */ +#define NCDLG_BBAR_WIDTH 66 +/* Height of the button bar in dialog units */ +#define NCDLG_BBAR_HEIGHT 190 + +/* Control identifier for the tab control in the new credentials + dialog. We declare this here since we will be creating the control + manually. */ +#define IDC_NC_TABS 8001 + +/* This is the first control ID that is created in the custom tabstrip + control buttons. Subsequent buttons get consecutive IDs starting + from this one. */ +#define NC_TS_CTRL_ID_MIN 8002 + +/* Maximum number of controls */ +#define NC_TS_MAX_CTRLS 8 + +/* Maximum control ID */ +#define NC_TS_CTRL_ID_MAX (NC_TS_CTRL_ID_MIN + NC_TS_MAX_CTRLS - 1) + +#define NC_BN_SET_DEF_ID 8012 + +/* the first control ID that may be used by an identity provider */ +#define NC_IS_CTRL_ID_MIN 8016 + +/* the maximum number of controls that may be created by an identity + provider*/ +#define NC_IS_CTRL_MAX_CTRLS 8 + +/* the maximum control ID that may be used by an identity provider */ +#define NC_IS_CTRL_ID_MAX (NC_IS_CTRL_ID_MIN + NC_IS_MAX_CTRLS - 1) + +#define NC_WINDOW_EX_STYLES (WS_EX_DLGMODALFRAME | WS_EX_CONTEXTHELP | WS_EX_APPWINDOW) +#define NC_WINDOW_STYLES (WS_DLGFRAME | WS_POPUPWINDOW | WS_CLIPCHILDREN) + +#define NC_SZ_STEPS_MIN 3 +#define NC_SZ_STEPS_DEF 10 +#define NC_SZ_STEPS_MAX 100 + +#define NC_SZ_TIMEOUT_MIN 5 +#define NC_SZ_TIMEOUT_DEF 10 +#define NC_SZ_TIMEOUT_MAX 500 + +#define NC_TIMER_SIZER 1001 +#define NC_TIMER_ENABLEANIMATE 1002 + +#define ENABLEANIMATE_TIMEOUT 400 + +#endif