Beispiel #1
0
/* called with cs_mkq_global && cs_kmq_types held */
void kmqint_free_msg_type(int t) {
    kmq_msg_type * pt;
    kmq_msg_subscription * s;

    pt = msg_types[t];

    msg_types[t] = NULL;

    if (pt == NULL)
        return;

    /* all the subscriptions attached to a message type are owned by
       the message type */
    LPOP(&pt->subs, &s);
    while(s) {
        s->magic = 0;

        PFREE(s);

        LPOP(&pt->subs, &s);
    }

    pt->completion_handler = NULL;

    LDELETE(&all_msg_types, pt);

    PFREE(pt);
}
Beispiel #2
0
/*! \internal
    \brief Get a message ref object
    \note called with cs_kmq_msg_ref held */
kmq_message_ref * kmqint_get_message_ref(void) {
    kmq_message_ref * r;

    LPOP(&kmq_msg_ref_free, &r);
    if(!r) {
        r = PMALLOC(sizeof(kmq_message_ref));
    }
    ZeroMemory(r, sizeof(kmq_message_ref));

    r->msg = NULL;
    r->recipient = NULL;

    return r;
}
Beispiel #3
0
/*! \internal
    \brief Get a message object
    \note called with ::cs_kmq_msg held */
kmq_message *
kmqint_get_message(void) {
    kmq_message * m;

    LPOP(&msg_free,&m);
    if(!m) {
        /* allocate one */
        m = PMALLOC(sizeof(kmq_message));
    }
    ZeroMemory((void*)m, sizeof(kmq_message));

    LPUSH(&msg_active, m);

    return m;
}
Beispiel #4
0
static allocation * get_allocation(void) {
    allocation * a;

    LPOP(&free_alloc, &a);
    if (!a) {
        if (idx_next_alloc == ALLOCBLOCK) {
            next_alloc = malloc(sizeof(allocation) * ALLOCBLOCK);
            assert(next_alloc);
            idx_next_alloc = 0;
        }

        a = &next_alloc[idx_next_alloc];
        idx_next_alloc++;
    }

    return a;
}
Beispiel #5
0
static kherr_event *
get_empty_event(void)
{
    kherr_event * e;

    EnterCriticalSection(&cs_error);
    if(evt_free_list) {
        LPOP(&evt_free_list, &e);
    } else {
        e = PMALLOC(sizeof(*e));
    }
    LeaveCriticalSection(&cs_error);
    ZeroMemory(e, sizeof(*e));
    e->severity = KHERR_NONE;
    e->magic = KHERR_EVENT_MAGIC;

    return e;
}
Beispiel #6
0
static kherr_context *
get_empty_context(void)
{
    kherr_context * c;

    EnterCriticalSection(&cs_error);
    if(ctx_free_list) {
        LPOP(&ctx_free_list, &c);
    } else {
        c = PMALLOC(sizeof(kherr_context));
    }

    ZeroMemory(c,sizeof(*c));
    c->severity = KHERR_NONE;
    c->flags = KHERR_CF_UNBOUND;
    c->magic = KHERR_CONTEXT_MAGIC;
    c->serial = ++ctx_serial;

    LPUSH(&ctx_root_list, c);

    LeaveCriticalSection(&cs_error);

    return c;
}
Beispiel #7
0
/*! \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);
    }
}
Beispiel #8
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();
}