diff options
author | Jeffrey Altman <jaltman@secure-endpoints.com> | 2007-04-12 21:19:33 +0000 |
---|---|---|
committer | Jeffrey Altman <jaltman@secure-endpoints.com> | 2007-04-12 21:19:33 +0000 |
commit | 5fe50bd1d38ef818da22e5ef0dce85b83e1dd09b (patch) | |
tree | ff8b62dc8f69fa3de1d485563cb7bb387f8817f3 | |
parent | 927f1754d4d21c606b618b0ffabd819cc1ce453e (diff) | |
download | krb5-5fe50bd1d38ef818da22e5ef0dce85b83e1dd09b.tar.gz krb5-5fe50bd1d38ef818da22e5ef0dce85b83e1dd09b.tar.xz krb5-5fe50bd1d38ef818da22e5ef0dce85b83e1dd09b.zip |
NIM - Fix taskbar button visibility on Vista
Although the Platform SDK docs suggest using ITaskbarList to add/remove
a taskbar button on the fly, it doesn't work on Vista. Instead we will
just set the window style to use WS_EX_APPWINDOW and be done with it.
No change in the NIM version number.
ticket: new
component: windows
tags: pullup
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@19440 dc483132-0cff-0310-8789-dd5450dbe970
-rw-r--r-- | src/windows/identity/ui/mainwnd.c | 2722 | ||||
-rw-r--r-- | src/windows/identity/ui/newcredwnd.c | 5820 | ||||
-rw-r--r-- | src/windows/identity/ui/newcredwnd.h | 378 |
3 files changed, 4455 insertions, 4465 deletions
diff --git a/src/windows/identity/ui/mainwnd.c b/src/windows/identity/ui/mainwnd.c index 159255f1ca..d177b114c7 100644 --- a/src/windows/identity/ui/mainwnd.c +++ b/src/windows/identity/ui/mainwnd.c @@ -1,1364 +1,1358 @@ -/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- * Copyright (c) 2007 Secure Endpoints Inc.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<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;
-
- khm_taskbar_remove_window(khm_hwnd_main);
-
- /* Check if we should destroy all credentials on exit... */
-
- if (KHM_FAILED(khc_open_space(NULL, L"CredWindow", 0, &csp_cw)))
- return;
-
- if (KHM_FAILED(khc_read_int32(csp_cw, L"DestroyCredsOnExit", &t)) ||
- !t)
- goto _cleanup;
-
- if (KHM_FAILED(kcdb_credset_create(&credset)))
- goto _cleanup;
-
- if (KHM_FAILED(kcdb_credset_extract(credset, NULL, NULL,
- KCDB_TYPE_INVALID)))
- goto _cleanup;
-
- if (KHM_FAILED(kcdb_credset_get_size(credset, &s)) ||
- s == 0)
- goto _cleanup;
-
- kcdb_credset_apply(credset, mw_select_cred, NULL);
-
- khui_context_set(KHUI_SCOPE_GROUP,
- NULL,
- KCDB_CREDTYPE_INVALID,
- NULL,
- NULL,
- 0,
- credset);
-
- khm_cred_destroy_creds(TRUE, TRUE);
-
- _cleanup:
-
- if (credset)
- kcdb_credset_delete(credset);
-
- if (csp_cw)
- khc_close_space(csp_cw);
-}
-
-void
-khm_process_query_app_ver(khm_query_app_version * papp_ver) {
-
- if (!papp_ver || papp_ver->magic != KHM_QUERY_APP_VER_MAGIC)
- return;
-
- papp_ver->ver_remote = app_version;
-
- /* the remote instance has requested swapping in. we check the
- version numbers and if the remote instance is newer than us,
- then we exit and let the remote instance take over. */
- if (papp_ver->request_swap) {
- khm_version ver_caller = papp_ver->ver_caller;
-
- if (ver_caller.major > app_version.major ||
-
- (ver_caller.major == app_version.major &&
- ver_caller.minor > app_version.minor) ||
-
- (ver_caller.major == app_version.major &&
- ver_caller.minor == app_version.minor &&
- ver_caller.aux > app_version.aux) ||
-
- (ver_caller.major == app_version.major &&
- ver_caller.minor == app_version.minor &&
- ver_caller.aux == app_version.aux &&
- ver_caller.patch > app_version.patch)) {
-
- papp_ver->request_swap = TRUE;
-
- if (khm_hwnd_main)
- DestroyWindow(khm_hwnd_main);
-
- } else {
-
- papp_ver->request_swap = FALSE;
-
- }
- }
-
- papp_ver->code = KHM_ERROR_SUCCESS;
-}
-
-static void
-khm_ui_cb(LPARAM lParam) {
- khui_ui_callback_data * pcbdata;
-
- pcbdata = (khui_ui_callback_data *) lParam;
-
- if (pcbdata == NULL || pcbdata->magic != KHUI_UICBDATA_MAGIC) {
-#ifdef DEBUG
- assert(FALSE);
-#endif
- return;
- }
-
-#ifdef DEBUG
- assert(pcbdata->cb);
-#endif
-
- /* make the call */
- if (!IsBadCodePtr(pcbdata->cb))
- pcbdata->rv = (*pcbdata->cb)(khm_hwnd_main, pcbdata->rock);
- else {
-#ifdef DEBUG
- assert(FALSE);
-#endif
- pcbdata->rv = KHM_ERROR_INVALID_PARAM;
- }
-}
-
-LRESULT CALLBACK
-khm_main_wnd_proc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam)
-{
- LPNMHDR lpnm;
-
- switch(uMsg) {
- case WM_CREATE:
- khm_create_main_window_controls(hwnd);
- kmq_subscribe_hwnd(KMSG_CRED, hwnd);
- kmq_subscribe_hwnd(KMSG_ACT, hwnd);
- kmq_subscribe_hwnd(KMSG_KMM, hwnd);
- mw_restart_refresh_timer(hwnd);
-
- /* if the plug-ins finished loading before the window was
- created, we would have missed the KMSG_KMM_I_DONE message.
- So we check if the module load is complete and if so, fire
- off KMSG_ACT_BEGIN_CMDLINE. */
- if (!kmm_load_pending())
- kmq_post_message(KMSG_ACT, KMSG_ACT_BEGIN_CMDLINE, 0, 0);
- break;
-
- case WM_DESTROY:
- khm_pre_shutdown();
- kmq_unsubscribe_hwnd(KMSG_ACT, hwnd);
- kmq_unsubscribe_hwnd(KMSG_CRED, hwnd);
- kmq_unsubscribe_hwnd(KMSG_KMM, hwnd);
- HtmlHelp(NULL, NULL, HH_CLOSE_ALL, 0);
- PostQuitMessage(0);
- break;
-
- case WM_NOTIFY:
- lpnm = (LPNMHDR) lParam;
- if(lpnm->hwndFrom == khui_main_menu_toolbar) {
- return khm_menu_notify_main(lpnm);
- } else if(lpnm->hwndFrom == khui_hwnd_standard_toolbar) {
- return khm_toolbar_notify(lpnm);
- } else if(lpnm->hwndFrom == khm_hwnd_rebar) {
- return khm_rebar_notify(lpnm);
- } else if(lpnm->hwndFrom == khm_hwnd_statusbar) {
- return khm_statusbar_notify(lpnm);
- }
- break;
-
- case WM_HELP:
- khm_html_help(khm_hwnd_main, NULL, HH_HELP_CONTEXT, IDH_WELCOME);
- break;
-
- case WM_COMMAND:
- switch(LOWORD(wParam)) {
- /* general actions */
- case KHUI_ACTION_VIEW_REFRESH:
- khm_cred_refresh();
- InvalidateRect(khm_hwnd_main_cred, NULL, FALSE);
- return 0;
-
- case KHUI_ACTION_PASSWD_ID:
- if (khm_startup.processing)
- return 0;
-
- khm_cred_change_password(NULL);
- return 0;
-
- case KHUI_ACTION_NEW_CRED:
- if (khm_startup.processing)
- return 0;
-
- khm_cred_obtain_new_creds(NULL);
- return 0;
-
- case KHUI_ACTION_RENEW_CRED:
- if (khm_startup.processing)
- return 0;
-
- khm_cred_renew_creds();
- return 0;
-
- case KHUI_ACTION_DESTROY_CRED:
- if (khm_startup.processing)
- return 0;
-
- khm_cred_destroy_creds(FALSE, FALSE);
- return 0;
-
- case KHUI_ACTION_SET_DEF_ID:
- if (khm_startup.processing)
- return 0;
-
- khm_cred_set_default();
- return 0;
-
- case KHUI_ACTION_EXIT:
- DestroyWindow(hwnd);
- return 0;
-
- case KHUI_ACTION_OPEN_APP:
- khm_show_main_window();
- return 0;
-
- case KHUI_ACTION_CLOSE_APP:
- khm_hide_main_window();
- return 0;
-
- case KHUI_ACTION_OPT_KHIM: {
- khui_config_node node = NULL;
-
- khui_cfg_open(NULL, L"KhmGeneral", &node);
- khm_show_config_pane(node);
- }
- return 0;
-
- case KHUI_ACTION_OPT_IDENTS: {
- khui_config_node node = NULL;
-
- khui_cfg_open(NULL, L"KhmIdentities", &node);
- khm_show_config_pane(node);
- }
- return 0;
-
- case KHUI_ACTION_OPT_APPEAR: {
- khui_config_node node = NULL;
-
- khui_cfg_open(NULL, L"KhmAppear", &node);
- khm_show_config_pane(node);
- }
- return 0;
-
- case KHUI_ACTION_OPT_NOTIF: {
- khui_config_node node = NULL;
-
- khui_cfg_open(NULL, L"KhmNotifications", &node);
- khm_show_config_pane(node);
- }
- return 0;
-
- case KHUI_ACTION_OPT_PLUGINS: {
- khui_config_node node = NULL;
-
- khui_cfg_open(NULL, L"KhmPlugins", &node);
- khm_show_config_pane(node);
- }
- return 0;
-
- case KHUI_ACTION_HELP_CTX:
- khm_html_help(khm_hwnd_main, NULL, HH_HELP_CONTEXT, IDH_WELCOME);
- return 0;
-
- case KHUI_ACTION_HELP_CONTENTS:
- khm_html_help(khm_hwnd_main, NULL, HH_DISPLAY_TOC, 0);
- return 0;
-
- case KHUI_ACTION_HELP_INDEX:
- khm_html_help(khm_hwnd_main, NULL, HH_DISPLAY_INDEX, (DWORD_PTR) L"");
- return 0;
-
- case KHUI_ACTION_HELP_ABOUT:
- khm_create_about_window();
- return 0;
-
- case KHUI_ACTION_IMPORT:
- khm_cred_import();
- return 0;
-
- case KHUI_ACTION_PROPERTIES:
- /* properties are not handled by the main window.
- Just bounce it to credwnd. However, use SendMessage
- instead of PostMessage so we don't lose context */
- return SendMessage(khm_hwnd_main_cred, uMsg,
- wParam, lParam);
-
- case KHUI_ACTION_UICB:
- khm_ui_cb(lParam);
- return 0;
-
- /* layout control */
- case KHUI_ACTION_LAYOUT_MINI:
- if (khm_main_wnd_mode == KHM_MAIN_WND_MINI) {
- khm_set_main_window_mode(KHM_MAIN_WND_NORMAL);
- } else {
- khm_set_main_window_mode(KHM_MAIN_WND_MINI);
- }
- return SendMessage(khm_hwnd_main_cred, uMsg,
- wParam, lParam);
-
- case KHUI_ACTION_LAYOUT_RELOAD:
- return SendMessage(khm_hwnd_main_cred, uMsg,
- wParam, lParam);
-
- case KHUI_ACTION_LAYOUT_ID:
- case KHUI_ACTION_LAYOUT_TYPE:
- case KHUI_ACTION_LAYOUT_LOC:
- case KHUI_ACTION_LAYOUT_CUST:
- khm_set_main_window_mode(KHM_MAIN_WND_NORMAL);
- return SendMessage(khm_hwnd_main_cred, uMsg,
- wParam, lParam);
-
- /* menu commands */
- case KHUI_PACTION_MENU:
- if(HIWORD(lParam) == 1)
- mm_last_hot_item = LOWORD(lParam);
- return khm_menu_activate(MENU_ACTIVATE_DEFAULT);
-
- case KHUI_PACTION_ESC:
- /* if esc is pressed while no menu is active, we close the
- main window */
- if (mm_last_hot_item == -1) {
- khm_close_main_window();
- return 0;
- }
-
- /* generic, retargetting */
- case KHUI_PACTION_UP:
- case KHUI_PACTION_UP_TOGGLE:
- case KHUI_PACTION_UP_EXTEND:
- case KHUI_PACTION_PGUP:
- case KHUI_PACTION_PGUP_EXTEND:
- case KHUI_PACTION_DOWN:
- case KHUI_PACTION_DOWN_TOGGLE:
- case KHUI_PACTION_DOWN_EXTEND:
- case KHUI_PACTION_PGDN:
- case KHUI_PACTION_PGDN_EXTEND:
- case KHUI_PACTION_LEFT:
- case KHUI_PACTION_RIGHT:
- case KHUI_PACTION_ENTER:
- /* menu tracking */
- if(mm_last_hot_item != -1) {
- switch(LOWORD(wParam)) {
- case KHUI_PACTION_LEFT:
- khm_menu_activate(MENU_ACTIVATE_LEFT);
- break;
-
- case KHUI_PACTION_RIGHT:
- khm_menu_activate(MENU_ACTIVATE_RIGHT);
- break;
-
- case KHUI_PACTION_ESC:
- case KHUI_PACTION_ENTER:
- khm_menu_activate(MENU_ACTIVATE_NONE);
- break;
-
- case KHUI_PACTION_DOWN:
- khm_menu_track_current();
- break;
- }
- return 0;
- }
-
- /*FALLTHROUGH*/
- case KHUI_PACTION_DELETE:
-
- case KHUI_PACTION_SELALL:
- /* otherwise fallthrough and bounce to the creds window */
- return SendMessage(khm_hwnd_main_cred, uMsg,
- wParam, lParam);
-
- default:
- /* handle custom actions here */
- {
- khui_action * act;
-
- /* check if this is an identity menu action. (custom
- actions that were created for renewing or
- destroying specific identities). */
- if (khm_check_identity_menu_action(LOWORD(wParam)))
- break;
-
- act = khui_find_action(LOWORD(wParam));
- if (act && act->listener) {
- kmq_post_sub_msg(act->listener, KMSG_ACT, KMSG_ACT_ACTIVATE, act->cmd, NULL);
- return 0;
- }
- }
- }
- break; /* WM_COMMAND */
-
- case WM_SYSCOMMAND:
- switch(wParam & 0xfff0) {
- case SC_MINIMIZE:
- khm_hide_main_window();
- return 0;
-
- case SC_CLOSE:
- khm_close_main_window();
- return 0;
- }
- break;
-
- case WM_MEASUREITEM:
- /* sent to measure the bitmaps associated with a menu item */
- if(!wParam) /* sent by menu */
- return khm_menu_measure_item(wParam, lParam);
- break;
-
- case WM_DRAWITEM:
- /* sent to draw a menu item */
- if(!wParam)
- return khm_menu_draw_item(wParam, lParam);
- break;
-
- case WM_ERASEBKGND:
- /* Don't erase the background. The whole client area is
- covered with children. It doesn't need to be erased */
- return TRUE;
- break;
-
- case WM_SIZE:
- if(hwnd == khm_hwnd_main &&
- (wParam == SIZE_MAXIMIZED || wParam == SIZE_RESTORED)) {
- int cwidth, cheight;
- RECT r_rebar, r_status;
-
- cwidth = LOWORD(lParam);
- cheight = HIWORD(lParam);
-
- /* resize the rebar control */
- SendMessage(khm_hwnd_rebar, WM_SIZE, 0, 0);
-
- khm_update_statusbar(hwnd);
-
- GetWindowRect(khm_hwnd_rebar, &r_rebar);
- GetWindowRect(khm_hwnd_statusbar, &r_status);
-
- /* the cred window fills the area between the rebar
- and the status bar */
- MoveWindow(khm_hwnd_main_cred, 0,
- r_rebar.bottom - r_rebar.top,
- r_status.right - r_status.left,
- r_status.top - r_rebar.bottom, TRUE);
-
- SetTimer(hwnd,
- MW_RESIZE_TIMER,
- MW_RESIZE_TIMEOUT,
- NULL);
- return 0;
- }
- break;
-
- case WM_MOVE:
- {
- SetTimer(hwnd,
- MW_RESIZE_TIMER,
- MW_RESIZE_TIMEOUT,
- NULL);
-
- return 0;
- }
- break;
-
- case WM_MOVING:
- {
- RECT * r;
-
- r = (RECT *) lParam;
- khm_adjust_window_dimensions_for_display(r,
- KHM_DOCK_AUTO | KHM_DOCKF_XBORDER);
- }
- return TRUE;
-
- case WM_TIMER:
- if (wParam == MW_RESIZE_TIMER) {
- RECT r;
- khm_handle csp_cw;
- khm_handle csp_mw;
- const wchar_t * wconfig;
-
- if (khm_main_wnd_mode == KHM_MAIN_WND_MINI)
- wconfig = L"Windows\\MainMini";
- else
- wconfig = L"Windows\\Main";
-
- KillTimer(hwnd, wParam);
-
- GetWindowRect(hwnd, &r);
-
- if (KHM_SUCCEEDED(khc_open_space(NULL,
- L"CredWindow",
- KHM_PERM_WRITE,
- &csp_cw))) {
- if (KHM_SUCCEEDED(khc_open_space(csp_cw,
- wconfig,
- KHM_PERM_WRITE,
- &csp_mw))) {
- khm_int32 t;
-
- khc_write_int32(csp_mw, L"XPos", r.left);
- khc_write_int32(csp_mw, L"YPos", r.top);
- khc_write_int32(csp_mw, L"Width",
- r.right - r.left);
- khc_write_int32(csp_mw, L"Height",
- r.bottom - r.top);
-
- if (KHM_SUCCEEDED(khc_read_int32(csp_mw, L"Dock", &t)) &&
- t != KHM_DOCK_NONE) {
- khc_write_int32(csp_mw, L"Dock", KHM_DOCK_AUTO);
- }
-
- khc_close_space(csp_mw);
- }
- khc_close_space(csp_cw);
- }
-
- return 0;
-
- } else if (wParam == MW_REFRESH_TIMER) {
- kmq_post_message(KMSG_CRED, KMSG_CRED_REFRESH, 0, 0);
-
- return 0;
-
- }
- break;
-
- case WM_MENUSELECT:
- return khm_menu_handle_select(wParam, lParam);
-
- case KMQ_WM_DISPATCH:
- {
- kmq_message * m;
- khm_int32 rv = KHM_ERROR_SUCCESS;
-
- kmq_wm_begin(lParam, &m);
- if (m->type == KMSG_ACT &&
- m->subtype == KMSG_ACT_REFRESH) {
- khm_menu_refresh_items();
- khm_update_standard_toolbar();
- } else if (m->type == KMSG_ACT &&
- m->subtype == KMSG_ACT_BEGIN_CMDLINE) {
- khm_cred_begin_startup_actions();
- } else if (m->type == KMSG_ACT &&
- m->subtype == KMSG_ACT_CONTINUE_CMDLINE) {
- khm_cred_process_startup_actions();
- } else if (m->type == KMSG_ACT &&
- m->subtype == KMSG_ACT_END_CMDLINE) {
- /* nothing yet */
- } else if (m->type == KMSG_ACT &&
- m->subtype == KMSG_ACT_SYNC_CFG) {
- khm_refresh_config();
- } else if (m->type == KMSG_ACT &&
- m->subtype == KMSG_ACT_ACTIVATE) {
- /* some custom action fired */
-
- khm_int32 action;
- khui_action * paction;
-
- action = m->uparam;
- paction = khui_find_action(action);
- if (paction && paction->data == (void *) CFGACTION_MAGIC) {
- /* a custom configuration needs to be invoked */
- khui_config_node node;
-
- if (KHM_SUCCEEDED(khui_cfg_open(NULL, paction->name, &node))) {
- khm_show_config_pane(node);
- khui_cfg_release(node);
- }
- }
- } else if (m->type == KMSG_CRED &&
- m->subtype == KMSG_CRED_REFRESH) {
- mw_restart_refresh_timer(hwnd);
- } else if (m->type == KMSG_CRED &&
- m->subtype == KMSG_CRED_ADDR_CHANGE) {
- khm_cred_addr_change();
- } else if (m->type == KMSG_CRED &&
- m->subtype == KMSG_CRED_ROOTDELTA) {
- khm_refresh_identity_menus();
- } else if (m->type == KMSG_KMM &&
- m->subtype == KMSG_KMM_I_DONE) {
- kmq_post_message(KMSG_ACT, KMSG_ACT_BEGIN_CMDLINE, 0, 0);
- }
-
- return kmq_wm_end(m, rv);
- }
- return 0;
-
- case WM_KHUI_ASSIGN_COMMANDLINE_V1:
- {
- HANDLE hmap;
- void * xfer;
- wchar_t mapname[256];
- struct tag_khm_startup_options_v1 * pv1opt;
- int code = KHM_ERROR_SUCCESS;
-
- StringCbPrintf(mapname, sizeof(mapname),
- COMMANDLINE_MAP_FMT, (DWORD) lParam);
-
- hmap = OpenFileMapping(FILE_MAP_READ, FALSE, mapname);
-
- if (hmap == NULL)
- return 1;
-
- xfer = MapViewOfFile(hmap, FILE_MAP_READ, 0, 0,
- sizeof(*pv1opt));
-
- if (xfer) {
- pv1opt = (struct tag_khm_startup_options_v1 *) xfer;
-
- khm_startup.init = pv1opt->init;
- khm_startup.import = pv1opt->import;
- khm_startup.renew = pv1opt->renew;
- khm_startup.destroy = pv1opt->destroy;
-
- khm_startup.autoinit = pv1opt->autoinit;
- khm_startup.error_exit = FALSE;
-
- khm_startup.no_main_window = FALSE;
- khm_startup.remote_exit = FALSE;
-
- UnmapViewOfFile(xfer);
- } else {
- code = KHM_ERROR_NOT_FOUND;
- }
-
- CloseHandle(hmap);
-
- if(InSendMessage())
- ReplyMessage(code);
-
- if (code == KHM_ERROR_SUCCESS) {
- khm_startup.exit = FALSE;
-
- khm_startup.seen = FALSE;
- khm_startup.remote = TRUE;
-#ifdef DEBUG
- assert(!khm_startup.processing);
-#endif
- khm_startup.processing = FALSE;
-
- khm_cred_begin_startup_actions();
- }
-
- return code;
- }
-
- case WM_KHUI_ASSIGN_COMMANDLINE_V2:
- {
- HANDLE hmap;
- void * xfer;
- wchar_t mapname[256];
- struct tag_khm_startup_options_v2 *pv2opt;
- int code = KHM_ERROR_SUCCESS;
-
- StringCbPrintf(mapname, sizeof(mapname),
- COMMANDLINE_MAP_FMT, (DWORD) lParam);
-
- hmap = OpenFileMapping(FILE_MAP_WRITE, FALSE, mapname);
-
- if (hmap == NULL)
- return 1;
-
- xfer = MapViewOfFile(hmap, FILE_MAP_WRITE, 0, 0,
- sizeof(*pv2opt));
-
- if (xfer) {
- pv2opt = (struct tag_khm_startup_options_v2 *) xfer;
-
- if (pv2opt->magic != STARTUP_OPTIONS_MAGIC ||
- pv2opt->cb_size != sizeof(*pv2opt)) {
- code = KHM_ERROR_INVALID_PARAM;
- goto done_with_v2_opt;
- }
-
- khm_startup.init = pv2opt->init;
- khm_startup.import = pv2opt->import;
- khm_startup.renew = pv2opt->renew;
- khm_startup.destroy = pv2opt->destroy;
-
- khm_startup.autoinit = pv2opt->autoinit;
- khm_startup.exit = pv2opt->remote_exit;
-
- pv2opt->code = KHM_ERROR_SUCCESS;
-
- done_with_v2_opt:
- UnmapViewOfFile(xfer);
- } else {
- code = KHM_ERROR_NOT_FOUND;
- }
-
- CloseHandle(hmap);
-
- if(InSendMessage())
- ReplyMessage(code);
-
- if (code == KHM_ERROR_SUCCESS) {
- khm_startup.seen = FALSE;
- khm_startup.remote = TRUE;
-#ifdef DEBUG
- assert(!khm_startup.processing);
-#endif
- khm_startup.processing = FALSE;
-
- khm_cred_begin_startup_actions();
- }
-
- return code;
- }
-
- case WM_KHUI_QUERY_APP_VERSION:
- {
- HANDLE hmap;
- void * xfer;
- wchar_t mapname[256];
-
- StringCbPrintf(mapname, sizeof(mapname),
- QUERY_APP_VER_MAP_FMT, (DWORD) lParam);
-
- hmap = OpenFileMapping(FILE_MAP_READ | FILE_MAP_WRITE,
- FALSE, mapname);
-
- if (hmap == NULL)
- return 1;
-
- xfer = MapViewOfFile(hmap, FILE_MAP_WRITE, 0, 0,
- sizeof(khm_query_app_version));
-
- if (xfer) {
- khm_process_query_app_ver((khm_query_app_version *) xfer);
-
- UnmapViewOfFile(xfer);
- }
-
- CloseHandle(hmap);
- }
- return 0;
-
- }
- return DefWindowProc(hwnd,uMsg,wParam,lParam);
-}
-
-LRESULT CALLBACK
-khm_null_wnd_proc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam) {
- return DefWindowProc(hwnd, uMsg, wParam, lParam);
-}
-
-LRESULT
-khm_rebar_notify(LPNMHDR lpnm) {
- switch(lpnm->code) {
-#if (_WIN32_WINNT >= 0x0501)
- case RBN_AUTOBREAK:
- {
- LPNMREBARAUTOBREAK lpra = (LPNMREBARAUTOBREAK) lpnm;
- lpra->fAutoBreak = TRUE;
- }
- break;
-#endif
- case RBN_BEGINDRAG:
- {
- LPNMREBAR lprb = (LPNMREBAR) lpnm;
- if ((lprb->dwMask & RBNM_ID) &&
- lprb->wID == 0)
- return 1;
- else
- return 0;
- }
- break;
-
- case NM_CUSTOMDRAW:
- return CDRF_DODEFAULT;
- break;
- }
-
- return 1;
-}
-
-void
-khm_create_main_window_controls(HWND hwnd_main) {
- REBARINFO rbi;
- HWND hwRebar;
-
- khm_menu_create_main(hwnd_main);
-
- hwRebar =
- CreateWindowEx(WS_EX_TOOLWINDOW,
- REBARCLASSNAME,
- L"Rebar",
- WS_CHILD |
- WS_VISIBLE|
- WS_CLIPSIBLINGS |
- WS_CLIPCHILDREN |
- CCS_NODIVIDER |
- RBS_VARHEIGHT |
- RBS_FIXEDORDER,
- 0,0,0,0,
- hwnd_main,
- NULL,
- khm_hInstance,
- NULL);
-
- if(!hwRebar) {
- DWORD dwe = GetLastError();
- return;
- }
-
- khm_hwnd_rebar = hwRebar;
-
- rbi.cbSize = sizeof(rbi);
- rbi.fMask = 0;
- rbi.himl = (HIMAGELIST) NULL;
- if(!SendMessage(hwRebar, RB_SETBARINFO, 0, (LPARAM) &rbi))
- return;
-
- /* self attach */
- khm_create_standard_toolbar(hwRebar);
- khm_create_statusbar(hwnd_main);
-
- /* manual attach */
- khm_hwnd_main_cred = khm_create_credwnd(hwnd_main);
-}
-
-void
-khm_adjust_window_dimensions_for_display(RECT * pr, int dock) {
-
- HMONITOR hmon;
- RECT rm;
- long x, y, width, height;
-
- x = pr->left;
- y = pr->top;
- width = pr->right - pr->left;
- height = pr->bottom - pr->top;
-
- /* if the rect doesn't intersect with the display area of any
- monitor, we just default to the primary monitor. */
- hmon = MonitorFromRect(pr, MONITOR_DEFAULTTOPRIMARY);
-
- if (hmon == NULL) {
- /* huh? we'll just center this on the primary screen */
- goto nomonitor;
- } else {
- MONITORINFO mi;
-
- ZeroMemory(&mi, sizeof(mi));
- mi.cbSize = sizeof(mi);
-
- if (!GetMonitorInfo(hmon, &mi))
- goto nomonitor;
-
- CopyRect(&rm, &mi.rcWork);
-
- goto adjust_dims;
- }
-
- nomonitor:
- /* for some reason we couldn't get a handle on a monitor or we
- couldn't get the metrics for that monitor. We default to
- setting things up on the primary monitor. */
-
- SetRectEmpty(&rm);
- if (!SystemParametersInfo(SPI_GETWORKAREA, 0, (PVOID) &rm, 0))
- goto done_with_monitor;
-
- adjust_dims:
-
- if (width > (rm.right - rm.left))
- width = rm.right - rm.left;
- if (height > (rm.bottom - rm.top))
- height = rm.bottom - rm.top;
-
- switch (dock & KHM_DOCKF_DOCKHINT) {
- case KHM_DOCK_TOPLEFT:
- x = rm.left;
- y = rm.top;
- break;
-
- case KHM_DOCK_TOPRIGHT:
- x = rm.right - width;
- y = rm.top;
- break;
-
- case KHM_DOCK_BOTTOMRIGHT:
- x = rm.right - width;
- y = rm.bottom - height;
- break;
-
- case KHM_DOCK_BOTTOMLEFT:
- x = rm.left;
- y = rm.bottom - height;
- break;
-
- case KHM_DOCK_AUTO:
- {
- int cxt, cyt;
-
- cxt = GetSystemMetrics(SM_CXDRAG);
- cyt = GetSystemMetrics(SM_CYDRAG);
-
- if (x > rm.left && (x - rm.left) < cxt)
- x = rm.left;
- else if ((x + width) < rm.right && (rm.right - (x + width)) < cxt)
- x = rm.right - width;
-
- if (y > rm.top && (y - rm.top) < cyt)
- y = rm.top;
- else if ((y + height) < rm.bottom && (rm.bottom - (y + height)) < cyt)
- y = rm.bottom - height;
- }
- break;
- }
-
- if (!(dock & KHM_DOCKF_XBORDER)) {
- if (x < rm.left)
- x = rm.left;
- if (x + width > rm.right)
- x = rm.right - width;
- if (y < rm.top)
- y = rm.top;
- if (y + height > rm.bottom)
- y = rm.bottom - height;
- }
-
- done_with_monitor:
- pr->left = x;
- pr->top = y;
- pr->right = x + width;
- pr->bottom = y + height;
-
-}
-
-void
-khm_get_main_window_rect(RECT * pr) {
- khm_handle csp_mw = NULL;
- int x,y,width,height,dock;
- RECT r;
- const wchar_t * wconfig;
-
- x = CW_USEDEFAULT;
- y = CW_USEDEFAULT;
- width = CW_USEDEFAULT;
- height = CW_USEDEFAULT;
- dock = KHM_DOCK_NONE;
-
- if (khm_main_wnd_mode == KHM_MAIN_WND_MINI)
- wconfig = L"CredWindow\\Windows\\MainMini";
- else
- wconfig = L"CredWindow\\Windows\\Main";
-
- if (KHM_SUCCEEDED(khc_open_space(NULL,
- wconfig,
- KHM_PERM_READ,
- &csp_mw))) {
- khm_int32 t;
-
- if (KHM_SUCCEEDED(khc_read_int32(csp_mw, L"XPos", &t)))
- x = t;
- if (KHM_SUCCEEDED(khc_read_int32(csp_mw, L"YPos", &t)))
- y = t;
- if (KHM_SUCCEEDED(khc_read_int32(csp_mw, L"Width", &t)))
- width = t;
- if (KHM_SUCCEEDED(khc_read_int32(csp_mw, L"Height", &t)))
- height = t;
- if (KHM_SUCCEEDED(khc_read_int32(csp_mw, L"Dock", &t)))
- dock = t;
-
- khc_close_space(csp_mw);
- }
-
- /* If there were no default values, we default to using 1/4 of the
- work area centered on the primary monitor. If there were any
- docking hints, then the next call to
- khm_adjust_window_dimensions_for_display() will reposition the
- window. */
- if (width == CW_USEDEFAULT || x == CW_USEDEFAULT) {
- RECT wr;
-
- SetRectEmpty(&wr);
- SystemParametersInfo(SPI_GETWORKAREA, 0, &wr, 0);
-
- if (width == CW_USEDEFAULT) {
- width = (wr.right - wr.left) / 2;
- height = (wr.bottom - wr.top) / 2;
- }
-
- if (x == CW_USEDEFAULT) {
- x = (wr.left + wr.right) / 2 - width / 2;
- y = (wr.top + wr.bottom) / 2 - height / 2;
- }
- }
-
- /* The saved dimensions might not actually be visible if the user
- has changed the resolution of the display or if it's a multiple
- monitor system where the monitor on which the Network Identity
- Manager window was on previously is no longer connected. We
- have to check for that and adjust the dimensions if needed. */
- SetRect(&r, x, y, x + width, y + height);
- khm_adjust_window_dimensions_for_display(&r, dock);
-
- *pr = r;
-}
-
-void
-khm_set_main_window_mode(int mode) {
-
- RECT r;
- khm_handle csp_cw;
-
- if (mode == khm_main_wnd_mode)
- return;
-
- khui_check_action(KHUI_ACTION_LAYOUT_MINI,
- ((mode == KHM_MAIN_WND_MINI)? FALSE : TRUE));
- khui_enable_action(KHUI_MENU_LAYOUT,
- ((mode == KHM_MAIN_WND_MINI)? FALSE : TRUE));
- khui_enable_action(KHUI_MENU_COLUMNS,
- ((mode == KHM_MAIN_WND_MINI)? FALSE : TRUE));
-
- khui_refresh_actions();
-
- khm_main_wnd_mode = mode;
- if (khm_hwnd_main) {
- khm_get_main_window_rect(&r);
-
- SetWindowPos(khm_hwnd_main,
- NULL,
- r.left, r.top,
- r.right - r.left, r.bottom - r.top,
- SWP_NOACTIVATE | SWP_NOOWNERZORDER |
- SWP_NOZORDER);
- }
-
- if (KHM_SUCCEEDED(khc_open_space(NULL, L"CredWindow", KHM_PERM_WRITE,
- &csp_cw))) {
-
- khc_write_int32(csp_cw, L"DefaultWindowMode", mode);
- khc_close_space(csp_cw);
-
- }
-
- khm_cred_refresh();
-}
-
-void
-khm_create_main_window(void) {
- wchar_t buf[1024];
- khm_handle csp_cw = NULL;
- RECT r;
-
- LoadString(khm_hInstance, IDS_MAIN_WINDOW_TITLE,
- buf, ARRAYLENGTH(buf));
-
- khm_hwnd_null =
- CreateWindow(MAKEINTATOM(khm_null_window_class),
- buf,
- 0, /* Style */
- 0, 0, /* x, y */
- 100, 100, /* width, height */
- NULL, /* parent */
- NULL, /* menu */
- NULL, /* HINSTANCE */
- 0); /* lparam */
-
- if (!khm_hwnd_null)
- return;
-
- if (KHM_SUCCEEDED(khc_open_space(NULL, L"CredWindow",
- KHM_PERM_READ,
- &csp_cw))) {
- khm_int32 t;
-
- if (KHM_SUCCEEDED(khc_read_int32(csp_cw, L"DefaultWindowMode", &t))) {
- khm_set_main_window_mode(t);
- }
-
- khc_close_space(csp_cw);
- }
-
- khm_get_main_window_rect(&r);
-
- khm_hwnd_main =
- CreateWindowEx(WS_EX_OVERLAPPEDWINDOW,
- MAKEINTATOM(khm_main_window_class),
- buf,
- WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN |
- WS_CLIPSIBLINGS,
- r.left, r.top,
- r.right - r.left,
- r.bottom - r.top,
- khm_hwnd_null,
- NULL,
- NULL,
- NULL);
-
- khui_set_main_window(khm_hwnd_main);
-}
-
-void
-khm_show_main_window(void) {
-
- if (khm_nCmdShow == SW_RESTORE) {
- HWND hw;
-
- hw = GetForegroundWindow();
- if (hw != khm_hwnd_main)
- SetForegroundWindow(khm_hwnd_main);
- }
-
- if (khm_nCmdShow == SW_SHOWMINIMIZED ||
- khm_nCmdShow == SW_SHOWMINNOACTIVE ||
- khm_nCmdShow == SW_MINIMIZE) {
- khm_hide_main_window();
- } else {
- ShowWindow(khm_hwnd_main, khm_nCmdShow);
- UpdateWindow(khm_hwnd_main);
-
- khm_taskbar_add_window(khm_hwnd_main);
-
- khm_cred_refresh();
- }
-
- khm_nCmdShow = SW_RESTORE;
-}
-
-void
-khm_activate_main_window(void) {
-
- if (!SetForegroundWindow(khm_hwnd_main)) {
- FLASHWINFO finfo;
-
- SetActiveWindow(khm_hwnd_main);
-
- ZeroMemory(&finfo, sizeof(finfo));
- finfo.cbSize = sizeof(finfo);
- finfo.hwnd = khm_hwnd_main;
- finfo.dwFlags = FLASHW_ALL;
- finfo.uCount = 3;
- finfo.dwTimeout = 0;
-
- FlashWindowEx(&finfo);
- }
-}
-
-void
-khm_close_main_window(void) {
- khm_handle csp_cw;
- BOOL keep_running = FALSE;
-
- if (KHM_SUCCEEDED(khc_open_space(NULL, L"CredWindow",
- KHM_PERM_READ, &csp_cw))) {
- khm_int32 t;
-
- if (KHM_SUCCEEDED(khc_read_int32(csp_cw, L"KeepRunning",
- &t))) {
- keep_running = t;
- } else {
-#ifdef DEBUG
- assert(FALSE);
-#endif
- }
-
- khc_close_space(csp_cw);
- } else {
-#ifdef DEBUG
- assert(FALSE);
-#endif
- }
-
- if (keep_running)
- khm_hide_main_window();
- else
- DestroyWindow(khm_hwnd_main);
-}
-
-void
-khm_hide_main_window(void) {
- khm_handle csp_notices = NULL;
- khm_int32 show_warning = FALSE;
-
- if (khm_nCmdShow != SW_MINIMIZE &&
- KHM_SUCCEEDED(khc_open_space(NULL, L"CredWindow\\Notices",
- KHM_PERM_WRITE, &csp_notices)) &&
- KHM_SUCCEEDED(khc_read_int32(csp_notices, L"MinimizeWarning",
- &show_warning)) &&
- show_warning != 0) {
-
- khui_alert * alert;
- wchar_t title[KHUI_MAXCCH_TITLE];
- wchar_t msg[KHUI_MAXCCH_MESSAGE];
-
- LoadString(khm_hInstance, IDS_WARN_WM_TITLE,
- title, ARRAYLENGTH(title));
- LoadString(khm_hInstance, IDS_WARN_WM_MSG,
- msg, ARRAYLENGTH(msg));
-
- khui_alert_create_simple(title, msg, KHERR_INFO, &alert);
- khui_alert_set_flags(alert, KHUI_ALERT_FLAG_REQUEST_BALLOON,
- KHUI_ALERT_FLAG_REQUEST_BALLOON);
-
- khui_alert_show(alert);
-
- khc_write_int32(csp_notices, L"MinimizeWarning", 0);
- }
-
- if (csp_notices != NULL)
- khc_close_space(csp_notices);
-
- ShowWindow(khm_hwnd_main, SW_HIDE);
-
- khm_taskbar_remove_window(khm_hwnd_main);
-}
-
-BOOL
-khm_is_main_window_visible(void) {
- return IsWindowVisible(khm_hwnd_main);
-}
-
-BOOL
-khm_is_main_window_active(void) {
- if (!IsWindowVisible(khm_hwnd_main))
- return FALSE;
- if (GetForegroundWindow() == khm_hwnd_main)
- return TRUE;
- return khm_is_dialog_active();
-}
-
-void
-khm_register_main_wnd_class(void) {
- WNDCLASSEX wc;
-
- wc.cbSize = sizeof(WNDCLASSEX);
- wc.style = 0;
- wc.lpfnWndProc = khm_null_wnd_proc;
- wc.cbClsExtra = 0;
- wc.cbWndExtra = 0;
- wc.hInstance = khm_hInstance;
- wc.hIcon = LoadIcon(khm_hInstance, MAKEINTRESOURCE(IDI_MAIN_APP));
- wc.hCursor = LoadCursor((HINSTANCE) NULL, MAKEINTRESOURCE(IDC_ARROW));
- wc.hIconSm = LoadImage(khm_hInstance, MAKEINTRESOURCE(IDI_MAIN_APP), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE);
- wc.hbrBackground = (HBRUSH) (COLOR_APPWORKSPACE);
- wc.lpszMenuName = NULL;
- wc.lpszClassName = KHUI_NULL_WINDOW_CLASS;
-
- khm_null_window_class = RegisterClassEx(&wc);
-
- wc.cbSize = sizeof(WNDCLASSEX);
- wc.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
- wc.lpfnWndProc = khm_main_wnd_proc;
- wc.cbClsExtra = 0;
- wc.cbWndExtra = 0;
- wc.hInstance = khm_hInstance;
- wc.hIcon = LoadIcon(khm_hInstance, MAKEINTRESOURCE(IDI_MAIN_APP));
- wc.hCursor = LoadCursor((HINSTANCE) NULL, MAKEINTRESOURCE(IDC_ARROW));
- wc.hIconSm = LoadImage(khm_hInstance, MAKEINTRESOURCE(IDI_MAIN_APP), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE);
- wc.hbrBackground = (HBRUSH) (COLOR_APPWORKSPACE);
- wc.lpszMenuName = NULL;
- wc.lpszClassName = KHUI_MAIN_WINDOW_CLASS;
-
- khm_main_window_class = RegisterClassEx(&wc);
-}
-
-void
-khm_unregister_main_wnd_class(void) {
- UnregisterClass(MAKEINTATOM(khm_main_window_class),khm_hInstance);
- UnregisterClass(MAKEINTATOM(khm_null_window_class),khm_hInstance);
-}
+/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * Copyright (c) 2007 Secure Endpoints Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include<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); +} diff --git a/src/windows/identity/ui/newcredwnd.c b/src/windows/identity/ui/newcredwnd.c index d4d9a785c6..6c8ea60943 100644 --- a/src/windows/identity/ui/newcredwnd.c +++ b/src/windows/identity/ui/newcredwnd.c @@ -1,2912 +1,2908 @@ -/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- * Copyright (c) 2007 Secure Endpoints Inc.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-/* Include the OEMRESOURCE constants for locating standard icon
- resources. */
-#define OEMRESOURCE
-
-#include<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);
-
- khm_taskbar_add_window(hwnd);
-
- return TRUE;
-}
-
-/* add a control row supplied by an identity provider */
-static void
-nc_add_control_row(khui_nc_wnd_data * d,
- HWND label,
- HWND input,
- khui_control_size size)
-{
- RECT r_row;
- RECT r_label;
- RECT r_input;
- HFONT hf;
- HDWP hdefer;
-
- hf = (HFONT) SendMessage(d->dlg_main, WM_GETFONT, 0, 0);
- SendMessage(label, WM_SETFONT, (WPARAM) hf, FALSE);
- SendMessage(input, WM_SETFONT, (WPARAM) hf, FALSE);
-
- CopyRect(&r_row, &d->r_row);
- OffsetRect(&r_row, d->r_idspec.left, d->r_idspec.bottom);
-
- if (size == KHUI_CTRLSIZE_SMALL) {
- CopyRect(&r_label, &d->r_n_label);
- CopyRect(&r_input, &d->r_n_input);
- OffsetRect(&r_label, r_row.left, r_row.top);
- OffsetRect(&r_input, r_row.left, r_row.top);
- } else if (size == KHUI_CTRLSIZE_HALF) {
- CopyRect(&r_label, &d->r_e_label);
- CopyRect(&r_input, &d->r_e_input);
- OffsetRect(&r_label, r_row.left, r_row.top);
- OffsetRect(&r_input, r_row.left, r_row.top);
- } else if (size == KHUI_CTRLSIZE_FULL) {
- CopyRect(&r_label, &d->r_n_label);
- r_label.right = d->r_row.right;
- CopyRect(&r_input, &d->r_n_input);
- OffsetRect(&r_input, r_row.left, r_row.top);
- OffsetRect(&r_input, 0, r_input.bottom);
- r_row.bottom += r_input.bottom;
- OffsetRect(&r_label, r_row.left, r_row.top);
- } else {
- SetRectEmpty(&r_label);
- SetRectEmpty(&r_input);
-#ifdef DEBUG
- assert(FALSE);
-#endif
- return;
- }
-
- hdefer = BeginDeferWindowPos(2);
-
- if (label)
- DeferWindowPos(hdefer, label,
- ((d->hwnd_last_idspec != NULL)?
- d->hwnd_last_idspec:
- HWND_TOP),
- r_label.left, r_label.top,
- r_label.right - r_label.left,
- r_label.bottom - r_label.top,
- SWP_NOACTIVATE | SWP_NOOWNERZORDER);
-
- if (input)
- DeferWindowPos(hdefer, input,
- (label ? label : ((d->hwnd_last_idspec != NULL)?
- d->hwnd_last_idspec:
- HWND_TOP)),
- r_input.left, r_input.top,
- r_input.right - r_input.left,
- r_input.bottom - r_input.top,
- SWP_NOACTIVATE | SWP_NOOWNERZORDER);
-
- EndDeferWindowPos(hdefer);
-
- d->hwnd_last_idspec = (input ? input : label);
-
- d->r_idspec.bottom = r_row.bottom;
-
- /* we don't update the layout of the main panel yet, since these
- control additions happen before the main panel is displayed. A
- call to nc_layout_main_panel() will be made before the main
- panel is shown anyway. */
-
-}
-
-
-static LRESULT
-nc_handle_wm_destroy(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam)
-{
- khui_nc_wnd_data * d;
-
- /* remove self from dialog chain */
- khm_del_dialog(hwnd);
-
- khm_taskbar_remove_window(hwnd);
-
- d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM);
-
- d->nc->ident_cb(d->nc, WMNC_IDENT_EXIT, NULL, 0, 0, 0);
-
- if (d->hwnd_notif_label)
- DestroyWindow(d->hwnd_notif_label);
- if (d->hwnd_notif_aux)
- DestroyWindow(d->hwnd_notif_aux);
-
- if(d->dlg_bb)
- DestroyWindow(d->dlg_bb);
- if(d->dlg_main)
- DestroyWindow(d->dlg_main);
-
- d->dlg_bb = NULL;
- d->dlg_main = NULL;
-
- PFREE(d);
-
- return TRUE;
-}
-
-static LRESULT
-nc_handle_wm_command(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam)
-{
- khui_nc_wnd_data * d;
-
- d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM);
-
- switch(HIWORD(wParam)) {
- case BN_CLICKED:
- switch(LOWORD(wParam)) {
-
- case IDOK:
- d->nc->result = KHUI_NC_RESULT_PROCESS;
-
- /* fallthrough */
-
- case IDCANCEL:
- /* the default value for d->nc->result is set to
- KHUI_NC_RESULT_CANCEL */
- d->nc->response = KHUI_NC_RESPONSE_PROCESSING;
-
- nc_enable_controls(d, FALSE);
-
- nc_notify_types(d->nc,
- KHUI_WM_NC_NOTIFY,
- MAKEWPARAM(0,WMNC_DIALOG_PREPROCESS),
- (LPARAM) d->nc,
- TRUE);
-
- khui_cw_sync_prompt_values(d->nc);
-
- khm_cred_dispatch_process_message(d->nc);
-
- /* we won't know whether to abort or not until we get
- feedback from the plugins, even if the command was
- to cancel */
- {
- HWND hw;
-
- hw = GetDlgItem(d->dlg_main, IDOK);
- EnableWindow(hw, FALSE);
- hw = GetDlgItem(d->dlg_main, IDCANCEL);
- EnableWindow(hw, FALSE);
- hw = GetDlgItem(d->dlg_main, IDC_NC_ADVANCED);
- EnableWindow(hw, FALSE);
- hw = GetDlgItem(d->dlg_bb, IDOK);
- EnableWindow(hw, FALSE);
- hw = GetDlgItem(d->dlg_bb, IDCANCEL);
- EnableWindow(hw, FALSE);
- }
- return FALSE;
-
- case IDC_NC_HELP:
- khm_html_help(hwnd, NULL, HH_HELP_CONTEXT, IDH_ACTION_NEW_ID);
- return FALSE;
-
- case IDC_NC_BASIC:
- case IDC_NC_ADVANCED:
- /* the Options button in the main window was clicked. we
- respond by expanding the dialog. */
- PostMessage(hwnd, KHUI_WM_NC_NOTIFY,
- MAKEWPARAM(0, WMNC_DIALOG_EXPAND), 0);
- return FALSE;
-
- case IDC_NC_CREDTEXT: /* credtext link activated */
- {
- khui_htwnd_link * l;
- wchar_t sid[KHUI_MAXCCH_HTLINK_FIELD];
- wchar_t sparam[KHUI_MAXCCH_HTLINK_FIELD];
- wchar_t * colon;
-
- l = (khui_htwnd_link *) lParam;
-
- /* do we have a valid link? */
- if(l->id == NULL || l->id_len >= ARRAYLENGTH(sid))
- return TRUE; /* nope */
-
- StringCchCopyN(sid, ARRAYLENGTH(sid), l->id, l->id_len);
- sid[l->id_len] = L'\0'; /* just make sure */
-
- if(l->param != NULL &&
- l->param_len < ARRAYLENGTH(sparam) &&
- l->param_len > 0) {
-
- StringCchCopyN(sparam, ARRAYLENGTH(sparam),
- l->param, l->param_len);
- sparam[l->param_len] = L'\0';
-
- } else {
- sparam[0] = L'\0';
- }
-
- /* If the ID is of the form '<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);
-}
+/* + * 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); +} diff --git a/src/windows/identity/ui/newcredwnd.h b/src/windows/identity/ui/newcredwnd.h index 939cf0141f..22819a6939 100644 --- a/src/windows/identity/ui/newcredwnd.h +++ b/src/windows/identity/ui/newcredwnd.h @@ -1,189 +1,189 @@ -/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#ifndef __KHIMAIRA_NEWCREDWND_H
-#define __KHIMAIRA_NEWCREDWND_H
-
-#include<khuidefs.h>
-
-#define KHUI_NEWCREDWND_CLASS L"KhmNewCredWnd"
-
-typedef enum tag_nc_notification_types {
- NC_NOTIFY_NONE = 0, /* no notification */
- NC_NOTIFY_MARQUEE, /* marquee type notification */
- NC_NOTIFY_PROGRESS, /* progress notification */
- NC_NOTIFY_MESSAGE, /* a message */
-} nc_notification_type;
-
-typedef struct khui_nc_wnd_data_t {
- khui_new_creds * nc;
-
- /* The tab control */
-
- HWND tab_wnd; /* tab control */
- int current_panel; /* ordinal of the current panel being
- displayed. */
-
- /* The main panel */
- HWND dlg_main; /* main dialog */
- RECT r_main; /* the extent of the main panel that
- we have used so far. The rect
- includes the size of the area used
- by the identity selector controls,
- the custom controls added by
- credentials providers and the
- buttons that may be required when
- in the mini mode. */
- RECT r_required; /* required size of the main window */
-
- /* The button bar */
-
- HWND dlg_bb; /* button bar */
-
- /* Sizing the new credentials window */
-
- BOOL animation_enabled; /* Flag indicating whether animation
- is enabled for the dialg. If this
- flag is off, we don't animate size
- changes even if the configuration
- says so. */
- BOOL size_changing; /* flag indicating that the size of
- the main window is being
- adjusted. */
- RECT sz_ch_source; /* Source size, from which we are
- going towards target size in
- sz_ch_max steps. The RECT is self
- relative (i.e. left=0 and top=0)*/
- RECT sz_ch_target; /* If we are doing an incremental size
- change, this holds the target size
- that we were going for. Note that
- the target size might change while
- we are adjusting the size. So this
- helps keep track of whether we need
- to start the size change again. The
- RECT is self relative (i.e. left=0
- and top=0). */
- int sz_ch_increment; /* Current step of the incremental
- size change operation. */
- int sz_ch_max; /* Max number of steps in the size
- change operation. */
- int sz_ch_timeout; /* Milliseconds between each increment */
-
- /* Custom controls and identity specifiers */
-
- HWND hwnd_banner; /* static control for banner */
- HWND hwnd_name; /* static control for name */
-
- HWND hwnd_last_idspec; /* last identity specifier control */
-
- /* Notification windows */
-
- nc_notification_type notif_type; /* Type of notification */
- HWND hwnd_notif_label; /* Label for notifications */
- HWND hwnd_notif_aux; /* Other control for notifications */
-
- /* Areas of the main panel */
-
- RECT r_idspec; /* Area used by identity specifiers
- (relative to client) */
- RECT r_custprompt; /* Area used by custom controls (relative
- to client) */
- RECT r_notif; /* Area used for notifications. */
-
- /* Metrics for custom prompts and identity specifiers */
-
- RECT r_row; /* Metrics for a control row (left=0,
- top=0, right=width, bottom=height) */
- RECT r_area; /* Area available for controls (relative
- to client) */
- RECT r_n_label; /* coords of the static control (relative
- to row) */
- RECT r_n_input; /* coords of the edit control (relative to
- row) */
- RECT r_e_label; /* coords of the extended edit control
- (relative to row) */
- RECT r_e_input; /* coords of the extended edit control
- (relative to row) */
- RECT r_credtext; /* Area for credtext window (relative to
- row) */
-} khui_nc_wnd_data;
-
-void khm_register_newcredwnd_class(void);
-void khm_unregister_newcredwnd_class(void);
-HWND khm_create_newcredwnd(HWND parent, khui_new_creds * c);
-void khm_prep_newcredwnd(HWND hwnd);
-void khm_show_newcredwnd(HWND hwnd);
-
-/* Width of the button bar in dialog units */
-#define NCDLG_BBAR_WIDTH 66
-/* Height of the button bar in dialog units */
-#define NCDLG_BBAR_HEIGHT 190
-
-/* Control identifier for the tab control in the new credentials
- dialog. We declare this here since we will be creating the control
- manually. */
-#define IDC_NC_TABS 8001
-
-/* This is the first control ID that is created in the custom tabstrip
- control buttons. Subsequent buttons get consecutive IDs starting
- from this one. */
-#define NC_TS_CTRL_ID_MIN 8002
-
-/* Maximum number of controls */
-#define NC_TS_MAX_CTRLS 8
-
-/* Maximum control ID */
-#define NC_TS_CTRL_ID_MAX (NC_TS_CTRL_ID_MIN + NC_TS_MAX_CTRLS - 1)
-
-#define NC_BN_SET_DEF_ID 8012
-
-/* the first control ID that may be used by an identity provider */
-#define NC_IS_CTRL_ID_MIN 8016
-
-/* the maximum number of controls that may be created by an identity
- provider*/
-#define NC_IS_CTRL_MAX_CTRLS 8
-
-/* the maximum control ID that may be used by an identity provider */
-#define NC_IS_CTRL_ID_MAX (NC_IS_CTRL_ID_MIN + NC_IS_MAX_CTRLS - 1)
-
-#define NC_WINDOW_EX_STYLES (WS_EX_DLGMODALFRAME | WS_EX_CONTEXTHELP)
-#define NC_WINDOW_STYLES (WS_DLGFRAME | WS_POPUPWINDOW | WS_CLIPCHILDREN)
-
-#define NC_SZ_STEPS_MIN 3
-#define NC_SZ_STEPS_DEF 10
-#define NC_SZ_STEPS_MAX 100
-
-#define NC_SZ_TIMEOUT_MIN 5
-#define NC_SZ_TIMEOUT_DEF 10
-#define NC_SZ_TIMEOUT_MAX 500
-
-#define NC_TIMER_SIZER 1001
-#define NC_TIMER_ENABLEANIMATE 1002
-
-#define ENABLEANIMATE_TIMEOUT 400
-
-#endif
+/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __KHIMAIRA_NEWCREDWND_H +#define __KHIMAIRA_NEWCREDWND_H + +#include<khuidefs.h> + +#define KHUI_NEWCREDWND_CLASS L"KhmNewCredWnd" + +typedef enum tag_nc_notification_types { + NC_NOTIFY_NONE = 0, /* no notification */ + NC_NOTIFY_MARQUEE, /* marquee type notification */ + NC_NOTIFY_PROGRESS, /* progress notification */ + NC_NOTIFY_MESSAGE, /* a message */ +} nc_notification_type; + +typedef struct khui_nc_wnd_data_t { + khui_new_creds * nc; + + /* The tab control */ + + HWND tab_wnd; /* tab control */ + int current_panel; /* ordinal of the current panel being + displayed. */ + + /* The main panel */ + HWND dlg_main; /* main dialog */ + RECT r_main; /* the extent of the main panel that + we have used so far. The rect + includes the size of the area used + by the identity selector controls, + the custom controls added by + credentials providers and the + buttons that may be required when + in the mini mode. */ + RECT r_required; /* required size of the main window */ + + /* The button bar */ + + HWND dlg_bb; /* button bar */ + + /* Sizing the new credentials window */ + + BOOL animation_enabled; /* Flag indicating whether animation + is enabled for the dialg. If this + flag is off, we don't animate size + changes even if the configuration + says so. */ + BOOL size_changing; /* flag indicating that the size of + the main window is being + adjusted. */ + RECT sz_ch_source; /* Source size, from which we are + going towards target size in + sz_ch_max steps. The RECT is self + relative (i.e. left=0 and top=0)*/ + RECT sz_ch_target; /* If we are doing an incremental size + change, this holds the target size + that we were going for. Note that + the target size might change while + we are adjusting the size. So this + helps keep track of whether we need + to start the size change again. The + RECT is self relative (i.e. left=0 + and top=0). */ + int sz_ch_increment; /* Current step of the incremental + size change operation. */ + int sz_ch_max; /* Max number of steps in the size + change operation. */ + int sz_ch_timeout; /* Milliseconds between each increment */ + + /* Custom controls and identity specifiers */ + + HWND hwnd_banner; /* static control for banner */ + HWND hwnd_name; /* static control for name */ + + HWND hwnd_last_idspec; /* last identity specifier control */ + + /* Notification windows */ + + nc_notification_type notif_type; /* Type of notification */ + HWND hwnd_notif_label; /* Label for notifications */ + HWND hwnd_notif_aux; /* Other control for notifications */ + + /* Areas of the main panel */ + + RECT r_idspec; /* Area used by identity specifiers + (relative to client) */ + RECT r_custprompt; /* Area used by custom controls (relative + to client) */ + RECT r_notif; /* Area used for notifications. */ + + /* Metrics for custom prompts and identity specifiers */ + + RECT r_row; /* Metrics for a control row (left=0, + top=0, right=width, bottom=height) */ + RECT r_area; /* Area available for controls (relative + to client) */ + RECT r_n_label; /* coords of the static control (relative + to row) */ + RECT r_n_input; /* coords of the edit control (relative to + row) */ + RECT r_e_label; /* coords of the extended edit control + (relative to row) */ + RECT r_e_input; /* coords of the extended edit control + (relative to row) */ + RECT r_credtext; /* Area for credtext window (relative to + row) */ +} khui_nc_wnd_data; + +void khm_register_newcredwnd_class(void); +void khm_unregister_newcredwnd_class(void); +HWND khm_create_newcredwnd(HWND parent, khui_new_creds * c); +void khm_prep_newcredwnd(HWND hwnd); +void khm_show_newcredwnd(HWND hwnd); + +/* Width of the button bar in dialog units */ +#define NCDLG_BBAR_WIDTH 66 +/* Height of the button bar in dialog units */ +#define NCDLG_BBAR_HEIGHT 190 + +/* Control identifier for the tab control in the new credentials + dialog. We declare this here since we will be creating the control + manually. */ +#define IDC_NC_TABS 8001 + +/* This is the first control ID that is created in the custom tabstrip + control buttons. Subsequent buttons get consecutive IDs starting + from this one. */ +#define NC_TS_CTRL_ID_MIN 8002 + +/* Maximum number of controls */ +#define NC_TS_MAX_CTRLS 8 + +/* Maximum control ID */ +#define NC_TS_CTRL_ID_MAX (NC_TS_CTRL_ID_MIN + NC_TS_MAX_CTRLS - 1) + +#define NC_BN_SET_DEF_ID 8012 + +/* the first control ID that may be used by an identity provider */ +#define NC_IS_CTRL_ID_MIN 8016 + +/* the maximum number of controls that may be created by an identity + provider*/ +#define NC_IS_CTRL_MAX_CTRLS 8 + +/* the maximum control ID that may be used by an identity provider */ +#define NC_IS_CTRL_ID_MAX (NC_IS_CTRL_ID_MIN + NC_IS_MAX_CTRLS - 1) + +#define NC_WINDOW_EX_STYLES (WS_EX_DLGMODALFRAME | WS_EX_CONTEXTHELP | WS_EX_APPWINDOW) +#define NC_WINDOW_STYLES (WS_DLGFRAME | WS_POPUPWINDOW | WS_CLIPCHILDREN) + +#define NC_SZ_STEPS_MIN 3 +#define NC_SZ_STEPS_DEF 10 +#define NC_SZ_STEPS_MAX 100 + +#define NC_SZ_TIMEOUT_MIN 5 +#define NC_SZ_TIMEOUT_DEF 10 +#define NC_SZ_TIMEOUT_MAX 500 + +#define NC_TIMER_SIZER 1001 +#define NC_TIMER_ENABLEANIMATE 1002 + +#define ENABLEANIMATE_TIMEOUT 400 + +#endif |