-/*\r
- * Copyright (c) 2005 Massachusetts Institute of Technology\r
- * Copyright (c) 2007 Secure Endpoints Inc.\r
- *\r
- * Permission is hereby granted, free of charge, to any person\r
- * obtaining a copy of this software and associated documentation\r
- * files (the "Software"), to deal in the Software without\r
- * restriction, including without limitation the rights to use, copy,\r
- * modify, merge, publish, distribute, sublicense, and/or sell copies\r
- * of the Software, and to permit persons to whom the Software is\r
- * furnished to do so, subject to the following conditions:\r
- *\r
- * The above copyright notice and this permission notice shall be\r
- * included in all copies or substantial portions of the Software.\r
- *\r
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
- * SOFTWARE.\r
- */\r
-\r
-/* $Id$ */\r
-\r
-#include<khmapp.h>\r
-#include<intaction.h>\r
-#include<assert.h>\r
-\r
-ATOM khm_main_window_class;\r
-ATOM khm_null_window_class;\r
-HWND khm_hwnd_null;\r
-HWND khm_hwnd_main;\r
-HWND khm_hwnd_rebar;\r
-HWND khm_hwnd_main_cred;\r
-\r
-int khm_main_wnd_mode = KHM_MAIN_WND_NORMAL;\r
-\r
-#define MW_RESIZE_TIMER 1\r
-#define MW_RESIZE_TIMEOUT 2000\r
-#define MW_REFRESH_TIMER 2\r
-#define MW_REFRESH_TIMEOUT 600\r
-\r
-void\r
-khm_set_dialog_result(HWND hwnd, LRESULT lr) {\r
-#pragma warning(push)\r
-#pragma warning(disable: 4244)\r
- SetWindowLongPtr(hwnd, DWLP_MSGRESULT, lr);\r
-#pragma warning(pop)\r
-}\r
-\r
-static void\r
-mw_restart_refresh_timer(HWND hwnd) {\r
- khm_handle csp_cw;\r
- khm_int32 timeout;\r
-\r
- KillTimer(hwnd, MW_REFRESH_TIMER);\r
- if (KHM_SUCCEEDED(khc_open_space(NULL,\r
- L"CredWindow",\r
- KHM_PERM_READ,\r
- &csp_cw))) {\r
- if (KHM_FAILED(khc_read_int32(csp_cw,\r
- L"RefreshTimeout",\r
- &timeout)))\r
- timeout = MW_REFRESH_TIMEOUT;\r
- khc_close_space(csp_cw);\r
- } else {\r
- timeout = MW_REFRESH_TIMEOUT;\r
- }\r
-\r
- timeout *= 1000; /* convert to milliseconds */\r
-\r
- SetTimer(hwnd, MW_REFRESH_TIMER, timeout, NULL);\r
-}\r
-\r
-khm_int32 KHMAPI\r
-mw_select_cred(khm_handle cred, void * rock) {\r
- if (cred)\r
- kcdb_cred_set_flags(cred,\r
- KCDB_CRED_FLAG_SELECTED,\r
- KCDB_CRED_FLAG_SELECTED);\r
-\r
- return KHM_ERROR_SUCCESS;\r
-}\r
-\r
-/* perform shutdown operations */\r
-static void\r
-khm_pre_shutdown(void) {\r
- khm_handle csp_cw = NULL;\r
- khm_handle credset = NULL;\r
- khm_int32 t;\r
- khm_size s;\r
-\r
- khm_taskbar_remove_window(khm_hwnd_main);\r
-\r
- /* Check if we should destroy all credentials on exit... */\r
-\r
- if (KHM_FAILED(khc_open_space(NULL, L"CredWindow", 0, &csp_cw)))\r
- return;\r
-\r
- if (KHM_FAILED(khc_read_int32(csp_cw, L"DestroyCredsOnExit", &t)) ||\r
- !t)\r
- goto _cleanup;\r
-\r
- if (KHM_FAILED(kcdb_credset_create(&credset)))\r
- goto _cleanup;\r
-\r
- if (KHM_FAILED(kcdb_credset_extract(credset, NULL, NULL,\r
- KCDB_TYPE_INVALID)))\r
- goto _cleanup;\r
-\r
- if (KHM_FAILED(kcdb_credset_get_size(credset, &s)) ||\r
- s == 0)\r
- goto _cleanup;\r
-\r
- kcdb_credset_apply(credset, mw_select_cred, NULL);\r
-\r
- khui_context_set(KHUI_SCOPE_GROUP,\r
- NULL,\r
- KCDB_CREDTYPE_INVALID,\r
- NULL,\r
- NULL,\r
- 0,\r
- credset);\r
-\r
- khm_cred_destroy_creds(TRUE, TRUE);\r
-\r
- _cleanup:\r
-\r
- if (credset)\r
- kcdb_credset_delete(credset);\r
-\r
- if (csp_cw)\r
- khc_close_space(csp_cw);\r
-}\r
-\r
-void\r
-khm_process_query_app_ver(khm_query_app_version * papp_ver) {\r
-\r
- if (!papp_ver || papp_ver->magic != KHM_QUERY_APP_VER_MAGIC)\r
- return;\r
-\r
- papp_ver->ver_remote = app_version;\r
-\r
- /* the remote instance has requested swapping in. we check the\r
- version numbers and if the remote instance is newer than us,\r
- then we exit and let the remote instance take over. */\r
- if (papp_ver->request_swap) {\r
- khm_version ver_caller = papp_ver->ver_caller;\r
-\r
- if (ver_caller.major > app_version.major ||\r
-\r
- (ver_caller.major == app_version.major &&\r
- ver_caller.minor > app_version.minor) ||\r
-\r
- (ver_caller.major == app_version.major &&\r
- ver_caller.minor == app_version.minor &&\r
- ver_caller.aux > app_version.aux) ||\r
-\r
- (ver_caller.major == app_version.major &&\r
- ver_caller.minor == app_version.minor &&\r
- ver_caller.aux == app_version.aux &&\r
- ver_caller.patch > app_version.patch)) {\r
-\r
- papp_ver->request_swap = TRUE;\r
-\r
- if (khm_hwnd_main)\r
- DestroyWindow(khm_hwnd_main);\r
-\r
- } else {\r
-\r
- papp_ver->request_swap = FALSE;\r
-\r
- }\r
- }\r
-\r
- papp_ver->code = KHM_ERROR_SUCCESS;\r
-}\r
-\r
-static void\r
-khm_ui_cb(LPARAM lParam) {\r
- khui_ui_callback_data * pcbdata;\r
-\r
- pcbdata = (khui_ui_callback_data *) lParam;\r
-\r
- if (pcbdata == NULL || pcbdata->magic != KHUI_UICBDATA_MAGIC) {\r
-#ifdef DEBUG\r
- assert(FALSE);\r
-#endif\r
- return;\r
- }\r
-\r
-#ifdef DEBUG\r
- assert(pcbdata->cb);\r
-#endif\r
-\r
- /* make the call */\r
- if (!IsBadCodePtr(pcbdata->cb))\r
- pcbdata->rv = (*pcbdata->cb)(khm_hwnd_main, pcbdata->rock);\r
- else {\r
-#ifdef DEBUG\r
- assert(FALSE);\r
-#endif\r
- pcbdata->rv = KHM_ERROR_INVALID_PARAM;\r
- }\r
-}\r
-\r
-LRESULT CALLBACK \r
-khm_main_wnd_proc(HWND hwnd,\r
- UINT uMsg,\r
- WPARAM wParam,\r
- LPARAM lParam) \r
-{\r
- LPNMHDR lpnm;\r
-\r
- switch(uMsg) {\r
- case WM_CREATE:\r
- khm_create_main_window_controls(hwnd);\r
- kmq_subscribe_hwnd(KMSG_CRED, hwnd);\r
- kmq_subscribe_hwnd(KMSG_ACT, hwnd);\r
- kmq_subscribe_hwnd(KMSG_KMM, hwnd);\r
- mw_restart_refresh_timer(hwnd);\r
-\r
- /* if the plug-ins finished loading before the window was\r
- created, we would have missed the KMSG_KMM_I_DONE message.\r
- So we check if the module load is complete and if so, fire\r
- off KMSG_ACT_BEGIN_CMDLINE. */\r
- if (!kmm_load_pending())\r
- kmq_post_message(KMSG_ACT, KMSG_ACT_BEGIN_CMDLINE, 0, 0);\r
- break;\r
-\r
- case WM_DESTROY:\r
- khm_pre_shutdown();\r
- kmq_unsubscribe_hwnd(KMSG_ACT, hwnd);\r
- kmq_unsubscribe_hwnd(KMSG_CRED, hwnd);\r
- kmq_unsubscribe_hwnd(KMSG_KMM, hwnd);\r
- HtmlHelp(NULL, NULL, HH_CLOSE_ALL, 0);\r
- PostQuitMessage(0);\r
- break;\r
-\r
- case WM_NOTIFY:\r
- lpnm = (LPNMHDR) lParam;\r
- if(lpnm->hwndFrom == khui_main_menu_toolbar) {\r
- return khm_menu_notify_main(lpnm);\r
- } else if(lpnm->hwndFrom == khui_hwnd_standard_toolbar) {\r
- return khm_toolbar_notify(lpnm);\r
- } else if(lpnm->hwndFrom == khm_hwnd_rebar) {\r
- return khm_rebar_notify(lpnm);\r
- } else if(lpnm->hwndFrom == khm_hwnd_statusbar) {\r
- return khm_statusbar_notify(lpnm);\r
- }\r
- break;\r
-\r
- case WM_HELP:\r
- khm_html_help(khm_hwnd_main, NULL, HH_HELP_CONTEXT, IDH_WELCOME);\r
- break;\r
-\r
- case WM_COMMAND:\r
- switch(LOWORD(wParam)) {\r
- /* general actions */\r
- case KHUI_ACTION_VIEW_REFRESH:\r
- khm_cred_refresh();\r
- InvalidateRect(khm_hwnd_main_cred, NULL, FALSE);\r
- return 0;\r
-\r
- case KHUI_ACTION_PASSWD_ID:\r
- if (khm_startup.processing)\r
- return 0;\r
-\r
- khm_cred_change_password(NULL);\r
- return 0;\r
-\r
- case KHUI_ACTION_NEW_CRED:\r
- if (khm_startup.processing)\r
- return 0;\r
-\r
- khm_cred_obtain_new_creds(NULL);\r
- return 0;\r
-\r
- case KHUI_ACTION_RENEW_CRED:\r
- if (khm_startup.processing)\r
- return 0;\r
-\r
- khm_cred_renew_creds();\r
- return 0;\r
-\r
- case KHUI_ACTION_DESTROY_CRED:\r
- if (khm_startup.processing)\r
- return 0;\r
-\r
- khm_cred_destroy_creds(FALSE, FALSE);\r
- return 0;\r
-\r
- case KHUI_ACTION_SET_DEF_ID:\r
- if (khm_startup.processing)\r
- return 0;\r
-\r
- khm_cred_set_default();\r
- return 0;\r
-\r
- case KHUI_ACTION_EXIT:\r
- DestroyWindow(hwnd);\r
- return 0;\r
-\r
- case KHUI_ACTION_OPEN_APP:\r
- khm_show_main_window();\r
- return 0;\r
-\r
- case KHUI_ACTION_CLOSE_APP:\r
- khm_hide_main_window();\r
- return 0;\r
-\r
- case KHUI_ACTION_OPT_KHIM: {\r
- khui_config_node node = NULL;\r
-\r
- khui_cfg_open(NULL, L"KhmGeneral", &node);\r
- khm_show_config_pane(node);\r
- }\r
- return 0;\r
-\r
- case KHUI_ACTION_OPT_IDENTS: {\r
- khui_config_node node = NULL;\r
-\r
- khui_cfg_open(NULL, L"KhmIdentities", &node);\r
- khm_show_config_pane(node);\r
- }\r
- return 0;\r
-\r
- case KHUI_ACTION_OPT_APPEAR: {\r
- khui_config_node node = NULL;\r
-\r
- khui_cfg_open(NULL, L"KhmAppear", &node);\r
- khm_show_config_pane(node);\r
- }\r
- return 0;\r
-\r
- case KHUI_ACTION_OPT_NOTIF: {\r
- khui_config_node node = NULL;\r
-\r
- khui_cfg_open(NULL, L"KhmNotifications", &node);\r
- khm_show_config_pane(node);\r
- }\r
- return 0;\r
-\r
- case KHUI_ACTION_OPT_PLUGINS: {\r
- khui_config_node node = NULL;\r
-\r
- khui_cfg_open(NULL, L"KhmPlugins", &node);\r
- khm_show_config_pane(node);\r
- }\r
- return 0;\r
-\r
- case KHUI_ACTION_HELP_CTX:\r
- khm_html_help(khm_hwnd_main, NULL, HH_HELP_CONTEXT, IDH_WELCOME);\r
- return 0;\r
-\r
- case KHUI_ACTION_HELP_CONTENTS:\r
- khm_html_help(khm_hwnd_main, NULL, HH_DISPLAY_TOC, 0);\r
- return 0;\r
-\r
- case KHUI_ACTION_HELP_INDEX:\r
- khm_html_help(khm_hwnd_main, NULL, HH_DISPLAY_INDEX, (DWORD_PTR) L"");\r
- return 0;\r
-\r
- case KHUI_ACTION_HELP_ABOUT:\r
- khm_create_about_window();\r
- return 0;\r
-\r
- case KHUI_ACTION_IMPORT:\r
- khm_cred_import();\r
- return 0;\r
-\r
- case KHUI_ACTION_PROPERTIES:\r
- /* properties are not handled by the main window.\r
- Just bounce it to credwnd. However, use SendMessage\r
- instead of PostMessage so we don't lose context */\r
- return SendMessage(khm_hwnd_main_cred, uMsg, \r
- wParam, lParam);\r
-\r
- case KHUI_ACTION_UICB:\r
- khm_ui_cb(lParam);\r
- return 0;\r
-\r
- /* layout control */\r
- case KHUI_ACTION_LAYOUT_MINI:\r
- if (khm_main_wnd_mode == KHM_MAIN_WND_MINI) {\r
- khm_set_main_window_mode(KHM_MAIN_WND_NORMAL);\r
- } else {\r
- khm_set_main_window_mode(KHM_MAIN_WND_MINI);\r
- }\r
- return SendMessage(khm_hwnd_main_cred, uMsg, \r
- wParam, lParam);\r
-\r
- case KHUI_ACTION_LAYOUT_RELOAD:\r
- return SendMessage(khm_hwnd_main_cred, uMsg, \r
- wParam, lParam);\r
-\r
- case KHUI_ACTION_LAYOUT_ID:\r
- case KHUI_ACTION_LAYOUT_TYPE:\r
- case KHUI_ACTION_LAYOUT_LOC:\r
- case KHUI_ACTION_LAYOUT_CUST:\r
- khm_set_main_window_mode(KHM_MAIN_WND_NORMAL);\r
- return SendMessage(khm_hwnd_main_cred, uMsg, \r
- wParam, lParam);\r
-\r
- /* menu commands */\r
- case KHUI_PACTION_MENU:\r
- if(HIWORD(lParam) == 1)\r
- mm_last_hot_item = LOWORD(lParam);\r
- return khm_menu_activate(MENU_ACTIVATE_DEFAULT);\r
-\r
- case KHUI_PACTION_ESC:\r
- /* if esc is pressed while no menu is active, we close the\r
- main window */\r
- if (mm_last_hot_item == -1) {\r
- khm_close_main_window();\r
- return 0;\r
- }\r
-\r
- /* generic, retargetting */\r
- case KHUI_PACTION_UP:\r
- case KHUI_PACTION_UP_TOGGLE:\r
- case KHUI_PACTION_UP_EXTEND:\r
- case KHUI_PACTION_PGUP:\r
- case KHUI_PACTION_PGUP_EXTEND:\r
- case KHUI_PACTION_DOWN:\r
- case KHUI_PACTION_DOWN_TOGGLE:\r
- case KHUI_PACTION_DOWN_EXTEND:\r
- case KHUI_PACTION_PGDN:\r
- case KHUI_PACTION_PGDN_EXTEND:\r
- case KHUI_PACTION_LEFT:\r
- case KHUI_PACTION_RIGHT:\r
- case KHUI_PACTION_ENTER:\r
- /* menu tracking */\r
- if(mm_last_hot_item != -1) {\r
- switch(LOWORD(wParam)) {\r
- case KHUI_PACTION_LEFT:\r
- khm_menu_activate(MENU_ACTIVATE_LEFT);\r
- break;\r
-\r
- case KHUI_PACTION_RIGHT:\r
- khm_menu_activate(MENU_ACTIVATE_RIGHT);\r
- break;\r
-\r
- case KHUI_PACTION_ESC:\r
- case KHUI_PACTION_ENTER:\r
- khm_menu_activate(MENU_ACTIVATE_NONE);\r
- break;\r
-\r
- case KHUI_PACTION_DOWN:\r
- khm_menu_track_current();\r
- break;\r
- }\r
- return 0;\r
- }\r
-\r
- /*FALLTHROUGH*/\r
- case KHUI_PACTION_DELETE:\r
-\r
- case KHUI_PACTION_SELALL:\r
- /* otherwise fallthrough and bounce to the creds window */\r
- return SendMessage(khm_hwnd_main_cred, uMsg, \r
- wParam, lParam);\r
-\r
- default:\r
- /* handle custom actions here */\r
- {\r
- khui_action * act;\r
-\r
- /* check if this is an identity menu action. (custom\r
- actions that were created for renewing or\r
- destroying specific identities). */\r
- if (khm_check_identity_menu_action(LOWORD(wParam)))\r
- break;\r
-\r
- act = khui_find_action(LOWORD(wParam));\r
- if (act && act->listener) {\r
- kmq_post_sub_msg(act->listener, KMSG_ACT, KMSG_ACT_ACTIVATE, act->cmd, NULL);\r
- return 0;\r
- }\r
- }\r
- }\r
- break; /* WM_COMMAND */\r
-\r
- case WM_SYSCOMMAND:\r
- switch(wParam & 0xfff0) {\r
- case SC_MINIMIZE:\r
- khm_hide_main_window();\r
- return 0;\r
-\r
- case SC_CLOSE:\r
- khm_close_main_window();\r
- return 0;\r
- }\r
- break;\r
-\r
- case WM_MEASUREITEM:\r
- /* sent to measure the bitmaps associated with a menu item */\r
- if(!wParam) /* sent by menu */\r
- return khm_menu_measure_item(wParam, lParam);\r
- break;\r
-\r
- case WM_DRAWITEM:\r
- /* sent to draw a menu item */\r
- if(!wParam) \r
- return khm_menu_draw_item(wParam, lParam);\r
- break;\r
-\r
- case WM_ERASEBKGND:\r
- /* Don't erase the background. The whole client area is\r
- covered with children. It doesn't need to be erased */\r
- return TRUE;\r
- break;\r
-\r
- case WM_SIZE: \r
- if(hwnd == khm_hwnd_main && \r
- (wParam == SIZE_MAXIMIZED || wParam == SIZE_RESTORED)) {\r
- int cwidth, cheight;\r
- RECT r_rebar, r_status;\r
-\r
- cwidth = LOWORD(lParam);\r
- cheight = HIWORD(lParam);\r
-\r
- /* resize the rebar control */\r
- SendMessage(khm_hwnd_rebar, WM_SIZE, 0, 0);\r
-\r
- khm_update_statusbar(hwnd);\r
- \r
- GetWindowRect(khm_hwnd_rebar, &r_rebar);\r
- GetWindowRect(khm_hwnd_statusbar, &r_status);\r
-\r
- /* the cred window fills the area between the rebar\r
- and the status bar */\r
- MoveWindow(khm_hwnd_main_cred, 0, \r
- r_rebar.bottom - r_rebar.top, \r
- r_status.right - r_status.left, \r
- r_status.top - r_rebar.bottom, TRUE);\r
-\r
- SetTimer(hwnd,\r
- MW_RESIZE_TIMER,\r
- MW_RESIZE_TIMEOUT,\r
- NULL);\r
- return 0;\r
- }\r
- break;\r
-\r
- case WM_MOVE:\r
- {\r
- SetTimer(hwnd,\r
- MW_RESIZE_TIMER,\r
- MW_RESIZE_TIMEOUT,\r
- NULL);\r
-\r
- return 0;\r
- }\r
- break;\r
-\r
- case WM_MOVING:\r
- {\r
- RECT * r;\r
-\r
- r = (RECT *) lParam;\r
- khm_adjust_window_dimensions_for_display(r,\r
- KHM_DOCK_AUTO | KHM_DOCKF_XBORDER);\r
- }\r
- return TRUE;\r
-\r
- case WM_TIMER:\r
- if (wParam == MW_RESIZE_TIMER) {\r
- RECT r;\r
- khm_handle csp_cw;\r
- khm_handle csp_mw;\r
- const wchar_t * wconfig;\r
-\r
- if (khm_main_wnd_mode == KHM_MAIN_WND_MINI)\r
- wconfig = L"Windows\\MainMini";\r
- else\r
- wconfig = L"Windows\\Main";\r
-\r
- KillTimer(hwnd, wParam);\r
-\r
- GetWindowRect(hwnd, &r);\r
-\r
- if (KHM_SUCCEEDED(khc_open_space(NULL,\r
- L"CredWindow",\r
- KHM_PERM_WRITE,\r
- &csp_cw))) {\r
- if (KHM_SUCCEEDED(khc_open_space(csp_cw,\r
- wconfig,\r
- KHM_PERM_WRITE,\r
- &csp_mw))) {\r
- khm_int32 t;\r
-\r
- khc_write_int32(csp_mw, L"XPos", r.left);\r
- khc_write_int32(csp_mw, L"YPos", r.top);\r
- khc_write_int32(csp_mw, L"Width",\r
- r.right - r.left);\r
- khc_write_int32(csp_mw, L"Height",\r
- r.bottom - r.top);\r
-\r
- if (KHM_SUCCEEDED(khc_read_int32(csp_mw, L"Dock", &t)) &&\r
- t != KHM_DOCK_NONE) {\r
- khc_write_int32(csp_mw, L"Dock", KHM_DOCK_AUTO);\r
- }\r
-\r
- khc_close_space(csp_mw);\r
- }\r
- khc_close_space(csp_cw);\r
- }\r
-\r
- return 0;\r
-\r
- } else if (wParam == MW_REFRESH_TIMER) {\r
- kmq_post_message(KMSG_CRED, KMSG_CRED_REFRESH, 0, 0);\r
-\r
- return 0;\r
-\r
- }\r
- break;\r
-\r
- case WM_MENUSELECT:\r
- return khm_menu_handle_select(wParam, lParam);\r
-\r
- case KMQ_WM_DISPATCH:\r
- {\r
- kmq_message * m;\r
- khm_int32 rv = KHM_ERROR_SUCCESS;\r
-\r
- kmq_wm_begin(lParam, &m);\r
- if (m->type == KMSG_ACT &&\r
- m->subtype == KMSG_ACT_REFRESH) {\r
- khm_menu_refresh_items();\r
- khm_update_standard_toolbar();\r
- } else if (m->type == KMSG_ACT &&\r
- m->subtype == KMSG_ACT_BEGIN_CMDLINE) {\r
- khm_cred_begin_startup_actions();\r
- } else if (m->type == KMSG_ACT &&\r
- m->subtype == KMSG_ACT_CONTINUE_CMDLINE) {\r
- khm_cred_process_startup_actions();\r
- } else if (m->type == KMSG_ACT &&\r
- m->subtype == KMSG_ACT_END_CMDLINE) {\r
- /* nothing yet */\r
- } else if (m->type == KMSG_ACT &&\r
- m->subtype == KMSG_ACT_SYNC_CFG) {\r
- khm_refresh_config();\r
- } else if (m->type == KMSG_ACT &&\r
- m->subtype == KMSG_ACT_ACTIVATE) {\r
- /* some custom action fired */\r
-\r
- khm_int32 action;\r
- khui_action * paction;\r
-\r
- action = m->uparam;\r
- paction = khui_find_action(action);\r
- if (paction && paction->data == (void *) CFGACTION_MAGIC) {\r
- /* a custom configuration needs to be invoked */\r
- khui_config_node node;\r
-\r
- if (KHM_SUCCEEDED(khui_cfg_open(NULL, paction->name, &node))) {\r
- khm_show_config_pane(node);\r
- khui_cfg_release(node);\r
- }\r
- }\r
- } else if (m->type == KMSG_CRED &&\r
- m->subtype == KMSG_CRED_REFRESH) {\r
- mw_restart_refresh_timer(hwnd);\r
- } else if (m->type == KMSG_CRED &&\r
- m->subtype == KMSG_CRED_ADDR_CHANGE) {\r
- khm_cred_addr_change();\r
- } else if (m->type == KMSG_CRED &&\r
- m->subtype == KMSG_CRED_ROOTDELTA) {\r
- khm_refresh_identity_menus();\r
- } else if (m->type == KMSG_KMM &&\r
- m->subtype == KMSG_KMM_I_DONE) {\r
- kmq_post_message(KMSG_ACT, KMSG_ACT_BEGIN_CMDLINE, 0, 0);\r
- }\r
-\r
- return kmq_wm_end(m, rv);\r
- }\r
- return 0;\r
-\r
- case WM_KHUI_ASSIGN_COMMANDLINE_V1:\r
- {\r
- HANDLE hmap;\r
- void * xfer;\r
- wchar_t mapname[256];\r
- struct tag_khm_startup_options_v1 * pv1opt;\r
- int code = KHM_ERROR_SUCCESS;\r
-\r
- StringCbPrintf(mapname, sizeof(mapname),\r
- COMMANDLINE_MAP_FMT, (DWORD) lParam);\r
-\r
- hmap = OpenFileMapping(FILE_MAP_READ, FALSE, mapname);\r
-\r
- if (hmap == NULL)\r
- return 1;\r
-\r
- xfer = MapViewOfFile(hmap, FILE_MAP_READ, 0, 0,\r
- sizeof(*pv1opt));\r
-\r
- if (xfer) {\r
- pv1opt = (struct tag_khm_startup_options_v1 *) xfer;\r
-\r
- khm_startup.init = pv1opt->init;\r
- khm_startup.import = pv1opt->import;\r
- khm_startup.renew = pv1opt->renew;\r
- khm_startup.destroy = pv1opt->destroy;\r
-\r
- khm_startup.autoinit = pv1opt->autoinit;\r
- khm_startup.error_exit = FALSE;\r
-\r
- khm_startup.no_main_window = FALSE;\r
- khm_startup.remote_exit = FALSE;\r
-\r
- UnmapViewOfFile(xfer);\r
- } else {\r
- code = KHM_ERROR_NOT_FOUND;\r
- }\r
-\r
- CloseHandle(hmap);\r
-\r
- if(InSendMessage())\r
- ReplyMessage(code);\r
-\r
- if (code == KHM_ERROR_SUCCESS) {\r
- khm_startup.exit = FALSE;\r
-\r
- khm_startup.seen = FALSE;\r
- khm_startup.remote = TRUE;\r
-#ifdef DEBUG\r
- assert(!khm_startup.processing);\r
-#endif\r
- khm_startup.processing = FALSE;\r
-\r
- khm_cred_begin_startup_actions();\r
- }\r
-\r
- return code;\r
- }\r
-\r
- case WM_KHUI_ASSIGN_COMMANDLINE_V2:\r
- {\r
- HANDLE hmap;\r
- void * xfer;\r
- wchar_t mapname[256];\r
- struct tag_khm_startup_options_v2 *pv2opt;\r
- int code = KHM_ERROR_SUCCESS;\r
-\r
- StringCbPrintf(mapname, sizeof(mapname),\r
- COMMANDLINE_MAP_FMT, (DWORD) lParam);\r
-\r
- hmap = OpenFileMapping(FILE_MAP_WRITE, FALSE, mapname);\r
-\r
- if (hmap == NULL)\r
- return 1;\r
-\r
- xfer = MapViewOfFile(hmap, FILE_MAP_WRITE, 0, 0,\r
- sizeof(*pv2opt));\r
-\r
- if (xfer) {\r
- pv2opt = (struct tag_khm_startup_options_v2 *) xfer;\r
-\r
- if (pv2opt->magic != STARTUP_OPTIONS_MAGIC ||\r
- pv2opt->cb_size != sizeof(*pv2opt)) {\r
- code = KHM_ERROR_INVALID_PARAM;\r
- goto done_with_v2_opt;\r
- }\r
-\r
- khm_startup.init = pv2opt->init;\r
- khm_startup.import = pv2opt->import;\r
- khm_startup.renew = pv2opt->renew;\r
- khm_startup.destroy = pv2opt->destroy;\r
-\r
- khm_startup.autoinit = pv2opt->autoinit;\r
- khm_startup.exit = pv2opt->remote_exit;\r
-\r
- pv2opt->code = KHM_ERROR_SUCCESS;\r
-\r
- done_with_v2_opt:\r
- UnmapViewOfFile(xfer);\r
- } else {\r
- code = KHM_ERROR_NOT_FOUND;\r
- }\r
-\r
- CloseHandle(hmap);\r
-\r
- if(InSendMessage())\r
- ReplyMessage(code);\r
-\r
- if (code == KHM_ERROR_SUCCESS) {\r
- khm_startup.seen = FALSE;\r
- khm_startup.remote = TRUE;\r
-#ifdef DEBUG\r
- assert(!khm_startup.processing);\r
-#endif\r
- khm_startup.processing = FALSE;\r
-\r
- khm_cred_begin_startup_actions();\r
- }\r
-\r
- return code;\r
- }\r
-\r
- case WM_KHUI_QUERY_APP_VERSION:\r
- {\r
- HANDLE hmap;\r
- void * xfer;\r
- wchar_t mapname[256];\r
-\r
- StringCbPrintf(mapname, sizeof(mapname),\r
- QUERY_APP_VER_MAP_FMT, (DWORD) lParam);\r
-\r
- hmap = OpenFileMapping(FILE_MAP_READ | FILE_MAP_WRITE,\r
- FALSE, mapname);\r
-\r
- if (hmap == NULL)\r
- return 1;\r
-\r
- xfer = MapViewOfFile(hmap, FILE_MAP_WRITE, 0, 0,\r
- sizeof(khm_query_app_version));\r
- \r
- if (xfer) {\r
- khm_process_query_app_ver((khm_query_app_version *) xfer);\r
-\r
- UnmapViewOfFile(xfer);\r
- }\r
-\r
- CloseHandle(hmap);\r
- }\r
- return 0;\r
-\r
- }\r
- return DefWindowProc(hwnd,uMsg,wParam,lParam);\r
-}\r
-\r
-LRESULT CALLBACK \r
-khm_null_wnd_proc(HWND hwnd,\r
- UINT uMsg,\r
- WPARAM wParam,\r
- LPARAM lParam) {\r
- return DefWindowProc(hwnd, uMsg, wParam, lParam);\r
-}\r
-\r
-LRESULT \r
-khm_rebar_notify(LPNMHDR lpnm) {\r
- switch(lpnm->code) {\r
-#if (_WIN32_WINNT >= 0x0501)\r
- case RBN_AUTOBREAK:\r
- {\r
- LPNMREBARAUTOBREAK lpra = (LPNMREBARAUTOBREAK) lpnm;\r
- lpra->fAutoBreak = TRUE;\r
- }\r
- break;\r
-#endif\r
- case RBN_BEGINDRAG:\r
- {\r
- LPNMREBAR lprb = (LPNMREBAR) lpnm;\r
- if ((lprb->dwMask & RBNM_ID) &&\r
- lprb->wID == 0)\r
- return 1;\r
- else\r
- return 0;\r
- }\r
- break;\r
-\r
- case NM_CUSTOMDRAW:\r
- return CDRF_DODEFAULT;\r
- break;\r
- }\r
-\r
- return 1;\r
-}\r
-\r
-void \r
-khm_create_main_window_controls(HWND hwnd_main) {\r
- REBARINFO rbi;\r
- HWND hwRebar;\r
-\r
- khm_menu_create_main(hwnd_main);\r
-\r
- hwRebar = \r
- CreateWindowEx(WS_EX_TOOLWINDOW,\r
- REBARCLASSNAME,\r
- L"Rebar",\r
- WS_CHILD | \r
- WS_VISIBLE| \r
- WS_CLIPSIBLINGS | \r
- WS_CLIPCHILDREN |\r
- CCS_NODIVIDER |\r
- RBS_VARHEIGHT |\r
- RBS_FIXEDORDER,\r
- 0,0,0,0,\r
- hwnd_main,\r
- NULL,\r
- khm_hInstance,\r
- NULL);\r
-\r
- if(!hwRebar) {\r
- DWORD dwe = GetLastError();\r
- return;\r
- }\r
-\r
- khm_hwnd_rebar = hwRebar;\r
-\r
- rbi.cbSize = sizeof(rbi);\r
- rbi.fMask = 0;\r
- rbi.himl = (HIMAGELIST) NULL;\r
- if(!SendMessage(hwRebar, RB_SETBARINFO, 0, (LPARAM) &rbi))\r
- return;\r
-\r
- /* self attach */\r
- khm_create_standard_toolbar(hwRebar);\r
- khm_create_statusbar(hwnd_main);\r
-\r
- /* manual attach */\r
- khm_hwnd_main_cred = khm_create_credwnd(hwnd_main);\r
-}\r
-\r
-void\r
-khm_adjust_window_dimensions_for_display(RECT * pr, int dock) {\r
-\r
- HMONITOR hmon;\r
- RECT rm;\r
- long x, y, width, height;\r
-\r
- x = pr->left;\r
- y = pr->top;\r
- width = pr->right - pr->left;\r
- height = pr->bottom - pr->top;\r
-\r
- /* if the rect doesn't intersect with the display area of any\r
- monitor, we just default to the primary monitor. */\r
- hmon = MonitorFromRect(pr, MONITOR_DEFAULTTOPRIMARY);\r
-\r
- if (hmon == NULL) {\r
- /* huh? we'll just center this on the primary screen */\r
- goto nomonitor;\r
- } else {\r
- MONITORINFO mi;\r
-\r
- ZeroMemory(&mi, sizeof(mi));\r
- mi.cbSize = sizeof(mi);\r
-\r
- if (!GetMonitorInfo(hmon, &mi))\r
- goto nomonitor;\r
-\r
- CopyRect(&rm, &mi.rcWork);\r
-\r
- goto adjust_dims;\r
- }\r
-\r
- nomonitor:\r
- /* for some reason we couldn't get a handle on a monitor or we\r
- couldn't get the metrics for that monitor. We default to\r
- setting things up on the primary monitor. */\r
-\r
- SetRectEmpty(&rm);\r
- if (!SystemParametersInfo(SPI_GETWORKAREA, 0, (PVOID) &rm, 0))\r
- goto done_with_monitor;\r
-\r
- adjust_dims:\r
-\r
- if (width > (rm.right - rm.left))\r
- width = rm.right - rm.left;\r
- if (height > (rm.bottom - rm.top))\r
- height = rm.bottom - rm.top;\r
-\r
- switch (dock & KHM_DOCKF_DOCKHINT) {\r
- case KHM_DOCK_TOPLEFT:\r
- x = rm.left;\r
- y = rm.top;\r
- break;\r
-\r
- case KHM_DOCK_TOPRIGHT:\r
- x = rm.right - width;\r
- y = rm.top;\r
- break;\r
-\r
- case KHM_DOCK_BOTTOMRIGHT:\r
- x = rm.right - width;\r
- y = rm.bottom - height;\r
- break;\r
-\r
- case KHM_DOCK_BOTTOMLEFT:\r
- x = rm.left;\r
- y = rm.bottom - height;\r
- break;\r
-\r
- case KHM_DOCK_AUTO:\r
- {\r
- int cxt, cyt;\r
-\r
- cxt = GetSystemMetrics(SM_CXDRAG);\r
- cyt = GetSystemMetrics(SM_CYDRAG);\r
-\r
- if (x > rm.left && (x - rm.left) < cxt)\r
- x = rm.left;\r
- else if ((x + width) < rm.right && (rm.right - (x + width)) < cxt)\r
- x = rm.right - width;\r
-\r
- if (y > rm.top && (y - rm.top) < cyt)\r
- y = rm.top;\r
- else if ((y + height) < rm.bottom && (rm.bottom - (y + height)) < cyt)\r
- y = rm.bottom - height;\r
- }\r
- break;\r
- }\r
-\r
- if (!(dock & KHM_DOCKF_XBORDER)) {\r
- if (x < rm.left)\r
- x = rm.left;\r
- if (x + width > rm.right)\r
- x = rm.right - width;\r
- if (y < rm.top)\r
- y = rm.top;\r
- if (y + height > rm.bottom)\r
- y = rm.bottom - height;\r
- }\r
-\r
- done_with_monitor:\r
- pr->left = x;\r
- pr->top = y;\r
- pr->right = x + width;\r
- pr->bottom = y + height;\r
-\r
-}\r
-\r
-void\r
-khm_get_main_window_rect(RECT * pr) {\r
- khm_handle csp_mw = NULL;\r
- int x,y,width,height,dock;\r
- RECT r;\r
- const wchar_t * wconfig;\r
-\r
- x = CW_USEDEFAULT;\r
- y = CW_USEDEFAULT;\r
- width = CW_USEDEFAULT;\r
- height = CW_USEDEFAULT;\r
- dock = KHM_DOCK_NONE;\r
-\r
- if (khm_main_wnd_mode == KHM_MAIN_WND_MINI)\r
- wconfig = L"CredWindow\\Windows\\MainMini";\r
- else\r
- wconfig = L"CredWindow\\Windows\\Main";\r
-\r
- if (KHM_SUCCEEDED(khc_open_space(NULL,\r
- wconfig,\r
- KHM_PERM_READ,\r
- &csp_mw))) {\r
- khm_int32 t;\r
-\r
- if (KHM_SUCCEEDED(khc_read_int32(csp_mw, L"XPos", &t)))\r
- x = t;\r
- if (KHM_SUCCEEDED(khc_read_int32(csp_mw, L"YPos", &t)))\r
- y = t;\r
- if (KHM_SUCCEEDED(khc_read_int32(csp_mw, L"Width", &t)))\r
- width = t;\r
- if (KHM_SUCCEEDED(khc_read_int32(csp_mw, L"Height", &t)))\r
- height = t;\r
- if (KHM_SUCCEEDED(khc_read_int32(csp_mw, L"Dock", &t)))\r
- dock = t;\r
-\r
- khc_close_space(csp_mw);\r
- }\r
-\r
- /* If there were no default values, we default to using 1/4 of the\r
- work area centered on the primary monitor. If there were any\r
- docking hints, then the next call to\r
- khm_adjust_window_dimensions_for_display() will reposition the\r
- window. */\r
- if (width == CW_USEDEFAULT || x == CW_USEDEFAULT) {\r
- RECT wr;\r
-\r
- SetRectEmpty(&wr);\r
- SystemParametersInfo(SPI_GETWORKAREA, 0, &wr, 0);\r
-\r
- if (width == CW_USEDEFAULT) {\r
- width = (wr.right - wr.left) / 2;\r
- height = (wr.bottom - wr.top) / 2;\r
- }\r
-\r
- if (x == CW_USEDEFAULT) {\r
- x = (wr.left + wr.right) / 2 - width / 2;\r
- y = (wr.top + wr.bottom) / 2 - height / 2;\r
- }\r
- }\r
-\r
- /* The saved dimensions might not actually be visible if the user\r
- has changed the resolution of the display or if it's a multiple\r
- monitor system where the monitor on which the Network Identity\r
- Manager window was on previously is no longer connected. We\r
- have to check for that and adjust the dimensions if needed. */\r
- SetRect(&r, x, y, x + width, y + height);\r
- khm_adjust_window_dimensions_for_display(&r, dock);\r
-\r
- *pr = r;\r
-}\r
-\r
-void\r
-khm_set_main_window_mode(int mode) {\r
-\r
- RECT r;\r
- khm_handle csp_cw;\r
-\r
- if (mode == khm_main_wnd_mode)\r
- return;\r
-\r
- khui_check_action(KHUI_ACTION_LAYOUT_MINI,\r
- ((mode == KHM_MAIN_WND_MINI)? FALSE : TRUE));\r
- khui_enable_action(KHUI_MENU_LAYOUT,\r
- ((mode == KHM_MAIN_WND_MINI)? FALSE : TRUE));\r
- khui_enable_action(KHUI_MENU_COLUMNS,\r
- ((mode == KHM_MAIN_WND_MINI)? FALSE : TRUE));\r
-\r
- khui_refresh_actions();\r
-\r
- khm_main_wnd_mode = mode;\r
- if (khm_hwnd_main) {\r
- khm_get_main_window_rect(&r);\r
-\r
- SetWindowPos(khm_hwnd_main,\r
- NULL,\r
- r.left, r.top,\r
- r.right - r.left, r.bottom - r.top,\r
- SWP_NOACTIVATE | SWP_NOOWNERZORDER |\r
- SWP_NOZORDER);\r
- }\r
-\r
- if (KHM_SUCCEEDED(khc_open_space(NULL, L"CredWindow", KHM_PERM_WRITE,\r
- &csp_cw))) {\r
-\r
- khc_write_int32(csp_cw, L"DefaultWindowMode", mode);\r
- khc_close_space(csp_cw);\r
-\r
- }\r
-\r
- khm_cred_refresh();\r
-}\r
-\r
-void \r
-khm_create_main_window(void) {\r
- wchar_t buf[1024];\r
- khm_handle csp_cw = NULL;\r
- RECT r;\r
-\r
- LoadString(khm_hInstance, IDS_MAIN_WINDOW_TITLE, \r
- buf, ARRAYLENGTH(buf));\r
-\r
- khm_hwnd_null =\r
- CreateWindow(MAKEINTATOM(khm_null_window_class),\r
- buf,\r
- 0, /* Style */\r
- 0, 0, /* x, y */\r
- 100, 100, /* width, height */\r
- NULL, /* parent */\r
- NULL, /* menu */\r
- NULL, /* HINSTANCE */\r
- 0); /* lparam */\r
-\r
- if (!khm_hwnd_null)\r
- return;\r
-\r
- if (KHM_SUCCEEDED(khc_open_space(NULL, L"CredWindow",\r
- KHM_PERM_READ,\r
- &csp_cw))) {\r
- khm_int32 t;\r
-\r
- if (KHM_SUCCEEDED(khc_read_int32(csp_cw, L"DefaultWindowMode", &t))) {\r
- khm_set_main_window_mode(t);\r
- }\r
-\r
- khc_close_space(csp_cw);\r
- }\r
-\r
- khm_get_main_window_rect(&r);\r
-\r
- khm_hwnd_main = \r
- CreateWindowEx(WS_EX_OVERLAPPEDWINDOW,\r
- MAKEINTATOM(khm_main_window_class),\r
- buf,\r
- WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | \r
- WS_CLIPSIBLINGS,\r
- r.left, r.top,\r
- r.right - r.left,\r
- r.bottom - r.top,\r
- khm_hwnd_null,\r
- NULL,\r
- NULL,\r
- NULL);\r
-\r
- khui_set_main_window(khm_hwnd_main);\r
-}\r
-\r
-void \r
-khm_show_main_window(void) {\r
-\r
- if (khm_nCmdShow == SW_RESTORE) {\r
- HWND hw;\r
-\r
- hw = GetForegroundWindow();\r
- if (hw != khm_hwnd_main)\r
- SetForegroundWindow(khm_hwnd_main);\r
- }\r
-\r
- if (khm_nCmdShow == SW_SHOWMINIMIZED ||\r
- khm_nCmdShow == SW_SHOWMINNOACTIVE ||\r
- khm_nCmdShow == SW_MINIMIZE) {\r
- khm_hide_main_window();\r
- } else {\r
- ShowWindow(khm_hwnd_main, khm_nCmdShow);\r
- UpdateWindow(khm_hwnd_main);\r
-\r
- khm_taskbar_add_window(khm_hwnd_main);\r
-\r
- khm_cred_refresh();\r
- }\r
-\r
- khm_nCmdShow = SW_RESTORE;\r
-}\r
-\r
-void\r
-khm_activate_main_window(void) {\r
-\r
- if (!SetForegroundWindow(khm_hwnd_main)) {\r
- FLASHWINFO finfo;\r
-\r
- SetActiveWindow(khm_hwnd_main);\r
-\r
- ZeroMemory(&finfo, sizeof(finfo));\r
- finfo.cbSize = sizeof(finfo);\r
- finfo.hwnd = khm_hwnd_main;\r
- finfo.dwFlags = FLASHW_ALL;\r
- finfo.uCount = 3;\r
- finfo.dwTimeout = 0;\r
-\r
- FlashWindowEx(&finfo);\r
- }\r
-}\r
-\r
-void \r
-khm_close_main_window(void) {\r
- khm_handle csp_cw;\r
- BOOL keep_running = FALSE;\r
-\r
- if (KHM_SUCCEEDED(khc_open_space(NULL, L"CredWindow",\r
- KHM_PERM_READ, &csp_cw))) {\r
- khm_int32 t;\r
-\r
- if (KHM_SUCCEEDED(khc_read_int32(csp_cw, L"KeepRunning", \r
- &t))) {\r
- keep_running = t;\r
- } else {\r
-#ifdef DEBUG\r
- assert(FALSE);\r
-#endif\r
- }\r
-\r
- khc_close_space(csp_cw);\r
- } else {\r
-#ifdef DEBUG\r
- assert(FALSE);\r
-#endif\r
- }\r
-\r
- if (keep_running)\r
- khm_hide_main_window();\r
- else\r
- DestroyWindow(khm_hwnd_main);\r
-}\r
-\r
-void \r
-khm_hide_main_window(void) {\r
- khm_handle csp_notices = NULL;\r
- khm_int32 show_warning = FALSE;\r
-\r
- if (khm_nCmdShow != SW_MINIMIZE &&\r
- KHM_SUCCEEDED(khc_open_space(NULL, L"CredWindow\\Notices",\r
- KHM_PERM_WRITE, &csp_notices)) &&\r
- KHM_SUCCEEDED(khc_read_int32(csp_notices, L"MinimizeWarning",\r
- &show_warning)) &&\r
- show_warning != 0) {\r
-\r
- khui_alert * alert;\r
- wchar_t title[KHUI_MAXCCH_TITLE];\r
- wchar_t msg[KHUI_MAXCCH_MESSAGE];\r
-\r
- LoadString(khm_hInstance, IDS_WARN_WM_TITLE,\r
- title, ARRAYLENGTH(title));\r
- LoadString(khm_hInstance, IDS_WARN_WM_MSG,\r
- msg, ARRAYLENGTH(msg));\r
-\r
- khui_alert_create_simple(title, msg, KHERR_INFO, &alert);\r
- khui_alert_set_flags(alert, KHUI_ALERT_FLAG_REQUEST_BALLOON,\r
- KHUI_ALERT_FLAG_REQUEST_BALLOON);\r
-\r
- khui_alert_show(alert);\r
-\r
- khc_write_int32(csp_notices, L"MinimizeWarning", 0);\r
- }\r
-\r
- if (csp_notices != NULL)\r
- khc_close_space(csp_notices);\r
-\r
- ShowWindow(khm_hwnd_main, SW_HIDE);\r
-\r
- khm_taskbar_remove_window(khm_hwnd_main);\r
-}\r
-\r
-BOOL \r
-khm_is_main_window_visible(void) {\r
- return IsWindowVisible(khm_hwnd_main);\r
-}\r
-\r
-BOOL \r
-khm_is_main_window_active(void) {\r
- if (!IsWindowVisible(khm_hwnd_main))\r
- return FALSE;\r
- if (GetForegroundWindow() == khm_hwnd_main)\r
- return TRUE;\r
- return khm_is_dialog_active();\r
-}\r
-\r
-void \r
-khm_register_main_wnd_class(void) {\r
- WNDCLASSEX wc;\r
-\r
- wc.cbSize = sizeof(WNDCLASSEX);\r
- wc.style = 0;\r
- wc.lpfnWndProc = khm_null_wnd_proc;\r
- wc.cbClsExtra = 0;\r
- wc.cbWndExtra = 0;\r
- wc.hInstance = khm_hInstance;\r
- wc.hIcon = LoadIcon(khm_hInstance, MAKEINTRESOURCE(IDI_MAIN_APP));\r
- wc.hCursor = LoadCursor((HINSTANCE) NULL, MAKEINTRESOURCE(IDC_ARROW));\r
- wc.hIconSm = LoadImage(khm_hInstance, MAKEINTRESOURCE(IDI_MAIN_APP), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE);\r
- wc.hbrBackground = (HBRUSH) (COLOR_APPWORKSPACE);\r
- wc.lpszMenuName = NULL;\r
- wc.lpszClassName = KHUI_NULL_WINDOW_CLASS;\r
-\r
- khm_null_window_class = RegisterClassEx(&wc);\r
-\r
- wc.cbSize = sizeof(WNDCLASSEX);\r
- wc.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;\r
- wc.lpfnWndProc = khm_main_wnd_proc;\r
- wc.cbClsExtra = 0;\r
- wc.cbWndExtra = 0;\r
- wc.hInstance = khm_hInstance;\r
- wc.hIcon = LoadIcon(khm_hInstance, MAKEINTRESOURCE(IDI_MAIN_APP));\r
- wc.hCursor = LoadCursor((HINSTANCE) NULL, MAKEINTRESOURCE(IDC_ARROW));\r
- wc.hIconSm = LoadImage(khm_hInstance, MAKEINTRESOURCE(IDI_MAIN_APP), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE);\r
- wc.hbrBackground = (HBRUSH) (COLOR_APPWORKSPACE);\r
- wc.lpszMenuName = NULL;\r
- wc.lpszClassName = KHUI_MAIN_WINDOW_CLASS;\r
-\r
- khm_main_window_class = RegisterClassEx(&wc);\r
-}\r
-\r
-void \r
-khm_unregister_main_wnd_class(void) {\r
- UnregisterClass(MAKEINTATOM(khm_main_window_class),khm_hInstance);\r
- UnregisterClass(MAKEINTATOM(khm_null_window_class),khm_hInstance);\r
-}\r
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ * Copyright (c) 2007 Secure Endpoints Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<khmapp.h>
+#include<intaction.h>
+#include<assert.h>
+
+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);
+}
-/*\r
- * Copyright (c) 2005 Massachusetts Institute of Technology\r
- * Copyright (c) 2007 Secure Endpoints Inc.\r
- *\r
- * Permission is hereby granted, free of charge, to any person\r
- * obtaining a copy of this software and associated documentation\r
- * files (the "Software"), to deal in the Software without\r
- * restriction, including without limitation the rights to use, copy,\r
- * modify, merge, publish, distribute, sublicense, and/or sell copies\r
- * of the Software, and to permit persons to whom the Software is\r
- * furnished to do so, subject to the following conditions:\r
- *\r
- * The above copyright notice and this permission notice shall be\r
- * included in all copies or substantial portions of the Software.\r
- *\r
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
- * SOFTWARE.\r
- */\r
-\r
-/* $Id$ */\r
-\r
-/* Include the OEMRESOURCE constants for locating standard icon\r
- resources. */\r
-#define OEMRESOURCE\r
-\r
-#include<khmapp.h>\r
-#include<assert.h>\r
-\r
-ATOM khui_newcredwnd_cls;\r
-\r
-/* forward dcl */\r
-static void\r
-nc_position_credtext(khui_nc_wnd_data * d);\r
-\r
-/* Common dialog procedure used by the main credential panel\r
- (IDD_NC_NEWCRED) and the button bar (IDC_NC_BBAR). */\r
-\r
-static void\r
-nc_layout_main_panel(khui_nc_wnd_data * d);\r
-\r
-static void\r
-nc_layout_new_cred_window(khui_nc_wnd_data * d);\r
-\r
-static INT_PTR CALLBACK \r
-nc_common_dlg_proc(HWND hwnd,\r
- UINT uMsg,\r
- WPARAM wParam,\r
- LPARAM lParam)\r
-{\r
- switch(uMsg) {\r
- case WM_INITDIALOG:\r
- {\r
- khui_nc_wnd_data * d;\r
-\r
- d = (khui_nc_wnd_data *) lParam;\r
-\r
-#pragma warning(push)\r
-#pragma warning(disable: 4244)\r
- SetWindowLongPtr(hwnd, DWLP_USER, lParam);\r
-#pragma warning(pop)\r
-\r
- if (d->nc->subtype == KMSG_CRED_PASSWORD) {\r
- ShowWindow(GetDlgItem(hwnd, IDC_NC_ADVANCED),\r
- SW_HIDE);\r
- }\r
- }\r
- return TRUE;\r
-\r
- case WM_COMMAND:\r
- {\r
- int ctrl_id;\r
-\r
- ctrl_id = LOWORD(wParam);\r
- if (ctrl_id < KHUI_CW_ID_MIN ||\r
- ctrl_id > KHUI_CW_ID_MAX) {\r
- /* pump it to the parent */\r
- PostMessage(GetParent(hwnd), WM_COMMAND, wParam, lParam);\r
- return TRUE;\r
- } /* else we allow the message to fall through and get\r
- passed into the identity provider's message\r
- handler. */\r
- }\r
- break;\r
-\r
- case KHUI_WM_NC_NOTIFY:\r
- {\r
- khui_nc_wnd_data * d;\r
- d = (khui_nc_wnd_data *)(LONG_PTR) \r
- GetWindowLongPtr(hwnd, DWLP_USER);\r
-\r
- /* message sent by parent to notify us of something */\r
- switch(HIWORD(wParam)) {\r
- case WMNC_DIALOG_EXPAND:\r
- /* fallthrough */\r
- case WMNC_UPDATE_LAYOUT:\r
- if(hwnd == d->dlg_main) {\r
-\r
- nc_layout_main_panel(d);\r
-\r
- return TRUE;\r
- }\r
- break; /* nop */\r
- }\r
- }\r
- return TRUE;\r
- }\r
-\r
- /* check if we have a wnd_data, and if so pass the message on to\r
- the identity provider callback. */\r
- {\r
- khui_nc_wnd_data * d;\r
-\r
- d = (khui_nc_wnd_data *) (LONG_PTR)\r
- GetWindowLongPtr(hwnd, DWLP_USER);\r
-\r
- /* TODO: filter out and forward only the messages that\r
- originated or pertain to the identity selection\r
- controls. */\r
- if (d && d->nc && d->nc->ident_cb) {\r
- return d->nc->ident_cb(d->nc, WMNC_IDENT_WMSG, hwnd, uMsg, \r
- wParam, lParam);\r
- }\r
- }\r
-\r
- return FALSE;\r
-}\r
-\r
-static void\r
-nc_notify_clear(khui_nc_wnd_data * d) {\r
-\r
- if (d->notif_type == NC_NOTIFY_NONE)\r
- /* there are no notifications anyway. */\r
- return;\r
-\r
- if (d->hwnd_notif_label)\r
- DestroyWindow(d->hwnd_notif_label);\r
-\r
- if (d->hwnd_notif_aux)\r
- DestroyWindow(d->hwnd_notif_aux);\r
-\r
- d->hwnd_notif_label = NULL;\r
- d->hwnd_notif_aux = NULL;\r
-\r
- SetRectEmpty(&d->r_notif);\r
-\r
- d->notif_type = NC_NOTIFY_NONE;\r
-\r
- /* Note that we must call nc_layout_main_panel() after calling\r
- this to adjust the layout of the main panel. However we aren't\r
- calling it here since we might want to add another set of\r
- notifications or make other changes to the main panel content\r
- before calling nc_layout_main_panel(). */\r
-}\r
-\r
-static void\r
-nc_notify_marquee(khui_nc_wnd_data * d, const wchar_t * label) {\r
-\r
-#if (_WIN32_IE >= 0x0600)\r
- HDC hdc;\r
- size_t length;\r
- SIZE label_size;\r
-#endif\r
-\r
- RECT r_label;\r
- RECT r_mq;\r
- RECT r_row;\r
- HFONT hfont;\r
- HWND hwnd;\r
- HDWP hdefer;\r
-\r
- /* Clear the notification area. We only support one notification\r
- at a time. */\r
- nc_notify_clear(d);\r
-\r
-#ifdef DEBUG\r
- assert(d->dlg_main);\r
-#endif\r
-\r
-#if (_WIN32_IE >= 0x0600)\r
-\r
- /* We can only show the marquee control if the comctl32 DLL is\r
- version 6.0 or later. Otherwise we only show the label. */\r
-\r
- if (FAILED(StringCchLength(label, KHUI_MAXCCH_SHORT_DESC, &length))) {\r
-#ifdef DEBUG\r
- assert(FALSE);\r
-#endif\r
- length = KHUI_MAXCCH_SHORT_DESC;\r
- }\r
-\r
- /* See how big the notification control needs to be. */\r
-\r
- hdc = GetDC(d->dlg_main);\r
-#ifdef DEBUG\r
- assert(hdc != NULL);\r
-#endif\r
-\r
- GetTextExtentPoint32(hdc, label, (int) length, &label_size);\r
-\r
- ReleaseDC(d->dlg_main, hdc);\r
-\r
- CopyRect(&r_row, &d->r_row);\r
-\r
- if (label_size.cx > d->r_e_label.right - d->r_e_label.left) {\r
- /* using an entire row */\r
- CopyRect(&r_label, &d->r_row);\r
- CopyRect(&r_mq, &d->r_n_input);\r
- OffsetRect(&r_mq, 0, r_row.bottom - r_row.top);\r
- r_row.bottom += r_row.bottom - r_row.top;\r
- } else if (label_size.cx > d->r_n_label.right - d->r_n_label.left) {\r
- /* using large labels */\r
- CopyRect(&r_label, &d->r_e_label);\r
- CopyRect(&r_mq, &d->r_e_input);\r
- } else {\r
- /* normal labels */\r
- CopyRect(&r_label, &d->r_n_label);\r
- CopyRect(&r_mq, &d->r_n_input);\r
- }\r
-\r
- InflateRect(&r_mq, 0, - ((r_mq.bottom - r_mq.top) / 4));\r
-\r
-#else /* _WIN32_IE < 0x0600 */\r
-\r
- /* We are just showing the label */\r
- CopyRect(&r_row, &d->r_row);\r
- CopyRect(&r_label, &r_row);\r
- SetRectEmpty(&r_mq);\r
-\r
-#endif /* _WIN32_IE >= 0x0600 */\r
-\r
- {\r
- long y;\r
-\r
- if (IsRectEmpty(&d->r_custprompt)) {\r
- y = d->r_idspec.bottom;\r
- } else {\r
- y = d->r_custprompt.bottom;\r
- }\r
-\r
- OffsetRect(&r_row, d->r_area.left, y);\r
- OffsetRect(&r_label, r_row.left, r_row.top);\r
- OffsetRect(&r_mq, r_row.left, r_row.top);\r
- }\r
-\r
- hfont = (HFONT) SendMessage(d->dlg_main, WM_GETFONT, 0, 0);\r
-\r
- hdefer = BeginDeferWindowPos(2);\r
-\r
- /* the label */\r
- hwnd = CreateWindowEx(0,\r
- L"STATIC",\r
- label,\r
- WS_CHILD | SS_ENDELLIPSIS,\r
- r_label.left, r_label.top,\r
- r_label.right - r_label.left,\r
- r_label.bottom - r_label.top,\r
- d->dlg_main,\r
- NULL, NULL, NULL);\r
-#ifdef DEBUG\r
- assert(hwnd != NULL);\r
-#endif\r
- SendMessage(hwnd, WM_SETFONT, (WPARAM) hfont, (LPARAM) TRUE);\r
-\r
- DeferWindowPos(hdefer, hwnd, NULL,\r
- 0, 0, 0, 0,\r
- SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER |\r
- SWP_NOSIZE | SWP_SHOWWINDOW);\r
-\r
- d->hwnd_notif_label = hwnd;\r
-\r
- /* and the marquee */\r
-\r
-#if (_WIN32_IE >= 0x0600)\r
-\r
- /* unfortunately, the marquee is only available on comctl32\r
- version 6.0 or later. On previous versions, we only display\r
- the message label. */\r
-\r
- hwnd = CreateWindowEx(0,\r
- PROGRESS_CLASS,\r
- L"",\r
- WS_CHILD | PBS_MARQUEE,\r
- r_mq.left, r_mq.top,\r
- r_mq.right - r_mq.left,\r
- r_mq.bottom - r_mq.top,\r
- d->dlg_main,\r
- NULL, NULL, NULL);\r
-#ifdef DEBUG\r
- assert(hwnd != NULL);\r
-#endif\r
-\r
- SendMessage(hwnd, PBM_SETMARQUEE, TRUE, 100);\r
-\r
- DeferWindowPos(hdefer, hwnd, NULL,\r
- 0, 0, 0, 0,\r
- SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER |\r
- SWP_NOSIZE | SWP_SHOWWINDOW);\r
-\r
- d->hwnd_notif_aux = hwnd;\r
-\r
-#endif /* _WIN32_IE >= 0x0600 */\r
-\r
- EndDeferWindowPos(hdefer);\r
-\r
- CopyRect(&d->r_notif, &r_row);\r
-\r
- d->notif_type = NC_NOTIFY_MARQUEE;\r
-\r
- /* Note that we must call nc_layout_main_panel() after calling\r
- this to adjust the layout of the main panel. However we aren't\r
- calling it here since we might want to add another set of\r
- notifications or make other changes to the main panel content\r
- before calling nc_layout_main_panel(). */\r
-}\r
-\r
-static void\r
-nc_notify_message(khui_nc_wnd_data * d,\r
- kherr_severity severity,\r
- const wchar_t * message) {\r
-\r
- SIZE icon_size;\r
- LPCTSTR icon_res;\r
- HICON h_icon;\r
- HWND hwnd;\r
- HFONT hfont;\r
- HDWP hdefer;\r
-\r
- RECT r_row;\r
- RECT r_label;\r
- RECT r_icon;\r
-\r
- nc_notify_clear(d);\r
-\r
- icon_size.cx = GetSystemMetrics(SM_CXSMICON);\r
- icon_size.cy = GetSystemMetrics(SM_CYSMICON);\r
-\r
- switch(severity) {\r
- case KHERR_INFO:\r
- icon_res = MAKEINTRESOURCE(OIC_INFORMATION);\r
- break;\r
-\r
- case KHERR_WARNING:\r
- icon_res = MAKEINTRESOURCE(OIC_WARNING);\r
- break;\r
-\r
- case KHERR_ERROR:\r
- icon_res = MAKEINTRESOURCE(OIC_ERROR);\r
- break;\r
-\r
- default:\r
- icon_res = NULL;\r
- }\r
-\r
- if (icon_res != NULL) {\r
- h_icon = (HICON) LoadImage(NULL,\r
- icon_res,\r
- IMAGE_ICON,\r
- icon_size.cx,\r
- icon_size.cy,\r
- LR_DEFAULTCOLOR | LR_SHARED);\r
- } else {\r
- h_icon = NULL;\r
- }\r
-\r
- CopyRect(&r_row, &d->r_row);\r
-\r
-#define CENTERVALUE(w,v) ((w)/2 - (v)/2)\r
-\r
- SetRect(&r_icon,\r
- 0, CENTERVALUE(r_row.bottom - r_row.top, icon_size.cy),\r
- icon_size.cx,\r
- CENTERVALUE(r_row.bottom - r_row.top, icon_size.cy) + icon_size.cy);\r
-\r
-#undef CENTERVALUE\r
-\r
- CopyRect(&r_label, &r_row);\r
- OffsetRect(&r_label, -r_label.left, -r_label.top);\r
- r_label.left += (icon_size.cx * 3) / 2;\r
-\r
- {\r
- long y;\r
-\r
- if (IsRectEmpty(&d->r_custprompt)) {\r
- y = d->r_idspec.bottom;\r
- } else {\r
- y = d->r_custprompt.bottom;\r
- }\r
-\r
- OffsetRect(&r_row, d->r_area.left, y);\r
- OffsetRect(&r_label, r_row.left, r_row.top);\r
- OffsetRect(&r_icon, r_row.left, r_row.top);\r
- }\r
-\r
- hfont = (HFONT) SendMessage(d->dlg_main, WM_GETFONT, 0, 0);\r
-\r
- hdefer = BeginDeferWindowPos(2);\r
-\r
- hwnd = CreateWindowEx(0,\r
- L"STATIC",\r
- message,\r
- WS_CHILD | SS_ENDELLIPSIS | SS_CENTER,\r
- r_label.left, r_label.top,\r
- r_label.right - r_label.left,\r
- r_label.bottom - r_label.top,\r
- d->dlg_main,\r
- NULL, NULL, NULL);\r
-#ifdef DEBUG\r
- assert(hwnd != NULL);\r
-#endif\r
- SendMessage(hwnd, WM_SETFONT, (WPARAM) hfont, (LPARAM) TRUE);\r
-\r
- DeferWindowPos(hdefer, hwnd, NULL,\r
- 0, 0, 0, 0,\r
- SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER |\r
- SWP_NOSIZE | SWP_SHOWWINDOW);\r
-\r
- d->hwnd_notif_label = hwnd;\r
-\r
- hwnd = CreateWindowEx(0,\r
- L"STATIC",\r
- NULL,\r
- WS_CHILD | SS_ICON |\r
-#if (_WIN32_IE >= 0x0600)\r
- SS_REALSIZECONTROL\r
-#else\r
- 0\r
-#endif\r
- ,\r
- r_icon.left, r_icon.top,\r
- r_icon.right - r_icon.left,\r
- r_icon.bottom - r_icon.top,\r
- d->dlg_main,\r
- NULL, NULL, NULL);\r
-#ifdef DEBUG\r
- assert(hwnd != NULL);\r
-#endif\r
-\r
- if (h_icon && hwnd)\r
- SendMessage(hwnd, STM_SETICON, (WPARAM) h_icon, 0);\r
-\r
- DeferWindowPos(hdefer, hwnd, NULL,\r
- 0, 0, 0, 0,\r
- SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER |\r
- SWP_NOSIZE | SWP_SHOWWINDOW | SWP_NOZORDER);\r
-\r
- d->hwnd_notif_aux = hwnd;\r
-\r
- EndDeferWindowPos(hdefer);\r
-\r
- CopyRect(&d->r_notif, &r_row);\r
-\r
- d->notif_type = NC_NOTIFY_MESSAGE;\r
-\r
- /* Note that we must call nc_layout_main_panel() after calling\r
- this to adjust the layout of the main panel. However we aren't\r
- calling it here since we might want to add another set of\r
- notifications or make other changes to the main panel content\r
- before calling nc_layout_main_panel(). */\r
-}\r
-\r
-static void\r
-nc_layout_main_panel(khui_nc_wnd_data * d)\r
-{\r
- RECT r_main;\r
- HWND hw_ct;\r
- HWND hw_ct_label;\r
- HDWP hdwp;\r
- RECT r_used; /* extent used by identity specifiers,\r
- custom prompts and notificaiton\r
- controls. */\r
-\r
- RECT r_wmain; /* extents of the main window in screen\r
- coordinates. */\r
-\r
- r_main.left = 0;\r
- r_main.top = 0;\r
- r_main.bottom = NCDLG_HEIGHT;\r
- r_main.right = NCDLG_WIDTH;\r
-\r
- MapDialogRect(d->dlg_main, &r_main);\r
-\r
- CopyRect(&r_used, &d->r_idspec);\r
-\r
- GetWindowRect(d->dlg_main, &r_wmain);\r
-\r
- hdwp = BeginDeferWindowPos(7);\r
-\r
- /* check if the notification area and the custom prompt area are\r
- overlapping. */\r
-\r
- if (d->notif_type != NC_NOTIFY_NONE) {\r
- long delta_y = 0;\r
- RECT r;\r
-\r
- CopyRect(&r, &d->r_custprompt);\r
-\r
- if (IsRectEmpty(&d->r_custprompt)) {\r
- /* if there are no custom prompts, then the notification\r
- area should be immediately below the identitify\r
- specifers. */\r
-\r
- delta_y = d->r_idspec.bottom - d->r_notif.top;\r
- } else {\r
- /* otherwise, the notification area should be immediately\r
- below the custom prompt area */\r
-\r
- delta_y = d->r_custprompt.bottom - d->r_notif.top;\r
- }\r
-\r
- if (delta_y != 0) {\r
- RECT r_lbl;\r
- RECT r_aux;\r
-\r
- if (d->hwnd_notif_label) {\r
- GetWindowRect(d->hwnd_notif_label, &r_lbl);\r
- OffsetRect(&r_lbl, -r_wmain.left, delta_y - r_wmain.top);\r
-\r
- DeferWindowPos(hdwp, d->hwnd_notif_label, NULL,\r
- r_lbl.left, r_lbl.top, 0, 0,\r
- SWP_NOACTIVATE | SWP_NOOWNERZORDER |\r
- SWP_NOZORDER | SWP_NOSIZE);\r
- }\r
-\r
- if (d->hwnd_notif_aux) {\r
- GetWindowRect(d->hwnd_notif_aux, &r_aux);\r
- OffsetRect(&r_aux, -r_wmain.left, delta_y - r_wmain.top);\r
-\r
- DeferWindowPos(hdwp, d->hwnd_notif_aux, NULL,\r
- r_aux.left, r_aux.top, 0, 0,\r
- SWP_NOACTIVATE | SWP_NOOWNERZORDER |\r
- SWP_NOZORDER | SWP_NOSIZE);\r
- }\r
-\r
- OffsetRect(&d->r_notif, 0, delta_y);\r
- }\r
- }\r
-\r
- if (!IsRectEmpty(&d->r_custprompt)) {\r
- r_used.bottom = max(d->r_custprompt.bottom,\r
- r_used.bottom);\r
- }\r
-\r
- if (!IsRectEmpty(&d->r_notif)) {\r
- r_used.bottom = max(d->r_notif.bottom,\r
- r_used.bottom);\r
- }\r
-\r
- if (d->nc->mode == KHUI_NC_MODE_MINI) {\r
- RECT r_ok;\r
- RECT r_cancel;\r
- RECT r_advanced;\r
- HWND hw;\r
-\r
- hw = GetDlgItem(d->dlg_main, IDOK);\r
-#ifdef DEBUG\r
- assert(hw != NULL);\r
-#endif\r
- GetWindowRect(hw, &r_ok);\r
- OffsetRect(&r_ok, -r_wmain.left, -r_ok.top + r_used.bottom);\r
-\r
- DeferWindowPos(hdwp, hw, NULL,\r
- r_ok.left, r_ok.top, 0, 0,\r
- SWP_NOACTIVATE | SWP_NOOWNERZORDER |\r
- SWP_NOZORDER | SWP_NOSIZE | SWP_SHOWWINDOW);\r
-\r
- hw = GetDlgItem(d->dlg_main, IDCANCEL);\r
-#ifdef DEBUG\r
- assert(hw != NULL);\r
-#endif\r
- GetWindowRect(hw, &r_cancel);\r
- OffsetRect(&r_cancel, -r_wmain.left, -r_cancel.top + r_used.bottom);\r
-\r
- DeferWindowPos(hdwp, hw, NULL,\r
- r_cancel.left, r_cancel.top, 0, 0,\r
- SWP_NOACTIVATE | SWP_NOOWNERZORDER |\r
- SWP_NOZORDER | SWP_NOSIZE | SWP_SHOWWINDOW);\r
-\r
- hw = GetDlgItem(d->dlg_main, IDC_NC_ADVANCED);\r
-#ifdef DEBUG\r
- assert(hw != NULL);\r
-#endif\r
- GetWindowRect(hw, &r_advanced);\r
- OffsetRect(&r_advanced, -r_wmain.left, -r_advanced.top + r_used.bottom);\r
-\r
- DeferWindowPos(hdwp, hw, NULL,\r
- r_advanced.left, r_advanced.top, 0, 0,\r
- SWP_NOACTIVATE | SWP_NOOWNERZORDER |\r
- SWP_NOZORDER | SWP_NOSIZE | SWP_SHOWWINDOW);\r
-\r
- /* and now update the extents of the main panel */\r
- r_main.bottom = r_used.bottom + (r_ok.bottom - r_ok.top) + d->r_area.top;\r
-\r
- CopyRect(&d->r_main, &r_main);\r
-\r
- } else {\r
-\r
- HWND hw;\r
-\r
- hw = GetDlgItem(d->dlg_main, IDOK);\r
-#ifdef DEBUG\r
- assert(hw != NULL);\r
-#endif\r
- if (IsWindowVisible(hw))\r
- DeferWindowPos(hdwp, hw, NULL,\r
- 0, 0, 0, 0,\r
- SWP_HIDEWINDOW | SWP_NOMOVE | SWP_NOSIZE |\r
- SWP_NOOWNERZORDER | SWP_NOZORDER);\r
-\r
- hw = GetDlgItem(d->dlg_main, IDCANCEL);\r
-#ifdef DEBUG\r
- assert(hw != NULL);\r
-#endif\r
- if (IsWindowVisible(hw))\r
- DeferWindowPos(hdwp, hw, NULL,\r
- 0, 0, 0, 0,\r
- SWP_HIDEWINDOW | SWP_NOMOVE | SWP_NOSIZE |\r
- SWP_NOOWNERZORDER | SWP_NOZORDER);\r
-\r
- hw = GetDlgItem(d->dlg_main, IDC_NC_ADVANCED);\r
-#ifdef DEBUG\r
- assert(hw != NULL);\r
-#endif\r
- if (IsWindowVisible(hw))\r
- DeferWindowPos(hdwp, hw, NULL,\r
- 0, 0, 0, 0,\r
- SWP_HIDEWINDOW | SWP_NOMOVE | SWP_NOSIZE |\r
- SWP_NOOWNERZORDER | SWP_NOZORDER);\r
-\r
- d->r_credtext.top = r_used.bottom;\r
-\r
- CopyRect(&d->r_main, &r_main);\r
- }\r
-\r
- /* now update the layout of the credentials text window */\r
-\r
- hw_ct = GetDlgItem(d->dlg_main, IDC_NC_CREDTEXT);\r
- hw_ct_label = GetDlgItem(d->dlg_main, IDC_NC_CREDTEXT_LABEL);\r
-#ifdef DEBUG\r
- assert(hw_ct != NULL);\r
- assert(hw_ct_label != NULL);\r
-#endif\r
-\r
- if (d->nc->mode == KHUI_NC_MODE_MINI ||\r
- d->r_credtext.bottom < d->r_credtext.top + d->r_row.bottom * 2) {\r
-\r
- /* either we aren't supposed to show the credentials text\r
- window, or we don't have enough room. */\r
- if (IsWindowVisible(hw_ct) || IsWindowVisible(hw_ct_label)) {\r
-\r
- DeferWindowPos(hdwp, hw_ct, NULL,\r
- 0, 0, 0, 0,\r
- SWP_HIDEWINDOW | SWP_NOOWNERZORDER |\r
- SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE);\r
-\r
- DeferWindowPos(hdwp, hw_ct_label, NULL,\r
- 0, 0, 0, 0,\r
- SWP_HIDEWINDOW | SWP_NOOWNERZORDER |\r
- SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE);\r
-\r
- }\r
-\r
- } else {\r
-\r
- DeferWindowPos(hdwp,\r
- hw_ct, NULL,\r
- d->r_credtext.left + d->r_n_input.left, /* x */\r
- d->r_credtext.top, /* y */\r
- d->r_n_input.right - d->r_n_input.left, /* width */\r
- d->r_credtext.bottom - d->r_credtext.top, /* height */\r
- SWP_NOACTIVATE | SWP_NOOWNERZORDER | \r
- SWP_NOZORDER | SWP_SHOWWINDOW);\r
-\r
- DeferWindowPos(hdwp,\r
- hw_ct_label, NULL,\r
- d->r_credtext.left + d->r_n_label.left, /* x */\r
- d->r_credtext.top, /* y */\r
- d->r_n_label.right - d->r_n_label.left, /* width */\r
- d->r_n_label.bottom - d->r_n_label.top, /* height */\r
- SWP_NOACTIVATE | SWP_NOOWNERZORDER |\r
- SWP_NOZORDER | SWP_SHOWWINDOW);\r
- }\r
-\r
- EndDeferWindowPos(hdwp);\r
-\r
- /* NOTE: although we updated d->r_main, if the new credentials\r
- window is in mini mode, we must call\r
- nc_layout_new_cred_window() to adjust the size of the new\r
- credentials window to fit the main panel. We don't do it here\r
- because we need to keep these two operations separate. */\r
-}\r
-\r
-/* Credential type panel comparison function. Tabs are sorted based\r
- on the following criteria:\r
-\r
- 1) By ordinal - Panels with ordinal -1 will be ranked after panels\r
- whose ordinal is not -1.\r
-\r
- 2) By name - Case insensitive comparison of the name. If the panel\r
- does not have a name (i.e. the ->name member is NULL, it will be\r
- ranked after panels which have a name.\r
- */\r
-static int __cdecl\r
-nc_tab_sort_func(const void * v1, const void * v2)\r
-{\r
- /* v1 and v2 and of type : khui_new_creds_by_type ** */\r
- khui_new_creds_by_type *t1, *t2;\r
-\r
- t1 = *((khui_new_creds_by_type **) v1);\r
- t2 = *((khui_new_creds_by_type **) v2);\r
-\r
- if(t1->ordinal != -1) {\r
- if(t2->ordinal != -1) {\r
- if(t1->ordinal == t2->ordinal) {\r
- if (t1->name && t2->name)\r
- return _wcsicmp(t1->name, t2->name);\r
- else if (t1->name)\r
- return -1;\r
- else if (t2->name)\r
- return 1;\r
- else\r
- return 0;\r
- } else {\r
- /* safe to convert to an int here */\r
- return (int) (t1->ordinal - t2->ordinal);\r
- }\r
- } else\r
- return -1;\r
- } else {\r
- if(t2->ordinal != -1)\r
- return 1;\r
- else if (t1->name && t2->name)\r
- return wcscmp(t1->name, t2->name);\r
- else if (t1->name)\r
- return -1;\r
- else if (t2->name)\r
- return 1;\r
- else\r
- return 0;\r
- }\r
-}\r
-\r
-static void \r
-nc_notify_types(khui_new_creds * c, UINT uMsg,\r
- WPARAM wParam, LPARAM lParam, BOOL sync)\r
-{\r
- khm_size i;\r
-\r
- for(i=0; i<c->n_types; i++) {\r
-\r
- if (c->types[i]->hwnd_panel == NULL)\r
- continue;\r
-\r
- if (sync)\r
- SendMessage(c->types[i]->hwnd_panel, uMsg, wParam, lParam);\r
- else\r
- PostMessage(c->types[i]->hwnd_panel, uMsg, wParam, lParam);\r
- }\r
-}\r
-\r
-static void\r
-nc_clear_password_fields(khui_nc_wnd_data * d)\r
-{\r
- khm_size i;\r
- khm_boolean need_sync = FALSE;\r
-\r
- khui_cw_lock_nc(d->nc);\r
-\r
- for (i=0; i < d->nc->n_prompts; i++) {\r
- if ((d->nc->prompts[i]->flags & KHUI_NCPROMPT_FLAG_HIDDEN) &&\r
- d->nc->prompts[i]->hwnd_edit) {\r
- SetWindowText(d->nc->prompts[i]->hwnd_edit,\r
- L"");\r
- need_sync = TRUE;\r
- }\r
- }\r
-\r
- khui_cw_unlock_nc(d->nc);\r
-\r
- if (need_sync) {\r
- khui_cw_sync_prompt_values(d->nc);\r
- }\r
-}\r
-\r
-/* used by nc_enable_controls */\r
-\r
-struct nc_enum_wnd_data {\r
- khui_nc_wnd_data * d;\r
- khm_boolean enable;\r
-};\r
-\r
-static\r
-BOOL CALLBACK\r
-nc_enum_wnd_proc(HWND hwnd,\r
- LPARAM lParam)\r
-{\r
- struct nc_enum_wnd_data * wd;\r
-\r
- wd = (struct nc_enum_wnd_data *) lParam;\r
-\r
- EnableWindow(hwnd, wd->enable);\r
-\r
- return TRUE;\r
-}\r
-\r
-static void\r
-nc_enable_controls(khui_nc_wnd_data * d, khm_boolean enable)\r
-{\r
- struct nc_enum_wnd_data wd;\r
-\r
- ZeroMemory(&wd, sizeof(wd));\r
-\r
- wd.d = d;\r
- wd.enable = enable;\r
-\r
- EnumChildWindows(d->dlg_main, nc_enum_wnd_proc, (LPARAM) &wd);\r
-}\r
-\r
-#define NC_MAXCCH_CREDTEXT 16384\r
-#define NC_MAXCB_CREDTEXT (NC_MAXCCH_CREDTEXT * sizeof(wchar_t))\r
-\r
-static void \r
-nc_update_credtext(khui_nc_wnd_data * d) \r
-{\r
- wchar_t * ctbuf = NULL;\r
- wchar_t * buf;\r
- BOOL okEnable = FALSE;\r
- BOOL validId = FALSE;\r
- HWND hw = NULL;\r
- size_t cch = 0;\r
-\r
- ctbuf = PMALLOC(NC_MAXCB_CREDTEXT);\r
-\r
- assert(ctbuf != NULL);\r
-\r
- LoadString(khm_hInstance, IDS_NC_CREDTEXT_TABS, ctbuf, NC_MAXCCH_CREDTEXT);\r
- StringCchLength(ctbuf, NC_MAXCCH_CREDTEXT, &cch);\r
- buf = ctbuf + cch;\r
- nc_notify_types(d->nc, KHUI_WM_NC_NOTIFY, \r
- MAKEWPARAM(0, WMNC_UPDATE_CREDTEXT), (LPARAM) d->nc, TRUE);\r
-\r
- /* hopefully all the types have updated their credential texts */\r
-\r
- /* if the dialog is in the mini mode, we have to display\r
- exceptions using a notification. */\r
- if (d->nc->mode == KHUI_NC_MODE_MINI) {\r
- BOOL need_layout = FALSE;\r
- if (d->nc->n_identities == 0) {\r
-\r
- /* There are no identities selected. We don't show any\r
- notifications here. */\r
- if (d->notif_type != NC_NOTIFY_NONE) {\r
- nc_notify_clear(d);\r
- need_layout = TRUE;\r
- }\r
-\r
- } else {\r
-\r
- wchar_t id_name[KCDB_IDENT_MAXCCH_NAME];\r
- wchar_t format[256];\r
- wchar_t msg[ARRAYLENGTH(format) + ARRAYLENGTH(id_name)];\r
- khm_size cbbuf;\r
- khm_int32 flags;\r
-\r
- kcdb_identity_get_flags(d->nc->identities[0], &flags);\r
-\r
- cbbuf = sizeof(id_name);\r
- kcdb_identity_get_name(d->nc->identities[0], id_name, &cbbuf);\r
-\r
- if (flags & KCDB_IDENT_FLAG_INVALID) {\r
-\r
- /* identity is invalid */\r
- LoadString(khm_hInstance, IDS_NCN_IDENT_INVALID,\r
- format, ARRAYLENGTH(format));\r
- StringCbPrintf(msg, sizeof(msg), format, id_name);\r
-\r
- nc_notify_message(d, KHERR_ERROR, msg);\r
-\r
- need_layout = TRUE;\r
-\r
- } else if ((flags & KCDB_IDENT_FLAG_VALID) ||\r
- d->nc->subtype == KMSG_CRED_PASSWORD) {\r
- /* special case: If we are going to change the\r
- password, we don't expect the identity provider to\r
- validate the identity in real time. As such, we\r
- assume that the identity is valid. */\r
- \r
- /* identity is valid */\r
- if (d->notif_type != NC_NOTIFY_NONE) {\r
- nc_notify_clear(d);\r
- need_layout = TRUE;\r
- }\r
-\r
- } else if (flags & KCDB_IDENT_FLAG_UNKNOWN) {\r
-\r
- /* unknown state */\r
- LoadString(khm_hInstance, IDS_NCN_IDENT_UNKNOWN,\r
- format, ARRAYLENGTH(format));\r
- StringCbPrintf(msg, sizeof(msg), format, id_name);\r
-\r
- nc_notify_message(d, KHERR_WARNING, msg);\r
-\r
- need_layout = TRUE;\r
-\r
- } else {\r
-\r
- /* still checking */\r
- LoadString(khm_hInstance, IDS_NCN_IDENT_CHECKING,\r
- format, ARRAYLENGTH(format));\r
- StringCbPrintf(msg, sizeof(msg), format, id_name);\r
-\r
- nc_notify_marquee(d, msg);\r
-\r
- need_layout = TRUE;\r
-\r
- }\r
- }\r
-\r
- if (need_layout) {\r
- nc_layout_main_panel(d);\r
- nc_layout_new_cred_window(d);\r
- }\r
- }\r
-\r
- if(d->nc->n_identities == 1) {\r
- wchar_t main_fmt[256];\r
- wchar_t id_fmt[256];\r
- wchar_t id_name[KCDB_IDENT_MAXCCH_NAME];\r
- wchar_t id_string[KCDB_IDENT_MAXCCH_NAME + 256];\r
- khm_size cbbuf;\r
- khm_int32 flags;\r
-\r
- LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_ONE, \r
- main_fmt, (int) ARRAYLENGTH(main_fmt));\r
-\r
- cbbuf = sizeof(id_name);\r
- kcdb_identity_get_name(d->nc->identities[0], id_name, &cbbuf);\r
-\r
- kcdb_identity_get_flags(d->nc->identities[0], &flags);\r
-\r
- if (flags & KCDB_IDENT_FLAG_INVALID) {\r
- LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_INVALID, \r
- id_fmt, (int) ARRAYLENGTH(id_fmt));\r
- } else if(flags & KCDB_IDENT_FLAG_VALID) {\r
- LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_VALID, \r
- id_fmt, (int) ARRAYLENGTH(id_fmt));\r
- } else if(flags & KCDB_IDENT_FLAG_UNKNOWN) {\r
- LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_UNCHECKED,\r
- id_fmt, (int) ARRAYLENGTH(id_fmt));\r
- } else if(d->nc->subtype == KMSG_CRED_NEW_CREDS) {\r
- LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_CHECKING, \r
- id_fmt, (int) ARRAYLENGTH(id_fmt));\r
- } else {\r
- LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_UNCHECKED, \r
- id_fmt, (int) ARRAYLENGTH(id_fmt));\r
- }\r
-\r
- StringCbPrintf(id_string, sizeof(id_string), id_fmt, id_name);\r
-\r
- StringCbPrintf(buf, NC_MAXCB_CREDTEXT - cch*sizeof(wchar_t), \r
- main_fmt, id_string);\r
-\r
- if (flags & KCDB_IDENT_FLAG_VALID) {\r
- if (flags & KCDB_IDENT_FLAG_DEFAULT)\r
- LoadString(khm_hInstance, IDS_NC_ID_DEF,\r
- id_string, ARRAYLENGTH(id_string));\r
- else if (d->nc->set_default)\r
- LoadString(khm_hInstance, IDS_NC_ID_WDEF,\r
- id_string, ARRAYLENGTH(id_string));\r
- else\r
- LoadString(khm_hInstance, IDS_NC_ID_NDEF,\r
- id_string, ARRAYLENGTH(id_string));\r
-\r
- StringCbCat(buf, NC_MAXCB_CREDTEXT - cch * sizeof(wchar_t),\r
- id_string);\r
- }\r
-\r
- } else if(d->nc->n_identities > 1) {\r
- wchar_t *ids_string;\r
- khm_size cb_ids_string;\r
-\r
- wchar_t id_name[KCDB_IDENT_MAXCCH_NAME];\r
- wchar_t id_fmt[256];\r
- wchar_t id_string[KCDB_IDENT_MAXCCH_NAME + 256];\r
-\r
- wchar_t main_fmt[256];\r
- khm_size cbbuf;\r
-\r
- LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_MANY, \r
- main_fmt, (int) ARRAYLENGTH(main_fmt));\r
-\r
- /* we are going to concatenate all the identity names into\r
- a comma separated string */\r
-\r
- /* d->nc->n_identities is at least 2 */\r
- ids_string = PMALLOC((KCDB_IDENT_MAXCB_NAME + sizeof(id_fmt)) * \r
- (d->nc->n_identities - 1));\r
- cb_ids_string = \r
- (KCDB_IDENT_MAXCB_NAME + sizeof(id_fmt)) * \r
- (d->nc->n_identities - 1);\r
-\r
- assert(ids_string != NULL);\r
-\r
- ids_string[0] = 0;\r
-\r
- {\r
- khm_size i;\r
- khm_int32 flags;\r
-\r
- for(i=1; i<d->nc->n_identities; i++) {\r
- if(i>1) {\r
- StringCbCat(ids_string, cb_ids_string, L",");\r
- }\r
-\r
- flags = 0;\r
-\r
- cbbuf = sizeof(id_name);\r
- kcdb_identity_get_name(d->nc->identities[i], id_name, &cbbuf);\r
- kcdb_identity_get_flags(d->nc->identities[i], &flags);\r
- if(flags & KCDB_IDENT_FLAG_INVALID) {\r
- LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_INVALID, \r
- id_fmt, (int) ARRAYLENGTH(id_fmt));\r
- } else if(flags & KCDB_IDENT_FLAG_VALID) {\r
- LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_VALID, \r
- id_fmt, (int) ARRAYLENGTH(id_fmt));\r
- } else {\r
- LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_UNCHECKED, \r
- id_fmt, (int) ARRAYLENGTH(id_fmt));\r
- }\r
-\r
- StringCbPrintf(id_string, sizeof(id_string), id_fmt, id_name);\r
- StringCbCat(ids_string, cb_ids_string, id_string);\r
- }\r
-\r
- cbbuf = sizeof(id_name);\r
- kcdb_identity_get_name(d->nc->identities[0], id_name, &cbbuf);\r
- kcdb_identity_get_flags(d->nc->identities[0], &flags);\r
- if(flags & KCDB_IDENT_FLAG_INVALID) {\r
- LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_INVALID, \r
- id_fmt, (int) ARRAYLENGTH(id_fmt));\r
- } else if(flags & KCDB_IDENT_FLAG_VALID) {\r
- LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_VALID, \r
- id_fmt, (int) ARRAYLENGTH(id_fmt));\r
- } else {\r
- LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_UNCHECKED, \r
- id_fmt, (int) ARRAYLENGTH(id_fmt));\r
- }\r
- StringCbPrintf(id_string, sizeof(id_string), id_fmt, id_name);\r
-\r
- StringCbPrintf(buf, NC_MAXCB_CREDTEXT - cch*sizeof(wchar_t), \r
- main_fmt, id_string, ids_string);\r
-\r
- PFREE(ids_string);\r
- }\r
- } else {\r
- LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_NONE, \r
- buf, (int)(NC_MAXCCH_CREDTEXT - cch));\r
- }\r
-\r
- /* now, append the credtext string from each of the cred types */\r
- {\r
- khm_size i;\r
- size_t cb;\r
- wchar_t * buf;\r
-\r
- cb = NC_MAXCB_CREDTEXT;\r
- buf = ctbuf;\r
-\r
- for(i=0; i<d->nc->n_types; i++) {\r
- if(d->nc->types[i]->credtext != NULL) {\r
- StringCbCatEx(buf, cb, \r
- d->nc->types[i]->credtext,\r
- &buf, &cb,\r
- 0);\r
- }\r
- }\r
- }\r
-\r
- SetDlgItemText(d->dlg_main, IDC_NC_CREDTEXT, ctbuf);\r
-\r
- PFREE(ctbuf);\r
-\r
- /* so depending on whether the primary identity was found to be\r
- invalid, we need to disable the Ok button and set the title to\r
- reflect this */\r
-\r
- if(d->nc->n_identities > 0) {\r
- khm_int32 flags = 0;\r
-\r
- if(KHM_SUCCEEDED(kcdb_identity_get_flags(d->nc->identities[0], \r
- &flags)) &&\r
- (flags & KCDB_IDENT_FLAG_VALID)) {\r
- validId = TRUE;\r
- }\r
- }\r
-\r
- if (d->nc->window_title == NULL) {\r
- if(validId) {\r
- wchar_t wpostfix[256];\r
- wchar_t wtitle[KCDB_IDENT_MAXCCH_NAME + 256];\r
- khm_size cbsize;\r
-\r
- cbsize = sizeof(wtitle);\r
- kcdb_identity_get_name(d->nc->identities[0], wtitle, &cbsize);\r
-\r
- if (d->nc->subtype == KMSG_CRED_PASSWORD)\r
- LoadString(khm_hInstance, IDS_WTPOST_PASSWORD,\r
- wpostfix, (int) ARRAYLENGTH(wpostfix));\r
- else\r
- LoadString(khm_hInstance, IDS_WTPOST_NEW_CREDS, \r
- wpostfix, (int) ARRAYLENGTH(wpostfix));\r
-\r
- StringCbCat(wtitle, sizeof(wtitle), wpostfix);\r
-\r
- SetWindowText(d->nc->hwnd, wtitle);\r
- } else {\r
- wchar_t wtitle[256];\r
-\r
- if (d->nc->subtype == KMSG_CRED_PASSWORD)\r
- LoadString(khm_hInstance, IDS_WT_PASSWORD,\r
- wtitle, (int) ARRAYLENGTH(wtitle));\r
- else\r
- LoadString(khm_hInstance, IDS_WT_NEW_CREDS, \r
- wtitle, (int) ARRAYLENGTH(wtitle));\r
-\r
- SetWindowText(d->nc->hwnd, wtitle);\r
- }\r
- }\r
-\r
- if (!(d->nc->response & KHUI_NC_RESPONSE_PROCESSING)) {\r
- if(validId ||\r
- d->nc->subtype == KMSG_CRED_PASSWORD) {\r
- /* TODO: check if all the required fields have valid values\r
- before enabling the Ok button */\r
- okEnable = TRUE;\r
- }\r
-\r
- hw = GetDlgItem(d->dlg_main, IDOK);\r
- EnableWindow(hw, okEnable);\r
- hw = GetDlgItem(d->dlg_bb, IDOK);\r
- EnableWindow(hw, okEnable);\r
- }\r
-}\r
-\r
-static void\r
-nc_layout_new_cred_window(khui_nc_wnd_data * ncd) {\r
- khui_new_creds * c;\r
- RECT r_main;\r
- RECT r_ncdialog;\r
- HDWP hdefer;\r
-\r
- c = ncd->nc;\r
-\r
- r_main.left = 0;\r
- r_main.top = 0;\r
- r_main.right = NCDLG_WIDTH;\r
- r_main.bottom = NCDLG_HEIGHT;\r
-\r
- MapDialogRect(ncd->dlg_main, &r_main);\r
-\r
- hdefer = BeginDeferWindowPos(5);\r
-\r
- if (c->mode == KHUI_NC_MODE_MINI) {\r
-\r
- if (IsWindowVisible(ncd->tab_wnd)) {\r
- DeferWindowPos(hdefer,\r
- ncd->tab_wnd, NULL,\r
- 0, 0, 0, 0,\r
- SWP_HIDEWINDOW |\r
- SWP_NOMOVE | SWP_NOOWNERZORDER |\r
- SWP_NOSIZE | SWP_NOZORDER);\r
- }\r
-\r
- if (IsWindowVisible(ncd->dlg_bb)) {\r
- DeferWindowPos(hdefer,\r
- ncd->dlg_bb, NULL,\r
- 0, 0, 0, 0,\r
- SWP_HIDEWINDOW |\r
- SWP_NOMOVE | SWP_NOOWNERZORDER |\r
- SWP_NOSIZE | SWP_NOZORDER);\r
- }\r
-\r
- DeferWindowPos(hdefer, ncd->dlg_main, NULL,\r
- r_main.left, r_main.top,\r
- r_main.right - r_main.left,\r
- r_main.bottom - r_main.top,\r
- SWP_NOACTIVATE | SWP_NOOWNERZORDER |\r
- SWP_NOZORDER | SWP_SHOWWINDOW);\r
-\r
- /* note that the ncd->r_main.bottom may not be the same as\r
- r_main.bottom because ncd->r_main.bottom is set dynamically\r
- depending on custom controls. ncd->r_main is valid only\r
- once nc_layout_main_panel() is called.*/\r
- CopyRect(&ncd->r_required, &ncd->r_main);\r
-\r
- } else {\r
- RECT r_tabctrl;\r
- RECT r_displayarea;\r
- RECT r_bbar;\r
- khm_size i;\r
-\r
- /* calculate the size of the tab control so that it fits\r
- snugly around the expanded main panel. */\r
- CopyRect(&r_tabctrl, &r_main);\r
- TabCtrl_AdjustRect(ncd->tab_wnd, TRUE, &r_tabctrl);\r
-\r
- if (r_tabctrl.left < 0 ||\r
- r_tabctrl.top < 0) {\r
-\r
- OffsetRect(&r_tabctrl,\r
- (r_tabctrl.left < 0)? -r_tabctrl.left : 0,\r
- (r_tabctrl.top < 0)? -r_tabctrl.top : 0);\r
-\r
- }\r
-\r
-#ifdef DEBUG\r
- assert(r_tabctrl.left == 0);\r
- assert(r_tabctrl.top == 0);\r
-#endif\r
-\r
- OffsetRect(&r_tabctrl, 0, ncd->r_area.top);\r
-\r
- /* and now calculate the rectangle where the main panel should\r
- be inside the tab control. */\r
- CopyRect(&r_displayarea, &r_tabctrl);\r
- TabCtrl_AdjustRect(ncd->tab_wnd, FALSE, &r_displayarea);\r
-\r
- DeferWindowPos(hdefer,\r
- ncd->tab_wnd, HWND_BOTTOM,\r
- r_tabctrl.left, r_tabctrl.top,\r
- r_tabctrl.right - r_tabctrl.left,\r
- r_tabctrl.bottom - r_tabctrl.top,\r
- SWP_NOACTIVATE | SWP_NOOWNERZORDER |\r
- SWP_SHOWWINDOW);\r
-\r
- /* we have to place the button bar just to the right of the\r
- tab panel. */\r
- r_bbar.left = 0;\r
- r_bbar.top = 0;\r
- r_bbar.right = NCDLG_BBAR_WIDTH;\r
- r_bbar.bottom = NCDLG_BBAR_HEIGHT;\r
-\r
- MapDialogRect(ncd->dlg_main, &r_bbar);\r
-\r
- OffsetRect(&r_bbar, r_tabctrl.right, 0);\r
-\r
- DeferWindowPos(hdefer,\r
- ncd->dlg_bb, NULL,\r
- r_bbar.left, r_bbar.top,\r
- r_bbar.right - r_bbar.left,\r
- r_bbar.bottom - r_bbar.top,\r
- SWP_NOACTIVATE | SWP_NOOWNERZORDER |\r
- SWP_NOZORDER | SWP_SHOWWINDOW);\r
-\r
- /* move the main panel inside the tab control... */\r
- DeferWindowPos(hdefer,\r
- ncd->dlg_main, NULL,\r
- r_displayarea.left, r_displayarea.top,\r
- r_displayarea.right - r_displayarea.left,\r
- r_displayarea.bottom - r_displayarea.top,\r
- SWP_NOACTIVATE | SWP_NOOWNERZORDER |\r
- SWP_NOZORDER |\r
- (ncd->current_panel == 0 ? SWP_SHOWWINDOW : SWP_HIDEWINDOW));\r
-\r
- /* and also move all the credential type panels (if they have\r
- been created) inside the tab control too. */\r
- khui_cw_lock_nc(c);\r
-\r
- for (i=0; i < c->n_types; i++) {\r
- if (c->types[i]->hwnd_panel != NULL) {\r
- DeferWindowPos(hdefer,\r
- c->types[i]->hwnd_panel, NULL,\r
- r_displayarea.left, r_displayarea.top,\r
- r_displayarea.right - r_displayarea.left,\r
- r_displayarea.bottom - r_displayarea.top,\r
- SWP_NOACTIVATE | SWP_NOOWNERZORDER |\r
- SWP_NOZORDER |\r
- (ncd->current_panel == c->types[i]->ordinal ?\r
- SWP_SHOWWINDOW : SWP_HIDEWINDOW));\r
- }\r
- }\r
-\r
- khui_cw_unlock_nc(c);\r
-\r
- /* then update the required size of the new credentials\r
- dialog. */\r
- ncd->r_required.left = 0;\r
- ncd->r_required.top = 0;\r
- ncd->r_required.right = r_bbar.right;\r
- ncd->r_required.bottom = max(r_tabctrl.bottom, r_bbar.bottom) + ncd->r_area.top;\r
- }\r
-\r
- /* commit all the window moves, resizes and hides/shows we did*/\r
- EndDeferWindowPos(hdefer);\r
-\r
- /* now we have to see if the client area of the new credentials\r
- window is the right size. */\r
-\r
- GetClientRect(c->hwnd, &r_ncdialog);\r
-\r
- if (\r
-\r
- ((r_ncdialog.right - r_ncdialog.left !=\r
- ncd->r_required.right - ncd->r_required.left)\r
-\r
- ||\r
-\r
- (r_ncdialog.bottom - r_ncdialog.top !=\r
- ncd->r_required.bottom - ncd->r_required.top))\r
-\r
- &&\r
-\r
- /* we don't bother if the new creds window is already in the\r
- process of changing the size. */\r
- !ncd->size_changing) {\r
-\r
- /* if not, notify the window that the size needs adjusting. */\r
- if (IsWindowVisible(c->hwnd))\r
- PostMessage(c->hwnd, KHUI_WM_NC_NOTIFY,\r
- MAKEWPARAM(0, WMNC_UPDATE_LAYOUT), 0);\r
- else\r
- SendMessage(c->hwnd, KHUI_WM_NC_NOTIFY,\r
- MAKEWPARAM(0, WMNC_UPDATE_LAYOUT), 0);\r
- }\r
-}\r
-\r
-#define CW_PARAM DWLP_USER\r
-\r
-static LRESULT \r
-nc_handle_wm_create(HWND hwnd,\r
- UINT uMsg,\r
- WPARAM wParam,\r
- LPARAM lParam)\r
-{\r
- LPCREATESTRUCT lpc;\r
- khui_new_creds * c;\r
- khui_nc_wnd_data * ncd;\r
- int x, y;\r
- int width, height;\r
- RECT r;\r
- HFONT hf_main;\r
-\r
- lpc = (LPCREATESTRUCT) lParam;\r
-\r
- ncd = PMALLOC(sizeof(*ncd));\r
- ZeroMemory(ncd, sizeof(*ncd));\r
-\r
- c = (khui_new_creds *) lpc->lpCreateParams;\r
- ncd->nc = c;\r
- c->hwnd = hwnd;\r
-\r
-#ifdef DEBUG\r
- assert(c->subtype == KMSG_CRED_NEW_CREDS ||\r
- c->subtype == KMSG_CRED_PASSWORD);\r
-#endif\r
-\r
-#pragma warning(push)\r
-#pragma warning(disable: 4244)\r
- SetWindowLongPtr(hwnd, CW_PARAM, (LONG_PTR) ncd);\r
-#pragma warning(pop)\r
-\r
- /* first, create the tab control that will house the main dialog\r
- panel as well as the plug-in specific panels */\r
- ncd->tab_wnd = CreateWindowEx(0, /* extended style */\r
- WC_TABCONTROL,\r
- L"TabControloxxrz", /* window name */\r
- TCS_HOTTRACK | TCS_RAGGEDRIGHT |\r
- TCS_SINGLELINE | TCS_TABS |\r
- WS_CHILD | WS_TABSTOP | WS_CLIPSIBLINGS,\r
- 0, 0, 100, 100, /* x,y,width height.\r
- We'll be changing\r
- these later\r
- anyway. */\r
- hwnd,\r
- (HMENU) IDC_NC_TABS,\r
- NULL,\r
- 0);\r
-\r
-#ifdef DEBUG\r
- assert(ncd->tab_wnd != NULL);\r
-#endif\r
-\r
- /* try to create the main dialog panel */\r
-\r
- ncd->dlg_main = CreateDialogParam(khm_hInstance,\r
- MAKEINTRESOURCE(IDD_NC_NEWCRED),\r
- hwnd,\r
- nc_common_dlg_proc,\r
- (LPARAM) ncd);\r
-#ifdef DEBUG\r
- assert(ncd->dlg_main != NULL);\r
-#endif\r
-\r
- hf_main = (HFONT) SendMessage(ncd->dlg_main, WM_GETFONT, 0, 0);\r
- if (hf_main)\r
- SendMessage(ncd->tab_wnd, WM_SETFONT, (WPARAM) hf_main, FALSE);\r
-\r
- {\r
- RECT r_main;\r
- RECT r_area;\r
- RECT r_row;\r
- HWND hw;\r
- \r
- /* During the operation of the new credentials window, we will\r
- need to dynamically change the layout of the controls as a\r
- result of custom prompting from credentials providers and\r
- identity selectors from identity providers. In order to\r
- guide the dynamic layout, we pick out a few metrics from\r
- the dialog template for the main panel. The metrics come\r
- from hidden STATIC controls in the dialog template. */\r
-\r
- GetWindowRect(ncd->dlg_main, &r_main);\r
-\r
- /* IDC_NC_TPL_PANEL spans the full extent of the dialog that\r
- we can populate with custom controls. */\r
- hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_PANEL);\r
-#ifdef DEBUG\r
- assert(hw);\r
-#endif\r
- GetWindowRect(hw, &r_area);\r
- OffsetRect(&r_area,-r_main.left, -r_main.top);\r
- CopyRect(&ncd->r_area, &r_area);\r
-\r
- /* IDC_NC_TPL_ROW spans the extent of a row of normal sized\r
- custom controls. A row of custom controls typicall consist\r
- of a text label and an input control. */\r
- hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_ROW);\r
-#ifdef DEBUG\r
- assert(hw);\r
-#endif\r
- GetWindowRect(hw, &r);\r
- CopyRect(&r_row, &r);\r
- OffsetRect(&r,-r.left, -r.top);\r
- CopyRect(&ncd->r_row, &r);\r
-\r
- /* IDC_NC_TPL_LABEL spans the extent that a normal sized\r
- label. The control overlaps IDC_NC_TPL_ROW so we can get\r
- coordinates relative to the row extents. */\r
- hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_LABEL);\r
-#ifdef DEBUG\r
- assert(hw);\r
-#endif\r
- GetWindowRect(hw, &r);\r
- OffsetRect(&r,-r_row.left, -r_row.top);\r
- CopyRect(&ncd->r_n_label, &r);\r
-\r
- /* IDC_NC_TPL_INPUT spans the extent of a normal sized input\r
- control in a custom control row. The control overlaps\r
- IDC_NC_TPL_ROW so we can get relative coordinates. */\r
- hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_INPUT);\r
-#ifdef DEBUG\r
- assert(hw);\r
-#endif\r
- GetWindowRect(hw, &r);\r
- OffsetRect(&r, -r_row.left, -r_row.top);\r
- CopyRect(&ncd->r_n_input, &r);\r
-\r
- /* IDC_NC_TPL_ROW_LG spans the extent of a row of large sized\r
- controls. */\r
- hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_ROW_LG);\r
-#ifdef DEBUG\r
- assert(hw);\r
-#endif\r
- GetWindowRect(hw, &r_row);\r
-\r
- /* IDC_NC_TPL_LABEL_LG is a large sized label. The control\r
- overlaps IDC_NC_TPL_ROW_LG. */\r
- hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_LABEL_LG);\r
-#ifdef DEBUG\r
- assert(hw);\r
-#endif\r
- GetWindowRect(hw, &r);\r
- OffsetRect(&r, -r_row.left, -r_row.top);\r
- CopyRect(&ncd->r_e_label, &r);\r
-\r
- /* IDC_NC_TPL_INPUT_LG is a large sized input control.\r
- Overlaps IDC_NC_TPL_ROW_LG. */\r
- hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_INPUT_LG);\r
-#ifdef DEBUG\r
- assert(hw);\r
-#endif\r
- GetWindowRect(hw, &r);\r
- OffsetRect(&r, -r_row.left, -r_row.top);\r
- CopyRect(&ncd->r_e_input, &r);\r
-\r
- CopyRect(&ncd->r_credtext, &ncd->r_area);\r
- CopyRect(&ncd->r_idspec, &ncd->r_area);\r
-\r
- ncd->r_idspec.bottom = ncd->r_idspec.top;\r
-\r
- /* And finally the credential text window. The only metric we\r
- take from here is the Y coordinate of the bottom of the\r
- control since the actual size and position of the\r
- credentials window will change depending on the custom\r
- controls being displayed. */\r
- hw = GetDlgItem(ncd->dlg_main, IDC_NC_CREDTEXT);\r
-#ifdef DEBUG\r
- assert(hw);\r
-#endif\r
- GetWindowRect(hw, &r);\r
- OffsetRect(&r, -r_main.left, -r_main.top);\r
- ncd->r_credtext.bottom = r.bottom;\r
- }\r
-\r
- /* if the mode is 'mini'*/\r
- r.left = 0;\r
- r.top = 0;\r
-\r
- if(c->mode == KHUI_NC_MODE_MINI) {\r
- r.right = NCDLG_WIDTH;\r
- r.bottom = NCDLG_HEIGHT;\r
- } else {\r
- r.right = NCDLG_WIDTH + NCDLG_BBAR_WIDTH;\r
- r.bottom = NCDLG_BBAR_HEIGHT;\r
- }\r
-\r
- MapDialogRect(ncd->dlg_main, &r);\r
-\r
- /* position the new credentials dialog */\r
- width = r.right - r.left;\r
- height = r.bottom - r.top;\r
-\r
- /* adjust width and height to accomodate NC area */\r
- {\r
- RECT wr,cr;\r
-\r
- GetWindowRect(hwnd, &wr);\r
- GetClientRect(hwnd, &cr);\r
-\r
- /* the non-client and client areas have already been calculated\r
- at this point. We just use the difference to adjust the width\r
- and height */\r
- width += (wr.right - wr.left) - (cr.right - cr.left);\r
- height += (wr.bottom - wr.top) - (cr.bottom - cr.top);\r
- }\r
-\r
- /* if the parent window is visible, we center the new credentials\r
- dialog over the parent. Otherwise, we center it on the primary\r
- display. */\r
-\r
- if (IsWindowVisible(lpc->hwndParent)) {\r
- GetWindowRect(lpc->hwndParent, &r);\r
- } else {\r
- if(!SystemParametersInfo(SPI_GETWORKAREA, 0, (PVOID) &r, 0)) {\r
- /* failover to the window coordinates */\r
- GetWindowRect(lpc->hwndParent, &r);\r
- }\r
- }\r
- x = (r.right + r.left)/2 - width / 2;\r
- y = (r.top + r.bottom)/2 - height / 2;\r
-\r
- MoveWindow(hwnd, x, y, width, height, FALSE);\r
-\r
- ncd->dlg_bb = CreateDialogParam(khm_hInstance,\r
- MAKEINTRESOURCE(IDD_NC_BBAR),\r
- hwnd,\r
- nc_common_dlg_proc,\r
- (LPARAM) ncd);\r
-\r
-#ifdef DEBUG\r
- assert(ncd->dlg_bb);\r
-#endif\r
-\r
- /* Call the identity provider callback to set the identity\r
- selector controls. These controls need to be there before we\r
- layout the main panel. */\r
- c->ident_cb(c, WMNC_IDENT_INIT, NULL, 0, 0, (LPARAM) ncd->dlg_main);\r
-\r
- if (c->mode == KHUI_NC_MODE_EXPANDED) {\r
- SendMessage(ncd->dlg_main, KHUI_WM_NC_NOTIFY,\r
- MAKEWPARAM(0, WMNC_DIALOG_EXPAND), 0);\r
- } else {\r
- /* we don't call nc_layout_main_panel() if the dialog is\r
- expanded because posting WMNC_DIALOG_EXPAND to the main\r
- panel results in it getting called anyway. */\r
- nc_layout_main_panel(ncd);\r
- }\r
-\r
- nc_layout_new_cred_window(ncd);\r
-\r
- /* add this to the dialog chain */\r
- khm_add_dialog(hwnd);\r
-\r
- khm_taskbar_add_window(hwnd);\r
-\r
- return TRUE;\r
-}\r
-\r
-/* add a control row supplied by an identity provider */\r
-static void\r
-nc_add_control_row(khui_nc_wnd_data * d, \r
- HWND label,\r
- HWND input,\r
- khui_control_size size)\r
-{\r
- RECT r_row;\r
- RECT r_label;\r
- RECT r_input;\r
- HFONT hf;\r
- HDWP hdefer;\r
-\r
- hf = (HFONT) SendMessage(d->dlg_main, WM_GETFONT, 0, 0);\r
- SendMessage(label, WM_SETFONT, (WPARAM) hf, FALSE);\r
- SendMessage(input, WM_SETFONT, (WPARAM) hf, FALSE);\r
-\r
- CopyRect(&r_row, &d->r_row);\r
- OffsetRect(&r_row, d->r_idspec.left, d->r_idspec.bottom);\r
-\r
- if (size == KHUI_CTRLSIZE_SMALL) {\r
- CopyRect(&r_label, &d->r_n_label);\r
- CopyRect(&r_input, &d->r_n_input);\r
- OffsetRect(&r_label, r_row.left, r_row.top);\r
- OffsetRect(&r_input, r_row.left, r_row.top);\r
- } else if (size == KHUI_CTRLSIZE_HALF) {\r
- CopyRect(&r_label, &d->r_e_label);\r
- CopyRect(&r_input, &d->r_e_input);\r
- OffsetRect(&r_label, r_row.left, r_row.top);\r
- OffsetRect(&r_input, r_row.left, r_row.top);\r
- } else if (size == KHUI_CTRLSIZE_FULL) {\r
- CopyRect(&r_label, &d->r_n_label);\r
- r_label.right = d->r_row.right;\r
- CopyRect(&r_input, &d->r_n_input);\r
- OffsetRect(&r_input, r_row.left, r_row.top);\r
- OffsetRect(&r_input, 0, r_input.bottom);\r
- r_row.bottom += r_input.bottom;\r
- OffsetRect(&r_label, r_row.left, r_row.top);\r
- } else {\r
- SetRectEmpty(&r_label);\r
- SetRectEmpty(&r_input);\r
-#ifdef DEBUG\r
- assert(FALSE);\r
-#endif\r
- return;\r
- }\r
-\r
- hdefer = BeginDeferWindowPos(2);\r
-\r
- if (label)\r
- DeferWindowPos(hdefer, label,\r
- ((d->hwnd_last_idspec != NULL)?\r
- d->hwnd_last_idspec:\r
- HWND_TOP),\r
- r_label.left, r_label.top,\r
- r_label.right - r_label.left,\r
- r_label.bottom - r_label.top,\r
- SWP_NOACTIVATE | SWP_NOOWNERZORDER);\r
-\r
- if (input)\r
- DeferWindowPos(hdefer, input,\r
- (label ? label : ((d->hwnd_last_idspec != NULL)?\r
- d->hwnd_last_idspec:\r
- HWND_TOP)),\r
- r_input.left, r_input.top,\r
- r_input.right - r_input.left,\r
- r_input.bottom - r_input.top,\r
- SWP_NOACTIVATE | SWP_NOOWNERZORDER);\r
-\r
- EndDeferWindowPos(hdefer);\r
-\r
- d->hwnd_last_idspec = (input ? input : label);\r
-\r
- d->r_idspec.bottom = r_row.bottom;\r
-\r
- /* we don't update the layout of the main panel yet, since these\r
- control additions happen before the main panel is displayed. A\r
- call to nc_layout_main_panel() will be made before the main\r
- panel is shown anyway. */\r
-\r
-}\r
-\r
-\r
-static LRESULT \r
-nc_handle_wm_destroy(HWND hwnd,\r
- UINT uMsg,\r
- WPARAM wParam,\r
- LPARAM lParam)\r
-{\r
- khui_nc_wnd_data * d;\r
-\r
- /* remove self from dialog chain */\r
- khm_del_dialog(hwnd);\r
-\r
- khm_taskbar_remove_window(hwnd);\r
-\r
- d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM);\r
-\r
- d->nc->ident_cb(d->nc, WMNC_IDENT_EXIT, NULL, 0, 0, 0);\r
-\r
- if (d->hwnd_notif_label)\r
- DestroyWindow(d->hwnd_notif_label);\r
- if (d->hwnd_notif_aux)\r
- DestroyWindow(d->hwnd_notif_aux);\r
-\r
- if(d->dlg_bb)\r
- DestroyWindow(d->dlg_bb);\r
- if(d->dlg_main)\r
- DestroyWindow(d->dlg_main);\r
-\r
- d->dlg_bb = NULL;\r
- d->dlg_main = NULL;\r
-\r
- PFREE(d);\r
-\r
- return TRUE;\r
-}\r
-\r
-static LRESULT \r
-nc_handle_wm_command(HWND hwnd,\r
- UINT uMsg,\r
- WPARAM wParam,\r
- LPARAM lParam)\r
-{\r
- khui_nc_wnd_data * d;\r
-\r
- d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM);\r
-\r
- switch(HIWORD(wParam)) {\r
- case BN_CLICKED:\r
- switch(LOWORD(wParam)) {\r
-\r
- case IDOK:\r
- d->nc->result = KHUI_NC_RESULT_PROCESS;\r
-\r
- /* fallthrough */\r
-\r
- case IDCANCEL:\r
- /* the default value for d->nc->result is set to\r
- KHUI_NC_RESULT_CANCEL */\r
- d->nc->response = KHUI_NC_RESPONSE_PROCESSING;\r
-\r
- nc_enable_controls(d, FALSE);\r
-\r
- nc_notify_types(d->nc, \r
- KHUI_WM_NC_NOTIFY, \r
- MAKEWPARAM(0,WMNC_DIALOG_PREPROCESS), \r
- (LPARAM) d->nc,\r
- TRUE);\r
-\r
- khui_cw_sync_prompt_values(d->nc);\r
-\r
- khm_cred_dispatch_process_message(d->nc);\r
-\r
- /* we won't know whether to abort or not until we get\r
- feedback from the plugins, even if the command was\r
- to cancel */\r
- {\r
- HWND hw;\r
-\r
- hw = GetDlgItem(d->dlg_main, IDOK);\r
- EnableWindow(hw, FALSE);\r
- hw = GetDlgItem(d->dlg_main, IDCANCEL);\r
- EnableWindow(hw, FALSE);\r
- hw = GetDlgItem(d->dlg_main, IDC_NC_ADVANCED);\r
- EnableWindow(hw, FALSE);\r
- hw = GetDlgItem(d->dlg_bb, IDOK);\r
- EnableWindow(hw, FALSE);\r
- hw = GetDlgItem(d->dlg_bb, IDCANCEL);\r
- EnableWindow(hw, FALSE);\r
- }\r
- return FALSE;\r
-\r
- case IDC_NC_HELP:\r
- khm_html_help(hwnd, NULL, HH_HELP_CONTEXT, IDH_ACTION_NEW_ID);\r
- return FALSE;\r
-\r
- case IDC_NC_BASIC:\r
- case IDC_NC_ADVANCED: \r
- /* the Options button in the main window was clicked. we\r
- respond by expanding the dialog. */\r
- PostMessage(hwnd, KHUI_WM_NC_NOTIFY, \r
- MAKEWPARAM(0, WMNC_DIALOG_EXPAND), 0);\r
- return FALSE;\r
-\r
- case IDC_NC_CREDTEXT: /* credtext link activated */\r
- {\r
- khui_htwnd_link * l;\r
- wchar_t sid[KHUI_MAXCCH_HTLINK_FIELD];\r
- wchar_t sparam[KHUI_MAXCCH_HTLINK_FIELD];\r
- wchar_t * colon;\r
-\r
- l = (khui_htwnd_link *) lParam;\r
-\r
- /* do we have a valid link? */\r
- if(l->id == NULL || l->id_len >= ARRAYLENGTH(sid))\r
- return TRUE; /* nope */\r
-\r
- StringCchCopyN(sid, ARRAYLENGTH(sid), l->id, l->id_len);\r
- sid[l->id_len] = L'\0'; /* just make sure */\r
-\r
- if(l->param != NULL && \r
- l->param_len < ARRAYLENGTH(sparam) &&\r
- l->param_len > 0) {\r
-\r
- StringCchCopyN(sparam, ARRAYLENGTH(sparam),\r
- l->param, l->param_len);\r
- sparam[l->param_len] = L'\0';\r
-\r
- } else {\r
- sparam[0] = L'\0';\r
- }\r
-\r
- /* If the ID is of the form '<credtype>:<link_tag>'\r
- and <credtype> is a valid name of a credentials\r
- type that is participating in the credentials\r
- acquisition process, then we forward the message to\r
- the panel that is providing the UI for that cred\r
- type. We also switch to that panel first, unless\r
- the link is of the form '<credtype>:!<link_tag>'. */\r
-\r
- colon = wcschr(sid, L':');\r
- if (colon != NULL) {\r
- khm_int32 credtype;\r
- khui_new_creds_by_type * t;\r
-\r
- *colon = L'\0';\r
- if (KHM_SUCCEEDED(kcdb_credtype_get_id(sid, &credtype)) &&\r
- KHM_SUCCEEDED(khui_cw_find_type(d->nc, credtype, &t))){\r
- *colon = L':';\r
-\r
- if (t->ordinal != d->current_panel &&\r
- *(colon + 1) != L'!')\r
- PostMessage(hwnd,\r
- KHUI_WM_NC_NOTIFY,\r
- MAKEWPARAM(t->ordinal,\r
- WMNC_DIALOG_SWITCH_PANEL),\r
- 0);\r
-\r
- return SendMessage(t->hwnd_panel,\r
- KHUI_WM_NC_NOTIFY,\r
- MAKEWPARAM(0, WMNC_CREDTEXT_LINK),\r
- lParam);\r
- } else {\r
- *colon = L':';\r
- }\r
- }\r
-\r
- /* if it was for us, then we need to process the message */\r
- if(!_wcsicmp(sid, CTLINKID_SWITCH_PANEL)) {\r
- khm_int32 credtype;\r
- khui_new_creds_by_type * t;\r
-\r
- if (KHM_SUCCEEDED(kcdb_credtype_get_id(sparam, \r
- &credtype)) &&\r
- KHM_SUCCEEDED(khui_cw_find_type(d->nc,\r
- credtype, &t))) {\r
- if (t->ordinal != d->current_panel)\r
- PostMessage(hwnd,\r
- KHUI_WM_NC_NOTIFY,\r
- MAKEWPARAM(t->ordinal,\r
- WMNC_DIALOG_SWITCH_PANEL),\r
- 0);\r
- }\r
- } else if (!_wcsicmp(sid, L"NotDef")) {\r
- d->nc->set_default = FALSE;\r
- nc_update_credtext(d);\r
- } else if (!_wcsicmp(sid, L"MakeDef")) {\r
- d->nc->set_default = TRUE;\r
- nc_update_credtext(d);\r
- }\r
- }\r
- return FALSE;\r
-\r
-#if 0\r
- case NC_BN_SET_DEF_ID:\r
- {\r
- d->nc->set_default =\r
- (IsDlgButtonChecked(d->dlg_main, NC_BN_SET_DEF_ID)\r
- == BST_CHECKED);\r
- }\r
- return FALSE;\r
-#endif\r
- }\r
- break;\r
- }\r
-\r
- return TRUE;\r
-}\r
-\r
-static LRESULT nc_handle_wm_moving(HWND hwnd,\r
- UINT uMsg,\r
- WPARAM wParam,\r
- LPARAM lParam)\r
-{\r
- khui_nc_wnd_data * d;\r
-\r
- d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM);\r
-\r
- nc_notify_types(d->nc, KHUI_WM_NC_NOTIFY, \r
- MAKEWPARAM(0, WMNC_DIALOG_MOVE), (LPARAM) d->nc, TRUE);\r
-\r
- return FALSE;\r
-}\r
-\r
-static LRESULT nc_handle_wm_nc_notify(HWND hwnd,\r
- UINT uMsg,\r
- WPARAM wParam,\r
- LPARAM lParam)\r
-{\r
- khui_nc_wnd_data * d;\r
- int id;\r
-\r
- d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM);\r
-\r
- switch(HIWORD(wParam)) {\r
-\r
- case WMNC_DIALOG_SWITCH_PANEL:\r
- id = LOWORD(wParam);\r
- if(id >= 0 && id <= (int) d->nc->n_types) {\r
- /* one of the tab buttons were pressed */\r
- if(d->current_panel == id) {\r
- return TRUE; /* nothing to do */\r
- }\r
-\r
- d->current_panel = id;\r
-\r
- TabCtrl_SetCurSel(d->tab_wnd, id);\r
- }\r
-\r
- if(d->nc->mode == KHUI_NC_MODE_EXPANDED) {\r
- nc_layout_new_cred_window(d);\r
- return TRUE;\r
- }\r
- /*else*/\r
- /* fallthrough */\r
-\r
- case WMNC_DIALOG_EXPAND:\r
- /* we are switching from basic to advanced or vice versa */\r
-\r
- if (d->nc->mode == KHUI_NC_MODE_EXPANDED) {\r
- d->nc->mode = KHUI_NC_MODE_MINI;\r
- } else {\r
- d->nc->mode = KHUI_NC_MODE_EXPANDED;\r
- }\r
-\r
- /* if we are switching to the advanced mode, we clear any\r
- notifications because we now have a credential text area\r
- for that. */\r
- if (d->nc->mode == KHUI_NC_MODE_EXPANDED)\r
- nc_notify_clear(d);\r
-\r
- nc_layout_main_panel(d);\r
-\r
- nc_layout_new_cred_window(d);\r
-\r
- break;\r
-\r
- case WMNC_DIALOG_SETUP:\r
-\r
- if(d->nc->n_types > 0) {\r
- khm_size i;\r
- for(i=0; i < d->nc->n_types;i++) {\r
-\r
- if (d->nc->types[i]->dlg_proc == NULL) {\r
- d->nc->types[i]->hwnd_panel = NULL;\r
- } else {\r
- /* Create the dialog panel */\r
- d->nc->types[i]->hwnd_panel = \r
- CreateDialogParam(d->nc->types[i]->h_module,\r
- d->nc->types[i]->dlg_template,\r
- d->nc->hwnd,\r
- d->nc->types[i]->dlg_proc,\r
- (LPARAM) d->nc);\r
-\r
-#ifdef DEBUG\r
- assert(d->nc->types[i]->hwnd_panel);\r
-#endif\r
- }\r
- }\r
- }\r
-\r
- break;\r
-\r
- case WMNC_DIALOG_ACTIVATE:\r
- {\r
- wchar_t wname[KCDB_MAXCCH_NAME];\r
- TCITEM tabitem;\r
- khm_int32 t;\r
-\r
- /* About to activate the window. We should add all the\r
- panels to the tab control. */\r
-\r
-#ifdef DEBUG\r
- assert(d->tab_wnd != NULL);\r
-#endif\r
-\r
- ZeroMemory(&tabitem, sizeof(tabitem));\r
-\r
- tabitem.mask = TCIF_PARAM | TCIF_TEXT;\r
-\r
- LoadString(khm_hInstance, IDS_NC_IDENTITY, \r
- wname, ARRAYLENGTH(wname));\r
-\r
- tabitem.pszText = wname;\r
- tabitem.lParam = 0; /* ordinal */\r
-\r
- TabCtrl_InsertItem(d->tab_wnd, 0, &tabitem);\r
-\r
- khui_cw_lock_nc(d->nc);\r
-\r
- if(d->nc->n_types > 0) {\r
- khm_size i;\r
-\r
- /* We should sort the tabs first. See\r
- nc_tab_sort_func() for sort criteria. */\r
- qsort(d->nc->types, \r
- d->nc->n_types, \r
- sizeof(*(d->nc->types)), \r
- nc_tab_sort_func);\r
-\r
- for(i=0; i < d->nc->n_types;i++) {\r
-\r
- d->nc->types[i]->ordinal = i + 1;\r
-\r
- if(d->nc->types[i]->name)\r
- tabitem.pszText = d->nc->types[i]->name;\r
- else {\r
- khm_size cbsize;\r
-\r
- cbsize = sizeof(wname);\r
-\r
- if(KHM_FAILED\r
- (kcdb_credtype_describe\r
- (d->nc->types[i]->type, \r
- wname, \r
- &cbsize, \r
- KCDB_TS_SHORT))) {\r
-\r
-#ifdef DEBUG\r
- assert(FALSE);\r
-#endif\r
- wname[0] = L'\0';\r
-\r
- }\r
-\r
- tabitem.pszText = wname;\r
-\r
- }\r
-\r
- tabitem.lParam = d->nc->types[i]->ordinal;\r
-\r
- TabCtrl_InsertItem(d->tab_wnd, d->nc->types[i]->ordinal,\r
- &tabitem);\r
- }\r
- }\r
-\r
- khui_cw_unlock_nc(d->nc);\r
-\r
- nc_update_credtext(d);\r
-\r
- TabCtrl_SetCurSel(d->tab_wnd, 0); /* the first selected\r
- tab is the main\r
- panel. */\r
-\r
- /* bring the window to the top, if necessary */\r
- if (KHM_SUCCEEDED(khc_read_int32(NULL,\r
- L"CredWindow\\Windows\\NewCred\\ForceToTop",\r
- &t)) &&\r
-\r
- t != 0) {\r
- /* it used to be that the above condition also called\r
- !khm_is_dialog_active() to find out whether there\r
- was a dialog active. If there was, we wouldn't try\r
- to bring the new cred window to the foreground. But\r
- that was not the behavior we want. */\r
-\r
- /* if the main window is not visible, then the SetWindowPos()\r
- call is sufficient to bring the new creds window to the\r
- top. However, if the main window is visible but not\r
- active, the main window needs to be activated before a\r
- child window can be activated. */\r
- khm_activate_main_window();\r
-\r
- SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0,\r
- (SWP_NOMOVE | SWP_NOSIZE));\r
- }\r
-\r
- ShowWindow(hwnd, SW_SHOWNOACTIVATE);\r
-\r
- /* we don't enable animations until a specific timeout\r
- elapses after showing the window. We don't need to\r
- animate any size changes if the user has barely had a\r
- chance to notice the original size. This prevents the\r
- new cred window from appearing in an animated state. */\r
- SetTimer(hwnd, NC_TIMER_ENABLEANIMATE, ENABLEANIMATE_TIMEOUT, NULL);\r
-\r
- SetFocus(hwnd);\r
-\r
- if (d->nc->n_identities == 0)\r
- break;\r
- /* else */\r
- /* fallthrough */\r
- }\r
-\r
- case WMNC_IDENTITY_CHANGE:\r
- {\r
- BOOL okEnable = FALSE;\r
-\r
- nc_notify_types(d->nc, KHUI_WM_NC_NOTIFY,\r
- MAKEWPARAM(0, WMNC_IDENTITY_CHANGE), (LPARAM) d->nc,\r
- TRUE);\r
-\r
- if (d->nc->subtype == KMSG_CRED_NEW_CREDS &&\r
- d->nc->n_identities > 0 &&\r
- d->nc->identities[0]) {\r
- khm_int32 f = 0;\r
-\r
- kcdb_identity_get_flags(d->nc->identities[0], &f);\r
-\r
- if (!(f & KCDB_IDENT_FLAG_DEFAULT)) {\r
- d->nc->set_default = FALSE;\r
- }\r
- }\r
-\r
- nc_update_credtext(d);\r
-\r
- }\r
- break;\r
-\r
- case WMNC_TYPE_STATE:\r
- /* fallthrough */\r
- case WMNC_UPDATE_CREDTEXT:\r
- nc_update_credtext(d);\r
- break;\r
-\r
- case WMNC_CLEAR_PROMPTS:\r
- {\r
- khm_size i;\r
-\r
- khui_cw_lock_nc(d->nc);\r
-\r
- if(d->hwnd_banner != NULL) {\r
- DestroyWindow(d->hwnd_banner);\r
- d->hwnd_banner = NULL;\r
- }\r
-\r
- if(d->hwnd_name != NULL) {\r
- DestroyWindow(d->hwnd_name);\r
- d->hwnd_name = NULL;\r
- }\r
-\r
- for(i=0;i<d->nc->n_prompts;i++) {\r
- if(!(d->nc->prompts[i]->flags & \r
- KHUI_NCPROMPT_FLAG_STOCK)) {\r
- if(d->nc->prompts[i]->hwnd_static != NULL)\r
- DestroyWindow(d->nc->prompts[i]->hwnd_static);\r
-\r
- if(d->nc->prompts[i]->hwnd_edit != NULL)\r
- DestroyWindow(d->nc->prompts[i]->hwnd_edit);\r
- }\r
-\r
- d->nc->prompts[i]->hwnd_static = NULL;\r
- d->nc->prompts[i]->hwnd_edit = NULL;\r
- }\r
-\r
- khui_cw_unlock_nc(d->nc);\r
-\r
- SetRectEmpty(&d->r_custprompt);\r
-\r
- nc_layout_main_panel(d);\r
-\r
- nc_layout_new_cred_window(d);\r
- }\r
- break;\r
-\r
- case WMNC_SET_PROMPTS:\r
- {\r
- khm_size i;\r
- int y;\r
- HWND hw, hw_prev;\r
- HFONT hf, hfold;\r
- HDC hdc;\r
- BOOL use_large_lables = FALSE;\r
-\r
- /* we assume that WMNC_CLEAR_PROMPTS has already been\r
- received */\r
-\r
-#ifdef DEBUG\r
- assert(IsRectEmpty(&d->r_custprompt));\r
-#endif\r
-\r
- khui_cw_lock_nc(d->nc);\r
-\r
-#if 0\r
- /* special case, we have one prompt and it is a password\r
- prompt. very common */\r
- if(d->nc->n_prompts == 1 && \r
- d->nc->prompts[0]->type == KHUI_NCPROMPT_TYPE_PASSWORD) {\r
-\r
- hw = GetDlgItem(d->dlg_main, IDC_NC_PASSWORD);\r
- EnableWindow(hw, TRUE);\r
-\r
- d->nc->prompts[0]->flags |= KHUI_NCPROMPT_FLAG_STOCK;\r
- d->nc->prompts[0]->hwnd_edit = hw;\r
- d->nc->prompts[0]->hwnd_static = NULL; /* don't care */\r
-\r
- khui_cw_unlock_nc(d->nc);\r
- break;\r
- }\r
-#endif\r
- /* for everything else */\r
-\r
- y = d->r_idspec.bottom;\r
-\r
- d->r_custprompt.left = d->r_area.left;\r
- d->r_custprompt.right = d->r_area.right;\r
- d->r_custprompt.top = y;\r
-\r
- hf = (HFONT) SendMessage(d->dlg_main, WM_GETFONT, 0, 0);\r
-\r
- if (d->nc->pname != NULL) {\r
- hw =\r
- CreateWindowEx\r
- (0,\r
- L"STATIC",\r
- d->nc->pname,\r
- SS_SUNKEN | WS_CHILD,\r
- d->r_area.left, y,\r
- d->r_row.right, \r
- d->r_n_label.bottom - d->r_n_label.top,\r
- d->dlg_main,\r
- NULL,\r
- khm_hInstance,\r
- NULL);\r
-\r
-#ifdef DEBUG\r
- assert(hw);\r
-#endif\r
- d->hwnd_name = hw;\r
- SendMessage(hw, WM_SETFONT, (WPARAM)hf, (LPARAM) TRUE);\r
- ShowWindow(hw, SW_SHOW);\r
-\r
- y += d->r_n_label.bottom - d->r_n_label.top;\r
- }\r
-\r
- if (d->nc->banner != NULL) {\r
- hw = \r
- CreateWindowEx\r
- (0,\r
- L"STATIC",\r
- d->nc->banner,\r
- WS_CHILD,\r
- d->r_area.left, y,\r
- d->r_row.right, d->r_row.bottom,\r
- d->dlg_main,\r
- NULL,\r
- khm_hInstance,\r
- NULL);\r
-#ifdef DEBUG\r
- assert(hw);\r
-#endif\r
- d->hwnd_banner = hw;\r
- SendMessage(hw, WM_SETFONT, (WPARAM)hf, (LPARAM)TRUE);\r
- ShowWindow(hw, SW_SHOW);\r
- y += d->r_row.bottom;\r
- }\r
-\r
- hw_prev = d->hwnd_last_idspec;\r
-\r
- hdc = GetWindowDC(d->dlg_main);\r
- hfold = SelectObject(hdc,hf);\r
-\r
- /* first do a trial run and see if we should use the\r
- larger text labels or not. This is so that all the\r
- labels and input controls align properly. */\r
- for (i=0; i < d->nc->n_prompts; i++) {\r
- if (d->nc->prompts[i]->prompt != NULL) {\r
- SIZE s;\r
-\r
- GetTextExtentPoint32(hdc, \r
- d->nc->prompts[i]->prompt, \r
- (int) wcslen(d->nc->prompts[i]->prompt),\r
- &s);\r
-\r
- if(s.cx >= d->r_n_label.right - d->r_n_label.left) {\r
- use_large_lables = TRUE;\r
- break;\r
- }\r
- }\r
- }\r
-\r
- for(i=0; i<d->nc->n_prompts; i++) {\r
- RECT pr, er;\r
- SIZE s;\r
- int dy;\r
-\r
- if(d->nc->prompts[i]->prompt != NULL) {\r
- GetTextExtentPoint32(hdc, \r
- d->nc->prompts[i]->prompt, \r
- (int) wcslen(d->nc->prompts[i]->prompt),\r
- &s);\r
- if(s.cx < d->r_n_label.right - d->r_n_label.left &&\r
- !use_large_lables) {\r
- CopyRect(&pr, &d->r_n_label);\r
- CopyRect(&er, &d->r_n_input);\r
- dy = d->r_row.bottom;\r
- } else if(s.cx <\r
- d->r_e_label.right - d->r_e_label.left) {\r
- CopyRect(&pr, &d->r_e_label);\r
- CopyRect(&er, &d->r_e_input);\r
- dy = d->r_row.bottom;\r
- } else {\r
- /* oops. the prompt doesn't fit in our\r
- controls. we need to use up two lines */\r
- pr.left = 0;\r
- pr.right = d->r_row.right;\r
- pr.top = 0;\r
- pr.bottom = d->r_n_label.bottom - \r
- d->r_n_label.top;\r
- CopyRect(&er, &d->r_n_input);\r
- OffsetRect(&er, 0, pr.bottom);\r
- dy = er.bottom + (d->r_row.bottom - \r
- d->r_n_input.bottom);\r
- }\r
- } else {\r
- SetRectEmpty(&pr);\r
- CopyRect(&er, &d->r_n_input);\r
- dy = d->r_row.bottom;\r
- }\r
-\r
- if(IsRectEmpty(&pr)) {\r
- d->nc->prompts[i]->hwnd_static = NULL;\r
- } else {\r
- OffsetRect(&pr, d->r_area.left, y);\r
-\r
- hw = CreateWindowEx\r
- (0,\r
- L"STATIC",\r
- d->nc->prompts[i]->prompt,\r
- WS_CHILD,\r
- pr.left, pr.top,\r
- pr.right - pr.left, pr.bottom - pr.top,\r
- d->dlg_main,\r
- NULL,\r
- khm_hInstance,\r
- NULL);\r
-#ifdef DEBUG\r
- assert(hw);\r
-#endif\r
-\r
- SendMessage(hw, WM_SETFONT, \r
- (WPARAM) hf, (LPARAM) TRUE);\r
-\r
- SetWindowPos(hw, hw_prev,\r
- 0, 0, 0, 0,\r
- SWP_NOACTIVATE | SWP_NOMOVE |\r
- SWP_NOOWNERZORDER | SWP_NOSIZE |\r
- SWP_SHOWWINDOW);\r
-\r
- d->nc->prompts[i]->hwnd_static = hw;\r
- hw_prev = hw;\r
- }\r
-\r
- OffsetRect(&er, d->r_area.left, y);\r
-\r
- hw = CreateWindowEx\r
- (0,\r
- L"EDIT",\r
- (d->nc->prompts[i]->def ? \r
- d->nc->prompts[i]->def : L""),\r
- WS_CHILD | WS_TABSTOP |\r
- WS_BORDER |\r
- ((d->nc->prompts[i]->flags & \r
- KHUI_NCPROMPT_FLAG_HIDDEN)? ES_PASSWORD:0),\r
- er.left, er.top,\r
- er.right - er.left, er.bottom - er.top,\r
- d->dlg_main,\r
- NULL,\r
- khm_hInstance,\r
- NULL);\r
-\r
-#ifdef DEBUG\r
- assert(hw);\r
-#endif\r
-\r
- SendMessage(hw, WM_SETFONT, \r
- (WPARAM) hf, (LPARAM) TRUE);\r
-\r
- SetWindowPos(hw, hw_prev,\r
- 0, 0, 0, 0, \r
- SWP_NOACTIVATE | SWP_NOMOVE | \r
- SWP_NOOWNERZORDER | SWP_NOSIZE | \r
- SWP_SHOWWINDOW);\r
-\r
- SendMessage(hw, EM_SETLIMITTEXT,\r
- KHUI_MAXCCH_PROMPT_VALUE -1,\r
- 0);\r
-\r
- d->nc->prompts[i]->hwnd_edit = hw;\r
-\r
- hw_prev = hw;\r
-\r
- y += dy;\r
- }\r
-\r
- if (d->nc->n_prompts > 0 &&\r
- d->nc->prompts[0]->hwnd_edit) {\r
-\r
- PostMessage(d->dlg_main, WM_NEXTDLGCTL,\r
- (WPARAM) d->nc->prompts[0]->hwnd_edit,\r
- MAKELPARAM(TRUE, 0));\r
-\r
- }\r
-\r
- SelectObject(hdc, hfold);\r
- ReleaseDC(d->dlg_main, hdc);\r
-\r
- khui_cw_unlock_nc(d->nc);\r
-\r
- d->r_custprompt.bottom = y;\r
-\r
- if (d->r_custprompt.bottom == d->r_custprompt.top)\r
- SetRectEmpty(&d->r_custprompt);\r
-\r
- nc_layout_main_panel(d);\r
-\r
- nc_layout_new_cred_window(d);\r
- }\r
- break;\r
-\r
- case WMNC_DIALOG_PROCESS_COMPLETE:\r
- {\r
- khui_new_creds * nc;\r
-\r
- nc = d->nc;\r
-\r
- nc->response &= ~KHUI_NC_RESPONSE_PROCESSING;\r
-\r
- if(nc->response & KHUI_NC_RESPONSE_NOEXIT) {\r
- HWND hw;\r
-\r
- nc_enable_controls(d, TRUE);\r
-\r
- /* reset state */\r
- nc->result = KHUI_NC_RESULT_CANCEL;\r
-\r
- hw = GetDlgItem(d->dlg_main, IDOK);\r
- EnableWindow(hw, TRUE);\r
- hw = GetDlgItem(d->dlg_main, IDCANCEL);\r
- EnableWindow(hw, TRUE);\r
- hw = GetDlgItem(d->dlg_main, IDC_NC_ADVANCED);\r
- EnableWindow(hw, TRUE);\r
- hw = GetDlgItem(d->dlg_bb, IDOK);\r
- EnableWindow(hw, TRUE);\r
- hw = GetDlgItem(d->dlg_bb, IDCANCEL);\r
- EnableWindow(hw, TRUE);\r
-\r
- nc_clear_password_fields(d);\r
-\r
- return TRUE;\r
- }\r
-\r
- DestroyWindow(hwnd);\r
-\r
- kmq_post_message(KMSG_CRED, KMSG_CRED_END, 0, (void *) nc);\r
- }\r
- break;\r
-\r
- /* MUST be called with SendMessage */\r
- case WMNC_ADD_CONTROL_ROW:\r
- {\r
- khui_control_row * row;\r
-\r
- row = (khui_control_row *) lParam;\r
-\r
-#ifdef DEBUG\r
- assert(row->label);\r
- assert(row->input);\r
-#endif\r
-\r
- nc_add_control_row(d, row->label, row->input, row->size);\r
- }\r
- break;\r
-\r
- case WMNC_UPDATE_LAYOUT:\r
- {\r
-\r
- RECT r_client;\r
- khm_int32 animate;\r
- khm_int32 steps;\r
- khm_int32 timeout;\r
-\r
- /* We are already adjusting the size of the window. The\r
- next time the timer fires, it will notice if the target\r
- size has changed. */\r
- if (d->size_changing)\r
- return TRUE;\r
-\r
- GetClientRect(hwnd, &r_client);\r
-\r
- if ((r_client.right - r_client.left ==\r
- d->r_required.right - d->r_required.left) &&\r
- (r_client.bottom - r_client.top ==\r
- d->r_required.bottom - d->r_required.top)) {\r
-\r
- /* the window is already at the right size */\r
- return TRUE;\r
-\r
- }\r
-\r
- if (!IsWindowVisible(hwnd)) {\r
- /* The window is not visible yet. There's no need to\r
- animate anything. */\r
-\r
- animate = FALSE;\r
-\r
- } else if (KHM_FAILED(khc_read_int32(NULL,\r
- L"CredWindow\\Windows\\NewCred\\AnimateSizeChanges",\r
- &animate))) {\r
-#ifdef DEBUG\r
- assert(FALSE);\r
-#endif\r
- animate = TRUE;\r
- }\r
-\r
- /* if we aren't animating the window resize, then we just\r
- do it in one call. */\r
- if (!animate || !d->animation_enabled) {\r
- RECT r_window;\r
-\r
- CopyRect(&r_window, &d->r_required);\r
- AdjustWindowRectEx(&r_window, NC_WINDOW_STYLES, FALSE,\r
- NC_WINDOW_EX_STYLES);\r
-\r
- SetWindowPos(hwnd, NULL, 0, 0,\r
- r_window.right - r_window.left,\r
- r_window.bottom - r_window.top,\r
- SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER |\r
- SWP_NOZORDER);\r
-\r
- return TRUE;\r
- }\r
-\r
- if (KHM_FAILED(khc_read_int32(NULL,\r
- L"CredWindow\\Windows\\NewCred\\AnimationSteps",\r
- &steps))) {\r
-#ifdef DEBUG\r
- assert(FALSE);\r
-#endif\r
- steps = NC_SZ_STEPS_DEF;\r
- } else {\r
-\r
- if (steps < NC_SZ_STEPS_MIN)\r
- steps = NC_SZ_STEPS_MIN;\r
- else if (steps > NC_SZ_STEPS_MAX)\r
- steps = NC_SZ_STEPS_MAX;\r
-\r
- }\r
-\r
- if (KHM_FAILED(khc_read_int32(NULL,\r
- L"CredWindow\\Windows\\NewCred\\AnimationStepTimeout",\r
- &timeout))) {\r
-#ifdef DEBUG\r
- assert(FALSE);\r
-#endif\r
- timeout = NC_SZ_TIMEOUT_DEF;\r
- } else {\r
-\r
- if (timeout < NC_SZ_TIMEOUT_MIN)\r
- timeout = NC_SZ_TIMEOUT_MIN;\r
- else if (timeout > NC_SZ_TIMEOUT_MAX)\r
- timeout = NC_SZ_TIMEOUT_MAX;\r
-\r
- }\r
-\r
- CopyRect(&d->sz_ch_source, &r_client);\r
- OffsetRect(&d->sz_ch_source, -d->sz_ch_source.left, -d->sz_ch_source.top);\r
- CopyRect(&d->sz_ch_target, &d->r_required);\r
- OffsetRect(&d->sz_ch_target, -d->sz_ch_target.left, -d->sz_ch_target.top);\r
- d->sz_ch_increment = 0;\r
- d->sz_ch_max = steps;\r
- d->sz_ch_timeout = timeout;\r
- d->size_changing = TRUE;\r
-\r
- SetTimer(hwnd, NC_TIMER_SIZER, timeout, NULL);\r
- }\r
- break;\r
- } /* switch(HIWORD(wParam)) */\r
-\r
- return TRUE;\r
-}\r
-\r
-static LRESULT nc_handle_wm_timer(HWND hwnd,\r
- UINT uMsg,\r
- WPARAM wParam,\r
- LPARAM lParam) {\r
- khui_nc_wnd_data * d;\r
-\r
- d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM);\r
-\r
- if (wParam == NC_TIMER_SIZER) {\r
-\r
- RECT r_now;\r
-\r
- /* are we done with this sizing operation? */\r
- if (!d->size_changing ||\r
- d->sz_ch_increment >= d->sz_ch_max) {\r
-\r
- d->size_changing = FALSE;\r
- KillTimer(hwnd, NC_TIMER_SIZER);\r
- return 0;\r
- }\r
-\r
- /* have the requirements changed while we were processing the\r
- sizing operation? */\r
- if ((d->r_required.right - d->r_required.left !=\r
- d->sz_ch_target.right)\r
-\r
- ||\r
-\r
- (d->r_required.bottom - d->r_required.top !=\r
- d->sz_ch_target.bottom)) {\r
-\r
- /* the target size has changed. we need to restart the\r
- sizing operation. */\r
-\r
- RECT r_client;\r
-\r
- GetClientRect(hwnd, &r_client);\r
-\r
- CopyRect(&d->sz_ch_source, &r_client);\r
- OffsetRect(&d->sz_ch_source, -d->sz_ch_source.left, -d->sz_ch_source.top);\r
- CopyRect(&d->sz_ch_target, &d->r_required);\r
- OffsetRect(&d->sz_ch_target, -d->sz_ch_target.left, -d->sz_ch_target.top);\r
- d->sz_ch_increment = 0;\r
-\r
- /* leave the other fields alone */\r
-\r
-#ifdef DEBUG\r
- assert(d->sz_ch_max >= NC_SZ_STEPS_MIN);\r
- assert(d->sz_ch_max <= NC_SZ_STEPS_MAX);\r
- assert(d->sz_ch_timeout >= NC_SZ_TIMEOUT_MIN);\r
- assert(d->sz_ch_timeout <= NC_SZ_TIMEOUT_MAX);\r
- assert(d->size_changing);\r
-#endif\r
- }\r
-\r
- /* we are going to do the next increment */\r
- d->sz_ch_increment ++;\r
-\r
- /* now, figure out the size of the client area for this\r
- step */\r
-\r
- r_now.left = 0;\r
- r_now.top = 0;\r
-\r
-#define PROPORTION(v1, v2, i, s) (((v1) * ((s) - (i)) + (v2) * (i)) / (s))\r
-\r
- r_now.right = PROPORTION(d->sz_ch_source.right, d->sz_ch_target.right,\r
- d->sz_ch_increment, d->sz_ch_max);\r
-\r
- r_now.bottom = PROPORTION(d->sz_ch_source.bottom, d->sz_ch_target.bottom,\r
- d->sz_ch_increment, d->sz_ch_max);\r
-\r
-#undef PROPORTION\r
-\r
-#ifdef DEBUG\r
- {\r
- long dx = (r_now.right - d->sz_ch_target.right) *\r
- (d->sz_ch_source.right - d->sz_ch_target.right);\r
-\r
- long dy = (r_now.bottom - d->sz_ch_target.bottom) *\r
- (d->sz_ch_source.bottom - d->sz_ch_target.bottom);\r
-\r
- if (dx < 0 || dy < 0) {\r
- KillTimer(hwnd, NC_TIMER_SIZER);\r
- assert(dx >= 0);\r
- assert(dy >= 0);\r
- SetTimer(hwnd, NC_TIMER_SIZER, d->sz_ch_timeout, NULL);\r
- }\r
- }\r
-#endif\r
-\r
- AdjustWindowRectEx(&r_now, NC_WINDOW_STYLES, FALSE,\r
- NC_WINDOW_EX_STYLES);\r
-\r
- SetWindowPos(hwnd, NULL,\r
- 0, 0,\r
- r_now.right - r_now.left,\r
- r_now.bottom - r_now.top,\r
- SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER |\r
- SWP_NOZORDER);\r
-\r
- /* and now we wait for the next timer message */\r
-\r
- return 0;\r
- } else if (wParam == NC_TIMER_ENABLEANIMATE) {\r
-\r
- d->animation_enabled = TRUE;\r
- KillTimer(hwnd, NC_TIMER_ENABLEANIMATE);\r
- }\r
-\r
- return 0;\r
-}\r
-\r
-static LRESULT nc_handle_wm_notify(HWND hwnd,\r
- UINT uMsg,\r
- WPARAM wParam,\r
- LPARAM lParam) {\r
-\r
- LPNMHDR nmhdr;\r
- khui_nc_wnd_data * d;\r
-\r
- d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM);\r
- nmhdr = (LPNMHDR) lParam;\r
-\r
- if (nmhdr->code == TCN_SELCHANGE) {\r
- /* the current tab has changed. */\r
- int idx;\r
- TCITEM tcitem;\r
-\r
- idx = TabCtrl_GetCurSel(d->tab_wnd);\r
- ZeroMemory(&tcitem, sizeof(tcitem));\r
-\r
- tcitem.mask = TCIF_PARAM;\r
- TabCtrl_GetItem(d->tab_wnd, idx, &tcitem);\r
-\r
- d->current_panel = (int) tcitem.lParam;\r
-\r
- nc_layout_new_cred_window(d);\r
-\r
- return TRUE;\r
- }\r
-\r
- return FALSE;\r
-}\r
-\r
-static LRESULT nc_handle_wm_help(HWND hwnd,\r
- UINT uMsg,\r
- WPARAM wParam,\r
- LPARAM lParam) {\r
- static DWORD ctxids[] = {\r
- NC_TS_CTRL_ID_MIN, IDH_NC_TABMAIN,\r
- NC_TS_CTRL_ID_MIN + 1, IDH_NC_TABBUTTON,\r
- NC_TS_CTRL_ID_MIN + 2, IDH_NC_TABBUTTON,\r
- NC_TS_CTRL_ID_MIN + 3, IDH_NC_TABBUTTON,\r
- NC_TS_CTRL_ID_MIN + 4, IDH_NC_TABBUTTON,\r
- NC_TS_CTRL_ID_MIN + 5, IDH_NC_TABBUTTON,\r
- NC_TS_CTRL_ID_MIN + 6, IDH_NC_TABBUTTON,\r
- NC_TS_CTRL_ID_MIN + 7, IDH_NC_TABBUTTON,\r
- IDOK, IDH_NC_OK,\r
- IDCANCEL, IDH_NC_CANCEL,\r
- IDC_NC_HELP, IDH_NC_HELP,\r
- IDC_NC_ADVANCED, IDH_NC_ADVANCED,\r
- IDC_NC_CREDTEXT, IDH_NC_CREDWND,\r
- 0\r
- };\r
-\r
- HELPINFO * hlp;\r
- HWND hw = NULL;\r
- HWND hw_ctrl;\r
- khui_nc_wnd_data * d;\r
-\r
- d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM);\r
-\r
- hlp = (HELPINFO *) lParam;\r
-\r
- if (d->nc->subtype != KMSG_CRED_NEW_CREDS &&\r
- d->nc->subtype != KMSG_CRED_PASSWORD)\r
- return TRUE;\r
-\r
- if (hlp->iContextType != HELPINFO_WINDOW)\r
- return TRUE;\r
-\r
- if (hlp->hItemHandle != NULL &&\r
- hlp->hItemHandle != hwnd) {\r
- DWORD id;\r
- int i;\r
-\r
- hw_ctrl =hlp->hItemHandle;\r
-\r
- id = GetWindowLong(hw_ctrl, GWL_ID);\r
- for (i=0; ctxids[i] != 0; i += 2)\r
- if (ctxids[i] == id)\r
- break;\r
-\r
- if (ctxids[i] != 0)\r
- hw = khm_html_help(hw_ctrl,\r
- ((d->nc->subtype == KMSG_CRED_NEW_CREDS)?\r
- L"::popups_newcreds.txt":\r
- L"::popups_password.txt"),\r
- HH_TP_HELP_WM_HELP,\r
- (DWORD_PTR) ctxids);\r
- }\r
-\r
- if (hw == NULL) {\r
- khm_html_help(hwnd, NULL, HH_HELP_CONTEXT,\r
- ((d->nc->subtype == KMSG_CRED_NEW_CREDS)?\r
- IDH_ACTION_NEW_ID: IDH_ACTION_PASSWD_ID));\r
- }\r
-\r
- return TRUE;\r
-}\r
-\r
-static LRESULT CALLBACK nc_window_proc(HWND hwnd,\r
- UINT uMsg,\r
- WPARAM wParam,\r
- LPARAM lParam)\r
-{\r
- switch(uMsg) {\r
- case WM_CREATE:\r
- return nc_handle_wm_create(hwnd, uMsg, wParam, lParam);\r
-\r
- case WM_DESTROY:\r
- return nc_handle_wm_destroy(hwnd, uMsg, wParam, lParam);\r
-\r
- case WM_COMMAND:\r
- return nc_handle_wm_command(hwnd, uMsg, wParam, lParam);\r
-\r
- case WM_NOTIFY:\r
- return nc_handle_wm_notify(hwnd, uMsg, wParam, lParam);\r
-\r
- case WM_MOVE:\r
- case WM_MOVING:\r
- return nc_handle_wm_moving(hwnd, uMsg, wParam, lParam);\r
-\r
- case WM_TIMER:\r
- return nc_handle_wm_timer(hwnd, uMsg, wParam, lParam);\r
-\r
- case WM_HELP:\r
- return nc_handle_wm_help(hwnd, uMsg, wParam, lParam);\r
-\r
- case KHUI_WM_NC_NOTIFY:\r
- return nc_handle_wm_nc_notify(hwnd, uMsg, wParam, lParam);\r
- }\r
-\r
- /* Note that this is technically a dialog box */\r
- return DefDlgProc(hwnd, uMsg, wParam, lParam);\r
-}\r
-\r
-void khm_register_newcredwnd_class(void)\r
-{\r
- WNDCLASSEX wcx;\r
-\r
- wcx.cbSize = sizeof(wcx);\r
- wcx.style = CS_DBLCLKS | CS_OWNDC;\r
- wcx.lpfnWndProc = nc_window_proc;\r
- wcx.cbClsExtra = 0;\r
- wcx.cbWndExtra = DLGWINDOWEXTRA + sizeof(LONG_PTR);\r
- wcx.hInstance = khm_hInstance;\r
- wcx.hIcon = LoadIcon(khm_hInstance, MAKEINTRESOURCE(IDI_MAIN_APP));\r
- wcx.hCursor = LoadCursor((HINSTANCE) NULL, IDC_ARROW);\r
- wcx.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1);\r
- wcx.lpszMenuName = NULL;\r
- wcx.lpszClassName = KHUI_NEWCREDWND_CLASS;\r
- wcx.hIconSm = NULL;\r
-\r
- khui_newcredwnd_cls = RegisterClassEx(&wcx);\r
-}\r
-\r
-void khm_unregister_newcredwnd_class(void)\r
-{\r
- UnregisterClass((LPWSTR) khui_newcredwnd_cls, khm_hInstance);\r
-}\r
-\r
-HWND khm_create_newcredwnd(HWND parent, khui_new_creds * c)\r
-{\r
- wchar_t wtitle[256];\r
- HWND hwnd;\r
-\r
- if (c->window_title == NULL) {\r
- if (c->subtype == KMSG_CRED_PASSWORD)\r
- LoadString(khm_hInstance, \r
- IDS_WT_PASSWORD,\r
- wtitle,\r
- ARRAYLENGTH(wtitle));\r
- else\r
- LoadString(khm_hInstance, \r
- IDS_WT_NEW_CREDS,\r
- wtitle,\r
- ARRAYLENGTH(wtitle));\r
- }\r
-\r
- hwnd = CreateWindowEx(NC_WINDOW_EX_STYLES,\r
- MAKEINTATOM(khui_newcredwnd_cls),\r
- ((c->window_title)?c->window_title: wtitle),\r
- NC_WINDOW_STYLES,\r
- 0,0,400,400, /* bogus values. the window\r
- is going to resize and\r
- reposition itself\r
- anyway */\r
- parent,\r
- NULL,\r
- khm_hInstance,\r
- (LPVOID) c);\r
-\r
-#ifdef DEBUG\r
- assert(hwnd != NULL);\r
-#endif\r
-\r
- /* note that the window is not visible yet. That's because, at\r
- this point we don't know what the panels are */\r
-\r
- return hwnd;\r
-}\r
-\r
-void khm_prep_newcredwnd(HWND hwnd)\r
-{\r
- SendMessage(hwnd, KHUI_WM_NC_NOTIFY, \r
- MAKEWPARAM(0, WMNC_DIALOG_SETUP), 0);\r
-}\r
-\r
-void khm_show_newcredwnd(HWND hwnd)\r
-{\r
- /* add all the panels in and prep UI */\r
- PostMessage(hwnd, KHUI_WM_NC_NOTIFY, \r
- MAKEWPARAM(0, WMNC_DIALOG_ACTIVATE), 0);\r
-}\r
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ * Copyright (c) 2007 Secure Endpoints Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+/* Include the OEMRESOURCE constants for locating standard icon
+ resources. */
+#define OEMRESOURCE
+
+#include<khmapp.h>
+#include<assert.h>
+
+ATOM khui_newcredwnd_cls;
+
+/* forward dcl */
+static void
+nc_position_credtext(khui_nc_wnd_data * d);
+
+/* Common dialog procedure used by the main credential panel
+ (IDD_NC_NEWCRED) and the button bar (IDC_NC_BBAR). */
+
+static void
+nc_layout_main_panel(khui_nc_wnd_data * d);
+
+static void
+nc_layout_new_cred_window(khui_nc_wnd_data * d);
+
+static INT_PTR CALLBACK
+nc_common_dlg_proc(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ switch(uMsg) {
+ case WM_INITDIALOG:
+ {
+ khui_nc_wnd_data * d;
+
+ d = (khui_nc_wnd_data *) lParam;
+
+#pragma warning(push)
+#pragma warning(disable: 4244)
+ SetWindowLongPtr(hwnd, DWLP_USER, lParam);
+#pragma warning(pop)
+
+ if (d->nc->subtype == KMSG_CRED_PASSWORD) {
+ ShowWindow(GetDlgItem(hwnd, IDC_NC_ADVANCED),
+ SW_HIDE);
+ }
+ }
+ return TRUE;
+
+ case WM_COMMAND:
+ {
+ int ctrl_id;
+
+ ctrl_id = LOWORD(wParam);
+ if (ctrl_id < KHUI_CW_ID_MIN ||
+ ctrl_id > KHUI_CW_ID_MAX) {
+ /* pump it to the parent */
+ PostMessage(GetParent(hwnd), WM_COMMAND, wParam, lParam);
+ return TRUE;
+ } /* else we allow the message to fall through and get
+ passed into the identity provider's message
+ handler. */
+ }
+ break;
+
+ case KHUI_WM_NC_NOTIFY:
+ {
+ khui_nc_wnd_data * d;
+ d = (khui_nc_wnd_data *)(LONG_PTR)
+ GetWindowLongPtr(hwnd, DWLP_USER);
+
+ /* message sent by parent to notify us of something */
+ switch(HIWORD(wParam)) {
+ case WMNC_DIALOG_EXPAND:
+ /* fallthrough */
+ case WMNC_UPDATE_LAYOUT:
+ if(hwnd == d->dlg_main) {
+
+ nc_layout_main_panel(d);
+
+ return TRUE;
+ }
+ break; /* nop */
+ }
+ }
+ return TRUE;
+ }
+
+ /* check if we have a wnd_data, and if so pass the message on to
+ the identity provider callback. */
+ {
+ khui_nc_wnd_data * d;
+
+ d = (khui_nc_wnd_data *) (LONG_PTR)
+ GetWindowLongPtr(hwnd, DWLP_USER);
+
+ /* TODO: filter out and forward only the messages that
+ originated or pertain to the identity selection
+ controls. */
+ if (d && d->nc && d->nc->ident_cb) {
+ return d->nc->ident_cb(d->nc, WMNC_IDENT_WMSG, hwnd, uMsg,
+ wParam, lParam);
+ }
+ }
+
+ return FALSE;
+}
+
+static void
+nc_notify_clear(khui_nc_wnd_data * d) {
+
+ if (d->notif_type == NC_NOTIFY_NONE)
+ /* there are no notifications anyway. */
+ return;
+
+ if (d->hwnd_notif_label)
+ DestroyWindow(d->hwnd_notif_label);
+
+ if (d->hwnd_notif_aux)
+ DestroyWindow(d->hwnd_notif_aux);
+
+ d->hwnd_notif_label = NULL;
+ d->hwnd_notif_aux = NULL;
+
+ SetRectEmpty(&d->r_notif);
+
+ d->notif_type = NC_NOTIFY_NONE;
+
+ /* Note that we must call nc_layout_main_panel() after calling
+ this to adjust the layout of the main panel. However we aren't
+ calling it here since we might want to add another set of
+ notifications or make other changes to the main panel content
+ before calling nc_layout_main_panel(). */
+}
+
+static void
+nc_notify_marquee(khui_nc_wnd_data * d, const wchar_t * label) {
+
+#if (_WIN32_IE >= 0x0600)
+ HDC hdc;
+ size_t length;
+ SIZE label_size;
+#endif
+
+ RECT r_label;
+ RECT r_mq;
+ RECT r_row;
+ HFONT hfont;
+ HWND hwnd;
+ HDWP hdefer;
+
+ /* Clear the notification area. We only support one notification
+ at a time. */
+ nc_notify_clear(d);
+
+#ifdef DEBUG
+ assert(d->dlg_main);
+#endif
+
+#if (_WIN32_IE >= 0x0600)
+
+ /* We can only show the marquee control if the comctl32 DLL is
+ version 6.0 or later. Otherwise we only show the label. */
+
+ if (FAILED(StringCchLength(label, KHUI_MAXCCH_SHORT_DESC, &length))) {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ length = KHUI_MAXCCH_SHORT_DESC;
+ }
+
+ /* See how big the notification control needs to be. */
+
+ hdc = GetDC(d->dlg_main);
+#ifdef DEBUG
+ assert(hdc != NULL);
+#endif
+
+ GetTextExtentPoint32(hdc, label, (int) length, &label_size);
+
+ ReleaseDC(d->dlg_main, hdc);
+
+ CopyRect(&r_row, &d->r_row);
+
+ if (label_size.cx > d->r_e_label.right - d->r_e_label.left) {
+ /* using an entire row */
+ CopyRect(&r_label, &d->r_row);
+ CopyRect(&r_mq, &d->r_n_input);
+ OffsetRect(&r_mq, 0, r_row.bottom - r_row.top);
+ r_row.bottom += r_row.bottom - r_row.top;
+ } else if (label_size.cx > d->r_n_label.right - d->r_n_label.left) {
+ /* using large labels */
+ CopyRect(&r_label, &d->r_e_label);
+ CopyRect(&r_mq, &d->r_e_input);
+ } else {
+ /* normal labels */
+ CopyRect(&r_label, &d->r_n_label);
+ CopyRect(&r_mq, &d->r_n_input);
+ }
+
+ InflateRect(&r_mq, 0, - ((r_mq.bottom - r_mq.top) / 4));
+
+#else /* _WIN32_IE < 0x0600 */
+
+ /* We are just showing the label */
+ CopyRect(&r_row, &d->r_row);
+ CopyRect(&r_label, &r_row);
+ SetRectEmpty(&r_mq);
+
+#endif /* _WIN32_IE >= 0x0600 */
+
+ {
+ long y;
+
+ if (IsRectEmpty(&d->r_custprompt)) {
+ y = d->r_idspec.bottom;
+ } else {
+ y = d->r_custprompt.bottom;
+ }
+
+ OffsetRect(&r_row, d->r_area.left, y);
+ OffsetRect(&r_label, r_row.left, r_row.top);
+ OffsetRect(&r_mq, r_row.left, r_row.top);
+ }
+
+ hfont = (HFONT) SendMessage(d->dlg_main, WM_GETFONT, 0, 0);
+
+ hdefer = BeginDeferWindowPos(2);
+
+ /* the label */
+ hwnd = CreateWindowEx(0,
+ L"STATIC",
+ label,
+ WS_CHILD | SS_ENDELLIPSIS,
+ r_label.left, r_label.top,
+ r_label.right - r_label.left,
+ r_label.bottom - r_label.top,
+ d->dlg_main,
+ NULL, NULL, NULL);
+#ifdef DEBUG
+ assert(hwnd != NULL);
+#endif
+ SendMessage(hwnd, WM_SETFONT, (WPARAM) hfont, (LPARAM) TRUE);
+
+ DeferWindowPos(hdefer, hwnd, NULL,
+ 0, 0, 0, 0,
+ SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER |
+ SWP_NOSIZE | SWP_SHOWWINDOW);
+
+ d->hwnd_notif_label = hwnd;
+
+ /* and the marquee */
+
+#if (_WIN32_IE >= 0x0600)
+
+ /* unfortunately, the marquee is only available on comctl32
+ version 6.0 or later. On previous versions, we only display
+ the message label. */
+
+ hwnd = CreateWindowEx(0,
+ PROGRESS_CLASS,
+ L"",
+ WS_CHILD | PBS_MARQUEE,
+ r_mq.left, r_mq.top,
+ r_mq.right - r_mq.left,
+ r_mq.bottom - r_mq.top,
+ d->dlg_main,
+ NULL, NULL, NULL);
+#ifdef DEBUG
+ assert(hwnd != NULL);
+#endif
+
+ SendMessage(hwnd, PBM_SETMARQUEE, TRUE, 100);
+
+ DeferWindowPos(hdefer, hwnd, NULL,
+ 0, 0, 0, 0,
+ SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER |
+ SWP_NOSIZE | SWP_SHOWWINDOW);
+
+ d->hwnd_notif_aux = hwnd;
+
+#endif /* _WIN32_IE >= 0x0600 */
+
+ EndDeferWindowPos(hdefer);
+
+ CopyRect(&d->r_notif, &r_row);
+
+ d->notif_type = NC_NOTIFY_MARQUEE;
+
+ /* Note that we must call nc_layout_main_panel() after calling
+ this to adjust the layout of the main panel. However we aren't
+ calling it here since we might want to add another set of
+ notifications or make other changes to the main panel content
+ before calling nc_layout_main_panel(). */
+}
+
+static void
+nc_notify_message(khui_nc_wnd_data * d,
+ kherr_severity severity,
+ const wchar_t * message) {
+
+ SIZE icon_size;
+ LPCTSTR icon_res;
+ HICON h_icon;
+ HWND hwnd;
+ HFONT hfont;
+ HDWP hdefer;
+
+ RECT r_row;
+ RECT r_label;
+ RECT r_icon;
+
+ nc_notify_clear(d);
+
+ icon_size.cx = GetSystemMetrics(SM_CXSMICON);
+ icon_size.cy = GetSystemMetrics(SM_CYSMICON);
+
+ switch(severity) {
+ case KHERR_INFO:
+ icon_res = MAKEINTRESOURCE(OIC_INFORMATION);
+ break;
+
+ case KHERR_WARNING:
+ icon_res = MAKEINTRESOURCE(OIC_WARNING);
+ break;
+
+ case KHERR_ERROR:
+ icon_res = MAKEINTRESOURCE(OIC_ERROR);
+ break;
+
+ default:
+ icon_res = NULL;
+ }
+
+ if (icon_res != NULL) {
+ h_icon = (HICON) LoadImage(NULL,
+ icon_res,
+ IMAGE_ICON,
+ icon_size.cx,
+ icon_size.cy,
+ LR_DEFAULTCOLOR | LR_SHARED);
+ } else {
+ h_icon = NULL;
+ }
+
+ CopyRect(&r_row, &d->r_row);
+
+#define CENTERVALUE(w,v) ((w)/2 - (v)/2)
+
+ SetRect(&r_icon,
+ 0, CENTERVALUE(r_row.bottom - r_row.top, icon_size.cy),
+ icon_size.cx,
+ CENTERVALUE(r_row.bottom - r_row.top, icon_size.cy) + icon_size.cy);
+
+#undef CENTERVALUE
+
+ CopyRect(&r_label, &r_row);
+ OffsetRect(&r_label, -r_label.left, -r_label.top);
+ r_label.left += (icon_size.cx * 3) / 2;
+
+ {
+ long y;
+
+ if (IsRectEmpty(&d->r_custprompt)) {
+ y = d->r_idspec.bottom;
+ } else {
+ y = d->r_custprompt.bottom;
+ }
+
+ OffsetRect(&r_row, d->r_area.left, y);
+ OffsetRect(&r_label, r_row.left, r_row.top);
+ OffsetRect(&r_icon, r_row.left, r_row.top);
+ }
+
+ hfont = (HFONT) SendMessage(d->dlg_main, WM_GETFONT, 0, 0);
+
+ hdefer = BeginDeferWindowPos(2);
+
+ hwnd = CreateWindowEx(0,
+ L"STATIC",
+ message,
+ WS_CHILD | SS_ENDELLIPSIS | SS_CENTER,
+ r_label.left, r_label.top,
+ r_label.right - r_label.left,
+ r_label.bottom - r_label.top,
+ d->dlg_main,
+ NULL, NULL, NULL);
+#ifdef DEBUG
+ assert(hwnd != NULL);
+#endif
+ SendMessage(hwnd, WM_SETFONT, (WPARAM) hfont, (LPARAM) TRUE);
+
+ DeferWindowPos(hdefer, hwnd, NULL,
+ 0, 0, 0, 0,
+ SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER |
+ SWP_NOSIZE | SWP_SHOWWINDOW);
+
+ d->hwnd_notif_label = hwnd;
+
+ hwnd = CreateWindowEx(0,
+ L"STATIC",
+ NULL,
+ WS_CHILD | SS_ICON |
+#if (_WIN32_IE >= 0x0600)
+ SS_REALSIZECONTROL
+#else
+ 0
+#endif
+ ,
+ r_icon.left, r_icon.top,
+ r_icon.right - r_icon.left,
+ r_icon.bottom - r_icon.top,
+ d->dlg_main,
+ NULL, NULL, NULL);
+#ifdef DEBUG
+ assert(hwnd != NULL);
+#endif
+
+ if (h_icon && hwnd)
+ SendMessage(hwnd, STM_SETICON, (WPARAM) h_icon, 0);
+
+ DeferWindowPos(hdefer, hwnd, NULL,
+ 0, 0, 0, 0,
+ SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER |
+ SWP_NOSIZE | SWP_SHOWWINDOW | SWP_NOZORDER);
+
+ d->hwnd_notif_aux = hwnd;
+
+ EndDeferWindowPos(hdefer);
+
+ CopyRect(&d->r_notif, &r_row);
+
+ d->notif_type = NC_NOTIFY_MESSAGE;
+
+ /* Note that we must call nc_layout_main_panel() after calling
+ this to adjust the layout of the main panel. However we aren't
+ calling it here since we might want to add another set of
+ notifications or make other changes to the main panel content
+ before calling nc_layout_main_panel(). */
+}
+
+static void
+nc_layout_main_panel(khui_nc_wnd_data * d)
+{
+ RECT r_main;
+ HWND hw_ct;
+ HWND hw_ct_label;
+ HDWP hdwp;
+ RECT r_used; /* extent used by identity specifiers,
+ custom prompts and notificaiton
+ controls. */
+
+ RECT r_wmain; /* extents of the main window in screen
+ coordinates. */
+
+ r_main.left = 0;
+ r_main.top = 0;
+ r_main.bottom = NCDLG_HEIGHT;
+ r_main.right = NCDLG_WIDTH;
+
+ MapDialogRect(d->dlg_main, &r_main);
+
+ CopyRect(&r_used, &d->r_idspec);
+
+ GetWindowRect(d->dlg_main, &r_wmain);
+
+ hdwp = BeginDeferWindowPos(7);
+
+ /* check if the notification area and the custom prompt area are
+ overlapping. */
+
+ if (d->notif_type != NC_NOTIFY_NONE) {
+ long delta_y = 0;
+ RECT r;
+
+ CopyRect(&r, &d->r_custprompt);
+
+ if (IsRectEmpty(&d->r_custprompt)) {
+ /* if there are no custom prompts, then the notification
+ area should be immediately below the identitify
+ specifers. */
+
+ delta_y = d->r_idspec.bottom - d->r_notif.top;
+ } else {
+ /* otherwise, the notification area should be immediately
+ below the custom prompt area */
+
+ delta_y = d->r_custprompt.bottom - d->r_notif.top;
+ }
+
+ if (delta_y != 0) {
+ RECT r_lbl;
+ RECT r_aux;
+
+ if (d->hwnd_notif_label) {
+ GetWindowRect(d->hwnd_notif_label, &r_lbl);
+ OffsetRect(&r_lbl, -r_wmain.left, delta_y - r_wmain.top);
+
+ DeferWindowPos(hdwp, d->hwnd_notif_label, NULL,
+ r_lbl.left, r_lbl.top, 0, 0,
+ SWP_NOACTIVATE | SWP_NOOWNERZORDER |
+ SWP_NOZORDER | SWP_NOSIZE);
+ }
+
+ if (d->hwnd_notif_aux) {
+ GetWindowRect(d->hwnd_notif_aux, &r_aux);
+ OffsetRect(&r_aux, -r_wmain.left, delta_y - r_wmain.top);
+
+ DeferWindowPos(hdwp, d->hwnd_notif_aux, NULL,
+ r_aux.left, r_aux.top, 0, 0,
+ SWP_NOACTIVATE | SWP_NOOWNERZORDER |
+ SWP_NOZORDER | SWP_NOSIZE);
+ }
+
+ OffsetRect(&d->r_notif, 0, delta_y);
+ }
+ }
+
+ if (!IsRectEmpty(&d->r_custprompt)) {
+ r_used.bottom = max(d->r_custprompt.bottom,
+ r_used.bottom);
+ }
+
+ if (!IsRectEmpty(&d->r_notif)) {
+ r_used.bottom = max(d->r_notif.bottom,
+ r_used.bottom);
+ }
+
+ if (d->nc->mode == KHUI_NC_MODE_MINI) {
+ RECT r_ok;
+ RECT r_cancel;
+ RECT r_advanced;
+ HWND hw;
+
+ hw = GetDlgItem(d->dlg_main, IDOK);
+#ifdef DEBUG
+ assert(hw != NULL);
+#endif
+ GetWindowRect(hw, &r_ok);
+ OffsetRect(&r_ok, -r_wmain.left, -r_ok.top + r_used.bottom);
+
+ DeferWindowPos(hdwp, hw, NULL,
+ r_ok.left, r_ok.top, 0, 0,
+ SWP_NOACTIVATE | SWP_NOOWNERZORDER |
+ SWP_NOZORDER | SWP_NOSIZE | SWP_SHOWWINDOW);
+
+ hw = GetDlgItem(d->dlg_main, IDCANCEL);
+#ifdef DEBUG
+ assert(hw != NULL);
+#endif
+ GetWindowRect(hw, &r_cancel);
+ OffsetRect(&r_cancel, -r_wmain.left, -r_cancel.top + r_used.bottom);
+
+ DeferWindowPos(hdwp, hw, NULL,
+ r_cancel.left, r_cancel.top, 0, 0,
+ SWP_NOACTIVATE | SWP_NOOWNERZORDER |
+ SWP_NOZORDER | SWP_NOSIZE | SWP_SHOWWINDOW);
+
+ hw = GetDlgItem(d->dlg_main, IDC_NC_ADVANCED);
+#ifdef DEBUG
+ assert(hw != NULL);
+#endif
+ GetWindowRect(hw, &r_advanced);
+ OffsetRect(&r_advanced, -r_wmain.left, -r_advanced.top + r_used.bottom);
+
+ DeferWindowPos(hdwp, hw, NULL,
+ r_advanced.left, r_advanced.top, 0, 0,
+ SWP_NOACTIVATE | SWP_NOOWNERZORDER |
+ SWP_NOZORDER | SWP_NOSIZE | SWP_SHOWWINDOW);
+
+ /* and now update the extents of the main panel */
+ r_main.bottom = r_used.bottom + (r_ok.bottom - r_ok.top) + d->r_area.top;
+
+ CopyRect(&d->r_main, &r_main);
+
+ } else {
+
+ HWND hw;
+
+ hw = GetDlgItem(d->dlg_main, IDOK);
+#ifdef DEBUG
+ assert(hw != NULL);
+#endif
+ if (IsWindowVisible(hw))
+ DeferWindowPos(hdwp, hw, NULL,
+ 0, 0, 0, 0,
+ SWP_HIDEWINDOW | SWP_NOMOVE | SWP_NOSIZE |
+ SWP_NOOWNERZORDER | SWP_NOZORDER);
+
+ hw = GetDlgItem(d->dlg_main, IDCANCEL);
+#ifdef DEBUG
+ assert(hw != NULL);
+#endif
+ if (IsWindowVisible(hw))
+ DeferWindowPos(hdwp, hw, NULL,
+ 0, 0, 0, 0,
+ SWP_HIDEWINDOW | SWP_NOMOVE | SWP_NOSIZE |
+ SWP_NOOWNERZORDER | SWP_NOZORDER);
+
+ hw = GetDlgItem(d->dlg_main, IDC_NC_ADVANCED);
+#ifdef DEBUG
+ assert(hw != NULL);
+#endif
+ if (IsWindowVisible(hw))
+ DeferWindowPos(hdwp, hw, NULL,
+ 0, 0, 0, 0,
+ SWP_HIDEWINDOW | SWP_NOMOVE | SWP_NOSIZE |
+ SWP_NOOWNERZORDER | SWP_NOZORDER);
+
+ d->r_credtext.top = r_used.bottom;
+
+ CopyRect(&d->r_main, &r_main);
+ }
+
+ /* now update the layout of the credentials text window */
+
+ hw_ct = GetDlgItem(d->dlg_main, IDC_NC_CREDTEXT);
+ hw_ct_label = GetDlgItem(d->dlg_main, IDC_NC_CREDTEXT_LABEL);
+#ifdef DEBUG
+ assert(hw_ct != NULL);
+ assert(hw_ct_label != NULL);
+#endif
+
+ if (d->nc->mode == KHUI_NC_MODE_MINI ||
+ d->r_credtext.bottom < d->r_credtext.top + d->r_row.bottom * 2) {
+
+ /* either we aren't supposed to show the credentials text
+ window, or we don't have enough room. */
+ if (IsWindowVisible(hw_ct) || IsWindowVisible(hw_ct_label)) {
+
+ DeferWindowPos(hdwp, hw_ct, NULL,
+ 0, 0, 0, 0,
+ SWP_HIDEWINDOW | SWP_NOOWNERZORDER |
+ SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE);
+
+ DeferWindowPos(hdwp, hw_ct_label, NULL,
+ 0, 0, 0, 0,
+ SWP_HIDEWINDOW | SWP_NOOWNERZORDER |
+ SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE);
+
+ }
+
+ } else {
+
+ DeferWindowPos(hdwp,
+ hw_ct, NULL,
+ d->r_credtext.left + d->r_n_input.left, /* x */
+ d->r_credtext.top, /* y */
+ d->r_n_input.right - d->r_n_input.left, /* width */
+ d->r_credtext.bottom - d->r_credtext.top, /* height */
+ SWP_NOACTIVATE | SWP_NOOWNERZORDER |
+ SWP_NOZORDER | SWP_SHOWWINDOW);
+
+ DeferWindowPos(hdwp,
+ hw_ct_label, NULL,
+ d->r_credtext.left + d->r_n_label.left, /* x */
+ d->r_credtext.top, /* y */
+ d->r_n_label.right - d->r_n_label.left, /* width */
+ d->r_n_label.bottom - d->r_n_label.top, /* height */
+ SWP_NOACTIVATE | SWP_NOOWNERZORDER |
+ SWP_NOZORDER | SWP_SHOWWINDOW);
+ }
+
+ EndDeferWindowPos(hdwp);
+
+ /* NOTE: although we updated d->r_main, if the new credentials
+ window is in mini mode, we must call
+ nc_layout_new_cred_window() to adjust the size of the new
+ credentials window to fit the main panel. We don't do it here
+ because we need to keep these two operations separate. */
+}
+
+/* Credential type panel comparison function. Tabs are sorted based
+ on the following criteria:
+
+ 1) By ordinal - Panels with ordinal -1 will be ranked after panels
+ whose ordinal is not -1.
+
+ 2) By name - Case insensitive comparison of the name. If the panel
+ does not have a name (i.e. the ->name member is NULL, it will be
+ ranked after panels which have a name.
+ */
+static int __cdecl
+nc_tab_sort_func(const void * v1, const void * v2)
+{
+ /* v1 and v2 and of type : khui_new_creds_by_type ** */
+ khui_new_creds_by_type *t1, *t2;
+
+ t1 = *((khui_new_creds_by_type **) v1);
+ t2 = *((khui_new_creds_by_type **) v2);
+
+ if(t1->ordinal != -1) {
+ if(t2->ordinal != -1) {
+ if(t1->ordinal == t2->ordinal) {
+ if (t1->name && t2->name)
+ return _wcsicmp(t1->name, t2->name);
+ else if (t1->name)
+ return -1;
+ else if (t2->name)
+ return 1;
+ else
+ return 0;
+ } else {
+ /* safe to convert to an int here */
+ return (int) (t1->ordinal - t2->ordinal);
+ }
+ } else
+ return -1;
+ } else {
+ if(t2->ordinal != -1)
+ return 1;
+ else if (t1->name && t2->name)
+ return wcscmp(t1->name, t2->name);
+ else if (t1->name)
+ return -1;
+ else if (t2->name)
+ return 1;
+ else
+ return 0;
+ }
+}
+
+static void
+nc_notify_types(khui_new_creds * c, UINT uMsg,
+ WPARAM wParam, LPARAM lParam, BOOL sync)
+{
+ khm_size i;
+
+ for(i=0; i<c->n_types; i++) {
+
+ if (c->types[i]->hwnd_panel == NULL)
+ continue;
+
+ if (sync)
+ SendMessage(c->types[i]->hwnd_panel, uMsg, wParam, lParam);
+ else
+ PostMessage(c->types[i]->hwnd_panel, uMsg, wParam, lParam);
+ }
+}
+
+static void
+nc_clear_password_fields(khui_nc_wnd_data * d)
+{
+ khm_size i;
+ khm_boolean need_sync = FALSE;
+
+ khui_cw_lock_nc(d->nc);
+
+ for (i=0; i < d->nc->n_prompts; i++) {
+ if ((d->nc->prompts[i]->flags & KHUI_NCPROMPT_FLAG_HIDDEN) &&
+ d->nc->prompts[i]->hwnd_edit) {
+ SetWindowText(d->nc->prompts[i]->hwnd_edit,
+ L"");
+ need_sync = TRUE;
+ }
+ }
+
+ khui_cw_unlock_nc(d->nc);
+
+ if (need_sync) {
+ khui_cw_sync_prompt_values(d->nc);
+ }
+}
+
+/* used by nc_enable_controls */
+
+struct nc_enum_wnd_data {
+ khui_nc_wnd_data * d;
+ khm_boolean enable;
+};
+
+static
+BOOL CALLBACK
+nc_enum_wnd_proc(HWND hwnd,
+ LPARAM lParam)
+{
+ struct nc_enum_wnd_data * wd;
+
+ wd = (struct nc_enum_wnd_data *) lParam;
+
+ EnableWindow(hwnd, wd->enable);
+
+ return TRUE;
+}
+
+static void
+nc_enable_controls(khui_nc_wnd_data * d, khm_boolean enable)
+{
+ struct nc_enum_wnd_data wd;
+
+ ZeroMemory(&wd, sizeof(wd));
+
+ wd.d = d;
+ wd.enable = enable;
+
+ EnumChildWindows(d->dlg_main, nc_enum_wnd_proc, (LPARAM) &wd);
+}
+
+#define NC_MAXCCH_CREDTEXT 16384
+#define NC_MAXCB_CREDTEXT (NC_MAXCCH_CREDTEXT * sizeof(wchar_t))
+
+static void
+nc_update_credtext(khui_nc_wnd_data * d)
+{
+ wchar_t * ctbuf = NULL;
+ wchar_t * buf;
+ BOOL okEnable = FALSE;
+ BOOL validId = FALSE;
+ HWND hw = NULL;
+ size_t cch = 0;
+
+ ctbuf = PMALLOC(NC_MAXCB_CREDTEXT);
+
+ assert(ctbuf != NULL);
+
+ LoadString(khm_hInstance, IDS_NC_CREDTEXT_TABS, ctbuf, NC_MAXCCH_CREDTEXT);
+ StringCchLength(ctbuf, NC_MAXCCH_CREDTEXT, &cch);
+ buf = ctbuf + cch;
+ nc_notify_types(d->nc, KHUI_WM_NC_NOTIFY,
+ MAKEWPARAM(0, WMNC_UPDATE_CREDTEXT), (LPARAM) d->nc, TRUE);
+
+ /* hopefully all the types have updated their credential texts */
+
+ /* if the dialog is in the mini mode, we have to display
+ exceptions using a notification. */
+ if (d->nc->mode == KHUI_NC_MODE_MINI) {
+ BOOL need_layout = FALSE;
+ if (d->nc->n_identities == 0) {
+
+ /* There are no identities selected. We don't show any
+ notifications here. */
+ if (d->notif_type != NC_NOTIFY_NONE) {
+ nc_notify_clear(d);
+ need_layout = TRUE;
+ }
+
+ } else {
+
+ wchar_t id_name[KCDB_IDENT_MAXCCH_NAME];
+ wchar_t format[256];
+ wchar_t msg[ARRAYLENGTH(format) + ARRAYLENGTH(id_name)];
+ khm_size cbbuf;
+ khm_int32 flags;
+
+ kcdb_identity_get_flags(d->nc->identities[0], &flags);
+
+ cbbuf = sizeof(id_name);
+ kcdb_identity_get_name(d->nc->identities[0], id_name, &cbbuf);
+
+ if (flags & KCDB_IDENT_FLAG_INVALID) {
+
+ /* identity is invalid */
+ LoadString(khm_hInstance, IDS_NCN_IDENT_INVALID,
+ format, ARRAYLENGTH(format));
+ StringCbPrintf(msg, sizeof(msg), format, id_name);
+
+ nc_notify_message(d, KHERR_ERROR, msg);
+
+ need_layout = TRUE;
+
+ } else if ((flags & KCDB_IDENT_FLAG_VALID) ||
+ d->nc->subtype == KMSG_CRED_PASSWORD) {
+ /* special case: If we are going to change the
+ password, we don't expect the identity provider to
+ validate the identity in real time. As such, we
+ assume that the identity is valid. */
+
+ /* identity is valid */
+ if (d->notif_type != NC_NOTIFY_NONE) {
+ nc_notify_clear(d);
+ need_layout = TRUE;
+ }
+
+ } else if (flags & KCDB_IDENT_FLAG_UNKNOWN) {
+
+ /* unknown state */
+ LoadString(khm_hInstance, IDS_NCN_IDENT_UNKNOWN,
+ format, ARRAYLENGTH(format));
+ StringCbPrintf(msg, sizeof(msg), format, id_name);
+
+ nc_notify_message(d, KHERR_WARNING, msg);
+
+ need_layout = TRUE;
+
+ } else {
+
+ /* still checking */
+ LoadString(khm_hInstance, IDS_NCN_IDENT_CHECKING,
+ format, ARRAYLENGTH(format));
+ StringCbPrintf(msg, sizeof(msg), format, id_name);
+
+ nc_notify_marquee(d, msg);
+
+ need_layout = TRUE;
+
+ }
+ }
+
+ if (need_layout) {
+ nc_layout_main_panel(d);
+ nc_layout_new_cred_window(d);
+ }
+ }
+
+ if(d->nc->n_identities == 1) {
+ wchar_t main_fmt[256];
+ wchar_t id_fmt[256];
+ wchar_t id_name[KCDB_IDENT_MAXCCH_NAME];
+ wchar_t id_string[KCDB_IDENT_MAXCCH_NAME + 256];
+ khm_size cbbuf;
+ khm_int32 flags;
+
+ LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_ONE,
+ main_fmt, (int) ARRAYLENGTH(main_fmt));
+
+ cbbuf = sizeof(id_name);
+ kcdb_identity_get_name(d->nc->identities[0], id_name, &cbbuf);
+
+ kcdb_identity_get_flags(d->nc->identities[0], &flags);
+
+ if (flags & KCDB_IDENT_FLAG_INVALID) {
+ LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_INVALID,
+ id_fmt, (int) ARRAYLENGTH(id_fmt));
+ } else if(flags & KCDB_IDENT_FLAG_VALID) {
+ LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_VALID,
+ id_fmt, (int) ARRAYLENGTH(id_fmt));
+ } else if(flags & KCDB_IDENT_FLAG_UNKNOWN) {
+ LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_UNCHECKED,
+ id_fmt, (int) ARRAYLENGTH(id_fmt));
+ } else if(d->nc->subtype == KMSG_CRED_NEW_CREDS) {
+ LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_CHECKING,
+ id_fmt, (int) ARRAYLENGTH(id_fmt));
+ } else {
+ LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_UNCHECKED,
+ id_fmt, (int) ARRAYLENGTH(id_fmt));
+ }
+
+ StringCbPrintf(id_string, sizeof(id_string), id_fmt, id_name);
+
+ StringCbPrintf(buf, NC_MAXCB_CREDTEXT - cch*sizeof(wchar_t),
+ main_fmt, id_string);
+
+ if (flags & KCDB_IDENT_FLAG_VALID) {
+ if (flags & KCDB_IDENT_FLAG_DEFAULT)
+ LoadString(khm_hInstance, IDS_NC_ID_DEF,
+ id_string, ARRAYLENGTH(id_string));
+ else if (d->nc->set_default)
+ LoadString(khm_hInstance, IDS_NC_ID_WDEF,
+ id_string, ARRAYLENGTH(id_string));
+ else
+ LoadString(khm_hInstance, IDS_NC_ID_NDEF,
+ id_string, ARRAYLENGTH(id_string));
+
+ StringCbCat(buf, NC_MAXCB_CREDTEXT - cch * sizeof(wchar_t),
+ id_string);
+ }
+
+ } else if(d->nc->n_identities > 1) {
+ wchar_t *ids_string;
+ khm_size cb_ids_string;
+
+ wchar_t id_name[KCDB_IDENT_MAXCCH_NAME];
+ wchar_t id_fmt[256];
+ wchar_t id_string[KCDB_IDENT_MAXCCH_NAME + 256];
+
+ wchar_t main_fmt[256];
+ khm_size cbbuf;
+
+ LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_MANY,
+ main_fmt, (int) ARRAYLENGTH(main_fmt));
+
+ /* we are going to concatenate all the identity names into
+ a comma separated string */
+
+ /* d->nc->n_identities is at least 2 */
+ ids_string = PMALLOC((KCDB_IDENT_MAXCB_NAME + sizeof(id_fmt)) *
+ (d->nc->n_identities - 1));
+ cb_ids_string =
+ (KCDB_IDENT_MAXCB_NAME + sizeof(id_fmt)) *
+ (d->nc->n_identities - 1);
+
+ assert(ids_string != NULL);
+
+ ids_string[0] = 0;
+
+ {
+ khm_size i;
+ khm_int32 flags;
+
+ for(i=1; i<d->nc->n_identities; i++) {
+ if(i>1) {
+ StringCbCat(ids_string, cb_ids_string, L",");
+ }
+
+ flags = 0;
+
+ cbbuf = sizeof(id_name);
+ kcdb_identity_get_name(d->nc->identities[i], id_name, &cbbuf);
+ kcdb_identity_get_flags(d->nc->identities[i], &flags);
+ if(flags & KCDB_IDENT_FLAG_INVALID) {
+ LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_INVALID,
+ id_fmt, (int) ARRAYLENGTH(id_fmt));
+ } else if(flags & KCDB_IDENT_FLAG_VALID) {
+ LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_VALID,
+ id_fmt, (int) ARRAYLENGTH(id_fmt));
+ } else {
+ LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_UNCHECKED,
+ id_fmt, (int) ARRAYLENGTH(id_fmt));
+ }
+
+ StringCbPrintf(id_string, sizeof(id_string), id_fmt, id_name);
+ StringCbCat(ids_string, cb_ids_string, id_string);
+ }
+
+ cbbuf = sizeof(id_name);
+ kcdb_identity_get_name(d->nc->identities[0], id_name, &cbbuf);
+ kcdb_identity_get_flags(d->nc->identities[0], &flags);
+ if(flags & KCDB_IDENT_FLAG_INVALID) {
+ LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_INVALID,
+ id_fmt, (int) ARRAYLENGTH(id_fmt));
+ } else if(flags & KCDB_IDENT_FLAG_VALID) {
+ LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_VALID,
+ id_fmt, (int) ARRAYLENGTH(id_fmt));
+ } else {
+ LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_UNCHECKED,
+ id_fmt, (int) ARRAYLENGTH(id_fmt));
+ }
+ StringCbPrintf(id_string, sizeof(id_string), id_fmt, id_name);
+
+ StringCbPrintf(buf, NC_MAXCB_CREDTEXT - cch*sizeof(wchar_t),
+ main_fmt, id_string, ids_string);
+
+ PFREE(ids_string);
+ }
+ } else {
+ LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_NONE,
+ buf, (int)(NC_MAXCCH_CREDTEXT - cch));
+ }
+
+ /* now, append the credtext string from each of the cred types */
+ {
+ khm_size i;
+ size_t cb;
+ wchar_t * buf;
+
+ cb = NC_MAXCB_CREDTEXT;
+ buf = ctbuf;
+
+ for(i=0; i<d->nc->n_types; i++) {
+ if(d->nc->types[i]->credtext != NULL) {
+ StringCbCatEx(buf, cb,
+ d->nc->types[i]->credtext,
+ &buf, &cb,
+ 0);
+ }
+ }
+ }
+
+ SetDlgItemText(d->dlg_main, IDC_NC_CREDTEXT, ctbuf);
+
+ PFREE(ctbuf);
+
+ /* so depending on whether the primary identity was found to be
+ invalid, we need to disable the Ok button and set the title to
+ reflect this */
+
+ if(d->nc->n_identities > 0) {
+ khm_int32 flags = 0;
+
+ if(KHM_SUCCEEDED(kcdb_identity_get_flags(d->nc->identities[0],
+ &flags)) &&
+ (flags & KCDB_IDENT_FLAG_VALID)) {
+ validId = TRUE;
+ }
+ }
+
+ if (d->nc->window_title == NULL) {
+ if(validId) {
+ wchar_t wpostfix[256];
+ wchar_t wtitle[KCDB_IDENT_MAXCCH_NAME + 256];
+ khm_size cbsize;
+
+ cbsize = sizeof(wtitle);
+ kcdb_identity_get_name(d->nc->identities[0], wtitle, &cbsize);
+
+ if (d->nc->subtype == KMSG_CRED_PASSWORD)
+ LoadString(khm_hInstance, IDS_WTPOST_PASSWORD,
+ wpostfix, (int) ARRAYLENGTH(wpostfix));
+ else
+ LoadString(khm_hInstance, IDS_WTPOST_NEW_CREDS,
+ wpostfix, (int) ARRAYLENGTH(wpostfix));
+
+ StringCbCat(wtitle, sizeof(wtitle), wpostfix);
+
+ SetWindowText(d->nc->hwnd, wtitle);
+ } else {
+ wchar_t wtitle[256];
+
+ if (d->nc->subtype == KMSG_CRED_PASSWORD)
+ LoadString(khm_hInstance, IDS_WT_PASSWORD,
+ wtitle, (int) ARRAYLENGTH(wtitle));
+ else
+ LoadString(khm_hInstance, IDS_WT_NEW_CREDS,
+ wtitle, (int) ARRAYLENGTH(wtitle));
+
+ SetWindowText(d->nc->hwnd, wtitle);
+ }
+ }
+
+ if (!(d->nc->response & KHUI_NC_RESPONSE_PROCESSING)) {
+ if(validId ||
+ d->nc->subtype == KMSG_CRED_PASSWORD) {
+ /* TODO: check if all the required fields have valid values
+ before enabling the Ok button */
+ okEnable = TRUE;
+ }
+
+ hw = GetDlgItem(d->dlg_main, IDOK);
+ EnableWindow(hw, okEnable);
+ hw = GetDlgItem(d->dlg_bb, IDOK);
+ EnableWindow(hw, okEnable);
+ }
+}
+
+static void
+nc_layout_new_cred_window(khui_nc_wnd_data * ncd) {
+ khui_new_creds * c;
+ RECT r_main;
+ RECT r_ncdialog;
+ HDWP hdefer;
+
+ c = ncd->nc;
+
+ r_main.left = 0;
+ r_main.top = 0;
+ r_main.right = NCDLG_WIDTH;
+ r_main.bottom = NCDLG_HEIGHT;
+
+ MapDialogRect(ncd->dlg_main, &r_main);
+
+ hdefer = BeginDeferWindowPos(5);
+
+ if (c->mode == KHUI_NC_MODE_MINI) {
+
+ if (IsWindowVisible(ncd->tab_wnd)) {
+ DeferWindowPos(hdefer,
+ ncd->tab_wnd, NULL,
+ 0, 0, 0, 0,
+ SWP_HIDEWINDOW |
+ SWP_NOMOVE | SWP_NOOWNERZORDER |
+ SWP_NOSIZE | SWP_NOZORDER);
+ }
+
+ if (IsWindowVisible(ncd->dlg_bb)) {
+ DeferWindowPos(hdefer,
+ ncd->dlg_bb, NULL,
+ 0, 0, 0, 0,
+ SWP_HIDEWINDOW |
+ SWP_NOMOVE | SWP_NOOWNERZORDER |
+ SWP_NOSIZE | SWP_NOZORDER);
+ }
+
+ DeferWindowPos(hdefer, ncd->dlg_main, NULL,
+ r_main.left, r_main.top,
+ r_main.right - r_main.left,
+ r_main.bottom - r_main.top,
+ SWP_NOACTIVATE | SWP_NOOWNERZORDER |
+ SWP_NOZORDER | SWP_SHOWWINDOW);
+
+ /* note that the ncd->r_main.bottom may not be the same as
+ r_main.bottom because ncd->r_main.bottom is set dynamically
+ depending on custom controls. ncd->r_main is valid only
+ once nc_layout_main_panel() is called.*/
+ CopyRect(&ncd->r_required, &ncd->r_main);
+
+ } else {
+ RECT r_tabctrl;
+ RECT r_displayarea;
+ RECT r_bbar;
+ khm_size i;
+
+ /* calculate the size of the tab control so that it fits
+ snugly around the expanded main panel. */
+ CopyRect(&r_tabctrl, &r_main);
+ TabCtrl_AdjustRect(ncd->tab_wnd, TRUE, &r_tabctrl);
+
+ if (r_tabctrl.left < 0 ||
+ r_tabctrl.top < 0) {
+
+ OffsetRect(&r_tabctrl,
+ (r_tabctrl.left < 0)? -r_tabctrl.left : 0,
+ (r_tabctrl.top < 0)? -r_tabctrl.top : 0);
+
+ }
+
+#ifdef DEBUG
+ assert(r_tabctrl.left == 0);
+ assert(r_tabctrl.top == 0);
+#endif
+
+ OffsetRect(&r_tabctrl, 0, ncd->r_area.top);
+
+ /* and now calculate the rectangle where the main panel should
+ be inside the tab control. */
+ CopyRect(&r_displayarea, &r_tabctrl);
+ TabCtrl_AdjustRect(ncd->tab_wnd, FALSE, &r_displayarea);
+
+ DeferWindowPos(hdefer,
+ ncd->tab_wnd, HWND_BOTTOM,
+ r_tabctrl.left, r_tabctrl.top,
+ r_tabctrl.right - r_tabctrl.left,
+ r_tabctrl.bottom - r_tabctrl.top,
+ SWP_NOACTIVATE | SWP_NOOWNERZORDER |
+ SWP_SHOWWINDOW);
+
+ /* we have to place the button bar just to the right of the
+ tab panel. */
+ r_bbar.left = 0;
+ r_bbar.top = 0;
+ r_bbar.right = NCDLG_BBAR_WIDTH;
+ r_bbar.bottom = NCDLG_BBAR_HEIGHT;
+
+ MapDialogRect(ncd->dlg_main, &r_bbar);
+
+ OffsetRect(&r_bbar, r_tabctrl.right, 0);
+
+ DeferWindowPos(hdefer,
+ ncd->dlg_bb, NULL,
+ r_bbar.left, r_bbar.top,
+ r_bbar.right - r_bbar.left,
+ r_bbar.bottom - r_bbar.top,
+ SWP_NOACTIVATE | SWP_NOOWNERZORDER |
+ SWP_NOZORDER | SWP_SHOWWINDOW);
+
+ /* move the main panel inside the tab control... */
+ DeferWindowPos(hdefer,
+ ncd->dlg_main, NULL,
+ r_displayarea.left, r_displayarea.top,
+ r_displayarea.right - r_displayarea.left,
+ r_displayarea.bottom - r_displayarea.top,
+ SWP_NOACTIVATE | SWP_NOOWNERZORDER |
+ SWP_NOZORDER |
+ (ncd->current_panel == 0 ? SWP_SHOWWINDOW : SWP_HIDEWINDOW));
+
+ /* and also move all the credential type panels (if they have
+ been created) inside the tab control too. */
+ khui_cw_lock_nc(c);
+
+ for (i=0; i < c->n_types; i++) {
+ if (c->types[i]->hwnd_panel != NULL) {
+ DeferWindowPos(hdefer,
+ c->types[i]->hwnd_panel, NULL,
+ r_displayarea.left, r_displayarea.top,
+ r_displayarea.right - r_displayarea.left,
+ r_displayarea.bottom - r_displayarea.top,
+ SWP_NOACTIVATE | SWP_NOOWNERZORDER |
+ SWP_NOZORDER |
+ (ncd->current_panel == c->types[i]->ordinal ?
+ SWP_SHOWWINDOW : SWP_HIDEWINDOW));
+ }
+ }
+
+ khui_cw_unlock_nc(c);
+
+ /* then update the required size of the new credentials
+ dialog. */
+ ncd->r_required.left = 0;
+ ncd->r_required.top = 0;
+ ncd->r_required.right = r_bbar.right;
+ ncd->r_required.bottom = max(r_tabctrl.bottom, r_bbar.bottom) + ncd->r_area.top;
+ }
+
+ /* commit all the window moves, resizes and hides/shows we did*/
+ EndDeferWindowPos(hdefer);
+
+ /* now we have to see if the client area of the new credentials
+ window is the right size. */
+
+ GetClientRect(c->hwnd, &r_ncdialog);
+
+ if (
+
+ ((r_ncdialog.right - r_ncdialog.left !=
+ ncd->r_required.right - ncd->r_required.left)
+
+ ||
+
+ (r_ncdialog.bottom - r_ncdialog.top !=
+ ncd->r_required.bottom - ncd->r_required.top))
+
+ &&
+
+ /* we don't bother if the new creds window is already in the
+ process of changing the size. */
+ !ncd->size_changing) {
+
+ /* if not, notify the window that the size needs adjusting. */
+ if (IsWindowVisible(c->hwnd))
+ PostMessage(c->hwnd, KHUI_WM_NC_NOTIFY,
+ MAKEWPARAM(0, WMNC_UPDATE_LAYOUT), 0);
+ else
+ SendMessage(c->hwnd, KHUI_WM_NC_NOTIFY,
+ MAKEWPARAM(0, WMNC_UPDATE_LAYOUT), 0);
+ }
+}
+
+#define CW_PARAM DWLP_USER
+
+static LRESULT
+nc_handle_wm_create(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ LPCREATESTRUCT lpc;
+ khui_new_creds * c;
+ khui_nc_wnd_data * ncd;
+ int x, y;
+ int width, height;
+ RECT r;
+ HFONT hf_main;
+
+ lpc = (LPCREATESTRUCT) lParam;
+
+ ncd = PMALLOC(sizeof(*ncd));
+ ZeroMemory(ncd, sizeof(*ncd));
+
+ c = (khui_new_creds *) lpc->lpCreateParams;
+ ncd->nc = c;
+ c->hwnd = hwnd;
+
+#ifdef DEBUG
+ assert(c->subtype == KMSG_CRED_NEW_CREDS ||
+ c->subtype == KMSG_CRED_PASSWORD);
+#endif
+
+#pragma warning(push)
+#pragma warning(disable: 4244)
+ SetWindowLongPtr(hwnd, CW_PARAM, (LONG_PTR) ncd);
+#pragma warning(pop)
+
+ /* first, create the tab control that will house the main dialog
+ panel as well as the plug-in specific panels */
+ ncd->tab_wnd = CreateWindowEx(0, /* extended style */
+ WC_TABCONTROL,
+ L"TabControloxxrz", /* window name */
+ TCS_HOTTRACK | TCS_RAGGEDRIGHT |
+ TCS_SINGLELINE | TCS_TABS |
+ WS_CHILD | WS_TABSTOP | WS_CLIPSIBLINGS,
+ 0, 0, 100, 100, /* x,y,width height.
+ We'll be changing
+ these later
+ anyway. */
+ hwnd,
+ (HMENU) IDC_NC_TABS,
+ NULL,
+ 0);
+
+#ifdef DEBUG
+ assert(ncd->tab_wnd != NULL);
+#endif
+
+ /* try to create the main dialog panel */
+
+ ncd->dlg_main = CreateDialogParam(khm_hInstance,
+ MAKEINTRESOURCE(IDD_NC_NEWCRED),
+ hwnd,
+ nc_common_dlg_proc,
+ (LPARAM) ncd);
+#ifdef DEBUG
+ assert(ncd->dlg_main != NULL);
+#endif
+
+ hf_main = (HFONT) SendMessage(ncd->dlg_main, WM_GETFONT, 0, 0);
+ if (hf_main)
+ SendMessage(ncd->tab_wnd, WM_SETFONT, (WPARAM) hf_main, FALSE);
+
+ {
+ 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 '<credtype>:<link_tag>'
+ and <credtype> is a valid name of a credentials
+ type that is participating in the credentials
+ acquisition process, then we forward the message to
+ the panel that is providing the UI for that cred
+ type. We also switch to that panel first, unless
+ the link is of the form '<credtype>:!<link_tag>'. */
+
+ colon = wcschr(sid, L':');
+ if (colon != NULL) {
+ khm_int32 credtype;
+ khui_new_creds_by_type * t;
+
+ *colon = L'\0';
+ if (KHM_SUCCEEDED(kcdb_credtype_get_id(sid, &credtype)) &&
+ KHM_SUCCEEDED(khui_cw_find_type(d->nc, credtype, &t))){
+ *colon = L':';
+
+ if (t->ordinal != d->current_panel &&
+ *(colon + 1) != L'!')
+ PostMessage(hwnd,
+ KHUI_WM_NC_NOTIFY,
+ MAKEWPARAM(t->ordinal,
+ WMNC_DIALOG_SWITCH_PANEL),
+ 0);
+
+ return SendMessage(t->hwnd_panel,
+ KHUI_WM_NC_NOTIFY,
+ MAKEWPARAM(0, WMNC_CREDTEXT_LINK),
+ lParam);
+ } else {
+ *colon = L':';
+ }
+ }
+
+ /* if it was for us, then we need to process the message */
+ if(!_wcsicmp(sid, CTLINKID_SWITCH_PANEL)) {
+ khm_int32 credtype;
+ khui_new_creds_by_type * t;
+
+ if (KHM_SUCCEEDED(kcdb_credtype_get_id(sparam,
+ &credtype)) &&
+ KHM_SUCCEEDED(khui_cw_find_type(d->nc,
+ credtype, &t))) {
+ if (t->ordinal != d->current_panel)
+ PostMessage(hwnd,
+ KHUI_WM_NC_NOTIFY,
+ MAKEWPARAM(t->ordinal,
+ WMNC_DIALOG_SWITCH_PANEL),
+ 0);
+ }
+ } else if (!_wcsicmp(sid, L"NotDef")) {
+ d->nc->set_default = FALSE;
+ nc_update_credtext(d);
+ } else if (!_wcsicmp(sid, L"MakeDef")) {
+ d->nc->set_default = TRUE;
+ nc_update_credtext(d);
+ }
+ }
+ return FALSE;
+
+#if 0
+ case NC_BN_SET_DEF_ID:
+ {
+ d->nc->set_default =
+ (IsDlgButtonChecked(d->dlg_main, NC_BN_SET_DEF_ID)
+ == BST_CHECKED);
+ }
+ return FALSE;
+#endif
+ }
+ break;
+ }
+
+ return TRUE;
+}
+
+static LRESULT nc_handle_wm_moving(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ khui_nc_wnd_data * d;
+
+ d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM);
+
+ 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;i<d->nc->n_prompts;i++) {
+ if(!(d->nc->prompts[i]->flags &
+ KHUI_NCPROMPT_FLAG_STOCK)) {
+ if(d->nc->prompts[i]->hwnd_static != NULL)
+ DestroyWindow(d->nc->prompts[i]->hwnd_static);
+
+ if(d->nc->prompts[i]->hwnd_edit != NULL)
+ DestroyWindow(d->nc->prompts[i]->hwnd_edit);
+ }
+
+ d->nc->prompts[i]->hwnd_static = NULL;
+ d->nc->prompts[i]->hwnd_edit = NULL;
+ }
+
+ khui_cw_unlock_nc(d->nc);
+
+ SetRectEmpty(&d->r_custprompt);
+
+ nc_layout_main_panel(d);
+
+ nc_layout_new_cred_window(d);
+ }
+ break;
+
+ case WMNC_SET_PROMPTS:
+ {
+ khm_size i;
+ int y;
+ HWND hw, hw_prev;
+ HFONT hf, hfold;
+ HDC hdc;
+ BOOL use_large_lables = FALSE;
+
+ /* we assume that WMNC_CLEAR_PROMPTS has already been
+ received */
+
+#ifdef DEBUG
+ assert(IsRectEmpty(&d->r_custprompt));
+#endif
+
+ khui_cw_lock_nc(d->nc);
+
+#if 0
+ /* special case, we have one prompt and it is a password
+ prompt. very common */
+ if(d->nc->n_prompts == 1 &&
+ d->nc->prompts[0]->type == KHUI_NCPROMPT_TYPE_PASSWORD) {
+
+ hw = GetDlgItem(d->dlg_main, IDC_NC_PASSWORD);
+ EnableWindow(hw, TRUE);
+
+ d->nc->prompts[0]->flags |= KHUI_NCPROMPT_FLAG_STOCK;
+ d->nc->prompts[0]->hwnd_edit = hw;
+ d->nc->prompts[0]->hwnd_static = NULL; /* don't care */
+
+ khui_cw_unlock_nc(d->nc);
+ break;
+ }
+#endif
+ /* for everything else */
+
+ y = d->r_idspec.bottom;
+
+ d->r_custprompt.left = d->r_area.left;
+ d->r_custprompt.right = d->r_area.right;
+ d->r_custprompt.top = y;
+
+ hf = (HFONT) SendMessage(d->dlg_main, WM_GETFONT, 0, 0);
+
+ if (d->nc->pname != NULL) {
+ hw =
+ CreateWindowEx
+ (0,
+ L"STATIC",
+ d->nc->pname,
+ SS_SUNKEN | WS_CHILD,
+ d->r_area.left, y,
+ d->r_row.right,
+ d->r_n_label.bottom - d->r_n_label.top,
+ d->dlg_main,
+ NULL,
+ khm_hInstance,
+ NULL);
+
+#ifdef DEBUG
+ assert(hw);
+#endif
+ d->hwnd_name = hw;
+ SendMessage(hw, WM_SETFONT, (WPARAM)hf, (LPARAM) TRUE);
+ ShowWindow(hw, SW_SHOW);
+
+ y += d->r_n_label.bottom - d->r_n_label.top;
+ }
+
+ if (d->nc->banner != NULL) {
+ hw =
+ CreateWindowEx
+ (0,
+ L"STATIC",
+ d->nc->banner,
+ WS_CHILD,
+ d->r_area.left, y,
+ d->r_row.right, d->r_row.bottom,
+ d->dlg_main,
+ NULL,
+ khm_hInstance,
+ NULL);
+#ifdef DEBUG
+ assert(hw);
+#endif
+ d->hwnd_banner = hw;
+ SendMessage(hw, WM_SETFONT, (WPARAM)hf, (LPARAM)TRUE);
+ ShowWindow(hw, SW_SHOW);
+ y += d->r_row.bottom;
+ }
+
+ hw_prev = d->hwnd_last_idspec;
+
+ hdc = GetWindowDC(d->dlg_main);
+ hfold = SelectObject(hdc,hf);
+
+ /* first do a trial run and see if we should use the
+ larger text labels or not. This is so that all the
+ labels and input controls align properly. */
+ for (i=0; i < d->nc->n_prompts; i++) {
+ if (d->nc->prompts[i]->prompt != NULL) {
+ SIZE s;
+
+ GetTextExtentPoint32(hdc,
+ d->nc->prompts[i]->prompt,
+ (int) wcslen(d->nc->prompts[i]->prompt),
+ &s);
+
+ if(s.cx >= d->r_n_label.right - d->r_n_label.left) {
+ use_large_lables = TRUE;
+ break;
+ }
+ }
+ }
+
+ for(i=0; i<d->nc->n_prompts; i++) {
+ RECT pr, er;
+ SIZE s;
+ int dy;
+
+ if(d->nc->prompts[i]->prompt != NULL) {
+ GetTextExtentPoint32(hdc,
+ d->nc->prompts[i]->prompt,
+ (int) wcslen(d->nc->prompts[i]->prompt),
+ &s);
+ if(s.cx < d->r_n_label.right - d->r_n_label.left &&
+ !use_large_lables) {
+ CopyRect(&pr, &d->r_n_label);
+ CopyRect(&er, &d->r_n_input);
+ dy = d->r_row.bottom;
+ } else if(s.cx <
+ d->r_e_label.right - d->r_e_label.left) {
+ CopyRect(&pr, &d->r_e_label);
+ CopyRect(&er, &d->r_e_input);
+ dy = d->r_row.bottom;
+ } else {
+ /* oops. the prompt doesn't fit in our
+ controls. we need to use up two lines */
+ pr.left = 0;
+ pr.right = d->r_row.right;
+ pr.top = 0;
+ pr.bottom = d->r_n_label.bottom -
+ d->r_n_label.top;
+ CopyRect(&er, &d->r_n_input);
+ OffsetRect(&er, 0, pr.bottom);
+ dy = er.bottom + (d->r_row.bottom -
+ d->r_n_input.bottom);
+ }
+ } else {
+ SetRectEmpty(&pr);
+ CopyRect(&er, &d->r_n_input);
+ dy = d->r_row.bottom;
+ }
+
+ if(IsRectEmpty(&pr)) {
+ d->nc->prompts[i]->hwnd_static = NULL;
+ } else {
+ OffsetRect(&pr, d->r_area.left, y);
+
+ hw = CreateWindowEx
+ (0,
+ L"STATIC",
+ d->nc->prompts[i]->prompt,
+ WS_CHILD,
+ pr.left, pr.top,
+ pr.right - pr.left, pr.bottom - pr.top,
+ d->dlg_main,
+ NULL,
+ khm_hInstance,
+ NULL);
+#ifdef DEBUG
+ assert(hw);
+#endif
+
+ SendMessage(hw, WM_SETFONT,
+ (WPARAM) hf, (LPARAM) TRUE);
+
+ SetWindowPos(hw, hw_prev,
+ 0, 0, 0, 0,
+ SWP_NOACTIVATE | SWP_NOMOVE |
+ SWP_NOOWNERZORDER | SWP_NOSIZE |
+ SWP_SHOWWINDOW);
+
+ d->nc->prompts[i]->hwnd_static = hw;
+ hw_prev = hw;
+ }
+
+ OffsetRect(&er, d->r_area.left, y);
+
+ hw = CreateWindowEx
+ (0,
+ L"EDIT",
+ (d->nc->prompts[i]->def ?
+ d->nc->prompts[i]->def : L""),
+ WS_CHILD | WS_TABSTOP |
+ WS_BORDER |
+ ((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);
+}