#include<kcreddbinternal.h>
#include<assert.h>
static CRITICAL_SECTION cs_ident;
hashtable * kcdb_identities_namemap = NULL;
khm_int32 kcdb_n_identities = 0;
kcdb_identity * kcdb_identities = NULL;
kcdb_identity * kcdb_def_identity = NULL;
khm_handle kcdb_ident_sub = NULL;
khm_int32 kcdb_ident_cred_type = KCDB_CREDTYPE_INVALID;
khm_ui_4 kcdb_ident_refresh_cycle = 0;
khm_boolean kcdb_checked_config = FALSE;
khm_boolean kcdb_checking_config = FALSE;
KHMEXP khm_boolean KHMAPI
kcdb_identity_is_equal(khm_handle identity1,
khm_handle identity2)
{
return (identity1 == identity2);
}
KHMEXP khm_int32 KHMAPI
kcdb_identity_set_provider(khm_handle sub)
{
EnterCriticalSection(&cs_ident);
if (sub != kcdb_ident_sub) {
if(kcdb_ident_sub != NULL) {
kmq_send_sub_msg(kcdb_ident_sub,
KMSG_IDENT,
KMSG_IDENT_EXIT,
0,
0);
kmq_delete_subscription(kcdb_ident_sub);
}
kcdb_ident_sub = sub;
if (kcdb_ident_sub)
kmq_send_sub_msg(kcdb_ident_sub,
KMSG_IDENT,
KMSG_IDENT_INIT,
0,
0);
}
LeaveCriticalSection(&cs_ident);
return KHM_ERROR_SUCCESS;
}
KHMEXP khm_int32 KHMAPI
kcdb_identity_get_provider(khm_handle * sub)
{
khm_int32 rv = KHM_ERROR_SUCCESS;
EnterCriticalSection(&cs_ident);
if(kcdb_ident_sub != NULL)
rv = KHM_ERROR_SUCCESS;
else
rv = KHM_ERROR_NOT_FOUND;
if(sub != NULL)
*sub = kcdb_ident_sub;
LeaveCriticalSection(&cs_ident);
return rv;
}
KHMEXP khm_int32 KHMAPI
kcdb_identity_set_type(khm_int32 cred_type)
{
EnterCriticalSection(&cs_ident);
kcdb_ident_cred_type = cred_type;
LeaveCriticalSection(&cs_ident);
return KHM_ERROR_SUCCESS;
}
KHMEXP khm_int32 KHMAPI
kcdb_identity_get_type(khm_int32 * ptype)
{
if (!ptype)
return KHM_ERROR_INVALID_PARAM;
EnterCriticalSection(&cs_ident);
*ptype = kcdb_ident_cred_type;
LeaveCriticalSection(&cs_ident);
if (*ptype >= 0)
return KHM_ERROR_SUCCESS;
else
return KHM_ERROR_NOT_FOUND;
}
void
kcdbint_ident_msg_completion(kmq_message * m) {
kcdb_identity_release(m->vparam);
}
void
kcdbint_ident_add_ref(const void * key, void * vid) {
}
void
kcdbint_ident_del_ref(const void * key, void * vid) {
}
void
kcdbint_ident_init(void) {
InitializeCriticalSection(&cs_ident);
kcdb_identities_namemap = hash_new_hashtable(
KCDB_IDENT_HASHTABLE_SIZE,
hash_string,
hash_string_comp,
kcdbint_ident_add_ref,
kcdbint_ident_del_ref);
}
void
kcdbint_ident_exit(void) {
EnterCriticalSection(&cs_ident);
hash_del_hashtable(kcdb_identities_namemap);
LeaveCriticalSection(&cs_ident);
DeleteCriticalSection(&cs_ident);
}
KHMEXP khm_boolean KHMAPI
kcdb_identity_is_valid_name(const wchar_t * name)
{
khm_int32 rv;
if (!wcscmp(name, L"_Schema"))
return FALSE;
rv = kcdb_identpro_validate_name(name);
if(rv == KHM_ERROR_NO_PROVIDER ||
rv == KHM_ERROR_NOT_IMPLEMENTED)
return TRUE;
else
return KHM_SUCCEEDED(rv);
}
KHMEXP khm_int32 KHMAPI
kcdb_identity_create(const wchar_t *name,
khm_int32 flags,
khm_handle * result) {
kcdb_identity * id = NULL;
kcdb_identity * id_tmp = NULL;
size_t namesize;
if(!result || !name)
return KHM_ERROR_INVALID_PARAM;
*result = NULL;
EnterCriticalSection(&cs_ident);
id = hash_lookup(kcdb_identities_namemap, (void *) name);
if(id)
kcdb_identity_hold((khm_handle) id);
LeaveCriticalSection(&cs_ident);
if(id) {
*result = (khm_handle) id;
return KHM_ERROR_SUCCESS;
} else if(!(flags & KCDB_IDENT_FLAG_CREATE)) {
return KHM_ERROR_NOT_FOUND;
}
flags &= ~KCDB_IDENT_FLAG_CREATE;
if((flags & ~KCDB_IDENT_FLAGMASK_RDWR) ||
(flags & (KCDB_IDENT_FLAG_DEFAULT |
KCDB_IDENT_FLAG_SEARCHABLE |
KCDB_IDENT_FLAG_STICKY))) {
return KHM_ERROR_INVALID_PARAM;
}
if(!kcdb_identity_is_valid_name(name)) {
return KHM_ERROR_INVALID_NAME;
}
StringCbLength(name, KCDB_IDENT_MAXCB_NAME, &namesize);
namesize += sizeof(wchar_t);
id = PMALLOC(sizeof(kcdb_identity));
ZeroMemory(id, sizeof(kcdb_identity));
id->magic = KCDB_IDENT_MAGIC;
id->name = PMALLOC(namesize);
StringCbCopy(id->name, namesize, name);
id->flags = (flags & KCDB_IDENT_FLAGMASK_RDWR);
id->flags |= KCDB_IDENT_FLAG_ACTIVE | KCDB_IDENT_FLAG_EMPTY;
LINIT(id);
EnterCriticalSection(&cs_ident);
id_tmp = hash_lookup(kcdb_identities_namemap, (void *) id->name);
if(id_tmp) {
kcdb_identity_hold((khm_handle) id_tmp);
*result = (khm_handle) id_tmp;
PFREE(id->name);
PFREE(id);
id = NULL;
} else {
khm_handle h_cfg;
kcdb_identity_hold((khm_handle) id);
hash_add(kcdb_identities_namemap,
(void *) id->name,
(void *) id);
LPUSH(&kcdb_identities, id);
if(KHM_SUCCEEDED(kcdb_identity_get_config((khm_handle) id,
0,
&h_cfg))) {
khm_int32 sticky;
if (KHM_SUCCEEDED(khc_read_int32(h_cfg, L"Sticky", &sticky)) &&
sticky) {
id->flags |= KCDB_IDENT_FLAG_STICKY;
}
khc_close_space(h_cfg);
}
}
LeaveCriticalSection(&cs_ident);
if(id != NULL) {
*result = (khm_handle) id;
kcdb_identpro_notify_create((khm_handle) id);
kcdbint_ident_post_message(KCDB_OP_INSERT, id);
}
return KHM_ERROR_SUCCESS;
}
KHMEXP khm_int32 KHMAPI
kcdb_identity_delete(khm_handle vid) {
kcdb_identity * id;
khm_int32 code = KHM_ERROR_SUCCESS;
EnterCriticalSection(&cs_ident);
if(!kcdb_is_identity(vid)) {
code = KHM_ERROR_INVALID_PARAM;
goto _exit;
}
id = (kcdb_identity *) vid;
if (kcdb_is_active_identity(vid)) {
id->flags &= ~KCDB_IDENT_FLAG_ACTIVE;
hash_del(kcdb_identities_namemap, (void *) id->name);
LeaveCriticalSection(&cs_ident);
kcdbint_ident_post_message(KCDB_OP_DELETE, id);
return KHM_ERROR_SUCCESS;
} else if (id->refcount == 0) {
LDELETE(&kcdb_identities, id);
if (id->name)
PFREE(id->name);
PFREE(id);
}
_exit:
LeaveCriticalSection(&cs_ident);
return code;
}
KHMEXP khm_int32 KHMAPI
kcdb_identity_set_flags(khm_handle vid,
khm_int32 flag,
khm_int32 mask) {
kcdb_identity * id;
khm_int32 oldflags;
khm_int32 newflags;
khm_int32 delta = 0;
khm_int32 rv;
if (mask == 0)
return KHM_ERROR_SUCCESS;
if(!kcdb_is_active_identity(vid))
return KHM_ERROR_INVALID_PARAM;
id = (kcdb_identity *) vid;
flag &= mask;
if((mask & ~KCDB_IDENT_FLAGMASK_RDWR) ||
((flag & KCDB_IDENT_FLAG_INVALID) && (flag & KCDB_IDENT_FLAG_VALID)))
return KHM_ERROR_INVALID_PARAM;
if((mask & KCDB_IDENT_FLAG_DEFAULT) &&
(flag & KCDB_IDENT_FLAG_DEFAULT)) {
rv = kcdb_identity_set_default(vid);
if(KHM_FAILED(rv))
return rv;
mask &= ~KCDB_IDENT_FLAG_DEFAULT;
flag &= ~KCDB_IDENT_FLAG_DEFAULT;
}
EnterCriticalSection(&cs_ident);
if(mask & KCDB_IDENT_FLAG_SEARCHABLE) {
if(!(flag & KCDB_IDENT_FLAG_SEARCHABLE)) {
if(id->flags & KCDB_IDENT_FLAG_SEARCHABLE) {
LeaveCriticalSection(&cs_ident);
rv = kcdb_identpro_set_searchable(vid, FALSE);
EnterCriticalSection(&cs_ident);
if(rv == KHM_ERROR_NO_PROVIDER ||
KHM_SUCCEEDED(rv)) {
id->flags &= ~KCDB_IDENT_FLAG_SEARCHABLE;
delta |= KCDB_IDENT_FLAG_SEARCHABLE;
}
}
} else {
if(!(id->flags & KCDB_IDENT_FLAG_SEARCHABLE)) {
LeaveCriticalSection(&cs_ident);
rv = kcdb_identpro_set_searchable(vid, TRUE);
EnterCriticalSection(&cs_ident);
if(rv == KHM_ERROR_NO_PROVIDER ||
KHM_SUCCEEDED(rv)) {
id->flags |= KCDB_IDENT_FLAG_SEARCHABLE;
delta |= KCDB_IDENT_FLAG_SEARCHABLE;
}
}
}
flag &= ~KCDB_IDENT_FLAG_SEARCHABLE;
mask &= ~KCDB_IDENT_FLAG_SEARCHABLE;
}
if (mask & KCDB_IDENT_FLAG_STICKY) {
if ((flag ^ id->flags) & KCDB_IDENT_FLAG_STICKY) {
khm_handle h_conf;
if (KHM_SUCCEEDED(kcdb_identity_get_config(vid,
KHM_FLAG_CREATE,
&h_conf))) {
khc_write_int32(h_conf, L"Sticky",
!!(flag & KCDB_IDENT_FLAG_STICKY));
khc_close_space(h_conf);
}
id->flags =
((id->flags & ~KCDB_IDENT_FLAG_STICKY) |
(flag & KCDB_IDENT_FLAG_STICKY));
delta |= KCDB_IDENT_FLAG_STICKY;
}
flag &= ~KCDB_IDENT_FLAG_STICKY;
mask &= ~KCDB_IDENT_FLAG_STICKY;
}
oldflags = id->flags;
id->flags = (id->flags & ~mask) | (flag & mask);
if (flag & KCDB_IDENT_FLAG_VALID) {
id->flags &= ~(KCDB_IDENT_FLAG_INVALID | KCDB_IDENT_FLAG_UNKNOWN);
}
if (flag & KCDB_IDENT_FLAG_INVALID) {
id->flags &= ~(KCDB_IDENT_FLAG_VALID | KCDB_IDENT_FLAG_UNKNOWN);
}
newflags = id->flags;
LeaveCriticalSection(&cs_ident);
delta |= newflags ^ oldflags;
if((delta & KCDB_IDENT_FLAG_HIDDEN)) {
kcdbint_ident_post_message(
(newflags & KCDB_IDENT_FLAG_HIDDEN)?KCDB_OP_HIDE:KCDB_OP_UNHIDE,
vid);
}
if((delta & KCDB_IDENT_FLAG_SEARCHABLE)) {
kcdbint_ident_post_message(
(newflags & KCDB_IDENT_FLAG_SEARCHABLE)?KCDB_OP_SETSEARCH:KCDB_OP_UNSETSEARCH,
vid);
}
if(delta != 0)
kcdbint_ident_post_message(KCDB_OP_MODIFY, vid);
return KHM_ERROR_SUCCESS;
}
KHMEXP khm_int32 KHMAPI
kcdb_identity_get_flags(khm_handle vid,
khm_int32 * flags) {
kcdb_identity * id;
*flags = 0;
if(!kcdb_is_active_identity(vid))
return KHM_ERROR_INVALID_PARAM;
id = (kcdb_identity *) vid;
EnterCriticalSection(&cs_ident);
*flags = id->flags;
LeaveCriticalSection(&cs_ident);
return KHM_ERROR_SUCCESS;
}
KHMEXP khm_int32 KHMAPI
kcdb_identity_get_name(khm_handle vid,
wchar_t * buffer,
khm_size * pcbsize) {
size_t namesize;
kcdb_identity * id;
if(!kcdb_is_active_identity(vid) || !pcbsize)
return KHM_ERROR_INVALID_PARAM;
id = (kcdb_identity *) vid;
if(FAILED(StringCbLength(id->name, KCDB_IDENT_MAXCB_NAME, &namesize)))
return KHM_ERROR_UNKNOWN;
namesize += sizeof(wchar_t);
if(!buffer || namesize > *pcbsize) {
*pcbsize = namesize;
return KHM_ERROR_TOO_LONG;
}
StringCbCopy(buffer, *pcbsize, id->name);
*pcbsize = namesize;
return KHM_ERROR_SUCCESS;
}
KHMEXP khm_int32 KHMAPI
kcdb_identity_get_default(khm_handle * pvid) {
khm_handle def;
if (pvid == NULL)
return KHM_ERROR_INVALID_PARAM;
EnterCriticalSection(&cs_ident);
def = kcdb_def_identity;
if (def != NULL)
kcdb_identity_hold(def);
LeaveCriticalSection(&cs_ident);
*pvid = def;
if (def != NULL)
return KHM_ERROR_SUCCESS;
else
return KHM_ERROR_NOT_FOUND;
}
static khm_int32
kcdbint_ident_set_default(khm_handle vid,
khm_boolean invoke_identpro) {
kcdb_identity * new_def;
kcdb_identity * old_def;
khm_int32 rv;
if (vid != NULL && !kcdb_is_active_identity(vid))
return KHM_ERROR_INVALID_PARAM;
new_def = (kcdb_identity *)vid;
if (new_def != NULL && (new_def->flags & KCDB_IDENT_FLAG_DEFAULT))
return KHM_ERROR_SUCCESS;
if ((new_def == NULL && kcdb_def_identity == NULL) ||
(new_def == kcdb_def_identity))
return KHM_ERROR_SUCCESS;
if (invoke_identpro) {
rv = kcdb_identpro_set_default(vid);
if(rv != KHM_ERROR_NO_PROVIDER && KHM_FAILED(rv))
return rv;
}
EnterCriticalSection(&cs_ident);
old_def = kcdb_def_identity;
kcdb_def_identity = new_def;
if(old_def != new_def) {
if(old_def) {
old_def->flags &= ~KCDB_IDENT_FLAG_DEFAULT;
kcdb_identity_release((khm_handle) old_def);
}
if(new_def) {
new_def->flags |= KCDB_IDENT_FLAG_DEFAULT;
kcdb_identity_hold((khm_handle) new_def);
}
LeaveCriticalSection(&cs_ident);
kcdbint_ident_post_message(KCDB_OP_NEW_DEFAULT, new_def);
} else {
LeaveCriticalSection(&cs_ident);
}
return KHM_ERROR_SUCCESS;
}
KHMEXP khm_int32 KHMAPI
kcdb_identity_set_default(khm_handle vid) {
return kcdbint_ident_set_default(vid, TRUE);
}
KHMEXP khm_int32 KHMAPI
kcdb_identity_set_default_int(khm_handle vid) {
return kcdbint_ident_set_default(vid, FALSE);
}
KHMEXP khm_int32 KHMAPI
kcdb_identity_get_config(khm_handle vid,
khm_int32 flags,
khm_handle * result) {
khm_handle hkcdb;
khm_handle hidents = NULL;
khm_handle hident = NULL;
khm_int32 rv;
kcdb_identity * id;
if(kcdb_is_active_identity(vid)) {
id = (kcdb_identity *) vid;
} else {
return KHM_ERROR_INVALID_PARAM;
}
hkcdb = kcdb_get_config();
if(hkcdb) {
rv = khc_open_space(hkcdb, L"Identity", 0, &hidents);
if(KHM_FAILED(rv))
goto _exit;
rv = khc_open_space(hidents,
id->name,
flags | KCONF_FLAG_NOPARSENAME,
&hident);
if(KHM_FAILED(rv)) {
khm_int32 oldflags;
EnterCriticalSection(&cs_ident);
oldflags = id->flags;
id->flags &= ~KCDB_IDENT_FLAG_CONFIG;
LeaveCriticalSection(&cs_ident);
if (oldflags & KCDB_IDENT_FLAG_CONFIG)
kcdbint_ident_post_message(KCDB_OP_DELCONFIG, id);
goto _exit;
}
EnterCriticalSection(&cs_ident);
id->flags |= KCDB_IDENT_FLAG_CONFIG;
LeaveCriticalSection(&cs_ident);
*result = hident;
} else
rv = KHM_ERROR_UNKNOWN;
_exit:
if(hidents)
khc_close_space(hidents);
if(hkcdb)
khc_close_space(hkcdb);
return rv;
}
void
kcdbint_ident_post_message(khm_int32 op, kcdb_identity * id) {
kcdb_identity_hold(id);
kmq_post_message(KMSG_KCDB, KMSG_KCDB_IDENT, op, (void *) id);
}
KHMEXP khm_int32 KHMAPI
kcdb_identity_hold(khm_handle vid) {
kcdb_identity * id;
EnterCriticalSection(&cs_ident);
if(kcdb_is_active_identity(vid)) {
id = vid;
id->refcount++;
} else {
LeaveCriticalSection(&cs_ident);
return KHM_ERROR_INVALID_PARAM;
}
LeaveCriticalSection(&cs_ident);
return ERROR_SUCCESS;
}
KHMEXP khm_int32 KHMAPI
kcdb_identity_release(khm_handle vid) {
kcdb_identity * id;
khm_int32 refcount;
EnterCriticalSection(&cs_ident);
if(kcdb_is_identity(vid)) {
id = vid;
refcount = --id->refcount;
if(refcount == 0) {
if (id->refcount == 0 &&
!(id->flags & KCDB_IDENT_FLAG_CONFIG))
kcdb_identity_delete(vid);
}
} else {
LeaveCriticalSection(&cs_ident);
return KHM_ERROR_INVALID_PARAM;
}
LeaveCriticalSection(&cs_ident);
return ERROR_SUCCESS;
}
struct kcdb_idref_result {
kcdb_identity * ident;
khm_int32 flags;
khm_size count;
};
static khm_int32 KHMAPI
kcdbint_idref_proc(khm_handle cred, void * r) {
khm_handle vid;
struct kcdb_idref_result *result;
khm_int32 flags;
result = (struct kcdb_idref_result *) r;
if (KHM_SUCCEEDED(kcdb_cred_get_identity(cred, &vid))) {
if (result->ident == (kcdb_identity *) vid) {
result->count++;
kcdb_cred_get_flags(cred, &flags);
if (flags & KCDB_CRED_FLAG_RENEWABLE) {
result->flags |= KCDB_IDENT_FLAG_CRED_RENEW;
if (flags & KCDB_CRED_FLAG_INITIAL) {
result->flags |= KCDB_IDENT_FLAG_RENEWABLE;
}
}
if (flags & KCDB_CRED_FLAG_EXPIRED) {
result->flags |= KCDB_IDENT_FLAG_CRED_EXP;
if (flags & KCDB_CRED_FLAG_INITIAL) {
result->flags |= KCDB_IDENT_FLAG_EXPIRED;
}
}
if (flags & KCDB_CRED_FLAG_INITIAL) {
result->flags |= KCDB_IDENT_FLAG_VALID;
}
}
kcdb_identity_release(vid);
}
return KHM_ERROR_SUCCESS;
}
KHMEXP khm_int32 KHMAPI
kcdb_identity_refresh(khm_handle vid) {
kcdb_identity * ident;
khm_int32 code = KHM_ERROR_SUCCESS;
struct kcdb_idref_result result;
EnterCriticalSection(&cs_ident);
if (!kcdb_is_active_identity(vid)) {
code = KHM_ERROR_INVALID_PARAM;
goto _exit;
}
ident = (kcdb_identity *) vid;
result.ident = ident;
result.flags = 0;
result.count = 0;
LeaveCriticalSection(&cs_ident);
kcdb_credset_apply(NULL, kcdbint_idref_proc, &result);
if (result.count == 0)
result.flags |= KCDB_IDENT_FLAG_EMPTY;
kcdb_identity_set_flags(vid, result.flags,
KCDB_IDENT_FLAGMASK_RDWR &
~(KCDB_IDENT_FLAG_DEFAULT |
KCDB_IDENT_FLAG_SEARCHABLE |
KCDB_IDENT_FLAG_STICKY));
EnterCriticalSection(&cs_ident);
ident->refresh_cycle = kcdb_ident_refresh_cycle;
_exit:
LeaveCriticalSection(&cs_ident);
if (code == 0)
code = kcdb_identpro_update(vid);
return code;
}
KHMEXP khm_int32 KHMAPI
kcdb_identity_refresh_all(void) {
kcdb_identity * ident;
kcdb_identity * next;
khm_int32 code = KHM_ERROR_SUCCESS;
int hit_count;
EnterCriticalSection(&cs_ident);
kcdb_ident_refresh_cycle++;
do {
hit_count = 0;
for (ident = kcdb_identities;
ident != NULL;
ident = next) {
if (!kcdb_is_active_identity(ident) ||
ident->refresh_cycle == kcdb_ident_refresh_cycle) {
next = LNEXT(ident);
continue;
}
kcdb_identity_hold((khm_handle) ident);
LeaveCriticalSection(&cs_ident);
kcdb_identity_refresh((khm_handle) ident);
EnterCriticalSection(&cs_ident);
next = LNEXT(ident);
kcdb_identity_release((khm_handle) ident);
hit_count++;
}
} while (hit_count > 0);
LeaveCriticalSection(&cs_ident);
return code;
}
KHMEXP khm_int32 KHMAPI
kcdb_identity_set_attr(khm_handle vid,
khm_int32 attr_id,
void * buffer,
khm_size cbbuf)
{
kcdb_identity * id = NULL;
kcdb_attrib * attrib = NULL;
kcdb_type * type = NULL;
khm_size slot;
khm_size cbdest;
khm_int32 code = KHM_ERROR_SUCCESS;
EnterCriticalSection(&cs_ident);
if(!kcdb_is_active_identity(vid)) {
LeaveCriticalSection(&cs_ident);
return KHM_ERROR_INVALID_PARAM;
}
id = (kcdb_identity *) vid;
if(!(id->flags & KCDB_IDENT_FLAG_ATTRIBS)) {
kcdb_buf_new(&id->buf, KCDB_BUF_DEFAULT);
id->flags |= KCDB_IDENT_FLAG_ATTRIBS;
}
if(KHM_FAILED(kcdb_attrib_get_info(attr_id, &attrib))) {
LeaveCriticalSection(&cs_ident);
return KHM_ERROR_INVALID_PARAM;
}
#if 0
if(attrib->flags & KCDB_ATTR_FLAG_COMPUTED)
{
LeaveCriticalSection(&cs_ident);
kcdb_attrib_release_info(attrib);
return KHM_ERROR_INVALID_OPERATION;
}
#endif
if (buffer == NULL) {
slot = kcdb_buf_slot_by_id(&id->buf, (khm_ui_2) attr_id);
if (slot != KCDB_BUF_INVALID_SLOT &&
kcdb_buf_exist(&id->buf, slot))
kcdb_buf_alloc(&id->buf, slot, (khm_ui_2) attr_id, 0);
code = KHM_ERROR_SUCCESS;
goto _exit;
}
if(KHM_FAILED(kcdb_type_get_info(attrib->type, &type))) {
LeaveCriticalSection(&cs_ident);
kcdb_attrib_release_info(attrib);
return KHM_ERROR_INVALID_PARAM;
}
if(!(type->isValid(buffer,cbbuf))) {
code = KHM_ERROR_TYPE_MISMATCH;
goto _exit;
}
if((type->dup(buffer, cbbuf, NULL, &cbdest)) != KHM_ERROR_TOO_LONG) {
code = KHM_ERROR_INVALID_PARAM;
goto _exit;
}
kcdb_buf_alloc(&id->buf, KCDB_BUF_APPEND, (khm_ui_2) attr_id, cbdest);
slot = kcdb_buf_slot_by_id(&id->buf, (khm_ui_2) attr_id);
if(slot == KCDB_BUF_INVALID_SLOT || !kcdb_buf_exist(&id->buf, slot)) {
code = KHM_ERROR_NO_RESOURCES;
goto _exit;
}
if(KHM_FAILED(code =
type->dup(buffer, cbbuf, kcdb_buf_get(&id->buf, slot), &cbdest)))
{
kcdb_buf_alloc(&id->buf, slot, (khm_ui_2) attr_id, 0);
goto _exit;
}
kcdb_buf_set_value_flag(&id->buf, slot);
_exit:
LeaveCriticalSection(&cs_ident);
if(attrib)
kcdb_attrib_release_info(attrib);
if(type)
kcdb_type_release_info(type);
return code;
}
KHMEXP khm_int32 KHMAPI
kcdb_identity_set_attrib(khm_handle vid,
const wchar_t * attr_name,
void * buffer,
khm_size cbbuf)
{
khm_int32 attr_id = -1;
if(KHM_FAILED(kcdb_attrib_get_id(attr_name, &attr_id)))
return KHM_ERROR_INVALID_PARAM;
return kcdb_identity_set_attr(
vid,
attr_id,
buffer,
cbbuf);
}
KHMEXP khm_int32 KHMAPI
kcdb_identity_get_attr(khm_handle vid,
khm_int32 attr_id,
khm_int32 * attr_type,
void * buffer,
khm_size * pcbbuf)
{
khm_int32 code = KHM_ERROR_SUCCESS;
kcdb_identity * id = NULL;
kcdb_attrib * attrib = NULL;
kcdb_type * type = NULL;
khm_size slot;
if(KHM_FAILED(kcdb_attrib_get_info(attr_id, &attrib))) {
return KHM_ERROR_INVALID_PARAM;
}
if(KHM_FAILED(kcdb_type_get_info(attrib->type, &type))) {
kcdb_attrib_release_info(attrib);
return KHM_ERROR_UNKNOWN;
}
if(attr_type)
*attr_type = attrib->type;
EnterCriticalSection(&cs_ident);
if(!kcdb_is_active_identity(vid)) {
code = KHM_ERROR_INVALID_PARAM;
goto _exit;
}
id = (kcdb_identity *) vid;
if(!(id->flags & KCDB_IDENT_FLAG_ATTRIBS) ||
(slot = kcdb_buf_slot_by_id(&id->buf, (khm_ui_2) attr_id)) == KCDB_BUF_INVALID_SLOT ||
!kcdb_buf_val_exist(&id->buf, slot))
{
code = KHM_ERROR_NOT_FOUND;
goto _exit;
}
if(!buffer && !pcbbuf) {
code = KHM_ERROR_SUCCESS;
goto _exit;
}
#if 0
if(attrib->flags & KCDB_ATTR_FLAG_COMPUTED) {
#ifdef DEBUG
assert(FALSE);
#endif
code = KHM_ERROR_INVALID_OPERATION;
} else {
#endif
code = type->dup(
kcdb_buf_get(&id->buf, slot),
kcdb_buf_size(&id->buf, slot),
buffer,
pcbbuf);
#if 0
}
#endif
_exit:
LeaveCriticalSection(&cs_ident);
if(type)
kcdb_type_release_info(type);
if(attrib)
kcdb_attrib_release_info(attrib);
return code;
}
KHMEXP khm_int32 KHMAPI
kcdb_identity_get_attrib(khm_handle vid,
const wchar_t * attr_name,
khm_int32 * attr_type,
void * buffer,
khm_size * pcbbuf)
{
khm_int32 attr_id = -1;
if(KHM_FAILED(kcdb_attrib_get_id(attr_name, &attr_id)))
return KHM_ERROR_NOT_FOUND;
return kcdb_identity_get_attr(vid,
attr_id,
attr_type,
buffer,
pcbbuf);
}
KHMEXP khm_int32 KHMAPI
kcdb_identity_get_attr_string(khm_handle vid,
khm_int32 attr_id,
wchar_t * buffer,
khm_size * pcbbuf,
khm_int32 flags)
{
khm_int32 code = KHM_ERROR_SUCCESS;
kcdb_identity * id = NULL;
kcdb_attrib * attrib = NULL;
kcdb_type * type = NULL;
khm_size slot;
if(KHM_FAILED(kcdb_attrib_get_info(attr_id, &attrib))) {
return KHM_ERROR_INVALID_PARAM;
}
if(KHM_FAILED(kcdb_type_get_info(attrib->type, &type))) {
kcdb_attrib_release_info(attrib);
return KHM_ERROR_UNKNOWN;
}
EnterCriticalSection(&cs_ident);
if(!kcdb_is_active_identity(vid)) {
code = KHM_ERROR_INVALID_PARAM;
goto _exit;
}
id = (kcdb_identity *) vid;
if(!(id->flags & KCDB_IDENT_FLAG_ATTRIBS) ||
(slot = kcdb_buf_slot_by_id(&id->buf, (khm_ui_2) attr_id)) == KCDB_BUF_INVALID_SLOT ||
!kcdb_buf_val_exist(&id->buf, slot))
{
code = KHM_ERROR_NOT_FOUND;
goto _exit;
}
if(!buffer && !pcbbuf) {
code = KHM_ERROR_SUCCESS;
goto _exit;
}
#if 0
if(attrib->flags & KCDB_ATTR_FLAG_COMPUTED) {
#ifdef DEBUG
assert(FALSE);
#endif
code = KHM_ERROR_INVALID_OPERATION;
} else {
#endif
if(kcdb_buf_exist(&id->buf, slot)) {
code = type->toString(
kcdb_buf_get(&id->buf, slot),
kcdb_buf_size(&id->buf, slot),
buffer,
pcbbuf,
flags);
} else
code = KHM_ERROR_NOT_FOUND;
#if 0
}
#endif
_exit:
LeaveCriticalSection(&cs_ident);
if(type)
kcdb_type_release_info(type);
if(attrib)
kcdb_attrib_release_info(attrib);
return code;
}
KHMEXP khm_int32 KHMAPI
kcdb_identity_get_attrib_string(khm_handle vid,
const wchar_t * attr_name,
wchar_t * buffer,
khm_size * pcbbuf,
khm_int32 flags)
{
khm_int32 attr_id = -1;
if(KHM_FAILED(kcdb_attrib_get_id(attr_name, &attr_id)))
return KHM_ERROR_NOT_FOUND;
return kcdb_identity_get_attr_string(
vid,
attr_id,
buffer,
pcbbuf,
flags);
}
KHMEXP khm_int32 KHMAPI
kcdb_identpro_validate_name(const wchar_t * name)
{
kcdb_ident_name_xfer namex;
khm_handle sub;
khm_size cch;
khm_int32 rv = KHM_ERROR_SUCCESS;
if(FAILED(StringCchLength(name, KCDB_IDENT_MAXCCH_NAME, &cch)))
return KHM_ERROR_TOO_LONG;
#ifdef VALIDATE_IDENTIY_CHARACTERS
if(wcsspn(name, KCDB_IDENT_VALID_CHARS) != cch)
return KHM_ERROR_INVALID_NAME;
#endif
EnterCriticalSection(&cs_ident);
if(kcdb_ident_sub != NULL) {
sub = kcdb_ident_sub;
} else {
sub = NULL;
rv = KHM_ERROR_NO_PROVIDER;
}
LeaveCriticalSection(&cs_ident);
if(sub != NULL) {
ZeroMemory(&namex, sizeof(namex));
namex.name_src = name;
namex.result = KHM_ERROR_NOT_IMPLEMENTED;
kmq_send_sub_msg(sub,
KMSG_IDENT,
KMSG_IDENT_VALIDATE_NAME,
0,
(void *) &namex);
rv = namex.result;
}
return rv;
}
KHMEXP khm_int32 KHMAPI
kcdb_identpro_validate_identity(khm_handle identity)
{
khm_int32 rv = KHM_ERROR_SUCCESS;
khm_handle sub;
if(!kcdb_is_active_identity(identity))
return KHM_ERROR_INVALID_PARAM;
EnterCriticalSection(&cs_ident);
if(kcdb_ident_sub != NULL) {
sub = kcdb_ident_sub;
} else {
sub = NULL;
rv = KHM_ERROR_NO_PROVIDER;
}
LeaveCriticalSection(&cs_ident);
if(sub != NULL) {
rv = kmq_send_sub_msg(sub,
KMSG_IDENT,
KMSG_IDENT_VALIDATE_IDENTITY,
0,
(void *) identity);
}
return rv;
}
KHMEXP khm_int32 KHMAPI
kcdb_identpro_canon_name(const wchar_t * name_in,
wchar_t * name_out,
khm_size * cb_name_out)
{
khm_handle sub;
kcdb_ident_name_xfer namex;
wchar_t name_tmp[KCDB_IDENT_MAXCCH_NAME];
khm_int32 rv = KHM_ERROR_SUCCESS;
khm_size cch;
if(cb_name_out == 0 ||
FAILED(StringCchLength(name_in, KCDB_IDENT_MAXCCH_NAME, &cch)))
return KHM_ERROR_INVALID_NAME;
EnterCriticalSection(&cs_ident);
if(kcdb_ident_sub != NULL) {
sub = kcdb_ident_sub;
} else {
sub = NULL;
rv = KHM_ERROR_NO_PROVIDER;
}
LeaveCriticalSection(&cs_ident);
if(sub != NULL) {
ZeroMemory(&namex, sizeof(namex));
ZeroMemory(name_tmp, sizeof(name_tmp));
namex.name_src = name_in;
namex.name_dest = name_tmp;
namex.cb_name_dest = sizeof(name_tmp);
namex.result = KHM_ERROR_NOT_IMPLEMENTED;
rv = kmq_send_sub_msg(sub,
KMSG_IDENT,
KMSG_IDENT_CANON_NAME,
0,
(void *) &namex);
if(KHM_SUCCEEDED(namex.result)) {
const wchar_t * name_result;
khm_size cb;
if(name_in[0] != 0 && name_tmp[0] == 0)
name_result = name_tmp;
else
name_result = name_in;
if(FAILED(StringCbLength(name_result, KCDB_IDENT_MAXCB_NAME, &cb)))
rv = KHM_ERROR_UNKNOWN;
else {
cb += sizeof(wchar_t);
if(name_out == 0 || *cb_name_out < cb) {
rv = KHM_ERROR_TOO_LONG;
*cb_name_out = cb;
} else {
StringCbCopy(name_out, *cb_name_out, name_result);
*cb_name_out = cb;
rv = KHM_ERROR_SUCCESS;
}
}
}
}
return rv;
}
KHMEXP khm_int32 KHMAPI
kcdb_identpro_compare_name(const wchar_t * name1,
const wchar_t * name2)
{
khm_handle sub;
kcdb_ident_name_xfer namex;
khm_int32 rv = 0;
rv = wcscmp(name1, name2);
EnterCriticalSection(&cs_ident);
if(kcdb_ident_sub != NULL) {
sub = kcdb_ident_sub;
} else {
sub = NULL;
}
LeaveCriticalSection(&cs_ident);
if(sub != NULL) {
ZeroMemory(&namex, sizeof(namex));
namex.name_src = name1;
namex.name_alt = name2;
namex.result = rv;
kmq_send_sub_msg(sub,
KMSG_IDENT,
KMSG_IDENT_COMPARE_NAME,
0,
(void *) &namex);
rv = namex.result;
}
return rv;
}
KHMEXP khm_int32 KHMAPI
kcdb_identpro_set_default(khm_handle identity)
{
khm_handle sub;
khm_int32 rv = KHM_ERROR_SUCCESS;
if((identity != NULL) &&
!kcdb_is_active_identity(identity))
return KHM_ERROR_INVALID_PARAM;
EnterCriticalSection(&cs_ident);
if(kcdb_ident_sub != NULL) {
sub = kcdb_ident_sub;
} else {
sub = NULL;
rv = KHM_ERROR_NO_PROVIDER;
}
LeaveCriticalSection(&cs_ident);
if(sub != NULL) {
rv = kmq_send_sub_msg(sub,
KMSG_IDENT,
KMSG_IDENT_SET_DEFAULT,
(identity != NULL),
(void *) identity);
}
return rv;
}
KHMEXP khm_int32 KHMAPI
kcdb_identpro_set_searchable(khm_handle identity,
khm_boolean searchable)
{
khm_handle sub;
khm_int32 rv = KHM_ERROR_SUCCESS;
if(!kcdb_is_active_identity(identity))
return KHM_ERROR_INVALID_PARAM;
EnterCriticalSection(&cs_ident);
if(kcdb_ident_sub != NULL) {
sub = kcdb_ident_sub;
} else {
sub = NULL;
rv = KHM_ERROR_NO_PROVIDER;
}
LeaveCriticalSection(&cs_ident);
if(sub != NULL) {
rv = kmq_send_sub_msg(
sub,
KMSG_IDENT,
KMSG_IDENT_SET_SEARCHABLE,
searchable,
(void *) identity);
}
return rv;
}
KHMEXP khm_int32 KHMAPI
kcdb_identpro_update(khm_handle identity)
{
khm_handle sub;
khm_int32 rv = KHM_ERROR_SUCCESS;
if(!kcdb_is_active_identity(identity))
return KHM_ERROR_INVALID_PARAM;
EnterCriticalSection(&cs_ident);
if(kcdb_ident_sub != NULL) {
sub = kcdb_ident_sub;
} else {
sub = NULL;
rv = KHM_ERROR_NO_PROVIDER;
}
LeaveCriticalSection(&cs_ident);
if(sub != NULL) {
rv = kmq_send_sub_msg(sub,
KMSG_IDENT,
KMSG_IDENT_UPDATE,
0,
(void *) identity);
}
return rv;
}
KHMEXP khm_int32 KHMAPI
kcdb_identpro_notify_create(khm_handle identity)
{
khm_handle sub;
khm_int32 rv = KHM_ERROR_SUCCESS;
if(!kcdb_is_active_identity(identity))
return KHM_ERROR_INVALID_PARAM;
EnterCriticalSection(&cs_ident);
if(kcdb_ident_sub != NULL) {
sub = kcdb_ident_sub;
} else {
sub = NULL;
rv = KHM_ERROR_NO_PROVIDER;
}
LeaveCriticalSection(&cs_ident);
if(sub != NULL) {
rv = kmq_send_sub_msg(
sub,
KMSG_IDENT,
KMSG_IDENT_NOTIFY_CREATE,
0,
(void *) identity);
}
return rv;
}
KHMEXP khm_int32 KHMAPI
kcdb_identpro_get_ui_cb(void * rock)
{
khm_handle sub;
khm_int32 rv = KHM_ERROR_SUCCESS;
EnterCriticalSection(&cs_ident);
if(kcdb_ident_sub != NULL) {
sub = kcdb_ident_sub;
} else {
sub = NULL;
rv = KHM_ERROR_NO_PROVIDER;
}
LeaveCriticalSection(&cs_ident);
if(sub != NULL) {
rv = kmq_send_sub_msg(
sub,
KMSG_IDENT,
KMSG_IDENT_GET_UI_CALLBACK,
0,
rock);
}
return rv;
}
KHMEXP khm_int32 KHMAPI
kcdb_identity_enum(khm_int32 and_flags,
khm_int32 eq_flags,
wchar_t * name_buf,
khm_size * pcb_buf,
khm_size * pn_idents)
{
kcdb_identity * id;
khm_int32 rv = KHM_ERROR_SUCCESS;
khm_size cb_req = 0;
khm_size n_idents = 0;
size_t cb_curr;
size_t cch_curr;
size_t cch_left;
HRESULT hr;
if ((name_buf == NULL && pcb_buf == NULL && pn_idents == NULL) ||
(name_buf != NULL && pcb_buf == NULL))
return KHM_ERROR_INVALID_PARAM;
eq_flags &= and_flags;
EnterCriticalSection(&cs_ident);
if (!kcdb_checked_config) {
khm_handle h_kcdb = NULL;
khm_handle h_idents = NULL;
khm_handle h_ident = NULL;
kcdb_checked_config = TRUE;
kcdb_checking_config = TRUE;
h_kcdb = kcdb_get_config();
if (!h_kcdb)
goto _config_check_cleanup;
if(KHM_FAILED(khc_open_space(h_kcdb, L"Identity", 0, &h_idents)))
goto _config_check_cleanup;
while(KHM_SUCCEEDED(khc_enum_subspaces(h_idents,
h_ident,
&h_ident))) {
wchar_t wname[KCDB_IDENT_MAXCCH_NAME];
khm_size cb;
khm_handle t_id;
cb = sizeof(wname);
if (KHM_FAILED(khc_get_config_space_name(h_ident,
wname,
&cb)))
continue;
LeaveCriticalSection(&cs_ident);
if (KHM_SUCCEEDED(kcdb_identity_create(wname,
KCDB_IDENT_FLAG_CREATE,
&t_id)))
kcdb_identity_release(t_id);
EnterCriticalSection(&cs_ident);
}
_config_check_cleanup:
if (h_kcdb)
khc_close_space(h_kcdb);
if (h_idents)
khc_close_space(h_idents);
kcdb_checking_config = FALSE;
}
for ( id = kcdb_identities;
id != NULL;
id = LNEXT(id) ) {
if (((id->flags & KCDB_IDENT_FLAG_ACTIVE) ==
KCDB_IDENT_FLAG_ACTIVE) &&
((id->flags & and_flags) == eq_flags)) {
n_idents ++;
hr = StringCbLength(id->name, KCDB_IDENT_MAXCB_NAME, &cb_curr);
#ifdef DEBUG
assert(SUCCEEDED(hr));
#endif
cb_req += cb_curr + sizeof(wchar_t);
}
}
cb_req += sizeof(wchar_t);
if (pn_idents != NULL)
*pn_idents = n_idents;
if (pcb_buf != NULL && (name_buf == NULL || *pcb_buf < cb_req)) {
*pcb_buf = cb_req;
rv = KHM_ERROR_TOO_LONG;
} else if(name_buf != NULL) {
cch_left = (*pcb_buf) / sizeof(wchar_t);
for (id = kcdb_identities;
id != NULL;
id = LNEXT(id)) {
if (((id->flags & KCDB_IDENT_FLAG_ACTIVE) ==
KCDB_IDENT_FLAG_ACTIVE) &&
((id->flags & and_flags) == eq_flags)) {
StringCchLength(id->name, KCDB_IDENT_MAXCCH_NAME,
&cch_curr);
cch_curr++;
StringCchCopy(name_buf, cch_left, id->name);
cch_left -= cch_curr;
name_buf += cch_curr;
}
}
*name_buf = L'\0';
*pcb_buf = cb_req;
}
LeaveCriticalSection(&cs_ident);
return rv;
}