/*! \internal \brief Message handler for the registrar thread. */ khm_boolean KHMAPI kmmint_reg_cb(khm_int32 msg_type, khm_int32 msg_sub_type, khm_ui_4 uparam, void *vparam) { /* we should only be getting <KMSG_KMM,KMSG_KMM_I_REG> anyway */ if(msg_type != KMSG_KMM || msg_sub_type != KMSG_KMM_I_REG) return FALSE; switch(uparam) { case KMM_REG_INIT_MODULE: kmmint_init_module((kmm_module_i *) vparam); kmm_release_module(kmm_handle_from_module((kmm_module_i *) vparam)); break; case KMM_REG_EXIT_MODULE: kmmint_exit_module((kmm_module_i *) vparam); kmm_release_module(kmm_handle_from_module((kmm_module_i *) vparam)); break; case KMM_REG_INIT_PLUGIN: kmmint_init_plugin((kmm_plugin_i *) vparam); kmm_release_plugin(kmm_handle_from_plugin((kmm_plugin_i *) vparam)); break; case KMM_REG_EXIT_PLUGIN: kmmint_exit_plugin((kmm_plugin_i *) vparam); kmm_release_plugin(kmm_handle_from_plugin((kmm_plugin_i *) vparam)); break; } return TRUE; }
KHMEXP khm_int32 KHMAPI kmm_release_module_info_i(kmm_module_info * info) { if (info->h_module) kmm_release_module(info->h_module); ZeroMemory(info, sizeof(*info)); return KHM_ERROR_SUCCESS; }
/* called with cs_kmm held */ void kmmint_free_plugin(kmm_plugin_i * pi) { int i; pi->magic = 0; hash_del(hash_plugins, (void *) pi->p.name); kmmint_delist_plugin(pi); for(i=0; i<pi->n_dependants; i++) { kmm_release_plugin(kmm_handle_from_plugin(pi->dependants[i])); pi->dependants[i] = NULL; } if(pi->module) { kmm_release_module(kmm_handle_from_module(pi->module)); } pi->module = NULL; pi->p.module = NULL; if(pi->p.name) PFREE(pi->p.name); pi->p.name = NULL; if(pi->p.description) PFREE(pi->p.description); pi->p.description = NULL; if(pi->p.dependencies) PFREE(pi->p.dependencies); pi->p.dependencies = NULL; PFREE(pi); }
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 \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); } }
/*! \internal \brief Initialize a module \a m is not in the linked list yet. \note Should only be called from the context of the registrar thread. */ void kmmint_init_module(kmm_module_i * m) { HMODULE hm; init_module_t p_init_module; kmm_plugin_i * pi; khm_int32 rv; khm_handle csp_mod = NULL; khm_handle csp_mods = NULL; khm_size sz; khm_int32 i; /* error condition handling */ BOOL exit_module = FALSE; BOOL release_module = TRUE; BOOL record_failure = FALSE; /* failure handling */ khm_int32 max_fail_count = 0; khm_int64 fail_reset_time = 0; _begin_task(0); _report_mr1(KHERR_NONE, MSG_INIT_MODULE, _cstr(m->name)); _describe(); kmm_hold_module(kmm_handle_from_module(m)); if(KHM_FAILED(kmm_get_modules_config(0, &csp_mods))) { _report_mr0(KHERR_ERROR, MSG_IM_GET_CONFIG); _location(L"kmm_get_modules_config()"); m->state = KMM_MODULE_STATE_FAIL_UNKNOWN; goto _exit; } khc_read_int32(csp_mods, L"ModuleMaxFailureCount", &max_fail_count); khc_read_int64(csp_mods, L"ModuleFailureCountResetTime", &fail_reset_time); /* If the module is not in the pre-init state, we can't initialize it. */ if(m->state != KMM_MODULE_STATE_PREINIT) { _report_mr1(KHERR_INFO, MSG_IM_NOT_PREINIT, _int32(m->state)); goto _exit; } if(KHM_FAILED(kmm_get_module_config(m->name, 0, &csp_mod))) { _report_mr0(KHERR_ERROR, MSG_IM_NOT_REGISTERED); m->state = KMM_MODULE_STATE_FAIL_NOT_REGISTERED; goto _exit; } if(KHM_SUCCEEDED(khc_read_int32(csp_mod, L"Disabled", &i)) && i) { _report_mr0(KHERR_INFO, MSG_IM_DISABLED); m->state = KMM_MODULE_STATE_FAIL_DISABLED; goto _exit; } if(KHM_SUCCEEDED(khc_read_int32(csp_mod, L"NoUnload", &i)) && i) { m->flags |= KMM_MODULE_FLAG_NOUNLOAD; } if(KHM_SUCCEEDED(khc_read_int32(csp_mod, L"FailureCount", &i))) { khm_int64 tm; khm_int64 ct; FILETIME fct; khm_int32 last_reason = 0; /* reset the failure count if the failure count reset time period has elapsed */ tm = 0; khc_read_int64(csp_mod, L"FailureTime", &tm); GetSystemTimeAsFileTime(&fct); ct = (FtToInt(&fct) - tm) / 10000000i64; if(tm > 0 && ct > fail_reset_time) { i = 0; khc_write_int32(csp_mod, L"FailureCount", 0); khc_write_int64(csp_mod, L"FailureTime", 0); } khc_read_int32(csp_mod, L"FailureReason", &last_reason); /* did we exceed the max failure count? However, we ignore the max failure count if the reason why it didn't load the last time was because the module wasn't found. */ if(i > max_fail_count && last_reason != KMM_MODULE_STATE_FAIL_NOT_FOUND) { /* failed too many times */ _report_mr0(KHERR_INFO, MSG_IM_MAX_FAIL); m->state = KMM_MODULE_STATE_FAIL_MAX_FAILURE; goto _exit; } } if(khc_read_string(csp_mod, L"ImagePath", NULL, &sz) == KHM_ERROR_TOO_LONG) { if(m->path) PFREE(m->path); m->path = PMALLOC(sz); khc_read_string(csp_mod, L"ImagePath", m->path, &sz); } else { _report_mr0(KHERR_ERROR, MSG_IM_NOT_REGISTERED); m->state = KMM_MODULE_STATE_FAIL_NOT_REGISTERED; goto _exit; } rv = kmmint_read_module_info(m); if (KHM_FAILED(rv)) { if (rv == KHM_ERROR_INCOMPATIBLE) { _report_mr0(KHERR_ERROR, MSG_IM_INCOMPATIBLE); m->state = KMM_MODULE_STATE_FAIL_INCOMPAT; } else if (rv == KHM_ERROR_NOT_FOUND) { _report_mr1(KHERR_ERROR, MSG_IM_NOT_FOUND, _dupstr(m->path)); m->state = KMM_MODULE_STATE_FAIL_NOT_FOUND; } else { _report_mr0(KHERR_ERROR, MSG_IM_INVALID_MODULE); m->state = KMM_MODULE_STATE_FAIL_INV_MODULE; } goto _exit; } /* check again */ if(m->state != KMM_MODULE_STATE_PREINIT) { _report_mr0(KHERR_ERROR, MSG_IM_NOT_PREINIT); goto _exit; } /* from this point on, we must record any failure codes */ record_failure = TRUE; hm = LoadLibrary(m->path); if(!hm) { m->h_module = NULL; m->state = KMM_MODULE_STATE_FAIL_NOT_FOUND; _report_mr1(KHERR_ERROR, MSG_IM_NOT_FOUND, _dupstr(m->path)); goto _exit; } /* from this point on, we need to discard the module through exit_module */ ResetEvent(evt_exit); kmm_active_modules++; release_module = FALSE; exit_module = TRUE; m->flags |= KMM_MODULE_FLAG_LOADED; m->h_module = hm; /* TODO: check signatures */ p_init_module = (init_module_t) GetProcAddress(hm, EXP_INIT_MODULE); if(!p_init_module) { _report_mr1(KHERR_ERROR, MSG_IM_NO_ENTRY, _cstr(EXP_INIT_MODULE)); m->state = KMM_MODULE_STATE_FAIL_INVALID; goto _exit; } m->state = KMM_MODULE_STATE_INIT; /* call init_module() */ rv = (*p_init_module)(kmm_handle_from_module(m)); m->flags |= KMM_MODULE_FLAG_INITP; if(KHM_FAILED(rv)) { _report_mr1(KHERR_ERROR, MSG_IM_INIT_FAIL, _int32(rv)); m->state = KMM_MODULE_STATE_FAIL_LOAD; goto _exit; } if(!m->plugins) { _report_mr0(KHERR_ERROR, MSG_IM_NO_PLUGINS); m->state = KMM_MODULE_STATE_FAIL_NO_PLUGINS; record_failure = FALSE; goto _exit; } m->state = KMM_MODULE_STATE_INITPLUG; do { LPOP(&(m->plugins), &pi); if(pi) { pi->flags &= ~KMM_PLUGIN_FLAG_IN_MODLIST; kmmint_init_plugin(pi); /* release the hold obtained in kmm_provide_plugin() */ kmm_release_plugin(kmm_handle_from_plugin(pi)); } } while(pi); if(!m->plugin_count) { /* We don't want to report this case. This usually means that the plugins that were provided by the module were disabled. */ #ifdef REPORT_EMPTY_MODULES _report_mr0(KHERR_ERROR, MSG_IM_NO_PLUGINS); m->state = KMM_MODULE_STATE_FAIL_NO_PLUGINS; #endif record_failure = FALSE; goto _exit; } m->state = KMM_MODULE_STATE_RUNNING; exit_module = FALSE; record_failure = FALSE; _exit: if(csp_mod) { if(record_failure) { FILETIME fct; i = 0; khc_read_int32(csp_mod, L"FailureCount", &i); i++; khc_write_int32(csp_mod, L"FailureCount", i); if(i==1) { /* first fault */ GetSystemTimeAsFileTime(&fct); khc_write_int64(csp_mod, L"FailureTime", FtToInt(&fct)); } khc_write_int32(csp_mod, L"FailureReason", m->state); } khc_close_space(csp_mod); } if(csp_mods) khc_close_space(csp_mods); _report_mr2(KHERR_INFO, MSG_IM_MOD_STATE, _dupstr(m->name), _int32(m->state)); kmmint_remove_from_module_queue(); /* if something went wrong after init_module was called on the module code, we need to call exit_module */ if(exit_module) kmmint_exit_module(m); if(release_module) kmm_release_module(kmm_handle_from_module(m)); if (kherr_is_error()) { kherr_context * c; kherr_event * err_e = NULL; kherr_event * warn_e = NULL; kherr_event * e; c = kherr_peek_context(); err_e = kherr_get_err_event(c); for(e = kherr_get_first_event(c); e; e = kherr_get_next_event(e)) { if (e != err_e && e->severity == KHERR_WARNING) { warn_e = e; break; } } kherr_evaluate_event(err_e); if (warn_e) kherr_evaluate_event(warn_e); kherr_clear_error(); e = kherr_report(KHERR_ERROR, (wchar_t *) MSG_IMERR_TITLE, KHERR_FACILITY, NULL, err_e->long_desc, ((warn_e)? (wchar_t *)MSG_IMERR_SUGGEST: NULL), KHERR_FACILITY_ID, KHERR_SUGGEST_NONE, _cstr(m->name), ((warn_e)? _cstr(warn_e->long_desc):_vnull()), _vnull(),_vnull(), KHERR_RF_MSG_SHORT_DESC | ((warn_e)? KHERR_RF_MSG_SUGGEST: 0), KHERR_HMODULE); kherr_evaluate_event(e); kherr_release_context(c); } _end_task(); }
INT_PTR CALLBACK khm_cfg_plugins_proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { plugin_dlg_data * d; switch(uMsg) { case WM_INITDIALOG: { kmm_plugin p; kmm_plugin pn; kmm_module m; khm_size i; LVCOLUMN lvc; RECT r; HWND hw; wchar_t buf[256]; HIMAGELIST h_ilist; HICON h_icon; d = PMALLOC(sizeof(*d)); #ifdef DEBUG assert(d); #endif ZeroMemory(d, sizeof(*d)); #pragma warning(push) #pragma warning(disable: 4244) SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) d); #pragma warning(pop) p = NULL; i = 0; do { if (KHM_FAILED(kmm_get_next_plugin(p, &pn))) break; if (p) kmm_release_plugin(p); p = pn; #ifdef DEBUG assert(d->info[i] == NULL); #endif d->info[i] = PMALLOC(sizeof(*(d->info[i]))); #ifdef DEBUG assert(d->info[i]); #endif ZeroMemory(&d->info[i]->plugin, sizeof(d->info[i]->plugin)); if (KHM_FAILED(kmm_get_plugin_info_i(p, &d->info[i]->plugin))) { PFREE(d->info[i]); d->info[i] = NULL; break; } ZeroMemory(&d->info[i]->module, sizeof(d->info[i]->module)); if (KHM_SUCCEEDED(kmm_load_module(d->info[i]->plugin.reg.module, KMM_LM_FLAG_NOLOAD, &m))) { kmm_get_module_info_i(m, &d->info[i]->module); kmm_release_module(m); } i ++; if (i == MAX_PLUGINS) break; } while(p); if (p) kmm_release_plugin(p); d->n_info = i; /* now populate the list view */ hw = GetDlgItem(hwnd, IDC_CFG_PLUGINS); #ifdef DEBUG assert(hw); #endif h_ilist = ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), ILC_COLOR8, 4, 4); h_icon = LoadImage(khm_hInstance, MAKEINTRESOURCE(IDI_CFG_PLUGIN), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR); #ifdef DEBUG assert(h_icon); #endif ImageList_AddIcon(h_ilist, h_icon); DestroyIcon(h_icon); h_icon = LoadImage(khm_hInstance, MAKEINTRESOURCE(IDI_CFG_PLUGIN_DIS), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR); #ifdef DEBUG assert(h_icon); #endif ImageList_AddIcon(h_ilist, h_icon); DestroyIcon(h_icon); h_icon = LoadImage(khm_hInstance, MAKEINTRESOURCE(IDI_CFG_PLUGIN_ERR), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR); #ifdef DEBUG assert(h_icon); #endif ImageList_AddIcon(h_ilist, h_icon); DestroyIcon(h_icon); ListView_SetImageList(hw, h_ilist, LVSIL_STATE); ZeroMemory(&lvc, sizeof(lvc)); lvc.mask = LVCF_TEXT | LVCF_WIDTH; GetWindowRect(hw, &r); lvc.cx = ((r.right - r.left) * 95) / 100; lvc.pszText = buf; LoadString(khm_hInstance, IDS_CFG_PI_COL_PLUGINS, buf, ARRAYLENGTH(buf)); ListView_InsertColumn(hw, 0, &lvc); for(i=0; i<d->n_info; i++) { LVITEM lvi; ZeroMemory(&lvi, sizeof(lvi)); lvi.mask = LVIF_PARAM | LVIF_TEXT | LVIF_STATE; lvi.lParam = (LPARAM) d->info[i]; lvi.pszText = d->info[i]->plugin.reg.name; if (d->info[i]->plugin.flags & KMM_PLUGIN_FLAG_DISABLED) { lvi.state = INDEXTOSTATEIMAGEMASK(IDX_PLUGIN_DISABLED); } else if (d->info[i]->plugin.state < 0) { lvi.state = INDEXTOSTATEIMAGEMASK(IDX_PLUGIN_ERROR); } else { lvi.state = INDEXTOSTATEIMAGEMASK(IDX_PLUGIN_NORMAL); } ListView_InsertItem(hw, &lvi); } d->plugin_ico = (HICON) LoadImage(khm_hInstance, MAKEINTRESOURCE(IDI_CFG_PLUGIN), IMAGE_ICON, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), LR_DEFAULTCOLOR); } return FALSE; case WM_NOTIFY: { LPNMHDR lpnm; HWND hw; d = (plugin_dlg_data *) (LONG_PTR) GetWindowLongPtr(hwnd, DWLP_USER); if (d == NULL) return FALSE; if (wParam == IDC_CFG_PLUGINS && (lpnm = (LPNMHDR) lParam) && lpnm->code == LVN_ITEMCHANGED) { LVITEM lvi; hw = GetDlgItem(hwnd, IDC_CFG_PLUGINS); #ifdef DEBUG assert(hw); #endif if (ListView_GetSelectedCount(hw) != 1) { SetDlgItemText(hwnd, IDC_CFG_DESC, L""); SetDlgItemText(hwnd, IDC_CFG_STATE, L""); SetDlgItemText(hwnd, IDC_CFG_MODULE, L""); SetDlgItemText(hwnd, IDC_CFG_VENDOR, L""); SetDlgItemText(hwnd, IDC_CFG_VERSION, L""); EnableWindow(GetDlgItem(hwnd, IDC_CFG_ENABLE), FALSE); EnableWindow(GetDlgItem(hwnd, IDC_CFG_DISABLE), FALSE); EnableWindow(GetDlgItem(hwnd, IDC_CFG_UNREGISTER), FALSE); SendDlgItemMessage(hwnd, IDC_CFG_DEPS, LB_RESETCONTENT, 0, 0); SendDlgItemMessage(hwnd, IDC_CFG_ICON, STM_SETICON, (WPARAM) d->plugin_ico, 0); d->selected = NULL; } else { int idx; plugin_data * info; idx = ListView_GetNextItem(hw, -1, LVNI_SELECTED); #ifdef DEBUG assert(idx != -1); #endif ZeroMemory(&lvi, sizeof(lvi)); lvi.iItem = idx; lvi.iSubItem = 0; lvi.mask = LVIF_PARAM; ListView_GetItem(hw, &lvi); #ifdef DEBUG assert(lvi.lParam != 0); #endif info = (plugin_data *) lvi.lParam; update_dialog_fields(hwnd, d, info); } } } return TRUE; case WM_COMMAND: { d = (plugin_dlg_data *) (LONG_PTR) GetWindowLongPtr(hwnd, DWLP_USER); if (d == NULL) return FALSE; switch (wParam) { case MAKEWPARAM(IDC_CFG_ENABLE, BN_CLICKED): if (d->selected != NULL) { khui_alert * alert = NULL; wchar_t buf[KHUI_MAXCCH_MESSAGE]; wchar_t fmt[KHUI_MAXCCH_MESSAGE]; kmm_plugin p; khui_alert_create_empty(&alert); LoadString(khm_hInstance, IDS_CFG_P_ENBCNFT, fmt, ARRAYLENGTH(fmt)); StringCbPrintf(buf, sizeof(buf), fmt, d->selected->plugin.reg.name); khui_alert_set_title(alert, buf); LoadString(khm_hInstance, IDS_CFG_P_ENBCNFM, fmt, ARRAYLENGTH(fmt)); StringCbPrintf(buf, sizeof(buf), fmt, d->selected->plugin.reg.name); khui_alert_set_message(alert, buf); khui_alert_set_severity(alert, KHERR_INFO); khui_alert_show_modal(alert); kmm_enable_plugin(d->selected->plugin.h_plugin, TRUE); khui_alert_release(alert); p = d->selected->plugin.h_plugin; kmm_hold_plugin(p); kmm_release_plugin_info_i(&d->selected->plugin); kmm_get_plugin_info_i(p, &d->selected->plugin); kmm_release_plugin(p); update_dialog_fields(hwnd, d, d->selected); } break; case MAKEWPARAM(IDC_CFG_DISABLE, BN_CLICKED): if (d->selected != NULL) { khui_alert * alert = NULL; wchar_t buf[KHUI_MAXCCH_MESSAGE]; wchar_t fmt[KHUI_MAXCCH_MESSAGE]; wchar_t depends[KHUI_MAXCCH_MESSAGE]; khm_size i; kmm_plugin p; khui_alert_create_empty(&alert); #ifdef DEBUG assert(alert); #endif if (alert == NULL) break; LoadString(khm_hInstance, IDS_CFG_P_DELCNFT, fmt, ARRAYLENGTH(fmt)); StringCbPrintf(buf, sizeof(buf), fmt, d->selected->plugin.reg.name); khui_alert_set_title(alert, buf); LoadString(khm_hInstance, IDS_CFG_P_DELCNFM, fmt, ARRAYLENGTH(fmt)); StringCbPrintf(buf, sizeof(buf), fmt, d->selected->plugin.reg.name); khui_alert_set_message(alert, buf); depends[0] = L'\0'; for (i=0; i<d->n_info; i++) { wchar_t * t; t = d->info[i]->plugin.reg.dependencies; while(t) { if (!wcscmp(t, d->selected->plugin.reg.name)) { if (depends[0]) StringCbCat(depends, sizeof(depends), L", "); StringCbCat(depends, sizeof(depends), d->info[i]->plugin.reg.name); break; } t = multi_string_next(t); } } if (depends[0]) { LoadString(khm_hInstance, IDS_CFG_P_DELCNFS, fmt, ARRAYLENGTH(fmt)); StringCbPrintf(buf, sizeof(buf), fmt, depends); khui_alert_set_suggestion(alert, buf); } else { LoadString(khm_hInstance, IDS_CFG_P_DELNDEP, buf, ARRAYLENGTH(buf)); khui_alert_set_suggestion(alert, buf); } khui_alert_add_command(alert, KHUI_PACTION_YES); khui_alert_add_command(alert, KHUI_PACTION_NO); khui_alert_set_severity(alert, KHERR_WARNING); if (KHM_SUCCEEDED(khui_alert_show_modal(alert)) && alert->response == KHUI_PACTION_YES) { kmm_enable_plugin(d->selected->plugin.h_plugin, FALSE); } khui_alert_release(alert); p = d->selected->plugin.h_plugin; kmm_hold_plugin(p); kmm_release_plugin_info_i(&d->selected->plugin); kmm_get_plugin_info_i(p, &d->selected->plugin); kmm_release_plugin(p); update_dialog_fields(hwnd, d, d->selected); } break; case MAKEWPARAM(IDC_CFG_UNREGISTER, BN_CLICKED): { khui_alert * alert = NULL; wchar_t buf[KHUI_MAXCCH_MESSAGE]; wchar_t fmt[KHUI_MAXCCH_MESSAGE]; wchar_t plist[KHUI_MAXCCH_MESSAGE]; khm_size i; if (d->selected == NULL) { #ifdef DEBUG assert(FALSE); #endif break; } khui_alert_create_empty(&alert); LoadString(khm_hInstance, IDS_CFG_P_UNRCNFT, fmt, ARRAYLENGTH(fmt)); StringCbPrintf(buf, sizeof(buf), fmt, d->selected->plugin.reg.name); khui_alert_set_title(alert, buf); LoadString(khm_hInstance, IDS_CFG_P_UNRCNFM, fmt, ARRAYLENGTH(fmt)); StringCbPrintf(buf, sizeof(buf), fmt, d->selected->plugin.reg.name); khui_alert_set_message(alert, buf); plist[0] = L'\0'; for (i=0; i < d->n_info; i++) { if (!wcscmp(d->info[i]->module.reg.name, d->selected->module.reg.name)) { if (plist[0]) StringCbCat(plist, sizeof(plist), L", "); StringCbCat(plist, sizeof(plist), d->info[i]->plugin.reg.name); } } #ifdef DEBUG /* there should have been at least one plugin */ assert(plist[0]); #endif LoadString(khm_hInstance, IDS_CFG_P_UNRCNFS, fmt, ARRAYLENGTH(fmt)); StringCbPrintf(buf, sizeof(buf), fmt, plist); khui_alert_set_suggestion(alert, buf); khui_alert_add_command(alert, KHUI_PACTION_YES); khui_alert_add_command(alert, KHUI_PACTION_NO); khui_alert_set_severity(alert, KHERR_WARNING); if (KHM_SUCCEEDED(khui_alert_show_modal(alert)) && alert->response == KHUI_PACTION_YES) { kmm_unregister_module(d->selected->module.reg.name, 0); update_dialog_fields(hwnd, d, d->selected); } } break; case MAKEWPARAM(IDC_CFG_REGISTER, BN_CLICKED): { } break; } } return TRUE; case WM_DESTROY: { khm_size i; d = (plugin_dlg_data *) (LONG_PTR) GetWindowLongPtr(hwnd, DWLP_USER); #ifdef DEBUG assert(d); #endif if (d == NULL) return TRUE; for (i=0; i<d->n_info; i++) { #ifdef DEBUG assert(d->info[i]); #endif kmm_release_plugin_info_i(&d->info[i]->plugin); kmm_release_module_info_i(&d->info[i]->module); PFREE(d->info[i]); } PFREE(d); SetWindowLongPtr(hwnd, DWLP_USER, 0); khm_set_dialog_result(hwnd, 0); } return TRUE; } return FALSE; }