Exemple #1
0
/* 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);
}
Exemple #2
0
KHMEXP khm_int32   KHMAPI
kmm_provide_plugin(kmm_module module, kmm_plugin_reg * plugin)
{
    kmm_module_i * m;
    kmm_plugin_i * p;
    size_t cb_name = 0;
    size_t cb_desc = 0;
    size_t cb_dep = 0;

    m = kmm_module_from_handle(module);

    /* can only called when handing init_module() */
    if(m->state != KMM_MODULE_STATE_INIT)
        return KHM_ERROR_INVALID_OPERATION;

    if(!plugin ||
       FAILED(StringCbLength(plugin->name, KMM_MAXCB_NAME - sizeof(wchar_t),
                             &cb_name)) ||
       (plugin->description &&
        FAILED(StringCbLength(plugin->description,
                              KMM_MAXCB_DESC - sizeof(wchar_t),
                              &cb_desc))) ||
       (plugin->dependencies &&
        KHM_FAILED(multi_string_length_cb(plugin->dependencies,
                                          KMM_MAXCB_DEPS, &cb_dep)))) {
        return KHM_ERROR_INVALID_PARAM;
    }

    cb_name += sizeof(wchar_t);
    cb_desc += sizeof(wchar_t);

    p = kmmint_get_plugin_i(plugin->name);

    /* released below or in kmmint_init_module() */
    kmm_hold_plugin(kmm_handle_from_plugin(p));

    if(p->state != KMM_PLUGIN_STATE_NONE &&
        p->state != KMM_PLUGIN_STATE_PLACEHOLDER)
    {
        kmm_release_plugin(kmm_handle_from_plugin(p));
        return KHM_ERROR_DUPLICATE;
    }

    /* released when the plugin quits */
    kmm_hold_module(module);

    p->module = m;
    p->p.flags = plugin->flags;
    p->p.msg_proc = plugin->msg_proc;
    p->p.type = plugin->type;

    if(plugin->description) {
        p->p.description = PMALLOC(cb_desc);
        StringCbCopy(p->p.description, cb_desc, plugin->description);
    } else
        p->p.description = NULL;

    if(plugin->dependencies) {
        p->p.dependencies = PMALLOC(cb_dep);
        multi_string_copy_cb(p->p.dependencies, cb_dep, plugin->dependencies);
    } else
        p->p.dependencies = NULL;

    p->p.module = p->module->name;

    p->p.icon = plugin->icon;

    p->state = KMM_PLUGIN_STATE_REG;

    kmmint_delist_plugin(p);
    EnterCriticalSection(&cs_kmm);
    LPUSH(&(m->plugins), p);
    p->flags |= KMM_PLUGIN_FLAG_IN_MODLIST;
    LeaveCriticalSection(&cs_kmm);

    /* leave the plugin held because it is in the module's plugin list */
    return KHM_ERROR_SUCCESS;
}
Exemple #3
0
/*! \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
}