Ejemplo n.º 1
0
/* Note: This callback runs under the UI thread */
INT_PTR
handle_wm_initdialog(HWND hwnd, WPARAM wParam, LPARAM lParam) {
    khui_new_creds * nc = NULL;
    khui_new_creds_by_type * nct = NULL;
    struct nc_dialog_data * d = NULL;

    nc = (khui_new_creds *) lParam;
    khui_cw_find_type(nc, credtype_id, &nct);

    assert(nct);

    d = malloc(sizeof(*d));
    ZeroMemory(d, sizeof(*d));

    d->nc = nc;
    d->nct = nct;

#pragma warning(push)
#pragma warning(disable: 4244)
    SetWindowLongPtr(hwnd, DWLP_USER, (LPARAM) d);
#pragma warning(pop)

    nct->aux = (LPARAM) d;      /* we can use the auxiliary field to
                                   hold a pointer to d */

    /* TODO: Perform any additional initialization here */

    return FALSE;
}
Ejemplo n.º 2
0
/* this is called by khm_cred_dispatch_process_message and the
   kmsg_cred_completion to initiate and continue checked broadcasts of
   KMSG_CRED_DIALOG_PROCESS messages.
   
   Returns TRUE if more KMSG_CRED_DIALOG_PROCESS messages were
   posted. */
