Beispiel #1
0
KHMEXP khm_int32   KHMAPI
kmm_register_module(kmm_module_reg * module, khm_int32 config_flags)
{
    khm_int32 rv = KHM_ERROR_SUCCESS;
    khm_handle csp_module = NULL;
    size_t cch;
    int i;

    if((module == NULL) ||
        FAILED(StringCchLength(module->name, KMM_MAXCCH_NAME, &cch)) ||
        (module->description &&
            FAILED(StringCchLength(module->description,
                                   KMM_MAXCCH_DESC, &cch))) ||
        FAILED(StringCchLength(module->path, MAX_PATH, &cch)) ||
        (module->n_plugins > 0 && module->plugin_reg_info == NULL)) {
        return KHM_ERROR_INVALID_PARAM;
    }

#define CKRV if(KHM_FAILED(rv)) goto _exit

    rv = kmm_get_module_config(module->name, config_flags | KHM_FLAG_CREATE,
                               &csp_module);
    CKRV;

    rv = khc_write_string(csp_module, L"ImagePath", module->path);
    CKRV;

    rv = khc_write_int32(csp_module, L"Disabled", 0);
    CKRV;

    /* FileVersion and ProductVersion will be set when the module
       is loaded for the first time */

    for(i=0; i<module->n_plugins; i++) {
        rv = kmm_register_plugin(&(module->plugin_reg_info[i]), config_flags);
        CKRV;
    }

#undef CKRV
_exit:
    if(csp_module)
        khc_close_space(csp_module);

    return rv;
}
Beispiel #2
0
KHMEXP khm_int32   KHMAPI
kmm_unregister_module(wchar_t * module, khm_int32 config_flags)
{
    khm_handle csp_module = NULL;
    khm_int32 rv = KHM_ERROR_SUCCESS;

    rv = kmm_get_module_config(module, config_flags, &csp_module);

    if (KHM_FAILED(rv))
        goto _cleanup;

    rv = khc_remove_space(csp_module);

 _cleanup:
    if (csp_module)
        khc_close_space(csp_module);

    return rv;
}
Beispiel #3
0
/*! \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();
}
Beispiel #4
0
KHMEXP khm_int32   KHMAPI
kmm_register_plugin(kmm_plugin_reg * plugin, khm_int32 config_flags)
{
    khm_int32 rv = KHM_ERROR_SUCCESS;
    khm_handle csp_plugin = NULL;
    khm_handle csp_module = NULL;
    size_t cch;

    /* avoid accidently creating the module key if it doesn't exist */
    config_flags &= ~KHM_FLAG_CREATE;

    if((plugin == NULL) ||
       (plugin->dependencies &&
        KHM_FAILED(multi_string_length_cch(plugin->dependencies,
                                           KMM_MAXCCH_DEPS, &cch))) ||
       FAILED(StringCchLength(plugin->module, KMM_MAXCCH_NAME, &cch)) ||
       (plugin->description &&
        FAILED(StringCchLength(plugin->description,
                               KMM_MAXCCH_DESC, &cch))) ||
       FAILED(StringCchLength(plugin->name, KMM_MAXCCH_NAME, &cch)))
    {
        return KHM_ERROR_INVALID_PARAM;
    }

    /* note that we are retaining the length of the plugin name in
       chars in cch */
    cch ++;

#define CKRV if(KHM_FAILED(rv)) goto _exit

    rv = kmm_get_plugin_config(plugin->name,
                               config_flags | KHM_FLAG_CREATE, &csp_plugin);
    CKRV;

    /* should fail if the module key doesn't exist */
    rv = kmm_get_module_config(plugin->module, config_flags, &csp_module);
    CKRV;

    /*TODO: Make sure that the module registration is in the same
      config store as the one in which the plugin is going to be
      registered */

    rv = khc_write_string(csp_plugin, L"Module", plugin->module);
    CKRV;
    if(plugin->description) {
        rv = khc_write_string(csp_plugin, L"Description", plugin->description);
        CKRV;
    }

    if(plugin->dependencies) {
        rv = khc_write_multi_string(csp_plugin, L"Dependencies",
                                    plugin->dependencies);
        CKRV;
    }

    rv = khc_write_int32(csp_plugin, L"Type", plugin->type);
    CKRV;
    rv = khc_write_int32(csp_plugin, L"Disabled",
                         !!(plugin->flags & KMM_PLUGIN_FLAG_DISABLED));
    CKRV;

    {
        khm_size cb = 0;
        wchar_t * pl = NULL;
        size_t scb = 0;

        rv = khc_read_multi_string(csp_module, L"PluginList", NULL, &cb);
        if(rv != KHM_ERROR_TOO_LONG) {
            if (rv == KHM_ERROR_NOT_FOUND) {

                scb = cb = (cch + 1) * sizeof(wchar_t);
                pl = PMALLOC(cb);
                multi_string_init(pl, cb);
                rv = KHM_ERROR_SUCCESS;

                goto add_plugin_to_list;

            } else {
                goto _exit;
            }
        }

        cb += cch * sizeof(wchar_t);
        scb = cb;

        pl = PMALLOC(cb);

        rv = khc_read_multi_string(csp_module, L"PluginList", pl, &cb);
        if(KHM_FAILED(rv)) {
            if(pl)
                PFREE(pl);
            goto _exit;
        }

    add_plugin_to_list:

        if(!multi_string_find(pl, plugin->name, 0)) {
            multi_string_append(pl, &scb, plugin->name);
            rv = khc_write_multi_string(csp_module, L"PluginList", pl);
        }

        PFREE(pl);
        CKRV;
    }

#undef CKRV

