Windows: Help text update for Network Identity Manager Provider
[openafs.git] / src / WINNT / netidmgr_plugin / afsnewcreds.c
1 /*
2  * Copyright (c) 2005,2006,2007,2008 Secure Endpoints Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person
5  * obtaining a copy of this software and associated documentation
6  * files (the "Software"), to deal in the Software without
7  * restriction, including without limitation the rights to use, copy,
8  * modify, merge, publish, distribute, sublicense, and/or sell copies
9  * of the Software, and to permit persons to whom the Software is
10  * furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be
13  * included in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  */
24
25 /* $Id$ */
26
27 #include<afscred.h>
28 #include<commctrl.h>
29 #include<assert.h>
30 #include<netidmgr_version.h>
31 #include<htmlhelp.h>
32 #include<help/afsplhlp.h>
33
34 /* UI stuff */
35
36 #define WMNC_AFS_UPDATE_ROWS (WMNC_USER + 1)
37
38 typedef struct tag_afs_ident_token_set {
39     khm_handle ident;
40     afs_cred_list * l;
41     khm_boolean add_new;
42     khm_boolean update_info;
43 } afs_ident_token_set;
44
45
46 void 
47 afs_cred_flush_rows(afs_cred_list * l) {
48     int i;
49
50     for(i=0; i<l->n_rows; i++) {
51         if(l->rows[i].cell)
52             PFREE(l->rows[i].cell);
53         if(l->rows[i].realm)
54             PFREE(l->rows[i].realm);
55     }
56
57     if(l->nc_rows) {
58         ZeroMemory(l->rows, sizeof(l->rows[0]) * l->nc_rows);
59     }
60
61     l->n_rows = 0;
62 }
63
64 void 
65 afs_cred_free_rows(afs_cred_list * l) {
66
67     afs_cred_flush_rows(l);
68
69     if(l->rows)
70         PFREE(l->rows);
71     l->rows = NULL;
72     l->n_rows = 0;
73     l->nc_rows = 0;
74 }
75
76 void 
77 afs_cred_assert_rows(afs_cred_list * l, int n) {
78     afs_cred_row * rows;
79
80     if(n > l->nc_rows) {
81         l->nc_rows = UBOUNDSS(n, AFS_DLG_ROW_ALLOC, AFS_DLG_ROW_ALLOC);
82         rows = PMALLOC(sizeof(afs_cred_row) * l->nc_rows);
83         ZeroMemory(rows, sizeof(afs_cred_row) * l->nc_rows);
84
85         if(l->rows) {
86             if(l->n_rows)
87                 memcpy(rows, l->rows, sizeof(afs_cred_row) * l->n_rows);
88             PFREE(l->rows);
89         }
90         l->rows = rows;
91     }
92 }
93
94 void 
95 afs_cred_delete_row(afs_cred_list * l, int i) {
96     if (i < 0 || i >= l->n_rows)
97         return;
98
99     if(i < (l->n_rows - 1)) {
100         if(l->rows[i].cell)
101             PFREE(l->rows[i].cell);
102         if(l->rows[i].realm)
103             PFREE(l->rows[i].realm);
104         memmove(&(l->rows[i]),
105                 &(l->rows[i+1]),
106                 ((l->n_rows - (i+1)) * 
107                  sizeof(l->rows[0])));
108     }
109     l->n_rows--;
110 }
111
112 afs_cred_row * 
113 afs_cred_get_new_row(afs_cred_list * l) {
114     afs_cred_row * r;
115
116     afs_cred_assert_rows(l, l->n_rows + 1);
117     r = &(l->rows[l->n_rows]);
118     l->n_rows++;
119
120     ZeroMemory(r, sizeof(*r));
121
122     return r;
123 }
124
125 afs_cred_row *
126 afs_cred_add_row_from_cred(afs_cred_list * l,
127                            khm_handle cred) {
128     khm_int32 rv;
129     afs_cred_row * row;
130     khm_size cb;
131     wchar_t cell[MAXCELLCHARS];
132     int i;
133
134     cb = sizeof(cell);
135     rv = kcdb_cred_get_attr(cred,
136                             afs_attr_cell,
137                             NULL,
138                             cell,
139                             &cb);
140 #ifdef DEBUG
141     assert(rv == KHM_ERROR_SUCCESS && cb != 0);
142 #endif
143
144     /* check if we already have the cell listed. */
145     for (i=0; i<l->n_rows; i++) {
146         if (!_wcsicmp(l->rows[i].cell, cell))
147             return &l->rows[i];
148     }
149
150     row = afs_cred_get_new_row(l);
151
152     row->cell = PMALLOC(cb);
153     StringCbCopy(row->cell, cb, cell);
154
155     cb = sizeof(row->method);
156     rv = kcdb_cred_get_attr(cred,
157                             afs_attr_method,
158                             NULL,
159                             &row->method,
160                             &cb);
161
162     if (KHM_FAILED(rv)) {
163         row->method = AFS_TOKEN_AUTO;
164         row->realm = NULL;
165         return row;
166     }
167
168     rv = kcdb_cred_get_attr(cred,
169                             afs_attr_realm,
170                             NULL,
171                             NULL,
172                             &cb);
173
174     if (rv == KHM_ERROR_TOO_LONG && cb > sizeof(wchar_t)) {
175         row->realm = PMALLOC(cb);
176 #ifdef DEBUG
177         assert(row->realm);
178 #endif
179         rv = kcdb_cred_get_attr(cred,
180                                 afs_attr_realm,
181                                 NULL,
182                                 row->realm,
183                                 &cb);
184
185         if (KHM_FAILED(rv)) {
186             if (row->realm)
187                 PFREE(row->realm);
188             row->realm = NULL;
189         }
190     } else {
191         row->realm = NULL;
192     }
193
194     return row;
195 }
196
197 khm_int32 KHMAPI
198 afs_cred_add_cred_proc(khm_handle cred, void * rock) {
199     afs_cred_list * l = (afs_cred_list *) rock;
200     khm_int32 t;
201
202     if (KHM_FAILED(kcdb_cred_get_type(cred, &t)) ||
203         t != afs_credtype_id)
204         return KHM_ERROR_SUCCESS;
205
206     afs_cred_add_row_from_cred(l, cred);
207
208     return KHM_ERROR_SUCCESS;
209 }
210
211 void
212 afs_cred_get_context_creds(afs_cred_list *l,
213                            khui_action_context * ctx) {
214     khm_handle credset = NULL;
215
216     if (KHM_FAILED(kcdb_credset_create(&credset)))
217         return;
218
219     if (KHM_FAILED(kcdb_credset_extract_filtered(credset,
220                                                  NULL,
221                                                  khui_context_cursor_filter,
222                                                  (void *) ctx)))
223         goto _cleanup;
224
225     kcdb_credset_apply(credset,
226                        afs_cred_add_cred_proc,
227                        (void *) l);
228
229  _cleanup:
230     if (credset)
231         kcdb_credset_delete(credset);
232 }
233
234 khm_int32 KHMAPI
235 afs_get_id_creds_apply_proc(khm_handle cred, void * rock) {
236     khm_int32 t;
237     afs_ident_token_set * ts;
238     afs_cred_list * l;
239     khm_handle ident;
240     wchar_t cell[MAXCELLCHARS];
241     khm_size cb;
242     int i;
243     khm_int32 cflags = 0;
244
245     ts = (afs_ident_token_set *) rock;
246     l = ts->l;
247
248     kcdb_cred_get_type(cred, &t);
249     if (t != afs_credtype_id)
250         return KHM_ERROR_SUCCESS;
251
252     cb = sizeof(cell);
253     if (KHM_FAILED(kcdb_cred_get_attr(cred, afs_attr_cell,
254                                       NULL,
255                                       cell, &cb)))
256         return KHM_ERROR_SUCCESS;
257
258     kcdb_cred_get_flags(cred, &cflags);
259
260     kcdb_cred_get_identity(cred, &ident);
261
262     if (kcdb_identity_is_equal(ident, ts->ident)) {
263
264         for (i=0; i < l->n_rows; i++) {
265             if (!_wcsicmp(l->rows[i].cell, cell)) {
266                 khm_int32 method;
267
268                 /* if the token exists, then these are implied */
269                 l->rows[i].flags =
270                     DLGROW_FLAG_EXISTS |
271                     DLGROW_FLAG_CHECKED |
272                     DLGROW_FLAG_VALID;
273
274                 if (cflags & KCDB_CRED_FLAG_EXPIRED)
275                     l->rows[i].flags |= DLGROW_FLAG_EXPIRED;
276
277                 if (ts->update_info) {
278                     wchar_t realm[KHUI_MAXCCH_NAME];
279
280                     cb = sizeof(method);
281                     if (KHM_SUCCEEDED
282                         (kcdb_cred_get_attr(cred, afs_attr_method,
283                                             NULL,
284                                             &method, &cb)) &&
285                         afs_is_valid_method_id(method))
286                         l->rows[i].method = method;
287
288                     cb = sizeof(realm);
289                     if (KHM_SUCCEEDED
290                         (kcdb_cred_get_attr(cred, afs_attr_realm,
291                                             NULL,
292                                             realm, &cb)) &&
293                         cb > sizeof(wchar_t)) {
294
295                         if (l->rows[i].realm)
296                             PFREE(l->rows[i].realm);
297                         l->rows[i].realm = PMALLOC(cb);
298                         StringCbCopy(l->rows[i].realm,
299                                      cb,
300                                      realm);
301                     }
302                 }
303                 break;
304             }
305         }
306
307         /* not found? add! */
308         if (i >= l->n_rows && ts->add_new) {
309             afs_cred_row * r;
310
311             r = afs_cred_add_row_from_cred(l, cred);
312
313             r->flags = DLGROW_FLAG_VALID | DLGROW_FLAG_CHECKED |
314                 DLGROW_FLAG_EXISTS;
315
316             if (cflags & KCDB_CRED_FLAG_EXPIRED)
317                 r->flags |= DLGROW_FLAG_EXPIRED;
318         }
319
320     } else {                    /* different identities */
321
322         for (i=0; i < l->n_rows; i++) {
323             if (!_wcsicmp(l->rows[i].cell, cell)) {
324                 l->rows[i].flags =
325                     DLGROW_FLAG_NOTOWNED | DLGROW_FLAG_EXISTS |
326                     DLGROW_FLAG_VALID | DLGROW_FLAG_CHECKED;
327                 if (cflags & KCDB_CRED_FLAG_EXPIRED)
328                     l->rows[i].flags |= DLGROW_FLAG_EXPIRED;
329             }
330         }
331
332     }
333
334     kcdb_identity_release(ident);
335
336     return KHM_ERROR_SUCCESS;
337 }
338
339 void
340 afs_remove_token_from_identities(wchar_t * cell) {
341     wchar_t * idents = NULL;
342     wchar_t * t;
343     khm_size cb_id;
344     khm_size n_id = 0;
345
346     do {
347         if (kcdb_identity_enum(KCDB_IDENT_FLAG_CONFIG,
348                                KCDB_IDENT_FLAG_CONFIG,
349                                NULL,
350                                &cb_id,
351                                &n_id) != KHM_ERROR_TOO_LONG ||
352             n_id == 0) {
353             if (idents)
354                 PFREE(idents);
355             return;
356         }
357
358         if (idents)
359             PFREE(idents);
360         idents = PMALLOC(cb_id);
361
362         if (kcdb_identity_enum(KCDB_IDENT_FLAG_CONFIG,
363                                KCDB_IDENT_FLAG_CONFIG,
364                                idents,
365                                &cb_id,
366                                &n_id) == KHM_ERROR_SUCCESS)
367             break;
368     } while(TRUE);
369
370     for (t=idents;
371          t && *t;
372          t = multi_string_next(t)) {
373
374         khm_handle h_id = NULL;
375         khm_handle csp_ident = NULL;
376         khm_handle csp_afs = NULL;
377         khm_size cb;
378         wchar_t vbuf[1024];
379         wchar_t * tbuf = NULL;
380         khm_int32 enabled = 0;
381
382         kcdb_identity_create(t, 0, &h_id);
383         if (h_id == NULL) {
384 #ifdef DEBUG
385             assert(FALSE);
386 #endif
387             continue;
388         }
389
390         if (KHM_FAILED(kcdb_identity_get_config(h_id, 0, &csp_ident)))
391             goto _cleanup_loop;
392
393         if (KHM_FAILED(khc_open_space(csp_ident, CSNAME_AFSCRED,
394                                       0, &csp_afs)))
395             goto _cleanup_loop;
396
397         if (KHM_SUCCEEDED(khc_read_int32(csp_afs, L"AFSEnabled", &enabled)) &&
398             !enabled)
399             goto _cleanup_loop;
400
401         if (khc_read_multi_string(csp_afs, L"Cells", NULL, &cb)
402             != KHM_ERROR_TOO_LONG)
403             goto _cleanup_loop;
404
405         if (cb < sizeof(vbuf))
406             tbuf = vbuf;
407         else
408             tbuf = PMALLOC(cb);
409
410         if (khc_read_multi_string(csp_afs, L"Cells", tbuf, &cb)
411             != KHM_ERROR_SUCCESS)
412             goto _cleanup_loop;
413
414         if (multi_string_find(tbuf, cell, 0) == NULL)
415             goto _cleanup_loop;
416
417         multi_string_delete(tbuf, cell, 0);
418
419         khc_write_multi_string(csp_afs, L"Cells", tbuf);
420
421     _cleanup_loop:
422         kcdb_identity_release(h_id);
423         if (csp_ident)
424             khc_close_space(csp_ident);
425         if (csp_afs)
426             khc_close_space(csp_afs);
427         if (tbuf && tbuf != vbuf)
428             PFREE(tbuf);
429     }
430
431     if (idents)
432         PFREE(idents);
433 }
434
435 khm_boolean
436 afs_check_add_token_to_identity(wchar_t * cell, khm_handle ident,
437                                 khm_handle * ident_conflict) {
438     wchar_t * idents = NULL;
439     wchar_t * t;
440     khm_size cb_id;
441     khm_size n_id = 0;
442     khm_boolean ok_to_add = TRUE;
443
444     /* check if this cell is listed for any other identity. */
445
446     do {
447         if (kcdb_identity_enum(KCDB_IDENT_FLAG_CONFIG,
448                                KCDB_IDENT_FLAG_CONFIG,
449                                NULL,
450                                &cb_id,
451                                &n_id) != KHM_ERROR_TOO_LONG ||
452             n_id == 0) {
453             if (idents)
454                 PFREE(idents);
455             return TRUE;
456         }
457
458         if (idents)
459             PFREE(idents);
460         idents = PMALLOC(cb_id);
461
462         if (kcdb_identity_enum(KCDB_IDENT_FLAG_CONFIG,
463                                KCDB_IDENT_FLAG_CONFIG,
464                                idents,
465                                &cb_id,
466                                &n_id) == KHM_ERROR_SUCCESS)
467             break;
468     } while(TRUE);
469
470     for (t=idents;
471          ok_to_add && t && *t;
472          t = multi_string_next(t)) {
473
474         khm_handle h_id = NULL;
475         khm_handle csp_ident = NULL;
476         khm_handle csp_afs = NULL;
477         khm_size cb;
478         wchar_t vbuf[1024];
479         wchar_t * tbuf = NULL;
480         khm_int32 enabled = 0;
481
482         kcdb_identity_create(t, 0, &h_id);
483         if (h_id == NULL) {
484 #ifdef DEBUG
485             assert(FALSE);
486 #endif
487             continue;
488         }
489
490         if (kcdb_identity_is_equal(h_id, ident)) {
491             kcdb_identity_release(h_id);
492             continue;
493         }
494
495         if (KHM_FAILED(kcdb_identity_get_config(h_id, 0, &csp_ident)))
496             goto _cleanup_loop;
497
498         if (KHM_FAILED(khc_open_space(csp_ident, CSNAME_AFSCRED,
499                                       0, &csp_afs)))
500             goto _cleanup_loop;
501
502         if (KHM_SUCCEEDED(khc_read_int32(csp_afs, L"AFSEnabled", &enabled)) &&
503             !enabled)
504             goto _cleanup_loop;
505
506         if (khc_read_multi_string(csp_afs, L"Cells", NULL, &cb)
507             != KHM_ERROR_TOO_LONG)
508             goto _cleanup_loop;
509
510         if (cb < sizeof(vbuf))
511             tbuf = vbuf;
512         else
513             tbuf = PMALLOC(cb);
514
515         if (khc_read_multi_string(csp_afs, L"Cells", tbuf, &cb)
516             != KHM_ERROR_SUCCESS)
517             goto _cleanup_loop;
518
519         if (multi_string_find(tbuf, cell, 0) == NULL)
520             goto _cleanup_loop;
521
522         /* we found another identity which gets tokens for the
523            same cell */
524
525         ok_to_add = FALSE;
526
527         if (ident_conflict) {
528             *ident_conflict = h_id;
529             kcdb_identity_hold(h_id);
530         }
531
532     _cleanup_loop:
533         kcdb_identity_release(h_id);
534         if (csp_ident)
535             khc_close_space(csp_ident);
536         if (csp_afs)
537             khc_close_space(csp_afs);
538         if (tbuf && tbuf != vbuf)
539             PFREE(tbuf);
540     }
541
542     if (idents)
543         PFREE(idents);
544
545     return ok_to_add;
546 }
547
548 static void
549 add_token_to_list(afs_cred_list * l,
550                   khm_handle h_gcells,
551                   HKEY hk_gcells,
552                   const wchar_t * c_cell)
553 {
554     khm_size cb;
555     int i;
556     afs_cred_row * r;
557     khm_handle h_cell = NULL;
558     HKEY       hk_cell = NULL;
559     wchar_t wbuf[MAXCELLCHARS];
560     wchar_t wmethod[KHUI_MAXCCH_NAME];
561
562     if (FAILED(StringCbLength(c_cell, (MAXCELLCHARS + 1) * sizeof(wchar_t),
563                               &cb)))
564         return;
565     cb += sizeof(wchar_t);
566
567     for (i=0; i < l->n_rows; i++) {
568         if (!_wcsicmp(l->rows[i].cell, c_cell))
569             break;
570     }
571
572     if (i < l->n_rows)
573         return;
574
575     r = afs_cred_get_new_row(l);
576
577     r->cell = PMALLOC(cb);
578     StringCbCopy(r->cell, cb, c_cell);
579
580     if (h_gcells &&
581         KHM_SUCCEEDED(khc_open_space(h_gcells, c_cell, 0, &h_cell))) {
582
583         cb = sizeof(wmethod);
584         if (KHM_SUCCEEDED(khc_read_string(h_cell, L"MethodName",
585                                           wmethod, &cb))) {
586
587             r->method = afs_get_method_id(wmethod);
588
589             /* remove the deprecated value if it is present. */
590             khc_remove_value(h_cell, L"Method", 0);
591
592         } else if (KHM_SUCCEEDED(khc_read_int32(h_cell, 
593                                                 L"Method", &i))) {
594             /* the Method property is deprecated.  We detect and
595                correct this whenever possible. */
596
597             if (!afs_is_valid_method_id(i))
598                 i = AFS_TOKEN_AUTO;
599
600             r->method = i;
601
602             afs_get_method_name(i, wmethod, sizeof(wmethod));
603
604             khc_write_string(h_cell, L"MethodName", wmethod);
605
606             khc_remove_value(h_cell, L"Method", 0);
607         } else {
608             r->method = AFS_TOKEN_AUTO;
609         }
610
611         cb = sizeof(wbuf);
612         if (KHM_SUCCEEDED(khc_read_string(h_cell, L"Realm", wbuf, &cb)) &&
613             cb > sizeof(wchar_t)) {
614             r->realm = PMALLOC(cb);
615             StringCbCopy(r->realm, cb, wbuf);
616         } else {
617             r->realm = NULL;
618         }
619
620         khc_close_space(h_cell);
621         h_cell = NULL;
622     } else if (hk_gcells &&
623                RegOpenKeyEx(hk_gcells, c_cell, 0, KEY_READ, &hk_cell) == ERROR_SUCCESS) {
624
625         DWORD cbd;
626
627         cbd = sizeof(wmethod);
628         if (RegQueryValueEx(hk_cell, L"MethodName", NULL, NULL, (LPBYTE) wmethod, &cbd) == ERROR_SUCCESS) {
629             r->method = afs_get_method_id(wmethod);
630         } else {
631             r->method = AFS_TOKEN_AUTO;
632         }
633
634         cbd = sizeof(wbuf);
635         if (RegQueryValueEx(hk_cell, L"Realm", NULL, NULL, (LPBYTE) wbuf, &cbd) == ERROR_SUCCESS) {
636             cbd += sizeof(wchar_t);
637             r->realm = PMALLOC(cbd);
638             ZeroMemory(r->realm, cbd);
639             StringCbCopy(r->realm, cbd, wbuf);
640         } else {
641             r->realm = NULL;
642         }
643
644         RegCloseKey(hk_cell);
645
646     } else {
647         r->realm = NULL;
648         r->method = AFS_TOKEN_AUTO;
649     }
650
651     r->flags = 0;
652 }
653
654
655 void 
656 afs_cred_get_identity_creds(afs_cred_list * l, 
657                             khm_handle ident,
658                             khm_boolean * penabled) {
659     khm_handle h_id = NULL;
660     khm_handle h_afs = NULL;
661     khm_handle h_cells = NULL;  /* per identity cells space */
662     khm_handle h_gcells = NULL; /* global cells space */
663     khm_boolean load_defs = TRUE;
664     khm_size cbi;
665     wchar_t * ms = NULL;
666     wchar_t * s = NULL;
667     afs_ident_token_set ts;
668     khm_int32 t;
669
670     if (penabled)
671         *penabled = TRUE;
672
673     afs_cred_flush_rows(l);
674
675     kcdb_identity_get_config(ident, 0, &h_id);
676     if(!h_id) 
677         goto _done_config;
678
679     if(KHM_FAILED(khc_open_space(h_id, CSNAME_AFSCRED, 
680                                  0, &h_afs)))
681         goto _done_config;
682
683     if (penabled) {
684         t = 1;
685         if (KHM_FAILED(khc_read_int32(h_afs, L"AFSEnabled", &t)))
686             khc_read_int32(csp_params, L"AFSEnabled", &t);
687         *penabled = !!t;
688     }
689
690     if(KHM_FAILED(khc_open_space(h_afs, L"Cells", 
691                                  0, &h_cells)))
692         goto _done_config;
693
694     if(khc_read_multi_string(h_afs, L"Cells", NULL, &cbi) != 
695        KHM_ERROR_TOO_LONG)
696         goto _done_config;
697
698     load_defs = FALSE;
699
700     ms = PMALLOC(cbi);
701     ZeroMemory(ms, cbi);
702
703     khc_read_multi_string(h_afs, L"Cells", ms, &cbi);
704
705     s = ms;
706     for(s = ms; s && *s; s = multi_string_next(s)) {
707         add_token_to_list(l, h_cells, NULL, s);
708     }
709
710     if(ms) {
711         PFREE(ms);
712         ms = NULL;
713     }
714
715  _done_config:
716
717     if (load_defs) {
718         /* We want to load defaults */
719         char buf[MAXCELLCHARS];
720         wchar_t wbuf[MAXCELLCHARS];
721         wchar_t * defcells;
722         khm_size cb_defcells;
723
724         khc_open_space(csp_params, L"Cells", 0, &h_gcells);
725
726         if (!cm_GetRootCellName(buf) &&
727             afs_check_for_cell_realm_match(ident, buf)) {
728             AnsiStrToUnicode(wbuf, sizeof(wbuf), buf);
729
730             if (afs_check_add_token_to_identity(wbuf, ident, NULL)) {
731                 add_token_to_list(l, h_gcells, NULL, wbuf);
732             }
733         }
734
735         if (khc_read_multi_string(csp_params, L"DefaultCells",
736                                   NULL, &cb_defcells) == KHM_ERROR_TOO_LONG &&
737             cb_defcells > sizeof(wchar_t) * 2) {
738             wchar_t * c_cell;
739
740             defcells = PMALLOC(cb_defcells);
741             if (defcells == NULL)
742                 goto _done_defaults;
743
744             if (KHM_FAILED(khc_read_multi_string(csp_params, L"DefaultCells",
745                                                  defcells, &cb_defcells))) {
746                 PFREE(defcells);
747                 goto _done_defaults;
748             }
749
750             for (c_cell = defcells;
751                  c_cell && *c_cell;
752                  c_cell = multi_string_next(c_cell)) {
753                 char cell[MAXCELLCHARS];
754
755                 UnicodeStrToAnsi(cell, sizeof(cell), c_cell);
756
757                 if (!afs_check_for_cell_realm_match(ident, cell))
758                     continue;
759
760                 add_token_to_list(l, h_gcells, NULL, c_cell);
761                 }
762
763             PFREE(defcells);
764         }
765
766         /* Check HKLM\Software\OpenAFS\Client\Realms\<Realm> registry key as well */
767         {
768             wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
769             wchar_t * realm;
770             wchar_t * cell=NULL;
771             khm_size cb;
772             HKEY hk_realms = NULL, hk_realm = NULL;
773
774             cb = sizeof(idname);
775             kcdb_identity_get_name(ident, idname, &cb);
776
777             realm = wcsrchr(idname, L'@');
778             if (realm == NULL || realm[1] == L'\0')
779                 goto _done_realms;
780
781             realm++;
782
783             if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\OpenAFS\\Client\\Realms", 0, KEY_READ, &hk_realms) != ERROR_SUCCESS)
784                 goto _done_realms;
785
786             if (RegOpenKeyEx(hk_realms, realm, 0, KEY_READ, &hk_realm) != ERROR_SUCCESS)
787                 goto _done_realms;
788
789             if (penabled) {
790                 DWORD enabled = 1;
791                 DWORD cbd;
792
793                 cbd = sizeof(enabled);
794
795                 if (RegQueryValueEx(hk_realm, L"AFSEnabled",
796                                     NULL, NULL, (LPBYTE) &enabled, &cbd) == ERROR_SUCCESS) {
797                     *penabled = !!enabled;
798                 }
799             }
800
801             {
802                 DWORD dwNumCells=0, dwMaxCellLen=0, dwIndex, dwCellBufSz;
803
804                 RegQueryInfoKey( hk_realm,
805                                  NULL,  /* lpClass */
806                                  NULL,  /* lpcClass */
807                                  NULL,  /* lpReserved */
808                                  &dwNumCells,  /* lpcSubKeys */
809                                  &dwMaxCellLen,  /* lpcMaxSubKeyLen */
810                                  NULL,  /* lpcMaxClassLen */
811                                  NULL, /* lpcValues */
812                                  NULL,  /* lpcMaxValueNameLen */
813                                  NULL,  /* lpcMaxValueLen */
814                                  NULL,  /* lpcbSecurityDescriptor */
815                                  NULL   /* lpftLastWriteTime */
816                                  );
817
818                 dwCellBufSz = (dwMaxCellLen + 1) * sizeof(wchar_t);
819                 cell = PMALLOC(dwCellBufSz);
820                 ZeroMemory(cell, dwCellBufSz);
821
822                 for ( dwIndex=0; dwIndex < dwNumCells; dwIndex++ ) {
823                     if (RegEnumKey( hk_realm, dwIndex, cell, dwCellBufSz) != ERROR_SUCCESS)
824                         goto _done_realms;
825
826                     if (afs_check_add_token_to_identity(cell, ident, NULL))
827                         add_token_to_list(l, NULL, hk_realm, cell);
828                 }
829             }
830
831         _done_realms:
832
833             if (hk_realm)
834                 RegCloseKey(hk_realm);
835
836             if (hk_realms)
837                 RegCloseKey(hk_realms);
838
839             if (cell)
840                 PFREE(cell);
841         }
842     }
843
844  _done_defaults:
845
846     ts.ident = ident;
847     ts.l = l;
848     ts.add_new = TRUE;
849     ts.update_info = FALSE;
850
851     kcdb_credset_apply(NULL, afs_get_id_creds_apply_proc,
852                        &ts);
853
854     if(h_id)
855         khc_close_space(h_id);
856     if(h_afs)
857         khc_close_space(h_afs);
858     if(h_cells)
859         khc_close_space(h_cells);
860     if(h_gcells)
861         khc_close_space(h_gcells);
862 }
863
864 void 
865 nc_dlg_enable(HWND hwnd, BOOL enable) {
866     if(enable) {
867         SendDlgItemMessage(hwnd, IDC_NCAFS_OBTAIN, BM_SETCHECK, 
868                            BST_CHECKED, 0);
869     } else {
870         SendDlgItemMessage(hwnd, IDC_NCAFS_OBTAIN, BM_SETCHECK, 
871                            BST_UNCHECKED, 0);
872     }
873
874     EnableWindow(GetDlgItem(hwnd,IDC_NCAFS_CELL), enable);
875     EnableWindow(GetDlgItem(hwnd,IDC_NCAFS_REALM), enable);
876     EnableWindow(GetDlgItem(hwnd,IDC_NCAFS_METHOD), enable);
877     EnableWindow(GetDlgItem(hwnd,IDC_NCAFS_TOKENLIST), enable);
878     EnableWindow(GetDlgItem(hwnd,IDC_NCAFS_ADD_TOKEN), enable);
879     EnableWindow(GetDlgItem(hwnd,IDC_NCAFS_DELETE_TOKEN), enable);
880 }
881
882 void 
883 nc_dlg_show_tooltip(HWND hwnd, 
884                     UINT_PTR id, 
885                     LPWSTR msg, 
886                     LPWSTR title, 
887                     int type, 
888                     int x, 
889                     int y)
890 {
891     afs_dlg_data * d;
892     TOOLINFO ti;
893
894     d = (afs_dlg_data *)(LONG_PTR) GetWindowLongPtr(hwnd, DWLP_USER);
895
896     if (d == NULL)
897         return;
898
899     ZeroMemory(&ti, sizeof(ti));
900     ti.cbSize = sizeof(ti);
901     ti.hwnd = hwnd;
902     ti.uId = id;
903     SendMessage(d->tooltip, TTM_GETTOOLINFO, 0, (LPARAM) &ti);
904
905     ti.hinst = hResModule;
906     ti.lpszText = msg;
907
908     SendMessage(d->tooltip, TTM_SETTOOLINFO, 0, (LPARAM) &ti);
909
910     if(IS_INTRESOURCE(title)) {
911         wchar_t wbuf[1024];
912         UINT resid;
913
914         resid = (UINT)(UINT_PTR) title;
915
916         LoadString(hResModule, resid, wbuf, ARRAYLENGTH(wbuf));
917         SendMessage(d->tooltip, TTM_SETTITLE, type, (LPARAM) wbuf);
918     } else
919         SendMessage(d->tooltip, TTM_SETTITLE, type, (LPARAM) title);
920
921     SendMessage(d->tooltip, TTM_TRACKACTIVATE, TRUE, (LPARAM) &ti);
922     SendMessage(d->tooltip, TTM_TRACKPOSITION, 0, (LPARAM) MAKELONG(x,y));
923
924     d->tooltip_visible = TRUE;
925
926     SetTimer(hwnd, DLG_TOOLTIP_TIMER_ID, DLG_TOOLTIP_TIMEOUT, NULL);
927 }
928
929 void 
930 nc_dlg_hide_tooltip(HWND hwnd, UINT_PTR id)
931 {
932     TOOLINFO ti;
933     afs_dlg_data * d;
934
935     d = (afs_dlg_data *)(LONG_PTR) GetWindowLongPtr(hwnd, DWLP_USER);
936
937     if (d == NULL)
938         return;
939
940     if(!d->tooltip_visible)
941         return;
942
943     ZeroMemory(&ti, sizeof(ti));
944     ti.cbSize = sizeof(ti);
945     ti.hwnd = hwnd;
946     ti.uId = id;
947
948     SendMessage(d->tooltip, TTM_TRACKACTIVATE, FALSE, (LPARAM) &ti);
949     d->tooltip_visible = FALSE;
950 }
951
952 void 
953 afs_dlg_update_rows(HWND hwnd, afs_dlg_data * d) {
954     HWND hwlist;
955     LVITEM lvi;
956     wchar_t wauto[256];
957     int i;
958
959     CheckDlgButton(hwnd, IDC_NCAFS_OBTAIN,
960                    (d->afs_enabled)? BST_CHECKED: BST_UNCHECKED);
961
962     hwlist = GetDlgItem(hwnd, IDC_NCAFS_TOKENLIST);
963
964     ListView_DeleteAllItems(hwlist);
965
966     if(d->creds.n_rows == 0)
967         return;
968
969     LoadString(hResModule, IDS_NC_AUTO, wauto, ARRAYLENGTH(wauto));
970
971     for(i=0; i < d->creds.n_rows; i++) {
972         wchar_t wbuf[256];
973         int flags;
974
975         ZeroMemory(&lvi, sizeof(lvi));
976
977         lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE;
978         lvi.iItem = d->creds.n_rows + 1;
979
980         lvi.stateMask = LVIS_STATEIMAGEMASK;
981         flags = d->creds.rows[i].flags;
982         if ((flags & DLGROW_FLAG_EXISTS) &&
983             (flags & DLGROW_FLAG_NOTOWNED)) {
984             lvi.state = INDEXTOSTATEIMAGEMASK(d->idx_bad_token);
985         } else if ((flags & DLGROW_FLAG_EXISTS)) {
986             lvi.state = INDEXTOSTATEIMAGEMASK(d->idx_existing_token);
987         } else {
988             lvi.state = INDEXTOSTATEIMAGEMASK(d->idx_new_token);
989         }
990
991         lvi.lParam = (LPARAM) i;
992
993         lvi.iSubItem = NCAFS_IDX_CELL;
994         lvi.pszText = d->creds.rows[i].cell;
995
996         lvi.iItem = ListView_InsertItem(hwlist, &lvi);
997
998         lvi.mask = LVIF_TEXT; /* subitems dislike lParam */
999         lvi.iSubItem = NCAFS_IDX_REALM;
1000         if(d->creds.rows[i].realm != NULL)
1001             lvi.pszText = d->creds.rows[i].realm;
1002         else
1003             lvi.pszText = wauto;
1004         ListView_SetItem(hwlist, &lvi);
1005
1006         lvi.iSubItem = NCAFS_IDX_METHOD;
1007         afs_method_describe(d->creds.rows[i].method,
1008                             KCDB_TS_SHORT,
1009                             wbuf, sizeof(wbuf));
1010         lvi.pszText = wbuf;
1011
1012         ListView_SetItem(hwlist, &lvi);
1013     }
1014 }
1015
1016 void 
1017 nc_dlg_del_token(HWND hwnd) {
1018     afs_dlg_data * d;
1019     khui_new_creds_by_type * nct;
1020
1021     d = (afs_dlg_data *)(LONG_PTR) GetWindowLongPtr(hwnd, DWLP_USER);
1022
1023     if (d == NULL)
1024         return;
1025
1026     if (d->nc)
1027         khui_cw_find_type(d->nc, afs_credtype_id, &nct);
1028
1029     if(ListView_GetSelectedCount(GetDlgItem(hwnd, IDC_NCAFS_TOKENLIST)) == 0) {
1030         wchar_t cell[KCDB_MAXCCH_NAME];
1031         int i;
1032
1033         /* nothing is selected in the list view */
1034         /* we delete the row that matches the current contents of the
1035         cell edit control */
1036         cell[0] = 0;
1037         GetDlgItemText(hwnd, IDC_NCAFS_CELL, cell, ARRAYLENGTH(cell));
1038         for(i=0; i<d->creds.n_rows; i++) {
1039             if(!_wcsicmp(d->creds.rows[i].cell, cell)) {
1040                 /* found it */
1041                 afs_cred_delete_row(&d->creds, i);
1042                 afs_dlg_update_rows(hwnd, d);
1043                 d->dirty = TRUE;
1044                 break;
1045             }
1046         }
1047     } else {
1048         /* something is selected in the token list view */
1049         /* we delete that */
1050         HWND hw;
1051         LVITEM lvi;
1052         int idx;
1053         int row;
1054         BOOL deleted = FALSE;
1055
1056         hw = GetDlgItem(hwnd, IDC_NCAFS_TOKENLIST);
1057         idx = -1;
1058         do {
1059             idx = ListView_GetNextItem(hw, idx, LVNI_SELECTED);
1060             if(idx >= 0) {
1061                 ZeroMemory(&lvi, sizeof(lvi));
1062                 lvi.iItem = idx;
1063                 lvi.iSubItem = 0;
1064                 lvi.mask = LVIF_PARAM;
1065                 if(!ListView_GetItem(hw, &lvi))
1066                     continue;
1067                 row = (int) lvi.lParam;
1068                 if(row >= 0 && row < d->creds.n_rows) {
1069                     d->creds.rows[row].flags |= DLGROW_FLAG_DELETED;
1070                     deleted = TRUE;
1071                 }
1072             }
1073         } while(idx != -1);
1074
1075         if(deleted) {
1076             for(idx = 0; idx < d->creds.n_rows; idx ++) {
1077                 if(d->creds.rows[idx].flags & DLGROW_FLAG_DELETED) {
1078                     afs_cred_delete_row(&d->creds, idx);
1079                     idx--; /* we have to look at the current item again */
1080                 }
1081             }
1082
1083             d->dirty = TRUE;
1084             afs_dlg_update_rows(hwnd, d);
1085         }
1086     }
1087
1088     if (d->nc)
1089         SendMessage(d->nc->hwnd, KHUI_WM_NC_NOTIFY, 
1090                     MAKEWPARAM(0, WMNC_UPDATE_CREDTEXT), 0);
1091     else if (d->config_dlg && d->dirty)
1092         khui_cfg_set_flags_inst(&d->cfg, KHUI_CNFLAG_MODIFIED,
1093                                 KHUI_CNFLAG_MODIFIED);
1094 }
1095
1096 void 
1097 nc_dlg_add_token(HWND hwnd) {
1098     afs_dlg_data * d;
1099     afs_cred_row * prow;
1100     afs_cred_row trow;
1101     khui_new_creds_by_type * nct;
1102     wchar_t buf[256];
1103     int idx;
1104     size_t n;
1105     size_t cb;
1106     int i;
1107     BOOL new_row = FALSE;
1108     khm_handle ident = NULL;
1109
1110     d = (afs_dlg_data *)(LONG_PTR) GetWindowLongPtr(hwnd, DWLP_USER);
1111
1112     if (d == NULL)
1113         return;
1114
1115     if (d->nc)
1116         khui_cw_find_type(d->nc, afs_credtype_id, &nct);
1117     else
1118         nct = NULL;
1119
1120     if((n = SendDlgItemMessage(hwnd, IDC_NCAFS_CELL, WM_GETTEXT, 
1121                                (WPARAM) ARRAYLENGTH(buf), (LPARAM) buf)) 
1122        == 0)
1123     {
1124         /* probably should indicate that user should type something */
1125         RECT r;
1126         GetWindowRect(GetDlgItem(hwnd, IDC_NCAFS_CELL), &r);
1127         nc_dlg_show_tooltip(hwnd, 
1128                             0, 
1129                             MAKEINTRESOURCE(IDS_NC_TT_NO_CELL), 
1130                             MAKEINTRESOURCE(IDS_NC_TT_CANT_ADD), 
1131                             2, (r.left + r.right)/ 2, r.bottom);
1132         return;
1133     }
1134
1135     if(n != wcsspn(buf, AFS_VALID_CELL_CHARS)) {
1136         RECT r;
1137         GetWindowRect(GetDlgItem(hwnd, IDC_NCAFS_CELL), &r);
1138         nc_dlg_show_tooltip(hwnd, 
1139                             0, 
1140                             MAKEINTRESOURCE(IDS_NC_TT_MALFORMED_CELL), 
1141                             MAKEINTRESOURCE(IDS_NC_TT_CANT_ADD), 
1142                             2, (r.left + r.right)/2, r.bottom);
1143         return;
1144     }
1145
1146     /* check if this is already listed */
1147     for(i=0;i<d->creds.n_rows;i++) {
1148         if(!_wcsicmp(buf, d->creds.rows[i].cell))
1149             break;
1150     }
1151
1152     if(i < d->creds.n_rows) {
1153         new_row = FALSE;
1154
1155         prow = &(d->creds.rows[i]);
1156     } else {
1157         new_row = TRUE;
1158         prow = NULL;
1159     }
1160
1161     ZeroMemory(&trow, sizeof(trow));
1162
1163     cb = (n+1) * sizeof(wchar_t);
1164     trow.cell = PMALLOC(cb);
1165     StringCbCopy(trow.cell, cb, buf);
1166
1167     /* now for the realm */
1168     do {
1169         idx = (int) SendDlgItemMessage(hwnd, IDC_NCAFS_REALM, 
1170                                        CB_GETCURSEL, 0, 0);
1171         if(idx != CB_ERR) {
1172             int lp;
1173             lp = (int) SendDlgItemMessage(hwnd, IDC_NCAFS_REALM, 
1174                                           CB_GETITEMDATA, idx, 0);
1175             if(lp != CB_ERR && lp) /* this is the 'determine realm
1176                                       automatically' item */
1177             {
1178                 trow.realm = NULL;
1179                 break;
1180             }
1181         }
1182
1183         if((n = SendDlgItemMessage(hwnd, IDC_NCAFS_REALM, WM_GETTEXT, 
1184                                    ARRAYLENGTH(buf), (LPARAM) buf)) == 0) {
1185             RECT r;
1186             GetWindowRect(GetDlgItem(hwnd, IDC_NCAFS_REALM), &r);
1187             nc_dlg_show_tooltip(hwnd, 
1188                                 0, 
1189                                 MAKEINTRESOURCE(IDS_NC_TT_NO_REALM), 
1190                                 MAKEINTRESOURCE((new_row)?
1191                                                 IDS_NC_TT_CANT_ADD:
1192                                                 IDS_NC_TT_CANT_UPDATE),
1193                                 2, (r.left + r.right)/2, r.bottom);
1194             goto _error_exit;
1195         }
1196
1197         if(n != wcsspn(buf, AFS_VALID_REALM_CHARS)) {
1198             RECT r;
1199             GetWindowRect(GetDlgItem(hwnd, IDC_NCAFS_REALM), &r);
1200             nc_dlg_show_tooltip(hwnd,
1201                                 0, 
1202                                 MAKEINTRESOURCE(IDS_NC_TT_MALFORMED_REALM),
1203                                 MAKEINTRESOURCE((new_row)?
1204                                                 IDS_NC_TT_CANT_ADD:
1205                                                 IDS_NC_TT_CANT_UPDATE), 
1206                                 2, (r.left + r.right)/2, r.bottom);
1207             goto _error_exit;
1208         }
1209
1210         cb = (n+1) * sizeof(wchar_t);
1211         trow.realm = PMALLOC(cb);
1212         StringCbCopy(trow.realm, cb, buf);
1213
1214     } while(FALSE);
1215
1216     idx = (int)SendDlgItemMessage(hwnd, IDC_NCAFS_METHOD, 
1217                                   CB_GETCURSEL, 0, 0);
1218     if (idx != CB_ERR) {
1219         trow.method = (afs_tk_method)
1220             SendDlgItemMessage(hwnd, IDC_NCAFS_METHOD, CB_GETITEMDATA, 
1221                                idx, 0);
1222     } else {
1223         trow.method = AFS_TOKEN_AUTO;
1224     }
1225
1226     if (d->nc &&
1227         d->nc->n_identities > 0 &&
1228         d->nc->identities[0]) {
1229         
1230         ident = d->nc->identities[0];
1231
1232     } else if (d->ident) {
1233
1234         ident = d->ident;
1235         
1236     }
1237
1238     if(new_row) {
1239         khm_boolean ok_to_add = TRUE;
1240
1241         if (ident) {
1242             khm_handle id_conf = NULL;
1243
1244             ok_to_add =
1245                 afs_check_add_token_to_identity(trow.cell,
1246                                                 ident,
1247                                                 &id_conf);
1248
1249             if (!ok_to_add) {
1250 #if KH_VERSION_API >= 5
1251                 khui_alert * a;
1252                 wchar_t wbuf[512];
1253                 wchar_t wfmt[128];
1254                 wchar_t widname[KCDB_IDENT_MAXCCH_NAME];
1255                 khm_size cb;
1256
1257 #ifdef DEBUG
1258                 assert(id_conf);
1259 #endif
1260                 khui_alert_create_empty(&a);
1261
1262                 cb = sizeof(widname);
1263                 kcdb_identity_get_name(id_conf, widname, &cb);
1264
1265                 LoadString(hResModule, IDS_NC_TT_CONFLICT,
1266                            wfmt, ARRAYLENGTH(wfmt));
1267                 StringCbPrintf(wbuf, sizeof(wbuf),
1268                                wfmt, trow.cell, widname);
1269                 khui_alert_set_message(a, wbuf);
1270
1271                 LoadString(hResModule, IDS_NC_TT_PROBLEM,
1272                            wbuf, ARRAYLENGTH(wbuf));
1273                 khui_alert_set_title(a, wbuf);
1274
1275                 khui_alert_add_command(a, KHUI_PACTION_KEEP);
1276                 khui_alert_add_command(a, KHUI_PACTION_REMOVE);
1277                 khui_alert_add_command(a, KHUI_PACTION_CANCEL);
1278
1279                 khui_alert_set_severity(a, KHERR_INFO);
1280
1281                 khui_alert_show_modal(a);
1282
1283                 ok_to_add = TRUE;
1284
1285                 if (a->response == KHUI_PACTION_REMOVE) {
1286                     afs_remove_token_from_identities(trow.cell);
1287                 } else if (a->response == KHUI_PACTION_CANCEL) {
1288                     ok_to_add = FALSE;
1289                 }
1290
1291                 khui_alert_release(a);
1292 #else
1293                 wchar_t widname[KCDB_IDENT_MAXCCH_NAME];
1294                 wchar_t wtitle[64];
1295                 wchar_t wmsg[512];
1296                 wchar_t wfmt[128];
1297                 khm_size cb;
1298                 int r;
1299
1300 #ifdef DEBUG
1301                 assert(id_conf);
1302 #endif
1303
1304                 cb = sizeof(widname);
1305                 kcdb_identity_get_name(id_conf, widname, &cb);
1306                 LoadString(hResModule, IDS_NC_TT_PROBLEM,
1307                            wtitle, ARRAYLENGTH(wtitle));
1308                 LoadString(hResModule, IDS_NC_TT_CONFLICTM,
1309                            wfmt, ARRAYLENGTH(wfmt));
1310                 StringCbPrintf(wmsg, sizeof(wmsg), wfmt,
1311                                trow.cell, widname);
1312                 r = MessageBox(NULL, wmsg, wtitle,
1313                                MB_YESNOCANCEL | MB_ICONWARNING |
1314                                MB_APPLMODAL);
1315
1316                 ok_to_add = TRUE;
1317                 if (r == IDNO) {
1318                     afs_remove_token_from_identities(trow.cell);
1319                 } else if (r == IDCANCEL) {
1320                     ok_to_add = FALSE;
1321                 }
1322 #endif
1323
1324                 kcdb_identity_release(id_conf);
1325             }
1326
1327             if (!ok_to_add)
1328                 goto _error_exit;
1329         }
1330
1331         prow = afs_cred_get_new_row(&d->creds);
1332     } else {
1333         if (prow->cell)
1334             PFREE(prow->cell);
1335
1336         if(prow->realm)
1337             PFREE(prow->realm);
1338
1339         ZeroMemory(prow, sizeof(*prow));
1340     }
1341
1342     *prow = trow;
1343
1344     if (ident) {
1345         afs_ident_token_set ts;
1346
1347         ts.ident = ident;
1348         ts.l = &d->creds;
1349         ts.add_new = FALSE;
1350         ts.update_info = FALSE;
1351
1352         kcdb_credset_apply(NULL, afs_get_id_creds_apply_proc,
1353                            &ts);
1354     }
1355
1356     afs_dlg_update_rows(hwnd, d);
1357
1358     d->dirty = TRUE;
1359
1360     if (d->nc)
1361         SendMessage(d->nc->hwnd, KHUI_WM_NC_NOTIFY, 
1362                     MAKEWPARAM(0, WMNC_UPDATE_CREDTEXT), 0);
1363     else if (d->config_dlg) {
1364         khui_cfg_set_flags_inst(&d->cfg,
1365                                 KHUI_CNFLAG_MODIFIED,
1366                                 KHUI_CNFLAG_MODIFIED);
1367     }
1368
1369     return;
1370
1371 _error_exit:
1372     if(trow.realm)
1373         PFREE(trow.realm);
1374     if(trow.cell)
1375         PFREE(trow.cell);
1376 }
1377
1378 /* this is shared between the new credentials window and the AFS per
1379    identity configuration dialog. */
1380 INT_PTR CALLBACK 
1381 afs_dlg_proc(HWND hwnd,
1382              UINT uMsg,
1383              WPARAM wParam,
1384              LPARAM lParam)
1385 {
1386     switch(uMsg) {
1387     case WM_INITDIALOG:
1388         {
1389             HWND hw;
1390             HIMAGELIST hw_ilist;
1391             afs_dlg_data * d;
1392             khui_new_creds_by_type * nct = NULL;
1393             RECT r;
1394
1395             d = PMALLOC(sizeof(*d));
1396             ZeroMemory(d, sizeof(*d));
1397
1398             InitializeCriticalSection(&d->cs);
1399
1400             /* lParam is a pointer to a khui_new_creds structure */
1401             d->nc = (khui_new_creds *) lParam;
1402
1403             if (d->nc)
1404                 khui_cw_find_type(d->nc, afs_credtype_id, &nct);
1405
1406 #pragma warning(push)
1407 #pragma warning(disable: 4244)
1408             SetWindowLongPtr(hwnd, DWLP_USER, (LPARAM) d);
1409 #pragma warning(pop)
1410
1411             EnterCriticalSection(&d->cs);
1412
1413             if (nct)
1414                 nct->aux = (LPARAM) d;
1415
1416             /* create the tooltip window */
1417             d->tooltip = 
1418                 CreateWindowEx(WS_EX_TOPMOST,
1419                                TOOLTIPS_CLASS,
1420                                NULL,
1421                                WS_POPUP | TTS_BALLOON | TTS_ALWAYSTIP,
1422                                CW_USEDEFAULT, CW_USEDEFAULT,
1423                                CW_USEDEFAULT, CW_USEDEFAULT,
1424                                hwnd,  /* make this an owned window, so
1425                                          we don't have to worry about
1426                                          destroying it */
1427                                NULL,
1428                                hInstance,
1429                                NULL);
1430
1431             SetWindowPos(d->tooltip,
1432                          HWND_TOPMOST,
1433                          0,
1434                          0,
1435                          0,
1436                          0,
1437                          SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
1438
1439             {
1440                 TOOLINFO ti;
1441
1442                 ZeroMemory(&ti, sizeof(ti));
1443                 ti.cbSize = sizeof(ti);
1444                 ti.uFlags = TTF_TRACK;
1445                 ti.hwnd = hwnd;
1446                 ti.uId = 0;
1447                 ti.hinst = hResModule;
1448                 ti.lpszText = L"";
1449                 GetClientRect(hwnd, &(ti.rect));
1450
1451                 SendMessage(d->tooltip, TTM_ADDTOOL, 0, (LPARAM) &ti);
1452             }
1453
1454             /* we only initialize the constant bits here. */
1455             hw = GetDlgItem(hwnd, IDC_NCAFS_TOKENLIST);
1456
1457             GetClientRect(hw, &r);
1458
1459             /* set the list view status icons */
1460             hw_ilist = ImageList_Create(GetSystemMetrics(SM_CXSMICON),
1461                                         GetSystemMetrics(SM_CYSMICON),
1462                                         ILC_COLOR8 | ILC_MASK,
1463                                         4, 4);
1464 #ifdef DEBUG
1465             assert(hw_ilist);
1466 #endif
1467             {
1468                 HICON hi;
1469
1470                 hi = LoadImage(hResModule, MAKEINTRESOURCE(IDI_NC_NEW),
1471                                IMAGE_ICON,
1472                                GetSystemMetrics(SM_CXSMICON),
1473                                GetSystemMetrics(SM_CYSMICON),
1474                                LR_DEFAULTCOLOR);
1475
1476                 d->idx_new_token = ImageList_AddIcon(hw_ilist, hi) + 1;
1477
1478                 DestroyIcon(hi);
1479
1480                 hi = LoadImage(hResModule, MAKEINTRESOURCE(IDI_NC_EXIST),
1481                                IMAGE_ICON,
1482                                GetSystemMetrics(SM_CXSMICON),
1483                                GetSystemMetrics(SM_CYSMICON),
1484                                LR_DEFAULTCOLOR);
1485                 d->idx_existing_token = ImageList_AddIcon(hw_ilist, hi) + 1;
1486
1487                 DestroyIcon(hi);
1488
1489                 hi = LoadImage(hResModule,
1490                                MAKEINTRESOURCE(IDI_NC_NOTOWNED),
1491                                IMAGE_ICON,
1492                                GetSystemMetrics(SM_CXSMICON),
1493                                GetSystemMetrics(SM_CYSMICON),
1494                                LR_DEFAULTCOLOR);
1495                 d->idx_bad_token = ImageList_AddIcon(hw_ilist, hi) + 1 ;
1496
1497                 DestroyIcon(hi);
1498             }
1499
1500             ListView_SetImageList(hw, hw_ilist, LVSIL_STATE);
1501
1502             ListView_DeleteAllItems(hw);
1503
1504             /* set the columns */
1505             {
1506                 LVCOLUMN lc;
1507                 wchar_t wbuf[256];
1508
1509                 lc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT;
1510                 lc.fmt = LVCFMT_LEFT;
1511                 lc.cx = ((r.right - r.left) * 2) / 5;
1512                 LoadString(hResModule, IDS_NCAFS_COL_CELL, 
1513                            wbuf, ARRAYLENGTH(wbuf));
1514                 lc.pszText = wbuf;
1515
1516                 ListView_InsertColumn(hw, 0, &lc);
1517
1518                 lc.mask |= LVCF_SUBITEM;
1519                 //lc.cx is the same as above
1520                 lc.iSubItem = NCAFS_IDX_REALM;
1521                 LoadString(hResModule, IDS_NCAFS_COL_REALM, 
1522                            wbuf, ARRAYLENGTH(wbuf));
1523
1524                 ListView_InsertColumn(hw, 1, &lc);
1525
1526                 lc.cx = ((r.right - r.left) * 1) / 5;
1527                 lc.iSubItem = NCAFS_IDX_METHOD;
1528                 LoadString(hResModule, IDS_NCAFS_COL_METHOD, 
1529                            wbuf, ARRAYLENGTH(wbuf));
1530
1531                 ListView_InsertColumn(hw, 2, &lc);
1532             }
1533
1534             /* Set the items for the 'method' combo box */
1535             hw = GetDlgItem(hwnd, IDC_NCAFS_METHOD);
1536
1537             {
1538                 wchar_t wbuf[KHUI_MAXCB_SHORT_DESC];
1539                 afs_tk_method method = -1;
1540                 int idx;
1541
1542                 SendMessage(hw, CB_RESETCONTENT, 0, 0);
1543
1544                 while((method = afs_get_next_method_id(method)) >= 0) {
1545                     afs_method_describe(method, KCDB_TS_SHORT,
1546                                         wbuf, sizeof(wbuf));
1547                     idx = (int)SendMessage(hw, CB_INSERTSTRING,
1548                                            (WPARAM) -1, (LPARAM) wbuf);
1549 #ifdef DEBUG
1550                     assert(idx != CB_ERR);
1551 #endif
1552                     SendMessage(hw, CB_SETITEMDATA, (WPARAM) idx,
1553                                 (LPARAM)  method);
1554                 }
1555
1556                 /* finally, set the current selection to auto, which
1557                    is the first method returned by
1558                    afs_get_next_method_id() */
1559                 SendMessage(hw, CB_SETCURSEL, 0, 0);
1560             }
1561
1562             d->afs_enabled = TRUE;
1563             SendDlgItemMessage(hwnd, IDC_NCAFS_OBTAIN, 
1564                                BM_SETCHECK, BST_CHECKED, 0);
1565
1566             SendDlgItemMessage(hwnd, IDC_NCAFS_CELL, CB_LIMITTEXT, MAXCELLCHARS-1, 0);
1567             SendDlgItemMessage(hwnd, IDC_NCAFS_REALM, CB_LIMITTEXT, MAXKTCREALMLEN-1, 0);
1568             SendDlgItemMessage(hwnd, IDC_NCAFS_METHOD, CB_LIMITTEXT, KCDB_MAXCCH_NAME-1, 0);
1569
1570             LeaveCriticalSection(&d->cs);
1571
1572             /* the cells and realms combo boxes need to be filled
1573                in the plugin thread since that requires making
1574                potentially blocking and non-thread safe calls */
1575         }
1576         return TRUE;
1577
1578     case WM_DESTROY:
1579         {
1580             afs_dlg_data * d;
1581             khui_new_creds_by_type * nct;
1582
1583             d = (afs_dlg_data *)(LONG_PTR) 
1584                 GetWindowLongPtr(hwnd, DWLP_USER);
1585
1586             if (d == NULL)
1587                 return TRUE;
1588
1589             EnterCriticalSection(&d->cs);
1590
1591             if (d->nc) {
1592                 khui_cw_find_type(d->nc, afs_credtype_id, &nct);
1593
1594                 nct->aux = (LPARAM) NULL;
1595             }
1596
1597             afs_cred_free_rows(&d->creds);
1598
1599             LeaveCriticalSection(&d->cs);
1600             DeleteCriticalSection(&d->cs);
1601
1602             PFREE(d);
1603
1604             SetWindowLongPtr(hwnd, DWLP_USER, 0);
1605         }
1606         return TRUE;
1607
1608     case WM_COMMAND:
1609         {
1610             afs_dlg_data * d;
1611             khui_new_creds_by_type * nct;
1612
1613             d = (afs_dlg_data *)(LONG_PTR) 
1614                 GetWindowLongPtr(hwnd, DWLP_USER);
1615
1616             if (d == NULL)
1617                 return FALSE;
1618
1619             EnterCriticalSection(&d->cs);
1620
1621             if (d->nc)
1622                 khui_cw_find_type(d->nc, afs_credtype_id, &nct);
1623             else
1624                 nct = NULL;
1625
1626             nc_dlg_hide_tooltip(hwnd, 0);
1627
1628             /* Handle WM_COMMAND */
1629             switch(wParam) {
1630             case MAKEWPARAM(IDC_NCAFS_OBTAIN, BN_CLICKED):
1631                 {
1632                     BOOL c;
1633                     c = (SendDlgItemMessage(hwnd, IDC_NCAFS_OBTAIN, 
1634                                             BM_GETCHECK, 0, 0) 
1635                          == BST_CHECKED);
1636                     d->afs_enabled = c;
1637                     d->dirty = TRUE;
1638                     if (d->nc)
1639                         khui_cw_enable_type(d->nc, afs_credtype_id, c);
1640                     else if (d->config_dlg)
1641                         khui_cfg_set_flags_inst(&d->cfg,
1642                                                 KHUI_CNFLAG_MODIFIED,
1643                                                 KHUI_CNFLAG_MODIFIED);
1644                     nc_dlg_enable(hwnd, c);
1645                 }
1646                 break;
1647
1648             case MAKEWPARAM(IDC_NCAFS_ADD_TOKEN, BN_CLICKED):
1649                 {
1650                     nc_dlg_add_token(hwnd);
1651                 }
1652                 break;
1653
1654             case MAKEWPARAM(IDC_NCAFS_DELETE_TOKEN, BN_CLICKED):
1655                 {
1656                     nc_dlg_del_token(hwnd);
1657                 }
1658                 break;
1659             }
1660
1661             LeaveCriticalSection(&d->cs);
1662         }
1663         return TRUE;
1664
1665     case KHUI_WM_NC_NOTIFY:
1666         {
1667             afs_dlg_data * d;
1668             khui_new_creds_by_type * nct;
1669
1670             d = (afs_dlg_data *)(LONG_PTR) 
1671                 GetWindowLongPtr(hwnd, DWLP_USER);
1672
1673             if (d == NULL)
1674                 return TRUE;
1675
1676             EnterCriticalSection(&d->cs);
1677
1678             if (d->nc)
1679                 khui_cw_find_type(d->nc, afs_credtype_id, &nct);
1680             else
1681                 nct = NULL;
1682
1683             switch(HIWORD(wParam)) {
1684             case WMNC_DIALOG_SETUP:
1685                 {
1686                     SendDlgItemMessage(hwnd, IDC_NCAFS_CELL, 
1687                                        CB_RESETCONTENT, 0, 0);
1688                     
1689                     /* load the LRU cells */
1690                     {
1691                         wchar_t * buf;
1692                         wchar_t *s;
1693                         khm_size cbbuf;
1694
1695                         if(khc_read_multi_string(csp_params, L"LRUCells", 
1696                                                  NULL, &cbbuf) == 
1697                            KHM_ERROR_TOO_LONG) {
1698                             buf = PMALLOC(cbbuf);
1699                             khc_read_multi_string(csp_params, L"LRUCells", 
1700                                                   buf, &cbbuf);
1701                             s = buf;
1702                             while(*s) {
1703                                 SendDlgItemMessage(hwnd, IDC_NCAFS_CELL, 
1704                                                    CB_ADDSTRING, 0, (LPARAM) s);
1705                                 s += wcslen(s) + 1;
1706                             }
1707                             PFREE(buf);
1708                         }
1709                     }
1710
1711                     /* now, if the root cell is not in the LRU, add it */
1712                     {
1713                         char buf[256];
1714                         wchar_t wbuf[256];
1715
1716                         if(!cm_GetRootCellName(buf)) {
1717                             AnsiStrToUnicode(wbuf, sizeof(wbuf), buf);
1718                             if(SendDlgItemMessage(hwnd,
1719                                                   IDC_NCAFS_CELL,
1720                                                   CB_FINDSTRINGEXACT,
1721                                                   (WPARAM) -1,
1722                                                   (LPARAM) wbuf) == CB_ERR) {
1723                                 SendDlgItemMessage(hwnd, IDC_NCAFS_CELL, 
1724                                                    CB_ADDSTRING, 
1725                                                    0, (LPARAM) wbuf);
1726                             }
1727                             SendDlgItemMessage(hwnd, IDC_NCAFS_CELL, 
1728                                                CB_SELECTSTRING, 
1729                                                (WPARAM)-1, (LPARAM) wbuf);
1730                         }
1731                     }
1732
1733                     SendDlgItemMessage(hwnd, IDC_NCAFS_REALM, 
1734                                        CB_RESETCONTENT, 0, 0);
1735
1736                     /* as for the realms, we have a special one here */
1737                     {
1738                         wchar_t wbuf[256];
1739                         int idx;
1740
1741                         LoadString(hResModule, IDS_NC_REALM_AUTO, wbuf, 
1742                                    (int) ARRAYLENGTH(wbuf));
1743                         idx = (int) SendDlgItemMessage(hwnd, IDC_NCAFS_REALM, 
1744                                                        CB_ADDSTRING, 0, 
1745                                                        (LPARAM) wbuf);
1746                         /* item data for the realm strings is the
1747                            answer to the question, "is this the
1748                            'determine realm automatically' item?" */
1749                         SendDlgItemMessage(hwnd, IDC_NCAFS_REALM, 
1750                                            CB_SETITEMDATA, idx, TRUE);
1751                         SendDlgItemMessage(hwnd, IDC_NCAFS_REALM, 
1752                                            CB_SELECTSTRING, 
1753                                            (WPARAM)-1, (LPARAM) wbuf);
1754                     }
1755
1756                     /* load the LRU realms */
1757                     {
1758                         wchar_t * buf;
1759                         wchar_t *s;
1760                         int idx;
1761                         khm_size cbbuf;
1762
1763                         if(khc_read_multi_string(csp_params, L"LRURealms", 
1764                                                  NULL, &cbbuf) == 
1765                            KHM_ERROR_TOO_LONG) {
1766                             buf = PMALLOC(cbbuf);
1767                             khc_read_multi_string(csp_params, L"LRURealms", 
1768                                                   buf, &cbbuf);
1769                             s = buf;
1770                             while(*s) {
1771                                 if(SendDlgItemMessage(hwnd, IDC_NCAFS_REALM, 
1772                                                       CB_FINDSTRINGEXACT, 
1773                                                       (WPARAM)-1,
1774                                                       (LPARAM) s) == CB_ERR) {
1775                                     idx = 
1776                                         (int)
1777                                         SendDlgItemMessage(hwnd, 
1778                                                            IDC_NCAFS_REALM, 
1779                                                            CB_ADDSTRING, 
1780                                                            0, (LPARAM) s);
1781                                     SendDlgItemMessage(hwnd, IDC_NCAFS_REALM, 
1782                                                        CB_SETITEMDATA, 
1783                                                        idx, FALSE);
1784                                 }
1785
1786                                 s += wcslen(s) + 1;
1787                             }
1788                             PFREE(buf);
1789                         }
1790                     }
1791
1792                     if (d->nc)
1793                         khui_cw_enable_type(d->nc, afs_credtype_id, 
1794                                             d->afs_enabled);
1795
1796                     nc_dlg_enable(hwnd, d->afs_enabled);
1797
1798                     afs_dlg_update_rows(hwnd, d);
1799                 }
1800                 break;
1801
1802             case WMNC_UPDATE_CREDTEXT:
1803                 {
1804                     wchar_t wformat[256];
1805                     wchar_t wstr[2048];
1806                     khm_int32 flags;
1807
1808                     if(nct->credtext) {
1809                         PFREE(nct->credtext);
1810                         nct->credtext = NULL;
1811                     }
1812
1813 #ifdef DEBUG
1814                     assert(d->nc);
1815 #endif
1816
1817                     if (d->nc->n_identities == 0 ||
1818                         KHM_FAILED(kcdb_identity_get_flags(d->nc->identities[0],
1819                                                            &flags)) ||
1820                         !(flags & KCDB_IDENT_FLAG_VALID))
1821                         /* in this case, we don't show any credential text */
1822                         break;
1823
1824                     wstr[0] = 0;
1825
1826                     if(!d->afs_enabled) {
1827                         LoadString(hResModule, IDS_AFS_CREDTEXT_DIS, 
1828                                    wstr, ARRAYLENGTH(wstr));
1829                     } else {
1830                         if(d->creds.n_rows == 0) {
1831                             LoadString(hResModule, IDS_AFS_CREDTEXT_0, 
1832                                        wstr, ARRAYLENGTH(wstr));
1833                         } else if(d->creds.n_rows == 1) {
1834                             LoadString(hResModule, IDS_AFS_CREDTEXT_1, 
1835                                        wformat, ARRAYLENGTH(wformat));
1836                             StringCbPrintf(wstr, sizeof(wstr), wformat, 
1837                                            d->creds.rows[0].cell);
1838                         } else {
1839                             int i;
1840                             wchar_t wcells[1024];
1841
1842                             LoadString(hResModule, IDS_AFS_CREDTEXT_N, 
1843                                        wformat, ARRAYLENGTH(wformat));
1844                             wcells[0] = 0;
1845                             for(i=0; i<d->creds.n_rows; i++) {
1846                                 if(i > 0)
1847                                     StringCbCat(wcells, sizeof(wcells), 
1848                                                 L", ");
1849                                 if(FAILED(StringCbCat(wcells, 
1850                                                       sizeof(wcells), 
1851                                                       d->creds.rows[i].cell))) {
1852                                     size_t cch;
1853                                     /* looks like we overflowed */
1854                                     /* add an ellipsis at the end */
1855                                     StringCchLength(wcells, ARRAYLENGTH(wcells), &cch);
1856                                     cch = min(ARRAYLENGTH(wcells) - 4, cch);
1857                                     StringCchCopy(wcells + cch, 4, L"...");
1858
1859                                     break;
1860                                 }
1861                             }
1862
1863                             StringCbPrintf(wstr, sizeof(wstr), wformat, wcells);
1864                         }
1865                     }
1866
1867                     if(wstr[0] != 0) {
1868                         size_t cbs;
1869                         StringCbLength(wstr, sizeof(wstr), &cbs);
1870                         cbs += sizeof(wchar_t);
1871                         assert(nct->credtext == NULL);
1872                         nct->credtext = PMALLOC(cbs);
1873                         StringCbCopy(nct->credtext, cbs, wstr);
1874                     } else {
1875                         /* something went wrong */
1876                         nct->credtext = NULL;
1877                     }
1878                 }
1879                 break;
1880
1881             case WMNC_CREDTEXT_LINK:
1882                 {
1883                     khui_htwnd_link * l;
1884                     wchar_t wid[KHUI_MAXCCH_HTLINK_FIELD];
1885                     wchar_t * wids;
1886
1887                     l = (khui_htwnd_link *) lParam;
1888
1889                     StringCchCopyN(wid, ARRAYLENGTH(wid), l->id, l->id_len);
1890                     wids = wcschr(wid, L':');
1891                         
1892                     if(!wids)
1893                         break;
1894                     else
1895                         wids++;
1896
1897 #ifdef DEBUG
1898                     assert(d->nc);
1899 #endif
1900
1901                     if(!wcscmp(wids, L"Enable")) {
1902                         SendDlgItemMessage(hwnd, IDC_NCAFS_OBTAIN, 
1903                                            BM_SETCHECK, BST_CHECKED, 0);
1904                         d->afs_enabled = TRUE;
1905                         khui_cw_enable_type(d->nc, afs_credtype_id, TRUE);
1906                         nc_dlg_enable(hwnd, TRUE);
1907                     }
1908                 }
1909                 break;
1910
1911             case WMNC_IDENTITY_CHANGE:
1912                 kmq_post_sub_msg(afs_sub, KMSG_CRED, 
1913                                  KMSG_CRED_DIALOG_NEW_IDENTITY, 0, 
1914                                  (void *) d->nc);
1915                 break;
1916                 
1917             case WMNC_AFS_UPDATE_ROWS:
1918                 afs_dlg_update_rows(hwnd, d);
1919
1920 #ifdef DEBUG
1921                 assert(d->nc);
1922 #endif
1923
1924                 PostMessage(d->nc->hwnd, KHUI_WM_NC_NOTIFY, 
1925                             MAKEWPARAM(0, WMNC_UPDATE_CREDTEXT), 0);
1926                 break;
1927             }
1928
1929             LeaveCriticalSection(&d->cs);
1930         }
1931         return TRUE;
1932
1933     case WM_NOTIFY:
1934         if(wParam == IDC_NCAFS_TOKENLIST) {
1935             LPNMHDR lpnmh = (LPNMHDR) lParam;
1936
1937             if(lpnmh->code == LVN_ITEMCHANGED) {
1938                 /* when an item in the list view is clicked, we
1939                    load the corresponding values into the edit and
1940                    combo boxes */
1941                 NMLISTVIEW *lpnmlv = (NMLISTVIEW *) lpnmh;
1942                 LVITEM lvi;
1943                 HWND hw;
1944                 int idx;
1945                 int row;
1946                 afs_dlg_data * d;
1947
1948                 if (!(lpnmlv->uChanged & LVIF_STATE) ||
1949                     !(lpnmlv->uNewState & LVIS_SELECTED) ||
1950                     (lpnmlv->iItem == -1))
1951
1952                     return TRUE;
1953
1954                 d = (afs_dlg_data *)(LONG_PTR) 
1955                     GetWindowLongPtr(hwnd, DWLP_USER);
1956
1957                 if (d == NULL)
1958                     return FALSE;
1959
1960                 EnterCriticalSection(&d->cs);
1961
1962                 hw = GetDlgItem(hwnd, IDC_NCAFS_TOKENLIST);
1963
1964                 idx = lpnmlv->iItem;
1965
1966                 ZeroMemory(&lvi, sizeof(lvi));
1967                 lvi.iItem = idx;
1968                 lvi.iSubItem = 0;
1969                 lvi.mask = LVIF_PARAM;
1970
1971                 if(!ListView_GetItem(hw, &lvi))
1972                     goto _done_notify_select;
1973
1974                 /* ok, now lvi.lParam should be the row of the token */
1975                 row = (int) lvi.lParam;
1976                 if(row < 0 || row >= d->creds.n_rows)
1977                     goto _done_notify_select;
1978
1979                 SetDlgItemText(hwnd, IDC_NCAFS_CELL, 
1980                                d->creds.rows[row].cell);
1981                 if(d->creds.rows[row].realm != NULL) {
1982                     SetDlgItemText(hwnd, IDC_NCAFS_REALM, 
1983                                    d->creds.rows[row].realm);
1984                 } else {
1985                     wchar_t wbuf[256];
1986                     int idx;
1987                         
1988                     LoadString(hResModule, IDS_NC_REALM_AUTO, wbuf, 
1989                                ARRAYLENGTH(wbuf));
1990                     idx = (int) SendDlgItemMessage(hwnd, IDC_NCAFS_REALM, 
1991                                                    CB_FINDSTRINGEXACT, 
1992                                                    (WPARAM) -1,
1993                                                    (LPARAM) wbuf);
1994                     SendDlgItemMessage(hwnd, IDC_NCAFS_REALM, CB_SETCURSEL,
1995                                        idx, 0);
1996                 }
1997                 SendDlgItemMessage(hwnd, IDC_NCAFS_METHOD, CB_SETCURSEL, 
1998                                    d->creds.rows[row].method, 0);
1999             _done_notify_select:
2000                 LeaveCriticalSection(&d->cs);
2001
2002             } else if (lpnmh->code == NM_DBLCLK) {
2003
2004                 LPNMITEMACTIVATE pnmi;
2005                 LVITEM lvi;
2006                 HWND hw;
2007                 afs_dlg_data * d;
2008                 int row;
2009                 int x,y;
2010                 RECT r;
2011
2012                 d = (afs_dlg_data *)(LONG_PTR) 
2013                     GetWindowLongPtr(hwnd, DWLP_USER);
2014
2015                 if (d == NULL)
2016                     return FALSE;
2017
2018                 EnterCriticalSection(&d->cs);
2019
2020                 pnmi = (LPNMITEMACTIVATE) lpnmh;
2021
2022                 hw = GetDlgItem(hwnd, IDC_NCAFS_TOKENLIST);
2023
2024                 ZeroMemory(&lvi, sizeof(lvi));
2025                 lvi.iItem = pnmi->iItem;
2026                 lvi.iSubItem = 0;
2027                 lvi.mask = LVIF_PARAM;
2028
2029                 if (!ListView_GetItem(hw, &lvi))
2030                     goto _done_notify_click;
2031
2032                 row = (int) lvi.lParam;
2033                 if(row < 0 || row >= d->creds.n_rows)
2034                     goto _done_notify_click;
2035
2036                 ListView_GetItemRect(hw, pnmi->iItem, &r, LVIR_SELECTBOUNDS);
2037                 x = (r.left + r.right) / 2;
2038                 y = (r.bottom);
2039
2040                 GetWindowRect(hw, &r);
2041                 y += r.top;
2042                 x += r.left;
2043
2044                 if (d->creds.rows[row].flags & DLGROW_FLAG_NOTOWNED) {
2045                     nc_dlg_show_tooltip(hwnd, 0,
2046                                         MAKEINTRESOURCE(IDS_NC_TT_CONFLICTD),
2047                                         MAKEINTRESOURCE(IDS_NC_TT_PROBLEM),
2048                                         2,
2049                                         x,y);
2050                 } else if (d->creds.rows[row].flags &
2051                            DLGROW_FLAG_EXPIRED) {
2052                     nc_dlg_show_tooltip(hwnd, 0,
2053                                         MAKEINTRESOURCE(IDS_NC_TT_EXPIRED),
2054                                         MAKEINTRESOURCE(IDS_NC_TT_DETAILS),
2055                                         1,
2056                                         x, y);
2057                 } else if (d->creds.rows[row].flags &
2058                            DLGROW_FLAG_EXISTS) {
2059                     nc_dlg_show_tooltip(hwnd, 0,
2060                                         MAKEINTRESOURCE(IDS_NC_TT_EXISTS),
2061                                         MAKEINTRESOURCE(IDS_NC_TT_DETAILS),
2062                                         1, x, y);
2063                 } else {
2064                     nc_dlg_show_tooltip(hwnd, 0,
2065                                         MAKEINTRESOURCE(IDS_NC_TT_NEW),
2066                                         MAKEINTRESOURCE(IDS_NC_TT_DETAILS),
2067                                         1, x, y);
2068                 }
2069
2070             _done_notify_click:
2071                 LeaveCriticalSection(&d->cs);
2072             }
2073         }
2074         return TRUE;
2075
2076     case WM_TIMER:
2077         {
2078             if(wParam == DLG_TOOLTIP_TIMER_ID) {
2079                 KillTimer(hwnd, DLG_TOOLTIP_TIMER_ID);
2080                 nc_dlg_hide_tooltip(hwnd, 0);
2081             }
2082         }
2083         return TRUE;
2084
2085     case WM_HELP:
2086         {
2087             static const DWORD ctx_help[] = {
2088                 IDC_NCAFS_OBTAIN, IDH_OBTAIN,
2089                 IDC_NCAFS_CELL, IDH_CELL,
2090                 IDC_NCAFS_REALM, IDH_REALM,
2091                 IDC_NCAFS_METHOD, IDH_METHOD,
2092                 IDC_NCAFS_ADD_TOKEN, IDH_ADD,
2093                 IDC_NCAFS_DELETE_TOKEN, IDH_DELETE,
2094                 IDC_NCAFS_TOKENLIST, IDH_TOKENLIST,
2095                 0
2096             };
2097
2098             LPHELPINFO hlp;
2099
2100             hlp = (LPHELPINFO) lParam;
2101
2102             if (hlp->iContextType != HELPINFO_WINDOW)
2103                 break;
2104
2105             afs_html_help(hlp->hItemHandle, L"::/popups_newcred.txt",
2106                           HH_TP_HELP_WM_HELP, (DWORD_PTR) ctx_help);
2107         }
2108         return TRUE;
2109     } /* switch(uMsg) */
2110
2111     return FALSE;
2112 }
2113
2114
2115 /* passed in to kcdb_credset_apply along with the afs_credset to adjust
2116    newly acquired credentials to include informatino derived from the
2117    new creds operation */
2118 khm_int32 KHMAPI 
2119 afs_adjust_token_ident_proc(khm_handle cred, void * vd)
2120 {
2121     wchar_t cell[MAXCELLCHARS];
2122     afs_ident_token_set * b = (afs_ident_token_set *) vd;
2123     afs_cred_list * l;
2124     khm_size cbbuf;
2125     int i;
2126
2127     l = b->l;
2128
2129     /* ASSUMPTION: for each user, there can be tokens for only one
2130        cell */
2131
2132     cbbuf = sizeof(cell);
2133
2134     if(KHM_FAILED(kcdb_cred_get_attr(cred, afs_attr_cell, NULL, cell, &cbbuf)))
2135         return KHM_ERROR_SUCCESS; /* remember, kcdb doesn't care if
2136                                      this run succeeded or not.  all
2137                                      it wants to know if whether or
2138                                      not we want to continue the
2139                                      search */
2140     
2141     for(i=0; i<l->n_rows; i++) {
2142         if((l->rows[i].flags & DLGROW_FLAG_DONE) && 
2143            !_wcsicmp(cell, l->rows[i].cell)) {
2144             khm_int32 method;
2145
2146             kcdb_cred_set_identity(cred, b->ident);
2147             if(l->rows[i].realm)
2148                 kcdb_cred_set_attr(cred, afs_attr_realm, l->rows[i].realm, 
2149                                    (khm_size)KCDB_CBSIZE_AUTO);
2150             else
2151                 kcdb_cred_set_attr(cred, afs_attr_realm, NULL, 0);
2152
2153             method = l->rows[i].method;
2154             kcdb_cred_set_attr(cred, afs_attr_method, &method, 
2155                                (khm_size)KCDB_CBSIZE_AUTO);
2156
2157             break;
2158         }
2159     }
2160
2161     return KHM_ERROR_SUCCESS;
2162 }
2163
2164 void
2165 afs_cred_write_ident_data(afs_dlg_data * d) {
2166     wchar_t * lru_cell = NULL;
2167     wchar_t * lru_realm = NULL;
2168     wchar_t * id_cell = NULL;
2169     khm_size cbidcell;
2170     khm_size cbcell;
2171     khm_size cbrealm;
2172     khm_size cbt;
2173     size_t cbz;
2174     khm_handle h_idc = NULL;
2175     khm_handle h_afs = NULL;
2176     khm_handle h_acells = NULL;
2177     khm_handle h_cellmap = NULL;
2178     wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
2179     khm_handle ident = NULL;
2180     afs_cred_list * l;
2181     int i;
2182
2183     l = &d->creds;
2184
2185     if (d->nc &&
2186         d->nc->n_identities > 0 &&
2187         d->nc->identities[0])
2188
2189         ident = d->nc->identities[0];
2190
2191     else if (d->config_dlg)
2192
2193         ident = d->ident;
2194
2195     if (!ident)
2196         return;
2197
2198     cbt = sizeof(idname);
2199     kcdb_identity_get_name(ident, idname, &cbt);
2200
2201     khc_open_space(csp_afscred, L"Cells", 0, &h_cellmap);
2202
2203     if(ident) {
2204         if(KHM_SUCCEEDED(kcdb_identity_get_config(ident,
2205                                                   KHM_FLAG_CREATE,
2206                                                   &h_idc))) {
2207             khc_open_space(h_idc, CSNAME_AFSCRED, 
2208                            KHM_FLAG_CREATE, &h_afs);
2209         }
2210
2211         if(h_afs) {
2212             khc_open_space(h_afs, L"Cells", KHM_FLAG_CREATE, 
2213                            &h_acells);
2214         }
2215     }
2216
2217     if (h_afs && d) {
2218         khc_write_int32(h_afs, L"AFSEnabled",
2219                         !!d->afs_enabled);
2220     }
2221
2222     if(khc_read_multi_string(csp_params, 
2223                              L"LRUCells", 
2224                              NULL,
2225                              &cbcell) == KHM_ERROR_TOO_LONG) {
2226         cbcell += MAXCELLCHARS * sizeof(wchar_t) * 
2227             l->n_rows;
2228         lru_cell = PMALLOC(cbcell);
2229         ZeroMemory(lru_cell, cbcell);
2230         cbt = cbcell;
2231                     
2232         khc_read_multi_string(csp_params,
2233                               L"LRUCells",
2234                               lru_cell,
2235                               &cbt);
2236     } else {
2237         cbcell = MAXCELLCHARS * sizeof(wchar_t) * l->n_rows + sizeof(wchar_t);
2238         if (l->n_rows > 0) {
2239             lru_cell = PMALLOC(cbcell);
2240             ZeroMemory(lru_cell, cbcell);
2241         } else {
2242             lru_cell = NULL;
2243             cbcell = 0;
2244         }
2245     }
2246
2247     if(khc_read_multi_string(csp_params,
2248                              L"LRURealms",
2249                              NULL,
2250                              &cbrealm) == KHM_ERROR_TOO_LONG) {
2251         cbrealm += MAXCELLCHARS * sizeof(wchar_t) * l->n_rows;
2252         lru_realm = PMALLOC(cbrealm);
2253         ZeroMemory(lru_realm, cbrealm);
2254         cbt = cbrealm;
2255
2256         khc_read_multi_string(csp_params,
2257                               L"LRURealms",
2258                               lru_realm,
2259                               &cbt);
2260     } else {
2261         cbrealm = MAXCELLCHARS * sizeof(wchar_t) * l->n_rows + sizeof(wchar_t);
2262         if (l->n_rows > 0) {
2263             lru_realm = PMALLOC(cbrealm);
2264             ZeroMemory(lru_realm, cbrealm);
2265         } else {
2266             lru_cell = NULL;
2267             cbrealm = 0;
2268         }
2269     }
2270
2271     cbidcell = MAXCELLCHARS * sizeof(wchar_t) * l->n_rows + sizeof(wchar_t);
2272     if (l->n_rows > 0) {
2273         id_cell = PMALLOC(cbidcell);
2274         ZeroMemory(id_cell, cbidcell);
2275     } else {
2276         id_cell = NULL;
2277         cbidcell = 0;
2278     }
2279
2280     for(i=0; i < l->n_rows; i++)
2281         if(!(l->rows[i].flags & DLGROW_FLAG_DELETED)) {
2282             khm_handle h_acell = NULL;
2283             
2284             if(!multi_string_find(lru_cell, 
2285                                   l->rows[i].cell, 0)) {
2286                 cbz = cbcell;
2287                 multi_string_append(lru_cell, &cbz, 
2288                                     l->rows[i].cell);
2289             }
2290
2291             if(l->rows[i].realm && 
2292                !multi_string_find(lru_realm, 
2293                                   l->rows[i].realm, 0)) {
2294                 cbz = cbrealm;
2295                 multi_string_append(lru_realm, &cbz, 
2296                                     l->rows[i].realm);
2297             }
2298
2299             cbz = cbidcell;
2300             multi_string_append(id_cell, &cbz, 
2301                                 l->rows[i].cell);
2302
2303             if(h_acells && 
2304                KHM_SUCCEEDED(khc_open_space(h_acells, 
2305                                             l->rows[i].cell, 
2306                                             KHM_FLAG_CREATE, 
2307                                             &h_acell))) {
2308                 wchar_t methodname[KHUI_MAXCCH_NAME];
2309
2310                 afs_get_method_name(l->rows[i].method,
2311                                     methodname,
2312                                     sizeof(methodname));
2313
2314                 khc_write_string(h_acell, L"MethodName", 
2315                                  methodname);
2316
2317                 if(l->rows[i].realm)
2318                     khc_write_string(h_acell, L"Realm", 
2319                                      l->rows[i].realm);
2320                 else
2321                     khc_write_string(h_acell, L"Realm", L"");
2322                 khc_close_space(h_acell);
2323             }
2324
2325             if (l->rows[i].flags & DLGROW_FLAG_DONE) {
2326                 if (h_cellmap) {
2327                     khc_write_string(h_cellmap,
2328                                      l->rows[i].cell,
2329                                      idname);
2330                 }
2331             }
2332         }
2333
2334     if (lru_cell)                
2335         khc_write_multi_string(csp_params,
2336                                L"LRUCells", lru_cell);
2337     if (lru_realm)
2338         khc_write_multi_string(csp_params,
2339                                L"LRURealms", lru_realm);
2340     if (id_cell)
2341         khc_write_multi_string(h_afs, L"Cells",
2342                                id_cell);
2343     else
2344         khc_write_multi_string(h_afs, L"Cells", L"\0");
2345
2346     if (d->config_dlg) {
2347         if (d->dirty)
2348             khui_cfg_set_flags_inst(&d->cfg, KHUI_CNFLAG_APPLIED,
2349                                     KHUI_CNFLAG_APPLIED |
2350                                     KHUI_CNFLAG_MODIFIED);
2351         else
2352             khui_cfg_set_flags_inst(&d->cfg, 0,
2353                                     KHUI_CNFLAG_MODIFIED);
2354     }
2355
2356     d->dirty = FALSE;
2357
2358     if(h_cellmap)
2359         khc_close_space(h_cellmap);
2360     if(h_idc)
2361         khc_close_space(h_idc);
2362     if(h_afs)
2363         khc_close_space(h_afs);
2364     if(h_acells)
2365         khc_close_space(h_acells);
2366     if(id_cell)
2367         PFREE(id_cell);
2368     if(lru_cell)
2369         PFREE(lru_cell);
2370     if(lru_realm)
2371         PFREE(lru_realm);
2372 }
2373
2374 khm_int32
2375 afs_msg_newcred(khm_int32 msg_subtype, 
2376                 khm_ui_4 uparam, 
2377                 void * vparam) {
2378
2379     switch(msg_subtype) {
2380     case KMSG_CRED_NEW_CREDS:
2381         {
2382             khui_new_creds * nc;
2383             khui_new_creds_by_type * nct;
2384             wchar_t wbuf[256];
2385             size_t cbsize;
2386
2387             nc = (khui_new_creds *) vparam;
2388
2389             nct = PMALLOC(sizeof(*nct));
2390             ZeroMemory(nct, sizeof(*nct));
2391
2392             nct->type = afs_credtype_id;
2393             nct->ordinal = 3;
2394
2395             LoadString(hResModule, IDS_AFS_NAME, wbuf, ARRAYLENGTH(wbuf));
2396             StringCbLength(wbuf, sizeof(wbuf), &cbsize);
2397             cbsize += sizeof(wchar_t);
2398
2399             nct->name = PMALLOC(cbsize);
2400             StringCbCopy(nct->name, cbsize, wbuf);
2401
2402             nct->h_module = hResModule;
2403             nct->dlg_proc = afs_dlg_proc;
2404             nct->dlg_template = MAKEINTRESOURCE(IDD_NC_AFS);
2405             nct->type_deps[nct->n_type_deps++] = krb5_credtype_id;
2406
2407             if (krb4_credtype_id < 0) {
2408                 kcdb_credtype_get_id(KRB4_CREDTYPE_NAME,
2409                                      &krb4_credtype_id);
2410             }
2411             if (krb4_credtype_id >= 0) {
2412                 nct->type_deps[nct->n_type_deps++] =
2413                     krb4_credtype_id;
2414             }
2415
2416             khui_cw_add_type(nc, nct);
2417         }
2418         break;
2419
2420     case KMSG_CRED_RENEW_CREDS:
2421         {
2422             khui_new_creds * nc;
2423             khui_new_creds_by_type * nct;
2424
2425             nc = (khui_new_creds *) vparam;
2426
2427             nct = PMALLOC(sizeof(*nct));
2428             ZeroMemory(nct, sizeof(*nct));
2429
2430             nct->type = afs_credtype_id;
2431             nct->type_deps[nct->n_type_deps++] = krb5_credtype_id;
2432             if (krb4_credtype_id < 0) {
2433                 kcdb_credtype_get_id(KRB4_CREDTYPE_NAME,
2434                                      &krb4_credtype_id);
2435             }
2436             if (krb4_credtype_id >= 0) {
2437                 nct->type_deps[nct->n_type_deps++] =
2438                     krb4_credtype_id;
2439             }
2440
2441             khui_cw_add_type(nc, nct);
2442         }
2443         break;
2444
2445     case KMSG_CRED_DIALOG_PRESTART:
2446         {
2447             khui_new_creds * nc;
2448             khui_new_creds_by_type * nct = NULL;
2449             HWND hwnd;
2450
2451             nc = (khui_new_creds *) vparam;
2452             khui_cw_find_type(nc, afs_credtype_id, &nct);
2453
2454             if(!nct)
2455                 break;
2456
2457             hwnd = nct->hwnd_panel;
2458             if (!hwnd)
2459                 break;
2460
2461             PostMessage(hwnd, KHUI_WM_NC_NOTIFY,
2462                         MAKEWPARAM(0,WMNC_DIALOG_SETUP), 0);
2463         }
2464         break;
2465
2466     case KMSG_CRED_DIALOG_NEW_IDENTITY:
2467         {
2468             khui_new_creds * nc;
2469             khui_new_creds_by_type * nct = NULL;
2470             afs_dlg_data * d;
2471
2472             nc = (khui_new_creds *) vparam;
2473             khui_cw_find_type(nc, afs_credtype_id, &nct);
2474
2475             if(nct == NULL)
2476                 break;
2477
2478             d = (afs_dlg_data *) nct->aux;
2479
2480             if(d == NULL)
2481                 break;
2482
2483             EnterCriticalSection(&d->cs);
2484
2485             if (nct->aux == 0) {
2486                 LeaveCriticalSection(&d->cs);
2487                 break;
2488             }
2489
2490             /* we should load up the selected tokens for this
2491                identity */
2492             if(nc->n_identities == 0) {
2493                 LeaveCriticalSection(&d->cs);
2494                 /* no identities selected. nothing to do */
2495                 break;
2496             }
2497
2498             afs_cred_get_identity_creds(&d->creds, nc->identities[0],
2499                                         &d->afs_enabled);
2500
2501             LeaveCriticalSection(&d->cs);
2502
2503             PostMessage(nct->hwnd_panel, KHUI_WM_NC_NOTIFY,
2504                         MAKEWPARAM(0, WMNC_AFS_UPDATE_ROWS), 0);
2505         }
2506         break;
2507
2508     case KMSG_CRED_PROCESS:
2509         {
2510             khui_new_creds * nc;
2511             khui_new_creds_by_type * nct = NULL;
2512             afs_cred_list tlist;
2513             afs_cred_list * l;
2514             int i;
2515             BOOL failed = FALSE;    /* one or more cells failed */
2516             BOOL succeeded = FALSE; /* one or more cells succeeded */
2517             BOOL free_tlist = FALSE;
2518             khm_handle ident = NULL;
2519             afs_dlg_data * d = NULL;
2520             BOOL get_tokens = TRUE;
2521             BOOL ident_renew_triggered = TRUE;
2522             khm_handle csp_afscred = NULL;
2523             khm_handle csp_cells = NULL;
2524
2525             nc = (khui_new_creds *) vparam;
2526             khui_cw_find_type(nc, afs_credtype_id, &nct);
2527
2528             if(!nct)
2529                 break;
2530
2531             _begin_task(0);
2532             _report_cs0(KHERR_INFO,
2533                         L"Getting AFS tokens...");
2534             _describe();
2535
2536             if(nc->result != KHUI_NC_RESULT_PROCESS &&
2537                nc->subtype != KMSG_CRED_RENEW_CREDS) {
2538                 /* nothing to do */
2539                 khui_cw_set_response(nc, afs_credtype_id,
2540                                      KHUI_NC_RESPONSE_SUCCESS);
2541
2542                 _report_cs0(KHERR_INFO, 
2543                             L"Cancelling");
2544                 _end_task();
2545                 break;
2546             }
2547
2548             /* we can't proceed if Kerberos 5 has failed */
2549             if(!khui_cw_type_succeeded(nc, krb5_credtype_id)) {
2550                 khui_cw_set_response(nc, afs_credtype_id,
2551                                      KHUI_NC_RESPONSE_FAILED);
2552
2553                 _report_cs0(KHERR_INFO,
2554                             L"Kerberos 5 plugin failed to process credentials request.  Aborting");
2555                 _end_task();
2556                 break;
2557             }
2558
2559             if (nc->subtype == KMSG_CRED_RENEW_CREDS) {
2560
2561                 if (nc->ctx.scope == KHUI_SCOPE_IDENT ||
2562
2563                     (nc->ctx.scope == KHUI_SCOPE_CREDTYPE &&
2564                      nc->ctx.cred_type == afs_credtype_id) ||
2565
2566                     (nc->ctx.scope == KHUI_SCOPE_CRED &&
2567                      nc->ctx.cred_type == afs_credtype_id)) {
2568
2569                     _report_cs1(KHERR_INFO,
2570                                 L"AFS Renew Creds :: ident %1!p!", 
2571                                 _cptr(nc->ctx.identity));
2572
2573                 } else {
2574
2575                     _report_cs0(KHERR_INFO,
2576                                 L"Renew request not applicable to AFS");
2577                     _end_task();
2578                     break;
2579
2580                 }
2581
2582                 if (nc->ctx.identity != NULL) {
2583                     ident = nc->ctx.identity;
2584                 } else {
2585                     khui_cw_set_response(nc, afs_credtype_id,
2586                                          KHUI_NC_RESPONSE_FAILED);
2587
2588                     _report_cs0(KHERR_INFO,
2589                                 L"No identity specified.  Aborting");
2590                     _end_task();
2591                     break;
2592                 }
2593
2594                 ZeroMemory(&tlist, sizeof(tlist));
2595                 l = &tlist;
2596                 free_tlist = TRUE;
2597
2598                 afs_cred_get_identity_creds(l, ident, NULL);
2599
2600                 /* if the identity has any tokens associated with it
2601                    that aren't persistent, we should renew those as
2602                    well. */
2603                 afs_cred_get_context_creds(l, &nc->ctx);
2604
2605                 if (nc->ctx.scope == KHUI_SCOPE_CREDTYPE ||
2606                     nc->ctx.scope == KHUI_SCOPE_CRED) {
2607
2608                     ident_renew_triggered = FALSE;
2609
2610                 }
2611
2612             } else {
2613                 _report_cs1(KHERR_INFO,
2614                             L"AFS New Creds :: ident %1!p!",
2615                             _cptr(nc->identities[0]));
2616
2617                 d = (afs_dlg_data *) nct->aux;
2618                 if(!d) {
2619                     _report_cs0(KHERR_INFO,
2620                                 L"No dialog data found.  Aborting");
2621
2622                     khui_cw_set_response(nc, afs_credtype_id,
2623                                          KHUI_NC_RESPONSE_FAILED);
2624                     _end_task();
2625                     break;
2626                 }
2627
2628                 EnterCriticalSection(&d->cs);
2629
2630                 l = &d->creds;
2631
2632                 ident = nc->identities[0];
2633                 if (!ident) {
2634                     LeaveCriticalSection(&d->cs);
2635
2636                     _report_cs0(KHERR_INFO,
2637                                 L"No identity specified. Aborting");
2638
2639                     khui_cw_set_response(nc, afs_credtype_id,
2640                                          KHUI_NC_RESPONSE_FAILED);
2641
2642                     _end_task();
2643                     break;
2644                 }
2645
2646                 get_tokens = d->afs_enabled;
2647             }
2648
2649             if (!get_tokens)
2650                 goto _skip_tokens;
2651
2652             if (KHM_SUCCEEDED(kmm_get_plugin_config(AFS_PLUGIN_NAME, 0,
2653                                                     &csp_afscred)))
2654                 khc_open_space(csp_afscred, L"Cells", 0, &csp_cells);
2655
2656             /* looks like k5 worked.  Now see about getting those
2657                tokens */
2658             for(i=0; i<l->n_rows; i++) {
2659                 int code;
2660                 char cell[MAXCELLCHARS];
2661                 char realm[MAXKTCREALMLEN];
2662                 char linkedCell[MAXCELLCHARS]="";
2663                 khm_handle ctoken;
2664                 FILETIME ft_old;
2665                 FILETIME ft_new;
2666                 time_t new_exp = 0;
2667                 khm_size cb;
2668                 khm_int32 method = AFS_TOKEN_AUTO;
2669                 khm_handle csp_cell = NULL;
2670                 BOOL bgetLinked = 0;
2671
2672                 _progress(i, l->n_rows);
2673
2674                 if (l->rows[i].flags &
2675                     (DLGROW_FLAG_DONE | DLGROW_FLAG_DELETED))
2676
2677                     continue;
2678
2679                 ZeroMemory(cell, sizeof(cell));
2680                 ZeroMemory(realm, sizeof(realm));
2681
2682                 UnicodeStrToAnsi(cell, sizeof(cell), l->rows[i].cell);
2683                 if (l->rows[i].realm != NULL)
2684                     UnicodeStrToAnsi(realm, sizeof(realm), 
2685                                      l->rows[i].realm);
2686
2687                 ZeroMemory(&ft_old, sizeof(ft_old));
2688
2689                 if (!ident_renew_triggered &&
2690                     (ctoken = afs_find_token(NULL, l->rows[i].cell))) {
2691
2692                     cb = sizeof(ft_old);
2693                     kcdb_cred_get_attr(ctoken, KCDB_ATTR_EXPIRE,
2694                                        NULL, &ft_old, &cb);
2695
2696                     kcdb_cred_release(ctoken);
2697                 }
2698
2699                 if (l->rows[i].method == AFS_TOKEN_AUTO && csp_cells &&
2700                     KHM_SUCCEEDED(khc_open_space(csp_cells,
2701                                                  l->rows[i].cell, 0,
2702                                                  &csp_cell))) {
2703
2704                     if (KHM_FAILED(khc_read_int32(csp_cell, L"Method", &method))) {
2705                         method = l->rows[i].method;
2706                     } else {
2707                         _report_cs3(KHERR_INFO,
2708                                     L"Overriding method %1!d! with global default %2!d! for cell %3!s!",
2709                                     _int32(l->rows[i].method),
2710                                     _int32(method),
2711                                     _cstr(l->rows[i].cell));
2712                         _resolve();
2713                     }
2714
2715                     khc_close_space(csp_cell);               
2716                 } else {
2717                     method = l->rows[i].method;
2718                 }
2719
2720               getLinked:
2721                 _report_cs3(KHERR_INFO,
2722                             L"Getting tokens for cell %1!S! with realm %2!S! using method %3!d!",
2723                             _cstr((bgetLinked ? linkedCell: cell)),
2724                             _cstr(realm),
2725                             _int32(method));
2726                 _resolve();
2727
2728                 /* make the call */
2729                 code = afs_klog(ident, "", 
2730                                 bgetLinked ? linkedCell : cell, 
2731                                 realm, 0,
2732                                 method, &new_exp, 
2733                                 bgetLinked ? NULL :linkedCell);
2734
2735                 _report_cs1(KHERR_INFO,
2736                             L"klog returns code %1!d!",
2737                             _int32(code));
2738
2739                 if(code) {
2740                     failed = TRUE;
2741                     l->rows[i].flags &= ~DLGROW_FLAG_DONE;
2742
2743                     if (!kherr_is_error()) {
2744                         /* failed to get tokens, but no error was reported */
2745                         _report_sr1(KHERR_ERROR, IDS_ERR_GENERAL,
2746                                     _cptr(cell));
2747                         _resolve();
2748                     }
2749
2750                 } else {
2751                     l->rows[i].flags |= DLGROW_FLAG_DONE;
2752                     succeeded = TRUE;
2753
2754                     if (new_exp &&
2755                         !ident_renew_triggered) {
2756                         TimetToFileTime(new_exp, &ft_new);
2757
2758                         if (CompareFileTime(&ft_old, &ft_new) >= 0) {
2759                             /* getting a new token didn't improve the
2760                                situation much.  We only get here if we
2761                                were trying to renew tokens. So we try
2762                                to trigger an identity renewal.  Doing
2763                                so should get us new initial tickets
2764                                which will allow us to get a better
2765                                token. */
2766
2767                             khui_action_context ctx;
2768
2769                             _reportf(L"Renewal of AFS tokens for cell %s failed to get a longer token.  Triggering identity renewal", l->rows[i].cell);
2770
2771                             khui_context_create(&ctx,
2772                                                 KHUI_SCOPE_IDENT,
2773                                                 nc->ctx.identity,
2774                                                 KCDB_CREDTYPE_INVALID,
2775                                                 NULL);
2776                             khui_action_trigger(KHUI_ACTION_RENEW_CRED,
2777                                                 &ctx);
2778
2779                             khui_context_release(&ctx);
2780
2781                             ident_renew_triggered = TRUE;
2782                         }
2783                     }
2784
2785                     if ( !bgetLinked && linkedCell[0] ) {
2786                         bgetLinked = TRUE;
2787                         goto getLinked;
2788                     }
2789                 }
2790             }
2791
2792             _progress(1,1);
2793
2794         _skip_tokens:
2795
2796             if(failed) {
2797                 /* we should indicate errors if anything went wrong */
2798                 khui_cw_set_response(nc, afs_credtype_id, 
2799                                      KHUI_NC_RESPONSE_FAILED);
2800             } else {
2801                 khui_cw_set_response(nc, afs_credtype_id,
2802                                      KHUI_NC_RESPONSE_SUCCESS);
2803             }
2804
2805             if (succeeded && nc->subtype == KMSG_CRED_RENEW_CREDS) {
2806                 afs_ident_token_set b;
2807
2808                 afs_list_tokens_internal();
2809
2810                 /* the tokens that we just acquired need adjusting to
2811                    include the realm, method and identity information
2812                    derived from the new creds operation.  this is done
2813                    in afs_adjust_token_ident_proc */
2814                 b.ident = ident;
2815                 b.l = l;
2816                 b.add_new = FALSE;
2817                 b.update_info = FALSE;
2818
2819                 kcdb_credset_apply(afs_credset, afs_adjust_token_ident_proc, 
2820                                    (void *) &b);
2821
2822                 kcdb_credset_collect(NULL, afs_credset, NULL, 
2823                                      afs_credtype_id, NULL);
2824
2825             } else if (nc->subtype == KMSG_CRED_NEW_CREDS) {
2826                 afs_ident_token_set b;
2827
2828                 afs_list_tokens_internal();
2829
2830                 /* the tokens that we just acquired need adjusting to
2831                    include the realm, method and identity information
2832                    derived from the new creds operation.  this is done
2833                    in afs_adjust_token_ident_proc */
2834                 b.ident = ident;
2835                 b.l = l;
2836                 b.add_new = FALSE;
2837                 b.update_info = FALSE;
2838
2839                 kcdb_credset_apply(afs_credset, afs_adjust_token_ident_proc, 
2840                                    (void *) &b);
2841
2842                 kcdb_credset_collect(NULL, afs_credset, NULL, 
2843                                      afs_credtype_id, NULL);
2844
2845                 afs_cred_write_ident_data(d);
2846             }
2847
2848             if (d)
2849                 LeaveCriticalSection(&d->cs);
2850
2851             if (free_tlist) {
2852                 afs_cred_free_rows(&tlist);
2853             }
2854
2855             if (csp_afscred)
2856                 khc_close_space(csp_afscred);
2857
2858             if (csp_cells)
2859                 khc_close_space(csp_cells);
2860
2861             _end_task();
2862         }
2863         break;
2864
2865     case KMSG_CRED_END:
2866         {
2867             khui_new_creds * nc;
2868             khui_new_creds_by_type * nct;
2869
2870             nc = (khui_new_creds *) vparam;
2871             khui_cw_find_type(nc, afs_credtype_id, &nct);
2872
2873             if(!nct)
2874                 break;
2875
2876             khui_cw_del_type(nc, afs_credtype_id);
2877     
2878             if (nct->name)
2879                 PFREE(nct->name);
2880             if (nct->credtext)
2881                 PFREE(nct->credtext);
2882
2883             PFREE(nct);
2884         }
2885         break;
2886     }
2887
2888     return KHM_ERROR_SUCCESS;
2889 }