BOOL khm_cred_dispatch_process_level(khui_new_creds *nc)
{
    khm_size i,j;
    khm_handle subs[KHUI_MAX_NCTYPES];
    int n_subs = 0;
    BOOL cont = FALSE;
    khui_new_creds_by_type *t, *d;

    /* at each level, we dispatch a wave of notifications to plug-ins
       who's dependencies are all satisfied */
    EnterCriticalSection(&nc->cs);

    /* if any types have already completed, we mark them are processed
       and skip them */
    for (i=0; i < nc->n_types; i++) {
        t = nc->types[i];
        if(t->flags & KHUI_NC_RESPONSE_COMPLETED)
            t->flags |= KHUI_NCT_FLAG_PROCESSED;
    }

    for(i=0; i<nc->n_types; i++) {
        t = nc->types[i];

        if((t->flags & KHUI_NCT_FLAG_PROCESSED) ||
           (t->flags & KHUI_NC_RESPONSE_COMPLETED))
            continue;

        for(j=0; j<t->n_type_deps; j++) {
            if(KHM_FAILED(khui_cw_find_type(nc, t->type_deps[j], &d)))
                break;

            if(!(d->flags & KHUI_NC_RESPONSE_COMPLETED))
                break;
        }

        if(j<t->n_type_deps) /* there are unmet dependencies */
            continue;

        /* all dependencies for this type have been met. */
        subs[n_subs++] = kcdb_credtype_get_sub(t->type);
        t->flags |= KHUI_NCT_FLAG_PROCESSED;
        cont = TRUE;
    }

    LeaveCriticalSection(&nc->cs);

    /* the reason why we are posting messages in batches is because
       when the message has completed we know that all the types that
       have the KHUI_NCT_FLAG_PROCESSED set have completed processing.
       Otherwise we have to individually track each message and update
       the type */
    if(n_subs > 0)
        kmq_post_subs_msg(subs, n_subs, KMSG_CRED, KMSG_CRED_PROCESS, 0,
                          (void *) nc);

    return cont;
}
Ejemplo n.º 3
0
/* Note: This callback runs under the UI thread */
INT_PTR
handle_wm_initdialog(HWND hwnd, WPARAM wParam, LPARAM lParam) {
    khui_new_creds * nc = NULL;
    struct nc_dialog_data * d = NULL;

    nc = (khui_new_creds *) lParam;
    khui_cw_find_type(nc, credtype_id, (khui_new_creds_by_type **) &d);

    assert(d);

#pragma warning(push)
#pragma warning(disable: 4244)
    SetWindowLongPtr(hwnd, DWLP_USER, (LPARAM) d);
#pragma warning(pop)

    /* TODO: Perform any additional initialization here */

    return FALSE;
}
Ejemplo n.º 4
0
/* Handler for KMSG_CRED_END */
khm_int32
handle_kmsg_cred_end(khui_new_creds * nc) {

    struct nc_dialog_data * d;

    /* TODO: Perform any additional uninitialization as needed. */

    khui_cw_find_type(nc, credtype_id, (khui_new_creds_by_type **) &d);

    if (d) {

        khui_cw_del_type(nc, credtype_id);

        if (d->nct.name)
            free(d->nct.name);

        free(d);
    }

    return KHM_ERROR_SUCCESS;
}
Ejemplo n.º 5
0
/* Handler for KMSG_CRED_END */
khm_int32
handle_kmsg_cred_end(khui_new_creds * nc) {

    khui_new_creds_by_type * nct = NULL;

    /* TODO: Perform any additional uninitialization as needed. */

    khui_cw_find_type(nc, credtype_id, &nct);

    if (nct) {

        khui_cw_del_type(nc, credtype_id);

        if (nct->name)
            free(nct->name);
        if (nct->credtext)
            free(nct->credtext);

        free(nct);

    }

    return KHM_ERROR_SUCCESS;
}
Ejemplo n.º 6
0
khm_int32
krb4_msg_newcred(khm_int32 msg_type, khm_int32 msg_subtype,
                 khm_ui_4 uparam, void * vparam) {

    switch(msg_subtype) {
    case KMSG_CRED_NEW_CREDS:
        {
            khui_new_creds * nc;
            khui_new_creds_by_type * nct;
            khm_size cbsize;
            wchar_t wbuf[256];

            nc = (khui_new_creds *) vparam;

            nct = PMALLOC(sizeof(*nct));
#ifdef DEBUG
            assert(nct);
#endif
            ZeroMemory(nct, sizeof(*nct));

            nct->type = credtype_id_krb4;
            nct->ordinal = 3;
            LoadString(hResModule, IDS_NC_K4_SHORT,
                       wbuf, ARRAYLENGTH(wbuf));
            StringCbLength(wbuf, sizeof(wbuf), &cbsize);
            cbsize += sizeof(wchar_t);

            nct->name = PMALLOC(cbsize);
            StringCbCopy(nct->name, cbsize, wbuf);

            nct->type_deps[nct->n_type_deps++] = credtype_id_krb5;

            nct->h_module = hResModule;
            nct->dlg_proc = k4_nc_dlg_proc;
            nct->dlg_template = MAKEINTRESOURCE(IDD_NC_KRB4);

            khui_cw_add_type(nc, nct);
        }
        break;

    case KMSG_CRED_RENEW_CREDS:
        {
            khui_new_creds * nc;
            khui_new_creds_by_type * nct;
            khm_size cbsize;
            wchar_t wbuf[256];
            khui_action_context * pctx = NULL;

            nc = (khui_new_creds *) vparam;
            pctx = khui_cw_get_ctx(nc);
            if (!pctx->identity)
                break;

            nct = PMALLOC(sizeof(*nct));
#ifdef DEBUG
            assert(nct);
#endif

            ZeroMemory(nct, sizeof(*nct));

            nct->type = credtype_id_krb4;
            nct->ordinal = 3;
            LoadString(hResModule, IDS_NC_K4_SHORT,
                       wbuf, ARRAYLENGTH(wbuf));
            StringCbLength(wbuf, sizeof(wbuf), &cbsize);
            cbsize += sizeof(wchar_t);

            nct->name = PMALLOC(cbsize);
            StringCbCopy(nct->name, cbsize, wbuf);

            nct->type_deps[nct->n_type_deps++] = credtype_id_krb5;

            khui_cw_add_type(nc, nct);
        }
        break;

    case KMSG_CRED_DIALOG_SETUP:
        break;

    case KMSG_CRED_PROCESS:
        {
            khui_new_creds * nc;
            khui_new_creds_by_type * nct = NULL;
            khm_handle ident = NULL;
            khui_action_context * pctx = NULL;
            k4_dlg_data * d = NULL;
            long code = 0;
            wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
            khm_size cb;
            khm_int32 subtype;

            nc = (khui_new_creds *) vparam;
            if (KHM_FAILED(khui_cw_find_type(nc, credtype_id_krb4, &nct)))
                break;

            subtype = khui_cw_get_subtype(nc);
            if (subtype == KMSG_CRED_NEW_CREDS ||
                subtype == KMSG_CRED_RENEW_CREDS) {
                khm_int32 method;

                if (subtype == KMSG_CRED_NEW_CREDS) {

                    d = (k4_dlg_data *) nct->aux;

                    if (KHM_FAILED(khui_cw_get_primary_id(nc, &ident)))
                        break;

                    if (!d ||
                        khui_cw_get_result(nc) != KHUI_NC_RESULT_PROCESS) {
                        khui_cw_set_response(nc, credtype_id_krb4,
                                             KHUI_NC_RESPONSE_SUCCESS |
                                             KHUI_NC_RESPONSE_EXIT);
                        kcdb_identity_release(ident);
                        break;
                    }

                    if (!d->k4_enabled) {
                        k4_write_identity_data(d);
                        khui_cw_set_response(nc, credtype_id_krb4,
                                             KHUI_NC_RESPONSE_SUCCESS |
                                             KHUI_NC_RESPONSE_EXIT);
                        kcdb_identity_release(ident);
                        break;
                    }

                    method = d->method;

                    cb = sizeof(idname);
                    kcdb_identity_get_name(ident, idname, &cb);
                    _begin_task(0);
                    _report_sr0(KHERR_NONE, IDS_MSG_K4NEW);
                    _resolve();
                    _describe();

                } else if (subtype == KMSG_CRED_RENEW_CREDS) {

                    pctx = khui_cw_get_ctx(nc);

                    if ((pctx->scope == KHUI_SCOPE_IDENT &&
                         pctx->identity != NULL) ||

                        (pctx->scope == KHUI_SCOPE_CREDTYPE &&
                         pctx->cred_type == credtype_id_krb4 &&
                         pctx->identity != NULL) ||

                        (pctx->scope == KHUI_SCOPE_CRED &&
                         pctx->cred_type == credtype_id_krb4 &&
                         pctx->identity != NULL &&
                         pctx->cred != NULL)) {

                        ident = pctx->identity;
                        kcdb_identity_hold(ident);

                        if (!k4_should_identity_get_k4(ident)) {

                            _reportf(L"Kerberos 4 is not enabled for this identity.  Skipping");

                            khui_cw_set_response(nc, credtype_id_krb4,
                                                 KHUI_NC_RESPONSE_FAILED |
                                                 KHUI_NC_RESPONSE_EXIT);
                            kcdb_identity_release(ident);
                            break;
                        }

                    } else {

                        _reportf(L"Kerberos 4 is not within renewal scope. Skipping");

                        khui_cw_set_response(nc, credtype_id_krb4,
                                             KHUI_NC_RESPONSE_FAILED |
                                             KHUI_NC_RESPONSE_EXIT);
                        break;
                    }

                    method = K4_METHOD_K524; /* only k524 is supported
                                                for renewals */

                    _begin_task(0);
                    cb = sizeof(idname);
                    kcdb_identity_get_name(ident, idname, &cb);
                    _report_sr0(KHERR_NONE, IDS_MSG_K4RENEW);
                    _resolve();
                    _describe();
                } else {
                    assert(FALSE);
                    break;
                }

                _progress(0,1);

                if ((method == K4_METHOD_AUTO ||
                     method == K4_METHOD_K524) &&
                    khui_cw_type_succeeded(nc, credtype_id_krb5)) {

                    khm_handle tgt;
                    FILETIME ft_prev;
                    FILETIME ft_new;
                    khm_size cb;

                    _report_cs0(KHERR_INFO, L"Trying K524...");

                    tgt = khm_krb4_find_tgt(NULL, ident);
                    _progress(1,3);

                    if (tgt) {
                        cb = sizeof(ft_prev);
                        if (KHM_FAILED(kcdb_cred_get_attr(tgt,
                                                          KCDB_ATTR_EXPIRE,
                                                          NULL,
                                                          &ft_prev,
                                                          &cb)))
                            ZeroMemory(&ft_prev, sizeof(ft_prev));
                        kcdb_cred_release(tgt);
                    }

                    code = khm_convert524(ident);
                    _progress(2,3);

                    _reportf(L"khm_convert524 returns code %d", code);

                    if (code == 0) {
                        khui_cw_set_response(nc, credtype_id_krb4,
                                             KHUI_NC_RESPONSE_SUCCESS |
                                             KHUI_NC_RESPONSE_EXIT);

                        if (subtype == KMSG_CRED_NEW_CREDS) {
                            assert(d != NULL);

                            k4_write_identity_data(d);

                        } else if (subtype == KMSG_CRED_RENEW_CREDS &&
                                   (pctx->scope == KHUI_SCOPE_CREDTYPE ||
                                    pctx->scope == KHUI_SCOPE_CRED)) {

                            khm_krb4_list_tickets();

                            tgt = khm_krb4_find_tgt(NULL, ident);

                            if (tgt) {
                                cb = sizeof(ft_new);
                                ZeroMemory(&ft_new, sizeof(ft_new));

                                kcdb_cred_get_attr(tgt, KCDB_ATTR_EXPIRE,
                                                   NULL, &ft_new, &cb);

                                kcdb_cred_release(tgt);
                            }

                            if (!tgt ||
                                CompareFileTime(&ft_new, &ft_prev) <= 0) {
                                /* The new TGT wasn't much of an
                                   improvement over what we already
                                   had.  We should go out and try to
                                   renew the identity now. */

                                khui_action_context ctx;

                                _reportf(L"Renewal of Krb4 creds failed to get a longer TGT.  Triggering identity renewal");

                                khui_context_create(&ctx,
                                                    KHUI_SCOPE_IDENT,
                                                    pctx->identity,
                                                    KCDB_CREDTYPE_INVALID,
                                                    NULL);
                                khui_action_trigger(KHUI_ACTION_RENEW_CRED,
                                                    &ctx);

                                khui_context_release(&ctx);
                            }
                        }

                        _progress(1,1);

                        _end_task();
                        if (ident)
                            kcdb_identity_release(ident);
                        break;

                    } else if (method == K4_METHOD_K524) {
                        khui_cw_set_response(nc, credtype_id_krb4,
                                             KHUI_NC_RESPONSE_FAILED |
                                             KHUI_NC_RESPONSE_EXIT);

			if (subtype == KMSG_CRED_RENEW_CREDS &&
			    (pctx->scope == KHUI_SCOPE_CREDTYPE ||
			     pctx->scope == KHUI_SCOPE_CRED)) {
			    /* We were trying to get a new Krb4 TGT
			       for this identity.  Sometimes this
			       fails because of restrictions placed on
			       K524d regarding the lifetime of the
			       issued K4 TGT.  In this case, we
			       trigger a renewal of the identity in
			       the hope that the new K5 TGT will allow
			       us to successfully get a new K4 TGT
			       next time over using the new K5 TGT. */

			    khui_action_context ctx;

                            _reportf(L"Renewal of Krb4 creds failed using k524.  Triggerring identity renewal.");

			    khui_context_create(&ctx,
						KHUI_SCOPE_IDENT,
						pctx->identity,
						KCDB_CREDTYPE_INVALID,
						NULL);

			    khui_action_trigger(KHUI_ACTION_RENEW_CRED,
						&ctx);

			    khui_context_release(&ctx);
			}

                        _progress(1,1);
                        _end_task();

                        if (ident)
                            kcdb_identity_release(ident);
                        break;

                    }
                }

                /* only supported for new credentials */
                if (method == K4_METHOD_AUTO ||
                    method == K4_METHOD_PASSWORD) {

                    khm_size n_prompts = 0;
                    khm_size idx;
                    khm_size cb;
                    wchar_t wpwd[KHUI_MAXCCH_PROMPT_VALUE];
                    char pwd[KHUI_MAXCCH_PROMPT_VALUE];
                    wchar_t widname[KCDB_IDENT_MAXCCH_NAME];
                    char idname[KCDB_IDENT_MAXCCH_NAME];

                    char * aname = NULL;
                    char * inst = NULL;
                    char * realm = NULL;

                    assert(subtype == KMSG_CRED_NEW_CREDS);

                    _report_cs0(KHERR_INFO, L"Trying password ...");

                    code = TRUE; /* just has to be non-zero */

                    khui_cw_get_prompt_count(nc, &n_prompts);

                    if (n_prompts == 0)
                        goto _skip_pwd;

                    for (idx = 0; idx < n_prompts; idx++) {
                        khui_new_creds_prompt * p;

                        if (KHM_FAILED(khui_cw_get_prompt(nc, idx, &p)))
                            continue;

                        if (p->type == KHUI_NCPROMPT_TYPE_PASSWORD)
                            break;
                    }

                    if (idx >= n_prompts) {
                        _reportf(L"Password prompt not found");
                        goto _skip_pwd;
                    }

                    khui_cw_sync_prompt_values(nc);

                    cb = sizeof(wpwd);
                    if (KHM_FAILED(khui_cw_get_prompt_value(nc, idx,
                                                            wpwd,
                                                            &cb))) {
                        _reportf(L"Failed to obtain password value");
                        goto _skip_pwd;
                    }

                    UnicodeStrToAnsi(pwd, sizeof(pwd), wpwd);

                    cb = sizeof(widname);
                    kcdb_identity_get_name(ident,
                                           widname,
                                           &cb);

                    UnicodeStrToAnsi(idname, sizeof(idname), widname);

                    {
                        char * atsign;

                        atsign = strchr(idname, '@');
                        if (atsign == NULL) {
                            _reportf(L"Identity name does not contain an '@'");
                            goto _skip_pwd;
                        }

                        *atsign++ = 0;

                        realm = atsign;
                    }

                    {
                        char * slash;

                        slash = strchr(idname, '/');
                        if (slash != NULL) {
                            *slash++ = 0;
                            inst = slash;
                        } else {
                            inst = "";
                        }
                    }

                    aname = idname;

                    code = khm_krb4_kinit(aname, inst, realm,
                                          (long) d->lifetime, pwd);

                    _progress(2,3);

                    _reportf(L"khm_krb4_kinit returns code %d", code);

                _skip_pwd:

                    if (code) {
                        khui_cw_set_response(nc, credtype_id_krb4,
                                             KHUI_NC_RESPONSE_EXIT |
                                             KHUI_NC_RESPONSE_FAILED);

                    } else {
                        khui_cw_set_response(nc, credtype_id_krb4,
                                             KHUI_NC_RESPONSE_EXIT |
                                             KHUI_NC_RESPONSE_SUCCESS);

                        if (subtype == KMSG_CRED_NEW_CREDS) {

                            assert(d != NULL);
                            k4_write_identity_data(d);

                        }
                    }
                }

                _progress(1,1);

                _end_task();
            }

            if (ident)
                kcdb_identity_release(ident);
        }
        break;

    case KMSG_CRED_END:
        {
            khui_new_creds * nc;
            khui_new_creds_by_type * nct = NULL;

            nc = (khui_new_creds *) vparam;
            if (KHM_FAILED(khui_cw_find_type(nc, credtype_id_krb4, &nct)))
                break;

            khui_cw_del_type(nc, credtype_id_krb4);

            if (nct->name)
                PFREE(nct->name);

            if (nct->credtext)
                PFREE(nct->credtext);

            PFREE(nct);
        }
        break;
    }

    return KHM_ERROR_SUCCESS;
}
Ejemplo n.º 7
0
INT_PTR CALLBACK k4_nc_dlg_proc(HWND hwnd,
                                UINT uMsg,
                                WPARAM wParam,
                                LPARAM lParam) {

    k4_dlg_data * d;

    switch(uMsg) {
    case WM_INITDIALOG:
        {
            d = PMALLOC(sizeof(*d));
            ZeroMemory(d, sizeof(*d));

            d->nc = (khui_new_creds *) lParam;
            khui_cw_find_type(d->nc, credtype_id_krb4, &d->nct);

#pragma warning(push)
#pragma warning(disable: 4244)
            SetWindowLongPtr(hwnd, DWLP_USER, (LPARAM) d);
#pragma warning(pop)

            d->nct->aux = (LPARAM) d;
            d->hwnd = hwnd;

            d->k4_enabled = TRUE;
            d->method = K4_METHOD_AUTO;

            k4_update_display(d, TRUE);
        }
        break;

    case WM_COMMAND:
        {
            if (HIWORD(wParam) == BN_CLICKED) {
                d = (k4_dlg_data *) (LONG_PTR)
                    GetWindowLongPtr(hwnd, DWLP_USER);

                if (d == NULL)
                    break;

                k4_update_data(d);

                if (LOWORD(wParam) == IDC_NCK4_OBTAIN) {
                    k4_update_display(d, TRUE);
                }

                return TRUE;
            }
        }
        break;

    case KHUI_WM_NC_NOTIFY:
        {
            d = (k4_dlg_data *) (LONG_PTR)
                GetWindowLongPtr(hwnd, DWLP_USER);

            if (d == NULL)
                break;

            k4_handle_wmnc_notify(d, wParam, lParam);
        }
        break;

    case WM_DESTROY:
        {
            d = (k4_dlg_data *) (LONG_PTR)
                GetWindowLongPtr(hwnd, DWLP_USER);

            if (d == NULL)
                break;

            d->nct->aux = 0;

            PFREE(d);
            SetWindowLongPtr(hwnd, DWLP_USER, 0);
        }
        break;
    }

    return FALSE;
}
Ejemplo n.º 8
0
k5_kinit_task *
k5_kinit_task_create(khui_new_creds * nc)
{
    k5_kinit_task * kt;
    k5_dlg_data   * d;

    wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
    khm_size cbbuf;

    LPNETID_DLGINFO pdlginfo;
    khui_action_context * pctx = NULL;

    khm_handle hsub = NULL;

    khui_cw_find_type(nc, credtype_id_krb5, (khui_new_creds_by_type **) &d);
    if (!d)
	return NULL;

    kt = (k5_kinit_task *) PMALLOC(sizeof(*kt));
    memset(kt, 0, sizeof(*kt));
    kt->magic = K5_KINIT_TASK_MAGIC;
    kt->nc = nc;
    kt->dlg_data = d;
    kt->nct = &d->nct;
    kt->context = 0;

    khui_cw_get_primary_id(nc, &kt->identity);
    cbbuf = sizeof(idname);
    kcdb_identity_get_name(kt->identity, idname, &cbbuf);
    cbbuf = (cbbuf * sizeof(char)) / sizeof(wchar_t);

    kt->principal = PMALLOC(cbbuf);
    UnicodeStrToAnsi(kt->principal, cbbuf, idname);
    kt->password = NULL;
    kt->params = d->params;
    kt->params.lifetime = (krb5_deltat) d->tc_lifetime.current;
    kt->params.renew_life = (krb5_deltat) d->tc_renew.current;

    /* if we have external parameters, we should use them as well */
    pctx = khui_cw_get_ctx(nc);
    if (pctx && pctx->cb_vparam == sizeof(NETID_DLGINFO) &&
        (pdlginfo = pctx->vparam) != NULL &&
        pdlginfo->size == NETID_DLGINFO_V1_SZ) {

        wchar_t * t;
        size_t size;

        if (pdlginfo->in.ccache[0] &&
            SUCCEEDED(StringCchLength(pdlginfo->in.ccache,
                                      NETID_CCACHE_NAME_SZ,
                                      &size))) {
            kt->ccache = PMALLOC(sizeof(char) * (size + 1));
            UnicodeStrToAnsi(kt->ccache, size + 1,
                             pdlginfo->in.ccache);

            /* this is the same as the output cache */

            StringCbCopy(pdlginfo->out.ccache, sizeof(pdlginfo->out.ccache),
                         pdlginfo->in.ccache);
        } else {
            wchar_t ccache[KRB5_MAXCCH_CCNAME];

            size = sizeof(ccache);

            khm_krb5_get_identity_default_ccache(kt->identity, ccache, &size);

            StringCbCopy(pdlginfo->out.ccache, sizeof(pdlginfo->out.ccache),
                         ccache);
        }

        t = khm_get_realm_from_princ(idname);

        if (t) {
            StringCbCopy(pdlginfo->out.realm,
                         sizeof(pdlginfo->out.realm),
                         t);

            if ((t - idname) > 1) {
                StringCchCopyN(pdlginfo->out.username,
                               ARRAYLENGTH(pdlginfo->out.username),
                               idname,
                               (t - idname) - 1);
            } else {
                StringCbCopy(pdlginfo->out.username,
                             sizeof(pdlginfo->out.username),
                             L"");
            }
        } else {
            StringCbCopy(pdlginfo->out.username,
                         sizeof(pdlginfo->out.username),
                         idname);
            StringCbCopy(pdlginfo->out.realm,
                         sizeof(pdlginfo->out.realm),
                         L"");
        }
    }

    kt->state = K5_KINIT_STATE_PREP;
    InitializeCriticalSection(&kt->cs);
    kt->h_task_wait = CreateEvent(NULL, FALSE, FALSE, NULL);
    kt->h_parent_wait = CreateEvent(NULL, FALSE, FALSE, NULL);

    kt->refcount = 2;           /* One hold for the caller, one hold
                                   for the thread */

    kmq_create_subscription(k5_msg_callback, &hsub);

    kt->task = task_create(NULL, 32 * 4096, kinit_task_proc, kt, hsub, 0);

    return kt;
}