_exit:
    if(csp_plugin)
        khc_close_space(csp_plugin);
    if(csp_module)
        khc_close_space(csp_module);

    return rv;
}
void update_dialog_fields(HWND hwnd,
                          plugin_dlg_data * d,
                          plugin_data * info) {
    wchar_t buf[256];
    UINT resid;
    wchar_t * t;
    khm_handle csp_module = NULL;

    d->selected = info;

    if (info->plugin.reg.description)
        SetDlgItemText(hwnd, IDC_CFG_DESC, info->plugin.reg.description);
    else {
        wchar_t fmt[128];

        LoadString(khm_hInstance, IDS_CFG_NODESC, fmt, ARRAYLENGTH(fmt));
        StringCbPrintf(buf, sizeof(buf), fmt, info->plugin.reg.name);
        SetDlgItemText(hwnd, IDC_CFG_DESC, buf);
    }
    
    switch(info->plugin.state) {
    case KMM_PLUGIN_STATE_FAIL_INIT:
        resid = IDS_PISTATE_FAILINIT;
        break;

    case KMM_PLUGIN_STATE_FAIL_UNKNOWN:
        resid = IDS_PISTATE_FAILUNK;
        break;

    case KMM_PLUGIN_STATE_FAIL_MAX_FAILURE:
        resid = IDS_PISTATE_FAILMAX;
        break;

    case KMM_PLUGIN_STATE_FAIL_NOT_REGISTERED:
        resid = IDS_PISTATE_FAILREG;
        break;

    case KMM_PLUGIN_STATE_FAIL_DISABLED:
        resid = IDS_PISTATE_FAILDIS;
        break;

    case KMM_PLUGIN_STATE_FAIL_LOAD:
        resid = IDS_PISTATE_FAILLOD;
        break;

    case KMM_PLUGIN_STATE_NONE:
    case KMM_PLUGIN_STATE_PLACEHOLDER:
        resid = IDS_PISTATE_PLACEHOLD;
        break;

    case KMM_PLUGIN_STATE_REG:
    case KMM_PLUGIN_STATE_PREINIT:
        resid = IDS_PISTATE_REG;
        break;

    case KMM_PLUGIN_STATE_HOLD:
        resid = IDS_PISTATE_HOLD;
        break;

    case KMM_PLUGIN_STATE_INIT:
        resid = IDS_PISTATE_INIT;
        break;

    case KMM_PLUGIN_STATE_RUNNING:
        resid = IDS_PISTATE_RUN;
        break;

    case KMM_PLUGIN_STATE_EXITED:
        resid = IDS_PISTATE_EXIT;
        break;

    default:
#ifdef DEBUG
        assert(FALSE);
#endif
        resid = IDS_PISTATE_FAILUNK;
    }

    LoadString(khm_hInstance, resid,
               buf, ARRAYLENGTH(buf));

    SetDlgItemText(hwnd, IDC_CFG_STATE, buf);

    SendDlgItemMessage(hwnd, IDC_CFG_DEPS,
                       LB_RESETCONTENT, 0, 0);

    for (t = info->plugin.reg.dependencies; t && *t;
         t = multi_string_next(t)) {
        SendDlgItemMessage(hwnd, IDC_CFG_DEPS,
                           LB_INSERTSTRING, (WPARAM) -1, (LPARAM) t);
    }

    if (info->plugin.reg.module)
        SetDlgItemText(hwnd, IDC_CFG_MODULE,
                       info->plugin.reg.module);
    else
        SetDlgItemText(hwnd, IDC_CFG_MODULE,
                       L"");

    if (info->module.reg.vendor)
        SetDlgItemText(hwnd, IDC_CFG_VENDOR,
                       info->module.reg.vendor);
    else
        SetDlgItemText(hwnd, IDC_CFG_VENDOR,
                       L"");

    StringCbPrintf(buf, sizeof(buf), L"%u.%u.%u.%u",
                   (unsigned int) info->module.product_version.major,
                   (unsigned int) info->module.product_version.minor,
                   (unsigned int) info->module.product_version.patch,
                   (unsigned int) info->module.product_version.aux);

    SetDlgItemText(hwnd, IDC_CFG_VERSION, buf);

    if (info->plugin.reg.icon) {
        SendDlgItemMessage(hwnd, IDC_CFG_ICON,
                           STM_SETICON,
                           (WPARAM) info->plugin.reg.icon,
                           0);
    } else {
        SendDlgItemMessage(hwnd, IDC_CFG_ICON,
                           STM_SETICON,
                           (WPARAM) d->plugin_ico,
                           0);
    }

    if (KHM_SUCCEEDED(kmm_get_module_config(info->module.reg.name,
                                            0, &csp_module)) &&
        (khc_value_exists(csp_module, L"ImagePath") &
         (KCONF_FLAG_MACHINE | KCONF_FLAG_USER))) {

        EnableWindow(GetDlgItem(hwnd, IDC_CFG_UNREGISTER), TRUE);
    } else {
        EnableWindow(GetDlgItem(hwnd, IDC_CFG_UNREGISTER), FALSE);
    }

    if (csp_module)
        khc_close_space(csp_module);

    if (info->plugin.flags & KMM_PLUGIN_FLAG_DISABLED) {
        EnableWindow(GetDlgItem(hwnd, IDC_CFG_ENABLE), TRUE);
        EnableWindow(GetDlgItem(hwnd, IDC_CFG_DISABLE), FALSE);
    } else {
        EnableWindow(GetDlgItem(hwnd, IDC_CFG_ENABLE), FALSE);
        EnableWindow(GetDlgItem(hwnd, IDC_CFG_DISABLE), TRUE);
    }
}