c1f41316026f39035fd05425917915441d0003f7
[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             LeaveCriticalSection(&d->cs);
1567
1568             /* the cells and realms combo boxes need to be filled
1569                in the plugin thread since that requires making
1570                potentially blocking and non-thread safe calls */
1571         }
1572         return TRUE;
1573
1574     case WM_DESTROY:
1575         {
1576             afs_dlg_data * d;
1577             khui_new_creds_by_type * nct;
1578
1579             d = (afs_dlg_data *)(LONG_PTR) 
1580                 GetWindowLongPtr(hwnd, DWLP_USER);
1581
1582             if (d == NULL)
1583                 return TRUE;
1584
1585             EnterCriticalSection(&d->cs);
1586
1587             if (d->nc) {
1588                 khui_cw_find_type(d->nc, afs_credtype_id, &nct);
1589
1590                 nct->aux = (LPARAM) NULL;
1591             }
1592
1593             afs_cred_free_rows(&d->creds);
1594
1595             LeaveCriticalSection(&d->cs);
1596             DeleteCriticalSection(&d->cs);
1597
1598             PFREE(d);
1599
1600             SetWindowLongPtr(hwnd, DWLP_USER, 0);
1601         }
1602         return TRUE;
1603
1604     case WM_COMMAND:
1605         {
1606             afs_dlg_data * d;
1607             khui_new_creds_by_type * nct;
1608
1609             d = (afs_dlg_data *)(LONG_PTR) 
1610                 GetWindowLongPtr(hwnd, DWLP_USER);
1611
1612             if (d == NULL)
1613                 return FALSE;
1614
1615             EnterCriticalSection(&d->cs);
1616
1617             if (d->nc)
1618                 khui_cw_find_type(d->nc, afs_credtype_id, &nct);
1619             else
1620                 nct = NULL;
1621
1622             nc_dlg_hide_tooltip(hwnd, 0);
1623
1624             /* Handle WM_COMMAND */
1625             switch(wParam) {
1626             case MAKEWPARAM(IDC_NCAFS_OBTAIN, BN_CLICKED):
1627                 {
1628                     BOOL c;
1629                     c = (SendDlgItemMessage(hwnd, IDC_NCAFS_OBTAIN, 
1630                                             BM_GETCHECK, 0, 0) 
1631                          == BST_CHECKED);
1632                     d->afs_enabled = c;
1633                     d->dirty = TRUE;
1634                     if (d->nc)
1635                         khui_cw_enable_type(d->nc, afs_credtype_id, c);
1636                     else if (d->config_dlg)
1637                         khui_cfg_set_flags_inst(&d->cfg,
1638                                                 KHUI_CNFLAG_MODIFIED,
1639                                                 KHUI_CNFLAG_MODIFIED);
1640                     nc_dlg_enable(hwnd, c);
1641                 }
1642                 break;
1643
1644             case MAKEWPARAM(IDC_NCAFS_ADD_TOKEN, BN_CLICKED):
1645                 {
1646                     nc_dlg_add_token(hwnd);
1647                 }
1648                 break;
1649
1650             case MAKEWPARAM(IDC_NCAFS_DELETE_TOKEN, BN_CLICKED):
1651                 {
1652                     nc_dlg_del_token(hwnd);
1653                 }
1654                 break;
1655             }
1656
1657             LeaveCriticalSection(&d->cs);
1658         }
1659         return TRUE;
1660
1661     case KHUI_WM_NC_NOTIFY:
1662         {
1663             afs_dlg_data * d;
1664             khui_new_creds_by_type * nct;
1665
1666             d = (afs_dlg_data *)(LONG_PTR) 
1667                 GetWindowLongPtr(hwnd, DWLP_USER);
1668
1669             if (d == NULL)
1670                 return TRUE;
1671
1672             EnterCriticalSection(&d->cs);
1673
1674             if (d->nc)
1675                 khui_cw_find_type(d->nc, afs_credtype_id, &nct);
1676             else
1677                 nct = NULL;
1678
1679             switch(HIWORD(wParam)) {
1680             case WMNC_DIALOG_SETUP:
1681                 {
1682                     SendDlgItemMessage(hwnd, IDC_NCAFS_CELL, 
1683                                        CB_RESETCONTENT, 0, 0);
1684                     
1685                     /* load the LRU cells */
1686                     {
1687                         wchar_t * buf;
1688                         wchar_t *s;
1689                         khm_size cbbuf;
1690
1691                         if(khc_read_multi_string(csp_params, L"LRUCells", 
1692                                                  NULL, &cbbuf) == 
1693                            KHM_ERROR_TOO_LONG) {
1694                             buf = PMALLOC(cbbuf);
1695                             khc_read_multi_string(csp_params, L"LRUCells", 
1696                                                   buf, &cbbuf);
1697                             s = buf;
1698                             while(*s) {
1699                                 SendDlgItemMessage(hwnd, IDC_NCAFS_CELL, 
1700                                                    CB_ADDSTRING, 0, (LPARAM) s);
1701                                 s += wcslen(s) + 1;
1702                             }
1703                             PFREE(buf);
1704                         }
1705                     }
1706
1707                     /* now, if the root cell is not in the LRU, add it */
1708                     {
1709                         char buf[256];
1710                         wchar_t wbuf[256];
1711
1712                         if(!cm_GetRootCellName(buf)) {
1713                             AnsiStrToUnicode(wbuf, sizeof(wbuf), buf);
1714                             if(SendDlgItemMessage(hwnd,
1715                                                   IDC_NCAFS_CELL,
1716                                                   CB_FINDSTRINGEXACT,
1717                                                   (WPARAM) -1,
1718                                                   (LPARAM) wbuf) == CB_ERR) {
1719                                 SendDlgItemMessage(hwnd, IDC_NCAFS_CELL, 
1720                                                    CB_ADDSTRING, 
1721                                                    0, (LPARAM) wbuf);
1722                             }
1723                             SendDlgItemMessage(hwnd, IDC_NCAFS_CELL, 
1724                                                CB_SELECTSTRING, 
1725                                                (WPARAM)-1, (LPARAM) wbuf);
1726                         }
1727                     }
1728
1729                     SendDlgItemMessage(hwnd, IDC_NCAFS_REALM, 
1730                                        CB_RESETCONTENT, 0, 0);
1731
1732                     /* as for the realms, we have a special one here */
1733                     {
1734                         wchar_t wbuf[256];
1735                         int idx;
1736
1737                         LoadString(hResModule, IDS_NC_REALM_AUTO, wbuf, 
1738                                    (int) ARRAYLENGTH(wbuf));
1739                         idx = (int) SendDlgItemMessage(hwnd, IDC_NCAFS_REALM, 
1740                                                        CB_ADDSTRING, 0, 
1741                                                        (LPARAM) wbuf);
1742                         /* item data for the realm strings is the
1743                            answer to the question, "is this the
1744                            'determine realm automatically' item?" */
1745                         SendDlgItemMessage(hwnd, IDC_NCAFS_REALM, 
1746                                            CB_SETITEMDATA, idx, TRUE);
1747                         SendDlgItemMessage(hwnd, IDC_NCAFS_REALM, 
1748                                            CB_SELECTSTRING, 
1749                                            (WPARAM)-1, (LPARAM) wbuf);
1750                     }
1751
1752                     /* load the LRU realms */
1753                     {
1754                         wchar_t * buf;
1755                         wchar_t *s;
1756                         int idx;
1757                         khm_size cbbuf;
1758
1759                         if(khc_read_multi_string(csp_params, L"LRURealms", 
1760                                                  NULL, &cbbuf) == 
1761                            KHM_ERROR_TOO_LONG) {
1762                             buf = PMALLOC(cbbuf);
1763                             khc_read_multi_string(csp_params, L"LRURealms", 
1764                                                   buf, &cbbuf);
1765                             s = buf;
1766                             while(*s) {
1767                                 if(SendDlgItemMessage(hwnd, IDC_NCAFS_REALM, 
1768                                                       CB_FINDSTRINGEXACT, 
1769                                                       (WPARAM)-1,
1770                                                       (LPARAM) s) == CB_ERR) {
1771                                     idx = 
1772                                         (int)
1773                                         SendDlgItemMessage(hwnd, 
1774                                                            IDC_NCAFS_REALM, 
1775                                                            CB_ADDSTRING, 
1776                                                            0, (LPARAM) s);
1777                                     SendDlgItemMessage(hwnd, IDC_NCAFS_REALM, 
1778                                                        CB_SETITEMDATA, 
1779                                                        idx, FALSE);
1780                                 }
1781
1782                                 s += wcslen(s) + 1;
1783                             }
1784                             PFREE(buf);
1785                         }
1786                     }
1787
1788                     if (d->nc)
1789                         khui_cw_enable_type(d->nc, afs_credtype_id, 
1790                                             d->afs_enabled);
1791
1792                     nc_dlg_enable(hwnd, d->afs_enabled);
1793
1794                     afs_dlg_update_rows(hwnd, d);
1795                 }
1796                 break;
1797
1798             case WMNC_UPDATE_CREDTEXT:
1799                 {
1800                     wchar_t wformat[256];
1801                     wchar_t wstr[2048];
1802                     khm_int32 flags;
1803
1804                     if(nct->credtext) {
1805                         PFREE(nct->credtext);
1806                         nct->credtext = NULL;
1807                     }
1808
1809 #ifdef DEBUG
1810                     assert(d->nc);
1811 #endif
1812
1813                     if (d->nc->n_identities == 0 ||
1814                         KHM_FAILED(kcdb_identity_get_flags(d->nc->identities[0],
1815                                                            &flags)) ||
1816                         !(flags & KCDB_IDENT_FLAG_VALID))
1817                         /* in this case, we don't show any credential text */
1818                         break;
1819
1820                     wstr[0] = 0;
1821
1822                     if(!d->afs_enabled) {
1823                         LoadString(hResModule, IDS_AFS_CREDTEXT_DIS, 
1824                                    wstr, ARRAYLENGTH(wstr));
1825                     } else {
1826                         if(d->creds.n_rows == 0) {
1827                             LoadString(hResModule, IDS_AFS_CREDTEXT_0, 
1828                                        wstr, ARRAYLENGTH(wstr));
1829                         } else if(d->creds.n_rows == 1) {
1830                             LoadString(hResModule, IDS_AFS_CREDTEXT_1, 
1831                                        wformat, ARRAYLENGTH(wformat));
1832                             StringCbPrintf(wstr, sizeof(wstr), wformat, 
1833                                            d->creds.rows[0].cell);
1834                         } else {
1835                             int i;
1836                             wchar_t wcells[1024];
1837
1838                             LoadString(hResModule, IDS_AFS_CREDTEXT_N, 
1839                                        wformat, ARRAYLENGTH(wformat));
1840                             wcells[0] = 0;
1841                             for(i=0; i<d->creds.n_rows; i++) {
1842                                 if(i > 0)
1843                                     StringCbCat(wcells, sizeof(wcells), 
1844                                                 L", ");
1845                                 if(FAILED(StringCbCat(wcells, 
1846                                                       sizeof(wcells), 
1847                                                       d->creds.rows[i].cell))) {
1848                                     size_t cch;
1849                                     /* looks like we overflowed */
1850                                     /* add an ellipsis at the end */
1851                                     StringCchLength(wcells, ARRAYLENGTH(wcells), &cch);
1852                                     cch = min(ARRAYLENGTH(wcells) - 4, cch);
1853                                     StringCchCopy(wcells + cch, 4, L"...");
1854
1855                                     break;
1856                                 }
1857                             }
1858
1859                             StringCbPrintf(wstr, sizeof(wstr), wformat, wcells);
1860                         }
1861                     }
1862
1863                     if(wstr[0] != 0) {
1864                         size_t cbs;
1865                         StringCbLength(wstr, sizeof(wstr), &cbs);
1866                         cbs += sizeof(wchar_t);
1867                         assert(nct->credtext == NULL);
1868                         nct->credtext = PMALLOC(cbs);
1869                         StringCbCopy(nct->credtext, cbs, wstr);
1870                     } else {
1871                         /* something went wrong */
1872                         nct->credtext = NULL;
1873                     }
1874                 }
1875                 break;
1876
1877             case WMNC_CREDTEXT_LINK:
1878                 {
1879                     khui_htwnd_link * l;
1880                     wchar_t wid[KHUI_MAXCCH_HTLINK_FIELD];
1881                     wchar_t * wids;
1882
1883                     l = (khui_htwnd_link *) lParam;
1884
1885                     StringCchCopyN(wid, ARRAYLENGTH(wid), l->id, l->id_len);
1886                     wids = wcschr(wid, L':');
1887                         
1888                     if(!wids)
1889                         break;
1890                     else
1891                         wids++;
1892
1893 #ifdef DEBUG
1894                     assert(d->nc);
1895 #endif
1896
1897                     if(!wcscmp(wids, L"Enable")) {
1898                         SendDlgItemMessage(hwnd, IDC_NCAFS_OBTAIN, 
1899                                            BM_SETCHECK, BST_CHECKED, 0);
1900                         d->afs_enabled = TRUE;
1901                         khui_cw_enable_type(d->nc, afs_credtype_id, TRUE);
1902                         nc_dlg_enable(hwnd, TRUE);
1903                     }
1904                 }
1905                 break;
1906
1907             case WMNC_IDENTITY_CHANGE:
1908                 kmq_post_sub_msg(afs_sub, KMSG_CRED, 
1909                                  KMSG_CRED_DIALOG_NEW_IDENTITY, 0, 
1910                                  (void *) d->nc);
1911                 break;
1912                 
1913             case WMNC_AFS_UPDATE_ROWS:
1914                 afs_dlg_update_rows(hwnd, d);
1915
1916 #ifdef DEBUG
1917                 assert(d->nc);
1918 #endif
1919
1920                 PostMessage(d->nc->hwnd, KHUI_WM_NC_NOTIFY, 
1921                             MAKEWPARAM(0, WMNC_UPDATE_CREDTEXT), 0);
1922                 break;
1923             }
1924
1925             LeaveCriticalSection(&d->cs);
1926         }
1927         return TRUE;
1928
1929     case WM_NOTIFY:
1930         if(wParam == IDC_NCAFS_TOKENLIST) {
1931             LPNMHDR lpnmh = (LPNMHDR) lParam;
1932
1933             if(lpnmh->code == LVN_ITEMCHANGED) {
1934                 /* when an item in the list view is clicked, we
1935                    load the corresponding values into the edit and
1936                    combo boxes */
1937                 NMLISTVIEW *lpnmlv = (NMLISTVIEW *) lpnmh;
1938                 LVITEM lvi;
1939                 HWND hw;
1940                 int idx;
1941                 int row;
1942                 afs_dlg_data * d;
1943
1944                 if (!(lpnmlv->uChanged & LVIF_STATE) ||
1945                     !(lpnmlv->uNewState & LVIS_SELECTED) ||
1946                     (lpnmlv->iItem == -1))
1947
1948                     return TRUE;
1949
1950                 d = (afs_dlg_data *)(LONG_PTR) 
1951                     GetWindowLongPtr(hwnd, DWLP_USER);
1952
1953                 if (d == NULL)
1954                     return FALSE;
1955
1956                 EnterCriticalSection(&d->cs);
1957
1958                 hw = GetDlgItem(hwnd, IDC_NCAFS_TOKENLIST);
1959
1960                 idx = lpnmlv->iItem;
1961
1962                 ZeroMemory(&lvi, sizeof(lvi));
1963                 lvi.iItem = idx;
1964                 lvi.iSubItem = 0;
1965                 lvi.mask = LVIF_PARAM;
1966
1967                 if(!ListView_GetItem(hw, &lvi))
1968                     goto _done_notify_select;
1969
1970                 /* ok, now lvi.lParam should be the row of the token */
1971                 row = (int) lvi.lParam;
1972                 if(row < 0 || row >= d->creds.n_rows)
1973                     goto _done_notify_select;
1974
1975                 SetDlgItemText(hwnd, IDC_NCAFS_CELL, 
1976                                d->creds.rows[row].cell);
1977                 if(d->creds.rows[row].realm != NULL) {
1978                     SetDlgItemText(hwnd, IDC_NCAFS_REALM, 
1979                                    d->creds.rows[row].realm);
1980                 } else {
1981                     wchar_t wbuf[256];
1982                     int idx;
1983                         
1984                     LoadString(hResModule, IDS_NC_REALM_AUTO, wbuf, 
1985                                ARRAYLENGTH(wbuf));
1986                     idx = (int) SendDlgItemMessage(hwnd, IDC_NCAFS_REALM, 
1987                                                    CB_FINDSTRINGEXACT, 
1988                                                    (WPARAM) -1,
1989                                                    (LPARAM) wbuf);
1990                     SendDlgItemMessage(hwnd, IDC_NCAFS_REALM, CB_SETCURSEL,
1991                                        idx, 0);
1992                 }
1993                 SendDlgItemMessage(hwnd, IDC_NCAFS_METHOD, CB_SETCURSEL, 
1994                                    d->creds.rows[row].method, 0);
1995             _done_notify_select:
1996                 LeaveCriticalSection(&d->cs);
1997
1998             } else if (lpnmh->code == NM_DBLCLK) {
1999
2000                 LPNMITEMACTIVATE pnmi;
2001                 LVITEM lvi;
2002                 HWND hw;
2003                 afs_dlg_data * d;
2004                 int row;
2005                 int x,y;
2006                 RECT r;
2007
2008                 d = (afs_dlg_data *)(LONG_PTR) 
2009                     GetWindowLongPtr(hwnd, DWLP_USER);
2010
2011                 if (d == NULL)
2012                     return FALSE;
2013
2014                 EnterCriticalSection(&d->cs);
2015
2016                 pnmi = (LPNMITEMACTIVATE) lpnmh;
2017
2018                 hw = GetDlgItem(hwnd, IDC_NCAFS_TOKENLIST);
2019
2020                 ZeroMemory(&lvi, sizeof(lvi));
2021                 lvi.iItem = pnmi->iItem;
2022                 lvi.iSubItem = 0;
2023                 lvi.mask = LVIF_PARAM;
2024
2025                 if (!ListView_GetItem(hw, &lvi))
2026                     goto _done_notify_click;
2027
2028                 row = (int) lvi.lParam;
2029                 if(row < 0 || row >= d->creds.n_rows)
2030                     goto _done_notify_click;
2031
2032                 ListView_GetItemRect(hw, pnmi->iItem, &r, LVIR_SELECTBOUNDS);
2033                 x = (r.left + r.right) / 2;
2034                 y = (r.bottom);
2035
2036                 GetWindowRect(hw, &r);
2037                 y += r.top;
2038                 x += r.left;
2039
2040                 if (d->creds.rows[row].flags & DLGROW_FLAG_NOTOWNED) {
2041                     nc_dlg_show_tooltip(hwnd, 0,
2042                                         MAKEINTRESOURCE(IDS_NC_TT_CONFLICTD),
2043                                         MAKEINTRESOURCE(IDS_NC_TT_PROBLEM),
2044                                         2,
2045                                         x,y);
2046                 } else if (d->creds.rows[row].flags &
2047                            DLGROW_FLAG_EXPIRED) {
2048                     nc_dlg_show_tooltip(hwnd, 0,
2049                                         MAKEINTRESOURCE(IDS_NC_TT_EXPIRED),
2050                                         MAKEINTRESOURCE(IDS_NC_TT_DETAILS),
2051                                         1,
2052                                         x, y);
2053                 } else if (d->creds.rows[row].flags &
2054                            DLGROW_FLAG_EXISTS) {
2055                     nc_dlg_show_tooltip(hwnd, 0,
2056                                         MAKEINTRESOURCE(IDS_NC_TT_EXISTS),
2057                                         MAKEINTRESOURCE(IDS_NC_TT_DETAILS),
2058                                         1, x, y);
2059                 } else {
2060                     nc_dlg_show_tooltip(hwnd, 0,
2061                                         MAKEINTRESOURCE(IDS_NC_TT_NEW),
2062                                         MAKEINTRESOURCE(IDS_NC_TT_DETAILS),
2063                                         1, x, y);
2064                 }
2065
2066             _done_notify_click:
2067                 LeaveCriticalSection(&d->cs);
2068             }
2069         }
2070         return TRUE;
2071
2072     case WM_TIMER:
2073         {
2074             if(wParam == DLG_TOOLTIP_TIMER_ID) {
2075                 KillTimer(hwnd, DLG_TOOLTIP_TIMER_ID);
2076                 nc_dlg_hide_tooltip(hwnd, 0);
2077             }
2078         }
2079         return TRUE;
2080
2081     case WM_HELP:
2082         {
2083             static const DWORD ctx_help[] = {
2084                 IDC_NCAFS_OBTAIN, IDH_OBTAIN,
2085                 IDC_NCAFS_CELL, IDH_CELL,
2086                 IDC_NCAFS_REALM, IDH_REALM,
2087                 IDC_NCAFS_METHOD, IDH_METHOD,
2088                 IDC_NCAFS_ADD_TOKEN, IDH_ADD,
2089                 IDC_NCAFS_DELETE_TOKEN, IDH_DELETE,
2090                 IDC_NCAFS_TOKENLIST, IDH_TOKENLIST,
2091                 0
2092             };
2093
2094             LPHELPINFO hlp;
2095
2096             hlp = (LPHELPINFO) lParam;
2097
2098             if (hlp->iContextType != HELPINFO_WINDOW)
2099                 break;
2100
2101             afs_html_help(hlp->hItemHandle, L"::/popups_newcred.txt",
2102                           HH_TP_HELP_WM_HELP, (DWORD_PTR) ctx_help);
2103         }
2104         return TRUE;
2105     } /* switch(uMsg) */
2106
2107     return FALSE;
2108 }
2109
2110
2111 /* passed in to kcdb_credset_apply along with the afs_credset to adjust
2112    newly acquired credentials to include informatino derived from the
2113    new creds operation */
2114 khm_int32 KHMAPI 
2115 afs_adjust_token_ident_proc(khm_handle cred, void * vd)
2116 {
2117     wchar_t cell[MAXCELLCHARS];
2118     afs_ident_token_set * b = (afs_ident_token_set *) vd;
2119     afs_cred_list * l;
2120     khm_size cbbuf;
2121     int i;
2122
2123     l = b->l;
2124
2125     /* ASSUMPTION: for each user, there can be tokens for only one
2126        cell */
2127
2128     cbbuf = sizeof(cell);
2129
2130     if(KHM_FAILED(kcdb_cred_get_attr(cred, afs_attr_cell, NULL, cell, &cbbuf)))
2131         return KHM_ERROR_SUCCESS; /* remember, kcdb doesn't care if
2132                                      this run succeeded or not.  all
2133                                      it wants to know if whether or
2134                                      not we want to continue the
2135                                      search */
2136     
2137     for(i=0; i<l->n_rows; i++) {
2138         if((l->rows[i].flags & DLGROW_FLAG_DONE) && 
2139            !_wcsicmp(cell, l->rows[i].cell)) {
2140             khm_int32 method;
2141
2142             kcdb_cred_set_identity(cred, b->ident);
2143             if(l->rows[i].realm)
2144                 kcdb_cred_set_attr(cred, afs_attr_realm, l->rows[i].realm, 
2145                                    (khm_size)KCDB_CBSIZE_AUTO);
2146             else
2147                 kcdb_cred_set_attr(cred, afs_attr_realm, NULL, 0);
2148
2149             method = l->rows[i].method;
2150             kcdb_cred_set_attr(cred, afs_attr_method, &method, 
2151                                (khm_size)KCDB_CBSIZE_AUTO);
2152
2153             break;
2154         }
2155     }
2156
2157     return KHM_ERROR_SUCCESS;
2158 }
2159
2160 void
2161 afs_cred_write_ident_data(afs_dlg_data * d) {
2162     wchar_t * lru_cell = NULL;
2163     wchar_t * lru_realm = NULL;
2164     wchar_t * id_cell = NULL;
2165     khm_size cbidcell;
2166     khm_size cbcell;
2167     khm_size cbrealm;
2168     khm_size cbt;
2169     size_t cbz;
2170     khm_handle h_idc = NULL;
2171     khm_handle h_afs = NULL;
2172     khm_handle h_acells = NULL;
2173     khm_handle h_cellmap = NULL;
2174     wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
2175     khm_handle ident = NULL;
2176     afs_cred_list * l;
2177     int i;
2178
2179     l = &d->creds;
2180
2181     if (d->nc &&
2182         d->nc->n_identities > 0 &&
2183         d->nc->identities[0])
2184
2185         ident = d->nc->identities[0];
2186
2187     else if (d->config_dlg)
2188
2189         ident = d->ident;
2190
2191     if (!ident)
2192         return;
2193
2194     cbt = sizeof(idname);
2195     kcdb_identity_get_name(ident, idname, &cbt);
2196
2197     khc_open_space(csp_afscred, L"Cells", 0, &h_cellmap);
2198
2199     if(ident) {
2200         if(KHM_SUCCEEDED(kcdb_identity_get_config(ident,
2201                                                   KHM_FLAG_CREATE,
2202                                                   &h_idc))) {
2203             khc_open_space(h_idc, CSNAME_AFSCRED, 
2204                            KHM_FLAG_CREATE, &h_afs);
2205         }
2206
2207         if(h_afs) {
2208             khc_open_space(h_afs, L"Cells", KHM_FLAG_CREATE, 
2209                            &h_acells);
2210         }
2211     }
2212
2213     if (h_afs && d) {
2214         khc_write_int32(h_afs, L"AFSEnabled",
2215                         !!d->afs_enabled);
2216     }
2217
2218     if(khc_read_multi_string(csp_params, 
2219                              L"LRUCells", 
2220                              NULL,
2221                              &cbcell) == KHM_ERROR_TOO_LONG) {
2222         cbcell += MAXCELLCHARS * sizeof(wchar_t) * 
2223             l->n_rows;
2224         lru_cell = PMALLOC(cbcell);
2225         ZeroMemory(lru_cell, cbcell);
2226         cbt = cbcell;
2227                     
2228         khc_read_multi_string(csp_params,
2229                               L"LRUCells",
2230                               lru_cell,
2231                               &cbt);
2232     } else {
2233         cbcell = MAXCELLCHARS * sizeof(wchar_t) * l->n_rows + sizeof(wchar_t);
2234         if (l->n_rows > 0) {
2235             lru_cell = PMALLOC(cbcell);
2236             ZeroMemory(lru_cell, cbcell);
2237         } else {
2238             lru_cell = NULL;
2239             cbcell = 0;
2240         }
2241     }
2242
2243     if(khc_read_multi_string(csp_params,
2244                              L"LRURealms",
2245                              NULL,
2246                              &cbrealm) == KHM_ERROR_TOO_LONG) {
2247         cbrealm += MAXCELLCHARS * sizeof(wchar_t) * l->n_rows;
2248         lru_realm = PMALLOC(cbrealm);
2249         ZeroMemory(lru_realm, cbrealm);
2250         cbt = cbrealm;
2251
2252         khc_read_multi_string(csp_params,
2253                               L"LRURealms",
2254                               lru_realm,
2255                               &cbt);
2256     } else {
2257         cbrealm = MAXCELLCHARS * sizeof(wchar_t) * l->n_rows + sizeof(wchar_t);
2258         if (l->n_rows > 0) {
2259             lru_realm = PMALLOC(cbrealm);
2260             ZeroMemory(lru_realm, cbrealm);
2261         } else {
2262             lru_cell = NULL;
2263             cbrealm = 0;
2264         }
2265     }
2266
2267     cbidcell = MAXCELLCHARS * sizeof(wchar_t) * l->n_rows + sizeof(wchar_t);
2268     if (l->n_rows > 0) {
2269         id_cell = PMALLOC(cbidcell);
2270         ZeroMemory(id_cell, cbidcell);
2271     } else {
2272         id_cell = NULL;
2273         cbidcell = 0;
2274     }
2275
2276     for(i=0; i < l->n_rows; i++)
2277         if(!(l->rows[i].flags & DLGROW_FLAG_DELETED)) {
2278             khm_handle h_acell = NULL;
2279             
2280             if(!multi_string_find(lru_cell, 
2281                                   l->rows[i].cell, 0)) {
2282                 cbz = cbcell;
2283                 multi_string_append(lru_cell, &cbz, 
2284                                     l->rows[i].cell);
2285             }
2286
2287             if(l->rows[i].realm && 
2288                !multi_string_find(lru_realm, 
2289                                   l->rows[i].realm, 0)) {
2290                 cbz = cbrealm;
2291                 multi_string_append(lru_realm, &cbz, 
2292                                     l->rows[i].realm);
2293             }
2294
2295             cbz = cbidcell;
2296             multi_string_append(id_cell, &cbz, 
2297                                 l->rows[i].cell);
2298
2299             if(h_acells && 
2300                KHM_SUCCEEDED(khc_open_space(h_acells, 
2301                                             l->rows[i].cell, 
2302                                             KHM_FLAG_CREATE, 
2303                                             &h_acell))) {
2304                 wchar_t methodname[KHUI_MAXCCH_NAME];
2305
2306                 afs_get_method_name(l->rows[i].method,
2307                                     methodname,
2308                                     sizeof(methodname));
2309
2310                 khc_write_string(h_acell, L"MethodName", 
2311                                  methodname);
2312
2313                 if(l->rows[i].realm)
2314                     khc_write_string(h_acell, L"Realm", 
2315                                      l->rows[i].realm);
2316                 else
2317                     khc_write_string(h_acell, L"Realm", L"");
2318                 khc_close_space(h_acell);
2319             }
2320
2321             if (l->rows[i].flags & DLGROW_FLAG_DONE) {
2322                 if (h_cellmap) {
2323                     khc_write_string(h_cellmap,
2324                                      l->rows[i].cell,
2325                                      idname);
2326                 }
2327             }
2328         }
2329
2330     if (lru_cell)                
2331         khc_write_multi_string(csp_params,
2332                                L"LRUCells", lru_cell);
2333     if (lru_realm)
2334         khc_write_multi_string(csp_params,
2335                                L"LRURealms", lru_realm);
2336     if (id_cell)
2337         khc_write_multi_string(h_afs, L"Cells",
2338                                id_cell);
2339     else
2340         khc_write_multi_string(h_afs, L"Cells", L"\0");
2341
2342     if (d->config_dlg) {
2343         if (d->dirty)
2344             khui_cfg_set_flags_inst(&d->cfg, KHUI_CNFLAG_APPLIED,
2345                                     KHUI_CNFLAG_APPLIED |
2346                                     KHUI_CNFLAG_MODIFIED);
2347         else
2348             khui_cfg_set_flags_inst(&d->cfg, 0,
2349                                     KHUI_CNFLAG_MODIFIED);
2350     }
2351
2352     d->dirty = FALSE;
2353
2354     if(h_cellmap)
2355         khc_close_space(h_cellmap);
2356     if(h_idc)
2357         khc_close_space(h_idc);
2358     if(h_afs)
2359         khc_close_space(h_afs);
2360     if(h_acells)
2361         khc_close_space(h_acells);
2362     if(id_cell)
2363         PFREE(id_cell);
2364     if(lru_cell)
2365         PFREE(lru_cell);
2366     if(lru_realm)
2367         PFREE(lru_realm);
2368 }
2369
2370 khm_int32
2371 afs_msg_newcred(khm_int32 msg_subtype, 
2372                 khm_ui_4 uparam, 
2373                 void * vparam) {
2374
2375     switch(msg_subtype) {
2376     case KMSG_CRED_NEW_CREDS:
2377         {
2378             khui_new_creds * nc;
2379             khui_new_creds_by_type * nct;
2380             wchar_t wbuf[256];
2381             size_t cbsize;
2382
2383             nc = (khui_new_creds *) vparam;
2384
2385             nct = PMALLOC(sizeof(*nct));
2386             ZeroMemory(nct, sizeof(*nct));
2387
2388             nct->type = afs_credtype_id;
2389             nct->ordinal = 3;
2390
2391             LoadString(hResModule, IDS_AFS_NAME, wbuf, ARRAYLENGTH(wbuf));
2392             StringCbLength(wbuf, sizeof(wbuf), &cbsize);
2393             cbsize += sizeof(wchar_t);
2394
2395             nct->name = PMALLOC(cbsize);
2396             StringCbCopy(nct->name, cbsize, wbuf);
2397
2398             nct->h_module = hResModule;
2399             nct->dlg_proc = afs_dlg_proc;
2400             nct->dlg_template = MAKEINTRESOURCE(IDD_NC_AFS);
2401             nct->type_deps[nct->n_type_deps++] = krb5_credtype_id;
2402
2403             if (krb4_credtype_id < 0) {
2404                 kcdb_credtype_get_id(KRB4_CREDTYPE_NAME,
2405                                      &krb4_credtype_id);
2406             }
2407             if (krb4_credtype_id >= 0) {
2408                 nct->type_deps[nct->n_type_deps++] =
2409                     krb4_credtype_id;
2410             }
2411
2412             khui_cw_add_type(nc, nct);
2413         }
2414         break;
2415
2416     case KMSG_CRED_RENEW_CREDS:
2417         {
2418             khui_new_creds * nc;
2419             khui_new_creds_by_type * nct;
2420
2421             nc = (khui_new_creds *) vparam;
2422
2423             nct = PMALLOC(sizeof(*nct));
2424             ZeroMemory(nct, sizeof(*nct));
2425
2426             nct->type = afs_credtype_id;
2427             nct->type_deps[nct->n_type_deps++] = krb5_credtype_id;
2428             if (krb4_credtype_id < 0) {
2429                 kcdb_credtype_get_id(KRB4_CREDTYPE_NAME,
2430                                      &krb4_credtype_id);
2431             }
2432             if (krb4_credtype_id >= 0) {
2433                 nct->type_deps[nct->n_type_deps++] =
2434                     krb4_credtype_id;
2435             }
2436
2437             khui_cw_add_type(nc, nct);
2438         }
2439         break;
2440
2441     case KMSG_CRED_DIALOG_PRESTART:
2442         {
2443             khui_new_creds * nc;
2444             khui_new_creds_by_type * nct = NULL;
2445             HWND hwnd;
2446
2447             nc = (khui_new_creds *) vparam;
2448             khui_cw_find_type(nc, afs_credtype_id, &nct);
2449
2450             if(!nct)
2451                 break;
2452
2453             hwnd = nct->hwnd_panel;
2454             if (!hwnd)
2455                 break;
2456
2457             PostMessage(hwnd, KHUI_WM_NC_NOTIFY,
2458                         MAKEWPARAM(0,WMNC_DIALOG_SETUP), 0);
2459         }
2460         break;
2461
2462     case KMSG_CRED_DIALOG_NEW_IDENTITY:
2463         {
2464             khui_new_creds * nc;
2465             khui_new_creds_by_type * nct = NULL;
2466             afs_dlg_data * d;
2467
2468             nc = (khui_new_creds *) vparam;
2469             khui_cw_find_type(nc, afs_credtype_id, &nct);
2470
2471             if(nct == NULL)
2472                 break;
2473
2474             d = (afs_dlg_data *) nct->aux;
2475
2476             if(d == NULL)
2477                 break;
2478
2479             EnterCriticalSection(&d->cs);
2480
2481             if (nct->aux == 0) {
2482                 LeaveCriticalSection(&d->cs);
2483                 break;
2484             }
2485
2486             /* we should load up the selected tokens for this
2487                identity */
2488             if(nc->n_identities == 0) {
2489                 LeaveCriticalSection(&d->cs);
2490                 /* no identities selected. nothing to do */
2491                 break;
2492             }
2493
2494             afs_cred_get_identity_creds(&d->creds, nc->identities[0],
2495                                         &d->afs_enabled);
2496
2497             LeaveCriticalSection(&d->cs);
2498
2499             PostMessage(nct->hwnd_panel, KHUI_WM_NC_NOTIFY,
2500                         MAKEWPARAM(0, WMNC_AFS_UPDATE_ROWS), 0);
2501         }
2502         break;
2503
2504     case KMSG_CRED_PROCESS:
2505         {
2506             khui_new_creds * nc;
2507             khui_new_creds_by_type * nct = NULL;
2508             afs_cred_list tlist;
2509             afs_cred_list * l;
2510             int i;
2511             BOOL failed = FALSE;    /* one or more cells failed */
2512             BOOL succeeded = FALSE; /* one or more cells succeeded */
2513             BOOL free_tlist = FALSE;
2514             khm_handle ident = NULL;
2515             afs_dlg_data * d = NULL;
2516             BOOL get_tokens = TRUE;
2517             BOOL ident_renew_triggered = TRUE;
2518             khm_handle csp_afscred = NULL;
2519             khm_handle csp_cells = NULL;
2520
2521             nc = (khui_new_creds *) vparam;
2522             khui_cw_find_type(nc, afs_credtype_id, &nct);
2523
2524             if(!nct)
2525                 break;
2526
2527             _begin_task(0);
2528             _report_cs0(KHERR_INFO,
2529                         L"Getting AFS tokens...");
2530             _describe();
2531
2532             if(nc->result != KHUI_NC_RESULT_PROCESS &&
2533                nc->subtype != KMSG_CRED_RENEW_CREDS) {
2534                 /* nothing to do */
2535                 khui_cw_set_response(nc, afs_credtype_id,
2536                                      KHUI_NC_RESPONSE_SUCCESS);
2537
2538                 _report_cs0(KHERR_INFO, 
2539                             L"Cancelling");
2540                 _end_task();
2541                 break;
2542             }
2543
2544             /* we can't proceed if Kerberos 5 has failed */
2545             if(!khui_cw_type_succeeded(nc, krb5_credtype_id)) {
2546                 khui_cw_set_response(nc, afs_credtype_id,
2547                                      KHUI_NC_RESPONSE_FAILED);
2548
2549                 _report_cs0(KHERR_INFO,
2550                             L"Kerberos 5 plugin failed to process credentials request.  Aborting");
2551                 _end_task();
2552                 break;
2553             }
2554
2555             if (nc->subtype == KMSG_CRED_RENEW_CREDS) {
2556
2557                 if (nc->ctx.scope == KHUI_SCOPE_IDENT ||
2558
2559                     (nc->ctx.scope == KHUI_SCOPE_CREDTYPE &&
2560                      nc->ctx.cred_type == afs_credtype_id) ||
2561
2562                     (nc->ctx.scope == KHUI_SCOPE_CRED &&
2563                      nc->ctx.cred_type == afs_credtype_id)) {
2564
2565                     _report_cs1(KHERR_INFO,
2566                                 L"AFS Renew Creds :: ident %1!p!", 
2567                                 _cptr(nc->ctx.identity));
2568
2569                 } else {
2570
2571                     _report_cs0(KHERR_INFO,
2572                                 L"Renew request not applicable to AFS");
2573                     _end_task();
2574                     break;
2575
2576                 }
2577
2578                 if (nc->ctx.identity != NULL) {
2579                     ident = nc->ctx.identity;
2580                 } else {
2581                     khui_cw_set_response(nc, afs_credtype_id,
2582                                          KHUI_NC_RESPONSE_FAILED);
2583
2584                     _report_cs0(KHERR_INFO,
2585                                 L"No identity specified.  Aborting");
2586                     _end_task();
2587                     break;
2588                 }
2589
2590                 ZeroMemory(&tlist, sizeof(tlist));
2591                 l = &tlist;
2592                 free_tlist = TRUE;
2593
2594                 afs_cred_get_identity_creds(l, ident, NULL);
2595
2596                 /* if the identity has any tokens associated with it
2597                    that aren't persistent, we should renew those as
2598                    well. */
2599                 afs_cred_get_context_creds(l, &nc->ctx);
2600
2601                 if (nc->ctx.scope == KHUI_SCOPE_CREDTYPE ||
2602                     nc->ctx.scope == KHUI_SCOPE_CRED) {
2603
2604                     ident_renew_triggered = FALSE;
2605
2606                 }
2607
2608             } else {
2609                 _report_cs1(KHERR_INFO,
2610                             L"AFS New Creds :: ident %1!p!",
2611                             _cptr(nc->identities[0]));
2612
2613                 d = (afs_dlg_data *) nct->aux;
2614                 if(!d) {
2615                     _report_cs0(KHERR_INFO,
2616                                 L"No dialog data found.  Aborting");
2617
2618                     khui_cw_set_response(nc, afs_credtype_id,
2619                                          KHUI_NC_RESPONSE_FAILED);
2620                     _end_task();
2621                     break;
2622                 }
2623
2624                 EnterCriticalSection(&d->cs);
2625
2626                 l = &d->creds;
2627
2628                 ident = nc->identities[0];
2629                 if (!ident) {
2630                     LeaveCriticalSection(&d->cs);
2631
2632                     _report_cs0(KHERR_INFO,
2633                                 L"No identity specified. Aborting");
2634
2635                     khui_cw_set_response(nc, afs_credtype_id,
2636                                          KHUI_NC_RESPONSE_FAILED);
2637
2638                     _end_task();
2639                     break;
2640                 }
2641
2642                 get_tokens = d->afs_enabled;
2643             }
2644
2645             if (!get_tokens)
2646                 goto _skip_tokens;
2647
2648             if (KHM_SUCCEEDED(kmm_get_plugin_config(AFS_PLUGIN_NAME, 0,
2649                                                     &csp_afscred)))
2650                 khc_open_space(csp_afscred, L"Cells", 0, &csp_cells);
2651
2652             /* looks like k5 worked.  Now see about getting those
2653                tokens */
2654             for(i=0; i<l->n_rows; i++) {
2655                 int code;
2656                 char cell[MAXCELLCHARS];
2657                 char realm[MAXCELLCHARS];
2658                 khm_handle ctoken;
2659                 FILETIME ft_old;
2660                 FILETIME ft_new;
2661                 time_t new_exp = 0;
2662                 khm_size cb;
2663                 khm_int32 method = AFS_TOKEN_AUTO;
2664                 khm_handle csp_cell = NULL;
2665
2666                 if (l->rows[i].flags &
2667                     (DLGROW_FLAG_DONE | DLGROW_FLAG_DELETED))
2668
2669                     continue;
2670
2671                 ZeroMemory(cell, sizeof(cell));
2672                 ZeroMemory(realm, sizeof(realm));
2673
2674                 UnicodeStrToAnsi(cell, sizeof(cell), l->rows[i].cell);
2675                 if (l->rows[i].realm != NULL)
2676                     UnicodeStrToAnsi(realm, sizeof(realm), 
2677                                      l->rows[i].realm);
2678
2679                 ZeroMemory(&ft_old, sizeof(ft_old));
2680
2681                 if (!ident_renew_triggered &&
2682                     (ctoken = afs_find_token(NULL, l->rows[i].cell))) {
2683
2684                     cb = sizeof(ft_old);
2685                     kcdb_cred_get_attr(ctoken, KCDB_ATTR_EXPIRE,
2686                                        NULL, &ft_old, &cb);
2687
2688                     kcdb_cred_release(ctoken);
2689                 }
2690
2691                 if (l->rows[i].method == AFS_TOKEN_AUTO && csp_cells &&
2692                     KHM_SUCCEEDED(khc_open_space(csp_cells,
2693                                                  l->rows[i].cell, 0,
2694                                                  &csp_cell))) {
2695
2696                     if (KHM_FAILED(khc_read_int32(csp_cell, L"Method", &method))) {
2697                         method = l->rows[i].method;
2698                     } else {
2699                         _report_cs3(KHERR_INFO,
2700                                     L"Overriding method %1!d! with global default %2!d! for cell %3!s!",
2701                                     _int32(l->rows[i].method),
2702                                     _int32(method),
2703                                     _cstr(l->rows[i].cell));
2704                         _resolve();
2705                     }
2706
2707                     khc_close_space(csp_cell);               
2708                 } else {
2709                     method = l->rows[i].method;
2710                 }
2711
2712                 _report_cs3(KHERR_INFO,
2713                             L"Getting tokens for cell %1!S! with realm %2!S! using method %3!d!",
2714                             _cstr(cell),
2715                             _cstr(realm),
2716                             _int32(method));
2717                 _resolve();
2718
2719                 /* make the call */
2720                 code = afs_klog(ident, "", cell, realm, 0, 
2721                                 method, &new_exp);
2722
2723                 _report_cs1(KHERR_INFO,
2724                             L"klog returns code %1!d!",
2725                             _int32(code));
2726
2727                 if(code) {
2728                     failed = TRUE;
2729                     l->rows[i].flags &= ~DLGROW_FLAG_DONE;
2730
2731                     if (!kherr_is_error()) {
2732                         /* failed to get tokens, but no error was reported */
2733                         _report_sr1(KHERR_ERROR, IDS_ERR_GENERAL,
2734                                     _cptr(cell));
2735                         _resolve();
2736                     }
2737
2738                 } else {
2739                     l->rows[i].flags |= DLGROW_FLAG_DONE;
2740                     succeeded = TRUE;
2741
2742                     if (new_exp &&
2743                         !ident_renew_triggered) {
2744                         TimetToFileTime(new_exp, &ft_new);
2745
2746                         if (CompareFileTime(&ft_old, &ft_new) >= 0) {
2747                             /* getting a new token didn't improve the
2748                                situation much.  We only get here if we
2749                                were trying to renew tokens. So we try
2750                                to trigger an identity renewal.  Doing
2751                                so should get us new initial tickets
2752                                which will allow us to get a better
2753                                token. */
2754
2755                             khui_action_context ctx;
2756
2757                             _reportf(L"Renewal of AFS tokens for cell %s failed to get a longer token.  Triggering identity renewal", l->rows[i].cell);
2758
2759                             khui_context_create(&ctx,
2760                                                 KHUI_SCOPE_IDENT,
2761                                                 nc->ctx.identity,
2762                                                 KCDB_CREDTYPE_INVALID,
2763                                                 NULL);
2764                             khui_action_trigger(KHUI_ACTION_RENEW_CRED,
2765                                                 &ctx);
2766
2767                             khui_context_release(&ctx);
2768
2769                             ident_renew_triggered = TRUE;
2770                         }
2771                     }
2772                 }
2773             }
2774
2775         _skip_tokens:
2776
2777             if(failed) {
2778                 /* we should indicate errors if anything went wrong */
2779                 khui_cw_set_response(nc, afs_credtype_id, 
2780                                      KHUI_NC_RESPONSE_FAILED);
2781             } else {
2782                 khui_cw_set_response(nc, afs_credtype_id,
2783                                      KHUI_NC_RESPONSE_SUCCESS);
2784             }
2785
2786             if (succeeded && nc->subtype == KMSG_CRED_RENEW_CREDS) {
2787                 afs_ident_token_set b;
2788
2789                 afs_list_tokens_internal();
2790
2791                 /* the tokens that we just acquired need adjusting to
2792                    include the realm, method and identity information
2793                    derived from the new creds operation.  this is done
2794                    in afs_adjust_token_ident_proc */
2795                 b.ident = ident;
2796                 b.l = l;
2797                 b.add_new = FALSE;
2798                 b.update_info = FALSE;
2799
2800                 kcdb_credset_apply(afs_credset, afs_adjust_token_ident_proc, 
2801                                    (void *) &b);
2802
2803                 kcdb_credset_collect(NULL, afs_credset, NULL, 
2804                                      afs_credtype_id, NULL);
2805
2806             } else if (nc->subtype == KMSG_CRED_NEW_CREDS) {
2807                 afs_ident_token_set b;
2808
2809                 afs_list_tokens_internal();
2810
2811                 /* the tokens that we just acquired need adjusting to
2812                    include the realm, method and identity information
2813                    derived from the new creds operation.  this is done
2814                    in afs_adjust_token_ident_proc */
2815                 b.ident = ident;
2816                 b.l = l;
2817                 b.add_new = FALSE;
2818                 b.update_info = FALSE;
2819
2820                 kcdb_credset_apply(afs_credset, afs_adjust_token_ident_proc, 
2821                                    (void *) &b);
2822
2823                 kcdb_credset_collect(NULL, afs_credset, NULL, 
2824                                      afs_credtype_id, NULL);
2825
2826                 afs_cred_write_ident_data(d);
2827             }
2828
2829             if (d)
2830                 LeaveCriticalSection(&d->cs);
2831
2832             if (free_tlist) {
2833                 afs_cred_free_rows(&tlist);
2834             }
2835
2836             if (csp_afscred)
2837                 khc_close_space(csp_afscred);
2838
2839             if (csp_cells)
2840                 khc_close_space(csp_cells);
2841
2842             _end_task();
2843         }
2844         break;
2845
2846     case KMSG_CRED_END:
2847         {
2848             khui_new_creds * nc;
2849             khui_new_creds_by_type * nct;
2850
2851             nc = (khui_new_creds *) vparam;
2852             khui_cw_find_type(nc, afs_credtype_id, &nct);
2853
2854             if(!nct)
2855                 break;
2856
2857             khui_cw_del_type(nc, afs_credtype_id);
2858     
2859             if (nct->name)
2860                 PFREE(nct->name);
2861             if (nct->credtext)
2862                 PFREE(nct->credtext);
2863
2864             PFREE(nct);
2865         }
2866         break;
2867     }
2868
2869     return KHM_ERROR_SUCCESS;
2870 }