bozo: Introduce bnode_Wait()
[openafs.git] / src / WINNT / netidmgr_plugin / afsplugin.c
1 /*
2  * Copyright (c) 2005,2006 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<kcreddb.h>
29 #include<khmsgtypes.h>
30 #include<kherror.h>
31 #include<khuidefs.h>
32 #include<commctrl.h>
33 #include<htmlhelp.h>
34 #include<assert.h>
35
36 static BOOL initialized = FALSE;
37 khm_int32 afs_credtype_id = -1;
38 khm_int32 krb5_credtype_id = -1;
39 khm_int32 krb4_credtype_id = -1;
40 khm_int32 afs_msg_type_id = -1;
41 khm_int32 afs_type_principal = -1;
42 khm_int32 afs_type_method = -1;
43 khm_int32 afs_attr_client_princ = -1;
44 khm_int32 afs_attr_server_princ = -1;
45 khm_int32 afs_attr_cell = -1;
46 khm_int32 afs_attr_method = -1;
47 khm_int32 afs_attr_realm = -1;
48 khm_handle afs_credset = NULL;
49 khm_handle afs_sub = NULL;      /* AFS message subscription */
50
51 khm_int32 action_id_afs_help = 0;
52
53 /* forward dcls */
54 khm_int32 KHMAPI
55 afs_msg_system(khm_int32 msg_subtype, khm_ui_4 uparam, void * vparam);
56
57 khm_int32 KHMAPI
58 afs_msg_kcdb(khm_int32 msg_subtype, khm_ui_4 uparam, void * vparam);
59
60 khm_int32 KHMAPI
61 afs_msg_cred(khm_int32 msg_subtype, khm_ui_4 uparam, void * vparam);
62
63 khm_int32 KHMAPI
64 afs_msg_act(khm_int32 msg_subtype, khm_ui_4 uparam, void * vparam);
65
66 khm_int32 KHMAPI
67 afs_msg_ext(khm_int32 msg_subtype, khm_ui_4 uparam, void * vparam);
68
69 /* AFS help menu extensions */
70
71 /* some of the functions we will be calling are only available on API
72    version 7 and above of Network Identity Manager.  Since these
73    aren't critical, we allow building using API version 5 or above,
74    but conditionally use the newer functionality if the plug-in is
75    loaded by a newer version of Network Identity Manager. */
76
77 #if KH_VERSION_API < 7
78
79 HMODULE hm_netidmgr;
80
81 /* declarations from version 7 of the API */
82 void
83 (KHMAPI * pkhui_action_lock)(void);
84
85 void
86 (KHMAPI * pkhui_action_unlock)(void);
87
88 void
89 (KHMAPI * pkhui_refresh_actions)(void);
90
91 typedef khm_int32
92 (KHMAPI * khm_ui_callback)(HWND hwnd_main_wnd, void * rock);
93
94 khm_int32
95 (KHMAPI * pkhui_request_UI_callback)(khm_ui_callback cb,
96                                      void * rock);
97
98 #endif
99
100 /* AFS plugin callback */
101 khm_int32 KHMAPI
102 afs_plugin_cb(khm_int32 msg_type,
103               khm_int32 msg_subtype,
104               khm_ui_4 uparam,
105               void * vparam)
106 {
107     if (msg_type == KMSG_SYSTEM)
108         return afs_msg_system(msg_subtype, uparam, vparam);
109     if (msg_type == KMSG_KCDB)
110         return afs_msg_kcdb(msg_subtype, uparam, vparam);
111     if (msg_type == KMSG_CRED)
112         return afs_msg_cred(msg_subtype, uparam, vparam);
113     if (msg_type == KMSG_ACT)
114         return afs_msg_act(msg_subtype, uparam, vparam);
115     if (msg_type == afs_msg_type_id)
116         return afs_msg_ext(msg_subtype, uparam, vparam);
117
118     return KHM_ERROR_SUCCESS;
119 }
120
121 /* ktc_principal attribute type */
122 /* String */
123
124 khm_int32 KHMAPI
125 afs_type_principal_toString(const void * d,
126                             khm_size cbd,
127                             wchar_t * buffer,
128                             khm_size * cb_buf,
129                             khm_int32 flags)
130 {
131     size_t cbsize;
132     struct ktc_principal * p;
133     wchar_t sprinc[512] = L"";
134
135     if(!cb_buf)
136         return KHM_ERROR_INVALID_PARAM;
137
138     p = (struct ktc_principal *) d;
139
140     // assume this works.
141     afs_princ_to_string(p, sprinc, sizeof(sprinc));
142     StringCbLength(sprinc, sizeof(sprinc), &cbsize);
143     cbsize += sizeof(wchar_t);
144
145     if(!buffer || *cb_buf < cbsize) {
146         *cb_buf = cbsize;
147         return KHM_ERROR_TOO_LONG;
148     }
149
150     StringCbCopy(buffer, *cb_buf, sprinc);
151
152     *cb_buf = cbsize;
153
154     return KHM_ERROR_SUCCESS;
155 }
156
157 khm_boolean KHMAPI
158 afs_type_principal_isValid(const void * d,
159                            khm_size cbd)
160 {
161     /*TODO: check for more inconsistencies */
162     if(cbd != sizeof(struct ktc_principal))
163         return FALSE;
164     return TRUE;
165 }
166
167 khm_int32 KHMAPI
168 afs_type_principal_comp(const void * d1,
169                         khm_size cbd1,
170                         const void * d2,
171                         khm_size cbd2)
172 {
173     struct ktc_principal * p1 = (struct ktc_principal *) d1;
174     struct ktc_principal * p2 = (struct ktc_principal *) d2;
175     int r;
176
177     r = strcmp(p1->name, p2->name);
178     if(r != 0)
179         return r;
180     r = strcmp(p1->instance, p2->instance);
181     if(r != 0)
182         return r;
183     r = strcmp(p1->cell, p2->cell);
184     return r;
185 }
186
187 khm_int32 KHMAPI
188 afs_type_principal_dup(const void * d_src,
189                        khm_size cbd_src,
190                        void * d_dst,
191                        khm_size * cbd_dst)
192 {
193     if(!d_dst || *cbd_dst < sizeof(struct ktc_principal)) {
194         *cbd_dst = sizeof(struct ktc_principal);
195         return KHM_ERROR_TOO_LONG;
196     }
197
198     memcpy(d_dst, d_src, sizeof(struct ktc_principal));
199     *cbd_dst = sizeof(struct ktc_principal);
200
201     return KHM_ERROR_SUCCESS;
202 }
203
204 khm_int32 KHMAPI
205 afs_type_method_toString(const void * data,
206                          khm_size     cb_data,
207                          wchar_t *    s_buf,
208                          khm_size *   pcb_s_buf,
209                          khm_int32    flags) {
210     khm_int32 * pmethod = (khm_int32 *) data;
211     wchar_t wbuf[KHUI_MAXCCH_LONG_DESC];
212     khm_size cb;
213
214     if (!data || cb_data != sizeof(khm_int32))
215         return KHM_ERROR_INVALID_PARAM;
216
217     wbuf[0] = L'\0';
218     if (!afs_method_describe(*pmethod, flags, wbuf, sizeof(wbuf))) {
219         LoadString(hResModule,
220                    IDS_NC_METHOD_INVALID,
221                    wbuf,
222                    ARRAYLENGTH(wbuf));
223     }
224
225     StringCbLength(wbuf, sizeof(wbuf), &cb);
226     cb += sizeof(wchar_t);
227
228     if (!s_buf || *pcb_s_buf < cb) {
229         *pcb_s_buf = cb;
230         return KHM_ERROR_TOO_LONG;
231     } else {
232         StringCbCopy(s_buf, *pcb_s_buf, wbuf);
233         *pcb_s_buf = cb;
234         return KHM_ERROR_SUCCESS;
235     }
236 }
237
238 /* process KMSG_SYSTEM messages */
239 khm_int32 KHMAPI
240 afs_msg_system(khm_int32 msg_subtype,
241                khm_ui_4 uparam,
242                void * vparam)
243 {
244     khm_int32 rv = KHM_ERROR_UNKNOWN;
245
246     switch(msg_subtype) {
247     case KMSG_SYSTEM_INIT:
248
249         /* If we are building against an older SDK, we should try to
250            load newer APIs if it's available at run-time. */
251 #if KH_VERSION_API < 7
252         do {
253             khm_version libver;
254             khm_ui_4 apiver;
255
256             khm_get_lib_version(&libver, &apiver);
257
258             if (apiver < 7)
259                 break;
260
261             hm_netidmgr = LoadLibrary(NIMDLLNAME);
262
263             if (hm_netidmgr == NULL)
264                 break;
265
266             pkhui_action_lock = (void (KHMAPI *)(void))
267                 GetProcAddress(hm_netidmgr, API_khui_action_lock);
268             pkhui_action_unlock = (void (KHMAPI *)(void))
269                 GetProcAddress(hm_netidmgr, API_khui_action_unlock);
270             pkhui_refresh_actions = (void (KHMAPI *)(void))
271                 GetProcAddress(hm_netidmgr, API_khui_refresh_actions);
272             pkhui_request_UI_callback = (khm_int32 (KHMAPI *)(khm_ui_callback, void *))
273                 GetProcAddress(hm_netidmgr, API_khui_request_UI_callback);
274
275         } while (FALSE);
276 #endif
277
278         /* Add the icon now.  On NIM v2.x, doing so after tokens were
279            reported may result in a deadlock as we try to switch to
280            the UI thread and the UI thread is blocked on a resource
281            request to this plug-in. */
282         afs_icon_set_state(AFSICON_SERVICE_STOPPED, NULL);
283
284         /* Perform critical registrations and data structure
285            initalization */
286         {
287             kcdb_credtype ct;
288             wchar_t buf[KCDB_MAXCCH_LONG_DESC];
289             size_t cbsize;
290             kcdb_attrib att;
291             khm_handle csp_afscred = NULL;
292             khm_int32 disable_afscreds = FALSE;
293
294             ZeroMemory(&ct, sizeof(ct));
295             /* first of all, register the AFS token credential type */
296             ct.id = KCDB_CREDTYPE_AUTO;
297             ct.name = AFS_CREDTYPE_NAME;
298
299             if(LoadString(hResModule,
300                           IDS_AFS_SHORT_DESC,
301                           buf,
302                           ARRAYLENGTH(buf)) != 0) {
303                 StringCbLength(buf, sizeof(buf), &cbsize);
304                 cbsize += sizeof(wchar_t);
305                 ct.short_desc = PMALLOC(cbsize);
306                 StringCbCopy(ct.short_desc, cbsize, buf);
307             } else
308                 ct.short_desc = NULL;
309
310             if(LoadString(hResModule,
311                           IDS_AFS_LONG_DESC,
312                           buf,
313                           ARRAYLENGTH(buf)) != 0) {
314                 StringCbLength(buf, sizeof(buf), &cbsize);
315                 cbsize += sizeof(wchar_t);
316                 ct.long_desc = PMALLOC(cbsize);
317                 StringCbCopy(ct.long_desc, cbsize, buf);
318             } else
319                 ct.long_desc = NULL;
320
321             ct.icon = LoadImage(hResModule,
322                                 MAKEINTRESOURCE(IDI_AFSTOKEN),
323                                 IMAGE_ICON,
324                                 0, 0, LR_DEFAULTSIZE);
325
326             kmq_create_subscription(afs_plugin_cb, &afs_sub);
327             ct.sub = afs_sub;
328
329             kcdb_credtype_register(&ct, &afs_credtype_id);
330
331             /* register the attribute types */
332             {
333                 kcdb_type type;
334
335                 ZeroMemory(&type, sizeof(type));
336                 type.comp = afs_type_principal_comp;
337                 type.dup = afs_type_principal_dup;
338                 type.isValid = afs_type_principal_isValid;
339                 type.toString = afs_type_principal_toString;
340                 type.name = AFS_TYPENAME_PRINCIPAL;
341                 type.id = KCDB_TYPE_INVALID;
342                 type.cb_max = sizeof(struct ktc_principal);
343                 type.cb_min = sizeof(struct ktc_principal);
344                 type.flags = KCDB_TYPE_FLAG_CB_FIXED;
345
346                 if(KHM_FAILED(kcdb_type_register(&type,
347                                                  &afs_type_principal)))
348                     goto _exit_init;
349             }
350
351             {
352                 kcdb_type type;
353                 kcdb_type *ti32 = NULL;
354
355                 kcdb_type_get_info(KCDB_TYPE_INT32, &ti32);
356
357                 ZeroMemory(&type, sizeof(type));
358                 type.comp = ti32->comp;
359                 type.dup = ti32->dup;
360                 type.isValid = ti32->isValid;
361                 type.toString = afs_type_method_toString;
362                 type.name = AFS_TYPENAME_METHOD;
363                 type.id = KCDB_TYPE_INVALID;
364                 type.cb_max = sizeof(khm_int32);
365                 type.cb_min = sizeof(khm_int32);
366                 type.flags = KCDB_TYPE_FLAG_CB_FIXED;
367
368                 if(KHM_FAILED(kcdb_type_register(&type,
369                                                  &afs_type_method))) {
370                     kcdb_type_release_info(ti32);
371                     goto _exit_init;
372                 }
373
374                 kcdb_type_release_info(ti32);
375             }
376
377             /* now register the attributes */
378             {
379                 wchar_t short_desc[KCDB_MAXCCH_SHORT_DESC];
380
381                 ZeroMemory(&att, sizeof(att));
382
383                 att.type = KCDB_TYPE_STRING;
384                 att.name = AFS_ATTRNAME_CELL;
385                 LoadString(hResModule,
386                            IDS_ATTR_CELL_SHORT_DESC,
387                            short_desc,
388                            ARRAYLENGTH(short_desc));
389                 att.short_desc = short_desc;
390                 att.long_desc = NULL;
391                 att.id = KCDB_ATTR_INVALID;
392                 att.flags = KCDB_ATTR_FLAG_TRANSIENT;
393
394                 if(KHM_FAILED(rv = kcdb_attrib_register(&att,
395                                                         &afs_attr_cell)))
396                     goto _exit_init;
397             }
398
399             {
400                 wchar_t short_desc[KCDB_MAXCCH_SHORT_DESC];
401
402                 ZeroMemory(&att, sizeof(att));
403
404                 att.type = KCDB_TYPE_STRING;
405                 att.name = AFS_ATTRNAME_REALM;
406                 LoadString(hResModule,
407                            IDS_ATTR_REALM_SHORT_DESC,
408                            short_desc,
409                            ARRAYLENGTH(short_desc));
410                 att.short_desc = short_desc;
411                 att.long_desc = NULL;
412                 att.id = KCDB_ATTR_INVALID;
413                 att.flags = KCDB_ATTR_FLAG_TRANSIENT;
414
415                 if(KHM_FAILED(rv = kcdb_attrib_register(&att,
416                                                         &afs_attr_realm)))
417                     goto _exit_init;
418             }
419
420             {
421                 wchar_t short_desc[KCDB_MAXCCH_SHORT_DESC];
422
423                 ZeroMemory(&att, sizeof(att));
424
425                 att.type = afs_type_method;
426                 att.name = AFS_ATTRNAME_METHOD;
427                 LoadString(hResModule,
428                            IDS_ATTR_METHOD_SHORT_DESC,
429                            short_desc,
430                            ARRAYLENGTH(short_desc));
431                 att.short_desc = short_desc;
432                 att.long_desc = NULL;
433                 att.id = KCDB_ATTR_INVALID;
434                 att.flags = KCDB_ATTR_FLAG_TRANSIENT;
435
436                 if(KHM_FAILED(rv = kcdb_attrib_register(&att,
437                                                         &afs_attr_method)))
438                     goto _exit_init;
439             }
440
441             {
442                 wchar_t short_desc[KCDB_MAXCCH_SHORT_DESC];
443
444                 ZeroMemory(&att, sizeof(att));
445
446                 att.type = afs_type_principal;
447                 att.name = AFS_ATTRNAME_CLIENT_PRINC;
448                 LoadString(hResModule,
449                            IDS_ATTR_CLIENT_PRINC_SHORT_DESC,
450                            short_desc,
451                            ARRAYLENGTH(short_desc));
452                 att.short_desc = short_desc;
453                 att.long_desc = NULL;
454                 att.id = KCDB_ATTR_INVALID;
455                 att.flags = KCDB_ATTR_FLAG_TRANSIENT;
456
457                 if(KHM_FAILED(rv = kcdb_attrib_register(&att, &afs_attr_client_princ)))
458                     goto _exit_init;
459             }
460
461             {
462                 wchar_t short_desc[KCDB_MAXCCH_SHORT_DESC];
463
464                 ZeroMemory(&att, sizeof(att));
465
466                 att.type = afs_type_principal;
467                 att.name = AFS_ATTRNAME_SERVER_PRINC;
468                 LoadString(hResModule,
469                            IDS_ATTR_SERVER_PRINC_SHORT_DESC,
470                            short_desc, ARRAYLENGTH(short_desc));
471                 att.short_desc = short_desc;
472                 att.long_desc = NULL;
473                 att.id = KCDB_ATTR_INVALID;
474                 att.flags = KCDB_ATTR_FLAG_TRANSIENT;
475
476                 if(KHM_FAILED(rv = kcdb_attrib_register(&att, &afs_attr_server_princ)))
477                     goto _exit_init;
478             }
479
480             /* afs_credset is our stock credentials set that we
481                use for all our credset needs (instead of creating
482                a new one every time) */
483
484             if(KHM_FAILED(rv = kcdb_credset_create(&afs_credset)))
485                 goto _exit_init;
486
487             if(KHM_FAILED(rv = kcdb_credtype_get_id(KRB5_CREDTYPE_NAME,
488                                                     &krb5_credtype_id)))
489                 goto _exit_init;
490
491             /* register the configuration nodes */
492             {
493                 khui_config_node node_ident;
494                 khui_config_node_reg reg;
495                 wchar_t wshort_desc[KHUI_MAXCCH_SHORT_DESC];
496                 wchar_t wlong_desc[KHUI_MAXCCH_LONG_DESC];
497
498                 if (KHM_FAILED(rv = khui_cfg_open(NULL,
499                                                   L"KhmIdentities",
500                                                   &node_ident)))
501                     goto _exit_init;
502
503                 ZeroMemory(&reg, sizeof(reg));
504                 reg.name = AFS_CONFIG_NODE_MAIN;
505                 reg.short_desc = wshort_desc;
506                 reg.long_desc = wlong_desc;
507                 reg.h_module = hResModule;
508                 reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_AFS);
509                 reg.dlg_proc = afs_cfg_main_proc;
510                 reg.flags = 0;
511                 LoadString(hResModule, IDS_CFG_MAIN_LONG,
512                            wlong_desc, ARRAYLENGTH(wlong_desc));
513                 LoadString(hResModule, IDS_CFG_MAIN_SHORT,
514                            wshort_desc, ARRAYLENGTH(wshort_desc));
515
516                 khui_cfg_register(NULL, &reg);
517
518                 ZeroMemory(&reg, sizeof(reg));
519                 reg.name = AFS_CONFIG_NODE_IDS;
520                 reg.short_desc = wshort_desc;
521                 reg.long_desc = wshort_desc;
522                 reg.h_module = hResModule;
523                 reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_IDS_TAB);
524                 reg.dlg_proc = afs_cfg_ids_proc;
525                 reg.flags = KHUI_CNFLAG_SUBPANEL;
526                 LoadString(hResModule, IDS_CFG_IDS_TAB,
527                            wshort_desc, ARRAYLENGTH(wshort_desc));
528
529                 khui_cfg_register(node_ident, &reg);
530
531                 ZeroMemory(&reg, sizeof(reg));
532                 reg.name = AFS_CONFIG_NODE_ID;
533                 reg.short_desc = wshort_desc;
534                 reg.long_desc = wshort_desc;
535                 reg.h_module = hResModule;
536                 reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_ID_TAB);
537                 reg.dlg_proc = afs_cfg_id_proc;
538                 reg.flags = KHUI_CNFLAG_SUBPANEL | KHUI_CNFLAG_PLURAL;
539                 LoadString(hResModule, IDS_CFG_ID_TAB,
540                            wshort_desc, ARRAYLENGTH(wshort_desc));
541
542                 khui_cfg_register(node_ident, &reg);
543             }
544
545             /* and register the AFS message type */
546             rv = kmq_register_type(AFS_MSG_TYPENAME, &afs_msg_type_id);
547
548             if (KHM_SUCCEEDED(rv))
549                 kmq_subscribe(afs_msg_type_id, afs_plugin_cb);
550
551             /* if the configuration is set to disable afscreds.exe,
552                then we look for the shortcut and remove it if
553                found. */
554             if (KHM_SUCCEEDED(kmm_get_plugin_config(AFS_PLUGIN_NAME,
555                                                     0,
556                                                     &csp_afscred))) {
557                 wchar_t wpath[MAX_PATH];
558
559                 khc_read_int32(csp_afscred, L"Disableafscreds",
560                                &disable_afscreds);
561
562                 if (disable_afscreds &&
563                     afs_cfg_get_afscreds_shortcut(wpath)) {
564
565                     DeleteFile(wpath);
566
567                 }
568
569                 khc_close_space(csp_afscred);
570             }
571
572             /* try to register the "AFS Help" menu item, if
573                possible */
574             {
575                 khm_handle h_sub = NULL;
576                 wchar_t short_desc[KHUI_MAXCCH_SHORT_DESC];
577                 wchar_t long_desc[KHUI_MAXCCH_LONG_DESC];
578
579 #if KH_VERSION_API < 7
580                 if (pkhui_action_lock == NULL ||
581                     pkhui_action_unlock == NULL ||
582                     pkhui_refresh_actions == NULL ||
583                     pkhui_request_UI_callback == NULL)
584
585                     goto no_custom_help;
586 #endif
587
588                 kmq_create_subscription(afs_plugin_cb, &h_sub);
589
590                 LoadString(hResModule, IDS_ACTION_AFS_HELP,
591                            short_desc, ARRAYLENGTH(short_desc));
592                 LoadString(hResModule, IDS_ACTION_AFS_HELP_TT,
593                            long_desc, ARRAYLENGTH(long_desc));
594
595                 action_id_afs_help = khui_action_create(NULL,
596                                                         short_desc,
597                                                         long_desc,
598                                                         NULL,
599                                                         KHUI_ACTIONTYPE_TRIGGER,
600                                                         h_sub);
601
602                 if (action_id_afs_help != 0) {
603                     khm_size s;
604                     khm_size i;
605                     khui_menu_def * help_menu;
606                     khm_boolean refresh = FALSE;
607
608                     khui_action_lock();
609
610                     help_menu = khui_find_menu(KHUI_MENU_HELP);
611                     if (help_menu) {
612                         s = khui_menu_get_size(help_menu);
613
614                         for (i=0; i < s; i++) {
615                             khui_action_ref * aref;
616
617                             aref = khui_menu_get_action(help_menu, i);
618
619                             if (aref && !(aref->flags & KHUI_ACTIONREF_PACTION) &&
620                                 aref->action == KHUI_ACTION_HELP_INDEX) {
621
622                                 khui_menu_insert_action(help_menu,
623                                                         i + 1,
624                                                         action_id_afs_help,
625                                                         0);
626                                 refresh = TRUE;
627                                 break;
628                             }
629                         }
630                     }
631
632                     khui_action_unlock();
633
634                     if (refresh)
635                         khui_refresh_actions();
636                 }
637
638 #if KH_VERSION_API < 7
639             no_custom_help:
640                 ;
641 #endif
642             }
643
644         _exit_init:
645             if(ct.short_desc)
646                 PFREE(ct.short_desc);
647             if(ct.long_desc)
648                 PFREE(ct.long_desc);
649         }
650         /* now that the critical stuff is done, we move on to the
651            non-critical stuff */
652         if(KHM_SUCCEEDED(rv)) {
653             initialized = TRUE;
654
655             /* obtain existing tokens */
656             afs_list_tokens();
657         }
658
659         /* define this so that if there are no TGT's, we don't
660            deadlock trying to open a new creds dialog from within the
661            new creds dialog. */
662         SetEnvironmentVariable(L"KERBEROSLOGIN_NEVER_PROMPT", L"1");
663
664         break;
665         /* end of KMSG_SYSTEM_INIT */
666
667     case KMSG_SYSTEM_EXIT:
668
669         afs_remove_icon();
670
671         /* Try to remove the AFS plug-in action from Help menu if it
672            was successfully registered.  Also, delete the action. */
673         if (action_id_afs_help != 0) {
674
675             khui_menu_def * help_menu;
676             khm_boolean menu_changed = FALSE;
677
678             khui_action_lock();
679
680             help_menu = khui_find_menu(KHUI_MENU_HELP);
681             if (help_menu) {
682                 khm_size s;
683                 khm_size i;
684
685                 s = khui_menu_get_size(help_menu);
686                 for (i=0; i < s; i++) {
687                     khui_action_ref * aref = khui_menu_get_action(help_menu, i);
688
689                     if (aref && !(aref->flags & KHUI_ACTIONREF_PACTION) &&
690                         aref->action == action_id_afs_help) {
691
692                         khui_menu_remove_action(help_menu, i);
693                         menu_changed = TRUE;
694                         break;
695                     }
696                 }
697             }
698
699             khui_action_delete(action_id_afs_help);
700
701             khui_action_unlock();
702
703             if (menu_changed)
704                 khui_refresh_actions();
705
706             action_id_afs_help = 0;
707         }
708
709         if (afs_msg_type_id != -1) {
710             kmq_unsubscribe(afs_msg_type_id, afs_plugin_cb);
711             kmq_unregister_type(afs_msg_type_id);
712         }
713         if(afs_credtype_id >= 0) {
714             kcdb_credtype_unregister(afs_credtype_id);
715         }
716         if(afs_attr_cell >= 0) {
717             kcdb_attrib_unregister(afs_attr_cell);
718         }
719         if(afs_attr_realm >= 0) {
720             kcdb_attrib_unregister(afs_attr_realm);
721         }
722         if(afs_attr_method >= 0) {
723             kcdb_attrib_unregister(afs_attr_method);
724         }
725         if(afs_attr_client_princ >= 0) {
726             kcdb_attrib_unregister(afs_attr_client_princ);
727         }
728         if(afs_attr_server_princ >= 0) {
729             kcdb_attrib_unregister(afs_attr_server_princ);
730         }
731         if(afs_type_principal >= 0) {
732             kcdb_type_unregister(afs_type_principal);
733         }
734         if(afs_type_method >= 0) {
735             kcdb_type_unregister(afs_type_method);
736         }
737         initialized = FALSE;
738         if(afs_credset)
739             kcdb_credset_delete(afs_credset);
740
741         /* afs_sub doesn't need to be deleted.  That is taken care
742            of when unregistering the afs cred type */
743         afs_sub = NULL;
744
745 #if KH_VERSION_API < 7
746         if (hm_netidmgr)
747             FreeLibrary(hm_netidmgr);
748
749         pkhui_action_lock = NULL;
750         pkhui_action_unlock = NULL;
751         pkhui_refresh_actions = NULL;
752         pkhui_request_UI_callback = NULL;
753 #endif
754
755         rv = KHM_ERROR_SUCCESS;
756         break;
757         /* end of KMSG_SYSTEM_EXIT */
758     }
759     return rv;
760 }
761
762 /* process KMSG_KCDB messages */
763 khm_int32 KHMAPI
764 afs_msg_kcdb(khm_int32 msg_subtype,
765              khm_ui_4 uparam,
766              void * vparam)
767 {
768     khm_int32 rv = KHM_ERROR_SUCCESS;
769
770     return rv;
771 }
772
773
774
775 static khm_int32 KHMAPI
776 afs_cred_destroy_proc(khm_handle cred, void * rock) {
777     khm_int32 t;
778
779     if (KHM_FAILED(kcdb_cred_get_type(cred, &t)) ||
780         t != afs_credtype_id)
781         return KHM_ERROR_SUCCESS;
782
783     afs_unlog_cred(cred);
784
785     return KHM_ERROR_SUCCESS;
786 }
787
788 /* process KMSG_CRED messages */
789 khm_int32 KHMAPI
790 afs_msg_cred(khm_int32 msg_subtype,
791              khm_ui_4 uparam,
792              void * vparam)
793 {
794     khm_int32 rv = KHM_ERROR_SUCCESS;
795
796     switch(msg_subtype) {
797     case KMSG_CRED_REFRESH:
798         afs_list_tokens();
799         break;
800
801     case KMSG_CRED_DESTROY_CREDS:
802         {
803             khui_action_context * ctx;
804
805             ctx = (khui_action_context *) vparam;
806
807             if (ctx->credset) {
808                 _begin_task(0);
809                 _report_cs0(KHERR_INFO, L"Destroying AFS Tokens");
810                 _describe();
811
812                 kcdb_credset_apply(ctx->credset,
813                                    afs_cred_destroy_proc,
814                                    NULL);
815
816                 _end_task();
817             }
818         }
819         break;
820
821     default:
822
823         if (IS_CRED_ACQ_MSG(msg_subtype))
824             return afs_msg_newcred(msg_subtype, uparam, vparam);
825     }
826
827     return rv;
828 }
829
830
831 khm_int32 KHMAPI
832 help_launcher(HWND hwnd_main, void * rock) {
833     afs_html_help(hwnd_main, NULL, HH_DISPLAY_TOC, 0);
834
835     return KHM_ERROR_SUCCESS;
836 }
837
838 khm_int32 KHMAPI
839 afs_msg_act(khm_int32 msg_subtype,
840             khm_ui_4 uparam,
841             void * vparam)
842 {
843     khm_int32 rv = KHM_ERROR_SUCCESS;
844
845     if (msg_subtype == KMSG_ACT_ACTIVATE &&
846         uparam == (khm_ui_4)action_id_afs_help) {
847
848         khui_request_UI_callback(help_launcher, NULL);
849
850     }
851
852     return rv;
853 }