/*! \internal \brief The registrar thread. The only thing this function does is to dispatch messages to the callback routine ( kmmint_reg_cb() ) */ DWORD WINAPI kmmint_registrar(LPVOID lpParameter) { PDESCTHREAD(L"KMM Registrar", L"KMM"); tid_registrar = GetCurrentThreadId(); kmq_subscribe(KMSG_KMM, kmmint_reg_cb); kmq_subscribe(KMSG_SYSTEM, kmmint_reg_cb); SetEvent(evt_startup); while(KHM_SUCCEEDED(kmq_dispatch(INFINITE))); kmq_unsubscribe(KMSG_KMM, kmmint_reg_cb); kmq_unsubscribe(KMSG_SYSTEM, kmmint_reg_cb); ExitThread(0); }
DWORD WINAPI addr_change_thread(LPVOID dummy) { HANDLE h_waits[2]; HANDLE h_notify; OVERLAPPED overlap; DWORD ret; PDESCTHREAD(L"Address change waiter", L"App"); ZeroMemory(&overlap, sizeof(overlap)); h_notify = NULL; overlap.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); do { ret = NotifyAddrChange(&h_notify, &overlap); if (ret != ERROR_IO_PENDING) { goto _end_thread; /* some error */ } h_waits[0] = overlap.hEvent; h_waits[1] = evt_terminate; ret = WaitForMultipleObjects(2, h_waits, FALSE, INFINITE); if ( ret == WAIT_OBJECT_0 ) { Sleep(3000); /* wait for things to settle down */ kmq_post_message(KMSG_CRED, KMSG_CRED_ADDR_CHANGE, 0, 0); } else { goto _end_thread; } } while(TRUE); _end_thread: ExitThread(0); return 0; /* unreachable */ }
DWORD WINAPI kmqint_completion_thread_proc(LPVOID p) { kmq_message * m; kherr_context * ctx; PDESCTHREAD(L"Msg completion thread", L"KMQ"); EnterCriticalSection(&cs_compl); do { if (QTOP(&kmq_completion_xfer) == NULL) { LeaveCriticalSection(&cs_compl); WaitForSingleObject(compl_wx, INFINITE); EnterCriticalSection(&cs_compl); /* go through the loop again before checking the queue */ } else { QGET(&kmq_completion_xfer, &m); LeaveCriticalSection(&cs_compl); EnterCriticalSection(&cs_kmq_msg); ctx = m->err_ctx; if (ctx) kherr_push_context(ctx); kmqint_put_message(m); if (ctx) kherr_pop_context(); LeaveCriticalSection(&cs_kmq_msg); EnterCriticalSection(&cs_compl); } } while(compl_continue); LeaveCriticalSection(&cs_compl); ExitThread(0); }
/*! \internal \brief Manages a plugin message thread. Each plugin gets its own plugin thread which is used to dispatch messages to the plugin. This acts as the thread function for the plugin thread.*/ DWORD WINAPI kmmint_plugin_broker(LPVOID lpParameter) { DWORD rv = 0; kmm_plugin_i * p = (kmm_plugin_i *) lpParameter; PDESCTHREAD(p->p.name, L"KMM"); _begin_task(0); _report_mr1(KHERR_NONE, MSG_PB_START, _cstr(p->p.name)); _describe(); TlsSetValue(tls_kmm, (LPVOID) p); kmm_hold_plugin(kmm_handle_from_plugin(p)); p->tid_thread = GetCurrentThreadId(); if (IsBadCodePtr(p->p.msg_proc)) { _report_mr0(KHERR_WARNING, MSG_PB_INVALID_CODE_PTR); rv = KHM_ERROR_INVALID_PARAM; } else { rv = (*p->p.msg_proc)(KMSG_SYSTEM, KMSG_SYSTEM_INIT, 0, (void *) &(p->p)); _report_mr1(KHERR_INFO, MSG_PB_INIT_RV, _int32(rv)); } /* if it fails to initialize, we exit the plugin */ if(KHM_FAILED(rv)) { kherr_report(KHERR_ERROR, (wchar_t *) MSG_PB_INIT_FAIL_S, (wchar_t *) KHERR_FACILITY, NULL, (wchar_t *) MSG_PB_INIT_FAIL, (wchar_t *) MSG_PB_INIT_FAIL_G, KHERR_FACILITY_ID, KHERR_SUGGEST_NONE, _cstr(p->p.name), _cstr(p->p.description), _cstr(p->module->path), _cstr(p->module->support), KHERR_RF_MSG_SHORT_DESC | KHERR_RF_MSG_LONG_DESC | KHERR_RF_MSG_SUGGEST #ifdef _WIN32 ,KHERR_HMODULE #endif ); _resolve(); /* exit the plugin first. Otherwise it may not uninitialize correctly */ (*p->p.msg_proc)(KMSG_SYSTEM, KMSG_SYSTEM_EXIT, 0, (void *) &(p->p)); kmmint_remove_from_plugin_queue(p); rv = 1; _end_task(); p->state = KMM_PLUGIN_STATE_FAIL_INIT; goto _exit; } /* subscribe to default message classes by plugin type */ if(p->p.type == KHM_PITYPE_CRED) { kmq_subscribe(KMSG_SYSTEM, p->p.msg_proc); kmq_subscribe(KMSG_KCDB, p->p.msg_proc); kmq_subscribe(KMSG_CRED, p->p.msg_proc); } else if(p->p.type == KHM_PITYPE_IDENT) { khm_handle h = NULL; kmq_subscribe(KMSG_SYSTEM, p->p.msg_proc); kmq_subscribe(KMSG_KCDB, p->p.msg_proc); kmq_create_subscription(p->p.msg_proc, &h); kcdb_identity_set_provider(h); /* kcdb deletes the subscription when it's done with it */ } else if(p->p.type == KHM_PITYPE_CONFIG) { /*TODO: subscribe to configuration provider messages here */ } p->state = KMM_PLUGIN_STATE_RUNNING; _report_mr0(KHERR_INFO, MSG_PB_INIT_DONE); _end_task(); /* if there were any plugins that were waiting for this one to start, we should start them too */ EnterCriticalSection(&cs_kmm); do { kmm_plugin_i * pd; int i; for(i=0; i < p->n_dependants; i++) { pd = p->dependants[i]; pd->n_unresolved--; if(pd->n_unresolved == 0) { kmmint_add_to_plugin_queue(pd); kmm_hold_plugin(kmm_handle_from_plugin(pd)); kmq_post_message(KMSG_KMM, KMSG_KMM_I_REG, KMM_REG_INIT_PLUGIN, (void *) pd); } } } while(FALSE); LeaveCriticalSection(&cs_kmm); kmmint_remove_from_plugin_queue(p); /* main message loop */ while(KHM_SUCCEEDED(kmq_dispatch(INFINITE))); /* unsubscribe from default message classes by plugin type */ if(p->p.type == KHM_PITYPE_CRED) { kmq_unsubscribe(KMSG_SYSTEM, p->p.msg_proc); kmq_unsubscribe(KMSG_KCDB, p->p.msg_proc); kmq_unsubscribe(KMSG_CRED, p->p.msg_proc); } else if (p->p.type == KHM_PITYPE_IDENT) { kmq_unsubscribe(KMSG_KCDB, p->p.msg_proc); kmq_unsubscribe(KMSG_SYSTEM, p->p.msg_proc); kcdb_identity_set_provider(NULL); } else if(p->p.type == KHM_PITYPE_CONFIG) { /*TODO: unsubscribe from configuration provider messages here */ } p->p.msg_proc(KMSG_SYSTEM, KMSG_SYSTEM_EXIT, 0, (void *) &(p->p)); _exit: if (p->state >= 0) p->state = KMM_PLUGIN_STATE_EXITED; /* the following call will automatically release the plugin */ kmq_post_message(KMSG_KMM, KMSG_KMM_I_REG, KMM_REG_EXIT_PLUGIN, (void *) p); TlsSetValue(tls_kmm, (LPVOID) 0); ExitThread(rv); /* not reached */ return rv; }