summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJeffrey Altman <jaltman@secure-endpoints.com>2007-03-29 21:19:43 +0000
committerJeffrey Altman <jaltman@secure-endpoints.com>2007-03-29 21:19:43 +0000
commit4a1a867562bbc20ef769e3f556a69767b236433f (patch)
tree39400a87fcf5d27ee334b19573051c854cbe58ce /src
parent6b012c14dafd83c9b69438ff94c5f5c5ae138bf2 (diff)
more bug fixes for NIM 1.2 (KFW 3.2)
netidmgr.exe - Credentials display : - If an outline is marked as KHUI_CW_O_STICKY | KHUI_CW_O_RELIDENT, release the identity when deleting the outline node. - Correctly determine the location of UI widgets using the column specifier of the outline node instead of the column specifier of the row. - Do not recompute the extents of a row. - If there is a default identity and it has no credentials and it is not pinned, display it anyway. krb5common.obj - Import profile_rename_section() krb5cred.dll - In the realm editor: - When writing realm data, keep track of whether any updates were performed. - Reset the dirty bits for each element whose changes were written to the profile. - Use profile_rename_section() correctly to delete sections. - Check if any changes were applied before setting the 'applied' bit for the configuration node. - Don't assume that the Kerberos 5 General configuration panel has received WMCFG_APPLY before the realm editor. It will not receive the notification if it hasn't indicated that there are changes to be applied. - New credentials : - If there is no "ExpiresOn" value for a cached prompt set, assume that it has already expired. - Set the lifetime for a new prompt set to be 7 days longer than then maximum renewable lifetime. ticket: new component: windows tags: pullup git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@19307 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src')
-rw-r--r--src/windows/identity/plugins/common/dynimport.c2
-rw-r--r--src/windows/identity/plugins/common/dynimport.h1
-rw-r--r--src/windows/identity/plugins/krb5/krb5configdlg.c69
-rw-r--r--src/windows/identity/plugins/krb5/krb5newcreds.c23
-rw-r--r--src/windows/identity/ui/credwnd.c157
-rw-r--r--src/windows/identity/ui/credwnd.h1
6 files changed, 143 insertions, 110 deletions
diff --git a/src/windows/identity/plugins/common/dynimport.c b/src/windows/identity/plugins/common/dynimport.c
index d891af122..f49987ca7 100644
--- a/src/windows/identity/plugins/common/dynimport.c
+++ b/src/windows/identity/plugins/common/dynimport.c
@@ -168,6 +168,7 @@ DECL_FUNC_PTR(profile_clear_relation);
DECL_FUNC_PTR(profile_add_relation);
DECL_FUNC_PTR(profile_update_relation);
DECL_FUNC_PTR(profile_release_string);
+DECL_FUNC_PTR(profile_rename_section);
// Service functions
DECL_FUNC_PTR(OpenSCManagerA);
@@ -315,6 +316,7 @@ FUNC_INFO profile_fi[] = {
MAKE_FUNC_INFO(profile_add_relation),
MAKE_FUNC_INFO(profile_update_relation),
MAKE_FUNC_INFO(profile_release_string),
+ MAKE_FUNC_INFO(profile_rename_section),
END_FUNC_INFO
};
diff --git a/src/windows/identity/plugins/common/dynimport.h b/src/windows/identity/plugins/common/dynimport.h
index 0f2cc237d..7f3f598b0 100644
--- a/src/windows/identity/plugins/common/dynimport.h
+++ b/src/windows/identity/plugins/common/dynimport.h
@@ -291,6 +291,7 @@ extern DECL_FUNC_PTR(profile_clear_relation);
extern DECL_FUNC_PTR(profile_add_relation);
extern DECL_FUNC_PTR(profile_update_relation);
extern DECL_FUNC_PTR(profile_release_string);
+extern DECL_FUNC_PTR(profile_rename_section);
// Service functions
extern DECL_FUNC_PTR(OpenSCManagerA);
diff --git a/src/windows/identity/plugins/krb5/krb5configdlg.c b/src/windows/identity/plugins/krb5/krb5configdlg.c
index 2d1e3259c..36936cdea 100644
--- a/src/windows/identity/plugins/krb5/krb5configdlg.c
+++ b/src/windows/identity/plugins/krb5/krb5configdlg.c
@@ -234,6 +234,7 @@ k5_is_profile_loaded(void) {
assert(pprofile_add_relation);
assert(pprofile_update_relation);
assert(pprofile_flush);
+ assert(pprofile_rename_section);
#endif
if (!pprofile_init ||
@@ -247,7 +248,8 @@ k5_is_profile_loaded(void) {
!pprofile_clear_relation ||
!pprofile_add_relation ||
!pprofile_update_relation ||
- !pprofile_flush)
+ !pprofile_flush ||
+ !pprofile_rename_section)
return FALSE;
@@ -529,7 +531,7 @@ k5_read_config_data(k5_config_data * d) {
d->flags = 0;
}
-void
+int
k5_write_config_data(k5_config_data * d) {
char astr[MAX_PATH * 2];
char config_file[MAX_PATH];
@@ -537,22 +539,25 @@ k5_write_config_data(k5_config_data * d) {
const char *filenames[2];
long rv;
khm_size s;
+ int applied = FALSE;
if (d->flags == 0)
- return;
+ return FALSE;
if (!k5_is_profile_loaded())
- return;
+ return FALSE;
/* write the MSLSA import setting */
if (d->flags & K5_CDFLAG_MOD_LSA_IMPORT) {
khc_write_int32(csp_params, L"MsLsaImport", d->lsa_import);
d->flags &= ~K5_CDFLAG_MOD_LSA_IMPORT;
+ applied = TRUE;
}
if (d->flags & K5_CDFLAG_MOD_INC_REALMS) {
khc_write_int32(csp_params, L"UseFullRealmList", d->inc_realms);
d->flags &= ~K5_CDFLAG_MOD_INC_REALMS;
+ applied = TRUE;
}
if (!(d->flags &
@@ -566,7 +571,7 @@ k5_write_config_data(k5_config_data * d) {
K5_CDFLAG_MOD_REALMS))) {
d->flags = 0;
- return;
+ return applied;
}
khm_krb5_get_profile_file(config_file, ARRAYLENGTH(config_file));
@@ -620,6 +625,7 @@ k5_write_config_data(k5_config_data * d) {
rv = pprofile_add_relation(profile, sec_libdefaults,
defrealm);
+ applied = TRUE;
}
d->flags &= ~K5_CDFLAG_MOD_DEF_REALM;
}
@@ -635,6 +641,7 @@ k5_write_config_data(k5_config_data * d) {
KRB5_CONF_YES:
KRB5_CONF_NO);
d->flags &= ~K5_CDFLAG_MOD_DNS_LOOKUP_KDC;
+ applied = TRUE;
}
if (d->flags & K5_CDFLAG_MOD_DNS_LOOKUP_RLM) {
@@ -649,6 +656,7 @@ k5_write_config_data(k5_config_data * d) {
KRB5_CONF_NO);
d->flags &= ~K5_CDFLAG_MOD_DNS_LOOKUP_RLM;
+ applied = TRUE;
}
if (d->flags & K5_CDFLAG_MOD_DNS_FALLBACK) {
@@ -663,6 +671,7 @@ k5_write_config_data(k5_config_data * d) {
KRB5_CONF_NO);
d->flags &= ~K5_CDFLAG_MOD_DNS_FALLBACK;
+ applied = TRUE;
}
if (d->flags & K5_CDFLAG_MOD_NOADDRESSES) {
@@ -677,6 +686,7 @@ k5_write_config_data(k5_config_data * d) {
KRB5_CONF_NO);
d->flags &= ~K5_CDFLAG_MOD_NOADDRESSES;
+ applied = TRUE;
}
/* now we look at the [realms] section */
@@ -726,7 +736,10 @@ k5_write_config_data(k5_config_data * d) {
pprofile_add_relation(profile, sec_admin,
host);
- d->realms[r].kdcs[k].flags &= ~K5_RKFLAG_NEW;
+ d->realms[r].kdcs[k].flags &= ~ (K5_RKFLAG_NEW |
+ K5_RKFLAG_MOD_MASTER |
+ K5_RKFLAG_MOD_ADMIN);
+ applied = TRUE;
}
}
@@ -745,6 +758,7 @@ k5_write_config_data(k5_config_data * d) {
is deleted and not in the profile file
anymore. */
d->realms[r].domain_maps[m].flags |= K5_DMFLAG_NEW;
+ applied = TRUE;
} else if (!(d->realms[r].domain_maps[m].flags &
K5_DMFLAG_DELETED) &&
(d->realms[r].domain_maps[m].flags &
@@ -753,10 +767,12 @@ k5_write_config_data(k5_config_data * d) {
realm);
d->realms[r].domain_maps[m].flags &= ~K5_DMFLAG_NEW;
+ applied = TRUE;
}
}
- d->realms[r].flags &= ~K5_RDFLAG_NEW;
+ d->realms[r].flags &= ~(K5_RDFLAG_NEW |
+ K5_RDFLAG_MODIFED);
} else if ((d->realms[r].flags & K5_RDFLAG_DELETED) &&
!(d->realms[r].flags & K5_RDFLAG_NEW)) {
@@ -774,7 +790,10 @@ k5_write_config_data(k5_config_data * d) {
sec_all[2] = values[v];
pprofile_clear_relation(profile, sec_all);
}
+ sec_all[2] = NULL;
+ pprofile_rename_section(profile, sec_all, NULL);
pprofile_free_list(values);
+ applied = TRUE;
}
rv = pprofile_get_relation_names(profile, sec_domain_realm,
@@ -794,6 +813,7 @@ k5_write_config_data(k5_config_data * d) {
values[v]);
pprofile_clear_relation(profile,
sec_domain_map);
+ applied = TRUE;
}
pprofile_release_string(maprealm);
}
@@ -806,7 +826,8 @@ k5_write_config_data(k5_config_data * d) {
deleted and is not in the profile file. */
d->realms[r].flags |= K5_RDFLAG_NEW;
- } else if (!(d->realms[r].flags & K5_RDFLAG_DELETED)) {
+ } else if (!(d->realms[r].flags & K5_RDFLAG_DELETED) &&
+ (d->realms[r].flags & K5_RDFLAG_MODIFED)) {
khm_size k;
khm_size m;
@@ -830,6 +851,8 @@ k5_write_config_data(k5_config_data * d) {
pprofile_update_relation(profile, sec_master,
host, NULL);
+ applied = TRUE;
+
/* as above, setting 'new' flag to indicate
that the item does not exist in the profile
file. */
@@ -849,7 +872,10 @@ k5_write_config_data(k5_config_data * d) {
pprofile_add_relation(profile, sec_admin,
host);
- d->realms[r].kdcs[k].flags &= ~K5_RKFLAG_NEW;
+ d->realms[r].kdcs[k].flags &= ~(K5_RKFLAG_NEW |
+ K5_RKFLAG_MOD_ADMIN |
+ K5_RKFLAG_MOD_MASTER);
+ applied = TRUE;
continue;
}
@@ -864,6 +890,7 @@ k5_write_config_data(k5_config_data * d) {
host);
}
+ applied = TRUE;
d->realms[r].kdcs[k].flags &= ~K5_RKFLAG_MOD_MASTER;
}
@@ -878,6 +905,7 @@ k5_write_config_data(k5_config_data * d) {
host, NULL);
}
+ applied = TRUE;
d->realms[r].kdcs[k].flags &= ~K5_RKFLAG_MOD_ADMIN;
}
}
@@ -895,6 +923,7 @@ k5_write_config_data(k5_config_data * d) {
pprofile_clear_relation(profile, sec_domain_map);
d->realms[r].domain_maps[m].flags |= K5_DMFLAG_NEW;
+ applied = TRUE;
} else if (!(d->realms[r].domain_maps[m].flags &
K5_DMFLAG_DELETED) &&
@@ -905,6 +934,8 @@ k5_write_config_data(k5_config_data * d) {
pprofile_add_relation(profile, sec_domain_map,
realm);
d->realms[r].domain_maps[m].flags &= ~K5_DMFLAG_NEW;
+ applied = TRUE;
+
}
}
@@ -945,6 +976,8 @@ k5_write_config_data(k5_config_data * d) {
}
d->flags = 0;
+
+ return applied;
}
/* actual dialog stuff */
@@ -1199,13 +1232,14 @@ k5_config_dlgproc(HWND hwnd,
if (HIWORD(wParam) == WMCFG_APPLY) {
khm_int32 oflags;
+ int applied;
oflags = d->flags;
- k5_write_config_data(d);
+ applied = k5_write_config_data(d);
if (d->flags != oflags) {
khui_cfg_set_flags(d->node_main,
- KHUI_CNFLAG_APPLIED,
+ (applied ? KHUI_CNFLAG_APPLIED : 0),
KHUI_CNFLAG_APPLIED |
KHUI_CNFLAG_MODIFIED);
}
@@ -2664,12 +2698,11 @@ k5_realms_dlgproc(HWND hwnd,
case KHUI_WM_CFG_NOTIFY:
/* the realms dialog receives this notification after the top
- level krb5 configuration panel has received it. Therefore,
- we assume that any changes have already been applied. When
- applying changes, we switch the mod bits off to indicate
- that the changes have been written. We just have to
- repaint the screen at this point. */
+ level krb5 configuration panel has received it. */
if (HIWORD(wParam) == WMCFG_APPLY) {
+ int applied;
+
+ applied = k5_write_config_data(d);
k5_purge_config_data(d, TRUE, TRUE, TRUE);
k5_update_realms_display(GetDlgItem(hwnd, IDC_CFG_REALMS), d);
if (d->c_realm != -1) {
@@ -2679,6 +2712,10 @@ k5_realms_dlgproc(HWND hwnd,
k5_update_kdcs_display(GetDlgItem(hwnd, IDC_CFG_KDC), NULL, 0);
k5_update_dmap_display(GetDlgItem(hwnd, IDC_CFG_DMAP), NULL, 0);
}
+ khui_cfg_set_flags(d->node_realm,
+ (applied ? KHUI_CNFLAG_APPLIED : 0),
+ KHUI_CNFLAG_APPLIED);
+
}
break;
}
diff --git a/src/windows/identity/plugins/krb5/krb5newcreds.c b/src/windows/identity/plugins/krb5/krb5newcreds.c
index d52e934cc..b9f0c075e 100644
--- a/src/windows/identity/plugins/krb5/krb5newcreds.c
+++ b/src/windows/identity/plugins/krb5/krb5newcreds.c
@@ -775,19 +775,9 @@ k5_cached_kinit_prompter(void) {
/* already expired */
goto _cleanup;
} else {
- FILETIME lifetime;
- khm_int32 t;
-
- /* make the cache expire at some point */
- GetSystemTimeAsFileTime(&current);
- khc_read_int32(csp_params, L"PromptCacheLifetime", &t);
- if (t == 0)
- t = 172800; /* 48 hours */
- TimetToFileTimeInterval(t, &lifetime);
- expiry = FtAdd(&current, &lifetime);
- iexpiry = FtToInt(&expiry);
-
- khc_write_int64(csp_prcache, L"ExpiresOn", iexpiry);
+ /* if there is no value for ExpiresOn, we assume the prompts
+ have already expired. */
+ goto _cleanup;
}
/* we found a prompt cache. We take this to imply that the
@@ -1167,9 +1157,16 @@ k5_kinit_prompter(krb5_context context,
(khm_int32) num_prompts);
GetSystemTimeAsFileTime(&current);
+#ifdef USE_PROMPT_CACHE_LIFETIME
khc_read_int32(csp_params, L"PromptCacheLifetime", &t);
if (t == 0)
t = 172800; /* 48 hours */
+#else
+ khc_read_int32(csp_params, L"MaxRenewLifetime", &t);
+ if (t == 0)
+ t = 2592000; /* 30 days */
+ t += 604800; /* + 7 days */
+#endif
TimetToFileTimeInterval(t, &lifetime);
expiry = FtAdd(&current, &lifetime);
iexpiry = FtToInt(&expiry);
diff --git a/src/windows/identity/ui/credwnd.c b/src/windows/identity/ui/credwnd.c
index b4982218e..4ed45e6d9 100644
--- a/src/windows/identity/ui/credwnd.c
+++ b/src/windows/identity/ui/credwnd.c
@@ -1037,7 +1037,8 @@ cw_del_outline(khui_credwnd_outline *o) {
o->data)
PFREE(o->data);
- if ((o->flags & KHUI_CW_O_STICKY) &&
+ if (((o->flags & KHUI_CW_O_STICKY) ||
+ (o->flags & KHUI_CW_O_RELIDENT)) &&
o->data)
kcdb_identity_release((khm_handle) o->data);
@@ -1666,7 +1667,8 @@ cw_update_outline(khui_credwnd_tbl * tbl)
prevcred = NULL;
}
- /* Add any sticky identities that we haven't seen yet */
+ /* Add any default identities with no credentials and sticky
+ identities that we haven't seen yet */
if (n_grouping > 0 &&
tbl->cols[grouping[0]].attr_id == KCDB_ATTR_ID_NAME) {
@@ -1678,6 +1680,56 @@ cw_update_outline(khui_credwnd_tbl * tbl)
wchar_t ** idarray = NULL;
int i;
+ /* see if the defualt identity is in the list */
+ {
+ khm_handle id_def = NULL;
+ wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
+ khm_size cb;
+ khm_int32 flags;
+
+ if (KHM_FAILED(kcdb_identity_get_default(&id_def))) {
+ goto done_with_defident;
+ }
+
+ kcdb_identity_get_flags(id_def, &flags);
+ cb = sizeof(idname);
+ kcdb_identity_get_name(id_def, idname, &cb);
+
+ for (o = tbl->outline; o; o = LNEXT(o)) {
+ if (!wcscmp(idname, o->header))
+ break;
+ }
+
+ if (o == NULL) {
+ o = cw_new_outline_node(idname);
+ LPUSH(&tbl->outline, o);
+ o->flags = KHUI_CW_O_VISIBLE | KHUI_CW_O_RELIDENT;
+ o->level = 0;
+ o->col = grouping[0];
+ o->data = id_def;
+ o->attr_id = KCDB_ATTR_ID;
+
+ if (flags & KCDB_IDENT_FLAG_STICKY)
+ o->flags |= KHUI_CW_O_STICKY;
+
+ o->start = n_rows;
+ o->length = 1;
+ o->idx_start = -1;
+
+ if (grouping[0] == tbl->n_cols - 1)
+ o->flags |= KHUI_CW_O_NOOUTLINE;
+
+ cw_set_tbl_row_header(tbl, n_rows, grouping[0], o);
+
+ n_rows ++;
+ } else {
+ kcdb_identity_release(id_def);
+ }
+
+ done_with_defident:
+ ;
+ }
+
if (kcdb_identity_enum(KCDB_IDENT_FLAG_STICKY,
KCDB_IDENT_FLAG_STICKY,
NULL,
@@ -1728,10 +1780,15 @@ cw_update_outline(khui_credwnd_tbl * tbl)
} else {
/* not found. create */
o = cw_new_outline_node(idarray[i]);
+ LPUSH(&tbl->outline, o);
o->flags = KHUI_CW_O_VISIBLE;
o->level = 0;
o->col = grouping[0];
o->data = (void *) h;
+ o->attr_id = KCDB_ATTR_ID;
+
+ if (grouping[0] == tbl->n_cols - 1)
+ o->flags |= KHUI_CW_O_NOOUTLINE;
}
if (o->flags & KHUI_CW_O_STICKY)
@@ -3963,22 +4020,14 @@ cw_wm_mouse(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
x += tbl->scr_left;
y += tbl->scr_top - tbl->header_height;
- if (tbl->flags & KHUI_CW_TBL_EXPIDENT) {
- int ty = 0;
-
- for (i=0; i < tbl->n_rows; i++) {
- if (tbl->rows[i].flags & KHUI_CW_ROW_EXPVIEW)
- ty += tbl->cell_height * CW_EXP_ROW_MULT;
- else
- ty += tbl->cell_height;
+ row = -1;
- if (ty > y)
- break;
+ for (i=0; i < tbl->n_rows; i++) {
+ if (y >= tbl->rows[i].r_ext.top &&
+ y < tbl->rows[i].r_ext.bottom) {
+ row = i;
+ break;
}
-
- row = i;
- } else {
- row = y / tbl->cell_height;
}
col = -1;
@@ -4006,7 +4055,7 @@ cw_wm_mouse(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
o = (khui_credwnd_outline *) tbl->rows[row].data;
/* are we on a widget then? */
- x -= tbl->cols[tbl->rows[row].col].x;
+ x -= tbl->cols[o->col].x;
if (!(o->flags & KHUI_CW_O_NOOUTLINE)) {
if(x >= 0 && x < KHUI_SMICON_CX) /* hit */ {
@@ -4116,41 +4165,14 @@ cw_wm_mouse(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
}
if(tbl->mouse_state & CW_MOUSE_WSTICKY) {
if (tbl->flags & KHUI_CW_TBL_EXPIDENT) {
- int ty = 0;
- for (i=0; i < tbl->n_rows && i < tbl->mouse_row; i++) {
- if (tbl->rows[i].flags & KHUI_CW_ROW_EXPVIEW)
- ty += tbl->cell_height * CW_EXP_ROW_MULT;
- else
- ty += tbl->cell_height;
- }
-
- r.top = ty;
-
- if (tbl->mouse_row < tbl->n_rows &&
- (tbl->rows[tbl->mouse_row].flags & KHUI_CW_ROW_EXPVIEW)) {
- r.bottom = r.top + tbl->cell_height * CW_EXP_ROW_MULT;
- } else {
- r.bottom = r.top + tbl->cell_height;
- }
-
- if (tbl->mouse_row < tbl->n_rows &&
- (tbl->rows[tbl->mouse_row].flags & KHUI_CW_ROW_HEADER)) {
- khui_credwnd_outline * o;
-
- o = (khui_credwnd_outline *) tbl->rows[tbl->mouse_row].data;
-
- if (o->flags & KHUI_CW_O_NOOUTLINE) {
- r.left = tbl->cols[tbl->mouse_col].x - tbl->scr_left;
- } else {
- r.left = KHUI_SMICON_CX * 3 / 2 + tbl->cols[tbl->mouse_col].x - tbl->scr_left;
- }
+ if (tbl->mouse_row >= 0 && tbl->mouse_row < tbl->n_rows) {
+ r = tbl->rows[tbl->mouse_row].r_ext;
+ OffsetRect(&r, -tbl->scr_left, tbl->header_height - tbl->scr_top);
r.right = r.left + KHUI_SMICON_CX;
- } else {
-#ifdef DEBUG
- assert(FALSE);
-#endif
+ InvalidateRect(tbl->hwnd, &r, TRUE);
}
+
} else {
r.left = KHUI_SMICON_CX * 3 / 2 +
tbl->cols[tbl->mouse_col].x - tbl->scr_left;
@@ -4182,41 +4204,14 @@ cw_wm_mouse(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
}
if(tbl->mouse_state & CW_MOUSE_WSTICKY) {
if (tbl->flags & KHUI_CW_TBL_EXPIDENT) {
- int ty = 0;
-
- for (i=0; i < tbl->n_rows && i < tbl->mouse_row; i++) {
- if (tbl->rows[i].flags & KHUI_CW_ROW_EXPVIEW)
- ty += tbl->cell_height * CW_EXP_ROW_MULT;
- else
- ty += tbl->cell_height;
- }
-
- r.top = ty;
-
- if (tbl->mouse_row < tbl->n_rows &&
- (tbl->rows[tbl->mouse_row].flags & KHUI_CW_ROW_EXPVIEW)) {
- r.bottom = r.top + tbl->cell_height * CW_EXP_ROW_MULT;
- } else {
- r.bottom = r.top + tbl->cell_height;
- }
- if (tbl->mouse_row < tbl->n_rows &&
- (tbl->rows[tbl->mouse_row].flags & KHUI_CW_ROW_HEADER)) {
- khui_credwnd_outline * o;
-
- o = (khui_credwnd_outline *) tbl->rows[tbl->mouse_row].data;
-
- if (o->flags & KHUI_CW_O_NOOUTLINE) {
- r.left = tbl->cols[tbl->mouse_col].x - tbl->scr_left;
- } else {
- r.left = KHUI_SMICON_CX * 3 / 2 + tbl->cols[tbl->mouse_col].x - tbl->scr_left;
- }
+ if (tbl->mouse_row >= 0 && tbl->mouse_row < tbl->n_rows) {
+ r = tbl->rows[tbl->mouse_row].r_ext;
+ OffsetRect(&r, -tbl->scr_left, tbl->header_height - tbl->scr_top);
r.right = r.left + KHUI_SMICON_CX;
- } else {
-#ifdef DEBUG
- assert(FALSE);
-#endif
+ InvalidateRect(tbl->hwnd, &r, TRUE);
}
+
} else {
r.left = KHUI_SMICON_CX * 3 / 2 +
tbl->cols[tbl->mouse_col].x - tbl->scr_left;
diff --git a/src/windows/identity/ui/credwnd.h b/src/windows/identity/ui/credwnd.h
index 42edf2842..7e7e63cba 100644
--- a/src/windows/identity/ui/credwnd.h
+++ b/src/windows/identity/ui/credwnd.h
@@ -68,6 +68,7 @@ typedef struct khui_credwnd_outline_t {
#define KHUI_CW_O_SELECTED 0x00000010
#define KHUI_CW_O_DATAALLOC 0x00000020
#define KHUI_CW_O_NOOUTLINE 0x00000040
+#define KHUI_CW_O_RELIDENT 0x00000080
typedef struct khui_credwnd_row_t {
khm_int32 flags;