#include<kmminternal.h>
kmm_plugin_i *
kmmint_get_plugin_i(wchar_t * name)
{
kmm_plugin_i * p;
size_t cb;
if(FAILED(StringCbLength(name, KMM_MAXCB_NAME, &cb)))
return NULL;
cb += sizeof(wchar_t);
EnterCriticalSection(&cs_kmm);
p = (kmm_plugin_i *) hash_lookup(hash_plugins, (void *) name);
if(p == NULL) {
p = PMALLOC(sizeof(kmm_plugin_i));
ZeroMemory(p, sizeof(kmm_plugin_i));
p->magic = KMM_PLUGIN_MAGIC;
p->p.name = PMALLOC(cb);
StringCbCopy(p->p.name, cb, name);
p->state = KMM_PLUGIN_STATE_NONE;
hash_add(hash_plugins, (void *) p->p.name, (void *) p);
kmmint_list_plugin(p);
}
LeaveCriticalSection(&cs_kmm);
return p;
}
kmm_plugin_i *
kmmint_find_plugin_i(wchar_t * name)
{
kmm_plugin_i * p;
size_t cb;
if(FAILED(StringCbLength(name, KMM_MAXCB_NAME, &cb)))
return NULL;
EnterCriticalSection(&cs_kmm);
p = (kmm_plugin_i *) hash_lookup(hash_plugins, (void *) name);
LeaveCriticalSection(&cs_kmm);
return p;
}
void
kmmint_list_plugin(kmm_plugin_i * p)
{
EnterCriticalSection(&cs_kmm);
if((p->flags & KMM_PLUGIN_FLAG_IN_MODLIST) ||
(p->flags & KMM_PLUGIN_FLAG_IN_LIST))
{
RaiseException(2, EXCEPTION_NONCONTINUABLE, 0, NULL);
}
p->flags |= KMM_PLUGIN_FLAG_IN_LIST;
LPUSH(&kmm_listed_plugins, p);
LeaveCriticalSection(&cs_kmm);
}
void
kmmint_delist_plugin(kmm_plugin_i * p)
{
EnterCriticalSection(&cs_kmm);
if(p->flags & KMM_PLUGIN_FLAG_IN_LIST) {
p->flags &= ~KMM_PLUGIN_FLAG_IN_LIST;
LDELETE(&kmm_listed_plugins, p);
}
if(p->flags & KMM_PLUGIN_FLAG_IN_MODLIST) {
p->flags &= ~KMM_PLUGIN_FLAG_IN_MODLIST;
LDELETE(&(p->module->plugins), p);
}
LeaveCriticalSection(&cs_kmm);
}
KHMEXP khm_int32 KHMAPI
kmm_hold_plugin(kmm_plugin p)
{
kmm_plugin_i * pi;
if(!kmm_is_plugin(p))
return KHM_ERROR_INVALID_PARAM;
EnterCriticalSection(&cs_kmm);
pi = kmm_plugin_from_handle(p);
pi->refcount++;
LeaveCriticalSection(&cs_kmm);
return KHM_ERROR_SUCCESS;
}
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_enable_plugin(kmm_plugin p, khm_boolean enable) {
kmm_plugin_i * pi;
khm_int32 rv = KHM_ERROR_NOT_FOUND;
khm_handle csp_plugin = NULL;
EnterCriticalSection(&cs_kmm);
if (!kmm_is_plugin(p)) {
rv = KHM_ERROR_INVALID_PARAM;
goto _cleanup;
}
pi = kmm_plugin_from_handle(p);
if (KHM_FAILED(rv = kmm_get_plugin_config(pi->p.name, 0, &csp_plugin))) {
goto _cleanup;
}
if (KHM_FAILED(rv = khc_write_int32(csp_plugin, L"Disabled", !enable))) {
goto _cleanup;
}
rv = KHM_ERROR_SUCCESS;
_cleanup:
LeaveCriticalSection(&cs_kmm);
if (csp_plugin)
khc_close_space(csp_plugin);
return rv;
}
KHMEXP khm_int32 KHMAPI
kmm_get_plugin_info_i(kmm_plugin p, kmm_plugin_info * info) {
khm_int32 rv = KHM_ERROR_SUCCESS;
kmm_plugin_i * pi;
khm_handle csp_plugin;
if (!info)
return KHM_ERROR_INVALID_PARAM;
EnterCriticalSection(&cs_kmm);
if (!kmm_is_plugin(p)) {
rv = KHM_ERROR_INVALID_PARAM;
goto _cleanup;
}
pi = kmm_plugin_from_handle(p);
ZeroMemory(info, sizeof(*info));
info->reg = pi->p;
info->reg.msg_proc = NULL;
if (KHM_FAILED(kmm_get_plugin_config(pi->p.name, KHM_PERM_READ,
&csp_plugin))) {
info->failure_count = 0;
*((khm_int64 *)&info->failure_time) = 0;
info->failure_reason = 0;
} else {
if (KHM_FAILED(khc_read_int32(csp_plugin, L"FailureCount",
&info->failure_count)))
info->failure_count = 0;
if (KHM_FAILED(khc_read_int64(csp_plugin, L"FailureTime",
(khm_int64 *) &info->failure_time)))
*((khm_int64 *) &info->failure_time) = 0;
if (KHM_FAILED(khc_read_int32(csp_plugin, L"FailureReason",
&info->failure_reason)))
info->failure_reason = 0;
khc_close_space(csp_plugin);
}
info->state = pi->state;
kmm_hold_plugin(p);
info->h_plugin = p;
info->flags = (pi->flags & KMM_PLUGIN_FLAG_DISABLED);
_cleanup:
LeaveCriticalSection(&cs_kmm);
return rv;
}
KHMEXP khm_int32 KHMAPI
kmm_release_plugin_info_i(kmm_plugin_info * info) {
khm_int32 rv;
if (!info || !info->h_plugin)
return KHM_ERROR_INVALID_PARAM;
rv = kmm_release_plugin(info->h_plugin);
ZeroMemory(info, sizeof(info));
return rv;
}
KHMEXP khm_int32 KHMAPI
kmm_get_next_plugin(kmm_plugin p, kmm_plugin * p_next) {
khm_int32 rv = KHM_ERROR_SUCCESS;
kmm_plugin_i * pi;
kmm_plugin_i * pi_next = NULL;
kmm_module_i * m;
EnterCriticalSection(&cs_kmm);
if (p == NULL) {
if (kmm_listed_plugins)
pi_next = kmm_listed_plugins;
else {
for (m = kmm_all_modules; m; m = LNEXT(m)) {
if (m->plugins) {
pi_next = m->plugins;
break;
}
}
}
} else if (kmm_is_plugin(p)) {
pi = kmm_plugin_from_handle(p);
pi_next = LNEXT(pi);
if (!pi_next) {
if (pi->module) {
m = LNEXT(pi->module);
} else {
m = kmm_all_modules;
}
for(; m; m = LNEXT(m)) {
if (m->plugins) {
pi_next = m->plugins;
break;
}
}
}
}
if (pi_next) {
*p_next = kmm_handle_from_plugin(pi_next);
kmm_hold_plugin(*p_next);
} else {
*p_next = NULL;
rv = KHM_ERROR_NOT_FOUND;
}
LeaveCriticalSection(&cs_kmm);
return rv;
}
KHMEXP khm_int32 KHMAPI
kmm_release_plugin(kmm_plugin p)
{
kmm_plugin_i * pi;
if(!kmm_is_plugin(p))
return KHM_ERROR_INVALID_PARAM;
EnterCriticalSection(&cs_kmm);
pi = kmm_plugin_from_handle(p);
pi->refcount--;
if(pi->refcount == 0) {
kmmint_free_plugin(pi);
}
LeaveCriticalSection(&cs_kmm);
return KHM_ERROR_SUCCESS;
}
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);
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);
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;
}
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);
return KHM_ERROR_SUCCESS;
}