void khm_cred_destroy_identity(khm_handle identity) { khui_action_context * pctx; wchar_t idname[KCDB_IDENT_MAXCCH_NAME]; khm_size cb; if (identity == NULL) return; pctx = PMALLOC(sizeof(*pctx)); #ifdef DEBUG assert(pctx); #endif khui_context_create(pctx, KHUI_SCOPE_IDENT, identity, KCDB_CREDTYPE_INVALID, NULL); cb = sizeof(idname); kcdb_identity_get_name(identity, idname, &cb); _begin_task(KHERR_CF_TRANSITIVE); _report_sr1(KHERR_NONE, IDS_CTX_DESTROY_ID, _dupstr(idname)); _describe(); kmq_post_message(KMSG_CRED, KMSG_CRED_DESTROY_CREDS, 0, (void *) pctx); _end_task(); }
void khm_cred_renew_cred(khm_handle cred) { khui_new_creds * c; khui_cw_create_cred_blob(&c); c->subtype = KMSG_CRED_RENEW_CREDS; c->result = KHUI_NC_RESULT_PROCESS; khui_context_create(&c->ctx, KHUI_SCOPE_CRED, NULL, KCDB_CREDTYPE_INVALID, cred); _begin_task(KHERR_CF_TRANSITIVE); _report_sr0(KHERR_NONE, IDS_CTX_RENEW_CREDS); _describe(); /* if we are calling this while processing startup actions, we need to keep track of how many we have issued. */ if (khm_startup.processing) { InterlockedIncrement(&khm_startup.pending_renewals); } kmq_post_message(KMSG_CRED, KMSG_CRED_RENEW_CREDS, 0, (void *) c); _end_task(); }
/*! \internal \brief Uninitialize a plugin In addition to terminating the thread, and removing p from the linked list and hashtable, it also frees up p. \note Should only be called from the context of the registrar thread. */ void kmmint_exit_plugin(kmm_plugin_i * p) { int np; khm_boolean release_plugin = TRUE; if(p->state == KMM_PLUGIN_STATE_RUNNING || p->state == KMM_PLUGIN_STATE_INIT) { kmq_post_thread_quit_message(p->tid_thread, 0, NULL); /* when we post the quit message to the plugin thread, the plugin broker terminates the plugin and posts a EXIT_PLUGIN message, which calls this function again. We just exit here because the EXIT_PLUGIN message will end up calling us again momentarily */ return; } if(p->ht_thread) { /* wait for the thread to terminate */ WaitForSingleObject(p->ht_thread, INFINITE); p->ht_thread = NULL; } EnterCriticalSection(&cs_kmm); /* undo reference count done in kmmint_init_plugin() */ if(p->flags & KMM_PLUGIN_FLAG_IN_MODCOUNT) { np = --(p->module->plugin_count); p->flags &= ~KMM_PLUGIN_FLAG_IN_MODCOUNT; } else { /* the plugin was not included in the module's plugin_count. We can't base a decision to unload the module based on this plugin exiting. */ np = TRUE; } /* The plugin is in an error state. We need to keep the plugin record intact so that the failure information is kept around. Also, we shouldn't release the plugin if it appears that kmmint_init_plugin() was never called for it. */ if (p->state < KMM_PLUGIN_STATE_HOLD) { release_plugin = FALSE; } LeaveCriticalSection(&cs_kmm); if(!np) { /* if this is the last plugin to exit, then notify the registrar that the module should be removed as well */ kmm_hold_module(kmm_handle_from_module(p->module)); kmq_post_message(KMSG_KMM, KMSG_KMM_I_REG, KMM_REG_EXIT_MODULE, (void *) p->module); } /* release the hold obtained in kmmint_init_plugin() */ if (release_plugin) kmm_release_plugin(kmm_handle_from_plugin(p)); }
void khm_cred_import(void) { _begin_task(KHERR_CF_TRANSITIVE); _report_sr0(KHERR_NONE, IDS_CTX_IMPORT); _describe(); kmq_post_message(KMSG_CRED, KMSG_CRED_IMPORT, 0, 0); _end_task(); }
KHMEXP khm_int32 KHMAPI khui_alert_queue(khui_alert * alert) { assert(alert->magic == KHUI_ALERT_MAGIC); khui_alert_hold(alert); kmq_post_message(KMSG_ALERT, KMSG_ALERT_QUEUE, 0, (void *) alert); return KHM_ERROR_SUCCESS; }
void khm_cred_destroy_creds(khm_boolean sync, khm_boolean quiet) { khui_action_context * pctx; pctx = PMALLOC(sizeof(*pctx)); #ifdef DEBUG assert(pctx); #endif khui_context_get(pctx); if(pctx->scope == KHUI_SCOPE_NONE && !quiet) { /* this really shouldn't be necessary once we start enabling and disbling actions based on context */ wchar_t title[256]; wchar_t message[256]; LoadString(khm_hInstance, IDS_ALERT_NOSEL_TITLE, title, ARRAYLENGTH(title)); LoadString(khm_hInstance, IDS_ALERT_NOSEL, message, ARRAYLENGTH(message)); khui_alert_show_simple(title, message, KHERR_WARNING); khui_context_release(pctx); PFREE(pctx); return; } _begin_task(KHERR_CF_TRANSITIVE); _report_sr0(KHERR_NONE, IDS_CTX_DESTROY_CREDS); _describe(); if (sync) kmq_send_message(KMSG_CRED, KMSG_CRED_DESTROY_CREDS, 0, (void *) pctx); else kmq_post_message(KMSG_CRED, KMSG_CRED_DESTROY_CREDS, 0, (void *) pctx); _end_task(); }
KHMEXP khm_int32 KHMAPI khui_alert_show(khui_alert * alert) { assert(alert->magic == KHUI_ALERT_MAGIC); khui_alert_hold(alert); /* the alert will be released when the message is processed */ kmq_post_message(KMSG_ALERT, KMSG_ALERT_SHOW, 0, (void *) alert); return KHM_ERROR_SUCCESS; }
void kmmint_check_completion(void) { if (pending_modules == 0 && pending_plugins == 0 && InterlockedIncrement(&startup_signal) == 1) { load_done = TRUE; /* TODO: check for orphaned plugins */ kmq_post_message(KMSG_KMM, KMSG_KMM_I_DONE, 0, 0); } }
KHMEXP khm_int32 KHMAPI kmm_unload_module(kmm_module module) { if(!kmm_is_module(module)) return KHM_ERROR_INVALID_PARAM; kmm_hold_module(module); kmq_post_message(KMSG_KMM, KMSG_KMM_I_REG, KMM_REG_EXIT_MODULE, (void *) kmm_module_from_handle(module)); return KHM_ERROR_SUCCESS; }
DWORD WINAPI addr_change_thread(LPVOID dummy) { HANDLE h_waits[2]; HANDLE h_notify; OVERLAPPED overlap; DWORD ret; PDESCTHREAD(L"Address change waiter", L"App"); ZeroMemory(&overlap, sizeof(overlap)); h_notify = NULL; overlap.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); do { ret = NotifyAddrChange(&h_notify, &overlap); if (ret != ERROR_IO_PENDING) { goto _end_thread; /* some error */ } h_waits[0] = overlap.hEvent; h_waits[1] = evt_terminate; ret = WaitForMultipleObjects(2, h_waits, FALSE, INFINITE); if ( ret == WAIT_OBJECT_0 ) { Sleep(3000); /* wait for things to settle down */ kmq_post_message(KMSG_CRED, KMSG_CRED_ADDR_CHANGE, 0, 0); } else { goto _end_thread; } } while(TRUE); _end_thread: ExitThread(0); return 0; /* unreachable */ }
LRESULT khm_statusbar_notify(LPNMHDR nmhdr) { LPNMMOUSE pnmm; switch(nmhdr->code) { case NM_CLICK: case NM_DBLCLK: pnmm = (LPNMMOUSE) nmhdr; if (pnmm->dwItemSpec >= (DWORD) khm_n_statusbar_parts) return TRUE; if (khm_statusbar_parts[pnmm->dwItemSpec].id == KHUI_SBPART_NOTICE) { /* means, show next notification */ kmq_post_message(KMSG_ALERT, KMSG_ALERT_SHOW_QUEUED, 0, 0); } return TRUE; } return FALSE; }
void khm_create_statusbar(HWND parent) { HWND hwsb; hwsb = CreateWindowEx( 0, STATUSCLASSNAME, NULL, SBARS_SIZEGRIP | WS_CHILD | WS_VISIBLE, 0,0,0,0, parent, NULL, khm_hInstance, NULL); if(!hwsb) return; khm_hwnd_statusbar = hwsb; khui_statusbar_set_parts(parent); kmq_post_message(KMSG_ALERT, KMSG_ALERT_CHECK_QUEUE, 0, 0); }
void khm_cred_change_password(wchar_t * title) { khui_new_creds * nc; LPNETID_DLGINFO pdlginfo; khm_size cb; if (!khm_cred_begin_dialog()) return; khui_cw_create_cred_blob(&nc); nc->subtype = KMSG_CRED_PASSWORD; dialog_nc = nc; khui_context_get(&nc->ctx); kcdb_identpro_get_ui_cb((void *) &nc->ident_cb); assert(nc->ident_cb); if (title) { if (SUCCEEDED(StringCbLength(title, KHUI_MAXCB_TITLE, &cb))) { cb += sizeof(wchar_t); nc->window_title = PMALLOC(cb); #ifdef DEBUG assert(nc->window_title); #endif StringCbCopy(nc->window_title, cb, title); } } else if (nc->ctx.cb_vparam == sizeof(NETID_DLGINFO) && (pdlginfo = nc->ctx.vparam) && pdlginfo->size == NETID_DLGINFO_V1_SZ && pdlginfo->in.title[0] && SUCCEEDED(StringCchLength(pdlginfo->in.title, NETID_TITLE_SZ, &cb))) { cb = (cb + 1) * sizeof(wchar_t); nc->window_title = PMALLOC(cb); #ifdef DEBUG assert(nc->window_title); #endif StringCbCopy(nc->window_title, cb, pdlginfo->in.title); } khm_create_newcredwnd(khm_hwnd_main, nc); if (nc->hwnd != NULL) { _begin_task(KHERR_CF_TRANSITIVE); _report_sr0(KHERR_NONE, IDS_CTX_PASSWORD); _describe(); kmq_post_message(KMSG_CRED, KMSG_CRED_PASSWORD, 0, (void *) nc); _end_task(); } else { khui_cw_destroy_cred_blob(nc); } }
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_VIEW_ALL_IDS: return SendMessage(khm_hwnd_main_cred, uMsg, wParam, lParam); 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) { main_wnd_save_sizepos(); 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); } case WM_KHUI_ASSIGN_COMMANDLINE_V1: { HANDLE hmap; void * xfer; wchar_t mapname[256]; 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 = (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; khm_startup.display = 0; 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]; khm_startup_options_v2 *pv2opt = NULL; khm_startup_options_v3 *pv3opt = NULL; 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 = (khm_startup_options_v2 *) xfer; if (pv2opt->magic != STARTUP_OPTIONS_MAGIC || (pv2opt->cb_size != sizeof(*pv2opt) && pv2opt->cb_size != sizeof(*pv3opt))) { 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; if (pv2opt->cb_size == sizeof(*pv3opt)) { pv3opt = (khm_startup_options_v3 *) xfer; khm_startup.display = pv3opt->remote_display; } else { khm_startup.display = 0; } 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); }
void khm_cred_dispatch_process_message(khui_new_creds *nc) { khm_size i; BOOL pending; wchar_t wsinsert[512]; khm_size cbsize; /* see if there's anything to do. We can check this without obtaining a lock */ if(nc->n_types == 0 || (nc->subtype == KMSG_CRED_NEW_CREDS && nc->n_identities == 0) || (nc->subtype == KMSG_CRED_PASSWORD && nc->n_identities == 0)) goto _terminate_job; /* check dependencies and stuff first */ EnterCriticalSection(&nc->cs); for(i=0; i<nc->n_types; i++) { nc->types[i]->flags &= ~ KHUI_NCT_FLAG_PROCESSED; } LeaveCriticalSection(&nc->cs); /* Consindering all that can go wrong here and the desire to handle errors here separately from others, we create a new task for the purpose of tracking the credentials acquisition process. */ _begin_task(KHERR_CF_TRANSITIVE); /* Describe the context */ if(nc->subtype == KMSG_CRED_NEW_CREDS) { cbsize = sizeof(wsinsert); kcdb_identity_get_name(nc->identities[0], wsinsert, &cbsize); _report_sr1(KHERR_NONE, IDS_CTX_PROC_NEW_CREDS, _cstr(wsinsert)); _resolve(); } else if (nc->subtype == KMSG_CRED_RENEW_CREDS) { cbsize = sizeof(wsinsert); if (nc->ctx.scope == KHUI_SCOPE_IDENT) kcdb_identity_get_name(nc->ctx.identity, wsinsert, &cbsize); else if (nc->ctx.scope == KHUI_SCOPE_CREDTYPE) { if (nc->ctx.identity != NULL) kcdb_identity_get_name(nc->ctx.identity, wsinsert, &cbsize); else kcdb_credtype_get_name(nc->ctx.cred_type, wsinsert, &cbsize); } else if (nc->ctx.scope == KHUI_SCOPE_CRED) { kcdb_cred_get_name(nc->ctx.cred, wsinsert, &cbsize); } else { StringCbCopy(wsinsert, sizeof(wsinsert), L"(?)"); } _report_sr1(KHERR_NONE, IDS_CTX_PROC_RENEW_CREDS, _cstr(wsinsert)); _resolve(); } else if (nc->subtype == KMSG_CRED_PASSWORD) { cbsize = sizeof(wsinsert); kcdb_identity_get_name(nc->identities[0], wsinsert, &cbsize); _report_sr1(KHERR_NONE, IDS_CTX_PROC_PASSWORD, _cstr(wsinsert)); _resolve(); } else { assert(FALSE); } _describe(); pending = khm_cred_dispatch_process_level(nc); _end_task(); if(!pending) goto _terminate_job; return; _terminate_job: if (nc->subtype == KMSG_CRED_RENEW_CREDS) kmq_post_message(KMSG_CRED, KMSG_CRED_END, 0, (void *) nc); else PostMessage(nc->hwnd, KHUI_WM_NC_NOTIFY, MAKEWPARAM(0, WMNC_DIALOG_PROCESS_COMPLETE), 0); }
void khm_cred_process_startup_actions(void) { khm_handle defident = NULL; if (!khm_startup.processing) return; if (khm_startup.init || khm_startup.renew || khm_startup.destroy || khm_startup.autoinit) { kcdb_identity_get_default(&defident); } /* For asynchronous actions, we trigger the action and then exit the loop. Once the action completes, the completion handler will trigger a continuation message which will result in this function getting called again. Then we can proceed with the rest of the startup actions. */ do { if (khm_startup.init) { khm_cred_obtain_new_creds_for_ident(defident, NULL); khm_startup.init = FALSE; break; } if (khm_startup.import) { khm_cred_import(); khm_startup.import = FALSE; /* we also set the renew command to false here because we trigger a renewal for all the identities at the end of the import operation anyway. */ khm_startup.renew = FALSE; break; } if (khm_startup.renew) { LONG pending_renewals; /* if there are no credentials, we just skip over the renew action. */ khm_startup.renew = FALSE; InterlockedIncrement(&khm_startup.pending_renewals); khm_cred_renew_all_identities(); pending_renewals = InterlockedDecrement(&khm_startup.pending_renewals); if (pending_renewals != 0) break; /* if there were no pending renewals, then we just fall through. This means that either there were no identities to renew, or all the renewals completed. If all the renewals completed, then the commandline contiuation message wasn't triggered. Either way, we must fall through if the count is zero. */ } if (khm_startup.destroy) { khm_startup.destroy = FALSE; if (defident) { khm_cred_destroy_identity(defident); break; } } if (khm_startup.autoinit) { khm_size count = 0; khm_handle credset = NULL; khm_int32 ctype_ident = KCDB_CREDTYPE_INVALID; khm_int32 delta = 0; khm_startup.autoinit = FALSE; kcdb_credset_create(&credset); kcdb_identity_get_type(&ctype_ident); kcdb_credset_collect(credset, NULL, defident, ctype_ident, &delta); kcdb_credset_get_size(credset, &count); kcdb_credset_delete(credset); if (count == 0) { if (defident) khui_context_set(KHUI_SCOPE_IDENT, defident, KCDB_CREDTYPE_INVALID, NULL, NULL, 0, NULL); else khui_context_reset(); khm_cred_obtain_new_creds(NULL); break; } } if (khm_startup.exit) { PostMessage(khm_hwnd_main, WM_COMMAND, MAKEWPARAM(KHUI_ACTION_EXIT, 0), 0); khm_startup.exit = FALSE; break; } if (khm_startup.display & SOPTS_DISPLAY_HIDE) { khm_hide_main_window(); } else if (khm_startup.display & SOPTS_DISPLAY_SHOW) { khm_show_main_window(); } khm_startup.display = 0; /* when we get here, then we are all done with the command line stuff */ khm_startup.processing = FALSE; khm_startup.remote = FALSE; kmq_post_message(KMSG_ACT, KMSG_ACT_END_CMDLINE, 0, 0); } while(FALSE); if (defident) kcdb_identity_release(defident); }
KHMEXP khm_int32 KHMAPI kmm_load_module(wchar_t * modname, khm_int32 flags, kmm_module * result) { kmm_module_i * m = NULL; kmm_module_i * mi; size_t cbsize; khm_int32 rv = KHM_ERROR_SUCCESS; if(FAILED(StringCbLength(modname, KMM_MAXCB_NAME, &cbsize))) return KHM_ERROR_INVALID_PARAM; cbsize += sizeof(wchar_t); EnterCriticalSection(&cs_kmm); mi = kmmint_find_module_i(modname); if(mi != NULL) { kmm_hold_module(kmm_handle_from_module(mi)); /* check if the module has either failed to load either or if it has been terminated. If so, we try once again to load the module. */ if(!(flags & KMM_LM_FLAG_NOLOAD) && (mi->state < 0 || mi->state == KMM_MODULE_STATE_EXITED)) { mi->state = KMM_MODULE_STATE_PREINIT; } } LeaveCriticalSection(&cs_kmm); if(flags & KMM_LM_FLAG_NOLOAD) { if(result) *result = mi; else if(mi) kmm_release_module(kmm_handle_from_module(mi)); return (mi)? KHM_ERROR_SUCCESS: KHM_ERROR_NOT_FOUND; } if(mi) { m = mi; } else { m = kmmint_get_module_i(modname); m->state = KMM_MODULE_STATE_PREINIT; kmm_hold_module(kmm_handle_from_module(m)); } /* the module is already running or is already being worked on by the registrar */ if(m->state != KMM_MODULE_STATE_PREINIT) { if(result) *result = kmm_handle_from_module(m); else kmm_release_module(kmm_handle_from_module(m)); return KHM_ERROR_EXISTS; } kmmint_add_to_module_queue(); if(flags & KMM_LM_FLAG_SYNC) { kmm_hold_module(kmm_handle_from_module(m)); kmq_send_message(KMSG_KMM, KMSG_KMM_I_REG, KMM_REG_INIT_MODULE, (void*) m); if(m->state <= 0) { /* failed to load ? */ if(m->state == KMM_MODULE_STATE_FAIL_NOT_FOUND) rv = KHM_ERROR_NOT_FOUND; else if(m->state == KMM_MODULE_STATE_FAIL_SIGNATURE) rv = KHM_ERROR_INVALID_SIGNATURE; else rv = KHM_ERROR_UNKNOWN; kmm_release_module(kmm_handle_from_module(m)); if(result) *result = NULL; } else { if(result) *result = kmm_handle_from_module(m); else kmm_release_module(kmm_handle_from_module(m)); } } else { kmm_hold_module(kmm_handle_from_module(m)); kmq_post_message(KMSG_KMM, KMSG_KMM_I_REG, KMM_REG_INIT_MODULE, (void*) m); if(result) *result = kmm_handle_from_module(m); else kmm_release_module(kmm_handle_from_module(m)); } return rv; }
/*! \internal Collect credentials from cs_src to cs_dest which have already been selected into cl_dest and cl_src. - Credentials in cl_src that are not in cl_dest will get added to cs_dest - Credentials in cl_dest that are not in cl_src will get removed from cs_dest - Credentials in cl_dest and cl_src will be updated in cs_dest cl_dest and cl_src will be modified. */ khm_int32 kcdb_credset_collect_core(kcdb_credset * cs_dest, kcdb_cred ** cl_dest, khm_int32 ncl_dest, kcdb_credset * cs_src, kcdb_cred ** cl_src, khm_int32 ncl_src, khm_int32 * delta) { int i, j; int ldelta = 0; khm_int32 rv; khm_boolean dest_is_root; khm_handle last_identity = NULL; dest_is_root = (cs_dest == kcdb_root_credset); /* find matching credentials and update them */ for (i=0; i < ncl_dest; i++) { if (cl_dest[i]) { for (j=0; j < ncl_src; j++) { if (cl_src[j] && kcdb_creds_is_equal((khm_handle) cl_dest[i], (khm_handle) cl_src[j])) { /* depending on whether any changes were made, update ldelta with the proper bit flag */ rv = kcdb_cred_update(cl_dest[i], cl_src[j]); if (rv == KHM_ERROR_SUCCESS) { kcdb_credset_update_cred_ref((khm_handle) cs_dest, (khm_handle) cl_dest[i]); ldelta |= KCDB_DELTA_MODIFY; if (dest_is_root) check_and_set_refresh_bit_for_identity(cl_dest[i], &last_identity); } cl_src[j] = NULL; cl_dest[i] = NULL; break; } } } } /* all the creds that are left in cl_dest need to be removed */ for (i=0; i < ncl_dest; i++) { if (cl_dest[i]) { if (dest_is_root) check_and_set_refresh_bit_for_identity(cl_dest[i], &last_identity); kcdb_credset_del_cred_ref((khm_handle) cs_dest, (khm_handle) cl_dest[i]); ldelta |= KCDB_DELTA_DEL; cl_dest[i] = NULL; } } /* all the creds in cl_src need to be added to cs_dest */ for (j=0; j < ncl_src; j++) { if (cl_src[j]) { /* duplicate the credential and add it if we are adding it to or from the root credential store. */ if (cs_dest == kcdb_root_credset || cs_src == kcdb_root_credset) { khm_handle h; if (KHM_SUCCEEDED(kcdb_cred_dup((khm_handle) cl_src[j], &h))) { kcdb_credset_add_cred((khm_handle) cs_dest, h, -1); kcdb_cred_release(h); } } else { kcdb_credset_add_cred((khm_handle) cs_dest, cl_src[j], -1); } if (dest_is_root) check_and_set_refresh_bit_for_identity(cl_src[j], &last_identity); cl_src[j] = NULL; ldelta |= KCDB_DELTA_ADD; } } if (last_identity) { kcdb_identity_release(last_identity); last_identity = NULL; } if (delta) *delta = ldelta; if (dest_is_root && ldelta) { /* something changed in the root credential set */ kmq_post_message(KMSG_CRED,KMSG_CRED_ROOTDELTA,ldelta,NULL); } return KHM_ERROR_SUCCESS; }
/*! \internal \brief Uninitializes a module \note Should only be called from the context of the registrar thread */ void kmmint_exit_module(kmm_module_i * m) { kmm_plugin_i * p; /* Exiting a module happens in two stages. If the module state is running (there are active plugins) then those plugins must be exited. This has to be done from the plugin threads. The signal for the plugins to exit must be issued from the registrar. Therefore, we post messages to the registrar for each plugin we want to remove and exit kmmint_exit_module(). When the last plugin is exited, the plugin management code automatically signalls the registrar to remove the module. kmmint_exit_module() gets called again. This is the second stage, where we call exit_module() for the module and start unloading everything. */ EnterCriticalSection(&cs_kmm); /* get rid of any dangling uninitialized plugins */ LPOP(&(m->plugins), &p); while(p) { p->flags &= ~KMM_PLUGIN_FLAG_IN_MODLIST; kmmint_exit_plugin(p); /* release hold from kmm_provide_plugin() */ kmm_release_plugin(kmm_handle_from_plugin(p)); LPOP(&(m->plugins), &p); } if(m->state == KMM_MODULE_STATE_RUNNING) { int np = 0; m->state = KMM_MODULE_STATE_EXITPLUG; p = kmm_listed_plugins; while(p) { if(p->module == m && (p->flags & KMM_PLUGIN_FLAG_IN_MODCOUNT)) { kmm_hold_plugin(kmm_handle_from_plugin(p)); kmq_post_message(KMSG_KMM, KMSG_KMM_I_REG, KMM_REG_EXIT_PLUGIN, (void *) p); np++; } p = LNEXT(p); } #ifdef DEBUG assert(np == m->plugin_count); #endif if(np > 0) { /* we have to go back and wait for the plugins to exit. when the last plugin exits, it automatically posts EXIT_MODULE. We can pick up from there when this happens. */ LeaveCriticalSection(&cs_kmm); return; } } else { #ifdef DEBUG assert(m->plugin_count == 0 || m->state == KMM_MODULE_STATE_EXITPLUG); #endif /* if there are still plug-ins waiting to be unloaded, then we have to go back and wait for them to finish. Once they are done, kmmint_exit_module() will get called again. */ if (m->plugin_count > 0) { LeaveCriticalSection(&cs_kmm); return; } } if(m->flags & KMM_MODULE_FLAG_INITP) { exit_module_t p_exit_module; if(m->state > 0) m->state = KMM_MODULE_STATE_EXIT; p_exit_module = (exit_module_t) GetProcAddress(m->h_module, EXP_EXIT_MODULE); if(p_exit_module) { LeaveCriticalSection(&cs_kmm); (*p_exit_module)(kmm_handle_from_module(m)); EnterCriticalSection(&cs_kmm); } } if(m->state > 0) m->state = KMM_MODULE_STATE_EXITED; LeaveCriticalSection(&cs_kmm); if(!(m->flags & KMM_MODULE_FLAG_NOUNLOAD) && m->h_module) { FreeLibrary(m->h_module); } if(!(m->flags & KMM_MODULE_FLAG_NOUNLOAD) && m->h_resource && (m->h_resource != m->h_module)) { FreeLibrary(m->h_resource); } m->h_module = NULL; m->h_resource = NULL; if (m->flags & KMM_MODULE_FLAG_LOADED) { #ifdef DEBUG assert(kmm_active_modules > 0); #endif kmm_active_modules--; } m->flags = 0; /* release the hold obtained in kmmint_init_module() */ kmm_release_module(kmm_handle_from_module(m)); /* Last but not least, now see if there are any modules left that are running. If not, we can safely signal an exit. */ if (kmm_active_modules == 0) { SetEvent(evt_exit); } }
void khm_cred_refresh(void) { kmq_post_message(KMSG_CRED, KMSG_CRED_REFRESH, 0, NULL); }
/* Completion handler for KMSG_CRED messages. We control the overall logic of credentials acquisition and other operations here. Once a credentials operation is triggered, each successive message completion notification will be used to dispatch the messages for the next step in processing the operation. */ void KHMAPI kmsg_cred_completion(kmq_message *m) { khui_new_creds * nc; #ifdef DEBUG assert(m->type == KMSG_CRED); #else if(m->type != KMSG_CRED) return; /* huh? */ #endif switch(m->subtype) { case KMSG_CRED_PASSWORD: /* fallthrough */ case KMSG_CRED_NEW_CREDS: /* Cred types have attached themselves. Trigger the next phase. */ kmq_post_message(KMSG_CRED, KMSG_CRED_DIALOG_SETUP, 0, m->vparam); break; case KMSG_CRED_RENEW_CREDS: nc = (khui_new_creds *) m->vparam; /* khm_cred_dispatch_process_message() deals with the case where there are no credential types that wants to participate in this operation. */ khm_cred_dispatch_process_message(nc); break; case KMSG_CRED_DIALOG_SETUP: nc = (khui_new_creds *) m->vparam; khm_prep_newcredwnd(nc->hwnd); /* all the controls have been created. Now initialize them */ if (nc->n_types > 0) { kmq_post_subs_msg(nc->type_subs, nc->n_types, KMSG_CRED, KMSG_CRED_DIALOG_PRESTART, 0, m->vparam); } else { PostMessage(nc->hwnd, KHUI_WM_NC_NOTIFY, MAKEWPARAM(0, WMNC_DIALOG_PROCESS_COMPLETE), 0); } break; case KMSG_CRED_DIALOG_PRESTART: /* all prestart stuff is done. Now to activate the dialog */ nc = (khui_new_creds *) m->vparam; khm_show_newcredwnd(nc->hwnd); kmq_post_subs_msg(nc->type_subs, nc->n_types, KMSG_CRED, KMSG_CRED_DIALOG_START, 0, m->vparam); /* at this point, the dialog window takes over. We let it run the show until KMSG_CRED_DIALOG_END is posted by the dialog procedure. */ break; case KMSG_CRED_PROCESS: /* a wave of these messages have completed. We should check if there's more */ nc = (khui_new_creds *) m->vparam; /* if we are done processing all the plug-ins, then check if there were any errors reported. Otherwise we dispatch another set of messages. */ if(!khm_cred_dispatch_process_level(nc)) { if(kherr_is_error()) { khui_alert * alert; kherr_event * evt; kherr_context * ctx; wchar_t ws_tfmt[512]; wchar_t w_idname[KCDB_IDENT_MAXCCH_NAME]; wchar_t ws_title[ARRAYLENGTH(ws_tfmt) + KCDB_IDENT_MAXCCH_NAME]; khm_size cb; /* For renewals, we suppress the error message for the following case: - The renewal was for an identity - There are no identity credentials for the identity (no credentials that have the same type as the identity provider). */ if (nc->subtype == KMSG_CRED_RENEW_CREDS && nc->ctx.scope == KHUI_SCOPE_IDENT && nc->ctx.identity != NULL) { khm_handle tcs = NULL; /* credential set */ khm_size count = 0; khm_int32 id_ctype = KCDB_CREDTYPE_INVALID; khm_int32 delta = 0; kcdb_identity_get_type(&id_ctype); kcdb_credset_create(&tcs); kcdb_credset_collect(tcs, NULL, nc->ctx.identity, id_ctype, &delta); kcdb_credset_get_size(tcs, &count); kcdb_credset_delete(tcs); if (count == 0) { goto done_with_op; } } ctx = kherr_peek_context(); evt = kherr_get_err_event(ctx); kherr_evaluate_event(evt); khui_alert_create_empty(&alert); if (nc->subtype == KMSG_CRED_NEW_CREDS) { khui_alert_set_type(alert, KHUI_ALERTTYPE_ACQUIREFAIL); cb = sizeof(w_idname); if (nc->n_identities == 0 || KHM_FAILED(kcdb_identity_get_name(nc->identities[0], w_idname, &cb))) { /* an identity could not be determined */ LoadString(khm_hInstance, IDS_NC_FAILED_TITLE, ws_title, ARRAYLENGTH(ws_title)); } else { LoadString(khm_hInstance, IDS_NC_FAILED_TITLE_I, ws_tfmt, ARRAYLENGTH(ws_tfmt)); StringCbPrintf(ws_title, sizeof(ws_title), ws_tfmt, w_idname); khui_alert_set_ctx(alert, KHUI_SCOPE_IDENT, nc->identities[0], KCDB_CREDTYPE_INVALID, NULL); } } else if (nc->subtype == KMSG_CRED_PASSWORD) { khui_alert_set_type(alert, KHUI_ALERTTYPE_CHPW); cb = sizeof(w_idname); if (nc->n_identities == 0 || KHM_FAILED(kcdb_identity_get_name(nc->identities[0], w_idname, &cb))) { LoadString(khm_hInstance, IDS_NC_PWD_FAILED_TITLE, ws_title, ARRAYLENGTH(ws_title)); } else { LoadString(khm_hInstance, IDS_NC_PWD_FAILED_TITLE_I, ws_tfmt, ARRAYLENGTH(ws_tfmt)); StringCbPrintf(ws_title, sizeof(ws_title), ws_tfmt, w_idname); khui_alert_set_ctx(alert, KHUI_SCOPE_IDENT, nc->identities[0], KCDB_CREDTYPE_INVALID, NULL); } } else if (nc->subtype == KMSG_CRED_RENEW_CREDS) { khui_alert_set_type(alert, KHUI_ALERTTYPE_RENEWFAIL); cb = sizeof(w_idname); if (nc->ctx.identity == NULL || KHM_FAILED(kcdb_identity_get_name(nc->ctx.identity, w_idname, &cb))) { LoadString(khm_hInstance, IDS_NC_REN_FAILED_TITLE, ws_title, ARRAYLENGTH(ws_title)); } else { LoadString(khm_hInstance, IDS_NC_REN_FAILED_TITLE_I, ws_tfmt, ARRAYLENGTH(ws_tfmt)); StringCbPrintf(ws_title, sizeof(ws_title), ws_tfmt, w_idname); khui_alert_set_ctx(alert, KHUI_SCOPE_IDENT, nc->ctx.identity, KCDB_CREDTYPE_INVALID, NULL); } } else { #ifdef DEBUG assert(FALSE); #endif } khui_alert_set_title(alert, ws_title); khui_alert_set_severity(alert, evt->severity); if(!evt->long_desc) khui_alert_set_message(alert, evt->short_desc); else khui_alert_set_message(alert, evt->long_desc); if(evt->suggestion) khui_alert_set_suggestion(alert, evt->suggestion); if (nc->subtype == KMSG_CRED_RENEW_CREDS && nc->ctx.identity != NULL) { khm_int32 n_cmd; n_cmd = khm_get_identity_new_creds_action(nc->ctx.identity); if (n_cmd != 0) { khui_alert_add_command(alert, n_cmd); khui_alert_add_command(alert, KHUI_PACTION_CLOSE); khui_alert_set_flags(alert, KHUI_ALERT_FLAG_DISPATCH_CMD, KHUI_ALERT_FLAG_DISPATCH_CMD); } } khui_alert_show(alert); khui_alert_release(alert); kherr_release_context(ctx); kherr_clear_error(); } done_with_op: if (nc->subtype == KMSG_CRED_RENEW_CREDS) { kmq_post_message(KMSG_CRED, KMSG_CRED_END, 0, m->vparam); } else { PostMessage(nc->hwnd, KHUI_WM_NC_NOTIFY, MAKEWPARAM(0, WMNC_DIALOG_PROCESS_COMPLETE), 0); } } break; case KMSG_CRED_END: /* all is done. */ { khui_new_creds * nc; khm_boolean continue_cmdline = TRUE; nc = (khui_new_creds *) m->vparam; if (nc->subtype == KMSG_CRED_NEW_CREDS || nc->subtype == KMSG_CRED_PASSWORD) { khm_cred_end_dialog(nc); } else if (nc->subtype == KMSG_CRED_RENEW_CREDS) { /* if this is a renewal that was triggered while we were processing the commandline, then we need to update the pending renewal count. */ if (khm_startup.processing) { LONG renewals; renewals = InterlockedDecrement(&khm_startup.pending_renewals); if (renewals != 0) { continue_cmdline = FALSE; } } } khui_cw_destroy_cred_blob(nc); kmq_post_message(KMSG_CRED, KMSG_CRED_REFRESH, 0, 0); if (continue_cmdline) kmq_post_message(KMSG_ACT, KMSG_ACT_CONTINUE_CMDLINE, 0, 0); } break; /* property sheet stuff */ case KMSG_CRED_PP_BEGIN: /* all the pages should have been added by now. Just send out the precreate message */ kmq_post_message(KMSG_CRED, KMSG_CRED_PP_PRECREATE, 0, m->vparam); break; case KMSG_CRED_PP_END: kmq_post_message(KMSG_CRED, KMSG_CRED_PP_DESTROY, 0, m->vparam); break; case KMSG_CRED_DESTROY_CREDS: #ifdef DEBUG assert(m->vparam != NULL); #endif khui_context_release((khui_action_context *) m->vparam); PFREE(m->vparam); kmq_post_message(KMSG_CRED, KMSG_CRED_REFRESH, 0, 0); kmq_post_message(KMSG_ACT, KMSG_ACT_CONTINUE_CMDLINE, 0, 0); break; case KMSG_CRED_IMPORT: { khm_boolean continue_cmdline = FALSE; LONG pending_renewals; /* once an import operation ends, we have to trigger a renewal so that other plug-ins that didn't participate in the import operation can have a chance at getting the necessary credentials. If we are in the middle of processing the commandline, we have to be a little bit careful. We can't issue a commandline conituation message right now because the import action is still ongoing (since the renewals are part of the action). Once the renewals have completed, the completion handler will automatically issue a commandline continuation message. However, if there were no identities to renew, then we have to issue the message ourselves. */ InterlockedIncrement(&khm_startup.pending_renewals); khm_cred_renew_all_identities(); pending_renewals = InterlockedDecrement(&khm_startup.pending_renewals); if (pending_renewals == 0 && khm_startup.processing) kmq_post_message(KMSG_ACT, KMSG_ACT_CONTINUE_CMDLINE, 0, 0); } break; case KMSG_CRED_REFRESH: kcdb_identity_refresh_all(); break; } }
void kcdb_credtype_post_message(khm_int32 op, kcdb_credtype * type) { kcdb_credtype_hold((kcdb_credtype_i *) type); kmq_post_message(KMSG_KCDB, KMSG_KCDB_CREDTYPE, op, (void *) type); }
KHMEXP khm_int32 KHMAPI khui_cfg_register(khui_config_node vparent, const khui_config_node_reg * reg) { size_t cb_name; size_t cb_short_desc; size_t cb_long_desc; khui_config_node_i * node; khui_config_node_i * parent; khui_config_node t; wchar_t * name; wchar_t * short_desc; wchar_t * long_desc; cfgui_init_once(); if (!reg || FAILED(StringCbLength(reg->name, KHUI_MAXCB_NAME, &cb_name)) || FAILED(StringCbLength(reg->short_desc, KHUI_MAXCB_SHORT_DESC, &cb_short_desc)) || FAILED(StringCbLength(reg->long_desc, KHUI_MAXCB_LONG_DESC, &cb_long_desc)) || (vparent && !cfgui_is_valid_node_handle(vparent))) return KHM_ERROR_INVALID_PARAM; if (KHM_SUCCEEDED(khui_cfg_open(vparent, reg->name, &t))) { khui_cfg_release(t); return KHM_ERROR_DUPLICATE; } cb_name += sizeof(wchar_t); cb_short_desc += sizeof(wchar_t); cb_long_desc += sizeof(wchar_t); node = cfgui_create_new_node(); node->reg = *reg; node->reg.flags &= KHUI_CNFLAGMASK_STATIC; name = PMALLOC(cb_name); StringCbCopy(name, cb_name, reg->name); short_desc = PMALLOC(cb_short_desc); StringCbCopy(short_desc, cb_short_desc, reg->short_desc); long_desc = PMALLOC(cb_long_desc); StringCbCopy(long_desc, cb_long_desc, reg->long_desc); node->reg.name = name; node->reg.short_desc = short_desc; node->reg.long_desc = long_desc; node->flags = node->reg.flags; if (vparent == NULL) { parent = cfgui_root_config; } else { parent = cfgui_node_i_from_handle(vparent); } /* plugin handles should not be obtained lightly. For the moment, the cleanup of nodes doesn't happen until module unload and module unload doesn't happen until all the plugin and module handles have been freed. */ /* node->owner = kmm_this_plugin(); */ EnterCriticalSection(&cs_cfgui); TADDCHILD(parent, node); if (hwnd_cfgui) { SendMessage(hwnd_cfgui, KHUI_WM_CFG_NOTIFY, MAKEWPARAM(0, WMCFG_SYNC_NODE_LIST), 0); } LeaveCriticalSection(&cs_cfgui); /* when the root config list changes, we need to notify the UI. this way, the Options menu can be kept in sync. */ if (parent == cfgui_root_config) { kmq_post_message(KMSG_ACT, KMSG_ACT_SYNC_CFG, 0, 0); } return KHM_ERROR_SUCCESS; }
void kcdb_type_post_message(khm_int32 op, kcdb_type_i * t) { kcdb_type_hold(t); kmq_post_message(KMSG_KCDB, KMSG_KCDB_TYPE, op, (void *) t); }
void khm_cred_obtain_new_creds(wchar_t * title) { khui_new_creds * nc; LPNETID_DLGINFO pdlginfo; khm_size cb; if (!khm_cred_begin_dialog()) return; khui_cw_create_cred_blob(&nc); nc->subtype = KMSG_CRED_NEW_CREDS; dialog_nc = nc; khui_context_get(&nc->ctx); kcdb_identpro_get_ui_cb((void *) &nc->ident_cb); if (nc->ident_cb == NULL) { wchar_t title[256]; wchar_t msg[512]; wchar_t suggestion[512]; khui_alert * a; LoadString(khm_hInstance, IDS_ERR_TITLE_NO_IDENTPRO, title, ARRAYLENGTH(title)); LoadString(khm_hInstance, IDS_ERR_MSG_NO_IDENTPRO, msg, ARRAYLENGTH(msg)); LoadString(khm_hInstance, IDS_ERR_SUGG_NO_IDENTPRO, suggestion, ARRAYLENGTH(suggestion)); khui_alert_create_simple(title, msg, KHERR_ERROR, &a); khui_alert_set_suggestion(a, suggestion); khui_alert_show(a); khui_alert_release(a); khui_context_release(&nc->ctx); nc->result = KHUI_NC_RESULT_CANCEL; khm_cred_end_dialog(nc); khui_cw_destroy_cred_blob(nc); return; } if (title) { if (SUCCEEDED(StringCbLength(title, KHUI_MAXCB_TITLE, &cb))) { cb += sizeof(wchar_t); nc->window_title = PMALLOC(cb); #ifdef DEBUG assert(nc->window_title); #endif StringCbCopy(nc->window_title, cb, title); } } else if (nc->ctx.cb_vparam == sizeof(NETID_DLGINFO) && (pdlginfo = nc->ctx.vparam) && pdlginfo->size == NETID_DLGINFO_V1_SZ && pdlginfo->in.title[0] && SUCCEEDED(StringCchLength(pdlginfo->in.title, NETID_TITLE_SZ, &cb))) { cb = (cb + 1) * sizeof(wchar_t); nc->window_title = PMALLOC(cb); #ifdef DEBUG assert(nc->window_title); #endif StringCbCopy(nc->window_title, cb, pdlginfo->in.title); } khm_create_newcredwnd(khm_hwnd_main, nc); if (nc->hwnd != NULL) { _begin_task(KHERR_CF_TRANSITIVE); _report_sr0(KHERR_NONE, IDS_CTX_NEW_CREDS); _describe(); kmq_post_message(KMSG_CRED, KMSG_CRED_NEW_CREDS, 0, (void *) nc); _end_task(); } else { khui_context_release(&nc->ctx); nc->result = KHUI_NC_RESULT_CANCEL; khm_cred_end_dialog(nc); khui_cw_destroy_cred_blob(nc); } }
/*! \internal Collect credentials from cs2 to cs1 which have already been selected into cl1 and cl2. - Credentials in cl2 that are not in cl1 will get added to cs1 - Credentials in cl1 that are not in cl2 will get removed from cs1 - Credentials in cl1 and cl2 will be updated in cs1 cl1 and cl2 will be modified. */ khm_int32 kcdb_credset_collect_core(kcdb_credset * cs1, kcdb_cred ** cl1, khm_int32 ncl1, kcdb_credset * cs2, kcdb_cred ** cl2, khm_int32 ncl2, khm_int32 * delta) { int i, j; int ldelta = 0; khm_int32 rv; /* find matching creds and update them */ for(i=0; i<ncl1; i++) if(cl1[i]) { for(j=0; j<ncl2; j++) if(cl2[j] && kcdb_creds_is_equal((khm_handle) cl1[i], (khm_handle) cl2[j])) { /* they are equivalent. make them equal */ /* depending on whether any changes were made, update ldelta with the proper bit flag */ rv = kcdb_cred_update(cl1[i], cl2[j]); if (rv == KHM_ERROR_SUCCESS) { kcdb_credset_update_cred_ref((khm_handle) cs1, (khm_handle) cl1[i]); ldelta |= KCDB_DELTA_MODIFY; } cl2[j] = NULL; cl1[i] = NULL; break; } } /* all the creds that are left in cl1 need to be removed */ for(i=0; i<ncl1; i++) if(cl1[i]) { kcdb_credset_del_cred_ref((khm_handle) cs1, (khm_handle) cl1[i]); cl1[i] = NULL; ldelta |= KCDB_DELTA_DEL; } /* all the creds in cl2 need to be added to cs1 */ for(j=0; j<ncl2; j++) if(cl2[j]) { /* duplicate the credential and add it if we are adding it to the root credential store. */ if(cs1 == kcdb_root_credset) { khm_handle h; if(KHM_SUCCEEDED(kcdb_cred_dup((khm_handle) cl2[j], &h))) { kcdb_credset_add_cred((khm_handle) cs1, h, -1); kcdb_cred_release(h); } } else kcdb_credset_add_cred((khm_handle) cs1, cl2[j], -1); cl2[j] = NULL; ldelta |= KCDB_DELTA_ADD; } if(delta) *delta = ldelta; if((cs1 == kcdb_root_credset) && ldelta) { /* something changed in the root credential set */ kmq_post_message(KMSG_CRED,KMSG_CRED_ROOTDELTA,ldelta,NULL); } return KHM_ERROR_SUCCESS; }
/*! \internal \brief Manages a plugin message thread. Each plugin gets its own plugin thread which is used to dispatch messages to the plugin. This acts as the thread function for the plugin thread.*/ DWORD WINAPI kmmint_plugin_broker(LPVOID lpParameter) { DWORD rv = 0; kmm_plugin_i * p = (kmm_plugin_i *) lpParameter; PDESCTHREAD(p->p.name, L"KMM"); _begin_task(0); _report_mr1(KHERR_NONE, MSG_PB_START, _cstr(p->p.name)); _describe(); TlsSetValue(tls_kmm, (LPVOID) p); kmm_hold_plugin(kmm_handle_from_plugin(p)); p->tid_thread = GetCurrentThreadId(); if (IsBadCodePtr(p->p.msg_proc)) { _report_mr0(KHERR_WARNING, MSG_PB_INVALID_CODE_PTR); rv = KHM_ERROR_INVALID_PARAM; } else { rv = (*p->p.msg_proc)(KMSG_SYSTEM, KMSG_SYSTEM_INIT, 0, (void *) &(p->p)); _report_mr1(KHERR_INFO, MSG_PB_INIT_RV, _int32(rv)); } /* if it fails to initialize, we exit the plugin */ if(KHM_FAILED(rv)) { kherr_report(KHERR_ERROR, (wchar_t *) MSG_PB_INIT_FAIL_S, (wchar_t *) KHERR_FACILITY, NULL, (wchar_t *) MSG_PB_INIT_FAIL, (wchar_t *) MSG_PB_INIT_FAIL_G, KHERR_FACILITY_ID, KHERR_SUGGEST_NONE, _cstr(p->p.name), _cstr(p->p.description), _cstr(p->module->path), _cstr(p->module->support), KHERR_RF_MSG_SHORT_DESC | KHERR_RF_MSG_LONG_DESC | KHERR_RF_MSG_SUGGEST #ifdef _WIN32 ,KHERR_HMODULE #endif ); _resolve(); /* exit the plugin first. Otherwise it may not uninitialize correctly */ (*p->p.msg_proc)(KMSG_SYSTEM, KMSG_SYSTEM_EXIT, 0, (void *) &(p->p)); kmmint_remove_from_plugin_queue(p); rv = 1; _end_task(); p->state = KMM_PLUGIN_STATE_FAIL_INIT; goto _exit; } /* subscribe to default message classes by plugin type */ if(p->p.type == KHM_PITYPE_CRED) { kmq_subscribe(KMSG_SYSTEM, p->p.msg_proc); kmq_subscribe(KMSG_KCDB, p->p.msg_proc); kmq_subscribe(KMSG_CRED, p->p.msg_proc); } else if(p->p.type == KHM_PITYPE_IDENT) { khm_handle h = NULL; kmq_subscribe(KMSG_SYSTEM, p->p.msg_proc); kmq_subscribe(KMSG_KCDB, p->p.msg_proc); kmq_create_subscription(p->p.msg_proc, &h); kcdb_identity_set_provider(h); /* kcdb deletes the subscription when it's done with it */ } else if(p->p.type == KHM_PITYPE_CONFIG) { /*TODO: subscribe to configuration provider messages here */ } p->state = KMM_PLUGIN_STATE_RUNNING; _report_mr0(KHERR_INFO, MSG_PB_INIT_DONE); _end_task(); /* if there were any plugins that were waiting for this one to start, we should start them too */ EnterCriticalSection(&cs_kmm); do { kmm_plugin_i * pd; int i; for(i=0; i < p->n_dependants; i++) { pd = p->dependants[i]; pd->n_unresolved--; if(pd->n_unresolved == 0) { kmmint_add_to_plugin_queue(pd); kmm_hold_plugin(kmm_handle_from_plugin(pd)); kmq_post_message(KMSG_KMM, KMSG_KMM_I_REG, KMM_REG_INIT_PLUGIN, (void *) pd); } } } while(FALSE); LeaveCriticalSection(&cs_kmm); kmmint_remove_from_plugin_queue(p); /* main message loop */ while(KHM_SUCCEEDED(kmq_dispatch(INFINITE))); /* unsubscribe from default message classes by plugin type */ if(p->p.type == KHM_PITYPE_CRED) { kmq_unsubscribe(KMSG_SYSTEM, p->p.msg_proc); kmq_unsubscribe(KMSG_KCDB, p->p.msg_proc); kmq_unsubscribe(KMSG_CRED, p->p.msg_proc); } else if (p->p.type == KHM_PITYPE_IDENT) { kmq_unsubscribe(KMSG_KCDB, p->p.msg_proc); kmq_unsubscribe(KMSG_SYSTEM, p->p.msg_proc); kcdb_identity_set_provider(NULL); } else if(p->p.type == KHM_PITYPE_CONFIG) { /*TODO: unsubscribe from configuration provider messages here */ } p->p.msg_proc(KMSG_SYSTEM, KMSG_SYSTEM_EXIT, 0, (void *) &(p->p)); _exit: if (p->state >= 0) p->state = KMM_PLUGIN_STATE_EXITED; /* the following call will automatically release the plugin */ kmq_post_message(KMSG_KMM, KMSG_KMM_I_REG, KMM_REG_EXIT_PLUGIN, (void *) p); TlsSetValue(tls_kmm, (LPVOID) 0); ExitThread(rv); /* not reached */ return rv; }
/*! \internal \brief Initialize a plugin \note If kmmint_init_plugin() is called on a plugin, then kmmint_exit_plugin() \b must be called for the plugin. \note Should only be called from the context of the registrar thread */ void kmmint_init_plugin(kmm_plugin_i * p) { DWORD dummy; khm_handle csp_plugin = NULL; khm_handle csp_plugins = NULL; khm_int32 t; /* the following will be undone in kmmint_exit_plugin() */ kmm_hold_plugin(kmm_handle_from_plugin(p)); EnterCriticalSection(&cs_kmm); if(p->state != KMM_PLUGIN_STATE_REG && p->state != KMM_PLUGIN_STATE_HOLD) { LeaveCriticalSection(&cs_kmm); goto _exit; } _begin_task(0); _report_mr1(KHERR_NONE, MSG_IP_TASK_DESC, _cstr(p->p.name)); _describe(); if(p->state == KMM_PLUGIN_STATE_HOLD) { /* if this plugin was held, then we already had a hold from the initial attempt to start the plugin. Undo the hold we did a few lines earlier. */ kmm_release_plugin(kmm_handle_from_plugin(p)); /* same for the plugin count for the module. */ #ifdef DEBUG assert(p->flags & KMM_PLUGIN_FLAG_IN_MODCOUNT); #endif p->module->plugin_count--; p->flags &= ~KMM_PLUGIN_FLAG_IN_MODCOUNT; } p->state = KMM_PLUGIN_STATE_PREINIT; kmmint_delist_plugin(p); kmmint_list_plugin(p); LeaveCriticalSection(&cs_kmm); if(KHM_FAILED(kmm_get_plugins_config(0, &csp_plugins))) { _report_mr0(KHERR_ERROR, MSG_IP_GET_CONFIG); p->state = KMM_PLUGIN_STATE_FAIL_UNKNOWN; goto _exit; } if(KHM_FAILED(kmm_get_plugin_config(p->p.name, 0, &csp_plugin))) { if(KHM_FAILED(kmm_register_plugin(&(p->p), 0))) { _report_mr0(KHERR_ERROR, MSG_IP_NOT_REGISTERED); p->state = KMM_PLUGIN_STATE_FAIL_NOT_REGISTERED; goto _exit; } if(KHM_FAILED(kmm_get_plugin_config(p->p.name, 0, &csp_plugin))) { _report_mr0(KHERR_ERROR, MSG_IP_NOT_REGISTERED); p->state = KMM_PLUGIN_STATE_FAIL_NOT_REGISTERED; goto _exit; } } if (KHM_SUCCEEDED(khc_read_int32(csp_plugin, L"Disabled", &t)) && t) { p->flags |= KMM_PLUGIN_FLAG_DISABLED; p->state = KMM_PLUGIN_STATE_FAIL_DISABLED; goto _exit; } #if 0 /*TODO: check the failure count and act accordingly */ if(KHM_SUCCEEDED(khc_read_int32(csp_plugin, L"FailureCount", &t)) && (t > 0)) { } #endif EnterCriticalSection(&cs_kmm); p->n_depends = 0; p->n_unresolved = 0; do { wchar_t * deps = NULL; wchar_t * d; khm_size sz = 0; if(khc_read_multi_string(csp_plugin, L"Dependencies", NULL, &sz) != KHM_ERROR_TOO_LONG) break; deps = PMALLOC(sz); if(KHM_FAILED(khc_read_multi_string(csp_plugin, L"Dependencies", deps, &sz))) { if(deps) PFREE(deps); break; } for(d = deps; d && *d; d = multi_string_next(d)) { kmm_plugin_i * pd; int i; pd = kmmint_get_plugin_i(d); if(pd->state == KMM_PLUGIN_STATE_NONE) { /* the dependant was not previously known */ pd->state = KMM_PLUGIN_STATE_PLACEHOLDER; } for(i=0; i < pd->n_dependants; i++) { if(pd->dependants[i] == p) break; } if(i >= pd->n_dependants) { if( pd->n_dependants >= KMM_MAX_DEPENDANTS ) { /*TODO: handle this gracefully */ RaiseException(1, EXCEPTION_NONCONTINUABLE, 0, NULL); } /* released in kmmint_free_plugin() */ kmm_hold_plugin(kmm_handle_from_plugin(p)); pd->dependants[pd->n_dependants] = p; pd->n_dependants++; } p->n_depends++; if(pd->state != KMM_PLUGIN_STATE_RUNNING) { p->n_unresolved++; } } if(p->n_unresolved > 0) { p->state = KMM_PLUGIN_STATE_HOLD; } PFREE(deps); } while(FALSE); #ifdef DEBUG assert(!(p->flags & KMM_PLUGIN_FLAG_IN_MODCOUNT)); #endif p->flags |= KMM_PLUGIN_FLAG_IN_MODCOUNT; p->module->plugin_count++; LeaveCriticalSection(&cs_kmm); if(p->state == KMM_PLUGIN_STATE_HOLD) { _report_mr1(KHERR_INFO, MSG_IP_HOLD, _dupstr(p->p.name)); goto _exit_post; } kmmint_add_to_plugin_queue(p); p->ht_thread = CreateThread(NULL, 0, kmmint_plugin_broker, (LPVOID) p, CREATE_SUSPENDED, &dummy); p->state = KMM_PLUGIN_STATE_INIT; ResumeThread(p->ht_thread); _exit_post: if(csp_plugin != NULL) khc_close_space(csp_plugin); if(csp_plugins != NULL) khc_close_space(csp_plugins); _report_mr2(KHERR_INFO, MSG_IP_STATE, _dupstr(p->p.name), _int32(p->state)); _end_task(); return; /* jump here if an error condition happens before the plugin broker thread starts and the plugin should be unloaded */ _exit: if(csp_plugin != NULL) khc_close_space(csp_plugin); if(csp_plugins != NULL) khc_close_space(csp_plugins); _report_mr2(KHERR_WARNING, MSG_IP_EXITING, _dupstr(p->p.name), _int32(p->state)); _end_task(); #ifdef ASYNC_PLUGIN_UNLOAD_ON_FAILURE kmm_hold_plugin(kmm_handle_from_plugin(p)); kmq_post_message(KMSG_KMM, KMSG_KMM_I_REG, KMM_REG_EXIT_PLUGIN, (void *) p); #else kmmint_exit_plugin(p); #endif }
void kcdbint_identpro_post_message(khm_int32 op, kcdb_identpro_i * p) { identpro_hold(p); kmq_post_message(KMSG_KCDB, KMSG_KCDB_IDENTPRO, op, (void *) p); }