summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/lib/krb5/krb/srv_dec_tkt.c188
-rw-r--r--src/windows/identity/doc/cred_aquisition.h426
-rw-r--r--src/windows/identity/doc/cred_data_types.h528
-rw-r--r--src/windows/identity/doc/cred_main.h72
-rw-r--r--src/windows/identity/doc/cred_msgs.h96
-rw-r--r--src/windows/identity/doc/cred_prop_pages.h168
-rw-r--r--src/windows/identity/doc/main_page.h332
-rw-r--r--src/windows/identity/doc/plugin_framework.h366
-rw-r--r--src/windows/identity/doc/plugin_locale.h218
-rw-r--r--src/windows/identity/doc/plugin_main.h230
-rw-r--r--src/windows/identity/doc/plugin_structure.h110
-rw-r--r--src/windows/identity/doc/ui_actions.h60
-rw-r--r--src/windows/identity/doc/ui_context.h376
-rw-r--r--src/windows/identity/doc/ui_main.h72
-rw-r--r--src/windows/identity/doc/ui_menus.h60
-rw-r--r--src/windows/identity/help/khhelp.h66
-rw-r--r--src/windows/identity/include/khdefs.h476
-rw-r--r--src/windows/identity/include/kherror.h370
-rw-r--r--src/windows/identity/include/khlist.h428
-rw-r--r--src/windows/identity/include/khmsgtypes.h1634
-rw-r--r--src/windows/identity/include/netidmgr.h86
-rw-r--r--src/windows/identity/kconfig/api.c5312
-rw-r--r--src/windows/identity/kconfig/kconfig.h1920
-rw-r--r--src/windows/identity/kconfig/kconfiginternal.h258
-rw-r--r--src/windows/identity/kconfig/kconfigmain.c74
-rw-r--r--src/windows/identity/kconfig/registry.c56
-rw-r--r--src/windows/identity/kconfig/test/utiltest.c414
-rw-r--r--src/windows/identity/kcreddb/attrib.c1756
-rw-r--r--src/windows/identity/kcreddb/attrib.h110
-rw-r--r--src/windows/identity/kcreddb/buf.c782
-rw-r--r--src/windows/identity/kcreddb/buf.h156
-rw-r--r--src/windows/identity/kcreddb/credential.c2184
-rw-r--r--src/windows/identity/kcreddb/credential.h142
-rw-r--r--src/windows/identity/kcreddb/credset.c2354
-rw-r--r--src/windows/identity/kcreddb/credset.h150
-rw-r--r--src/windows/identity/kcreddb/credtype.c816
-rw-r--r--src/windows/identity/kcreddb/credtype.h110
-rw-r--r--src/windows/identity/kcreddb/identity.c3198
-rw-r--r--src/windows/identity/kcreddb/identity.h120
-rw-r--r--src/windows/identity/kcreddb/init.c182
-rw-r--r--src/windows/identity/kcreddb/kcreddb.h6658
-rw-r--r--src/windows/identity/kcreddb/kcreddbinternal.h122
-rw-r--r--src/windows/identity/kcreddb/kcreddbmain.c80
-rw-r--r--src/windows/identity/kcreddb/langres.h96
-rw-r--r--src/windows/identity/kcreddb/resource.h54
-rw-r--r--src/windows/identity/kcreddb/type.c2772
-rw-r--r--src/windows/identity/kcreddb/type.h432
-rw-r--r--src/windows/identity/kherr/kherr.c2642
-rw-r--r--src/windows/identity/kherr/kherr.h2188
-rw-r--r--src/windows/identity/kherr/kherrinternal.h138
-rw-r--r--src/windows/identity/kherr/kherrmain.c104
-rw-r--r--src/windows/identity/kmm/kmm.c384
-rw-r--r--src/windows/identity/kmm/kmm.h2136
-rw-r--r--src/windows/identity/kmm/kmm_module.c1352
-rw-r--r--src/windows/identity/kmm/kmm_plugin.c828
-rw-r--r--src/windows/identity/kmm/kmm_reg.c672
-rw-r--r--src/windows/identity/kmm/kmm_registrar.c2076
-rw-r--r--src/windows/identity/kmm/kmminternal.h516
-rw-r--r--src/windows/identity/kmm/kmmmain.c318
-rw-r--r--src/windows/identity/kmm/kplugin.h292
-rw-r--r--src/windows/identity/kmq/consumer.c1146
-rw-r--r--src/windows/identity/kmq/init.c626
-rw-r--r--src/windows/identity/kmq/kmq.h1402
-rw-r--r--src/windows/identity/kmq/kmqinternal.h478
-rw-r--r--src/windows/identity/kmq/kmqmain.c94
-rw-r--r--src/windows/identity/kmq/msgtype.c776
-rw-r--r--src/windows/identity/kmq/publisher.c1112
-rw-r--r--src/windows/identity/nidmgrdll/dllmain.c228
-rw-r--r--src/windows/identity/plugins/common/dynimport.c954
-rw-r--r--src/windows/identity/plugins/common/dynimport.h722
-rw-r--r--src/windows/identity/plugins/common/krb5common.c902
-rw-r--r--src/windows/identity/plugins/common/krb5common.h112
-rw-r--r--src/windows/identity/plugins/krb4/errorfuncs.c452
-rw-r--r--src/windows/identity/plugins/krb4/errorfuncs.h130
-rw-r--r--src/windows/identity/plugins/krb4/krb4configdlg.c1078
-rw-r--r--src/windows/identity/plugins/krb4/krb4funcs.c1794
-rw-r--r--src/windows/identity/plugins/krb4/krb4funcs.h264
-rw-r--r--src/windows/identity/plugins/krb4/krb4main.c314
-rw-r--r--src/windows/identity/plugins/krb4/krb4newcreds.c1746
-rw-r--r--src/windows/identity/plugins/krb4/krb4plugin.c594
-rw-r--r--src/windows/identity/plugins/krb4/krbcred.h272
-rw-r--r--src/windows/identity/plugins/krb4/langres.h98
-rw-r--r--src/windows/identity/plugins/krb5/datarep.c814
-rw-r--r--src/windows/identity/plugins/krb5/datarep.h152
-rw-r--r--src/windows/identity/plugins/krb5/errorfuncs.c594
-rw-r--r--src/windows/identity/plugins/krb5/errorfuncs.h150
-rw-r--r--src/windows/identity/plugins/krb5/krb5configcc.c1142
-rw-r--r--src/windows/identity/plugins/krb5/krb5configid.c710
-rw-r--r--src/windows/identity/plugins/krb5/krb5configids.c540
-rw-r--r--src/windows/identity/plugins/krb5/krb5funcs.c6974
-rw-r--r--src/windows/identity/plugins/krb5/krb5funcs.h434
-rw-r--r--src/windows/identity/plugins/krb5/krb5identpro.c3762
-rw-r--r--src/windows/identity/plugins/krb5/krb5main.c994
-rw-r--r--src/windows/identity/plugins/krb5/krb5newcreds.c5494
-rw-r--r--src/windows/identity/plugins/krb5/krb5plugin.c530
-rw-r--r--src/windows/identity/plugins/krb5/krb5props.c352
-rw-r--r--src/windows/identity/plugins/krb5/krbcred.h488
-rw-r--r--src/windows/identity/plugins/krb5/langres.h432
-rw-r--r--src/windows/identity/sample/templates/credprov/config_id.c236
-rw-r--r--src/windows/identity/sample/templates/credprov/config_ids.c192
-rw-r--r--src/windows/identity/sample/templates/credprov/config_main.c198
-rw-r--r--src/windows/identity/sample/templates/credprov/credacq.c810
-rw-r--r--src/windows/identity/sample/templates/credprov/credprov.h352
-rw-r--r--src/windows/identity/sample/templates/credprov/credtype.c104
-rw-r--r--src/windows/identity/sample/templates/credprov/langres.h68
-rw-r--r--src/windows/identity/sample/templates/credprov/main.c342
-rw-r--r--src/windows/identity/sample/templates/credprov/plugin.c764
-rw-r--r--src/windows/identity/sample/templates/credprov/proppage.c118
-rw-r--r--src/windows/identity/ui/aboutwnd.c308
-rw-r--r--src/windows/identity/ui/aboutwnd.h66
-rw-r--r--src/windows/identity/ui/addrchange.c188
-rw-r--r--src/windows/identity/ui/addrchange.h72
-rw-r--r--src/windows/identity/ui/appglobal.h286
-rw-r--r--src/windows/identity/ui/cfg_appear_wnd.c870
-rw-r--r--src/windows/identity/ui/cfg_general_wnd.c838
-rw-r--r--src/windows/identity/ui/cfg_identities_wnd.c3046
-rw-r--r--src/windows/identity/ui/cfg_notif_wnd.c682
-rw-r--r--src/windows/identity/ui/cfg_plugins_wnd.c1292
-rw-r--r--src/windows/identity/ui/configwnd.c2438
-rw-r--r--src/windows/identity/ui/configwnd.h176
-rw-r--r--src/windows/identity/ui/credfuncs.c2796
-rw-r--r--src/windows/identity/ui/credfuncs.h186
-rw-r--r--src/windows/identity/ui/credwnd.c10994
-rw-r--r--src/windows/identity/ui/credwnd.h600
-rw-r--r--src/windows/identity/ui/debugfuncs.c512
-rw-r--r--src/windows/identity/ui/debugfuncs.h74
-rw-r--r--src/windows/identity/ui/htwnd.c2572
-rw-r--r--src/windows/identity/ui/htwnd.h114
-rw-r--r--src/windows/identity/ui/khmapp.h140
-rw-r--r--src/windows/identity/ui/main.c1794
-rw-r--r--src/windows/identity/ui/mainmenu.c2278
-rw-r--r--src/windows/identity/ui/mainmenu.h136
-rw-r--r--src/windows/identity/ui/mainwnd.h164
-rw-r--r--src/windows/identity/ui/notifier.c6320
-rw-r--r--src/windows/identity/ui/notifier.h126
-rw-r--r--src/windows/identity/ui/passwnd.c266
-rw-r--r--src/windows/identity/ui/passwnd.h78
-rw-r--r--src/windows/identity/ui/propertywnd.c496
-rw-r--r--src/windows/identity/ui/propertywnd.h72
-rw-r--r--src/windows/identity/ui/reqdaemon.c906
-rw-r--r--src/windows/identity/ui/reqdaemon.h84
-rw-r--r--src/windows/identity/ui/resource.h830
-rw-r--r--src/windows/identity/ui/statusbar.c416
-rw-r--r--src/windows/identity/ui/statusbar.h110
-rw-r--r--src/windows/identity/ui/timer.c2030
-rw-r--r--src/windows/identity/ui/timer.h200
-rw-r--r--src/windows/identity/ui/toolbar.c942
-rw-r--r--src/windows/identity/ui/toolbar.h104
-rw-r--r--src/windows/identity/uilib/action.c3312
-rw-r--r--src/windows/identity/uilib/alert.c874
-rw-r--r--src/windows/identity/uilib/configui.c2170
-rw-r--r--src/windows/identity/uilib/configui.h148
-rw-r--r--src/windows/identity/uilib/creddlg.c1436
-rw-r--r--src/windows/identity/uilib/intaction.h216
-rw-r--r--src/windows/identity/uilib/khaction.h2010
-rw-r--r--src/windows/identity/uilib/khactiondef.h336
-rw-r--r--src/windows/identity/uilib/khalerts.h806
-rw-r--r--src/windows/identity/uilib/khconfigui.h1254
-rw-r--r--src/windows/identity/uilib/khhtlink.h154
-rw-r--r--src/windows/identity/uilib/khnewcred.h1970
-rw-r--r--src/windows/identity/uilib/khprops.h418
-rw-r--r--src/windows/identity/uilib/khremote.h168
-rw-r--r--src/windows/identity/uilib/khrescache.h200
-rw-r--r--src/windows/identity/uilib/khtracker.h228
-rw-r--r--src/windows/identity/uilib/khuidefs.h292
-rw-r--r--src/windows/identity/uilib/propsheet.c460
-rw-r--r--src/windows/identity/uilib/propwnd.c74
-rw-r--r--src/windows/identity/uilib/rescache.c606
-rw-r--r--src/windows/identity/uilib/trackerwnd.c948
-rw-r--r--src/windows/identity/uilib/uibind.c118
-rw-r--r--src/windows/identity/uilib/uilibmain.c88
-rw-r--r--src/windows/identity/uilib/version.c166
-rw-r--r--src/windows/identity/util/hashtable.c342
-rw-r--r--src/windows/identity/util/hashtable.h462
-rw-r--r--src/windows/identity/util/mstring.c1020
-rw-r--r--src/windows/identity/util/mstring.h722
-rw-r--r--src/windows/identity/util/perfstat.c822
-rw-r--r--src/windows/identity/util/perfstat.h148
-rw-r--r--src/windows/identity/util/sync.c260
-rw-r--r--src/windows/identity/util/sync.h256
-rw-r--r--src/windows/identity/util/utils.h74
-rw-r--r--src/windows/kfwlogon/kfwcommon.c2704
-rw-r--r--src/windows/kfwlogon/kfwcpcc.c78
-rw-r--r--src/windows/kfwlogon/kfwlogon.c1268
-rw-r--r--src/windows/kfwlogon/kfwlogon.h430
-rw-r--r--src/windows/winlevel.h66
186 files changed, 82531 insertions, 82531 deletions
diff --git a/src/lib/krb5/krb/srv_dec_tkt.c b/src/lib/krb5/krb/srv_dec_tkt.c
index 7dad1ed163..e994ac9950 100644
--- a/src/lib/krb5/krb/srv_dec_tkt.c
+++ b/src/lib/krb5/krb/srv_dec_tkt.c
@@ -1,94 +1,94 @@
-/*
- * lib/krb5/krb/srv_dec_tkt.c
- *
- * Copyright 2006 by the Massachusetts Institute of Technology.
- * All Rights Reserved.
- *
- * Export of this software from the United States of America may
- * require a specific license from the United States Government.
- * It is the responsibility of any person or organization contemplating
- * export to obtain such a license before exporting.
- *
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
- * distribute this software and its documentation for any purpose and
- * without fee is hereby granted, provided that the above copyright
- * notice appear in all copies and that both that copyright notice and
- * this permission notice appear in supporting documentation, and that
- * the name of M.I.T. not be used in advertising or publicity pertaining
- * to distribution of the software without specific, written prior
- * permission. Furthermore if you modify this software you must label
- * your software as modified software and not distribute it in such a
- * fashion that it might be confused with the original M.I.T. software.
- * M.I.T. makes no representations about the suitability of
- * this software for any purpose. It is provided "as is" without express
- * or implied warranty.
- *
- *
- * Server decrypt ticket via keytab or keyblock.
- *
- * Different from krb5_rd_req_decoded. (krb5/src/lib/krb5/krb/rd_req_dec.c)
- * - No krb5_principal_compare or KRB5KRB_AP_ERR_BADMATCH error.
- * - No replay cache processing.
- * - No skew checking or KRB5KRB_AP_ERR_SKEW error.
- * - No address checking or KRB5KRB_AP_ERR_BADADDR error.
- * - No time validation.
- * - No permitted enctype validation or KRB5_NOPERM_ETYPE error.
- * - Does not free ticket->enc_part2 on error.
- */
-
-#include <k5-int.h>
-
-krb5_error_code KRB5_CALLCONV
-krb5int_server_decrypt_ticket_keyblock(krb5_context context,
- const krb5_keyblock *key,
- krb5_ticket *ticket)
-{
- krb5_error_code retval;
- krb5_data *realm;
- krb5_transited *trans;
-
- retval = krb5_decrypt_tkt_part(context, key, ticket);
- if (retval)
- goto done;
-
- trans = &ticket->enc_part2->transited;
- realm = &ticket->enc_part2->client->realm;
- if (trans->tr_contents.data && *trans->tr_contents.data) {
- retval = krb5_check_transited_list(context, &trans->tr_contents,
- realm, &ticket->server->realm);
- goto done;
- }
-
- if (ticket->enc_part2->flags & TKT_FLG_INVALID) { /* ie, KDC_OPT_POSTDATED */
- retval = KRB5KRB_AP_ERR_TKT_INVALID;
- goto done;
- }
-
- done:
- return retval;
-}
-
-
-krb5_error_code KRB5_CALLCONV
-krb5_server_decrypt_ticket_keytab(krb5_context context,
- const krb5_keytab kt,
- krb5_ticket *ticket)
-{
- krb5_error_code retval;
- krb5_enctype enctype;
- krb5_keytab_entry ktent;
-
- enctype = ticket->enc_part.enctype;
-
- if ((retval = krb5_kt_get_entry(context, kt, ticket->server,
- ticket->enc_part.kvno,
- enctype, &ktent)))
- return retval;
-
- retval = krb5int_server_decrypt_ticket_keyblock(context,
- &ktent.key, ticket);
- /* Upon error, Free keytab entry first, then return */
-
- (void) krb5_kt_free_entry(context, &ktent);
- return retval;
-}
+/*
+ * lib/krb5/krb/srv_dec_tkt.c
+ *
+ * Copyright 2006 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ *
+ * Server decrypt ticket via keytab or keyblock.
+ *
+ * Different from krb5_rd_req_decoded. (krb5/src/lib/krb5/krb/rd_req_dec.c)
+ * - No krb5_principal_compare or KRB5KRB_AP_ERR_BADMATCH error.
+ * - No replay cache processing.
+ * - No skew checking or KRB5KRB_AP_ERR_SKEW error.
+ * - No address checking or KRB5KRB_AP_ERR_BADADDR error.
+ * - No time validation.
+ * - No permitted enctype validation or KRB5_NOPERM_ETYPE error.
+ * - Does not free ticket->enc_part2 on error.
+ */
+
+#include <k5-int.h>
+
+krb5_error_code KRB5_CALLCONV
+krb5int_server_decrypt_ticket_keyblock(krb5_context context,
+ const krb5_keyblock *key,
+ krb5_ticket *ticket)
+{
+ krb5_error_code retval;
+ krb5_data *realm;
+ krb5_transited *trans;
+
+ retval = krb5_decrypt_tkt_part(context, key, ticket);
+ if (retval)
+ goto done;
+
+ trans = &ticket->enc_part2->transited;
+ realm = &ticket->enc_part2->client->realm;
+ if (trans->tr_contents.data && *trans->tr_contents.data) {
+ retval = krb5_check_transited_list(context, &trans->tr_contents,
+ realm, &ticket->server->realm);
+ goto done;
+ }
+
+ if (ticket->enc_part2->flags & TKT_FLG_INVALID) { /* ie, KDC_OPT_POSTDATED */
+ retval = KRB5KRB_AP_ERR_TKT_INVALID;
+ goto done;
+ }
+
+ done:
+ return retval;
+}
+
+
+krb5_error_code KRB5_CALLCONV
+krb5_server_decrypt_ticket_keytab(krb5_context context,
+ const krb5_keytab kt,
+ krb5_ticket *ticket)
+{
+ krb5_error_code retval;
+ krb5_enctype enctype;
+ krb5_keytab_entry ktent;
+
+ enctype = ticket->enc_part.enctype;
+
+ if ((retval = krb5_kt_get_entry(context, kt, ticket->server,
+ ticket->enc_part.kvno,
+ enctype, &ktent)))
+ return retval;
+
+ retval = krb5int_server_decrypt_ticket_keyblock(context,
+ &ktent.key, ticket);
+ /* Upon error, Free keytab entry first, then return */
+
+ (void) krb5_kt_free_entry(context, &ktent);
+ return retval;
+}
diff --git a/src/windows/identity/doc/cred_aquisition.h b/src/windows/identity/doc/cred_aquisition.h
index 30f626f8e8..bce826dc8b 100644
--- a/src/windows/identity/doc/cred_aquisition.h
+++ b/src/windows/identity/doc/cred_aquisition.h
@@ -1,213 +1,213 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- * Copyright (c) 2007 Secure Endpoints Inc.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-/*! \page cred_acq Managed credential acquisition
-
- Credential providers and identity providers must participate in
- managed credential acquisition in order to respond to the user's
- requests to obtain new credentials for an identity or to renew
- credentials for an existing identity.
-
- There are two major processes that result in managed credential
- acuqisition. One is the acquisition of credentials, while the
- other is credential renewal. During a renewal, existing
- credentials are used to obtain new credentials which expire later
- than the existing credential. Typically, the identity provider
- performs the task of obtaining renewed initial credentials while
- the other credential providers obtain new credentials based on
- these initial credentials.
-
- \section cred_acq_new New Credentials
-
- When a user initiates the process of initial credential
- acquisition, Network Identity Manager broadcasts a
- <::KMSG_CRED,::KMSG_CRED_NEW_CREDS> message. Credential providers
- which need to participate in the credential acquisition should
- respond to this message as detailed in \ref cred_acq_handle.
-
- \section cred_acq_renew Renew Credentials
-
- Network Identity Manager broadcasts a
- <::KMSG_CRED,::KMSG_CRED_RENEW_CREDS> message to initiate the
- process of renewing credentials. This may be triggered
- automatically or by a user action. Credential providers which
- need to participate in the renewal should respond to this message
- as detailed in \ref cred_acq_handle.
-
- The following pages provide detailed information:
-
- - \subpage cred_acq_new_resp
- - \subpage cred_acq_dlgproc
- */
-
-/*! \page cred_acq_new_resp Handling new credentials acquisition
-
- The process of acquiring credentials happens as follows:
-
- - Network Identity Manager creates a ::khui_new_creds object and a
- credentials acquisition window.
-
- - <::KMSG_CRED,::KMSG_CRED_RENEW_CREDS> or
- <::KMSG_CRED,::KMSG_CRED_NEW_CREDS> is sent to all the
- credentials providers.
-
- - The credential providers create the panels (where appropriate)
- for customizing their respective credential types. The type,
- panel and any dependency information is populated into a
- ::khui_new_creds_by_type structure and added to the
- ::khui_new_creds structure. (See khui_cw_add_type()).
-
- - <::KMSG_CRED, ::KMSG_CRED_DIALOG_PRESTART> is sent to all the
- credentials providers. Credentials providers should use this
- message to finialize initialization in preparation of showing
- the credentials acquisition window, such as by initializing the
- controls of the individual panels.
-
- - <::KMSG_CRED, ::KMSG_CRED_DIALOG_START> is sent to all the
- credentials providers.
-
- - The dialog for obtaining credentials is displayed.
- Notifications between the main dialog and the individual panels
- are done through ::KHUI_WM_NC_NOTIFY messages to the dialog
- procedures.
-
- - Once the dialog processing is done, a ::WMNC_DIALOG_PREPROCESS
- message is sent to the dialog procedure.
-
- - Network Identity Manager posts
- <::KMSG_CRED,::KMSG_CRED_DIALOG_PROCESS> message to all the
- credentials providers. Each provider should check if the user
- cancelled the dialog or indicated that the new credentials
- should be obtained and act accordingly. The \a result field of
- the ::khui_new_creds structure will be set to either
- ::KHUI_NC_RESULT_PROCESS or ::KHUI_NC_RESULT_CANCEL to indicate
- whether the user wishes to acquire credentials or cancel the
- operation.
-
- - A <::KMSG_CRED, ::KMSG_CRED_END> message signals the end of the
- credentials acquisition process. Each credentials provider is
- responsible for removing the ::khui_new_creds_by_type structre
- from the ::khui_new_creds structure and freeing up any resources
- it allocated earlier in preparation for obtaining new
- credentials.
-
- \section cred_acq_handle Responding to credential acquisition messages
-
- The credential acquisition messages are
- <::KMSG_CRED,::KMSG_CRED_NEW_CREDS> and <::KMSG_CRED,
- ::KMSG_CRED_RENEW_CREDS>. They are structured as follows:
-
- - \b type : ::KMSG_CRED
- - \b subtype: ::KMSG_CRED_NEW_CREDS or ::KMSG_CRED_RENEW_CREDS
- - \b uparam : 0 (unused)
- - \b vparam : a pointer to a ::khui_new_creds structure.
-
- The \a vparam parameter of the message, as shown above, is a
- pointer to a ::khui_new_creds structure. You can use the \a
- subtype field of this structure to determine whether this is a new
- credentials acquisition or a renewal.
-
- In response to this message, a credentials provider is expected to
- provide a configuration panel which the user can use to customize
- how the credentials of this type are to be obtained. The panel is
- described by the ::khui_new_creds_by_type structure.
-
- \subsection cred_acq_panel_spec Specifying the credentials type panel
-
- The credentials type panel is used by the user to customize how
- credentials of the specified type are to be obtained. The
- ::khui_new_creds_by_type structure that describes the panel can be
- used to specify a number of parameters that guide how the panel is
- to be displayed in the new credentials acquisition dialog.
-
- The \a name field defines a localized string that will be
- displayed in the tab control that houses the panel. If it is \a
- NULL, then the name of the credentials type is used. Optionally,
- an icon can be specified in the \a icon field which will appear
- alongside the name. A tooltip may be provided in the \a tooltip
- field which will be displayed when the user hovers the mouse over
- the tab.
-
- In order to assert that the tab appears at a specific position in
- the list of tabs, you can specify a positive number in the \a
- ordinal field. Zero does not count as a valid ordinal. The
- panels with positive ordinals are arranged first in increasing
- order of ordinal (conflicts are resolved by sorting along the \a
- name). Then the panels without a positive ordianl are arranged
- behind these in increasing order of \a name.
-
- Currently, the credentials provider must specify a dialog template
- that will be used to create the embedded dialog for configuring
- new credentials for the type. This is done by setting the
- khui_new_creds_by_type::h_module, khui_new_creds_by_type::dlg_proc
- and khui_new_creds_by_type::dlg_template fields.
-
- Following is example code which suggests how this could be done:
-
- \code
- // Message handling code for KMSG_CRED_NEW_CREDS or
- // KMSG_CRED_INIT_CREDS
- ...
- khui_new_creds * c;
- khui_new_creds_by_type * t;
-
- c = (khui_new_creds *) vparam;
- t = PMALLOC(sizeof(*t));
- ZeroMemory(t, sizeof(*t));
-
- t->type = my_cred_type;
-
- // set look and feel params
- t->ordinal = 3; // third in line
- t->name = L"My panel name";
- t->icon = LoadIcon(my_hInstance, MAKEINTRESOURCE(IDI_PANEL_ICON));
- t->tooltip = L"Configure credentials of my type";
-
- // specify the dialog template to use
- t->h_module = my_hInstance;
- t->dlg_proc = my_dialog_procedure;
- t->dlg_template = MAKEINTRESOURCE(IDD_NEW_CREDS);
-
- if(KHM_FAILED(khui_cw_add_type(c,t))) {
- // handle error
- }
- \endcode
-
- It is important to note that the ::khui_new_creds_by_type pointer
- that is passed into khui_cw_add_type() points to an allocated
- block of memory which should remain in memory until
- <::KMSG_CRED,::KMSG_CRED_END> message is received.
-
- For information on how the dialog procedure should be written, see
- \ref cred_acq_dlgproc .
-
-*/
-
-/*! \page cred_acq_dlgproc Writing the dialog procedure for a cred type panel
-
-
-*/
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ * Copyright (c) 2007 Secure Endpoints Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+/*! \page cred_acq Managed credential acquisition
+
+ Credential providers and identity providers must participate in
+ managed credential acquisition in order to respond to the user's
+ requests to obtain new credentials for an identity or to renew
+ credentials for an existing identity.
+
+ There are two major processes that result in managed credential
+ acuqisition. One is the acquisition of credentials, while the
+ other is credential renewal. During a renewal, existing
+ credentials are used to obtain new credentials which expire later
+ than the existing credential. Typically, the identity provider
+ performs the task of obtaining renewed initial credentials while
+ the other credential providers obtain new credentials based on
+ these initial credentials.
+
+ \section cred_acq_new New Credentials
+
+ When a user initiates the process of initial credential
+ acquisition, Network Identity Manager broadcasts a
+ <::KMSG_CRED,::KMSG_CRED_NEW_CREDS> message. Credential providers
+ which need to participate in the credential acquisition should
+ respond to this message as detailed in \ref cred_acq_handle.
+
+ \section cred_acq_renew Renew Credentials
+
+ Network Identity Manager broadcasts a
+ <::KMSG_CRED,::KMSG_CRED_RENEW_CREDS> message to initiate the
+ process of renewing credentials. This may be triggered
+ automatically or by a user action. Credential providers which
+ need to participate in the renewal should respond to this message
+ as detailed in \ref cred_acq_handle.
+
+ The following pages provide detailed information:
+
+ - \subpage cred_acq_new_resp
+ - \subpage cred_acq_dlgproc
+ */
+
+/*! \page cred_acq_new_resp Handling new credentials acquisition
+
+ The process of acquiring credentials happens as follows:
+
+ - Network Identity Manager creates a ::khui_new_creds object and a
+ credentials acquisition window.
+
+ - <::KMSG_CRED,::KMSG_CRED_RENEW_CREDS> or
+ <::KMSG_CRED,::KMSG_CRED_NEW_CREDS> is sent to all the
+ credentials providers.
+
+ - The credential providers create the panels (where appropriate)
+ for customizing their respective credential types. The type,
+ panel and any dependency information is populated into a
+ ::khui_new_creds_by_type structure and added to the
+ ::khui_new_creds structure. (See khui_cw_add_type()).
+
+ - <::KMSG_CRED, ::KMSG_CRED_DIALOG_PRESTART> is sent to all the
+ credentials providers. Credentials providers should use this
+ message to finialize initialization in preparation of showing
+ the credentials acquisition window, such as by initializing the
+ controls of the individual panels.
+
+ - <::KMSG_CRED, ::KMSG_CRED_DIALOG_START> is sent to all the
+ credentials providers.
+
+ - The dialog for obtaining credentials is displayed.
+ Notifications between the main dialog and the individual panels
+ are done through ::KHUI_WM_NC_NOTIFY messages to the dialog
+ procedures.
+
+ - Once the dialog processing is done, a ::WMNC_DIALOG_PREPROCESS
+ message is sent to the dialog procedure.
+
+ - Network Identity Manager posts
+ <::KMSG_CRED,::KMSG_CRED_DIALOG_PROCESS> message to all the
+ credentials providers. Each provider should check if the user
+ cancelled the dialog or indicated that the new credentials
+ should be obtained and act accordingly. The \a result field of
+ the ::khui_new_creds structure will be set to either
+ ::KHUI_NC_RESULT_PROCESS or ::KHUI_NC_RESULT_CANCEL to indicate
+ whether the user wishes to acquire credentials or cancel the
+ operation.
+
+ - A <::KMSG_CRED, ::KMSG_CRED_END> message signals the end of the
+ credentials acquisition process. Each credentials provider is
+ responsible for removing the ::khui_new_creds_by_type structre
+ from the ::khui_new_creds structure and freeing up any resources
+ it allocated earlier in preparation for obtaining new
+ credentials.
+
+ \section cred_acq_handle Responding to credential acquisition messages
+
+ The credential acquisition messages are
+ <::KMSG_CRED,::KMSG_CRED_NEW_CREDS> and <::KMSG_CRED,
+ ::KMSG_CRED_RENEW_CREDS>. They are structured as follows:
+
+ - \b type : ::KMSG_CRED
+ - \b subtype: ::KMSG_CRED_NEW_CREDS or ::KMSG_CRED_RENEW_CREDS
+ - \b uparam : 0 (unused)
+ - \b vparam : a pointer to a ::khui_new_creds structure.
+
+ The \a vparam parameter of the message, as shown above, is a
+ pointer to a ::khui_new_creds structure. You can use the \a
+ subtype field of this structure to determine whether this is a new
+ credentials acquisition or a renewal.
+
+ In response to this message, a credentials provider is expected to
+ provide a configuration panel which the user can use to customize
+ how the credentials of this type are to be obtained. The panel is
+ described by the ::khui_new_creds_by_type structure.
+
+ \subsection cred_acq_panel_spec Specifying the credentials type panel
+
+ The credentials type panel is used by the user to customize how
+ credentials of the specified type are to be obtained. The
+ ::khui_new_creds_by_type structure that describes the panel can be
+ used to specify a number of parameters that guide how the panel is
+ to be displayed in the new credentials acquisition dialog.
+
+ The \a name field defines a localized string that will be
+ displayed in the tab control that houses the panel. If it is \a
+ NULL, then the name of the credentials type is used. Optionally,
+ an icon can be specified in the \a icon field which will appear
+ alongside the name. A tooltip may be provided in the \a tooltip
+ field which will be displayed when the user hovers the mouse over
+ the tab.
+
+ In order to assert that the tab appears at a specific position in
+ the list of tabs, you can specify a positive number in the \a
+ ordinal field. Zero does not count as a valid ordinal. The
+ panels with positive ordinals are arranged first in increasing
+ order of ordinal (conflicts are resolved by sorting along the \a
+ name). Then the panels without a positive ordianl are arranged
+ behind these in increasing order of \a name.
+
+ Currently, the credentials provider must specify a dialog template
+ that will be used to create the embedded dialog for configuring
+ new credentials for the type. This is done by setting the
+ khui_new_creds_by_type::h_module, khui_new_creds_by_type::dlg_proc
+ and khui_new_creds_by_type::dlg_template fields.
+
+ Following is example code which suggests how this could be done:
+
+ \code
+ // Message handling code for KMSG_CRED_NEW_CREDS or
+ // KMSG_CRED_INIT_CREDS
+ ...
+ khui_new_creds * c;
+ khui_new_creds_by_type * t;
+
+ c = (khui_new_creds *) vparam;
+ t = PMALLOC(sizeof(*t));
+ ZeroMemory(t, sizeof(*t));
+
+ t->type = my_cred_type;
+
+ // set look and feel params
+ t->ordinal = 3; // third in line
+ t->name = L"My panel name";
+ t->icon = LoadIcon(my_hInstance, MAKEINTRESOURCE(IDI_PANEL_ICON));
+ t->tooltip = L"Configure credentials of my type";
+
+ // specify the dialog template to use
+ t->h_module = my_hInstance;
+ t->dlg_proc = my_dialog_procedure;
+ t->dlg_template = MAKEINTRESOURCE(IDD_NEW_CREDS);
+
+ if(KHM_FAILED(khui_cw_add_type(c,t))) {
+ // handle error
+ }
+ \endcode
+
+ It is important to note that the ::khui_new_creds_by_type pointer
+ that is passed into khui_cw_add_type() points to an allocated
+ block of memory which should remain in memory until
+ <::KMSG_CRED,::KMSG_CRED_END> message is received.
+
+ For information on how the dialog procedure should be written, see
+ \ref cred_acq_dlgproc .
+
+*/
+
+/*! \page cred_acq_dlgproc Writing the dialog procedure for a cred type panel
+
+
+*/
diff --git a/src/windows/identity/doc/cred_data_types.h b/src/windows/identity/doc/cred_data_types.h
index dcd1152191..f2a4122112 100644
--- a/src/windows/identity/doc/cred_data_types.h
+++ b/src/windows/identity/doc/cred_data_types.h
@@ -1,264 +1,264 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- * Copyright (c) 2007 Secure Endpoints Inc.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-/*! \page cred_data_types Data types in Network Identity Manager
-
- Network Identity Manager's Credentials Database supports several
- useful data types. In addition, plug-ins can define custom data
- types. Only a few operations are expected of these data types
- since the core KCDB delegates fine grained operations to other
- entities that understand the underlying format.
-
- A field in a credential can have any one of these data types, but
- it must have some data type. Each value can be at most \a
- KCDB_TYPE_MAXCB bytes in length regardless of the data type.
-
- Some data types have a fixed size (such as \a Int32), while others
- are variable size. The required memory for each field in a
- credential is allocated as needed.
-
- \section kcdb_pg_dt Data types
-
- Descriptions of individual data types are below.
-
- \subsection kcdb_pg_idt Individual data types
-
- \subsubsection kcdb_pg_idt_v Void
-
- Type identifier : ::KCDB_TYPE_VOID
-
- The Void data type is used to indicate that the associated object
- does not contain any data.
-
- \subsubsection kcdb_pg_idt_s String
-
- Type identifier : ::KCDB_TYPE_STRING
-
- A unicode string that is terminated with a unicode NULL (L'\\0').
- By default, the type has the following flags:
-
- \a KCDB_TYPE_FLAG_CB_AUTO
-
- This is because, as long as the string is terminated with a unicode NULL,
- the length of the string, and therefore it's size in bytes, can be inferred
- from the data itself.
-
- \subsubsection kcdb_pg_idt_d Date
-
- Type identifier : ::KCDB_TYPE_DATE
-
- Dates and times in Network Identity Manager are stored in \a
- FILETIME structures. Utility functions are provided for
- converting from other formats such as \a time_t.
-
- \subsubsection kcdb_pg_idt_i Interval
-
- Type identifier : ::KCDB_TYPE_INTERVAL
-
- Stores an interval of time. Stored as a 64-bit signed integer. The
- string representation of this data type is different from the \a
- Date data type and designates an interval of time.
-
- The special value _I64_MAX (which is defined in limits.h as
- 0x7fffffffffffffff, or in other words, the largest positive value
- that can be stored in a 64-bit signed integer) is used to
- represent an interval of unknown length.
-
- The string representations of a data value of Interval type are
- defined as follows for English (US):
-
- - "(Unknown)" if the value is _I64_MAX
-
- - "(Expired)" if the value is less than zero
-
- - "%d days %d hours" if the value is greater than 24 hours
-
- - "%d hours %d mins" if the value is greater than 1 hour
-
- - "%d mins %d secs" if the value is greater than 1 minute
-
- - "%d seconds" otherwise
-
- \subsubsection kcdb_pg_idt_i32 Int32
-
- Type identifier : ::KCDB_TYPE_INT32
-
- A signed 32-bit integer.
-
- \subsubsection kcdb_pg_idt_i64 Int64
-
- Type identifier : ::KCDB_TYPE_INT64
-
- A signed 64-bit integer.
-
- \subsubsection kcdb_pg_idt_da Data
-
- Type identifier : ::KCDB_TYPE_DATA
-
- Raw data. Can contain a byte stream. This data type can be used
- by plug-ins to associate raw data with a credential. However,
- there is no built-in string representation for this data type. As
- such, this is not meant to be used for storing anything that has
- to be displayed to the user verbatim.
-
- \section kcdb_pg_cust Custom data types
-
- \subsection kcdb_pg_cb Custom data type call backs
-
- Custom data types in the Network Identity Manager Credentials
- Database are defined using \a kcdb_type structures that must
- include several callback functions. The expected behavior of
- these callback functions is documented below.
-
- \subsubsection kcdb_pg_cb_ts toString
-
- \code
- khm_int32 toString(
- const void * data,
- khm_int32 cb_data,
- wchar_t *buffer,
- khm_int32 *pcb_buffer,
- khm_int32 flags);
- \endcode
-
- Produce the localized string representation of the object pointed to by
- \a data. The size of the data block is specified by the \a cb_data
- parameter. If the data type specified the \a KCDB_TYPE_FLAG_CB_AUTO flag
- then \a cb_data can be \a KCDB_CBSIZE_AUTO, in which case the size of the
- data block is to be inferred.
-
- \a toString should assume that the block of data pointed to by \a data is
- valid for this data type.
-
- The \a pcb_buffer parameter is always a valid pointer to an \a khm_int32
- variable.
-
- The \a buffer parameter is a pointer to a \a wchar_t buffer which is to
- receive the unicode string representing the object. \a buffer may be
- \a NULL, in which case the required size of the buffer should be returned
- in \a pcb_buffer. In this case, the function should return
- \a KHM_ERROR_TOO_LONG.
-
- If the \a buffer parameter is not \a NULL and the \a pcb_buffer specifies
- that the buffer is large enough to hold the string representation, the
- function should copy the string representation to the buffer, set the
- \a pcb_buffer to the number of bytes that were copied including the
- terminating \a NULL, and return \a KHM_ERROR_SUCCESS.
-
- If the \a buffer parameter is not \a NULL and the \a pcb_buffer specifies
- a buffer that is not large enough, the function should set \a pcb_buffer
- to the required size (including the terminating \a NULL) and then return
- \a KHM_ERROR_TOO_LONG.
-
- \subsubsection kcdb_pg_cb_cmp comp
-
- \code
- khm_int32 comp(
- const void * data1,
- khm_int32 cb_data1,
- const void * data2,
- khm_int32 cb_d2);
- \endcode
-
- Compares two objects and returns a value indicating the relative ordering.
-
- Since the KCDB does not interpret any data type, it relies on a loose
- definition of what a relative ordering is. It is left up to each data
- type callback to interpret what 'ascending' and 'descending' mean.
-
- The return value \a r should be as follows:
-
- \a r < 0 : if \a data1 < \a data2
-
- \a r > 0 : if \a data1 > \a data2
-
- \a r = 0 : if \a data1 = \a data2 or no relative ordering can be determined
- for the two objects \a data1 and \a data2.
-
- The function should assume that both objects are valid for this data type.
-
- The size specifiers \a cb_data1 and \a cb_data2 can (either or both) be
- \a KCDB_CBSIZE_AUTO if the data type specified \a KCDB_TYPE_FLAG_CB_AUTO
- flag.
-
- \subsubsection kcdb_pg_cb_dup dup
-
- \code
- khm_int32 dup(
- const void * d_src,
- khm_int32 cb_src,
- void * d_dst,
- khm_int32 * pcb_dst);
- \endcode
-
- Duplicate an object. The object pointed to by \a d_src is to be copied to
- the buffer pointed to by \a d_dst. The function is to assume that \a d_src
- object is valid. The size specifier \a cb_src may be \a KCDB_CBSIZE_AUTO
- if \a KCDB_TYPE_FLAG_CB_AUTO was specified for the data type.
-
- If \a d_dst pointer is \a NULL, then the required buffer size should be
- returned in \a pcb_dst. In this case, the function itself should return
- \a KHM_ERROR_TOO_LONG. The same behavior should occur if \a d_dst is non
- \a NULL and \a pcb_dst indicates that the buffer is not sufficient.
-
- If \a d_dst is not \a NULL and \a pcb_dst indicates that the buffer is
- sufficient, then a copy of the object in \a d_src should be placed in
- \a d_dst. The function shold return \a KHM_ERROR_SUCCESS and set
- \a pcb_dst to the number of bytes that were copied.
-
- This callback will only be called when the credentials database is
- retrieving objects from the outside. Once it receives an object it may be
- copied or moved as required. Hence the object should not assume to reside
- in a specific location of memory. Also, \a dup is not intended to perform
- such functions as reference counting which require knowledge of a precise
- number of instances of an object, as the credentials database may copy
- the object simply by copying the block of memory.
-
- Note that whenever \a pcb_dst is to be set, it MUST be set to a valid byte
- count. It can not be assigned \a KCDB_CBSIZE_AUTO even if the data type
- supports it. The \a pcb_dst parameter is used internally to allocate
- memory for the object.
-
- \subsubsection kcdb_pg_cb_iv isValid
-
- \code
- khm_boolean isValid(
- const void * data,
- khm_int32 cb_data);
- \endcode
-
- Checks if the object pointed to by the \a data pointer is a valid object
- for this data type. If the data type specified the \a KCDB_TYPE_CB_AUTO
- flag, then the \a cb_data parameter may be \a KCDB_CBSIZE_AUTO, in which
- the size of the object should be inferred from the data.
-
- The function should be able to determine the validity of the object and
- return \a TRUE if it is valid. Return \a FALSE if it isn't, or if the
- size of the object can not be inferred from the given data, or if the
- inferred size exceeds \a KCDB_TYPE_MAXCB.
-
-*/
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ * Copyright (c) 2007 Secure Endpoints Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+/*! \page cred_data_types Data types in Network Identity Manager
+
+ Network Identity Manager's Credentials Database supports several
+ useful data types. In addition, plug-ins can define custom data
+ types. Only a few operations are expected of these data types
+ since the core KCDB delegates fine grained operations to other
+ entities that understand the underlying format.
+
+ A field in a credential can have any one of these data types, but
+ it must have some data type. Each value can be at most \a
+ KCDB_TYPE_MAXCB bytes in length regardless of the data type.
+
+ Some data types have a fixed size (such as \a Int32), while others
+ are variable size. The required memory for each field in a
+ credential is allocated as needed.
+
+ \section kcdb_pg_dt Data types
+
+ Descriptions of individual data types are below.
+
+ \subsection kcdb_pg_idt Individual data types
+
+ \subsubsection kcdb_pg_idt_v Void
+
+ Type identifier : ::KCDB_TYPE_VOID
+
+ The Void data type is used to indicate that the associated object
+ does not contain any data.
+
+ \subsubsection kcdb_pg_idt_s String
+
+ Type identifier : ::KCDB_TYPE_STRING
+
+ A unicode string that is terminated with a unicode NULL (L'\\0').
+ By default, the type has the following flags:
+
+ \a KCDB_TYPE_FLAG_CB_AUTO
+
+ This is because, as long as the string is terminated with a unicode NULL,
+ the length of the string, and therefore it's size in bytes, can be inferred
+ from the data itself.
+
+ \subsubsection kcdb_pg_idt_d Date
+
+ Type identifier : ::KCDB_TYPE_DATE
+
+ Dates and times in Network Identity Manager are stored in \a
+ FILETIME structures. Utility functions are provided for
+ converting from other formats such as \a time_t.
+
+ \subsubsection kcdb_pg_idt_i Interval
+
+ Type identifier : ::KCDB_TYPE_INTERVAL
+
+ Stores an interval of time. Stored as a 64-bit signed integer. The
+ string representation of this data type is different from the \a
+ Date data type and designates an interval of time.
+
+ The special value _I64_MAX (which is defined in limits.h as
+ 0x7fffffffffffffff, or in other words, the largest positive value
+ that can be stored in a 64-bit signed integer) is used to
+ represent an interval of unknown length.
+
+ The string representations of a data value of Interval type are
+ defined as follows for English (US):
+
+ - "(Unknown)" if the value is _I64_MAX
+
+ - "(Expired)" if the value is less than zero
+
+ - "%d days %d hours" if the value is greater than 24 hours
+
+ - "%d hours %d mins" if the value is greater than 1 hour
+
+ - "%d mins %d secs" if the value is greater than 1 minute
+
+ - "%d seconds" otherwise
+
+ \subsubsection kcdb_pg_idt_i32 Int32
+
+ Type identifier : ::KCDB_TYPE_INT32
+
+ A signed 32-bit integer.
+
+ \subsubsection kcdb_pg_idt_i64 Int64
+
+ Type identifier : ::KCDB_TYPE_INT64
+
+ A signed 64-bit integer.
+
+ \subsubsection kcdb_pg_idt_da Data
+
+ Type identifier : ::KCDB_TYPE_DATA
+
+ Raw data. Can contain a byte stream. This data type can be used
+ by plug-ins to associate raw data with a credential. However,
+ there is no built-in string representation for this data type. As
+ such, this is not meant to be used for storing anything that has
+ to be displayed to the user verbatim.
+
+ \section kcdb_pg_cust Custom data types
+
+ \subsection kcdb_pg_cb Custom data type call backs
+
+ Custom data types in the Network Identity Manager Credentials
+ Database are defined using \a kcdb_type structures that must
+ include several callback functions. The expected behavior of
+ these callback functions is documented below.
+
+ \subsubsection kcdb_pg_cb_ts toString
+
+ \code
+ khm_int32 toString(
+ const void * data,
+ khm_int32 cb_data,
+ wchar_t *buffer,
+ khm_int32 *pcb_buffer,
+ khm_int32 flags);
+ \endcode
+
+ Produce the localized string representation of the object pointed to by
+ \a data. The size of the data block is specified by the \a cb_data
+ parameter. If the data type specified the \a KCDB_TYPE_FLAG_CB_AUTO flag
+ then \a cb_data can be \a KCDB_CBSIZE_AUTO, in which case the size of the
+ data block is to be inferred.
+
+ \a toString should assume that the block of data pointed to by \a data is
+ valid for this data type.
+
+ The \a pcb_buffer parameter is always a valid pointer to an \a khm_int32
+ variable.
+
+ The \a buffer parameter is a pointer to a \a wchar_t buffer which is to
+ receive the unicode string representing the object. \a buffer may be
+ \a NULL, in which case the required size of the buffer should be returned
+ in \a pcb_buffer. In this case, the function should return
+ \a KHM_ERROR_TOO_LONG.
+
+ If the \a buffer parameter is not \a NULL and the \a pcb_buffer specifies
+ that the buffer is large enough to hold the string representation, the
+ function should copy the string representation to the buffer, set the
+ \a pcb_buffer to the number of bytes that were copied including the
+ terminating \a NULL, and return \a KHM_ERROR_SUCCESS.
+
+ If the \a buffer parameter is not \a NULL and the \a pcb_buffer specifies
+ a buffer that is not large enough, the function should set \a pcb_buffer
+ to the required size (including the terminating \a NULL) and then return
+ \a KHM_ERROR_TOO_LONG.
+
+ \subsubsection kcdb_pg_cb_cmp comp
+
+ \code
+ khm_int32 comp(
+ const void * data1,
+ khm_int32 cb_data1,
+ const void * data2,
+ khm_int32 cb_d2);
+ \endcode
+
+ Compares two objects and returns a value indicating the relative ordering.
+
+ Since the KCDB does not interpret any data type, it relies on a loose
+ definition of what a relative ordering is. It is left up to each data
+ type callback to interpret what 'ascending' and 'descending' mean.
+
+ The return value \a r should be as follows:
+
+ \a r < 0 : if \a data1 < \a data2
+
+ \a r > 0 : if \a data1 > \a data2
+
+ \a r = 0 : if \a data1 = \a data2 or no relative ordering can be determined
+ for the two objects \a data1 and \a data2.
+
+ The function should assume that both objects are valid for this data type.
+
+ The size specifiers \a cb_data1 and \a cb_data2 can (either or both) be
+ \a KCDB_CBSIZE_AUTO if the data type specified \a KCDB_TYPE_FLAG_CB_AUTO
+ flag.
+
+ \subsubsection kcdb_pg_cb_dup dup
+
+ \code
+ khm_int32 dup(
+ const void * d_src,
+ khm_int32 cb_src,
+ void * d_dst,
+ khm_int32 * pcb_dst);
+ \endcode
+
+ Duplicate an object. The object pointed to by \a d_src is to be copied to
+ the buffer pointed to by \a d_dst. The function is to assume that \a d_src
+ object is valid. The size specifier \a cb_src may be \a KCDB_CBSIZE_AUTO
+ if \a KCDB_TYPE_FLAG_CB_AUTO was specified for the data type.
+
+ If \a d_dst pointer is \a NULL, then the required buffer size should be
+ returned in \a pcb_dst. In this case, the function itself should return
+ \a KHM_ERROR_TOO_LONG. The same behavior should occur if \a d_dst is non
+ \a NULL and \a pcb_dst indicates that the buffer is not sufficient.
+
+ If \a d_dst is not \a NULL and \a pcb_dst indicates that the buffer is
+ sufficient, then a copy of the object in \a d_src should be placed in
+ \a d_dst. The function shold return \a KHM_ERROR_SUCCESS and set
+ \a pcb_dst to the number of bytes that were copied.
+
+ This callback will only be called when the credentials database is
+ retrieving objects from the outside. Once it receives an object it may be
+ copied or moved as required. Hence the object should not assume to reside
+ in a specific location of memory. Also, \a dup is not intended to perform
+ such functions as reference counting which require knowledge of a precise
+ number of instances of an object, as the credentials database may copy
+ the object simply by copying the block of memory.
+
+ Note that whenever \a pcb_dst is to be set, it MUST be set to a valid byte
+ count. It can not be assigned \a KCDB_CBSIZE_AUTO even if the data type
+ supports it. The \a pcb_dst parameter is used internally to allocate
+ memory for the object.
+
+ \subsubsection kcdb_pg_cb_iv isValid
+
+ \code
+ khm_boolean isValid(
+ const void * data,
+ khm_int32 cb_data);
+ \endcode
+
+ Checks if the object pointed to by the \a data pointer is a valid object
+ for this data type. If the data type specified the \a KCDB_TYPE_CB_AUTO
+ flag, then the \a cb_data parameter may be \a KCDB_CBSIZE_AUTO, in which
+ the size of the object should be inferred from the data.
+
+ The function should be able to determine the validity of the object and
+ return \a TRUE if it is valid. Return \a FALSE if it isn't, or if the
+ size of the object can not be inferred from the given data, or if the
+ inferred size exceeds \a KCDB_TYPE_MAXCB.
+
+*/
diff --git a/src/windows/identity/doc/cred_main.h b/src/windows/identity/doc/cred_main.h
index a9949aedb6..97ac0c2af8 100644
--- a/src/windows/identity/doc/cred_main.h
+++ b/src/windows/identity/doc/cred_main.h
@@ -1,36 +1,36 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- * Copyright (c) 2007 Secure Endpoints Inc.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-/*! \page cred Credentials Providers
-
- \section cred_contents Contents
-
- - \subpage cred_data_types
- - \subpage cred_acq
- - \subpage cred_prop_pages
- - \subpage cred_msgs
-*/
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ * Copyright (c) 2007 Secure Endpoints Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+/*! \page cred Credentials Providers
+
+ \section cred_contents Contents
+
+ - \subpage cred_data_types
+ - \subpage cred_acq
+ - \subpage cred_prop_pages
+ - \subpage cred_msgs
+*/
diff --git a/src/windows/identity/doc/cred_msgs.h b/src/windows/identity/doc/cred_msgs.h
index 6d7cd3d1b2..405acef454 100644
--- a/src/windows/identity/doc/cred_msgs.h
+++ b/src/windows/identity/doc/cred_msgs.h
@@ -1,48 +1,48 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- * Copyright (c) 2007 Secure Endpoints Inc.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-/*! \page cred_msgs Handling credentials provider messages
-
-A credentials provider plug-in receives a number of messages during the
-course of execution. This section describes the appropriate ways of
-handling these messages.
-
-\section pi_credmsg_system System mesages
-
-There are only two system messages that a credentials provider needs
-to handle. Both of these are explained elsewhere as they deal with
-initialization and uninitialization of the plug-in. See the following
-two sections for details on handling these messages.
-
-- <::KMSG_SYSTEM,::KMSG_SYSTEM_INIT> \ref pi_pt_cred_init
-- <::KMSG_SYSTEM,::KMSG_SYSTEM_EXIT> \ref pi_pt_cred_exit
-
-\section pi_credmsg_cred Credential messages
-
-
-
-*/
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ * Copyright (c) 2007 Secure Endpoints Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+/*! \page cred_msgs Handling credentials provider messages
+
+A credentials provider plug-in receives a number of messages during the
+course of execution. This section describes the appropriate ways of
+handling these messages.
+
+\section pi_credmsg_system System mesages
+
+There are only two system messages that a credentials provider needs
+to handle. Both of these are explained elsewhere as they deal with
+initialization and uninitialization of the plug-in. See the following
+two sections for details on handling these messages.
+
+- <::KMSG_SYSTEM,::KMSG_SYSTEM_INIT> \ref pi_pt_cred_init
+- <::KMSG_SYSTEM,::KMSG_SYSTEM_EXIT> \ref pi_pt_cred_exit
+
+\section pi_credmsg_cred Credential messages
+
+
+
+*/
diff --git a/src/windows/identity/doc/cred_prop_pages.h b/src/windows/identity/doc/cred_prop_pages.h
index fd1da5ad60..ac82e1c5d9 100644
--- a/src/windows/identity/doc/cred_prop_pages.h
+++ b/src/windows/identity/doc/cred_prop_pages.h
@@ -1,84 +1,84 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- * Copyright (c) 2007 Secure Endpoints Inc.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-/*! \page cred_prop_pages Property Pages for Credentials
-
- This section describes the logistics of property pages. When a
- user selects the 'Properties' option from a menu (either the File
- menu or a context menu), then a KHUI_ACTION_PROPERTIES action is
- triggered. This is handled by the credentials window and triggers
- the launch of a property sheet if there is a valid context to
- extract properties from.
-
- Sequence of actions:
-
- - KHUI_ACTION_PROPERTIES action is triggered.
-
- - The main window dispatches the action to the credentials window.
-
- - If there is a valid context, then the credentials window calls
- khui_ps_create_sheet() to create an empty property sheet
- structure of type ::khui_property_sheet. The \a ctx member of
- the structure is populated with the property context obtained
- through khui_context_get().
-
- - A global message is broadcast of type
- <::KMSG_CRED,::KMSG_CRED_PP_BEGIN> with the parameter blob that
- is a pointer to the ::khui_property_sheet structure.
-
- - Subscribers to <::KMSG_CRED> messages handle the message, check
- the \a ctx member of the structure and determine whether or not
- and what type property pages to add to the property sheet. New
- property sheets are added by calling khui_ps_add_page().
-
- - Once all the pages are added, a
- <::KMSG_CRED,::KMSG_CRED_PP_PRECREATE> message is broadcast.
- This is a chance for the property page providers to do any
- processing before the property page is created.
-
- - The property sheet is created and made visible with a call to
- khui_ps_show_sheet().
-
- - The Network Identity Manager message loop takes over. Further interaction
- including notifications of 'Ok','Cancel','Apply' and other
- property sheet related actions are handled through WIN32
- messages.
-
- - Once the user closes the property sheet, a
- <::KMSG_CRED,::KMSG_CRED_PP_END> message is sent to all
- subscribers. Individual subscribers who added pages to the
- property sheet must free up any associated resources at this
- point.
-
- - All the ::khui_property_page structures that were allocated as
- well as the ::khui_property_sheet structure are freed up with a
- call to khui_ps_destroy_sheet().
-
-The maximum number of property sheets that can be open at one time is
-currently set to 256. Each property sheet can have a maximum of 16
-property pages.
- */
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ * Copyright (c) 2007 Secure Endpoints Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+/*! \page cred_prop_pages Property Pages for Credentials
+
+ This section describes the logistics of property pages. When a
+ user selects the 'Properties' option from a menu (either the File
+ menu or a context menu), then a KHUI_ACTION_PROPERTIES action is
+ triggered. This is handled by the credentials window and triggers
+ the launch of a property sheet if there is a valid context to
+ extract properties from.
+
+ Sequence of actions:
+
+ - KHUI_ACTION_PROPERTIES action is triggered.
+
+ - The main window dispatches the action to the credentials window.
+
+ - If there is a valid context, then the credentials window calls
+ khui_ps_create_sheet() to create an empty property sheet
+ structure of type ::khui_property_sheet. The \a ctx member of
+ the structure is populated with the property context obtained
+ through khui_context_get().
+
+ - A global message is broadcast of type
+ <::KMSG_CRED,::KMSG_CRED_PP_BEGIN> with the parameter blob that
+ is a pointer to the ::khui_property_sheet structure.
+
+ - Subscribers to <::KMSG_CRED> messages handle the message, check
+ the \a ctx member of the structure and determine whether or not
+ and what type property pages to add to the property sheet. New
+ property sheets are added by calling khui_ps_add_page().
+
+ - Once all the pages are added, a
+ <::KMSG_CRED,::KMSG_CRED_PP_PRECREATE> message is broadcast.
+ This is a chance for the property page providers to do any
+ processing before the property page is created.
+
+ - The property sheet is created and made visible with a call to
+ khui_ps_show_sheet().
+
+ - The Network Identity Manager message loop takes over. Further interaction
+ including notifications of 'Ok','Cancel','Apply' and other
+ property sheet related actions are handled through WIN32
+ messages.
+
+ - Once the user closes the property sheet, a
+ <::KMSG_CRED,::KMSG_CRED_PP_END> message is sent to all
+ subscribers. Individual subscribers who added pages to the
+ property sheet must free up any associated resources at this
+ point.
+
+ - All the ::khui_property_page structures that were allocated as
+ well as the ::khui_property_sheet structure are freed up with a
+ call to khui_ps_destroy_sheet().
+
+The maximum number of property sheets that can be open at one time is
+currently set to 256. Each property sheet can have a maximum of 16
+property pages.
+ */
diff --git a/src/windows/identity/doc/main_page.h b/src/windows/identity/doc/main_page.h
index 55ccb69dc2..58aece3fc5 100644
--- a/src/windows/identity/doc/main_page.h
+++ b/src/windows/identity/doc/main_page.h
@@ -1,166 +1,166 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- * Copyright (c) 2007 Secure Endpoints Inc.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-/*! \mainpage Network Identity Manager
-
- \image html khimaira_logo.png
-
- \section main_dev Documentation for Developers
-
- Network Identity Manager is a credentials manager, which is
- capable of managing Kerberos v5, Kerberos v4, Andrew File System,
- and Kerberized Certificate Authority credentials. This document
- describes the API that is implemented by the Khimaira framework
- upon which Network Identity Manager is based.
-
- See the following sections for more information :
- - \subpage license
- - \subpage bugs
- - \subpage releases
-
- &copy; 2004-2007 Massachusetts Institute of Technology
-
- &copy; 2005-2007 Secure Endpoints Inc.
-*/
-
-/*!
- \page license License agreement and credits
-
- Network Identity Manager is distributed under the MIT License.
-
- \section license_l MIT License
-
- Copyright &copy; 2004,2005,2006,2007 Massachusetts Institute of Technology
-
- Copyright &copy; 2005,2006,2007 Secure Endpoints Inc.
-
- Permission is hereby granted, free of charge, to any person
- obtaining a copy of this software and associated documentation
- files (the "Software"), to deal in the Software without
- restriction, including without limitation the rights to use, copy,
- modify, merge, publish, distribute, sublicense, and/or sell copies
- of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
-
- The above copyright notice and this permission notice shall be
- included in all copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- DEALINGS IN THE SOFTWARE.
-
- \section license_credits Credits
-
- Network Identity Manager was developed at the Massachusetts Institute of
- Technology in partnership with Secure Endpoints Inc.
-
- <a href="http://web.mit.edu/is">Information Services and
- Technology</a> at <a href="http://web.mit.edu">Massachusetts
- Institute of Technology</a>
-
- <a href="http://www.secure-endpoints.com">Secure Endpoints Inc.</a>
-*/
-
-/*! \page bugs Reporting bugs
-
- Network Identity Manager bugs can be reported to
- <a href="mailto:kfw-bugs@mit.edu">kfw-bugs@mit.edu</a> or
- <a href="mailto:netidmgr@secure-endpoints.com">netidmgr@secure-endpoints.com</a>
-
- When reporting bugs, please include as much information as
- possible to help reproduce the problem.
-
- \image html khimaira_logo_small.png
-*/
-
-/*! \page releases Prior releases
-
- The following is a list of releases of Network Identity Manager.
- Whenever there is an addition to the API or a significant change
- in behavior, the API version is incremented. A plug-in that is
- developed against a particular version of the API will be
- compatible with any release of Network Identity Manager that
- implements that version of the API.
-
- The Network Identity Manager version number is set as the file and
- product version of <tt>nidmgr32.dll</tt>.
-
- - <b>1.2.0.2</b> Kerberos for Windows 3.2 Beta 2 <em>Apr 11, 2007</em>\n
- API version : <b>8</b>
-
- - <b>1.2.0.1</b> <em>Apr 06, 2007</em>\n
- API version : <b>8</b>
-
- - <b>1.2.0.0</b> Kerberos for Windows 3.2 Beta 1 <em>Mar 29, 2007</em>\n
- API version : <b>8</b>
-
- - <b>1.1.11.0</b> <em>Mar 20, 2007</em>\n
- API version : <b>8</b>
-
- - <b>1.1.10.0</b> <em>Feb 28, 2007</em>\n
- API version : <b>8</b>
-
- - <b>1.1.9.0</b> <em>Jan 20, 2007</em>\n
- API version : <b>7</b>
-
- - <b>1.1.8.0</b> Kerberos for Windows 3.1 Final <em>Nov 22, 2006</em>\n
- API version : <b>6</b>
-
- - <b>1.1.6.0</b> Kerberos for Windows 3.1 Beta 4 <em>Nov 17, 2006</em>\n
- API version : <b>6</b>
-
- - <b>1.1.4.0</b> Kerberos for Windows 3.1 Beta 3 <em>Nov 08, 2006</em>\n
- API version : <b>6</b>
-
- - <b>1.1.2.0</b> <em>Oct 09, 2006</em>\n
- API version : <b>6</b>
-
- - <b>1.1.0.2</b> <em>Sep 21, 2006</em>\n
- API version : <b>6</b>
-
- - <b>1.1.0.1</b> <em>Jul 19, 2006</em>\n
- API version : <b>5</b>
-
- - <b>1.1.0.0</b> <em>Mar 08, 2006</em>\n
- API version : <b>5</b>
-
- - <b>1.0.0.0</b> Kerberos for Windows 3.0 <em>Dec 05, 2005</em>\n
- API version : <b>4</b>
-
- - <b>0.1.2.0</b> Second Alpha release <em>Nov 30, 2005</em>\n
- API version : <b>3</b>\n
- Released along with Kerberos for Windows 3.0 beta 2.
-
- - <b>0.1.1</b> First Alpha release <em>Nov 01, 2005</em>\n
- Released along with Kerberos for Windows 3.0 beta.
-
-*/
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ * Copyright (c) 2007 Secure Endpoints Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+/*! \mainpage Network Identity Manager
+
+ \image html khimaira_logo.png
+
+ \section main_dev Documentation for Developers
+
+ Network Identity Manager is a credentials manager, which is
+ capable of managing Kerberos v5, Kerberos v4, Andrew File System,
+ and Kerberized Certificate Authority credentials. This document
+ describes the API that is implemented by the Khimaira framework
+ upon which Network Identity Manager is based.
+
+ See the following sections for more information :
+ - \subpage license
+ - \subpage bugs
+ - \subpage releases
+
+ &copy; 2004-2007 Massachusetts Institute of Technology
+
+ &copy; 2005-2007 Secure Endpoints Inc.
+*/
+
+/*!
+ \page license License agreement and credits
+
+ Network Identity Manager is distributed under the MIT License.
+
+ \section license_l MIT License
+
+ Copyright &copy; 2004,2005,2006,2007 Massachusetts Institute of Technology
+
+ Copyright &copy; 2005,2006,2007 Secure Endpoints Inc.
+
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation
+ files (the "Software"), to deal in the Software without
+ restriction, including without limitation the rights to use, copy,
+ modify, merge, publish, distribute, sublicense, and/or sell copies
+ of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
+
+ \section license_credits Credits
+
+ Network Identity Manager was developed at the Massachusetts Institute of
+ Technology in partnership with Secure Endpoints Inc.
+
+ <a href="http://web.mit.edu/is">Information Services and
+ Technology</a> at <a href="http://web.mit.edu">Massachusetts
+ Institute of Technology</a>
+
+ <a href="http://www.secure-endpoints.com">Secure Endpoints Inc.</a>
+*/
+
+/*! \page bugs Reporting bugs
+
+ Network Identity Manager bugs can be reported to
+ <a href="mailto:kfw-bugs@mit.edu">kfw-bugs@mit.edu</a> or
+ <a href="mailto:netidmgr@secure-endpoints.com">netidmgr@secure-endpoints.com</a>
+
+ When reporting bugs, please include as much information as
+ possible to help reproduce the problem.
+
+ \image html khimaira_logo_small.png
+*/
+
+/*! \page releases Prior releases
+
+ The following is a list of releases of Network Identity Manager.
+ Whenever there is an addition to the API or a significant change
+ in behavior, the API version is incremented. A plug-in that is
+ developed against a particular version of the API will be
+ compatible with any release of Network Identity Manager that
+ implements that version of the API.
+
+ The Network Identity Manager version number is set as the file and
+ product version of <tt>nidmgr32.dll</tt>.
+
+ - <b>1.2.0.2</b> Kerberos for Windows 3.2 Beta 2 <em>Apr 11, 2007</em>\n
+ API version : <b>8</b>
+
+ - <b>1.2.0.1</b> <em>Apr 06, 2007</em>\n
+ API version : <b>8</b>
+
+ - <b>1.2.0.0</b> Kerberos for Windows 3.2 Beta 1 <em>Mar 29, 2007</em>\n
+ API version : <b>8</b>
+
+ - <b>1.1.11.0</b> <em>Mar 20, 2007</em>\n
+ API version : <b>8</b>
+
+ - <b>1.1.10.0</b> <em>Feb 28, 2007</em>\n
+ API version : <b>8</b>
+
+ - <b>1.1.9.0</b> <em>Jan 20, 2007</em>\n
+ API version : <b>7</b>
+
+ - <b>1.1.8.0</b> Kerberos for Windows 3.1 Final <em>Nov 22, 2006</em>\n
+ API version : <b>6</b>
+
+ - <b>1.1.6.0</b> Kerberos for Windows 3.1 Beta 4 <em>Nov 17, 2006</em>\n
+ API version : <b>6</b>
+
+ - <b>1.1.4.0</b> Kerberos for Windows 3.1 Beta 3 <em>Nov 08, 2006</em>\n
+ API version : <b>6</b>
+
+ - <b>1.1.2.0</b> <em>Oct 09, 2006</em>\n
+ API version : <b>6</b>
+
+ - <b>1.1.0.2</b> <em>Sep 21, 2006</em>\n
+ API version : <b>6</b>
+
+ - <b>1.1.0.1</b> <em>Jul 19, 2006</em>\n
+ API version : <b>5</b>
+
+ - <b>1.1.0.0</b> <em>Mar 08, 2006</em>\n
+ API version : <b>5</b>
+
+ - <b>1.0.0.0</b> Kerberos for Windows 3.0 <em>Dec 05, 2005</em>\n
+ API version : <b>4</b>
+
+ - <b>0.1.2.0</b> Second Alpha release <em>Nov 30, 2005</em>\n
+ API version : <b>3</b>\n
+ Released along with Kerberos for Windows 3.0 beta 2.
+
+ - <b>0.1.1</b> First Alpha release <em>Nov 01, 2005</em>\n
+ Released along with Kerberos for Windows 3.0 beta.
+
+*/
diff --git a/src/windows/identity/doc/plugin_framework.h b/src/windows/identity/doc/plugin_framework.h
index a10af2a6f4..5f225b8112 100644
--- a/src/windows/identity/doc/plugin_framework.h
+++ b/src/windows/identity/doc/plugin_framework.h
@@ -1,183 +1,183 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- * Copyright (c) 2007 Secure Endpoints Inc.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-/*!
-\page pi_framework Plug-in Framework
-
-\section pi_fw_pnm Introduction to Plug-ins, Modules and Messages
-
-\subsection pi_fw_pnm_p Plug-ins
-
-A plug-in is a package that implements a defined API that will perform
-credentials management or related tasks on behalf of Network Identity
-Manager.
-
-The Network Identity Manager architecture is message based. The core
-of each plug-in is a message handler. The plug-in integrates with the
-application by subscribing to, and handling specific types of
-messages.
-
-The plug-in message handler runs in its own thread and receive
-asynchronous messages. There are exceptions, such as when one plug-in
-requires another plug-in to handle a specific message before it can
-handle the message. In addition, during certain operations that
-require user interaction, each plug-in can delegate code that will run
-in the main application thread (the user interface thread) to process
-window messages.
-
-\subsection pi_fw_pnw_m Modules
-
-One or more plug-ins can be bundled together into a module. A module
-is a dynamically loadable library which exports a specific set of
-callbacks. Currently, the only two required callbacks for a module
-are :
-
-- init_module(), and
-- exit_module()
-
-For more information about how a module is structured, see \ref
-pi_structure .
-
-\subsection pi_fw_pnm_msg Messages and Message Queues
-
-An integral part of this framework is the messaging system. Most of
-the communication between the Network Identity Manager application and
-plug-ins is conducted through passing messages.
-
-A message has a type and subtype and is denoted in this documentation
-as \< \e message_type, \e message_subtype\>. For example, when a
-plug-in is loaded, the first message it receives is \< ::KMSG_SYSTEM,
-::KMSG_SYSTEM_INIT \>.
-
-Each thread in the application, specially threads that were created
-for individual plug-in messages handlers, has an associated message
-queue that stores and manages all the messages that have been sent to
-subscribers in that thread.
-
-The most common recipient of a message is a message callback function
-(see ::kmq_callback_t ). The message handler for a plug-in is one such
-example. A message callback function receives the message type,
-subtype and two optional parameters for the message.
-
-Any acceptable recipient can subscribe to broadcast messages of any
-type. Once subscribed, whenever a message of that type is broadcast,
-the message will get queued on the corresponding message queue. Then,
-one of the dispatch functions can dispatch the message to the correct
-callback function. (see ::kmq_dispatch).
-
-Next \subpage pi_fw_pm ...
-
-*/
-
-/*!
-
-\page pi_fw_pm Module Manager
-
-The module manager is tasked with loading, unloading and managing the
-plug-in message processing. It maintains a separate thread for loading
-and registering modules. When a module is successfully loaded and it
-registers one or more plug-ins, a new thread is created for each
-plug-in. Plug-in specific initialization and other callback functions
-are called from within this new thread. This is to prevent one
-plug-in from "hanging" other plug-ins and the main Network Identity
-Manager user interface threads.
-
-Read more :
-- \ref pi_structure
-
-\subsection pi_fw_pm_load Load sequence
-
-When kmm_load_module() is called to load a specific module, the
-following sequence of events occur:
-
-- The registration information for the module is located on the
- registry key \c
- \Software\MIT\NetIDMgr\PluginManager\Modules\[ModuleName].
-
-- The \c ImagePath value from the registration information is used to
- locate the module binary. If it is not an absolute path, then the
- binary is located using the standard system search path starting
- from the directory in which Network Identity Manager binaries are
- located.
-
-- The binary is loaded into the address space of Network Identity
- Manager along with any dependencies not already loaded.
-
-- If the Network Identity Manager core binary is signed, then the
- signature is checked against the system and user certificate stores.
- If this fails, the module is unloaded. See \ref pi_fw_pm_unload.
-
-- The init_module() entry point for the loaded module is called. If
- this function returns an error or if no plug-ins are registered,
- then the module is immediately unloaded. See \ref pi_fw_pm_unload.
-
-- During processing of init_module(), if any localized resource
- libraries are specified using kmm_set_locale_info(), then one of the
- localized libraries will be loaded. See \ref pi_localization
-
-- During processing of init_module(), the module registers all the
- plug-ins that it is implementing by calling kmm_register_plugin() for
- each.
-
-- Once init_module() returns, each plug-in is initialized. The method
- by which a plug-in is initialized depends on the plug-in type. The
- initialization code for the plug-in may indicate that it didn't
- initialize properly, in which case the plug-in is immediately
- unregistered. No further calls are made to the plug-in.
-
-- If no plug-in is successfully loaded, the module is unloaded. See
- \ref pi_fw_pm_unload.
-
-- During normal operation, any registered plug-ins for a module can be
- unloaded explicitly, or the plug-in itself may signal that it should
- be unloaded. If at anytime, all the plug-ins for the module are
- unloaded, then the module itself is also unloaded unless the \c
- NoUnload registry value is set in the module key.
-
-\subsection pi_fw_pm_unload Unload sequence
-
-- For each of the plug-ins that are registered for a module, the exit
- code is invoked. The method by which this happens depends on the
- plug-in type. The plug-in is not given a chance to veto the
- decision to unload. Each plug-in is responsible for performing
- cleanup tasks, freeing resources and unsubscribing from any message
- classes that it has subscribed to.
-
-- The exit_module() entry point is called for the module.
-
-- If any localized resource libraries were loaded for the module, they
- are unloaded.
-
-- The module is unloaded.
-
-The following diagram illustrates the relationship between modules and
-plug-ins as implemented in the Kerberos 5 plug-in distributed with
-Network Identity Manager.
-
-\image html modules_plugins_krb5.png
-
- */
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ * Copyright (c) 2007 Secure Endpoints Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+/*!
+\page pi_framework Plug-in Framework
+
+\section pi_fw_pnm Introduction to Plug-ins, Modules and Messages
+
+\subsection pi_fw_pnm_p Plug-ins
+
+A plug-in is a package that implements a defined API that will perform
+credentials management or related tasks on behalf of Network Identity
+Manager.
+
+The Network Identity Manager architecture is message based. The core
+of each plug-in is a message handler. The plug-in integrates with the
+application by subscribing to, and handling specific types of
+messages.
+
+The plug-in message handler runs in its own thread and receive
+asynchronous messages. There are exceptions, such as when one plug-in
+requires another plug-in to handle a specific message before it can
+handle the message. In addition, during certain operations that
+require user interaction, each plug-in can delegate code that will run
+in the main application thread (the user interface thread) to process
+window messages.
+
+\subsection pi_fw_pnw_m Modules
+
+One or more plug-ins can be bundled together into a module. A module
+is a dynamically loadable library which exports a specific set of
+callbacks. Currently, the only two required callbacks for a module
+are :
+
+- init_module(), and
+- exit_module()
+
+For more information about how a module is structured, see \ref
+pi_structure .
+
+\subsection pi_fw_pnm_msg Messages and Message Queues
+
+An integral part of this framework is the messaging system. Most of
+the communication between the Network Identity Manager application and
+plug-ins is conducted through passing messages.
+
+A message has a type and subtype and is denoted in this documentation
+as \< \e message_type, \e message_subtype\>. For example, when a
+plug-in is loaded, the first message it receives is \< ::KMSG_SYSTEM,
+::KMSG_SYSTEM_INIT \>.
+
+Each thread in the application, specially threads that were created
+for individual plug-in messages handlers, has an associated message
+queue that stores and manages all the messages that have been sent to
+subscribers in that thread.
+
+The most common recipient of a message is a message callback function
+(see ::kmq_callback_t ). The message handler for a plug-in is one such
+example. A message callback function receives the message type,
+subtype and two optional parameters for the message.
+
+Any acceptable recipient can subscribe to broadcast messages of any
+type. Once subscribed, whenever a message of that type is broadcast,
+the message will get queued on the corresponding message queue. Then,
+one of the dispatch functions can dispatch the message to the correct
+callback function. (see ::kmq_dispatch).
+
+Next \subpage pi_fw_pm ...
+
+*/
+
+/*!
+
+\page pi_fw_pm Module Manager
+
+The module manager is tasked with loading, unloading and managing the
+plug-in message processing. It maintains a separate thread for loading
+and registering modules. When a module is successfully loaded and it
+registers one or more plug-ins, a new thread is created for each
+plug-in. Plug-in specific initialization and other callback functions
+are called from within this new thread. This is to prevent one
+plug-in from "hanging" other plug-ins and the main Network Identity
+Manager user interface threads.
+
+Read more :
+- \ref pi_structure
+
+\subsection pi_fw_pm_load Load sequence
+
+When kmm_load_module() is called to load a specific module, the
+following sequence of events occur:
+
+- The registration information for the module is located on the
+ registry key \c
+ \Software\MIT\NetIDMgr\PluginManager\Modules\[ModuleName].
+
+- The \c ImagePath value from the registration information is used to
+ locate the module binary. If it is not an absolute path, then the
+ binary is located using the standard system search path starting
+ from the directory in which Network Identity Manager binaries are
+ located.
+
+- The binary is loaded into the address space of Network Identity
+ Manager along with any dependencies not already loaded.
+
+- If the Network Identity Manager core binary is signed, then the
+ signature is checked against the system and user certificate stores.
+ If this fails, the module is unloaded. See \ref pi_fw_pm_unload.
+
+- The init_module() entry point for the loaded module is called. If
+ this function returns an error or if no plug-ins are registered,
+ then the module is immediately unloaded. See \ref pi_fw_pm_unload.
+
+- During processing of init_module(), if any localized resource
+ libraries are specified using kmm_set_locale_info(), then one of the
+ localized libraries will be loaded. See \ref pi_localization
+
+- During processing of init_module(), the module registers all the
+ plug-ins that it is implementing by calling kmm_register_plugin() for
+ each.
+
+- Once init_module() returns, each plug-in is initialized. The method
+ by which a plug-in is initialized depends on the plug-in type. The
+ initialization code for the plug-in may indicate that it didn't
+ initialize properly, in which case the plug-in is immediately
+ unregistered. No further calls are made to the plug-in.
+
+- If no plug-in is successfully loaded, the module is unloaded. See
+ \ref pi_fw_pm_unload.
+
+- During normal operation, any registered plug-ins for a module can be
+ unloaded explicitly, or the plug-in itself may signal that it should
+ be unloaded. If at anytime, all the plug-ins for the module are
+ unloaded, then the module itself is also unloaded unless the \c
+ NoUnload registry value is set in the module key.
+
+\subsection pi_fw_pm_unload Unload sequence
+
+- For each of the plug-ins that are registered for a module, the exit
+ code is invoked. The method by which this happens depends on the
+ plug-in type. The plug-in is not given a chance to veto the
+ decision to unload. Each plug-in is responsible for performing
+ cleanup tasks, freeing resources and unsubscribing from any message
+ classes that it has subscribed to.
+
+- The exit_module() entry point is called for the module.
+
+- If any localized resource libraries were loaded for the module, they
+ are unloaded.
+
+- The module is unloaded.
+
+The following diagram illustrates the relationship between modules and
+plug-ins as implemented in the Kerberos 5 plug-in distributed with
+Network Identity Manager.
+
+\image html modules_plugins_krb5.png
+
+ */
diff --git a/src/windows/identity/doc/plugin_locale.h b/src/windows/identity/doc/plugin_locale.h
index 646f895704..3c6a236e69 100644
--- a/src/windows/identity/doc/plugin_locale.h
+++ b/src/windows/identity/doc/plugin_locale.h
@@ -1,109 +1,109 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- * Copyright (c) 2007 Secure Endpoints Inc.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-/*!
-\page pi_localization Localization
-
-If a module requires localized resources, it can register the
-localized resource libraries with the module manager when it receives
-the init_module() callback. Note that you can only register localized
-resource libraries during init_module().
-
-The localized resource library is global to a module. Each plug-in is
-not allowed to define its own localization library, although it is
-free to load and use any library as it sees fit. The module manager
-does not manage these libraries for the plug-in.
-
-\section pi_loc_spec Specification of localized resources
-
-In order to register localized resource libraries, a module calls
-kmm_set_locale_info(). The \a locales parameter to the function holds
-a pointer to an array of ::kmm_module_locale records. Each record
-specifies one language code and a filename of a library that holds the
-language resources for that language.
-
-It is recommended that you use the LOCALE_DEF convenience macro when
-defining locale records for use with kmm_set_locale_info(). This will
-ensure that future changes in the API will only minimally affect your
-code. For example:
-
-\code
-kmm_module_locale my_locales[] = {
-LOCALE_DEF(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US), L"english.dll", KMM_MLOC_FLAG_DEFAULT),
-LOCALE_DEF(MAKELANGID(LANG_DUTCH,SUBLANG_DUTCH), L"dutch.dll", 0),
-LOCALE_DEF(MAKELANGID(LANG_SPANISH,SUBLANG_SPANISH_MODERN), L"spanish.dll", 0)
-};
-
-int n_locales = sizeof(my_locales)/sizeof(my_locales[0]);
-
-...
-
-kmm_set_locale_info(h_module, my_locales, n_locales);
-
-...
-\endcode
-
-See kmm_set_locale_info() and ::kmm_module_locale for more info.
-
-\section pi_loc_how Selection of localized resource library
-
-The module manager searches the array of ::kmm_module_locale objects
-passed into the kmm_set_locale_info() function for one that matches
-the current user locale (as opposed to the current system locale). A
-record matches the locale if it has the same language ID.
-
-If a match is found, that library is selected. Otherwise, the list is
-searched for one that is compatible with the current user locale. A
-locale record is compatible with the user locale if the primary
-language matches.
-
-If a match is still not found, the first record in the locale array
-that has the ::KMM_MLOC_FLAG_DEFAULT flag set will be selected.
-
-If a match is still not found, then the kmm_set_locale_info() will
-return ::KHM_ERROR_NOT_FOUND.
-
-\section pi_loc_usage Using localization
-
-The following convenience macros are available for using a module
-handle to load resources from the corresponding resource library.
-However, for performance reasons, it is advisable to obtain a handle
-to the resource library loaded by the module manager using
-kmm_get_resource_module() and then use it to access resources using
-the regular WIN32 API.
-
-- ::kmm_LoadAccelerators
-- ::kmm_LoadBitmap
-- ::kmm_LoadCursor
-- ::kmm_LoadIcon
-- ::kmm_LoadImage
-- ::kmm_LoadMenu
-- ::kmm_LoadString
-
-*/
-
-
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ * Copyright (c) 2007 Secure Endpoints Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+/*!
+\page pi_localization Localization
+
+If a module requires localized resources, it can register the
+localized resource libraries with the module manager when it receives
+the init_module() callback. Note that you can only register localized
+resource libraries during init_module().
+
+The localized resource library is global to a module. Each plug-in is
+not allowed to define its own localization library, although it is
+free to load and use any library as it sees fit. The module manager
+does not manage these libraries for the plug-in.
+
+\section pi_loc_spec Specification of localized resources
+
+In order to register localized resource libraries, a module calls
+kmm_set_locale_info(). The \a locales parameter to the function holds
+a pointer to an array of ::kmm_module_locale records. Each record
+specifies one language code and a filename of a library that holds the
+language resources for that language.
+
+It is recommended that you use the LOCALE_DEF convenience macro when
+defining locale records for use with kmm_set_locale_info(). This will
+ensure that future changes in the API will only minimally affect your
+code. For example:
+
+\code
+kmm_module_locale my_locales[] = {
+LOCALE_DEF(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US), L"english.dll", KMM_MLOC_FLAG_DEFAULT),
+LOCALE_DEF(MAKELANGID(LANG_DUTCH,SUBLANG_DUTCH), L"dutch.dll", 0),
+LOCALE_DEF(MAKELANGID(LANG_SPANISH,SUBLANG_SPANISH_MODERN), L"spanish.dll", 0)
+};
+
+int n_locales = sizeof(my_locales)/sizeof(my_locales[0]);
+
+...
+
+kmm_set_locale_info(h_module, my_locales, n_locales);
+
+...
+\endcode
+
+See kmm_set_locale_info() and ::kmm_module_locale for more info.
+
+\section pi_loc_how Selection of localized resource library
+
+The module manager searches the array of ::kmm_module_locale objects
+passed into the kmm_set_locale_info() function for one that matches
+the current user locale (as opposed to the current system locale). A
+record matches the locale if it has the same language ID.
+
+If a match is found, that library is selected. Otherwise, the list is
+searched for one that is compatible with the current user locale. A
+locale record is compatible with the user locale if the primary
+language matches.
+
+If a match is still not found, the first record in the locale array
+that has the ::KMM_MLOC_FLAG_DEFAULT flag set will be selected.
+
+If a match is still not found, then the kmm_set_locale_info() will
+return ::KHM_ERROR_NOT_FOUND.
+
+\section pi_loc_usage Using localization
+
+The following convenience macros are available for using a module
+handle to load resources from the corresponding resource library.
+However, for performance reasons, it is advisable to obtain a handle
+to the resource library loaded by the module manager using
+kmm_get_resource_module() and then use it to access resources using
+the regular WIN32 API.
+
+- ::kmm_LoadAccelerators
+- ::kmm_LoadBitmap
+- ::kmm_LoadCursor
+- ::kmm_LoadIcon
+- ::kmm_LoadImage
+- ::kmm_LoadMenu
+- ::kmm_LoadString
+
+*/
+
+
diff --git a/src/windows/identity/doc/plugin_main.h b/src/windows/identity/doc/plugin_main.h
index 70040b2853..9542150a82 100644
--- a/src/windows/identity/doc/plugin_main.h
+++ b/src/windows/identity/doc/plugin_main.h
@@ -1,115 +1,115 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- * Copyright (c) 2007 Secure Endpoints Inc.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-/*!
-
-\page plug-ins Network Identity Manager Modules and Plug-ins
-
- The Network Identity Manager application does not include any
- ability to manage any specific type of credential. Instead it
- exposes a framework on which plug-ins can be implemented to manage
- credentials.
-
- Plug-ins and localization are handled by the Network Identity
- Manager Module Manager API.
-
- The following sections describe plug-ins in detail:
-
- - \subpage pi_framework
- - \subpage pi_pt
- - \subpage pi_structure
- - \subpage pi_localization
-*/
-
-/*! \page pi_pt Plug-in Types
-
-The types of plug-ins that are currently supported by Network Identity
-Manager are :
-
-\section pi_pt_cred Credential Provider
-
-A credential provider plug-in essentially acts as an interface between
-Network Identity Manager and some entity which defines the credentials
-for the purpose of managing those credentials.
-
-There can be more than one credential provider in a module.
-
-\subsection pi_pt_cred_comm Communication
-
-Communication between Network Identity Manager and a credential
-provider occurs through a message processor. When registering a
-credential provider, the module initialization code in init_module()
-specifies ::KHM_PITYPE_CRED as the \a type member and sets \a msg_proc
-member to a valid message processor in the ::khm_plugin record.
-
-\subsection pi_pt_cred_init Initialization
-
-Once init_module() has completed, the module manager sends a
-<::KMSG_SYSTEM,::KMSG_SYSTEM_INIT> message to the message processor.
-
-For credential provider plug-ins, <::KMSG_SYSTEM,::KMSG_SYSTEM_INIT> is
-guaranteed to be the first message it receives.
-
-The callback function should return KHM_ERROR_SUCCESS if it
-initializes properly or some other value otherwise. If the return
-value signals an error, then the plug-in is assumed to have failed
-initialization and is immediately unloaded.
-
-The message processor is automatically subscribed to the following
-message types:
-- ::KMSG_SYSTEM
-- ::KMSG_KCDB
-
-Although a plug-in can use the <::KMSG_SYSTEM,::KMSG_SYSTEM_INIT>
-message enumerate existing credentials in the system, it should not
-obtain new credentials. This is because other plug-ins that may depend
-on the new credential messages may not be loaded at this time. See the
-section on \ref cred_msgs for more information.
-
-\subsection pi_pt_cred_exit Uninitialization
-
-When the plug-in is to be removed, the module manager sends a
-<::KMSG_SYSTEM,::KMSG_SYSTEM_EXIT> to the message processor. The
-plug-in must perform any necessary shutdown operations, free up
-resources and unsubscribe from any messages that it has subscribed to.
-
-This message is guaranteed to be the last message received by a
-credentials manager plug-in if the plug-in unsubsribes from all
-additional message classes that it subsribed to.
-
-The message types that the message processor is automatically
-subscribed to (See \ref pi_pt_cred_init) do not have to be
-unsubscribed from as they are automatically removed.
-
-\subsection pi_pt_cred_other Other Notes
-
-Since credential managers may receive privileged information, the
-signature requirements for credential managers are specially strict.
-
-*/
-
-
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ * Copyright (c) 2007 Secure Endpoints Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+/*!
+
+\page plug-ins Network Identity Manager Modules and Plug-ins
+
+ The Network Identity Manager application does not include any
+ ability to manage any specific type of credential. Instead it
+ exposes a framework on which plug-ins can be implemented to manage
+ credentials.
+
+ Plug-ins and localization are handled by the Network Identity
+ Manager Module Manager API.
+
+ The following sections describe plug-ins in detail:
+
+ - \subpage pi_framework
+ - \subpage pi_pt
+ - \subpage pi_structure
+ - \subpage pi_localization
+*/
+
+/*! \page pi_pt Plug-in Types
+
+The types of plug-ins that are currently supported by Network Identity
+Manager are :
+
+\section pi_pt_cred Credential Provider
+
+A credential provider plug-in essentially acts as an interface between
+Network Identity Manager and some entity which defines the credentials
+for the purpose of managing those credentials.
+
+There can be more than one credential provider in a module.
+
+\subsection pi_pt_cred_comm Communication
+
+Communication between Network Identity Manager and a credential
+provider occurs through a message processor. When registering a
+credential provider, the module initialization code in init_module()
+specifies ::KHM_PITYPE_CRED as the \a type member and sets \a msg_proc
+member to a valid message processor in the ::khm_plugin record.
+
+\subsection pi_pt_cred_init Initialization
+
+Once init_module() has completed, the module manager sends a
+<::KMSG_SYSTEM,::KMSG_SYSTEM_INIT> message to the message processor.
+
+For credential provider plug-ins, <::KMSG_SYSTEM,::KMSG_SYSTEM_INIT> is
+guaranteed to be the first message it receives.
+
+The callback function should return KHM_ERROR_SUCCESS if it
+initializes properly or some other value otherwise. If the return
+value signals an error, then the plug-in is assumed to have failed
+initialization and is immediately unloaded.
+
+The message processor is automatically subscribed to the following
+message types:
+- ::KMSG_SYSTEM
+- ::KMSG_KCDB
+
+Although a plug-in can use the <::KMSG_SYSTEM,::KMSG_SYSTEM_INIT>
+message enumerate existing credentials in the system, it should not
+obtain new credentials. This is because other plug-ins that may depend
+on the new credential messages may not be loaded at this time. See the
+section on \ref cred_msgs for more information.
+
+\subsection pi_pt_cred_exit Uninitialization
+
+When the plug-in is to be removed, the module manager sends a
+<::KMSG_SYSTEM,::KMSG_SYSTEM_EXIT> to the message processor. The
+plug-in must perform any necessary shutdown operations, free up
+resources and unsubscribe from any messages that it has subscribed to.
+
+This message is guaranteed to be the last message received by a
+credentials manager plug-in if the plug-in unsubsribes from all
+additional message classes that it subsribed to.
+
+The message types that the message processor is automatically
+subscribed to (See \ref pi_pt_cred_init) do not have to be
+unsubscribed from as they are automatically removed.
+
+\subsection pi_pt_cred_other Other Notes
+
+Since credential managers may receive privileged information, the
+signature requirements for credential managers are specially strict.
+
+*/
+
+
diff --git a/src/windows/identity/doc/plugin_structure.h b/src/windows/identity/doc/plugin_structure.h
index 452029e4f1..68cee13e73 100644
--- a/src/windows/identity/doc/plugin_structure.h
+++ b/src/windows/identity/doc/plugin_structure.h
@@ -1,55 +1,55 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- * Copyright (c) 2007 Secure Endpoints Inc.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-/*!
-
-\page pi_structure Structure of a module
-
-A Network Identity Manager module is a dynamically loadable library
-with a specific set of exported symbols. Each export symbol and
-general notes about writing a plug-in module are documented below.
-
-\section pi_str_reg Registration and Version Information
-
-[TODO]
-
-\section pi_str_init Initialization
-
-Do not use DllMain or other system specific callback routines to
-perform intilization tasks other than creating mutexes, initializing
-thread local storage and other tasks that must be performed at that
-stage. Specifically, do not call any Network Identity Manager API functions from
-within DllMain.
-
-\section pi_str_cb Callbacks
-
-The callbacks that must be implemented by a module are:
-
-- init_module()
-- exit_module()
-
- */
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ * Copyright (c) 2007 Secure Endpoints Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+/*!
+
+\page pi_structure Structure of a module
+
+A Network Identity Manager module is a dynamically loadable library
+with a specific set of exported symbols. Each export symbol and
+general notes about writing a plug-in module are documented below.
+
+\section pi_str_reg Registration and Version Information
+
+[TODO]
+
+\section pi_str_init Initialization
+
+Do not use DllMain or other system specific callback routines to
+perform intilization tasks other than creating mutexes, initializing
+thread local storage and other tasks that must be performed at that
+stage. Specifically, do not call any Network Identity Manager API functions from
+within DllMain.
+
+\section pi_str_cb Callbacks
+
+The callbacks that must be implemented by a module are:
+
+- init_module()
+- exit_module()
+
+ */
diff --git a/src/windows/identity/doc/ui_actions.h b/src/windows/identity/doc/ui_actions.h
index 43bf3a94fb..04f9aa6f24 100644
--- a/src/windows/identity/doc/ui_actions.h
+++ b/src/windows/identity/doc/ui_actions.h
@@ -1,30 +1,30 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- * Copyright (c) 2007 Secure Endpoints Inc.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-/*! \page khui_actions Actions
-
- */
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ * Copyright (c) 2007 Secure Endpoints Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+/*! \page khui_actions Actions
+
+ */
diff --git a/src/windows/identity/doc/ui_context.h b/src/windows/identity/doc/ui_context.h
index 12843fb46a..9799b5c4a0 100644
--- a/src/windows/identity/doc/ui_context.h
+++ b/src/windows/identity/doc/ui_context.h
@@ -1,188 +1,188 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- * Copyright (c) 2007 Secure Endpoints Inc.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-/*! \page khui_context Contexts
-
- \section khui_context_contents Contents
-
- - \ref khui_context_intro "Introduction"
- - \subpage khui_context_using
-
- \section khui_context_intro Introduction
-
- Several ::KMSG_CRED messages and many messages depend on the
- selections that the user has made on the user interface. The UI
- context functions and data structures provide access to this
- information.
-
- The Network Identity Manager user interface presents an outline view of all the
- credentials that were provided by credentials providers. This
- view consists of headers representing the outline levels and rows
- representing individual credentials.
-
- Users can make multiple selections of credentials or headers from
- this view. If all the credentials and subheaders under a
- particular outline level are selected, then the header itself is
- automatically selected. There may be multiple disjointed
- selections of headers and credentials.
-
- In addition, the current cursor position also acts as a selector.
- The credential or header under the cursor may not actually be
- selected. The cursor is not the mouse pointer, but the focus
- rectangle that may be moved either using the keyboard or by
- clicking on a credential or header.
-
- Thus there are two independent groups of selections:
-
- - Credentials and headers which are in a selected state at some
- specific point in time (the <b>current selection</b>).
-
- - The current credential or selection which the cursor is on (the
- <b>cursor selection</b>).
-
- There are a few notes on how credentials are selected:
-
- - An "empty" header (a header that does not contain any credential
- rows) does not appear in a UI context. However they can appear
- as the current cursor context.
-
- - At its current implementation, cursor selections of identity,
- credential type, and individual credentials are treated as
- special cases since they are the most common.
-
- How the UI context is used when processing a specific action or
- message depends on the action or message. If an action operates
- on a group of credentials, then the current selection may be used,
- and on the other hand if an action or message relates to just one
- credential, identity or credential type is invoked, then the
- cursor selection is invoked.
-
- For example, double-clicking a credential, or right clicking and
- selecting 'Properties' from the context menu launches the property
- window for a credential. This operates on the cursor selection
- since that reflects where the user double clicked. However,
- choosing 'Destroy' from the context menu invokes a command that
- can be applied to a group of credential, and hence uses the
- current selection.
-
- Next: \ref khui_context_using "Using Contexts"
- */
-
-/*! \page khui_context_using Using Contexts
-
- \section khui_context_using_1 Obtaining the context
-
- Typically, messages sent by actions that rely on UI context will
- obtain and store the context in a location that is accessible to
- the handlers of the message.
-
- If a plug-in needs to obtain the UI context, it should do so by
- calling khui_context_get() and passing in a pointer to a
- ::khui_action_context structure.
-
- Once obtained, the contents of the ::khui_action_context structure
- should be considered read-only. When the plug-in is done with the
- structure, it should call ::khui_context_release(). This cleans
- up any additional memory allocated for storing the context as well
- as releasing all the objects that were referenced from the
- context.
-
- \section khui_context_sel_ctx Selection context
-
- The selection context is specified in the ::khui_action_context
- structure in the \a sel_creds and \a n_sel_creds fields. These
- combined provide an array of handles to credentials which are
- selected.
-
- \note If \a n_sel_creds is zero, then \a sel_creds may be NULL.
-
- \section khui_context_cur_ctx Cursor context
-
- The scope of the cursor context is specified in the \a scope field
- of the ::khui_action_context strucutre. The scope can be one of:
-
- - ::KHUI_SCOPE_NONE
- - ::KHUI_SCOPE_IDENT
- - ::KHUI_SCOPE_CREDTYPE
- - ::KHUI_SCOPE_GROUP
- - ::KHUI_SCOPE_CRED
-
- Depending on the scope, several other members of the strucre may
- also be set.
-
- In general, the cursor context can be a single credential or an
- entire outline level. Unlike the selection context, since this
- specifies a single point of selection it can not be disjointed.
-
- The contents of the \a identity, \a cred_type, \a cred, \a headers
- and \a n_headers are described in the documentation of each of the
- scope values above.
-
- \subsection khui_context_sel_ctx_grp KHUI_SCOPE_GROUP
-
- The ::KHUI_SCOPE_GROUP scope is the generic scope which describes
- a cursor selection that can not be simplified into any other
- scope.
-
- In this case, the selection is described by an array of
- ::khui_header elements each of which specify a criterion for
- narrowing down the selection of credentials. The ::khui_header
- structure specifies an attribute in the \a attr_id field and a
- value in the \a data and \a cb_data fields. The credentials that
- are selected are those in the root credential set whose repective
- attributes contain the values specified in each of the
- ::khui_header elements.
-
- For example, the following selection:
-
- \image html credview-select-outline.jpg
-
- will result in the following header specification:
-
- \code
- ctx.n_headers = 3;
-
- ctx.headers[0].attr_id = KCDB_ATTR_LOCATION;
- ctx.headers[0].data = L"grailauth@KHMTEST";
- ctx.headers[0].cb_data = sizeof(L"grailauth@KHMTEST");
-
- ctx.headers[1].attr_id = KCDB_ATTR_ID;
- ctx.headers[1].data = &handle_to_identity;
- ctx.headers[1].cb_data = sizeof(khm_handle);
-
- ctx.headers[2].attr_id = KCDB_ATTR_TYPE;
- ctx.headers[2].data = &kerberos_5_credtype;
- ctx.headers[2].cb_data = sizeof(khm_int32);
- \endcode
-
- \note The attribute that is used to specify the header is not the
- display attribute, but the canonical attribute. For example,
- in the above, the second header was actually
- KCDB_ATTR_ID_NAME. But KCDB_ATTR_ID was used since that is
- the canonical source for KCDB_ATTR_ID_NAME. See ::kcdb_attrib
- for more information on canonical attributes.
-*/
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ * Copyright (c) 2007 Secure Endpoints Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+/*! \page khui_context Contexts
+
+ \section khui_context_contents Contents
+
+ - \ref khui_context_intro "Introduction"
+ - \subpage khui_context_using
+
+ \section khui_context_intro Introduction
+
+ Several ::KMSG_CRED messages and many messages depend on the
+ selections that the user has made on the user interface. The UI
+ context functions and data structures provide access to this
+ information.
+
+ The Network Identity Manager user interface presents an outline view of all the
+ credentials that were provided by credentials providers. This
+ view consists of headers representing the outline levels and rows
+ representing individual credentials.
+
+ Users can make multiple selections of credentials or headers from
+ this view. If all the credentials and subheaders under a
+ particular outline level are selected, then the header itself is
+ automatically selected. There may be multiple disjointed
+ selections of headers and credentials.
+
+ In addition, the current cursor position also acts as a selector.
+ The credential or header under the cursor may not actually be
+ selected. The cursor is not the mouse pointer, but the focus
+ rectangle that may be moved either using the keyboard or by
+ clicking on a credential or header.
+
+ Thus there are two independent groups of selections:
+
+ - Credentials and headers which are in a selected state at some
+ specific point in time (the <b>current selection</b>).
+
+ - The current credential or selection which the cursor is on (the
+ <b>cursor selection</b>).
+
+ There are a few notes on how credentials are selected:
+
+ - An "empty" header (a header that does not contain any credential
+ rows) does not appear in a UI context. However they can appear
+ as the current cursor context.
+
+ - At its current implementation, cursor selections of identity,
+ credential type, and individual credentials are treated as
+ special cases since they are the most common.
+
+ How the UI context is used when processing a specific action or
+ message depends on the action or message. If an action operates
+ on a group of credentials, then the current selection may be used,
+ and on the other hand if an action or message relates to just one
+ credential, identity or credential type is invoked, then the
+ cursor selection is invoked.
+
+ For example, double-clicking a credential, or right clicking and
+ selecting 'Properties' from the context menu launches the property
+ window for a credential. This operates on the cursor selection
+ since that reflects where the user double clicked. However,
+ choosing 'Destroy' from the context menu invokes a command that
+ can be applied to a group of credential, and hence uses the
+ current selection.
+
+ Next: \ref khui_context_using "Using Contexts"
+ */
+
+/*! \page khui_context_using Using Contexts
+
+ \section khui_context_using_1 Obtaining the context
+
+ Typically, messages sent by actions that rely on UI context will
+ obtain and store the context in a location that is accessible to
+ the handlers of the message.
+
+ If a plug-in needs to obtain the UI context, it should do so by
+ calling khui_context_get() and passing in a pointer to a
+ ::khui_action_context structure.
+
+ Once obtained, the contents of the ::khui_action_context structure
+ should be considered read-only. When the plug-in is done with the
+ structure, it should call ::khui_context_release(). This cleans
+ up any additional memory allocated for storing the context as well
+ as releasing all the objects that were referenced from the
+ context.
+
+ \section khui_context_sel_ctx Selection context
+
+ The selection context is specified in the ::khui_action_context
+ structure in the \a sel_creds and \a n_sel_creds fields. These
+ combined provide an array of handles to credentials which are
+ selected.
+
+ \note If \a n_sel_creds is zero, then \a sel_creds may be NULL.
+
+ \section khui_context_cur_ctx Cursor context
+
+ The scope of the cursor context is specified in the \a scope field
+ of the ::khui_action_context strucutre. The scope can be one of:
+
+ - ::KHUI_SCOPE_NONE
+ - ::KHUI_SCOPE_IDENT
+ - ::KHUI_SCOPE_CREDTYPE
+ - ::KHUI_SCOPE_GROUP
+ - ::KHUI_SCOPE_CRED
+
+ Depending on the scope, several other members of the strucre may
+ also be set.
+
+ In general, the cursor context can be a single credential or an
+ entire outline level. Unlike the selection context, since this
+ specifies a single point of selection it can not be disjointed.
+
+ The contents of the \a identity, \a cred_type, \a cred, \a headers
+ and \a n_headers are described in the documentation of each of the
+ scope values above.
+
+ \subsection khui_context_sel_ctx_grp KHUI_SCOPE_GROUP
+
+ The ::KHUI_SCOPE_GROUP scope is the generic scope which describes
+ a cursor selection that can not be simplified into any other
+ scope.
+
+ In this case, the selection is described by an array of
+ ::khui_header elements each of which specify a criterion for
+ narrowing down the selection of credentials. The ::khui_header
+ structure specifies an attribute in the \a attr_id field and a
+ value in the \a data and \a cb_data fields. The credentials that
+ are selected are those in the root credential set whose repective
+ attributes contain the values specified in each of the
+ ::khui_header elements.
+
+ For example, the following selection:
+
+ \image html credview-select-outline.jpg
+
+ will result in the following header specification:
+
+ \code
+ ctx.n_headers = 3;
+
+ ctx.headers[0].attr_id = KCDB_ATTR_LOCATION;
+ ctx.headers[0].data = L"grailauth@KHMTEST";
+ ctx.headers[0].cb_data = sizeof(L"grailauth@KHMTEST");
+
+ ctx.headers[1].attr_id = KCDB_ATTR_ID;
+ ctx.headers[1].data = &handle_to_identity;
+ ctx.headers[1].cb_data = sizeof(khm_handle);
+
+ ctx.headers[2].attr_id = KCDB_ATTR_TYPE;
+ ctx.headers[2].data = &kerberos_5_credtype;
+ ctx.headers[2].cb_data = sizeof(khm_int32);
+ \endcode
+
+ \note The attribute that is used to specify the header is not the
+ display attribute, but the canonical attribute. For example,
+ in the above, the second header was actually
+ KCDB_ATTR_ID_NAME. But KCDB_ATTR_ID was used since that is
+ the canonical source for KCDB_ATTR_ID_NAME. See ::kcdb_attrib
+ for more information on canonical attributes.
+*/
diff --git a/src/windows/identity/doc/ui_main.h b/src/windows/identity/doc/ui_main.h
index d7bc6be00f..ae67008470 100644
--- a/src/windows/identity/doc/ui_main.h
+++ b/src/windows/identity/doc/ui_main.h
@@ -1,36 +1,36 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- * Copyright (c) 2007 Secure Endpoints Inc.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-/*! \page khui User Interface Topics
-
- \section khui_contents Contents
-
- - \subpage khui_actions
- - \subpage khui_menus
- - \subpage khui_context
- - \subpage khui_htwnd
- */
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ * Copyright (c) 2007 Secure Endpoints Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+/*! \page khui User Interface Topics
+
+ \section khui_contents Contents
+
+ - \subpage khui_actions
+ - \subpage khui_menus
+ - \subpage khui_context
+ - \subpage khui_htwnd
+ */
diff --git a/src/windows/identity/doc/ui_menus.h b/src/windows/identity/doc/ui_menus.h
index 794aef6ca4..e46ee08408 100644
--- a/src/windows/identity/doc/ui_menus.h
+++ b/src/windows/identity/doc/ui_menus.h
@@ -1,30 +1,30 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- * Copyright (c) 2007 Secure Endpoints Inc.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-/*! \page khui_menus Menus
-
- */
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ * Copyright (c) 2007 Secure Endpoints Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+/*! \page khui_menus Menus
+
+ */
diff --git a/src/windows/identity/help/khhelp.h b/src/windows/identity/help/khhelp.h
index fbfef6047b..f6fbd3f784 100644
--- a/src/windows/identity/help/khhelp.h
+++ b/src/windows/identity/help/khhelp.h
@@ -1,33 +1,33 @@
-#define IDH_WELCOME 1000
-#define IDH_WIN_MAIN 1001
-
-#define IDH_MENU_FILE 1501
-#define IDH_MENU_CRED 1502
-#define IDH_MENU_VIEW 1503
-#define IDH_MENU_OPTIONS 1504
-#define IDH_MENU_HELP 1505
-
-#define IDH_ACTION_PROPERTIES 2000
-#define IDH_ACTION_EXIT 2001
-#define IDH_ACTION_NEW_ID 2002
-#define IDH_ACTION_SET_DEF_ID 2003
-#define IDH_ACTION_SET_SRCH_ID 2004
-#define IDH_ACTION_DESTROY_ID 2005
-#define IDH_ACTION_RENEW_ID 2006
-#define IDH_ACTION_PASSWD_ID 2007
-#define IDH_ACTION_NEW_CRED 2008
-#define IDH_ACTION_CHOOSE_COLS 2009
-#define IDH_ACTION_DEBUG_WINDOW 2010
-#define IDH_ACTION_VIEW_REFRESH 2011
-#define IDH_ACTION_OPT_KHIM 2012
-#define IDH_ACTION_OPT_INIT 2013
-#define IDH_ACTION_OPT_NOTIF 2014
-
-#define IDH_NC_CREDWND 3000
-#define IDH_NC_OK 3001
-#define IDH_NC_CANCEL 3002
-#define IDH_NC_HELP 3003
-#define IDH_NC_TABBUTTON 3004
-#define IDH_NC_ADVANCED 3005
-#define IDH_NC_TABMAIN 3006
-#define IDH_NC_SETDEF 3007
+#define IDH_WELCOME 1000
+#define IDH_WIN_MAIN 1001
+
+#define IDH_MENU_FILE 1501
+#define IDH_MENU_CRED 1502
+#define IDH_MENU_VIEW 1503
+#define IDH_MENU_OPTIONS 1504
+#define IDH_MENU_HELP 1505
+
+#define IDH_ACTION_PROPERTIES 2000
+#define IDH_ACTION_EXIT 2001
+#define IDH_ACTION_NEW_ID 2002
+#define IDH_ACTION_SET_DEF_ID 2003
+#define IDH_ACTION_SET_SRCH_ID 2004
+#define IDH_ACTION_DESTROY_ID 2005
+#define IDH_ACTION_RENEW_ID 2006
+#define IDH_ACTION_PASSWD_ID 2007
+#define IDH_ACTION_NEW_CRED 2008
+#define IDH_ACTION_CHOOSE_COLS 2009
+#define IDH_ACTION_DEBUG_WINDOW 2010
+#define IDH_ACTION_VIEW_REFRESH 2011
+#define IDH_ACTION_OPT_KHIM 2012
+#define IDH_ACTION_OPT_INIT 2013
+#define IDH_ACTION_OPT_NOTIF 2014
+
+#define IDH_NC_CREDWND 3000
+#define IDH_NC_OK 3001
+#define IDH_NC_CANCEL 3002
+#define IDH_NC_HELP 3003
+#define IDH_NC_TABBUTTON 3004
+#define IDH_NC_ADVANCED 3005
+#define IDH_NC_TABMAIN 3006
+#define IDH_NC_SETDEF 3007
diff --git a/src/windows/identity/include/khdefs.h b/src/windows/identity/include/khdefs.h
index 6b81f4ca07..0d32356f69 100644
--- a/src/windows/identity/include/khdefs.h
+++ b/src/windows/identity/include/khdefs.h
@@ -1,238 +1,238 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#ifndef __KHIMAIRA_KHDEFS_H__
-#define __KHIMAIRA_KHDEFS_H__
-
-/*! \defgroup khdef Core definitions
-
- Key type definitions used throughout NetIDMgr.
- */
-/*@{*/
-#include<stddef.h>
-#include<limits.h>
-#include<wchar.h>
-
-/*!\typedef khm_octet
- \brief A byte (8 bit unsigned)*/
-
-/*!\typedef khm_int16
- \brief A signed 16 bit quantity */
-
-/*!\typedef khm_ui_2
- \brief An unsigned 16 bit quantity */
-
-/*!\typedef khm_int32
- \brief A signed 32 bit quantity */
-
-/*!\typedef khm_ui_4
- \brief An unsigned 32 bit quantity */
-
-/*!\typedef khm_int64
- \brief A signed 64 bit quantity */
-
-/*!\typedef khm_ui_8
- \brief An unsigned 64 bit quantity */
-
-typedef unsigned __int8 khm_octet;
-
-typedef __int16 khm_int16;
-typedef unsigned __int16 khm_ui_2;
-
-typedef __int32 khm_int32;
-typedef unsigned __int32 khm_ui_4;
-
-typedef __int64 khm_int64;
-typedef unsigned __int64 khm_ui_8;
-
-#define VALID_INT_BITS INT_MAX
-#define VALID_UINT_BITS UINT_MAX
-
-#define KHM_UINT32_MAX 4294967295
-
-#define KHM_INT32_MAX 2147483647
-/* this strange form is necessary since - is a unary operator, not a sign
- indicator */
-#define KHM_INT32_MIN (-KHM_INT32_MAX-1)
-
-#define KHM_UINT16_MAX 65535
-
-#define KHM_INT16_MAX 32767
-/* this strange form is necessary since - is a unary operator, not a sign
- indicator */
-#define KHM_INT16_MIN (-KHM_INT16_MAX-1)
-
-/*! \brief Generic handle type.
-
- Handles in NetIDMgr are generic pointers.
-*/
-typedef void * khm_handle;
-
-/*! \brief The invalid handle
-
- Just used to indicate that this handle does not point to anything useful.
- Usually returned by a function that returns a handle as a signal that the
- operation failed.
-*/
-#define KHM_INVALID_HANDLE ((khm_handle) NULL)
-
-/*! \brief Boolean.
-*/
-typedef khm_int32 khm_boolean;
-
-/*! \brief A size
- */
-typedef size_t khm_size;
-
-/*! \typedef ssize_t
- \brief Signed size specifier
-
- Just a signed version of size_t
- */
-
-#ifndef _SSIZE_T_DEFINED
-#ifdef _WIN64
-typedef __int64 ssize_t;
-#else
-typedef _W64 int ssize_t;
-#endif
-#define _SSIZE_T_DEFINED
-#endif
-
-typedef ssize_t khm_ssize;
-
-#if defined(_WIN64)
-typedef unsigned __int64 khm_wparm;
-/*TODO: is this enough? */
-typedef unsigned __int64 khm_lparm;
-#elif defined(_WIN32)
-typedef unsigned __int32 khm_wparm;
-typedef unsigned __int64 khm_lparm;
-#else
-#error khm_wparm and khm_lparm need to be defined for this platform
-#endif
-
-/*!\def KHMAPI
- \brief Calling convention for NetIDMgr exported functions
-
- The caling convention for all NetIDMgr exported functions is \b
- __stdcall , unless otherwise noted.
- */
-
-/*!\def KHMEXP
- \brief Export prefix for NetIDMgr exported functions
-
- When compiling source that exports functions, those exported
- function declarations will be done as follows:
-
- \code
- __declspec(dllexport) khm_int32 __stdcall function_name(arguments...);
- \endcode
-
- This eliminates the need for a separate exports definition file.
- However, it doesn't preserve ordinals, but we aren't guaranteeing
- that anyway.
-
- On the other hand, if a particular function is going to be imported
- from a DLL, it should declared as follows:
-
- \code
- __declspec(dllimport) khm_int32 __stdcall function_name(arguments...);
- \endcode
-
- This allows the compiler to properly instrument the import. If the
- function is not declared this way, there will be a stub function
- generated that will just jump to the proper import, generating
- redundant instructions and wasting execution time.
-
- This macro encapsulates the proper declaration specifier.
- */
-
-#ifdef _WIN32
-#define KHMAPI __stdcall
-
-#define KHMEXP_EXP __declspec(dllexport)
-#define KHMEXP_IMP __declspec(dllimport)
-
-#define KHMEXP KHMEXP_EXP
-#endif
-
-/* Generic permission values */
-/*! \brief Generic read permission or request */
-#define KHM_PERM_READ 0x100
-
-/*! \brief Generic write permission or request */
-#define KHM_PERM_WRITE 0x200
-
-/* Generic flags */
-/*! \brief Generic create request
-
- For most lookup functions, specifying this flag indicates that if
- the requested object is not found it should be created.
-*/
-#define KHM_FLAG_CREATE 0x1000
-
-/*! \brief Wrap to DWORD boundary
-
- Returns the smallest integer greater than or equal to the
- parameter that is a multiple of 4.
-
- \note Only use with positive integers. */
-#define UBOUND32(d) ((((d)-1)&~3) + 4)
-
-/*! \brief Offset a pointer by a number of bytes
-
- Given a pointer, returns a void pointer that is a given number of
- bytes offset from the pointer.
- */
-#define BYTEOFFSET(p,off) ((void *)(((char *) (p)) + (off)))
-
-/*! \brief Check for powers of 2
-
- Return TRUE if the operand is a positive power of 2 or 0*/
-#define IS_POW2(d) ((d)>=0 && !((d) & ((d) - 1)))
-
-/*! \brief Wrap to upper bound based on start and step size
-
- Return the smallest element in the series <tt>s, s+t, s+2*t,
- s+3*t, ...</tt> that is greater than or equal to \c v.
-*/
-#define UBOUNDSS(v,start,step) (((v)<=(start))?(start):(start)+((((v)-((start)+1))/(step))+1)*(step))
-
-/* \brief Length of an array
-*/
-#define ARRAYLENGTH(x) (sizeof(x)/sizeof(x[0]))
-
-/*! \brief Generic version type*/
-typedef struct tag_khm_version {
- khm_ui_2 major; /*!< Major version number */
- khm_ui_2 minor; /*!< Minor version number */
- khm_ui_2 patch; /*!< Patch level */
- khm_ui_2 aux; /*!< Auxilary level (usually carries a build number) */
-} khm_version;
-
-/*@}*/
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __KHIMAIRA_KHDEFS_H__
+#define __KHIMAIRA_KHDEFS_H__
+
+/*! \defgroup khdef Core definitions
+
+ Key type definitions used throughout NetIDMgr.
+ */
+/*@{*/
+#include<stddef.h>
+#include<limits.h>
+#include<wchar.h>
+
+/*!\typedef khm_octet
+ \brief A byte (8 bit unsigned)*/
+
+/*!\typedef khm_int16
+ \brief A signed 16 bit quantity */
+
+/*!\typedef khm_ui_2
+ \brief An unsigned 16 bit quantity */
+
+/*!\typedef khm_int32
+ \brief A signed 32 bit quantity */
+
+/*!\typedef khm_ui_4
+ \brief An unsigned 32 bit quantity */
+
+/*!\typedef khm_int64
+ \brief A signed 64 bit quantity */
+
+/*!\typedef khm_ui_8
+ \brief An unsigned 64 bit quantity */
+
+typedef unsigned __int8 khm_octet;
+
+typedef __int16 khm_int16;
+typedef unsigned __int16 khm_ui_2;
+
+typedef __int32 khm_int32;
+typedef unsigned __int32 khm_ui_4;
+
+typedef __int64 khm_int64;
+typedef unsigned __int64 khm_ui_8;
+
+#define VALID_INT_BITS INT_MAX
+#define VALID_UINT_BITS UINT_MAX
+
+#define KHM_UINT32_MAX 4294967295
+
+#define KHM_INT32_MAX 2147483647
+/* this strange form is necessary since - is a unary operator, not a sign
+ indicator */
+#define KHM_INT32_MIN (-KHM_INT32_MAX-1)
+
+#define KHM_UINT16_MAX 65535
+
+#define KHM_INT16_MAX 32767
+/* this strange form is necessary since - is a unary operator, not a sign
+ indicator */
+#define KHM_INT16_MIN (-KHM_INT16_MAX-1)
+
+/*! \brief Generic handle type.
+
+ Handles in NetIDMgr are generic pointers.
+*/
+typedef void * khm_handle;
+
+/*! \brief The invalid handle
+
+ Just used to indicate that this handle does not point to anything useful.
+ Usually returned by a function that returns a handle as a signal that the
+ operation failed.
+*/
+#define KHM_INVALID_HANDLE ((khm_handle) NULL)
+
+/*! \brief Boolean.
+*/
+typedef khm_int32 khm_boolean;
+
+/*! \brief A size
+ */
+typedef size_t khm_size;
+
+/*! \typedef ssize_t
+ \brief Signed size specifier
+
+ Just a signed version of size_t
+ */
+
+#ifndef _SSIZE_T_DEFINED
+#ifdef _WIN64
+typedef __int64 ssize_t;
+#else
+typedef _W64 int ssize_t;
+#endif
+#define _SSIZE_T_DEFINED
+#endif
+
+typedef ssize_t khm_ssize;
+
+#if defined(_WIN64)
+typedef unsigned __int64 khm_wparm;
+/*TODO: is this enough? */
+typedef unsigned __int64 khm_lparm;
+#elif defined(_WIN32)
+typedef unsigned __int32 khm_wparm;
+typedef unsigned __int64 khm_lparm;
+#else
+#error khm_wparm and khm_lparm need to be defined for this platform
+#endif
+
+/*!\def KHMAPI
+ \brief Calling convention for NetIDMgr exported functions
+
+ The caling convention for all NetIDMgr exported functions is \b
+ __stdcall , unless otherwise noted.
+ */
+
+/*!\def KHMEXP
+ \brief Export prefix for NetIDMgr exported functions
+
+ When compiling source that exports functions, those exported
+ function declarations will be done as follows:
+
+ \code
+ __declspec(dllexport) khm_int32 __stdcall function_name(arguments...);
+ \endcode
+
+ This eliminates the need for a separate exports definition file.
+ However, it doesn't preserve ordinals, but we aren't guaranteeing
+ that anyway.
+
+ On the other hand, if a particular function is going to be imported
+ from a DLL, it should declared as follows:
+
+ \code
+ __declspec(dllimport) khm_int32 __stdcall function_name(arguments...);
+ \endcode
+
+ This allows the compiler to properly instrument the import. If the
+ function is not declared this way, there will be a stub function
+ generated that will just jump to the proper import, generating
+ redundant instructions and wasting execution time.
+
+ This macro encapsulates the proper declaration specifier.
+ */
+
+#ifdef _WIN32
+#define KHMAPI __stdcall
+
+#define KHMEXP_EXP __declspec(dllexport)
+#define KHMEXP_IMP __declspec(dllimport)
+
+#define KHMEXP KHMEXP_EXP
+#endif
+
+/* Generic permission values */
+/*! \brief Generic read permission or request */
+#define KHM_PERM_READ 0x100
+
+/*! \brief Generic write permission or request */
+#define KHM_PERM_WRITE 0x200
+
+/* Generic flags */
+/*! \brief Generic create request
+
+ For most lookup functions, specifying this flag indicates that if
+ the requested object is not found it should be created.
+*/
+#define KHM_FLAG_CREATE 0x1000
+
+/*! \brief Wrap to DWORD boundary
+
+ Returns the smallest integer greater than or equal to the
+ parameter that is a multiple of 4.
+
+ \note Only use with positive integers. */
+#define UBOUND32(d) ((((d)-1)&~3) + 4)
+
+/*! \brief Offset a pointer by a number of bytes
+
+ Given a pointer, returns a void pointer that is a given number of
+ bytes offset from the pointer.
+ */
+#define BYTEOFFSET(p,off) ((void *)(((char *) (p)) + (off)))
+
+/*! \brief Check for powers of 2
+
+ Return TRUE if the operand is a positive power of 2 or 0*/
+#define IS_POW2(d) ((d)>=0 && !((d) & ((d) - 1)))
+
+/*! \brief Wrap to upper bound based on start and step size
+
+ Return the smallest element in the series <tt>s, s+t, s+2*t,
+ s+3*t, ...</tt> that is greater than or equal to \c v.
+*/
+#define UBOUNDSS(v,start,step) (((v)<=(start))?(start):(start)+((((v)-((start)+1))/(step))+1)*(step))
+
+/* \brief Length of an array
+*/
+#define ARRAYLENGTH(x) (sizeof(x)/sizeof(x[0]))
+
+/*! \brief Generic version type*/
+typedef struct tag_khm_version {
+ khm_ui_2 major; /*!< Major version number */
+ khm_ui_2 minor; /*!< Minor version number */
+ khm_ui_2 patch; /*!< Patch level */
+ khm_ui_2 aux; /*!< Auxilary level (usually carries a build number) */
+} khm_version;
+
+/*@}*/
+#endif
diff --git a/src/windows/identity/include/kherror.h b/src/windows/identity/include/kherror.h
index ae381ff56c..a8ee64505f 100644
--- a/src/windows/identity/include/kherror.h
+++ b/src/windows/identity/include/kherror.h
@@ -1,185 +1,185 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-/* Exported */
-#ifndef __KHIMAIRA_KHERROR_H
-#define __KHIMAIRA_KHERROR_H
-
-/*! \defgroup kherror NetIDMgr errors
-
-@{*/
-/*! \brief Base for error codes
-
- NetIDMgr errors range from \a KHM_ERROR_BASE to KHM_ERROR_BASE +
- KHM_ERROR_RANGE, with the exception of KHM_ERROR_SUCCESS and
- KHM_ERROR_NONE.
- */
-#define KHM_ERROR_BASE 0x40000000L
-
-/*! \brief Range for error codes
-
- NetIDMgr errors range from \a KHM_ERROR_BASE to
- KHM_ERROR_BASE + KHM_ERROR_RANGE.
-*/
-#define KHM_ERROR_RANGE 256L
-
-/*! \defgroup kherror_codes Error codes
- @{*/
-
-/*! \brief No error */
-#define KHM_ERROR_NONE 0x00000000L
-
-/*! \brief Success. Same as \a KHM_ERROR_NONE */
-#define KHM_ERROR_SUCCESS KHM_ERROR_NONE
-
-/*! \brief The supplied name was invalid */
-#define KHM_ERROR_INVALID_NAME (KHM_ERROR_BASE + 1)
-
-/*! \brief Too much data
-
- A supplied buffer was invalid, was of insufficient size, or a
- buffer was of a larger size than expected
- */
-#define KHM_ERROR_TOO_LONG (KHM_ERROR_BASE + 2)
-
-/*! \brief One or more parameters supplied to a function were invalid */
-#define KHM_ERROR_INVALID_PARAM (KHM_ERROR_BASE + 3)
-
-/*! \brief A duplicate.
-
- Usually means that something that should have been unique was
- found to be not.
- */
-#define KHM_ERROR_DUPLICATE (KHM_ERROR_BASE + 4)
-
-/*! \brief An object was not found
-
- An object referenced in a parameter was not found.
- */
-#define KHM_ERROR_NOT_FOUND (KHM_ERROR_BASE + 5)
-
-/*! \brief The relevant subsystem is not ready
-
- Indicates that initialization has not been completed for a
- subsystem.
- */
-#define KHM_ERROR_NOT_READY (KHM_ERROR_BASE + 6)
-
-/*! \brief No more resources
-
- A limited resource has been exhausted.
- */
-#define KHM_ERROR_NO_RESOURCES (KHM_ERROR_BASE + 7)
-
-/*! \brief Type mismatch
- */
-#define KHM_ERROR_TYPE_MISMATCH (KHM_ERROR_BASE + 8)
-
-/*! \brief Already exists
-
- Usually indicates that an exclusive create operation failed due to
- the existence of a similar object. Subtly different from
- ::KHM_ERROR_DUPLICATE
- */
-#define KHM_ERROR_EXISTS (KHM_ERROR_BASE + 9)
-
-/*! \brief Operation timed out
- */
-#define KHM_ERROR_TIMEOUT (KHM_ERROR_BASE + 10)
-
-/*! \brief An EXIT message was received
- */
-#define KHM_ERROR_EXIT (KHM_ERROR_BASE + 11)
-
-/*! \brief Unknown or unspecified error
- */
-#define KHM_ERROR_UNKNOWN (KHM_ERROR_BASE + 12)
-
-/*! \brief General error
- */
-#define KHM_ERROR_GENERAL KHM_ERROR_UNKNOWN
-
-/*! \brief An index was out of bounds
- */
-#define KHM_ERROR_OUT_OF_BOUNDS (KHM_ERROR_BASE + 13)
-
-/*! \brief Object already deleted
-
- One or more objects that were referenced were found to have been
- already deleted.
- */
-#define KHM_ERROR_DELETED (KHM_ERROR_BASE + 14)
-
-/*! \brief Invalid operation
-
- The operation was not permitted to continue for some reason.
- Usually because the necessary conditions for the operation haven't
- been met yet or the operation can only be performed at certain
- times during the execution of NetIDMgr.
- */
-#define KHM_ERROR_INVALID_OPERATION (KHM_ERROR_BASE + 15)
-
-/*! \brief Signature check failed
- */
-#define KHM_ERROR_INVALID_SIGNATURE (KHM_ERROR_BASE + 16)
-
-/*! \brief Not implemented yet
-
- The operation that was attempted involved invoking functionality
- that has not been implemented yet.
- */
-#define KHM_ERROR_NOT_IMPLEMENTED (KHM_ERROR_BASE + 17)
-
-/*! \brief The objects were equivalent
- */
-#define KHM_ERROR_EQUIVALENT (KHM_ERROR_BASE + 18)
-
-/*! \brief No provider exists to service the request
-*/
-#define KHM_ERROR_NO_PROVIDER (KHM_ERROR_BASE + 19)
-
-/*! \brief The operation succeeded, but with errors
-*/
-#define KHM_ERROR_PARTIAL (KHM_ERROR_BASE + 20)
-
-/*! \brief An incompatibility was found */
-#define KHM_ERROR_INCOMPATIBLE (KHM_ERROR_BASE + 21)
-
-/*! \brief The operation was put on hold
-
- A request was put on hold or postponed. */
-#define KHM_ERROR_HELD (KHM_ERROR_BASE + 22)
-
-/*@}*/ /*kherror_codes*/
-
-/*! \brief Tests whether a return value indicates success */
-#define KHM_SUCCEEDED(rv) ((rv)==KHM_ERROR_NONE)
-
-/*! \brief Tests whether a return value indicates failure */
-#define KHM_FAILED(rv) ((rv)!=KHM_ERROR_NONE)
-
-/*@}*/
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+/* Exported */
+#ifndef __KHIMAIRA_KHERROR_H
+#define __KHIMAIRA_KHERROR_H
+
+/*! \defgroup kherror NetIDMgr errors
+
+@{*/
+/*! \brief Base for error codes
+
+ NetIDMgr errors range from \a KHM_ERROR_BASE to KHM_ERROR_BASE +
+ KHM_ERROR_RANGE, with the exception of KHM_ERROR_SUCCESS and
+ KHM_ERROR_NONE.
+ */
+#define KHM_ERROR_BASE 0x40000000L
+
+/*! \brief Range for error codes
+
+ NetIDMgr errors range from \a KHM_ERROR_BASE to
+ KHM_ERROR_BASE + KHM_ERROR_RANGE.
+*/
+#define KHM_ERROR_RANGE 256L
+
+/*! \defgroup kherror_codes Error codes
+ @{*/
+
+/*! \brief No error */
+#define KHM_ERROR_NONE 0x00000000L
+
+/*! \brief Success. Same as \a KHM_ERROR_NONE */
+#define KHM_ERROR_SUCCESS KHM_ERROR_NONE
+
+/*! \brief The supplied name was invalid */
+#define KHM_ERROR_INVALID_NAME (KHM_ERROR_BASE + 1)
+
+/*! \brief Too much data
+
+ A supplied buffer was invalid, was of insufficient size, or a
+ buffer was of a larger size than expected
+ */
+#define KHM_ERROR_TOO_LONG (KHM_ERROR_BASE + 2)
+
+/*! \brief One or more parameters supplied to a function were invalid */
+#define KHM_ERROR_INVALID_PARAM (KHM_ERROR_BASE + 3)
+
+/*! \brief A duplicate.
+
+ Usually means that something that should have been unique was
+ found to be not.
+ */
+#define KHM_ERROR_DUPLICATE (KHM_ERROR_BASE + 4)
+
+/*! \brief An object was not found
+
+ An object referenced in a parameter was not found.
+ */
+#define KHM_ERROR_NOT_FOUND (KHM_ERROR_BASE + 5)
+
+/*! \brief The relevant subsystem is not ready
+
+ Indicates that initialization has not been completed for a
+ subsystem.
+ */
+#define KHM_ERROR_NOT_READY (KHM_ERROR_BASE + 6)
+
+/*! \brief No more resources
+
+ A limited resource has been exhausted.
+ */
+#define KHM_ERROR_NO_RESOURCES (KHM_ERROR_BASE + 7)
+
+/*! \brief Type mismatch
+ */
+#define KHM_ERROR_TYPE_MISMATCH (KHM_ERROR_BASE + 8)
+
+/*! \brief Already exists
+
+ Usually indicates that an exclusive create operation failed due to
+ the existence of a similar object. Subtly different from
+ ::KHM_ERROR_DUPLICATE
+ */
+#define KHM_ERROR_EXISTS (KHM_ERROR_BASE + 9)
+
+/*! \brief Operation timed out
+ */
+#define KHM_ERROR_TIMEOUT (KHM_ERROR_BASE + 10)
+
+/*! \brief An EXIT message was received
+ */
+#define KHM_ERROR_EXIT (KHM_ERROR_BASE + 11)
+
+/*! \brief Unknown or unspecified error
+ */
+#define KHM_ERROR_UNKNOWN (KHM_ERROR_BASE + 12)
+
+/*! \brief General error
+ */
+#define KHM_ERROR_GENERAL KHM_ERROR_UNKNOWN
+
+/*! \brief An index was out of bounds
+ */
+#define KHM_ERROR_OUT_OF_BOUNDS (KHM_ERROR_BASE + 13)
+
+/*! \brief Object already deleted
+
+ One or more objects that were referenced were found to have been
+ already deleted.
+ */
+#define KHM_ERROR_DELETED (KHM_ERROR_BASE + 14)
+
+/*! \brief Invalid operation
+
+ The operation was not permitted to continue for some reason.
+ Usually because the necessary conditions for the operation haven't
+ been met yet or the operation can only be performed at certain
+ times during the execution of NetIDMgr.
+ */
+#define KHM_ERROR_INVALID_OPERATION (KHM_ERROR_BASE + 15)
+
+/*! \brief Signature check failed
+ */
+#define KHM_ERROR_INVALID_SIGNATURE (KHM_ERROR_BASE + 16)
+
+/*! \brief Not implemented yet
+
+ The operation that was attempted involved invoking functionality
+ that has not been implemented yet.
+ */
+#define KHM_ERROR_NOT_IMPLEMENTED (KHM_ERROR_BASE + 17)
+
+/*! \brief The objects were equivalent
+ */
+#define KHM_ERROR_EQUIVALENT (KHM_ERROR_BASE + 18)
+
+/*! \brief No provider exists to service the request
+*/
+#define KHM_ERROR_NO_PROVIDER (KHM_ERROR_BASE + 19)
+
+/*! \brief The operation succeeded, but with errors
+*/
+#define KHM_ERROR_PARTIAL (KHM_ERROR_BASE + 20)
+
+/*! \brief An incompatibility was found */
+#define KHM_ERROR_INCOMPATIBLE (KHM_ERROR_BASE + 21)
+
+/*! \brief The operation was put on hold
+
+ A request was put on hold or postponed. */
+#define KHM_ERROR_HELD (KHM_ERROR_BASE + 22)
+
+/*@}*/ /*kherror_codes*/
+
+/*! \brief Tests whether a return value indicates success */
+#define KHM_SUCCEEDED(rv) ((rv)==KHM_ERROR_NONE)
+
+/*! \brief Tests whether a return value indicates failure */
+#define KHM_FAILED(rv) ((rv)!=KHM_ERROR_NONE)
+
+/*@}*/
+#endif
diff --git a/src/windows/identity/include/khlist.h b/src/windows/identity/include/khlist.h
index 8bf43695b9..ab60ca37d4 100644
--- a/src/windows/identity/include/khlist.h
+++ b/src/windows/identity/include/khlist.h
@@ -1,214 +1,214 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-/* Not exported */
-#ifndef _KHIMAIRA_KHLIST_H
-#define _KHIMAIRA_KHLIST_H
-
-/* Note that most of these are "unsafe" macros. Not for general use */
-
-/* LIFO lists */
-#define LDCL(type) \
- type * next; \
- type * prev
-
-#define LINIT(pe) \
- do { \
- (pe)->next = NULL; \
- (pe)->prev = NULL; } while(0)
-
-#define LPUSH(pph,pe) \
- do { \
- (pe)->next = *pph; \
- (pe)->prev = NULL; \
- if(*(pph)) (*(pph))->prev = (pe); \
- (*(pph)) = (pe); } while(0)
-
-#define LPOP(pph,ppe) \
- do { \
- *(ppe) = *(pph); \
- if(*(pph)) *(pph) = (*(pph))->next; \
- if(*(pph)) (*(pph))->prev = NULL; \
- if(*(ppe)) (*(ppe))->next = NULL; \
- } while(0)
-
-#define LDELETE(pph,pe) \
- do { \
- if((pe)->prev) (pe)->prev->next = (pe)->next; \
- if((pe)->next) (pe)->next->prev = (pe)->prev; \
- if(*(pph) == (pe)) *(pph) = (pe)->next; \
- (pe)->next = (pe)->prev = NULL; \
- } while(0)
-
-#define LEMPTY(pph) (*(pph) == NULL)
-
-#define LNEXT(pe) ((pe)?(pe)->next:NULL)
-
-#define LPREV(pe) ((pe)?(pe)->prev:NULL)
-
-/* Trees with LIFO child lists */
-#define TDCL(type) \
- LDCL(type); \
- type * children; \
- type * parent
-
-#define TINIT(pe) \
- do { \
- (pe)->children = NULL; \
- (pe)->parent = NULL; } while(0)
-
-#define TADDCHILD(pt,pe) \
- do { \
- LPUSH(&((pt)->children),(pe)); \
- (pe)->parent = (pt); } while(0)
-
-#define TFIRSTCHILD(pt) ((pt)?(pt)->children:NULL)
-
-#define TPOPCHILD(pt, ppe) \
- do { \
- LPOP(&((pt)->children), ppe); \
- if(*(ppe)) (*(ppe))->parent = NULL; \
- } while(0)
-
-#define TDELCHILD(pt, pe) \
- do { \
- LDELETE(&((pt)->children), (pe)); \
- (pe)->parent = NULL; } while(0)
-
-#define TPARENT(pe) ((pe)?(pe)->parent:NULL)
-
-/* FIFO lists */
-#define QDCL(type) \
- type * head; \
- type * tail
-
-#define QINIT(pq) \
- do { \
- (pq)->head = (pq)->tail = NULL; \
- } while(0)
-
-#define QPUT(pq, pe) \
- do { \
- LPUSH(&(pq)->tail, (pe)); \
- if(!(pq)->head) (pq)->head = (pe); \
- } while(0)
-
-#define QPUSH(pq, pe) \
- do { \
- (pe)->next = NULL; \
- (pe)->prev = (pq)->head; \
- if((pq)->head) (pq)->head->next = (pe); \
- if(!(pq)->tail) (pq)->tail = (pe); \
- (pq)->head = (pe); \
- } while (0)
-
-#define QGET(pq, ppe) \
- do { \
- *(ppe) = (pq)->head; \
- if(*(ppe)) { \
- (pq)->head = (*(ppe))->prev; \
- if( (*(ppe))->prev ) (*(ppe))->prev->next = NULL; \
- (*(ppe))->prev = NULL; \
- if( (pq)->tail == *(ppe)) (pq)->tail = NULL; \
- } \
- } while(0)
-
-#define QDEL(pq, pe) \
- do { \
- if((pq)->head == (pe)) (pq)->head = LPREV(pe); \
- LDELETE(&((pq)->tail), (pe)); \
- } while(0)
-
-
-#define QGETT(pq,ppe) \
- do { \
- *(ppe) = (pq)->tail; \
- if(*(ppe)) { \
- (pq)->tail = (*(ppe))->next; \
- if( (*(ppe))->next ) (*(ppe))->next->prev = NULL; \
- (*(ppe))->next = NULL; \
- if( (pq)->head == *(ppe)) (pq)->head = NULL; \
- } \
- } while(0)
-
-#define QTOP(pq) ((pq)->head)
-#define QBOTTOM(pq) ((pq)->tail)
-#define QNEXT(pe) ((pe)->prev)
-#define QPREV(pe) ((pe)->next)
-
-#define QINSERT(pt, pre, pe) \
- do { \
- if ((pre) == NULL || \
- QNEXT(pre) == NULL) { QPUT(pt, pe); } \
- else { \
- (pe)->prev = (pre)->prev; \
- (pe)->next = (pre); \
- (pre)->prev->next = (pe); \
- (pre)->prev = (pe); \
- }} while(0)
-
-/* Trees with FIFO child lists */
-#define TQDCL(type) \
- LDCL(type); \
- QDCL(type); \
- type * parent
-
-#define TQINIT(pe) \
- do { \
- LINIT(pe); \
- QINIT(pe); \
- (pe)->parent = NULL; } while(0)
-
-#define TQPUTCHILD(pt,pe) \
- do { \
- QPUT((pt), (pe)); \
- (pe)->parent = (pt); } while(0)
-
-#define TQINSERT(pt, pre, pe) \
- do { \
- QINSERT(pt, pre, pe); \
- (pe)->parent = (pt); } while(0)
-
-#define TQGETCHILD(pt,ppe) \
- do { \
- QGET(pt, ppe); \
- if (*(ppe)) { *(ppe)->parent = NULL; } \
- } while(0)
-
-#define TQDELCHILD(pt, pe) \
- do { \
- QDEL(pt, pe); \
- (pe)->parent = NULL; } while(0)
-
-#define TQFIRSTCHILD(pt) ((pt)?QTOP(pt):NULL)
-
-#define TQNEXTCHILD(pe) QNEXT(pe)
-
-#define TQPREVCHILD(pe) QPREV(pe)
-
-#define TQPARENT(pe) ((pe)?(pe)->parent:NULL)
-
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+/* Not exported */
+#ifndef _KHIMAIRA_KHLIST_H
+#define _KHIMAIRA_KHLIST_H
+
+/* Note that most of these are "unsafe" macros. Not for general use */
+
+/* LIFO lists */
+#define LDCL(type) \
+ type * next; \
+ type * prev
+
+#define LINIT(pe) \
+ do { \
+ (pe)->next = NULL; \
+ (pe)->prev = NULL; } while(0)
+
+#define LPUSH(pph,pe) \
+ do { \
+ (pe)->next = *pph; \
+ (pe)->prev = NULL; \
+ if(*(pph)) (*(pph))->prev = (pe); \
+ (*(pph)) = (pe); } while(0)
+
+#define LPOP(pph,ppe) \
+ do { \
+ *(ppe) = *(pph); \
+ if(*(pph)) *(pph) = (*(pph))->next; \
+ if(*(pph)) (*(pph))->prev = NULL; \
+ if(*(ppe)) (*(ppe))->next = NULL; \
+ } while(0)
+
+#define LDELETE(pph,pe) \
+ do { \
+ if((pe)->prev) (pe)->prev->next = (pe)->next; \
+ if((pe)->next) (pe)->next->prev = (pe)->prev; \
+ if(*(pph) == (pe)) *(pph) = (pe)->next; \
+ (pe)->next = (pe)->prev = NULL; \
+ } while(0)
+
+#define LEMPTY(pph) (*(pph) == NULL)
+
+#define LNEXT(pe) ((pe)?(pe)->next:NULL)
+
+#define LPREV(pe) ((pe)?(pe)->prev:NULL)
+
+/* Trees with LIFO child lists */
+#define TDCL(type) \
+ LDCL(type); \
+ type * children; \
+ type * parent
+
+#define TINIT(pe) \
+ do { \
+ (pe)->children = NULL; \
+ (pe)->parent = NULL; } while(0)
+
+#define TADDCHILD(pt,pe) \
+ do { \
+ LPUSH(&((pt)->children),(pe)); \
+ (pe)->parent = (pt); } while(0)
+
+#define TFIRSTCHILD(pt) ((pt)?(pt)->children:NULL)
+
+#define TPOPCHILD(pt, ppe) \
+ do { \
+ LPOP(&((pt)->children), ppe); \
+ if(*(ppe)) (*(ppe))->parent = NULL; \
+ } while(0)
+
+#define TDELCHILD(pt, pe) \
+ do { \
+ LDELETE(&((pt)->children), (pe)); \
+ (pe)->parent = NULL; } while(0)
+
+#define TPARENT(pe) ((pe)?(pe)->parent:NULL)
+
+/* FIFO lists */
+#define QDCL(type) \
+ type * head; \
+ type * tail
+
+#define QINIT(pq) \
+ do { \
+ (pq)->head = (pq)->tail = NULL; \
+ } while(0)
+
+#define QPUT(pq, pe) \
+ do { \
+ LPUSH(&(pq)->tail, (pe)); \
+ if(!(pq)->head) (pq)->head = (pe); \
+ } while(0)
+
+#define QPUSH(pq, pe) \
+ do { \
+ (pe)->next = NULL; \
+ (pe)->prev = (pq)->head; \
+ if((pq)->head) (pq)->head->next = (pe); \
+ if(!(pq)->tail) (pq)->tail = (pe); \
+ (pq)->head = (pe); \
+ } while (0)
+
+#define QGET(pq, ppe) \
+ do { \
+ *(ppe) = (pq)->head; \
+ if(*(ppe)) { \
+ (pq)->head = (*(ppe))->prev; \
+ if( (*(ppe))->prev ) (*(ppe))->prev->next = NULL; \
+ (*(ppe))->prev = NULL; \
+ if( (pq)->tail == *(ppe)) (pq)->tail = NULL; \
+ } \
+ } while(0)
+
+#define QDEL(pq, pe) \
+ do { \
+ if((pq)->head == (pe)) (pq)->head = LPREV(pe); \
+ LDELETE(&((pq)->tail), (pe)); \
+ } while(0)
+
+
+#define QGETT(pq,ppe) \
+ do { \
+ *(ppe) = (pq)->tail; \
+ if(*(ppe)) { \
+ (pq)->tail = (*(ppe))->next; \
+ if( (*(ppe))->next ) (*(ppe))->next->prev = NULL; \
+ (*(ppe))->next = NULL; \
+ if( (pq)->head == *(ppe)) (pq)->head = NULL; \
+ } \
+ } while(0)
+
+#define QTOP(pq) ((pq)->head)
+#define QBOTTOM(pq) ((pq)->tail)
+#define QNEXT(pe) ((pe)->prev)
+#define QPREV(pe) ((pe)->next)
+
+#define QINSERT(pt, pre, pe) \
+ do { \
+ if ((pre) == NULL || \
+ QNEXT(pre) == NULL) { QPUT(pt, pe); } \
+ else { \
+ (pe)->prev = (pre)->prev; \
+ (pe)->next = (pre); \
+ (pre)->prev->next = (pe); \
+ (pre)->prev = (pe); \
+ }} while(0)
+
+/* Trees with FIFO child lists */
+#define TQDCL(type) \
+ LDCL(type); \
+ QDCL(type); \
+ type * parent
+
+#define TQINIT(pe) \
+ do { \
+ LINIT(pe); \
+ QINIT(pe); \
+ (pe)->parent = NULL; } while(0)
+
+#define TQPUTCHILD(pt,pe) \
+ do { \
+ QPUT((pt), (pe)); \
+ (pe)->parent = (pt); } while(0)
+
+#define TQINSERT(pt, pre, pe) \
+ do { \
+ QINSERT(pt, pre, pe); \
+ (pe)->parent = (pt); } while(0)
+
+#define TQGETCHILD(pt,ppe) \
+ do { \
+ QGET(pt, ppe); \
+ if (*(ppe)) { *(ppe)->parent = NULL; } \
+ } while(0)
+
+#define TQDELCHILD(pt, pe) \
+ do { \
+ QDEL(pt, pe); \
+ (pe)->parent = NULL; } while(0)
+
+#define TQFIRSTCHILD(pt) ((pt)?QTOP(pt):NULL)
+
+#define TQNEXTCHILD(pe) QNEXT(pe)
+
+#define TQPREVCHILD(pe) QPREV(pe)
+
+#define TQPARENT(pe) ((pe)?(pe)->parent:NULL)
+
+#endif
diff --git a/src/windows/identity/include/khmsgtypes.h b/src/windows/identity/include/khmsgtypes.h
index 77397f90b5..cfb43f94e3 100644
--- a/src/windows/identity/include/khmsgtypes.h
+++ b/src/windows/identity/include/khmsgtypes.h
@@ -1,817 +1,817 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#ifndef __KHIMAIRA_KHMSGTYPES_H
-#define __KHIMAIRA_KHMSGTYPES_H
-
-/*! \addtogroup kmq
-@{*/
-/*! \defgroup kmq_msg Message Types
-@{*/
-
-/*! \name Global message types
-@{*/
-
-/*! \brief System messages.
-
- All subscribers are subscribed to the system message class by default.
-
- \see \ref kmq_msg_system
-*/
-#define KMSG_SYSTEM 0
-
-/*! \brief Ad-hoc messages.
-
- These are messages that are sent through add hoc publishers and
- subscribers.
-*/
-#define KMSG_ADHOC 1
-
-/*! \brief NetIDMgr Credentials Database messages
-
- These messages notify subscribers of events related to the
- credentials database, such as the registration, unregistration and
- modification of identities, attributes, attribute types and
- credential types. It also provides notifications of changes to
- the root crednetial set.
-
- \see \ref kmq_msg_kcdb
-*/
-#define KMSG_KCDB 2
-
-/*! \brief NetIDMgr Module Manager messages
-
- \see \ref kmq_msg_kmm
-*/
-#define KMSG_KMM 3
-
-/*! \brief NetIDMgr Credential messages
-
- Notifications of crednetial events. These are the most important
- events that a credentials provider should respond to. The
- notifications provide co-oridination between credential providers
- for performing basic credentials management tasks such as
- obtaining new credentials for an identity, deleting credentials
- for an identity, obtaining or deleting credentials of a particular
- type for an identity etc.
-
- \see \ref cred_msgs
- \see \ref kmq_msg_cred
- */
-#define KMSG_CRED 4
-
-/*! \brief Action list messages
-
- Notifications of changes in action state and firing of custom
- actions.
-
- \see \ref kmq_msg_act
- */
-#define KMSG_ACT 5
-
-/*! \brief Alert messages
-
- Notifier is the component which displays alerts and error messages
- when the NetIDMgr window is normally in operation and which
- displays balloon prompts when the window is minimized to alert the
- user to important messages such as credentials expiring etc.
-
- \note This is an internal message class. Components that are not
- the notifier should not be subscribing to alert messages.
-
- \see \ref kmq_msg_alert
- */
-#define KMSG_ALERT 6
-
-/*! \brief Identity messages
-
- These are messages that are sent to the identity provider. These
- are generally dispatched through a specific subscription object
- and are not broadcast.
-
- \see \ref kmq_msg_ident
- */
-#define KMSG_IDENT 7
-
-/*! \brief Base message type ID for customized message types
- */
-#define KMSGBASE_USER 16
-
-/*@}*/
-
-/*! \defgroup kmq_msg_system KMSG_SYSTEM subtypes
-@{*/
-/*! \brief Generic initialization message
-
- This message is used by specific components to signal that the
- recipient is to perform initialization tasks. As a convention,
- the recipient should return KHM_ERROR_SUCCESS if it successfully
- performed the initlization tasks or some other value if it failed
- to do so. Failure to successfully initialize is usually taken to
- mean that the recipient component is not able to perform its
- function.
-
- Usually this is the first message to be received by the recipient.
-
- \see \ref pi_pt_cred_init
- */
-#define KMSG_SYSTEM_INIT 1
-
-/*! \brief Generic uninitialization message
-
- Used by specific components to signal that the recipient should
- perform uninitilization tasks in preparation of termination. The
- return value of this message is not used.
-
- Usually this is the last message to be received by the recipient.
-
- \see \ref pi_pt_cred_exit
- */
-#define KMSG_SYSTEM_EXIT 2
-
-/*! \brief Message completion
-
- This is an internal message
- */
-#define KMSG_SYSTEM_COMPLETION 3
-/*@}*/
-
-/*! \defgroup kmq_msg_kcdb KMSG_KCDB subtypes
-@{*/
-#define KMSG_KCDB_IDENT 1
-#define KMSG_KCDB_CREDTYPE 2
-#define KMSG_KCDB_ATTRIB 3
-#define KMSG_KCDB_TYPE 4
-
-/*! \brief Generic credentials request
-
- \see ::kcdb_cred_request for more information
- */
-#define KMSG_KCDB_REQUEST 256
-/*@}*/
-
-/*! \defgroup kmq_msg_kmm KMSG_KMM subtypes
-@{*/
-#define KMSG_KMM_I_REG 1
-
-#define KMSG_KMM_I_DONE 2
-/*@}*/
-
-/*! \defgroup kmq_msg_act KMSG_ACT subtypes
- @{*/
-
-/*! \brief One or more actions changed state
-
- This message is sent in response to a call to
- khui_enable_actions() or khui_enable_action() and indicates that
- one or more actions have changed their state.
- */
-#define KMSG_ACT_ENABLE 1
-
-/*! \brief One or more actions changed check state
-
- Sent in response to khui_check_radio_action() or
- khui_check_action() and indicates that one or more actions have
- either been checked or unchecked.
- */
-#define KMSG_ACT_CHECK 2
-
-/*! \brief Refresh action states
-
- Sent after a batch of modifications were made to action states.
- */
-#define KMSG_ACT_REFRESH 3
-
-/*! \brief A new action was created
-
- Sent when a new custom action was created. The \a uparam
- parameter of the message contains the identifier of the newly
- created action.
-*/
-#define KMSG_ACT_NEW 4
-
-/*! \brief A custom action was deleted
-
- Sent after a custom action is deleted. The \a uparam parameter of
- the message contains the identifier of the deleted action.
- */
-#define KMSG_ACT_DELETE 5
-
-/*! \brief A custom action has been activated
-
- When a custom action is activated, then the listener of that
- custom action receives this message. Note that only the listener
- for that custom action will receive this notification.
-
- \a uparam of the message is set to the identifier of the custom
- action.
- */
-#define KMSG_ACT_ACTIVATE 6
-
-/*! \brief Internal */
-#define KMSG_ACT_BEGIN_CMDLINE 128
-
-/*! \brief Internal */
-#define KMSG_ACT_CONTINUE_CMDLINE 129
-
-/*! \brief Internal */
-#define KMSG_ACT_SYNC_CFG 130
-
-/*! \brief Internal */
-#define KMSG_ACT_END_CMDLINE 131
-
-/*@}*/
-
-/*! \defgroup kmq_msg_cred KMSG_CRED subtypes
- @{*/
-/*! \brief Root credential set changed
-
- This message is issued when the root credential set successfully
- collected credentials from another credential set.
-
- \a uparam of the message is set to a bitmask indicating the change
- that occured. It is a combination of ::KCDB_DELTA_ADD,
- ::KCDB_DELTA_DEL and ::KCDB_DELTA_MODIFY.
- */
-#define KMSG_CRED_ROOTDELTA 1
-
-/*! \brief Re-enumerate credentials
-
- A notice to all credential providers to re-enumerate their
- respective credentials.
-
- \note May be sent to individual credential subscriptions.
- */
-#define KMSG_CRED_REFRESH 2
-
-/*! \brief Change the password
-
- This message notifies credentials providers that a password change
- request has been received.
-
- A plug-in handling this message that wishes to participate in the
- password change operation is expected to add a
- ::khui_new_creds_by_type to the list of participants in the
- ::khui_new_creds structure by calling khui_cw_add_type().
-
- The password change operation requires user interaction. Any
- plug-ins that are participating in the operation need to provide a
- user-interface.
-
- Message parameters:
- - \b vparam : pointer to a ::khui_new_creds structure
-
- \see khui_cw_add_type(), ::khui_new_creds, ::khui_new_creds_by_type
- */
-#define KMSG_CRED_PASSWORD 16
-
-/*! \brief Initiate the process of obtaining new credentials
-
- The UI sends this message to start the process of obtaining new
- credentials. See \ref cred_acq for more information about
- handling this message.
-
- A plug-in handling this message that wishes to participate in the
- new credentials acquisition operation is expected to add a
- ::khui_new_creds_by_type to hte list of participants in the
- ::khui_new_creds structure by calling khui_cw_add_type().
-
- Message parameters:
- - \b vparam : pointer to a ::khui_new_creds structure
-
- \see \ref cred_acq, khui_cw_add_type(), ::khui_new_creds,
- ::khui_new_creds_by_type
- */
-#define KMSG_CRED_NEW_CREDS 17
-
-/*! \brief Renew credentials
-
- This is a notification sent to individual credentials providers
- that a specified identity's credentials should be renewed.
-
- A plug-in handling this message that wishes to participate in the
- renew credentials operation is expected to add a
- ::khui_new_creds_by_type to the list of participants in the
- ::khui_new_creds structure by calling khui_cw_add_type().
-
- Message parameters:
- - \b vparam : Pointer to a khui_new_creds object
-
- \see khui_cw_add_type(), ::khui_new_creds,
- ::khui_new_creds_by_type
- */
-#define KMSG_CRED_RENEW_CREDS 18
-
-/*! \brief Dialog setup
-
- Once ::KMSG_CRED_NEW_CREDS has been responded to by all the
- credential types, the UI creates the dialog windows using the data
- supplied in the ::khui_new_creds_by_type structures and issues
- this message. Each credentials provider is expected to respond by
- finalizing dialog creation operations.
-
- Message parameters:
- - \b vparam : pointer to a ::khui_new_creds structure
-
- \note May be sent to individual credential subscriptions.
- */
-#define KMSG_CRED_DIALOG_SETUP 19
-
-/*! \brief Dialog pre-start
-
- Sent after all the credentials providers have responded to
- ::KMSG_CRED_DIALOG_SETUP and all the initialization has been
- completed. Credentials providers are expected to respond to this
- message by loading any default data into the dialog controls for
- each credential type.
-
- Message parameters:
- - \b vparam : pointer to a ::khui_new_creds structure
-
- \note May be sent to individual credential subscriptions.
- */
-#define KMSG_CRED_DIALOG_PRESTART 20
-
-/*! \brief Dialog start
-
- A notification that the dialog is now in progress.
-
- Message parameters:
- - \b vparam : pointer to a ::khui_new_creds structure
-
- \note May be sent to individual credential subscriptions.
- */
-#define KMSG_CRED_DIALOG_START 21
-
-/*! \brief The primary identity of the new credentials dialog has changed
-
- This message is not sent out by the UI, but is reserved here for
- use by individual credentials providers. The message may be sent
- from the dialog procedure to the plugin.
-
- Message parameters:
- - \b vparam : pointer to a ::khui_new_creds structure
-
- \note Be careful when sending this message. All messages that are
- not sent by the system should not be sent via broadcast.
- Instead, create a subscription using kmq_create_subscription()
- for the individual plugin that you want to send the message
- and use one of the per-subscription message functions to send
- the actual message.
- */
-#define KMSG_CRED_DIALOG_NEW_IDENTITY 22
-
-/*! \brief New credentials options have changed.
-
- This message is not sent out by the UI, but is reserved here for
- use by individual credentials providers. The message may be sent
- from the dialog procedure to the plugin.
-
- Message parameters:
- - \b vparam : pointer to a ::khui_new_creds structure
-
- \note Be careful when sending this message. All messages that are
- not sent by the system should not be sent via broadcast.
- Instead, create a subscription using kmq_create_subscription()
- for the individual plugin that you want to send the message
- and use one of the per-subscription message functions to send
- the actual message.
- */
-#define KMSG_CRED_DIALOG_NEW_OPTIONS 23
-
-/*! \brief Process dialog
-
- Sent to all the credential providers to look at the contents of
- the given ::khui_new_creds structure and do any required
- processing.
-
- If the \a result field in the structure is set to
- ::KHUI_NC_RESULT_PROCESS, then new credentials should be
- obtained using the given data.
-
- Set the \a response field in the structure to indicate how the UI
- should proceed from here.
-
- Message parameters:
- - \b vparam : pointer to a ::khui_new_creds structure
-
- \note May be sent to individual credential subscriptions.
- */
-#define KMSG_CRED_PROCESS 24
-
-/*! \brief End a credentials acquisition operation
-
- A notification that the credentials acquisition operation has
- ended.
-
- Message parameters:
- - \b vparam : pointer to a ::khui_new_creds structure
-
- \note May be sent to individual credential subscriptions.
- */
-#define KMSG_CRED_END 25
-
-/*! \brief Import credentials from the operating system
-
- Notification to all credentials providers to import any available
- credentials from the operating system.
-
- Message parameters:
- - This message does not have any parameters
-*/
-#define KMSG_CRED_IMPORT 26
-
-/*! \brief Destroy credentials
-
- Notification that the specified credentials should be destroyed.
- Once this message has completed processing a ::KMSG_CRED_REFRESH
- message will be issued.
-
- The credentials that should be destroyed are specified by a
- ::khui_action_context structure. The context that should be used
- is the selection context. Hence, the credentials that must be
- destroyed are the ones lised in the credential set (\a credset).
-
- Message parameters:
-
- - \b upram : Unused. Zero.
-
- - \b vparam : pointer to a ::khui_action_context structure which
- describes which credentials need to be destroyed.
-
- */
-#define KMSG_CRED_DESTROY_CREDS 32
-
-#if 0
-/*! \brief Parse an identity
-
- \note May be sent to individual credential subscriptions.
- */
-#define KMSG_CRED_IDENT_PARSE 65
-#endif
-
-/*! \brief A property page is being launced
-
- Handlers of this message should determine whether or not they
- should participate in the property sheet and if so, add a
- ::khui_property_page structure to the property sheet.
-
- Message parameters:
- - \b vparam : pointer to a ::khui_property_sheet structure
- */
-#define KMSG_CRED_PP_BEGIN 128
-
-/*! \brief A property page is about to be created
-
- Message parameters:
- - \b vparam : pointer to a ::khui_property_sheet structure
-
- \note This message is merely a notification that the property
- sheet is being created. Handlers should not modify the state
- of the property sheet or pages at this time.
- */
-#define KMSG_CRED_PP_PRECREATE 129
-
-/*! \brief A property page has finished processing
-
- Handlers of this message should remove any ::khui_property_page
- structures they added when processing ::KMSG_CRED_PP_BEGIN.
-
- Message parameters:
- - \b vparam : pointer to a ::khui_property_sheet structure
- */
-#define KMSG_CRED_PP_END 130
-
-/*! \brief A property page has been destroyed
-
- Message parameters:
- - \b vparam : pointer to a ::khui_property_sheet structure
-
- \note This is a notification that the property sheet processing
- has been completed and that the property sheet data structures
- should be freed. Any property page data structures should
- have already been freed while processing KMSG_CRED_PP_END.
- The validity of the ::khui_property_sheet structure should not
- be relied upon while processing this message.
- */
-#define KMSG_CRED_PP_DESTROY 131
-
-/*! \brief An IP address change occurred
-
- There are no parameters for this message. The NetIDMgr
- application handles this message and depending on configuration,
- posts message for the individual credentials providers to either
- obtain new credentials or renew old ones.
- */
-#define KMSG_CRED_ADDR_CHANGE 140
-
-/*! \brief Check if a KMSG_CRED subtype is a credentials acquisition message
-
- Dialog messages are those that deal with the new or initial
- credentials acquisition dialog, from initial announcement to
- dialog completion.
-
- Currently, the dialog messages are:
- - ::KMSG_CRED_NEW_CREDS
- - ::KMSG_CRED_RENEW_CREDS
- - ::KMSG_CRED_DIALOG_SETUP
- - ::KMSG_CRED_DIALOG_PRESTART
- - ::KMSG_CRED_DIALOG_START
- - ::KMSG_CRED_DIALOG_NEW_IDENTITY
- - ::KMSG_CRED_DIALOG_NEW_OPTIONS
- - ::KMSG_CRED_PROCESS
- - ::KMSG_CRED_END
-
- All dialog message numbers are allocated in a contigous block.
-
- Note that while ::KMSG_CRED_PROCESS and ::KMSG_CRED_END are not
- specific to dialogs, they are still included in this predicate
- because they are also part of the dialog message sequence.
- */
-#define IS_CRED_ACQ_MSG(msg) ((msg) >= 16 && (msg) <=31)
-
-/*@}*/ /* /KMSG_CRED subtypes */
-
-/*! \defgroup kmq_msg_alert KMSG_ALERT Subtypes
- @{*/
-
-/*! \brief Show an alert
-
- Message parameters:
- - \b vparam : held pointer to a ::khui_alert object
-
- \note The ::khui_alert object will be released when the processing
- of this message completes.
- */
-#define KMSG_ALERT_SHOW 1
-
-/*! \brief Add an alert to the alert queue
-
- Message parameters:
- - \b vparam : held pointer to a ::khui_alert object
-
- \note the ::khui_alert object will be released when the queued
- messages are displayed.
- */
-#define KMSG_ALERT_QUEUE 2
-
-/*! \brief Show the next queued alert
-
- There are no message parameters
- */
-#define KMSG_ALERT_SHOW_QUEUED 3
-
-/*! \brief Check if there are any queued messages and, if so, update the statusbar
-
- There are no message parameters
- */
-#define KMSG_ALERT_CHECK_QUEUE 4
-
-/*! \brief Show a modal alert
-
- Message parameters:
- - \b vparam : held pointer to a ::khui_alert object.
-
- \note the ::khui_alert object will be released when the queued
- messages are displayed.
- */
-#define KMSG_ALERT_SHOW_MODAL 5
-
-/*@}*/
-
-/*! \defgroup kmq_msg_ident KMSG_IDENT Subtypes
- @{*/
-
-/*! \brief Initialize and start the identity provider
-
-
- Sent by the KCDB to notify the identity provider that it is now
- the current identity provider.
-
- Note that unlike regular plugins, an identity provider can be
- loaded and inert (not provide any services). Also, the user may
- switch between multiple identity providers on the fly.
- */
-#define KMSG_IDENT_INIT 1
-
-/*! \brief Stop the identity provider
-
- Sent by the KCDB as notificaton that the identity provider is no
- longer the current provider.
- */
-#define KMSG_IDENT_EXIT 2
-
-/*! \brief Check if an identity name is valid
-
- This message is sent to the identity provider to verify the syntax
- of an identity name. Note that only the syntax of the name is to
- be verfied and not the actual physical existence of said identity.
-
- Message parameters:
-
- - \b vparam : pointer to ::kcdb_ident_name_xfer object. The
- name to be validated will be in the \a name_src member. The
- buffer will be NULL terminated with a maximum limit of
- KCDB_IDENT_MAXCCH_NAME characters including the terminating
- NULL, consisting only of characters in KCDB_IDENT_VALID_CHARS
- The \a result member should be set to one of the following
- depending on the result of the validation:
-
- - KHM_ERROR_SUCCESS : The name was valid
- - KHM_ERROR_INVALID_NAME : The name was invalid
- */
-#define KMSG_IDENT_VALIDATE_NAME 3
-
-/*! \brief Check if an identity is valid
-
- Sent to the identity provider to verify the validity of the given
- identity. The provider should verify that the identity exists and
- is in a state where it can be actively used.
-
- Depending on the result of the validation, the flags of the
- identity should be updated.
-
- Message parameters:
- - \b vparam : Handle to an identity cast as a void pointer.
- */
-#define KMSG_IDENT_VALIDATE_IDENTITY 4
-
-/*! \brief Canonicalize identity name
-
- The identity provider will be given a name, which it should put in
- canonical form, adjusting case and any character replacement or
- doing any relevant expansions if applicable, and place it in the
- supplied buffer.
-
- Message parameters:
-
- - \b vparam : Pointer to a ::kcdb_ident_name_xfer structure
- which provides the identity name to canonicalize in the \a
- name_src member, and the buffer to store the canonical name
- in the \a name_dest member. The \a name_dest buffer is
- guaranteed to be at least KCDB_IDENT_MAXCCH_NAME characters
- in size.
-
- If the name cannot be canonicalized for some reason, the
- destination buffer should be set to a zero-length string and the
- \a result member of the ::kcdb_ident_name_xfer structure should be
- set to the error code. If the destination buffer is set to a
- zero-length string and \a result is KHM_ERROR_SUCCESS, then the
- original name provided in \a name_src is assumed to be already in
- canonical form.
- */
-#define KMSG_IDENT_CANON_NAME 5
-
-/*! \brief Compare names
-
- Compare two identity names. The names that are given aren't
- guaranteed to be in canonical form. The return value should be
- akin to strcmp().
-
- Message parameters:
-
- - \b vparam : A pointer to a ::kcdb_ident_name_xfer structure.
- The \a name_src member points at the first name, and the \a
- name_alt member specifies the second name. The result of the
- comparison should be place in \a result.
- */
-#define KMSG_IDENT_COMPARE_NAME 6
-
-/*! \brief Set the default identity
-
- Set or unset the default identity. To set the default identity,
- the \a uparam parameter will be set to a non-zero value and a
- handle to the identity will be specified in \a vparam. To unset
- the default identity (i.e. not have a default identity), a zero
- value will be specified in \a uparam and no identities will be
- specified in \a vparam.
-
- When setting a default identity, the identity provider will
- receive this message prior to the ::KCDB_IDENT_FLAG_DEFAULT bit
- being set or reset on any identity. It should return
- KHM_ERROR_SUCCESS if the requested operation can be performed.
- Returning any other value will abort the operation and will leave
- the default identity unchanged.
-
- When resetting the default identity, this message should be
- treated only as a notification.
-
- Message parameters:
-
- - \a uparam : Is non-zero if an identity is being made default. If
- this is zero, then identity should be the default.
-
- - \a vparam : A handle to the identity to be made default if \a
- uparam is non-zero. NULL otherwise.
-
- Return value:
-
- - KHM_ERROR_SUCCESS : The identity should be marked as default
- - Any other value : The identity should not be marked as default
-
- */
-#define KMSG_IDENT_SET_DEFAULT 7
-
-/*! \brief Set an identity as searchable
-
- Set or reset the searchable bit on an identity. If the \a uparam
- parameter is non-zero, then the searchable bit is being set.
- Otherwise it is being reset. The identity provider should return
- KHM_ERROR_SUCCESS in order to indicate that the identity should be
- marked as searchable. Any other value will result in the
- searchable bit being reset on the identity.
-
- Message parameters:
-
- - \a uparam : Is non-zero if the searchable bit is being set. Zero
- otherwise.
-
- - \a vparam : Handle to the identity
-
- Return value:
-
- - KHM_ERROR_SUCCESS: The identity should be marked as searchable
- - Any other value : The identity should not be marked as default
- */
-#define KMSG_IDENT_SET_SEARCHABLE 8
-
-/*! \brief Get information about an identity
-
- */
-#define KMSG_IDENT_GET_INFO 9
-
-/*! \brief Enumerate known and accessible identities
- */
-#define KMSG_IDENT_ENUM_KNOWN 10
-
-/*! \brief Update information about an identity
- */
-#define KMSG_IDENT_UPDATE 11
-
-/*! \brief Retrieve the user interface callback function
-
- When obtaining new credentials, the user interface needs to obtain
- a callback function which will provide identity selection
- controls.
-
- Message parameters:
-
- - \a uparam : Not used
-
- - \a vparam : pointer to a ::khui_ident_new_creds_cb which will
- receive the call back.
- */
-#define KMSG_IDENT_GET_UI_CALLBACK 12
-
-/*! \brief Notification of the creation of an identity
-
- This should be considered just a notification. The identit
- provider does not have an opportunity to veto the creation of an
- identity whose name has been found to be valid. However, when
- handing this notification, the identity provider can:
-
- - Change the flags of the identity and/or marking the identity as
- invalid.
-
- - Change the default identity.
-
- Note that this notification is sent before the general :;KMSG_KCDB
- notification of the identity creation is sent.
-
- Message parameters:
-
- - \a uparam : Not used.
-
- - \p vparam : handle to the identity
- */
-#define KMSG_IDENT_NOTIFY_CREATE 13
-
-/*@}*/ /* /KMSG_IDENT subtypes */
-
-/*@}*/ /* / message types */
-/*@}*/ /* / kmq */
-
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __KHIMAIRA_KHMSGTYPES_H
+#define __KHIMAIRA_KHMSGTYPES_H
+
+/*! \addtogroup kmq
+@{*/
+/*! \defgroup kmq_msg Message Types
+@{*/
+
+/*! \name Global message types
+@{*/
+
+/*! \brief System messages.
+
+ All subscribers are subscribed to the system message class by default.
+
+ \see \ref kmq_msg_system
+*/
+#define KMSG_SYSTEM 0
+
+/*! \brief Ad-hoc messages.
+
+ These are messages that are sent through add hoc publishers and
+ subscribers.
+*/
+#define KMSG_ADHOC 1
+
+/*! \brief NetIDMgr Credentials Database messages
+
+ These messages notify subscribers of events related to the
+ credentials database, such as the registration, unregistration and
+ modification of identities, attributes, attribute types and
+ credential types. It also provides notifications of changes to
+ the root crednetial set.
+
+ \see \ref kmq_msg_kcdb
+*/
+#define KMSG_KCDB 2
+
+/*! \brief NetIDMgr Module Manager messages
+
+ \see \ref kmq_msg_kmm
+*/
+#define KMSG_KMM 3
+
+/*! \brief NetIDMgr Credential messages
+
+ Notifications of crednetial events. These are the most important
+ events that a credentials provider should respond to. The
+ notifications provide co-oridination between credential providers
+ for performing basic credentials management tasks such as
+ obtaining new credentials for an identity, deleting credentials
+ for an identity, obtaining or deleting credentials of a particular
+ type for an identity etc.
+
+ \see \ref cred_msgs
+ \see \ref kmq_msg_cred
+ */
+#define KMSG_CRED 4
+
+/*! \brief Action list messages
+
+ Notifications of changes in action state and firing of custom
+ actions.
+
+ \see \ref kmq_msg_act
+ */
+#define KMSG_ACT 5
+
+/*! \brief Alert messages
+
+ Notifier is the component which displays alerts and error messages
+ when the NetIDMgr window is normally in operation and which
+ displays balloon prompts when the window is minimized to alert the
+ user to important messages such as credentials expiring etc.
+
+ \note This is an internal message class. Components that are not
+ the notifier should not be subscribing to alert messages.
+
+ \see \ref kmq_msg_alert
+ */
+#define KMSG_ALERT 6
+
+/*! \brief Identity messages
+
+ These are messages that are sent to the identity provider. These
+ are generally dispatched through a specific subscription object
+ and are not broadcast.
+
+ \see \ref kmq_msg_ident
+ */
+#define KMSG_IDENT 7
+
+/*! \brief Base message type ID for customized message types
+ */
+#define KMSGBASE_USER 16
+
+/*@}*/
+
+/*! \defgroup kmq_msg_system KMSG_SYSTEM subtypes
+@{*/
+/*! \brief Generic initialization message
+
+ This message is used by specific components to signal that the
+ recipient is to perform initialization tasks. As a convention,
+ the recipient should return KHM_ERROR_SUCCESS if it successfully
+ performed the initlization tasks or some other value if it failed
+ to do so. Failure to successfully initialize is usually taken to
+ mean that the recipient component is not able to perform its
+ function.
+
+ Usually this is the first message to be received by the recipient.
+
+ \see \ref pi_pt_cred_init
+ */
+#define KMSG_SYSTEM_INIT 1
+
+/*! \brief Generic uninitialization message
+
+ Used by specific components to signal that the recipient should
+ perform uninitilization tasks in preparation of termination. The
+ return value of this message is not used.
+
+ Usually this is the last message to be received by the recipient.
+
+ \see \ref pi_pt_cred_exit
+ */
+#define KMSG_SYSTEM_EXIT 2
+
+/*! \brief Message completion
+
+ This is an internal message
+ */
+#define KMSG_SYSTEM_COMPLETION 3
+/*@}*/
+
+/*! \defgroup kmq_msg_kcdb KMSG_KCDB subtypes
+@{*/
+#define KMSG_KCDB_IDENT 1
+#define KMSG_KCDB_CREDTYPE 2
+#define KMSG_KCDB_ATTRIB 3
+#define KMSG_KCDB_TYPE 4
+
+/*! \brief Generic credentials request
+
+ \see ::kcdb_cred_request for more information
+ */
+#define KMSG_KCDB_REQUEST 256
+/*@}*/
+
+/*! \defgroup kmq_msg_kmm KMSG_KMM subtypes
+@{*/
+#define KMSG_KMM_I_REG 1
+
+#define KMSG_KMM_I_DONE 2
+/*@}*/
+
+/*! \defgroup kmq_msg_act KMSG_ACT subtypes
+ @{*/
+
+/*! \brief One or more actions changed state
+
+ This message is sent in response to a call to
+ khui_enable_actions() or khui_enable_action() and indicates that
+ one or more actions have changed their state.
+ */
+#define KMSG_ACT_ENABLE 1
+
+/*! \brief One or more actions changed check state
+
+ Sent in response to khui_check_radio_action() or
+ khui_check_action() and indicates that one or more actions have
+ either been checked or unchecked.
+ */
+#define KMSG_ACT_CHECK 2
+
+/*! \brief Refresh action states
+
+ Sent after a batch of modifications were made to action states.
+ */
+#define KMSG_ACT_REFRESH 3
+
+/*! \brief A new action was created
+
+ Sent when a new custom action was created. The \a uparam
+ parameter of the message contains the identifier of the newly
+ created action.
+*/
+#define KMSG_ACT_NEW 4
+
+/*! \brief A custom action was deleted
+
+ Sent after a custom action is deleted. The \a uparam parameter of
+ the message contains the identifier of the deleted action.
+ */
+#define KMSG_ACT_DELETE 5
+
+/*! \brief A custom action has been activated
+
+ When a custom action is activated, then the listener of that
+ custom action receives this message. Note that only the listener
+ for that custom action will receive this notification.
+
+ \a uparam of the message is set to the identifier of the custom
+ action.
+ */
+#define KMSG_ACT_ACTIVATE 6
+
+/*! \brief Internal */
+#define KMSG_ACT_BEGIN_CMDLINE 128
+
+/*! \brief Internal */
+#define KMSG_ACT_CONTINUE_CMDLINE 129
+
+/*! \brief Internal */
+#define KMSG_ACT_SYNC_CFG 130
+
+/*! \brief Internal */
+#define KMSG_ACT_END_CMDLINE 131
+
+/*@}*/
+
+/*! \defgroup kmq_msg_cred KMSG_CRED subtypes
+ @{*/
+/*! \brief Root credential set changed
+
+ This message is issued when the root credential set successfully
+ collected credentials from another credential set.
+
+ \a uparam of the message is set to a bitmask indicating the change
+ that occured. It is a combination of ::KCDB_DELTA_ADD,
+ ::KCDB_DELTA_DEL and ::KCDB_DELTA_MODIFY.
+ */
+#define KMSG_CRED_ROOTDELTA 1
+
+/*! \brief Re-enumerate credentials
+
+ A notice to all credential providers to re-enumerate their
+ respective credentials.
+
+ \note May be sent to individual credential subscriptions.
+ */
+#define KMSG_CRED_REFRESH 2
+
+/*! \brief Change the password
+
+ This message notifies credentials providers that a password change
+ request has been received.
+
+ A plug-in handling this message that wishes to participate in the
+ password change operation is expected to add a
+ ::khui_new_creds_by_type to the list of participants in the
+ ::khui_new_creds structure by calling khui_cw_add_type().
+
+ The password change operation requires user interaction. Any
+ plug-ins that are participating in the operation need to provide a
+ user-interface.
+
+ Message parameters:
+ - \b vparam : pointer to a ::khui_new_creds structure
+
+ \see khui_cw_add_type(), ::khui_new_creds, ::khui_new_creds_by_type
+ */
+#define KMSG_CRED_PASSWORD 16
+
+/*! \brief Initiate the process of obtaining new credentials
+
+ The UI sends this message to start the process of obtaining new
+ credentials. See \ref cred_acq for more information about
+ handling this message.
+
+ A plug-in handling this message that wishes to participate in the
+ new credentials acquisition operation is expected to add a
+ ::khui_new_creds_by_type to hte list of participants in the
+ ::khui_new_creds structure by calling khui_cw_add_type().
+
+ Message parameters:
+ - \b vparam : pointer to a ::khui_new_creds structure
+
+ \see \ref cred_acq, khui_cw_add_type(), ::khui_new_creds,
+ ::khui_new_creds_by_type
+ */
+#define KMSG_CRED_NEW_CREDS 17
+
+/*! \brief Renew credentials
+
+ This is a notification sent to individual credentials providers
+ that a specified identity's credentials should be renewed.
+
+ A plug-in handling this message that wishes to participate in the
+ renew credentials operation is expected to add a
+ ::khui_new_creds_by_type to the list of participants in the
+ ::khui_new_creds structure by calling khui_cw_add_type().
+
+ Message parameters:
+ - \b vparam : Pointer to a khui_new_creds object
+
+ \see khui_cw_add_type(), ::khui_new_creds,
+ ::khui_new_creds_by_type
+ */
+#define KMSG_CRED_RENEW_CREDS 18
+
+/*! \brief Dialog setup
+
+ Once ::KMSG_CRED_NEW_CREDS has been responded to by all the
+ credential types, the UI creates the dialog windows using the data
+ supplied in the ::khui_new_creds_by_type structures and issues
+ this message. Each credentials provider is expected to respond by
+ finalizing dialog creation operations.
+
+ Message parameters:
+ - \b vparam : pointer to a ::khui_new_creds structure
+
+ \note May be sent to individual credential subscriptions.
+ */
+#define KMSG_CRED_DIALOG_SETUP 19
+
+/*! \brief Dialog pre-start
+
+ Sent after all the credentials providers have responded to
+ ::KMSG_CRED_DIALOG_SETUP and all the initialization has been
+ completed. Credentials providers are expected to respond to this
+ message by loading any default data into the dialog controls for
+ each credential type.
+
+ Message parameters:
+ - \b vparam : pointer to a ::khui_new_creds structure
+
+ \note May be sent to individual credential subscriptions.
+ */
+#define KMSG_CRED_DIALOG_PRESTART 20
+
+/*! \brief Dialog start
+
+ A notification that the dialog is now in progress.
+
+ Message parameters:
+ - \b vparam : pointer to a ::khui_new_creds structure
+
+ \note May be sent to individual credential subscriptions.
+ */
+#define KMSG_CRED_DIALOG_START 21
+
+/*! \brief The primary identity of the new credentials dialog has changed
+
+ This message is not sent out by the UI, but is reserved here for
+ use by individual credentials providers. The message may be sent
+ from the dialog procedure to the plugin.
+
+ Message parameters:
+ - \b vparam : pointer to a ::khui_new_creds structure
+
+ \note Be careful when sending this message. All messages that are
+ not sent by the system should not be sent via broadcast.
+ Instead, create a subscription using kmq_create_subscription()
+ for the individual plugin that you want to send the message
+ and use one of the per-subscription message functions to send
+ the actual message.
+ */
+#define KMSG_CRED_DIALOG_NEW_IDENTITY 22
+
+/*! \brief New credentials options have changed.
+
+ This message is not sent out by the UI, but is reserved here for
+ use by individual credentials providers. The message may be sent
+ from the dialog procedure to the plugin.
+
+ Message parameters:
+ - \b vparam : pointer to a ::khui_new_creds structure
+
+ \note Be careful when sending this message. All messages that are
+ not sent by the system should not be sent via broadcast.
+ Instead, create a subscription using kmq_create_subscription()
+ for the individual plugin that you want to send the message
+ and use one of the per-subscription message functions to send
+ the actual message.
+ */
+#define KMSG_CRED_DIALOG_NEW_OPTIONS 23
+
+/*! \brief Process dialog
+
+ Sent to all the credential providers to look at the contents of
+ the given ::khui_new_creds structure and do any required
+ processing.
+
+ If the \a result field in the structure is set to
+ ::KHUI_NC_RESULT_PROCESS, then new credentials should be
+ obtained using the given data.
+
+ Set the \a response field in the structure to indicate how the UI
+ should proceed from here.
+
+ Message parameters:
+ - \b vparam : pointer to a ::khui_new_creds structure
+
+ \note May be sent to individual credential subscriptions.
+ */
+#define KMSG_CRED_PROCESS 24
+
+/*! \brief End a credentials acquisition operation
+
+ A notification that the credentials acquisition operation has
+ ended.
+
+ Message parameters:
+ - \b vparam : pointer to a ::khui_new_creds structure
+
+ \note May be sent to individual credential subscriptions.
+ */
+#define KMSG_CRED_END 25
+
+/*! \brief Import credentials from the operating system
+
+ Notification to all credentials providers to import any available
+ credentials from the operating system.
+
+ Message parameters:
+ - This message does not have any parameters
+*/
+#define KMSG_CRED_IMPORT 26
+
+/*! \brief Destroy credentials
+
+ Notification that the specified credentials should be destroyed.
+ Once this message has completed processing a ::KMSG_CRED_REFRESH
+ message will be issued.
+
+ The credentials that should be destroyed are specified by a
+ ::khui_action_context structure. The context that should be used
+ is the selection context. Hence, the credentials that must be
+ destroyed are the ones lised in the credential set (\a credset).
+
+ Message parameters:
+
+ - \b upram : Unused. Zero.
+
+ - \b vparam : pointer to a ::khui_action_context structure which
+ describes which credentials need to be destroyed.
+
+ */
+#define KMSG_CRED_DESTROY_CREDS 32
+
+#if 0
+/*! \brief Parse an identity
+
+ \note May be sent to individual credential subscriptions.
+ */
+#define KMSG_CRED_IDENT_PARSE 65
+#endif
+
+/*! \brief A property page is being launced
+
+ Handlers of this message should determine whether or not they
+ should participate in the property sheet and if so, add a
+ ::khui_property_page structure to the property sheet.
+
+ Message parameters:
+ - \b vparam : pointer to a ::khui_property_sheet structure
+ */
+#define KMSG_CRED_PP_BEGIN 128
+
+/*! \brief A property page is about to be created
+
+ Message parameters:
+ - \b vparam : pointer to a ::khui_property_sheet structure
+
+ \note This message is merely a notification that the property
+ sheet is being created. Handlers should not modify the state
+ of the property sheet or pages at this time.
+ */
+#define KMSG_CRED_PP_PRECREATE 129
+
+/*! \brief A property page has finished processing
+
+ Handlers of this message should remove any ::khui_property_page
+ structures they added when processing ::KMSG_CRED_PP_BEGIN.
+
+ Message parameters:
+ - \b vparam : pointer to a ::khui_property_sheet structure
+ */
+#define KMSG_CRED_PP_END 130
+
+/*! \brief A property page has been destroyed
+
+ Message parameters:
+ - \b vparam : pointer to a ::khui_property_sheet structure
+
+ \note This is a notification that the property sheet processing
+ has been completed and that the property sheet data structures
+ should be freed. Any property page data structures should
+ have already been freed while processing KMSG_CRED_PP_END.
+ The validity of the ::khui_property_sheet structure should not
+ be relied upon while processing this message.
+ */
+#define KMSG_CRED_PP_DESTROY 131
+
+/*! \brief An IP address change occurred
+
+ There are no parameters for this message. The NetIDMgr
+ application handles this message and depending on configuration,
+ posts message for the individual credentials providers to either
+ obtain new credentials or renew old ones.
+ */
+#define KMSG_CRED_ADDR_CHANGE 140
+
+/*! \brief Check if a KMSG_CRED subtype is a credentials acquisition message
+
+ Dialog messages are those that deal with the new or initial
+ credentials acquisition dialog, from initial announcement to
+ dialog completion.
+
+ Currently, the dialog messages are:
+ - ::KMSG_CRED_NEW_CREDS
+ - ::KMSG_CRED_RENEW_CREDS
+ - ::KMSG_CRED_DIALOG_SETUP
+ - ::KMSG_CRED_DIALOG_PRESTART
+ - ::KMSG_CRED_DIALOG_START
+ - ::KMSG_CRED_DIALOG_NEW_IDENTITY
+ - ::KMSG_CRED_DIALOG_NEW_OPTIONS
+ - ::KMSG_CRED_PROCESS
+ - ::KMSG_CRED_END
+
+ All dialog message numbers are allocated in a contigous block.
+
+ Note that while ::KMSG_CRED_PROCESS and ::KMSG_CRED_END are not
+ specific to dialogs, they are still included in this predicate
+ because they are also part of the dialog message sequence.
+ */
+#define IS_CRED_ACQ_MSG(msg) ((msg) >= 16 && (msg) <=31)
+
+/*@}*/ /* /KMSG_CRED subtypes */
+
+/*! \defgroup kmq_msg_alert KMSG_ALERT Subtypes
+ @{*/
+
+/*! \brief Show an alert
+
+ Message parameters:
+ - \b vparam : held pointer to a ::khui_alert object
+
+ \note The ::khui_alert object will be released when the processing
+ of this message completes.
+ */
+#define KMSG_ALERT_SHOW 1
+
+/*! \brief Add an alert to the alert queue
+
+ Message parameters:
+ - \b vparam : held pointer to a ::khui_alert object
+
+ \note the ::khui_alert object will be released when the queued
+ messages are displayed.
+ */
+#define KMSG_ALERT_QUEUE 2
+
+/*! \brief Show the next queued alert
+
+ There are no message parameters
+ */
+#define KMSG_ALERT_SHOW_QUEUED 3
+
+/*! \brief Check if there are any queued messages and, if so, update the statusbar
+
+ There are no message parameters
+ */
+#define KMSG_ALERT_CHECK_QUEUE 4
+
+/*! \brief Show a modal alert
+
+ Message parameters:
+ - \b vparam : held pointer to a ::khui_alert object.
+
+ \note the ::khui_alert object will be released when the queued
+ messages are displayed.
+ */
+#define KMSG_ALERT_SHOW_MODAL 5
+
+/*@}*/
+
+/*! \defgroup kmq_msg_ident KMSG_IDENT Subtypes
+ @{*/
+
+/*! \brief Initialize and start the identity provider
+
+
+ Sent by the KCDB to notify the identity provider that it is now
+ the current identity provider.
+
+ Note that unlike regular plugins, an identity provider can be
+ loaded and inert (not provide any services). Also, the user may
+ switch between multiple identity providers on the fly.
+ */
+#define KMSG_IDENT_INIT 1
+
+/*! \brief Stop the identity provider
+
+ Sent by the KCDB as notificaton that the identity provider is no
+ longer the current provider.
+ */
+#define KMSG_IDENT_EXIT 2
+
+/*! \brief Check if an identity name is valid
+
+ This message is sent to the identity provider to verify the syntax
+ of an identity name. Note that only the syntax of the name is to
+ be verfied and not the actual physical existence of said identity.
+
+ Message parameters:
+
+ - \b vparam : pointer to ::kcdb_ident_name_xfer object. The
+ name to be validated will be in the \a name_src member. The
+ buffer will be NULL terminated with a maximum limit of
+ KCDB_IDENT_MAXCCH_NAME characters including the terminating
+ NULL, consisting only of characters in KCDB_IDENT_VALID_CHARS
+ The \a result member should be set to one of the following
+ depending on the result of the validation:
+
+ - KHM_ERROR_SUCCESS : The name was valid
+ - KHM_ERROR_INVALID_NAME : The name was invalid
+ */
+#define KMSG_IDENT_VALIDATE_NAME 3
+
+/*! \brief Check if an identity is valid
+
+ Sent to the identity provider to verify the validity of the given
+ identity. The provider should verify that the identity exists and
+ is in a state where it can be actively used.
+
+ Depending on the result of the validation, the flags of the
+ identity should be updated.
+
+ Message parameters:
+ - \b vparam : Handle to an identity cast as a void pointer.
+ */
+#define KMSG_IDENT_VALIDATE_IDENTITY 4
+
+/*! \brief Canonicalize identity name
+
+ The identity provider will be given a name, which it should put in
+ canonical form, adjusting case and any character replacement or
+ doing any relevant expansions if applicable, and place it in the
+ supplied buffer.
+
+ Message parameters:
+
+ - \b vparam : Pointer to a ::kcdb_ident_name_xfer structure
+ which provides the identity name to canonicalize in the \a
+ name_src member, and the buffer to store the canonical name
+ in the \a name_dest member. The \a name_dest buffer is
+ guaranteed to be at least KCDB_IDENT_MAXCCH_NAME characters
+ in size.
+
+ If the name cannot be canonicalized for some reason, the
+ destination buffer should be set to a zero-length string and the
+ \a result member of the ::kcdb_ident_name_xfer structure should be
+ set to the error code. If the destination buffer is set to a
+ zero-length string and \a result is KHM_ERROR_SUCCESS, then the
+ original name provided in \a name_src is assumed to be already in
+ canonical form.
+ */
+#define KMSG_IDENT_CANON_NAME 5
+
+/*! \brief Compare names
+
+ Compare two identity names. The names that are given aren't
+ guaranteed to be in canonical form. The return value should be
+ akin to strcmp().
+
+ Message parameters:
+
+ - \b vparam : A pointer to a ::kcdb_ident_name_xfer structure.
+ The \a name_src member points at the first name, and the \a
+ name_alt member specifies the second name. The result of the
+ comparison should be place in \a result.
+ */
+#define KMSG_IDENT_COMPARE_NAME 6
+
+/*! \brief Set the default identity
+
+ Set or unset the default identity. To set the default identity,
+ the \a uparam parameter will be set to a non-zero value and a
+ handle to the identity will be specified in \a vparam. To unset
+ the default identity (i.e. not have a default identity), a zero
+ value will be specified in \a uparam and no identities will be
+ specified in \a vparam.
+
+ When setting a default identity, the identity provider will
+ receive this message prior to the ::KCDB_IDENT_FLAG_DEFAULT bit
+ being set or reset on any identity. It should return
+ KHM_ERROR_SUCCESS if the requested operation can be performed.
+ Returning any other value will abort the operation and will leave
+ the default identity unchanged.
+
+ When resetting the default identity, this message should be
+ treated only as a notification.
+
+ Message parameters:
+
+ - \a uparam : Is non-zero if an identity is being made default. If
+ this is zero, then identity should be the default.
+
+ - \a vparam : A handle to the identity to be made default if \a
+ uparam is non-zero. NULL otherwise.
+
+ Return value:
+
+ - KHM_ERROR_SUCCESS : The identity should be marked as default
+ - Any other value : The identity should not be marked as default
+
+ */
+#define KMSG_IDENT_SET_DEFAULT 7
+
+/*! \brief Set an identity as searchable
+
+ Set or reset the searchable bit on an identity. If the \a uparam
+ parameter is non-zero, then the searchable bit is being set.
+ Otherwise it is being reset. The identity provider should return
+ KHM_ERROR_SUCCESS in order to indicate that the identity should be
+ marked as searchable. Any other value will result in the
+ searchable bit being reset on the identity.
+
+ Message parameters:
+
+ - \a uparam : Is non-zero if the searchable bit is being set. Zero
+ otherwise.
+
+ - \a vparam : Handle to the identity
+
+ Return value:
+
+ - KHM_ERROR_SUCCESS: The identity should be marked as searchable
+ - Any other value : The identity should not be marked as default
+ */
+#define KMSG_IDENT_SET_SEARCHABLE 8
+
+/*! \brief Get information about an identity
+
+ */
+#define KMSG_IDENT_GET_INFO 9
+
+/*! \brief Enumerate known and accessible identities
+ */
+#define KMSG_IDENT_ENUM_KNOWN 10
+
+/*! \brief Update information about an identity
+ */
+#define KMSG_IDENT_UPDATE 11
+
+/*! \brief Retrieve the user interface callback function
+
+ When obtaining new credentials, the user interface needs to obtain
+ a callback function which will provide identity selection
+ controls.
+
+ Message parameters:
+
+ - \a uparam : Not used
+
+ - \a vparam : pointer to a ::khui_ident_new_creds_cb which will
+ receive the call back.
+ */
+#define KMSG_IDENT_GET_UI_CALLBACK 12
+
+/*! \brief Notification of the creation of an identity
+
+ This should be considered just a notification. The identit
+ provider does not have an opportunity to veto the creation of an
+ identity whose name has been found to be valid. However, when
+ handing this notification, the identity provider can:
+
+ - Change the flags of the identity and/or marking the identity as
+ invalid.
+
+ - Change the default identity.
+
+ Note that this notification is sent before the general :;KMSG_KCDB
+ notification of the identity creation is sent.
+
+ Message parameters:
+
+ - \a uparam : Not used.
+
+ - \p vparam : handle to the identity
+ */
+#define KMSG_IDENT_NOTIFY_CREATE 13
+
+/*@}*/ /* /KMSG_IDENT subtypes */
+
+/*@}*/ /* / message types */
+/*@}*/ /* / kmq */
+
+#endif
diff --git a/src/windows/identity/include/netidmgr.h b/src/windows/identity/include/netidmgr.h
index 94e188ff1c..cc680fcadc 100644
--- a/src/windows/identity/include/netidmgr.h
+++ b/src/windows/identity/include/netidmgr.h
@@ -1,43 +1,43 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#ifndef __NETIDMGR_H
-#define __NETIDMGR_H
-
-#include "khdefs.h"
-
-#include "utils.h"
-#include "khuidefs.h"
-#include "kmq.h"
-#include "khmsgtypes.h"
-#include "kcreddb.h"
-#include "kherr.h"
-#include "kherror.h"
-#include "kconfig.h"
-#include "kmm.h"
-#include "kplugin.h"
-
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __NETIDMGR_H
+#define __NETIDMGR_H
+
+#include "khdefs.h"
+
+#include "utils.h"
+#include "khuidefs.h"
+#include "kmq.h"
+#include "khmsgtypes.h"
+#include "kcreddb.h"
+#include "kherr.h"
+#include "kherror.h"
+#include "kconfig.h"
+#include "kmm.h"
+#include "kplugin.h"
+
+#endif
diff --git a/src/windows/identity/kconfig/api.c b/src/windows/identity/kconfig/api.c
index 60984358fb..6c7ac8e47c 100644
--- a/src/windows/identity/kconfig/api.c
+++ b/src/windows/identity/kconfig/api.c
@@ -1,2656 +1,2656 @@
-/*
-* Copyright (c) 2005 Massachusetts Institute of Technology
-*
-* Permission is hereby granted, free of charge, to any person
-* obtaining a copy of this software and associated documentation
-* files (the "Software"), to deal in the Software without
-* restriction, including without limitation the rights to use, copy,
-* modify, merge, publish, distribute, sublicense, and/or sell copies
-* of the Software, and to permit persons to whom the Software is
-* furnished to do so, subject to the following conditions:
-*
-* The above copyright notice and this permission notice shall be
-* included in all copies or substantial portions of the Software.
-*
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
-* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
-* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-* SOFTWARE.
-*/
-
-/* $Id$ */
-
-#include<shlwapi.h>
-#include<kconfiginternal.h>
-#include<netidmgr_intver.h>
-#include<assert.h>
-
-kconf_conf_space * conf_root = NULL;
-kconf_handle * conf_handles = NULL;
-kconf_handle * conf_free_handles = NULL;
-
-CRITICAL_SECTION cs_conf_global;
-CRITICAL_SECTION cs_conf_handle;
-LONG conf_init = 0;
-LONG conf_status = 0;
-
-void init_kconf(void) {
- if(InterlockedIncrement(&conf_init) == 1L) {
- /* we are the first */
- InitializeCriticalSection(&cs_conf_global);
- EnterCriticalSection(&cs_conf_global);
- conf_root = khcint_create_empty_space();
- conf_root->name = PWCSDUP(L"Root");
- conf_root->regpath = PWCSDUP(CONFIG_REGPATHW);
- conf_root->refcount++;
- conf_status = 1;
- InitializeCriticalSection(&cs_conf_handle);
- LeaveCriticalSection(&cs_conf_global);
- }
- /* else assume we are already initialized */
-}
-
-void exit_kconf(void) {
- if(khc_is_config_running()) {
- kconf_handle * h;
-
- EnterCriticalSection(&cs_conf_global);
-
- conf_init = 0;
- conf_status = 0;
-
- khcint_free_space(conf_root);
-
- LeaveCriticalSection(&cs_conf_global);
- DeleteCriticalSection(&cs_conf_global);
-
- EnterCriticalSection(&cs_conf_handle);
- while(conf_free_handles) {
- LPOP(&conf_free_handles, &h);
- if(h) {
- PFREE(h);
- }
- }
-
- while(conf_handles) {
- LPOP(&conf_handles, &h);
- if(h) {
- PFREE(h);
- }
- }
- LeaveCriticalSection(&cs_conf_handle);
- DeleteCriticalSection(&cs_conf_handle);
- }
-}
-
-#if defined(DEBUG) && (defined(KH_BUILD_PRIVATE) || defined(KH_BUILD_SPECIAL))
-
-#include<stdio.h>
-
-static void
-khcint_dump_space(FILE * f, kconf_conf_space * sp) {
-
- kconf_conf_space * sc;
-
- fprintf(f, "c12\t[%S]\t[%S]\t%d\t0x%x\tWin(%s|%s)|%s\n",
- ((sp->regpath) ? sp->regpath : L"!No Reg path"),
- sp->name,
- (int) sp->refcount,
- (int) sp->flags,
- ((sp->regkey_user)? "HKCU" : ""),
- ((sp->regkey_machine)? "HKLM" : ""),
- ((sp->schema)? "Schema" : ""));
-
-
- sc = TFIRSTCHILD(sp);
- while(sc) {
-
- khcint_dump_space(f, sc);
-
- sc = LNEXT(sc);
- }
-}
-
-KHMEXP void KHMAPI
-khcint_dump_handles(FILE * f) {
- if (khc_is_config_running()) {
- kconf_handle * h, * sh;
-
- EnterCriticalSection(&cs_conf_handle);
- EnterCriticalSection(&cs_conf_global);
-
- fprintf(f, "c00\t*** Active handles ***\n");
- fprintf(f, "c01\tHandle\tName\tFlags\tRegpath\n");
-
- h = conf_handles;
- while(h) {
- kconf_conf_space * sp;
-
- sp = h->space;
-
- if (!khc_is_handle(h) || sp == NULL) {
-
- fprintf(f, "c02\t!!INVALID HANDLE!!\n");
-
- } else {
-
- fprintf(f, "c02\t0x%p\t[%S]\t0x%x\t[%S]\n",
- h,
- sp->name,
- h->flags,
- sp->regpath);
-
- sh = khc_shadow(h);
-
- while(sh) {
-
- sp = sh->space;
-
- if (!khc_is_handle(sh) || sp == NULL) {
-
- fprintf(f, "c02\t0x%p:Shadow:0x%p\t[!!INVALID HANDLE!!]\n",
- h, sh);
-
- } else {
-
- fprintf(f, "c02\t0x%p:Shadow:0x%p,[%S]\t0x%x\t[%S]\n",
- h, sh,
- sp->name,
- sh->flags,
- sp->regpath);
-
- }
-
- sh = khc_shadow(sh);
- }
-
- }
-
- h = LNEXT(h);
- }
-
- fprintf(f, "c03\t------ End ---------\n");
-
- fprintf(f, "c10\t*** Active Configuration Spaces ***\n");
- fprintf(f, "c11\tReg path\tName\tRefcount\tFlags\tLayers\n");
-
- khcint_dump_space(f, conf_root);
-
- fprintf(f, "c13\t------ End ---------\n");
-
- LeaveCriticalSection(&cs_conf_global);
- LeaveCriticalSection(&cs_conf_handle);
-
- } else {
- fprintf(f, "c00\t------- KHC Configuration not running -------\n");
- }
-}
-
-#endif
-
-/* obtains cs_conf_handle/cs_conf_global */
-kconf_handle *
-khcint_handle_from_space(kconf_conf_space * s, khm_int32 flags)
-{
- kconf_handle * h;
-
- EnterCriticalSection(&cs_conf_handle);
- LPOP(&conf_free_handles, &h);
- if(!h) {
- h = PMALLOC(sizeof(kconf_handle));
- assert(h != NULL);
- }
- ZeroMemory((void *) h, sizeof(kconf_handle));
-
- h->magic = KCONF_HANDLE_MAGIC;
- khcint_space_hold(s);
- h->space = s;
- h->flags = flags;
-
- LPUSH(&conf_handles, h);
- LeaveCriticalSection(&cs_conf_handle);
-
- return h;
-}
-
-/* obtains cs_conf_handle/cs_conf_global */
-void
-khcint_handle_free(kconf_handle * h)
-{
- kconf_handle * lower;
-
- EnterCriticalSection(&cs_conf_handle);
-#ifdef DEBUG
- /* check if the handle is actually in use */
- {
- kconf_handle * a;
- a = conf_handles;
- while(a) {
- if(h == a)
- break;
- a = LNEXT(a);
- }
-
- if(a == NULL) {
- DebugBreak();
-
- /* hmm. the handle was not in the in-use list */
- LeaveCriticalSection(&cs_conf_handle);
- return;
- }
- }
-#endif
- while(h) {
- LDELETE(&conf_handles, h);
- if(h->space) {
- khcint_space_release(h->space);
- h->space = NULL;
- }
- lower = h->lower;
- h->magic = 0;
- LPUSH(&conf_free_handles, h);
- h = lower;
- }
- LeaveCriticalSection(&cs_conf_handle);
-}
-
-/* obains cs_conf_handle/cs_conf_global */
-kconf_handle *
-khcint_handle_dup(kconf_handle * o)
-{
- kconf_handle * h;
- kconf_handle * r;
-
- r = khcint_handle_from_space(o->space, o->flags);
- h = r;
-
- while(o->lower) {
- h->lower = khcint_handle_from_space(o->lower->space, o->lower->flags);
-
- o = o->lower;
- h = h->lower;
- }
-
- return r;
-}
-
-/* obtains cs_conf_global */
-void
-khcint_space_hold(kconf_conf_space * s) {
- EnterCriticalSection(&cs_conf_global);
- s->refcount ++;
- LeaveCriticalSection(&cs_conf_global);
-}
-
-/* called with cs_conf_global */
-void
-khcint_try_free_space(kconf_conf_space * s) {
-
- if (TFIRSTCHILD(s) == NULL &&
- s->refcount == 0 &&
- s->schema == NULL) {
-
- kconf_conf_space * p;
-
- p = TPARENT(s);
-
- if (p == NULL)
- return;
-
- TDELCHILD(p, s);
-
- khcint_free_space(s);
-
- khcint_try_free_space(p);
- }
-}
-
-/* obtains cs_conf_global */
-void
-khcint_space_release(kconf_conf_space * s) {
- khm_int32 l;
-
- EnterCriticalSection(&cs_conf_global);
-
- l = -- s->refcount;
- if (l == 0) {
- if(s->regkey_machine)
- RegCloseKey(s->regkey_machine);
- if(s->regkey_user)
- RegCloseKey(s->regkey_user);
- s->regkey_machine = NULL;
- s->regkey_user = NULL;
-
- if (s->flags &
- (KCONF_SPACE_FLAG_DELETE_M |
- KCONF_SPACE_FLAG_DELETE_U)) {
- khcint_remove_space(s, s->flags);
- } else {
-#ifdef USE_TRY_FREE
- /* even if the refcount is zero, we shouldn't free a
- configuration space just yet since that doesn't play
- well with the configuration space enumeration mechanism
- which expects the spaces to dangle around if there is a
- corresponding registry key or schema. */
- khcint_try_free_space(s);
-#endif
- }
- }
-
- LeaveCriticalSection(&cs_conf_global);
-}
-
-/* case sensitive replacement for RegOpenKeyEx */
-LONG
-khcint_RegOpenKeyEx(HKEY hkey, LPCWSTR sSubKey, DWORD ulOptions,
- REGSAM samDesired, PHKEY phkResult) {
- int i;
- wchar_t sk_name[KCONF_MAXCCH_NAME];
- FILETIME ft;
- size_t cch;
- HKEY hkp = NULL;
- const wchar_t * t;
- LONG rv = ERROR_SUCCESS;
-
- hkp = hkey;
- t = sSubKey;
-
- /* check for case insensitive prefix first */
- if (!_wcsnicmp(sSubKey, CONFIG_REGPATHW, ARRAYLENGTH(CONFIG_REGPATHW) - 1)) {
- HKEY hkt;
-
- t = sSubKey + (ARRAYLENGTH(CONFIG_REGPATHW) - 1);
-
-#ifdef DEBUG
- assert(*t == L'\0' || *t == L'\\');
-#endif
-
- rv = RegOpenKeyEx(hkp,
- CONFIG_REGPATHW,
- ulOptions,
- samDesired,
- &hkt);
-
- if (rv != ERROR_SUCCESS)
- return rv;
-
- if (*t == L'\0') {
- *phkResult = hkt;
- return rv;
- }
-
- t++;
- hkp = hkt;
- }
-
- /* descend down the components of the subkey */
- while(TRUE) {
- wchar_t * slash;
- HKEY hkt;
-
- slash = wcschr(t, L'\\');
- if (slash == NULL)
- break;
-
- if (FAILED(StringCchCopyN(sk_name, ARRAYLENGTH(sk_name),
- t, slash - t))) {
- rv = ERROR_CANTOPEN;
- goto _cleanup;
- }
-
- sk_name[slash - t] = L'\0';
- t = slash+1;
-
- if (khcint_RegOpenKeyEx(hkp, sk_name, ulOptions, samDesired, &hkt) ==
- ERROR_SUCCESS) {
-
- if (hkp != hkey)
- RegCloseKey(hkp);
- hkp = hkt;
-
- } else {
-
- rv = ERROR_CANTOPEN;
- goto _cleanup;
-
- }
- }
-
- /* by now hkp is a handle to the parent of the last component in
- the subkey. t is a pointer to the last component. */
-
- if (FAILED(StringCchLength(t, KCONF_MAXCCH_NAME, &cch))) {
- rv = ERROR_CANTOPEN;
- goto _cleanup;
- }
-
- /* go through and find the case sensitive match for the key */
-
- for (i=0; ;i++) {
- LONG l;
- DWORD dw;
-
- dw = ARRAYLENGTH(sk_name);
- l = RegEnumKeyEx(hkp, i, sk_name, &dw,
- NULL, NULL, NULL, &ft);
-
- if (l != ERROR_SUCCESS) {
- rv = ERROR_CANTOPEN;
- goto _cleanup;
- }
-
- if (!(wcsncmp(sk_name, t, cch))) {
- /* bingo! ?? */
- if (cch < KCONF_MAXCCH_NAME &&
- (sk_name[cch] == L'\0' ||
- sk_name[cch] == L'~')) {
- rv = RegOpenKeyEx(hkp, sk_name, ulOptions,
- samDesired, phkResult);
- goto _cleanup;
- }
- }
- }
-
- _cleanup:
- if (hkp != hkey && hkp != NULL)
- RegCloseKey(hkp);
-
- return rv;
-}
-
-/*! \internal
-
- \note This function is not a good replacement for RegDeleteKey since
- it deletes all the subkeys in addition to the key being deleted.
- */
-LONG
-khcint_RegDeleteKey(HKEY hKey,
- LPCWSTR lpSubKey) {
- int i;
- wchar_t sk_name[KCONF_MAXCCH_NAME];
- FILETIME ft;
- size_t cch;
- LONG rv = ERROR_SUCCESS;
-
- /* go through and find the case sensitive match for the key */
-
- if (FAILED(StringCchLength(lpSubKey, KCONF_MAXCCH_NAME, &cch)))
- return ERROR_BADKEY;
-
- for (i=0; ;i++) {
- LONG l;
- DWORD dw;
-
- dw = ARRAYLENGTH(sk_name);
- l = RegEnumKeyEx(hKey, i, sk_name, &dw,
- NULL, NULL, NULL, &ft);
-
- if (l != ERROR_SUCCESS) {
- rv = ERROR_BADKEY;
- goto _cleanup;
- }
-
- if (!(wcsncmp(sk_name, lpSubKey, cch))) {
- /* bingo! ?? */
- if ((sk_name[cch] == L'\0' ||
- sk_name[cch] == L'~')) {
-
- /* instead of calling RegDeleteKey we call SHDeleteKey
- because we want to blow off all the subkeys as
- well. This is different from the behavior of
- RegDeleteKey making khcint_RegDeleteKey not a very
- good case sensitive replacement for
- RegDeleteKey. */
-
- rv = SHDeleteKey(hKey, sk_name);
- goto _cleanup;
- }
- }
- }
-
- _cleanup:
- return rv;
-}
-
-LONG
-khcint_RegCreateKeyEx(HKEY hKey,
- LPCWSTR lpSubKey,
- DWORD Reserved,
- LPWSTR lpClass,
- DWORD dwOptions,
- REGSAM samDesired,
- LPSECURITY_ATTRIBUTES lpSecurityAttributes,
- PHKEY phkResult,
- LPDWORD lpdwDisposition) {
- LONG l;
- int i;
- long index = 0;
- wchar_t sk_name[KCONF_MAXCCH_NAME]; /* hard limit in Windows */
- FILETIME ft;
- size_t cch;
- const wchar_t * t;
- LONG rv = ERROR_SUCCESS;
- HKEY hkp = NULL;
-
- hkp = hKey;
- t = lpSubKey;
-
- /* check for case insensitive prefix first */
- if (!_wcsnicmp(lpSubKey, CONFIG_REGPATHW, ARRAYLENGTH(CONFIG_REGPATHW) - 1)) {
- HKEY hkt;
-
- t = lpSubKey + (ARRAYLENGTH(CONFIG_REGPATHW) - 1);
-
-#ifdef DEBUG
- assert(*t == L'\0' || *t == L'\\');
-#endif
-
- rv = RegCreateKeyEx(hkp,
- CONFIG_REGPATHW,
- Reserved,
- lpClass,
- dwOptions,
- samDesired,
- lpSecurityAttributes,
- &hkt,
- lpdwDisposition);
-
- if (rv != ERROR_SUCCESS)
- return rv;
-
- if (*t == L'\0') {
- *phkResult = hkt;
- return rv;
- }
-
- t++;
- hkp = hkt;
- }
-
- while(TRUE) {
- wchar_t * slash;
- HKEY hkt;
-
- slash = wcschr(t, L'\\');
- if (slash == NULL)
- break;
-
- if (FAILED(StringCchCopyN(sk_name, ARRAYLENGTH(sk_name),
- t, slash - t))) {
- rv = ERROR_CANTOPEN;
- goto _cleanup;
- }
-
- sk_name[slash - t] = L'\0';
- t = slash+1;
-
- if (khcint_RegOpenKeyEx(hkp, sk_name, 0, samDesired, &hkt) ==
- ERROR_SUCCESS) {
-
- if (hkp != hKey)
- RegCloseKey(hkp);
- hkp = hkt;
- } else {
-
- rv = RegCreateKeyEx(hKey,
- lpSubKey,
- Reserved,
- lpClass,
- dwOptions,
- samDesired,
- lpSecurityAttributes,
- phkResult,
- lpdwDisposition);
- goto _cleanup;
- }
- }
-
- if (FAILED(StringCchLength(t, KCONF_MAXCCH_NAME, &cch))) {
- rv = ERROR_CANTOPEN;
- goto _cleanup;
- }
-
- for (i=0; ;i++) {
- DWORD dw;
-
- dw = ARRAYLENGTH(sk_name);
- l = RegEnumKeyEx(hkp, i, sk_name, &dw,
- NULL, NULL, NULL, &ft);
-
- if (l != ERROR_SUCCESS)
- break;
-
- if (!(wcsncmp(sk_name, t, cch))) {
- /* bingo! ?? */
- if (sk_name[cch] == L'\0' ||
- sk_name[cch] == L'~') {
- l = RegOpenKeyEx(hkp, sk_name, 0,
- samDesired, phkResult);
- if (l == ERROR_SUCCESS && lpdwDisposition)
- *lpdwDisposition = REG_OPENED_EXISTING_KEY;
- rv = l;
- goto _cleanup;
- }
- }
-
- if (!_wcsnicmp(sk_name, t, cch) &&
- (sk_name[cch] == L'\0' ||
- sk_name[cch] == L'~')) {
- long new_idx;
-
- if (sk_name[cch] == L'\0')
- new_idx = 1;
- else if (cch + 1 < KCONF_MAXCCH_NAME)
- new_idx = wcstol(sk_name + (cch + 1), NULL, 10);
- else
- return ERROR_BUFFER_OVERFLOW;
-
- assert(new_idx > 0);
-
- if (new_idx > index)
- index = new_idx;
- }
- }
-
- if (index != 0) {
- if (FAILED(StringCbPrintf(sk_name, sizeof(sk_name),
- L"%s~%d", t, index)))
- return ERROR_BUFFER_OVERFLOW;
- } else {
- StringCbCopy(sk_name, sizeof(sk_name), t);
- }
-
- rv = RegCreateKeyEx(hkp,
- sk_name,
- Reserved,
- lpClass,
- dwOptions,
- samDesired,
- lpSecurityAttributes,
- phkResult,
- lpdwDisposition);
-
- _cleanup:
-
- if (hkp != hKey && hkp != NULL)
- RegCloseKey(hkp);
-
- return rv;
-}
-
-/* obtains cs_conf_global */
-HKEY
-khcint_space_open_key(kconf_conf_space * s, khm_int32 flags) {
- HKEY hk = NULL;
- int nflags = 0;
- DWORD disp;
- if(flags & KCONF_FLAG_MACHINE) {
- if(s->regkey_machine)
- return s->regkey_machine;
- if((khcint_RegOpenKeyEx(HKEY_LOCAL_MACHINE, s->regpath, 0,
- KEY_READ | KEY_WRITE, &hk) !=
- ERROR_SUCCESS) &&
- !(flags & KHM_PERM_WRITE)) {
-
- if(khcint_RegOpenKeyEx(HKEY_LOCAL_MACHINE, s->regpath, 0,
- KEY_READ, &hk) == ERROR_SUCCESS) {
- nflags = KHM_PERM_READ;
- }
-
- }
- if(!hk && (flags & KHM_FLAG_CREATE)) {
-
- khcint_RegCreateKeyEx(HKEY_LOCAL_MACHINE,
- s->regpath,
- 0,
- NULL,
- REG_OPTION_NON_VOLATILE,
- KEY_READ | KEY_WRITE,
- NULL,
- &hk,
- &disp);
- }
- if(hk) {
- EnterCriticalSection(&cs_conf_global);
- s->regkey_machine = hk;
- s->regkey_machine_flags = nflags;
- LeaveCriticalSection(&cs_conf_global);
- }
-
- return hk;
- } else {
- if(s->regkey_user)
- return s->regkey_user;
- if((khcint_RegOpenKeyEx(HKEY_CURRENT_USER, s->regpath, 0,
- KEY_READ | KEY_WRITE, &hk) !=
- ERROR_SUCCESS) &&
- !(flags & KHM_PERM_WRITE)) {
- if(khcint_RegOpenKeyEx(HKEY_CURRENT_USER, s->regpath, 0,
- KEY_READ, &hk) == ERROR_SUCCESS) {
- nflags = KHM_PERM_READ;
- }
- }
- if(!hk && (flags & KHM_FLAG_CREATE)) {
- khcint_RegCreateKeyEx(HKEY_CURRENT_USER,
- s->regpath, 0, NULL,
- REG_OPTION_NON_VOLATILE,
- KEY_READ | KEY_WRITE,
- NULL, &hk, &disp);
- }
- if(hk) {
- EnterCriticalSection(&cs_conf_global);
- s->regkey_user = hk;
- s->regkey_user_flags = nflags;
- LeaveCriticalSection(&cs_conf_global);
- }
-
- return hk;
- }
-}
-
-/* obtains cs_conf_handle/cs_conf_global */
-KHMEXP khm_int32 KHMAPI
-khc_shadow_space(khm_handle upper, khm_handle lower)
-{
- kconf_handle * h;
-
- if(!khc_is_config_running())
- return KHM_ERROR_NOT_READY;
-
- if(!khc_is_handle(upper)) {
-#ifdef DEBUG
- DebugBreak();
-#endif
- return KHM_ERROR_INVALID_PARAM;
- }
-
- h = (kconf_handle *) upper;
-
- EnterCriticalSection(&cs_conf_handle);
- if(h->lower) {
- EnterCriticalSection(&cs_conf_global);
- khcint_handle_free(h->lower);
- LeaveCriticalSection(&cs_conf_global);
- h->lower = NULL;
- }
-
- if(khc_is_handle(lower)) {
- kconf_handle * l;
- kconf_handle * lc;
-
- l = (kconf_handle *) lower;
- lc = khcint_handle_dup(l);
- h->lower = lc;
- }
- LeaveCriticalSection(&cs_conf_handle);
-
- return KHM_ERROR_SUCCESS;
-}
-
-/* no locks */
-kconf_conf_space *
-khcint_create_empty_space(void) {
- kconf_conf_space * r;
-
- r = PMALLOC(sizeof(kconf_conf_space));
- assert(r != NULL);
- ZeroMemory(r,sizeof(kconf_conf_space));
-
- return r;
-}
-
-/* called with cs_conf_global */
-void
-khcint_free_space(kconf_conf_space * r) {
- kconf_conf_space * c;
-
- if(!r)
- return;
-
- TPOPCHILD(r, &c);
- while(c) {
- khcint_free_space(c);
- TPOPCHILD(r, &c);
- }
-
- if(r->name)
- PFREE(r->name);
-
- if(r->regpath)
- PFREE(r->regpath);
-
- if(r->regkey_machine)
- RegCloseKey(r->regkey_machine);
-
- if(r->regkey_user)
- RegCloseKey(r->regkey_user);
-
- PFREE(r);
-}
-
-/* obtains cs_conf_global */
-khm_int32
-khcint_open_space(kconf_conf_space * parent,
- const wchar_t * sname, size_t n_sname,
- khm_int32 flags, kconf_conf_space **result) {
- kconf_conf_space * p;
- kconf_conf_space * c;
- HKEY pkey = NULL;
- HKEY ckey = NULL;
- wchar_t buf[KCONF_MAXCCH_NAME];
- size_t cb_regpath = 0;
-
- if(!parent)
- p = conf_root;
- else
- p = parent;
-
- if(n_sname >= KCONF_MAXCCH_NAME || n_sname <= 0)
- return KHM_ERROR_INVALID_PARAM;
-
- StringCchCopyN(buf, ARRAYLENGTH(buf), sname, n_sname);
-
- /* see if there is already a config space by this name. if so,
- return it. Note that if the configuration space is specified
- in a schema, we would find it here. */
- EnterCriticalSection(&cs_conf_global);
- c = TFIRSTCHILD(p);
- while(c) {
- if(c->name && !wcscmp(c->name, buf))
- break;
-
- c = LNEXT(c);
- }
- LeaveCriticalSection(&cs_conf_global);
-
- if(c) {
-
- if (c->flags & KCONF_SPACE_FLAG_DELETED) {
- if (flags & KHM_FLAG_CREATE) {
- c->flags &= ~(KCONF_SPACE_FLAG_DELETED |
- KCONF_SPACE_FLAG_DELETE_M |
- KCONF_SPACE_FLAG_DELETE_U);
- } else {
- *result = NULL;
- return KHM_ERROR_NOT_FOUND;
- }
- }
-
- khcint_space_hold(c);
- *result = c;
- return KHM_ERROR_SUCCESS;
- }
-
- if(!(flags & KHM_FLAG_CREATE)) {
-
- /* we are not creating the space, so it must exist in the form of a
- registry key in HKLM or HKCU. If it existed as a schema, we
- would have already retured it above. */
-
- if (flags & KCONF_FLAG_USER)
- pkey = khcint_space_open_key(p, KHM_PERM_READ | KCONF_FLAG_USER);
-
- if((!pkey ||
- (khcint_RegOpenKeyEx(pkey, buf, 0, KEY_READ, &ckey) !=
- ERROR_SUCCESS))
- && (flags & KCONF_FLAG_MACHINE)) {
-
- pkey = khcint_space_open_key(p, KHM_PERM_READ | KCONF_FLAG_MACHINE);
- if(!pkey ||
- (khcint_RegOpenKeyEx(pkey, buf, 0, KEY_READ, &ckey) !=
- ERROR_SUCCESS)) {
- *result = NULL;
-
- return KHM_ERROR_NOT_FOUND;
- }
- }
-
- if(ckey) {
- RegCloseKey(ckey);
- ckey = NULL;
- }
- }
-
- c = khcint_create_empty_space();
-
- /*SAFE: buf: is of known length < KCONF_MAXCCH_NAME */
- c->name = PWCSDUP(buf);
-
- /*SAFE: p->regpath: is valid since it was set using this same
- function. */
- /*SAFE: buf: see above */
- cb_regpath = (wcslen(p->regpath) + wcslen(buf) + 2) * sizeof(wchar_t);
- c->regpath = PMALLOC(cb_regpath);
-
- assert(c->regpath != NULL);
-
- /*SAFE: c->regpath: allocated above to be big enough */
- /*SAFE: p->regpath: see above */
- StringCbCopy(c->regpath, cb_regpath, p->regpath);
- StringCbCat(c->regpath, cb_regpath, L"\\");
-
- /*SAFE: buf: see above */
- StringCbCat(c->regpath, cb_regpath, buf);
-
- khcint_space_hold(c);
-
- EnterCriticalSection(&cs_conf_global);
- TADDCHILD(p,c);
- LeaveCriticalSection(&cs_conf_global);
-
- *result = c;
- return KHM_ERROR_SUCCESS;
-}
-
-/* obtains cs_conf_handle/cs_conf_global */
-KHMEXP khm_int32 KHMAPI
-khc_open_space(khm_handle parent, const wchar_t * cspace, khm_int32 flags,
- khm_handle * result) {
- kconf_handle * h;
- kconf_conf_space * p;
- kconf_conf_space * c = NULL;
- size_t cbsize;
- const wchar_t * str;
- khm_int32 rv = KHM_ERROR_SUCCESS;
-
- if(!khc_is_config_running()) {
- return KHM_ERROR_NOT_READY;
- }
-
- if(!result || (parent && !khc_is_handle(parent))) {
-#ifdef DEBUG
- DebugBreak();
-#endif
- return KHM_ERROR_INVALID_PARAM;
- }
-
- if(!parent)
- p = conf_root;
- else {
- h = (kconf_handle *) parent;
- p = khc_space_from_handle(parent);
- }
-
- khcint_space_hold(p);
-
- /* if none of these flags are specified, make it seem like all of
- them were */
- if(!(flags & KCONF_FLAG_USER) &&
- !(flags & KCONF_FLAG_MACHINE) &&
- !(flags & KCONF_FLAG_SCHEMA))
- flags |= KCONF_FLAG_USER | KCONF_FLAG_MACHINE | KCONF_FLAG_SCHEMA;
-
- if(cspace == NULL) {
- *result = (khm_handle) khcint_handle_from_space(p, flags);
- khcint_space_release(p);
- return KHM_ERROR_SUCCESS;
- }
-
- if(FAILED(StringCbLength(cspace, KCONF_MAXCB_PATH, &cbsize))) {
- khcint_space_release(p);
- *result = NULL;
- return KHM_ERROR_INVALID_PARAM;
- }
-
- str = cspace;
- while(TRUE) {
- const wchar_t * end = NULL;
-
- if (!(flags & KCONF_FLAG_NOPARSENAME)) {
-
- end = wcschr(str, L'\\'); /* safe because cspace was
- validated above */
- }
-
- if(!end) {
- if(flags & KCONF_FLAG_TRAILINGVALUE) {
- /* we are at the value component */
- c = p;
- khcint_space_hold(c);
- break;
- } else
- end = str + wcslen(str); /* safe because cspace was
- validated above */
- }
-
- rv = khcint_open_space(p, str, end - str, flags, &c);
-
- if(KHM_SUCCEEDED(rv) && (*end == L'\\')) {
- khcint_space_release(p);
- p = c;
- c = NULL;
- str = end+1;
- }
- else
- break;
- }
-
- khcint_space_release(p);
- if(KHM_SUCCEEDED(rv)) {
- *result = khcint_handle_from_space(c, flags);
- } else
- *result = NULL;
-
- if (c)
- khcint_space_release(c);
-
- return rv;
-}
-
-/* obtains cs_conf_handle/cs_conf_global */
-KHMEXP khm_int32 KHMAPI
-khc_close_space(khm_handle csp) {
- if(!khc_is_config_running())
- return KHM_ERROR_NOT_READY;
-
- if(!khc_is_handle(csp)) {
-#ifdef DEBUG
- DebugBreak();
-#endif
- return KHM_ERROR_INVALID_PARAM;
- }
-
- khcint_handle_free((kconf_handle *) csp);
- return KHM_ERROR_SUCCESS;
-}
-
-/* obtains cs_conf_handle/cs_conf_global */
-KHMEXP khm_int32 KHMAPI
-khc_read_string(khm_handle pconf,
- const wchar_t * pvalue,
- wchar_t * buf,
- khm_size * bufsize)
-{
- kconf_conf_space * c;
- khm_int32 rv = KHM_ERROR_SUCCESS;
-
- if(!khc_is_config_running())
- return KHM_ERROR_NOT_READY;
-
- do {
- HKEY hku = NULL;
- HKEY hkm = NULL;
- const wchar_t * value = NULL;
- int free_space = 0;
- khm_handle conf = NULL;
- DWORD size;
- DWORD type;
- LONG hr;
-
- int i;
-
- if((value = wcsrchr(pvalue, L'\\')) != NULL) {
-
- if(KHM_FAILED(khc_open_space(
- pconf,
- pvalue,
- KCONF_FLAG_TRAILINGVALUE | (pconf?khc_handle_flags(pconf):0),
- &conf)))
- goto _shadow;
-
- free_space = 1;
-
- if (value) {
- value++;
- } else {
-#ifdef DEBUG
- assert(FALSE);
-#endif
- }
- } else {
- value = pvalue;
- conf = pconf;
- free_space = 0;
- }
-
- if(!khc_is_handle(conf))
- goto _shadow;
-
- c = khc_space_from_handle(conf);
-
- if(khc_is_user_handle(conf))
- hku = khcint_space_open_key(c, KHM_PERM_READ);
-
- if(khc_is_machine_handle(conf))
- hkm = khcint_space_open_key(c, KHM_PERM_READ | KCONF_FLAG_MACHINE);
-
- size = (DWORD) *bufsize;
- if(hku) {
- hr = RegQueryValueEx(hku, value, NULL, &type, (LPBYTE) buf, &size);
- if(hr == ERROR_SUCCESS) {
- if(type != REG_SZ) {
- rv = KHM_ERROR_TYPE_MISMATCH;
- goto _exit;
- }
- else {
- *bufsize = size;
- /* if buf==NULL, RegQueryValueEx will return success and just return the
- required buffer size in 'size' */
- rv = (buf)? KHM_ERROR_SUCCESS: KHM_ERROR_TOO_LONG;
- goto _exit;
- }
- } else {
- if(hr == ERROR_MORE_DATA) {
- *bufsize = size;
- rv = KHM_ERROR_TOO_LONG;
- goto _exit;
- }
- }
- }
-
- size = (DWORD) *bufsize;
- if(hkm) {
- hr = RegQueryValueEx(hkm, value, NULL, &type, (LPBYTE) buf, &size);
- if(hr == ERROR_SUCCESS) {
- if(type != REG_SZ) {
- rv = KHM_ERROR_TYPE_MISMATCH;
- goto _exit;
- }
- else {
- *bufsize = size;
- rv = (buf)? KHM_ERROR_SUCCESS: KHM_ERROR_TOO_LONG;
- goto _exit;
- }
- } else {
- if(hr == ERROR_MORE_DATA) {
- *bufsize = size;
- rv = KHM_ERROR_TOO_LONG;
- goto _exit;
- }
- }
- }
-
- if(c->schema && khc_is_schema_handle(conf)) {
- for(i=0;i<c->nSchema;i++) {
- if(c->schema[i].type == KC_STRING && !wcscmp(value, c->schema[i].name)) {
- /* found it */
- size_t cbsize = 0;
-
- if(!c->schema[i].value) {
- rv = KHM_ERROR_NOT_FOUND;
- goto _exit;
- }
-
- if(FAILED(StringCbLength((wchar_t *) c->schema[i].value, KCONF_MAXCB_STRING, &cbsize))) {
- rv = KHM_ERROR_NOT_FOUND;
- goto _exit;
- }
- cbsize += sizeof(wchar_t);
-
- if(!buf || *bufsize < cbsize) {
- *bufsize = cbsize;
- rv = KHM_ERROR_TOO_LONG;
- goto _exit;
- }
-
- StringCbCopy(buf, *bufsize, (wchar_t *) c->schema[i].value);
- *bufsize = cbsize;
- rv = KHM_ERROR_SUCCESS;
- goto _exit;
- }
- }
- }
-
-_shadow:
- if(free_space && conf)
- khc_close_space(conf);
-
- if(khc_is_shadowed(pconf)) {
- pconf = khc_shadow(pconf);
- continue;
- } else {
- rv = KHM_ERROR_NOT_FOUND;
- break;
- }
-
-_exit:
- if(free_space && conf)
- khc_close_space(conf);
- break;
-
- } while(TRUE);
-
- return rv;
-}
-
-/* obtains cs_conf_handle/cs_conf_global */
-KHMEXP khm_int32 KHMAPI
-khc_read_int32(khm_handle pconf, const wchar_t * pvalue, khm_int32 * buf) {
- kconf_conf_space * c;
- khm_int32 rv = KHM_ERROR_SUCCESS;
-
- if(!khc_is_config_running())
- return KHM_ERROR_NOT_READY;
-
- if(!buf || !pvalue)
- return KHM_ERROR_INVALID_PARAM;
-
- do {
- DWORD size;
- DWORD type;
- LONG hr;
- HKEY hku = NULL;
- HKEY hkm = NULL;
-
- const wchar_t * value = NULL;
- int free_space = 0;
- khm_handle conf = NULL;
-
- int i;
-
- if((value = wcsrchr(pvalue, L'\\')) != NULL) {
- if(KHM_FAILED(khc_open_space(
- pconf,
- pvalue,
- KCONF_FLAG_TRAILINGVALUE | (pconf?khc_handle_flags(pconf):0),
- &conf)))
- goto _shadow;
- free_space = 1;
-
- if (value) {
- value++;
- } else {
-#ifdef DEBUG
- assert(FALSE);
-#endif
- }
- } else {
- value = pvalue;
- conf = pconf;
- free_space = 0;
- }
-
- if(!khc_is_handle(conf) || !buf)
- goto _shadow;
-
- c = khc_space_from_handle(conf);
-
- if(khc_is_user_handle(conf))
- hku = khcint_space_open_key(c, KHM_PERM_READ);
-
- if(khc_is_machine_handle(conf))
- hkm = khcint_space_open_key(c, KHM_PERM_READ | KCONF_FLAG_MACHINE);
-
- size = sizeof(DWORD);
- if(hku) {
- hr = RegQueryValueEx(hku, value, NULL, &type, (LPBYTE) buf, &size);
- if(hr == ERROR_SUCCESS) {
- if(type != REG_DWORD) {
- rv = KHM_ERROR_TYPE_MISMATCH;
- goto _exit;
- }
- else {
- rv = KHM_ERROR_SUCCESS;
- goto _exit;
- }
- }
- }
-
- size = sizeof(DWORD);
- if(hkm) {
- hr = RegQueryValueEx(hkm, value, NULL, &type, (LPBYTE) buf, &size);
- if(hr == ERROR_SUCCESS) {
- if(type != REG_DWORD) {
- rv= KHM_ERROR_TYPE_MISMATCH;
- goto _exit;
- }
- else {
- rv= KHM_ERROR_SUCCESS;
- goto _exit;
- }
- }
- }
-
- if(c->schema && khc_is_schema_handle(conf)) {
- for(i=0;i<c->nSchema;i++) {
- if(c->schema[i].type == KC_INT32 && !wcscmp(value, c->schema[i].name)) {
- *buf = (khm_int32) c->schema[i].value;
- rv = KHM_ERROR_SUCCESS;
- goto _exit;
- }
- }
- }
-_shadow:
- if(free_space && conf)
- khc_close_space(conf);
-
- if(khc_is_shadowed(pconf)) {
- pconf = khc_shadow(pconf);
- continue;
- } else {
- rv = KHM_ERROR_NOT_FOUND;
- break;
- }
-_exit:
- if(free_space && conf)
- khc_close_space(conf);
- break;
- }
- while(TRUE);
-
- return rv;
-}
-
-/* obtains cs_conf_handle/cs_conf_global */
-KHMEXP khm_int32 KHMAPI
-khc_read_int64(khm_handle pconf, const wchar_t * pvalue, khm_int64 * buf) {
- kconf_conf_space * c;
- khm_int32 rv = KHM_ERROR_SUCCESS;
-
- if(!khc_is_config_running())
- return KHM_ERROR_NOT_READY;
-
- do {
- DWORD size;
- DWORD type;
- LONG hr;
- HKEY hku = NULL;
- HKEY hkm = NULL;
-
- const wchar_t * value = NULL;
- int free_space = 0;
- khm_handle conf = NULL;
-
- int i;
-
- if((value = wcsrchr(pvalue, L'\\')) != NULL) {
- if(KHM_FAILED(khc_open_space(
- pconf,
- pvalue,
- KCONF_FLAG_TRAILINGVALUE | (pconf?khc_handle_flags(pconf):0),
- &conf)))
- goto _shadow;
- free_space = 1;
-
- if (value) {
- value++;
- } else {
-#ifdef DEBUG
- assert(FALSE);
-#endif
- }
- } else {
- value = pvalue;
- conf = pconf;
- free_space = 0;
- }
-
- if(!khc_is_handle(conf) || !buf)
- goto _shadow;
-
- c = khc_space_from_handle(conf);
-
- if(khc_is_user_handle(conf))
- hku = khcint_space_open_key(c, KHM_PERM_READ);
-
- if(khc_is_machine_handle(conf))
- hkm = khcint_space_open_key(c, KHM_PERM_READ | KCONF_FLAG_MACHINE);
-
- size = sizeof(khm_int64);
- if(hku) {
- hr = RegQueryValueEx(hku, value, NULL, &type, (LPBYTE) buf, &size);
- if(hr == ERROR_SUCCESS) {
- if(type != REG_QWORD) {
- rv= KHM_ERROR_TYPE_MISMATCH;
- goto _exit;
- }
- else {
- rv = KHM_ERROR_SUCCESS;
- goto _exit;
- }
- }
- }
-
- size = sizeof(khm_int64);
- if(hkm) {
- hr = RegQueryValueEx(hkm, value, NULL, &type, (LPBYTE) buf, &size);
- if(hr == ERROR_SUCCESS) {
- if(type != REG_QWORD) {
- rv = KHM_ERROR_TYPE_MISMATCH;
- goto _exit;
- }
- else {
- rv = KHM_ERROR_SUCCESS;
- goto _exit;
- }
- }
- }
-
- if(c->schema && khc_is_schema_handle(conf)) {
- for(i=0;i<c->nSchema;i++) {
- if(c->schema[i].type == KC_INT64 && !wcscmp(value, c->schema[i].name)) {
- *buf = (khm_int64) c->schema[i].value;
- rv = KHM_ERROR_SUCCESS;
- goto _exit;
- }
- }
- }
-
-_shadow:
- if(free_space && conf)
- khc_close_space(conf);
- if(khc_is_shadowed(pconf)) {
- pconf = khc_shadow(pconf);
- continue;
- } else {
- rv = KHM_ERROR_NOT_FOUND;
- break;
- }
-
-_exit:
- if(free_space && conf)
- khc_close_space(conf);
- break;
-
- } while(TRUE);
- return rv;
-}
-
-/* obtaincs cs_conf_handle/cs_conf_global */
-KHMEXP khm_int32 KHMAPI
-khc_read_binary(khm_handle pconf, const wchar_t * pvalue,
- void * buf, khm_size * bufsize) {
- kconf_conf_space * c;
- khm_int32 rv = KHM_ERROR_SUCCESS;
-
- if(!khc_is_config_running())
- return KHM_ERROR_NOT_READY;
-
- do {
- DWORD size;
- DWORD type;
- LONG hr;
- HKEY hku = NULL;
- HKEY hkm = NULL;
-
- const wchar_t * value = NULL;
- int free_space = 0;
- khm_handle conf = NULL;
-
- if((value = wcsrchr(pvalue, L'\\')) != NULL) {
- if(KHM_FAILED(khc_open_space(
- pconf,
- pvalue,
- KCONF_FLAG_TRAILINGVALUE | (pconf?khc_handle_flags(pconf):0),
- &conf)))
- goto _shadow;
- free_space = 1;
-
- if (value) {
- value++;
- } else {
-#ifdef DEBUG
- assert(FALSE);
-#endif
- }
- } else {
- value = pvalue;
- conf = pconf;
- free_space = 0;
- }
-
- if(!khc_is_handle(conf))
- goto _shadow;
-
- c = khc_space_from_handle(conf);
-
- if(khc_is_user_handle(conf))
- hku = khcint_space_open_key(c, KHM_PERM_READ);
-
- if(khc_is_machine_handle(conf))
- hkm = khcint_space_open_key(c, KHM_PERM_READ | KCONF_FLAG_MACHINE);
-
- size = (DWORD) *bufsize;
- if(hku) {
- hr = RegQueryValueEx(hku, value, NULL, &type, (LPBYTE) buf, &size);
- if(hr == ERROR_SUCCESS) {
- if(type != REG_BINARY) {
- rv = KHM_ERROR_TYPE_MISMATCH;
- goto _exit;
- }
- else {
- *bufsize = size;
- rv = KHM_ERROR_SUCCESS;
- goto _exit;
- }
- } else {
- if(hr == ERROR_MORE_DATA) {
- *bufsize = size;
- rv = KHM_ERROR_TOO_LONG;
- goto _exit;
- }
- }
- }
-
- size = (DWORD) *bufsize;
- if(hkm) {
- hr = RegQueryValueEx(hkm, value, NULL, &type, (LPBYTE) buf, &size);
- if(hr == ERROR_SUCCESS) {
- if(type != REG_BINARY) {
- rv = KHM_ERROR_TYPE_MISMATCH;
- goto _exit;
- }
- else {
- *bufsize = size;
- rv = KHM_ERROR_SUCCESS;
- goto _exit;
- }
- } else {
- if(hr == ERROR_MORE_DATA) {
- *bufsize = size;
- rv = KHM_ERROR_TOO_LONG;
- goto _exit;
- }
- }
- }
-
- /* binary values aren't supported in schema */
-_shadow:
- if(free_space && conf)
- khc_close_space(conf);
- if(khc_is_shadowed(pconf)) {
- pconf = khc_shadow(pconf);
- continue;
- } else {
- rv = KHM_ERROR_NOT_FOUND;
- break;
- }
-
-_exit:
- if(free_space && conf)
- khc_close_space(conf);
- break;
-
- }while (TRUE);
-
- return rv;
-}
-
-/* obtains cs_conf_handle/cs_conf_global */
-KHMEXP khm_int32 KHMAPI
-khc_write_string(khm_handle pconf,
- const wchar_t * pvalue,
- wchar_t * buf)
-{
- HKEY pk = NULL;
- kconf_conf_space * c;
- khm_int32 rv = KHM_ERROR_SUCCESS;
- LONG hr;
- size_t cbsize;
- const wchar_t * value = NULL;
- int free_space = 0;
- khm_handle conf = NULL;
-
-
- if(!khc_is_config_running())
- return KHM_ERROR_NOT_READY;
-
- if(pconf && !khc_is_machine_handle(pconf) && !khc_is_user_handle(pconf))
- return KHM_ERROR_INVALID_OPERATION;
-
- if(FAILED(StringCbLength(buf, KCONF_MAXCB_STRING, &cbsize))) {
- rv = KHM_ERROR_INVALID_PARAM;
- goto _exit;
- }
-
- cbsize += sizeof(wchar_t);
-
- if (khc_handle_flags(pconf) & KCONF_FLAG_WRITEIFMOD) {
- wchar_t tmpbuf[512];
- wchar_t * buffer;
- size_t tmpsize = cbsize;
- khm_boolean is_equal = FALSE;
-
- if (cbsize <= sizeof(tmpbuf)) {
- buffer = tmpbuf;
- } else {
- buffer = PMALLOC(cbsize);
- }
-
- if (KHM_SUCCEEDED(khc_read_string(pconf, pvalue, buffer, &tmpsize)) &&
- tmpsize == cbsize) {
- if (khc_handle_flags(pconf) & KCONF_FLAG_IFMODCI)
- is_equal = !_wcsicmp(buffer, buf);
- else
- is_equal = !wcscmp(buffer, buf);
- }
-
- if (buffer != tmpbuf)
- PFREE(buffer);
-
- if (is_equal) {
- return KHM_ERROR_SUCCESS;
- }
- }
-
- if((value = wcsrchr(pvalue, L'\\')) != NULL) {
- if(KHM_FAILED(khc_open_space(pconf, pvalue,
- KCONF_FLAG_TRAILINGVALUE | (pconf?khc_handle_flags(pconf):0),
- &conf)))
- return KHM_ERROR_INVALID_PARAM;
- free_space = 1;
-
- if (value) {
- value ++;
- } else {
-#ifdef DEBUG
- assert(FALSE);
-#endif
- }
- } else {
- value = pvalue;
- conf = pconf;
- free_space = 0;
- }
-
- if(!khc_is_handle(conf) || !buf) {
- rv = KHM_ERROR_INVALID_PARAM;
- goto _exit;
- }
-
- c = khc_space_from_handle(conf);
-
- if(khc_is_user_handle(conf)) {
- pk = khcint_space_open_key(c, KHM_PERM_WRITE | KHM_FLAG_CREATE);
- } else {
- pk = khcint_space_open_key(c, KHM_PERM_WRITE | KCONF_FLAG_MACHINE | KHM_FLAG_CREATE);
- }
-
- hr = RegSetValueEx(pk, value, 0, REG_SZ, (LPBYTE) buf, (DWORD) cbsize);
-
- if(hr != ERROR_SUCCESS)
- rv = KHM_ERROR_INVALID_OPERATION;
-
-_exit:
- if(free_space)
- khc_close_space(conf);
- return rv;
-}
-
-/* obtaincs cs_conf_handle/cs_conf_global */
-KHMEXP khm_int32 KHMAPI
-khc_write_int32(khm_handle pconf,
- const wchar_t * pvalue,
- khm_int32 buf)
-{
- HKEY pk = NULL;
- kconf_conf_space * c;
- khm_int32 rv = KHM_ERROR_SUCCESS;
- LONG hr;
- const wchar_t * value = NULL;
- int free_space = 0;
- khm_handle conf = NULL;
-
-
- if(!khc_is_config_running())
- return KHM_ERROR_NOT_READY;
-
- if(pconf && !khc_is_machine_handle(pconf) && !khc_is_user_handle(pconf))
- return KHM_ERROR_INVALID_OPERATION;
-
- if (khc_handle_flags(pconf) & KCONF_FLAG_WRITEIFMOD) {
- khm_int32 tmpvalue;
-
- if (KHM_SUCCEEDED(khc_read_int32(pconf, pvalue, &tmpvalue)) &&
- tmpvalue == buf) {
- return KHM_ERROR_SUCCESS;
- }
- }
-
- if((value = wcsrchr(pvalue, L'\\')) != NULL) {
- if(KHM_FAILED(khc_open_space(
- pconf,
- pvalue,
- KCONF_FLAG_TRAILINGVALUE | (pconf?khc_handle_flags(pconf):0),
- &conf)))
- return KHM_ERROR_INVALID_PARAM;
- free_space = 1;
-
- if (value) {
- value ++;
- } else {
-#ifdef DEBUG
- assert(FALSE);
-#endif
- }
- } else {
- value = pvalue;
- conf = pconf;
- free_space = 0;
- }
-
- if(!khc_is_handle(conf))
- return KHM_ERROR_INVALID_PARAM;
-
- c = khc_space_from_handle( conf);
-
- if(khc_is_user_handle(conf)) {
- pk = khcint_space_open_key(c, KHM_PERM_WRITE | KHM_FLAG_CREATE);
- } else {
- pk = khcint_space_open_key(c, KHM_PERM_WRITE | KCONF_FLAG_MACHINE | KHM_FLAG_CREATE);
- }
-
- hr = RegSetValueEx(pk, value, 0, REG_DWORD, (LPBYTE) &buf, sizeof(khm_int32));
-
- if(hr != ERROR_SUCCESS)
- rv = KHM_ERROR_INVALID_OPERATION;
-
- if(free_space)
- khc_close_space(conf);
-
- return rv;
-}
-
-/* obtains cs_conf_handle/cs_conf_global */
-KHMEXP khm_int32 KHMAPI
-khc_write_int64(khm_handle pconf, const wchar_t * pvalue, khm_int64 buf) {
- HKEY pk = NULL;
- kconf_conf_space * c;
- khm_int32 rv = KHM_ERROR_SUCCESS;
- LONG hr;
- const wchar_t * value = NULL;
- int free_space = 0;
- khm_handle conf = NULL;
-
-
- if(!khc_is_config_running())
- return KHM_ERROR_NOT_READY;
-
- if(pconf && !khc_is_machine_handle(pconf) && !khc_is_user_handle(pconf))
- return KHM_ERROR_INVALID_OPERATION;
-
- if (khc_handle_flags(pconf) & KCONF_FLAG_WRITEIFMOD) {
- khm_int64 tmpvalue;
-
- if (KHM_SUCCEEDED(khc_read_int64(pconf, pvalue, &tmpvalue)) &&
- tmpvalue == buf) {
- return KHM_ERROR_SUCCESS;
- }
- }
-
- if((value = wcsrchr(pvalue, L'\\')) != NULL) {
- if(KHM_FAILED(khc_open_space(
- pconf,
- pvalue,
- KCONF_FLAG_TRAILINGVALUE | (pconf?khc_handle_flags(pconf):0),
- &conf)))
- return KHM_ERROR_INVALID_PARAM;
- free_space = 1;
-
- if (value) {
- value ++;
- } else {
-#ifdef DEBUG
- assert(FALSE);
-#endif
- }
- } else {
- value = pvalue;
- conf = pconf;
- free_space = 0;
- }
-
- if(!khc_is_handle(conf))
- return KHM_ERROR_INVALID_PARAM;
-
- c = khc_space_from_handle( conf);
-
- if(khc_is_user_handle(conf)) {
- pk = khcint_space_open_key(c, KHM_PERM_WRITE | KHM_FLAG_CREATE);
- } else {
- pk = khcint_space_open_key(c, KHM_PERM_WRITE | KCONF_FLAG_MACHINE | KHM_FLAG_CREATE);
- }
-
- hr = RegSetValueEx(pk, value, 0, REG_QWORD, (LPBYTE) &buf, sizeof(khm_int64));
-
- if(hr != ERROR_SUCCESS)
- rv = KHM_ERROR_INVALID_OPERATION;
-
- if(free_space)
- khc_close_space(conf);
-
- return rv;
-}
-
-/* obtains cs_conf_handle/cs_conf_global */
-KHMEXP khm_int32 KHMAPI
-khc_write_binary(khm_handle pconf,
- const wchar_t * pvalue,
- void * buf, khm_size bufsize) {
- HKEY pk = NULL;
- kconf_conf_space * c;
- khm_int32 rv = KHM_ERROR_SUCCESS;
- LONG hr;
- const wchar_t * value = NULL;
- int free_space = 0;
- khm_handle conf = NULL;
-
-
- if(!khc_is_config_running())
- return KHM_ERROR_NOT_READY;
-
- if(pconf && !khc_is_machine_handle(pconf) && !khc_is_user_handle(pconf))
- return KHM_ERROR_INVALID_OPERATION;
-
- if((value = wcsrchr(pvalue, L'\\')) != NULL) {
- if(KHM_FAILED(khc_open_space(
- pconf,
- pvalue,
- KCONF_FLAG_TRAILINGVALUE | (pconf?khc_handle_flags(pconf):0),
- &conf)))
- return KHM_ERROR_INVALID_PARAM;
- free_space = 1;
-
- if (value) {
- value ++;
- } else {
-#ifdef DEBUG
- assert(FALSE);
-#endif
- }
- } else {
- value = pvalue;
- conf = pconf;
- free_space = 0;
- }
-
- if(!khc_is_handle(conf))
- return KHM_ERROR_INVALID_PARAM;
-
- c = khc_space_from_handle(conf);
-
- if(khc_is_user_handle(conf)) {
- pk = khcint_space_open_key(c, KHM_PERM_WRITE | KHM_FLAG_CREATE);
- } else {
- pk = khcint_space_open_key(c, KHM_PERM_WRITE | KCONF_FLAG_MACHINE | KHM_FLAG_CREATE);
- }
-
- hr = RegSetValueEx(pk, value, 0, REG_BINARY, buf, (DWORD) bufsize);
-
- if(hr != ERROR_SUCCESS)
- rv = KHM_ERROR_INVALID_OPERATION;
-
- if(free_space)
- khc_close_space(conf);
-
- return rv;
-}
-
-/* no locks */
-KHMEXP khm_int32 KHMAPI
-khc_get_config_space_name(khm_handle conf,
- wchar_t * buf, khm_size * bufsize) {
- kconf_conf_space * c;
- khm_int32 rv = KHM_ERROR_SUCCESS;
-
- if(!khc_is_config_running())
- return KHM_ERROR_NOT_READY;
-
- if(!khc_is_handle(conf))
- return KHM_ERROR_INVALID_PARAM;
-
- c = khc_space_from_handle(conf);
-
- if(!c->name) {
- if(buf && *bufsize > 0)
- buf[0] = L'\0';
- else {
- *bufsize = sizeof(wchar_t);
- rv = KHM_ERROR_TOO_LONG;
- }
- } else {
- size_t cbsize;
-
- if(FAILED(StringCbLength(c->name, KCONF_MAXCB_NAME, &cbsize)))
- return KHM_ERROR_UNKNOWN;
-
- cbsize += sizeof(wchar_t);
-
- if(!buf || cbsize > *bufsize) {
- *bufsize = cbsize;
- rv = KHM_ERROR_TOO_LONG;
- } else {
- StringCbCopy(buf, *bufsize, c->name);
- *bufsize = cbsize;
- }
- }
-
- return rv;
-}
-
-/* obtains cs_conf_handle/cs_conf_global */
-KHMEXP khm_int32 KHMAPI
-khc_get_config_space_parent(khm_handle conf, khm_handle * parent) {
- kconf_conf_space * c;
-
- if(!khc_is_config_running())
- return KHM_ERROR_NOT_READY;
-
- if(!khc_is_handle(conf))
- return KHM_ERROR_INVALID_PARAM;
-
- c = khc_space_from_handle(conf);
-
- if(c == conf_root || c->parent == conf_root)
- *parent = NULL;
- else
- *parent = khcint_handle_from_space(c->parent, khc_handle_flags(conf));
-
- return KHM_ERROR_SUCCESS;
-}
-
-/* obtains cs_conf_global */
-KHMEXP khm_int32 KHMAPI
-khc_get_type(khm_handle conf, const wchar_t * value) {
- HKEY hkm = NULL;
- HKEY hku = NULL;
- kconf_conf_space * c;
- khm_int32 rv;
- LONG hr = ERROR_SUCCESS;
- DWORD type = 0;
-
- if(!khc_is_config_running())
- return KC_NONE;
-
- if(!khc_is_handle(conf))
- return KC_NONE;
-
- c = khc_space_from_handle(conf);
-
- if(!khc_is_machine_handle(conf))
- hku = khcint_space_open_key(c, KHM_PERM_READ);
- hkm = khcint_space_open_key(c, KHM_PERM_READ | KCONF_FLAG_MACHINE);
-
- if(hku)
- hr = RegQueryValueEx(hku, value, NULL, &type, NULL, NULL);
- if(!hku || hr != ERROR_SUCCESS)
- hr = RegQueryValueEx(hkm, value, NULL, &type, NULL, NULL);
- if(((!hku && !hkm) || hr != ERROR_SUCCESS) && c->schema) {
- int i;
-
- for(i=0; i<c->nSchema; i++) {
- if(!wcscmp(c->schema[i].name, value)) {
- return c->schema[i].type;
- }
- }
-
- return KC_NONE;
- }
-
- switch(type) {
- case REG_MULTI_SZ:
- case REG_SZ:
- rv = KC_STRING;
- break;
- case REG_DWORD:
- rv = KC_INT32;
- break;
- case REG_QWORD:
- rv = KC_INT64;
- break;
- case REG_BINARY:
- rv = KC_BINARY;
- break;
- default:
- rv = KC_NONE;
- }
-
- return rv;
-}
-
-/* obtains cs_conf_global */
-KHMEXP khm_int32 KHMAPI
-khc_value_exists(khm_handle conf, const wchar_t * value) {
- HKEY hku = NULL;
- HKEY hkm = NULL;
- kconf_conf_space * c;
- khm_int32 rv = 0;
- DWORD t;
- int i;
-
- if(!khc_is_config_running())
- return KHM_ERROR_NOT_READY;
-
- if(!khc_is_handle(conf))
- return KHM_ERROR_INVALID_PARAM;
-
- do {
- c = khc_space_from_handle(conf);
-
- if (khc_is_user_handle(conf))
- hku = khcint_space_open_key(c, KHM_PERM_READ);
- if (khc_is_machine_handle(conf))
- hkm = khcint_space_open_key(c, KHM_PERM_READ | KCONF_FLAG_MACHINE);
-
- if(hku && (RegQueryValueEx(hku, value, NULL, &t, NULL, NULL) == ERROR_SUCCESS))
- rv |= KCONF_FLAG_USER;
- if(hkm && (RegQueryValueEx(hkm, value, NULL, &t, NULL, NULL) == ERROR_SUCCESS))
- rv |= KCONF_FLAG_MACHINE;
-
- if(c->schema && khc_is_schema_handle(conf)) {
- for(i=0; i<c->nSchema; i++) {
- if(!wcscmp(c->schema[i].name, value)) {
- rv |= KCONF_FLAG_SCHEMA;
- break;
- }
- }
- }
-
- /* if the value is not found at this level and the handle is
- shadowed, try the next level down. */
- if (rv == 0 && khc_is_shadowed(conf))
- conf = khc_shadow(conf);
- else
- break;
- } while (conf);
-
- return rv;
-}
-
-/* obtains cs_conf_global */
-KHMEXP khm_int32 KHMAPI
-khc_remove_value(khm_handle conf, const wchar_t * value, khm_int32 flags) {
- HKEY hku = NULL;
- HKEY hkm = NULL;
- kconf_conf_space * c;
- khm_int32 rv = KHM_ERROR_NOT_FOUND;
- DWORD t;
- LONG l;
-
- if(!khc_is_config_running())
- return KHM_ERROR_NOT_READY;
-
- if(!khc_is_handle(conf))
- return KHM_ERROR_INVALID_PARAM;
-
- c = khc_space_from_handle(conf);
-
- if(!khc_is_machine_handle(conf))
- hku = khcint_space_open_key(c, KHM_PERM_READ);
- hkm = khcint_space_open_key(c, KHM_PERM_READ | KCONF_FLAG_MACHINE);
-
- if((flags == 0 ||
- (flags & KCONF_FLAG_USER)) &&
- hku && (RegQueryValueEx(hku, value, NULL,
- &t, NULL, NULL) == ERROR_SUCCESS)) {
- l = RegDeleteValue(hku, value);
- if (l == ERROR_SUCCESS)
- rv = KHM_ERROR_SUCCESS;
- else
- rv = KHM_ERROR_UNKNOWN;
- }
- if((flags == 0 ||
- (flags & KCONF_FLAG_MACHINE)) &&
- hkm && (RegQueryValueEx(hkm, value, NULL,
- &t, NULL, NULL) == ERROR_SUCCESS)) {
- l = RegDeleteValue(hkm, value);
- if (l == ERROR_SUCCESS)
- rv = (rv == KHM_ERROR_UNKNOWN)?KHM_ERROR_PARTIAL:
- KHM_ERROR_SUCCESS;
- else
- rv = (rv == KHM_ERROR_SUCCESS)?KHM_ERROR_PARTIAL:
- KHM_ERROR_UNKNOWN;
- }
-
- return rv;
-}
-
-/* called with cs_conf_global held */
-khm_int32
-khcint_remove_space(kconf_conf_space * c, khm_int32 flags) {
- kconf_conf_space * cc;
- kconf_conf_space * cn;
- kconf_conf_space * p;
-
- /* TODO: if this is the last child space and the parent is marked
- for deletion, delete the parent as well. */
-
- p = TPARENT(c);
-
- /* We don't allow deleting top level keys. They are
- predefined. */
-#ifdef DEBUG
- assert(p);
-#endif
- if (!p)
- return KHM_ERROR_INVALID_OPERATION;
-
- cc = TFIRSTCHILD(c);
- while (cc) {
- cn = LNEXT(cc);
-
- khcint_remove_space(cc, flags);
-
- cc = cn;
- }
-
- cc = TFIRSTCHILD(c);
- if (!cc && c->refcount == 0) {
- TDELCHILD(p, c);
- khcint_free_space(c);
- } else {
- c->flags |= (flags &
- (KCONF_SPACE_FLAG_DELETE_M |
- KCONF_SPACE_FLAG_DELETE_U));
-
- /* if all the registry spaces have been marked as deleted and
- there is no schema, we should mark the space as deleted as
- well. Note that ideally we only need to check for stores
- which have data corresponding to this configuration space,
- but this is a bit problematic since we don't monitor the
- registry for changes. */
- if ((c->flags &
- (KCONF_SPACE_FLAG_DELETE_M |
- KCONF_SPACE_FLAG_DELETE_U)) ==
- (KCONF_SPACE_FLAG_DELETE_M |
- KCONF_SPACE_FLAG_DELETE_U) &&
- (!c->schema || c->nSchema == 0))
-
- c->flags |= KCONF_SPACE_FLAG_DELETED;
- }
-
- if (c->regpath && p->regpath) {
- HKEY hk;
-
- if (flags & KCONF_SPACE_FLAG_DELETE_U) {
- hk = khcint_space_open_key(p, KCONF_FLAG_USER);
-
- if (hk)
- khcint_RegDeleteKey(hk, c->name);
- }
- if (flags & KCONF_SPACE_FLAG_DELETE_M) {
- hk = khcint_space_open_key(p, KCONF_FLAG_MACHINE);
-
- if (hk)
- khcint_RegDeleteKey(hk, c->name);
- }
- }
-
- return KHM_ERROR_SUCCESS;
-}
-
-/* obtains cs_conf_global */
-KHMEXP khm_int32 KHMAPI
-khc_remove_space(khm_handle conf) {
-
- /*
- - mark this space as well as all child spaces as
- 'delete-on-close' using flags. Mark should indicate which
- repository to delete the space from. (user/machine)
-
- - When each subspace is released, check if it has been marked
- for deletion. If so, delete the marked spaces as well as
- removing the space from kconf space tree.
-
- - When removing a subspace from a space, check if the parent
- space has any children left. If there are none, check if the
- parent space is also marked for deletion.
- */
- kconf_conf_space * c;
- khm_int32 rv = KHM_ERROR_SUCCESS;
- khm_int32 flags = 0;
-
- if(!khc_is_config_running())
- return KHM_ERROR_NOT_READY;
-
- if(!khc_is_handle(conf))
- return KHM_ERROR_INVALID_PARAM;
-
- c = khc_space_from_handle(conf);
-
- EnterCriticalSection(&cs_conf_global);
-
- if (khc_is_machine_handle(conf))
- flags |= KCONF_SPACE_FLAG_DELETE_M;
- if (khc_is_user_handle(conf))
- flags |= KCONF_SPACE_FLAG_DELETE_U;
-
- rv = khcint_remove_space(c, flags);
-
- LeaveCriticalSection(&cs_conf_global);
-
- return rv;
-}
-
-/* no locks */
-khm_boolean
-khcint_is_valid_name(wchar_t * name)
-{
- size_t cbsize;
- if(FAILED(StringCbLength(name, KCONF_MAXCB_NAME, &cbsize)))
- return FALSE;
- return TRUE;
-}
-
-/* no locks */
-khm_int32
-khcint_validate_schema(const kconf_schema * schema,
- int begin,
- int *end)
-{
- int i;
- int state = 0;
- int end_found = 0;
-
- i=begin;
- while(!end_found) {
- switch(state) {
- case 0: /* initial. this record should start a config space */
- if(!khcint_is_valid_name(schema[i].name) ||
- schema[i].type != KC_SPACE)
- return KHM_ERROR_INVALID_PARAM;
- state = 1;
- break;
-
- case 1: /* we are inside a config space, in the values area */
- if(!khcint_is_valid_name(schema[i].name))
- return KHM_ERROR_INVALID_PARAM;
- if(schema[i].type == KC_SPACE) {
- if(KHM_FAILED(khcint_validate_schema(schema, i, &i)))
- return KHM_ERROR_INVALID_PARAM;
- state = 2;
- } else if(schema[i].type == KC_ENDSPACE) {
- end_found = 1;
- if(end)
- *end = i;
- } else {
- if(schema[i].type != KC_STRING &&
- schema[i].type != KC_INT32 &&
- schema[i].type != KC_INT64 &&
- schema[i].type != KC_BINARY)
- return KHM_ERROR_INVALID_PARAM;
- }
- break;
-
- case 2: /* we are inside a config space, in the subspace area */
- if(schema[i].type == KC_SPACE) {
- if(KHM_FAILED(khcint_validate_schema(schema, i, &i)))
- return KHM_ERROR_INVALID_PARAM;
- } else if(schema[i].type == KC_ENDSPACE) {
- end_found = 1;
- if(end)
- *end = i;
- } else {
- return KHM_ERROR_INVALID_PARAM;
- }
- break;
-
- default:
- /* unreachable */
- return KHM_ERROR_INVALID_PARAM;
- }
- i++;
- }
-
- return KHM_ERROR_SUCCESS;
-}
-
-/* obtains cs_conf_handle/cs_conf_global; called with cs_conf_global */
-khm_int32
-khcint_load_schema_i(khm_handle parent, const kconf_schema * schema,
- int begin, int * end)
-{
- int i;
- int state = 0;
- int end_found = 0;
- kconf_conf_space * thisconf = NULL;
- khm_handle h = NULL;
-
- i=begin;
- while(!end_found) {
- switch(state) {
- case 0: /* initial. this record should start a config space */
- LeaveCriticalSection(&cs_conf_global);
- if(KHM_FAILED(khc_open_space(parent, schema[i].name,
- KHM_FLAG_CREATE, &h))) {
- EnterCriticalSection(&cs_conf_global);
- return KHM_ERROR_INVALID_PARAM;
- }
- EnterCriticalSection(&cs_conf_global);
- thisconf = khc_space_from_handle(h);
- thisconf->schema = schema + (begin + 1);
- thisconf->nSchema = 0;
- state = 1;
- break;
-
- case 1: /* we are inside a config space, in the values area */
- if(schema[i].type == KC_SPACE) {
- thisconf->nSchema = i - (begin + 1);
- if(KHM_FAILED(khcint_load_schema_i(h, schema, i, &i)))
- return KHM_ERROR_INVALID_PARAM;
- state = 2;
- } else if(schema[i].type == KC_ENDSPACE) {
- thisconf->nSchema = i - (begin + 1);
- end_found = 1;
- if(end)
- *end = i;
- LeaveCriticalSection(&cs_conf_global);
- khc_close_space(h);
- EnterCriticalSection(&cs_conf_global);
- }
- break;
-
- case 2: /* we are inside a config space, in the subspace area */
- if(schema[i].type == KC_SPACE) {
- if(KHM_FAILED(khcint_load_schema_i(h, schema, i, &i)))
- return KHM_ERROR_INVALID_PARAM;
- } else if(schema[i].type == KC_ENDSPACE) {
- end_found = 1;
- if(end)
- *end = i;
- LeaveCriticalSection(&cs_conf_global);
- khc_close_space(h);
- EnterCriticalSection(&cs_conf_global);
- } else {
- return KHM_ERROR_INVALID_PARAM;
- }
- break;
-
- default:
- /* unreachable */
- return KHM_ERROR_INVALID_PARAM;
- }
- i++;
- }
-
- return KHM_ERROR_SUCCESS;
-}
-
-/* obtains cs_conf_handle/cs_conf_global */
-KHMEXP khm_int32 KHMAPI
-khc_load_schema(khm_handle conf, const kconf_schema * schema)
-{
- khm_int32 rv = KHM_ERROR_SUCCESS;
-
- if(!khc_is_config_running())
- return KHM_ERROR_NOT_READY;
-
- if(conf && !khc_is_handle(conf))
- return KHM_ERROR_INVALID_PARAM;
-
- if(KHM_FAILED(khcint_validate_schema(schema, 0, NULL)))
- return KHM_ERROR_INVALID_PARAM;
-
- EnterCriticalSection(&cs_conf_global);
- rv = khcint_load_schema_i(conf, schema, 0, NULL);
- LeaveCriticalSection(&cs_conf_global);
-
- return rv;
-}
-
-/* obtains cs_conf_handle/cs_conf_global; called with cs_conf_global */
-khm_int32
-khcint_unload_schema_i(khm_handle parent, const kconf_schema * schema,
- int begin, int * end)
-{
- int i;
- int state = 0;
- int end_found = 0;
- kconf_conf_space * thisconf = NULL;
- khm_handle h = NULL;
-
- i=begin;
- while(!end_found) {
- switch(state) {
- case 0: /* initial. this record should start a config space */
- LeaveCriticalSection(&cs_conf_global);
- if(KHM_FAILED(khc_open_space(parent, schema[i].name, 0, &h))) {
- EnterCriticalSection(&cs_conf_global);
- return KHM_ERROR_INVALID_PARAM;
- }
- EnterCriticalSection(&cs_conf_global);
- thisconf = khc_space_from_handle(h);
- if(thisconf->schema == (schema + (begin + 1))) {
- thisconf->schema = NULL;
- thisconf->nSchema = 0;
- }
- state = 1;
- break;
-
- case 1: /* we are inside a config space, in the values area */
- if(schema[i].type == KC_SPACE) {
- if(KHM_FAILED(khcint_unload_schema_i(h, schema, i, &i)))
- return KHM_ERROR_INVALID_PARAM;
- state = 2;
- } else if(schema[i].type == KC_ENDSPACE) {
- end_found = 1;
- if(end)
- *end = i;
- LeaveCriticalSection(&cs_conf_global);
- khc_close_space(h);
- EnterCriticalSection(&cs_conf_global);
- }
- break;
-
- case 2: /* we are inside a config space, in the subspace area */
- if(schema[i].type == KC_SPACE) {
- if(KHM_FAILED(khcint_unload_schema_i(h, schema, i, &i)))
- return KHM_ERROR_INVALID_PARAM;
- } else if(schema[i].type == KC_ENDSPACE) {
- end_found = 1;
- if(end)
- *end = i;
- LeaveCriticalSection(&cs_conf_global);
- khc_close_space(h);
- EnterCriticalSection(&cs_conf_global);
- } else {
- return KHM_ERROR_INVALID_PARAM;
- }
- break;
-
- default:
- /* unreachable */
- return KHM_ERROR_INVALID_PARAM;
- }
- i++;
- }
-
- return KHM_ERROR_SUCCESS;
-}
-
-/* obtains cs_conf_handle/cs_conf_global */
-KHMEXP khm_int32 KHMAPI
-khc_unload_schema(khm_handle conf, const kconf_schema * schema)
-{
- khm_int32 rv = KHM_ERROR_SUCCESS;
-
- if(!khc_is_config_running())
- return KHM_ERROR_NOT_READY;
-
- if(conf && !khc_is_handle(conf))
- return KHM_ERROR_INVALID_PARAM;
-
- if(KHM_FAILED(khcint_validate_schema(schema, 0, NULL)))
- return KHM_ERROR_INVALID_PARAM;
-
- EnterCriticalSection(&cs_conf_global);
- rv = khcint_unload_schema_i(conf, schema, 0, NULL);
- LeaveCriticalSection(&cs_conf_global);
-
- return rv;
-}
-
-/* obtaincs cs_conf_handle/cs_conf_global */
-KHMEXP khm_int32 KHMAPI
-khc_enum_subspaces(khm_handle conf,
- khm_handle prev,
- khm_handle * next)
-{
- kconf_conf_space * s;
- kconf_conf_space * c;
- kconf_conf_space * p;
- khm_int32 rv = KHM_ERROR_SUCCESS;
-
- if(!khc_is_config_running())
- return KHM_ERROR_NOT_READY;
-
- if(!khc_is_handle(conf) || next == NULL ||
- (prev != NULL && !khc_is_handle(prev)))
- return KHM_ERROR_INVALID_PARAM;
-
- s = khc_space_from_handle(conf);
-
- if(prev == NULL) {
- /* first off, we enumerate all the registry spaces regardless of
- whether the handle is applicable for some registry space or not.
- See notes for khc_begin_enum_subspaces() for reasons as to why
- this is done (notes are in kconfig.h)*/
-
- /* go through the user hive first */
- {
- HKEY hk_conf;
-
- hk_conf = khcint_space_open_key(s, 0);
- if(hk_conf) {
- wchar_t name[KCONF_MAXCCH_NAME];
- khm_handle h;
- int idx;
-
- idx = 0;
- while(RegEnumKey(hk_conf, idx,
- name, ARRAYLENGTH(name)) == ERROR_SUCCESS) {
- wchar_t * tilde;
- tilde = wcschr(name, L'~');
- if (tilde)
- *tilde = 0;
- if(KHM_SUCCEEDED(khc_open_space(conf, name, 0, &h)))
- khc_close_space(h);
- idx++;
- }
- }
- }
-
- /* go through the machine hive next */
- {
- HKEY hk_conf;
-
- hk_conf = khcint_space_open_key(s, KCONF_FLAG_MACHINE);
- if(hk_conf) {
- wchar_t name[KCONF_MAXCCH_NAME];
- khm_handle h;
- int idx;
-
- idx = 0;
- while(RegEnumKey(hk_conf, idx,
- name, ARRAYLENGTH(name)) == ERROR_SUCCESS) {
- wchar_t * tilde;
- tilde = wcschr(name, L'~');
- if (tilde)
- *tilde = 0;
-
- if(KHM_SUCCEEDED(khc_open_space(conf, name,
- KCONF_FLAG_MACHINE, &h)))
- khc_close_space(h);
- idx++;
- }
- }
- }
-
- /* don't need to go through schema, because that was already
- done when the schema was loaded. */
- }
-
- /* at last we are now ready to return the results */
- EnterCriticalSection(&cs_conf_global);
- if(prev == NULL) {
- c = TFIRSTCHILD(s);
- rv = KHM_ERROR_SUCCESS;
- } else {
- p = khc_space_from_handle(prev);
- if(TPARENT(p) == s)
- c = LNEXT(p);
- else
- c = NULL;
- }
- LeaveCriticalSection(&cs_conf_global);
-
- if(prev != NULL)
- khc_close_space(prev);
-
- if(c) {
- *next = khcint_handle_from_space(c, khc_handle_flags(conf));
- rv = KHM_ERROR_SUCCESS;
- } else {
- *next = NULL;
- rv = KHM_ERROR_NOT_FOUND;
- }
-
- return rv;
-}
-
-/* obtains cs_conf_handle/cs_conf_global */
-KHMEXP khm_int32 KHMAPI
-khc_write_multi_string(khm_handle conf, const wchar_t * value, wchar_t * buf)
-{
- size_t cb;
- wchar_t vbuf[KCONF_MAXCCH_STRING];
- wchar_t *tb;
- khm_int32 rv;
-
- if(!khc_is_config_running())
- return KHM_ERROR_NOT_READY;
- if(!khc_is_handle(conf) || buf == NULL || value == NULL)
- return KHM_ERROR_INVALID_PARAM;
-
- if(multi_string_to_csv(NULL, &cb, buf) != KHM_ERROR_TOO_LONG)
- return KHM_ERROR_INVALID_PARAM;
-
- if (cb < sizeof(vbuf))
- tb = vbuf;
- else
- tb = PMALLOC(cb);
-
- assert(tb != NULL);
-
- multi_string_to_csv(tb, &cb, buf);
- rv = khc_write_string(conf, value, tb);
-
- if (tb != vbuf)
- PFREE(tb);
- return rv;
-}
-
-/* obtains cs_conf_handle/cs_conf_global */
-KHMEXP khm_int32 KHMAPI
-khc_read_multi_string(khm_handle conf, const wchar_t * value,
- wchar_t * buf, khm_size * bufsize)
-{
- wchar_t vbuf[KCONF_MAXCCH_STRING];
- wchar_t * tb;
- khm_size cbbuf;
- khm_int32 rv = KHM_ERROR_SUCCESS;
-
- if(!khc_is_config_running())
- return KHM_ERROR_NOT_READY;
-
- if(!bufsize)
- return KHM_ERROR_INVALID_PARAM;
-
- rv = khc_read_string(conf, value, NULL, &cbbuf);
- if(rv != KHM_ERROR_TOO_LONG)
- return rv;
-
- if (cbbuf < sizeof(vbuf))
- tb = vbuf;
- else
- tb = PMALLOC(cbbuf);
-
- assert(tb != NULL);
-
- rv = khc_read_string(conf, value, tb, &cbbuf);
-
- if(KHM_FAILED(rv))
- goto _exit;
-
- rv = csv_to_multi_string(buf, bufsize, tb);
-
-_exit:
- if (tb != vbuf)
- PFREE(tb);
-
- return rv;
-}
+/*
+* Copyright (c) 2005 Massachusetts Institute of Technology
+*
+* Permission is hereby granted, free of charge, to any person
+* obtaining a copy of this software and associated documentation
+* files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy,
+* modify, merge, publish, distribute, sublicense, and/or sell copies
+* of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be
+* included in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*/
+
+/* $Id$ */
+
+#include<shlwapi.h>
+#include<kconfiginternal.h>
+#include<netidmgr_intver.h>
+#include<assert.h>
+
+kconf_conf_space * conf_root = NULL;
+kconf_handle * conf_handles = NULL;
+kconf_handle * conf_free_handles = NULL;
+
+CRITICAL_SECTION cs_conf_global;
+CRITICAL_SECTION cs_conf_handle;
+LONG conf_init = 0;
+LONG conf_status = 0;
+
+void init_kconf(void) {
+ if(InterlockedIncrement(&conf_init) == 1L) {
+ /* we are the first */
+ InitializeCriticalSection(&cs_conf_global);
+ EnterCriticalSection(&cs_conf_global);
+ conf_root = khcint_create_empty_space();
+ conf_root->name = PWCSDUP(L"Root");
+ conf_root->regpath = PWCSDUP(CONFIG_REGPATHW);
+ conf_root->refcount++;
+ conf_status = 1;
+ InitializeCriticalSection(&cs_conf_handle);
+ LeaveCriticalSection(&cs_conf_global);
+ }
+ /* else assume we are already initialized */
+}
+
+void exit_kconf(void) {
+ if(khc_is_config_running()) {
+ kconf_handle * h;
+
+ EnterCriticalSection(&cs_conf_global);
+
+ conf_init = 0;
+ conf_status = 0;
+
+ khcint_free_space(conf_root);
+
+ LeaveCriticalSection(&cs_conf_global);
+ DeleteCriticalSection(&cs_conf_global);
+
+ EnterCriticalSection(&cs_conf_handle);
+ while(conf_free_handles) {
+ LPOP(&conf_free_handles, &h);
+ if(h) {
+ PFREE(h);
+ }
+ }
+
+ while(conf_handles) {
+ LPOP(&conf_handles, &h);
+ if(h) {
+ PFREE(h);
+ }
+ }
+ LeaveCriticalSection(&cs_conf_handle);
+ DeleteCriticalSection(&cs_conf_handle);
+ }
+}
+
+#if defined(DEBUG) && (defined(KH_BUILD_PRIVATE) || defined(KH_BUILD_SPECIAL))
+
+#include<stdio.h>
+
+static void
+khcint_dump_space(FILE * f, kconf_conf_space * sp) {
+
+ kconf_conf_space * sc;
+
+ fprintf(f, "c12\t[%S]\t[%S]\t%d\t0x%x\tWin(%s|%s)|%s\n",
+ ((sp->regpath) ? sp->regpath : L"!No Reg path"),
+ sp->name,
+ (int) sp->refcount,
+ (int) sp->flags,
+ ((sp->regkey_user)? "HKCU" : ""),
+ ((sp->regkey_machine)? "HKLM" : ""),
+ ((sp->schema)? "Schema" : ""));
+
+
+ sc = TFIRSTCHILD(sp);
+ while(sc) {
+
+ khcint_dump_space(f, sc);
+
+ sc = LNEXT(sc);
+ }
+}
+
+KHMEXP void KHMAPI
+khcint_dump_handles(FILE * f) {
+ if (khc_is_config_running()) {
+ kconf_handle * h, * sh;
+
+ EnterCriticalSection(&cs_conf_handle);
+ EnterCriticalSection(&cs_conf_global);
+
+ fprintf(f, "c00\t*** Active handles ***\n");
+ fprintf(f, "c01\tHandle\tName\tFlags\tRegpath\n");
+
+ h = conf_handles;
+ while(h) {
+ kconf_conf_space * sp;
+
+ sp = h->space;
+
+ if (!khc_is_handle(h) || sp == NULL) {
+
+ fprintf(f, "c02\t!!INVALID HANDLE!!\n");
+
+ } else {
+
+ fprintf(f, "c02\t0x%p\t[%S]\t0x%x\t[%S]\n",
+ h,
+ sp->name,
+ h->flags,
+ sp->regpath);
+
+ sh = khc_shadow(h);
+
+ while(sh) {
+
+ sp = sh->space;
+
+ if (!khc_is_handle(sh) || sp == NULL) {
+
+ fprintf(f, "c02\t0x%p:Shadow:0x%p\t[!!INVALID HANDLE!!]\n",
+ h, sh);
+
+ } else {
+
+ fprintf(f, "c02\t0x%p:Shadow:0x%p,[%S]\t0x%x\t[%S]\n",
+ h, sh,
+ sp->name,
+ sh->flags,
+ sp->regpath);
+
+ }
+
+ sh = khc_shadow(sh);
+ }
+
+ }
+
+ h = LNEXT(h);
+ }
+
+ fprintf(f, "c03\t------ End ---------\n");
+
+ fprintf(f, "c10\t*** Active Configuration Spaces ***\n");
+ fprintf(f, "c11\tReg path\tName\tRefcount\tFlags\tLayers\n");
+
+ khcint_dump_space(f, conf_root);
+
+ fprintf(f, "c13\t------ End ---------\n");
+
+ LeaveCriticalSection(&cs_conf_global);
+ LeaveCriticalSection(&cs_conf_handle);
+
+ } else {
+ fprintf(f, "c00\t------- KHC Configuration not running -------\n");
+ }
+}
+
+#endif
+
+/* obtains cs_conf_handle/cs_conf_global */
+kconf_handle *
+khcint_handle_from_space(kconf_conf_space * s, khm_int32 flags)
+{
+ kconf_handle * h;
+
+ EnterCriticalSection(&cs_conf_handle);
+ LPOP(&conf_free_handles, &h);
+ if(!h) {
+ h = PMALLOC(sizeof(kconf_handle));
+ assert(h != NULL);
+ }
+ ZeroMemory((void *) h, sizeof(kconf_handle));
+
+ h->magic = KCONF_HANDLE_MAGIC;
+ khcint_space_hold(s);
+ h->space = s;
+ h->flags = flags;
+
+ LPUSH(&conf_handles, h);
+ LeaveCriticalSection(&cs_conf_handle);
+
+ return h;
+}
+
+/* obtains cs_conf_handle/cs_conf_global */
+void
+khcint_handle_free(kconf_handle * h)
+{
+ kconf_handle * lower;
+
+ EnterCriticalSection(&cs_conf_handle);
+#ifdef DEBUG
+ /* check if the handle is actually in use */
+ {
+ kconf_handle * a;
+ a = conf_handles;
+ while(a) {
+ if(h == a)
+ break;
+ a = LNEXT(a);
+ }
+
+ if(a == NULL) {
+ DebugBreak();
+
+ /* hmm. the handle was not in the in-use list */
+ LeaveCriticalSection(&cs_conf_handle);
+ return;
+ }
+ }
+#endif
+ while(h) {
+ LDELETE(&conf_handles, h);
+ if(h->space) {
+ khcint_space_release(h->space);
+ h->space = NULL;
+ }
+ lower = h->lower;
+ h->magic = 0;
+ LPUSH(&conf_free_handles, h);
+ h = lower;
+ }
+ LeaveCriticalSection(&cs_conf_handle);
+}
+
+/* obains cs_conf_handle/cs_conf_global */
+kconf_handle *
+khcint_handle_dup(kconf_handle * o)
+{
+ kconf_handle * h;
+ kconf_handle * r;
+
+ r = khcint_handle_from_space(o->space, o->flags);
+ h = r;
+
+ while(o->lower) {
+ h->lower = khcint_handle_from_space(o->lower->space, o->lower->flags);
+
+ o = o->lower;
+ h = h->lower;
+ }
+
+ return r;
+}
+
+/* obtains cs_conf_global */
+void
+khcint_space_hold(kconf_conf_space * s) {
+ EnterCriticalSection(&cs_conf_global);
+ s->refcount ++;
+ LeaveCriticalSection(&cs_conf_global);
+}
+
+/* called with cs_conf_global */
+void
+khcint_try_free_space(kconf_conf_space * s) {
+
+ if (TFIRSTCHILD(s) == NULL &&
+ s->refcount == 0 &&
+ s->schema == NULL) {
+
+ kconf_conf_space * p;
+
+ p = TPARENT(s);
+
+ if (p == NULL)
+ return;
+
+ TDELCHILD(p, s);
+
+ khcint_free_space(s);
+
+ khcint_try_free_space(p);
+ }
+}
+
+/* obtains cs_conf_global */
+void
+khcint_space_release(kconf_conf_space * s) {
+ khm_int32 l;
+
+ EnterCriticalSection(&cs_conf_global);
+
+ l = -- s->refcount;
+ if (l == 0) {
+ if(s->regkey_machine)
+ RegCloseKey(s->regkey_machine);
+ if(s->regkey_user)
+ RegCloseKey(s->regkey_user);
+ s->regkey_machine = NULL;
+ s->regkey_user = NULL;
+
+ if (s->flags &
+ (KCONF_SPACE_FLAG_DELETE_M |
+ KCONF_SPACE_FLAG_DELETE_U)) {
+ khcint_remove_space(s, s->flags);
+ } else {
+#ifdef USE_TRY_FREE
+ /* even if the refcount is zero, we shouldn't free a
+ configuration space just yet since that doesn't play
+ well with the configuration space enumeration mechanism
+ which expects the spaces to dangle around if there is a
+ corresponding registry key or schema. */
+ khcint_try_free_space(s);
+#endif
+ }
+ }
+
+ LeaveCriticalSection(&cs_conf_global);
+}
+
+/* case sensitive replacement for RegOpenKeyEx */
+LONG
+khcint_RegOpenKeyEx(HKEY hkey, LPCWSTR sSubKey, DWORD ulOptions,
+ REGSAM samDesired, PHKEY phkResult) {
+ int i;
+ wchar_t sk_name[KCONF_MAXCCH_NAME];
+ FILETIME ft;
+ size_t cch;
+ HKEY hkp = NULL;
+ const wchar_t * t;
+ LONG rv = ERROR_SUCCESS;
+
+ hkp = hkey;
+ t = sSubKey;
+
+ /* check for case insensitive prefix first */
+ if (!_wcsnicmp(sSubKey, CONFIG_REGPATHW, ARRAYLENGTH(CONFIG_REGPATHW) - 1)) {
+ HKEY hkt;
+
+ t = sSubKey + (ARRAYLENGTH(CONFIG_REGPATHW) - 1);
+
+#ifdef DEBUG
+ assert(*t == L'\0' || *t == L'\\');
+#endif
+
+ rv = RegOpenKeyEx(hkp,
+ CONFIG_REGPATHW,
+ ulOptions,
+ samDesired,
+ &hkt);
+
+ if (rv != ERROR_SUCCESS)
+ return rv;
+
+ if (*t == L'\0') {
+ *phkResult = hkt;
+ return rv;
+ }
+
+ t++;
+ hkp = hkt;
+ }
+
+ /* descend down the components of the subkey */
+ while(TRUE) {
+ wchar_t * slash;
+ HKEY hkt;
+
+ slash = wcschr(t, L'\\');
+ if (slash == NULL)
+ break;
+
+ if (FAILED(StringCchCopyN(sk_name, ARRAYLENGTH(sk_name),
+ t, slash - t))) {
+ rv = ERROR_CANTOPEN;
+ goto _cleanup;
+ }
+
+ sk_name[slash - t] = L'\0';
+ t = slash+1;
+
+ if (khcint_RegOpenKeyEx(hkp, sk_name, ulOptions, samDesired, &hkt) ==
+ ERROR_SUCCESS) {
+
+ if (hkp != hkey)
+ RegCloseKey(hkp);
+ hkp = hkt;
+
+ } else {
+
+ rv = ERROR_CANTOPEN;
+ goto _cleanup;
+
+ }
+ }
+
+ /* by now hkp is a handle to the parent of the last component in
+ the subkey. t is a pointer to the last component. */
+
+ if (FAILED(StringCchLength(t, KCONF_MAXCCH_NAME, &cch))) {
+ rv = ERROR_CANTOPEN;
+ goto _cleanup;
+ }
+
+ /* go through and find the case sensitive match for the key */
+
+ for (i=0; ;i++) {
+ LONG l;
+ DWORD dw;
+
+ dw = ARRAYLENGTH(sk_name);
+ l = RegEnumKeyEx(hkp, i, sk_name, &dw,
+ NULL, NULL, NULL, &ft);
+
+ if (l != ERROR_SUCCESS) {
+ rv = ERROR_CANTOPEN;
+ goto _cleanup;
+ }
+
+ if (!(wcsncmp(sk_name, t, cch))) {
+ /* bingo! ?? */
+ if (cch < KCONF_MAXCCH_NAME &&
+ (sk_name[cch] == L'\0' ||
+ sk_name[cch] == L'~')) {
+ rv = RegOpenKeyEx(hkp, sk_name, ulOptions,
+ samDesired, phkResult);
+ goto _cleanup;
+ }
+ }
+ }
+
+ _cleanup:
+ if (hkp != hkey && hkp != NULL)
+ RegCloseKey(hkp);
+
+ return rv;
+}
+
+/*! \internal
+
+ \note This function is not a good replacement for RegDeleteKey since
+ it deletes all the subkeys in addition to the key being deleted.
+ */
+LONG
+khcint_RegDeleteKey(HKEY hKey,
+ LPCWSTR lpSubKey) {
+ int i;
+ wchar_t sk_name[KCONF_MAXCCH_NAME];
+ FILETIME ft;
+ size_t cch;
+ LONG rv = ERROR_SUCCESS;
+
+ /* go through and find the case sensitive match for the key */
+
+ if (FAILED(StringCchLength(lpSubKey, KCONF_MAXCCH_NAME, &cch)))
+ return ERROR_BADKEY;
+
+ for (i=0; ;i++) {
+ LONG l;
+ DWORD dw;
+
+ dw = ARRAYLENGTH(sk_name);
+ l = RegEnumKeyEx(hKey, i, sk_name, &dw,
+ NULL, NULL, NULL, &ft);
+
+ if (l != ERROR_SUCCESS) {
+ rv = ERROR_BADKEY;
+ goto _cleanup;
+ }
+
+ if (!(wcsncmp(sk_name, lpSubKey, cch))) {
+ /* bingo! ?? */
+ if ((sk_name[cch] == L'\0' ||
+ sk_name[cch] == L'~')) {
+
+ /* instead of calling RegDeleteKey we call SHDeleteKey
+ because we want to blow off all the subkeys as
+ well. This is different from the behavior of
+ RegDeleteKey making khcint_RegDeleteKey not a very
+ good case sensitive replacement for
+ RegDeleteKey. */
+
+ rv = SHDeleteKey(hKey, sk_name);
+ goto _cleanup;
+ }
+ }
+ }
+
+ _cleanup:
+ return rv;
+}
+
+LONG
+khcint_RegCreateKeyEx(HKEY hKey,
+ LPCWSTR lpSubKey,
+ DWORD Reserved,
+ LPWSTR lpClass,
+ DWORD dwOptions,
+ REGSAM samDesired,
+ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
+ PHKEY phkResult,
+ LPDWORD lpdwDisposition) {
+ LONG l;
+ int i;
+ long index = 0;
+ wchar_t sk_name[KCONF_MAXCCH_NAME]; /* hard limit in Windows */
+ FILETIME ft;
+ size_t cch;
+ const wchar_t * t;
+ LONG rv = ERROR_SUCCESS;
+ HKEY hkp = NULL;
+
+ hkp = hKey;
+ t = lpSubKey;
+
+ /* check for case insensitive prefix first */
+ if (!_wcsnicmp(lpSubKey, CONFIG_REGPATHW, ARRAYLENGTH(CONFIG_REGPATHW) - 1)) {
+ HKEY hkt;
+
+ t = lpSubKey + (ARRAYLENGTH(CONFIG_REGPATHW) - 1);
+
+#ifdef DEBUG
+ assert(*t == L'\0' || *t == L'\\');
+#endif
+
+ rv = RegCreateKeyEx(hkp,
+ CONFIG_REGPATHW,
+ Reserved,
+ lpClass,
+ dwOptions,
+ samDesired,
+ lpSecurityAttributes,
+ &hkt,
+ lpdwDisposition);
+
+ if (rv != ERROR_SUCCESS)
+ return rv;
+
+ if (*t == L'\0') {
+ *phkResult = hkt;
+ return rv;
+ }
+
+ t++;
+ hkp = hkt;
+ }
+
+ while(TRUE) {
+ wchar_t * slash;
+ HKEY hkt;
+
+ slash = wcschr(t, L'\\');
+ if (slash == NULL)
+ break;
+
+ if (FAILED(StringCchCopyN(sk_name, ARRAYLENGTH(sk_name),
+ t, slash - t))) {
+ rv = ERROR_CANTOPEN;
+ goto _cleanup;
+ }
+
+ sk_name[slash - t] = L'\0';
+ t = slash+1;
+
+ if (khcint_RegOpenKeyEx(hkp, sk_name, 0, samDesired, &hkt) ==
+ ERROR_SUCCESS) {
+
+ if (hkp != hKey)
+ RegCloseKey(hkp);
+ hkp = hkt;
+ } else {
+
+ rv = RegCreateKeyEx(hKey,
+ lpSubKey,
+ Reserved,
+ lpClass,
+ dwOptions,
+ samDesired,
+ lpSecurityAttributes,
+ phkResult,
+ lpdwDisposition);
+ goto _cleanup;
+ }
+ }
+
+ if (FAILED(StringCchLength(t, KCONF_MAXCCH_NAME, &cch))) {
+ rv = ERROR_CANTOPEN;
+ goto _cleanup;
+ }
+
+ for (i=0; ;i++) {
+ DWORD dw;
+
+ dw = ARRAYLENGTH(sk_name);
+ l = RegEnumKeyEx(hkp, i, sk_name, &dw,
+ NULL, NULL, NULL, &ft);
+
+ if (l != ERROR_SUCCESS)
+ break;
+
+ if (!(wcsncmp(sk_name, t, cch))) {
+ /* bingo! ?? */
+ if (sk_name[cch] == L'\0' ||
+ sk_name[cch] == L'~') {
+ l = RegOpenKeyEx(hkp, sk_name, 0,
+ samDesired, phkResult);
+ if (l == ERROR_SUCCESS && lpdwDisposition)
+ *lpdwDisposition = REG_OPENED_EXISTING_KEY;
+ rv = l;
+ goto _cleanup;
+ }
+ }
+
+ if (!_wcsnicmp(sk_name, t, cch) &&
+ (sk_name[cch] == L'\0' ||
+ sk_name[cch] == L'~')) {
+ long new_idx;
+
+ if (sk_name[cch] == L'\0')
+ new_idx = 1;
+ else if (cch + 1 < KCONF_MAXCCH_NAME)
+ new_idx = wcstol(sk_name + (cch + 1), NULL, 10);
+ else
+ return ERROR_BUFFER_OVERFLOW;
+
+ assert(new_idx > 0);
+
+ if (new_idx > index)
+ index = new_idx;
+ }
+ }
+
+ if (index != 0) {
+ if (FAILED(StringCbPrintf(sk_name, sizeof(sk_name),
+ L"%s~%d", t, index)))
+ return ERROR_BUFFER_OVERFLOW;
+ } else {
+ StringCbCopy(sk_name, sizeof(sk_name), t);
+ }
+
+ rv = RegCreateKeyEx(hkp,
+ sk_name,
+ Reserved,
+ lpClass,
+ dwOptions,
+ samDesired,
+ lpSecurityAttributes,
+ phkResult,
+ lpdwDisposition);
+
+ _cleanup:
+
+ if (hkp != hKey && hkp != NULL)
+ RegCloseKey(hkp);
+
+ return rv;
+}
+
+/* obtains cs_conf_global */
+HKEY
+khcint_space_open_key(kconf_conf_space * s, khm_int32 flags) {
+ HKEY hk = NULL;
+ int nflags = 0;
+ DWORD disp;
+ if(flags & KCONF_FLAG_MACHINE) {
+ if(s->regkey_machine)
+ return s->regkey_machine;
+ if((khcint_RegOpenKeyEx(HKEY_LOCAL_MACHINE, s->regpath, 0,
+ KEY_READ | KEY_WRITE, &hk) !=
+ ERROR_SUCCESS) &&
+ !(flags & KHM_PERM_WRITE)) {
+
+ if(khcint_RegOpenKeyEx(HKEY_LOCAL_MACHINE, s->regpath, 0,
+ KEY_READ, &hk) == ERROR_SUCCESS) {
+ nflags = KHM_PERM_READ;
+ }
+
+ }
+ if(!hk && (flags & KHM_FLAG_CREATE)) {
+
+ khcint_RegCreateKeyEx(HKEY_LOCAL_MACHINE,
+ s->regpath,
+ 0,
+ NULL,
+ REG_OPTION_NON_VOLATILE,
+ KEY_READ | KEY_WRITE,
+ NULL,
+ &hk,
+ &disp);
+ }
+ if(hk) {
+ EnterCriticalSection(&cs_conf_global);
+ s->regkey_machine = hk;
+ s->regkey_machine_flags = nflags;
+ LeaveCriticalSection(&cs_conf_global);
+ }
+
+ return hk;
+ } else {
+ if(s->regkey_user)
+ return s->regkey_user;
+ if((khcint_RegOpenKeyEx(HKEY_CURRENT_USER, s->regpath, 0,
+ KEY_READ | KEY_WRITE, &hk) !=
+ ERROR_SUCCESS) &&
+ !(flags & KHM_PERM_WRITE)) {
+ if(khcint_RegOpenKeyEx(HKEY_CURRENT_USER, s->regpath, 0,
+ KEY_READ, &hk) == ERROR_SUCCESS) {
+ nflags = KHM_PERM_READ;
+ }
+ }
+ if(!hk && (flags & KHM_FLAG_CREATE)) {
+ khcint_RegCreateKeyEx(HKEY_CURRENT_USER,
+ s->regpath, 0, NULL,
+ REG_OPTION_NON_VOLATILE,
+ KEY_READ | KEY_WRITE,
+ NULL, &hk, &disp);
+ }
+ if(hk) {
+ EnterCriticalSection(&cs_conf_global);
+ s->regkey_user = hk;
+ s->regkey_user_flags = nflags;
+ LeaveCriticalSection(&cs_conf_global);
+ }
+
+ return hk;
+ }
+}
+
+/* obtains cs_conf_handle/cs_conf_global */
+KHMEXP khm_int32 KHMAPI
+khc_shadow_space(khm_handle upper, khm_handle lower)
+{
+ kconf_handle * h;
+
+ if(!khc_is_config_running())
+ return KHM_ERROR_NOT_READY;
+
+ if(!khc_is_handle(upper)) {
+#ifdef DEBUG
+ DebugBreak();
+#endif
+ return KHM_ERROR_INVALID_PARAM;
+ }
+
+ h = (kconf_handle *) upper;
+
+ EnterCriticalSection(&cs_conf_handle);
+ if(h->lower) {
+ EnterCriticalSection(&cs_conf_global);
+ khcint_handle_free(h->lower);
+ LeaveCriticalSection(&cs_conf_global);
+ h->lower = NULL;
+ }
+
+ if(khc_is_handle(lower)) {
+ kconf_handle * l;
+ kconf_handle * lc;
+
+ l = (kconf_handle *) lower;
+ lc = khcint_handle_dup(l);
+ h->lower = lc;
+ }
+ LeaveCriticalSection(&cs_conf_handle);
+
+ return KHM_ERROR_SUCCESS;
+}
+
+/* no locks */
+kconf_conf_space *
+khcint_create_empty_space(void) {
+ kconf_conf_space * r;
+
+ r = PMALLOC(sizeof(kconf_conf_space));
+ assert(r != NULL);
+ ZeroMemory(r,sizeof(kconf_conf_space));
+
+ return r;
+}
+
+/* called with cs_conf_global */
+void
+khcint_free_space(kconf_conf_space * r) {
+ kconf_conf_space * c;
+
+ if(!r)
+ return;
+
+ TPOPCHILD(r, &c);
+ while(c) {
+ khcint_free_space(c);
+ TPOPCHILD(r, &c);
+ }
+
+ if(r->name)
+ PFREE(r->name);
+
+ if(r->regpath)
+ PFREE(r->regpath);
+
+ if(r->regkey_machine)
+ RegCloseKey(r->regkey_machine);
+
+ if(r->regkey_user)
+ RegCloseKey(r->regkey_user);
+
+ PFREE(r);
+}
+
+/* obtains cs_conf_global */
+khm_int32
+khcint_open_space(kconf_conf_space * parent,
+ const wchar_t * sname, size_t n_sname,
+ khm_int32 flags, kconf_conf_space **result) {
+ kconf_conf_space * p;
+ kconf_conf_space * c;
+ HKEY pkey = NULL;
+ HKEY ckey = NULL;
+ wchar_t buf[KCONF_MAXCCH_NAME];
+ size_t cb_regpath = 0;
+
+ if(!parent)
+ p = conf_root;
+ else
+ p = parent;
+
+ if(n_sname >= KCONF_MAXCCH_NAME || n_sname <= 0)
+ return KHM_ERROR_INVALID_PARAM;
+
+ StringCchCopyN(buf, ARRAYLENGTH(buf), sname, n_sname);
+
+ /* see if there is already a config space by this name. if so,
+ return it. Note that if the configuration space is specified
+ in a schema, we would find it here. */
+ EnterCriticalSection(&cs_conf_global);
+ c = TFIRSTCHILD(p);
+ while(c) {
+ if(c->name && !wcscmp(c->name, buf))
+ break;
+
+ c = LNEXT(c);
+ }
+ LeaveCriticalSection(&cs_conf_global);
+
+ if(c) {
+
+ if (c->flags & KCONF_SPACE_FLAG_DELETED) {
+ if (flags & KHM_FLAG_CREATE) {
+ c->flags &= ~(KCONF_SPACE_FLAG_DELETED |
+ KCONF_SPACE_FLAG_DELETE_M |
+ KCONF_SPACE_FLAG_DELETE_U);
+ } else {
+ *result = NULL;
+ return KHM_ERROR_NOT_FOUND;
+ }
+ }
+
+ khcint_space_hold(c);
+ *result = c;
+ return KHM_ERROR_SUCCESS;
+ }
+
+ if(!(flags & KHM_FLAG_CREATE)) {
+
+ /* we are not creating the space, so it must exist in the form of a
+ registry key in HKLM or HKCU. If it existed as a schema, we
+ would have already retured it above. */
+
+ if (flags & KCONF_FLAG_USER)
+ pkey = khcint_space_open_key(p, KHM_PERM_READ | KCONF_FLAG_USER);
+
+ if((!pkey ||
+ (khcint_RegOpenKeyEx(pkey, buf, 0, KEY_READ, &ckey) !=
+ ERROR_SUCCESS))
+ && (flags & KCONF_FLAG_MACHINE)) {
+
+ pkey = khcint_space_open_key(p, KHM_PERM_READ | KCONF_FLAG_MACHINE);
+ if(!pkey ||
+ (khcint_RegOpenKeyEx(pkey, buf, 0, KEY_READ, &ckey) !=
+ ERROR_SUCCESS)) {
+ *result = NULL;
+
+ return KHM_ERROR_NOT_FOUND;
+ }
+ }
+
+ if(ckey) {
+ RegCloseKey(ckey);
+ ckey = NULL;
+ }
+ }
+
+ c = khcint_create_empty_space();
+
+ /*SAFE: buf: is of known length < KCONF_MAXCCH_NAME */
+ c->name = PWCSDUP(buf);
+
+ /*SAFE: p->regpath: is valid since it was set using this same
+ function. */
+ /*SAFE: buf: see above */
+ cb_regpath = (wcslen(p->regpath) + wcslen(buf) + 2) * sizeof(wchar_t);
+ c->regpath = PMALLOC(cb_regpath);
+
+ assert(c->regpath != NULL);
+
+ /*SAFE: c->regpath: allocated above to be big enough */
+ /*SAFE: p->regpath: see above */
+ StringCbCopy(c->regpath, cb_regpath, p->regpath);
+ StringCbCat(c->regpath, cb_regpath, L"\\");
+
+ /*SAFE: buf: see above */
+ StringCbCat(c->regpath, cb_regpath, buf);
+
+ khcint_space_hold(c);
+
+ EnterCriticalSection(&cs_conf_global);
+ TADDCHILD(p,c);
+ LeaveCriticalSection(&cs_conf_global);
+
+ *result = c;
+ return KHM_ERROR_SUCCESS;
+}
+
+/* obtains cs_conf_handle/cs_conf_global */
+KHMEXP khm_int32 KHMAPI
+khc_open_space(khm_handle parent, const wchar_t * cspace, khm_int32 flags,
+ khm_handle * result) {
+ kconf_handle * h;
+ kconf_conf_space * p;
+ kconf_conf_space * c = NULL;
+ size_t cbsize;
+ const wchar_t * str;
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+
+ if(!khc_is_config_running()) {
+ return KHM_ERROR_NOT_READY;
+ }
+
+ if(!result || (parent && !khc_is_handle(parent))) {
+#ifdef DEBUG
+ DebugBreak();
+#endif
+ return KHM_ERROR_INVALID_PARAM;
+ }
+
+ if(!parent)
+ p = conf_root;
+ else {
+ h = (kconf_handle *) parent;
+ p = khc_space_from_handle(parent);
+ }
+
+ khcint_space_hold(p);
+
+ /* if none of these flags are specified, make it seem like all of
+ them were */
+ if(!(flags & KCONF_FLAG_USER) &&
+ !(flags & KCONF_FLAG_MACHINE) &&
+ !(flags & KCONF_FLAG_SCHEMA))
+ flags |= KCONF_FLAG_USER | KCONF_FLAG_MACHINE | KCONF_FLAG_SCHEMA;
+
+ if(cspace == NULL) {
+ *result = (khm_handle) khcint_handle_from_space(p, flags);
+ khcint_space_release(p);
+ return KHM_ERROR_SUCCESS;
+ }
+
+ if(FAILED(StringCbLength(cspace, KCONF_MAXCB_PATH, &cbsize))) {
+ khcint_space_release(p);
+ *result = NULL;
+ return KHM_ERROR_INVALID_PARAM;
+ }
+
+ str = cspace;
+ while(TRUE) {
+ const wchar_t * end = NULL;
+
+ if (!(flags & KCONF_FLAG_NOPARSENAME)) {
+
+ end = wcschr(str, L'\\'); /* safe because cspace was
+ validated above */
+ }
+
+ if(!end) {
+ if(flags & KCONF_FLAG_TRAILINGVALUE) {
+ /* we are at the value component */
+ c = p;
+ khcint_space_hold(c);
+ break;
+ } else
+ end = str + wcslen(str); /* safe because cspace was
+ validated above */
+ }
+
+ rv = khcint_open_space(p, str, end - str, flags, &c);
+
+ if(KHM_SUCCEEDED(rv) && (*end == L'\\')) {
+ khcint_space_release(p);
+ p = c;
+ c = NULL;
+ str = end+1;
+ }
+ else
+ break;
+ }
+
+ khcint_space_release(p);
+ if(KHM_SUCCEEDED(rv)) {
+ *result = khcint_handle_from_space(c, flags);
+ } else
+ *result = NULL;
+
+ if (c)
+ khcint_space_release(c);
+
+ return rv;
+}
+
+/* obtains cs_conf_handle/cs_conf_global */
+KHMEXP khm_int32 KHMAPI
+khc_close_space(khm_handle csp) {
+ if(!khc_is_config_running())
+ return KHM_ERROR_NOT_READY;
+
+ if(!khc_is_handle(csp)) {
+#ifdef DEBUG
+ DebugBreak();
+#endif
+ return KHM_ERROR_INVALID_PARAM;
+ }
+
+ khcint_handle_free((kconf_handle *) csp);
+ return KHM_ERROR_SUCCESS;
+}
+
+/* obtains cs_conf_handle/cs_conf_global */
+KHMEXP khm_int32 KHMAPI
+khc_read_string(khm_handle pconf,
+ const wchar_t * pvalue,
+ wchar_t * buf,
+ khm_size * bufsize)
+{
+ kconf_conf_space * c;
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+
+ if(!khc_is_config_running())
+ return KHM_ERROR_NOT_READY;
+
+ do {
+ HKEY hku = NULL;
+ HKEY hkm = NULL;
+ const wchar_t * value = NULL;
+ int free_space = 0;
+ khm_handle conf = NULL;
+ DWORD size;
+ DWORD type;
+ LONG hr;
+
+ int i;
+
+ if((value = wcsrchr(pvalue, L'\\')) != NULL) {
+
+ if(KHM_FAILED(khc_open_space(
+ pconf,
+ pvalue,
+ KCONF_FLAG_TRAILINGVALUE | (pconf?khc_handle_flags(pconf):0),
+ &conf)))
+ goto _shadow;
+
+ free_space = 1;
+
+ if (value) {
+ value++;
+ } else {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ }
+ } else {
+ value = pvalue;
+ conf = pconf;
+ free_space = 0;
+ }
+
+ if(!khc_is_handle(conf))
+ goto _shadow;
+
+ c = khc_space_from_handle(conf);
+
+ if(khc_is_user_handle(conf))
+ hku = khcint_space_open_key(c, KHM_PERM_READ);
+
+ if(khc_is_machine_handle(conf))
+ hkm = khcint_space_open_key(c, KHM_PERM_READ | KCONF_FLAG_MACHINE);
+
+ size = (DWORD) *bufsize;
+ if(hku) {
+ hr = RegQueryValueEx(hku, value, NULL, &type, (LPBYTE) buf, &size);
+ if(hr == ERROR_SUCCESS) {
+ if(type != REG_SZ) {
+ rv = KHM_ERROR_TYPE_MISMATCH;
+ goto _exit;
+ }
+ else {
+ *bufsize = size;
+ /* if buf==NULL, RegQueryValueEx will return success and just return the
+ required buffer size in 'size' */
+ rv = (buf)? KHM_ERROR_SUCCESS: KHM_ERROR_TOO_LONG;
+ goto _exit;
+ }
+ } else {
+ if(hr == ERROR_MORE_DATA) {
+ *bufsize = size;
+ rv = KHM_ERROR_TOO_LONG;
+ goto _exit;
+ }
+ }
+ }
+
+ size = (DWORD) *bufsize;
+ if(hkm) {
+ hr = RegQueryValueEx(hkm, value, NULL, &type, (LPBYTE) buf, &size);
+ if(hr == ERROR_SUCCESS) {
+ if(type != REG_SZ) {
+ rv = KHM_ERROR_TYPE_MISMATCH;
+ goto _exit;
+ }
+ else {
+ *bufsize = size;
+ rv = (buf)? KHM_ERROR_SUCCESS: KHM_ERROR_TOO_LONG;
+ goto _exit;
+ }
+ } else {
+ if(hr == ERROR_MORE_DATA) {
+ *bufsize = size;
+ rv = KHM_ERROR_TOO_LONG;
+ goto _exit;
+ }
+ }
+ }
+
+ if(c->schema && khc_is_schema_handle(conf)) {
+ for(i=0;i<c->nSchema;i++) {
+ if(c->schema[i].type == KC_STRING && !wcscmp(value, c->schema[i].name)) {
+ /* found it */
+ size_t cbsize = 0;
+
+ if(!c->schema[i].value) {
+ rv = KHM_ERROR_NOT_FOUND;
+ goto _exit;
+ }
+
+ if(FAILED(StringCbLength((wchar_t *) c->schema[i].value, KCONF_MAXCB_STRING, &cbsize))) {
+ rv = KHM_ERROR_NOT_FOUND;
+ goto _exit;
+ }
+ cbsize += sizeof(wchar_t);
+
+ if(!buf || *bufsize < cbsize) {
+ *bufsize = cbsize;
+ rv = KHM_ERROR_TOO_LONG;
+ goto _exit;
+ }
+
+ StringCbCopy(buf, *bufsize, (wchar_t *) c->schema[i].value);
+ *bufsize = cbsize;
+ rv = KHM_ERROR_SUCCESS;
+ goto _exit;
+ }
+ }
+ }
+
+_shadow:
+ if(free_space && conf)
+ khc_close_space(conf);
+
+ if(khc_is_shadowed(pconf)) {
+ pconf = khc_shadow(pconf);
+ continue;
+ } else {
+ rv = KHM_ERROR_NOT_FOUND;
+ break;
+ }
+
+_exit:
+ if(free_space && conf)
+ khc_close_space(conf);
+ break;
+
+ } while(TRUE);
+
+ return rv;
+}
+
+/* obtains cs_conf_handle/cs_conf_global */
+KHMEXP khm_int32 KHMAPI
+khc_read_int32(khm_handle pconf, const wchar_t * pvalue, khm_int32 * buf) {
+ kconf_conf_space * c;
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+
+ if(!khc_is_config_running())
+ return KHM_ERROR_NOT_READY;
+
+ if(!buf || !pvalue)
+ return KHM_ERROR_INVALID_PARAM;
+
+ do {
+ DWORD size;
+ DWORD type;
+ LONG hr;
+ HKEY hku = NULL;
+ HKEY hkm = NULL;
+
+ const wchar_t * value = NULL;
+ int free_space = 0;
+ khm_handle conf = NULL;
+
+ int i;
+
+ if((value = wcsrchr(pvalue, L'\\')) != NULL) {
+ if(KHM_FAILED(khc_open_space(
+ pconf,
+ pvalue,
+ KCONF_FLAG_TRAILINGVALUE | (pconf?khc_handle_flags(pconf):0),
+ &conf)))
+ goto _shadow;
+ free_space = 1;
+
+ if (value) {
+ value++;
+ } else {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ }
+ } else {
+ value = pvalue;
+ conf = pconf;
+ free_space = 0;
+ }
+
+ if(!khc_is_handle(conf) || !buf)
+ goto _shadow;
+
+ c = khc_space_from_handle(conf);
+
+ if(khc_is_user_handle(conf))
+ hku = khcint_space_open_key(c, KHM_PERM_READ);
+
+ if(khc_is_machine_handle(conf))
+ hkm = khcint_space_open_key(c, KHM_PERM_READ | KCONF_FLAG_MACHINE);
+
+ size = sizeof(DWORD);
+ if(hku) {
+ hr = RegQueryValueEx(hku, value, NULL, &type, (LPBYTE) buf, &size);
+ if(hr == ERROR_SUCCESS) {
+ if(type != REG_DWORD) {
+ rv = KHM_ERROR_TYPE_MISMATCH;
+ goto _exit;
+ }
+ else {
+ rv = KHM_ERROR_SUCCESS;
+ goto _exit;
+ }
+ }
+ }
+
+ size = sizeof(DWORD);
+ if(hkm) {
+ hr = RegQueryValueEx(hkm, value, NULL, &type, (LPBYTE) buf, &size);
+ if(hr == ERROR_SUCCESS) {
+ if(type != REG_DWORD) {
+ rv= KHM_ERROR_TYPE_MISMATCH;
+ goto _exit;
+ }
+ else {
+ rv= KHM_ERROR_SUCCESS;
+ goto _exit;
+ }
+ }
+ }
+
+ if(c->schema && khc_is_schema_handle(conf)) {
+ for(i=0;i<c->nSchema;i++) {
+ if(c->schema[i].type == KC_INT32 && !wcscmp(value, c->schema[i].name)) {
+ *buf = (khm_int32) c->schema[i].value;
+ rv = KHM_ERROR_SUCCESS;
+ goto _exit;
+ }
+ }
+ }
+_shadow:
+ if(free_space && conf)
+ khc_close_space(conf);
+
+ if(khc_is_shadowed(pconf)) {
+ pconf = khc_shadow(pconf);
+ continue;
+ } else {
+ rv = KHM_ERROR_NOT_FOUND;
+ break;
+ }
+_exit:
+ if(free_space && conf)
+ khc_close_space(conf);
+ break;
+ }
+ while(TRUE);
+
+ return rv;
+}
+
+/* obtains cs_conf_handle/cs_conf_global */
+KHMEXP khm_int32 KHMAPI
+khc_read_int64(khm_handle pconf, const wchar_t * pvalue, khm_int64 * buf) {
+ kconf_conf_space * c;
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+
+ if(!khc_is_config_running())
+ return KHM_ERROR_NOT_READY;
+
+ do {
+ DWORD size;
+ DWORD type;
+ LONG hr;
+ HKEY hku = NULL;
+ HKEY hkm = NULL;
+
+ const wchar_t * value = NULL;
+ int free_space = 0;
+ khm_handle conf = NULL;
+
+ int i;
+
+ if((value = wcsrchr(pvalue, L'\\')) != NULL) {
+ if(KHM_FAILED(khc_open_space(
+ pconf,
+ pvalue,
+ KCONF_FLAG_TRAILINGVALUE | (pconf?khc_handle_flags(pconf):0),
+ &conf)))
+ goto _shadow;
+ free_space = 1;
+
+ if (value) {
+ value++;
+ } else {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ }
+ } else {
+ value = pvalue;
+ conf = pconf;
+ free_space = 0;
+ }
+
+ if(!khc_is_handle(conf) || !buf)
+ goto _shadow;
+
+ c = khc_space_from_handle(conf);
+
+ if(khc_is_user_handle(conf))
+ hku = khcint_space_open_key(c, KHM_PERM_READ);
+
+ if(khc_is_machine_handle(conf))
+ hkm = khcint_space_open_key(c, KHM_PERM_READ | KCONF_FLAG_MACHINE);
+
+ size = sizeof(khm_int64);
+ if(hku) {
+ hr = RegQueryValueEx(hku, value, NULL, &type, (LPBYTE) buf, &size);
+ if(hr == ERROR_SUCCESS) {
+ if(type != REG_QWORD) {
+ rv= KHM_ERROR_TYPE_MISMATCH;
+ goto _exit;
+ }
+ else {
+ rv = KHM_ERROR_SUCCESS;
+ goto _exit;
+ }
+ }
+ }
+
+ size = sizeof(khm_int64);
+ if(hkm) {
+ hr = RegQueryValueEx(hkm, value, NULL, &type, (LPBYTE) buf, &size);
+ if(hr == ERROR_SUCCESS) {
+ if(type != REG_QWORD) {
+ rv = KHM_ERROR_TYPE_MISMATCH;
+ goto _exit;
+ }
+ else {
+ rv = KHM_ERROR_SUCCESS;
+ goto _exit;
+ }
+ }
+ }
+
+ if(c->schema && khc_is_schema_handle(conf)) {
+ for(i=0;i<c->nSchema;i++) {
+ if(c->schema[i].type == KC_INT64 && !wcscmp(value, c->schema[i].name)) {
+ *buf = (khm_int64) c->schema[i].value;
+ rv = KHM_ERROR_SUCCESS;
+ goto _exit;
+ }
+ }
+ }
+
+_shadow:
+ if(free_space && conf)
+ khc_close_space(conf);
+ if(khc_is_shadowed(pconf)) {
+ pconf = khc_shadow(pconf);
+ continue;
+ } else {
+ rv = KHM_ERROR_NOT_FOUND;
+ break;
+ }
+
+_exit:
+ if(free_space && conf)
+ khc_close_space(conf);
+ break;
+
+ } while(TRUE);
+ return rv;
+}
+
+/* obtaincs cs_conf_handle/cs_conf_global */
+KHMEXP khm_int32 KHMAPI
+khc_read_binary(khm_handle pconf, const wchar_t * pvalue,
+ void * buf, khm_size * bufsize) {
+ kconf_conf_space * c;
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+
+ if(!khc_is_config_running())
+ return KHM_ERROR_NOT_READY;
+
+ do {
+ DWORD size;
+ DWORD type;
+ LONG hr;
+ HKEY hku = NULL;
+ HKEY hkm = NULL;
+
+ const wchar_t * value = NULL;
+ int free_space = 0;
+ khm_handle conf = NULL;
+
+ if((value = wcsrchr(pvalue, L'\\')) != NULL) {
+ if(KHM_FAILED(khc_open_space(
+ pconf,
+ pvalue,
+ KCONF_FLAG_TRAILINGVALUE | (pconf?khc_handle_flags(pconf):0),
+ &conf)))
+ goto _shadow;
+ free_space = 1;
+
+ if (value) {
+ value++;
+ } else {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ }
+ } else {
+ value = pvalue;
+ conf = pconf;
+ free_space = 0;
+ }
+
+ if(!khc_is_handle(conf))
+ goto _shadow;
+
+ c = khc_space_from_handle(conf);
+
+ if(khc_is_user_handle(conf))
+ hku = khcint_space_open_key(c, KHM_PERM_READ);
+
+ if(khc_is_machine_handle(conf))
+ hkm = khcint_space_open_key(c, KHM_PERM_READ | KCONF_FLAG_MACHINE);
+
+ size = (DWORD) *bufsize;
+ if(hku) {
+ hr = RegQueryValueEx(hku, value, NULL, &type, (LPBYTE) buf, &size);
+ if(hr == ERROR_SUCCESS) {
+ if(type != REG_BINARY) {
+ rv = KHM_ERROR_TYPE_MISMATCH;
+ goto _exit;
+ }
+ else {
+ *bufsize = size;
+ rv = KHM_ERROR_SUCCESS;
+ goto _exit;
+ }
+ } else {
+ if(hr == ERROR_MORE_DATA) {
+ *bufsize = size;
+ rv = KHM_ERROR_TOO_LONG;
+ goto _exit;
+ }
+ }
+ }
+
+ size = (DWORD) *bufsize;
+ if(hkm) {
+ hr = RegQueryValueEx(hkm, value, NULL, &type, (LPBYTE) buf, &size);
+ if(hr == ERROR_SUCCESS) {
+ if(type != REG_BINARY) {
+ rv = KHM_ERROR_TYPE_MISMATCH;
+ goto _exit;
+ }
+ else {
+ *bufsize = size;
+ rv = KHM_ERROR_SUCCESS;
+ goto _exit;
+ }
+ } else {
+ if(hr == ERROR_MORE_DATA) {
+ *bufsize = size;
+ rv = KHM_ERROR_TOO_LONG;
+ goto _exit;
+ }
+ }
+ }
+
+ /* binary values aren't supported in schema */
+_shadow:
+ if(free_space && conf)
+ khc_close_space(conf);
+ if(khc_is_shadowed(pconf)) {
+ pconf = khc_shadow(pconf);
+ continue;
+ } else {
+ rv = KHM_ERROR_NOT_FOUND;
+ break;
+ }
+
+_exit:
+ if(free_space && conf)
+ khc_close_space(conf);
+ break;
+
+ }while (TRUE);
+
+ return rv;
+}
+
+/* obtains cs_conf_handle/cs_conf_global */
+KHMEXP khm_int32 KHMAPI
+khc_write_string(khm_handle pconf,
+ const wchar_t * pvalue,
+ wchar_t * buf)
+{
+ HKEY pk = NULL;
+ kconf_conf_space * c;
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+ LONG hr;
+ size_t cbsize;
+ const wchar_t * value = NULL;
+ int free_space = 0;
+ khm_handle conf = NULL;
+
+
+ if(!khc_is_config_running())
+ return KHM_ERROR_NOT_READY;
+
+ if(pconf && !khc_is_machine_handle(pconf) && !khc_is_user_handle(pconf))
+ return KHM_ERROR_INVALID_OPERATION;
+
+ if(FAILED(StringCbLength(buf, KCONF_MAXCB_STRING, &cbsize))) {
+ rv = KHM_ERROR_INVALID_PARAM;
+ goto _exit;
+ }
+
+ cbsize += sizeof(wchar_t);
+
+ if (khc_handle_flags(pconf) & KCONF_FLAG_WRITEIFMOD) {
+ wchar_t tmpbuf[512];
+ wchar_t * buffer;
+ size_t tmpsize = cbsize;
+ khm_boolean is_equal = FALSE;
+
+ if (cbsize <= sizeof(tmpbuf)) {
+ buffer = tmpbuf;
+ } else {
+ buffer = PMALLOC(cbsize);
+ }
+
+ if (KHM_SUCCEEDED(khc_read_string(pconf, pvalue, buffer, &tmpsize)) &&
+ tmpsize == cbsize) {
+ if (khc_handle_flags(pconf) & KCONF_FLAG_IFMODCI)
+ is_equal = !_wcsicmp(buffer, buf);
+ else
+ is_equal = !wcscmp(buffer, buf);
+ }
+
+ if (buffer != tmpbuf)
+ PFREE(buffer);
+
+ if (is_equal) {
+ return KHM_ERROR_SUCCESS;
+ }
+ }
+
+ if((value = wcsrchr(pvalue, L'\\')) != NULL) {
+ if(KHM_FAILED(khc_open_space(pconf, pvalue,
+ KCONF_FLAG_TRAILINGVALUE | (pconf?khc_handle_flags(pconf):0),
+ &conf)))
+ return KHM_ERROR_INVALID_PARAM;
+ free_space = 1;
+
+ if (value) {
+ value ++;
+ } else {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ }
+ } else {
+ value = pvalue;
+ conf = pconf;
+ free_space = 0;
+ }
+
+ if(!khc_is_handle(conf) || !buf) {
+ rv = KHM_ERROR_INVALID_PARAM;
+ goto _exit;
+ }
+
+ c = khc_space_from_handle(conf);
+
+ if(khc_is_user_handle(conf)) {
+ pk = khcint_space_open_key(c, KHM_PERM_WRITE | KHM_FLAG_CREATE);
+ } else {
+ pk = khcint_space_open_key(c, KHM_PERM_WRITE | KCONF_FLAG_MACHINE | KHM_FLAG_CREATE);
+ }
+
+ hr = RegSetValueEx(pk, value, 0, REG_SZ, (LPBYTE) buf, (DWORD) cbsize);
+
+ if(hr != ERROR_SUCCESS)
+ rv = KHM_ERROR_INVALID_OPERATION;
+
+_exit:
+ if(free_space)
+ khc_close_space(conf);
+ return rv;
+}
+
+/* obtaincs cs_conf_handle/cs_conf_global */
+KHMEXP khm_int32 KHMAPI
+khc_write_int32(khm_handle pconf,
+ const wchar_t * pvalue,
+ khm_int32 buf)
+{
+ HKEY pk = NULL;
+ kconf_conf_space * c;
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+ LONG hr;
+ const wchar_t * value = NULL;
+ int free_space = 0;
+ khm_handle conf = NULL;
+
+
+ if(!khc_is_config_running())
+ return KHM_ERROR_NOT_READY;
+
+ if(pconf && !khc_is_machine_handle(pconf) && !khc_is_user_handle(pconf))
+ return KHM_ERROR_INVALID_OPERATION;
+
+ if (khc_handle_flags(pconf) & KCONF_FLAG_WRITEIFMOD) {
+ khm_int32 tmpvalue;
+
+ if (KHM_SUCCEEDED(khc_read_int32(pconf, pvalue, &tmpvalue)) &&
+ tmpvalue == buf) {
+ return KHM_ERROR_SUCCESS;
+ }
+ }
+
+ if((value = wcsrchr(pvalue, L'\\')) != NULL) {
+ if(KHM_FAILED(khc_open_space(
+ pconf,
+ pvalue,
+ KCONF_FLAG_TRAILINGVALUE | (pconf?khc_handle_flags(pconf):0),
+ &conf)))
+ return KHM_ERROR_INVALID_PARAM;
+ free_space = 1;
+
+ if (value) {
+ value ++;
+ } else {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ }
+ } else {
+ value = pvalue;
+ conf = pconf;
+ free_space = 0;
+ }
+
+ if(!khc_is_handle(conf))
+ return KHM_ERROR_INVALID_PARAM;
+
+ c = khc_space_from_handle( conf);
+
+ if(khc_is_user_handle(conf)) {
+ pk = khcint_space_open_key(c, KHM_PERM_WRITE | KHM_FLAG_CREATE);
+ } else {
+ pk = khcint_space_open_key(c, KHM_PERM_WRITE | KCONF_FLAG_MACHINE | KHM_FLAG_CREATE);
+ }
+
+ hr = RegSetValueEx(pk, value, 0, REG_DWORD, (LPBYTE) &buf, sizeof(khm_int32));
+
+ if(hr != ERROR_SUCCESS)
+ rv = KHM_ERROR_INVALID_OPERATION;
+
+ if(free_space)
+ khc_close_space(conf);
+
+ return rv;
+}
+
+/* obtains cs_conf_handle/cs_conf_global */
+KHMEXP khm_int32 KHMAPI
+khc_write_int64(khm_handle pconf, const wchar_t * pvalue, khm_int64 buf) {
+ HKEY pk = NULL;
+ kconf_conf_space * c;
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+ LONG hr;
+ const wchar_t * value = NULL;
+ int free_space = 0;
+ khm_handle conf = NULL;
+
+
+ if(!khc_is_config_running())
+ return KHM_ERROR_NOT_READY;
+
+ if(pconf && !khc_is_machine_handle(pconf) && !khc_is_user_handle(pconf))
+ return KHM_ERROR_INVALID_OPERATION;
+
+ if (khc_handle_flags(pconf) & KCONF_FLAG_WRITEIFMOD) {
+ khm_int64 tmpvalue;
+
+ if (KHM_SUCCEEDED(khc_read_int64(pconf, pvalue, &tmpvalue)) &&
+ tmpvalue == buf) {
+ return KHM_ERROR_SUCCESS;
+ }
+ }
+
+ if((value = wcsrchr(pvalue, L'\\')) != NULL) {
+ if(KHM_FAILED(khc_open_space(
+ pconf,
+ pvalue,
+ KCONF_FLAG_TRAILINGVALUE | (pconf?khc_handle_flags(pconf):0),
+ &conf)))
+ return KHM_ERROR_INVALID_PARAM;
+ free_space = 1;
+
+ if (value) {
+ value ++;
+ } else {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ }
+ } else {
+ value = pvalue;
+ conf = pconf;
+ free_space = 0;
+ }
+
+ if(!khc_is_handle(conf))
+ return KHM_ERROR_INVALID_PARAM;
+
+ c = khc_space_from_handle( conf);
+
+ if(khc_is_user_handle(conf)) {
+ pk = khcint_space_open_key(c, KHM_PERM_WRITE | KHM_FLAG_CREATE);
+ } else {
+ pk = khcint_space_open_key(c, KHM_PERM_WRITE | KCONF_FLAG_MACHINE | KHM_FLAG_CREATE);
+ }
+
+ hr = RegSetValueEx(pk, value, 0, REG_QWORD, (LPBYTE) &buf, sizeof(khm_int64));
+
+ if(hr != ERROR_SUCCESS)
+ rv = KHM_ERROR_INVALID_OPERATION;
+
+ if(free_space)
+ khc_close_space(conf);
+
+ return rv;
+}
+
+/* obtains cs_conf_handle/cs_conf_global */
+KHMEXP khm_int32 KHMAPI
+khc_write_binary(khm_handle pconf,
+ const wchar_t * pvalue,
+ void * buf, khm_size bufsize) {
+ HKEY pk = NULL;
+ kconf_conf_space * c;
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+ LONG hr;
+ const wchar_t * value = NULL;
+ int free_space = 0;
+ khm_handle conf = NULL;
+
+
+ if(!khc_is_config_running())
+ return KHM_ERROR_NOT_READY;
+
+ if(pconf && !khc_is_machine_handle(pconf) && !khc_is_user_handle(pconf))
+ return KHM_ERROR_INVALID_OPERATION;
+
+ if((value = wcsrchr(pvalue, L'\\')) != NULL) {
+ if(KHM_FAILED(khc_open_space(
+ pconf,
+ pvalue,
+ KCONF_FLAG_TRAILINGVALUE | (pconf?khc_handle_flags(pconf):0),
+ &conf)))
+ return KHM_ERROR_INVALID_PARAM;
+ free_space = 1;
+
+ if (value) {
+ value ++;
+ } else {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ }
+ } else {
+ value = pvalue;
+ conf = pconf;
+ free_space = 0;
+ }
+
+ if(!khc_is_handle(conf))
+ return KHM_ERROR_INVALID_PARAM;
+
+ c = khc_space_from_handle(conf);
+
+ if(khc_is_user_handle(conf)) {
+ pk = khcint_space_open_key(c, KHM_PERM_WRITE | KHM_FLAG_CREATE);
+ } else {
+ pk = khcint_space_open_key(c, KHM_PERM_WRITE | KCONF_FLAG_MACHINE | KHM_FLAG_CREATE);
+ }
+
+ hr = RegSetValueEx(pk, value, 0, REG_BINARY, buf, (DWORD) bufsize);
+
+ if(hr != ERROR_SUCCESS)
+ rv = KHM_ERROR_INVALID_OPERATION;
+
+ if(free_space)
+ khc_close_space(conf);
+
+ return rv;
+}
+
+/* no locks */
+KHMEXP khm_int32 KHMAPI
+khc_get_config_space_name(khm_handle conf,
+ wchar_t * buf, khm_size * bufsize) {
+ kconf_conf_space * c;
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+
+ if(!khc_is_config_running())
+ return KHM_ERROR_NOT_READY;
+
+ if(!khc_is_handle(conf))
+ return KHM_ERROR_INVALID_PARAM;
+
+ c = khc_space_from_handle(conf);
+
+ if(!c->name) {
+ if(buf && *bufsize > 0)
+ buf[0] = L'\0';
+ else {
+ *bufsize = sizeof(wchar_t);
+ rv = KHM_ERROR_TOO_LONG;
+ }
+ } else {
+ size_t cbsize;
+
+ if(FAILED(StringCbLength(c->name, KCONF_MAXCB_NAME, &cbsize)))
+ return KHM_ERROR_UNKNOWN;
+
+ cbsize += sizeof(wchar_t);
+
+ if(!buf || cbsize > *bufsize) {
+ *bufsize = cbsize;
+ rv = KHM_ERROR_TOO_LONG;
+ } else {
+ StringCbCopy(buf, *bufsize, c->name);
+ *bufsize = cbsize;
+ }
+ }
+
+ return rv;
+}
+
+/* obtains cs_conf_handle/cs_conf_global */
+KHMEXP khm_int32 KHMAPI
+khc_get_config_space_parent(khm_handle conf, khm_handle * parent) {
+ kconf_conf_space * c;
+
+ if(!khc_is_config_running())
+ return KHM_ERROR_NOT_READY;
+
+ if(!khc_is_handle(conf))
+ return KHM_ERROR_INVALID_PARAM;
+
+ c = khc_space_from_handle(conf);
+
+ if(c == conf_root || c->parent == conf_root)
+ *parent = NULL;
+ else
+ *parent = khcint_handle_from_space(c->parent, khc_handle_flags(conf));
+
+ return KHM_ERROR_SUCCESS;
+}
+
+/* obtains cs_conf_global */
+KHMEXP khm_int32 KHMAPI
+khc_get_type(khm_handle conf, const wchar_t * value) {
+ HKEY hkm = NULL;
+ HKEY hku = NULL;
+ kconf_conf_space * c;
+ khm_int32 rv;
+ LONG hr = ERROR_SUCCESS;
+ DWORD type = 0;
+
+ if(!khc_is_config_running())
+ return KC_NONE;
+
+ if(!khc_is_handle(conf))
+ return KC_NONE;
+
+ c = khc_space_from_handle(conf);
+
+ if(!khc_is_machine_handle(conf))
+ hku = khcint_space_open_key(c, KHM_PERM_READ);
+ hkm = khcint_space_open_key(c, KHM_PERM_READ | KCONF_FLAG_MACHINE);
+
+ if(hku)
+ hr = RegQueryValueEx(hku, value, NULL, &type, NULL, NULL);
+ if(!hku || hr != ERROR_SUCCESS)
+ hr = RegQueryValueEx(hkm, value, NULL, &type, NULL, NULL);
+ if(((!hku && !hkm) || hr != ERROR_SUCCESS) && c->schema) {
+ int i;
+
+ for(i=0; i<c->nSchema; i++) {
+ if(!wcscmp(c->schema[i].name, value)) {
+ return c->schema[i].type;
+ }
+ }
+
+ return KC_NONE;
+ }
+
+ switch(type) {
+ case REG_MULTI_SZ:
+ case REG_SZ:
+ rv = KC_STRING;
+ break;
+ case REG_DWORD:
+ rv = KC_INT32;
+ break;
+ case REG_QWORD:
+ rv = KC_INT64;
+ break;
+ case REG_BINARY:
+ rv = KC_BINARY;
+ break;
+ default:
+ rv = KC_NONE;
+ }
+
+ return rv;
+}
+
+/* obtains cs_conf_global */
+KHMEXP khm_int32 KHMAPI
+khc_value_exists(khm_handle conf, const wchar_t * value) {
+ HKEY hku = NULL;
+ HKEY hkm = NULL;
+ kconf_conf_space * c;
+ khm_int32 rv = 0;
+ DWORD t;
+ int i;
+
+ if(!khc_is_config_running())
+ return KHM_ERROR_NOT_READY;
+
+ if(!khc_is_handle(conf))
+ return KHM_ERROR_INVALID_PARAM;
+
+ do {
+ c = khc_space_from_handle(conf);
+
+ if (khc_is_user_handle(conf))
+ hku = khcint_space_open_key(c, KHM_PERM_READ);
+ if (khc_is_machine_handle(conf))
+ hkm = khcint_space_open_key(c, KHM_PERM_READ | KCONF_FLAG_MACHINE);
+
+ if(hku && (RegQueryValueEx(hku, value, NULL, &t, NULL, NULL) == ERROR_SUCCESS))
+ rv |= KCONF_FLAG_USER;
+ if(hkm && (RegQueryValueEx(hkm, value, NULL, &t, NULL, NULL) == ERROR_SUCCESS))
+ rv |= KCONF_FLAG_MACHINE;
+
+ if(c->schema && khc_is_schema_handle(conf)) {
+ for(i=0; i<c->nSchema; i++) {
+ if(!wcscmp(c->schema[i].name, value)) {
+ rv |= KCONF_FLAG_SCHEMA;
+ break;
+ }
+ }
+ }
+
+ /* if the value is not found at this level and the handle is
+ shadowed, try the next level down. */
+ if (rv == 0 && khc_is_shadowed(conf))
+ conf = khc_shadow(conf);
+ else
+ break;
+ } while (conf);
+
+ return rv;
+}
+
+/* obtains cs_conf_global */
+KHMEXP khm_int32 KHMAPI
+khc_remove_value(khm_handle conf, const wchar_t * value, khm_int32 flags) {
+ HKEY hku = NULL;
+ HKEY hkm = NULL;
+ kconf_conf_space * c;
+ khm_int32 rv = KHM_ERROR_NOT_FOUND;
+ DWORD t;
+ LONG l;
+
+ if(!khc_is_config_running())
+ return KHM_ERROR_NOT_READY;
+
+ if(!khc_is_handle(conf))
+ return KHM_ERROR_INVALID_PARAM;
+
+ c = khc_space_from_handle(conf);
+
+ if(!khc_is_machine_handle(conf))
+ hku = khcint_space_open_key(c, KHM_PERM_READ);
+ hkm = khcint_space_open_key(c, KHM_PERM_READ | KCONF_FLAG_MACHINE);
+
+ if((flags == 0 ||
+ (flags & KCONF_FLAG_USER)) &&
+ hku && (RegQueryValueEx(hku, value, NULL,
+ &t, NULL, NULL) == ERROR_SUCCESS)) {
+ l = RegDeleteValue(hku, value);
+ if (l == ERROR_SUCCESS)
+ rv = KHM_ERROR_SUCCESS;
+ else
+ rv = KHM_ERROR_UNKNOWN;
+ }
+ if((flags == 0 ||
+ (flags & KCONF_FLAG_MACHINE)) &&
+ hkm && (RegQueryValueEx(hkm, value, NULL,
+ &t, NULL, NULL) == ERROR_SUCCESS)) {
+ l = RegDeleteValue(hkm, value);
+ if (l == ERROR_SUCCESS)
+ rv = (rv == KHM_ERROR_UNKNOWN)?KHM_ERROR_PARTIAL:
+ KHM_ERROR_SUCCESS;
+ else
+ rv = (rv == KHM_ERROR_SUCCESS)?KHM_ERROR_PARTIAL:
+ KHM_ERROR_UNKNOWN;
+ }
+
+ return rv;
+}
+
+/* called with cs_conf_global held */
+khm_int32
+khcint_remove_space(kconf_conf_space * c, khm_int32 flags) {
+ kconf_conf_space * cc;
+ kconf_conf_space * cn;
+ kconf_conf_space * p;
+
+ /* TODO: if this is the last child space and the parent is marked
+ for deletion, delete the parent as well. */
+
+ p = TPARENT(c);
+
+ /* We don't allow deleting top level keys. They are
+ predefined. */
+#ifdef DEBUG
+ assert(p);
+#endif
+ if (!p)
+ return KHM_ERROR_INVALID_OPERATION;
+
+ cc = TFIRSTCHILD(c);
+ while (cc) {
+ cn = LNEXT(cc);
+
+ khcint_remove_space(cc, flags);
+
+ cc = cn;
+ }
+
+ cc = TFIRSTCHILD(c);
+ if (!cc && c->refcount == 0) {
+ TDELCHILD(p, c);
+ khcint_free_space(c);
+ } else {
+ c->flags |= (flags &
+ (KCONF_SPACE_FLAG_DELETE_M |
+ KCONF_SPACE_FLAG_DELETE_U));
+
+ /* if all the registry spaces have been marked as deleted and
+ there is no schema, we should mark the space as deleted as
+ well. Note that ideally we only need to check for stores
+ which have data corresponding to this configuration space,
+ but this is a bit problematic since we don't monitor the
+ registry for changes. */
+ if ((c->flags &
+ (KCONF_SPACE_FLAG_DELETE_M |
+ KCONF_SPACE_FLAG_DELETE_U)) ==
+ (KCONF_SPACE_FLAG_DELETE_M |
+ KCONF_SPACE_FLAG_DELETE_U) &&
+ (!c->schema || c->nSchema == 0))
+
+ c->flags |= KCONF_SPACE_FLAG_DELETED;
+ }
+
+ if (c->regpath && p->regpath) {
+ HKEY hk;
+
+ if (flags & KCONF_SPACE_FLAG_DELETE_U) {
+ hk = khcint_space_open_key(p, KCONF_FLAG_USER);
+
+ if (hk)
+ khcint_RegDeleteKey(hk, c->name);
+ }
+ if (flags & KCONF_SPACE_FLAG_DELETE_M) {
+ hk = khcint_space_open_key(p, KCONF_FLAG_MACHINE);
+
+ if (hk)
+ khcint_RegDeleteKey(hk, c->name);
+ }
+ }
+
+ return KHM_ERROR_SUCCESS;
+}
+
+/* obtains cs_conf_global */
+KHMEXP khm_int32 KHMAPI
+khc_remove_space(khm_handle conf) {
+
+ /*
+ - mark this space as well as all child spaces as
+ 'delete-on-close' using flags. Mark should indicate which
+ repository to delete the space from. (user/machine)
+
+ - When each subspace is released, check if it has been marked
+ for deletion. If so, delete the marked spaces as well as
+ removing the space from kconf space tree.
+
+ - When removing a subspace from a space, check if the parent
+ space has any children left. If there are none, check if the
+ parent space is also marked for deletion.
+ */
+ kconf_conf_space * c;
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+ khm_int32 flags = 0;
+
+ if(!khc_is_config_running())
+ return KHM_ERROR_NOT_READY;
+
+ if(!khc_is_handle(conf))
+ return KHM_ERROR_INVALID_PARAM;
+
+ c = khc_space_from_handle(conf);
+
+ EnterCriticalSection(&cs_conf_global);
+
+ if (khc_is_machine_handle(conf))
+ flags |= KCONF_SPACE_FLAG_DELETE_M;
+ if (khc_is_user_handle(conf))
+ flags |= KCONF_SPACE_FLAG_DELETE_U;
+
+ rv = khcint_remove_space(c, flags);
+
+ LeaveCriticalSection(&cs_conf_global);
+
+ return rv;
+}
+
+/* no locks */
+khm_boolean
+khcint_is_valid_name(wchar_t * name)
+{
+ size_t cbsize;
+ if(FAILED(StringCbLength(name, KCONF_MAXCB_NAME, &cbsize)))
+ return FALSE;
+ return TRUE;
+}
+
+/* no locks */
+khm_int32
+khcint_validate_schema(const kconf_schema * schema,
+ int begin,
+ int *end)
+{
+ int i;
+ int state = 0;
+ int end_found = 0;
+
+ i=begin;
+ while(!end_found) {
+ switch(state) {
+ case 0: /* initial. this record should start a config space */
+ if(!khcint_is_valid_name(schema[i].name) ||
+ schema[i].type != KC_SPACE)
+ return KHM_ERROR_INVALID_PARAM;
+ state = 1;
+ break;
+
+ case 1: /* we are inside a config space, in the values area */
+ if(!khcint_is_valid_name(schema[i].name))
+ return KHM_ERROR_INVALID_PARAM;
+ if(schema[i].type == KC_SPACE) {
+ if(KHM_FAILED(khcint_validate_schema(schema, i, &i)))
+ return KHM_ERROR_INVALID_PARAM;
+ state = 2;
+ } else if(schema[i].type == KC_ENDSPACE) {
+ end_found = 1;
+ if(end)
+ *end = i;
+ } else {
+ if(schema[i].type != KC_STRING &&
+ schema[i].type != KC_INT32 &&
+ schema[i].type != KC_INT64 &&
+ schema[i].type != KC_BINARY)
+ return KHM_ERROR_INVALID_PARAM;
+ }
+ break;
+
+ case 2: /* we are inside a config space, in the subspace area */
+ if(schema[i].type == KC_SPACE) {
+ if(KHM_FAILED(khcint_validate_schema(schema, i, &i)))
+ return KHM_ERROR_INVALID_PARAM;
+ } else if(schema[i].type == KC_ENDSPACE) {
+ end_found = 1;
+ if(end)
+ *end = i;
+ } else {
+ return KHM_ERROR_INVALID_PARAM;
+ }
+ break;
+
+ default:
+ /* unreachable */
+ return KHM_ERROR_INVALID_PARAM;
+ }
+ i++;
+ }
+
+ return KHM_ERROR_SUCCESS;
+}
+
+/* obtains cs_conf_handle/cs_conf_global; called with cs_conf_global */
+khm_int32
+khcint_load_schema_i(khm_handle parent, const kconf_schema * schema,
+ int begin, int * end)
+{
+ int i;
+ int state = 0;
+ int end_found = 0;
+ kconf_conf_space * thisconf = NULL;
+ khm_handle h = NULL;
+
+ i=begin;
+ while(!end_found) {
+ switch(state) {
+ case 0: /* initial. this record should start a config space */
+ LeaveCriticalSection(&cs_conf_global);
+ if(KHM_FAILED(khc_open_space(parent, schema[i].name,
+ KHM_FLAG_CREATE, &h))) {
+ EnterCriticalSection(&cs_conf_global);
+ return KHM_ERROR_INVALID_PARAM;
+ }
+ EnterCriticalSection(&cs_conf_global);
+ thisconf = khc_space_from_handle(h);
+ thisconf->schema = schema + (begin + 1);
+ thisconf->nSchema = 0;
+ state = 1;
+ break;
+
+ case 1: /* we are inside a config space, in the values area */
+ if(schema[i].type == KC_SPACE) {
+ thisconf->nSchema = i - (begin + 1);
+ if(KHM_FAILED(khcint_load_schema_i(h, schema, i, &i)))
+ return KHM_ERROR_INVALID_PARAM;
+ state = 2;
+ } else if(schema[i].type == KC_ENDSPACE) {
+ thisconf->nSchema = i - (begin + 1);
+ end_found = 1;
+ if(end)
+ *end = i;
+ LeaveCriticalSection(&cs_conf_global);
+ khc_close_space(h);
+ EnterCriticalSection(&cs_conf_global);
+ }
+ break;
+
+ case 2: /* we are inside a config space, in the subspace area */
+ if(schema[i].type == KC_SPACE) {
+ if(KHM_FAILED(khcint_load_schema_i(h, schema, i, &i)))
+ return KHM_ERROR_INVALID_PARAM;
+ } else if(schema[i].type == KC_ENDSPACE) {
+ end_found = 1;
+ if(end)
+ *end = i;
+ LeaveCriticalSection(&cs_conf_global);
+ khc_close_space(h);
+ EnterCriticalSection(&cs_conf_global);
+ } else {
+ return KHM_ERROR_INVALID_PARAM;
+ }
+ break;
+
+ default:
+ /* unreachable */
+ return KHM_ERROR_INVALID_PARAM;
+ }
+ i++;
+ }
+
+ return KHM_ERROR_SUCCESS;
+}
+
+/* obtains cs_conf_handle/cs_conf_global */
+KHMEXP khm_int32 KHMAPI
+khc_load_schema(khm_handle conf, const kconf_schema * schema)
+{
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+
+ if(!khc_is_config_running())
+ return KHM_ERROR_NOT_READY;
+
+ if(conf && !khc_is_handle(conf))
+ return KHM_ERROR_INVALID_PARAM;
+
+ if(KHM_FAILED(khcint_validate_schema(schema, 0, NULL)))
+ return KHM_ERROR_INVALID_PARAM;
+
+ EnterCriticalSection(&cs_conf_global);
+ rv = khcint_load_schema_i(conf, schema, 0, NULL);
+ LeaveCriticalSection(&cs_conf_global);
+
+ return rv;
+}
+
+/* obtains cs_conf_handle/cs_conf_global; called with cs_conf_global */
+khm_int32
+khcint_unload_schema_i(khm_handle parent, const kconf_schema * schema,
+ int begin, int * end)
+{
+ int i;
+ int state = 0;
+ int end_found = 0;
+ kconf_conf_space * thisconf = NULL;
+ khm_handle h = NULL;
+
+ i=begin;
+ while(!end_found) {
+ switch(state) {
+ case 0: /* initial. this record should start a config space */
+ LeaveCriticalSection(&cs_conf_global);
+ if(KHM_FAILED(khc_open_space(parent, schema[i].name, 0, &h))) {
+ EnterCriticalSection(&cs_conf_global);
+ return KHM_ERROR_INVALID_PARAM;
+ }
+ EnterCriticalSection(&cs_conf_global);
+ thisconf = khc_space_from_handle(h);
+ if(thisconf->schema == (schema + (begin + 1))) {
+ thisconf->schema = NULL;
+ thisconf->nSchema = 0;
+ }
+ state = 1;
+ break;
+
+ case 1: /* we are inside a config space, in the values area */
+ if(schema[i].type == KC_SPACE) {
+ if(KHM_FAILED(khcint_unload_schema_i(h, schema, i, &i)))
+ return KHM_ERROR_INVALID_PARAM;
+ state = 2;
+ } else if(schema[i].type == KC_ENDSPACE) {
+ end_found = 1;
+ if(end)
+ *end = i;
+ LeaveCriticalSection(&cs_conf_global);
+ khc_close_space(h);
+ EnterCriticalSection(&cs_conf_global);
+ }
+ break;
+
+ case 2: /* we are inside a config space, in the subspace area */
+ if(schema[i].type == KC_SPACE) {
+ if(KHM_FAILED(khcint_unload_schema_i(h, schema, i, &i)))
+ return KHM_ERROR_INVALID_PARAM;
+ } else if(schema[i].type == KC_ENDSPACE) {
+ end_found = 1;
+ if(end)
+ *end = i;
+ LeaveCriticalSection(&cs_conf_global);
+ khc_close_space(h);
+ EnterCriticalSection(&cs_conf_global);
+ } else {
+ return KHM_ERROR_INVALID_PARAM;
+ }
+ break;
+
+ default:
+ /* unreachable */
+ return KHM_ERROR_INVALID_PARAM;
+ }
+ i++;
+ }
+
+ return KHM_ERROR_SUCCESS;
+}
+
+/* obtains cs_conf_handle/cs_conf_global */
+KHMEXP khm_int32 KHMAPI
+khc_unload_schema(khm_handle conf, const kconf_schema * schema)
+{
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+
+ if(!khc_is_config_running())
+ return KHM_ERROR_NOT_READY;
+
+ if(conf && !khc_is_handle(conf))
+ return KHM_ERROR_INVALID_PARAM;
+
+ if(KHM_FAILED(khcint_validate_schema(schema, 0, NULL)))
+ return KHM_ERROR_INVALID_PARAM;
+
+ EnterCriticalSection(&cs_conf_global);
+ rv = khcint_unload_schema_i(conf, schema, 0, NULL);
+ LeaveCriticalSection(&cs_conf_global);
+
+ return rv;
+}
+
+/* obtaincs cs_conf_handle/cs_conf_global */
+KHMEXP khm_int32 KHMAPI
+khc_enum_subspaces(khm_handle conf,
+ khm_handle prev,
+ khm_handle * next)
+{
+ kconf_conf_space * s;
+ kconf_conf_space * c;
+ kconf_conf_space * p;
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+
+ if(!khc_is_config_running())
+ return KHM_ERROR_NOT_READY;
+
+ if(!khc_is_handle(conf) || next == NULL ||
+ (prev != NULL && !khc_is_handle(prev)))
+ return KHM_ERROR_INVALID_PARAM;
+
+ s = khc_space_from_handle(conf);
+
+ if(prev == NULL) {
+ /* first off, we enumerate all the registry spaces regardless of
+ whether the handle is applicable for some registry space or not.
+ See notes for khc_begin_enum_subspaces() for reasons as to why
+ this is done (notes are in kconfig.h)*/
+
+ /* go through the user hive first */
+ {
+ HKEY hk_conf;
+
+ hk_conf = khcint_space_open_key(s, 0);
+ if(hk_conf) {
+ wchar_t name[KCONF_MAXCCH_NAME];
+ khm_handle h;
+ int idx;
+
+ idx = 0;
+ while(RegEnumKey(hk_conf, idx,
+ name, ARRAYLENGTH(name)) == ERROR_SUCCESS) {
+ wchar_t * tilde;
+ tilde = wcschr(name, L'~');
+ if (tilde)
+ *tilde = 0;
+ if(KHM_SUCCEEDED(khc_open_space(conf, name, 0, &h)))
+ khc_close_space(h);
+ idx++;
+ }
+ }
+ }
+
+ /* go through the machine hive next */
+ {
+ HKEY hk_conf;
+
+ hk_conf = khcint_space_open_key(s, KCONF_FLAG_MACHINE);
+ if(hk_conf) {
+ wchar_t name[KCONF_MAXCCH_NAME];
+ khm_handle h;
+ int idx;
+
+ idx = 0;
+ while(RegEnumKey(hk_conf, idx,
+ name, ARRAYLENGTH(name)) == ERROR_SUCCESS) {
+ wchar_t * tilde;
+ tilde = wcschr(name, L'~');
+ if (tilde)
+ *tilde = 0;
+
+ if(KHM_SUCCEEDED(khc_open_space(conf, name,
+ KCONF_FLAG_MACHINE, &h)))
+ khc_close_space(h);
+ idx++;
+ }
+ }
+ }
+
+ /* don't need to go through schema, because that was already
+ done when the schema was loaded. */
+ }
+
+ /* at last we are now ready to return the results */
+ EnterCriticalSection(&cs_conf_global);
+ if(prev == NULL) {
+ c = TFIRSTCHILD(s);
+ rv = KHM_ERROR_SUCCESS;
+ } else {
+ p = khc_space_from_handle(prev);
+ if(TPARENT(p) == s)
+ c = LNEXT(p);
+ else
+ c = NULL;
+ }
+ LeaveCriticalSection(&cs_conf_global);
+
+ if(prev != NULL)
+ khc_close_space(prev);
+
+ if(c) {
+ *next = khcint_handle_from_space(c, khc_handle_flags(conf));
+ rv = KHM_ERROR_SUCCESS;
+ } else {
+ *next = NULL;
+ rv = KHM_ERROR_NOT_FOUND;
+ }
+
+ return rv;
+}
+
+/* obtains cs_conf_handle/cs_conf_global */
+KHMEXP khm_int32 KHMAPI
+khc_write_multi_string(khm_handle conf, const wchar_t * value, wchar_t * buf)
+{
+ size_t cb;
+ wchar_t vbuf[KCONF_MAXCCH_STRING];
+ wchar_t *tb;
+ khm_int32 rv;
+
+ if(!khc_is_config_running())
+ return KHM_ERROR_NOT_READY;
+ if(!khc_is_handle(conf) || buf == NULL || value == NULL)
+ return KHM_ERROR_INVALID_PARAM;
+
+ if(multi_string_to_csv(NULL, &cb, buf) != KHM_ERROR_TOO_LONG)
+ return KHM_ERROR_INVALID_PARAM;
+
+ if (cb < sizeof(vbuf))
+ tb = vbuf;
+ else
+ tb = PMALLOC(cb);
+
+ assert(tb != NULL);
+
+ multi_string_to_csv(tb, &cb, buf);
+ rv = khc_write_string(conf, value, tb);
+
+ if (tb != vbuf)
+ PFREE(tb);
+ return rv;
+}
+
+/* obtains cs_conf_handle/cs_conf_global */
+KHMEXP khm_int32 KHMAPI
+khc_read_multi_string(khm_handle conf, const wchar_t * value,
+ wchar_t * buf, khm_size * bufsize)
+{
+ wchar_t vbuf[KCONF_MAXCCH_STRING];
+ wchar_t * tb;
+ khm_size cbbuf;
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+
+ if(!khc_is_config_running())
+ return KHM_ERROR_NOT_READY;
+
+ if(!bufsize)
+ return KHM_ERROR_INVALID_PARAM;
+
+ rv = khc_read_string(conf, value, NULL, &cbbuf);
+ if(rv != KHM_ERROR_TOO_LONG)
+ return rv;
+
+ if (cbbuf < sizeof(vbuf))
+ tb = vbuf;
+ else
+ tb = PMALLOC(cbbuf);
+
+ assert(tb != NULL);
+
+ rv = khc_read_string(conf, value, tb, &cbbuf);
+
+ if(KHM_FAILED(rv))
+ goto _exit;
+
+ rv = csv_to_multi_string(buf, bufsize, tb);
+
+_exit:
+ if (tb != vbuf)
+ PFREE(tb);
+
+ return rv;
+}
diff --git a/src/windows/identity/kconfig/kconfig.h b/src/windows/identity/kconfig/kconfig.h
index b550d13584..691fe7115c 100644
--- a/src/windows/identity/kconfig/kconfig.h
+++ b/src/windows/identity/kconfig/kconfig.h
@@ -1,960 +1,960 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#ifndef __KHIMAIRA_KCONFIG_H
-#define __KHIMAIRA_KCONFIG_H
-
-#include<khdefs.h>
-#include<mstring.h>
-
-/*! \defgroup kconf NetIDMgr Configuration Provider */
-/*@{*/
-
-/*! \brief Configuration schema descriptor record
-
- The schema descriptor is a convenient way to provide a default set
- of configuration options for a part of an application. It
- describes the configuration spaces and the values and subspaces
- contained in each space.
-
- \see kconf_load_schema()
-*/
-typedef struct tag_kconf_schema {
- wchar_t * name; /*!< name of the object being described.
- Optional for KC_ENDSPACE type object,
- but required for everything else.
- Names can be upto KCONF_MAXCCH_NAME
- characters in length. */
- khm_int32 type; /*!< type of the object. Can be one of
- KC_SPACE, KC_ENDSPACE, KC_INT32,
- KC_INT64, KC_STRING or KC_BINARY */
- khm_ui_8 value; /*!< the value of the object. It is not
- used for KC_SPACE and KC_ENDSPACE
- typed objects. For a KC_STRING, this
- contains a pointer to the string
- value. The string should not be
- longer than KCONF_MAXCCH_STRING
- characters. KC_INT32 and KC_INT64
- objects store the value directly in
- this field, while KC_BINARY objects do
- not support defining a default value
- here. */
- wchar_t * description;/*!< a friendly description of the value
- or configuration space. */
-} kconf_schema;
-
-/*! \name Configuration data types
- @{*/
-/*! \brief Not a known type */
-#define KC_NONE 0
-
-/*! \brief When used as ::kconf_schema \a type, defines the start of a configuration space.
-
- There should be a subsequent KC_ENDSPACE record in the schema
- which defines the end of this configuration space.
-
- \a name specifies the name of the configuration space. Optionally
- use \a description to provide a description.*/
-#define KC_SPACE 1
-
-/*! \brief Ends a configuration space started with KC_SPACE */
-#define KC_ENDSPACE 2
-
-/*! \brief A 32 bit integer
-
- Specifies a configuration parameter named \a name which is of this
- type. Use \a description to provide an optional description of
- the value.
-
- \a value specifies a default value for this parameter in the lower
- 32 bits.
-*/
-#define KC_INT32 3
-
-/*! \brief A 64 bit integer
-
- Specifies a configuration parameter named \a name which is of this
- type. Use \a description to provide an optional description of
- the value.
-
- \a value specifies a default value for this parameter.
-*/
-#define KC_INT64 4
-
-/*! \brief A unicode string
-
- Specifies a configuration parameter named \a name which is of this
- type. Use \a description to provide an optional description of
- the value.
-
- \a value specifies a default value for this parameter which should
- be a pointer to a NULL terminated unicode string of no more than
- ::KCONF_MAXCCH_STRING characters.
-*/
-#define KC_STRING 5
-
-/*! \brief An unparsed binary stream
-
- Specifies a configuration parameter named \a name which is of this
- type. Use \a description to provide an optional description of
- the value.
-
- Default values are not supported for binary streams. \a value is
- ignored.
-*/
-#define KC_BINARY 6
-/*@}*/
-
-/*! \brief This is the root configuration space */
-#define KCONF_FLAG_ROOT 0x00000001
-
-/*! \brief Indicates the configuration store which stores user-specific information */
-#define KCONF_FLAG_USER 0x00000002
-
-/*! \brief Indicates the configuration store which stores machine-specific information */
-#define KCONF_FLAG_MACHINE 0x00000004
-
-/*! \brief Indicates the configuration store which stores the schema */
-#define KCONF_FLAG_SCHEMA 0x00000008
-
-/*! \brief Indicates that the last component of the given configuration path is to be considered to be a configuration value */
-#define KCONF_FLAG_TRAILINGVALUE 0x00000020
-
-/*! \brief Only write values back there is a change
-
- Any write operations using the handle with check if the value
- being written is different from the value being read from the
- handle. It will only be written if the value is different.
-
- \note Note that the value being read from a handle takes schema and
- shadowed configuration handles into consideration while the value
- being written is only written to the topmost layer of
- configuration that can be written to.
-
- \note Note also that this flag does not affect binary values.
- */
-#define KCONF_FLAG_WRITEIFMOD 0x00000040
-
-/*! \brief Use case-insensitive comparison for KCONF_FLAG_WRITEIFMOD
-
- When used in combination with \a KCONF_FLAG_WRITEIFMOD , the
- string comparison used when determining whether the string read
- from the configuration handle is the same as the string being
- written will be case insensitive. If this flag is not set, the
- comparison will be case sensitive.
- */
-#define KCONF_FLAG_IFMODCI 0x00000080
-
-/*! \brief Do not parse the configuration space name
-
- If set, disables the parsing of the configuration space for
- subspaces. The space name is taken verbatim to be a configuration
- space name. This can be used when there can be forward slashes or
- backslahes in the name which are not escaped.
-
- By default, the configuration space name,
-
- \code
- L"foo\\bar"
- \endcode
-
- is taken to mean the configuration space \a bar which is a
- subspace of \a foo. If ::KCONF_FLAG_NOPARSENAME is set, then this
- is taken to mean configuration space \a foo\\bar.
- */
-#define KCONF_FLAG_NOPARSENAME 0x00000040
-
-/*! \brief Maximum number of allowed characters (including terminating NULL) in a name
-
- \note This is a hard limit in Windows, since we are mapping
- configuration spaces to registry keys.
-*/
-#define KCONF_MAXCCH_NAME 256
-
-/*! \brief Maximum number of allowed bytes (including terminating NULL) in a name */
-#define KCONF_MAXCB_NAME (KCONF_MAXCCH_NAME * sizeof(wchar_t))
-
-/*! \brief Maximum level of nesting for configuration spaces
- */
-#define KCONF_MAX_DEPTH 16
-
-/*! \brief Maximum number of allowed characters (including terminating NULL) in a configuration path */
-#define KCONF_MAXCCH_PATH (KCONF_MAXCCH_NAME * KCONF_MAX_DEPTH)
-
-/*! \brief Maximum number of allowed bytes (including terminating NULL) in a configuration path */
-#define KCONF_MAXCB_PATH (KCONF_MAXCCH_PATH * sizeof(wchar_t))
-
-/*! \brief Maximum number of allowed characters (including terminating NULL) in a string */
-#define KCONF_MAXCCH_STRING KHM_MAXCCH_STRING
-
-/*! \brief Maximum number of allowed bytes (including terminating NULL) in a string */
-#define KCONF_MAXCB_STRING (KCONF_MAXCCH_STRING * sizeof(wchar_t))
-
-/*! \brief Open a configuration space
-
- Opens the configuration space specified by \a cspace. By default,
- the opened space includes user,machine and schema configuration
- stores. However, you can specify a subset of these.
-
- If the configuration space does not exist and the \a flags specify
- KHM_FLAG_CREATE, then the configuration space is created. The
- stores that are affected by the create operation depend on \a
- flags. If the \a flags only specifies ::KCONF_FLAG_MACHINE, then
- the configuration space is created in the machine store. If \a
- flags specifies any combination of stores including \a
- ::KCONF_FLAG_USER, then the configuration space is created in the
- user store. Note that ::KCONF_FLAG_SCHEMA is readonly.
-
- Once opened, use khc_close_space() to close the configuration
- space.
-
- \param[in] parent The parent configuration space. The path
- specified in \a cspace is relative to the parent. Set this to
- NULL to indicate the root configuration space.
-
- \param[in] cspace The confiuration path. This can be up to
- ::KCONF_MAXCCH_PATH characters in length. Use either
- backslashes or forward slashes to specify hiearchy. Set this
- to NULL to reopen the parent configuration space.
-
- \param[in] flags Flags. This can be a combination of KCONF_FLAG_*
- constants and KHM_FLAG_CREATE. If none of ::KCONF_FLAG_USER,
- ::KCONF_FLAG_MACHINE or ::KCONF_FLAG_SCHEMA is specified, then
- it defaults to all three.
-
- \param[out] result Pointer to a handle which receives the handle
- to the opened configuration space if the call succeeds.
-
- \note You can re-open a configuration space with different flags
- such as ::KCONF_FLAG_MACHINE by specifying NULL for \a cspace
- and settings \a flags to the required flags.
-
-*/
-KHMEXP khm_int32 KHMAPI
-khc_open_space(khm_handle parent, const wchar_t * cspace, khm_int32 flags,
- khm_handle * result);
-
-/*! \brief Set the shadow space for a configuration handle
-
- The handle specified by \a lower becomes a shadow for the handle
- specified by \a upper. Any configuration value that is queried in
- \a upper that does not exist in \a upper will be queried in \a
- lower.
-
- If \a upper already had a shadow handle, that handle will be
- replaced by \a lower. The handle \a lower still needs to be
- closed by a call to khc_close_space(). However, closing \a lower
- will not affect \a upper which will still treat the configuration
- space pointed to by \a lower to be it's shadow.
-
- Shadows are specific to handles and not configuration spaces.
- Shadowing a configuration space using one handle does not affect
- any other handles which may be obtained for the same configuration
- space.
-
- Specify NULL for \a lower to remove any prior shadow.
- */
-KHMEXP khm_int32 KHMAPI
-khc_shadow_space(khm_handle upper, khm_handle lower);
-
-/*! \brief Close a handle opened with khc_open_space()
-*/
-KHMEXP khm_int32 KHMAPI
-khc_close_space(khm_handle conf);
-
-/*! \brief Read a string value from a configuration space
-
- The \a value_name parameter specifies the value to read from the
- configuration space. This can be either a value name or a value
- path consisting of a series nested configuration space names
- followed by the value name all separated by backslashes or forward
- slashes.
-
- For example: If \a conf is a handle to the configuration space \c
- 'A/B/C', then the value name \c 'D/E/v' refers to the value named
- \c 'v' in the configuration space \c 'A/B/C/D/E'.
-
- The specific configuration store that is used to access the value
- depends on the flags that were specified in the call to
- khc_open_space(). The precedence of configuration stores are as
- follows:
-
- - If KCONF_FLAG_USER was specified, then the user configuration
- space.
-
- - Otherwise, if KCONF_FLAG_MACHINE was specified, then the machine
- configuration space.
-
- - Otherwise, if KCONF_FLAG_SCHEMA was specified, the the schema
- store.
-
- Note that not specifying any of the configuration store specifiers
- in the call to khc_open_space() is equivalent to specifying all
- three.
-
- If the value is not found in the configuration space and any
- shadowed configuration spaces, the function returns \a
- KHM_ERROR_NOT_FOUND. In this case, the buffer is left unmodified.
-
- \param[in] buf Buffer to copy the string to. Specify NULL to just
- retrieve the number of required bytes.
-
- \param[in,out] bufsize On entry, specifies the number of bytes of
- space available at the location specified by \a buf. On exit
- specifies the number of bytes actually copied or the size of
- the required buffer if \a buf is NULL or insufficient.
-
- \retval KHM_ERROR_NOT_READY The configuration provider has not started
- \retval KHM_ERROR_INVALID_PARAM One or more of the supplied parameters are not valid
- \retval KHM_ERROR_TYPE_MISMATCH The specified value is not a string
- \retval KHM_ERROR_TOO_LONG \a buf was NULL or the size of the buffer was insufficient. The required size is in bufsize.
- \retval KHM_ERROR_SUCCESS Success. The number of bytes copied is in bufsize.
- \retval KHM_ERROR_NOT_FOUND The value was not found.
-
- \see khc_open_space()
-*/
-KHMEXP khm_int32 KHMAPI
-khc_read_string(khm_handle conf,
- const wchar_t * value_name,
- wchar_t * buf,
- khm_size * bufsize);
-
-/*! \brief Read a multi-string value from a configuration space
-
- The \a value_name parameter specifies the value to read from the
- configuration space. This can be either a value name or a value
- path consisting of a series nested configuration space names
- followed by the value name all separated by backslashes or forward
- slashes.
-
- For example: If \a conf is a handle to the configuration space \c
- 'A/B/C', then the value name \c 'D/E/v' refers to the value named
- \c 'v' in the configuration space \c 'A/B/C/D/E'.
-
- The specific configuration store that is used to access the value
- depends on the flags that were specified in the call to
- khc_open_space(). The precedence of configuration stores are as
- follows:
-
- - If KCONF_FLAG_USER was specified, then the user configuration
- space.
-
- - Otherwise, if KCONF_FLAG_MACHINE was specified, then the machine
- configuration space.
-
- - Otherwise, if KCONF_FLAG_SCHEMA was specified, the the schema
- store.
-
- A multi-string is a pseudo data type. The value in the
- configuration store should contain a CSV string. Each comma
- separated value in the CSV string is considered to be a separate
- value. Empty values are not allowed. The buffer pointed to by \a
- buf will receive these values in the form of a series of NULL
- terminated strings terminated by an empty string (or equivalently,
- the last string will be terminated by a double NULL).
-
- Note that not specifying any of the configuration store specifiers
- in the call to khc_open_space() is equivalent to specifying all
- three.
-
- If the value is not found in the configuration space and any
- shadowed configuration spaces, the function returns \a
- KHM_ERROR_NOT_FOUND. In this case, the buffer is left unmodified.
-
- \param[in] buf Buffer to copy the multi-string to. Specify NULL
- to just retrieve the number of required bytes.
-
- \param[in,out] bufsize On entry, specifies the number of bytes of
- space available at the location specified by \a buf. On exit
- specifies the number of bytes actually copied or the size of
- the required buffer if \a buf is NULL or insufficient.
-
- \retval KHM_ERROR_NOT_READY The configuration provider has not started
- \retval KHM_ERROR_INVALID_PARAM One or more of the supplied parameters are not valid
- \retval KHM_ERROR_TYPE_MISMATCH The specified value is not a string
- \retval KHM_ERROR_TOO_LONG \a buf was NULL or the size of the buffer was insufficient. The required size is in bufsize.
- \retval KHM_ERROR_SUCCESS Success. The number of bytes copied is in bufsize.
- \retval KHM_ERROR_NOT_FOUND The value was not found.
-
- \see khc_open_space()
-*/
-KHMEXP khm_int32 KHMAPI
-khc_read_multi_string(khm_handle conf,
- const wchar_t * value_name,
- wchar_t * buf,
- khm_size * bufsize);
-
-/*! \brief Read a 32 bit integer value from a configuration space
-
- The \a value_name parameter specifies the value to read from the
- configuration space. This can be either a value name or a value
- path consisting of a series nested configuration space names
- followed by the value name all separated by backslashes or forward
- slashes.
-
- For example: If \a conf is a handle to the configuration space \c
- 'A/B/C', then the value name \c 'D/E/v' refers to the value named
- \c 'v' in the configuration space \c 'A/B/C/D/E'.
-
- The specific configuration store that is used to access the value
- depends on the flags that were specified in the call to
- khc_open_space(). The precedence of configuration stores are as
- follows:
-
- - If KCONF_FLAG_USER was specified, then the user configuration
- space.
-
- - Otherwise, if KCONF_FLAG_MACHINE was specified, then the machine
- configuration space.
-
- - Otherwise, if KCONF_FLAG_SCHEMA was specified, the the schema
- store.
-
- Note that not specifying any of the configuration store specifiers
- in the call to khc_open_space() is equivalent to specifying all
- three.
-
- If the value is not found in the configuration space and any
- shadowed configuration spaces, the function returns \a
- KHM_ERROR_NOT_FOUND. In this case, the buffer is left unmodified.
-
- \param[in] conf Handle to a configuration space
- \param[in] value The value to query
- \param[out] buf The buffer to receive the value
-
- \retval KHM_ERROR_NOT_READY The configuration provider has not started.
- \retval KHM_ERROR_SUCCESS Success. The value that was read was placed in \a buf
- \retval KHM_ERROR_NOT_FOUND The specified value was not found
- \retval KHM_ERROR_INVALID_PARAM One or more parameters were invalid
- \retval KHM_ERROR_TYPE_MISMATCH The specified value was found but was not of the correct type.
- \see khc_open_space()
-*/
-KHMEXP khm_int32 KHMAPI
-khc_read_int32(khm_handle conf,
- const wchar_t * value_name,
- khm_int32 * buf);
-
-/*! \brief Read a 64 bit integer value from a configuration space
-
- The \a value_name parameter specifies the value to read from the
- configuration space. This can be either a value name or a value
- path consisting of a series nested configuration space names
- followed by the value name all separated by backslashes or forward
- slashes.
-
- For example: If \a conf is a handle to the configuration space \c
- 'A/B/C', then the value name \c 'D/E/v' refers to the value named
- \c 'v' in the configuration space \c 'A/B/C/D/E'.
-
- The specific configuration store that is used to access the value
- depends on the flags that were specified in the call to
- khc_open_space(). The precedence of configuration stores are as
- follows:
-
- - If KCONF_FLAG_USER was specified, then the user configuration
- space.
-
- - Otherwise, if KCONF_FLAG_MACHINE was specified, then the machine
- configuration space.
-
- - Otherwise, if KCONF_FLAG_SCHEMA was specified, the the schema
- store.
-
- Note that not specifying any of the configuration store specifiers
- in the call to khc_open_space() is equivalent to specifying all
- three.
-
- If the value is not found in the configuration space and any
- shadowed configuration spaces, the function returns \a
- KHM_ERROR_NOT_FOUND. In this case, the buffer is left unmodified.
-
- \param[in] conf Handle to a configuration space
- \param[in] value_name The value to query
- \param[out] buf The buffer to receive the value
-
- \retval KHM_ERROR_NOT_READY The configuration provider has not started
- \retval KHM_ERROR_SUCCESS Success. The value that was read was placed in \a buf
- \retval KHM_ERROR_NOT_FOUND The specified value was not found
- \retval KHM_ERROR_INVALID_PARAM One or more parameters were invalid
- \retval KHM_ERROR_TYPE_MISMATCH The specified value was found but was not the correct data type.
-
- \see khc_open_space()
-*/
-KHMEXP khm_int32 KHMAPI
-khc_read_int64(khm_handle conf,
- const wchar_t * value_name,
- khm_int64 * buf);
-
-/*! \brief Read a binary value from a configuration space
-
- The \a value_name parameter specifies the value to read from the
- configuration space. This can be either a value name or a value
- path consisting of a series nested configuration space names
- followed by the value name all separated by backslashes or forward
- slashes.
-
- For example: If \a conf is a handle to the configuration space \c
- 'A/B/C', then the value name \c 'D/E/v' refers to the value named
- \c 'v' in the configuration space \c 'A/B/C/D/E'.
-
- The specific configuration store that is used to access the value
- depends on the flags that were specified in the call to
- khc_open_space(). The precedence of configuration stores are as
- follows:
-
- - If KCONF_FLAG_USER was specified, then the user configuration
- space.
-
- - Otherwise, if KCONF_FLAG_MACHINE was specified, then the machine
- configuration space.
-
- Note that not specifying any of the configuration store specifiers
- in the call to khc_open_space() is equivalent to specifying all
- three. Also note that the schema store (KCONF_FLAG_SCHEMA) does
- not support binary values.
-
- If the value is not found in the configuration space and any
- shadowed configuration spaces, the function returns \a
- KHM_ERROR_NOT_FOUND. In this case, the buffer is left unmodified.
-
- \param[in] buf Buffer to copy the string to. Specify NULL to just
- retrieve the number of required bytes.
-
- \param[in,out] bufsize On entry, specifies the number of bytes of
- space available at the location specified by \a buf. On exit
- specifies the number of bytes actually copied or the size of
- the required buffer if \a buf is NULL or insufficient.
-
- \retval KHM_ERROR_SUCCESS Success. The data was copied to \a buf. The number of bytes copied is stored in \a bufsize
- \retval KHM_ERROR_NOT_FOUND The specified value was not found
- \retval KHM_ERROR_INVALID_PARAM One or more parameters were invalid.
-
- \see khc_open_space()
-*/
-KHMEXP khm_int32 KHMAPI
-khc_read_binary(khm_handle conf,
- const wchar_t * value_name,
- void * buf,
- khm_size * bufsize);
-
-/*! \brief Write a string value to a configuration space
-
- The \a value_name parameter specifies the value to write to the
- configuration space. This can be either a value name or a value
- path consisting of a series nested configuration space names
- followed by the value name all separated by backslashes or forward
- slashes.
-
- For example: If \a conf is a handle to the configuration space \c
- 'A/B/C', then the value name \c 'D/E/v' refers to the value named
- \c 'v' in the configuration space \c 'A/B/C/D/E'.
-
- The specific configuration store that is used to write the value
- depends on the flags that were specified in the call to
- khc_open_space(). The precedence of configuration stores are as
- follows:
-
- - If \a KCONF_FLAG_USER was specified, then the user configuration
- space.
-
- - Otherwise, if \a KCONF_FLAG_MACHINE was specified, then the
- machine configuration space.
-
- Note that not specifying any of the configuration store specifiers
- in the call to khc_open_space() is equivalent to specifying all
- three. Also note that the schema store (KCONF_FLAG_SCHEMA) is
- readonly.
-
- If the \a KCONF_FLAG_WRITEIFMOD flag is specified in the call to
- khc_open_space() for obtaining the configuration handle, the
- specified string will only be written if it is different from the
- value being read from the handle.
-
- If the \a KCONF_FLAG_IFMODCI flag is specified along with the \a
- KCONF_FLAG_WRITEIFMOD flag, then the string comparison used will
- be case insensitive.
-
- \param[in] conf Handle to a configuration space
- \param[in] value_name Name of value to write
- \param[in] buf A NULL terminated unicode string not exceeding KCONF_MAXCCH_STRING in characters including terminating NULL
-
- \see khc_open_space()
-*/
-KHMEXP khm_int32 KHMAPI
-khc_write_string(khm_handle conf,
- const wchar_t * value_name,
- wchar_t * buf);
-
-/*! \brief Write a multi-string value to a configuration space
-
- The \a value_name parameter specifies the value to write to the
- configuration space. This can be either a value name or a value
- path consisting of a series nested configuration space names
- followed by the value name all separated by backslashes or forward
- slashes.
-
- For example: If \a conf is a handle to the configuration space \c
- 'A/B/C', then the value name \c 'D/E/v' refers to the value named
- \c 'v' in the configuration space \c 'A/B/C/D/E'.
-
- The specific configuration store that is used to write the value
- depends on the flags that were specified in the call to
- khc_open_space(). The precedence of configuration stores are as
- follows:
-
- A multi-string is a pseudo data type. The buffer pointed to by \a
- buf should contain a sequence of NULL terminated strings
- terminated by an empty string (or equivalently, the last string
- should terminate with a double NULL). This will be stored in the
- value as a CSV string.
-
- - If KCONF_FLAG_USER was specified, then the user configuration
- space.
-
- - Otherwise, if KCONF_FLAG_MACHINE was specified, then the machine
- configuration space.
-
- Note that not specifying any of the configuration store specifiers
- in the call to khc_open_space() is equivalent to specifying all
- three. Also note that the schema store (KCONF_FLAG_SCHEMA) is
- readonly.
-
- If the \a KCONF_FLAG_WRITEIFMOD flag is specified in the call to
- khc_open_space() for obtaining the configuration handle, the
- specified string will only be written if it is different from the
- value being read from the handle.
-
- If the \a KCONF_FLAG_IFMODCI flag is specified along with the \a
- KCONF_FLAG_WRITEIFMOD flag, then the string comparison used will
- be case insensitive.
-
- \see khc_open_space()
-*/
-KHMEXP khm_int32 KHMAPI
-khc_write_multi_string(khm_handle conf,
- const wchar_t * value_name,
- wchar_t * buf);
-
-/*! \brief Write a 32 bit integer value to a configuration space
-
- The \a value_name parameter specifies the value to write to the
- configuration space. This can be either a value name or a value
- path consisting of a series nested configuration space names
- followed by the value name all separated by backslashes or forward
- slashes.
-
- For example: If \a conf is a handle to the configuration space \c
- 'A/B/C', then the value name \c 'D/E/v' refers to the value named
- \c 'v' in the configuration space \c 'A/B/C/D/E'.
-
- The specific configuration store that is used to write the value
- depends on the flags that were specified in the call to
- khc_open_space(). The precedence of configuration stores are as
- follows:
-
- - If KCONF_FLAG_USER was specified, then the user configuration
- space.
-
- - Otherwise, if KCONF_FLAG_MACHINE was specified, then the machine
- configuration space.
-
- Note that not specifying any of the configuration store specifiers
- in the call to khc_open_space() is equivalent to specifying all
- three. Also note that the schema store (KCONF_FLAG_SCHEMA) is
- readonly.
-
- If the \a KCONF_FLAG_WRITEIFMOD flag is specified in the call to
- khc_open_space() for obtaining the configuration handle, the
- specified string will only be written if it is different from the
- value being read from the handle.
-
- \see khc_open_space()
-*/
-KHMEXP khm_int32 KHMAPI
-khc_write_int32(khm_handle conf,
- const wchar_t * value_name,
- khm_int32 buf);
-
-/*! \brief Write a 64 bit integer value to a configuration space
-
- The \a value_name parameter specifies the value to write to the
- configuration space. This can be either a value name or a value
- path consisting of a series nested configuration space names
- followed by the value name all separated by backslashes or forward
- slashes.
-
- For example: If \a conf is a handle to the configuration space \c
- 'A/B/C', then the value name \c 'D/E/v' refers to the value named
- \c 'v' in the configuration space \c 'A/B/C/D/E'.
-
- The specific configuration store that is used to write the value
- depends on the flags that were specified in the call to
- khc_open_space(). The precedence of configuration stores are as
- follows:
-
- - If KCONF_FLAG_USER was specified, then the user configuration
- space.
-
- - Otherwise, if KCONF_FLAG_MACHINE was specified, then the machine
- configuration space.
-
- Note that not specifying any of the configuration store specifiers
- in the call to khc_open_space() is equivalent to specifying all
- three. Also note that the schema store (KCONF_FLAG_SCHEMA) is
- readonly.
-
- If the \a KCONF_FLAG_WRITEIFMOD flag is specified in the call to
- khc_open_space() for obtaining the configuration handle, the
- specified string will only be written if it is different from the
- value being read from the handle.
-
- \see khc_open_space()
-*/
-KHMEXP khm_int32 KHMAPI
-khc_write_int64(khm_handle conf,
- const wchar_t * value_name,
- khm_int64 buf);
-
-/*! \brief Write a binary value to a configuration space
-
- The \a value_name parameter specifies the value to write to the
- configuration space. This can be either a value name or a value
- path consisting of a series nested configuration space names
- followed by the value name all separated by backslashes or forward
- slashes.
-
- For example: If \a conf is a handle to the configuration space \c
- 'A/B/C', then the value name \c 'D/E/v' refers to the value named
- \c 'v' in the configuration space \c 'A/B/C/D/E'.
-
- The specific configuration store that is used to write the value
- depends on the flags that were specified in the call to
- khc_open_space(). The precedence of configuration stores are as
- follows:
-
- - If KCONF_FLAG_USER was specified, then the user configuration
- space.
-
- - Otherwise, if KCONF_FLAG_MACHINE was specified, then the machine
- configuration space.
-
- Note that not specifying any of the configuration store specifiers
- in the call to khc_open_space() is equivalent to specifying all
- three. Also note that the schema store (KCONF_FLAG_SCHEMA) is
- readonly.
-
- \see khc_open_space()
-*/
-KHMEXP khm_int32 KHMAPI
-khc_write_binary(khm_handle conf,
- const wchar_t * value_name,
- void * buf,
- khm_size bufsize);
-
-/*! \brief Get the type of a value in a configuration space
-
- \return The return value is the type of the specified value, or
- KC_NONE if the value does not exist.
- */
-KHMEXP khm_int32 KHMAPI
-khc_get_type(khm_handle conf, const wchar_t * value_name);
-
-/*! \brief Check which configuration stores contain a specific value.
-
- Each value in a configuration space can be contained in zero or
- more configuration stores. Use this function to determine which
- configuration stores contain the specific value.
-
- The returned bitmask always indicates a subset of the
- configuration stores that were specified when opening the
- configuration space corresponding to \a conf.
-
- If the specified handle is shadowed (see khc_shadow_space()) and
- the value is not found in any of the visible stores for the
- topmost handle, each of the shadowed handles will be tried in turn
- until the value is found. The return value will correspond to the
- handle where the value is first found.
-
- \return A combination of ::KCONF_FLAG_MACHINE, ::KCONF_FLAG_USER
- and ::KCONF_FLAG_SCHEMA indicating which stores contain the
- value.
- */
-KHMEXP khm_int32 KHMAPI
-khc_value_exists(khm_handle conf, const wchar_t * value);
-
-/*! \brief Remove a value from a configuration space
-
- Removes a value from one or more configuration stores.
-
- A value can exist in multiple configuration stores. Only the
- values that are stored in writable stores can be removed. When
- the function searches for values to remove, it will only look in
- configuration stores that are specified in the handle. In
- addition, the configuration stores affected can be further
- narrowed by specifying them in the \a flags parameter. If \a
- flags is zero, then all the stores visible to the handle are
- searched. If \a flags specifies ::KCONF_FLAG_USER or
- ::KCONF_FLAG_MACHINE or both, then only the specified stores are
- searched, provided that the stores are visible to the handle.
-
- This function only operates on the topmost configuration space
- visible to the handle. If the configuration handle is shadowed,
- the shadowed configuration spaces are unaffected by the removal.
-
- \param[in] conf Handle to configuration space to remove value from
-
- \param[in] value_name Value to remove
-
- \param[in] flags Specifies which configuration stores will be
- affected by the removal. See above.
-
- \retval KHM_ERROR_SUCCESS The value was removed from all the
- specified configuration stores.
-
- \retval KHM_ERROR_NOT_FOUND The value was not found.
-
- \retval KHM_ERROR_UNKNOWN An unknown error occurred while trying
- to remove the value.
-
- \retval KHM_ERROR_PARTIAL The value was successfully removed from
- one or more stores, but the operation failed on one or more
- other stores.
- */
-KHMEXP khm_int32 KHMAPI
-khc_remove_value(khm_handle conf, const wchar_t * value_name, khm_int32 flags);
-
-/*! \brief Get the name of a configuration space
-
- \param[in] conf Handle to a configuration space
-
- \param[out] buf The buffer to receive the name. Set to NULL if
- only the size of the buffer is required.
-
- \param[in,out] bufsize On entry, holds the size of the buffer
- pointed to by \a buf. On exit, holds the number of bytes
- copied into the buffer including the NULL terminator.
- */
-KHMEXP khm_int32 KHMAPI
-khc_get_config_space_name(khm_handle conf,
- wchar_t * buf,
- khm_size * bufsize);
-
-/*! \brief Get a handle to the parent space
-
- \param[in] conf Handle to a configuration space
-
- \param[out] parent Handle to the parent configuration space if the
- call succeeds. Receives NULL otherwise. The returned handle
- must be closed using khc_close_space()
- */
-KHMEXP khm_int32 KHMAPI
-khc_get_config_space_parent(khm_handle conf,
- khm_handle * parent);
-
-/*! \brief Load a configuration schema into the specified configuration space
-
- \param[in] conf Handle to a configuration space or NULL to use the
- root configuration space.
-
- \param[in] schema The schema to load. The schema is assumed to be
- well formed.
-
- \see khc_unload_schema()
- */
-KHMEXP khm_int32 KHMAPI
-khc_load_schema(khm_handle conf,
- const kconf_schema * schema);
-
-/*! \brief Unload a schema from a configuration space
- */
-KHMEXP khm_int32 KHMAPI
-khc_unload_schema(khm_handle conf,
- const kconf_schema * schema);
-
-/*! \brief Enumerate the subspaces of a configuration space
-
- Prepares a configuration space for enumeration and returns the
- child spaces in no particular order.
-
- \param[in] conf The configuration space to enumerate child spaces
-
- \param[in] prev The previous configuration space returned by
- khc_enum_subspaces() or NULL if this is the first call. If
- this is not NULL, then the handle passed in \a prev will be
- freed.
-
- \param[out] next If \a prev was NULL, receives the first sub space
- found in \a conf. You must \b either call
- khc_enum_subspaces() again with the returned handle or call
- khc_close_space() to free the returned handle if no more
- subspaces are required. \a next can point to the same handle
- specified in \a prev.
-
- \retval KHM_ERROR_SUCCESS The call succeeded. There is a valid
- handle to a configuration space in \a first_subspace.
-
- \retval KHM_ERROR_INVALID_PARAM Either \a conf or \a prev was not a
- valid configuration space handle or \a first_subspace is NULL.
- Note that \a prev can be NULL.
-
- \retval KHM_ERROR_NOT_FOUND There were no subspaces in the
- configuration space pointed to by \a conf.
-
- \note The configuration spaces that are enumerated directly belong
- to the configuration space given by \a conf. This function
- does not enumerate subspaces of shadowed configuration spaces
- (see khc_shadow_space()). Even if \a conf was obtained on a
- restricted domain (i.e. you specified one or more
- configuration stores when you openend the handle and didn't
- include all the configuration stores. See khc_open_space()),
- the subspaces that are returned are the union of all
- configuration spaces in all the configuration stores. This is
- not a bug. This is a feature. In NetIDMgr, a configuartion
- space exists if some configuration store defines it (or it was
- created with a call to khc_open_space() even if no
- configuration store defines it yet). This is the tradeoff you
- make when using a layered configuration system.
-
- However, the returned handle has the same domain restrictions
- as \a conf.
- */
-KHMEXP khm_int32 KHMAPI
-khc_enum_subspaces(khm_handle conf,
- khm_handle prev,
- khm_handle * next);
-
-/*! \brief Remove a configuration space
-
- The configuration space will be marked for removal. Once all the
- handles for the space have been released, it will be deleted. The
- configuration stores that will be affected are the write enabled
- configuration stores for the handle.
- */
-KHMEXP khm_int32 KHMAPI
-khc_remove_space(khm_handle conf);
-/*@}*/
-
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __KHIMAIRA_KCONFIG_H
+#define __KHIMAIRA_KCONFIG_H
+
+#include<khdefs.h>
+#include<mstring.h>
+
+/*! \defgroup kconf NetIDMgr Configuration Provider */
+/*@{*/
+
+/*! \brief Configuration schema descriptor record
+
+ The schema descriptor is a convenient way to provide a default set
+ of configuration options for a part of an application. It
+ describes the configuration spaces and the values and subspaces
+ contained in each space.
+
+ \see kconf_load_schema()
+*/
+typedef struct tag_kconf_schema {
+ wchar_t * name; /*!< name of the object being described.
+ Optional for KC_ENDSPACE type object,
+ but required for everything else.
+ Names can be upto KCONF_MAXCCH_NAME
+ characters in length. */
+ khm_int32 type; /*!< type of the object. Can be one of
+ KC_SPACE, KC_ENDSPACE, KC_INT32,
+ KC_INT64, KC_STRING or KC_BINARY */
+ khm_ui_8 value; /*!< the value of the object. It is not
+ used for KC_SPACE and KC_ENDSPACE
+ typed objects. For a KC_STRING, this
+ contains a pointer to the string
+ value. The string should not be
+ longer than KCONF_MAXCCH_STRING
+ characters. KC_INT32 and KC_INT64
+ objects store the value directly in
+ this field, while KC_BINARY objects do
+ not support defining a default value
+ here. */
+ wchar_t * description;/*!< a friendly description of the value
+ or configuration space. */
+} kconf_schema;
+
+/*! \name Configuration data types
+ @{*/
+/*! \brief Not a known type */
+#define KC_NONE 0
+
+/*! \brief When used as ::kconf_schema \a type, defines the start of a configuration space.
+
+ There should be a subsequent KC_ENDSPACE record in the schema
+ which defines the end of this configuration space.
+
+ \a name specifies the name of the configuration space. Optionally
+ use \a description to provide a description.*/
+#define KC_SPACE 1
+
+/*! \brief Ends a configuration space started with KC_SPACE */
+#define KC_ENDSPACE 2
+
+/*! \brief A 32 bit integer
+
+ Specifies a configuration parameter named \a name which is of this
+ type. Use \a description to provide an optional description of
+ the value.
+
+ \a value specifies a default value for this parameter in the lower
+ 32 bits.
+*/
+#define KC_INT32 3
+
+/*! \brief A 64 bit integer
+
+ Specifies a configuration parameter named \a name which is of this
+ type. Use \a description to provide an optional description of
+ the value.
+
+ \a value specifies a default value for this parameter.
+*/
+#define KC_INT64 4
+
+/*! \brief A unicode string
+
+ Specifies a configuration parameter named \a name which is of this
+ type. Use \a description to provide an optional description of
+ the value.
+
+ \a value specifies a default value for this parameter which should
+ be a pointer to a NULL terminated unicode string of no more than
+ ::KCONF_MAXCCH_STRING characters.
+*/
+#define KC_STRING 5
+
+/*! \brief An unparsed binary stream
+
+ Specifies a configuration parameter named \a name which is of this
+ type. Use \a description to provide an optional description of
+ the value.
+
+ Default values are not supported for binary streams. \a value is
+ ignored.
+*/
+#define KC_BINARY 6
+/*@}*/
+
+/*! \brief This is the root configuration space */
+#define KCONF_FLAG_ROOT 0x00000001
+
+/*! \brief Indicates the configuration store which stores user-specific information */
+#define KCONF_FLAG_USER 0x00000002
+
+/*! \brief Indicates the configuration store which stores machine-specific information */
+#define KCONF_FLAG_MACHINE 0x00000004
+
+/*! \brief Indicates the configuration store which stores the schema */
+#define KCONF_FLAG_SCHEMA 0x00000008
+
+/*! \brief Indicates that the last component of the given configuration path is to be considered to be a configuration value */
+#define KCONF_FLAG_TRAILINGVALUE 0x00000020
+
+/*! \brief Only write values back there is a change
+
+ Any write operations using the handle with check if the value
+ being written is different from the value being read from the
+ handle. It will only be written if the value is different.
+
+ \note Note that the value being read from a handle takes schema and
+ shadowed configuration handles into consideration while the value
+ being written is only written to the topmost layer of
+ configuration that can be written to.
+
+ \note Note also that this flag does not affect binary values.
+ */
+#define KCONF_FLAG_WRITEIFMOD 0x00000040
+
+/*! \brief Use case-insensitive comparison for KCONF_FLAG_WRITEIFMOD
+
+ When used in combination with \a KCONF_FLAG_WRITEIFMOD , the
+ string comparison used when determining whether the string read
+ from the configuration handle is the same as the string being
+ written will be case insensitive. If this flag is not set, the
+ comparison will be case sensitive.
+ */
+#define KCONF_FLAG_IFMODCI 0x00000080
+
+/*! \brief Do not parse the configuration space name
+
+ If set, disables the parsing of the configuration space for
+ subspaces. The space name is taken verbatim to be a configuration
+ space name. This can be used when there can be forward slashes or
+ backslahes in the name which are not escaped.
+
+ By default, the configuration space name,
+
+ \code
+ L"foo\\bar"
+ \endcode
+
+ is taken to mean the configuration space \a bar which is a
+ subspace of \a foo. If ::KCONF_FLAG_NOPARSENAME is set, then this
+ is taken to mean configuration space \a foo\\bar.
+ */
+#define KCONF_FLAG_NOPARSENAME 0x00000040
+
+/*! \brief Maximum number of allowed characters (including terminating NULL) in a name
+
+ \note This is a hard limit in Windows, since we are mapping
+ configuration spaces to registry keys.
+*/
+#define KCONF_MAXCCH_NAME 256
+
+/*! \brief Maximum number of allowed bytes (including terminating NULL) in a name */
+#define KCONF_MAXCB_NAME (KCONF_MAXCCH_NAME * sizeof(wchar_t))
+
+/*! \brief Maximum level of nesting for configuration spaces
+ */
+#define KCONF_MAX_DEPTH 16
+
+/*! \brief Maximum number of allowed characters (including terminating NULL) in a configuration path */
+#define KCONF_MAXCCH_PATH (KCONF_MAXCCH_NAME * KCONF_MAX_DEPTH)
+
+/*! \brief Maximum number of allowed bytes (including terminating NULL) in a configuration path */
+#define KCONF_MAXCB_PATH (KCONF_MAXCCH_PATH * sizeof(wchar_t))
+
+/*! \brief Maximum number of allowed characters (including terminating NULL) in a string */
+#define KCONF_MAXCCH_STRING KHM_MAXCCH_STRING
+
+/*! \brief Maximum number of allowed bytes (including terminating NULL) in a string */
+#define KCONF_MAXCB_STRING (KCONF_MAXCCH_STRING * sizeof(wchar_t))
+
+/*! \brief Open a configuration space
+
+ Opens the configuration space specified by \a cspace. By default,
+ the opened space includes user,machine and schema configuration
+ stores. However, you can specify a subset of these.
+
+ If the configuration space does not exist and the \a flags specify
+ KHM_FLAG_CREATE, then the configuration space is created. The
+ stores that are affected by the create operation depend on \a
+ flags. If the \a flags only specifies ::KCONF_FLAG_MACHINE, then
+ the configuration space is created in the machine store. If \a
+ flags specifies any combination of stores including \a
+ ::KCONF_FLAG_USER, then the configuration space is created in the
+ user store. Note that ::KCONF_FLAG_SCHEMA is readonly.
+
+ Once opened, use khc_close_space() to close the configuration
+ space.
+
+ \param[in] parent The parent configuration space. The path
+ specified in \a cspace is relative to the parent. Set this to
+ NULL to indicate the root configuration space.
+
+ \param[in] cspace The confiuration path. This can be up to
+ ::KCONF_MAXCCH_PATH characters in length. Use either
+ backslashes or forward slashes to specify hiearchy. Set this
+ to NULL to reopen the parent configuration space.
+
+ \param[in] flags Flags. This can be a combination of KCONF_FLAG_*
+ constants and KHM_FLAG_CREATE. If none of ::KCONF_FLAG_USER,
+ ::KCONF_FLAG_MACHINE or ::KCONF_FLAG_SCHEMA is specified, then
+ it defaults to all three.
+
+ \param[out] result Pointer to a handle which receives the handle
+ to the opened configuration space if the call succeeds.
+
+ \note You can re-open a configuration space with different flags
+ such as ::KCONF_FLAG_MACHINE by specifying NULL for \a cspace
+ and settings \a flags to the required flags.
+
+*/
+KHMEXP khm_int32 KHMAPI
+khc_open_space(khm_handle parent, const wchar_t * cspace, khm_int32 flags,
+ khm_handle * result);
+
+/*! \brief Set the shadow space for a configuration handle
+
+ The handle specified by \a lower becomes a shadow for the handle
+ specified by \a upper. Any configuration value that is queried in
+ \a upper that does not exist in \a upper will be queried in \a
+ lower.
+
+ If \a upper already had a shadow handle, that handle will be
+ replaced by \a lower. The handle \a lower still needs to be
+ closed by a call to khc_close_space(). However, closing \a lower
+ will not affect \a upper which will still treat the configuration
+ space pointed to by \a lower to be it's shadow.
+
+ Shadows are specific to handles and not configuration spaces.
+ Shadowing a configuration space using one handle does not affect
+ any other handles which may be obtained for the same configuration
+ space.
+
+ Specify NULL for \a lower to remove any prior shadow.
+ */
+KHMEXP khm_int32 KHMAPI
+khc_shadow_space(khm_handle upper, khm_handle lower);
+
+/*! \brief Close a handle opened with khc_open_space()
+*/
+KHMEXP khm_int32 KHMAPI
+khc_close_space(khm_handle conf);
+
+/*! \brief Read a string value from a configuration space
+
+ The \a value_name parameter specifies the value to read from the
+ configuration space. This can be either a value name or a value
+ path consisting of a series nested configuration space names
+ followed by the value name all separated by backslashes or forward
+ slashes.
+
+ For example: If \a conf is a handle to the configuration space \c
+ 'A/B/C', then the value name \c 'D/E/v' refers to the value named
+ \c 'v' in the configuration space \c 'A/B/C/D/E'.
+
+ The specific configuration store that is used to access the value
+ depends on the flags that were specified in the call to
+ khc_open_space(). The precedence of configuration stores are as
+ follows:
+
+ - If KCONF_FLAG_USER was specified, then the user configuration
+ space.
+
+ - Otherwise, if KCONF_FLAG_MACHINE was specified, then the machine
+ configuration space.
+
+ - Otherwise, if KCONF_FLAG_SCHEMA was specified, the the schema
+ store.
+
+ Note that not specifying any of the configuration store specifiers
+ in the call to khc_open_space() is equivalent to specifying all
+ three.
+
+ If the value is not found in the configuration space and any
+ shadowed configuration spaces, the function returns \a
+ KHM_ERROR_NOT_FOUND. In this case, the buffer is left unmodified.
+
+ \param[in] buf Buffer to copy the string to. Specify NULL to just
+ retrieve the number of required bytes.
+
+ \param[in,out] bufsize On entry, specifies the number of bytes of
+ space available at the location specified by \a buf. On exit
+ specifies the number of bytes actually copied or the size of
+ the required buffer if \a buf is NULL or insufficient.
+
+ \retval KHM_ERROR_NOT_READY The configuration provider has not started
+ \retval KHM_ERROR_INVALID_PARAM One or more of the supplied parameters are not valid
+ \retval KHM_ERROR_TYPE_MISMATCH The specified value is not a string
+ \retval KHM_ERROR_TOO_LONG \a buf was NULL or the size of the buffer was insufficient. The required size is in bufsize.
+ \retval KHM_ERROR_SUCCESS Success. The number of bytes copied is in bufsize.
+ \retval KHM_ERROR_NOT_FOUND The value was not found.
+
+ \see khc_open_space()
+*/
+KHMEXP khm_int32 KHMAPI
+khc_read_string(khm_handle conf,
+ const wchar_t * value_name,
+ wchar_t * buf,
+ khm_size * bufsize);
+
+/*! \brief Read a multi-string value from a configuration space
+
+ The \a value_name parameter specifies the value to read from the
+ configuration space. This can be either a value name or a value
+ path consisting of a series nested configuration space names
+ followed by the value name all separated by backslashes or forward
+ slashes.
+
+ For example: If \a conf is a handle to the configuration space \c
+ 'A/B/C', then the value name \c 'D/E/v' refers to the value named
+ \c 'v' in the configuration space \c 'A/B/C/D/E'.
+
+ The specific configuration store that is used to access the value
+ depends on the flags that were specified in the call to
+ khc_open_space(). The precedence of configuration stores are as
+ follows:
+
+ - If KCONF_FLAG_USER was specified, then the user configuration
+ space.
+
+ - Otherwise, if KCONF_FLAG_MACHINE was specified, then the machine
+ configuration space.
+
+ - Otherwise, if KCONF_FLAG_SCHEMA was specified, the the schema
+ store.
+
+ A multi-string is a pseudo data type. The value in the
+ configuration store should contain a CSV string. Each comma
+ separated value in the CSV string is considered to be a separate
+ value. Empty values are not allowed. The buffer pointed to by \a
+ buf will receive these values in the form of a series of NULL
+ terminated strings terminated by an empty string (or equivalently,
+ the last string will be terminated by a double NULL).
+
+ Note that not specifying any of the configuration store specifiers
+ in the call to khc_open_space() is equivalent to specifying all
+ three.
+
+ If the value is not found in the configuration space and any
+ shadowed configuration spaces, the function returns \a
+ KHM_ERROR_NOT_FOUND. In this case, the buffer is left unmodified.
+
+ \param[in] buf Buffer to copy the multi-string to. Specify NULL
+ to just retrieve the number of required bytes.
+
+ \param[in,out] bufsize On entry, specifies the number of bytes of
+ space available at the location specified by \a buf. On exit
+ specifies the number of bytes actually copied or the size of
+ the required buffer if \a buf is NULL or insufficient.
+
+ \retval KHM_ERROR_NOT_READY The configuration provider has not started
+ \retval KHM_ERROR_INVALID_PARAM One or more of the supplied parameters are not valid
+ \retval KHM_ERROR_TYPE_MISMATCH The specified value is not a string
+ \retval KHM_ERROR_TOO_LONG \a buf was NULL or the size of the buffer was insufficient. The required size is in bufsize.
+ \retval KHM_ERROR_SUCCESS Success. The number of bytes copied is in bufsize.
+ \retval KHM_ERROR_NOT_FOUND The value was not found.
+
+ \see khc_open_space()
+*/
+KHMEXP khm_int32 KHMAPI
+khc_read_multi_string(khm_handle conf,
+ const wchar_t * value_name,
+ wchar_t * buf,
+ khm_size * bufsize);
+
+/*! \brief Read a 32 bit integer value from a configuration space
+
+ The \a value_name parameter specifies the value to read from the
+ configuration space. This can be either a value name or a value
+ path consisting of a series nested configuration space names
+ followed by the value name all separated by backslashes or forward
+ slashes.
+
+ For example: If \a conf is a handle to the configuration space \c
+ 'A/B/C', then the value name \c 'D/E/v' refers to the value named
+ \c 'v' in the configuration space \c 'A/B/C/D/E'.
+
+ The specific configuration store that is used to access the value
+ depends on the flags that were specified in the call to
+ khc_open_space(). The precedence of configuration stores are as
+ follows:
+
+ - If KCONF_FLAG_USER was specified, then the user configuration
+ space.
+
+ - Otherwise, if KCONF_FLAG_MACHINE was specified, then the machine
+ configuration space.
+
+ - Otherwise, if KCONF_FLAG_SCHEMA was specified, the the schema
+ store.
+
+ Note that not specifying any of the configuration store specifiers
+ in the call to khc_open_space() is equivalent to specifying all
+ three.
+
+ If the value is not found in the configuration space and any
+ shadowed configuration spaces, the function returns \a
+ KHM_ERROR_NOT_FOUND. In this case, the buffer is left unmodified.
+
+ \param[in] conf Handle to a configuration space
+ \param[in] value The value to query
+ \param[out] buf The buffer to receive the value
+
+ \retval KHM_ERROR_NOT_READY The configuration provider has not started.
+ \retval KHM_ERROR_SUCCESS Success. The value that was read was placed in \a buf
+ \retval KHM_ERROR_NOT_FOUND The specified value was not found
+ \retval KHM_ERROR_INVALID_PARAM One or more parameters were invalid
+ \retval KHM_ERROR_TYPE_MISMATCH The specified value was found but was not of the correct type.
+ \see khc_open_space()
+*/
+KHMEXP khm_int32 KHMAPI
+khc_read_int32(khm_handle conf,
+ const wchar_t * value_name,
+ khm_int32 * buf);
+
+/*! \brief Read a 64 bit integer value from a configuration space
+
+ The \a value_name parameter specifies the value to read from the
+ configuration space. This can be either a value name or a value
+ path consisting of a series nested configuration space names
+ followed by the value name all separated by backslashes or forward
+ slashes.
+
+ For example: If \a conf is a handle to the configuration space \c
+ 'A/B/C', then the value name \c 'D/E/v' refers to the value named
+ \c 'v' in the configuration space \c 'A/B/C/D/E'.
+
+ The specific configuration store that is used to access the value
+ depends on the flags that were specified in the call to
+ khc_open_space(). The precedence of configuration stores are as
+ follows:
+
+ - If KCONF_FLAG_USER was specified, then the user configuration
+ space.
+
+ - Otherwise, if KCONF_FLAG_MACHINE was specified, then the machine
+ configuration space.
+
+ - Otherwise, if KCONF_FLAG_SCHEMA was specified, the the schema
+ store.
+
+ Note that not specifying any of the configuration store specifiers
+ in the call to khc_open_space() is equivalent to specifying all
+ three.
+
+ If the value is not found in the configuration space and any
+ shadowed configuration spaces, the function returns \a
+ KHM_ERROR_NOT_FOUND. In this case, the buffer is left unmodified.
+
+ \param[in] conf Handle to a configuration space
+ \param[in] value_name The value to query
+ \param[out] buf The buffer to receive the value
+
+ \retval KHM_ERROR_NOT_READY The configuration provider has not started
+ \retval KHM_ERROR_SUCCESS Success. The value that was read was placed in \a buf
+ \retval KHM_ERROR_NOT_FOUND The specified value was not found
+ \retval KHM_ERROR_INVALID_PARAM One or more parameters were invalid
+ \retval KHM_ERROR_TYPE_MISMATCH The specified value was found but was not the correct data type.
+
+ \see khc_open_space()
+*/
+KHMEXP khm_int32 KHMAPI
+khc_read_int64(khm_handle conf,
+ const wchar_t * value_name,
+ khm_int64 * buf);
+
+/*! \brief Read a binary value from a configuration space
+
+ The \a value_name parameter specifies the value to read from the
+ configuration space. This can be either a value name or a value
+ path consisting of a series nested configuration space names
+ followed by the value name all separated by backslashes or forward
+ slashes.
+
+ For example: If \a conf is a handle to the configuration space \c
+ 'A/B/C', then the value name \c 'D/E/v' refers to the value named
+ \c 'v' in the configuration space \c 'A/B/C/D/E'.
+
+ The specific configuration store that is used to access the value
+ depends on the flags that were specified in the call to
+ khc_open_space(). The precedence of configuration stores are as
+ follows:
+
+ - If KCONF_FLAG_USER was specified, then the user configuration
+ space.
+
+ - Otherwise, if KCONF_FLAG_MACHINE was specified, then the machine
+ configuration space.
+
+ Note that not specifying any of the configuration store specifiers
+ in the call to khc_open_space() is equivalent to specifying all
+ three. Also note that the schema store (KCONF_FLAG_SCHEMA) does
+ not support binary values.
+
+ If the value is not found in the configuration space and any
+ shadowed configuration spaces, the function returns \a
+ KHM_ERROR_NOT_FOUND. In this case, the buffer is left unmodified.
+
+ \param[in] buf Buffer to copy the string to. Specify NULL to just
+ retrieve the number of required bytes.
+
+ \param[in,out] bufsize On entry, specifies the number of bytes of
+ space available at the location specified by \a buf. On exit
+ specifies the number of bytes actually copied or the size of
+ the required buffer if \a buf is NULL or insufficient.
+
+ \retval KHM_ERROR_SUCCESS Success. The data was copied to \a buf. The number of bytes copied is stored in \a bufsize
+ \retval KHM_ERROR_NOT_FOUND The specified value was not found
+ \retval KHM_ERROR_INVALID_PARAM One or more parameters were invalid.
+
+ \see khc_open_space()
+*/
+KHMEXP khm_int32 KHMAPI
+khc_read_binary(khm_handle conf,
+ const wchar_t * value_name,
+ void * buf,
+ khm_size * bufsize);
+
+/*! \brief Write a string value to a configuration space
+
+ The \a value_name parameter specifies the value to write to the
+ configuration space. This can be either a value name or a value
+ path consisting of a series nested configuration space names
+ followed by the value name all separated by backslashes or forward
+ slashes.
+
+ For example: If \a conf is a handle to the configuration space \c
+ 'A/B/C', then the value name \c 'D/E/v' refers to the value named
+ \c 'v' in the configuration space \c 'A/B/C/D/E'.
+
+ The specific configuration store that is used to write the value
+ depends on the flags that were specified in the call to
+ khc_open_space(). The precedence of configuration stores are as
+ follows:
+
+ - If \a KCONF_FLAG_USER was specified, then the user configuration
+ space.
+
+ - Otherwise, if \a KCONF_FLAG_MACHINE was specified, then the
+ machine configuration space.
+
+ Note that not specifying any of the configuration store specifiers
+ in the call to khc_open_space() is equivalent to specifying all
+ three. Also note that the schema store (KCONF_FLAG_SCHEMA) is
+ readonly.
+
+ If the \a KCONF_FLAG_WRITEIFMOD flag is specified in the call to
+ khc_open_space() for obtaining the configuration handle, the
+ specified string will only be written if it is different from the
+ value being read from the handle.
+
+ If the \a KCONF_FLAG_IFMODCI flag is specified along with the \a
+ KCONF_FLAG_WRITEIFMOD flag, then the string comparison used will
+ be case insensitive.
+
+ \param[in] conf Handle to a configuration space
+ \param[in] value_name Name of value to write
+ \param[in] buf A NULL terminated unicode string not exceeding KCONF_MAXCCH_STRING in characters including terminating NULL
+
+ \see khc_open_space()
+*/
+KHMEXP khm_int32 KHMAPI
+khc_write_string(khm_handle conf,
+ const wchar_t * value_name,
+ wchar_t * buf);
+
+/*! \brief Write a multi-string value to a configuration space
+
+ The \a value_name parameter specifies the value to write to the
+ configuration space. This can be either a value name or a value
+ path consisting of a series nested configuration space names
+ followed by the value name all separated by backslashes or forward
+ slashes.
+
+ For example: If \a conf is a handle to the configuration space \c
+ 'A/B/C', then the value name \c 'D/E/v' refers to the value named
+ \c 'v' in the configuration space \c 'A/B/C/D/E'.
+
+ The specific configuration store that is used to write the value
+ depends on the flags that were specified in the call to
+ khc_open_space(). The precedence of configuration stores are as
+ follows:
+
+ A multi-string is a pseudo data type. The buffer pointed to by \a
+ buf should contain a sequence of NULL terminated strings
+ terminated by an empty string (or equivalently, the last string
+ should terminate with a double NULL). This will be stored in the
+ value as a CSV string.
+
+ - If KCONF_FLAG_USER was specified, then the user configuration
+ space.
+
+ - Otherwise, if KCONF_FLAG_MACHINE was specified, then the machine
+ configuration space.
+
+ Note that not specifying any of the configuration store specifiers
+ in the call to khc_open_space() is equivalent to specifying all
+ three. Also note that the schema store (KCONF_FLAG_SCHEMA) is
+ readonly.
+
+ If the \a KCONF_FLAG_WRITEIFMOD flag is specified in the call to
+ khc_open_space() for obtaining the configuration handle, the
+ specified string will only be written if it is different from the
+ value being read from the handle.
+
+ If the \a KCONF_FLAG_IFMODCI flag is specified along with the \a
+ KCONF_FLAG_WRITEIFMOD flag, then the string comparison used will
+ be case insensitive.
+
+ \see khc_open_space()
+*/
+KHMEXP khm_int32 KHMAPI
+khc_write_multi_string(khm_handle conf,
+ const wchar_t * value_name,
+ wchar_t * buf);
+
+/*! \brief Write a 32 bit integer value to a configuration space
+
+ The \a value_name parameter specifies the value to write to the
+ configuration space. This can be either a value name or a value
+ path consisting of a series nested configuration space names
+ followed by the value name all separated by backslashes or forward
+ slashes.
+
+ For example: If \a conf is a handle to the configuration space \c
+ 'A/B/C', then the value name \c 'D/E/v' refers to the value named
+ \c 'v' in the configuration space \c 'A/B/C/D/E'.
+
+ The specific configuration store that is used to write the value
+ depends on the flags that were specified in the call to
+ khc_open_space(). The precedence of configuration stores are as
+ follows:
+
+ - If KCONF_FLAG_USER was specified, then the user configuration
+ space.
+
+ - Otherwise, if KCONF_FLAG_MACHINE was specified, then the machine
+ configuration space.
+
+ Note that not specifying any of the configuration store specifiers
+ in the call to khc_open_space() is equivalent to specifying all
+ three. Also note that the schema store (KCONF_FLAG_SCHEMA) is
+ readonly.
+
+ If the \a KCONF_FLAG_WRITEIFMOD flag is specified in the call to
+ khc_open_space() for obtaining the configuration handle, the
+ specified string will only be written if it is different from the
+ value being read from the handle.
+
+ \see khc_open_space()
+*/
+KHMEXP khm_int32 KHMAPI
+khc_write_int32(khm_handle conf,
+ const wchar_t * value_name,
+ khm_int32 buf);
+
+/*! \brief Write a 64 bit integer value to a configuration space
+
+ The \a value_name parameter specifies the value to write to the
+ configuration space. This can be either a value name or a value
+ path consisting of a series nested configuration space names
+ followed by the value name all separated by backslashes or forward
+ slashes.
+
+ For example: If \a conf is a handle to the configuration space \c
+ 'A/B/C', then the value name \c 'D/E/v' refers to the value named
+ \c 'v' in the configuration space \c 'A/B/C/D/E'.
+
+ The specific configuration store that is used to write the value
+ depends on the flags that were specified in the call to
+ khc_open_space(). The precedence of configuration stores are as
+ follows:
+
+ - If KCONF_FLAG_USER was specified, then the user configuration
+ space.
+
+ - Otherwise, if KCONF_FLAG_MACHINE was specified, then the machine
+ configuration space.
+
+ Note that not specifying any of the configuration store specifiers
+ in the call to khc_open_space() is equivalent to specifying all
+ three. Also note that the schema store (KCONF_FLAG_SCHEMA) is
+ readonly.
+
+ If the \a KCONF_FLAG_WRITEIFMOD flag is specified in the call to
+ khc_open_space() for obtaining the configuration handle, the
+ specified string will only be written if it is different from the
+ value being read from the handle.
+
+ \see khc_open_space()
+*/
+KHMEXP khm_int32 KHMAPI
+khc_write_int64(khm_handle conf,
+ const wchar_t * value_name,
+ khm_int64 buf);
+
+/*! \brief Write a binary value to a configuration space
+
+ The \a value_name parameter specifies the value to write to the
+ configuration space. This can be either a value name or a value
+ path consisting of a series nested configuration space names
+ followed by the value name all separated by backslashes or forward
+ slashes.
+
+ For example: If \a conf is a handle to the configuration space \c
+ 'A/B/C', then the value name \c 'D/E/v' refers to the value named
+ \c 'v' in the configuration space \c 'A/B/C/D/E'.
+
+ The specific configuration store that is used to write the value
+ depends on the flags that were specified in the call to
+ khc_open_space(). The precedence of configuration stores are as
+ follows:
+
+ - If KCONF_FLAG_USER was specified, then the user configuration
+ space.
+
+ - Otherwise, if KCONF_FLAG_MACHINE was specified, then the machine
+ configuration space.
+
+ Note that not specifying any of the configuration store specifiers
+ in the call to khc_open_space() is equivalent to specifying all
+ three. Also note that the schema store (KCONF_FLAG_SCHEMA) is
+ readonly.
+
+ \see khc_open_space()
+*/
+KHMEXP khm_int32 KHMAPI
+khc_write_binary(khm_handle conf,
+ const wchar_t * value_name,
+ void * buf,
+ khm_size bufsize);
+
+/*! \brief Get the type of a value in a configuration space
+
+ \return The return value is the type of the specified value, or
+ KC_NONE if the value does not exist.
+ */
+KHMEXP khm_int32 KHMAPI
+khc_get_type(khm_handle conf, const wchar_t * value_name);
+
+/*! \brief Check which configuration stores contain a specific value.
+
+ Each value in a configuration space can be contained in zero or
+ more configuration stores. Use this function to determine which
+ configuration stores contain the specific value.
+
+ The returned bitmask always indicates a subset of the
+ configuration stores that were specified when opening the
+ configuration space corresponding to \a conf.
+
+ If the specified handle is shadowed (see khc_shadow_space()) and
+ the value is not found in any of the visible stores for the
+ topmost handle, each of the shadowed handles will be tried in turn
+ until the value is found. The return value will correspond to the
+ handle where the value is first found.
+
+ \return A combination of ::KCONF_FLAG_MACHINE, ::KCONF_FLAG_USER
+ and ::KCONF_FLAG_SCHEMA indicating which stores contain the
+ value.
+ */
+KHMEXP khm_int32 KHMAPI
+khc_value_exists(khm_handle conf, const wchar_t * value);
+
+/*! \brief Remove a value from a configuration space
+
+ Removes a value from one or more configuration stores.
+
+ A value can exist in multiple configuration stores. Only the
+ values that are stored in writable stores can be removed. When
+ the function searches for values to remove, it will only look in
+ configuration stores that are specified in the handle. In
+ addition, the configuration stores affected can be further
+ narrowed by specifying them in the \a flags parameter. If \a
+ flags is zero, then all the stores visible to the handle are
+ searched. If \a flags specifies ::KCONF_FLAG_USER or
+ ::KCONF_FLAG_MACHINE or both, then only the specified stores are
+ searched, provided that the stores are visible to the handle.
+
+ This function only operates on the topmost configuration space
+ visible to the handle. If the configuration handle is shadowed,
+ the shadowed configuration spaces are unaffected by the removal.
+
+ \param[in] conf Handle to configuration space to remove value from
+
+ \param[in] value_name Value to remove
+
+ \param[in] flags Specifies which configuration stores will be
+ affected by the removal. See above.
+
+ \retval KHM_ERROR_SUCCESS The value was removed from all the
+ specified configuration stores.
+
+ \retval KHM_ERROR_NOT_FOUND The value was not found.
+
+ \retval KHM_ERROR_UNKNOWN An unknown error occurred while trying
+ to remove the value.
+
+ \retval KHM_ERROR_PARTIAL The value was successfully removed from
+ one or more stores, but the operation failed on one or more
+ other stores.
+ */
+KHMEXP khm_int32 KHMAPI
+khc_remove_value(khm_handle conf, const wchar_t * value_name, khm_int32 flags);
+
+/*! \brief Get the name of a configuration space
+
+ \param[in] conf Handle to a configuration space
+
+ \param[out] buf The buffer to receive the name. Set to NULL if
+ only the size of the buffer is required.
+
+ \param[in,out] bufsize On entry, holds the size of the buffer
+ pointed to by \a buf. On exit, holds the number of bytes
+ copied into the buffer including the NULL terminator.
+ */
+KHMEXP khm_int32 KHMAPI
+khc_get_config_space_name(khm_handle conf,
+ wchar_t * buf,
+ khm_size * bufsize);
+
+/*! \brief Get a handle to the parent space
+
+ \param[in] conf Handle to a configuration space
+
+ \param[out] parent Handle to the parent configuration space if the
+ call succeeds. Receives NULL otherwise. The returned handle
+ must be closed using khc_close_space()
+ */
+KHMEXP khm_int32 KHMAPI
+khc_get_config_space_parent(khm_handle conf,
+ khm_handle * parent);
+
+/*! \brief Load a configuration schema into the specified configuration space
+
+ \param[in] conf Handle to a configuration space or NULL to use the
+ root configuration space.
+
+ \param[in] schema The schema to load. The schema is assumed to be
+ well formed.
+
+ \see khc_unload_schema()
+ */
+KHMEXP khm_int32 KHMAPI
+khc_load_schema(khm_handle conf,
+ const kconf_schema * schema);
+
+/*! \brief Unload a schema from a configuration space
+ */
+KHMEXP khm_int32 KHMAPI
+khc_unload_schema(khm_handle conf,
+ const kconf_schema * schema);
+
+/*! \brief Enumerate the subspaces of a configuration space
+
+ Prepares a configuration space for enumeration and returns the
+ child spaces in no particular order.
+
+ \param[in] conf The configuration space to enumerate child spaces
+
+ \param[in] prev The previous configuration space returned by
+ khc_enum_subspaces() or NULL if this is the first call. If
+ this is not NULL, then the handle passed in \a prev will be
+ freed.
+
+ \param[out] next If \a prev was NULL, receives the first sub space
+ found in \a conf. You must \b either call
+ khc_enum_subspaces() again with the returned handle or call
+ khc_close_space() to free the returned handle if no more
+ subspaces are required. \a next can point to the same handle
+ specified in \a prev.
+
+ \retval KHM_ERROR_SUCCESS The call succeeded. There is a valid
+ handle to a configuration space in \a first_subspace.
+
+ \retval KHM_ERROR_INVALID_PARAM Either \a conf or \a prev was not a
+ valid configuration space handle or \a first_subspace is NULL.
+ Note that \a prev can be NULL.
+
+ \retval KHM_ERROR_NOT_FOUND There were no subspaces in the
+ configuration space pointed to by \a conf.
+
+ \note The configuration spaces that are enumerated directly belong
+ to the configuration space given by \a conf. This function
+ does not enumerate subspaces of shadowed configuration spaces
+ (see khc_shadow_space()). Even if \a conf was obtained on a
+ restricted domain (i.e. you specified one or more
+ configuration stores when you openend the handle and didn't
+ include all the configuration stores. See khc_open_space()),
+ the subspaces that are returned are the union of all
+ configuration spaces in all the configuration stores. This is
+ not a bug. This is a feature. In NetIDMgr, a configuartion
+ space exists if some configuration store defines it (or it was
+ created with a call to khc_open_space() even if no
+ configuration store defines it yet). This is the tradeoff you
+ make when using a layered configuration system.
+
+ However, the returned handle has the same domain restrictions
+ as \a conf.
+ */
+KHMEXP khm_int32 KHMAPI
+khc_enum_subspaces(khm_handle conf,
+ khm_handle prev,
+ khm_handle * next);
+
+/*! \brief Remove a configuration space
+
+ The configuration space will be marked for removal. Once all the
+ handles for the space have been released, it will be deleted. The
+ configuration stores that will be affected are the write enabled
+ configuration stores for the handle.
+ */
+KHMEXP khm_int32 KHMAPI
+khc_remove_space(khm_handle conf);
+/*@}*/
+
+#endif
diff --git a/src/windows/identity/kconfig/kconfiginternal.h b/src/windows/identity/kconfig/kconfiginternal.h
index b4c39ee2d5..dc1bfa3635 100644
--- a/src/windows/identity/kconfig/kconfiginternal.h
+++ b/src/windows/identity/kconfig/kconfiginternal.h
@@ -1,129 +1,129 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#ifndef __KHIMAIRA_KCONFIGINTERNAL_H
-#define __KHIMAIRA_KCONFIGINTERNAL_H
-
-#include<windows.h>
-#include<kconfig.h>
-#include<khlist.h>
-#include<kherror.h>
-#include<utils.h>
-#include<strsafe.h>
-
-/* TODO: Implement configuration provider interfaces
-
-typedef struct kconf_provider_t {
-
-} kconf_provider;
-*/
-
-typedef struct kconf_conf_space_t {
- wchar_t * name;
-
- /* kconf_provider * provider; */
-
- /* the regpath is the cumulative path starting from a hive root */
- wchar_t * regpath;
- HKEY regkey_user;
- khm_int32 regkey_user_flags;
- HKEY regkey_machine;
- khm_int32 regkey_machine_flags;
-
- khm_int32 refcount;
- khm_int32 flags;
-
- const kconf_schema * schema;
- khm_int32 nSchema;
-
- TDCL(struct kconf_conf_space_t);
-} kconf_conf_space;
-
-#define KCONF_SPACE_FLAG_DELETE_U 0x00000040
-#define KCONF_SPACE_FLAG_DELETE_M 0x00000080
-#define KCONF_SPACE_FLAG_DELETED 0x00000100
-
-typedef struct kconf_conf_handle_t {
- khm_int32 magic;
- khm_int32 flags;
- kconf_conf_space * space;
-
- struct kconf_conf_handle_t * lower;
-
- LDCL(struct kconf_conf_handle_t);
-} kconf_handle;
-
-#define KCONF_HANDLE_MAGIC 0x38eb49d2
-#define khc_is_handle(h) ((h) && ((kconf_handle *)h)->magic == KCONF_HANDLE_MAGIC)
-#define khc_shadow(h) (((kconf_handle *)h)->lower)
-#define khc_is_shadowed(h) (khc_is_handle(h) && khc_shadow(h) != NULL)
-
-extern kconf_conf_space * conf_root;
-extern kconf_handle * conf_handles;
-extern kconf_handle * conf_free_handles;
-extern CRITICAL_SECTION cs_conf_global;
-extern LONG conf_init;
-extern LONG conf_status;
-
-#define khc_is_config_running() (conf_init && conf_status)
-
-#define CONFIG_REGPATHW L"Software\\MIT\\NetIDMgr"
-
-void init_kconf(void);
-void exit_kconf(void);
-
-/* handle operations */
-#define khc_space_from_handle(h) (((kconf_handle *) h)->space)
-#define khc_is_schema_handle(h) (((kconf_handle *) h)->flags & KCONF_FLAG_SCHEMA)
-#define khc_is_user_handle(h) (((kconf_handle *) h)->flags & KCONF_FLAG_USER)
-#define khc_is_machine_handle(h) (((kconf_handle *) h)->flags & KCONF_FLAG_MACHINE)
-#define khc_handle_flags(h) (((kconf_handle *) h)->flags)
-
-kconf_handle *
-khcint_handle_from_space(kconf_conf_space * s, khm_int32 flags);
-
-void
-khcint_handle_free(kconf_handle * h);
-
-kconf_conf_space *
-khcint_create_empty_space(void);
-
-void
-khcint_free_space(kconf_conf_space * r);
-
-void
-khcint_space_hold(kconf_conf_space * s);
-
-void
-khcint_space_release(kconf_conf_space * s);
-
-HKEY
-khcint_space_open_key(kconf_conf_space * s, khm_int32 flags);
-
-khm_int32
-khcint_remove_space(kconf_conf_space * c, khm_int32 flags);
-
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __KHIMAIRA_KCONFIGINTERNAL_H
+#define __KHIMAIRA_KCONFIGINTERNAL_H
+
+#include<windows.h>
+#include<kconfig.h>
+#include<khlist.h>
+#include<kherror.h>
+#include<utils.h>
+#include<strsafe.h>
+
+/* TODO: Implement configuration provider interfaces
+
+typedef struct kconf_provider_t {
+
+} kconf_provider;
+*/
+
+typedef struct kconf_conf_space_t {
+ wchar_t * name;
+
+ /* kconf_provider * provider; */
+
+ /* the regpath is the cumulative path starting from a hive root */
+ wchar_t * regpath;
+ HKEY regkey_user;
+ khm_int32 regkey_user_flags;
+ HKEY regkey_machine;
+ khm_int32 regkey_machine_flags;
+
+ khm_int32 refcount;
+ khm_int32 flags;
+
+ const kconf_schema * schema;
+ khm_int32 nSchema;
+
+ TDCL(struct kconf_conf_space_t);
+} kconf_conf_space;
+
+#define KCONF_SPACE_FLAG_DELETE_U 0x00000040
+#define KCONF_SPACE_FLAG_DELETE_M 0x00000080
+#define KCONF_SPACE_FLAG_DELETED 0x00000100
+
+typedef struct kconf_conf_handle_t {
+ khm_int32 magic;
+ khm_int32 flags;
+ kconf_conf_space * space;
+
+ struct kconf_conf_handle_t * lower;
+
+ LDCL(struct kconf_conf_handle_t);
+} kconf_handle;
+
+#define KCONF_HANDLE_MAGIC 0x38eb49d2
+#define khc_is_handle(h) ((h) && ((kconf_handle *)h)->magic == KCONF_HANDLE_MAGIC)
+#define khc_shadow(h) (((kconf_handle *)h)->lower)
+#define khc_is_shadowed(h) (khc_is_handle(h) && khc_shadow(h) != NULL)
+
+extern kconf_conf_space * conf_root;
+extern kconf_handle * conf_handles;
+extern kconf_handle * conf_free_handles;
+extern CRITICAL_SECTION cs_conf_global;
+extern LONG conf_init;
+extern LONG conf_status;
+
+#define khc_is_config_running() (conf_init && conf_status)
+
+#define CONFIG_REGPATHW L"Software\\MIT\\NetIDMgr"
+
+void init_kconf(void);
+void exit_kconf(void);
+
+/* handle operations */
+#define khc_space_from_handle(h) (((kconf_handle *) h)->space)
+#define khc_is_schema_handle(h) (((kconf_handle *) h)->flags & KCONF_FLAG_SCHEMA)
+#define khc_is_user_handle(h) (((kconf_handle *) h)->flags & KCONF_FLAG_USER)
+#define khc_is_machine_handle(h) (((kconf_handle *) h)->flags & KCONF_FLAG_MACHINE)
+#define khc_handle_flags(h) (((kconf_handle *) h)->flags)
+
+kconf_handle *
+khcint_handle_from_space(kconf_conf_space * s, khm_int32 flags);
+
+void
+khcint_handle_free(kconf_handle * h);
+
+kconf_conf_space *
+khcint_create_empty_space(void);
+
+void
+khcint_free_space(kconf_conf_space * r);
+
+void
+khcint_space_hold(kconf_conf_space * s);
+
+void
+khcint_space_release(kconf_conf_space * s);
+
+HKEY
+khcint_space_open_key(kconf_conf_space * s, khm_int32 flags);
+
+khm_int32
+khcint_remove_space(kconf_conf_space * c, khm_int32 flags);
+
+#endif
diff --git a/src/windows/identity/kconfig/kconfigmain.c b/src/windows/identity/kconfig/kconfigmain.c
index c49364ab28..bcf14625ef 100644
--- a/src/windows/identity/kconfig/kconfigmain.c
+++ b/src/windows/identity/kconfig/kconfigmain.c
@@ -1,37 +1,37 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<kconfiginternal.h>
-
-void
-kconfig_process_attach(void) {
- init_kconf();
-}
-
-void
-kconfig_process_detach(void) {
- exit_kconf();
-}
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<kconfiginternal.h>
+
+void
+kconfig_process_attach(void) {
+ init_kconf();
+}
+
+void
+kconfig_process_detach(void) {
+ exit_kconf();
+}
diff --git a/src/windows/identity/kconfig/registry.c b/src/windows/identity/kconfig/registry.c
index 03b49b2c03..d1e4009f2a 100644
--- a/src/windows/identity/kconfig/registry.c
+++ b/src/windows/identity/kconfig/registry.c
@@ -1,28 +1,28 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<kconfiginternal.h>
-
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<kconfiginternal.h>
+
diff --git a/src/windows/identity/kconfig/test/utiltest.c b/src/windows/identity/kconfig/test/utiltest.c
index 0652c63b98..f999dfa710 100644
--- a/src/windows/identity/kconfig/test/utiltest.c
+++ b/src/windows/identity/kconfig/test/utiltest.c
@@ -1,207 +1,207 @@
-#include<stdio.h>
-#include<kconfig.h>
-#include<strsafe.h>
-
-struct string_pair {
- wchar_t * ms;
- wchar_t * csv;
-};
-
-struct string_pair strings[] = {
- {L"foo\0bar\0baz,quux\0ab\"cd\0", L"foo,bar,\"baz,quux\",\"ab\"\"cd\""},
- {L"a\0b\0c\0d\0e\0", L"a,b,c,d,e"},
- {L"1\0", L"1"},
- {L"\0", L""},
- {L"b\0a\0", L"b,a"},
- {L"c\0a\0b\0", L"c,a,b"},
- {L"c\0a\0B\0", L"c,a,B"},
- {L"sdf\0Bar\0Foo\0BBB\0", L"sdf,Bar,Foo,BBB"}
-};
-
-int n_strings = ARRAYLENGTH(strings);
-
-void print_ms(wchar_t * ms) {
- wchar_t * s;
- size_t cch;
-
- s = ms;
- while(*s) {
- printf("%S\\0", s);
- StringCchLength(s, 512, &cch);
- s += cch + 1;
- }
-}
-
-int ms_to_csv_test(void) {
- wchar_t wbuf[512];
- int i;
- khm_int32 code = 0;
- size_t cbbuf;
- size_t cbr;
- size_t cbnull;
-
- printf("khc_multi_string_to_csv() test:\n");
-
- for(i=0; i<n_strings; i++) {
- cbbuf = sizeof(wbuf);
- printf("Multi string:[");
- print_ms(strings[i].ms);
- printf("]->");
- code = khc_multi_string_to_csv(NULL, &cbnull, strings[i].ms);
- code = khc_multi_string_to_csv(wbuf, &cbbuf, strings[i].ms);
- if(code) {
- printf(" returned %d\n", code);
- return code;
- }
- printf("CSV[%S]", wbuf);
- if(wcscmp(wbuf, strings[i].csv)) {
- printf(" MISMATCH!");
- return 1;
- }
-
- StringCbLength(wbuf, sizeof(wbuf), &cbr);
- cbr+= sizeof(wchar_t);
-
- if(cbr != cbbuf) {
- printf(" Length mismatch");
- return 1;
- }
-
- if(cbnull != cbr) {
- printf(" NULL length mismatch");
- return 1;
- }
-
- printf("\n");
- }
-
- return code;
-}
-
-int csv_to_ms_test(void) {
- wchar_t wbuf[512];
- int i;
- khm_int32 code = 0;
- size_t cbbuf;
- size_t cbr;
- size_t cbnull;
-
- printf("khc_csv_to_multi_string() test:\n");
-
- for(i=0; i<n_strings; i++) {
- cbbuf = sizeof(wbuf);
- printf("CSV:[%S]->", strings[i].csv);
- code = khc_csv_to_multi_string(NULL, &cbnull, strings[i].csv);
- code = khc_csv_to_multi_string(wbuf, &cbbuf, strings[i].csv);
- if(code) {
- printf(" returned %d\n", code);
- return code;
- }
- printf("MS[");
- print_ms(wbuf);
- printf("]");
-
- if(cbnull != cbbuf) {
- printf(" NULL length mismatch");
- return 1;
- }
-
- printf("\n");
-
- printf(" Byte length:%d\n", cbbuf);
- }
-
- return code;
-}
-
-int ms_append_test(void)
-{
- wchar_t wbuf[512];
- size_t cbbuf;
- khm_int32 code;
- int i;
-
- printf("khc_multi_string_append() test:\n");
-
- for(i=0; i<n_strings; i++) {
- cbbuf = sizeof(wbuf);
- khc_csv_to_multi_string(wbuf, &cbbuf, strings[i].csv);
-
- printf("MS[");
- print_ms(wbuf);
- printf("] + [foo]=[");
-
- cbbuf = sizeof(wbuf);
- code = khc_multi_string_append(wbuf, &cbbuf, L"foo");
-
- if(code) {
- printf(" returned %d\n", code);
- return code;
- }
-
- print_ms(wbuf);
- printf("]\n");
-
- printf(" byte length: %d\n", cbbuf);
- }
- return code;
-}
-
-int ms_delete_test(void)
-{
- int code = 0;
- wchar_t wbuf[512];
- int i;
- size_t cbs;
-
- printf("khc_multi_string_delete() test:\n");
- for(i=0; i<n_strings; i++) {
- cbs = sizeof(wbuf);
- khc_csv_to_multi_string(wbuf, &cbs, strings[i].csv);
-
- printf("MS[");
- print_ms(wbuf);
- printf("] - [b]=[");
-
- printf("cs:");
- code = khc_multi_string_delete(wbuf, L"b", KHC_CASE_SENSITIVE);
- if(code) {
- printf("ci:");
- code = khc_multi_string_delete(wbuf, L"b", 0);
- }
- if(code) {
- printf("pcs:");
- code = khc_multi_string_delete(wbuf, L"b", KHC_CASE_SENSITIVE | KHC_PREFIX);
- }
- if(code) {
- printf("pci:");
- code = khc_multi_string_delete(wbuf, L"b", KHC_PREFIX);
- }
-
- if(!code)
- print_ms(wbuf);
- else
- printf(" returned %d\n", code);
-
- printf("]\n");
- }
-
- return code;
-}
-
-int main(int argc, char ** argv) {
-
- if(ms_to_csv_test())
- return 1;
-
- if(csv_to_ms_test())
- return 1;
-
- if(ms_append_test())
- return 1;
-
- if(ms_delete_test())
- return 1;
-
- return 0;
-}
+#include<stdio.h>
+#include<kconfig.h>
+#include<strsafe.h>
+
+struct string_pair {
+ wchar_t * ms;
+ wchar_t * csv;
+};
+
+struct string_pair strings[] = {
+ {L"foo\0bar\0baz,quux\0ab\"cd\0", L"foo,bar,\"baz,quux\",\"ab\"\"cd\""},
+ {L"a\0b\0c\0d\0e\0", L"a,b,c,d,e"},
+ {L"1\0", L"1"},
+ {L"\0", L""},
+ {L"b\0a\0", L"b,a"},
+ {L"c\0a\0b\0", L"c,a,b"},
+ {L"c\0a\0B\0", L"c,a,B"},
+ {L"sdf\0Bar\0Foo\0BBB\0", L"sdf,Bar,Foo,BBB"}
+};
+
+int n_strings = ARRAYLENGTH(strings);
+
+void print_ms(wchar_t * ms) {
+ wchar_t * s;
+ size_t cch;
+
+ s = ms;
+ while(*s) {
+ printf("%S\\0", s);
+ StringCchLength(s, 512, &cch);
+ s += cch + 1;
+ }
+}
+
+int ms_to_csv_test(void) {
+ wchar_t wbuf[512];
+ int i;
+ khm_int32 code = 0;
+ size_t cbbuf;
+ size_t cbr;
+ size_t cbnull;
+
+ printf("khc_multi_string_to_csv() test:\n");
+
+ for(i=0; i<n_strings; i++) {
+ cbbuf = sizeof(wbuf);
+ printf("Multi string:[");
+ print_ms(strings[i].ms);
+ printf("]->");
+ code = khc_multi_string_to_csv(NULL, &cbnull, strings[i].ms);
+ code = khc_multi_string_to_csv(wbuf, &cbbuf, strings[i].ms);
+ if(code) {
+ printf(" returned %d\n", code);
+ return code;
+ }
+ printf("CSV[%S]", wbuf);
+ if(wcscmp(wbuf, strings[i].csv)) {
+ printf(" MISMATCH!");
+ return 1;
+ }
+
+ StringCbLength(wbuf, sizeof(wbuf), &cbr);
+ cbr+= sizeof(wchar_t);
+
+ if(cbr != cbbuf) {
+ printf(" Length mismatch");
+ return 1;
+ }
+
+ if(cbnull != cbr) {
+ printf(" NULL length mismatch");
+ return 1;
+ }
+
+ printf("\n");
+ }
+
+ return code;
+}
+
+int csv_to_ms_test(void) {
+ wchar_t wbuf[512];
+ int i;
+ khm_int32 code = 0;
+ size_t cbbuf;
+ size_t cbr;
+ size_t cbnull;
+
+ printf("khc_csv_to_multi_string() test:\n");
+
+ for(i=0; i<n_strings; i++) {
+ cbbuf = sizeof(wbuf);
+ printf("CSV:[%S]->", strings[i].csv);
+ code = khc_csv_to_multi_string(NULL, &cbnull, strings[i].csv);
+ code = khc_csv_to_multi_string(wbuf, &cbbuf, strings[i].csv);
+ if(code) {
+ printf(" returned %d\n", code);
+ return code;
+ }
+ printf("MS[");
+ print_ms(wbuf);
+ printf("]");
+
+ if(cbnull != cbbuf) {
+ printf(" NULL length mismatch");
+ return 1;
+ }
+
+ printf("\n");
+
+ printf(" Byte length:%d\n", cbbuf);
+ }
+
+ return code;
+}
+
+int ms_append_test(void)
+{
+ wchar_t wbuf[512];
+ size_t cbbuf;
+ khm_int32 code;
+ int i;
+
+ printf("khc_multi_string_append() test:\n");
+
+ for(i=0; i<n_strings; i++) {
+ cbbuf = sizeof(wbuf);
+ khc_csv_to_multi_string(wbuf, &cbbuf, strings[i].csv);
+
+ printf("MS[");
+ print_ms(wbuf);
+ printf("] + [foo]=[");
+
+ cbbuf = sizeof(wbuf);
+ code = khc_multi_string_append(wbuf, &cbbuf, L"foo");
+
+ if(code) {
+ printf(" returned %d\n", code);
+ return code;
+ }
+
+ print_ms(wbuf);
+ printf("]\n");
+
+ printf(" byte length: %d\n", cbbuf);
+ }
+ return code;
+}
+
+int ms_delete_test(void)
+{
+ int code = 0;
+ wchar_t wbuf[512];
+ int i;
+ size_t cbs;
+
+ printf("khc_multi_string_delete() test:\n");
+ for(i=0; i<n_strings; i++) {
+ cbs = sizeof(wbuf);
+ khc_csv_to_multi_string(wbuf, &cbs, strings[i].csv);
+
+ printf("MS[");
+ print_ms(wbuf);
+ printf("] - [b]=[");
+
+ printf("cs:");
+ code = khc_multi_string_delete(wbuf, L"b", KHC_CASE_SENSITIVE);
+ if(code) {
+ printf("ci:");
+ code = khc_multi_string_delete(wbuf, L"b", 0);
+ }
+ if(code) {
+ printf("pcs:");
+ code = khc_multi_string_delete(wbuf, L"b", KHC_CASE_SENSITIVE | KHC_PREFIX);
+ }
+ if(code) {
+ printf("pci:");
+ code = khc_multi_string_delete(wbuf, L"b", KHC_PREFIX);
+ }
+
+ if(!code)
+ print_ms(wbuf);
+ else
+ printf(" returned %d\n", code);
+
+ printf("]\n");
+ }
+
+ return code;
+}
+
+int main(int argc, char ** argv) {
+
+ if(ms_to_csv_test())
+ return 1;
+
+ if(csv_to_ms_test())
+ return 1;
+
+ if(ms_append_test())
+ return 1;
+
+ if(ms_delete_test())
+ return 1;
+
+ return 0;
+}
diff --git a/src/windows/identity/kcreddb/attrib.c b/src/windows/identity/kcreddb/attrib.c
index 9c892dafcb..983e3cc98e 100644
--- a/src/windows/identity/kcreddb/attrib.c
+++ b/src/windows/identity/kcreddb/attrib.c
@@ -1,878 +1,878 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<kcreddbinternal.h>
-#include<assert.h>
-
-CRITICAL_SECTION cs_attrib;
-hashtable * kcdb_attrib_namemap = NULL;
-kcdb_attrib_i ** kcdb_attrib_tbl = NULL;
-kcdb_attrib_i ** kcdb_property_tbl = NULL;
-kcdb_attrib_i * kcdb_attribs = NULL;
-
-void
-kcdb_attrib_add_ref_func(const void * key, void * va)
-{
- kcdb_attrib_hold((kcdb_attrib_i *) va);
-}
-
-void
-kcdb_attrib_del_ref_func(const void * key, void * va)
-{
- kcdb_attrib_release((kcdb_attrib_i *) va);
-}
-
-void
-kcdb_attrib_msg_completion(kmq_message * m)
-{
- if(m && m->vparam) {
- kcdb_attrib_release((kcdb_attrib_i *) m->vparam);
- }
-}
-
-khm_int32
-kcdb_attrib_hold(kcdb_attrib_i * ai)
-{
- if(!ai)
- return KHM_ERROR_INVALID_PARAM;
-
- EnterCriticalSection(&cs_attrib);
- ai->refcount++;
- LeaveCriticalSection(&cs_attrib);
- return KHM_ERROR_SUCCESS;
-}
-
-khm_int32
-kcdb_attrib_release(kcdb_attrib_i * ai)
-{
- if(!ai)
- return KHM_ERROR_INVALID_PARAM;
-
- EnterCriticalSection(&cs_attrib);
- ai->refcount--;
- LeaveCriticalSection(&cs_attrib);
- return KHM_ERROR_SUCCESS;
-}
-
-void
-kcdb_attrib_post_message(khm_int32 op, kcdb_attrib_i * ai)
-{
- kcdb_attrib_hold(ai);
- kmq_post_message(KMSG_KCDB, KMSG_KCDB_ATTRIB, op, (void *) ai);
-}
-
-khm_int32 KHMAPI
-kcdb_attr_sys_cb(khm_handle vcred,
- khm_int32 attr,
- void * buf,
- khm_size * pcb_buf)
-{
- kcdb_cred * c;
-
- c = (kcdb_cred *) vcred;
-
- switch(attr) {
- case KCDB_ATTR_NAME:
- return kcdb_cred_get_name(vcred, buf, pcb_buf);
-
- case KCDB_ATTR_ID:
- if(buf && *pcb_buf >= sizeof(khm_ui_8)) {
- *pcb_buf = sizeof(khm_int64);
- *((khm_ui_8 *) buf) = (khm_ui_8) c->identity;
- return KHM_ERROR_SUCCESS;
- } else {
- *pcb_buf = sizeof(khm_ui_8);
- return KHM_ERROR_TOO_LONG;
- }
-
- case KCDB_ATTR_ID_NAME:
- return kcdb_identity_get_name((khm_handle) c->identity,
- (wchar_t *) buf, pcb_buf);
-
- case KCDB_ATTR_TYPE:
- if(buf && *pcb_buf >= sizeof(khm_int32)) {
- *pcb_buf = sizeof(khm_int32);
- *((khm_int32 *) buf) = c->type;
- return KHM_ERROR_SUCCESS;
- } else {
- *pcb_buf = sizeof(khm_int32);
- return KHM_ERROR_TOO_LONG;
- }
-
- case KCDB_ATTR_TYPE_NAME:
- return kcdb_credtype_describe(c->type, buf,
- pcb_buf, KCDB_TS_SHORT);
-
- case KCDB_ATTR_TIMELEFT:
- {
- khm_int32 rv = KHM_ERROR_SUCCESS;
-
- if(!buf || *pcb_buf < sizeof(FILETIME)) {
- *pcb_buf = sizeof(FILETIME);
- rv = KHM_ERROR_TOO_LONG;
- } else if(!kcdb_cred_buf_exist(c,KCDB_ATTR_EXPIRE)) {
- *pcb_buf = sizeof(FILETIME);
- /* setting the timeleft to _I64_MAX has the
- interpretation that this credential does not
- expire, which is the default behavior if the
- expiration time is not known */
- *((FILETIME *) buf) = IntToFt(_I64_MAX);
- } else {
- FILETIME ftc;
- khm_int64 iftc;
-
- GetSystemTimeAsFileTime(&ftc);
- iftc = FtToInt(&ftc);
-
- *((FILETIME *) buf) =
- IntToFt(FtToInt((FILETIME *)
- kcdb_cred_buf_get(c,KCDB_ATTR_EXPIRE))
- - iftc);
- *pcb_buf = sizeof(FILETIME);
- }
-
- return rv;
- }
-
- case KCDB_ATTR_RENEW_TIMELEFT:
- {
- khm_int32 rv = KHM_ERROR_SUCCESS;
-
- if(!buf || *pcb_buf < sizeof(FILETIME)) {
- *pcb_buf = sizeof(FILETIME);
- rv = KHM_ERROR_TOO_LONG;
- } else if(!kcdb_cred_buf_exist(c,KCDB_ATTR_RENEW_EXPIRE)) {
- *pcb_buf = sizeof(FILETIME);
- /* setting the timeleft to _I64_MAX has the
- interpretation that this credential does not
- expire, which is the default behavior if the
- expiration time is not known */
- *((FILETIME *) buf) = IntToFt(_I64_MAX);
- } else {
- FILETIME ftc;
- khm_int64 i_re;
- khm_int64 i_ct;
-
- GetSystemTimeAsFileTime(&ftc);
-
- i_re = FtToInt(((FILETIME *)
- kcdb_cred_buf_get(c, KCDB_ATTR_RENEW_EXPIRE)));
- i_ct = FtToInt(&ftc);
-
- if (i_re > i_ct)
- *((FILETIME *) buf) =
- IntToFt(i_re - i_ct);
- else
- *((FILETIME *) buf) =
- IntToFt(0);
-
- *pcb_buf = sizeof(FILETIME);
- }
-
- return rv;
- }
-
- case KCDB_ATTR_FLAGS:
- if(buf && *pcb_buf >= sizeof(khm_int32)) {
- *pcb_buf = sizeof(khm_int32);
- *((khm_int32 *) buf) = c->flags;
- return KHM_ERROR_SUCCESS;
- } else {
- *pcb_buf = sizeof(khm_int32);
- return KHM_ERROR_TOO_LONG;
- }
-
- default:
- return KHM_ERROR_NOT_FOUND;
- }
-}
-
-void
-kcdb_attrib_init(void)
-{
- kcdb_attrib attrib;
- wchar_t sbuf[256];
-
- InitializeCriticalSection(&cs_attrib);
- kcdb_attrib_namemap =
- hash_new_hashtable(KCDB_ATTRIB_HASH_SIZE,
- hash_string,
- hash_string_comp,
- kcdb_attrib_add_ref_func,
- kcdb_attrib_del_ref_func);
-
- kcdb_attrib_tbl =
- PMALLOC(sizeof(kcdb_attrib_i *) * (KCDB_ATTR_MAX_ID + 1));
- assert(kcdb_attrib_tbl != NULL);
- ZeroMemory(kcdb_attrib_tbl,
- sizeof(kcdb_attrib_i *) * (KCDB_ATTR_MAX_ID + 1));
-
- kcdb_property_tbl =
- PMALLOC(sizeof(kcdb_attrib_i *) * KCDB_ATTR_MAX_PROPS);
- assert(kcdb_property_tbl != NULL);
- ZeroMemory(kcdb_property_tbl,
- sizeof(kcdb_attrib_i *) * KCDB_ATTR_MAX_PROPS);
-
- kcdb_attribs = NULL;
-
- /* register standard attributes */
-
- /* Name */
- attrib.id = KCDB_ATTR_NAME;
- attrib.name = KCDB_ATTRNAME_NAME;
- attrib.type = KCDB_TYPE_STRING;
- LoadString(hinst_kcreddb, IDS_NAME, sbuf, ARRAYLENGTH(sbuf));
- attrib.short_desc = sbuf;
- attrib.long_desc = NULL;
- attrib.flags =
- KCDB_ATTR_FLAG_REQUIRED |
- KCDB_ATTR_FLAG_COMPUTED |
- KCDB_ATTR_FLAG_SYSTEM;
- attrib.compute_cb = kcdb_attr_sys_cb;
- attrib.compute_min_cbsize = sizeof(wchar_t);
- attrib.compute_max_cbsize = KCDB_MAXCB_NAME;
-
- kcdb_attrib_register(&attrib, NULL);
-
- /* ID */
- attrib.id = KCDB_ATTR_ID;
- attrib.name = KCDB_ATTRNAME_ID;
- attrib.type = KCDB_TYPE_INT64;
- LoadString(hinst_kcreddb, IDS_IDENTITY, sbuf, ARRAYLENGTH(sbuf));
- attrib.short_desc = sbuf;
- attrib.long_desc = NULL;
- attrib.flags =
- KCDB_ATTR_FLAG_REQUIRED |
- KCDB_ATTR_FLAG_COMPUTED |
- KCDB_ATTR_FLAG_SYSTEM |
- KCDB_ATTR_FLAG_HIDDEN;
- attrib.compute_cb = kcdb_attr_sys_cb;
- attrib.compute_min_cbsize = sizeof(khm_int32);
- attrib.compute_max_cbsize = sizeof(khm_int32);
-
- kcdb_attrib_register(&attrib, NULL);
-
- /* ID Name */
- attrib.id = KCDB_ATTR_ID_NAME;
- attrib.alt_id = KCDB_ATTR_ID;
- attrib.name = KCDB_ATTRNAME_ID_NAME;
- attrib.type = KCDB_TYPE_STRING;
- LoadString(hinst_kcreddb, IDS_IDENTITY, sbuf, ARRAYLENGTH(sbuf));
- attrib.short_desc = sbuf;
- attrib.long_desc = NULL;
- attrib.flags =
- KCDB_ATTR_FLAG_REQUIRED |
- KCDB_ATTR_FLAG_COMPUTED |
- KCDB_ATTR_FLAG_ALTVIEW |
- KCDB_ATTR_FLAG_SYSTEM;
- attrib.compute_cb = kcdb_attr_sys_cb;
- attrib.compute_min_cbsize = sizeof(wchar_t);
- attrib.compute_max_cbsize = KCDB_IDENT_MAXCB_NAME;
-
- kcdb_attrib_register(&attrib, NULL);
-
- /* Type */
- attrib.id = KCDB_ATTR_TYPE;
- attrib.name = KCDB_ATTRNAME_TYPE;
- attrib.type = KCDB_TYPE_INT32;
- LoadString(hinst_kcreddb, IDS_TYPE, sbuf, ARRAYLENGTH(sbuf));
- attrib.short_desc = sbuf;
- attrib.long_desc = NULL;
- attrib.flags =
- KCDB_ATTR_FLAG_REQUIRED |
- KCDB_ATTR_FLAG_COMPUTED |
- KCDB_ATTR_FLAG_SYSTEM |
- KCDB_ATTR_FLAG_HIDDEN;
- attrib.compute_cb = kcdb_attr_sys_cb;
- attrib.compute_min_cbsize = sizeof(khm_int32);
- attrib.compute_max_cbsize = sizeof(khm_int32);
-
- kcdb_attrib_register(&attrib, NULL);
-
- /* Type Name */
- attrib.id = KCDB_ATTR_TYPE_NAME;
- attrib.alt_id = KCDB_ATTR_TYPE;
- attrib.name = KCDB_ATTRNAME_TYPE_NAME;
- attrib.type = KCDB_TYPE_STRING;
- LoadString(hinst_kcreddb, IDS_TYPE, sbuf, ARRAYLENGTH(sbuf));
- attrib.short_desc = sbuf;
- attrib.long_desc = NULL;
- attrib.flags =
- KCDB_ATTR_FLAG_REQUIRED |
- KCDB_ATTR_FLAG_COMPUTED |
- KCDB_ATTR_FLAG_ALTVIEW |
- KCDB_ATTR_FLAG_SYSTEM;
- attrib.compute_cb = kcdb_attr_sys_cb;
- attrib.compute_min_cbsize = sizeof(wchar_t);
- attrib.compute_max_cbsize = KCDB_MAXCB_NAME;
-
- kcdb_attrib_register(&attrib, NULL);
-
- /* Parent Name */
- attrib.id = KCDB_ATTR_PARENT_NAME;
- attrib.name = KCDB_ATTRNAME_PARENT_NAME;
- attrib.type = KCDB_TYPE_STRING;
- LoadString(hinst_kcreddb, IDS_PARENT, sbuf, ARRAYLENGTH(sbuf));
- attrib.short_desc = sbuf;
- attrib.long_desc = NULL;
- attrib.flags = KCDB_ATTR_FLAG_SYSTEM | KCDB_ATTR_FLAG_HIDDEN;
- attrib.compute_cb = NULL;
- attrib.compute_min_cbsize = 0;
- attrib.compute_max_cbsize = 0;
-
- kcdb_attrib_register(&attrib, NULL);
-
- /* Issed On */
- attrib.id = KCDB_ATTR_ISSUE;
- attrib.name = KCDB_ATTRNAME_ISSUE;
- attrib.type = KCDB_TYPE_DATE;
- LoadString(hinst_kcreddb, IDS_ISSUED, sbuf, ARRAYLENGTH(sbuf));
- attrib.short_desc = sbuf;
- attrib.long_desc = NULL;
- attrib.flags = KCDB_ATTR_FLAG_SYSTEM;
- attrib.compute_cb = NULL;
- attrib.compute_min_cbsize = 0;
- attrib.compute_max_cbsize = 0;
-
- kcdb_attrib_register(&attrib, NULL);
-
- /* Expires On */
- attrib.id = KCDB_ATTR_EXPIRE;
- attrib.name = KCDB_ATTRNAME_EXPIRE;
- attrib.type = KCDB_TYPE_DATE;
- LoadString(hinst_kcreddb, IDS_EXPIRES, sbuf, ARRAYLENGTH(sbuf));
- attrib.short_desc = sbuf;
- attrib.long_desc = NULL;
- attrib.flags = KCDB_ATTR_FLAG_SYSTEM;
- attrib.compute_cb = NULL;
- attrib.compute_min_cbsize = 0;
- attrib.compute_max_cbsize = 0;
-
- kcdb_attrib_register(&attrib, NULL);
-
- /* Renewable Time Expires On */
- attrib.id = KCDB_ATTR_RENEW_EXPIRE;
- attrib.name = KCDB_ATTRNAME_RENEW_EXPIRE;
- attrib.type = KCDB_TYPE_DATE;
- LoadString(hinst_kcreddb, IDS_RENEW_EXPIRES,
- sbuf, ARRAYLENGTH(sbuf));
- attrib.short_desc = sbuf;
- attrib.long_desc = NULL;
- attrib.flags = KCDB_ATTR_FLAG_SYSTEM;
- attrib.compute_cb = NULL;
- attrib.compute_min_cbsize = 0;
- attrib.compute_max_cbsize = 0;
-
- kcdb_attrib_register(&attrib, NULL);
-
- /* Time Left */
- attrib.id = KCDB_ATTR_TIMELEFT;
- attrib.alt_id = KCDB_ATTR_EXPIRE;
- attrib.name = KCDB_ATTRNAME_TIMELEFT;
- attrib.type = KCDB_TYPE_INTERVAL;
- LoadString(hinst_kcreddb, IDS_TIMELEFT, sbuf, ARRAYLENGTH(sbuf));
- attrib.short_desc = sbuf;
- attrib.long_desc = NULL;
- attrib.flags = KCDB_ATTR_FLAG_SYSTEM |
- KCDB_ATTR_FLAG_COMPUTED |
- KCDB_ATTR_FLAG_ALTVIEW |
- KCDB_ATTR_FLAG_VOLATILE;
- attrib.compute_cb = kcdb_attr_sys_cb;
- attrib.compute_min_cbsize = sizeof(FILETIME);
- attrib.compute_max_cbsize = sizeof(FILETIME);
-
- kcdb_attrib_register(&attrib, NULL);
-
- /* Renewable Time Left */
- attrib.id = KCDB_ATTR_RENEW_TIMELEFT;
- attrib.alt_id = KCDB_ATTR_RENEW_EXPIRE;
- attrib.name = KCDB_ATTRNAME_RENEW_TIMELEFT;
- attrib.type = KCDB_TYPE_INTERVAL;
- LoadString(hinst_kcreddb,
- IDS_RENEW_TIMELEFT, sbuf, ARRAYLENGTH(sbuf));
- attrib.short_desc = sbuf;
- attrib.long_desc = NULL;
- attrib.flags = KCDB_ATTR_FLAG_SYSTEM |
- KCDB_ATTR_FLAG_COMPUTED |
- KCDB_ATTR_FLAG_ALTVIEW |
- KCDB_ATTR_FLAG_VOLATILE;
- attrib.compute_cb = kcdb_attr_sys_cb;
- attrib.compute_min_cbsize = sizeof(FILETIME);
- attrib.compute_max_cbsize = sizeof(FILETIME);
-
- kcdb_attrib_register(&attrib, NULL);
-
- /* Location of Credential */
- attrib.id = KCDB_ATTR_LOCATION;
- attrib.name = KCDB_ATTRNAME_LOCATION;
- attrib.type = KCDB_TYPE_STRING;
- LoadString(hinst_kcreddb, IDS_LOCATION, sbuf, ARRAYLENGTH(sbuf));
- attrib.short_desc = sbuf;
- attrib.long_desc = NULL;
- attrib.flags = KCDB_ATTR_FLAG_SYSTEM;
- attrib.compute_cb = NULL;
- attrib.compute_min_cbsize = 0;
- attrib.compute_max_cbsize = 0;
-
- kcdb_attrib_register(&attrib, NULL);
-
- /* Lifetime */
- attrib.id = KCDB_ATTR_LIFETIME;
- attrib.name = KCDB_ATTRNAME_LIFETIME;
- attrib.type = KCDB_TYPE_INTERVAL;
- LoadString(hinst_kcreddb, IDS_LIFETIME, sbuf, ARRAYLENGTH(sbuf));
- attrib.short_desc = sbuf;
- attrib.long_desc = NULL;
- attrib.flags = KCDB_ATTR_FLAG_SYSTEM;
- attrib.compute_cb = NULL;
- attrib.compute_min_cbsize = 0;
- attrib.compute_max_cbsize = 0;
-
- kcdb_attrib_register(&attrib, NULL);
-
- /* Renewable Lifetime */
- attrib.id = KCDB_ATTR_RENEW_LIFETIME;
- attrib.name = KCDB_ATTRNAME_RENEW_LIFETIME;
- attrib.type = KCDB_TYPE_INTERVAL;
- LoadString(hinst_kcreddb,
- IDS_RENEW_LIFETIME, sbuf, ARRAYLENGTH(sbuf));
- attrib.short_desc = sbuf;
- attrib.long_desc = NULL;
- attrib.flags = KCDB_ATTR_FLAG_SYSTEM;
- attrib.compute_cb = NULL;
- attrib.compute_min_cbsize = 0;
- attrib.compute_max_cbsize = 0;
-
- kcdb_attrib_register(&attrib, NULL);
-
- /* Flags */
- attrib.id = KCDB_ATTR_FLAGS;
- attrib.name = KCDB_ATTRNAME_FLAGS;
- attrib.type = KCDB_TYPE_INT32;
- LoadString(hinst_kcreddb, IDS_FLAGS, sbuf, ARRAYLENGTH(sbuf));
- attrib.short_desc = sbuf;
- attrib.long_desc = NULL;
- attrib.flags =
- KCDB_ATTR_FLAG_REQUIRED |
- KCDB_ATTR_FLAG_COMPUTED |
- KCDB_ATTR_FLAG_SYSTEM |
- KCDB_ATTR_FLAG_HIDDEN;
- attrib.compute_cb = kcdb_attr_sys_cb;
- attrib.compute_min_cbsize = sizeof(khm_int32);
- attrib.compute_max_cbsize = sizeof(khm_int32);
-
- kcdb_attrib_register(&attrib, NULL);
-}
-
-void
-kcdb_attrib_exit(void)
-{
- DeleteCriticalSection(&cs_attrib);
-
- if(kcdb_attrib_tbl)
- PFREE(kcdb_attrib_tbl);
-
- if(kcdb_property_tbl)
- PFREE(kcdb_property_tbl);
-}
-
-KHMEXP khm_int32 KHMAPI
-kcdb_attrib_get_id(const wchar_t *name, khm_int32 * id)
-{
- kcdb_attrib_i * ai;
-
- if(!name)
- return KHM_ERROR_INVALID_PARAM;
-
- EnterCriticalSection(&cs_attrib);
- ai = hash_lookup(kcdb_attrib_namemap, (void *) name);
- LeaveCriticalSection(&cs_attrib);
-
- if(ai) {
- *id = ai->attr.id;
- return KHM_ERROR_SUCCESS;
- } else {
- *id = KCDB_ATTR_INVALID;
- return KHM_ERROR_NOT_FOUND;
- }
-}
-
-KHMEXP khm_int32 KHMAPI
-kcdb_attrib_register(const kcdb_attrib * attrib, khm_int32 * new_id)
-{
- kcdb_attrib_i * ai;
- size_t cb_name;
- size_t cb_short_desc;
- size_t cb_long_desc;
- khm_int32 attr_id;
- khm_boolean prop = FALSE;
-
- if(!attrib ||
- KHM_FAILED(kcdb_type_get_info(attrib->type, NULL)) ||
- !attrib->name)
- return KHM_ERROR_INVALID_PARAM;
-
- if(FAILED(StringCbLength(attrib->name, KCDB_MAXCB_NAME, &cb_name)))
- return KHM_ERROR_TOO_LONG;
- cb_name += sizeof(wchar_t);
-
- if(attrib->short_desc) {
- if(FAILED(StringCbLength(attrib->short_desc, KCDB_MAXCB_SHORT_DESC, &cb_short_desc)))
- return KHM_ERROR_TOO_LONG;
- cb_short_desc += sizeof(wchar_t);
- } else
- cb_short_desc = 0;
-
- if(attrib->long_desc) {
- if(FAILED(StringCbLength(attrib->long_desc, KCDB_MAXCB_LONG_DESC, &cb_long_desc)))
- return KHM_ERROR_TOO_LONG;
- cb_long_desc += sizeof(wchar_t);
- } else
- cb_long_desc = 0;
-
- if((attrib->flags & KCDB_ATTR_FLAG_COMPUTED) &&
- (!attrib->compute_cb ||
- attrib->compute_min_cbsize <= 0 ||
- attrib->compute_max_cbsize < attrib->compute_min_cbsize))
- return KHM_ERROR_INVALID_PARAM;
-
- if ((attrib->flags & KCDB_ATTR_FLAG_ALTVIEW) &&
- KHM_FAILED(kcdb_attrib_get_info(attrib->alt_id,
- NULL)))
- return KHM_ERROR_INVALID_PARAM;
-
- prop = !!(attrib->flags & KCDB_ATTR_FLAG_PROPERTY);
-
- EnterCriticalSection(&cs_attrib);
-
- if(!prop &&
- (attrib->id < 0 || attrib->id > KCDB_ATTR_MAX_ID))
- {
- if(KHM_FAILED(kcdb_attrib_next_free_id(&attr_id))) {
- LeaveCriticalSection(&cs_attrib);
- return KHM_ERROR_NO_RESOURCES;
- }
- } else if (prop &&
- (attrib->id < KCDB_ATTR_MIN_PROP_ID ||
- attrib->id > KCDB_ATTR_MAX_PROP_ID)) {
-
- if(KHM_FAILED(kcdb_attrib_next_free_prop_id(&attr_id))) {
- LeaveCriticalSection(&cs_attrib);
- return KHM_ERROR_NO_RESOURCES;
- }
-
- } else {
- attr_id = attrib->id;
- }
-
-#ifdef DEBUG
- assert(!prop || (attr_id >= KCDB_ATTR_MIN_PROP_ID && attr_id <= KCDB_ATTR_MAX_PROP_ID));
- assert(prop || (attr_id >= 0 && attr_id <= KCDB_ATTR_MAX_ID));
-#endif
-
- if((!prop && kcdb_attrib_tbl[attr_id]) ||
- (prop && kcdb_property_tbl[attr_id - KCDB_ATTR_MIN_PROP_ID])) {
-
- LeaveCriticalSection(&cs_attrib);
- return KHM_ERROR_DUPLICATE;
-
- }
-
- ai = PMALLOC(sizeof(kcdb_attrib_i));
- ZeroMemory(ai, sizeof(kcdb_attrib_i));
-
- ai->attr.type = attrib->type;
- ai->attr.id = attr_id;
- ai->attr.alt_id = attrib->alt_id;
- ai->attr.flags = attrib->flags;
- ai->attr.compute_cb = attrib->compute_cb;
- ai->attr.compute_max_cbsize = attrib->compute_max_cbsize;
- ai->attr.compute_min_cbsize = attrib->compute_min_cbsize;
- ai->attr.name = PMALLOC(cb_name);
- StringCbCopy(ai->attr.name, cb_name, attrib->name);
- if(cb_short_desc) {
- ai->attr.short_desc = PMALLOC(cb_short_desc);
- StringCbCopy(ai->attr.short_desc, cb_short_desc, attrib->short_desc);
- }
- if(cb_long_desc) {
- ai->attr.long_desc = PMALLOC(cb_long_desc);
- StringCbCopy(ai->attr.long_desc, cb_long_desc, attrib->long_desc);
- }
-
- LINIT(ai);
-
- if(!prop)
- kcdb_attrib_tbl[attr_id] = ai;
- else
- kcdb_property_tbl[attr_id - KCDB_ATTR_MIN_PROP_ID] = ai;
-
- LPUSH(&kcdb_attribs, ai);
-
- hash_add(kcdb_attrib_namemap, (void *) ai->attr.name, ai);
-
- LeaveCriticalSection(&cs_attrib);
-
- kcdb_attrib_post_message(KCDB_OP_INSERT, ai);
-
- if(new_id)
- *new_id = attr_id;
-
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP khm_int32 KHMAPI kcdb_attrib_get_info(
- khm_int32 id,
- kcdb_attrib ** attrib)
-{
- kcdb_attrib_i * ai;
- khm_boolean prop;
-
- if(id >= 0 && id <= KCDB_ATTR_MAX_ID)
- prop = FALSE;
- else if(id >= KCDB_ATTR_MIN_PROP_ID && id <= KCDB_ATTR_MAX_PROP_ID)
- prop = TRUE;
- else
- return KHM_ERROR_INVALID_PARAM;
-
- EnterCriticalSection(&cs_attrib);
- if(prop)
- ai = kcdb_property_tbl[id - KCDB_ATTR_MIN_PROP_ID];
- else
- ai = kcdb_attrib_tbl[id];
- LeaveCriticalSection(&cs_attrib);
-
- if(ai) {
- if(attrib) {
- *attrib = &(ai->attr);
- kcdb_attrib_hold(ai);
- }
- return KHM_ERROR_SUCCESS;
- } else {
- if(attrib)
- *attrib = NULL;
- return KHM_ERROR_NOT_FOUND;
- }
-}
-
-KHMEXP khm_int32 KHMAPI kcdb_attrib_release_info(kcdb_attrib * attrib)
-{
- if(attrib)
- kcdb_attrib_release((kcdb_attrib_i *) attrib);
- return KHM_ERROR_SUCCESS;
-}
-
-
-KHMEXP khm_int32 KHMAPI kcdb_attrib_unregister(khm_int32 id)
-{
- /*TODO: implement this */
- return KHM_ERROR_NOT_IMPLEMENTED;
-}
-
-KHMEXP khm_int32 KHMAPI kcdb_attrib_describe(
- khm_int32 id,
- wchar_t * buffer,
- khm_size * cbsize,
- khm_int32 flags)
-{
- kcdb_attrib_i * ai;
- size_t cb_size = 0;
- khm_boolean prop = FALSE;
-
- if(!cbsize)
- return KHM_ERROR_INVALID_PARAM;
-
- if(id >= 0 && id <= KCDB_ATTR_MAX_ID)
- prop = FALSE;
- else if(id >= KCDB_ATTR_MIN_PROP_ID && id <= KCDB_ATTR_MAX_PROP_ID)
- prop = TRUE;
- else
- return KHM_ERROR_INVALID_PARAM;
-
- if(prop)
- ai = kcdb_property_tbl[id - KCDB_ATTR_MIN_PROP_ID];
- else
- ai = kcdb_attrib_tbl[id];
-
- if(!ai)
- return KHM_ERROR_NOT_FOUND;
-
- if((flags & KCDB_TS_SHORT) &&
- ai->attr.short_desc)
- {
- if(FAILED(StringCbLength(ai->attr.short_desc, KCDB_MAXCB_SHORT_DESC, &cb_size)))
- return KHM_ERROR_UNKNOWN;
- cb_size += sizeof(wchar_t);
-
- if(!buffer || *cbsize < cb_size) {
- *cbsize = cb_size;
- return KHM_ERROR_TOO_LONG;
- }
-
- StringCbCopy(buffer, *cbsize, ai->attr.short_desc);
-
- *cbsize = cb_size;
-
- return KHM_ERROR_SUCCESS;
- } else {
- if(FAILED(StringCbLength(ai->attr.long_desc, KCDB_MAXCB_LONG_DESC, &cb_size)))
- return KHM_ERROR_UNKNOWN;
- cb_size += sizeof(wchar_t);
-
- if(!buffer || *cbsize < cb_size) {
- *cbsize = cb_size;
- return KHM_ERROR_TOO_LONG;
- }
-
- StringCbCopy(buffer, *cbsize, ai->attr.long_desc);
-
- *cbsize = cb_size;
-
- return KHM_ERROR_SUCCESS;
- }
-}
-
-khm_int32 kcdb_attrib_next_free_prop_id(khm_int32 * id)
-{
- int i;
-
- if(!id)
- return KHM_ERROR_INVALID_PARAM;
-
- EnterCriticalSection(&cs_attrib);
- for(i=0;i < KCDB_ATTR_MAX_PROPS; i++) {
- if(!kcdb_property_tbl[i])
- break;
- }
- LeaveCriticalSection(&cs_attrib);
-
- if(i < KCDB_ATTR_MAX_PROPS) {
- *id = i + KCDB_ATTR_MIN_PROP_ID;
- return KHM_ERROR_SUCCESS;
- } else {
- *id = KCDB_ATTR_INVALID;
- return KHM_ERROR_NO_RESOURCES;
- }
-}
-
-khm_int32 kcdb_attrib_next_free_id(khm_int32 * id)
-{
- int i;
-
- if(!id)
- return KHM_ERROR_INVALID_PARAM;
-
- EnterCriticalSection(&cs_attrib);
- for(i=0;i<= KCDB_ATTR_MAX_ID; i++) {
- if(!kcdb_attrib_tbl[i])
- break;
- }
- LeaveCriticalSection(&cs_attrib);
-
- if(i <= KCDB_ATTR_MAX_ID) {
- *id = i;
- return KHM_ERROR_SUCCESS;
- } else {
- *id = KCDB_ATTR_INVALID;
- return KHM_ERROR_NO_RESOURCES;
- }
-}
-
-KHMEXP khm_int32 KHMAPI kcdb_attrib_get_count(
- khm_int32 and_flags,
- khm_int32 eq_flags,
- khm_size * pcount)
-{
- khm_int32 rv = KHM_ERROR_SUCCESS;
- khm_size count = 0;
- int i;
-
- if(pcount == NULL)
- return KHM_ERROR_INVALID_PARAM;
-
- eq_flags &= and_flags;
-
- EnterCriticalSection(&cs_attrib);
- for(i = 0; i <= KCDB_ATTR_MAX_ID; i++) {
- if(kcdb_attrib_tbl[i] &&
- (kcdb_attrib_tbl[i]->attr.flags & and_flags) == eq_flags)
- count++;
- }
-
- for(i = 0; i < KCDB_ATTR_MAX_PROPS; i++) {
- if(kcdb_property_tbl[i] &&
- (kcdb_property_tbl[i]->attr.flags & and_flags) == eq_flags)
- count++;
- }
- LeaveCriticalSection(&cs_attrib);
-
- *pcount = count;
-
- return rv;
-}
-
-KHMEXP khm_int32 KHMAPI kcdb_attrib_get_ids(
- khm_int32 and_flags,
- khm_int32 eq_flags,
- khm_int32 * plist,
- khm_size * pcsize)
-{
- khm_int32 rv = KHM_ERROR_SUCCESS;
- khm_size count = 0;
- int i;
-
- if(plist == NULL || pcsize == NULL)
- return KHM_ERROR_INVALID_PARAM;
-
- eq_flags &= and_flags;
-
- EnterCriticalSection(&cs_attrib);
- for(i = 0; i <= KCDB_ATTR_MAX_ID; i++) {
- if(kcdb_attrib_tbl[i] &&
- (kcdb_attrib_tbl[i]->attr.flags & and_flags) == eq_flags) {
- if(count >= *pcsize) {
- rv = KHM_ERROR_TOO_LONG;
- count++;
- } else
- plist[count++] = i;
- }
- }
-
- for(i = 0; i < KCDB_ATTR_MAX_PROPS; i++) {
- if(kcdb_property_tbl[i] &&
- (kcdb_property_tbl[i]->attr.flags & and_flags) == eq_flags) {
- if(count >= *pcsize) {
- rv = KHM_ERROR_TOO_LONG;
- count++;
- } else
- plist[count++] = i + KCDB_ATTR_MIN_PROP_ID;
- }
- }
- LeaveCriticalSection(&cs_attrib);
-
- *pcsize = count;
-
- return rv;
-}
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<kcreddbinternal.h>
+#include<assert.h>
+
+CRITICAL_SECTION cs_attrib;
+hashtable * kcdb_attrib_namemap = NULL;
+kcdb_attrib_i ** kcdb_attrib_tbl = NULL;
+kcdb_attrib_i ** kcdb_property_tbl = NULL;
+kcdb_attrib_i * kcdb_attribs = NULL;
+
+void
+kcdb_attrib_add_ref_func(const void * key, void * va)
+{
+ kcdb_attrib_hold((kcdb_attrib_i *) va);
+}
+
+void
+kcdb_attrib_del_ref_func(const void * key, void * va)
+{
+ kcdb_attrib_release((kcdb_attrib_i *) va);
+}
+
+void
+kcdb_attrib_msg_completion(kmq_message * m)
+{
+ if(m && m->vparam) {
+ kcdb_attrib_release((kcdb_attrib_i *) m->vparam);
+ }
+}
+
+khm_int32
+kcdb_attrib_hold(kcdb_attrib_i * ai)
+{
+ if(!ai)
+ return KHM_ERROR_INVALID_PARAM;
+
+ EnterCriticalSection(&cs_attrib);
+ ai->refcount++;
+ LeaveCriticalSection(&cs_attrib);
+ return KHM_ERROR_SUCCESS;
+}
+
+khm_int32
+kcdb_attrib_release(kcdb_attrib_i * ai)
+{
+ if(!ai)
+ return KHM_ERROR_INVALID_PARAM;
+
+ EnterCriticalSection(&cs_attrib);
+ ai->refcount--;
+ LeaveCriticalSection(&cs_attrib);
+ return KHM_ERROR_SUCCESS;
+}
+
+void
+kcdb_attrib_post_message(khm_int32 op, kcdb_attrib_i * ai)
+{
+ kcdb_attrib_hold(ai);
+ kmq_post_message(KMSG_KCDB, KMSG_KCDB_ATTRIB, op, (void *) ai);
+}
+
+khm_int32 KHMAPI
+kcdb_attr_sys_cb(khm_handle vcred,
+ khm_int32 attr,
+ void * buf,
+ khm_size * pcb_buf)
+{
+ kcdb_cred * c;
+
+ c = (kcdb_cred *) vcred;
+
+ switch(attr) {
+ case KCDB_ATTR_NAME:
+ return kcdb_cred_get_name(vcred, buf, pcb_buf);
+
+ case KCDB_ATTR_ID:
+ if(buf && *pcb_buf >= sizeof(khm_ui_8)) {
+ *pcb_buf = sizeof(khm_int64);
+ *((khm_ui_8 *) buf) = (khm_ui_8) c->identity;
+ return KHM_ERROR_SUCCESS;
+ } else {
+ *pcb_buf = sizeof(khm_ui_8);
+ return KHM_ERROR_TOO_LONG;
+ }
+
+ case KCDB_ATTR_ID_NAME:
+ return kcdb_identity_get_name((khm_handle) c->identity,
+ (wchar_t *) buf, pcb_buf);
+
+ case KCDB_ATTR_TYPE:
+ if(buf && *pcb_buf >= sizeof(khm_int32)) {
+ *pcb_buf = sizeof(khm_int32);
+ *((khm_int32 *) buf) = c->type;
+ return KHM_ERROR_SUCCESS;
+ } else {
+ *pcb_buf = sizeof(khm_int32);
+ return KHM_ERROR_TOO_LONG;
+ }
+
+ case KCDB_ATTR_TYPE_NAME:
+ return kcdb_credtype_describe(c->type, buf,
+ pcb_buf, KCDB_TS_SHORT);
+
+ case KCDB_ATTR_TIMELEFT:
+ {
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+
+ if(!buf || *pcb_buf < sizeof(FILETIME)) {
+ *pcb_buf = sizeof(FILETIME);
+ rv = KHM_ERROR_TOO_LONG;
+ } else if(!kcdb_cred_buf_exist(c,KCDB_ATTR_EXPIRE)) {
+ *pcb_buf = sizeof(FILETIME);
+ /* setting the timeleft to _I64_MAX has the
+ interpretation that this credential does not
+ expire, which is the default behavior if the
+ expiration time is not known */
+ *((FILETIME *) buf) = IntToFt(_I64_MAX);
+ } else {
+ FILETIME ftc;
+ khm_int64 iftc;
+
+ GetSystemTimeAsFileTime(&ftc);
+ iftc = FtToInt(&ftc);
+
+ *((FILETIME *) buf) =
+ IntToFt(FtToInt((FILETIME *)
+ kcdb_cred_buf_get(c,KCDB_ATTR_EXPIRE))
+ - iftc);
+ *pcb_buf = sizeof(FILETIME);
+ }
+
+ return rv;
+ }
+
+ case KCDB_ATTR_RENEW_TIMELEFT:
+ {
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+
+ if(!buf || *pcb_buf < sizeof(FILETIME)) {
+ *pcb_buf = sizeof(FILETIME);
+ rv = KHM_ERROR_TOO_LONG;
+ } else if(!kcdb_cred_buf_exist(c,KCDB_ATTR_RENEW_EXPIRE)) {
+ *pcb_buf = sizeof(FILETIME);
+ /* setting the timeleft to _I64_MAX has the
+ interpretation that this credential does not
+ expire, which is the default behavior if the
+ expiration time is not known */
+ *((FILETIME *) buf) = IntToFt(_I64_MAX);
+ } else {
+ FILETIME ftc;
+ khm_int64 i_re;
+ khm_int64 i_ct;
+
+ GetSystemTimeAsFileTime(&ftc);
+
+ i_re = FtToInt(((FILETIME *)
+ kcdb_cred_buf_get(c, KCDB_ATTR_RENEW_EXPIRE)));
+ i_ct = FtToInt(&ftc);
+
+ if (i_re > i_ct)
+ *((FILETIME *) buf) =
+ IntToFt(i_re - i_ct);
+ else
+ *((FILETIME *) buf) =
+ IntToFt(0);
+
+ *pcb_buf = sizeof(FILETIME);
+ }
+
+ return rv;
+ }
+
+ case KCDB_ATTR_FLAGS:
+ if(buf && *pcb_buf >= sizeof(khm_int32)) {
+ *pcb_buf = sizeof(khm_int32);
+ *((khm_int32 *) buf) = c->flags;
+ return KHM_ERROR_SUCCESS;
+ } else {
+ *pcb_buf = sizeof(khm_int32);
+ return KHM_ERROR_TOO_LONG;
+ }
+
+ default:
+ return KHM_ERROR_NOT_FOUND;
+ }
+}
+
+void
+kcdb_attrib_init(void)
+{
+ kcdb_attrib attrib;
+ wchar_t sbuf[256];
+
+ InitializeCriticalSection(&cs_attrib);
+ kcdb_attrib_namemap =
+ hash_new_hashtable(KCDB_ATTRIB_HASH_SIZE,
+ hash_string,
+ hash_string_comp,
+ kcdb_attrib_add_ref_func,
+ kcdb_attrib_del_ref_func);
+
+ kcdb_attrib_tbl =
+ PMALLOC(sizeof(kcdb_attrib_i *) * (KCDB_ATTR_MAX_ID + 1));
+ assert(kcdb_attrib_tbl != NULL);
+ ZeroMemory(kcdb_attrib_tbl,
+ sizeof(kcdb_attrib_i *) * (KCDB_ATTR_MAX_ID + 1));
+
+ kcdb_property_tbl =
+ PMALLOC(sizeof(kcdb_attrib_i *) * KCDB_ATTR_MAX_PROPS);
+ assert(kcdb_property_tbl != NULL);
+ ZeroMemory(kcdb_property_tbl,
+ sizeof(kcdb_attrib_i *) * KCDB_ATTR_MAX_PROPS);
+
+ kcdb_attribs = NULL;
+
+ /* register standard attributes */
+
+ /* Name */
+ attrib.id = KCDB_ATTR_NAME;
+ attrib.name = KCDB_ATTRNAME_NAME;
+ attrib.type = KCDB_TYPE_STRING;
+ LoadString(hinst_kcreddb, IDS_NAME, sbuf, ARRAYLENGTH(sbuf));
+ attrib.short_desc = sbuf;
+ attrib.long_desc = NULL;
+ attrib.flags =
+ KCDB_ATTR_FLAG_REQUIRED |
+ KCDB_ATTR_FLAG_COMPUTED |
+ KCDB_ATTR_FLAG_SYSTEM;
+ attrib.compute_cb = kcdb_attr_sys_cb;
+ attrib.compute_min_cbsize = sizeof(wchar_t);
+ attrib.compute_max_cbsize = KCDB_MAXCB_NAME;
+
+ kcdb_attrib_register(&attrib, NULL);
+
+ /* ID */
+ attrib.id = KCDB_ATTR_ID;
+ attrib.name = KCDB_ATTRNAME_ID;
+ attrib.type = KCDB_TYPE_INT64;
+ LoadString(hinst_kcreddb, IDS_IDENTITY, sbuf, ARRAYLENGTH(sbuf));
+ attrib.short_desc = sbuf;
+ attrib.long_desc = NULL;
+ attrib.flags =
+ KCDB_ATTR_FLAG_REQUIRED |
+ KCDB_ATTR_FLAG_COMPUTED |
+ KCDB_ATTR_FLAG_SYSTEM |
+ KCDB_ATTR_FLAG_HIDDEN;
+ attrib.compute_cb = kcdb_attr_sys_cb;
+ attrib.compute_min_cbsize = sizeof(khm_int32);
+ attrib.compute_max_cbsize = sizeof(khm_int32);
+
+ kcdb_attrib_register(&attrib, NULL);
+
+ /* ID Name */
+ attrib.id = KCDB_ATTR_ID_NAME;
+ attrib.alt_id = KCDB_ATTR_ID;
+ attrib.name = KCDB_ATTRNAME_ID_NAME;
+ attrib.type = KCDB_TYPE_STRING;
+ LoadString(hinst_kcreddb, IDS_IDENTITY, sbuf, ARRAYLENGTH(sbuf));
+ attrib.short_desc = sbuf;
+ attrib.long_desc = NULL;
+ attrib.flags =
+ KCDB_ATTR_FLAG_REQUIRED |
+ KCDB_ATTR_FLAG_COMPUTED |
+ KCDB_ATTR_FLAG_ALTVIEW |
+ KCDB_ATTR_FLAG_SYSTEM;
+ attrib.compute_cb = kcdb_attr_sys_cb;
+ attrib.compute_min_cbsize = sizeof(wchar_t);
+ attrib.compute_max_cbsize = KCDB_IDENT_MAXCB_NAME;
+
+ kcdb_attrib_register(&attrib, NULL);
+
+ /* Type */
+ attrib.id = KCDB_ATTR_TYPE;
+ attrib.name = KCDB_ATTRNAME_TYPE;
+ attrib.type = KCDB_TYPE_INT32;
+ LoadString(hinst_kcreddb, IDS_TYPE, sbuf, ARRAYLENGTH(sbuf));
+ attrib.short_desc = sbuf;
+ attrib.long_desc = NULL;
+ attrib.flags =
+ KCDB_ATTR_FLAG_REQUIRED |
+ KCDB_ATTR_FLAG_COMPUTED |
+ KCDB_ATTR_FLAG_SYSTEM |
+ KCDB_ATTR_FLAG_HIDDEN;
+ attrib.compute_cb = kcdb_attr_sys_cb;
+ attrib.compute_min_cbsize = sizeof(khm_int32);
+ attrib.compute_max_cbsize = sizeof(khm_int32);
+
+ kcdb_attrib_register(&attrib, NULL);
+
+ /* Type Name */
+ attrib.id = KCDB_ATTR_TYPE_NAME;
+ attrib.alt_id = KCDB_ATTR_TYPE;
+ attrib.name = KCDB_ATTRNAME_TYPE_NAME;
+ attrib.type = KCDB_TYPE_STRING;
+ LoadString(hinst_kcreddb, IDS_TYPE, sbuf, ARRAYLENGTH(sbuf));
+ attrib.short_desc = sbuf;
+ attrib.long_desc = NULL;
+ attrib.flags =
+ KCDB_ATTR_FLAG_REQUIRED |
+ KCDB_ATTR_FLAG_COMPUTED |
+ KCDB_ATTR_FLAG_ALTVIEW |
+ KCDB_ATTR_FLAG_SYSTEM;
+ attrib.compute_cb = kcdb_attr_sys_cb;
+ attrib.compute_min_cbsize = sizeof(wchar_t);
+ attrib.compute_max_cbsize = KCDB_MAXCB_NAME;
+
+ kcdb_attrib_register(&attrib, NULL);
+
+ /* Parent Name */
+ attrib.id = KCDB_ATTR_PARENT_NAME;
+ attrib.name = KCDB_ATTRNAME_PARENT_NAME;
+ attrib.type = KCDB_TYPE_STRING;
+ LoadString(hinst_kcreddb, IDS_PARENT, sbuf, ARRAYLENGTH(sbuf));
+ attrib.short_desc = sbuf;
+ attrib.long_desc = NULL;
+ attrib.flags = KCDB_ATTR_FLAG_SYSTEM | KCDB_ATTR_FLAG_HIDDEN;
+ attrib.compute_cb = NULL;
+ attrib.compute_min_cbsize = 0;
+ attrib.compute_max_cbsize = 0;
+
+ kcdb_attrib_register(&attrib, NULL);
+
+ /* Issed On */
+ attrib.id = KCDB_ATTR_ISSUE;
+ attrib.name = KCDB_ATTRNAME_ISSUE;
+ attrib.type = KCDB_TYPE_DATE;
+ LoadString(hinst_kcreddb, IDS_ISSUED, sbuf, ARRAYLENGTH(sbuf));
+ attrib.short_desc = sbuf;
+ attrib.long_desc = NULL;
+ attrib.flags = KCDB_ATTR_FLAG_SYSTEM;
+ attrib.compute_cb = NULL;
+ attrib.compute_min_cbsize = 0;
+ attrib.compute_max_cbsize = 0;
+
+ kcdb_attrib_register(&attrib, NULL);
+
+ /* Expires On */
+ attrib.id = KCDB_ATTR_EXPIRE;
+ attrib.name = KCDB_ATTRNAME_EXPIRE;
+ attrib.type = KCDB_TYPE_DATE;
+ LoadString(hinst_kcreddb, IDS_EXPIRES, sbuf, ARRAYLENGTH(sbuf));
+ attrib.short_desc = sbuf;
+ attrib.long_desc = NULL;
+ attrib.flags = KCDB_ATTR_FLAG_SYSTEM;
+ attrib.compute_cb = NULL;
+ attrib.compute_min_cbsize = 0;
+ attrib.compute_max_cbsize = 0;
+
+ kcdb_attrib_register(&attrib, NULL);
+
+ /* Renewable Time Expires On */
+ attrib.id = KCDB_ATTR_RENEW_EXPIRE;
+ attrib.name = KCDB_ATTRNAME_RENEW_EXPIRE;
+ attrib.type = KCDB_TYPE_DATE;
+ LoadString(hinst_kcreddb, IDS_RENEW_EXPIRES,
+ sbuf, ARRAYLENGTH(sbuf));
+ attrib.short_desc = sbuf;
+ attrib.long_desc = NULL;
+ attrib.flags = KCDB_ATTR_FLAG_SYSTEM;
+ attrib.compute_cb = NULL;
+ attrib.compute_min_cbsize = 0;
+ attrib.compute_max_cbsize = 0;
+
+ kcdb_attrib_register(&attrib, NULL);
+
+ /* Time Left */
+ attrib.id = KCDB_ATTR_TIMELEFT;
+ attrib.alt_id = KCDB_ATTR_EXPIRE;
+ attrib.name = KCDB_ATTRNAME_TIMELEFT;
+ attrib.type = KCDB_TYPE_INTERVAL;
+ LoadString(hinst_kcreddb, IDS_TIMELEFT, sbuf, ARRAYLENGTH(sbuf));
+ attrib.short_desc = sbuf;
+ attrib.long_desc = NULL;
+ attrib.flags = KCDB_ATTR_FLAG_SYSTEM |
+ KCDB_ATTR_FLAG_COMPUTED |
+ KCDB_ATTR_FLAG_ALTVIEW |
+ KCDB_ATTR_FLAG_VOLATILE;
+ attrib.compute_cb = kcdb_attr_sys_cb;
+ attrib.compute_min_cbsize = sizeof(FILETIME);
+ attrib.compute_max_cbsize = sizeof(FILETIME);
+
+ kcdb_attrib_register(&attrib, NULL);
+
+ /* Renewable Time Left */
+ attrib.id = KCDB_ATTR_RENEW_TIMELEFT;
+ attrib.alt_id = KCDB_ATTR_RENEW_EXPIRE;
+ attrib.name = KCDB_ATTRNAME_RENEW_TIMELEFT;
+ attrib.type = KCDB_TYPE_INTERVAL;
+ LoadString(hinst_kcreddb,
+ IDS_RENEW_TIMELEFT, sbuf, ARRAYLENGTH(sbuf));
+ attrib.short_desc = sbuf;
+ attrib.long_desc = NULL;
+ attrib.flags = KCDB_ATTR_FLAG_SYSTEM |
+ KCDB_ATTR_FLAG_COMPUTED |
+ KCDB_ATTR_FLAG_ALTVIEW |
+ KCDB_ATTR_FLAG_VOLATILE;
+ attrib.compute_cb = kcdb_attr_sys_cb;
+ attrib.compute_min_cbsize = sizeof(FILETIME);
+ attrib.compute_max_cbsize = sizeof(FILETIME);
+
+ kcdb_attrib_register(&attrib, NULL);
+
+ /* Location of Credential */
+ attrib.id = KCDB_ATTR_LOCATION;
+ attrib.name = KCDB_ATTRNAME_LOCATION;
+ attrib.type = KCDB_TYPE_STRING;
+ LoadString(hinst_kcreddb, IDS_LOCATION, sbuf, ARRAYLENGTH(sbuf));
+ attrib.short_desc = sbuf;
+ attrib.long_desc = NULL;
+ attrib.flags = KCDB_ATTR_FLAG_SYSTEM;
+ attrib.compute_cb = NULL;
+ attrib.compute_min_cbsize = 0;
+ attrib.compute_max_cbsize = 0;
+
+ kcdb_attrib_register(&attrib, NULL);
+
+ /* Lifetime */
+ attrib.id = KCDB_ATTR_LIFETIME;
+ attrib.name = KCDB_ATTRNAME_LIFETIME;
+ attrib.type = KCDB_TYPE_INTERVAL;
+ LoadString(hinst_kcreddb, IDS_LIFETIME, sbuf, ARRAYLENGTH(sbuf));
+ attrib.short_desc = sbuf;
+ attrib.long_desc = NULL;
+ attrib.flags = KCDB_ATTR_FLAG_SYSTEM;
+ attrib.compute_cb = NULL;
+ attrib.compute_min_cbsize = 0;
+ attrib.compute_max_cbsize = 0;
+
+ kcdb_attrib_register(&attrib, NULL);
+
+ /* Renewable Lifetime */
+ attrib.id = KCDB_ATTR_RENEW_LIFETIME;
+ attrib.name = KCDB_ATTRNAME_RENEW_LIFETIME;
+ attrib.type = KCDB_TYPE_INTERVAL;
+ LoadString(hinst_kcreddb,
+ IDS_RENEW_LIFETIME, sbuf, ARRAYLENGTH(sbuf));
+ attrib.short_desc = sbuf;
+ attrib.long_desc = NULL;
+ attrib.flags = KCDB_ATTR_FLAG_SYSTEM;
+ attrib.compute_cb = NULL;
+ attrib.compute_min_cbsize = 0;
+ attrib.compute_max_cbsize = 0;
+
+ kcdb_attrib_register(&attrib, NULL);
+
+ /* Flags */
+ attrib.id = KCDB_ATTR_FLAGS;
+ attrib.name = KCDB_ATTRNAME_FLAGS;
+ attrib.type = KCDB_TYPE_INT32;
+ LoadString(hinst_kcreddb, IDS_FLAGS, sbuf, ARRAYLENGTH(sbuf));
+ attrib.short_desc = sbuf;
+ attrib.long_desc = NULL;
+ attrib.flags =
+ KCDB_ATTR_FLAG_REQUIRED |
+ KCDB_ATTR_FLAG_COMPUTED |
+ KCDB_ATTR_FLAG_SYSTEM |
+ KCDB_ATTR_FLAG_HIDDEN;
+ attrib.compute_cb = kcdb_attr_sys_cb;
+ attrib.compute_min_cbsize = sizeof(khm_int32);
+ attrib.compute_max_cbsize = sizeof(khm_int32);
+
+ kcdb_attrib_register(&attrib, NULL);
+}
+
+void
+kcdb_attrib_exit(void)
+{
+ DeleteCriticalSection(&cs_attrib);
+
+ if(kcdb_attrib_tbl)
+ PFREE(kcdb_attrib_tbl);
+
+ if(kcdb_property_tbl)
+ PFREE(kcdb_property_tbl);
+}
+
+KHMEXP khm_int32 KHMAPI
+kcdb_attrib_get_id(const wchar_t *name, khm_int32 * id)
+{
+ kcdb_attrib_i * ai;
+
+ if(!name)
+ return KHM_ERROR_INVALID_PARAM;
+
+ EnterCriticalSection(&cs_attrib);
+ ai = hash_lookup(kcdb_attrib_namemap, (void *) name);
+ LeaveCriticalSection(&cs_attrib);
+
+ if(ai) {
+ *id = ai->attr.id;
+ return KHM_ERROR_SUCCESS;
+ } else {
+ *id = KCDB_ATTR_INVALID;
+ return KHM_ERROR_NOT_FOUND;
+ }
+}
+
+KHMEXP khm_int32 KHMAPI
+kcdb_attrib_register(const kcdb_attrib * attrib, khm_int32 * new_id)
+{
+ kcdb_attrib_i * ai;
+ size_t cb_name;
+ size_t cb_short_desc;
+ size_t cb_long_desc;
+ khm_int32 attr_id;
+ khm_boolean prop = FALSE;
+
+ if(!attrib ||
+ KHM_FAILED(kcdb_type_get_info(attrib->type, NULL)) ||
+ !attrib->name)
+ return KHM_ERROR_INVALID_PARAM;
+
+ if(FAILED(StringCbLength(attrib->name, KCDB_MAXCB_NAME, &cb_name)))
+ return KHM_ERROR_TOO_LONG;
+ cb_name += sizeof(wchar_t);
+
+ if(attrib->short_desc) {
+ if(FAILED(StringCbLength(attrib->short_desc, KCDB_MAXCB_SHORT_DESC, &cb_short_desc)))
+ return KHM_ERROR_TOO_LONG;
+ cb_short_desc += sizeof(wchar_t);
+ } else
+ cb_short_desc = 0;
+
+ if(attrib->long_desc) {
+ if(FAILED(StringCbLength(attrib->long_desc, KCDB_MAXCB_LONG_DESC, &cb_long_desc)))
+ return KHM_ERROR_TOO_LONG;
+ cb_long_desc += sizeof(wchar_t);
+ } else
+ cb_long_desc = 0;
+
+ if((attrib->flags & KCDB_ATTR_FLAG_COMPUTED) &&
+ (!attrib->compute_cb ||
+ attrib->compute_min_cbsize <= 0 ||
+ attrib->compute_max_cbsize < attrib->compute_min_cbsize))
+ return KHM_ERROR_INVALID_PARAM;
+
+ if ((attrib->flags & KCDB_ATTR_FLAG_ALTVIEW) &&
+ KHM_FAILED(kcdb_attrib_get_info(attrib->alt_id,
+ NULL)))
+ return KHM_ERROR_INVALID_PARAM;
+
+ prop = !!(attrib->flags & KCDB_ATTR_FLAG_PROPERTY);
+
+ EnterCriticalSection(&cs_attrib);
+
+ if(!prop &&
+ (attrib->id < 0 || attrib->id > KCDB_ATTR_MAX_ID))
+ {
+ if(KHM_FAILED(kcdb_attrib_next_free_id(&attr_id))) {
+ LeaveCriticalSection(&cs_attrib);
+ return KHM_ERROR_NO_RESOURCES;
+ }
+ } else if (prop &&
+ (attrib->id < KCDB_ATTR_MIN_PROP_ID ||
+ attrib->id > KCDB_ATTR_MAX_PROP_ID)) {
+
+ if(KHM_FAILED(kcdb_attrib_next_free_prop_id(&attr_id))) {
+ LeaveCriticalSection(&cs_attrib);
+ return KHM_ERROR_NO_RESOURCES;
+ }
+
+ } else {
+ attr_id = attrib->id;
+ }
+
+#ifdef DEBUG
+ assert(!prop || (attr_id >= KCDB_ATTR_MIN_PROP_ID && attr_id <= KCDB_ATTR_MAX_PROP_ID));
+ assert(prop || (attr_id >= 0 && attr_id <= KCDB_ATTR_MAX_ID));
+#endif
+
+ if((!prop && kcdb_attrib_tbl[attr_id]) ||
+ (prop && kcdb_property_tbl[attr_id - KCDB_ATTR_MIN_PROP_ID])) {
+
+ LeaveCriticalSection(&cs_attrib);
+ return KHM_ERROR_DUPLICATE;
+
+ }
+
+ ai = PMALLOC(sizeof(kcdb_attrib_i));
+ ZeroMemory(ai, sizeof(kcdb_attrib_i));
+
+ ai->attr.type = attrib->type;
+ ai->attr.id = attr_id;
+ ai->attr.alt_id = attrib->alt_id;
+ ai->attr.flags = attrib->flags;
+ ai->attr.compute_cb = attrib->compute_cb;
+ ai->attr.compute_max_cbsize = attrib->compute_max_cbsize;
+ ai->attr.compute_min_cbsize = attrib->compute_min_cbsize;
+ ai->attr.name = PMALLOC(cb_name);
+ StringCbCopy(ai->attr.name, cb_name, attrib->name);
+ if(cb_short_desc) {
+ ai->attr.short_desc = PMALLOC(cb_short_desc);
+ StringCbCopy(ai->attr.short_desc, cb_short_desc, attrib->short_desc);
+ }
+ if(cb_long_desc) {
+ ai->attr.long_desc = PMALLOC(cb_long_desc);
+ StringCbCopy(ai->attr.long_desc, cb_long_desc, attrib->long_desc);
+ }
+
+ LINIT(ai);
+
+ if(!prop)
+ kcdb_attrib_tbl[attr_id] = ai;
+ else
+ kcdb_property_tbl[attr_id - KCDB_ATTR_MIN_PROP_ID] = ai;
+
+ LPUSH(&kcdb_attribs, ai);
+
+ hash_add(kcdb_attrib_namemap, (void *) ai->attr.name, ai);
+
+ LeaveCriticalSection(&cs_attrib);
+
+ kcdb_attrib_post_message(KCDB_OP_INSERT, ai);
+
+ if(new_id)
+ *new_id = attr_id;
+
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP khm_int32 KHMAPI kcdb_attrib_get_info(
+ khm_int32 id,
+ kcdb_attrib ** attrib)
+{
+ kcdb_attrib_i * ai;
+ khm_boolean prop;
+
+ if(id >= 0 && id <= KCDB_ATTR_MAX_ID)
+ prop = FALSE;
+ else if(id >= KCDB_ATTR_MIN_PROP_ID && id <= KCDB_ATTR_MAX_PROP_ID)
+ prop = TRUE;
+ else
+ return KHM_ERROR_INVALID_PARAM;
+
+ EnterCriticalSection(&cs_attrib);
+ if(prop)
+ ai = kcdb_property_tbl[id - KCDB_ATTR_MIN_PROP_ID];
+ else
+ ai = kcdb_attrib_tbl[id];
+ LeaveCriticalSection(&cs_attrib);
+
+ if(ai) {
+ if(attrib) {
+ *attrib = &(ai->attr);
+ kcdb_attrib_hold(ai);
+ }
+ return KHM_ERROR_SUCCESS;
+ } else {
+ if(attrib)
+ *attrib = NULL;
+ return KHM_ERROR_NOT_FOUND;
+ }
+}
+
+KHMEXP khm_int32 KHMAPI kcdb_attrib_release_info(kcdb_attrib * attrib)
+{
+ if(attrib)
+ kcdb_attrib_release((kcdb_attrib_i *) attrib);
+ return KHM_ERROR_SUCCESS;
+}
+
+
+KHMEXP khm_int32 KHMAPI kcdb_attrib_unregister(khm_int32 id)
+{
+ /*TODO: implement this */
+ return KHM_ERROR_NOT_IMPLEMENTED;
+}
+
+KHMEXP khm_int32 KHMAPI kcdb_attrib_describe(
+ khm_int32 id,
+ wchar_t * buffer,
+ khm_size * cbsize,
+ khm_int32 flags)
+{
+ kcdb_attrib_i * ai;
+ size_t cb_size = 0;
+ khm_boolean prop = FALSE;
+
+ if(!cbsize)
+ return KHM_ERROR_INVALID_PARAM;
+
+ if(id >= 0 && id <= KCDB_ATTR_MAX_ID)
+ prop = FALSE;
+ else if(id >= KCDB_ATTR_MIN_PROP_ID && id <= KCDB_ATTR_MAX_PROP_ID)
+ prop = TRUE;
+ else
+ return KHM_ERROR_INVALID_PARAM;
+
+ if(prop)
+ ai = kcdb_property_tbl[id - KCDB_ATTR_MIN_PROP_ID];
+ else
+ ai = kcdb_attrib_tbl[id];
+
+ if(!ai)
+ return KHM_ERROR_NOT_FOUND;
+
+ if((flags & KCDB_TS_SHORT) &&
+ ai->attr.short_desc)
+ {
+ if(FAILED(StringCbLength(ai->attr.short_desc, KCDB_MAXCB_SHORT_DESC, &cb_size)))
+ return KHM_ERROR_UNKNOWN;
+ cb_size += sizeof(wchar_t);
+
+ if(!buffer || *cbsize < cb_size) {
+ *cbsize = cb_size;
+ return KHM_ERROR_TOO_LONG;
+ }
+
+ StringCbCopy(buffer, *cbsize, ai->attr.short_desc);
+
+ *cbsize = cb_size;
+
+ return KHM_ERROR_SUCCESS;
+ } else {
+ if(FAILED(StringCbLength(ai->attr.long_desc, KCDB_MAXCB_LONG_DESC, &cb_size)))
+ return KHM_ERROR_UNKNOWN;
+ cb_size += sizeof(wchar_t);
+
+ if(!buffer || *cbsize < cb_size) {
+ *cbsize = cb_size;
+ return KHM_ERROR_TOO_LONG;
+ }
+
+ StringCbCopy(buffer, *cbsize, ai->attr.long_desc);
+
+ *cbsize = cb_size;
+
+ return KHM_ERROR_SUCCESS;
+ }
+}
+
+khm_int32 kcdb_attrib_next_free_prop_id(khm_int32 * id)
+{
+ int i;
+
+ if(!id)
+ return KHM_ERROR_INVALID_PARAM;
+
+ EnterCriticalSection(&cs_attrib);
+ for(i=0;i < KCDB_ATTR_MAX_PROPS; i++) {
+ if(!kcdb_property_tbl[i])
+ break;
+ }
+ LeaveCriticalSection(&cs_attrib);
+
+ if(i < KCDB_ATTR_MAX_PROPS) {
+ *id = i + KCDB_ATTR_MIN_PROP_ID;
+ return KHM_ERROR_SUCCESS;
+ } else {
+ *id = KCDB_ATTR_INVALID;
+ return KHM_ERROR_NO_RESOURCES;
+ }
+}
+
+khm_int32 kcdb_attrib_next_free_id(khm_int32 * id)
+{
+ int i;
+
+ if(!id)
+ return KHM_ERROR_INVALID_PARAM;
+
+ EnterCriticalSection(&cs_attrib);
+ for(i=0;i<= KCDB_ATTR_MAX_ID; i++) {
+ if(!kcdb_attrib_tbl[i])
+ break;
+ }
+ LeaveCriticalSection(&cs_attrib);
+
+ if(i <= KCDB_ATTR_MAX_ID) {
+ *id = i;
+ return KHM_ERROR_SUCCESS;
+ } else {
+ *id = KCDB_ATTR_INVALID;
+ return KHM_ERROR_NO_RESOURCES;
+ }
+}
+
+KHMEXP khm_int32 KHMAPI kcdb_attrib_get_count(
+ khm_int32 and_flags,
+ khm_int32 eq_flags,
+ khm_size * pcount)
+{
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+ khm_size count = 0;
+ int i;
+
+ if(pcount == NULL)
+ return KHM_ERROR_INVALID_PARAM;
+
+ eq_flags &= and_flags;
+
+ EnterCriticalSection(&cs_attrib);
+ for(i = 0; i <= KCDB_ATTR_MAX_ID; i++) {
+ if(kcdb_attrib_tbl[i] &&
+ (kcdb_attrib_tbl[i]->attr.flags & and_flags) == eq_flags)
+ count++;
+ }
+
+ for(i = 0; i < KCDB_ATTR_MAX_PROPS; i++) {
+ if(kcdb_property_tbl[i] &&
+ (kcdb_property_tbl[i]->attr.flags & and_flags) == eq_flags)
+ count++;
+ }
+ LeaveCriticalSection(&cs_attrib);
+
+ *pcount = count;
+
+ return rv;
+}
+
+KHMEXP khm_int32 KHMAPI kcdb_attrib_get_ids(
+ khm_int32 and_flags,
+ khm_int32 eq_flags,
+ khm_int32 * plist,
+ khm_size * pcsize)
+{
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+ khm_size count = 0;
+ int i;
+
+ if(plist == NULL || pcsize == NULL)
+ return KHM_ERROR_INVALID_PARAM;
+
+ eq_flags &= and_flags;
+
+ EnterCriticalSection(&cs_attrib);
+ for(i = 0; i <= KCDB_ATTR_MAX_ID; i++) {
+ if(kcdb_attrib_tbl[i] &&
+ (kcdb_attrib_tbl[i]->attr.flags & and_flags) == eq_flags) {
+ if(count >= *pcsize) {
+ rv = KHM_ERROR_TOO_LONG;
+ count++;
+ } else
+ plist[count++] = i;
+ }
+ }
+
+ for(i = 0; i < KCDB_ATTR_MAX_PROPS; i++) {
+ if(kcdb_property_tbl[i] &&
+ (kcdb_property_tbl[i]->attr.flags & and_flags) == eq_flags) {
+ if(count >= *pcsize) {
+ rv = KHM_ERROR_TOO_LONG;
+ count++;
+ } else
+ plist[count++] = i + KCDB_ATTR_MIN_PROP_ID;
+ }
+ }
+ LeaveCriticalSection(&cs_attrib);
+
+ *pcsize = count;
+
+ return rv;
+}
diff --git a/src/windows/identity/kcreddb/attrib.h b/src/windows/identity/kcreddb/attrib.h
index f5647d67a6..2f0cc0f8e8 100644
--- a/src/windows/identity/kcreddb/attrib.h
+++ b/src/windows/identity/kcreddb/attrib.h
@@ -1,55 +1,55 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#ifndef __KHIMAIRA_KCDB_ATTRIB_H
-#define __KHIMAIRA_KCDB_ATTRIB_H
-
-/* Attributes */
-
-typedef struct kcdb_attrib_i_t {
- kcdb_attrib attr;
-
- khm_int32 refcount;
-
- struct kcdb_attrib_i_t * next;
- struct kcdb_attrib_i_t * prev;
-} kcdb_attrib_i;
-
-#define KCDB_ATTRIB_HASH_SIZE 31
-
-void kcdb_attrib_init(void);
-void kcdb_attrib_exit(void);
-void kcdb_attrib_add_ref_func(const void * key, void * va);
-void kcdb_attrib_del_ref_func(const void * key, void * va);
-void kcdb_attrib_msg_completion(kmq_message * m);
-khm_int32 kcdb_attrib_next_free_prop_id(khm_int32 * id);
-khm_int32 kcdb_attrib_next_free_id(khm_int32 * id);
-khm_int32 kcdb_attrib_hold(kcdb_attrib_i * ai);
-khm_int32 kcdb_attrib_release(kcdb_attrib_i * ai);
-void kcdb_attrib_post_message(khm_int32 op, kcdb_attrib_i * ai);
-khm_int32 KHMAPI kcdb_attr_sys_cb(khm_handle cred, khm_int32 attr, void * buf, khm_size * pcb_buf);
-
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __KHIMAIRA_KCDB_ATTRIB_H
+#define __KHIMAIRA_KCDB_ATTRIB_H
+
+/* Attributes */
+
+typedef struct kcdb_attrib_i_t {
+ kcdb_attrib attr;
+
+ khm_int32 refcount;
+
+ struct kcdb_attrib_i_t * next;
+ struct kcdb_attrib_i_t * prev;
+} kcdb_attrib_i;
+
+#define KCDB_ATTRIB_HASH_SIZE 31
+
+void kcdb_attrib_init(void);
+void kcdb_attrib_exit(void);
+void kcdb_attrib_add_ref_func(const void * key, void * va);
+void kcdb_attrib_del_ref_func(const void * key, void * va);
+void kcdb_attrib_msg_completion(kmq_message * m);
+khm_int32 kcdb_attrib_next_free_prop_id(khm_int32 * id);
+khm_int32 kcdb_attrib_next_free_id(khm_int32 * id);
+khm_int32 kcdb_attrib_hold(kcdb_attrib_i * ai);
+khm_int32 kcdb_attrib_release(kcdb_attrib_i * ai);
+void kcdb_attrib_post_message(khm_int32 op, kcdb_attrib_i * ai);
+khm_int32 KHMAPI kcdb_attr_sys_cb(khm_handle cred, khm_int32 attr, void * buf, khm_size * pcb_buf);
+
+#endif
diff --git a/src/windows/identity/kcreddb/buf.c b/src/windows/identity/kcreddb/buf.c
index 6272924e5c..521baeb976 100644
--- a/src/windows/identity/kcreddb/buf.c
+++ b/src/windows/identity/kcreddb/buf.c
@@ -1,391 +1,391 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<kcreddbinternal.h>
-#include<assert.h>
-
-void kcdb_buf_new(kcdb_buf * buf, khm_size n_fields)
-{
- buf->buffer = PMALLOC(KCDB_BUF_CBBUF_INITIAL);
- buf->cb_buffer = KCDB_BUF_CBBUF_INITIAL;
- buf->cb_used = 0;
-
- if(n_fields == KCDB_BUF_DEFAULT)
- n_fields = KCDB_BUF_FIELDS_INITIAL;
-
- assert(n_fields < KCDB_BUF_MAX_SLOTS);
-
- buf->n_fields = n_fields;
- buf->nc_fields = UBOUNDSS(n_fields, KCDB_BUF_FIELDS_INITIAL, KCDB_BUF_FIELDS_GROWTH);
- buf->fields = PMALLOC(sizeof(buf->fields[0]) * buf->n_fields);
- ZeroMemory(buf->fields, sizeof(buf->fields[0]) * buf->n_fields);
-}
-
-void kcdb_buf_delete(kcdb_buf * buf)
-{
- buf->cb_buffer = 0;
- buf->cb_used = 0;
- if(buf->buffer)
- PFREE(buf->buffer);
- buf->buffer = NULL;
-
- buf->n_fields = 0;
- buf->nc_fields = 0;
- if(buf->fields)
- PFREE(buf->fields);
- buf->fields = NULL;
-}
-
-static void kcdb_buf_assert_size(kcdb_buf * buf, khm_size cbsize)
-{
- khm_size new_size;
- void * new_buf;
-
- /* should be less than or equal to the max signed 32 bit int */
- assert(cbsize <= KHM_INT32_MAX);
- if(cbsize <= buf->cb_buffer)
- return;
-
- new_size = UBOUNDSS(cbsize, KCDB_BUF_CBBUF_INITIAL, KCDB_BUF_CBBUF_GROWTH);
-
- assert(new_size > buf->cb_buffer && new_size > 0);
-
- new_buf = PMALLOC(new_size);
- assert(new_buf != NULL);
-
- memcpy(new_buf, buf->buffer, buf->cb_used);
- PFREE(buf->buffer);
- buf->buffer = new_buf;
-}
-
-void kcdb_buf_alloc(kcdb_buf * buf, khm_size slot, khm_ui_2 id, khm_size cbsize)
-{
- khm_size cbnew;
- khm_ssize cbdelta;
- khm_size cbold;
- kcdb_buf_field * f;
-
- cbnew = UBOUND32(cbsize);
-
- assert(slot <= KCDB_BUF_APPEND);
-
- if(slot == KCDB_BUF_APPEND) {
- slot = kcdb_buf_slot_by_id(buf, id);
- if(slot == KCDB_BUF_INVALID_SLOT)
- slot = buf->n_fields;
- }
-
- assert(slot < KCDB_BUF_MAX_SLOTS);
-
- if((slot + 1) > buf->nc_fields) {
- kcdb_buf_field * nf;
- khm_size ns;
-
- ns = UBOUNDSS((slot + 1), KCDB_BUF_FIELDS_INITIAL, KCDB_BUF_FIELDS_GROWTH);
-
- nf = PMALLOC(sizeof(buf->fields[0]) * ns);
- memcpy(nf, buf->fields, sizeof(buf->fields[0]) * buf->n_fields);
-
- if(ns > buf->n_fields)
- memset(&(nf[buf->n_fields]), 0, sizeof(buf->fields[0]) * (ns - buf->n_fields));
-
- PFREE(buf->fields);
- buf->fields = nf;
- buf->nc_fields = ns;
- }
-
- if((slot + 1) > buf->n_fields)
- buf->n_fields = slot + 1;
-
- f = &(buf->fields[slot]);
-
- if(f->flags & KCDB_CREDF_FLAG_ALLOCD) {
- /* there's already an allocation. we have to resize it to
- accomodate the new size */
- cbold = UBOUND32(f->cbsize);
- /* demote before substraction */
- cbdelta = ((khm_ssize) cbnew) - (khm_ssize) cbold;
-
- if(cbnew > cbold) {
- kcdb_buf_assert_size(buf, buf->cb_used + cbdelta);
- }
-
- if(buf->cb_used > f->offset + cbold) {
- khm_size i;
-
- memmove(
- ((BYTE *) buf->buffer) + (f->offset + cbnew),
- ((BYTE *) buf->buffer) + (f->offset + cbold),
- buf->cb_used - (f->offset + cbold));
-
- for(i=0; i < (int) buf->n_fields; i++) {
- if(i != slot &&
- (buf->fields[i].flags & KCDB_CREDF_FLAG_ALLOCD) &&
- buf->fields[i].offset > f->offset)
- {
- buf->fields[i].offset =
- (khm_ui_4)(((khm_ssize) buf->fields[i].offset) + cbdelta);
- }
- }
- }
-
- /* demote integer before adding signed quantity */
- buf->cb_used = (khm_size)(((khm_ssize) buf->cb_used) + cbdelta);
-
- f->cbsize = (khm_ui_4) cbsize;
-
- } else {
- kcdb_buf_assert_size(buf, buf->cb_used + cbnew);
- f->offset = (khm_ui_4) buf->cb_used;
- f->cbsize = (khm_ui_4) cbsize;
- buf->cb_used += cbnew;
- }
-
- if(cbsize == 0) {
- f->flags &= ~KCDB_CREDF_FLAG_ALLOCD;
- f->flags &= ~KCDB_CREDF_FLAG_DATA;
- f->id = KCDB_BUFF_ID_INVALID;
- } else {
- f->flags |= KCDB_CREDF_FLAG_ALLOCD;
- f->id = id;
- }
-}
-
-void kcdb_buf_dup(kcdb_buf * dest, const kcdb_buf * src)
-{
- khm_size cb_buf;
- khm_size nc_fields;
-
- cb_buf = UBOUNDSS(src->cb_used, KCDB_BUF_CBBUF_INITIAL, KCDB_BUF_CBBUF_GROWTH);
-#if 0
- /* replaced by UBOUNDSS() above */
- (src->cb_used <= kcdb_cred_initial_size)? kcdb_cred_initial_size:
- kcdb_cred_initial_size +
- (((src->cb_used - (kcdb_cred_initial_size + 1)) / kcdb_cred_growth_factor + 1) * kcdb_cred_growth_factor);
-#endif
-
- kcdb_buf_delete(dest);
-
- dest->cb_buffer = cb_buf;
- dest->cb_used = src->cb_used;
- dest->buffer = PMALLOC(cb_buf);
- memcpy(dest->buffer, src->buffer, src->cb_used);
-
- nc_fields = UBOUNDSS(src->n_fields, KCDB_BUF_FIELDS_INITIAL, KCDB_BUF_FIELDS_GROWTH);
- dest->nc_fields = nc_fields;
- dest->n_fields = src->n_fields;
- dest->fields = PMALLOC(nc_fields * sizeof(dest->fields[0]));
- memcpy(dest->fields, src->fields, src->n_fields * sizeof(dest->fields[0]));
- if(dest->n_fields < dest->nc_fields)
- memset(&(dest->fields[dest->n_fields]), 0, (src->nc_fields - src->n_fields) * sizeof(dest->fields[0]));
-}
-
-void kcdb_buf_set_value(kcdb_buf * buf, khm_size slot, khm_ui_2 id, void * src, khm_size cb_src)
-{
- void * dest;
- kcdb_buf_alloc(buf, slot, id, cb_src);
- if(slot == KCDB_BUF_APPEND) {
- slot = kcdb_buf_slot_by_id(buf, id);
- if(slot == KCDB_BUF_INVALID_SLOT) {
-#ifdef DEBUG
- assert(FALSE);
-#else
- return;
-#endif
- }
- }
- if(kcdb_buf_exist(buf, slot)) {
- dest = kcdb_buf_get(buf, slot);
- memcpy(dest, src, cb_src);
-
- buf->fields[slot].flags |= KCDB_CREDF_FLAG_DATA;
- }
-}
-
-int kcdb_buf_exist(kcdb_buf * buf, khm_size slot)
-{
- if(slot >= buf->n_fields)
- return 0;
- return (buf->fields[slot].flags & KCDB_CREDF_FLAG_ALLOCD);
-}
-
-int kcdb_buf_val_exist(kcdb_buf * buf, khm_size slot)
-{
- if(slot >= buf->n_fields)
- return 0;
- return (buf->fields[slot].flags & KCDB_CREDF_FLAG_DATA);
-}
-
-void * kcdb_buf_get(kcdb_buf * buf, khm_size slot)
-{
- if(slot >= buf->n_fields ||
- !(buf->fields[slot].flags & KCDB_CREDF_FLAG_ALLOCD))
- return NULL;
- return (((BYTE *) buf->buffer) + buf->fields[slot].offset);
-}
-
-khm_size kcdb_buf_size(kcdb_buf * buf, khm_size slot)
-{
- if(slot >= buf->n_fields ||
- !(buf->fields[slot].flags & KCDB_CREDF_FLAG_ALLOCD))
- return 0;
- return (buf->fields[slot].cbsize);
-}
-
-void kcdb_buf_set_value_flag(kcdb_buf * buf, khm_size slot)
-{
- if(slot >= buf->n_fields ||
- !(buf->fields[slot].flags & KCDB_CREDF_FLAG_ALLOCD))
- return;
-
- (buf->fields[slot].flags |= KCDB_CREDF_FLAG_DATA);
-}
-
-khm_size kcdb_buf_slot_by_id(kcdb_buf * buf, khm_ui_2 id)
-{
- int i;
-
- for(i=0; i < (int) buf->n_fields; i++) {
- if(buf->fields[i].id == id)
- break;
- }
-
- if(i < (int) buf->n_fields)
- return i;
- else
- return KCDB_BUF_INVALID_SLOT;
-}
-
-/* API for accessing generic buffers */
-
-KHMEXP khm_int32 KHMAPI kcdb_buf_get_attr(
- khm_handle record,
- khm_int32 attr_id,
- khm_int32 * attr_type,
- void * buffer,
- khm_size * pcb_buf)
-{
- if(kcdb_cred_is_active_cred(record))
- return kcdb_cred_get_attr(record, attr_id, attr_type, buffer, pcb_buf);
- else if(kcdb_is_active_identity(record))
- return kcdb_identity_get_attr(record, attr_id, attr_type, buffer, pcb_buf);
- else
- return KHM_ERROR_INVALID_PARAM;
-}
-
-KHMEXP khm_int32 KHMAPI kcdb_buf_get_attrib(
- khm_handle record,
- const wchar_t * attr_name,
- khm_int32 * attr_type,
- void * buffer,
- khm_size * pcb_buf)
-{
- if(kcdb_cred_is_active_cred(record))
- return kcdb_cred_get_attrib(record, attr_name, attr_type, buffer, pcb_buf);
- else if(kcdb_is_active_identity(record))
- return kcdb_identity_get_attrib(record, attr_name, attr_type, buffer, pcb_buf);
- else
- return KHM_ERROR_INVALID_PARAM;
-}
-
-KHMEXP khm_int32 KHMAPI kcdb_buf_get_attr_string(
- khm_handle record,
- khm_int32 attr_id,
- wchar_t * buffer,
- khm_size * pcbbuf,
- khm_int32 flags)
-{
- if(kcdb_cred_is_active_cred(record))
- return kcdb_cred_get_attr_string(record, attr_id, buffer, pcbbuf, flags);
- else if(kcdb_is_active_identity(record))
- return kcdb_identity_get_attr_string(record, attr_id, buffer, pcbbuf, flags);
- else
- return KHM_ERROR_INVALID_PARAM;
-}
-
-KHMEXP khm_int32 KHMAPI kcdb_buf_get_attrib_string(
- khm_handle record,
- const wchar_t * attr_name,
- wchar_t * buffer,
- khm_size * pcbbuf,
- khm_int32 flags)
-{
- if(kcdb_cred_is_active_cred(record))
- return kcdb_cred_get_attrib_string(record, attr_name, buffer, pcbbuf, flags);
- else if(kcdb_is_active_identity(record))
- return kcdb_identity_get_attrib_string(record, attr_name, buffer, pcbbuf, flags);
- else
- return KHM_ERROR_INVALID_PARAM;
-}
-
-KHMEXP khm_int32 KHMAPI kcdb_buf_set_attr(
- khm_handle record,
- khm_int32 attr_id,
- void * buffer,
- khm_size cbbuf)
-{
- if(kcdb_cred_is_active_cred(record))
- return kcdb_cred_set_attr(record, attr_id, buffer, cbbuf);
- else if(kcdb_is_active_identity(record))
- return kcdb_identity_set_attr(record, attr_id, buffer, cbbuf);
- else
- return KHM_ERROR_INVALID_PARAM;
-}
-
-KHMEXP khm_int32 KHMAPI kcdb_buf_set_attrib(
- khm_handle record,
- const wchar_t * attr_name,
- void * buffer,
- khm_size cbbuf)
-{
- if(kcdb_cred_is_active_cred(record))
- return kcdb_cred_set_attrib(record, attr_name, buffer, cbbuf);
- else if(kcdb_is_active_identity(record))
- return kcdb_identity_set_attrib(record, attr_name, buffer, cbbuf);
- else
- return KHM_ERROR_INVALID_PARAM;
-}
-
-KHMEXP khm_int32 KHMAPI kcdb_buf_hold(khm_handle record)
-{
- if(kcdb_cred_is_active_cred(record))
- return kcdb_cred_hold(record);
- else if(kcdb_is_active_identity(record))
- return kcdb_identity_hold(record);
- else
- return KHM_ERROR_INVALID_PARAM;
-}
-
-KHMEXP khm_int32 KHMAPI kcdb_buf_release(khm_handle record)
-{
- if(kcdb_cred_is_active_cred(record))
- return kcdb_cred_release(record);
- else if(kcdb_is_active_identity(record))
- return kcdb_identity_release(record);
- else
- return KHM_ERROR_INVALID_PARAM;
-}
-
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<kcreddbinternal.h>
+#include<assert.h>
+
+void kcdb_buf_new(kcdb_buf * buf, khm_size n_fields)
+{
+ buf->buffer = PMALLOC(KCDB_BUF_CBBUF_INITIAL);
+ buf->cb_buffer = KCDB_BUF_CBBUF_INITIAL;
+ buf->cb_used = 0;
+
+ if(n_fields == KCDB_BUF_DEFAULT)
+ n_fields = KCDB_BUF_FIELDS_INITIAL;
+
+ assert(n_fields < KCDB_BUF_MAX_SLOTS);
+
+ buf->n_fields = n_fields;
+ buf->nc_fields = UBOUNDSS(n_fields, KCDB_BUF_FIELDS_INITIAL, KCDB_BUF_FIELDS_GROWTH);
+ buf->fields = PMALLOC(sizeof(buf->fields[0]) * buf->n_fields);
+ ZeroMemory(buf->fields, sizeof(buf->fields[0]) * buf->n_fields);
+}
+
+void kcdb_buf_delete(kcdb_buf * buf)
+{
+ buf->cb_buffer = 0;
+ buf->cb_used = 0;
+ if(buf->buffer)
+ PFREE(buf->buffer);
+ buf->buffer = NULL;
+
+ buf->n_fields = 0;
+ buf->nc_fields = 0;
+ if(buf->fields)
+ PFREE(buf->fields);
+ buf->fields = NULL;
+}
+
+static void kcdb_buf_assert_size(kcdb_buf * buf, khm_size cbsize)
+{
+ khm_size new_size;
+ void * new_buf;
+
+ /* should be less than or equal to the max signed 32 bit int */
+ assert(cbsize <= KHM_INT32_MAX);
+ if(cbsize <= buf->cb_buffer)
+ return;
+
+ new_size = UBOUNDSS(cbsize, KCDB_BUF_CBBUF_INITIAL, KCDB_BUF_CBBUF_GROWTH);
+
+ assert(new_size > buf->cb_buffer && new_size > 0);
+
+ new_buf = PMALLOC(new_size);
+ assert(new_buf != NULL);
+
+ memcpy(new_buf, buf->buffer, buf->cb_used);
+ PFREE(buf->buffer);
+ buf->buffer = new_buf;
+}
+
+void kcdb_buf_alloc(kcdb_buf * buf, khm_size slot, khm_ui_2 id, khm_size cbsize)
+{
+ khm_size cbnew;
+ khm_ssize cbdelta;
+ khm_size cbold;
+ kcdb_buf_field * f;
+
+ cbnew = UBOUND32(cbsize);
+
+ assert(slot <= KCDB_BUF_APPEND);
+
+ if(slot == KCDB_BUF_APPEND) {
+ slot = kcdb_buf_slot_by_id(buf, id);
+ if(slot == KCDB_BUF_INVALID_SLOT)
+ slot = buf->n_fields;
+ }
+
+ assert(slot < KCDB_BUF_MAX_SLOTS);
+
+ if((slot + 1) > buf->nc_fields) {
+ kcdb_buf_field * nf;
+ khm_size ns;
+
+ ns = UBOUNDSS((slot + 1), KCDB_BUF_FIELDS_INITIAL, KCDB_BUF_FIELDS_GROWTH);
+
+ nf = PMALLOC(sizeof(buf->fields[0]) * ns);
+ memcpy(nf, buf->fields, sizeof(buf->fields[0]) * buf->n_fields);
+
+ if(ns > buf->n_fields)
+ memset(&(nf[buf->n_fields]), 0, sizeof(buf->fields[0]) * (ns - buf->n_fields));
+
+ PFREE(buf->fields);
+ buf->fields = nf;
+ buf->nc_fields = ns;
+ }
+
+ if((slot + 1) > buf->n_fields)
+ buf->n_fields = slot + 1;
+
+ f = &(buf->fields[slot]);
+
+ if(f->flags & KCDB_CREDF_FLAG_ALLOCD) {
+ /* there's already an allocation. we have to resize it to
+ accomodate the new size */
+ cbold = UBOUND32(f->cbsize);
+ /* demote before substraction */
+ cbdelta = ((khm_ssize) cbnew) - (khm_ssize) cbold;
+
+ if(cbnew > cbold) {
+ kcdb_buf_assert_size(buf, buf->cb_used + cbdelta);
+ }
+
+ if(buf->cb_used > f->offset + cbold) {
+ khm_size i;
+
+ memmove(
+ ((BYTE *) buf->buffer) + (f->offset + cbnew),
+ ((BYTE *) buf->buffer) + (f->offset + cbold),
+ buf->cb_used - (f->offset + cbold));
+
+ for(i=0; i < (int) buf->n_fields; i++) {
+ if(i != slot &&
+ (buf->fields[i].flags & KCDB_CREDF_FLAG_ALLOCD) &&
+ buf->fields[i].offset > f->offset)
+ {
+ buf->fields[i].offset =
+ (khm_ui_4)(((khm_ssize) buf->fields[i].offset) + cbdelta);
+ }
+ }
+ }
+
+ /* demote integer before adding signed quantity */
+ buf->cb_used = (khm_size)(((khm_ssize) buf->cb_used) + cbdelta);
+
+ f->cbsize = (khm_ui_4) cbsize;
+
+ } else {
+ kcdb_buf_assert_size(buf, buf->cb_used + cbnew);
+ f->offset = (khm_ui_4) buf->cb_used;
+ f->cbsize = (khm_ui_4) cbsize;
+ buf->cb_used += cbnew;
+ }
+
+ if(cbsize == 0) {
+ f->flags &= ~KCDB_CREDF_FLAG_ALLOCD;
+ f->flags &= ~KCDB_CREDF_FLAG_DATA;
+ f->id = KCDB_BUFF_ID_INVALID;
+ } else {
+ f->flags |= KCDB_CREDF_FLAG_ALLOCD;
+ f->id = id;
+ }
+}
+
+void kcdb_buf_dup(kcdb_buf * dest, const kcdb_buf * src)
+{
+ khm_size cb_buf;
+ khm_size nc_fields;
+
+ cb_buf = UBOUNDSS(src->cb_used, KCDB_BUF_CBBUF_INITIAL, KCDB_BUF_CBBUF_GROWTH);
+#if 0
+ /* replaced by UBOUNDSS() above */
+ (src->cb_used <= kcdb_cred_initial_size)? kcdb_cred_initial_size:
+ kcdb_cred_initial_size +
+ (((src->cb_used - (kcdb_cred_initial_size + 1)) / kcdb_cred_growth_factor + 1) * kcdb_cred_growth_factor);
+#endif
+
+ kcdb_buf_delete(dest);
+
+ dest->cb_buffer = cb_buf;
+ dest->cb_used = src->cb_used;
+ dest->buffer = PMALLOC(cb_buf);
+ memcpy(dest->buffer, src->buffer, src->cb_used);
+
+ nc_fields = UBOUNDSS(src->n_fields, KCDB_BUF_FIELDS_INITIAL, KCDB_BUF_FIELDS_GROWTH);
+ dest->nc_fields = nc_fields;
+ dest->n_fields = src->n_fields;
+ dest->fields = PMALLOC(nc_fields * sizeof(dest->fields[0]));
+ memcpy(dest->fields, src->fields, src->n_fields * sizeof(dest->fields[0]));
+ if(dest->n_fields < dest->nc_fields)
+ memset(&(dest->fields[dest->n_fields]), 0, (src->nc_fields - src->n_fields) * sizeof(dest->fields[0]));
+}
+
+void kcdb_buf_set_value(kcdb_buf * buf, khm_size slot, khm_ui_2 id, void * src, khm_size cb_src)
+{
+ void * dest;
+ kcdb_buf_alloc(buf, slot, id, cb_src);
+ if(slot == KCDB_BUF_APPEND) {
+ slot = kcdb_buf_slot_by_id(buf, id);
+ if(slot == KCDB_BUF_INVALID_SLOT) {
+#ifdef DEBUG
+ assert(FALSE);
+#else
+ return;
+#endif
+ }
+ }
+ if(kcdb_buf_exist(buf, slot)) {
+ dest = kcdb_buf_get(buf, slot);
+ memcpy(dest, src, cb_src);
+
+ buf->fields[slot].flags |= KCDB_CREDF_FLAG_DATA;
+ }
+}
+
+int kcdb_buf_exist(kcdb_buf * buf, khm_size slot)
+{
+ if(slot >= buf->n_fields)
+ return 0;
+ return (buf->fields[slot].flags & KCDB_CREDF_FLAG_ALLOCD);
+}
+
+int kcdb_buf_val_exist(kcdb_buf * buf, khm_size slot)
+{
+ if(slot >= buf->n_fields)
+ return 0;
+ return (buf->fields[slot].flags & KCDB_CREDF_FLAG_DATA);
+}
+
+void * kcdb_buf_get(kcdb_buf * buf, khm_size slot)
+{
+ if(slot >= buf->n_fields ||
+ !(buf->fields[slot].flags & KCDB_CREDF_FLAG_ALLOCD))
+ return NULL;
+ return (((BYTE *) buf->buffer) + buf->fields[slot].offset);
+}
+
+khm_size kcdb_buf_size(kcdb_buf * buf, khm_size slot)
+{
+ if(slot >= buf->n_fields ||
+ !(buf->fields[slot].flags & KCDB_CREDF_FLAG_ALLOCD))
+ return 0;
+ return (buf->fields[slot].cbsize);
+}
+
+void kcdb_buf_set_value_flag(kcdb_buf * buf, khm_size slot)
+{
+ if(slot >= buf->n_fields ||
+ !(buf->fields[slot].flags & KCDB_CREDF_FLAG_ALLOCD))
+ return;
+
+ (buf->fields[slot].flags |= KCDB_CREDF_FLAG_DATA);
+}
+
+khm_size kcdb_buf_slot_by_id(kcdb_buf * buf, khm_ui_2 id)
+{
+ int i;
+
+ for(i=0; i < (int) buf->n_fields; i++) {
+ if(buf->fields[i].id == id)
+ break;
+ }
+
+ if(i < (int) buf->n_fields)
+ return i;
+ else
+ return KCDB_BUF_INVALID_SLOT;
+}
+
+/* API for accessing generic buffers */
+
+KHMEXP khm_int32 KHMAPI kcdb_buf_get_attr(
+ khm_handle record,
+ khm_int32 attr_id,
+ khm_int32 * attr_type,
+ void * buffer,
+ khm_size * pcb_buf)
+{
+ if(kcdb_cred_is_active_cred(record))
+ return kcdb_cred_get_attr(record, attr_id, attr_type, buffer, pcb_buf);
+ else if(kcdb_is_active_identity(record))
+ return kcdb_identity_get_attr(record, attr_id, attr_type, buffer, pcb_buf);
+ else
+ return KHM_ERROR_INVALID_PARAM;
+}
+
+KHMEXP khm_int32 KHMAPI kcdb_buf_get_attrib(
+ khm_handle record,
+ const wchar_t * attr_name,
+ khm_int32 * attr_type,
+ void * buffer,
+ khm_size * pcb_buf)
+{
+ if(kcdb_cred_is_active_cred(record))
+ return kcdb_cred_get_attrib(record, attr_name, attr_type, buffer, pcb_buf);
+ else if(kcdb_is_active_identity(record))
+ return kcdb_identity_get_attrib(record, attr_name, attr_type, buffer, pcb_buf);
+ else
+ return KHM_ERROR_INVALID_PARAM;
+}
+
+KHMEXP khm_int32 KHMAPI kcdb_buf_get_attr_string(
+ khm_handle record,
+ khm_int32 attr_id,
+ wchar_t * buffer,
+ khm_size * pcbbuf,
+ khm_int32 flags)
+{
+ if(kcdb_cred_is_active_cred(record))
+ return kcdb_cred_get_attr_string(record, attr_id, buffer, pcbbuf, flags);
+ else if(kcdb_is_active_identity(record))
+ return kcdb_identity_get_attr_string(record, attr_id, buffer, pcbbuf, flags);
+ else
+ return KHM_ERROR_INVALID_PARAM;
+}
+
+KHMEXP khm_int32 KHMAPI kcdb_buf_get_attrib_string(
+ khm_handle record,
+ const wchar_t * attr_name,
+ wchar_t * buffer,
+ khm_size * pcbbuf,
+ khm_int32 flags)
+{
+ if(kcdb_cred_is_active_cred(record))
+ return kcdb_cred_get_attrib_string(record, attr_name, buffer, pcbbuf, flags);
+ else if(kcdb_is_active_identity(record))
+ return kcdb_identity_get_attrib_string(record, attr_name, buffer, pcbbuf, flags);
+ else
+ return KHM_ERROR_INVALID_PARAM;
+}
+
+KHMEXP khm_int32 KHMAPI kcdb_buf_set_attr(
+ khm_handle record,
+ khm_int32 attr_id,
+ void * buffer,
+ khm_size cbbuf)
+{
+ if(kcdb_cred_is_active_cred(record))
+ return kcdb_cred_set_attr(record, attr_id, buffer, cbbuf);
+ else if(kcdb_is_active_identity(record))
+ return kcdb_identity_set_attr(record, attr_id, buffer, cbbuf);
+ else
+ return KHM_ERROR_INVALID_PARAM;
+}
+
+KHMEXP khm_int32 KHMAPI kcdb_buf_set_attrib(
+ khm_handle record,
+ const wchar_t * attr_name,
+ void * buffer,
+ khm_size cbbuf)
+{
+ if(kcdb_cred_is_active_cred(record))
+ return kcdb_cred_set_attrib(record, attr_name, buffer, cbbuf);
+ else if(kcdb_is_active_identity(record))
+ return kcdb_identity_set_attrib(record, attr_name, buffer, cbbuf);
+ else
+ return KHM_ERROR_INVALID_PARAM;
+}
+
+KHMEXP khm_int32 KHMAPI kcdb_buf_hold(khm_handle record)
+{
+ if(kcdb_cred_is_active_cred(record))
+ return kcdb_cred_hold(record);
+ else if(kcdb_is_active_identity(record))
+ return kcdb_identity_hold(record);
+ else
+ return KHM_ERROR_INVALID_PARAM;
+}
+
+KHMEXP khm_int32 KHMAPI kcdb_buf_release(khm_handle record)
+{
+ if(kcdb_cred_is_active_cred(record))
+ return kcdb_cred_release(record);
+ else if(kcdb_is_active_identity(record))
+ return kcdb_identity_release(record);
+ else
+ return KHM_ERROR_INVALID_PARAM;
+}
+
diff --git a/src/windows/identity/kcreddb/buf.h b/src/windows/identity/kcreddb/buf.h
index f47bd0a2a0..723253036c 100644
--- a/src/windows/identity/kcreddb/buf.h
+++ b/src/windows/identity/kcreddb/buf.h
@@ -1,78 +1,78 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#ifndef __KHIMAIRA_KCDB_BUF_H
-#define __KHIMAIRA_KCDB_BUF_H
-
-typedef struct tag_kcdb_buf_field {
- khm_ui_2 id;
- khm_ui_2 flags;
- khm_ui_4 offset;
- khm_ui_4 cbsize;
-} kcdb_buf_field;
-
-#define KCDB_CREDF_FLAG_EMPTY 0
-#define KCDB_CREDF_FLAG_DATA 1
-#define KCDB_CREDF_FLAG_INLINE 2
-#define KCDB_CREDF_FLAG_ALLOCD 4
-
-#define KCDB_BUFF_ID_INVALID 0xffff
-
-typedef struct tag_kcdb_buf {
- void * buffer;
- khm_size cb_buffer;
- khm_size cb_used;
-
- kcdb_buf_field * fields;
- khm_size n_fields;
- khm_size nc_fields;
-} kcdb_buf;
-
-#define KCDB_BUF_CBBUF_INITIAL 4096
-#define KCDB_BUF_CBBUF_GROWTH 4096
-#define KCDB_BUF_FIELDS_INITIAL 16
-#define KCDB_BUF_FIELDS_GROWTH 16
-
-#define KCDB_BUF_APPEND 0x8000
-
-#define KCDB_BUF_INVALID_SLOT 0xf0000000
-#define KCDB_BUF_DEFAULT 0xe0000000
-
-#define KCDB_BUF_MAX_SLOTS 0x00004000
-
-void kcdb_buf_new(kcdb_buf * buf, khm_size n_slots);
-void kcdb_buf_delete(kcdb_buf * buf);
-void kcdb_buf_alloc(kcdb_buf * buf, khm_size slot, khm_ui_2 id, khm_size cbsize);
-void kcdb_buf_dup(kcdb_buf * dest, const kcdb_buf * src);
-void kcdb_buf_set_value(kcdb_buf * buf, khm_size slot, khm_ui_2 id, void * src, khm_size cb_src);
-int kcdb_buf_exist(kcdb_buf * buf, khm_size slot);
-int kcdb_buf_val_exist(kcdb_buf * buf, khm_size slot);
-void * kcdb_buf_get(kcdb_buf * buf, khm_size slot);
-khm_size kcdb_buf_size(kcdb_buf * buf, khm_size slot);
-void kcdb_buf_set_value_flag(kcdb_buf * buf, khm_size slot);
-khm_size kcdb_buf_slot_by_id(kcdb_buf * buf, khm_ui_2 id);
-
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __KHIMAIRA_KCDB_BUF_H
+#define __KHIMAIRA_KCDB_BUF_H
+
+typedef struct tag_kcdb_buf_field {
+ khm_ui_2 id;
+ khm_ui_2 flags;
+ khm_ui_4 offset;
+ khm_ui_4 cbsize;
+} kcdb_buf_field;
+
+#define KCDB_CREDF_FLAG_EMPTY 0
+#define KCDB_CREDF_FLAG_DATA 1
+#define KCDB_CREDF_FLAG_INLINE 2
+#define KCDB_CREDF_FLAG_ALLOCD 4
+
+#define KCDB_BUFF_ID_INVALID 0xffff
+
+typedef struct tag_kcdb_buf {
+ void * buffer;
+ khm_size cb_buffer;
+ khm_size cb_used;
+
+ kcdb_buf_field * fields;
+ khm_size n_fields;
+ khm_size nc_fields;
+} kcdb_buf;
+
+#define KCDB_BUF_CBBUF_INITIAL 4096
+#define KCDB_BUF_CBBUF_GROWTH 4096
+#define KCDB_BUF_FIELDS_INITIAL 16
+#define KCDB_BUF_FIELDS_GROWTH 16
+
+#define KCDB_BUF_APPEND 0x8000
+
+#define KCDB_BUF_INVALID_SLOT 0xf0000000
+#define KCDB_BUF_DEFAULT 0xe0000000
+
+#define KCDB_BUF_MAX_SLOTS 0x00004000
+
+void kcdb_buf_new(kcdb_buf * buf, khm_size n_slots);
+void kcdb_buf_delete(kcdb_buf * buf);
+void kcdb_buf_alloc(kcdb_buf * buf, khm_size slot, khm_ui_2 id, khm_size cbsize);
+void kcdb_buf_dup(kcdb_buf * dest, const kcdb_buf * src);
+void kcdb_buf_set_value(kcdb_buf * buf, khm_size slot, khm_ui_2 id, void * src, khm_size cb_src);
+int kcdb_buf_exist(kcdb_buf * buf, khm_size slot);
+int kcdb_buf_val_exist(kcdb_buf * buf, khm_size slot);
+void * kcdb_buf_get(kcdb_buf * buf, khm_size slot);
+khm_size kcdb_buf_size(kcdb_buf * buf, khm_size slot);
+void kcdb_buf_set_value_flag(kcdb_buf * buf, khm_size slot);
+khm_size kcdb_buf_slot_by_id(kcdb_buf * buf, khm_ui_2 id);
+
+#endif
diff --git a/src/windows/identity/kcreddb/credential.c b/src/windows/identity/kcreddb/credential.c
index 12b8c5fc53..c8a423a2a8 100644
--- a/src/windows/identity/kcreddb/credential.c
+++ b/src/windows/identity/kcreddb/credential.c
@@ -1,1092 +1,1092 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<kcreddbinternal.h>
-#include<assert.h>
-
-/* cs_creds protects the *collection* of credentials, while l_creds
- protects the *contents* of individual credentials. */
-CRITICAL_SECTION cs_creds;
-kcdb_cred * kcdb_creds = NULL;
-
-/* a read lock must be obtained when querying any existing credential.
- a write lock must be obtained when modifying any existing credential.
- */
-RWLOCK l_creds;
-
-/* serial number */
-khm_ui_8 kcdb_cred_id = 0;
-
-void kcdb_cred_init(void)
-{
- InitializeCriticalSection(&cs_creds);
- InitializeRwLock(&l_creds);
- kcdb_cred_id = 0;
-}
-
-void kcdb_cred_exit(void)
-{
- /*TODO: Free the credentials */
- DeleteCriticalSection(&cs_creds);
- DeleteRwLock(&l_creds);
-}
-
-/*! \internal
-
- can be called by kcdb_cred_dup with a write lock on l_creds and in other
- places with a read lock on l_creds. New credentials must be creatable while
- holding either lock. */
-KHMEXP khm_int32 KHMAPI
-kcdb_cred_create(const wchar_t * name,
- khm_handle identity,
- khm_int32 cred_type,
- khm_handle * result)
-{
- kcdb_cred * cred;
- size_t cb_name;
-
- if(!name || !result ||
- FAILED(StringCbLength(name, KCDB_CRED_MAXCB_NAME, &cb_name)) ||
- KHM_FAILED(kcdb_credtype_get_info(cred_type, NULL)) ||
- KHM_FAILED(kcdb_identity_hold(identity))) {
- return KHM_ERROR_INVALID_PARAM;
- }
-
- cb_name += sizeof(wchar_t);
-
- cred = PMALLOC(sizeof(kcdb_cred));
- ZeroMemory(cred, sizeof(kcdb_cred));
-
- cred->magic = KCDB_CRED_MAGIC;
- cred->identity = identity;
- cred->name = PMALLOC(cb_name);
- StringCbCopy(cred->name, cb_name, name);
- cred->type = cred_type;
-
- cred->refcount = 1; /* initially held */
-
- LINIT(cred);
-
- kcdb_buf_new(&cred->buf, KCDB_ATTR_MAX_ID + 1);
-
- /* Not obtaining a write lock on l_cred on purpose.
- Well, because no one should be referencing this credential until
- this function returns. */
- EnterCriticalSection(&cs_creds);
- cred->id = kcdb_cred_id++;
- LPUSH(&kcdb_creds, cred);
- LeaveCriticalSection(&cs_creds);
-
- *result = cred;
-
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP khm_int32 KHMAPI kcdb_cred_update(khm_handle vdest,
- khm_handle vsrc)
-{
- khm_int32 rv = KHM_ERROR_EQUIVALENT;
- kcdb_cred * src;
- kcdb_cred * dest;
- kcdb_type * t;
- kcdb_attrib * a;
- void * srcbuf;
- void * destbuf;
- khm_size cbsrcbuf;
- khm_size cbdestbuf;
-
- int i;
-
- kcdb_cred_lock_write();
-
- if(!kcdb_cred_is_active_cred(vsrc) ||
- !kcdb_cred_is_active_cred(vdest))
- goto _exit;
-
- src = (kcdb_cred *) vsrc;
- dest = (kcdb_cred *) vdest;
-
- for(i=0;i<KCDB_ATTR_MAX_ID;i++) {
- if(kcdb_cred_val_exist(src, i)) {
- /*NOTE: the logic here has to reflect the logic in
- kcdb_cred_set_attr() */
- if(KHM_FAILED(kcdb_attrib_get_info(i, &a)))
- continue;
-
- if((a->flags & KCDB_ATTR_FLAG_COMPUTED) ||
- KHM_FAILED(kcdb_type_get_info(a->type, &t))) {
- kcdb_attrib_release_info(a);
- continue;
- }
-
- srcbuf = kcdb_cred_buf_get(src,i);
- cbsrcbuf = kcdb_cred_buf_size(src, i);
-
- if(kcdb_cred_val_exist(dest, i)) {
- destbuf = kcdb_cred_buf_get(dest, i);
- cbdestbuf = kcdb_cred_buf_size(dest, i);
-
- if(!t->comp(srcbuf, cbsrcbuf, destbuf, cbdestbuf))
- goto _skip_copy;
- }
-
- kcdb_buf_set_value(&dest->buf, i, i, srcbuf, cbsrcbuf);
- rv = KHM_ERROR_SUCCESS;
-
- _skip_copy:
- kcdb_attrib_release_info(a);
- kcdb_type_release_info(t);
- } else {
- if (KHM_FAILED(kcdb_attrib_get_info(i, &a)))
- continue;
-
- if (!(a->flags & KCDB_ATTR_FLAG_COMPUTED) &&
- (a->flags & KCDB_ATTR_FLAG_TRANSIENT) &&
- kcdb_cred_val_exist(dest, i)) {
- kcdb_buf_set_value(&dest->buf, i, i, NULL, 0);
-
- rv = KHM_ERROR_SUCCESS;
- }
-
- kcdb_attrib_release_info(a);
- }
- }
-
- if (dest->flags != src->flags) {
- khm_int32 old_flags;
-
- old_flags = dest->flags;
-
- dest->flags = (src->flags & ~KCDB_CRED_FLAGMASK_ADDITIVE) |
- ((src->flags | dest->flags) & KCDB_CRED_FLAGMASK_ADDITIVE);
-
- if (dest->flags != old_flags)
- rv = KHM_ERROR_SUCCESS;
- }
-
- _exit:
- kcdb_cred_unlock_write();
- return rv;
-}
-
-KHMEXP khm_int32 KHMAPI kcdb_cred_dup(
- khm_handle vcred,
- khm_handle * pnewcred)
-{
- khm_int32 code = KHM_ERROR_SUCCESS;
- kcdb_cred * cred;
- kcdb_cred * newcred;
- khm_handle vnewcred;
-
- if(!pnewcred)
- return KHM_ERROR_INVALID_PARAM;
-
- *pnewcred = NULL;
-
- kcdb_cred_lock_write();
-
- if(!kcdb_cred_is_active_cred(vcred)) {
- code = KHM_ERROR_INVALID_PARAM;
- goto _exit;
- }
-
- cred = (kcdb_cred *) vcred;
-
- if(KHM_FAILED(kcdb_cred_create(cred->name,
- cred->identity,
- cred->type,
- &vnewcred)))
- {
- code = KHM_ERROR_UNKNOWN;
- goto _exit;
- }
-
- newcred = (kcdb_cred *) vnewcred;
-
- newcred->flags = cred->flags;
-
- kcdb_buf_dup(&newcred->buf, &cred->buf);
-
- /* newcred is already held from the call to kcdb_cred_create */
- *pnewcred = (khm_handle) newcred;
-
-_exit:
- kcdb_cred_unlock_write();
- return code;
-}
-
-KHMEXP khm_int32 KHMAPI kcdb_cred_get_serial(
- khm_handle vcred,
- khm_ui_8 * pserial)
-{
- kcdb_cred * c;
-
- if(!pserial)
- return KHM_ERROR_INVALID_PARAM;
-
- kcdb_cred_lock_read();
-
- if(!kcdb_cred_is_active_cred(vcred)) {
- kcdb_cred_unlock_read();
- return KHM_ERROR_INVALID_PARAM;
- }
-
- c = (kcdb_cred *) vcred;
-
- *pserial = c->id;
-
- kcdb_cred_unlock_read();
-
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP khm_int32 KHMAPI kcdb_cred_set_identity(
- khm_handle vcred,
- khm_handle id)
-{
- kcdb_cred * c;
-
- if(!kcdb_is_identity(id))
- return KHM_ERROR_INVALID_PARAM;
-
- kcdb_cred_lock_write();
- if(!kcdb_cred_is_active_cred(vcred)) {
- kcdb_cred_unlock_write();
- return KHM_ERROR_INVALID_PARAM;
- }
-
- c = (kcdb_cred *) vcred;
-
- if(c->identity) {
- kcdb_identity_release((khm_handle) c->identity);
- }
- kcdb_identity_hold(id);
- c->identity = (kcdb_identity *) id;
-
- kcdb_cred_unlock_write();
-
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP khm_int32 KHMAPI kcdb_cred_get_type(
- khm_handle vcred,
- khm_int32 * type)
-{
- kcdb_cred * c;
-
- if(!type)
- return KHM_ERROR_INVALID_PARAM;
-
- kcdb_cred_lock_read();
-
- if(!kcdb_cred_is_active_cred(vcred)) {
- kcdb_cred_unlock_read();
- return KHM_ERROR_INVALID_PARAM;
- }
-
- c = (kcdb_cred *) vcred;
-
- *type = c->type;
-
- kcdb_cred_unlock_read();
-
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP khm_int32 KHMAPI kcdb_cred_set_attrib(
- khm_handle cred,
- const wchar_t * name,
- void * buffer,
- khm_size cbbuf)
-{
- khm_int32 attr_id = -1;
-
- if(KHM_FAILED(kcdb_attrib_get_id(name, &attr_id)))
- return KHM_ERROR_INVALID_PARAM;
-
- return kcdb_cred_set_attr(
- cred,
- attr_id,
- buffer,
- cbbuf);
-}
-
-KHMEXP khm_int32 KHMAPI kcdb_cred_set_attr(
- khm_handle vcred,
- khm_int32 attr_id,
- void * buffer,
- khm_size cbbuf)
-{
- kcdb_cred * cred;
- kcdb_type * type = NULL;
- kcdb_attrib * attrib = NULL;
- khm_size cbdest;
- khm_int32 code = KHM_ERROR_SUCCESS;
-
- if(attr_id < 0 || attr_id > KCDB_ATTR_MAX_ID)
- return KHM_ERROR_INVALID_PARAM;
-
- kcdb_cred_lock_write();
-
- if(!kcdb_cred_is_active_cred(vcred)) {
- kcdb_cred_unlock_write();
- return KHM_ERROR_INVALID_PARAM;
- }
-
- cred = (kcdb_cred *) vcred;
-
- if(KHM_FAILED(kcdb_attrib_get_info(attr_id, &attrib))) {
- kcdb_cred_unlock_write();
- return KHM_ERROR_INVALID_PARAM;
- }
-
- if(attrib->flags & KCDB_ATTR_FLAG_COMPUTED)
- {
- kcdb_cred_unlock_write();
- kcdb_attrib_release_info(attrib);
- return KHM_ERROR_INVALID_OPERATION;
- }
-
- if (buffer == 0) {
- /* we are removing the value */
- kcdb_buf_alloc(&cred->buf, attr_id, attr_id, 0);
- code = KHM_ERROR_SUCCESS;
- goto _exit;
- }
-
- if(KHM_FAILED(kcdb_type_get_info(attrib->type, &type))) {
- kcdb_cred_unlock_write();
- kcdb_attrib_release_info(attrib);
- return KHM_ERROR_INVALID_PARAM;
- }
-
- if(!(type->isValid(buffer,cbbuf))) {
- code = KHM_ERROR_TYPE_MISMATCH;
- goto _exit;
- }
-
- if((type->dup(buffer, cbbuf, NULL, &cbdest)) != KHM_ERROR_TOO_LONG) {
- code = KHM_ERROR_INVALID_PARAM;
- goto _exit;
- }
-
- kcdb_buf_alloc(&cred->buf, attr_id, attr_id, cbdest);
- if(!kcdb_cred_buf_exist(cred, attr_id)) {
- code = KHM_ERROR_NO_RESOURCES;
- goto _exit;
- }
-
- if(KHM_FAILED(code =
- type->dup(buffer, cbbuf, kcdb_cred_buf_get(cred,attr_id), &cbdest)))
- {
- kcdb_buf_alloc(&cred->buf, attr_id, attr_id, 0);
- goto _exit;
- }
-
- kcdb_buf_set_value_flag(&cred->buf, attr_id);
-
-_exit:
- kcdb_cred_unlock_write();
-
- if(attrib)
- kcdb_attrib_release_info(attrib);
- if(type)
- kcdb_type_release_info(type);
-
- return code;
-}
-
-KHMEXP khm_int32 KHMAPI kcdb_cred_get_attrib(
- khm_handle cred,
- const wchar_t * name,
- khm_int32 * attr_type,
- void * buffer,
- khm_size * cbbuf)
-{
- khm_int32 attr_id = -1;
-
- if(KHM_FAILED(kcdb_attrib_get_id(name, &attr_id)))
- return KHM_ERROR_NOT_FOUND;
-
- return kcdb_cred_get_attr(
- cred,
- attr_id,
- attr_type,
- buffer,
- cbbuf);
-}
-
-KHMEXP khm_int32 KHMAPI kcdb_cred_get_attrib_string(
- khm_handle cred,
- const wchar_t * name,
- wchar_t * buffer,
- khm_size * cbbuf,
- khm_int32 flags)
-{
- khm_int32 attr_id = -1;
-
- if(KHM_FAILED(kcdb_attrib_get_id(name, &attr_id)))
- return KHM_ERROR_NOT_FOUND;
-
- return kcdb_cred_get_attr_string(
- cred,
- attr_id,
- buffer,
- cbbuf,
- flags);
-}
-
-KHMEXP khm_int32 KHMAPI
-kcdb_cred_get_attr(khm_handle vcred,
- khm_int32 attr_id,
- khm_int32 * attr_type,
- void * buffer,
- khm_size * pcbbuf)
-{
- khm_int32 code = KHM_ERROR_SUCCESS;
- kcdb_cred * cred = NULL;
- kcdb_attrib * attrib = NULL;
- kcdb_type * type = NULL;
-
- if(attr_id < 0 || attr_id > KCDB_ATTR_MAX_ID)
- return KHM_ERROR_INVALID_PARAM;
-
- if(KHM_FAILED(kcdb_attrib_get_info(attr_id, &attrib))) {
- return KHM_ERROR_INVALID_PARAM;
- }
-
- if(KHM_FAILED(kcdb_type_get_info(attrib->type, &type))) {
- kcdb_attrib_release_info(attrib);
- return KHM_ERROR_UNKNOWN;
- }
-
- if(attr_type)
- *attr_type = attrib->type;
-
- kcdb_cred_lock_read();
- if(!kcdb_cred_is_active_cred(vcred)) {
- code = KHM_ERROR_INVALID_PARAM;
- goto _exit;
- }
-
- cred = (kcdb_cred *) vcred;
-
- if(!buffer && !pcbbuf) {
- /* in this case the caller is only trying to determine if the
- field contains data. We assume that computed fields are
- always non-null. */
- code = (kcdb_cred_val_exist(cred, attr_id) ||
- (attrib->flags & KCDB_ATTR_FLAG_COMPUTED))?KHM_ERROR_SUCCESS:KHM_ERROR_NOT_FOUND;
- goto _exit;
- }
-
- if(attrib->flags & KCDB_ATTR_FLAG_COMPUTED) {
- code = attrib->compute_cb(
- vcred,
- attr_id,
- buffer,
- pcbbuf);
- } else if (kcdb_cred_val_exist(cred, attr_id)) {
- code = type->dup(
- kcdb_cred_buf_get(cred, attr_id),
- kcdb_cred_buf_size(cred, attr_id),
- buffer,
- pcbbuf);
- } else {
- code = KHM_ERROR_NOT_FOUND;
- }
-
-_exit:
- kcdb_cred_unlock_read();
- if(type)
- kcdb_type_release_info(type);
- if(attrib)
- kcdb_attrib_release_info(attrib);
-
- return code;
-}
-
-KHMEXP khm_int32 KHMAPI kcdb_cred_get_attr_string(
- khm_handle vcred,
- khm_int32 attr_id,
- wchar_t * buffer,
- khm_size * pcbbuf,
- khm_int32 flags)
-{
- khm_int32 code = KHM_ERROR_SUCCESS;
- kcdb_cred * cred = NULL;
- kcdb_attrib * attrib = NULL;
- kcdb_type * type = NULL;
-
- if(attr_id < 0 || attr_id > KCDB_ATTR_MAX_ID)
- return KHM_ERROR_INVALID_PARAM;
-
- if(KHM_FAILED(kcdb_attrib_get_info(attr_id, &attrib))) {
- code = KHM_ERROR_INVALID_PARAM;
- goto _exit_nolock;
- }
-
- if(KHM_FAILED(kcdb_type_get_info(attrib->type, &type))) {
- code = KHM_ERROR_UNKNOWN;
- goto _exit_nolock;
- }
-
- kcdb_cred_lock_read();
- if(!kcdb_cred_is_active_cred(vcred)) {
- code = KHM_ERROR_INVALID_PARAM;
- goto _exit;
- }
-
- cred = (kcdb_cred *) vcred;
-
- if(!buffer && !pcbbuf) {
- /* in this case the caller is only trying to determine if the
- field contains data. We assume that computed fields are
- always non-null. */
- code = (kcdb_cred_val_exist(cred, attr_id) ||
- (attrib->flags & KCDB_ATTR_FLAG_COMPUTED))?KHM_ERROR_SUCCESS:KHM_ERROR_NOT_FOUND;
- goto _exit;
- }
-
- if(attrib->flags & KCDB_ATTR_FLAG_COMPUTED) {
- void * buf;
- khm_size cbbuf;
-
- code = attrib->compute_cb(vcred,
- attr_id,
- NULL,
- &cbbuf);
- if(code == KHM_ERROR_TOO_LONG) {
- wchar_t vbuf[KCDB_MAXCCH_NAME];
-
- if (cbbuf < sizeof(vbuf))
- buf = vbuf;
- else
- buf = PMALLOC(cbbuf);
-
- code = attrib->compute_cb(vcred,
- attr_id,
- buf,
- &cbbuf);
- if(KHM_SUCCEEDED(code)) {
- code = type->toString(buf,
- cbbuf,
- buffer,
- pcbbuf,
- flags);
- }
-
- if (buf != vbuf)
- PFREE(buf);
- }
- } else {
- if(kcdb_cred_buf_exist(cred, attr_id)) {
- code = type->toString(
- kcdb_cred_buf_get(cred, attr_id),
- kcdb_cred_buf_size(cred, attr_id),
- buffer,
- pcbbuf,
- flags);
- } else
- code = KHM_ERROR_NOT_FOUND;
- }
-
- _exit:
- kcdb_cred_unlock_read();
- _exit_nolock:
- if(type)
- kcdb_type_release_info(type);
- if(attrib)
- kcdb_attrib_release_info(attrib);
-
- return code;
-}
-
-
-KHMEXP khm_int32 KHMAPI kcdb_cred_get_name(
- khm_handle vcred,
- wchar_t * buffer,
- khm_size * cbbuf)
-{
- khm_int32 code = KHM_ERROR_SUCCESS;
- kcdb_cred * cred = NULL;
- size_t cbsize;
-
- if(!cbbuf)
- return KHM_ERROR_INVALID_PARAM;
-
- kcdb_cred_lock_read();
-
- if(!kcdb_cred_is_active_cred(vcred)) {
- code = KHM_ERROR_INVALID_PARAM;
- goto _exit;
- }
-
- cred = (kcdb_cred *) vcred;
-
- if(FAILED(StringCbLength(cred->name, KCDB_CRED_MAXCB_NAME, &cbsize))) {
- code = KHM_ERROR_UNKNOWN;
- goto _exit;
- }
-
- cbsize += sizeof(wchar_t);
-
- if(!buffer || *cbbuf < cbsize) {
- *cbbuf = cbsize;
- code = KHM_ERROR_TOO_LONG;
- goto _exit;
- }
-
- StringCbCopy(buffer, *cbbuf, cred->name);
-
- *cbbuf = cbsize;
-
-_exit:
-
- kcdb_cred_unlock_read();
- return code;
-}
-
-KHMEXP khm_int32 KHMAPI kcdb_cred_get_identity(
- khm_handle vcred,
- khm_handle * identity)
-{
- khm_int32 code = KHM_ERROR_SUCCESS;
- kcdb_cred * cred;
-
- if(!identity)
- return KHM_ERROR_INVALID_PARAM;
-
- kcdb_cred_lock_read();
-
- if(!kcdb_cred_is_active_cred(vcred)) {
- code = KHM_ERROR_INVALID_PARAM;
- goto _exit;
- }
-
- cred = (kcdb_cred *) vcred;
-
- kcdb_identity_hold((khm_handle) cred->identity);
-
- *identity = cred->identity;
-
-_exit:
- kcdb_cred_unlock_read();
- return code;
-}
-
-KHMEXP khm_int32 KHMAPI kcdb_cred_hold(khm_handle vcred)
-{
- khm_int32 code = KHM_ERROR_SUCCESS;
- kcdb_cred * cred;
-
- kcdb_cred_lock_write();
-
- if(!kcdb_cred_is_cred(vcred)) {
- code = KHM_ERROR_INVALID_PARAM;
- goto _exit;
- }
-
- cred = (kcdb_cred *) vcred;
-
- cred->refcount++;
-
-_exit:
- kcdb_cred_unlock_write();
- return code;
-}
-
-KHMEXP khm_int32 KHMAPI kcdb_cred_release(khm_handle vcred)
-{
- khm_int32 code = KHM_ERROR_SUCCESS;
- kcdb_cred * cred;
-
- kcdb_cred_lock_write();
-
- if(!kcdb_cred_is_cred(vcred)) {
- code = KHM_ERROR_INVALID_PARAM;
- goto _exit;
- }
-
- cred = (kcdb_cred *) vcred;
-
- cred->refcount--;
-
-_exit:
- kcdb_cred_unlock_write();
-
- kcdb_cred_check_and_delete(vcred);
-
- return code;
-}
-
-void kcdb_cred_check_and_delete(khm_handle vcred)
-{
- kcdb_cred * cred;
-
- kcdb_cred_lock_read();
- if(!kcdb_cred_is_cred(vcred)) {
- goto _exit;
- }
-
- cred = (kcdb_cred *) vcred;
-
- if(cred->refcount)
- goto _exit;
-
- kcdb_cred_unlock_read();
- kcdb_cred_lock_write();
- if(!kcdb_cred_is_cred(vcred)) {
- /* did we lose the race? */
- goto _exit2;
- }
-
- cred->magic = 0; /* no longer a cred */
- kcdb_identity_release(cred->identity);
-
- EnterCriticalSection(&cs_creds);
- LDELETE(&kcdb_creds, cred);
- LeaveCriticalSection(&cs_creds);
-
- kcdb_buf_delete(&cred->buf);
- PFREE(cred->name);
- PFREE(cred);
-
- /*TODO: notifications */
-
-_exit2:
- kcdb_cred_unlock_write();
- return;
-
-_exit:
- kcdb_cred_unlock_read();
-}
-
-KHMEXP khm_int32 KHMAPI kcdb_cred_delete(khm_handle vcred)
-{
- khm_int32 code = KHM_ERROR_SUCCESS;
- kcdb_cred * cred;
-
- kcdb_cred_lock_write();
-
- if(!kcdb_cred_is_active_cred(vcred)) {
- code = KHM_ERROR_INVALID_PARAM;
- goto _exit;
- }
-
- cred = (kcdb_cred *) vcred;
-
- cred->flags |= KCDB_CRED_FLAG_DELETED;
-
-_exit:
- kcdb_cred_unlock_write();
-
- kcdb_cred_check_and_delete(vcred);
-
- return code;
-}
-
-KHMEXP khm_int32 KHMAPI
-kcdb_creds_comp_attrib(khm_handle cred1,
- khm_handle cred2,
- const wchar_t * name)
-{
- khm_int32 attr_id;
-
- if(KHM_FAILED(kcdb_attrib_get_id(name, &attr_id)))
- return 0;
-
- return kcdb_creds_comp_attr(cred1, cred2, attr_id);
-}
-
-KHMEXP khm_int32 KHMAPI
-kcdb_creds_comp_attr(khm_handle vcred1,
- khm_handle vcred2,
- khm_int32 attr_id)
-{
- khm_int32 code = 0;
- kcdb_cred * cred1;
- kcdb_cred * cred2;
- kcdb_attrib * attrib = NULL;
- kcdb_type * type = NULL;
-
- if(attr_id < 0 || attr_id > KCDB_ATTR_MAX_ID)
- return 0;
-
- cred1 = (kcdb_cred *) vcred1;
- cred2 = (kcdb_cred *) vcred2;
-
- kcdb_cred_lock_read();
- if(
- !kcdb_cred_is_active_cred(vcred1) ||
- !kcdb_cred_is_active_cred(vcred2))
- goto _exit;
-
- cred1 = (kcdb_cred *) vcred1;
- cred2 = (kcdb_cred *) vcred2;
-
- if(KHM_FAILED(kcdb_attrib_get_info(attr_id, &attrib)))
- goto _exit;
-
- if(!(attrib->flags & KCDB_ATTR_FLAG_COMPUTED)) {
- int nc = 0;
-
- if(!kcdb_cred_val_exist(cred1, attr_id)) {
- code = -1;
- nc = 1;
- }
- if(!kcdb_cred_val_exist(cred2, attr_id)) {
- code += 1;
- nc = 1;
- }
-
- if(nc)
- goto _exit;
- }
-
- if(KHM_FAILED(kcdb_type_get_info(attrib->type, &type)))
- goto _exit;
-
- if(attrib->flags & KCDB_ATTR_FLAG_COMPUTED) {
- khm_octet vbuf[KCDB_MAXCB_NAME * 2];
- void * buf1 = NULL;
- void * buf2 = NULL;
- khm_size cb1;
- khm_size cb2;
-
- code = 0;
-
- if(attrib->compute_cb(vcred1, attr_id,
- NULL, &cb1) != KHM_ERROR_TOO_LONG)
- goto _exit_1;
-
- if(attrib->compute_cb(vcred2, attr_id,
- NULL, &cb2) != KHM_ERROR_TOO_LONG)
- goto _exit_1;
-
- if(cb1) {
- if (cb1 < sizeof(vbuf))
- buf1 = vbuf;
- else
- buf1 = PMALLOC(cb1);
-
- if(KHM_FAILED(attrib->compute_cb(vcred1, attr_id, buf1, &cb1)))
- goto _exit_1;
- }
-
- if(cb2) {
- if (cb1 + cb2 < sizeof(vbuf))
- buf2 = vbuf + cb1;
- else
- buf2 = PMALLOC(cb2);
-
- if(KHM_FAILED(attrib->compute_cb(vcred2, attr_id, buf2, &cb2)))
- goto _exit_1;
- }
-
- code = type->comp(buf1, cb1,
- buf2, cb2);
-_exit_1:
- if(buf1 && (buf1 < (void *)vbuf ||
- buf1 >= (void*)(vbuf + sizeof(vbuf))))
- PFREE(buf1);
- if(buf2 && (buf2 < (void *)vbuf ||
- buf2 >= (void *)(vbuf + sizeof(vbuf))))
- PFREE(buf2);
- } else {
- code = type->comp(
- kcdb_cred_buf_get(cred1, attr_id),
- kcdb_cred_buf_size(cred1, attr_id),
- kcdb_cred_buf_get(cred2, attr_id),
- kcdb_cred_buf_size(cred2, attr_id));
- }
-
-_exit:
- kcdb_cred_unlock_read();
- if(attrib)
- kcdb_attrib_release_info(attrib);
- if(type)
- kcdb_type_release_info(type);
- return code;
-}
-
-KHMEXP khm_int32 KHMAPI
-kcdb_creds_is_equal(khm_handle vcred1,
- khm_handle vcred2)
-{
- khm_int32 code = 0;
- kcdb_cred * cred1;
- kcdb_cred * cred2;
-
- kcdb_cred_lock_read();
- if(!kcdb_cred_is_active_cred(vcred1) ||
- !kcdb_cred_is_active_cred(vcred2)) {
-
- code = FALSE;
- goto _exit;
-
- }
-
- if(vcred1 == vcred2) {
-
- code = TRUE;
- goto _exit;
-
- }
-
- cred1 = vcred1;
- cred2 = vcred2;
-
- if(cred1->identity == cred2->identity &&
- cred1->type == cred2->type &&
- !wcscmp(cred1->name, cred2->name)) {
-
- kcdb_credtype * type;
-
- code = TRUE;
-
- if (KHM_SUCCEEDED(kcdb_credtype_get_info(cred1->type, &type))) {
- if (type->is_equal &&
- (*type->is_equal)(vcred1, vcred2, NULL))
- code = 0;
-
- kcdb_credtype_release_info(type);
- }
- }
-
-_exit:
- kcdb_cred_unlock_read();
- return code;
-}
-
-KHMEXP khm_int32 KHMAPI
-kcdb_cred_get_flags(khm_handle vcred,
- khm_int32 * pflags)
-{
- khm_int32 f;
- khm_int32 rv = KHM_ERROR_SUCCESS;
- kcdb_cred * cred;
- int release_lock = TRUE;
-
- if (pflags == NULL)
- return KHM_ERROR_INVALID_PARAM;
-
- kcdb_cred_lock_read();
- if (!kcdb_cred_is_active_cred(vcred)) {
- *pflags = 0;
- rv = KHM_ERROR_INVALID_PARAM;
- goto _exit;
- }
-
- cred = vcred;
- f = cred->flags;
-
- /* Update flags if necessary */
-
- if (!(f & KCDB_CRED_FLAG_EXPIRED) &&
- kcdb_cred_buf_exist(cred, KCDB_ATTR_EXPIRE)) {
-
- FILETIME ftc;
-
- GetSystemTimeAsFileTime(&ftc);
- if (CompareFileTime(&ftc, ((FILETIME *)
- kcdb_cred_buf_get(cred, KCDB_ATTR_EXPIRE)))
- >= 0)
- f |= KCDB_CRED_FLAG_EXPIRED;
- }
-
-#if 0
- /* Commented out: if the credential has expired, then checking the
- renewable time is not useful */
- if (!(f & KCDB_CRED_FLAG_INVALID)) {
- if (f & KCDB_CRED_FLAG_RENEWABLE) {
- if (kcdb_cred_buf_exist(cred, KCDB_ATTR_RENEW_EXPIRE)) {
- FILETIME ftc;
-
- GetSystemTimeAsFileTime(&ftc);
- if (CompareFileTime(&ftc, ((FILETIME *)
- kcdb_cred_buf_get(cred, KCDB_ATTR_RENEW_EXPIRE))) >= 0)
- f |= KCDB_CRED_FLAG_INVALID;
- }
- } else {
- if (f & KCDB_CRED_FLAG_EXPIRED)
- f |= KCDB_CRED_FLAG_INVALID;
- }
- }
-
- /* Commented out: this is a read operation. We shouldn't attempt
- to lock for writing */
- if (f != cred->flags) {
- kcdb_cred_unlock_read();
- kcdb_cred_lock_write();
- /* Did we lose a race? */
- if (kcdb_cred_is_active_cred(vcred))
- cred->flags = f;
- else {
- rv = KHM_ERROR_INVALID_PARAM;
- f = 0;
- }
- kcdb_cred_unlock_write();
- release_lock = FALSE;
- }
-#endif
-
- *pflags = f;
-
- _exit:
- if (release_lock)
- kcdb_cred_unlock_read();
-
- return rv;
-}
-
-KHMEXP khm_int32 KHMAPI kcdb_cred_set_flags(
- khm_handle vcred,
- khm_int32 flags,
- khm_int32 mask)
-{
- khm_int32 rv = KHM_ERROR_SUCCESS;
- kcdb_cred * cred;
-
- kcdb_cred_lock_write();
- if(!kcdb_cred_is_active_cred(vcred)) {
- rv = KHM_ERROR_INVALID_PARAM;
- goto _exit;
- }
-
- cred = vcred;
-
- flags &= ~(KCDB_CRED_FLAG_DELETED);
- mask &= ~(KCDB_CRED_FLAG_DELETED);
-
- cred->flags =
- (cred->flags & (~mask)) |
- (flags & mask);
-
- _exit:
- kcdb_cred_unlock_write();
- return rv;
-}
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<kcreddbinternal.h>
+#include<assert.h>
+
+/* cs_creds protects the *collection* of credentials, while l_creds
+ protects the *contents* of individual credentials. */
+CRITICAL_SECTION cs_creds;
+kcdb_cred * kcdb_creds = NULL;
+
+/* a read lock must be obtained when querying any existing credential.
+ a write lock must be obtained when modifying any existing credential.
+ */
+RWLOCK l_creds;
+
+/* serial number */
+khm_ui_8 kcdb_cred_id = 0;
+
+void kcdb_cred_init(void)
+{
+ InitializeCriticalSection(&cs_creds);
+ InitializeRwLock(&l_creds);
+ kcdb_cred_id = 0;
+}
+
+void kcdb_cred_exit(void)
+{
+ /*TODO: Free the credentials */
+ DeleteCriticalSection(&cs_creds);
+ DeleteRwLock(&l_creds);
+}
+
+/*! \internal
+
+ can be called by kcdb_cred_dup with a write lock on l_creds and in other
+ places with a read lock on l_creds. New credentials must be creatable while
+ holding either lock. */
+KHMEXP khm_int32 KHMAPI
+kcdb_cred_create(const wchar_t * name,
+ khm_handle identity,
+ khm_int32 cred_type,
+ khm_handle * result)
+{
+ kcdb_cred * cred;
+ size_t cb_name;
+
+ if(!name || !result ||
+ FAILED(StringCbLength(name, KCDB_CRED_MAXCB_NAME, &cb_name)) ||
+ KHM_FAILED(kcdb_credtype_get_info(cred_type, NULL)) ||
+ KHM_FAILED(kcdb_identity_hold(identity))) {
+ return KHM_ERROR_INVALID_PARAM;
+ }
+
+ cb_name += sizeof(wchar_t);
+
+ cred = PMALLOC(sizeof(kcdb_cred));
+ ZeroMemory(cred, sizeof(kcdb_cred));
+
+ cred->magic = KCDB_CRED_MAGIC;
+ cred->identity = identity;
+ cred->name = PMALLOC(cb_name);
+ StringCbCopy(cred->name, cb_name, name);
+ cred->type = cred_type;
+
+ cred->refcount = 1; /* initially held */
+
+ LINIT(cred);
+
+ kcdb_buf_new(&cred->buf, KCDB_ATTR_MAX_ID + 1);
+
+ /* Not obtaining a write lock on l_cred on purpose.
+ Well, because no one should be referencing this credential until
+ this function returns. */
+ EnterCriticalSection(&cs_creds);
+ cred->id = kcdb_cred_id++;
+ LPUSH(&kcdb_creds, cred);
+ LeaveCriticalSection(&cs_creds);
+
+ *result = cred;
+
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP khm_int32 KHMAPI kcdb_cred_update(khm_handle vdest,
+ khm_handle vsrc)
+{
+ khm_int32 rv = KHM_ERROR_EQUIVALENT;
+ kcdb_cred * src;
+ kcdb_cred * dest;
+ kcdb_type * t;
+ kcdb_attrib * a;
+ void * srcbuf;
+ void * destbuf;
+ khm_size cbsrcbuf;
+ khm_size cbdestbuf;
+
+ int i;
+
+ kcdb_cred_lock_write();
+
+ if(!kcdb_cred_is_active_cred(vsrc) ||
+ !kcdb_cred_is_active_cred(vdest))
+ goto _exit;
+
+ src = (kcdb_cred *) vsrc;
+ dest = (kcdb_cred *) vdest;
+
+ for(i=0;i<KCDB_ATTR_MAX_ID;i++) {
+ if(kcdb_cred_val_exist(src, i)) {
+ /*NOTE: the logic here has to reflect the logic in
+ kcdb_cred_set_attr() */
+ if(KHM_FAILED(kcdb_attrib_get_info(i, &a)))
+ continue;
+
+ if((a->flags & KCDB_ATTR_FLAG_COMPUTED) ||
+ KHM_FAILED(kcdb_type_get_info(a->type, &t))) {
+ kcdb_attrib_release_info(a);
+ continue;
+ }
+
+ srcbuf = kcdb_cred_buf_get(src,i);
+ cbsrcbuf = kcdb_cred_buf_size(src, i);
+
+ if(kcdb_cred_val_exist(dest, i)) {
+ destbuf = kcdb_cred_buf_get(dest, i);
+ cbdestbuf = kcdb_cred_buf_size(dest, i);
+
+ if(!t->comp(srcbuf, cbsrcbuf, destbuf, cbdestbuf))
+ goto _skip_copy;
+ }
+
+ kcdb_buf_set_value(&dest->buf, i, i, srcbuf, cbsrcbuf);
+ rv = KHM_ERROR_SUCCESS;
+
+ _skip_copy:
+ kcdb_attrib_release_info(a);
+ kcdb_type_release_info(t);
+ } else {
+ if (KHM_FAILED(kcdb_attrib_get_info(i, &a)))
+ continue;
+
+ if (!(a->flags & KCDB_ATTR_FLAG_COMPUTED) &&
+ (a->flags & KCDB_ATTR_FLAG_TRANSIENT) &&
+ kcdb_cred_val_exist(dest, i)) {
+ kcdb_buf_set_value(&dest->buf, i, i, NULL, 0);
+
+ rv = KHM_ERROR_SUCCESS;
+ }
+
+ kcdb_attrib_release_info(a);
+ }
+ }
+
+ if (dest->flags != src->flags) {
+ khm_int32 old_flags;
+
+ old_flags = dest->flags;
+
+ dest->flags = (src->flags & ~KCDB_CRED_FLAGMASK_ADDITIVE) |
+ ((src->flags | dest->flags) & KCDB_CRED_FLAGMASK_ADDITIVE);
+
+ if (dest->flags != old_flags)
+ rv = KHM_ERROR_SUCCESS;
+ }
+
+ _exit:
+ kcdb_cred_unlock_write();
+ return rv;
+}
+
+KHMEXP khm_int32 KHMAPI kcdb_cred_dup(
+ khm_handle vcred,
+ khm_handle * pnewcred)
+{
+ khm_int32 code = KHM_ERROR_SUCCESS;
+ kcdb_cred * cred;
+ kcdb_cred * newcred;
+ khm_handle vnewcred;
+
+ if(!pnewcred)
+ return KHM_ERROR_INVALID_PARAM;
+
+ *pnewcred = NULL;
+
+ kcdb_cred_lock_write();
+
+ if(!kcdb_cred_is_active_cred(vcred)) {
+ code = KHM_ERROR_INVALID_PARAM;
+ goto _exit;
+ }
+
+ cred = (kcdb_cred *) vcred;
+
+ if(KHM_FAILED(kcdb_cred_create(cred->name,
+ cred->identity,
+ cred->type,
+ &vnewcred)))
+ {
+ code = KHM_ERROR_UNKNOWN;
+ goto _exit;
+ }
+
+ newcred = (kcdb_cred *) vnewcred;
+
+ newcred->flags = cred->flags;
+
+ kcdb_buf_dup(&newcred->buf, &cred->buf);
+
+ /* newcred is already held from the call to kcdb_cred_create */
+ *pnewcred = (khm_handle) newcred;
+
+_exit:
+ kcdb_cred_unlock_write();
+ return code;
+}
+
+KHMEXP khm_int32 KHMAPI kcdb_cred_get_serial(
+ khm_handle vcred,
+ khm_ui_8 * pserial)
+{
+ kcdb_cred * c;
+
+ if(!pserial)
+ return KHM_ERROR_INVALID_PARAM;
+
+ kcdb_cred_lock_read();
+
+ if(!kcdb_cred_is_active_cred(vcred)) {
+ kcdb_cred_unlock_read();
+ return KHM_ERROR_INVALID_PARAM;
+ }
+
+ c = (kcdb_cred *) vcred;
+
+ *pserial = c->id;
+
+ kcdb_cred_unlock_read();
+
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP khm_int32 KHMAPI kcdb_cred_set_identity(
+ khm_handle vcred,
+ khm_handle id)
+{
+ kcdb_cred * c;
+
+ if(!kcdb_is_identity(id))
+ return KHM_ERROR_INVALID_PARAM;
+
+ kcdb_cred_lock_write();
+ if(!kcdb_cred_is_active_cred(vcred)) {
+ kcdb_cred_unlock_write();
+ return KHM_ERROR_INVALID_PARAM;
+ }
+
+ c = (kcdb_cred *) vcred;
+
+ if(c->identity) {
+ kcdb_identity_release((khm_handle) c->identity);
+ }
+ kcdb_identity_hold(id);
+ c->identity = (kcdb_identity *) id;
+
+ kcdb_cred_unlock_write();
+
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP khm_int32 KHMAPI kcdb_cred_get_type(
+ khm_handle vcred,
+ khm_int32 * type)
+{
+ kcdb_cred * c;
+
+ if(!type)
+ return KHM_ERROR_INVALID_PARAM;
+
+ kcdb_cred_lock_read();
+
+ if(!kcdb_cred_is_active_cred(vcred)) {
+ kcdb_cred_unlock_read();
+ return KHM_ERROR_INVALID_PARAM;
+ }
+
+ c = (kcdb_cred *) vcred;
+
+ *type = c->type;
+
+ kcdb_cred_unlock_read();
+
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP khm_int32 KHMAPI kcdb_cred_set_attrib(
+ khm_handle cred,
+ const wchar_t * name,
+ void * buffer,
+ khm_size cbbuf)
+{
+ khm_int32 attr_id = -1;
+
+ if(KHM_FAILED(kcdb_attrib_get_id(name, &attr_id)))
+ return KHM_ERROR_INVALID_PARAM;
+
+ return kcdb_cred_set_attr(
+ cred,
+ attr_id,
+ buffer,
+ cbbuf);
+}
+
+KHMEXP khm_int32 KHMAPI kcdb_cred_set_attr(
+ khm_handle vcred,
+ khm_int32 attr_id,
+ void * buffer,
+ khm_size cbbuf)
+{
+ kcdb_cred * cred;
+ kcdb_type * type = NULL;
+ kcdb_attrib * attrib = NULL;
+ khm_size cbdest;
+ khm_int32 code = KHM_ERROR_SUCCESS;
+
+ if(attr_id < 0 || attr_id > KCDB_ATTR_MAX_ID)
+ return KHM_ERROR_INVALID_PARAM;
+
+ kcdb_cred_lock_write();
+
+ if(!kcdb_cred_is_active_cred(vcred)) {
+ kcdb_cred_unlock_write();
+ return KHM_ERROR_INVALID_PARAM;
+ }
+
+ cred = (kcdb_cred *) vcred;
+
+ if(KHM_FAILED(kcdb_attrib_get_info(attr_id, &attrib))) {
+ kcdb_cred_unlock_write();
+ return KHM_ERROR_INVALID_PARAM;
+ }
+
+ if(attrib->flags & KCDB_ATTR_FLAG_COMPUTED)
+ {
+ kcdb_cred_unlock_write();
+ kcdb_attrib_release_info(attrib);
+ return KHM_ERROR_INVALID_OPERATION;
+ }
+
+ if (buffer == 0) {
+ /* we are removing the value */
+ kcdb_buf_alloc(&cred->buf, attr_id, attr_id, 0);
+ code = KHM_ERROR_SUCCESS;
+ goto _exit;
+ }
+
+ if(KHM_FAILED(kcdb_type_get_info(attrib->type, &type))) {
+ kcdb_cred_unlock_write();
+ kcdb_attrib_release_info(attrib);
+ return KHM_ERROR_INVALID_PARAM;
+ }
+
+ if(!(type->isValid(buffer,cbbuf))) {
+ code = KHM_ERROR_TYPE_MISMATCH;
+ goto _exit;
+ }
+
+ if((type->dup(buffer, cbbuf, NULL, &cbdest)) != KHM_ERROR_TOO_LONG) {
+ code = KHM_ERROR_INVALID_PARAM;
+ goto _exit;
+ }
+
+ kcdb_buf_alloc(&cred->buf, attr_id, attr_id, cbdest);
+ if(!kcdb_cred_buf_exist(cred, attr_id)) {
+ code = KHM_ERROR_NO_RESOURCES;
+ goto _exit;
+ }
+
+ if(KHM_FAILED(code =
+ type->dup(buffer, cbbuf, kcdb_cred_buf_get(cred,attr_id), &cbdest)))
+ {
+ kcdb_buf_alloc(&cred->buf, attr_id, attr_id, 0);
+ goto _exit;
+ }
+
+ kcdb_buf_set_value_flag(&cred->buf, attr_id);
+
+_exit:
+ kcdb_cred_unlock_write();
+
+ if(attrib)
+ kcdb_attrib_release_info(attrib);
+ if(type)
+ kcdb_type_release_info(type);
+
+ return code;
+}
+
+KHMEXP khm_int32 KHMAPI kcdb_cred_get_attrib(
+ khm_handle cred,
+ const wchar_t * name,
+ khm_int32 * attr_type,
+ void * buffer,
+ khm_size * cbbuf)
+{
+ khm_int32 attr_id = -1;
+
+ if(KHM_FAILED(kcdb_attrib_get_id(name, &attr_id)))
+ return KHM_ERROR_NOT_FOUND;
+
+ return kcdb_cred_get_attr(
+ cred,
+ attr_id,
+ attr_type,
+ buffer,
+ cbbuf);
+}
+
+KHMEXP khm_int32 KHMAPI kcdb_cred_get_attrib_string(
+ khm_handle cred,
+ const wchar_t * name,
+ wchar_t * buffer,
+ khm_size * cbbuf,
+ khm_int32 flags)
+{
+ khm_int32 attr_id = -1;
+
+ if(KHM_FAILED(kcdb_attrib_get_id(name, &attr_id)))
+ return KHM_ERROR_NOT_FOUND;
+
+ return kcdb_cred_get_attr_string(
+ cred,
+ attr_id,
+ buffer,
+ cbbuf,
+ flags);
+}
+
+KHMEXP khm_int32 KHMAPI
+kcdb_cred_get_attr(khm_handle vcred,
+ khm_int32 attr_id,
+ khm_int32 * attr_type,
+ void * buffer,
+ khm_size * pcbbuf)
+{
+ khm_int32 code = KHM_ERROR_SUCCESS;
+ kcdb_cred * cred = NULL;
+ kcdb_attrib * attrib = NULL;
+ kcdb_type * type = NULL;
+
+ if(attr_id < 0 || attr_id > KCDB_ATTR_MAX_ID)
+ return KHM_ERROR_INVALID_PARAM;
+
+ if(KHM_FAILED(kcdb_attrib_get_info(attr_id, &attrib))) {
+ return KHM_ERROR_INVALID_PARAM;
+ }
+
+ if(KHM_FAILED(kcdb_type_get_info(attrib->type, &type))) {
+ kcdb_attrib_release_info(attrib);
+ return KHM_ERROR_UNKNOWN;
+ }
+
+ if(attr_type)
+ *attr_type = attrib->type;
+
+ kcdb_cred_lock_read();
+ if(!kcdb_cred_is_active_cred(vcred)) {
+ code = KHM_ERROR_INVALID_PARAM;
+ goto _exit;
+ }
+
+ cred = (kcdb_cred *) vcred;
+
+ if(!buffer && !pcbbuf) {
+ /* in this case the caller is only trying to determine if the
+ field contains data. We assume that computed fields are
+ always non-null. */
+ code = (kcdb_cred_val_exist(cred, attr_id) ||
+ (attrib->flags & KCDB_ATTR_FLAG_COMPUTED))?KHM_ERROR_SUCCESS:KHM_ERROR_NOT_FOUND;
+ goto _exit;
+ }
+
+ if(attrib->flags & KCDB_ATTR_FLAG_COMPUTED) {
+ code = attrib->compute_cb(
+ vcred,
+ attr_id,
+ buffer,
+ pcbbuf);
+ } else if (kcdb_cred_val_exist(cred, attr_id)) {
+ code = type->dup(
+ kcdb_cred_buf_get(cred, attr_id),
+ kcdb_cred_buf_size(cred, attr_id),
+ buffer,
+ pcbbuf);
+ } else {
+ code = KHM_ERROR_NOT_FOUND;
+ }
+
+_exit:
+ kcdb_cred_unlock_read();
+ if(type)
+ kcdb_type_release_info(type);
+ if(attrib)
+ kcdb_attrib_release_info(attrib);
+
+ return code;
+}
+
+KHMEXP khm_int32 KHMAPI kcdb_cred_get_attr_string(
+ khm_handle vcred,
+ khm_int32 attr_id,
+ wchar_t * buffer,
+ khm_size * pcbbuf,
+ khm_int32 flags)
+{
+ khm_int32 code = KHM_ERROR_SUCCESS;
+ kcdb_cred * cred = NULL;
+ kcdb_attrib * attrib = NULL;
+ kcdb_type * type = NULL;
+
+ if(attr_id < 0 || attr_id > KCDB_ATTR_MAX_ID)
+ return KHM_ERROR_INVALID_PARAM;
+
+ if(KHM_FAILED(kcdb_attrib_get_info(attr_id, &attrib))) {
+ code = KHM_ERROR_INVALID_PARAM;
+ goto _exit_nolock;
+ }
+
+ if(KHM_FAILED(kcdb_type_get_info(attrib->type, &type))) {
+ code = KHM_ERROR_UNKNOWN;
+ goto _exit_nolock;
+ }
+
+ kcdb_cred_lock_read();
+ if(!kcdb_cred_is_active_cred(vcred)) {
+ code = KHM_ERROR_INVALID_PARAM;
+ goto _exit;
+ }
+
+ cred = (kcdb_cred *) vcred;
+
+ if(!buffer && !pcbbuf) {
+ /* in this case the caller is only trying to determine if the
+ field contains data. We assume that computed fields are
+ always non-null. */
+ code = (kcdb_cred_val_exist(cred, attr_id) ||
+ (attrib->flags & KCDB_ATTR_FLAG_COMPUTED))?KHM_ERROR_SUCCESS:KHM_ERROR_NOT_FOUND;
+ goto _exit;
+ }
+
+ if(attrib->flags & KCDB_ATTR_FLAG_COMPUTED) {
+ void * buf;
+ khm_size cbbuf;
+
+ code = attrib->compute_cb(vcred,
+ attr_id,
+ NULL,
+ &cbbuf);
+ if(code == KHM_ERROR_TOO_LONG) {
+ wchar_t vbuf[KCDB_MAXCCH_NAME];
+
+ if (cbbuf < sizeof(vbuf))
+ buf = vbuf;
+ else
+ buf = PMALLOC(cbbuf);
+
+ code = attrib->compute_cb(vcred,
+ attr_id,
+ buf,
+ &cbbuf);
+ if(KHM_SUCCEEDED(code)) {
+ code = type->toString(buf,
+ cbbuf,
+ buffer,
+ pcbbuf,
+ flags);
+ }
+
+ if (buf != vbuf)
+ PFREE(buf);
+ }
+ } else {
+ if(kcdb_cred_buf_exist(cred, attr_id)) {
+ code = type->toString(
+ kcdb_cred_buf_get(cred, attr_id),
+ kcdb_cred_buf_size(cred, attr_id),
+ buffer,
+ pcbbuf,
+ flags);
+ } else
+ code = KHM_ERROR_NOT_FOUND;
+ }
+
+ _exit:
+ kcdb_cred_unlock_read();
+ _exit_nolock:
+ if(type)
+ kcdb_type_release_info(type);
+ if(attrib)
+ kcdb_attrib_release_info(attrib);
+
+ return code;
+}
+
+
+KHMEXP khm_int32 KHMAPI kcdb_cred_get_name(
+ khm_handle vcred,
+ wchar_t * buffer,
+ khm_size * cbbuf)
+{
+ khm_int32 code = KHM_ERROR_SUCCESS;
+ kcdb_cred * cred = NULL;
+ size_t cbsize;
+
+ if(!cbbuf)
+ return KHM_ERROR_INVALID_PARAM;
+
+ kcdb_cred_lock_read();
+
+ if(!kcdb_cred_is_active_cred(vcred)) {
+ code = KHM_ERROR_INVALID_PARAM;
+ goto _exit;
+ }
+
+ cred = (kcdb_cred *) vcred;
+
+ if(FAILED(StringCbLength(cred->name, KCDB_CRED_MAXCB_NAME, &cbsize))) {
+ code = KHM_ERROR_UNKNOWN;
+ goto _exit;
+ }
+
+ cbsize += sizeof(wchar_t);
+
+ if(!buffer || *cbbuf < cbsize) {
+ *cbbuf = cbsize;
+ code = KHM_ERROR_TOO_LONG;
+ goto _exit;
+ }
+
+ StringCbCopy(buffer, *cbbuf, cred->name);
+
+ *cbbuf = cbsize;
+
+_exit:
+
+ kcdb_cred_unlock_read();
+ return code;
+}
+
+KHMEXP khm_int32 KHMAPI kcdb_cred_get_identity(
+ khm_handle vcred,
+ khm_handle * identity)
+{
+ khm_int32 code = KHM_ERROR_SUCCESS;
+ kcdb_cred * cred;
+
+ if(!identity)
+ return KHM_ERROR_INVALID_PARAM;
+
+ kcdb_cred_lock_read();
+
+ if(!kcdb_cred_is_active_cred(vcred)) {
+ code = KHM_ERROR_INVALID_PARAM;
+ goto _exit;
+ }
+
+ cred = (kcdb_cred *) vcred;
+
+ kcdb_identity_hold((khm_handle) cred->identity);
+
+ *identity = cred->identity;
+
+_exit:
+ kcdb_cred_unlock_read();
+ return code;
+}
+
+KHMEXP khm_int32 KHMAPI kcdb_cred_hold(khm_handle vcred)
+{
+ khm_int32 code = KHM_ERROR_SUCCESS;
+ kcdb_cred * cred;
+
+ kcdb_cred_lock_write();
+
+ if(!kcdb_cred_is_cred(vcred)) {
+ code = KHM_ERROR_INVALID_PARAM;
+ goto _exit;
+ }
+
+ cred = (kcdb_cred *) vcred;
+
+ cred->refcount++;
+
+_exit:
+ kcdb_cred_unlock_write();
+ return code;
+}
+
+KHMEXP khm_int32 KHMAPI kcdb_cred_release(khm_handle vcred)
+{
+ khm_int32 code = KHM_ERROR_SUCCESS;
+ kcdb_cred * cred;
+
+ kcdb_cred_lock_write();
+
+ if(!kcdb_cred_is_cred(vcred)) {
+ code = KHM_ERROR_INVALID_PARAM;
+ goto _exit;
+ }
+
+ cred = (kcdb_cred *) vcred;
+
+ cred->refcount--;
+
+_exit:
+ kcdb_cred_unlock_write();
+
+ kcdb_cred_check_and_delete(vcred);
+
+ return code;
+}
+
+void kcdb_cred_check_and_delete(khm_handle vcred)
+{
+ kcdb_cred * cred;
+
+ kcdb_cred_lock_read();
+ if(!kcdb_cred_is_cred(vcred)) {
+ goto _exit;
+ }
+
+ cred = (kcdb_cred *) vcred;
+
+ if(cred->refcount)
+ goto _exit;
+
+ kcdb_cred_unlock_read();
+ kcdb_cred_lock_write();
+ if(!kcdb_cred_is_cred(vcred)) {
+ /* did we lose the race? */
+ goto _exit2;
+ }
+
+ cred->magic = 0; /* no longer a cred */
+ kcdb_identity_release(cred->identity);
+
+ EnterCriticalSection(&cs_creds);
+ LDELETE(&kcdb_creds, cred);
+ LeaveCriticalSection(&cs_creds);
+
+ kcdb_buf_delete(&cred->buf);
+ PFREE(cred->name);
+ PFREE(cred);
+
+ /*TODO: notifications */
+
+_exit2:
+ kcdb_cred_unlock_write();
+ return;
+
+_exit:
+ kcdb_cred_unlock_read();
+}
+
+KHMEXP khm_int32 KHMAPI kcdb_cred_delete(khm_handle vcred)
+{
+ khm_int32 code = KHM_ERROR_SUCCESS;
+ kcdb_cred * cred;
+
+ kcdb_cred_lock_write();
+
+ if(!kcdb_cred_is_active_cred(vcred)) {
+ code = KHM_ERROR_INVALID_PARAM;
+ goto _exit;
+ }
+
+ cred = (kcdb_cred *) vcred;
+
+ cred->flags |= KCDB_CRED_FLAG_DELETED;
+
+_exit:
+ kcdb_cred_unlock_write();
+
+ kcdb_cred_check_and_delete(vcred);
+
+ return code;
+}
+
+KHMEXP khm_int32 KHMAPI
+kcdb_creds_comp_attrib(khm_handle cred1,
+ khm_handle cred2,
+ const wchar_t * name)
+{
+ khm_int32 attr_id;
+
+ if(KHM_FAILED(kcdb_attrib_get_id(name, &attr_id)))
+ return 0;
+
+ return kcdb_creds_comp_attr(cred1, cred2, attr_id);
+}
+
+KHMEXP khm_int32 KHMAPI
+kcdb_creds_comp_attr(khm_handle vcred1,
+ khm_handle vcred2,
+ khm_int32 attr_id)
+{
+ khm_int32 code = 0;
+ kcdb_cred * cred1;
+ kcdb_cred * cred2;
+ kcdb_attrib * attrib = NULL;
+ kcdb_type * type = NULL;
+
+ if(attr_id < 0 || attr_id > KCDB_ATTR_MAX_ID)
+ return 0;
+
+ cred1 = (kcdb_cred *) vcred1;
+ cred2 = (kcdb_cred *) vcred2;
+
+ kcdb_cred_lock_read();
+ if(
+ !kcdb_cred_is_active_cred(vcred1) ||
+ !kcdb_cred_is_active_cred(vcred2))
+ goto _exit;
+
+ cred1 = (kcdb_cred *) vcred1;
+ cred2 = (kcdb_cred *) vcred2;
+
+ if(KHM_FAILED(kcdb_attrib_get_info(attr_id, &attrib)))
+ goto _exit;
+
+ if(!(attrib->flags & KCDB_ATTR_FLAG_COMPUTED)) {
+ int nc = 0;
+
+ if(!kcdb_cred_val_exist(cred1, attr_id)) {
+ code = -1;
+ nc = 1;
+ }
+ if(!kcdb_cred_val_exist(cred2, attr_id)) {
+ code += 1;
+ nc = 1;
+ }
+
+ if(nc)
+ goto _exit;
+ }
+
+ if(KHM_FAILED(kcdb_type_get_info(attrib->type, &type)))
+ goto _exit;
+
+ if(attrib->flags & KCDB_ATTR_FLAG_COMPUTED) {
+ khm_octet vbuf[KCDB_MAXCB_NAME * 2];
+ void * buf1 = NULL;
+ void * buf2 = NULL;
+ khm_size cb1;
+ khm_size cb2;
+
+ code = 0;
+
+ if(attrib->compute_cb(vcred1, attr_id,
+ NULL, &cb1) != KHM_ERROR_TOO_LONG)
+ goto _exit_1;
+
+ if(attrib->compute_cb(vcred2, attr_id,
+ NULL, &cb2) != KHM_ERROR_TOO_LONG)
+ goto _exit_1;
+
+ if(cb1) {
+ if (cb1 < sizeof(vbuf))
+ buf1 = vbuf;
+ else
+ buf1 = PMALLOC(cb1);
+
+ if(KHM_FAILED(attrib->compute_cb(vcred1, attr_id, buf1, &cb1)))
+ goto _exit_1;
+ }
+
+ if(cb2) {
+ if (cb1 + cb2 < sizeof(vbuf))
+ buf2 = vbuf + cb1;
+ else
+ buf2 = PMALLOC(cb2);
+
+ if(KHM_FAILED(attrib->compute_cb(vcred2, attr_id, buf2, &cb2)))
+ goto _exit_1;
+ }
+
+ code = type->comp(buf1, cb1,
+ buf2, cb2);
+_exit_1:
+ if(buf1 && (buf1 < (void *)vbuf ||
+ buf1 >= (void*)(vbuf + sizeof(vbuf))))
+ PFREE(buf1);
+ if(buf2 && (buf2 < (void *)vbuf ||
+ buf2 >= (void *)(vbuf + sizeof(vbuf))))
+ PFREE(buf2);
+ } else {
+ code = type->comp(
+ kcdb_cred_buf_get(cred1, attr_id),
+ kcdb_cred_buf_size(cred1, attr_id),
+ kcdb_cred_buf_get(cred2, attr_id),
+ kcdb_cred_buf_size(cred2, attr_id));
+ }
+
+_exit:
+ kcdb_cred_unlock_read();
+ if(attrib)
+ kcdb_attrib_release_info(attrib);
+ if(type)
+ kcdb_type_release_info(type);
+ return code;
+}
+
+KHMEXP khm_int32 KHMAPI
+kcdb_creds_is_equal(khm_handle vcred1,
+ khm_handle vcred2)
+{
+ khm_int32 code = 0;
+ kcdb_cred * cred1;
+ kcdb_cred * cred2;
+
+ kcdb_cred_lock_read();
+ if(!kcdb_cred_is_active_cred(vcred1) ||
+ !kcdb_cred_is_active_cred(vcred2)) {
+
+ code = FALSE;
+ goto _exit;
+
+ }
+
+ if(vcred1 == vcred2) {
+
+ code = TRUE;
+ goto _exit;
+
+ }
+
+ cred1 = vcred1;
+ cred2 = vcred2;
+
+ if(cred1->identity == cred2->identity &&
+ cred1->type == cred2->type &&
+ !wcscmp(cred1->name, cred2->name)) {
+
+ kcdb_credtype * type;
+
+ code = TRUE;
+
+ if (KHM_SUCCEEDED(kcdb_credtype_get_info(cred1->type, &type))) {
+ if (type->is_equal &&
+ (*type->is_equal)(vcred1, vcred2, NULL))
+ code = 0;
+
+ kcdb_credtype_release_info(type);
+ }
+ }
+
+_exit:
+ kcdb_cred_unlock_read();
+ return code;
+}
+
+KHMEXP khm_int32 KHMAPI
+kcdb_cred_get_flags(khm_handle vcred,
+ khm_int32 * pflags)
+{
+ khm_int32 f;
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+ kcdb_cred * cred;
+ int release_lock = TRUE;
+
+ if (pflags == NULL)
+ return KHM_ERROR_INVALID_PARAM;
+
+ kcdb_cred_lock_read();
+ if (!kcdb_cred_is_active_cred(vcred)) {
+ *pflags = 0;
+ rv = KHM_ERROR_INVALID_PARAM;
+ goto _exit;
+ }
+
+ cred = vcred;
+ f = cred->flags;
+
+ /* Update flags if necessary */
+
+ if (!(f & KCDB_CRED_FLAG_EXPIRED) &&
+ kcdb_cred_buf_exist(cred, KCDB_ATTR_EXPIRE)) {
+
+ FILETIME ftc;
+
+ GetSystemTimeAsFileTime(&ftc);
+ if (CompareFileTime(&ftc, ((FILETIME *)
+ kcdb_cred_buf_get(cred, KCDB_ATTR_EXPIRE)))
+ >= 0)
+ f |= KCDB_CRED_FLAG_EXPIRED;
+ }
+
+#if 0
+ /* Commented out: if the credential has expired, then checking the
+ renewable time is not useful */
+ if (!(f & KCDB_CRED_FLAG_INVALID)) {
+ if (f & KCDB_CRED_FLAG_RENEWABLE) {
+ if (kcdb_cred_buf_exist(cred, KCDB_ATTR_RENEW_EXPIRE)) {
+ FILETIME ftc;
+
+ GetSystemTimeAsFileTime(&ftc);
+ if (CompareFileTime(&ftc, ((FILETIME *)
+ kcdb_cred_buf_get(cred, KCDB_ATTR_RENEW_EXPIRE))) >= 0)
+ f |= KCDB_CRED_FLAG_INVALID;
+ }
+ } else {
+ if (f & KCDB_CRED_FLAG_EXPIRED)
+ f |= KCDB_CRED_FLAG_INVALID;
+ }
+ }
+
+ /* Commented out: this is a read operation. We shouldn't attempt
+ to lock for writing */
+ if (f != cred->flags) {
+ kcdb_cred_unlock_read();
+ kcdb_cred_lock_write();
+ /* Did we lose a race? */
+ if (kcdb_cred_is_active_cred(vcred))
+ cred->flags = f;
+ else {
+ rv = KHM_ERROR_INVALID_PARAM;
+ f = 0;
+ }
+ kcdb_cred_unlock_write();
+ release_lock = FALSE;
+ }
+#endif
+
+ *pflags = f;
+
+ _exit:
+ if (release_lock)
+ kcdb_cred_unlock_read();
+
+ return rv;
+}
+
+KHMEXP khm_int32 KHMAPI kcdb_cred_set_flags(
+ khm_handle vcred,
+ khm_int32 flags,
+ khm_int32 mask)
+{
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+ kcdb_cred * cred;
+
+ kcdb_cred_lock_write();
+ if(!kcdb_cred_is_active_cred(vcred)) {
+ rv = KHM_ERROR_INVALID_PARAM;
+ goto _exit;
+ }
+
+ cred = vcred;
+
+ flags &= ~(KCDB_CRED_FLAG_DELETED);
+ mask &= ~(KCDB_CRED_FLAG_DELETED);
+
+ cred->flags =
+ (cred->flags & (~mask)) |
+ (flags & mask);
+
+ _exit:
+ kcdb_cred_unlock_write();
+ return rv;
+}
diff --git a/src/windows/identity/kcreddb/credential.h b/src/windows/identity/kcreddb/credential.h
index 9cb70ab4d2..49b3953c9f 100644
--- a/src/windows/identity/kcreddb/credential.h
+++ b/src/windows/identity/kcreddb/credential.h
@@ -1,71 +1,71 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#ifndef __KHIMAIRA_KCDB_CREDENTIAL_H
-#define __KHIMAIRA_KCDB_CREDENTIAL_H
-
-/* Credentials */
-
-typedef struct kcdb_cred_t {
- khm_int32 magic;
- khm_ui_8 id; /* serial number */
- kcdb_identity * identity;
- khm_int32 type;
- wchar_t * name;
-
- khm_int32 flags;
- khm_int32 refcount;
-
- kcdb_buf buf;
-
- LDCL(struct kcdb_cred_t);
-} kcdb_cred;
-
-#define KCDB_CRED_MAGIC 0x38fb84a6
-
-extern CRITICAL_SECTION cs_creds;
-extern kcdb_cred * kcdb_creds;
-extern RWLOCK l_creds;
-extern khm_ui_8 kcdb_cred_id;
-
-#define kcdb_cred_val_exist(c,a) kcdb_buf_val_exist(&(c)->buf, a)
-#define kcdb_cred_buf_exist(c,a) kcdb_buf_exist(&(c)->buf, a)
-#define kcdb_cred_buf_get(c,a) kcdb_buf_get(&(c)->buf, a)
-#define kcdb_cred_buf_size(c,a) kcdb_buf_size(&(c)->buf, a)
-
-#define kcdb_cred_is_cred(c) ((c) && ((kcdb_cred *) c)->magic == KCDB_CRED_MAGIC)
-#define kcdb_cred_is_active_cred(c) (kcdb_cred_is_cred(c) && !(((kcdb_cred *) c)->flags & KCDB_CRED_FLAG_DELETED))
-
-#define kcdb_cred_lock_read() (LockObtainRead(&l_creds))
-#define kcdb_cred_unlock_read() (LockReleaseRead(&l_creds))
-#define kcdb_cred_lock_write() (LockObtainWrite(&l_creds))
-#define kcdb_cred_unlock_write() (LockReleaseWrite(&l_creds))
-
-void kcdb_cred_init(void);
-void kcdb_cred_exit(void);
-void kcdb_cred_check_and_delete(khm_handle vcred);
-
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __KHIMAIRA_KCDB_CREDENTIAL_H
+#define __KHIMAIRA_KCDB_CREDENTIAL_H
+
+/* Credentials */
+
+typedef struct kcdb_cred_t {
+ khm_int32 magic;
+ khm_ui_8 id; /* serial number */
+ kcdb_identity * identity;
+ khm_int32 type;
+ wchar_t * name;
+
+ khm_int32 flags;
+ khm_int32 refcount;
+
+ kcdb_buf buf;
+
+ LDCL(struct kcdb_cred_t);
+} kcdb_cred;
+
+#define KCDB_CRED_MAGIC 0x38fb84a6
+
+extern CRITICAL_SECTION cs_creds;
+extern kcdb_cred * kcdb_creds;
+extern RWLOCK l_creds;
+extern khm_ui_8 kcdb_cred_id;
+
+#define kcdb_cred_val_exist(c,a) kcdb_buf_val_exist(&(c)->buf, a)
+#define kcdb_cred_buf_exist(c,a) kcdb_buf_exist(&(c)->buf, a)
+#define kcdb_cred_buf_get(c,a) kcdb_buf_get(&(c)->buf, a)
+#define kcdb_cred_buf_size(c,a) kcdb_buf_size(&(c)->buf, a)
+
+#define kcdb_cred_is_cred(c) ((c) && ((kcdb_cred *) c)->magic == KCDB_CRED_MAGIC)
+#define kcdb_cred_is_active_cred(c) (kcdb_cred_is_cred(c) && !(((kcdb_cred *) c)->flags & KCDB_CRED_FLAG_DELETED))
+
+#define kcdb_cred_lock_read() (LockObtainRead(&l_creds))
+#define kcdb_cred_unlock_read() (LockReleaseRead(&l_creds))
+#define kcdb_cred_lock_write() (LockObtainWrite(&l_creds))
+#define kcdb_cred_unlock_write() (LockReleaseWrite(&l_creds))
+
+void kcdb_cred_init(void);
+void kcdb_cred_exit(void);
+void kcdb_cred_check_and_delete(khm_handle vcred);
+
+#endif
diff --git a/src/windows/identity/kcreddb/credset.c b/src/windows/identity/kcreddb/credset.c
index 2d7eeeb1fc..41ca19a468 100644
--- a/src/windows/identity/kcreddb/credset.c
+++ b/src/windows/identity/kcreddb/credset.c
@@ -1,1177 +1,1177 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<kcreddbinternal.h>
-#include<assert.h>
-
-CRITICAL_SECTION cs_credset;
-kcdb_credset * kcdb_credsets = NULL;
-kcdb_credset * kcdb_root_credset = NULL;
-
-void
-kcdb_credset_init(void)
-{
- khm_handle rc;
-
- InitializeCriticalSection(&cs_credset);
- kcdb_credsets = NULL;
-
- kcdb_credset_create(&rc);
- kcdb_root_credset = (kcdb_credset *) rc;
- kcdb_root_credset->flags |= KCDB_CREDSET_FLAG_ROOT;
-}
-
-void
-kcdb_credset_exit(void)
-{
- /*TODO: free the credsets */
- DeleteCriticalSection(&cs_credset);
-}
-
-/* called on an unreleased credset, or with credset::cs held */
-void
-kcdb_credset_buf_new(kcdb_credset * cs)
-{
- cs->clist = PMALLOC(KCDB_CREDSET_INITIAL_SIZE *
- sizeof(kcdb_credset_credref));
- ZeroMemory(cs->clist,
- KCDB_CREDSET_INITIAL_SIZE *
- sizeof(kcdb_credset_credref));
- cs->nc_clist = KCDB_CREDSET_INITIAL_SIZE;
- cs->nclist = 0;
-}
-
-/* called on an unreleased credset, or with credset::cs held */
-void
-kcdb_credset_buf_delete(kcdb_credset * cs)
-{
- PFREE(cs->clist);
- cs->nc_clist = 0;
- cs->nclist = 0;
-}
-
-void
-kcdb_credset_buf_assert_size(kcdb_credset * cs, khm_int32 nclist)
-{
- if(cs->nc_clist < nclist) {
- kcdb_credset_credref * new_clist;
-
- /* nclist had better be greater than KCDB_CREDSET_INITIAL_SIZE */
- nclist = KCDB_CREDSET_INITIAL_SIZE +
- (((nclist - (KCDB_CREDSET_INITIAL_SIZE + 1)) / KCDB_CREDSET_GROWTH_FACTOR) + 1) *
- KCDB_CREDSET_GROWTH_FACTOR;
-
- new_clist = PCALLOC(nclist, sizeof(kcdb_credset_credref));
-
- memcpy(new_clist, cs->clist, cs->nclist * sizeof(kcdb_credset_credref));
-
- PFREE(cs->clist);
-
- cs->clist = new_clist;
- }
-}
-
-KHMEXP khm_int32 KHMAPI
-kcdb_credset_create(khm_handle * result)
-{
- kcdb_credset * cs;
-
- cs = PMALLOC(sizeof(kcdb_credset));
- ZeroMemory(cs, sizeof(kcdb_credset));
-
- cs->magic = KCDB_CREDSET_MAGIC;
- InitializeCriticalSection(&(cs->cs));
- LINIT(cs);
- kcdb_credset_buf_new(cs);
- cs->version = 0;
- cs->seal_count = 0;
-
- EnterCriticalSection(&cs_credset);
- LPUSH(&kcdb_credsets, cs);
- LeaveCriticalSection(&cs_credset);
-
- *result = (khm_handle) cs;
-
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP khm_int32 KHMAPI
-kcdb_credset_delete(khm_handle vcredset)
-{
- kcdb_credset * cs;
- int i;
-
- if(!kcdb_credset_is_credset(vcredset)) {
- return KHM_ERROR_INVALID_PARAM;
- }
-
- cs = (kcdb_credset *) vcredset;
-
- EnterCriticalSection(&cs_credset);
- LDELETE(&kcdb_credsets, cs);
- LeaveCriticalSection(&cs_credset);
-
- EnterCriticalSection(&(cs->cs));
- cs->magic = 0;
-
- for(i=0;i<cs->nclist;i++) {
- if(cs->clist[i].cred) {
- kcdb_cred_release((khm_handle) cs->clist[i].cred);
- }
- }
- kcdb_credset_buf_delete(cs);
-
- LeaveCriticalSection(&(cs->cs));
- DeleteCriticalSection(&(cs->cs));
-
- PFREE(cs);
-
- return KHM_ERROR_SUCCESS;
-}
-
-/*! \internal
-
-Collect credentials from cs2 to cs1 which have already been selected into
-cl1 and cl2.
-
-- Credentials in cl2 that are not in cl1 will get added to cs1
-- Credentials in cl1 that are not in cl2 will get removed from cs1
-- Credentials in cl1 and cl2 will be updated in cs1
-
-cl1 and cl2 will be modified.
-*/
-khm_int32
-kcdb_credset_collect_core(kcdb_credset * cs1,
- kcdb_cred ** cl1,
- khm_int32 ncl1,
- kcdb_credset * cs2,
- kcdb_cred ** cl2,
- khm_int32 ncl2,
- khm_int32 * delta)
-{
- int i, j;
- int ldelta = 0;
- khm_int32 rv;
-
- /* find matching creds and update them */
- for(i=0; i<ncl1; i++)
- if(cl1[i]) {
- for(j=0; j<ncl2; j++)
- if(cl2[j] && kcdb_creds_is_equal((khm_handle) cl1[i], (khm_handle) cl2[j])) {
- /* they are equivalent. make them equal */
-
- /* depending on whether any changes were made,
- update ldelta with the proper bit flag */
-
- rv = kcdb_cred_update(cl1[i], cl2[j]);
- if (rv == KHM_ERROR_SUCCESS) {
- kcdb_credset_update_cred_ref((khm_handle) cs1, (khm_handle) cl1[i]);
- ldelta |= KCDB_DELTA_MODIFY;
- }
-
- cl2[j] = NULL;
- cl1[i] = NULL;
- break;
- }
- }
-
- /* all the creds that are left in cl1 need to be removed */
- for(i=0; i<ncl1; i++)
- if(cl1[i]) {
- kcdb_credset_del_cred_ref((khm_handle) cs1, (khm_handle) cl1[i]);
- cl1[i] = NULL;
- ldelta |= KCDB_DELTA_DEL;
- }
-
- /* all the creds in cl2 need to be added to cs1 */
- for(j=0; j<ncl2; j++)
- if(cl2[j]) {
- /* duplicate the credential and add it if we are adding it to the
- root credential store. */
- if(cs1 == kcdb_root_credset) {
- khm_handle h;
-
- if(KHM_SUCCEEDED(kcdb_cred_dup((khm_handle) cl2[j], &h))) {
- kcdb_credset_add_cred((khm_handle) cs1, h, -1);
- kcdb_cred_release(h);
- }
- } else
- kcdb_credset_add_cred((khm_handle) cs1, cl2[j], -1);
- cl2[j] = NULL;
- ldelta |= KCDB_DELTA_ADD;
- }
-
- if(delta)
- *delta = ldelta;
-
- if((cs1 == kcdb_root_credset) && ldelta) {
- /* something changed in the root credential set */
- kmq_post_message(KMSG_CRED,KMSG_CRED_ROOTDELTA,ldelta,NULL);
- }
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP khm_int32 KHMAPI
-kcdb_credset_collect(khm_handle cs_dest,
- khm_handle cs_src,
- khm_handle identity,
- khm_int32 type,
- khm_int32 * delta)
-{
- kcdb_credset * cs;
- kcdb_credset * rcs;
- khm_int32 code = KHM_ERROR_SUCCESS;
- kcdb_cred ** r_sel = NULL;
- kcdb_cred ** c_sel = NULL;
- int nr_sel, nc_sel;
- int i;
-
- if((cs_src && !kcdb_credset_is_credset(cs_src)) ||
- (cs_dest && !kcdb_credset_is_credset(cs_dest)) ||
- (cs_src == cs_dest)) /* works because credsets use shared
- handles */
- return KHM_ERROR_INVALID_PARAM;
-
- if(identity && !kcdb_is_active_identity(identity))
- return KHM_ERROR_INVALID_PARAM;
-
- if(cs_src)
- cs = (kcdb_credset *) cs_src;
- else
- cs = kcdb_root_credset;
-
- if(cs_dest)
- rcs = (kcdb_credset *) cs_dest;
- else
- rcs = kcdb_root_credset;
-
- if (kcdb_credset_is_sealed(rcs))
- return KHM_ERROR_INVALID_OPERATION;
-
- EnterCriticalSection(&(cs->cs));
- EnterCriticalSection(&(rcs->cs));
-
- /* enumerate through the root and given credential sets and select
- the ones we want */
-
- if(rcs->nclist > 0)
- r_sel = PMALLOC(sizeof(kcdb_cred *) * rcs->nclist);
- if(cs->nclist > 0)
- c_sel = PMALLOC(sizeof(kcdb_cred *) * cs->nclist);
- nr_sel = 0;
- nc_sel = 0;
-
- for(i=0; i<rcs->nclist; i++) {
- if(rcs->clist[i].cred &&
- (!identity || rcs->clist[i].cred->identity == identity) &&
- (type==KCDB_CREDTYPE_ALL || rcs->clist[i].cred->type == type))
- {
- r_sel[nr_sel++] = rcs->clist[i].cred;
- }
- }
-
- for(i=0; i<cs->nclist; i++) {
- if(cs->clist[i].cred &&
- (!identity || cs->clist[i].cred->identity == identity) &&
- (type==KCDB_CREDTYPE_ALL || cs->clist[i].cred->type == type))
- {
- c_sel[nc_sel++] = cs->clist[i].cred;
- }
- }
-
- rcs->version++;
-
- code = kcdb_credset_collect_core(
- rcs,
- r_sel,
- nr_sel,
- cs,
- c_sel,
- nc_sel,
- delta);
-
- LeaveCriticalSection(&(rcs->cs));
- LeaveCriticalSection(&(cs->cs));
-
- if(r_sel)
- PFREE(r_sel);
- if(c_sel)
- PFREE(c_sel);
-
- if (cs_dest == NULL) {
- kcdb_identity_refresh_all();
- }
-
- return code;
-}
-
-KHMEXP khm_int32 KHMAPI
-kcdb_credset_collect_filtered(khm_handle cs_dest,
- khm_handle cs_src,
- kcdb_cred_filter_func filter,
- void * rock,
- khm_int32 * delta)
-{
- kcdb_credset * cs;
- kcdb_credset * rcs;
- khm_int32 code = KHM_ERROR_SUCCESS;
- kcdb_cred ** r_sel = NULL;
- kcdb_cred ** c_sel = NULL;
- int nr_sel, nc_sel;
- int i;
- khm_int32 cs_f = 0;
- khm_int32 rcs_f = 0;
-
- if((cs_src && !kcdb_credset_is_credset(cs_src)) ||
- (cs_dest && !kcdb_credset_is_credset(cs_dest)) ||
- (cs_src == cs_dest)) /* works because credsets use shared
- handles */
- return KHM_ERROR_INVALID_PARAM;
-
- if(cs_src)
- cs = (kcdb_credset *) cs_src;
- else {
- cs = kcdb_root_credset;
- cs_f = KCDB_CREDCOLL_FILTER_ROOT;
- }
-
- if(cs_dest)
- rcs = (kcdb_credset *) cs_dest;
- else {
- rcs = kcdb_root_credset;
- rcs_f = KCDB_CREDCOLL_FILTER_ROOT;
- }
-
- if (kcdb_credset_is_sealed(rcs))
- return KHM_ERROR_INVALID_OPERATION;
-
- EnterCriticalSection(&(cs->cs));
- EnterCriticalSection(&(rcs->cs));
-
-#ifdef DEBUG
- assert(!(rcs->flags & KCDB_CREDSET_FLAG_ENUM));
- assert(!(cs->flags & KCDB_CREDSET_FLAG_ENUM));
-#endif
-
- if(rcs->nclist)
- r_sel = PMALLOC(sizeof(kcdb_cred *) * rcs->nclist);
- if(cs->nclist)
- c_sel = PMALLOC(sizeof(kcdb_cred *) * cs->nclist);
- nr_sel = 0;
- nc_sel = 0;
-
- rcs->flags |= KCDB_CREDSET_FLAG_ENUM;
-
- for(i=0; i<rcs->nclist; i++) {
- if(rcs->clist[i].cred &&
- (*filter)((khm_handle)rcs->clist[i].cred,
- KCDB_CREDCOLL_FILTER_DEST | rcs_f,
- rock))
- {
- r_sel[nr_sel++] = rcs->clist[i].cred;
- }
- }
-
- rcs->flags &= ~KCDB_CREDSET_FLAG_ENUM;
- cs->flags |= KCDB_CREDSET_FLAG_ENUM;
-
- for(i=0; i<cs->nclist; i++) {
- if(cs->clist[i].cred && filter((khm_handle)rcs->clist[i].cred, KCDB_CREDCOLL_FILTER_SRC | cs_f, rock))
- {
- c_sel[nc_sel++] = cs->clist[i].cred;
- }
- }
-
- cs->flags &= ~KCDB_CREDSET_FLAG_ENUM;
-
- rcs->version++;
-
- code = kcdb_credset_collect_core(
- rcs,
- r_sel,
- nr_sel,
- cs,
- c_sel,
- nc_sel,
- delta);
-
- LeaveCriticalSection(&(rcs->cs));
- LeaveCriticalSection(&(cs->cs));
-
- if(r_sel)
- PFREE(r_sel);
- if(c_sel)
- PFREE(c_sel);
-
- if (cs_dest == NULL) {
- kcdb_identity_refresh_all();
- }
-
- return code;
-}
-
-KHMEXP khm_int32 KHMAPI
-kcdb_credset_flush(khm_handle vcredset)
-{
- int i;
- kcdb_credset * cs;
-
- if(!kcdb_credset_is_credset(vcredset))
- return KHM_ERROR_INVALID_PARAM;
-
- cs = (kcdb_credset *) vcredset;
-
- if (kcdb_credset_is_sealed(cs))
- return KHM_ERROR_INVALID_OPERATION;
-
- EnterCriticalSection(&(cs->cs));
-
-#ifdef DEBUG
- assert(!(cs->flags & KCDB_CREDSET_FLAG_ENUM));
-#endif
-
- for(i=0;i<cs->nclist;i++) {
- if(cs->clist[i].cred) {
- kcdb_cred_release((khm_handle) cs->clist[i].cred);
- }
- }
- cs->nclist = 0;
- LeaveCriticalSection(&(cs->cs));
-
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP khm_int32 KHMAPI
-kcdb_credset_extract(khm_handle destcredset,
- khm_handle sourcecredset,
- khm_handle identity,
- khm_int32 type)
-{
- khm_int32 code = KHM_ERROR_SUCCESS;
- kcdb_credset * dest;
- kcdb_credset * src;
- int isRoot = 0;
- khm_size srcSize = 0;
- int i;
-
- if(!kcdb_credset_is_credset(destcredset))
- return KHM_ERROR_INVALID_PARAM;
-
- if(sourcecredset) {
- if(!kcdb_credset_is_credset(sourcecredset))
- return KHM_ERROR_INVALID_PARAM;
- } else {
- sourcecredset = kcdb_root_credset;
- }
-
- if (sourcecredset == kcdb_root_credset)
- isRoot = 1;
-
- src = (kcdb_credset *) sourcecredset;
- dest = (kcdb_credset *) destcredset;
-
- if (kcdb_credset_is_sealed(dest))
- return KHM_ERROR_INVALID_OPERATION;
-
- EnterCriticalSection(&(src->cs));
- EnterCriticalSection(&(dest->cs));
-
-#ifdef DEBUG
- assert(!(dest->flags & KCDB_CREDSET_FLAG_ENUM));
-#endif
-
- if(KHM_FAILED(kcdb_credset_get_size(sourcecredset, &srcSize))) {
- code = KHM_ERROR_UNKNOWN;
- goto _exit;
- }
-
- kcdb_cred_lock_read();
-
- for(i=0; i < (int) srcSize; i++) {
- kcdb_cred * c;
-
- c = src->clist[i].cred;
- if(kcdb_cred_is_active_cred((khm_handle) c) &&
- (!identity || c->identity == identity) &&
- (type < 0 || c->type == type))
- {
- if(isRoot) {
- khm_handle newcred;
-
- kcdb_cred_unlock_read();
- kcdb_cred_dup((khm_handle) c, &newcred);
- kcdb_credset_add_cred(destcredset, newcred, -1);
- kcdb_cred_release(newcred);
- kcdb_cred_lock_read();
- } else {
- kcdb_cred_unlock_read();
- kcdb_credset_add_cred(destcredset, (khm_handle) c, -1);
- kcdb_cred_lock_read();
- }
- }
- }
-
- kcdb_cred_unlock_read();
-
-_exit:
- LeaveCriticalSection(&(dest->cs));
- LeaveCriticalSection(&(src->cs));
-
- return code;
-}
-
-KHMEXP khm_int32 KHMAPI
-kcdb_credset_extract_filtered(khm_handle destcredset,
- khm_handle sourcecredset,
- kcdb_cred_filter_func filter,
- void * rock)
-{
- khm_int32 code = KHM_ERROR_SUCCESS;
- kcdb_credset * dest;
- kcdb_credset * src;
- int isRoot = 0;
- khm_size srcSize = 0;
- int i;
-
- if(!kcdb_credset_is_credset(destcredset))
- return KHM_ERROR_INVALID_PARAM;
-
- if(sourcecredset) {
- if(!kcdb_credset_is_credset(sourcecredset))
- return KHM_ERROR_INVALID_PARAM;
- } else {
- sourcecredset = kcdb_root_credset;
- isRoot = 1;
- }
-
- src = (kcdb_credset *) sourcecredset;
- dest = (kcdb_credset *) destcredset;
-
- if (kcdb_credset_is_sealed(dest))
- return KHM_ERROR_INVALID_OPERATION;
-
- EnterCriticalSection(&(src->cs));
- EnterCriticalSection(&(dest->cs));
-
-#ifdef DEBUG
- assert(!(dest->flags & KCDB_CREDSET_FLAG_ENUM));
-#endif
-
- if(KHM_FAILED(kcdb_credset_get_size(sourcecredset, &srcSize))) {
- code = KHM_ERROR_UNKNOWN;
- goto _exit;
- }
-
- kcdb_cred_lock_read();
-
- dest->flags |= KCDB_CREDSET_FLAG_ENUM;
-
- for(i=0; i < (int) srcSize; i++) {
- kcdb_cred * c;
-
- c = src->clist[i].cred;
- if(kcdb_cred_is_active_cred((khm_handle) c) &&
- filter(c, 0, rock))
- {
- if(isRoot) {
- khm_handle newcred;
-
- kcdb_cred_unlock_read();
- kcdb_cred_dup((khm_handle) c, &newcred);
- kcdb_credset_add_cred(destcredset, newcred, -1);
- kcdb_cred_release(newcred);
- kcdb_cred_lock_read();
- } else {
- kcdb_cred_unlock_read();
- kcdb_credset_add_cred(destcredset, (khm_handle) c, -1);
- kcdb_cred_lock_read();
- }
- }
- }
-
- dest->flags &= ~KCDB_CREDSET_FLAG_ENUM;
-
- kcdb_cred_unlock_read();
-
-_exit:
- LeaveCriticalSection(&(dest->cs));
- LeaveCriticalSection(&(src->cs));
-
- return code;
-}
-
-KHMEXP khm_int32 KHMAPI
-kcdb_credset_apply(khm_handle vcredset, kcdb_cred_apply_func f,
- void * rock)
-{
- kcdb_credset * cs;
- khm_int32 rv = KHM_ERROR_SUCCESS;
- int i;
-
- if(vcredset != NULL && !kcdb_credset_is_credset(vcredset))
- return KHM_ERROR_INVALID_PARAM;
-
- if(vcredset == NULL) {
- cs = kcdb_root_credset;
- } else {
- cs = (kcdb_credset *) vcredset;
- }
-
- EnterCriticalSection(&cs->cs);
-
-#ifdef DEBUG
- assert(!(cs->flags & KCDB_CREDSET_FLAG_ENUM));
-#endif
-
- cs->flags |= KCDB_CREDSET_FLAG_ENUM;
-
- for(i=0; i<cs->nclist; i++) {
- if(!kcdb_cred_is_active_cred(cs->clist[i].cred))
- continue;
-
- if(KHM_FAILED(f((khm_handle) cs->clist[i].cred, rock)))
- break;
- }
-
- cs->flags &= ~KCDB_CREDSET_FLAG_ENUM;
-
- LeaveCriticalSection(&cs->cs);
-
- if(i<cs->nclist)
- rv = KHM_ERROR_EXIT;
-
- return rv;
-}
-
-KHMEXP khm_int32 KHMAPI
-kcdb_credset_get_cred(khm_handle vcredset,
- khm_int32 idx,
- khm_handle * cred)
-{
- kcdb_credset * cs;
- khm_int32 code = KHM_ERROR_SUCCESS;
-
- if(!kcdb_credset_is_credset(vcredset))
- return KHM_ERROR_INVALID_PARAM;
-
- cs = (kcdb_credset *) vcredset;
-
- *cred = NULL;
-
- EnterCriticalSection(&(cs->cs));
- if(idx < 0 || idx >= cs->nclist)
- code = KHM_ERROR_OUT_OF_BOUNDS;
- else if(!cs->clist[idx].cred || !kcdb_cred_is_active_cred((khm_handle) cs->clist[idx].cred)) {
- code = KHM_ERROR_DELETED;
- if(cs->clist[idx].cred) {
- kcdb_cred_release((khm_handle) cs->clist[idx].cred);
- cs->clist[idx].cred = NULL;
- }
- }
- else {
- kcdb_cred_hold((khm_handle) cs->clist[idx].cred);
- *cred = cs->clist[idx].cred;
- }
- LeaveCriticalSection(&(cs->cs));
- return code;
-}
-
-KHMEXP khm_int32 KHMAPI
-kcdb_credset_find_filtered(khm_handle credset,
- khm_int32 idx_start,
- kcdb_cred_filter_func f,
- void * rock,
- khm_handle * cred,
- khm_int32 * idx)
-{
- kcdb_credset * cs;
- khm_int32 rv = KHM_ERROR_SUCCESS;
- int i;
-
- if((credset && !kcdb_credset_is_credset(credset)) || !f)
- return KHM_ERROR_INVALID_PARAM;
-
- if(credset)
- cs = (kcdb_credset *) credset;
- else
- cs = kcdb_root_credset;
-
- EnterCriticalSection(&cs->cs);
-
- if(idx_start < 0)
- i = 0;
- else
- i = idx_start + 1;
-
-#ifdef DEBUG
- assert(!(cs->flags & KCDB_CREDSET_FLAG_ENUM));
-#endif
-
- cs->flags |= KCDB_CREDSET_FLAG_ENUM;
-
- for(; i < cs->nclist; i++) {
- if(kcdb_cred_is_active_cred(cs->clist[i].cred) &&
- (*f)((khm_handle) cs->clist[i].cred, 0, rock) != 0)
- break;
- }
-
- cs->flags &= ~KCDB_CREDSET_FLAG_ENUM;
-
- if(i < cs->nclist) {
- if (cred) {
- *cred = (khm_handle) cs->clist[i].cred;
- kcdb_cred_hold(*cred);
- }
-
- if(idx) {
- *idx = i;
- }
- } else {
- rv = KHM_ERROR_NOT_FOUND;
- }
-
- LeaveCriticalSection(&cs->cs);
-
- return rv;
-}
-
-KHMEXP khm_int32 KHMAPI
-kcdb_credset_find_cred(khm_handle vcredset,
- khm_handle vcred_src,
- khm_handle *cred_dest) {
- kcdb_credset * cs;
- khm_handle cred = NULL;
- int idx;
-
- if (!kcdb_credset_is_credset(vcredset))
- return KHM_ERROR_INVALID_PARAM;
-
- if (!kcdb_cred_is_active_cred(vcred_src))
- return KHM_ERROR_INVALID_PARAM;
-
- cs = (kcdb_credset *) vcredset;
-
- EnterCriticalSection(&cs->cs);
- for (idx = 0; idx < cs->nclist; idx++) {
- if (cs->clist[idx].cred &&
- kcdb_creds_is_equal(vcred_src, cs->clist[idx].cred)) {
- cred = cs->clist[idx].cred;
- break;
- }
- }
-
- if (cred)
- kcdb_cred_hold(cred);
-
- LeaveCriticalSection(&cs->cs);
-
- if (cred) {
- if (cred_dest)
- *cred_dest = cred;
- else
- kcdb_cred_release(cred);
-
- return KHM_ERROR_SUCCESS;
- } else {
- return KHM_ERROR_NOT_FOUND;
- }
-}
-
-KHMEXP khm_int32 KHMAPI
-kcdb_credset_del_cred(khm_handle vcredset,
- khm_int32 idx)
-{
- kcdb_credset * cs;
- khm_int32 code = KHM_ERROR_SUCCESS;
-
- if(!kcdb_credset_is_credset(vcredset))
- return KHM_ERROR_INVALID_PARAM;
-
- cs = (kcdb_credset *) vcredset;
-
- if (kcdb_credset_is_sealed(cs))
- return KHM_ERROR_INVALID_OPERATION;
-
- EnterCriticalSection(&(cs->cs));
- if(idx < 0 || idx >= cs->nclist) {
- code = KHM_ERROR_INVALID_PARAM;
- goto _exit;
- }
-
- if(cs->clist[idx].cred)
- kcdb_cred_release((khm_handle) cs->clist[idx].cred);
-
- if (!(cs->flags & KCDB_CREDSET_FLAG_ENUM)) {
-
- if(idx + 1 < cs->nclist)
- memmove(&(cs->clist[idx]),
- &(cs->clist[idx+1]),
- sizeof(kcdb_credset_credref) *
- (cs->nclist - (idx + 1)));
-
- cs->nclist--;
- } else {
- cs->clist[idx].cred = NULL;
- }
-
-_exit:
- LeaveCriticalSection(&(cs->cs));
-
- return code;
-}
-
-khm_int32
-kcdb_credset_update_cred_ref(khm_handle credset,
- khm_handle cred)
-{
- kcdb_credset * cs;
- khm_int32 code = KHM_ERROR_SUCCESS;
- int i;
-
- if(!kcdb_credset_is_credset(credset))
- return KHM_ERROR_INVALID_PARAM;
-
- cs = (kcdb_credset *) credset;
-
- EnterCriticalSection(&(cs->cs));
-
- for(i=0; i<cs->nclist; i++) {
- if(cs->clist[i].cred == cred)
- break;
- }
-
- if(i<cs->nclist) {
- cs->clist[i].version = cs->version;
- } else {
- code = KHM_ERROR_NOT_FOUND;
- }
-
- LeaveCriticalSection(&(cs->cs));
- return code;
-}
-
-KHMEXP khm_int32 KHMAPI
-kcdb_credset_del_cred_ref(khm_handle credset,
- khm_handle cred)
-{
- kcdb_credset * cs;
- khm_int32 code = KHM_ERROR_SUCCESS;
- int i;
-
- if(!kcdb_credset_is_credset(credset))
- return KHM_ERROR_INVALID_PARAM;
-
- cs = (kcdb_credset *) credset;
-
- if (kcdb_credset_is_sealed(cs))
- return KHM_ERROR_INVALID_OPERATION;
-
- EnterCriticalSection(&(cs->cs));
-
- for(i=0; i<cs->nclist; i++) {
- if(cs->clist[i].cred == cred)
- break;
- }
-
- if(i<cs->nclist) {
- code = kcdb_credset_del_cred(credset, i);
- } else {
- code = KHM_ERROR_NOT_FOUND;
- }
-
- LeaveCriticalSection(&(cs->cs));
- return code;
-}
-
-KHMEXP khm_int32 KHMAPI
-kcdb_credset_add_cred(khm_handle credset,
- khm_handle cred,
- khm_int32 idx)
-{
- int new_idx;
- kcdb_credset * cs;
- khm_int32 code = KHM_ERROR_SUCCESS;
-
- if(!kcdb_credset_is_credset(credset))
- return KHM_ERROR_INVALID_PARAM;
-
- cs = (kcdb_credset *) credset;
-
- if (kcdb_credset_is_sealed(cs))
- return KHM_ERROR_INVALID_OPERATION;
-
- EnterCriticalSection(&(cs->cs));
-
- kcdb_credset_buf_assert_size(cs, cs->nclist + 1);
-
- if(idx < 0 || idx > cs->nclist)
- new_idx = cs->nclist;
- else if(idx < cs->nclist){
-#ifdef DEBUG
- assert(!(cs->flags & KCDB_CREDSET_FLAG_ENUM));
-#endif
- memmove(&(cs->clist[idx+1]), &(cs->clist[idx]), (cs->nclist - idx)*sizeof(cs->clist[0]));
- new_idx = idx;
- } else
- new_idx = idx;
-
- kcdb_cred_hold(cred);
-
- cs->clist[new_idx].cred = (kcdb_cred *) cred;
- cs->clist[new_idx].version = cs->version;
- cs->nclist++;
-
- LeaveCriticalSection(&(cs->cs));
- return code;
-}
-
-KHMEXP khm_int32 KHMAPI
-kcdb_credset_get_size(khm_handle credset,
- khm_size * size)
-{
- kcdb_credset * cs;
-
- *size = 0;
-
- /* we don't rely on this working, since we can't purge a sealed
- credset, although we can measure its size. */
- kcdb_credset_purge(credset);
-
- if (credset == NULL)
- cs = kcdb_root_credset;
- else
- cs = (kcdb_credset *) credset;
-
- EnterCriticalSection(&(cs->cs));
- /* while it may seem a bit redundant to get a lock, it ensures that
- that the size that we return is consistent with the current state
- of the credential set */
- *size = cs->nclist;
- LeaveCriticalSection(&(cs->cs));
-
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP khm_int32 KHMAPI
-kcdb_credset_purge(khm_handle credset)
-{
- khm_int32 code = KHM_ERROR_SUCCESS;
- kcdb_credset * cs;
- int i,j;
-
- if(!kcdb_credset_is_credset(credset))
- return KHM_ERROR_INVALID_PARAM;
-
- cs = (kcdb_credset *) credset;
-
- if (kcdb_credset_is_sealed(cs))
- return KHM_ERROR_INVALID_OPERATION;
-
- EnterCriticalSection(&(cs->cs));
-
- /* we can't purge a credset while an enumeration operation is in
- progress. */
- if (cs->flags & KCDB_CREDSET_FLAG_ENUM) {
- code = KHM_ERROR_INVALID_OPERATION;
- goto _exit;
- }
-
- for(i=0,j=0; i < cs->nclist; i++) {
- if(cs->clist[i].cred) {
- if(!kcdb_cred_is_active_cred((khm_handle) cs->clist[i].cred)) {
- kcdb_cred_release((khm_handle) cs->clist[i].cred);
- } else if(i != j) {
- cs->clist[j++] = cs->clist[i];
- } else
- j++;
- }
- }
- cs->nclist = j;
-
- _exit:
- LeaveCriticalSection(&(cs->cs));
- return code;
-}
-
-KHMEXP khm_int32 KHMAPI
-kcdb_credset_seal(khm_handle credset) {
- kcdb_credset * cs;
-
- if (!kcdb_credset_is_credset(credset))
- return KHM_ERROR_INVALID_PARAM;
-
- cs = (kcdb_credset *) credset;
-
- EnterCriticalSection(&cs->cs);
- cs->seal_count++;
- LeaveCriticalSection(&cs->cs);
-
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP khm_int32 KHMAPI
-kcdb_credset_unseal(khm_handle credset) {
- kcdb_credset * cs;
- khm_int32 rv;
-
- if (!kcdb_credset_is_credset(credset))
- return KHM_ERROR_INVALID_PARAM;
-
- cs = (kcdb_credset *) credset;
-
- EnterCriticalSection(&cs->cs);
- if (cs->seal_count > 0) {
- cs->seal_count--;
- rv = KHM_ERROR_SUCCESS;
- } else {
- rv = KHM_ERROR_INVALID_OPERATION;
- }
- LeaveCriticalSection(&cs->cs);
-
- return rv;
-}
-
-
-/* wrapper for qsort and also parameter gobbling FSM. Access to this
- function is serialized via cs_credset. */
-int __cdecl
-kcdb_creds_comp_wrapper(const void * a, const void * b)
-{
- static void * rock = NULL;
- static kcdb_cred_comp_func comp = NULL;
-
- if(!b) {
- rock = (void *) a;
- return 0;
- }
-
- if(!a) {
- comp = (kcdb_cred_comp_func) b;
- return 0;
- }
-
- return comp((khm_handle) ((kcdb_credset_credref *)a)->cred,
- (khm_handle) ((kcdb_credset_credref *)b)->cred,
- rock);
-}
-
-KHMEXP khm_int32 KHMAPI
-kcdb_credset_sort(khm_handle credset,
- kcdb_cred_comp_func comp,
- void * rock)
-{
- khm_int32 code = KHM_ERROR_SUCCESS;
- kcdb_credset * cs;
-
- if(!kcdb_credset_is_credset(credset))
- return KHM_ERROR_INVALID_PARAM;
-
- cs = (kcdb_credset *) credset;
-
- if (kcdb_credset_is_sealed(cs))
- return KHM_ERROR_INVALID_OPERATION;
-
- EnterCriticalSection(&(cs->cs));
-
-#ifdef DEBUG
- assert(!(cs->flags & KCDB_CREDSET_FLAG_ENUM));
-#endif
-
- EnterCriticalSection(&cs_credset);
-
- kcdb_creds_comp_wrapper(rock, NULL);
- kcdb_creds_comp_wrapper(NULL, (void *) comp);
-
- qsort(cs->clist, cs->nclist,
- sizeof(kcdb_credset_credref), kcdb_creds_comp_wrapper);
-
- LeaveCriticalSection(&cs_credset);
-
- LeaveCriticalSection(&(cs->cs));
- return code;
-}
-
-KHMEXP khm_int32 KHMAPI
-kcdb_cred_comp_generic(khm_handle cred1,
- khm_handle cred2,
- void * rock)
-{
- kcdb_cred_comp_order * o = (kcdb_cred_comp_order *) rock;
- int i;
- khm_int32 r = 0;
- khm_int32 f1, f2;
- khm_int32 t1, t2;
- khm_int32 pt;
-
- for(i=0; i<o->nFields; i++) {
- if (o->fields[i].order & KCDB_CRED_COMP_INITIAL_FIRST) {
-
- if (o->fields[i].attrib == KCDB_ATTR_TYPE_NAME ||
- o->fields[i].attrib == KCDB_ATTR_TYPE) {
-
- kcdb_cred_get_type(cred1, &t1);
- kcdb_cred_get_type(cred2, &t2);
- kcdb_identity_get_type(&pt);
-
- if (t1 == t2)
- r = 0;
- else if (t1 == pt)
- r = -1;
- else if (t2 == pt)
- r = 1;
- else
- r = 0;
-
- } else {
-
- kcdb_cred_get_flags(cred1, &f1);
- kcdb_cred_get_flags(cred2, &f2);
-
- if (((f1 ^ f2) & KCDB_CRED_FLAG_INITIAL) == 0)
- r = 0;
- else if (f1 & KCDB_CRED_FLAG_INITIAL)
- r = -1;
- else
- r = 1;
-
- }
-
- } else {
- r = 0;
- }
-
- if (r == 0)
- r = kcdb_creds_comp_attr(cred1,cred2,o->fields[i].attrib);
-
- if(r != 0) {
- if(o->fields[i].order & KCDB_CRED_COMP_DECREASING)
- r = -r;
- break;
- }
- }
-
- return r;
-}
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<kcreddbinternal.h>
+#include<assert.h>
+
+CRITICAL_SECTION cs_credset;
+kcdb_credset * kcdb_credsets = NULL;
+kcdb_credset * kcdb_root_credset = NULL;
+
+void
+kcdb_credset_init(void)
+{
+ khm_handle rc;
+
+ InitializeCriticalSection(&cs_credset);
+ kcdb_credsets = NULL;
+
+ kcdb_credset_create(&rc);
+ kcdb_root_credset = (kcdb_credset *) rc;
+ kcdb_root_credset->flags |= KCDB_CREDSET_FLAG_ROOT;
+}
+
+void
+kcdb_credset_exit(void)
+{
+ /*TODO: free the credsets */
+ DeleteCriticalSection(&cs_credset);
+}
+
+/* called on an unreleased credset, or with credset::cs held */
+void
+kcdb_credset_buf_new(kcdb_credset * cs)
+{
+ cs->clist = PMALLOC(KCDB_CREDSET_INITIAL_SIZE *
+ sizeof(kcdb_credset_credref));
+ ZeroMemory(cs->clist,
+ KCDB_CREDSET_INITIAL_SIZE *
+ sizeof(kcdb_credset_credref));
+ cs->nc_clist = KCDB_CREDSET_INITIAL_SIZE;
+ cs->nclist = 0;
+}
+
+/* called on an unreleased credset, or with credset::cs held */
+void
+kcdb_credset_buf_delete(kcdb_credset * cs)
+{
+ PFREE(cs->clist);
+ cs->nc_clist = 0;
+ cs->nclist = 0;
+}
+
+void
+kcdb_credset_buf_assert_size(kcdb_credset * cs, khm_int32 nclist)
+{
+ if(cs->nc_clist < nclist) {
+ kcdb_credset_credref * new_clist;
+
+ /* nclist had better be greater than KCDB_CREDSET_INITIAL_SIZE */
+ nclist = KCDB_CREDSET_INITIAL_SIZE +
+ (((nclist - (KCDB_CREDSET_INITIAL_SIZE + 1)) / KCDB_CREDSET_GROWTH_FACTOR) + 1) *
+ KCDB_CREDSET_GROWTH_FACTOR;
+
+ new_clist = PCALLOC(nclist, sizeof(kcdb_credset_credref));
+
+ memcpy(new_clist, cs->clist, cs->nclist * sizeof(kcdb_credset_credref));
+
+ PFREE(cs->clist);
+
+ cs->clist = new_clist;
+ }
+}
+
+KHMEXP khm_int32 KHMAPI
+kcdb_credset_create(khm_handle * result)
+{
+ kcdb_credset * cs;
+
+ cs = PMALLOC(sizeof(kcdb_credset));
+ ZeroMemory(cs, sizeof(kcdb_credset));
+
+ cs->magic = KCDB_CREDSET_MAGIC;
+ InitializeCriticalSection(&(cs->cs));
+ LINIT(cs);
+ kcdb_credset_buf_new(cs);
+ cs->version = 0;
+ cs->seal_count = 0;
+
+ EnterCriticalSection(&cs_credset);
+ LPUSH(&kcdb_credsets, cs);
+ LeaveCriticalSection(&cs_credset);
+
+ *result = (khm_handle) cs;
+
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP khm_int32 KHMAPI
+kcdb_credset_delete(khm_handle vcredset)
+{
+ kcdb_credset * cs;
+ int i;
+
+ if(!kcdb_credset_is_credset(vcredset)) {
+ return KHM_ERROR_INVALID_PARAM;
+ }
+
+ cs = (kcdb_credset *) vcredset;
+
+ EnterCriticalSection(&cs_credset);
+ LDELETE(&kcdb_credsets, cs);
+ LeaveCriticalSection(&cs_credset);
+
+ EnterCriticalSection(&(cs->cs));
+ cs->magic = 0;
+
+ for(i=0;i<cs->nclist;i++) {
+ if(cs->clist[i].cred) {
+ kcdb_cred_release((khm_handle) cs->clist[i].cred);
+ }
+ }
+ kcdb_credset_buf_delete(cs);
+
+ LeaveCriticalSection(&(cs->cs));
+ DeleteCriticalSection(&(cs->cs));
+
+ PFREE(cs);
+
+ return KHM_ERROR_SUCCESS;
+}
+
+/*! \internal
+
+Collect credentials from cs2 to cs1 which have already been selected into
+cl1 and cl2.
+
+- Credentials in cl2 that are not in cl1 will get added to cs1
+- Credentials in cl1 that are not in cl2 will get removed from cs1
+- Credentials in cl1 and cl2 will be updated in cs1
+
+cl1 and cl2 will be modified.
+*/
+khm_int32
+kcdb_credset_collect_core(kcdb_credset * cs1,
+ kcdb_cred ** cl1,
+ khm_int32 ncl1,
+ kcdb_credset * cs2,
+ kcdb_cred ** cl2,
+ khm_int32 ncl2,
+ khm_int32 * delta)
+{
+ int i, j;
+ int ldelta = 0;
+ khm_int32 rv;
+
+ /* find matching creds and update them */
+ for(i=0; i<ncl1; i++)
+ if(cl1[i]) {
+ for(j=0; j<ncl2; j++)
+ if(cl2[j] && kcdb_creds_is_equal((khm_handle) cl1[i], (khm_handle) cl2[j])) {
+ /* they are equivalent. make them equal */
+
+ /* depending on whether any changes were made,
+ update ldelta with the proper bit flag */
+
+ rv = kcdb_cred_update(cl1[i], cl2[j]);
+ if (rv == KHM_ERROR_SUCCESS) {
+ kcdb_credset_update_cred_ref((khm_handle) cs1, (khm_handle) cl1[i]);
+ ldelta |= KCDB_DELTA_MODIFY;
+ }
+
+ cl2[j] = NULL;
+ cl1[i] = NULL;
+ break;
+ }
+ }
+
+ /* all the creds that are left in cl1 need to be removed */
+ for(i=0; i<ncl1; i++)
+ if(cl1[i]) {
+ kcdb_credset_del_cred_ref((khm_handle) cs1, (khm_handle) cl1[i]);
+ cl1[i] = NULL;
+ ldelta |= KCDB_DELTA_DEL;
+ }
+
+ /* all the creds in cl2 need to be added to cs1 */
+ for(j=0; j<ncl2; j++)
+ if(cl2[j]) {
+ /* duplicate the credential and add it if we are adding it to the
+ root credential store. */
+ if(cs1 == kcdb_root_credset) {
+ khm_handle h;
+
+ if(KHM_SUCCEEDED(kcdb_cred_dup((khm_handle) cl2[j], &h))) {
+ kcdb_credset_add_cred((khm_handle) cs1, h, -1);
+ kcdb_cred_release(h);
+ }
+ } else
+ kcdb_credset_add_cred((khm_handle) cs1, cl2[j], -1);
+ cl2[j] = NULL;
+ ldelta |= KCDB_DELTA_ADD;
+ }
+
+ if(delta)
+ *delta = ldelta;
+
+ if((cs1 == kcdb_root_credset) && ldelta) {
+ /* something changed in the root credential set */
+ kmq_post_message(KMSG_CRED,KMSG_CRED_ROOTDELTA,ldelta,NULL);
+ }
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP khm_int32 KHMAPI
+kcdb_credset_collect(khm_handle cs_dest,
+ khm_handle cs_src,
+ khm_handle identity,
+ khm_int32 type,
+ khm_int32 * delta)
+{
+ kcdb_credset * cs;
+ kcdb_credset * rcs;
+ khm_int32 code = KHM_ERROR_SUCCESS;
+ kcdb_cred ** r_sel = NULL;
+ kcdb_cred ** c_sel = NULL;
+ int nr_sel, nc_sel;
+ int i;
+
+ if((cs_src && !kcdb_credset_is_credset(cs_src)) ||
+ (cs_dest && !kcdb_credset_is_credset(cs_dest)) ||
+ (cs_src == cs_dest)) /* works because credsets use shared
+ handles */
+ return KHM_ERROR_INVALID_PARAM;
+
+ if(identity && !kcdb_is_active_identity(identity))
+ return KHM_ERROR_INVALID_PARAM;
+
+ if(cs_src)
+ cs = (kcdb_credset *) cs_src;
+ else
+ cs = kcdb_root_credset;
+
+ if(cs_dest)
+ rcs = (kcdb_credset *) cs_dest;
+ else
+ rcs = kcdb_root_credset;
+
+ if (kcdb_credset_is_sealed(rcs))
+ return KHM_ERROR_INVALID_OPERATION;
+
+ EnterCriticalSection(&(cs->cs));
+ EnterCriticalSection(&(rcs->cs));
+
+ /* enumerate through the root and given credential sets and select
+ the ones we want */
+
+ if(rcs->nclist > 0)
+ r_sel = PMALLOC(sizeof(kcdb_cred *) * rcs->nclist);
+ if(cs->nclist > 0)
+ c_sel = PMALLOC(sizeof(kcdb_cred *) * cs->nclist);
+ nr_sel = 0;
+ nc_sel = 0;
+
+ for(i=0; i<rcs->nclist; i++) {
+ if(rcs->clist[i].cred &&
+ (!identity || rcs->clist[i].cred->identity == identity) &&
+ (type==KCDB_CREDTYPE_ALL || rcs->clist[i].cred->type == type))
+ {
+ r_sel[nr_sel++] = rcs->clist[i].cred;
+ }
+ }
+
+ for(i=0; i<cs->nclist; i++) {
+ if(cs->clist[i].cred &&
+ (!identity || cs->clist[i].cred->identity == identity) &&
+ (type==KCDB_CREDTYPE_ALL || cs->clist[i].cred->type == type))
+ {
+ c_sel[nc_sel++] = cs->clist[i].cred;
+ }
+ }
+
+ rcs->version++;
+
+ code = kcdb_credset_collect_core(
+ rcs,
+ r_sel,
+ nr_sel,
+ cs,
+ c_sel,
+ nc_sel,
+ delta);
+
+ LeaveCriticalSection(&(rcs->cs));
+ LeaveCriticalSection(&(cs->cs));
+
+ if(r_sel)
+ PFREE(r_sel);
+ if(c_sel)
+ PFREE(c_sel);
+
+ if (cs_dest == NULL) {
+ kcdb_identity_refresh_all();
+ }
+
+ return code;
+}
+
+KHMEXP khm_int32 KHMAPI
+kcdb_credset_collect_filtered(khm_handle cs_dest,
+ khm_handle cs_src,
+ kcdb_cred_filter_func filter,
+ void * rock,
+ khm_int32 * delta)
+{
+ kcdb_credset * cs;
+ kcdb_credset * rcs;
+ khm_int32 code = KHM_ERROR_SUCCESS;
+ kcdb_cred ** r_sel = NULL;
+ kcdb_cred ** c_sel = NULL;
+ int nr_sel, nc_sel;
+ int i;
+ khm_int32 cs_f = 0;
+ khm_int32 rcs_f = 0;
+
+ if((cs_src && !kcdb_credset_is_credset(cs_src)) ||
+ (cs_dest && !kcdb_credset_is_credset(cs_dest)) ||
+ (cs_src == cs_dest)) /* works because credsets use shared
+ handles */
+ return KHM_ERROR_INVALID_PARAM;
+
+ if(cs_src)
+ cs = (kcdb_credset *) cs_src;
+ else {
+ cs = kcdb_root_credset;
+ cs_f = KCDB_CREDCOLL_FILTER_ROOT;
+ }
+
+ if(cs_dest)
+ rcs = (kcdb_credset *) cs_dest;
+ else {
+ rcs = kcdb_root_credset;
+ rcs_f = KCDB_CREDCOLL_FILTER_ROOT;
+ }
+
+ if (kcdb_credset_is_sealed(rcs))
+ return KHM_ERROR_INVALID_OPERATION;
+
+ EnterCriticalSection(&(cs->cs));
+ EnterCriticalSection(&(rcs->cs));
+
+#ifdef DEBUG
+ assert(!(rcs->flags & KCDB_CREDSET_FLAG_ENUM));
+ assert(!(cs->flags & KCDB_CREDSET_FLAG_ENUM));
+#endif
+
+ if(rcs->nclist)
+ r_sel = PMALLOC(sizeof(kcdb_cred *) * rcs->nclist);
+ if(cs->nclist)
+ c_sel = PMALLOC(sizeof(kcdb_cred *) * cs->nclist);
+ nr_sel = 0;
+ nc_sel = 0;
+
+ rcs->flags |= KCDB_CREDSET_FLAG_ENUM;
+
+ for(i=0; i<rcs->nclist; i++) {
+ if(rcs->clist[i].cred &&
+ (*filter)((khm_handle)rcs->clist[i].cred,
+ KCDB_CREDCOLL_FILTER_DEST | rcs_f,
+ rock))
+ {
+ r_sel[nr_sel++] = rcs->clist[i].cred;
+ }
+ }
+
+ rcs->flags &= ~KCDB_CREDSET_FLAG_ENUM;
+ cs->flags |= KCDB_CREDSET_FLAG_ENUM;
+
+ for(i=0; i<cs->nclist; i++) {
+ if(cs->clist[i].cred && filter((khm_handle)rcs->clist[i].cred, KCDB_CREDCOLL_FILTER_SRC | cs_f, rock))
+ {
+ c_sel[nc_sel++] = cs->clist[i].cred;
+ }
+ }
+
+ cs->flags &= ~KCDB_CREDSET_FLAG_ENUM;
+
+ rcs->version++;
+
+ code = kcdb_credset_collect_core(
+ rcs,
+ r_sel,
+ nr_sel,
+ cs,
+ c_sel,
+ nc_sel,
+ delta);
+
+ LeaveCriticalSection(&(rcs->cs));
+ LeaveCriticalSection(&(cs->cs));
+
+ if(r_sel)
+ PFREE(r_sel);
+ if(c_sel)
+ PFREE(c_sel);
+
+ if (cs_dest == NULL) {
+ kcdb_identity_refresh_all();
+ }
+
+ return code;
+}
+
+KHMEXP khm_int32 KHMAPI
+kcdb_credset_flush(khm_handle vcredset)
+{
+ int i;
+ kcdb_credset * cs;
+
+ if(!kcdb_credset_is_credset(vcredset))
+ return KHM_ERROR_INVALID_PARAM;
+
+ cs = (kcdb_credset *) vcredset;
+
+ if (kcdb_credset_is_sealed(cs))
+ return KHM_ERROR_INVALID_OPERATION;
+
+ EnterCriticalSection(&(cs->cs));
+
+#ifdef DEBUG
+ assert(!(cs->flags & KCDB_CREDSET_FLAG_ENUM));
+#endif
+
+ for(i=0;i<cs->nclist;i++) {
+ if(cs->clist[i].cred) {
+ kcdb_cred_release((khm_handle) cs->clist[i].cred);
+ }
+ }
+ cs->nclist = 0;
+ LeaveCriticalSection(&(cs->cs));
+
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP khm_int32 KHMAPI
+kcdb_credset_extract(khm_handle destcredset,
+ khm_handle sourcecredset,
+ khm_handle identity,
+ khm_int32 type)
+{
+ khm_int32 code = KHM_ERROR_SUCCESS;
+ kcdb_credset * dest;
+ kcdb_credset * src;
+ int isRoot = 0;
+ khm_size srcSize = 0;
+ int i;
+
+ if(!kcdb_credset_is_credset(destcredset))
+ return KHM_ERROR_INVALID_PARAM;
+
+ if(sourcecredset) {
+ if(!kcdb_credset_is_credset(sourcecredset))
+ return KHM_ERROR_INVALID_PARAM;
+ } else {
+ sourcecredset = kcdb_root_credset;
+ }
+
+ if (sourcecredset == kcdb_root_credset)
+ isRoot = 1;
+
+ src = (kcdb_credset *) sourcecredset;
+ dest = (kcdb_credset *) destcredset;
+
+ if (kcdb_credset_is_sealed(dest))
+ return KHM_ERROR_INVALID_OPERATION;
+
+ EnterCriticalSection(&(src->cs));
+ EnterCriticalSection(&(dest->cs));
+
+#ifdef DEBUG
+ assert(!(dest->flags & KCDB_CREDSET_FLAG_ENUM));
+#endif
+
+ if(KHM_FAILED(kcdb_credset_get_size(sourcecredset, &srcSize))) {
+ code = KHM_ERROR_UNKNOWN;
+ goto _exit;
+ }
+
+ kcdb_cred_lock_read();
+
+ for(i=0; i < (int) srcSize; i++) {
+ kcdb_cred * c;
+
+ c = src->clist[i].cred;
+ if(kcdb_cred_is_active_cred((khm_handle) c) &&
+ (!identity || c->identity == identity) &&
+ (type < 0 || c->type == type))
+ {
+ if(isRoot) {
+ khm_handle newcred;
+
+ kcdb_cred_unlock_read();
+ kcdb_cred_dup((khm_handle) c, &newcred);
+ kcdb_credset_add_cred(destcredset, newcred, -1);
+ kcdb_cred_release(newcred);
+ kcdb_cred_lock_read();
+ } else {
+ kcdb_cred_unlock_read();
+ kcdb_credset_add_cred(destcredset, (khm_handle) c, -1);
+ kcdb_cred_lock_read();
+ }
+ }
+ }
+
+ kcdb_cred_unlock_read();
+
+_exit:
+ LeaveCriticalSection(&(dest->cs));
+ LeaveCriticalSection(&(src->cs));
+
+ return code;
+}
+
+KHMEXP khm_int32 KHMAPI
+kcdb_credset_extract_filtered(khm_handle destcredset,
+ khm_handle sourcecredset,
+ kcdb_cred_filter_func filter,
+ void * rock)
+{
+ khm_int32 code = KHM_ERROR_SUCCESS;
+ kcdb_credset * dest;
+ kcdb_credset * src;
+ int isRoot = 0;
+ khm_size srcSize = 0;
+ int i;
+
+ if(!kcdb_credset_is_credset(destcredset))
+ return KHM_ERROR_INVALID_PARAM;
+
+ if(sourcecredset) {
+ if(!kcdb_credset_is_credset(sourcecredset))
+ return KHM_ERROR_INVALID_PARAM;
+ } else {
+ sourcecredset = kcdb_root_credset;
+ isRoot = 1;
+ }
+
+ src = (kcdb_credset *) sourcecredset;
+ dest = (kcdb_credset *) destcredset;
+
+ if (kcdb_credset_is_sealed(dest))
+ return KHM_ERROR_INVALID_OPERATION;
+
+ EnterCriticalSection(&(src->cs));
+ EnterCriticalSection(&(dest->cs));
+
+#ifdef DEBUG
+ assert(!(dest->flags & KCDB_CREDSET_FLAG_ENUM));
+#endif
+
+ if(KHM_FAILED(kcdb_credset_get_size(sourcecredset, &srcSize))) {
+ code = KHM_ERROR_UNKNOWN;
+ goto _exit;
+ }
+
+ kcdb_cred_lock_read();
+
+ dest->flags |= KCDB_CREDSET_FLAG_ENUM;
+
+ for(i=0; i < (int) srcSize; i++) {
+ kcdb_cred * c;
+
+ c = src->clist[i].cred;
+ if(kcdb_cred_is_active_cred((khm_handle) c) &&
+ filter(c, 0, rock))
+ {
+ if(isRoot) {
+ khm_handle newcred;
+
+ kcdb_cred_unlock_read();
+ kcdb_cred_dup((khm_handle) c, &newcred);
+ kcdb_credset_add_cred(destcredset, newcred, -1);
+ kcdb_cred_release(newcred);
+ kcdb_cred_lock_read();
+ } else {
+ kcdb_cred_unlock_read();
+ kcdb_credset_add_cred(destcredset, (khm_handle) c, -1);
+ kcdb_cred_lock_read();
+ }
+ }
+ }
+
+ dest->flags &= ~KCDB_CREDSET_FLAG_ENUM;
+
+ kcdb_cred_unlock_read();
+
+_exit:
+ LeaveCriticalSection(&(dest->cs));
+ LeaveCriticalSection(&(src->cs));
+
+ return code;
+}
+
+KHMEXP khm_int32 KHMAPI
+kcdb_credset_apply(khm_handle vcredset, kcdb_cred_apply_func f,
+ void * rock)
+{
+ kcdb_credset * cs;
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+ int i;
+
+ if(vcredset != NULL && !kcdb_credset_is_credset(vcredset))
+ return KHM_ERROR_INVALID_PARAM;
+
+ if(vcredset == NULL) {
+ cs = kcdb_root_credset;
+ } else {
+ cs = (kcdb_credset *) vcredset;
+ }
+
+ EnterCriticalSection(&cs->cs);
+
+#ifdef DEBUG
+ assert(!(cs->flags & KCDB_CREDSET_FLAG_ENUM));
+#endif
+
+ cs->flags |= KCDB_CREDSET_FLAG_ENUM;
+
+ for(i=0; i<cs->nclist; i++) {
+ if(!kcdb_cred_is_active_cred(cs->clist[i].cred))
+ continue;
+
+ if(KHM_FAILED(f((khm_handle) cs->clist[i].cred, rock)))
+ break;
+ }
+
+ cs->flags &= ~KCDB_CREDSET_FLAG_ENUM;
+
+ LeaveCriticalSection(&cs->cs);
+
+ if(i<cs->nclist)
+ rv = KHM_ERROR_EXIT;
+
+ return rv;
+}
+
+KHMEXP khm_int32 KHMAPI
+kcdb_credset_get_cred(khm_handle vcredset,
+ khm_int32 idx,
+ khm_handle * cred)
+{
+ kcdb_credset * cs;
+ khm_int32 code = KHM_ERROR_SUCCESS;
+
+ if(!kcdb_credset_is_credset(vcredset))
+ return KHM_ERROR_INVALID_PARAM;
+
+ cs = (kcdb_credset *) vcredset;
+
+ *cred = NULL;
+
+ EnterCriticalSection(&(cs->cs));
+ if(idx < 0 || idx >= cs->nclist)
+ code = KHM_ERROR_OUT_OF_BOUNDS;
+ else if(!cs->clist[idx].cred || !kcdb_cred_is_active_cred((khm_handle) cs->clist[idx].cred)) {
+ code = KHM_ERROR_DELETED;
+ if(cs->clist[idx].cred) {
+ kcdb_cred_release((khm_handle) cs->clist[idx].cred);
+ cs->clist[idx].cred = NULL;
+ }
+ }
+ else {
+ kcdb_cred_hold((khm_handle) cs->clist[idx].cred);
+ *cred = cs->clist[idx].cred;
+ }
+ LeaveCriticalSection(&(cs->cs));
+ return code;
+}
+
+KHMEXP khm_int32 KHMAPI
+kcdb_credset_find_filtered(khm_handle credset,
+ khm_int32 idx_start,
+ kcdb_cred_filter_func f,
+ void * rock,
+ khm_handle * cred,
+ khm_int32 * idx)
+{
+ kcdb_credset * cs;
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+ int i;
+
+ if((credset && !kcdb_credset_is_credset(credset)) || !f)
+ return KHM_ERROR_INVALID_PARAM;
+
+ if(credset)
+ cs = (kcdb_credset *) credset;
+ else
+ cs = kcdb_root_credset;
+
+ EnterCriticalSection(&cs->cs);
+
+ if(idx_start < 0)
+ i = 0;
+ else
+ i = idx_start + 1;
+
+#ifdef DEBUG
+ assert(!(cs->flags & KCDB_CREDSET_FLAG_ENUM));
+#endif
+
+ cs->flags |= KCDB_CREDSET_FLAG_ENUM;
+
+ for(; i < cs->nclist; i++) {
+ if(kcdb_cred_is_active_cred(cs->clist[i].cred) &&
+ (*f)((khm_handle) cs->clist[i].cred, 0, rock) != 0)
+ break;
+ }
+
+ cs->flags &= ~KCDB_CREDSET_FLAG_ENUM;
+
+ if(i < cs->nclist) {
+ if (cred) {
+ *cred = (khm_handle) cs->clist[i].cred;
+ kcdb_cred_hold(*cred);
+ }
+
+ if(idx) {
+ *idx = i;
+ }
+ } else {
+ rv = KHM_ERROR_NOT_FOUND;
+ }
+
+ LeaveCriticalSection(&cs->cs);
+
+ return rv;
+}
+
+KHMEXP khm_int32 KHMAPI
+kcdb_credset_find_cred(khm_handle vcredset,
+ khm_handle vcred_src,
+ khm_handle *cred_dest) {
+ kcdb_credset * cs;
+ khm_handle cred = NULL;
+ int idx;
+
+ if (!kcdb_credset_is_credset(vcredset))
+ return KHM_ERROR_INVALID_PARAM;
+
+ if (!kcdb_cred_is_active_cred(vcred_src))
+ return KHM_ERROR_INVALID_PARAM;
+
+ cs = (kcdb_credset *) vcredset;
+
+ EnterCriticalSection(&cs->cs);
+ for (idx = 0; idx < cs->nclist; idx++) {
+ if (cs->clist[idx].cred &&
+ kcdb_creds_is_equal(vcred_src, cs->clist[idx].cred)) {
+ cred = cs->clist[idx].cred;
+ break;
+ }
+ }
+
+ if (cred)
+ kcdb_cred_hold(cred);
+
+ LeaveCriticalSection(&cs->cs);
+
+ if (cred) {
+ if (cred_dest)
+ *cred_dest = cred;
+ else
+ kcdb_cred_release(cred);
+
+ return KHM_ERROR_SUCCESS;
+ } else {
+ return KHM_ERROR_NOT_FOUND;
+ }
+}
+
+KHMEXP khm_int32 KHMAPI
+kcdb_credset_del_cred(khm_handle vcredset,
+ khm_int32 idx)
+{
+ kcdb_credset * cs;
+ khm_int32 code = KHM_ERROR_SUCCESS;
+
+ if(!kcdb_credset_is_credset(vcredset))
+ return KHM_ERROR_INVALID_PARAM;
+
+ cs = (kcdb_credset *) vcredset;
+
+ if (kcdb_credset_is_sealed(cs))
+ return KHM_ERROR_INVALID_OPERATION;
+
+ EnterCriticalSection(&(cs->cs));
+ if(idx < 0 || idx >= cs->nclist) {
+ code = KHM_ERROR_INVALID_PARAM;
+ goto _exit;
+ }
+
+ if(cs->clist[idx].cred)
+ kcdb_cred_release((khm_handle) cs->clist[idx].cred);
+
+ if (!(cs->flags & KCDB_CREDSET_FLAG_ENUM)) {
+
+ if(idx + 1 < cs->nclist)
+ memmove(&(cs->clist[idx]),
+ &(cs->clist[idx+1]),
+ sizeof(kcdb_credset_credref) *
+ (cs->nclist - (idx + 1)));
+
+ cs->nclist--;
+ } else {
+ cs->clist[idx].cred = NULL;
+ }
+
+_exit:
+ LeaveCriticalSection(&(cs->cs));
+
+ return code;
+}
+
+khm_int32
+kcdb_credset_update_cred_ref(khm_handle credset,
+ khm_handle cred)
+{
+ kcdb_credset * cs;
+ khm_int32 code = KHM_ERROR_SUCCESS;
+ int i;
+
+ if(!kcdb_credset_is_credset(credset))
+ return KHM_ERROR_INVALID_PARAM;
+
+ cs = (kcdb_credset *) credset;
+
+ EnterCriticalSection(&(cs->cs));
+
+ for(i=0; i<cs->nclist; i++) {
+ if(cs->clist[i].cred == cred)
+ break;
+ }
+
+ if(i<cs->nclist) {
+ cs->clist[i].version = cs->version;
+ } else {
+ code = KHM_ERROR_NOT_FOUND;
+ }
+
+ LeaveCriticalSection(&(cs->cs));
+ return code;
+}
+
+KHMEXP khm_int32 KHMAPI
+kcdb_credset_del_cred_ref(khm_handle credset,
+ khm_handle cred)
+{
+ kcdb_credset * cs;
+ khm_int32 code = KHM_ERROR_SUCCESS;
+ int i;
+
+ if(!kcdb_credset_is_credset(credset))
+ return KHM_ERROR_INVALID_PARAM;
+
+ cs = (kcdb_credset *) credset;
+
+ if (kcdb_credset_is_sealed(cs))
+ return KHM_ERROR_INVALID_OPERATION;
+
+ EnterCriticalSection(&(cs->cs));
+
+ for(i=0; i<cs->nclist; i++) {
+ if(cs->clist[i].cred == cred)
+ break;
+ }
+
+ if(i<cs->nclist) {
+ code = kcdb_credset_del_cred(credset, i);
+ } else {
+ code = KHM_ERROR_NOT_FOUND;
+ }
+
+ LeaveCriticalSection(&(cs->cs));
+ return code;
+}
+
+KHMEXP khm_int32 KHMAPI
+kcdb_credset_add_cred(khm_handle credset,
+ khm_handle cred,
+ khm_int32 idx)
+{
+ int new_idx;
+ kcdb_credset * cs;
+ khm_int32 code = KHM_ERROR_SUCCESS;
+
+ if(!kcdb_credset_is_credset(credset))
+ return KHM_ERROR_INVALID_PARAM;
+
+ cs = (kcdb_credset *) credset;
+
+ if (kcdb_credset_is_sealed(cs))
+ return KHM_ERROR_INVALID_OPERATION;
+
+ EnterCriticalSection(&(cs->cs));
+
+ kcdb_credset_buf_assert_size(cs, cs->nclist + 1);
+
+ if(idx < 0 || idx > cs->nclist)
+ new_idx = cs->nclist;
+ else if(idx < cs->nclist){
+#ifdef DEBUG
+ assert(!(cs->flags & KCDB_CREDSET_FLAG_ENUM));
+#endif
+ memmove(&(cs->clist[idx+1]), &(cs->clist[idx]), (cs->nclist - idx)*sizeof(cs->clist[0]));
+ new_idx = idx;
+ } else
+ new_idx = idx;
+
+ kcdb_cred_hold(cred);
+
+ cs->clist[new_idx].cred = (kcdb_cred *) cred;
+ cs->clist[new_idx].version = cs->version;
+ cs->nclist++;
+
+ LeaveCriticalSection(&(cs->cs));
+ return code;
+}
+
+KHMEXP khm_int32 KHMAPI
+kcdb_credset_get_size(khm_handle credset,
+ khm_size * size)
+{
+ kcdb_credset * cs;
+
+ *size = 0;
+
+ /* we don't rely on this working, since we can't purge a sealed
+ credset, although we can measure its size. */
+ kcdb_credset_purge(credset);
+
+ if (credset == NULL)
+ cs = kcdb_root_credset;
+ else
+ cs = (kcdb_credset *) credset;
+
+ EnterCriticalSection(&(cs->cs));
+ /* while it may seem a bit redundant to get a lock, it ensures that
+ that the size that we return is consistent with the current state
+ of the credential set */
+ *size = cs->nclist;
+ LeaveCriticalSection(&(cs->cs));
+
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP khm_int32 KHMAPI
+kcdb_credset_purge(khm_handle credset)
+{
+ khm_int32 code = KHM_ERROR_SUCCESS;
+ kcdb_credset * cs;
+ int i,j;
+
+ if(!kcdb_credset_is_credset(credset))
+ return KHM_ERROR_INVALID_PARAM;
+
+ cs = (kcdb_credset *) credset;
+
+ if (kcdb_credset_is_sealed(cs))
+ return KHM_ERROR_INVALID_OPERATION;
+
+ EnterCriticalSection(&(cs->cs));
+
+ /* we can't purge a credset while an enumeration operation is in
+ progress. */
+ if (cs->flags & KCDB_CREDSET_FLAG_ENUM) {
+ code = KHM_ERROR_INVALID_OPERATION;
+ goto _exit;
+ }
+
+ for(i=0,j=0; i < cs->nclist; i++) {
+ if(cs->clist[i].cred) {
+ if(!kcdb_cred_is_active_cred((khm_handle) cs->clist[i].cred)) {
+ kcdb_cred_release((khm_handle) cs->clist[i].cred);
+ } else if(i != j) {
+ cs->clist[j++] = cs->clist[i];
+ } else
+ j++;
+ }
+ }
+ cs->nclist = j;
+
+ _exit:
+ LeaveCriticalSection(&(cs->cs));
+ return code;
+}
+
+KHMEXP khm_int32 KHMAPI
+kcdb_credset_seal(khm_handle credset) {
+ kcdb_credset * cs;
+
+ if (!kcdb_credset_is_credset(credset))
+ return KHM_ERROR_INVALID_PARAM;
+
+ cs = (kcdb_credset *) credset;
+
+ EnterCriticalSection(&cs->cs);
+ cs->seal_count++;
+ LeaveCriticalSection(&cs->cs);
+
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP khm_int32 KHMAPI
+kcdb_credset_unseal(khm_handle credset) {
+ kcdb_credset * cs;
+ khm_int32 rv;
+
+ if (!kcdb_credset_is_credset(credset))
+ return KHM_ERROR_INVALID_PARAM;
+
+ cs = (kcdb_credset *) credset;
+
+ EnterCriticalSection(&cs->cs);
+ if (cs->seal_count > 0) {
+ cs->seal_count--;
+ rv = KHM_ERROR_SUCCESS;
+ } else {
+ rv = KHM_ERROR_INVALID_OPERATION;
+ }
+ LeaveCriticalSection(&cs->cs);
+
+ return rv;
+}
+
+
+/* wrapper for qsort and also parameter gobbling FSM. Access to this
+ function is serialized via cs_credset. */
+int __cdecl
+kcdb_creds_comp_wrapper(const void * a, const void * b)
+{
+ static void * rock = NULL;
+ static kcdb_cred_comp_func comp = NULL;
+
+ if(!b) {
+ rock = (void *) a;
+ return 0;
+ }
+
+ if(!a) {
+ comp = (kcdb_cred_comp_func) b;
+ return 0;
+ }
+
+ return comp((khm_handle) ((kcdb_credset_credref *)a)->cred,
+ (khm_handle) ((kcdb_credset_credref *)b)->cred,
+ rock);
+}
+
+KHMEXP khm_int32 KHMAPI
+kcdb_credset_sort(khm_handle credset,
+ kcdb_cred_comp_func comp,
+ void * rock)
+{
+ khm_int32 code = KHM_ERROR_SUCCESS;
+ kcdb_credset * cs;
+
+ if(!kcdb_credset_is_credset(credset))
+ return KHM_ERROR_INVALID_PARAM;
+
+ cs = (kcdb_credset *) credset;
+
+ if (kcdb_credset_is_sealed(cs))
+ return KHM_ERROR_INVALID_OPERATION;
+
+ EnterCriticalSection(&(cs->cs));
+
+#ifdef DEBUG
+ assert(!(cs->flags & KCDB_CREDSET_FLAG_ENUM));
+#endif
+
+ EnterCriticalSection(&cs_credset);
+
+ kcdb_creds_comp_wrapper(rock, NULL);
+ kcdb_creds_comp_wrapper(NULL, (void *) comp);
+
+ qsort(cs->clist, cs->nclist,
+ sizeof(kcdb_credset_credref), kcdb_creds_comp_wrapper);
+
+ LeaveCriticalSection(&cs_credset);
+
+ LeaveCriticalSection(&(cs->cs));
+ return code;
+}
+
+KHMEXP khm_int32 KHMAPI
+kcdb_cred_comp_generic(khm_handle cred1,
+ khm_handle cred2,
+ void * rock)
+{
+ kcdb_cred_comp_order * o = (kcdb_cred_comp_order *) rock;
+ int i;
+ khm_int32 r = 0;
+ khm_int32 f1, f2;
+ khm_int32 t1, t2;
+ khm_int32 pt;
+
+ for(i=0; i<o->nFields; i++) {
+ if (o->fields[i].order & KCDB_CRED_COMP_INITIAL_FIRST) {
+
+ if (o->fields[i].attrib == KCDB_ATTR_TYPE_NAME ||
+ o->fields[i].attrib == KCDB_ATTR_TYPE) {
+
+ kcdb_cred_get_type(cred1, &t1);
+ kcdb_cred_get_type(cred2, &t2);
+ kcdb_identity_get_type(&pt);
+
+ if (t1 == t2)
+ r = 0;
+ else if (t1 == pt)
+ r = -1;
+ else if (t2 == pt)
+ r = 1;
+ else
+ r = 0;
+
+ } else {
+
+ kcdb_cred_get_flags(cred1, &f1);
+ kcdb_cred_get_flags(cred2, &f2);
+
+ if (((f1 ^ f2) & KCDB_CRED_FLAG_INITIAL) == 0)
+ r = 0;
+ else if (f1 & KCDB_CRED_FLAG_INITIAL)
+ r = -1;
+ else
+ r = 1;
+
+ }
+
+ } else {
+ r = 0;
+ }
+
+ if (r == 0)
+ r = kcdb_creds_comp_attr(cred1,cred2,o->fields[i].attrib);
+
+ if(r != 0) {
+ if(o->fields[i].order & KCDB_CRED_COMP_DECREASING)
+ r = -r;
+ break;
+ }
+ }
+
+ return r;
+}
diff --git a/src/windows/identity/kcreddb/credset.h b/src/windows/identity/kcreddb/credset.h
index cd216fdd25..ba8ec419e1 100644
--- a/src/windows/identity/kcreddb/credset.h
+++ b/src/windows/identity/kcreddb/credset.h
@@ -1,75 +1,75 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#ifndef __KHIMAIRA_KCDB_CREDSET_H
-#define __KHIMAIRA_KCDB_CREDSET_H
-
-/* credset */
-
-typedef struct kcdb_credset_credref_t {
- khm_int32 version;
- kcdb_cred * cred;
-} kcdb_credset_credref;
-
-typedef struct kcdb_credset_t {
- khm_int32 magic;
- khm_int32 flags;
- CRITICAL_SECTION cs;
-
- kcdb_credset_credref * clist;
- khm_int32 nc_clist; /* total capacity */
- khm_int32 nclist; /* current load */
-
- khm_int32 version; /* data version */
-
- khm_int32 seal_count; /* number of seals applied to the
- credset */
-
- struct kcdb_credset_t * next;
- struct kcdb_credset_t * prev;
-} kcdb_credset;
-
-#define KCDB_CREDSET_MAGIC 0x63a84f8b
-
-#define KCDB_CREDSET_FLAG_ROOT 1
-
-/* the credset is in the process of being enumerated */
-#define KCDB_CREDSET_FLAG_ENUM 2
-
-#define kcdb_credset_is_credset(c) ((c) && ((kcdb_credset *)c)->magic == KCDB_CREDSET_MAGIC)
-
-#define kcdb_credset_is_sealed(c) ((c)->seal_count != 0)
-
-#define KCDB_CREDSET_INITIAL_SIZE 256
-#define KCDB_CREDSET_GROWTH_FACTOR 256
-
-void kcdb_credset_init(void);
-void kcdb_credset_exit(void);
-khm_int32 kcdb_credset_update_cred_ref(
- khm_handle credset,
- khm_handle cred);
-
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __KHIMAIRA_KCDB_CREDSET_H
+#define __KHIMAIRA_KCDB_CREDSET_H
+
+/* credset */
+
+typedef struct kcdb_credset_credref_t {
+ khm_int32 version;
+ kcdb_cred * cred;
+} kcdb_credset_credref;
+
+typedef struct kcdb_credset_t {
+ khm_int32 magic;
+ khm_int32 flags;
+ CRITICAL_SECTION cs;
+
+ kcdb_credset_credref * clist;
+ khm_int32 nc_clist; /* total capacity */
+ khm_int32 nclist; /* current load */
+
+ khm_int32 version; /* data version */
+
+ khm_int32 seal_count; /* number of seals applied to the
+ credset */
+
+ struct kcdb_credset_t * next;
+ struct kcdb_credset_t * prev;
+} kcdb_credset;
+
+#define KCDB_CREDSET_MAGIC 0x63a84f8b
+
+#define KCDB_CREDSET_FLAG_ROOT 1
+
+/* the credset is in the process of being enumerated */
+#define KCDB_CREDSET_FLAG_ENUM 2
+
+#define kcdb_credset_is_credset(c) ((c) && ((kcdb_credset *)c)->magic == KCDB_CREDSET_MAGIC)
+
+#define kcdb_credset_is_sealed(c) ((c)->seal_count != 0)
+
+#define KCDB_CREDSET_INITIAL_SIZE 256
+#define KCDB_CREDSET_GROWTH_FACTOR 256
+
+void kcdb_credset_init(void);
+void kcdb_credset_exit(void);
+khm_int32 kcdb_credset_update_cred_ref(
+ khm_handle credset,
+ khm_handle cred);
+
+#endif
diff --git a/src/windows/identity/kcreddb/credtype.c b/src/windows/identity/kcreddb/credtype.c
index 89bd26b85d..b88852cfcb 100644
--- a/src/windows/identity/kcreddb/credtype.c
+++ b/src/windows/identity/kcreddb/credtype.c
@@ -1,408 +1,408 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<kcreddbinternal.h>
-
-CRITICAL_SECTION cs_credtype;
-kcdb_credtype_i ** kcdb_credtype_tbl = NULL;
-kcdb_credtype_i * kcdb_credtypes = NULL;
-
-void kcdb_credtype_init(void)
-{
- InitializeCriticalSection(&cs_credtype);
- kcdb_credtypes = NULL;
-
- kcdb_credtype_tbl = PMALLOC(sizeof(kcdb_credtype_i *) * (KCDB_CREDTYPE_MAX_ID+1));
- ZeroMemory(kcdb_credtype_tbl, sizeof(kcdb_credtype_i *) * (KCDB_CREDTYPE_MAX_ID+1));
-}
-
-void kcdb_credtype_exit(void)
-{
- /*TODO:Free up the cred types */
- PFREE(kcdb_credtype_tbl);
- DeleteCriticalSection(&cs_credtype);
-}
-
-/* Called with cs_credtype held */
-void kcdb_credtype_check_and_delete(khm_int32 id)
-{
- kcdb_credtype_i * ict;
- ict = kcdb_credtype_tbl[id];
- if(!ict)
- return;
-
- if((ict->flags & KCDB_CTI_FLAG_DELETED) &&
- !ict->refcount)
- {
- kcdb_credtype_tbl[id] = NULL;
- LDELETE(&kcdb_credtypes, ict);
-
- PFREE(ict->ct.name);
- if(ict->ct.short_desc)
- PFREE(ict->ct.short_desc);
- if(ict->ct.long_desc)
- PFREE(ict->ct.long_desc);
- if(ict->ct.sub)
- kmq_delete_subscription(ict->ct.sub);
-
- PFREE(ict);
- }
-}
-
-KHMEXP khm_int32 KHMAPI
-kcdb_credtype_register(const kcdb_credtype * type, khm_int32 * new_id)
-{
- khm_int32 id;
- kcdb_credtype_i * ict;
- size_t cb_name;
- size_t cb_short_desc;
- size_t cb_long_desc;
- int i;
-
- if(!type)
- return KHM_ERROR_INVALID_PARAM;
-
- if(type->id >= KCDB_CREDTYPE_MAX_ID)
- return KHM_ERROR_INVALID_PARAM;
-
- if(type->name) {
- if(FAILED(StringCbLength(type->name, KCDB_MAXCB_NAME, &cb_name)))
- return KHM_ERROR_TOO_LONG;
- cb_name += sizeof(wchar_t);
- } else
- return KHM_ERROR_INVALID_PARAM;
-
- if(type->short_desc) {
- if(FAILED(StringCbLength(type->short_desc, KCDB_MAXCB_SHORT_DESC, &cb_short_desc)))
- return KHM_ERROR_TOO_LONG;
- cb_short_desc += sizeof(wchar_t);
- } else
- cb_short_desc = 0;
-
- if(type->long_desc) {
- if(FAILED(StringCbLength(type->long_desc, KCDB_MAXCB_LONG_DESC, &cb_long_desc)))
- return KHM_ERROR_TOO_LONG;
- cb_long_desc += sizeof(wchar_t);
- } else
- cb_long_desc = 0;
-
- if(type->sub == NULL)
- return KHM_ERROR_INVALID_PARAM;
-
- EnterCriticalSection(&cs_credtype);
-
- if(type->id < 0) {
- if(KHM_FAILED(kcdb_credtype_get_next_free_id(&id))) {
- LeaveCriticalSection(&cs_credtype);
- return KHM_ERROR_NO_RESOURCES;
- }
- }
- else
- id = type->id;
-
- if(kcdb_credtype_tbl[id]) {
- LeaveCriticalSection(&cs_credtype);
- return KHM_ERROR_DUPLICATE;
- }
-
- for(i=0;i<=KCDB_CREDTYPE_MAX_ID;i++) {
- if(kcdb_credtype_tbl[i] && !wcscmp(kcdb_credtype_tbl[i]->ct.name, type->name)) {
- LeaveCriticalSection(&cs_credtype);
- return KHM_ERROR_DUPLICATE;
- }
- }
-
- ict = PMALLOC(sizeof(kcdb_credtype_i));
- ZeroMemory(ict, sizeof(kcdb_credtype_i));
-
- ict->ct.name = PMALLOC(cb_name);
- StringCbCopy(ict->ct.name, cb_name, type->name);
-
- if(cb_short_desc) {
- ict->ct.short_desc = PMALLOC(cb_short_desc);
- StringCbCopy(ict->ct.short_desc, cb_short_desc, type->short_desc);
- }
-
- if(cb_long_desc) {
- ict->ct.long_desc = PMALLOC(cb_long_desc);
- StringCbCopy(ict->ct.long_desc, cb_long_desc, type->long_desc);
- }
-
- ict->ct.id = id;
-
- ict->ct.icon = type->icon;
-
- ict->ct.sub = type->sub;
-
- ict->ct.is_equal = type->is_equal;
-
- kcdb_credtype_tbl[id] = ict;
-
- LPUSH(&kcdb_credtypes, ict);
-
- LeaveCriticalSection(&cs_credtype);
-
- kcdb_credtype_post_message(KCDB_OP_INSERT, &(ict->ct));
-
- if (new_id)
- *new_id = id;
-
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP khm_int32 KHMAPI kcdb_credtype_get_info(
- khm_int32 id,
- kcdb_credtype ** type)
-{
- int found = 0;
-
- if(id < 0 || id > KCDB_CREDTYPE_MAX_ID)
- return KHM_ERROR_INVALID_PARAM;
-
- EnterCriticalSection(&cs_credtype);
- if(kcdb_credtype_tbl[id] &&
- !(kcdb_credtype_tbl[id]->flags & KCDB_CTI_FLAG_DELETED))
- {
- found = 1;
- if(type) {
- *type = &(kcdb_credtype_tbl[id]->ct);
- kcdb_credtype_hold(kcdb_credtype_tbl[id]);
- }
- } else {
- if(type)
- *type = NULL;
- }
- LeaveCriticalSection(&cs_credtype);
-
- if(found)
- return KHM_ERROR_SUCCESS;
- else
- return KHM_ERROR_NOT_FOUND;
-}
-
-KHMEXP khm_int32 KHMAPI kcdb_credtype_release_info(kcdb_credtype * type)
-{
- kcdb_credtype_i * ict;
-
- if(!type)
- return KHM_ERROR_INVALID_PARAM;
-
- ict = (kcdb_credtype_i *) type;
- return kcdb_credtype_release(ict);
-}
-
-KHMEXP khm_int32 KHMAPI kcdb_credtype_unregister(khm_int32 id)
-{
- kcdb_credtype_i * ict;
-
- if(id < 0 || id > KCDB_CREDTYPE_MAX_ID)
- return KHM_ERROR_INVALID_PARAM;
-
- EnterCriticalSection(&cs_credtype);
- ict = kcdb_credtype_tbl[id];
- ict->flags |= KCDB_CTI_FLAG_DELETED;
- kcdb_credtype_check_and_delete(id);
- LeaveCriticalSection(&cs_credtype);
-
- //kcdb_credtype_post_message(KCDB_OP_DELETE, &(ict->ct));
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP khm_handle KHMAPI kcdb_credtype_get_sub(khm_int32 id)
-{
- kcdb_credtype_i * t;
- khm_handle s;
-
- if(id < 0 || id > KCDB_CREDTYPE_MAX_ID)
- return NULL;
-
- EnterCriticalSection(&cs_credtype);
- t = kcdb_credtype_tbl[id];
- if(t)
- s = t->ct.sub;
- else
- s = NULL;
- LeaveCriticalSection(&cs_credtype);
-
- return s;
-}
-
-KHMEXP khm_int32 KHMAPI kcdb_credtype_describe(
- khm_int32 id,
- wchar_t * buf,
- khm_size * cbbuf,
- khm_int32 flags)
-{
- size_t s;
- size_t maxs;
- wchar_t * str;
- kcdb_credtype_i * t;
- khm_int32 rv = KHM_ERROR_SUCCESS;
-
- if(!cbbuf || id < 0 || id > KCDB_CREDTYPE_MAX_ID)
- return KHM_ERROR_INVALID_PARAM;
-
- EnterCriticalSection(&cs_credtype);
- t = kcdb_credtype_tbl[id];
- if(t) {
- if(flags & KCDB_TS_SHORT) {
- str = (t->ct.short_desc)?t->ct.short_desc:t->ct.name;
- maxs = (t->ct.short_desc)?KCDB_MAXCB_SHORT_DESC:KCDB_MAXCB_NAME;
- } else {
- str = (t->ct.long_desc)?t->ct.long_desc:((t->ct.short_desc)?t->ct.short_desc:t->ct.name);
- maxs = (t->ct.long_desc)?KCDB_MAXCB_LONG_DESC:((t->ct.short_desc)?KCDB_MAXCB_SHORT_DESC:KCDB_MAXCB_NAME);
- }
- StringCbLength(str, maxs, &s);
- s += sizeof(wchar_t);
- if(!buf || *cbbuf < s) {
- *cbbuf = s;
- rv = KHM_ERROR_TOO_LONG;
- } else {
- StringCbCopy(buf, *cbbuf, str);
- *cbbuf = s;
- }
- } else {
- if(buf && *cbbuf > 0)
- *buf = L'\0';
- *cbbuf = 0;
- rv = KHM_ERROR_NOT_FOUND;
- }
- LeaveCriticalSection(&cs_credtype);
-
- return rv;
-}
-
-
-KHMEXP khm_int32 KHMAPI kcdb_credtype_get_name(
- khm_int32 id,
- wchar_t * buf,
- khm_size * cbbuf)
-{
- size_t s;
- kcdb_credtype_i * t;
- khm_int32 rv = KHM_ERROR_SUCCESS;
-
- if(!cbbuf || id < 0 || id > KCDB_CREDTYPE_MAX_ID)
- return KHM_ERROR_INVALID_PARAM;
-
- EnterCriticalSection(&cs_credtype);
- t = kcdb_credtype_tbl[id];
- if(t) {
- StringCbLength(t->ct.name, KCDB_MAXCB_NAME, &s);
- s += sizeof(wchar_t);
- if(!buf || *cbbuf < s) {
- *cbbuf = s;
- rv = KHM_ERROR_TOO_LONG;
- } else {
- StringCbCopy(buf, *cbbuf, t->ct.name);
- *cbbuf = s;
- }
- } else {
- *cbbuf = 0;
- rv = KHM_ERROR_NOT_FOUND;
- }
- LeaveCriticalSection(&cs_credtype);
-
- return rv;
-}
-
-KHMEXP khm_int32 KHMAPI kcdb_credtype_get_id(
- const wchar_t * name,
- khm_int32 * id)
-{
- int i;
-
- *id = 0;
- if(!name)
- return KHM_ERROR_INVALID_PARAM;
-
- EnterCriticalSection(&cs_credtype);
- for(i=0;i <= KCDB_CREDTYPE_MAX_ID; i++) {
- if(kcdb_credtype_tbl[i] && !wcscmp(name, kcdb_credtype_tbl[i]->ct.name))
- break;
- }
- LeaveCriticalSection(&cs_credtype);
-
- if(i <= KCDB_CREDTYPE_MAX_ID) {
- *id = i;
- return KHM_ERROR_SUCCESS;
- } else
- return KHM_ERROR_NOT_FOUND;
-}
-
-khm_int32 kcdb_credtype_get_next_free_id(khm_int32 * id)
-{
- int i;
-
- EnterCriticalSection(&cs_credtype);
- for(i=0;i <= KCDB_CREDTYPE_MAX_ID; i++) {
- if(!kcdb_credtype_tbl[i])
- break;
- }
- LeaveCriticalSection(&cs_credtype);
-
- if(i <= KCDB_CREDTYPE_MAX_ID) {
- *id = i;
- return KHM_ERROR_SUCCESS;
- } else {
- *id = -1;
- return KHM_ERROR_NO_RESOURCES;
- }
-}
-
-khm_int32 kcdb_credtype_hold(kcdb_credtype_i * ict) {
-
- if(!ict)
- return KHM_ERROR_INVALID_PARAM;
-
- EnterCriticalSection(&cs_credtype);
- ict->refcount++;
- LeaveCriticalSection(&cs_credtype);
- return KHM_ERROR_SUCCESS;
-}
-
-khm_int32 kcdb_credtype_release(kcdb_credtype_i * ict) {
-
- if(!ict)
- return KHM_ERROR_INVALID_PARAM;
-
- EnterCriticalSection(&cs_credtype);
- ict->refcount--;
- kcdb_credtype_check_and_delete(ict->ct.id);
- LeaveCriticalSection(&cs_credtype);
- return KHM_ERROR_SUCCESS;
-}
-
-void kcdb_credtype_msg_completion(kmq_message * m)
-{
- kcdb_credtype_release((kcdb_credtype_i *) m->vparam);
-}
-
-void kcdb_credtype_post_message(khm_int32 op, kcdb_credtype * type)
-{
- kcdb_credtype_hold((kcdb_credtype_i *) type);
- kmq_post_message(KMSG_KCDB, KMSG_KCDB_CREDTYPE, op, (void *) type);
-}
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<kcreddbinternal.h>
+
+CRITICAL_SECTION cs_credtype;
+kcdb_credtype_i ** kcdb_credtype_tbl = NULL;
+kcdb_credtype_i * kcdb_credtypes = NULL;
+
+void kcdb_credtype_init(void)
+{
+ InitializeCriticalSection(&cs_credtype);
+ kcdb_credtypes = NULL;
+
+ kcdb_credtype_tbl = PMALLOC(sizeof(kcdb_credtype_i *) * (KCDB_CREDTYPE_MAX_ID+1));
+ ZeroMemory(kcdb_credtype_tbl, sizeof(kcdb_credtype_i *) * (KCDB_CREDTYPE_MAX_ID+1));
+}
+
+void kcdb_credtype_exit(void)
+{
+ /*TODO:Free up the cred types */
+ PFREE(kcdb_credtype_tbl);
+ DeleteCriticalSection(&cs_credtype);
+}
+
+/* Called with cs_credtype held */
+void kcdb_credtype_check_and_delete(khm_int32 id)
+{
+ kcdb_credtype_i * ict;
+ ict = kcdb_credtype_tbl[id];
+ if(!ict)
+ return;
+
+ if((ict->flags & KCDB_CTI_FLAG_DELETED) &&
+ !ict->refcount)
+ {
+ kcdb_credtype_tbl[id] = NULL;
+ LDELETE(&kcdb_credtypes, ict);
+
+ PFREE(ict->ct.name);
+ if(ict->ct.short_desc)
+ PFREE(ict->ct.short_desc);
+ if(ict->ct.long_desc)
+ PFREE(ict->ct.long_desc);
+ if(ict->ct.sub)
+ kmq_delete_subscription(ict->ct.sub);
+
+ PFREE(ict);
+ }
+}
+
+KHMEXP khm_int32 KHMAPI
+kcdb_credtype_register(const kcdb_credtype * type, khm_int32 * new_id)
+{
+ khm_int32 id;
+ kcdb_credtype_i * ict;
+ size_t cb_name;
+ size_t cb_short_desc;
+ size_t cb_long_desc;
+ int i;
+
+ if(!type)
+ return KHM_ERROR_INVALID_PARAM;
+
+ if(type->id >= KCDB_CREDTYPE_MAX_ID)
+ return KHM_ERROR_INVALID_PARAM;
+
+ if(type->name) {
+ if(FAILED(StringCbLength(type->name, KCDB_MAXCB_NAME, &cb_name)))
+ return KHM_ERROR_TOO_LONG;
+ cb_name += sizeof(wchar_t);
+ } else
+ return KHM_ERROR_INVALID_PARAM;
+
+ if(type->short_desc) {
+ if(FAILED(StringCbLength(type->short_desc, KCDB_MAXCB_SHORT_DESC, &cb_short_desc)))
+ return KHM_ERROR_TOO_LONG;
+ cb_short_desc += sizeof(wchar_t);
+ } else
+ cb_short_desc = 0;
+
+ if(type->long_desc) {
+ if(FAILED(StringCbLength(type->long_desc, KCDB_MAXCB_LONG_DESC, &cb_long_desc)))
+ return KHM_ERROR_TOO_LONG;
+ cb_long_desc += sizeof(wchar_t);
+ } else
+ cb_long_desc = 0;
+
+ if(type->sub == NULL)
+ return KHM_ERROR_INVALID_PARAM;
+
+ EnterCriticalSection(&cs_credtype);
+
+ if(type->id < 0) {
+ if(KHM_FAILED(kcdb_credtype_get_next_free_id(&id))) {
+ LeaveCriticalSection(&cs_credtype);
+ return KHM_ERROR_NO_RESOURCES;
+ }
+ }
+ else
+ id = type->id;
+
+ if(kcdb_credtype_tbl[id]) {
+ LeaveCriticalSection(&cs_credtype);
+ return KHM_ERROR_DUPLICATE;
+ }
+
+ for(i=0;i<=KCDB_CREDTYPE_MAX_ID;i++) {
+ if(kcdb_credtype_tbl[i] && !wcscmp(kcdb_credtype_tbl[i]->ct.name, type->name)) {
+ LeaveCriticalSection(&cs_credtype);
+ return KHM_ERROR_DUPLICATE;
+ }
+ }
+
+ ict = PMALLOC(sizeof(kcdb_credtype_i));
+ ZeroMemory(ict, sizeof(kcdb_credtype_i));
+
+ ict->ct.name = PMALLOC(cb_name);
+ StringCbCopy(ict->ct.name, cb_name, type->name);
+
+ if(cb_short_desc) {
+ ict->ct.short_desc = PMALLOC(cb_short_desc);
+ StringCbCopy(ict->ct.short_desc, cb_short_desc, type->short_desc);
+ }
+
+ if(cb_long_desc) {
+ ict->ct.long_desc = PMALLOC(cb_long_desc);
+ StringCbCopy(ict->ct.long_desc, cb_long_desc, type->long_desc);
+ }
+
+ ict->ct.id = id;
+
+ ict->ct.icon = type->icon;
+
+ ict->ct.sub = type->sub;
+
+ ict->ct.is_equal = type->is_equal;
+
+ kcdb_credtype_tbl[id] = ict;
+
+ LPUSH(&kcdb_credtypes, ict);
+
+ LeaveCriticalSection(&cs_credtype);
+
+ kcdb_credtype_post_message(KCDB_OP_INSERT, &(ict->ct));
+
+ if (new_id)
+ *new_id = id;
+
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP khm_int32 KHMAPI kcdb_credtype_get_info(
+ khm_int32 id,
+ kcdb_credtype ** type)
+{
+ int found = 0;
+
+ if(id < 0 || id > KCDB_CREDTYPE_MAX_ID)
+ return KHM_ERROR_INVALID_PARAM;
+
+ EnterCriticalSection(&cs_credtype);
+ if(kcdb_credtype_tbl[id] &&
+ !(kcdb_credtype_tbl[id]->flags & KCDB_CTI_FLAG_DELETED))
+ {
+ found = 1;
+ if(type) {
+ *type = &(kcdb_credtype_tbl[id]->ct);
+ kcdb_credtype_hold(kcdb_credtype_tbl[id]);
+ }
+ } else {
+ if(type)
+ *type = NULL;
+ }
+ LeaveCriticalSection(&cs_credtype);
+
+ if(found)
+ return KHM_ERROR_SUCCESS;
+ else
+ return KHM_ERROR_NOT_FOUND;
+}
+
+KHMEXP khm_int32 KHMAPI kcdb_credtype_release_info(kcdb_credtype * type)
+{
+ kcdb_credtype_i * ict;
+
+ if(!type)
+ return KHM_ERROR_INVALID_PARAM;
+
+ ict = (kcdb_credtype_i *) type;
+ return kcdb_credtype_release(ict);
+}
+
+KHMEXP khm_int32 KHMAPI kcdb_credtype_unregister(khm_int32 id)
+{
+ kcdb_credtype_i * ict;
+
+ if(id < 0 || id > KCDB_CREDTYPE_MAX_ID)
+ return KHM_ERROR_INVALID_PARAM;
+
+ EnterCriticalSection(&cs_credtype);
+ ict = kcdb_credtype_tbl[id];
+ ict->flags |= KCDB_CTI_FLAG_DELETED;
+ kcdb_credtype_check_and_delete(id);
+ LeaveCriticalSection(&cs_credtype);
+
+ //kcdb_credtype_post_message(KCDB_OP_DELETE, &(ict->ct));
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP khm_handle KHMAPI kcdb_credtype_get_sub(khm_int32 id)
+{
+ kcdb_credtype_i * t;
+ khm_handle s;
+
+ if(id < 0 || id > KCDB_CREDTYPE_MAX_ID)
+ return NULL;
+
+ EnterCriticalSection(&cs_credtype);
+ t = kcdb_credtype_tbl[id];
+ if(t)
+ s = t->ct.sub;
+ else
+ s = NULL;
+ LeaveCriticalSection(&cs_credtype);
+
+ return s;
+}
+
+KHMEXP khm_int32 KHMAPI kcdb_credtype_describe(
+ khm_int32 id,
+ wchar_t * buf,
+ khm_size * cbbuf,
+ khm_int32 flags)
+{
+ size_t s;
+ size_t maxs;
+ wchar_t * str;
+ kcdb_credtype_i * t;
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+
+ if(!cbbuf || id < 0 || id > KCDB_CREDTYPE_MAX_ID)
+ return KHM_ERROR_INVALID_PARAM;
+
+ EnterCriticalSection(&cs_credtype);
+ t = kcdb_credtype_tbl[id];
+ if(t) {
+ if(flags & KCDB_TS_SHORT) {
+ str = (t->ct.short_desc)?t->ct.short_desc:t->ct.name;
+ maxs = (t->ct.short_desc)?KCDB_MAXCB_SHORT_DESC:KCDB_MAXCB_NAME;
+ } else {
+ str = (t->ct.long_desc)?t->ct.long_desc:((t->ct.short_desc)?t->ct.short_desc:t->ct.name);
+ maxs = (t->ct.long_desc)?KCDB_MAXCB_LONG_DESC:((t->ct.short_desc)?KCDB_MAXCB_SHORT_DESC:KCDB_MAXCB_NAME);
+ }
+ StringCbLength(str, maxs, &s);
+ s += sizeof(wchar_t);
+ if(!buf || *cbbuf < s) {
+ *cbbuf = s;
+ rv = KHM_ERROR_TOO_LONG;
+ } else {
+ StringCbCopy(buf, *cbbuf, str);
+ *cbbuf = s;
+ }
+ } else {
+ if(buf && *cbbuf > 0)
+ *buf = L'\0';
+ *cbbuf = 0;
+ rv = KHM_ERROR_NOT_FOUND;
+ }
+ LeaveCriticalSection(&cs_credtype);
+
+ return rv;
+}
+
+
+KHMEXP khm_int32 KHMAPI kcdb_credtype_get_name(
+ khm_int32 id,
+ wchar_t * buf,
+ khm_size * cbbuf)
+{
+ size_t s;
+ kcdb_credtype_i * t;
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+
+ if(!cbbuf || id < 0 || id > KCDB_CREDTYPE_MAX_ID)
+ return KHM_ERROR_INVALID_PARAM;
+
+ EnterCriticalSection(&cs_credtype);
+ t = kcdb_credtype_tbl[id];
+ if(t) {
+ StringCbLength(t->ct.name, KCDB_MAXCB_NAME, &s);
+ s += sizeof(wchar_t);
+ if(!buf || *cbbuf < s) {
+ *cbbuf = s;
+ rv = KHM_ERROR_TOO_LONG;
+ } else {
+ StringCbCopy(buf, *cbbuf, t->ct.name);
+ *cbbuf = s;
+ }
+ } else {
+ *cbbuf = 0;
+ rv = KHM_ERROR_NOT_FOUND;
+ }
+ LeaveCriticalSection(&cs_credtype);
+
+ return rv;
+}
+
+KHMEXP khm_int32 KHMAPI kcdb_credtype_get_id(
+ const wchar_t * name,
+ khm_int32 * id)
+{
+ int i;
+
+ *id = 0;
+ if(!name)
+ return KHM_ERROR_INVALID_PARAM;
+
+ EnterCriticalSection(&cs_credtype);
+ for(i=0;i <= KCDB_CREDTYPE_MAX_ID; i++) {
+ if(kcdb_credtype_tbl[i] && !wcscmp(name, kcdb_credtype_tbl[i]->ct.name))
+ break;
+ }
+ LeaveCriticalSection(&cs_credtype);
+
+ if(i <= KCDB_CREDTYPE_MAX_ID) {
+ *id = i;
+ return KHM_ERROR_SUCCESS;
+ } else
+ return KHM_ERROR_NOT_FOUND;
+}
+
+khm_int32 kcdb_credtype_get_next_free_id(khm_int32 * id)
+{
+ int i;
+
+ EnterCriticalSection(&cs_credtype);
+ for(i=0;i <= KCDB_CREDTYPE_MAX_ID; i++) {
+ if(!kcdb_credtype_tbl[i])
+ break;
+ }
+ LeaveCriticalSection(&cs_credtype);
+
+ if(i <= KCDB_CREDTYPE_MAX_ID) {
+ *id = i;
+ return KHM_ERROR_SUCCESS;
+ } else {
+ *id = -1;
+ return KHM_ERROR_NO_RESOURCES;
+ }
+}
+
+khm_int32 kcdb_credtype_hold(kcdb_credtype_i * ict) {
+
+ if(!ict)
+ return KHM_ERROR_INVALID_PARAM;
+
+ EnterCriticalSection(&cs_credtype);
+ ict->refcount++;
+ LeaveCriticalSection(&cs_credtype);
+ return KHM_ERROR_SUCCESS;
+}
+
+khm_int32 kcdb_credtype_release(kcdb_credtype_i * ict) {
+
+ if(!ict)
+ return KHM_ERROR_INVALID_PARAM;
+
+ EnterCriticalSection(&cs_credtype);
+ ict->refcount--;
+ kcdb_credtype_check_and_delete(ict->ct.id);
+ LeaveCriticalSection(&cs_credtype);
+ return KHM_ERROR_SUCCESS;
+}
+
+void kcdb_credtype_msg_completion(kmq_message * m)
+{
+ kcdb_credtype_release((kcdb_credtype_i *) m->vparam);
+}
+
+void kcdb_credtype_post_message(khm_int32 op, kcdb_credtype * type)
+{
+ kcdb_credtype_hold((kcdb_credtype_i *) type);
+ kmq_post_message(KMSG_KCDB, KMSG_KCDB_CREDTYPE, op, (void *) type);
+}
diff --git a/src/windows/identity/kcreddb/credtype.h b/src/windows/identity/kcreddb/credtype.h
index aa605d7307..3bb0a7d5e8 100644
--- a/src/windows/identity/kcreddb/credtype.h
+++ b/src/windows/identity/kcreddb/credtype.h
@@ -1,55 +1,55 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#ifndef __KHIMAIRA_KCDB_CREDTYPE_H
-#define __KHIMAIRA_KCDB_CREDTYPE_H
-
-/* credtype */
-typedef struct kcdb_credtype_i_t {
- kcdb_credtype ct;
- khm_int32 refcount;
- khm_int32 flags;
-
- struct kcdb_credtype_i_t * next;
- struct kcdb_credtype_i_t * prev;
-} kcdb_credtype_i;
-
-#define KCDB_CTI_FLAG_DELETED 8
-
-extern CRITICAL_SECTION cs_credtype;
-extern kcdb_credtype_i * kcdb_credtypes;
-extern kcdb_credtype_i ** kcdb_credtype_tbl;
-
-void kcdb_credtype_init(void);
-void kcdb_credtype_exit(void);
-void kcdb_credtype_check_and_delete(khm_int32 id);
-khm_int32 kcdb_credtype_hold(kcdb_credtype_i * ict);
-khm_int32 kcdb_credtype_release(kcdb_credtype_i * ict);
-void kcdb_credtype_msg_completion(kmq_message * m);
-void kcdb_credtype_post_message(khm_int32 op, kcdb_credtype * type);
-khm_int32 kcdb_credtype_get_next_free_id(khm_int32 * id);
-
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __KHIMAIRA_KCDB_CREDTYPE_H
+#define __KHIMAIRA_KCDB_CREDTYPE_H
+
+/* credtype */
+typedef struct kcdb_credtype_i_t {
+ kcdb_credtype ct;
+ khm_int32 refcount;
+ khm_int32 flags;
+
+ struct kcdb_credtype_i_t * next;
+ struct kcdb_credtype_i_t * prev;
+} kcdb_credtype_i;
+
+#define KCDB_CTI_FLAG_DELETED 8
+
+extern CRITICAL_SECTION cs_credtype;
+extern kcdb_credtype_i * kcdb_credtypes;
+extern kcdb_credtype_i ** kcdb_credtype_tbl;
+
+void kcdb_credtype_init(void);
+void kcdb_credtype_exit(void);
+void kcdb_credtype_check_and_delete(khm_int32 id);
+khm_int32 kcdb_credtype_hold(kcdb_credtype_i * ict);
+khm_int32 kcdb_credtype_release(kcdb_credtype_i * ict);
+void kcdb_credtype_msg_completion(kmq_message * m);
+void kcdb_credtype_post_message(khm_int32 op, kcdb_credtype * type);
+khm_int32 kcdb_credtype_get_next_free_id(khm_int32 * id);
+
+#endif
diff --git a/src/windows/identity/kcreddb/identity.c b/src/windows/identity/kcreddb/identity.c
index 5d76384d9e..e14ceec4c2 100644
--- a/src/windows/identity/kcreddb/identity.c
+++ b/src/windows/identity/kcreddb/identity.c
@@ -1,1599 +1,1599 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- * Copyright (c) 2007 Secure Endpoints Inc.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<kcreddbinternal.h>
-#include<assert.h>
-
-static CRITICAL_SECTION cs_ident;
-hashtable * kcdb_identities_namemap = NULL;
-khm_int32 kcdb_n_identities = 0;
-kcdb_identity * kcdb_identities = NULL;
-kcdb_identity * kcdb_def_identity = NULL;
-khm_handle kcdb_ident_sub = NULL; /* identity provider */
-khm_int32 kcdb_ident_cred_type = KCDB_CREDTYPE_INVALID;
-/* primary credentials type */
-khm_ui_4 kcdb_ident_refresh_cycle = 0;
-khm_boolean kcdb_checked_config = FALSE;
-khm_boolean kcdb_checking_config = FALSE;
-
-KHMEXP khm_boolean KHMAPI
-kcdb_identity_is_equal(khm_handle identity1,
- khm_handle identity2)
-{
-
- return (identity1 == identity2);
-
-}
-
-KHMEXP khm_int32 KHMAPI
-kcdb_identity_set_provider(khm_handle sub)
-{
- EnterCriticalSection(&cs_ident);
- if (sub != kcdb_ident_sub) {
- if(kcdb_ident_sub != NULL) {
- kmq_send_sub_msg(kcdb_ident_sub,
- KMSG_IDENT,
- KMSG_IDENT_EXIT,
- 0,
- 0);
- kmq_delete_subscription(kcdb_ident_sub);
- }
- kcdb_ident_sub = sub;
-
- if (kcdb_ident_sub)
- kmq_send_sub_msg(kcdb_ident_sub,
- KMSG_IDENT,
- KMSG_IDENT_INIT,
- 0,
- 0);
- }
- LeaveCriticalSection(&cs_ident);
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP khm_int32 KHMAPI
-kcdb_identity_get_provider(khm_handle * sub)
-{
- khm_int32 rv = KHM_ERROR_SUCCESS;
-
- EnterCriticalSection(&cs_ident);
- if(kcdb_ident_sub != NULL)
- rv = KHM_ERROR_SUCCESS;
- else
- rv = KHM_ERROR_NOT_FOUND;
- if(sub != NULL)
- *sub = kcdb_ident_sub;
- LeaveCriticalSection(&cs_ident);
-
- return rv;
-}
-
-KHMEXP khm_int32 KHMAPI
-kcdb_identity_set_type(khm_int32 cred_type)
-{
- EnterCriticalSection(&cs_ident);
- kcdb_ident_cred_type = cred_type;
- LeaveCriticalSection(&cs_ident);
-
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP khm_int32 KHMAPI
-kcdb_identity_get_type(khm_int32 * ptype)
-{
- if (!ptype)
- return KHM_ERROR_INVALID_PARAM;
-
- EnterCriticalSection(&cs_ident);
- *ptype = kcdb_ident_cred_type;
- LeaveCriticalSection(&cs_ident);
-
- if (*ptype >= 0)
- return KHM_ERROR_SUCCESS;
- else
- return KHM_ERROR_NOT_FOUND;
-}
-
-/* message completion routine */
-void
-kcdbint_ident_msg_completion(kmq_message * m) {
- kcdb_identity_release(m->vparam);
-}
-
-void
-kcdbint_ident_add_ref(const void * key, void * vid) {
- /* References in the hashtable are not refcounted */
-
- // kcdb_identity_hold(vid);
-}
-
-void
-kcdbint_ident_del_ref(const void * key, void * vid) {
- /* References in the hashtable are not refcounted */
-
- // kcdb_identity_release(vid);
-}
-
-void
-kcdbint_ident_init(void) {
- InitializeCriticalSection(&cs_ident);
- kcdb_identities_namemap = hash_new_hashtable(
- KCDB_IDENT_HASHTABLE_SIZE,
- hash_string,
- hash_string_comp,
- kcdbint_ident_add_ref,
- kcdbint_ident_del_ref);
-}
-
-void
-kcdbint_ident_exit(void) {
- EnterCriticalSection(&cs_ident);
- hash_del_hashtable(kcdb_identities_namemap);
- LeaveCriticalSection(&cs_ident);
- DeleteCriticalSection(&cs_ident);
-}
-
-/* NOT called with cs_ident held */
-KHMEXP khm_boolean KHMAPI
-kcdb_identity_is_valid_name(const wchar_t * name)
-{
- khm_int32 rv;
-
- /* special case. Note since the string we are comparing with is
- of a known length we don't need to check the length of name. */
- if (!wcscmp(name, L"_Schema"))
- return FALSE;
-
- rv = kcdb_identpro_validate_name(name);
-
- if(rv == KHM_ERROR_NO_PROVIDER ||
- rv == KHM_ERROR_NOT_IMPLEMENTED)
- return TRUE;
- else
- return KHM_SUCCEEDED(rv);
-}
-
-KHMEXP khm_int32 KHMAPI
-kcdb_identity_create(const wchar_t *name,
- khm_int32 flags,
- khm_handle * result) {
- kcdb_identity * id = NULL;
- kcdb_identity * id_tmp = NULL;
- size_t namesize;
-
- if(!result || !name)
- return KHM_ERROR_INVALID_PARAM;
-
- *result = NULL;
-
- /* is it there already? */
- EnterCriticalSection(&cs_ident);
- id = hash_lookup(kcdb_identities_namemap, (void *) name);
- if(id)
- kcdb_identity_hold((khm_handle) id);
- LeaveCriticalSection(&cs_ident);
-
- if(id) {
- *result = (khm_handle) id;
- return KHM_ERROR_SUCCESS;
- } else if(!(flags & KCDB_IDENT_FLAG_CREATE)) {
- return KHM_ERROR_NOT_FOUND;
- }
-
- flags &= ~KCDB_IDENT_FLAG_CREATE;
-
- /* nope. create it */
- if((flags & ~KCDB_IDENT_FLAGMASK_RDWR) ||
- (flags & (KCDB_IDENT_FLAG_DEFAULT |
- KCDB_IDENT_FLAG_SEARCHABLE |
- KCDB_IDENT_FLAG_STICKY))) {
- /* can't specify this flag in create */
- return KHM_ERROR_INVALID_PARAM;
- }
-
- if(!kcdb_identity_is_valid_name(name)) {
- return KHM_ERROR_INVALID_NAME;
- }
-
- /* we expect the following will succeed since the above
- test passed */
- StringCbLength(name, KCDB_IDENT_MAXCB_NAME, &namesize);
- namesize += sizeof(wchar_t);
-
- id = PMALLOC(sizeof(kcdb_identity));
- ZeroMemory(id, sizeof(kcdb_identity));
- id->magic = KCDB_IDENT_MAGIC;
- id->name = PMALLOC(namesize);
- StringCbCopy(id->name, namesize, name);
-
- id->flags = (flags & KCDB_IDENT_FLAGMASK_RDWR);
- id->flags |= KCDB_IDENT_FLAG_ACTIVE | KCDB_IDENT_FLAG_EMPTY;
- LINIT(id);
-
- EnterCriticalSection(&cs_ident);
- id_tmp = hash_lookup(kcdb_identities_namemap, (void *) id->name);
- if(id_tmp) {
- /* lost a race */
- kcdb_identity_hold((khm_handle) id_tmp);
- *result = (khm_handle) id_tmp;
-
- PFREE(id->name);
- PFREE(id);
-
- id = NULL;
- } else {
- khm_handle h_cfg;
-
- kcdb_identity_hold((khm_handle) id);
- hash_add(kcdb_identities_namemap,
- (void *) id->name,
- (void *) id);
- LPUSH(&kcdb_identities, id);
-
- if(KHM_SUCCEEDED(kcdb_identity_get_config((khm_handle) id,
- 0,
- &h_cfg))) {
- /* don't need to set the KCDB_IDENT_FLAG_CONFIG flags
- since kcdb_identity_get_config() sets it for us. */
- khm_int32 sticky;
-
- if (KHM_SUCCEEDED(khc_read_int32(h_cfg, L"Sticky", &sticky)) &&
- sticky) {
- id->flags |= KCDB_IDENT_FLAG_STICKY;
- }
-
- khc_close_space(h_cfg);
- }
- }
- LeaveCriticalSection(&cs_ident);
-
- if(id != NULL) {
- *result = (khm_handle) id;
-
- kcdb_identpro_notify_create((khm_handle) id);
-
- kcdbint_ident_post_message(KCDB_OP_INSERT, id);
- }
-
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP khm_int32 KHMAPI
-kcdb_identity_delete(khm_handle vid) {
- kcdb_identity * id;
- khm_int32 code = KHM_ERROR_SUCCESS;
-
- EnterCriticalSection(&cs_ident);
- if(!kcdb_is_identity(vid)) {
- code = KHM_ERROR_INVALID_PARAM;
- goto _exit;
- }
-
- id = (kcdb_identity *) vid;
-
- if (kcdb_is_active_identity(vid)) {
-
- id->flags &= ~KCDB_IDENT_FLAG_ACTIVE;
-
- hash_del(kcdb_identities_namemap, (void *) id->name);
-
- LeaveCriticalSection(&cs_ident);
-
- kcdbint_ident_post_message(KCDB_OP_DELETE, id);
-
- /* Once everybody finishes dealing with the identity deletion,
- we will get called again. */
- return KHM_ERROR_SUCCESS;
- } else if (id->refcount == 0) {
- /* If the identity is not active, it is not in the hashtable
- either */
- LDELETE(&kcdb_identities, id);
-
- if (id->name)
- PFREE(id->name);
- PFREE(id);
- }
- /* else, we have an identity that is not active, but has
- outstanding references. We have to wait until those references
- are freed. Once they are released, kcdb_identity_delete() will
- be called again. */
-
- _exit:
- LeaveCriticalSection(&cs_ident);
-
- return code;
-}
-
-KHMEXP khm_int32 KHMAPI
-kcdb_identity_set_flags(khm_handle vid,
- khm_int32 flag,
- khm_int32 mask) {
- kcdb_identity * id;
- khm_int32 oldflags;
- khm_int32 newflags;
- khm_int32 delta = 0;
- khm_int32 rv;
-
- if (mask == 0)
- return KHM_ERROR_SUCCESS;
-
- if(!kcdb_is_active_identity(vid))
- return KHM_ERROR_INVALID_PARAM;
-
- id = (kcdb_identity *) vid;
-
- flag &= mask;
-
- if((mask & ~KCDB_IDENT_FLAGMASK_RDWR) ||
- ((flag & KCDB_IDENT_FLAG_INVALID) && (flag & KCDB_IDENT_FLAG_VALID)))
- return KHM_ERROR_INVALID_PARAM;
-
- if((mask & KCDB_IDENT_FLAG_DEFAULT) &&
- (flag & KCDB_IDENT_FLAG_DEFAULT)) {
- /* kcdb_identity_set_default already does checking for
- redundant transitions */
- rv = kcdb_identity_set_default(vid);
-
- if(KHM_FAILED(rv))
- return rv;
-
- mask &= ~KCDB_IDENT_FLAG_DEFAULT;
- flag &= ~KCDB_IDENT_FLAG_DEFAULT;
- }
-
- EnterCriticalSection(&cs_ident);
-
- if(mask & KCDB_IDENT_FLAG_SEARCHABLE) {
- if(!(flag & KCDB_IDENT_FLAG_SEARCHABLE)) {
- if(id->flags & KCDB_IDENT_FLAG_SEARCHABLE) {
- LeaveCriticalSection(&cs_ident);
- rv = kcdb_identpro_set_searchable(vid, FALSE);
- EnterCriticalSection(&cs_ident);
- if(rv == KHM_ERROR_NO_PROVIDER ||
- KHM_SUCCEEDED(rv)) {
- id->flags &= ~KCDB_IDENT_FLAG_SEARCHABLE;
- delta |= KCDB_IDENT_FLAG_SEARCHABLE;
- }
- }
- } else {
- if(!(id->flags & KCDB_IDENT_FLAG_SEARCHABLE)) {
- LeaveCriticalSection(&cs_ident);
- rv = kcdb_identpro_set_searchable(vid, TRUE);
- EnterCriticalSection(&cs_ident);
- if(rv == KHM_ERROR_NO_PROVIDER ||
- KHM_SUCCEEDED(rv)) {
- id->flags |= KCDB_IDENT_FLAG_SEARCHABLE;
- delta |= KCDB_IDENT_FLAG_SEARCHABLE;
- }
- }
- }
-
- flag &= ~KCDB_IDENT_FLAG_SEARCHABLE;
- mask &= ~KCDB_IDENT_FLAG_SEARCHABLE;
- }
-
- if (mask & KCDB_IDENT_FLAG_STICKY) {
- if ((flag ^ id->flags) & KCDB_IDENT_FLAG_STICKY) {
- khm_handle h_conf;
-
- if (KHM_SUCCEEDED(kcdb_identity_get_config(vid,
- KHM_FLAG_CREATE,
- &h_conf))) {
- khc_write_int32(h_conf, L"Sticky",
- !!(flag & KCDB_IDENT_FLAG_STICKY));
- khc_close_space(h_conf);
- }
-
- id->flags =
- ((id->flags & ~KCDB_IDENT_FLAG_STICKY) |
- (flag & KCDB_IDENT_FLAG_STICKY));
-
- delta |= KCDB_IDENT_FLAG_STICKY;
- }
-
- flag &= ~KCDB_IDENT_FLAG_STICKY;
- mask &= ~KCDB_IDENT_FLAG_STICKY;
- }
-
- /* deal with every other flag */
-
- oldflags = id->flags;
-
- id->flags = (id->flags & ~mask) | (flag & mask);
-
- if (flag & KCDB_IDENT_FLAG_VALID) {
- id->flags &= ~(KCDB_IDENT_FLAG_INVALID | KCDB_IDENT_FLAG_UNKNOWN);
- }
- if (flag & KCDB_IDENT_FLAG_INVALID) {
- id->flags &= ~(KCDB_IDENT_FLAG_VALID | KCDB_IDENT_FLAG_UNKNOWN);
- }
-
- newflags = id->flags;
-
- LeaveCriticalSection(&cs_ident);
-
- delta |= newflags ^ oldflags;
-
- if((delta & KCDB_IDENT_FLAG_HIDDEN)) {
- kcdbint_ident_post_message(
- (newflags & KCDB_IDENT_FLAG_HIDDEN)?KCDB_OP_HIDE:KCDB_OP_UNHIDE,
- vid);
- }
-
- if((delta & KCDB_IDENT_FLAG_SEARCHABLE)) {
- kcdbint_ident_post_message(
- (newflags & KCDB_IDENT_FLAG_SEARCHABLE)?KCDB_OP_SETSEARCH:KCDB_OP_UNSETSEARCH,
- vid);
- }
-
- if(delta != 0)
- kcdbint_ident_post_message(KCDB_OP_MODIFY, vid);
-
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP khm_int32 KHMAPI
-kcdb_identity_get_flags(khm_handle vid,
- khm_int32 * flags) {
- kcdb_identity * id;
-
- *flags = 0;
-
- if(!kcdb_is_active_identity(vid))
- return KHM_ERROR_INVALID_PARAM;
-
- id = (kcdb_identity *) vid;
-
- EnterCriticalSection(&cs_ident);
- *flags = id->flags;
- LeaveCriticalSection(&cs_ident);
-
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP khm_int32 KHMAPI
-kcdb_identity_get_name(khm_handle vid,
- wchar_t * buffer,
- khm_size * pcbsize) {
- size_t namesize;
- kcdb_identity * id;
-
- if(!kcdb_is_active_identity(vid) || !pcbsize)
- return KHM_ERROR_INVALID_PARAM;
-
- id = (kcdb_identity *) vid;
-
- if(FAILED(StringCbLength(id->name, KCDB_IDENT_MAXCB_NAME, &namesize)))
- return KHM_ERROR_UNKNOWN;
-
- namesize += sizeof(wchar_t);
-
- if(!buffer || namesize > *pcbsize) {
- *pcbsize = namesize;
- return KHM_ERROR_TOO_LONG;
- }
-
- StringCbCopy(buffer, *pcbsize, id->name);
- *pcbsize = namesize;
-
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP khm_int32 KHMAPI
-kcdb_identity_get_default(khm_handle * pvid) {
- khm_handle def;
-
- if (pvid == NULL)
- return KHM_ERROR_INVALID_PARAM;
-
- EnterCriticalSection(&cs_ident);
- def = kcdb_def_identity;
- if (def != NULL)
- kcdb_identity_hold(def);
- LeaveCriticalSection(&cs_ident);
-
- *pvid = def;
-
- if (def != NULL)
- return KHM_ERROR_SUCCESS;
- else
- return KHM_ERROR_NOT_FOUND;
-}
-
-static khm_int32
-kcdbint_ident_set_default(khm_handle vid,
- khm_boolean invoke_identpro) {
- kcdb_identity * new_def;
- kcdb_identity * old_def;
- khm_int32 rv;
-
- if (vid != NULL && !kcdb_is_active_identity(vid))
- return KHM_ERROR_INVALID_PARAM;
-
- new_def = (kcdb_identity *)vid;
-
- if (new_def != NULL && (new_def->flags & KCDB_IDENT_FLAG_DEFAULT))
- return KHM_ERROR_SUCCESS;
-
- if ((new_def == NULL && kcdb_def_identity == NULL) ||
- (new_def == kcdb_def_identity))
- return KHM_ERROR_SUCCESS;
-
- /* first check with the identity provider if this operation
- is permitted. */
- if (invoke_identpro) {
- rv = kcdb_identpro_set_default(vid);
- if(rv != KHM_ERROR_NO_PROVIDER && KHM_FAILED(rv))
- return rv;
- }
-
- EnterCriticalSection(&cs_ident);
-
- old_def = kcdb_def_identity;
- kcdb_def_identity = new_def;
-
- if(old_def != new_def) {
- if(old_def) {
- old_def->flags &= ~KCDB_IDENT_FLAG_DEFAULT;
- kcdb_identity_release((khm_handle) old_def);
- }
-
- if(new_def) {
- new_def->flags |= KCDB_IDENT_FLAG_DEFAULT;
- kcdb_identity_hold((khm_handle) new_def);
- }
-
- LeaveCriticalSection(&cs_ident);
-
- /* if (invoke_identpro) */
- kcdbint_ident_post_message(KCDB_OP_NEW_DEFAULT, new_def);
- } else {
- LeaveCriticalSection(&cs_ident);
- }
-
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP khm_int32 KHMAPI
-kcdb_identity_set_default(khm_handle vid) {
- return kcdbint_ident_set_default(vid, TRUE);
-}
-
-KHMEXP khm_int32 KHMAPI
-kcdb_identity_set_default_int(khm_handle vid) {
- return kcdbint_ident_set_default(vid, FALSE);
-}
-
-KHMEXP khm_int32 KHMAPI
-kcdb_identity_get_config(khm_handle vid,
- khm_int32 flags,
- khm_handle * result) {
- khm_handle hkcdb;
- khm_handle hidents = NULL;
- khm_handle hident = NULL;
- khm_int32 rv;
- kcdb_identity * id;
-
- if(kcdb_is_active_identity(vid)) {
- id = (kcdb_identity *) vid;
- } else {
- return KHM_ERROR_INVALID_PARAM;
- }
-
- hkcdb = kcdb_get_config();
- if(hkcdb) {
- rv = khc_open_space(hkcdb, L"Identity", 0, &hidents);
- if(KHM_FAILED(rv))
- goto _exit;
-
- rv = khc_open_space(hidents,
- id->name,
- flags | KCONF_FLAG_NOPARSENAME,
- &hident);
-
- if(KHM_FAILED(rv)) {
- khm_int32 oldflags;
- EnterCriticalSection(&cs_ident);
- oldflags = id->flags;
- id->flags &= ~KCDB_IDENT_FLAG_CONFIG;
- LeaveCriticalSection(&cs_ident);
- if (oldflags & KCDB_IDENT_FLAG_CONFIG)
- kcdbint_ident_post_message(KCDB_OP_DELCONFIG, id);
- goto _exit;
- }
-
- EnterCriticalSection(&cs_ident);
- id->flags |= KCDB_IDENT_FLAG_CONFIG;
- LeaveCriticalSection(&cs_ident);
-
- *result = hident;
- } else
- rv = KHM_ERROR_UNKNOWN;
-
-_exit:
- if(hidents)
- khc_close_space(hidents);
- if(hkcdb)
- khc_close_space(hkcdb);
- return rv;
-}
-
-/*! \note cs_ident must be available. */
-void
-kcdbint_ident_post_message(khm_int32 op, kcdb_identity * id) {
- kcdb_identity_hold(id);
- kmq_post_message(KMSG_KCDB, KMSG_KCDB_IDENT, op, (void *) id);
-}
-
-/*! \note cs_ident must be available. */
-KHMEXP khm_int32 KHMAPI
-kcdb_identity_hold(khm_handle vid) {
- kcdb_identity * id;
-
- EnterCriticalSection(&cs_ident);
- if(kcdb_is_active_identity(vid)) {
- id = vid;
- id->refcount++;
- } else {
- LeaveCriticalSection(&cs_ident);
- return KHM_ERROR_INVALID_PARAM;
- }
- LeaveCriticalSection(&cs_ident);
- return ERROR_SUCCESS;
-}
-
-/*! \note cs_ident must be available. */
-KHMEXP khm_int32 KHMAPI
-kcdb_identity_release(khm_handle vid) {
- kcdb_identity * id;
- khm_int32 refcount;
-
- EnterCriticalSection(&cs_ident);
- if(kcdb_is_identity(vid)) {
- id = vid;
- refcount = --id->refcount;
- if(refcount == 0) {
- /* We only delete identities which do not have a
- configuration. */
- if (id->refcount == 0 &&
- !(id->flags & KCDB_IDENT_FLAG_CONFIG))
- kcdb_identity_delete(vid);
- }
- } else {
- LeaveCriticalSection(&cs_ident);
- return KHM_ERROR_INVALID_PARAM;
- }
- LeaveCriticalSection(&cs_ident);
- return ERROR_SUCCESS;
-}
-
-struct kcdb_idref_result {
- kcdb_identity * ident;
- khm_int32 flags;
- khm_size count;
-};
-
-static khm_int32 KHMAPI
-kcdbint_idref_proc(khm_handle cred, void * r) {
- khm_handle vid;
- struct kcdb_idref_result *result;
- khm_int32 flags;
-
- result = (struct kcdb_idref_result *) r;
-
- if (KHM_SUCCEEDED(kcdb_cred_get_identity(cred, &vid))) {
- if (result->ident == (kcdb_identity *) vid) {
-
- result->count++;
- kcdb_cred_get_flags(cred, &flags);
-
- if (flags & KCDB_CRED_FLAG_RENEWABLE) {
- result->flags |= KCDB_IDENT_FLAG_CRED_RENEW;
- if (flags & KCDB_CRED_FLAG_INITIAL) {
- result->flags |= KCDB_IDENT_FLAG_RENEWABLE;
- }
- }
-
- if (flags & KCDB_CRED_FLAG_EXPIRED) {
- result->flags |= KCDB_IDENT_FLAG_CRED_EXP;
- if (flags & KCDB_CRED_FLAG_INITIAL) {
- result->flags |= KCDB_IDENT_FLAG_EXPIRED;
- }
- }
-
- if (flags & KCDB_CRED_FLAG_INITIAL) {
- result->flags |= KCDB_IDENT_FLAG_VALID;
- }
- }
-
- kcdb_identity_release(vid);
- }
-
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP khm_int32 KHMAPI
-kcdb_identity_refresh(khm_handle vid) {
- kcdb_identity * ident;
- khm_int32 code = KHM_ERROR_SUCCESS;
- struct kcdb_idref_result result;
-
- EnterCriticalSection(&cs_ident);
-
- if (!kcdb_is_active_identity(vid)) {
- code = KHM_ERROR_INVALID_PARAM;
- goto _exit;
- }
-
- ident = (kcdb_identity *) vid;
-
- result.ident = ident;
- result.flags = 0;
- result.count = 0;
-
- LeaveCriticalSection(&cs_ident);
-
- kcdb_credset_apply(NULL, kcdbint_idref_proc, &result);
-
- if (result.count == 0)
- result.flags |= KCDB_IDENT_FLAG_EMPTY;
-
- kcdb_identity_set_flags(vid, result.flags,
- KCDB_IDENT_FLAGMASK_RDWR &
- ~(KCDB_IDENT_FLAG_DEFAULT |
- KCDB_IDENT_FLAG_SEARCHABLE |
- KCDB_IDENT_FLAG_STICKY));
-
- EnterCriticalSection(&cs_ident);
- ident->refresh_cycle = kcdb_ident_refresh_cycle;
-
- _exit:
- LeaveCriticalSection(&cs_ident);
-
- if (code == 0)
- code = kcdb_identpro_update(vid);
-
- return code;
-}
-
-KHMEXP khm_int32 KHMAPI
-kcdb_identity_refresh_all(void) {
- kcdb_identity * ident;
- kcdb_identity * next;
- khm_int32 code = KHM_ERROR_SUCCESS;
- int hit_count;
-
- EnterCriticalSection(&cs_ident);
-
- kcdb_ident_refresh_cycle++;
-
- /* The do-while loop is here to account for race conditions. We
- release cs_ident in the for loop, so we don't actually have a
- guarantee that we traversed the whole identity list at the end.
- We repeat until all the identities are uptodate. */
-
- do {
- hit_count = 0;
-
- for (ident = kcdb_identities;
- ident != NULL;
- ident = next) {
-
- if (!kcdb_is_active_identity(ident) ||
- ident->refresh_cycle == kcdb_ident_refresh_cycle) {
- next = LNEXT(ident);
- continue;
- }
-
- kcdb_identity_hold((khm_handle) ident);
-
- LeaveCriticalSection(&cs_ident);
-
- kcdb_identity_refresh((khm_handle) ident);
-
- EnterCriticalSection(&cs_ident);
-
- next = LNEXT(ident);
- kcdb_identity_release((khm_handle) ident);
-
- hit_count++;
- }
-
- } while (hit_count > 0);
-
- LeaveCriticalSection(&cs_ident);
-
- return code;
-}
-
-/*****************************************/
-/* Custom property functions */
-
-KHMEXP khm_int32 KHMAPI
-kcdb_identity_set_attr(khm_handle vid,
- khm_int32 attr_id,
- void * buffer,
- khm_size cbbuf)
-{
- kcdb_identity * id = NULL;
- kcdb_attrib * attrib = NULL;
- kcdb_type * type = NULL;
- khm_size slot;
- khm_size cbdest;
- khm_int32 code = KHM_ERROR_SUCCESS;
-
- EnterCriticalSection(&cs_ident);
- if(!kcdb_is_active_identity(vid)) {
- LeaveCriticalSection(&cs_ident);
- return KHM_ERROR_INVALID_PARAM;
- }
-
- id = (kcdb_identity *) vid;
-
- if(!(id->flags & KCDB_IDENT_FLAG_ATTRIBS)) {
- kcdb_buf_new(&id->buf, KCDB_BUF_DEFAULT);
- id->flags |= KCDB_IDENT_FLAG_ATTRIBS;
- }
-
- if(KHM_FAILED(kcdb_attrib_get_info(attr_id, &attrib))) {
- LeaveCriticalSection(&cs_ident);
- return KHM_ERROR_INVALID_PARAM;
- }
-
-#if 0
- /* actually, even if an attribute is computed, we still allow
- those values to be set. This is because computing values
- is only for credentials. If a computed value is used as a
- property in any other object, it is treated as a regular value
- */
- if(attrib->flags & KCDB_ATTR_FLAG_COMPUTED)
- {
- LeaveCriticalSection(&cs_ident);
- kcdb_attrib_release_info(attrib);
- return KHM_ERROR_INVALID_OPERATION;
- }
-#endif
-
- if (buffer == NULL) {
- /* we are removing a value */
- slot = kcdb_buf_slot_by_id(&id->buf, attr_id);
- if (slot != KCDB_BUF_INVALID_SLOT &&
- kcdb_buf_exist(&id->buf, slot))
- kcdb_buf_alloc(&id->buf, slot, attr_id, 0);
- code = KHM_ERROR_SUCCESS;
- goto _exit;
- }
-
- if(KHM_FAILED(kcdb_type_get_info(attrib->type, &type))) {
- LeaveCriticalSection(&cs_ident);
- kcdb_attrib_release_info(attrib);
- return KHM_ERROR_INVALID_PARAM;
- }
-
- if(!(type->isValid(buffer,cbbuf))) {
- code = KHM_ERROR_TYPE_MISMATCH;
- goto _exit;
- }
-
- if((type->dup(buffer, cbbuf, NULL, &cbdest)) != KHM_ERROR_TOO_LONG) {
- code = KHM_ERROR_INVALID_PARAM;
- goto _exit;
- }
-
- kcdb_buf_alloc(&id->buf, KCDB_BUF_APPEND, attr_id, cbdest);
- slot = kcdb_buf_slot_by_id(&id->buf, attr_id);
- if(slot == KCDB_BUF_INVALID_SLOT || !kcdb_buf_exist(&id->buf, slot)) {
- code = KHM_ERROR_NO_RESOURCES;
- goto _exit;
- }
-
- if(KHM_FAILED(code =
- type->dup(buffer, cbbuf, kcdb_buf_get(&id->buf, slot), &cbdest)))
- {
- kcdb_buf_alloc(&id->buf, slot, attr_id, 0);
- goto _exit;
- }
-
- kcdb_buf_set_value_flag(&id->buf, slot);
-
-_exit:
- LeaveCriticalSection(&cs_ident);
-
- if(attrib)
- kcdb_attrib_release_info(attrib);
- if(type)
- kcdb_type_release_info(type);
-
- return code;
-}
-
-KHMEXP khm_int32 KHMAPI
-kcdb_identity_set_attrib(khm_handle vid,
- const wchar_t * attr_name,
- void * buffer,
- khm_size cbbuf)
-{
- khm_int32 attr_id = -1;
-
- if(KHM_FAILED(kcdb_attrib_get_id(attr_name, &attr_id)))
- return KHM_ERROR_INVALID_PARAM;
-
- return kcdb_identity_set_attr(
- vid,
- attr_id,
- buffer,
- cbbuf);
-}
-
-KHMEXP khm_int32 KHMAPI
-kcdb_identity_get_attr(khm_handle vid,
- khm_int32 attr_id,
- khm_int32 * attr_type,
- void * buffer,
- khm_size * pcbbuf)
-{
- khm_int32 code = KHM_ERROR_SUCCESS;
- kcdb_identity * id = NULL;
- kcdb_attrib * attrib = NULL;
- kcdb_type * type = NULL;
- khm_size slot;
-
- if(KHM_FAILED(kcdb_attrib_get_info(attr_id, &attrib))) {
- return KHM_ERROR_INVALID_PARAM;
- }
-
- if(KHM_FAILED(kcdb_type_get_info(attrib->type, &type))) {
- kcdb_attrib_release_info(attrib);
- return KHM_ERROR_UNKNOWN;
- }
-
- if(attr_type)
- *attr_type = attrib->type;
-
- EnterCriticalSection(&cs_ident);
-
- if(!kcdb_is_active_identity(vid)) {
- code = KHM_ERROR_INVALID_PARAM;
- goto _exit;
- }
-
- id = (kcdb_identity *) vid;
-
- if(!(id->flags & KCDB_IDENT_FLAG_ATTRIBS) ||
- (slot = kcdb_buf_slot_by_id(&id->buf, attr_id)) == KCDB_BUF_INVALID_SLOT ||
- !kcdb_buf_val_exist(&id->buf, slot))
- {
- code = KHM_ERROR_NOT_FOUND;
- goto _exit;
- }
-
- if(!buffer && !pcbbuf) {
- /* in this case the caller is only trying to determine if the field
- contains data. If we get here, then the value exists. */
- code = KHM_ERROR_SUCCESS;
- goto _exit;
- }
-
-#if 0
- if(attrib->flags & KCDB_ATTR_FLAG_COMPUTED) {
- /* we should never hit this case */
-#ifdef DEBUG
- assert(FALSE);
-#endif
- code = KHM_ERROR_INVALID_OPERATION;
- } else {
-#endif
- code = type->dup(
- kcdb_buf_get(&id->buf, slot),
- kcdb_buf_size(&id->buf, slot),
- buffer,
- pcbbuf);
-#if 0
- }
-#endif
-
-_exit:
- LeaveCriticalSection(&cs_ident);
- if(type)
- kcdb_type_release_info(type);
- if(attrib)
- kcdb_attrib_release_info(attrib);
-
- return code;
-}
-
-KHMEXP khm_int32 KHMAPI
-kcdb_identity_get_attrib(khm_handle vid,
- const wchar_t * attr_name,
- khm_int32 * attr_type,
- void * buffer,
- khm_size * pcbbuf)
-{
- khm_int32 attr_id = -1;
-
- if(KHM_FAILED(kcdb_attrib_get_id(attr_name, &attr_id)))
- return KHM_ERROR_NOT_FOUND;
-
- return kcdb_identity_get_attr(vid,
- attr_id,
- attr_type,
- buffer,
- pcbbuf);
-}
-
-KHMEXP khm_int32 KHMAPI
-kcdb_identity_get_attr_string(khm_handle vid,
- khm_int32 attr_id,
- wchar_t * buffer,
- khm_size * pcbbuf,
- khm_int32 flags)
-{
- khm_int32 code = KHM_ERROR_SUCCESS;
- kcdb_identity * id = NULL;
- kcdb_attrib * attrib = NULL;
- kcdb_type * type = NULL;
- khm_size slot;
-
- if(KHM_FAILED(kcdb_attrib_get_info(attr_id, &attrib))) {
- return KHM_ERROR_INVALID_PARAM;
- }
-
- if(KHM_FAILED(kcdb_type_get_info(attrib->type, &type))) {
- kcdb_attrib_release_info(attrib);
- return KHM_ERROR_UNKNOWN;
- }
-
- EnterCriticalSection(&cs_ident);
-
- if(!kcdb_is_active_identity(vid)) {
- code = KHM_ERROR_INVALID_PARAM;
- goto _exit;
- }
-
- id = (kcdb_identity *) vid;
-
- if(!(id->flags & KCDB_IDENT_FLAG_ATTRIBS) ||
- (slot = kcdb_buf_slot_by_id(&id->buf, attr_id)) == KCDB_BUF_INVALID_SLOT ||
- !kcdb_buf_val_exist(&id->buf, slot))
- {
- code = KHM_ERROR_NOT_FOUND;
- goto _exit;
- }
-
- if(!buffer && !pcbbuf) {
- /* in this case the caller is only trying to determine if the field
- contains data. If we get here, then the value exists */
- code = KHM_ERROR_SUCCESS;
- goto _exit;
- }
-
-#if 0
- if(attrib->flags & KCDB_ATTR_FLAG_COMPUTED) {
-#ifdef DEBUG
- assert(FALSE);
-#endif
- code = KHM_ERROR_INVALID_OPERATION;
- } else {
-#endif
- if(kcdb_buf_exist(&id->buf, slot)) {
- code = type->toString(
- kcdb_buf_get(&id->buf, slot),
- kcdb_buf_size(&id->buf, slot),
- buffer,
- pcbbuf,
- flags);
- } else
- code = KHM_ERROR_NOT_FOUND;
-#if 0
- }
-#endif
-
-_exit:
- LeaveCriticalSection(&cs_ident);
- if(type)
- kcdb_type_release_info(type);
- if(attrib)
- kcdb_attrib_release_info(attrib);
-
- return code;
-}
-
-KHMEXP khm_int32 KHMAPI
-kcdb_identity_get_attrib_string(khm_handle vid,
- const wchar_t * attr_name,
- wchar_t * buffer,
- khm_size * pcbbuf,
- khm_int32 flags)
-{
- khm_int32 attr_id = -1;
-
- if(KHM_FAILED(kcdb_attrib_get_id(attr_name, &attr_id)))
- return KHM_ERROR_NOT_FOUND;
-
- return kcdb_identity_get_attr_string(
- vid,
- attr_id,
- buffer,
- pcbbuf,
- flags);
-}
-
-/*****************************************/
-/* Identity provider interface functions */
-
-/* NOT called with cs_ident held */
-KHMEXP khm_int32 KHMAPI
-kcdb_identpro_validate_name(const wchar_t * name)
-{
- kcdb_ident_name_xfer namex;
- khm_handle sub;
- khm_size cch;
- khm_int32 rv = KHM_ERROR_SUCCESS;
-
- /* we need to verify the length and the contents of the string
- before calling the identity provider */
- if(FAILED(StringCchLength(name, KCDB_IDENT_MAXCCH_NAME, &cch)))
- return KHM_ERROR_TOO_LONG;
-
- /* We can't really make an assumption about the valid characters
- in an identity. So we let the identity provider decide */
-#ifdef VALIDATE_IDENTIY_CHARACTERS
- if(wcsspn(name, KCDB_IDENT_VALID_CHARS) != cch)
- return KHM_ERROR_INVALID_NAME;
-#endif
-
- EnterCriticalSection(&cs_ident);
- if(kcdb_ident_sub != NULL) {
- sub = kcdb_ident_sub;
- } else {
- sub = NULL;
- rv = KHM_ERROR_NO_PROVIDER;
- }
- LeaveCriticalSection(&cs_ident);
-
- if(sub != NULL) {
- ZeroMemory(&namex, sizeof(namex));
-
- namex.name_src = name;
- namex.result = KHM_ERROR_NOT_IMPLEMENTED;
-
- kmq_send_sub_msg(sub,
- KMSG_IDENT,
- KMSG_IDENT_VALIDATE_NAME,
- 0,
- (void *) &namex);
-
- rv = namex.result;
- }
-
- return rv;
-}
-
-KHMEXP khm_int32 KHMAPI
-kcdb_identpro_validate_identity(khm_handle identity)
-{
- khm_int32 rv = KHM_ERROR_SUCCESS;
- khm_handle sub;
-
- if(!kcdb_is_active_identity(identity))
- return KHM_ERROR_INVALID_PARAM;
-
- EnterCriticalSection(&cs_ident);
- if(kcdb_ident_sub != NULL) {
- sub = kcdb_ident_sub;
- } else {
- sub = NULL;
- rv = KHM_ERROR_NO_PROVIDER;
- }
- LeaveCriticalSection(&cs_ident);
-
- if(sub != NULL) {
- rv = kmq_send_sub_msg(sub,
- KMSG_IDENT,
- KMSG_IDENT_VALIDATE_IDENTITY,
- 0,
- (void *) identity);
- }
-
- return rv;
-}
-
-KHMEXP khm_int32 KHMAPI
-kcdb_identpro_canon_name(const wchar_t * name_in,
- wchar_t * name_out,
- khm_size * cb_name_out)
-{
- khm_handle sub;
- kcdb_ident_name_xfer namex;
- wchar_t name_tmp[KCDB_IDENT_MAXCCH_NAME];
- khm_int32 rv = KHM_ERROR_SUCCESS;
- khm_size cch;
-
- if(cb_name_out == 0 ||
- FAILED(StringCchLength(name_in, KCDB_IDENT_MAXCCH_NAME, &cch)))
- return KHM_ERROR_INVALID_NAME;
-
- EnterCriticalSection(&cs_ident);
- if(kcdb_ident_sub != NULL) {
- sub = kcdb_ident_sub;
- } else {
- sub = NULL;
- rv = KHM_ERROR_NO_PROVIDER;
- }
- LeaveCriticalSection(&cs_ident);
-
- if(sub != NULL) {
- ZeroMemory(&namex, sizeof(namex));
- ZeroMemory(name_tmp, sizeof(name_tmp));
-
- namex.name_src = name_in;
- namex.name_dest = name_tmp;
- namex.cb_name_dest = sizeof(name_tmp);
- namex.result = KHM_ERROR_NOT_IMPLEMENTED;
-
- rv = kmq_send_sub_msg(sub,
- KMSG_IDENT,
- KMSG_IDENT_CANON_NAME,
- 0,
- (void *) &namex);
-
- if(KHM_SUCCEEDED(namex.result)) {
- const wchar_t * name_result;
- khm_size cb;
-
- if(name_in[0] != 0 && name_tmp[0] == 0)
- name_result = name_tmp;
- else
- name_result = name_in;
-
- if(FAILED(StringCbLength(name_result, KCDB_IDENT_MAXCB_NAME, &cb)))
- rv = KHM_ERROR_UNKNOWN;
- else {
- cb += sizeof(wchar_t);
- if(name_out == 0 || *cb_name_out < cb) {
- rv = KHM_ERROR_TOO_LONG;
- *cb_name_out = cb;
- } else {
- StringCbCopy(name_out, *cb_name_out, name_result);
- *cb_name_out = cb;
- rv = KHM_ERROR_SUCCESS;
- }
- }
- }
- }
-
- return rv;
-}
-
-KHMEXP khm_int32 KHMAPI
-kcdb_identpro_compare_name(const wchar_t * name1,
- const wchar_t * name2)
-{
- khm_handle sub;
- kcdb_ident_name_xfer namex;
- khm_int32 rv = 0;
-
- /* Generally in kcdb_identpro_* functions we don't emulate
- any behavior if the provider is not available, but lacking
- a way to make this known, we emulate here */
- rv = wcscmp(name1, name2);
-
- EnterCriticalSection(&cs_ident);
- if(kcdb_ident_sub != NULL) {
- sub = kcdb_ident_sub;
- } else {
- sub = NULL;
- }
- LeaveCriticalSection(&cs_ident);
-
- if(sub != NULL) {
- ZeroMemory(&namex, sizeof(namex));
- namex.name_src = name1;
- namex.name_alt = name2;
- namex.result = rv;
-
- kmq_send_sub_msg(sub,
- KMSG_IDENT,
- KMSG_IDENT_COMPARE_NAME,
- 0,
- (void *) &namex);
-
- rv = namex.result;
- }
-
- return rv;
-}
-
-KHMEXP khm_int32 KHMAPI
-kcdb_identpro_set_default(khm_handle identity)
-{
- khm_handle sub;
- khm_int32 rv = KHM_ERROR_SUCCESS;
-
- if((identity != NULL) &&
- !kcdb_is_active_identity(identity))
- return KHM_ERROR_INVALID_PARAM;
-
- EnterCriticalSection(&cs_ident);
- if(kcdb_ident_sub != NULL) {
- sub = kcdb_ident_sub;
- } else {
- sub = NULL;
- rv = KHM_ERROR_NO_PROVIDER;
- }
- LeaveCriticalSection(&cs_ident);
-
- if(sub != NULL) {
- rv = kmq_send_sub_msg(sub,
- KMSG_IDENT,
- KMSG_IDENT_SET_DEFAULT,
- (identity != NULL),
- (void *) identity);
- }
-
- return rv;
-}
-
-KHMEXP khm_int32 KHMAPI
-kcdb_identpro_set_searchable(khm_handle identity,
- khm_boolean searchable)
-{
- khm_handle sub;
- khm_int32 rv = KHM_ERROR_SUCCESS;
-
- if(!kcdb_is_active_identity(identity))
- return KHM_ERROR_INVALID_PARAM;
-
- EnterCriticalSection(&cs_ident);
- if(kcdb_ident_sub != NULL) {
- sub = kcdb_ident_sub;
- } else {
- sub = NULL;
- rv = KHM_ERROR_NO_PROVIDER;
- }
- LeaveCriticalSection(&cs_ident);
-
- if(sub != NULL) {
- rv = kmq_send_sub_msg(
- sub,
- KMSG_IDENT,
- KMSG_IDENT_SET_SEARCHABLE,
- searchable,
- (void *) identity);
- }
-
- return rv;
-}
-
-
-KHMEXP khm_int32 KHMAPI
-kcdb_identpro_update(khm_handle identity)
-{
- khm_handle sub;
- khm_int32 rv = KHM_ERROR_SUCCESS;
-
- if(!kcdb_is_active_identity(identity))
- return KHM_ERROR_INVALID_PARAM;
-
- EnterCriticalSection(&cs_ident);
- if(kcdb_ident_sub != NULL) {
- sub = kcdb_ident_sub;
- } else {
- sub = NULL;
- rv = KHM_ERROR_NO_PROVIDER;
- }
- LeaveCriticalSection(&cs_ident);
-
- if(sub != NULL) {
- rv = kmq_send_sub_msg(sub,
- KMSG_IDENT,
- KMSG_IDENT_UPDATE,
- 0,
- (void *) identity);
- }
-
- return rv;
-}
-
-KHMEXP khm_int32 KHMAPI
-kcdb_identpro_notify_create(khm_handle identity)
-{
- khm_handle sub;
- khm_int32 rv = KHM_ERROR_SUCCESS;
-
- if(!kcdb_is_active_identity(identity))
- return KHM_ERROR_INVALID_PARAM;
-
- EnterCriticalSection(&cs_ident);
- if(kcdb_ident_sub != NULL) {
- sub = kcdb_ident_sub;
- } else {
- sub = NULL;
- rv = KHM_ERROR_NO_PROVIDER;
- }
- LeaveCriticalSection(&cs_ident);
-
- if(sub != NULL) {
- rv = kmq_send_sub_msg(
- sub,
- KMSG_IDENT,
- KMSG_IDENT_NOTIFY_CREATE,
- 0,
- (void *) identity);
- }
-
- return rv;
-}
-
-KHMEXP khm_int32 KHMAPI
-kcdb_identpro_get_ui_cb(void * rock)
-{
- khm_handle sub;
- khm_int32 rv = KHM_ERROR_SUCCESS;
-
- EnterCriticalSection(&cs_ident);
- if(kcdb_ident_sub != NULL) {
- sub = kcdb_ident_sub;
- } else {
- sub = NULL;
- rv = KHM_ERROR_NO_PROVIDER;
- }
- LeaveCriticalSection(&cs_ident);
-
- if(sub != NULL) {
- rv = kmq_send_sub_msg(
- sub,
- KMSG_IDENT,
- KMSG_IDENT_GET_UI_CALLBACK,
- 0,
- rock);
- }
-
- return rv;
-}
-
-KHMEXP khm_int32 KHMAPI
-kcdb_identity_enum(khm_int32 and_flags,
- khm_int32 eq_flags,
- wchar_t * name_buf,
- khm_size * pcb_buf,
- khm_size * pn_idents)
-{
- kcdb_identity * id;
- khm_int32 rv = KHM_ERROR_SUCCESS;
- khm_size cb_req = 0;
- khm_size n_idents = 0;
- size_t cb_curr;
- size_t cch_curr;
- size_t cch_left;
- HRESULT hr;
-
- if ((name_buf == NULL && pcb_buf == NULL && pn_idents == NULL) ||
- (name_buf != NULL && pcb_buf == NULL))
- return KHM_ERROR_INVALID_PARAM;
-
- eq_flags &= and_flags;
-
- EnterCriticalSection(&cs_ident);
-
- if (!kcdb_checked_config) {
- khm_handle h_kcdb = NULL;
- khm_handle h_idents = NULL;
- khm_handle h_ident = NULL;
-
- kcdb_checked_config = TRUE;
- kcdb_checking_config = TRUE;
-
- h_kcdb = kcdb_get_config();
- if (!h_kcdb)
- goto _config_check_cleanup;
- if(KHM_FAILED(khc_open_space(h_kcdb, L"Identity", 0, &h_idents)))
- goto _config_check_cleanup;
-
- while(KHM_SUCCEEDED(khc_enum_subspaces(h_idents,
- h_ident,
- &h_ident))) {
-
- wchar_t wname[KCDB_IDENT_MAXCCH_NAME];
- khm_size cb;
- khm_handle t_id;
-
- cb = sizeof(wname);
- if (KHM_FAILED(khc_get_config_space_name(h_ident,
- wname,
- &cb)))
- continue;
-
- LeaveCriticalSection(&cs_ident);
-
- if (KHM_SUCCEEDED(kcdb_identity_create(wname,
- KCDB_IDENT_FLAG_CREATE,
- &t_id)))
- kcdb_identity_release(t_id);
-
- EnterCriticalSection(&cs_ident);
- }
-
- _config_check_cleanup:
- if (h_kcdb)
- khc_close_space(h_kcdb);
- if (h_idents)
- khc_close_space(h_idents);
-
- kcdb_checking_config = FALSE;
- }
-
- for ( id = kcdb_identities;
- id != NULL;
- id = LNEXT(id) ) {
- if (((id->flags & KCDB_IDENT_FLAG_ACTIVE) ==
- KCDB_IDENT_FLAG_ACTIVE) &&
- ((id->flags & and_flags) == eq_flags)) {
- n_idents ++;
- hr = StringCbLength(id->name, KCDB_IDENT_MAXCB_NAME, &cb_curr);
-#ifdef DEBUG
- assert(SUCCEEDED(hr));
-#endif
- cb_req += cb_curr + sizeof(wchar_t);
- }
- }
-
- cb_req += sizeof(wchar_t);
-
- if (pn_idents != NULL)
- *pn_idents = n_idents;
-
- if (pcb_buf != NULL && (name_buf == NULL || *pcb_buf < cb_req)) {
- *pcb_buf = cb_req;
-
- rv = KHM_ERROR_TOO_LONG;
- } else if(name_buf != NULL) {
- cch_left = (*pcb_buf) / sizeof(wchar_t);
-
- for (id = kcdb_identities;
- id != NULL;
- id = LNEXT(id)) {
- if (((id->flags & KCDB_IDENT_FLAG_ACTIVE) ==
- KCDB_IDENT_FLAG_ACTIVE) &&
- ((id->flags & and_flags) == eq_flags)) {
- StringCchLength(id->name, KCDB_IDENT_MAXCCH_NAME,
- &cch_curr);
- cch_curr++;
- StringCchCopy(name_buf, cch_left, id->name);
- cch_left -= cch_curr;
- name_buf += cch_curr;
- }
- }
-
- *name_buf = L'\0';
- *pcb_buf = cb_req;
- }
-
- LeaveCriticalSection(&cs_ident);
-
- return rv;
-}
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ * Copyright (c) 2007 Secure Endpoints Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<kcreddbinternal.h>
+#include<assert.h>
+
+static CRITICAL_SECTION cs_ident;
+hashtable * kcdb_identities_namemap = NULL;
+khm_int32 kcdb_n_identities = 0;
+kcdb_identity * kcdb_identities = NULL;
+kcdb_identity * kcdb_def_identity = NULL;
+khm_handle kcdb_ident_sub = NULL; /* identity provider */
+khm_int32 kcdb_ident_cred_type = KCDB_CREDTYPE_INVALID;
+/* primary credentials type */
+khm_ui_4 kcdb_ident_refresh_cycle = 0;
+khm_boolean kcdb_checked_config = FALSE;
+khm_boolean kcdb_checking_config = FALSE;
+
+KHMEXP khm_boolean KHMAPI
+kcdb_identity_is_equal(khm_handle identity1,
+ khm_handle identity2)
+{
+
+ return (identity1 == identity2);
+
+}
+
+KHMEXP khm_int32 KHMAPI
+kcdb_identity_set_provider(khm_handle sub)
+{
+ EnterCriticalSection(&cs_ident);
+ if (sub != kcdb_ident_sub) {
+ if(kcdb_ident_sub != NULL) {
+ kmq_send_sub_msg(kcdb_ident_sub,
+ KMSG_IDENT,
+ KMSG_IDENT_EXIT,
+ 0,
+ 0);
+ kmq_delete_subscription(kcdb_ident_sub);
+ }
+ kcdb_ident_sub = sub;
+
+ if (kcdb_ident_sub)
+ kmq_send_sub_msg(kcdb_ident_sub,
+ KMSG_IDENT,
+ KMSG_IDENT_INIT,
+ 0,
+ 0);
+ }
+ LeaveCriticalSection(&cs_ident);
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP khm_int32 KHMAPI
+kcdb_identity_get_provider(khm_handle * sub)
+{
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+
+ EnterCriticalSection(&cs_ident);
+ if(kcdb_ident_sub != NULL)
+ rv = KHM_ERROR_SUCCESS;
+ else
+ rv = KHM_ERROR_NOT_FOUND;
+ if(sub != NULL)
+ *sub = kcdb_ident_sub;
+ LeaveCriticalSection(&cs_ident);
+
+ return rv;
+}
+
+KHMEXP khm_int32 KHMAPI
+kcdb_identity_set_type(khm_int32 cred_type)
+{
+ EnterCriticalSection(&cs_ident);
+ kcdb_ident_cred_type = cred_type;
+ LeaveCriticalSection(&cs_ident);
+
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP khm_int32 KHMAPI
+kcdb_identity_get_type(khm_int32 * ptype)
+{
+ if (!ptype)
+ return KHM_ERROR_INVALID_PARAM;
+
+ EnterCriticalSection(&cs_ident);
+ *ptype = kcdb_ident_cred_type;
+ LeaveCriticalSection(&cs_ident);
+
+ if (*ptype >= 0)
+ return KHM_ERROR_SUCCESS;
+ else
+ return KHM_ERROR_NOT_FOUND;
+}
+
+/* message completion routine */
+void
+kcdbint_ident_msg_completion(kmq_message * m) {
+ kcdb_identity_release(m->vparam);
+}
+
+void
+kcdbint_ident_add_ref(const void * key, void * vid) {
+ /* References in the hashtable are not refcounted */
+
+ // kcdb_identity_hold(vid);
+}
+
+void
+kcdbint_ident_del_ref(const void * key, void * vid) {
+ /* References in the hashtable are not refcounted */
+
+ // kcdb_identity_release(vid);
+}
+
+void
+kcdbint_ident_init(void) {
+ InitializeCriticalSection(&cs_ident);
+ kcdb_identities_namemap = hash_new_hashtable(
+ KCDB_IDENT_HASHTABLE_SIZE,
+ hash_string,
+ hash_string_comp,
+ kcdbint_ident_add_ref,
+ kcdbint_ident_del_ref);
+}
+
+void
+kcdbint_ident_exit(void) {
+ EnterCriticalSection(&cs_ident);
+ hash_del_hashtable(kcdb_identities_namemap);
+ LeaveCriticalSection(&cs_ident);
+ DeleteCriticalSection(&cs_ident);
+}
+
+/* NOT called with cs_ident held */
+KHMEXP khm_boolean KHMAPI
+kcdb_identity_is_valid_name(const wchar_t * name)
+{
+ khm_int32 rv;
+
+ /* special case. Note since the string we are comparing with is
+ of a known length we don't need to check the length of name. */
+ if (!wcscmp(name, L"_Schema"))
+ return FALSE;
+
+ rv = kcdb_identpro_validate_name(name);
+
+ if(rv == KHM_ERROR_NO_PROVIDER ||
+ rv == KHM_ERROR_NOT_IMPLEMENTED)
+ return TRUE;
+ else
+ return KHM_SUCCEEDED(rv);
+}
+
+KHMEXP khm_int32 KHMAPI
+kcdb_identity_create(const wchar_t *name,
+ khm_int32 flags,
+ khm_handle * result) {
+ kcdb_identity * id = NULL;
+ kcdb_identity * id_tmp = NULL;
+ size_t namesize;
+
+ if(!result || !name)
+ return KHM_ERROR_INVALID_PARAM;
+
+ *result = NULL;
+
+ /* is it there already? */
+ EnterCriticalSection(&cs_ident);
+ id = hash_lookup(kcdb_identities_namemap, (void *) name);
+ if(id)
+ kcdb_identity_hold((khm_handle) id);
+ LeaveCriticalSection(&cs_ident);
+
+ if(id) {
+ *result = (khm_handle) id;
+ return KHM_ERROR_SUCCESS;
+ } else if(!(flags & KCDB_IDENT_FLAG_CREATE)) {
+ return KHM_ERROR_NOT_FOUND;
+ }
+
+ flags &= ~KCDB_IDENT_FLAG_CREATE;
+
+ /* nope. create it */
+ if((flags & ~KCDB_IDENT_FLAGMASK_RDWR) ||
+ (flags & (KCDB_IDENT_FLAG_DEFAULT |
+ KCDB_IDENT_FLAG_SEARCHABLE |
+ KCDB_IDENT_FLAG_STICKY))) {
+ /* can't specify this flag in create */
+ return KHM_ERROR_INVALID_PARAM;
+ }
+
+ if(!kcdb_identity_is_valid_name(name)) {
+ return KHM_ERROR_INVALID_NAME;
+ }
+
+ /* we expect the following will succeed since the above
+ test passed */
+ StringCbLength(name, KCDB_IDENT_MAXCB_NAME, &namesize);
+ namesize += sizeof(wchar_t);
+
+ id = PMALLOC(sizeof(kcdb_identity));
+ ZeroMemory(id, sizeof(kcdb_identity));
+ id->magic = KCDB_IDENT_MAGIC;
+ id->name = PMALLOC(namesize);
+ StringCbCopy(id->name, namesize, name);
+
+ id->flags = (flags & KCDB_IDENT_FLAGMASK_RDWR);
+ id->flags |= KCDB_IDENT_FLAG_ACTIVE | KCDB_IDENT_FLAG_EMPTY;
+ LINIT(id);
+
+ EnterCriticalSection(&cs_ident);
+ id_tmp = hash_lookup(kcdb_identities_namemap, (void *) id->name);
+ if(id_tmp) {
+ /* lost a race */
+ kcdb_identity_hold((khm_handle) id_tmp);
+ *result = (khm_handle) id_tmp;
+
+ PFREE(id->name);
+ PFREE(id);
+
+ id = NULL;
+ } else {
+ khm_handle h_cfg;
+
+ kcdb_identity_hold((khm_handle) id);
+ hash_add(kcdb_identities_namemap,
+ (void *) id->name,
+ (void *) id);
+ LPUSH(&kcdb_identities, id);
+
+ if(KHM_SUCCEEDED(kcdb_identity_get_config((khm_handle) id,
+ 0,
+ &h_cfg))) {
+ /* don't need to set the KCDB_IDENT_FLAG_CONFIG flags
+ since kcdb_identity_get_config() sets it for us. */
+ khm_int32 sticky;
+
+ if (KHM_SUCCEEDED(khc_read_int32(h_cfg, L"Sticky", &sticky)) &&
+ sticky) {
+ id->flags |= KCDB_IDENT_FLAG_STICKY;
+ }
+
+ khc_close_space(h_cfg);
+ }
+ }
+ LeaveCriticalSection(&cs_ident);
+
+ if(id != NULL) {
+ *result = (khm_handle) id;
+
+ kcdb_identpro_notify_create((khm_handle) id);
+
+ kcdbint_ident_post_message(KCDB_OP_INSERT, id);
+ }
+
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP khm_int32 KHMAPI
+kcdb_identity_delete(khm_handle vid) {
+ kcdb_identity * id;
+ khm_int32 code = KHM_ERROR_SUCCESS;
+
+ EnterCriticalSection(&cs_ident);
+ if(!kcdb_is_identity(vid)) {
+ code = KHM_ERROR_INVALID_PARAM;
+ goto _exit;
+ }
+
+ id = (kcdb_identity *) vid;
+
+ if (kcdb_is_active_identity(vid)) {
+
+ id->flags &= ~KCDB_IDENT_FLAG_ACTIVE;
+
+ hash_del(kcdb_identities_namemap, (void *) id->name);
+
+ LeaveCriticalSection(&cs_ident);
+
+ kcdbint_ident_post_message(KCDB_OP_DELETE, id);
+
+ /* Once everybody finishes dealing with the identity deletion,
+ we will get called again. */
+ return KHM_ERROR_SUCCESS;
+ } else if (id->refcount == 0) {
+ /* If the identity is not active, it is not in the hashtable
+ either */
+ LDELETE(&kcdb_identities, id);
+
+ if (id->name)
+ PFREE(id->name);
+ PFREE(id);
+ }
+ /* else, we have an identity that is not active, but has
+ outstanding references. We have to wait until those references
+ are freed. Once they are released, kcdb_identity_delete() will
+ be called again. */
+
+ _exit:
+ LeaveCriticalSection(&cs_ident);
+
+ return code;
+}
+
+KHMEXP khm_int32 KHMAPI
+kcdb_identity_set_flags(khm_handle vid,
+ khm_int32 flag,
+ khm_int32 mask) {
+ kcdb_identity * id;
+ khm_int32 oldflags;
+ khm_int32 newflags;
+ khm_int32 delta = 0;
+ khm_int32 rv;
+
+ if (mask == 0)
+ return KHM_ERROR_SUCCESS;
+
+ if(!kcdb_is_active_identity(vid))
+ return KHM_ERROR_INVALID_PARAM;
+
+ id = (kcdb_identity *) vid;
+
+ flag &= mask;
+
+ if((mask & ~KCDB_IDENT_FLAGMASK_RDWR) ||
+ ((flag & KCDB_IDENT_FLAG_INVALID) && (flag & KCDB_IDENT_FLAG_VALID)))
+ return KHM_ERROR_INVALID_PARAM;
+
+ if((mask & KCDB_IDENT_FLAG_DEFAULT) &&
+ (flag & KCDB_IDENT_FLAG_DEFAULT)) {
+ /* kcdb_identity_set_default already does checking for
+ redundant transitions */
+ rv = kcdb_identity_set_default(vid);
+
+ if(KHM_FAILED(rv))
+ return rv;
+
+ mask &= ~KCDB_IDENT_FLAG_DEFAULT;
+ flag &= ~KCDB_IDENT_FLAG_DEFAULT;
+ }
+
+ EnterCriticalSection(&cs_ident);
+
+ if(mask & KCDB_IDENT_FLAG_SEARCHABLE) {
+ if(!(flag & KCDB_IDENT_FLAG_SEARCHABLE)) {
+ if(id->flags & KCDB_IDENT_FLAG_SEARCHABLE) {
+ LeaveCriticalSection(&cs_ident);
+ rv = kcdb_identpro_set_searchable(vid, FALSE);
+ EnterCriticalSection(&cs_ident);
+ if(rv == KHM_ERROR_NO_PROVIDER ||
+ KHM_SUCCEEDED(rv)) {
+ id->flags &= ~KCDB_IDENT_FLAG_SEARCHABLE;
+ delta |= KCDB_IDENT_FLAG_SEARCHABLE;
+ }
+ }
+ } else {
+ if(!(id->flags & KCDB_IDENT_FLAG_SEARCHABLE)) {
+ LeaveCriticalSection(&cs_ident);
+ rv = kcdb_identpro_set_searchable(vid, TRUE);
+ EnterCriticalSection(&cs_ident);
+ if(rv == KHM_ERROR_NO_PROVIDER ||
+ KHM_SUCCEEDED(rv)) {
+ id->flags |= KCDB_IDENT_FLAG_SEARCHABLE;
+ delta |= KCDB_IDENT_FLAG_SEARCHABLE;
+ }
+ }
+ }
+
+ flag &= ~KCDB_IDENT_FLAG_SEARCHABLE;
+ mask &= ~KCDB_IDENT_FLAG_SEARCHABLE;
+ }
+
+ if (mask & KCDB_IDENT_FLAG_STICKY) {
+ if ((flag ^ id->flags) & KCDB_IDENT_FLAG_STICKY) {
+ khm_handle h_conf;
+
+ if (KHM_SUCCEEDED(kcdb_identity_get_config(vid,
+ KHM_FLAG_CREATE,
+ &h_conf))) {
+ khc_write_int32(h_conf, L"Sticky",
+ !!(flag & KCDB_IDENT_FLAG_STICKY));
+ khc_close_space(h_conf);
+ }
+
+ id->flags =
+ ((id->flags & ~KCDB_IDENT_FLAG_STICKY) |
+ (flag & KCDB_IDENT_FLAG_STICKY));
+
+ delta |= KCDB_IDENT_FLAG_STICKY;
+ }
+
+ flag &= ~KCDB_IDENT_FLAG_STICKY;
+ mask &= ~KCDB_IDENT_FLAG_STICKY;
+ }
+
+ /* deal with every other flag */
+
+ oldflags = id->flags;
+
+ id->flags = (id->flags & ~mask) | (flag & mask);
+
+ if (flag & KCDB_IDENT_FLAG_VALID) {
+ id->flags &= ~(KCDB_IDENT_FLAG_INVALID | KCDB_IDENT_FLAG_UNKNOWN);
+ }
+ if (flag & KCDB_IDENT_FLAG_INVALID) {
+ id->flags &= ~(KCDB_IDENT_FLAG_VALID | KCDB_IDENT_FLAG_UNKNOWN);
+ }
+
+ newflags = id->flags;
+
+ LeaveCriticalSection(&cs_ident);
+
+ delta |= newflags ^ oldflags;
+
+ if((delta & KCDB_IDENT_FLAG_HIDDEN)) {
+ kcdbint_ident_post_message(
+ (newflags & KCDB_IDENT_FLAG_HIDDEN)?KCDB_OP_HIDE:KCDB_OP_UNHIDE,
+ vid);
+ }
+
+ if((delta & KCDB_IDENT_FLAG_SEARCHABLE)) {
+ kcdbint_ident_post_message(
+ (newflags & KCDB_IDENT_FLAG_SEARCHABLE)?KCDB_OP_SETSEARCH:KCDB_OP_UNSETSEARCH,
+ vid);
+ }
+
+ if(delta != 0)
+ kcdbint_ident_post_message(KCDB_OP_MODIFY, vid);
+
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP khm_int32 KHMAPI
+kcdb_identity_get_flags(khm_handle vid,
+ khm_int32 * flags) {
+ kcdb_identity * id;
+
+ *flags = 0;
+
+ if(!kcdb_is_active_identity(vid))
+ return KHM_ERROR_INVALID_PARAM;
+
+ id = (kcdb_identity *) vid;
+
+ EnterCriticalSection(&cs_ident);
+ *flags = id->flags;
+ LeaveCriticalSection(&cs_ident);
+
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP khm_int32 KHMAPI
+kcdb_identity_get_name(khm_handle vid,
+ wchar_t * buffer,
+ khm_size * pcbsize) {
+ size_t namesize;
+ kcdb_identity * id;
+
+ if(!kcdb_is_active_identity(vid) || !pcbsize)
+ return KHM_ERROR_INVALID_PARAM;
+
+ id = (kcdb_identity *) vid;
+
+ if(FAILED(StringCbLength(id->name, KCDB_IDENT_MAXCB_NAME, &namesize)))
+ return KHM_ERROR_UNKNOWN;
+
+ namesize += sizeof(wchar_t);
+
+ if(!buffer || namesize > *pcbsize) {
+ *pcbsize = namesize;
+ return KHM_ERROR_TOO_LONG;
+ }
+
+ StringCbCopy(buffer, *pcbsize, id->name);
+ *pcbsize = namesize;
+
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP khm_int32 KHMAPI
+kcdb_identity_get_default(khm_handle * pvid) {
+ khm_handle def;
+
+ if (pvid == NULL)
+ return KHM_ERROR_INVALID_PARAM;
+
+ EnterCriticalSection(&cs_ident);
+ def = kcdb_def_identity;
+ if (def != NULL)
+ kcdb_identity_hold(def);
+ LeaveCriticalSection(&cs_ident);
+
+ *pvid = def;
+
+ if (def != NULL)
+ return KHM_ERROR_SUCCESS;
+ else
+ return KHM_ERROR_NOT_FOUND;
+}
+
+static khm_int32
+kcdbint_ident_set_default(khm_handle vid,
+ khm_boolean invoke_identpro) {
+ kcdb_identity * new_def;
+ kcdb_identity * old_def;
+ khm_int32 rv;
+
+ if (vid != NULL && !kcdb_is_active_identity(vid))
+ return KHM_ERROR_INVALID_PARAM;
+
+ new_def = (kcdb_identity *)vid;
+
+ if (new_def != NULL && (new_def->flags & KCDB_IDENT_FLAG_DEFAULT))
+ return KHM_ERROR_SUCCESS;
+
+ if ((new_def == NULL && kcdb_def_identity == NULL) ||
+ (new_def == kcdb_def_identity))
+ return KHM_ERROR_SUCCESS;
+
+ /* first check with the identity provider if this operation
+ is permitted. */
+ if (invoke_identpro) {
+ rv = kcdb_identpro_set_default(vid);
+ if(rv != KHM_ERROR_NO_PROVIDER && KHM_FAILED(rv))
+ return rv;
+ }
+
+ EnterCriticalSection(&cs_ident);
+
+ old_def = kcdb_def_identity;
+ kcdb_def_identity = new_def;
+
+ if(old_def != new_def) {
+ if(old_def) {
+ old_def->flags &= ~KCDB_IDENT_FLAG_DEFAULT;
+ kcdb_identity_release((khm_handle) old_def);
+ }
+
+ if(new_def) {
+ new_def->flags |= KCDB_IDENT_FLAG_DEFAULT;
+ kcdb_identity_hold((khm_handle) new_def);
+ }
+
+ LeaveCriticalSection(&cs_ident);
+
+ /* if (invoke_identpro) */
+ kcdbint_ident_post_message(KCDB_OP_NEW_DEFAULT, new_def);
+ } else {
+ LeaveCriticalSection(&cs_ident);
+ }
+
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP khm_int32 KHMAPI
+kcdb_identity_set_default(khm_handle vid) {
+ return kcdbint_ident_set_default(vid, TRUE);
+}
+
+KHMEXP khm_int32 KHMAPI
+kcdb_identity_set_default_int(khm_handle vid) {
+ return kcdbint_ident_set_default(vid, FALSE);
+}
+
+KHMEXP khm_int32 KHMAPI
+kcdb_identity_get_config(khm_handle vid,
+ khm_int32 flags,
+ khm_handle * result) {
+ khm_handle hkcdb;
+ khm_handle hidents = NULL;
+ khm_handle hident = NULL;
+ khm_int32 rv;
+ kcdb_identity * id;
+
+ if(kcdb_is_active_identity(vid)) {
+ id = (kcdb_identity *) vid;
+ } else {
+ return KHM_ERROR_INVALID_PARAM;
+ }
+
+ hkcdb = kcdb_get_config();
+ if(hkcdb) {
+ rv = khc_open_space(hkcdb, L"Identity", 0, &hidents);
+ if(KHM_FAILED(rv))
+ goto _exit;
+
+ rv = khc_open_space(hidents,
+ id->name,
+ flags | KCONF_FLAG_NOPARSENAME,
+ &hident);
+
+ if(KHM_FAILED(rv)) {
+ khm_int32 oldflags;
+ EnterCriticalSection(&cs_ident);
+ oldflags = id->flags;
+ id->flags &= ~KCDB_IDENT_FLAG_CONFIG;
+ LeaveCriticalSection(&cs_ident);
+ if (oldflags & KCDB_IDENT_FLAG_CONFIG)
+ kcdbint_ident_post_message(KCDB_OP_DELCONFIG, id);
+ goto _exit;
+ }
+
+ EnterCriticalSection(&cs_ident);
+ id->flags |= KCDB_IDENT_FLAG_CONFIG;
+ LeaveCriticalSection(&cs_ident);
+
+ *result = hident;
+ } else
+ rv = KHM_ERROR_UNKNOWN;
+
+_exit:
+ if(hidents)
+ khc_close_space(hidents);
+ if(hkcdb)
+ khc_close_space(hkcdb);
+ return rv;
+}
+
+/*! \note cs_ident must be available. */
+void
+kcdbint_ident_post_message(khm_int32 op, kcdb_identity * id) {
+ kcdb_identity_hold(id);
+ kmq_post_message(KMSG_KCDB, KMSG_KCDB_IDENT, op, (void *) id);
+}
+
+/*! \note cs_ident must be available. */
+KHMEXP khm_int32 KHMAPI
+kcdb_identity_hold(khm_handle vid) {
+ kcdb_identity * id;
+
+ EnterCriticalSection(&cs_ident);
+ if(kcdb_is_active_identity(vid)) {
+ id = vid;
+ id->refcount++;
+ } else {
+ LeaveCriticalSection(&cs_ident);
+ return KHM_ERROR_INVALID_PARAM;
+ }
+ LeaveCriticalSection(&cs_ident);
+ return ERROR_SUCCESS;
+}
+
+/*! \note cs_ident must be available. */
+KHMEXP khm_int32 KHMAPI
+kcdb_identity_release(khm_handle vid) {
+ kcdb_identity * id;
+ khm_int32 refcount;
+
+ EnterCriticalSection(&cs_ident);
+ if(kcdb_is_identity(vid)) {
+ id = vid;
+ refcount = --id->refcount;
+ if(refcount == 0) {
+ /* We only delete identities which do not have a
+ configuration. */
+ if (id->refcount == 0 &&
+ !(id->flags & KCDB_IDENT_FLAG_CONFIG))
+ kcdb_identity_delete(vid);
+ }
+ } else {
+ LeaveCriticalSection(&cs_ident);
+ return KHM_ERROR_INVALID_PARAM;
+ }
+ LeaveCriticalSection(&cs_ident);
+ return ERROR_SUCCESS;
+}
+
+struct kcdb_idref_result {
+ kcdb_identity * ident;
+ khm_int32 flags;
+ khm_size count;
+};
+
+static khm_int32 KHMAPI
+kcdbint_idref_proc(khm_handle cred, void * r) {
+ khm_handle vid;
+ struct kcdb_idref_result *result;
+ khm_int32 flags;
+
+ result = (struct kcdb_idref_result *) r;
+
+ if (KHM_SUCCEEDED(kcdb_cred_get_identity(cred, &vid))) {
+ if (result->ident == (kcdb_identity *) vid) {
+
+ result->count++;
+ kcdb_cred_get_flags(cred, &flags);
+
+ if (flags & KCDB_CRED_FLAG_RENEWABLE) {
+ result->flags |= KCDB_IDENT_FLAG_CRED_RENEW;
+ if (flags & KCDB_CRED_FLAG_INITIAL) {
+ result->flags |= KCDB_IDENT_FLAG_RENEWABLE;
+ }
+ }
+
+ if (flags & KCDB_CRED_FLAG_EXPIRED) {
+ result->flags |= KCDB_IDENT_FLAG_CRED_EXP;
+ if (flags & KCDB_CRED_FLAG_INITIAL) {
+ result->flags |= KCDB_IDENT_FLAG_EXPIRED;
+ }
+ }
+
+ if (flags & KCDB_CRED_FLAG_INITIAL) {
+ result->flags |= KCDB_IDENT_FLAG_VALID;
+ }
+ }
+
+ kcdb_identity_release(vid);
+ }
+
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP khm_int32 KHMAPI
+kcdb_identity_refresh(khm_handle vid) {
+ kcdb_identity * ident;
+ khm_int32 code = KHM_ERROR_SUCCESS;
+ struct kcdb_idref_result result;
+
+ EnterCriticalSection(&cs_ident);
+
+ if (!kcdb_is_active_identity(vid)) {
+ code = KHM_ERROR_INVALID_PARAM;
+ goto _exit;
+ }
+
+ ident = (kcdb_identity *) vid;
+
+ result.ident = ident;
+ result.flags = 0;
+ result.count = 0;
+
+ LeaveCriticalSection(&cs_ident);
+
+ kcdb_credset_apply(NULL, kcdbint_idref_proc, &result);
+
+ if (result.count == 0)
+ result.flags |= KCDB_IDENT_FLAG_EMPTY;
+
+ kcdb_identity_set_flags(vid, result.flags,
+ KCDB_IDENT_FLAGMASK_RDWR &
+ ~(KCDB_IDENT_FLAG_DEFAULT |
+ KCDB_IDENT_FLAG_SEARCHABLE |
+ KCDB_IDENT_FLAG_STICKY));
+
+ EnterCriticalSection(&cs_ident);
+ ident->refresh_cycle = kcdb_ident_refresh_cycle;
+
+ _exit:
+ LeaveCriticalSection(&cs_ident);
+
+ if (code == 0)
+ code = kcdb_identpro_update(vid);
+
+ return code;
+}
+
+KHMEXP khm_int32 KHMAPI
+kcdb_identity_refresh_all(void) {
+ kcdb_identity * ident;
+ kcdb_identity * next;
+ khm_int32 code = KHM_ERROR_SUCCESS;
+ int hit_count;
+
+ EnterCriticalSection(&cs_ident);
+
+ kcdb_ident_refresh_cycle++;
+
+ /* The do-while loop is here to account for race conditions. We
+ release cs_ident in the for loop, so we don't actually have a
+ guarantee that we traversed the whole identity list at the end.
+ We repeat until all the identities are uptodate. */
+
+ do {
+ hit_count = 0;
+
+ for (ident = kcdb_identities;
+ ident != NULL;
+ ident = next) {
+
+ if (!kcdb_is_active_identity(ident) ||
+ ident->refresh_cycle == kcdb_ident_refresh_cycle) {
+ next = LNEXT(ident);
+ continue;
+ }
+
+ kcdb_identity_hold((khm_handle) ident);
+
+ LeaveCriticalSection(&cs_ident);
+
+ kcdb_identity_refresh((khm_handle) ident);
+
+ EnterCriticalSection(&cs_ident);
+
+ next = LNEXT(ident);
+ kcdb_identity_release((khm_handle) ident);
+
+ hit_count++;
+ }
+
+ } while (hit_count > 0);
+
+ LeaveCriticalSection(&cs_ident);
+
+ return code;
+}
+
+/*****************************************/
+/* Custom property functions */
+
+KHMEXP khm_int32 KHMAPI
+kcdb_identity_set_attr(khm_handle vid,
+ khm_int32 attr_id,
+ void * buffer,
+ khm_size cbbuf)
+{
+ kcdb_identity * id = NULL;
+ kcdb_attrib * attrib = NULL;
+ kcdb_type * type = NULL;
+ khm_size slot;
+ khm_size cbdest;
+ khm_int32 code = KHM_ERROR_SUCCESS;
+
+ EnterCriticalSection(&cs_ident);
+ if(!kcdb_is_active_identity(vid)) {
+ LeaveCriticalSection(&cs_ident);
+ return KHM_ERROR_INVALID_PARAM;
+ }
+
+ id = (kcdb_identity *) vid;
+
+ if(!(id->flags & KCDB_IDENT_FLAG_ATTRIBS)) {
+ kcdb_buf_new(&id->buf, KCDB_BUF_DEFAULT);
+ id->flags |= KCDB_IDENT_FLAG_ATTRIBS;
+ }
+
+ if(KHM_FAILED(kcdb_attrib_get_info(attr_id, &attrib))) {
+ LeaveCriticalSection(&cs_ident);
+ return KHM_ERROR_INVALID_PARAM;
+ }
+
+#if 0
+ /* actually, even if an attribute is computed, we still allow
+ those values to be set. This is because computing values
+ is only for credentials. If a computed value is used as a
+ property in any other object, it is treated as a regular value
+ */
+ if(attrib->flags & KCDB_ATTR_FLAG_COMPUTED)
+ {
+ LeaveCriticalSection(&cs_ident);
+ kcdb_attrib_release_info(attrib);
+ return KHM_ERROR_INVALID_OPERATION;
+ }
+#endif
+
+ if (buffer == NULL) {
+ /* we are removing a value */
+ slot = kcdb_buf_slot_by_id(&id->buf, attr_id);
+ if (slot != KCDB_BUF_INVALID_SLOT &&
+ kcdb_buf_exist(&id->buf, slot))
+ kcdb_buf_alloc(&id->buf, slot, attr_id, 0);
+ code = KHM_ERROR_SUCCESS;
+ goto _exit;
+ }
+
+ if(KHM_FAILED(kcdb_type_get_info(attrib->type, &type))) {
+ LeaveCriticalSection(&cs_ident);
+ kcdb_attrib_release_info(attrib);
+ return KHM_ERROR_INVALID_PARAM;
+ }
+
+ if(!(type->isValid(buffer,cbbuf))) {
+ code = KHM_ERROR_TYPE_MISMATCH;
+ goto _exit;
+ }
+
+ if((type->dup(buffer, cbbuf, NULL, &cbdest)) != KHM_ERROR_TOO_LONG) {
+ code = KHM_ERROR_INVALID_PARAM;
+ goto _exit;
+ }
+
+ kcdb_buf_alloc(&id->buf, KCDB_BUF_APPEND, attr_id, cbdest);
+ slot = kcdb_buf_slot_by_id(&id->buf, attr_id);
+ if(slot == KCDB_BUF_INVALID_SLOT || !kcdb_buf_exist(&id->buf, slot)) {
+ code = KHM_ERROR_NO_RESOURCES;
+ goto _exit;
+ }
+
+ if(KHM_FAILED(code =
+ type->dup(buffer, cbbuf, kcdb_buf_get(&id->buf, slot), &cbdest)))
+ {
+ kcdb_buf_alloc(&id->buf, slot, attr_id, 0);
+ goto _exit;
+ }
+
+ kcdb_buf_set_value_flag(&id->buf, slot);
+
+_exit:
+ LeaveCriticalSection(&cs_ident);
+
+ if(attrib)
+ kcdb_attrib_release_info(attrib);
+ if(type)
+ kcdb_type_release_info(type);
+
+ return code;
+}
+
+KHMEXP khm_int32 KHMAPI
+kcdb_identity_set_attrib(khm_handle vid,
+ const wchar_t * attr_name,
+ void * buffer,
+ khm_size cbbuf)
+{
+ khm_int32 attr_id = -1;
+
+ if(KHM_FAILED(kcdb_attrib_get_id(attr_name, &attr_id)))
+ return KHM_ERROR_INVALID_PARAM;
+
+ return kcdb_identity_set_attr(
+ vid,
+ attr_id,
+ buffer,
+ cbbuf);
+}
+
+KHMEXP khm_int32 KHMAPI
+kcdb_identity_get_attr(khm_handle vid,
+ khm_int32 attr_id,
+ khm_int32 * attr_type,
+ void * buffer,
+ khm_size * pcbbuf)
+{
+ khm_int32 code = KHM_ERROR_SUCCESS;
+ kcdb_identity * id = NULL;
+ kcdb_attrib * attrib = NULL;
+ kcdb_type * type = NULL;
+ khm_size slot;
+
+ if(KHM_FAILED(kcdb_attrib_get_info(attr_id, &attrib))) {
+ return KHM_ERROR_INVALID_PARAM;
+ }
+
+ if(KHM_FAILED(kcdb_type_get_info(attrib->type, &type))) {
+ kcdb_attrib_release_info(attrib);
+ return KHM_ERROR_UNKNOWN;
+ }
+
+ if(attr_type)
+ *attr_type = attrib->type;
+
+ EnterCriticalSection(&cs_ident);
+
+ if(!kcdb_is_active_identity(vid)) {
+ code = KHM_ERROR_INVALID_PARAM;
+ goto _exit;
+ }
+
+ id = (kcdb_identity *) vid;
+
+ if(!(id->flags & KCDB_IDENT_FLAG_ATTRIBS) ||
+ (slot = kcdb_buf_slot_by_id(&id->buf, attr_id)) == KCDB_BUF_INVALID_SLOT ||
+ !kcdb_buf_val_exist(&id->buf, slot))
+ {
+ code = KHM_ERROR_NOT_FOUND;
+ goto _exit;
+ }
+
+ if(!buffer && !pcbbuf) {
+ /* in this case the caller is only trying to determine if the field
+ contains data. If we get here, then the value exists. */
+ code = KHM_ERROR_SUCCESS;
+ goto _exit;
+ }
+
+#if 0
+ if(attrib->flags & KCDB_ATTR_FLAG_COMPUTED) {
+ /* we should never hit this case */
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ code = KHM_ERROR_INVALID_OPERATION;
+ } else {
+#endif
+ code = type->dup(
+ kcdb_buf_get(&id->buf, slot),
+ kcdb_buf_size(&id->buf, slot),
+ buffer,
+ pcbbuf);
+#if 0
+ }
+#endif
+
+_exit:
+ LeaveCriticalSection(&cs_ident);
+ if(type)
+ kcdb_type_release_info(type);
+ if(attrib)
+ kcdb_attrib_release_info(attrib);
+
+ return code;
+}
+
+KHMEXP khm_int32 KHMAPI
+kcdb_identity_get_attrib(khm_handle vid,
+ const wchar_t * attr_name,
+ khm_int32 * attr_type,
+ void * buffer,
+ khm_size * pcbbuf)
+{
+ khm_int32 attr_id = -1;
+
+ if(KHM_FAILED(kcdb_attrib_get_id(attr_name, &attr_id)))
+ return KHM_ERROR_NOT_FOUND;
+
+ return kcdb_identity_get_attr(vid,
+ attr_id,
+ attr_type,
+ buffer,
+ pcbbuf);
+}
+
+KHMEXP khm_int32 KHMAPI
+kcdb_identity_get_attr_string(khm_handle vid,
+ khm_int32 attr_id,
+ wchar_t * buffer,
+ khm_size * pcbbuf,
+ khm_int32 flags)
+{
+ khm_int32 code = KHM_ERROR_SUCCESS;
+ kcdb_identity * id = NULL;
+ kcdb_attrib * attrib = NULL;
+ kcdb_type * type = NULL;
+ khm_size slot;
+
+ if(KHM_FAILED(kcdb_attrib_get_info(attr_id, &attrib))) {
+ return KHM_ERROR_INVALID_PARAM;
+ }
+
+ if(KHM_FAILED(kcdb_type_get_info(attrib->type, &type))) {
+ kcdb_attrib_release_info(attrib);
+ return KHM_ERROR_UNKNOWN;
+ }
+
+ EnterCriticalSection(&cs_ident);
+
+ if(!kcdb_is_active_identity(vid)) {
+ code = KHM_ERROR_INVALID_PARAM;
+ goto _exit;
+ }
+
+ id = (kcdb_identity *) vid;
+
+ if(!(id->flags & KCDB_IDENT_FLAG_ATTRIBS) ||
+ (slot = kcdb_buf_slot_by_id(&id->buf, attr_id)) == KCDB_BUF_INVALID_SLOT ||
+ !kcdb_buf_val_exist(&id->buf, slot))
+ {
+ code = KHM_ERROR_NOT_FOUND;
+ goto _exit;
+ }
+
+ if(!buffer && !pcbbuf) {
+ /* in this case the caller is only trying to determine if the field
+ contains data. If we get here, then the value exists */
+ code = KHM_ERROR_SUCCESS;
+ goto _exit;
+ }
+
+#if 0
+ if(attrib->flags & KCDB_ATTR_FLAG_COMPUTED) {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ code = KHM_ERROR_INVALID_OPERATION;
+ } else {
+#endif
+ if(kcdb_buf_exist(&id->buf, slot)) {
+ code = type->toString(
+ kcdb_buf_get(&id->buf, slot),
+ kcdb_buf_size(&id->buf, slot),
+ buffer,
+ pcbbuf,
+ flags);
+ } else
+ code = KHM_ERROR_NOT_FOUND;
+#if 0
+ }
+#endif
+
+_exit:
+ LeaveCriticalSection(&cs_ident);
+ if(type)
+ kcdb_type_release_info(type);
+ if(attrib)
+ kcdb_attrib_release_info(attrib);
+
+ return code;
+}
+
+KHMEXP khm_int32 KHMAPI
+kcdb_identity_get_attrib_string(khm_handle vid,
+ const wchar_t * attr_name,
+ wchar_t * buffer,
+ khm_size * pcbbuf,
+ khm_int32 flags)
+{
+ khm_int32 attr_id = -1;
+
+ if(KHM_FAILED(kcdb_attrib_get_id(attr_name, &attr_id)))
+ return KHM_ERROR_NOT_FOUND;
+
+ return kcdb_identity_get_attr_string(
+ vid,
+ attr_id,
+ buffer,
+ pcbbuf,
+ flags);
+}
+
+/*****************************************/
+/* Identity provider interface functions */
+
+/* NOT called with cs_ident held */
+KHMEXP khm_int32 KHMAPI
+kcdb_identpro_validate_name(const wchar_t * name)
+{
+ kcdb_ident_name_xfer namex;
+ khm_handle sub;
+ khm_size cch;
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+
+ /* we need to verify the length and the contents of the string
+ before calling the identity provider */
+ if(FAILED(StringCchLength(name, KCDB_IDENT_MAXCCH_NAME, &cch)))
+ return KHM_ERROR_TOO_LONG;
+
+ /* We can't really make an assumption about the valid characters
+ in an identity. So we let the identity provider decide */
+#ifdef VALIDATE_IDENTIY_CHARACTERS
+ if(wcsspn(name, KCDB_IDENT_VALID_CHARS) != cch)
+ return KHM_ERROR_INVALID_NAME;
+#endif
+
+ EnterCriticalSection(&cs_ident);
+ if(kcdb_ident_sub != NULL) {
+ sub = kcdb_ident_sub;
+ } else {
+ sub = NULL;
+ rv = KHM_ERROR_NO_PROVIDER;
+ }
+ LeaveCriticalSection(&cs_ident);
+
+ if(sub != NULL) {
+ ZeroMemory(&namex, sizeof(namex));
+
+ namex.name_src = name;
+ namex.result = KHM_ERROR_NOT_IMPLEMENTED;
+
+ kmq_send_sub_msg(sub,
+ KMSG_IDENT,
+ KMSG_IDENT_VALIDATE_NAME,
+ 0,
+ (void *) &namex);
+
+ rv = namex.result;
+ }
+
+ return rv;
+}
+
+KHMEXP khm_int32 KHMAPI
+kcdb_identpro_validate_identity(khm_handle identity)
+{
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+ khm_handle sub;
+
+ if(!kcdb_is_active_identity(identity))
+ return KHM_ERROR_INVALID_PARAM;
+
+ EnterCriticalSection(&cs_ident);
+ if(kcdb_ident_sub != NULL) {
+ sub = kcdb_ident_sub;
+ } else {
+ sub = NULL;
+ rv = KHM_ERROR_NO_PROVIDER;
+ }
+ LeaveCriticalSection(&cs_ident);
+
+ if(sub != NULL) {
+ rv = kmq_send_sub_msg(sub,
+ KMSG_IDENT,
+ KMSG_IDENT_VALIDATE_IDENTITY,
+ 0,
+ (void *) identity);
+ }
+
+ return rv;
+}
+
+KHMEXP khm_int32 KHMAPI
+kcdb_identpro_canon_name(const wchar_t * name_in,
+ wchar_t * name_out,
+ khm_size * cb_name_out)
+{
+ khm_handle sub;
+ kcdb_ident_name_xfer namex;
+ wchar_t name_tmp[KCDB_IDENT_MAXCCH_NAME];
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+ khm_size cch;
+
+ if(cb_name_out == 0 ||
+ FAILED(StringCchLength(name_in, KCDB_IDENT_MAXCCH_NAME, &cch)))
+ return KHM_ERROR_INVALID_NAME;
+
+ EnterCriticalSection(&cs_ident);
+ if(kcdb_ident_sub != NULL) {
+ sub = kcdb_ident_sub;
+ } else {
+ sub = NULL;
+ rv = KHM_ERROR_NO_PROVIDER;
+ }
+ LeaveCriticalSection(&cs_ident);
+
+ if(sub != NULL) {
+ ZeroMemory(&namex, sizeof(namex));
+ ZeroMemory(name_tmp, sizeof(name_tmp));
+
+ namex.name_src = name_in;
+ namex.name_dest = name_tmp;
+ namex.cb_name_dest = sizeof(name_tmp);
+ namex.result = KHM_ERROR_NOT_IMPLEMENTED;
+
+ rv = kmq_send_sub_msg(sub,
+ KMSG_IDENT,
+ KMSG_IDENT_CANON_NAME,
+ 0,
+ (void *) &namex);
+
+ if(KHM_SUCCEEDED(namex.result)) {
+ const wchar_t * name_result;
+ khm_size cb;
+
+ if(name_in[0] != 0 && name_tmp[0] == 0)
+ name_result = name_tmp;
+ else
+ name_result = name_in;
+
+ if(FAILED(StringCbLength(name_result, KCDB_IDENT_MAXCB_NAME, &cb)))
+ rv = KHM_ERROR_UNKNOWN;
+ else {
+ cb += sizeof(wchar_t);
+ if(name_out == 0 || *cb_name_out < cb) {
+ rv = KHM_ERROR_TOO_LONG;
+ *cb_name_out = cb;
+ } else {
+ StringCbCopy(name_out, *cb_name_out, name_result);
+ *cb_name_out = cb;
+ rv = KHM_ERROR_SUCCESS;
+ }
+ }
+ }
+ }
+
+ return rv;
+}
+
+KHMEXP khm_int32 KHMAPI
+kcdb_identpro_compare_name(const wchar_t * name1,
+ const wchar_t * name2)
+{
+ khm_handle sub;
+ kcdb_ident_name_xfer namex;
+ khm_int32 rv = 0;
+
+ /* Generally in kcdb_identpro_* functions we don't emulate
+ any behavior if the provider is not available, but lacking
+ a way to make this known, we emulate here */
+ rv = wcscmp(name1, name2);
+
+ EnterCriticalSection(&cs_ident);
+ if(kcdb_ident_sub != NULL) {
+ sub = kcdb_ident_sub;
+ } else {
+ sub = NULL;
+ }
+ LeaveCriticalSection(&cs_ident);
+
+ if(sub != NULL) {
+ ZeroMemory(&namex, sizeof(namex));
+ namex.name_src = name1;
+ namex.name_alt = name2;
+ namex.result = rv;
+
+ kmq_send_sub_msg(sub,
+ KMSG_IDENT,
+ KMSG_IDENT_COMPARE_NAME,
+ 0,
+ (void *) &namex);
+
+ rv = namex.result;
+ }
+
+ return rv;
+}
+
+KHMEXP khm_int32 KHMAPI
+kcdb_identpro_set_default(khm_handle identity)
+{
+ khm_handle sub;
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+
+ if((identity != NULL) &&
+ !kcdb_is_active_identity(identity))
+ return KHM_ERROR_INVALID_PARAM;
+
+ EnterCriticalSection(&cs_ident);
+ if(kcdb_ident_sub != NULL) {
+ sub = kcdb_ident_sub;
+ } else {
+ sub = NULL;
+ rv = KHM_ERROR_NO_PROVIDER;
+ }
+ LeaveCriticalSection(&cs_ident);
+
+ if(sub != NULL) {
+ rv = kmq_send_sub_msg(sub,
+ KMSG_IDENT,
+ KMSG_IDENT_SET_DEFAULT,
+ (identity != NULL),
+ (void *) identity);
+ }
+
+ return rv;
+}
+
+KHMEXP khm_int32 KHMAPI
+kcdb_identpro_set_searchable(khm_handle identity,
+ khm_boolean searchable)
+{
+ khm_handle sub;
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+
+ if(!kcdb_is_active_identity(identity))
+ return KHM_ERROR_INVALID_PARAM;
+
+ EnterCriticalSection(&cs_ident);
+ if(kcdb_ident_sub != NULL) {
+ sub = kcdb_ident_sub;
+ } else {
+ sub = NULL;
+ rv = KHM_ERROR_NO_PROVIDER;
+ }
+ LeaveCriticalSection(&cs_ident);
+
+ if(sub != NULL) {
+ rv = kmq_send_sub_msg(
+ sub,
+ KMSG_IDENT,
+ KMSG_IDENT_SET_SEARCHABLE,
+ searchable,
+ (void *) identity);
+ }
+
+ return rv;
+}
+
+
+KHMEXP khm_int32 KHMAPI
+kcdb_identpro_update(khm_handle identity)
+{
+ khm_handle sub;
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+
+ if(!kcdb_is_active_identity(identity))
+ return KHM_ERROR_INVALID_PARAM;
+
+ EnterCriticalSection(&cs_ident);
+ if(kcdb_ident_sub != NULL) {
+ sub = kcdb_ident_sub;
+ } else {
+ sub = NULL;
+ rv = KHM_ERROR_NO_PROVIDER;
+ }
+ LeaveCriticalSection(&cs_ident);
+
+ if(sub != NULL) {
+ rv = kmq_send_sub_msg(sub,
+ KMSG_IDENT,
+ KMSG_IDENT_UPDATE,
+ 0,
+ (void *) identity);
+ }
+
+ return rv;
+}
+
+KHMEXP khm_int32 KHMAPI
+kcdb_identpro_notify_create(khm_handle identity)
+{
+ khm_handle sub;
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+
+ if(!kcdb_is_active_identity(identity))
+ return KHM_ERROR_INVALID_PARAM;
+
+ EnterCriticalSection(&cs_ident);
+ if(kcdb_ident_sub != NULL) {
+ sub = kcdb_ident_sub;
+ } else {
+ sub = NULL;
+ rv = KHM_ERROR_NO_PROVIDER;
+ }
+ LeaveCriticalSection(&cs_ident);
+
+ if(sub != NULL) {
+ rv = kmq_send_sub_msg(
+ sub,
+ KMSG_IDENT,
+ KMSG_IDENT_NOTIFY_CREATE,
+ 0,
+ (void *) identity);
+ }
+
+ return rv;
+}
+
+KHMEXP khm_int32 KHMAPI
+kcdb_identpro_get_ui_cb(void * rock)
+{
+ khm_handle sub;
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+
+ EnterCriticalSection(&cs_ident);
+ if(kcdb_ident_sub != NULL) {
+ sub = kcdb_ident_sub;
+ } else {
+ sub = NULL;
+ rv = KHM_ERROR_NO_PROVIDER;
+ }
+ LeaveCriticalSection(&cs_ident);
+
+ if(sub != NULL) {
+ rv = kmq_send_sub_msg(
+ sub,
+ KMSG_IDENT,
+ KMSG_IDENT_GET_UI_CALLBACK,
+ 0,
+ rock);
+ }
+
+ return rv;
+}
+
+KHMEXP khm_int32 KHMAPI
+kcdb_identity_enum(khm_int32 and_flags,
+ khm_int32 eq_flags,
+ wchar_t * name_buf,
+ khm_size * pcb_buf,
+ khm_size * pn_idents)
+{
+ kcdb_identity * id;
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+ khm_size cb_req = 0;
+ khm_size n_idents = 0;
+ size_t cb_curr;
+ size_t cch_curr;
+ size_t cch_left;
+ HRESULT hr;
+
+ if ((name_buf == NULL && pcb_buf == NULL && pn_idents == NULL) ||
+ (name_buf != NULL && pcb_buf == NULL))
+ return KHM_ERROR_INVALID_PARAM;
+
+ eq_flags &= and_flags;
+
+ EnterCriticalSection(&cs_ident);
+
+ if (!kcdb_checked_config) {
+ khm_handle h_kcdb = NULL;
+ khm_handle h_idents = NULL;
+ khm_handle h_ident = NULL;
+
+ kcdb_checked_config = TRUE;
+ kcdb_checking_config = TRUE;
+
+ h_kcdb = kcdb_get_config();
+ if (!h_kcdb)
+ goto _config_check_cleanup;
+ if(KHM_FAILED(khc_open_space(h_kcdb, L"Identity", 0, &h_idents)))
+ goto _config_check_cleanup;
+
+ while(KHM_SUCCEEDED(khc_enum_subspaces(h_idents,
+ h_ident,
+ &h_ident))) {
+
+ wchar_t wname[KCDB_IDENT_MAXCCH_NAME];
+ khm_size cb;
+ khm_handle t_id;
+
+ cb = sizeof(wname);
+ if (KHM_FAILED(khc_get_config_space_name(h_ident,
+ wname,
+ &cb)))
+ continue;
+
+ LeaveCriticalSection(&cs_ident);
+
+ if (KHM_SUCCEEDED(kcdb_identity_create(wname,
+ KCDB_IDENT_FLAG_CREATE,
+ &t_id)))
+ kcdb_identity_release(t_id);
+
+ EnterCriticalSection(&cs_ident);
+ }
+
+ _config_check_cleanup:
+ if (h_kcdb)
+ khc_close_space(h_kcdb);
+ if (h_idents)
+ khc_close_space(h_idents);
+
+ kcdb_checking_config = FALSE;
+ }
+
+ for ( id = kcdb_identities;
+ id != NULL;
+ id = LNEXT(id) ) {
+ if (((id->flags & KCDB_IDENT_FLAG_ACTIVE) ==
+ KCDB_IDENT_FLAG_ACTIVE) &&
+ ((id->flags & and_flags) == eq_flags)) {
+ n_idents ++;
+ hr = StringCbLength(id->name, KCDB_IDENT_MAXCB_NAME, &cb_curr);
+#ifdef DEBUG
+ assert(SUCCEEDED(hr));
+#endif
+ cb_req += cb_curr + sizeof(wchar_t);
+ }
+ }
+
+ cb_req += sizeof(wchar_t);
+
+ if (pn_idents != NULL)
+ *pn_idents = n_idents;
+
+ if (pcb_buf != NULL && (name_buf == NULL || *pcb_buf < cb_req)) {
+ *pcb_buf = cb_req;
+
+ rv = KHM_ERROR_TOO_LONG;
+ } else if(name_buf != NULL) {
+ cch_left = (*pcb_buf) / sizeof(wchar_t);
+
+ for (id = kcdb_identities;
+ id != NULL;
+ id = LNEXT(id)) {
+ if (((id->flags & KCDB_IDENT_FLAG_ACTIVE) ==
+ KCDB_IDENT_FLAG_ACTIVE) &&
+ ((id->flags & and_flags) == eq_flags)) {
+ StringCchLength(id->name, KCDB_IDENT_MAXCCH_NAME,
+ &cch_curr);
+ cch_curr++;
+ StringCchCopy(name_buf, cch_left, id->name);
+ cch_left -= cch_curr;
+ name_buf += cch_curr;
+ }
+ }
+
+ *name_buf = L'\0';
+ *pcb_buf = cb_req;
+ }
+
+ LeaveCriticalSection(&cs_ident);
+
+ return rv;
+}
diff --git a/src/windows/identity/kcreddb/identity.h b/src/windows/identity/kcreddb/identity.h
index be0205d963..ba55a201ba 100644
--- a/src/windows/identity/kcreddb/identity.h
+++ b/src/windows/identity/kcreddb/identity.h
@@ -1,60 +1,60 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#ifndef __KHIMAIRA_KCDB_IDENTITY_H
-#define __KHIMAIRA_KCDB_IDENTITY_H
-
-/* Identity */
-
-#define KCDB_IDENT_HASHTABLE_SIZE 31
-
-typedef struct kcdb_identity_t {
- khm_int32 magic;
- wchar_t * name;
- khm_int32 flags;
- khm_int32 refcount;
- kcdb_buf buf;
- khm_ui_4 refresh_cycle;
- LDCL(struct kcdb_identity_t);
-} kcdb_identity;
-
-#define KCDB_IDENT_MAGIC 0x31938d4f
-
-extern hashtable * kcdb_identities_namemap;
-extern khm_int32 kcdb_n_identities;
-extern kcdb_identity * kcdb_identities; /* all identities */
-extern kcdb_identity * kcdb_def_identity; /* default identity */
-extern khm_ui_4 kcdb_ident_refresh_cycle;
-
-void kcdbint_ident_init(void);
-void kcdbint_ident_exit(void);
-void kcdbint_ident_msg_completion(kmq_message * m);
-void kcdbint_ident_post_message(khm_int32 op, kcdb_identity * id);
-
-#define kcdb_is_identity(id) ((id) && ((kcdb_identity *)(id))->magic == KCDB_IDENT_MAGIC)
-#define kcdb_is_active_identity(id) (kcdb_is_identity(id) && (((kcdb_identity *)(id))->flags & KCDB_IDENT_FLAG_ACTIVE))
-
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __KHIMAIRA_KCDB_IDENTITY_H
+#define __KHIMAIRA_KCDB_IDENTITY_H
+
+/* Identity */
+
+#define KCDB_IDENT_HASHTABLE_SIZE 31
+
+typedef struct kcdb_identity_t {
+ khm_int32 magic;
+ wchar_t * name;
+ khm_int32 flags;
+ khm_int32 refcount;
+ kcdb_buf buf;
+ khm_ui_4 refresh_cycle;
+ LDCL(struct kcdb_identity_t);
+} kcdb_identity;
+
+#define KCDB_IDENT_MAGIC 0x31938d4f
+
+extern hashtable * kcdb_identities_namemap;
+extern khm_int32 kcdb_n_identities;
+extern kcdb_identity * kcdb_identities; /* all identities */
+extern kcdb_identity * kcdb_def_identity; /* default identity */
+extern khm_ui_4 kcdb_ident_refresh_cycle;
+
+void kcdbint_ident_init(void);
+void kcdbint_ident_exit(void);
+void kcdbint_ident_msg_completion(kmq_message * m);
+void kcdbint_ident_post_message(khm_int32 op, kcdb_identity * id);
+
+#define kcdb_is_identity(id) ((id) && ((kcdb_identity *)(id))->magic == KCDB_IDENT_MAGIC)
+#define kcdb_is_active_identity(id) (kcdb_is_identity(id) && (((kcdb_identity *)(id))->flags & KCDB_IDENT_FLAG_ACTIVE))
+
+#endif
diff --git a/src/windows/identity/kcreddb/init.c b/src/windows/identity/kcreddb/init.c
index 13ef4da552..cea97a8c76 100644
--- a/src/windows/identity/kcreddb/init.c
+++ b/src/windows/identity/kcreddb/init.c
@@ -1,91 +1,91 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<kcreddbinternal.h>
-
-/* set to TRUE when the configuration is loaded */
-static int kcdb_config_loaded = 0;
-
-/* global state cs */
-static CRITICAL_SECTION cs_kcdb_global;
-
-/* forward dcl */
-void KHMAPI kcdb_msg_completion(kmq_message * m);
-
-void kcdb_init(void) {
- /* setup the critical sections */
- InitializeCriticalSection(&cs_kcdb_global);
-
- kmq_set_completion_handler(KMSG_KCDB, kcdb_msg_completion);
-
- kcdb_credtype_init();
- kcdbint_ident_init();
- kcdb_credset_init();
- kcdb_cred_init();
- kcdb_type_init();
- kcdb_attrib_init();
-}
-
-void kcdb_exit(void) {
-
- kcdb_attrib_exit();
- kcdb_type_exit();
- kcdb_cred_exit();
- kcdb_credset_exit();
- kcdbint_ident_exit();
- kcdb_credtype_exit();
-
- kmq_set_completion_handler(KMSG_KCDB, NULL);
-
- DeleteCriticalSection(&cs_kcdb_global);
-}
-
-khm_handle kcdb_get_config(void) {
- khm_handle space = NULL;
-
- EnterCriticalSection(&cs_kcdb_global);
- if(!kcdb_config_loaded) {
- khc_load_schema(NULL, schema_kcdbconfig);
- kcdb_config_loaded = 1;
- }
- khc_open_space(NULL, L"KCDB", 0, &space);
- LeaveCriticalSection(&cs_kcdb_global);
-
- return space;
-}
-
-void KHMAPI kcdb_msg_completion(kmq_message * m) {
- if(!m)
- return;
- if(m->subtype == KMSG_KCDB_IDENT)
- kcdbint_ident_msg_completion(m);
- else if(m->subtype == KMSG_KCDB_ATTRIB)
- kcdb_attrib_msg_completion(m);
- else if(m->subtype == KMSG_KCDB_TYPE)
- kcdb_type_msg_completion(m);
- else if(m->subtype == KMSG_KCDB_CREDTYPE)
- kcdb_credtype_msg_completion(m);
-}
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<kcreddbinternal.h>
+
+/* set to TRUE when the configuration is loaded */
+static int kcdb_config_loaded = 0;
+
+/* global state cs */
+static CRITICAL_SECTION cs_kcdb_global;
+
+/* forward dcl */
+void KHMAPI kcdb_msg_completion(kmq_message * m);
+
+void kcdb_init(void) {
+ /* setup the critical sections */
+ InitializeCriticalSection(&cs_kcdb_global);
+
+ kmq_set_completion_handler(KMSG_KCDB, kcdb_msg_completion);
+
+ kcdb_credtype_init();
+ kcdbint_ident_init();
+ kcdb_credset_init();
+ kcdb_cred_init();
+ kcdb_type_init();
+ kcdb_attrib_init();
+}
+
+void kcdb_exit(void) {
+
+ kcdb_attrib_exit();
+ kcdb_type_exit();
+ kcdb_cred_exit();
+ kcdb_credset_exit();
+ kcdbint_ident_exit();
+ kcdb_credtype_exit();
+
+ kmq_set_completion_handler(KMSG_KCDB, NULL);
+
+ DeleteCriticalSection(&cs_kcdb_global);
+}
+
+khm_handle kcdb_get_config(void) {
+ khm_handle space = NULL;
+
+ EnterCriticalSection(&cs_kcdb_global);
+ if(!kcdb_config_loaded) {
+ khc_load_schema(NULL, schema_kcdbconfig);
+ kcdb_config_loaded = 1;
+ }
+ khc_open_space(NULL, L"KCDB", 0, &space);
+ LeaveCriticalSection(&cs_kcdb_global);
+
+ return space;
+}
+
+void KHMAPI kcdb_msg_completion(kmq_message * m) {
+ if(!m)
+ return;
+ if(m->subtype == KMSG_KCDB_IDENT)
+ kcdbint_ident_msg_completion(m);
+ else if(m->subtype == KMSG_KCDB_ATTRIB)
+ kcdb_attrib_msg_completion(m);
+ else if(m->subtype == KMSG_KCDB_TYPE)
+ kcdb_type_msg_completion(m);
+ else if(m->subtype == KMSG_KCDB_CREDTYPE)
+ kcdb_credtype_msg_completion(m);
+}
diff --git a/src/windows/identity/kcreddb/kcreddb.h b/src/windows/identity/kcreddb/kcreddb.h
index 4b15a245f6..9d54105c45 100644
--- a/src/windows/identity/kcreddb/kcreddb.h
+++ b/src/windows/identity/kcreddb/kcreddb.h
@@ -1,3329 +1,3329 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#ifndef __KHIMAIRA_KCREDDB_H__
-#define __KHIMAIRA_KCREDDB_H__
-
-#include<khdefs.h>
-#include<time.h>
-
-
-/*! \defgroup kcdb NetIDMgr Credentials Database */
-/*@{*/
-
-/*! \brief Maximum length in characters of short description
-
- The length includes the terminating \a NULL character.
- */
-#define KCDB_MAXCCH_SHORT_DESC 256
-
-/*! \brief Maximum length in bytes of short description
-
- The length includes the terminating \a NULL character.
- */
-#define KCDB_MAXCB_SHORT_DESC (sizeof(wchar_t) * KCDB_MAXCCH_SHORT_DESC)
-
-/*! \brief Maximum length in characters of long description
-
- The length includes the terminating \a NULL character.
- */
-#define KCDB_MAXCCH_LONG_DESC 8192
-
-/*! \brief Maximum length in characters of long description
-
- The length includes the terminating \a NULL character.
- */
-#define KCDB_MAXCB_LONG_DESC (sizeof(wchar_t) * KCDB_MAXCCH_LONG_DESC)
-
-/*! \brief Maximum length in characters of name
-
- The length includes the terminating \a NULL character.
- */
-#define KCDB_MAXCCH_NAME 256
-
-/*! \brief Maximum length in bytes of short description
-
- The length includes the terminating \a NULL character.
- */
-#define KCDB_MAXCB_NAME (sizeof(wchar_t) * KCDB_MAXCCH_NAME)
-
-/*! \brief Automatically determine the number of bytes required
-
- Can be used in most places where a count of bytes is required.
- For many objects, the number of bytes that are required can be
- determined through context and may be ommited. In such cases you
- can use the \a KCDB_CBSIZE_AUTO value to specify that the function
- is to determine the size automatically.
-
- \note Not all functions that take a count of bytes support the \a
- KCDB_CBSIZE_AUTO value.
-*/
-#define KCDB_CBSIZE_AUTO (-1)
-
-/*!
-\defgroup kcdb_ident Identities
-
-Functions, macros etc. for manipulating identities.
-*/
-
-/*@{*/
-
-/*! \brief The maximum number of characters (including terminator) that can
- be specified as an identity name */
-#define KCDB_IDENT_MAXCCH_NAME 256
-
-/*! \brief The maximum number of bytes that can be specified as an identity
- name */
-#define KCDB_IDENT_MAXCB_NAME (sizeof(wchar_t) * KCDB_IDENT_MAXCCH_NAME)
-
-/*! \brief Valid characters in an identity name */
-#define KCDB_IDENT_VALID_CHARS L"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ._@-/"
-
-/*!
-\name Flags for identities */
-/*@{*/
-
-/*! \brief Create the identity if it doesn't already exist.
- \note Only to be used with kcdb_identity_create() */
-#define KCDB_IDENT_FLAG_CREATE 0x10000000L
-
-/*! \brief Has configuration information
-
- Indicates that the identity has persistent configuration
- information associated with it.
- */
-#define KCDB_IDENT_FLAG_CONFIG 0x00800000L
-
-/*! \brief Marks the identity as active.
-
- An active identity is one that is in active use within NetIDMgr.
-
- \note This flag is readonly and cannot be specified when creating
- or modifying an identity. Once an identity is deleted, it will
- no longer have this flag. */
-#define KCDB_IDENT_FLAG_ACTIVE 0x02000000L
-
-
-/*! \brief The identity has custom attributes assigned
- */
-#define KCDB_IDENT_FLAG_ATTRIBS 0x08000000L
-
-/*! \brief This is the default identity.
-
- At most one identity will have this flag set at any given time.
- To set or reset the flag, use kcdb_identity_set_default() */
-#define KCDB_IDENT_FLAG_DEFAULT 0x00000001L
-
-/*! \brief This identity can be searched.
-
- The meaning of this flag is left to be interpreted by individual
- plugins. */
-#define KCDB_IDENT_FLAG_SEARCHABLE 0x00000002L
-
-/*! \brief Hidden identity.
-
- The identity will not show up in the identity list window. Once
- the hidden is switched off, the identity (and all associated
- credentials) will re-appear in the window */
-#define KCDB_IDENT_FLAG_HIDDEN 0x00000004L
-
-/*! \brief Invalid identity
-
- For one reason or another, this identity is invalid. This flag
- can be set by an identity provider to indicate that this identity
- does not correspond to an actual identity because an external
- entity (such as a KDC) has denied it's existence.
-
- The absence of this flag does not imply that the identity is
- valid. The ::KCDB_IDENT_FLAG_VALID bit must be set for that to be
- the case. If neither flag is set, then the status of the identity
- is not known.
-*/
-#define KCDB_IDENT_FLAG_INVALID 0x00000008L
-
-/*! \brief Valid identity
-
- The identity has been validated through an external entity, or
- it's validity implied through the existence of credentials for the
- identity.
-
- The absence of this flag does not imply that the identity is
- invalid. The ::KCDB_IDENT_FLAG_INVALID bit must be set for that
- to be the case. If neither flag is set, then the status of the
- identity is not known.
- */
-#define KCDB_IDENT_FLAG_VALID 0x00000010L
-
-/*! \brief Expired identity
-
- This identity has expired and can not be actively used to obtain
- credentials. This determination is made based on the input of
- some external entity. This flag may only be set by an identity
- provider.
-*/
-#define KCDB_IDENT_FLAG_EXPIRED 0x00000020L
-
-/*! \brief Empty identity
-
- The identity does not have actual credentials associated with it.
- */
-#define KCDB_IDENT_FLAG_EMPTY 0x00000040L
-
-/*! \brief Renewable identity
-
- The initial credentials associated with this identity are
- renewable. Thus making the whole identity renewable.
- */
-#define KCDB_IDENT_FLAG_RENEWABLE 0x00000080L
-
-/*! \brief Required user interaction
-
- The identity is in a state which requires user interaction to
- activate. Currently, the identity may not be in a state where it
- can be used to obtain credentials.
-
- A typical example of this is when the primary password for an
- identity has expired.
- */
-#define KCDB_IDENT_FLAG_INTERACT 0x00000100L
-
-/*! \brief Has expired credentials
-
- The identity has expired credentials associated with it.
- */
-#define KCDB_IDENT_FLAG_CRED_EXP 0x00000200L
-
-/*! \brief Has renewable credentials
-
- The identity has renewable credentials associated with it. If the
- initial credentials of the identity are renewable, then identity
- is renewable. Hence the ::KCDB_IDENT_FLAG_RENEWABLE should also
- be set.
- */
-#define KCDB_IDENT_FLAG_CRED_RENEW 0x00000400L
-
-/*! \brief Sticky identity
-
- Sticky identities are identities that are always visible in the
- credentials display even if no credentials are associated with it.
- */
-#define KCDB_IDENT_FLAG_STICKY 0x00000800L
-
-/*! \brief Unknown state
-
- The validity of the identity cannot be determined. This usually
- means that an authority could not be contacted. This flag is to
- be treated as transient. If ::KCDB_IDENT_FLAG_INVALID or
- ::KCDB_IDENT_FLAG_VALID is set for the identity, this flag is to
- be ignored.
- */
-#define KCDB_IDENT_FLAG_UNKNOWN 0x00001000L
-
-/*! \brief Read/write flags mask.
-
- A bitmask that correspond to all the read/write flags in the mask.
-*/
-#define KCDB_IDENT_FLAGMASK_RDWR 0x00001fffL
-
-/*@}*/
-
-/*! \name Identity Provider Data Structures
-@{*/
-
-/*! \brief Name transfer structure
-
- Used when the KCDB is communicating with the identity provider to
- exchange string names of identities. See individual ::KMSG_IDENT
- message subtypes for the usage of this structure.
- */
-typedef struct tag_kcdb_ident_name_xfer {
- const wchar_t * name_src; /*!< An identity name. Does not
- exceed KCDB_IDENT_MAXCCH_NAME
- characters including terminating
- NULL. */
- const wchar_t * name_alt; /*!< An identity name. Does not
- exceed KCDB_IDENT_MAXCCH_NAME
- characters including terminating
- NULL. */
- wchar_t * name_dest; /*!< Pointer to a buffer that is to
- receive a response string. The
- size of the buffer in bytes is
- specified in \a cb_name_dest. */
- khm_size cb_name_dest; /*!< Size of buffer pointed to by \a
- name_dest in bytes. */
- khm_int32 result; /*!< Receives a result value, which is
- usually an error code defined in
- kherror.h, though it is not
- always. */
-} kcdb_ident_name_xfer;
-
-typedef struct tag_kcdb_ident_info {
- khm_handle identity;
- khm_int32 fields;
-
- FILETIME expiration;
-} kcdb_ident_info;
-
-/*@}*/
-
-/*! \name Identity provider interface functions
-
- These functions encapsulate safe calls to the current identity
- provider. While these functions are exported, applications should
- not call these functions directly. They are provided for use by
- the NetIDMgr core application.
-@{*/
-
-/*! \brief Validate an identity name
-
- The name that is provided will be passed through sets of
- validations. One set, which doesn't depend on the identity
- provider checks whether the length of the identity name and
- whether there are any invalid characters in the identity name. If
- the name passes those tests, then the name is passed down to the
- identity provider's name validation handler.
-
- \retval KHM_ERROR_SUCCESS The name is valid
- \retval KHM_ERROR_TOO_LONG Too many characters in name
- \retval KHM_ERROR_INVALID_NAME There were invalid characters in the name.
- \retval KHM_ERROR_NO_PROVIDER There is no identity provider;
- however the name passed the length and character tests.
- \retval KHM_ERROR_NOT_IMPLEMENTED The identity provider doesn't
- implement a name validation handler; however the name passed
- the length and character tests.
-
- \see ::KMSG_IDENT_VALIDATE_NAME
- */
-KHMEXP khm_int32 KHMAPI
-kcdb_identpro_validate_name(const wchar_t * name);
-
-/*! \brief Validate an identity
-
- The identity itself needs to be validated. This may involve
- communicating with an external entity.
-
- \see ::KMSG_IDENT_VALIDATE_IDENTITY
- */
-KHMEXP khm_int32 KHMAPI
-kcdb_identpro_validate_identity(khm_handle identity);
-
-/*! \brief Canonicalize the name
-
-
- \see ::KMSG_IDENT_CANON_NAME
-*/
-KHMEXP khm_int32 KHMAPI
-kcdb_identpro_canon_name(const wchar_t * name_in,
- wchar_t * name_out,
- khm_size * cb_name_out);
-
-/*! \brief Compare two identity names
-
- \see ::KMSG_IDENT_COMPARE_NAME
-*/
-KHMEXP khm_int32 KHMAPI
-kcdb_identpro_compare_name(const wchar_t * name1,
- const wchar_t * name2);
-
-/*! \brief Set the specified identity as the default
-
- \see ::KMSG_IDENT_SET_DEFAULT
-*/
-KHMEXP khm_int32 KHMAPI
-kcdb_identpro_set_default(khm_handle identity);
-
-/*! \brief Set the specified identity as searchable
-
- \see ::KMSG_IDENT_SET_SEARCHABLE
-*/
-KHMEXP khm_int32 KHMAPI
-kcdb_identpro_set_searchable(khm_handle identity,
- khm_boolean searchable);
-
-/*! \brief Update the specified identity
-
- \see ::KMSG_IDENT_UPDATE
-*/
-KHMEXP khm_int32 KHMAPI
-kcdb_identpro_update(khm_handle identity);
-
-/*! \brief Obtain the UI callback
-
- \a rock is actually a pointer to a ::khui_ident_new_creds_cb which
- is to receive the callback.
-
- \see ::KMSG_IDENT_GET_UI_CALLBACK
- */
-KHMEXP khm_int32 KHMAPI
-kcdb_identpro_get_ui_cb(void * rock);
-
-/*! \brief Notify an identity provider of the creation of a new identity
-
- \see ::KMSG_IDENT_NOTIFY_CREATE
-*/
-KHMEXP khm_int32 KHMAPI
-kcdb_identpro_notify_create(khm_handle identity);
-
-/*@}*/
-
-/*! \brief Check if the given name is a valid identity name
-
- \return TRUE or FALSE to the question, is this valid?
-*/
-KHMEXP khm_boolean KHMAPI
-kcdb_identity_is_valid_name(const wchar_t * name);
-
-/*! \brief Create or open an identity.
-
- If the KCDB_IDENT_FLAG_CREATE flag is specified in the flags
- parameter a new identity will be created if one does not already
- exist with the given name. If an identity by that name already
- exists, then the existing identity will be opened. The result
- parameter will receive a held reference to the opened identity.
- Use kcdb_identity_release() to release the handle.
-
- \param[in] name Name of identity to create
- \param[in] flags If KCDB_IDENT_FLAG_CREATE is specified, then the
- identity will be created if it doesn't already exist.
- Additional flags can be set here which will be assigned to the
- identity if it is created. Additional flags have no effect if
- an existing identity is opened.
- \param[out] result If the call is successful, this receives a held
- reference to the identity. The caller should call
- kcdb_identity_release() to release the identity once it is no
- longer needed.
- */
-KHMEXP khm_int32 KHMAPI
-kcdb_identity_create(const wchar_t *name,
- khm_int32 flags,
- khm_handle * result);
-
-/*! \brief Mark an identity for deletion.
-
- The identity will be marked for deletion. The
- KCDB_IDENT_FLAG_ACTIVE will no longer be present for this
- identity. Once all references to the identity are released, it
- will be removed from memory. All associated credentials will also
- be removed. */
-KHMEXP khm_int32 KHMAPI
-kcdb_identity_delete(khm_handle id);
-
-/*! \brief Set or unset the specified flags in the specified identity.
-
- Only flags that are in KCDB_IDENT_FLAGMASK_RDWR can be specifed in
- the \a flags parameter or the \a mask parameter. The flags set in
- the \a mask parameter of the identity will be set to the
- corresponding values in the \a flags parameter.
-
- If ::KCDB_IDENT_FLAG_INVALID is set using this function, then the
- ::KCDB_IDENT_FLAG_VALID will be automatically reset, and vice
- versa. Resetting either bit does not undo this change, and will
- leave the identity's validity unspecified. Setting either of
- ::KCDB_IDENT_FLAG_INVALID or ::KCDB_IDENT_FLAG_VALID will
- automatically reset ::KCDB_IDENT_FLAG_UNKNOWN.
-
- Note that setting or resetting certain flags have other semantic
- side-effects:
-
- - ::KCDB_IDENT_FLAG_DEFAULT : Setting this is equivalent to
- calling kcdb_identity_set_default() with \a id. Resetting this
- is equivalent to calling kcdb_identity_set_default() with NULL.
-
- - ::KCDB_IDENT_FLAG_SEARCHABLE : Setting this will result in the
- identity provider getting notified of the change. If the
- identity provider indicates that searchable flag should not be
- set or reset on the identity, then kcdb_identity_set_flags()
- will return an error.
-
- \note kcdb_identity_set_flags() is not atomic. Even if the
- function returns a failure code, some flags in the identity may
- have been set. When calling kcdb_identity_set_flags() always
- check the flags in the identity using kcdb_identity_get_flags() to
- check which flags have been set and which have failed.
-*/
-KHMEXP khm_int32 KHMAPI
-kcdb_identity_set_flags(khm_handle id,
- khm_int32 flags,
- khm_int32 mask);
-
-/*! \brief Return all the flags for the identity
-
- The returned flags may include internal flags.
-*/
-KHMEXP khm_int32 KHMAPI
-kcdb_identity_get_flags(khm_handle id,
- khm_int32 * flags);
-
-/*! \brief Return the name of the identity
-
- \param[out] buffer Buffer to copy the identity name into. The
- maximum size of an identity name is \a KCDB_IDENT_MAXCB_NAME.
- If \a buffer is \a NULL, then the required size of the buffer
- is returned in \a pcbsize.
-
- \param[in,out] pcbsize Size of buffer in bytes. */
-KHMEXP khm_int32 KHMAPI
-kcdb_identity_get_name(khm_handle id,
- wchar_t * buffer,
- khm_size * pcbsize);
-
-/*! \brief Set the specified identity as the default.
-
- Specifying NULL effectively makes none of the identities the
- default.
-
- \see kcdb_identity_set_flags()
-*/
-KHMEXP khm_int32 KHMAPI
-kcdb_identity_set_default(khm_handle id);
-
-/*! \brief Mark the specified identity as the default.
-
- This API is reserved for use by identity providers as a means of
- specifying which identity is default. The difference between
- kcdb_identity_set_default() and kcdb_identity_set_default_int() is
- in semantics.
-
- - kcdb_identity_set_default() is used to request the KCDB to
- designate the specified identity as the default. When
- processing the request, the KCDB invokes the identity provider
- to do the necessary work to make the identity the default.
-
- - kcdb_identity_set_default_int() is used by the identity provider
- to notify the KCDB that the specified identity is the default.
- This does not result in the invocation of any other semantics to
- make the identity the default other than releasing the previous
- defualt identity and making the specified one the default.
- */
-KHMEXP khm_int32 KHMAPI
-kcdb_identity_set_default_int(khm_handle id);
-
-/*! \brief Get the default identity
-
- Obtain a held handle to the default identity if there is one. The
- handle must be freed using kcdb_identity_release().
-
- If there is no default identity, then the handle pointed to by \a
- pvid is set to \a NULL and the function returns
- KHM_ERROR_NOT_FOUND. */
-KHMEXP khm_int32 KHMAPI
-kcdb_identity_get_default(khm_handle * pvid);
-
-/*! \brief Get the configuration space for the identity.
-
- If the configuration space for the identity does not exist and the
- flags parameter does not specify ::KHM_FLAG_CREATE, then the
- function will return a failure code as specified in
- ::khc_open_space(). Depending on whether or not a configuration
- space was found, the ::KCDB_IDENT_FLAG_CONFIG flag will be set or
- reset for the identity.
-
- \param[in] id Identity for which the configuraiton space is requested
-
- \param[in] flags Flags used when calling khc_open_space(). If \a
- flags specifies KHM_FLAG_CREATE, then the configuration space
- is created.
-
- \param[out] result The resulting handle. If the call is
- successful, this receives a handle to the configuration space.
- Use khc_close_space() to close the handle.
-*/
-KHMEXP khm_int32 KHMAPI
-kcdb_identity_get_config(khm_handle id,
- khm_int32 flags,
- khm_handle * result);
-
-/*! \brief Hold a reference to an identity.
-
- A reference to an identity (a handle) is only valid while it is
- held. \note Once the handle is released, it can not be
- revalidated by calling kcdb_identity_hold(). Doing so would lead
- to unpredictable consequences. */
-KHMEXP khm_int32 KHMAPI
-kcdb_identity_hold(khm_handle id);
-
-/*! \brief Release a reference to an identity.
- \see kcdb_identity_hold() */
-KHMEXP khm_int32 KHMAPI
-kcdb_identity_release(khm_handle id);
-
-/*! \brief Set the identity provider subscription
-
- If there was a previous subscription, that subscription will be
- automatically deleted.
-
- \param[in] sub New identity provider subscription
-*/
-KHMEXP khm_int32 KHMAPI
-kcdb_identity_set_provider(khm_handle sub);
-
-/*! \brief Set the primary credentials type
-
- The primary credentials type is designated by the identity
- provider. As such, this function should only be called by an
- identity provider.
- */
-KHMEXP khm_int32 KHMAPI
-kcdb_identity_set_type(khm_int32 cred_type);
-
-/*! \brief Retrieve the identity provider subscription
-
- \param[out] sub Receives the current identity provider
- subscription. Set to NULL if only the existence of an
- identity provider needs to be checked.
-
- \retval KHM_ERROR_SUCCESS An identity provider exists. If \a sub
- was not NULL, the subscription has been copied there.
-
- \retval KHM_ERROR_NOT_FOUND There is currently no registered
- identity provider. If \a sub was not NULL, the handle it
- points to has been set to NULL.
-*/
-KHMEXP khm_int32 KHMAPI
-kcdb_identity_get_provider(khm_handle * sub);
-
-/*! \brief Retrieve the identity provider credentials type
-
- This is the credentials type that the identity provider has
- designated as the primary credentials type.
- */
-KHMEXP khm_int32 KHMAPI
-kcdb_identity_get_type(khm_int32 * ptype);
-
-/*! \brief Returns TRUE if the two identities are equal
-
- Also returns TRUE if both identities are NULL.
- */
-KHMEXP khm_boolean KHMAPI
-kcdb_identity_is_equal(khm_handle identity1,
- khm_handle identity2);
-
-/*! \brief Set an attribute in an identity by attribute id
-
- \param[in] buffer A pointer to a buffer containing the data to
- assign to the attribute. Setting \a buffer to NULL has the
- effect of removing any data that is already assigned to the
- attribute. If \a buffer is non-NULL, then \a cbbuf should
- specify the number of bytes in \a buffer.
-
- \param[in] cbbuf Number of bytes of data in \a buffer. The
- individual data type handlers may copy in less than this many
- bytes in to the credential.
-*/
-KHMEXP khm_int32 KHMAPI
-kcdb_identity_set_attr(khm_handle identity,
- khm_int32 attr_id,
- void * buffer,
- khm_size cbbuf);
-
-/*! \brief Set an attribute in an identity by name
-
- The attribute name has to be a KCDB registered attribute or
- property.
-
- \param[in] cbbuf Number of bytes of data in \a buffer. The
- individual data type handlers may copy in less than this many
- bytes in to the credential.
-*/
-KHMEXP khm_int32 KHMAPI
-kcdb_identity_set_attrib(khm_handle identity,
- const wchar_t * attr_name,
- void * buffer,
- khm_size cbbuf);
-
-/*! \brief Get an attribute from an identity by attribute id.
-
- \param[in] buffer The buffer that is to receive the attribute
- value. Set this to NULL if only the required buffer size is
- to be returned.
-
- \param[in,out] cbbuf The number of bytes available in \a buffer.
- If \a buffer is not sufficient, returns KHM_ERROR_TOO_LONG and
- sets this to the required buffer size.
-
- \param[out] attr_type Receives the data type of the attribute.
- Set this to NULL if the type is not required.
-
- \note Set both \a buffer and \a cbbuf to NULL if only the
- existence of the attribute is to be checked. If the attribute
- exists in this identity then the function will return
- KHM_ERROR_SUCCESS, otherwise it returns KHM_ERROR_NOT_FOUND.
-*/
-KHMEXP khm_int32 KHMAPI
-kcdb_identity_get_attr(khm_handle identity,
- khm_int32 attr_id,
- khm_int32 * attr_type,
- void * buffer,
- khm_size * pcbbuf);
-
-/*! \brief Get an attribute from an identity by name.
-
- \param[in] buffer The buffer that is to receive the attribute
- value. Set this to NULL if only the required buffer size is
- to be returned.
-
- \param[in,out] cbbuf The number of bytes available in \a buffer.
- If \a buffer is not sufficient, returns KHM_ERROR_TOO_LONG and
- sets this to the required buffer size.
-
- \note Set both \a buffer and \a cbbuf to NULL if only the
- existence of the attribute is to be checked. If the attribute
- exists in this identity then the function will return
- KHM_ERROR_SUCCESS, otherwise it returns KHM_ERROR_NOT_FOUND.
-*/
-KHMEXP khm_int32 KHMAPI
-kcdb_identity_get_attrib(khm_handle identity,
- const wchar_t * attr_name,
- khm_int32 * attr_type,
- void * buffer,
- khm_size * pcbbuf);
-
-/*! \brief Get the string representation of an identity attribute.
-
- A shortcut function which generates the string representation of
- an identity attribute directly.
-
- \param[in] identity A handle to an identity
-
- \param[in] attr_id The attribute to retrieve
-
- \param[out] buffer A pointer to a string buffer which receives the
- string form of the attribute. Set this to NULL if you only
- want to determine the size of the required buffer.
-
- \param[in,out] pcbbuf A pointer to a #khm_int32 that, on entry,
- holds the size of the buffer pointed to by \a buffer, and on
- exit, receives the actual number of bytes that were copied.
-
- \param[in] flags Flags for the string conversion. Can be set to
- one of KCDB_TS_LONG or KCDB_TS_SHORT. The default is
- KCDB_TS_LONG.
-
- \retval KHM_ERROR_SUCCESS Success
- \retval KHM_ERROR_NOT_FOUND The given attribute was either invalid
- or was not defined for this identity
- \retval KHM_ERROR_INVALID_PARAM One or more parameters were invalid
- \retval KHM_ERROR_TOO_LONG Either \a buffer was NULL or the
- supplied buffer was insufficient
-*/
-KHMEXP khm_int32 KHMAPI
-kcdb_identity_get_attr_string(khm_handle identity,
- khm_int32 attr_id,
- wchar_t * buffer,
- khm_size * pcbbuf,
- khm_int32 flags);
-
-/*! \brief Get the string representation of an identity attribute by name.
-
- A shortcut function which generates the string representation of
- an identity attribute directly.
-
- \param[in] identity A handle to an identity
-
- \param[in] attrib The name of the attribute to retrieve
-
- \param[out] buffer A pointer to a string buffer which receives the
- string form of the attribute. Set this to NULL if you only
- want to determine the size of the required buffer.
-
- \param[in,out] pcbbuf A pointer to a #khm_int32 that, on entry,
- holds the size of the buffer pointed to by \a buffer, and on
- exit, receives the actual number of bytes that were copied.
-
- \param[in] flags Flags for the string conversion. Can be set to
- one of KCDB_TS_LONG or KCDB_TS_SHORT. The default is
- KCDB_TS_LONG.
-
- \see kcdb_identity_get_attr_string()
-*/
-KHMEXP khm_int32 KHMAPI
-kcdb_identity_get_attrib_string(khm_handle identity,
- const wchar_t * attr_name,
- wchar_t * buffer,
- khm_size * pcbbuf,
- khm_int32 flags);
-
-/*! \brief Enumerate identities
-
- Enumerates all the active identities that match the criteria
- specified using \a and_flags and \a eq_flags. The condition is
- applied to all active identities as follows:
-
- \code
- (identity->flags & and_flags) == (eq_flags & and_flags)
- \endcode
-
- Essentially, if a flag is set in \a and_flags, then that flag in
- the identity should equal the setting in \a eq_flags.
-
- \param[in] and_flags See above
-
- \param[in] eq_flags See above
-
- \param[out] name_buf Buffer to receive the list of identity names.
- Can be NULL if only the required size of the buffer or the
- number of matching identities is required. The list is
- returned as a multi string.
-
- \param[in,out] pcb_buf Number of bytes in buffer pointed to by \a
- name_buf on entry. On exit, will receive the number of bytes
- copied. Can be NULL only if \a name_buf is also NULL. If \a
- name_buf is NULL or if \a pcb_buf indicates that the buffer is
- insufficient, this will receive the number of bytes required
- and the return value of the function will be
- KHM_ERROR_TOO_LONG
-
- \param[out] pn_idents Receives the number of identities that match
- the given criteria.
-
- \retval KHM_ERROR_SUCCESS If \a name_buf was valid, the buffer now
- contains a multi string of identities that matched. If \a
- pn_idents was valid, it contains the number of identities
- matched.
-
- \retval KHM_ERROR_TOO_LONG No buffer was supplied or the supplied
- buffer was insufficient. If \a pn_idents was valid, it
- contains the number of identities.
-
- \retval KHM_ERROR_INVALID_PARAM None of the parameters \a name_buf,
- \a pcb_buf and \a pn_idents were supplied, or \a pcb_buf was
- NULL when \a name_buf was not.
-
- \note Calling this function to obtain the required size of the
- buffer and then calling it with a that sized buffer is not
- guaranteed to work since the list of identities may change
- between the two calls.
- */
-KHMEXP khm_int32 KHMAPI
-kcdb_identity_enum(khm_int32 and_flags,
- khm_int32 eq_flags,
- wchar_t * name_buf,
- khm_size * pcb_buf,
- khm_size * pn_idents);
-
-/*! \brief Refresh identity attributes based on root credential set
-
- Several flags in an identity are dependent on the credentials that
- are associated with it in the root credential set. In addition,
- other flags in an identity depend on external factors that need to
- be verfied once in a while. This API goes through the root
- credential set as well as consulting the identity provider to
- update an identity.
-
- \see kcdb_identity_refresh()
- */
-KHMEXP khm_int32 KHMAPI
-kcdb_identity_refresh(khm_handle vid);
-
-/*! \brief Refresh all identities
-
- Equivalent to calling kcdb_identity_refresh() for all active
- identities.
-
- \see kcdb_identityt_refresh()
- */
-KHMEXP khm_int32 KHMAPI
-kcdb_identity_refresh_all(void);
-
-/* KSMG_KCDB_IDENT notifications are structured as follows:
- type=KMSG_KCDB
- subtype=KMSG_KCDB_IDENT
- uparam=one of KCDB_OP_*
- blob=handle to identity in question */
-
-/*@}*/
-
-
-/*********************************************************************/
-
-
-/*!
-\defgroup kcdb_creds Credential sets and individual credentials
-
-@{
-*/
-
-
-/*! \brief Credentials process function
-
- This function is called for each credential in a credential set
- when supplied to kcdb_credset_apply(). It should return
- KHM_ERROR_SUCCESS to continue the operation, or any other value to
- terminate the processing.
-
- \see kcdb_credset_apply()
-*/
-typedef khm_int32
-(KHMAPI *kcdb_cred_apply_func)(khm_handle cred,
- void * rock);
-
-/*! \brief Credentials filter function.
-
- Should return non-zero if the credential passed as \a cred is to
- be "accepted". The precise consequence of a non-zero return value
- is determined by the individual function that this call back is
- passed into.
-
- This function should not call any other function which may modify
- \a cred.
-
- \see kcdb_credset_collect_filtered()
- \see kcdb_credset_extract_filtered()
-*/
-typedef khm_int32
-(KHMAPI *kcdb_cred_filter_func)(khm_handle cred,
- khm_int32 flags,
- void * rock);
-
-/*! \brief Credentials compare function.
-
- Asserts a weak ordering on the credentials that are passed in as
- \a cred1 and \a cred2. It should return:
-
- - a negative value if \a cred1 < \a cred2
- - zero if \a cred1 == \a cred2
- - a postive value if \a cred1 > \a cred2
- \see kcdb_credset_sort()
- \see ::kcdb_credtype
-*/
-typedef khm_int32
-(KHMAPI *kcdb_cred_comp_func)(khm_handle cred1,
- khm_handle cred2,
- void * rock);
-
-/*! \defgroup kcdb_credset Credential sets */
-/*@{*/
-
-/*! \brief Create a credential set.
-
- Credential sets are temporary containers for credentials. These
- can be used by plug-ins to store credentials while they are being
- enumerated from an external source. Once all the credentials have
- been collected into the credential set, the plug-in may call
- kcdb_credset_collect() to collect the credentials into the root
- credential store.
-
- The user interface will only display credentials that are in the
- root credential store. No notifications are generated for changes
- to a non-root credential set.
-
- Use kcdb_credset_delete() to delete the credential set once it is
- created.
-
- \see kcdb_credset_delete()
- \see kcdb_credset_collect()
-*/
-KHMEXP khm_int32 KHMAPI
-kcdb_credset_create(khm_handle * result);
-
-/** \brief Delete a credential set
-
- \see kcdb_credset_create()
-*/
-KHMEXP khm_int32 KHMAPI
-kcdb_credset_delete(khm_handle credset);
-
-/** \brief Collect credentials from a credential set to another credential set.
-
- Collecting a subset of credentials from credential set \a cs_src
- into credential set \a cs_dest involves the following steps:
-
- - Select all credentials from \a cs_src that matches the \a
- identity and \a type specified in the function call and add them
- to the \a cs_dest credential set if they are not there already.
- Note that if neither credential set is not the root credential
- store, then the credentials will be added by reference, while if
- it is the root credential store, the credentials will be
- duplicated, and the copies will be added to \a cs_dest.
-
- - If a selected credential in \a cs_src already exists in \a
- cs_dest, then update the credential in \a cs_dest with the
- credential fields in \a cs_src. In other words, once a
- credential is found to exist in both \a cs_src and \a cs_dest,
- all the non-null fields from the credential in \a cs_src will be
- copied to the credential in \a cs_dest. Fields which are null
- (undefined) in \a cs_src and are non-null in \a cs_dest will be
- left unmodified in \a cs_dest.
-
- One notable exception is the credentials' flags. All flags in
- \a cs_src which are not included in
- ::KCDB_CRED_FLAGMASK_ADDITIVE will be copied to the
- corresponding bits in the flags of \a cs_dest. However, flags
- that are included in ::KCDB_CRED_FLAGMASK_ADDITIVE will be added
- to the corresponding bits in \a cs_dest.
-
- (See notes below)
-
- - Remove all credentials from \a cs_dest that match the \a
- identity and \a type that do not appear in \a cs_src. (see notes
- below)
-
- For performance reasons, plugins should use kcdb_credset_collect()
- to update the root credentials store instead of adding and
- removing individual credentials from the root store.
-
- Only credentials that are associated with active identities are
- affected by kcdb_credset_collect().
-
- \param[in] cs_dest A handle to the destination credential set. If
- this is \a NULL, then it is assumed to refer to the root
- credential store.
-
- \param[in] cs_src A handle to the source credential set. If this
- is NULL, then it is assumed to refer to the root credential
- store.
-
- \param[in] identity A handle to an identity. Setting this to NULL
- collects all identities in the credential set.
-
- \param[in] type A credentials type. Setting this to
- KCDB_CREDTYPE_ALL collects all credential types in the set.
-
- \param[out] delta A bit mask that indicates the modifications that
- were made to \a cs_dest as a result of the collect operation.
- This is a combination of KCDB_DELTA_* values. This parameter
- can be \a NULL if the value is not required.
-
- \warning If \a identity and \a type is set to a wildcard, all
- credentials in the root store that are not in this credentials
- set will be deleted.
-
- \note Two credentials \a A and \a B are considered equal if:
- - They refer to the same identity
- - Both have the same credential type
- - Both have the same name
-
- \note This is the only supported way of modifying the root
- credential store.
-
- \note \a cs_src and \a cs_dest can not refer to the same
- credentials set.
-
- \note The destination credential set cannot be sealed.
-*/
-KHMEXP khm_int32 KHMAPI
-kcdb_credset_collect(khm_handle cs_dest,
- khm_handle cs_src,
- khm_handle identity,
- khm_int32 type,
- khm_int32 * delta);
-
-/*! \brief Credentials were added
- \see kcdb_credset_collect() */
-#define KCDB_DELTA_ADD 1
-
-/*! \brief Credentials were deleted
- \see kcdb_credset_collect() */
-#define KCDB_DELTA_DEL 2
-
-/*! \brief Credentials were modified
- \see kcdb_credset_collect() */
-#define KCDB_DELTA_MODIFY 4
-
-/*! \brief Indicates that the credential to be filtered is from the root store.
-
- \see kcdb_credset_collect_filtered()
-*/
-#define KCDB_CREDCOLL_FILTER_ROOT 1
-
-/*! \brief Indicates that the credential to be filtered is from the source
- credential set
-
- \see kcdb_credset_collect_filtered() */
-#define KCDB_CREDCOLL_FILTER_SRC 2
-
-/*! \brief Indicates that the credential to be filtered is from the destination
- credential set
-
- \see kcdb_credset_collect_filtered() */
-#define KCDB_CREDCOLL_FILTER_DEST 4
-
-/*! \brief Collect credentials from one credential set to another using a filter.
-
- Similar to kcdb_credset_collect() except instead of selecting
- credentials by matching against an identity and/or type, a filter
- function is called. If the filter function returns non-zero for a
- credential, that credential is selected.
-
- Credentials in the source and destination credential sets are
- passed into the filter function. Depending on whether the
- credential is in the source credential set or destination
- credential set, the \a flag parameter may have either \a
- KCDB_CREDCOLL_FILTER_SRC or \a KCDB_CREDCOLL_FILTER_DEST bits set.
- Also, if either one of the credential sets is the root credential
- store, then additionally \a KCDB_CREDCOLL_FILTER_ROOT would also
- be set.
-
- See the kcdb_credset_collect() documentation for explanations of
- the \a cs_src, \a cs_dest and \a delta parameters which perform
- identical functions.
-
- \param[in] filter The filter of type ::kcdb_cred_filter_func
- \param[in] rock A custom argument to be passed to the filter function.
-
- \see kcdb_credset_collect()
-*/
-KHMEXP khm_int32 KHMAPI
-kcdb_credset_collect_filtered(khm_handle cs_dest,
- khm_handle cs_src,
- kcdb_cred_filter_func filter,
- void * rock,
- khm_int32 * delta);
-
-/*! \brief Flush all credentials from a credential set
-
- Deletes all the crednetials from the credential set.
-
- \param[in] credset A handle to a credential set. Cannot be NULL.
-
- \note The credential set cannot be sealed
-*/
-KHMEXP khm_int32 KHMAPI
-kcdb_credset_flush(khm_handle credset);
-
-/*! \brief Extract credentials from one credential set to another
-
- Credentials from the source credential set are selected based on
- the \a identity and \a type arguements. If a credential is
- matched, then it is added to the \a destcredset.
-
- If the \a sourcecredset is the root credential set, the added
- credentials are copies of the actual credentials in the root
- credential set. Otherwise the credentials are references to the
- original credentials in the \a sourcecredset .
-
- \param[in] destcredset Destination credential set. Must be valid.
-
- \param[in] sourcecredset The source credential set. If set to
- NULL, extracts from the root credential set.
-
- \param[in] identity The identity to match in the source credential
- set. If set to NULL, matches all identities.
-
- \param[in] type The credential type to match in the source credential set.
- If set to KCDB_CREDTYPE_INVALID, matches all types.
-
- \note This function does not check for duplicate credentials.
-
- \note The destination credential set cannot be sealed.
-*/
-KHMEXP khm_int32 KHMAPI
-kcdb_credset_extract(khm_handle destcredset,
- khm_handle sourcecredset,
- khm_handle identity,
- khm_int32 type);
-
-/*! \brief Extract credentials from one credential set to another using a filter.
-
- Similar to kcdb_credset_extract() except a filter function is used
- to determine which credentials should be selected.
-
- \param[in] rock A custom argument to be passed in to the filter function.
-
- \note The destination credential set cannot be sealed.
-*/
-KHMEXP khm_int32 KHMAPI
-kcdb_credset_extract_filtered(khm_handle destcredset,
- khm_handle sourcecredset,
- kcdb_cred_filter_func filter,
- void * rock);
-
-/*! \brief Retrieve a held reference to a credential in a credential set based on index.
-
- \param[in] idx The index of the credential to retrieve. This is a
- zero based index which goes from 0 ... (size of credset - 1).
-
- \param[out] cred The held reference to a credential. Call
- kcdb_cred_release() to release the credential.
-
- \retval KHM_ERROR_SUCCESS Success. \a cred has a held reference to the credential.
- \retval KHM_ERROR_OUT_OF_BOUNDS The index specified in \a idx is out of bounds.
- \retval KHM_ERROR_DELETED The credential at index \a idx has been marked as deleted.
-
- \see kcdb_cred_release()
-*/
-KHMEXP khm_int32 KHMAPI
-kcdb_credset_get_cred(khm_handle credset,
- khm_int32 idx,
- khm_handle * cred);
-
-/*! \brief Search a credential set for a specific credential
-
- The credential set indicated by \a credset is searched for a
- credential that satisfies the predicate function \a f. Each
- credential starting at \a idx_start is passed into the predicate
- function until it returns a non-zero value. At this point, that
- credential is passed in to the \a cred parameter, and the index of
- the credential is passed into the \a idx parameter.
-
- \param[in] credset The credential set to search on. Specify NULL
- if you want to search teh root credential set.
-
- \param[in] idx_start The index at which to start the search after.
- The first credential passed to the predicate function will be
- at \a idx_start + 1. Specify -1 to start from the beginning
- of the credential set.
-
- \param[in] f The predicate function. The \a flags parameter of
- the predicate function will always receive 0.
-
- \param[in] rock An opaque parameter to be passed to the predicate
- function \a f.
-
- \param[out] cred A held reference to the credential that satisfied
- the predicate function or NULL if no such credential was
- found. Note that if a valid credential is returned, the
- calling function must release the credential using
- kcdb_cred_release().
-
- \param[out] idx The index of the credential passed in \a cred.
- Specify NULL if the index is not required.
-
- \retval KHM_ERROR_SUCCESS A credential that satisfied the
- predicate function was found and was assigned to \a cred.
-
- \retval KHM_ERROR_NOT_FOUND No credential was found that matched
- the predicate function.
-
- \note When querying credential sets that are shared between
- threads, it is possible that another thread modifies the
- credential set between successive calls to
- kcdb_credset_find_filtered(). Therefore a continued sequences of
- searches are not guaranteed to exhastively cover the
- credential set nor to not return duplicate matches. Duplicate
- matches are possible if the order of the credentials in the
- set was changed.
-*/
-KHMEXP khm_int32 KHMAPI
-kcdb_credset_find_filtered(khm_handle credset,
- khm_int32 idx_start,
- kcdb_cred_filter_func f,
- void * rock,
- khm_handle * cred,
- khm_int32 * idx);
-
-/*! \brief Find matching credential
-
- Searches a credential set for a credential that matches the
- specified credential. For a credential to be a match, it must
- have the same identity, credential type and name.
-
- \param[in] credset Credential set to search
-
- \param[in] cred_src Credetial to search on
-
- \param[out] cred_dest receieves the matching credential if the
- search is successful. If a handle is returend, the
- kcdb_cred_release() must be used to release the handle. If
- the matching credential is not required, you can pass in NULL.
-
- \retval KHM_ERROR_SUCCESS The search was successful. A credential
- was assigned to \a cred_dest
-
- \retval KHM_ERROR_NOT_FOUND A matching credential was not found.
- */
-KHMEXP khm_int32 KHMAPI
-kcdb_credset_find_cred(khm_handle credset,
- khm_handle cred_src,
- khm_handle *cred_dest);
-
-
-/*! \brief Delete a credential from a credential set.
-
- The credential at index \a idx will be deleted. All the
- credentials that are at indices \a idx + 1 and above will be moved
- down to fill the gap and the size of the credential set will
- decrease by one.
-
- Use kcdb_credset_del_cred_ref() to delete a credential by
- reference. Using kcdb_credset_del_cred() is faster than
- kcdb_credset_del_cred_ref().
-
- If you call kcdb_credset_del_cred() or kcdb_credset_del_cred_ref()
- from within kcdb_credset_apply(), the credential will only be
- marked as deleted. They will not be removed. This means that the
- size of the credential set will not decrease. To purge the
- deleted credentials from the set, call kcdb_credset_purge() after
- kcdb_credset_apply() completes.
-
- \note The credential set cannot be sealed.
-
- \see kcdb_credset_del_cred_ref()
-*/
-KHMEXP khm_int32 KHMAPI
-kcdb_credset_del_cred(khm_handle credset,
- khm_int32 idx);
-
-/*! \brief Delete a credential from a credential set by reference.
-
- See kcdb_credset_del_cred() for description of what happens when a
- credential is deleted from a credential set.
-
- \note The credential set cannot be sealed.
-
- \see kcdb_credset_del_cred()
-*/
-KHMEXP khm_int32 KHMAPI
-kcdb_credset_del_cred_ref(khm_handle credset,
- khm_handle cred);
-
-/*! \brief Add a credential to a credential set.
-
- The credential is added by reference. In other words, no copy of
- the credential is made.
-
- \param[in] idx Index of the new credential. This must be a value
- in the range 0..(previous size of credential set) or -1. If
- -1 is specifed, then the credential is appended at the end of
- the set.
-
- \note The credential set cannot be sealed.
-*/
-KHMEXP khm_int32 KHMAPI
-kcdb_credset_add_cred(khm_handle credset,
- khm_handle cred,
- khm_int32 idx);
-
-/*! \brief Get the number of credentials in a credential set.
-
- Credentials in a credential set may be volatile. When
- kcdb_credeset_get_size() is called, the credential set is
- compacted to only include credentials that are active at the time.
- However, when you are iterating through the credential set, it
- might be the case that some credentials would get marked as
- deleted. These credentials will remain in the credential set
- until the credential set is discarded or another call to
- kcdb_credset_get_size() or kdcb_credset_purge() is made.
-
- If the credential set is sealed, then it will not be compacted and
- will include deleted credentials as well.
-
- \see kcdb_credset_purge()
- \see kcdb_credset_get_cred()
-*/
-KHMEXP khm_int32 KHMAPI
-kcdb_credset_get_size(khm_handle credset,
- khm_size * size);
-
-/*! \brief Removes credentials that have been marked as deleted from a credential set.
-
- See description of \a kcdb_credset_purge() for a description of
- what happens when credntials that are contained in a credential
- set are deleted by an external entity.
-
- \note The credential set cannot be sealed.
-
- \see kcdb_credset_get_size()
- \see kcdb_credset_get_cred()
-*/
-KHMEXP khm_int32 KHMAPI
-kcdb_credset_purge(khm_handle credset);
-
-/*! \brief Applies a function to all the credentials in a credentials set
-
- The given function is called for each credential in a credential
- set. With each iteration, the function is called with a handle to
- the credential and the user defined parameter \a rock. If the
- function returns anything other than KHM_ERROR_SUCCESS, the
- processing stops.
-
- \param[in] credset The credential set to apply the function to, or
- NULL if you want to apply this to the root credential set.
-
- \param[in] f Function to call for each credential
-
- \param[in] rock An opaque parameter which is to be passed to 'f'
- as the second argument.
-
- \retval KHM_ERROR_SUCCESS All the credentials were processed.
-
- \retval KHM_ERROR_EXIT The supplied function signalled the
- processing to be aborted.
-
- \retval KHM_ERROR_INVALID_PARAM One or more parameters were invalid.
-*/
-KHMEXP khm_int32 KHMAPI
-kcdb_credset_apply(khm_handle credset,
- kcdb_cred_apply_func f,
- void * rock);
-
-/*! \brief Sort the contents of a credential set.
-
- \param[in] rock A custom argument to be passed in to the \a comp function.
-
- \note The credential set cannot be sealed.
-
- \see kcdb_cred_comp_generic()
-*/
-KHMEXP khm_int32 KHMAPI
-kcdb_credset_sort(khm_handle credset,
- kcdb_cred_comp_func comp,
- void * rock);
-
-/*! \brief Seal a credential set
-
- Sealing a credential set makes it read-only. To unseal a
- credential set, call kcdb_credset_unseal().
-
- Sealing is an additive operation. kcdb_credset_seal() can be
- called muliple times. However, for every call to
- kcdb_credset_seal() a call to kcdb_credset_unseal() must be made
- to undo the seal. The credential set will become unsealed when
- all the seals are released.
-
- Once sealed, the credential set will not allow any operation that
- might change its contents. However, a selaed credential set can
- still be delted.
-
- \see kcdb_credset_unseal()
- */
-KHMEXP khm_int32 KHMAPI
-kcdb_credset_seal(khm_handle credset);
-
-/*! \brief Unseal a credential set
-
- Undoes what kcdb_credset_seal() did. This does not guarantee that
- the credential set is unsealed since there may be other seals.
-
- \see kcdb_credset_seal()
- */
-KHMEXP khm_int32 KHMAPI
-kcdb_credset_unseal(khm_handle credset);
-
-/*! \brief Defines a sort criterion for kcdb_cred_comp_generic()
-
- \see kcdb_cred_comp_generic()
-*/
-typedef struct tag_kcdb_cred_comp_field {
- khm_int32 attrib; /*!< a valid attribute ID */
- khm_int32 order; /*!< one of KCDB_CRED_COMP_INCREASING or
- KCDB_CRED_COMP_DECREASING. Optionally,
- KCDB_CRED_COMP_INITIAL_FIRST may be combined
- with either. */
-} kcdb_cred_comp_field;
-
-/*! \brief Defines the sort order for a field in ::kcdb_cred_comp_field
-
- Sorts lexicographically ascending by string representation of field.
-*/
-#define KCDB_CRED_COMP_INCREASING 0
-
-/*! \brief Defines the sort order for a field in ::kcdb_cred_comp_field
-
- Sorts lexicographically descending by string representation of
- field.
- */
-#define KCDB_CRED_COMP_DECREASING 1
-
-/*! \brief Defines the sort order for a field in ::kcdb_cred_comp_field
-
- Any credentials which have the ::KCDB_CRED_FLAG_INITIAL will be
- grouped above any that don't.
-
- If that does not apply, then credentials from the primary
- credentials type will be sorted before others.
-*/
-#define KCDB_CRED_COMP_INITIAL_FIRST 2
-
-/*! \brief Defines the sort criteria for kcdb_cred_comp_generic()
-
- \see kcdb_cred_comp_generic()
-*/
-typedef struct tag_kcdb_cred_comp_order {
- khm_int32 nFields;
- kcdb_cred_comp_field * fields;
-} kcdb_cred_comp_order;
-
-/*! \brief A generic compare function for comparing credentials.
-
- This function can be passed as a parameter to kcdb_credset_sort().
-
- The \a rock parameter to this function should be a pointer to a
- ::kcdb_cred_comp_order object. The \a fields member of the
- ::kcdb_cred_comp_order object should point to an array of
- ::kcdb_cred_comp_field objects, each of which specifies the sort
- order in decreasing order of priority. The number of
- ::kcdb_cred_comp_field objects in the array should correspond to
- the \a nFields member in the ::kcdb_cred_comp_order object.
-
- The array of ::kcdb_cred_comp_field objects define the sort
- criteria, in order. The \a attrib member should be a valid
- attribute ID, while the \a order member determines whether the
- sort order is increasing or decreasing. The exact meaning or
- increasing or decreasing depends on the data type of the
- attribute.
-
- \param[in] rock a pointer to a ::kcdb_cred_comp_order object
-*/
-KHMEXP khm_int32 KHMAPI
-kcdb_cred_comp_generic(khm_handle cred1,
- khm_handle cred2,
- void * rock);
-
-/*@}*/
-
-/*! \defgroup kcdb_cred Credentials */
-/*@{*/
-
-/*! \brief Maximum number of characters in a credential name */
-#define KCDB_CRED_MAXCCH_NAME 256
-
-/*! \brief Maximum number of bytes in a credential name */
-#define KCDB_CRED_MAXCB_NAME (sizeof(wchar_t) * KCDB_CRED_MAXCCH_NAME)
-
-/*! \brief Marked as deleted */
-#define KCDB_CRED_FLAG_DELETED 0x00000008
-
-/*! \brief Renewable */
-#define KCDB_CRED_FLAG_RENEWABLE 0x00000010
-
-/*! \brief Initial
-
- Initial credentials form the basis of an identity. Some
- properties of an initial credential, such as being renewable, are
- directly inherited by the identity. An identity is also
- automatically considered valid if it contains a valid initial
- credential.
- */
-#define KCDB_CRED_FLAG_INITIAL 0x00000020
-
-/*! \brief Expired
-
- The credential's lifetime has ended.
- */
-#define KCDB_CRED_FLAG_EXPIRED 0x00000040
-
-/*! \brief Invalid
-
- The credential can no longer serve its intended function. This
- may be because it is expired and is not renewable, or its
- renewable time period has also expired, or for some other reason.
- */
-#define KCDB_CRED_FLAG_INVALID 0x00000080
-
-/*! \brief Credential is selected
-
- Indicates that the credential is selected. Note that using this
- flag may be subject to race conditions.
- */
-#define KCDB_CRED_FLAG_SELECTED 0x00000100
-
-/*! \brief Bitmask indicating all known credential flags
- */
-#define KCDB_CRED_FLAGMASK_ALL 0x0000ffff
-
-/*! \brief External flags
-
- These are flags that are provided by the credentials providers.
- The other flags are internal to KCDB and should not be modified.
- */
-#define KCDB_CRED_FLAGMASK_EXT (KCDB_CRED_FLAG_INITIAL | KCDB_CRED_FLAG_EXPIRED | KCDB_CRED_FLAG_INVALID | KCDB_CRED_FLAG_RENEWABLE)
-
-/*! \brief Bitmask indicating dditive flags
-
- Additive flags are special flags which are added to exiting
- credentials based on new credentials when doing a collect
- operation. See details on kcdb_credset_collect()
-
- \see kcdb_credset_collect()
-*/
-#define KCDB_CRED_FLAGMASK_ADDITIVE KCDB_CRED_FLAG_SELECTED
-
-/*! \brief Generic credentials request
-
- This data structure is used as the format for a generic
- credentials reqeust for a ::KMSG_KCDB_REQUEST message. A plugin
- typically publishes this message so that a credentials provider
- may handle it and in response, obtain the specified credential.
-
- While the \a identity, \a type and \a name members of the
- structure are all optional, typically one would specify all three
- or at least two for a credential provider to be able to provide
- the credential unambigously.
-
- Credential providers do not need to respond to ::KMSG_KCDB_REQUEST
- messages. However, if they do, they should make sure that they
- are the only credential provider that is responding by setting the
- \a semaphore member to a non-zero value. The \a semaphore is set
- to zero when a request is initially sent out. When incrementing
- the semaphore, the plugin should use a thread safe mechanism to
- ensure that there are no race conditions that would allow more
- than one provider to respond to the message.
- */
-typedef struct tag_kcdb_cred_request {
- khm_handle identity; /*!< Identity of the credential. Set
- to NULL if not specified. */
- khm_int32 type; /*!< Type of the credential. Set to
- KCDB_CREDTYPE_INVALID if not
- specified. */
- wchar_t * name; /*!< Name of the credential. Set to
- NULL if not specified. */
-
- khm_handle dest_credset; /*!< If non-NULL, instructs whoever is
- handling the request that the
- credential thus obtained be placed
- in this credential set in addition
- to whereever it may place newly
- acquired credentials. Note that
- while this can be NULL if the new
- credential does not need to be
- placed in a credential set, it can
- not equal the root credential
- set. */
-
- void * vparam; /*!< An unspecified
- parameter. Specific credential types
- may specify how this field is to be
- used. */
-
- long semaphore; /*!< Incremented by one when this
- request is answered. Only one
- credential provider is allowed to
- answer a ::KMSG_KCDB_REQUEST
- message. Initially, when the
- message is sent out, this member
- should be set to zero. */
-} kcdb_cred_request;
-
-/*! \brief Create a new credential
-
- \param[in] name Name of credential. \a name cannot be NULL and cannot
- exceed \a KCDB_CRED_MAXCCH_NAME unicode characters including the
- \a NULL terminator.
- \param[in] identity A reference to an identity.
- \param[in] cred_type A credentials type identifier for the credential.
- \param[out] result Gets a held reference to the newly created credential.
- Call kcdb_cred_release() or kcdb_cred_delete() to release the
- reference.
- \see kcdb_cred_release()
-*/
-KHMEXP khm_int32 KHMAPI
-kcdb_cred_create(const wchar_t * name,
- khm_handle identity,
- khm_int32 cred_type,
- khm_handle * result);
-
-/*! \brief Duplicate an existing credential.
-
- \param[out] newcred A held reference to the new credential if the call
- succeeds.
-*/
-KHMEXP khm_int32 KHMAPI
-kcdb_cred_dup(khm_handle cred,
- khm_handle * newcred);
-
-/*! \brief Updates one credential using field values from another
-
- All fields that exist in \a vsrc will get copied to \a vdest and will
- overwrite any values that are already there in \a vdest. However any
- values that exist in \a vdest taht do not exist in \a vsrc will not be
- modified.
-
- \retval KHM_ERROR_SUCCESS vdest was successfully updated
- \retval KHM_ERROR_EQUIVALENT all fields in vsrc were present and equivalent in vdest
-*/
-KHMEXP khm_int32 KHMAPI
-kcdb_cred_update(khm_handle vdest,
- khm_handle vsrc);
-
-/*! \brief Set an attribute in a credential by name
-
-
-
- \param[in] cbbuf Number of bytes of data in \a buffer. The
- individual data type handlers may copy in less than this many
- bytes in to the credential. For some data types where the
- size of the buffer is fixed or can be determined from its
- contents, you can specify ::KCDB_CBSIZE_AUTO for this
- parameter.
-*/
-KHMEXP khm_int32 KHMAPI
-kcdb_cred_set_attrib(khm_handle cred,
- const wchar_t * name,
- void * buffer,
- khm_size cbbuf);
-
-/*! \brief Set an attribute in a credential by attribute id
-
- \param[in] buffer A pointer to a buffer containing the data to
- assign to the attribute. Setting this to NULL has the effect
- of removing any data that is already assigned to the
- attribute. If \a buffer is non-NULL, then \a cbbuf should
- specify the number of bytes in \a buffer.
-
- \param[in] cbbuf Number of bytes of data in \a buffer. The
- individual data type handlers may copy in less than this many
- bytes in to the credential.
-*/
-KHMEXP khm_int32 KHMAPI
-kcdb_cred_set_attr(khm_handle cred,
- khm_int32 attr_id,
- void * buffer,
- khm_size cbbuf);
-
-/*! \brief Get an attribute from a credential by name.
-
- \param[in] buffer The buffer that is to receive the attribute
- value. Set this to NULL if only the required buffer size is
- to be returned.
-
- \param[in,out] cbbuf The number of bytes available in \a buffer.
- If \a buffer is not sufficient, returns KHM_ERROR_TOO_LONG and
- sets this to the required buffer size.
-
- \note Set both \a buffer and \a cbbuf to NULL if only the
- existence of the attribute is to be checked. If the attribute
- exists in this credential then the function will return
- KHM_ERROR_SUCCESS, otherwise it returns KHM_ERROR_NOT_FOUND.
-*/
-KHMEXP khm_int32 KHMAPI
-kcdb_cred_get_attrib(khm_handle cred,
- const wchar_t * name,
- khm_int32 * attr_type,
- void * buffer,
- khm_size * cbbuf);
-
-/*! \brief Get an attribute from a credential by attribute id.
-
- \param[in] buffer The buffer that is to receive the attribute
- value. Set this to NULL if only the required buffer size is
- to be returned.
-
- \param[in,out] cbbuf The number of bytes available in \a buffer.
- If \a buffer is not sufficient, returns KHM_ERROR_TOO_LONG and
- sets this to the required buffer size.
-
- \param[out] attr_type Receives the data type of the attribute.
- Set this to NULL if the type is not required.
-
- \note Set both \a buffer and \a cbbuf to NULL if only the
- existence of the attribute is to be checked. If the attribute
- exists in this credential then the function will return
- KHM_ERROR_SUCCESS, otherwise it returns KHM_ERROR_NOT_FOUND.
-*/
-KHMEXP khm_int32 KHMAPI
-kcdb_cred_get_attr(khm_handle cred,
- khm_int32 attr_id,
- khm_int32 * attr_type,
- void * buffer,
- khm_size * cbbuf);
-
-/*! \brief Get the name of a credential.
-
- \param[in] buffer The buffer that is to receive the credential
- name. Set this to NULL if only the required buffer size is to
- be returned.
-
- \param[in,out] cbbuf The number of bytes available in \a buffer.
- If \a buffer is not sufficient, returns KHM_ERROR_TOO_LONG and
- sets this to the required buffer size.
-*/
-KHMEXP khm_int32 KHMAPI
-kcdb_cred_get_name(khm_handle cred,
- wchar_t * buffer,
- khm_size * cbbuf);
-
-/*! \brief Get the string representation of a credential attribute.
-
- A shortcut function which generates the string representation of a
- credential attribute directly.
-
- \param[in] vcred A handle to a credential
-
- \param[in] attr_id The attribute to retrieve
-
- \param[out] buffer A pointer to a string buffer which receives the
- string form of the attribute. Set this to NULL if you only
- want to determine the size of the required buffer.
-
- \param[in,out] pcbbuf A pointer to a #khm_int32 that, on entry,
- holds the size of the buffer pointed to by \a buffer, and on
- exit, receives the actual number of bytes that were copied.
-
- \param[in] flags Flags for the string conversion. Can be set to
- one of KCDB_TS_LONG or KCDB_TS_SHORT. The default is
- KCDB_TS_LONG.
-
- \retval KHM_ERROR_SUCCESS Success
- \retval KHM_ERROR_NOT_FOUND The given attribute was either invalid
- or was not defined for this credential
- \retval KHM_ERROR_INVALID_PARAM One or more parameters were invalid
- \retval KHM_ERROR_TOO_LONG Either \a buffer was NULL or the
- supplied buffer was insufficient
-*/
-KHMEXP khm_int32 KHMAPI
-kcdb_cred_get_attr_string(khm_handle vcred,
- khm_int32 attr_id,
- wchar_t * buffer,
- khm_size * pcbbuf,
- khm_int32 flags);
-
-/*! \brief Get the string representation of a credential attribute by name.
-
- A shortcut function which generates the string representation of a
- credential attribute directly.
-
- \param[in] vcred A handle to a credential
-
- \param[in] attrib The name of the attribute to retrieve
-
- \param[out] buffer A pointer to a string buffer which receives the
- string form of the attribute. Set this to NULL if you only
- want to determine the size of the required buffer.
-
- \param[in,out] pcbbuf A pointer to a #khm_int32 that, on entry,
- holds the size of the buffer pointed to by \a buffer, and on
- exit, receives the actual number of bytes that were copied.
-
- \param[in] flags Flags for the string conversion. Can be set to
- one of KCDB_TS_LONG or KCDB_TS_SHORT. The default is
- KCDB_TS_LONG.
-
- \see kcdb_cred_get_attr_string()
-*/
-KHMEXP khm_int32 KHMAPI
-kcdb_cred_get_attrib_string(khm_handle cred,
- const wchar_t * name,
- wchar_t * buffer,
- khm_size * cbbuf,
- khm_int32 flags) ;
-
-
-/*! \brief Get a held reference to the identity associated with a credential
-
- Use kcdb_identity_release() to release the reference that is
- returned.
-
- \see kcdb_identity_relase()
-*/
-KHMEXP khm_int32 KHMAPI
-kcdb_cred_get_identity(khm_handle cred,
- khm_handle * identity);
-
-/*! \brief Set the identity of a credential
-
- While it is ill-advised to change the identity of a credential
- that has been placed in one or more credential sets, there can be
- legitimate reasons for doing so. Only change the identity of a
- credential that is not placed in a credential set or placed in a
- credential set that is only used by a single entity.
-*/
-KHMEXP khm_int32 KHMAPI
-kcdb_cred_set_identity(khm_handle vcred,
- khm_handle id);
-
-/*! \brief Get the serial number for the credential.
-
- Each credential gets assigned a serial number at the time it is
- created. This will stay with the credential for its lifetime.
-
- \param[out] pserial Receives the serial number. Cannot be NULL.
-*/
-KHMEXP khm_int32 KHMAPI
-kcdb_cred_get_serial(khm_handle cred,
- khm_ui_8 * pserial);
-
-/*! \brief Get the type of the credential.
-
- The returned type is a credential type. Doh.
-
- \param[out] type Receives the type. Cannot be NULL.
-*/
-KHMEXP khm_int32 KHMAPI
-kcdb_cred_get_type(khm_handle cred,
- khm_int32 * type);
-
-/*! \brief Retrieve flags from a credential
-
- The flags returned will be place in the location pointed to by \a
- flags. Note that the specified credential must be an active
- credential for the operation to succeed. This means the
- ::KCDB_CRED_FLAG_DELETED will never be retured by this function.
- */
-KHMEXP khm_int32 KHMAPI
-kcdb_cred_get_flags(khm_handle cred,
- khm_int32 * flags);
-
-/*! \brief Set the flags of a credential
-
- The flags specified in the \a mask parameter will be set to the
- values specified in the \a flags parameter. The flags that are
- not included in \a mask will not be modified.
-
- This function can not be used to set the ::KCDB_CRED_FLAG_DELETED
- flag. If this bit is specified in either \a flags or \a mask, it
- will be ignored.
-
- \see ::KCDB_CRED_FLAGMASK_ALL
- */
-KHMEXP khm_int32 KHMAPI
-kcdb_cred_set_flags(khm_handle cred,
- khm_int32 flags,
- khm_int32 mask);
-
-/*! \brief Hold a reference to a credential.
-
- Use kcdb_cred_release() to release the reference.
-
- \see kcdb_cred_release()
-*/
-KHMEXP khm_int32 KHMAPI
-kcdb_cred_hold(khm_handle cred);
-
-/*! \brief Release a held reference to a credential.
-*/
-KHMEXP khm_int32 KHMAPI
-kcdb_cred_release(khm_handle cred);
-
-/*! \brief Delete a credential.
-
- The credential will be marked for deletion and will continue to
- exist until all held references are released. If the credential
- is bound to a credential set or the root credential store, it will
- be removed from the respective container.
-*/
-KHMEXP khm_int32 KHMAPI
-kcdb_cred_delete(khm_handle cred);
-
-/*! \brief Compare an attribute of two credentials by name.
-
- \return The return value is dependent on the type of the attribute
- and indicate a weak ordering of the attribute values of the two
- credentials. If one or both credentials do not contain the
- attribute, the return value is 0, which signifies that no ordering
- can be determined.
-*/
-KHMEXP khm_int32 KHMAPI
-kcdb_creds_comp_attrib(khm_handle cred1,
- khm_handle cred2,
- const wchar_t * name);
-
-/*! \brief Compare an attribute of two credentials by attribute id.
-
- \return The return value is dependent on the type of the attribute
- and indicate a weak ordering of the attribute values of the two
- credentials. If one or both credentials do not contain the
- attribute, the return value is 0, which signifies that no ordering
- can be determined.
-*/
-KHMEXP khm_int32 KHMAPI
-kcdb_creds_comp_attr(khm_handle cred1,
- khm_handle cred2,
- khm_int32 attr_id);
-
-/*! \brief Compare two credentials for equivalence
-
- \return Non-zero if the two credentials are equal. Zero otherwise.
- \note Two credentials are considered equal if all the following hold:
- - Both refer to the same identity.
- - Both have the same name.
- - Both have the same type.
-*/
-KHMEXP khm_int32 KHMAPI
-kcdb_creds_is_equal(khm_handle cred1,
- khm_handle cred2);
-
-/*@}*/
-/*@}*/
-
-/********************************************************************/
-
-/*! \defgroup kcdb_type Credential attribute types
-
-@{*/
-
-/*! \brief Convert a field to a string
-
- Provides a string representation of a field in a credential. The
- data buffer can be assumed to be valid.
-
- On entry, \a s_buf can be NULL if only the required size of the
- buffer is to be returned. \a pcb_s_buf should be non-NULL and
- should point to a valid variable of type ::khm_size that will, on
- entry, contain the size of the buffer pointed to by \a s_buf if \a
- s_buf is not \a NULL, and on exit will contain the number of bytes
- consumed in \a s_buf, or the required size of the buffer if \a
- s_buf was NULL or the size of the buffer was insufficient.
-
- The implementation should verify the parameters that are passed in
- to the function.
-
- The data pointed to by \a data should not be modified in any way.
-
- \param[in] data Valid pointer to a block of data
-
- \param[in] cb_data Number of bytes in data block pointed to by \a
- data
-
- \param[out] s_buf Buffer to receive the string representation of
- data. If the data type flags has KCDB_TYPE_FLAG_CB_AUTO, then
- this parameter could be set to KCDB_CBSIZE_AUTO. In this
- case, the function should compute the size of the input buffer
- assuming that the input buffer is valid.
-
- \param[in,out] pcb_s_buf On entry, contains the size of the buffer
- pointed to by \a s_buf, and on exit, contains the number of
- bytes used by the string representation of the data including
- the NULL terminator
-
- \param[in] flags Flags for formatting the string
-
- \retval KHM_ERROR_SUCCESS The string representation of the data
- field was successfully copied to \a s_buf and the size of the
- buffer used was copied to \a pcb_s_buf.
-
- \retval KHM_ERROR_INVALID_PARAM One or more parameters were invalid
-
- \retval KHM_ERROR_TOO_LONG Either \a s_buf was \a NULL or the size
- indicated by \a pcb_s_buf was too small to contain the string
- representation of the value. The required size of the buffer
- is in \a pcb_s_buf.
-
- \note This documents the expected behavior of this prototype function
-
- \see ::kcdb_type
- */
-typedef khm_int32
-(KHMAPI *kcdb_dtf_toString)(const void * data,
- khm_size cb_data,
- wchar_t * s_buf,
- khm_size * pcb_s_buf,
- khm_int32 flags);
-
-/*! \brief Verifies whetehr the given buffer contains valid data
-
- The function should examine the buffer and the size of the buffer
- and determine whether or not the buffer contains valid data for
- this data type.
-
- The data field pointed to by \a data should not be modified in any
- way.
-
- \param[in] data A pointer to a data buffer
-
- \param[in] cb_data The number of bytes in the data buffer. If the
- data type flags has KCDB_TYPE_FLAG_CB_AUTO, then this
- parameter could be set to KCDB_CBSIZE_AUTO. In this case, the
- function should compute the size of the input buffer assuming
- that the input buffer is valid.
-
- \return TRUE if the data is valid, FALSE otherwise.
-
- \note This documents the expected behavior of this prototype function
-
- \see ::kcdb_type
-*/
-typedef khm_boolean
-(KHMAPI *kcdb_dtf_isValid)(const void * data,
- khm_size cb_data);
-
-/*! \brief Compare two fields
-
- Compare the two data fields and return a value indicating their
- relative ordering. The return value follows the same
- specification as strcmp().
-
- Both data buffers that are passed in can be assumed to be valid.
-
- None of the data buffers should be modified in any way.
-
- \param[in] data_l Valid pointer to first data buffer
-
- \param[in] cb_data_l Number of bytes in \a data_l. If the data
- type flags has KCDB_TYPE_FLAG_CB_AUTO, then this parameter
- could be set to KCDB_CBSIZE_AUTO. In this case, the function
- should compute the size of the input buffer assuming that the
- input buffer is valid.
-
- \param[in] data_r Valid pointer to second data buffer
-
- \param[in] cb_data_r Number of bytes in \a data_r. If the data
- type flags has KCDB_TYPE_FLAG_CB_AUTO, then this parameter
- could be set to KCDB_CBSIZE_AUTO. In this case, the function
- should compute the size of the input buffer assuming that the
- input buffer is valid.
-
- \return The return value should be
- - Less than zero if \a data_l &lt; \a data_r
- - Equal to zero if \a data_l == \a data_r or if this data type can not be compared
- - Greater than zero if \a data_l &gt; \a data_r
-
- \note This documents the expected behavior of this prototype function
-
- \see ::kcdb_type
-*/
-typedef khm_int32
-(KHMAPI *kcdb_dtf_comp)(const void * data_l,
- khm_size cb_data_l,
- const void * data_r,
- khm_size cb_data_r);
-
-/*! \brief Duplicate a data field
-
- Duplicates a data field. The buffer pointed to by \a data_src
- contains a valid field. The function should copy the field with
- appropriate adjustments to \a data_dst.
-
- The \a data_dst parameter can be NULL if only the required size of
- the buffer is needed. In this case, teh function should set \a
- pcb_data_dst to the number of bytes required and then return
- KHM_ERROR_TOO_LONG.
-
- \param[in] data_src Pointer to a valid data buffer
-
- \param[in] cb_data_src Number of bytes in \a data_src. If the data
- type flags has KCDB_TYPE_FLAG_CB_AUTO, then this parameter
- could be set to KCDB_CBSIZE_AUTO. In this case, the function
- should compute the size of the input buffer assuming that the
- input buffer is valid.
-
- \param[out] data_dst Poitner to destination buffer. Could be NULL
- if only the required size of the destination buffer is to be
- returned.
-
- \param[in,out] pcb_data_dst On entry specifies the number of bytes
- in \a data_dst, and on exit should contain the number of bytes
- copied.
-
- \retval KHM_ERROR_SUCCESS The data was successfully copied. The
- number of bytes copied is in \a pcb_data_dst
-
- \retval KHM_ERROR_INVALID_PARAM One or more parameters is incorrect.
-
- \retval KHM_ERROR_TOO_LONG Either \a data_dst was NULL or the size
- of the buffer was insufficient. The required size is in \a
- pcb_data_dst
-
- \note This documents the expected behavior of this prototype function
-
- \see ::kcdb_type
- */
-typedef khm_int32
-(KHMAPI *kcdb_dtf_dup)(const void * data_src,
- khm_size cb_data_src,
- void * data_dst,
- khm_size * pcb_data_dst);
-
-/*! \brief A data type descriptor.
-
- Handles basic operation for a specific data type.
-
- \see \ref cred_data_types
-*/
-typedef struct tag_kcdb_type {
- wchar_t * name;
- khm_int32 id;
- khm_int32 flags;
-
- khm_size cb_min;
- khm_size cb_max;
-
- kcdb_dtf_toString toString;
- /*!< Provides a string representation for a value. */
-
- kcdb_dtf_isValid isValid;
- /*!< Returns true of the value is valid for this data type */
-
- kcdb_dtf_comp comp;
- /*!< Compare two values and return \a strcmp style return value */
-
- kcdb_dtf_dup dup;
- /*!< Duplicate a value into a secondary buffer */
-} kcdb_type;
-
-/*! \name Flags for kcdb_type::toString
-@{*/
-/*! \brief Specify that the short form of the string representation should be returned.
-
- Flags for #kcdb_type::toString. The flag specifies how long the
- string representation should be. The specific length of a short
- or long description is not restricted and it is up to the
- implementation to choose how to interpret the flags.
-
- Usually, KCDB_TS_SHORT is specified when the amount of space that
- is available to display the string is very restricted. It may be
- the case that the string is truncated to facilitate displaying in
- a constrainted space.
-*/
-#define KCDB_TS_SHORT 1
-
-/*! \brief Specify that the long form of the string representation should be returned
-
- Flags for #kcdb_type::toString. The flag specifies how long the
- string representation should be. The specific length of a short
- or long description is not restricted and it is up to the
- implementation to choose how to interpret the flags.
-
-*/
-#define KCDB_TS_LONG 0
-/*@}*/
-
-/*! \brief The maximum number of bytes allowed for a value of any type */
-#define KCDB_TYPE_MAXCB 16384
-
-/*! \name Flags for kcdb_type
-@{*/
-
-/*! \brief The type supports KCDB_CBSIZE_AUTO.
-
- Used for types where the size of the object can be determined
- through context or by the object content. Such as for objects
- that have a fixed size or unicode strings that have a terminator.
-
- This implies that ALL the object manipulation callbacks that are
- defined in this type definition support the KCDB_CBSIZE_AUTO
- value.
-*/
-#define KCDB_TYPE_FLAG_CB_AUTO 16
-
-/*! \brief The \a cb_min member is valid.
-
- The \a cb_min member defines the minimum number of bytes that an
- object of this type will consume.
-
- \note If this flag is used in conjunction with \a
- KCDB_TYPE_FLAG_CB_MAX then, \a cb_min must be less than or equal
- to \a cb_max.
-*/
-#define KCDB_TYPE_FLAG_CB_MIN 128
-
-/*! \brief The \a cb_max member is valid.
-
- The \a cb_max member defines the maximum number of bytes that an
- object of this type will consume.
-
- \note If this flag is used in conjunction with \a
- KCDB_TYPE_FLAG_CB_MIN then, \a cb_min must be less than or
- equal to \a cb_max. */
-#define KCDB_TYPE_FLAG_CB_MAX 256
-
-/*! \brief Denotes that objects of this type have a fixed size.
-
- If this flags is specified, then the type definition must also
- specify cb_min and cb_max, which must both be the same value.
-
- \note Implies \a KCDB_TYPE_FLAG_CB_AUTO, \a KCDB_TYPE_FLAG_CB_MIN
- and \a KCDB_TYPE_FLAG_CB_MAX. Pay special attention to the
- implication of \a KCDB_TYPE_FLAG_AUTO.
-*/
-#define KCDB_TYPE_FLAG_CB_FIXED (KCDB_TYPE_FLAG_CB_AUTO|KCDB_TYPE_FLAG_CB_MIN|KCDB_TYPE_FLAG_CB_MAX)
-
-/*@}*/
-
-KHMEXP khm_int32 KHMAPI
-kcdb_type_get_id(const wchar_t *name, khm_int32 * id);
-
-/*! \brief Return the type descriptor for a given type id
-
- \param[out] info Receives a held reference to a type descriptor.
- Use kcdb_type_release_info() to release the handle. If the \a
- info parameter is NULL, the function returns KHM_ERROR_SUCCESS
- if \a id is a valid type id, and returns KHM_ERROR_NOT_FOUND
- otherwise.
-
- \see kcdb_type_release_info()
-*/
-KHMEXP khm_int32 KHMAPI
-kcdb_type_get_info(khm_int32 id, kcdb_type ** info);
-
-/*! \brief Release a reference to a type info structure
-
- Releases the reference to the type information obtained with a
- prior call to kcdb_type_get_info().
- */
-KHMEXP khm_int32 KHMAPI
-kcdb_type_release_info(kcdb_type * info);
-
-/*! \brief Get the name of a type
-
- Retrieves the non-localized name of the specified type.
- */
-KHMEXP khm_int32 KHMAPI
-kcdb_type_get_name(khm_int32 id,
- wchar_t * buffer,
- khm_size * cbbuf);
-
-/*! \brief Register a credentials attribute type
-
- The credentials type record pointed to by \a type defines a new
- credential attribute type. The \a id member of \a type may be set
- to KCDB_TYPE_INVALID to indicate that an attribute ID is to be
- generated automatically.
-
- \param[in] type The type descriptor
- \param[out] new_id Receives the identifier for the credential attribute type.
-*/
-KHMEXP khm_int32 KHMAPI
-kcdb_type_register(const kcdb_type * type,
- khm_int32 * new_id);
-
-/*! \brief Unregister a credential attribute type
-
- Removes the registration for the specified credentials attribute
- type.
-*/
-KHMEXP khm_int32 KHMAPI
-kcdb_type_unregister(khm_int32 id);
-
-KHMEXP khm_int32 KHMAPI
-kcdb_type_get_next_free(khm_int32 * id);
-
-/*! \name Conversion functions
-@{*/
-/*! \brief Convert a time_t value to FILETIME
-*/
-KHMEXP void KHMAPI
-TimetToFileTime( time_t t, LPFILETIME pft );
-
-/*! \brief Convert a time_t interval to a FILETIME interval
-*/
-KHMEXP void KHMAPI
-TimetToFileTimeInterval(time_t t, LPFILETIME pft);
-
-/*! \brief Convert a FILETIME interval to seconds
-*/
-KHMEXP long KHMAPI
-FtIntervalToSeconds(LPFILETIME pft);
-
-/*! \brief Convert a FILETIME interval to milliseconds
-*/
-KHMEXP long KHMAPI
-FtIntervalToMilliseconds(LPFILETIME pft);
-
-/*! \brief Compare two FILETIME values
-
- The return value is similar to the return value of strcmp(), based
- on the comparison of the two FILETIME values.
- */
-KHMEXP long KHMAPI
-FtCompare(LPFILETIME pft1, LPFILETIME pft2);
-
-/*! \brief Convert a FILETIME to a 64 bit int
-*/
-KHMEXP khm_int64 KHMAPI FtToInt(LPFILETIME pft);
-
-/*! \brief Convert a 64 bit int to a FILETIME
-*/
-KHMEXP FILETIME KHMAPI IntToFt(khm_int64 i);
-
-/*! \brief Calculate the difference between two FILETIMEs
-
- Returns the value of ft1 - ft2
- */
-KHMEXP FILETIME KHMAPI FtSub(LPFILETIME ft1, LPFILETIME ft2);
-
-/*! \brief Calculate the sum of two FILETIMEs
-
- Return the value of ft1 + ft2
- */
-KHMEXP FILETIME KHMAPI FtAdd(LPFILETIME ft1, LPFILETIME ft2);
-
-/*! \brief Convert a FILETIME inverval to a string
-*/
-KHMEXP khm_int32 KHMAPI
-FtIntervalToString(LPFILETIME data,
- wchar_t * buffer,
- khm_size * cb_buf);
-
-/*! \brief Parse a string representing an interval into a FILETIME interval
-
- The string is a localized string which should look like the
- following:
-
- \code
- [number unit] [number unit]...
- \endcode
-
- where \a number is an integer while \a unit is a localized
- (possibly abbreviated) unit specification. The value of the
- described interval is calculated as the sum of each \a number in
- \a units. For example :
-
- \code
- 1 hour 36 minutes
- \endcode
-
- would result in an interval specification that's equivalent to 1
- hour and 36 minutes. Of course there is no restriction on the
- order in which the \a number \a unit specifications are given and
- the same unit may be repeated multiple times.
-
- \retval KHM_ERROR_INVALID_PARAM The given string was invalid or had
- a token that could not be parsed. It can also mean that \a
- pft was NULL or \a str was NULL.
-
- \retval KHM_ERROR_SUCCESS The string was successfully parsed and
- the result was placed in \a pft.
-*/
-KHMEXP khm_int32 KHMAPI
-IntervalStringToFt(FILETIME * pft, wchar_t * str);
-
-/*! \brief Return number of milliseconds till next representation change
-
- Returns the number of milliseconds that must elapse away from the
- interval specified in pft \a for the representation of pft to change
- from whatever it is right now.
-
- Returns 0 if the representation is not expected to change.
-*/
-KHMEXP long KHMAPI
-FtIntervalMsToRepChange(LPFILETIME pft);
-
-/*! \brief Convert a safe ANSI string to a Unicode string
-
- The resulting string is guaranteed to be NULL terminated and
- within the size limit set by \a cbwstr.
-
- If the whole string cannot be converted, \a wstr is set to an
- empty string.
-
- \return the number of characters converted. This is always either
- the length of the string \a astr or 0.
-*/
-KHMEXP int KHMAPI
-AnsiStrToUnicode( wchar_t * wstr, size_t cbwstr, const char * astr);
-
-/*! \brief Convert a Unicode string to ANSI
-
- The resulting string is guaranteed to be NULL terminated and
- within the size limit set by \a cbdest.
-
- \return the number of characters converted. This is always either
- the length of the string \a src or 0.
-*/
-KHMEXP int KHMAPI
-UnicodeStrToAnsi( char * dest, size_t cbdest, const wchar_t * src);
-/*@}*/
-
-/*! \name Standard type identifiers and names
-@{*/
-
-/*! Maximum identifier number */
-#define KCDB_TYPE_MAX_ID 255
-
-/*! \brief Invalid type
-
- Used by functions that return a type identifier to indicate that
- the returned type identifier is invalid. Also used to indicate
- that a type identifier is not available */
-#define KCDB_TYPE_INVALID (-1)
-
-/*! \brief All types
-
- Used by filters to indicate that all types are allowed.
-*/
-#define KCDB_TYPE_ALL KCDB_TYPE_INVALID
-
-/*! \brief Void
-
- No data. This is not an actual data type.
- */
-#define KCDB_TYPE_VOID 0
-
-/*! \brief String
-
- NULL terminated Unicode string. The byte count for a string
- attribute always includes the terminating NULL.
- */
-#define KCDB_TYPE_STRING 1
-
-/*! \brief Data
-
- A date/time represented in FILETIME format.
- */
-#define KCDB_TYPE_DATE 2
-
-/*! \brief Interval
-
- An interval of time represented as the difference between two
- FILETIME values.
- */
-#define KCDB_TYPE_INTERVAL 3
-
-/*! \brief 32-bit integer
-
- A 32-bit signed integer.
- */
-#define KCDB_TYPE_INT32 4
-
-/*! \brief 64-bit integer
-
- A 64-bit integer.
- */
-#define KCDB_TYPE_INT64 5
-
-/*! \brief Raw data
-
- A raw data buffer.
- */
-#define KCDB_TYPE_DATA 6
-
-#define KCDB_TYPENAME_VOID L"Void"
-#define KCDB_TYPENAME_STRING L"String"
-#define KCDB_TYPENAME_DATE L"Date"
-#define KCDB_TYPENAME_INTERVAL L"Interval"
-#define KCDB_TYPENAME_INT32 L"Int32"
-#define KCDB_TYPENAME_INT64 L"Int64"
-#define KCDB_TYPENAME_DATA L"Data"
-/*@}*/
-/*@}*/
-
-/********************************************************************/
-
-/*! \defgroup kcdb_credattr Credential attributes */
-/*@{*/
-
-/*! \brief Prototype callback function for computed data types.
-
- If the flags for a particular attribute specifies that the value
- is computed, then a callback function should be specified. The
- callback function will be called with a handle to a credential
- along with the attribute ID for the requested attribute. The
- function should place the computed value in \a buffer. The size
- of the buffer in bytes is specifed in \a cbsize. However, if \a
- buffer is \a NULL, then the required buffer size should be placed
- in \a cbsize.
- */
-typedef khm_int32
-(KHMAPI *kcdb_attrib_compute_cb)(khm_handle cred,
- khm_int32 id,
- void * buffer,
- khm_size * cbsize);
-
-/*! \brief Credential attribute descriptor
-
- \see kcdb_attrib_register()
-*/
-typedef struct tag_kcdb_attrib {
- wchar_t * name; /*!< Name. (Not localized,
- required) */
- khm_int32 id; /*!< Identifier. When registering,
- this can be set to
- ::KCDB_ATTR_INVALID if a unique
- identifier is to be generated. */
- khm_int32 alt_id; /*!< Alternate identifier. If the \a
- flags specify
- ::KCDB_ATTR_FLAG_ALTVIEW, then this
- field should specify the identifier
- of the canonical attribute from
- which this attribute is derived. */
- khm_int32 flags; /*!< Flags. Combination of \ref
- kcdb_credattr_flags "attribute
- flags" */
-
- khm_int32 type; /*!< Type of the attribute. Must be valid. */
-
- wchar_t * short_desc; /*!< Short description. (Localized,
- optional) */
-
- wchar_t * long_desc; /*!< Long description. (Localized,
- optional) */
-
- kcdb_attrib_compute_cb compute_cb;
- /*!< Callback. Required if \a flags
- specify ::KCDB_ATTR_FLAG_COMPUTED. */
-
- khm_size compute_min_cbsize;
- /*!< Minimum number of bytes required
- to store this attribute. Required
- if ::KCDB_ATTR_FLAG_COMPUTED is
- specified.*/
- khm_size compute_max_cbsize;
- /*!< Maximum number of bytes required
- to store this attribute. Required
- if ::KCDB_ATTR_FLAG_COMPUTED is
- specified.*/
-} kcdb_attrib;
-
-/*! \brief Retrieve the ID of a named attribute */
-KHMEXP khm_int32 KHMAPI
-kcdb_attrib_get_id(const wchar_t *name,
- khm_int32 * id);
-
-/*! \brief Register an attribute
-
- \param[out] new_id Receives the ID of the newly registered
- attribute. If the \a id member of the ::kcdb_attrib object is
- set to KCDB_ATTR_INVALID, then a unique ID is generated. */
-KHMEXP khm_int32 KHMAPI
-kcdb_attrib_register(const kcdb_attrib * attrib,
- khm_int32 * new_id);
-
-/*! \brief Retrieve the attribute descriptor for an attribute
-
- The descriptor that is returned must be released through a call to
- kcdb_attrib_release_info()
-
- If only the validity of the attribute identifier needs to be
- checked, you can pass in NULL for \a attrib. In this case, if the
- identifier is valid, then the funciton will return
- KHM_ERROR_SUCCESS, otherwise it will return KHM_ERROR_NOT_FOUND.
-
- \see kcdb_attrib_release_info()
- */
-KHMEXP khm_int32 KHMAPI
-kcdb_attrib_get_info(khm_int32 id,
- kcdb_attrib ** attrib);
-
-/*! \brief Release an attribute descriptor
-
- \see kcdb_attrib_get_info()
- */
-KHMEXP khm_int32 KHMAPI
-kcdb_attrib_release_info(kcdb_attrib * attrib);
-
-/*! \brief Unregister an attribute
-
- Once an attribute ID has been unregistered, it may be reclaimed by
- a subsequent call to kcdb_attrib_register().
-*/
-KHMEXP khm_int32 KHMAPI
-kcdb_attrib_unregister(khm_int32 id);
-
-/*! \brief Retrieve the description of an attribute
-
- \param[in] flags Specify \a KCDB_TS_SHORT to retrieve the short description. */
-KHMEXP khm_int32 KHMAPI
-kcdb_attrib_describe(khm_int32 id,
- wchar_t * buffer,
- khm_size * cbsize,
- khm_int32 flags);
-
-/*! \brief Count attributes
-
- Counts the number of attributes that match the given criteria.
- The criteria is specified against the flags of the attribute. An
- attribute is a match if its flags satisfy the condition below:
-
- \code
- (attrib.flags & and_flags) == (eq_flags & and_flags)
- \endcode
-
- The number of attributes that match are returned in \a pcount.
- */
-KHMEXP khm_int32 KHMAPI
-kcdb_attrib_get_count(khm_int32 and_flags,
- khm_int32 eq_flags,
- khm_size * pcount);
-
-/*! \brief List attribute identifiers
-
- Lists the identifiers of the attributes that match the given
- criteria. The criteria is specified against the flags of the
- attribute. An attribute is a match if the following condition is
- satisfied:
-
- \code
- (attrib.flags & and_flags) == (eq_flags & and_flags)
- \endcode
-
- The list of attributes found are copied to the \a khm_int32 array
- specified in \a plist. The number of elements available in the
- buffer \a plist is specified in \a pcsize. On exit, \a pcsize
- will hold the actual number of attribute identifiers copied to the
- array.
-
- \param[in] and_flags See above
- \param[in] eq_flags See above
- \param[in] plist A khm_int32 array
- \param[in,out] pcsize On entry, holds the number of elements
- available in the array pointed to by \a plist. On exit, holds
- the number of elements copied to the array.
-
- \retval KHM_ERROR_SUCCESS The list of attribute identifiers have
- been copied.
- \retval KHM_ERROR_TOO_LONG The list was too long to fit in the
- supplied buffer. As many elements as possible have been
- copied to the \a plist array and the required number of
- elements has been written to \a pcsize.
-
- \note The \a pcsize parameter specifies the number of khm_int32
- elements in the array and not the number of bytes in the
- array. This is different from the usual size parameters used
- in the NetIDMgr API.
- */
-KHMEXP khm_int32 KHMAPI
-kcdb_attrib_get_ids(khm_int32 and_flags,
- khm_int32 eq_flags,
- khm_int32 * plist,
- khm_size * pcsize);
-
-/*! \defgroup kcdb_credattr_flags Attribute flags */
-/*@{*/
-/*! \brief The attribute is required */
-#define KCDB_ATTR_FLAG_REQUIRED 0x00000008
-
-/*! \brief The attribute is computed.
-
- If this flag is set, the \a compute_cb, \a compute_min_cbsize and
- \a compute_max_cbsize members of the ::kcdb_attrib attribute
- descriptor must be assigned valid values.
-*/
-#define KCDB_ATTR_FLAG_COMPUTED 0x00000010
-
-/*! \brief System attribute.
-
- This cannot be specified for a custom attribute. Implies that the
- value of the attribute is given by the credentials database
- itself.
-*/
-#define KCDB_ATTR_FLAG_SYSTEM 0x00000020
-
-/*! \brief Hidden
-
- The attribute is not meant to be displayed to the user. Setting
- this flag prevents this attribute from being listed in the list of
- available data fields in the UI.
-*/
-#define KCDB_ATTR_FLAG_HIDDEN 0x00000040
-
-/*! \brief Property
-
- The attribute is a property. The main difference between regular
- attributes and properties are that properties are not allocated
- off the credentials record. Hence, a property can not be used as
- a credentials field. Other objects such as identities can hold
- property sets. A property set can hold both regular attributes as
- well as properties.
-*/
-#define KCDB_ATTR_FLAG_PROPERTY 0x00000080
-
-/*! \brief Volatile
-
- A volatile property is one whose value changes often, such as
- ::KCDB_ATTR_TIMELEFT. Some controls will make use of additional
- logic to deal with such values, or not display them at all.
- */
-#define KCDB_ATTR_FLAG_VOLATILE 0x00000100
-
-/*! \brief Alternate view
-
- The attribute is actually an alternate representation of another
- attribute. The Canonical attribute name is specified in \a
- alt_id.
-
- Sometimes a certain attribute may need to be represented in
- different ways. You can register multiple attributes for each
- view. However, you should also provide a canonical attribute for
- whenever the canonical set of attributes of the credential is
- required.
- */
-#define KCDB_ATTR_FLAG_ALTVIEW 0x00000200
-
-/*! \brief Transient attribute
-
- A transient attribute is one whose absence is meaningful. When
- updating one record using another, if a transient attribute is
- absent in the source but present in the destination, then the
- attribute is removed from the destination.
-*/
-#define KCDB_ATTR_FLAG_TRANSIENT 0x00000400
-
-/*@}*/
-
-/*! \defgroup kcdb_credattr_idnames Standard attribute IDs and names */
-/*@{*/
-
-/*! \name Attribute related constants */
-/*@{*/
-/*! \brief Maximum valid attribute ID */
-#define KCDB_ATTR_MAX_ID 255
-
-/*! \brief Minimum valid property ID */
-#define KCDB_ATTR_MIN_PROP_ID 4096
-
-/*! \brief Maximum number of properties */
-#define KCDB_ATTR_MAX_PROPS 128
-
-/*! \brief Maximum valid property ID */
-#define KCDB_ATTR_MAX_PROP_ID (KCDB_ATTR_MIN_PROP_ID + KCDB_ATTR_MAX_PROPS - 1)
-
-/*! \brief Invalid ID */
-#define KCDB_ATTR_INVALID (-1)
-
-/*! \brief First custom attribute ID */
-#define KCDB_ATTRID_USER 20
-
-/*@}*/
-
-/*!\name Attribute identifiers */
-/*@{*/
-/*! \brief Name of the credential
-
- - \b Type: STRING
- - \b Flags: REQUIRED, COMPUTED, SYSTEM
- */
-#define KCDB_ATTR_NAME 0
-
-/*! \brief The identity handle for the credential
-
- - \b Type: INT64
- - \b Flags: REQUIRED, COMPUTED, SYSTEM, HIDDEN
-
- \note The handle returned in by specifying this attribute to
- kcdb_cred_get_attr() or kcdb_cred_get_attrib() is not held.
- While the identity is implicitly held for the duration that
- the credential is held, it is not recommended to obtain a
- handle to the identity using this method. Use
- kcdb_cred_get_identity() instead.
-*/
-#define KCDB_ATTR_ID 1
-
-/*! \brief The name of the identity
-
- - \b Type: STRING
- - \b Flags: REQUIRED, COMPUTED, SYSTEM
- */
-#define KCDB_ATTR_ID_NAME 2
-
-/*! \brief The type of the credential
-
- - \b Type: INT32
- - \b Flags: REQUIRED, COMPUTED, SYSTEM, HIDDEN
-*/
-#define KCDB_ATTR_TYPE 3
-
-/*! \brief Type name for the credential
-
- - \b Type: STRING
- - \b Flags: REQUIRED, COMPUTED, SYSTEM
-*/
-#define KCDB_ATTR_TYPE_NAME 4
-
-/*! \brief Name of the parent credential
-
- - \b Type: STRING
- - \b Flags: SYSTEM
-*/
-#define KCDB_ATTR_PARENT_NAME 5
-
-/*! \brief Issed on
-
- - \b Type: DATE
- - \b Flags: SYSTEM
-*/
-#define KCDB_ATTR_ISSUE 6
-
-/*! \brief Expires on
-
- - \b Type: DATE
- - \b Flags: SYSTEM
-*/
-#define KCDB_ATTR_EXPIRE 7
-
-/*! \brief Renewable period expires on
-
- - \b Type: DATE
- - \b Flags: SYSTEM
-*/
-#define KCDB_ATTR_RENEW_EXPIRE 8
-
-/*! \brief Time left till expiration
-
- - \b Type: INTERVAL
- - \b Flags: SYSTEM, COMPUTED, VOLATILE
-*/
-#define KCDB_ATTR_TIMELEFT 9
-
-#define KCDB_ATTR_RENEW_TIMELEFT 10
-
-/*! \brief Location of the credential
-
- - \b Type: STRING
- - \b Flags: SYSTEM
-*/
-#define KCDB_ATTR_LOCATION 11
-
-/*! \brief Lifetime of the credential
-
- - \b Type: INTERVAL
- - \b Flags: SYSTEM
-*/
-#define KCDB_ATTR_LIFETIME 12
-
-#define KCDB_ATTR_RENEW_LIFETIME 13
-
-/*! \brief Flags for the credential
-
- - \b Type: INT32
- - \b Flags: REQUIRED, COMPUTED, SYSTEM, HIDDEN
- */
-#define KCDB_ATTR_FLAGS 14
-
-/*@}*/
-
-/*!\name Attribute names */
-/*@{ */
-
-#define KCDB_ATTRNAME_NAME L"Name"
-#define KCDB_ATTRNAME_ID L"Identity"
-#define KCDB_ATTRNAME_ID_NAME L"IdentityName"
-#define KCDB_ATTRNAME_TYPE L"TypeId"
-#define KCDB_ATTRNAME_TYPE_NAME L"TypeName"
-#define KCDB_ATTRNAME_FLAGS L"Flags"
-
-#define KCDB_ATTRNAME_PARENT_NAME L"Parent"
-#define KCDB_ATTRNAME_ISSUE L"Issued"
-#define KCDB_ATTRNAME_EXPIRE L"Expires"
-#define KCDB_ATTRNAME_RENEW_EXPIRE L"RenewExpires"
-#define KCDB_ATTRNAME_TIMELEFT L"TimeLeft"
-#define KCDB_ATTRNAME_RENEW_TIMELEFT L"RenewTimeLeft"
-#define KCDB_ATTRNAME_LOCATION L"Location"
-#define KCDB_ATTRNAME_LIFETIME L"Lifetime"
-#define KCDB_ATTRNAME_RENEW_LIFETIME L"RenewLifetime"
-
-/*@}*/
-
-/*@}*/
-
-/*@}*/
-
-/*****************************************************************************/
-
-/*! \defgroup kcdb_credtype Credential types */
-/*@{*/
-
-/*! \brief Credential type descriptor */
-typedef struct tag_kcdb_credtype {
- wchar_t * name; /*!< name (less than KCDB_MAXCB_NAME bytes) */
- khm_int32 id;
- wchar_t * short_desc; /*!< short localized description (less
- than KCDB_MAXCB_SHORT_DESC bytes) */
- wchar_t * long_desc; /*!< long localized descriptionn (less
- than KCDB_MAXCB_LONG_DESC bytes) */
- khm_handle sub; /*!< Subscription for credentials type
- hander. This should be a valid
- subscription constructed through a
- call to kmq_create_subscription()
- and must handle KMSG_CRED messages
- that are marked as being sent to
- type specific subscriptions.
-
- The subscription will be
- automatically deleted with a call to
- kmq_delete_subscription() when the
- credentials type is unregistered.*/
-
- kcdb_cred_comp_func is_equal; /*!< Used as an additional clause
- when comparing two credentials for
- equality. The function this is
- actually a comparison function, it
- should return zero if the two
- credentials are equal and non-zero
- if they are not. The addtional \a
- rock parameter is always zero.
-
- It can be assumed that the identity,
- name and credentials type have
- already been found to be equal among
- the credentials and the credential
- type is the type that is being
- registered.*/
-
-#ifdef _WIN32
- HICON icon;
-#endif
-} kcdb_credtype;
-
-/*! \brief Maximum value of a credential type identifier
-
- Credential type identifiers are assigned serially unless the
- process registering the credential type sets a specific identity.
- The maximum identifier number places a hard limit to the number of
- credential types that can be registered at one time, which is
- KCDB_CREDTYPE_MAX_ID + 1.
- */
-#define KCDB_CREDTYPE_MAX_ID 31
-
-/*! \brief Specify all credential types
-
- This value is used by functions which filter credentials based on
- credential types. Specifying this value tells the filter to
- accept all credential types.
- */
-#define KCDB_CREDTYPE_ALL (-1)
-
-/*! \brief Automatically determine a credential type identifier
-
- Used with kcdb_credtype_register() to specify that the credential
- type identifier should be automatically determined to avoid
- collisions.
- */
-#define KCDB_CREDTYPE_AUTO (-2)
-
-/*! \brief An invalid credential type
-
- Even though any non positive credential type ID is invalid
- anywhere where a specific credential type ID is required, this
- value is provided for explicit indication that the credential type
- is invalid. Also it makes code more readable to have a constant
- that shouts out INVALID.
-
-*/
-#define KCDB_CREDTYPE_INVALID (-3)
-
-/*! \brief Macro predicate for testing whether a credtype is valid
-
- Returns TRUE if the given credtype is valid. This is a safe
- macro.
-*/
-#define KCDB_CREDTYPE_IS_VALID(t) ((t) >= 0)
-
-/*! \brief Register a credentials type.
-
- The information given in the \a type parameter is used to register
- a new credential type. Note that the \a name member of the \a
- type should be unique among all credential types.
-
- You can specify ::KCDB_CREDTYPE_AUTO as the \a id member of \a
- type to let kcdb_credtype_register() determine a suitable
- credential type identifier. You can subsequently call
- kcdb_credtype_get_id() to retrieve the generated id or pass a
- valid pointer to a khm_int32 type variable as \a new_id.
-
- \param[in] type Credential type descriptor
-
- \param[out] new_id The credential type identifier that this type
- was registered as.
-
- \retval KHM_ERROR_SUCCESS The credential type was successfully registered.
-
- \retval KHM_ERROR_INVALID_PARAM One or more of the parameters were invalid
-
- \retval KHM_ERROR_TOO_LONG One or more of the string fields in \a
- type exceeded the character limit for that field.
-
- \retval KHM_ERROR_NO_RESOURCES When autogenerating credential type
- identifiers, this value indicates that the maximum number of
- credential types have been registered. No more registrations
- can be accepted unless some credentials type is unregisred.
-
- \retval KHM_ERROR_DUPLICATE The \a name or \a id that was
- specified is already in use.
-*/
-KHMEXP khm_int32 KHMAPI
-kcdb_credtype_register(const kcdb_credtype * type,
- khm_int32 * new_id);
-
-/*! \brief Return a held reference to a \a kcdb_credtype object describing the credential type.
-
- The reference points to a static internal object of type \a
- kcdb_credtype. Use the kcdb_credtype_release_info() function to
- release the reference.
-
- Also, the structure passed in as the \a type argument to
- kcdb_credtype_register() is not valid as a credential type
- descriptor. Use kcdb_credtype_get_info() to obtain the actual
- credential type descriptor.
-
- \param[in] id Credentials type identifier.
-
- \param[out] type Receives the credentials descriptor handle. If
- \a type is NULL, then no handle is returned. However, the
- function will still return \a KHM_ERROR_SUCCESS if the \a id
- parameter passed in is a valid credentials type identifier.
-
- \see kcdb_credtype_release_info()
- \see kcdb_credtype_register()
-*/
-KHMEXP khm_int32 KHMAPI
-kcdb_credtype_get_info(khm_int32 id,
- kcdb_credtype ** type);
-
-/*! \brief Release a reference to a \a kcdb_credtype object
-
- Undoes the hold obtained on a \a kcdb_credtype object from a
- previous call to kcdb_credtype_get_info().
-
- \see kcdb_credtype_get_info()
- */
-KHMEXP khm_int32 KHMAPI
-kcdb_credtype_release_info(kcdb_credtype * type);
-
-/*! \brief Unregister a credentials type
-
- Undoes the registration performed by kcdb_credtype_register().
-
- This should only be done when the credentials provider is being
- unloaded.
- */
-KHMEXP khm_int32 KHMAPI
-kcdb_credtype_unregister(khm_int32 id);
-
-/*! \brief Retrieve the name of a credentials type
-
- Given a credentials type identifier, retrieves the name. The name
- is not localized and serves as a persistent identifier of the
- credentials type.
-
- \param[out] buf The buffer to receive the name. Could be \a NULL
- if only the length of the buffer is required.
-
- \param[in,out] cbbuf On entry, specifies the size of the buffer
- pointed to by \a buf if \a buf is not NULL. On exit, contains
- the number of bytes copied to \a buf or the required size of
- the buffer.
-
- \retval KHM_ERROR_SUCCESS The call succeeded.
-
- \retval KHM_ERROR_TOO_LONG Either \a buf was NULL or the supplied
- buffer was not large enough. The required size is in \a cbbuf.
-
- \retval KHM_ERROR_INVALID_PARAM Invalid parameter.
- */
-KHMEXP khm_int32 KHMAPI
-kcdb_credtype_get_name(khm_int32 id,
- wchar_t * buf,
- khm_size * cbbuf);
-
-/*! \brief Retrieve the type specific subscription for a type
-
- Given a credentials type, this function returns the credentials
- type specific subcription. It may return NULL if the subscription
- is not available.
- */
-KHMEXP khm_handle KHMAPI
-kcdb_credtype_get_sub(khm_int32 id);
-
-/*! \brief Get the description of a credentials type
-
- Unlike the name of a credential type, the description is localized.
-
- \param[in] id Credentials type identifier
-
- \param[out] buf Receives the description. Can bet set to NULL if
- only the size of the buffer is required.
-
- \param[in,out] cbbuf On entry, specifies the size of the buffer
- pointed to by \a buf. On exit, specifies the required size of
- the buffer or the number of bytes copied, depending on whether
- the call succeeded or not.
-
- \param[in] flags Specify ::KCDB_TS_SHORT if the short version of
- the description is desired if there is more than one.
-
- \retval KHM_ERROR_SUCCESS The call succeeded
- \retval KHM_ERROR_TOO_LONG Either \a buf was NULL or the supplied buffer was insufficient. The required size is specified in \a cbbuf.
- \retval KHM_ERROR_INVALID_PARAM One or more parameters were invalid.
- */
-KHMEXP khm_int32 KHMAPI
-kcdb_credtype_describe(khm_int32 id,
- wchar_t * buf,
- khm_size * cbbuf,
- khm_int32 flags);
-
-/*! \brief Look up the identifier of a credentials type by name
-
- Given a name, looks up the identifier.
-
- \param[in] name Name of the credentials type
- \param[out] id Receives the identifier if the call succeeds
-
- */
-KHMEXP khm_int32 KHMAPI
-kcdb_credtype_get_id(const wchar_t * name,
- khm_int32 * id);
-
-/*@}*/
-
-/*********************************************************************/
-
-/*! \defgroup kcdb_buf Generic access to buffer
-
- Currently, credentials and identities both hold record data types.
- This set of API's allow an application to access fields in the
- records using a single interface. Note that credentials only
- accept regular attributes while identities can hold both
- attributes and properties.
-
- Handles to credentials and identities are implicitly also handles
- to records. Thus they can be directly used as such.
-*/
-/*@{*/
-
-/*! \brief Get an attribute from a record by attribute id.
-
- \param[in] buffer The buffer that is to receive the attribute
- value. Set this to NULL if only the required buffer size is
- to be returned.
-
- \param[in,out] cbbuf The number of bytes available in \a buffer.
- If \a buffer is not sufficient, returns KHM_ERROR_TOO_LONG and
- sets this to the required buffer size.
-
- \param[out] attr_type Receives the data type of the attribute.
- Set this to NULL if the type is not required.
-
- \note Set both \a buffer and \a cbbuf to NULL if only the
- existence of the attribute is to be checked. If the attribute
- exists in this record then the function will return
- KHM_ERROR_SUCCESS, otherwise it returns KHM_ERROR_NOT_FOUND.
-*/
-KHMEXP khm_int32 KHMAPI
-kcdb_buf_get_attr(khm_handle record,
- khm_int32 attr_id,
- khm_int32 * attr_type,
- void * buffer,
- khm_size * pcb_buf);
-
-/*! \brief Get an attribute from a record by name.
-
- \param[in] buffer The buffer that is to receive the attribute
- value. Set this to NULL if only the required buffer size is
- to be returned.
-
- \param[in,out] cbbuf The number of bytes available in \a buffer.
- If \a buffer is not sufficient, returns KHM_ERROR_TOO_LONG and
- sets this to the required buffer size.
-
- \note Set both \a buffer and \a cbbuf to NULL if only the
- existence of the attribute is to be checked. If the attribute
- exists in this record then the function will return
- KHM_ERROR_SUCCESS, otherwise it returns KHM_ERROR_NOT_FOUND.
-*/
-KHMEXP khm_int32 KHMAPI
-kcdb_buf_get_attrib(khm_handle record,
- const wchar_t * attr_name,
- khm_int32 * attr_type,
- void * buffer,
- khm_size * pcb_buf);
-
-/*! \brief Get the string representation of a record attribute.
-
- A shortcut function which generates the string representation of a
- record attribute directly.
-
- \param[in] record A handle to a record
-
- \param[in] attr_id The attribute to retrieve
-
- \param[out] buffer A pointer to a string buffer which receives the
- string form of the attribute. Set this to NULL if you only
- want to determine the size of the required buffer.
-
- \param[in,out] pcbbuf A pointer to a #khm_int32 that, on entry,
- holds the size of the buffer pointed to by \a buffer, and on
- exit, receives the actual number of bytes that were copied.
-
- \param[in] flags Flags for the string conversion. Can be set to
- one of KCDB_TS_LONG or KCDB_TS_SHORT. The default is
- KCDB_TS_LONG.
-
- \retval KHM_ERROR_SUCCESS Success
- \retval KHM_ERROR_NOT_FOUND The given attribute was either invalid
- or was not defined for this record
- \retval KHM_ERROR_INVALID_PARAM One or more parameters were invalid
- \retval KHM_ERROR_TOO_LONG Either \a buffer was NULL or the
- supplied buffer was insufficient
-*/
-KHMEXP khm_int32 KHMAPI
-kcdb_buf_get_attr_string(khm_handle record,
- khm_int32 attr_id,
- wchar_t * buffer,
- khm_size * pcbbuf,
- khm_int32 flags);
-
-/*! \brief Get the string representation of a record attribute by name.
-
- A shortcut function which generates the string representation of a
- record attribute directly.
-
- \param[in] record A handle to a record
-
- \param[in] attrib The name of the attribute to retrieve
-
- \param[out] buffer A pointer to a string buffer which receives the
- string form of the attribute. Set this to NULL if you only
- want to determine the size of the required buffer.
-
- \param[in,out] pcbbuf A pointer to a #khm_int32 that, on entry,
- holds the size of the buffer pointed to by \a buffer, and on
- exit, receives the actual number of bytes that were copied.
-
- \param[in] flags Flags for the string conversion. Can be set to
- one of KCDB_TS_LONG or KCDB_TS_SHORT. The default is
- KCDB_TS_LONG.
-
- \see kcdb_cred_get_attr_string()
-*/
-KHMEXP khm_int32 KHMAPI
-kcdb_buf_get_attrib_string(khm_handle record,
- const wchar_t * attr_name,
- wchar_t * buffer,
- khm_size * pcbbuf,
- khm_int32 flags);
-
-/*! \brief Set an attribute in a record by attribute id
-
- \param[in] cbbuf Number of bytes of data in \a buffer. The
- individual data type handlers may copy in less than this many
- bytes in to the record.
-*/
-KHMEXP khm_int32 KHMAPI
-kcdb_buf_set_attr(khm_handle record,
- khm_int32 attr_id,
- void * buffer,
- khm_size cbbuf);
-
-/*! \brief Set an attribute in a record by name
-
- \param[in] cbbuf Number of bytes of data in \a buffer. The
- individual data type handlers may copy in less than this many
- bytes in to the record.
-*/
-KHMEXP khm_int32 KHMAPI
-kcdb_buf_set_attrib(khm_handle record,
- const wchar_t * attr_name,
- void * buffer,
- khm_size cbbuf);
-
-KHMEXP khm_int32 KHMAPI
-kcdb_buf_hold(khm_handle record);
-
-KHMEXP khm_int32 KHMAPI
-kcdb_buf_release(khm_handle record);
-
-/*@}*/
-
-/********************************************************************/
-
-/* Notification operation constants */
-
-#define KCDB_OP_INSERT 1
-#define KCDB_OP_DELETE 2
-#define KCDB_OP_MODIFY 3
-#define KCDB_OP_ACTIVATE 4
-#define KCDB_OP_DEACTIVATE 5
-#define KCDB_OP_HIDE 6
-#define KCDB_OP_UNHIDE 7
-#define KCDB_OP_SETSEARCH 8
-#define KCDB_OP_UNSETSEARCH 9
-#define KCDB_OP_NEW_DEFAULT 10
-#define KCDB_OP_DELCONFIG 11
-
-/*@}*/
-
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __KHIMAIRA_KCREDDB_H__
+#define __KHIMAIRA_KCREDDB_H__
+
+#include<khdefs.h>
+#include<time.h>
+
+
+/*! \defgroup kcdb NetIDMgr Credentials Database */
+/*@{*/
+
+/*! \brief Maximum length in characters of short description
+
+ The length includes the terminating \a NULL character.
+ */
+#define KCDB_MAXCCH_SHORT_DESC 256
+
+/*! \brief Maximum length in bytes of short description
+
+ The length includes the terminating \a NULL character.
+ */
+#define KCDB_MAXCB_SHORT_DESC (sizeof(wchar_t) * KCDB_MAXCCH_SHORT_DESC)
+
+/*! \brief Maximum length in characters of long description
+
+ The length includes the terminating \a NULL character.
+ */
+#define KCDB_MAXCCH_LONG_DESC 8192
+
+/*! \brief Maximum length in characters of long description
+
+ The length includes the terminating \a NULL character.
+ */
+#define KCDB_MAXCB_LONG_DESC (sizeof(wchar_t) * KCDB_MAXCCH_LONG_DESC)
+
+/*! \brief Maximum length in characters of name
+
+ The length includes the terminating \a NULL character.
+ */
+#define KCDB_MAXCCH_NAME 256
+
+/*! \brief Maximum length in bytes of short description
+
+ The length includes the terminating \a NULL character.
+ */
+#define KCDB_MAXCB_NAME (sizeof(wchar_t) * KCDB_MAXCCH_NAME)
+
+/*! \brief Automatically determine the number of bytes required
+
+ Can be used in most places where a count of bytes is required.
+ For many objects, the number of bytes that are required can be
+ determined through context and may be ommited. In such cases you
+ can use the \a KCDB_CBSIZE_AUTO value to specify that the function
+ is to determine the size automatically.
+
+ \note Not all functions that take a count of bytes support the \a
+ KCDB_CBSIZE_AUTO value.
+*/
+#define KCDB_CBSIZE_AUTO (-1)
+
+/*!
+\defgroup kcdb_ident Identities
+
+Functions, macros etc. for manipulating identities.
+*/
+
+/*@{*/
+
+/*! \brief The maximum number of characters (including terminator) that can
+ be specified as an identity name */
+#define KCDB_IDENT_MAXCCH_NAME 256
+
+/*! \brief The maximum number of bytes that can be specified as an identity
+ name */
+#define KCDB_IDENT_MAXCB_NAME (sizeof(wchar_t) * KCDB_IDENT_MAXCCH_NAME)
+
+/*! \brief Valid characters in an identity name */
+#define KCDB_IDENT_VALID_CHARS L"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ._@-/"
+
+/*!
+\name Flags for identities */
+/*@{*/
+
+/*! \brief Create the identity if it doesn't already exist.
+ \note Only to be used with kcdb_identity_create() */
+#define KCDB_IDENT_FLAG_CREATE 0x10000000L
+
+/*! \brief Has configuration information
+
+ Indicates that the identity has persistent configuration
+ information associated with it.
+ */
+#define KCDB_IDENT_FLAG_CONFIG 0x00800000L
+
+/*! \brief Marks the identity as active.
+
+ An active identity is one that is in active use within NetIDMgr.
+
+ \note This flag is readonly and cannot be specified when creating
+ or modifying an identity. Once an identity is deleted, it will
+ no longer have this flag. */
+#define KCDB_IDENT_FLAG_ACTIVE 0x02000000L
+
+
+/*! \brief The identity has custom attributes assigned
+ */
+#define KCDB_IDENT_FLAG_ATTRIBS 0x08000000L
+
+/*! \brief This is the default identity.
+
+ At most one identity will have this flag set at any given time.
+ To set or reset the flag, use kcdb_identity_set_default() */
+#define KCDB_IDENT_FLAG_DEFAULT 0x00000001L
+
+/*! \brief This identity can be searched.
+
+ The meaning of this flag is left to be interpreted by individual
+ plugins. */
+#define KCDB_IDENT_FLAG_SEARCHABLE 0x00000002L
+
+/*! \brief Hidden identity.
+
+ The identity will not show up in the identity list window. Once
+ the hidden is switched off, the identity (and all associated
+ credentials) will re-appear in the window */
+#define KCDB_IDENT_FLAG_HIDDEN 0x00000004L
+
+/*! \brief Invalid identity
+
+ For one reason or another, this identity is invalid. This flag
+ can be set by an identity provider to indicate that this identity
+ does not correspond to an actual identity because an external
+ entity (such as a KDC) has denied it's existence.
+
+ The absence of this flag does not imply that the identity is
+ valid. The ::KCDB_IDENT_FLAG_VALID bit must be set for that to be
+ the case. If neither flag is set, then the status of the identity
+ is not known.
+*/
+#define KCDB_IDENT_FLAG_INVALID 0x00000008L
+
+/*! \brief Valid identity
+
+ The identity has been validated through an external entity, or
+ it's validity implied through the existence of credentials for the
+ identity.
+
+ The absence of this flag does not imply that the identity is
+ invalid. The ::KCDB_IDENT_FLAG_INVALID bit must be set for that
+ to be the case. If neither flag is set, then the status of the
+ identity is not known.
+ */
+#define KCDB_IDENT_FLAG_VALID 0x00000010L
+
+/*! \brief Expired identity
+
+ This identity has expired and can not be actively used to obtain
+ credentials. This determination is made based on the input of
+ some external entity. This flag may only be set by an identity
+ provider.
+*/
+#define KCDB_IDENT_FLAG_EXPIRED 0x00000020L
+
+/*! \brief Empty identity
+
+ The identity does not have actual credentials associated with it.
+ */
+#define KCDB_IDENT_FLAG_EMPTY 0x00000040L
+
+/*! \brief Renewable identity
+
+ The initial credentials associated with this identity are
+ renewable. Thus making the whole identity renewable.
+ */
+#define KCDB_IDENT_FLAG_RENEWABLE 0x00000080L
+
+/*! \brief Required user interaction
+
+ The identity is in a state which requires user interaction to
+ activate. Currently, the identity may not be in a state where it
+ can be used to obtain credentials.
+
+ A typical example of this is when the primary password for an
+ identity has expired.
+ */
+#define KCDB_IDENT_FLAG_INTERACT 0x00000100L
+
+/*! \brief Has expired credentials
+
+ The identity has expired credentials associated with it.
+ */
+#define KCDB_IDENT_FLAG_CRED_EXP 0x00000200L
+
+/*! \brief Has renewable credentials
+
+ The identity has renewable credentials associated with it. If the
+ initial credentials of the identity are renewable, then identity
+ is renewable. Hence the ::KCDB_IDENT_FLAG_RENEWABLE should also
+ be set.
+ */
+#define KCDB_IDENT_FLAG_CRED_RENEW 0x00000400L
+
+/*! \brief Sticky identity
+
+ Sticky identities are identities that are always visible in the
+ credentials display even if no credentials are associated with it.
+ */
+#define KCDB_IDENT_FLAG_STICKY 0x00000800L
+
+/*! \brief Unknown state
+
+ The validity of the identity cannot be determined. This usually
+ means that an authority could not be contacted. This flag is to
+ be treated as transient. If ::KCDB_IDENT_FLAG_INVALID or
+ ::KCDB_IDENT_FLAG_VALID is set for the identity, this flag is to
+ be ignored.
+ */
+#define KCDB_IDENT_FLAG_UNKNOWN 0x00001000L
+
+/*! \brief Read/write flags mask.
+
+ A bitmask that correspond to all the read/write flags in the mask.
+*/
+#define KCDB_IDENT_FLAGMASK_RDWR 0x00001fffL
+
+/*@}*/
+
+/*! \name Identity Provider Data Structures
+@{*/
+
+/*! \brief Name transfer structure
+
+ Used when the KCDB is communicating with the identity provider to
+ exchange string names of identities. See individual ::KMSG_IDENT
+ message subtypes for the usage of this structure.
+ */
+typedef struct tag_kcdb_ident_name_xfer {
+ const wchar_t * name_src; /*!< An identity name. Does not
+ exceed KCDB_IDENT_MAXCCH_NAME
+ characters including terminating
+ NULL. */
+ const wchar_t * name_alt; /*!< An identity name. Does not
+ exceed KCDB_IDENT_MAXCCH_NAME
+ characters including terminating
+ NULL. */
+ wchar_t * name_dest; /*!< Pointer to a buffer that is to
+ receive a response string. The
+ size of the buffer in bytes is
+ specified in \a cb_name_dest. */
+ khm_size cb_name_dest; /*!< Size of buffer pointed to by \a
+ name_dest in bytes. */
+ khm_int32 result; /*!< Receives a result value, which is
+ usually an error code defined in
+ kherror.h, though it is not
+ always. */
+} kcdb_ident_name_xfer;
+
+typedef struct tag_kcdb_ident_info {
+ khm_handle identity;
+ khm_int32 fields;
+
+ FILETIME expiration;
+} kcdb_ident_info;
+
+/*@}*/
+
+/*! \name Identity provider interface functions
+
+ These functions encapsulate safe calls to the current identity
+ provider. While these functions are exported, applications should
+ not call these functions directly. They are provided for use by
+ the NetIDMgr core application.
+@{*/
+
+/*! \brief Validate an identity name
+
+ The name that is provided will be passed through sets of
+ validations. One set, which doesn't depend on the identity
+ provider checks whether the length of the identity name and
+ whether there are any invalid characters in the identity name. If
+ the name passes those tests, then the name is passed down to the
+ identity provider's name validation handler.
+
+ \retval KHM_ERROR_SUCCESS The name is valid
+ \retval KHM_ERROR_TOO_LONG Too many characters in name
+ \retval KHM_ERROR_INVALID_NAME There were invalid characters in the name.
+ \retval KHM_ERROR_NO_PROVIDER There is no identity provider;
+ however the name passed the length and character tests.
+ \retval KHM_ERROR_NOT_IMPLEMENTED The identity provider doesn't
+ implement a name validation handler; however the name passed
+ the length and character tests.
+
+ \see ::KMSG_IDENT_VALIDATE_NAME
+ */
+KHMEXP khm_int32 KHMAPI
+kcdb_identpro_validate_name(const wchar_t * name);
+
+/*! \brief Validate an identity
+
+ The identity itself needs to be validated. This may involve
+ communicating with an external entity.
+
+ \see ::KMSG_IDENT_VALIDATE_IDENTITY
+ */
+KHMEXP khm_int32 KHMAPI
+kcdb_identpro_validate_identity(khm_handle identity);
+
+/*! \brief Canonicalize the name
+
+
+ \see ::KMSG_IDENT_CANON_NAME
+*/
+KHMEXP khm_int32 KHMAPI
+kcdb_identpro_canon_name(const wchar_t * name_in,
+ wchar_t * name_out,
+ khm_size * cb_name_out);
+
+/*! \brief Compare two identity names
+
+ \see ::KMSG_IDENT_COMPARE_NAME
+*/
+KHMEXP khm_int32 KHMAPI
+kcdb_identpro_compare_name(const wchar_t * name1,
+ const wchar_t * name2);
+
+/*! \brief Set the specified identity as the default
+
+ \see ::KMSG_IDENT_SET_DEFAULT
+*/
+KHMEXP khm_int32 KHMAPI
+kcdb_identpro_set_default(khm_handle identity);
+
+/*! \brief Set the specified identity as searchable
+
+ \see ::KMSG_IDENT_SET_SEARCHABLE
+*/
+KHMEXP khm_int32 KHMAPI
+kcdb_identpro_set_searchable(khm_handle identity,
+ khm_boolean searchable);
+
+/*! \brief Update the specified identity
+
+ \see ::KMSG_IDENT_UPDATE
+*/
+KHMEXP khm_int32 KHMAPI
+kcdb_identpro_update(khm_handle identity);
+
+/*! \brief Obtain the UI callback
+
+ \a rock is actually a pointer to a ::khui_ident_new_creds_cb which
+ is to receive the callback.
+
+ \see ::KMSG_IDENT_GET_UI_CALLBACK
+ */
+KHMEXP khm_int32 KHMAPI
+kcdb_identpro_get_ui_cb(void * rock);
+
+/*! \brief Notify an identity provider of the creation of a new identity
+
+ \see ::KMSG_IDENT_NOTIFY_CREATE
+*/
+KHMEXP khm_int32 KHMAPI
+kcdb_identpro_notify_create(khm_handle identity);
+
+/*@}*/
+
+/*! \brief Check if the given name is a valid identity name
+
+ \return TRUE or FALSE to the question, is this valid?
+*/
+KHMEXP khm_boolean KHMAPI
+kcdb_identity_is_valid_name(const wchar_t * name);
+
+/*! \brief Create or open an identity.
+
+ If the KCDB_IDENT_FLAG_CREATE flag is specified in the flags
+ parameter a new identity will be created if one does not already
+ exist with the given name. If an identity by that name already
+ exists, then the existing identity will be opened. The result
+ parameter will receive a held reference to the opened identity.
+ Use kcdb_identity_release() to release the handle.
+
+ \param[in] name Name of identity to create
+ \param[in] flags If KCDB_IDENT_FLAG_CREATE is specified, then the
+ identity will be created if it doesn't already exist.
+ Additional flags can be set here which will be assigned to the
+ identity if it is created. Additional flags have no effect if
+ an existing identity is opened.
+ \param[out] result If the call is successful, this receives a held
+ reference to the identity. The caller should call
+ kcdb_identity_release() to release the identity once it is no
+ longer needed.
+ */
+KHMEXP khm_int32 KHMAPI
+kcdb_identity_create(const wchar_t *name,
+ khm_int32 flags,
+ khm_handle * result);
+
+/*! \brief Mark an identity for deletion.
+
+ The identity will be marked for deletion. The
+ KCDB_IDENT_FLAG_ACTIVE will no longer be present for this
+ identity. Once all references to the identity are released, it
+ will be removed from memory. All associated credentials will also
+ be removed. */
+KHMEXP khm_int32 KHMAPI
+kcdb_identity_delete(khm_handle id);
+
+/*! \brief Set or unset the specified flags in the specified identity.
+
+ Only flags that are in KCDB_IDENT_FLAGMASK_RDWR can be specifed in
+ the \a flags parameter or the \a mask parameter. The flags set in
+ the \a mask parameter of the identity will be set to the
+ corresponding values in the \a flags parameter.
+
+ If ::KCDB_IDENT_FLAG_INVALID is set using this function, then the
+ ::KCDB_IDENT_FLAG_VALID will be automatically reset, and vice
+ versa. Resetting either bit does not undo this change, and will
+ leave the identity's validity unspecified. Setting either of
+ ::KCDB_IDENT_FLAG_INVALID or ::KCDB_IDENT_FLAG_VALID will
+ automatically reset ::KCDB_IDENT_FLAG_UNKNOWN.
+
+ Note that setting or resetting certain flags have other semantic
+ side-effects:
+
+ - ::KCDB_IDENT_FLAG_DEFAULT : Setting this is equivalent to
+ calling kcdb_identity_set_default() with \a id. Resetting this
+ is equivalent to calling kcdb_identity_set_default() with NULL.
+
+ - ::KCDB_IDENT_FLAG_SEARCHABLE : Setting this will result in the
+ identity provider getting notified of the change. If the
+ identity provider indicates that searchable flag should not be
+ set or reset on the identity, then kcdb_identity_set_flags()
+ will return an error.
+
+ \note kcdb_identity_set_flags() is not atomic. Even if the
+ function returns a failure code, some flags in the identity may
+ have been set. When calling kcdb_identity_set_flags() always
+ check the flags in the identity using kcdb_identity_get_flags() to
+ check which flags have been set and which have failed.
+*/
+KHMEXP khm_int32 KHMAPI
+kcdb_identity_set_flags(khm_handle id,
+ khm_int32 flags,
+ khm_int32 mask);
+
+/*! \brief Return all the flags for the identity
+
+ The returned flags may include internal flags.
+*/
+KHMEXP khm_int32 KHMAPI
+kcdb_identity_get_flags(khm_handle id,
+ khm_int32 * flags);
+
+/*! \brief Return the name of the identity
+
+ \param[out] buffer Buffer to copy the identity name into. The
+ maximum size of an identity name is \a KCDB_IDENT_MAXCB_NAME.
+ If \a buffer is \a NULL, then the required size of the buffer
+ is returned in \a pcbsize.
+
+ \param[in,out] pcbsize Size of buffer in bytes. */
+KHMEXP khm_int32 KHMAPI
+kcdb_identity_get_name(khm_handle id,
+ wchar_t * buffer,
+ khm_size * pcbsize);
+
+/*! \brief Set the specified identity as the default.
+
+ Specifying NULL effectively makes none of the identities the
+ default.
+
+ \see kcdb_identity_set_flags()
+*/
+KHMEXP khm_int32 KHMAPI
+kcdb_identity_set_default(khm_handle id);
+
+/*! \brief Mark the specified identity as the default.
+
+ This API is reserved for use by identity providers as a means of
+ specifying which identity is default. The difference between
+ kcdb_identity_set_default() and kcdb_identity_set_default_int() is
+ in semantics.
+
+ - kcdb_identity_set_default() is used to request the KCDB to
+ designate the specified identity as the default. When
+ processing the request, the KCDB invokes the identity provider
+ to do the necessary work to make the identity the default.
+
+ - kcdb_identity_set_default_int() is used by the identity provider
+ to notify the KCDB that the specified identity is the default.
+ This does not result in the invocation of any other semantics to
+ make the identity the default other than releasing the previous
+ defualt identity and making the specified one the default.
+ */
+KHMEXP khm_int32 KHMAPI
+kcdb_identity_set_default_int(khm_handle id);
+
+/*! \brief Get the default identity
+
+ Obtain a held handle to the default identity if there is one. The
+ handle must be freed using kcdb_identity_release().
+
+ If there is no default identity, then the handle pointed to by \a
+ pvid is set to \a NULL and the function returns
+ KHM_ERROR_NOT_FOUND. */
+KHMEXP khm_int32 KHMAPI
+kcdb_identity_get_default(khm_handle * pvid);
+
+/*! \brief Get the configuration space for the identity.
+
+ If the configuration space for the identity does not exist and the
+ flags parameter does not specify ::KHM_FLAG_CREATE, then the
+ function will return a failure code as specified in
+ ::khc_open_space(). Depending on whether or not a configuration
+ space was found, the ::KCDB_IDENT_FLAG_CONFIG flag will be set or
+ reset for the identity.
+
+ \param[in] id Identity for which the configuraiton space is requested
+
+ \param[in] flags Flags used when calling khc_open_space(). If \a
+ flags specifies KHM_FLAG_CREATE, then the configuration space
+ is created.
+
+ \param[out] result The resulting handle. If the call is
+ successful, this receives a handle to the configuration space.
+ Use khc_close_space() to close the handle.
+*/
+KHMEXP khm_int32 KHMAPI
+kcdb_identity_get_config(khm_handle id,
+ khm_int32 flags,
+ khm_handle * result);
+
+/*! \brief Hold a reference to an identity.
+
+ A reference to an identity (a handle) is only valid while it is
+ held. \note Once the handle is released, it can not be
+ revalidated by calling kcdb_identity_hold(). Doing so would lead
+ to unpredictable consequences. */
+KHMEXP khm_int32 KHMAPI
+kcdb_identity_hold(khm_handle id);
+
+/*! \brief Release a reference to an identity.
+ \see kcdb_identity_hold() */
+KHMEXP khm_int32 KHMAPI
+kcdb_identity_release(khm_handle id);
+
+/*! \brief Set the identity provider subscription
+
+ If there was a previous subscription, that subscription will be
+ automatically deleted.
+
+ \param[in] sub New identity provider subscription
+*/
+KHMEXP khm_int32 KHMAPI
+kcdb_identity_set_provider(khm_handle sub);
+
+/*! \brief Set the primary credentials type
+
+ The primary credentials type is designated by the identity
+ provider. As such, this function should only be called by an
+ identity provider.
+ */
+KHMEXP khm_int32 KHMAPI
+kcdb_identity_set_type(khm_int32 cred_type);
+
+/*! \brief Retrieve the identity provider subscription
+
+ \param[out] sub Receives the current identity provider
+ subscription. Set to NULL if only the existence of an
+ identity provider needs to be checked.
+
+ \retval KHM_ERROR_SUCCESS An identity provider exists. If \a sub
+ was not NULL, the subscription has been copied there.
+
+ \retval KHM_ERROR_NOT_FOUND There is currently no registered
+ identity provider. If \a sub was not NULL, the handle it
+ points to has been set to NULL.
+*/
+KHMEXP khm_int32 KHMAPI
+kcdb_identity_get_provider(khm_handle * sub);
+
+/*! \brief Retrieve the identity provider credentials type
+
+ This is the credentials type that the identity provider has
+ designated as the primary credentials type.
+ */
+KHMEXP khm_int32 KHMAPI
+kcdb_identity_get_type(khm_int32 * ptype);
+
+/*! \brief Returns TRUE if the two identities are equal
+
+ Also returns TRUE if both identities are NULL.
+ */
+KHMEXP khm_boolean KHMAPI
+kcdb_identity_is_equal(khm_handle identity1,
+ khm_handle identity2);
+
+/*! \brief Set an attribute in an identity by attribute id
+
+ \param[in] buffer A pointer to a buffer containing the data to
+ assign to the attribute. Setting \a buffer to NULL has the
+ effect of removing any data that is already assigned to the
+ attribute. If \a buffer is non-NULL, then \a cbbuf should
+ specify the number of bytes in \a buffer.
+
+ \param[in] cbbuf Number of bytes of data in \a buffer. The
+ individual data type handlers may copy in less than this many
+ bytes in to the credential.
+*/
+KHMEXP khm_int32 KHMAPI
+kcdb_identity_set_attr(khm_handle identity,
+ khm_int32 attr_id,
+ void * buffer,
+ khm_size cbbuf);
+
+/*! \brief Set an attribute in an identity by name
+
+ The attribute name has to be a KCDB registered attribute or
+ property.
+
+ \param[in] cbbuf Number of bytes of data in \a buffer. The
+ individual data type handlers may copy in less than this many
+ bytes in to the credential.
+*/
+KHMEXP khm_int32 KHMAPI
+kcdb_identity_set_attrib(khm_handle identity,
+ const wchar_t * attr_name,
+ void * buffer,
+ khm_size cbbuf);
+
+/*! \brief Get an attribute from an identity by attribute id.
+
+ \param[in] buffer The buffer that is to receive the attribute
+ value. Set this to NULL if only the required buffer size is
+ to be returned.
+
+ \param[in,out] cbbuf The number of bytes available in \a buffer.
+ If \a buffer is not sufficient, returns KHM_ERROR_TOO_LONG and
+ sets this to the required buffer size.
+
+ \param[out] attr_type Receives the data type of the attribute.
+ Set this to NULL if the type is not required.
+
+ \note Set both \a buffer and \a cbbuf to NULL if only the
+ existence of the attribute is to be checked. If the attribute
+ exists in this identity then the function will return
+ KHM_ERROR_SUCCESS, otherwise it returns KHM_ERROR_NOT_FOUND.
+*/
+KHMEXP khm_int32 KHMAPI
+kcdb_identity_get_attr(khm_handle identity,
+ khm_int32 attr_id,
+ khm_int32 * attr_type,
+ void * buffer,
+ khm_size * pcbbuf);
+
+/*! \brief Get an attribute from an identity by name.
+
+ \param[in] buffer The buffer that is to receive the attribute
+ value. Set this to NULL if only the required buffer size is
+ to be returned.
+
+ \param[in,out] cbbuf The number of bytes available in \a buffer.
+ If \a buffer is not sufficient, returns KHM_ERROR_TOO_LONG and
+ sets this to the required buffer size.
+
+ \note Set both \a buffer and \a cbbuf to NULL if only the
+ existence of the attribute is to be checked. If the attribute
+ exists in this identity then the function will return
+ KHM_ERROR_SUCCESS, otherwise it returns KHM_ERROR_NOT_FOUND.
+*/
+KHMEXP khm_int32 KHMAPI
+kcdb_identity_get_attrib(khm_handle identity,
+ const wchar_t * attr_name,
+ khm_int32 * attr_type,
+ void * buffer,
+ khm_size * pcbbuf);
+
+/*! \brief Get the string representation of an identity attribute.
+
+ A shortcut function which generates the string representation of
+ an identity attribute directly.
+
+ \param[in] identity A handle to an identity
+
+ \param[in] attr_id The attribute to retrieve
+
+ \param[out] buffer A pointer to a string buffer which receives the
+ string form of the attribute. Set this to NULL if you only
+ want to determine the size of the required buffer.
+
+ \param[in,out] pcbbuf A pointer to a #khm_int32 that, on entry,
+ holds the size of the buffer pointed to by \a buffer, and on
+ exit, receives the actual number of bytes that were copied.
+
+ \param[in] flags Flags for the string conversion. Can be set to
+ one of KCDB_TS_LONG or KCDB_TS_SHORT. The default is
+ KCDB_TS_LONG.
+
+ \retval KHM_ERROR_SUCCESS Success
+ \retval KHM_ERROR_NOT_FOUND The given attribute was either invalid
+ or was not defined for this identity
+ \retval KHM_ERROR_INVALID_PARAM One or more parameters were invalid
+ \retval KHM_ERROR_TOO_LONG Either \a buffer was NULL or the
+ supplied buffer was insufficient
+*/
+KHMEXP khm_int32 KHMAPI
+kcdb_identity_get_attr_string(khm_handle identity,
+ khm_int32 attr_id,
+ wchar_t * buffer,
+ khm_size * pcbbuf,
+ khm_int32 flags);
+
+/*! \brief Get the string representation of an identity attribute by name.
+
+ A shortcut function which generates the string representation of
+ an identity attribute directly.
+
+ \param[in] identity A handle to an identity
+
+ \param[in] attrib The name of the attribute to retrieve
+
+ \param[out] buffer A pointer to a string buffer which receives the
+ string form of the attribute. Set this to NULL if you only
+ want to determine the size of the required buffer.
+
+ \param[in,out] pcbbuf A pointer to a #khm_int32 that, on entry,
+ holds the size of the buffer pointed to by \a buffer, and on
+ exit, receives the actual number of bytes that were copied.
+
+ \param[in] flags Flags for the string conversion. Can be set to
+ one of KCDB_TS_LONG or KCDB_TS_SHORT. The default is
+ KCDB_TS_LONG.
+
+ \see kcdb_identity_get_attr_string()
+*/
+KHMEXP khm_int32 KHMAPI
+kcdb_identity_get_attrib_string(khm_handle identity,
+ const wchar_t * attr_name,
+ wchar_t * buffer,
+ khm_size * pcbbuf,
+ khm_int32 flags);
+
+/*! \brief Enumerate identities
+
+ Enumerates all the active identities that match the criteria
+ specified using \a and_flags and \a eq_flags. The condition is
+ applied to all active identities as follows:
+
+ \code
+ (identity->flags & and_flags) == (eq_flags & and_flags)
+ \endcode
+
+ Essentially, if a flag is set in \a and_flags, then that flag in
+ the identity should equal the setting in \a eq_flags.
+
+ \param[in] and_flags See above
+
+ \param[in] eq_flags See above
+
+ \param[out] name_buf Buffer to receive the list of identity names.
+ Can be NULL if only the required size of the buffer or the
+ number of matching identities is required. The list is
+ returned as a multi string.
+
+ \param[in,out] pcb_buf Number of bytes in buffer pointed to by \a
+ name_buf on entry. On exit, will receive the number of bytes
+ copied. Can be NULL only if \a name_buf is also NULL. If \a
+ name_buf is NULL or if \a pcb_buf indicates that the buffer is
+ insufficient, this will receive the number of bytes required
+ and the return value of the function will be
+ KHM_ERROR_TOO_LONG
+
+ \param[out] pn_idents Receives the number of identities that match
+ the given criteria.
+
+ \retval KHM_ERROR_SUCCESS If \a name_buf was valid, the buffer now
+ contains a multi string of identities that matched. If \a
+ pn_idents was valid, it contains the number of identities
+ matched.
+
+ \retval KHM_ERROR_TOO_LONG No buffer was supplied or the supplied
+ buffer was insufficient. If \a pn_idents was valid, it
+ contains the number of identities.
+
+ \retval KHM_ERROR_INVALID_PARAM None of the parameters \a name_buf,
+ \a pcb_buf and \a pn_idents were supplied, or \a pcb_buf was
+ NULL when \a name_buf was not.
+
+ \note Calling this function to obtain the required size of the
+ buffer and then calling it with a that sized buffer is not
+ guaranteed to work since the list of identities may change
+ between the two calls.
+ */
+KHMEXP khm_int32 KHMAPI
+kcdb_identity_enum(khm_int32 and_flags,
+ khm_int32 eq_flags,
+ wchar_t * name_buf,
+ khm_size * pcb_buf,
+ khm_size * pn_idents);
+
+/*! \brief Refresh identity attributes based on root credential set
+
+ Several flags in an identity are dependent on the credentials that
+ are associated with it in the root credential set. In addition,
+ other flags in an identity depend on external factors that need to
+ be verfied once in a while. This API goes through the root
+ credential set as well as consulting the identity provider to
+ update an identity.
+
+ \see kcdb_identity_refresh()
+ */
+KHMEXP khm_int32 KHMAPI
+kcdb_identity_refresh(khm_handle vid);
+
+/*! \brief Refresh all identities
+
+ Equivalent to calling kcdb_identity_refresh() for all active
+ identities.
+
+ \see kcdb_identityt_refresh()
+ */
+KHMEXP khm_int32 KHMAPI
+kcdb_identity_refresh_all(void);
+
+/* KSMG_KCDB_IDENT notifications are structured as follows:
+ type=KMSG_KCDB
+ subtype=KMSG_KCDB_IDENT
+ uparam=one of KCDB_OP_*
+ blob=handle to identity in question */
+
+/*@}*/
+
+
+/*********************************************************************/
+
+
+/*!
+\defgroup kcdb_creds Credential sets and individual credentials
+
+@{
+*/
+
+
+/*! \brief Credentials process function
+
+ This function is called for each credential in a credential set
+ when supplied to kcdb_credset_apply(). It should return
+ KHM_ERROR_SUCCESS to continue the operation, or any other value to
+ terminate the processing.
+
+ \see kcdb_credset_apply()
+*/
+typedef khm_int32
+(KHMAPI *kcdb_cred_apply_func)(khm_handle cred,
+ void * rock);
+
+/*! \brief Credentials filter function.
+
+ Should return non-zero if the credential passed as \a cred is to
+ be "accepted". The precise consequence of a non-zero return value
+ is determined by the individual function that this call back is
+ passed into.
+
+ This function should not call any other function which may modify
+ \a cred.
+
+ \see kcdb_credset_collect_filtered()
+ \see kcdb_credset_extract_filtered()
+*/
+typedef khm_int32
+(KHMAPI *kcdb_cred_filter_func)(khm_handle cred,
+ khm_int32 flags,
+ void * rock);
+
+/*! \brief Credentials compare function.
+
+ Asserts a weak ordering on the credentials that are passed in as
+ \a cred1 and \a cred2. It should return:
+
+ - a negative value if \a cred1 < \a cred2
+ - zero if \a cred1 == \a cred2
+ - a postive value if \a cred1 > \a cred2
+ \see kcdb_credset_sort()
+ \see ::kcdb_credtype
+*/
+typedef khm_int32
+(KHMAPI *kcdb_cred_comp_func)(khm_handle cred1,
+ khm_handle cred2,
+ void * rock);
+
+/*! \defgroup kcdb_credset Credential sets */
+/*@{*/
+
+/*! \brief Create a credential set.
+
+ Credential sets are temporary containers for credentials. These
+ can be used by plug-ins to store credentials while they are being
+ enumerated from an external source. Once all the credentials have
+ been collected into the credential set, the plug-in may call
+ kcdb_credset_collect() to collect the credentials into the root
+ credential store.
+
+ The user interface will only display credentials that are in the
+ root credential store. No notifications are generated for changes
+ to a non-root credential set.
+
+ Use kcdb_credset_delete() to delete the credential set once it is
+ created.
+
+ \see kcdb_credset_delete()
+ \see kcdb_credset_collect()
+*/
+KHMEXP khm_int32 KHMAPI
+kcdb_credset_create(khm_handle * result);
+
+/** \brief Delete a credential set
+
+ \see kcdb_credset_create()
+*/
+KHMEXP khm_int32 KHMAPI
+kcdb_credset_delete(khm_handle credset);
+
+/** \brief Collect credentials from a credential set to another credential set.
+
+ Collecting a subset of credentials from credential set \a cs_src
+ into credential set \a cs_dest involves the following steps:
+
+ - Select all credentials from \a cs_src that matches the \a
+ identity and \a type specified in the function call and add them
+ to the \a cs_dest credential set if they are not there already.
+ Note that if neither credential set is not the root credential
+ store, then the credentials will be added by reference, while if
+ it is the root credential store, the credentials will be
+ duplicated, and the copies will be added to \a cs_dest.
+
+ - If a selected credential in \a cs_src already exists in \a
+ cs_dest, then update the credential in \a cs_dest with the
+ credential fields in \a cs_src. In other words, once a
+ credential is found to exist in both \a cs_src and \a cs_dest,
+ all the non-null fields from the credential in \a cs_src will be
+ copied to the credential in \a cs_dest. Fields which are null
+ (undefined) in \a cs_src and are non-null in \a cs_dest will be
+ left unmodified in \a cs_dest.
+
+ One notable exception is the credentials' flags. All flags in
+ \a cs_src which are not included in
+ ::KCDB_CRED_FLAGMASK_ADDITIVE will be copied to the
+ corresponding bits in the flags of \a cs_dest. However, flags
+ that are included in ::KCDB_CRED_FLAGMASK_ADDITIVE will be added
+ to the corresponding bits in \a cs_dest.
+
+ (See notes below)
+
+ - Remove all credentials from \a cs_dest that match the \a
+ identity and \a type that do not appear in \a cs_src. (see notes
+ below)
+
+ For performance reasons, plugins should use kcdb_credset_collect()
+ to update the root credentials store instead of adding and
+ removing individual credentials from the root store.
+
+ Only credentials that are associated with active identities are
+ affected by kcdb_credset_collect().
+
+ \param[in] cs_dest A handle to the destination credential set. If
+ this is \a NULL, then it is assumed to refer to the root
+ credential store.
+
+ \param[in] cs_src A handle to the source credential set. If this
+ is NULL, then it is assumed to refer to the root credential
+ store.
+
+ \param[in] identity A handle to an identity. Setting this to NULL
+ collects all identities in the credential set.
+
+ \param[in] type A credentials type. Setting this to
+ KCDB_CREDTYPE_ALL collects all credential types in the set.
+
+ \param[out] delta A bit mask that indicates the modifications that
+ were made to \a cs_dest as a result of the collect operation.
+ This is a combination of KCDB_DELTA_* values. This parameter
+ can be \a NULL if the value is not required.
+
+ \warning If \a identity and \a type is set to a wildcard, all
+ credentials in the root store that are not in this credentials
+ set will be deleted.
+
+ \note Two credentials \a A and \a B are considered equal if:
+ - They refer to the same identity
+ - Both have the same credential type
+ - Both have the same name
+
+ \note This is the only supported way of modifying the root
+ credential store.
+
+ \note \a cs_src and \a cs_dest can not refer to the same
+ credentials set.
+
+ \note The destination credential set cannot be sealed.
+*/
+KHMEXP khm_int32 KHMAPI
+kcdb_credset_collect(khm_handle cs_dest,
+ khm_handle cs_src,
+ khm_handle identity,
+ khm_int32 type,
+ khm_int32 * delta);
+
+/*! \brief Credentials were added
+ \see kcdb_credset_collect() */
+#define KCDB_DELTA_ADD 1
+
+/*! \brief Credentials were deleted
+ \see kcdb_credset_collect() */
+#define KCDB_DELTA_DEL 2
+
+/*! \brief Credentials were modified
+ \see kcdb_credset_collect() */
+#define KCDB_DELTA_MODIFY 4
+
+/*! \brief Indicates that the credential to be filtered is from the root store.
+
+ \see kcdb_credset_collect_filtered()
+*/
+#define KCDB_CREDCOLL_FILTER_ROOT 1
+
+/*! \brief Indicates that the credential to be filtered is from the source
+ credential set
+
+ \see kcdb_credset_collect_filtered() */
+#define KCDB_CREDCOLL_FILTER_SRC 2
+
+/*! \brief Indicates that the credential to be filtered is from the destination
+ credential set
+
+ \see kcdb_credset_collect_filtered() */
+#define KCDB_CREDCOLL_FILTER_DEST 4
+
+/*! \brief Collect credentials from one credential set to another using a filter.
+
+ Similar to kcdb_credset_collect() except instead of selecting
+ credentials by matching against an identity and/or type, a filter
+ function is called. If the filter function returns non-zero for a
+ credential, that credential is selected.
+
+ Credentials in the source and destination credential sets are
+ passed into the filter function. Depending on whether the
+ credential is in the source credential set or destination
+ credential set, the \a flag parameter may have either \a
+ KCDB_CREDCOLL_FILTER_SRC or \a KCDB_CREDCOLL_FILTER_DEST bits set.
+ Also, if either one of the credential sets is the root credential
+ store, then additionally \a KCDB_CREDCOLL_FILTER_ROOT would also
+ be set.
+
+ See the kcdb_credset_collect() documentation for explanations of
+ the \a cs_src, \a cs_dest and \a delta parameters which perform
+ identical functions.
+
+ \param[in] filter The filter of type ::kcdb_cred_filter_func
+ \param[in] rock A custom argument to be passed to the filter function.
+
+ \see kcdb_credset_collect()
+*/
+KHMEXP khm_int32 KHMAPI
+kcdb_credset_collect_filtered(khm_handle cs_dest,
+ khm_handle cs_src,
+ kcdb_cred_filter_func filter,
+ void * rock,
+ khm_int32 * delta);
+
+/*! \brief Flush all credentials from a credential set
+
+ Deletes all the crednetials from the credential set.
+
+ \param[in] credset A handle to a credential set. Cannot be NULL.
+
+ \note The credential set cannot be sealed
+*/
+KHMEXP khm_int32 KHMAPI
+kcdb_credset_flush(khm_handle credset);
+
+/*! \brief Extract credentials from one credential set to another
+
+ Credentials from the source credential set are selected based on
+ the \a identity and \a type arguements. If a credential is
+ matched, then it is added to the \a destcredset.
+
+ If the \a sourcecredset is the root credential set, the added
+ credentials are copies of the actual credentials in the root
+ credential set. Otherwise the credentials are references to the
+ original credentials in the \a sourcecredset .
+
+ \param[in] destcredset Destination credential set. Must be valid.
+
+ \param[in] sourcecredset The source credential set. If set to
+ NULL, extracts from the root credential set.
+
+ \param[in] identity The identity to match in the source credential
+ set. If set to NULL, matches all identities.
+
+ \param[in] type The credential type to match in the source credential set.
+ If set to KCDB_CREDTYPE_INVALID, matches all types.
+
+ \note This function does not check for duplicate credentials.
+
+ \note The destination credential set cannot be sealed.
+*/
+KHMEXP khm_int32 KHMAPI
+kcdb_credset_extract(khm_handle destcredset,
+ khm_handle sourcecredset,
+ khm_handle identity,
+ khm_int32 type);
+
+/*! \brief Extract credentials from one credential set to another using a filter.
+
+ Similar to kcdb_credset_extract() except a filter function is used
+ to determine which credentials should be selected.
+
+ \param[in] rock A custom argument to be passed in to the filter function.
+
+ \note The destination credential set cannot be sealed.
+*/
+KHMEXP khm_int32 KHMAPI
+kcdb_credset_extract_filtered(khm_handle destcredset,
+ khm_handle sourcecredset,
+ kcdb_cred_filter_func filter,
+ void * rock);
+
+/*! \brief Retrieve a held reference to a credential in a credential set based on index.
+
+ \param[in] idx The index of the credential to retrieve. This is a
+ zero based index which goes from 0 ... (size of credset - 1).
+
+ \param[out] cred The held reference to a credential. Call
+ kcdb_cred_release() to release the credential.
+
+ \retval KHM_ERROR_SUCCESS Success. \a cred has a held reference to the credential.
+ \retval KHM_ERROR_OUT_OF_BOUNDS The index specified in \a idx is out of bounds.
+ \retval KHM_ERROR_DELETED The credential at index \a idx has been marked as deleted.
+
+ \see kcdb_cred_release()
+*/
+KHMEXP khm_int32 KHMAPI
+kcdb_credset_get_cred(khm_handle credset,
+ khm_int32 idx,
+ khm_handle * cred);
+
+/*! \brief Search a credential set for a specific credential
+
+ The credential set indicated by \a credset is searched for a
+ credential that satisfies the predicate function \a f. Each
+ credential starting at \a idx_start is passed into the predicate
+ function until it returns a non-zero value. At this point, that
+ credential is passed in to the \a cred parameter, and the index of
+ the credential is passed into the \a idx parameter.
+
+ \param[in] credset The credential set to search on. Specify NULL
+ if you want to search teh root credential set.
+
+ \param[in] idx_start The index at which to start the search after.
+ The first credential passed to the predicate function will be
+ at \a idx_start + 1. Specify -1 to start from the beginning
+ of the credential set.
+
+ \param[in] f The predicate function. The \a flags parameter of
+ the predicate function will always receive 0.
+
+ \param[in] rock An opaque parameter to be passed to the predicate
+ function \a f.
+
+ \param[out] cred A held reference to the credential that satisfied
+ the predicate function or NULL if no such credential was
+ found. Note that if a valid credential is returned, the
+ calling function must release the credential using
+ kcdb_cred_release().
+
+ \param[out] idx The index of the credential passed in \a cred.
+ Specify NULL if the index is not required.
+
+ \retval KHM_ERROR_SUCCESS A credential that satisfied the
+ predicate function was found and was assigned to \a cred.
+
+ \retval KHM_ERROR_NOT_FOUND No credential was found that matched
+ the predicate function.
+
+ \note When querying credential sets that are shared between
+ threads, it is possible that another thread modifies the
+ credential set between successive calls to
+ kcdb_credset_find_filtered(). Therefore a continued sequences of
+ searches are not guaranteed to exhastively cover the
+ credential set nor to not return duplicate matches. Duplicate
+ matches are possible if the order of the credentials in the
+ set was changed.
+*/
+KHMEXP khm_int32 KHMAPI
+kcdb_credset_find_filtered(khm_handle credset,
+ khm_int32 idx_start,
+ kcdb_cred_filter_func f,
+ void * rock,
+ khm_handle * cred,
+ khm_int32 * idx);
+
+/*! \brief Find matching credential
+
+ Searches a credential set for a credential that matches the
+ specified credential. For a credential to be a match, it must
+ have the same identity, credential type and name.
+
+ \param[in] credset Credential set to search
+
+ \param[in] cred_src Credetial to search on
+
+ \param[out] cred_dest receieves the matching credential if the
+ search is successful. If a handle is returend, the
+ kcdb_cred_release() must be used to release the handle. If
+ the matching credential is not required, you can pass in NULL.
+
+ \retval KHM_ERROR_SUCCESS The search was successful. A credential
+ was assigned to \a cred_dest
+
+ \retval KHM_ERROR_NOT_FOUND A matching credential was not found.
+ */
+KHMEXP khm_int32 KHMAPI
+kcdb_credset_find_cred(khm_handle credset,
+ khm_handle cred_src,
+ khm_handle *cred_dest);
+
+
+/*! \brief Delete a credential from a credential set.
+
+ The credential at index \a idx will be deleted. All the
+ credentials that are at indices \a idx + 1 and above will be moved
+ down to fill the gap and the size of the credential set will
+ decrease by one.
+
+ Use kcdb_credset_del_cred_ref() to delete a credential by
+ reference. Using kcdb_credset_del_cred() is faster than
+ kcdb_credset_del_cred_ref().
+
+ If you call kcdb_credset_del_cred() or kcdb_credset_del_cred_ref()
+ from within kcdb_credset_apply(), the credential will only be
+ marked as deleted. They will not be removed. This means that the
+ size of the credential set will not decrease. To purge the
+ deleted credentials from the set, call kcdb_credset_purge() after
+ kcdb_credset_apply() completes.
+
+ \note The credential set cannot be sealed.
+
+ \see kcdb_credset_del_cred_ref()
+*/
+KHMEXP khm_int32 KHMAPI
+kcdb_credset_del_cred(khm_handle credset,
+ khm_int32 idx);
+
+/*! \brief Delete a credential from a credential set by reference.
+
+ See kcdb_credset_del_cred() for description of what happens when a
+ credential is deleted from a credential set.
+
+ \note The credential set cannot be sealed.
+
+ \see kcdb_credset_del_cred()
+*/
+KHMEXP khm_int32 KHMAPI
+kcdb_credset_del_cred_ref(khm_handle credset,
+ khm_handle cred);
+
+/*! \brief Add a credential to a credential set.
+
+ The credential is added by reference. In other words, no copy of
+ the credential is made.
+
+ \param[in] idx Index of the new credential. This must be a value
+ in the range 0..(previous size of credential set) or -1. If
+ -1 is specifed, then the credential is appended at the end of
+ the set.
+
+ \note The credential set cannot be sealed.
+*/
+KHMEXP khm_int32 KHMAPI
+kcdb_credset_add_cred(khm_handle credset,
+ khm_handle cred,
+ khm_int32 idx);
+
+/*! \brief Get the number of credentials in a credential set.
+
+ Credentials in a credential set may be volatile. When
+ kcdb_credeset_get_size() is called, the credential set is
+ compacted to only include credentials that are active at the time.
+ However, when you are iterating through the credential set, it
+ might be the case that some credentials would get marked as
+ deleted. These credentials will remain in the credential set
+ until the credential set is discarded or another call to
+ kcdb_credset_get_size() or kdcb_credset_purge() is made.
+
+ If the credential set is sealed, then it will not be compacted and
+ will include deleted credentials as well.
+
+ \see kcdb_credset_purge()
+ \see kcdb_credset_get_cred()
+*/
+KHMEXP khm_int32 KHMAPI
+kcdb_credset_get_size(khm_handle credset,
+ khm_size * size);
+
+/*! \brief Removes credentials that have been marked as deleted from a credential set.
+
+ See description of \a kcdb_credset_purge() for a description of
+ what happens when credntials that are contained in a credential
+ set are deleted by an external entity.
+
+ \note The credential set cannot be sealed.
+
+ \see kcdb_credset_get_size()
+ \see kcdb_credset_get_cred()
+*/
+KHMEXP khm_int32 KHMAPI
+kcdb_credset_purge(khm_handle credset);
+
+/*! \brief Applies a function to all the credentials in a credentials set
+
+ The given function is called for each credential in a credential
+ set. With each iteration, the function is called with a handle to
+ the credential and the user defined parameter \a rock. If the
+ function returns anything other than KHM_ERROR_SUCCESS, the
+ processing stops.
+
+ \param[in] credset The credential set to apply the function to, or
+ NULL if you want to apply this to the root credential set.
+
+ \param[in] f Function to call for each credential
+
+ \param[in] rock An opaque parameter which is to be passed to 'f'
+ as the second argument.
+
+ \retval KHM_ERROR_SUCCESS All the credentials were processed.
+
+ \retval KHM_ERROR_EXIT The supplied function signalled the
+ processing to be aborted.
+
+ \retval KHM_ERROR_INVALID_PARAM One or more parameters were invalid.
+*/
+KHMEXP khm_int32 KHMAPI
+kcdb_credset_apply(khm_handle credset,
+ kcdb_cred_apply_func f,
+ void * rock);
+
+/*! \brief Sort the contents of a credential set.
+
+ \param[in] rock A custom argument to be passed in to the \a comp function.
+
+ \note The credential set cannot be sealed.
+
+ \see kcdb_cred_comp_generic()
+*/
+KHMEXP khm_int32 KHMAPI
+kcdb_credset_sort(khm_handle credset,
+ kcdb_cred_comp_func comp,
+ void * rock);
+
+/*! \brief Seal a credential set
+
+ Sealing a credential set makes it read-only. To unseal a
+ credential set, call kcdb_credset_unseal().
+
+ Sealing is an additive operation. kcdb_credset_seal() can be
+ called muliple times. However, for every call to
+ kcdb_credset_seal() a call to kcdb_credset_unseal() must be made
+ to undo the seal. The credential set will become unsealed when
+ all the seals are released.
+
+ Once sealed, the credential set will not allow any operation that
+ might change its contents. However, a selaed credential set can
+ still be delted.
+
+ \see kcdb_credset_unseal()
+ */
+KHMEXP khm_int32 KHMAPI
+kcdb_credset_seal(khm_handle credset);
+
+/*! \brief Unseal a credential set
+
+ Undoes what kcdb_credset_seal() did. This does not guarantee that
+ the credential set is unsealed since there may be other seals.
+
+ \see kcdb_credset_seal()
+ */
+KHMEXP khm_int32 KHMAPI
+kcdb_credset_unseal(khm_handle credset);
+
+/*! \brief Defines a sort criterion for kcdb_cred_comp_generic()
+
+ \see kcdb_cred_comp_generic()
+*/
+typedef struct tag_kcdb_cred_comp_field {
+ khm_int32 attrib; /*!< a valid attribute ID */
+ khm_int32 order; /*!< one of KCDB_CRED_COMP_INCREASING or
+ KCDB_CRED_COMP_DECREASING. Optionally,
+ KCDB_CRED_COMP_INITIAL_FIRST may be combined
+ with either. */
+} kcdb_cred_comp_field;
+
+/*! \brief Defines the sort order for a field in ::kcdb_cred_comp_field
+
+ Sorts lexicographically ascending by string representation of field.
+*/
+#define KCDB_CRED_COMP_INCREASING 0
+
+/*! \brief Defines the sort order for a field in ::kcdb_cred_comp_field
+
+ Sorts lexicographically descending by string representation of
+ field.
+ */
+#define KCDB_CRED_COMP_DECREASING 1
+
+/*! \brief Defines the sort order for a field in ::kcdb_cred_comp_field
+
+ Any credentials which have the ::KCDB_CRED_FLAG_INITIAL will be
+ grouped above any that don't.
+
+ If that does not apply, then credentials from the primary
+ credentials type will be sorted before others.
+*/
+#define KCDB_CRED_COMP_INITIAL_FIRST 2
+
+/*! \brief Defines the sort criteria for kcdb_cred_comp_generic()
+
+ \see kcdb_cred_comp_generic()
+*/
+typedef struct tag_kcdb_cred_comp_order {
+ khm_int32 nFields;
+ kcdb_cred_comp_field * fields;
+} kcdb_cred_comp_order;
+
+/*! \brief A generic compare function for comparing credentials.
+
+ This function can be passed as a parameter to kcdb_credset_sort().
+
+ The \a rock parameter to this function should be a pointer to a
+ ::kcdb_cred_comp_order object. The \a fields member of the
+ ::kcdb_cred_comp_order object should point to an array of
+ ::kcdb_cred_comp_field objects, each of which specifies the sort
+ order in decreasing order of priority. The number of
+ ::kcdb_cred_comp_field objects in the array should correspond to
+ the \a nFields member in the ::kcdb_cred_comp_order object.
+
+ The array of ::kcdb_cred_comp_field objects define the sort
+ criteria, in order. The \a attrib member should be a valid
+ attribute ID, while the \a order member determines whether the
+ sort order is increasing or decreasing. The exact meaning or
+ increasing or decreasing depends on the data type of the
+ attribute.
+
+ \param[in] rock a pointer to a ::kcdb_cred_comp_order object
+*/
+KHMEXP khm_int32 KHMAPI
+kcdb_cred_comp_generic(khm_handle cred1,
+ khm_handle cred2,
+ void * rock);
+
+/*@}*/
+
+/*! \defgroup kcdb_cred Credentials */
+/*@{*/
+
+/*! \brief Maximum number of characters in a credential name */
+#define KCDB_CRED_MAXCCH_NAME 256
+
+/*! \brief Maximum number of bytes in a credential name */
+#define KCDB_CRED_MAXCB_NAME (sizeof(wchar_t) * KCDB_CRED_MAXCCH_NAME)
+
+/*! \brief Marked as deleted */
+#define KCDB_CRED_FLAG_DELETED 0x00000008
+
+/*! \brief Renewable */
+#define KCDB_CRED_FLAG_RENEWABLE 0x00000010
+
+/*! \brief Initial
+
+ Initial credentials form the basis of an identity. Some
+ properties of an initial credential, such as being renewable, are
+ directly inherited by the identity. An identity is also
+ automatically considered valid if it contains a valid initial
+ credential.
+ */
+#define KCDB_CRED_FLAG_INITIAL 0x00000020
+
+/*! \brief Expired
+
+ The credential's lifetime has ended.
+ */
+#define KCDB_CRED_FLAG_EXPIRED 0x00000040
+
+/*! \brief Invalid
+
+ The credential can no longer serve its intended function. This
+ may be because it is expired and is not renewable, or its
+ renewable time period has also expired, or for some other reason.
+ */
+#define KCDB_CRED_FLAG_INVALID 0x00000080
+
+/*! \brief Credential is selected
+
+ Indicates that the credential is selected. Note that using this
+ flag may be subject to race conditions.
+ */
+#define KCDB_CRED_FLAG_SELECTED 0x00000100
+
+/*! \brief Bitmask indicating all known credential flags
+ */
+#define KCDB_CRED_FLAGMASK_ALL 0x0000ffff
+
+/*! \brief External flags
+
+ These are flags that are provided by the credentials providers.
+ The other flags are internal to KCDB and should not be modified.
+ */
+#define KCDB_CRED_FLAGMASK_EXT (KCDB_CRED_FLAG_INITIAL | KCDB_CRED_FLAG_EXPIRED | KCDB_CRED_FLAG_INVALID | KCDB_CRED_FLAG_RENEWABLE)
+
+/*! \brief Bitmask indicating dditive flags
+
+ Additive flags are special flags which are added to exiting
+ credentials based on new credentials when doing a collect
+ operation. See details on kcdb_credset_collect()
+
+ \see kcdb_credset_collect()
+*/
+#define KCDB_CRED_FLAGMASK_ADDITIVE KCDB_CRED_FLAG_SELECTED
+
+/*! \brief Generic credentials request
+
+ This data structure is used as the format for a generic
+ credentials reqeust for a ::KMSG_KCDB_REQUEST message. A plugin
+ typically publishes this message so that a credentials provider
+ may handle it and in response, obtain the specified credential.
+
+ While the \a identity, \a type and \a name members of the
+ structure are all optional, typically one would specify all three
+ or at least two for a credential provider to be able to provide
+ the credential unambigously.
+
+ Credential providers do not need to respond to ::KMSG_KCDB_REQUEST
+ messages. However, if they do, they should make sure that they
+ are the only credential provider that is responding by setting the
+ \a semaphore member to a non-zero value. The \a semaphore is set
+ to zero when a request is initially sent out. When incrementing
+ the semaphore, the plugin should use a thread safe mechanism to
+ ensure that there are no race conditions that would allow more
+ than one provider to respond to the message.
+ */
+typedef struct tag_kcdb_cred_request {
+ khm_handle identity; /*!< Identity of the credential. Set
+ to NULL if not specified. */
+ khm_int32 type; /*!< Type of the credential. Set to
+ KCDB_CREDTYPE_INVALID if not
+ specified. */
+ wchar_t * name; /*!< Name of the credential. Set to
+ NULL if not specified. */
+
+ khm_handle dest_credset; /*!< If non-NULL, instructs whoever is
+ handling the request that the
+ credential thus obtained be placed
+ in this credential set in addition
+ to whereever it may place newly
+ acquired credentials. Note that
+ while this can be NULL if the new
+ credential does not need to be
+ placed in a credential set, it can
+ not equal the root credential
+ set. */
+
+ void * vparam; /*!< An unspecified
+ parameter. Specific credential types
+ may specify how this field is to be
+ used. */
+
+ long semaphore; /*!< Incremented by one when this
+ request is answered. Only one
+ credential provider is allowed to
+ answer a ::KMSG_KCDB_REQUEST
+ message. Initially, when the
+ message is sent out, this member
+ should be set to zero. */
+} kcdb_cred_request;
+
+/*! \brief Create a new credential
+
+ \param[in] name Name of credential. \a name cannot be NULL and cannot
+ exceed \a KCDB_CRED_MAXCCH_NAME unicode characters including the
+ \a NULL terminator.
+ \param[in] identity A reference to an identity.
+ \param[in] cred_type A credentials type identifier for the credential.
+ \param[out] result Gets a held reference to the newly created credential.
+ Call kcdb_cred_release() or kcdb_cred_delete() to release the
+ reference.
+ \see kcdb_cred_release()
+*/
+KHMEXP khm_int32 KHMAPI
+kcdb_cred_create(const wchar_t * name,
+ khm_handle identity,
+ khm_int32 cred_type,
+ khm_handle * result);
+
+/*! \brief Duplicate an existing credential.
+
+ \param[out] newcred A held reference to the new credential if the call
+ succeeds.
+*/
+KHMEXP khm_int32 KHMAPI
+kcdb_cred_dup(khm_handle cred,
+ khm_handle * newcred);
+
+/*! \brief Updates one credential using field values from another
+
+ All fields that exist in \a vsrc will get copied to \a vdest and will
+ overwrite any values that are already there in \a vdest. However any
+ values that exist in \a vdest taht do not exist in \a vsrc will not be
+ modified.
+
+ \retval KHM_ERROR_SUCCESS vdest was successfully updated
+ \retval KHM_ERROR_EQUIVALENT all fields in vsrc were present and equivalent in vdest
+*/
+KHMEXP khm_int32 KHMAPI
+kcdb_cred_update(khm_handle vdest,
+ khm_handle vsrc);
+
+/*! \brief Set an attribute in a credential by name
+
+
+
+ \param[in] cbbuf Number of bytes of data in \a buffer. The
+ individual data type handlers may copy in less than this many
+ bytes in to the credential. For some data types where the
+ size of the buffer is fixed or can be determined from its
+ contents, you can specify ::KCDB_CBSIZE_AUTO for this
+ parameter.
+*/
+KHMEXP khm_int32 KHMAPI
+kcdb_cred_set_attrib(khm_handle cred,
+ const wchar_t * name,
+ void * buffer,
+ khm_size cbbuf);
+
+/*! \brief Set an attribute in a credential by attribute id
+
+ \param[in] buffer A pointer to a buffer containing the data to
+ assign to the attribute. Setting this to NULL has the effect
+ of removing any data that is already assigned to the
+ attribute. If \a buffer is non-NULL, then \a cbbuf should
+ specify the number of bytes in \a buffer.
+
+ \param[in] cbbuf Number of bytes of data in \a buffer. The
+ individual data type handlers may copy in less than this many
+ bytes in to the credential.
+*/
+KHMEXP khm_int32 KHMAPI
+kcdb_cred_set_attr(khm_handle cred,
+ khm_int32 attr_id,
+ void * buffer,
+ khm_size cbbuf);
+
+/*! \brief Get an attribute from a credential by name.
+
+ \param[in] buffer The buffer that is to receive the attribute
+ value. Set this to NULL if only the required buffer size is
+ to be returned.
+
+ \param[in,out] cbbuf The number of bytes available in \a buffer.
+ If \a buffer is not sufficient, returns KHM_ERROR_TOO_LONG and
+ sets this to the required buffer size.
+
+ \note Set both \a buffer and \a cbbuf to NULL if only the
+ existence of the attribute is to be checked. If the attribute
+ exists in this credential then the function will return
+ KHM_ERROR_SUCCESS, otherwise it returns KHM_ERROR_NOT_FOUND.
+*/
+KHMEXP khm_int32 KHMAPI
+kcdb_cred_get_attrib(khm_handle cred,
+ const wchar_t * name,
+ khm_int32 * attr_type,
+ void * buffer,
+ khm_size * cbbuf);
+
+/*! \brief Get an attribute from a credential by attribute id.
+
+ \param[in] buffer The buffer that is to receive the attribute
+ value. Set this to NULL if only the required buffer size is
+ to be returned.
+
+ \param[in,out] cbbuf The number of bytes available in \a buffer.
+ If \a buffer is not sufficient, returns KHM_ERROR_TOO_LONG and
+ sets this to the required buffer size.
+
+ \param[out] attr_type Receives the data type of the attribute.
+ Set this to NULL if the type is not required.
+
+ \note Set both \a buffer and \a cbbuf to NULL if only the
+ existence of the attribute is to be checked. If the attribute
+ exists in this credential then the function will return
+ KHM_ERROR_SUCCESS, otherwise it returns KHM_ERROR_NOT_FOUND.
+*/
+KHMEXP khm_int32 KHMAPI
+kcdb_cred_get_attr(khm_handle cred,
+ khm_int32 attr_id,
+ khm_int32 * attr_type,
+ void * buffer,
+ khm_size * cbbuf);
+
+/*! \brief Get the name of a credential.
+
+ \param[in] buffer The buffer that is to receive the credential
+ name. Set this to NULL if only the required buffer size is to
+ be returned.
+
+ \param[in,out] cbbuf The number of bytes available in \a buffer.
+ If \a buffer is not sufficient, returns KHM_ERROR_TOO_LONG and
+ sets this to the required buffer size.
+*/
+KHMEXP khm_int32 KHMAPI
+kcdb_cred_get_name(khm_handle cred,
+ wchar_t * buffer,
+ khm_size * cbbuf);
+
+/*! \brief Get the string representation of a credential attribute.
+
+ A shortcut function which generates the string representation of a
+ credential attribute directly.
+
+ \param[in] vcred A handle to a credential
+
+ \param[in] attr_id The attribute to retrieve
+
+ \param[out] buffer A pointer to a string buffer which receives the
+ string form of the attribute. Set this to NULL if you only
+ want to determine the size of the required buffer.
+
+ \param[in,out] pcbbuf A pointer to a #khm_int32 that, on entry,
+ holds the size of the buffer pointed to by \a buffer, and on
+ exit, receives the actual number of bytes that were copied.
+
+ \param[in] flags Flags for the string conversion. Can be set to
+ one of KCDB_TS_LONG or KCDB_TS_SHORT. The default is
+ KCDB_TS_LONG.
+
+ \retval KHM_ERROR_SUCCESS Success
+ \retval KHM_ERROR_NOT_FOUND The given attribute was either invalid
+ or was not defined for this credential
+ \retval KHM_ERROR_INVALID_PARAM One or more parameters were invalid
+ \retval KHM_ERROR_TOO_LONG Either \a buffer was NULL or the
+ supplied buffer was insufficient
+*/
+KHMEXP khm_int32 KHMAPI
+kcdb_cred_get_attr_string(khm_handle vcred,
+ khm_int32 attr_id,
+ wchar_t * buffer,
+ khm_size * pcbbuf,
+ khm_int32 flags);
+
+/*! \brief Get the string representation of a credential attribute by name.
+
+ A shortcut function which generates the string representation of a
+ credential attribute directly.
+
+ \param[in] vcred A handle to a credential
+
+ \param[in] attrib The name of the attribute to retrieve
+
+ \param[out] buffer A pointer to a string buffer which receives the
+ string form of the attribute. Set this to NULL if you only
+ want to determine the size of the required buffer.
+
+ \param[in,out] pcbbuf A pointer to a #khm_int32 that, on entry,
+ holds the size of the buffer pointed to by \a buffer, and on
+ exit, receives the actual number of bytes that were copied.
+
+ \param[in] flags Flags for the string conversion. Can be set to
+ one of KCDB_TS_LONG or KCDB_TS_SHORT. The default is
+ KCDB_TS_LONG.
+
+ \see kcdb_cred_get_attr_string()
+*/
+KHMEXP khm_int32 KHMAPI
+kcdb_cred_get_attrib_string(khm_handle cred,
+ const wchar_t * name,
+ wchar_t * buffer,
+ khm_size * cbbuf,
+ khm_int32 flags) ;
+
+
+/*! \brief Get a held reference to the identity associated with a credential
+
+ Use kcdb_identity_release() to release the reference that is
+ returned.
+
+ \see kcdb_identity_relase()
+*/
+KHMEXP khm_int32 KHMAPI
+kcdb_cred_get_identity(khm_handle cred,
+ khm_handle * identity);
+
+/*! \brief Set the identity of a credential
+
+ While it is ill-advised to change the identity of a credential
+ that has been placed in one or more credential sets, there can be
+ legitimate reasons for doing so. Only change the identity of a
+ credential that is not placed in a credential set or placed in a
+ credential set that is only used by a single entity.
+*/
+KHMEXP khm_int32 KHMAPI
+kcdb_cred_set_identity(khm_handle vcred,
+ khm_handle id);
+
+/*! \brief Get the serial number for the credential.
+
+ Each credential gets assigned a serial number at the time it is
+ created. This will stay with the credential for its lifetime.
+
+ \param[out] pserial Receives the serial number. Cannot be NULL.
+*/
+KHMEXP khm_int32 KHMAPI
+kcdb_cred_get_serial(khm_handle cred,
+ khm_ui_8 * pserial);
+
+/*! \brief Get the type of the credential.
+
+ The returned type is a credential type. Doh.
+
+ \param[out] type Receives the type. Cannot be NULL.
+*/
+KHMEXP khm_int32 KHMAPI
+kcdb_cred_get_type(khm_handle cred,
+ khm_int32 * type);
+
+/*! \brief Retrieve flags from a credential
+
+ The flags returned will be place in the location pointed to by \a
+ flags. Note that the specified credential must be an active
+ credential for the operation to succeed. This means the
+ ::KCDB_CRED_FLAG_DELETED will never be retured by this function.
+ */
+KHMEXP khm_int32 KHMAPI
+kcdb_cred_get_flags(khm_handle cred,
+ khm_int32 * flags);
+
+/*! \brief Set the flags of a credential
+
+ The flags specified in the \a mask parameter will be set to the
+ values specified in the \a flags parameter. The flags that are
+ not included in \a mask will not be modified.
+
+ This function can not be used to set the ::KCDB_CRED_FLAG_DELETED
+ flag. If this bit is specified in either \a flags or \a mask, it
+ will be ignored.
+
+ \see ::KCDB_CRED_FLAGMASK_ALL
+ */
+KHMEXP khm_int32 KHMAPI
+kcdb_cred_set_flags(khm_handle cred,
+ khm_int32 flags,
+ khm_int32 mask);
+
+/*! \brief Hold a reference to a credential.
+
+ Use kcdb_cred_release() to release the reference.
+
+ \see kcdb_cred_release()
+*/
+KHMEXP khm_int32 KHMAPI
+kcdb_cred_hold(khm_handle cred);
+
+/*! \brief Release a held reference to a credential.
+*/
+KHMEXP khm_int32 KHMAPI
+kcdb_cred_release(khm_handle cred);
+
+/*! \brief Delete a credential.
+
+ The credential will be marked for deletion and will continue to
+ exist until all held references are released. If the credential
+ is bound to a credential set or the root credential store, it will
+ be removed from the respective container.
+*/
+KHMEXP khm_int32 KHMAPI
+kcdb_cred_delete(khm_handle cred);
+
+/*! \brief Compare an attribute of two credentials by name.
+
+ \return The return value is dependent on the type of the attribute
+ and indicate a weak ordering of the attribute values of the two
+ credentials. If one or both credentials do not contain the
+ attribute, the return value is 0, which signifies that no ordering
+ can be determined.
+*/
+KHMEXP khm_int32 KHMAPI
+kcdb_creds_comp_attrib(khm_handle cred1,
+ khm_handle cred2,
+ const wchar_t * name);
+
+/*! \brief Compare an attribute of two credentials by attribute id.
+
+ \return The return value is dependent on the type of the attribute
+ and indicate a weak ordering of the attribute values of the two
+ credentials. If one or both credentials do not contain the
+ attribute, the return value is 0, which signifies that no ordering
+ can be determined.
+*/
+KHMEXP khm_int32 KHMAPI
+kcdb_creds_comp_attr(khm_handle cred1,
+ khm_handle cred2,
+ khm_int32 attr_id);
+
+/*! \brief Compare two credentials for equivalence
+
+ \return Non-zero if the two credentials are equal. Zero otherwise.
+ \note Two credentials are considered equal if all the following hold:
+ - Both refer to the same identity.
+ - Both have the same name.
+ - Both have the same type.
+*/
+KHMEXP khm_int32 KHMAPI
+kcdb_creds_is_equal(khm_handle cred1,
+ khm_handle cred2);
+
+/*@}*/
+/*@}*/
+
+/********************************************************************/
+
+/*! \defgroup kcdb_type Credential attribute types
+
+@{*/
+
+/*! \brief Convert a field to a string
+
+ Provides a string representation of a field in a credential. The
+ data buffer can be assumed to be valid.
+
+ On entry, \a s_buf can be NULL if only the required size of the
+ buffer is to be returned. \a pcb_s_buf should be non-NULL and
+ should point to a valid variable of type ::khm_size that will, on
+ entry, contain the size of the buffer pointed to by \a s_buf if \a
+ s_buf is not \a NULL, and on exit will contain the number of bytes
+ consumed in \a s_buf, or the required size of the buffer if \a
+ s_buf was NULL or the size of the buffer was insufficient.
+
+ The implementation should verify the parameters that are passed in
+ to the function.
+
+ The data pointed to by \a data should not be modified in any way.
+
+ \param[in] data Valid pointer to a block of data
+
+ \param[in] cb_data Number of bytes in data block pointed to by \a
+ data
+
+ \param[out] s_buf Buffer to receive the string representation of
+ data. If the data type flags has KCDB_TYPE_FLAG_CB_AUTO, then
+ this parameter could be set to KCDB_CBSIZE_AUTO. In this
+ case, the function should compute the size of the input buffer
+ assuming that the input buffer is valid.
+
+ \param[in,out] pcb_s_buf On entry, contains the size of the buffer
+ pointed to by \a s_buf, and on exit, contains the number of
+ bytes used by the string representation of the data including
+ the NULL terminator
+
+ \param[in] flags Flags for formatting the string
+
+ \retval KHM_ERROR_SUCCESS The string representation of the data
+ field was successfully copied to \a s_buf and the size of the
+ buffer used was copied to \a pcb_s_buf.
+
+ \retval KHM_ERROR_INVALID_PARAM One or more parameters were invalid
+
+ \retval KHM_ERROR_TOO_LONG Either \a s_buf was \a NULL or the size
+ indicated by \a pcb_s_buf was too small to contain the string
+ representation of the value. The required size of the buffer
+ is in \a pcb_s_buf.
+
+ \note This documents the expected behavior of this prototype function
+
+ \see ::kcdb_type
+ */
+typedef khm_int32
+(KHMAPI *kcdb_dtf_toString)(const void * data,
+ khm_size cb_data,
+ wchar_t * s_buf,
+ khm_size * pcb_s_buf,
+ khm_int32 flags);
+
+/*! \brief Verifies whetehr the given buffer contains valid data
+
+ The function should examine the buffer and the size of the buffer
+ and determine whether or not the buffer contains valid data for
+ this data type.
+
+ The data field pointed to by \a data should not be modified in any
+ way.
+
+ \param[in] data A pointer to a data buffer
+
+ \param[in] cb_data The number of bytes in the data buffer. If the
+ data type flags has KCDB_TYPE_FLAG_CB_AUTO, then this
+ parameter could be set to KCDB_CBSIZE_AUTO. In this case, the
+ function should compute the size of the input buffer assuming
+ that the input buffer is valid.
+
+ \return TRUE if the data is valid, FALSE otherwise.
+
+ \note This documents the expected behavior of this prototype function
+
+ \see ::kcdb_type
+*/
+typedef khm_boolean
+(KHMAPI *kcdb_dtf_isValid)(const void * data,
+ khm_size cb_data);
+
+/*! \brief Compare two fields
+
+ Compare the two data fields and return a value indicating their
+ relative ordering. The return value follows the same
+ specification as strcmp().
+
+ Both data buffers that are passed in can be assumed to be valid.
+
+ None of the data buffers should be modified in any way.
+
+ \param[in] data_l Valid pointer to first data buffer
+
+ \param[in] cb_data_l Number of bytes in \a data_l. If the data
+ type flags has KCDB_TYPE_FLAG_CB_AUTO, then this parameter
+ could be set to KCDB_CBSIZE_AUTO. In this case, the function
+ should compute the size of the input buffer assuming that the
+ input buffer is valid.
+
+ \param[in] data_r Valid pointer to second data buffer
+
+ \param[in] cb_data_r Number of bytes in \a data_r. If the data
+ type flags has KCDB_TYPE_FLAG_CB_AUTO, then this parameter
+ could be set to KCDB_CBSIZE_AUTO. In this case, the function
+ should compute the size of the input buffer assuming that the
+ input buffer is valid.
+
+ \return The return value should be
+ - Less than zero if \a data_l &lt; \a data_r
+ - Equal to zero if \a data_l == \a data_r or if this data type can not be compared
+ - Greater than zero if \a data_l &gt; \a data_r
+
+ \note This documents the expected behavior of this prototype function
+
+ \see ::kcdb_type
+*/
+typedef khm_int32
+(KHMAPI *kcdb_dtf_comp)(const void * data_l,
+ khm_size cb_data_l,
+ const void * data_r,
+ khm_size cb_data_r);
+
+/*! \brief Duplicate a data field
+
+ Duplicates a data field. The buffer pointed to by \a data_src
+ contains a valid field. The function should copy the field with
+ appropriate adjustments to \a data_dst.
+
+ The \a data_dst parameter can be NULL if only the required size of
+ the buffer is needed. In this case, teh function should set \a
+ pcb_data_dst to the number of bytes required and then return
+ KHM_ERROR_TOO_LONG.
+
+ \param[in] data_src Pointer to a valid data buffer
+
+ \param[in] cb_data_src Number of bytes in \a data_src. If the data
+ type flags has KCDB_TYPE_FLAG_CB_AUTO, then this parameter
+ could be set to KCDB_CBSIZE_AUTO. In this case, the function
+ should compute the size of the input buffer assuming that the
+ input buffer is valid.
+
+ \param[out] data_dst Poitner to destination buffer. Could be NULL
+ if only the required size of the destination buffer is to be
+ returned.
+
+ \param[in,out] pcb_data_dst On entry specifies the number of bytes
+ in \a data_dst, and on exit should contain the number of bytes
+ copied.
+
+ \retval KHM_ERROR_SUCCESS The data was successfully copied. The
+ number of bytes copied is in \a pcb_data_dst
+
+ \retval KHM_ERROR_INVALID_PARAM One or more parameters is incorrect.
+
+ \retval KHM_ERROR_TOO_LONG Either \a data_dst was NULL or the size
+ of the buffer was insufficient. The required size is in \a
+ pcb_data_dst
+
+ \note This documents the expected behavior of this prototype function
+
+ \see ::kcdb_type
+ */
+typedef khm_int32
+(KHMAPI *kcdb_dtf_dup)(const void * data_src,
+ khm_size cb_data_src,
+ void * data_dst,
+ khm_size * pcb_data_dst);
+
+/*! \brief A data type descriptor.
+
+ Handles basic operation for a specific data type.
+
+ \see \ref cred_data_types
+*/
+typedef struct tag_kcdb_type {
+ wchar_t * name;
+ khm_int32 id;
+ khm_int32 flags;
+
+ khm_size cb_min;
+ khm_size cb_max;
+
+ kcdb_dtf_toString toString;
+ /*!< Provides a string representation for a value. */
+
+ kcdb_dtf_isValid isValid;
+ /*!< Returns true of the value is valid for this data type */
+
+ kcdb_dtf_comp comp;
+ /*!< Compare two values and return \a strcmp style return value */
+
+ kcdb_dtf_dup dup;
+ /*!< Duplicate a value into a secondary buffer */
+} kcdb_type;
+
+/*! \name Flags for kcdb_type::toString
+@{*/
+/*! \brief Specify that the short form of the string representation should be returned.
+
+ Flags for #kcdb_type::toString. The flag specifies how long the
+ string representation should be. The specific length of a short
+ or long description is not restricted and it is up to the
+ implementation to choose how to interpret the flags.
+
+ Usually, KCDB_TS_SHORT is specified when the amount of space that
+ is available to display the string is very restricted. It may be
+ the case that the string is truncated to facilitate displaying in
+ a constrainted space.
+*/
+#define KCDB_TS_SHORT 1
+
+/*! \brief Specify that the long form of the string representation should be returned
+
+ Flags for #kcdb_type::toString. The flag specifies how long the
+ string representation should be. The specific length of a short
+ or long description is not restricted and it is up to the
+ implementation to choose how to interpret the flags.
+
+*/
+#define KCDB_TS_LONG 0
+/*@}*/
+
+/*! \brief The maximum number of bytes allowed for a value of any type */
+#define KCDB_TYPE_MAXCB 16384
+
+/*! \name Flags for kcdb_type
+@{*/
+
+/*! \brief The type supports KCDB_CBSIZE_AUTO.
+
+ Used for types where the size of the object can be determined
+ through context or by the object content. Such as for objects
+ that have a fixed size or unicode strings that have a terminator.
+
+ This implies that ALL the object manipulation callbacks that are
+ defined in this type definition support the KCDB_CBSIZE_AUTO
+ value.
+*/
+#define KCDB_TYPE_FLAG_CB_AUTO 16
+
+/*! \brief The \a cb_min member is valid.
+
+ The \a cb_min member defines the minimum number of bytes that an
+ object of this type will consume.
+
+ \note If this flag is used in conjunction with \a
+ KCDB_TYPE_FLAG_CB_MAX then, \a cb_min must be less than or equal
+ to \a cb_max.
+*/
+#define KCDB_TYPE_FLAG_CB_MIN 128
+
+/*! \brief The \a cb_max member is valid.
+
+ The \a cb_max member defines the maximum number of bytes that an
+ object of this type will consume.
+
+ \note If this flag is used in conjunction with \a
+ KCDB_TYPE_FLAG_CB_MIN then, \a cb_min must be less than or
+ equal to \a cb_max. */
+#define KCDB_TYPE_FLAG_CB_MAX 256
+
+/*! \brief Denotes that objects of this type have a fixed size.
+
+ If this flags is specified, then the type definition must also
+ specify cb_min and cb_max, which must both be the same value.
+
+ \note Implies \a KCDB_TYPE_FLAG_CB_AUTO, \a KCDB_TYPE_FLAG_CB_MIN
+ and \a KCDB_TYPE_FLAG_CB_MAX. Pay special attention to the
+ implication of \a KCDB_TYPE_FLAG_AUTO.
+*/
+#define KCDB_TYPE_FLAG_CB_FIXED (KCDB_TYPE_FLAG_CB_AUTO|KCDB_TYPE_FLAG_CB_MIN|KCDB_TYPE_FLAG_CB_MAX)
+
+/*@}*/
+
+KHMEXP khm_int32 KHMAPI
+kcdb_type_get_id(const wchar_t *name, khm_int32 * id);
+
+/*! \brief Return the type descriptor for a given type id
+
+ \param[out] info Receives a held reference to a type descriptor.
+ Use kcdb_type_release_info() to release the handle. If the \a
+ info parameter is NULL, the function returns KHM_ERROR_SUCCESS
+ if \a id is a valid type id, and returns KHM_ERROR_NOT_FOUND
+ otherwise.
+
+ \see kcdb_type_release_info()
+*/
+KHMEXP khm_int32 KHMAPI
+kcdb_type_get_info(khm_int32 id, kcdb_type ** info);
+
+/*! \brief Release a reference to a type info structure
+
+ Releases the reference to the type information obtained with a
+ prior call to kcdb_type_get_info().
+ */
+KHMEXP khm_int32 KHMAPI
+kcdb_type_release_info(kcdb_type * info);
+
+/*! \brief Get the name of a type
+
+ Retrieves the non-localized name of the specified type.
+ */
+KHMEXP khm_int32 KHMAPI
+kcdb_type_get_name(khm_int32 id,
+ wchar_t * buffer,
+ khm_size * cbbuf);
+
+/*! \brief Register a credentials attribute type
+
+ The credentials type record pointed to by \a type defines a new
+ credential attribute type. The \a id member of \a type may be set
+ to KCDB_TYPE_INVALID to indicate that an attribute ID is to be
+ generated automatically.
+
+ \param[in] type The type descriptor
+ \param[out] new_id Receives the identifier for the credential attribute type.
+*/
+KHMEXP khm_int32 KHMAPI
+kcdb_type_register(const kcdb_type * type,
+ khm_int32 * new_id);
+
+/*! \brief Unregister a credential attribute type
+
+ Removes the registration for the specified credentials attribute
+ type.
+*/
+KHMEXP khm_int32 KHMAPI
+kcdb_type_unregister(khm_int32 id);
+
+KHMEXP khm_int32 KHMAPI
+kcdb_type_get_next_free(khm_int32 * id);
+
+/*! \name Conversion functions
+@{*/
+/*! \brief Convert a time_t value to FILETIME
+*/
+KHMEXP void KHMAPI
+TimetToFileTime( time_t t, LPFILETIME pft );
+
+/*! \brief Convert a time_t interval to a FILETIME interval
+*/
+KHMEXP void KHMAPI
+TimetToFileTimeInterval(time_t t, LPFILETIME pft);
+
+/*! \brief Convert a FILETIME interval to seconds
+*/
+KHMEXP long KHMAPI
+FtIntervalToSeconds(LPFILETIME pft);
+
+/*! \brief Convert a FILETIME interval to milliseconds
+*/
+KHMEXP long KHMAPI
+FtIntervalToMilliseconds(LPFILETIME pft);
+
+/*! \brief Compare two FILETIME values
+
+ The return value is similar to the return value of strcmp(), based
+ on the comparison of the two FILETIME values.
+ */
+KHMEXP long KHMAPI
+FtCompare(LPFILETIME pft1, LPFILETIME pft2);
+
+/*! \brief Convert a FILETIME to a 64 bit int
+*/
+KHMEXP khm_int64 KHMAPI FtToInt(LPFILETIME pft);
+
+/*! \brief Convert a 64 bit int to a FILETIME
+*/
+KHMEXP FILETIME KHMAPI IntToFt(khm_int64 i);
+
+/*! \brief Calculate the difference between two FILETIMEs
+
+ Returns the value of ft1 - ft2
+ */
+KHMEXP FILETIME KHMAPI FtSub(LPFILETIME ft1, LPFILETIME ft2);
+
+/*! \brief Calculate the sum of two FILETIMEs
+
+ Return the value of ft1 + ft2
+ */
+KHMEXP FILETIME KHMAPI FtAdd(LPFILETIME ft1, LPFILETIME ft2);
+
+/*! \brief Convert a FILETIME inverval to a string
+*/
+KHMEXP khm_int32 KHMAPI
+FtIntervalToString(LPFILETIME data,
+ wchar_t * buffer,
+ khm_size * cb_buf);
+
+/*! \brief Parse a string representing an interval into a FILETIME interval
+
+ The string is a localized string which should look like the
+ following:
+
+ \code
+ [number unit] [number unit]...
+ \endcode
+
+ where \a number is an integer while \a unit is a localized
+ (possibly abbreviated) unit specification. The value of the
+ described interval is calculated as the sum of each \a number in
+ \a units. For example :
+
+ \code
+ 1 hour 36 minutes
+ \endcode
+
+ would result in an interval specification that's equivalent to 1
+ hour and 36 minutes. Of course there is no restriction on the
+ order in which the \a number \a unit specifications are given and
+ the same unit may be repeated multiple times.
+
+ \retval KHM_ERROR_INVALID_PARAM The given string was invalid or had
+ a token that could not be parsed. It can also mean that \a
+ pft was NULL or \a str was NULL.
+
+ \retval KHM_ERROR_SUCCESS The string was successfully parsed and
+ the result was placed in \a pft.
+*/
+KHMEXP khm_int32 KHMAPI
+IntervalStringToFt(FILETIME * pft, wchar_t * str);
+
+/*! \brief Return number of milliseconds till next representation change
+
+ Returns the number of milliseconds that must elapse away from the
+ interval specified in pft \a for the representation of pft to change
+ from whatever it is right now.
+
+ Returns 0 if the representation is not expected to change.
+*/
+KHMEXP long KHMAPI
+FtIntervalMsToRepChange(LPFILETIME pft);
+
+/*! \brief Convert a safe ANSI string to a Unicode string
+
+ The resulting string is guaranteed to be NULL terminated and
+ within the size limit set by \a cbwstr.
+
+ If the whole string cannot be converted, \a wstr is set to an
+ empty string.
+
+ \return the number of characters converted. This is always either
+ the length of the string \a astr or 0.
+*/
+KHMEXP int KHMAPI
+AnsiStrToUnicode( wchar_t * wstr, size_t cbwstr, const char * astr);
+
+/*! \brief Convert a Unicode string to ANSI
+
+ The resulting string is guaranteed to be NULL terminated and
+ within the size limit set by \a cbdest.
+
+ \return the number of characters converted. This is always either
+ the length of the string \a src or 0.
+*/
+KHMEXP int KHMAPI
+UnicodeStrToAnsi( char * dest, size_t cbdest, const wchar_t * src);
+/*@}*/
+
+/*! \name Standard type identifiers and names
+@{*/
+
+/*! Maximum identifier number */
+#define KCDB_TYPE_MAX_ID 255
+
+/*! \brief Invalid type
+
+ Used by functions that return a type identifier to indicate that
+ the returned type identifier is invalid. Also used to indicate
+ that a type identifier is not available */
+#define KCDB_TYPE_INVALID (-1)
+
+/*! \brief All types
+
+ Used by filters to indicate that all types are allowed.
+*/
+#define KCDB_TYPE_ALL KCDB_TYPE_INVALID
+
+/*! \brief Void
+
+ No data. This is not an actual data type.
+ */
+#define KCDB_TYPE_VOID 0
+
+/*! \brief String
+
+ NULL terminated Unicode string. The byte count for a string
+ attribute always includes the terminating NULL.
+ */
+#define KCDB_TYPE_STRING 1
+
+/*! \brief Data
+
+ A date/time represented in FILETIME format.
+ */
+#define KCDB_TYPE_DATE 2
+
+/*! \brief Interval
+
+ An interval of time represented as the difference between two
+ FILETIME values.
+ */
+#define KCDB_TYPE_INTERVAL 3
+
+/*! \brief 32-bit integer
+
+ A 32-bit signed integer.
+ */
+#define KCDB_TYPE_INT32 4
+
+/*! \brief 64-bit integer
+
+ A 64-bit integer.
+ */
+#define KCDB_TYPE_INT64 5
+
+/*! \brief Raw data
+
+ A raw data buffer.
+ */
+#define KCDB_TYPE_DATA 6
+
+#define KCDB_TYPENAME_VOID L"Void"
+#define KCDB_TYPENAME_STRING L"String"
+#define KCDB_TYPENAME_DATE L"Date"
+#define KCDB_TYPENAME_INTERVAL L"Interval"
+#define KCDB_TYPENAME_INT32 L"Int32"
+#define KCDB_TYPENAME_INT64 L"Int64"
+#define KCDB_TYPENAME_DATA L"Data"
+/*@}*/
+/*@}*/
+
+/********************************************************************/
+
+/*! \defgroup kcdb_credattr Credential attributes */
+/*@{*/
+
+/*! \brief Prototype callback function for computed data types.
+
+ If the flags for a particular attribute specifies that the value
+ is computed, then a callback function should be specified. The
+ callback function will be called with a handle to a credential
+ along with the attribute ID for the requested attribute. The
+ function should place the computed value in \a buffer. The size
+ of the buffer in bytes is specifed in \a cbsize. However, if \a
+ buffer is \a NULL, then the required buffer size should be placed
+ in \a cbsize.
+ */
+typedef khm_int32
+(KHMAPI *kcdb_attrib_compute_cb)(khm_handle cred,
+ khm_int32 id,
+ void * buffer,
+ khm_size * cbsize);
+
+/*! \brief Credential attribute descriptor
+
+ \see kcdb_attrib_register()
+*/
+typedef struct tag_kcdb_attrib {
+ wchar_t * name; /*!< Name. (Not localized,
+ required) */
+ khm_int32 id; /*!< Identifier. When registering,
+ this can be set to
+ ::KCDB_ATTR_INVALID if a unique
+ identifier is to be generated. */
+ khm_int32 alt_id; /*!< Alternate identifier. If the \a
+ flags specify
+ ::KCDB_ATTR_FLAG_ALTVIEW, then this
+ field should specify the identifier
+ of the canonical attribute from
+ which this attribute is derived. */
+ khm_int32 flags; /*!< Flags. Combination of \ref
+ kcdb_credattr_flags "attribute
+ flags" */
+
+ khm_int32 type; /*!< Type of the attribute. Must be valid. */
+
+ wchar_t * short_desc; /*!< Short description. (Localized,
+ optional) */
+
+ wchar_t * long_desc; /*!< Long description. (Localized,
+ optional) */
+
+ kcdb_attrib_compute_cb compute_cb;
+ /*!< Callback. Required if \a flags
+ specify ::KCDB_ATTR_FLAG_COMPUTED. */
+
+ khm_size compute_min_cbsize;
+ /*!< Minimum number of bytes required
+ to store this attribute. Required
+ if ::KCDB_ATTR_FLAG_COMPUTED is
+ specified.*/
+ khm_size compute_max_cbsize;
+ /*!< Maximum number of bytes required
+ to store this attribute. Required
+ if ::KCDB_ATTR_FLAG_COMPUTED is
+ specified.*/
+} kcdb_attrib;
+
+/*! \brief Retrieve the ID of a named attribute */
+KHMEXP khm_int32 KHMAPI
+kcdb_attrib_get_id(const wchar_t *name,
+ khm_int32 * id);
+
+/*! \brief Register an attribute
+
+ \param[out] new_id Receives the ID of the newly registered
+ attribute. If the \a id member of the ::kcdb_attrib object is
+ set to KCDB_ATTR_INVALID, then a unique ID is generated. */
+KHMEXP khm_int32 KHMAPI
+kcdb_attrib_register(const kcdb_attrib * attrib,
+ khm_int32 * new_id);
+
+/*! \brief Retrieve the attribute descriptor for an attribute
+
+ The descriptor that is returned must be released through a call to
+ kcdb_attrib_release_info()
+
+ If only the validity of the attribute identifier needs to be
+ checked, you can pass in NULL for \a attrib. In this case, if the
+ identifier is valid, then the funciton will return
+ KHM_ERROR_SUCCESS, otherwise it will return KHM_ERROR_NOT_FOUND.
+
+ \see kcdb_attrib_release_info()
+ */
+KHMEXP khm_int32 KHMAPI
+kcdb_attrib_get_info(khm_int32 id,
+ kcdb_attrib ** attrib);
+
+/*! \brief Release an attribute descriptor
+
+ \see kcdb_attrib_get_info()
+ */
+KHMEXP khm_int32 KHMAPI
+kcdb_attrib_release_info(kcdb_attrib * attrib);
+
+/*! \brief Unregister an attribute
+
+ Once an attribute ID has been unregistered, it may be reclaimed by
+ a subsequent call to kcdb_attrib_register().
+*/
+KHMEXP khm_int32 KHMAPI
+kcdb_attrib_unregister(khm_int32 id);
+
+/*! \brief Retrieve the description of an attribute
+
+ \param[in] flags Specify \a KCDB_TS_SHORT to retrieve the short description. */
+KHMEXP khm_int32 KHMAPI
+kcdb_attrib_describe(khm_int32 id,
+ wchar_t * buffer,
+ khm_size * cbsize,
+ khm_int32 flags);
+
+/*! \brief Count attributes
+
+ Counts the number of attributes that match the given criteria.
+ The criteria is specified against the flags of the attribute. An
+ attribute is a match if its flags satisfy the condition below:
+
+ \code
+ (attrib.flags & and_flags) == (eq_flags & and_flags)
+ \endcode
+
+ The number of attributes that match are returned in \a pcount.
+ */
+KHMEXP khm_int32 KHMAPI
+kcdb_attrib_get_count(khm_int32 and_flags,
+ khm_int32 eq_flags,
+ khm_size * pcount);
+
+/*! \brief List attribute identifiers
+
+ Lists the identifiers of the attributes that match the given
+ criteria. The criteria is specified against the flags of the
+ attribute. An attribute is a match if the following condition is
+ satisfied:
+
+ \code
+ (attrib.flags & and_flags) == (eq_flags & and_flags)
+ \endcode
+
+ The list of attributes found are copied to the \a khm_int32 array
+ specified in \a plist. The number of elements available in the
+ buffer \a plist is specified in \a pcsize. On exit, \a pcsize
+ will hold the actual number of attribute identifiers copied to the
+ array.
+
+ \param[in] and_flags See above
+ \param[in] eq_flags See above
+ \param[in] plist A khm_int32 array
+ \param[in,out] pcsize On entry, holds the number of elements
+ available in the array pointed to by \a plist. On exit, holds
+ the number of elements copied to the array.
+
+ \retval KHM_ERROR_SUCCESS The list of attribute identifiers have
+ been copied.
+ \retval KHM_ERROR_TOO_LONG The list was too long to fit in the
+ supplied buffer. As many elements as possible have been
+ copied to the \a plist array and the required number of
+ elements has been written to \a pcsize.
+
+ \note The \a pcsize parameter specifies the number of khm_int32
+ elements in the array and not the number of bytes in the
+ array. This is different from the usual size parameters used
+ in the NetIDMgr API.
+ */
+KHMEXP khm_int32 KHMAPI
+kcdb_attrib_get_ids(khm_int32 and_flags,
+ khm_int32 eq_flags,
+ khm_int32 * plist,
+ khm_size * pcsize);
+
+/*! \defgroup kcdb_credattr_flags Attribute flags */
+/*@{*/
+/*! \brief The attribute is required */
+#define KCDB_ATTR_FLAG_REQUIRED 0x00000008
+
+/*! \brief The attribute is computed.
+
+ If this flag is set, the \a compute_cb, \a compute_min_cbsize and
+ \a compute_max_cbsize members of the ::kcdb_attrib attribute
+ descriptor must be assigned valid values.
+*/
+#define KCDB_ATTR_FLAG_COMPUTED 0x00000010
+
+/*! \brief System attribute.
+
+ This cannot be specified for a custom attribute. Implies that the
+ value of the attribute is given by the credentials database
+ itself.
+*/
+#define KCDB_ATTR_FLAG_SYSTEM 0x00000020
+
+/*! \brief Hidden
+
+ The attribute is not meant to be displayed to the user. Setting
+ this flag prevents this attribute from being listed in the list of
+ available data fields in the UI.
+*/
+#define KCDB_ATTR_FLAG_HIDDEN 0x00000040
+
+/*! \brief Property
+
+ The attribute is a property. The main difference between regular
+ attributes and properties are that properties are not allocated
+ off the credentials record. Hence, a property can not be used as
+ a credentials field. Other objects such as identities can hold
+ property sets. A property set can hold both regular attributes as
+ well as properties.
+*/
+#define KCDB_ATTR_FLAG_PROPERTY 0x00000080
+
+/*! \brief Volatile
+
+ A volatile property is one whose value changes often, such as
+ ::KCDB_ATTR_TIMELEFT. Some controls will make use of additional
+ logic to deal with such values, or not display them at all.
+ */
+#define KCDB_ATTR_FLAG_VOLATILE 0x00000100
+
+/*! \brief Alternate view
+
+ The attribute is actually an alternate representation of another
+ attribute. The Canonical attribute name is specified in \a
+ alt_id.
+
+ Sometimes a certain attribute may need to be represented in
+ different ways. You can register multiple attributes for each
+ view. However, you should also provide a canonical attribute for
+ whenever the canonical set of attributes of the credential is
+ required.
+ */
+#define KCDB_ATTR_FLAG_ALTVIEW 0x00000200
+
+/*! \brief Transient attribute
+
+ A transient attribute is one whose absence is meaningful. When
+ updating one record using another, if a transient attribute is
+ absent in the source but present in the destination, then the
+ attribute is removed from the destination.
+*/
+#define KCDB_ATTR_FLAG_TRANSIENT 0x00000400
+
+/*@}*/
+
+/*! \defgroup kcdb_credattr_idnames Standard attribute IDs and names */
+/*@{*/
+
+/*! \name Attribute related constants */
+/*@{*/
+/*! \brief Maximum valid attribute ID */
+#define KCDB_ATTR_MAX_ID 255
+
+/*! \brief Minimum valid property ID */
+#define KCDB_ATTR_MIN_PROP_ID 4096
+
+/*! \brief Maximum number of properties */
+#define KCDB_ATTR_MAX_PROPS 128
+
+/*! \brief Maximum valid property ID */
+#define KCDB_ATTR_MAX_PROP_ID (KCDB_ATTR_MIN_PROP_ID + KCDB_ATTR_MAX_PROPS - 1)
+
+/*! \brief Invalid ID */
+#define KCDB_ATTR_INVALID (-1)
+
+/*! \brief First custom attribute ID */
+#define KCDB_ATTRID_USER 20
+
+/*@}*/
+
+/*!\name Attribute identifiers */
+/*@{*/
+/*! \brief Name of the credential
+
+ - \b Type: STRING
+ - \b Flags: REQUIRED, COMPUTED, SYSTEM
+ */
+#define KCDB_ATTR_NAME 0
+
+/*! \brief The identity handle for the credential
+
+ - \b Type: INT64
+ - \b Flags: REQUIRED, COMPUTED, SYSTEM, HIDDEN
+
+ \note The handle returned in by specifying this attribute to
+ kcdb_cred_get_attr() or kcdb_cred_get_attrib() is not held.
+ While the identity is implicitly held for the duration that
+ the credential is held, it is not recommended to obtain a
+ handle to the identity using this method. Use
+ kcdb_cred_get_identity() instead.
+*/
+#define KCDB_ATTR_ID 1
+
+/*! \brief The name of the identity
+
+ - \b Type: STRING
+ - \b Flags: REQUIRED, COMPUTED, SYSTEM
+ */
+#define KCDB_ATTR_ID_NAME 2
+
+/*! \brief The type of the credential
+
+ - \b Type: INT32
+ - \b Flags: REQUIRED, COMPUTED, SYSTEM, HIDDEN
+*/
+#define KCDB_ATTR_TYPE 3
+
+/*! \brief Type name for the credential
+
+ - \b Type: STRING
+ - \b Flags: REQUIRED, COMPUTED, SYSTEM
+*/
+#define KCDB_ATTR_TYPE_NAME 4
+
+/*! \brief Name of the parent credential
+
+ - \b Type: STRING
+ - \b Flags: SYSTEM
+*/
+#define KCDB_ATTR_PARENT_NAME 5
+
+/*! \brief Issed on
+
+ - \b Type: DATE
+ - \b Flags: SYSTEM
+*/
+#define KCDB_ATTR_ISSUE 6
+
+/*! \brief Expires on
+
+ - \b Type: DATE
+ - \b Flags: SYSTEM
+*/
+#define KCDB_ATTR_EXPIRE 7
+
+/*! \brief Renewable period expires on
+
+ - \b Type: DATE
+ - \b Flags: SYSTEM
+*/
+#define KCDB_ATTR_RENEW_EXPIRE 8
+
+/*! \brief Time left till expiration
+
+ - \b Type: INTERVAL
+ - \b Flags: SYSTEM, COMPUTED, VOLATILE
+*/
+#define KCDB_ATTR_TIMELEFT 9
+
+#define KCDB_ATTR_RENEW_TIMELEFT 10
+
+/*! \brief Location of the credential
+
+ - \b Type: STRING
+ - \b Flags: SYSTEM
+*/
+#define KCDB_ATTR_LOCATION 11
+
+/*! \brief Lifetime of the credential
+
+ - \b Type: INTERVAL
+ - \b Flags: SYSTEM
+*/
+#define KCDB_ATTR_LIFETIME 12
+
+#define KCDB_ATTR_RENEW_LIFETIME 13
+
+/*! \brief Flags for the credential
+
+ - \b Type: INT32
+ - \b Flags: REQUIRED, COMPUTED, SYSTEM, HIDDEN
+ */
+#define KCDB_ATTR_FLAGS 14
+
+/*@}*/
+
+/*!\name Attribute names */
+/*@{ */
+
+#define KCDB_ATTRNAME_NAME L"Name"
+#define KCDB_ATTRNAME_ID L"Identity"
+#define KCDB_ATTRNAME_ID_NAME L"IdentityName"
+#define KCDB_ATTRNAME_TYPE L"TypeId"
+#define KCDB_ATTRNAME_TYPE_NAME L"TypeName"
+#define KCDB_ATTRNAME_FLAGS L"Flags"
+
+#define KCDB_ATTRNAME_PARENT_NAME L"Parent"
+#define KCDB_ATTRNAME_ISSUE L"Issued"
+#define KCDB_ATTRNAME_EXPIRE L"Expires"
+#define KCDB_ATTRNAME_RENEW_EXPIRE L"RenewExpires"
+#define KCDB_ATTRNAME_TIMELEFT L"TimeLeft"
+#define KCDB_ATTRNAME_RENEW_TIMELEFT L"RenewTimeLeft"
+#define KCDB_ATTRNAME_LOCATION L"Location"
+#define KCDB_ATTRNAME_LIFETIME L"Lifetime"
+#define KCDB_ATTRNAME_RENEW_LIFETIME L"RenewLifetime"
+
+/*@}*/
+
+/*@}*/
+
+/*@}*/
+
+/*****************************************************************************/
+
+/*! \defgroup kcdb_credtype Credential types */
+/*@{*/
+
+/*! \brief Credential type descriptor */
+typedef struct tag_kcdb_credtype {
+ wchar_t * name; /*!< name (less than KCDB_MAXCB_NAME bytes) */
+ khm_int32 id;
+ wchar_t * short_desc; /*!< short localized description (less
+ than KCDB_MAXCB_SHORT_DESC bytes) */
+ wchar_t * long_desc; /*!< long localized descriptionn (less
+ than KCDB_MAXCB_LONG_DESC bytes) */
+ khm_handle sub; /*!< Subscription for credentials type
+ hander. This should be a valid
+ subscription constructed through a
+ call to kmq_create_subscription()
+ and must handle KMSG_CRED messages
+ that are marked as being sent to
+ type specific subscriptions.
+
+ The subscription will be
+ automatically deleted with a call to
+ kmq_delete_subscription() when the
+ credentials type is unregistered.*/
+
+ kcdb_cred_comp_func is_equal; /*!< Used as an additional clause
+ when comparing two credentials for
+ equality. The function this is
+ actually a comparison function, it
+ should return zero if the two
+ credentials are equal and non-zero
+ if they are not. The addtional \a
+ rock parameter is always zero.
+
+ It can be assumed that the identity,
+ name and credentials type have
+ already been found to be equal among
+ the credentials and the credential
+ type is the type that is being
+ registered.*/
+
+#ifdef _WIN32
+ HICON icon;
+#endif
+} kcdb_credtype;
+
+/*! \brief Maximum value of a credential type identifier
+
+ Credential type identifiers are assigned serially unless the
+ process registering the credential type sets a specific identity.
+ The maximum identifier number places a hard limit to the number of
+ credential types that can be registered at one time, which is
+ KCDB_CREDTYPE_MAX_ID + 1.
+ */
+#define KCDB_CREDTYPE_MAX_ID 31
+
+/*! \brief Specify all credential types
+
+ This value is used by functions which filter credentials based on
+ credential types. Specifying this value tells the filter to
+ accept all credential types.
+ */
+#define KCDB_CREDTYPE_ALL (-1)
+
+/*! \brief Automatically determine a credential type identifier
+
+ Used with kcdb_credtype_register() to specify that the credential
+ type identifier should be automatically determined to avoid
+ collisions.
+ */
+#define KCDB_CREDTYPE_AUTO (-2)
+
+/*! \brief An invalid credential type
+
+ Even though any non positive credential type ID is invalid
+ anywhere where a specific credential type ID is required, this
+ value is provided for explicit indication that the credential type
+ is invalid. Also it makes code more readable to have a constant
+ that shouts out INVALID.
+
+*/
+#define KCDB_CREDTYPE_INVALID (-3)
+
+/*! \brief Macro predicate for testing whether a credtype is valid
+
+ Returns TRUE if the given credtype is valid. This is a safe
+ macro.
+*/
+#define KCDB_CREDTYPE_IS_VALID(t) ((t) >= 0)
+
+/*! \brief Register a credentials type.
+
+ The information given in the \a type parameter is used to register
+ a new credential type. Note that the \a name member of the \a
+ type should be unique among all credential types.
+
+ You can specify ::KCDB_CREDTYPE_AUTO as the \a id member of \a
+ type to let kcdb_credtype_register() determine a suitable
+ credential type identifier. You can subsequently call
+ kcdb_credtype_get_id() to retrieve the generated id or pass a
+ valid pointer to a khm_int32 type variable as \a new_id.
+
+ \param[in] type Credential type descriptor
+
+ \param[out] new_id The credential type identifier that this type
+ was registered as.
+
+ \retval KHM_ERROR_SUCCESS The credential type was successfully registered.
+
+ \retval KHM_ERROR_INVALID_PARAM One or more of the parameters were invalid
+
+ \retval KHM_ERROR_TOO_LONG One or more of the string fields in \a
+ type exceeded the character limit for that field.
+
+ \retval KHM_ERROR_NO_RESOURCES When autogenerating credential type
+ identifiers, this value indicates that the maximum number of
+ credential types have been registered. No more registrations
+ can be accepted unless some credentials type is unregisred.
+
+ \retval KHM_ERROR_DUPLICATE The \a name or \a id that was
+ specified is already in use.
+*/
+KHMEXP khm_int32 KHMAPI
+kcdb_credtype_register(const kcdb_credtype * type,
+ khm_int32 * new_id);
+
+/*! \brief Return a held reference to a \a kcdb_credtype object describing the credential type.
+
+ The reference points to a static internal object of type \a
+ kcdb_credtype. Use the kcdb_credtype_release_info() function to
+ release the reference.
+
+ Also, the structure passed in as the \a type argument to
+ kcdb_credtype_register() is not valid as a credential type
+ descriptor. Use kcdb_credtype_get_info() to obtain the actual
+ credential type descriptor.
+
+ \param[in] id Credentials type identifier.
+
+ \param[out] type Receives the credentials descriptor handle. If
+ \a type is NULL, then no handle is returned. However, the
+ function will still return \a KHM_ERROR_SUCCESS if the \a id
+ parameter passed in is a valid credentials type identifier.
+
+ \see kcdb_credtype_release_info()
+ \see kcdb_credtype_register()
+*/
+KHMEXP khm_int32 KHMAPI
+kcdb_credtype_get_info(khm_int32 id,
+ kcdb_credtype ** type);
+
+/*! \brief Release a reference to a \a kcdb_credtype object
+
+ Undoes the hold obtained on a \a kcdb_credtype object from a
+ previous call to kcdb_credtype_get_info().
+
+ \see kcdb_credtype_get_info()
+ */
+KHMEXP khm_int32 KHMAPI
+kcdb_credtype_release_info(kcdb_credtype * type);
+
+/*! \brief Unregister a credentials type
+
+ Undoes the registration performed by kcdb_credtype_register().
+
+ This should only be done when the credentials provider is being
+ unloaded.
+ */
+KHMEXP khm_int32 KHMAPI
+kcdb_credtype_unregister(khm_int32 id);
+
+/*! \brief Retrieve the name of a credentials type
+
+ Given a credentials type identifier, retrieves the name. The name
+ is not localized and serves as a persistent identifier of the
+ credentials type.
+
+ \param[out] buf The buffer to receive the name. Could be \a NULL
+ if only the length of the buffer is required.
+
+ \param[in,out] cbbuf On entry, specifies the size of the buffer
+ pointed to by \a buf if \a buf is not NULL. On exit, contains
+ the number of bytes copied to \a buf or the required size of
+ the buffer.
+
+ \retval KHM_ERROR_SUCCESS The call succeeded.
+
+ \retval KHM_ERROR_TOO_LONG Either \a buf was NULL or the supplied
+ buffer was not large enough. The required size is in \a cbbuf.
+
+ \retval KHM_ERROR_INVALID_PARAM Invalid parameter.
+ */
+KHMEXP khm_int32 KHMAPI
+kcdb_credtype_get_name(khm_int32 id,
+ wchar_t * buf,
+ khm_size * cbbuf);
+
+/*! \brief Retrieve the type specific subscription for a type
+
+ Given a credentials type, this function returns the credentials
+ type specific subcription. It may return NULL if the subscription
+ is not available.
+ */
+KHMEXP khm_handle KHMAPI
+kcdb_credtype_get_sub(khm_int32 id);
+
+/*! \brief Get the description of a credentials type
+
+ Unlike the name of a credential type, the description is localized.
+
+ \param[in] id Credentials type identifier
+
+ \param[out] buf Receives the description. Can bet set to NULL if
+ only the size of the buffer is required.
+
+ \param[in,out] cbbuf On entry, specifies the size of the buffer
+ pointed to by \a buf. On exit, specifies the required size of
+ the buffer or the number of bytes copied, depending on whether
+ the call succeeded or not.
+
+ \param[in] flags Specify ::KCDB_TS_SHORT if the short version of
+ the description is desired if there is more than one.
+
+ \retval KHM_ERROR_SUCCESS The call succeeded
+ \retval KHM_ERROR_TOO_LONG Either \a buf was NULL or the supplied buffer was insufficient. The required size is specified in \a cbbuf.
+ \retval KHM_ERROR_INVALID_PARAM One or more parameters were invalid.
+ */
+KHMEXP khm_int32 KHMAPI
+kcdb_credtype_describe(khm_int32 id,
+ wchar_t * buf,
+ khm_size * cbbuf,
+ khm_int32 flags);
+
+/*! \brief Look up the identifier of a credentials type by name
+
+ Given a name, looks up the identifier.
+
+ \param[in] name Name of the credentials type
+ \param[out] id Receives the identifier if the call succeeds
+
+ */
+KHMEXP khm_int32 KHMAPI
+kcdb_credtype_get_id(const wchar_t * name,
+ khm_int32 * id);
+
+/*@}*/
+
+/*********************************************************************/
+
+/*! \defgroup kcdb_buf Generic access to buffer
+
+ Currently, credentials and identities both hold record data types.
+ This set of API's allow an application to access fields in the
+ records using a single interface. Note that credentials only
+ accept regular attributes while identities can hold both
+ attributes and properties.
+
+ Handles to credentials and identities are implicitly also handles
+ to records. Thus they can be directly used as such.
+*/
+/*@{*/
+
+/*! \brief Get an attribute from a record by attribute id.
+
+ \param[in] buffer The buffer that is to receive the attribute
+ value. Set this to NULL if only the required buffer size is
+ to be returned.
+
+ \param[in,out] cbbuf The number of bytes available in \a buffer.
+ If \a buffer is not sufficient, returns KHM_ERROR_TOO_LONG and
+ sets this to the required buffer size.
+
+ \param[out] attr_type Receives the data type of the attribute.
+ Set this to NULL if the type is not required.
+
+ \note Set both \a buffer and \a cbbuf to NULL if only the
+ existence of the attribute is to be checked. If the attribute
+ exists in this record then the function will return
+ KHM_ERROR_SUCCESS, otherwise it returns KHM_ERROR_NOT_FOUND.
+*/
+KHMEXP khm_int32 KHMAPI
+kcdb_buf_get_attr(khm_handle record,
+ khm_int32 attr_id,
+ khm_int32 * attr_type,
+ void * buffer,
+ khm_size * pcb_buf);
+
+/*! \brief Get an attribute from a record by name.
+
+ \param[in] buffer The buffer that is to receive the attribute
+ value. Set this to NULL if only the required buffer size is
+ to be returned.
+
+ \param[in,out] cbbuf The number of bytes available in \a buffer.
+ If \a buffer is not sufficient, returns KHM_ERROR_TOO_LONG and
+ sets this to the required buffer size.
+
+ \note Set both \a buffer and \a cbbuf to NULL if only the
+ existence of the attribute is to be checked. If the attribute
+ exists in this record then the function will return
+ KHM_ERROR_SUCCESS, otherwise it returns KHM_ERROR_NOT_FOUND.
+*/
+KHMEXP khm_int32 KHMAPI
+kcdb_buf_get_attrib(khm_handle record,
+ const wchar_t * attr_name,
+ khm_int32 * attr_type,
+ void * buffer,
+ khm_size * pcb_buf);
+
+/*! \brief Get the string representation of a record attribute.
+
+ A shortcut function which generates the string representation of a
+ record attribute directly.
+
+ \param[in] record A handle to a record
+
+ \param[in] attr_id The attribute to retrieve
+
+ \param[out] buffer A pointer to a string buffer which receives the
+ string form of the attribute. Set this to NULL if you only
+ want to determine the size of the required buffer.
+
+ \param[in,out] pcbbuf A pointer to a #khm_int32 that, on entry,
+ holds the size of the buffer pointed to by \a buffer, and on
+ exit, receives the actual number of bytes that were copied.
+
+ \param[in] flags Flags for the string conversion. Can be set to
+ one of KCDB_TS_LONG or KCDB_TS_SHORT. The default is
+ KCDB_TS_LONG.
+
+ \retval KHM_ERROR_SUCCESS Success
+ \retval KHM_ERROR_NOT_FOUND The given attribute was either invalid
+ or was not defined for this record
+ \retval KHM_ERROR_INVALID_PARAM One or more parameters were invalid
+ \retval KHM_ERROR_TOO_LONG Either \a buffer was NULL or the
+ supplied buffer was insufficient
+*/
+KHMEXP khm_int32 KHMAPI
+kcdb_buf_get_attr_string(khm_handle record,
+ khm_int32 attr_id,
+ wchar_t * buffer,
+ khm_size * pcbbuf,
+ khm_int32 flags);
+
+/*! \brief Get the string representation of a record attribute by name.
+
+ A shortcut function which generates the string representation of a
+ record attribute directly.
+
+ \param[in] record A handle to a record
+
+ \param[in] attrib The name of the attribute to retrieve
+
+ \param[out] buffer A pointer to a string buffer which receives the
+ string form of the attribute. Set this to NULL if you only
+ want to determine the size of the required buffer.
+
+ \param[in,out] pcbbuf A pointer to a #khm_int32 that, on entry,
+ holds the size of the buffer pointed to by \a buffer, and on
+ exit, receives the actual number of bytes that were copied.
+
+ \param[in] flags Flags for the string conversion. Can be set to
+ one of KCDB_TS_LONG or KCDB_TS_SHORT. The default is
+ KCDB_TS_LONG.
+
+ \see kcdb_cred_get_attr_string()
+*/
+KHMEXP khm_int32 KHMAPI
+kcdb_buf_get_attrib_string(khm_handle record,
+ const wchar_t * attr_name,
+ wchar_t * buffer,
+ khm_size * pcbbuf,
+ khm_int32 flags);
+
+/*! \brief Set an attribute in a record by attribute id
+
+ \param[in] cbbuf Number of bytes of data in \a buffer. The
+ individual data type handlers may copy in less than this many
+ bytes in to the record.
+*/
+KHMEXP khm_int32 KHMAPI
+kcdb_buf_set_attr(khm_handle record,
+ khm_int32 attr_id,
+ void * buffer,
+ khm_size cbbuf);
+
+/*! \brief Set an attribute in a record by name
+
+ \param[in] cbbuf Number of bytes of data in \a buffer. The
+ individual data type handlers may copy in less than this many
+ bytes in to the record.
+*/
+KHMEXP khm_int32 KHMAPI
+kcdb_buf_set_attrib(khm_handle record,
+ const wchar_t * attr_name,
+ void * buffer,
+ khm_size cbbuf);
+
+KHMEXP khm_int32 KHMAPI
+kcdb_buf_hold(khm_handle record);
+
+KHMEXP khm_int32 KHMAPI
+kcdb_buf_release(khm_handle record);
+
+/*@}*/
+
+/********************************************************************/
+
+/* Notification operation constants */
+
+#define KCDB_OP_INSERT 1
+#define KCDB_OP_DELETE 2
+#define KCDB_OP_MODIFY 3
+#define KCDB_OP_ACTIVATE 4
+#define KCDB_OP_DEACTIVATE 5
+#define KCDB_OP_HIDE 6
+#define KCDB_OP_UNHIDE 7
+#define KCDB_OP_SETSEARCH 8
+#define KCDB_OP_UNSETSEARCH 9
+#define KCDB_OP_NEW_DEFAULT 10
+#define KCDB_OP_DELCONFIG 11
+
+/*@}*/
+
+#endif
diff --git a/src/windows/identity/kcreddb/kcreddbinternal.h b/src/windows/identity/kcreddb/kcreddbinternal.h
index f7bf4e7bd0..2b80d1832d 100644
--- a/src/windows/identity/kcreddb/kcreddbinternal.h
+++ b/src/windows/identity/kcreddb/kcreddbinternal.h
@@ -1,61 +1,61 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#ifndef __KHIMAIRA_KCREDDBINTERNAL_H__
-#define __KHIMAIRA_KCREDDBINTERNAL_H__
-
-#include<windows.h>
-#include<kcreddb.h>
-#include<kmq.h>
-#include<khlist.h>
-#include<utils.h>
-#include<kherror.h>
-#include<khmsgtypes.h>
-#include<kconfig.h>
-#include<strsafe.h>
-
-#include<langres.h>
-
-#include "buf.h"
-#include "identity.h"
-#include "attrib.h"
-#include "type.h"
-#include "credential.h"
-#include "credset.h"
-#include "credtype.h"
-
-/* globals */
-
-extern HINSTANCE hinst_kcreddb;
-
-kconf_schema schema_kcdbconfig[];
-
-void kcdb_init(void);
-void kcdb_exit(void);
-khm_handle kcdb_get_config(void);
-
-
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __KHIMAIRA_KCREDDBINTERNAL_H__
+#define __KHIMAIRA_KCREDDBINTERNAL_H__
+
+#include<windows.h>
+#include<kcreddb.h>
+#include<kmq.h>
+#include<khlist.h>
+#include<utils.h>
+#include<kherror.h>
+#include<khmsgtypes.h>
+#include<kconfig.h>
+#include<strsafe.h>
+
+#include<langres.h>
+
+#include "buf.h"
+#include "identity.h"
+#include "attrib.h"
+#include "type.h"
+#include "credential.h"
+#include "credset.h"
+#include "credtype.h"
+
+/* globals */
+
+extern HINSTANCE hinst_kcreddb;
+
+kconf_schema schema_kcdbconfig[];
+
+void kcdb_init(void);
+void kcdb_exit(void);
+khm_handle kcdb_get_config(void);
+
+
+#endif
diff --git a/src/windows/identity/kcreddb/kcreddbmain.c b/src/windows/identity/kcreddb/kcreddbmain.c
index 8f8a01b064..7702368ce0 100644
--- a/src/windows/identity/kcreddb/kcreddbmain.c
+++ b/src/windows/identity/kcreddb/kcreddbmain.c
@@ -1,40 +1,40 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<kcreddbinternal.h>
-
-HINSTANCE hinst_kcreddb;
-
-void
-kcdb_process_attach(HINSTANCE hinstDLL) {
- hinst_kcreddb = hinstDLL;
- kcdb_init();
-}
-
-void
-kcdb_process_detach(void) {
- kcdb_exit();
-}
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<kcreddbinternal.h>
+
+HINSTANCE hinst_kcreddb;
+
+void
+kcdb_process_attach(HINSTANCE hinstDLL) {
+ hinst_kcreddb = hinstDLL;
+ kcdb_init();
+}
+
+void
+kcdb_process_detach(void) {
+ kcdb_exit();
+}
diff --git a/src/windows/identity/kcreddb/langres.h b/src/windows/identity/kcreddb/langres.h
index 417b214e0a..1c3258b3d9 100644
--- a/src/windows/identity/kcreddb/langres.h
+++ b/src/windows/identity/kcreddb/langres.h
@@ -1,48 +1,48 @@
-//{{NO_DEPENDENCIES}}
-// Microsoft Visual C++ generated include file.
-// Used by D:\work\pismere\athena\auth\krb5\src\windows\identity\kcreddb\lang\en_us\kcredres.rc
-//
-#define IDS_CREDDB 101
-#define IDS_NAME 102
-#define IDS_IDENTITY 103
-#define IDS_ISSUED 104
-#define IDS_EXPIRES 105
-#define IDS_TIMELEFT 106
-#define IDS_LOCATION 107
-#define IDS_PARENT 108
-#define IDS_TYPE 109
-#define IDS_IVL_EXPIRED 110
-#define IDS_IVL_D_H 111
-#define IDS_IVL_H_M 112
-#define IDS_IVL_M_S 113
-#define IDS_IVL_S 114
-#define IDS_IVL_UNKNOWN 115
-#define IDS_LIFETIME 116
-#define IDS_IVL_1D 117
-#define IDS_IVL_1H 118
-#define IDS_IVL_1M 119
-#define IDS_IVL_1S 120
-#define IDS_IVL_D 121
-#define IDS_IVL_H 122
-#define IDS_IVL_M 123
-#define IDS_IVL_S_SPEC 124
-#define IDS_IVL_M_SPEC 125
-#define IDS_IVL_H_SPEC 126
-#define IDS_IVL_D_SPEC 127
-#define IDS_IVl_W_SPEC 128
-#define IDS_IVL_W_SPEC 128
-#define IDS_FLAGS 129
-#define IDS_RENEW_TIMELEFT 130
-#define IDS_RENEW_EXPIRES 131
-#define IDS_RENEW_LIFETIME 132
-
-// Next default values for new objects
-//
-#ifdef APSTUDIO_INVOKED
-#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE 102
-#define _APS_NEXT_COMMAND_VALUE 40001
-#define _APS_NEXT_CONTROL_VALUE 1001
-#define _APS_NEXT_SYMED_VALUE 101
-#endif
-#endif
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by D:\work\pismere\athena\auth\krb5\src\windows\identity\kcreddb\lang\en_us\kcredres.rc
+//
+#define IDS_CREDDB 101
+#define IDS_NAME 102
+#define IDS_IDENTITY 103
+#define IDS_ISSUED 104
+#define IDS_EXPIRES 105
+#define IDS_TIMELEFT 106
+#define IDS_LOCATION 107
+#define IDS_PARENT 108
+#define IDS_TYPE 109
+#define IDS_IVL_EXPIRED 110
+#define IDS_IVL_D_H 111
+#define IDS_IVL_H_M 112
+#define IDS_IVL_M_S 113
+#define IDS_IVL_S 114
+#define IDS_IVL_UNKNOWN 115
+#define IDS_LIFETIME 116
+#define IDS_IVL_1D 117
+#define IDS_IVL_1H 118
+#define IDS_IVL_1M 119
+#define IDS_IVL_1S 120
+#define IDS_IVL_D 121
+#define IDS_IVL_H 122
+#define IDS_IVL_M 123
+#define IDS_IVL_S_SPEC 124
+#define IDS_IVL_M_SPEC 125
+#define IDS_IVL_H_SPEC 126
+#define IDS_IVL_D_SPEC 127
+#define IDS_IVl_W_SPEC 128
+#define IDS_IVL_W_SPEC 128
+#define IDS_FLAGS 129
+#define IDS_RENEW_TIMELEFT 130
+#define IDS_RENEW_EXPIRES 131
+#define IDS_RENEW_LIFETIME 132
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 102
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1001
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/src/windows/identity/kcreddb/resource.h b/src/windows/identity/kcreddb/resource.h
index dfb47e0d43..bc587b2781 100644
--- a/src/windows/identity/kcreddb/resource.h
+++ b/src/windows/identity/kcreddb/resource.h
@@ -1,27 +1,27 @@
-//{{NO_DEPENDENCIES}}
-// Microsoft Visual C++ generated include file.
-// Used by kcreddb.rc
-//
-#define IDS_PROJNAME 100
-#define IDR_WMDMLOGGER 101
-#define IDS_LOG_SEV_INFO 201
-#define IDS_LOG_SEV_WARN 202
-#define IDS_LOG_SEV_ERROR 203
-#define IDS_LOG_DATETIME 204
-#define IDS_LOG_SRCNAME 205
-#define IDS_DEF_LOGFILE 301
-#define IDS_DEF_MAXSIZE 302
-#define IDS_DEF_SHRINKTOSIZE 303
-#define IDS_DEF_LOGENABLED 304
-#define IDS_MUTEX_TIMEOUT 401
-
-// Next default values for new objects
-//
-#ifdef APSTUDIO_INVOKED
-#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE 201
-#define _APS_NEXT_COMMAND_VALUE 32768
-#define _APS_NEXT_CONTROL_VALUE 201
-#define _APS_NEXT_SYMED_VALUE 101
-#endif
-#endif
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by kcreddb.rc
+//
+#define IDS_PROJNAME 100
+#define IDR_WMDMLOGGER 101
+#define IDS_LOG_SEV_INFO 201
+#define IDS_LOG_SEV_WARN 202
+#define IDS_LOG_SEV_ERROR 203
+#define IDS_LOG_DATETIME 204
+#define IDS_LOG_SRCNAME 205
+#define IDS_DEF_LOGFILE 301
+#define IDS_DEF_MAXSIZE 302
+#define IDS_DEF_SHRINKTOSIZE 303
+#define IDS_DEF_LOGENABLED 304
+#define IDS_MUTEX_TIMEOUT 401
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 201
+#define _APS_NEXT_COMMAND_VALUE 32768
+#define _APS_NEXT_CONTROL_VALUE 201
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/src/windows/identity/kcreddb/type.c b/src/windows/identity/kcreddb/type.c
index 48630b5fd5..e4fd2df2c4 100644
--- a/src/windows/identity/kcreddb/type.c
+++ b/src/windows/identity/kcreddb/type.c
@@ -1,1386 +1,1386 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<kcreddbinternal.h>
-#include<limits.h>
-
-CRITICAL_SECTION cs_type;
-hashtable * kcdb_type_namemap;
-kcdb_type_i ** kcdb_type_tbl;
-kcdb_type_i * kcdb_types = NULL;
-
-/* Void */
-
-#define GENERIC_VOID_STR L"(Void)"
-
-khm_int32 KHMAPI kcdb_type_void_toString(
- const void * d,
- khm_size cbd,
- wchar_t * buffer,
- khm_size * cb_buf,
- khm_int32 flags)
-{
- size_t cbsize;
-
- if(!cb_buf)
- return KHM_ERROR_INVALID_PARAM;
-
- cbsize = sizeof(GENERIC_VOID_STR);
-
- if(!buffer || *cb_buf < cbsize) {
- *cb_buf = cbsize;
- return KHM_ERROR_TOO_LONG;
- }
-
- StringCbCopy(buffer, *cb_buf, GENERIC_VOID_STR);
-
- *cb_buf = cbsize;
-
- return KHM_ERROR_SUCCESS;
-}
-
-khm_boolean KHMAPI kcdb_type_void_isValid(
- const void * d,
- khm_size cbd)
-{
- /* void is always valid, even if d is NULL */
- return TRUE;
-}
-
-khm_int32 KHMAPI kcdb_type_void_comp(
- const void * d1,
- khm_size cbd1,
- const void * d2,
- khm_size cbd2)
-{
- /* voids can not be compared */
- return 0;
-}
-
-khm_int32 KHMAPI kcdb_type_void_dup(
- const void * d_src,
- khm_size cbd_src,
- void * d_dst,
- khm_size * cbd_dst)
-{
- if(!cbd_dst)
- return KHM_ERROR_INVALID_PARAM;
-
- *cbd_dst = 0;
-
- /* copying a void doesn't do much */
- return KHM_ERROR_SUCCESS;
-}
-
-
-/* String */
-khm_int32 KHMAPI kcdb_type_string_toString(
- const void * d,
- khm_size cbd,
- wchar_t * buffer,
- khm_size * cb_buf,
- khm_int32 flags)
-{
- size_t cbsize;
- wchar_t * sd;
-
- if(!cb_buf)
- return KHM_ERROR_INVALID_PARAM;
-
- sd = (wchar_t *) d;
-
- if(FAILED(StringCbLength(sd, KCDB_TYPE_MAXCB, &cbsize)))
- return KHM_ERROR_INVALID_PARAM;
-
- cbsize += sizeof(wchar_t);
-
- if(!buffer || *cb_buf < cbsize) {
- *cb_buf = cbsize;
- return KHM_ERROR_TOO_LONG;
- }
-
- StringCbCopy(buffer, *cb_buf, sd);
-
- *cb_buf = cbsize;
-
- return KHM_ERROR_SUCCESS;
-}
-
-khm_boolean KHMAPI kcdb_type_string_isValid(
- const void * d,
- khm_size cbd)
-{
- size_t cbsize;
-
- if(cbd == KCDB_CBSIZE_AUTO)
- cbd = KCDB_TYPE_MAXCB;
-
- if(FAILED(StringCbLength((wchar_t *) d, cbd, &cbsize)))
- return FALSE;
- else
- return TRUE;
-}
-
-khm_int32 KHMAPI kcdb_type_string_comp(
- const void * d1,
- khm_size cbd1,
- const void * d2,
- khm_size cbd2)
-{
- return wcscmp((const wchar_t *) d1, (const wchar_t *) d2);
-}
-
-khm_int32 KHMAPI kcdb_type_string_dup(
- const void * d_src,
- khm_size cbd_src,
- void * d_dst,
- khm_size * cbd_dst)
-{
- size_t cbsize;
-
- if(!cbd_dst)
- return KHM_ERROR_INVALID_PARAM;
-
- if(cbd_src == KCDB_CBSIZE_AUTO) {
- cbd_src = KCDB_TYPE_MAXCB;
- }
-
- if(FAILED(StringCbLength((const wchar_t *) d_src, cbd_src, &cbsize))) {
- return KHM_ERROR_UNKNOWN;
- }
-
- cbsize += sizeof(wchar_t);
-
- if(!d_dst || *cbd_dst < cbsize) {
- *cbd_dst = cbsize;
- return KHM_ERROR_TOO_LONG;
- }
-
- StringCbCopy((wchar_t *) d_dst, *cbd_dst, (const wchar_t *) d_src);
- *cbd_dst = cbsize;
-
- return KHM_ERROR_SUCCESS;
-}
-
-/* Date and time */
-
-
-khm_int32 KHMAPI kcdb_type_date_toString(
- const void * d,
- khm_size cbd,
- wchar_t * buffer,
- khm_size * cb_buf,
- khm_int32 flags)
-{
- size_t cbsize;
- size_t cchsize;
- wchar_t * bufend;
- SYSTEMTIME st_now;
- SYSTEMTIME st_d;
- SYSTEMTIME st_dl;
- FILETIME *ft;
- int today = 0;
-
- if(!cb_buf)
- return KHM_ERROR_INVALID_PARAM;
-
- ft = (FILETIME *) d;
-
- GetLocalTime(&st_now);
- FileTimeToSystemTime(ft, &st_d);
- SystemTimeToTzSpecificLocalTime(NULL, &st_d, &st_dl);
- if (st_now.wYear == st_dl.wYear &&
- st_now.wMonth == st_dl.wMonth &&
- st_now.wDay == st_dl.wDay)
- today = 1;
-
- if(today && (flags & KCDB_TS_SHORT)) {
- cbsize = 0;
- } else {
- cbsize = GetDateFormat(
- LOCALE_USER_DEFAULT,
- DATE_SHORTDATE,
- &st_dl,
- NULL,
- NULL,
- 0) * sizeof(wchar_t);
- }
-
- cbsize += GetTimeFormat(
- LOCALE_USER_DEFAULT,
- 0,
- &st_dl,
- NULL,
- NULL,
- 0) * sizeof(wchar_t);
-
- if(!buffer || *cb_buf < cbsize) {
- *cb_buf = cbsize;
- return KHM_ERROR_TOO_LONG;
- }
-
- cchsize = cbsize / sizeof(wchar_t);
-
- if(!today || !(flags & KCDB_TS_SHORT)) {
- size_t cch_buf_len;
-
- GetDateFormat(
- LOCALE_USER_DEFAULT,
- DATE_SHORTDATE,
- &st_dl,
- NULL,
- buffer,
- (int) cchsize);
-
- StringCchCat(buffer, cchsize, L" ");
-
- StringCchLength(buffer, cchsize, &cch_buf_len);
-
- bufend = buffer + cch_buf_len;
- cchsize -= cch_buf_len;
- } else {
- bufend = buffer;
- }
-
- GetTimeFormat(
- LOCALE_USER_DEFAULT,
- 0,
- &st_dl,
- NULL,
- bufend,
- (int) cchsize);
-
- *cb_buf = cbsize;
-
- return KHM_ERROR_SUCCESS;
-}
-
-khm_boolean KHMAPI kcdb_type_date_isValid(
- const void * d,
- khm_size cbd)
-{
- return (d && (cbd == KCDB_CBSIZE_AUTO || cbd == sizeof(FILETIME)));
-}
-
-khm_int32 KHMAPI kcdb_type_date_comp(
- const void * d1,
- khm_size cbd1,
- const void * d2,
- khm_size cbd2)
-{
- return (khm_int32) CompareFileTime((CONST FILETIME *) d1, (CONST FILETIME *) d2);
-}
-
-khm_int32 KHMAPI kcdb_type_date_dup(
- const void * d_src,
- khm_size cbd_src,
- void * d_dst,
- khm_size * cbd_dst)
-{
- if(d_dst && *cbd_dst >= sizeof(FILETIME)) {
- *cbd_dst = sizeof(FILETIME);
- *((FILETIME *) d_dst) = *((FILETIME *) d_src);
- return KHM_ERROR_SUCCESS;
- } else {
- *cbd_dst = sizeof(FILETIME);
- return KHM_ERROR_TOO_LONG;
- }
-}
-
-/* Interval */
-
-/* returns the number of milliseconds that must elapse away from the
- interval specified in pft for the representation of pft to change
- from whatever it is right now */
-KHMEXP long KHMAPI
-FtIntervalMsToRepChange(LPFILETIME pft)
-{
- __int64 ms,s,m,h,d;
- __int64 ift;
- long l;
-
- ift = FtToInt(pft);
- ms = ift / 10000i64;
-
- if(ms < 0 || ift == _I64_MAX)
- return -1;
-
- s = ms / 1000i64;
- m = s / 60;
- h = s / 3600;
- d = s / (3600*24);
-
- if (d > 0) {
- /* rep change at next hour change */
- l = (long) (ms % (3600*1000i64));
- } else if (h > 0) {
- /* rep change at next minute change */
- l = (long) (ms % (60*1000i64));
- } else if (m > 5) {
- /* rep change at next minute change */
- l = (long) (ms % (60*1000i64));
- } else {
- /* rep change at next second change */
- l = (long) (ms % 1000);
- }
-
- return l;
-}
-
-KHMEXP khm_int32 KHMAPI
-FtIntervalToString(LPFILETIME data, wchar_t * buffer, khm_size * cb_buf)
-{
- size_t cbsize;
- __int64 s,m,h,d;
- __int64 ift;
- wchar_t ibuf[256];
- wchar_t fbuf[256];
- wchar_t * t;
-
- if(!cb_buf)
- return KHM_ERROR_INVALID_PARAM;
-
- ift = FtToInt(data);
- s = ift / 10000000i64;
-
- m = s / 60;
- h = s / 3600;
- d = s / (3600*24);
-
- if(ift == _I64_MAX) {
-#ifdef INDICATE_UNKNOWN_EXPIRY_TIMES
- LoadString(hinst_kcreddb, IDS_IVL_UNKNOWN, ibuf, sizeof(ibuf)/sizeof(wchar_t));
-#else
- StringCbCopy(ibuf, sizeof(ibuf), L"");
-#endif
- } else if(s < 0) {
- LoadString(hinst_kcreddb, IDS_IVL_EXPIRED, ibuf, sizeof(ibuf)/sizeof(wchar_t));
- } else if(d > 0) {
- h = (s - (d * 3600 * 24)) / 3600;
- if(d == 1) {
- LoadString(hinst_kcreddb, IDS_IVL_1D, ibuf, ARRAYLENGTH(ibuf));
- } else {
- LoadString(hinst_kcreddb, IDS_IVL_D, fbuf, ARRAYLENGTH(fbuf));
- StringCbPrintf(ibuf, sizeof(ibuf), fbuf, d);
- }
- if(h > 0) {
- StringCbCat(ibuf, sizeof(ibuf), L" ");
- t = ibuf + wcslen(ibuf);
- if(h == 1)
- {
- LoadString(hinst_kcreddb, IDS_IVL_1H, t,
- (int) (ARRAYLENGTH(ibuf) - wcslen(ibuf)));
- } else {
- LoadString(hinst_kcreddb, IDS_IVL_H, fbuf,
- (int) ARRAYLENGTH(fbuf));
- StringCbPrintf(t, sizeof(ibuf) - wcslen(ibuf)*sizeof(wchar_t), fbuf, h);
- }
- }
- } else if(h > 0 || m > 5) {
- m = (s - (h * 3600)) / 60;
- if(h == 1) {
- LoadString(hinst_kcreddb, IDS_IVL_1H, ibuf, ARRAYLENGTH(ibuf));
- } else if (h > 1) {
- LoadString(hinst_kcreddb, IDS_IVL_H, fbuf, ARRAYLENGTH(fbuf));
- StringCbPrintf(ibuf, sizeof(ibuf), fbuf, h);
- } else {
- *ibuf = L'\0';
- }
-
- if(m > 0 || h == 0) {
- if (h >= 1)
- StringCbCat(ibuf, sizeof(ibuf), L" ");
-
- t = ibuf + wcslen(ibuf);
- if(m == 1)
- {
- LoadString(hinst_kcreddb, IDS_IVL_1M, t,
- (int) (ARRAYLENGTH(ibuf) - wcslen(ibuf)));
- } else {
- LoadString(hinst_kcreddb, IDS_IVL_M, fbuf,
- (int) ARRAYLENGTH(fbuf));
- StringCbPrintf(t, sizeof(ibuf) - wcslen(ibuf)*sizeof(wchar_t), fbuf, m);
- }
- }
- } else if(m > 0) {
- s -= m * 60;
- if(m == 1) {
- LoadString(hinst_kcreddb, IDS_IVL_1M, ibuf, ARRAYLENGTH(ibuf));
- } else {
- LoadString(hinst_kcreddb, IDS_IVL_M, fbuf, ARRAYLENGTH(fbuf));
- StringCbPrintf(ibuf, sizeof(ibuf), fbuf, m);
- }
- if(s > 0) {
- StringCbCat(ibuf, sizeof(ibuf), L" ");
- t = ibuf + wcslen(ibuf);
- if(s == 1)
- {
- LoadString(hinst_kcreddb, IDS_IVL_1S, t,
- (int) (ARRAYLENGTH(ibuf) - wcslen(ibuf)));
- } else {
- LoadString(hinst_kcreddb, IDS_IVL_S, fbuf,
- (int) ARRAYLENGTH(fbuf));
- StringCbPrintf(t, sizeof(ibuf) - wcslen(ibuf)*sizeof(wchar_t), fbuf, s);
- }
- }
- } else {
- if(s == 1) {
- LoadString(hinst_kcreddb, IDS_IVL_1S, ibuf, ARRAYLENGTH(ibuf));
- } else {
- LoadString(hinst_kcreddb, IDS_IVL_S, fbuf, sizeof(fbuf)/sizeof(wchar_t));
- StringCbPrintf(ibuf, sizeof(ibuf), fbuf, s);
- }
- }
-
- StringCbLength(ibuf, sizeof(ibuf), &cbsize);
- cbsize += sizeof(wchar_t);
-
- if(!buffer || *cb_buf < cbsize) {
- *cb_buf = cbsize;
- return KHM_ERROR_TOO_LONG;
- }
-
- StringCbCopy(buffer, *cb_buf, ibuf);
- *cb_buf = cbsize;
-
- return KHM_ERROR_SUCCESS;
-}
-
-khm_int32 KHMAPI
-kcdb_type_interval_toString(const void * data,
- khm_size cbd,
- wchar_t * buffer,
- khm_size * cb_buf,
- khm_int32 flags)
-{
- return FtIntervalToString((LPFILETIME) data, buffer, cb_buf);
-}
-
-khm_boolean KHMAPI kcdb_type_interval_isValid(
- const void * d,
- khm_size cbd)
-{
- return (d && (cbd == sizeof(FILETIME) || cbd == KCDB_CBSIZE_AUTO));
-}
-
-khm_int32 KHMAPI kcdb_type_interval_comp(
- const void * d1,
- khm_size cbd1,
- const void * d2,
- khm_size cbd2)
-{
- __int64 i1, i2;
-
- i1 = FtToInt((FILETIME *) d1);
- i2 = FtToInt((FILETIME *) d2);
-
- if(i1 < i2)
- return -1;
- else if(i1 > i2)
- return 1;
- else
- return 0;
-}
-
-khm_int32 KHMAPI kcdb_type_interval_dup(
- const void * d_src,
- khm_size cbd_src,
- void * d_dst,
- khm_size * cbd_dst)
-{
- if(d_dst && *cbd_dst >= sizeof(FILETIME)) {
- *cbd_dst = sizeof(FILETIME);
- *((FILETIME *) d_dst) = *((FILETIME *) d_src);
- return KHM_ERROR_SUCCESS;
- } else {
- *cbd_dst = sizeof(FILETIME);
- return KHM_ERROR_TOO_LONG;
- }
-}
-
-/* Int32 */
-
-khm_int32 KHMAPI kcdb_type_int32_toString(
- const void * d,
- khm_size cbd,
- wchar_t * buffer,
- khm_size * cb_buf,
- khm_int32 flags)
-{
- size_t cbsize;
- wchar_t ibuf[12];
-
- if(!cb_buf)
- return KHM_ERROR_INVALID_PARAM;
-
- StringCbPrintf(ibuf, sizeof(ibuf), L"%d", *((khm_int32 *) d));
- StringCbLength(ibuf, sizeof(ibuf), &cbsize);
- cbsize += sizeof(wchar_t);
-
- if(!buffer || *cb_buf < cbsize) {
- *cb_buf = cbsize;
- return KHM_ERROR_TOO_LONG;
- }
-
- StringCbCopy((wchar_t *) buffer, *cb_buf, ibuf);
- *cb_buf = cbsize;
-
- return KHM_ERROR_SUCCESS;
-}
-
-khm_boolean KHMAPI kcdb_type_int32_isValid(
- const void * d,
- khm_size cbd)
-{
- return (d && (cbd == KCDB_CBSIZE_AUTO || cbd == sizeof(khm_int32)));
-}
-
-khm_int32 KHMAPI kcdb_type_int32_comp(
- const void * d1,
- khm_size cbd1,
- const void * d2,
- khm_size cbd2)
-{
- return *((khm_int32 *) d1) - *((khm_int32 *) d2);
-}
-
-khm_int32 KHMAPI kcdb_type_int32_dup(
- const void * d_src,
- khm_size cbd_src,
- void * d_dst,
- khm_size * cbd_dst)
-{
- if(d_dst && (*cbd_dst >= sizeof(khm_int32))) {
- *cbd_dst = sizeof(khm_int32);
- *((khm_int32 *) d_dst) = *((khm_int32 *) d_src);
- return KHM_ERROR_SUCCESS;
- } else {
- *cbd_dst = sizeof(khm_int32);
- return KHM_ERROR_TOO_LONG;
- }
-}
-
-/* Int64 */
-
-khm_int32 KHMAPI kcdb_type_int64_toString(
- const void * d,
- khm_size cbd,
- wchar_t * buffer,
- khm_size * cb_buf,
- khm_int32 flags)
-{
- size_t cbsize;
- wchar_t ibuf[22];
-
- if(!cb_buf)
- return KHM_ERROR_INVALID_PARAM;
-
- StringCbPrintf(ibuf, sizeof(ibuf), L"%I64d", *((__int64 *) d));
- StringCbLength(ibuf, sizeof(ibuf), &cbsize);
- cbsize += sizeof(wchar_t);
-
- if(!buffer || *cb_buf < cbsize) {
- *cb_buf = cbsize;
- return KHM_ERROR_TOO_LONG;
- }
-
- StringCbCopy((wchar_t *) buffer, *cb_buf, ibuf);
- *cb_buf = cbsize;
-
- return KHM_ERROR_SUCCESS;
-}
-
-khm_boolean KHMAPI kcdb_type_int64_isValid(
- const void * d,
- khm_size cbd)
-{
- return (d && (cbd == KCDB_CBSIZE_AUTO || cbd == sizeof(__int64)));
-}
-
-khm_int32 KHMAPI kcdb_type_int64_comp(
- const void * d1,
- khm_size cbd1,
- const void * d2,
- khm_size cbd2)
-{
- __int64 r = *((__int64 *) d1) - *((__int64 *) d2);
- return (r==0i64)?0:((r>0i64)?1:-1);
-}
-
-khm_int32 KHMAPI kcdb_type_int64_dup(
- const void * d_src,
- khm_size cbd_src,
- void * d_dst,
- khm_size * cbd_dst)
-{
- if(d_dst && (*cbd_dst >= sizeof(__int64))) {
- *cbd_dst = sizeof(__int64);
- *((__int64 *) d_dst) = *((__int64 *) d_src);
- return KHM_ERROR_SUCCESS;
- } else {
- *cbd_dst = sizeof(__int64);
- return KHM_ERROR_TOO_LONG;
- }
-}
-
-/* Data */
-#define GENERIC_DATA_STR L"(Data)"
-
-khm_int32 KHMAPI kcdb_type_data_toString(
- const void * d,
- khm_size cbd,
- wchar_t * buffer,
- khm_size * cb_buf,
- khm_int32 flags)
-{
- size_t cbsize;
-
- if(!cb_buf)
- return KHM_ERROR_INVALID_PARAM;
-
- cbsize = sizeof(GENERIC_DATA_STR);
-
- if(!buffer || *cb_buf < cbsize) {
- *cb_buf = cbsize;
- return KHM_ERROR_TOO_LONG;
- }
-
- StringCbCopy(buffer, *cb_buf, GENERIC_DATA_STR);
-
- *cb_buf = cbsize;
-
- return KHM_ERROR_SUCCESS;
-}
-
-khm_boolean KHMAPI kcdb_type_data_isValid(
- const void * d,
- khm_size cbd)
-{
- /* data is always valid */
- if (cbd != 0 && d == NULL)
- return FALSE;
- else
- return TRUE;
-}
-
-khm_int32 KHMAPI kcdb_type_data_comp(
- const void * d1,
- khm_size cbd1,
- const void * d2,
- khm_size cbd2)
-{
- khm_size pref;
- khm_int32 rv = 0;
-
- pref = min(cbd1, cbd2);
-
- if (pref == 0)
- return (cbd1 < cbd2)? -1 : ((cbd1 > cbd2)? 1 : 0);
-
- rv = memcmp(d1, d2, pref);
-
- if (rv == 0) {
- return (cbd1 < cbd2)? -1 : ((cbd1 > cbd2)? 1 : 0);
- } else {
- return rv;
- }
-}
-
-khm_int32 KHMAPI kcdb_type_data_dup(
- const void * d_src,
- khm_size cbd_src,
- void * d_dst,
- khm_size * cbd_dst)
-{
- if(!cbd_dst || cbd_src == KCDB_CBSIZE_AUTO)
- return KHM_ERROR_INVALID_PARAM;
-
- if(!d_dst || *cbd_dst < cbd_src) {
- *cbd_dst = cbd_src;
- return KHM_ERROR_TOO_LONG;
- } else {
- *cbd_dst = cbd_src;
- memcpy(d_dst, d_src, cbd_src);
- return KHM_ERROR_SUCCESS;
- }
-}
-
-
-void kcdb_type_msg_completion(kmq_message * m)
-{
- kcdb_type_release((kcdb_type_i *) m->vparam);
-}
-
-void kcdb_type_post_message(khm_int32 op, kcdb_type_i * t)
-{
- kcdb_type_hold(t);
- kmq_post_message(KMSG_KCDB, KMSG_KCDB_TYPE, op, (void *) t);
-}
-
-void kcdb_type_init(void)
-{
- kcdb_type type;
-
- InitializeCriticalSection(&cs_type);
- kcdb_type_namemap = hash_new_hashtable(
- KCDB_TYPE_HASH_SIZE,
- hash_string,
- hash_string_comp,
- kcdb_type_add_ref,
- kcdb_type_del_ref);
- kcdb_type_tbl = PMALLOC(sizeof(kcdb_type_i *) * (KCDB_TYPE_MAX_ID + 1));
- ZeroMemory(kcdb_type_tbl, sizeof(kcdb_type_i *) * (KCDB_TYPE_MAX_ID + 1));
- kcdb_types = NULL;
-
- /*TODO: register standard data types */
-
- ZeroMemory(&type, sizeof(type));
- type.comp = kcdb_type_void_comp;
- type.dup = kcdb_type_void_dup;
- type.isValid = kcdb_type_void_isValid;
- type.toString = kcdb_type_void_toString;
- type.name = KCDB_TYPENAME_VOID;
- type.id = KCDB_TYPE_VOID;
-
- kcdb_type_register(&type, NULL);
-
- ZeroMemory(&type, sizeof(type));
- type.comp = kcdb_type_string_comp;
- type.dup = kcdb_type_string_dup;
- type.isValid = kcdb_type_string_isValid;
- type.toString = kcdb_type_string_toString;
- type.name = KCDB_TYPENAME_STRING;
- type.id = KCDB_TYPE_STRING;
- type.flags = KCDB_TYPE_FLAG_CB_AUTO;
-
- kcdb_type_register(&type, NULL);
-
- ZeroMemory(&type, sizeof(type));
- type.comp = kcdb_type_date_comp;
- type.dup = kcdb_type_date_dup;
- type.isValid = kcdb_type_date_isValid;
- type.toString = kcdb_type_date_toString;
- type.name = KCDB_TYPENAME_DATE;
- type.id = KCDB_TYPE_DATE;
- type.cb_max = sizeof(FILETIME);
- type.cb_min = sizeof(FILETIME);
- type.flags = KCDB_TYPE_FLAG_CB_FIXED;
-
- kcdb_type_register(&type, NULL);
-
- ZeroMemory(&type, sizeof(type));
- type.comp = kcdb_type_interval_comp;
- type.dup = kcdb_type_interval_dup;
- type.isValid = kcdb_type_interval_isValid;
- type.toString = kcdb_type_interval_toString;
- type.name = KCDB_TYPENAME_INTERVAL;
- type.id = KCDB_TYPE_INTERVAL;
- type.cb_max = sizeof(FILETIME);
- type.cb_min = sizeof(FILETIME);
- type.flags = KCDB_TYPE_FLAG_CB_FIXED;
-
- kcdb_type_register(&type, NULL);
-
- ZeroMemory(&type, sizeof(type));
- type.comp = kcdb_type_int32_comp;
- type.dup = kcdb_type_int32_dup;
- type.isValid = kcdb_type_int32_isValid;
- type.toString = kcdb_type_int32_toString;
- type.name = KCDB_TYPENAME_INT32;
- type.id = KCDB_TYPE_INT32;
- type.cb_max = sizeof(khm_int32);
- type.cb_min = sizeof(khm_int32);
- type.flags = KCDB_TYPE_FLAG_CB_FIXED;
-
- kcdb_type_register(&type, NULL);
-
- ZeroMemory(&type, sizeof(type));
- type.comp = kcdb_type_int64_comp;
- type.dup = kcdb_type_int64_dup;
- type.isValid = kcdb_type_int64_isValid;
- type.toString = kcdb_type_int64_toString;
- type.name = KCDB_TYPENAME_INT64;
- type.id = KCDB_TYPE_INT64;
- type.cb_max = sizeof(__int64);
- type.cb_min = sizeof(__int64);
- type.flags = KCDB_TYPE_FLAG_CB_FIXED;
-
- kcdb_type_register(&type, NULL);
-
- ZeroMemory(&type, sizeof(type));
- type.comp = kcdb_type_data_comp;
- type.dup = kcdb_type_data_dup;
- type.isValid = kcdb_type_data_isValid;
- type.toString = kcdb_type_data_toString;
- type.name = KCDB_TYPENAME_DATA;
- type.id = KCDB_TYPE_DATA;
-
- kcdb_type_register(&type, NULL);
-}
-
-void kcdb_type_add_ref(const void *key, void *vt)
-{
- kcdb_type_hold((kcdb_type_i *) vt);
-}
-
-void kcdb_type_del_ref(const void *key, void *vt)
-{
- kcdb_type_release((kcdb_type_i *) vt);
-}
-
-khm_int32 kcdb_type_hold(kcdb_type_i * t)
-{
- if(!t)
- return KHM_ERROR_INVALID_PARAM;
-
- EnterCriticalSection(&cs_type);
- t->refcount++;
- LeaveCriticalSection(&cs_type);
-
- return KHM_ERROR_SUCCESS;
-}
-
-khm_int32 kcdb_type_release(kcdb_type_i * t)
-{
- if(!t)
- return KHM_ERROR_INVALID_PARAM;
-
- EnterCriticalSection(&cs_type);
- t->refcount--;
- kcdb_type_check_and_delete(t->type.id);
- LeaveCriticalSection(&cs_type);
-
- return KHM_ERROR_SUCCESS;
-}
-
-void kcdb_type_exit(void)
-{
- EnterCriticalSection(&cs_type);
- PFREE(kcdb_type_tbl);
- /*TODO: free up the individual types */
- LeaveCriticalSection(&cs_type);
- DeleteCriticalSection(&cs_type);
-}
-
-void kcdb_type_check_and_delete(khm_int32 id)
-{
- kcdb_type_i * t;
-
- if(id < 0 || id > KCDB_TYPE_MAX_ID)
- return;
-
- EnterCriticalSection(&cs_type);
- t = kcdb_type_tbl[id];
- if(t && !t->refcount) {
- kcdb_type_tbl[id] = NULL;
- LDELETE(&kcdb_types, t);
- /* must already be out of the hash-table, otherwise refcount should not
- be zero */
- PFREE(t->type.name);
- PFREE(t);
- }
- LeaveCriticalSection(&cs_type);
-}
-
-KHMEXP khm_int32 KHMAPI kcdb_type_get_id(const wchar_t *name, khm_int32 * id)
-{
- kcdb_type_i * t;
- size_t cbsize;
-
- if(FAILED(StringCbLength(name, KCDB_MAXCB_NAME, &cbsize))) {
- /* also fails of name is NULL */
- return KHM_ERROR_INVALID_PARAM;
- }
-
- EnterCriticalSection(&cs_type);
- t = hash_lookup(kcdb_type_namemap, (void*) name);
- LeaveCriticalSection(&cs_type);
-
- if(!t) {
- *id = KCDB_TYPE_INVALID;
- return KHM_ERROR_NOT_FOUND;
- } else {
- *id = t->type.id;
- return KHM_ERROR_SUCCESS;
- }
-}
-
-KHMEXP khm_int32 KHMAPI kcdb_type_get_info(khm_int32 id, kcdb_type ** info)
-{
- kcdb_type_i * t;
-
- if(id < 0 || id > KCDB_TYPE_MAX_ID)
- return KHM_ERROR_INVALID_PARAM;
-
- EnterCriticalSection(&cs_type);
- t = kcdb_type_tbl[id];
-
- if (t)
- kcdb_type_hold(t);
- LeaveCriticalSection(&cs_type);
-
- if(info)
- *info = (kcdb_type *) t;
- else if (t)
- kcdb_type_release(t);
-
- return (t)? KHM_ERROR_SUCCESS : KHM_ERROR_NOT_FOUND;
-}
-
-KHMEXP khm_int32 KHMAPI kcdb_type_release_info(kcdb_type * info)
-{
- return kcdb_type_release((kcdb_type_i *) info);
-}
-
-KHMEXP khm_int32 KHMAPI kcdb_type_get_name(khm_int32 id, wchar_t * buffer, khm_size * cbbuf)
-{
- size_t cbsize;
- kcdb_type_i * t;
-
- if(id < 0 || id > KCDB_TYPE_MAX_ID || !cbbuf)
- return KHM_ERROR_INVALID_PARAM;
-
- t = kcdb_type_tbl[id];
-
- if(!t)
- return KHM_ERROR_NOT_FOUND;
-
- if(FAILED(StringCbLength(t->type.name, KCDB_MAXCB_NAME, &cbsize)))
- return KHM_ERROR_UNKNOWN;
-
- cbsize += sizeof(wchar_t);
-
- if(!buffer || *cbbuf < cbsize) {
- *cbbuf = cbsize;
- return KHM_ERROR_TOO_LONG;
- }
-
- StringCbCopy(buffer, *cbbuf, t->type.name);
- *cbbuf = cbsize;
-
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP khm_int32 KHMAPI kcdb_type_register(const kcdb_type * type, khm_int32 * new_id)
-{
- kcdb_type_i *t;
- size_t cbsize;
- khm_int32 type_id;
-
- if(!type ||
- !type->comp ||
- !type->dup ||
- !type->isValid ||
- !type->toString ||
- !type->name)
- return KHM_ERROR_INVALID_PARAM;
-
- if((type->flags & KCDB_TYPE_FLAG_CB_MIN) &&
- (type->cb_min < 0 || type->cb_min > KCDB_TYPE_MAXCB))
- {
- return KHM_ERROR_INVALID_PARAM;
- }
-
- if((type->flags & KCDB_TYPE_FLAG_CB_MAX) &&
- (type->cb_max < 0 || type->cb_max > KCDB_TYPE_MAXCB))
- {
- return KHM_ERROR_INVALID_PARAM;
- }
-
- if((type->flags & KCDB_TYPE_FLAG_CB_MIN) &&
- (type->flags & KCDB_TYPE_FLAG_CB_MAX) &&
- (type->cb_max < type->cb_min))
- {
- return KHM_ERROR_INVALID_PARAM;
- }
-
- if(FAILED(StringCbLength(type->name, KCDB_MAXCB_NAME, &cbsize)))
- return KHM_ERROR_TOO_LONG;
-
- cbsize += sizeof(wchar_t);
-
- EnterCriticalSection(&cs_type);
- if(type->id == KCDB_TYPE_INVALID) {
- kcdb_type_get_next_free(&type_id);
- } else if(type->id < 0 || type->id > KCDB_TYPE_MAX_ID) {
- LeaveCriticalSection(&cs_type);
- return KHM_ERROR_INVALID_PARAM;
- } else if(kcdb_type_tbl[type->id]) {
- LeaveCriticalSection(&cs_type);
- return KHM_ERROR_DUPLICATE;
- } else {
- type_id = type->id;
- }
-
- if(type_id == KCDB_TYPE_INVALID) {
- LeaveCriticalSection(&cs_type);
- return KHM_ERROR_NO_RESOURCES;
- }
-
- t = PMALLOC(sizeof(kcdb_type_i));
- ZeroMemory(t, sizeof(kcdb_type_i));
-
- t->type.name = PMALLOC(cbsize);
- StringCbCopy(t->type.name, cbsize, type->name);
-
- t->type.comp = type->comp;
- t->type.dup = type->dup;
- t->type.flags = type->flags;
- t->type.id = type_id;
- t->type.isValid = type->isValid;
- t->type.toString = type->toString;
-
- LINIT(t);
-
- kcdb_type_tbl[type_id] = t;
- LPUSH(&kcdb_types, t);
-
- hash_add(kcdb_type_namemap, (void *) t->type.name, (void *) t);
-
- LeaveCriticalSection(&cs_type);
-
- if(new_id)
- *new_id = type_id;
-
- kcdb_type_post_message(KCDB_OP_INSERT, t);
-
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP khm_int32 KHMAPI kcdb_type_unregister(khm_int32 id)
-{
- kcdb_type_i * t;
-
- if(id < 0 || id > KCDB_TYPE_MAX_ID)
- return KHM_ERROR_INVALID_PARAM;
-
- EnterCriticalSection(&cs_type);
- t = kcdb_type_tbl[id];
- if(t) {
- kcdb_type_post_message(KCDB_OP_DELETE, t);
- /* we are going to remove t from the hash table. If no one is holding
- a reference to it, then we can free it (actually, the del_ref code
- will take care of that anyway). If there is a hold, then it will
- get freed when they release it.
-
- Actually, the post_message call above pretty much guarantees that
- the type has a hold on it.*/
- t->type.flags |= KCDB_TYPE_FLAG_DELETED;
- hash_del(kcdb_type_namemap, t->type.name);
- }
- LeaveCriticalSection(&cs_type);
-
- if(t)
- return KHM_ERROR_SUCCESS;
- else
- return KHM_ERROR_NOT_FOUND;
-}
-
-KHMEXP khm_int32 KHMAPI kcdb_type_get_next_free(khm_int32 * id)
-{
- int i;
-
- if(!id)
- return KHM_ERROR_INVALID_PARAM;
-
- /* do a linear search because this function only gets called a few times */
- EnterCriticalSection(&cs_type);
- for(i=0; i <= KCDB_TYPE_MAX_ID; i++) {
- if(!kcdb_type_tbl[i])
- break;
- }
- LeaveCriticalSection(&cs_type);
-
- if(i <= KCDB_TYPE_MAX_ID) {
- *id = i;
- return KHM_ERROR_SUCCESS;
- } else {
- *id = KCDB_TYPE_INVALID;
- return KHM_ERROR_NO_RESOURCES;
- }
-}
-
-/* Conversion functions */
-
-KHMEXP void KHMAPI TimetToFileTime( time_t t, LPFILETIME pft )
-{
- LONGLONG ll;
-
- if ( sizeof(time_t) == 4 )
- ll = Int32x32To64(t, 10000000) + 116444736000000000i64;
- else {
- ll = t * 10000000i64 + 116444736000000000i64;
- }
- pft->dwLowDateTime = (DWORD) ll;
- pft->dwHighDateTime = (DWORD) (ll >> 32);
-}
-
-KHMEXP void KHMAPI TimetToFileTimeInterval(time_t t, LPFILETIME pft)
-{
- LONGLONG ll;
-
- if ( sizeof(time_t) == 4 )
- ll = Int32x32To64(t, 10000000);
- else {
- ll = t * 10000000i64;
- }
- pft->dwLowDateTime = (DWORD) ll;
- pft->dwHighDateTime = (DWORD) (ll >> 32);
-}
-
-KHMEXP long KHMAPI FtIntervalToSeconds(LPFILETIME pft)
-{
- __int64 i = FtToInt(pft);
- return (long) (i / 10000000i64);
-}
-
-KHMEXP long KHMAPI FtIntervalToMilliseconds(LPFILETIME pft)
-{
- __int64 i = FtToInt(pft);
- return (long) (i / 10000i64);
-}
-
-KHMEXP khm_int64 KHMAPI FtToInt(LPFILETIME pft) {
- LARGE_INTEGER ll;
- ll.LowPart = pft->dwLowDateTime;
- ll.HighPart = pft->dwHighDateTime;
- return ll.QuadPart;
-}
-
-KHMEXP FILETIME KHMAPI IntToFt(khm_int64 i) {
- LARGE_INTEGER ll;
- FILETIME ft;
-
- ll.QuadPart = i;
- ft.dwLowDateTime = ll.LowPart;
- ft.dwHighDateTime = ll.HighPart;
-
- return ft;
-}
-
-KHMEXP FILETIME KHMAPI FtSub(LPFILETIME ft1, LPFILETIME ft2) {
- FILETIME d;
- LARGE_INTEGER l1, l2;
-
- l1.LowPart = ft1->dwLowDateTime;
- l1.HighPart = ft1->dwHighDateTime;
- l2.LowPart = ft2->dwLowDateTime;
- l2.HighPart = ft2->dwHighDateTime;
-
- l1.QuadPart -= l2.QuadPart;
-
- d.dwLowDateTime = l1.LowPart;
- d.dwHighDateTime = l1.HighPart;
-
- return d;
-}
-
-KHMEXP FILETIME KHMAPI FtAdd(LPFILETIME ft1, LPFILETIME ft2) {
- FILETIME d;
- LARGE_INTEGER l1, l2;
-
- l1.LowPart = ft1->dwLowDateTime;
- l1.HighPart = ft1->dwHighDateTime;
- l2.LowPart = ft2->dwLowDateTime;
- l2.HighPart = ft2->dwHighDateTime;
-
- l1.QuadPart += l2.QuadPart;
-
- d.dwLowDateTime = l1.LowPart;
- d.dwHighDateTime = l1.HighPart;
-
- return d;
-}
-
-KHMEXP int KHMAPI AnsiStrToUnicode( wchar_t * wstr, size_t cbwstr, const char * astr)
-{
- size_t nc;
-
- if(cbwstr == 0)
- return 0;
-
- nc = strlen(astr);
- if(nc == MultiByteToWideChar(
- CP_ACP,
- 0,
- astr,
- (int) nc,
- wstr,
- (int)(cbwstr / sizeof(wchar_t) - 1))) {
- wstr[nc] = L'\0';
- } else {
- wstr[0] = L'\0';
- nc = 0;
- }
-
- return (int) nc;
-}
-
-KHMEXP int KHMAPI UnicodeStrToAnsi( char * dest, size_t cbdest, const wchar_t * src)
-{
- size_t nc;
-
- if(cbdest == 0)
- return 0;
-
- dest[0] = 0;
-
- if(FAILED(StringCchLength(src, cbdest, &nc)) || nc*sizeof(char) >= cbdest)
- // note that cbdest counts the terminating NULL, while nc doesn't
- return 0;
-
- nc = WideCharToMultiByte(
- CP_ACP,
- WC_NO_BEST_FIT_CHARS,
- src,
- (int) nc,
- dest,
- (int) cbdest,
- NULL,
- NULL);
-
- dest[nc] = 0;
-
- return (int) nc;
-}
-
-#define MAX_IVL_SPECLIST_LEN 256
-#define MAX_IVL_UNITS 5
-
-enum _ivl_indices {
- IVL_SECONDS = 0,
- IVL_MINUTES,
- IVL_HOURS,
- IVL_DAYS,
- IVL_WEEKS
-};
-
-typedef struct ivspec_t {
- wchar_t str[MAX_IVL_SPECLIST_LEN];
- __int64 mul;
-} ivspec;
-
-static ivspec ivspecs[MAX_IVL_UNITS];
-static BOOL ivspecs_loaded = FALSE;
-
-int _iv_is_in_spec(wchar_t *s, int n, wchar_t * spec)
-{
- /* spec strigns are comma separated */
- wchar_t *b, *e;
-
- b = spec;
- while(*b) {
- e = wcschr(b, L',');
- if(!e)
- e = b + wcslen(b);
-
- if((e - b) == n && !_wcsnicmp(b, s, n)) {
- return TRUE;
- }
-
- if(*e)
- b = e+1;
- else
- break;
- }
-
- return FALSE;
-}
-
-KHMEXP khm_int32 KHMAPI IntervalStringToFt(FILETIME * pft, wchar_t * str)
-{
- size_t cb;
- wchar_t * b;
- __int64 t;
-
- *pft = IntToFt(0);
-
- /* ideally we should synchronize this, but it doesn't hurt if two
- threads do this at the same time, because we only set the ivspecs_loaded
- flag when we are done */
- if(!ivspecs_loaded) {
- LoadString(hinst_kcreddb, IDS_IVL_S_SPEC, ivspecs[IVL_SECONDS].str, MAX_IVL_SPECLIST_LEN);
- ivspecs[IVL_SECONDS].mul = 10000000i64;
- LoadString(hinst_kcreddb, IDS_IVL_M_SPEC, ivspecs[IVL_MINUTES].str, MAX_IVL_SPECLIST_LEN);
- ivspecs[IVL_MINUTES].mul = ivspecs[IVL_SECONDS].mul * 60;
- LoadString(hinst_kcreddb, IDS_IVL_H_SPEC, ivspecs[2].str, MAX_IVL_SPECLIST_LEN);
- ivspecs[IVL_HOURS].mul = ivspecs[IVL_MINUTES].mul * 60;
- LoadString(hinst_kcreddb, IDS_IVL_D_SPEC, ivspecs[3].str, MAX_IVL_SPECLIST_LEN);
- ivspecs[IVL_DAYS].mul = ivspecs[IVL_HOURS].mul * 24;
- LoadString(hinst_kcreddb, IDS_IVL_W_SPEC, ivspecs[4].str, MAX_IVL_SPECLIST_LEN);
- ivspecs[IVL_WEEKS].mul = ivspecs[IVL_DAYS].mul * 7;
-
- ivspecs_loaded = TRUE;
- }
-
- if(!str || FAILED(StringCbLength(str, MAX_IVL_SPECLIST_LEN, &cb)))
- return KHM_ERROR_INVALID_PARAM;
-
- b = str;
- t = 0;
- while(*b) {
- __int64 f = 1;
- wchar_t *e;
- int i;
-
- while(*b && iswspace(*b))
- b++;
-
- if(*b && iswdigit(*b)) {
- f = _wtoi64(b);
-
- while(*b && iswdigit(*b))
- b++;
- }
-
- while(*b && iswspace(*b))
- b++;
-
- if(!*b) /* no unit specified */
- return KHM_ERROR_INVALID_PARAM;
-
- e = b;
-
- while(*e && !iswspace(*e))
- e++;
-
- for(i=0; i < MAX_IVL_UNITS; i++) {
- if(_iv_is_in_spec(b, (int)(e-b), ivspecs[i].str))
- break;
- }
-
- if(i==MAX_IVL_UNITS)
- return KHM_ERROR_INVALID_PARAM;
-
- t += f * ivspecs[i].mul;
-
- b = e;
- }
-
- *pft = IntToFt(t);
-
- return KHM_ERROR_SUCCESS;
-}
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<kcreddbinternal.h>
+#include<limits.h>
+
+CRITICAL_SECTION cs_type;
+hashtable * kcdb_type_namemap;
+kcdb_type_i ** kcdb_type_tbl;
+kcdb_type_i * kcdb_types = NULL;
+
+/* Void */
+
+#define GENERIC_VOID_STR L"(Void)"
+
+khm_int32 KHMAPI kcdb_type_void_toString(
+ const void * d,
+ khm_size cbd,
+ wchar_t * buffer,
+ khm_size * cb_buf,
+ khm_int32 flags)
+{
+ size_t cbsize;
+
+ if(!cb_buf)
+ return KHM_ERROR_INVALID_PARAM;
+
+ cbsize = sizeof(GENERIC_VOID_STR);
+
+ if(!buffer || *cb_buf < cbsize) {
+ *cb_buf = cbsize;
+ return KHM_ERROR_TOO_LONG;
+ }
+
+ StringCbCopy(buffer, *cb_buf, GENERIC_VOID_STR);
+
+ *cb_buf = cbsize;
+
+ return KHM_ERROR_SUCCESS;
+}
+
+khm_boolean KHMAPI kcdb_type_void_isValid(
+ const void * d,
+ khm_size cbd)
+{
+ /* void is always valid, even if d is NULL */
+ return TRUE;
+}
+
+khm_int32 KHMAPI kcdb_type_void_comp(
+ const void * d1,
+ khm_size cbd1,
+ const void * d2,
+ khm_size cbd2)
+{
+ /* voids can not be compared */
+ return 0;
+}
+
+khm_int32 KHMAPI kcdb_type_void_dup(
+ const void * d_src,
+ khm_size cbd_src,
+ void * d_dst,
+ khm_size * cbd_dst)
+{
+ if(!cbd_dst)
+ return KHM_ERROR_INVALID_PARAM;
+
+ *cbd_dst = 0;
+
+ /* copying a void doesn't do much */
+ return KHM_ERROR_SUCCESS;
+}
+
+
+/* String */
+khm_int32 KHMAPI kcdb_type_string_toString(
+ const void * d,
+ khm_size cbd,
+ wchar_t * buffer,
+ khm_size * cb_buf,
+ khm_int32 flags)
+{
+ size_t cbsize;
+ wchar_t * sd;
+
+ if(!cb_buf)
+ return KHM_ERROR_INVALID_PARAM;
+
+ sd = (wchar_t *) d;
+
+ if(FAILED(StringCbLength(sd, KCDB_TYPE_MAXCB, &cbsize)))
+ return KHM_ERROR_INVALID_PARAM;
+
+ cbsize += sizeof(wchar_t);
+
+ if(!buffer || *cb_buf < cbsize) {
+ *cb_buf = cbsize;
+ return KHM_ERROR_TOO_LONG;
+ }
+
+ StringCbCopy(buffer, *cb_buf, sd);
+
+ *cb_buf = cbsize;
+
+ return KHM_ERROR_SUCCESS;
+}
+
+khm_boolean KHMAPI kcdb_type_string_isValid(
+ const void * d,
+ khm_size cbd)
+{
+ size_t cbsize;
+
+ if(cbd == KCDB_CBSIZE_AUTO)
+ cbd = KCDB_TYPE_MAXCB;
+
+ if(FAILED(StringCbLength((wchar_t *) d, cbd, &cbsize)))
+ return FALSE;
+ else
+ return TRUE;
+}
+
+khm_int32 KHMAPI kcdb_type_string_comp(
+ const void * d1,
+ khm_size cbd1,
+ const void * d2,
+ khm_size cbd2)
+{
+ return wcscmp((const wchar_t *) d1, (const wchar_t *) d2);
+}
+
+khm_int32 KHMAPI kcdb_type_string_dup(
+ const void * d_src,
+ khm_size cbd_src,
+ void * d_dst,
+ khm_size * cbd_dst)
+{
+ size_t cbsize;
+
+ if(!cbd_dst)
+ return KHM_ERROR_INVALID_PARAM;
+
+ if(cbd_src == KCDB_CBSIZE_AUTO) {
+ cbd_src = KCDB_TYPE_MAXCB;
+ }
+
+ if(FAILED(StringCbLength((const wchar_t *) d_src, cbd_src, &cbsize))) {
+ return KHM_ERROR_UNKNOWN;
+ }
+
+ cbsize += sizeof(wchar_t);
+
+ if(!d_dst || *cbd_dst < cbsize) {
+ *cbd_dst = cbsize;
+ return KHM_ERROR_TOO_LONG;
+ }
+
+ StringCbCopy((wchar_t *) d_dst, *cbd_dst, (const wchar_t *) d_src);
+ *cbd_dst = cbsize;
+
+ return KHM_ERROR_SUCCESS;
+}
+
+/* Date and time */
+
+
+khm_int32 KHMAPI kcdb_type_date_toString(
+ const void * d,
+ khm_size cbd,
+ wchar_t * buffer,
+ khm_size * cb_buf,
+ khm_int32 flags)
+{
+ size_t cbsize;
+ size_t cchsize;
+ wchar_t * bufend;
+ SYSTEMTIME st_now;
+ SYSTEMTIME st_d;
+ SYSTEMTIME st_dl;
+ FILETIME *ft;
+ int today = 0;
+
+ if(!cb_buf)
+ return KHM_ERROR_INVALID_PARAM;
+
+ ft = (FILETIME *) d;
+
+ GetLocalTime(&st_now);
+ FileTimeToSystemTime(ft, &st_d);
+ SystemTimeToTzSpecificLocalTime(NULL, &st_d, &st_dl);
+ if (st_now.wYear == st_dl.wYear &&
+ st_now.wMonth == st_dl.wMonth &&
+ st_now.wDay == st_dl.wDay)
+ today = 1;
+
+ if(today && (flags & KCDB_TS_SHORT)) {
+ cbsize = 0;
+ } else {
+ cbsize = GetDateFormat(
+ LOCALE_USER_DEFAULT,
+ DATE_SHORTDATE,
+ &st_dl,
+ NULL,
+ NULL,
+ 0) * sizeof(wchar_t);
+ }
+
+ cbsize += GetTimeFormat(
+ LOCALE_USER_DEFAULT,
+ 0,
+ &st_dl,
+ NULL,
+ NULL,
+ 0) * sizeof(wchar_t);
+
+ if(!buffer || *cb_buf < cbsize) {
+ *cb_buf = cbsize;
+ return KHM_ERROR_TOO_LONG;
+ }
+
+ cchsize = cbsize / sizeof(wchar_t);
+
+ if(!today || !(flags & KCDB_TS_SHORT)) {
+ size_t cch_buf_len;
+
+ GetDateFormat(
+ LOCALE_USER_DEFAULT,
+ DATE_SHORTDATE,
+ &st_dl,
+ NULL,
+ buffer,
+ (int) cchsize);
+
+ StringCchCat(buffer, cchsize, L" ");
+
+ StringCchLength(buffer, cchsize, &cch_buf_len);
+
+ bufend = buffer + cch_buf_len;
+ cchsize -= cch_buf_len;
+ } else {
+ bufend = buffer;
+ }
+
+ GetTimeFormat(
+ LOCALE_USER_DEFAULT,
+ 0,
+ &st_dl,
+ NULL,
+ bufend,
+ (int) cchsize);
+
+ *cb_buf = cbsize;
+
+ return KHM_ERROR_SUCCESS;
+}
+
+khm_boolean KHMAPI kcdb_type_date_isValid(
+ const void * d,
+ khm_size cbd)
+{
+ return (d && (cbd == KCDB_CBSIZE_AUTO || cbd == sizeof(FILETIME)));
+}
+
+khm_int32 KHMAPI kcdb_type_date_comp(
+ const void * d1,
+ khm_size cbd1,
+ const void * d2,
+ khm_size cbd2)
+{
+ return (khm_int32) CompareFileTime((CONST FILETIME *) d1, (CONST FILETIME *) d2);
+}
+
+khm_int32 KHMAPI kcdb_type_date_dup(
+ const void * d_src,
+ khm_size cbd_src,
+ void * d_dst,
+ khm_size * cbd_dst)
+{
+ if(d_dst && *cbd_dst >= sizeof(FILETIME)) {
+ *cbd_dst = sizeof(FILETIME);
+ *((FILETIME *) d_dst) = *((FILETIME *) d_src);
+ return KHM_ERROR_SUCCESS;
+ } else {
+ *cbd_dst = sizeof(FILETIME);
+ return KHM_ERROR_TOO_LONG;
+ }
+}
+
+/* Interval */
+
+/* returns the number of milliseconds that must elapse away from the
+ interval specified in pft for the representation of pft to change
+ from whatever it is right now */
+KHMEXP long KHMAPI
+FtIntervalMsToRepChange(LPFILETIME pft)
+{
+ __int64 ms,s,m,h,d;
+ __int64 ift;
+ long l;
+
+ ift = FtToInt(pft);
+ ms = ift / 10000i64;
+
+ if(ms < 0 || ift == _I64_MAX)
+ return -1;
+
+ s = ms / 1000i64;
+ m = s / 60;
+ h = s / 3600;
+ d = s / (3600*24);
+
+ if (d > 0) {
+ /* rep change at next hour change */
+ l = (long) (ms % (3600*1000i64));
+ } else if (h > 0) {
+ /* rep change at next minute change */
+ l = (long) (ms % (60*1000i64));
+ } else if (m > 5) {
+ /* rep change at next minute change */
+ l = (long) (ms % (60*1000i64));
+ } else {
+ /* rep change at next second change */
+ l = (long) (ms % 1000);
+ }
+
+ return l;
+}
+
+KHMEXP khm_int32 KHMAPI
+FtIntervalToString(LPFILETIME data, wchar_t * buffer, khm_size * cb_buf)
+{
+ size_t cbsize;
+ __int64 s,m,h,d;
+ __int64 ift;
+ wchar_t ibuf[256];
+ wchar_t fbuf[256];
+ wchar_t * t;
+
+ if(!cb_buf)
+ return KHM_ERROR_INVALID_PARAM;
+
+ ift = FtToInt(data);
+ s = ift / 10000000i64;
+
+ m = s / 60;
+ h = s / 3600;
+ d = s / (3600*24);
+
+ if(ift == _I64_MAX) {
+#ifdef INDICATE_UNKNOWN_EXPIRY_TIMES
+ LoadString(hinst_kcreddb, IDS_IVL_UNKNOWN, ibuf, sizeof(ibuf)/sizeof(wchar_t));
+#else
+ StringCbCopy(ibuf, sizeof(ibuf), L"");
+#endif
+ } else if(s < 0) {
+ LoadString(hinst_kcreddb, IDS_IVL_EXPIRED, ibuf, sizeof(ibuf)/sizeof(wchar_t));
+ } else if(d > 0) {
+ h = (s - (d * 3600 * 24)) / 3600;
+ if(d == 1) {
+ LoadString(hinst_kcreddb, IDS_IVL_1D, ibuf, ARRAYLENGTH(ibuf));
+ } else {
+ LoadString(hinst_kcreddb, IDS_IVL_D, fbuf, ARRAYLENGTH(fbuf));
+ StringCbPrintf(ibuf, sizeof(ibuf), fbuf, d);
+ }
+ if(h > 0) {
+ StringCbCat(ibuf, sizeof(ibuf), L" ");
+ t = ibuf + wcslen(ibuf);
+ if(h == 1)
+ {
+ LoadString(hinst_kcreddb, IDS_IVL_1H, t,
+ (int) (ARRAYLENGTH(ibuf) - wcslen(ibuf)));
+ } else {
+ LoadString(hinst_kcreddb, IDS_IVL_H, fbuf,
+ (int) ARRAYLENGTH(fbuf));
+ StringCbPrintf(t, sizeof(ibuf) - wcslen(ibuf)*sizeof(wchar_t), fbuf, h);
+ }
+ }
+ } else if(h > 0 || m > 5) {
+ m = (s - (h * 3600)) / 60;
+ if(h == 1) {
+ LoadString(hinst_kcreddb, IDS_IVL_1H, ibuf, ARRAYLENGTH(ibuf));
+ } else if (h > 1) {
+ LoadString(hinst_kcreddb, IDS_IVL_H, fbuf, ARRAYLENGTH(fbuf));
+ StringCbPrintf(ibuf, sizeof(ibuf), fbuf, h);
+ } else {
+ *ibuf = L'\0';
+ }
+
+ if(m > 0 || h == 0) {
+ if (h >= 1)
+ StringCbCat(ibuf, sizeof(ibuf), L" ");
+
+ t = ibuf + wcslen(ibuf);
+ if(m == 1)
+ {
+ LoadString(hinst_kcreddb, IDS_IVL_1M, t,
+ (int) (ARRAYLENGTH(ibuf) - wcslen(ibuf)));
+ } else {
+ LoadString(hinst_kcreddb, IDS_IVL_M, fbuf,
+ (int) ARRAYLENGTH(fbuf));
+ StringCbPrintf(t, sizeof(ibuf) - wcslen(ibuf)*sizeof(wchar_t), fbuf, m);
+ }
+ }
+ } else if(m > 0) {
+ s -= m * 60;
+ if(m == 1) {
+ LoadString(hinst_kcreddb, IDS_IVL_1M, ibuf, ARRAYLENGTH(ibuf));
+ } else {
+ LoadString(hinst_kcreddb, IDS_IVL_M, fbuf, ARRAYLENGTH(fbuf));
+ StringCbPrintf(ibuf, sizeof(ibuf), fbuf, m);
+ }
+ if(s > 0) {
+ StringCbCat(ibuf, sizeof(ibuf), L" ");
+ t = ibuf + wcslen(ibuf);
+ if(s == 1)
+ {
+ LoadString(hinst_kcreddb, IDS_IVL_1S, t,
+ (int) (ARRAYLENGTH(ibuf) - wcslen(ibuf)));
+ } else {
+ LoadString(hinst_kcreddb, IDS_IVL_S, fbuf,
+ (int) ARRAYLENGTH(fbuf));
+ StringCbPrintf(t, sizeof(ibuf) - wcslen(ibuf)*sizeof(wchar_t), fbuf, s);
+ }
+ }
+ } else {
+ if(s == 1) {
+ LoadString(hinst_kcreddb, IDS_IVL_1S, ibuf, ARRAYLENGTH(ibuf));
+ } else {
+ LoadString(hinst_kcreddb, IDS_IVL_S, fbuf, sizeof(fbuf)/sizeof(wchar_t));
+ StringCbPrintf(ibuf, sizeof(ibuf), fbuf, s);
+ }
+ }
+
+ StringCbLength(ibuf, sizeof(ibuf), &cbsize);
+ cbsize += sizeof(wchar_t);
+
+ if(!buffer || *cb_buf < cbsize) {
+ *cb_buf = cbsize;
+ return KHM_ERROR_TOO_LONG;
+ }
+
+ StringCbCopy(buffer, *cb_buf, ibuf);
+ *cb_buf = cbsize;
+
+ return KHM_ERROR_SUCCESS;
+}
+
+khm_int32 KHMAPI
+kcdb_type_interval_toString(const void * data,
+ khm_size cbd,
+ wchar_t * buffer,
+ khm_size * cb_buf,
+ khm_int32 flags)
+{
+ return FtIntervalToString((LPFILETIME) data, buffer, cb_buf);
+}
+
+khm_boolean KHMAPI kcdb_type_interval_isValid(
+ const void * d,
+ khm_size cbd)
+{
+ return (d && (cbd == sizeof(FILETIME) || cbd == KCDB_CBSIZE_AUTO));
+}
+
+khm_int32 KHMAPI kcdb_type_interval_comp(
+ const void * d1,
+ khm_size cbd1,
+ const void * d2,
+ khm_size cbd2)
+{
+ __int64 i1, i2;
+
+ i1 = FtToInt((FILETIME *) d1);
+ i2 = FtToInt((FILETIME *) d2);
+
+ if(i1 < i2)
+ return -1;
+ else if(i1 > i2)
+ return 1;
+ else
+ return 0;
+}
+
+khm_int32 KHMAPI kcdb_type_interval_dup(
+ const void * d_src,
+ khm_size cbd_src,
+ void * d_dst,
+ khm_size * cbd_dst)
+{
+ if(d_dst && *cbd_dst >= sizeof(FILETIME)) {
+ *cbd_dst = sizeof(FILETIME);
+ *((FILETIME *) d_dst) = *((FILETIME *) d_src);
+ return KHM_ERROR_SUCCESS;
+ } else {
+ *cbd_dst = sizeof(FILETIME);
+ return KHM_ERROR_TOO_LONG;
+ }
+}
+
+/* Int32 */
+
+khm_int32 KHMAPI kcdb_type_int32_toString(
+ const void * d,
+ khm_size cbd,
+ wchar_t * buffer,
+ khm_size * cb_buf,
+ khm_int32 flags)
+{
+ size_t cbsize;
+ wchar_t ibuf[12];
+
+ if(!cb_buf)
+ return KHM_ERROR_INVALID_PARAM;
+
+ StringCbPrintf(ibuf, sizeof(ibuf), L"%d", *((khm_int32 *) d));
+ StringCbLength(ibuf, sizeof(ibuf), &cbsize);
+ cbsize += sizeof(wchar_t);
+
+ if(!buffer || *cb_buf < cbsize) {
+ *cb_buf = cbsize;
+ return KHM_ERROR_TOO_LONG;
+ }
+
+ StringCbCopy((wchar_t *) buffer, *cb_buf, ibuf);
+ *cb_buf = cbsize;
+
+ return KHM_ERROR_SUCCESS;
+}
+
+khm_boolean KHMAPI kcdb_type_int32_isValid(
+ const void * d,
+ khm_size cbd)
+{
+ return (d && (cbd == KCDB_CBSIZE_AUTO || cbd == sizeof(khm_int32)));
+}
+
+khm_int32 KHMAPI kcdb_type_int32_comp(
+ const void * d1,
+ khm_size cbd1,
+ const void * d2,
+ khm_size cbd2)
+{
+ return *((khm_int32 *) d1) - *((khm_int32 *) d2);
+}
+
+khm_int32 KHMAPI kcdb_type_int32_dup(
+ const void * d_src,
+ khm_size cbd_src,
+ void * d_dst,
+ khm_size * cbd_dst)
+{
+ if(d_dst && (*cbd_dst >= sizeof(khm_int32))) {
+ *cbd_dst = sizeof(khm_int32);
+ *((khm_int32 *) d_dst) = *((khm_int32 *) d_src);
+ return KHM_ERROR_SUCCESS;
+ } else {
+ *cbd_dst = sizeof(khm_int32);
+ return KHM_ERROR_TOO_LONG;
+ }
+}
+
+/* Int64 */
+
+khm_int32 KHMAPI kcdb_type_int64_toString(
+ const void * d,
+ khm_size cbd,
+ wchar_t * buffer,
+ khm_size * cb_buf,
+ khm_int32 flags)
+{
+ size_t cbsize;
+ wchar_t ibuf[22];
+
+ if(!cb_buf)
+ return KHM_ERROR_INVALID_PARAM;
+
+ StringCbPrintf(ibuf, sizeof(ibuf), L"%I64d", *((__int64 *) d));
+ StringCbLength(ibuf, sizeof(ibuf), &cbsize);
+ cbsize += sizeof(wchar_t);
+
+ if(!buffer || *cb_buf < cbsize) {
+ *cb_buf = cbsize;
+ return KHM_ERROR_TOO_LONG;
+ }
+
+ StringCbCopy((wchar_t *) buffer, *cb_buf, ibuf);
+ *cb_buf = cbsize;
+
+ return KHM_ERROR_SUCCESS;
+}
+
+khm_boolean KHMAPI kcdb_type_int64_isValid(
+ const void * d,
+ khm_size cbd)
+{
+ return (d && (cbd == KCDB_CBSIZE_AUTO || cbd == sizeof(__int64)));
+}
+
+khm_int32 KHMAPI kcdb_type_int64_comp(
+ const void * d1,
+ khm_size cbd1,
+ const void * d2,
+ khm_size cbd2)
+{
+ __int64 r = *((__int64 *) d1) - *((__int64 *) d2);
+ return (r==0i64)?0:((r>0i64)?1:-1);
+}
+
+khm_int32 KHMAPI kcdb_type_int64_dup(
+ const void * d_src,
+ khm_size cbd_src,
+ void * d_dst,
+ khm_size * cbd_dst)
+{
+ if(d_dst && (*cbd_dst >= sizeof(__int64))) {
+ *cbd_dst = sizeof(__int64);
+ *((__int64 *) d_dst) = *((__int64 *) d_src);
+ return KHM_ERROR_SUCCESS;
+ } else {
+ *cbd_dst = sizeof(__int64);
+ return KHM_ERROR_TOO_LONG;
+ }
+}
+
+/* Data */
+#define GENERIC_DATA_STR L"(Data)"
+
+khm_int32 KHMAPI kcdb_type_data_toString(
+ const void * d,
+ khm_size cbd,
+ wchar_t * buffer,
+ khm_size * cb_buf,
+ khm_int32 flags)
+{
+ size_t cbsize;
+
+ if(!cb_buf)
+ return KHM_ERROR_INVALID_PARAM;
+
+ cbsize = sizeof(GENERIC_DATA_STR);
+
+ if(!buffer || *cb_buf < cbsize) {
+ *cb_buf = cbsize;
+ return KHM_ERROR_TOO_LONG;
+ }
+
+ StringCbCopy(buffer, *cb_buf, GENERIC_DATA_STR);
+
+ *cb_buf = cbsize;
+
+ return KHM_ERROR_SUCCESS;
+}
+
+khm_boolean KHMAPI kcdb_type_data_isValid(
+ const void * d,
+ khm_size cbd)
+{
+ /* data is always valid */
+ if (cbd != 0 && d == NULL)
+ return FALSE;
+ else
+ return TRUE;
+}
+
+khm_int32 KHMAPI kcdb_type_data_comp(
+ const void * d1,
+ khm_size cbd1,
+ const void * d2,
+ khm_size cbd2)
+{
+ khm_size pref;
+ khm_int32 rv = 0;
+
+ pref = min(cbd1, cbd2);
+
+ if (pref == 0)
+ return (cbd1 < cbd2)? -1 : ((cbd1 > cbd2)? 1 : 0);
+
+ rv = memcmp(d1, d2, pref);
+
+ if (rv == 0) {
+ return (cbd1 < cbd2)? -1 : ((cbd1 > cbd2)? 1 : 0);
+ } else {
+ return rv;
+ }
+}
+
+khm_int32 KHMAPI kcdb_type_data_dup(
+ const void * d_src,
+ khm_size cbd_src,
+ void * d_dst,
+ khm_size * cbd_dst)
+{
+ if(!cbd_dst || cbd_src == KCDB_CBSIZE_AUTO)
+ return KHM_ERROR_INVALID_PARAM;
+
+ if(!d_dst || *cbd_dst < cbd_src) {
+ *cbd_dst = cbd_src;
+ return KHM_ERROR_TOO_LONG;
+ } else {
+ *cbd_dst = cbd_src;
+ memcpy(d_dst, d_src, cbd_src);
+ return KHM_ERROR_SUCCESS;
+ }
+}
+
+
+void kcdb_type_msg_completion(kmq_message * m)
+{
+ kcdb_type_release((kcdb_type_i *) m->vparam);
+}
+
+void kcdb_type_post_message(khm_int32 op, kcdb_type_i * t)
+{
+ kcdb_type_hold(t);
+ kmq_post_message(KMSG_KCDB, KMSG_KCDB_TYPE, op, (void *) t);
+}
+
+void kcdb_type_init(void)
+{
+ kcdb_type type;
+
+ InitializeCriticalSection(&cs_type);
+ kcdb_type_namemap = hash_new_hashtable(
+ KCDB_TYPE_HASH_SIZE,
+ hash_string,
+ hash_string_comp,
+ kcdb_type_add_ref,
+ kcdb_type_del_ref);
+ kcdb_type_tbl = PMALLOC(sizeof(kcdb_type_i *) * (KCDB_TYPE_MAX_ID + 1));
+ ZeroMemory(kcdb_type_tbl, sizeof(kcdb_type_i *) * (KCDB_TYPE_MAX_ID + 1));
+ kcdb_types = NULL;
+
+ /*TODO: register standard data types */
+
+ ZeroMemory(&type, sizeof(type));
+ type.comp = kcdb_type_void_comp;
+ type.dup = kcdb_type_void_dup;
+ type.isValid = kcdb_type_void_isValid;
+ type.toString = kcdb_type_void_toString;
+ type.name = KCDB_TYPENAME_VOID;
+ type.id = KCDB_TYPE_VOID;
+
+ kcdb_type_register(&type, NULL);
+
+ ZeroMemory(&type, sizeof(type));
+ type.comp = kcdb_type_string_comp;
+ type.dup = kcdb_type_string_dup;
+ type.isValid = kcdb_type_string_isValid;
+ type.toString = kcdb_type_string_toString;
+ type.name = KCDB_TYPENAME_STRING;
+ type.id = KCDB_TYPE_STRING;
+ type.flags = KCDB_TYPE_FLAG_CB_AUTO;
+
+ kcdb_type_register(&type, NULL);
+
+ ZeroMemory(&type, sizeof(type));
+ type.comp = kcdb_type_date_comp;
+ type.dup = kcdb_type_date_dup;
+ type.isValid = kcdb_type_date_isValid;
+ type.toString = kcdb_type_date_toString;
+ type.name = KCDB_TYPENAME_DATE;
+ type.id = KCDB_TYPE_DATE;
+ type.cb_max = sizeof(FILETIME);
+ type.cb_min = sizeof(FILETIME);
+ type.flags = KCDB_TYPE_FLAG_CB_FIXED;
+
+ kcdb_type_register(&type, NULL);
+
+ ZeroMemory(&type, sizeof(type));
+ type.comp = kcdb_type_interval_comp;
+ type.dup = kcdb_type_interval_dup;
+ type.isValid = kcdb_type_interval_isValid;
+ type.toString = kcdb_type_interval_toString;
+ type.name = KCDB_TYPENAME_INTERVAL;
+ type.id = KCDB_TYPE_INTERVAL;
+ type.cb_max = sizeof(FILETIME);
+ type.cb_min = sizeof(FILETIME);
+ type.flags = KCDB_TYPE_FLAG_CB_FIXED;
+
+ kcdb_type_register(&type, NULL);
+
+ ZeroMemory(&type, sizeof(type));
+ type.comp = kcdb_type_int32_comp;
+ type.dup = kcdb_type_int32_dup;
+ type.isValid = kcdb_type_int32_isValid;
+ type.toString = kcdb_type_int32_toString;
+ type.name = KCDB_TYPENAME_INT32;
+ type.id = KCDB_TYPE_INT32;
+ type.cb_max = sizeof(khm_int32);
+ type.cb_min = sizeof(khm_int32);
+ type.flags = KCDB_TYPE_FLAG_CB_FIXED;
+
+ kcdb_type_register(&type, NULL);
+
+ ZeroMemory(&type, sizeof(type));
+ type.comp = kcdb_type_int64_comp;
+ type.dup = kcdb_type_int64_dup;
+ type.isValid = kcdb_type_int64_isValid;
+ type.toString = kcdb_type_int64_toString;
+ type.name = KCDB_TYPENAME_INT64;
+ type.id = KCDB_TYPE_INT64;
+ type.cb_max = sizeof(__int64);
+ type.cb_min = sizeof(__int64);
+ type.flags = KCDB_TYPE_FLAG_CB_FIXED;
+
+ kcdb_type_register(&type, NULL);
+
+ ZeroMemory(&type, sizeof(type));
+ type.comp = kcdb_type_data_comp;
+ type.dup = kcdb_type_data_dup;
+ type.isValid = kcdb_type_data_isValid;
+ type.toString = kcdb_type_data_toString;
+ type.name = KCDB_TYPENAME_DATA;
+ type.id = KCDB_TYPE_DATA;
+
+ kcdb_type_register(&type, NULL);
+}
+
+void kcdb_type_add_ref(const void *key, void *vt)
+{
+ kcdb_type_hold((kcdb_type_i *) vt);
+}
+
+void kcdb_type_del_ref(const void *key, void *vt)
+{
+ kcdb_type_release((kcdb_type_i *) vt);
+}
+
+khm_int32 kcdb_type_hold(kcdb_type_i * t)
+{
+ if(!t)
+ return KHM_ERROR_INVALID_PARAM;
+
+ EnterCriticalSection(&cs_type);
+ t->refcount++;
+ LeaveCriticalSection(&cs_type);
+
+ return KHM_ERROR_SUCCESS;
+}
+
+khm_int32 kcdb_type_release(kcdb_type_i * t)
+{
+ if(!t)
+ return KHM_ERROR_INVALID_PARAM;
+
+ EnterCriticalSection(&cs_type);
+ t->refcount--;
+ kcdb_type_check_and_delete(t->type.id);
+ LeaveCriticalSection(&cs_type);
+
+ return KHM_ERROR_SUCCESS;
+}
+
+void kcdb_type_exit(void)
+{
+ EnterCriticalSection(&cs_type);
+ PFREE(kcdb_type_tbl);
+ /*TODO: free up the individual types */
+ LeaveCriticalSection(&cs_type);
+ DeleteCriticalSection(&cs_type);
+}
+
+void kcdb_type_check_and_delete(khm_int32 id)
+{
+ kcdb_type_i * t;
+
+ if(id < 0 || id > KCDB_TYPE_MAX_ID)
+ return;
+
+ EnterCriticalSection(&cs_type);
+ t = kcdb_type_tbl[id];
+ if(t && !t->refcount) {
+ kcdb_type_tbl[id] = NULL;
+ LDELETE(&kcdb_types, t);
+ /* must already be out of the hash-table, otherwise refcount should not
+ be zero */
+ PFREE(t->type.name);
+ PFREE(t);
+ }
+ LeaveCriticalSection(&cs_type);
+}
+
+KHMEXP khm_int32 KHMAPI kcdb_type_get_id(const wchar_t *name, khm_int32 * id)
+{
+ kcdb_type_i * t;
+ size_t cbsize;
+
+ if(FAILED(StringCbLength(name, KCDB_MAXCB_NAME, &cbsize))) {
+ /* also fails of name is NULL */
+ return KHM_ERROR_INVALID_PARAM;
+ }
+
+ EnterCriticalSection(&cs_type);
+ t = hash_lookup(kcdb_type_namemap, (void*) name);
+ LeaveCriticalSection(&cs_type);
+
+ if(!t) {
+ *id = KCDB_TYPE_INVALID;
+ return KHM_ERROR_NOT_FOUND;
+ } else {
+ *id = t->type.id;
+ return KHM_ERROR_SUCCESS;
+ }
+}
+
+KHMEXP khm_int32 KHMAPI kcdb_type_get_info(khm_int32 id, kcdb_type ** info)
+{
+ kcdb_type_i * t;
+
+ if(id < 0 || id > KCDB_TYPE_MAX_ID)
+ return KHM_ERROR_INVALID_PARAM;
+
+ EnterCriticalSection(&cs_type);
+ t = kcdb_type_tbl[id];
+
+ if (t)
+ kcdb_type_hold(t);
+ LeaveCriticalSection(&cs_type);
+
+ if(info)
+ *info = (kcdb_type *) t;
+ else if (t)
+ kcdb_type_release(t);
+
+ return (t)? KHM_ERROR_SUCCESS : KHM_ERROR_NOT_FOUND;
+}
+
+KHMEXP khm_int32 KHMAPI kcdb_type_release_info(kcdb_type * info)
+{
+ return kcdb_type_release((kcdb_type_i *) info);
+}
+
+KHMEXP khm_int32 KHMAPI kcdb_type_get_name(khm_int32 id, wchar_t * buffer, khm_size * cbbuf)
+{
+ size_t cbsize;
+ kcdb_type_i * t;
+
+ if(id < 0 || id > KCDB_TYPE_MAX_ID || !cbbuf)
+ return KHM_ERROR_INVALID_PARAM;
+
+ t = kcdb_type_tbl[id];
+
+ if(!t)
+ return KHM_ERROR_NOT_FOUND;
+
+ if(FAILED(StringCbLength(t->type.name, KCDB_MAXCB_NAME, &cbsize)))
+ return KHM_ERROR_UNKNOWN;
+
+ cbsize += sizeof(wchar_t);
+
+ if(!buffer || *cbbuf < cbsize) {
+ *cbbuf = cbsize;
+ return KHM_ERROR_TOO_LONG;
+ }
+
+ StringCbCopy(buffer, *cbbuf, t->type.name);
+ *cbbuf = cbsize;
+
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP khm_int32 KHMAPI kcdb_type_register(const kcdb_type * type, khm_int32 * new_id)
+{
+ kcdb_type_i *t;
+ size_t cbsize;
+ khm_int32 type_id;
+
+ if(!type ||
+ !type->comp ||
+ !type->dup ||
+ !type->isValid ||
+ !type->toString ||
+ !type->name)
+ return KHM_ERROR_INVALID_PARAM;
+
+ if((type->flags & KCDB_TYPE_FLAG_CB_MIN) &&
+ (type->cb_min < 0 || type->cb_min > KCDB_TYPE_MAXCB))
+ {
+ return KHM_ERROR_INVALID_PARAM;
+ }
+
+ if((type->flags & KCDB_TYPE_FLAG_CB_MAX) &&
+ (type->cb_max < 0 || type->cb_max > KCDB_TYPE_MAXCB))
+ {
+ return KHM_ERROR_INVALID_PARAM;
+ }
+
+ if((type->flags & KCDB_TYPE_FLAG_CB_MIN) &&
+ (type->flags & KCDB_TYPE_FLAG_CB_MAX) &&
+ (type->cb_max < type->cb_min))
+ {
+ return KHM_ERROR_INVALID_PARAM;
+ }
+
+ if(FAILED(StringCbLength(type->name, KCDB_MAXCB_NAME, &cbsize)))
+ return KHM_ERROR_TOO_LONG;
+
+ cbsize += sizeof(wchar_t);
+
+ EnterCriticalSection(&cs_type);
+ if(type->id == KCDB_TYPE_INVALID) {
+ kcdb_type_get_next_free(&type_id);
+ } else if(type->id < 0 || type->id > KCDB_TYPE_MAX_ID) {
+ LeaveCriticalSection(&cs_type);
+ return KHM_ERROR_INVALID_PARAM;
+ } else if(kcdb_type_tbl[type->id]) {
+ LeaveCriticalSection(&cs_type);
+ return KHM_ERROR_DUPLICATE;
+ } else {
+ type_id = type->id;
+ }
+
+ if(type_id == KCDB_TYPE_INVALID) {
+ LeaveCriticalSection(&cs_type);
+ return KHM_ERROR_NO_RESOURCES;
+ }
+
+ t = PMALLOC(sizeof(kcdb_type_i));
+ ZeroMemory(t, sizeof(kcdb_type_i));
+
+ t->type.name = PMALLOC(cbsize);
+ StringCbCopy(t->type.name, cbsize, type->name);
+
+ t->type.comp = type->comp;
+ t->type.dup = type->dup;
+ t->type.flags = type->flags;
+ t->type.id = type_id;
+ t->type.isValid = type->isValid;
+ t->type.toString = type->toString;
+
+ LINIT(t);
+
+ kcdb_type_tbl[type_id] = t;
+ LPUSH(&kcdb_types, t);
+
+ hash_add(kcdb_type_namemap, (void *) t->type.name, (void *) t);
+
+ LeaveCriticalSection(&cs_type);
+
+ if(new_id)
+ *new_id = type_id;
+
+ kcdb_type_post_message(KCDB_OP_INSERT, t);
+
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP khm_int32 KHMAPI kcdb_type_unregister(khm_int32 id)
+{
+ kcdb_type_i * t;
+
+ if(id < 0 || id > KCDB_TYPE_MAX_ID)
+ return KHM_ERROR_INVALID_PARAM;
+
+ EnterCriticalSection(&cs_type);
+ t = kcdb_type_tbl[id];
+ if(t) {
+ kcdb_type_post_message(KCDB_OP_DELETE, t);
+ /* we are going to remove t from the hash table. If no one is holding
+ a reference to it, then we can free it (actually, the del_ref code
+ will take care of that anyway). If there is a hold, then it will
+ get freed when they release it.
+
+ Actually, the post_message call above pretty much guarantees that
+ the type has a hold on it.*/
+ t->type.flags |= KCDB_TYPE_FLAG_DELETED;
+ hash_del(kcdb_type_namemap, t->type.name);
+ }
+ LeaveCriticalSection(&cs_type);
+
+ if(t)
+ return KHM_ERROR_SUCCESS;
+ else
+ return KHM_ERROR_NOT_FOUND;
+}
+
+KHMEXP khm_int32 KHMAPI kcdb_type_get_next_free(khm_int32 * id)
+{
+ int i;
+
+ if(!id)
+ return KHM_ERROR_INVALID_PARAM;
+
+ /* do a linear search because this function only gets called a few times */
+ EnterCriticalSection(&cs_type);
+ for(i=0; i <= KCDB_TYPE_MAX_ID; i++) {
+ if(!kcdb_type_tbl[i])
+ break;
+ }
+ LeaveCriticalSection(&cs_type);
+
+ if(i <= KCDB_TYPE_MAX_ID) {
+ *id = i;
+ return KHM_ERROR_SUCCESS;
+ } else {
+ *id = KCDB_TYPE_INVALID;
+ return KHM_ERROR_NO_RESOURCES;
+ }
+}
+
+/* Conversion functions */
+
+KHMEXP void KHMAPI TimetToFileTime( time_t t, LPFILETIME pft )
+{
+ LONGLONG ll;
+
+ if ( sizeof(time_t) == 4 )
+ ll = Int32x32To64(t, 10000000) + 116444736000000000i64;
+ else {
+ ll = t * 10000000i64 + 116444736000000000i64;
+ }
+ pft->dwLowDateTime = (DWORD) ll;
+ pft->dwHighDateTime = (DWORD) (ll >> 32);
+}
+
+KHMEXP void KHMAPI TimetToFileTimeInterval(time_t t, LPFILETIME pft)
+{
+ LONGLONG ll;
+
+ if ( sizeof(time_t) == 4 )
+ ll = Int32x32To64(t, 10000000);
+ else {
+ ll = t * 10000000i64;
+ }
+ pft->dwLowDateTime = (DWORD) ll;
+ pft->dwHighDateTime = (DWORD) (ll >> 32);
+}
+
+KHMEXP long KHMAPI FtIntervalToSeconds(LPFILETIME pft)
+{
+ __int64 i = FtToInt(pft);
+ return (long) (i / 10000000i64);
+}
+
+KHMEXP long KHMAPI FtIntervalToMilliseconds(LPFILETIME pft)
+{
+ __int64 i = FtToInt(pft);
+ return (long) (i / 10000i64);
+}
+
+KHMEXP khm_int64 KHMAPI FtToInt(LPFILETIME pft) {
+ LARGE_INTEGER ll;
+ ll.LowPart = pft->dwLowDateTime;
+ ll.HighPart = pft->dwHighDateTime;
+ return ll.QuadPart;
+}
+
+KHMEXP FILETIME KHMAPI IntToFt(khm_int64 i) {
+ LARGE_INTEGER ll;
+ FILETIME ft;
+
+ ll.QuadPart = i;
+ ft.dwLowDateTime = ll.LowPart;
+ ft.dwHighDateTime = ll.HighPart;
+
+ return ft;
+}
+
+KHMEXP FILETIME KHMAPI FtSub(LPFILETIME ft1, LPFILETIME ft2) {
+ FILETIME d;
+ LARGE_INTEGER l1, l2;
+
+ l1.LowPart = ft1->dwLowDateTime;
+ l1.HighPart = ft1->dwHighDateTime;
+ l2.LowPart = ft2->dwLowDateTime;
+ l2.HighPart = ft2->dwHighDateTime;
+
+ l1.QuadPart -= l2.QuadPart;
+
+ d.dwLowDateTime = l1.LowPart;
+ d.dwHighDateTime = l1.HighPart;
+
+ return d;
+}
+
+KHMEXP FILETIME KHMAPI FtAdd(LPFILETIME ft1, LPFILETIME ft2) {
+ FILETIME d;
+ LARGE_INTEGER l1, l2;
+
+ l1.LowPart = ft1->dwLowDateTime;
+ l1.HighPart = ft1->dwHighDateTime;
+ l2.LowPart = ft2->dwLowDateTime;
+ l2.HighPart = ft2->dwHighDateTime;
+
+ l1.QuadPart += l2.QuadPart;
+
+ d.dwLowDateTime = l1.LowPart;
+ d.dwHighDateTime = l1.HighPart;
+
+ return d;
+}
+
+KHMEXP int KHMAPI AnsiStrToUnicode( wchar_t * wstr, size_t cbwstr, const char * astr)
+{
+ size_t nc;
+
+ if(cbwstr == 0)
+ return 0;
+
+ nc = strlen(astr);
+ if(nc == MultiByteToWideChar(
+ CP_ACP,
+ 0,
+ astr,
+ (int) nc,
+ wstr,
+ (int)(cbwstr / sizeof(wchar_t) - 1))) {
+ wstr[nc] = L'\0';
+ } else {
+ wstr[0] = L'\0';
+ nc = 0;
+ }
+
+ return (int) nc;
+}
+
+KHMEXP int KHMAPI UnicodeStrToAnsi( char * dest, size_t cbdest, const wchar_t * src)
+{
+ size_t nc;
+
+ if(cbdest == 0)
+ return 0;
+
+ dest[0] = 0;
+
+ if(FAILED(StringCchLength(src, cbdest, &nc)) || nc*sizeof(char) >= cbdest)
+ // note that cbdest counts the terminating NULL, while nc doesn't
+ return 0;
+
+ nc = WideCharToMultiByte(
+ CP_ACP,
+ WC_NO_BEST_FIT_CHARS,
+ src,
+ (int) nc,
+ dest,
+ (int) cbdest,
+ NULL,
+ NULL);
+
+ dest[nc] = 0;
+
+ return (int) nc;
+}
+
+#define MAX_IVL_SPECLIST_LEN 256
+#define MAX_IVL_UNITS 5
+
+enum _ivl_indices {
+ IVL_SECONDS = 0,
+ IVL_MINUTES,
+ IVL_HOURS,
+ IVL_DAYS,
+ IVL_WEEKS
+};
+
+typedef struct ivspec_t {
+ wchar_t str[MAX_IVL_SPECLIST_LEN];
+ __int64 mul;
+} ivspec;
+
+static ivspec ivspecs[MAX_IVL_UNITS];
+static BOOL ivspecs_loaded = FALSE;
+
+int _iv_is_in_spec(wchar_t *s, int n, wchar_t * spec)
+{
+ /* spec strigns are comma separated */
+ wchar_t *b, *e;
+
+ b = spec;
+ while(*b) {
+ e = wcschr(b, L',');
+ if(!e)
+ e = b + wcslen(b);
+
+ if((e - b) == n && !_wcsnicmp(b, s, n)) {
+ return TRUE;
+ }
+
+ if(*e)
+ b = e+1;
+ else
+ break;
+ }
+
+ return FALSE;
+}
+
+KHMEXP khm_int32 KHMAPI IntervalStringToFt(FILETIME * pft, wchar_t * str)
+{
+ size_t cb;
+ wchar_t * b;
+ __int64 t;
+
+ *pft = IntToFt(0);
+
+ /* ideally we should synchronize this, but it doesn't hurt if two
+ threads do this at the same time, because we only set the ivspecs_loaded
+ flag when we are done */
+ if(!ivspecs_loaded) {
+ LoadString(hinst_kcreddb, IDS_IVL_S_SPEC, ivspecs[IVL_SECONDS].str, MAX_IVL_SPECLIST_LEN);
+ ivspecs[IVL_SECONDS].mul = 10000000i64;
+ LoadString(hinst_kcreddb, IDS_IVL_M_SPEC, ivspecs[IVL_MINUTES].str, MAX_IVL_SPECLIST_LEN);
+ ivspecs[IVL_MINUTES].mul = ivspecs[IVL_SECONDS].mul * 60;
+ LoadString(hinst_kcreddb, IDS_IVL_H_SPEC, ivspecs[2].str, MAX_IVL_SPECLIST_LEN);
+ ivspecs[IVL_HOURS].mul = ivspecs[IVL_MINUTES].mul * 60;
+ LoadString(hinst_kcreddb, IDS_IVL_D_SPEC, ivspecs[3].str, MAX_IVL_SPECLIST_LEN);
+ ivspecs[IVL_DAYS].mul = ivspecs[IVL_HOURS].mul * 24;
+ LoadString(hinst_kcreddb, IDS_IVL_W_SPEC, ivspecs[4].str, MAX_IVL_SPECLIST_LEN);
+ ivspecs[IVL_WEEKS].mul = ivspecs[IVL_DAYS].mul * 7;
+
+ ivspecs_loaded = TRUE;
+ }
+
+ if(!str || FAILED(StringCbLength(str, MAX_IVL_SPECLIST_LEN, &cb)))
+ return KHM_ERROR_INVALID_PARAM;
+
+ b = str;
+ t = 0;
+ while(*b) {
+ __int64 f = 1;
+ wchar_t *e;
+ int i;
+
+ while(*b && iswspace(*b))
+ b++;
+
+ if(*b && iswdigit(*b)) {
+ f = _wtoi64(b);
+
+ while(*b && iswdigit(*b))
+ b++;
+ }
+
+ while(*b && iswspace(*b))
+ b++;
+
+ if(!*b) /* no unit specified */
+ return KHM_ERROR_INVALID_PARAM;
+
+ e = b;
+
+ while(*e && !iswspace(*e))
+ e++;
+
+ for(i=0; i < MAX_IVL_UNITS; i++) {
+ if(_iv_is_in_spec(b, (int)(e-b), ivspecs[i].str))
+ break;
+ }
+
+ if(i==MAX_IVL_UNITS)
+ return KHM_ERROR_INVALID_PARAM;
+
+ t += f * ivspecs[i].mul;
+
+ b = e;
+ }
+
+ *pft = IntToFt(t);
+
+ return KHM_ERROR_SUCCESS;
+}
diff --git a/src/windows/identity/kcreddb/type.h b/src/windows/identity/kcreddb/type.h
index f7ef26ac44..698e5f3863 100644
--- a/src/windows/identity/kcreddb/type.h
+++ b/src/windows/identity/kcreddb/type.h
@@ -1,216 +1,216 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#ifndef __KHIMAIRA_KCDB_TYPE_H
-#define __KHIMAIRA_KCDB_TYPE_H
-
-/* Types */
-
-typedef struct kcdb_type_i_t {
- kcdb_type type;
-
- khm_int32 refcount;
-
- struct kcdb_type_i_t * next;
- struct kcdb_type_i_t * prev;
-} kcdb_type_i;
-
-#define KCDB_TYPE_HASH_SIZE 31
-
-#define KCDB_TYPE_FLAG_DELETED 8
-
-void kcdb_type_init(void);
-void kcdb_type_exit(void);
-void kcdb_type_add_ref(const void *key, void *vt);
-void kcdb_type_del_ref(const void *key, void *vt);
-void kcdb_type_msg_completion(kmq_message * m);
-khm_int32 kcdb_type_hold(kcdb_type_i * t);
-khm_int32 kcdb_type_release(kcdb_type_i * t);
-void kcdb_type_check_and_delete(khm_int32 id);
-void kcdb_type_post_message(khm_int32 op, kcdb_type_i * t);
-
-khm_int32 KHMAPI kcdb_type_void_toString(
- const void * d,
- khm_size cbd,
- wchar_t * buffer,
- khm_size * cb_buf,
- khm_int32 flags);
-
-khm_boolean KHMAPI kcdb_type_void_isValid(
- const void * d,
- khm_size cbd);
-
-khm_int32 KHMAPI kcdb_type_void_comp(
- const void * d1,
- khm_size cbd1,
- const void * d2,
- khm_size cbd2);
-
-khm_int32 KHMAPI kcdb_type_void_dup(
- const void * d_src,
- khm_size cbd_src,
- void * d_dst,
- khm_size * cbd_dst);
-
-khm_int32 KHMAPI kcdb_type_string_toString(
- const void * d,
- khm_size cbd,
- wchar_t * buffer,
- khm_size * cb_buf,
- khm_int32 flags);
-
-khm_boolean KHMAPI kcdb_type_string_isValid(
- const void * d,
- khm_size cbd);
-
-khm_int32 KHMAPI kcdb_type_string_comp(
- const void * d1,
- khm_size cbd1,
- const void * d2,
- khm_size cbd2);
-
-khm_int32 KHMAPI kcdb_type_string_dup(
- const void * d_src,
- khm_size cbd_src,
- void * d_dst,
- khm_size * cbd_dst);
-
-khm_int32 KHMAPI kcdb_type_date_toString(
- const void * d,
- khm_size cbd,
- wchar_t * buffer,
- khm_size * cb_buf,
- khm_int32 flags);
-
-khm_boolean KHMAPI kcdb_type_date_isValid(
- const void * d,
- khm_size cbd);
-
-khm_int32 KHMAPI kcdb_type_date_comp(
- const void * d1,
- khm_size cbd1,
- const void * d2,
- khm_size cbd2);
-
-khm_int32 KHMAPI kcdb_type_date_dup(
- const void * d_src,
- khm_size cbd_src,
- void * d_dst,
- khm_size * cbd_dst);
-
-khm_int32 KHMAPI kcdb_type_interval_toString(
- const void * d,
- khm_size cbd,
- wchar_t * buffer,
- khm_size * cb_buf,
- khm_int32 flags);
-
-khm_boolean KHMAPI kcdb_type_interval_isValid(
- const void * d,
- khm_size cbd);
-
-khm_int32 KHMAPI kcdb_type_interval_comp(
- const void * d1,
- khm_size cbd1,
- const void * d2,
- khm_size cbd2);
-
-khm_int32 KHMAPI kcdb_type_interval_dup(
- const void * d_src,
- khm_size cbd_src,
- void * d_dst,
- khm_size * cbd_dst);
-
-khm_int32 KHMAPI kcdb_type_int32_toString(
- const void * d,
- khm_size cbd,
- wchar_t * buffer,
- khm_size * cb_buf,
- khm_int32 flags);
-
-khm_boolean KHMAPI kcdb_type_int32_isValid(
- const void * d,
- khm_size cbd);
-
-khm_int32 KHMAPI kcdb_type_int32_comp(
- const void * d1,
- khm_size cbd1,
- const void * d2,
- khm_size cbd2);
-
-khm_int32 KHMAPI kcdb_type_int32_dup(
- const void * d_src,
- khm_size cbd_src,
- void * d_dst,
- khm_size * cbd_dst);
-
-khm_int32 KHMAPI kcdb_type_int64_toString(
- const void * d,
- khm_size cbd,
- wchar_t * buffer,
- khm_size * cb_buf,
- khm_int32 flags);
-
-khm_boolean KHMAPI kcdb_type_int64_isValid(
- const void * d,
- khm_size cbd);
-
-khm_int32 KHMAPI kcdb_type_int64_comp(
- const void * d1,
- khm_size cbd1,
- const void * d2,
- khm_size cbd2);
-
-khm_int32 KHMAPI kcdb_type_int64_dup(
- const void * d_src,
- khm_size cbd_src,
- void * d_dst,
- khm_size * cbd_dst);
-
-khm_int32 KHMAPI kcdb_type_data_toString(
- const void * d,
- khm_size cbd,
- wchar_t * buffer,
- khm_size * cb_buf,
- khm_int32 flags);
-
-khm_boolean KHMAPI kcdb_type_data_isValid(
- const void * d,
- khm_size cbd);
-
-khm_int32 KHMAPI kcdb_type_data_comp(
- const void * d1,
- khm_size cbd1,
- const void * d2,
- khm_size cbd2);
-
-khm_int32 KHMAPI kcdb_type_data_dup(
- const void * d_src,
- khm_size cbd_src,
- void * d_dst,
- khm_size * cbd_dst);
-
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __KHIMAIRA_KCDB_TYPE_H
+#define __KHIMAIRA_KCDB_TYPE_H
+
+/* Types */
+
+typedef struct kcdb_type_i_t {
+ kcdb_type type;
+
+ khm_int32 refcount;
+
+ struct kcdb_type_i_t * next;
+ struct kcdb_type_i_t * prev;
+} kcdb_type_i;
+
+#define KCDB_TYPE_HASH_SIZE 31
+
+#define KCDB_TYPE_FLAG_DELETED 8
+
+void kcdb_type_init(void);
+void kcdb_type_exit(void);
+void kcdb_type_add_ref(const void *key, void *vt);
+void kcdb_type_del_ref(const void *key, void *vt);
+void kcdb_type_msg_completion(kmq_message * m);
+khm_int32 kcdb_type_hold(kcdb_type_i * t);
+khm_int32 kcdb_type_release(kcdb_type_i * t);
+void kcdb_type_check_and_delete(khm_int32 id);
+void kcdb_type_post_message(khm_int32 op, kcdb_type_i * t);
+
+khm_int32 KHMAPI kcdb_type_void_toString(
+ const void * d,
+ khm_size cbd,
+ wchar_t * buffer,
+ khm_size * cb_buf,
+ khm_int32 flags);
+
+khm_boolean KHMAPI kcdb_type_void_isValid(
+ const void * d,
+ khm_size cbd);
+
+khm_int32 KHMAPI kcdb_type_void_comp(
+ const void * d1,
+ khm_size cbd1,
+ const void * d2,
+ khm_size cbd2);
+
+khm_int32 KHMAPI kcdb_type_void_dup(
+ const void * d_src,
+ khm_size cbd_src,
+ void * d_dst,
+ khm_size * cbd_dst);
+
+khm_int32 KHMAPI kcdb_type_string_toString(
+ const void * d,
+ khm_size cbd,
+ wchar_t * buffer,
+ khm_size * cb_buf,
+ khm_int32 flags);
+
+khm_boolean KHMAPI kcdb_type_string_isValid(
+ const void * d,
+ khm_size cbd);
+
+khm_int32 KHMAPI kcdb_type_string_comp(
+ const void * d1,
+ khm_size cbd1,
+ const void * d2,
+ khm_size cbd2);
+
+khm_int32 KHMAPI kcdb_type_string_dup(
+ const void * d_src,
+ khm_size cbd_src,
+ void * d_dst,
+ khm_size * cbd_dst);
+
+khm_int32 KHMAPI kcdb_type_date_toString(
+ const void * d,
+ khm_size cbd,
+ wchar_t * buffer,
+ khm_size * cb_buf,
+ khm_int32 flags);
+
+khm_boolean KHMAPI kcdb_type_date_isValid(
+ const void * d,
+ khm_size cbd);
+
+khm_int32 KHMAPI kcdb_type_date_comp(
+ const void * d1,
+ khm_size cbd1,
+ const void * d2,
+ khm_size cbd2);
+
+khm_int32 KHMAPI kcdb_type_date_dup(
+ const void * d_src,
+ khm_size cbd_src,
+ void * d_dst,
+ khm_size * cbd_dst);
+
+khm_int32 KHMAPI kcdb_type_interval_toString(
+ const void * d,
+ khm_size cbd,
+ wchar_t * buffer,
+ khm_size * cb_buf,
+ khm_int32 flags);
+
+khm_boolean KHMAPI kcdb_type_interval_isValid(
+ const void * d,
+ khm_size cbd);
+
+khm_int32 KHMAPI kcdb_type_interval_comp(
+ const void * d1,
+ khm_size cbd1,
+ const void * d2,
+ khm_size cbd2);
+
+khm_int32 KHMAPI kcdb_type_interval_dup(
+ const void * d_src,
+ khm_size cbd_src,
+ void * d_dst,
+ khm_size * cbd_dst);
+
+khm_int32 KHMAPI kcdb_type_int32_toString(
+ const void * d,
+ khm_size cbd,
+ wchar_t * buffer,
+ khm_size * cb_buf,
+ khm_int32 flags);
+
+khm_boolean KHMAPI kcdb_type_int32_isValid(
+ const void * d,
+ khm_size cbd);
+
+khm_int32 KHMAPI kcdb_type_int32_comp(
+ const void * d1,
+ khm_size cbd1,
+ const void * d2,
+ khm_size cbd2);
+
+khm_int32 KHMAPI kcdb_type_int32_dup(
+ const void * d_src,
+ khm_size cbd_src,
+ void * d_dst,
+ khm_size * cbd_dst);
+
+khm_int32 KHMAPI kcdb_type_int64_toString(
+ const void * d,
+ khm_size cbd,
+ wchar_t * buffer,
+ khm_size * cb_buf,
+ khm_int32 flags);
+
+khm_boolean KHMAPI kcdb_type_int64_isValid(
+ const void * d,
+ khm_size cbd);
+
+khm_int32 KHMAPI kcdb_type_int64_comp(
+ const void * d1,
+ khm_size cbd1,
+ const void * d2,
+ khm_size cbd2);
+
+khm_int32 KHMAPI kcdb_type_int64_dup(
+ const void * d_src,
+ khm_size cbd_src,
+ void * d_dst,
+ khm_size * cbd_dst);
+
+khm_int32 KHMAPI kcdb_type_data_toString(
+ const void * d,
+ khm_size cbd,
+ wchar_t * buffer,
+ khm_size * cb_buf,
+ khm_int32 flags);
+
+khm_boolean KHMAPI kcdb_type_data_isValid(
+ const void * d,
+ khm_size cbd);
+
+khm_int32 KHMAPI kcdb_type_data_comp(
+ const void * d1,
+ khm_size cbd1,
+ const void * d2,
+ khm_size cbd2);
+
+khm_int32 KHMAPI kcdb_type_data_dup(
+ const void * d_src,
+ khm_size cbd_src,
+ void * d_dst,
+ khm_size * cbd_dst);
+
+#endif
diff --git a/src/windows/identity/kherr/kherr.c b/src/windows/identity/kherr/kherr.c
index feecbe06ce..d9fdf2d49b 100644
--- a/src/windows/identity/kherr/kherr.c
+++ b/src/windows/identity/kherr/kherr.c
@@ -1,1321 +1,1321 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<kherrinternal.h>
-#include<assert.h>
-#include<stdarg.h>
-
-CRITICAL_SECTION cs_error;
-DWORD tls_error = 0;
-kherr_context * ctx_free_list = NULL;
-kherr_context * ctx_root_list = NULL;
-kherr_context * ctx_error_list = NULL;
-kherr_event * evt_free_list = NULL;
-
-kherr_handler_node * ctx_handlers = NULL;
-khm_size n_ctx_handlers;
-khm_size nc_ctx_handlers;
-
-kherr_serial ctx_serial = 0;
-
-#ifdef DEBUG
-#define DEBUG_CONTEXT
-
-KHMEXP void kherr_debug_printf(wchar_t * fmt, ...) {
- va_list vl;
- wchar_t buf[1024];
-
- va_start(vl, fmt);
- StringCbVPrintf(buf, sizeof(buf), fmt, vl);
- OutputDebugString(buf);
- va_end(vl);
-}
-#endif
-
-KHMEXP void KHMAPI kherr_add_ctx_handler(kherr_ctx_handler h,
- khm_int32 filter,
- kherr_serial serial) {
-
- khm_size idx;
-
- assert(h);
-
- EnterCriticalSection(&cs_error);
- if( ctx_handlers == NULL) {
- nc_ctx_handlers = CTX_ALLOC_INCR;
- n_ctx_handlers = 0;
- ctx_handlers = PMALLOC(sizeof(*ctx_handlers) * nc_ctx_handlers);
- /* No need to initialize */
- } else if (n_ctx_handlers == nc_ctx_handlers) {
- khm_size new_nc;
- kherr_handler_node * new_ctxs;
-
- new_nc = nc_ctx_handlers + CTX_ALLOC_INCR;
- new_ctxs = PMALLOC(sizeof(*new_ctxs) * new_nc);
- memcpy(new_ctxs, ctx_handlers, n_ctx_handlers * sizeof(*new_ctxs));
-
- PFREE(ctx_handlers);
- ctx_handlers = new_ctxs;
- nc_ctx_handlers = new_nc;
- }
-
- if (filter == 0)
- filter = KHERR_CTX_BEGIN |
- KHERR_CTX_DESCRIBE |
- KHERR_CTX_END |
- KHERR_CTX_ERROR;
-
- /* Since commit events are the most frequent, we put those
- handlers at the top of the list. When dispatching a commit
- event, we stop looking at the list when we find a filter that
- doesn't filter for commit events. */
- if (filter & KHERR_CTX_EVTCOMMIT) {
- idx = 0;
- memmove(&ctx_handlers[1], &ctx_handlers[0],
- n_ctx_handlers * sizeof(ctx_handlers[0]));
- } else {
- idx = n_ctx_handlers;
- }
-
- ctx_handlers[idx].h = h;
- ctx_handlers[idx].filter = filter;
- ctx_handlers[idx].serial = serial;
-
- n_ctx_handlers++;
-
- LeaveCriticalSection(&cs_error);
-}
-
-KHMEXP void KHMAPI kherr_remove_ctx_handler(kherr_ctx_handler h,
- kherr_serial serial) {
- khm_size i;
- EnterCriticalSection(&cs_error);
-
- for (i=0 ; i < n_ctx_handlers; i++) {
- if (ctx_handlers[i].h == h &&
- ctx_handlers[i].serial == serial) {
- break;
- }
- }
-
- if ( i < n_ctx_handlers ) {
- n_ctx_handlers --;
- for (; i < n_ctx_handlers; i++) {
- ctx_handlers[i] = ctx_handlers[i + 1];
- }
- }
-
- LeaveCriticalSection(&cs_error);
-}
-
-/* Called with cs_error held */
-void notify_ctx_event(enum kherr_ctx_event e, kherr_context * c) {
- khm_size i;
-
- kherr_ctx_handler h;
-
- for (i=0; i<n_ctx_handlers; i++) {
- if (ctx_handlers[i].h && (ctx_handlers[i].filter & e) &&
- (ctx_handlers[i].serial == 0 ||
- ctx_handlers[i].serial == c->serial)) {
- if (IsBadCodePtr((FARPROC) ctx_handlers[i].h)) {
- ctx_handlers[i].h = NULL;
- } else {
- h = ctx_handlers[i].h;
- (*h)(e,c);
-
- /* a context handler is allowed to remove itself
- during a callback. It is, however, not allowed to
- remove anything else. */
- if (h != ctx_handlers[i].h)
- i--;
- }
- } else if (e == KHERR_CTX_EVTCOMMIT &&
- !(ctx_handlers[i].filter & KHERR_CTX_EVTCOMMIT)) {
- /* All handlers that filter for commit events are at the
- top of the list. If this handler wasn't filtering for
- it, then there's no point in goint further down the
- list. */
- break;
- }
- }
-}
-
-void attach_this_thread(void) {
- kherr_thread * t;
-
- t = (kherr_thread *) TlsGetValue(tls_error);
- if (t)
- return;
-
- t = PMALLOC(sizeof(kherr_thread) +
- sizeof(kherr_context *) * THREAD_STACK_SIZE);
- t->nc_ctx = THREAD_STACK_SIZE;
- t->n_ctx = 0;
- t->ctx = (kherr_context **) &t[1];
-
- TlsSetValue(tls_error, t);
-}
-
-void detach_this_thread(void) {
- kherr_thread * t;
- khm_size i;
-
- t = (kherr_thread *) TlsGetValue(tls_error);
- if (t) {
- for(i=0; i < t->n_ctx; i++) {
- kherr_release_context(t->ctx[i]);
- }
- PFREE(t);
- TlsSetValue(tls_error, 0);
- }
-}
-
-kherr_context * peek_context(void) {
- kherr_thread * t;
-
- t = (kherr_thread *) TlsGetValue(tls_error);
- if (t) {
- if (t->n_ctx > 0)
- return t->ctx[t->n_ctx - 1];
- else
- return NULL;
- } else
- return NULL;
-}
-
-void push_context(kherr_context * c) {
- kherr_thread * t;
-
- t = (kherr_thread *) TlsGetValue(tls_error);
- if (!t) {
- attach_this_thread();
- t = (kherr_thread *) TlsGetValue(tls_error);
- assert(t);
- }
-
- if (t->n_ctx == t->nc_ctx) {
- khm_size nc_new;
- khm_size cb_new;
- kherr_thread * nt;
-
- nc_new = t->nc_ctx + THREAD_STACK_SIZE;
- cb_new = sizeof(kherr_thread) +
- sizeof(kherr_context *) * nc_new;
-
- nt = PMALLOC(cb_new);
- memcpy(nt, t, sizeof(kherr_thread) +
- sizeof(kherr_context *) * t->n_ctx);
- nt->ctx = (kherr_context **) &nt[1];
- nt->nc_ctx = nc_new;
-
- PFREE(t);
- t = nt;
- TlsSetValue(tls_error, t);
- }
-
- assert(t->n_ctx < t->nc_ctx);
- t->ctx[t->n_ctx++] = c;
-
- kherr_hold_context(c);
-}
-
-/* returned pointer is still held */
-kherr_context * pop_context(void) {
- kherr_thread * t;
- kherr_context * c;
-
- t = (kherr_thread *) TlsGetValue(tls_error);
- if (t) {
- if (t->n_ctx > 0) {
- c = t->ctx[--(t->n_ctx)];
- return c;
- } else
- return NULL;
- } else {
- return NULL;
- }
-}
-
-kherr_event * get_empty_event(void) {
- kherr_event * e;
-
- EnterCriticalSection(&cs_error);
- if(evt_free_list) {
- LPOP(&evt_free_list, &e);
- } else {
- e = PMALLOC(sizeof(*e));
- }
- LeaveCriticalSection(&cs_error);
- ZeroMemory(e, sizeof(*e));
- e->severity = KHERR_NONE;
- e->magic = KHERR_EVENT_MAGIC;
-
- return e;
-}
-
-void free_event_params(kherr_event * e) {
- if(parm_type(e->p1) == KEPT_STRINGT) {
- assert((void *) parm_data(e->p1));
- PFREE((void*) parm_data(e->p1));
- ZeroMemory(&e->p1, sizeof(e->p1));
- }
- if(parm_type(e->p2) == KEPT_STRINGT) {
- assert((void *) parm_data(e->p2));
- PFREE((void*) parm_data(e->p2));
- ZeroMemory(&e->p2, sizeof(e->p2));
- }
- if(parm_type(e->p3) == KEPT_STRINGT) {
- assert((void *) parm_data(e->p3));
- PFREE((void*) parm_data(e->p3));
- ZeroMemory(&e->p3, sizeof(e->p3));
- }
- if(parm_type(e->p4) == KEPT_STRINGT) {
- assert((void *) parm_data(e->p4));
- PFREE((void*) parm_data(e->p4));
- ZeroMemory(&e->p4, sizeof(e->p4));
- }
-}
-
-void free_event(kherr_event * e) {
-
- EnterCriticalSection(&cs_error);
-
- assert(e->magic == KHERR_EVENT_MAGIC);
-
-#ifdef DEBUG_CONTEXT
- kherr_debug_printf(L"Freeing event 0x%x\n", e);
- if (!(e->flags & KHERR_RF_STR_RESOLVED))
- resolve_event_strings(e);
- if (e->short_desc)
- kherr_debug_printf(L" Desc(S):[%s]\n", e->short_desc);
- if (e->long_desc)
- kherr_debug_printf(L" Desc(L):[%s]\n", e->long_desc);
- if (e->suggestion)
- kherr_debug_printf(L" Suggest:[%s]\n", e->suggestion);
- if (e->facility)
- kherr_debug_printf(L" Facility:[%s]\n", e->facility);
-#endif
-
- if(e->flags & KHERR_RF_FREE_SHORT_DESC) {
- assert(e->short_desc);
- PFREE((void *) e->short_desc);
- }
- if(e->flags & KHERR_RF_FREE_LONG_DESC) {
- assert(e->long_desc);
- PFREE((void *) e->long_desc);
- }
- if(e->flags & KHERR_RF_FREE_SUGGEST) {
- assert(e->suggestion);
- PFREE((void *) e->suggestion);
- }
-
- free_event_params(e);
-
- ZeroMemory(e, sizeof(e));
-
- LPUSH(&evt_free_list, e);
- LeaveCriticalSection(&cs_error);
-}
-
-kherr_context * get_empty_context(void) {
- kherr_context * c;
-
- EnterCriticalSection(&cs_error);
- if(ctx_free_list)
- LPOP(&ctx_free_list, &c);
- else {
- c = PMALLOC(sizeof(kherr_context));
- }
-
- ZeroMemory(c,sizeof(*c));
- c->severity = KHERR_NONE;
- c->flags = KHERR_CF_UNBOUND;
- c->magic = KHERR_CONTEXT_MAGIC;
- c->serial = ++ctx_serial;
-
- LPUSH(&ctx_root_list, c);
-
- LeaveCriticalSection(&cs_error);
-
- return c;
-}
-
-
-/* Assumes that the context has been deleted from all relevant
- lists */
-void free_context(kherr_context * c) {
- kherr_context * ch;
- kherr_event * e;
-
- assert(c->magic == KHERR_CONTEXT_MAGIC);
-#ifdef DEBUG_CONTEXT
- kherr_debug_printf(L"Freeing context 0x%x\n", c);
-#endif
-
- EnterCriticalSection(&cs_error);
-
- if (c->desc_event)
- free_event(c->desc_event);
- c->desc_event = NULL;
-
- TPOPCHILD(c, &ch);
- while(ch) {
- free_context(ch);
- TPOPCHILD(c, &ch);
- }
- QGET(c, &e);
- while(e) {
- free_event(e);
- QGET(c, &e);
- }
-
- c->serial = 0;
-
- LPUSH(&ctx_free_list,c);
- LeaveCriticalSection(&cs_error);
-
-#ifdef DEBUG_CONTEXT
- kherr_debug_printf(L"Done with context 0x%x\n", c);
-#endif
-}
-
-void add_event(kherr_context * c, kherr_event * e)
-{
- kherr_event * te;
-
- EnterCriticalSection(&cs_error);
- te = QBOTTOM(c);
- if (te && !(te->flags & KHERR_RF_COMMIT)) {
- notify_ctx_event(KHERR_CTX_EVTCOMMIT, c);
- te->flags |= KHERR_RF_COMMIT;
- }
-
- QPUT(c,e);
- if(c->severity >= e->severity) {
- if (e->severity <= KHERR_ERROR)
- notify_ctx_event(KHERR_CTX_ERROR, c);
-
- c->severity = e->severity;
- c->err_event = e;
- c->flags &= ~KHERR_CF_DIRTY;
- }
- LeaveCriticalSection(&cs_error);
-}
-
-void pick_err_event(kherr_context * c)
-{
- kherr_event * e;
- kherr_event * ce = NULL;
- enum kherr_severity s;
-
- s = KHERR_RESERVED_BANK;
-
- EnterCriticalSection(&cs_error);
- e = QTOP(c);
- while(e) {
- if(!(e->flags & KHERR_RF_INERT) &&
- s >= e->severity) {
- ce = e;
- s = e->severity;
- }
- e = QNEXT(e);
- }
-
- if(ce) {
- c->err_event = ce;
- c->severity = ce->severity;
- } else {
- c->err_event = NULL;
- c->severity = KHERR_NONE;
- }
-
- c->flags &= ~KHERR_CF_DIRTY;
- LeaveCriticalSection(&cs_error);
-}
-
-static void arg_from_param(DWORD_PTR ** parm, kherr_param p) {
- int t;
-
- if (p.type != KEPT_NONE) {
- t = parm_type(p);
- if (t == KEPT_INT32 ||
- t == KEPT_UINT32 ||
- t == KEPT_STRINGC ||
- t == KEPT_STRINGT ||
- t == KEPT_PTR) {
-
- *(*parm)++ = (DWORD_PTR) parm_data(p);
-
- } else if (t == KEPT_INT64 ||
- t == KEPT_UINT64) {
- *(*parm)++ = (DWORD_PTR) parm_data(p) & 0xffffffff;
- *(*parm)++ = (DWORD_PTR) (parm_data(p) >> 32) & 0xffffffff;
- } else
- *(*parm)++ = 0;
- }
-}
-
-/* The 'buf' parameter MUST point to a DWORD_PTR[8] array */
-static void args_from_event(DWORD_PTR * buf, kherr_event * e) {
- arg_from_param(&buf, e->p1);
- arg_from_param(&buf, e->p2);
- arg_from_param(&buf, e->p3);
- arg_from_param(&buf, e->p4);
-}
-
-static void resolve_string_resource(kherr_event * e,
- const wchar_t ** str,
- khm_int32 if_flag,
- khm_int32 or_flag) {
- wchar_t tfmt[KHERR_MAXCCH_STRING];
- wchar_t tbuf[KHERR_MAXCCH_STRING];
- size_t chars = 0;
- size_t bytes = 0;
-
- if(e->flags & if_flag) {
- if(e->h_module != NULL)
- chars = LoadString(e->h_module, (UINT)(INT_PTR) *str,
- tfmt, ARRAYLENGTH(tbuf));
- if(e->h_module == NULL || chars == 0)
- *str = NULL;
- else {
- wchar_t * s;
- DWORD_PTR args[8];
-
- args_from_event(args, e);
-
- chars = FormatMessage(FORMAT_MESSAGE_FROM_STRING |
- FORMAT_MESSAGE_ARGUMENT_ARRAY,
- tfmt,
- 0,
- 0,
- tbuf,
- ARRAYLENGTH(tbuf),
- (va_list *) args);
-
- if (chars == 0) {
- *str = NULL;
- } else {
- bytes = (chars + 1) * sizeof(wchar_t);
- s = PMALLOC(bytes);
- assert(s);
- StringCbCopy(s, bytes, tbuf);
- *str = s;
- e->flags |= or_flag;
- }
- }
- e->flags &= ~if_flag;
- }
-}
-
-static void resolve_msg_resource(kherr_event * e,
- const wchar_t ** str,
- khm_int32 if_flag,
- khm_int32 or_flag) {
- wchar_t tbuf[KHERR_MAXCCH_STRING];
- size_t chars = 0;
- size_t bytes = 0;
- DWORD_PTR args[8];
-
- if(e->flags & if_flag) {
- if(e->h_module != NULL) {
- args_from_event(args, e);
-
- chars = FormatMessage(FORMAT_MESSAGE_FROM_HMODULE |
- FORMAT_MESSAGE_ARGUMENT_ARRAY,
- (LPCVOID) e->h_module,
- (DWORD)(DWORD_PTR) *str,
- 0,
- tbuf,
- ARRAYLENGTH(tbuf),
- (va_list *) args);
- }
-
- if(e->h_module == NULL || chars == 0) {
- *str = NULL;
- } else {
- wchar_t * s;
-
- /* MC inserts trailing \r\n to each message unless the
- message is terminated with a %0. We remove the last
- line break since it is irrelevant to our handling of
- the string in the UI. */
- if (tbuf[chars-1] == L'\n')
- tbuf[--chars] = L'\0';
- if (tbuf[chars-1] == L'\r')
- tbuf[--chars] = L'\0';
-
- bytes = (chars + 1) * sizeof(wchar_t);
- s = PMALLOC(bytes);
- assert(s);
- StringCbCopy(s, bytes, tbuf);
- *str = s;
- e->flags |= or_flag;
- }
- e->flags &= ~if_flag;
- }
-}
-
-static void resolve_string(kherr_event * e,
- const wchar_t ** str,
- khm_int32 mask,
- khm_int32 free_if,
- khm_int32 or_flag) {
-
- wchar_t tbuf[KHERR_MAXCCH_STRING];
- size_t chars;
- size_t bytes;
- DWORD_PTR args[8];
-
- if (((e->flags & mask) == 0 ||
- (e->flags & mask) == free_if) &&
- *str != NULL) {
-
- args_from_event(args, e);
- chars = FormatMessage(FORMAT_MESSAGE_FROM_STRING |
- FORMAT_MESSAGE_ARGUMENT_ARRAY,
- (LPCVOID) *str,
- 0,
- 0,
- tbuf,
- ARRAYLENGTH(tbuf),
- (va_list *) args);
-
- if ((e->flags & mask) == free_if) {
- PFREE((void *) *str);
- }
-
- e->flags &= ~mask;
-
- if (chars == 0) {
- *str = 0;
- } else {
- wchar_t * s;
-
- bytes = (chars + 1) * sizeof(wchar_t);
- s = PMALLOC(bytes);
- assert(s);
- StringCbCopy(s, bytes, tbuf);
- *str = s;
- e->flags |= or_flag;
- }
- }
-
-}
-
-void resolve_event_strings(kherr_event * e)
-{
- resolve_string(e, &e->short_desc,
- KHERR_RFMASK_SHORT_DESC,
- KHERR_RF_FREE_SHORT_DESC,
- KHERR_RF_FREE_SHORT_DESC);
-
- resolve_string(e, &e->long_desc,
- KHERR_RFMASK_LONG_DESC,
- KHERR_RF_FREE_LONG_DESC,
- KHERR_RF_FREE_LONG_DESC);
-
- resolve_string(e, &e->suggestion,
- KHERR_RFMASK_SUGGEST,
- KHERR_RF_FREE_SUGGEST,
- KHERR_RF_FREE_SUGGEST);
-
- resolve_string_resource(e, &e->short_desc,
- KHERR_RF_RES_SHORT_DESC,
- KHERR_RF_FREE_SHORT_DESC);
-
- resolve_string_resource(e, &e->long_desc,
- KHERR_RF_RES_LONG_DESC,
- KHERR_RF_FREE_LONG_DESC);
-
- resolve_string_resource(e, &e->suggestion,
- KHERR_RF_RES_SUGGEST,
- KHERR_RF_FREE_SUGGEST);
-
- resolve_msg_resource(e, &e->short_desc,
- KHERR_RF_MSG_SHORT_DESC,
- KHERR_RF_FREE_SHORT_DESC);
- resolve_msg_resource(e, &e->long_desc,
- KHERR_RF_MSG_LONG_DESC,
- KHERR_RF_FREE_LONG_DESC);
- resolve_msg_resource(e, &e->suggestion,
- KHERR_RF_MSG_SUGGEST,
- KHERR_RF_FREE_SUGGEST);
-
- /* get rid of dangling reference now that we have done everything
- we can with it. Since we have already dealt with all the
- parameter inserts, we don't need the parameters anymore
- either. */
- free_event_params(e);
-
- e->h_module = NULL;
- e->flags |= KHERR_RF_STR_RESOLVED;
-}
-
-
-KHMEXP void KHMAPI kherr_evaluate_event(kherr_event * e) {
- if (!e)
- return;
-
- EnterCriticalSection(&cs_error);
- resolve_event_strings(e);
- LeaveCriticalSection(&cs_error);
-}
-
-KHMEXP void KHMAPI kherr_evaluate_last_event(void) {
- kherr_context * c;
- kherr_event * e;
- DWORD tid;
-
- c = peek_context();
- if(!c)
- return;
- tid = GetCurrentThreadId();
-
- EnterCriticalSection(&cs_error);
- e = QBOTTOM(c);
- while (e != NULL && e->thread_id != tid)
- e = QPREV(e);
-
- if(!e)
- goto _exit;
-
- resolve_event_strings(e);
-
- _exit:
- LeaveCriticalSection(&cs_error);
-}
-
-KHMEXP kherr_event * __cdecl
-kherr_reportf(const wchar_t * long_desc_fmt, ...) {
- va_list vl;
- wchar_t buf[1024];
- kherr_event * e;
-
- va_start(vl, long_desc_fmt);
- StringCbVPrintf(buf, sizeof(buf), long_desc_fmt, vl);
-#ifdef DEBUG
- OutputDebugString(buf);
-#endif
- va_end(vl);
-
- e = kherr_report(KHERR_DEBUG_1,
- NULL, NULL, NULL, buf, NULL, 0,
- KHERR_SUGGEST_NONE, _vnull(), _vnull(), _vnull(), _vnull(),
- KHERR_RF_CSTR_LONG_DESC
-#ifdef _WIN32
- ,NULL
-#endif
- );
- if (e) {
- kherr_evaluate_event(e);
- }
-
- return e;
-}
-
-KHMEXP kherr_event * __cdecl
-kherr_reportf_ex(enum kherr_severity severity,
- const wchar_t * facility,
- khm_int32 facility_id,
-#ifdef _WIN32
- HMODULE hModule,
-#endif
- const wchar_t * long_desc_fmt, ...) {
- va_list vl;
- wchar_t buf[1024];
- kherr_event * e;
-
- va_start(vl, long_desc_fmt);
- StringCbVPrintf(buf, sizeof(buf), long_desc_fmt, vl);
-#ifdef DEBUG
- OutputDebugString(buf);
-#endif
- va_end(vl);
-
- e = kherr_report(severity, NULL, facility, NULL, buf, NULL, facility_id,
- KHERR_SUGGEST_NONE,
- _vnull(),
- _vnull(),
- _vnull(),
- _vnull(), KHERR_RF_CSTR_LONG_DESC
-#ifdef _WIN32
- ,hModule
-#endif
- );
- if (e) {
- kherr_evaluate_event(e);
- }
-
- return e;
-}
-
-KHMEXP kherr_event * KHMAPI
-kherr_report(enum kherr_severity severity,
- const wchar_t * short_desc,
- const wchar_t * facility,
- const wchar_t * location,
- const wchar_t * long_desc,
- const wchar_t * suggestion,
- khm_int32 facility_id,
- enum kherr_suggestion suggestion_id,
- kherr_param p1,
- kherr_param p2,
- kherr_param p3,
- kherr_param p4,
- khm_int32 flags
-#ifdef _WIN32
- ,HMODULE h_module
-#endif
- ) {
- kherr_context * c;
- kherr_event * e;
-
- /*TODO: sanity check flags (ISPOW2) */
-
- e = get_empty_event();
-
- e->thread_id = GetCurrentThreadId();
- e->time_ticks = GetTickCount();
- GetSystemTimeAsFileTime(&e->time_ft);
-
- e->severity = severity;
- e->short_desc = short_desc;
- e->facility = facility;
- e->location = location;
- e->long_desc = long_desc;
- e->suggestion = suggestion;
- e->facility_id = facility_id;
- e->suggestion_id = suggestion_id;
- e->p1 = p1;
- e->p2 = p2;
- e->p3 = p3;
- e->p4 = p4;
- e->flags = flags;
-#ifdef _WIN32
- e->h_module = h_module;
-#endif
-
- EnterCriticalSection(&cs_error);
- c = peek_context();
-
- if(!c) {
- /* the reason why we are doing it this way is because p1..p4,
- the descriptions and the suggestion may contain allocations
- that has to be freed. */
- free_event(e);
- e = NULL;
- } else {
- add_event(c,e);
- }
-
- LeaveCriticalSection(&cs_error);
-
- return e;
-}
-
-KHMEXP void KHMAPI kherr_suggest(wchar_t * suggestion,
- enum kherr_suggestion suggestion_id,
- khm_int32 flags) {
- kherr_context * c;
- kherr_event * e;
- DWORD tid;
-
- if (flags != KHERR_RF_CSTR_SUGGEST &&
- flags != KHERR_RF_RES_SUGGEST &&
- flags != KHERR_RF_MSG_SUGGEST &&
- flags != KHERR_RF_FREE_SUGGEST)
- return;
-
- c = peek_context();
- if(!c)
- return;
-
- tid = GetCurrentThreadId();
-
- EnterCriticalSection(&cs_error);
- e = QBOTTOM(c);
- while (e != NULL && e->thread_id != tid)
- e = QPREV(e);
-
- if(!e)
- goto _exit;
-
- /* if strings have already been resolved in this event, we cant
- add any more unresolved strings. */
- if ((flags == KHERR_RF_RES_SUGGEST ||
- flags == KHERR_RF_MSG_SUGGEST) &&
- (e->flags & KHERR_RF_STR_RESOLVED))
- goto _exit;
-
- e->suggestion = suggestion;
- e->suggestion_id = suggestion_id;
- e->flags |= flags;
-_exit:
- LeaveCriticalSection(&cs_error);
-}
-
-KHMEXP void KHMAPI kherr_location(wchar_t * location) {
- kherr_context * c;
- kherr_event * e;
- DWORD tid;
-
- c = peek_context();
- if(!c)
- return;
- tid = GetCurrentThreadId();
-
- EnterCriticalSection(&cs_error);
- e = QBOTTOM(c);
- while (e != NULL && e->thread_id != tid)
- e = QPREV(e);
-
- if(!e)
- goto _exit;
- e->location = location;
-_exit:
- LeaveCriticalSection(&cs_error);
-}
-
-KHMEXP void KHMAPI kherr_facility(wchar_t * facility,
- khm_int32 facility_id) {
- kherr_context * c;
- kherr_event * e;
- DWORD tid;
-
- c = peek_context();
- if(!c)
- return;
- tid = GetCurrentThreadId();
- EnterCriticalSection(&cs_error);
- e = QBOTTOM(c);
- while (e != NULL && e->thread_id != tid)
- e = QPREV(e);
-
- if(!e)
- goto _exit;
- e->facility = facility;
- e->facility_id = facility_id;
-_exit:
- LeaveCriticalSection(&cs_error);
-}
-
-KHMEXP void KHMAPI kherr_set_desc_event(void) {
- kherr_context * c;
- kherr_event * e;
- DWORD tid;
-
- c = peek_context();
- if(!c)
- return;
- tid = GetCurrentThreadId();
-
- EnterCriticalSection(&cs_error);
- e = QBOTTOM(c);
- while (e != NULL && e->thread_id != tid)
- e = QPREV(e);
-
- if(!e || c->desc_event)
- goto _exit;
-
- QDEL(c,e);
- c->desc_event = e;
- e->severity = KHERR_NONE;
- resolve_event_strings(e);
-
- notify_ctx_event(KHERR_CTX_DESCRIBE, c);
-
-_exit:
- LeaveCriticalSection(&cs_error);
-}
-
-KHMEXP void KHMAPI kherr_del_last_event(void) {
- kherr_context * c;
- kherr_event * e;
- DWORD tid;
-
- c = peek_context();
-
- if(!c)
- return;
-
- tid = GetCurrentThreadId();
-
- EnterCriticalSection(&cs_error);
- e = QBOTTOM(c);
- while (e != NULL && e->thread_id != tid)
- e = QPREV(e);
-
- if(e) {
- QDEL(c, e);
- if(c->err_event == e) {
- pick_err_event(c);
- }
- free_event(e);
- }
- LeaveCriticalSection(&cs_error);
-}
-
-KHMEXP void KHMAPI kherr_push_context(kherr_context * c)
-{
- kherr_context * p;
- int new_context = FALSE;
-
- EnterCriticalSection(&cs_error);
- p = peek_context();
- if(p && (c->flags & KHERR_CF_UNBOUND)) {
- LDELETE(&ctx_root_list, c);
- TADDCHILD(p,c);
- c->flags &= ~KHERR_CF_UNBOUND;
- kherr_hold_context(p);
- new_context = TRUE;
- }
- push_context(c);
-
- if (new_context)
- notify_ctx_event(KHERR_CTX_BEGIN, c);
-
- LeaveCriticalSection(&cs_error);
-}
-
-KHMEXP void KHMAPI kherr_push_new_context(khm_int32 flags)
-{
- kherr_context * p;
- kherr_context * c;
-
- flags &= KHERR_CFMASK_INITIAL;
-
- EnterCriticalSection(&cs_error);
- p = peek_context();
- c = get_empty_context();
- if(p) {
- LDELETE(&ctx_root_list, c);
- TADDCHILD(p,c);
- c->flags &= ~KHERR_CF_UNBOUND;
- kherr_hold_context(p);
- }
- c->flags |= flags;
- push_context(c);
-
- notify_ctx_event(KHERR_CTX_BEGIN, c);
-
- LeaveCriticalSection(&cs_error);
-}
-
-kherr_param dup_parm(kherr_param p) {
- if(parm_type(p) == KEPT_STRINGT) {
- wchar_t * d = PWCSDUP((wchar_t *)parm_data(p));
- return kherr_val(KEPT_STRINGT, (khm_ui_8) d);
- } else
- return p;
-}
-
-kherr_event * fold_context(kherr_context * c) {
- kherr_event * e;
- kherr_event * g;
-
- if (!c)
- return NULL;
-
- EnterCriticalSection(&cs_error);
- if(!c->err_event || (c->flags & KHERR_CF_DIRTY)) {
- pick_err_event(c);
- }
- if(c->err_event) {
- g = c->err_event;
- e = get_empty_event();
- *e = *g;
- g->short_desc = NULL;
- g->long_desc = NULL;
- g->suggestion = NULL;
- g->flags &=
- ~(KHERR_RF_FREE_SHORT_DESC |
- KHERR_RF_FREE_LONG_DESC |
- KHERR_RF_FREE_SUGGEST);
- LINIT(e);
- e->p1 = dup_parm(g->p1);
- e->p2 = dup_parm(g->p2);
- e->p3 = dup_parm(g->p3);
- e->p4 = dup_parm(g->p4);
- } else {
- e = c->desc_event;
- c->desc_event = NULL;
- }
-
- if (e)
- e->flags |= KHERR_RF_CONTEXT_FOLD;
-
- LeaveCriticalSection(&cs_error);
-
- return e;
-}
-
-KHMEXP void KHMAPI kherr_hold_context(kherr_context * c) {
- assert(c && c->magic == KHERR_CONTEXT_MAGIC);
- EnterCriticalSection(&cs_error);
- c->refcount++;
- LeaveCriticalSection(&cs_error);
-}
-
-KHMEXP void KHMAPI kherr_release_context(kherr_context * c) {
- assert(c && c->magic == KHERR_CONTEXT_MAGIC);
- EnterCriticalSection(&cs_error);
- c->refcount--;
- if (c->refcount == 0) {
- kherr_event * e;
- kherr_context * p;
-
- e = QBOTTOM(c);
- if (e && !(e->flags & KHERR_RF_COMMIT)) {
- notify_ctx_event(KHERR_CTX_EVTCOMMIT, c);
- e->flags |= KHERR_RF_COMMIT;
- }
-
- notify_ctx_event(KHERR_CTX_END, c);
-
- p = TPARENT(c);
- if (p) {
- e = fold_context(c);
- if (e)
- add_event(p, e);
-
- TDELCHILD(p, c);
- kherr_release_context(p);
- } else {
- LDELETE(&ctx_root_list, c);
- }
- free_context(c);
- }
- LeaveCriticalSection(&cs_error);
-}
-
-KHMEXP void KHMAPI kherr_pop_context(void) {
- kherr_context * c;
-
- EnterCriticalSection(&cs_error);
- c = pop_context();
- if(c) {
- kherr_release_context(c);
- }
- LeaveCriticalSection(&cs_error);
-}
-
-KHMEXP kherr_context * KHMAPI kherr_peek_context(void) {
- kherr_context * c;
-
- c = peek_context();
- if (c)
- kherr_hold_context(c);
-
- return c;
-}
-
-KHMEXP khm_boolean KHMAPI kherr_is_error(void) {
- kherr_context * c = peek_context();
- return kherr_is_error_i(c);
-}
-
-KHMEXP khm_boolean KHMAPI kherr_is_error_i(kherr_context * c) {
- if(c && c->severity <= KHERR_ERROR)
- return TRUE;
- else
- return FALSE;
-}
-
-KHMEXP void KHMAPI kherr_clear_error(void) {
- kherr_context * c = peek_context();
- if (c)
- kherr_clear_error_i(c);
-}
-
-KHMEXP void KHMAPI kherr_clear_error_i(kherr_context * c) {
- kherr_event * e;
- if (c) {
- EnterCriticalSection(&cs_error);
- e = QTOP(c);
- while(e) {
- e->flags |= KHERR_RF_INERT;
- e = QNEXT(e);
- }
- c->severity = KHERR_NONE;
- c->err_event = NULL;
- c->flags &= ~KHERR_CF_DIRTY;
- LeaveCriticalSection(&cs_error);
- }
-}
-
-KHMEXP void KHMAPI kherr_set_progress(khm_ui_4 num, khm_ui_4 denom) {
- kherr_context * c = peek_context();
- if(c) {
- EnterCriticalSection(&cs_error);
- c->progress_denom = denom;
- c->progress_num = num;
- LeaveCriticalSection(&cs_error);
- }
-}
-
-KHMEXP void KHMAPI kherr_get_progress(khm_ui_4 * num, khm_ui_4 * denom) {
- kherr_context * c = peek_context();
- kherr_get_progress_i(c,num,denom);
-}
-
-KHMEXP void KHMAPI kherr_get_progress_i(kherr_context * c,
- khm_ui_4 * num,
- khm_ui_4 * denom) {
- if(c) {
- EnterCriticalSection(&cs_error);
- *num = c->progress_num;
- *denom = c->progress_denom;
- LeaveCriticalSection(&cs_error);
- } else {
- *num = 0;
- *denom = 0;
- }
-}
-
-KHMEXP kherr_event * KHMAPI kherr_get_first_event(kherr_context * c)
-{
- kherr_event * e;
- EnterCriticalSection(&cs_error);
- e = QTOP(c);
- LeaveCriticalSection(&cs_error);
- return e;
-}
-
-KHMEXP kherr_event * KHMAPI kherr_get_next_event(kherr_event * e)
-{
- kherr_event * ee;
-
- EnterCriticalSection(&cs_error);
- ee = QNEXT(e);
- LeaveCriticalSection(&cs_error);
- return ee;
-}
-
-KHMEXP kherr_event * KHMAPI kherr_get_prev_event(kherr_event * e)
-{
- kherr_event * ee;
-
- EnterCriticalSection(&cs_error);
- ee = QPREV(e);
- LeaveCriticalSection(&cs_error);
-
- return ee;
-}
-
-KHMEXP kherr_event * KHMAPI kherr_get_last_event(kherr_context * c)
-{
- kherr_event * e;
- EnterCriticalSection(&cs_error);
- e = QBOTTOM(c);
- LeaveCriticalSection(&cs_error);
- return e;
-}
-
-KHMEXP kherr_context * KHMAPI kherr_get_first_context(kherr_context * c)
-{
- kherr_context * cc;
-
- EnterCriticalSection(&cs_error);
- if (c) {
- cc = TFIRSTCHILD(c);
- if (cc)
- kherr_hold_context(cc);
- } else {
- cc = ctx_root_list;
- if (cc)
- kherr_hold_context(cc);
- }
- LeaveCriticalSection(&cs_error);
- return cc;
-}
-
-KHMEXP kherr_context * KHMAPI kherr_get_next_context(kherr_context * c)
-{
- kherr_context * cc;
- EnterCriticalSection(&cs_error);
- cc = LNEXT(c);
- if (cc)
- kherr_hold_context(cc);
- LeaveCriticalSection(&cs_error);
- return cc;
-}
-
-KHMEXP kherr_event * KHMAPI kherr_get_err_event(kherr_context * c)
-{
- kherr_event * e;
- EnterCriticalSection(&cs_error);
- if(!c->err_event) {
- pick_err_event(c);
- }
- e = c->err_event;
- LeaveCriticalSection(&cs_error);
- return e;
-}
-
-KHMEXP kherr_event * KHMAPI kherr_get_desc_event(kherr_context * c)
-{
- kherr_event * e;
-
- EnterCriticalSection(&cs_error);
- e = c->desc_event;
- LeaveCriticalSection(&cs_error);
- return e;
-}
-
-KHMEXP kherr_param kherr_dup_string(const wchar_t * s)
-{
- wchar_t * dest;
- size_t cb_s;
-
- if (s == NULL)
- return _vnull();
-
- if (FAILED(StringCbLength(s, KHERR_MAXCB_STRING, &cb_s)))
- cb_s = KHERR_MAXCB_STRING;
- else
- cb_s += sizeof(wchar_t);
-
- dest = PMALLOC(cb_s);
- assert(dest != NULL);
- dest[0] = L'\0';
-
- StringCbCopy(dest, cb_s, s);
-
- return _tstr(dest);
-}
-
-
-#if 0
-KHMEXP kherr_param kherr_val(khm_octet ptype, khm_ui_8 pvalue) {
- kherr_param p;
- p.type = ptype;
- p.data = pvalue;
-
- return p;
-}
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<kherrinternal.h>
+#include<assert.h>
+#include<stdarg.h>
+
+CRITICAL_SECTION cs_error;
+DWORD tls_error = 0;
+kherr_context * ctx_free_list = NULL;
+kherr_context * ctx_root_list = NULL;
+kherr_context * ctx_error_list = NULL;
+kherr_event * evt_free_list = NULL;
+
+kherr_handler_node * ctx_handlers = NULL;
+khm_size n_ctx_handlers;
+khm_size nc_ctx_handlers;
+
+kherr_serial ctx_serial = 0;
+
+#ifdef DEBUG
+#define DEBUG_CONTEXT
+
+KHMEXP void kherr_debug_printf(wchar_t * fmt, ...) {
+ va_list vl;
+ wchar_t buf[1024];
+
+ va_start(vl, fmt);
+ StringCbVPrintf(buf, sizeof(buf), fmt, vl);
+ OutputDebugString(buf);
+ va_end(vl);
+}
+#endif
+
+KHMEXP void KHMAPI kherr_add_ctx_handler(kherr_ctx_handler h,
+ khm_int32 filter,
+ kherr_serial serial) {
+
+ khm_size idx;
+
+ assert(h);
+
+ EnterCriticalSection(&cs_error);
+ if( ctx_handlers == NULL) {
+ nc_ctx_handlers = CTX_ALLOC_INCR;
+ n_ctx_handlers = 0;
+ ctx_handlers = PMALLOC(sizeof(*ctx_handlers) * nc_ctx_handlers);
+ /* No need to initialize */
+ } else if (n_ctx_handlers == nc_ctx_handlers) {
+ khm_size new_nc;
+ kherr_handler_node * new_ctxs;
+
+ new_nc = nc_ctx_handlers + CTX_ALLOC_INCR;
+ new_ctxs = PMALLOC(sizeof(*new_ctxs) * new_nc);
+ memcpy(new_ctxs, ctx_handlers, n_ctx_handlers * sizeof(*new_ctxs));
+
+ PFREE(ctx_handlers);
+ ctx_handlers = new_ctxs;
+ nc_ctx_handlers = new_nc;
+ }
+
+ if (filter == 0)
+ filter = KHERR_CTX_BEGIN |
+ KHERR_CTX_DESCRIBE |
+ KHERR_CTX_END |
+ KHERR_CTX_ERROR;
+
+ /* Since commit events are the most frequent, we put those
+ handlers at the top of the list. When dispatching a commit
+ event, we stop looking at the list when we find a filter that
+ doesn't filter for commit events. */
+ if (filter & KHERR_CTX_EVTCOMMIT) {
+ idx = 0;
+ memmove(&ctx_handlers[1], &ctx_handlers[0],
+ n_ctx_handlers * sizeof(ctx_handlers[0]));
+ } else {
+ idx = n_ctx_handlers;
+ }
+
+ ctx_handlers[idx].h = h;
+ ctx_handlers[idx].filter = filter;
+ ctx_handlers[idx].serial = serial;
+
+ n_ctx_handlers++;
+
+ LeaveCriticalSection(&cs_error);
+}
+
+KHMEXP void KHMAPI kherr_remove_ctx_handler(kherr_ctx_handler h,
+ kherr_serial serial) {
+ khm_size i;
+ EnterCriticalSection(&cs_error);
+
+ for (i=0 ; i < n_ctx_handlers; i++) {
+ if (ctx_handlers[i].h == h &&
+ ctx_handlers[i].serial == serial) {
+ break;
+ }
+ }
+
+ if ( i < n_ctx_handlers ) {
+ n_ctx_handlers --;
+ for (; i < n_ctx_handlers; i++) {
+ ctx_handlers[i] = ctx_handlers[i + 1];
+ }
+ }
+
+ LeaveCriticalSection(&cs_error);
+}
+
+/* Called with cs_error held */
+void notify_ctx_event(enum kherr_ctx_event e, kherr_context * c) {
+ khm_size i;
+
+ kherr_ctx_handler h;
+
+ for (i=0; i<n_ctx_handlers; i++) {
+ if (ctx_handlers[i].h && (ctx_handlers[i].filter & e) &&
+ (ctx_handlers[i].serial == 0 ||
+ ctx_handlers[i].serial == c->serial)) {
+ if (IsBadCodePtr((FARPROC) ctx_handlers[i].h)) {
+ ctx_handlers[i].h = NULL;
+ } else {
+ h = ctx_handlers[i].h;
+ (*h)(e,c);
+
+ /* a context handler is allowed to remove itself
+ during a callback. It is, however, not allowed to
+ remove anything else. */
+ if (h != ctx_handlers[i].h)
+ i--;
+ }
+ } else if (e == KHERR_CTX_EVTCOMMIT &&
+ !(ctx_handlers[i].filter & KHERR_CTX_EVTCOMMIT)) {
+ /* All handlers that filter for commit events are at the
+ top of the list. If this handler wasn't filtering for
+ it, then there's no point in goint further down the
+ list. */
+ break;
+ }
+ }
+}
+
+void attach_this_thread(void) {
+ kherr_thread * t;
+
+ t = (kherr_thread *) TlsGetValue(tls_error);
+ if (t)
+ return;
+
+ t = PMALLOC(sizeof(kherr_thread) +
+ sizeof(kherr_context *) * THREAD_STACK_SIZE);
+ t->nc_ctx = THREAD_STACK_SIZE;
+ t->n_ctx = 0;
+ t->ctx = (kherr_context **) &t[1];
+
+ TlsSetValue(tls_error, t);
+}
+
+void detach_this_thread(void) {
+ kherr_thread * t;
+ khm_size i;
+
+ t = (kherr_thread *) TlsGetValue(tls_error);
+ if (t) {
+ for(i=0; i < t->n_ctx; i++) {
+ kherr_release_context(t->ctx[i]);
+ }
+ PFREE(t);
+ TlsSetValue(tls_error, 0);
+ }
+}
+
+kherr_context * peek_context(void) {
+ kherr_thread * t;
+
+ t = (kherr_thread *) TlsGetValue(tls_error);
+ if (t) {
+ if (t->n_ctx > 0)
+ return t->ctx[t->n_ctx - 1];
+ else
+ return NULL;
+ } else
+ return NULL;
+}
+
+void push_context(kherr_context * c) {
+ kherr_thread * t;
+
+ t = (kherr_thread *) TlsGetValue(tls_error);
+ if (!t) {
+ attach_this_thread();
+ t = (kherr_thread *) TlsGetValue(tls_error);
+ assert(t);
+ }
+
+ if (t->n_ctx == t->nc_ctx) {
+ khm_size nc_new;
+ khm_size cb_new;
+ kherr_thread * nt;
+
+ nc_new = t->nc_ctx + THREAD_STACK_SIZE;
+ cb_new = sizeof(kherr_thread) +
+ sizeof(kherr_context *) * nc_new;
+
+ nt = PMALLOC(cb_new);
+ memcpy(nt, t, sizeof(kherr_thread) +
+ sizeof(kherr_context *) * t->n_ctx);
+ nt->ctx = (kherr_context **) &nt[1];
+ nt->nc_ctx = nc_new;
+
+ PFREE(t);
+ t = nt;
+ TlsSetValue(tls_error, t);
+ }
+
+ assert(t->n_ctx < t->nc_ctx);
+ t->ctx[t->n_ctx++] = c;
+
+ kherr_hold_context(c);
+}
+
+/* returned pointer is still held */
+kherr_context * pop_context(void) {
+ kherr_thread * t;
+ kherr_context * c;
+
+ t = (kherr_thread *) TlsGetValue(tls_error);
+ if (t) {
+ if (t->n_ctx > 0) {
+ c = t->ctx[--(t->n_ctx)];
+ return c;
+ } else
+ return NULL;
+ } else {
+ return NULL;
+ }
+}
+
+kherr_event * get_empty_event(void) {
+ kherr_event * e;
+
+ EnterCriticalSection(&cs_error);
+ if(evt_free_list) {
+ LPOP(&evt_free_list, &e);
+ } else {
+ e = PMALLOC(sizeof(*e));
+ }
+ LeaveCriticalSection(&cs_error);
+ ZeroMemory(e, sizeof(*e));
+ e->severity = KHERR_NONE;
+ e->magic = KHERR_EVENT_MAGIC;
+
+ return e;
+}
+
+void free_event_params(kherr_event * e) {
+ if(parm_type(e->p1) == KEPT_STRINGT) {
+ assert((void *) parm_data(e->p1));
+ PFREE((void*) parm_data(e->p1));
+ ZeroMemory(&e->p1, sizeof(e->p1));
+ }
+ if(parm_type(e->p2) == KEPT_STRINGT) {
+ assert((void *) parm_data(e->p2));
+ PFREE((void*) parm_data(e->p2));
+ ZeroMemory(&e->p2, sizeof(e->p2));
+ }
+ if(parm_type(e->p3) == KEPT_STRINGT) {
+ assert((void *) parm_data(e->p3));
+ PFREE((void*) parm_data(e->p3));
+ ZeroMemory(&e->p3, sizeof(e->p3));
+ }
+ if(parm_type(e->p4) == KEPT_STRINGT) {
+ assert((void *) parm_data(e->p4));
+ PFREE((void*) parm_data(e->p4));
+ ZeroMemory(&e->p4, sizeof(e->p4));
+ }
+}
+
+void free_event(kherr_event * e) {
+
+ EnterCriticalSection(&cs_error);
+
+ assert(e->magic == KHERR_EVENT_MAGIC);
+
+#ifdef DEBUG_CONTEXT
+ kherr_debug_printf(L"Freeing event 0x%x\n", e);
+ if (!(e->flags & KHERR_RF_STR_RESOLVED))
+ resolve_event_strings(e);
+ if (e->short_desc)
+ kherr_debug_printf(L" Desc(S):[%s]\n", e->short_desc);
+ if (e->long_desc)
+ kherr_debug_printf(L" Desc(L):[%s]\n", e->long_desc);
+ if (e->suggestion)
+ kherr_debug_printf(L" Suggest:[%s]\n", e->suggestion);
+ if (e->facility)
+ kherr_debug_printf(L" Facility:[%s]\n", e->facility);
+#endif
+
+ if(e->flags & KHERR_RF_FREE_SHORT_DESC) {
+ assert(e->short_desc);
+ PFREE((void *) e->short_desc);
+ }
+ if(e->flags & KHERR_RF_FREE_LONG_DESC) {
+ assert(e->long_desc);
+ PFREE((void *) e->long_desc);
+ }
+ if(e->flags & KHERR_RF_FREE_SUGGEST) {
+ assert(e->suggestion);
+ PFREE((void *) e->suggestion);
+ }
+
+ free_event_params(e);
+
+ ZeroMemory(e, sizeof(e));
+
+ LPUSH(&evt_free_list, e);
+ LeaveCriticalSection(&cs_error);
+}
+
+kherr_context * get_empty_context(void) {
+ kherr_context * c;
+
+ EnterCriticalSection(&cs_error);
+ if(ctx_free_list)
+ LPOP(&ctx_free_list, &c);
+ else {
+ c = PMALLOC(sizeof(kherr_context));
+ }
+
+ ZeroMemory(c,sizeof(*c));
+ c->severity = KHERR_NONE;
+ c->flags = KHERR_CF_UNBOUND;
+ c->magic = KHERR_CONTEXT_MAGIC;
+ c->serial = ++ctx_serial;
+
+ LPUSH(&ctx_root_list, c);
+
+ LeaveCriticalSection(&cs_error);
+
+ return c;
+}
+
+
+/* Assumes that the context has been deleted from all relevant
+ lists */
+void free_context(kherr_context * c) {
+ kherr_context * ch;
+ kherr_event * e;
+
+ assert(c->magic == KHERR_CONTEXT_MAGIC);
+#ifdef DEBUG_CONTEXT
+ kherr_debug_printf(L"Freeing context 0x%x\n", c);
+#endif
+
+ EnterCriticalSection(&cs_error);
+
+ if (c->desc_event)
+ free_event(c->desc_event);
+ c->desc_event = NULL;
+
+ TPOPCHILD(c, &ch);
+ while(ch) {
+ free_context(ch);
+ TPOPCHILD(c, &ch);
+ }
+ QGET(c, &e);
+ while(e) {
+ free_event(e);
+ QGET(c, &e);
+ }
+
+ c->serial = 0;
+
+ LPUSH(&ctx_free_list,c);
+ LeaveCriticalSection(&cs_error);
+
+#ifdef DEBUG_CONTEXT
+ kherr_debug_printf(L"Done with context 0x%x\n", c);
+#endif
+}
+
+void add_event(kherr_context * c, kherr_event * e)
+{
+ kherr_event * te;
+
+ EnterCriticalSection(&cs_error);
+ te = QBOTTOM(c);
+ if (te && !(te->flags & KHERR_RF_COMMIT)) {
+ notify_ctx_event(KHERR_CTX_EVTCOMMIT, c);
+ te->flags |= KHERR_RF_COMMIT;
+ }
+
+ QPUT(c,e);
+ if(c->severity >= e->severity) {
+ if (e->severity <= KHERR_ERROR)
+ notify_ctx_event(KHERR_CTX_ERROR, c);
+
+ c->severity = e->severity;
+ c->err_event = e;
+ c->flags &= ~KHERR_CF_DIRTY;
+ }
+ LeaveCriticalSection(&cs_error);
+}
+
+void pick_err_event(kherr_context * c)
+{
+ kherr_event * e;
+ kherr_event * ce = NULL;
+ enum kherr_severity s;
+
+ s = KHERR_RESERVED_BANK;
+
+ EnterCriticalSection(&cs_error);
+ e = QTOP(c);
+ while(e) {
+ if(!(e->flags & KHERR_RF_INERT) &&
+ s >= e->severity) {
+ ce = e;
+ s = e->severity;
+ }
+ e = QNEXT(e);
+ }
+
+ if(ce) {
+ c->err_event = ce;
+ c->severity = ce->severity;
+ } else {
+ c->err_event = NULL;
+ c->severity = KHERR_NONE;
+ }
+
+ c->flags &= ~KHERR_CF_DIRTY;
+ LeaveCriticalSection(&cs_error);
+}
+
+static void arg_from_param(DWORD_PTR ** parm, kherr_param p) {
+ int t;
+
+ if (p.type != KEPT_NONE) {
+ t = parm_type(p);
+ if (t == KEPT_INT32 ||
+ t == KEPT_UINT32 ||
+ t == KEPT_STRINGC ||
+ t == KEPT_STRINGT ||
+ t == KEPT_PTR) {
+
+ *(*parm)++ = (DWORD_PTR) parm_data(p);
+
+ } else if (t == KEPT_INT64 ||
+ t == KEPT_UINT64) {
+ *(*parm)++ = (DWORD_PTR) parm_data(p) & 0xffffffff;
+ *(*parm)++ = (DWORD_PTR) (parm_data(p) >> 32) & 0xffffffff;
+ } else
+ *(*parm)++ = 0;
+ }
+}
+
+/* The 'buf' parameter MUST point to a DWORD_PTR[8] array */
+static void args_from_event(DWORD_PTR * buf, kherr_event * e) {
+ arg_from_param(&buf, e->p1);
+ arg_from_param(&buf, e->p2);
+ arg_from_param(&buf, e->p3);
+ arg_from_param(&buf, e->p4);
+}
+
+static void resolve_string_resource(kherr_event * e,
+ const wchar_t ** str,
+ khm_int32 if_flag,
+ khm_int32 or_flag) {
+ wchar_t tfmt[KHERR_MAXCCH_STRING];
+ wchar_t tbuf[KHERR_MAXCCH_STRING];
+ size_t chars = 0;
+ size_t bytes = 0;
+
+ if(e->flags & if_flag) {
+ if(e->h_module != NULL)
+ chars = LoadString(e->h_module, (UINT)(INT_PTR) *str,
+ tfmt, ARRAYLENGTH(tbuf));
+ if(e->h_module == NULL || chars == 0)
+ *str = NULL;
+ else {
+ wchar_t * s;
+ DWORD_PTR args[8];
+
+ args_from_event(args, e);
+
+ chars = FormatMessage(FORMAT_MESSAGE_FROM_STRING |
+ FORMAT_MESSAGE_ARGUMENT_ARRAY,
+ tfmt,
+ 0,
+ 0,
+ tbuf,
+ ARRAYLENGTH(tbuf),
+ (va_list *) args);
+
+ if (chars == 0) {
+ *str = NULL;
+ } else {
+ bytes = (chars + 1) * sizeof(wchar_t);
+ s = PMALLOC(bytes);
+ assert(s);
+ StringCbCopy(s, bytes, tbuf);
+ *str = s;
+ e->flags |= or_flag;
+ }
+ }
+ e->flags &= ~if_flag;
+ }
+}
+
+static void resolve_msg_resource(kherr_event * e,
+ const wchar_t ** str,
+ khm_int32 if_flag,
+ khm_int32 or_flag) {
+ wchar_t tbuf[KHERR_MAXCCH_STRING];
+ size_t chars = 0;
+ size_t bytes = 0;
+ DWORD_PTR args[8];
+
+ if(e->flags & if_flag) {
+ if(e->h_module != NULL) {
+ args_from_event(args, e);
+
+ chars = FormatMessage(FORMAT_MESSAGE_FROM_HMODULE |
+ FORMAT_MESSAGE_ARGUMENT_ARRAY,
+ (LPCVOID) e->h_module,
+ (DWORD)(DWORD_PTR) *str,
+ 0,
+ tbuf,
+ ARRAYLENGTH(tbuf),
+ (va_list *) args);
+ }
+
+ if(e->h_module == NULL || chars == 0) {
+ *str = NULL;
+ } else {
+ wchar_t * s;
+
+ /* MC inserts trailing \r\n to each message unless the
+ message is terminated with a %0. We remove the last
+ line break since it is irrelevant to our handling of
+ the string in the UI. */
+ if (tbuf[chars-1] == L'\n')
+ tbuf[--chars] = L'\0';
+ if (tbuf[chars-1] == L'\r')
+ tbuf[--chars] = L'\0';
+
+ bytes = (chars + 1) * sizeof(wchar_t);
+ s = PMALLOC(bytes);
+ assert(s);
+ StringCbCopy(s, bytes, tbuf);
+ *str = s;
+ e->flags |= or_flag;
+ }
+ e->flags &= ~if_flag;
+ }
+}
+
+static void resolve_string(kherr_event * e,
+ const wchar_t ** str,
+ khm_int32 mask,
+ khm_int32 free_if,
+ khm_int32 or_flag) {
+
+ wchar_t tbuf[KHERR_MAXCCH_STRING];
+ size_t chars;
+ size_t bytes;
+ DWORD_PTR args[8];
+
+ if (((e->flags & mask) == 0 ||
+ (e->flags & mask) == free_if) &&
+ *str != NULL) {
+
+ args_from_event(args, e);
+ chars = FormatMessage(FORMAT_MESSAGE_FROM_STRING |
+ FORMAT_MESSAGE_ARGUMENT_ARRAY,
+ (LPCVOID) *str,
+ 0,
+ 0,
+ tbuf,
+ ARRAYLENGTH(tbuf),
+ (va_list *) args);
+
+ if ((e->flags & mask) == free_if) {
+ PFREE((void *) *str);
+ }
+
+ e->flags &= ~mask;
+
+ if (chars == 0) {
+ *str = 0;
+ } else {
+ wchar_t * s;
+
+ bytes = (chars + 1) * sizeof(wchar_t);
+ s = PMALLOC(bytes);
+ assert(s);
+ StringCbCopy(s, bytes, tbuf);
+ *str = s;
+ e->flags |= or_flag;
+ }
+ }
+
+}
+
+void resolve_event_strings(kherr_event * e)
+{
+ resolve_string(e, &e->short_desc,
+ KHERR_RFMASK_SHORT_DESC,
+ KHERR_RF_FREE_SHORT_DESC,
+ KHERR_RF_FREE_SHORT_DESC);
+
+ resolve_string(e, &e->long_desc,
+ KHERR_RFMASK_LONG_DESC,
+ KHERR_RF_FREE_LONG_DESC,
+ KHERR_RF_FREE_LONG_DESC);
+
+ resolve_string(e, &e->suggestion,
+ KHERR_RFMASK_SUGGEST,
+ KHERR_RF_FREE_SUGGEST,
+ KHERR_RF_FREE_SUGGEST);
+
+ resolve_string_resource(e, &e->short_desc,
+ KHERR_RF_RES_SHORT_DESC,
+ KHERR_RF_FREE_SHORT_DESC);
+
+ resolve_string_resource(e, &e->long_desc,
+ KHERR_RF_RES_LONG_DESC,
+ KHERR_RF_FREE_LONG_DESC);
+
+ resolve_string_resource(e, &e->suggestion,
+ KHERR_RF_RES_SUGGEST,
+ KHERR_RF_FREE_SUGGEST);
+
+ resolve_msg_resource(e, &e->short_desc,
+ KHERR_RF_MSG_SHORT_DESC,
+ KHERR_RF_FREE_SHORT_DESC);
+ resolve_msg_resource(e, &e->long_desc,
+ KHERR_RF_MSG_LONG_DESC,
+ KHERR_RF_FREE_LONG_DESC);
+ resolve_msg_resource(e, &e->suggestion,
+ KHERR_RF_MSG_SUGGEST,
+ KHERR_RF_FREE_SUGGEST);
+
+ /* get rid of dangling reference now that we have done everything
+ we can with it. Since we have already dealt with all the
+ parameter inserts, we don't need the parameters anymore
+ either. */
+ free_event_params(e);
+
+ e->h_module = NULL;
+ e->flags |= KHERR_RF_STR_RESOLVED;
+}
+
+
+KHMEXP void KHMAPI kherr_evaluate_event(kherr_event * e) {
+ if (!e)
+ return;
+
+ EnterCriticalSection(&cs_error);
+ resolve_event_strings(e);
+ LeaveCriticalSection(&cs_error);
+}
+
+KHMEXP void KHMAPI kherr_evaluate_last_event(void) {
+ kherr_context * c;
+ kherr_event * e;
+ DWORD tid;
+
+ c = peek_context();
+ if(!c)
+ return;
+ tid = GetCurrentThreadId();
+
+ EnterCriticalSection(&cs_error);
+ e = QBOTTOM(c);
+ while (e != NULL && e->thread_id != tid)
+ e = QPREV(e);
+
+ if(!e)
+ goto _exit;
+
+ resolve_event_strings(e);
+
+ _exit:
+ LeaveCriticalSection(&cs_error);
+}
+
+KHMEXP kherr_event * __cdecl
+kherr_reportf(const wchar_t * long_desc_fmt, ...) {
+ va_list vl;
+ wchar_t buf[1024];
+ kherr_event * e;
+
+ va_start(vl, long_desc_fmt);
+ StringCbVPrintf(buf, sizeof(buf), long_desc_fmt, vl);
+#ifdef DEBUG
+ OutputDebugString(buf);
+#endif
+ va_end(vl);
+
+ e = kherr_report(KHERR_DEBUG_1,
+ NULL, NULL, NULL, buf, NULL, 0,
+ KHERR_SUGGEST_NONE, _vnull(), _vnull(), _vnull(), _vnull(),
+ KHERR_RF_CSTR_LONG_DESC
+#ifdef _WIN32
+ ,NULL
+#endif
+ );
+ if (e) {
+ kherr_evaluate_event(e);
+ }
+
+ return e;
+}
+
+KHMEXP kherr_event * __cdecl
+kherr_reportf_ex(enum kherr_severity severity,
+ const wchar_t * facility,
+ khm_int32 facility_id,
+#ifdef _WIN32
+ HMODULE hModule,
+#endif
+ const wchar_t * long_desc_fmt, ...) {
+ va_list vl;
+ wchar_t buf[1024];
+ kherr_event * e;
+
+ va_start(vl, long_desc_fmt);
+ StringCbVPrintf(buf, sizeof(buf), long_desc_fmt, vl);
+#ifdef DEBUG
+ OutputDebugString(buf);
+#endif
+ va_end(vl);
+
+ e = kherr_report(severity, NULL, facility, NULL, buf, NULL, facility_id,
+ KHERR_SUGGEST_NONE,
+ _vnull(),
+ _vnull(),
+ _vnull(),
+ _vnull(), KHERR_RF_CSTR_LONG_DESC
+#ifdef _WIN32
+ ,hModule
+#endif
+ );
+ if (e) {
+ kherr_evaluate_event(e);
+ }
+
+ return e;
+}
+
+KHMEXP kherr_event * KHMAPI
+kherr_report(enum kherr_severity severity,
+ const wchar_t * short_desc,
+ const wchar_t * facility,
+ const wchar_t * location,
+ const wchar_t * long_desc,
+ const wchar_t * suggestion,
+ khm_int32 facility_id,
+ enum kherr_suggestion suggestion_id,
+ kherr_param p1,
+ kherr_param p2,
+ kherr_param p3,
+ kherr_param p4,
+ khm_int32 flags
+#ifdef _WIN32
+ ,HMODULE h_module
+#endif
+ ) {
+ kherr_context * c;
+ kherr_event * e;
+
+ /*TODO: sanity check flags (ISPOW2) */
+
+ e = get_empty_event();
+
+ e->thread_id = GetCurrentThreadId();
+ e->time_ticks = GetTickCount();
+ GetSystemTimeAsFileTime(&e->time_ft);
+
+ e->severity = severity;
+ e->short_desc = short_desc;
+ e->facility = facility;
+ e->location = location;
+ e->long_desc = long_desc;
+ e->suggestion = suggestion;
+ e->facility_id = facility_id;
+ e->suggestion_id = suggestion_id;
+ e->p1 = p1;
+ e->p2 = p2;
+ e->p3 = p3;
+ e->p4 = p4;
+ e->flags = flags;
+#ifdef _WIN32
+ e->h_module = h_module;
+#endif
+
+ EnterCriticalSection(&cs_error);
+ c = peek_context();
+
+ if(!c) {
+ /* the reason why we are doing it this way is because p1..p4,
+ the descriptions and the suggestion may contain allocations
+ that has to be freed. */
+ free_event(e);
+ e = NULL;
+ } else {
+ add_event(c,e);
+ }
+
+ LeaveCriticalSection(&cs_error);
+
+ return e;
+}
+
+KHMEXP void KHMAPI kherr_suggest(wchar_t * suggestion,
+ enum kherr_suggestion suggestion_id,
+ khm_int32 flags) {
+ kherr_context * c;
+ kherr_event * e;
+ DWORD tid;
+
+ if (flags != KHERR_RF_CSTR_SUGGEST &&
+ flags != KHERR_RF_RES_SUGGEST &&
+ flags != KHERR_RF_MSG_SUGGEST &&
+ flags != KHERR_RF_FREE_SUGGEST)
+ return;
+
+ c = peek_context();
+ if(!c)
+ return;
+
+ tid = GetCurrentThreadId();
+
+ EnterCriticalSection(&cs_error);
+ e = QBOTTOM(c);
+ while (e != NULL && e->thread_id != tid)
+ e = QPREV(e);
+
+ if(!e)
+ goto _exit;
+
+ /* if strings have already been resolved in this event, we cant
+ add any more unresolved strings. */
+ if ((flags == KHERR_RF_RES_SUGGEST ||
+ flags == KHERR_RF_MSG_SUGGEST) &&
+ (e->flags & KHERR_RF_STR_RESOLVED))
+ goto _exit;
+
+ e->suggestion = suggestion;
+ e->suggestion_id = suggestion_id;
+ e->flags |= flags;
+_exit:
+ LeaveCriticalSection(&cs_error);
+}
+
+KHMEXP void KHMAPI kherr_location(wchar_t * location) {
+ kherr_context * c;
+ kherr_event * e;
+ DWORD tid;
+
+ c = peek_context();
+ if(!c)
+ return;
+ tid = GetCurrentThreadId();
+
+ EnterCriticalSection(&cs_error);
+ e = QBOTTOM(c);
+ while (e != NULL && e->thread_id != tid)
+ e = QPREV(e);
+
+ if(!e)
+ goto _exit;
+ e->location = location;
+_exit:
+ LeaveCriticalSection(&cs_error);
+}
+
+KHMEXP void KHMAPI kherr_facility(wchar_t * facility,
+ khm_int32 facility_id) {
+ kherr_context * c;
+ kherr_event * e;
+ DWORD tid;
+
+ c = peek_context();
+ if(!c)
+ return;
+ tid = GetCurrentThreadId();
+ EnterCriticalSection(&cs_error);
+ e = QBOTTOM(c);
+ while (e != NULL && e->thread_id != tid)
+ e = QPREV(e);
+
+ if(!e)
+ goto _exit;
+ e->facility = facility;
+ e->facility_id = facility_id;
+_exit:
+ LeaveCriticalSection(&cs_error);
+}
+
+KHMEXP void KHMAPI kherr_set_desc_event(void) {
+ kherr_context * c;
+ kherr_event * e;
+ DWORD tid;
+
+ c = peek_context();
+ if(!c)
+ return;
+ tid = GetCurrentThreadId();
+
+ EnterCriticalSection(&cs_error);
+ e = QBOTTOM(c);
+ while (e != NULL && e->thread_id != tid)
+ e = QPREV(e);
+
+ if(!e || c->desc_event)
+ goto _exit;
+
+ QDEL(c,e);
+ c->desc_event = e;
+ e->severity = KHERR_NONE;
+ resolve_event_strings(e);
+
+ notify_ctx_event(KHERR_CTX_DESCRIBE, c);
+
+_exit:
+ LeaveCriticalSection(&cs_error);
+}
+
+KHMEXP void KHMAPI kherr_del_last_event(void) {
+ kherr_context * c;
+ kherr_event * e;
+ DWORD tid;
+
+ c = peek_context();
+
+ if(!c)
+ return;
+
+ tid = GetCurrentThreadId();
+
+ EnterCriticalSection(&cs_error);
+ e = QBOTTOM(c);
+ while (e != NULL && e->thread_id != tid)
+ e = QPREV(e);
+
+ if(e) {
+ QDEL(c, e);
+ if(c->err_event == e) {
+ pick_err_event(c);
+ }
+ free_event(e);
+ }
+ LeaveCriticalSection(&cs_error);
+}
+
+KHMEXP void KHMAPI kherr_push_context(kherr_context * c)
+{
+ kherr_context * p;
+ int new_context = FALSE;
+
+ EnterCriticalSection(&cs_error);
+ p = peek_context();
+ if(p && (c->flags & KHERR_CF_UNBOUND)) {
+ LDELETE(&ctx_root_list, c);
+ TADDCHILD(p,c);
+ c->flags &= ~KHERR_CF_UNBOUND;
+ kherr_hold_context(p);
+ new_context = TRUE;
+ }
+ push_context(c);
+
+ if (new_context)
+ notify_ctx_event(KHERR_CTX_BEGIN, c);
+
+ LeaveCriticalSection(&cs_error);
+}
+
+KHMEXP void KHMAPI kherr_push_new_context(khm_int32 flags)
+{
+ kherr_context * p;
+ kherr_context * c;
+
+ flags &= KHERR_CFMASK_INITIAL;
+
+ EnterCriticalSection(&cs_error);
+ p = peek_context();
+ c = get_empty_context();
+ if(p) {
+ LDELETE(&ctx_root_list, c);
+ TADDCHILD(p,c);
+ c->flags &= ~KHERR_CF_UNBOUND;
+ kherr_hold_context(p);
+ }
+ c->flags |= flags;
+ push_context(c);
+
+ notify_ctx_event(KHERR_CTX_BEGIN, c);
+
+ LeaveCriticalSection(&cs_error);
+}
+
+kherr_param dup_parm(kherr_param p) {
+ if(parm_type(p) == KEPT_STRINGT) {
+ wchar_t * d = PWCSDUP((wchar_t *)parm_data(p));
+ return kherr_val(KEPT_STRINGT, (khm_ui_8) d);
+ } else
+ return p;
+}
+
+kherr_event * fold_context(kherr_context * c) {
+ kherr_event * e;
+ kherr_event * g;
+
+ if (!c)
+ return NULL;
+
+ EnterCriticalSection(&cs_error);
+ if(!c->err_event || (c->flags & KHERR_CF_DIRTY)) {
+ pick_err_event(c);
+ }
+ if(c->err_event) {
+ g = c->err_event;
+ e = get_empty_event();
+ *e = *g;
+ g->short_desc = NULL;
+ g->long_desc = NULL;
+ g->suggestion = NULL;
+ g->flags &=
+ ~(KHERR_RF_FREE_SHORT_DESC |
+ KHERR_RF_FREE_LONG_DESC |
+ KHERR_RF_FREE_SUGGEST);
+ LINIT(e);
+ e->p1 = dup_parm(g->p1);
+ e->p2 = dup_parm(g->p2);
+ e->p3 = dup_parm(g->p3);
+ e->p4 = dup_parm(g->p4);
+ } else {
+ e = c->desc_event;
+ c->desc_event = NULL;
+ }
+
+ if (e)
+ e->flags |= KHERR_RF_CONTEXT_FOLD;
+
+ LeaveCriticalSection(&cs_error);
+
+ return e;
+}
+
+KHMEXP void KHMAPI kherr_hold_context(kherr_context * c) {
+ assert(c && c->magic == KHERR_CONTEXT_MAGIC);
+ EnterCriticalSection(&cs_error);
+ c->refcount++;
+ LeaveCriticalSection(&cs_error);
+}
+
+KHMEXP void KHMAPI kherr_release_context(kherr_context * c) {
+ assert(c && c->magic == KHERR_CONTEXT_MAGIC);
+ EnterCriticalSection(&cs_error);
+ c->refcount--;
+ if (c->refcount == 0) {
+ kherr_event * e;
+ kherr_context * p;
+
+ e = QBOTTOM(c);
+ if (e && !(e->flags & KHERR_RF_COMMIT)) {
+ notify_ctx_event(KHERR_CTX_EVTCOMMIT, c);
+ e->flags |= KHERR_RF_COMMIT;
+ }
+
+ notify_ctx_event(KHERR_CTX_END, c);
+
+ p = TPARENT(c);
+ if (p) {
+ e = fold_context(c);
+ if (e)
+ add_event(p, e);
+
+ TDELCHILD(p, c);
+ kherr_release_context(p);
+ } else {
+ LDELETE(&ctx_root_list, c);
+ }
+ free_context(c);
+ }
+ LeaveCriticalSection(&cs_error);
+}
+
+KHMEXP void KHMAPI kherr_pop_context(void) {
+ kherr_context * c;
+
+ EnterCriticalSection(&cs_error);
+ c = pop_context();
+ if(c) {
+ kherr_release_context(c);
+ }
+ LeaveCriticalSection(&cs_error);
+}
+
+KHMEXP kherr_context * KHMAPI kherr_peek_context(void) {
+ kherr_context * c;
+
+ c = peek_context();
+ if (c)
+ kherr_hold_context(c);
+
+ return c;
+}
+
+KHMEXP khm_boolean KHMAPI kherr_is_error(void) {
+ kherr_context * c = peek_context();
+ return kherr_is_error_i(c);
+}
+
+KHMEXP khm_boolean KHMAPI kherr_is_error_i(kherr_context * c) {
+ if(c && c->severity <= KHERR_ERROR)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+KHMEXP void KHMAPI kherr_clear_error(void) {
+ kherr_context * c = peek_context();
+ if (c)
+ kherr_clear_error_i(c);
+}
+
+KHMEXP void KHMAPI kherr_clear_error_i(kherr_context * c) {
+ kherr_event * e;
+ if (c) {
+ EnterCriticalSection(&cs_error);
+ e = QTOP(c);
+ while(e) {
+ e->flags |= KHERR_RF_INERT;
+ e = QNEXT(e);
+ }
+ c->severity = KHERR_NONE;
+ c->err_event = NULL;
+ c->flags &= ~KHERR_CF_DIRTY;
+ LeaveCriticalSection(&cs_error);
+ }
+}
+
+KHMEXP void KHMAPI kherr_set_progress(khm_ui_4 num, khm_ui_4 denom) {
+ kherr_context * c = peek_context();
+ if(c) {
+ EnterCriticalSection(&cs_error);
+ c->progress_denom = denom;
+ c->progress_num = num;
+ LeaveCriticalSection(&cs_error);
+ }
+}
+
+KHMEXP void KHMAPI kherr_get_progress(khm_ui_4 * num, khm_ui_4 * denom) {
+ kherr_context * c = peek_context();
+ kherr_get_progress_i(c,num,denom);
+}
+
+KHMEXP void KHMAPI kherr_get_progress_i(kherr_context * c,
+ khm_ui_4 * num,
+ khm_ui_4 * denom) {
+ if(c) {
+ EnterCriticalSection(&cs_error);
+ *num = c->progress_num;
+ *denom = c->progress_denom;
+ LeaveCriticalSection(&cs_error);
+ } else {
+ *num = 0;
+ *denom = 0;
+ }
+}
+
+KHMEXP kherr_event * KHMAPI kherr_get_first_event(kherr_context * c)
+{
+ kherr_event * e;
+ EnterCriticalSection(&cs_error);
+ e = QTOP(c);
+ LeaveCriticalSection(&cs_error);
+ return e;
+}
+
+KHMEXP kherr_event * KHMAPI kherr_get_next_event(kherr_event * e)
+{
+ kherr_event * ee;
+
+ EnterCriticalSection(&cs_error);
+ ee = QNEXT(e);
+ LeaveCriticalSection(&cs_error);
+ return ee;
+}
+
+KHMEXP kherr_event * KHMAPI kherr_get_prev_event(kherr_event * e)
+{
+ kherr_event * ee;
+
+ EnterCriticalSection(&cs_error);
+ ee = QPREV(e);
+ LeaveCriticalSection(&cs_error);
+
+ return ee;
+}
+
+KHMEXP kherr_event * KHMAPI kherr_get_last_event(kherr_context * c)
+{
+ kherr_event * e;
+ EnterCriticalSection(&cs_error);
+ e = QBOTTOM(c);
+ LeaveCriticalSection(&cs_error);
+ return e;
+}
+
+KHMEXP kherr_context * KHMAPI kherr_get_first_context(kherr_context * c)
+{
+ kherr_context * cc;
+
+ EnterCriticalSection(&cs_error);
+ if (c) {
+ cc = TFIRSTCHILD(c);
+ if (cc)
+ kherr_hold_context(cc);
+ } else {
+ cc = ctx_root_list;
+ if (cc)
+ kherr_hold_context(cc);
+ }
+ LeaveCriticalSection(&cs_error);
+ return cc;
+}
+
+KHMEXP kherr_context * KHMAPI kherr_get_next_context(kherr_context * c)
+{
+ kherr_context * cc;
+ EnterCriticalSection(&cs_error);
+ cc = LNEXT(c);
+ if (cc)
+ kherr_hold_context(cc);
+ LeaveCriticalSection(&cs_error);
+ return cc;
+}
+
+KHMEXP kherr_event * KHMAPI kherr_get_err_event(kherr_context * c)
+{
+ kherr_event * e;
+ EnterCriticalSection(&cs_error);
+ if(!c->err_event) {
+ pick_err_event(c);
+ }
+ e = c->err_event;
+ LeaveCriticalSection(&cs_error);
+ return e;
+}
+
+KHMEXP kherr_event * KHMAPI kherr_get_desc_event(kherr_context * c)
+{
+ kherr_event * e;
+
+ EnterCriticalSection(&cs_error);
+ e = c->desc_event;
+ LeaveCriticalSection(&cs_error);
+ return e;
+}
+
+KHMEXP kherr_param kherr_dup_string(const wchar_t * s)
+{
+ wchar_t * dest;
+ size_t cb_s;
+
+ if (s == NULL)
+ return _vnull();
+
+ if (FAILED(StringCbLength(s, KHERR_MAXCB_STRING, &cb_s)))
+ cb_s = KHERR_MAXCB_STRING;
+ else
+ cb_s += sizeof(wchar_t);
+
+ dest = PMALLOC(cb_s);
+ assert(dest != NULL);
+ dest[0] = L'\0';
+
+ StringCbCopy(dest, cb_s, s);
+
+ return _tstr(dest);
+}
+
+
+#if 0
+KHMEXP kherr_param kherr_val(khm_octet ptype, khm_ui_8 pvalue) {
+ kherr_param p;
+ p.type = ptype;
+ p.data = pvalue;
+
+ return p;
+}
+#endif
diff --git a/src/windows/identity/kherr/kherr.h b/src/windows/identity/kherr/kherr.h
index 7950587646..fff3d5031e 100644
--- a/src/windows/identity/kherr/kherr.h
+++ b/src/windows/identity/kherr/kherr.h
@@ -1,1094 +1,1094 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#ifndef __KHIMAIRA_KHERR_H
-#define __KHIMAIRA_KHERR_H
-
-/*! \defgroup kherr NetIDMgr Error Reporting
-
- Error reporting functions provide a mechanism to construct
- meaningful and user friendly error reports for the user.
-
- Unlike most of the other NetIDMgr API's, the error reporting APIs
- are lightweight and usually do not return an error value. This is
- mostly because, these functions are called \b after an error
- occurs.
-
- @{*/
-#include<khdefs.h>
-#include<khlist.h>
-
-/*! \name Customizable macros
-@{ */
-#ifndef KHERR_FACILITY
-/*! \brief The default facility when reporting errors
-
- When including this header file, if the KHERR_FACILITY macro is
- defined to be a wide character string, then it will be used as the
- default facility when for the convenience macros. All of the
- calls to the convenience macros in the source file would then have
- that facility.
-
- If left undefined, the convenience macros will leave the facility
- value undefined.
- */
-#define KHERR_FACILITY NULL
-#endif
-
-#ifndef KHERR_FACILITY_ID
-/*! \brief The default facility ID when reporting errors
-
- When including this header file, if the KHERR_FACILITY_ID macro is
- defined to be non-zero, then it will be used as the default
- facility identifier for the convenience macros. All of the calls
- to the convenience macros in the source file would then have that
- facility identifier.
-
- The default value of 0 means that the facility is undefined.
- */
-#define KHERR_FACILITY_ID 0
-#endif
-
-/*! \define KHERR_HMODULE (undefined)
- \brief The default module handle
-
- When including this header file, if the KHERR_HMODULE macro is
- defined to be an identifier that holds the module handle, then the
- convenience macros that specify a module handle will use it.
-
- A default value is not defined for KHERR_HMODULE. Any attempt to
- invoke any of the convenience macros that use it should generate a
- compile time error.
- */
-#ifdef _WIN32
-#ifndef KHERR_HMODULE
-#endif
-#endif
-/*@}*/
-
-/*! \brief Parameter types
- */
-enum kherr_parm_types {
- KEPT_NONE = 0,
- KEPT_INT32 = 1,
- KEPT_UINT32,
- KEPT_INT64,
- KEPT_UINT64,
- KEPT_STRINGC, /*!< String constant */
- KEPT_STRINGT, /*!< String. Will be freed using
- free() when the event is freed */
- KEPT_PTR /*!< Pointer type. */
-};
-
-
-typedef struct tag_kherr_param {
- khm_octet type;
- khm_ui_8 data;
-} kherr_param;
-
-/*! \brief Severity levels
-
- Larger the value, the less severe it is.
-*/
-enum tag_kherr_severity {
- KHERR_FATAL = 0, /*!< Fatal error.*/
- KHERR_ERROR, /*!< Non-fatal error. We'll probably
- survive. See the suggested action. */
- KHERR_WARNING, /*!< Warning. Something almost broke
- or soon will. See the suggested
- action. */
- KHERR_INFO, /*!< Informational. Something happened
- that we would like you to know
- about. */
- KHERR_DEBUG_1 = 64, /*!< Verbose debug level 1 (high)
- Events at this severity level are
- not required to be based on
- localized strings. */
- KHERR_DEBUG_2 = 65, /*!< Verbose debug level 2 (medium)
- Events at this severity level are
- not required to be based on
- localized strings. */
- KHERR_DEBUG_3 = 66, /*!< Verbose debug level 3 (low)
- Events at this severity level are
- not required to be based on
- localized strings. */
- KHERR_RESERVED_BANK = 127, /*!< Internal use */
- KHERR_NONE = 128 /*!< Nothing interesting has happened
- so far */
-};
-
-typedef enum tag_kherr_severity kherr_severity;
-
-/*! \brief Suggestions */
-enum tag_kherr_suggestion {
- KHERR_SUGGEST_NONE = 0, /*!< No suggestions. */
- KHERR_SUGGEST_ABORT, /*!< Abort whatever it was you were
- trying. It's not gonna work. */
- KHERR_SUGGEST_RETRY, /*!< Retry. It might work the second
- or third time over */
- KHERR_SUGGEST_IGNORE, /*!< Ignore. It might go away. */
- KHERR_SUGGEST_INTERACT, /*!< Further user interaction is
- necessary to resolve the situation.
- The suggest string in the event
- should be prompted to the user. */
- KHERR_SUGGEST_OTHER, /*!< Something else. */
-};
-
-typedef enum tag_kherr_suggestion kherr_suggestion;
-
-/*! \brief An event */
-typedef struct tag_kherr_event {
- khm_int32 magic; /*!< Magic number. Always set to
- KHERR_EVENT_MAGIC */
- DWORD thread_id; /*!< The thread which reported this
- event. */
- const wchar_t * short_desc; /*!< Short description or title
- (localized) */
- const wchar_t * facility; /*!< Facility name of the reporter
- (not localized) */
- const wchar_t * location; /*!< Location. Usually the function
- name or such of where the event
- occured (not localized) */
- const wchar_t * long_desc; /*!< A long description of what went
- wrong (localized, formatted) */
- const wchar_t * suggestion; /*!< A suggested way to fix it
- (localized,formatted) */
-
- kherr_severity severity;
- /*!< Severity level. One of the
- severity levels listed in
- enumeration ::kherr_severity */
- khm_int32 facility_id; /*!< Left to the application to
- interpret */
- kherr_suggestion suggestion_id;
- /*!< One of the suggestion ID's from
- the enumeration
- ::kherr_suggestion */
-
- int flags; /*!< Flags. */
-
- kherr_param p1; /*!< Parameter 1 for formatting */
- kherr_param p2; /*!< Parameter 2 for formatting */
- kherr_param p3; /*!< Parameter 3 for formatting */
- kherr_param p4; /*!< Parameter 4 for formatting */
-
- DWORD time_ticks; /*!< Time at which event was reported
- (as returned by GetTickCount(). */
- FILETIME time_ft; /*!< Time at which event was reported.
- Current system time as FILETIME. */
-
-#ifdef _WIN32
- HMODULE h_module; /*!< Handle to the module which should
- resolve any unresolved resources
- references above. */
-#endif
-
- LDCL(struct tag_kherr_event);
-} kherr_event;
-
-#define KHERR_EVENT_MAGIC 0x0423e84f
-
-/*! \brief Flags for kherr_event
-
- Each set of flags that define the type of resource for one value
- is mutually exclusive.
- */
-enum kherr_event_flags {
- KHERR_RF_CSTR_SHORT_DESC= 0x00000000,
- /*!< Short description is a constant
- string */
- KHERR_RF_RES_SHORT_DESC = 0x00000001,
- /*!< Short description is a string
- resource */
- KHERR_RF_MSG_SHORT_DESC = 0x00000002,
- /*!< Short description is a message
- resource */
- KHERR_RF_FREE_SHORT_DESC= 0x00000004,
- /*!< Short description is an allocated
- string */
- KHERR_RFMASK_SHORT_DESC = 0x00000007,
-
- KHERR_RF_CSTR_LONG_DESC = 0x00000000,
- /*!< Long description is a constant
- string */
- KHERR_RF_RES_LONG_DESC = 0x00000008,
- /*!< Long description is a string
- resource */
- KHERR_RF_MSG_LONG_DESC = 0x00000010,
- /*!< Long description is a message
- resouce */
- KHERR_RF_FREE_LONG_DESC = 0x00000020,
- /*!< Long description is an allocated
- string */
- KHERR_RFMASK_LONG_DESC = 0x00000038,
-
- KHERR_RF_CSTR_SUGGEST = 0x00000000,
- /*!< Suggestion is a constant
- string */
- KHERR_RF_RES_SUGGEST = 0x00000040,
- /*!< Suggestion is a string
- resource */
- KHERR_RF_MSG_SUGGEST = 0x00000080,
- /*!< Suggestion is a message
- resource */
- KHERR_RF_FREE_SUGGEST = 0x00000100,
- /*!< Suggestion is an allocated
- string */
- KHERR_RFMASK_SUGGEST = 0x000001C0,
-
- KHERR_RF_STR_RESOLVED = 0x00010000,
- /*!< The string resources in the event
- have been resolved. */
- KHERR_RF_CONTEXT_FOLD = 0x00020000,
- /*!< The event is a representation of
- a folded context. */
-
- KHERR_RF_INERT = 0x00040000,
- /*!< Inert event. The event has
- already been dealt with and is no
- longer considered significant. */
- KHERR_RF_COMMIT = 0x00080000
- /*!< Committed event. The commit
- handlers for this event have already
- been called. */
-};
-
-/*! \brief Serial number for error contexts */
-typedef khm_ui_4 kherr_serial;
-
-/*! \brief An error context
-*/
-typedef struct tag_kherr_context {
- khm_int32 magic; /*!< Magic number. Always set to
- KHERR_CONTEXT_MAGIC */
-
- kherr_serial serial; /*!< Context instance serial number.
- Context objects themselves may be
- reused for different contexts as
- they are freed and reallocated.
- However every instance of a context
- is guaranteed to have a unique
- serial number as specified in this
- field. If an external entity wants
- to keep track of the context, it
- should keep track of the serial
- number as well as the pointer to the
- context object. */
-
- kherr_severity severity;
- /*!< Severity level. One of the
- severity levels listed below. This
- is the severity level of the context
- and is the maximum severity level of
- all the events in the queue of
- events. */
-
- khm_int32 flags; /*!< Flags. Used internally. */
- khm_ui_4 refcount; /*!< Reference count. Used
- internally */
-
- kherr_event *desc_event; /*!< Description event. The event that
- describes the error context. This
- points to an event that is not in
- the event queue. */
-
- kherr_event *err_event; /*!< Significant event. The last one
- that caused the severity level to be
- what it is right now. This points
- to an event that is listed in the
- event queue for this context.*/
-
- khm_ui_4 progress_num; /*!< Progress numerator */
- khm_ui_4 progress_denom; /*!< Progress denominator */
-
- TDCL(struct tag_kherr_context);
- QDCL(struct tag_kherr_event);
-} kherr_context;
-
-#define KHERR_CONTEXT_MAGIC 0x34f3238c
-
-enum kherr_context_flags {
- KHERR_CF_NONE = 0x00000000,
- /*!< None. */
-
- KHERR_CF_DIRTY = 0x00000001,
- /*!< Used Internally. Denotes that
- the err_event and severity may need
- to be recalculated. Cannot be set
- as an initial flag. */
-
- KHERR_CF_OWN_PROGRESS = 0x00000002,
- /*!< The context maintains its own
- progress meter as opposed to one
- that is derived from child
- contexts. */
-
- KHERR_CF_UNBOUND = 0x00000004,
- /*!< Unbound context. The context
- can't be used to log events. Call
- kherr_push_context() to associate
- the context with the global context
- hierarchy. Cannot be set as an
- initial flag. */
-
- KHERR_CF_TRANSITIVE = 0x00000008,
- /*!< Transitive. The context is
- automatically made the current
- context for all other threads that
- handle messages sent or posted by
- threads whose current error context
- is this one. */
-
- KHERR_CFMASK_INITIAL = 0x0000000a,
- /*!< Allowed initial flags */
-};
-
-/*! \brief Maximum length of a string field in characters including terminating NULL
- */
-#define KHERR_MAXCCH_STRING 1024
-
-/*! \brief Maximum length of a string field in bytes including terminating NULL
- */
-#define KHERR_MAXCB_STRING (KHERR_MAXCCH_STRING * sizeof(wchar_t))
-
-/*! \brief Context event
-
- \see kherr_add_ctx_handler()
-*/
-enum kherr_ctx_event {
- KHERR_CTX_BEGIN = 0x0001, /*!< A new context was created */
- KHERR_CTX_DESCRIBE=0x0002, /*!< A context was described */
- KHERR_CTX_END = 0x0004, /*!< A context was closed */
- KHERR_CTX_ERROR = 0x0008, /*!< A context switched to an error
- state */
- KHERR_CTX_EVTCOMMIT = 0x0010 /*!< A event was committed into the
- context */
-};
-
-/*! \brief Context event handler
-
- Context event handlers are invoked when specific events occur with
- respect to an error context. The ::kherr_ctx_event parameter
- specifies which event occurred using one of the event values
- described in the enumeration. The error context in which this
- event occurred is specified by the ::kherr_context pointer.
-
- Note that if the handler needs to keep track of the error context
- for later processing, it also needs to keep track of the \a serial
- field of the error context. The same context object may be
- reused, but the serial number is guaranteed to be unique.
-
- \see kherr_add_ctx_handler()
- */
-typedef void (KHMAPI * kherr_ctx_handler)(enum kherr_ctx_event,
- kherr_context *);
-
-/*! \brief Add a context event handler
-
- An application can register an event handler that gets notified of
- events that pertain to error contexts. More than one handler can
- be registered. The order in which the handlers are called is
- undefined for any specific event.
-
- These event occur in the context of individual application
- threads. The handler will be called from within the thread that
- caused the event. Therefore it is important that the handler is
- both reentrant and returns quickly.
-
- The events that the handler will be notified of are explained
- below:
-
- <b>KHERR_CTX_BEGIN</b>: Notification that a new context was
- created. A pointer to the context will be supplied to the
- handler. The supplied pointer should not be used to obtain a hold
- on the context, as it will prevent the context from being closed.
-
- <b>KHERR_CTX_DESCRIBE</b>: The thread called
- kherr_set_desc_event() to set the description of a context. Once
- again, the pointer should not be used to obtain a hold on the
- context.
-
- <b>KHERR_CTX_ERROR</b>: The last event that was reported for the
- context was an error event (the severity was was equal or higher
- than KHERR_ERROR). The pointer may be used to obtain a hold on
- the context. However, it is the application's resonsibility to
- make sure that the hold is released later. Otherwise the event
- will never be closed.
-
- <b>KHERR_CTX_END</b>: Closure. This event is signalled when the
- last open handle to the context is closed and there is no thread
- that is currently active which has this context in its error
- context stack. At the time the handler is invoked, the context is
- still intact. The pointer that is supplied should not be used to
- obtain a handle on the context.
-
- <b>KHERR_CTX_EVTCOMMIT</b>: An event was committed into the error
- context. An event is committed when another event is reported
- after the event, or if the context is closed. Since the last
- event that is reported can still be modified by adding new
- information, the event remains open until it is no longer the last
- event or the context is no longer active. When this notification
- is received, the last event in the context's event queue is the
- event that was committed.
-
- \param[in] h Context event handler, of type ::kherr_ctx_handler
-
- \param[in] filter A combination of ::kherr_ctx_event values
- indication which notifications should be sent to the handler.
- If a \a filter value of zero is provided, all of the events
- will be sent to the handler.
-
- \param[in] serial The serial number of the error context that
- should be tracked. If this is zero, all error contexts can
- trigger the handler.
- */
-KHMEXP void KHMAPI kherr_add_ctx_handler(kherr_ctx_handler h,
- khm_int32 filter,
- kherr_serial serial);
-
-/*! \brief Remove a context event handler
-
- Undoes what was done with kherr_add_ctx_handler()
-
- \see kherr_add_ctx_handler()
- */
-KHMEXP void KHMAPI kherr_remove_ctx_handler(kherr_ctx_handler h,
- kherr_serial serial);
-
-
-/*! \brief Report an error
-
- Creates an event, fills in the details specified in the arguments,
- and adds it to the current error context.
-
- If the current thread does not have an error context, no reporting
- happens. However, if any of the supplied strings or parameters
- are marked as allocated, they will be freed before the function
- returns.
-
- Certain parameters that expect strings can instead be given string
- resources, message resources or allocated strings in addition to
- constant string. By default, the parameters are expected to be
- constant strings.
-
- <b>Allocated strings</b>: The application can allocate memory for
- a string. Since the application is not notified when the event is
- no longer used and freed, it \b must indicate that the string is
- an allocated string by setting the appropriate flag in the \a
- flags parameter. When the event is no longer used, the memory
- pointed to by the relevant pointer will be freed through a call to
- free(). Not all string parameters take allocated strings. See
- individual parameter documentation for details.
-
- <b>String resources</b>: On WIN32, string resources can be passed
- in to kherr_report() using the MAKEINTRESOURCE macro. However,
- the application \b must specify that the parameter is a string
- resource using the appropriate flag in the \a flags parameter.
- The error reporting engine will expand the string against the
- module handle passed in the \a h_module parameter when the value
- of the string is required. Not all string parameters take string
- resources. See individual parameter documentation for details.
- Strings loaded through string resources cannot be longer than
- ::KHERR_MAXCCH_STRING in characters inclusive of terminating NULL.
-
- <b>Message resources</b>: On WIN32, message resources can be
- passed in to kherr_report() by specifying the message ID where it
- ordinarily expects a pointer to a constant string. The
- application \b must indicate that the string is a message resource
- by using the appropriate flag in the \a flags parameter. When the
- value of the string is needed, it is expanded against the module
- handle passed in the \a h_module parameter using the message ID.
- Not all string parameters take message resources. See individual
- parameter documentation for details. Note that the facility and
- severity values associated with a message resource are ignored.
- Strings loaded through message resources cannot be longer than
- ::KHERR_MAXCCH_STRING in characters inclusive of terminating NULL.
-
- <b>Formatted fields</b>: Parameters that are formatted can have
- can have parameter inserts like in printf(). However, specifying
- inserts is different from printf() and follows the conventions
- used in WIN32 API FormatMessage(). This is because for localized
- strings, the order of the parameters in the string may be
- different. See the documentation for FormatMessage() for details
- on the format string. The same set of parameters (i.e. \a p1, \a
- p2, \a p3, \a p4) is used for all formatted strings with
- appropriate marshalling for 64 bit types. The size of the string
- after expansion must not exceed 65536 bytes inclusive of
- terminating NULL.
-
- \param[in] severity One of ::kherr_severity_level
- \param[in] short_desc Short description or title (localized). Can
- be a string resource, message resource, allocated string or
- constant string. The \a flags parameter should indicate the
- type of string used.
- \param[in] facility Facility name of the reporter (not localized)
- \param[in] location Usually the function name or such of where the
- event occured (not localized)
- \param[in] long_desc Long description of event (localized,
- formatted). Can be a string resource, message resource,
- allocated string or constant string. The \a flags parameter
- should indicate the type of string used.
- \param[in] suggestion Suggested action to correct situation, if
- applicable (localized). Can be a string resource, message
- resource, allocated string or constant string. The \a flags
- parameter should indicate the type of string used.
- \param[in] facility_id Identifier of facility. Application
- defined.
- \param[in] suggestion_id One of the suggestion identifiers from
- ::kherr_suggestion_ids
- \param[in] p1 First parameter. Used for formatting.
- \param[in] p2 Second parameter. Used for formatting.
- \param[in] p3 Third parameter. Used for formatting.
- \param[in] p4 Fourth parameter. Used for formatting.
- \param[in] flags Flags. See ::kherr_report_flags
- \param[in] h_module Handle to a module that resolves any string or
- message resources used for the \a short_description , \a
- long_desc or \a suggestion parameters. This parameter is only
- available on WIN32.
-
- \note With the exception of parameters of type KEPT_STRINGT and
- parameters which are flagged for freeing using the \a flags
- parameter, all other string parameters are assumed to be
- pointers to constant strings. The strings are not copied and
- the pointers are used as is. Also, no clean-up is performed
- when the event is freed other than that implied by \a flags.
- */
-KHMEXP kherr_event * KHMAPI kherr_report(
- enum kherr_severity severity,
- const wchar_t * short_desc,
- const wchar_t * facility,
- const wchar_t * location,
- const wchar_t * long_desC,
- const wchar_t * suggestion,
- khm_int32 facility_id,
- enum kherr_suggestion suggestion_id,
- kherr_param p1,
- kherr_param p2,
- kherr_param p3,
- kherr_param p4,
- khm_int32 flags
-#ifdef _WIN32
- ,HMODULE h_module
-#endif
-);
-
-/*! \brief Report a formatted message
-
- The format string \a long_desc_fmt should be a string constant and
- the format specifiers follow that of \a sprintf. This creates an
- event with the long description set to the expansion of the format
- string against the arguments.
- */
-KHMEXP kherr_event * __cdecl
-kherr_reportf_ex(enum kherr_severity severity,
- const wchar_t * facility,
- khm_int32 facility_id,
-#ifdef _WIN32
- HMODULE hModule,
-#endif
- const wchar_t * long_desc_fmt,
- ...);
-#define _reportf_ex kherr_reportf_ex
-
-/*! \brief Report a formatted message
-
- The format string \a long_desc_fmt should be a string constant and
- the format specifiers follow that of \a sprintf. This creates an
- event with the long description set to the expansion of the format
- string against the arguments.
- */
-KHMEXP kherr_event * __cdecl
-kherr_reportf(const wchar_t * long_desc_fmt,
- ...);
-#define _reportf kherr_reportf
-
-/*! \brief Create a parameter out of a transient string
-
- A parameter is created by duplicating the string that is passed
- into the function. If the string exceeds KHERR_MAXCCH_STRING,
- then only the first part of the string that fits within the limit
- is duplicated.
-
- The resulign ::kherr_param must be passed in to kherr_report().
- The event logging framework will free the duplicated string once
- the data is no longer required.
- */
-KHMEXP kherr_param kherr_dup_string(const wchar_t * s);
-
-__inline KHMEXP kherr_param
-kherr_val(khm_octet ptype, khm_ui_8 pvalue) {
- kherr_param p;
-
- p.type = ptype;
- p.data = pvalue;
-
- return p;
-}
-
-#define _int32(i) kherr_val(KEPT_INT32, (khm_ui_8) i)
-#define _uint32(ui) kherr_val(KEPT_UINT32, (khm_ui_8) ui)
-#define _int64(i) kherr_val(KEPT_INT64, (khm_ui_8) i)
-#define _uint64(ui) kherr_val(KEPT_UINT64, (khm_ui_8) ui)
-#define _cstr(cs) kherr_val(KEPT_STRINGC, (khm_ui_8) cs)
-#define _tstr(ts) kherr_val(KEPT_STRINGT, (khm_ui_8) ts)
-#define _cptr(p) kherr_val(KEPT_PTR, (khm_ui_8) p)
-#define _vnull() kherr_val(KEPT_NONE, 0)
-#define _dupstr(s) kherr_dup_string(s)
-
-/* convenience macros for calling kherr_report */
-#ifdef KHERR_HMODULE
-
-#define _report_cs0(severity, long_description) \
- kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_description), NULL, KHERR_FACILITY_ID, 0, _vnull(), _vnull(), _vnull(), _vnull(), 0, KHERR_HMODULE)
-
-#define _report_cs1(severity, long_description, p1) \
- kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_description), NULL, KHERR_FACILITY_ID, 0, p1, _vnull(), _vnull(), _vnull(), 0, KHERR_HMODULE)
-
-#define _report_cs2(severity, long_description, p1, p2) \
- kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_description), NULL, KHERR_FACILITY_ID, 0, p1, p2, _vnull(), _vnull(), 0, KHERR_HMODULE)
-
-#define _report_cs3(severity, long_description, p1, p2, p3) \
- kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_description), NULL, KHERR_FACILITY_ID, 0, p1, p2, p3, _vnull(), 0, KHERR_HMODULE)
-
-#define _report_cs4(severity, long_description, p1, p2, p3, p4) \
- kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_description), NULL, KHERR_FACILITY_ID, 0, p1, p2, p3, p4, 0, KHERR_HMODULE)
-
-#else
-
-#define _report_cs0(severity, long_description) \
- kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_description), NULL, KHERR_FACILITY_ID, 0, _vnull(), _vnull(), _vnull(), _vnull(), 0, NULL)
-
-#define _report_cs1(severity, long_description, p1) \
- kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_description), NULL, KHERR_FACILITY_ID, 0, p1, _vnull(), _vnull(), _vnull(), 0, NULL)
-
-#define _report_cs2(severity, long_description, p1, p2) \
- kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_description), NULL, KHERR_FACILITY_ID, 0, p1, p2, _vnull(), _vnull(), 0, NULL)
-
-#define _report_cs3(severity, long_description, p1, p2, p3) \
- kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_description), NULL, KHERR_FACILITY_ID, 0, p1, p2, p3, _vnull(), 0, NULL)
-
-#define _report_cs4(severity, long_description, p1, p2, p3, p4) \
- kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_description), NULL, KHERR_FACILITY_ID, 0, p1, p2, p3, p4, 0, NULL)
-#endif /* !defined(KHERR_HMODULE) */
-
-#ifdef _WIN32
-#define _report_sr0(severity, long_desc_id) \
- kherr_report((severity), NULL, KHERR_FACILITY, NULL, MAKEINTRESOURCE(long_desc_id), NULL, KHERR_FACILITY_ID, 0, _vnull(), _vnull(), _vnull(), _vnull(), KHERR_RF_RES_LONG_DESC, KHERR_HMODULE)
-
-#define _report_sr1(severity, long_desc_id, p1) \
- kherr_report((severity), NULL, KHERR_FACILITY, NULL, MAKEINTRESOURCE(long_desc_id), NULL, KHERR_FACILITY_ID, 0, p1, _vnull(), _vnull(), _vnull(), KHERR_RF_RES_LONG_DESC, KHERR_HMODULE)
-
-#define _report_sr2(severity, long_desc_id, p1, p2) \
- kherr_report((severity), NULL, KHERR_FACILITY, NULL, MAKEINTRESOURCE(long_desc_id), NULL, KHERR_FACILITY_ID, 0, p1, p2, _vnull(), _vnull(), KHERR_RF_RES_LONG_DESC, KHERR_HMODULE)
-
-#define _report_sr3(severity, long_desc_id, p1, p2, p3) \
- kherr_report((severity), NULL, KHERR_FACILITY, NULL, MAKEINTRESOURCE(long_desc_id), NULL, KHERR_FACILITY_ID, 0, p1, p2, p3, _vnull(), KHERR_RF_RES_LONG_DESC, KHERR_HMODULE)
-
-#define _report_sr4(severity, long_desc_id, p1, p2, p3, p4) \
- kherr_report((severity), NULL, KHERR_FACILITY, NULL, MAKEINTRESOURCE(long_desc_id), NULL, KHERR_FACILITY_ID, 0, p1, p2, p3, p4, KHERR_RF_RES_LONG_DESC, KHERR_HMODULE)
-#endif
-
-#ifdef _WIN32
-#define _report_mr0(severity, long_desc_msg_id) \
- kherr_report((severity), NULL, KHERR_FACILITY, NULL, (wchar_t *)(long_desc_msg_id), NULL, KHERR_FACILITY_ID, 0, _vnull(), _vnull(), _vnull(), _vnull(), KHERR_RF_MSG_LONG_DESC, KHERR_HMODULE)
-
-#define _report_mr1(severity, long_desc_msg_id, p1) \
- kherr_report((severity), NULL, KHERR_FACILITY, NULL, (wchar_t *)(long_desc_msg_id), NULL, KHERR_FACILITY_ID, 0, p1, _vnull(), _vnull(), _vnull(), KHERR_RF_MSG_LONG_DESC, KHERR_HMODULE)
-
-#define _report_mr2(severity, long_desc_msg_id, p1, p2) \
- kherr_report((severity), NULL, KHERR_FACILITY, NULL, (wchar_t *)(long_desc_msg_id), NULL, KHERR_FACILITY_ID, 0, p1, p2, _vnull(), _vnull(), KHERR_RF_MSG_LONG_DESC, KHERR_HMODULE)
-
-#define _report_mr3(severity, long_desc_msg_id, p1, p2, p3) \
- kherr_report((severity), NULL, KHERR_FACILITY, NULL, (wchar_t *)(long_desc_msg_id), NULL, KHERR_FACILITY_ID, 0, p1, p2, p3, _vnull(), KHERR_RF_MSG_LONG_DESC, KHERR_HMODULE)
-
-#define _report_mr4(severity, long_desc_msg_id, p1, p2, p3, p4) \
- kherr_report((severity), NULL, KHERR_FACILITY, NULL, (wchar_t *)(long_desc_msg_id), NULL, KHERR_FACILITY_ID, 0, p1, p2, p3, p4, KHERR_RF_MSG_LONG_DESC, KHERR_HMODULE)
-#endif
-
-#define _report_ts0(severity, long_desc_ptr) \
- kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_desc_ptr), NULL, KHERR_FACILITY_ID, 0, _vnull(), _vnull(), _vnull(), _vnull(), KHERR_RF_FREE_LONG_DESC, NULL)
-
-#define _report_ts1(severity, long_desc_ptr, p1) \
- kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_desc_ptr), NULL, KHERR_FACILITY_ID, 0, p1, _vnull(), _vnull(), _vnull(), KHERR_RF_FREE_LONG_DESC, NULL)
-
-#define _report_ts2(severity, long_desc_ptr, p1, p2) \
- kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_desc_ptr), NULL, KHERR_FACILITY_ID, 0, p1, p2, _vnull(), _vnull(), KHERR_RF_FREE_LONG_DESC, NULL)
-
-#define _report_ts3(severity, long_desc_ptr, p1, p2, p3) \
- kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_desc_ptr), NULL, KHERR_FACILITY_ID, 0, p1, p2, p3, _vnull(), KHERR_RF_FREE_LONG_DESC, NULL)
-
-#define _report_ts4(severity, long_desc_ptr, p1, p2, p3, p4) \
- kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_desc_ptr), NULL, KHERR_FACILITY_ID, 0, p1, p2, p3, p4, KHERR_RF_FREE_LONG_DESC, NULL)
-
-/*! \brief Set the suggestion and suggestion identifier for the last event
-
- The event that will be modified is the last event reported by the
- calling thread.
- */
-KHMEXP void KHMAPI kherr_suggest(wchar_t * suggestion, khm_int32 suggestion_id, khm_int32 flags);
-#define _suggest_cs(cs,sid) kherr_suggest((cs), (sid), KHERR_RF_CSTR_SUGGEST)
-#define _suggest_ts(ts,sid) kherr_suggest((ts), (sid), KHERR_RF_FREE_SUGGEST)
-#define _suggest_sr(sr,sid) kherr_suggest(MAKEINTRESOURCE(sr), (sid), KHERR_RF_RES_SUGGEST)
-#define _suggest_mr(mr,sid) kherr_suggest((wchar_t *)(DWORD_PTR)(mr), (sid), KHERR_RF_MSG_SUGGEST)
-
-/*! \brief Set the location string for the last event
-
- The event that will be modified is the last event reported by the
- calling thread.
- */
-KHMEXP void KHMAPI kherr_location(wchar_t * location);
-#define _location(l) kherr_location(l)
-
-/*! \brief Set the facility string and identifier for the last event
-
- The event that will be modified is the last event reported by the
- calling thread.
- */
-KHMEXP void KHMAPI kherr_facility(wchar_t * facility, khm_int32 facility_id);
-#define _facility(f,fid) kherr_facility((f),(fid))
-
-/*! \brief Marks the last event as the descriptor event for the current error context
-
- Note that marking an event as the descriptor event has the effect
- of removing the event from event queue. The event will henceforth
- be used as the descriptor for the context. The only effective
- fields of a descriptor event are \a short_desc, \a long_desc, \a
- facility, \a facility_id and the parameters which are used for
- resolving formatted strings in the aforementioned fields.
-
- Upon calling kherr_set_desc_event(), the event will be
- automatically evaluated as if kherr_evaluate_event() was called.
-
- The event that will be referenced is the last event reported by
- the calling thread.
- */
-KHMEXP void KHMAPI kherr_set_desc_event(void);
-#define _describe kherr_set_desc_event
-
-/*! \brief Delete the last event
-
- The event that will be deleted is the last event reported by the
- calling thread.
- */
-KHMEXP void KHMAPI kherr_del_last_event(void);
-#define _del_event kherr_del_last_event
-
-/*! \brief Create a new context
-
- The created context is not bound to any thread or any context
- hierarchy. Hence it cannot be used to capture any events until it
- is used in a call to kherr_push_context().
-
- Release the returned context pointer with a call to
- kherr_release_context().
-
- \param[in] flags Initial flags for the context. Combination of
- ::kherr_context_flags
-
- \note This function is for internal use only.
- */
-KHMEXP kherr_context * KHMAPI kherr_create_new_context(khm_int32 flags);
-
-/*! \brief Obtain a hold on a context */
-KHMEXP void KHMAPI kherr_hold_context(kherr_context * c);
-
-/*! \brief Release a context */
-KHMEXP void KHMAPI kherr_release_context(kherr_context * c);
-
-/*! \brief Push an empty context
-
- Creates an empty context, adds it as a child of the current
- thread's error context. If the current thread does not have an
- error context, then the created error context will be a root level
- context.
-
- The new context will be the current error context for the calling
- thread.
-
- \param[in] flags Initial flags for the context. Combination of
- ::kherr_context_flags
-
- \see kherr_push_new_context() for more information about thread
- specific context stacks.
-
- */
-KHMEXP void KHMAPI kherr_push_new_context(khm_int32 flags);
-#define _begin_task kherr_push_new_context
-
-/*! \brief Push a context
-
- Each thread has a stack of error contexts. The topmost one is
- current. The thread can push or pop contexts on to the stack
- independently of the hierarchy of contexts (the only exception, as
- explained below is when the context that is being pushed is
- unbound).
-
- If the context being pushed by kherr_push_context() is unbound,
- then it will be attached to the current context of the thread as a
- child. Once the new context is pushed to the top of the stack, it
- will become the current context for the thread.
-
- The calling thread must call kherr_pop_context() to remove the
- context from the top of the stack. Each call to
- kherr_push_new_context() or kher_push_context() must have a
- corresponding kherr_pop_context() call.
-
- When the thread terminates, all of the contexts in the thread's
- context stack will be automatically removed.
-
- \see kherr_pop_context()
- */
-KHMEXP void KHMAPI kherr_push_context(kherr_context * c);
-
-/*! \brief Pop a context
-
- Remove the current error context from the thread's context stack.
- If no other open handles exist to the error context, this causes
- the error context to collapse into it's parent context or vanish
- entirely unless the context contains an error.
-
- \see kherr_push_context() for more information about thread
- specific context stacks.
- */
-KHMEXP void KHMAPI kherr_pop_context(void);
-#define _end_task kherr_pop_context
-
-/*! \brief Retrieve the current error context
-
- The returned pointer must be released with a call to
- kherr_release_context().
-*/
-KHMEXP kherr_context * KHMAPI kherr_peek_context(void);
-
-/*! \brief Check if the current error context indicates an error
-
- \return TRUE if there is an error. FALSE otherwise.
- \see kherr_analyze()
- */
-KHMEXP khm_boolean KHMAPI kherr_is_error(void);
-
-/*! \brief Check if an error context indicates an error
-
- \return TRUE if there is an error. FALSE otherwise.
- \see kherr_analyze()
- */
-KHMEXP khm_boolean KHMAPI kherr_is_error_i(kherr_context * c);
-
-/*! \brief Clear the error state of the current context */
-KHMEXP void KHMAPI kherr_clear_error(void);
-
-/*! \brief Clear the error state of an error context */
-KHMEXP void KHMAPI kherr_clear_error_i(kherr_context * c);
-
-/*! \brief Set the progress meter of the current error context
-
- Setting \a denom to zero removes the progress meter.
- */
-KHMEXP void KHMAPI kherr_set_progress(khm_ui_4 num, khm_ui_4 denom);
-#define _progress(num,denom) kherr_set_progress((num),(denom))
-
-/*! \brief Get the progress meter of the current error context
- */
-KHMEXP void KHMAPI kherr_get_progress(khm_ui_4 * num, khm_ui_4 * denom);
-
-/*! \brief Get the progress meter of an error context
- */
-KHMEXP void KHMAPI kherr_get_progress_i(kherr_context * c, khm_ui_4 * num, khm_ui_4 * denom);
-
-/*! \brief Get the first event in a context
-
- The returned pointer is only valid as long as there is a hold on
- \a c. Once the context is released with a call to
- kherr_release_context() all pointers to events in the context
- become invalid.
-
- In addition, the last event in a context may still be "active". A
- thread can still modify the last event as long as the context is
- active.
-
- \see kherr_get_next_event(), kherr_get_prev_event(),
- kherr_get_last_event()
- */
-KHMEXP kherr_event * KHMAPI kherr_get_first_event(kherr_context * c);
-
-/*! \brief Get the next event
-
- Call kherr_get_first_event() to obtain the first event in a
- context. Subsequent calls to kherr_get_next_event() will yield
- other events in the order in which they were reported. The list
- ends when kherr_get_next_event() returns NULL.
-
- The returned pointer is only valid as long as there is a hold on
- \a c. Once the context is released with a call to
- kherr_release_context() all pointers to events in the context
- become invalid.
-
- In addition, the last event in a context may still be "active". A
- thread can still modify the last event as long as the context is
- active.
-
- \see kherr_get_first_event(), kherr_get_prev_event(),
- kherr_get_last_event()
- */
-KHMEXP kherr_event * KHMAPI kherr_get_next_event(kherr_event * e);
-
-/*! \brief Get the previous event
-
- Returns a pointer to the event that was reported in the context
- containing \a e prior to \a e being reported.
-
- The returned pointer is only valid as long as there is a hold on
- the error context. Once the context is released with a call to
- kherr_release_context() all pointers to events in the context
- become invalid.
-
- In addition, the last event in a context may still be "active". A
- thread can still modify the last event as long as the context is
- active.
-
- \see kherr_get_first_event(), kherr_get_next_event(),
- kherr_get_last_event()
- */
-KHMEXP kherr_event * KHMAPI kherr_get_prev_event(kherr_event * e);
-
-/*! \brief Get the last event in an error context
-
- Returns a pointer to the last error event that that was reported
- to the context \a c.
-
- The returned pointer is only valid as long as there is a hold on
- the error context. Once the context is released with a call to
- kherr_release_context(), all pointers to events in the context
- become invalid.
-
- In addtion, the last event in a context may still be "active". A
- thread can still modify the last event as long as the context is
- active.
-
- \see kherr_get_first_event(), kherr_get_next_event(),
- kherr_get_prev_event()
- */
-KHMEXP kherr_event * KHMAPI kherr_get_last_event(kherr_context * c);
-
-/*! \brief Get the first child context of a context
-
- Contexts are arranged in a hiearchy. This function returns the
- first child of an error context. Use kherr_get_next_context() to
- obtain the other contexts. If \a c is \a NULL, this returns the
- first root level context.
-
- The returned pointer must be released with a call to
- kherr_release_context()
- */
-KHMEXP kherr_context * KHMAPI kherr_get_first_context(kherr_context * c);
-
-/*! \brief Get the next sibling context of a context
-
- The returned pointer must be released with a call to
- kherr_release_context()
-
- \see kherr_get_first_context()
- */
-KHMEXP kherr_context * KHMAPI kherr_get_next_context(kherr_context * c);
-
-/*! \brief Get the desciption event for the context
-
- The description event is the event that was denoted using
- kherr_set_desc_event() as the event which describes the context.
-
- The returned pointer is only valid as long as there is a hold on
- \a c. Once the context is released with a call to
- kherr_release_context() all pointers to events in the context
- becomes invalid.
- */
-KHMEXP kherr_event * KHMAPI kherr_get_desc_event(kherr_context * c);
-
-/*! \brief Get the error event for the context
-
- The error event for a context is the last event that had the
- highest severity level.
-
- The returned pointer is only valid as long as there is a hold on
- \a c. Once the context is released with a call to
- kherr_release_context() all pointers to events in the context
- becomes invalid.
- */
-KHMEXP kherr_event * KHMAPI kherr_get_err_event(kherr_context * c);
-
-/*! \brief Evaluate an event
-
- When an event is reported, all the parameters and resource
- references that were passed to kherr_report() are kept as-is until
- the actual string values are required by the error reporting
- library. However, if the string fields are required before then,
- an application can call kherr_evaluate_event() to get them.
-
- This function does the following:
-
- - Load any referenced string or message resources that are
- referenced in the event's short description, long description or
- suggestion.
-
- - Expand any inserts using the parameters that were passed in.
-
- - Free up allocated strings in for the descriptions or suggestion
- fields and any parameters.
-
- - Update the string fields in the event to contain the newly
- generated strings.
-
- */
-KHMEXP void KHMAPI kherr_evaluate_event(kherr_event * e);
-
-/*! \brief Evaluate the last event
-
- Same as kherr_evaluate_event(), but operates on the last event
- logged by the current thread.
-
- \see kherr_evaluate_event()
- */
-KHMEXP void KHMAPI kherr_evaluate_last_event(void);
-#define _resolve kherr_evaluate_last_event
-
-/*! \defgroup kherr_fids Standard Facility IDs
-@{*/
-#define KHM_FACILITY_KMM 1
-#define KHM_FACILITY_KCDB 2
-#define KHM_FACILITY_UI 3
-#define KHM_FACILITY_KRB5 64
-#define KHM_FACILITY_KRB4 65
-#define KHM_FACILITY_AFS 66
-#define KHM_FACILITY_USER 128
-/*@}*/
-
-/*@}*/
-
-/* In debug mode, outputs the formatted string to the debug console */
-#ifdef DEBUG
-KHMEXP void kherr_debug_printf(wchar_t * fmt, ...);
-#endif
-
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __KHIMAIRA_KHERR_H
+#define __KHIMAIRA_KHERR_H
+
+/*! \defgroup kherr NetIDMgr Error Reporting
+
+ Error reporting functions provide a mechanism to construct
+ meaningful and user friendly error reports for the user.
+
+ Unlike most of the other NetIDMgr API's, the error reporting APIs
+ are lightweight and usually do not return an error value. This is
+ mostly because, these functions are called \b after an error
+ occurs.
+
+ @{*/
+#include<khdefs.h>
+#include<khlist.h>
+
+/*! \name Customizable macros
+@{ */
+#ifndef KHERR_FACILITY
+/*! \brief The default facility when reporting errors
+
+ When including this header file, if the KHERR_FACILITY macro is
+ defined to be a wide character string, then it will be used as the
+ default facility when for the convenience macros. All of the
+ calls to the convenience macros in the source file would then have
+ that facility.
+
+ If left undefined, the convenience macros will leave the facility
+ value undefined.
+ */
+#define KHERR_FACILITY NULL
+#endif
+
+#ifndef KHERR_FACILITY_ID
+/*! \brief The default facility ID when reporting errors
+
+ When including this header file, if the KHERR_FACILITY_ID macro is
+ defined to be non-zero, then it will be used as the default
+ facility identifier for the convenience macros. All of the calls
+ to the convenience macros in the source file would then have that
+ facility identifier.
+
+ The default value of 0 means that the facility is undefined.
+ */
+#define KHERR_FACILITY_ID 0
+#endif
+
+/*! \define KHERR_HMODULE (undefined)
+ \brief The default module handle
+
+ When including this header file, if the KHERR_HMODULE macro is
+ defined to be an identifier that holds the module handle, then the
+ convenience macros that specify a module handle will use it.
+
+ A default value is not defined for KHERR_HMODULE. Any attempt to
+ invoke any of the convenience macros that use it should generate a
+ compile time error.
+ */
+#ifdef _WIN32
+#ifndef KHERR_HMODULE
+#endif
+#endif
+/*@}*/
+
+/*! \brief Parameter types
+ */
+enum kherr_parm_types {
+ KEPT_NONE = 0,
+ KEPT_INT32 = 1,
+ KEPT_UINT32,
+ KEPT_INT64,
+ KEPT_UINT64,
+ KEPT_STRINGC, /*!< String constant */
+ KEPT_STRINGT, /*!< String. Will be freed using
+ free() when the event is freed */
+ KEPT_PTR /*!< Pointer type. */
+};
+
+
+typedef struct tag_kherr_param {
+ khm_octet type;
+ khm_ui_8 data;
+} kherr_param;
+
+/*! \brief Severity levels
+
+ Larger the value, the less severe it is.
+*/
+enum tag_kherr_severity {
+ KHERR_FATAL = 0, /*!< Fatal error.*/
+ KHERR_ERROR, /*!< Non-fatal error. We'll probably
+ survive. See the suggested action. */
+ KHERR_WARNING, /*!< Warning. Something almost broke
+ or soon will. See the suggested
+ action. */
+ KHERR_INFO, /*!< Informational. Something happened
+ that we would like you to know
+ about. */
+ KHERR_DEBUG_1 = 64, /*!< Verbose debug level 1 (high)
+ Events at this severity level are
+ not required to be based on
+ localized strings. */
+ KHERR_DEBUG_2 = 65, /*!< Verbose debug level 2 (medium)
+ Events at this severity level are
+ not required to be based on
+ localized strings. */
+ KHERR_DEBUG_3 = 66, /*!< Verbose debug level 3 (low)
+ Events at this severity level are
+ not required to be based on
+ localized strings. */
+ KHERR_RESERVED_BANK = 127, /*!< Internal use */
+ KHERR_NONE = 128 /*!< Nothing interesting has happened
+ so far */
+};
+
+typedef enum tag_kherr_severity kherr_severity;
+
+/*! \brief Suggestions */
+enum tag_kherr_suggestion {
+ KHERR_SUGGEST_NONE = 0, /*!< No suggestions. */
+ KHERR_SUGGEST_ABORT, /*!< Abort whatever it was you were
+ trying. It's not gonna work. */
+ KHERR_SUGGEST_RETRY, /*!< Retry. It might work the second
+ or third time over */
+ KHERR_SUGGEST_IGNORE, /*!< Ignore. It might go away. */
+ KHERR_SUGGEST_INTERACT, /*!< Further user interaction is
+ necessary to resolve the situation.
+ The suggest string in the event
+ should be prompted to the user. */
+ KHERR_SUGGEST_OTHER, /*!< Something else. */
+};
+
+typedef enum tag_kherr_suggestion kherr_suggestion;
+
+/*! \brief An event */
+typedef struct tag_kherr_event {
+ khm_int32 magic; /*!< Magic number. Always set to
+ KHERR_EVENT_MAGIC */
+ DWORD thread_id; /*!< The thread which reported this
+ event. */
+ const wchar_t * short_desc; /*!< Short description or title
+ (localized) */
+ const wchar_t * facility; /*!< Facility name of the reporter
+ (not localized) */
+ const wchar_t * location; /*!< Location. Usually the function
+ name or such of where the event
+ occured (not localized) */
+ const wchar_t * long_desc; /*!< A long description of what went
+ wrong (localized, formatted) */
+ const wchar_t * suggestion; /*!< A suggested way to fix it
+ (localized,formatted) */
+
+ kherr_severity severity;
+ /*!< Severity level. One of the
+ severity levels listed in
+ enumeration ::kherr_severity */
+ khm_int32 facility_id; /*!< Left to the application to
+ interpret */
+ kherr_suggestion suggestion_id;
+ /*!< One of the suggestion ID's from
+ the enumeration
+ ::kherr_suggestion */
+
+ int flags; /*!< Flags. */
+
+ kherr_param p1; /*!< Parameter 1 for formatting */
+ kherr_param p2; /*!< Parameter 2 for formatting */
+ kherr_param p3; /*!< Parameter 3 for formatting */
+ kherr_param p4; /*!< Parameter 4 for formatting */
+
+ DWORD time_ticks; /*!< Time at which event was reported
+ (as returned by GetTickCount(). */
+ FILETIME time_ft; /*!< Time at which event was reported.
+ Current system time as FILETIME. */
+
+#ifdef _WIN32
+ HMODULE h_module; /*!< Handle to the module which should
+ resolve any unresolved resources
+ references above. */
+#endif
+
+ LDCL(struct tag_kherr_event);
+} kherr_event;
+
+#define KHERR_EVENT_MAGIC 0x0423e84f
+
+/*! \brief Flags for kherr_event
+
+ Each set of flags that define the type of resource for one value
+ is mutually exclusive.
+ */
+enum kherr_event_flags {
+ KHERR_RF_CSTR_SHORT_DESC= 0x00000000,
+ /*!< Short description is a constant
+ string */
+ KHERR_RF_RES_SHORT_DESC = 0x00000001,
+ /*!< Short description is a string
+ resource */
+ KHERR_RF_MSG_SHORT_DESC = 0x00000002,
+ /*!< Short description is a message
+ resource */
+ KHERR_RF_FREE_SHORT_DESC= 0x00000004,
+ /*!< Short description is an allocated
+ string */
+ KHERR_RFMASK_SHORT_DESC = 0x00000007,
+
+ KHERR_RF_CSTR_LONG_DESC = 0x00000000,
+ /*!< Long description is a constant
+ string */
+ KHERR_RF_RES_LONG_DESC = 0x00000008,
+ /*!< Long description is a string
+ resource */
+ KHERR_RF_MSG_LONG_DESC = 0x00000010,
+ /*!< Long description is a message
+ resouce */
+ KHERR_RF_FREE_LONG_DESC = 0x00000020,
+ /*!< Long description is an allocated
+ string */
+ KHERR_RFMASK_LONG_DESC = 0x00000038,
+
+ KHERR_RF_CSTR_SUGGEST = 0x00000000,
+ /*!< Suggestion is a constant
+ string */
+ KHERR_RF_RES_SUGGEST = 0x00000040,
+ /*!< Suggestion is a string
+ resource */
+ KHERR_RF_MSG_SUGGEST = 0x00000080,
+ /*!< Suggestion is a message
+ resource */
+ KHERR_RF_FREE_SUGGEST = 0x00000100,
+ /*!< Suggestion is an allocated
+ string */
+ KHERR_RFMASK_SUGGEST = 0x000001C0,
+
+ KHERR_RF_STR_RESOLVED = 0x00010000,
+ /*!< The string resources in the event
+ have been resolved. */
+ KHERR_RF_CONTEXT_FOLD = 0x00020000,
+ /*!< The event is a representation of
+ a folded context. */
+
+ KHERR_RF_INERT = 0x00040000,
+ /*!< Inert event. The event has
+ already been dealt with and is no
+ longer considered significant. */
+ KHERR_RF_COMMIT = 0x00080000
+ /*!< Committed event. The commit
+ handlers for this event have already
+ been called. */
+};
+
+/*! \brief Serial number for error contexts */
+typedef khm_ui_4 kherr_serial;
+
+/*! \brief An error context
+*/
+typedef struct tag_kherr_context {
+ khm_int32 magic; /*!< Magic number. Always set to
+ KHERR_CONTEXT_MAGIC */
+
+ kherr_serial serial; /*!< Context instance serial number.
+ Context objects themselves may be
+ reused for different contexts as
+ they are freed and reallocated.
+ However every instance of a context
+ is guaranteed to have a unique
+ serial number as specified in this
+ field. If an external entity wants
+ to keep track of the context, it
+ should keep track of the serial
+ number as well as the pointer to the
+ context object. */
+
+ kherr_severity severity;
+ /*!< Severity level. One of the
+ severity levels listed below. This
+ is the severity level of the context
+ and is the maximum severity level of
+ all the events in the queue of
+ events. */
+
+ khm_int32 flags; /*!< Flags. Used internally. */
+ khm_ui_4 refcount; /*!< Reference count. Used
+ internally */
+
+ kherr_event *desc_event; /*!< Description event. The event that
+ describes the error context. This
+ points to an event that is not in
+ the event queue. */
+
+ kherr_event *err_event; /*!< Significant event. The last one
+ that caused the severity level to be
+ what it is right now. This points
+ to an event that is listed in the
+ event queue for this context.*/
+
+ khm_ui_4 progress_num; /*!< Progress numerator */
+ khm_ui_4 progress_denom; /*!< Progress denominator */
+
+ TDCL(struct tag_kherr_context);
+ QDCL(struct tag_kherr_event);
+} kherr_context;
+
+#define KHERR_CONTEXT_MAGIC 0x34f3238c
+
+enum kherr_context_flags {
+ KHERR_CF_NONE = 0x00000000,
+ /*!< None. */
+
+ KHERR_CF_DIRTY = 0x00000001,
+ /*!< Used Internally. Denotes that
+ the err_event and severity may need
+ to be recalculated. Cannot be set
+ as an initial flag. */
+
+ KHERR_CF_OWN_PROGRESS = 0x00000002,
+ /*!< The context maintains its own
+ progress meter as opposed to one
+ that is derived from child
+ contexts. */
+
+ KHERR_CF_UNBOUND = 0x00000004,
+ /*!< Unbound context. The context
+ can't be used to log events. Call
+ kherr_push_context() to associate
+ the context with the global context
+ hierarchy. Cannot be set as an
+ initial flag. */
+
+ KHERR_CF_TRANSITIVE = 0x00000008,
+ /*!< Transitive. The context is
+ automatically made the current
+ context for all other threads that
+ handle messages sent or posted by
+ threads whose current error context
+ is this one. */
+
+ KHERR_CFMASK_INITIAL = 0x0000000a,
+ /*!< Allowed initial flags */
+};
+
+/*! \brief Maximum length of a string field in characters including terminating NULL
+ */
+#define KHERR_MAXCCH_STRING 1024
+
+/*! \brief Maximum length of a string field in bytes including terminating NULL
+ */
+#define KHERR_MAXCB_STRING (KHERR_MAXCCH_STRING * sizeof(wchar_t))
+
+/*! \brief Context event
+
+ \see kherr_add_ctx_handler()
+*/
+enum kherr_ctx_event {
+ KHERR_CTX_BEGIN = 0x0001, /*!< A new context was created */
+ KHERR_CTX_DESCRIBE=0x0002, /*!< A context was described */
+ KHERR_CTX_END = 0x0004, /*!< A context was closed */
+ KHERR_CTX_ERROR = 0x0008, /*!< A context switched to an error
+ state */
+ KHERR_CTX_EVTCOMMIT = 0x0010 /*!< A event was committed into the
+ context */
+};
+
+/*! \brief Context event handler
+
+ Context event handlers are invoked when specific events occur with
+ respect to an error context. The ::kherr_ctx_event parameter
+ specifies which event occurred using one of the event values
+ described in the enumeration. The error context in which this
+ event occurred is specified by the ::kherr_context pointer.
+
+ Note that if the handler needs to keep track of the error context
+ for later processing, it also needs to keep track of the \a serial
+ field of the error context. The same context object may be
+ reused, but the serial number is guaranteed to be unique.
+
+ \see kherr_add_ctx_handler()
+ */
+typedef void (KHMAPI * kherr_ctx_handler)(enum kherr_ctx_event,
+ kherr_context *);
+
+/*! \brief Add a context event handler
+
+ An application can register an event handler that gets notified of
+ events that pertain to error contexts. More than one handler can
+ be registered. The order in which the handlers are called is
+ undefined for any specific event.
+
+ These event occur in the context of individual application
+ threads. The handler will be called from within the thread that
+ caused the event. Therefore it is important that the handler is
+ both reentrant and returns quickly.
+
+ The events that the handler will be notified of are explained
+ below:
+
+ <b>KHERR_CTX_BEGIN</b>: Notification that a new context was
+ created. A pointer to the context will be supplied to the
+ handler. The supplied pointer should not be used to obtain a hold
+ on the context, as it will prevent the context from being closed.
+
+ <b>KHERR_CTX_DESCRIBE</b>: The thread called
+ kherr_set_desc_event() to set the description of a context. Once
+ again, the pointer should not be used to obtain a hold on the
+ context.
+
+ <b>KHERR_CTX_ERROR</b>: The last event that was reported for the
+ context was an error event (the severity was was equal or higher
+ than KHERR_ERROR). The pointer may be used to obtain a hold on
+ the context. However, it is the application's resonsibility to
+ make sure that the hold is released later. Otherwise the event
+ will never be closed.
+
+ <b>KHERR_CTX_END</b>: Closure. This event is signalled when the
+ last open handle to the context is closed and there is no thread
+ that is currently active which has this context in its error
+ context stack. At the time the handler is invoked, the context is
+ still intact. The pointer that is supplied should not be used to
+ obtain a handle on the context.
+
+ <b>KHERR_CTX_EVTCOMMIT</b>: An event was committed into the error
+ context. An event is committed when another event is reported
+ after the event, or if the context is closed. Since the last
+ event that is reported can still be modified by adding new
+ information, the event remains open until it is no longer the last
+ event or the context is no longer active. When this notification
+ is received, the last event in the context's event queue is the
+ event that was committed.
+
+ \param[in] h Context event handler, of type ::kherr_ctx_handler
+
+ \param[in] filter A combination of ::kherr_ctx_event values
+ indication which notifications should be sent to the handler.
+ If a \a filter value of zero is provided, all of the events
+ will be sent to the handler.
+
+ \param[in] serial The serial number of the error context that
+ should be tracked. If this is zero, all error contexts can
+ trigger the handler.
+ */
+KHMEXP void KHMAPI kherr_add_ctx_handler(kherr_ctx_handler h,
+ khm_int32 filter,
+ kherr_serial serial);
+
+/*! \brief Remove a context event handler
+
+ Undoes what was done with kherr_add_ctx_handler()
+
+ \see kherr_add_ctx_handler()
+ */
+KHMEXP void KHMAPI kherr_remove_ctx_handler(kherr_ctx_handler h,
+ kherr_serial serial);
+
+
+/*! \brief Report an error
+
+ Creates an event, fills in the details specified in the arguments,
+ and adds it to the current error context.
+
+ If the current thread does not have an error context, no reporting
+ happens. However, if any of the supplied strings or parameters
+ are marked as allocated, they will be freed before the function
+ returns.
+
+ Certain parameters that expect strings can instead be given string
+ resources, message resources or allocated strings in addition to
+ constant string. By default, the parameters are expected to be
+ constant strings.
+
+ <b>Allocated strings</b>: The application can allocate memory for
+ a string. Since the application is not notified when the event is
+ no longer used and freed, it \b must indicate that the string is
+ an allocated string by setting the appropriate flag in the \a
+ flags parameter. When the event is no longer used, the memory
+ pointed to by the relevant pointer will be freed through a call to
+ free(). Not all string parameters take allocated strings. See
+ individual parameter documentation for details.
+
+ <b>String resources</b>: On WIN32, string resources can be passed
+ in to kherr_report() using the MAKEINTRESOURCE macro. However,
+ the application \b must specify that the parameter is a string
+ resource using the appropriate flag in the \a flags parameter.
+ The error reporting engine will expand the string against the
+ module handle passed in the \a h_module parameter when the value
+ of the string is required. Not all string parameters take string
+ resources. See individual parameter documentation for details.
+ Strings loaded through string resources cannot be longer than
+ ::KHERR_MAXCCH_STRING in characters inclusive of terminating NULL.
+
+ <b>Message resources</b>: On WIN32, message resources can be
+ passed in to kherr_report() by specifying the message ID where it
+ ordinarily expects a pointer to a constant string. The
+ application \b must indicate that the string is a message resource
+ by using the appropriate flag in the \a flags parameter. When the
+ value of the string is needed, it is expanded against the module
+ handle passed in the \a h_module parameter using the message ID.
+ Not all string parameters take message resources. See individual
+ parameter documentation for details. Note that the facility and
+ severity values associated with a message resource are ignored.
+ Strings loaded through message resources cannot be longer than
+ ::KHERR_MAXCCH_STRING in characters inclusive of terminating NULL.
+
+ <b>Formatted fields</b>: Parameters that are formatted can have
+ can have parameter inserts like in printf(). However, specifying
+ inserts is different from printf() and follows the conventions
+ used in WIN32 API FormatMessage(). This is because for localized
+ strings, the order of the parameters in the string may be
+ different. See the documentation for FormatMessage() for details
+ on the format string. The same set of parameters (i.e. \a p1, \a
+ p2, \a p3, \a p4) is used for all formatted strings with
+ appropriate marshalling for 64 bit types. The size of the string
+ after expansion must not exceed 65536 bytes inclusive of
+ terminating NULL.
+
+ \param[in] severity One of ::kherr_severity_level
+ \param[in] short_desc Short description or title (localized). Can
+ be a string resource, message resource, allocated string or
+ constant string. The \a flags parameter should indicate the
+ type of string used.
+ \param[in] facility Facility name of the reporter (not localized)
+ \param[in] location Usually the function name or such of where the
+ event occured (not localized)
+ \param[in] long_desc Long description of event (localized,
+ formatted). Can be a string resource, message resource,
+ allocated string or constant string. The \a flags parameter
+ should indicate the type of string used.
+ \param[in] suggestion Suggested action to correct situation, if
+ applicable (localized). Can be a string resource, message
+ resource, allocated string or constant string. The \a flags
+ parameter should indicate the type of string used.
+ \param[in] facility_id Identifier of facility. Application
+ defined.
+ \param[in] suggestion_id One of the suggestion identifiers from
+ ::kherr_suggestion_ids
+ \param[in] p1 First parameter. Used for formatting.
+ \param[in] p2 Second parameter. Used for formatting.
+ \param[in] p3 Third parameter. Used for formatting.
+ \param[in] p4 Fourth parameter. Used for formatting.
+ \param[in] flags Flags. See ::kherr_report_flags
+ \param[in] h_module Handle to a module that resolves any string or
+ message resources used for the \a short_description , \a
+ long_desc or \a suggestion parameters. This parameter is only
+ available on WIN32.
+
+ \note With the exception of parameters of type KEPT_STRINGT and
+ parameters which are flagged for freeing using the \a flags
+ parameter, all other string parameters are assumed to be
+ pointers to constant strings. The strings are not copied and
+ the pointers are used as is. Also, no clean-up is performed
+ when the event is freed other than that implied by \a flags.
+ */
+KHMEXP kherr_event * KHMAPI kherr_report(
+ enum kherr_severity severity,
+ const wchar_t * short_desc,
+ const wchar_t * facility,
+ const wchar_t * location,
+ const wchar_t * long_desC,
+ const wchar_t * suggestion,
+ khm_int32 facility_id,
+ enum kherr_suggestion suggestion_id,
+ kherr_param p1,
+ kherr_param p2,
+ kherr_param p3,
+ kherr_param p4,
+ khm_int32 flags
+#ifdef _WIN32
+ ,HMODULE h_module
+#endif
+);
+
+/*! \brief Report a formatted message
+
+ The format string \a long_desc_fmt should be a string constant and
+ the format specifiers follow that of \a sprintf. This creates an
+ event with the long description set to the expansion of the format
+ string against the arguments.
+ */
+KHMEXP kherr_event * __cdecl
+kherr_reportf_ex(enum kherr_severity severity,
+ const wchar_t * facility,
+ khm_int32 facility_id,
+#ifdef _WIN32
+ HMODULE hModule,
+#endif
+ const wchar_t * long_desc_fmt,
+ ...);
+#define _reportf_ex kherr_reportf_ex
+
+/*! \brief Report a formatted message
+
+ The format string \a long_desc_fmt should be a string constant and
+ the format specifiers follow that of \a sprintf. This creates an
+ event with the long description set to the expansion of the format
+ string against the arguments.
+ */
+KHMEXP kherr_event * __cdecl
+kherr_reportf(const wchar_t * long_desc_fmt,
+ ...);
+#define _reportf kherr_reportf
+
+/*! \brief Create a parameter out of a transient string
+
+ A parameter is created by duplicating the string that is passed
+ into the function. If the string exceeds KHERR_MAXCCH_STRING,
+ then only the first part of the string that fits within the limit
+ is duplicated.
+
+ The resulign ::kherr_param must be passed in to kherr_report().
+ The event logging framework will free the duplicated string once
+ the data is no longer required.
+ */
+KHMEXP kherr_param kherr_dup_string(const wchar_t * s);
+
+__inline KHMEXP kherr_param
+kherr_val(khm_octet ptype, khm_ui_8 pvalue) {
+ kherr_param p;
+
+ p.type = ptype;
+ p.data = pvalue;
+
+ return p;
+}
+
+#define _int32(i) kherr_val(KEPT_INT32, (khm_ui_8) i)
+#define _uint32(ui) kherr_val(KEPT_UINT32, (khm_ui_8) ui)
+#define _int64(i) kherr_val(KEPT_INT64, (khm_ui_8) i)
+#define _uint64(ui) kherr_val(KEPT_UINT64, (khm_ui_8) ui)
+#define _cstr(cs) kherr_val(KEPT_STRINGC, (khm_ui_8) cs)
+#define _tstr(ts) kherr_val(KEPT_STRINGT, (khm_ui_8) ts)
+#define _cptr(p) kherr_val(KEPT_PTR, (khm_ui_8) p)
+#define _vnull() kherr_val(KEPT_NONE, 0)
+#define _dupstr(s) kherr_dup_string(s)
+
+/* convenience macros for calling kherr_report */
+#ifdef KHERR_HMODULE
+
+#define _report_cs0(severity, long_description) \
+ kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_description), NULL, KHERR_FACILITY_ID, 0, _vnull(), _vnull(), _vnull(), _vnull(), 0, KHERR_HMODULE)
+
+#define _report_cs1(severity, long_description, p1) \
+ kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_description), NULL, KHERR_FACILITY_ID, 0, p1, _vnull(), _vnull(), _vnull(), 0, KHERR_HMODULE)
+
+#define _report_cs2(severity, long_description, p1, p2) \
+ kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_description), NULL, KHERR_FACILITY_ID, 0, p1, p2, _vnull(), _vnull(), 0, KHERR_HMODULE)
+
+#define _report_cs3(severity, long_description, p1, p2, p3) \
+ kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_description), NULL, KHERR_FACILITY_ID, 0, p1, p2, p3, _vnull(), 0, KHERR_HMODULE)
+
+#define _report_cs4(severity, long_description, p1, p2, p3, p4) \
+ kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_description), NULL, KHERR_FACILITY_ID, 0, p1, p2, p3, p4, 0, KHERR_HMODULE)
+
+#else
+
+#define _report_cs0(severity, long_description) \
+ kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_description), NULL, KHERR_FACILITY_ID, 0, _vnull(), _vnull(), _vnull(), _vnull(), 0, NULL)
+
+#define _report_cs1(severity, long_description, p1) \
+ kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_description), NULL, KHERR_FACILITY_ID, 0, p1, _vnull(), _vnull(), _vnull(), 0, NULL)
+
+#define _report_cs2(severity, long_description, p1, p2) \
+ kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_description), NULL, KHERR_FACILITY_ID, 0, p1, p2, _vnull(), _vnull(), 0, NULL)
+
+#define _report_cs3(severity, long_description, p1, p2, p3) \
+ kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_description), NULL, KHERR_FACILITY_ID, 0, p1, p2, p3, _vnull(), 0, NULL)
+
+#define _report_cs4(severity, long_description, p1, p2, p3, p4) \
+ kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_description), NULL, KHERR_FACILITY_ID, 0, p1, p2, p3, p4, 0, NULL)
+#endif /* !defined(KHERR_HMODULE) */
+
+#ifdef _WIN32
+#define _report_sr0(severity, long_desc_id) \
+ kherr_report((severity), NULL, KHERR_FACILITY, NULL, MAKEINTRESOURCE(long_desc_id), NULL, KHERR_FACILITY_ID, 0, _vnull(), _vnull(), _vnull(), _vnull(), KHERR_RF_RES_LONG_DESC, KHERR_HMODULE)
+
+#define _report_sr1(severity, long_desc_id, p1) \
+ kherr_report((severity), NULL, KHERR_FACILITY, NULL, MAKEINTRESOURCE(long_desc_id), NULL, KHERR_FACILITY_ID, 0, p1, _vnull(), _vnull(), _vnull(), KHERR_RF_RES_LONG_DESC, KHERR_HMODULE)
+
+#define _report_sr2(severity, long_desc_id, p1, p2) \
+ kherr_report((severity), NULL, KHERR_FACILITY, NULL, MAKEINTRESOURCE(long_desc_id), NULL, KHERR_FACILITY_ID, 0, p1, p2, _vnull(), _vnull(), KHERR_RF_RES_LONG_DESC, KHERR_HMODULE)
+
+#define _report_sr3(severity, long_desc_id, p1, p2, p3) \
+ kherr_report((severity), NULL, KHERR_FACILITY, NULL, MAKEINTRESOURCE(long_desc_id), NULL, KHERR_FACILITY_ID, 0, p1, p2, p3, _vnull(), KHERR_RF_RES_LONG_DESC, KHERR_HMODULE)
+
+#define _report_sr4(severity, long_desc_id, p1, p2, p3, p4) \
+ kherr_report((severity), NULL, KHERR_FACILITY, NULL, MAKEINTRESOURCE(long_desc_id), NULL, KHERR_FACILITY_ID, 0, p1, p2, p3, p4, KHERR_RF_RES_LONG_DESC, KHERR_HMODULE)
+#endif
+
+#ifdef _WIN32
+#define _report_mr0(severity, long_desc_msg_id) \
+ kherr_report((severity), NULL, KHERR_FACILITY, NULL, (wchar_t *)(long_desc_msg_id), NULL, KHERR_FACILITY_ID, 0, _vnull(), _vnull(), _vnull(), _vnull(), KHERR_RF_MSG_LONG_DESC, KHERR_HMODULE)
+
+#define _report_mr1(severity, long_desc_msg_id, p1) \
+ kherr_report((severity), NULL, KHERR_FACILITY, NULL, (wchar_t *)(long_desc_msg_id), NULL, KHERR_FACILITY_ID, 0, p1, _vnull(), _vnull(), _vnull(), KHERR_RF_MSG_LONG_DESC, KHERR_HMODULE)
+
+#define _report_mr2(severity, long_desc_msg_id, p1, p2) \
+ kherr_report((severity), NULL, KHERR_FACILITY, NULL, (wchar_t *)(long_desc_msg_id), NULL, KHERR_FACILITY_ID, 0, p1, p2, _vnull(), _vnull(), KHERR_RF_MSG_LONG_DESC, KHERR_HMODULE)
+
+#define _report_mr3(severity, long_desc_msg_id, p1, p2, p3) \
+ kherr_report((severity), NULL, KHERR_FACILITY, NULL, (wchar_t *)(long_desc_msg_id), NULL, KHERR_FACILITY_ID, 0, p1, p2, p3, _vnull(), KHERR_RF_MSG_LONG_DESC, KHERR_HMODULE)
+
+#define _report_mr4(severity, long_desc_msg_id, p1, p2, p3, p4) \
+ kherr_report((severity), NULL, KHERR_FACILITY, NULL, (wchar_t *)(long_desc_msg_id), NULL, KHERR_FACILITY_ID, 0, p1, p2, p3, p4, KHERR_RF_MSG_LONG_DESC, KHERR_HMODULE)
+#endif
+
+#define _report_ts0(severity, long_desc_ptr) \
+ kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_desc_ptr), NULL, KHERR_FACILITY_ID, 0, _vnull(), _vnull(), _vnull(), _vnull(), KHERR_RF_FREE_LONG_DESC, NULL)
+
+#define _report_ts1(severity, long_desc_ptr, p1) \
+ kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_desc_ptr), NULL, KHERR_FACILITY_ID, 0, p1, _vnull(), _vnull(), _vnull(), KHERR_RF_FREE_LONG_DESC, NULL)
+
+#define _report_ts2(severity, long_desc_ptr, p1, p2) \
+ kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_desc_ptr), NULL, KHERR_FACILITY_ID, 0, p1, p2, _vnull(), _vnull(), KHERR_RF_FREE_LONG_DESC, NULL)
+
+#define _report_ts3(severity, long_desc_ptr, p1, p2, p3) \
+ kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_desc_ptr), NULL, KHERR_FACILITY_ID, 0, p1, p2, p3, _vnull(), KHERR_RF_FREE_LONG_DESC, NULL)
+
+#define _report_ts4(severity, long_desc_ptr, p1, p2, p3, p4) \
+ kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_desc_ptr), NULL, KHERR_FACILITY_ID, 0, p1, p2, p3, p4, KHERR_RF_FREE_LONG_DESC, NULL)
+
+/*! \brief Set the suggestion and suggestion identifier for the last event
+
+ The event that will be modified is the last event reported by the
+ calling thread.
+ */
+KHMEXP void KHMAPI kherr_suggest(wchar_t * suggestion, khm_int32 suggestion_id, khm_int32 flags);
+#define _suggest_cs(cs,sid) kherr_suggest((cs), (sid), KHERR_RF_CSTR_SUGGEST)
+#define _suggest_ts(ts,sid) kherr_suggest((ts), (sid), KHERR_RF_FREE_SUGGEST)
+#define _suggest_sr(sr,sid) kherr_suggest(MAKEINTRESOURCE(sr), (sid), KHERR_RF_RES_SUGGEST)
+#define _suggest_mr(mr,sid) kherr_suggest((wchar_t *)(DWORD_PTR)(mr), (sid), KHERR_RF_MSG_SUGGEST)
+
+/*! \brief Set the location string for the last event
+
+ The event that will be modified is the last event reported by the
+ calling thread.
+ */
+KHMEXP void KHMAPI kherr_location(wchar_t * location);
+#define _location(l) kherr_location(l)
+
+/*! \brief Set the facility string and identifier for the last event
+
+ The event that will be modified is the last event reported by the
+ calling thread.
+ */
+KHMEXP void KHMAPI kherr_facility(wchar_t * facility, khm_int32 facility_id);
+#define _facility(f,fid) kherr_facility((f),(fid))
+
+/*! \brief Marks the last event as the descriptor event for the current error context
+
+ Note that marking an event as the descriptor event has the effect
+ of removing the event from event queue. The event will henceforth
+ be used as the descriptor for the context. The only effective
+ fields of a descriptor event are \a short_desc, \a long_desc, \a
+ facility, \a facility_id and the parameters which are used for
+ resolving formatted strings in the aforementioned fields.
+
+ Upon calling kherr_set_desc_event(), the event will be
+ automatically evaluated as if kherr_evaluate_event() was called.
+
+ The event that will be referenced is the last event reported by
+ the calling thread.
+ */
+KHMEXP void KHMAPI kherr_set_desc_event(void);
+#define _describe kherr_set_desc_event
+
+/*! \brief Delete the last event
+
+ The event that will be deleted is the last event reported by the
+ calling thread.
+ */
+KHMEXP void KHMAPI kherr_del_last_event(void);
+#define _del_event kherr_del_last_event
+
+/*! \brief Create a new context
+
+ The created context is not bound to any thread or any context
+ hierarchy. Hence it cannot be used to capture any events until it
+ is used in a call to kherr_push_context().
+
+ Release the returned context pointer with a call to
+ kherr_release_context().
+
+ \param[in] flags Initial flags for the context. Combination of
+ ::kherr_context_flags
+
+ \note This function is for internal use only.
+ */
+KHMEXP kherr_context * KHMAPI kherr_create_new_context(khm_int32 flags);
+
+/*! \brief Obtain a hold on a context */
+KHMEXP void KHMAPI kherr_hold_context(kherr_context * c);
+
+/*! \brief Release a context */
+KHMEXP void KHMAPI kherr_release_context(kherr_context * c);
+
+/*! \brief Push an empty context
+
+ Creates an empty context, adds it as a child of the current
+ thread's error context. If the current thread does not have an
+ error context, then the created error context will be a root level
+ context.
+
+ The new context will be the current error context for the calling
+ thread.
+
+ \param[in] flags Initial flags for the context. Combination of
+ ::kherr_context_flags
+
+ \see kherr_push_new_context() for more information about thread
+ specific context stacks.
+
+ */
+KHMEXP void KHMAPI kherr_push_new_context(khm_int32 flags);
+#define _begin_task kherr_push_new_context
+
+/*! \brief Push a context
+
+ Each thread has a stack of error contexts. The topmost one is
+ current. The thread can push or pop contexts on to the stack
+ independently of the hierarchy of contexts (the only exception, as
+ explained below is when the context that is being pushed is
+ unbound).
+
+ If the context being pushed by kherr_push_context() is unbound,
+ then it will be attached to the current context of the thread as a
+ child. Once the new context is pushed to the top of the stack, it
+ will become the current context for the thread.
+
+ The calling thread must call kherr_pop_context() to remove the
+ context from the top of the stack. Each call to
+ kherr_push_new_context() or kher_push_context() must have a
+ corresponding kherr_pop_context() call.
+
+ When the thread terminates, all of the contexts in the thread's
+ context stack will be automatically removed.
+
+ \see kherr_pop_context()
+ */
+KHMEXP void KHMAPI kherr_push_context(kherr_context * c);
+
+/*! \brief Pop a context
+
+ Remove the current error context from the thread's context stack.
+ If no other open handles exist to the error context, this causes
+ the error context to collapse into it's parent context or vanish
+ entirely unless the context contains an error.
+
+ \see kherr_push_context() for more information about thread
+ specific context stacks.
+ */
+KHMEXP void KHMAPI kherr_pop_context(void);
+#define _end_task kherr_pop_context
+
+/*! \brief Retrieve the current error context
+
+ The returned pointer must be released with a call to
+ kherr_release_context().
+*/
+KHMEXP kherr_context * KHMAPI kherr_peek_context(void);
+
+/*! \brief Check if the current error context indicates an error
+
+ \return TRUE if there is an error. FALSE otherwise.
+ \see kherr_analyze()
+ */
+KHMEXP khm_boolean KHMAPI kherr_is_error(void);
+
+/*! \brief Check if an error context indicates an error
+
+ \return TRUE if there is an error. FALSE otherwise.
+ \see kherr_analyze()
+ */
+KHMEXP khm_boolean KHMAPI kherr_is_error_i(kherr_context * c);
+
+/*! \brief Clear the error state of the current context */
+KHMEXP void KHMAPI kherr_clear_error(void);
+
+/*! \brief Clear the error state of an error context */
+KHMEXP void KHMAPI kherr_clear_error_i(kherr_context * c);
+
+/*! \brief Set the progress meter of the current error context
+
+ Setting \a denom to zero removes the progress meter.
+ */
+KHMEXP void KHMAPI kherr_set_progress(khm_ui_4 num, khm_ui_4 denom);
+#define _progress(num,denom) kherr_set_progress((num),(denom))
+
+/*! \brief Get the progress meter of the current error context
+ */
+KHMEXP void KHMAPI kherr_get_progress(khm_ui_4 * num, khm_ui_4 * denom);
+
+/*! \brief Get the progress meter of an error context
+ */
+KHMEXP void KHMAPI kherr_get_progress_i(kherr_context * c, khm_ui_4 * num, khm_ui_4 * denom);
+
+/*! \brief Get the first event in a context
+
+ The returned pointer is only valid as long as there is a hold on
+ \a c. Once the context is released with a call to
+ kherr_release_context() all pointers to events in the context
+ become invalid.
+
+ In addition, the last event in a context may still be "active". A
+ thread can still modify the last event as long as the context is
+ active.
+
+ \see kherr_get_next_event(), kherr_get_prev_event(),
+ kherr_get_last_event()
+ */
+KHMEXP kherr_event * KHMAPI kherr_get_first_event(kherr_context * c);
+
+/*! \brief Get the next event
+
+ Call kherr_get_first_event() to obtain the first event in a
+ context. Subsequent calls to kherr_get_next_event() will yield
+ other events in the order in which they were reported. The list
+ ends when kherr_get_next_event() returns NULL.
+
+ The returned pointer is only valid as long as there is a hold on
+ \a c. Once the context is released with a call to
+ kherr_release_context() all pointers to events in the context
+ become invalid.
+
+ In addition, the last event in a context may still be "active". A
+ thread can still modify the last event as long as the context is
+ active.
+
+ \see kherr_get_first_event(), kherr_get_prev_event(),
+ kherr_get_last_event()
+ */
+KHMEXP kherr_event * KHMAPI kherr_get_next_event(kherr_event * e);
+
+/*! \brief Get the previous event
+
+ Returns a pointer to the event that was reported in the context
+ containing \a e prior to \a e being reported.
+
+ The returned pointer is only valid as long as there is a hold on
+ the error context. Once the context is released with a call to
+ kherr_release_context() all pointers to events in the context
+ become invalid.
+
+ In addition, the last event in a context may still be "active". A
+ thread can still modify the last event as long as the context is
+ active.
+
+ \see kherr_get_first_event(), kherr_get_next_event(),
+ kherr_get_last_event()
+ */
+KHMEXP kherr_event * KHMAPI kherr_get_prev_event(kherr_event * e);
+
+/*! \brief Get the last event in an error context
+
+ Returns a pointer to the last error event that that was reported
+ to the context \a c.
+
+ The returned pointer is only valid as long as there is a hold on
+ the error context. Once the context is released with a call to
+ kherr_release_context(), all pointers to events in the context
+ become invalid.
+
+ In addtion, the last event in a context may still be "active". A
+ thread can still modify the last event as long as the context is
+ active.
+
+ \see kherr_get_first_event(), kherr_get_next_event(),
+ kherr_get_prev_event()
+ */
+KHMEXP kherr_event * KHMAPI kherr_get_last_event(kherr_context * c);
+
+/*! \brief Get the first child context of a context
+
+ Contexts are arranged in a hiearchy. This function returns the
+ first child of an error context. Use kherr_get_next_context() to
+ obtain the other contexts. If \a c is \a NULL, this returns the
+ first root level context.
+
+ The returned pointer must be released with a call to
+ kherr_release_context()
+ */
+KHMEXP kherr_context * KHMAPI kherr_get_first_context(kherr_context * c);
+
+/*! \brief Get the next sibling context of a context
+
+ The returned pointer must be released with a call to
+ kherr_release_context()
+
+ \see kherr_get_first_context()
+ */
+KHMEXP kherr_context * KHMAPI kherr_get_next_context(kherr_context * c);
+
+/*! \brief Get the desciption event for the context
+
+ The description event is the event that was denoted using
+ kherr_set_desc_event() as the event which describes the context.
+
+ The returned pointer is only valid as long as there is a hold on
+ \a c. Once the context is released with a call to
+ kherr_release_context() all pointers to events in the context
+ becomes invalid.
+ */
+KHMEXP kherr_event * KHMAPI kherr_get_desc_event(kherr_context * c);
+
+/*! \brief Get the error event for the context
+
+ The error event for a context is the last event that had the
+ highest severity level.
+
+ The returned pointer is only valid as long as there is a hold on
+ \a c. Once the context is released with a call to
+ kherr_release_context() all pointers to events in the context
+ becomes invalid.
+ */
+KHMEXP kherr_event * KHMAPI kherr_get_err_event(kherr_context * c);
+
+/*! \brief Evaluate an event
+
+ When an event is reported, all the parameters and resource
+ references that were passed to kherr_report() are kept as-is until
+ the actual string values are required by the error reporting
+ library. However, if the string fields are required before then,
+ an application can call kherr_evaluate_event() to get them.
+
+ This function does the following:
+
+ - Load any referenced string or message resources that are
+ referenced in the event's short description, long description or
+ suggestion.
+
+ - Expand any inserts using the parameters that were passed in.
+
+ - Free up allocated strings in for the descriptions or suggestion
+ fields and any parameters.
+
+ - Update the string fields in the event to contain the newly
+ generated strings.
+
+ */
+KHMEXP void KHMAPI kherr_evaluate_event(kherr_event * e);
+
+/*! \brief Evaluate the last event
+
+ Same as kherr_evaluate_event(), but operates on the last event
+ logged by the current thread.
+
+ \see kherr_evaluate_event()
+ */
+KHMEXP void KHMAPI kherr_evaluate_last_event(void);
+#define _resolve kherr_evaluate_last_event
+
+/*! \defgroup kherr_fids Standard Facility IDs
+@{*/
+#define KHM_FACILITY_KMM 1
+#define KHM_FACILITY_KCDB 2
+#define KHM_FACILITY_UI 3
+#define KHM_FACILITY_KRB5 64
+#define KHM_FACILITY_KRB4 65
+#define KHM_FACILITY_AFS 66
+#define KHM_FACILITY_USER 128
+/*@}*/
+
+/*@}*/
+
+/* In debug mode, outputs the formatted string to the debug console */
+#ifdef DEBUG
+KHMEXP void kherr_debug_printf(wchar_t * fmt, ...);
+#endif
+
+#endif
diff --git a/src/windows/identity/kherr/kherrinternal.h b/src/windows/identity/kherr/kherrinternal.h
index da33c596e2..fb6412aa24 100644
--- a/src/windows/identity/kherr/kherrinternal.h
+++ b/src/windows/identity/kherr/kherrinternal.h
@@ -1,69 +1,69 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#ifndef __KHIMAIRA_KHERRORINTERNAL_H
-#define __KHIMAIRA_KHERRORINTERNAL_H
-
-#include<windows.h>
-#include<kherr.h>
-#include<utils.h>
-#include<strsafe.h>
-
-typedef struct tag_kherr_thread {
- khm_size nc_ctx;
- khm_size n_ctx;
- kherr_context ** ctx;
-} kherr_thread;
-
-#define THREAD_STACK_SIZE 8
-
-typedef struct tag_kherr_handler_node {
- khm_int32 filter;
- kherr_ctx_handler h;
- kherr_serial serial;
-} kherr_handler_node;
-
-#define CTX_ALLOC_INCR 4
-
-#define EVENT_MASK_UNRESOLVED \
- (KHERR_RF_RES_SHORT_DESC|KHERR_RF_MSG_SHORT_DESC| \
- KHERR_RF_RES_LONG_DESC|KHERR_RF_MSG_LONG_DESC| \
- KHERR_RF_RES_SUGGEST|KHERR_RF_MSG_SUGGEST)
-
-extern CRITICAL_SECTION cs_error;
-extern DWORD tls_error;
-extern kherr_context * ctx_free_list;
-extern kherr_event * evt_free_list;
-extern kherr_handler_node * ctx_handlers;
-extern khm_size n_ctx_handlers;
-
-#define parm_type(p) ((p).type)
-#define parm_data(p) ((p).data)
-
-void resolve_event_strings(kherr_event *);
-void attach_this_thread(void);
-void detach_this_thread(void);
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __KHIMAIRA_KHERRORINTERNAL_H
+#define __KHIMAIRA_KHERRORINTERNAL_H
+
+#include<windows.h>
+#include<kherr.h>
+#include<utils.h>
+#include<strsafe.h>
+
+typedef struct tag_kherr_thread {
+ khm_size nc_ctx;
+ khm_size n_ctx;
+ kherr_context ** ctx;
+} kherr_thread;
+
+#define THREAD_STACK_SIZE 8
+
+typedef struct tag_kherr_handler_node {
+ khm_int32 filter;
+ kherr_ctx_handler h;
+ kherr_serial serial;
+} kherr_handler_node;
+
+#define CTX_ALLOC_INCR 4
+
+#define EVENT_MASK_UNRESOLVED \
+ (KHERR_RF_RES_SHORT_DESC|KHERR_RF_MSG_SHORT_DESC| \
+ KHERR_RF_RES_LONG_DESC|KHERR_RF_MSG_LONG_DESC| \
+ KHERR_RF_RES_SUGGEST|KHERR_RF_MSG_SUGGEST)
+
+extern CRITICAL_SECTION cs_error;
+extern DWORD tls_error;
+extern kherr_context * ctx_free_list;
+extern kherr_event * evt_free_list;
+extern kherr_handler_node * ctx_handlers;
+extern khm_size n_ctx_handlers;
+
+#define parm_type(p) ((p).type)
+#define parm_data(p) ((p).data)
+
+void resolve_event_strings(kherr_event *);
+void attach_this_thread(void);
+void detach_this_thread(void);
+#endif
diff --git a/src/windows/identity/kherr/kherrmain.c b/src/windows/identity/kherr/kherrmain.c
index 0ae2292046..c7afd7bc25 100644
--- a/src/windows/identity/kherr/kherrmain.c
+++ b/src/windows/identity/kherr/kherrmain.c
@@ -1,52 +1,52 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<kherrinternal.h>
-
-void
-kherr_process_attach(void) {
- InitializeCriticalSection(&cs_error);
- tls_error = TlsAlloc();
-}
-
-void
-kherr_process_detach(void) {
- TlsFree(tls_error);
- DeleteCriticalSection(&cs_error);
-}
-
-void
-kherr_thread_attach(void) {
- /* We don't call attach_this_thread() here since we only
- want to create a context stack for this thread if
- someone wants one. */
- /* attach_this_thread(); */
-}
-
-void
-kherr_thread_detach(void) {
- detach_this_thread();
-}
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<kherrinternal.h>
+
+void
+kherr_process_attach(void) {
+ InitializeCriticalSection(&cs_error);
+ tls_error = TlsAlloc();
+}
+
+void
+kherr_process_detach(void) {
+ TlsFree(tls_error);
+ DeleteCriticalSection(&cs_error);
+}
+
+void
+kherr_thread_attach(void) {
+ /* We don't call attach_this_thread() here since we only
+ want to create a context stack for this thread if
+ someone wants one. */
+ /* attach_this_thread(); */
+}
+
+void
+kherr_thread_detach(void) {
+ detach_this_thread();
+}
diff --git a/src/windows/identity/kmm/kmm.c b/src/windows/identity/kmm/kmm.c
index 5e955953df..721865c4d2 100644
--- a/src/windows/identity/kmm/kmm.c
+++ b/src/windows/identity/kmm/kmm.c
@@ -1,192 +1,192 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<kmminternal.h>
-#include<assert.h>
-
-khm_boolean kmmint_load_locale_lib(kmm_module_i * m, kmm_module_locale * l)
-{
- HMODULE h;
-
- if(l->filename != NULL) {
- wchar_t path[MAX_PATH];
- DWORD dw;
-
- /* construct the path name */
- assert(m->h_module != NULL);
-
- dw = PathIsFileSpec(l->filename);
-
- assert(dw);
- if (!dw)
- return FALSE;
-
- dw = GetModuleFileName(m->h_module, path, ARRAYLENGTH(path));
- assert(dw != 0);
- if (dw == 0)
- return FALSE;
-
- PathRemoveFileSpec(path);
- dw = PathAppend(path, l->filename);
- assert(dw);
- if (!dw)
- return FALSE;
-
- h = LoadLibrary(path);
- if(!h)
- return FALSE;
-
- EnterCriticalSection(&cs_kmm);
- m->h_resource = h;
- m->lcid_resource = l->language;
- LeaveCriticalSection(&cs_kmm);
-
- return TRUE;
-
- } else {
- /* in this case, the language resources are assumed to be in the
- main module library itself. */
-
- EnterCriticalSection(&cs_kmm);
- m->h_resource = m->h_module;
- m->lcid_resource = l->language;
- LeaveCriticalSection(&cs_kmm);
-
- return TRUE;
- }
-}
-
-
-KHMEXP khm_int32 KHMAPI kmm_set_locale_info(kmm_module module, kmm_module_locale * locales, khm_int32 n_locales)
-{
- kmm_module_i * m;
- LANGID lcid;
- int i;
- int * f;
- khm_int32 rv = KHM_ERROR_SUCCESS;
-
- m = kmm_module_from_handle(module);
-
- if(!m || m->state != KMM_MODULE_STATE_INIT)
- return KHM_ERROR_INVALID_OPERATION;
-
- if(!locales || n_locales < 0)
- return KHM_ERROR_INVALID_PARAM;
-
- f = PMALLOC(n_locales * sizeof(int));
- if(!f)
- return KHM_ERROR_UNKNOWN;
- ZeroMemory(f, sizeof(int) * n_locales);
-
- lcid = GetUserDefaultLangID();
-
- /* first search for an exact match */
- for(i=0; i<n_locales; i++) {
- if(locales[i].language == lcid) {
- f[i] = TRUE;
- if(kmmint_load_locale_lib(m, &locales[i]))
- break;
- }
- }
-
- if(i<n_locales)
- goto _exit;
-
- /* ok, that didn't work. Try an inexact match. */
- for(i=0; i<n_locales; i++) {
- if(!f[i] && (PRIMARYLANGID(locales[i].language) == PRIMARYLANGID(lcid))) {
- f[i] = TRUE;
- if(kmmint_load_locale_lib(m,&locales[i]))
- break;
- }
- }
-
- if(i < n_locales)
- goto _exit;
-
- /* hmm. no matches yet. just try to locate the default locale */
- for(i=0; i<n_locales; i++) {
- if(!f[i] && (locales[i].flags & KMM_MLOC_FLAG_DEFAULT)) {
- f[i] = TRUE;
- if(kmmint_load_locale_lib(m,&locales[i]))
- break;
- }
- }
-
- if(i < n_locales)
- goto _exit;
-
- /* give up */
- rv = KHM_ERROR_NOT_FOUND;
-
-_exit:
- PFREE(f);
- return rv;
-}
-
-#ifdef _WIN32
-KHMEXP HMODULE KHMAPI kmm_get_resource_hmodule(kmm_module vm)
-{
- if(!kmm_is_module(vm))
- return NULL;
- else
- return (kmm_module_from_handle(vm))->h_resource;
-}
-#endif
-
-KHMEXP kmm_module KHMAPI
-kmm_this_module(void) {
- kmm_plugin_i * p;
- kmm_module_i * m;
- kmm_module vm;
-
- p = TlsGetValue(tls_kmm);
- if (!kmm_is_plugin(p))
- return NULL;
-
- m = p->module;
- vm = kmm_handle_from_module(m);
-
- kmm_hold_module(vm);
-
- return vm;
-}
-
-KHMEXP kmm_plugin KHMAPI
-kmm_this_plugin(void) {
- kmm_plugin_i * p;
- kmm_plugin vp;
-
- p = TlsGetValue(tls_kmm);
- if (!kmm_is_plugin(p))
- return NULL;
-
- vp = kmm_handle_from_plugin(p);
-
- kmm_hold_plugin(vp);
-
- return vp;
-}
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<kmminternal.h>
+#include<assert.h>
+
+khm_boolean kmmint_load_locale_lib(kmm_module_i * m, kmm_module_locale * l)
+{
+ HMODULE h;
+
+ if(l->filename != NULL) {
+ wchar_t path[MAX_PATH];
+ DWORD dw;
+
+ /* construct the path name */
+ assert(m->h_module != NULL);
+
+ dw = PathIsFileSpec(l->filename);
+
+ assert(dw);
+ if (!dw)
+ return FALSE;
+
+ dw = GetModuleFileName(m->h_module, path, ARRAYLENGTH(path));
+ assert(dw != 0);
+ if (dw == 0)
+ return FALSE;
+
+ PathRemoveFileSpec(path);
+ dw = PathAppend(path, l->filename);
+ assert(dw);
+ if (!dw)
+ return FALSE;
+
+ h = LoadLibrary(path);
+ if(!h)
+ return FALSE;
+
+ EnterCriticalSection(&cs_kmm);
+ m->h_resource = h;
+ m->lcid_resource = l->language;
+ LeaveCriticalSection(&cs_kmm);
+
+ return TRUE;
+
+ } else {
+ /* in this case, the language resources are assumed to be in the
+ main module library itself. */
+
+ EnterCriticalSection(&cs_kmm);
+ m->h_resource = m->h_module;
+ m->lcid_resource = l->language;
+ LeaveCriticalSection(&cs_kmm);
+
+ return TRUE;
+ }
+}
+
+
+KHMEXP khm_int32 KHMAPI kmm_set_locale_info(kmm_module module, kmm_module_locale * locales, khm_int32 n_locales)
+{
+ kmm_module_i * m;
+ LANGID lcid;
+ int i;
+ int * f;
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+
+ m = kmm_module_from_handle(module);
+
+ if(!m || m->state != KMM_MODULE_STATE_INIT)
+ return KHM_ERROR_INVALID_OPERATION;
+
+ if(!locales || n_locales < 0)
+ return KHM_ERROR_INVALID_PARAM;
+
+ f = PMALLOC(n_locales * sizeof(int));
+ if(!f)
+ return KHM_ERROR_UNKNOWN;
+ ZeroMemory(f, sizeof(int) * n_locales);
+
+ lcid = GetUserDefaultLangID();
+
+ /* first search for an exact match */
+ for(i=0; i<n_locales; i++) {
+ if(locales[i].language == lcid) {
+ f[i] = TRUE;
+ if(kmmint_load_locale_lib(m, &locales[i]))
+ break;
+ }
+ }
+
+ if(i<n_locales)
+ goto _exit;
+
+ /* ok, that didn't work. Try an inexact match. */
+ for(i=0; i<n_locales; i++) {
+ if(!f[i] && (PRIMARYLANGID(locales[i].language) == PRIMARYLANGID(lcid))) {
+ f[i] = TRUE;
+ if(kmmint_load_locale_lib(m,&locales[i]))
+ break;
+ }
+ }
+
+ if(i < n_locales)
+ goto _exit;
+
+ /* hmm. no matches yet. just try to locate the default locale */
+ for(i=0; i<n_locales; i++) {
+ if(!f[i] && (locales[i].flags & KMM_MLOC_FLAG_DEFAULT)) {
+ f[i] = TRUE;
+ if(kmmint_load_locale_lib(m,&locales[i]))
+ break;
+ }
+ }
+
+ if(i < n_locales)
+ goto _exit;
+
+ /* give up */
+ rv = KHM_ERROR_NOT_FOUND;
+
+_exit:
+ PFREE(f);
+ return rv;
+}
+
+#ifdef _WIN32
+KHMEXP HMODULE KHMAPI kmm_get_resource_hmodule(kmm_module vm)
+{
+ if(!kmm_is_module(vm))
+ return NULL;
+ else
+ return (kmm_module_from_handle(vm))->h_resource;
+}
+#endif
+
+KHMEXP kmm_module KHMAPI
+kmm_this_module(void) {
+ kmm_plugin_i * p;
+ kmm_module_i * m;
+ kmm_module vm;
+
+ p = TlsGetValue(tls_kmm);
+ if (!kmm_is_plugin(p))
+ return NULL;
+
+ m = p->module;
+ vm = kmm_handle_from_module(m);
+
+ kmm_hold_module(vm);
+
+ return vm;
+}
+
+KHMEXP kmm_plugin KHMAPI
+kmm_this_plugin(void) {
+ kmm_plugin_i * p;
+ kmm_plugin vp;
+
+ p = TlsGetValue(tls_kmm);
+ if (!kmm_is_plugin(p))
+ return NULL;
+
+ vp = kmm_handle_from_plugin(p);
+
+ kmm_hold_plugin(vp);
+
+ return vp;
+}
diff --git a/src/windows/identity/kmm/kmm.h b/src/windows/identity/kmm/kmm.h
index d10f2150e6..735f006add 100644
--- a/src/windows/identity/kmm/kmm.h
+++ b/src/windows/identity/kmm/kmm.h
@@ -1,1068 +1,1068 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#ifndef __KHIMAIRA_KMM_H
-#define __KHIMAIRA_KMM_H
-
-#include<khdefs.h>
-#include<kmq.h>
-
-/*! \defgroup kmm NetIDMgr Module Manager
-@{*/
-
-/*! \brief A handle to a module.
-*/
-typedef khm_handle kmm_module;
-
-/*! \brief A handle to a plugin.
- */
-typedef khm_handle kmm_plugin;
-
-/*! \name Limits
- @{*/
-
-/*! \brief Maximum number of characters in a name in KMM including the terminating NULL */
-#define KMM_MAXCCH_NAME 256
-
-/*! \brief Maximum number of bytes in a name in KMM including the terminating NULL */
-#define KMM_MAXCB_NAME (sizeof(wchar_t) * KMM_MAXCCH_NAME)
-
-/*! \brief Maximum number of characters in a description in KMM including the terminating NULL */
-#define KMM_MAXCCH_DESC 512
-
-/*! \brief Maximum number of bytes in a description in KMM including the terminating NULL */
-#define KMM_MAXCB_DESC (sizeof(wchar_t) * KMM_MAXCCH_NAME)
-
-/*! \brief Maximum number of characters in a vendor string in KMM including the terminating NULL */
-#define KMM_MAXCCH_VENDOR 256
-
-/*! \brief Maximum number of bytes in a vendor string in KMM including the terminating NULL */
-#define KMM_MAXCB_VENDOR (sizeof(wchar_t) * KMM_MAXCCH_VENDOR)
-
-/*! \brief Maximum number of characters in a support URI in KMM including the terminating NULL */
-#define KMM_MAXCCH_SUPPORT 256
-
-/*! \brief Maximum number of bytes in a vendor string in KMM including the terminating NULL */
-#define KMM_MAXCB_SUPPORT (sizeof(wchar_t) * KMM_MAXCCH_SUPPORT)
-
-/*! \brief Maximum number of dependencies per plugin
-*/
-#define KMM_MAX_DEPENDENCIES 8
-
-/*! \brief Maximum number of dependants per plugin
- */
-#define KMM_MAX_DEPENDANTS 32
-
-/*! \brief Maximum number of characters a dependency string including trailing double NULL */
-#define KMM_MAXCCH_DEPS (KMM_MAXCCH_NAME * KMM_MAX_DEPENDENCIES + 1)
-
-/*! \brief Maximum number of bytes in a dependency string including trailing double NULL */
-#define KMM_MAXCB_DEPS (sizeof(wchar_t) * KMM_MAXCCH_DEPS)
-/*@}*/ /* Limits */
-
-/*! \brief Plugin registration
-
- \see ::khm_cred_provider
-*/
-typedef struct tag_kmm_plugin_reg {
- wchar_t * name; /*!< Name of the plugin. Maximum of
- KMM_MAXCCH_NAME characters
- including the terminating
- NULL. Required. */
-
- wchar_t * module; /*!< Name of module that owns the
- plugin. Maximum of
- KMM_MAXCCH_NAME characters
- including terminating NULL.
- Required. */
-
- khm_int32 type; /*!< Type plugin type. One of
- KHM_PITYPE_*. Required. */
- khm_int32 flags; /*!< Unused. Set to 0 */
- kmq_callback_t msg_proc; /*!< Message processor. Required. */
- wchar_t * dependencies; /*!< Dependencies. Note that this is
- a multi string. (you can use the
- KHC multi string functions to
- manipulate multi strings or to
- convert a comma separated list of
- dependencies to a multi string).
- Each string in the multi string
- is a name of a plugin that this
- plugin depends on. Optional (set
- to NULL if this plugin has no
- dependencies). Maximum of
- KMM_MAXCCH_DEPS characters
- including terminating double
- NULL.*/
-
- wchar_t * description; /*!< Description of the plugin.
- Maximum of KMM_MAXCCH_DESC
- characters including the
- terminating
- NULL. Localized. Optional (set to
- NULL if not provided) */
-#ifdef _WIN32
- HICON icon; /*!< Icon used to represent the
- plugin. Optional. (set to NULL if
- not provided) */
-#endif
-} kmm_plugin_reg;
-
-/*! \brief Plugin information
-*/
-typedef struct tag_kmm_plugin_info {
- kmm_plugin_reg reg; /*!< Registration info */
-
- khm_int32 state; /*!< Current status of the plugin.
- One of ::_kmm_plugin_states */
-
- khm_int32 failure_count; /*!< Number of recorded failures in
- the plugin */
- FILETIME failure_time; /*!< Time of first recorded failure */
- khm_int32 failure_reason; /*!< The reason for the first recorded
- failure */
-
- kmm_plugin h_plugin; /*!< Handle to plugin */
-
- khm_int32 flags; /*!< Flags for the plugin. Currently
- this can only specify
- ::KMM_PLUGIN_FLAG_DISABLED. */
-} kmm_plugin_info;
-
-/*! \brief The plugin is disabled
-
- This flag will be set in the \a flags field of the
- ::kmm_plugin_info structure for a plugin that has been marked as
- disabled. If the plugin is currently running, but marked as
- disabled for future sessions, then this bit will be set in \a
- flags , but the \a state of the plugin will indicate that the
- plugin is running.
- */
-#define KMM_PLUGIN_FLAG_DISABLED 0x00000400
-
-/*! \name Plugin types
-@{*/
-/*! \brief A credentials provider
-
- \see \ref pi_pt_cred for more information.
- */
-#define KHM_PITYPE_CRED 1
-
-/*! \brief A identity provider
-
- \see \ref pi_pt_cred for more information
- */
-#define KHM_PITYPE_IDENT 2
-
-/*! \brief A configuration provider
-
- \see \ref pi_pt_conf for more information.
- */
-#define KHM_PITYPE_CONFIG 3
-
-/*! \brief Undefined plugin type
-
- The plugin doesn't provide any credential type.
- */
-#define KHM_PITYPE_MISC 4
-
-/*@}*/
-
-/*! \brief Plugin states */
-enum _kmm_plugin_states {
- KMM_PLUGIN_STATE_FAIL_INIT = -6, /*!< Failed to initialize */
- KMM_PLUGIN_STATE_FAIL_UNKNOWN = -5, /*!< Failed due to unknown
- reasons */
- KMM_PLUGIN_STATE_FAIL_MAX_FAILURE = -4, /*!< The plugin has
- reached the maximum number
- of failures and cannot be
- initialized until the
- failure count is reset */
- KMM_PLUGIN_STATE_FAIL_NOT_REGISTERED = -3, /*!< Failed because the
- plugin was not registered
- and automatic registration
- failed. */
- KMM_PLUGIN_STATE_FAIL_DISABLED = -2,/*!< Failed because plugin was
- disabled by the user. */
- KMM_PLUGIN_STATE_FAIL_LOAD = -1, /*!< The plugin failed to load
- due to some unknown
- reason. */
- KMM_PLUGIN_STATE_NONE = 0, /*!< Unknown state */
- KMM_PLUGIN_STATE_PLACEHOLDER, /*!< Placeholder. The plugin
- hasn't been provided by
- anyone yet, but the plugin
- record has been created to
- keep track of
- dependencies. */
- KMM_PLUGIN_STATE_REG, /*!< The plugin is registered
- but not initialized */
- KMM_PLUGIN_STATE_PREINIT, /*!< The plugin is in the
- process of being
- initialized */
- KMM_PLUGIN_STATE_HOLD, /*!< On hold. One or more
- dependencies of this plugin
- has not been resolved */
- KMM_PLUGIN_STATE_INIT, /*!< The plugin was initialized */
- KMM_PLUGIN_STATE_RUNNING, /*!< The plugin is running */
- KMM_PLUGIN_STATE_EXITED /*!< The plugin has been stopped. */
-};
-
-/*! \brief Module registration */
-typedef struct tag_kmm_module_reg {
- wchar_t * name; /*!< Identifier for the module */
- wchar_t * path; /*!< Full pathname to module
- binary */
-
- wchar_t * description; /*!< Description of module */
-
- wchar_t * vendor; /*!< Vendor/copyright string */
-
- wchar_t * support; /*!< Support URL/contact */
-
- khm_int32 n_plugins; /*!< Number of plugins that are
- active */
- kmm_plugin_reg * plugin_reg_info; /*!< Array of kmm_plugin_reg
- records for each active
- plugin */
-} kmm_module_reg;
-
-/*! \brief Module information record */
-typedef struct tag_kmm_module_info {
- kmm_module_reg reg; /*!< Registration info */
-
- khm_ui_4 language; /*!< Currently loaded langugage */
-
- khm_int32 state; /*!< Current status of the
- module */
-
- khm_version file_version; /*!< File version for the
- module */
- khm_version product_version; /*!< Product version for the
- module */
-
- khm_int32 failure_count; /*!< Number of times the module
- has failed to load */
- FILETIME failure_time; /*!< Time of first recorded
- failure */
- khm_int32 failure_reason; /*!< Reason for first failure.
- One of the module status
- values */
-
- kmm_module h_module; /*!< Handle to the module. */
-} kmm_module_info;
-
-/*! \brief Module states
-*/
-enum KMM_MODULE_STATES {
- KMM_MODULE_STATE_FAIL_INCOMPAT=-12, /*!< The library containing
- the module was not
- compatible with this version
- of NetIDMgr. */
- KMM_MODULE_STATE_FAIL_INV_MODULE=-11, /*!< The library containing
- the module was invalid. */
- KMM_MODULE_STATE_FAIL_UNKNOWN=-10, /*!< Module could not be
- loaded due to unknown
- reasons. */
- KMM_MODULE_STATE_FAIL_MAX_FAILURE=-9,/*!< The module has failed
- too many times already. Not
- attempting to restart it
- again */
- KMM_MODULE_STATE_FAIL_DUPLICATE=-8, /*!< An attempt was made to
- load the same module
- twice. */
- KMM_MODULE_STATE_FAIL_NOT_REGISTERED=-7, /*!< The module is not
- found among the registered
- module list */
- KMM_MODULE_STATE_FAIL_NO_PLUGINS=-6,/*!< The module provided no
- plugins, or all the plugins
- that are provided are
- disabled */
- KMM_MODULE_STATE_FAIL_DISABLED=-5, /*!< Module is disabled and
- cannot be loaded */
- KMM_MODULE_STATE_FAIL_LOAD=-4, /*!< The module failed to
- initialize */
- KMM_MODULE_STATE_FAIL_INVALID=-3, /*!< The module was invalid.
- Typically caused by the
- required entrypoints not
- being present */
- KMM_MODULE_STATE_FAIL_SIGNATURE=-2, /*!< The module failed to load
- due to an unverifiable
- signature */
- KMM_MODULE_STATE_FAIL_NOT_FOUND=-1, /*!< The module was not
- found */
- KMM_MODULE_STATE_NONE=0, /*!< Unknown state. The handle
- is possibly invalid */
- KMM_MODULE_STATE_PREINIT, /*!< The module is being
- loaded. init_module() hasn't
- been called yet */
- KMM_MODULE_STATE_INIT, /*!< In init_module() */
- KMM_MODULE_STATE_INITPLUG, /*!< Initializing plugins */
- KMM_MODULE_STATE_RUNNING, /*!< Running */
- KMM_MODULE_STATE_EXITPLUG, /*!< Currently exiting plugins */
- KMM_MODULE_STATE_EXIT, /*!< Currently exiting */
- KMM_MODULE_STATE_EXITED /*!< Exited */
-};
-
-/*! \brief Start the Module Manager
-
- \note Only called by the NetIDMgr core.
-*/
-KHMEXP void KHMAPI
-kmm_init(void);
-
-/*! \brief Stop the Module Manager
-
- \note Only called by the NetIDMgr core.
-*/
-KHMEXP void KHMAPI
-kmm_exit(void);
-
-/*! \brief Return the plugin handle for the current plugin
-
- The returned handle represents the plugin which owns the current
- thread. The returned handle must be released by calling
- kmm_release_plugin(). Returns NULL if the current thread is not
- owned by any plugin.
- */
-KHMEXP kmm_plugin KHMAPI
-kmm_this_plugin(void);
-
-/*! \brief Return the module handle for the current module
-
- The returned handle represents the module which owns the current
- thread. The returned handle must be released by calling
- kmm_release_module()
-*/
-KHMEXP kmm_module KHMAPI
-kmm_this_module(void);
-
-/*! \name Flags for kmm_load_module()
-@{*/
-/*!\brief Load synchronously
-
- If this flag is set, then the function waits for the module to be
- loaded. The default is to load the module asynchronously.
-
- When loading a module asynchronously, the kmm_load_module()
- function returns KHM_ERROR_SUCCESS and exits without waiting for
- the module to load. If \a result is not NULL, it will receive a
- valid handle to the module.
-
- When loading a module synchronously, kmm_load_module() will wait
- for the module to completely load. If it fails to load properly,
- it will return an error code and set \a result to NULL.
-*/
-#define KMM_LM_FLAG_SYNC 1
-
-/*! \brief Do not load
-
- Indicates that the module shouldn't actually be loaded. If the
- specified module name identifies a module that has already been
- loaded, then the function returns a held handle to the existing
- module (use kmm_release_module() to free the handle). Otherwise,
- the function returns KHM_ERROR_NOT_FOUND.
-*/
-#define KMM_LM_FLAG_NOLOAD 2
-/*@}*/
-
-/*! \brief Load a module
-
- The \a modulename parameter specifies a module to load. Depending
- on the configuration, not all of the plugins that are provided by
- the module may be loaded. If no plugins are successfully loaded,
- the module will be immediately unloaded.
-
- If the module is currently loaded or is being loaded, then a valid
- handle to the existing module is returned.
-
- When called with KMM_LM_FLAG_SYNC, the function does not return
- until the module and the associated plugins are all initialized,
- or an error occurs.
-
- If the KMM_LM_FLAG_NOLOAD flag is set, then a handle to an
- existing instance of the module will be returned. If the module
- hasn't been loaded yet, then no handle is returned and the
- function returns KHM_ERROR_NOT_FOUND.
-
- See the associated NetIDMgr Module Manager documentation on the
- sequence of events associated with loading a module.
-
- \param[in] modulename Name of the module. The module should have
- been registered under this name prior to the call.
- \param[in] flags Combination of KMM_LM_FLAG_*
- \param[out] result Receives a handle to the loaded module. If the
- result is not required, set this to NULL. If \a result is not
- NULL, and km_load_module() returns KHM_ERROR_SUCCESS, then
- kmm_release_module() must be called to release the handle to
- the module. Otherwise, \a result receives NULL. If a handle
- is returned, it will be valid regardless of whether the module
- fails to load or not. You can use kmm_get_module_state() to
- query the progress of the loading process. See
- ::KMM_LM_FLAG_SYNC.
-
- \retval KHM_ERROR_SUCCESS The call succeeded. If \a
- KMM_LM_FLAG_SYNC was specified, this means that the module was
- successfully loaded. Otherwise, it only means that the module
- has been queued up for loading. Use kmm_get_module_state() to
- determine if it was successfully loaded. If \a result is not
- NULL, a valid handle is returned.
- \retval KHM_ERROR_EXISTS The module is already loaded or has been
- already queued for loading. If \a result is not NULL, a valid
- handle to the existing module instance is returned.
- \retval KHM_ERROR_NOT_FOUND If called with KMM_LM_FLAG_NOLOAD,
- indicates that the module has not been loaded. Otherwise only
- returned when called with KMM_LM_FLAG_SYNC. The module image
- was not found. No handle is returned.
- \retval KHM_ERROR_INVALID_SIGNATURE Only returned when called with
- KMM_LM_FLAG_SYNC. The module was signed with an invalid
- certificate. No handle is returned.
- \retval KHM_ERROR_UNKNOWN Only returned when called with
- KMM_LM_FLAG_SYNC. Some other error has occured. No handle is
- returned.
-
- \see \ref pi_fw_pm_load
- \see ::KMM_LM_FLAG_SYNC, ::KMM_LM_FLAG_NOLOAD
-*/
-KHMEXP khm_int32 KHMAPI
-kmm_load_module(wchar_t * modname, khm_int32 flags, kmm_module * result);
-
-/*! \brief Hold a handle to a module
-
- Use kmm_release_module() to release the hold.
-*/
-KHMEXP khm_int32 KHMAPI
-kmm_hold_module(kmm_module module);
-
-/*! \brief Release a handle to a module
-
- Release a held referece to a module that was returned in a call to
- kmm_load_module().
-*/
-KHMEXP khm_int32 KHMAPI
-kmm_release_module(kmm_module m);
-
-/*! \brief Query the state of a module
-
- When loading a module asynchronously you can query the state of
- the loading process using this. The return value is a status
- indicator.
-
- \return The return value is one of the ::KMM_MODULE_STATES
- enumerations.
-*/
-KHMEXP khm_int32 KHMAPI
-kmm_get_module_state(kmm_module m);
-
-/*! \brief Unload a module
-
- See the associated NetIDMgr Module Manager documentation on the
- sequence of events associated with unloading a module.
-
- \see \ref pi_fw_pm_unload
-*/
-KHMEXP khm_int32 KHMAPI
-kmm_unload_module(kmm_module module);
-
-/*! \brief Loads the default modules as specified in the configuration
-
- The configuration can specify the default set of modules to load.
- This function dispatches the necessary message for loading these
- modules and reutnrs.
-*/
-KHMEXP khm_int32 KHMAPI
-kmm_load_default_modules(void);
-
-/*! \brief Checks whether there are any pending loads
-
- Returns TRUE if there are modules still waiting to be loaded.
-*/
-KHMEXP khm_boolean KHMAPI
-kmm_load_pending(void);
-
-#ifdef _WIN32
-
-/*! \brief Returns the Windows module handle from a handle to a NetIDMgr module.
- Although it is possible to obtain the Windows module handle and
- use it to call Windows API functions, it is not recommended to do
- so. This is because that might cause the state of the module to
- change in ways which are inconsistent from the internal data
- structures that kmm maintains.
- */
-KHMEXP HMODULE KHMAPI
-kmm_get_hmodule(kmm_module m);
-#endif
-
-/*! \brief Hold a plugin
-
- Obtains a hold on a plugin. The plugin handle will remain valid
- until the hold is released with a call to kmm_release_plugin().
- No guarantees are made on the handle once the handle is released.
- */
-KHMEXP khm_int32 KHMAPI
-kmm_hold_plugin(kmm_plugin p);
-
-/*! \brief Release a plugin
-
- Releases a hold on a plugin obtained through a call to
- kmm_hold_plugin(). The plugin handle should no longer be
- considered valied once this is called.
- */
-KHMEXP khm_int32 KHMAPI
-kmm_release_plugin(kmm_plugin p);
-
-/*! \brief Provide a plugin
-
- This function must be called for each plugin that the module
- provides.
-
- Note that this function returns immediately and does not
- initialize the plugin. All plugins that are provided by a
- module will be initialized once the init_module() function
- returns. If the plugin has dependencies, it will be kept in a
- held state until the plugins that it depends on are successfully
- initialized. If the dependencies are not resolved (the dependent
- plugins are not loaded), then plugin will not be initialized.
-
- If the plugin is not registered and \a plugin contains enough
- information to perform the registration, then it will be
- automatically registered. However, if the plugin is not
- registered and cannot be registered using the provided
- information, the plugin will not be initialized properly. Note
- that automatic registration will always register the plugin in the
- user configuration store.
-
- The \a name and \a msg_proc members of \a plugin are required to
- have valid values. The \a icon member may optionally be
- specified. The other fields can be specified if the plugin should
- be automatically registered, however, the \a module field will be
- ignored and will be determined by the \a module handle.
-
- \param[in] module Handle to this module that is providing the plugin.
- \param[in] plugin A plugin descriptor.
-
- \retval KHM_ERROR_SUCCESS Succeeded.
- \retval KHM_ERROR_INVALID_OPERATION The function was not called
- during init_module()
- \retval KHM_ERROR_INVALID_PARAM One or more parameters were invalid
- \retval KHM_ERROR_DUPLICATE The plugin was already provided
-
- \note This can only be called when handing init_module()
-*/
-KHMEXP khm_int32 KHMAPI
-kmm_provide_plugin(kmm_module module, kmm_plugin_reg * plugin);
-
-/*! \brief Query the state of a plugin.
-
- \return One of ::_kmm_plugin_states
-*/
-KHMEXP khm_int32 KHMAPI
-kmm_get_plugin_state(wchar_t * plugin);
-
-/*! \defgroup kmm_reg Registration
-
- The functions for managing plugin and module registration. These
- functions are also available as static linked libraries for use by
- external applications which must register or unregister plugins or
- modules.
-@{*/
-
-/*! \brief Obtain the configuration space for a named plugin
-
- Note that the named plugin does not have to actually exist.
- Configuration spaces for plugins are based solely on the plugin
- name and hence can be accessed regardless of whether the specific
- plugin is loaded or not.
-
- \param[in] flags Controls the options for opening the
- configuration space. If KHM_FLAG_CREATE is specified, then
- the configuration space for the plugin named \a plugin wil be
- created if it doesn't already exist. The \a flags parameter
- is directly passed into a call to khc_open_space().
-
- \param[in] plugin Name of the plugin. The name can not contain
- slashes.
-
- \param[out] result Receives a configuration space handle. The
- calling application should free the handle using
- khc_close_space().
-
- \see khc_open_space()
- \see khc_close_space()
- */
-KHMEXP khm_int32 KHMAPI
-kmm_get_plugin_config(wchar_t * plugin, khm_int32 flags, khm_handle * result);
-
-/*! \brief Obtain the configuration space or a named module
-
- The named module does not have to actually exist. Configuration
- spaces for modules are based on the basename of the module
- (including the extension).
-
- \param[in] module Name of the module.
-
- \param[in] flags The flags used to call khc_open_space(). You can
- use this to specify a particular configuration store if
- needed.
-
- \param[out] result Receives the handle to a configuration space if
- successful. Call khc_close_space() to close the handle.
-
- \see khc_open_space()
- \see khc_close_space()
-*/
-KHMEXP khm_int32 KHMAPI
-kmm_get_module_config(wchar_t * module, khm_int32 flags, khm_handle * result);
-
-/*! \brief Retrieve a handle to the configuration space for plugins
-
- The configuration space for plugins is a container which holds the
- configuration subspaces for all the plugins. This is the config
- space which must be used to load a configuration space for a
- plugin.
-
- \param[in] flags The flags to pass in to the call to
- khc_open_space(). The flags can be used to select a specific
- configuration store if needed.
-
- \param[out] result Receives a handle to the configuration
- space. Call khc_close_space() to close the handle
-
- \see khc_open_space()
- \see khc_close_space()
- */
-KHMEXP khm_int32 KHMAPI
-kmm_get_plugins_config(khm_int32 flags, khm_handle * result);
-
-/*! \brief Retrieve the handle to the configuration space for modules
-
- The configuration space for modules is a container which hold the
- configuration subspaces for all the modules. Each module
- registration ends up in this subspace.
-
- \param[in] flags The flags to pass in to the call to
- khc_open_space(). The flags can be used to select a specific
- configuration store if needed.
-
- \param[out] result Receives a handle to the configuration space.
- Call khc_close_space() to close the handle.
-
- \see khc_open_space()
- \see khc_close_space()
- */
-KHMEXP khm_int32 KHMAPI
-kmm_get_modules_config(khm_int32 flags, khm_handle * result);
-
-/*! \brief Return information about a loaded module
-
- The retrieves a block of information about a module. Refer to
- ::kmm_module_info for information about the format of the returned
- data.
-
- Note that the size of the required buffer is actually greater than
- the size of the ::kmm_module_info structure and accomodates the
- ::kmm_plugin_info structures and strings required to complete the
- information block.
-
- Call the function with \a buffer set to NULL and \a cb_buffer
- pointing at a khm_size variable to obtain the required size of the
- buffer.
-
- \param[in] module_name Name of a module
- \param[in] flags Flags indicating which types of information to
- return
- \param[out] buffer Points to a buffer that recieves information.
- Set this to NULL if only the size of the buffer is required.
- \param[in,out] On entry, contains the size of the buffer pointed
- to by \a buffer if \a buffer is not NULL. On exit, contains
- the required size of the buffer or the number of actual bytes
- copied.
-
- \retval KHM_ERROR_SUCCESS The requested information was copied
- \retval KHM_ERROR_INVALID_PARAM One of the parameters was invalid
- \retval KHM_ERROR_TOO_LONG The buffer was not large enough or was
- NULL. The number of bytes requied is in \a cb_buffer.
- \retval KHM_ERROR_NOT_FOUND The specified module is not a
- registered module.
- */
-KHMEXP khm_int32 KHMAPI
-kmm_get_module_info(wchar_t * module_name, khm_int32 flags,
- kmm_module_info * buffer, khm_size * cb_buffer);
-
-/*! \brief Get information about a module
-
- Similar to kmm_get_module_info(), but uses a module handle instead
- of a name, and uses internal buffers for providing string fields.
-
- The information that is returned should be freed using a call to
- kmm_release_module_info_i().
-
- \see kmm_release_module_info_i()
- */
-KHMEXP khm_int32 KHMAPI
-kmm_get_module_info_i(kmm_module module, kmm_module_info * info);
-
-/*! \brief Release module information
-
- Releases the information returned by a previous call to
- kmm_get_module_info_i(). The contents of the ::kmm_module_info
- structure should not have been modified in any way between calling
- kmm_get_module_info_i() and kmm_release_module_info_i().
- */
-KHMEXP khm_int32 KHMAPI
-kmm_release_module_info_i(kmm_module_info * info);
-
-/*! \brief Obtain information about a plugin
-
- Retrieve a block of information about a plugin. See
- ::kmm_plugin_info for details about what information can be
- returned. Note that some fields may not be available if the
- module is not loaded.
-
- Note that the size of the required buffer is greater than the size
- of the ::kmm_plugin_info structure and accounts for strings as
- well. Call kmm_get_plugin_info() with \a buffer set to NULL and
- \a cb_buffer set to point to a variable of type \a khm_size to
- obtain the required size of the structure.
-
- \param[in] plugin_name Name of the plugin
- \param[out] buffer The buffer to receive the plugin information.
- Set to \a NULL if only the size of the buffer is required.
- \param[in,out] cb_buffer On entry, points to variable that
- specifies the size of the buffer pointed to by \a buffer is \a
- buffer is not \a NULL. On exit, holds the number of bytes
- copied or the required size of the buffer.
-
- \retval KHM_ERROR_SUCCESS The requested information was
- successfully copied to the \a buffer
- \retval KHM_ERROR_TOO_LONG The buffer was either \a NULL or
- insufficient to hold the requested information. The required
- size of the buffer was stored in \a cb_buffer
- \retval KHM_ERROR_INVALID_PARAM One or more parameters were
- invlaid.
- \retval KHM_ERROR_NOT_FOUND The specified plugin was not found
- among the registered plugins.
-*/
-KHMEXP khm_int32 KHMAPI
-kmm_get_plugin_info(wchar_t * plugin_name,
- kmm_plugin_info * buffer,
- khm_size * cb_buffer);
-
-/*! \brief Obtain information about a plugin using a plugin handle
-
- Similar to kmm_get_plugin_info() but uses a plugin handle instead
- of a plugin name. If the call is successful, the \a info
- structure will be filled with information about the plugin. The
- returned info should not be modified in any way and may contain
- pointers to internal buffers.
-
- The returned information must be released with a call to
- kmm_release_plugin_info_i().
- */
-KHMEXP khm_int32 KHMAPI
-kmm_get_plugin_info_i(kmm_plugin p, kmm_plugin_info * info);
-
-/*! \brief Release plugin information returned by kmm_get_plugin_info_i
-
- The information returned by kmm_get_plugin_info_i() should not be
- modified in any way before calling kmm_release_plugin_info_i().
- Once the call completes, the contents of \a info will be
- initialized to zero.
- */
-KHMEXP khm_int32 KHMAPI
-kmm_release_plugin_info_i(kmm_plugin_info * info);
-
-/*! \brief Enumerates plugins
-
- Enumerates through known plugins. This list may not include
- plugins which were not loaded by NetIDMgr in this session.
-
- If the call is successful, a handle to the next plugin in the list
- will be placed in \a p_next. The returned handle must be freed
- with a call to kmm_release_plugin().
-
- If the \a p parameter is set to NULL, then the first plugin handle
- will be placed in \a p_next. The handles will not be returned in
- any specific order. In addition, the enumeration may not include
- all known plugins if the list of plugins changes during
- enumeration.
- */
-KHMEXP khm_int32 KHMAPI
-kmm_get_next_plugin(kmm_plugin p, kmm_plugin * p_next);
-
-/*! \brief Enables or disables a plugin
-
- This function currently does not take effect immediately. However
- it marks the plugin as enabled or disabled so that the next time
- NetIDMgr starts, the module manager will act accordingly.
-
- \param[in] p Handle to the plugin
-
- \param[in] enable If non-zero, the plugin will be marked as
- enabled. Otherwise the plugin will be marked as disabled.
- */
-KHMEXP khm_int32 KHMAPI
-kmm_enable_plugin(kmm_plugin p, khm_boolean enable);
-
-/*! \brief Register a plugin
-
- The \a plugin member defines the plugin to be registered. The \a
- msg_proc and \a icon members of the structure are ignored.
-
- At the time kmm_register_plugin() is called, the module specified
- by \a module member of the \a plugin parameter must have been already
- registered. Otherwise the function call fails.
-
- If the plugin has already been registered, then all the fields in
- the plugin registration will be updated to be in sync with the
- information provided in the \a plugin parameter. The failure
- counts and associated statistics will not be reset when the
- configuration information is updated.
-
- If the plugin has not been registered, the a new registration
- entry is created in the configuration space indicated by the \a
- config_flags parameter. In addition, the plugin will be added to
- the list of plugins associated with the owning module.
-
- Note that the module that owns the plugin must be registered in
- the same configuration store as the plugin.
-
- \param[in] plugin Registration info for the plugin. The \a
- msg_proc and \a icon members are ignored. All other fields
- are required. The \a description member should be localized
- to the system locale when registering a plugin in the machine
- configuration store and should be localized to the user locale
- when registering a plugin in the user configuration store.
- \param[in] config_flags Flags for the configuration provider.
- These flags are used verbatim to call khc_open_space(), hence
- they may be used to pick whether or not the registration is
- per machine or per user.
-
- \see kmm_register_module()
- */
-KHMEXP khm_int32 KHMAPI
-kmm_register_plugin(kmm_plugin_reg * plugin, khm_int32 config_flags);
-
-/*! \brief Register a module
-
- The \a module parameter specifies the parameters for the module
- registration.
-
- The \a plugin_info member should point to an array of
- ::kmm_plugin_info structures unless the \a n_plugins member is
- zero, in which case \a plugin_info can be \a NULL. Plugins can be
- registered separately using kmm_register_plugin().
-
- \param[in] module Information about the module. The name and path
- fields are required. The \a plugin_info field can only be \a
- NULL if \a n_plugins is zero.
-
- \param[in] config_flags Flags used to call khc_open_space(). This
- can be used to choose the configuration store in which the
- module registration will be performed.
- */
-KHMEXP khm_int32 KHMAPI
-kmm_register_module(kmm_module_reg * module, khm_int32 config_flags);
-
-/*! \brief Unregister a plugin
-
- Registration information associated with the plugin will be
- removed. In addtion, the plugin will be removed from the list of
- plugins provided by the owner module.
-
- \param[in] plugin Names the plugin to be removed
- \param[in] config_flags Flags used to call khc_open_space(). Can
- be used to choose the configuraiton store that is affected by
- the call.
-
- \note kmm_unregister_plugin() has no effect on whether the plugin
- is loaded or not. The caller must make sure that the plugin
- is unloaded and the associated module is either also unloaded
- or in a state where the plugin can be unregistered.
- */
-KHMEXP khm_int32 KHMAPI
-kmm_unregister_plugin(wchar_t * plugin, khm_int32 config_flags);
-
-/*! \brief Unregister a module
-
- Registration information associated with the module as well as all
- the plugins provided by the module will be removed from the
- configuration store.
-
- \param[in] module Names the module to be removed
-
- \param[in] config_flags Flags used to call khc_open_space(). Can
- be used to choose the configuration store affected by the
- call.
-
- \note kmm_unregister_module() has no effect on the loaded state of
- the module. The caller should make sure that the module is
- unloaded and in a state where it can be unregistered.
- */
-KHMEXP khm_int32 KHMAPI
-kmm_unregister_module(wchar_t * module, khm_int32 config_flags);
-
-/*@}*/ /* kmm_reg */
-
-/*! \defgroup kmm_loc Internationalization support
-
- See \ref pi_localization for more information about
- internationalization.
-
-@{*/
-
-/*! \brief Locale descriptor record
-
- See kmm_set_locale()
-*/
-typedef struct tag_kmm_module_locale {
- khm_ui_4 language; /*!< A language ID. On Windows, you can use the
- MAKELANGID macro to generate this value. */
- wchar_t * filename; /*!< The filename corresponding to this language.
- Use NULL to indicate that resources for this
- language are to be found in the main module. */
- khm_int32 flags; /*!< Flags. Combination of KMM_MLOC_FLAG_* */
-} kmm_module_locale;
-
-#define LOCALE_DEF(language_id, filename, flags) {language_id, filename, flags}
-
-/*! \brief Default (fallback) locale
-*/
-#define KMM_MLOC_FLAG_DEFAULT 1
-
-
-/*! \brief Sets the locale for a loaded module.
-
- The given locale records are searched in the given order until a
- locale that matches the current user locale is found. If no
- locales match, then the first locale with the
- ::KMM_MLOC_FLAG_DEFAULT flag set will be loaded. If no locales
- have that flag set, then the first locale is loaded.
-
- You can obtain a handle to the loaded library using
- kmm_get_resource_hmodule(). This function does not return until a
- matched library is loaded.
-
- Note that the ::kmm_module_locale structure only specifies a
- module name for the resource module. This resource module must
- exist in the same directory as the \a module.
-
- \param[in] module The module handle
- \param[in] locales An array of ::kmm_module_locale objects
- \param[in] n_locales The number of objects in the array pointed to by \a locales
-
- \retval KHM_ERROR_SUCCESS Succeeded.
- \retval KHM_ERROR_NOT_FOUND A matching locale resource library was not found.
- \retval KHM_ERROR_INVALID_OPERATION The function was called on a module which is currently not being initalized.
-
- \see \ref pi_localization
- \see kmm_get_resource_hmodule()
-
- \note This can only be called when handing init_module()
-*/
-KHMEXP khm_int32 KHMAPI
-kmm_set_locale_info(kmm_module module,
- kmm_module_locale * locales,
- khm_int32 n_locales);
-
-#ifdef _WIN32
-
-/*! \brief Return the Windows module handle of the resource library of a NetIDMgr module.
-
- NetIDMgr allows the specification of an alternate resource library
- that will be used to load localized resources from. This function
- returns a handle to this library.
-
- While you can use the convenience macros to access resources in a
- localization library using the module handle, it is recommended,
- for performance reasons, to use this function to obtain the handle
- to the resource library and then use that handle in calls to
- LoadString, LoadImage etc. directly.
-*/
-KHMEXP HMODULE KHMAPI
-kmm_get_resource_hmodule(kmm_module m);
-
-/*! \name Convenience Macros
-@{*/
-/*! \brief Convenience macro for using calling LoadAccelerators using a module handle
-
- \param[in] module A handle to a loaded module. The corresponding resource
- module will be located through a call to kmm_get_resource_hmodule()
-*/
-#define kmm_LoadAccelerators(module, lpTableName) \
- (LoadAccelerators(kmm_get_resource_hmodule(module), lpTableName))
-
-/*! \brief Convenience macro for using calling LoadBitmap using a module handle
-
- \param[in] module A handle to a loaded module. The corresponding resource
- module will be located through a call to kmm_get_resource_hmodule()
-*/
-#define kmm_LoadBitmap(module, lpBitmapName) \
- (LoadBitmap(kmm_get_resource_hmodule(module), lpBitmapName))
-
-/*! \brief Convenience macro for using calling LoadImage using a module handle
-
- \param[in] module A handle to a loaded module. The corresponding resource
- module will be located through a call to kmm_get_resource_hmodule()
-*/
-#define kmm_LoadImage(module, lpszName, uType, cxDesired, cyDesired, fuLoad) \
- (LoadImage(kmm_get_resource_hmodule(module), lpszName, uType, cxDesired, cyDesired, fuLoad))
-
-/*! \brief Convenience macro for using calling LoadCursor using a module handle
-
- \param[in] module A handle to a loaded module. The corresponding resource
- module will be located through a call to kmm_get_resource_hmodule()
-*/
-#define kmm_LoadCursor(module, lpCursorName) \
- (LoadCursor(kmm_get_resource_hmodule(module), lpCursorName))
-
-/*! \brief Convenience macro for using calling LoadIcon using a module handle
-
- \param[in] module A handle to a loaded module. The corresponding resource
- module will be located through a call to kmm_get_resource_hmodule()
-*/
-#define kmm_LoadIcon(module, lpIconName) \
- (LoadIcon(kmm_get_resource_hmodule(module), lpIconName))
-
-/*! \brief Convenience macro for using calling LoadMenu using a module handle
-
- \param[in] module A handle to a loaded module. The corresponding resource
- module will be located through a call to kmm_get_resource_hmodule()
-*/
-#define kmm_LoadMenu(module, lpMenuName) \
- (LoadMenu(kmm_get_resource_hmodule(module), lpMenuName))
-
-/*! \brief Convenience macro for using calling LoadString using a module handle
-
- \param[in] module A handle to a loaded module. The corresponding resource
- module will be located through a call to kmm_get_resource_hmodule()
-*/
-#define kmm_LoadString(module, uID, lpBuffer, nBufferMax) \
- (LoadString(kmm_get_resource_hmodule(module), uID, lpBuffer, nBufferMax))
-/*@}*/ /* Convenience Macros */
-#endif
-/*@}*/ /* group kmm_loc */
-/*@}*/ /* group kmm */
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __KHIMAIRA_KMM_H
+#define __KHIMAIRA_KMM_H
+
+#include<khdefs.h>
+#include<kmq.h>
+
+/*! \defgroup kmm NetIDMgr Module Manager
+@{*/
+
+/*! \brief A handle to a module.
+*/
+typedef khm_handle kmm_module;
+
+/*! \brief A handle to a plugin.
+ */
+typedef khm_handle kmm_plugin;
+
+/*! \name Limits
+ @{*/
+
+/*! \brief Maximum number of characters in a name in KMM including the terminating NULL */
+#define KMM_MAXCCH_NAME 256
+
+/*! \brief Maximum number of bytes in a name in KMM including the terminating NULL */
+#define KMM_MAXCB_NAME (sizeof(wchar_t) * KMM_MAXCCH_NAME)
+
+/*! \brief Maximum number of characters in a description in KMM including the terminating NULL */
+#define KMM_MAXCCH_DESC 512
+
+/*! \brief Maximum number of bytes in a description in KMM including the terminating NULL */
+#define KMM_MAXCB_DESC (sizeof(wchar_t) * KMM_MAXCCH_NAME)
+
+/*! \brief Maximum number of characters in a vendor string in KMM including the terminating NULL */
+#define KMM_MAXCCH_VENDOR 256
+
+/*! \brief Maximum number of bytes in a vendor string in KMM including the terminating NULL */
+#define KMM_MAXCB_VENDOR (sizeof(wchar_t) * KMM_MAXCCH_VENDOR)
+
+/*! \brief Maximum number of characters in a support URI in KMM including the terminating NULL */
+#define KMM_MAXCCH_SUPPORT 256
+
+/*! \brief Maximum number of bytes in a vendor string in KMM including the terminating NULL */
+#define KMM_MAXCB_SUPPORT (sizeof(wchar_t) * KMM_MAXCCH_SUPPORT)
+
+/*! \brief Maximum number of dependencies per plugin
+*/
+#define KMM_MAX_DEPENDENCIES 8
+
+/*! \brief Maximum number of dependants per plugin
+ */
+#define KMM_MAX_DEPENDANTS 32
+
+/*! \brief Maximum number of characters a dependency string including trailing double NULL */
+#define KMM_MAXCCH_DEPS (KMM_MAXCCH_NAME * KMM_MAX_DEPENDENCIES + 1)
+
+/*! \brief Maximum number of bytes in a dependency string including trailing double NULL */
+#define KMM_MAXCB_DEPS (sizeof(wchar_t) * KMM_MAXCCH_DEPS)
+/*@}*/ /* Limits */
+
+/*! \brief Plugin registration
+
+ \see ::khm_cred_provider
+*/
+typedef struct tag_kmm_plugin_reg {
+ wchar_t * name; /*!< Name of the plugin. Maximum of
+ KMM_MAXCCH_NAME characters
+ including the terminating
+ NULL. Required. */
+
+ wchar_t * module; /*!< Name of module that owns the
+ plugin. Maximum of
+ KMM_MAXCCH_NAME characters
+ including terminating NULL.
+ Required. */
+
+ khm_int32 type; /*!< Type plugin type. One of
+ KHM_PITYPE_*. Required. */
+ khm_int32 flags; /*!< Unused. Set to 0 */
+ kmq_callback_t msg_proc; /*!< Message processor. Required. */
+ wchar_t * dependencies; /*!< Dependencies. Note that this is
+ a multi string. (you can use the
+ KHC multi string functions to
+ manipulate multi strings or to
+ convert a comma separated list of
+ dependencies to a multi string).
+ Each string in the multi string
+ is a name of a plugin that this
+ plugin depends on. Optional (set
+ to NULL if this plugin has no
+ dependencies). Maximum of
+ KMM_MAXCCH_DEPS characters
+ including terminating double
+ NULL.*/
+
+ wchar_t * description; /*!< Description of the plugin.
+ Maximum of KMM_MAXCCH_DESC
+ characters including the
+ terminating
+ NULL. Localized. Optional (set to
+ NULL if not provided) */
+#ifdef _WIN32
+ HICON icon; /*!< Icon used to represent the
+ plugin. Optional. (set to NULL if
+ not provided) */
+#endif
+} kmm_plugin_reg;
+
+/*! \brief Plugin information
+*/
+typedef struct tag_kmm_plugin_info {
+ kmm_plugin_reg reg; /*!< Registration info */
+
+ khm_int32 state; /*!< Current status of the plugin.
+ One of ::_kmm_plugin_states */
+
+ khm_int32 failure_count; /*!< Number of recorded failures in
+ the plugin */
+ FILETIME failure_time; /*!< Time of first recorded failure */
+ khm_int32 failure_reason; /*!< The reason for the first recorded
+ failure */
+
+ kmm_plugin h_plugin; /*!< Handle to plugin */
+
+ khm_int32 flags; /*!< Flags for the plugin. Currently
+ this can only specify
+ ::KMM_PLUGIN_FLAG_DISABLED. */
+} kmm_plugin_info;
+
+/*! \brief The plugin is disabled
+
+ This flag will be set in the \a flags field of the
+ ::kmm_plugin_info structure for a plugin that has been marked as
+ disabled. If the plugin is currently running, but marked as
+ disabled for future sessions, then this bit will be set in \a
+ flags , but the \a state of the plugin will indicate that the
+ plugin is running.
+ */
+#define KMM_PLUGIN_FLAG_DISABLED 0x00000400
+
+/*! \name Plugin types
+@{*/
+/*! \brief A credentials provider
+
+ \see \ref pi_pt_cred for more information.
+ */
+#define KHM_PITYPE_CRED 1
+
+/*! \brief A identity provider
+
+ \see \ref pi_pt_cred for more information
+ */
+#define KHM_PITYPE_IDENT 2
+
+/*! \brief A configuration provider
+
+ \see \ref pi_pt_conf for more information.
+ */
+#define KHM_PITYPE_CONFIG 3
+
+/*! \brief Undefined plugin type
+
+ The plugin doesn't provide any credential type.
+ */
+#define KHM_PITYPE_MISC 4
+
+/*@}*/
+
+/*! \brief Plugin states */
+enum _kmm_plugin_states {
+ KMM_PLUGIN_STATE_FAIL_INIT = -6, /*!< Failed to initialize */
+ KMM_PLUGIN_STATE_FAIL_UNKNOWN = -5, /*!< Failed due to unknown
+ reasons */
+ KMM_PLUGIN_STATE_FAIL_MAX_FAILURE = -4, /*!< The plugin has
+ reached the maximum number
+ of failures and cannot be
+ initialized until the
+ failure count is reset */
+ KMM_PLUGIN_STATE_FAIL_NOT_REGISTERED = -3, /*!< Failed because the
+ plugin was not registered
+ and automatic registration
+ failed. */
+ KMM_PLUGIN_STATE_FAIL_DISABLED = -2,/*!< Failed because plugin was
+ disabled by the user. */
+ KMM_PLUGIN_STATE_FAIL_LOAD = -1, /*!< The plugin failed to load
+ due to some unknown
+ reason. */
+ KMM_PLUGIN_STATE_NONE = 0, /*!< Unknown state */
+ KMM_PLUGIN_STATE_PLACEHOLDER, /*!< Placeholder. The plugin
+ hasn't been provided by
+ anyone yet, but the plugin
+ record has been created to
+ keep track of
+ dependencies. */
+ KMM_PLUGIN_STATE_REG, /*!< The plugin is registered
+ but not initialized */
+ KMM_PLUGIN_STATE_PREINIT, /*!< The plugin is in the
+ process of being
+ initialized */
+ KMM_PLUGIN_STATE_HOLD, /*!< On hold. One or more
+ dependencies of this plugin
+ has not been resolved */
+ KMM_PLUGIN_STATE_INIT, /*!< The plugin was initialized */
+ KMM_PLUGIN_STATE_RUNNING, /*!< The plugin is running */
+ KMM_PLUGIN_STATE_EXITED /*!< The plugin has been stopped. */
+};
+
+/*! \brief Module registration */
+typedef struct tag_kmm_module_reg {
+ wchar_t * name; /*!< Identifier for the module */
+ wchar_t * path; /*!< Full pathname to module
+ binary */
+
+ wchar_t * description; /*!< Description of module */
+
+ wchar_t * vendor; /*!< Vendor/copyright string */
+
+ wchar_t * support; /*!< Support URL/contact */
+
+ khm_int32 n_plugins; /*!< Number of plugins that are
+ active */
+ kmm_plugin_reg * plugin_reg_info; /*!< Array of kmm_plugin_reg
+ records for each active
+ plugin */
+} kmm_module_reg;
+
+/*! \brief Module information record */
+typedef struct tag_kmm_module_info {
+ kmm_module_reg reg; /*!< Registration info */
+
+ khm_ui_4 language; /*!< Currently loaded langugage */
+
+ khm_int32 state; /*!< Current status of the
+ module */
+
+ khm_version file_version; /*!< File version for the
+ module */
+ khm_version product_version; /*!< Product version for the
+ module */
+
+ khm_int32 failure_count; /*!< Number of times the module
+ has failed to load */
+ FILETIME failure_time; /*!< Time of first recorded
+ failure */
+ khm_int32 failure_reason; /*!< Reason for first failure.
+ One of the module status
+ values */
+
+ kmm_module h_module; /*!< Handle to the module. */
+} kmm_module_info;
+
+/*! \brief Module states
+*/
+enum KMM_MODULE_STATES {
+ KMM_MODULE_STATE_FAIL_INCOMPAT=-12, /*!< The library containing
+ the module was not
+ compatible with this version
+ of NetIDMgr. */
+ KMM_MODULE_STATE_FAIL_INV_MODULE=-11, /*!< The library containing
+ the module was invalid. */
+ KMM_MODULE_STATE_FAIL_UNKNOWN=-10, /*!< Module could not be
+ loaded due to unknown
+ reasons. */
+ KMM_MODULE_STATE_FAIL_MAX_FAILURE=-9,/*!< The module has failed
+ too many times already. Not
+ attempting to restart it
+ again */
+ KMM_MODULE_STATE_FAIL_DUPLICATE=-8, /*!< An attempt was made to
+ load the same module
+ twice. */
+ KMM_MODULE_STATE_FAIL_NOT_REGISTERED=-7, /*!< The module is not
+ found among the registered
+ module list */
+ KMM_MODULE_STATE_FAIL_NO_PLUGINS=-6,/*!< The module provided no
+ plugins, or all the plugins
+ that are provided are
+ disabled */
+ KMM_MODULE_STATE_FAIL_DISABLED=-5, /*!< Module is disabled and
+ cannot be loaded */
+ KMM_MODULE_STATE_FAIL_LOAD=-4, /*!< The module failed to
+ initialize */
+ KMM_MODULE_STATE_FAIL_INVALID=-3, /*!< The module was invalid.
+ Typically caused by the
+ required entrypoints not
+ being present */
+ KMM_MODULE_STATE_FAIL_SIGNATURE=-2, /*!< The module failed to load
+ due to an unverifiable
+ signature */
+ KMM_MODULE_STATE_FAIL_NOT_FOUND=-1, /*!< The module was not
+ found */
+ KMM_MODULE_STATE_NONE=0, /*!< Unknown state. The handle
+ is possibly invalid */
+ KMM_MODULE_STATE_PREINIT, /*!< The module is being
+ loaded. init_module() hasn't
+ been called yet */
+ KMM_MODULE_STATE_INIT, /*!< In init_module() */
+ KMM_MODULE_STATE_INITPLUG, /*!< Initializing plugins */
+ KMM_MODULE_STATE_RUNNING, /*!< Running */
+ KMM_MODULE_STATE_EXITPLUG, /*!< Currently exiting plugins */
+ KMM_MODULE_STATE_EXIT, /*!< Currently exiting */
+ KMM_MODULE_STATE_EXITED /*!< Exited */
+};
+
+/*! \brief Start the Module Manager
+
+ \note Only called by the NetIDMgr core.
+*/
+KHMEXP void KHMAPI
+kmm_init(void);
+
+/*! \brief Stop the Module Manager
+
+ \note Only called by the NetIDMgr core.
+*/
+KHMEXP void KHMAPI
+kmm_exit(void);
+
+/*! \brief Return the plugin handle for the current plugin
+
+ The returned handle represents the plugin which owns the current
+ thread. The returned handle must be released by calling
+ kmm_release_plugin(). Returns NULL if the current thread is not
+ owned by any plugin.
+ */
+KHMEXP kmm_plugin KHMAPI
+kmm_this_plugin(void);
+
+/*! \brief Return the module handle for the current module
+
+ The returned handle represents the module which owns the current
+ thread. The returned handle must be released by calling
+ kmm_release_module()
+*/
+KHMEXP kmm_module KHMAPI
+kmm_this_module(void);
+
+/*! \name Flags for kmm_load_module()
+@{*/
+/*!\brief Load synchronously
+
+ If this flag is set, then the function waits for the module to be
+ loaded. The default is to load the module asynchronously.
+
+ When loading a module asynchronously, the kmm_load_module()
+ function returns KHM_ERROR_SUCCESS and exits without waiting for
+ the module to load. If \a result is not NULL, it will receive a
+ valid handle to the module.
+
+ When loading a module synchronously, kmm_load_module() will wait
+ for the module to completely load. If it fails to load properly,
+ it will return an error code and set \a result to NULL.
+*/
+#define KMM_LM_FLAG_SYNC 1
+
+/*! \brief Do not load
+
+ Indicates that the module shouldn't actually be loaded. If the
+ specified module name identifies a module that has already been
+ loaded, then the function returns a held handle to the existing
+ module (use kmm_release_module() to free the handle). Otherwise,
+ the function returns KHM_ERROR_NOT_FOUND.
+*/
+#define KMM_LM_FLAG_NOLOAD 2
+/*@}*/
+
+/*! \brief Load a module
+
+ The \a modulename parameter specifies a module to load. Depending
+ on the configuration, not all of the plugins that are provided by
+ the module may be loaded. If no plugins are successfully loaded,
+ the module will be immediately unloaded.
+
+ If the module is currently loaded or is being loaded, then a valid
+ handle to the existing module is returned.
+
+ When called with KMM_LM_FLAG_SYNC, the function does not return
+ until the module and the associated plugins are all initialized,
+ or an error occurs.
+
+ If the KMM_LM_FLAG_NOLOAD flag is set, then a handle to an
+ existing instance of the module will be returned. If the module
+ hasn't been loaded yet, then no handle is returned and the
+ function returns KHM_ERROR_NOT_FOUND.
+
+ See the associated NetIDMgr Module Manager documentation on the
+ sequence of events associated with loading a module.
+
+ \param[in] modulename Name of the module. The module should have
+ been registered under this name prior to the call.
+ \param[in] flags Combination of KMM_LM_FLAG_*
+ \param[out] result Receives a handle to the loaded module. If the
+ result is not required, set this to NULL. If \a result is not
+ NULL, and km_load_module() returns KHM_ERROR_SUCCESS, then
+ kmm_release_module() must be called to release the handle to
+ the module. Otherwise, \a result receives NULL. If a handle
+ is returned, it will be valid regardless of whether the module
+ fails to load or not. You can use kmm_get_module_state() to
+ query the progress of the loading process. See
+ ::KMM_LM_FLAG_SYNC.
+
+ \retval KHM_ERROR_SUCCESS The call succeeded. If \a
+ KMM_LM_FLAG_SYNC was specified, this means that the module was
+ successfully loaded. Otherwise, it only means that the module
+ has been queued up for loading. Use kmm_get_module_state() to
+ determine if it was successfully loaded. If \a result is not
+ NULL, a valid handle is returned.
+ \retval KHM_ERROR_EXISTS The module is already loaded or has been
+ already queued for loading. If \a result is not NULL, a valid
+ handle to the existing module instance is returned.
+ \retval KHM_ERROR_NOT_FOUND If called with KMM_LM_FLAG_NOLOAD,
+ indicates that the module has not been loaded. Otherwise only
+ returned when called with KMM_LM_FLAG_SYNC. The module image
+ was not found. No handle is returned.
+ \retval KHM_ERROR_INVALID_SIGNATURE Only returned when called with
+ KMM_LM_FLAG_SYNC. The module was signed with an invalid
+ certificate. No handle is returned.
+ \retval KHM_ERROR_UNKNOWN Only returned when called with
+ KMM_LM_FLAG_SYNC. Some other error has occured. No handle is
+ returned.
+
+ \see \ref pi_fw_pm_load
+ \see ::KMM_LM_FLAG_SYNC, ::KMM_LM_FLAG_NOLOAD
+*/
+KHMEXP khm_int32 KHMAPI
+kmm_load_module(wchar_t * modname, khm_int32 flags, kmm_module * result);
+
+/*! \brief Hold a handle to a module
+
+ Use kmm_release_module() to release the hold.
+*/
+KHMEXP khm_int32 KHMAPI
+kmm_hold_module(kmm_module module);
+
+/*! \brief Release a handle to a module
+
+ Release a held referece to a module that was returned in a call to
+ kmm_load_module().
+*/
+KHMEXP khm_int32 KHMAPI
+kmm_release_module(kmm_module m);
+
+/*! \brief Query the state of a module
+
+ When loading a module asynchronously you can query the state of
+ the loading process using this. The return value is a status
+ indicator.
+
+ \return The return value is one of the ::KMM_MODULE_STATES
+ enumerations.
+*/
+KHMEXP khm_int32 KHMAPI
+kmm_get_module_state(kmm_module m);
+
+/*! \brief Unload a module
+
+ See the associated NetIDMgr Module Manager documentation on the
+ sequence of events associated with unloading a module.
+
+ \see \ref pi_fw_pm_unload
+*/
+KHMEXP khm_int32 KHMAPI
+kmm_unload_module(kmm_module module);
+
+/*! \brief Loads the default modules as specified in the configuration
+
+ The configuration can specify the default set of modules to load.
+ This function dispatches the necessary message for loading these
+ modules and reutnrs.
+*/
+KHMEXP khm_int32 KHMAPI
+kmm_load_default_modules(void);
+
+/*! \brief Checks whether there are any pending loads
+
+ Returns TRUE if there are modules still waiting to be loaded.
+*/
+KHMEXP khm_boolean KHMAPI
+kmm_load_pending(void);
+
+#ifdef _WIN32
+
+/*! \brief Returns the Windows module handle from a handle to a NetIDMgr module.
+ Although it is possible to obtain the Windows module handle and
+ use it to call Windows API functions, it is not recommended to do
+ so. This is because that might cause the state of the module to
+ change in ways which are inconsistent from the internal data
+ structures that kmm maintains.
+ */
+KHMEXP HMODULE KHMAPI
+kmm_get_hmodule(kmm_module m);
+#endif
+
+/*! \brief Hold a plugin
+
+ Obtains a hold on a plugin. The plugin handle will remain valid
+ until the hold is released with a call to kmm_release_plugin().
+ No guarantees are made on the handle once the handle is released.
+ */
+KHMEXP khm_int32 KHMAPI
+kmm_hold_plugin(kmm_plugin p);
+
+/*! \brief Release a plugin
+
+ Releases a hold on a plugin obtained through a call to
+ kmm_hold_plugin(). The plugin handle should no longer be
+ considered valied once this is called.
+ */
+KHMEXP khm_int32 KHMAPI
+kmm_release_plugin(kmm_plugin p);
+
+/*! \brief Provide a plugin
+
+ This function must be called for each plugin that the module
+ provides.
+
+ Note that this function returns immediately and does not
+ initialize the plugin. All plugins that are provided by a
+ module will be initialized once the init_module() function
+ returns. If the plugin has dependencies, it will be kept in a
+ held state until the plugins that it depends on are successfully
+ initialized. If the dependencies are not resolved (the dependent
+ plugins are not loaded), then plugin will not be initialized.
+
+ If the plugin is not registered and \a plugin contains enough
+ information to perform the registration, then it will be
+ automatically registered. However, if the plugin is not
+ registered and cannot be registered using the provided
+ information, the plugin will not be initialized properly. Note
+ that automatic registration will always register the plugin in the
+ user configuration store.
+
+ The \a name and \a msg_proc members of \a plugin are required to
+ have valid values. The \a icon member may optionally be
+ specified. The other fields can be specified if the plugin should
+ be automatically registered, however, the \a module field will be
+ ignored and will be determined by the \a module handle.
+
+ \param[in] module Handle to this module that is providing the plugin.
+ \param[in] plugin A plugin descriptor.
+
+ \retval KHM_ERROR_SUCCESS Succeeded.
+ \retval KHM_ERROR_INVALID_OPERATION The function was not called
+ during init_module()
+ \retval KHM_ERROR_INVALID_PARAM One or more parameters were invalid
+ \retval KHM_ERROR_DUPLICATE The plugin was already provided
+
+ \note This can only be called when handing init_module()
+*/
+KHMEXP khm_int32 KHMAPI
+kmm_provide_plugin(kmm_module module, kmm_plugin_reg * plugin);
+
+/*! \brief Query the state of a plugin.
+
+ \return One of ::_kmm_plugin_states
+*/
+KHMEXP khm_int32 KHMAPI
+kmm_get_plugin_state(wchar_t * plugin);
+
+/*! \defgroup kmm_reg Registration
+
+ The functions for managing plugin and module registration. These
+ functions are also available as static linked libraries for use by
+ external applications which must register or unregister plugins or
+ modules.
+@{*/
+
+/*! \brief Obtain the configuration space for a named plugin
+
+ Note that the named plugin does not have to actually exist.
+ Configuration spaces for plugins are based solely on the plugin
+ name and hence can be accessed regardless of whether the specific
+ plugin is loaded or not.
+
+ \param[in] flags Controls the options for opening the
+ configuration space. If KHM_FLAG_CREATE is specified, then
+ the configuration space for the plugin named \a plugin wil be
+ created if it doesn't already exist. The \a flags parameter
+ is directly passed into a call to khc_open_space().
+
+ \param[in] plugin Name of the plugin. The name can not contain
+ slashes.
+
+ \param[out] result Receives a configuration space handle. The
+ calling application should free the handle using
+ khc_close_space().
+
+ \see khc_open_space()
+ \see khc_close_space()
+ */
+KHMEXP khm_int32 KHMAPI
+kmm_get_plugin_config(wchar_t * plugin, khm_int32 flags, khm_handle * result);
+
+/*! \brief Obtain the configuration space or a named module
+
+ The named module does not have to actually exist. Configuration
+ spaces for modules are based on the basename of the module
+ (including the extension).
+
+ \param[in] module Name of the module.
+
+ \param[in] flags The flags used to call khc_open_space(). You can
+ use this to specify a particular configuration store if
+ needed.
+
+ \param[out] result Receives the handle to a configuration space if
+ successful. Call khc_close_space() to close the handle.
+
+ \see khc_open_space()
+ \see khc_close_space()
+*/
+KHMEXP khm_int32 KHMAPI
+kmm_get_module_config(wchar_t * module, khm_int32 flags, khm_handle * result);
+
+/*! \brief Retrieve a handle to the configuration space for plugins
+
+ The configuration space for plugins is a container which holds the
+ configuration subspaces for all the plugins. This is the config
+ space which must be used to load a configuration space for a
+ plugin.
+
+ \param[in] flags The flags to pass in to the call to
+ khc_open_space(). The flags can be used to select a specific
+ configuration store if needed.
+
+ \param[out] result Receives a handle to the configuration
+ space. Call khc_close_space() to close the handle
+
+ \see khc_open_space()
+ \see khc_close_space()
+ */
+KHMEXP khm_int32 KHMAPI
+kmm_get_plugins_config(khm_int32 flags, khm_handle * result);
+
+/*! \brief Retrieve the handle to the configuration space for modules
+
+ The configuration space for modules is a container which hold the
+ configuration subspaces for all the modules. Each module
+ registration ends up in this subspace.
+
+ \param[in] flags The flags to pass in to the call to
+ khc_open_space(). The flags can be used to select a specific
+ configuration store if needed.
+
+ \param[out] result Receives a handle to the configuration space.
+ Call khc_close_space() to close the handle.
+
+ \see khc_open_space()
+ \see khc_close_space()
+ */
+KHMEXP khm_int32 KHMAPI
+kmm_get_modules_config(khm_int32 flags, khm_handle * result);
+
+/*! \brief Return information about a loaded module
+
+ The retrieves a block of information about a module. Refer to
+ ::kmm_module_info for information about the format of the returned
+ data.
+
+ Note that the size of the required buffer is actually greater than
+ the size of the ::kmm_module_info structure and accomodates the
+ ::kmm_plugin_info structures and strings required to complete the
+ information block.
+
+ Call the function with \a buffer set to NULL and \a cb_buffer
+ pointing at a khm_size variable to obtain the required size of the
+ buffer.
+
+ \param[in] module_name Name of a module
+ \param[in] flags Flags indicating which types of information to
+ return
+ \param[out] buffer Points to a buffer that recieves information.
+ Set this to NULL if only the size of the buffer is required.
+ \param[in,out] On entry, contains the size of the buffer pointed
+ to by \a buffer if \a buffer is not NULL. On exit, contains
+ the required size of the buffer or the number of actual bytes
+ copied.
+
+ \retval KHM_ERROR_SUCCESS The requested information was copied
+ \retval KHM_ERROR_INVALID_PARAM One of the parameters was invalid
+ \retval KHM_ERROR_TOO_LONG The buffer was not large enough or was
+ NULL. The number of bytes requied is in \a cb_buffer.
+ \retval KHM_ERROR_NOT_FOUND The specified module is not a
+ registered module.
+ */
+KHMEXP khm_int32 KHMAPI
+kmm_get_module_info(wchar_t * module_name, khm_int32 flags,
+ kmm_module_info * buffer, khm_size * cb_buffer);
+
+/*! \brief Get information about a module
+
+ Similar to kmm_get_module_info(), but uses a module handle instead
+ of a name, and uses internal buffers for providing string fields.
+
+ The information that is returned should be freed using a call to
+ kmm_release_module_info_i().
+
+ \see kmm_release_module_info_i()
+ */
+KHMEXP khm_int32 KHMAPI
+kmm_get_module_info_i(kmm_module module, kmm_module_info * info);
+
+/*! \brief Release module information
+
+ Releases the information returned by a previous call to
+ kmm_get_module_info_i(). The contents of the ::kmm_module_info
+ structure should not have been modified in any way between calling
+ kmm_get_module_info_i() and kmm_release_module_info_i().
+ */
+KHMEXP khm_int32 KHMAPI
+kmm_release_module_info_i(kmm_module_info * info);
+
+/*! \brief Obtain information about a plugin
+
+ Retrieve a block of information about a plugin. See
+ ::kmm_plugin_info for details about what information can be
+ returned. Note that some fields may not be available if the
+ module is not loaded.
+
+ Note that the size of the required buffer is greater than the size
+ of the ::kmm_plugin_info structure and accounts for strings as
+ well. Call kmm_get_plugin_info() with \a buffer set to NULL and
+ \a cb_buffer set to point to a variable of type \a khm_size to
+ obtain the required size of the structure.
+
+ \param[in] plugin_name Name of the plugin
+ \param[out] buffer The buffer to receive the plugin information.
+ Set to \a NULL if only the size of the buffer is required.
+ \param[in,out] cb_buffer On entry, points to variable that
+ specifies the size of the buffer pointed to by \a buffer is \a
+ buffer is not \a NULL. On exit, holds the number of bytes
+ copied or the required size of the buffer.
+
+ \retval KHM_ERROR_SUCCESS The requested information was
+ successfully copied to the \a buffer
+ \retval KHM_ERROR_TOO_LONG The buffer was either \a NULL or
+ insufficient to hold the requested information. The required
+ size of the buffer was stored in \a cb_buffer
+ \retval KHM_ERROR_INVALID_PARAM One or more parameters were
+ invlaid.
+ \retval KHM_ERROR_NOT_FOUND The specified plugin was not found
+ among the registered plugins.
+*/
+KHMEXP khm_int32 KHMAPI
+kmm_get_plugin_info(wchar_t * plugin_name,
+ kmm_plugin_info * buffer,
+ khm_size * cb_buffer);
+
+/*! \brief Obtain information about a plugin using a plugin handle
+
+ Similar to kmm_get_plugin_info() but uses a plugin handle instead
+ of a plugin name. If the call is successful, the \a info
+ structure will be filled with information about the plugin. The
+ returned info should not be modified in any way and may contain
+ pointers to internal buffers.
+
+ The returned information must be released with a call to
+ kmm_release_plugin_info_i().
+ */
+KHMEXP khm_int32 KHMAPI
+kmm_get_plugin_info_i(kmm_plugin p, kmm_plugin_info * info);
+
+/*! \brief Release plugin information returned by kmm_get_plugin_info_i
+
+ The information returned by kmm_get_plugin_info_i() should not be
+ modified in any way before calling kmm_release_plugin_info_i().
+ Once the call completes, the contents of \a info will be
+ initialized to zero.
+ */
+KHMEXP khm_int32 KHMAPI
+kmm_release_plugin_info_i(kmm_plugin_info * info);
+
+/*! \brief Enumerates plugins
+
+ Enumerates through known plugins. This list may not include
+ plugins which were not loaded by NetIDMgr in this session.
+
+ If the call is successful, a handle to the next plugin in the list
+ will be placed in \a p_next. The returned handle must be freed
+ with a call to kmm_release_plugin().
+
+ If the \a p parameter is set to NULL, then the first plugin handle
+ will be placed in \a p_next. The handles will not be returned in
+ any specific order. In addition, the enumeration may not include
+ all known plugins if the list of plugins changes during
+ enumeration.
+ */
+KHMEXP khm_int32 KHMAPI
+kmm_get_next_plugin(kmm_plugin p, kmm_plugin * p_next);
+
+/*! \brief Enables or disables a plugin
+
+ This function currently does not take effect immediately. However
+ it marks the plugin as enabled or disabled so that the next time
+ NetIDMgr starts, the module manager will act accordingly.
+
+ \param[in] p Handle to the plugin
+
+ \param[in] enable If non-zero, the plugin will be marked as
+ enabled. Otherwise the plugin will be marked as disabled.
+ */
+KHMEXP khm_int32 KHMAPI
+kmm_enable_plugin(kmm_plugin p, khm_boolean enable);
+
+/*! \brief Register a plugin
+
+ The \a plugin member defines the plugin to be registered. The \a
+ msg_proc and \a icon members of the structure are ignored.
+
+ At the time kmm_register_plugin() is called, the module specified
+ by \a module member of the \a plugin parameter must have been already
+ registered. Otherwise the function call fails.
+
+ If the plugin has already been registered, then all the fields in
+ the plugin registration will be updated to be in sync with the
+ information provided in the \a plugin parameter. The failure
+ counts and associated statistics will not be reset when the
+ configuration information is updated.
+
+ If the plugin has not been registered, the a new registration
+ entry is created in the configuration space indicated by the \a
+ config_flags parameter. In addition, the plugin will be added to
+ the list of plugins associated with the owning module.
+
+ Note that the module that owns the plugin must be registered in
+ the same configuration store as the plugin.
+
+ \param[in] plugin Registration info for the plugin. The \a
+ msg_proc and \a icon members are ignored. All other fields
+ are required. The \a description member should be localized
+ to the system locale when registering a plugin in the machine
+ configuration store and should be localized to the user locale
+ when registering a plugin in the user configuration store.
+ \param[in] config_flags Flags for the configuration provider.
+ These flags are used verbatim to call khc_open_space(), hence
+ they may be used to pick whether or not the registration is
+ per machine or per user.
+
+ \see kmm_register_module()
+ */
+KHMEXP khm_int32 KHMAPI
+kmm_register_plugin(kmm_plugin_reg * plugin, khm_int32 config_flags);
+
+/*! \brief Register a module
+
+ The \a module parameter specifies the parameters for the module
+ registration.
+
+ The \a plugin_info member should point to an array of
+ ::kmm_plugin_info structures unless the \a n_plugins member is
+ zero, in which case \a plugin_info can be \a NULL. Plugins can be
+ registered separately using kmm_register_plugin().
+
+ \param[in] module Information about the module. The name and path
+ fields are required. The \a plugin_info field can only be \a
+ NULL if \a n_plugins is zero.
+
+ \param[in] config_flags Flags used to call khc_open_space(). This
+ can be used to choose the configuration store in which the
+ module registration will be performed.
+ */
+KHMEXP khm_int32 KHMAPI
+kmm_register_module(kmm_module_reg * module, khm_int32 config_flags);
+
+/*! \brief Unregister a plugin
+
+ Registration information associated with the plugin will be
+ removed. In addtion, the plugin will be removed from the list of
+ plugins provided by the owner module.
+
+ \param[in] plugin Names the plugin to be removed
+ \param[in] config_flags Flags used to call khc_open_space(). Can
+ be used to choose the configuraiton store that is affected by
+ the call.
+
+ \note kmm_unregister_plugin() has no effect on whether the plugin
+ is loaded or not. The caller must make sure that the plugin
+ is unloaded and the associated module is either also unloaded
+ or in a state where the plugin can be unregistered.
+ */
+KHMEXP khm_int32 KHMAPI
+kmm_unregister_plugin(wchar_t * plugin, khm_int32 config_flags);
+
+/*! \brief Unregister a module
+
+ Registration information associated with the module as well as all
+ the plugins provided by the module will be removed from the
+ configuration store.
+
+ \param[in] module Names the module to be removed
+
+ \param[in] config_flags Flags used to call khc_open_space(). Can
+ be used to choose the configuration store affected by the
+ call.
+
+ \note kmm_unregister_module() has no effect on the loaded state of
+ the module. The caller should make sure that the module is
+ unloaded and in a state where it can be unregistered.
+ */
+KHMEXP khm_int32 KHMAPI
+kmm_unregister_module(wchar_t * module, khm_int32 config_flags);
+
+/*@}*/ /* kmm_reg */
+
+/*! \defgroup kmm_loc Internationalization support
+
+ See \ref pi_localization for more information about
+ internationalization.
+
+@{*/
+
+/*! \brief Locale descriptor record
+
+ See kmm_set_locale()
+*/
+typedef struct tag_kmm_module_locale {
+ khm_ui_4 language; /*!< A language ID. On Windows, you can use the
+ MAKELANGID macro to generate this value. */
+ wchar_t * filename; /*!< The filename corresponding to this language.
+ Use NULL to indicate that resources for this
+ language are to be found in the main module. */
+ khm_int32 flags; /*!< Flags. Combination of KMM_MLOC_FLAG_* */
+} kmm_module_locale;
+
+#define LOCALE_DEF(language_id, filename, flags) {language_id, filename, flags}
+
+/*! \brief Default (fallback) locale
+*/
+#define KMM_MLOC_FLAG_DEFAULT 1
+
+
+/*! \brief Sets the locale for a loaded module.
+
+ The given locale records are searched in the given order until a
+ locale that matches the current user locale is found. If no
+ locales match, then the first locale with the
+ ::KMM_MLOC_FLAG_DEFAULT flag set will be loaded. If no locales
+ have that flag set, then the first locale is loaded.
+
+ You can obtain a handle to the loaded library using
+ kmm_get_resource_hmodule(). This function does not return until a
+ matched library is loaded.
+
+ Note that the ::kmm_module_locale structure only specifies a
+ module name for the resource module. This resource module must
+ exist in the same directory as the \a module.
+
+ \param[in] module The module handle
+ \param[in] locales An array of ::kmm_module_locale objects
+ \param[in] n_locales The number of objects in the array pointed to by \a locales
+
+ \retval KHM_ERROR_SUCCESS Succeeded.
+ \retval KHM_ERROR_NOT_FOUND A matching locale resource library was not found.
+ \retval KHM_ERROR_INVALID_OPERATION The function was called on a module which is currently not being initalized.
+
+ \see \ref pi_localization
+ \see kmm_get_resource_hmodule()
+
+ \note This can only be called when handing init_module()
+*/
+KHMEXP khm_int32 KHMAPI
+kmm_set_locale_info(kmm_module module,
+ kmm_module_locale * locales,
+ khm_int32 n_locales);
+
+#ifdef _WIN32
+
+/*! \brief Return the Windows module handle of the resource library of a NetIDMgr module.
+
+ NetIDMgr allows the specification of an alternate resource library
+ that will be used to load localized resources from. This function
+ returns a handle to this library.
+
+ While you can use the convenience macros to access resources in a
+ localization library using the module handle, it is recommended,
+ for performance reasons, to use this function to obtain the handle
+ to the resource library and then use that handle in calls to
+ LoadString, LoadImage etc. directly.
+*/
+KHMEXP HMODULE KHMAPI
+kmm_get_resource_hmodule(kmm_module m);
+
+/*! \name Convenience Macros
+@{*/
+/*! \brief Convenience macro for using calling LoadAccelerators using a module handle
+
+ \param[in] module A handle to a loaded module. The corresponding resource
+ module will be located through a call to kmm_get_resource_hmodule()
+*/
+#define kmm_LoadAccelerators(module, lpTableName) \
+ (LoadAccelerators(kmm_get_resource_hmodule(module), lpTableName))
+
+/*! \brief Convenience macro for using calling LoadBitmap using a module handle
+
+ \param[in] module A handle to a loaded module. The corresponding resource
+ module will be located through a call to kmm_get_resource_hmodule()
+*/
+#define kmm_LoadBitmap(module, lpBitmapName) \
+ (LoadBitmap(kmm_get_resource_hmodule(module), lpBitmapName))
+
+/*! \brief Convenience macro for using calling LoadImage using a module handle
+
+ \param[in] module A handle to a loaded module. The corresponding resource
+ module will be located through a call to kmm_get_resource_hmodule()
+*/
+#define kmm_LoadImage(module, lpszName, uType, cxDesired, cyDesired, fuLoad) \
+ (LoadImage(kmm_get_resource_hmodule(module), lpszName, uType, cxDesired, cyDesired, fuLoad))
+
+/*! \brief Convenience macro for using calling LoadCursor using a module handle
+
+ \param[in] module A handle to a loaded module. The corresponding resource
+ module will be located through a call to kmm_get_resource_hmodule()
+*/
+#define kmm_LoadCursor(module, lpCursorName) \
+ (LoadCursor(kmm_get_resource_hmodule(module), lpCursorName))
+
+/*! \brief Convenience macro for using calling LoadIcon using a module handle
+
+ \param[in] module A handle to a loaded module. The corresponding resource
+ module will be located through a call to kmm_get_resource_hmodule()
+*/
+#define kmm_LoadIcon(module, lpIconName) \
+ (LoadIcon(kmm_get_resource_hmodule(module), lpIconName))
+
+/*! \brief Convenience macro for using calling LoadMenu using a module handle
+
+ \param[in] module A handle to a loaded module. The corresponding resource
+ module will be located through a call to kmm_get_resource_hmodule()
+*/
+#define kmm_LoadMenu(module, lpMenuName) \
+ (LoadMenu(kmm_get_resource_hmodule(module), lpMenuName))
+
+/*! \brief Convenience macro for using calling LoadString using a module handle
+
+ \param[in] module A handle to a loaded module. The corresponding resource
+ module will be located through a call to kmm_get_resource_hmodule()
+*/
+#define kmm_LoadString(module, uID, lpBuffer, nBufferMax) \
+ (LoadString(kmm_get_resource_hmodule(module), uID, lpBuffer, nBufferMax))
+/*@}*/ /* Convenience Macros */
+#endif
+/*@}*/ /* group kmm_loc */
+/*@}*/ /* group kmm */
+#endif
diff --git a/src/windows/identity/kmm/kmm_module.c b/src/windows/identity/kmm/kmm_module.c
index 932bdf8ef3..52c34ac03f 100644
--- a/src/windows/identity/kmm/kmm_module.c
+++ b/src/windows/identity/kmm/kmm_module.c
@@ -1,676 +1,676 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<kmminternal.h>
-#include<netidmgr_version.h>
-#include<assert.h>
-
-/* should only be accessed from the registrar thread */
-khm_size kmm_active_modules = 0;
-
-kmm_module_i * kmmint_get_module_i(wchar_t * name)
-{
- kmm_module_i * m;
- size_t sz;
-
- if(FAILED(StringCbLength(name, KMM_MAXCB_NAME, &sz)))
- return NULL;
- sz += sizeof(wchar_t);
-
- EnterCriticalSection(&cs_kmm);
- m = (kmm_module_i *) hash_lookup(hash_modules, (void *) name);
-
- if(m == NULL) {
- m = PMALLOC(sizeof(kmm_module_i));
- ZeroMemory(m, sizeof(kmm_module_i));
-
- m->magic = KMM_MODULE_MAGIC;
- m->name = PMALLOC(sz);
- StringCbCopy(m->name, sz, name);
- m->state = KMM_MODULE_STATE_NONE;
-
- hash_add(hash_modules, (void *) m->name, (void *) m);
- LPUSH(&kmm_all_modules, m);
- }
- LeaveCriticalSection(&cs_kmm);
-
- return m;
-}
-
-kmm_module_i * kmmint_find_module_i(wchar_t * name)
-{
- kmm_module_i * m;
-
- EnterCriticalSection(&cs_kmm);
- m = (kmm_module_i *) hash_lookup(hash_modules, (void *) name);
- LeaveCriticalSection(&cs_kmm);
-
- return m;
-}
-
-/* called with cs_kmm held */
-void kmmint_free_module(kmm_module_i * m)
-{
- m->magic = 0;
-
- hash_del(hash_modules, m->name);
- LDELETE(&kmm_all_modules, m);
-
- if (m->name)
- PFREE(m->name);
-
- if (m->description)
- PFREE(m->description);
-
- if (m->path)
- PFREE(m->path);
-
- if (m->vendor)
- PFREE(m->vendor);
-
- if (m->support)
- PFREE(m->support);
-
- if (m->version_info)
- PFREE(m->version_info);
-
- PFREE(m);
-}
-
-KHMEXP khm_int32 KHMAPI kmm_hold_module(kmm_module module)
-{
- if(!kmm_is_module(module))
- return KHM_ERROR_INVALID_PARAM;
- EnterCriticalSection(&cs_kmm);
- kmm_module_from_handle(module)->refcount++;
- LeaveCriticalSection(&cs_kmm);
-
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP khm_int32 KHMAPI kmm_release_module(kmm_module vm)
-{
- kmm_module_i * m;
-
- if(!kmm_is_module(vm))
- return KHM_ERROR_INVALID_PARAM;
-
- EnterCriticalSection(&cs_kmm);
- m = kmm_module_from_handle(vm);
- if(! --(m->refcount))
- {
- /* note that a 0 ref count means that there are no active
- plugins */
- kmmint_free_module(m);
- }
- LeaveCriticalSection(&cs_kmm);
- return KHM_ERROR_SUCCESS;
-}
-
-khm_int32
-kmmint_check_api_version(DWORD v) {
- /* for now, we allow API versions in the range
- KH_VERSION_API_MINCOMPAT through KH_VERSION_API, inclusive. In
- the future when we are swamped with so much time that we don't
- know what to do with it, we can actually parse the
- apiversion.txt file and create a compatibility table which we
- can check against the functions used by the module and decide
- whether or not it is compatible. */
-
- if (v < KH_VERSION_API_MINCOMPAT ||
- v > KH_VERSION_API)
- return KHM_ERROR_INCOMPATIBLE;
- else
- return KHM_ERROR_SUCCESS;
-}
-
-struct lang_code {
- WORD language;
- WORD codepage;
-};
-
-khm_int32
-kmmint_read_module_info(kmm_module_i * m) {
- /* the only fields we can count on at this point are m->name and
- m->path */
- DWORD t;
- size_t cb;
- WORD lang;
- khm_int32 rv = KHM_ERROR_SUCCESS;
- struct lang_code *languages;
- int n_languages;
- int i;
- wchar_t resname[256]; /* the resource names are a lot shorter */
- wchar_t * r;
- VS_FIXEDFILEINFO *vff;
-
- assert(m->name);
- assert(m->path);
-
- t = TRUE;
- cb = GetFileVersionInfoSize(m->path,
- &t);
- /* if successful, cb gets the size in bytes of the version info
- structure and sets t to zero */
- if (t) {
- return KHM_ERROR_NOT_FOUND;
- } else if (cb == 0) {
- _report_mr1(KHERR_WARNING, MSG_RMI_NOT_FOUND, _dupstr(m->path));
- return KHM_ERROR_INVALID_PARAM;
- }
-
- if (m->version_info) {
- PFREE(m->version_info);
- m->version_info = NULL;
- }
-
- m->version_info = PMALLOC(cb);
-#ifdef DEBUG
- assert(m->version_info);
-#endif
-
- if(!GetFileVersionInfo(m->path,
- t, (DWORD) cb, m->version_info)) {
- rv = KHM_ERROR_NOT_FOUND;
- _report_mr1(KHERR_WARNING, MSG_RMI_NOT_FOUND, _dupstr(m->path));
- _location(L"GetFileVersionInfo");
- goto _cleanup;
- }
-
- if(!VerQueryValue(m->version_info,
- L"\\VarFileInfo\\Translation",
- (LPVOID*) &languages,
- &cb)) {
- rv = KHM_ERROR_INVALID_PARAM;
- _report_mr1(KHERR_WARNING, MSG_RMI_NO_TRANS, _dupstr(m->path));
- _location(L"VerQueryValue");
- goto _cleanup;
- }
-
- n_languages = (int) (cb / sizeof(*languages));
-
- /* Try searching for the user's default language first */
- lang = GetUserDefaultLangID();
- for (i = 0; i < n_languages; i++) {
- if(languages[i].language == lang)
- break;
- }
-
- /* If not, try the system default */
- if (i >= n_languages) {
- lang = GetSystemDefaultLangID();
- for (i=0; i<n_languages; i++)
- if (languages[i].language == lang)
- break;
- }
-
- /* Then try EN_US */
- if (i >= n_languages) {
- lang = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
- for (i=0; i<n_languages; i++)
- if (languages[i].language == lang)
- break;
- }
-
- /* Language neutral? */
- if (i >= n_languages) {
- lang = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
- for (i=0; i<n_languages; i++)
- if (languages[i].language == lang)
- break;
- }
-
- /* Just use the first one? */
- if (i >= n_languages) {
- i = 0;
- }
-
- if (i >= n_languages) {
- rv = KHM_ERROR_INVALID_PARAM;
- _report_mr0(KHERR_WARNING, MSG_RMI_NO_LOCAL);
- goto _cleanup;
- }
-
- /* check module name */
- StringCbPrintf(resname, sizeof(resname),
- L"\\StringFileInfo\\%04x%04x\\" TEXT(NIMV_MODULE),
- languages[i].language,
- languages[i].codepage);
-
- if (!VerQueryValue(m->version_info,
- resname, (LPVOID *) &r, &cb)) {
- rv = KHM_ERROR_INVALID_PARAM;
- _report_mr1(KHERR_WARNING, MSG_RMI_RES_MISSING,
- _cstr(TEXT(NIMV_MODULE)));
- goto _cleanup;
- }
-
- if (cb > KMM_MAXCB_NAME ||
- FAILED(StringCbLength(r, KMM_MAXCB_NAME, &cb))) {
- rv = KHM_ERROR_INVALID_PARAM;
- _report_mr1(KHERR_WARNING, MSG_RMI_RES_TOO_LONG,
- _cstr(TEXT(NIMV_MODULE)));
- goto _cleanup;
- }
-
- if (wcscmp(r, m->name)) {
- rv = KHM_ERROR_INVALID_PARAM;
- _report_mr2(KHERR_WARNING, MSG_RMI_MOD_MISMATCH,
- _dupstr(r), _dupstr(m->name));
- goto _cleanup;
- }
-
- /* check API version */
- StringCbPrintf(resname, sizeof(resname),
- L"\\StringFileInfo\\%04x%04x\\" TEXT(NIMV_APIVER),
- languages[i].language,
- languages[i].codepage);
-
- if (!VerQueryValue(m->version_info,
- resname, (LPVOID *) &r, &cb)) {
- rv = KHM_ERROR_INVALID_PARAM;
- _report_mr1(KHERR_WARNING, MSG_RMI_RES_MISSING,
- _cstr(TEXT(NIMV_APIVER)));
- goto _cleanup;
- }
-
- if (cb > KMM_MAXCB_NAME ||
- FAILED(StringCbLength(r, KMM_MAXCB_NAME, &cb))) {
- rv = KHM_ERROR_INVALID_PARAM;
- _report_mr1(KHERR_WARNING, MSG_RMI_RES_TOO_LONG,
- _cstr(TEXT(NIMV_APIVER)));
- goto _cleanup;
- }
-
- t = wcstol(r, NULL, 10);
-
- rv = kmmint_check_api_version(t);
-
- if (KHM_FAILED(rv)) {
- _report_mr2(KHERR_WARNING, MSG_RMI_API_MISMATCH,
- _int32(t), _int32(KH_VERSION_API));
- goto _cleanup;
- }
-
- /* Looks good. Now load the description, copyright, support URI
- and file versions */
- if (m->description) {
- PFREE(m->description);
- m->description = NULL;
- }
-
- StringCbPrintf(resname, sizeof(resname),
- L"\\StringFileInfo\\%04x%04x\\FileDescription",
- languages[i].language,
- languages[i].codepage);
-
- if (!VerQueryValue(m->version_info,
- resname, (LPVOID *) &r, &cb)) {
- rv = KHM_ERROR_INVALID_PARAM;
- _report_mr1(KHERR_WARNING, MSG_RMI_RES_MISSING,
- _cstr(L"FileDescription"));
- goto _cleanup;
- }
-
- if (cb > KMM_MAXCB_DESC ||
- FAILED(StringCbLength(r, KMM_MAXCB_DESC, &cb))) {
- rv = KHM_ERROR_INVALID_PARAM;
- _report_mr1(KHERR_WARNING, MSG_RMI_RES_TOO_LONG,
- _cstr(L"FileDescription"));
- goto _cleanup;
- }
-
- cb += sizeof(wchar_t);
-
- m->description = PMALLOC(cb);
-#ifdef DEBUG
- assert(m->description);
-#endif
- StringCbCopy(m->description, cb, r);
-
- /* on to the support URI */
- if (m->support) {
- PFREE(m->support);
- m->support = NULL;
- }
-
- StringCbPrintf(resname, sizeof(resname),
- L"\\StringFileInfo\\%04x%04x\\" TEXT(NIMV_SUPPORT),
- languages[i].language,
- languages[i].codepage);
-
- if (!VerQueryValue(m->version_info,
- resname, (LPVOID *) &r, &cb)) {
- rv = KHM_ERROR_INVALID_PARAM;
- _report_mr1(KHERR_WARNING, MSG_RMI_RES_MISSING,
- _cstr(TEXT(NIMV_SUPPORT)));
- goto _cleanup;
- }
-
- if (cb > KMM_MAXCB_SUPPORT ||
- FAILED(StringCbLength(r, KMM_MAXCB_SUPPORT, &cb))) {
- rv = KHM_ERROR_INVALID_PARAM;
- _report_mr1(KHERR_WARNING, MSG_RMI_RES_TOO_LONG,
- _cstr(TEXT(NIMV_SUPPORT)));
- goto _cleanup;
- }
-
- cb += sizeof(wchar_t);
-
- m->support = PMALLOC(cb);
-#ifdef DEBUG
- assert(m->support);
-#endif
- StringCbCopy(m->support, cb, r);
-
- /* the vendor/copyright */
- if (m->vendor) {
- PFREE(m->vendor);
- m->vendor = NULL;
- }
-
- StringCbPrintf(resname, sizeof(resname),
- L"\\StringFileInfo\\%04x%04x\\LegalCopyright",
- languages[i].language,
- languages[i].codepage);
-
- if (!VerQueryValue(m->version_info,
- resname, (LPVOID *) &r, &cb)) {
- rv = KHM_ERROR_INVALID_PARAM;
- _report_mr1(KHERR_WARNING, MSG_RMI_RES_MISSING,
- _cstr(L"LegalCopyright"));
- goto _cleanup;
- }
-
- if (cb > KMM_MAXCB_SUPPORT ||
- FAILED(StringCbLength(r, KMM_MAXCB_SUPPORT, &cb))) {
- rv = KHM_ERROR_INVALID_PARAM;
- _report_mr1(KHERR_WARNING, MSG_RMI_RES_TOO_LONG,
- _cstr(L"LegalCopyright"));
- goto _cleanup;
- }
-
- cb += sizeof(wchar_t);
-
- m->vendor = PMALLOC(cb);
-#ifdef DEBUG
- assert(m->vendor);
-#endif
- StringCbCopy(m->vendor, cb, r);
-
- if (!VerQueryValue(m->version_info,
- L"\\",
- (LPVOID *) &vff,
- &cb) ||
- cb != sizeof(*vff)) {
-
- rv = KHM_ERROR_INVALID_PARAM;
- _report_mr1(KHERR_WARNING, MSG_RMI_RES_MISSING,
- _cstr(L"Fixed Version Info"));
- goto _cleanup;
- }
-
- m->file_version.major = HIWORD(vff->dwFileVersionMS);
- m->file_version.minor = LOWORD(vff->dwFileVersionMS);
- m->file_version.patch = HIWORD(vff->dwFileVersionLS);
- m->file_version.aux = LOWORD(vff->dwFileVersionLS);
-
- m->prod_version.major = HIWORD(vff->dwProductVersionMS);
- m->prod_version.minor = LOWORD(vff->dwProductVersionMS);
- m->prod_version.patch = HIWORD(vff->dwProductVersionLS);
- m->prod_version.aux = LOWORD(vff->dwProductVersionLS);
-
- rv = KHM_ERROR_SUCCESS;
-
- _cleanup:
- if (KHM_FAILED(rv)) {
- if (m->version_info) {
- PFREE(m->version_info);
- m->version_info = NULL;
- }
- }
-
- return rv;
-}
-
-KHMEXP khm_int32 KHMAPI kmm_load_module(wchar_t * modname,
- khm_int32 flags,
- kmm_module * result)
-{
- kmm_module_i * m = NULL;
- kmm_module_i * mi;
- size_t cbsize;
- khm_int32 rv = KHM_ERROR_SUCCESS;
-
- if(FAILED(StringCbLength(modname, KMM_MAXCB_NAME, &cbsize)))
- return KHM_ERROR_INVALID_PARAM;
- cbsize += sizeof(wchar_t);
-
- EnterCriticalSection(&cs_kmm);
- mi = kmmint_find_module_i(modname);
-
- if(mi != NULL) {
- kmm_hold_module(kmm_handle_from_module(mi));
- /* check if the module has either failed to load either or if
- it has been terminated. If so, we try once again to load the
- module. */
- if(!(flags & KMM_LM_FLAG_NOLOAD) &&
- (mi->state < 0 || mi->state == KMM_MODULE_STATE_EXITED))
- {
- mi->state = KMM_MODULE_STATE_PREINIT;
- }
- }
- LeaveCriticalSection(&cs_kmm);
-
- if(flags & KMM_LM_FLAG_NOLOAD) {
- if(result)
- *result = mi;
- else if(mi)
- kmm_release_module(kmm_handle_from_module(mi));
-
- return (mi)? KHM_ERROR_SUCCESS: KHM_ERROR_NOT_FOUND;
- }
-
- if(mi) {
- m = mi;
- } else {
- m = kmmint_get_module_i(modname);
- m->state = KMM_MODULE_STATE_PREINIT;
- kmm_hold_module(kmm_handle_from_module(m));
- }
-
- /* the module is already running or is already being
- worked on by the registrar */
- if(m->state != KMM_MODULE_STATE_PREINIT) {
- if(result)
- *result = kmm_handle_from_module(m);
- else
- kmm_release_module(kmm_handle_from_module(m));
-
- return KHM_ERROR_EXISTS;
- }
-
- kmmint_add_to_module_queue();
-
- if(flags & KMM_LM_FLAG_SYNC) {
- kmm_hold_module(kmm_handle_from_module(m));
- kmq_send_message(KMSG_KMM,
- KMSG_KMM_I_REG,
- KMM_REG_INIT_MODULE,
- (void*) m);
- if(m->state <= 0) {
- /* failed to load ? */
- if(m->state == KMM_MODULE_STATE_FAIL_NOT_FOUND)
- rv = KHM_ERROR_NOT_FOUND;
- else if(m->state == KMM_MODULE_STATE_FAIL_SIGNATURE)
- rv = KHM_ERROR_INVALID_SIGNATURE;
- else
- rv = KHM_ERROR_UNKNOWN;
-
- kmm_release_module(kmm_handle_from_module(m));
- if(result)
- *result = NULL;
- } else {
- if(result)
- *result = kmm_handle_from_module(m);
- else
- kmm_release_module(kmm_handle_from_module(m));
- }
- } else {
- kmm_hold_module(kmm_handle_from_module(m));
- kmq_post_message(KMSG_KMM,
- KMSG_KMM_I_REG,
- KMM_REG_INIT_MODULE,
- (void*) m);
- if(result)
- *result = kmm_handle_from_module(m);
- else
- kmm_release_module(kmm_handle_from_module(m));
- }
-
- return rv;
-}
-
-KHMEXP khm_int32 KHMAPI
-kmm_get_module_state(kmm_module m)
-{
- if(!kmm_is_module(m))
- return KMM_MODULE_STATE_NONE;
- else
- return kmm_module_from_handle(m)->state;
-}
-
-KHMEXP khm_int32 KHMAPI
-kmm_get_module_info_i(kmm_module vm, kmm_module_info * info) {
- kmm_module_i * m;
- khm_int32 rv;
-
- EnterCriticalSection(&cs_kmm);
- if (!kmm_is_module(vm) || !info)
- rv = KHM_ERROR_INVALID_PARAM;
- else {
- m = kmm_module_from_handle(vm);
-
- ZeroMemory(info, sizeof(*info));
-
- info->reg.name = m->name;
- info->reg.path = m->path;
- info->reg.vendor = m->vendor;
-
- info->reg.n_plugins = m->plugin_count;
-
- info->state = m->state;
-
- info->h_module = vm;
-
- info->file_version = m->file_version;
- info->product_version = m->prod_version;
- kmm_hold_module(vm);
-
- rv = KHM_ERROR_SUCCESS;
- }
- LeaveCriticalSection(&cs_kmm);
-
- return rv;
-}
-
-KHMEXP khm_int32 KHMAPI
-kmm_release_module_info_i(kmm_module_info * info) {
- if (info->h_module)
- kmm_release_module(info->h_module);
-
- ZeroMemory(info, sizeof(*info));
-
- return KHM_ERROR_SUCCESS;
-}
-
-
-KHMEXP khm_int32 KHMAPI
-kmm_unload_module(kmm_module module) {
-
- if(!kmm_is_module(module))
- return KHM_ERROR_INVALID_PARAM;
-
- kmm_hold_module(module);
- kmq_post_message(KMSG_KMM,
- KMSG_KMM_I_REG,
- KMM_REG_EXIT_MODULE,
- (void *) kmm_module_from_handle(module));
-
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP khm_int32 KHMAPI
-kmm_load_default_modules(void) {
- khm_handle csm = NULL;
- khm_handle cs_mod = NULL;
- khm_int32 rv;
- wchar_t buf[KMM_MAXCCH_NAME];
- khm_size s;
-
- rv = kmm_get_modules_config(0, &csm);
- if(KHM_FAILED(rv))
- return rv;
-
- _begin_task(KHERR_CF_TRANSITIVE);
- _report_mr0(KHERR_NONE, MSG_LOAD_DEFAULT);
- _describe();
-
- kmmint_add_to_module_queue();
-
- while(KHM_SUCCEEDED(khc_enum_subspaces(csm, cs_mod, &cs_mod))) {
-
- s = sizeof(buf);
- if (KHM_FAILED(khc_get_config_space_name(cs_mod, buf, &s)))
- continue;
-
- /* check for schema subspace. This is not an actual module. */
- if (!wcscmp(buf, L"_Schema"))
- continue;
-
- kmm_load_module(buf, 0, NULL);
- }
-
- kmmint_remove_from_module_queue();
-
- if(csm)
- khc_close_space(csm);
-
- _end_task();
-
- return rv;
-}
-
-#ifdef _WIN32
-KHMEXP HMODULE KHMAPI
-kmm_get_hmodule(kmm_module m)
-{
- if(!kmm_is_module(m))
- return NULL;
- else
- return kmm_module_from_handle(m)->h_module;
-}
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<kmminternal.h>
+#include<netidmgr_version.h>
+#include<assert.h>
+
+/* should only be accessed from the registrar thread */
+khm_size kmm_active_modules = 0;
+
+kmm_module_i * kmmint_get_module_i(wchar_t * name)
+{
+ kmm_module_i * m;
+ size_t sz;
+
+ if(FAILED(StringCbLength(name, KMM_MAXCB_NAME, &sz)))
+ return NULL;
+ sz += sizeof(wchar_t);
+
+ EnterCriticalSection(&cs_kmm);
+ m = (kmm_module_i *) hash_lookup(hash_modules, (void *) name);
+
+ if(m == NULL) {
+ m = PMALLOC(sizeof(kmm_module_i));
+ ZeroMemory(m, sizeof(kmm_module_i));
+
+ m->magic = KMM_MODULE_MAGIC;
+ m->name = PMALLOC(sz);
+ StringCbCopy(m->name, sz, name);
+ m->state = KMM_MODULE_STATE_NONE;
+
+ hash_add(hash_modules, (void *) m->name, (void *) m);
+ LPUSH(&kmm_all_modules, m);
+ }
+ LeaveCriticalSection(&cs_kmm);
+
+ return m;
+}
+
+kmm_module_i * kmmint_find_module_i(wchar_t * name)
+{
+ kmm_module_i * m;
+
+ EnterCriticalSection(&cs_kmm);
+ m = (kmm_module_i *) hash_lookup(hash_modules, (void *) name);
+ LeaveCriticalSection(&cs_kmm);
+
+ return m;
+}
+
+/* called with cs_kmm held */
+void kmmint_free_module(kmm_module_i * m)
+{
+ m->magic = 0;
+
+ hash_del(hash_modules, m->name);
+ LDELETE(&kmm_all_modules, m);
+
+ if (m->name)
+ PFREE(m->name);
+
+ if (m->description)
+ PFREE(m->description);
+
+ if (m->path)
+ PFREE(m->path);
+
+ if (m->vendor)
+ PFREE(m->vendor);
+
+ if (m->support)
+ PFREE(m->support);
+
+ if (m->version_info)
+ PFREE(m->version_info);
+
+ PFREE(m);
+}
+
+KHMEXP khm_int32 KHMAPI kmm_hold_module(kmm_module module)
+{
+ if(!kmm_is_module(module))
+ return KHM_ERROR_INVALID_PARAM;
+ EnterCriticalSection(&cs_kmm);
+ kmm_module_from_handle(module)->refcount++;
+ LeaveCriticalSection(&cs_kmm);
+
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP khm_int32 KHMAPI kmm_release_module(kmm_module vm)
+{
+ kmm_module_i * m;
+
+ if(!kmm_is_module(vm))
+ return KHM_ERROR_INVALID_PARAM;
+
+ EnterCriticalSection(&cs_kmm);
+ m = kmm_module_from_handle(vm);
+ if(! --(m->refcount))
+ {
+ /* note that a 0 ref count means that there are no active
+ plugins */
+ kmmint_free_module(m);
+ }
+ LeaveCriticalSection(&cs_kmm);
+ return KHM_ERROR_SUCCESS;
+}
+
+khm_int32
+kmmint_check_api_version(DWORD v) {
+ /* for now, we allow API versions in the range
+ KH_VERSION_API_MINCOMPAT through KH_VERSION_API, inclusive. In
+ the future when we are swamped with so much time that we don't
+ know what to do with it, we can actually parse the
+ apiversion.txt file and create a compatibility table which we
+ can check against the functions used by the module and decide
+ whether or not it is compatible. */
+
+ if (v < KH_VERSION_API_MINCOMPAT ||
+ v > KH_VERSION_API)
+ return KHM_ERROR_INCOMPATIBLE;
+ else
+ return KHM_ERROR_SUCCESS;
+}
+
+struct lang_code {
+ WORD language;
+ WORD codepage;
+};
+
+khm_int32
+kmmint_read_module_info(kmm_module_i * m) {
+ /* the only fields we can count on at this point are m->name and
+ m->path */
+ DWORD t;
+ size_t cb;
+ WORD lang;
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+ struct lang_code *languages;
+ int n_languages;
+ int i;
+ wchar_t resname[256]; /* the resource names are a lot shorter */
+ wchar_t * r;
+ VS_FIXEDFILEINFO *vff;
+
+ assert(m->name);
+ assert(m->path);
+
+ t = TRUE;
+ cb = GetFileVersionInfoSize(m->path,
+ &t);
+ /* if successful, cb gets the size in bytes of the version info
+ structure and sets t to zero */
+ if (t) {
+ return KHM_ERROR_NOT_FOUND;
+ } else if (cb == 0) {
+ _report_mr1(KHERR_WARNING, MSG_RMI_NOT_FOUND, _dupstr(m->path));
+ return KHM_ERROR_INVALID_PARAM;
+ }
+
+ if (m->version_info) {
+ PFREE(m->version_info);
+ m->version_info = NULL;
+ }
+
+ m->version_info = PMALLOC(cb);
+#ifdef DEBUG
+ assert(m->version_info);
+#endif
+
+ if(!GetFileVersionInfo(m->path,
+ t, (DWORD) cb, m->version_info)) {
+ rv = KHM_ERROR_NOT_FOUND;
+ _report_mr1(KHERR_WARNING, MSG_RMI_NOT_FOUND, _dupstr(m->path));
+ _location(L"GetFileVersionInfo");
+ goto _cleanup;
+ }
+
+ if(!VerQueryValue(m->version_info,
+ L"\\VarFileInfo\\Translation",
+ (LPVOID*) &languages,
+ &cb)) {
+ rv = KHM_ERROR_INVALID_PARAM;
+ _report_mr1(KHERR_WARNING, MSG_RMI_NO_TRANS, _dupstr(m->path));
+ _location(L"VerQueryValue");
+ goto _cleanup;
+ }
+
+ n_languages = (int) (cb / sizeof(*languages));
+
+ /* Try searching for the user's default language first */
+ lang = GetUserDefaultLangID();
+ for (i = 0; i < n_languages; i++) {
+ if(languages[i].language == lang)
+ break;
+ }
+
+ /* If not, try the system default */
+ if (i >= n_languages) {
+ lang = GetSystemDefaultLangID();
+ for (i=0; i<n_languages; i++)
+ if (languages[i].language == lang)
+ break;
+ }
+
+ /* Then try EN_US */
+ if (i >= n_languages) {
+ lang = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
+ for (i=0; i<n_languages; i++)
+ if (languages[i].language == lang)
+ break;
+ }
+
+ /* Language neutral? */
+ if (i >= n_languages) {
+ lang = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
+ for (i=0; i<n_languages; i++)
+ if (languages[i].language == lang)
+ break;
+ }
+
+ /* Just use the first one? */
+ if (i >= n_languages) {
+ i = 0;
+ }
+
+ if (i >= n_languages) {
+ rv = KHM_ERROR_INVALID_PARAM;
+ _report_mr0(KHERR_WARNING, MSG_RMI_NO_LOCAL);
+ goto _cleanup;
+ }
+
+ /* check module name */
+ StringCbPrintf(resname, sizeof(resname),
+ L"\\StringFileInfo\\%04x%04x\\" TEXT(NIMV_MODULE),
+ languages[i].language,
+ languages[i].codepage);
+
+ if (!VerQueryValue(m->version_info,
+ resname, (LPVOID *) &r, &cb)) {
+ rv = KHM_ERROR_INVALID_PARAM;
+ _report_mr1(KHERR_WARNING, MSG_RMI_RES_MISSING,
+ _cstr(TEXT(NIMV_MODULE)));
+ goto _cleanup;
+ }
+
+ if (cb > KMM_MAXCB_NAME ||
+ FAILED(StringCbLength(r, KMM_MAXCB_NAME, &cb))) {
+ rv = KHM_ERROR_INVALID_PARAM;
+ _report_mr1(KHERR_WARNING, MSG_RMI_RES_TOO_LONG,
+ _cstr(TEXT(NIMV_MODULE)));
+ goto _cleanup;
+ }
+
+ if (wcscmp(r, m->name)) {
+ rv = KHM_ERROR_INVALID_PARAM;
+ _report_mr2(KHERR_WARNING, MSG_RMI_MOD_MISMATCH,
+ _dupstr(r), _dupstr(m->name));
+ goto _cleanup;
+ }
+
+ /* check API version */
+ StringCbPrintf(resname, sizeof(resname),
+ L"\\StringFileInfo\\%04x%04x\\" TEXT(NIMV_APIVER),
+ languages[i].language,
+ languages[i].codepage);
+
+ if (!VerQueryValue(m->version_info,
+ resname, (LPVOID *) &r, &cb)) {
+ rv = KHM_ERROR_INVALID_PARAM;
+ _report_mr1(KHERR_WARNING, MSG_RMI_RES_MISSING,
+ _cstr(TEXT(NIMV_APIVER)));
+ goto _cleanup;
+ }
+
+ if (cb > KMM_MAXCB_NAME ||
+ FAILED(StringCbLength(r, KMM_MAXCB_NAME, &cb))) {
+ rv = KHM_ERROR_INVALID_PARAM;
+ _report_mr1(KHERR_WARNING, MSG_RMI_RES_TOO_LONG,
+ _cstr(TEXT(NIMV_APIVER)));
+ goto _cleanup;
+ }
+
+ t = wcstol(r, NULL, 10);
+
+ rv = kmmint_check_api_version(t);
+
+ if (KHM_FAILED(rv)) {
+ _report_mr2(KHERR_WARNING, MSG_RMI_API_MISMATCH,
+ _int32(t), _int32(KH_VERSION_API));
+ goto _cleanup;
+ }
+
+ /* Looks good. Now load the description, copyright, support URI
+ and file versions */
+ if (m->description) {
+ PFREE(m->description);
+ m->description = NULL;
+ }
+
+ StringCbPrintf(resname, sizeof(resname),
+ L"\\StringFileInfo\\%04x%04x\\FileDescription",
+ languages[i].language,
+ languages[i].codepage);
+
+ if (!VerQueryValue(m->version_info,
+ resname, (LPVOID *) &r, &cb)) {
+ rv = KHM_ERROR_INVALID_PARAM;
+ _report_mr1(KHERR_WARNING, MSG_RMI_RES_MISSING,
+ _cstr(L"FileDescription"));
+ goto _cleanup;
+ }
+
+ if (cb > KMM_MAXCB_DESC ||
+ FAILED(StringCbLength(r, KMM_MAXCB_DESC, &cb))) {
+ rv = KHM_ERROR_INVALID_PARAM;
+ _report_mr1(KHERR_WARNING, MSG_RMI_RES_TOO_LONG,
+ _cstr(L"FileDescription"));
+ goto _cleanup;
+ }
+
+ cb += sizeof(wchar_t);
+
+ m->description = PMALLOC(cb);
+#ifdef DEBUG
+ assert(m->description);
+#endif
+ StringCbCopy(m->description, cb, r);
+
+ /* on to the support URI */
+ if (m->support) {
+ PFREE(m->support);
+ m->support = NULL;
+ }
+
+ StringCbPrintf(resname, sizeof(resname),
+ L"\\StringFileInfo\\%04x%04x\\" TEXT(NIMV_SUPPORT),
+ languages[i].language,
+ languages[i].codepage);
+
+ if (!VerQueryValue(m->version_info,
+ resname, (LPVOID *) &r, &cb)) {
+ rv = KHM_ERROR_INVALID_PARAM;
+ _report_mr1(KHERR_WARNING, MSG_RMI_RES_MISSING,
+ _cstr(TEXT(NIMV_SUPPORT)));
+ goto _cleanup;
+ }
+
+ if (cb > KMM_MAXCB_SUPPORT ||
+ FAILED(StringCbLength(r, KMM_MAXCB_SUPPORT, &cb))) {
+ rv = KHM_ERROR_INVALID_PARAM;
+ _report_mr1(KHERR_WARNING, MSG_RMI_RES_TOO_LONG,
+ _cstr(TEXT(NIMV_SUPPORT)));
+ goto _cleanup;
+ }
+
+ cb += sizeof(wchar_t);
+
+ m->support = PMALLOC(cb);
+#ifdef DEBUG
+ assert(m->support);
+#endif
+ StringCbCopy(m->support, cb, r);
+
+ /* the vendor/copyright */
+ if (m->vendor) {
+ PFREE(m->vendor);
+ m->vendor = NULL;
+ }
+
+ StringCbPrintf(resname, sizeof(resname),
+ L"\\StringFileInfo\\%04x%04x\\LegalCopyright",
+ languages[i].language,
+ languages[i].codepage);
+
+ if (!VerQueryValue(m->version_info,
+ resname, (LPVOID *) &r, &cb)) {
+ rv = KHM_ERROR_INVALID_PARAM;
+ _report_mr1(KHERR_WARNING, MSG_RMI_RES_MISSING,
+ _cstr(L"LegalCopyright"));
+ goto _cleanup;
+ }
+
+ if (cb > KMM_MAXCB_SUPPORT ||
+ FAILED(StringCbLength(r, KMM_MAXCB_SUPPORT, &cb))) {
+ rv = KHM_ERROR_INVALID_PARAM;
+ _report_mr1(KHERR_WARNING, MSG_RMI_RES_TOO_LONG,
+ _cstr(L"LegalCopyright"));
+ goto _cleanup;
+ }
+
+ cb += sizeof(wchar_t);
+
+ m->vendor = PMALLOC(cb);
+#ifdef DEBUG
+ assert(m->vendor);
+#endif
+ StringCbCopy(m->vendor, cb, r);
+
+ if (!VerQueryValue(m->version_info,
+ L"\\",
+ (LPVOID *) &vff,
+ &cb) ||
+ cb != sizeof(*vff)) {
+
+ rv = KHM_ERROR_INVALID_PARAM;
+ _report_mr1(KHERR_WARNING, MSG_RMI_RES_MISSING,
+ _cstr(L"Fixed Version Info"));
+ goto _cleanup;
+ }
+
+ m->file_version.major = HIWORD(vff->dwFileVersionMS);
+ m->file_version.minor = LOWORD(vff->dwFileVersionMS);
+ m->file_version.patch = HIWORD(vff->dwFileVersionLS);
+ m->file_version.aux = LOWORD(vff->dwFileVersionLS);
+
+ m->prod_version.major = HIWORD(vff->dwProductVersionMS);
+ m->prod_version.minor = LOWORD(vff->dwProductVersionMS);
+ m->prod_version.patch = HIWORD(vff->dwProductVersionLS);
+ m->prod_version.aux = LOWORD(vff->dwProductVersionLS);
+
+ rv = KHM_ERROR_SUCCESS;
+
+ _cleanup:
+ if (KHM_FAILED(rv)) {
+ if (m->version_info) {
+ PFREE(m->version_info);
+ m->version_info = NULL;
+ }
+ }
+
+ return rv;
+}
+
+KHMEXP khm_int32 KHMAPI kmm_load_module(wchar_t * modname,
+ khm_int32 flags,
+ kmm_module * result)
+{
+ kmm_module_i * m = NULL;
+ kmm_module_i * mi;
+ size_t cbsize;
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+
+ if(FAILED(StringCbLength(modname, KMM_MAXCB_NAME, &cbsize)))
+ return KHM_ERROR_INVALID_PARAM;
+ cbsize += sizeof(wchar_t);
+
+ EnterCriticalSection(&cs_kmm);
+ mi = kmmint_find_module_i(modname);
+
+ if(mi != NULL) {
+ kmm_hold_module(kmm_handle_from_module(mi));
+ /* check if the module has either failed to load either or if
+ it has been terminated. If so, we try once again to load the
+ module. */
+ if(!(flags & KMM_LM_FLAG_NOLOAD) &&
+ (mi->state < 0 || mi->state == KMM_MODULE_STATE_EXITED))
+ {
+ mi->state = KMM_MODULE_STATE_PREINIT;
+ }
+ }
+ LeaveCriticalSection(&cs_kmm);
+
+ if(flags & KMM_LM_FLAG_NOLOAD) {
+ if(result)
+ *result = mi;
+ else if(mi)
+ kmm_release_module(kmm_handle_from_module(mi));
+
+ return (mi)? KHM_ERROR_SUCCESS: KHM_ERROR_NOT_FOUND;
+ }
+
+ if(mi) {
+ m = mi;
+ } else {
+ m = kmmint_get_module_i(modname);
+ m->state = KMM_MODULE_STATE_PREINIT;
+ kmm_hold_module(kmm_handle_from_module(m));
+ }
+
+ /* the module is already running or is already being
+ worked on by the registrar */
+ if(m->state != KMM_MODULE_STATE_PREINIT) {
+ if(result)
+ *result = kmm_handle_from_module(m);
+ else
+ kmm_release_module(kmm_handle_from_module(m));
+
+ return KHM_ERROR_EXISTS;
+ }
+
+ kmmint_add_to_module_queue();
+
+ if(flags & KMM_LM_FLAG_SYNC) {
+ kmm_hold_module(kmm_handle_from_module(m));
+ kmq_send_message(KMSG_KMM,
+ KMSG_KMM_I_REG,
+ KMM_REG_INIT_MODULE,
+ (void*) m);
+ if(m->state <= 0) {
+ /* failed to load ? */
+ if(m->state == KMM_MODULE_STATE_FAIL_NOT_FOUND)
+ rv = KHM_ERROR_NOT_FOUND;
+ else if(m->state == KMM_MODULE_STATE_FAIL_SIGNATURE)
+ rv = KHM_ERROR_INVALID_SIGNATURE;
+ else
+ rv = KHM_ERROR_UNKNOWN;
+
+ kmm_release_module(kmm_handle_from_module(m));
+ if(result)
+ *result = NULL;
+ } else {
+ if(result)
+ *result = kmm_handle_from_module(m);
+ else
+ kmm_release_module(kmm_handle_from_module(m));
+ }
+ } else {
+ kmm_hold_module(kmm_handle_from_module(m));
+ kmq_post_message(KMSG_KMM,
+ KMSG_KMM_I_REG,
+ KMM_REG_INIT_MODULE,
+ (void*) m);
+ if(result)
+ *result = kmm_handle_from_module(m);
+ else
+ kmm_release_module(kmm_handle_from_module(m));
+ }
+
+ return rv;
+}
+
+KHMEXP khm_int32 KHMAPI
+kmm_get_module_state(kmm_module m)
+{
+ if(!kmm_is_module(m))
+ return KMM_MODULE_STATE_NONE;
+ else
+ return kmm_module_from_handle(m)->state;
+}
+
+KHMEXP khm_int32 KHMAPI
+kmm_get_module_info_i(kmm_module vm, kmm_module_info * info) {
+ kmm_module_i * m;
+ khm_int32 rv;
+
+ EnterCriticalSection(&cs_kmm);
+ if (!kmm_is_module(vm) || !info)
+ rv = KHM_ERROR_INVALID_PARAM;
+ else {
+ m = kmm_module_from_handle(vm);
+
+ ZeroMemory(info, sizeof(*info));
+
+ info->reg.name = m->name;
+ info->reg.path = m->path;
+ info->reg.vendor = m->vendor;
+
+ info->reg.n_plugins = m->plugin_count;
+
+ info->state = m->state;
+
+ info->h_module = vm;
+
+ info->file_version = m->file_version;
+ info->product_version = m->prod_version;
+ kmm_hold_module(vm);
+
+ rv = KHM_ERROR_SUCCESS;
+ }
+ LeaveCriticalSection(&cs_kmm);
+
+ return rv;
+}
+
+KHMEXP khm_int32 KHMAPI
+kmm_release_module_info_i(kmm_module_info * info) {
+ if (info->h_module)
+ kmm_release_module(info->h_module);
+
+ ZeroMemory(info, sizeof(*info));
+
+ return KHM_ERROR_SUCCESS;
+}
+
+
+KHMEXP khm_int32 KHMAPI
+kmm_unload_module(kmm_module module) {
+
+ if(!kmm_is_module(module))
+ return KHM_ERROR_INVALID_PARAM;
+
+ kmm_hold_module(module);
+ kmq_post_message(KMSG_KMM,
+ KMSG_KMM_I_REG,
+ KMM_REG_EXIT_MODULE,
+ (void *) kmm_module_from_handle(module));
+
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP khm_int32 KHMAPI
+kmm_load_default_modules(void) {
+ khm_handle csm = NULL;
+ khm_handle cs_mod = NULL;
+ khm_int32 rv;
+ wchar_t buf[KMM_MAXCCH_NAME];
+ khm_size s;
+
+ rv = kmm_get_modules_config(0, &csm);
+ if(KHM_FAILED(rv))
+ return rv;
+
+ _begin_task(KHERR_CF_TRANSITIVE);
+ _report_mr0(KHERR_NONE, MSG_LOAD_DEFAULT);
+ _describe();
+
+ kmmint_add_to_module_queue();
+
+ while(KHM_SUCCEEDED(khc_enum_subspaces(csm, cs_mod, &cs_mod))) {
+
+ s = sizeof(buf);
+ if (KHM_FAILED(khc_get_config_space_name(cs_mod, buf, &s)))
+ continue;
+
+ /* check for schema subspace. This is not an actual module. */
+ if (!wcscmp(buf, L"_Schema"))
+ continue;
+
+ kmm_load_module(buf, 0, NULL);
+ }
+
+ kmmint_remove_from_module_queue();
+
+ if(csm)
+ khc_close_space(csm);
+
+ _end_task();
+
+ return rv;
+}
+
+#ifdef _WIN32
+KHMEXP HMODULE KHMAPI
+kmm_get_hmodule(kmm_module m)
+{
+ if(!kmm_is_module(m))
+ return NULL;
+ else
+ return kmm_module_from_handle(m)->h_module;
+}
+#endif
diff --git a/src/windows/identity/kmm/kmm_plugin.c b/src/windows/identity/kmm/kmm_plugin.c
index 18a46b7c46..89e31ad844 100644
--- a/src/windows/identity/kmm/kmm_plugin.c
+++ b/src/windows/identity/kmm/kmm_plugin.c
@@ -1,414 +1,414 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<kmminternal.h>
-
-/* Called with no locks held to get a kmm_plugin_i structure
- that matches the name. First we look in the hash table, and
- if one isn't found, we create an empty one.
-*/
-
-kmm_plugin_i *
-kmmint_get_plugin_i(wchar_t * name)
-{
- kmm_plugin_i * p;
- size_t cb;
-
- if(FAILED(StringCbLength(name, KMM_MAXCB_NAME, &cb)))
- return NULL;
- cb += sizeof(wchar_t);
-
- EnterCriticalSection(&cs_kmm);
- p = (kmm_plugin_i *) hash_lookup(hash_plugins, (void *) name);
-
- if(p == NULL) {
- p = PMALLOC(sizeof(kmm_plugin_i));
- ZeroMemory(p, sizeof(kmm_plugin_i));
- p->magic = KMM_PLUGIN_MAGIC;
- p->p.name = PMALLOC(cb);
- StringCbCopy(p->p.name, cb, name);
- p->state = KMM_PLUGIN_STATE_NONE;
-
- hash_add(hash_plugins, (void *) p->p.name, (void *) p);
- kmmint_list_plugin(p);
- }
- LeaveCriticalSection(&cs_kmm);
-
- return p;
-}
-
-kmm_plugin_i *
-kmmint_find_plugin_i(wchar_t * name)
-{
- kmm_plugin_i * p;
- size_t cb;
-
- if(FAILED(StringCbLength(name, KMM_MAXCB_NAME, &cb)))
- return NULL;
-
- EnterCriticalSection(&cs_kmm);
- p = (kmm_plugin_i *) hash_lookup(hash_plugins, (void *) name);
- LeaveCriticalSection(&cs_kmm);
-
- return p;
-}
-
-/* the plugin must be delisted before calling this */
-void
-kmmint_list_plugin(kmm_plugin_i * p)
-{
- EnterCriticalSection(&cs_kmm);
- if((p->flags & KMM_PLUGIN_FLAG_IN_MODLIST) ||
- (p->flags & KMM_PLUGIN_FLAG_IN_LIST))
- {
- RaiseException(2, EXCEPTION_NONCONTINUABLE, 0, NULL);
- }
- p->flags |= KMM_PLUGIN_FLAG_IN_LIST;
- LPUSH(&kmm_listed_plugins, p);
- LeaveCriticalSection(&cs_kmm);
-}
-
-void
-kmmint_delist_plugin(kmm_plugin_i * p)
-{
- EnterCriticalSection(&cs_kmm);
- if(p->flags & KMM_PLUGIN_FLAG_IN_LIST) {
- p->flags &= ~KMM_PLUGIN_FLAG_IN_LIST;
- LDELETE(&kmm_listed_plugins, p);
- }
- if(p->flags & KMM_PLUGIN_FLAG_IN_MODLIST) {
- p->flags &= ~KMM_PLUGIN_FLAG_IN_MODLIST;
- LDELETE(&(p->module->plugins), p);
- }
- LeaveCriticalSection(&cs_kmm);
-}
-
-KHMEXP khm_int32 KHMAPI
-kmm_hold_plugin(kmm_plugin p)
-{
- kmm_plugin_i * pi;
-
- if(!kmm_is_plugin(p))
- return KHM_ERROR_INVALID_PARAM;
-
- EnterCriticalSection(&cs_kmm);
- pi = kmm_plugin_from_handle(p);
- pi->refcount++;
- LeaveCriticalSection(&cs_kmm);
-
- return KHM_ERROR_SUCCESS;
-}
-
-/* called with cs_kmm held */
-void
-kmmint_free_plugin(kmm_plugin_i * pi)
-{
- int i;
- pi->magic = 0;
-
- hash_del(hash_plugins, (void *) pi->p.name);
-
- kmmint_delist_plugin(pi);
-
- for(i=0; i<pi->n_dependants; i++) {
- kmm_release_plugin(kmm_handle_from_plugin(pi->dependants[i]));
- pi->dependants[i] = NULL;
- }
-
- if(pi->module) {
- kmm_release_module(kmm_handle_from_module(pi->module));
- }
-
- pi->module = NULL;
- pi->p.module = NULL;
-
- if(pi->p.name)
- PFREE(pi->p.name);
- pi->p.name = NULL;
-
- if(pi->p.description)
- PFREE(pi->p.description);
- pi->p.description = NULL;
-
- if(pi->p.dependencies)
- PFREE(pi->p.dependencies);
- pi->p.dependencies = NULL;
-
- PFREE(pi);
-}
-
-KHMEXP khm_int32 KHMAPI
-kmm_enable_plugin(kmm_plugin p, khm_boolean enable) {
- kmm_plugin_i * pi;
- khm_int32 rv = KHM_ERROR_NOT_FOUND; /* default to error */
- khm_handle csp_plugin = NULL;
-
- EnterCriticalSection(&cs_kmm);
- if (!kmm_is_plugin(p)) {
- rv = KHM_ERROR_INVALID_PARAM;
- goto _cleanup;
- }
-
- pi = kmm_plugin_from_handle(p);
-
- if (KHM_FAILED(rv = kmm_get_plugin_config(pi->p.name, 0, &csp_plugin))) {
- goto _cleanup;
- }
-
- if (KHM_FAILED(rv = khc_write_int32(csp_plugin, L"Disabled", !enable))) {
- goto _cleanup;
- }
-
- rv = KHM_ERROR_SUCCESS;
-
- _cleanup:
- LeaveCriticalSection(&cs_kmm);
-
- if (csp_plugin)
- khc_close_space(csp_plugin);
-
- return rv;
-}
-
-KHMEXP khm_int32 KHMAPI
-kmm_get_plugin_info_i(kmm_plugin p, kmm_plugin_info * info) {
- khm_int32 rv = KHM_ERROR_SUCCESS;
- kmm_plugin_i * pi;
- khm_handle csp_plugin;
-
- if (!info)
- return KHM_ERROR_INVALID_PARAM;
-
- EnterCriticalSection(&cs_kmm);
- if (!kmm_is_plugin(p)) {
- rv = KHM_ERROR_INVALID_PARAM;
- goto _cleanup;
- }
-
- pi = kmm_plugin_from_handle(p);
-
- ZeroMemory(info, sizeof(*info));
-
- info->reg = pi->p;
- info->reg.msg_proc = NULL;
-
- if (KHM_FAILED(kmm_get_plugin_config(pi->p.name, KHM_PERM_READ,
- &csp_plugin))) {
- info->failure_count = 0;
- *((khm_int64 *)&info->failure_time) = 0;
- info->failure_reason = 0;
- } else {
- if (KHM_FAILED(khc_read_int32(csp_plugin, L"FailureCount",
- &info->failure_count)))
- info->failure_count = 0;
- if (KHM_FAILED(khc_read_int64(csp_plugin, L"FailureTime",
- (khm_int64 *) &info->failure_time)))
- *((khm_int64 *) &info->failure_time) = 0;
- if (KHM_FAILED(khc_read_int32(csp_plugin, L"FailureReason",
- &info->failure_reason)))
- info->failure_reason = 0;
-
- khc_close_space(csp_plugin);
- }
-
- info->state = pi->state;
-
- kmm_hold_plugin(p);
- info->h_plugin = p;
-
- info->flags = (pi->flags & KMM_PLUGIN_FLAG_DISABLED);
-
- _cleanup:
- LeaveCriticalSection(&cs_kmm);
-
- return rv;
-}
-
-KHMEXP khm_int32 KHMAPI
-kmm_release_plugin_info_i(kmm_plugin_info * info) {
- khm_int32 rv;
-
- if (!info || !info->h_plugin)
- return KHM_ERROR_INVALID_PARAM;
-
- rv = kmm_release_plugin(info->h_plugin);
-
- ZeroMemory(info, sizeof(info));
-
- return rv;
-}
-
-KHMEXP khm_int32 KHMAPI
-kmm_get_next_plugin(kmm_plugin p, kmm_plugin * p_next) {
- khm_int32 rv = KHM_ERROR_SUCCESS;
- kmm_plugin_i * pi;
- kmm_plugin_i * pi_next = NULL;
- kmm_module_i * m;
-
- EnterCriticalSection(&cs_kmm);
- if (p == NULL) {
- if (kmm_listed_plugins)
- pi_next = kmm_listed_plugins;
- else {
- for (m = kmm_all_modules; m; m = LNEXT(m)) {
- if (m->plugins) {
- pi_next = m->plugins;
- break;
- }
- }
- }
- } else if (kmm_is_plugin(p)) {
- pi = kmm_plugin_from_handle(p);
- pi_next = LNEXT(pi);
-
- if (!pi_next) {
- /* we have either exhausted the listed plugins or we are
- at the end of the module's plugin list */
- if (pi->module) {
- m = LNEXT(pi->module);
- } else {
- m = kmm_all_modules;
- }
-
- for(; m; m = LNEXT(m)) {
- if (m->plugins) {
- pi_next = m->plugins;
- break;
- }
- }
- }
- }
-
- if (pi_next) {
- *p_next = kmm_handle_from_plugin(pi_next);
- kmm_hold_plugin(*p_next);
- } else {
- *p_next = NULL;
- rv = KHM_ERROR_NOT_FOUND;
- }
-
- LeaveCriticalSection(&cs_kmm);
- return rv;
-}
-
-KHMEXP khm_int32 KHMAPI
-kmm_release_plugin(kmm_plugin p)
-{
- kmm_plugin_i * pi;
-
- if(!kmm_is_plugin(p))
- return KHM_ERROR_INVALID_PARAM;
-
- EnterCriticalSection(&cs_kmm);
- pi = kmm_plugin_from_handle(p);
- pi->refcount--;
- if(pi->refcount == 0) {
- kmmint_free_plugin(pi);
- }
- LeaveCriticalSection(&cs_kmm);
-
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP khm_int32 KHMAPI
-kmm_provide_plugin(kmm_module module, kmm_plugin_reg * plugin)
-{
- kmm_module_i * m;
- kmm_plugin_i * p;
- size_t cb_name = 0;
- size_t cb_desc = 0;
- size_t cb_dep = 0;
-
- m = kmm_module_from_handle(module);
-
- /* can only called when handing init_module() */
- if(m->state != KMM_MODULE_STATE_INIT)
- return KHM_ERROR_INVALID_OPERATION;
-
- if(!plugin ||
- FAILED(StringCbLength(plugin->name, KMM_MAXCB_NAME - sizeof(wchar_t),
- &cb_name)) ||
- (plugin->description &&
- FAILED(StringCbLength(plugin->description,
- KMM_MAXCB_DESC - sizeof(wchar_t),
- &cb_desc))) ||
- (plugin->dependencies &&
- KHM_FAILED(multi_string_length_cb(plugin->dependencies,
- KMM_MAXCB_DEPS, &cb_dep)))) {
- return KHM_ERROR_INVALID_PARAM;
- }
-
- cb_name += sizeof(wchar_t);
- cb_desc += sizeof(wchar_t);
-
- p = kmmint_get_plugin_i(plugin->name);
-
- /* released below or in kmmint_init_module() */
- kmm_hold_plugin(kmm_handle_from_plugin(p));
-
- if(p->state != KMM_PLUGIN_STATE_NONE &&
- p->state != KMM_PLUGIN_STATE_PLACEHOLDER)
- {
- kmm_release_plugin(kmm_handle_from_plugin(p));
- return KHM_ERROR_DUPLICATE;
- }
-
- /* released when the plugin quits */
- kmm_hold_module(module);
-
- p->module = m;
- p->p.flags = plugin->flags;
- p->p.msg_proc = plugin->msg_proc;
- p->p.type = plugin->type;
-
- if(plugin->description) {
- p->p.description = PMALLOC(cb_desc);
- StringCbCopy(p->p.description, cb_desc, plugin->description);
- } else
- p->p.description = NULL;
-
- if(plugin->dependencies) {
- p->p.dependencies = PMALLOC(cb_dep);
- multi_string_copy_cb(p->p.dependencies, cb_dep, plugin->dependencies);
- } else
- p->p.dependencies = NULL;
-
- p->p.module = p->module->name;
-
- p->p.icon = plugin->icon;
-
- p->state = KMM_PLUGIN_STATE_REG;
-
- kmmint_delist_plugin(p);
- EnterCriticalSection(&cs_kmm);
- LPUSH(&(m->plugins), p);
- p->flags |= KMM_PLUGIN_FLAG_IN_MODLIST;
- LeaveCriticalSection(&cs_kmm);
-
- /* leave the plugin held because it is in the module's plugin list */
- return KHM_ERROR_SUCCESS;
-}
-
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<kmminternal.h>
+
+/* Called with no locks held to get a kmm_plugin_i structure
+ that matches the name. First we look in the hash table, and
+ if one isn't found, we create an empty one.
+*/
+
+kmm_plugin_i *
+kmmint_get_plugin_i(wchar_t * name)
+{
+ kmm_plugin_i * p;
+ size_t cb;
+
+ if(FAILED(StringCbLength(name, KMM_MAXCB_NAME, &cb)))
+ return NULL;
+ cb += sizeof(wchar_t);
+
+ EnterCriticalSection(&cs_kmm);
+ p = (kmm_plugin_i *) hash_lookup(hash_plugins, (void *) name);
+
+ if(p == NULL) {
+ p = PMALLOC(sizeof(kmm_plugin_i));
+ ZeroMemory(p, sizeof(kmm_plugin_i));
+ p->magic = KMM_PLUGIN_MAGIC;
+ p->p.name = PMALLOC(cb);
+ StringCbCopy(p->p.name, cb, name);
+ p->state = KMM_PLUGIN_STATE_NONE;
+
+ hash_add(hash_plugins, (void *) p->p.name, (void *) p);
+ kmmint_list_plugin(p);
+ }
+ LeaveCriticalSection(&cs_kmm);
+
+ return p;
+}
+
+kmm_plugin_i *
+kmmint_find_plugin_i(wchar_t * name)
+{
+ kmm_plugin_i * p;
+ size_t cb;
+
+ if(FAILED(StringCbLength(name, KMM_MAXCB_NAME, &cb)))
+ return NULL;
+
+ EnterCriticalSection(&cs_kmm);
+ p = (kmm_plugin_i *) hash_lookup(hash_plugins, (void *) name);
+ LeaveCriticalSection(&cs_kmm);
+
+ return p;
+}
+
+/* the plugin must be delisted before calling this */
+void
+kmmint_list_plugin(kmm_plugin_i * p)
+{
+ EnterCriticalSection(&cs_kmm);
+ if((p->flags & KMM_PLUGIN_FLAG_IN_MODLIST) ||
+ (p->flags & KMM_PLUGIN_FLAG_IN_LIST))
+ {
+ RaiseException(2, EXCEPTION_NONCONTINUABLE, 0, NULL);
+ }
+ p->flags |= KMM_PLUGIN_FLAG_IN_LIST;
+ LPUSH(&kmm_listed_plugins, p);
+ LeaveCriticalSection(&cs_kmm);
+}
+
+void
+kmmint_delist_plugin(kmm_plugin_i * p)
+{
+ EnterCriticalSection(&cs_kmm);
+ if(p->flags & KMM_PLUGIN_FLAG_IN_LIST) {
+ p->flags &= ~KMM_PLUGIN_FLAG_IN_LIST;
+ LDELETE(&kmm_listed_plugins, p);
+ }
+ if(p->flags & KMM_PLUGIN_FLAG_IN_MODLIST) {
+ p->flags &= ~KMM_PLUGIN_FLAG_IN_MODLIST;
+ LDELETE(&(p->module->plugins), p);
+ }
+ LeaveCriticalSection(&cs_kmm);
+}
+
+KHMEXP khm_int32 KHMAPI
+kmm_hold_plugin(kmm_plugin p)
+{
+ kmm_plugin_i * pi;
+
+ if(!kmm_is_plugin(p))
+ return KHM_ERROR_INVALID_PARAM;
+
+ EnterCriticalSection(&cs_kmm);
+ pi = kmm_plugin_from_handle(p);
+ pi->refcount++;
+ LeaveCriticalSection(&cs_kmm);
+
+ return KHM_ERROR_SUCCESS;
+}
+
+/* called with cs_kmm held */
+void
+kmmint_free_plugin(kmm_plugin_i * pi)
+{
+ int i;
+ pi->magic = 0;
+
+ hash_del(hash_plugins, (void *) pi->p.name);
+
+ kmmint_delist_plugin(pi);
+
+ for(i=0; i<pi->n_dependants; i++) {
+ kmm_release_plugin(kmm_handle_from_plugin(pi->dependants[i]));
+ pi->dependants[i] = NULL;
+ }
+
+ if(pi->module) {
+ kmm_release_module(kmm_handle_from_module(pi->module));
+ }
+
+ pi->module = NULL;
+ pi->p.module = NULL;
+
+ if(pi->p.name)
+ PFREE(pi->p.name);
+ pi->p.name = NULL;
+
+ if(pi->p.description)
+ PFREE(pi->p.description);
+ pi->p.description = NULL;
+
+ if(pi->p.dependencies)
+ PFREE(pi->p.dependencies);
+ pi->p.dependencies = NULL;
+
+ PFREE(pi);
+}
+
+KHMEXP khm_int32 KHMAPI
+kmm_enable_plugin(kmm_plugin p, khm_boolean enable) {
+ kmm_plugin_i * pi;
+ khm_int32 rv = KHM_ERROR_NOT_FOUND; /* default to error */
+ khm_handle csp_plugin = NULL;
+
+ EnterCriticalSection(&cs_kmm);
+ if (!kmm_is_plugin(p)) {
+ rv = KHM_ERROR_INVALID_PARAM;
+ goto _cleanup;
+ }
+
+ pi = kmm_plugin_from_handle(p);
+
+ if (KHM_FAILED(rv = kmm_get_plugin_config(pi->p.name, 0, &csp_plugin))) {
+ goto _cleanup;
+ }
+
+ if (KHM_FAILED(rv = khc_write_int32(csp_plugin, L"Disabled", !enable))) {
+ goto _cleanup;
+ }
+
+ rv = KHM_ERROR_SUCCESS;
+
+ _cleanup:
+ LeaveCriticalSection(&cs_kmm);
+
+ if (csp_plugin)
+ khc_close_space(csp_plugin);
+
+ return rv;
+}
+
+KHMEXP khm_int32 KHMAPI
+kmm_get_plugin_info_i(kmm_plugin p, kmm_plugin_info * info) {
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+ kmm_plugin_i * pi;
+ khm_handle csp_plugin;
+
+ if (!info)
+ return KHM_ERROR_INVALID_PARAM;
+
+ EnterCriticalSection(&cs_kmm);
+ if (!kmm_is_plugin(p)) {
+ rv = KHM_ERROR_INVALID_PARAM;
+ goto _cleanup;
+ }
+
+ pi = kmm_plugin_from_handle(p);
+
+ ZeroMemory(info, sizeof(*info));
+
+ info->reg = pi->p;
+ info->reg.msg_proc = NULL;
+
+ if (KHM_FAILED(kmm_get_plugin_config(pi->p.name, KHM_PERM_READ,
+ &csp_plugin))) {
+ info->failure_count = 0;
+ *((khm_int64 *)&info->failure_time) = 0;
+ info->failure_reason = 0;
+ } else {
+ if (KHM_FAILED(khc_read_int32(csp_plugin, L"FailureCount",
+ &info->failure_count)))
+ info->failure_count = 0;
+ if (KHM_FAILED(khc_read_int64(csp_plugin, L"FailureTime",
+ (khm_int64 *) &info->failure_time)))
+ *((khm_int64 *) &info->failure_time) = 0;
+ if (KHM_FAILED(khc_read_int32(csp_plugin, L"FailureReason",
+ &info->failure_reason)))
+ info->failure_reason = 0;
+
+ khc_close_space(csp_plugin);
+ }
+
+ info->state = pi->state;
+
+ kmm_hold_plugin(p);
+ info->h_plugin = p;
+
+ info->flags = (pi->flags & KMM_PLUGIN_FLAG_DISABLED);
+
+ _cleanup:
+ LeaveCriticalSection(&cs_kmm);
+
+ return rv;
+}
+
+KHMEXP khm_int32 KHMAPI
+kmm_release_plugin_info_i(kmm_plugin_info * info) {
+ khm_int32 rv;
+
+ if (!info || !info->h_plugin)
+ return KHM_ERROR_INVALID_PARAM;
+
+ rv = kmm_release_plugin(info->h_plugin);
+
+ ZeroMemory(info, sizeof(info));
+
+ return rv;
+}
+
+KHMEXP khm_int32 KHMAPI
+kmm_get_next_plugin(kmm_plugin p, kmm_plugin * p_next) {
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+ kmm_plugin_i * pi;
+ kmm_plugin_i * pi_next = NULL;
+ kmm_module_i * m;
+
+ EnterCriticalSection(&cs_kmm);
+ if (p == NULL) {
+ if (kmm_listed_plugins)
+ pi_next = kmm_listed_plugins;
+ else {
+ for (m = kmm_all_modules; m; m = LNEXT(m)) {
+ if (m->plugins) {
+ pi_next = m->plugins;
+ break;
+ }
+ }
+ }
+ } else if (kmm_is_plugin(p)) {
+ pi = kmm_plugin_from_handle(p);
+ pi_next = LNEXT(pi);
+
+ if (!pi_next) {
+ /* we have either exhausted the listed plugins or we are
+ at the end of the module's plugin list */
+ if (pi->module) {
+ m = LNEXT(pi->module);
+ } else {
+ m = kmm_all_modules;
+ }
+
+ for(; m; m = LNEXT(m)) {
+ if (m->plugins) {
+ pi_next = m->plugins;
+ break;
+ }
+ }
+ }
+ }
+
+ if (pi_next) {
+ *p_next = kmm_handle_from_plugin(pi_next);
+ kmm_hold_plugin(*p_next);
+ } else {
+ *p_next = NULL;
+ rv = KHM_ERROR_NOT_FOUND;
+ }
+
+ LeaveCriticalSection(&cs_kmm);
+ return rv;
+}
+
+KHMEXP khm_int32 KHMAPI
+kmm_release_plugin(kmm_plugin p)
+{
+ kmm_plugin_i * pi;
+
+ if(!kmm_is_plugin(p))
+ return KHM_ERROR_INVALID_PARAM;
+
+ EnterCriticalSection(&cs_kmm);
+ pi = kmm_plugin_from_handle(p);
+ pi->refcount--;
+ if(pi->refcount == 0) {
+ kmmint_free_plugin(pi);
+ }
+ LeaveCriticalSection(&cs_kmm);
+
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP khm_int32 KHMAPI
+kmm_provide_plugin(kmm_module module, kmm_plugin_reg * plugin)
+{
+ kmm_module_i * m;
+ kmm_plugin_i * p;
+ size_t cb_name = 0;
+ size_t cb_desc = 0;
+ size_t cb_dep = 0;
+
+ m = kmm_module_from_handle(module);
+
+ /* can only called when handing init_module() */
+ if(m->state != KMM_MODULE_STATE_INIT)
+ return KHM_ERROR_INVALID_OPERATION;
+
+ if(!plugin ||
+ FAILED(StringCbLength(plugin->name, KMM_MAXCB_NAME - sizeof(wchar_t),
+ &cb_name)) ||
+ (plugin->description &&
+ FAILED(StringCbLength(plugin->description,
+ KMM_MAXCB_DESC - sizeof(wchar_t),
+ &cb_desc))) ||
+ (plugin->dependencies &&
+ KHM_FAILED(multi_string_length_cb(plugin->dependencies,
+ KMM_MAXCB_DEPS, &cb_dep)))) {
+ return KHM_ERROR_INVALID_PARAM;
+ }
+
+ cb_name += sizeof(wchar_t);
+ cb_desc += sizeof(wchar_t);
+
+ p = kmmint_get_plugin_i(plugin->name);
+
+ /* released below or in kmmint_init_module() */
+ kmm_hold_plugin(kmm_handle_from_plugin(p));
+
+ if(p->state != KMM_PLUGIN_STATE_NONE &&
+ p->state != KMM_PLUGIN_STATE_PLACEHOLDER)
+ {
+ kmm_release_plugin(kmm_handle_from_plugin(p));
+ return KHM_ERROR_DUPLICATE;
+ }
+
+ /* released when the plugin quits */
+ kmm_hold_module(module);
+
+ p->module = m;
+ p->p.flags = plugin->flags;
+ p->p.msg_proc = plugin->msg_proc;
+ p->p.type = plugin->type;
+
+ if(plugin->description) {
+ p->p.description = PMALLOC(cb_desc);
+ StringCbCopy(p->p.description, cb_desc, plugin->description);
+ } else
+ p->p.description = NULL;
+
+ if(plugin->dependencies) {
+ p->p.dependencies = PMALLOC(cb_dep);
+ multi_string_copy_cb(p->p.dependencies, cb_dep, plugin->dependencies);
+ } else
+ p->p.dependencies = NULL;
+
+ p->p.module = p->module->name;
+
+ p->p.icon = plugin->icon;
+
+ p->state = KMM_PLUGIN_STATE_REG;
+
+ kmmint_delist_plugin(p);
+ EnterCriticalSection(&cs_kmm);
+ LPUSH(&(m->plugins), p);
+ p->flags |= KMM_PLUGIN_FLAG_IN_MODLIST;
+ LeaveCriticalSection(&cs_kmm);
+
+ /* leave the plugin held because it is in the module's plugin list */
+ return KHM_ERROR_SUCCESS;
+}
+
diff --git a/src/windows/identity/kmm/kmm_reg.c b/src/windows/identity/kmm/kmm_reg.c
index 60159df37c..66354229fb 100644
--- a/src/windows/identity/kmm/kmm_reg.c
+++ b/src/windows/identity/kmm/kmm_reg.c
@@ -1,336 +1,336 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- * Copyright (c) 2006 Secure Endpoints Inc.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<kmminternal.h>
-
-KHMEXP khm_int32 KHMAPI
-kmm_get_module_info(wchar_t * module_name, khm_int32 flags,
- kmm_module_info * buffer, khm_size * cb_buffer)
-{
- /*TODO:Implement this */
- return KHM_ERROR_NOT_IMPLEMENTED;
-}
-
-KHMEXP khm_int32 KHMAPI
-kmm_get_plugin_info(wchar_t * plugin_name,
- kmm_plugin_info * buffer, khm_size * cb_buffer)
-{
- /*TODO:Implement this */
- return KHM_ERROR_NOT_IMPLEMENTED;
-}
-
-KHMEXP khm_int32 KHMAPI
-kmm_get_plugins_config(khm_int32 flags, khm_handle * result) {
- khm_handle csp_root;
- khm_handle csp_plugins;
- khm_int32 rv;
-
- rv = khc_open_space(KHM_INVALID_HANDLE, KMM_CSNAME_ROOT, flags, &csp_root);
-
- if(KHM_FAILED(rv))
- return rv;
-
- rv = khc_open_space(csp_root, KMM_CSNAME_PLUGINS, flags, &csp_plugins);
- khc_close_space(csp_root);
-
- if(KHM_SUCCEEDED(rv))
- *result = csp_plugins;
- else
- *result = NULL;
-
- return rv;
-}
-
-
-KHMEXP khm_int32 KHMAPI
-kmm_get_modules_config(khm_int32 flags, khm_handle * result) {
- khm_handle croot;
- khm_handle kmm_all_modules;
- khm_int32 rv;
-
- rv = khc_open_space(NULL, KMM_CSNAME_ROOT, flags, &croot);
-
- if(KHM_FAILED(rv))
- return rv;
-
- rv = khc_open_space(croot, KMM_CSNAME_MODULES, flags, &kmm_all_modules);
- khc_close_space(croot);
-
- if(KHM_SUCCEEDED(rv))
- *result = kmm_all_modules;
- else
- *result = NULL;
-
- return rv;
-}
-
-
-KHMEXP khm_int32 KHMAPI
-kmm_get_plugin_config(wchar_t * plugin, khm_int32 flags, khm_handle * result)
-{
- khm_handle csplugins;
- khm_handle csplugin;
- khm_int32 rv;
-
- if(!plugin || wcschr(plugin, L'/') || wcschr(plugin, L'\\'))
- return KHM_ERROR_INVALID_PARAM;
-
- if(KHM_FAILED(kmm_get_plugins_config(flags, &csplugins)))
- return KHM_ERROR_UNKNOWN;
-
- rv = khc_open_space(csplugins, plugin, flags, &csplugin);
- *result = csplugin;
-
- khc_close_space(csplugins);
-
- return rv;
-}
-
-
-KHMEXP khm_int32 KHMAPI
-kmm_get_module_config(wchar_t * module, khm_int32 flags, khm_handle * result)
-{
- khm_handle csmodules;
- khm_handle csmodule;
- khm_int32 rv;
-
- if(!module || wcschr(module, L'/') || wcschr(module, L'\\'))
- return KHM_ERROR_INVALID_PARAM;
-
- if(KHM_FAILED(kmm_get_modules_config(flags, &csmodules)))
- return KHM_ERROR_UNKNOWN;
-
- rv = khc_open_space(csmodules, module, flags, &csmodule);
- *result = csmodule;
-
- khc_close_space(csmodules);
-
- return rv;
-}
-
-KHMEXP khm_int32 KHMAPI
-kmm_register_plugin(kmm_plugin_reg * plugin, khm_int32 config_flags)
-{
- khm_int32 rv = KHM_ERROR_SUCCESS;
- khm_handle csp_plugin = NULL;
- khm_handle csp_module = NULL;
- size_t cch;
-
- /* avoid accidently creating the module key if it doesn't exist */
- config_flags &= ~KHM_FLAG_CREATE;
-
- if((plugin == NULL) ||
- (plugin->dependencies &&
- KHM_FAILED(multi_string_length_cch(plugin->dependencies,
- KMM_MAXCCH_DEPS, &cch))) ||
- FAILED(StringCchLength(plugin->module, KMM_MAXCCH_NAME, &cch)) ||
- (plugin->description &&
- FAILED(StringCchLength(plugin->description,
- KMM_MAXCCH_DESC, &cch))) ||
- FAILED(StringCchLength(plugin->name, KMM_MAXCCH_NAME, &cch)))
- {
- return KHM_ERROR_INVALID_PARAM;
- }
-
- /* note that we are retaining the length of the plugin name in
- chars in cch */
- cch ++;
-
-#define CKRV if(KHM_FAILED(rv)) goto _exit
-
- rv = kmm_get_plugin_config(plugin->name,
- config_flags | KHM_FLAG_CREATE, &csp_plugin);
- CKRV;
-
- /* should fail if the module key doesn't exist */
- rv = kmm_get_module_config(plugin->module, config_flags, &csp_module);
- CKRV;
-
- /*TODO: Make sure that the module registration is in the same
- config store as the one in which the plugin is going to be
- registered */
-
- rv = khc_write_string(csp_plugin, L"Module", plugin->module);
- CKRV;
- if(plugin->description) {
- rv = khc_write_string(csp_plugin, L"Description", plugin->description);
- CKRV;
- }
-
- if(plugin->dependencies) {
- rv = khc_write_multi_string(csp_plugin, L"Dependencies",
- plugin->dependencies);
- CKRV;
- }
-
- rv = khc_write_int32(csp_plugin, L"Type", plugin->type);
- CKRV;
- rv = khc_write_int32(csp_plugin, L"Disabled",
- !!(plugin->flags & KMM_PLUGIN_FLAG_DISABLED));
- CKRV;
-
- {
- khm_size cb = 0;
- wchar_t * pl = NULL;
- size_t scb = 0;
-
- rv = khc_read_multi_string(csp_module, L"PluginList", NULL, &cb);
- if(rv != KHM_ERROR_TOO_LONG) {
- if (rv == KHM_ERROR_NOT_FOUND) {
-
- scb = cb = cch * sizeof(wchar_t);
- pl = PMALLOC(cb);
- multi_string_init(pl, cb);
- rv = KHM_ERROR_SUCCESS;
-
- goto add_plugin_to_list;
-
- } else {
- goto _exit;
- }
- }
-
- cb += cch * sizeof(wchar_t);
- scb = cb;
-
- pl = PMALLOC(cb);
-
- rv = khc_read_multi_string(csp_module, L"PluginList", pl, &cb);
- if(KHM_FAILED(rv)) {
- if(pl)
- PFREE(pl);
- goto _exit;
- }
-
- add_plugin_to_list:
-
- if(!multi_string_find(pl, plugin->name, 0)) {
- multi_string_append(pl, &scb, plugin->name);
- rv = khc_write_multi_string(csp_module, L"PluginList", pl);
- }
-
- PFREE(pl);
- CKRV;
- }
-
-#undef CKRV
-
-_exit:
- if(csp_plugin)
- khc_close_space(csp_plugin);
- if(csp_module)
- khc_close_space(csp_module);
-
- return rv;
-}
-
-KHMEXP khm_int32 KHMAPI
-kmm_register_module(kmm_module_reg * module, khm_int32 config_flags)
-{
- khm_int32 rv = KHM_ERROR_SUCCESS;
- khm_handle csp_module = NULL;
- size_t cch;
- int i;
-
- if((module == NULL) ||
- FAILED(StringCchLength(module->name, KMM_MAXCCH_NAME, &cch)) ||
- (module->description &&
- FAILED(StringCchLength(module->description,
- KMM_MAXCCH_DESC, &cch))) ||
- FAILED(StringCchLength(module->path, MAX_PATH, &cch)) ||
- (module->n_plugins > 0 && module->plugin_reg_info == NULL)) {
- return KHM_ERROR_INVALID_PARAM;
- }
-
-#define CKRV if(KHM_FAILED(rv)) goto _exit
-
- rv = kmm_get_module_config(module->name, config_flags | KHM_FLAG_CREATE,
- &csp_module);
- CKRV;
-
- rv = khc_write_string(csp_module, L"ImagePath", module->path);
- CKRV;
-
- rv = khc_write_int32(csp_module, L"Disabled", 0);
- CKRV;
-
- /* FileVersion and ProductVersion will be set when the module
- is loaded for the first time */
-
- for(i=0; i<module->n_plugins; i++) {
- rv = kmm_register_plugin(&(module->plugin_reg_info[i]), config_flags);
- CKRV;
- }
-
-#undef CKRV
-_exit:
- if(csp_module)
- khc_close_space(csp_module);
-
- return rv;
-}
-
-KHMEXP khm_int32 KHMAPI
-kmm_unregister_plugin(wchar_t * plugin, khm_int32 config_flags)
-{
- khm_handle csp_plugin = NULL;
- khm_int32 rv = KHM_ERROR_SUCCESS;
-
- rv = kmm_get_plugin_config(plugin, config_flags, &csp_plugin);
-
- if (KHM_FAILED(rv))
- goto _cleanup;
-
- rv = khc_remove_space(csp_plugin);
-
- _cleanup:
-
- if (csp_plugin)
- khc_close_space(csp_plugin);
-
- return rv;
-}
-
-KHMEXP khm_int32 KHMAPI
-kmm_unregister_module(wchar_t * module, khm_int32 config_flags)
-{
- khm_handle csp_module = NULL;
- khm_int32 rv = KHM_ERROR_SUCCESS;
-
- rv = kmm_get_module_config(module, config_flags, &csp_module);
-
- if (KHM_FAILED(rv))
- goto _cleanup;
-
- rv = khc_remove_space(csp_module);
-
- _cleanup:
- if (csp_module)
- khc_close_space(csp_module);
-
- return rv;
-}
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ * Copyright (c) 2006 Secure Endpoints Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<kmminternal.h>
+
+KHMEXP khm_int32 KHMAPI
+kmm_get_module_info(wchar_t * module_name, khm_int32 flags,
+ kmm_module_info * buffer, khm_size * cb_buffer)
+{
+ /*TODO:Implement this */
+ return KHM_ERROR_NOT_IMPLEMENTED;
+}
+
+KHMEXP khm_int32 KHMAPI
+kmm_get_plugin_info(wchar_t * plugin_name,
+ kmm_plugin_info * buffer, khm_size * cb_buffer)
+{
+ /*TODO:Implement this */
+ return KHM_ERROR_NOT_IMPLEMENTED;
+}
+
+KHMEXP khm_int32 KHMAPI
+kmm_get_plugins_config(khm_int32 flags, khm_handle * result) {
+ khm_handle csp_root;
+ khm_handle csp_plugins;
+ khm_int32 rv;
+
+ rv = khc_open_space(KHM_INVALID_HANDLE, KMM_CSNAME_ROOT, flags, &csp_root);
+
+ if(KHM_FAILED(rv))
+ return rv;
+
+ rv = khc_open_space(csp_root, KMM_CSNAME_PLUGINS, flags, &csp_plugins);
+ khc_close_space(csp_root);
+
+ if(KHM_SUCCEEDED(rv))
+ *result = csp_plugins;
+ else
+ *result = NULL;
+
+ return rv;
+}
+
+
+KHMEXP khm_int32 KHMAPI
+kmm_get_modules_config(khm_int32 flags, khm_handle * result) {
+ khm_handle croot;
+ khm_handle kmm_all_modules;
+ khm_int32 rv;
+
+ rv = khc_open_space(NULL, KMM_CSNAME_ROOT, flags, &croot);
+
+ if(KHM_FAILED(rv))
+ return rv;
+
+ rv = khc_open_space(croot, KMM_CSNAME_MODULES, flags, &kmm_all_modules);
+ khc_close_space(croot);
+
+ if(KHM_SUCCEEDED(rv))
+ *result = kmm_all_modules;
+ else
+ *result = NULL;
+
+ return rv;
+}
+
+
+KHMEXP khm_int32 KHMAPI
+kmm_get_plugin_config(wchar_t * plugin, khm_int32 flags, khm_handle * result)
+{
+ khm_handle csplugins;
+ khm_handle csplugin;
+ khm_int32 rv;
+
+ if(!plugin || wcschr(plugin, L'/') || wcschr(plugin, L'\\'))
+ return KHM_ERROR_INVALID_PARAM;
+
+ if(KHM_FAILED(kmm_get_plugins_config(flags, &csplugins)))
+ return KHM_ERROR_UNKNOWN;
+
+ rv = khc_open_space(csplugins, plugin, flags, &csplugin);
+ *result = csplugin;
+
+ khc_close_space(csplugins);
+
+ return rv;
+}
+
+
+KHMEXP khm_int32 KHMAPI
+kmm_get_module_config(wchar_t * module, khm_int32 flags, khm_handle * result)
+{
+ khm_handle csmodules;
+ khm_handle csmodule;
+ khm_int32 rv;
+
+ if(!module || wcschr(module, L'/') || wcschr(module, L'\\'))
+ return KHM_ERROR_INVALID_PARAM;
+
+ if(KHM_FAILED(kmm_get_modules_config(flags, &csmodules)))
+ return KHM_ERROR_UNKNOWN;
+
+ rv = khc_open_space(csmodules, module, flags, &csmodule);
+ *result = csmodule;
+
+ khc_close_space(csmodules);
+
+ return rv;
+}
+
+KHMEXP khm_int32 KHMAPI
+kmm_register_plugin(kmm_plugin_reg * plugin, khm_int32 config_flags)
+{
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+ khm_handle csp_plugin = NULL;
+ khm_handle csp_module = NULL;
+ size_t cch;
+
+ /* avoid accidently creating the module key if it doesn't exist */
+ config_flags &= ~KHM_FLAG_CREATE;
+
+ if((plugin == NULL) ||
+ (plugin->dependencies &&
+ KHM_FAILED(multi_string_length_cch(plugin->dependencies,
+ KMM_MAXCCH_DEPS, &cch))) ||
+ FAILED(StringCchLength(plugin->module, KMM_MAXCCH_NAME, &cch)) ||
+ (plugin->description &&
+ FAILED(StringCchLength(plugin->description,
+ KMM_MAXCCH_DESC, &cch))) ||
+ FAILED(StringCchLength(plugin->name, KMM_MAXCCH_NAME, &cch)))
+ {
+ return KHM_ERROR_INVALID_PARAM;
+ }
+
+ /* note that we are retaining the length of the plugin name in
+ chars in cch */
+ cch ++;
+
+#define CKRV if(KHM_FAILED(rv)) goto _exit
+
+ rv = kmm_get_plugin_config(plugin->name,
+ config_flags | KHM_FLAG_CREATE, &csp_plugin);
+ CKRV;
+
+ /* should fail if the module key doesn't exist */
+ rv = kmm_get_module_config(plugin->module, config_flags, &csp_module);
+ CKRV;
+
+ /*TODO: Make sure that the module registration is in the same
+ config store as the one in which the plugin is going to be
+ registered */
+
+ rv = khc_write_string(csp_plugin, L"Module", plugin->module);
+ CKRV;
+ if(plugin->description) {
+ rv = khc_write_string(csp_plugin, L"Description", plugin->description);
+ CKRV;
+ }
+
+ if(plugin->dependencies) {
+ rv = khc_write_multi_string(csp_plugin, L"Dependencies",
+ plugin->dependencies);
+ CKRV;
+ }
+
+ rv = khc_write_int32(csp_plugin, L"Type", plugin->type);
+ CKRV;
+ rv = khc_write_int32(csp_plugin, L"Disabled",
+ !!(plugin->flags & KMM_PLUGIN_FLAG_DISABLED));
+ CKRV;
+
+ {
+ khm_size cb = 0;
+ wchar_t * pl = NULL;
+ size_t scb = 0;
+
+ rv = khc_read_multi_string(csp_module, L"PluginList", NULL, &cb);
+ if(rv != KHM_ERROR_TOO_LONG) {
+ if (rv == KHM_ERROR_NOT_FOUND) {
+
+ scb = cb = cch * sizeof(wchar_t);
+ pl = PMALLOC(cb);
+ multi_string_init(pl, cb);
+ rv = KHM_ERROR_SUCCESS;
+
+ goto add_plugin_to_list;
+
+ } else {
+ goto _exit;
+ }
+ }
+
+ cb += cch * sizeof(wchar_t);
+ scb = cb;
+
+ pl = PMALLOC(cb);
+
+ rv = khc_read_multi_string(csp_module, L"PluginList", pl, &cb);
+ if(KHM_FAILED(rv)) {
+ if(pl)
+ PFREE(pl);
+ goto _exit;
+ }
+
+ add_plugin_to_list:
+
+ if(!multi_string_find(pl, plugin->name, 0)) {
+ multi_string_append(pl, &scb, plugin->name);
+ rv = khc_write_multi_string(csp_module, L"PluginList", pl);
+ }
+
+ PFREE(pl);
+ CKRV;
+ }
+
+#undef CKRV
+
+_exit:
+ if(csp_plugin)
+ khc_close_space(csp_plugin);
+ if(csp_module)
+ khc_close_space(csp_module);
+
+ return rv;
+}
+
+KHMEXP khm_int32 KHMAPI
+kmm_register_module(kmm_module_reg * module, khm_int32 config_flags)
+{
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+ khm_handle csp_module = NULL;
+ size_t cch;
+ int i;
+
+ if((module == NULL) ||
+ FAILED(StringCchLength(module->name, KMM_MAXCCH_NAME, &cch)) ||
+ (module->description &&
+ FAILED(StringCchLength(module->description,
+ KMM_MAXCCH_DESC, &cch))) ||
+ FAILED(StringCchLength(module->path, MAX_PATH, &cch)) ||
+ (module->n_plugins > 0 && module->plugin_reg_info == NULL)) {
+ return KHM_ERROR_INVALID_PARAM;
+ }
+
+#define CKRV if(KHM_FAILED(rv)) goto _exit
+
+ rv = kmm_get_module_config(module->name, config_flags | KHM_FLAG_CREATE,
+ &csp_module);
+ CKRV;
+
+ rv = khc_write_string(csp_module, L"ImagePath", module->path);
+ CKRV;
+
+ rv = khc_write_int32(csp_module, L"Disabled", 0);
+ CKRV;
+
+ /* FileVersion and ProductVersion will be set when the module
+ is loaded for the first time */
+
+ for(i=0; i<module->n_plugins; i++) {
+ rv = kmm_register_plugin(&(module->plugin_reg_info[i]), config_flags);
+ CKRV;
+ }
+
+#undef CKRV
+_exit:
+ if(csp_module)
+ khc_close_space(csp_module);
+
+ return rv;
+}
+
+KHMEXP khm_int32 KHMAPI
+kmm_unregister_plugin(wchar_t * plugin, khm_int32 config_flags)
+{
+ khm_handle csp_plugin = NULL;
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+
+ rv = kmm_get_plugin_config(plugin, config_flags, &csp_plugin);
+
+ if (KHM_FAILED(rv))
+ goto _cleanup;
+
+ rv = khc_remove_space(csp_plugin);
+
+ _cleanup:
+
+ if (csp_plugin)
+ khc_close_space(csp_plugin);
+
+ return rv;
+}
+
+KHMEXP khm_int32 KHMAPI
+kmm_unregister_module(wchar_t * module, khm_int32 config_flags)
+{
+ khm_handle csp_module = NULL;
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+
+ rv = kmm_get_module_config(module, config_flags, &csp_module);
+
+ if (KHM_FAILED(rv))
+ goto _cleanup;
+
+ rv = khc_remove_space(csp_module);
+
+ _cleanup:
+ if (csp_module)
+ khc_close_space(csp_module);
+
+ return rv;
+}
diff --git a/src/windows/identity/kmm/kmm_registrar.c b/src/windows/identity/kmm/kmm_registrar.c
index 636e8579f6..0aa4b425f1 100644
--- a/src/windows/identity/kmm/kmm_registrar.c
+++ b/src/windows/identity/kmm/kmm_registrar.c
@@ -1,1038 +1,1038 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<kmminternal.h>
-#ifdef DEBUG
-#include<assert.h>
-#endif
-
-static LONG pending_modules = 0;
-static LONG pending_plugins = 0;
-static LONG startup_signal = 0;
-static BOOL load_done = FALSE;
-
-void
-kmmint_check_completion(void) {
- if (pending_modules == 0 &&
- pending_plugins == 0 &&
- InterlockedIncrement(&startup_signal) == 1) {
-
- load_done = TRUE;
-
- /* TODO: check for orphaned plugins */
-
- kmq_post_message(KMSG_KMM, KMSG_KMM_I_DONE, 0, 0);
- }
-}
-
-void
-kmmint_add_to_module_queue(void) {
- InterlockedIncrement(&pending_modules);
-}
-
-void
-kmmint_remove_from_module_queue(void) {
-
- InterlockedDecrement(&pending_modules);
-
- kmmint_check_completion();
-}
-
-void
-kmmint_add_to_plugin_queue(kmm_plugin_i * plugin) {
- EnterCriticalSection(&cs_kmm);
- if (!(plugin->flags & KMM_PLUGIN_FLAG_IN_QUEUE)) {
- InterlockedIncrement(&pending_plugins);
- plugin->flags |= KMM_PLUGIN_FLAG_IN_QUEUE;
- }
- LeaveCriticalSection(&cs_kmm);
-}
-
-void
-kmmint_remove_from_plugin_queue(kmm_plugin_i * plugin) {
- EnterCriticalSection(&cs_kmm);
-
- if (plugin->flags & KMM_PLUGIN_FLAG_IN_QUEUE) {
- InterlockedDecrement(&pending_plugins);
- plugin->flags &= ~KMM_PLUGIN_FLAG_IN_QUEUE;
- }
-
- LeaveCriticalSection(&cs_kmm);
- kmmint_check_completion();
-}
-
-KHMEXP khm_boolean KHMAPI
-kmm_load_pending(void) {
- return !load_done;
-}
-
-/*! \internal
- \brief Message handler for the registrar thread. */
-khm_boolean KHMAPI kmmint_reg_cb(khm_int32 msg_type,
- khm_int32 msg_sub_type,
- khm_ui_4 uparam,
- void *vparam)
-{
- /* we should only be getting <KMSG_KMM,KMSG_KMM_I_REG> anyway */
- if(msg_type != KMSG_KMM || msg_sub_type != KMSG_KMM_I_REG)
- return FALSE;
-
- switch(uparam) {
- case KMM_REG_INIT_MODULE:
- kmmint_init_module((kmm_module_i *) vparam);
- kmm_release_module(kmm_handle_from_module((kmm_module_i *) vparam));
- break;
-
- case KMM_REG_EXIT_MODULE:
- kmmint_exit_module((kmm_module_i *) vparam);
- kmm_release_module(kmm_handle_from_module((kmm_module_i *) vparam));
- break;
-
- case KMM_REG_INIT_PLUGIN:
- kmmint_init_plugin((kmm_plugin_i *) vparam);
- kmm_release_plugin(kmm_handle_from_plugin((kmm_plugin_i *) vparam));
- break;
-
- case KMM_REG_EXIT_PLUGIN:
- kmmint_exit_plugin((kmm_plugin_i *) vparam);
- kmm_release_plugin(kmm_handle_from_plugin((kmm_plugin_i *) vparam));
- break;
- }
- return TRUE;
-}
-
-/*! \internal
- \brief The registrar thread.
-
- The only thing this function does is to dispatch messages to the
- callback routine ( kmmint_reg_cb() ) */
-DWORD WINAPI kmmint_registrar(LPVOID lpParameter)
-{
-
- PDESCTHREAD(L"KMM Registrar", L"KMM");
-
- tid_registrar = GetCurrentThreadId();
-
- kmq_subscribe(KMSG_KMM, kmmint_reg_cb);
- kmq_subscribe(KMSG_SYSTEM, kmmint_reg_cb);
-
- SetEvent(evt_startup);
-
- while(KHM_SUCCEEDED(kmq_dispatch(INFINITE)));
-
- kmq_unsubscribe(KMSG_KMM, kmmint_reg_cb);
- kmq_unsubscribe(KMSG_SYSTEM, kmmint_reg_cb);
-
- ExitThread(0);
- /* not reached */
- return 0;
-}
-
-/*! \internal
- \brief Manages a plugin message thread.
-
- Each plugin gets its own plugin thread which is used to dispatch
- messages to the plugin. This acts as the thread function for the
- plugin thread.*/
-DWORD WINAPI kmmint_plugin_broker(LPVOID lpParameter)
-{
- DWORD rv = 0;
- kmm_plugin_i * p = (kmm_plugin_i *) lpParameter;
-
- PDESCTHREAD(p->p.name, L"KMM");
-
- _begin_task(0);
- _report_mr1(KHERR_NONE, MSG_PB_START, _cstr(p->p.name));
- _describe();
-
- TlsSetValue(tls_kmm, (LPVOID) p);
-
- kmm_hold_plugin(kmm_handle_from_plugin(p));
-
- p->tid_thread = GetCurrentThreadId();
-
- if (IsBadCodePtr(p->p.msg_proc)) {
- _report_mr0(KHERR_WARNING, MSG_PB_INVALID_CODE_PTR);
- rv = KHM_ERROR_INVALID_PARAM;
- } else {
- rv = (*p->p.msg_proc)(KMSG_SYSTEM, KMSG_SYSTEM_INIT,
- 0, (void *) &(p->p));
- _report_mr1(KHERR_INFO, MSG_PB_INIT_RV, _int32(rv));
- }
-
- /* if it fails to initialize, we exit the plugin */
- if(KHM_FAILED(rv)) {
-
- kherr_report(KHERR_ERROR,
- (wchar_t *) MSG_PB_INIT_FAIL_S,
- (wchar_t *) KHERR_FACILITY,
- NULL,
- (wchar_t *) MSG_PB_INIT_FAIL,
- (wchar_t *) MSG_PB_INIT_FAIL_G,
- KHERR_FACILITY_ID,
- KHERR_SUGGEST_NONE,
- _cstr(p->p.name),
- _cstr(p->p.description),
- _cstr(p->module->path),
- _cstr(p->module->support),
- KHERR_RF_MSG_SHORT_DESC |
- KHERR_RF_MSG_LONG_DESC |
- KHERR_RF_MSG_SUGGEST
-#ifdef _WIN32
- ,KHERR_HMODULE
-#endif
- );
- _resolve();
-
- /* exit the plugin first. Otherwise it may not uninitialize correctly */
- (*p->p.msg_proc)(KMSG_SYSTEM, KMSG_SYSTEM_EXIT, 0, (void *) &(p->p));
-
- kmmint_remove_from_plugin_queue(p);
- rv = 1;
- _end_task();
-
- p->state = KMM_PLUGIN_STATE_FAIL_INIT;
- goto _exit;
- }
-
- /* subscribe to default message classes by plugin type */
- if(p->p.type == KHM_PITYPE_CRED) {
- kmq_subscribe(KMSG_SYSTEM, p->p.msg_proc);
- kmq_subscribe(KMSG_KCDB, p->p.msg_proc);
- kmq_subscribe(KMSG_CRED, p->p.msg_proc);
- } else if(p->p.type == KHM_PITYPE_IDENT) {
- khm_handle h = NULL;
-
- kmq_subscribe(KMSG_SYSTEM, p->p.msg_proc);
- kmq_subscribe(KMSG_KCDB, p->p.msg_proc);
-
- kmq_create_subscription(p->p.msg_proc, &h);
- kcdb_identity_set_provider(h);
- /* kcdb deletes the subscription when it's done with it */
- } else if(p->p.type == KHM_PITYPE_CONFIG) {
- /*TODO: subscribe to configuration provider messages here */
- }
-
- p->state = KMM_PLUGIN_STATE_RUNNING;
-
- _report_mr0(KHERR_INFO, MSG_PB_INIT_DONE);
-
- _end_task();
-
- /* if there were any plugins that were waiting for this one to
- start, we should start them too */
- EnterCriticalSection(&cs_kmm);
- do {
- kmm_plugin_i * pd;
- int i;
-
- for(i=0; i < p->n_dependants; i++) {
- pd = p->dependants[i];
-
- pd->n_unresolved--;
-
- if(pd->n_unresolved == 0) {
- kmmint_add_to_plugin_queue(pd);
- kmm_hold_plugin(kmm_handle_from_plugin(pd));
- kmq_post_message(KMSG_KMM, KMSG_KMM_I_REG, KMM_REG_INIT_PLUGIN, (void *) pd);
- }
- }
- } while(FALSE);
- LeaveCriticalSection(&cs_kmm);
-
- kmmint_remove_from_plugin_queue(p);
-
- /* main message loop */
- while(KHM_SUCCEEDED(kmq_dispatch(INFINITE)));
-
- /* unsubscribe from default message classes by plugin type */
- if(p->p.type == KHM_PITYPE_CRED) {
- kmq_unsubscribe(KMSG_SYSTEM, p->p.msg_proc);
- kmq_unsubscribe(KMSG_KCDB, p->p.msg_proc);
- kmq_unsubscribe(KMSG_CRED, p->p.msg_proc);
- } else if (p->p.type == KHM_PITYPE_IDENT) {
- kmq_unsubscribe(KMSG_KCDB, p->p.msg_proc);
- kmq_unsubscribe(KMSG_SYSTEM, p->p.msg_proc);
- kcdb_identity_set_provider(NULL);
- } else if(p->p.type == KHM_PITYPE_CONFIG) {
- /*TODO: unsubscribe from configuration provider messages here */
- }
-
- p->p.msg_proc(KMSG_SYSTEM, KMSG_SYSTEM_EXIT, 0, (void *) &(p->p));
-
- _exit:
- if (p->state >= 0)
- p->state = KMM_PLUGIN_STATE_EXITED;
-
- /* the following call will automatically release the plugin */
- kmq_post_message(KMSG_KMM, KMSG_KMM_I_REG,
- KMM_REG_EXIT_PLUGIN, (void *) p);
-
- TlsSetValue(tls_kmm, (LPVOID) 0);
-
- ExitThread(rv);
-
- /* not reached */
- return rv;
-}
-
-/*! \internal
- \brief Initialize a plugin
-
- \note If kmmint_init_plugin() is called on a plugin, then kmmint_exit_plugin()
- \b must be called for the plugin.
-
- \note Should only be called from the context of the registrar thread */
-void kmmint_init_plugin(kmm_plugin_i * p) {
- DWORD dummy;
- khm_handle csp_plugin = NULL;
- khm_handle csp_plugins = NULL;
- khm_int32 t;
-
- /* the following will be undone in kmmint_exit_plugin() */
- kmm_hold_plugin(kmm_handle_from_plugin(p));
-
- EnterCriticalSection(&cs_kmm);
- if(p->state != KMM_PLUGIN_STATE_REG &&
- p->state != KMM_PLUGIN_STATE_HOLD)
- {
- LeaveCriticalSection(&cs_kmm);
- goto _exit;
- }
-
- _begin_task(0);
- _report_mr1(KHERR_NONE, MSG_IP_TASK_DESC, _cstr(p->p.name));
- _describe();
-
- if(p->state == KMM_PLUGIN_STATE_HOLD) {
- /* if this plugin was held, then we already had a hold
- from the initial attempt to start the plugin. Undo
- the hold we did a few lines earlier. */
- kmm_release_plugin(kmm_handle_from_plugin(p));
-
- /* same for the plugin count for the module. */
-#ifdef DEBUG
- assert(p->flags & KMM_PLUGIN_FLAG_IN_MODCOUNT);
-#endif
- p->module->plugin_count--;
- p->flags &= ~KMM_PLUGIN_FLAG_IN_MODCOUNT;
- }
-
- p->state = KMM_PLUGIN_STATE_PREINIT;
-
- kmmint_delist_plugin(p);
- kmmint_list_plugin(p);
-
- LeaveCriticalSection(&cs_kmm);
-
- if(KHM_FAILED(kmm_get_plugins_config(0, &csp_plugins))) {
- _report_mr0(KHERR_ERROR, MSG_IP_GET_CONFIG);
-
- p->state = KMM_PLUGIN_STATE_FAIL_UNKNOWN;
- goto _exit;
- }
-
- if(KHM_FAILED(kmm_get_plugin_config(p->p.name, 0, &csp_plugin))) {
- if(KHM_FAILED(kmm_register_plugin(&(p->p), 0))) {
- _report_mr0(KHERR_ERROR, MSG_IP_NOT_REGISTERED);
-
- p->state = KMM_PLUGIN_STATE_FAIL_NOT_REGISTERED;
- goto _exit;
- }
-
- if(KHM_FAILED(kmm_get_plugin_config(p->p.name, 0, &csp_plugin))) {
- _report_mr0(KHERR_ERROR, MSG_IP_NOT_REGISTERED);
-
- p->state = KMM_PLUGIN_STATE_FAIL_NOT_REGISTERED;
- goto _exit;
- }
- }
-
- if (KHM_SUCCEEDED(khc_read_int32(csp_plugin, L"Disabled", &t)) && t) {
- p->flags |= KMM_PLUGIN_FLAG_DISABLED;
- p->state = KMM_PLUGIN_STATE_FAIL_DISABLED;
- goto _exit;
- }
-
-#if 0
- /*TODO: check the failure count and act accordingly */
- if(KHM_SUCCEEDED(khc_read_int32(csp_plugin, L"FailureCount", &t)) && (t > 0)) {
- }
-#endif
-
- EnterCriticalSection(&cs_kmm);
-
- p->n_depends = 0;
- p->n_unresolved = 0;
-
- do {
- wchar_t * deps = NULL;
- wchar_t * d;
- khm_size sz = 0;
-
- if(khc_read_multi_string(csp_plugin, L"Dependencies",
- NULL, &sz) != KHM_ERROR_TOO_LONG)
- break;
-
- deps = PMALLOC(sz);
- if(KHM_FAILED(khc_read_multi_string(csp_plugin, L"Dependencies",
- deps, &sz))) {
- if(deps)
- PFREE(deps);
- break;
- }
-
- for(d = deps; d && *d; d = multi_string_next(d)) {
- kmm_plugin_i * pd;
- int i;
-
- pd = kmmint_get_plugin_i(d);
-
- if(pd->state == KMM_PLUGIN_STATE_NONE) {
- /* the dependant was not previously known */
- pd->state = KMM_PLUGIN_STATE_PLACEHOLDER;
- }
-
- for(i=0; i < pd->n_dependants; i++) {
- if(pd->dependants[i] == p)
- break;
- }
-
- if(i >= pd->n_dependants) {
- if( pd->n_dependants >= KMM_MAX_DEPENDANTS ) {
- /*TODO: handle this gracefully */
- RaiseException(1, EXCEPTION_NONCONTINUABLE, 0, NULL);
- }
-
- /* released in kmmint_free_plugin() */
- kmm_hold_plugin(kmm_handle_from_plugin(p));
- pd->dependants[pd->n_dependants] = p;
- pd->n_dependants++;
- }
-
- p->n_depends++;
-
- if(pd->state != KMM_PLUGIN_STATE_RUNNING) {
- p->n_unresolved++;
- }
- }
-
- if(p->n_unresolved > 0) {
- p->state = KMM_PLUGIN_STATE_HOLD;
- }
-
- PFREE(deps);
-
- } while(FALSE);
-
-#ifdef DEBUG
- assert(!(p->flags & KMM_PLUGIN_FLAG_IN_MODCOUNT));
-#endif
- p->flags |= KMM_PLUGIN_FLAG_IN_MODCOUNT;
- p->module->plugin_count++;
-
- LeaveCriticalSection(&cs_kmm);
-
- if(p->state == KMM_PLUGIN_STATE_HOLD) {
- _report_mr1(KHERR_INFO, MSG_IP_HOLD, _dupstr(p->p.name));
-
- goto _exit_post;
- }
-
- kmmint_add_to_plugin_queue(p);
-
- p->ht_thread = CreateThread(NULL,
- 0,
- kmmint_plugin_broker,
- (LPVOID) p,
- CREATE_SUSPENDED,
- &dummy);
-
- p->state = KMM_PLUGIN_STATE_INIT;
-
- ResumeThread(p->ht_thread);
-
-_exit_post:
- if(csp_plugin != NULL)
- khc_close_space(csp_plugin);
-
- if(csp_plugins != NULL)
- khc_close_space(csp_plugins);
-
- _report_mr2(KHERR_INFO, MSG_IP_STATE,
- _dupstr(p->p.name), _int32(p->state));
-
- _end_task();
-
- return;
-
- /* jump here if an error condition happens before the plugin
- broker thread starts and the plugin should be unloaded */
-
-_exit:
- if(csp_plugin != NULL)
- khc_close_space(csp_plugin);
- if(csp_plugins != NULL)
- khc_close_space(csp_plugins);
-
- _report_mr2(KHERR_WARNING, MSG_IP_EXITING,
- _dupstr(p->p.name), _int32(p->state));
- _end_task();
-
-
-#ifdef ASYNC_PLUGIN_UNLOAD_ON_FAILURE
-
- kmm_hold_plugin(kmm_handle_from_plugin(p));
-
- kmq_post_message(KMSG_KMM, KMSG_KMM_I_REG, KMM_REG_EXIT_PLUGIN, (void *) p);
-
-#else
-
- kmmint_exit_plugin(p);
-
-#endif
-}
-
-/*! \internal
- \brief Uninitialize a plugin
-
- In addition to terminating the thread, and removing p from the
- linked list and hashtable, it also frees up p.
-
- \note Should only be called from the context of the registrar thread. */
-void kmmint_exit_plugin(kmm_plugin_i * p) {
- int np;
- khm_boolean release_plugin = TRUE;
-
- if(p->state == KMM_PLUGIN_STATE_RUNNING ||
- p->state == KMM_PLUGIN_STATE_INIT) {
-
- kmq_post_thread_quit_message(p->tid_thread, 0, NULL);
- /* when we post the quit message to the plugin thread, the plugin
- broker terminates the plugin and posts a EXIT_PLUGIN message,
- which calls this function again. We just exit here because
- the EXIT_PLUGIN message will end up calling us again momentarily */
- return;
-
- }
-
- if(p->ht_thread) {
- /* wait for the thread to terminate */
- WaitForSingleObject(p->ht_thread, INFINITE);
- p->ht_thread = NULL;
- }
-
- EnterCriticalSection(&cs_kmm);
-
- /* undo reference count done in kmmint_init_plugin() */
- if(p->flags & KMM_PLUGIN_FLAG_IN_MODCOUNT) {
-
- np = --(p->module->plugin_count);
- p->flags &= ~KMM_PLUGIN_FLAG_IN_MODCOUNT;
-
- } else {
- /* the plugin was not included in the module's plugin_count.
- We can't base a decision to unload the module based on this
- plugin exiting. */
- np = TRUE;
- }
-
- /* The plugin is in an error state. We need to keep the plugin
- record in tact so that the failure information is kept
- around. */
- if (p->state < KMM_PLUGIN_STATE_NONE) {
- release_plugin = FALSE;
- }
-
- LeaveCriticalSection(&cs_kmm);
-
- if(!np) {
- /* if this is the last plugin to exit, then notify the
- registrar that the module should be removed as well */
- kmm_hold_module(kmm_handle_from_module(p->module));
- kmq_post_message(KMSG_KMM, KMSG_KMM_I_REG, KMM_REG_EXIT_MODULE, (void *) p->module);
- }
-
- /* release the hold obtained in kmmint_init_plugin() */
- if (release_plugin)
- kmm_release_plugin(kmm_handle_from_plugin(p));
-}
-
-/*! \internal
- \brief Initialize a module
-
- \a m is not in the linked list yet.
-
- \note Should only be called from the context of the registrar thread. */
-void kmmint_init_module(kmm_module_i * m) {
- HMODULE hm;
- init_module_t p_init_module;
- kmm_plugin_i * pi;
- khm_int32 rv;
- khm_handle csp_mod = NULL;
- khm_handle csp_mods = NULL;
- khm_size sz;
- khm_int32 i;
-
- /* error condition handling */
- BOOL exit_module = FALSE;
- BOOL release_module = TRUE;
- BOOL record_failure = FALSE;
-
- /* failure handling */
- khm_int32 max_fail_count = 0;
- khm_int64 fail_reset_time = 0;
-
- _begin_task(0);
- _report_mr1(KHERR_NONE, MSG_INIT_MODULE, _cstr(m->name));
- _describe();
-
- kmm_hold_module(kmm_handle_from_module(m));
-
- if(KHM_FAILED(kmm_get_modules_config(0, &csp_mods))) {
- _report_mr0(KHERR_ERROR, MSG_IM_GET_CONFIG);
- _location(L"kmm_get_modules_config()");
-
- m->state = KMM_MODULE_STATE_FAIL_UNKNOWN;
- goto _exit;
- }
-
- khc_read_int32(csp_mods, L"ModuleMaxFailureCount", &max_fail_count);
- khc_read_int64(csp_mods, L"ModuleFailureCountResetTime", &fail_reset_time);
-
- /* If the module is not in the pre-init state, we can't
- initialize it. */
- if(m->state != KMM_MODULE_STATE_PREINIT) {
- _report_mr1(KHERR_INFO, MSG_IM_NOT_PREINIT, _int32(m->state));
- goto _exit;
- }
-
- if(KHM_FAILED(kmm_get_module_config(m->name, 0, &csp_mod))) {
- _report_mr0(KHERR_ERROR, MSG_IM_NOT_REGISTERED);
-
- m->state = KMM_MODULE_STATE_FAIL_NOT_REGISTERED;
- goto _exit;
- }
-
- if(KHM_SUCCEEDED(khc_read_int32(csp_mod, L"Disabled", &i)) && i) {
- _report_mr0(KHERR_INFO, MSG_IM_DISABLED);
-
- m->state = KMM_MODULE_STATE_FAIL_DISABLED;
- goto _exit;
- }
-
- if(KHM_SUCCEEDED(khc_read_int32(csp_mod, L"NoUnload", &i)) && i) {
- m->flags |= KMM_MODULE_FLAG_NOUNLOAD;
- }
-
- if(KHM_SUCCEEDED(khc_read_int32(csp_mod, L"FailureCount", &i))) {
- khm_int64 tm;
- khm_int64 ct;
- FILETIME fct;
- khm_int32 last_reason = 0;
-
- /* reset the failure count if the failure count reset time
- period has elapsed */
- tm = 0;
- khc_read_int64(csp_mod, L"FailureTime", &tm);
- GetSystemTimeAsFileTime(&fct);
-
- ct = (FtToInt(&fct) - tm) / 10000000i64;
-
- if(tm > 0 &&
- ct > fail_reset_time) {
- i = 0;
- khc_write_int32(csp_mod, L"FailureCount", 0);
- khc_write_int64(csp_mod, L"FailureTime", 0);
- }
-
- khc_read_int32(csp_mod, L"FailureReason", &last_reason);
-
- /* did we exceed the max failure count? However, we ignore
- the max failure count if the reason why it didn't load the
- last time was because the module wasn't found. */
- if(i > max_fail_count &&
- last_reason != KMM_MODULE_STATE_FAIL_NOT_FOUND) {
- /* failed too many times */
- _report_mr0(KHERR_INFO, MSG_IM_MAX_FAIL);
-
- m->state = KMM_MODULE_STATE_FAIL_MAX_FAILURE;
- goto _exit;
- }
- }
-
- if(khc_read_string(csp_mod, L"ImagePath", NULL, &sz) ==
- KHM_ERROR_TOO_LONG) {
- if(m->path)
- PFREE(m->path);
- m->path = PMALLOC(sz);
- khc_read_string(csp_mod, L"ImagePath", m->path, &sz);
- } else {
- _report_mr0(KHERR_ERROR, MSG_IM_NOT_REGISTERED);
-
- m->state = KMM_MODULE_STATE_FAIL_NOT_REGISTERED;
- goto _exit;
- }
-
- rv = kmmint_read_module_info(m);
-
- if (KHM_FAILED(rv)) {
- if (rv == KHM_ERROR_INCOMPATIBLE) {
- _report_mr0(KHERR_ERROR, MSG_IM_INCOMPATIBLE);
-
- m->state = KMM_MODULE_STATE_FAIL_INCOMPAT;
- } else if (rv == KHM_ERROR_NOT_FOUND) {
- _report_mr1(KHERR_ERROR, MSG_IM_NOT_FOUND, _dupstr(m->path));
-
- m->state = KMM_MODULE_STATE_FAIL_NOT_FOUND;
- } else {
- _report_mr0(KHERR_ERROR, MSG_IM_INVALID_MODULE);
-
- m->state = KMM_MODULE_STATE_FAIL_INV_MODULE;
- }
- goto _exit;
- }
-
- /* check again */
- if(m->state != KMM_MODULE_STATE_PREINIT) {
- _report_mr0(KHERR_ERROR, MSG_IM_NOT_PREINIT);
-
- goto _exit;
- }
-
- /* from this point on, we must record any failure codes */
- record_failure = TRUE;
-
- hm = LoadLibrary(m->path);
- if(!hm) {
- m->h_module = NULL;
- m->state = KMM_MODULE_STATE_FAIL_NOT_FOUND;
-
- _report_mr1(KHERR_ERROR, MSG_IM_NOT_FOUND, _dupstr(m->path));
-
- goto _exit;
- }
-
- /* from this point on, we need to discard the module through
- exit_module */
- ResetEvent(evt_exit);
-
- kmm_active_modules++;
-
- release_module = FALSE;
- exit_module = TRUE;
-
- m->flags |= KMM_MODULE_FLAG_LOADED;
- m->h_module = hm;
-
- /* TODO: check signatures */
-
- p_init_module = (init_module_t) GetProcAddress(hm, EXP_INIT_MODULE);
-
- if(!p_init_module) {
- _report_mr1(KHERR_ERROR, MSG_IM_NO_ENTRY, _cstr(EXP_INIT_MODULE));
-
- m->state = KMM_MODULE_STATE_FAIL_INVALID;
- goto _exit;
- }
-
- m->state = KMM_MODULE_STATE_INIT;
-
- /* call init_module() */
- rv = (*p_init_module)(kmm_handle_from_module(m));
-
- m->flags |= KMM_MODULE_FLAG_INITP;
-
- if(KHM_FAILED(rv)) {
- _report_mr1(KHERR_ERROR, MSG_IM_INIT_FAIL, _int32(rv));
-
- m->state = KMM_MODULE_STATE_FAIL_LOAD;
- goto _exit;
- }
-
- if(!m->plugins) {
- _report_mr0(KHERR_ERROR, MSG_IM_NO_PLUGINS);
-
- m->state = KMM_MODULE_STATE_FAIL_NO_PLUGINS;
- record_failure = FALSE;
- goto _exit;
- }
-
- m->state = KMM_MODULE_STATE_INITPLUG;
-
- do {
- LPOP(&(m->plugins), &pi);
- if(pi) {
- pi->flags &= ~KMM_PLUGIN_FLAG_IN_MODLIST;
- kmmint_init_plugin(pi);
-
- /* release the hold obtained in kmm_provide_plugin() */
- kmm_release_plugin(kmm_handle_from_plugin(pi));
- }
- } while(pi);
-
- if(!m->plugin_count) {
- /* We don't want to report this case. This usually means that
- the plugins that were provided by the module were
- disabled. */
-#ifdef REPORT_EMPTY_MODULES
- _report_mr0(KHERR_ERROR, MSG_IM_NO_PLUGINS);
-
- m->state = KMM_MODULE_STATE_FAIL_NO_PLUGINS;
-#endif
- record_failure = FALSE;
- goto _exit;
- }
-
- m->state = KMM_MODULE_STATE_RUNNING;
-
- exit_module = FALSE;
- record_failure = FALSE;
-
- _exit:
- if(csp_mod) {
- if(record_failure) {
- FILETIME fct;
-
- i = 0;
- khc_read_int32(csp_mod, L"FailureCount", &i);
- i++;
- khc_write_int32(csp_mod, L"FailureCount", i);
-
- if(i==1) { /* first fault */
- GetSystemTimeAsFileTime(&fct);
- khc_write_int64(csp_mod, L"FailureTime", FtToInt(&fct));
- }
-
- khc_write_int32(csp_mod, L"FailureReason", m->state);
- }
- khc_close_space(csp_mod);
- }
-
- if(csp_mods)
- khc_close_space(csp_mods);
-
- _report_mr2(KHERR_INFO, MSG_IM_MOD_STATE,
- _dupstr(m->name), _int32(m->state));
-
- kmmint_remove_from_module_queue();
-
- /* if something went wrong after init_module was called on the
- module code, we need to call exit_module */
- if(exit_module)
- kmmint_exit_module(m);
-
- if(release_module)
- kmm_release_module(kmm_handle_from_module(m));
-
- if (kherr_is_error()) {
- kherr_context * c;
- kherr_event * err_e = NULL;
- kherr_event * warn_e = NULL;
- kherr_event * e;
-
- c = kherr_peek_context();
- err_e = kherr_get_err_event(c);
- for(e = kherr_get_first_event(c);
- e;
- e = kherr_get_next_event(e)) {
- if (e != err_e &&
- e->severity == KHERR_WARNING) {
- warn_e = e;
- break;
- }
- }
-
- kherr_evaluate_event(err_e);
- if (warn_e)
- kherr_evaluate_event(warn_e);
-
- kherr_clear_error();
-
- e = kherr_report(KHERR_ERROR,
- (wchar_t *) MSG_IMERR_TITLE,
- KHERR_FACILITY,
- NULL,
- err_e->long_desc,
- ((warn_e)? (wchar_t *)MSG_IMERR_SUGGEST: NULL),
- KHERR_FACILITY_ID,
- KHERR_SUGGEST_NONE,
- _cstr(m->name),
- ((warn_e)? _cstr(warn_e->long_desc):_vnull()),
- _vnull(),_vnull(),
- KHERR_RF_MSG_SHORT_DESC |
- ((warn_e)? KHERR_RF_MSG_SUGGEST: 0),
- KHERR_HMODULE);
-
- kherr_evaluate_event(e);
-
- kherr_release_context(c);
- }
-
- _end_task();
-}
-
-
-/*! \internal
- \brief Uninitializes a module
-
- \note Should only be called from the context of the registrar
- thread */
-void kmmint_exit_module(kmm_module_i * m) {
- kmm_plugin_i * p;
-
- /* Exiting a module happens in two stages.
-
- If the module state is running (there are active plugins) then
- those plugins must be exited. This has to be done from the
- plugin threads. The signal for the plugins to exit must be
- issued from the registrar. Therefore, we post messages to the
- registrar for each plugin we want to remove and exit
- kmmint_exit_module().
-
- When the last plugin is exited, the plugin management code
- automatically signalls the registrar to remove the module.
- kmmint_exit_module() gets called again. This is the second
- stage, where we call exit_module() for the module and start
- unloading everything.
- */
-
- EnterCriticalSection(&cs_kmm);
-
- /* get rid of any dangling uninitialized plugins */
- LPOP(&(m->plugins), &p);
- while(p) {
- p->flags &= ~KMM_PLUGIN_FLAG_IN_MODLIST;
- kmmint_exit_plugin(p);
-
- /* release hold from kmm_provide_plugin() */
- kmm_release_plugin(kmm_handle_from_plugin(p));
-
- LPOP(&(m->plugins), &p);
- }
-
- if(m->state == KMM_MODULE_STATE_RUNNING) {
- int np = 0;
-
- m->state = KMM_MODULE_STATE_EXITPLUG;
-
- p = kmm_listed_plugins;
-
- while(p) {
- if(p->module == m &&
- (p->flags & KMM_PLUGIN_FLAG_IN_MODCOUNT)) {
-
- kmm_hold_plugin(kmm_handle_from_plugin(p));
- kmq_post_message(KMSG_KMM, KMSG_KMM_I_REG,
- KMM_REG_EXIT_PLUGIN, (void *) p);
- np++;
-
- }
-
- p = LNEXT(p);
- }
-
-#ifdef DEBUG
- assert(np == m->plugin_count);
-#endif
-
- if(np > 0) {
- /* we have to go back and wait for the plugins to exit.
- when the last plugin exits, it automatically posts
- EXIT_MODULE. We can pick up from there when this
- happens. */
- LeaveCriticalSection(&cs_kmm);
- return;
- }
-
- } else {
-
-#ifdef DEBUG
- assert(m->plugin_count == 0 ||
- m->state == KMM_MODULE_STATE_EXITPLUG);
-#endif
-
- /* if there are still plug-ins waiting to be unloaded, then we
- have to go back and wait for them to finish. Once they are
- done, kmmint_exit_module() will get called again. */
- if (m->plugin_count > 0) {
- LeaveCriticalSection(&cs_kmm);
- return;
- }
- }
-
- if(m->flags & KMM_MODULE_FLAG_INITP) {
- exit_module_t p_exit_module;
-
- if(m->state > 0)
- m->state = KMM_MODULE_STATE_EXIT;
-
- p_exit_module =
- (exit_module_t) GetProcAddress(m->h_module,
- EXP_EXIT_MODULE);
- if(p_exit_module) {
- LeaveCriticalSection(&cs_kmm);
- (*p_exit_module)(kmm_handle_from_module(m));
- EnterCriticalSection(&cs_kmm);
- }
- }
-
- if(m->state > 0)
- m->state = KMM_MODULE_STATE_EXITED;
-
- LeaveCriticalSection(&cs_kmm);
-
- if(!(m->flags & KMM_MODULE_FLAG_NOUNLOAD) &&
- m->h_module) {
- FreeLibrary(m->h_module);
- }
-
- if(!(m->flags & KMM_MODULE_FLAG_NOUNLOAD) &&
- m->h_resource && (m->h_resource != m->h_module)) {
- FreeLibrary(m->h_resource);
- }
-
- m->h_module = NULL;
- m->h_resource = NULL;
-
- if (m->flags & KMM_MODULE_FLAG_LOADED) {
-#ifdef DEBUG
- assert(kmm_active_modules > 0);
-#endif
- kmm_active_modules--;
- }
-
- m->flags = 0;
-
- /* release the hold obtained in kmmint_init_module() */
- kmm_release_module(kmm_handle_from_module(m));
-
- /* Last but not least, now see if there are any modules left that
- are running. If not, we can safely signal an exit. */
- if (kmm_active_modules == 0) {
- SetEvent(evt_exit);
- }
-}
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<kmminternal.h>
+#ifdef DEBUG
+#include<assert.h>
+#endif
+
+static LONG pending_modules = 0;
+static LONG pending_plugins = 0;
+static LONG startup_signal = 0;
+static BOOL load_done = FALSE;
+
+void
+kmmint_check_completion(void) {
+ if (pending_modules == 0 &&
+ pending_plugins == 0 &&
+ InterlockedIncrement(&startup_signal) == 1) {
+
+ load_done = TRUE;
+
+ /* TODO: check for orphaned plugins */
+
+ kmq_post_message(KMSG_KMM, KMSG_KMM_I_DONE, 0, 0);
+ }
+}
+
+void
+kmmint_add_to_module_queue(void) {
+ InterlockedIncrement(&pending_modules);
+}
+
+void
+kmmint_remove_from_module_queue(void) {
+
+ InterlockedDecrement(&pending_modules);
+
+ kmmint_check_completion();
+}
+
+void
+kmmint_add_to_plugin_queue(kmm_plugin_i * plugin) {
+ EnterCriticalSection(&cs_kmm);
+ if (!(plugin->flags & KMM_PLUGIN_FLAG_IN_QUEUE)) {
+ InterlockedIncrement(&pending_plugins);
+ plugin->flags |= KMM_PLUGIN_FLAG_IN_QUEUE;
+ }
+ LeaveCriticalSection(&cs_kmm);
+}
+
+void
+kmmint_remove_from_plugin_queue(kmm_plugin_i * plugin) {
+ EnterCriticalSection(&cs_kmm);
+
+ if (plugin->flags & KMM_PLUGIN_FLAG_IN_QUEUE) {
+ InterlockedDecrement(&pending_plugins);
+ plugin->flags &= ~KMM_PLUGIN_FLAG_IN_QUEUE;
+ }
+
+ LeaveCriticalSection(&cs_kmm);
+ kmmint_check_completion();
+}
+
+KHMEXP khm_boolean KHMAPI
+kmm_load_pending(void) {
+ return !load_done;
+}
+
+/*! \internal
+ \brief Message handler for the registrar thread. */
+khm_boolean KHMAPI kmmint_reg_cb(khm_int32 msg_type,
+ khm_int32 msg_sub_type,
+ khm_ui_4 uparam,
+ void *vparam)
+{
+ /* we should only be getting <KMSG_KMM,KMSG_KMM_I_REG> anyway */
+ if(msg_type != KMSG_KMM || msg_sub_type != KMSG_KMM_I_REG)
+ return FALSE;
+
+ switch(uparam) {
+ case KMM_REG_INIT_MODULE:
+ kmmint_init_module((kmm_module_i *) vparam);
+ kmm_release_module(kmm_handle_from_module((kmm_module_i *) vparam));
+ break;
+
+ case KMM_REG_EXIT_MODULE:
+ kmmint_exit_module((kmm_module_i *) vparam);
+ kmm_release_module(kmm_handle_from_module((kmm_module_i *) vparam));
+ break;
+
+ case KMM_REG_INIT_PLUGIN:
+ kmmint_init_plugin((kmm_plugin_i *) vparam);
+ kmm_release_plugin(kmm_handle_from_plugin((kmm_plugin_i *) vparam));
+ break;
+
+ case KMM_REG_EXIT_PLUGIN:
+ kmmint_exit_plugin((kmm_plugin_i *) vparam);
+ kmm_release_plugin(kmm_handle_from_plugin((kmm_plugin_i *) vparam));
+ break;
+ }
+ return TRUE;
+}
+
+/*! \internal
+ \brief The registrar thread.
+
+ The only thing this function does is to dispatch messages to the
+ callback routine ( kmmint_reg_cb() ) */
+DWORD WINAPI kmmint_registrar(LPVOID lpParameter)
+{
+
+ PDESCTHREAD(L"KMM Registrar", L"KMM");
+
+ tid_registrar = GetCurrentThreadId();
+
+ kmq_subscribe(KMSG_KMM, kmmint_reg_cb);
+ kmq_subscribe(KMSG_SYSTEM, kmmint_reg_cb);
+
+ SetEvent(evt_startup);
+
+ while(KHM_SUCCEEDED(kmq_dispatch(INFINITE)));
+
+ kmq_unsubscribe(KMSG_KMM, kmmint_reg_cb);
+ kmq_unsubscribe(KMSG_SYSTEM, kmmint_reg_cb);
+
+ ExitThread(0);
+ /* not reached */
+ return 0;
+}
+
+/*! \internal
+ \brief Manages a plugin message thread.
+
+ Each plugin gets its own plugin thread which is used to dispatch
+ messages to the plugin. This acts as the thread function for the
+ plugin thread.*/
+DWORD WINAPI kmmint_plugin_broker(LPVOID lpParameter)
+{
+ DWORD rv = 0;
+ kmm_plugin_i * p = (kmm_plugin_i *) lpParameter;
+
+ PDESCTHREAD(p->p.name, L"KMM");
+
+ _begin_task(0);
+ _report_mr1(KHERR_NONE, MSG_PB_START, _cstr(p->p.name));
+ _describe();
+
+ TlsSetValue(tls_kmm, (LPVOID) p);
+
+ kmm_hold_plugin(kmm_handle_from_plugin(p));
+
+ p->tid_thread = GetCurrentThreadId();
+
+ if (IsBadCodePtr(p->p.msg_proc)) {
+ _report_mr0(KHERR_WARNING, MSG_PB_INVALID_CODE_PTR);
+ rv = KHM_ERROR_INVALID_PARAM;
+ } else {
+ rv = (*p->p.msg_proc)(KMSG_SYSTEM, KMSG_SYSTEM_INIT,
+ 0, (void *) &(p->p));
+ _report_mr1(KHERR_INFO, MSG_PB_INIT_RV, _int32(rv));
+ }
+
+ /* if it fails to initialize, we exit the plugin */
+ if(KHM_FAILED(rv)) {
+
+ kherr_report(KHERR_ERROR,
+ (wchar_t *) MSG_PB_INIT_FAIL_S,
+ (wchar_t *) KHERR_FACILITY,
+ NULL,
+ (wchar_t *) MSG_PB_INIT_FAIL,
+ (wchar_t *) MSG_PB_INIT_FAIL_G,
+ KHERR_FACILITY_ID,
+ KHERR_SUGGEST_NONE,
+ _cstr(p->p.name),
+ _cstr(p->p.description),
+ _cstr(p->module->path),
+ _cstr(p->module->support),
+ KHERR_RF_MSG_SHORT_DESC |
+ KHERR_RF_MSG_LONG_DESC |
+ KHERR_RF_MSG_SUGGEST
+#ifdef _WIN32
+ ,KHERR_HMODULE
+#endif
+ );
+ _resolve();
+
+ /* exit the plugin first. Otherwise it may not uninitialize correctly */
+ (*p->p.msg_proc)(KMSG_SYSTEM, KMSG_SYSTEM_EXIT, 0, (void *) &(p->p));
+
+ kmmint_remove_from_plugin_queue(p);
+ rv = 1;
+ _end_task();
+
+ p->state = KMM_PLUGIN_STATE_FAIL_INIT;
+ goto _exit;
+ }
+
+ /* subscribe to default message classes by plugin type */
+ if(p->p.type == KHM_PITYPE_CRED) {
+ kmq_subscribe(KMSG_SYSTEM, p->p.msg_proc);
+ kmq_subscribe(KMSG_KCDB, p->p.msg_proc);
+ kmq_subscribe(KMSG_CRED, p->p.msg_proc);
+ } else if(p->p.type == KHM_PITYPE_IDENT) {
+ khm_handle h = NULL;
+
+ kmq_subscribe(KMSG_SYSTEM, p->p.msg_proc);
+ kmq_subscribe(KMSG_KCDB, p->p.msg_proc);
+
+ kmq_create_subscription(p->p.msg_proc, &h);
+ kcdb_identity_set_provider(h);
+ /* kcdb deletes the subscription when it's done with it */
+ } else if(p->p.type == KHM_PITYPE_CONFIG) {
+ /*TODO: subscribe to configuration provider messages here */
+ }
+
+ p->state = KMM_PLUGIN_STATE_RUNNING;
+
+ _report_mr0(KHERR_INFO, MSG_PB_INIT_DONE);
+
+ _end_task();
+
+ /* if there were any plugins that were waiting for this one to
+ start, we should start them too */
+ EnterCriticalSection(&cs_kmm);
+ do {
+ kmm_plugin_i * pd;
+ int i;
+
+ for(i=0; i < p->n_dependants; i++) {
+ pd = p->dependants[i];
+
+ pd->n_unresolved--;
+
+ if(pd->n_unresolved == 0) {
+ kmmint_add_to_plugin_queue(pd);
+ kmm_hold_plugin(kmm_handle_from_plugin(pd));
+ kmq_post_message(KMSG_KMM, KMSG_KMM_I_REG, KMM_REG_INIT_PLUGIN, (void *) pd);
+ }
+ }
+ } while(FALSE);
+ LeaveCriticalSection(&cs_kmm);
+
+ kmmint_remove_from_plugin_queue(p);
+
+ /* main message loop */
+ while(KHM_SUCCEEDED(kmq_dispatch(INFINITE)));
+
+ /* unsubscribe from default message classes by plugin type */
+ if(p->p.type == KHM_PITYPE_CRED) {
+ kmq_unsubscribe(KMSG_SYSTEM, p->p.msg_proc);
+ kmq_unsubscribe(KMSG_KCDB, p->p.msg_proc);
+ kmq_unsubscribe(KMSG_CRED, p->p.msg_proc);
+ } else if (p->p.type == KHM_PITYPE_IDENT) {
+ kmq_unsubscribe(KMSG_KCDB, p->p.msg_proc);
+ kmq_unsubscribe(KMSG_SYSTEM, p->p.msg_proc);
+ kcdb_identity_set_provider(NULL);
+ } else if(p->p.type == KHM_PITYPE_CONFIG) {
+ /*TODO: unsubscribe from configuration provider messages here */
+ }
+
+ p->p.msg_proc(KMSG_SYSTEM, KMSG_SYSTEM_EXIT, 0, (void *) &(p->p));
+
+ _exit:
+ if (p->state >= 0)
+ p->state = KMM_PLUGIN_STATE_EXITED;
+
+ /* the following call will automatically release the plugin */
+ kmq_post_message(KMSG_KMM, KMSG_KMM_I_REG,
+ KMM_REG_EXIT_PLUGIN, (void *) p);
+
+ TlsSetValue(tls_kmm, (LPVOID) 0);
+
+ ExitThread(rv);
+
+ /* not reached */
+ return rv;
+}
+
+/*! \internal
+ \brief Initialize a plugin
+
+ \note If kmmint_init_plugin() is called on a plugin, then kmmint_exit_plugin()
+ \b must be called for the plugin.
+
+ \note Should only be called from the context of the registrar thread */
+void kmmint_init_plugin(kmm_plugin_i * p) {
+ DWORD dummy;
+ khm_handle csp_plugin = NULL;
+ khm_handle csp_plugins = NULL;
+ khm_int32 t;
+
+ /* the following will be undone in kmmint_exit_plugin() */
+ kmm_hold_plugin(kmm_handle_from_plugin(p));
+
+ EnterCriticalSection(&cs_kmm);
+ if(p->state != KMM_PLUGIN_STATE_REG &&
+ p->state != KMM_PLUGIN_STATE_HOLD)
+ {
+ LeaveCriticalSection(&cs_kmm);
+ goto _exit;
+ }
+
+ _begin_task(0);
+ _report_mr1(KHERR_NONE, MSG_IP_TASK_DESC, _cstr(p->p.name));
+ _describe();
+
+ if(p->state == KMM_PLUGIN_STATE_HOLD) {
+ /* if this plugin was held, then we already had a hold
+ from the initial attempt to start the plugin. Undo
+ the hold we did a few lines earlier. */
+ kmm_release_plugin(kmm_handle_from_plugin(p));
+
+ /* same for the plugin count for the module. */
+#ifdef DEBUG
+ assert(p->flags & KMM_PLUGIN_FLAG_IN_MODCOUNT);
+#endif
+ p->module->plugin_count--;
+ p->flags &= ~KMM_PLUGIN_FLAG_IN_MODCOUNT;
+ }
+
+ p->state = KMM_PLUGIN_STATE_PREINIT;
+
+ kmmint_delist_plugin(p);
+ kmmint_list_plugin(p);
+
+ LeaveCriticalSection(&cs_kmm);
+
+ if(KHM_FAILED(kmm_get_plugins_config(0, &csp_plugins))) {
+ _report_mr0(KHERR_ERROR, MSG_IP_GET_CONFIG);
+
+ p->state = KMM_PLUGIN_STATE_FAIL_UNKNOWN;
+ goto _exit;
+ }
+
+ if(KHM_FAILED(kmm_get_plugin_config(p->p.name, 0, &csp_plugin))) {
+ if(KHM_FAILED(kmm_register_plugin(&(p->p), 0))) {
+ _report_mr0(KHERR_ERROR, MSG_IP_NOT_REGISTERED);
+
+ p->state = KMM_PLUGIN_STATE_FAIL_NOT_REGISTERED;
+ goto _exit;
+ }
+
+ if(KHM_FAILED(kmm_get_plugin_config(p->p.name, 0, &csp_plugin))) {
+ _report_mr0(KHERR_ERROR, MSG_IP_NOT_REGISTERED);
+
+ p->state = KMM_PLUGIN_STATE_FAIL_NOT_REGISTERED;
+ goto _exit;
+ }
+ }
+
+ if (KHM_SUCCEEDED(khc_read_int32(csp_plugin, L"Disabled", &t)) && t) {
+ p->flags |= KMM_PLUGIN_FLAG_DISABLED;
+ p->state = KMM_PLUGIN_STATE_FAIL_DISABLED;
+ goto _exit;
+ }
+
+#if 0
+ /*TODO: check the failure count and act accordingly */
+ if(KHM_SUCCEEDED(khc_read_int32(csp_plugin, L"FailureCount", &t)) && (t > 0)) {
+ }
+#endif
+
+ EnterCriticalSection(&cs_kmm);
+
+ p->n_depends = 0;
+ p->n_unresolved = 0;
+
+ do {
+ wchar_t * deps = NULL;
+ wchar_t * d;
+ khm_size sz = 0;
+
+ if(khc_read_multi_string(csp_plugin, L"Dependencies",
+ NULL, &sz) != KHM_ERROR_TOO_LONG)
+ break;
+
+ deps = PMALLOC(sz);
+ if(KHM_FAILED(khc_read_multi_string(csp_plugin, L"Dependencies",
+ deps, &sz))) {
+ if(deps)
+ PFREE(deps);
+ break;
+ }
+
+ for(d = deps; d && *d; d = multi_string_next(d)) {
+ kmm_plugin_i * pd;
+ int i;
+
+ pd = kmmint_get_plugin_i(d);
+
+ if(pd->state == KMM_PLUGIN_STATE_NONE) {
+ /* the dependant was not previously known */
+ pd->state = KMM_PLUGIN_STATE_PLACEHOLDER;
+ }
+
+ for(i=0; i < pd->n_dependants; i++) {
+ if(pd->dependants[i] == p)
+ break;
+ }
+
+ if(i >= pd->n_dependants) {
+ if( pd->n_dependants >= KMM_MAX_DEPENDANTS ) {
+ /*TODO: handle this gracefully */
+ RaiseException(1, EXCEPTION_NONCONTINUABLE, 0, NULL);
+ }
+
+ /* released in kmmint_free_plugin() */
+ kmm_hold_plugin(kmm_handle_from_plugin(p));
+ pd->dependants[pd->n_dependants] = p;
+ pd->n_dependants++;
+ }
+
+ p->n_depends++;
+
+ if(pd->state != KMM_PLUGIN_STATE_RUNNING) {
+ p->n_unresolved++;
+ }
+ }
+
+ if(p->n_unresolved > 0) {
+ p->state = KMM_PLUGIN_STATE_HOLD;
+ }
+
+ PFREE(deps);
+
+ } while(FALSE);
+
+#ifdef DEBUG
+ assert(!(p->flags & KMM_PLUGIN_FLAG_IN_MODCOUNT));
+#endif
+ p->flags |= KMM_PLUGIN_FLAG_IN_MODCOUNT;
+ p->module->plugin_count++;
+
+ LeaveCriticalSection(&cs_kmm);
+
+ if(p->state == KMM_PLUGIN_STATE_HOLD) {
+ _report_mr1(KHERR_INFO, MSG_IP_HOLD, _dupstr(p->p.name));
+
+ goto _exit_post;
+ }
+
+ kmmint_add_to_plugin_queue(p);
+
+ p->ht_thread = CreateThread(NULL,
+ 0,
+ kmmint_plugin_broker,
+ (LPVOID) p,
+ CREATE_SUSPENDED,
+ &dummy);
+
+ p->state = KMM_PLUGIN_STATE_INIT;
+
+ ResumeThread(p->ht_thread);
+
+_exit_post:
+ if(csp_plugin != NULL)
+ khc_close_space(csp_plugin);
+
+ if(csp_plugins != NULL)
+ khc_close_space(csp_plugins);
+
+ _report_mr2(KHERR_INFO, MSG_IP_STATE,
+ _dupstr(p->p.name), _int32(p->state));
+
+ _end_task();
+
+ return;
+
+ /* jump here if an error condition happens before the plugin
+ broker thread starts and the plugin should be unloaded */
+
+_exit:
+ if(csp_plugin != NULL)
+ khc_close_space(csp_plugin);
+ if(csp_plugins != NULL)
+ khc_close_space(csp_plugins);
+
+ _report_mr2(KHERR_WARNING, MSG_IP_EXITING,
+ _dupstr(p->p.name), _int32(p->state));
+ _end_task();
+
+
+#ifdef ASYNC_PLUGIN_UNLOAD_ON_FAILURE
+
+ kmm_hold_plugin(kmm_handle_from_plugin(p));
+
+ kmq_post_message(KMSG_KMM, KMSG_KMM_I_REG, KMM_REG_EXIT_PLUGIN, (void *) p);
+
+#else
+
+ kmmint_exit_plugin(p);
+
+#endif
+}
+
+/*! \internal
+ \brief Uninitialize a plugin
+
+ In addition to terminating the thread, and removing p from the
+ linked list and hashtable, it also frees up p.
+
+ \note Should only be called from the context of the registrar thread. */
+void kmmint_exit_plugin(kmm_plugin_i * p) {
+ int np;
+ khm_boolean release_plugin = TRUE;
+
+ if(p->state == KMM_PLUGIN_STATE_RUNNING ||
+ p->state == KMM_PLUGIN_STATE_INIT) {
+
+ kmq_post_thread_quit_message(p->tid_thread, 0, NULL);
+ /* when we post the quit message to the plugin thread, the plugin
+ broker terminates the plugin and posts a EXIT_PLUGIN message,
+ which calls this function again. We just exit here because
+ the EXIT_PLUGIN message will end up calling us again momentarily */
+ return;
+
+ }
+
+ if(p->ht_thread) {
+ /* wait for the thread to terminate */
+ WaitForSingleObject(p->ht_thread, INFINITE);
+ p->ht_thread = NULL;
+ }
+
+ EnterCriticalSection(&cs_kmm);
+
+ /* undo reference count done in kmmint_init_plugin() */
+ if(p->flags & KMM_PLUGIN_FLAG_IN_MODCOUNT) {
+
+ np = --(p->module->plugin_count);
+ p->flags &= ~KMM_PLUGIN_FLAG_IN_MODCOUNT;
+
+ } else {
+ /* the plugin was not included in the module's plugin_count.
+ We can't base a decision to unload the module based on this
+ plugin exiting. */
+ np = TRUE;
+ }
+
+ /* The plugin is in an error state. We need to keep the plugin
+ record in tact so that the failure information is kept
+ around. */
+ if (p->state < KMM_PLUGIN_STATE_NONE) {
+ release_plugin = FALSE;
+ }
+
+ LeaveCriticalSection(&cs_kmm);
+
+ if(!np) {
+ /* if this is the last plugin to exit, then notify the
+ registrar that the module should be removed as well */
+ kmm_hold_module(kmm_handle_from_module(p->module));
+ kmq_post_message(KMSG_KMM, KMSG_KMM_I_REG, KMM_REG_EXIT_MODULE, (void *) p->module);
+ }
+
+ /* release the hold obtained in kmmint_init_plugin() */
+ if (release_plugin)
+ kmm_release_plugin(kmm_handle_from_plugin(p));
+}
+
+/*! \internal
+ \brief Initialize a module
+
+ \a m is not in the linked list yet.
+
+ \note Should only be called from the context of the registrar thread. */
+void kmmint_init_module(kmm_module_i * m) {
+ HMODULE hm;
+ init_module_t p_init_module;
+ kmm_plugin_i * pi;
+ khm_int32 rv;
+ khm_handle csp_mod = NULL;
+ khm_handle csp_mods = NULL;
+ khm_size sz;
+ khm_int32 i;
+
+ /* error condition handling */
+ BOOL exit_module = FALSE;
+ BOOL release_module = TRUE;
+ BOOL record_failure = FALSE;
+
+ /* failure handling */
+ khm_int32 max_fail_count = 0;
+ khm_int64 fail_reset_time = 0;
+
+ _begin_task(0);
+ _report_mr1(KHERR_NONE, MSG_INIT_MODULE, _cstr(m->name));
+ _describe();
+
+ kmm_hold_module(kmm_handle_from_module(m));
+
+ if(KHM_FAILED(kmm_get_modules_config(0, &csp_mods))) {
+ _report_mr0(KHERR_ERROR, MSG_IM_GET_CONFIG);
+ _location(L"kmm_get_modules_config()");
+
+ m->state = KMM_MODULE_STATE_FAIL_UNKNOWN;
+ goto _exit;
+ }
+
+ khc_read_int32(csp_mods, L"ModuleMaxFailureCount", &max_fail_count);
+ khc_read_int64(csp_mods, L"ModuleFailureCountResetTime", &fail_reset_time);
+
+ /* If the module is not in the pre-init state, we can't
+ initialize it. */
+ if(m->state != KMM_MODULE_STATE_PREINIT) {
+ _report_mr1(KHERR_INFO, MSG_IM_NOT_PREINIT, _int32(m->state));
+ goto _exit;
+ }
+
+ if(KHM_FAILED(kmm_get_module_config(m->name, 0, &csp_mod))) {
+ _report_mr0(KHERR_ERROR, MSG_IM_NOT_REGISTERED);
+
+ m->state = KMM_MODULE_STATE_FAIL_NOT_REGISTERED;
+ goto _exit;
+ }
+
+ if(KHM_SUCCEEDED(khc_read_int32(csp_mod, L"Disabled", &i)) && i) {
+ _report_mr0(KHERR_INFO, MSG_IM_DISABLED);
+
+ m->state = KMM_MODULE_STATE_FAIL_DISABLED;
+ goto _exit;
+ }
+
+ if(KHM_SUCCEEDED(khc_read_int32(csp_mod, L"NoUnload", &i)) && i) {
+ m->flags |= KMM_MODULE_FLAG_NOUNLOAD;
+ }
+
+ if(KHM_SUCCEEDED(khc_read_int32(csp_mod, L"FailureCount", &i))) {
+ khm_int64 tm;
+ khm_int64 ct;
+ FILETIME fct;
+ khm_int32 last_reason = 0;
+
+ /* reset the failure count if the failure count reset time
+ period has elapsed */
+ tm = 0;
+ khc_read_int64(csp_mod, L"FailureTime", &tm);
+ GetSystemTimeAsFileTime(&fct);
+
+ ct = (FtToInt(&fct) - tm) / 10000000i64;
+
+ if(tm > 0 &&
+ ct > fail_reset_time) {
+ i = 0;
+ khc_write_int32(csp_mod, L"FailureCount", 0);
+ khc_write_int64(csp_mod, L"FailureTime", 0);
+ }
+
+ khc_read_int32(csp_mod, L"FailureReason", &last_reason);
+
+ /* did we exceed the max failure count? However, we ignore
+ the max failure count if the reason why it didn't load the
+ last time was because the module wasn't found. */
+ if(i > max_fail_count &&
+ last_reason != KMM_MODULE_STATE_FAIL_NOT_FOUND) {
+ /* failed too many times */
+ _report_mr0(KHERR_INFO, MSG_IM_MAX_FAIL);
+
+ m->state = KMM_MODULE_STATE_FAIL_MAX_FAILURE;
+ goto _exit;
+ }
+ }
+
+ if(khc_read_string(csp_mod, L"ImagePath", NULL, &sz) ==
+ KHM_ERROR_TOO_LONG) {
+ if(m->path)
+ PFREE(m->path);
+ m->path = PMALLOC(sz);
+ khc_read_string(csp_mod, L"ImagePath", m->path, &sz);
+ } else {
+ _report_mr0(KHERR_ERROR, MSG_IM_NOT_REGISTERED);
+
+ m->state = KMM_MODULE_STATE_FAIL_NOT_REGISTERED;
+ goto _exit;
+ }
+
+ rv = kmmint_read_module_info(m);
+
+ if (KHM_FAILED(rv)) {
+ if (rv == KHM_ERROR_INCOMPATIBLE) {
+ _report_mr0(KHERR_ERROR, MSG_IM_INCOMPATIBLE);
+
+ m->state = KMM_MODULE_STATE_FAIL_INCOMPAT;
+ } else if (rv == KHM_ERROR_NOT_FOUND) {
+ _report_mr1(KHERR_ERROR, MSG_IM_NOT_FOUND, _dupstr(m->path));
+
+ m->state = KMM_MODULE_STATE_FAIL_NOT_FOUND;
+ } else {
+ _report_mr0(KHERR_ERROR, MSG_IM_INVALID_MODULE);
+
+ m->state = KMM_MODULE_STATE_FAIL_INV_MODULE;
+ }
+ goto _exit;
+ }
+
+ /* check again */
+ if(m->state != KMM_MODULE_STATE_PREINIT) {
+ _report_mr0(KHERR_ERROR, MSG_IM_NOT_PREINIT);
+
+ goto _exit;
+ }
+
+ /* from this point on, we must record any failure codes */
+ record_failure = TRUE;
+
+ hm = LoadLibrary(m->path);
+ if(!hm) {
+ m->h_module = NULL;
+ m->state = KMM_MODULE_STATE_FAIL_NOT_FOUND;
+
+ _report_mr1(KHERR_ERROR, MSG_IM_NOT_FOUND, _dupstr(m->path));
+
+ goto _exit;
+ }
+
+ /* from this point on, we need to discard the module through
+ exit_module */
+ ResetEvent(evt_exit);
+
+ kmm_active_modules++;
+
+ release_module = FALSE;
+ exit_module = TRUE;
+
+ m->flags |= KMM_MODULE_FLAG_LOADED;
+ m->h_module = hm;
+
+ /* TODO: check signatures */
+
+ p_init_module = (init_module_t) GetProcAddress(hm, EXP_INIT_MODULE);
+
+ if(!p_init_module) {
+ _report_mr1(KHERR_ERROR, MSG_IM_NO_ENTRY, _cstr(EXP_INIT_MODULE));
+
+ m->state = KMM_MODULE_STATE_FAIL_INVALID;
+ goto _exit;
+ }
+
+ m->state = KMM_MODULE_STATE_INIT;
+
+ /* call init_module() */
+ rv = (*p_init_module)(kmm_handle_from_module(m));
+
+ m->flags |= KMM_MODULE_FLAG_INITP;
+
+ if(KHM_FAILED(rv)) {
+ _report_mr1(KHERR_ERROR, MSG_IM_INIT_FAIL, _int32(rv));
+
+ m->state = KMM_MODULE_STATE_FAIL_LOAD;
+ goto _exit;
+ }
+
+ if(!m->plugins) {
+ _report_mr0(KHERR_ERROR, MSG_IM_NO_PLUGINS);
+
+ m->state = KMM_MODULE_STATE_FAIL_NO_PLUGINS;
+ record_failure = FALSE;
+ goto _exit;
+ }
+
+ m->state = KMM_MODULE_STATE_INITPLUG;
+
+ do {
+ LPOP(&(m->plugins), &pi);
+ if(pi) {
+ pi->flags &= ~KMM_PLUGIN_FLAG_IN_MODLIST;
+ kmmint_init_plugin(pi);
+
+ /* release the hold obtained in kmm_provide_plugin() */
+ kmm_release_plugin(kmm_handle_from_plugin(pi));
+ }
+ } while(pi);
+
+ if(!m->plugin_count) {
+ /* We don't want to report this case. This usually means that
+ the plugins that were provided by the module were
+ disabled. */
+#ifdef REPORT_EMPTY_MODULES
+ _report_mr0(KHERR_ERROR, MSG_IM_NO_PLUGINS);
+
+ m->state = KMM_MODULE_STATE_FAIL_NO_PLUGINS;
+#endif
+ record_failure = FALSE;
+ goto _exit;
+ }
+
+ m->state = KMM_MODULE_STATE_RUNNING;
+
+ exit_module = FALSE;
+ record_failure = FALSE;
+
+ _exit:
+ if(csp_mod) {
+ if(record_failure) {
+ FILETIME fct;
+
+ i = 0;
+ khc_read_int32(csp_mod, L"FailureCount", &i);
+ i++;
+ khc_write_int32(csp_mod, L"FailureCount", i);
+
+ if(i==1) { /* first fault */
+ GetSystemTimeAsFileTime(&fct);
+ khc_write_int64(csp_mod, L"FailureTime", FtToInt(&fct));
+ }
+
+ khc_write_int32(csp_mod, L"FailureReason", m->state);
+ }
+ khc_close_space(csp_mod);
+ }
+
+ if(csp_mods)
+ khc_close_space(csp_mods);
+
+ _report_mr2(KHERR_INFO, MSG_IM_MOD_STATE,
+ _dupstr(m->name), _int32(m->state));
+
+ kmmint_remove_from_module_queue();
+
+ /* if something went wrong after init_module was called on the
+ module code, we need to call exit_module */
+ if(exit_module)
+ kmmint_exit_module(m);
+
+ if(release_module)
+ kmm_release_module(kmm_handle_from_module(m));
+
+ if (kherr_is_error()) {
+ kherr_context * c;
+ kherr_event * err_e = NULL;
+ kherr_event * warn_e = NULL;
+ kherr_event * e;
+
+ c = kherr_peek_context();
+ err_e = kherr_get_err_event(c);
+ for(e = kherr_get_first_event(c);
+ e;
+ e = kherr_get_next_event(e)) {
+ if (e != err_e &&
+ e->severity == KHERR_WARNING) {
+ warn_e = e;
+ break;
+ }
+ }
+
+ kherr_evaluate_event(err_e);
+ if (warn_e)
+ kherr_evaluate_event(warn_e);
+
+ kherr_clear_error();
+
+ e = kherr_report(KHERR_ERROR,
+ (wchar_t *) MSG_IMERR_TITLE,
+ KHERR_FACILITY,
+ NULL,
+ err_e->long_desc,
+ ((warn_e)? (wchar_t *)MSG_IMERR_SUGGEST: NULL),
+ KHERR_FACILITY_ID,
+ KHERR_SUGGEST_NONE,
+ _cstr(m->name),
+ ((warn_e)? _cstr(warn_e->long_desc):_vnull()),
+ _vnull(),_vnull(),
+ KHERR_RF_MSG_SHORT_DESC |
+ ((warn_e)? KHERR_RF_MSG_SUGGEST: 0),
+ KHERR_HMODULE);
+
+ kherr_evaluate_event(e);
+
+ kherr_release_context(c);
+ }
+
+ _end_task();
+}
+
+
+/*! \internal
+ \brief Uninitializes a module
+
+ \note Should only be called from the context of the registrar
+ thread */
+void kmmint_exit_module(kmm_module_i * m) {
+ kmm_plugin_i * p;
+
+ /* Exiting a module happens in two stages.
+
+ If the module state is running (there are active plugins) then
+ those plugins must be exited. This has to be done from the
+ plugin threads. The signal for the plugins to exit must be
+ issued from the registrar. Therefore, we post messages to the
+ registrar for each plugin we want to remove and exit
+ kmmint_exit_module().
+
+ When the last plugin is exited, the plugin management code
+ automatically signalls the registrar to remove the module.
+ kmmint_exit_module() gets called again. This is the second
+ stage, where we call exit_module() for the module and start
+ unloading everything.
+ */
+
+ EnterCriticalSection(&cs_kmm);
+
+ /* get rid of any dangling uninitialized plugins */
+ LPOP(&(m->plugins), &p);
+ while(p) {
+ p->flags &= ~KMM_PLUGIN_FLAG_IN_MODLIST;
+ kmmint_exit_plugin(p);
+
+ /* release hold from kmm_provide_plugin() */
+ kmm_release_plugin(kmm_handle_from_plugin(p));
+
+ LPOP(&(m->plugins), &p);
+ }
+
+ if(m->state == KMM_MODULE_STATE_RUNNING) {
+ int np = 0;
+
+ m->state = KMM_MODULE_STATE_EXITPLUG;
+
+ p = kmm_listed_plugins;
+
+ while(p) {
+ if(p->module == m &&
+ (p->flags & KMM_PLUGIN_FLAG_IN_MODCOUNT)) {
+
+ kmm_hold_plugin(kmm_handle_from_plugin(p));
+ kmq_post_message(KMSG_KMM, KMSG_KMM_I_REG,
+ KMM_REG_EXIT_PLUGIN, (void *) p);
+ np++;
+
+ }
+
+ p = LNEXT(p);
+ }
+
+#ifdef DEBUG
+ assert(np == m->plugin_count);
+#endif
+
+ if(np > 0) {
+ /* we have to go back and wait for the plugins to exit.
+ when the last plugin exits, it automatically posts
+ EXIT_MODULE. We can pick up from there when this
+ happens. */
+ LeaveCriticalSection(&cs_kmm);
+ return;
+ }
+
+ } else {
+
+#ifdef DEBUG
+ assert(m->plugin_count == 0 ||
+ m->state == KMM_MODULE_STATE_EXITPLUG);
+#endif
+
+ /* if there are still plug-ins waiting to be unloaded, then we
+ have to go back and wait for them to finish. Once they are
+ done, kmmint_exit_module() will get called again. */
+ if (m->plugin_count > 0) {
+ LeaveCriticalSection(&cs_kmm);
+ return;
+ }
+ }
+
+ if(m->flags & KMM_MODULE_FLAG_INITP) {
+ exit_module_t p_exit_module;
+
+ if(m->state > 0)
+ m->state = KMM_MODULE_STATE_EXIT;
+
+ p_exit_module =
+ (exit_module_t) GetProcAddress(m->h_module,
+ EXP_EXIT_MODULE);
+ if(p_exit_module) {
+ LeaveCriticalSection(&cs_kmm);
+ (*p_exit_module)(kmm_handle_from_module(m));
+ EnterCriticalSection(&cs_kmm);
+ }
+ }
+
+ if(m->state > 0)
+ m->state = KMM_MODULE_STATE_EXITED;
+
+ LeaveCriticalSection(&cs_kmm);
+
+ if(!(m->flags & KMM_MODULE_FLAG_NOUNLOAD) &&
+ m->h_module) {
+ FreeLibrary(m->h_module);
+ }
+
+ if(!(m->flags & KMM_MODULE_FLAG_NOUNLOAD) &&
+ m->h_resource && (m->h_resource != m->h_module)) {
+ FreeLibrary(m->h_resource);
+ }
+
+ m->h_module = NULL;
+ m->h_resource = NULL;
+
+ if (m->flags & KMM_MODULE_FLAG_LOADED) {
+#ifdef DEBUG
+ assert(kmm_active_modules > 0);
+#endif
+ kmm_active_modules--;
+ }
+
+ m->flags = 0;
+
+ /* release the hold obtained in kmmint_init_module() */
+ kmm_release_module(kmm_handle_from_module(m));
+
+ /* Last but not least, now see if there are any modules left that
+ are running. If not, we can safely signal an exit. */
+ if (kmm_active_modules == 0) {
+ SetEvent(evt_exit);
+ }
+}
diff --git a/src/windows/identity/kmm/kmminternal.h b/src/windows/identity/kmm/kmminternal.h
index 38fce2422f..1712e976cf 100644
--- a/src/windows/identity/kmm/kmminternal.h
+++ b/src/windows/identity/kmm/kmminternal.h
@@ -1,258 +1,258 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#ifndef __KHIMAIRA_KMMINTERNAL_H
-#define __KHIMAIRA_KMMINTERNAL_H
-
-#include<windows.h>
-#include<shlwapi.h>
-#include<strsafe.h>
-
-#define KHERR_FACILITY kmm_facility
-#define KHERR_FACILITY_ID KHM_FACILITY_KMM
-#define KHERR_HMODULE ((HMODULE) kmm_hInstance)
-#include<kherr.h>
-
-#include<kmm.h>
-#include<khmsgtypes.h>
-#include<kherror.h>
-#include<kplugin.h>
-
-#define NOEXPORT
-
-#include<utils.h>
-#include<kconfig.h>
-#include<kcreddb.h>
-#include<kmm_msgs.h>
-
-struct kmm_plugin_i_t; /* forward dcl */
-
-typedef struct kmm_module_i_t {
- khm_int32 magic;
-
- wchar_t * name;
- wchar_t * path;
- wchar_t * description;
- wchar_t * vendor;
- wchar_t * support;
-
- khm_version file_version;
- khm_version prod_version;
-
- HMODULE h_module;
-
- HMODULE h_resource;
- WORD lcid_resource;
-
- khm_int32 flags;
- khm_int32 state;
- khm_int32 plugin_count; /* number of active plugins */
-
- void * version_info;
-
- khm_int32 refcount;
-
- struct kmm_plugin_i_t * plugins; /* only used for registration */
-
- LDCL(struct kmm_module_i_t);
-} kmm_module_i;
-
-#define KMM_MODULE_MAGIC 0x482f4e88
-
-#define kmm_is_module(m) ((m) && ((kmm_module_i *)m)->magic == KMM_MODULE_MAGIC)
-
-#define kmm_module_from_handle(m) ((kmm_module_i *) m)
-#define kmm_handle_from_module(m) ((kmm_module) m)
-
-/* LoadLibrary succeeded for module */
-#define KMM_MODULE_FLAG_LOADED 0x00000001
-
-/* init_module entry called */
-#define KMM_MODULE_FLAG_INITP 0x00000002
-
-/* the resources have been loaded */
-#define KMM_MODULE_FLAG_RES_LOADED 0x00000008
-
-/* the signature has been verified */
-#define KMM_MODULE_FLAG_SIG 0x00000010
-
-/* the module is disabled by the user
- (option specified in configuration) */
-#define KMM_MODULE_FLAG_DISABLED 0x00000400
-
-/* the module should not be unloaded
- (option specified in configuration)*/
-#define KMM_MODULE_FLAG_NOUNLOAD 0x00000800
-
-/* the module has been removed from the active modules list. */
-#define KMM_MODULE_FLAG_INACTIVE 0x00001000
-
-typedef struct kmm_plugin_i_t {
- kmm_plugin_reg p;
-
- khm_int32 magic;
-
- kmm_module_i * module;
- HANDLE ht_thread;
- DWORD tid_thread;
-
- khm_int32 state;
- khm_int32 flags;
-
- int refcount;
-
- int n_depends;
- int n_unresolved;
- struct kmm_plugin_i_t * dependants[KMM_MAX_DEPENDANTS];
- int n_dependants;
-
- LDCL(struct kmm_plugin_i_t);
-} kmm_plugin_i;
-
-#define KMM_PLUGIN_MAGIC 0x320e8fb4
-
-#define kmm_is_plugin(p) ((p) && ((kmm_plugin_i *) (p))->magic == KMM_PLUGIN_MAGIC)
-
-#define kmm_handle_from_plugin(p) ((kmm_plugin) p)
-#define kmm_plugin_from_handle(ph) ((kmm_plugin_i *) ph)
-
-/* the plugin has already been marked for unload */
-#define KMM_PLUGIN_FLAG_UNLOAD 0x00000001
-
-/* the plugin is in the kmm_listed_plugins list */
-#define KMM_PLUGIN_FLAG_IN_LIST 0x00000002
-
-/* the plugin is in the module's plugin list */
-#define KMM_PLUGIN_FLAG_IN_MODLIST 0x00000004
-
-/* the plugin has been included in the pending_plugins count. */
-#define KMM_PLUGIN_FLAG_IN_QUEUE 0x00000010
-
-/* the plugin is included in the module's plugin count */
-#define KMM_PLUGIN_FLAG_IN_MODCOUNT 0x00000020
-
-/* the plugin is disabled by the user
- (option specified in configuration) */
-/* (this is defined in kmm.h)
-
- #define KMM_PLUGIN_FLAG_DISABLED 0x00000400
-
-*/
-
-enum kmm_registrar_uparam_t {
- KMM_REG_INIT_MODULE,
- KMM_REG_EXIT_MODULE,
- KMM_REG_INIT_PLUGIN,
- KMM_REG_EXIT_PLUGIN
-};
-
-extern kmm_module_i * kmm_all_modules;
-extern khm_size kmm_active_modules;
-extern kmm_plugin_i * kmm_listed_plugins;
-extern HANDLE ht_registrar;
-extern DWORD tid_registrar;
-extern DWORD tls_kmm;
-
-extern hashtable * hash_plugins;
-extern hashtable * hash_modules;
-
-extern CRITICAL_SECTION cs_kmm;
-extern int ready;
-extern HANDLE evt_startup;
-extern HANDLE evt_exit;
-extern const wchar_t * kmm_facility;
-
-extern HINSTANCE kmm_hInstance;
-
-extern kconf_schema schema_kmmconfig[];
-
-/* Registrar */
-
-khm_boolean KHMAPI
-kmmint_reg_cb(khm_int32 msg_type,
- khm_int32 msg_sub_type,
- khm_ui_4 uparam,
- void *vparam);
-
-DWORD WINAPI kmmint_registrar(LPVOID lpParameter);
-
-DWORD WINAPI kmmint_plugin_broker(LPVOID lpParameter);
-
-void kmmint_init_plugin(kmm_plugin_i * p);
-void kmmint_exit_plugin(kmm_plugin_i * p);
-void kmmint_init_module(kmm_module_i * m);
-void kmmint_exit_module(kmm_module_i * m);
-
-/* Modules */
-kmm_module_i *
-kmmint_get_module_i(wchar_t * name);
-
-kmm_module_i *
-kmmint_find_module_i(wchar_t * name);
-
-void
-kmmint_free_module(kmm_module_i * m);
-
-khm_int32
-kmmint_read_module_info(kmm_module_i * m);
-
-/* Plugins */
-kmm_plugin_i *
-kmmint_get_plugin_i(wchar_t * name);
-
-kmm_plugin_i *
-kmmint_find_plugin_i(wchar_t * name);
-
-void
-kmmint_free_plugin(kmm_plugin_i * pi);
-
-void
-kmmint_list_plugin(kmm_plugin_i * p);
-
-void
-kmmint_delist_plugin(kmm_plugin_i * p);
-
-khm_boolean
-kmmint_load_locale_lib(kmm_module_i * m, kmm_module_locale * l);
-
-#define KMM_CSNAME_ROOT L"PluginManager"
-#define KMM_CSNAME_PLUGINS L"Plugins"
-#define KMM_CSNAME_MODULES L"Modules"
-#define KMM_VALNAME_LOADLIST L"LoadList"
-
-void
-kmmint_add_to_module_queue(void);
-
-void
-kmmint_remove_from_module_queue(void);
-
-#define _WAIT_FOR_START \
- do { \
- if(ready) break; \
- WaitForSingleObject(evt_startup, INFINITE); \
- } while(0)
-
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __KHIMAIRA_KMMINTERNAL_H
+#define __KHIMAIRA_KMMINTERNAL_H
+
+#include<windows.h>
+#include<shlwapi.h>
+#include<strsafe.h>
+
+#define KHERR_FACILITY kmm_facility
+#define KHERR_FACILITY_ID KHM_FACILITY_KMM
+#define KHERR_HMODULE ((HMODULE) kmm_hInstance)
+#include<kherr.h>
+
+#include<kmm.h>
+#include<khmsgtypes.h>
+#include<kherror.h>
+#include<kplugin.h>
+
+#define NOEXPORT
+
+#include<utils.h>
+#include<kconfig.h>
+#include<kcreddb.h>
+#include<kmm_msgs.h>
+
+struct kmm_plugin_i_t; /* forward dcl */
+
+typedef struct kmm_module_i_t {
+ khm_int32 magic;
+
+ wchar_t * name;
+ wchar_t * path;
+ wchar_t * description;
+ wchar_t * vendor;
+ wchar_t * support;
+
+ khm_version file_version;
+ khm_version prod_version;
+
+ HMODULE h_module;
+
+ HMODULE h_resource;
+ WORD lcid_resource;
+
+ khm_int32 flags;
+ khm_int32 state;
+ khm_int32 plugin_count; /* number of active plugins */
+
+ void * version_info;
+
+ khm_int32 refcount;
+
+ struct kmm_plugin_i_t * plugins; /* only used for registration */
+
+ LDCL(struct kmm_module_i_t);
+} kmm_module_i;
+
+#define KMM_MODULE_MAGIC 0x482f4e88
+
+#define kmm_is_module(m) ((m) && ((kmm_module_i *)m)->magic == KMM_MODULE_MAGIC)
+
+#define kmm_module_from_handle(m) ((kmm_module_i *) m)
+#define kmm_handle_from_module(m) ((kmm_module) m)
+
+/* LoadLibrary succeeded for module */
+#define KMM_MODULE_FLAG_LOADED 0x00000001
+
+/* init_module entry called */
+#define KMM_MODULE_FLAG_INITP 0x00000002
+
+/* the resources have been loaded */
+#define KMM_MODULE_FLAG_RES_LOADED 0x00000008
+
+/* the signature has been verified */
+#define KMM_MODULE_FLAG_SIG 0x00000010
+
+/* the module is disabled by the user
+ (option specified in configuration) */
+#define KMM_MODULE_FLAG_DISABLED 0x00000400
+
+/* the module should not be unloaded
+ (option specified in configuration)*/
+#define KMM_MODULE_FLAG_NOUNLOAD 0x00000800
+
+/* the module has been removed from the active modules list. */
+#define KMM_MODULE_FLAG_INACTIVE 0x00001000
+
+typedef struct kmm_plugin_i_t {
+ kmm_plugin_reg p;
+
+ khm_int32 magic;
+
+ kmm_module_i * module;
+ HANDLE ht_thread;
+ DWORD tid_thread;
+
+ khm_int32 state;
+ khm_int32 flags;
+
+ int refcount;
+
+ int n_depends;
+ int n_unresolved;
+ struct kmm_plugin_i_t * dependants[KMM_MAX_DEPENDANTS];
+ int n_dependants;
+
+ LDCL(struct kmm_plugin_i_t);
+} kmm_plugin_i;
+
+#define KMM_PLUGIN_MAGIC 0x320e8fb4
+
+#define kmm_is_plugin(p) ((p) && ((kmm_plugin_i *) (p))->magic == KMM_PLUGIN_MAGIC)
+
+#define kmm_handle_from_plugin(p) ((kmm_plugin) p)
+#define kmm_plugin_from_handle(ph) ((kmm_plugin_i *) ph)
+
+/* the plugin has already been marked for unload */
+#define KMM_PLUGIN_FLAG_UNLOAD 0x00000001
+
+/* the plugin is in the kmm_listed_plugins list */
+#define KMM_PLUGIN_FLAG_IN_LIST 0x00000002
+
+/* the plugin is in the module's plugin list */
+#define KMM_PLUGIN_FLAG_IN_MODLIST 0x00000004
+
+/* the plugin has been included in the pending_plugins count. */
+#define KMM_PLUGIN_FLAG_IN_QUEUE 0x00000010
+
+/* the plugin is included in the module's plugin count */
+#define KMM_PLUGIN_FLAG_IN_MODCOUNT 0x00000020
+
+/* the plugin is disabled by the user
+ (option specified in configuration) */
+/* (this is defined in kmm.h)
+
+ #define KMM_PLUGIN_FLAG_DISABLED 0x00000400
+
+*/
+
+enum kmm_registrar_uparam_t {
+ KMM_REG_INIT_MODULE,
+ KMM_REG_EXIT_MODULE,
+ KMM_REG_INIT_PLUGIN,
+ KMM_REG_EXIT_PLUGIN
+};
+
+extern kmm_module_i * kmm_all_modules;
+extern khm_size kmm_active_modules;
+extern kmm_plugin_i * kmm_listed_plugins;
+extern HANDLE ht_registrar;
+extern DWORD tid_registrar;
+extern DWORD tls_kmm;
+
+extern hashtable * hash_plugins;
+extern hashtable * hash_modules;
+
+extern CRITICAL_SECTION cs_kmm;
+extern int ready;
+extern HANDLE evt_startup;
+extern HANDLE evt_exit;
+extern const wchar_t * kmm_facility;
+
+extern HINSTANCE kmm_hInstance;
+
+extern kconf_schema schema_kmmconfig[];
+
+/* Registrar */
+
+khm_boolean KHMAPI
+kmmint_reg_cb(khm_int32 msg_type,
+ khm_int32 msg_sub_type,
+ khm_ui_4 uparam,
+ void *vparam);
+
+DWORD WINAPI kmmint_registrar(LPVOID lpParameter);
+
+DWORD WINAPI kmmint_plugin_broker(LPVOID lpParameter);
+
+void kmmint_init_plugin(kmm_plugin_i * p);
+void kmmint_exit_plugin(kmm_plugin_i * p);
+void kmmint_init_module(kmm_module_i * m);
+void kmmint_exit_module(kmm_module_i * m);
+
+/* Modules */
+kmm_module_i *
+kmmint_get_module_i(wchar_t * name);
+
+kmm_module_i *
+kmmint_find_module_i(wchar_t * name);
+
+void
+kmmint_free_module(kmm_module_i * m);
+
+khm_int32
+kmmint_read_module_info(kmm_module_i * m);
+
+/* Plugins */
+kmm_plugin_i *
+kmmint_get_plugin_i(wchar_t * name);
+
+kmm_plugin_i *
+kmmint_find_plugin_i(wchar_t * name);
+
+void
+kmmint_free_plugin(kmm_plugin_i * pi);
+
+void
+kmmint_list_plugin(kmm_plugin_i * p);
+
+void
+kmmint_delist_plugin(kmm_plugin_i * p);
+
+khm_boolean
+kmmint_load_locale_lib(kmm_module_i * m, kmm_module_locale * l);
+
+#define KMM_CSNAME_ROOT L"PluginManager"
+#define KMM_CSNAME_PLUGINS L"Plugins"
+#define KMM_CSNAME_MODULES L"Modules"
+#define KMM_VALNAME_LOADLIST L"LoadList"
+
+void
+kmmint_add_to_module_queue(void);
+
+void
+kmmint_remove_from_module_queue(void);
+
+#define _WAIT_FOR_START \
+ do { \
+ if(ready) break; \
+ WaitForSingleObject(evt_startup, INFINITE); \
+ } while(0)
+
+#endif
diff --git a/src/windows/identity/kmm/kmmmain.c b/src/windows/identity/kmm/kmmmain.c
index aa94a59a1a..e54dd6de26 100644
--- a/src/windows/identity/kmm/kmmmain.c
+++ b/src/windows/identity/kmm/kmmmain.c
@@ -1,159 +1,159 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<kmminternal.h>
-
-kmm_module_i * kmm_all_modules = NULL;
-kmm_plugin_i * kmm_listed_plugins = NULL;
-
-HANDLE ht_registrar = NULL;
-DWORD tid_registrar = 0;
-DWORD tls_kmm = 0;
-
-#define KMM_HASH_SIZE 31
-hashtable * hash_plugins = NULL;
-hashtable * hash_modules = NULL;
-
-CRITICAL_SECTION cs_kmm;
-HANDLE evt_startup = NULL;
-HANDLE evt_exit = NULL;
-int ready = 0;
-
-HINSTANCE kmm_hInstance;
-const wchar_t * kmm_facility = L"KMM";
-
-KHMEXP void KHMAPI kmm_init(void)
-{
- DWORD dummy;
-
- EnterCriticalSection(&cs_kmm);
- kmm_all_modules = NULL;
- kmm_listed_plugins = NULL;
-
- tls_kmm = TlsAlloc();
-
- hash_plugins = hash_new_hashtable(
- KMM_HASH_SIZE,
- hash_string,
- hash_string_comp,
- NULL,
- NULL);
-
- hash_modules = hash_new_hashtable(
- KMM_HASH_SIZE,
- hash_string,
- hash_string_comp,
- NULL,
- NULL);
-
- ht_registrar = CreateThread(
- NULL,
- 0,
- kmmint_registrar,
- NULL,
- 0,
- &dummy);
-
- _WAIT_FOR_START;
-
- khc_load_schema(NULL, schema_kmmconfig);
-
- LeaveCriticalSection(&cs_kmm);
-}
-
-KHMEXP void KHMAPI kmm_exit(void)
-{
- kmm_module_i * m;
- kmm_plugin_i * p;
-
- EnterCriticalSection(&cs_kmm);
-
- p = kmm_listed_plugins;
- while(p) {
- kmm_plugin_i * pn;
-
- pn = LNEXT(p);
- /* plugins that were never resolved should be kicked off the
- list. Flipping the refcount will do that if no other
- references exist for the plugin. The plugins that were
- waiting for unresolved dependencies will automatically get
- freed when the placeholders and other plugins get freed. */
- if(p->state == KMM_PLUGIN_STATE_PLACEHOLDER) {
- kmm_hold_plugin(kmm_handle_from_plugin(p));
- kmm_release_plugin(kmm_handle_from_plugin(p));
- }
-
- p = pn;
- }
-
- m = kmm_all_modules;
- while(m) {
- kmm_unload_module(kmm_handle_from_module(m));
- m = LNEXT(m);
- }
-
- LeaveCriticalSection(&cs_kmm);
- WaitForSingleObject(evt_exit, INFINITE);
- EnterCriticalSection(&cs_kmm);
-
- kmq_post_thread_quit_message(tid_registrar, 0, NULL);
-
- hash_del_hashtable(hash_plugins);
- hash_del_hashtable(hash_modules);
-
- LeaveCriticalSection(&cs_kmm);
-
- TlsFree(tls_kmm);
-
- tls_kmm = 0;
-}
-
-void kmm_dll_init(void)
-{
- InitializeCriticalSection(&cs_kmm);
- evt_startup = CreateEvent(NULL, TRUE, FALSE, NULL);
- evt_exit = CreateEvent(NULL, TRUE, TRUE, NULL);
-}
-
-void kmm_dll_exit(void)
-{
- DeleteCriticalSection(&cs_kmm);
- if(evt_startup)
- CloseHandle(evt_startup);
- evt_startup = NULL;
-}
-
-void
-kmm_process_attach(HINSTANCE hinstDLL) {
- kmm_hInstance = hinstDLL;
- kmm_dll_init();
-}
-
-void
-kmm_process_detach(void) {
- kmm_dll_exit();
-}
-
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<kmminternal.h>
+
+kmm_module_i * kmm_all_modules = NULL;
+kmm_plugin_i * kmm_listed_plugins = NULL;
+
+HANDLE ht_registrar = NULL;
+DWORD tid_registrar = 0;
+DWORD tls_kmm = 0;
+
+#define KMM_HASH_SIZE 31
+hashtable * hash_plugins = NULL;
+hashtable * hash_modules = NULL;
+
+CRITICAL_SECTION cs_kmm;
+HANDLE evt_startup = NULL;
+HANDLE evt_exit = NULL;
+int ready = 0;
+
+HINSTANCE kmm_hInstance;
+const wchar_t * kmm_facility = L"KMM";
+
+KHMEXP void KHMAPI kmm_init(void)
+{
+ DWORD dummy;
+
+ EnterCriticalSection(&cs_kmm);
+ kmm_all_modules = NULL;
+ kmm_listed_plugins = NULL;
+
+ tls_kmm = TlsAlloc();
+
+ hash_plugins = hash_new_hashtable(
+ KMM_HASH_SIZE,
+ hash_string,
+ hash_string_comp,
+ NULL,
+ NULL);
+
+ hash_modules = hash_new_hashtable(
+ KMM_HASH_SIZE,
+ hash_string,
+ hash_string_comp,
+ NULL,
+ NULL);
+
+ ht_registrar = CreateThread(
+ NULL,
+ 0,
+ kmmint_registrar,
+ NULL,
+ 0,
+ &dummy);
+
+ _WAIT_FOR_START;
+
+ khc_load_schema(NULL, schema_kmmconfig);
+
+ LeaveCriticalSection(&cs_kmm);
+}
+
+KHMEXP void KHMAPI kmm_exit(void)
+{
+ kmm_module_i * m;
+ kmm_plugin_i * p;
+
+ EnterCriticalSection(&cs_kmm);
+
+ p = kmm_listed_plugins;
+ while(p) {
+ kmm_plugin_i * pn;
+
+ pn = LNEXT(p);
+ /* plugins that were never resolved should be kicked off the
+ list. Flipping the refcount will do that if no other
+ references exist for the plugin. The plugins that were
+ waiting for unresolved dependencies will automatically get
+ freed when the placeholders and other plugins get freed. */
+ if(p->state == KMM_PLUGIN_STATE_PLACEHOLDER) {
+ kmm_hold_plugin(kmm_handle_from_plugin(p));
+ kmm_release_plugin(kmm_handle_from_plugin(p));
+ }
+
+ p = pn;
+ }
+
+ m = kmm_all_modules;
+ while(m) {
+ kmm_unload_module(kmm_handle_from_module(m));
+ m = LNEXT(m);
+ }
+
+ LeaveCriticalSection(&cs_kmm);
+ WaitForSingleObject(evt_exit, INFINITE);
+ EnterCriticalSection(&cs_kmm);
+
+ kmq_post_thread_quit_message(tid_registrar, 0, NULL);
+
+ hash_del_hashtable(hash_plugins);
+ hash_del_hashtable(hash_modules);
+
+ LeaveCriticalSection(&cs_kmm);
+
+ TlsFree(tls_kmm);
+
+ tls_kmm = 0;
+}
+
+void kmm_dll_init(void)
+{
+ InitializeCriticalSection(&cs_kmm);
+ evt_startup = CreateEvent(NULL, TRUE, FALSE, NULL);
+ evt_exit = CreateEvent(NULL, TRUE, TRUE, NULL);
+}
+
+void kmm_dll_exit(void)
+{
+ DeleteCriticalSection(&cs_kmm);
+ if(evt_startup)
+ CloseHandle(evt_startup);
+ evt_startup = NULL;
+}
+
+void
+kmm_process_attach(HINSTANCE hinstDLL) {
+ kmm_hInstance = hinstDLL;
+ kmm_dll_init();
+}
+
+void
+kmm_process_detach(void) {
+ kmm_dll_exit();
+}
+
diff --git a/src/windows/identity/kmm/kplugin.h b/src/windows/identity/kmm/kplugin.h
index e4e6003eec..6eb4e13c26 100644
--- a/src/windows/identity/kmm/kplugin.h
+++ b/src/windows/identity/kmm/kplugin.h
@@ -1,146 +1,146 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#ifndef __KHIMAIRA_KPLUGIN_H
-#define __KHIMAIRA_KPLUGIN_H
-
-#include<kmm.h>
-#include<kherror.h>
-
-/*! \addtogroup kmm
-@{*/
-/*! \defgroup kplugin NetIDMgr Plugin Callbacks
-
-See the following related documentation pages for more information
-about NetIDMgr plugins.
-
-These are prototypes of functions that must be implemented by a NetIDMgr
-plugin.
-
-- \ref plugins
-@{*/
-
-/*! \brief Initialize the module
-
- This is the first callback function to be called in a module.
- Perform all the required intialization when this is called. As
- mentioned in \ref plugins, you should not attempt to call any
- NetIDMgr API function from DLLMain or other initialization code
- other than this one.
-
- You should use this call back to register the plugins that will be
- implemented in this module and to notify the plugin manager of any
- resource libraries that this module will use.
-
- Call:
- - kmm_set_locale() : to set the notify the plugin manager of the
- locale specifc resource libraries that are used by this module.
- - kmm_provide_plugin() : to register each plugin that is
- implemented in this module.
-
- This function is called in the context of the current user, from
- the plug-in manager thread. This same thread is used by the
- plug-in manager to load and initialize all the modules for a
- session.
-
- The name of the callback must be init_module(). The calling
- convention is KHMAPI, which is currently __stdcall.
-
- If this function does not register any plugins, the plugin manager
- will immediately call exit_module() and unload the module even if
- the init_module() function completes successfully.
-
- \return Return the following values to indicate whether the module
- successfully initialized or not.
- - KHM_ERROR_SUCCESS : Succeeded. The module manager will call
- init_plugin() for each of the registered plugins for the
- module.
- - any other error code: Signals that the module did not
- successfully initialize. The plugin manager will
- immediately call exit_module() and then unload the module.
-
- \note This callback is required.
-*/
-KHMEXP khm_int32 KHMAPI init_module(kmm_module h_module);
-
-/*! \brief Type for init_module() */
-typedef khm_int32 (KHMAPI *init_module_t)(kmm_module);
-
-#if defined(_WIN64)
-#define EXP_INIT_MODULE "init_module"
-#elif defined(_WIN32)
-#define EXP_INIT_MODULE "_init_module@4"
-#else
-#error EXP_INIT_MODULE not defined for platform
-#endif
-
-/*! \brief Plugin procedure
-
- This is the message processor for a plugin. See \ref pi_fw_pnm_p
- for more information.
-
- Essentially, this is a message subscriber for KMQ messages.
-*/
-KHMEXP khm_int32 KHMAPI _plugin_proc(khm_int32 msg_type, khm_int32 msg_subtype, khm_ui_4 uparam, void * vparam);
-
-/*! \brief Type for init_plugin() */
-typedef kmq_callback_t _plugin_proc_t;
-
-/*! \brief Exit a module
-
- This is the last callback function that the NetIDMgr module
- manager calls before unloading the module. When this function is
- called, all of the plugins for the module have already been
- stopped. However, any localization libraries that were loaded as
- a result of init_module() calling kmm_set_locale_info() will still
- be loaded. These localization libraries will be unloaded
- immediately after this callback returns.
-
- Use this callback to perform any required cleanup tasks. However,
- it is advisable that each plugin perform its own cleanup tasks,
- since each plugin may be stopped independently of others.
-
- \return The return value of this function is ignored.
-
- \note This callback is not required.
-*/
-KHMEXP khm_int32 KHMAPI exit_module(kmm_module h_module);
-
-/*! \brief Type for exit_module() */
-typedef khm_int32 (KHMAPI *exit_module_t)(kmm_module);
-
-#if defined(_WIN64)
-#define EXP_EXIT_MODULE "exit_module"
-#elif defined(_WIN32)
-#define EXP_EXIT_MODULE "_exit_module@4"
-#else
-#error EXP_EXIT_MODULE not defined for platform
-#endif
-
-/*@}*/
-/*@}*/
-
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __KHIMAIRA_KPLUGIN_H
+#define __KHIMAIRA_KPLUGIN_H
+
+#include<kmm.h>
+#include<kherror.h>
+
+/*! \addtogroup kmm
+@{*/
+/*! \defgroup kplugin NetIDMgr Plugin Callbacks
+
+See the following related documentation pages for more information
+about NetIDMgr plugins.
+
+These are prototypes of functions that must be implemented by a NetIDMgr
+plugin.
+
+- \ref plugins
+@{*/
+
+/*! \brief Initialize the module
+
+ This is the first callback function to be called in a module.
+ Perform all the required intialization when this is called. As
+ mentioned in \ref plugins, you should not attempt to call any
+ NetIDMgr API function from DLLMain or other initialization code
+ other than this one.
+
+ You should use this call back to register the plugins that will be
+ implemented in this module and to notify the plugin manager of any
+ resource libraries that this module will use.
+
+ Call:
+ - kmm_set_locale() : to set the notify the plugin manager of the
+ locale specifc resource libraries that are used by this module.
+ - kmm_provide_plugin() : to register each plugin that is
+ implemented in this module.
+
+ This function is called in the context of the current user, from
+ the plug-in manager thread. This same thread is used by the
+ plug-in manager to load and initialize all the modules for a
+ session.
+
+ The name of the callback must be init_module(). The calling
+ convention is KHMAPI, which is currently __stdcall.
+
+ If this function does not register any plugins, the plugin manager
+ will immediately call exit_module() and unload the module even if
+ the init_module() function completes successfully.
+
+ \return Return the following values to indicate whether the module
+ successfully initialized or not.
+ - KHM_ERROR_SUCCESS : Succeeded. The module manager will call
+ init_plugin() for each of the registered plugins for the
+ module.
+ - any other error code: Signals that the module did not
+ successfully initialize. The plugin manager will
+ immediately call exit_module() and then unload the module.
+
+ \note This callback is required.
+*/
+KHMEXP khm_int32 KHMAPI init_module(kmm_module h_module);
+
+/*! \brief Type for init_module() */
+typedef khm_int32 (KHMAPI *init_module_t)(kmm_module);
+
+#if defined(_WIN64)
+#define EXP_INIT_MODULE "init_module"
+#elif defined(_WIN32)
+#define EXP_INIT_MODULE "_init_module@4"
+#else
+#error EXP_INIT_MODULE not defined for platform
+#endif
+
+/*! \brief Plugin procedure
+
+ This is the message processor for a plugin. See \ref pi_fw_pnm_p
+ for more information.
+
+ Essentially, this is a message subscriber for KMQ messages.
+*/
+KHMEXP khm_int32 KHMAPI _plugin_proc(khm_int32 msg_type, khm_int32 msg_subtype, khm_ui_4 uparam, void * vparam);
+
+/*! \brief Type for init_plugin() */
+typedef kmq_callback_t _plugin_proc_t;
+
+/*! \brief Exit a module
+
+ This is the last callback function that the NetIDMgr module
+ manager calls before unloading the module. When this function is
+ called, all of the plugins for the module have already been
+ stopped. However, any localization libraries that were loaded as
+ a result of init_module() calling kmm_set_locale_info() will still
+ be loaded. These localization libraries will be unloaded
+ immediately after this callback returns.
+
+ Use this callback to perform any required cleanup tasks. However,
+ it is advisable that each plugin perform its own cleanup tasks,
+ since each plugin may be stopped independently of others.
+
+ \return The return value of this function is ignored.
+
+ \note This callback is not required.
+*/
+KHMEXP khm_int32 KHMAPI exit_module(kmm_module h_module);
+
+/*! \brief Type for exit_module() */
+typedef khm_int32 (KHMAPI *exit_module_t)(kmm_module);
+
+#if defined(_WIN64)
+#define EXP_EXIT_MODULE "exit_module"
+#elif defined(_WIN32)
+#define EXP_EXIT_MODULE "_exit_module@4"
+#else
+#error EXP_EXIT_MODULE not defined for platform
+#endif
+
+/*@}*/
+/*@}*/
+
+#endif
diff --git a/src/windows/identity/kmq/consumer.c b/src/windows/identity/kmq/consumer.c
index d6041779f9..32bafec6e8 100644
--- a/src/windows/identity/kmq/consumer.c
+++ b/src/windows/identity/kmq/consumer.c
@@ -1,573 +1,573 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<kmqinternal.h>
-#include<assert.h>
-
-DWORD kmq_tls_queue;
-
-CRITICAL_SECTION cs_kmq_msg_ref;
-
-kmq_message_ref * kmq_msg_ref_free = NULL;
-
-/* ad-hoc subscriptions */
-kmq_msg_subscription * kmq_adhoc_subs = NULL;
-
-#ifdef DEBUG
-
-#include<stdio.h>
-
-void
-kmqint_dump_consumer(FILE * f) {
- kmq_message_ref * r;
- kmq_msg_subscription * s;
-
- int n_free = 0;
- int n_adhoc = 0;
-
- EnterCriticalSection(&cs_kmq_msg_ref);
-
- fprintf(f, "qc0\t*** Free Message References ***\n");
-
- fprintf(f, "qc1\tAddress\n");
-
- r = kmq_msg_ref_free;
- while(r) {
- n_free ++;
-
- fprintf(f, "qc2\t0x%p\n", r);
-
- r = LNEXT(r);
- }
-
- fprintf(f, "qc3\tTotal free message references : %d\n", n_free);
-
- fprintf(f, "qc4\t--- End ---\n");
-
- LeaveCriticalSection(&cs_kmq_msg_ref);
-
- EnterCriticalSection(&cs_kmq_global);
-
- fprintf(f, "qc5\t*** Adhoc Message Subscriptions ***\n");
-
- fprintf(f, "qc6\tAddress\tMsg Type\tRcpt Type\tRcpt\tQueue\n");
-
- s = kmq_adhoc_subs;
-
- while(s) {
- n_adhoc ++;
-
- fprintf(f, "qc7\t0x%p\t%d\t%s\t0x%p\t0x%p\n",
- s,
- s->type,
- (s->rcpt_type == KMQ_RCPTTYPE_CB)?"CALLBACK":"HWND",
- (s->rcpt_type == KMQ_RCPTTYPE_CB) ? (void *) s->recipient.cb: (void *) s->recipient.hwnd,
- s->queue);
-
- s = LNEXT(s);
- }
-
- fprintf(f, "qc8\tTotal ad-hoc subscriptions : %d\n", n_adhoc);
-
- fprintf(f, "qc9\t--- End ---\n");
-
- LeaveCriticalSection(&cs_kmq_global);
-
-}
-
-#endif
-
-/*! \internal
- \brief Get a message ref object
- \note called with cs_kmq_msg_ref held */
-kmq_message_ref * kmqint_get_message_ref(void) {
- kmq_message_ref * r;
-
- LPOP(&kmq_msg_ref_free, &r);
- if(!r) {
- r = PMALLOC(sizeof(kmq_message_ref));
- }
- ZeroMemory(r, sizeof(kmq_message_ref));
-
- r->msg = NULL;
- r->recipient = NULL;
-
- return r;
-}
-
-/*! \internal
- \brief Free a message ref object
- \note called with cs_kmq_msg_ref and cs_kmq_msg held */
-void kmqint_put_message_ref(kmq_message_ref * r) {
- if(!r)
- return;
- if(r->msg) {
- r->msg->refcount--;
- r->msg = NULL;
- }
- LPUSH(&kmq_msg_ref_free, r);
-}
-
-/*! \internal
- \brief Get the queue associated with the current thread
- \note Obtains ::cs_kmq_global
- */
-kmq_queue * kmqint_get_thread_queue(void) {
- kmq_queue * q;
-
- q = (kmq_queue *) TlsGetValue(kmq_tls_queue);
- if(!q) {
- kmqint_attach_this_thread();
- q = (kmq_queue *) TlsGetValue(kmq_tls_queue);
- }
-
- return q;
-}
-
-/*! \internal
- \brief Get the topmost message ref for a queue
- \note Obtains kmq_queue::cs
- */
-void kmqint_get_queue_message_ref(kmq_queue * q, kmq_message_ref ** r) {
- EnterCriticalSection(&q->cs);
-
- if (q->flags & KMQ_QUEUE_FLAG_DELETED) {
- *r = NULL;
- } else {
- QGET(q,r);
- if(QTOP(q))
- SetEvent(q->wait_o);
- }
-
- LeaveCriticalSection(&q->cs);
-}
-
-/*! \internal
- \brief Post a message to a queue
- \note Obtains ::cs_kmq_msg_ref, ::cs_kmq_msg, kmq_queue::cs
- */
-void kmqint_post_queue(kmq_queue * q, kmq_message *m) {
- kmq_message_ref *r;
-
- EnterCriticalSection(&q->cs);
- if (q->flags & KMQ_QUEUE_FLAG_DELETED) {
- LeaveCriticalSection(&q->cs);
- return;
- }
- LeaveCriticalSection(&q->cs);
-
- EnterCriticalSection(&cs_kmq_msg_ref);
- r = kmqint_get_message_ref();
- LeaveCriticalSection(&cs_kmq_msg_ref);
-
- r->msg = m;
- r->recipient = NULL;
-
- EnterCriticalSection(&cs_kmq_msg);
- m->refcount++;
- m->nSent++;
- LeaveCriticalSection(&cs_kmq_msg);
-
- EnterCriticalSection(&q->cs);
- QPUT(q,r);
- SetEvent(q->wait_o);
- LeaveCriticalSection(&q->cs);
-}
-
-/*! \internal
- \brief Post a message to a subscriber
- \note Obtains ::cs_kmq_msg_ref, ::cs_kmq_msg, kmq_queue::cs
- \note Should be called with ::cs_kmq_msg held
- */
-void kmqint_post(kmq_msg_subscription * s, kmq_message * m, khm_boolean try_send) {
- if(s->rcpt_type == KMQ_RCPTTYPE_CB) {
- kmq_queue *q;
- kmq_message_ref *r;
-
- q = s->queue;
-
- if(try_send && q->thread == GetCurrentThreadId()) {
- khm_int32 rv;
- /* we are sending a message from this thread to this
- thread. just call the recipient directly, bypassing
- the message queue. */
- m->refcount++;
- m->nSent++;
- if (IsBadCodePtr(s->recipient.cb)) {
- rv = KHM_ERROR_INVALID_OPERATION;
- } else {
- rv = s->recipient.cb(m->type, m->subtype,
- m->uparam, m->vparam);
- }
- m->refcount--;
- if(KHM_SUCCEEDED(rv))
- m->nCompleted++;
- else
- m->nFailed++;
- } else {
-
- EnterCriticalSection(&q->cs);
- if (q->flags & KMQ_QUEUE_FLAG_DELETED) {
- LeaveCriticalSection(&q->cs);
- return;
- }
- LeaveCriticalSection(&q->cs);
-
- EnterCriticalSection(&cs_kmq_msg_ref);
- r = kmqint_get_message_ref();
- LeaveCriticalSection(&cs_kmq_msg_ref);
-
- r->msg = m;
- r->recipient = s->recipient.cb;
-
- m->refcount++;
- m->nSent++;
-
- EnterCriticalSection(&q->cs);
- QPUT(q,r);
- SetEvent(q->wait_o);
- LeaveCriticalSection(&q->cs);
- }
- }
-
-#ifdef _WIN32
- else if(s->rcpt_type == KMQ_RCPTTYPE_HWND) {
- if(try_send &&
- GetCurrentThreadId() == GetWindowThreadProcessId(s->recipient.hwnd,
- NULL)) {
- /* kmqint_post does not know whether there are any other
- messages waiting to be posted at this point. Hence,
- simply sending the message is not the right thing to do
- as the recipient may incorrectly assume that the
- message has completed when (m->nCompleted + m->nFailed
- == m->nSent). Therefore, we only increment nSent after
- the message is sent. */
-
- m->refcount++;
-
- /* the kmq_wm_begin()/kmq_wm_end() and kmq_wm_dispatch()
- handlers decrement the reference count on the message
- when they are done. */
- SendMessage(s->recipient.hwnd, KMQ_WM_DISPATCH,
- m->type, (LPARAM) m);
-
- m->nSent++;
-
- } else {
- m->nSent++;
- m->refcount++;
-
- /* the kmq_wm_begin()/kmq_wm_end() and kmq_wm_dispatch()
- handlers decrement the reference count on the message
- when they are done. */
- PostMessage(s->recipient.hwnd, KMQ_WM_DISPATCH,
- m->type, (LPARAM) m);
- }
- }
-#endif
-
- else {
- /* This could either be because we were passed in an invalid
- subscription or because we lost a race to a thread that
- deleted an ad-hoc subscription. */
-#ifdef DEBUG
- assert(FALSE);
-#endif
- }
-}
-
-/*! \internal
- \brief Subscribes a window to a message type
- \note Obtains ::cs_kmq_types
- */
-KHMEXP khm_int32 KHMAPI kmq_subscribe_hwnd(khm_int32 type, HWND hwnd) {
- kmq_msg_subscription * s;
-
- s = PMALLOC(sizeof(kmq_msg_subscription));
- ZeroMemory(s, sizeof(*s));
- s->magic = KMQ_MSG_SUB_MAGIC;
- LINIT(s);
- s->queue = NULL;
- s->rcpt_type = KMQ_RCPTTYPE_HWND;
- s->recipient.hwnd = hwnd;
- kmqint_msg_type_add_sub(type, s);
-
- return KHM_ERROR_SUCCESS;
-}
-
-/*! \internal
- \note Obtains ::cs_kmq_types, ::cs_kmq_global
- */
-KHMEXP khm_int32 KHMAPI kmq_subscribe(khm_int32 type, kmq_callback_t cb) {
- kmq_msg_subscription * s;
-
- s = PMALLOC(sizeof(kmq_msg_subscription));
- ZeroMemory(s, sizeof(*s));
- s->magic = KMQ_MSG_SUB_MAGIC;
- LINIT(s);
- s->queue = kmqint_get_thread_queue();
- s->rcpt_type = KMQ_RCPTTYPE_CB;
- s->recipient.cb = cb;
- kmqint_msg_type_add_sub(type, s);
-
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP khm_int32 KHMAPI kmq_create_hwnd_subscription(HWND hw,
- khm_handle * result)
-{
- kmq_msg_subscription * s;
-
- s = PMALLOC(sizeof(kmq_msg_subscription));
- ZeroMemory(s, sizeof(*s));
- s->magic = KMQ_MSG_SUB_MAGIC;
- LINIT(s);
- s->queue = NULL;
- s->rcpt_type = KMQ_RCPTTYPE_HWND;
- s->recipient.hwnd = hw;
-
- EnterCriticalSection(&cs_kmq_global);
- LPUSH(&kmq_adhoc_subs, s);
- LeaveCriticalSection(&cs_kmq_global);
-
- *result = (khm_handle) s;
-
- return KHM_ERROR_SUCCESS;
-}
-
-/*! \internal
- \note Obtains ::cs_kmq_global
-*/
-KHMEXP khm_int32 KHMAPI kmq_create_subscription(kmq_callback_t cb,
- khm_handle * result)
-{
- kmq_msg_subscription * s;
-
- s = PMALLOC(sizeof(kmq_msg_subscription));
- ZeroMemory(s, sizeof(*s));
- s->magic = KMQ_MSG_SUB_MAGIC;
- LINIT(s);
- s->queue = kmqint_get_thread_queue();
- s->rcpt_type = KMQ_RCPTTYPE_CB;
- s->recipient.cb = cb;
-
- EnterCriticalSection(&cs_kmq_global);
- LPUSH(&kmq_adhoc_subs, s);
- LeaveCriticalSection(&cs_kmq_global);
-
- *result = (khm_handle) s;
-
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP khm_int32 KHMAPI kmq_delete_subscription(khm_handle sub)
-{
- kmq_msg_subscription * s;
-
- s = (kmq_msg_subscription *) sub;
-
- assert(s->magic == KMQ_MSG_SUB_MAGIC);
-
- s->type = 0;
-
- EnterCriticalSection(&cs_kmq_global);
- LDELETE(&kmq_adhoc_subs, s);
- LeaveCriticalSection(&cs_kmq_global);
-
- PFREE(s);
-
- return KHM_ERROR_SUCCESS;
-}
-
-/*! \internal
- \brief Unsubscribes a window from a message type
- \note Obtains ::cs_kmq_types
- */
-KHMEXP khm_int32 KHMAPI kmq_unsubscribe_hwnd(khm_int32 type, HWND hwnd) {
- kmq_msg_subscription * s;
-
- s = kmqint_msg_type_del_sub_hwnd(type, hwnd);
- if(s)
- PFREE(s);
- return (s)?KHM_ERROR_SUCCESS:KHM_ERROR_NOT_FOUND;
-}
-
-/*! \internal
- \brief Unsubscribe a callback from a message type
- \note Obtains ::cs_kmq_types, ::cs_kmq_global
- */
-KHMEXP khm_int32 KHMAPI kmq_unsubscribe(khm_int32 type, kmq_callback_t cb) {
- kmq_msg_subscription * s;
-
- s = kmqint_msg_type_del_sub_cb(type,cb);
- if(s)
- PFREE(s);
-
- return (s)?KHM_ERROR_SUCCESS:KHM_ERROR_NOT_FOUND;
-}
-
-KHMEXP LRESULT KHMAPI kmq_wm_begin(LPARAM lparm, kmq_message ** m) {
- *m = (kmq_message *) lparm;
- if ((*m)->err_ctx) {
- kherr_push_context((*m)->err_ctx);
- }
- return TRUE;
-}
-
-/*! \internal
- \note Obtains ::cs_kmq_msg
- */
-KHMEXP LRESULT KHMAPI kmq_wm_end(kmq_message *m, khm_int32 rv) {
- if (m->err_ctx)
- kherr_pop_context();
-
- EnterCriticalSection(&cs_kmq_msg);
- m->refcount--;
- if(KHM_SUCCEEDED(rv))
- m->nCompleted++;
- else
- m->nFailed++;
-
- if(m->nCompleted + m->nFailed == m->nSent) {
- kmqint_put_message(m);
- }
- LeaveCriticalSection(&cs_kmq_msg);
-
- return TRUE;
-}
-
-/*! \internal
- \note Obtains ::cs_kmq_msg
- */
-KHMEXP LRESULT KHMAPI kmq_wm_dispatch(LPARAM lparm, kmq_callback_t cb) {
- kmq_message *m;
- khm_int32 rv;
-
- m = (kmq_message *) lparm;
-
- if (m->err_ctx)
- kherr_push_context(m->err_ctx);
-
- rv = cb(m->type, m->subtype, m->uparam, m->vparam);
-
- if (m->err_ctx)
- kherr_pop_context();
-
- EnterCriticalSection(&cs_kmq_msg);
-
- m->refcount--;
- if(KHM_SUCCEEDED(rv))
- m->nCompleted++;
- else
- m->nFailed++;
-
- if(m->nCompleted + m->nFailed == m->nSent) {
- kmqint_put_message(m);
- }
- LeaveCriticalSection(&cs_kmq_msg);
-
- return TRUE;
-}
-
-KHMEXP khm_boolean KHMAPI kmq_is_call_aborted(void) {
- /* TODO: Implement this */
- return FALSE;
-}
-
-/*! \internal
-
- \note Obtains ::cs_kmq_global, kmq_queue::cs, ::cs_kmq_msg_ref, ::cs_kmq_msg,
-*/
-KHMEXP khm_int32 KHMAPI kmq_dispatch(kmq_timer timeout) {
- kmq_queue * q;
- kmq_message_ref * r;
- kmq_message *m;
- DWORD hr;
-
- q = kmqint_get_thread_queue();
-
- assert(q->wait_o);
-
- hr = WaitForSingleObject(q->wait_o, timeout);
- if(hr == WAIT_OBJECT_0) {
- /* signalled */
- kmqint_get_queue_message_ref(q, &r);
-
- m = r->msg;
-
- if(m->type != KMSG_SYSTEM || m->subtype != KMSG_SYSTEM_EXIT) {
- khm_boolean rv;
-
- if (m->err_ctx)
- kherr_push_context(m->err_ctx);
-
- /* TODO: before dispatching the message, the message being
- dispatched for this thread needs to be stored so that
- it can be looked up in kmq_is_call_aborted(). This
- needs to happen in kmq_wm_dispatch() and
- kmq_wm_begin() as well. */
-
- /* dispatch */
- rv = r->recipient(m->type, m->subtype, m->uparam, m->vparam);
-
- if (m->err_ctx)
- kherr_pop_context();
-
- EnterCriticalSection(&cs_kmq_msg);
- EnterCriticalSection(&cs_kmq_msg_ref);
- kmqint_put_message_ref(r);
- LeaveCriticalSection(&cs_kmq_msg_ref);
-
- if(KHM_SUCCEEDED(rv))
- m->nCompleted++;
- else
- m->nFailed++;
-
- if(m->nCompleted + m->nFailed == m->nSent) {
- kmqint_put_message(m);
- }
- LeaveCriticalSection(&cs_kmq_msg);
-
- return KHM_ERROR_SUCCESS;
- } else {
- EnterCriticalSection(&cs_kmq_msg);
- EnterCriticalSection(&cs_kmq_msg_ref);
- kmqint_put_message_ref(r);
- LeaveCriticalSection(&cs_kmq_msg_ref);
- m->nCompleted++;
- if(m->nCompleted + m->nFailed == m->nSent) {
- kmqint_put_message(m);
- }
- LeaveCriticalSection(&cs_kmq_msg);
-
- return KHM_ERROR_EXIT;
- }
- } else {
- return KHM_ERROR_TIMEOUT;
- }
-}
-
-/* TODO: rename this file to subscriber.c */
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<kmqinternal.h>
+#include<assert.h>
+
+DWORD kmq_tls_queue;
+
+CRITICAL_SECTION cs_kmq_msg_ref;
+
+kmq_message_ref * kmq_msg_ref_free = NULL;
+
+/* ad-hoc subscriptions */
+kmq_msg_subscription * kmq_adhoc_subs = NULL;
+
+#ifdef DEBUG
+
+#include<stdio.h>
+
+void
+kmqint_dump_consumer(FILE * f) {
+ kmq_message_ref * r;
+ kmq_msg_subscription * s;
+
+ int n_free = 0;
+ int n_adhoc = 0;
+
+ EnterCriticalSection(&cs_kmq_msg_ref);
+
+ fprintf(f, "qc0\t*** Free Message References ***\n");
+
+ fprintf(f, "qc1\tAddress\n");
+
+ r = kmq_msg_ref_free;
+ while(r) {
+ n_free ++;
+
+ fprintf(f, "qc2\t0x%p\n", r);
+
+ r = LNEXT(r);
+ }
+
+ fprintf(f, "qc3\tTotal free message references : %d\n", n_free);
+
+ fprintf(f, "qc4\t--- End ---\n");
+
+ LeaveCriticalSection(&cs_kmq_msg_ref);
+
+ EnterCriticalSection(&cs_kmq_global);
+
+ fprintf(f, "qc5\t*** Adhoc Message Subscriptions ***\n");
+
+ fprintf(f, "qc6\tAddress\tMsg Type\tRcpt Type\tRcpt\tQueue\n");
+
+ s = kmq_adhoc_subs;
+
+ while(s) {
+ n_adhoc ++;
+
+ fprintf(f, "qc7\t0x%p\t%d\t%s\t0x%p\t0x%p\n",
+ s,
+ s->type,
+ (s->rcpt_type == KMQ_RCPTTYPE_CB)?"CALLBACK":"HWND",
+ (s->rcpt_type == KMQ_RCPTTYPE_CB) ? (void *) s->recipient.cb: (void *) s->recipient.hwnd,
+ s->queue);
+
+ s = LNEXT(s);
+ }
+
+ fprintf(f, "qc8\tTotal ad-hoc subscriptions : %d\n", n_adhoc);
+
+ fprintf(f, "qc9\t--- End ---\n");
+
+ LeaveCriticalSection(&cs_kmq_global);
+
+}
+
+#endif
+
+/*! \internal
+ \brief Get a message ref object
+ \note called with cs_kmq_msg_ref held */
+kmq_message_ref * kmqint_get_message_ref(void) {
+ kmq_message_ref * r;
+
+ LPOP(&kmq_msg_ref_free, &r);
+ if(!r) {
+ r = PMALLOC(sizeof(kmq_message_ref));
+ }
+ ZeroMemory(r, sizeof(kmq_message_ref));
+
+ r->msg = NULL;
+ r->recipient = NULL;
+
+ return r;
+}
+
+/*! \internal
+ \brief Free a message ref object
+ \note called with cs_kmq_msg_ref and cs_kmq_msg held */
+void kmqint_put_message_ref(kmq_message_ref * r) {
+ if(!r)
+ return;
+ if(r->msg) {
+ r->msg->refcount--;
+ r->msg = NULL;
+ }
+ LPUSH(&kmq_msg_ref_free, r);
+}
+
+/*! \internal
+ \brief Get the queue associated with the current thread
+ \note Obtains ::cs_kmq_global
+ */
+kmq_queue * kmqint_get_thread_queue(void) {
+ kmq_queue * q;
+
+ q = (kmq_queue *) TlsGetValue(kmq_tls_queue);
+ if(!q) {
+ kmqint_attach_this_thread();
+ q = (kmq_queue *) TlsGetValue(kmq_tls_queue);
+ }
+
+ return q;
+}
+
+/*! \internal
+ \brief Get the topmost message ref for a queue
+ \note Obtains kmq_queue::cs
+ */
+void kmqint_get_queue_message_ref(kmq_queue * q, kmq_message_ref ** r) {
+ EnterCriticalSection(&q->cs);
+
+ if (q->flags & KMQ_QUEUE_FLAG_DELETED) {
+ *r = NULL;
+ } else {
+ QGET(q,r);
+ if(QTOP(q))
+ SetEvent(q->wait_o);
+ }
+
+ LeaveCriticalSection(&q->cs);
+}
+
+/*! \internal
+ \brief Post a message to a queue
+ \note Obtains ::cs_kmq_msg_ref, ::cs_kmq_msg, kmq_queue::cs
+ */
+void kmqint_post_queue(kmq_queue * q, kmq_message *m) {
+ kmq_message_ref *r;
+
+ EnterCriticalSection(&q->cs);
+ if (q->flags & KMQ_QUEUE_FLAG_DELETED) {
+ LeaveCriticalSection(&q->cs);
+ return;
+ }
+ LeaveCriticalSection(&q->cs);
+
+ EnterCriticalSection(&cs_kmq_msg_ref);
+ r = kmqint_get_message_ref();
+ LeaveCriticalSection(&cs_kmq_msg_ref);
+
+ r->msg = m;
+ r->recipient = NULL;
+
+ EnterCriticalSection(&cs_kmq_msg);
+ m->refcount++;
+ m->nSent++;
+ LeaveCriticalSection(&cs_kmq_msg);
+
+ EnterCriticalSection(&q->cs);
+ QPUT(q,r);
+ SetEvent(q->wait_o);
+ LeaveCriticalSection(&q->cs);
+}
+
+/*! \internal
+ \brief Post a message to a subscriber
+ \note Obtains ::cs_kmq_msg_ref, ::cs_kmq_msg, kmq_queue::cs
+ \note Should be called with ::cs_kmq_msg held
+ */
+void kmqint_post(kmq_msg_subscription * s, kmq_message * m, khm_boolean try_send) {
+ if(s->rcpt_type == KMQ_RCPTTYPE_CB) {
+ kmq_queue *q;
+ kmq_message_ref *r;
+
+ q = s->queue;
+
+ if(try_send && q->thread == GetCurrentThreadId()) {
+ khm_int32 rv;
+ /* we are sending a message from this thread to this
+ thread. just call the recipient directly, bypassing
+ the message queue. */
+ m->refcount++;
+ m->nSent++;
+ if (IsBadCodePtr(s->recipient.cb)) {
+ rv = KHM_ERROR_INVALID_OPERATION;
+ } else {
+ rv = s->recipient.cb(m->type, m->subtype,
+ m->uparam, m->vparam);
+ }
+ m->refcount--;
+ if(KHM_SUCCEEDED(rv))
+ m->nCompleted++;
+ else
+ m->nFailed++;
+ } else {
+
+ EnterCriticalSection(&q->cs);
+ if (q->flags & KMQ_QUEUE_FLAG_DELETED) {
+ LeaveCriticalSection(&q->cs);
+ return;
+ }
+ LeaveCriticalSection(&q->cs);
+
+ EnterCriticalSection(&cs_kmq_msg_ref);
+ r = kmqint_get_message_ref();
+ LeaveCriticalSection(&cs_kmq_msg_ref);
+
+ r->msg = m;
+ r->recipient = s->recipient.cb;
+
+ m->refcount++;
+ m->nSent++;
+
+ EnterCriticalSection(&q->cs);
+ QPUT(q,r);
+ SetEvent(q->wait_o);
+ LeaveCriticalSection(&q->cs);
+ }
+ }
+
+#ifdef _WIN32
+ else if(s->rcpt_type == KMQ_RCPTTYPE_HWND) {
+ if(try_send &&
+ GetCurrentThreadId() == GetWindowThreadProcessId(s->recipient.hwnd,
+ NULL)) {
+ /* kmqint_post does not know whether there are any other
+ messages waiting to be posted at this point. Hence,
+ simply sending the message is not the right thing to do
+ as the recipient may incorrectly assume that the
+ message has completed when (m->nCompleted + m->nFailed
+ == m->nSent). Therefore, we only increment nSent after
+ the message is sent. */
+
+ m->refcount++;
+
+ /* the kmq_wm_begin()/kmq_wm_end() and kmq_wm_dispatch()
+ handlers decrement the reference count on the message
+ when they are done. */
+ SendMessage(s->recipient.hwnd, KMQ_WM_DISPATCH,
+ m->type, (LPARAM) m);
+
+ m->nSent++;
+
+ } else {
+ m->nSent++;
+ m->refcount++;
+
+ /* the kmq_wm_begin()/kmq_wm_end() and kmq_wm_dispatch()
+ handlers decrement the reference count on the message
+ when they are done. */
+ PostMessage(s->recipient.hwnd, KMQ_WM_DISPATCH,
+ m->type, (LPARAM) m);
+ }
+ }
+#endif
+
+ else {
+ /* This could either be because we were passed in an invalid
+ subscription or because we lost a race to a thread that
+ deleted an ad-hoc subscription. */
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ }
+}
+
+/*! \internal
+ \brief Subscribes a window to a message type
+ \note Obtains ::cs_kmq_types
+ */
+KHMEXP khm_int32 KHMAPI kmq_subscribe_hwnd(khm_int32 type, HWND hwnd) {
+ kmq_msg_subscription * s;
+
+ s = PMALLOC(sizeof(kmq_msg_subscription));
+ ZeroMemory(s, sizeof(*s));
+ s->magic = KMQ_MSG_SUB_MAGIC;
+ LINIT(s);
+ s->queue = NULL;
+ s->rcpt_type = KMQ_RCPTTYPE_HWND;
+ s->recipient.hwnd = hwnd;
+ kmqint_msg_type_add_sub(type, s);
+
+ return KHM_ERROR_SUCCESS;
+}
+
+/*! \internal
+ \note Obtains ::cs_kmq_types, ::cs_kmq_global
+ */
+KHMEXP khm_int32 KHMAPI kmq_subscribe(khm_int32 type, kmq_callback_t cb) {
+ kmq_msg_subscription * s;
+
+ s = PMALLOC(sizeof(kmq_msg_subscription));
+ ZeroMemory(s, sizeof(*s));
+ s->magic = KMQ_MSG_SUB_MAGIC;
+ LINIT(s);
+ s->queue = kmqint_get_thread_queue();
+ s->rcpt_type = KMQ_RCPTTYPE_CB;
+ s->recipient.cb = cb;
+ kmqint_msg_type_add_sub(type, s);
+
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP khm_int32 KHMAPI kmq_create_hwnd_subscription(HWND hw,
+ khm_handle * result)
+{
+ kmq_msg_subscription * s;
+
+ s = PMALLOC(sizeof(kmq_msg_subscription));
+ ZeroMemory(s, sizeof(*s));
+ s->magic = KMQ_MSG_SUB_MAGIC;
+ LINIT(s);
+ s->queue = NULL;
+ s->rcpt_type = KMQ_RCPTTYPE_HWND;
+ s->recipient.hwnd = hw;
+
+ EnterCriticalSection(&cs_kmq_global);
+ LPUSH(&kmq_adhoc_subs, s);
+ LeaveCriticalSection(&cs_kmq_global);
+
+ *result = (khm_handle) s;
+
+ return KHM_ERROR_SUCCESS;
+}
+
+/*! \internal
+ \note Obtains ::cs_kmq_global
+*/
+KHMEXP khm_int32 KHMAPI kmq_create_subscription(kmq_callback_t cb,
+ khm_handle * result)
+{
+ kmq_msg_subscription * s;
+
+ s = PMALLOC(sizeof(kmq_msg_subscription));
+ ZeroMemory(s, sizeof(*s));
+ s->magic = KMQ_MSG_SUB_MAGIC;
+ LINIT(s);
+ s->queue = kmqint_get_thread_queue();
+ s->rcpt_type = KMQ_RCPTTYPE_CB;
+ s->recipient.cb = cb;
+
+ EnterCriticalSection(&cs_kmq_global);
+ LPUSH(&kmq_adhoc_subs, s);
+ LeaveCriticalSection(&cs_kmq_global);
+
+ *result = (khm_handle) s;
+
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP khm_int32 KHMAPI kmq_delete_subscription(khm_handle sub)
+{
+ kmq_msg_subscription * s;
+
+ s = (kmq_msg_subscription *) sub;
+
+ assert(s->magic == KMQ_MSG_SUB_MAGIC);
+
+ s->type = 0;
+
+ EnterCriticalSection(&cs_kmq_global);
+ LDELETE(&kmq_adhoc_subs, s);
+ LeaveCriticalSection(&cs_kmq_global);
+
+ PFREE(s);
+
+ return KHM_ERROR_SUCCESS;
+}
+
+/*! \internal
+ \brief Unsubscribes a window from a message type
+ \note Obtains ::cs_kmq_types
+ */
+KHMEXP khm_int32 KHMAPI kmq_unsubscribe_hwnd(khm_int32 type, HWND hwnd) {
+ kmq_msg_subscription * s;
+
+ s = kmqint_msg_type_del_sub_hwnd(type, hwnd);
+ if(s)
+ PFREE(s);
+ return (s)?KHM_ERROR_SUCCESS:KHM_ERROR_NOT_FOUND;
+}
+
+/*! \internal
+ \brief Unsubscribe a callback from a message type
+ \note Obtains ::cs_kmq_types, ::cs_kmq_global
+ */
+KHMEXP khm_int32 KHMAPI kmq_unsubscribe(khm_int32 type, kmq_callback_t cb) {
+ kmq_msg_subscription * s;
+
+ s = kmqint_msg_type_del_sub_cb(type,cb);
+ if(s)
+ PFREE(s);
+
+ return (s)?KHM_ERROR_SUCCESS:KHM_ERROR_NOT_FOUND;
+}
+
+KHMEXP LRESULT KHMAPI kmq_wm_begin(LPARAM lparm, kmq_message ** m) {
+ *m = (kmq_message *) lparm;
+ if ((*m)->err_ctx) {
+ kherr_push_context((*m)->err_ctx);
+ }
+ return TRUE;
+}
+
+/*! \internal
+ \note Obtains ::cs_kmq_msg
+ */
+KHMEXP LRESULT KHMAPI kmq_wm_end(kmq_message *m, khm_int32 rv) {
+ if (m->err_ctx)
+ kherr_pop_context();
+
+ EnterCriticalSection(&cs_kmq_msg);
+ m->refcount--;
+ if(KHM_SUCCEEDED(rv))
+ m->nCompleted++;
+ else
+ m->nFailed++;
+
+ if(m->nCompleted + m->nFailed == m->nSent) {
+ kmqint_put_message(m);
+ }
+ LeaveCriticalSection(&cs_kmq_msg);
+
+ return TRUE;
+}
+
+/*! \internal
+ \note Obtains ::cs_kmq_msg
+ */
+KHMEXP LRESULT KHMAPI kmq_wm_dispatch(LPARAM lparm, kmq_callback_t cb) {
+ kmq_message *m;
+ khm_int32 rv;
+
+ m = (kmq_message *) lparm;
+
+ if (m->err_ctx)
+ kherr_push_context(m->err_ctx);
+
+ rv = cb(m->type, m->subtype, m->uparam, m->vparam);
+
+ if (m->err_ctx)
+ kherr_pop_context();
+
+ EnterCriticalSection(&cs_kmq_msg);
+
+ m->refcount--;
+ if(KHM_SUCCEEDED(rv))
+ m->nCompleted++;
+ else
+ m->nFailed++;
+
+ if(m->nCompleted + m->nFailed == m->nSent) {
+ kmqint_put_message(m);
+ }
+ LeaveCriticalSection(&cs_kmq_msg);
+
+ return TRUE;
+}
+
+KHMEXP khm_boolean KHMAPI kmq_is_call_aborted(void) {
+ /* TODO: Implement this */
+ return FALSE;
+}
+
+/*! \internal
+
+ \note Obtains ::cs_kmq_global, kmq_queue::cs, ::cs_kmq_msg_ref, ::cs_kmq_msg,
+*/
+KHMEXP khm_int32 KHMAPI kmq_dispatch(kmq_timer timeout) {
+ kmq_queue * q;
+ kmq_message_ref * r;
+ kmq_message *m;
+ DWORD hr;
+
+ q = kmqint_get_thread_queue();
+
+ assert(q->wait_o);
+
+ hr = WaitForSingleObject(q->wait_o, timeout);
+ if(hr == WAIT_OBJECT_0) {
+ /* signalled */
+ kmqint_get_queue_message_ref(q, &r);
+
+ m = r->msg;
+
+ if(m->type != KMSG_SYSTEM || m->subtype != KMSG_SYSTEM_EXIT) {
+ khm_boolean rv;
+
+ if (m->err_ctx)
+ kherr_push_context(m->err_ctx);
+
+ /* TODO: before dispatching the message, the message being
+ dispatched for this thread needs to be stored so that
+ it can be looked up in kmq_is_call_aborted(). This
+ needs to happen in kmq_wm_dispatch() and
+ kmq_wm_begin() as well. */
+
+ /* dispatch */
+ rv = r->recipient(m->type, m->subtype, m->uparam, m->vparam);
+
+ if (m->err_ctx)
+ kherr_pop_context();
+
+ EnterCriticalSection(&cs_kmq_msg);
+ EnterCriticalSection(&cs_kmq_msg_ref);
+ kmqint_put_message_ref(r);
+ LeaveCriticalSection(&cs_kmq_msg_ref);
+
+ if(KHM_SUCCEEDED(rv))
+ m->nCompleted++;
+ else
+ m->nFailed++;
+
+ if(m->nCompleted + m->nFailed == m->nSent) {
+ kmqint_put_message(m);
+ }
+ LeaveCriticalSection(&cs_kmq_msg);
+
+ return KHM_ERROR_SUCCESS;
+ } else {
+ EnterCriticalSection(&cs_kmq_msg);
+ EnterCriticalSection(&cs_kmq_msg_ref);
+ kmqint_put_message_ref(r);
+ LeaveCriticalSection(&cs_kmq_msg_ref);
+ m->nCompleted++;
+ if(m->nCompleted + m->nFailed == m->nSent) {
+ kmqint_put_message(m);
+ }
+ LeaveCriticalSection(&cs_kmq_msg);
+
+ return KHM_ERROR_EXIT;
+ }
+ } else {
+ return KHM_ERROR_TIMEOUT;
+ }
+}
+
+/* TODO: rename this file to subscriber.c */
diff --git a/src/windows/identity/kmq/init.c b/src/windows/identity/kmq/init.c
index 875e3eaf3a..493780f798 100644
--- a/src/windows/identity/kmq/init.c
+++ b/src/windows/identity/kmq/init.c
@@ -1,313 +1,313 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<kmqinternal.h>
-#include<kconfig.h>
-#include<assert.h>
-
-CRITICAL_SECTION cs_kmq_global;
-kmq_timer kmq_queue_dead_timeout;
-kmq_timer kmq_call_dead_timeout;
-
-kmq_queue * queues;
-
-LONG kmq_init_once = 0;
-
-void kmqint_init(void) {
- khm_handle hconfig = NULL;
-
- queues = NULL;
-
- InitializeCriticalSection(&cs_kmq_global);
- InitializeCriticalSection(&cs_kmq_msg);
- InitializeCriticalSection(&cs_kmq_msg_ref);
-
- EnterCriticalSection(&cs_kmq_global);
- khc_load_schema(NULL, schema_kmqconfig);
- khc_open_space(NULL, KMQ_CONF_SPACE_NAME, KHM_PERM_READ, &hconfig);
- if(hconfig) {
- khm_int32 t = 0;
-
- khc_read_int32(hconfig, KMQ_CONF_QUEUE_DEAD_TIMEOUT_NAME, &t);
- kmq_queue_dead_timeout = t;
-
- khc_read_int32(hconfig, KMQ_CONF_CALL_DEAD_TIMEOUT_NAME, &t);
- kmq_call_dead_timeout = t;
-
- khc_close_space(hconfig);
- }
- kmqint_init_msg_types();
- LeaveCriticalSection(&cs_kmq_global);
-
- kmq_tls_queue = TlsAlloc();
-}
-
-void kmqint_exit(void) {
- EnterCriticalSection(&cs_kmq_global);
- kmqint_exit_msg_types();
- LeaveCriticalSection(&cs_kmq_global);
- DeleteCriticalSection(&cs_kmq_msg);
- DeleteCriticalSection(&cs_kmq_msg_ref);
- DeleteCriticalSection(&cs_kmq_global);
-
- TlsFree(kmq_tls_queue);
-}
-
-/*! \internal
- \brief Preps a thread for use with kmq
- \note Obtains ::cs_kmq_global
- */
-void kmqint_attach_this_thread(void) {
- kmq_queue * q;
-
- EnterCriticalSection(&cs_kmq_global);
-
- q = (kmq_queue *) TlsGetValue(kmq_tls_queue);
- if(!q) {
- q = PMALLOC(sizeof(kmq_queue));
-
- InitializeCriticalSection(&q->cs);
- q->thread = GetCurrentThreadId();
- QINIT(q);
- LINIT(q);
- q->wait_o = CreateEvent(NULL, FALSE, FALSE, NULL);
- q->load = 0;
- q->last_post = 0;
- q->flags = 0;
-
- LPUSH(&queues, q);
-
- TlsSetValue(kmq_tls_queue, (LPVOID) q);
- }
-
- LeaveCriticalSection(&cs_kmq_global);
-}
-
-/*! \internal
- \brief Detaches the current thread from kmq
- \note Obtains ::cs_kmq_global
- */
-void kmqint_detach_this_thread(void) {
- kmq_queue * q;
-
- q = (kmq_queue *) TlsGetValue(kmq_tls_queue);
- if(q) {
- kmq_message_ref * r;
- kmq_message * m;
-
- EnterCriticalSection(&q->cs);
-
- if (q->flags & KMQ_QUEUE_FLAG_DETACHING) {
-#ifdef DEBUG
- assert(FALSE);
-#endif
- LeaveCriticalSection(&q->cs);
- return;
- }
-
- q->flags |= KMQ_QUEUE_FLAG_DELETED | KMQ_QUEUE_FLAG_DETACHING;
-
- QGET(q, &r);
- while(r) {
-
- m = r->msg;
-
- LeaveCriticalSection(&q->cs);
-
- EnterCriticalSection(&cs_kmq_msg);
- EnterCriticalSection(&cs_kmq_msg_ref);
- kmqint_put_message_ref(r);
- LeaveCriticalSection(&cs_kmq_msg_ref);
-
- m->nFailed++;
- if(m->nCompleted + m->nFailed == m->nSent) {
- kmqint_put_message(m);
- }
- LeaveCriticalSection(&cs_kmq_msg);
-
- EnterCriticalSection(&q->cs);
-
- QGET(q, &r);
- }
-
- CloseHandle(q->wait_o);
-
- q->wait_o = NULL;
-
- q->flags &= ~KMQ_QUEUE_FLAG_DETACHING;
-
- LeaveCriticalSection(&q->cs);
-
- /* For now, we don't free the queue. */
-
- /* TODO: before we can free the queue, we have to go through
- all the message type subscriptions and ad-hoc subscriptions
- and make sure no subscriptions exist which refer to this
- message queue. */
- }
-}
-
-HANDLE kmq_h_compl = NULL;
-kmq_thread_id kmq_tid_compl;
-
-/* Message transfer */
-struct tag_kmq_msg_xfer {
- QDCL(kmq_message);
-} kmq_completion_xfer;
-
-HANDLE compl_wx;
-BOOL compl_continue;
-CRITICAL_SECTION cs_compl;
-
-DWORD WINAPI kmqint_completion_thread_proc(LPVOID p) {
- kmq_message * m;
- kherr_context * ctx;
-
- PDESCTHREAD(L"Msg completion thread", L"KMQ");
-
- EnterCriticalSection(&cs_compl);
- do {
-
- if (QTOP(&kmq_completion_xfer) == NULL) {
- LeaveCriticalSection(&cs_compl);
- WaitForSingleObject(compl_wx, INFINITE);
- EnterCriticalSection(&cs_compl);
- /* go through the loop again before checking the queue */
- } else {
- QGET(&kmq_completion_xfer, &m);
- LeaveCriticalSection(&cs_compl);
- EnterCriticalSection(&cs_kmq_msg);
-
- ctx = m->err_ctx;
-
- if (ctx)
- kherr_push_context(ctx);
-
- kmqint_put_message(m);
-
- if (ctx)
- kherr_pop_context();
-
- LeaveCriticalSection(&cs_kmq_msg);
- EnterCriticalSection(&cs_compl);
- }
-
- } while(compl_continue);
-
- LeaveCriticalSection(&cs_compl);
-
- ExitThread(0);
-
- /* not reached */
- return 0;
-}
-
-int kmqint_call_completion_handler(kmq_msg_completion_handler h,
- kmq_message * m) {
- if (h == NULL)
- return 0;
-
- /* We only dispatch to the completion thread if we are not the
- completion thread. If calling the completion handler results
- in more messages completing, then we just call the completion
- handler directly. We also make an exception for completions
- that happen before the message queue is properly intiailized. */
-
- if (kmq_tid_compl != GetCurrentThreadId() &&
- kmq_h_compl != NULL) {
-
- EnterCriticalSection(&cs_compl);
- QPUT(&kmq_completion_xfer, m);
- SetEvent(compl_wx);
- LeaveCriticalSection(&cs_compl);
-
- return 1;
-
- } else {
- h(m);
-
- return 0;
- }
-}
-
-KHMEXP khm_int32 KHMAPI kmq_init(void) {
- if (InterlockedIncrement(&kmq_init_once) == 1) {
- EnterCriticalSection(&cs_kmq_global);
-
- InitializeCriticalSection(&cs_compl);
- compl_wx = CreateEvent(NULL, FALSE, FALSE, NULL);
- compl_continue = TRUE;
- QINIT(&kmq_completion_xfer);
-
- kmq_h_compl = CreateThread(NULL,
- 0,
- kmqint_completion_thread_proc,
- NULL,
- 0,
- &kmq_tid_compl);
-
- assert(kmq_h_compl != NULL);
-
- LeaveCriticalSection(&cs_kmq_global);
- }
-
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP khm_int32 KHMAPI kmq_exit(void) {
- if (InterlockedDecrement(&kmq_init_once) == 0) {
-
- EnterCriticalSection(&cs_compl);
- compl_continue = FALSE;
- SetEvent(compl_wx);
- LeaveCriticalSection(&cs_compl);
-
- WaitForSingleObject(kmq_h_compl, INFINITE);
-
- EnterCriticalSection(&cs_kmq_global);
- CloseHandle(kmq_h_compl);
- kmq_h_compl = NULL;
- kmq_tid_compl = 0;
- CloseHandle(compl_wx);
- DeleteCriticalSection(&cs_compl);
- LeaveCriticalSection(&cs_kmq_global);
- }
-
- return KHM_ERROR_SUCCESS;
-}
-
-#ifdef DEBUG
-
-void kmqint_dump_consumer(FILE * f);
-void kmqint_dump_publisher(FILE * f);
-
-
-KHMEXP void KHMAPI kmqint_dump(FILE * f) {
- kmqint_dump_consumer(f);
- kmqint_dump_publisher(f);
-}
-
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<kmqinternal.h>
+#include<kconfig.h>
+#include<assert.h>
+
+CRITICAL_SECTION cs_kmq_global;
+kmq_timer kmq_queue_dead_timeout;
+kmq_timer kmq_call_dead_timeout;
+
+kmq_queue * queues;
+
+LONG kmq_init_once = 0;
+
+void kmqint_init(void) {
+ khm_handle hconfig = NULL;
+
+ queues = NULL;
+
+ InitializeCriticalSection(&cs_kmq_global);
+ InitializeCriticalSection(&cs_kmq_msg);
+ InitializeCriticalSection(&cs_kmq_msg_ref);
+
+ EnterCriticalSection(&cs_kmq_global);
+ khc_load_schema(NULL, schema_kmqconfig);
+ khc_open_space(NULL, KMQ_CONF_SPACE_NAME, KHM_PERM_READ, &hconfig);
+ if(hconfig) {
+ khm_int32 t = 0;
+
+ khc_read_int32(hconfig, KMQ_CONF_QUEUE_DEAD_TIMEOUT_NAME, &t);
+ kmq_queue_dead_timeout = t;
+
+ khc_read_int32(hconfig, KMQ_CONF_CALL_DEAD_TIMEOUT_NAME, &t);
+ kmq_call_dead_timeout = t;
+
+ khc_close_space(hconfig);
+ }
+ kmqint_init_msg_types();
+ LeaveCriticalSection(&cs_kmq_global);
+
+ kmq_tls_queue = TlsAlloc();
+}
+
+void kmqint_exit(void) {
+ EnterCriticalSection(&cs_kmq_global);
+ kmqint_exit_msg_types();
+ LeaveCriticalSection(&cs_kmq_global);
+ DeleteCriticalSection(&cs_kmq_msg);
+ DeleteCriticalSection(&cs_kmq_msg_ref);
+ DeleteCriticalSection(&cs_kmq_global);
+
+ TlsFree(kmq_tls_queue);
+}
+
+/*! \internal
+ \brief Preps a thread for use with kmq
+ \note Obtains ::cs_kmq_global
+ */
+void kmqint_attach_this_thread(void) {
+ kmq_queue * q;
+
+ EnterCriticalSection(&cs_kmq_global);
+
+ q = (kmq_queue *) TlsGetValue(kmq_tls_queue);
+ if(!q) {
+ q = PMALLOC(sizeof(kmq_queue));
+
+ InitializeCriticalSection(&q->cs);
+ q->thread = GetCurrentThreadId();
+ QINIT(q);
+ LINIT(q);
+ q->wait_o = CreateEvent(NULL, FALSE, FALSE, NULL);
+ q->load = 0;
+ q->last_post = 0;
+ q->flags = 0;
+
+ LPUSH(&queues, q);
+
+ TlsSetValue(kmq_tls_queue, (LPVOID) q);
+ }
+
+ LeaveCriticalSection(&cs_kmq_global);
+}
+
+/*! \internal
+ \brief Detaches the current thread from kmq
+ \note Obtains ::cs_kmq_global
+ */
+void kmqint_detach_this_thread(void) {
+ kmq_queue * q;
+
+ q = (kmq_queue *) TlsGetValue(kmq_tls_queue);
+ if(q) {
+ kmq_message_ref * r;
+ kmq_message * m;
+
+ EnterCriticalSection(&q->cs);
+
+ if (q->flags & KMQ_QUEUE_FLAG_DETACHING) {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ LeaveCriticalSection(&q->cs);
+ return;
+ }
+
+ q->flags |= KMQ_QUEUE_FLAG_DELETED | KMQ_QUEUE_FLAG_DETACHING;
+
+ QGET(q, &r);
+ while(r) {
+
+ m = r->msg;
+
+ LeaveCriticalSection(&q->cs);
+
+ EnterCriticalSection(&cs_kmq_msg);
+ EnterCriticalSection(&cs_kmq_msg_ref);
+ kmqint_put_message_ref(r);
+ LeaveCriticalSection(&cs_kmq_msg_ref);
+
+ m->nFailed++;
+ if(m->nCompleted + m->nFailed == m->nSent) {
+ kmqint_put_message(m);
+ }
+ LeaveCriticalSection(&cs_kmq_msg);
+
+ EnterCriticalSection(&q->cs);
+
+ QGET(q, &r);
+ }
+
+ CloseHandle(q->wait_o);
+
+ q->wait_o = NULL;
+
+ q->flags &= ~KMQ_QUEUE_FLAG_DETACHING;
+
+ LeaveCriticalSection(&q->cs);
+
+ /* For now, we don't free the queue. */
+
+ /* TODO: before we can free the queue, we have to go through
+ all the message type subscriptions and ad-hoc subscriptions
+ and make sure no subscriptions exist which refer to this
+ message queue. */
+ }
+}
+
+HANDLE kmq_h_compl = NULL;
+kmq_thread_id kmq_tid_compl;
+
+/* Message transfer */
+struct tag_kmq_msg_xfer {
+ QDCL(kmq_message);
+} kmq_completion_xfer;
+
+HANDLE compl_wx;
+BOOL compl_continue;
+CRITICAL_SECTION cs_compl;
+
+DWORD WINAPI kmqint_completion_thread_proc(LPVOID p) {
+ kmq_message * m;
+ kherr_context * ctx;
+
+ PDESCTHREAD(L"Msg completion thread", L"KMQ");
+
+ EnterCriticalSection(&cs_compl);
+ do {
+
+ if (QTOP(&kmq_completion_xfer) == NULL) {
+ LeaveCriticalSection(&cs_compl);
+ WaitForSingleObject(compl_wx, INFINITE);
+ EnterCriticalSection(&cs_compl);
+ /* go through the loop again before checking the queue */
+ } else {
+ QGET(&kmq_completion_xfer, &m);
+ LeaveCriticalSection(&cs_compl);
+ EnterCriticalSection(&cs_kmq_msg);
+
+ ctx = m->err_ctx;
+
+ if (ctx)
+ kherr_push_context(ctx);
+
+ kmqint_put_message(m);
+
+ if (ctx)
+ kherr_pop_context();
+
+ LeaveCriticalSection(&cs_kmq_msg);
+ EnterCriticalSection(&cs_compl);
+ }
+
+ } while(compl_continue);
+
+ LeaveCriticalSection(&cs_compl);
+
+ ExitThread(0);
+
+ /* not reached */
+ return 0;
+}
+
+int kmqint_call_completion_handler(kmq_msg_completion_handler h,
+ kmq_message * m) {
+ if (h == NULL)
+ return 0;
+
+ /* We only dispatch to the completion thread if we are not the
+ completion thread. If calling the completion handler results
+ in more messages completing, then we just call the completion
+ handler directly. We also make an exception for completions
+ that happen before the message queue is properly intiailized. */
+
+ if (kmq_tid_compl != GetCurrentThreadId() &&
+ kmq_h_compl != NULL) {
+
+ EnterCriticalSection(&cs_compl);
+ QPUT(&kmq_completion_xfer, m);
+ SetEvent(compl_wx);
+ LeaveCriticalSection(&cs_compl);
+
+ return 1;
+
+ } else {
+ h(m);
+
+ return 0;
+ }
+}
+
+KHMEXP khm_int32 KHMAPI kmq_init(void) {
+ if (InterlockedIncrement(&kmq_init_once) == 1) {
+ EnterCriticalSection(&cs_kmq_global);
+
+ InitializeCriticalSection(&cs_compl);
+ compl_wx = CreateEvent(NULL, FALSE, FALSE, NULL);
+ compl_continue = TRUE;
+ QINIT(&kmq_completion_xfer);
+
+ kmq_h_compl = CreateThread(NULL,
+ 0,
+ kmqint_completion_thread_proc,
+ NULL,
+ 0,
+ &kmq_tid_compl);
+
+ assert(kmq_h_compl != NULL);
+
+ LeaveCriticalSection(&cs_kmq_global);
+ }
+
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP khm_int32 KHMAPI kmq_exit(void) {
+ if (InterlockedDecrement(&kmq_init_once) == 0) {
+
+ EnterCriticalSection(&cs_compl);
+ compl_continue = FALSE;
+ SetEvent(compl_wx);
+ LeaveCriticalSection(&cs_compl);
+
+ WaitForSingleObject(kmq_h_compl, INFINITE);
+
+ EnterCriticalSection(&cs_kmq_global);
+ CloseHandle(kmq_h_compl);
+ kmq_h_compl = NULL;
+ kmq_tid_compl = 0;
+ CloseHandle(compl_wx);
+ DeleteCriticalSection(&cs_compl);
+ LeaveCriticalSection(&cs_kmq_global);
+ }
+
+ return KHM_ERROR_SUCCESS;
+}
+
+#ifdef DEBUG
+
+void kmqint_dump_consumer(FILE * f);
+void kmqint_dump_publisher(FILE * f);
+
+
+KHMEXP void KHMAPI kmqint_dump(FILE * f) {
+ kmqint_dump_consumer(f);
+ kmqint_dump_publisher(f);
+}
+
+#endif
diff --git a/src/windows/identity/kmq/kmq.h b/src/windows/identity/kmq/kmq.h
index 46ce74f3b2..d1a3db3c2d 100644
--- a/src/windows/identity/kmq/kmq.h
+++ b/src/windows/identity/kmq/kmq.h
@@ -1,701 +1,701 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#ifndef __KHIMAIRA_KMQ_H__
-#define __KHIMAIRA_KMQ_H__
-
-/*! \defgroup kmq NetIDMgr Message Queue */
-/*@{*/
-
-#include<khdefs.h>
-#include<khlist.h>
-#include<kherr.h>
-
-/* general */
-#ifdef _WIN32
-typedef DWORD kmq_thread_id;
-typedef DWORD kmq_timer;
-#endif
-
-#ifdef _WIN32
-/*! \brief Window message for kmq
-
- This message is sent to the window procedure of a window if that
- window is a subscriber to KMQ messages.
-
- \see kmq_subscribe_hwnd() for more information about handling this
- window message
- */
-#define KMQ_WM_DISPATCH (WM_APP+0x100)
-#endif
-
-/* callback */
-
-/*! \brief A message callback
-
- Should return TRUE if the message is properly handled. Otherwise
- return FALSE */
-typedef khm_int32 (KHMAPI *kmq_callback_t)(khm_int32 msg_type,
- khm_int32 msg_sub_type,
- khm_ui_4 uparam,
- void * vparam);
-
-/* message */
-
-/*! \brief A single response.
-
- Certain broadcast messages may user scatter-gather type
- notification and result gathering. Individual subscribers to a
- message attach their individual responses to a ::kmq_response
- object and attach that to the message which can later be read by
- the sender of the message.
- */
-typedef struct tag_kmq_response {
- kmq_thread_id thread;
- void * response;
-
- LDCL(struct tag_kmq_response);
-} kmq_response;
-
-/*! \brief A single message
- */
-typedef struct tag_kmq_message {
- khm_int32 type; /*!< Type of message */
- khm_int32 subtype; /*!< Subtype of message */
-
- khm_ui_4 uparam; /*!< Integer parameter */
- void * vparam; /*!< Pointer to parameter blob */
-
- khm_int32 nSent; /*!< Number of instances of message
- sent (for broadcast messages) */
-
- khm_int32 nCompleted; /*!< Number of instances that have
- completed processing (for broadcast
- messages) */
-
- khm_int32 nFailed; /*!< Number of instances that failed
- to process (for broadcast
- messages) */
-
- kmq_response * responses; /*!< List of responses */
- HANDLE wait_o; /*!< Event to wait on (only valid if
- the publisher of the message
- requested a handle to the call) */
-
- kmq_timer timeSent; /*!< Time at which the message was
- sent */
- kmq_timer timeExpire; /*!< Time at which the message
- expires */
-
- kherr_context * err_ctx; /*!< Error context for the message */
-
- khm_boolean aborted; /*!< TRUE if the message has been
- aborted. */
-
- khm_int32 refcount; /*!< Internal use */
-
- LDCL(struct tag_kmq_message); /*!< Internal use */
-} kmq_message;
-
-/*! \brief A handle to a call
- */
-typedef kmq_message *kmq_call;
-
-/* publishers */
-
-/*! \brief A completion handler for a message
-
- Each message type can have a completion handler. Once a message
- of this a specific type has been broadcast and handled by all the
- subscripbers, the message will be passed down to the completion
- handler before the associated data structures are freed. This
- allows applications that define message type to also define clean
- up for each message. For example, the completion handler can
- initiate another message if the messages form a sequence or free
- up blocks of memory that was passed as the parameter to the
- message.
- */
-typedef void (KHMAPI *kmq_msg_completion_handler)(kmq_message *);
-
-#ifdef NOEXPORT
-
-KHMEXP khm_int32 KHMAPI kmq_init(void);
-
-KHMEXP khm_int32 KHMAPI kmq_exit(void);
-
-#endif
-
-/*! \brief Register a message type
-
- Registers a custom message type. The \a name parameter specifies
- a language independent name for the message type and must be
- unique and must be less than ::KMQ_MAXCCH_TYPE_NAME characters.
-
- \param[in] name Name of the message type. Upto
- ::KMQ_MAXCCH_TYPE_NAME characters including terminating NULL.
- The \a name cannot be a zero length string.
-
- \param[out] new_id Receives the new message type ID. Specify NULL
- if the new message type is not required.
-
- \see kmq_find_type() and kmq_unregister_type()
-
- \retval KHM_ERROR_INVALID_PARAM The \a name parameter was invalid.
- \retval KHM_ERROR_EXISTS A message type with that name already exists.
- \retval KHM_ERROR_NO_RESOURCES Can't register any more message types.
- \retval KHM_ERROR_SUCCESS The operation succeeded.
- */
-KHMEXP khm_int32 KHMAPI kmq_register_type(wchar_t * name, khm_int32 * new_id);
-
-/*! \brief Find a message type
-
- Find the message type with the given name. If found, the type ID
- is returned in \a id.
-
- \retval KHM_ERROR_SUCCESS A message type with the given name was
- found.
- \retval KHM_ERROR_NOT_FOUND A message type with the given name was
- not found.
- */
-KHMEXP khm_int32 KHMAPI kmq_find_type(wchar_t * name, khm_int32 * id);
-
-/*! \brief Unregister a message type
-
- Unregisters a message type that was registered using
- kmq_register_type().
-
- \retval KHM_ERROR_SUCCESS The specified message type was
- successfully unregistered.
-
- \retval KHM_ERROR_NOT_FOUND The message type was not found.
- */
-KHMEXP khm_int32 KHMAPI kmq_unregister_type(khm_int32 id);
-
-/*! \brief Subscribte to a message type.
-
- Adds a subscription to messages of type \a type. Subscriptions
- are managed per thread. Therefore the subscription is actually
- added to the subscription list for the current thread (the thread
- which calls kmq_subscribe()).
-
- When a message of type \a type is received by the thread, it is
- dispatched to the callback function identified by \a cb within the
- context of this thread.
-
- \note Calling kmq_subscribe() from within multiple threads with
- the same \a type and \a cb will result in multiple
- subscriptions.
-
- \see kmq_unsubscribe()
- \see kmq_dispatch()
-*/
-KHMEXP khm_int32 KHMAPI kmq_subscribe(khm_int32 type, kmq_callback_t cb);
-
-/*! \brief Subscribe a window to a message type
-
- Adds the window specified by \a hwnd to the subscription list for
- the message type \a type. When a message of this type is posted,
- then the window procedure of the window \a hwnd receives a message
- ::KMQ_WM_DISPATCH.
-
- When a window receives a ::KMQ_WM_DISPATCH message, it means that
- a message has been posted which is of a type that the window has
- subscribed for. Because of the way Windows handles window
- messages and the way NetIDMgr message queues work, a thread which
- has a window (or thread) procedure can not call kmq_dispatch() to
- handle these messages. For threads that have window or thread
- message loops, they must call kmq_subscribe_hwnd() to subscribe a
- particular window (for thread message loops, this would be the
- HWND of the message window for the thread) to NetIDMgr messages.
-
- There are two supported ways of handling the ::KMQ_WM_DISPATCH
- message. Examples of both are provided below.
-
- Handling the message inline:
-
- \code
- LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
- kmq_message * m;
- khm_int32 rv;
- ...
- switch(uMsg) {
- case WM_CREATE:
- ...
- kmq_subscribe_hwnd(KMSG_CRED, hwnd);
- ...
- break;
-
- case WM_DESTROY:
- ...
- kmq_unsubscribe_hwnd(KMSG_CRED, hwnd);
- ...
- break;
-
- ...
- case KMQ_WM_DISPATCH:
- kmq_wm_begin(lParam,&m);
-
- if(m->type == KMSG_CRED && m->subtype == KMSG_CRED_ROOTDELTA) {
- // do something
- rv = KHM_ERROR_SUCCESS;
- }
-
- return kmq_wm_end(m, rv);
- ...
- };
- ...
- }
- \endcode
-
- The other method is to dispatch the ::KMQ_WM_DISPATCH message to a
- secondary callback function:
-
- \code
- khm_int32 msg_handler(khm_int32 t, khm_int32 st, khm_ui_4 up, void * pb) {
- khm_int32 rv = KHM_ERROR_SUCCESS;
-
- //handle message
-
- return rv;
- }
-
- LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
- kmq_message * m;
- khm_int32 rv;
- ...
- switch(uMsg) {
- ...
-
- case WM_CREATE:
- ...
- kmq_subscribe_hwnd(KMSG_CRED, hwnd);
- ...
- break;
-
- case WM_DESTROY:
- ...
- kmq_unsubscribe_hwnd(KMSG_CRED, hwnd);
- ...
- break;
-
- ...
- case KMQ_WM_DISPATCH:
- return kmq_wm_dispatch(lParam, msg_handler);
- ...
- };
- ...
- }
- \endcode
-
- \note Make sure you unsubscribe from the message type when the
- window is destroyed.
-
- \see kmq_unsubscribe_hwnd()
- \see kmq_wm_begin()
- \see kmq_wm_end()
- \see kmq_wm_dispatch()
- */
-KHMEXP khm_int32 KHMAPI kmq_subscribe_hwnd(khm_int32 type, HWND hwnd);
-
-#ifdef _WIN32
-/*! \brief Begins handling a KMQ_WM_DISPATCH message
-
- \return The return value of this function should be ignored.
-
- \see kmq_subscribe_hwnd() for more details about handling ::KMQ_WM_DISPATCH
- */
-KHMEXP LRESULT KHMAPI kmq_wm_begin(LPARAM lparm, kmq_message ** m);
-
-/*! \brief Ends handling a KMQ_WM_DISPATCH message
-
- \return The return value of this function should be the return
- value of the window procedure. See kmq_subscribe_hwnd()
- documentation for example
-
- \see kmq_subscribe_hwnd() for more details about handling ::KMQ_WM_DISPATCH
- */
-KHMEXP LRESULT KHMAPI kmq_wm_end(kmq_message *m, khm_int32 rv);
-
-/*! \brief Dispatches a KMQ_WM_DISPATCH message to a callback
-
- \return The return value of this function should be the return
- value of the window procedure. See kmq_subscribe_hwnd()
- documentation for example.
-
- \see kmq_subscribe_hwnd() for more details about handling ::KMQ_WM_DISPATCH
- */
-KHMEXP LRESULT KHMAPI kmq_wm_dispatch(LPARAM lparm, kmq_callback_t cb);
-#endif
-
-/*! \brief Unsubscribe a callback from a message type
-
- Removes the subscription for message type \a type for callback
- function \a cb from the subscription list for the current thread
- (the thread that calls kmq_unsubscribe()).
-
- \note kmq_unsubscribe() can only remove subscriptions for the subscription
- list for the current thread.
-
- \see kmq_subscribe()
- \see kmq_dispatch()
-*/
-KHMEXP khm_int32 KHMAPI kmq_unsubscribe(khm_int32 type, kmq_callback_t cb);
-
-/*! \brief Unsubscribe a window from a message type
-
- Removes the specific window from the subsription list for message
- type \a type.
-
- \see kmq_subscribe_hwnd()
-*/
-KHMEXP khm_int32 KHMAPI kmq_unsubscribe_hwnd(khm_int32 type, HWND hwnd);
-
-/*! \brief Create an ad-hoc subscription
-
- An ad-hoc subscription describes a callback point in a thread that
- can be dispatched messages to individually without broadcasting.
-
- \see kmq_post_sub_msg(), kmq_post_sub_msg_ex(),
- kmq_send_sub_msg(), kmq_post_subs_msg(),
- kmq_post_subs_msg_ex(), kmq_send_subs_msg(),
- kmq_delete_subscription()
-*/
-KHMEXP khm_int32 KHMAPI kmq_create_subscription(
- kmq_callback_t cb,
- khm_handle * result);
-
-/*! \brief Create an ad-hoc subscription for a window
-
- An ad-hoc subscription describes a window that will be dispatched
- messages individually without broadcasting.
-
- \see kmq_post_sub_msg(), kmq_post_sub_msg_ex(),
- kmq_send_sub_msg(), kmq_post_subs_msg(),
- kmq_post_subs_msg_ex(), kmq_send_subs_msg(),
- kmq_delete_subscription()
- */
-KHMEXP khm_int32 KHMAPI kmq_create_hwnd_subscription(HWND hw,
- khm_handle * result);
-
-/*! \brief Delete an ad-hoc subscription
-
- Deletes a subscriptoin that was created using
- kmq_create_subscription()
- */
-KHMEXP khm_int32 KHMAPI kmq_delete_subscription(khm_handle sub);
-
-/*! \brief Post a message to a subscription
-
- Equivalent of kmq_post_msg() but only posts the message to the
- specified subscription.
- */
-KHMEXP khm_int32 KHMAPI kmq_post_sub_msg(
- khm_handle sub,
- khm_int32 type,
- khm_int32 subtype,
- khm_ui_4 uparam,
- void * vparam);
-
-/*! \brief Post a message to a subscription and acquire a handle to the call
- */
-KHMEXP khm_int32 KHMAPI kmq_post_sub_msg_ex(
- khm_handle sub,
- khm_int32 type,
- khm_int32 subtype,
- khm_ui_4 uparam,
- void * vparam,
- kmq_call * call);
-
-/*! \brief Send a synchronous message to a subscription
-
- \retval KHM_ERROR_SUCCESS The call succeeded, and no subscribers reported errors
- \retval KHM_ERROR_PARTIAL The call succeeded, but at least one subscriber reported errors
- */
-KHMEXP khm_int32 KHMAPI kmq_send_sub_msg(
- khm_handle sub,
- khm_int32 type,
- khm_int32 subtype,
- khm_ui_4 uparam,
- void * vparam);
-
-/*! \brief Post a message to a group of subscriptions
-
- The block of memory pointed to by \a subs should be an array of
- subscriptions. The number of elements in that array should be \a
- n_subs. A message as specified by the remaining parameters will
- be dispatched to all of the subscription points in the array.
- */
-KHMEXP khm_int32 KHMAPI kmq_post_subs_msg(
- khm_handle * subs,
- khm_size n_subs,
- khm_int32 type,
- khm_int32 subtype,
- khm_ui_4 uparam,
- void * vparam);
-
-/*! \brief Post a message to a group of subscriptions and acquire a handle to the call
-
- The block of memory pointed to by \a subs should be an array of
- subscriptions. The number of elements in that array should be \a
- n_subs. A message as specified by the remaining parameters will
- be dispatched to all of the subscription points in the array, and
- a handle to the call will be returned in \a call.
-
- The returned \a call will reference all of the dispatches that
- were made.
-*/
-KHMEXP khm_int32 KHMAPI kmq_post_subs_msg_ex(
- khm_handle * subs,
- khm_int32 n_subs,
- khm_int32 type,
- khm_int32 subtype,
- khm_ui_4 uparam,
- void * vparam,
- kmq_call * call);
-
-/*! \brief Send a synchronous message to a group of subscriptions
-
- The block of memory pointed to by \a subs should be an array of
- subscriptions. The number of elements in that array should be \a
- n_subs. A message as specified by the remaining parameters will
- be dispatched to all of the subscription points in the array. The
- function will not return until all of the calls have succeeded.
-
- \retval KHM_ERROR_SUCCESS The call succeeded, and no subscribers reported errors
- \retval KHM_ERROR_PARTIAL The call succeeded, but at least one subscriber reported errors
-*/
-KHMEXP khm_int32 KHMAPI kmq_send_subs_msg(
- khm_handle *subs,
- khm_int32 n_subs,
- khm_int32 type,
- khm_int32 subtype,
- khm_ui_4 uparam,
- void * vparam);
-
-/*! \brief Dispatch a message for the current thread.
-
- This function opens the message list for the current thread and
- dispatches the first message instance that is found. Note that if
- multiple callbacks subscribe to the same message type in the same
- thread, then when a message of that type is received, multiple
- message instances are added to the message queue corresponding to
- each subscription.
-
- If no message instances are waiting in the queue, kmq_dispatch()
- waits for the \a timeout period for a message.
-
- \param[in] timeout The timeout period in milliseconds. Specify INFINITE for
- kmq_dispatch() to wait indefinitely.
-
- \retval KHM_ERROR_SUCCESS A message instance was dispatched
- \retval KHM_ERROR_TIMEOUT The timeout period elapsed
- \retval KHM_ERROR_EXIT The message found on the queue was <KMSG_SYSTEM,KMSG_SYSTEM_EXIT>
-*/
-KHMEXP khm_int32 KHMAPI kmq_dispatch(kmq_timer timeout);
-
-/*! \brief Send a message
-
- The specified message will be posted to all the subscribers of the
- message type. Then the function will wait for all the subscribers
- to finish processing the message before returning.
-
- \param[in] type The type of the message
- \param[in] subtype The subtype
- \param[in] uparam The khm_ui_4 parameter for the message
- \param[in] blob The parameter blob for the message
-
- \note The internal timeout for this function is INFINITE. If you
- it is desirable to use a different timeout, use
- kmq_post_message_ex() and kmq_wait() functions.
-
- \retval KHM_ERROR_SUCCESS The call succeeded and no subscribers returned errors
- \retval KHM_ERROR_PARTIAL The call succeeded but at least one subscriber returned an error
-*/
-KHMEXP khm_int32 KHMAPI kmq_send_message(
- khm_int32 type,
- khm_int32 subtype,
- khm_ui_4 uparam,
- void * blob);
-
-/*! \brief Post a message
-
- The specified message will be posted to all the subscribers of the
- message type. The function returns immediately.
-
- If you want to be able to wait for all the subscribers to finish
- processing the message, you should use kmq_post_message_ex()
- instead.
-
- \param[in] type The type of the message
- \param[in] subtype The subtype
- \param[in] uparam The khm_ui_4 parameter for the message
- \param[in] blob The parameter blob for the message
-*/
-KHMEXP khm_int32 KHMAPI kmq_post_message(
- khm_int32 type,
- khm_int32 subtype,
- khm_ui_4 uparam,
- void * blob);
-
-/*! \brief Post a message and acquire a handle to the call.
-
- The specified message is posted to all the subscribers. In
- addition, a handle is obtained for the call which can be used in
- subsequent call to kmq_free_call() or kmq_wait().
-
- Call kmq_free_call() to free the handle.
-
- \param[in] type The type of the message
- \param[in] subtype The subtype
- \param[in] uparam The khm_ui_4 parameter for the message
- \param[in] blob The parameter blob for the message
- \param[out] call Receives the call handle. Set to NULL if the call handle is not required.
-
- \see kmq_free_call()
-*/
-KHMEXP khm_int32 KHMAPI kmq_post_message_ex(
- khm_int32 type,
- khm_int32 subtype,
- khm_ui_4 uparam,
- void * blob,
- kmq_call * call);
-
-/*! \brief Free a handle to a call obtained through kmq_post_message_ex()
-
- All call handles obtained through kmq_post_message_ex() must be
- freed via a call to kmq_free_call().
-*/
-KHMEXP khm_int32 KHMAPI kmq_free_call(kmq_call call);
-
-/*! \brief Sends a <KMSG_SYSTEM,KMSG_SYSTEM_EXIT> message to the specified thread.
-
- The message itself will not be received by any callback function,
- however, any kmq_dispatch() function that is currently active of
- becomes active will exit with a KHM_ERROR_EXIT code.
- kmq_send_thread_quit_message() will wait for this to happen before
- returning.
- */
-KHMEXP khm_int32 KHMAPI kmq_send_thread_quit_message(
- kmq_thread_id thread,
- khm_ui_4 uparam);
-
-/*! \brief Post a <KMSG_SYSTEM,KMSG_SYSTEM_EXIT> message to the specified thread.
-
- The message itself will not be received by any callback function,
- however, any kmq_dispatch() function that is currently active of
- becomes active will exit with a KHM_ERROR_EXIT code.
- kmq_post_thread_quit_message() will return immediately.
- */
-KHMEXP khm_int32 KHMAPI kmq_post_thread_quit_message(
- kmq_thread_id thread,
- khm_ui_4 uparam,
- kmq_call * call);
-
-KHMEXP khm_int32 KHMAPI kmq_get_next_response(kmq_call call, void ** resp);
-
-/*! \brief Check if a specific call has completed
-
- \return TRUE if the call has completed. FALSE otherwise.
-*/
-KHMEXP khm_boolean KHMAPI kmq_has_completed(kmq_call call);
-
-/*! \brief Wait for a call to complete.
-
- Waits for the specified call to complete. If the call dispatched
- to multiple recipients, the function waits for all dispatches to
- complete.
-
- If the call has already completed, then the function returns
- immediately.
-
- If more than one thread is waiting for a single message to
- complete, then only one of them will be released when the message
- compeltes. Each subsequent thread will be released as each
- released thread calls kmq_free_call().
-
- \param[in] call A handle to a call.
- \param[in] timeout Specifies, in milliseconds, the amount of time
- to wait for the call to complete. Specify INFINITE to wait
- indefinitely.
-
- \retval KHM_ERROR_SUCCESS The call completed
- \retval KHM_ERROR_TIMEOUT The timeout period expired
- \retval KHM_ERROR_INVALID_PARAM One of the parameters were invalid.
-*/
-KHMEXP khm_int32 KHMAPI kmq_wait(kmq_call call, kmq_timer timeout);
-
-/*! \brief Abort a call
-
- Abort a pending call. The call handle should have been obtained
- using a prior call to kmq_post_message_ex().
-
- Note that this function may not abort the call immediately. It
- merely marks the message as being in an aborted state. It is upto
- the individual handlers of the message to check if the message has
- been aborted and act accordingly.
-
- The handlers are expected to call kmq_is_call_aborted()
- periodicially during the processing of specially lengthy
- operations during the course of handling a message. That function
- will return \a TRUE if the last dispatched message is now in an
- aborted state. In which case, the handler is expected to abort
- handling the message and return control to the dispatcher.
- */
-KHMEXP khm_int32 KHMAPI kmq_abort_call(kmq_call call);
-
-/*! \brief Check if the last dispatched message was aborted
-
- The sender of a message may abort it using a call to
- kmq_abort_call(). This function checks if the last dispatched
- message was aborted.
-
- A handler of a message is expected to call this function
- periodically if handling the message is going to take a specially
- long time (e.g. more than 5 or 10 seconds). If the message is
- found to be aborted, the handler is expected to abort handling the
- message, perform any necessary cleanup and return control to the
- dispatcher.
-
- Doing this allows operations like new credentials acquisition to
- be cleanly aborted by the user if she so wishes. Otherwise,
- Network Identity Manager has to wait for the message to complete
- processing since it has no means of cleanly terminating an
- executing plug-in thread.
-*/
-KHMEXP khm_boolean KHMAPI kmq_is_call_aborted(void);
-
-/*! \brief Sets the completion handler for a specified message type.
-
- \note Only one completion handler can exist for one message type.
- Calling this function overwrites the previous completion
- handler.
-*/
-KHMEXP khm_int32 KHMAPI kmq_set_completion_handler(
- khm_int32 type,
- kmq_msg_completion_handler hander);
-
-/*@}*/
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __KHIMAIRA_KMQ_H__
+#define __KHIMAIRA_KMQ_H__
+
+/*! \defgroup kmq NetIDMgr Message Queue */
+/*@{*/
+
+#include<khdefs.h>
+#include<khlist.h>
+#include<kherr.h>
+
+/* general */
+#ifdef _WIN32
+typedef DWORD kmq_thread_id;
+typedef DWORD kmq_timer;
+#endif
+
+#ifdef _WIN32
+/*! \brief Window message for kmq
+
+ This message is sent to the window procedure of a window if that
+ window is a subscriber to KMQ messages.
+
+ \see kmq_subscribe_hwnd() for more information about handling this
+ window message
+ */
+#define KMQ_WM_DISPATCH (WM_APP+0x100)
+#endif
+
+/* callback */
+
+/*! \brief A message callback
+
+ Should return TRUE if the message is properly handled. Otherwise
+ return FALSE */
+typedef khm_int32 (KHMAPI *kmq_callback_t)(khm_int32 msg_type,
+ khm_int32 msg_sub_type,
+ khm_ui_4 uparam,
+ void * vparam);
+
+/* message */
+
+/*! \brief A single response.
+
+ Certain broadcast messages may user scatter-gather type
+ notification and result gathering. Individual subscribers to a
+ message attach their individual responses to a ::kmq_response
+ object and attach that to the message which can later be read by
+ the sender of the message.
+ */
+typedef struct tag_kmq_response {
+ kmq_thread_id thread;
+ void * response;
+
+ LDCL(struct tag_kmq_response);
+} kmq_response;
+
+/*! \brief A single message
+ */
+typedef struct tag_kmq_message {
+ khm_int32 type; /*!< Type of message */
+ khm_int32 subtype; /*!< Subtype of message */
+
+ khm_ui_4 uparam; /*!< Integer parameter */
+ void * vparam; /*!< Pointer to parameter blob */
+
+ khm_int32 nSent; /*!< Number of instances of message
+ sent (for broadcast messages) */
+
+ khm_int32 nCompleted; /*!< Number of instances that have
+ completed processing (for broadcast
+ messages) */
+
+ khm_int32 nFailed; /*!< Number of instances that failed
+ to process (for broadcast
+ messages) */
+
+ kmq_response * responses; /*!< List of responses */
+ HANDLE wait_o; /*!< Event to wait on (only valid if
+ the publisher of the message
+ requested a handle to the call) */
+
+ kmq_timer timeSent; /*!< Time at which the message was
+ sent */
+ kmq_timer timeExpire; /*!< Time at which the message
+ expires */
+
+ kherr_context * err_ctx; /*!< Error context for the message */
+
+ khm_boolean aborted; /*!< TRUE if the message has been
+ aborted. */
+
+ khm_int32 refcount; /*!< Internal use */
+
+ LDCL(struct tag_kmq_message); /*!< Internal use */
+} kmq_message;
+
+/*! \brief A handle to a call
+ */
+typedef kmq_message *kmq_call;
+
+/* publishers */
+
+/*! \brief A completion handler for a message
+
+ Each message type can have a completion handler. Once a message
+ of this a specific type has been broadcast and handled by all the
+ subscripbers, the message will be passed down to the completion
+ handler before the associated data structures are freed. This
+ allows applications that define message type to also define clean
+ up for each message. For example, the completion handler can
+ initiate another message if the messages form a sequence or free
+ up blocks of memory that was passed as the parameter to the
+ message.
+ */
+typedef void (KHMAPI *kmq_msg_completion_handler)(kmq_message *);
+
+#ifdef NOEXPORT
+
+KHMEXP khm_int32 KHMAPI kmq_init(void);
+
+KHMEXP khm_int32 KHMAPI kmq_exit(void);
+
+#endif
+
+/*! \brief Register a message type
+
+ Registers a custom message type. The \a name parameter specifies
+ a language independent name for the message type and must be
+ unique and must be less than ::KMQ_MAXCCH_TYPE_NAME characters.
+
+ \param[in] name Name of the message type. Upto
+ ::KMQ_MAXCCH_TYPE_NAME characters including terminating NULL.
+ The \a name cannot be a zero length string.
+
+ \param[out] new_id Receives the new message type ID. Specify NULL
+ if the new message type is not required.
+
+ \see kmq_find_type() and kmq_unregister_type()
+
+ \retval KHM_ERROR_INVALID_PARAM The \a name parameter was invalid.
+ \retval KHM_ERROR_EXISTS A message type with that name already exists.
+ \retval KHM_ERROR_NO_RESOURCES Can't register any more message types.
+ \retval KHM_ERROR_SUCCESS The operation succeeded.
+ */
+KHMEXP khm_int32 KHMAPI kmq_register_type(wchar_t * name, khm_int32 * new_id);
+
+/*! \brief Find a message type
+
+ Find the message type with the given name. If found, the type ID
+ is returned in \a id.
+
+ \retval KHM_ERROR_SUCCESS A message type with the given name was
+ found.
+ \retval KHM_ERROR_NOT_FOUND A message type with the given name was
+ not found.
+ */
+KHMEXP khm_int32 KHMAPI kmq_find_type(wchar_t * name, khm_int32 * id);
+
+/*! \brief Unregister a message type
+
+ Unregisters a message type that was registered using
+ kmq_register_type().
+
+ \retval KHM_ERROR_SUCCESS The specified message type was
+ successfully unregistered.
+
+ \retval KHM_ERROR_NOT_FOUND The message type was not found.
+ */
+KHMEXP khm_int32 KHMAPI kmq_unregister_type(khm_int32 id);
+
+/*! \brief Subscribte to a message type.
+
+ Adds a subscription to messages of type \a type. Subscriptions
+ are managed per thread. Therefore the subscription is actually
+ added to the subscription list for the current thread (the thread
+ which calls kmq_subscribe()).
+
+ When a message of type \a type is received by the thread, it is
+ dispatched to the callback function identified by \a cb within the
+ context of this thread.
+
+ \note Calling kmq_subscribe() from within multiple threads with
+ the same \a type and \a cb will result in multiple
+ subscriptions.
+
+ \see kmq_unsubscribe()
+ \see kmq_dispatch()
+*/
+KHMEXP khm_int32 KHMAPI kmq_subscribe(khm_int32 type, kmq_callback_t cb);
+
+/*! \brief Subscribe a window to a message type
+
+ Adds the window specified by \a hwnd to the subscription list for
+ the message type \a type. When a message of this type is posted,
+ then the window procedure of the window \a hwnd receives a message
+ ::KMQ_WM_DISPATCH.
+
+ When a window receives a ::KMQ_WM_DISPATCH message, it means that
+ a message has been posted which is of a type that the window has
+ subscribed for. Because of the way Windows handles window
+ messages and the way NetIDMgr message queues work, a thread which
+ has a window (or thread) procedure can not call kmq_dispatch() to
+ handle these messages. For threads that have window or thread
+ message loops, they must call kmq_subscribe_hwnd() to subscribe a
+ particular window (for thread message loops, this would be the
+ HWND of the message window for the thread) to NetIDMgr messages.
+
+ There are two supported ways of handling the ::KMQ_WM_DISPATCH
+ message. Examples of both are provided below.
+
+ Handling the message inline:
+
+ \code
+ LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
+ kmq_message * m;
+ khm_int32 rv;
+ ...
+ switch(uMsg) {
+ case WM_CREATE:
+ ...
+ kmq_subscribe_hwnd(KMSG_CRED, hwnd);
+ ...
+ break;
+
+ case WM_DESTROY:
+ ...
+ kmq_unsubscribe_hwnd(KMSG_CRED, hwnd);
+ ...
+ break;
+
+ ...
+ case KMQ_WM_DISPATCH:
+ kmq_wm_begin(lParam,&m);
+
+ if(m->type == KMSG_CRED && m->subtype == KMSG_CRED_ROOTDELTA) {
+ // do something
+ rv = KHM_ERROR_SUCCESS;
+ }
+
+ return kmq_wm_end(m, rv);
+ ...
+ };
+ ...
+ }
+ \endcode
+
+ The other method is to dispatch the ::KMQ_WM_DISPATCH message to a
+ secondary callback function:
+
+ \code
+ khm_int32 msg_handler(khm_int32 t, khm_int32 st, khm_ui_4 up, void * pb) {
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+
+ //handle message
+
+ return rv;
+ }
+
+ LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
+ kmq_message * m;
+ khm_int32 rv;
+ ...
+ switch(uMsg) {
+ ...
+
+ case WM_CREATE:
+ ...
+ kmq_subscribe_hwnd(KMSG_CRED, hwnd);
+ ...
+ break;
+
+ case WM_DESTROY:
+ ...
+ kmq_unsubscribe_hwnd(KMSG_CRED, hwnd);
+ ...
+ break;
+
+ ...
+ case KMQ_WM_DISPATCH:
+ return kmq_wm_dispatch(lParam, msg_handler);
+ ...
+ };
+ ...
+ }
+ \endcode
+
+ \note Make sure you unsubscribe from the message type when the
+ window is destroyed.
+
+ \see kmq_unsubscribe_hwnd()
+ \see kmq_wm_begin()
+ \see kmq_wm_end()
+ \see kmq_wm_dispatch()
+ */
+KHMEXP khm_int32 KHMAPI kmq_subscribe_hwnd(khm_int32 type, HWND hwnd);
+
+#ifdef _WIN32
+/*! \brief Begins handling a KMQ_WM_DISPATCH message
+
+ \return The return value of this function should be ignored.
+
+ \see kmq_subscribe_hwnd() for more details about handling ::KMQ_WM_DISPATCH
+ */
+KHMEXP LRESULT KHMAPI kmq_wm_begin(LPARAM lparm, kmq_message ** m);
+
+/*! \brief Ends handling a KMQ_WM_DISPATCH message
+
+ \return The return value of this function should be the return
+ value of the window procedure. See kmq_subscribe_hwnd()
+ documentation for example
+
+ \see kmq_subscribe_hwnd() for more details about handling ::KMQ_WM_DISPATCH
+ */
+KHMEXP LRESULT KHMAPI kmq_wm_end(kmq_message *m, khm_int32 rv);
+
+/*! \brief Dispatches a KMQ_WM_DISPATCH message to a callback
+
+ \return The return value of this function should be the return
+ value of the window procedure. See kmq_subscribe_hwnd()
+ documentation for example.
+
+ \see kmq_subscribe_hwnd() for more details about handling ::KMQ_WM_DISPATCH
+ */
+KHMEXP LRESULT KHMAPI kmq_wm_dispatch(LPARAM lparm, kmq_callback_t cb);
+#endif
+
+/*! \brief Unsubscribe a callback from a message type
+
+ Removes the subscription for message type \a type for callback
+ function \a cb from the subscription list for the current thread
+ (the thread that calls kmq_unsubscribe()).
+
+ \note kmq_unsubscribe() can only remove subscriptions for the subscription
+ list for the current thread.
+
+ \see kmq_subscribe()
+ \see kmq_dispatch()
+*/
+KHMEXP khm_int32 KHMAPI kmq_unsubscribe(khm_int32 type, kmq_callback_t cb);
+
+/*! \brief Unsubscribe a window from a message type
+
+ Removes the specific window from the subsription list for message
+ type \a type.
+
+ \see kmq_subscribe_hwnd()
+*/
+KHMEXP khm_int32 KHMAPI kmq_unsubscribe_hwnd(khm_int32 type, HWND hwnd);
+
+/*! \brief Create an ad-hoc subscription
+
+ An ad-hoc subscription describes a callback point in a thread that
+ can be dispatched messages to individually without broadcasting.
+
+ \see kmq_post_sub_msg(), kmq_post_sub_msg_ex(),
+ kmq_send_sub_msg(), kmq_post_subs_msg(),
+ kmq_post_subs_msg_ex(), kmq_send_subs_msg(),
+ kmq_delete_subscription()
+*/
+KHMEXP khm_int32 KHMAPI kmq_create_subscription(
+ kmq_callback_t cb,
+ khm_handle * result);
+
+/*! \brief Create an ad-hoc subscription for a window
+
+ An ad-hoc subscription describes a window that will be dispatched
+ messages individually without broadcasting.
+
+ \see kmq_post_sub_msg(), kmq_post_sub_msg_ex(),
+ kmq_send_sub_msg(), kmq_post_subs_msg(),
+ kmq_post_subs_msg_ex(), kmq_send_subs_msg(),
+ kmq_delete_subscription()
+ */
+KHMEXP khm_int32 KHMAPI kmq_create_hwnd_subscription(HWND hw,
+ khm_handle * result);
+
+/*! \brief Delete an ad-hoc subscription
+
+ Deletes a subscriptoin that was created using
+ kmq_create_subscription()
+ */
+KHMEXP khm_int32 KHMAPI kmq_delete_subscription(khm_handle sub);
+
+/*! \brief Post a message to a subscription
+
+ Equivalent of kmq_post_msg() but only posts the message to the
+ specified subscription.
+ */
+KHMEXP khm_int32 KHMAPI kmq_post_sub_msg(
+ khm_handle sub,
+ khm_int32 type,
+ khm_int32 subtype,
+ khm_ui_4 uparam,
+ void * vparam);
+
+/*! \brief Post a message to a subscription and acquire a handle to the call
+ */
+KHMEXP khm_int32 KHMAPI kmq_post_sub_msg_ex(
+ khm_handle sub,
+ khm_int32 type,
+ khm_int32 subtype,
+ khm_ui_4 uparam,
+ void * vparam,
+ kmq_call * call);
+
+/*! \brief Send a synchronous message to a subscription
+
+ \retval KHM_ERROR_SUCCESS The call succeeded, and no subscribers reported errors
+ \retval KHM_ERROR_PARTIAL The call succeeded, but at least one subscriber reported errors
+ */
+KHMEXP khm_int32 KHMAPI kmq_send_sub_msg(
+ khm_handle sub,
+ khm_int32 type,
+ khm_int32 subtype,
+ khm_ui_4 uparam,
+ void * vparam);
+
+/*! \brief Post a message to a group of subscriptions
+
+ The block of memory pointed to by \a subs should be an array of
+ subscriptions. The number of elements in that array should be \a
+ n_subs. A message as specified by the remaining parameters will
+ be dispatched to all of the subscription points in the array.
+ */
+KHMEXP khm_int32 KHMAPI kmq_post_subs_msg(
+ khm_handle * subs,
+ khm_size n_subs,
+ khm_int32 type,
+ khm_int32 subtype,
+ khm_ui_4 uparam,
+ void * vparam);
+
+/*! \brief Post a message to a group of subscriptions and acquire a handle to the call
+
+ The block of memory pointed to by \a subs should be an array of
+ subscriptions. The number of elements in that array should be \a
+ n_subs. A message as specified by the remaining parameters will
+ be dispatched to all of the subscription points in the array, and
+ a handle to the call will be returned in \a call.
+
+ The returned \a call will reference all of the dispatches that
+ were made.
+*/
+KHMEXP khm_int32 KHMAPI kmq_post_subs_msg_ex(
+ khm_handle * subs,
+ khm_int32 n_subs,
+ khm_int32 type,
+ khm_int32 subtype,
+ khm_ui_4 uparam,
+ void * vparam,
+ kmq_call * call);
+
+/*! \brief Send a synchronous message to a group of subscriptions
+
+ The block of memory pointed to by \a subs should be an array of
+ subscriptions. The number of elements in that array should be \a
+ n_subs. A message as specified by the remaining parameters will
+ be dispatched to all of the subscription points in the array. The
+ function will not return until all of the calls have succeeded.
+
+ \retval KHM_ERROR_SUCCESS The call succeeded, and no subscribers reported errors
+ \retval KHM_ERROR_PARTIAL The call succeeded, but at least one subscriber reported errors
+*/
+KHMEXP khm_int32 KHMAPI kmq_send_subs_msg(
+ khm_handle *subs,
+ khm_int32 n_subs,
+ khm_int32 type,
+ khm_int32 subtype,
+ khm_ui_4 uparam,
+ void * vparam);
+
+/*! \brief Dispatch a message for the current thread.
+
+ This function opens the message list for the current thread and
+ dispatches the first message instance that is found. Note that if
+ multiple callbacks subscribe to the same message type in the same
+ thread, then when a message of that type is received, multiple
+ message instances are added to the message queue corresponding to
+ each subscription.
+
+ If no message instances are waiting in the queue, kmq_dispatch()
+ waits for the \a timeout period for a message.
+
+ \param[in] timeout The timeout period in milliseconds. Specify INFINITE for
+ kmq_dispatch() to wait indefinitely.
+
+ \retval KHM_ERROR_SUCCESS A message instance was dispatched
+ \retval KHM_ERROR_TIMEOUT The timeout period elapsed
+ \retval KHM_ERROR_EXIT The message found on the queue was <KMSG_SYSTEM,KMSG_SYSTEM_EXIT>
+*/
+KHMEXP khm_int32 KHMAPI kmq_dispatch(kmq_timer timeout);
+
+/*! \brief Send a message
+
+ The specified message will be posted to all the subscribers of the
+ message type. Then the function will wait for all the subscribers
+ to finish processing the message before returning.
+
+ \param[in] type The type of the message
+ \param[in] subtype The subtype
+ \param[in] uparam The khm_ui_4 parameter for the message
+ \param[in] blob The parameter blob for the message
+
+ \note The internal timeout for this function is INFINITE. If you
+ it is desirable to use a different timeout, use
+ kmq_post_message_ex() and kmq_wait() functions.
+
+ \retval KHM_ERROR_SUCCESS The call succeeded and no subscribers returned errors
+ \retval KHM_ERROR_PARTIAL The call succeeded but at least one subscriber returned an error
+*/
+KHMEXP khm_int32 KHMAPI kmq_send_message(
+ khm_int32 type,
+ khm_int32 subtype,
+ khm_ui_4 uparam,
+ void * blob);
+
+/*! \brief Post a message
+
+ The specified message will be posted to all the subscribers of the
+ message type. The function returns immediately.
+
+ If you want to be able to wait for all the subscribers to finish
+ processing the message, you should use kmq_post_message_ex()
+ instead.
+
+ \param[in] type The type of the message
+ \param[in] subtype The subtype
+ \param[in] uparam The khm_ui_4 parameter for the message
+ \param[in] blob The parameter blob for the message
+*/
+KHMEXP khm_int32 KHMAPI kmq_post_message(
+ khm_int32 type,
+ khm_int32 subtype,
+ khm_ui_4 uparam,
+ void * blob);
+
+/*! \brief Post a message and acquire a handle to the call.
+
+ The specified message is posted to all the subscribers. In
+ addition, a handle is obtained for the call which can be used in
+ subsequent call to kmq_free_call() or kmq_wait().
+
+ Call kmq_free_call() to free the handle.
+
+ \param[in] type The type of the message
+ \param[in] subtype The subtype
+ \param[in] uparam The khm_ui_4 parameter for the message
+ \param[in] blob The parameter blob for the message
+ \param[out] call Receives the call handle. Set to NULL if the call handle is not required.
+
+ \see kmq_free_call()
+*/
+KHMEXP khm_int32 KHMAPI kmq_post_message_ex(
+ khm_int32 type,
+ khm_int32 subtype,
+ khm_ui_4 uparam,
+ void * blob,
+ kmq_call * call);
+
+/*! \brief Free a handle to a call obtained through kmq_post_message_ex()
+
+ All call handles obtained through kmq_post_message_ex() must be
+ freed via a call to kmq_free_call().
+*/
+KHMEXP khm_int32 KHMAPI kmq_free_call(kmq_call call);
+
+/*! \brief Sends a <KMSG_SYSTEM,KMSG_SYSTEM_EXIT> message to the specified thread.
+
+ The message itself will not be received by any callback function,
+ however, any kmq_dispatch() function that is currently active of
+ becomes active will exit with a KHM_ERROR_EXIT code.
+ kmq_send_thread_quit_message() will wait for this to happen before
+ returning.
+ */
+KHMEXP khm_int32 KHMAPI kmq_send_thread_quit_message(
+ kmq_thread_id thread,
+ khm_ui_4 uparam);
+
+/*! \brief Post a <KMSG_SYSTEM,KMSG_SYSTEM_EXIT> message to the specified thread.
+
+ The message itself will not be received by any callback function,
+ however, any kmq_dispatch() function that is currently active of
+ becomes active will exit with a KHM_ERROR_EXIT code.
+ kmq_post_thread_quit_message() will return immediately.
+ */
+KHMEXP khm_int32 KHMAPI kmq_post_thread_quit_message(
+ kmq_thread_id thread,
+ khm_ui_4 uparam,
+ kmq_call * call);
+
+KHMEXP khm_int32 KHMAPI kmq_get_next_response(kmq_call call, void ** resp);
+
+/*! \brief Check if a specific call has completed
+
+ \return TRUE if the call has completed. FALSE otherwise.
+*/
+KHMEXP khm_boolean KHMAPI kmq_has_completed(kmq_call call);
+
+/*! \brief Wait for a call to complete.
+
+ Waits for the specified call to complete. If the call dispatched
+ to multiple recipients, the function waits for all dispatches to
+ complete.
+
+ If the call has already completed, then the function returns
+ immediately.
+
+ If more than one thread is waiting for a single message to
+ complete, then only one of them will be released when the message
+ compeltes. Each subsequent thread will be released as each
+ released thread calls kmq_free_call().
+
+ \param[in] call A handle to a call.
+ \param[in] timeout Specifies, in milliseconds, the amount of time
+ to wait for the call to complete. Specify INFINITE to wait
+ indefinitely.
+
+ \retval KHM_ERROR_SUCCESS The call completed
+ \retval KHM_ERROR_TIMEOUT The timeout period expired
+ \retval KHM_ERROR_INVALID_PARAM One of the parameters were invalid.
+*/
+KHMEXP khm_int32 KHMAPI kmq_wait(kmq_call call, kmq_timer timeout);
+
+/*! \brief Abort a call
+
+ Abort a pending call. The call handle should have been obtained
+ using a prior call to kmq_post_message_ex().
+
+ Note that this function may not abort the call immediately. It
+ merely marks the message as being in an aborted state. It is upto
+ the individual handlers of the message to check if the message has
+ been aborted and act accordingly.
+
+ The handlers are expected to call kmq_is_call_aborted()
+ periodicially during the processing of specially lengthy
+ operations during the course of handling a message. That function
+ will return \a TRUE if the last dispatched message is now in an
+ aborted state. In which case, the handler is expected to abort
+ handling the message and return control to the dispatcher.
+ */
+KHMEXP khm_int32 KHMAPI kmq_abort_call(kmq_call call);
+
+/*! \brief Check if the last dispatched message was aborted
+
+ The sender of a message may abort it using a call to
+ kmq_abort_call(). This function checks if the last dispatched
+ message was aborted.
+
+ A handler of a message is expected to call this function
+ periodically if handling the message is going to take a specially
+ long time (e.g. more than 5 or 10 seconds). If the message is
+ found to be aborted, the handler is expected to abort handling the
+ message, perform any necessary cleanup and return control to the
+ dispatcher.
+
+ Doing this allows operations like new credentials acquisition to
+ be cleanly aborted by the user if she so wishes. Otherwise,
+ Network Identity Manager has to wait for the message to complete
+ processing since it has no means of cleanly terminating an
+ executing plug-in thread.
+*/
+KHMEXP khm_boolean KHMAPI kmq_is_call_aborted(void);
+
+/*! \brief Sets the completion handler for a specified message type.
+
+ \note Only one completion handler can exist for one message type.
+ Calling this function overwrites the previous completion
+ handler.
+*/
+KHMEXP khm_int32 KHMAPI kmq_set_completion_handler(
+ khm_int32 type,
+ kmq_msg_completion_handler hander);
+
+/*@}*/
+#endif
diff --git a/src/windows/identity/kmq/kmqinternal.h b/src/windows/identity/kmq/kmqinternal.h
index 1d6196b307..bd97f1bb6d 100644
--- a/src/windows/identity/kmq/kmqinternal.h
+++ b/src/windows/identity/kmq/kmqinternal.h
@@ -1,239 +1,239 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#ifndef __KHIMAIRA_KMQINTERNAL_H
-#define __KHIMAIRA_KMQINTERNAL_H
-
-#include<windows.h>
-#include<kmq.h>
-#include<khlist.h>
-#include<kherror.h>
-#include<khmsgtypes.h>
-#include<kconfig.h>
-
-#define NOEXPORT
-
-#include<utils.h>
-#include<strsafe.h>
-
-
-
-
-/*! \brief Message reference */
-typedef struct tag_kmq_message_ref {
- kmq_message * msg; /*!< Message that we are referring
- to */
- kmq_callback_t recipient; /*!< The recipient of the message */
-
- LDCL(struct tag_kmq_message_ref);
-} kmq_message_ref;
-
-
-
-
-/*! \brief Message queue
-
- Each thread gets its own message queue. When a message is
- broadcast to which there is a subscriber in a particular thread, a
- reference to the message is placed in the message queue of the
- thread. The dispatch procedure then dispatches the message as
- described in the message reference.
-*/
-typedef struct tag_kmq_queue {
- kmq_thread_id thread; /*!< The thread id */
-
- CRITICAL_SECTION cs;
- HANDLE wait_o;
-
- khm_int32 load; /*!< Number of messages waiting to be
- processed on this message queue. */
- kmq_timer last_post; /*!< Time the last message was
- received */
-
- khm_int32 flags; /*!< Flags. Currently, it's just KMQ_QUEUE_FLAG_DELETED */
-
- /*Q*/
- QDCL(kmq_message_ref); /*!< Queue of message references */
-
- /*Lnode*/
- LDCL(struct tag_kmq_queue);
-} kmq_queue;
-
-#define KMQ_QUEUE_FLAG_DELETED 0x00000008
-#define KMQ_QUEUE_FLAG_DETACHING 0x00000010
-
-/*! \brief Message subscription
-
- A subscription binds a recipient with a message type. These are
- specific to a thread. I.e. a subscription that was made in one
- thread will not receive messages in the context of another thread.
-*/
-typedef struct tag_kmq_msg_subscription {
- khm_int32 magic; /*!< Magic number. Should always be
- ::KMQ_MSG_SUB_MAGIC */
- khm_int32 type; /*!< Type of message */
- khm_int32 rcpt_type; /*!< Type of recipient. One of
- ::KMQ_RCPTTYPE_CB or
- ::KMQ_RCPTTYPE_HWND */
- union {
- kmq_callback_t cb; /*!< Callback if the subscription is
- of callback type */
- HWND hwnd; /*!< Window handle if the subscription
- is a windows message type */
- } recipient;
-
- kmq_queue * queue; /*!< Associated queue */
-
- /*lnode*/
- LDCL(struct tag_kmq_msg_subscription);
-} kmq_msg_subscription;
-
-#define KMQ_MSG_SUB_MAGIC 0x3821b58e
-
-/*! \brief Callback recipient type
-
- The recipient is a callback function */
-#define KMQ_RCPTTYPE_CB 1
-
-/*! \brief Windows recipient type
-
- The recipient is a window */
-#define KMQ_RCPTTYPE_HWND 2
-
-
-
-
-/*! \brief A message type
- */
-typedef struct tag_kmq_msg_type {
- khm_int32 id; /*!< Identifier for the message
- type. */
- kmq_msg_subscription * subs; /*!< The list of subscriptions */
- kmq_msg_completion_handler completion_handler; /*!< Completion
- handler for the message type */
-
- wchar_t * name; /*!< Name of the message type for
- named types. Message type names are
- language independant. */
-
- /*Lnode*/
- LDCL(struct tag_kmq_msg_type);
-} kmq_msg_type;
-
-/*! \brief The maximum number of message types
- */
-#define KMQ_MSG_TYPE_MAX 255
-
-/*! \brief Maximum number of characters in a message type name
-
- The count includes the terminating NULL
- */
-#define KMQ_MAXCCH_TYPE_NAME 256
-
-/*! \brief Maximum number of bytes in a message type name
-
- Type count includes the terminating NULL
- */
-#define KMQ_MAXCB_TYPE_NAME (KMQ_MAXCCH_TYPE_NAME * sizeof(wchar_t))
-
-
-
-
-#define KMQ_CONF_SPACE_NAME L"KMQ"
-#define KMQ_CONF_QUEUE_DEAD_TIMEOUT_NAME L"QueueDeadTimeout"
-#define KMQ_CONF_CALL_DEAD_TIMEOUT_NAME L"CallDeadTimeout"
-
-extern CRITICAL_SECTION cs_kmq_global;
-extern kmq_timer kmq_queue_dead_timeout;
-extern kmq_timer kmq_call_dead_timeout;
-
-extern kmq_queue * queues;
-
-/* message type */
-extern CRITICAL_SECTION cs_kmq_types;
-extern kmq_msg_type *msg_types[KMQ_MSG_TYPE_MAX+1];
-
-void kmqint_init_msg_types(void);
-void kmqint_exit_msg_types(void);
-void kmqint_free_msg_type(int t);
-void kmqint_msg_type_create(int t);
-void kmqint_msg_type_add_sub(int t, kmq_msg_subscription *s);
-void kmqint_msg_type_del_sub(kmq_msg_subscription *s);
-kmq_msg_subscription * kmqint_msg_type_del_sub_hwnd(khm_int32 t, HWND hwnd);
-kmq_msg_subscription * kmqint_msg_type_del_sub_cb(khm_int32 t, kmq_callback_t cb);
-khm_int32 kmqint_msg_publish(kmq_message * m, khm_boolean try_send);
-khm_int32 kmqint_msg_type_set_handler(khm_int32 type, kmq_msg_completion_handler handler);
-int kmqint_notify_msg_completion(kmq_message * m);
-
-/* consumer */
-extern DWORD kmq_tls_queue;
-
-void kmqint_post_queue(kmq_queue * q, kmq_message *m);
-void kmqint_post(kmq_msg_subscription * s, kmq_message * m, khm_boolean try_send);
-kmq_queue * kmqint_get_thread_queue(void);
-void kmqint_get_queue_message_ref(kmq_queue * q, kmq_message_ref ** r);
-void kmqint_put_message_ref(kmq_message_ref * r);
-
-/* publisher */
-extern CRITICAL_SECTION cs_kmq_msg;
-extern CRITICAL_SECTION cs_kmq_msg_ref;
-
-kmq_message * kmqint_get_message(void);
-void kmqint_put_message(kmq_message *m);
-
-void kmqint_init(void);
-void kmqint_exit(void);
-void kmqint_attach_this_thread(void);
-void kmqint_detach_this_thread(void);
-
-khm_int32 kmqint_post_message_ex(
- khm_int32 type,
- khm_int32 subtype,
- khm_ui_4 uparam,
- void * blob,
- kmq_call * call,
- khm_boolean try_send);
-
-int kmqint_call_completion_handler(kmq_msg_completion_handler h,
- kmq_message * m);
-
-/* global */
-extern kconf_schema schema_kmqconfig[];
-
-/* Lock hiearchy :
-
- cs_kmq_types
- cs_kmq_msg
- cs_kmq_msg_ref
- cs_compl
- cs_kmq_global
- kmq_queue::cs
-
- If you have a level 'x' lock, you can obtain a level 'x+n' lock.
- You can't obtain a 'x-n' lock if you already have a level 'x' lock.
- If you don't have any locks, you can obtain any lock.
- */
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __KHIMAIRA_KMQINTERNAL_H
+#define __KHIMAIRA_KMQINTERNAL_H
+
+#include<windows.h>
+#include<kmq.h>
+#include<khlist.h>
+#include<kherror.h>
+#include<khmsgtypes.h>
+#include<kconfig.h>
+
+#define NOEXPORT
+
+#include<utils.h>
+#include<strsafe.h>
+
+
+
+
+/*! \brief Message reference */
+typedef struct tag_kmq_message_ref {
+ kmq_message * msg; /*!< Message that we are referring
+ to */
+ kmq_callback_t recipient; /*!< The recipient of the message */
+
+ LDCL(struct tag_kmq_message_ref);
+} kmq_message_ref;
+
+
+
+
+/*! \brief Message queue
+
+ Each thread gets its own message queue. When a message is
+ broadcast to which there is a subscriber in a particular thread, a
+ reference to the message is placed in the message queue of the
+ thread. The dispatch procedure then dispatches the message as
+ described in the message reference.
+*/
+typedef struct tag_kmq_queue {
+ kmq_thread_id thread; /*!< The thread id */
+
+ CRITICAL_SECTION cs;
+ HANDLE wait_o;
+
+ khm_int32 load; /*!< Number of messages waiting to be
+ processed on this message queue. */
+ kmq_timer last_post; /*!< Time the last message was
+ received */
+
+ khm_int32 flags; /*!< Flags. Currently, it's just KMQ_QUEUE_FLAG_DELETED */
+
+ /*Q*/
+ QDCL(kmq_message_ref); /*!< Queue of message references */
+
+ /*Lnode*/
+ LDCL(struct tag_kmq_queue);
+} kmq_queue;
+
+#define KMQ_QUEUE_FLAG_DELETED 0x00000008
+#define KMQ_QUEUE_FLAG_DETACHING 0x00000010
+
+/*! \brief Message subscription
+
+ A subscription binds a recipient with a message type. These are
+ specific to a thread. I.e. a subscription that was made in one
+ thread will not receive messages in the context of another thread.
+*/
+typedef struct tag_kmq_msg_subscription {
+ khm_int32 magic; /*!< Magic number. Should always be
+ ::KMQ_MSG_SUB_MAGIC */
+ khm_int32 type; /*!< Type of message */
+ khm_int32 rcpt_type; /*!< Type of recipient. One of
+ ::KMQ_RCPTTYPE_CB or
+ ::KMQ_RCPTTYPE_HWND */
+ union {
+ kmq_callback_t cb; /*!< Callback if the subscription is
+ of callback type */
+ HWND hwnd; /*!< Window handle if the subscription
+ is a windows message type */
+ } recipient;
+
+ kmq_queue * queue; /*!< Associated queue */
+
+ /*lnode*/
+ LDCL(struct tag_kmq_msg_subscription);
+} kmq_msg_subscription;
+
+#define KMQ_MSG_SUB_MAGIC 0x3821b58e
+
+/*! \brief Callback recipient type
+
+ The recipient is a callback function */
+#define KMQ_RCPTTYPE_CB 1
+
+/*! \brief Windows recipient type
+
+ The recipient is a window */
+#define KMQ_RCPTTYPE_HWND 2
+
+
+
+
+/*! \brief A message type
+ */
+typedef struct tag_kmq_msg_type {
+ khm_int32 id; /*!< Identifier for the message
+ type. */
+ kmq_msg_subscription * subs; /*!< The list of subscriptions */
+ kmq_msg_completion_handler completion_handler; /*!< Completion
+ handler for the message type */
+
+ wchar_t * name; /*!< Name of the message type for
+ named types. Message type names are
+ language independant. */
+
+ /*Lnode*/
+ LDCL(struct tag_kmq_msg_type);
+} kmq_msg_type;
+
+/*! \brief The maximum number of message types
+ */
+#define KMQ_MSG_TYPE_MAX 255
+
+/*! \brief Maximum number of characters in a message type name
+
+ The count includes the terminating NULL
+ */
+#define KMQ_MAXCCH_TYPE_NAME 256
+
+/*! \brief Maximum number of bytes in a message type name
+
+ Type count includes the terminating NULL
+ */
+#define KMQ_MAXCB_TYPE_NAME (KMQ_MAXCCH_TYPE_NAME * sizeof(wchar_t))
+
+
+
+
+#define KMQ_CONF_SPACE_NAME L"KMQ"
+#define KMQ_CONF_QUEUE_DEAD_TIMEOUT_NAME L"QueueDeadTimeout"
+#define KMQ_CONF_CALL_DEAD_TIMEOUT_NAME L"CallDeadTimeout"
+
+extern CRITICAL_SECTION cs_kmq_global;
+extern kmq_timer kmq_queue_dead_timeout;
+extern kmq_timer kmq_call_dead_timeout;
+
+extern kmq_queue * queues;
+
+/* message type */
+extern CRITICAL_SECTION cs_kmq_types;
+extern kmq_msg_type *msg_types[KMQ_MSG_TYPE_MAX+1];
+
+void kmqint_init_msg_types(void);
+void kmqint_exit_msg_types(void);
+void kmqint_free_msg_type(int t);
+void kmqint_msg_type_create(int t);
+void kmqint_msg_type_add_sub(int t, kmq_msg_subscription *s);
+void kmqint_msg_type_del_sub(kmq_msg_subscription *s);
+kmq_msg_subscription * kmqint_msg_type_del_sub_hwnd(khm_int32 t, HWND hwnd);
+kmq_msg_subscription * kmqint_msg_type_del_sub_cb(khm_int32 t, kmq_callback_t cb);
+khm_int32 kmqint_msg_publish(kmq_message * m, khm_boolean try_send);
+khm_int32 kmqint_msg_type_set_handler(khm_int32 type, kmq_msg_completion_handler handler);
+int kmqint_notify_msg_completion(kmq_message * m);
+
+/* consumer */
+extern DWORD kmq_tls_queue;
+
+void kmqint_post_queue(kmq_queue * q, kmq_message *m);
+void kmqint_post(kmq_msg_subscription * s, kmq_message * m, khm_boolean try_send);
+kmq_queue * kmqint_get_thread_queue(void);
+void kmqint_get_queue_message_ref(kmq_queue * q, kmq_message_ref ** r);
+void kmqint_put_message_ref(kmq_message_ref * r);
+
+/* publisher */
+extern CRITICAL_SECTION cs_kmq_msg;
+extern CRITICAL_SECTION cs_kmq_msg_ref;
+
+kmq_message * kmqint_get_message(void);
+void kmqint_put_message(kmq_message *m);
+
+void kmqint_init(void);
+void kmqint_exit(void);
+void kmqint_attach_this_thread(void);
+void kmqint_detach_this_thread(void);
+
+khm_int32 kmqint_post_message_ex(
+ khm_int32 type,
+ khm_int32 subtype,
+ khm_ui_4 uparam,
+ void * blob,
+ kmq_call * call,
+ khm_boolean try_send);
+
+int kmqint_call_completion_handler(kmq_msg_completion_handler h,
+ kmq_message * m);
+
+/* global */
+extern kconf_schema schema_kmqconfig[];
+
+/* Lock hiearchy :
+
+ cs_kmq_types
+ cs_kmq_msg
+ cs_kmq_msg_ref
+ cs_compl
+ cs_kmq_global
+ kmq_queue::cs
+
+ If you have a level 'x' lock, you can obtain a level 'x+n' lock.
+ You can't obtain a 'x-n' lock if you already have a level 'x' lock.
+ If you don't have any locks, you can obtain any lock.
+ */
+#endif
diff --git a/src/windows/identity/kmq/kmqmain.c b/src/windows/identity/kmq/kmqmain.c
index 3e8176f1b3..fecfc17fdc 100644
--- a/src/windows/identity/kmq/kmqmain.c
+++ b/src/windows/identity/kmq/kmqmain.c
@@ -1,47 +1,47 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<kmqinternal.h>
-
-void
-kmq_process_attach(void) {
- kmqint_init();
-}
-
-void
-kmq_process_detach(void) {
- kmqint_exit();
-}
-
-void
-kmq_thread_attach(void) {
- kmqint_attach_this_thread();
-}
-
-void
-kmq_thread_detach(void) {
- kmqint_detach_this_thread();
-}
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<kmqinternal.h>
+
+void
+kmq_process_attach(void) {
+ kmqint_init();
+}
+
+void
+kmq_process_detach(void) {
+ kmqint_exit();
+}
+
+void
+kmq_thread_attach(void) {
+ kmqint_attach_this_thread();
+}
+
+void
+kmq_thread_detach(void) {
+ kmqint_detach_this_thread();
+}
diff --git a/src/windows/identity/kmq/msgtype.c b/src/windows/identity/kmq/msgtype.c
index 1b0868d836..b7ea21fcab 100644
--- a/src/windows/identity/kmq/msgtype.c
+++ b/src/windows/identity/kmq/msgtype.c
@@ -1,388 +1,388 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<kmqinternal.h>
-
-CRITICAL_SECTION cs_kmq_types;
-
-kmq_msg_type *msg_types[KMQ_MSG_TYPE_MAX + 1];
-kmq_msg_type *all_msg_types = NULL;
-
-/*! \internal
- \brief Initializes the message type data structures
- \note called with cs_mkq_global held */
-void kmqint_init_msg_types(void) {
- ZeroMemory(msg_types, sizeof(kmq_msg_type *) * (KMQ_MSG_TYPE_MAX + 1));
- InitializeCriticalSection(&cs_kmq_types);
-}
-
-/*! \internal
- \brief Frees up the message type data structures
- \note called with cs_mkq_global held */
-void kmqint_exit_msg_types(void) {
- int i;
-
- EnterCriticalSection(&cs_kmq_types);
- for(i=0;i<KMQ_MSG_TYPE_MAX;i++) {
- if(msg_types[i])
- kmqint_free_msg_type(i);
- }
- LeaveCriticalSection(&cs_kmq_types);
- DeleteCriticalSection(&cs_kmq_types);
-}
-
-/*! \internal
- \brief Notifies that the message has completed
-
- \return Zero if the completion handling is done. Nonzero if the
- handling is queued.
- */
-int kmqint_notify_msg_completion(kmq_message * m) {
- kmq_msg_type * mt;
- kmq_msg_completion_handler h;
-
- /* doing it this way to elude race conditions without
- obtaining a lock */
-
- mt = msg_types[m->type];
- if(mt == NULL)
- return 0;
- h = mt->completion_handler;
-
- /* handler is set to NULL before freeing type */
- if(h == NULL || msg_types[m->type] == NULL)
- return 0;
-
- return kmqint_call_completion_handler(h,m);
-}
-
-/* called with cs_mkq_global && cs_kmq_types held */
-void kmqint_free_msg_type(int t) {
- kmq_msg_type * pt;
- kmq_msg_subscription * s;
-
- pt = msg_types[t];
-
- msg_types[t] = NULL;
-
- if (pt == NULL)
- return;
-
- /* all the subscriptions attached to a message type are owned by
- the message type */
- LPOP(&pt->subs, &s);
- while(s) {
- s->magic = 0;
-
- PFREE(s);
-
- LPOP(&pt->subs, &s);
- }
-
- pt->completion_handler = NULL;
-
- PFREE(pt);
-}
-
-/*! \internal
- \brief Create a message type
- \note Obtains ::cs_kmq_types
- */
-void kmqint_msg_type_create(int t) {
- if(t < 0 || t > KMQ_MSG_TYPE_MAX)
- return;
-
- EnterCriticalSection(&cs_kmq_types);
- if(!msg_types[t]) {
- kmq_msg_type * mt;
- mt = PMALLOC(sizeof(kmq_msg_type));
- ZeroMemory(mt, sizeof(kmq_msg_type));
- mt->id = t;
- LINIT(mt);
- mt->subs = NULL;
- msg_types[t] = mt;
-
- LPUSH(&all_msg_types, mt);
- }
- LeaveCriticalSection(&cs_kmq_types);
-}
-
-KHMEXP khm_int32 KHMAPI kmq_register_type(wchar_t * name,
- khm_int32 * new_id)
-{
- int i;
- khm_int32 rv = KHM_ERROR_SUCCESS;
- BOOL registered = FALSE;
- int first_free = 0;
- size_t sz;
-
- if(FAILED(StringCbLength(name, KMQ_MAXCB_TYPE_NAME, &sz)) ||
- sz == 0)
- return KHM_ERROR_INVALID_PARAM;
- sz += sizeof(wchar_t);
-
- EnterCriticalSection(&cs_kmq_types);
- for(i=KMSGBASE_USER; i <= KMQ_MSG_TYPE_MAX; i++) {
- if(msg_types[i] == NULL) {
- if(first_free == 0)
- first_free = i;
- /* continue searching since we might find that this type
- is already registered. */
- } else {
- if(msg_types[i]->name != NULL &&
- !wcscmp(msg_types[i]->name, name)) {
-
- registered = TRUE;
- if (new_id)
- *new_id = i;
- break;
- }
- }
- }
-
- if(registered) {
- rv = KHM_ERROR_EXISTS;
- } else if(first_free == 0) {
- rv = KHM_ERROR_NO_RESOURCES;
- } else {
- kmqint_msg_type_create(first_free);
- msg_types[first_free]->name = PMALLOC(sz);
- StringCbCopy(msg_types[first_free]->name, sz, name);
-
- if(new_id != NULL)
- *new_id = first_free;
- }
- LeaveCriticalSection(&cs_kmq_types);
-
- return rv;
-}
-
-KHMEXP khm_int32 KHMAPI kmq_find_type(wchar_t * name, khm_int32 * id)
-{
- int i;
-
- EnterCriticalSection(&cs_kmq_types);
- for(i=KMSGBASE_USER; i <= KMQ_MSG_TYPE_MAX; i++) {
- if(msg_types[i] != NULL && msg_types[i]->name != NULL) {
- if(!wcscmp(msg_types[i]->name, name))
- break;
- }
- }
- LeaveCriticalSection(&cs_kmq_types);
-
- if(i <= KMQ_MSG_TYPE_MAX) {
- if(id != NULL)
- *id = i;
- return KHM_ERROR_SUCCESS;
- }
-
- return KHM_ERROR_NOT_FOUND;
-}
-
-KHMEXP khm_int32 KHMAPI kmq_unregister_type(khm_int32 id)
-{
- khm_int32 rv = KHM_ERROR_SUCCESS;
-
- if(id < KMSGBASE_USER || id > KMQ_MSG_TYPE_MAX)
- return KHM_ERROR_INVALID_PARAM;
-
- EnterCriticalSection(&cs_kmq_types);
- if(msg_types[id] != NULL) {
- EnterCriticalSection(&cs_kmq_global);
- kmqint_free_msg_type(id);
- LeaveCriticalSection(&cs_kmq_global);
- } else {
- rv = KHM_ERROR_NOT_FOUND;
- }
- LeaveCriticalSection(&cs_kmq_types);
-
- return rv;
-}
-
-/*! \internal
- \brief Adds a subscription to a message type
- \note Obtains ::cs_kmq_types
- */
-void kmqint_msg_type_add_sub(int t, kmq_msg_subscription *s) {
- kmq_msg_subscription * ts;
-
- if(t < 0 || t > KMQ_MSG_TYPE_MAX)
- return;
-
- if(!msg_types[t])
- kmqint_msg_type_create(t);
-
- EnterCriticalSection(&cs_kmq_types);
- s->type = t;
- /* check if we already have this subscription */
- ts = msg_types[t]->subs;
- while(ts) {
- if((ts->rcpt_type == s->rcpt_type) &&
- (((ts->rcpt_type == KMQ_RCPTTYPE_CB) && (ts->recipient.cb == s->recipient.cb)) ||
- ((ts->rcpt_type == KMQ_RCPTTYPE_HWND) && (ts->recipient.hwnd == s->recipient.hwnd))))
- break;
- ts = LNEXT(ts);
- }
- /* add it if we didn't find it */
- if(!ts) {
- LPUSH(&msg_types[t]->subs, s);
- }
- LeaveCriticalSection(&cs_kmq_types);
-}
-
-/*! \internal
- \brief Delete a subscription
- \note Obtains ::cs_kmq_types
- */
-void kmqint_msg_type_del_sub(kmq_msg_subscription *s) {
- int t = s->type;
-
- EnterCriticalSection(&cs_kmq_types);
- if(msg_types[t]) {
- LDELETE(&msg_types[t]->subs,s);
- }
- LeaveCriticalSection(&cs_kmq_types);
-}
-
-
-/*! \internal
- \brief Deletes a window subscription from a message type
- \note Obtains ::cs_kmq_types
-*/
-kmq_msg_subscription * kmqint_msg_type_del_sub_hwnd(khm_int32 t, HWND hwnd) {
- kmq_msg_subscription *s = NULL;
-
- if(t < 0 || t > KMQ_MSG_TYPE_MAX)
- return NULL;
-
- EnterCriticalSection(&cs_kmq_types);
- if(msg_types[t]) {
- s = msg_types[t]->subs;
- while(s) {
- kmq_msg_subscription * n = LNEXT(s);
- if(s->rcpt_type == KMQ_RCPTTYPE_HWND && s->recipient.hwnd == hwnd) {
- /*TODO: do more here? */
- LDELETE(&msg_types[t]->subs, s);
- break;
- }
- s = n;
- }
- }
- LeaveCriticalSection(&cs_kmq_types);
-
- return s;
-}
-
-/*! \internal
- \brief Delete a callback from a message type
- \note Obtains ::cs_kmq_types, ::cs_kmq_global
- */
-kmq_msg_subscription * kmqint_msg_type_del_sub_cb(khm_int32 t, kmq_callback_t cb) {
- kmq_msg_subscription *s;
- kmq_queue *q;
-
- if(t < 0 || t > KMQ_MSG_TYPE_MAX)
- return NULL;
-
- if(!msg_types[t])
- return NULL;
-
- q = kmqint_get_thread_queue();
-
- EnterCriticalSection(&cs_kmq_types);
- s = msg_types[t]->subs;
- while(s) {
- kmq_msg_subscription * n = LNEXT(s);
- if(s->rcpt_type == KMQ_RCPTTYPE_CB &&
- s->recipient.cb == cb &&
- s->queue == q) {
- /*TODO: do more here? */
- LDELETE(&msg_types[t]->subs, s);
- break;
- }
- s = n;
- }
- LeaveCriticalSection(&cs_kmq_types);
-
- return s;
-}
-
-/*! \internal
- \brief Publish a message
- \note Obtains ::cs_kmq_types, ::cs_kmq_msg_ref, kmq_queue::cs, ::cs_kmq_msg
- */
-khm_int32 kmqint_msg_publish(kmq_message * m, khm_boolean try_send) {
- khm_int32 rv = KHM_ERROR_SUCCESS;
-
- if(msg_types[m->type]) {
- kmq_msg_type *t;
- kmq_msg_subscription * s;
-
- EnterCriticalSection(&cs_kmq_types);
- EnterCriticalSection(&cs_kmq_msg);
- t = msg_types[m->type];
- s = t->subs;
- while(s) {
- kmqint_post(s, m, try_send);
- s = LNEXT(s);
- }
-
- if(m->nCompleted + m->nFailed == m->nSent) {
- kmqint_put_message(m);
- }
-
- LeaveCriticalSection(&cs_kmq_msg);
- LeaveCriticalSection(&cs_kmq_types);
-
- } else {
- EnterCriticalSection(&cs_kmq_msg);
- kmqint_put_message(m);
- LeaveCriticalSection(&cs_kmq_msg);
- }
- return rv;
-}
-
-/*! \internal
- \brief Sets the completion handler for a message type
- \note Obtains ::cs_kmq_types
- */
-khm_int32 kmqint_msg_type_set_handler(khm_int32 type, kmq_msg_completion_handler handler) {
-
- if (type == KMSG_SYSTEM)
- return KHM_ERROR_INVALID_PARAM;
-
- if(!msg_types[type])
- kmqint_msg_type_create(type);
-
- if(!msg_types[type])
- return KHM_ERROR_NO_RESOURCES;
-
- EnterCriticalSection(&cs_kmq_types);
- msg_types[type]->completion_handler = handler;
- LeaveCriticalSection(&cs_kmq_types);
-
- return KHM_ERROR_SUCCESS;
-}
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<kmqinternal.h>
+
+CRITICAL_SECTION cs_kmq_types;
+
+kmq_msg_type *msg_types[KMQ_MSG_TYPE_MAX + 1];
+kmq_msg_type *all_msg_types = NULL;
+
+/*! \internal
+ \brief Initializes the message type data structures
+ \note called with cs_mkq_global held */
+void kmqint_init_msg_types(void) {
+ ZeroMemory(msg_types, sizeof(kmq_msg_type *) * (KMQ_MSG_TYPE_MAX + 1));
+ InitializeCriticalSection(&cs_kmq_types);
+}
+
+/*! \internal
+ \brief Frees up the message type data structures
+ \note called with cs_mkq_global held */
+void kmqint_exit_msg_types(void) {
+ int i;
+
+ EnterCriticalSection(&cs_kmq_types);
+ for(i=0;i<KMQ_MSG_TYPE_MAX;i++) {
+ if(msg_types[i])
+ kmqint_free_msg_type(i);
+ }
+ LeaveCriticalSection(&cs_kmq_types);
+ DeleteCriticalSection(&cs_kmq_types);
+}
+
+/*! \internal
+ \brief Notifies that the message has completed
+
+ \return Zero if the completion handling is done. Nonzero if the
+ handling is queued.
+ */
+int kmqint_notify_msg_completion(kmq_message * m) {
+ kmq_msg_type * mt;
+ kmq_msg_completion_handler h;
+
+ /* doing it this way to elude race conditions without
+ obtaining a lock */
+
+ mt = msg_types[m->type];
+ if(mt == NULL)
+ return 0;
+ h = mt->completion_handler;
+
+ /* handler is set to NULL before freeing type */
+ if(h == NULL || msg_types[m->type] == NULL)
+ return 0;
+
+ return kmqint_call_completion_handler(h,m);
+}
+
+/* called with cs_mkq_global && cs_kmq_types held */
+void kmqint_free_msg_type(int t) {
+ kmq_msg_type * pt;
+ kmq_msg_subscription * s;
+
+ pt = msg_types[t];
+
+ msg_types[t] = NULL;
+
+ if (pt == NULL)
+ return;
+
+ /* all the subscriptions attached to a message type are owned by
+ the message type */
+ LPOP(&pt->subs, &s);
+ while(s) {
+ s->magic = 0;
+
+ PFREE(s);
+
+ LPOP(&pt->subs, &s);
+ }
+
+ pt->completion_handler = NULL;
+
+ PFREE(pt);
+}
+
+/*! \internal
+ \brief Create a message type
+ \note Obtains ::cs_kmq_types
+ */
+void kmqint_msg_type_create(int t) {
+ if(t < 0 || t > KMQ_MSG_TYPE_MAX)
+ return;
+
+ EnterCriticalSection(&cs_kmq_types);
+ if(!msg_types[t]) {
+ kmq_msg_type * mt;
+ mt = PMALLOC(sizeof(kmq_msg_type));
+ ZeroMemory(mt, sizeof(kmq_msg_type));
+ mt->id = t;
+ LINIT(mt);
+ mt->subs = NULL;
+ msg_types[t] = mt;
+
+ LPUSH(&all_msg_types, mt);
+ }
+ LeaveCriticalSection(&cs_kmq_types);
+}
+
+KHMEXP khm_int32 KHMAPI kmq_register_type(wchar_t * name,
+ khm_int32 * new_id)
+{
+ int i;
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+ BOOL registered = FALSE;
+ int first_free = 0;
+ size_t sz;
+
+ if(FAILED(StringCbLength(name, KMQ_MAXCB_TYPE_NAME, &sz)) ||
+ sz == 0)
+ return KHM_ERROR_INVALID_PARAM;
+ sz += sizeof(wchar_t);
+
+ EnterCriticalSection(&cs_kmq_types);
+ for(i=KMSGBASE_USER; i <= KMQ_MSG_TYPE_MAX; i++) {
+ if(msg_types[i] == NULL) {
+ if(first_free == 0)
+ first_free = i;
+ /* continue searching since we might find that this type
+ is already registered. */
+ } else {
+ if(msg_types[i]->name != NULL &&
+ !wcscmp(msg_types[i]->name, name)) {
+
+ registered = TRUE;
+ if (new_id)
+ *new_id = i;
+ break;
+ }
+ }
+ }
+
+ if(registered) {
+ rv = KHM_ERROR_EXISTS;
+ } else if(first_free == 0) {
+ rv = KHM_ERROR_NO_RESOURCES;
+ } else {
+ kmqint_msg_type_create(first_free);
+ msg_types[first_free]->name = PMALLOC(sz);
+ StringCbCopy(msg_types[first_free]->name, sz, name);
+
+ if(new_id != NULL)
+ *new_id = first_free;
+ }
+ LeaveCriticalSection(&cs_kmq_types);
+
+ return rv;
+}
+
+KHMEXP khm_int32 KHMAPI kmq_find_type(wchar_t * name, khm_int32 * id)
+{
+ int i;
+
+ EnterCriticalSection(&cs_kmq_types);
+ for(i=KMSGBASE_USER; i <= KMQ_MSG_TYPE_MAX; i++) {
+ if(msg_types[i] != NULL && msg_types[i]->name != NULL) {
+ if(!wcscmp(msg_types[i]->name, name))
+ break;
+ }
+ }
+ LeaveCriticalSection(&cs_kmq_types);
+
+ if(i <= KMQ_MSG_TYPE_MAX) {
+ if(id != NULL)
+ *id = i;
+ return KHM_ERROR_SUCCESS;
+ }
+
+ return KHM_ERROR_NOT_FOUND;
+}
+
+KHMEXP khm_int32 KHMAPI kmq_unregister_type(khm_int32 id)
+{
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+
+ if(id < KMSGBASE_USER || id > KMQ_MSG_TYPE_MAX)
+ return KHM_ERROR_INVALID_PARAM;
+
+ EnterCriticalSection(&cs_kmq_types);
+ if(msg_types[id] != NULL) {
+ EnterCriticalSection(&cs_kmq_global);
+ kmqint_free_msg_type(id);
+ LeaveCriticalSection(&cs_kmq_global);
+ } else {
+ rv = KHM_ERROR_NOT_FOUND;
+ }
+ LeaveCriticalSection(&cs_kmq_types);
+
+ return rv;
+}
+
+/*! \internal
+ \brief Adds a subscription to a message type
+ \note Obtains ::cs_kmq_types
+ */
+void kmqint_msg_type_add_sub(int t, kmq_msg_subscription *s) {
+ kmq_msg_subscription * ts;
+
+ if(t < 0 || t > KMQ_MSG_TYPE_MAX)
+ return;
+
+ if(!msg_types[t])
+ kmqint_msg_type_create(t);
+
+ EnterCriticalSection(&cs_kmq_types);
+ s->type = t;
+ /* check if we already have this subscription */
+ ts = msg_types[t]->subs;
+ while(ts) {
+ if((ts->rcpt_type == s->rcpt_type) &&
+ (((ts->rcpt_type == KMQ_RCPTTYPE_CB) && (ts->recipient.cb == s->recipient.cb)) ||
+ ((ts->rcpt_type == KMQ_RCPTTYPE_HWND) && (ts->recipient.hwnd == s->recipient.hwnd))))
+ break;
+ ts = LNEXT(ts);
+ }
+ /* add it if we didn't find it */
+ if(!ts) {
+ LPUSH(&msg_types[t]->subs, s);
+ }
+ LeaveCriticalSection(&cs_kmq_types);
+}
+
+/*! \internal
+ \brief Delete a subscription
+ \note Obtains ::cs_kmq_types
+ */
+void kmqint_msg_type_del_sub(kmq_msg_subscription *s) {
+ int t = s->type;
+
+ EnterCriticalSection(&cs_kmq_types);
+ if(msg_types[t]) {
+ LDELETE(&msg_types[t]->subs,s);
+ }
+ LeaveCriticalSection(&cs_kmq_types);
+}
+
+
+/*! \internal
+ \brief Deletes a window subscription from a message type
+ \note Obtains ::cs_kmq_types
+*/
+kmq_msg_subscription * kmqint_msg_type_del_sub_hwnd(khm_int32 t, HWND hwnd) {
+ kmq_msg_subscription *s = NULL;
+
+ if(t < 0 || t > KMQ_MSG_TYPE_MAX)
+ return NULL;
+
+ EnterCriticalSection(&cs_kmq_types);
+ if(msg_types[t]) {
+ s = msg_types[t]->subs;
+ while(s) {
+ kmq_msg_subscription * n = LNEXT(s);
+ if(s->rcpt_type == KMQ_RCPTTYPE_HWND && s->recipient.hwnd == hwnd) {
+ /*TODO: do more here? */
+ LDELETE(&msg_types[t]->subs, s);
+ break;
+ }
+ s = n;
+ }
+ }
+ LeaveCriticalSection(&cs_kmq_types);
+
+ return s;
+}
+
+/*! \internal
+ \brief Delete a callback from a message type
+ \note Obtains ::cs_kmq_types, ::cs_kmq_global
+ */
+kmq_msg_subscription * kmqint_msg_type_del_sub_cb(khm_int32 t, kmq_callback_t cb) {
+ kmq_msg_subscription *s;
+ kmq_queue *q;
+
+ if(t < 0 || t > KMQ_MSG_TYPE_MAX)
+ return NULL;
+
+ if(!msg_types[t])
+ return NULL;
+
+ q = kmqint_get_thread_queue();
+
+ EnterCriticalSection(&cs_kmq_types);
+ s = msg_types[t]->subs;
+ while(s) {
+ kmq_msg_subscription * n = LNEXT(s);
+ if(s->rcpt_type == KMQ_RCPTTYPE_CB &&
+ s->recipient.cb == cb &&
+ s->queue == q) {
+ /*TODO: do more here? */
+ LDELETE(&msg_types[t]->subs, s);
+ break;
+ }
+ s = n;
+ }
+ LeaveCriticalSection(&cs_kmq_types);
+
+ return s;
+}
+
+/*! \internal
+ \brief Publish a message
+ \note Obtains ::cs_kmq_types, ::cs_kmq_msg_ref, kmq_queue::cs, ::cs_kmq_msg
+ */
+khm_int32 kmqint_msg_publish(kmq_message * m, khm_boolean try_send) {
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+
+ if(msg_types[m->type]) {
+ kmq_msg_type *t;
+ kmq_msg_subscription * s;
+
+ EnterCriticalSection(&cs_kmq_types);
+ EnterCriticalSection(&cs_kmq_msg);
+ t = msg_types[m->type];
+ s = t->subs;
+ while(s) {
+ kmqint_post(s, m, try_send);
+ s = LNEXT(s);
+ }
+
+ if(m->nCompleted + m->nFailed == m->nSent) {
+ kmqint_put_message(m);
+ }
+
+ LeaveCriticalSection(&cs_kmq_msg);
+ LeaveCriticalSection(&cs_kmq_types);
+
+ } else {
+ EnterCriticalSection(&cs_kmq_msg);
+ kmqint_put_message(m);
+ LeaveCriticalSection(&cs_kmq_msg);
+ }
+ return rv;
+}
+
+/*! \internal
+ \brief Sets the completion handler for a message type
+ \note Obtains ::cs_kmq_types
+ */
+khm_int32 kmqint_msg_type_set_handler(khm_int32 type, kmq_msg_completion_handler handler) {
+
+ if (type == KMSG_SYSTEM)
+ return KHM_ERROR_INVALID_PARAM;
+
+ if(!msg_types[type])
+ kmqint_msg_type_create(type);
+
+ if(!msg_types[type])
+ return KHM_ERROR_NO_RESOURCES;
+
+ EnterCriticalSection(&cs_kmq_types);
+ msg_types[type]->completion_handler = handler;
+ LeaveCriticalSection(&cs_kmq_types);
+
+ return KHM_ERROR_SUCCESS;
+}
diff --git a/src/windows/identity/kmq/publisher.c b/src/windows/identity/kmq/publisher.c
index 66360fb50b..2323837e2d 100644
--- a/src/windows/identity/kmq/publisher.c
+++ b/src/windows/identity/kmq/publisher.c
@@ -1,556 +1,556 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<kmqinternal.h>
-
-CRITICAL_SECTION cs_kmq_msg;
-kmq_message * msg_free = NULL;
-kmq_message * msg_active = NULL;
-
-#ifdef DEBUG
-
-#include<stdio.h>
-
-void
-kmqint_dump_publisher(FILE * f) {
-
- int n_free = 0;
- int n_active = 0;
- kmq_message * m;
-
- EnterCriticalSection(&cs_kmq_msg);
-
- fprintf(f, "qp0\t*** Free Messages ***\n");
- fprintf(f, "qp1\tAddress\n");
-
- m = msg_free;
- while(m) {
- n_free++;
-
- fprintf(f, "qp2\t0x%p\n", m);
-
- m = LNEXT(m);
- }
-
- fprintf(f, "qp3\tTotal free messages : %d\n", n_free);
-
- fprintf(f, "qp4\t*** Active Messages ***\n");
- fprintf(f, "qp5\tAddress\tType\tSubtype\tuParam\tvParam\tnSent\tnCompleted\tnFailed\twait_o\trefcount\n");
-
- m = msg_active;
- while(m) {
-
- n_active++;
-
- fprintf(f, "qp6\t0x%p\t%d\t%d\t0x%x\t0x%p\t%d\t%d\t%d\t0x%p\t%d\n",
- m,
- (int) m->type,
- (int) m->subtype,
- (unsigned int) m->uparam,
- m->vparam,
- (int) m->nSent,
- (int) m->nCompleted,
- (int) m->nFailed,
- (void *) m->wait_o,
- (int) m->refcount);
-
- m = LNEXT(m);
- }
-
- fprintf(f, "qp7\tTotal number of active messages = %d\n", n_active);
-
- fprintf(f, "qp8\t--- End ---\n");
-
- LeaveCriticalSection(&cs_kmq_msg);
-
-}
-
-#endif
-
-/*! \internal
- \brief Get a message object
- \note called with ::cs_kmq_msg held */
-kmq_message *
-kmqint_get_message(void) {
- kmq_message * m;
-
- LPOP(&msg_free,&m);
- if(!m) {
- /* allocate one */
- m = PMALLOC(sizeof(kmq_message));
- }
- ZeroMemory((void*)m, sizeof(kmq_message));
-
- LPUSH(&msg_active, m);
-
- return m;
-}
-
-/*! \internal
- \brief Frees a message object
- \note called with ::cs_kmq_msg held
- */
-void
-kmqint_put_message(kmq_message *m) {
- int queued;
- /* we can only free a message if the refcount is zero.
- Otherwise we have to wait until the call is freed. */
- if(m->refcount == 0) {
- LDELETE(&msg_active, m);
- LeaveCriticalSection(&cs_kmq_msg);
- queued = kmqint_notify_msg_completion(m);
- EnterCriticalSection(&cs_kmq_msg);
- if (!queued) {
- if(m->err_ctx) {
- kherr_release_context(m->err_ctx);
- m->err_ctx = NULL;
- }
- if(m->wait_o) {
- CloseHandle(m->wait_o);
- m->wait_o = NULL;
- }
- LPUSH(&msg_free,m);
- }
- } else if(m->wait_o) {
- SetEvent(m->wait_o);
- }
-}
-
-/*! \internal
- \note Obtains ::cs_kmq_msg, ::cs_kmq_types, ::cs_kmq_msg_ref, kmq_queue::cs
- */
-KHMEXP khm_int32 KHMAPI
-kmq_send_message(khm_int32 type, khm_int32 subtype,
- khm_ui_4 uparam, void * blob) {
- kmq_call c;
- khm_int32 rv = KHM_ERROR_SUCCESS;
-
- rv = kmqint_post_message_ex(type, subtype, uparam, blob, &c, TRUE);
- if(KHM_FAILED(rv))
- return rv;
-
- rv = kmq_wait(c, INFINITE);
- if(KHM_SUCCEEDED(rv) && c->nFailed > 0)
- rv = KHM_ERROR_PARTIAL;
-
- kmq_free_call(c);
-
- return rv;
-}
-
-/*! \internal
- \note Obtains ::cs_kmq_msg, ::cs_kmq_types, ::cs_kmq_msg_ref, kmq_queue::cs
- */
-KHMEXP khm_int32 KHMAPI
-kmq_post_message(khm_int32 type, khm_int32 subtype,
- khm_ui_4 uparam, void * blob) {
- return kmqint_post_message_ex(type, subtype, uparam, blob, NULL, FALSE);
-}
-
-/*! \internal
- \brief Frees a call
- \note Obtains ::cs_kmq_msg
- */
-KHMEXP khm_int32 KHMAPI
-kmq_free_call(kmq_call call) {
- kmq_message * m;
-
- m = call;
-
- EnterCriticalSection(&cs_kmq_msg);
- m->refcount--;
- if(!m->refcount) {
- kmqint_put_message(m);
- }
- LeaveCriticalSection(&cs_kmq_msg);
-
- return KHM_ERROR_SUCCESS;
-}
-
-/*! \internal
- \note Obtains ::cs_kmq_msg, ::cs_kmq_types, ::cs_kmq_msg_ref, kmq_queue::cs
- */
-khm_int32
-kmqint_post_message_ex(khm_int32 type, khm_int32 subtype, khm_ui_4 uparam,
- void * blob, kmq_call * call, khm_boolean try_send)
-{
- kmq_message * m;
- kherr_context * ctx;
-
- EnterCriticalSection(&cs_kmq_msg);
- m = kmqint_get_message();
- LeaveCriticalSection(&cs_kmq_msg);
-
- m->type = type;
- m->subtype = subtype;
- m->uparam = uparam;
- m->vparam = blob;
-
- m->timeSent = GetTickCount();
- m->timeExpire = m->timeSent + kmq_call_dead_timeout;
-
- ctx = kherr_peek_context();
- if (ctx) {
- if (ctx->flags & KHERR_CF_TRANSITIVE) {
- m->err_ctx = ctx;
- /* leave it held */
- } else {
- kherr_release_context(ctx);
- }
- }
-
- if(call) {
- m->wait_o = CreateEvent(NULL,FALSE,FALSE,NULL);
- *call = m;
- m->refcount++;
- } else
- m->wait_o = NULL;
-
- kmqint_msg_publish(m, try_send);
-
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP khm_int32 KHMAPI
-kmq_post_message_ex(khm_int32 type, khm_int32 subtype,
- khm_ui_4 uparam, void * blob, kmq_call * call)
-{
- return kmqint_post_message_ex(type, subtype, uparam, blob, call, FALSE);
-}
-
-KHMEXP khm_int32 KHMAPI
-kmq_abort_call(kmq_call call)
-{
- /* TODO: Implement this */
- return KHM_ERROR_NOT_IMPLEMENTED;
-}
-
-/*! \internal
-*/
-KHMEXP khm_int32 KHMAPI
-kmq_post_sub_msg(khm_handle sub, khm_int32 type, khm_int32 subtype,
- khm_ui_4 uparam, void * vparam)
-{
- return kmq_post_sub_msg_ex(sub, type, subtype, uparam, vparam, NULL);
-}
-
-/*! \internal
-*/
-khm_int32
-kmqint_post_sub_msg_ex(khm_handle sub, khm_int32 type, khm_int32 subtype,
- khm_ui_4 uparam, void * vparam,
- kmq_call * call, khm_boolean try_send)
-{
- kmq_message * m;
- kherr_context * ctx;
-
- EnterCriticalSection(&cs_kmq_msg);
- m = kmqint_get_message();
- LeaveCriticalSection(&cs_kmq_msg);
-
- m->type = type;
- m->subtype = subtype;
- m->uparam = uparam;
- m->vparam = vparam;
-
- m->timeSent = GetTickCount();
- m->timeExpire = m->timeSent + kmq_call_dead_timeout;
-
- ctx = kherr_peek_context();
- if (ctx) {
- if (ctx->flags & KHERR_CF_TRANSITIVE) {
- m->err_ctx = ctx;
- /* leave it held */
- } else {
- kherr_release_context(ctx);
- }
- }
-
- if(call) {
- m->wait_o = CreateEvent(NULL,FALSE,FALSE,NULL);
- *call = m;
- m->refcount++;
- } else
- m->wait_o = NULL;
-
- EnterCriticalSection(&cs_kmq_msg);
- kmqint_post((kmq_msg_subscription *) sub, m, try_send);
-
- if(m->nCompleted + m->nFailed == m->nSent) {
- kmqint_put_message(m);
- }
- LeaveCriticalSection(&cs_kmq_msg);
-
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP khm_int32 KHMAPI
-kmq_post_sub_msg_ex(khm_handle sub, khm_int32 type, khm_int32 subtype,
- khm_ui_4 uparam, void * vparam, kmq_call * call)
-{
- return kmqint_post_sub_msg_ex(sub, type, subtype,
- uparam, vparam, call, FALSE);
-}
-
-khm_int32
-kmqint_post_subs_msg_ex(khm_handle * subs, khm_size n_subs, khm_int32 type,
- khm_int32 subtype, khm_ui_4 uparam, void * vparam,
- kmq_call * call, khm_boolean try_send)
-{
- kmq_message * m;
- kherr_context * ctx;
- khm_size i;
-
- if(n_subs == 0)
- return KHM_ERROR_SUCCESS;
-
- EnterCriticalSection(&cs_kmq_msg);
- m = kmqint_get_message();
- LeaveCriticalSection(&cs_kmq_msg);
-
- m->type = type;
- m->subtype = subtype;
- m->uparam = uparam;
- m->vparam = vparam;
-
- m->timeSent = GetTickCount();
- m->timeExpire = m->timeSent + kmq_call_dead_timeout;
-
- ctx = kherr_peek_context();
- if (ctx) {
- if (ctx->flags & KHERR_CF_TRANSITIVE) {
- m->err_ctx = ctx;
- /* leave it held */
- } else {
- kherr_release_context(ctx);
- }
- }
-
- if(call) {
- m->wait_o = CreateEvent(NULL,FALSE,FALSE,NULL);
- *call = m;
- m->refcount++;
- } else
- m->wait_o = NULL;
-
- EnterCriticalSection(&cs_kmq_msg);
- for(i=0;i<n_subs;i++) {
- kmqint_post((kmq_msg_subscription *) subs[i], m, try_send);
- }
-
- if(m->nCompleted + m->nFailed == m->nSent) {
- kmqint_put_message(m);
- }
- LeaveCriticalSection(&cs_kmq_msg);
-
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP khm_int32 KHMAPI
-kmq_post_subs_msg(khm_handle * subs,
- khm_size n_subs,
- khm_int32 type,
- khm_int32 subtype,
- khm_ui_4 uparam,
- void * vparam)
-{
- return kmqint_post_subs_msg_ex(subs,
- n_subs,
- type,
- subtype,
- uparam,
- vparam,
- NULL,
- FALSE);
-}
-
-KHMEXP khm_int32 KHMAPI
-kmq_post_subs_msg_ex(khm_handle * subs,
- khm_int32 n_subs,
- khm_int32 type,
- khm_int32 subtype,
- khm_ui_4 uparam,
- void * vparam,
- kmq_call * call)
-{
- return kmqint_post_subs_msg_ex(subs, n_subs, type, subtype,
- uparam, vparam, call, FALSE);
-}
-
-KHMEXP khm_int32 KHMAPI
-kmq_send_subs_msg(khm_handle *subs,
- khm_int32 n_subs,
- khm_int32 type,
- khm_int32 subtype,
- khm_ui_4 uparam,
- void * vparam)
-{
- kmq_call c;
- khm_int32 rv = KHM_ERROR_SUCCESS;
-
- rv = kmqint_post_subs_msg_ex(subs, n_subs, type, subtype,
- uparam, vparam, &c, TRUE);
- if(KHM_FAILED(rv))
- return rv;
-
- rv = kmq_wait(c, INFINITE);
- if(KHM_SUCCEEDED(rv) && c->nFailed > 0)
- rv = KHM_ERROR_PARTIAL;
-
- kmq_free_call(c);
-
- return rv;
-}
-
-/*! \internal
-*/
-KHMEXP khm_int32 KHMAPI
-kmq_send_sub_msg(khm_handle sub, khm_int32 type, khm_int32 subtype,
- khm_ui_4 uparam, void * vparam)
-{
- kmq_call c;
- khm_int32 rv = KHM_ERROR_SUCCESS;
-
- rv = kmqint_post_sub_msg_ex(sub, type, subtype, uparam, vparam, &c, TRUE);
- if(KHM_FAILED(rv))
- return rv;
-
- rv = kmq_wait(c, INFINITE);
- if(KHM_SUCCEEDED(rv) && c->nFailed > 0)
- rv = KHM_ERROR_PARTIAL;
-
- kmq_free_call(c);
-
- return rv;
-}
-
-/*! \internal
- \note Obtains ::cs_kmq_global, ::cs_kmq_msg, ::cs_kmq_msg_ref, kmq_queue::cs
- */
-KHMEXP khm_int32 KHMAPI
-kmq_send_thread_quit_message(kmq_thread_id thread, khm_ui_4 uparam) {
- kmq_call c;
- khm_int32 rv = KHM_ERROR_SUCCESS;
-
- rv = kmq_post_thread_quit_message(thread, uparam, &c);
- if(KHM_FAILED(rv))
- return rv;
-
- rv = kmq_wait(c, INFINITE);
-
- kmq_free_call(c);
-
- return rv;
-}
-
-/*! \internal
- \note Obtains ::cs_kmq_global, ::cs_kmq_msg, ::cs_kmq_msg_ref, kmq_queue::cs
- */
-KHMEXP khm_int32 KHMAPI
-kmq_post_thread_quit_message(kmq_thread_id thread,
- khm_ui_4 uparam, kmq_call * call) {
- kmq_message * m;
- kmq_queue * q;
-
- EnterCriticalSection(&cs_kmq_global);
- q = queues;
- while(q) {
- if(q->thread == thread)
- break;
- q = LNEXT(q);
- }
- LeaveCriticalSection(&cs_kmq_global);
-
- if(!q)
- return KHM_ERROR_NOT_FOUND;
-
- EnterCriticalSection(&cs_kmq_msg);
- m = kmqint_get_message();
- LeaveCriticalSection(&cs_kmq_msg);
-
- m->type = KMSG_SYSTEM;
- m->subtype = KMSG_SYSTEM_EXIT;
- m->uparam = uparam;
- m->vparam = NULL;
-
- m->timeSent = GetTickCount();
- m->timeExpire = m->timeSent + kmq_call_dead_timeout;
-
- if(call) {
- m->wait_o = CreateEvent(NULL,FALSE,FALSE,NULL);
- *call = m;
- m->refcount++;
- } else
- m->wait_o = NULL;
-
- kmqint_post_queue(q, m);
-
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP khm_int32 KHMAPI
-kmq_get_next_response(kmq_call call, void ** resp) {
- /* TODO: Implement this */
- return 0;
-}
-
-KHMEXP khm_boolean KHMAPI
-kmq_has_completed(kmq_call call) {
- khm_boolean completed;
-
- EnterCriticalSection(&cs_kmq_msg);
- completed = (call->nCompleted + call->nFailed == call->nSent);
- LeaveCriticalSection(&cs_kmq_msg);
-
- return completed;
-}
-
-KHMEXP khm_int32 KHMAPI
-kmq_wait(kmq_call call, kmq_timer timeout) {
- kmq_message * m = call;
- DWORD rv;
- /*TODO: check for call free */
-
- if(m && m->wait_o) {
- rv = WaitForSingleObject(m->wait_o, timeout);
- if(rv == WAIT_OBJECT_0)
- return KHM_ERROR_SUCCESS;
- else
- return KHM_ERROR_TIMEOUT;
- } else
- return KHM_ERROR_INVALID_PARAM;
-}
-
-/*! \internal
- \note Obtains ::cs_kmq_types
- */
-KHMEXP khm_int32 KHMAPI
-kmq_set_completion_handler(khm_int32 type,
- kmq_msg_completion_handler handler) {
- return kmqint_msg_type_set_handler(type, handler);
-}
-
-
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<kmqinternal.h>
+
+CRITICAL_SECTION cs_kmq_msg;
+kmq_message * msg_free = NULL;
+kmq_message * msg_active = NULL;
+
+#ifdef DEBUG
+
+#include<stdio.h>
+
+void
+kmqint_dump_publisher(FILE * f) {
+
+ int n_free = 0;
+ int n_active = 0;
+ kmq_message * m;
+
+ EnterCriticalSection(&cs_kmq_msg);
+
+ fprintf(f, "qp0\t*** Free Messages ***\n");
+ fprintf(f, "qp1\tAddress\n");
+
+ m = msg_free;
+ while(m) {
+ n_free++;
+
+ fprintf(f, "qp2\t0x%p\n", m);
+
+ m = LNEXT(m);
+ }
+
+ fprintf(f, "qp3\tTotal free messages : %d\n", n_free);
+
+ fprintf(f, "qp4\t*** Active Messages ***\n");
+ fprintf(f, "qp5\tAddress\tType\tSubtype\tuParam\tvParam\tnSent\tnCompleted\tnFailed\twait_o\trefcount\n");
+
+ m = msg_active;
+ while(m) {
+
+ n_active++;
+
+ fprintf(f, "qp6\t0x%p\t%d\t%d\t0x%x\t0x%p\t%d\t%d\t%d\t0x%p\t%d\n",
+ m,
+ (int) m->type,
+ (int) m->subtype,
+ (unsigned int) m->uparam,
+ m->vparam,
+ (int) m->nSent,
+ (int) m->nCompleted,
+ (int) m->nFailed,
+ (void *) m->wait_o,
+ (int) m->refcount);
+
+ m = LNEXT(m);
+ }
+
+ fprintf(f, "qp7\tTotal number of active messages = %d\n", n_active);
+
+ fprintf(f, "qp8\t--- End ---\n");
+
+ LeaveCriticalSection(&cs_kmq_msg);
+
+}
+
+#endif
+
+/*! \internal
+ \brief Get a message object
+ \note called with ::cs_kmq_msg held */
+kmq_message *
+kmqint_get_message(void) {
+ kmq_message * m;
+
+ LPOP(&msg_free,&m);
+ if(!m) {
+ /* allocate one */
+ m = PMALLOC(sizeof(kmq_message));
+ }
+ ZeroMemory((void*)m, sizeof(kmq_message));
+
+ LPUSH(&msg_active, m);
+
+ return m;
+}
+
+/*! \internal
+ \brief Frees a message object
+ \note called with ::cs_kmq_msg held
+ */
+void
+kmqint_put_message(kmq_message *m) {
+ int queued;
+ /* we can only free a message if the refcount is zero.
+ Otherwise we have to wait until the call is freed. */
+ if(m->refcount == 0) {
+ LDELETE(&msg_active, m);
+ LeaveCriticalSection(&cs_kmq_msg);
+ queued = kmqint_notify_msg_completion(m);
+ EnterCriticalSection(&cs_kmq_msg);
+ if (!queued) {
+ if(m->err_ctx) {
+ kherr_release_context(m->err_ctx);
+ m->err_ctx = NULL;
+ }
+ if(m->wait_o) {
+ CloseHandle(m->wait_o);
+ m->wait_o = NULL;
+ }
+ LPUSH(&msg_free,m);
+ }
+ } else if(m->wait_o) {
+ SetEvent(m->wait_o);
+ }
+}
+
+/*! \internal
+ \note Obtains ::cs_kmq_msg, ::cs_kmq_types, ::cs_kmq_msg_ref, kmq_queue::cs
+ */
+KHMEXP khm_int32 KHMAPI
+kmq_send_message(khm_int32 type, khm_int32 subtype,
+ khm_ui_4 uparam, void * blob) {
+ kmq_call c;
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+
+ rv = kmqint_post_message_ex(type, subtype, uparam, blob, &c, TRUE);
+ if(KHM_FAILED(rv))
+ return rv;
+
+ rv = kmq_wait(c, INFINITE);
+ if(KHM_SUCCEEDED(rv) && c->nFailed > 0)
+ rv = KHM_ERROR_PARTIAL;
+
+ kmq_free_call(c);
+
+ return rv;
+}
+
+/*! \internal
+ \note Obtains ::cs_kmq_msg, ::cs_kmq_types, ::cs_kmq_msg_ref, kmq_queue::cs
+ */
+KHMEXP khm_int32 KHMAPI
+kmq_post_message(khm_int32 type, khm_int32 subtype,
+ khm_ui_4 uparam, void * blob) {
+ return kmqint_post_message_ex(type, subtype, uparam, blob, NULL, FALSE);
+}
+
+/*! \internal
+ \brief Frees a call
+ \note Obtains ::cs_kmq_msg
+ */
+KHMEXP khm_int32 KHMAPI
+kmq_free_call(kmq_call call) {
+ kmq_message * m;
+
+ m = call;
+
+ EnterCriticalSection(&cs_kmq_msg);
+ m->refcount--;
+ if(!m->refcount) {
+ kmqint_put_message(m);
+ }
+ LeaveCriticalSection(&cs_kmq_msg);
+
+ return KHM_ERROR_SUCCESS;
+}
+
+/*! \internal
+ \note Obtains ::cs_kmq_msg, ::cs_kmq_types, ::cs_kmq_msg_ref, kmq_queue::cs
+ */
+khm_int32
+kmqint_post_message_ex(khm_int32 type, khm_int32 subtype, khm_ui_4 uparam,
+ void * blob, kmq_call * call, khm_boolean try_send)
+{
+ kmq_message * m;
+ kherr_context * ctx;
+
+ EnterCriticalSection(&cs_kmq_msg);
+ m = kmqint_get_message();
+ LeaveCriticalSection(&cs_kmq_msg);
+
+ m->type = type;
+ m->subtype = subtype;
+ m->uparam = uparam;
+ m->vparam = blob;
+
+ m->timeSent = GetTickCount();
+ m->timeExpire = m->timeSent + kmq_call_dead_timeout;
+
+ ctx = kherr_peek_context();
+ if (ctx) {
+ if (ctx->flags & KHERR_CF_TRANSITIVE) {
+ m->err_ctx = ctx;
+ /* leave it held */
+ } else {
+ kherr_release_context(ctx);
+ }
+ }
+
+ if(call) {
+ m->wait_o = CreateEvent(NULL,FALSE,FALSE,NULL);
+ *call = m;
+ m->refcount++;
+ } else
+ m->wait_o = NULL;
+
+ kmqint_msg_publish(m, try_send);
+
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP khm_int32 KHMAPI
+kmq_post_message_ex(khm_int32 type, khm_int32 subtype,
+ khm_ui_4 uparam, void * blob, kmq_call * call)
+{
+ return kmqint_post_message_ex(type, subtype, uparam, blob, call, FALSE);
+}
+
+KHMEXP khm_int32 KHMAPI
+kmq_abort_call(kmq_call call)
+{
+ /* TODO: Implement this */
+ return KHM_ERROR_NOT_IMPLEMENTED;
+}
+
+/*! \internal
+*/
+KHMEXP khm_int32 KHMAPI
+kmq_post_sub_msg(khm_handle sub, khm_int32 type, khm_int32 subtype,
+ khm_ui_4 uparam, void * vparam)
+{
+ return kmq_post_sub_msg_ex(sub, type, subtype, uparam, vparam, NULL);
+}
+
+/*! \internal
+*/
+khm_int32
+kmqint_post_sub_msg_ex(khm_handle sub, khm_int32 type, khm_int32 subtype,
+ khm_ui_4 uparam, void * vparam,
+ kmq_call * call, khm_boolean try_send)
+{
+ kmq_message * m;
+ kherr_context * ctx;
+
+ EnterCriticalSection(&cs_kmq_msg);
+ m = kmqint_get_message();
+ LeaveCriticalSection(&cs_kmq_msg);
+
+ m->type = type;
+ m->subtype = subtype;
+ m->uparam = uparam;
+ m->vparam = vparam;
+
+ m->timeSent = GetTickCount();
+ m->timeExpire = m->timeSent + kmq_call_dead_timeout;
+
+ ctx = kherr_peek_context();
+ if (ctx) {
+ if (ctx->flags & KHERR_CF_TRANSITIVE) {
+ m->err_ctx = ctx;
+ /* leave it held */
+ } else {
+ kherr_release_context(ctx);
+ }
+ }
+
+ if(call) {
+ m->wait_o = CreateEvent(NULL,FALSE,FALSE,NULL);
+ *call = m;
+ m->refcount++;
+ } else
+ m->wait_o = NULL;
+
+ EnterCriticalSection(&cs_kmq_msg);
+ kmqint_post((kmq_msg_subscription *) sub, m, try_send);
+
+ if(m->nCompleted + m->nFailed == m->nSent) {
+ kmqint_put_message(m);
+ }
+ LeaveCriticalSection(&cs_kmq_msg);
+
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP khm_int32 KHMAPI
+kmq_post_sub_msg_ex(khm_handle sub, khm_int32 type, khm_int32 subtype,
+ khm_ui_4 uparam, void * vparam, kmq_call * call)
+{
+ return kmqint_post_sub_msg_ex(sub, type, subtype,
+ uparam, vparam, call, FALSE);
+}
+
+khm_int32
+kmqint_post_subs_msg_ex(khm_handle * subs, khm_size n_subs, khm_int32 type,
+ khm_int32 subtype, khm_ui_4 uparam, void * vparam,
+ kmq_call * call, khm_boolean try_send)
+{
+ kmq_message * m;
+ kherr_context * ctx;
+ khm_size i;
+
+ if(n_subs == 0)
+ return KHM_ERROR_SUCCESS;
+
+ EnterCriticalSection(&cs_kmq_msg);
+ m = kmqint_get_message();
+ LeaveCriticalSection(&cs_kmq_msg);
+
+ m->type = type;
+ m->subtype = subtype;
+ m->uparam = uparam;
+ m->vparam = vparam;
+
+ m->timeSent = GetTickCount();
+ m->timeExpire = m->timeSent + kmq_call_dead_timeout;
+
+ ctx = kherr_peek_context();
+ if (ctx) {
+ if (ctx->flags & KHERR_CF_TRANSITIVE) {
+ m->err_ctx = ctx;
+ /* leave it held */
+ } else {
+ kherr_release_context(ctx);
+ }
+ }
+
+ if(call) {
+ m->wait_o = CreateEvent(NULL,FALSE,FALSE,NULL);
+ *call = m;
+ m->refcount++;
+ } else
+ m->wait_o = NULL;
+
+ EnterCriticalSection(&cs_kmq_msg);
+ for(i=0;i<n_subs;i++) {
+ kmqint_post((kmq_msg_subscription *) subs[i], m, try_send);
+ }
+
+ if(m->nCompleted + m->nFailed == m->nSent) {
+ kmqint_put_message(m);
+ }
+ LeaveCriticalSection(&cs_kmq_msg);
+
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP khm_int32 KHMAPI
+kmq_post_subs_msg(khm_handle * subs,
+ khm_size n_subs,
+ khm_int32 type,
+ khm_int32 subtype,
+ khm_ui_4 uparam,
+ void * vparam)
+{
+ return kmqint_post_subs_msg_ex(subs,
+ n_subs,
+ type,
+ subtype,
+ uparam,
+ vparam,
+ NULL,
+ FALSE);
+}
+
+KHMEXP khm_int32 KHMAPI
+kmq_post_subs_msg_ex(khm_handle * subs,
+ khm_int32 n_subs,
+ khm_int32 type,
+ khm_int32 subtype,
+ khm_ui_4 uparam,
+ void * vparam,
+ kmq_call * call)
+{
+ return kmqint_post_subs_msg_ex(subs, n_subs, type, subtype,
+ uparam, vparam, call, FALSE);
+}
+
+KHMEXP khm_int32 KHMAPI
+kmq_send_subs_msg(khm_handle *subs,
+ khm_int32 n_subs,
+ khm_int32 type,
+ khm_int32 subtype,
+ khm_ui_4 uparam,
+ void * vparam)
+{
+ kmq_call c;
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+
+ rv = kmqint_post_subs_msg_ex(subs, n_subs, type, subtype,
+ uparam, vparam, &c, TRUE);
+ if(KHM_FAILED(rv))
+ return rv;
+
+ rv = kmq_wait(c, INFINITE);
+ if(KHM_SUCCEEDED(rv) && c->nFailed > 0)
+ rv = KHM_ERROR_PARTIAL;
+
+ kmq_free_call(c);
+
+ return rv;
+}
+
+/*! \internal
+*/
+KHMEXP khm_int32 KHMAPI
+kmq_send_sub_msg(khm_handle sub, khm_int32 type, khm_int32 subtype,
+ khm_ui_4 uparam, void * vparam)
+{
+ kmq_call c;
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+
+ rv = kmqint_post_sub_msg_ex(sub, type, subtype, uparam, vparam, &c, TRUE);
+ if(KHM_FAILED(rv))
+ return rv;
+
+ rv = kmq_wait(c, INFINITE);
+ if(KHM_SUCCEEDED(rv) && c->nFailed > 0)
+ rv = KHM_ERROR_PARTIAL;
+
+ kmq_free_call(c);
+
+ return rv;
+}
+
+/*! \internal
+ \note Obtains ::cs_kmq_global, ::cs_kmq_msg, ::cs_kmq_msg_ref, kmq_queue::cs
+ */
+KHMEXP khm_int32 KHMAPI
+kmq_send_thread_quit_message(kmq_thread_id thread, khm_ui_4 uparam) {
+ kmq_call c;
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+
+ rv = kmq_post_thread_quit_message(thread, uparam, &c);
+ if(KHM_FAILED(rv))
+ return rv;
+
+ rv = kmq_wait(c, INFINITE);
+
+ kmq_free_call(c);
+
+ return rv;
+}
+
+/*! \internal
+ \note Obtains ::cs_kmq_global, ::cs_kmq_msg, ::cs_kmq_msg_ref, kmq_queue::cs
+ */
+KHMEXP khm_int32 KHMAPI
+kmq_post_thread_quit_message(kmq_thread_id thread,
+ khm_ui_4 uparam, kmq_call * call) {
+ kmq_message * m;
+ kmq_queue * q;
+
+ EnterCriticalSection(&cs_kmq_global);
+ q = queues;
+ while(q) {
+ if(q->thread == thread)
+ break;
+ q = LNEXT(q);
+ }
+ LeaveCriticalSection(&cs_kmq_global);
+
+ if(!q)
+ return KHM_ERROR_NOT_FOUND;
+
+ EnterCriticalSection(&cs_kmq_msg);
+ m = kmqint_get_message();
+ LeaveCriticalSection(&cs_kmq_msg);
+
+ m->type = KMSG_SYSTEM;
+ m->subtype = KMSG_SYSTEM_EXIT;
+ m->uparam = uparam;
+ m->vparam = NULL;
+
+ m->timeSent = GetTickCount();
+ m->timeExpire = m->timeSent + kmq_call_dead_timeout;
+
+ if(call) {
+ m->wait_o = CreateEvent(NULL,FALSE,FALSE,NULL);
+ *call = m;
+ m->refcount++;
+ } else
+ m->wait_o = NULL;
+
+ kmqint_post_queue(q, m);
+
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP khm_int32 KHMAPI
+kmq_get_next_response(kmq_call call, void ** resp) {
+ /* TODO: Implement this */
+ return 0;
+}
+
+KHMEXP khm_boolean KHMAPI
+kmq_has_completed(kmq_call call) {
+ khm_boolean completed;
+
+ EnterCriticalSection(&cs_kmq_msg);
+ completed = (call->nCompleted + call->nFailed == call->nSent);
+ LeaveCriticalSection(&cs_kmq_msg);
+
+ return completed;
+}
+
+KHMEXP khm_int32 KHMAPI
+kmq_wait(kmq_call call, kmq_timer timeout) {
+ kmq_message * m = call;
+ DWORD rv;
+ /*TODO: check for call free */
+
+ if(m && m->wait_o) {
+ rv = WaitForSingleObject(m->wait_o, timeout);
+ if(rv == WAIT_OBJECT_0)
+ return KHM_ERROR_SUCCESS;
+ else
+ return KHM_ERROR_TIMEOUT;
+ } else
+ return KHM_ERROR_INVALID_PARAM;
+}
+
+/*! \internal
+ \note Obtains ::cs_kmq_types
+ */
+KHMEXP khm_int32 KHMAPI
+kmq_set_completion_handler(khm_int32 type,
+ kmq_msg_completion_handler handler) {
+ return kmqint_msg_type_set_handler(type, handler);
+}
+
+
diff --git a/src/windows/identity/nidmgrdll/dllmain.c b/src/windows/identity/nidmgrdll/dllmain.c
index e54e281374..696911df4d 100644
--- a/src/windows/identity/nidmgrdll/dllmain.c
+++ b/src/windows/identity/nidmgrdll/dllmain.c
@@ -1,114 +1,114 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<windows.h>
-
-/* forward dcls */
-void
-kherr_process_attach(void);
-
-void
-kherr_process_detach(void);
-
-void
-kherr_thread_attach(void);
-
-void
-kherr_thread_detach(void);
-
-void
-kconfig_process_attach(void);
-
-void
-kconfig_process_detach(void);
-
-void
-kmq_process_attach(void);
-
-void
-kmq_process_detach(void);
-
-void
-kmq_thread_attach(void);
-
-void
-kmq_thread_detach(void);
-
-void
-kcdb_process_attach(HINSTANCE);
-
-void
-kcdb_process_detach(void);
-
-void
-kmm_process_attach(HINSTANCE);
-
-void
-kmm_process_detach(void);
-
-void
-uilib_process_attach(void);
-
-void
-uilib_process_detach(void);
-
-
-BOOL WINAPI DllMain(
- HINSTANCE hinstDLL, // handle to DLL module
- DWORD fdwReason, // reason for calling function
- LPVOID lpReserved ) // reserved
-{
- switch(fdwReason) {
- case DLL_PROCESS_ATTACH:
- kherr_process_attach();
- kconfig_process_attach();
- kmq_process_attach();
- kcdb_process_attach(hinstDLL);
- kmm_process_attach(hinstDLL);
- uilib_process_attach();
- break;
-
- case DLL_PROCESS_DETACH:
- kherr_process_detach();
- kconfig_process_detach();
- kmq_process_detach();
- kcdb_process_detach();
- kmm_process_detach();
- uilib_process_detach();
- break;
-
- case DLL_THREAD_ATTACH:
- kherr_thread_attach();
- kmq_thread_attach();
- break;
-
- case DLL_THREAD_DETACH:
- kherr_thread_detach();
- kmq_thread_detach();
- break;
- }
- return TRUE;
-}
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<windows.h>
+
+/* forward dcls */
+void
+kherr_process_attach(void);
+
+void
+kherr_process_detach(void);
+
+void
+kherr_thread_attach(void);
+
+void
+kherr_thread_detach(void);
+
+void
+kconfig_process_attach(void);
+
+void
+kconfig_process_detach(void);
+
+void
+kmq_process_attach(void);
+
+void
+kmq_process_detach(void);
+
+void
+kmq_thread_attach(void);
+
+void
+kmq_thread_detach(void);
+
+void
+kcdb_process_attach(HINSTANCE);
+
+void
+kcdb_process_detach(void);
+
+void
+kmm_process_attach(HINSTANCE);
+
+void
+kmm_process_detach(void);
+
+void
+uilib_process_attach(void);
+
+void
+uilib_process_detach(void);
+
+
+BOOL WINAPI DllMain(
+ HINSTANCE hinstDLL, // handle to DLL module
+ DWORD fdwReason, // reason for calling function
+ LPVOID lpReserved ) // reserved
+{
+ switch(fdwReason) {
+ case DLL_PROCESS_ATTACH:
+ kherr_process_attach();
+ kconfig_process_attach();
+ kmq_process_attach();
+ kcdb_process_attach(hinstDLL);
+ kmm_process_attach(hinstDLL);
+ uilib_process_attach();
+ break;
+
+ case DLL_PROCESS_DETACH:
+ kherr_process_detach();
+ kconfig_process_detach();
+ kmq_process_detach();
+ kcdb_process_detach();
+ kmm_process_detach();
+ uilib_process_detach();
+ break;
+
+ case DLL_THREAD_ATTACH:
+ kherr_thread_attach();
+ kmq_thread_attach();
+ break;
+
+ case DLL_THREAD_DETACH:
+ kherr_thread_detach();
+ kmq_thread_detach();
+ break;
+ }
+ return TRUE;
+}
diff --git a/src/windows/identity/plugins/common/dynimport.c b/src/windows/identity/plugins/common/dynimport.c
index f49987ca73..24fa1a5515 100644
--- a/src/windows/identity/plugins/common/dynimport.c
+++ b/src/windows/identity/plugins/common/dynimport.c
@@ -1,477 +1,477 @@
-/*
-* Copyright (c) 2005 Massachusetts Institute of Technology
-* Copyright (c) 2007 Secure Endpoints Inc.
-*
-* Permission is hereby granted, free of charge, to any person
-* obtaining a copy of this software and associated documentation
-* files (the "Software"), to deal in the Software without
-* restriction, including without limitation the rights to use, copy,
-* modify, merge, publish, distribute, sublicense, and/or sell copies
-* of the Software, and to permit persons to whom the Software is
-* furnished to do so, subject to the following conditions:
-*
-* The above copyright notice and this permission notice shall be
-* included in all copies or substantial portions of the Software.
-*
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
-* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
-* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-* SOFTWARE.
-*/
-
-/* $Id$ */
-
-#include<windows.h>
-#include<netidmgr.h>
-#include<dynimport.h>
-
-HINSTANCE hKrb4 = 0;
-HINSTANCE hKrb5 = 0;
-HINSTANCE hKrb524 = 0;
-HINSTANCE hSecur32 = 0;
-HINSTANCE hComErr = 0;
-HINSTANCE hService = 0;
-HINSTANCE hProfile = 0;
-HINSTANCE hPsapi = 0;
-HINSTANCE hToolHelp32 = 0;
-HINSTANCE hCCAPI = 0;
-
-DWORD AfsAvailable = 0;
-
-// CCAPI
-DECL_FUNC_PTR(cc_initialize);
-DECL_FUNC_PTR(cc_shutdown);
-DECL_FUNC_PTR(cc_get_NC_info);
-DECL_FUNC_PTR(cc_free_NC_info);
-
-// krb4 functions
-DECL_FUNC_PTR(get_krb_err_txt_entry);
-DECL_FUNC_PTR(k_isinst);
-DECL_FUNC_PTR(k_isname);
-DECL_FUNC_PTR(k_isrealm);
-DECL_FUNC_PTR(kadm_change_your_password);
-DECL_FUNC_PTR(kname_parse);
-DECL_FUNC_PTR(krb_get_cred);
-DECL_FUNC_PTR(krb_get_krbhst);
-DECL_FUNC_PTR(krb_get_lrealm);
-DECL_FUNC_PTR(krb_get_pw_in_tkt);
-DECL_FUNC_PTR(krb_get_tf_realm);
-DECL_FUNC_PTR(krb_mk_req);
-DECL_FUNC_PTR(krb_realmofhost);
-DECL_FUNC_PTR(tf_init);
-DECL_FUNC_PTR(tf_close);
-DECL_FUNC_PTR(tf_get_cred);
-DECL_FUNC_PTR(tf_get_pname);
-DECL_FUNC_PTR(tf_get_pinst);
-DECL_FUNC_PTR(LocalHostAddr);
-DECL_FUNC_PTR(tkt_string);
-DECL_FUNC_PTR(krb_set_tkt_string);
-DECL_FUNC_PTR(initialize_krb_error_func);
-DECL_FUNC_PTR(initialize_kadm_error_table);
-DECL_FUNC_PTR(dest_tkt);
-DECL_FUNC_PTR(krb_in_tkt);
-DECL_FUNC_PTR(krb_save_credentials);
-DECL_FUNC_PTR(krb_get_krbconf2);
-DECL_FUNC_PTR(krb_get_krbrealm2);
-DECL_FUNC_PTR(krb_life_to_time);
-
-// krb5 functions
-DECL_FUNC_PTR(krb5_change_password);
-DECL_FUNC_PTR(krb5_get_init_creds_opt_init);
-DECL_FUNC_PTR(krb5_get_init_creds_opt_set_tkt_life);
-DECL_FUNC_PTR(krb5_get_init_creds_opt_set_renew_life);
-DECL_FUNC_PTR(krb5_get_init_creds_opt_set_forwardable);
-DECL_FUNC_PTR(krb5_get_init_creds_opt_set_proxiable);
-DECL_FUNC_PTR(krb5_get_init_creds_opt_set_address_list);
-DECL_FUNC_PTR(krb5_get_init_creds_opt_set_change_password_prompt);
-DECL_FUNC_PTR(krb5_get_init_creds_password);
-DECL_FUNC_PTR(krb5_get_prompt_types);
-DECL_FUNC_PTR(krb5_build_principal_ext);
-DECL_FUNC_PTR(krb5_cc_get_name);
-DECL_FUNC_PTR(krb5_cc_get_type);
-DECL_FUNC_PTR(krb5_cc_resolve);
-DECL_FUNC_PTR(krb5_cc_default);
-DECL_FUNC_PTR(krb5_cc_default_name);
-DECL_FUNC_PTR(krb5_cc_set_default_name);
-DECL_FUNC_PTR(krb5_cc_initialize);
-DECL_FUNC_PTR(krb5_cc_destroy);
-DECL_FUNC_PTR(krb5_cc_close);
-DECL_FUNC_PTR(krb5_cc_store_cred);
-DECL_FUNC_PTR(krb5_cc_copy_creds);
-DECL_FUNC_PTR(krb5_cc_retrieve_cred);
-DECL_FUNC_PTR(krb5_cc_get_principal);
-DECL_FUNC_PTR(krb5_cc_start_seq_get);
-DECL_FUNC_PTR(krb5_cc_next_cred);
-DECL_FUNC_PTR(krb5_cc_end_seq_get);
-DECL_FUNC_PTR(krb5_cc_remove_cred);
-DECL_FUNC_PTR(krb5_cc_set_flags);
-// DECL_FUNC_PTR(krb5_cc_get_type);
-DECL_FUNC_PTR(krb5_free_context);
-DECL_FUNC_PTR(krb5_free_cred_contents);
-DECL_FUNC_PTR(krb5_free_principal);
-DECL_FUNC_PTR(krb5_get_in_tkt_with_password);
-DECL_FUNC_PTR(krb5_init_context);
-DECL_FUNC_PTR(krb5_parse_name);
-DECL_FUNC_PTR(krb5_timeofday);
-DECL_FUNC_PTR(krb5_timestamp_to_sfstring);
-DECL_FUNC_PTR(krb5_unparse_name);
-DECL_FUNC_PTR(krb5_get_credentials);
-DECL_FUNC_PTR(krb5_mk_req);
-DECL_FUNC_PTR(krb5_sname_to_principal);
-DECL_FUNC_PTR(krb5_get_credentials_renew);
-DECL_FUNC_PTR(krb5_free_data);
-DECL_FUNC_PTR(krb5_free_data_contents);
-// DECL_FUNC_PTR(krb5_get_realm_domain);
-DECL_FUNC_PTR(krb5_free_unparsed_name);
-DECL_FUNC_PTR(krb5_os_localaddr);
-DECL_FUNC_PTR(krb5_copy_keyblock_contents);
-DECL_FUNC_PTR(krb5_copy_data);
-DECL_FUNC_PTR(krb5_free_creds);
-DECL_FUNC_PTR(krb5_build_principal);
-DECL_FUNC_PTR(krb5_get_renewed_creds);
-DECL_FUNC_PTR(krb5_get_default_config_files);
-DECL_FUNC_PTR(krb5_free_config_files);
-DECL_FUNC_PTR(krb5_get_default_realm);
-DECL_FUNC_PTR(krb5_set_default_realm);
-DECL_FUNC_PTR(krb5_free_ticket);
-DECL_FUNC_PTR(krb5_decode_ticket);
-DECL_FUNC_PTR(krb5_get_host_realm);
-DECL_FUNC_PTR(krb5_free_host_realm);
-DECL_FUNC_PTR(krb5_c_random_make_octets);
-DECL_FUNC_PTR(krb5_free_addresses);
-DECL_FUNC_PTR(krb5_free_default_realm);
-DECL_FUNC_PTR(krb5_string_to_deltat);
-
-// Krb524 functions
-DECL_FUNC_PTR(krb524_init_ets);
-DECL_FUNC_PTR(krb524_convert_creds_kdc);
-
-// ComErr functions
-DECL_FUNC_PTR(com_err);
-DECL_FUNC_PTR(error_message);
-
-// Profile functions
-DECL_FUNC_PTR(profile_init);
-DECL_FUNC_PTR(profile_flush);
-DECL_FUNC_PTR(profile_release);
-DECL_FUNC_PTR(profile_get_subsection_names);
-DECL_FUNC_PTR(profile_free_list);
-DECL_FUNC_PTR(profile_get_string);
-DECL_FUNC_PTR(profile_get_integer);
-DECL_FUNC_PTR(profile_get_values);
-DECL_FUNC_PTR(profile_get_relation_names);
-DECL_FUNC_PTR(profile_clear_relation);
-DECL_FUNC_PTR(profile_add_relation);
-DECL_FUNC_PTR(profile_update_relation);
-DECL_FUNC_PTR(profile_release_string);
-DECL_FUNC_PTR(profile_rename_section);
-
-// Service functions
-DECL_FUNC_PTR(OpenSCManagerA);
-DECL_FUNC_PTR(OpenServiceA);
-DECL_FUNC_PTR(QueryServiceStatus);
-DECL_FUNC_PTR(CloseServiceHandle);
-DECL_FUNC_PTR(LsaNtStatusToWinError);
-
-// LSA Functions
-DECL_FUNC_PTR(LsaConnectUntrusted);
-DECL_FUNC_PTR(LsaLookupAuthenticationPackage);
-DECL_FUNC_PTR(LsaCallAuthenticationPackage);
-DECL_FUNC_PTR(LsaFreeReturnBuffer);
-DECL_FUNC_PTR(LsaGetLogonSessionData);
-
-// CCAPI
-FUNC_INFO ccapi_fi[] = {
- MAKE_FUNC_INFO(cc_initialize),
- MAKE_FUNC_INFO(cc_shutdown),
- MAKE_FUNC_INFO(cc_get_NC_info),
- MAKE_FUNC_INFO(cc_free_NC_info),
- END_FUNC_INFO
-};
-
-FUNC_INFO k4_fi[] = {
- MAKE_FUNC_INFO(get_krb_err_txt_entry),
- MAKE_FUNC_INFO(k_isinst),
- MAKE_FUNC_INFO(k_isname),
- MAKE_FUNC_INFO(k_isrealm),
- MAKE_FUNC_INFO(kadm_change_your_password),
- MAKE_FUNC_INFO(kname_parse),
- MAKE_FUNC_INFO(krb_get_cred),
- MAKE_FUNC_INFO(krb_get_krbhst),
- MAKE_FUNC_INFO(krb_get_lrealm),
- MAKE_FUNC_INFO(krb_get_pw_in_tkt),
- MAKE_FUNC_INFO(krb_get_tf_realm),
- MAKE_FUNC_INFO(krb_mk_req),
- MAKE_FUNC_INFO(krb_realmofhost),
- MAKE_FUNC_INFO(tf_init),
- MAKE_FUNC_INFO(tf_close),
- MAKE_FUNC_INFO(tf_get_cred),
- MAKE_FUNC_INFO(tf_get_pname),
- MAKE_FUNC_INFO(tf_get_pinst),
- MAKE_FUNC_INFO(LocalHostAddr),
- MAKE_FUNC_INFO(tkt_string),
- MAKE_FUNC_INFO(krb_set_tkt_string),
- MAKE_FUNC_INFO(initialize_krb_error_func),
- MAKE_FUNC_INFO(initialize_kadm_error_table),
- MAKE_FUNC_INFO(dest_tkt),
- /* MAKE_FUNC_INFO(lsh_LoadKrb4LeashErrorTables), */// XXX
- MAKE_FUNC_INFO(krb_in_tkt),
- MAKE_FUNC_INFO(krb_save_credentials),
- MAKE_FUNC_INFO(krb_get_krbconf2),
- MAKE_FUNC_INFO(krb_get_krbrealm2),
- MAKE_FUNC_INFO(krb_life_to_time),
- END_FUNC_INFO
-};
-
-FUNC_INFO k5_fi[] = {
- MAKE_FUNC_INFO(krb5_change_password),
- MAKE_FUNC_INFO(krb5_get_init_creds_opt_init),
- MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_tkt_life),
- MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_renew_life),
- MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_forwardable),
- MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_proxiable),
- MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_address_list),
- MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_change_password_prompt),
- MAKE_FUNC_INFO(krb5_get_init_creds_password),
- MAKE_FUNC_INFO(krb5_get_prompt_types),
- MAKE_FUNC_INFO(krb5_build_principal_ext),
- MAKE_FUNC_INFO(krb5_cc_get_name),
- MAKE_FUNC_INFO(krb5_cc_get_type),
- MAKE_FUNC_INFO(krb5_cc_resolve),
- MAKE_FUNC_INFO(krb5_cc_default),
- MAKE_FUNC_INFO(krb5_cc_default_name),
- MAKE_FUNC_INFO(krb5_cc_set_default_name),
- MAKE_FUNC_INFO(krb5_cc_initialize),
- MAKE_FUNC_INFO(krb5_cc_destroy),
- MAKE_FUNC_INFO(krb5_cc_close),
- MAKE_FUNC_INFO(krb5_cc_copy_creds),
- MAKE_FUNC_INFO(krb5_cc_store_cred),
- MAKE_FUNC_INFO(krb5_cc_retrieve_cred),
- MAKE_FUNC_INFO(krb5_cc_get_principal),
- MAKE_FUNC_INFO(krb5_cc_start_seq_get),
- MAKE_FUNC_INFO(krb5_cc_next_cred),
- MAKE_FUNC_INFO(krb5_cc_end_seq_get),
- MAKE_FUNC_INFO(krb5_cc_remove_cred),
- MAKE_FUNC_INFO(krb5_cc_set_flags),
- // MAKE_FUNC_INFO(krb5_cc_get_type),
- MAKE_FUNC_INFO(krb5_free_context),
- MAKE_FUNC_INFO(krb5_free_cred_contents),
- MAKE_FUNC_INFO(krb5_free_principal),
- MAKE_FUNC_INFO(krb5_get_in_tkt_with_password),
- MAKE_FUNC_INFO(krb5_init_context),
- MAKE_FUNC_INFO(krb5_parse_name),
- MAKE_FUNC_INFO(krb5_timeofday),
- MAKE_FUNC_INFO(krb5_timestamp_to_sfstring),
- MAKE_FUNC_INFO(krb5_unparse_name),
- MAKE_FUNC_INFO(krb5_get_credentials),
- MAKE_FUNC_INFO(krb5_mk_req),
- MAKE_FUNC_INFO(krb5_sname_to_principal),
- MAKE_FUNC_INFO(krb5_get_credentials_renew),
- MAKE_FUNC_INFO(krb5_free_data),
- MAKE_FUNC_INFO(krb5_free_data_contents),
- // MAKE_FUNC_INFO(krb5_get_realm_domain),
- MAKE_FUNC_INFO(krb5_free_unparsed_name),
- MAKE_FUNC_INFO(krb5_os_localaddr),
- MAKE_FUNC_INFO(krb5_copy_keyblock_contents),
- MAKE_FUNC_INFO(krb5_copy_data),
- MAKE_FUNC_INFO(krb5_free_creds),
- MAKE_FUNC_INFO(krb5_build_principal),
- MAKE_FUNC_INFO(krb5_get_renewed_creds),
- MAKE_FUNC_INFO(krb5_free_addresses),
- MAKE_FUNC_INFO(krb5_get_default_config_files),
- MAKE_FUNC_INFO(krb5_free_config_files),
- MAKE_FUNC_INFO(krb5_get_default_realm),
- MAKE_FUNC_INFO(krb5_set_default_realm),
- MAKE_FUNC_INFO(krb5_free_ticket),
- MAKE_FUNC_INFO(krb5_decode_ticket),
- MAKE_FUNC_INFO(krb5_get_host_realm),
- MAKE_FUNC_INFO(krb5_free_host_realm),
- MAKE_FUNC_INFO(krb5_c_random_make_octets),
- MAKE_FUNC_INFO(krb5_free_default_realm),
- MAKE_FUNC_INFO(krb5_string_to_deltat),
- END_FUNC_INFO
-};
-
-FUNC_INFO k524_fi[] = {
- MAKE_FUNC_INFO(krb524_init_ets),
- MAKE_FUNC_INFO(krb524_convert_creds_kdc),
- END_FUNC_INFO
-};
-
-FUNC_INFO profile_fi[] = {
- MAKE_FUNC_INFO(profile_init),
- MAKE_FUNC_INFO(profile_flush),
- MAKE_FUNC_INFO(profile_release),
- MAKE_FUNC_INFO(profile_get_subsection_names),
- MAKE_FUNC_INFO(profile_free_list),
- MAKE_FUNC_INFO(profile_get_string),
- MAKE_FUNC_INFO(profile_get_integer),
- MAKE_FUNC_INFO(profile_get_values),
- MAKE_FUNC_INFO(profile_get_relation_names),
- MAKE_FUNC_INFO(profile_clear_relation),
- MAKE_FUNC_INFO(profile_add_relation),
- MAKE_FUNC_INFO(profile_update_relation),
- MAKE_FUNC_INFO(profile_release_string),
- MAKE_FUNC_INFO(profile_rename_section),
- END_FUNC_INFO
-};
-
-FUNC_INFO ce_fi[] = {
- MAKE_FUNC_INFO(com_err),
- MAKE_FUNC_INFO(error_message),
- END_FUNC_INFO
-};
-
-FUNC_INFO service_fi[] = {
- MAKE_FUNC_INFO(OpenSCManagerA),
- MAKE_FUNC_INFO(OpenServiceA),
- MAKE_FUNC_INFO(QueryServiceStatus),
- MAKE_FUNC_INFO(CloseServiceHandle),
- MAKE_FUNC_INFO(LsaNtStatusToWinError),
- END_FUNC_INFO
-};
-
-FUNC_INFO lsa_fi[] = {
- MAKE_FUNC_INFO(LsaConnectUntrusted),
- MAKE_FUNC_INFO(LsaLookupAuthenticationPackage),
- MAKE_FUNC_INFO(LsaCallAuthenticationPackage),
- MAKE_FUNC_INFO(LsaFreeReturnBuffer),
- MAKE_FUNC_INFO(LsaGetLogonSessionData),
- END_FUNC_INFO
-};
-
-// psapi functions
-DECL_FUNC_PTR(GetModuleFileNameExA);
-DECL_FUNC_PTR(EnumProcessModules);
-
-FUNC_INFO psapi_fi[] = {
- MAKE_FUNC_INFO(GetModuleFileNameExA),
- MAKE_FUNC_INFO(EnumProcessModules),
- END_FUNC_INFO
-};
-
-// toolhelp functions
-DECL_FUNC_PTR(CreateToolhelp32Snapshot);
-DECL_FUNC_PTR(Module32First);
-DECL_FUNC_PTR(Module32Next);
-
-FUNC_INFO toolhelp_fi[] = {
- MAKE_FUNC_INFO(CreateToolhelp32Snapshot),
- MAKE_FUNC_INFO(Module32First),
- MAKE_FUNC_INFO(Module32Next),
- END_FUNC_INFO
-};
-
-khm_int32 init_imports(void) {
- OSVERSIONINFO osvi;
- int imp_rv = 1;
-
-#define CKRV(m) \
- do { \
- if(!imp_rv) { \
- _reportf(L"Can't locate all required exports from module [%S]", (m)); \
- goto _err_ret; \
- } \
- } while (FALSE)
-
-#ifndef _WIN64
- imp_rv = LoadFuncs(KRB4_DLL, k4_fi, &hKrb4, 0, 1, 0, 0);
- CKRV(KRB4_DLL);
-#endif
-
- imp_rv = LoadFuncs(KRB5_DLL, k5_fi, &hKrb5, 0, 1, 0, 0);
- CKRV(KRB5_DLL);
-
- imp_rv = LoadFuncs(COMERR_DLL, ce_fi, &hComErr, 0, 0, 1, 0);
- CKRV(COMERR_DLL);
-
- imp_rv = LoadFuncs(SERVICE_DLL, service_fi, &hService, 0, 1, 0, 0);
- CKRV(SERVICE_DLL);
-
- imp_rv = LoadFuncs(SECUR32_DLL, lsa_fi, &hSecur32, 0, 1, 1, 1);
- CKRV(SECUR32_DLL);
-
- imp_rv = LoadFuncs(KRB524_DLL, k524_fi, &hKrb524, 0, 1, 1, 1);
- CKRV(KRB524_DLL);
-
- imp_rv = LoadFuncs(PROFILE_DLL, profile_fi, &hProfile, 0, 1, 0, 0);
- CKRV(PROFILE_DLL);
-
- imp_rv = LoadFuncs(CCAPI_DLL, ccapi_fi, &hCCAPI, 0, 1, 0, 0);
- /* CCAPI_DLL is optional. No error check. */
-
- memset(&osvi, 0, sizeof(OSVERSIONINFO));
- osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
- GetVersionEx(&osvi);
-
- // XXX: We should really use feature testing, first
- // checking for CreateToolhelp32Snapshot. If that's
- // not around, we try the psapi stuff.
- //
- // Only load LSA functions if on NT/2000/XP
- if(osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
- {
- // Windows 9x
- imp_rv = LoadFuncs(TOOLHELPDLL, toolhelp_fi, &hToolHelp32, 0, 1, 0, 0);
- CKRV(TOOLHELPDLL);
-
- hPsapi = 0;
- }
- else if(osvi.dwPlatformId == VER_PLATFORM_WIN32_NT)
- {
- // Windows NT
- imp_rv = LoadFuncs(PSAPIDLL, psapi_fi, &hPsapi, 0, 1, 0, 0);
- CKRV(PSAPIDLL);
-
- hToolHelp32 = 0;
- }
-
- AfsAvailable = TRUE; //afscompat_init();
-
- return KHM_ERROR_SUCCESS;
-
- _err_ret:
- return KHM_ERROR_NOT_FOUND;
-}
-
-khm_int32 exit_imports(void) {
- //afscompat_close();
-
- if (hKrb4)
- FreeLibrary(hKrb4);
- if (hKrb5)
- FreeLibrary(hKrb5);
- if (hProfile)
- FreeLibrary(hProfile);
- if (hComErr)
- FreeLibrary(hComErr);
- if (hService)
- FreeLibrary(hService);
- if (hSecur32)
- FreeLibrary(hSecur32);
- if (hKrb524)
- FreeLibrary(hKrb524);
- if (hPsapi)
- FreeLibrary(hPsapi);
- if (hToolHelp32)
- FreeLibrary(hToolHelp32);
-
- return KHM_ERROR_SUCCESS;
-}
-
-int (*Lcom_err)(LPSTR,long,LPSTR,...);
-LPSTR (*Lerror_message)(long);
-LPSTR (*Lerror_table_name)(long);
-
-void Leash_load_com_err_callback(FARPROC ce,
- FARPROC em,
- FARPROC etn)
-{
- (FARPROC)Lcom_err=ce;
- (FARPROC)Lerror_message=em;
- (FARPROC)Lerror_table_name=etn;
-}
+/*
+* Copyright (c) 2005 Massachusetts Institute of Technology
+* Copyright (c) 2007 Secure Endpoints Inc.
+*
+* Permission is hereby granted, free of charge, to any person
+* obtaining a copy of this software and associated documentation
+* files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy,
+* modify, merge, publish, distribute, sublicense, and/or sell copies
+* of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be
+* included in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*/
+
+/* $Id$ */
+
+#include<windows.h>
+#include<netidmgr.h>
+#include<dynimport.h>
+
+HINSTANCE hKrb4 = 0;
+HINSTANCE hKrb5 = 0;
+HINSTANCE hKrb524 = 0;
+HINSTANCE hSecur32 = 0;
+HINSTANCE hComErr = 0;
+HINSTANCE hService = 0;
+HINSTANCE hProfile = 0;
+HINSTANCE hPsapi = 0;
+HINSTANCE hToolHelp32 = 0;
+HINSTANCE hCCAPI = 0;
+
+DWORD AfsAvailable = 0;
+
+// CCAPI
+DECL_FUNC_PTR(cc_initialize);
+DECL_FUNC_PTR(cc_shutdown);
+DECL_FUNC_PTR(cc_get_NC_info);
+DECL_FUNC_PTR(cc_free_NC_info);
+
+// krb4 functions
+DECL_FUNC_PTR(get_krb_err_txt_entry);
+DECL_FUNC_PTR(k_isinst);
+DECL_FUNC_PTR(k_isname);
+DECL_FUNC_PTR(k_isrealm);
+DECL_FUNC_PTR(kadm_change_your_password);
+DECL_FUNC_PTR(kname_parse);
+DECL_FUNC_PTR(krb_get_cred);
+DECL_FUNC_PTR(krb_get_krbhst);
+DECL_FUNC_PTR(krb_get_lrealm);
+DECL_FUNC_PTR(krb_get_pw_in_tkt);
+DECL_FUNC_PTR(krb_get_tf_realm);
+DECL_FUNC_PTR(krb_mk_req);
+DECL_FUNC_PTR(krb_realmofhost);
+DECL_FUNC_PTR(tf_init);
+DECL_FUNC_PTR(tf_close);
+DECL_FUNC_PTR(tf_get_cred);
+DECL_FUNC_PTR(tf_get_pname);
+DECL_FUNC_PTR(tf_get_pinst);
+DECL_FUNC_PTR(LocalHostAddr);
+DECL_FUNC_PTR(tkt_string);
+DECL_FUNC_PTR(krb_set_tkt_string);
+DECL_FUNC_PTR(initialize_krb_error_func);
+DECL_FUNC_PTR(initialize_kadm_error_table);
+DECL_FUNC_PTR(dest_tkt);
+DECL_FUNC_PTR(krb_in_tkt);
+DECL_FUNC_PTR(krb_save_credentials);
+DECL_FUNC_PTR(krb_get_krbconf2);
+DECL_FUNC_PTR(krb_get_krbrealm2);
+DECL_FUNC_PTR(krb_life_to_time);
+
+// krb5 functions
+DECL_FUNC_PTR(krb5_change_password);
+DECL_FUNC_PTR(krb5_get_init_creds_opt_init);
+DECL_FUNC_PTR(krb5_get_init_creds_opt_set_tkt_life);
+DECL_FUNC_PTR(krb5_get_init_creds_opt_set_renew_life);
+DECL_FUNC_PTR(krb5_get_init_creds_opt_set_forwardable);
+DECL_FUNC_PTR(krb5_get_init_creds_opt_set_proxiable);
+DECL_FUNC_PTR(krb5_get_init_creds_opt_set_address_list);
+DECL_FUNC_PTR(krb5_get_init_creds_opt_set_change_password_prompt);
+DECL_FUNC_PTR(krb5_get_init_creds_password);
+DECL_FUNC_PTR(krb5_get_prompt_types);
+DECL_FUNC_PTR(krb5_build_principal_ext);
+DECL_FUNC_PTR(krb5_cc_get_name);
+DECL_FUNC_PTR(krb5_cc_get_type);
+DECL_FUNC_PTR(krb5_cc_resolve);
+DECL_FUNC_PTR(krb5_cc_default);
+DECL_FUNC_PTR(krb5_cc_default_name);
+DECL_FUNC_PTR(krb5_cc_set_default_name);
+DECL_FUNC_PTR(krb5_cc_initialize);
+DECL_FUNC_PTR(krb5_cc_destroy);
+DECL_FUNC_PTR(krb5_cc_close);
+DECL_FUNC_PTR(krb5_cc_store_cred);
+DECL_FUNC_PTR(krb5_cc_copy_creds);
+DECL_FUNC_PTR(krb5_cc_retrieve_cred);
+DECL_FUNC_PTR(krb5_cc_get_principal);
+DECL_FUNC_PTR(krb5_cc_start_seq_get);
+DECL_FUNC_PTR(krb5_cc_next_cred);
+DECL_FUNC_PTR(krb5_cc_end_seq_get);
+DECL_FUNC_PTR(krb5_cc_remove_cred);
+DECL_FUNC_PTR(krb5_cc_set_flags);
+// DECL_FUNC_PTR(krb5_cc_get_type);
+DECL_FUNC_PTR(krb5_free_context);
+DECL_FUNC_PTR(krb5_free_cred_contents);
+DECL_FUNC_PTR(krb5_free_principal);
+DECL_FUNC_PTR(krb5_get_in_tkt_with_password);
+DECL_FUNC_PTR(krb5_init_context);
+DECL_FUNC_PTR(krb5_parse_name);
+DECL_FUNC_PTR(krb5_timeofday);
+DECL_FUNC_PTR(krb5_timestamp_to_sfstring);
+DECL_FUNC_PTR(krb5_unparse_name);
+DECL_FUNC_PTR(krb5_get_credentials);
+DECL_FUNC_PTR(krb5_mk_req);
+DECL_FUNC_PTR(krb5_sname_to_principal);
+DECL_FUNC_PTR(krb5_get_credentials_renew);
+DECL_FUNC_PTR(krb5_free_data);
+DECL_FUNC_PTR(krb5_free_data_contents);
+// DECL_FUNC_PTR(krb5_get_realm_domain);
+DECL_FUNC_PTR(krb5_free_unparsed_name);
+DECL_FUNC_PTR(krb5_os_localaddr);
+DECL_FUNC_PTR(krb5_copy_keyblock_contents);
+DECL_FUNC_PTR(krb5_copy_data);
+DECL_FUNC_PTR(krb5_free_creds);
+DECL_FUNC_PTR(krb5_build_principal);
+DECL_FUNC_PTR(krb5_get_renewed_creds);
+DECL_FUNC_PTR(krb5_get_default_config_files);
+DECL_FUNC_PTR(krb5_free_config_files);
+DECL_FUNC_PTR(krb5_get_default_realm);
+DECL_FUNC_PTR(krb5_set_default_realm);
+DECL_FUNC_PTR(krb5_free_ticket);
+DECL_FUNC_PTR(krb5_decode_ticket);
+DECL_FUNC_PTR(krb5_get_host_realm);
+DECL_FUNC_PTR(krb5_free_host_realm);
+DECL_FUNC_PTR(krb5_c_random_make_octets);
+DECL_FUNC_PTR(krb5_free_addresses);
+DECL_FUNC_PTR(krb5_free_default_realm);
+DECL_FUNC_PTR(krb5_string_to_deltat);
+
+// Krb524 functions
+DECL_FUNC_PTR(krb524_init_ets);
+DECL_FUNC_PTR(krb524_convert_creds_kdc);
+
+// ComErr functions
+DECL_FUNC_PTR(com_err);
+DECL_FUNC_PTR(error_message);
+
+// Profile functions
+DECL_FUNC_PTR(profile_init);
+DECL_FUNC_PTR(profile_flush);
+DECL_FUNC_PTR(profile_release);
+DECL_FUNC_PTR(profile_get_subsection_names);
+DECL_FUNC_PTR(profile_free_list);
+DECL_FUNC_PTR(profile_get_string);
+DECL_FUNC_PTR(profile_get_integer);
+DECL_FUNC_PTR(profile_get_values);
+DECL_FUNC_PTR(profile_get_relation_names);
+DECL_FUNC_PTR(profile_clear_relation);
+DECL_FUNC_PTR(profile_add_relation);
+DECL_FUNC_PTR(profile_update_relation);
+DECL_FUNC_PTR(profile_release_string);
+DECL_FUNC_PTR(profile_rename_section);
+
+// Service functions
+DECL_FUNC_PTR(OpenSCManagerA);
+DECL_FUNC_PTR(OpenServiceA);
+DECL_FUNC_PTR(QueryServiceStatus);
+DECL_FUNC_PTR(CloseServiceHandle);
+DECL_FUNC_PTR(LsaNtStatusToWinError);
+
+// LSA Functions
+DECL_FUNC_PTR(LsaConnectUntrusted);
+DECL_FUNC_PTR(LsaLookupAuthenticationPackage);
+DECL_FUNC_PTR(LsaCallAuthenticationPackage);
+DECL_FUNC_PTR(LsaFreeReturnBuffer);
+DECL_FUNC_PTR(LsaGetLogonSessionData);
+
+// CCAPI
+FUNC_INFO ccapi_fi[] = {
+ MAKE_FUNC_INFO(cc_initialize),
+ MAKE_FUNC_INFO(cc_shutdown),
+ MAKE_FUNC_INFO(cc_get_NC_info),
+ MAKE_FUNC_INFO(cc_free_NC_info),
+ END_FUNC_INFO
+};
+
+FUNC_INFO k4_fi[] = {
+ MAKE_FUNC_INFO(get_krb_err_txt_entry),
+ MAKE_FUNC_INFO(k_isinst),
+ MAKE_FUNC_INFO(k_isname),
+ MAKE_FUNC_INFO(k_isrealm),
+ MAKE_FUNC_INFO(kadm_change_your_password),
+ MAKE_FUNC_INFO(kname_parse),
+ MAKE_FUNC_INFO(krb_get_cred),
+ MAKE_FUNC_INFO(krb_get_krbhst),
+ MAKE_FUNC_INFO(krb_get_lrealm),
+ MAKE_FUNC_INFO(krb_get_pw_in_tkt),
+ MAKE_FUNC_INFO(krb_get_tf_realm),
+ MAKE_FUNC_INFO(krb_mk_req),
+ MAKE_FUNC_INFO(krb_realmofhost),
+ MAKE_FUNC_INFO(tf_init),
+ MAKE_FUNC_INFO(tf_close),
+ MAKE_FUNC_INFO(tf_get_cred),
+ MAKE_FUNC_INFO(tf_get_pname),
+ MAKE_FUNC_INFO(tf_get_pinst),
+ MAKE_FUNC_INFO(LocalHostAddr),
+ MAKE_FUNC_INFO(tkt_string),
+ MAKE_FUNC_INFO(krb_set_tkt_string),
+ MAKE_FUNC_INFO(initialize_krb_error_func),
+ MAKE_FUNC_INFO(initialize_kadm_error_table),
+ MAKE_FUNC_INFO(dest_tkt),
+ /* MAKE_FUNC_INFO(lsh_LoadKrb4LeashErrorTables), */// XXX
+ MAKE_FUNC_INFO(krb_in_tkt),
+ MAKE_FUNC_INFO(krb_save_credentials),
+ MAKE_FUNC_INFO(krb_get_krbconf2),
+ MAKE_FUNC_INFO(krb_get_krbrealm2),
+ MAKE_FUNC_INFO(krb_life_to_time),
+ END_FUNC_INFO
+};
+
+FUNC_INFO k5_fi[] = {
+ MAKE_FUNC_INFO(krb5_change_password),
+ MAKE_FUNC_INFO(krb5_get_init_creds_opt_init),
+ MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_tkt_life),
+ MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_renew_life),
+ MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_forwardable),
+ MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_proxiable),
+ MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_address_list),
+ MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_change_password_prompt),
+ MAKE_FUNC_INFO(krb5_get_init_creds_password),
+ MAKE_FUNC_INFO(krb5_get_prompt_types),
+ MAKE_FUNC_INFO(krb5_build_principal_ext),
+ MAKE_FUNC_INFO(krb5_cc_get_name),
+ MAKE_FUNC_INFO(krb5_cc_get_type),
+ MAKE_FUNC_INFO(krb5_cc_resolve),
+ MAKE_FUNC_INFO(krb5_cc_default),
+ MAKE_FUNC_INFO(krb5_cc_default_name),
+ MAKE_FUNC_INFO(krb5_cc_set_default_name),
+ MAKE_FUNC_INFO(krb5_cc_initialize),
+ MAKE_FUNC_INFO(krb5_cc_destroy),
+ MAKE_FUNC_INFO(krb5_cc_close),
+ MAKE_FUNC_INFO(krb5_cc_copy_creds),
+ MAKE_FUNC_INFO(krb5_cc_store_cred),
+ MAKE_FUNC_INFO(krb5_cc_retrieve_cred),
+ MAKE_FUNC_INFO(krb5_cc_get_principal),
+ MAKE_FUNC_INFO(krb5_cc_start_seq_get),
+ MAKE_FUNC_INFO(krb5_cc_next_cred),
+ MAKE_FUNC_INFO(krb5_cc_end_seq_get),
+ MAKE_FUNC_INFO(krb5_cc_remove_cred),
+ MAKE_FUNC_INFO(krb5_cc_set_flags),
+ // MAKE_FUNC_INFO(krb5_cc_get_type),
+ MAKE_FUNC_INFO(krb5_free_context),
+ MAKE_FUNC_INFO(krb5_free_cred_contents),
+ MAKE_FUNC_INFO(krb5_free_principal),
+ MAKE_FUNC_INFO(krb5_get_in_tkt_with_password),
+ MAKE_FUNC_INFO(krb5_init_context),
+ MAKE_FUNC_INFO(krb5_parse_name),
+ MAKE_FUNC_INFO(krb5_timeofday),
+ MAKE_FUNC_INFO(krb5_timestamp_to_sfstring),
+ MAKE_FUNC_INFO(krb5_unparse_name),
+ MAKE_FUNC_INFO(krb5_get_credentials),
+ MAKE_FUNC_INFO(krb5_mk_req),
+ MAKE_FUNC_INFO(krb5_sname_to_principal),
+ MAKE_FUNC_INFO(krb5_get_credentials_renew),
+ MAKE_FUNC_INFO(krb5_free_data),
+ MAKE_FUNC_INFO(krb5_free_data_contents),
+ // MAKE_FUNC_INFO(krb5_get_realm_domain),
+ MAKE_FUNC_INFO(krb5_free_unparsed_name),
+ MAKE_FUNC_INFO(krb5_os_localaddr),
+ MAKE_FUNC_INFO(krb5_copy_keyblock_contents),
+ MAKE_FUNC_INFO(krb5_copy_data),
+ MAKE_FUNC_INFO(krb5_free_creds),
+ MAKE_FUNC_INFO(krb5_build_principal),
+ MAKE_FUNC_INFO(krb5_get_renewed_creds),
+ MAKE_FUNC_INFO(krb5_free_addresses),
+ MAKE_FUNC_INFO(krb5_get_default_config_files),
+ MAKE_FUNC_INFO(krb5_free_config_files),
+ MAKE_FUNC_INFO(krb5_get_default_realm),
+ MAKE_FUNC_INFO(krb5_set_default_realm),
+ MAKE_FUNC_INFO(krb5_free_ticket),
+ MAKE_FUNC_INFO(krb5_decode_ticket),
+ MAKE_FUNC_INFO(krb5_get_host_realm),
+ MAKE_FUNC_INFO(krb5_free_host_realm),
+ MAKE_FUNC_INFO(krb5_c_random_make_octets),
+ MAKE_FUNC_INFO(krb5_free_default_realm),
+ MAKE_FUNC_INFO(krb5_string_to_deltat),
+ END_FUNC_INFO
+};
+
+FUNC_INFO k524_fi[] = {
+ MAKE_FUNC_INFO(krb524_init_ets),
+ MAKE_FUNC_INFO(krb524_convert_creds_kdc),
+ END_FUNC_INFO
+};
+
+FUNC_INFO profile_fi[] = {
+ MAKE_FUNC_INFO(profile_init),
+ MAKE_FUNC_INFO(profile_flush),
+ MAKE_FUNC_INFO(profile_release),
+ MAKE_FUNC_INFO(profile_get_subsection_names),
+ MAKE_FUNC_INFO(profile_free_list),
+ MAKE_FUNC_INFO(profile_get_string),
+ MAKE_FUNC_INFO(profile_get_integer),
+ MAKE_FUNC_INFO(profile_get_values),
+ MAKE_FUNC_INFO(profile_get_relation_names),
+ MAKE_FUNC_INFO(profile_clear_relation),
+ MAKE_FUNC_INFO(profile_add_relation),
+ MAKE_FUNC_INFO(profile_update_relation),
+ MAKE_FUNC_INFO(profile_release_string),
+ MAKE_FUNC_INFO(profile_rename_section),
+ END_FUNC_INFO
+};
+
+FUNC_INFO ce_fi[] = {
+ MAKE_FUNC_INFO(com_err),
+ MAKE_FUNC_INFO(error_message),
+ END_FUNC_INFO
+};
+
+FUNC_INFO service_fi[] = {
+ MAKE_FUNC_INFO(OpenSCManagerA),
+ MAKE_FUNC_INFO(OpenServiceA),
+ MAKE_FUNC_INFO(QueryServiceStatus),
+ MAKE_FUNC_INFO(CloseServiceHandle),
+ MAKE_FUNC_INFO(LsaNtStatusToWinError),
+ END_FUNC_INFO
+};
+
+FUNC_INFO lsa_fi[] = {
+ MAKE_FUNC_INFO(LsaConnectUntrusted),
+ MAKE_FUNC_INFO(LsaLookupAuthenticationPackage),
+ MAKE_FUNC_INFO(LsaCallAuthenticationPackage),
+ MAKE_FUNC_INFO(LsaFreeReturnBuffer),
+ MAKE_FUNC_INFO(LsaGetLogonSessionData),
+ END_FUNC_INFO
+};
+
+// psapi functions
+DECL_FUNC_PTR(GetModuleFileNameExA);
+DECL_FUNC_PTR(EnumProcessModules);
+
+FUNC_INFO psapi_fi[] = {
+ MAKE_FUNC_INFO(GetModuleFileNameExA),
+ MAKE_FUNC_INFO(EnumProcessModules),
+ END_FUNC_INFO
+};
+
+// toolhelp functions
+DECL_FUNC_PTR(CreateToolhelp32Snapshot);
+DECL_FUNC_PTR(Module32First);
+DECL_FUNC_PTR(Module32Next);
+
+FUNC_INFO toolhelp_fi[] = {
+ MAKE_FUNC_INFO(CreateToolhelp32Snapshot),
+ MAKE_FUNC_INFO(Module32First),
+ MAKE_FUNC_INFO(Module32Next),
+ END_FUNC_INFO
+};
+
+khm_int32 init_imports(void) {
+ OSVERSIONINFO osvi;
+ int imp_rv = 1;
+
+#define CKRV(m) \
+ do { \
+ if(!imp_rv) { \
+ _reportf(L"Can't locate all required exports from module [%S]", (m)); \
+ goto _err_ret; \
+ } \
+ } while (FALSE)
+
+#ifndef _WIN64
+ imp_rv = LoadFuncs(KRB4_DLL, k4_fi, &hKrb4, 0, 1, 0, 0);
+ CKRV(KRB4_DLL);
+#endif
+
+ imp_rv = LoadFuncs(KRB5_DLL, k5_fi, &hKrb5, 0, 1, 0, 0);
+ CKRV(KRB5_DLL);
+
+ imp_rv = LoadFuncs(COMERR_DLL, ce_fi, &hComErr, 0, 0, 1, 0);
+ CKRV(COMERR_DLL);
+
+ imp_rv = LoadFuncs(SERVICE_DLL, service_fi, &hService, 0, 1, 0, 0);
+ CKRV(SERVICE_DLL);
+
+ imp_rv = LoadFuncs(SECUR32_DLL, lsa_fi, &hSecur32, 0, 1, 1, 1);
+ CKRV(SECUR32_DLL);
+
+ imp_rv = LoadFuncs(KRB524_DLL, k524_fi, &hKrb524, 0, 1, 1, 1);
+ CKRV(KRB524_DLL);
+
+ imp_rv = LoadFuncs(PROFILE_DLL, profile_fi, &hProfile, 0, 1, 0, 0);
+ CKRV(PROFILE_DLL);
+
+ imp_rv = LoadFuncs(CCAPI_DLL, ccapi_fi, &hCCAPI, 0, 1, 0, 0);
+ /* CCAPI_DLL is optional. No error check. */
+
+ memset(&osvi, 0, sizeof(OSVERSIONINFO));
+ osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+ GetVersionEx(&osvi);
+
+ // XXX: We should really use feature testing, first
+ // checking for CreateToolhelp32Snapshot. If that's
+ // not around, we try the psapi stuff.
+ //
+ // Only load LSA functions if on NT/2000/XP
+ if(osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
+ {
+ // Windows 9x
+ imp_rv = LoadFuncs(TOOLHELPDLL, toolhelp_fi, &hToolHelp32, 0, 1, 0, 0);
+ CKRV(TOOLHELPDLL);
+
+ hPsapi = 0;
+ }
+ else if(osvi.dwPlatformId == VER_PLATFORM_WIN32_NT)
+ {
+ // Windows NT
+ imp_rv = LoadFuncs(PSAPIDLL, psapi_fi, &hPsapi, 0, 1, 0, 0);
+ CKRV(PSAPIDLL);
+
+ hToolHelp32 = 0;
+ }
+
+ AfsAvailable = TRUE; //afscompat_init();
+
+ return KHM_ERROR_SUCCESS;
+
+ _err_ret:
+ return KHM_ERROR_NOT_FOUND;
+}
+
+khm_int32 exit_imports(void) {
+ //afscompat_close();
+
+ if (hKrb4)
+ FreeLibrary(hKrb4);
+ if (hKrb5)
+ FreeLibrary(hKrb5);
+ if (hProfile)
+ FreeLibrary(hProfile);
+ if (hComErr)
+ FreeLibrary(hComErr);
+ if (hService)
+ FreeLibrary(hService);
+ if (hSecur32)
+ FreeLibrary(hSecur32);
+ if (hKrb524)
+ FreeLibrary(hKrb524);
+ if (hPsapi)
+ FreeLibrary(hPsapi);
+ if (hToolHelp32)
+ FreeLibrary(hToolHelp32);
+
+ return KHM_ERROR_SUCCESS;
+}
+
+int (*Lcom_err)(LPSTR,long,LPSTR,...);
+LPSTR (*Lerror_message)(long);
+LPSTR (*Lerror_table_name)(long);
+
+void Leash_load_com_err_callback(FARPROC ce,
+ FARPROC em,
+ FARPROC etn)
+{
+ (FARPROC)Lcom_err=ce;
+ (FARPROC)Lerror_message=em;
+ (FARPROC)Lerror_table_name=etn;
+}
diff --git a/src/windows/identity/plugins/common/dynimport.h b/src/windows/identity/plugins/common/dynimport.h
index 7f3f598b06..850d96e5f6 100644
--- a/src/windows/identity/plugins/common/dynimport.h
+++ b/src/windows/identity/plugins/common/dynimport.h
@@ -1,361 +1,361 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#ifndef __KHIMAIRA_DYNIMPORT_H
-#define __KHIMAIRA_DYNIMPORT_H
-
-/* Dynamic imports */
-#include<khdefs.h>
-#include<tlhelp32.h>
-
-#if _WIN32_WINNT < 0x0501
-#define KHM_SAVE_WIN32_WINNT _WIN32_WINNT
-#undef _WIN32_WINNT
-#define _WIN32_WINNT 0x0501
-#endif
-#include<ntsecapi.h>
-#ifdef KHM_SAVE_WIN32_WINNT
-#undef _WIN32_WINNT
-#define _WIN32_WINNT KHM_SAVE_WIN32_WINNT
-#undef KHM_SAVE_WIN32_WINNT
-#endif
-
-extern HINSTANCE hKrb4;
-extern HINSTANCE hKrb5;
-extern HINSTANCE hProfile;
-
-///////////////////////////////////////////////////////////////////////////////
-
-#define CCAPI_DLL "krbcc32.dll"
-#define KRBCC32_DLL "krbcc32.dll"
-#define SERVICE_DLL "advapi32.dll"
-#define SECUR32_DLL "secur32.dll"
-#define PROFILE_DLL "xpprof32.dll"
-
-//////////////////////////////////////////////////////////////////////////////
-
-#include <loadfuncs-com_err.h>
-#include <loadfuncs-krb5.h>
-#include <loadfuncs-profile.h>
-#include <loadfuncs-krb.h>
-#include <loadfuncs-krb524.h>
-#include <loadfuncs-lsa.h>
-
-//// CCAPI
-/* In order to avoid including the private CCAPI headers */
-typedef int cc_int32;
-
-#define CC_API_VER_1 1
-#define CC_API_VER_2 2
-
-#define CCACHE_API cc_int32
-
-/*
-** The Official Error Codes
-*/
-#define CC_NOERROR 0
-#define CC_BADNAME 1
-#define CC_NOTFOUND 2
-#define CC_END 3
-#define CC_IO 4
-#define CC_WRITE 5
-#define CC_NOMEM 6
-#define CC_FORMAT 7
-#define CC_LOCKED 8
-#define CC_BAD_API_VERSION 9
-#define CC_NO_EXIST 10
-#define CC_NOT_SUPP 11
-#define CC_BAD_PARM 12
-#define CC_ERR_CACHE_ATTACH 13
-#define CC_ERR_CACHE_RELEASE 14
-#define CC_ERR_CACHE_FULL 15
-#define CC_ERR_CRED_VERSION 16
-
-enum {
- CC_CRED_VUNKNOWN = 0, // For validation
- CC_CRED_V4 = 1,
- CC_CRED_V5 = 2,
- CC_CRED_VMAX = 3 // For validation
-};
-
-typedef struct opaque_dll_control_block_type* apiCB;
-typedef struct _infoNC {
- char* name;
- char* principal;
- cc_int32 vers;
-} infoNC;
-
-TYPEDEF_FUNC(
-CCACHE_API,
-CALLCONV_C,
-cc_initialize,
- (
- apiCB** cc_ctx, // < DLL's primary control structure.
- // returned here, passed everywhere else
- cc_int32 api_version, // > ver supported by caller (use CC_API_VER_1)
- cc_int32* api_supported, // < if ~NULL, max ver supported by DLL
- const char** vendor // < if ~NULL, vendor name in read only C string
- )
-);
-
-TYPEDEF_FUNC(
-CCACHE_API,
-CALLCONV_C,
-cc_shutdown,
- (
- apiCB** cc_ctx // <> DLL's primary control structure. NULL after
- )
-);
-
-TYPEDEF_FUNC(
-CCACHE_API,
-CALLCONV_C,
-cc_get_NC_info,
- (
- apiCB* cc_ctx, // > DLL's primary control structure
- struct _infoNC*** ppNCi // < (NULL before call) null terminated,
- // list of a structs (free via cc_free_infoNC())
- )
-);
-
-TYPEDEF_FUNC(
-CCACHE_API,
-CALLCONV_C,
-cc_free_NC_info,
- (
- apiCB* cc_ctx,
- struct _infoNC*** ppNCi // < free list of structs returned by
- // cc_get_cache_names(). set to NULL on return
- )
-);
-//// \CCAPI
-
-extern DWORD AfsAvailable;
-
-// service definitions
-typedef SC_HANDLE (WINAPI *FP_OpenSCManagerA)(char *, char *, DWORD);
-typedef SC_HANDLE (WINAPI *FP_OpenServiceA)(SC_HANDLE, char *, DWORD);
-typedef BOOL (WINAPI *FP_QueryServiceStatus)(SC_HANDLE, LPSERVICE_STATUS);
-typedef BOOL (WINAPI *FP_CloseServiceHandle)(SC_HANDLE);
-
-//////////////////////////////////////////////////////////////////////////////
-
-// CCAPI
-extern DECL_FUNC_PTR(cc_initialize);
-extern DECL_FUNC_PTR(cc_shutdown);
-extern DECL_FUNC_PTR(cc_get_NC_info);
-extern DECL_FUNC_PTR(cc_free_NC_info);
-
-// krb4 functions
-extern DECL_FUNC_PTR(get_krb_err_txt_entry);
-extern DECL_FUNC_PTR(k_isinst);
-extern DECL_FUNC_PTR(k_isname);
-extern DECL_FUNC_PTR(k_isrealm);
-extern DECL_FUNC_PTR(kadm_change_your_password);
-extern DECL_FUNC_PTR(kname_parse);
-extern DECL_FUNC_PTR(krb_get_cred);
-extern DECL_FUNC_PTR(krb_get_krbhst);
-extern DECL_FUNC_PTR(krb_get_lrealm);
-extern DECL_FUNC_PTR(krb_get_pw_in_tkt);
-extern DECL_FUNC_PTR(krb_get_tf_realm);
-extern DECL_FUNC_PTR(krb_mk_req);
-extern DECL_FUNC_PTR(krb_realmofhost);
-extern DECL_FUNC_PTR(tf_init);
-extern DECL_FUNC_PTR(tf_close);
-extern DECL_FUNC_PTR(tf_get_cred);
-extern DECL_FUNC_PTR(tf_get_pname);
-extern DECL_FUNC_PTR(tf_get_pinst);
-extern DECL_FUNC_PTR(LocalHostAddr);
-extern DECL_FUNC_PTR(tkt_string);
-extern DECL_FUNC_PTR(krb_set_tkt_string);
-extern DECL_FUNC_PTR(initialize_krb_error_func);
-extern DECL_FUNC_PTR(initialize_kadm_error_table);
-extern DECL_FUNC_PTR(dest_tkt);
-extern DECL_FUNC_PTR(lsh_LoadKrb4LeashErrorTables); // XXX
-extern DECL_FUNC_PTR(krb_in_tkt);
-extern DECL_FUNC_PTR(krb_save_credentials);
-extern DECL_FUNC_PTR(krb_get_krbconf2);
-extern DECL_FUNC_PTR(krb_get_krbrealm2);
-extern DECL_FUNC_PTR(krb_life_to_time);
-
-// krb5 functions
-extern DECL_FUNC_PTR(krb5_change_password);
-extern DECL_FUNC_PTR(krb5_get_init_creds_opt_init);
-extern DECL_FUNC_PTR(krb5_get_init_creds_opt_set_tkt_life);
-extern DECL_FUNC_PTR(krb5_get_init_creds_opt_set_renew_life);
-extern DECL_FUNC_PTR(krb5_get_init_creds_opt_set_forwardable);
-extern DECL_FUNC_PTR(krb5_get_init_creds_opt_set_proxiable);
-extern DECL_FUNC_PTR(krb5_get_init_creds_opt_set_renew_life);
-extern DECL_FUNC_PTR(krb5_get_init_creds_opt_set_address_list);
-extern DECL_FUNC_PTR(krb5_get_init_creds_opt_set_change_password_prompt);
-extern DECL_FUNC_PTR(krb5_get_init_creds_password);
-extern DECL_FUNC_PTR(krb5_get_prompt_types);
-extern DECL_FUNC_PTR(krb5_build_principal_ext);
-extern DECL_FUNC_PTR(krb5_cc_get_name);
-extern DECL_FUNC_PTR(krb5_cc_get_type);
-extern DECL_FUNC_PTR(krb5_cc_resolve);
-extern DECL_FUNC_PTR(krb5_cc_default);
-extern DECL_FUNC_PTR(krb5_cc_default_name);
-extern DECL_FUNC_PTR(krb5_cc_set_default_name);
-extern DECL_FUNC_PTR(krb5_cc_initialize);
-extern DECL_FUNC_PTR(krb5_cc_destroy);
-extern DECL_FUNC_PTR(krb5_cc_close);
-extern DECL_FUNC_PTR(krb5_cc_copy_creds);
-extern DECL_FUNC_PTR(krb5_cc_store_cred);
-extern DECL_FUNC_PTR(krb5_cc_retrieve_cred);
-extern DECL_FUNC_PTR(krb5_cc_get_principal);
-extern DECL_FUNC_PTR(krb5_cc_start_seq_get);
-extern DECL_FUNC_PTR(krb5_cc_next_cred);
-extern DECL_FUNC_PTR(krb5_cc_end_seq_get);
-extern DECL_FUNC_PTR(krb5_cc_remove_cred);
-extern DECL_FUNC_PTR(krb5_cc_set_flags);
-// extern DECL_FUNC_PTR(krb5_cc_get_type);
-extern DECL_FUNC_PTR(krb5_free_context);
-extern DECL_FUNC_PTR(krb5_free_cred_contents);
-extern DECL_FUNC_PTR(krb5_free_principal);
-extern DECL_FUNC_PTR(krb5_get_in_tkt_with_password);
-extern DECL_FUNC_PTR(krb5_init_context);
-extern DECL_FUNC_PTR(krb5_parse_name);
-extern DECL_FUNC_PTR(krb5_timeofday);
-extern DECL_FUNC_PTR(krb5_timestamp_to_sfstring);
-extern DECL_FUNC_PTR(krb5_unparse_name);
-extern DECL_FUNC_PTR(krb5_get_credentials);
-extern DECL_FUNC_PTR(krb5_mk_req);
-extern DECL_FUNC_PTR(krb5_sname_to_principal);
-extern DECL_FUNC_PTR(krb5_get_credentials_renew);
-extern DECL_FUNC_PTR(krb5_free_data);
-extern DECL_FUNC_PTR(krb5_free_data_contents);
-// extern DECL_FUNC_PTR(krb5_get_realm_domain);
-extern DECL_FUNC_PTR(krb5_free_unparsed_name);
-extern DECL_FUNC_PTR(krb5_os_localaddr);
-extern DECL_FUNC_PTR(krb5_copy_keyblock_contents);
-extern DECL_FUNC_PTR(krb5_copy_data);
-extern DECL_FUNC_PTR(krb5_free_creds);
-extern DECL_FUNC_PTR(krb5_build_principal);
-extern DECL_FUNC_PTR(krb5_get_renewed_creds);
-extern DECL_FUNC_PTR(krb5_free_addresses);
-extern DECL_FUNC_PTR(krb5_get_default_config_files);
-extern DECL_FUNC_PTR(krb5_free_config_files);
-extern DECL_FUNC_PTR(krb5_get_default_realm);
-extern DECL_FUNC_PTR(krb5_set_default_realm);
-extern DECL_FUNC_PTR(krb5_free_ticket);
-extern DECL_FUNC_PTR(krb5_decode_ticket);
-extern DECL_FUNC_PTR(krb5_get_host_realm);
-extern DECL_FUNC_PTR(krb5_free_host_realm);
-extern DECL_FUNC_PTR(krb5_c_random_make_octets);
-extern DECL_FUNC_PTR(krb5_free_default_realm);
-extern DECL_FUNC_PTR(krb5_string_to_deltat);
-
-// Krb524 functions
-extern DECL_FUNC_PTR(krb524_init_ets);
-extern DECL_FUNC_PTR(krb524_convert_creds_kdc);
-
-// ComErr functions
-extern DECL_FUNC_PTR(com_err);
-extern DECL_FUNC_PTR(error_message);
-
-// Profile functions
-extern DECL_FUNC_PTR(profile_init);
-extern DECL_FUNC_PTR(profile_flush);
-extern DECL_FUNC_PTR(profile_release);
-extern DECL_FUNC_PTR(profile_get_subsection_names);
-extern DECL_FUNC_PTR(profile_free_list);
-extern DECL_FUNC_PTR(profile_get_string);
-extern DECL_FUNC_PTR(profile_get_integer);
-extern DECL_FUNC_PTR(profile_get_values);
-extern DECL_FUNC_PTR(profile_get_relation_names);
-extern DECL_FUNC_PTR(profile_clear_relation);
-extern DECL_FUNC_PTR(profile_add_relation);
-extern DECL_FUNC_PTR(profile_update_relation);
-extern DECL_FUNC_PTR(profile_release_string);
-extern DECL_FUNC_PTR(profile_rename_section);
-
-// Service functions
-extern DECL_FUNC_PTR(OpenSCManagerA);
-extern DECL_FUNC_PTR(OpenServiceA);
-extern DECL_FUNC_PTR(QueryServiceStatus);
-extern DECL_FUNC_PTR(CloseServiceHandle);
-extern DECL_FUNC_PTR(LsaNtStatusToWinError);
-
-// LSA Functions
-extern DECL_FUNC_PTR(LsaConnectUntrusted);
-extern DECL_FUNC_PTR(LsaLookupAuthenticationPackage);
-extern DECL_FUNC_PTR(LsaCallAuthenticationPackage);
-extern DECL_FUNC_PTR(LsaFreeReturnBuffer);
-extern DECL_FUNC_PTR(LsaGetLogonSessionData);
-
-// toolhelp functions
-TYPEDEF_FUNC(
- HANDLE,
- WINAPI,
- CreateToolhelp32Snapshot,
- (DWORD, DWORD)
- );
-TYPEDEF_FUNC(
- BOOL,
- WINAPI,
- Module32First,
- (HANDLE, LPMODULEENTRY32)
- );
-TYPEDEF_FUNC(
- BOOL,
- WINAPI,
- Module32Next,
- (HANDLE, LPMODULEENTRY32)
- );
-
-// psapi functions
-TYPEDEF_FUNC(
- DWORD,
- WINAPI,
- GetModuleFileNameExA,
- (HANDLE, HMODULE, LPSTR, DWORD)
- );
-
-TYPEDEF_FUNC(
- BOOL,
- WINAPI,
- EnumProcessModules,
- (HANDLE, HMODULE*, DWORD, LPDWORD)
- );
-
-#define pGetModuleFileNameEx pGetModuleFileNameExA
-#define TOOLHELPDLL "kernel32.dll"
-#define PSAPIDLL "psapi.dll"
-
-// psapi functions
-extern DECL_FUNC_PTR(GetModuleFileNameExA);
-extern DECL_FUNC_PTR(EnumProcessModules);
-
-// toolhelp functions
-extern DECL_FUNC_PTR(CreateToolhelp32Snapshot);
-extern DECL_FUNC_PTR(Module32First);
-extern DECL_FUNC_PTR(Module32Next);
-
-khm_int32 init_imports(void);
-khm_int32 exit_imports(void);
-
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __KHIMAIRA_DYNIMPORT_H
+#define __KHIMAIRA_DYNIMPORT_H
+
+/* Dynamic imports */
+#include<khdefs.h>
+#include<tlhelp32.h>
+
+#if _WIN32_WINNT < 0x0501
+#define KHM_SAVE_WIN32_WINNT _WIN32_WINNT
+#undef _WIN32_WINNT
+#define _WIN32_WINNT 0x0501
+#endif
+#include<ntsecapi.h>
+#ifdef KHM_SAVE_WIN32_WINNT
+#undef _WIN32_WINNT
+#define _WIN32_WINNT KHM_SAVE_WIN32_WINNT
+#undef KHM_SAVE_WIN32_WINNT
+#endif
+
+extern HINSTANCE hKrb4;
+extern HINSTANCE hKrb5;
+extern HINSTANCE hProfile;
+
+///////////////////////////////////////////////////////////////////////////////
+
+#define CCAPI_DLL "krbcc32.dll"
+#define KRBCC32_DLL "krbcc32.dll"
+#define SERVICE_DLL "advapi32.dll"
+#define SECUR32_DLL "secur32.dll"
+#define PROFILE_DLL "xpprof32.dll"
+
+//////////////////////////////////////////////////////////////////////////////
+
+#include <loadfuncs-com_err.h>
+#include <loadfuncs-krb5.h>
+#include <loadfuncs-profile.h>
+#include <loadfuncs-krb.h>
+#include <loadfuncs-krb524.h>
+#include <loadfuncs-lsa.h>
+
+//// CCAPI
+/* In order to avoid including the private CCAPI headers */
+typedef int cc_int32;
+
+#define CC_API_VER_1 1
+#define CC_API_VER_2 2
+
+#define CCACHE_API cc_int32
+
+/*
+** The Official Error Codes
+*/
+#define CC_NOERROR 0
+#define CC_BADNAME 1
+#define CC_NOTFOUND 2
+#define CC_END 3
+#define CC_IO 4
+#define CC_WRITE 5
+#define CC_NOMEM 6
+#define CC_FORMAT 7
+#define CC_LOCKED 8
+#define CC_BAD_API_VERSION 9
+#define CC_NO_EXIST 10
+#define CC_NOT_SUPP 11
+#define CC_BAD_PARM 12
+#define CC_ERR_CACHE_ATTACH 13
+#define CC_ERR_CACHE_RELEASE 14
+#define CC_ERR_CACHE_FULL 15
+#define CC_ERR_CRED_VERSION 16
+
+enum {
+ CC_CRED_VUNKNOWN = 0, // For validation
+ CC_CRED_V4 = 1,
+ CC_CRED_V5 = 2,
+ CC_CRED_VMAX = 3 // For validation
+};
+
+typedef struct opaque_dll_control_block_type* apiCB;
+typedef struct _infoNC {
+ char* name;
+ char* principal;
+ cc_int32 vers;
+} infoNC;
+
+TYPEDEF_FUNC(
+CCACHE_API,
+CALLCONV_C,
+cc_initialize,
+ (
+ apiCB** cc_ctx, // < DLL's primary control structure.
+ // returned here, passed everywhere else
+ cc_int32 api_version, // > ver supported by caller (use CC_API_VER_1)
+ cc_int32* api_supported, // < if ~NULL, max ver supported by DLL
+ const char** vendor // < if ~NULL, vendor name in read only C string
+ )
+);
+
+TYPEDEF_FUNC(
+CCACHE_API,
+CALLCONV_C,
+cc_shutdown,
+ (
+ apiCB** cc_ctx // <> DLL's primary control structure. NULL after
+ )
+);
+
+TYPEDEF_FUNC(
+CCACHE_API,
+CALLCONV_C,
+cc_get_NC_info,
+ (
+ apiCB* cc_ctx, // > DLL's primary control structure
+ struct _infoNC*** ppNCi // < (NULL before call) null terminated,
+ // list of a structs (free via cc_free_infoNC())
+ )
+);
+
+TYPEDEF_FUNC(
+CCACHE_API,
+CALLCONV_C,
+cc_free_NC_info,
+ (
+ apiCB* cc_ctx,
+ struct _infoNC*** ppNCi // < free list of structs returned by
+ // cc_get_cache_names(). set to NULL on return
+ )
+);
+//// \CCAPI
+
+extern DWORD AfsAvailable;
+
+// service definitions
+typedef SC_HANDLE (WINAPI *FP_OpenSCManagerA)(char *, char *, DWORD);
+typedef SC_HANDLE (WINAPI *FP_OpenServiceA)(SC_HANDLE, char *, DWORD);
+typedef BOOL (WINAPI *FP_QueryServiceStatus)(SC_HANDLE, LPSERVICE_STATUS);
+typedef BOOL (WINAPI *FP_CloseServiceHandle)(SC_HANDLE);
+
+//////////////////////////////////////////////////////////////////////////////
+
+// CCAPI
+extern DECL_FUNC_PTR(cc_initialize);
+extern DECL_FUNC_PTR(cc_shutdown);
+extern DECL_FUNC_PTR(cc_get_NC_info);
+extern DECL_FUNC_PTR(cc_free_NC_info);
+
+// krb4 functions
+extern DECL_FUNC_PTR(get_krb_err_txt_entry);
+extern DECL_FUNC_PTR(k_isinst);
+extern DECL_FUNC_PTR(k_isname);
+extern DECL_FUNC_PTR(k_isrealm);
+extern DECL_FUNC_PTR(kadm_change_your_password);
+extern DECL_FUNC_PTR(kname_parse);
+extern DECL_FUNC_PTR(krb_get_cred);
+extern DECL_FUNC_PTR(krb_get_krbhst);
+extern DECL_FUNC_PTR(krb_get_lrealm);
+extern DECL_FUNC_PTR(krb_get_pw_in_tkt);
+extern DECL_FUNC_PTR(krb_get_tf_realm);
+extern DECL_FUNC_PTR(krb_mk_req);
+extern DECL_FUNC_PTR(krb_realmofhost);
+extern DECL_FUNC_PTR(tf_init);
+extern DECL_FUNC_PTR(tf_close);
+extern DECL_FUNC_PTR(tf_get_cred);
+extern DECL_FUNC_PTR(tf_get_pname);
+extern DECL_FUNC_PTR(tf_get_pinst);
+extern DECL_FUNC_PTR(LocalHostAddr);
+extern DECL_FUNC_PTR(tkt_string);
+extern DECL_FUNC_PTR(krb_set_tkt_string);
+extern DECL_FUNC_PTR(initialize_krb_error_func);
+extern DECL_FUNC_PTR(initialize_kadm_error_table);
+extern DECL_FUNC_PTR(dest_tkt);
+extern DECL_FUNC_PTR(lsh_LoadKrb4LeashErrorTables); // XXX
+extern DECL_FUNC_PTR(krb_in_tkt);
+extern DECL_FUNC_PTR(krb_save_credentials);
+extern DECL_FUNC_PTR(krb_get_krbconf2);
+extern DECL_FUNC_PTR(krb_get_krbrealm2);
+extern DECL_FUNC_PTR(krb_life_to_time);
+
+// krb5 functions
+extern DECL_FUNC_PTR(krb5_change_password);
+extern DECL_FUNC_PTR(krb5_get_init_creds_opt_init);
+extern DECL_FUNC_PTR(krb5_get_init_creds_opt_set_tkt_life);
+extern DECL_FUNC_PTR(krb5_get_init_creds_opt_set_renew_life);
+extern DECL_FUNC_PTR(krb5_get_init_creds_opt_set_forwardable);
+extern DECL_FUNC_PTR(krb5_get_init_creds_opt_set_proxiable);
+extern DECL_FUNC_PTR(krb5_get_init_creds_opt_set_renew_life);
+extern DECL_FUNC_PTR(krb5_get_init_creds_opt_set_address_list);
+extern DECL_FUNC_PTR(krb5_get_init_creds_opt_set_change_password_prompt);
+extern DECL_FUNC_PTR(krb5_get_init_creds_password);
+extern DECL_FUNC_PTR(krb5_get_prompt_types);
+extern DECL_FUNC_PTR(krb5_build_principal_ext);
+extern DECL_FUNC_PTR(krb5_cc_get_name);
+extern DECL_FUNC_PTR(krb5_cc_get_type);
+extern DECL_FUNC_PTR(krb5_cc_resolve);
+extern DECL_FUNC_PTR(krb5_cc_default);
+extern DECL_FUNC_PTR(krb5_cc_default_name);
+extern DECL_FUNC_PTR(krb5_cc_set_default_name);
+extern DECL_FUNC_PTR(krb5_cc_initialize);
+extern DECL_FUNC_PTR(krb5_cc_destroy);
+extern DECL_FUNC_PTR(krb5_cc_close);
+extern DECL_FUNC_PTR(krb5_cc_copy_creds);
+extern DECL_FUNC_PTR(krb5_cc_store_cred);
+extern DECL_FUNC_PTR(krb5_cc_retrieve_cred);
+extern DECL_FUNC_PTR(krb5_cc_get_principal);
+extern DECL_FUNC_PTR(krb5_cc_start_seq_get);
+extern DECL_FUNC_PTR(krb5_cc_next_cred);
+extern DECL_FUNC_PTR(krb5_cc_end_seq_get);
+extern DECL_FUNC_PTR(krb5_cc_remove_cred);
+extern DECL_FUNC_PTR(krb5_cc_set_flags);
+// extern DECL_FUNC_PTR(krb5_cc_get_type);
+extern DECL_FUNC_PTR(krb5_free_context);
+extern DECL_FUNC_PTR(krb5_free_cred_contents);
+extern DECL_FUNC_PTR(krb5_free_principal);
+extern DECL_FUNC_PTR(krb5_get_in_tkt_with_password);
+extern DECL_FUNC_PTR(krb5_init_context);
+extern DECL_FUNC_PTR(krb5_parse_name);
+extern DECL_FUNC_PTR(krb5_timeofday);
+extern DECL_FUNC_PTR(krb5_timestamp_to_sfstring);
+extern DECL_FUNC_PTR(krb5_unparse_name);
+extern DECL_FUNC_PTR(krb5_get_credentials);
+extern DECL_FUNC_PTR(krb5_mk_req);
+extern DECL_FUNC_PTR(krb5_sname_to_principal);
+extern DECL_FUNC_PTR(krb5_get_credentials_renew);
+extern DECL_FUNC_PTR(krb5_free_data);
+extern DECL_FUNC_PTR(krb5_free_data_contents);
+// extern DECL_FUNC_PTR(krb5_get_realm_domain);
+extern DECL_FUNC_PTR(krb5_free_unparsed_name);
+extern DECL_FUNC_PTR(krb5_os_localaddr);
+extern DECL_FUNC_PTR(krb5_copy_keyblock_contents);
+extern DECL_FUNC_PTR(krb5_copy_data);
+extern DECL_FUNC_PTR(krb5_free_creds);
+extern DECL_FUNC_PTR(krb5_build_principal);
+extern DECL_FUNC_PTR(krb5_get_renewed_creds);
+extern DECL_FUNC_PTR(krb5_free_addresses);
+extern DECL_FUNC_PTR(krb5_get_default_config_files);
+extern DECL_FUNC_PTR(krb5_free_config_files);
+extern DECL_FUNC_PTR(krb5_get_default_realm);
+extern DECL_FUNC_PTR(krb5_set_default_realm);
+extern DECL_FUNC_PTR(krb5_free_ticket);
+extern DECL_FUNC_PTR(krb5_decode_ticket);
+extern DECL_FUNC_PTR(krb5_get_host_realm);
+extern DECL_FUNC_PTR(krb5_free_host_realm);
+extern DECL_FUNC_PTR(krb5_c_random_make_octets);
+extern DECL_FUNC_PTR(krb5_free_default_realm);
+extern DECL_FUNC_PTR(krb5_string_to_deltat);
+
+// Krb524 functions
+extern DECL_FUNC_PTR(krb524_init_ets);
+extern DECL_FUNC_PTR(krb524_convert_creds_kdc);
+
+// ComErr functions
+extern DECL_FUNC_PTR(com_err);
+extern DECL_FUNC_PTR(error_message);
+
+// Profile functions
+extern DECL_FUNC_PTR(profile_init);
+extern DECL_FUNC_PTR(profile_flush);
+extern DECL_FUNC_PTR(profile_release);
+extern DECL_FUNC_PTR(profile_get_subsection_names);
+extern DECL_FUNC_PTR(profile_free_list);
+extern DECL_FUNC_PTR(profile_get_string);
+extern DECL_FUNC_PTR(profile_get_integer);
+extern DECL_FUNC_PTR(profile_get_values);
+extern DECL_FUNC_PTR(profile_get_relation_names);
+extern DECL_FUNC_PTR(profile_clear_relation);
+extern DECL_FUNC_PTR(profile_add_relation);
+extern DECL_FUNC_PTR(profile_update_relation);
+extern DECL_FUNC_PTR(profile_release_string);
+extern DECL_FUNC_PTR(profile_rename_section);
+
+// Service functions
+extern DECL_FUNC_PTR(OpenSCManagerA);
+extern DECL_FUNC_PTR(OpenServiceA);
+extern DECL_FUNC_PTR(QueryServiceStatus);
+extern DECL_FUNC_PTR(CloseServiceHandle);
+extern DECL_FUNC_PTR(LsaNtStatusToWinError);
+
+// LSA Functions
+extern DECL_FUNC_PTR(LsaConnectUntrusted);
+extern DECL_FUNC_PTR(LsaLookupAuthenticationPackage);
+extern DECL_FUNC_PTR(LsaCallAuthenticationPackage);
+extern DECL_FUNC_PTR(LsaFreeReturnBuffer);
+extern DECL_FUNC_PTR(LsaGetLogonSessionData);
+
+// toolhelp functions
+TYPEDEF_FUNC(
+ HANDLE,
+ WINAPI,
+ CreateToolhelp32Snapshot,
+ (DWORD, DWORD)
+ );
+TYPEDEF_FUNC(
+ BOOL,
+ WINAPI,
+ Module32First,
+ (HANDLE, LPMODULEENTRY32)
+ );
+TYPEDEF_FUNC(
+ BOOL,
+ WINAPI,
+ Module32Next,
+ (HANDLE, LPMODULEENTRY32)
+ );
+
+// psapi functions
+TYPEDEF_FUNC(
+ DWORD,
+ WINAPI,
+ GetModuleFileNameExA,
+ (HANDLE, HMODULE, LPSTR, DWORD)
+ );
+
+TYPEDEF_FUNC(
+ BOOL,
+ WINAPI,
+ EnumProcessModules,
+ (HANDLE, HMODULE*, DWORD, LPDWORD)
+ );
+
+#define pGetModuleFileNameEx pGetModuleFileNameExA
+#define TOOLHELPDLL "kernel32.dll"
+#define PSAPIDLL "psapi.dll"
+
+// psapi functions
+extern DECL_FUNC_PTR(GetModuleFileNameExA);
+extern DECL_FUNC_PTR(EnumProcessModules);
+
+// toolhelp functions
+extern DECL_FUNC_PTR(CreateToolhelp32Snapshot);
+extern DECL_FUNC_PTR(Module32First);
+extern DECL_FUNC_PTR(Module32Next);
+
+khm_int32 init_imports(void);
+khm_int32 exit_imports(void);
+
+#endif
diff --git a/src/windows/identity/plugins/common/krb5common.c b/src/windows/identity/plugins/common/krb5common.c
index 6c39586945..1278fbcfa7 100644
--- a/src/windows/identity/plugins/common/krb5common.c
+++ b/src/windows/identity/plugins/common/krb5common.c
@@ -1,451 +1,451 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<windows.h>
-#include<netidmgr.h>
-#include<dynimport.h>
-#include<krb5common.h>
-#ifdef DEBUG
-#include<assert.h>
-#endif
-#include<strsafe.h>
-
-/**************************************/
-/* khm_krb5_error(): */
-/**************************************/
-int
-khm_krb5_error(krb5_error_code rc, LPCSTR FailedFunctionName,
- int FreeContextFlag, krb5_context * ctx,
- krb5_ccache * cache)
-{
-#ifdef NO_KRB5
- return 0;
-#else
-
-#ifdef SHOW_MESSAGE_IN_AN_ANNOYING_WAY
- char message[256];
- const char *errText;
- int krb5Error = ((int)(rc & 255));
-
- errText = perror_message(rc);
- _snprintf(message, sizeof(message),
- "%s\n(Kerberos error %ld)\n\n%s failed",
- errText,
- krb5Error,
- FailedFunctionName);
-
- MessageBoxA(NULL, message, "Kerberos Five", MB_OK | MB_ICONERROR |
- MB_TASKMODAL |
- MB_SETFOREGROUND);
-#endif
-
- if (FreeContextFlag == 1)
- {
- if (*ctx != NULL)
- {
- if (*cache != NULL) {
- pkrb5_cc_close(*ctx, *cache);
- *cache = NULL;
- }
-
- pkrb5_free_context(*ctx);
- *ctx = NULL;
- }
- }
-
- return rc;
-
-#endif //!NO_KRB5
-}
-
-int
-khm_krb5_initialize(khm_handle ident,
- krb5_context *ctx,
- krb5_ccache *cache)
-{
-#ifdef NO_KRB5
- return(0);
-#else
-
- LPCSTR functionName = NULL;
- int freeContextFlag = 0;
- krb5_error_code rc = 0;
- krb5_flags flags = 0;
-
- if (pkrb5_init_context == NULL)
- return 1;
-
- if (*ctx == 0 && (rc = (*pkrb5_init_context)(ctx))) {
- functionName = "krb5_init_context()";
- freeContextFlag = 0;
- goto on_error;
- }
-
- if(*cache == 0) {
- wchar_t wccname[MAX_PATH];
- khm_size cbwccname;
-
- if(ident != NULL) {
- cbwccname = sizeof(wccname);
- do {
- char ccname[256];
-
- if(KHM_FAILED(kcdb_identity_get_attrib(ident, L"Krb5CCName",
- NULL, wccname,
- &cbwccname))) {
- cbwccname = sizeof(wccname);
- if (KHM_FAILED
- (khm_krb5_find_ccache_for_identity(ident,
- ctx,
- wccname,
- &cbwccname))) {
-#ifdef DEBUG_LIKE_A_MADMAN
- assert(FALSE);
-#endif
- break;
- }
- }
-
- if(UnicodeStrToAnsi(ccname, sizeof(ccname), wccname) == 0)
- break;
-
- if((*pkrb5_cc_resolve)(*ctx, ccname, cache)) {
- functionName = "krb5_cc_resolve()";
- freeContextFlag = 1;
- goto on_error;
- }
- } while(FALSE);
- }
-
-#ifndef FAILOVER_TO_DEFAULT_CCACHE
- rc = 1;
-#endif
- if (*cache == 0
-#ifdef FAILOVER_TO_DEFAULT_CCACHE
- && (rc = (*pkrb5_cc_default)(*ctx, cache))
-#endif
- ) {
- functionName = "krb5_cc_default()";
- freeContextFlag = 1;
- goto on_error;
- }
- }
-
-#ifdef KRB5_TC_NOTICKET
- flags = KRB5_TC_NOTICKET;
-#endif
-
- if ((rc = (*pkrb5_cc_set_flags)(*ctx, *cache, flags)))
- {
- if (rc != KRB5_FCC_NOFILE && rc != KRB5_CC_NOTFOUND)
- khm_krb5_error(rc, "krb5_cc_set_flags()", 0, ctx,
- cache);
- else if ((rc == KRB5_FCC_NOFILE || rc == KRB5_CC_NOTFOUND) && *ctx != NULL) {
- if (*cache != NULL) {
- (*pkrb5_cc_close)(*ctx, *cache);
- *cache = NULL;
- }
- }
- return rc;
- }
- return 0;
-
-on_error:
- return khm_krb5_error(rc, functionName, freeContextFlag, ctx, cache);
-#endif //!NO_KRB5
-}
-
-#define TIMET_TOLERANCE (60*5)
-
-khm_int32 KHMAPI
-khm_get_identity_expiration_time(krb5_context ctx, krb5_ccache cc,
- khm_handle ident,
- krb5_timestamp * pexpiration)
-{
- krb5_principal principal = 0;
- char * princ_name = NULL;
- krb5_creds creds;
- krb5_error_code code;
- krb5_error_code cc_code;
- krb5_cc_cursor cur;
- krb5_timestamp now, expiration = 0;
-
- wchar_t w_ident_name[KCDB_IDENT_MAXCCH_NAME];
- char ident_name[KCDB_IDENT_MAXCCH_NAME];
- khm_size cb;
-
- khm_int32 rv = KHM_ERROR_NOT_FOUND;
-
- if (!ctx || !cc || !ident || !pexpiration)
- return KHM_ERROR_GENERAL;
-
- code = pkrb5_cc_get_principal(ctx, cc, &principal);
-
- if ( code )
- return KHM_ERROR_INVALID_PARAM;
-
- cb = sizeof(w_ident_name);
- kcdb_identity_get_name(ident, w_ident_name, &cb);
- UnicodeStrToAnsi(ident_name, sizeof(ident_name), w_ident_name);
-
- code = pkrb5_unparse_name(ctx, principal, &princ_name);
-
- /* compare principal to ident. */
-
- if ( code || !princ_name ||
- strcmp(princ_name, ident_name) ) {
- if (princ_name)
- pkrb5_free_unparsed_name(ctx, princ_name);
- pkrb5_free_principal(ctx, principal);
- return KHM_ERROR_UNKNOWN;
- }
-
- pkrb5_free_unparsed_name(ctx, princ_name);
- pkrb5_free_principal(ctx, principal);
-
- code = pkrb5_timeofday(ctx, &now);
-
- if (code)
- return KHM_ERROR_UNKNOWN;
-
- cc_code = pkrb5_cc_start_seq_get(ctx, cc, &cur);
-
- while (!(cc_code = pkrb5_cc_next_cred(ctx, cc, &cur, &creds))) {
- krb5_data * c0 = krb5_princ_name(ctx, creds.server);
- krb5_data * c1 = krb5_princ_component(ctx, creds.server, 1);
- krb5_data * r = krb5_princ_realm(ctx, creds.server);
-
- if ( c0 && c1 && r && c1->length == r->length &&
- !strncmp(c1->data,r->data,r->length) &&
- !strncmp("krbtgt",c0->data,c0->length) ) {
-
- /* we have a TGT, check for the expiration time.
- * if it is valid and renewable, use the renew time
- */
-
- if (!(creds.ticket_flags & TKT_FLG_INVALID) &&
- creds.times.starttime < (now + TIMET_TOLERANCE) &&
- (creds.times.endtime + TIMET_TOLERANCE) > now) {
- expiration = creds.times.endtime;
-
- if ((creds.ticket_flags & TKT_FLG_RENEWABLE) &&
- (creds.times.renew_till > creds.times.endtime)) {
- expiration = creds.times.renew_till;
- }
- }
- }
- }
-
- if (cc_code == KRB5_CC_END) {
- cc_code = pkrb5_cc_end_seq_get(ctx, cc, &cur);
- rv = KHM_ERROR_SUCCESS;
- *pexpiration = expiration;
- }
-
- return rv;
-}
-
-khm_int32 KHMAPI
-khm_krb5_find_ccache_for_identity(khm_handle ident, krb5_context *pctx,
- void * buffer, khm_size * pcbbuf)
-{
- krb5_context ctx = 0;
- krb5_ccache cache = 0;
- krb5_error_code code;
- apiCB * cc_ctx = 0;
- struct _infoNC ** pNCi = NULL;
- int i;
- khm_int32 t;
- wchar_t * ms = NULL;
- khm_size cb;
- krb5_timestamp expiration = 0;
- krb5_timestamp best_match_expiration = 0;
- char best_match_ccname[256] = "";
- khm_handle csp_params = NULL;
- khm_handle csp_plugins = NULL;
-
- if (!buffer || !pcbbuf)
- return KHM_ERROR_GENERAL;
-
- ctx = *pctx;
-
- if (!pcc_initialize ||
- !pcc_get_NC_info ||
- !pcc_free_NC_info ||
- !pcc_shutdown)
- goto _skip_cc_iter;
-
- code = pcc_initialize(&cc_ctx, CC_API_VER_2, NULL, NULL);
- if (code)
- goto _exit;
-
- code = pcc_get_NC_info(cc_ctx, &pNCi);
-
- if (code)
- goto _exit;
-
- for(i=0; pNCi[i]; i++) {
- if (pNCi[i]->vers != CC_CRED_V5)
- continue;
-
- code = (*pkrb5_cc_resolve)(ctx, pNCi[i]->name, &cache);
- if (code)
- continue;
-
- /* need a function to check the cache for the identity
- * and determine if it has valid tickets. If it has
- * the right identity and valid tickets, store the
- * expiration time and the cache name. If it has the
- * right identity but no valid tickets, store the ccache
- * name and an expiration time of zero. if it does not
- * have the right identity don't save the name.
- *
- * Keep searching to find the best cache available.
- */
-
- if (KHM_SUCCEEDED(khm_get_identity_expiration_time(ctx, cache,
- ident,
- &expiration))) {
- if ( expiration > best_match_expiration ) {
- best_match_expiration = expiration;
- StringCbCopyA(best_match_ccname,
- sizeof(best_match_ccname),
- "API:");
- StringCbCatA(best_match_ccname,
- sizeof(best_match_ccname),
- pNCi[i]->name);
- expiration = 0;
- }
- }
-
- if(ctx != NULL && cache != NULL)
- (*pkrb5_cc_close)(ctx, cache);
- cache = 0;
- }
-
- _skip_cc_iter:
-
- if (KHM_SUCCEEDED(kmm_get_plugins_config(0, &csp_plugins))) {
- khc_open_space(csp_plugins, L"Krb5Cred\\Parameters", 0, &csp_params);
- khc_close_space(csp_plugins);
- csp_plugins = NULL;
- }
-
-#ifdef DEBUG
- if (csp_params == NULL) {
- assert(FALSE);
- }
-#endif
-
- if (csp_params &&
- KHM_SUCCEEDED(khc_read_int32(csp_params, L"MsLsaList", &t)) && t) {
- code = (*pkrb5_cc_resolve)(ctx, "MSLSA:", &cache);
- if (code == 0 && cache) {
- if (KHM_SUCCEEDED(khm_get_identity_expiration_time(ctx, cache,
- ident,
- &expiration))) {
- if ( expiration > best_match_expiration ) {
- best_match_expiration = expiration;
- StringCbCopyA(best_match_ccname, sizeof(best_match_ccname),
- "MSLSA:");
- expiration = 0;
- }
- }
- }
-
- if (ctx != NULL && cache != NULL)
- (*pkrb5_cc_close)(ctx, cache);
-
- cache = 0;
- }
-
- if (csp_params &&
- khc_read_multi_string(csp_params, L"FileCCList", NULL, &cb)
- == KHM_ERROR_TOO_LONG &&
- cb > sizeof(wchar_t) * 2) {
-
- wchar_t * t;
- char ccname[MAX_PATH + 6];
-
- ms = PMALLOC(cb);
-
-#ifdef DEBUG
- assert(ms);
-#endif
-
- khc_read_multi_string(csp_params, L"FileCCList", ms, &cb);
- for(t = ms; t && *t; t = multi_string_next(t)) {
- StringCchPrintfA(ccname, ARRAYLENGTH(ccname),
- "FILE:%S", t);
-
- code = (*pkrb5_cc_resolve)(ctx, ccname, &cache);
- if (code)
- continue;
-
- if (KHM_SUCCEEDED(khm_get_identity_expiration_time(ctx, cache,
- ident,
- &expiration))) {
- if ( expiration > best_match_expiration ) {
- best_match_expiration = expiration;
- StringCbCopyA(best_match_ccname,
- sizeof(best_match_ccname),
- ccname);
- expiration = 0;
- }
- }
-
- if (ctx != NULL && cache != NULL)
- (*pkrb5_cc_close)(ctx, cache);
- cache = 0;
- }
-
- PFREE(ms);
- }
- _exit:
- if (csp_params)
- khc_close_space(csp_params);
-
- if (pNCi)
- (*pcc_free_NC_info)(cc_ctx, &pNCi);
-
- if (cc_ctx)
- (*pcc_shutdown)(&cc_ctx);
-
- if (best_match_ccname[0]) {
-
- if (*pcbbuf = AnsiStrToUnicode((wchar_t *)buffer,
- *pcbbuf,
- best_match_ccname)) {
-
- *pcbbuf = (*pcbbuf + 1) * sizeof(wchar_t);
-
- return KHM_ERROR_SUCCESS;
- }
-
- }
-
- return KHM_ERROR_GENERAL;
-}
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<windows.h>
+#include<netidmgr.h>
+#include<dynimport.h>
+#include<krb5common.h>
+#ifdef DEBUG
+#include<assert.h>
+#endif
+#include<strsafe.h>
+
+/**************************************/
+/* khm_krb5_error(): */
+/**************************************/
+int
+khm_krb5_error(krb5_error_code rc, LPCSTR FailedFunctionName,
+ int FreeContextFlag, krb5_context * ctx,
+ krb5_ccache * cache)
+{
+#ifdef NO_KRB5
+ return 0;
+#else
+
+#ifdef SHOW_MESSAGE_IN_AN_ANNOYING_WAY
+ char message[256];
+ const char *errText;
+ int krb5Error = ((int)(rc & 255));
+
+ errText = perror_message(rc);
+ _snprintf(message, sizeof(message),
+ "%s\n(Kerberos error %ld)\n\n%s failed",
+ errText,
+ krb5Error,
+ FailedFunctionName);
+
+ MessageBoxA(NULL, message, "Kerberos Five", MB_OK | MB_ICONERROR |
+ MB_TASKMODAL |
+ MB_SETFOREGROUND);
+#endif
+
+ if (FreeContextFlag == 1)
+ {
+ if (*ctx != NULL)
+ {
+ if (*cache != NULL) {
+ pkrb5_cc_close(*ctx, *cache);
+ *cache = NULL;
+ }
+
+ pkrb5_free_context(*ctx);
+ *ctx = NULL;
+ }
+ }
+
+ return rc;
+
+#endif //!NO_KRB5
+}
+
+int
+khm_krb5_initialize(khm_handle ident,
+ krb5_context *ctx,
+ krb5_ccache *cache)
+{
+#ifdef NO_KRB5
+ return(0);
+#else
+
+ LPCSTR functionName = NULL;
+ int freeContextFlag = 0;
+ krb5_error_code rc = 0;
+ krb5_flags flags = 0;
+
+ if (pkrb5_init_context == NULL)
+ return 1;
+
+ if (*ctx == 0 && (rc = (*pkrb5_init_context)(ctx))) {
+ functionName = "krb5_init_context()";
+ freeContextFlag = 0;
+ goto on_error;
+ }
+
+ if(*cache == 0) {
+ wchar_t wccname[MAX_PATH];
+ khm_size cbwccname;
+
+ if(ident != NULL) {
+ cbwccname = sizeof(wccname);
+ do {
+ char ccname[256];
+
+ if(KHM_FAILED(kcdb_identity_get_attrib(ident, L"Krb5CCName",
+ NULL, wccname,
+ &cbwccname))) {
+ cbwccname = sizeof(wccname);
+ if (KHM_FAILED
+ (khm_krb5_find_ccache_for_identity(ident,
+ ctx,
+ wccname,
+ &cbwccname))) {
+#ifdef DEBUG_LIKE_A_MADMAN
+ assert(FALSE);
+#endif
+ break;
+ }
+ }
+
+ if(UnicodeStrToAnsi(ccname, sizeof(ccname), wccname) == 0)
+ break;
+
+ if((*pkrb5_cc_resolve)(*ctx, ccname, cache)) {
+ functionName = "krb5_cc_resolve()";
+ freeContextFlag = 1;
+ goto on_error;
+ }
+ } while(FALSE);
+ }
+
+#ifndef FAILOVER_TO_DEFAULT_CCACHE
+ rc = 1;
+#endif
+ if (*cache == 0
+#ifdef FAILOVER_TO_DEFAULT_CCACHE
+ && (rc = (*pkrb5_cc_default)(*ctx, cache))
+#endif
+ ) {
+ functionName = "krb5_cc_default()";
+ freeContextFlag = 1;
+ goto on_error;
+ }
+ }
+
+#ifdef KRB5_TC_NOTICKET
+ flags = KRB5_TC_NOTICKET;
+#endif
+
+ if ((rc = (*pkrb5_cc_set_flags)(*ctx, *cache, flags)))
+ {
+ if (rc != KRB5_FCC_NOFILE && rc != KRB5_CC_NOTFOUND)
+ khm_krb5_error(rc, "krb5_cc_set_flags()", 0, ctx,
+ cache);
+ else if ((rc == KRB5_FCC_NOFILE || rc == KRB5_CC_NOTFOUND) && *ctx != NULL) {
+ if (*cache != NULL) {
+ (*pkrb5_cc_close)(*ctx, *cache);
+ *cache = NULL;
+ }
+ }
+ return rc;
+ }
+ return 0;
+
+on_error:
+ return khm_krb5_error(rc, functionName, freeContextFlag, ctx, cache);
+#endif //!NO_KRB5
+}
+
+#define TIMET_TOLERANCE (60*5)
+
+khm_int32 KHMAPI
+khm_get_identity_expiration_time(krb5_context ctx, krb5_ccache cc,
+ khm_handle ident,
+ krb5_timestamp * pexpiration)
+{
+ krb5_principal principal = 0;
+ char * princ_name = NULL;
+ krb5_creds creds;
+ krb5_error_code code;
+ krb5_error_code cc_code;
+ krb5_cc_cursor cur;
+ krb5_timestamp now, expiration = 0;
+
+ wchar_t w_ident_name[KCDB_IDENT_MAXCCH_NAME];
+ char ident_name[KCDB_IDENT_MAXCCH_NAME];
+ khm_size cb;
+
+ khm_int32 rv = KHM_ERROR_NOT_FOUND;
+
+ if (!ctx || !cc || !ident || !pexpiration)
+ return KHM_ERROR_GENERAL;
+
+ code = pkrb5_cc_get_principal(ctx, cc, &principal);
+
+ if ( code )
+ return KHM_ERROR_INVALID_PARAM;
+
+ cb = sizeof(w_ident_name);
+ kcdb_identity_get_name(ident, w_ident_name, &cb);
+ UnicodeStrToAnsi(ident_name, sizeof(ident_name), w_ident_name);
+
+ code = pkrb5_unparse_name(ctx, principal, &princ_name);
+
+ /* compare principal to ident. */
+
+ if ( code || !princ_name ||
+ strcmp(princ_name, ident_name) ) {
+ if (princ_name)
+ pkrb5_free_unparsed_name(ctx, princ_name);
+ pkrb5_free_principal(ctx, principal);
+ return KHM_ERROR_UNKNOWN;
+ }
+
+ pkrb5_free_unparsed_name(ctx, princ_name);
+ pkrb5_free_principal(ctx, principal);
+
+ code = pkrb5_timeofday(ctx, &now);
+
+ if (code)
+ return KHM_ERROR_UNKNOWN;
+
+ cc_code = pkrb5_cc_start_seq_get(ctx, cc, &cur);
+
+ while (!(cc_code = pkrb5_cc_next_cred(ctx, cc, &cur, &creds))) {
+ krb5_data * c0 = krb5_princ_name(ctx, creds.server);
+ krb5_data * c1 = krb5_princ_component(ctx, creds.server, 1);
+ krb5_data * r = krb5_princ_realm(ctx, creds.server);
+
+ if ( c0 && c1 && r && c1->length == r->length &&
+ !strncmp(c1->data,r->data,r->length) &&
+ !strncmp("krbtgt",c0->data,c0->length) ) {
+
+ /* we have a TGT, check for the expiration time.
+ * if it is valid and renewable, use the renew time
+ */
+
+ if (!(creds.ticket_flags & TKT_FLG_INVALID) &&
+ creds.times.starttime < (now + TIMET_TOLERANCE) &&
+ (creds.times.endtime + TIMET_TOLERANCE) > now) {
+ expiration = creds.times.endtime;
+
+ if ((creds.ticket_flags & TKT_FLG_RENEWABLE) &&
+ (creds.times.renew_till > creds.times.endtime)) {
+ expiration = creds.times.renew_till;
+ }
+ }
+ }
+ }
+
+ if (cc_code == KRB5_CC_END) {
+ cc_code = pkrb5_cc_end_seq_get(ctx, cc, &cur);
+ rv = KHM_ERROR_SUCCESS;
+ *pexpiration = expiration;
+ }
+
+ return rv;
+}
+
+khm_int32 KHMAPI
+khm_krb5_find_ccache_for_identity(khm_handle ident, krb5_context *pctx,
+ void * buffer, khm_size * pcbbuf)
+{
+ krb5_context ctx = 0;
+ krb5_ccache cache = 0;
+ krb5_error_code code;
+ apiCB * cc_ctx = 0;
+ struct _infoNC ** pNCi = NULL;
+ int i;
+ khm_int32 t;
+ wchar_t * ms = NULL;
+ khm_size cb;
+ krb5_timestamp expiration = 0;
+ krb5_timestamp best_match_expiration = 0;
+ char best_match_ccname[256] = "";
+ khm_handle csp_params = NULL;
+ khm_handle csp_plugins = NULL;
+
+ if (!buffer || !pcbbuf)
+ return KHM_ERROR_GENERAL;
+
+ ctx = *pctx;
+
+ if (!pcc_initialize ||
+ !pcc_get_NC_info ||
+ !pcc_free_NC_info ||
+ !pcc_shutdown)
+ goto _skip_cc_iter;
+
+ code = pcc_initialize(&cc_ctx, CC_API_VER_2, NULL, NULL);
+ if (code)
+ goto _exit;
+
+ code = pcc_get_NC_info(cc_ctx, &pNCi);
+
+ if (code)
+ goto _exit;
+
+ for(i=0; pNCi[i]; i++) {
+ if (pNCi[i]->vers != CC_CRED_V5)
+ continue;
+
+ code = (*pkrb5_cc_resolve)(ctx, pNCi[i]->name, &cache);
+ if (code)
+ continue;
+
+ /* need a function to check the cache for the identity
+ * and determine if it has valid tickets. If it has
+ * the right identity and valid tickets, store the
+ * expiration time and the cache name. If it has the
+ * right identity but no valid tickets, store the ccache
+ * name and an expiration time of zero. if it does not
+ * have the right identity don't save the name.
+ *
+ * Keep searching to find the best cache available.
+ */
+
+ if (KHM_SUCCEEDED(khm_get_identity_expiration_time(ctx, cache,
+ ident,
+ &expiration))) {
+ if ( expiration > best_match_expiration ) {
+ best_match_expiration = expiration;
+ StringCbCopyA(best_match_ccname,
+ sizeof(best_match_ccname),
+ "API:");
+ StringCbCatA(best_match_ccname,
+ sizeof(best_match_ccname),
+ pNCi[i]->name);
+ expiration = 0;
+ }
+ }
+
+ if(ctx != NULL && cache != NULL)
+ (*pkrb5_cc_close)(ctx, cache);
+ cache = 0;
+ }
+
+ _skip_cc_iter:
+
+ if (KHM_SUCCEEDED(kmm_get_plugins_config(0, &csp_plugins))) {
+ khc_open_space(csp_plugins, L"Krb5Cred\\Parameters", 0, &csp_params);
+ khc_close_space(csp_plugins);
+ csp_plugins = NULL;
+ }
+
+#ifdef DEBUG
+ if (csp_params == NULL) {
+ assert(FALSE);
+ }
+#endif
+
+ if (csp_params &&
+ KHM_SUCCEEDED(khc_read_int32(csp_params, L"MsLsaList", &t)) && t) {
+ code = (*pkrb5_cc_resolve)(ctx, "MSLSA:", &cache);
+ if (code == 0 && cache) {
+ if (KHM_SUCCEEDED(khm_get_identity_expiration_time(ctx, cache,
+ ident,
+ &expiration))) {
+ if ( expiration > best_match_expiration ) {
+ best_match_expiration = expiration;
+ StringCbCopyA(best_match_ccname, sizeof(best_match_ccname),
+ "MSLSA:");
+ expiration = 0;
+ }
+ }
+ }
+
+ if (ctx != NULL && cache != NULL)
+ (*pkrb5_cc_close)(ctx, cache);
+
+ cache = 0;
+ }
+
+ if (csp_params &&
+ khc_read_multi_string(csp_params, L"FileCCList", NULL, &cb)
+ == KHM_ERROR_TOO_LONG &&
+ cb > sizeof(wchar_t) * 2) {
+
+ wchar_t * t;
+ char ccname[MAX_PATH + 6];
+
+ ms = PMALLOC(cb);
+
+#ifdef DEBUG
+ assert(ms);
+#endif
+
+ khc_read_multi_string(csp_params, L"FileCCList", ms, &cb);
+ for(t = ms; t && *t; t = multi_string_next(t)) {
+ StringCchPrintfA(ccname, ARRAYLENGTH(ccname),
+ "FILE:%S", t);
+
+ code = (*pkrb5_cc_resolve)(ctx, ccname, &cache);
+ if (code)
+ continue;
+
+ if (KHM_SUCCEEDED(khm_get_identity_expiration_time(ctx, cache,
+ ident,
+ &expiration))) {
+ if ( expiration > best_match_expiration ) {
+ best_match_expiration = expiration;
+ StringCbCopyA(best_match_ccname,
+ sizeof(best_match_ccname),
+ ccname);
+ expiration = 0;
+ }
+ }
+
+ if (ctx != NULL && cache != NULL)
+ (*pkrb5_cc_close)(ctx, cache);
+ cache = 0;
+ }
+
+ PFREE(ms);
+ }
+ _exit:
+ if (csp_params)
+ khc_close_space(csp_params);
+
+ if (pNCi)
+ (*pcc_free_NC_info)(cc_ctx, &pNCi);
+
+ if (cc_ctx)
+ (*pcc_shutdown)(&cc_ctx);
+
+ if (best_match_ccname[0]) {
+
+ if (*pcbbuf = AnsiStrToUnicode((wchar_t *)buffer,
+ *pcbbuf,
+ best_match_ccname)) {
+
+ *pcbbuf = (*pcbbuf + 1) * sizeof(wchar_t);
+
+ return KHM_ERROR_SUCCESS;
+ }
+
+ }
+
+ return KHM_ERROR_GENERAL;
+}
diff --git a/src/windows/identity/plugins/common/krb5common.h b/src/windows/identity/plugins/common/krb5common.h
index df3db93ae1..29cae71ee9 100644
--- a/src/windows/identity/plugins/common/krb5common.h
+++ b/src/windows/identity/plugins/common/krb5common.h
@@ -1,56 +1,56 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-/* Adapted from multiple Leash header files */
-
-#ifndef __KHIMAIRA_KRB5COMMON_H
-#define __KHIMAIRA_KRB5COMMON_H
-
-#include<krb5.h>
-
-#ifndef NO_KRB5
-int khm_krb5_error(krb5_error_code rc, LPCSTR FailedFunctionName,
- int FreeContextFlag, krb5_context *ctx,
- krb5_ccache *cache);
-
-int
-khm_krb5_get_error_string(krb5_error_code rc,
- wchar_t * buffer,
- khm_size cb_buffer);
-
-int khm_krb5_initialize(khm_handle ident, krb5_context *, krb5_ccache *);
-
-khm_int32 KHMAPI
-khm_krb5_find_ccache_for_identity(khm_handle ident, krb5_context *pctx,
- void * buffer, khm_size * pcbbuf);
-
-khm_int32 KHMAPI
-khm_get_identity_expiration_time(krb5_context ctx, krb5_ccache cc,
- khm_handle ident,
- krb5_timestamp * pexpiration);
-#endif /* NO_KRB5 */
-
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+/* Adapted from multiple Leash header files */
+
+#ifndef __KHIMAIRA_KRB5COMMON_H
+#define __KHIMAIRA_KRB5COMMON_H
+
+#include<krb5.h>
+
+#ifndef NO_KRB5
+int khm_krb5_error(krb5_error_code rc, LPCSTR FailedFunctionName,
+ int FreeContextFlag, krb5_context *ctx,
+ krb5_ccache *cache);
+
+int
+khm_krb5_get_error_string(krb5_error_code rc,
+ wchar_t * buffer,
+ khm_size cb_buffer);
+
+int khm_krb5_initialize(khm_handle ident, krb5_context *, krb5_ccache *);
+
+khm_int32 KHMAPI
+khm_krb5_find_ccache_for_identity(khm_handle ident, krb5_context *pctx,
+ void * buffer, khm_size * pcbbuf);
+
+khm_int32 KHMAPI
+khm_get_identity_expiration_time(krb5_context ctx, krb5_ccache cc,
+ khm_handle ident,
+ krb5_timestamp * pexpiration);
+#endif /* NO_KRB5 */
+
+#endif
diff --git a/src/windows/identity/plugins/krb4/errorfuncs.c b/src/windows/identity/plugins/krb4/errorfuncs.c
index f1aa63d88b..f436a40a7e 100644
--- a/src/windows/identity/plugins/krb4/errorfuncs.c
+++ b/src/windows/identity/plugins/krb4/errorfuncs.c
@@ -1,226 +1,226 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<krbcred.h>
-#include<kherror.h>
-
-#include<strsafe.h>
-
-extern void (__cdecl *pinitialize_krb_error_func)();
-extern void (__cdecl *pinitialize_kadm_error_table)();
-
-
-khm_int32 init_error_funcs()
-{
-
-#if 0
- /*TODO: Do something about this */
- if (plsh_LoadKrb4LeashErrorTables)
- plsh_LoadKrb4LeashErrorTables(hLeashInst, 0);
-#endif
- return KHM_ERROR_SUCCESS;
-}
-
-khm_int32 exit_error_funcs()
-{
- return KHM_ERROR_SUCCESS;
-}
-
-// Global Variables.
-static long lsh_errno;
-static char *err_context; /* error context */
-extern int (*Lcom_err)(LPSTR,long,LPSTR,...);
-extern LPSTR (*Lerror_message)(long);
-extern LPSTR (*Lerror_table_name)(long);
-
-#ifdef WIN16
-#define UNDERSCORE "_"
-#else
-#define UNDERSCORE
-#endif
-
-HWND GetRootParent (HWND Child)
-{
- HWND Last = NULL;
- while (Child)
- {
- Last = Child;
- Child = GetParent (Child);
- }
- return Last;
-}
-
-
-LPSTR err_describe(LPSTR buf, size_t len, long code)
-{
- LPSTR cp, com_err_msg;
- int offset;
- long table_num;
- char *etype;
-
- offset = (int) (code & 255);
- table_num = code - offset;
- com_err_msg = Lerror_message(code);
-
- switch(table_num)
- {
- case krb_err_base:
- case kadm_err_base:
- break;
- default:
- StringCbCopyA(buf, len, com_err_msg);
- return buf;
- }
-
- cp = buf;
- if (table_num == krb_err_base)
- switch(offset)
- {
- case KDC_NAME_EXP: /* 001 Principal expired */
- case KDC_SERVICE_EXP: /* 002 Service expired */
- case KDC_AUTH_EXP: /* 003 Auth expired */
- case KDC_PKT_VER: /* 004 Protocol version unknown */
- case KDC_P_MKEY_VER: /* 005 Wrong master key version */
- case KDC_S_MKEY_VER: /* 006 Wrong master key version */
- case KDC_BYTE_ORDER: /* 007 Byte order unknown */
- case KDC_PR_N_UNIQUE: /* 009 Principal not unique */
- case KDC_NULL_KEY: /* 010 Principal has null key */
- case KDC_GEN_ERR: /* 011 Generic error from KDC */
- case INTK_W_NOTALL : /* 061 Not ALL tickets returned */
- case INTK_PROT : /* 063 Protocol Error */
- case INTK_ERR : /* 070 Other error */
- com_err_msg = "Something weird happened... try again, and if Leash"
- " continues to fail, contact Network Services as listed in the "
- "About box.";
- break;
- case KDC_PR_UNKNOWN: /* 008 Principal unknown */
- com_err_msg = "You have entered an unknown username/instance/realm"
- " combination.";
- break;
- case GC_TKFIL : /* 021 Can't read ticket file */
- case GC_NOTKT : /* 022 Can't find ticket or TGT */
- com_err_msg = "Something is wrong with the memory where your "
- "tickets are stored. Try exiting Windows and restarting your "
- "computer.";
- break;
- case MK_AP_TGTEXP : /* 026 TGT Expired */
- /* no extra error msg */
- break;
- case RD_AP_TIME : /* 037 delta_t too big */
- com_err_msg = "Your computer's clock is out of sync with the "
- "Kerberos server. Please see the help file about correcting "
- "your clock.";
- break;
-
- case RD_AP_UNDEC : /* 031 Can't decode authenticator */
- case RD_AP_EXP : /* 032 Ticket expired */
- case RD_AP_NYV : /* 033 Ticket not yet valid */
- case RD_AP_REPEAT : /* 034 Repeated request */
- case RD_AP_NOT_US : /* 035 The ticket isn't for us */
- case RD_AP_INCON : /* 036 Request is inconsistent */
- case RD_AP_BADD : /* 038 Incorrect net address */
- case RD_AP_VERSION : /* 039 protocol version mismatch */
- case RD_AP_MSG_TYPE : /* 040 invalid msg type */
- case RD_AP_MODIFIED : /* 041 message stream modified */
- case RD_AP_ORDER : /* 042 message out of order */
- case RD_AP_UNAUTHOR : /* 043 unauthorized request */
- /* no extra error msg */
- break;
- case GT_PW_NULL: /* 51 Current PW is null */
- case GT_PW_BADPW: /* 52 Incorrect current password */
- case GT_PW_PROT: /* 53 Protocol Error */
- case GT_PW_KDCERR: /* 54 Error returned by KDC */
- case GT_PW_NULLTKT: /* 55 Null tkt returned by KDC */
- /* no error msg yet */
- break;
-
- /* Values returned by send_to_kdc */
- case SKDC_RETRY : /* 56 Retry count exceeded */
- case SKDC_CANT : /* 57 Can't send request */
- com_err_msg = "Cannot contact the kerberos server for the selected realm.";
- break;
- /* no error message on purpose: */
- case INTK_BADPW : /* 062 Incorrect password */
- break;
- default:
- /* no extra error msg */
- break;
- }
- else
- switch(code)
- {
- case KADM_INSECURE_PW:
- /* if( kadm_info != NULL ){
- * wsprintf(buf, "%s\n%s", com_err_msg, kadm_info);
- * } else {
- * wsprintf(buf, "%s\nPlease see the help file for information "
- * "about secure passwords.", com_err_msg);
- * }
- * com_err_msg = buf;
- */
-
- /* The above code would be preferred since it allows site specific
- * information to be delivered from the Kerberos server. However the
- * message box is too small for VGA screens.
- * It does work well if we only have to support 1024x768
- */
-
- com_err_msg = "You have entered an insecure or weak password.";
-
- default:
- /* no extra error msg */
- break;
- }
- if(com_err_msg != buf) {
- StringCbCopyA(buf, len, com_err_msg);
- }
- cp = buf + strlen(buf);
- *cp++ = '\n';
- switch(table_num) {
- case krb_err_base:
- etype = "Kerberos";
- break;
- case kadm_err_base:
- etype = "Kerberos supplemental";
- break;
- default:
- etype = Lerror_table_name(table_num);
- break;
- }
- StringCbPrintfA((LPSTR) cp, len - (cp-buf), (LPSTR) "(%s error %d"
-#ifdef DEBUG_COM_ERR
- " (absolute error %ld)"
-#endif
- ")", etype, offset
- //")\nPress F1 for help on this error.", etype, offset
-#ifdef DEBUG_COM_ERR
- , code
-#endif
- );
-
- return (LPSTR)buf;
-}
-
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<krbcred.h>
+#include<kherror.h>
+
+#include<strsafe.h>
+
+extern void (__cdecl *pinitialize_krb_error_func)();
+extern void (__cdecl *pinitialize_kadm_error_table)();
+
+
+khm_int32 init_error_funcs()
+{
+
+#if 0
+ /*TODO: Do something about this */
+ if (plsh_LoadKrb4LeashErrorTables)
+ plsh_LoadKrb4LeashErrorTables(hLeashInst, 0);
+#endif
+ return KHM_ERROR_SUCCESS;
+}
+
+khm_int32 exit_error_funcs()
+{
+ return KHM_ERROR_SUCCESS;
+}
+
+// Global Variables.
+static long lsh_errno;
+static char *err_context; /* error context */
+extern int (*Lcom_err)(LPSTR,long,LPSTR,...);
+extern LPSTR (*Lerror_message)(long);
+extern LPSTR (*Lerror_table_name)(long);
+
+#ifdef WIN16
+#define UNDERSCORE "_"
+#else
+#define UNDERSCORE
+#endif
+
+HWND GetRootParent (HWND Child)
+{
+ HWND Last = NULL;
+ while (Child)
+ {
+ Last = Child;
+ Child = GetParent (Child);
+ }
+ return Last;
+}
+
+
+LPSTR err_describe(LPSTR buf, size_t len, long code)
+{
+ LPSTR cp, com_err_msg;
+ int offset;
+ long table_num;
+ char *etype;
+
+ offset = (int) (code & 255);
+ table_num = code - offset;
+ com_err_msg = Lerror_message(code);
+
+ switch(table_num)
+ {
+ case krb_err_base:
+ case kadm_err_base:
+ break;
+ default:
+ StringCbCopyA(buf, len, com_err_msg);
+ return buf;
+ }
+
+ cp = buf;
+ if (table_num == krb_err_base)
+ switch(offset)
+ {
+ case KDC_NAME_EXP: /* 001 Principal expired */
+ case KDC_SERVICE_EXP: /* 002 Service expired */
+ case KDC_AUTH_EXP: /* 003 Auth expired */
+ case KDC_PKT_VER: /* 004 Protocol version unknown */
+ case KDC_P_MKEY_VER: /* 005 Wrong master key version */
+ case KDC_S_MKEY_VER: /* 006 Wrong master key version */
+ case KDC_BYTE_ORDER: /* 007 Byte order unknown */
+ case KDC_PR_N_UNIQUE: /* 009 Principal not unique */
+ case KDC_NULL_KEY: /* 010 Principal has null key */
+ case KDC_GEN_ERR: /* 011 Generic error from KDC */
+ case INTK_W_NOTALL : /* 061 Not ALL tickets returned */
+ case INTK_PROT : /* 063 Protocol Error */
+ case INTK_ERR : /* 070 Other error */
+ com_err_msg = "Something weird happened... try again, and if Leash"
+ " continues to fail, contact Network Services as listed in the "
+ "About box.";
+ break;
+ case KDC_PR_UNKNOWN: /* 008 Principal unknown */
+ com_err_msg = "You have entered an unknown username/instance/realm"
+ " combination.";
+ break;
+ case GC_TKFIL : /* 021 Can't read ticket file */
+ case GC_NOTKT : /* 022 Can't find ticket or TGT */
+ com_err_msg = "Something is wrong with the memory where your "
+ "tickets are stored. Try exiting Windows and restarting your "
+ "computer.";
+ break;
+ case MK_AP_TGTEXP : /* 026 TGT Expired */
+ /* no extra error msg */
+ break;
+ case RD_AP_TIME : /* 037 delta_t too big */
+ com_err_msg = "Your computer's clock is out of sync with the "
+ "Kerberos server. Please see the help file about correcting "
+ "your clock.";
+ break;
+
+ case RD_AP_UNDEC : /* 031 Can't decode authenticator */
+ case RD_AP_EXP : /* 032 Ticket expired */
+ case RD_AP_NYV : /* 033 Ticket not yet valid */
+ case RD_AP_REPEAT : /* 034 Repeated request */
+ case RD_AP_NOT_US : /* 035 The ticket isn't for us */
+ case RD_AP_INCON : /* 036 Request is inconsistent */
+ case RD_AP_BADD : /* 038 Incorrect net address */
+ case RD_AP_VERSION : /* 039 protocol version mismatch */
+ case RD_AP_MSG_TYPE : /* 040 invalid msg type */
+ case RD_AP_MODIFIED : /* 041 message stream modified */
+ case RD_AP_ORDER : /* 042 message out of order */
+ case RD_AP_UNAUTHOR : /* 043 unauthorized request */
+ /* no extra error msg */
+ break;
+ case GT_PW_NULL: /* 51 Current PW is null */
+ case GT_PW_BADPW: /* 52 Incorrect current password */
+ case GT_PW_PROT: /* 53 Protocol Error */
+ case GT_PW_KDCERR: /* 54 Error returned by KDC */
+ case GT_PW_NULLTKT: /* 55 Null tkt returned by KDC */
+ /* no error msg yet */
+ break;
+
+ /* Values returned by send_to_kdc */
+ case SKDC_RETRY : /* 56 Retry count exceeded */
+ case SKDC_CANT : /* 57 Can't send request */
+ com_err_msg = "Cannot contact the kerberos server for the selected realm.";
+ break;
+ /* no error message on purpose: */
+ case INTK_BADPW : /* 062 Incorrect password */
+ break;
+ default:
+ /* no extra error msg */
+ break;
+ }
+ else
+ switch(code)
+ {
+ case KADM_INSECURE_PW:
+ /* if( kadm_info != NULL ){
+ * wsprintf(buf, "%s\n%s", com_err_msg, kadm_info);
+ * } else {
+ * wsprintf(buf, "%s\nPlease see the help file for information "
+ * "about secure passwords.", com_err_msg);
+ * }
+ * com_err_msg = buf;
+ */
+
+ /* The above code would be preferred since it allows site specific
+ * information to be delivered from the Kerberos server. However the
+ * message box is too small for VGA screens.
+ * It does work well if we only have to support 1024x768
+ */
+
+ com_err_msg = "You have entered an insecure or weak password.";
+
+ default:
+ /* no extra error msg */
+ break;
+ }
+ if(com_err_msg != buf) {
+ StringCbCopyA(buf, len, com_err_msg);
+ }
+ cp = buf + strlen(buf);
+ *cp++ = '\n';
+ switch(table_num) {
+ case krb_err_base:
+ etype = "Kerberos";
+ break;
+ case kadm_err_base:
+ etype = "Kerberos supplemental";
+ break;
+ default:
+ etype = Lerror_table_name(table_num);
+ break;
+ }
+ StringCbPrintfA((LPSTR) cp, len - (cp-buf), (LPSTR) "(%s error %d"
+#ifdef DEBUG_COM_ERR
+ " (absolute error %ld)"
+#endif
+ ")", etype, offset
+ //")\nPress F1 for help on this error.", etype, offset
+#ifdef DEBUG_COM_ERR
+ , code
+#endif
+ );
+
+ return (LPSTR)buf;
+}
+
diff --git a/src/windows/identity/plugins/krb4/errorfuncs.h b/src/windows/identity/plugins/krb4/errorfuncs.h
index e339eca4f7..d760c62595 100644
--- a/src/windows/identity/plugins/krb4/errorfuncs.h
+++ b/src/windows/identity/plugins/krb4/errorfuncs.h
@@ -1,65 +1,65 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#ifndef __KHIMAIRA_ERR_H
-#define __KHIMAIRA_ERR_H
-
-/* All error handling and reporting related functions for the krb4/5
- and AFS plugins */
-
-#include <errno.h>
-#include <com_err.h>
-/*
- * This is a hack needed because the real com_err.h does
- * not define err_func. We need it in the case where
- * we pull in the real com_err instead of the krb4
- * impostor.
- */
-#ifndef _DCNS_MIT_COM_ERR_H
-typedef LPSTR (*err_func)(int, long);
-#endif
-
-#include <krberr.h>
-#include <kadm_err.h>
-
-#define kadm_err_base ERROR_TABLE_BASE_kadm
-
-#include <stdarg.h>
-
-#ifndef KRBERR
-#define KRBERR(code) (code + krb_err_base)
-#endif
-
-LPSTR err_describe(LPSTR buf, size_t len, long code);
-
-
-/* */
-khm_int32 init_error_funcs();
-
-khm_int32 exit_error_funcs();
-
-
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __KHIMAIRA_ERR_H
+#define __KHIMAIRA_ERR_H
+
+/* All error handling and reporting related functions for the krb4/5
+ and AFS plugins */
+
+#include <errno.h>
+#include <com_err.h>
+/*
+ * This is a hack needed because the real com_err.h does
+ * not define err_func. We need it in the case where
+ * we pull in the real com_err instead of the krb4
+ * impostor.
+ */
+#ifndef _DCNS_MIT_COM_ERR_H
+typedef LPSTR (*err_func)(int, long);
+#endif
+
+#include <krberr.h>
+#include <kadm_err.h>
+
+#define kadm_err_base ERROR_TABLE_BASE_kadm
+
+#include <stdarg.h>
+
+#ifndef KRBERR
+#define KRBERR(code) (code + krb_err_base)
+#endif
+
+LPSTR err_describe(LPSTR buf, size_t len, long code);
+
+
+/* */
+khm_int32 init_error_funcs();
+
+khm_int32 exit_error_funcs();
+
+
+#endif
diff --git a/src/windows/identity/plugins/krb4/krb4configdlg.c b/src/windows/identity/plugins/krb4/krb4configdlg.c
index 523fbac5e0..338cf7fa88 100644
--- a/src/windows/identity/plugins/krb4/krb4configdlg.c
+++ b/src/windows/identity/plugins/krb4/krb4configdlg.c
@@ -1,539 +1,539 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<krbcred.h>
-#include<kherror.h>
-#include<khuidefs.h>
-#include<strsafe.h>
-#include<assert.h>
-
-typedef struct tag_k4_ids_data {
- khui_config_init_data cfg;
-
- khm_int32 get_tix;
-} k4_ids_data;
-
-static void
-k4_ids_read_params(k4_ids_data * d) {
- khm_int32 t;
-#ifdef DEBUG
- assert(csp_params);
-#endif
-
- t = 1;
- khc_read_int32(csp_params, L"Krb4NewCreds", &t);
- d->get_tix = !!t;
-}
-
-static void
-k4_ids_write_params(HWND hw, k4_ids_data * d) {
- khm_int32 nv;
- khm_boolean applied = FALSE;
-
- if (IsDlgButtonChecked(hw, IDC_CFG_GETTIX) == BST_CHECKED)
- nv = TRUE;
- else
- nv = FALSE;
-
- if (!!nv != !!d->get_tix) {
- d->get_tix = !!nv;
- khc_write_int32(csp_params, L"Krb4NewCreds", d->get_tix);
- applied = TRUE;
- }
-
- khui_cfg_set_flags_inst(&d->cfg,
- (applied)?KHUI_CNFLAG_APPLIED:0,
- KHUI_CNFLAG_APPLIED | KHUI_CNFLAG_MODIFIED);
-}
-
-static void
-k4_ids_check_mod(HWND hw, k4_ids_data * d) {
- khm_int32 nv;
-
- if (IsDlgButtonChecked(hw, IDC_CFG_GETTIX) == BST_CHECKED)
- nv = TRUE;
- else
- nv = FALSE;
-
- khui_cfg_set_flags_inst(&d->cfg,
- (!!nv != !!d->get_tix)? KHUI_CNFLAG_MODIFIED: 0,
- KHUI_CNFLAG_MODIFIED);
-}
-
-INT_PTR CALLBACK
-krb4_ids_config_proc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam) {
- k4_ids_data * d;
-
- switch(uMsg) {
- case WM_INITDIALOG:
- d = PMALLOC(sizeof(*d));
- ZeroMemory(d, sizeof(*d));
-
- d->cfg = *((khui_config_init_data *) lParam);
-
-#pragma warning(push)
-#pragma warning(disable: 4244)
- SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) d);
-#pragma warning(pop)
-
- k4_ids_read_params(d);
-
- CheckDlgButton(hwnd, IDC_CFG_GETTIX,
- (d->get_tix)? BST_CHECKED: BST_UNCHECKED);
-
- break;
-
- case WM_COMMAND:
- d = (k4_ids_data *) (LONG_PTR)
- GetWindowLongPtr(hwnd, DWLP_USER);
-
- if (HIWORD(wParam) == BN_CLICKED) {
- k4_ids_check_mod(hwnd, d);
- }
- break;
-
- case KHUI_WM_CFG_NOTIFY:
- d = (k4_ids_data *) (LONG_PTR)
- GetWindowLongPtr(hwnd, DWLP_USER);
-
- if (HIWORD(wParam) == WMCFG_APPLY) {
- k4_ids_write_params(hwnd, d);
- }
- break;
-
- case WM_DESTROY:
- d = (k4_ids_data *) (LONG_PTR)
- GetWindowLongPtr(hwnd, DWLP_USER);
-
- PFREE(d);
- break;
- }
-
- return FALSE;
-}
-
-typedef struct tag_k4_id_data {
- khui_config_init_data cfg;
- khm_int32 gettix; /* get tickets? */
- khm_boolean is_default_ident;
-} k4_id_data;
-
-void
-k4_id_read_params(k4_id_data * d) {
- wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
- khm_size cb;
- khm_handle ident = NULL;
- khm_handle csp_ident = NULL;
- khm_handle csp_idk4 = NULL;
- khm_int32 flags = 0;
- khm_int32 t;
-
- khc_read_int32(csp_params, L"Krb4NewCreds", &d->gettix);
-
- *idname = 0;
- cb = sizeof(idname);
- khui_cfg_get_name(d->cfg.ctx_node, idname, &cb);
-
- kcdb_identity_create(idname, 0, &ident);
-
- if (ident == NULL) {
- d->gettix = 0;
- goto done;
- }
-
- kcdb_identity_get_flags(ident, &flags);
-
- if (!(flags & KCDB_IDENT_FLAG_DEFAULT)) {
- d->gettix = 0;
- goto done;
- }
-
- d->is_default_ident = TRUE;
-
- if (d->gettix == 0)
- goto done;
-
- if (KHM_FAILED(kcdb_identity_get_config(ident, 0, &csp_ident)))
- goto done;
-
- if (KHM_FAILED(khc_open_space(csp_ident, CSNAME_KRB4CRED,
- 0, &csp_idk4)))
- goto close_config;
-
- if (KHM_SUCCEEDED(khc_read_int32(csp_idk4, L"Krb4NewCreds", &t)) &&
- !t)
- d->gettix = 1;
-
- close_config:
- if (csp_ident)
- khc_close_space(csp_ident);
-
- if (csp_idk4)
- khc_close_space(csp_idk4);
-
- done:
- if (ident)
- kcdb_identity_release(ident);
-
- return;
-}
-
-khm_boolean
-k4_id_write_params(HWND hwnd, k4_id_data * d) {
- wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
- khm_size cb_idname = sizeof(idname);
- khm_handle ident = NULL;
- khm_int32 flags = 0;
- khm_handle csp_ident = NULL;
- khm_handle csp_idk4 = NULL;
- khm_int32 gettix = 0;
- khm_boolean applied = FALSE;
-
- khui_cfg_get_name(d->cfg.ctx_node, idname, &cb_idname);
-
- kcdb_identity_create(idname, 0, &ident);
-
- if (ident == NULL)
- return FALSE;
-
- kcdb_identity_get_flags(ident, &flags);
-
- if (!(flags & KCDB_IDENT_FLAG_DEFAULT))
- goto done_apply;
-
- if (IsDlgButtonChecked(hwnd, IDC_CFG_GETTIX) == BST_CHECKED)
- gettix = TRUE;
-
- if (KHM_FAILED(kcdb_identity_get_config(ident, KHM_FLAG_CREATE,
- &csp_ident)))
- goto done_apply;
-
- if (KHM_FAILED(khc_open_space(csp_ident, CSNAME_KRB4CRED,
- KHM_FLAG_CREATE | KCONF_FLAG_WRITEIFMOD,
- &csp_idk4)))
- goto done_apply;
-
- khc_write_int32(csp_idk4, L"Krb4NewCreds", gettix);
-
- applied = TRUE;
-
- done_apply:
- if (ident)
- kcdb_identity_release(ident);
-
- if (csp_ident)
- khc_close_space(csp_ident);
-
- if (csp_idk4)
- khc_close_space(csp_idk4);
-
- return applied;
-}
-
-INT_PTR CALLBACK
-krb4_id_config_proc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam) {
- switch(uMsg) {
- case WM_INITDIALOG:
- {
- k4_id_data * d;
-
- d = PMALLOC(sizeof(k4_id_data));
-
- if (!d)
- break;
-
- ZeroMemory(d, sizeof(*d));
-
- d->cfg = *((khui_config_init_data *) lParam);
-
-#pragma warning(push)
-#pragma warning(disable: 4244)
- SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) d);
-#pragma warning(pop)
-
- k4_id_read_params(d);
-
- CheckDlgButton(hwnd, IDC_CFG_GETTIX,
- (d->gettix)?BST_CHECKED: BST_UNCHECKED);
- EnableWindow(GetDlgItem(hwnd, IDC_CFG_GETTIX),
- d->is_default_ident);
-
- }
- break;
-
- case WM_COMMAND:
- {
- k4_id_data * d;
-
- d = (k4_id_data *) (LONG_PTR)
- GetWindowLongPtr(hwnd, DWLP_USER);
-
- if (wParam == MAKEWPARAM(IDC_CFG_GETTIX,
- BN_CLICKED)) {
- int gettix = 0;
- int modified = 0;
-
- gettix = (IsDlgButtonChecked(hwnd, IDC_CFG_GETTIX) ==
- BST_CHECKED);
-
- modified = (!!gettix != !!d->gettix);
-
- khui_cfg_set_flags_inst(&d->cfg,
- ((modified)?KHUI_CNFLAG_MODIFIED: 0),
- KHUI_CNFLAG_MODIFIED);
- }
- }
- break;
-
- case KHUI_WM_CFG_NOTIFY:
- {
- k4_id_data * d;
-
- d = (k4_id_data *) (LONG_PTR)
- GetWindowLongPtr(hwnd, DWLP_USER);
-
- if (!d)
- break;
-
- if (HIWORD(wParam) == WMCFG_APPLY) {
- khm_int32 applied;
-
- applied = k4_id_write_params(hwnd, d);
-
- khui_cfg_set_flags_inst(&d->cfg,
- ((applied)? KHUI_CNFLAG_APPLIED: 0),
- (KHUI_CNFLAG_APPLIED | KHUI_CNFLAG_MODIFIED));
- }
- }
- break;
-
- case WM_DESTROY:
- {
- k4_id_data * d;
-
- d = (k4_id_data *) (LONG_PTR)
- GetWindowLongPtr(hwnd, DWLP_USER);
-
- if (!d)
- break;
-
- PFREE(d);
- }
- break;
- }
-
- return FALSE;
-}
-
-typedef struct tag_k4_config_dlg_data {
- khui_config_node node;
- char krb_path[MAX_PATH];
- char krbrealm_path[MAX_PATH];
- char tkt_string[MAX_PATH];
-} k4_config_dlg_data;
-
-INT_PTR CALLBACK
-krb4_confg_proc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam) {
-
- static BOOL in_init = FALSE;
- k4_config_dlg_data * d;
-
- switch(uMsg) {
- case WM_INITDIALOG:
- {
- wchar_t wbuf[MAX_PATH];
- CHAR krb_path[MAX_PATH];
- CHAR krbrealm_path[MAX_PATH];
- CHAR ticketName[MAX_PATH];
- char * pticketName;
- unsigned int krb_path_sz = sizeof(krb_path);
- unsigned int krbrealm_path_sz = sizeof(krbrealm_path);
- khm_size cbsize;
-
- d = PMALLOC(sizeof(*d));
- ZeroMemory(d, sizeof(*d));
-
-#pragma warning(push)
-#pragma warning(disable: 4244)
- SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) d);
-#pragma warning(pop)
-
- d->node = (khui_config_node) lParam;
-
- in_init = TRUE;
-
- // Set KRB.CON
- memset(krb_path, '\0', sizeof(krb_path));
- if (!pkrb_get_krbconf2(krb_path, &krb_path_sz)) {
- // Error has happened
- } else { // normal find
- AnsiStrToUnicode(wbuf, sizeof(wbuf), krb_path);
- SetDlgItemText(hwnd, IDC_CFG_CFGPATH, wbuf);
- StringCbCopyA(d->krb_path, sizeof(d->krb_path), krb_path);
- }
-
- // Set KRBREALM.CON
- memset(krbrealm_path, '\0', sizeof(krbrealm_path));
- if (!pkrb_get_krbrealm2(krbrealm_path, &krbrealm_path_sz)) {
- // Error has happened
- } else {
- AnsiStrToUnicode(wbuf, sizeof(wbuf), krbrealm_path);
- SetDlgItemText(hwnd, IDC_CFG_RLMPATH, wbuf);
- StringCbCopyA(d->krbrealm_path, sizeof(d->krbrealm_path),
- krbrealm_path);
- }
-
- cbsize = sizeof(wbuf);
- if (KHM_SUCCEEDED(khc_read_string(csp_params, L"TktString",
- wbuf, &cbsize)) &&
- wbuf[0] != L'\0') {
-
- UnicodeStrToAnsi(ticketName, sizeof(ticketName), wbuf);
-
- } else {
-
- // Set TICKET.KRB file Editbox
- *ticketName = 0;
- pkrb_set_tkt_string(0);
-
- pticketName = ptkt_string();
- if (pticketName)
- StringCbCopyA(ticketName, sizeof(ticketName), pticketName);
-
- }
-
- if (!*ticketName) {
- // error
- } else {
- AnsiStrToUnicode(wbuf, sizeof(wbuf), ticketName);
- SetDlgItemText(hwnd, IDC_CFG_CACHE, wbuf);
- StringCbCopyA(d->tkt_string, sizeof(d->tkt_string),
- ticketName);
- }
-
- in_init = FALSE;
-
- }
- break;
-
- case WM_COMMAND:
- if (MAKEWPARAM(IDC_CFG_CACHE, EN_CHANGE)) {
- char tkt_string[MAX_PATH];
- wchar_t wtkt_string[MAX_PATH];
-
- if (in_init) {
- return TRUE;
- }
-
- d = (k4_config_dlg_data *) (LONG_PTR)
- GetWindowLongPtr(hwnd, DWLP_USER);
-
- if (d == NULL)
- return TRUE;
-
- tkt_string[0] = 0;
- wtkt_string[0] = 0;
-
- GetDlgItemText(hwnd, IDC_CFG_CACHE,
- wtkt_string, ARRAYLENGTH(wtkt_string));
- UnicodeStrToAnsi(tkt_string, sizeof(tkt_string),
- wtkt_string);
-
- if (_stricmp(tkt_string, d->tkt_string)) {
- khui_cfg_set_flags(d->node,
- KHUI_CNFLAG_MODIFIED,
- KHUI_CNFLAG_MODIFIED);
- } else {
- khui_cfg_set_flags(d->node,
- 0,
- KHUI_CNFLAG_MODIFIED);
- }
-
- return TRUE;
- }
- break;
-
- case KHUI_WM_CFG_NOTIFY:
- if (HIWORD(wParam) == WMCFG_APPLY) {
- wchar_t wtkt_string[MAX_PATH];
- char tkt_string[MAX_PATH];
- int t;
-
- d = (k4_config_dlg_data *) (LONG_PTR)
- GetWindowLongPtr(hwnd, DWLP_USER);
-
- if (d == NULL)
- return TRUE;
-
- t = GetDlgItemText(hwnd, IDC_CFG_CACHE,
- wtkt_string, ARRAYLENGTH(wtkt_string));
- if (t == 0)
- return TRUE;
-
- UnicodeStrToAnsi(tkt_string, sizeof(tkt_string), wtkt_string);
-
- if (_stricmp(tkt_string, d->tkt_string)) {
-
- pkrb_set_tkt_string(tkt_string);
-
- khc_write_string(csp_params, L"TktString", wtkt_string);
-
- khui_cfg_set_flags(d->node,
- KHUI_CNFLAG_APPLIED,
- KHUI_CNFLAG_APPLIED |
- KHUI_CNFLAG_MODIFIED);
- khm_krb4_list_tickets();
- } else {
- khui_cfg_set_flags(d->node,
- 0,
- KHUI_CNFLAG_MODIFIED);
- }
-
- return TRUE;
- }
- break;
-
- case WM_DESTROY:
- d = (k4_config_dlg_data *) (LONG_PTR)
- GetWindowLongPtr(hwnd, DWLP_USER);
-
- if (d) {
- PFREE(d);
- }
-
- break;
- }
- return FALSE;
-}
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<krbcred.h>
+#include<kherror.h>
+#include<khuidefs.h>
+#include<strsafe.h>
+#include<assert.h>
+
+typedef struct tag_k4_ids_data {
+ khui_config_init_data cfg;
+
+ khm_int32 get_tix;
+} k4_ids_data;
+
+static void
+k4_ids_read_params(k4_ids_data * d) {
+ khm_int32 t;
+#ifdef DEBUG
+ assert(csp_params);
+#endif
+
+ t = 1;
+ khc_read_int32(csp_params, L"Krb4NewCreds", &t);
+ d->get_tix = !!t;
+}
+
+static void
+k4_ids_write_params(HWND hw, k4_ids_data * d) {
+ khm_int32 nv;
+ khm_boolean applied = FALSE;
+
+ if (IsDlgButtonChecked(hw, IDC_CFG_GETTIX) == BST_CHECKED)
+ nv = TRUE;
+ else
+ nv = FALSE;
+
+ if (!!nv != !!d->get_tix) {
+ d->get_tix = !!nv;
+ khc_write_int32(csp_params, L"Krb4NewCreds", d->get_tix);
+ applied = TRUE;
+ }
+
+ khui_cfg_set_flags_inst(&d->cfg,
+ (applied)?KHUI_CNFLAG_APPLIED:0,
+ KHUI_CNFLAG_APPLIED | KHUI_CNFLAG_MODIFIED);
+}
+
+static void
+k4_ids_check_mod(HWND hw, k4_ids_data * d) {
+ khm_int32 nv;
+
+ if (IsDlgButtonChecked(hw, IDC_CFG_GETTIX) == BST_CHECKED)
+ nv = TRUE;
+ else
+ nv = FALSE;
+
+ khui_cfg_set_flags_inst(&d->cfg,
+ (!!nv != !!d->get_tix)? KHUI_CNFLAG_MODIFIED: 0,
+ KHUI_CNFLAG_MODIFIED);
+}
+
+INT_PTR CALLBACK
+krb4_ids_config_proc(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam) {
+ k4_ids_data * d;
+
+ switch(uMsg) {
+ case WM_INITDIALOG:
+ d = PMALLOC(sizeof(*d));
+ ZeroMemory(d, sizeof(*d));
+
+ d->cfg = *((khui_config_init_data *) lParam);
+
+#pragma warning(push)
+#pragma warning(disable: 4244)
+ SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) d);
+#pragma warning(pop)
+
+ k4_ids_read_params(d);
+
+ CheckDlgButton(hwnd, IDC_CFG_GETTIX,
+ (d->get_tix)? BST_CHECKED: BST_UNCHECKED);
+
+ break;
+
+ case WM_COMMAND:
+ d = (k4_ids_data *) (LONG_PTR)
+ GetWindowLongPtr(hwnd, DWLP_USER);
+
+ if (HIWORD(wParam) == BN_CLICKED) {
+ k4_ids_check_mod(hwnd, d);
+ }
+ break;
+
+ case KHUI_WM_CFG_NOTIFY:
+ d = (k4_ids_data *) (LONG_PTR)
+ GetWindowLongPtr(hwnd, DWLP_USER);
+
+ if (HIWORD(wParam) == WMCFG_APPLY) {
+ k4_ids_write_params(hwnd, d);
+ }
+ break;
+
+ case WM_DESTROY:
+ d = (k4_ids_data *) (LONG_PTR)
+ GetWindowLongPtr(hwnd, DWLP_USER);
+
+ PFREE(d);
+ break;
+ }
+
+ return FALSE;
+}
+
+typedef struct tag_k4_id_data {
+ khui_config_init_data cfg;
+ khm_int32 gettix; /* get tickets? */
+ khm_boolean is_default_ident;
+} k4_id_data;
+
+void
+k4_id_read_params(k4_id_data * d) {
+ wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
+ khm_size cb;
+ khm_handle ident = NULL;
+ khm_handle csp_ident = NULL;
+ khm_handle csp_idk4 = NULL;
+ khm_int32 flags = 0;
+ khm_int32 t;
+
+ khc_read_int32(csp_params, L"Krb4NewCreds", &d->gettix);
+
+ *idname = 0;
+ cb = sizeof(idname);
+ khui_cfg_get_name(d->cfg.ctx_node, idname, &cb);
+
+ kcdb_identity_create(idname, 0, &ident);
+
+ if (ident == NULL) {
+ d->gettix = 0;
+ goto done;
+ }
+
+ kcdb_identity_get_flags(ident, &flags);
+
+ if (!(flags & KCDB_IDENT_FLAG_DEFAULT)) {
+ d->gettix = 0;
+ goto done;
+ }
+
+ d->is_default_ident = TRUE;
+
+ if (d->gettix == 0)
+ goto done;
+
+ if (KHM_FAILED(kcdb_identity_get_config(ident, 0, &csp_ident)))
+ goto done;
+
+ if (KHM_FAILED(khc_open_space(csp_ident, CSNAME_KRB4CRED,
+ 0, &csp_idk4)))
+ goto close_config;
+
+ if (KHM_SUCCEEDED(khc_read_int32(csp_idk4, L"Krb4NewCreds", &t)) &&
+ !t)
+ d->gettix = 1;
+
+ close_config:
+ if (csp_ident)
+ khc_close_space(csp_ident);
+
+ if (csp_idk4)
+ khc_close_space(csp_idk4);
+
+ done:
+ if (ident)
+ kcdb_identity_release(ident);
+
+ return;
+}
+
+khm_boolean
+k4_id_write_params(HWND hwnd, k4_id_data * d) {
+ wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
+ khm_size cb_idname = sizeof(idname);
+ khm_handle ident = NULL;
+ khm_int32 flags = 0;
+ khm_handle csp_ident = NULL;
+ khm_handle csp_idk4 = NULL;
+ khm_int32 gettix = 0;
+ khm_boolean applied = FALSE;
+
+ khui_cfg_get_name(d->cfg.ctx_node, idname, &cb_idname);
+
+ kcdb_identity_create(idname, 0, &ident);
+
+ if (ident == NULL)
+ return FALSE;
+
+ kcdb_identity_get_flags(ident, &flags);
+
+ if (!(flags & KCDB_IDENT_FLAG_DEFAULT))
+ goto done_apply;
+
+ if (IsDlgButtonChecked(hwnd, IDC_CFG_GETTIX) == BST_CHECKED)
+ gettix = TRUE;
+
+ if (KHM_FAILED(kcdb_identity_get_config(ident, KHM_FLAG_CREATE,
+ &csp_ident)))
+ goto done_apply;
+
+ if (KHM_FAILED(khc_open_space(csp_ident, CSNAME_KRB4CRED,
+ KHM_FLAG_CREATE | KCONF_FLAG_WRITEIFMOD,
+ &csp_idk4)))
+ goto done_apply;
+
+ khc_write_int32(csp_idk4, L"Krb4NewCreds", gettix);
+
+ applied = TRUE;
+
+ done_apply:
+ if (ident)
+ kcdb_identity_release(ident);
+
+ if (csp_ident)
+ khc_close_space(csp_ident);
+
+ if (csp_idk4)
+ khc_close_space(csp_idk4);
+
+ return applied;
+}
+
+INT_PTR CALLBACK
+krb4_id_config_proc(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam) {
+ switch(uMsg) {
+ case WM_INITDIALOG:
+ {
+ k4_id_data * d;
+
+ d = PMALLOC(sizeof(k4_id_data));
+
+ if (!d)
+ break;
+
+ ZeroMemory(d, sizeof(*d));
+
+ d->cfg = *((khui_config_init_data *) lParam);
+
+#pragma warning(push)
+#pragma warning(disable: 4244)
+ SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) d);
+#pragma warning(pop)
+
+ k4_id_read_params(d);
+
+ CheckDlgButton(hwnd, IDC_CFG_GETTIX,
+ (d->gettix)?BST_CHECKED: BST_UNCHECKED);
+ EnableWindow(GetDlgItem(hwnd, IDC_CFG_GETTIX),
+ d->is_default_ident);
+
+ }
+ break;
+
+ case WM_COMMAND:
+ {
+ k4_id_data * d;
+
+ d = (k4_id_data *) (LONG_PTR)
+ GetWindowLongPtr(hwnd, DWLP_USER);
+
+ if (wParam == MAKEWPARAM(IDC_CFG_GETTIX,
+ BN_CLICKED)) {
+ int gettix = 0;
+ int modified = 0;
+
+ gettix = (IsDlgButtonChecked(hwnd, IDC_CFG_GETTIX) ==
+ BST_CHECKED);
+
+ modified = (!!gettix != !!d->gettix);
+
+ khui_cfg_set_flags_inst(&d->cfg,
+ ((modified)?KHUI_CNFLAG_MODIFIED: 0),
+ KHUI_CNFLAG_MODIFIED);
+ }
+ }
+ break;
+
+ case KHUI_WM_CFG_NOTIFY:
+ {
+ k4_id_data * d;
+
+ d = (k4_id_data *) (LONG_PTR)
+ GetWindowLongPtr(hwnd, DWLP_USER);
+
+ if (!d)
+ break;
+
+ if (HIWORD(wParam) == WMCFG_APPLY) {
+ khm_int32 applied;
+
+ applied = k4_id_write_params(hwnd, d);
+
+ khui_cfg_set_flags_inst(&d->cfg,
+ ((applied)? KHUI_CNFLAG_APPLIED: 0),
+ (KHUI_CNFLAG_APPLIED | KHUI_CNFLAG_MODIFIED));
+ }
+ }
+ break;
+
+ case WM_DESTROY:
+ {
+ k4_id_data * d;
+
+ d = (k4_id_data *) (LONG_PTR)
+ GetWindowLongPtr(hwnd, DWLP_USER);
+
+ if (!d)
+ break;
+
+ PFREE(d);
+ }
+ break;
+ }
+
+ return FALSE;
+}
+
+typedef struct tag_k4_config_dlg_data {
+ khui_config_node node;
+ char krb_path[MAX_PATH];
+ char krbrealm_path[MAX_PATH];
+ char tkt_string[MAX_PATH];
+} k4_config_dlg_data;
+
+INT_PTR CALLBACK
+krb4_confg_proc(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam) {
+
+ static BOOL in_init = FALSE;
+ k4_config_dlg_data * d;
+
+ switch(uMsg) {
+ case WM_INITDIALOG:
+ {
+ wchar_t wbuf[MAX_PATH];
+ CHAR krb_path[MAX_PATH];
+ CHAR krbrealm_path[MAX_PATH];
+ CHAR ticketName[MAX_PATH];
+ char * pticketName;
+ unsigned int krb_path_sz = sizeof(krb_path);
+ unsigned int krbrealm_path_sz = sizeof(krbrealm_path);
+ khm_size cbsize;
+
+ d = PMALLOC(sizeof(*d));
+ ZeroMemory(d, sizeof(*d));
+
+#pragma warning(push)
+#pragma warning(disable: 4244)
+ SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) d);
+#pragma warning(pop)
+
+ d->node = (khui_config_node) lParam;
+
+ in_init = TRUE;
+
+ // Set KRB.CON
+ memset(krb_path, '\0', sizeof(krb_path));
+ if (!pkrb_get_krbconf2(krb_path, &krb_path_sz)) {
+ // Error has happened
+ } else { // normal find
+ AnsiStrToUnicode(wbuf, sizeof(wbuf), krb_path);
+ SetDlgItemText(hwnd, IDC_CFG_CFGPATH, wbuf);
+ StringCbCopyA(d->krb_path, sizeof(d->krb_path), krb_path);
+ }
+
+ // Set KRBREALM.CON
+ memset(krbrealm_path, '\0', sizeof(krbrealm_path));
+ if (!pkrb_get_krbrealm2(krbrealm_path, &krbrealm_path_sz)) {
+ // Error has happened
+ } else {
+ AnsiStrToUnicode(wbuf, sizeof(wbuf), krbrealm_path);
+ SetDlgItemText(hwnd, IDC_CFG_RLMPATH, wbuf);
+ StringCbCopyA(d->krbrealm_path, sizeof(d->krbrealm_path),
+ krbrealm_path);
+ }
+
+ cbsize = sizeof(wbuf);
+ if (KHM_SUCCEEDED(khc_read_string(csp_params, L"TktString",
+ wbuf, &cbsize)) &&
+ wbuf[0] != L'\0') {
+
+ UnicodeStrToAnsi(ticketName, sizeof(ticketName), wbuf);
+
+ } else {
+
+ // Set TICKET.KRB file Editbox
+ *ticketName = 0;
+ pkrb_set_tkt_string(0);
+
+ pticketName = ptkt_string();
+ if (pticketName)
+ StringCbCopyA(ticketName, sizeof(ticketName), pticketName);
+
+ }
+
+ if (!*ticketName) {
+ // error
+ } else {
+ AnsiStrToUnicode(wbuf, sizeof(wbuf), ticketName);
+ SetDlgItemText(hwnd, IDC_CFG_CACHE, wbuf);
+ StringCbCopyA(d->tkt_string, sizeof(d->tkt_string),
+ ticketName);
+ }
+
+ in_init = FALSE;
+
+ }
+ break;
+
+ case WM_COMMAND:
+ if (MAKEWPARAM(IDC_CFG_CACHE, EN_CHANGE)) {
+ char tkt_string[MAX_PATH];
+ wchar_t wtkt_string[MAX_PATH];
+
+ if (in_init) {
+ return TRUE;
+ }
+
+ d = (k4_config_dlg_data *) (LONG_PTR)
+ GetWindowLongPtr(hwnd, DWLP_USER);
+
+ if (d == NULL)
+ return TRUE;
+
+ tkt_string[0] = 0;
+ wtkt_string[0] = 0;
+
+ GetDlgItemText(hwnd, IDC_CFG_CACHE,
+ wtkt_string, ARRAYLENGTH(wtkt_string));
+ UnicodeStrToAnsi(tkt_string, sizeof(tkt_string),
+ wtkt_string);
+
+ if (_stricmp(tkt_string, d->tkt_string)) {
+ khui_cfg_set_flags(d->node,
+ KHUI_CNFLAG_MODIFIED,
+ KHUI_CNFLAG_MODIFIED);
+ } else {
+ khui_cfg_set_flags(d->node,
+ 0,
+ KHUI_CNFLAG_MODIFIED);
+ }
+
+ return TRUE;
+ }
+ break;
+
+ case KHUI_WM_CFG_NOTIFY:
+ if (HIWORD(wParam) == WMCFG_APPLY) {
+ wchar_t wtkt_string[MAX_PATH];
+ char tkt_string[MAX_PATH];
+ int t;
+
+ d = (k4_config_dlg_data *) (LONG_PTR)
+ GetWindowLongPtr(hwnd, DWLP_USER);
+
+ if (d == NULL)
+ return TRUE;
+
+ t = GetDlgItemText(hwnd, IDC_CFG_CACHE,
+ wtkt_string, ARRAYLENGTH(wtkt_string));
+ if (t == 0)
+ return TRUE;
+
+ UnicodeStrToAnsi(tkt_string, sizeof(tkt_string), wtkt_string);
+
+ if (_stricmp(tkt_string, d->tkt_string)) {
+
+ pkrb_set_tkt_string(tkt_string);
+
+ khc_write_string(csp_params, L"TktString", wtkt_string);
+
+ khui_cfg_set_flags(d->node,
+ KHUI_CNFLAG_APPLIED,
+ KHUI_CNFLAG_APPLIED |
+ KHUI_CNFLAG_MODIFIED);
+ khm_krb4_list_tickets();
+ } else {
+ khui_cfg_set_flags(d->node,
+ 0,
+ KHUI_CNFLAG_MODIFIED);
+ }
+
+ return TRUE;
+ }
+ break;
+
+ case WM_DESTROY:
+ d = (k4_config_dlg_data *) (LONG_PTR)
+ GetWindowLongPtr(hwnd, DWLP_USER);
+
+ if (d) {
+ PFREE(d);
+ }
+
+ break;
+ }
+ return FALSE;
+}
diff --git a/src/windows/identity/plugins/krb4/krb4funcs.c b/src/windows/identity/plugins/krb4/krb4funcs.c
index b2b5fef4e7..9e9ba42d25 100644
--- a/src/windows/identity/plugins/krb4/krb4funcs.c
+++ b/src/windows/identity/plugins/krb4/krb4funcs.c
@@ -1,897 +1,897 @@
-/*
-* Copyright (c) 2005 Massachusetts Institute of Technology
-*
-* Permission is hereby granted, free of charge, to any person
-* obtaining a copy of this software and associated documentation
-* files (the "Software"), to deal in the Software without
-* restriction, including without limitation the rights to use, copy,
-* modify, merge, publish, distribute, sublicense, and/or sell copies
-* of the Software, and to permit persons to whom the Software is
-* furnished to do so, subject to the following conditions:
-*
-* The above copyright notice and this permission notice shall be
-* included in all copies or substantial portions of the Software.
-*
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
-* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
-* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-* SOFTWARE.
-*/
-
-/* $Id$ */
-
-/* Originally this was krb5routines.c in Leash sources. Subsequently
-modified and adapted for NetIDMgr */
-
-#include<krbcred.h>
-#include<kherror.h>
-
-#define SECURITY_WIN32
-#include <security.h>
-
-#include <string.h>
-#include <time.h>
-#include <assert.h>
-#include <strsafe.h>
-
-
-
-int com_addr(void)
-{
- long ipAddr;
- char loc_addr[ADDR_SZ];
- CREDENTIALS cred;
- char service[40];
- char instance[40];
- // char addr[40];
- char realm[40];
- struct in_addr LocAddr;
- int k_errno;
-
- if (pkrb_get_cred == NULL)
- return(KSUCCESS);
-
- k_errno = (*pkrb_get_cred)(service,instance,realm,&cred);
- if (k_errno)
- return KRBERR(k_errno);
-
- while(1) {
- ipAddr = (*pLocalHostAddr)();
- LocAddr.s_addr = ipAddr;
- StringCbCopyA(loc_addr, sizeof(loc_addr), inet_ntoa(LocAddr));
- if ( strcmp(cred.address,loc_addr) != 0) {
- /* TODO: do something about this */
- //Leash_kdestroy ();
- break;
- }
- break;
- } // while()
- return 0;
-}
-
-
-long
-khm_krb4_list_tickets(void)
-{
- char ptktname[MAX_PATH + 5];
- char pname[ANAME_SZ];
- char pinst[INST_SZ];
- char prealm[REALM_SZ];
- wchar_t wbuf[256];
- int k_errno = 0;
- CREDENTIALS c;
- int newtickets = 0;
- int open = 0;
- khm_handle ident = NULL;
- khm_handle cred = NULL;
- time_t tt;
- FILETIME ft;
-
- kcdb_credset_flush(krb4_credset);
-
- // Since krb_get_tf_realm will return a ticket_file error,
- // we will call tf_init and tf_close first to filter out
- // things like no ticket file. Otherwise, the error that
- // the user would see would be
- // klist: can't find realm of ticket file: No ticket file (tf_util)
- // instead of klist: No ticket file (tf_util)
- if (ptf_init == NULL)
- goto collect;
-
- com_addr();
-
- // Open ticket file
- if ((k_errno = (*ptf_init)((*ptkt_string)(), R_TKT_FIL)))
- {
- goto cleanup;
- }
- // Close ticket file
- (void) (*ptf_close)();
-
- // We must find the realm of the ticket file here before calling
- // tf_init because since the realm of the ticket file is not
- // really stored in the principal section of the file, the
- // routine we use must itself call tf_init and tf_close.
-
- if ((k_errno = (*pkrb_get_tf_realm)((*ptkt_string)(), prealm)) != KSUCCESS)
- {
- goto cleanup;
- }
-
- // Open ticket file
- if (k_errno = (*ptf_init)((*ptkt_string)(), R_TKT_FIL))
- {
- goto cleanup;
- }
-
- StringCchCopyA(ptktname, ARRAYLENGTH(ptktname), (*ptkt_string)());
-
- open = 1;
-
- // Get principal name and instance
- if ((k_errno = (*ptf_get_pname)(pname)) || (k_errno = (*ptf_get_pinst)(pinst)))
- {
- goto cleanup;
- }
-
- // You may think that this is the obvious place to get the
- // realm of the ticket file, but it can't be done here as the
- // routine to do this must open the ticket file. This is why
- // it was done before tf_init.
- StringCbPrintf(wbuf, sizeof(wbuf), L"%S%S%S%S%S", (LPSTR)pname,
- (LPSTR)(pinst[0] ? "." : ""), (LPSTR)pinst,
- (LPSTR)(prealm[0] ? "@" : ""), (LPSTR)prealm);
-
- if(KHM_FAILED(kcdb_identity_create(wbuf, KCDB_IDENT_FLAG_CREATE, &ident)))
- {
- goto cleanup;
- }
-
- // Get KRB4 tickets
- while ((k_errno = (*ptf_get_cred)(&c)) == KSUCCESS)
- {
- StringCbPrintf(wbuf, sizeof(wbuf), L"%S%S%S%S%S",
- c.service,
- (c.instance[0] ? "." : ""),
- c.instance,
- (c.realm[0] ? "@" : ""),
- c.realm);
-
- if(KHM_FAILED(kcdb_cred_create(wbuf, ident, credtype_id_krb4, &cred)))
- continue;
-
- tt = c.issue_date + c.lifetime * 5L * 60L;
- TimetToFileTime(tt, &ft);
- kcdb_cred_set_attr(cred, KCDB_ATTR_EXPIRE, &ft, sizeof(ft));
-
- tt = c.issue_date;
- TimetToFileTime(tt, &ft);
- kcdb_cred_set_attr(cred, KCDB_ATTR_ISSUE, &ft, sizeof(ft));
-
- tt = c.lifetime * 5L * 60L;
- TimetToFileTimeInterval(tt, &ft);
- kcdb_cred_set_attr(cred, KCDB_ATTR_LIFETIME, &ft, sizeof(ft));
-
- AnsiStrToUnicode(wbuf, sizeof(wbuf), ptktname);
- kcdb_cred_set_attr(cred, KCDB_ATTR_LOCATION, wbuf, KCDB_CBSIZE_AUTO);
-
- kcdb_credset_add_cred(krb4_credset, cred, -1);
-
- kcdb_cred_release(cred);
- } // while
-
- cleanup:
- if (ptf_close == NULL)
- return(KSUCCESS);
-
- if (open)
- (*ptf_close)(); //close ticket file
-
- if (k_errno == EOF)
- k_errno = 0;
-
- // XXX the if statement directly below was inserted to eliminate
- // an error NO_TKT_FIL on Leash startup. The error occurs from an
- // error number thrown from krb_get_tf_realm. We believe this
- // change does not eliminate other errors, but it may.
-
- if (k_errno == NO_TKT_FIL)
- k_errno = 0;
-
- if(ident)
- kcdb_identity_release(ident);
-
-#if 0
- /*TODO: Handle errors here */
- if (k_errno)
- {
- CHAR message[256];
- CHAR errBuf[256];
- LPCSTR errText;
-
- if (!Lerror_message)
- return -1;
-
- errText = err_describe(errBuf, KRBERR(k_errno));
-
- sprintf(message, "%s\n\n%s failed", errText, functionName);
- MessageBox(NULL, message, "Kerberos Four",
- MB_OK | MB_ICONERROR | MB_TASKMODAL | MB_SETFOREGROUND);
- }
-#endif
-
- collect:
- kcdb_credset_collect(NULL, krb4_credset, ident, credtype_id_krb4, NULL);
-
- return k_errno;
-}
-
-#define KRB_FILE "KRB.CON"
-#define KRBREALM_FILE "KRBREALM.CON"
-#define KRB5_FILE "KRB5.INI"
-
-BOOL
-khm_krb5_get_profile_file(LPSTR confname, UINT szConfname)
-{
- char **configFile = NULL;
- if (pkrb5_get_default_config_files(&configFile))
- {
- GetWindowsDirectoryA(confname,szConfname);
- confname[szConfname-1] = '\0';
-
- StringCchCatA(confname, szConfname, "\\");
- StringCchCatA(confname, szConfname, KRB5_FILE);
-
- return FALSE;
- }
-
- *confname = 0;
-
- if (configFile)
- {
- StringCchCopyA(confname, szConfname, *configFile);
- pkrb5_free_config_files(configFile);
- }
-
- if (!*confname)
- {
- GetWindowsDirectoryA(confname,szConfname);
- confname[szConfname-1] = '\0';
-
- StringCchCatA(confname, szConfname, "\\");
- StringCchCatA(confname, szConfname, KRB5_FILE);
- }
-
- return FALSE;
-}
-
-BOOL
-khm_get_krb4_con_file(LPSTR confname, UINT szConfname)
-{
- if (hKrb5 && !hKrb4) {
- // hold krb.con where krb5.ini is located
- CHAR krbConFile[MAX_PATH]="";
- LPSTR pFind;
-
- if (khm_krb5_get_profile_file(krbConFile, sizeof(krbConFile))) {
- GetWindowsDirectoryA(krbConFile,sizeof(krbConFile));
- krbConFile[MAX_PATH-1] = '\0';
-
- StringCbCatA(krbConFile, sizeof(krbConFile), "\\");
- }
-
- pFind = strrchr(krbConFile, '\\');
-
- if (pFind) {
- *pFind = '\0';
-
- StringCbCatA(krbConFile, sizeof(krbConFile), "\\");
- StringCbCatA(krbConFile, sizeof(krbConFile), KRB_FILE);
- } else {
- krbConFile[0] = '\0';
- }
-
- StringCchCopyA(confname, szConfname, krbConFile);
- } else if (hKrb4) {
- unsigned int size = szConfname;
- memset(confname, '\0', szConfname);
- if (!pkrb_get_krbconf2(confname, &size)) {
- GetWindowsDirectoryA(confname,szConfname);
- confname[szConfname-1] = '\0';
- StringCchCatA(confname, szConfname, "\\");
- StringCchCatA(confname, szConfname, KRB_FILE);
- }
- }
-
- return FALSE;
-}
-
-int
-readstring(FILE * file, char * buf, int len)
-{
- int c,i;
- memset(buf, '\0', sizeof(buf));
- for (i=0, c=fgetc(file); c != EOF ; c=fgetc(file), i++)
- {
- if (i < sizeof(buf)) {
- if (c == '\n') {
- buf[i] = '\0';
- return i;
- } else {
- buf[i] = c;
- }
- } else {
- if (c == '\n') {
- buf[len-1] = '\0';
- return(i);
- }
- }
- }
- if (c == EOF) {
- if (i > 0 && i < len) {
- buf[i] = '\0';
- return(i);
- } else {
- buf[len-1] = '\0';
- return(-1);
- }
- }
- return(-1);
-}
-
-/*! \internal
- \brief Return a list of configured realms
-
- The string that is returned is a set of null terminated unicode strings,
- each of which denotes one realm. The set is terminated by a zero length
- null terminated string.
-
- The caller should free the returned string using free()
-
- \return The string with the list of realms or NULL if the operation fails.
-*/
-wchar_t * khm_krb5_get_realm_list(void)
-{
- wchar_t * rlist = NULL;
-
- if (pprofile_get_subsection_names && pprofile_free_list) {
- const char* rootSection[] = {"realms", NULL};
- const char** rootsec = rootSection;
- char **sections = NULL, **cpp = NULL, *value = NULL;
-
- char krb5_conf[MAX_PATH+1];
-
- if (!khm_krb5_get_profile_file(krb5_conf,sizeof(krb5_conf))) {
- profile_t profile;
- long retval;
- const char *filenames[2];
- wchar_t * d;
- size_t cbsize;
- size_t t;
-
- filenames[0] = krb5_conf;
- filenames[1] = NULL;
- retval = pprofile_init(filenames, &profile);
- if (!retval) {
- retval = pprofile_get_subsection_names(profile, rootsec, &sections);
-
- if (!retval)
- {
- /* first figure out how much space to allocate */
- cbsize = 0;
- for (cpp = sections; *cpp; cpp++)
- {
- cbsize += sizeof(wchar_t) * (strlen(*cpp) + 1);
- }
- cbsize += sizeof(wchar_t); /* double null terminated */
-
- rlist = PMALLOC(cbsize);
- d = rlist;
- for (cpp = sections; *cpp; cpp++)
- {
- AnsiStrToUnicode(d, cbsize, *cpp);
- t = wcslen(d) + 1;
- d += t;
- cbsize -= sizeof(wchar_t) * t;
- }
- *d = L'\0';
- }
-
- pprofile_free_list(sections);
-
-#if 0
- retval = pprofile_get_string(profile, "libdefaults","noaddresses", 0, "true", &value);
- if ( value ) {
- disable_noaddresses = config_boolean_to_int(value);
- pprofile_release_string(value);
- }
-#endif
- pprofile_release(profile);
- }
- }
- } else {
- FILE * file;
- char krb_conf[MAX_PATH+1];
- char * p;
- size_t cbsize, t;
- wchar_t * d;
-
- if (!khm_get_krb4_con_file(krb_conf,sizeof(krb_conf)) &&
-#if _MSC_VER >= 1400
- !fopen_s(&file, krb_conf, "rt")
-#else
- (file = fopen(krb_conf, "rt"))
-#endif
- )
- {
- char lineBuf[256];
-
- /*TODO: compute the actual required buffer size instead of hardcoding */
- cbsize = 16384; // arbitrary
- rlist = PMALLOC(cbsize);
- d = rlist;
-
- // Skip the default realm
- readstring(file,lineBuf,sizeof(lineBuf));
-
- // Read the defined realms
- while (TRUE)
- {
- if (readstring(file,lineBuf,sizeof(lineBuf)) < 0)
- break;
-
- if (*(lineBuf + strlen(lineBuf) - 1) == '\r')
- *(lineBuf + strlen(lineBuf) - 1) = 0;
-
- for (p=lineBuf; *p ; p++)
- {
- if (isspace(*p)) {
- *p = 0;
- break;
- }
- }
-
- if ( strncmp(".KERBEROS.OPTION.",lineBuf,17) ) {
- t = strlen(lineBuf) + 1;
- if(cbsize > (1 + t*sizeof(wchar_t))) {
- AnsiStrToUnicode(d, cbsize, lineBuf);
- d += t;
- cbsize -= t * sizeof(wchar_t);
- } else
- break;
- }
- }
-
- *d = L'\0';
-
- fclose(file);
- }
- }
-
- return rlist;
-}
-
-/*! \internal
- \brief Get the default realm
-
- A string will be returned that specifies the default realm. The caller
- should free the string using free().
-
- Returns NULL if the operation fails.
-*/
-wchar_t * khm_krb5_get_default_realm(void)
-{
- wchar_t * realm;
- size_t cch;
- krb5_context ctx=0;
- char * def = 0;
-
- pkrb5_init_context(&ctx);
- pkrb5_get_default_realm(ctx,&def);
-
- if (def) {
- cch = strlen(def) + 1;
- realm = PMALLOC(sizeof(wchar_t) * cch);
- AnsiStrToUnicode(realm, sizeof(wchar_t) * cch, def);
- pkrb5_free_default_realm(ctx, def);
- } else
- realm = NULL;
-
- pkrb5_free_context(ctx);
-
- return realm;
-}
-
-static
-char *
-make_postfix(const char * base,
- const char * postfix,
- char ** rcopy)
-{
- size_t base_size;
- size_t ret_size;
- char * copy = 0;
- char * ret = 0;
- size_t t;
-
- if (FAILED(StringCbLengthA(base, STRSAFE_MAX_CCH * sizeof(char), &t)))
- goto cleanup;
-
- base_size = t + 1;
-
- if (FAILED(StringCbLengthA(postfix, STRSAFE_MAX_CCH * sizeof(char), &t)))
- goto cleanup;
-
- ret_size = base_size + t + 1;
-
- copy = malloc(base_size);
- ret = malloc(ret_size);
-
- if (!copy || !ret)
- goto cleanup;
-
- StringCbCopyNA(copy, base_size, base, base_size);
- StringCbCopyNA(ret, ret_size, base, base_size);
- StringCbCopyNA(ret + (base_size - 1), ret_size - (base_size - 1),
- postfix, ret_size - (base_size - 1));
-
- cleanup:
- if (!copy || !ret) {
- if (copy)
- free(copy);
- if (ret)
- free(ret);
- copy = ret = 0;
- }
- // INVARIANT: (ret ==> copy) && (copy ==> ret)
- *rcopy = copy;
- return ret;
-}
-
-void
-khm_krb4_set_def_tkt_string(void) {
- wchar_t wtkt_string[MAX_PATH];
- char tkt_string[MAX_PATH];
- khm_size cb;
-
- cb = sizeof(wtkt_string);
-
- if (KHM_FAILED(khc_read_string(csp_params, L"TktString",
- wtkt_string, &cb)) ||
- wtkt_string[0] == L'\0') {
-
- pkrb_set_tkt_string(0);
-
- } else {
-
- UnicodeStrToAnsi(tkt_string, sizeof(tkt_string),
- wtkt_string);
- pkrb_set_tkt_string(tkt_string);
- }
-}
-
-
-static
-long
-make_temp_cache_v4(const char * postfix)
-{
- static char * old_cache = 0;
-
- if (!pkrb_set_tkt_string || !ptkt_string || !pdest_tkt)
- return 0; // XXX - is this appropriate?
-
- if (old_cache) {
- pdest_tkt();
- pkrb_set_tkt_string(old_cache);
- free(old_cache);
- old_cache = 0;
- }
-
- if (postfix)
- {
- char * tmp_cache = make_postfix(ptkt_string(), postfix, &old_cache);
-
- if (!tmp_cache)
- return KFAILURE;
-
- pkrb_set_tkt_string(tmp_cache);
- free(tmp_cache);
- }
- return 0;
-}
-
-long
-khm_krb4_changepwd(char * principal,
- char * password,
- char * newpassword,
- char** error_str)
-{
- long k_errno;
-
- if (!pkrb_set_tkt_string || !ptkt_string || !pkadm_change_your_password ||
- !pdest_tkt)
- return KFAILURE;
-
- k_errno = make_temp_cache_v4("_chgpwd");
- if (k_errno) return k_errno;
- k_errno = pkadm_change_your_password(principal, password, newpassword,
- error_str);
- make_temp_cache_v4(0);
- return k_errno;
-}
-
-struct tgt_filter_data {
- khm_handle identity;
- wchar_t realm[KCDB_IDENT_MAXCCH_NAME];
-};
-
-khm_int32 KHMAPI
-krb4_tgt_filter(khm_handle cred, khm_int32 flags, void * rock) {
- struct tgt_filter_data * pdata;
- wchar_t credname[KCDB_MAXCCH_NAME];
- wchar_t * t;
- khm_size cb;
- khm_int32 ctype;
-
- pdata = (struct tgt_filter_data *) rock;
- cb = sizeof(credname);
-
- if (KHM_FAILED(kcdb_cred_get_type(cred, &ctype)) ||
- ctype != credtype_id_krb4)
- return 0;
-
- if (KHM_FAILED(kcdb_cred_get_name(cred, credname, &cb)))
- return 0;
-
- if (wcsncmp(credname, L"krbtgt.", 7))
- return 0;
-
- t = wcsrchr(credname, L'@');
- if (t == NULL)
- return 0;
-
- if (wcscmp(t+1, pdata->realm))
- return 0;
-
- return 1;
-}
-
-khm_handle
-khm_krb4_find_tgt(khm_handle credset, khm_handle identity) {
- khm_handle result = NULL;
- wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
- wchar_t * t;
- khm_size cb;
- struct tgt_filter_data filter_data;
-
- cb = sizeof(idname);
-
- if (KHM_FAILED(kcdb_identity_get_name(identity,
- idname,
- &cb)))
- return NULL;
-
- t = wcsrchr(idname, L'@');
- if (t == NULL)
- return NULL;
-
- StringCbCopy(filter_data.realm, sizeof(filter_data.realm),
- t + 1);
- filter_data.identity = identity;
-
- if (KHM_FAILED(kcdb_credset_find_filtered(credset,
- -1,
- krb4_tgt_filter,
- &filter_data,
- &result,
- NULL)))
- return NULL;
- else
- return result;
-}
-
-long
-khm_convert524(khm_handle identity)
-{
-#ifdef NO_KRB5
- return(0);
-#else
- krb5_context ctx = 0;
- krb5_error_code code = 0;
- int icode = 0;
- krb5_principal me = 0;
- krb5_principal server = 0;
- krb5_creds *v5creds = 0;
- krb5_creds increds;
- krb5_ccache cc = 0;
- CREDENTIALS * v4creds = NULL;
- static int init_ets = 1;
-
- if (!pkrb5_init_context ||
- !pkrb_in_tkt ||
- !pkrb524_init_ets ||
- !pkrb524_convert_creds_kdc)
- return 0;
-
- v4creds = (CREDENTIALS *) malloc(sizeof(CREDENTIALS));
- memset((char *) v4creds, 0, sizeof(CREDENTIALS));
-
- memset((char *) &increds, 0, sizeof(increds));
- /*
- From this point on, we can goto cleanup because increds is
- initialized.
- */
-
- code = khm_krb5_initialize(identity, &ctx, &cc);
- if (code)
- goto cleanup;
-
- if ( init_ets ) {
- pkrb524_init_ets(ctx);
- init_ets = 0;
- }
-
- if (code = pkrb5_cc_get_principal(ctx, cc, &me))
- goto cleanup;
-
- if ((code = pkrb5_build_principal(ctx,
- &server,
- krb5_princ_realm(ctx, me)->length,
- krb5_princ_realm(ctx, me)->data,
- "krbtgt",
- krb5_princ_realm(ctx, me)->data,
- NULL))) {
- goto cleanup;
- }
-
- increds.client = me;
- increds.server = server;
- increds.times.endtime = 0;
- increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC;
- if ((code = pkrb5_get_credentials(ctx, 0,
- cc,
- &increds,
- &v5creds))) {
- goto cleanup;
- }
-
- if ((icode = pkrb524_convert_creds_kdc(ctx,
- v5creds,
- v4creds))) {
- goto cleanup;
- }
-
- /* initialize ticket cache */
- if ((icode = pkrb_in_tkt(v4creds->pname, v4creds->pinst, v4creds->realm)
- != KSUCCESS)) {
- goto cleanup;
- }
-
- /* stash ticket, session key, etc. for future use */
- if ((icode = pkrb_save_credentials(v4creds->service,
- v4creds->instance,
- v4creds->realm,
- v4creds->session,
- v4creds->lifetime,
- v4creds->kvno,
- &(v4creds->ticket_st),
- v4creds->issue_date))) {
- goto cleanup;
- }
-
- cleanup:
- memset(v4creds, 0, sizeof(v4creds));
- free(v4creds);
-
- if (v5creds) {
- pkrb5_free_creds(ctx, v5creds);
- }
- if (increds.client == me)
- me = 0;
- if (increds.server == server)
- server = 0;
-
- if (ctx)
- pkrb5_free_cred_contents(ctx, &increds);
-
- if (server) {
- pkrb5_free_principal(ctx, server);
- }
-
- if (me) {
- pkrb5_free_principal(ctx, me);
- }
-
- if (ctx && cc)
- pkrb5_cc_close(ctx, cc);
-
- if (ctx) {
- pkrb5_free_context(ctx);
- }
-
- return (code || icode);
-#endif /* NO_KRB5 */
-}
-
-long
-khm_krb4_kinit(char * aname,
- char * inst,
- char * realm,
- long lifetime,
- char * password) {
-
- wchar_t * functionName = NULL;
- wchar_t * err_context = NULL;
- int rc4 = 0;
- int msg = 0;
-
- if (pkname_parse == NULL) {
- goto cleanup;
- }
-
- err_context = L"getting realm";
- if (!*realm && (rc4 = (int)(*pkrb_get_lrealm)(realm, 1))) {
- functionName = L"krb_get_lrealm()";
- msg = IDS_ERR_REALM;
- goto cleanup;
- }
-
- err_context = L"checking principal";
- if ((!*aname) || (!(rc4 = (int)(*pk_isname)(aname)))) {
- functionName = L"krb_get_lrealm()";
- msg = IDS_ERR_PRINCIPAL;
- goto cleanup;
- }
-
- /* optional instance */
- if (!(rc4 = (int)(*pk_isinst)(inst))) {
- functionName = L"k_isinst()";
- msg = IDS_ERR_INVINST;
- goto cleanup;
- }
-
- if (!(rc4 = (int)(*pk_isrealm)(realm))) {
- functionName = L"k_isrealm()";
- msg = IDS_ERR_REALM;
- goto cleanup;
- }
-
- khm_krb4_set_def_tkt_string();
-
- err_context = L"fetching ticket";
- rc4 = (*pkrb_get_pw_in_tkt)(aname, inst, realm, "krbtgt", realm,
- lifetime, password);
-
- if (rc4) /* XXX: do we want: && (rc != NO_TKT_FIL) as well? */ {
- functionName = L"krb_get_pw_in_tkt()";
- msg = IDS_ERR_PWINTKT;
- goto cleanup;
- }
-
- return 0;
-
- cleanup:
- {
- _report_sr0(KHERR_ERROR, msg);
- _location(functionName);
- }
- return rc4;
-}
-
-
-int khm_krb4_kdestroy(void) {
- int k_errno = 0;
-
- if (pdest_tkt != NULL)
- {
- k_errno = (*pdest_tkt)();
- if (k_errno && (k_errno != RET_TKFIL))
- return KRBERR(k_errno);
- }
-
- return k_errno;
-}
+/*
+* Copyright (c) 2005 Massachusetts Institute of Technology
+*
+* Permission is hereby granted, free of charge, to any person
+* obtaining a copy of this software and associated documentation
+* files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy,
+* modify, merge, publish, distribute, sublicense, and/or sell copies
+* of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be
+* included in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*/
+
+/* $Id$ */
+
+/* Originally this was krb5routines.c in Leash sources. Subsequently
+modified and adapted for NetIDMgr */
+
+#include<krbcred.h>
+#include<kherror.h>
+
+#define SECURITY_WIN32
+#include <security.h>
+
+#include <string.h>
+#include <time.h>
+#include <assert.h>
+#include <strsafe.h>
+
+
+
+int com_addr(void)
+{
+ long ipAddr;
+ char loc_addr[ADDR_SZ];
+ CREDENTIALS cred;
+ char service[40];
+ char instance[40];
+ // char addr[40];
+ char realm[40];
+ struct in_addr LocAddr;
+ int k_errno;
+
+ if (pkrb_get_cred == NULL)
+ return(KSUCCESS);
+
+ k_errno = (*pkrb_get_cred)(service,instance,realm,&cred);
+ if (k_errno)
+ return KRBERR(k_errno);
+
+ while(1) {
+ ipAddr = (*pLocalHostAddr)();
+ LocAddr.s_addr = ipAddr;
+ StringCbCopyA(loc_addr, sizeof(loc_addr), inet_ntoa(LocAddr));
+ if ( strcmp(cred.address,loc_addr) != 0) {
+ /* TODO: do something about this */
+ //Leash_kdestroy ();
+ break;
+ }
+ break;
+ } // while()
+ return 0;
+}
+
+
+long
+khm_krb4_list_tickets(void)
+{
+ char ptktname[MAX_PATH + 5];
+ char pname[ANAME_SZ];
+ char pinst[INST_SZ];
+ char prealm[REALM_SZ];
+ wchar_t wbuf[256];
+ int k_errno = 0;
+ CREDENTIALS c;
+ int newtickets = 0;
+ int open = 0;
+ khm_handle ident = NULL;
+ khm_handle cred = NULL;
+ time_t tt;
+ FILETIME ft;
+
+ kcdb_credset_flush(krb4_credset);
+
+ // Since krb_get_tf_realm will return a ticket_file error,
+ // we will call tf_init and tf_close first to filter out
+ // things like no ticket file. Otherwise, the error that
+ // the user would see would be
+ // klist: can't find realm of ticket file: No ticket file (tf_util)
+ // instead of klist: No ticket file (tf_util)
+ if (ptf_init == NULL)
+ goto collect;
+
+ com_addr();
+
+ // Open ticket file
+ if ((k_errno = (*ptf_init)((*ptkt_string)(), R_TKT_FIL)))
+ {
+ goto cleanup;
+ }
+ // Close ticket file
+ (void) (*ptf_close)();
+
+ // We must find the realm of the ticket file here before calling
+ // tf_init because since the realm of the ticket file is not
+ // really stored in the principal section of the file, the
+ // routine we use must itself call tf_init and tf_close.
+
+ if ((k_errno = (*pkrb_get_tf_realm)((*ptkt_string)(), prealm)) != KSUCCESS)
+ {
+ goto cleanup;
+ }
+
+ // Open ticket file
+ if (k_errno = (*ptf_init)((*ptkt_string)(), R_TKT_FIL))
+ {
+ goto cleanup;
+ }
+
+ StringCchCopyA(ptktname, ARRAYLENGTH(ptktname), (*ptkt_string)());
+
+ open = 1;
+
+ // Get principal name and instance
+ if ((k_errno = (*ptf_get_pname)(pname)) || (k_errno = (*ptf_get_pinst)(pinst)))
+ {
+ goto cleanup;
+ }
+
+ // You may think that this is the obvious place to get the
+ // realm of the ticket file, but it can't be done here as the
+ // routine to do this must open the ticket file. This is why
+ // it was done before tf_init.
+ StringCbPrintf(wbuf, sizeof(wbuf), L"%S%S%S%S%S", (LPSTR)pname,
+ (LPSTR)(pinst[0] ? "." : ""), (LPSTR)pinst,
+ (LPSTR)(prealm[0] ? "@" : ""), (LPSTR)prealm);
+
+ if(KHM_FAILED(kcdb_identity_create(wbuf, KCDB_IDENT_FLAG_CREATE, &ident)))
+ {
+ goto cleanup;
+ }
+
+ // Get KRB4 tickets
+ while ((k_errno = (*ptf_get_cred)(&c)) == KSUCCESS)
+ {
+ StringCbPrintf(wbuf, sizeof(wbuf), L"%S%S%S%S%S",
+ c.service,
+ (c.instance[0] ? "." : ""),
+ c.instance,
+ (c.realm[0] ? "@" : ""),
+ c.realm);
+
+ if(KHM_FAILED(kcdb_cred_create(wbuf, ident, credtype_id_krb4, &cred)))
+ continue;
+
+ tt = c.issue_date + c.lifetime * 5L * 60L;
+ TimetToFileTime(tt, &ft);
+ kcdb_cred_set_attr(cred, KCDB_ATTR_EXPIRE, &ft, sizeof(ft));
+
+ tt = c.issue_date;
+ TimetToFileTime(tt, &ft);
+ kcdb_cred_set_attr(cred, KCDB_ATTR_ISSUE, &ft, sizeof(ft));
+
+ tt = c.lifetime * 5L * 60L;
+ TimetToFileTimeInterval(tt, &ft);
+ kcdb_cred_set_attr(cred, KCDB_ATTR_LIFETIME, &ft, sizeof(ft));
+
+ AnsiStrToUnicode(wbuf, sizeof(wbuf), ptktname);
+ kcdb_cred_set_attr(cred, KCDB_ATTR_LOCATION, wbuf, KCDB_CBSIZE_AUTO);
+
+ kcdb_credset_add_cred(krb4_credset, cred, -1);
+
+ kcdb_cred_release(cred);
+ } // while
+
+ cleanup:
+ if (ptf_close == NULL)
+ return(KSUCCESS);
+
+ if (open)
+ (*ptf_close)(); //close ticket file
+
+ if (k_errno == EOF)
+ k_errno = 0;
+
+ // XXX the if statement directly below was inserted to eliminate
+ // an error NO_TKT_FIL on Leash startup. The error occurs from an
+ // error number thrown from krb_get_tf_realm. We believe this
+ // change does not eliminate other errors, but it may.
+
+ if (k_errno == NO_TKT_FIL)
+ k_errno = 0;
+
+ if(ident)
+ kcdb_identity_release(ident);
+
+#if 0
+ /*TODO: Handle errors here */
+ if (k_errno)
+ {
+ CHAR message[256];
+ CHAR errBuf[256];
+ LPCSTR errText;
+
+ if (!Lerror_message)
+ return -1;
+
+ errText = err_describe(errBuf, KRBERR(k_errno));
+
+ sprintf(message, "%s\n\n%s failed", errText, functionName);
+ MessageBox(NULL, message, "Kerberos Four",
+ MB_OK | MB_ICONERROR | MB_TASKMODAL | MB_SETFOREGROUND);
+ }
+#endif
+
+ collect:
+ kcdb_credset_collect(NULL, krb4_credset, ident, credtype_id_krb4, NULL);
+
+ return k_errno;
+}
+
+#define KRB_FILE "KRB.CON"
+#define KRBREALM_FILE "KRBREALM.CON"
+#define KRB5_FILE "KRB5.INI"
+
+BOOL
+khm_krb5_get_profile_file(LPSTR confname, UINT szConfname)
+{
+ char **configFile = NULL;
+ if (pkrb5_get_default_config_files(&configFile))
+ {
+ GetWindowsDirectoryA(confname,szConfname);
+ confname[szConfname-1] = '\0';
+
+ StringCchCatA(confname, szConfname, "\\");
+ StringCchCatA(confname, szConfname, KRB5_FILE);
+
+ return FALSE;
+ }
+
+ *confname = 0;
+
+ if (configFile)
+ {
+ StringCchCopyA(confname, szConfname, *configFile);
+ pkrb5_free_config_files(configFile);
+ }
+
+ if (!*confname)
+ {
+ GetWindowsDirectoryA(confname,szConfname);
+ confname[szConfname-1] = '\0';
+
+ StringCchCatA(confname, szConfname, "\\");
+ StringCchCatA(confname, szConfname, KRB5_FILE);
+ }
+
+ return FALSE;
+}
+
+BOOL
+khm_get_krb4_con_file(LPSTR confname, UINT szConfname)
+{
+ if (hKrb5 && !hKrb4) {
+ // hold krb.con where krb5.ini is located
+ CHAR krbConFile[MAX_PATH]="";
+ LPSTR pFind;
+
+ if (khm_krb5_get_profile_file(krbConFile, sizeof(krbConFile))) {
+ GetWindowsDirectoryA(krbConFile,sizeof(krbConFile));
+ krbConFile[MAX_PATH-1] = '\0';
+
+ StringCbCatA(krbConFile, sizeof(krbConFile), "\\");
+ }
+
+ pFind = strrchr(krbConFile, '\\');
+
+ if (pFind) {
+ *pFind = '\0';
+
+ StringCbCatA(krbConFile, sizeof(krbConFile), "\\");
+ StringCbCatA(krbConFile, sizeof(krbConFile), KRB_FILE);
+ } else {
+ krbConFile[0] = '\0';
+ }
+
+ StringCchCopyA(confname, szConfname, krbConFile);
+ } else if (hKrb4) {
+ unsigned int size = szConfname;
+ memset(confname, '\0', szConfname);
+ if (!pkrb_get_krbconf2(confname, &size)) {
+ GetWindowsDirectoryA(confname,szConfname);
+ confname[szConfname-1] = '\0';
+ StringCchCatA(confname, szConfname, "\\");
+ StringCchCatA(confname, szConfname, KRB_FILE);
+ }
+ }
+
+ return FALSE;
+}
+
+int
+readstring(FILE * file, char * buf, int len)
+{
+ int c,i;
+ memset(buf, '\0', sizeof(buf));
+ for (i=0, c=fgetc(file); c != EOF ; c=fgetc(file), i++)
+ {
+ if (i < sizeof(buf)) {
+ if (c == '\n') {
+ buf[i] = '\0';
+ return i;
+ } else {
+ buf[i] = c;
+ }
+ } else {
+ if (c == '\n') {
+ buf[len-1] = '\0';
+ return(i);
+ }
+ }
+ }
+ if (c == EOF) {
+ if (i > 0 && i < len) {
+ buf[i] = '\0';
+ return(i);
+ } else {
+ buf[len-1] = '\0';
+ return(-1);
+ }
+ }
+ return(-1);
+}
+
+/*! \internal
+ \brief Return a list of configured realms
+
+ The string that is returned is a set of null terminated unicode strings,
+ each of which denotes one realm. The set is terminated by a zero length
+ null terminated string.
+
+ The caller should free the returned string using free()
+
+ \return The string with the list of realms or NULL if the operation fails.
+*/
+wchar_t * khm_krb5_get_realm_list(void)
+{
+ wchar_t * rlist = NULL;
+
+ if (pprofile_get_subsection_names && pprofile_free_list) {
+ const char* rootSection[] = {"realms", NULL};
+ const char** rootsec = rootSection;
+ char **sections = NULL, **cpp = NULL, *value = NULL;
+
+ char krb5_conf[MAX_PATH+1];
+
+ if (!khm_krb5_get_profile_file(krb5_conf,sizeof(krb5_conf))) {
+ profile_t profile;
+ long retval;
+ const char *filenames[2];
+ wchar_t * d;
+ size_t cbsize;
+ size_t t;
+
+ filenames[0] = krb5_conf;
+ filenames[1] = NULL;
+ retval = pprofile_init(filenames, &profile);
+ if (!retval) {
+ retval = pprofile_get_subsection_names(profile, rootsec, &sections);
+
+ if (!retval)
+ {
+ /* first figure out how much space to allocate */
+ cbsize = 0;
+ for (cpp = sections; *cpp; cpp++)
+ {
+ cbsize += sizeof(wchar_t) * (strlen(*cpp) + 1);
+ }
+ cbsize += sizeof(wchar_t); /* double null terminated */
+
+ rlist = PMALLOC(cbsize);
+ d = rlist;
+ for (cpp = sections; *cpp; cpp++)
+ {
+ AnsiStrToUnicode(d, cbsize, *cpp);
+ t = wcslen(d) + 1;
+ d += t;
+ cbsize -= sizeof(wchar_t) * t;
+ }
+ *d = L'\0';
+ }
+
+ pprofile_free_list(sections);
+
+#if 0
+ retval = pprofile_get_string(profile, "libdefaults","noaddresses", 0, "true", &value);
+ if ( value ) {
+ disable_noaddresses = config_boolean_to_int(value);
+ pprofile_release_string(value);
+ }
+#endif
+ pprofile_release(profile);
+ }
+ }
+ } else {
+ FILE * file;
+ char krb_conf[MAX_PATH+1];
+ char * p;
+ size_t cbsize, t;
+ wchar_t * d;
+
+ if (!khm_get_krb4_con_file(krb_conf,sizeof(krb_conf)) &&
+#if _MSC_VER >= 1400
+ !fopen_s(&file, krb_conf, "rt")
+#else
+ (file = fopen(krb_conf, "rt"))
+#endif
+ )
+ {
+ char lineBuf[256];
+
+ /*TODO: compute the actual required buffer size instead of hardcoding */
+ cbsize = 16384; // arbitrary
+ rlist = PMALLOC(cbsize);
+ d = rlist;
+
+ // Skip the default realm
+ readstring(file,lineBuf,sizeof(lineBuf));
+
+ // Read the defined realms
+ while (TRUE)
+ {
+ if (readstring(file,lineBuf,sizeof(lineBuf)) < 0)
+ break;
+
+ if (*(lineBuf + strlen(lineBuf) - 1) == '\r')
+ *(lineBuf + strlen(lineBuf) - 1) = 0;
+
+ for (p=lineBuf; *p ; p++)
+ {
+ if (isspace(*p)) {
+ *p = 0;
+ break;
+ }
+ }
+
+ if ( strncmp(".KERBEROS.OPTION.",lineBuf,17) ) {
+ t = strlen(lineBuf) + 1;
+ if(cbsize > (1 + t*sizeof(wchar_t))) {
+ AnsiStrToUnicode(d, cbsize, lineBuf);
+ d += t;
+ cbsize -= t * sizeof(wchar_t);
+ } else
+ break;
+ }
+ }
+
+ *d = L'\0';
+
+ fclose(file);
+ }
+ }
+
+ return rlist;
+}
+
+/*! \internal
+ \brief Get the default realm
+
+ A string will be returned that specifies the default realm. The caller
+ should free the string using free().
+
+ Returns NULL if the operation fails.
+*/
+wchar_t * khm_krb5_get_default_realm(void)
+{
+ wchar_t * realm;
+ size_t cch;
+ krb5_context ctx=0;
+ char * def = 0;
+
+ pkrb5_init_context(&ctx);
+ pkrb5_get_default_realm(ctx,&def);
+
+ if (def) {
+ cch = strlen(def) + 1;
+ realm = PMALLOC(sizeof(wchar_t) * cch);
+ AnsiStrToUnicode(realm, sizeof(wchar_t) * cch, def);
+ pkrb5_free_default_realm(ctx, def);
+ } else
+ realm = NULL;
+
+ pkrb5_free_context(ctx);
+
+ return realm;
+}
+
+static
+char *
+make_postfix(const char * base,
+ const char * postfix,
+ char ** rcopy)
+{
+ size_t base_size;
+ size_t ret_size;
+ char * copy = 0;
+ char * ret = 0;
+ size_t t;
+
+ if (FAILED(StringCbLengthA(base, STRSAFE_MAX_CCH * sizeof(char), &t)))
+ goto cleanup;
+
+ base_size = t + 1;
+
+ if (FAILED(StringCbLengthA(postfix, STRSAFE_MAX_CCH * sizeof(char), &t)))
+ goto cleanup;
+
+ ret_size = base_size + t + 1;
+
+ copy = malloc(base_size);
+ ret = malloc(ret_size);
+
+ if (!copy || !ret)
+ goto cleanup;
+
+ StringCbCopyNA(copy, base_size, base, base_size);
+ StringCbCopyNA(ret, ret_size, base, base_size);
+ StringCbCopyNA(ret + (base_size - 1), ret_size - (base_size - 1),
+ postfix, ret_size - (base_size - 1));
+
+ cleanup:
+ if (!copy || !ret) {
+ if (copy)
+ free(copy);
+ if (ret)
+ free(ret);
+ copy = ret = 0;
+ }
+ // INVARIANT: (ret ==> copy) && (copy ==> ret)
+ *rcopy = copy;
+ return ret;
+}
+
+void
+khm_krb4_set_def_tkt_string(void) {
+ wchar_t wtkt_string[MAX_PATH];
+ char tkt_string[MAX_PATH];
+ khm_size cb;
+
+ cb = sizeof(wtkt_string);
+
+ if (KHM_FAILED(khc_read_string(csp_params, L"TktString",
+ wtkt_string, &cb)) ||
+ wtkt_string[0] == L'\0') {
+
+ pkrb_set_tkt_string(0);
+
+ } else {
+
+ UnicodeStrToAnsi(tkt_string, sizeof(tkt_string),
+ wtkt_string);
+ pkrb_set_tkt_string(tkt_string);
+ }
+}
+
+
+static
+long
+make_temp_cache_v4(const char * postfix)
+{
+ static char * old_cache = 0;
+
+ if (!pkrb_set_tkt_string || !ptkt_string || !pdest_tkt)
+ return 0; // XXX - is this appropriate?
+
+ if (old_cache) {
+ pdest_tkt();
+ pkrb_set_tkt_string(old_cache);
+ free(old_cache);
+ old_cache = 0;
+ }
+
+ if (postfix)
+ {
+ char * tmp_cache = make_postfix(ptkt_string(), postfix, &old_cache);
+
+ if (!tmp_cache)
+ return KFAILURE;
+
+ pkrb_set_tkt_string(tmp_cache);
+ free(tmp_cache);
+ }
+ return 0;
+}
+
+long
+khm_krb4_changepwd(char * principal,
+ char * password,
+ char * newpassword,
+ char** error_str)
+{
+ long k_errno;
+
+ if (!pkrb_set_tkt_string || !ptkt_string || !pkadm_change_your_password ||
+ !pdest_tkt)
+ return KFAILURE;
+
+ k_errno = make_temp_cache_v4("_chgpwd");
+ if (k_errno) return k_errno;
+ k_errno = pkadm_change_your_password(principal, password, newpassword,
+ error_str);
+ make_temp_cache_v4(0);
+ return k_errno;
+}
+
+struct tgt_filter_data {
+ khm_handle identity;
+ wchar_t realm[KCDB_IDENT_MAXCCH_NAME];
+};
+
+khm_int32 KHMAPI
+krb4_tgt_filter(khm_handle cred, khm_int32 flags, void * rock) {
+ struct tgt_filter_data * pdata;
+ wchar_t credname[KCDB_MAXCCH_NAME];
+ wchar_t * t;
+ khm_size cb;
+ khm_int32 ctype;
+
+ pdata = (struct tgt_filter_data *) rock;
+ cb = sizeof(credname);
+
+ if (KHM_FAILED(kcdb_cred_get_type(cred, &ctype)) ||
+ ctype != credtype_id_krb4)
+ return 0;
+
+ if (KHM_FAILED(kcdb_cred_get_name(cred, credname, &cb)))
+ return 0;
+
+ if (wcsncmp(credname, L"krbtgt.", 7))
+ return 0;
+
+ t = wcsrchr(credname, L'@');
+ if (t == NULL)
+ return 0;
+
+ if (wcscmp(t+1, pdata->realm))
+ return 0;
+
+ return 1;
+}
+
+khm_handle
+khm_krb4_find_tgt(khm_handle credset, khm_handle identity) {
+ khm_handle result = NULL;
+ wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
+ wchar_t * t;
+ khm_size cb;
+ struct tgt_filter_data filter_data;
+
+ cb = sizeof(idname);
+
+ if (KHM_FAILED(kcdb_identity_get_name(identity,
+ idname,
+ &cb)))
+ return NULL;
+
+ t = wcsrchr(idname, L'@');
+ if (t == NULL)
+ return NULL;
+
+ StringCbCopy(filter_data.realm, sizeof(filter_data.realm),
+ t + 1);
+ filter_data.identity = identity;
+
+ if (KHM_FAILED(kcdb_credset_find_filtered(credset,
+ -1,
+ krb4_tgt_filter,
+ &filter_data,
+ &result,
+ NULL)))
+ return NULL;
+ else
+ return result;
+}
+
+long
+khm_convert524(khm_handle identity)
+{
+#ifdef NO_KRB5
+ return(0);
+#else
+ krb5_context ctx = 0;
+ krb5_error_code code = 0;
+ int icode = 0;
+ krb5_principal me = 0;
+ krb5_principal server = 0;
+ krb5_creds *v5creds = 0;
+ krb5_creds increds;
+ krb5_ccache cc = 0;
+ CREDENTIALS * v4creds = NULL;
+ static int init_ets = 1;
+
+ if (!pkrb5_init_context ||
+ !pkrb_in_tkt ||
+ !pkrb524_init_ets ||
+ !pkrb524_convert_creds_kdc)
+ return 0;
+
+ v4creds = (CREDENTIALS *) malloc(sizeof(CREDENTIALS));
+ memset((char *) v4creds, 0, sizeof(CREDENTIALS));
+
+ memset((char *) &increds, 0, sizeof(increds));
+ /*
+ From this point on, we can goto cleanup because increds is
+ initialized.
+ */
+
+ code = khm_krb5_initialize(identity, &ctx, &cc);
+ if (code)
+ goto cleanup;
+
+ if ( init_ets ) {
+ pkrb524_init_ets(ctx);
+ init_ets = 0;
+ }
+
+ if (code = pkrb5_cc_get_principal(ctx, cc, &me))
+ goto cleanup;
+
+ if ((code = pkrb5_build_principal(ctx,
+ &server,
+ krb5_princ_realm(ctx, me)->length,
+ krb5_princ_realm(ctx, me)->data,
+ "krbtgt",
+ krb5_princ_realm(ctx, me)->data,
+ NULL))) {
+ goto cleanup;
+ }
+
+ increds.client = me;
+ increds.server = server;
+ increds.times.endtime = 0;
+ increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC;
+ if ((code = pkrb5_get_credentials(ctx, 0,
+ cc,
+ &increds,
+ &v5creds))) {
+ goto cleanup;
+ }
+
+ if ((icode = pkrb524_convert_creds_kdc(ctx,
+ v5creds,
+ v4creds))) {
+ goto cleanup;
+ }
+
+ /* initialize ticket cache */
+ if ((icode = pkrb_in_tkt(v4creds->pname, v4creds->pinst, v4creds->realm)
+ != KSUCCESS)) {
+ goto cleanup;
+ }
+
+ /* stash ticket, session key, etc. for future use */
+ if ((icode = pkrb_save_credentials(v4creds->service,
+ v4creds->instance,
+ v4creds->realm,
+ v4creds->session,
+ v4creds->lifetime,
+ v4creds->kvno,
+ &(v4creds->ticket_st),
+ v4creds->issue_date))) {
+ goto cleanup;
+ }
+
+ cleanup:
+ memset(v4creds, 0, sizeof(v4creds));
+ free(v4creds);
+
+ if (v5creds) {
+ pkrb5_free_creds(ctx, v5creds);
+ }
+ if (increds.client == me)
+ me = 0;
+ if (increds.server == server)
+ server = 0;
+
+ if (ctx)
+ pkrb5_free_cred_contents(ctx, &increds);
+
+ if (server) {
+ pkrb5_free_principal(ctx, server);
+ }
+
+ if (me) {
+ pkrb5_free_principal(ctx, me);
+ }
+
+ if (ctx && cc)
+ pkrb5_cc_close(ctx, cc);
+
+ if (ctx) {
+ pkrb5_free_context(ctx);
+ }
+
+ return (code || icode);
+#endif /* NO_KRB5 */
+}
+
+long
+khm_krb4_kinit(char * aname,
+ char * inst,
+ char * realm,
+ long lifetime,
+ char * password) {
+
+ wchar_t * functionName = NULL;
+ wchar_t * err_context = NULL;
+ int rc4 = 0;
+ int msg = 0;
+
+ if (pkname_parse == NULL) {
+ goto cleanup;
+ }
+
+ err_context = L"getting realm";
+ if (!*realm && (rc4 = (int)(*pkrb_get_lrealm)(realm, 1))) {
+ functionName = L"krb_get_lrealm()";
+ msg = IDS_ERR_REALM;
+ goto cleanup;
+ }
+
+ err_context = L"checking principal";
+ if ((!*aname) || (!(rc4 = (int)(*pk_isname)(aname)))) {
+ functionName = L"krb_get_lrealm()";
+ msg = IDS_ERR_PRINCIPAL;
+ goto cleanup;
+ }
+
+ /* optional instance */
+ if (!(rc4 = (int)(*pk_isinst)(inst))) {
+ functionName = L"k_isinst()";
+ msg = IDS_ERR_INVINST;
+ goto cleanup;
+ }
+
+ if (!(rc4 = (int)(*pk_isrealm)(realm))) {
+ functionName = L"k_isrealm()";
+ msg = IDS_ERR_REALM;
+ goto cleanup;
+ }
+
+ khm_krb4_set_def_tkt_string();
+
+ err_context = L"fetching ticket";
+ rc4 = (*pkrb_get_pw_in_tkt)(aname, inst, realm, "krbtgt", realm,
+ lifetime, password);
+
+ if (rc4) /* XXX: do we want: && (rc != NO_TKT_FIL) as well? */ {
+ functionName = L"krb_get_pw_in_tkt()";
+ msg = IDS_ERR_PWINTKT;
+ goto cleanup;
+ }
+
+ return 0;
+
+ cleanup:
+ {
+ _report_sr0(KHERR_ERROR, msg);
+ _location(functionName);
+ }
+ return rc4;
+}
+
+
+int khm_krb4_kdestroy(void) {
+ int k_errno = 0;
+
+ if (pdest_tkt != NULL)
+ {
+ k_errno = (*pdest_tkt)();
+ if (k_errno && (k_errno != RET_TKFIL))
+ return KRBERR(k_errno);
+ }
+
+ return k_errno;
+}
diff --git a/src/windows/identity/plugins/krb4/krb4funcs.h b/src/windows/identity/plugins/krb4/krb4funcs.h
index 5ec11cc633..05ed3e75dc 100644
--- a/src/windows/identity/plugins/krb4/krb4funcs.h
+++ b/src/windows/identity/plugins/krb4/krb4funcs.h
@@ -1,132 +1,132 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-/* Adapted from multiple Leash header files */
-
-#ifndef __KHIMAIRA_KRB5FUNCS_H
-#define __KHIMAIRA_KRB5FUNCS_H
-
-#include<stdlib.h>
-#include<krb5.h>
-
-#include <windows.h>
-#define SECURITY_WIN32
-#include <security.h>
-
-#if _WIN32_WINNT < 0x0501
-#define KHM_SAVE_WIN32_WINNT _WIN32_WINNT
-#undef _WIN32_WINNT
-#define _WIN32_WINNT 0x0501
-#endif
-#include<ntsecapi.h>
-#ifdef KHM_SAVE_WIN32_WINNT
-#undef _WIN32_WINNT
-#define _WIN32_WINNT KHM_SAVE_WIN32_WINNT
-#undef KHM_SAVE_WIN32_WINNT
-#endif
-
-#include <krb5common.h>
-
-#define LEASH_DEBUG_CLASS_GENERIC 0
-#define LEASH_DEBUG_CLASS_KRB4 1
-#define LEASH_DEBUG_CLASS_KRB4_APP 2
-
-#define LEASH_PRIORITY_LOW 0
-#define LEASH_PRIORITY_HIGH 1
-
-#define KRB5_DEFAULT_LIFE 60*60*10 /* 10 hours */
-
-
-long
-khm_convert524(khm_handle identity);
-
-long
-khm_krb4_kinit(char * aname,
- char * inst,
- char * realm,
- long lifetime,
- char * password);
-
-long
-khm_krb4_list_tickets(void);
-
-int khm_krb4_kdestroy(void);
-
-khm_handle
-khm_krb4_find_tgt(khm_handle credset,
- khm_handle identity);
-
-LONG
-write_registry_setting(
- char* setting,
- DWORD type,
- void* buffer,
- size_t size
- );
-
-LONG
-read_registry_setting_user(
- char* setting,
- void* buffer,
- size_t size
- );
-
-LONG
-read_registry_setting(
- char* setting,
- void* buffer,
- size_t size
- );
-
-BOOL
-get_STRING_from_registry(
- HKEY hBaseKey,
- char * key,
- char * value,
- char * outbuf,
- DWORD outlen
- );
-
-BOOL
-get_DWORD_from_registry(
- HKEY hBaseKey,
- char * key,
- char * value,
- DWORD * result
- );
-
-int
-config_boolean_to_int(
- const char *s
- );
-
-void
-khm_krb4_set_def_tkt_string(void);
-
-wchar_t * khm_krb5_get_default_realm(void);
-wchar_t * khm_krb5_get_realm_list(void);
-
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+/* Adapted from multiple Leash header files */
+
+#ifndef __KHIMAIRA_KRB5FUNCS_H
+#define __KHIMAIRA_KRB5FUNCS_H
+
+#include<stdlib.h>
+#include<krb5.h>
+
+#include <windows.h>
+#define SECURITY_WIN32
+#include <security.h>
+
+#if _WIN32_WINNT < 0x0501
+#define KHM_SAVE_WIN32_WINNT _WIN32_WINNT
+#undef _WIN32_WINNT
+#define _WIN32_WINNT 0x0501
+#endif
+#include<ntsecapi.h>
+#ifdef KHM_SAVE_WIN32_WINNT
+#undef _WIN32_WINNT
+#define _WIN32_WINNT KHM_SAVE_WIN32_WINNT
+#undef KHM_SAVE_WIN32_WINNT
+#endif
+
+#include <krb5common.h>
+
+#define LEASH_DEBUG_CLASS_GENERIC 0
+#define LEASH_DEBUG_CLASS_KRB4 1
+#define LEASH_DEBUG_CLASS_KRB4_APP 2
+
+#define LEASH_PRIORITY_LOW 0
+#define LEASH_PRIORITY_HIGH 1
+
+#define KRB5_DEFAULT_LIFE 60*60*10 /* 10 hours */
+
+
+long
+khm_convert524(khm_handle identity);
+
+long
+khm_krb4_kinit(char * aname,
+ char * inst,
+ char * realm,
+ long lifetime,
+ char * password);
+
+long
+khm_krb4_list_tickets(void);
+
+int khm_krb4_kdestroy(void);
+
+khm_handle
+khm_krb4_find_tgt(khm_handle credset,
+ khm_handle identity);
+
+LONG
+write_registry_setting(
+ char* setting,
+ DWORD type,
+ void* buffer,
+ size_t size
+ );
+
+LONG
+read_registry_setting_user(
+ char* setting,
+ void* buffer,
+ size_t size
+ );
+
+LONG
+read_registry_setting(
+ char* setting,
+ void* buffer,
+ size_t size
+ );
+
+BOOL
+get_STRING_from_registry(
+ HKEY hBaseKey,
+ char * key,
+ char * value,
+ char * outbuf,
+ DWORD outlen
+ );
+
+BOOL
+get_DWORD_from_registry(
+ HKEY hBaseKey,
+ char * key,
+ char * value,
+ DWORD * result
+ );
+
+int
+config_boolean_to_int(
+ const char *s
+ );
+
+void
+khm_krb4_set_def_tkt_string(void);
+
+wchar_t * khm_krb5_get_default_realm(void);
+wchar_t * khm_krb5_get_realm_list(void);
+
+#endif
diff --git a/src/windows/identity/plugins/krb4/krb4main.c b/src/windows/identity/plugins/krb4/krb4main.c
index 57e33a8d8b..7ab2d71f32 100644
--- a/src/windows/identity/plugins/krb4/krb4main.c
+++ b/src/windows/identity/plugins/krb4/krb4main.c
@@ -1,157 +1,157 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<krbcred.h>
-#include<kherror.h>
-
-kmm_module h_khModule; /* KMM's handle to this module */
-HINSTANCE hInstance;
-HMODULE hResModule; /* HMODULE to the resource library */
-
-khm_int32 type_id_enctype = -1;
-khm_int32 type_id_addr_list = -1;
-khm_int32 type_id_krb5_flags = -1;
-
-khm_int32 attr_id_key_enctype = -1;
-khm_int32 attr_id_tkt_enctype = -1;
-khm_int32 attr_id_addr_list = -1;
-khm_int32 attr_id_krb5_flags = -1;
-
-khm_handle csp_plugins = NULL;
-khm_handle csp_krbcred = NULL;
-khm_handle csp_params = NULL;
-
-kmm_module_locale locales[] = {
- LOCALE_DEF(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US), L"krb4cred_en_us.dll", KMM_MLOC_FLAG_DEFAULT)
-};
-
-int n_locales = ARRAYLENGTH(locales);
-
-/* These two probably should not do anything */
-void init_krb() {
-}
-
-void exit_krb() {
-}
-
-/* called by the NetIDMgr module manager */
-KHMEXP khm_int32 KHMAPI init_module(kmm_module h_module) {
- khm_int32 rv = KHM_ERROR_SUCCESS;
- kmm_plugin_reg pi;
- wchar_t buf[256];
-
- h_khModule = h_module;
-
- rv = kmm_set_locale_info(h_module, locales, n_locales);
- if(KHM_SUCCEEDED(rv)) {
- hResModule = kmm_get_resource_hmodule(h_module);
- } else
- goto _exit;
-
- ZeroMemory(&pi, sizeof(pi));
- pi.name = KRB4_PLUGIN_NAME;
- pi.type = KHM_PITYPE_CRED;
- pi.icon = LoadImage(hResModule, MAKEINTRESOURCE(IDI_PLUGIN),
- IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR | LR_DEFAULTSIZE);
- pi.flags = 0;
- pi.msg_proc = krb4_cb;
- pi.dependencies = KRB4_PLUGIN_DEPS;
- pi.description = buf;
- LoadString(hResModule, IDS_PLUGIN_DESC,
- buf, ARRAYLENGTH(buf));
- kmm_provide_plugin(h_module, &pi);
-
- if(KHM_FAILED(rv = init_imports()))
- goto _exit;
-
- if(KHM_FAILED(rv = init_error_funcs()))
- goto _exit;
-
- rv = kmm_get_plugins_config(0, &csp_plugins);
- if(KHM_FAILED(rv)) goto _exit;
-
- rv = khc_load_schema(csp_plugins, schema_krbconfig);
- if(KHM_FAILED(rv)) goto _exit;
-
- rv = khc_open_space(csp_plugins, CSNAME_KRB4CRED, 0, &csp_krbcred);
- if(KHM_FAILED(rv)) goto _exit;
-
- rv = khc_open_space(csp_krbcred, CSNAME_PARAMS, 0, &csp_params);
- if(KHM_FAILED(rv)) goto _exit;
-
- _exit:
- return rv;
-}
-
-/* called by the NetIDMgr module manager */
-KHMEXP khm_int32 KHMAPI exit_module(kmm_module h_module) {
- exit_imports();
- exit_error_funcs();
-
- if(csp_params) {
- khc_close_space(csp_params);
- csp_params = NULL;
- }
-
- if(csp_krbcred) {
- khc_close_space(csp_krbcred);
- csp_krbcred = NULL;
- }
-
- if(csp_plugins) {
- khc_unload_schema(csp_plugins, schema_krbconfig);
- khc_close_space(csp_plugins);
- csp_plugins = NULL;
- }
-
- return KHM_ERROR_SUCCESS; /* the return code is ignored */
-}
-
-BOOL WINAPI DllMain(
- HINSTANCE hinstDLL,
- DWORD fdwReason,
- LPVOID lpvReserved
-)
-{
- switch(fdwReason) {
- case DLL_PROCESS_ATTACH:
- hInstance = hinstDLL;
- init_krb();
- break;
-
- case DLL_PROCESS_DETACH:
- exit_krb();
- break;
-
- case DLL_THREAD_ATTACH:
- break;
-
- case DLL_THREAD_DETACH:
- break;
- }
-
- return TRUE;
-}
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<krbcred.h>
+#include<kherror.h>
+
+kmm_module h_khModule; /* KMM's handle to this module */
+HINSTANCE hInstance;
+HMODULE hResModule; /* HMODULE to the resource library */
+
+khm_int32 type_id_enctype = -1;
+khm_int32 type_id_addr_list = -1;
+khm_int32 type_id_krb5_flags = -1;
+
+khm_int32 attr_id_key_enctype = -1;
+khm_int32 attr_id_tkt_enctype = -1;
+khm_int32 attr_id_addr_list = -1;
+khm_int32 attr_id_krb5_flags = -1;
+
+khm_handle csp_plugins = NULL;
+khm_handle csp_krbcred = NULL;
+khm_handle csp_params = NULL;
+
+kmm_module_locale locales[] = {
+ LOCALE_DEF(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US), L"krb4cred_en_us.dll", KMM_MLOC_FLAG_DEFAULT)
+};
+
+int n_locales = ARRAYLENGTH(locales);
+
+/* These two probably should not do anything */
+void init_krb() {
+}
+
+void exit_krb() {
+}
+
+/* called by the NetIDMgr module manager */
+KHMEXP khm_int32 KHMAPI init_module(kmm_module h_module) {
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+ kmm_plugin_reg pi;
+ wchar_t buf[256];
+
+ h_khModule = h_module;
+
+ rv = kmm_set_locale_info(h_module, locales, n_locales);
+ if(KHM_SUCCEEDED(rv)) {
+ hResModule = kmm_get_resource_hmodule(h_module);
+ } else
+ goto _exit;
+
+ ZeroMemory(&pi, sizeof(pi));
+ pi.name = KRB4_PLUGIN_NAME;
+ pi.type = KHM_PITYPE_CRED;
+ pi.icon = LoadImage(hResModule, MAKEINTRESOURCE(IDI_PLUGIN),
+ IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR | LR_DEFAULTSIZE);
+ pi.flags = 0;
+ pi.msg_proc = krb4_cb;
+ pi.dependencies = KRB4_PLUGIN_DEPS;
+ pi.description = buf;
+ LoadString(hResModule, IDS_PLUGIN_DESC,
+ buf, ARRAYLENGTH(buf));
+ kmm_provide_plugin(h_module, &pi);
+
+ if(KHM_FAILED(rv = init_imports()))
+ goto _exit;
+
+ if(KHM_FAILED(rv = init_error_funcs()))
+ goto _exit;
+
+ rv = kmm_get_plugins_config(0, &csp_plugins);
+ if(KHM_FAILED(rv)) goto _exit;
+
+ rv = khc_load_schema(csp_plugins, schema_krbconfig);
+ if(KHM_FAILED(rv)) goto _exit;
+
+ rv = khc_open_space(csp_plugins, CSNAME_KRB4CRED, 0, &csp_krbcred);
+ if(KHM_FAILED(rv)) goto _exit;
+
+ rv = khc_open_space(csp_krbcred, CSNAME_PARAMS, 0, &csp_params);
+ if(KHM_FAILED(rv)) goto _exit;
+
+ _exit:
+ return rv;
+}
+
+/* called by the NetIDMgr module manager */
+KHMEXP khm_int32 KHMAPI exit_module(kmm_module h_module) {
+ exit_imports();
+ exit_error_funcs();
+
+ if(csp_params) {
+ khc_close_space(csp_params);
+ csp_params = NULL;
+ }
+
+ if(csp_krbcred) {
+ khc_close_space(csp_krbcred);
+ csp_krbcred = NULL;
+ }
+
+ if(csp_plugins) {
+ khc_unload_schema(csp_plugins, schema_krbconfig);
+ khc_close_space(csp_plugins);
+ csp_plugins = NULL;
+ }
+
+ return KHM_ERROR_SUCCESS; /* the return code is ignored */
+}
+
+BOOL WINAPI DllMain(
+ HINSTANCE hinstDLL,
+ DWORD fdwReason,
+ LPVOID lpvReserved
+)
+{
+ switch(fdwReason) {
+ case DLL_PROCESS_ATTACH:
+ hInstance = hinstDLL;
+ init_krb();
+ break;
+
+ case DLL_PROCESS_DETACH:
+ exit_krb();
+ break;
+
+ case DLL_THREAD_ATTACH:
+ break;
+
+ case DLL_THREAD_DETACH:
+ break;
+ }
+
+ return TRUE;
+}
diff --git a/src/windows/identity/plugins/krb4/krb4newcreds.c b/src/windows/identity/plugins/krb4/krb4newcreds.c
index 54feae5b36..c2d477e0ee 100644
--- a/src/windows/identity/plugins/krb4/krb4newcreds.c
+++ b/src/windows/identity/plugins/krb4/krb4newcreds.c
@@ -1,873 +1,873 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<krbcred.h>
-#include<kherror.h>
-#include<khmsgtypes.h>
-#include<khuidefs.h>
-#include<utils.h>
-#include<commctrl.h>
-#include<strsafe.h>
-#include<krb5.h>
-#include<assert.h>
-
-/* method identifiers should be contiguous */
-#define K4_METHOD_AUTO 0
-#define K4_METHOD_PASSWORD 1
-#define K4_METHOD_K524 2
-
-int method_to_id[] = {
- IDC_NCK4_AUTO,
- IDC_NCK4_PWD,
- IDC_NCK4_K524
-};
-
-typedef struct tag_k4_dlg_data {
- HWND hwnd;
- khui_new_creds * nc;
- khui_new_creds_by_type * nct;
-
- khm_boolean k4_enabled;
- khm_int32 method;
- time_t lifetime;
-} k4_dlg_data;
-
-void k4_update_display(k4_dlg_data * d, BOOL update_methods) {
- CheckDlgButton(d->hwnd, IDC_NCK4_OBTAIN,
- (d->k4_enabled)?BST_CHECKED: BST_UNCHECKED);
-
- if (d->k4_enabled) {
- EnableWindow(GetDlgItem(d->hwnd, IDC_NCK4_AUTO), TRUE);
- EnableWindow(GetDlgItem(d->hwnd, IDC_NCK4_K524), TRUE);
- EnableWindow(GetDlgItem(d->hwnd, IDC_NCK4_PWD ), TRUE);
- } else {
- EnableWindow(GetDlgItem(d->hwnd, IDC_NCK4_AUTO), FALSE);
- EnableWindow(GetDlgItem(d->hwnd, IDC_NCK4_K524), FALSE);
- EnableWindow(GetDlgItem(d->hwnd, IDC_NCK4_PWD ), FALSE);
- }
-
-#ifdef DEBUG
- assert(d->method >= 0 && d->method < ARRAYLENGTH(method_to_id));
-#endif
-
- CheckRadioButton(d->hwnd, IDC_NCK4_AUTO, IDC_NCK4_PWD, method_to_id[d->method]);
-
- khui_cw_enable_type(d->nc, credtype_id_krb4, d->k4_enabled);
-}
-
-void k4_update_data(k4_dlg_data * d) {
- int i;
- khm_boolean oldstate;
-
- oldstate = d->k4_enabled;
-
- if (IsDlgButtonChecked(d->hwnd, IDC_NCK4_OBTAIN) == BST_CHECKED)
- d->k4_enabled = TRUE;
- else
- d->k4_enabled = FALSE;
-
- if ((oldstate && !d->k4_enabled) ||
- (!oldstate && d->k4_enabled)) {
-
- khui_cw_enable_type(d->nc, credtype_id_krb4, d->k4_enabled);
- }
-
- d->method = K4_METHOD_AUTO;
-
- for (i=K4_METHOD_AUTO; i<=K4_METHOD_K524; i++) {
- if (IsDlgButtonChecked(d->hwnd, method_to_id[i]) == BST_CHECKED) {
- d->method = i;
- break;
- }
- }
-}
-
-khm_boolean k4_should_identity_get_k4(khm_handle ident) {
- khm_int32 idflags = 0;
- khm_int32 t = TRUE;
- khm_handle csp_ident = NULL;
- khm_handle csp_k4 = NULL;
- khm_boolean get_k4 = TRUE;
- khm_boolean id_spec = FALSE;
-
- if (KHM_FAILED(kcdb_identity_get_flags(ident, &idflags)))
- return FALSE;
-
- if (!(idflags & KCDB_IDENT_FLAG_DEFAULT)) {
- /* we only support k4 for one identity, and that is the
- default identity. If we are trying to get tickets for a
- non-default identity, then we start off as disabled unless
- there is no default identity. */
-
- khm_handle defident = NULL;
-
- if (KHM_SUCCEEDED(kcdb_identity_get_default(&defident))) {
- kcdb_identity_release(defident);
-
- return FALSE;
- }
- }
-
- if (KHM_SUCCEEDED(kcdb_identity_get_config(ident, 0, &csp_ident))) {
- if (KHM_SUCCEEDED(khc_open_space(csp_ident, CSNAME_KRB4CRED, 0,
- &csp_k4))) {
- khm_int32 t = 0;
-
- if (KHM_SUCCEEDED(khc_read_int32(csp_k4, L"Krb4NewCreds", &t))) {
- get_k4 = !!t;
- id_spec = TRUE;
- }
-
- khc_close_space(csp_k4);
- }
- khc_close_space(csp_ident);
- }
-
- /* if there was a value specified for the identity, then that
- takes precedence. */
- if (id_spec || !get_k4)
- return get_k4;
-
- if (KHM_SUCCEEDED(khc_read_int32(csp_params, L"Krb4NewCreds", &t)) &&
- !t)
- return FALSE;
-
- return TRUE;
-}
-
-void k4_read_identity_data(k4_dlg_data * d) {
- khm_handle csp_ident = NULL;
- khm_handle csp_k4 = NULL;
-
- khm_int32 idflags = 0;
- khm_int32 t;
-
- if (KHM_SUCCEEDED(khc_read_int32(csp_params, L"Krb4NewCreds", &t)))
- d->k4_enabled = !!t;
- else
- d->k4_enabled = TRUE;
-
- if (KHM_SUCCEEDED(khc_read_int32(csp_params, L"Krb4Method", &t)))
- d->method = t;
- else
- d->method = K4_METHOD_AUTO;
-
- if (KHM_SUCCEEDED(khc_read_int32(csp_params, L"DefaultLifetime", &t)))
- d->lifetime = t;
- else
- d->lifetime = 10 * 60 * 60; /* 10 hours */
-
- if (d->nc->n_identities > 0 &&
- d->nc->identities[0]) {
-
- if (KHM_SUCCEEDED(kcdb_identity_get_config(d->nc->identities[0],
- 0,
- &csp_ident))) {
-
- khc_open_space(csp_ident, CSNAME_KRB4CRED, 0, &csp_k4);
-
- if (csp_k4) {
- if (KHM_SUCCEEDED(khc_read_int32(csp_k4, L"Krb4NewCreds", &t)))
- d->k4_enabled = !!t;
- if (KHM_SUCCEEDED(khc_read_int32(csp_k4, L"Krb4Method", &t)))
- d->method = t;
- khc_close_space(csp_k4);
- }
-
- khc_close_space(csp_ident);
- }
-
- if (d->k4_enabled) {
- d->k4_enabled = k4_should_identity_get_k4(d->nc->identities[0]);
- }
- } else {
- d->k4_enabled = FALSE;
- }
-
- if (d->method < 0 || d->method > K4_METHOD_K524)
- d->method = K4_METHOD_AUTO;
-}
-
-void k4_write_identity_data(k4_dlg_data * d) {
- khm_handle csp_ident = NULL;
- khm_handle csp_k4 = NULL;
-
- if (d->nc->n_identities > 0 &&
- d->nc->identities[0] &&
- KHM_SUCCEEDED(kcdb_identity_get_config(d->nc->identities[0],
- KHM_FLAG_CREATE,
- &csp_ident))) {
- khc_open_space(csp_ident, CSNAME_KRB4CRED,
- KHM_FLAG_CREATE | KCONF_FLAG_WRITEIFMOD,
- &csp_k4);
-
- if (csp_k4) {
- khc_write_int32(csp_k4, L"Krb4NewCreds", !!d->k4_enabled);
- khc_write_int32(csp_k4, L"Krb4Method", d->method);
-
- khc_close_space(csp_k4);
- }
-
- khc_close_space(csp_ident);
- }
-}
-
-void k4_handle_wmnc_notify(k4_dlg_data * d,
- WPARAM wParam,
- LPARAM lParam) {
- switch(HIWORD(wParam)) {
- case WMNC_UPDATE_CREDTEXT:
- {
- if (d->nct->credtext) {
- PFREE(d->nct->credtext);
- d->nct->credtext = NULL;
- }
-
- if (d->nc->n_identities > 0 &&
- d->nc->identities[0]) {
-
- khm_int32 flags = 0;
- wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
- wchar_t * atsign;
- wchar_t * realm;
- khm_size cb;
-
- kcdb_identity_get_flags(d->nc->identities[0], &flags);
-
- if (!(flags & KCDB_IDENT_FLAG_VALID)) {
- break;
- }
-
- cb = sizeof(idname);
- kcdb_identity_get_name(d->nc->identities[0], idname,
- &cb);
-
- atsign = wcsrchr(idname, L'@');
-
- if (atsign == NULL || !atsign[1])
- break;
-
- realm = ++atsign;
-
- if (d->k4_enabled) {
- wchar_t wmethod[128];
- wchar_t wfmt[128];
- wchar_t wct[512];
-
- LoadString(hResModule, IDS_CT_TGTFOR,
- wfmt, ARRAYLENGTH(wfmt));
-
- if (d->method == K4_METHOD_AUTO)
- LoadString(hResModule, IDS_METHOD_AUTO, wmethod,
- ARRAYLENGTH(wmethod));
- else if (d->method == K4_METHOD_PASSWORD)
- LoadString(hResModule, IDS_METHOD_PWD, wmethod,
- ARRAYLENGTH(wmethod));
- else if (d->method == K4_METHOD_K524)
- LoadString(hResModule, IDS_METHOD_K524, wmethod,
- ARRAYLENGTH(wmethod));
- else {
- assert(FALSE);
- }
-
- StringCbPrintf(wct, sizeof(wct), wfmt, realm, wmethod);
-
- StringCbLength(wct, sizeof(wct), &cb);
- cb += sizeof(wchar_t);
-
- d->nct->credtext = PMALLOC(cb);
-
- StringCbCopy(d->nct->credtext, cb, wct);
- } else {
- wchar_t wct[256];
-
- LoadString(hResModule, IDS_CT_DISABLED,
- wct, ARRAYLENGTH(wct));
-
- StringCbLength(wct, sizeof(wct), &cb);
- cb += sizeof(wchar_t);
-
- d->nct->credtext = PMALLOC(cb);
-
- StringCbCopy(d->nct->credtext, cb, wct);
- }
- }
- /* no identities were selected. it is not the
- responsibility of krb4 to complain about this. */
- }
- break;
-
- case WMNC_IDENTITY_CHANGE:
- k4_read_identity_data(d);
- k4_update_display(d, TRUE);
- break;
-
- case WMNC_CREDTEXT_LINK:
- {
- wchar_t wid[KHUI_MAXCCH_HTLINK_FIELD];
- wchar_t * wids;
- khui_htwnd_link * l;
-
- l = (khui_htwnd_link *) lParam;
-
- StringCchCopyN(wid, ARRAYLENGTH(wid), l->id, l->id_len);
- wids = wcschr(wid, L':');
-
- if (!wids)
- break;
- else
- wids++;
-
- if (!wcscmp(wids, L"Enable")) {
- d->k4_enabled = TRUE;
-
- k4_update_display(d, TRUE);
- khui_cw_enable_type(d->nc, credtype_id_krb4, TRUE);
- }
- }
- break;
- }
-}
-
-INT_PTR CALLBACK k4_nc_dlg_proc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam) {
-
- k4_dlg_data * d;
-
- switch(uMsg) {
- case WM_INITDIALOG:
- {
- d = PMALLOC(sizeof(*d));
- ZeroMemory(d, sizeof(*d));
-
- d->nc = (khui_new_creds *) lParam;
- khui_cw_find_type(d->nc, credtype_id_krb4, &d->nct);
-
-#pragma warning(push)
-#pragma warning(disable: 4244)
- SetWindowLongPtr(hwnd, DWLP_USER, (LPARAM) d);
-#pragma warning(pop)
-
- d->nct->aux = (LPARAM) d;
- d->hwnd = hwnd;
-
- d->k4_enabled = TRUE;
- d->method = K4_METHOD_AUTO;
-
- k4_update_display(d, TRUE);
- }
- break;
-
- case WM_COMMAND:
- {
- if (HIWORD(wParam) == BN_CLICKED) {
- d = (k4_dlg_data *) (LONG_PTR)
- GetWindowLongPtr(hwnd, DWLP_USER);
-
- k4_update_data(d);
-
- if (LOWORD(wParam) == IDC_NCK4_OBTAIN) {
- k4_update_display(d, TRUE);
- }
-
- return TRUE;
- }
- }
- break;
-
- case KHUI_WM_NC_NOTIFY:
- {
- d = (k4_dlg_data *) (LONG_PTR)
- GetWindowLongPtr(hwnd, DWLP_USER);
- k4_handle_wmnc_notify(d, wParam, lParam);
- }
- break;
-
- case WM_DESTROY:
- {
- d = (k4_dlg_data *) (LONG_PTR)
- GetWindowLongPtr(hwnd, DWLP_USER);
-
- d->nct->aux = 0;
-
- PFREE(d);
- }
- break;
- }
-
- return FALSE;
-}
-
-khm_int32
-krb4_msg_newcred(khm_int32 msg_type, khm_int32 msg_subtype,
- khm_ui_4 uparam, void * vparam) {
-
- switch(msg_subtype) {
- case KMSG_CRED_NEW_CREDS:
- {
- khui_new_creds * nc;
- khui_new_creds_by_type * nct;
- khm_size cbsize;
- wchar_t wbuf[256];
-
- nc = (khui_new_creds *) vparam;
-
- nct = PMALLOC(sizeof(*nct));
-#ifdef DEBUG
- assert(nct);
-#endif
- ZeroMemory(nct, sizeof(*nct));
-
- nct->type = credtype_id_krb4;
- nct->ordinal = 3;
- LoadString(hResModule, IDS_NC_K4_SHORT,
- wbuf, ARRAYLENGTH(wbuf));
- StringCbLength(wbuf, sizeof(wbuf), &cbsize);
- cbsize += sizeof(wchar_t);
-
- nct->name = PMALLOC(cbsize);
- StringCbCopy(nct->name, cbsize, wbuf);
-
- nct->type_deps[nct->n_type_deps++] = credtype_id_krb5;
-
- nct->h_module = hResModule;
- nct->dlg_proc = k4_nc_dlg_proc;
- nct->dlg_template = MAKEINTRESOURCE(IDD_NC_KRB4);
-
- khui_cw_add_type(nc, nct);
- }
- break;
-
- case KMSG_CRED_RENEW_CREDS:
- {
- khui_new_creds * nc;
- khui_new_creds_by_type * nct;
- khm_size cbsize;
- wchar_t wbuf[256];
-
- nc = (khui_new_creds *) vparam;
-
- if (!nc->ctx.identity)
- break;
-
- nct = PMALLOC(sizeof(*nct));
-#ifdef DEBUG
- assert(nct);
-#endif
-
- ZeroMemory(nct, sizeof(*nct));
-
- nct->type = credtype_id_krb4;
- nct->ordinal = 3;
- LoadString(hResModule, IDS_NC_K4_SHORT,
- wbuf, ARRAYLENGTH(wbuf));
- StringCbLength(wbuf, sizeof(wbuf), &cbsize);
- cbsize += sizeof(wchar_t);
-
- nct->name = PMALLOC(cbsize);
- StringCbCopy(nct->name, cbsize, wbuf);
-
- nct->type_deps[nct->n_type_deps++] = credtype_id_krb5;
-
- khui_cw_add_type(nc, nct);
- }
- break;
-
- case KMSG_CRED_DIALOG_SETUP:
- break;
-
- case KMSG_CRED_PROCESS:
- {
- khui_new_creds * nc;
- khui_new_creds_by_type * nct = NULL;
- khm_handle ident = NULL;
- k4_dlg_data * d = NULL;
- long code = 0;
- wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
- khm_size cb;
-
- nc = (khui_new_creds *) vparam;
- if (KHM_FAILED(khui_cw_find_type(nc, credtype_id_krb4, &nct)))
- break;
-
- if (nc->subtype == KMSG_CRED_NEW_CREDS ||
- nc->subtype == KMSG_CRED_RENEW_CREDS) {
- khm_int32 method;
-
- if (nc->subtype == KMSG_CRED_NEW_CREDS) {
-
- d = (k4_dlg_data *) nct->aux;
- if (!d ||
- nc->n_identities == 0 ||
- nc->identities[0] == NULL ||
- nc->result != KHUI_NC_RESULT_PROCESS) {
- khui_cw_set_response(nc, credtype_id_krb4,
- KHUI_NC_RESPONSE_SUCCESS |
- KHUI_NC_RESPONSE_EXIT);
- break;
- }
-
- if (!d->k4_enabled) {
- k4_write_identity_data(d);
- khui_cw_set_response(nc, credtype_id_krb4,
- KHUI_NC_RESPONSE_SUCCESS |
- KHUI_NC_RESPONSE_EXIT);
- break;
- }
-
- method = d->method;
- ident = nc->identities[0];
-
- cb = sizeof(idname);
- kcdb_identity_get_name(ident, idname, &cb);
- _begin_task(0);
- _report_mr2(KHERR_NONE, MSG_K4_NEW_CREDS,
- _cstr(ident), _int32(method));
- _resolve();
- _describe();
-
- } else if (nc->subtype == KMSG_CRED_RENEW_CREDS) {
-
- if ((nc->ctx.scope == KHUI_SCOPE_IDENT &&
- nc->ctx.identity != NULL) ||
-
- (nc->ctx.scope == KHUI_SCOPE_CREDTYPE &&
- nc->ctx.cred_type == credtype_id_krb4 &&
- nc->ctx.identity != NULL) ||
-
- (nc->ctx.scope == KHUI_SCOPE_CRED &&
- nc->ctx.cred_type == credtype_id_krb4 &&
- nc->ctx.identity != NULL &&
- nc->ctx.cred != NULL)) {
-
- ident = nc->ctx.identity;
-
- if (!k4_should_identity_get_k4(ident)) {
-
- _reportf(L"Kerberos 4 is not enabled for this identity. Skipping");
-
- khui_cw_set_response(nc, credtype_id_krb4,
- KHUI_NC_RESPONSE_FAILED |
- KHUI_NC_RESPONSE_EXIT);
- break;
- }
-
- } else {
-
- _reportf(L"Kerberos 4 is not within renewal scope. Skipping");
-
- khui_cw_set_response(nc, credtype_id_krb4,
- KHUI_NC_RESPONSE_FAILED |
- KHUI_NC_RESPONSE_EXIT);
- break;
- }
-
- method = K4_METHOD_K524; /* only k524 is supported
- for renewals */
-
- _begin_task(0);
- cb = sizeof(idname);
- kcdb_identity_get_name(ident, idname, &cb);
- _report_mr2(KHERR_NONE, MSG_K4_RENEW_CREDS,
- _cstr(ident), _int32(method));
- _resolve();
- _describe();
- } else {
- assert(FALSE);
- break;
- }
-
- if ((method == K4_METHOD_AUTO ||
- method == K4_METHOD_K524) &&
- khui_cw_type_succeeded(nc, credtype_id_krb5)) {
-
- khm_handle tgt;
- FILETIME ft_prev;
- FILETIME ft_new;
- khm_size cb;
-
- _report_mr0(KHERR_INFO, MSG_K4_TRY_K524);
-
- tgt = khm_krb4_find_tgt(NULL, ident);
- if (tgt) {
- cb = sizeof(ft_prev);
- if (KHM_FAILED(kcdb_cred_get_attr(tgt,
- KCDB_ATTR_EXPIRE,
- NULL,
- &ft_prev,
- &cb)))
- ZeroMemory(&ft_prev, sizeof(ft_prev));
- kcdb_cred_release(tgt);
- }
-
- code = khm_convert524(ident);
-
- _reportf(L"khm_convert524 returns code %d", code);
-
- if (code == 0) {
- khui_cw_set_response(nc, credtype_id_krb4,
- KHUI_NC_RESPONSE_SUCCESS |
- KHUI_NC_RESPONSE_EXIT);
-
- if (nc->subtype == KMSG_CRED_NEW_CREDS) {
- assert(d != NULL);
-
- k4_write_identity_data(d);
-
- } else if (nc->subtype == KMSG_CRED_RENEW_CREDS &&
- (nc->ctx.scope == KHUI_SCOPE_CREDTYPE ||
- nc->ctx.scope == KHUI_SCOPE_CRED)) {
-
- khm_krb4_list_tickets();
-
- tgt = khm_krb4_find_tgt(NULL, ident);
-
- if (tgt) {
- cb = sizeof(ft_new);
- ZeroMemory(&ft_new, sizeof(ft_new));
-
- kcdb_cred_get_attr(tgt,
- KCDB_ATTR_EXPIRE,
- NULL,
- &ft_new,
- &cb);
-
- kcdb_cred_release(tgt);
- }
-
- if (!tgt ||
- CompareFileTime(&ft_new,
- &ft_prev) <= 0) {
- /* The new TGT wasn't much of an
- improvement over what we already
- had. We should go out and try to
- renew the identity now. */
-
- khui_action_context ctx;
-
- _reportf(L"Renewal of Krb4 creds failed to get a longer TGT. Triggering identity renewal");
-
- khui_context_create(&ctx,
- KHUI_SCOPE_IDENT,
- nc->ctx.identity,
- KCDB_CREDTYPE_INVALID,
- NULL);
- khui_action_trigger(KHUI_ACTION_RENEW_CRED,
- &ctx);
-
- khui_context_release(&ctx);
- }
- }
-
- _end_task();
- break;
-
- } else if (method == K4_METHOD_K524) {
- khui_cw_set_response(nc, credtype_id_krb4,
- KHUI_NC_RESPONSE_FAILED |
- KHUI_NC_RESPONSE_EXIT);
-
- if (nc->subtype == KMSG_CRED_RENEW_CREDS &&
- (nc->ctx.scope == KHUI_SCOPE_CREDTYPE ||
- nc->ctx.scope == KHUI_SCOPE_CRED)) {
- /* We were trying to get a new Krb4 TGT
- for this identity. Sometimes this
- fails because of restrictions placed on
- K524d regarding the lifetime of the
- issued K4 TGT. In this case, we
- trigger a renewal of the identity in
- the hope that the new K5 TGT will allow
- us to successfully get a new K4 TGT
- next time over using the new K5 TGT. */
-
- khui_action_context ctx;
-
- _reportf(L"Renewal of Krb4 creds failed using k524. Triggerring identity renewal.");
-
- khui_context_create(&ctx,
- KHUI_SCOPE_IDENT,
- nc->ctx.identity,
- KCDB_CREDTYPE_INVALID,
- NULL);
-
- khui_action_trigger(KHUI_ACTION_RENEW_CRED,
- &ctx);
-
- khui_context_release(&ctx);
- }
-
- _end_task();
- break;
-
- }
- }
-
- /* only supported for new credentials */
- if (method == K4_METHOD_AUTO ||
- method == K4_METHOD_PASSWORD) {
-
- khm_size n_prompts = 0;
- khm_size idx;
- khm_size cb;
- wchar_t wpwd[KHUI_MAXCCH_PROMPT_VALUE];
- char pwd[KHUI_MAXCCH_PROMPT_VALUE];
- wchar_t widname[KCDB_IDENT_MAXCCH_NAME];
- char idname[KCDB_IDENT_MAXCCH_NAME];
-
- char * aname = NULL;
- char * inst = NULL;
- char * realm = NULL;
-
- assert(nc->subtype == KMSG_CRED_NEW_CREDS);
-
- _report_mr0(KHERR_INFO, MSG_K4_TRY_PASSWORD);
-
- code = TRUE; /* just has to be non-zero */
-
- khui_cw_get_prompt_count(nc, &n_prompts);
-
- if (n_prompts == 0)
- goto _skip_pwd;
-
- for (idx = 0; idx < n_prompts; idx++) {
- khui_new_creds_prompt * p;
-
- if (KHM_FAILED(khui_cw_get_prompt(nc, idx, &p)))
- continue;
-
- if (p->type == KHUI_NCPROMPT_TYPE_PASSWORD)
- break;
- }
-
- if (idx >= n_prompts) {
- _reportf(L"Password prompt not found");
- goto _skip_pwd;
- }
-
- khui_cw_sync_prompt_values(nc);
-
- cb = sizeof(wpwd);
- if (KHM_FAILED(khui_cw_get_prompt_value(nc, idx,
- wpwd,
- &cb))) {
- _reportf(L"Failed to obtain password value");
- goto _skip_pwd;
- }
-
- UnicodeStrToAnsi(pwd, sizeof(pwd), wpwd);
-
- cb = sizeof(widname);
- kcdb_identity_get_name(ident,
- widname,
- &cb);
-
- UnicodeStrToAnsi(idname, sizeof(idname), widname);
-
- {
- char * atsign;
-
- atsign = strchr(idname, '@');
- if (atsign == NULL) {
- _reportf(L"Identity name does not contain an '@'");
- goto _skip_pwd;
- }
-
- *atsign++ = 0;
-
- realm = atsign;
- }
-
- {
- char * slash;
-
- slash = strchr(idname, '/');
- if (slash != NULL) {
- *slash++ = 0;
- inst = slash;
- } else {
- inst = "";
- }
- }
-
- aname = idname;
-
- code = khm_krb4_kinit(aname, inst, realm,
- (long) d->lifetime, pwd);
-
- _reportf(L"khm_krb4_kinit returns code %d", code);
-
- _skip_pwd:
-
- if (code) {
- khui_cw_set_response(nc, credtype_id_krb4,
- KHUI_NC_RESPONSE_EXIT |
- KHUI_NC_RESPONSE_FAILED);
-
- } else {
- khui_cw_set_response(nc, credtype_id_krb4,
- KHUI_NC_RESPONSE_EXIT |
- KHUI_NC_RESPONSE_SUCCESS);
-
- if (nc->subtype == KMSG_CRED_NEW_CREDS) {
-
- assert(d != NULL);
- k4_write_identity_data(d);
-
- }
- }
- }
-
- _end_task();
- }
- }
- break;
-
- case KMSG_CRED_END:
- {
- khui_new_creds * nc;
- khui_new_creds_by_type * nct = NULL;
-
- nc = (khui_new_creds *) vparam;
- if (KHM_FAILED(khui_cw_find_type(nc, credtype_id_krb4, &nct)))
- break;
-
- khui_cw_del_type(nc, credtype_id_krb4);
-
- if (nct->name)
- PFREE(nct->name);
-
- if (nct->credtext)
- PFREE(nct->credtext);
-
- PFREE(nct);
- }
- break;
- }
-
- return KHM_ERROR_SUCCESS;
-}
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<krbcred.h>
+#include<kherror.h>
+#include<khmsgtypes.h>
+#include<khuidefs.h>
+#include<utils.h>
+#include<commctrl.h>
+#include<strsafe.h>
+#include<krb5.h>
+#include<assert.h>
+
+/* method identifiers should be contiguous */
+#define K4_METHOD_AUTO 0
+#define K4_METHOD_PASSWORD 1
+#define K4_METHOD_K524 2
+
+int method_to_id[] = {
+ IDC_NCK4_AUTO,
+ IDC_NCK4_PWD,
+ IDC_NCK4_K524
+};
+
+typedef struct tag_k4_dlg_data {
+ HWND hwnd;
+ khui_new_creds * nc;
+ khui_new_creds_by_type * nct;
+
+ khm_boolean k4_enabled;
+ khm_int32 method;
+ time_t lifetime;
+} k4_dlg_data;
+
+void k4_update_display(k4_dlg_data * d, BOOL update_methods) {
+ CheckDlgButton(d->hwnd, IDC_NCK4_OBTAIN,
+ (d->k4_enabled)?BST_CHECKED: BST_UNCHECKED);
+
+ if (d->k4_enabled) {
+ EnableWindow(GetDlgItem(d->hwnd, IDC_NCK4_AUTO), TRUE);
+ EnableWindow(GetDlgItem(d->hwnd, IDC_NCK4_K524), TRUE);
+ EnableWindow(GetDlgItem(d->hwnd, IDC_NCK4_PWD ), TRUE);
+ } else {
+ EnableWindow(GetDlgItem(d->hwnd, IDC_NCK4_AUTO), FALSE);
+ EnableWindow(GetDlgItem(d->hwnd, IDC_NCK4_K524), FALSE);
+ EnableWindow(GetDlgItem(d->hwnd, IDC_NCK4_PWD ), FALSE);
+ }
+
+#ifdef DEBUG
+ assert(d->method >= 0 && d->method < ARRAYLENGTH(method_to_id));
+#endif
+
+ CheckRadioButton(d->hwnd, IDC_NCK4_AUTO, IDC_NCK4_PWD, method_to_id[d->method]);
+
+ khui_cw_enable_type(d->nc, credtype_id_krb4, d->k4_enabled);
+}
+
+void k4_update_data(k4_dlg_data * d) {
+ int i;
+ khm_boolean oldstate;
+
+ oldstate = d->k4_enabled;
+
+ if (IsDlgButtonChecked(d->hwnd, IDC_NCK4_OBTAIN) == BST_CHECKED)
+ d->k4_enabled = TRUE;
+ else
+ d->k4_enabled = FALSE;
+
+ if ((oldstate && !d->k4_enabled) ||
+ (!oldstate && d->k4_enabled)) {
+
+ khui_cw_enable_type(d->nc, credtype_id_krb4, d->k4_enabled);
+ }
+
+ d->method = K4_METHOD_AUTO;
+
+ for (i=K4_METHOD_AUTO; i<=K4_METHOD_K524; i++) {
+ if (IsDlgButtonChecked(d->hwnd, method_to_id[i]) == BST_CHECKED) {
+ d->method = i;
+ break;
+ }
+ }
+}
+
+khm_boolean k4_should_identity_get_k4(khm_handle ident) {
+ khm_int32 idflags = 0;
+ khm_int32 t = TRUE;
+ khm_handle csp_ident = NULL;
+ khm_handle csp_k4 = NULL;
+ khm_boolean get_k4 = TRUE;
+ khm_boolean id_spec = FALSE;
+
+ if (KHM_FAILED(kcdb_identity_get_flags(ident, &idflags)))
+ return FALSE;
+
+ if (!(idflags & KCDB_IDENT_FLAG_DEFAULT)) {
+ /* we only support k4 for one identity, and that is the
+ default identity. If we are trying to get tickets for a
+ non-default identity, then we start off as disabled unless
+ there is no default identity. */
+
+ khm_handle defident = NULL;
+
+ if (KHM_SUCCEEDED(kcdb_identity_get_default(&defident))) {
+ kcdb_identity_release(defident);
+
+ return FALSE;
+ }
+ }
+
+ if (KHM_SUCCEEDED(kcdb_identity_get_config(ident, 0, &csp_ident))) {
+ if (KHM_SUCCEEDED(khc_open_space(csp_ident, CSNAME_KRB4CRED, 0,
+ &csp_k4))) {
+ khm_int32 t = 0;
+
+ if (KHM_SUCCEEDED(khc_read_int32(csp_k4, L"Krb4NewCreds", &t))) {
+ get_k4 = !!t;
+ id_spec = TRUE;
+ }
+
+ khc_close_space(csp_k4);
+ }
+ khc_close_space(csp_ident);
+ }
+
+ /* if there was a value specified for the identity, then that
+ takes precedence. */
+ if (id_spec || !get_k4)
+ return get_k4;
+
+ if (KHM_SUCCEEDED(khc_read_int32(csp_params, L"Krb4NewCreds", &t)) &&
+ !t)
+ return FALSE;
+
+ return TRUE;
+}
+
+void k4_read_identity_data(k4_dlg_data * d) {
+ khm_handle csp_ident = NULL;
+ khm_handle csp_k4 = NULL;
+
+ khm_int32 idflags = 0;
+ khm_int32 t;
+
+ if (KHM_SUCCEEDED(khc_read_int32(csp_params, L"Krb4NewCreds", &t)))
+ d->k4_enabled = !!t;
+ else
+ d->k4_enabled = TRUE;
+
+ if (KHM_SUCCEEDED(khc_read_int32(csp_params, L"Krb4Method", &t)))
+ d->method = t;
+ else
+ d->method = K4_METHOD_AUTO;
+
+ if (KHM_SUCCEEDED(khc_read_int32(csp_params, L"DefaultLifetime", &t)))
+ d->lifetime = t;
+ else
+ d->lifetime = 10 * 60 * 60; /* 10 hours */
+
+ if (d->nc->n_identities > 0 &&
+ d->nc->identities[0]) {
+
+ if (KHM_SUCCEEDED(kcdb_identity_get_config(d->nc->identities[0],
+ 0,
+ &csp_ident))) {
+
+ khc_open_space(csp_ident, CSNAME_KRB4CRED, 0, &csp_k4);
+
+ if (csp_k4) {
+ if (KHM_SUCCEEDED(khc_read_int32(csp_k4, L"Krb4NewCreds", &t)))
+ d->k4_enabled = !!t;
+ if (KHM_SUCCEEDED(khc_read_int32(csp_k4, L"Krb4Method", &t)))
+ d->method = t;
+ khc_close_space(csp_k4);
+ }
+
+ khc_close_space(csp_ident);
+ }
+
+ if (d->k4_enabled) {
+ d->k4_enabled = k4_should_identity_get_k4(d->nc->identities[0]);
+ }
+ } else {
+ d->k4_enabled = FALSE;
+ }
+
+ if (d->method < 0 || d->method > K4_METHOD_K524)
+ d->method = K4_METHOD_AUTO;
+}
+
+void k4_write_identity_data(k4_dlg_data * d) {
+ khm_handle csp_ident = NULL;
+ khm_handle csp_k4 = NULL;
+
+ if (d->nc->n_identities > 0 &&
+ d->nc->identities[0] &&
+ KHM_SUCCEEDED(kcdb_identity_get_config(d->nc->identities[0],
+ KHM_FLAG_CREATE,
+ &csp_ident))) {
+ khc_open_space(csp_ident, CSNAME_KRB4CRED,
+ KHM_FLAG_CREATE | KCONF_FLAG_WRITEIFMOD,
+ &csp_k4);
+
+ if (csp_k4) {
+ khc_write_int32(csp_k4, L"Krb4NewCreds", !!d->k4_enabled);
+ khc_write_int32(csp_k4, L"Krb4Method", d->method);
+
+ khc_close_space(csp_k4);
+ }
+
+ khc_close_space(csp_ident);
+ }
+}
+
+void k4_handle_wmnc_notify(k4_dlg_data * d,
+ WPARAM wParam,
+ LPARAM lParam) {
+ switch(HIWORD(wParam)) {
+ case WMNC_UPDATE_CREDTEXT:
+ {
+ if (d->nct->credtext) {
+ PFREE(d->nct->credtext);
+ d->nct->credtext = NULL;
+ }
+
+ if (d->nc->n_identities > 0 &&
+ d->nc->identities[0]) {
+
+ khm_int32 flags = 0;
+ wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
+ wchar_t * atsign;
+ wchar_t * realm;
+ khm_size cb;
+
+ kcdb_identity_get_flags(d->nc->identities[0], &flags);
+
+ if (!(flags & KCDB_IDENT_FLAG_VALID)) {
+ break;
+ }
+
+ cb = sizeof(idname);
+ kcdb_identity_get_name(d->nc->identities[0], idname,
+ &cb);
+
+ atsign = wcsrchr(idname, L'@');
+
+ if (atsign == NULL || !atsign[1])
+ break;
+
+ realm = ++atsign;
+
+ if (d->k4_enabled) {
+ wchar_t wmethod[128];
+ wchar_t wfmt[128];
+ wchar_t wct[512];
+
+ LoadString(hResModule, IDS_CT_TGTFOR,
+ wfmt, ARRAYLENGTH(wfmt));
+
+ if (d->method == K4_METHOD_AUTO)
+ LoadString(hResModule, IDS_METHOD_AUTO, wmethod,
+ ARRAYLENGTH(wmethod));
+ else if (d->method == K4_METHOD_PASSWORD)
+ LoadString(hResModule, IDS_METHOD_PWD, wmethod,
+ ARRAYLENGTH(wmethod));
+ else if (d->method == K4_METHOD_K524)
+ LoadString(hResModule, IDS_METHOD_K524, wmethod,
+ ARRAYLENGTH(wmethod));
+ else {
+ assert(FALSE);
+ }
+
+ StringCbPrintf(wct, sizeof(wct), wfmt, realm, wmethod);
+
+ StringCbLength(wct, sizeof(wct), &cb);
+ cb += sizeof(wchar_t);
+
+ d->nct->credtext = PMALLOC(cb);
+
+ StringCbCopy(d->nct->credtext, cb, wct);
+ } else {
+ wchar_t wct[256];
+
+ LoadString(hResModule, IDS_CT_DISABLED,
+ wct, ARRAYLENGTH(wct));
+
+ StringCbLength(wct, sizeof(wct), &cb);
+ cb += sizeof(wchar_t);
+
+ d->nct->credtext = PMALLOC(cb);
+
+ StringCbCopy(d->nct->credtext, cb, wct);
+ }
+ }
+ /* no identities were selected. it is not the
+ responsibility of krb4 to complain about this. */
+ }
+ break;
+
+ case WMNC_IDENTITY_CHANGE:
+ k4_read_identity_data(d);
+ k4_update_display(d, TRUE);
+ break;
+
+ case WMNC_CREDTEXT_LINK:
+ {
+ wchar_t wid[KHUI_MAXCCH_HTLINK_FIELD];
+ wchar_t * wids;
+ khui_htwnd_link * l;
+
+ l = (khui_htwnd_link *) lParam;
+
+ StringCchCopyN(wid, ARRAYLENGTH(wid), l->id, l->id_len);
+ wids = wcschr(wid, L':');
+
+ if (!wids)
+ break;
+ else
+ wids++;
+
+ if (!wcscmp(wids, L"Enable")) {
+ d->k4_enabled = TRUE;
+
+ k4_update_display(d, TRUE);
+ khui_cw_enable_type(d->nc, credtype_id_krb4, TRUE);
+ }
+ }
+ break;
+ }
+}
+
+INT_PTR CALLBACK k4_nc_dlg_proc(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam) {
+
+ k4_dlg_data * d;
+
+ switch(uMsg) {
+ case WM_INITDIALOG:
+ {
+ d = PMALLOC(sizeof(*d));
+ ZeroMemory(d, sizeof(*d));
+
+ d->nc = (khui_new_creds *) lParam;
+ khui_cw_find_type(d->nc, credtype_id_krb4, &d->nct);
+
+#pragma warning(push)
+#pragma warning(disable: 4244)
+ SetWindowLongPtr(hwnd, DWLP_USER, (LPARAM) d);
+#pragma warning(pop)
+
+ d->nct->aux = (LPARAM) d;
+ d->hwnd = hwnd;
+
+ d->k4_enabled = TRUE;
+ d->method = K4_METHOD_AUTO;
+
+ k4_update_display(d, TRUE);
+ }
+ break;
+
+ case WM_COMMAND:
+ {
+ if (HIWORD(wParam) == BN_CLICKED) {
+ d = (k4_dlg_data *) (LONG_PTR)
+ GetWindowLongPtr(hwnd, DWLP_USER);
+
+ k4_update_data(d);
+
+ if (LOWORD(wParam) == IDC_NCK4_OBTAIN) {
+ k4_update_display(d, TRUE);
+ }
+
+ return TRUE;
+ }
+ }
+ break;
+
+ case KHUI_WM_NC_NOTIFY:
+ {
+ d = (k4_dlg_data *) (LONG_PTR)
+ GetWindowLongPtr(hwnd, DWLP_USER);
+ k4_handle_wmnc_notify(d, wParam, lParam);
+ }
+ break;
+
+ case WM_DESTROY:
+ {
+ d = (k4_dlg_data *) (LONG_PTR)
+ GetWindowLongPtr(hwnd, DWLP_USER);
+
+ d->nct->aux = 0;
+
+ PFREE(d);
+ }
+ break;
+ }
+
+ return FALSE;
+}
+
+khm_int32
+krb4_msg_newcred(khm_int32 msg_type, khm_int32 msg_subtype,
+ khm_ui_4 uparam, void * vparam) {
+
+ switch(msg_subtype) {
+ case KMSG_CRED_NEW_CREDS:
+ {
+ khui_new_creds * nc;
+ khui_new_creds_by_type * nct;
+ khm_size cbsize;
+ wchar_t wbuf[256];
+
+ nc = (khui_new_creds *) vparam;
+
+ nct = PMALLOC(sizeof(*nct));
+#ifdef DEBUG
+ assert(nct);
+#endif
+ ZeroMemory(nct, sizeof(*nct));
+
+ nct->type = credtype_id_krb4;
+ nct->ordinal = 3;
+ LoadString(hResModule, IDS_NC_K4_SHORT,
+ wbuf, ARRAYLENGTH(wbuf));
+ StringCbLength(wbuf, sizeof(wbuf), &cbsize);
+ cbsize += sizeof(wchar_t);
+
+ nct->name = PMALLOC(cbsize);
+ StringCbCopy(nct->name, cbsize, wbuf);
+
+ nct->type_deps[nct->n_type_deps++] = credtype_id_krb5;
+
+ nct->h_module = hResModule;
+ nct->dlg_proc = k4_nc_dlg_proc;
+ nct->dlg_template = MAKEINTRESOURCE(IDD_NC_KRB4);
+
+ khui_cw_add_type(nc, nct);
+ }
+ break;
+
+ case KMSG_CRED_RENEW_CREDS:
+ {
+ khui_new_creds * nc;
+ khui_new_creds_by_type * nct;
+ khm_size cbsize;
+ wchar_t wbuf[256];
+
+ nc = (khui_new_creds *) vparam;
+
+ if (!nc->ctx.identity)
+ break;
+
+ nct = PMALLOC(sizeof(*nct));
+#ifdef DEBUG
+ assert(nct);
+#endif
+
+ ZeroMemory(nct, sizeof(*nct));
+
+ nct->type = credtype_id_krb4;
+ nct->ordinal = 3;
+ LoadString(hResModule, IDS_NC_K4_SHORT,
+ wbuf, ARRAYLENGTH(wbuf));
+ StringCbLength(wbuf, sizeof(wbuf), &cbsize);
+ cbsize += sizeof(wchar_t);
+
+ nct->name = PMALLOC(cbsize);
+ StringCbCopy(nct->name, cbsize, wbuf);
+
+ nct->type_deps[nct->n_type_deps++] = credtype_id_krb5;
+
+ khui_cw_add_type(nc, nct);
+ }
+ break;
+
+ case KMSG_CRED_DIALOG_SETUP:
+ break;
+
+ case KMSG_CRED_PROCESS:
+ {
+ khui_new_creds * nc;
+ khui_new_creds_by_type * nct = NULL;
+ khm_handle ident = NULL;
+ k4_dlg_data * d = NULL;
+ long code = 0;
+ wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
+ khm_size cb;
+
+ nc = (khui_new_creds *) vparam;
+ if (KHM_FAILED(khui_cw_find_type(nc, credtype_id_krb4, &nct)))
+ break;
+
+ if (nc->subtype == KMSG_CRED_NEW_CREDS ||
+ nc->subtype == KMSG_CRED_RENEW_CREDS) {
+ khm_int32 method;
+
+ if (nc->subtype == KMSG_CRED_NEW_CREDS) {
+
+ d = (k4_dlg_data *) nct->aux;
+ if (!d ||
+ nc->n_identities == 0 ||
+ nc->identities[0] == NULL ||
+ nc->result != KHUI_NC_RESULT_PROCESS) {
+ khui_cw_set_response(nc, credtype_id_krb4,
+ KHUI_NC_RESPONSE_SUCCESS |
+ KHUI_NC_RESPONSE_EXIT);
+ break;
+ }
+
+ if (!d->k4_enabled) {
+ k4_write_identity_data(d);
+ khui_cw_set_response(nc, credtype_id_krb4,
+ KHUI_NC_RESPONSE_SUCCESS |
+ KHUI_NC_RESPONSE_EXIT);
+ break;
+ }
+
+ method = d->method;
+ ident = nc->identities[0];
+
+ cb = sizeof(idname);
+ kcdb_identity_get_name(ident, idname, &cb);
+ _begin_task(0);
+ _report_mr2(KHERR_NONE, MSG_K4_NEW_CREDS,
+ _cstr(ident), _int32(method));
+ _resolve();
+ _describe();
+
+ } else if (nc->subtype == KMSG_CRED_RENEW_CREDS) {
+
+ if ((nc->ctx.scope == KHUI_SCOPE_IDENT &&
+ nc->ctx.identity != NULL) ||
+
+ (nc->ctx.scope == KHUI_SCOPE_CREDTYPE &&
+ nc->ctx.cred_type == credtype_id_krb4 &&
+ nc->ctx.identity != NULL) ||
+
+ (nc->ctx.scope == KHUI_SCOPE_CRED &&
+ nc->ctx.cred_type == credtype_id_krb4 &&
+ nc->ctx.identity != NULL &&
+ nc->ctx.cred != NULL)) {
+
+ ident = nc->ctx.identity;
+
+ if (!k4_should_identity_get_k4(ident)) {
+
+ _reportf(L"Kerberos 4 is not enabled for this identity. Skipping");
+
+ khui_cw_set_response(nc, credtype_id_krb4,
+ KHUI_NC_RESPONSE_FAILED |
+ KHUI_NC_RESPONSE_EXIT);
+ break;
+ }
+
+ } else {
+
+ _reportf(L"Kerberos 4 is not within renewal scope. Skipping");
+
+ khui_cw_set_response(nc, credtype_id_krb4,
+ KHUI_NC_RESPONSE_FAILED |
+ KHUI_NC_RESPONSE_EXIT);
+ break;
+ }
+
+ method = K4_METHOD_K524; /* only k524 is supported
+ for renewals */
+
+ _begin_task(0);
+ cb = sizeof(idname);
+ kcdb_identity_get_name(ident, idname, &cb);
+ _report_mr2(KHERR_NONE, MSG_K4_RENEW_CREDS,
+ _cstr(ident), _int32(method));
+ _resolve();
+ _describe();
+ } else {
+ assert(FALSE);
+ break;
+ }
+
+ if ((method == K4_METHOD_AUTO ||
+ method == K4_METHOD_K524) &&
+ khui_cw_type_succeeded(nc, credtype_id_krb5)) {
+
+ khm_handle tgt;
+ FILETIME ft_prev;
+ FILETIME ft_new;
+ khm_size cb;
+
+ _report_mr0(KHERR_INFO, MSG_K4_TRY_K524);
+
+ tgt = khm_krb4_find_tgt(NULL, ident);
+ if (tgt) {
+ cb = sizeof(ft_prev);
+ if (KHM_FAILED(kcdb_cred_get_attr(tgt,
+ KCDB_ATTR_EXPIRE,
+ NULL,
+ &ft_prev,
+ &cb)))
+ ZeroMemory(&ft_prev, sizeof(ft_prev));
+ kcdb_cred_release(tgt);
+ }
+
+ code = khm_convert524(ident);
+
+ _reportf(L"khm_convert524 returns code %d", code);
+
+ if (code == 0) {
+ khui_cw_set_response(nc, credtype_id_krb4,
+ KHUI_NC_RESPONSE_SUCCESS |
+ KHUI_NC_RESPONSE_EXIT);
+
+ if (nc->subtype == KMSG_CRED_NEW_CREDS) {
+ assert(d != NULL);
+
+ k4_write_identity_data(d);
+
+ } else if (nc->subtype == KMSG_CRED_RENEW_CREDS &&
+ (nc->ctx.scope == KHUI_SCOPE_CREDTYPE ||
+ nc->ctx.scope == KHUI_SCOPE_CRED)) {
+
+ khm_krb4_list_tickets();
+
+ tgt = khm_krb4_find_tgt(NULL, ident);
+
+ if (tgt) {
+ cb = sizeof(ft_new);
+ ZeroMemory(&ft_new, sizeof(ft_new));
+
+ kcdb_cred_get_attr(tgt,
+ KCDB_ATTR_EXPIRE,
+ NULL,
+ &ft_new,
+ &cb);
+
+ kcdb_cred_release(tgt);
+ }
+
+ if (!tgt ||
+ CompareFileTime(&ft_new,
+ &ft_prev) <= 0) {
+ /* The new TGT wasn't much of an
+ improvement over what we already
+ had. We should go out and try to
+ renew the identity now. */
+
+ khui_action_context ctx;
+
+ _reportf(L"Renewal of Krb4 creds failed to get a longer TGT. Triggering identity renewal");
+
+ khui_context_create(&ctx,
+ KHUI_SCOPE_IDENT,
+ nc->ctx.identity,
+ KCDB_CREDTYPE_INVALID,
+ NULL);
+ khui_action_trigger(KHUI_ACTION_RENEW_CRED,
+ &ctx);
+
+ khui_context_release(&ctx);
+ }
+ }
+
+ _end_task();
+ break;
+
+ } else if (method == K4_METHOD_K524) {
+ khui_cw_set_response(nc, credtype_id_krb4,
+ KHUI_NC_RESPONSE_FAILED |
+ KHUI_NC_RESPONSE_EXIT);
+
+ if (nc->subtype == KMSG_CRED_RENEW_CREDS &&
+ (nc->ctx.scope == KHUI_SCOPE_CREDTYPE ||
+ nc->ctx.scope == KHUI_SCOPE_CRED)) {
+ /* We were trying to get a new Krb4 TGT
+ for this identity. Sometimes this
+ fails because of restrictions placed on
+ K524d regarding the lifetime of the
+ issued K4 TGT. In this case, we
+ trigger a renewal of the identity in
+ the hope that the new K5 TGT will allow
+ us to successfully get a new K4 TGT
+ next time over using the new K5 TGT. */
+
+ khui_action_context ctx;
+
+ _reportf(L"Renewal of Krb4 creds failed using k524. Triggerring identity renewal.");
+
+ khui_context_create(&ctx,
+ KHUI_SCOPE_IDENT,
+ nc->ctx.identity,
+ KCDB_CREDTYPE_INVALID,
+ NULL);
+
+ khui_action_trigger(KHUI_ACTION_RENEW_CRED,
+ &ctx);
+
+ khui_context_release(&ctx);
+ }
+
+ _end_task();
+ break;
+
+ }
+ }
+
+ /* only supported for new credentials */
+ if (method == K4_METHOD_AUTO ||
+ method == K4_METHOD_PASSWORD) {
+
+ khm_size n_prompts = 0;
+ khm_size idx;
+ khm_size cb;
+ wchar_t wpwd[KHUI_MAXCCH_PROMPT_VALUE];
+ char pwd[KHUI_MAXCCH_PROMPT_VALUE];
+ wchar_t widname[KCDB_IDENT_MAXCCH_NAME];
+ char idname[KCDB_IDENT_MAXCCH_NAME];
+
+ char * aname = NULL;
+ char * inst = NULL;
+ char * realm = NULL;
+
+ assert(nc->subtype == KMSG_CRED_NEW_CREDS);
+
+ _report_mr0(KHERR_INFO, MSG_K4_TRY_PASSWORD);
+
+ code = TRUE; /* just has to be non-zero */
+
+ khui_cw_get_prompt_count(nc, &n_prompts);
+
+ if (n_prompts == 0)
+ goto _skip_pwd;
+
+ for (idx = 0; idx < n_prompts; idx++) {
+ khui_new_creds_prompt * p;
+
+ if (KHM_FAILED(khui_cw_get_prompt(nc, idx, &p)))
+ continue;
+
+ if (p->type == KHUI_NCPROMPT_TYPE_PASSWORD)
+ break;
+ }
+
+ if (idx >= n_prompts) {
+ _reportf(L"Password prompt not found");
+ goto _skip_pwd;
+ }
+
+ khui_cw_sync_prompt_values(nc);
+
+ cb = sizeof(wpwd);
+ if (KHM_FAILED(khui_cw_get_prompt_value(nc, idx,
+ wpwd,
+ &cb))) {
+ _reportf(L"Failed to obtain password value");
+ goto _skip_pwd;
+ }
+
+ UnicodeStrToAnsi(pwd, sizeof(pwd), wpwd);
+
+ cb = sizeof(widname);
+ kcdb_identity_get_name(ident,
+ widname,
+ &cb);
+
+ UnicodeStrToAnsi(idname, sizeof(idname), widname);
+
+ {
+ char * atsign;
+
+ atsign = strchr(idname, '@');
+ if (atsign == NULL) {
+ _reportf(L"Identity name does not contain an '@'");
+ goto _skip_pwd;
+ }
+
+ *atsign++ = 0;
+
+ realm = atsign;
+ }
+
+ {
+ char * slash;
+
+ slash = strchr(idname, '/');
+ if (slash != NULL) {
+ *slash++ = 0;
+ inst = slash;
+ } else {
+ inst = "";
+ }
+ }
+
+ aname = idname;
+
+ code = khm_krb4_kinit(aname, inst, realm,
+ (long) d->lifetime, pwd);
+
+ _reportf(L"khm_krb4_kinit returns code %d", code);
+
+ _skip_pwd:
+
+ if (code) {
+ khui_cw_set_response(nc, credtype_id_krb4,
+ KHUI_NC_RESPONSE_EXIT |
+ KHUI_NC_RESPONSE_FAILED);
+
+ } else {
+ khui_cw_set_response(nc, credtype_id_krb4,
+ KHUI_NC_RESPONSE_EXIT |
+ KHUI_NC_RESPONSE_SUCCESS);
+
+ if (nc->subtype == KMSG_CRED_NEW_CREDS) {
+
+ assert(d != NULL);
+ k4_write_identity_data(d);
+
+ }
+ }
+ }
+
+ _end_task();
+ }
+ }
+ break;
+
+ case KMSG_CRED_END:
+ {
+ khui_new_creds * nc;
+ khui_new_creds_by_type * nct = NULL;
+
+ nc = (khui_new_creds *) vparam;
+ if (KHM_FAILED(khui_cw_find_type(nc, credtype_id_krb4, &nct)))
+ break;
+
+ khui_cw_del_type(nc, credtype_id_krb4);
+
+ if (nct->name)
+ PFREE(nct->name);
+
+ if (nct->credtext)
+ PFREE(nct->credtext);
+
+ PFREE(nct);
+ }
+ break;
+ }
+
+ return KHM_ERROR_SUCCESS;
+}
diff --git a/src/windows/identity/plugins/krb4/krb4plugin.c b/src/windows/identity/plugins/krb4/krb4plugin.c
index b4edd4192f..9a50249f7a 100644
--- a/src/windows/identity/plugins/krb4/krb4plugin.c
+++ b/src/windows/identity/plugins/krb4/krb4plugin.c
@@ -1,297 +1,297 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<krbcred.h>
-#include<kherror.h>
-#include<khmsgtypes.h>
-#include<khuidefs.h>
-#include<utils.h>
-#include<commctrl.h>
-#include<strsafe.h>
-#include<krb5.h>
-
-khm_int32 credtype_id_krb4 = KCDB_CREDTYPE_INVALID;
-khm_int32 credtype_id_krb5 = KCDB_CREDTYPE_INVALID;
-
-khm_boolean krb4_initialized = FALSE;
-khm_handle krb4_credset = NULL;
-
-/* Kerberos IV stuff */
-khm_int32 KHMAPI
-krb4_msg_system(khm_int32 msg_type, khm_int32 msg_subtype,
- khm_ui_4 uparam, void * vparam)
-{
- khm_int32 rv = KHM_ERROR_SUCCESS;
-
- switch(msg_subtype) {
- case KMSG_SYSTEM_INIT:
- {
-#ifdef _WIN64
- return KHM_ERROR_NOT_IMPLEMENTED;
-#else
- kcdb_credtype ct;
- wchar_t buf[KCDB_MAXCCH_SHORT_DESC];
- size_t cbsize;
- khui_config_node_reg reg;
- wchar_t wshort_desc[KHUI_MAXCCH_SHORT_DESC];
- wchar_t wlong_desc[KHUI_MAXCCH_LONG_DESC];
-
- /* perform critical registrations and initialization
- stuff */
- ZeroMemory(&ct, sizeof(ct));
- ct.id = KCDB_CREDTYPE_AUTO;
- ct.name = KRB4_CREDTYPE_NAME;
-
- if(LoadString(hResModule, IDS_KRB4_SHORT_DESC,
- buf, ARRAYLENGTH(buf)))
- {
- StringCbLength(buf, KCDB_MAXCB_SHORT_DESC, &cbsize);
- cbsize += sizeof(wchar_t);
- ct.short_desc = PMALLOC(cbsize);
- StringCbCopy(ct.short_desc, cbsize, buf);
- }
-
- /* even though ideally we should be setting limits
- based KCDB_MAXCB_LONG_DESC, our long description
- actually fits nicely in KCDB_MAXCB_SHORT_DESC */
- if(LoadString(hResModule, IDS_KRB4_LONG_DESC,
- buf, ARRAYLENGTH(buf)))
- {
- StringCbLength(buf, KCDB_MAXCB_SHORT_DESC, &cbsize);
- cbsize += sizeof(wchar_t);
- ct.long_desc = PMALLOC(cbsize);
- StringCbCopy(ct.long_desc, cbsize, buf);
- }
-
- ct.icon = NULL; /* TODO: set a proper icon */
- kmq_create_subscription(krb4_cb, &ct.sub);
-
- rv = kcdb_credtype_register(&ct, &credtype_id_krb4);
-
- if(KHM_SUCCEEDED(rv))
- rv = kcdb_credset_create(&krb4_credset);
-
- if (KHM_SUCCEEDED(rv))
- rv = kcdb_credtype_get_id(KRB5_CREDTYPE_NAME,
- &credtype_id_krb5);
-
- if(ct.short_desc)
- PFREE(ct.short_desc);
-
- if(ct.long_desc)
- PFREE(ct.long_desc);
-
- if (KHM_SUCCEEDED(rv)) {
- khui_config_node idents;
-
- ZeroMemory(&reg, sizeof(reg));
-
- reg.name = KRB4_CONFIG_NODE_NAME;
- reg.short_desc = wshort_desc;
- reg.long_desc = wlong_desc;
- reg.h_module = hResModule;
- reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_KRB4);
- reg.dlg_proc = krb4_confg_proc;
- reg.flags = 0;
-
- LoadString(hResModule, IDS_CFG_KRB4_LONG,
- wlong_desc, ARRAYLENGTH(wlong_desc));
- LoadString(hResModule, IDS_CFG_KRB4_SHORT,
- wshort_desc, ARRAYLENGTH(wshort_desc));
-
- khui_cfg_register(NULL, &reg);
-
- khui_cfg_open(NULL, L"KhmIdentities", &idents);
-
- ZeroMemory(&reg, sizeof(reg));
-
- reg.name = KRB4_IDS_CONFIG_NODE_NAME;
- reg.short_desc = wshort_desc;
- reg.long_desc = wlong_desc;
- reg.h_module = hResModule;
- reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_IDS_KRB4);
- reg.dlg_proc = krb4_ids_config_proc;
- reg.flags = KHUI_CNFLAG_SUBPANEL;
-
- LoadString(hResModule, IDS_CFG_KRB4_SHORT,
- wlong_desc, ARRAYLENGTH(wlong_desc));
- LoadString(hResModule, IDS_CFG_KRB4_SHORT,
- wshort_desc, ARRAYLENGTH(wshort_desc));
-
- khui_cfg_register(idents, &reg);
-
- ZeroMemory(&reg, sizeof(reg));
-
- reg.name = KRB4_ID_CONFIG_NODE_NAME;
- reg.short_desc = wshort_desc;
- reg.long_desc = wlong_desc;
- reg.h_module = hResModule;
- reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_ID_KRB4);
- reg.dlg_proc = krb4_id_config_proc;
- reg.flags = KHUI_CNFLAG_SUBPANEL | KHUI_CNFLAG_PLURAL;
-
- LoadString(hResModule, IDS_CFG_KRB4_SHORT,
- wlong_desc, ARRAYLENGTH(wlong_desc));
- LoadString(hResModule, IDS_CFG_KRB4_SHORT,
- wshort_desc, ARRAYLENGTH(wshort_desc));
-
- khui_cfg_register(idents, &reg);
-
- khui_cfg_release(idents);
-
- }
-
- /* Lookup common data types */
- if(KHM_FAILED(kcdb_type_get_id(TYPENAME_ENCTYPE,
- &type_id_enctype))) {
- rv = KHM_ERROR_UNKNOWN;
- }
-
- if(KHM_FAILED(kcdb_type_get_id(TYPENAME_ADDR_LIST,
- &type_id_addr_list))) {
- rv = KHM_ERROR_UNKNOWN;
- }
-
- if(KHM_FAILED(kcdb_type_get_id(TYPENAME_KRB5_FLAGS,
- &type_id_krb5_flags))) {
- rv = KHM_ERROR_UNKNOWN;
- }
-
- /* Lookup common attributes */
- if(KHM_FAILED(kcdb_attrib_get_id(ATTRNAME_KEY_ENCTYPE,
- &attr_id_key_enctype))) {
- rv = KHM_ERROR_UNKNOWN;
- }
-
- if(KHM_FAILED(kcdb_attrib_get_id(ATTRNAME_TKT_ENCTYPE,
- &attr_id_tkt_enctype))) {
- rv = KHM_ERROR_UNKNOWN;
- }
-
- if(KHM_FAILED(kcdb_attrib_get_id(ATTRNAME_ADDR_LIST,
- &attr_id_addr_list))) {
- rv = KHM_ERROR_UNKNOWN;
- }
-
- if(KHM_FAILED(kcdb_attrib_get_id(ATTRNAME_KRB5_FLAGS,
- &attr_id_krb5_flags))) {
- rv = KHM_ERROR_UNKNOWN;
- }
-
- krb4_initialized = TRUE;
-
- khm_krb4_set_def_tkt_string();
-
- khm_krb4_list_tickets();
-#endif
- }
- break;
-
- case KMSG_SYSTEM_EXIT:
-#ifdef _WIN64
- /* See above. On 64-bit platforms, we don't support Krb4 at
- all. */
- return 0;
-#else
- if(credtype_id_krb4 >= 0)
- {
- /* basically just unregister the credential type */
- kcdb_credtype_unregister(credtype_id_krb4);
-
- kcdb_credset_delete(krb4_credset);
- }
- break;
-#endif
- }
-
- return rv;
-}
-
-khm_int32 KHMAPI
-krb4_msg_cred(khm_int32 msg_type, khm_int32 msg_subtype,
- khm_ui_4 uparam, void * vparam)
-{
- khm_int32 rv = KHM_ERROR_SUCCESS;
-
- switch(msg_subtype) {
- case KMSG_CRED_REFRESH:
- {
- khm_krb4_list_tickets();
- }
- break;
-
- case KMSG_CRED_DESTROY_CREDS:
- {
- khui_action_context * ctx;
- khm_handle credset;
- khm_size nc_root = 0;
- khm_size nc_sel = 0;
-
- ctx = (khui_action_context *) vparam;
-
- /* if all krb4 tickets are selected, then we destroy all
- of them. Otherwise, we do nothing. */
-
- kcdb_credset_create(&credset);
-
- kcdb_credset_extract(credset, ctx->credset,
- NULL, credtype_id_krb4);
- kcdb_credset_get_size(credset, &nc_sel);
-
- kcdb_credset_flush(credset);
-
- kcdb_credset_extract(credset, NULL,
- NULL, credtype_id_krb4);
- kcdb_credset_get_size(credset, &nc_root);
-
- kcdb_credset_delete(credset);
-
- if (nc_root == nc_sel) {
- khm_krb4_kdestroy();
- }
- }
- break;
-
- default:
- if (IS_CRED_ACQ_MSG(msg_subtype))
- return krb4_msg_newcred(msg_type, msg_subtype, uparam, vparam);
- }
-
- return rv;
-}
-
-khm_int32 KHMAPI
-krb4_cb(khm_int32 msg_type, khm_int32 msg_subtype,
- khm_ui_4 uparam, void * vparam)
-{
- switch(msg_type) {
- case KMSG_SYSTEM:
- return krb4_msg_system(msg_type, msg_subtype, uparam, vparam);
- case KMSG_CRED:
- return krb4_msg_cred(msg_type, msg_subtype, uparam, vparam);
- }
- return KHM_ERROR_SUCCESS;
-}
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<krbcred.h>
+#include<kherror.h>
+#include<khmsgtypes.h>
+#include<khuidefs.h>
+#include<utils.h>
+#include<commctrl.h>
+#include<strsafe.h>
+#include<krb5.h>
+
+khm_int32 credtype_id_krb4 = KCDB_CREDTYPE_INVALID;
+khm_int32 credtype_id_krb5 = KCDB_CREDTYPE_INVALID;
+
+khm_boolean krb4_initialized = FALSE;
+khm_handle krb4_credset = NULL;
+
+/* Kerberos IV stuff */
+khm_int32 KHMAPI
+krb4_msg_system(khm_int32 msg_type, khm_int32 msg_subtype,
+ khm_ui_4 uparam, void * vparam)
+{
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+
+ switch(msg_subtype) {
+ case KMSG_SYSTEM_INIT:
+ {
+#ifdef _WIN64
+ return KHM_ERROR_NOT_IMPLEMENTED;
+#else
+ kcdb_credtype ct;
+ wchar_t buf[KCDB_MAXCCH_SHORT_DESC];
+ size_t cbsize;
+ khui_config_node_reg reg;
+ wchar_t wshort_desc[KHUI_MAXCCH_SHORT_DESC];
+ wchar_t wlong_desc[KHUI_MAXCCH_LONG_DESC];
+
+ /* perform critical registrations and initialization
+ stuff */
+ ZeroMemory(&ct, sizeof(ct));
+ ct.id = KCDB_CREDTYPE_AUTO;
+ ct.name = KRB4_CREDTYPE_NAME;
+
+ if(LoadString(hResModule, IDS_KRB4_SHORT_DESC,
+ buf, ARRAYLENGTH(buf)))
+ {
+ StringCbLength(buf, KCDB_MAXCB_SHORT_DESC, &cbsize);
+ cbsize += sizeof(wchar_t);
+ ct.short_desc = PMALLOC(cbsize);
+ StringCbCopy(ct.short_desc, cbsize, buf);
+ }
+
+ /* even though ideally we should be setting limits
+ based KCDB_MAXCB_LONG_DESC, our long description
+ actually fits nicely in KCDB_MAXCB_SHORT_DESC */
+ if(LoadString(hResModule, IDS_KRB4_LONG_DESC,
+ buf, ARRAYLENGTH(buf)))
+ {
+ StringCbLength(buf, KCDB_MAXCB_SHORT_DESC, &cbsize);
+ cbsize += sizeof(wchar_t);
+ ct.long_desc = PMALLOC(cbsize);
+ StringCbCopy(ct.long_desc, cbsize, buf);
+ }
+
+ ct.icon = NULL; /* TODO: set a proper icon */
+ kmq_create_subscription(krb4_cb, &ct.sub);
+
+ rv = kcdb_credtype_register(&ct, &credtype_id_krb4);
+
+ if(KHM_SUCCEEDED(rv))
+ rv = kcdb_credset_create(&krb4_credset);
+
+ if (KHM_SUCCEEDED(rv))
+ rv = kcdb_credtype_get_id(KRB5_CREDTYPE_NAME,
+ &credtype_id_krb5);
+
+ if(ct.short_desc)
+ PFREE(ct.short_desc);
+
+ if(ct.long_desc)
+ PFREE(ct.long_desc);
+
+ if (KHM_SUCCEEDED(rv)) {
+ khui_config_node idents;
+
+ ZeroMemory(&reg, sizeof(reg));
+
+ reg.name = KRB4_CONFIG_NODE_NAME;
+ reg.short_desc = wshort_desc;
+ reg.long_desc = wlong_desc;
+ reg.h_module = hResModule;
+ reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_KRB4);
+ reg.dlg_proc = krb4_confg_proc;
+ reg.flags = 0;
+
+ LoadString(hResModule, IDS_CFG_KRB4_LONG,
+ wlong_desc, ARRAYLENGTH(wlong_desc));
+ LoadString(hResModule, IDS_CFG_KRB4_SHORT,
+ wshort_desc, ARRAYLENGTH(wshort_desc));
+
+ khui_cfg_register(NULL, &reg);
+
+ khui_cfg_open(NULL, L"KhmIdentities", &idents);
+
+ ZeroMemory(&reg, sizeof(reg));
+
+ reg.name = KRB4_IDS_CONFIG_NODE_NAME;
+ reg.short_desc = wshort_desc;
+ reg.long_desc = wlong_desc;
+ reg.h_module = hResModule;
+ reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_IDS_KRB4);
+ reg.dlg_proc = krb4_ids_config_proc;
+ reg.flags = KHUI_CNFLAG_SUBPANEL;
+
+ LoadString(hResModule, IDS_CFG_KRB4_SHORT,
+ wlong_desc, ARRAYLENGTH(wlong_desc));
+ LoadString(hResModule, IDS_CFG_KRB4_SHORT,
+ wshort_desc, ARRAYLENGTH(wshort_desc));
+
+ khui_cfg_register(idents, &reg);
+
+ ZeroMemory(&reg, sizeof(reg));
+
+ reg.name = KRB4_ID_CONFIG_NODE_NAME;
+ reg.short_desc = wshort_desc;
+ reg.long_desc = wlong_desc;
+ reg.h_module = hResModule;
+ reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_ID_KRB4);
+ reg.dlg_proc = krb4_id_config_proc;
+ reg.flags = KHUI_CNFLAG_SUBPANEL | KHUI_CNFLAG_PLURAL;
+
+ LoadString(hResModule, IDS_CFG_KRB4_SHORT,
+ wlong_desc, ARRAYLENGTH(wlong_desc));
+ LoadString(hResModule, IDS_CFG_KRB4_SHORT,
+ wshort_desc, ARRAYLENGTH(wshort_desc));
+
+ khui_cfg_register(idents, &reg);
+
+ khui_cfg_release(idents);
+
+ }
+
+ /* Lookup common data types */
+ if(KHM_FAILED(kcdb_type_get_id(TYPENAME_ENCTYPE,
+ &type_id_enctype))) {
+ rv = KHM_ERROR_UNKNOWN;
+ }
+
+ if(KHM_FAILED(kcdb_type_get_id(TYPENAME_ADDR_LIST,
+ &type_id_addr_list))) {
+ rv = KHM_ERROR_UNKNOWN;
+ }
+
+ if(KHM_FAILED(kcdb_type_get_id(TYPENAME_KRB5_FLAGS,
+ &type_id_krb5_flags))) {
+ rv = KHM_ERROR_UNKNOWN;
+ }
+
+ /* Lookup common attributes */
+ if(KHM_FAILED(kcdb_attrib_get_id(ATTRNAME_KEY_ENCTYPE,
+ &attr_id_key_enctype))) {
+ rv = KHM_ERROR_UNKNOWN;
+ }
+
+ if(KHM_FAILED(kcdb_attrib_get_id(ATTRNAME_TKT_ENCTYPE,
+ &attr_id_tkt_enctype))) {
+ rv = KHM_ERROR_UNKNOWN;
+ }
+
+ if(KHM_FAILED(kcdb_attrib_get_id(ATTRNAME_ADDR_LIST,
+ &attr_id_addr_list))) {
+ rv = KHM_ERROR_UNKNOWN;
+ }
+
+ if(KHM_FAILED(kcdb_attrib_get_id(ATTRNAME_KRB5_FLAGS,
+ &attr_id_krb5_flags))) {
+ rv = KHM_ERROR_UNKNOWN;
+ }
+
+ krb4_initialized = TRUE;
+
+ khm_krb4_set_def_tkt_string();
+
+ khm_krb4_list_tickets();
+#endif
+ }
+ break;
+
+ case KMSG_SYSTEM_EXIT:
+#ifdef _WIN64
+ /* See above. On 64-bit platforms, we don't support Krb4 at
+ all. */
+ return 0;
+#else
+ if(credtype_id_krb4 >= 0)
+ {
+ /* basically just unregister the credential type */
+ kcdb_credtype_unregister(credtype_id_krb4);
+
+ kcdb_credset_delete(krb4_credset);
+ }
+ break;
+#endif
+ }
+
+ return rv;
+}
+
+khm_int32 KHMAPI
+krb4_msg_cred(khm_int32 msg_type, khm_int32 msg_subtype,
+ khm_ui_4 uparam, void * vparam)
+{
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+
+ switch(msg_subtype) {
+ case KMSG_CRED_REFRESH:
+ {
+ khm_krb4_list_tickets();
+ }
+ break;
+
+ case KMSG_CRED_DESTROY_CREDS:
+ {
+ khui_action_context * ctx;
+ khm_handle credset;
+ khm_size nc_root = 0;
+ khm_size nc_sel = 0;
+
+ ctx = (khui_action_context *) vparam;
+
+ /* if all krb4 tickets are selected, then we destroy all
+ of them. Otherwise, we do nothing. */
+
+ kcdb_credset_create(&credset);
+
+ kcdb_credset_extract(credset, ctx->credset,
+ NULL, credtype_id_krb4);
+ kcdb_credset_get_size(credset, &nc_sel);
+
+ kcdb_credset_flush(credset);
+
+ kcdb_credset_extract(credset, NULL,
+ NULL, credtype_id_krb4);
+ kcdb_credset_get_size(credset, &nc_root);
+
+ kcdb_credset_delete(credset);
+
+ if (nc_root == nc_sel) {
+ khm_krb4_kdestroy();
+ }
+ }
+ break;
+
+ default:
+ if (IS_CRED_ACQ_MSG(msg_subtype))
+ return krb4_msg_newcred(msg_type, msg_subtype, uparam, vparam);
+ }
+
+ return rv;
+}
+
+khm_int32 KHMAPI
+krb4_cb(khm_int32 msg_type, khm_int32 msg_subtype,
+ khm_ui_4 uparam, void * vparam)
+{
+ switch(msg_type) {
+ case KMSG_SYSTEM:
+ return krb4_msg_system(msg_type, msg_subtype, uparam, vparam);
+ case KMSG_CRED:
+ return krb4_msg_cred(msg_type, msg_subtype, uparam, vparam);
+ }
+ return KHM_ERROR_SUCCESS;
+}
diff --git a/src/windows/identity/plugins/krb4/krbcred.h b/src/windows/identity/plugins/krb4/krbcred.h
index 7c3b31a133..53e22c8929 100644
--- a/src/windows/identity/plugins/krb4/krbcred.h
+++ b/src/windows/identity/plugins/krb4/krbcred.h
@@ -1,136 +1,136 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#ifndef __KHIMAIRA_KRBAFSCRED_H
-#define __KHIMAIRA_KRBAFSCRED_H
-
-#include<windows.h>
-
-#define KHERR_FACILITY L"Krb4Cred"
-#define KHERR_FACILITY_ID 65
-#define KHERR_HMODULE hResModule
-
-#include<netidmgr.h>
-
-#include<krb4funcs.h>
-#include<krb5common.h>
-#include<errorfuncs.h>
-#include<dynimport.h>
-
-#include<langres.h>
-#include<krb4_msgs.h>
-
-#define TYPENAME_ENCTYPE L"EncType"
-#define TYPENAME_ADDR_LIST L"AddrList"
-#define TYPENAME_KRB5_FLAGS L"Krb5Flags"
-
-#define ATTRNAME_KEY_ENCTYPE L"KeyEncType"
-#define ATTRNAME_TKT_ENCTYPE L"TktEncType"
-#define ATTRNAME_ADDR_LIST L"AddrList"
-#define ATTRNAME_KRB5_FLAGS L"Krb5Flags"
-#define ATTRNAME_RENEW_TILL L"RenewTill"
-#define ATTRNAME_RENEW_FOR L"RenewFor"
-
-void init_krb();
-void exit_krb();
-KHMEXP khm_int32 KHMAPI init_module(kmm_module h_module);
-KHMEXP khm_int32 KHMAPI exit_module(kmm_module h_module);
-
-/* globals */
-extern kmm_module h_khModule;
-extern HMODULE hResModule;
-extern HINSTANCE hInstance;
-
-extern khm_int32 type_id_enctype;
-extern khm_int32 type_id_addr_list;
-extern khm_int32 type_id_krb5_flags;
-
-extern khm_int32 attr_id_key_enctype;
-extern khm_int32 attr_id_tkt_enctype;
-extern khm_int32 attr_id_addr_list;
-extern khm_int32 attr_id_krb5_flags;
-extern khm_int32 attr_id_renew_till;
-extern khm_int32 attr_id_renew_for;
-
-/* Configuration spaces */
-#define CSNAME_KRB4CRED L"Krb4Cred"
-#define CSNAME_PARAMS L"Parameters"
-
-/* plugin constants */
-#define KRB4_PLUGIN_NAME L"Krb4Cred"
-
-#define KRB4_PLUGIN_DEPS L"Krb5Cred\0"
-
-#define KRB4_CREDTYPE_NAME L"Krb4Cred"
-
-#define KRB5_CREDTYPE_NAME L"Krb5Cred"
-
-#define KRB4_CONFIG_NODE_NAME L"Krb4Config"
-
-#define KRB4_ID_CONFIG_NODE_NAME L"Krb4IdentConfig"
-#define KRB4_IDS_CONFIG_NODE_NAME L"Krb4IdentsConfig"
-
-extern khm_handle csp_plugins;
-extern khm_handle csp_krbcred;
-extern khm_handle csp_params;
-
-extern kconf_schema schema_krbconfig[];
-
-/* other globals */
-extern khm_int32 credtype_id_krb4;
-extern khm_int32 credtype_id_krb5;
-
-extern khm_boolean krb4_initialized;
-
-extern khm_handle krb4_credset;
-
-/* plugin callbacks */
-khm_int32 KHMAPI
-krb4_cb(khm_int32 msg_type, khm_int32 msg_subtype,
- khm_ui_4 uparam, void * vparam);
-
-INT_PTR CALLBACK
-krb4_confg_proc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam);
-
-INT_PTR CALLBACK
-krb4_ids_config_proc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam);
-
-INT_PTR CALLBACK
-krb4_id_config_proc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam);
-
-khm_int32
-krb4_msg_newcred(khm_int32 msg_type, khm_int32 msg_subtype,
- khm_ui_4 uparam, void * vparam);
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __KHIMAIRA_KRBAFSCRED_H
+#define __KHIMAIRA_KRBAFSCRED_H
+
+#include<windows.h>
+
+#define KHERR_FACILITY L"Krb4Cred"
+#define KHERR_FACILITY_ID 65
+#define KHERR_HMODULE hResModule
+
+#include<netidmgr.h>
+
+#include<krb4funcs.h>
+#include<krb5common.h>
+#include<errorfuncs.h>
+#include<dynimport.h>
+
+#include<langres.h>
+#include<krb4_msgs.h>
+
+#define TYPENAME_ENCTYPE L"EncType"
+#define TYPENAME_ADDR_LIST L"AddrList"
+#define TYPENAME_KRB5_FLAGS L"Krb5Flags"
+
+#define ATTRNAME_KEY_ENCTYPE L"KeyEncType"
+#define ATTRNAME_TKT_ENCTYPE L"TktEncType"
+#define ATTRNAME_ADDR_LIST L"AddrList"
+#define ATTRNAME_KRB5_FLAGS L"Krb5Flags"
+#define ATTRNAME_RENEW_TILL L"RenewTill"
+#define ATTRNAME_RENEW_FOR L"RenewFor"
+
+void init_krb();
+void exit_krb();
+KHMEXP khm_int32 KHMAPI init_module(kmm_module h_module);
+KHMEXP khm_int32 KHMAPI exit_module(kmm_module h_module);
+
+/* globals */
+extern kmm_module h_khModule;
+extern HMODULE hResModule;
+extern HINSTANCE hInstance;
+
+extern khm_int32 type_id_enctype;
+extern khm_int32 type_id_addr_list;
+extern khm_int32 type_id_krb5_flags;
+
+extern khm_int32 attr_id_key_enctype;
+extern khm_int32 attr_id_tkt_enctype;
+extern khm_int32 attr_id_addr_list;
+extern khm_int32 attr_id_krb5_flags;
+extern khm_int32 attr_id_renew_till;
+extern khm_int32 attr_id_renew_for;
+
+/* Configuration spaces */
+#define CSNAME_KRB4CRED L"Krb4Cred"
+#define CSNAME_PARAMS L"Parameters"
+
+/* plugin constants */
+#define KRB4_PLUGIN_NAME L"Krb4Cred"
+
+#define KRB4_PLUGIN_DEPS L"Krb5Cred\0"
+
+#define KRB4_CREDTYPE_NAME L"Krb4Cred"
+
+#define KRB5_CREDTYPE_NAME L"Krb5Cred"
+
+#define KRB4_CONFIG_NODE_NAME L"Krb4Config"
+
+#define KRB4_ID_CONFIG_NODE_NAME L"Krb4IdentConfig"
+#define KRB4_IDS_CONFIG_NODE_NAME L"Krb4IdentsConfig"
+
+extern khm_handle csp_plugins;
+extern khm_handle csp_krbcred;
+extern khm_handle csp_params;
+
+extern kconf_schema schema_krbconfig[];
+
+/* other globals */
+extern khm_int32 credtype_id_krb4;
+extern khm_int32 credtype_id_krb5;
+
+extern khm_boolean krb4_initialized;
+
+extern khm_handle krb4_credset;
+
+/* plugin callbacks */
+khm_int32 KHMAPI
+krb4_cb(khm_int32 msg_type, khm_int32 msg_subtype,
+ khm_ui_4 uparam, void * vparam);
+
+INT_PTR CALLBACK
+krb4_confg_proc(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam);
+
+INT_PTR CALLBACK
+krb4_ids_config_proc(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam);
+
+INT_PTR CALLBACK
+krb4_id_config_proc(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam);
+
+khm_int32
+krb4_msg_newcred(khm_int32 msg_type, khm_int32 msg_subtype,
+ khm_ui_4 uparam, void * vparam);
+#endif
diff --git a/src/windows/identity/plugins/krb4/langres.h b/src/windows/identity/plugins/krb4/langres.h
index c78ae41674..5c0e46f9aa 100644
--- a/src/windows/identity/plugins/krb4/langres.h
+++ b/src/windows/identity/plugins/krb4/langres.h
@@ -1,49 +1,49 @@
-//{{NO_DEPENDENCIES}}
-// Microsoft Visual C++ generated include file.
-// Used by C:\work\pismere\athena\auth\krb5\src\windows\identity\plugins\krb4\lang\en_us\langres.rc
-//
-#define IDD_NC_KRB4 103
-#define IDS_PLUGIN_DESC 103
-#define IDD_CFG_KRB4 104
-#define IDS_NC_K4_SHORT 104
-#define IDS_ERR_REALM 105
-#define IDD_CFG_IDS_KRB4 105
-#define IDS_ERR_PRINCIPAL 106
-#define IDD_CFG_ID_KRB4 106
-#define IDS_ERR_INVINST 107
-#define IDI_PLUGIN 107
-#define IDS_ERR_PWINTKT 108
-#define IDS_CT_DISABLED 109
-#define IDS_CT_TGTFOR 110
-#define IDS_METHOD_AUTO 111
-#define IDS_METHOD_PWD 112
-#define IDS_METHOD_K524 113
-#define IDS_CFG_IDS_KRB4_SHORT 114
-#define IDS_KRB4_SHORT_DESC 128
-#define IDS_KRB4_LONG_DESC 129
-#define IDS_CFG_KRB4_LONG 135
-#define IDS_CFG_KRB4_SHORT 136
-#define IDC_CFG_LBL_CACHE 1025
-#define IDC_CFG_LBL_CFGFILE 1026
-#define IDC_CFG_LBL_RLMPATH 1027
-#define IDC_CFG_CACHE 1028
-#define IDC_CFG_CFGPATH 1029
-#define IDC_CFG_RLMPATH 1030
-#define IDC_CFG_CFGBROW 1031
-#define IDC_CFG_RLMBROW 1032
-#define IDC_NCK4_OBTAIN 1033
-#define IDC_NCK4_AUTO 1034
-#define IDC_NCK4_K524 1035
-#define IDC_NCK4_PWD 1036
-#define IDC_CFG_GETTIX 1037
-
-// Next default values for new objects
-//
-#ifdef APSTUDIO_INVOKED
-#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE 108
-#define _APS_NEXT_COMMAND_VALUE 40001
-#define _APS_NEXT_CONTROL_VALUE 1043
-#define _APS_NEXT_SYMED_VALUE 101
-#endif
-#endif
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by C:\work\pismere\athena\auth\krb5\src\windows\identity\plugins\krb4\lang\en_us\langres.rc
+//
+#define IDD_NC_KRB4 103
+#define IDS_PLUGIN_DESC 103
+#define IDD_CFG_KRB4 104
+#define IDS_NC_K4_SHORT 104
+#define IDS_ERR_REALM 105
+#define IDD_CFG_IDS_KRB4 105
+#define IDS_ERR_PRINCIPAL 106
+#define IDD_CFG_ID_KRB4 106
+#define IDS_ERR_INVINST 107
+#define IDI_PLUGIN 107
+#define IDS_ERR_PWINTKT 108
+#define IDS_CT_DISABLED 109
+#define IDS_CT_TGTFOR 110
+#define IDS_METHOD_AUTO 111
+#define IDS_METHOD_PWD 112
+#define IDS_METHOD_K524 113
+#define IDS_CFG_IDS_KRB4_SHORT 114
+#define IDS_KRB4_SHORT_DESC 128
+#define IDS_KRB4_LONG_DESC 129
+#define IDS_CFG_KRB4_LONG 135
+#define IDS_CFG_KRB4_SHORT 136
+#define IDC_CFG_LBL_CACHE 1025
+#define IDC_CFG_LBL_CFGFILE 1026
+#define IDC_CFG_LBL_RLMPATH 1027
+#define IDC_CFG_CACHE 1028
+#define IDC_CFG_CFGPATH 1029
+#define IDC_CFG_RLMPATH 1030
+#define IDC_CFG_CFGBROW 1031
+#define IDC_CFG_RLMBROW 1032
+#define IDC_NCK4_OBTAIN 1033
+#define IDC_NCK4_AUTO 1034
+#define IDC_NCK4_K524 1035
+#define IDC_NCK4_PWD 1036
+#define IDC_CFG_GETTIX 1037
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 108
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1043
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/src/windows/identity/plugins/krb5/datarep.c b/src/windows/identity/plugins/krb5/datarep.c
index 92eabf4daa..5c292e4780 100644
--- a/src/windows/identity/plugins/krb5/datarep.c
+++ b/src/windows/identity/plugins/krb5/datarep.c
@@ -1,407 +1,407 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-/* Data representation and related functions */
-
-#include<winsock2.h>
-#include<krbcred.h>
-#include<krb5.h>
-#include<kherror.h>
-#include<strsafe.h>
-#include<assert.h>
-
-khm_int32 KHMAPI
-enctype_toString(const void * data, khm_size cbdata,
- wchar_t *destbuf, khm_size *pcbdestbuf,
- khm_int32 flags)
-{
- int resid = 0;
- int etype;
- wchar_t buf[256];
- size_t cblength;
-
- if(cbdata != sizeof(khm_int32))
- return KHM_ERROR_INVALID_PARAM;
-
- etype = *((khm_int32 *) data);
-
- switch(etype) {
- case ENCTYPE_NULL:
- resid = IDS_ETYPE_NULL;
- break;
-
- case ENCTYPE_DES_CBC_CRC:
- resid = IDS_ETYPE_DES_CBC_CRC;
- break;
-
- case ENCTYPE_DES_CBC_MD4:
- resid = IDS_ETYPE_DES_CBC_MD4;
- break;
-
- case ENCTYPE_DES_CBC_MD5:
- resid = IDS_ETYPE_DES_CBC_MD5;
- break;
-
- case ENCTYPE_DES_CBC_RAW:
- resid = IDS_ETYPE_DES_CBC_RAW;
- break;
-
- case ENCTYPE_DES3_CBC_SHA:
- resid = IDS_ETYPE_DES3_CBC_SHA;
- break;
-
- case ENCTYPE_DES3_CBC_RAW:
- resid = IDS_ETYPE_DES3_CBC_RAW;
- break;
-
- case ENCTYPE_DES_HMAC_SHA1:
- resid = IDS_ETYPE_DES_HMAC_SHA1;
- break;
-
- case ENCTYPE_DES3_CBC_SHA1:
- resid = IDS_ETYPE_DES3_CBC_SHA1;
- break;
-
- case ENCTYPE_AES128_CTS_HMAC_SHA1_96:
- resid = IDS_ETYPE_AES128_CTS_HMAC_SHA1_96;
- break;
-
- case ENCTYPE_AES256_CTS_HMAC_SHA1_96:
- resid = IDS_ETYPE_AES256_CTS_HMAC_SHA1_96;
- break;
-
- case ENCTYPE_ARCFOUR_HMAC:
- resid = IDS_ETYPE_ARCFOUR_HMAC;
- break;
-
- case ENCTYPE_ARCFOUR_HMAC_EXP:
- resid = IDS_ETYPE_ARCFOUR_HMAC_EXP;
- break;
-
- case ENCTYPE_UNKNOWN:
- resid = IDS_ETYPE_UNKNOWN;
- break;
-
-#if 0
- case ENCTYPE_LOCAL_DES3_HMAC_SHA1:
- resid = IDS_ETYPE_LOCAL_DES3_HMAC_SHA1;
- break;
-
- case ENCTYPE_LOCAL_RC4_MD4:
- resid = IDS_ETYPE_LOCAL_RC4_MD4;
- break;
-#endif
- }
-
- if(resid != 0) {
- LoadString(hResModule, (UINT) resid, buf, ARRAYLENGTH(buf));
- } else {
- StringCbPrintf(buf, sizeof(buf), L"#%d", etype);
- }
-
- StringCbLength(buf, ARRAYLENGTH(buf), &cblength);
- cblength += sizeof(wchar_t);
-
- if(!destbuf || *pcbdestbuf < cblength) {
- *pcbdestbuf = cblength;
- return KHM_ERROR_TOO_LONG;
- } else {
- StringCbCopy(destbuf, *pcbdestbuf, buf);
- *pcbdestbuf = cblength;
- return KHM_ERROR_SUCCESS;
- }
-}
-
-khm_int32 KHMAPI
-addr_list_comp(const void *d1, khm_size cb_d1,
- const void *d2, khm_size cb_d2)
-{
- if (cb_d1 < cb_d2)
- return -1;
- if (cb_d1 > cb_d2)
- return 1;
- return memcmp(d1, d2, cb_d1);
-}
-
-khm_int32 KHMAPI
-addr_list_toString(const void *d, khm_size cb_d,
- wchar_t *buf, khm_size *pcb_buf,
- khm_int32 flags)
-{
- wchar_t tbuf[2048];
- wchar_t * strpos;
- khm_size cbleft;
- size_t t;
- k5_serial_address * addrs;
-
- if (cb_d == 0 || d == NULL) {
- tbuf[0] = L'\0';
- } else {
- addrs = (k5_serial_address *) d;
-
- strpos = tbuf;
- cbleft = sizeof(tbuf);
- tbuf[0] = L'\0';
-
- while (TRUE) {
- if (cb_d < sizeof(*addrs) ||
- addrs->magic != K5_SERIAL_ADDRESS_MAGIC ||
- cb_d < sizeof(*addrs) + addrs->length - sizeof(khm_int32))
- break;
-
- if (strpos != tbuf) {
- if (FAILED(StringCbCatEx(strpos, cbleft, L" ",
- &strpos, &cbleft,
- 0)))
- break;
- }
-
-#ifdef DEBUG
- assert(*strpos == L'\0');
-#endif
-
- one_addr(addrs, strpos, cbleft);
-
- t = 0;
- if (FAILED(StringCchLength(strpos,
- cbleft / sizeof(wchar_t),
- &t)))
- break;
-
- strpos += t;
- cbleft -= t * sizeof(wchar_t);
-
- t = sizeof(*addrs) + addrs->length - sizeof(khm_int32);
- addrs = (k5_serial_address *) BYTEOFFSET(addrs, t);
- cb_d -= t;
- }
- }
-
- StringCbLength(tbuf, sizeof(tbuf), &t);
-
- if (!buf || *pcb_buf < t) {
- *pcb_buf = t;
- return KHM_ERROR_TOO_LONG;
- }
-
- StringCbCopy(buf, *pcb_buf, tbuf);
- *pcb_buf = t;
-
- return KHM_ERROR_SUCCESS;
-}
-
-khm_int32 KHMAPI
-krb5flags_toString(const void *d,
- khm_size cb_d,
- wchar_t *buf,
- khm_size *pcb_buf,
- khm_int32 f)
-{
- wchar_t sbuf[32];
- int i = 0;
- khm_size cb;
- khm_int32 flags;
-
- flags = *((khm_int32 *) d);
-
- if (flags & TKT_FLG_FORWARDABLE)
- sbuf[i++] = L'F';
-
- if (flags & TKT_FLG_FORWARDED)
- sbuf[i++] = L'f';
-
- if (flags & TKT_FLG_PROXIABLE)
- sbuf[i++] = L'P';
-
- if (flags & TKT_FLG_PROXY)
- sbuf[i++] = L'p';
-
- if (flags & TKT_FLG_MAY_POSTDATE)
- sbuf[i++] = L'D';
-
- if (flags & TKT_FLG_POSTDATED)
- sbuf[i++] = L'd';
-
- if (flags & TKT_FLG_INVALID)
- sbuf[i++] = L'i';
-
- if (flags & TKT_FLG_RENEWABLE)
- sbuf[i++] = L'R';
-
- if (flags & TKT_FLG_INITIAL)
- sbuf[i++] = L'I';
-
- if (flags & TKT_FLG_HW_AUTH)
- sbuf[i++] = L'H';
-
- if (flags & TKT_FLG_PRE_AUTH)
- sbuf[i++] = L'A';
-
- sbuf[i++] = L'\0';
-
- cb = i * sizeof(wchar_t);
-
- if (!buf || *pcb_buf < cb) {
- *pcb_buf = cb;
- return KHM_ERROR_TOO_LONG;
- } else {
- StringCbCopy(buf, *pcb_buf, sbuf);
- *pcb_buf = cb;
- return KHM_ERROR_SUCCESS;
- }
-}
-
-khm_int32 KHMAPI
-kvno_toString(const void * data, khm_size cbdata,
- wchar_t *destbuf, khm_size *pcbdestbuf,
- khm_int32 flags)
-{
- int resid = 0;
- int kvno;
- wchar_t buf[256];
- size_t cblength;
-
- if (cbdata != sizeof(khm_int32))
- return KHM_ERROR_INVALID_PARAM;
-
- kvno = *((khm_int32 *) data);
-
- StringCbPrintf(buf, sizeof(buf), L"#%d", kvno);
-
- StringCbLength(buf, ARRAYLENGTH(buf), &cblength);
- cblength += sizeof(wchar_t);
-
- if (!destbuf || *pcbdestbuf < cblength) {
- *pcbdestbuf = cblength;
- return KHM_ERROR_TOO_LONG;
- } else {
- StringCbCopy(destbuf, *pcbdestbuf, buf);
- *pcbdestbuf = cblength;
- return KHM_ERROR_SUCCESS;
- }
-}
-
-khm_int32
-serialize_krb5_addresses(krb5_address ** a, void * buf, size_t * pcbbuf)
-{
- k5_serial_address * addr;
- khm_size cb_req;
- khm_size t;
- khm_boolean overflow = FALSE;
-
- addr = (k5_serial_address *) buf;
- cb_req = 0;
-
- for(; *a; a++) {
- t = sizeof(k5_serial_address) + (*a)->length - sizeof(khm_int32);
- cb_req += t;
- if (cb_req < *pcbbuf) {
- addr->magic = K5_SERIAL_ADDRESS_MAGIC;
- addr->addrtype = (*a)->addrtype;
- addr->length = (*a)->length;
- memcpy(&addr->data, (*a)->contents, (*a)->length);
-
- addr = (k5_serial_address *) BYTEOFFSET(addr, t);
- } else {
- overflow = TRUE;
- }
- }
-
- *pcbbuf = cb_req;
-
- return (overflow)?KHM_ERROR_TOO_LONG: KHM_ERROR_SUCCESS;
-}
-
-void
-one_addr(k5_serial_address *a, wchar_t * buf, khm_size cbbuf)
-{
- wchar_t retstr[256];
- struct hostent *h = NULL;
- int no_resolve = 1;
-
- retstr[0] = L'\0';
-
- if ((a->addrtype == ADDRTYPE_INET && a->length == 4)
-#ifdef AF_INET6
- || (a->addrtype == ADDRTYPE_INET6 && a->length == 16)
-#endif
- )
- {
- int af = AF_INET;
-#ifdef AF_INET6
- if (a->addrtype == ADDRTYPE_INET6)
- af = AF_INET6;
-#endif
- if (!no_resolve) {
-#ifdef HAVE_GETIPNODEBYADDR
- int err;
- h = getipnodebyaddr(&a->data, a->length, af, &err);
- if (h) {
- StringCbPrintf(retstr, sizeof(retstr), L"%S", h->h_name);
- freehostent(h);
- }
- else
- h = gethostbyaddr(&a->data, a->length, af);
- if (h) {
- StringCbPrintf(retstr, sizeof(retstr), L"%S", h->h_name);
- }
-#endif
- if (h)
- goto _copy_string;
- }
- if (no_resolve || !h) {
-#ifdef HAVE_INET_NTOP
- char buf[46];
- const char *name = inet_ntop(a->addrtype, &a->data, buf, sizeof(buf));
- if (name) {
- StringCbPrintf(retstr, sizeof(retstr), L"%S", name);
- goto _copy_string;
- }
-#else
- if (a->addrtype == ADDRTYPE_INET) {
- khm_ui_4 addr = a->data;
- StringCbPrintf(retstr, sizeof(retstr),
- L"%d.%d.%d.%d",
- (int) (addr & 0xff),
- (int) ((addr >> 8) & 0xff),
- (int) ((addr >> 16)& 0xff),
- (int) ((addr >> 24)& 0xff));
- goto _copy_string;
- }
-#endif
- }
- }
-
- {
- wchar_t tmpfmt[128];
- LoadString(hResModule, IDS_UNK_ADDR_FMT, tmpfmt, sizeof(tmpfmt)/sizeof(wchar_t));
- StringCbPrintf(retstr, sizeof(retstr), tmpfmt, a->addrtype);
- }
-
- _copy_string:
- StringCbCopy(buf, cbbuf, retstr);
-}
-
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+/* Data representation and related functions */
+
+#include<winsock2.h>
+#include<krbcred.h>
+#include<krb5.h>
+#include<kherror.h>
+#include<strsafe.h>
+#include<assert.h>
+
+khm_int32 KHMAPI
+enctype_toString(const void * data, khm_size cbdata,
+ wchar_t *destbuf, khm_size *pcbdestbuf,
+ khm_int32 flags)
+{
+ int resid = 0;
+ int etype;
+ wchar_t buf[256];
+ size_t cblength;
+
+ if(cbdata != sizeof(khm_int32))
+ return KHM_ERROR_INVALID_PARAM;
+
+ etype = *((khm_int32 *) data);
+
+ switch(etype) {
+ case ENCTYPE_NULL:
+ resid = IDS_ETYPE_NULL;
+ break;
+
+ case ENCTYPE_DES_CBC_CRC:
+ resid = IDS_ETYPE_DES_CBC_CRC;
+ break;
+
+ case ENCTYPE_DES_CBC_MD4:
+ resid = IDS_ETYPE_DES_CBC_MD4;
+ break;
+
+ case ENCTYPE_DES_CBC_MD5:
+ resid = IDS_ETYPE_DES_CBC_MD5;
+ break;
+
+ case ENCTYPE_DES_CBC_RAW:
+ resid = IDS_ETYPE_DES_CBC_RAW;
+ break;
+
+ case ENCTYPE_DES3_CBC_SHA:
+ resid = IDS_ETYPE_DES3_CBC_SHA;
+ break;
+
+ case ENCTYPE_DES3_CBC_RAW:
+ resid = IDS_ETYPE_DES3_CBC_RAW;
+ break;
+
+ case ENCTYPE_DES_HMAC_SHA1:
+ resid = IDS_ETYPE_DES_HMAC_SHA1;
+ break;
+
+ case ENCTYPE_DES3_CBC_SHA1:
+ resid = IDS_ETYPE_DES3_CBC_SHA1;
+ break;
+
+ case ENCTYPE_AES128_CTS_HMAC_SHA1_96:
+ resid = IDS_ETYPE_AES128_CTS_HMAC_SHA1_96;
+ break;
+
+ case ENCTYPE_AES256_CTS_HMAC_SHA1_96:
+ resid = IDS_ETYPE_AES256_CTS_HMAC_SHA1_96;
+ break;
+
+ case ENCTYPE_ARCFOUR_HMAC:
+ resid = IDS_ETYPE_ARCFOUR_HMAC;
+ break;
+
+ case ENCTYPE_ARCFOUR_HMAC_EXP:
+ resid = IDS_ETYPE_ARCFOUR_HMAC_EXP;
+ break;
+
+ case ENCTYPE_UNKNOWN:
+ resid = IDS_ETYPE_UNKNOWN;
+ break;
+
+#if 0
+ case ENCTYPE_LOCAL_DES3_HMAC_SHA1:
+ resid = IDS_ETYPE_LOCAL_DES3_HMAC_SHA1;
+ break;
+
+ case ENCTYPE_LOCAL_RC4_MD4:
+ resid = IDS_ETYPE_LOCAL_RC4_MD4;
+ break;
+#endif
+ }
+
+ if(resid != 0) {
+ LoadString(hResModule, (UINT) resid, buf, ARRAYLENGTH(buf));
+ } else {
+ StringCbPrintf(buf, sizeof(buf), L"#%d", etype);
+ }
+
+ StringCbLength(buf, ARRAYLENGTH(buf), &cblength);
+ cblength += sizeof(wchar_t);
+
+ if(!destbuf || *pcbdestbuf < cblength) {
+ *pcbdestbuf = cblength;
+ return KHM_ERROR_TOO_LONG;
+ } else {
+ StringCbCopy(destbuf, *pcbdestbuf, buf);
+ *pcbdestbuf = cblength;
+ return KHM_ERROR_SUCCESS;
+ }
+}
+
+khm_int32 KHMAPI
+addr_list_comp(const void *d1, khm_size cb_d1,
+ const void *d2, khm_size cb_d2)
+{
+ if (cb_d1 < cb_d2)
+ return -1;
+ if (cb_d1 > cb_d2)
+ return 1;
+ return memcmp(d1, d2, cb_d1);
+}
+
+khm_int32 KHMAPI
+addr_list_toString(const void *d, khm_size cb_d,
+ wchar_t *buf, khm_size *pcb_buf,
+ khm_int32 flags)
+{
+ wchar_t tbuf[2048];
+ wchar_t * strpos;
+ khm_size cbleft;
+ size_t t;
+ k5_serial_address * addrs;
+
+ if (cb_d == 0 || d == NULL) {
+ tbuf[0] = L'\0';
+ } else {
+ addrs = (k5_serial_address *) d;
+
+ strpos = tbuf;
+ cbleft = sizeof(tbuf);
+ tbuf[0] = L'\0';
+
+ while (TRUE) {
+ if (cb_d < sizeof(*addrs) ||
+ addrs->magic != K5_SERIAL_ADDRESS_MAGIC ||
+ cb_d < sizeof(*addrs) + addrs->length - sizeof(khm_int32))
+ break;
+
+ if (strpos != tbuf) {
+ if (FAILED(StringCbCatEx(strpos, cbleft, L" ",
+ &strpos, &cbleft,
+ 0)))
+ break;
+ }
+
+#ifdef DEBUG
+ assert(*strpos == L'\0');
+#endif
+
+ one_addr(addrs, strpos, cbleft);
+
+ t = 0;
+ if (FAILED(StringCchLength(strpos,
+ cbleft / sizeof(wchar_t),
+ &t)))
+ break;
+
+ strpos += t;
+ cbleft -= t * sizeof(wchar_t);
+
+ t = sizeof(*addrs) + addrs->length - sizeof(khm_int32);
+ addrs = (k5_serial_address *) BYTEOFFSET(addrs, t);
+ cb_d -= t;
+ }
+ }
+
+ StringCbLength(tbuf, sizeof(tbuf), &t);
+
+ if (!buf || *pcb_buf < t) {
+ *pcb_buf = t;
+ return KHM_ERROR_TOO_LONG;
+ }
+
+ StringCbCopy(buf, *pcb_buf, tbuf);
+ *pcb_buf = t;
+
+ return KHM_ERROR_SUCCESS;
+}
+
+khm_int32 KHMAPI
+krb5flags_toString(const void *d,
+ khm_size cb_d,
+ wchar_t *buf,
+ khm_size *pcb_buf,
+ khm_int32 f)
+{
+ wchar_t sbuf[32];
+ int i = 0;
+ khm_size cb;
+ khm_int32 flags;
+
+ flags = *((khm_int32 *) d);
+
+ if (flags & TKT_FLG_FORWARDABLE)
+ sbuf[i++] = L'F';
+
+ if (flags & TKT_FLG_FORWARDED)
+ sbuf[i++] = L'f';
+
+ if (flags & TKT_FLG_PROXIABLE)
+ sbuf[i++] = L'P';
+
+ if (flags & TKT_FLG_PROXY)
+ sbuf[i++] = L'p';
+
+ if (flags & TKT_FLG_MAY_POSTDATE)
+ sbuf[i++] = L'D';
+
+ if (flags & TKT_FLG_POSTDATED)
+ sbuf[i++] = L'd';
+
+ if (flags & TKT_FLG_INVALID)
+ sbuf[i++] = L'i';
+
+ if (flags & TKT_FLG_RENEWABLE)
+ sbuf[i++] = L'R';
+
+ if (flags & TKT_FLG_INITIAL)
+ sbuf[i++] = L'I';
+
+ if (flags & TKT_FLG_HW_AUTH)
+ sbuf[i++] = L'H';
+
+ if (flags & TKT_FLG_PRE_AUTH)
+ sbuf[i++] = L'A';
+
+ sbuf[i++] = L'\0';
+
+ cb = i * sizeof(wchar_t);
+
+ if (!buf || *pcb_buf < cb) {
+ *pcb_buf = cb;
+ return KHM_ERROR_TOO_LONG;
+ } else {
+ StringCbCopy(buf, *pcb_buf, sbuf);
+ *pcb_buf = cb;
+ return KHM_ERROR_SUCCESS;
+ }
+}
+
+khm_int32 KHMAPI
+kvno_toString(const void * data, khm_size cbdata,
+ wchar_t *destbuf, khm_size *pcbdestbuf,
+ khm_int32 flags)
+{
+ int resid = 0;
+ int kvno;
+ wchar_t buf[256];
+ size_t cblength;
+
+ if (cbdata != sizeof(khm_int32))
+ return KHM_ERROR_INVALID_PARAM;
+
+ kvno = *((khm_int32 *) data);
+
+ StringCbPrintf(buf, sizeof(buf), L"#%d", kvno);
+
+ StringCbLength(buf, ARRAYLENGTH(buf), &cblength);
+ cblength += sizeof(wchar_t);
+
+ if (!destbuf || *pcbdestbuf < cblength) {
+ *pcbdestbuf = cblength;
+ return KHM_ERROR_TOO_LONG;
+ } else {
+ StringCbCopy(destbuf, *pcbdestbuf, buf);
+ *pcbdestbuf = cblength;
+ return KHM_ERROR_SUCCESS;
+ }
+}
+
+khm_int32
+serialize_krb5_addresses(krb5_address ** a, void * buf, size_t * pcbbuf)
+{
+ k5_serial_address * addr;
+ khm_size cb_req;
+ khm_size t;
+ khm_boolean overflow = FALSE;
+
+ addr = (k5_serial_address *) buf;
+ cb_req = 0;
+
+ for(; *a; a++) {
+ t = sizeof(k5_serial_address) + (*a)->length - sizeof(khm_int32);
+ cb_req += t;
+ if (cb_req < *pcbbuf) {
+ addr->magic = K5_SERIAL_ADDRESS_MAGIC;
+ addr->addrtype = (*a)->addrtype;
+ addr->length = (*a)->length;
+ memcpy(&addr->data, (*a)->contents, (*a)->length);
+
+ addr = (k5_serial_address *) BYTEOFFSET(addr, t);
+ } else {
+ overflow = TRUE;
+ }
+ }
+
+ *pcbbuf = cb_req;
+
+ return (overflow)?KHM_ERROR_TOO_LONG: KHM_ERROR_SUCCESS;
+}
+
+void
+one_addr(k5_serial_address *a, wchar_t * buf, khm_size cbbuf)
+{
+ wchar_t retstr[256];
+ struct hostent *h = NULL;
+ int no_resolve = 1;
+
+ retstr[0] = L'\0';
+
+ if ((a->addrtype == ADDRTYPE_INET && a->length == 4)
+#ifdef AF_INET6
+ || (a->addrtype == ADDRTYPE_INET6 && a->length == 16)
+#endif
+ )
+ {
+ int af = AF_INET;
+#ifdef AF_INET6
+ if (a->addrtype == ADDRTYPE_INET6)
+ af = AF_INET6;
+#endif
+ if (!no_resolve) {
+#ifdef HAVE_GETIPNODEBYADDR
+ int err;
+ h = getipnodebyaddr(&a->data, a->length, af, &err);
+ if (h) {
+ StringCbPrintf(retstr, sizeof(retstr), L"%S", h->h_name);
+ freehostent(h);
+ }
+ else
+ h = gethostbyaddr(&a->data, a->length, af);
+ if (h) {
+ StringCbPrintf(retstr, sizeof(retstr), L"%S", h->h_name);
+ }
+#endif
+ if (h)
+ goto _copy_string;
+ }
+ if (no_resolve || !h) {
+#ifdef HAVE_INET_NTOP
+ char buf[46];
+ const char *name = inet_ntop(a->addrtype, &a->data, buf, sizeof(buf));
+ if (name) {
+ StringCbPrintf(retstr, sizeof(retstr), L"%S", name);
+ goto _copy_string;
+ }
+#else
+ if (a->addrtype == ADDRTYPE_INET) {
+ khm_ui_4 addr = a->data;
+ StringCbPrintf(retstr, sizeof(retstr),
+ L"%d.%d.%d.%d",
+ (int) (addr & 0xff),
+ (int) ((addr >> 8) & 0xff),
+ (int) ((addr >> 16)& 0xff),
+ (int) ((addr >> 24)& 0xff));
+ goto _copy_string;
+ }
+#endif
+ }
+ }
+
+ {
+ wchar_t tmpfmt[128];
+ LoadString(hResModule, IDS_UNK_ADDR_FMT, tmpfmt, sizeof(tmpfmt)/sizeof(wchar_t));
+ StringCbPrintf(retstr, sizeof(retstr), tmpfmt, a->addrtype);
+ }
+
+ _copy_string:
+ StringCbCopy(buf, cbbuf, retstr);
+}
+
diff --git a/src/windows/identity/plugins/krb5/datarep.h b/src/windows/identity/plugins/krb5/datarep.h
index 90f1923fa0..d81e7b91e9 100644
--- a/src/windows/identity/plugins/krb5/datarep.h
+++ b/src/windows/identity/plugins/krb5/datarep.h
@@ -1,76 +1,76 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#ifndef __KHIMAIRA_KRB_DATAREP_H
-#define __KHIMAIRA_KRB_DATAREP_H
-
-typedef struct tag_k5_serial_address {
- khm_int32 magic; /* should be K5_SERIAL_ADDRESS_MAGIC */
- khm_int32 addrtype; /* Address type. We only know what to
- do with ADDRTYPE_INET and
- ADDRTYPE_INET6 */
- khm_size length; /* number of bytes of data in [data].
- This should always be greater than
- sizeof(khm_int32) */
- khm_int32 data; /* actually, &data is the beginning of
- the data buffer that is [length]
- bytes long. */
-} k5_serial_address;
-
-#define K5_SERIAL_ADDRESS_MAGIC 0x44ce832d
-
-khm_int32 KHMAPI
-enctype_toString(const void * data, khm_size cbdata,
- wchar_t *destbuf, khm_size *pcbdestbuf,
- khm_int32 flags);
-
-khm_int32 KHMAPI
-addr_list_comp(const void *d1, khm_size cb_d1,
- const void *d2, khm_size cb_d2);
-
-khm_int32 KHMAPI
-addr_list_toString(const void *, khm_size, wchar_t *,
- khm_size *, khm_int32);
-
-khm_int32 KHMAPI
-krb5flags_toString(const void *, khm_size, wchar_t *,
- khm_size *, khm_int32);
-
-khm_int32 KHMAPI
-kvno_toString(const void * data, khm_size cbdata,
- wchar_t *destbuf, khm_size *pcbdestbuf,
- khm_int32 flags);
-
-khm_int32 KHMAPI
-renew_for_cb(khm_handle cred, khm_int32 id, void * buffer,
- khm_size * pcbsize);
-
-khm_int32
-serialize_krb5_addresses(krb5_address ** a, void * buf, size_t * pcbbuf);
-
-void
-one_addr(k5_serial_address *a, wchar_t * buf, khm_size cbbuf);
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __KHIMAIRA_KRB_DATAREP_H
+#define __KHIMAIRA_KRB_DATAREP_H
+
+typedef struct tag_k5_serial_address {
+ khm_int32 magic; /* should be K5_SERIAL_ADDRESS_MAGIC */
+ khm_int32 addrtype; /* Address type. We only know what to
+ do with ADDRTYPE_INET and
+ ADDRTYPE_INET6 */
+ khm_size length; /* number of bytes of data in [data].
+ This should always be greater than
+ sizeof(khm_int32) */
+ khm_int32 data; /* actually, &data is the beginning of
+ the data buffer that is [length]
+ bytes long. */
+} k5_serial_address;
+
+#define K5_SERIAL_ADDRESS_MAGIC 0x44ce832d
+
+khm_int32 KHMAPI
+enctype_toString(const void * data, khm_size cbdata,
+ wchar_t *destbuf, khm_size *pcbdestbuf,
+ khm_int32 flags);
+
+khm_int32 KHMAPI
+addr_list_comp(const void *d1, khm_size cb_d1,
+ const void *d2, khm_size cb_d2);
+
+khm_int32 KHMAPI
+addr_list_toString(const void *, khm_size, wchar_t *,
+ khm_size *, khm_int32);
+
+khm_int32 KHMAPI
+krb5flags_toString(const void *, khm_size, wchar_t *,
+ khm_size *, khm_int32);
+
+khm_int32 KHMAPI
+kvno_toString(const void * data, khm_size cbdata,
+ wchar_t *destbuf, khm_size *pcbdestbuf,
+ khm_int32 flags);
+
+khm_int32 KHMAPI
+renew_for_cb(khm_handle cred, khm_int32 id, void * buffer,
+ khm_size * pcbsize);
+
+khm_int32
+serialize_krb5_addresses(krb5_address ** a, void * buf, size_t * pcbbuf);
+
+void
+one_addr(k5_serial_address *a, wchar_t * buf, khm_size cbbuf);
+#endif
diff --git a/src/windows/identity/plugins/krb5/errorfuncs.c b/src/windows/identity/plugins/krb5/errorfuncs.c
index f631b3c0ce..4c2d78c630 100644
--- a/src/windows/identity/plugins/krb5/errorfuncs.c
+++ b/src/windows/identity/plugins/krb5/errorfuncs.c
@@ -1,297 +1,297 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<krbcred.h>
-#include<kherror.h>
-
-extern void (__cdecl *pinitialize_krb_error_func)();
-extern void (__cdecl *pinitialize_kadm_error_table)();
-
-
-khm_int32 init_error_funcs()
-{
- return KHM_ERROR_SUCCESS;
-}
-
-khm_int32 exit_error_funcs()
-{
- return KHM_ERROR_SUCCESS;
-}
-
-#ifdef DEPRECATED_REMOVABLE
-HWND GetRootParent (HWND Child)
-{
- HWND Last;
- while (Child)
- {
- Last = Child;
- Child = GetParent (Child);
- }
- return Last;
-}
-#endif
-
-void khm_err_describe(long code, wchar_t * buf, khm_size cbbuf,
- DWORD * suggestion,
- kherr_suggestion * suggest_code)
-{
- const char * com_err_msg;
- int offset;
- long table_num;
- DWORD msg_id = 0;
- DWORD sugg_id = 0;
- kherr_suggestion sugg_code = KHERR_SUGGEST_NONE;
-
- if (suggestion == NULL || buf == NULL || cbbuf == 0 || suggest_code == 0)
- return;
-
- *buf = L'\0';
-
- offset = (int) (code & 255);
- table_num = code - offset;
- com_err_msg = perror_message(code);
-
- *suggestion = 0;
- *suggest_code = KHERR_SUGGEST_NONE;
-
- if (WSABASEERR <= code && code < (WSABASEERR + 1064)) {
- /* winsock error */
- table_num = WSABASEERR;
- offset = code - WSABASEERR;
- }
-
- switch(table_num)
- {
- case krb_err_base:
- case kadm_err_base:
- case WSABASEERR:
- break;
- default:
-
- if (code == KRB5KRB_AP_ERR_BAD_INTEGRITY) {
- *suggestion = MSG_ERR_S_INTEGRITY;
- }
- *suggest_code = KHERR_SUGGEST_RETRY;
- AnsiStrToUnicode(buf, cbbuf, com_err_msg);
- return;
- }
-
- if (table_num == krb_err_base) {
- switch(offset) {
- case KDC_NAME_EXP: /* 001 Principal expired */
- case KDC_SERVICE_EXP: /* 002 Service expired */
- case KDC_AUTH_EXP: /* 003 Auth expired */
- case KDC_PKT_VER: /* 004 Protocol version unknown */
- case KDC_P_MKEY_VER: /* 005 Wrong master key version */
- case KDC_S_MKEY_VER: /* 006 Wrong master key version */
- case KDC_BYTE_ORDER: /* 007 Byte order unknown */
- case KDC_PR_N_UNIQUE: /* 009 Principal not unique */
- case KDC_NULL_KEY: /* 010 Principal has null key */
- case KDC_GEN_ERR: /* 011 Generic error from KDC */
- case INTK_W_NOTALL : /* 061 Not ALL tickets returned */
- case INTK_PROT : /* 063 Protocol Error */
- case INTK_ERR : /* 070 Other error */
- msg_id = MSG_ERR_UNKNOWN;
- sugg_code = KHERR_SUGGEST_RETRY;
- break;
-
- case KDC_PR_UNKNOWN: /* 008 Principal unknown */
- msg_id = MSG_ERR_PR_UNKNOWN;
- sugg_code = KHERR_SUGGEST_RETRY;
- break;
- case GC_TKFIL : /* 021 Can't read ticket file */
- case GC_NOTKT : /* 022 Can't find ticket or TGT */
- msg_id = MSG_ERR_TKFIL;
- sugg_id = MSG_ERR_S_TKFIL;
- sugg_code = KHERR_SUGGEST_RETRY;
- break;
- case MK_AP_TGTEXP : /* 026 TGT Expired */
- /* no extra error msg */
- break;
-
- case RD_AP_TIME : /* 037 delta_t too big */
- msg_id = MSG_ERR_CLOCKSKEW;
- sugg_id = MSG_ERR_S_CLOCKSKEW;
- sugg_code = KHERR_SUGGEST_RETRY;
- break;
-
- case RD_AP_UNDEC : /* 031 Can't decode
- authenticator */
- case RD_AP_EXP : /* 032 Ticket expired */
- case RD_AP_NYV : /* 033 Ticket not yet valid */
- case RD_AP_REPEAT : /* 034 Repeated request */
- case RD_AP_NOT_US : /* 035 The ticket isn't for us */
- case RD_AP_INCON : /* 036 Request is inconsistent */
- case RD_AP_BADD : /* 038 Incorrect net address */
- case RD_AP_VERSION : /* 039 protocol version mismatch */
- case RD_AP_MSG_TYPE : /* 040 invalid msg type */
- case RD_AP_MODIFIED : /* 041 message stream modified */
- case RD_AP_ORDER : /* 042 message out of order */
- case RD_AP_UNAUTHOR : /* 043 unauthorized request */
- /* no extra error msg */
- sugg_code = KHERR_SUGGEST_RETRY;
- break;
-
- case GT_PW_NULL: /* 51 Current PW is null */
- case GT_PW_BADPW: /* 52 Incorrect current password */
- case GT_PW_PROT: /* 53 Protocol Error */
- case GT_PW_KDCERR: /* 54 Error returned by KDC */
- case GT_PW_NULLTKT: /* 55 Null tkt returned by KDC */
- /* no error msg yet */
- sugg_code = KHERR_SUGGEST_RETRY;
- break;
-
- /* Values returned by send_to_kdc */
- case SKDC_RETRY : /* 56 Retry count exceeded */
- case SKDC_CANT : /* 57 Can't send request */
- msg_id = MSG_ERR_KDC_CONTACT;
- break;
- /* no error message on purpose: */
- case INTK_BADPW : /* 062 Incorrect password */
- sugg_code = KHERR_SUGGEST_RETRY;
- break;
- default:
- /* no extra error msg */
- break;
- }
- } else if (table_num == kadm_err_base) {
- switch(code) {
- case KADM_INSECURE_PW:
- /* if( kadm_info != NULL ){
- * wsprintf(buf, "%s\n%s", com_err_msg, kadm_info);
- * } else {
- * wsprintf(buf, "%s\nPlease see the help file for information "
- * "about secure passwords.", com_err_msg);
- * }
- * com_err_msg = buf;
- */
-
- /* The above code would be preferred since it allows site
- * specific information to be delivered from the Kerberos
- * server. However the message box is too small for VGA
- * screens. It does work well if we only have to support
- * 1024x768
- */
-
- msg_id = MSG_ERR_INSECURE_PW;
- sugg_code = KHERR_SUGGEST_RETRY;
- break;
-
- default:
- /* no extra error msg */
- break;
- }
- } else if (table_num == WSABASEERR) {
- switch(code) {
- case WSAENETDOWN:
- msg_id = MSG_ERR_NETDOWN;
- sugg_id = MSG_ERR_S_NETRETRY;
- sugg_code = KHERR_SUGGEST_RETRY;
- break;
-
- case WSATRY_AGAIN:
- msg_id = MSG_ERR_TEMPDOWN;
- sugg_id = MSG_ERR_S_TEMPDOWN;
- sugg_code = KHERR_SUGGEST_RETRY;
- break;
-
- case WSAENETUNREACH:
- case WSAENETRESET:
- case WSAECONNABORTED:
- case WSAECONNRESET:
- case WSAETIMEDOUT:
- case WSAECONNREFUSED:
- case WSAEHOSTDOWN:
- case WSAEHOSTUNREACH:
- msg_id = MSG_ERR_NOHOST;
- sugg_id = MSG_ERR_S_NOHOST;
- sugg_code = KHERR_SUGGEST_RETRY;
- break;
- }
- }
-
- if (msg_id != 0) {
- FormatMessage(FORMAT_MESSAGE_FROM_HMODULE |
- FORMAT_MESSAGE_IGNORE_INSERTS,
- KHERR_HMODULE,
- msg_id,
- 0,
- buf,
- (int) (cbbuf / sizeof(buf[0])),
- NULL);
- }
-
- if (sugg_id != 0) {
- *suggestion = sugg_id;
- }
-
- if (sugg_code != KHERR_SUGGEST_NONE)
- *suggest_code = sugg_code;
-}
-
-#ifdef DEPRECATED_REMOVABLE
-int lsh_com_err_proc (LPSTR whoami, long code,
- LPSTR fmt, va_list args)
-{
- int retval;
- HWND hOldFocus;
- char buf[1024], *cp;
- WORD mbformat = MB_OK | MB_ICONEXCLAMATION;
-
- cp = buf;
- memset(buf, '\0', sizeof(buf));
- cp[0] = '\0';
-
- if (code)
- {
- err_describe(buf, code);
- while (*cp)
- cp++;
- }
-
- if (fmt)
- {
- if (fmt[0] == '%' && fmt[1] == 'b')
- {
- fmt += 2;
- mbformat = va_arg(args, WORD);
- /* if the first arg is a %b, we use it for the message
- box MB_??? flags. */
- }
- if (code)
- {
- *cp++ = '\n';
- *cp++ = '\n';
- }
- wvsprintfA((LPSTR)cp, fmt, args);
- }
- hOldFocus = GetFocus();
- retval = MessageBoxA(/*GetRootParent(hOldFocus)*/NULL, buf, whoami,
- mbformat | MB_ICONHAND | MB_TASKMODAL);
- SetFocus(hOldFocus);
- return retval;
-}
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<krbcred.h>
+#include<kherror.h>
+
+extern void (__cdecl *pinitialize_krb_error_func)();
+extern void (__cdecl *pinitialize_kadm_error_table)();
+
+
+khm_int32 init_error_funcs()
+{
+ return KHM_ERROR_SUCCESS;
+}
+
+khm_int32 exit_error_funcs()
+{
+ return KHM_ERROR_SUCCESS;
+}
+
+#ifdef DEPRECATED_REMOVABLE
+HWND GetRootParent (HWND Child)
+{
+ HWND Last;
+ while (Child)
+ {
+ Last = Child;
+ Child = GetParent (Child);
+ }
+ return Last;
+}
+#endif
+
+void khm_err_describe(long code, wchar_t * buf, khm_size cbbuf,
+ DWORD * suggestion,
+ kherr_suggestion * suggest_code)
+{
+ const char * com_err_msg;
+ int offset;
+ long table_num;
+ DWORD msg_id = 0;
+ DWORD sugg_id = 0;
+ kherr_suggestion sugg_code = KHERR_SUGGEST_NONE;
+
+ if (suggestion == NULL || buf == NULL || cbbuf == 0 || suggest_code == 0)
+ return;
+
+ *buf = L'\0';
+
+ offset = (int) (code & 255);
+ table_num = code - offset;
+ com_err_msg = perror_message(code);
+
+ *suggestion = 0;
+ *suggest_code = KHERR_SUGGEST_NONE;
+
+ if (WSABASEERR <= code && code < (WSABASEERR + 1064)) {
+ /* winsock error */
+ table_num = WSABASEERR;
+ offset = code - WSABASEERR;
+ }
+
+ switch(table_num)
+ {
+ case krb_err_base:
+ case kadm_err_base:
+ case WSABASEERR:
+ break;
+ default:
+
+ if (code == KRB5KRB_AP_ERR_BAD_INTEGRITY) {
+ *suggestion = MSG_ERR_S_INTEGRITY;
+ }
+ *suggest_code = KHERR_SUGGEST_RETRY;
+ AnsiStrToUnicode(buf, cbbuf, com_err_msg);
+ return;
+ }
+
+ if (table_num == krb_err_base) {
+ switch(offset) {
+ case KDC_NAME_EXP: /* 001 Principal expired */
+ case KDC_SERVICE_EXP: /* 002 Service expired */
+ case KDC_AUTH_EXP: /* 003 Auth expired */
+ case KDC_PKT_VER: /* 004 Protocol version unknown */
+ case KDC_P_MKEY_VER: /* 005 Wrong master key version */
+ case KDC_S_MKEY_VER: /* 006 Wrong master key version */
+ case KDC_BYTE_ORDER: /* 007 Byte order unknown */
+ case KDC_PR_N_UNIQUE: /* 009 Principal not unique */
+ case KDC_NULL_KEY: /* 010 Principal has null key */
+ case KDC_GEN_ERR: /* 011 Generic error from KDC */
+ case INTK_W_NOTALL : /* 061 Not ALL tickets returned */
+ case INTK_PROT : /* 063 Protocol Error */
+ case INTK_ERR : /* 070 Other error */
+ msg_id = MSG_ERR_UNKNOWN;
+ sugg_code = KHERR_SUGGEST_RETRY;
+ break;
+
+ case KDC_PR_UNKNOWN: /* 008 Principal unknown */
+ msg_id = MSG_ERR_PR_UNKNOWN;
+ sugg_code = KHERR_SUGGEST_RETRY;
+ break;
+ case GC_TKFIL : /* 021 Can't read ticket file */
+ case GC_NOTKT : /* 022 Can't find ticket or TGT */
+ msg_id = MSG_ERR_TKFIL;
+ sugg_id = MSG_ERR_S_TKFIL;
+ sugg_code = KHERR_SUGGEST_RETRY;
+ break;
+ case MK_AP_TGTEXP : /* 026 TGT Expired */
+ /* no extra error msg */
+ break;
+
+ case RD_AP_TIME : /* 037 delta_t too big */
+ msg_id = MSG_ERR_CLOCKSKEW;
+ sugg_id = MSG_ERR_S_CLOCKSKEW;
+ sugg_code = KHERR_SUGGEST_RETRY;
+ break;
+
+ case RD_AP_UNDEC : /* 031 Can't decode
+ authenticator */
+ case RD_AP_EXP : /* 032 Ticket expired */
+ case RD_AP_NYV : /* 033 Ticket not yet valid */
+ case RD_AP_REPEAT : /* 034 Repeated request */
+ case RD_AP_NOT_US : /* 035 The ticket isn't for us */
+ case RD_AP_INCON : /* 036 Request is inconsistent */
+ case RD_AP_BADD : /* 038 Incorrect net address */
+ case RD_AP_VERSION : /* 039 protocol version mismatch */
+ case RD_AP_MSG_TYPE : /* 040 invalid msg type */
+ case RD_AP_MODIFIED : /* 041 message stream modified */
+ case RD_AP_ORDER : /* 042 message out of order */
+ case RD_AP_UNAUTHOR : /* 043 unauthorized request */
+ /* no extra error msg */
+ sugg_code = KHERR_SUGGEST_RETRY;
+ break;
+
+ case GT_PW_NULL: /* 51 Current PW is null */
+ case GT_PW_BADPW: /* 52 Incorrect current password */
+ case GT_PW_PROT: /* 53 Protocol Error */
+ case GT_PW_KDCERR: /* 54 Error returned by KDC */
+ case GT_PW_NULLTKT: /* 55 Null tkt returned by KDC */
+ /* no error msg yet */
+ sugg_code = KHERR_SUGGEST_RETRY;
+ break;
+
+ /* Values returned by send_to_kdc */
+ case SKDC_RETRY : /* 56 Retry count exceeded */
+ case SKDC_CANT : /* 57 Can't send request */
+ msg_id = MSG_ERR_KDC_CONTACT;
+ break;
+ /* no error message on purpose: */
+ case INTK_BADPW : /* 062 Incorrect password */
+ sugg_code = KHERR_SUGGEST_RETRY;
+ break;
+ default:
+ /* no extra error msg */
+ break;
+ }
+ } else if (table_num == kadm_err_base) {
+ switch(code) {
+ case KADM_INSECURE_PW:
+ /* if( kadm_info != NULL ){
+ * wsprintf(buf, "%s\n%s", com_err_msg, kadm_info);
+ * } else {
+ * wsprintf(buf, "%s\nPlease see the help file for information "
+ * "about secure passwords.", com_err_msg);
+ * }
+ * com_err_msg = buf;
+ */
+
+ /* The above code would be preferred since it allows site
+ * specific information to be delivered from the Kerberos
+ * server. However the message box is too small for VGA
+ * screens. It does work well if we only have to support
+ * 1024x768
+ */
+
+ msg_id = MSG_ERR_INSECURE_PW;
+ sugg_code = KHERR_SUGGEST_RETRY;
+ break;
+
+ default:
+ /* no extra error msg */
+ break;
+ }
+ } else if (table_num == WSABASEERR) {
+ switch(code) {
+ case WSAENETDOWN:
+ msg_id = MSG_ERR_NETDOWN;
+ sugg_id = MSG_ERR_S_NETRETRY;
+ sugg_code = KHERR_SUGGEST_RETRY;
+ break;
+
+ case WSATRY_AGAIN:
+ msg_id = MSG_ERR_TEMPDOWN;
+ sugg_id = MSG_ERR_S_TEMPDOWN;
+ sugg_code = KHERR_SUGGEST_RETRY;
+ break;
+
+ case WSAENETUNREACH:
+ case WSAENETRESET:
+ case WSAECONNABORTED:
+ case WSAECONNRESET:
+ case WSAETIMEDOUT:
+ case WSAECONNREFUSED:
+ case WSAEHOSTDOWN:
+ case WSAEHOSTUNREACH:
+ msg_id = MSG_ERR_NOHOST;
+ sugg_id = MSG_ERR_S_NOHOST;
+ sugg_code = KHERR_SUGGEST_RETRY;
+ break;
+ }
+ }
+
+ if (msg_id != 0) {
+ FormatMessage(FORMAT_MESSAGE_FROM_HMODULE |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ KHERR_HMODULE,
+ msg_id,
+ 0,
+ buf,
+ (int) (cbbuf / sizeof(buf[0])),
+ NULL);
+ }
+
+ if (sugg_id != 0) {
+ *suggestion = sugg_id;
+ }
+
+ if (sugg_code != KHERR_SUGGEST_NONE)
+ *suggest_code = sugg_code;
+}
+
+#ifdef DEPRECATED_REMOVABLE
+int lsh_com_err_proc (LPSTR whoami, long code,
+ LPSTR fmt, va_list args)
+{
+ int retval;
+ HWND hOldFocus;
+ char buf[1024], *cp;
+ WORD mbformat = MB_OK | MB_ICONEXCLAMATION;
+
+ cp = buf;
+ memset(buf, '\0', sizeof(buf));
+ cp[0] = '\0';
+
+ if (code)
+ {
+ err_describe(buf, code);
+ while (*cp)
+ cp++;
+ }
+
+ if (fmt)
+ {
+ if (fmt[0] == '%' && fmt[1] == 'b')
+ {
+ fmt += 2;
+ mbformat = va_arg(args, WORD);
+ /* if the first arg is a %b, we use it for the message
+ box MB_??? flags. */
+ }
+ if (code)
+ {
+ *cp++ = '\n';
+ *cp++ = '\n';
+ }
+ wvsprintfA((LPSTR)cp, fmt, args);
+ }
+ hOldFocus = GetFocus();
+ retval = MessageBoxA(/*GetRootParent(hOldFocus)*/NULL, buf, whoami,
+ mbformat | MB_ICONHAND | MB_TASKMODAL);
+ SetFocus(hOldFocus);
+ return retval;
+}
+#endif
diff --git a/src/windows/identity/plugins/krb5/errorfuncs.h b/src/windows/identity/plugins/krb5/errorfuncs.h
index 86fc5b4404..4b1d2e2b52 100644
--- a/src/windows/identity/plugins/krb5/errorfuncs.h
+++ b/src/windows/identity/plugins/krb5/errorfuncs.h
@@ -1,75 +1,75 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#ifndef __KHIMAIRA_ERR_H
-#define __KHIMAIRA_ERR_H
-
-/* All error handling and reporting related functions for the krb4/5
- and AFS plugins */
-
-#include <errno.h>
-#include <com_err.h>
-/*
- * This is a hack needed because the real com_err.h does
- * not define err_func. We need it in the case where
- * we pull in the real com_err instead of the krb4
- * impostor.
- */
-#ifndef _DCNS_MIT_COM_ERR_H
-typedef LPSTR (*err_func)(int, long);
-#endif
-
-#include <krberr.h>
-#include <kadm_err.h>
-
-#define kadm_err_base ERROR_TABLE_BASE_kadm
-
-#include <stdarg.h>
-
-#ifndef KRBERR
-#define KRBERR(code) (code + krb_err_base)
-#endif
-
-/*! \internal
- \brief Describe an error
-
- \param[in] code Error code returned by Kerberos
- \param[out] buf Receives the error string
- \param[in] cbbuf Size of buffer pointed to by \a buf
- \param[out] suggestion Message ID of suggestion
- \param[out] suggest_code Suggestion ID
-*/
-void khm_err_describe(long code, wchar_t * buf, khm_size cbbuf,
- DWORD * suggestion,
- kherr_suggestion * suggest_code);
-
-/* */
-khm_int32 init_error_funcs();
-
-khm_int32 exit_error_funcs();
-
-
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __KHIMAIRA_ERR_H
+#define __KHIMAIRA_ERR_H
+
+/* All error handling and reporting related functions for the krb4/5
+ and AFS plugins */
+
+#include <errno.h>
+#include <com_err.h>
+/*
+ * This is a hack needed because the real com_err.h does
+ * not define err_func. We need it in the case where
+ * we pull in the real com_err instead of the krb4
+ * impostor.
+ */
+#ifndef _DCNS_MIT_COM_ERR_H
+typedef LPSTR (*err_func)(int, long);
+#endif
+
+#include <krberr.h>
+#include <kadm_err.h>
+
+#define kadm_err_base ERROR_TABLE_BASE_kadm
+
+#include <stdarg.h>
+
+#ifndef KRBERR
+#define KRBERR(code) (code + krb_err_base)
+#endif
+
+/*! \internal
+ \brief Describe an error
+
+ \param[in] code Error code returned by Kerberos
+ \param[out] buf Receives the error string
+ \param[in] cbbuf Size of buffer pointed to by \a buf
+ \param[out] suggestion Message ID of suggestion
+ \param[out] suggest_code Suggestion ID
+*/
+void khm_err_describe(long code, wchar_t * buf, khm_size cbbuf,
+ DWORD * suggestion,
+ kherr_suggestion * suggest_code);
+
+/* */
+khm_int32 init_error_funcs();
+
+khm_int32 exit_error_funcs();
+
+
+#endif
diff --git a/src/windows/identity/plugins/krb5/krb5configcc.c b/src/windows/identity/plugins/krb5/krb5configcc.c
index 5edc02b1fe..b2b498e685 100644
--- a/src/windows/identity/plugins/krb5/krb5configcc.c
+++ b/src/windows/identity/plugins/krb5/krb5configcc.c
@@ -1,571 +1,571 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#if _WIN32_WINNT < 0x501
-#undef _WIN32_WINNT
-#define _WIN32_WINNT 0x501
-#endif
-
-#include<krbcred.h>
-#include<krb5.h>
-#include<assert.h>
-#include<lm.h>
-#include<commctrl.h>
-#include<shlwapi.h>
-
-#include<strsafe.h>
-
-typedef struct tag_k5_file_cc {
- wchar_t path[MAX_PATH];
- khm_int32 flags;
-} k5_file_cc;
-
-#define K5_FCC_ALLOC_INCR 8
-
-#define K5_FCC_FLAG_EXISTS 1
-
-typedef struct tag_k5_ccc_data {
- khm_boolean inc_api;
- khm_boolean inc_mslsa;
- k5_file_cc * file_ccs;
- khm_size n_file_ccs;
- khm_size nc_file_ccs;
-} k5_ccc_data;
-
-typedef struct tag_k5_ccc_dlg_data {
- khui_config_node node;
- k5_ccc_data save;
- k5_ccc_data work;
-} k5_ccc_dlg_data;
-
-void k5_free_file_ccs(k5_ccc_data * d) {
- if (d->file_ccs)
- PFREE(d->file_ccs);
- d->n_file_ccs = 0;
- d->nc_file_ccs = 0;
-}
-
-void k5_flush_file_ccs(k5_ccc_data * d) {
- d->n_file_ccs = 0;
-}
-
-void k5_del_file_cc(k5_ccc_data * d, khm_size idx) {
- if (idx > d->n_file_ccs)
- return;
-
- if (idx < d->n_file_ccs - 1) {
- MoveMemory(&d->file_ccs[idx],
- &d->file_ccs[idx + 1],
- sizeof(d->file_ccs[0]) * (d->n_file_ccs - (idx + 1)));
- }
-
- d->n_file_ccs--;
-}
-
-void k5_add_file_cc(k5_ccc_data * d, wchar_t * path) {
- khm_size i;
- khm_size cch;
-
- if (FAILED(StringCchLength(path, MAX_PATH, &cch)) ||
- cch == 0)
- return;
-
- /* see if it's there first */
- for (i=0; i < d->n_file_ccs; i++) {
- if(!_wcsicmp(d->file_ccs[i].path, path))
- return;
- }
-
- if (d->n_file_ccs == d->nc_file_ccs) {
- k5_file_cc * f;
-
- d->nc_file_ccs = UBOUNDSS(d->n_file_ccs + 1,
- K5_FCC_ALLOC_INCR,
- K5_FCC_ALLOC_INCR);
-#ifdef DEBUG
- assert(d->nc_file_ccs > d->n_file_ccs);
-#endif
- f = PMALLOC(sizeof(*f) * d->nc_file_ccs);
- ZeroMemory(f, sizeof(*f) * d->nc_file_ccs);
-
- if (d->n_file_ccs > 0) {
-#ifdef DEBUG
- assert(d->file_ccs != NULL);
-#endif
- memcpy(f, d->file_ccs, sizeof(*f) * d->n_file_ccs);
- }
- if (d->file_ccs)
- PFREE(d->file_ccs);
- d->file_ccs = f;
- }
-
- StringCbCopy(d->file_ccs[d->n_file_ccs].path,
- sizeof(d->file_ccs[0].path),
- path);
- if(PathFileExists(path))
- d->file_ccs[d->n_file_ccs].flags = K5_FCC_FLAG_EXISTS;
- else
- d->file_ccs[d->n_file_ccs].flags = 0;
-
- d->n_file_ccs++;
-}
-
-void k5_read_file_cc_data(k5_ccc_data * d) {
- khm_int32 t;
- wchar_t * fclist = NULL;
- wchar_t * fc;
- khm_size cb;
-
-#ifdef DEBUG
- assert(csp_params);
-#endif
-
- d->inc_api = TRUE;
- t = TRUE;
- khc_read_int32(csp_params, L"MsLsaList", &t);
- d->inc_mslsa = t;
-
- if (khc_read_multi_string(csp_params, L"FileCCList", NULL, &cb)
- != KHM_ERROR_TOO_LONG ||
- cb <= sizeof(wchar_t) * 2) {
-
- k5_flush_file_ccs(d);
- } else {
- fclist = PMALLOC(cb);
-#ifdef DEBUG
- assert(fclist);
-#endif
- khc_read_multi_string(csp_params, L"FileCCList", fclist, &cb);
-
- for(fc = fclist; fc && *fc; fc = multi_string_next(fc)) {
- k5_add_file_cc(d, fc);
- }
-
- PFREE(fclist);
- }
-}
-
-void k5_write_file_cc_data(k5_ccc_data * d) {
- wchar_t * ms;
- khm_size cb;
- khm_size cbt;
- khm_int32 t;
- khm_size i;
-
-#ifdef DEBUG
- assert(csp_params);
-#endif
- if (KHM_FAILED(khc_read_int32(csp_params, L"MsLsaList", &t)) ||
- !!t != !!d->inc_mslsa) {
- khc_write_int32(csp_params, L"MsLsaList", !!d->inc_mslsa);
- }
-
- if (d->n_file_ccs > 0) {
- cb = d->n_file_ccs * MAX_PATH * sizeof(wchar_t);
- ms = PMALLOC(cb);
-#ifdef DEBUG
- assert(ms);
-#endif
- multi_string_init(ms, cb);
-
- for(i=0; i<d->n_file_ccs; i++) {
- cbt = cb;
- multi_string_append(ms, &cbt, d->file_ccs[i].path);
- }
-
- khc_write_multi_string(csp_params, L"FileCCList", ms);
-
- PFREE(ms);
- } else {
- if (khc_read_multi_string(csp_params, L"FileCCList", NULL, &cb)
- != KHM_ERROR_TOO_LONG ||
- cb != sizeof(wchar_t) * 2)
-
- khc_write_multi_string(csp_params, L"FileCCList", L"\0\0");
- }
-}
-
-void k5_copy_file_cc_data(k5_ccc_data * dest, const k5_ccc_data * src) {
- khm_size i;
-
- k5_flush_file_ccs(dest);
- dest->inc_mslsa = src->inc_mslsa;
- dest->inc_api = src->inc_api;
-
- for (i=0; i < src->n_file_ccs; i++) {
- k5_add_file_cc(dest, src->file_ccs[i].path);
- }
-}
-
-BOOL k5_ccc_get_mod(k5_ccc_dlg_data * d) {
- khm_size i, j;
-
- if (!!d->work.inc_mslsa != !!d->save.inc_mslsa ||
- !!d->work.inc_api != !!d->save.inc_api ||
- d->work.n_file_ccs != d->save.n_file_ccs)
- return TRUE;
-
- for (i=0; i < d->work.n_file_ccs; i++) {
- for (j=0; j < d->save.n_file_ccs; j++) {
- if (!_wcsicmp(d->work.file_ccs[i].path,
- d->save.file_ccs[j].path))
- break;
- }
- if (j >= d->save.n_file_ccs)
- return TRUE;
- }
-
- return FALSE;
-}
-
-void k5_ccc_update_ui(HWND hwnd, k5_ccc_dlg_data * d) {
- khm_size i;
- HWND lv;
-
- if (d->work.inc_api)
- CheckDlgButton(hwnd, IDC_CFG_INCAPI, BST_CHECKED);
- else
- CheckDlgButton(hwnd, IDC_CFG_INCAPI, BST_UNCHECKED);
- if (d->work.inc_mslsa)
- CheckDlgButton(hwnd, IDC_CFG_INCMSLSA, BST_CHECKED);
- else
- CheckDlgButton(hwnd, IDC_CFG_INCMSLSA, BST_UNCHECKED);
-
- lv = GetDlgItem(hwnd, IDC_CFG_FCLIST);
-#ifdef DEBUG
- assert(lv);
-#endif
- ListView_DeleteAllItems(lv);
-
- for (i=0; i<d->work.n_file_ccs; i++) {
- LVITEM lvi;
-
- ZeroMemory(&lvi, sizeof(lvi));
-
- lvi.mask = LVIF_PARAM | LVIF_TEXT;
- lvi.lParam = (LPARAM) i;
- lvi.pszText = d->work.file_ccs[i].path;
-
- ListView_InsertItem(lv, &lvi);
- }
-
- if (k5_ccc_get_mod(d)) {
- khui_cfg_set_flags(d->node,
- KHUI_CNFLAG_MODIFIED,
- KHUI_CNFLAG_MODIFIED);
- } else {
- khui_cfg_set_flags(d->node,
- 0,
- KHUI_CNFLAG_MODIFIED);
- }
-}
-
-void k5_ccc_update_data(HWND hwnd, k5_ccc_data * d) {
- if (IsDlgButtonChecked(hwnd, IDC_CFG_INCAPI) == BST_CHECKED)
- d->inc_api = TRUE;
- else
- d->inc_api = FALSE;
-
- if (IsDlgButtonChecked(hwnd, IDC_CFG_INCMSLSA) == BST_CHECKED)
- d->inc_mslsa = TRUE;
- else
- d->inc_mslsa = FALSE;
- /* everything else is controlled by buttons */
-}
-
-INT_PTR CALLBACK
-k5_ccconfig_dlgproc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam) {
-
- k5_ccc_dlg_data * d;
-
- switch(uMsg) {
- case WM_INITDIALOG:
- d = PMALLOC(sizeof(*d));
-#ifdef DEBUG
- assert(d);
-#endif
- ZeroMemory(d, sizeof(*d));
- k5_read_file_cc_data(&d->save);
- k5_copy_file_cc_data(&d->work, &d->save);
-
- d->node = (khui_config_node) lParam;
-
-#pragma warning(push)
-#pragma warning(disable: 4244)
- SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) d);
-#pragma warning(pop)
-
- {
- LVCOLUMN lvc;
- HWND lv;
- wchar_t buf[256];
- RECT r;
-
- lv = GetDlgItem(hwnd, IDC_CFG_FCLIST);
-#ifdef DEBUG
- assert(lv);
-#endif
- ZeroMemory(&lvc, sizeof(lvc));
- lvc.mask = LVCF_TEXT | LVCF_WIDTH;
-
- LoadString(hResModule, IDS_CFG_FCTITLE,
- buf, ARRAYLENGTH(buf));
-
- GetWindowRect(lv, &r);
-
- lvc.pszText = buf;
- lvc.cx = (r.right - r.left) * 9 / 10;
-
- ListView_InsertColumn(lv, 0, &lvc);
- }
-
- SendDlgItemMessage(hwnd, IDC_CFG_FCNAME, EM_SETLIMITTEXT,
- MAX_PATH - 1, 0);
-
- k5_ccc_update_ui(hwnd, d);
- break;
-
- case WM_COMMAND:
- d = (k5_ccc_dlg_data *) (DWORD_PTR)
- GetWindowLongPtr(hwnd, DWLP_USER);
- switch(wParam) {
- case MAKEWPARAM(IDC_CFG_ADD, BN_CLICKED):
- {
- wchar_t path[MAX_PATH];
- wchar_t cpath[MAX_PATH];
- khm_size i;
-
- GetDlgItemText(hwnd, IDC_CFG_FCNAME,
- cpath, ARRAYLENGTH(cpath));
-
- PathCanonicalize(path, cpath);
-
- if (!*path)
- return TRUE; /* nothing to add */
-
- for (i=0; i < d->work.n_file_ccs; i++) {
- if (!_wcsicmp(path, d->work.file_ccs[i].path)) {
-
- /* allow the user to correct case, as appropriate */
- StringCbCopy(d->work.file_ccs[i].path,
- sizeof(d->work.file_ccs[i].path),
- path);
- k5_ccc_update_ui(hwnd, d);
- return TRUE;
- }
- }
-
- /* not there. we need to add. but check a few things
- first */
- if (!PathFileExists(path)) {
- wchar_t title[64];
- wchar_t text[128];
-
- LoadString(hResModule, IDS_CFG_FCN_WARNING,
- title, ARRAYLENGTH(title));
-
- LoadString(hResModule, IDS_CFG_FCN_W_NOTFOUND,
- text, ARRAYLENGTH(text));
-#if _WIN32_WINNT >= 0x501
- if (IS_COMMCTL6())
- {
- EDITBALLOONTIP bt;
-
- bt.cbStruct = sizeof(bt);
- bt.pszTitle = title;
- bt.pszText = text;
- bt.ttiIcon = TTI_WARNING;
-
- SendDlgItemMessage(hwnd, IDC_CFG_FCNAME,
- EM_SHOWBALLOONTIP,
- 0,
- (LPARAM) &bt);
- } else {
-#endif
- MessageBox(hwnd, text, title, MB_OK | MB_ICONWARNING);
-#if _WIN32_WINNT >= 0x501
- }
-#endif
- } else if (PathIsRelative(path)) {
- wchar_t title[64];
- wchar_t text[128];
-
- LoadString(hResModule, IDS_CFG_FCN_WARNING,
- title, ARRAYLENGTH(title));
- LoadString(hResModule, IDS_CFG_FCN_W_RELATIVE,
- text, ARRAYLENGTH(text));
-
-#if _WIN32_WINNT >= 0x501
- if (IS_COMMCTL6())
- {
- EDITBALLOONTIP bt;
-
- bt.cbStruct = sizeof(bt);
- bt.pszTitle = title;
- bt.pszText = text;
- bt.ttiIcon = TTI_WARNING;
-
- SendDlgItemMessage(hwnd, IDC_CFG_FCNAME,
- EM_SHOWBALLOONTIP,
- 0,
- (LPARAM) &bt);
- } else {
-#endif
- MessageBox(hwnd, text, title, MB_OK | MB_ICONWARNING);
-#if _WIN32_WINNT >= 0x501
- }
-#endif
- }
-
- k5_add_file_cc(&d->work, path);
-
- k5_ccc_update_ui(hwnd, d);
- }
- return TRUE;
-
- case MAKEWPARAM(IDC_CFG_BROWSE, BN_CLICKED):
- {
- OPENFILENAME ofn;
- wchar_t path[MAX_PATH * 8];
- wchar_t title[128];
-
- ZeroMemory(&ofn, sizeof(ofn));
- ZeroMemory(path, sizeof(path));
-
- GetDlgItemText(hwnd, IDC_CFG_FCNAME,
- path, ARRAYLENGTH(path));
-
- /* don't pass in invalid paths */
- if (!PathFileExists(path))
- *path = 0;
-
- ofn.lStructSize = sizeof(ofn);
- ofn.hwndOwner = hwnd;
- ofn.lpstrFilter = L"All files\0*.*\0\0";
- ofn.nFilterIndex = 1;
- ofn.lpstrFile = path;
- ofn.nMaxFile = ARRAYLENGTH(path);
- ofn.lpstrTitle = title;
-
- LoadString(hResModule, IDS_CFG_FCOPENTITLE,
- title, ARRAYLENGTH(title));
-
- ofn.Flags = OFN_ALLOWMULTISELECT |
- OFN_DONTADDTORECENT |
- OFN_FORCESHOWHIDDEN |
- OFN_EXPLORER;
-
- if (GetOpenFileName(&ofn)) {
- wchar_t * p;
- wchar_t spath[MAX_PATH];
-
- p = multi_string_next(path);
- if (p) {
- /* multi select */
- for(;p && *p; p = multi_string_next(p)) {
- StringCbCopy(spath, sizeof(spath), path);
- PathAppend(spath, p);
-
- k5_add_file_cc(&d->work, spath);
- }
- } else {
- /* single select */
- k5_add_file_cc(&d->work, path);
- }
- k5_ccc_update_ui(hwnd, d);
- }
- }
- return TRUE;
-
- case MAKEWPARAM(IDC_CFG_REMOVE, BN_CLICKED):
- {
- khm_size i;
- int lv_idx;
- HWND lv;
- wchar_t buf[MAX_PATH];
-
- lv = GetDlgItem(hwnd, IDC_CFG_FCLIST);
-#ifdef DEBUG
- assert(lv);
-#endif
-
- lv_idx = -1;
- while((lv_idx = ListView_GetNextItem(lv, lv_idx,
- LVNI_SELECTED)) != -1) {
- ListView_GetItemText(lv, lv_idx, 0, buf, ARRAYLENGTH(buf));
- for (i=0; i < d->work.n_file_ccs; i++) {
- if (!_wcsicmp(buf, d->work.file_ccs[i].path)) {
- k5_del_file_cc(&d->work, i);
- break;
- }
- }
- }
-
- k5_ccc_update_ui(hwnd, d);
- }
- return TRUE;
-
- case MAKEWPARAM(IDC_CFG_INCAPI, BN_CLICKED):
- case MAKEWPARAM(IDC_CFG_INCMSLSA, BN_CLICKED):
- k5_ccc_update_data(hwnd, &d->work);
- k5_ccc_update_ui(hwnd, d);
- return TRUE;
- }
- break;
-
- case WM_DESTROY:
- d = (k5_ccc_dlg_data *) (DWORD_PTR)
- GetWindowLongPtr(hwnd, DWLP_USER);
-
- k5_free_file_ccs(&d->work);
- k5_free_file_ccs(&d->save);
- PFREE(d);
- return TRUE;
-
- case KHUI_WM_CFG_NOTIFY:
- d = (k5_ccc_dlg_data *) (DWORD_PTR)
- GetWindowLongPtr(hwnd, DWLP_USER);
-
- switch(HIWORD(wParam)) {
- case WMCFG_APPLY:
- if (k5_ccc_get_mod(d)) {
- k5_write_file_cc_data(&d->work);
- k5_copy_file_cc_data(&d->save, &d->work);
- khui_cfg_set_flags(d->node,
- KHUI_CNFLAG_APPLIED,
- KHUI_CNFLAG_APPLIED);
- k5_ccc_update_ui(hwnd, d);
-
- kmq_post_sub_msg(k5_sub, KMSG_CRED, KMSG_CRED_REFRESH, 0, 0);
- }
- break;
- }
- }
- return FALSE;
-}
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#if _WIN32_WINNT < 0x501
+#undef _WIN32_WINNT
+#define _WIN32_WINNT 0x501
+#endif
+
+#include<krbcred.h>
+#include<krb5.h>
+#include<assert.h>
+#include<lm.h>
+#include<commctrl.h>
+#include<shlwapi.h>
+
+#include<strsafe.h>
+
+typedef struct tag_k5_file_cc {
+ wchar_t path[MAX_PATH];
+ khm_int32 flags;
+} k5_file_cc;
+
+#define K5_FCC_ALLOC_INCR 8
+
+#define K5_FCC_FLAG_EXISTS 1
+
+typedef struct tag_k5_ccc_data {
+ khm_boolean inc_api;
+ khm_boolean inc_mslsa;
+ k5_file_cc * file_ccs;
+ khm_size n_file_ccs;
+ khm_size nc_file_ccs;
+} k5_ccc_data;
+
+typedef struct tag_k5_ccc_dlg_data {
+ khui_config_node node;
+ k5_ccc_data save;
+ k5_ccc_data work;
+} k5_ccc_dlg_data;
+
+void k5_free_file_ccs(k5_ccc_data * d) {
+ if (d->file_ccs)
+ PFREE(d->file_ccs);
+ d->n_file_ccs = 0;
+ d->nc_file_ccs = 0;
+}
+
+void k5_flush_file_ccs(k5_ccc_data * d) {
+ d->n_file_ccs = 0;
+}
+
+void k5_del_file_cc(k5_ccc_data * d, khm_size idx) {
+ if (idx > d->n_file_ccs)
+ return;
+
+ if (idx < d->n_file_ccs - 1) {
+ MoveMemory(&d->file_ccs[idx],
+ &d->file_ccs[idx + 1],
+ sizeof(d->file_ccs[0]) * (d->n_file_ccs - (idx + 1)));
+ }
+
+ d->n_file_ccs--;
+}
+
+void k5_add_file_cc(k5_ccc_data * d, wchar_t * path) {
+ khm_size i;
+ khm_size cch;
+
+ if (FAILED(StringCchLength(path, MAX_PATH, &cch)) ||
+ cch == 0)
+ return;
+
+ /* see if it's there first */
+ for (i=0; i < d->n_file_ccs; i++) {
+ if(!_wcsicmp(d->file_ccs[i].path, path))
+ return;
+ }
+
+ if (d->n_file_ccs == d->nc_file_ccs) {
+ k5_file_cc * f;
+
+ d->nc_file_ccs = UBOUNDSS(d->n_file_ccs + 1,
+ K5_FCC_ALLOC_INCR,
+ K5_FCC_ALLOC_INCR);
+#ifdef DEBUG
+ assert(d->nc_file_ccs > d->n_file_ccs);
+#endif
+ f = PMALLOC(sizeof(*f) * d->nc_file_ccs);
+ ZeroMemory(f, sizeof(*f) * d->nc_file_ccs);
+
+ if (d->n_file_ccs > 0) {
+#ifdef DEBUG
+ assert(d->file_ccs != NULL);
+#endif
+ memcpy(f, d->file_ccs, sizeof(*f) * d->n_file_ccs);
+ }
+ if (d->file_ccs)
+ PFREE(d->file_ccs);
+ d->file_ccs = f;
+ }
+
+ StringCbCopy(d->file_ccs[d->n_file_ccs].path,
+ sizeof(d->file_ccs[0].path),
+ path);
+ if(PathFileExists(path))
+ d->file_ccs[d->n_file_ccs].flags = K5_FCC_FLAG_EXISTS;
+ else
+ d->file_ccs[d->n_file_ccs].flags = 0;
+
+ d->n_file_ccs++;
+}
+
+void k5_read_file_cc_data(k5_ccc_data * d) {
+ khm_int32 t;
+ wchar_t * fclist = NULL;
+ wchar_t * fc;
+ khm_size cb;
+
+#ifdef DEBUG
+ assert(csp_params);
+#endif
+
+ d->inc_api = TRUE;
+ t = TRUE;
+ khc_read_int32(csp_params, L"MsLsaList", &t);
+ d->inc_mslsa = t;
+
+ if (khc_read_multi_string(csp_params, L"FileCCList", NULL, &cb)
+ != KHM_ERROR_TOO_LONG ||
+ cb <= sizeof(wchar_t) * 2) {
+
+ k5_flush_file_ccs(d);
+ } else {
+ fclist = PMALLOC(cb);
+#ifdef DEBUG
+ assert(fclist);
+#endif
+ khc_read_multi_string(csp_params, L"FileCCList", fclist, &cb);
+
+ for(fc = fclist; fc && *fc; fc = multi_string_next(fc)) {
+ k5_add_file_cc(d, fc);
+ }
+
+ PFREE(fclist);
+ }
+}
+
+void k5_write_file_cc_data(k5_ccc_data * d) {
+ wchar_t * ms;
+ khm_size cb;
+ khm_size cbt;
+ khm_int32 t;
+ khm_size i;
+
+#ifdef DEBUG
+ assert(csp_params);
+#endif
+ if (KHM_FAILED(khc_read_int32(csp_params, L"MsLsaList", &t)) ||
+ !!t != !!d->inc_mslsa) {
+ khc_write_int32(csp_params, L"MsLsaList", !!d->inc_mslsa);
+ }
+
+ if (d->n_file_ccs > 0) {
+ cb = d->n_file_ccs * MAX_PATH * sizeof(wchar_t);
+ ms = PMALLOC(cb);
+#ifdef DEBUG
+ assert(ms);
+#endif
+ multi_string_init(ms, cb);
+
+ for(i=0; i<d->n_file_ccs; i++) {
+ cbt = cb;
+ multi_string_append(ms, &cbt, d->file_ccs[i].path);
+ }
+
+ khc_write_multi_string(csp_params, L"FileCCList", ms);
+
+ PFREE(ms);
+ } else {
+ if (khc_read_multi_string(csp_params, L"FileCCList", NULL, &cb)
+ != KHM_ERROR_TOO_LONG ||
+ cb != sizeof(wchar_t) * 2)
+
+ khc_write_multi_string(csp_params, L"FileCCList", L"\0\0");
+ }
+}
+
+void k5_copy_file_cc_data(k5_ccc_data * dest, const k5_ccc_data * src) {
+ khm_size i;
+
+ k5_flush_file_ccs(dest);
+ dest->inc_mslsa = src->inc_mslsa;
+ dest->inc_api = src->inc_api;
+
+ for (i=0; i < src->n_file_ccs; i++) {
+ k5_add_file_cc(dest, src->file_ccs[i].path);
+ }
+}
+
+BOOL k5_ccc_get_mod(k5_ccc_dlg_data * d) {
+ khm_size i, j;
+
+ if (!!d->work.inc_mslsa != !!d->save.inc_mslsa ||
+ !!d->work.inc_api != !!d->save.inc_api ||
+ d->work.n_file_ccs != d->save.n_file_ccs)
+ return TRUE;
+
+ for (i=0; i < d->work.n_file_ccs; i++) {
+ for (j=0; j < d->save.n_file_ccs; j++) {
+ if (!_wcsicmp(d->work.file_ccs[i].path,
+ d->save.file_ccs[j].path))
+ break;
+ }
+ if (j >= d->save.n_file_ccs)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+void k5_ccc_update_ui(HWND hwnd, k5_ccc_dlg_data * d) {
+ khm_size i;
+ HWND lv;
+
+ if (d->work.inc_api)
+ CheckDlgButton(hwnd, IDC_CFG_INCAPI, BST_CHECKED);
+ else
+ CheckDlgButton(hwnd, IDC_CFG_INCAPI, BST_UNCHECKED);
+ if (d->work.inc_mslsa)
+ CheckDlgButton(hwnd, IDC_CFG_INCMSLSA, BST_CHECKED);
+ else
+ CheckDlgButton(hwnd, IDC_CFG_INCMSLSA, BST_UNCHECKED);
+
+ lv = GetDlgItem(hwnd, IDC_CFG_FCLIST);
+#ifdef DEBUG
+ assert(lv);
+#endif
+ ListView_DeleteAllItems(lv);
+
+ for (i=0; i<d->work.n_file_ccs; i++) {
+ LVITEM lvi;
+
+ ZeroMemory(&lvi, sizeof(lvi));
+
+ lvi.mask = LVIF_PARAM | LVIF_TEXT;
+ lvi.lParam = (LPARAM) i;
+ lvi.pszText = d->work.file_ccs[i].path;
+
+ ListView_InsertItem(lv, &lvi);
+ }
+
+ if (k5_ccc_get_mod(d)) {
+ khui_cfg_set_flags(d->node,
+ KHUI_CNFLAG_MODIFIED,
+ KHUI_CNFLAG_MODIFIED);
+ } else {
+ khui_cfg_set_flags(d->node,
+ 0,
+ KHUI_CNFLAG_MODIFIED);
+ }
+}
+
+void k5_ccc_update_data(HWND hwnd, k5_ccc_data * d) {
+ if (IsDlgButtonChecked(hwnd, IDC_CFG_INCAPI) == BST_CHECKED)
+ d->inc_api = TRUE;
+ else
+ d->inc_api = FALSE;
+
+ if (IsDlgButtonChecked(hwnd, IDC_CFG_INCMSLSA) == BST_CHECKED)
+ d->inc_mslsa = TRUE;
+ else
+ d->inc_mslsa = FALSE;
+ /* everything else is controlled by buttons */
+}
+
+INT_PTR CALLBACK
+k5_ccconfig_dlgproc(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam) {
+
+ k5_ccc_dlg_data * d;
+
+ switch(uMsg) {
+ case WM_INITDIALOG:
+ d = PMALLOC(sizeof(*d));
+#ifdef DEBUG
+ assert(d);
+#endif
+ ZeroMemory(d, sizeof(*d));
+ k5_read_file_cc_data(&d->save);
+ k5_copy_file_cc_data(&d->work, &d->save);
+
+ d->node = (khui_config_node) lParam;
+
+#pragma warning(push)
+#pragma warning(disable: 4244)
+ SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) d);
+#pragma warning(pop)
+
+ {
+ LVCOLUMN lvc;
+ HWND lv;
+ wchar_t buf[256];
+ RECT r;
+
+ lv = GetDlgItem(hwnd, IDC_CFG_FCLIST);
+#ifdef DEBUG
+ assert(lv);
+#endif
+ ZeroMemory(&lvc, sizeof(lvc));
+ lvc.mask = LVCF_TEXT | LVCF_WIDTH;
+
+ LoadString(hResModule, IDS_CFG_FCTITLE,
+ buf, ARRAYLENGTH(buf));
+
+ GetWindowRect(lv, &r);
+
+ lvc.pszText = buf;
+ lvc.cx = (r.right - r.left) * 9 / 10;
+
+ ListView_InsertColumn(lv, 0, &lvc);
+ }
+
+ SendDlgItemMessage(hwnd, IDC_CFG_FCNAME, EM_SETLIMITTEXT,
+ MAX_PATH - 1, 0);
+
+ k5_ccc_update_ui(hwnd, d);
+ break;
+
+ case WM_COMMAND:
+ d = (k5_ccc_dlg_data *) (DWORD_PTR)
+ GetWindowLongPtr(hwnd, DWLP_USER);
+ switch(wParam) {
+ case MAKEWPARAM(IDC_CFG_ADD, BN_CLICKED):
+ {
+ wchar_t path[MAX_PATH];
+ wchar_t cpath[MAX_PATH];
+ khm_size i;
+
+ GetDlgItemText(hwnd, IDC_CFG_FCNAME,
+ cpath, ARRAYLENGTH(cpath));
+
+ PathCanonicalize(path, cpath);
+
+ if (!*path)
+ return TRUE; /* nothing to add */
+
+ for (i=0; i < d->work.n_file_ccs; i++) {
+ if (!_wcsicmp(path, d->work.file_ccs[i].path)) {
+
+ /* allow the user to correct case, as appropriate */
+ StringCbCopy(d->work.file_ccs[i].path,
+ sizeof(d->work.file_ccs[i].path),
+ path);
+ k5_ccc_update_ui(hwnd, d);
+ return TRUE;
+ }
+ }
+
+ /* not there. we need to add. but check a few things
+ first */
+ if (!PathFileExists(path)) {
+ wchar_t title[64];
+ wchar_t text[128];
+
+ LoadString(hResModule, IDS_CFG_FCN_WARNING,
+ title, ARRAYLENGTH(title));
+
+ LoadString(hResModule, IDS_CFG_FCN_W_NOTFOUND,
+ text, ARRAYLENGTH(text));
+#if _WIN32_WINNT >= 0x501
+ if (IS_COMMCTL6())
+ {
+ EDITBALLOONTIP bt;
+
+ bt.cbStruct = sizeof(bt);
+ bt.pszTitle = title;
+ bt.pszText = text;
+ bt.ttiIcon = TTI_WARNING;
+
+ SendDlgItemMessage(hwnd, IDC_CFG_FCNAME,
+ EM_SHOWBALLOONTIP,
+ 0,
+ (LPARAM) &bt);
+ } else {
+#endif
+ MessageBox(hwnd, text, title, MB_OK | MB_ICONWARNING);
+#if _WIN32_WINNT >= 0x501
+ }
+#endif
+ } else if (PathIsRelative(path)) {
+ wchar_t title[64];
+ wchar_t text[128];
+
+ LoadString(hResModule, IDS_CFG_FCN_WARNING,
+ title, ARRAYLENGTH(title));
+ LoadString(hResModule, IDS_CFG_FCN_W_RELATIVE,
+ text, ARRAYLENGTH(text));
+
+#if _WIN32_WINNT >= 0x501
+ if (IS_COMMCTL6())
+ {
+ EDITBALLOONTIP bt;
+
+ bt.cbStruct = sizeof(bt);
+ bt.pszTitle = title;
+ bt.pszText = text;
+ bt.ttiIcon = TTI_WARNING;
+
+ SendDlgItemMessage(hwnd, IDC_CFG_FCNAME,
+ EM_SHOWBALLOONTIP,
+ 0,
+ (LPARAM) &bt);
+ } else {
+#endif
+ MessageBox(hwnd, text, title, MB_OK | MB_ICONWARNING);
+#if _WIN32_WINNT >= 0x501
+ }
+#endif
+ }
+
+ k5_add_file_cc(&d->work, path);
+
+ k5_ccc_update_ui(hwnd, d);
+ }
+ return TRUE;
+
+ case MAKEWPARAM(IDC_CFG_BROWSE, BN_CLICKED):
+ {
+ OPENFILENAME ofn;
+ wchar_t path[MAX_PATH * 8];
+ wchar_t title[128];
+
+ ZeroMemory(&ofn, sizeof(ofn));
+ ZeroMemory(path, sizeof(path));
+
+ GetDlgItemText(hwnd, IDC_CFG_FCNAME,
+ path, ARRAYLENGTH(path));
+
+ /* don't pass in invalid paths */
+ if (!PathFileExists(path))
+ *path = 0;
+
+ ofn.lStructSize = sizeof(ofn);
+ ofn.hwndOwner = hwnd;
+ ofn.lpstrFilter = L"All files\0*.*\0\0";
+ ofn.nFilterIndex = 1;
+ ofn.lpstrFile = path;
+ ofn.nMaxFile = ARRAYLENGTH(path);
+ ofn.lpstrTitle = title;
+
+ LoadString(hResModule, IDS_CFG_FCOPENTITLE,
+ title, ARRAYLENGTH(title));
+
+ ofn.Flags = OFN_ALLOWMULTISELECT |
+ OFN_DONTADDTORECENT |
+ OFN_FORCESHOWHIDDEN |
+ OFN_EXPLORER;
+
+ if (GetOpenFileName(&ofn)) {
+ wchar_t * p;
+ wchar_t spath[MAX_PATH];
+
+ p = multi_string_next(path);
+ if (p) {
+ /* multi select */
+ for(;p && *p; p = multi_string_next(p)) {
+ StringCbCopy(spath, sizeof(spath), path);
+ PathAppend(spath, p);
+
+ k5_add_file_cc(&d->work, spath);
+ }
+ } else {
+ /* single select */
+ k5_add_file_cc(&d->work, path);
+ }
+ k5_ccc_update_ui(hwnd, d);
+ }
+ }
+ return TRUE;
+
+ case MAKEWPARAM(IDC_CFG_REMOVE, BN_CLICKED):
+ {
+ khm_size i;
+ int lv_idx;
+ HWND lv;
+ wchar_t buf[MAX_PATH];
+
+ lv = GetDlgItem(hwnd, IDC_CFG_FCLIST);
+#ifdef DEBUG
+ assert(lv);
+#endif
+
+ lv_idx = -1;
+ while((lv_idx = ListView_GetNextItem(lv, lv_idx,
+ LVNI_SELECTED)) != -1) {
+ ListView_GetItemText(lv, lv_idx, 0, buf, ARRAYLENGTH(buf));
+ for (i=0; i < d->work.n_file_ccs; i++) {
+ if (!_wcsicmp(buf, d->work.file_ccs[i].path)) {
+ k5_del_file_cc(&d->work, i);
+ break;
+ }
+ }
+ }
+
+ k5_ccc_update_ui(hwnd, d);
+ }
+ return TRUE;
+
+ case MAKEWPARAM(IDC_CFG_INCAPI, BN_CLICKED):
+ case MAKEWPARAM(IDC_CFG_INCMSLSA, BN_CLICKED):
+ k5_ccc_update_data(hwnd, &d->work);
+ k5_ccc_update_ui(hwnd, d);
+ return TRUE;
+ }
+ break;
+
+ case WM_DESTROY:
+ d = (k5_ccc_dlg_data *) (DWORD_PTR)
+ GetWindowLongPtr(hwnd, DWLP_USER);
+
+ k5_free_file_ccs(&d->work);
+ k5_free_file_ccs(&d->save);
+ PFREE(d);
+ return TRUE;
+
+ case KHUI_WM_CFG_NOTIFY:
+ d = (k5_ccc_dlg_data *) (DWORD_PTR)
+ GetWindowLongPtr(hwnd, DWLP_USER);
+
+ switch(HIWORD(wParam)) {
+ case WMCFG_APPLY:
+ if (k5_ccc_get_mod(d)) {
+ k5_write_file_cc_data(&d->work);
+ k5_copy_file_cc_data(&d->save, &d->work);
+ khui_cfg_set_flags(d->node,
+ KHUI_CNFLAG_APPLIED,
+ KHUI_CNFLAG_APPLIED);
+ k5_ccc_update_ui(hwnd, d);
+
+ kmq_post_sub_msg(k5_sub, KMSG_CRED, KMSG_CRED_REFRESH, 0, 0);
+ }
+ break;
+ }
+ }
+ return FALSE;
+}
diff --git a/src/windows/identity/plugins/krb5/krb5configid.c b/src/windows/identity/plugins/krb5/krb5configid.c
index e09281906e..b5af1c2b2e 100644
--- a/src/windows/identity/plugins/krb5/krb5configid.c
+++ b/src/windows/identity/plugins/krb5/krb5configid.c
@@ -1,355 +1,355 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<krbcred.h>
-#include<krb5.h>
-#include<assert.h>
-#include<lm.h>
-#include<commctrl.h>
-#include<shlwapi.h>
-
-#include<strsafe.h>
-
-typedef struct tag_k5_id_dlg_data {
- khui_config_init_data cfg;
-
- khm_handle ident;
-
- khui_tracker tc_life;
- khui_tracker tc_renew;
-
- wchar_t ccache[KRB5_MAXCCH_CCNAME];
-
- khm_boolean renewable;
- khm_boolean forwardable;
- khm_boolean proxiable;
- khm_boolean addressless;
-
- DWORD public_ip;
-
- time_t life;
- time_t renew_life;
-} k5_id_dlg_data;
-
-static void
-k5_id_read_params(k5_id_dlg_data * d) {
-
- wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
- khm_size cb;
- khm_int32 rv;
- khm_int32 t;
- khm_handle csp_ident;
- khm_handle csp_idroot = NULL;
-
- cb = sizeof(idname);
- rv = khui_cfg_get_name(d->cfg.ctx_node, idname, &cb);
-#ifdef DEBUG
- assert(KHM_SUCCEEDED(rv));
-#endif
-
- rv = kcdb_identity_create(idname, 0, &d->ident);
-#ifdef DEBUG
- assert(KHM_SUCCEEDED(rv));
-#endif
-
- rv = kcdb_identity_get_config(d->ident, 0, &csp_idroot);
- if (KHM_SUCCEEDED(rv) &&
- KHM_SUCCEEDED(khc_open_space(csp_idroot, CSNAME_KRB5CRED, 0,
- &csp_ident))) {
- khc_shadow_space(csp_ident, csp_params);
- } else {
- csp_ident = csp_params;
- }
-
- if (csp_idroot)
- khc_close_space(csp_idroot);
-
- rv = khc_read_int32(csp_ident, L"DefaultLifetime", &t);
- if (KHM_SUCCEEDED(rv))
- d->life = t;
- else
- d->life = 36000;
-
- rv = khc_read_int32(csp_ident, L"DefaultRenewLifetime", &t);
- if (KHM_SUCCEEDED(rv))
- d->renew_life = t;
- else
- d->renew_life = 604800;
-
- rv = khc_read_int32(csp_ident, L"Renewable", &t);
- if (KHM_SUCCEEDED(rv))
- d->renewable = !!t;
- else
- d->renewable = TRUE;
-
- rv = khc_read_int32(csp_ident, L"Forwardable", &t);
- if (KHM_SUCCEEDED(rv))
- d->forwardable = !!t;
- else
- d->forwardable = FALSE;
-
- rv = khc_read_int32(csp_ident, L"Proxiable", &t);
- if (KHM_SUCCEEDED(rv))
- d->proxiable = !!t;
- else
- d->proxiable = FALSE;
-
- rv = khc_read_int32(csp_ident, L"Addressless", &t);
- if (KHM_SUCCEEDED(rv))
- d->addressless = !!t;
- else
- d->addressless = TRUE;
-
- rv = khc_read_int32(csp_ident, L"PublicIP", &t);
- if (KHM_SUCCEEDED(rv))
- d->public_ip = (khm_ui_4) t;
- else
- d->public_ip = 0;
-
- cb = sizeof(d->ccache);
- rv = khc_read_string(csp_ident, L"DefaultCCName", d->ccache, &cb);
- if (KHM_FAILED(rv) || cb <= sizeof(wchar_t)) {
- cb = sizeof(d->ccache);
- if (KHM_FAILED(kcdb_identity_get_attr(d->ident, attr_id_krb5_ccname,
- NULL, d->ccache, &cb)))
- ZeroMemory(d->ccache, sizeof(d->ccache));
- }
-
- khui_tracker_initialize(&d->tc_life);
- d->tc_life.current = d->life;
- d->tc_life.min = 0;
- d->tc_life.max = 3600 * 24 * 7;
-
- khui_tracker_initialize(&d->tc_renew);
- d->tc_renew.current = d->renew_life;
- d->tc_renew.min = 0;
- d->tc_renew.max = 3600 * 24 * 30;
-
- if (csp_ident != csp_params)
- khc_close_space(csp_ident);
-}
-
-static khm_boolean
-k5_id_is_mod(HWND hw, k5_id_dlg_data * d) {
- wchar_t ccache[KRB5_MAXCCH_CCNAME];
- DWORD dwaddress = 0;
-
- GetDlgItemText(hw, IDC_CFG_CCACHE, ccache, ARRAYLENGTH(ccache));
-
- SendDlgItemMessage(hw, IDC_CFG_PUBLICIP, IPM_GETADDRESS,
- 0, (LPARAM) &dwaddress);
-
- if (_wcsicmp(ccache, d->ccache) ||
-
- d->tc_renew.current != d->renew_life ||
-
- d->tc_life.current != d->life ||
-
- (IsDlgButtonChecked(hw, IDC_CFG_RENEW) == BST_CHECKED) != d->renewable ||
-
- (IsDlgButtonChecked(hw, IDC_CFG_FORWARD) == BST_CHECKED) != d->forwardable ||
-
- (IsDlgButtonChecked(hw, IDC_CFG_ADDRESSLESS) == BST_CHECKED)
- != d->addressless ||
-
- dwaddress != d->public_ip)
-
- return TRUE;
-
- return FALSE;
-}
-
-static void
-k5_id_check_mod(HWND hw, k5_id_dlg_data * d) {
- BOOL modified = k5_id_is_mod(hw, d);
-
- khui_cfg_set_flags_inst(&d->cfg,
- (modified)?KHUI_CNFLAG_MODIFIED:0,
- KHUI_CNFLAG_MODIFIED);
-}
-
-static void
-k5_id_write_params(HWND hw, k5_id_dlg_data * d) {
-
- khm_handle csp_idroot = NULL;
- khm_handle csp_ident = NULL;
- wchar_t ccache[KRB5_MAXCCH_CCNAME];
- khm_size cb;
- khm_int32 rv;
- khm_boolean b;
- DWORD dwaddress = 0;
-
- if (!k5_id_is_mod(hw, d))
- return;
-
- rv = kcdb_identity_get_config(d->ident, KHM_FLAG_CREATE, &csp_idroot);
- if (KHM_SUCCEEDED(rv)) {
- khc_open_space(csp_idroot, CSNAME_KRB5CRED,
- KHM_FLAG_CREATE,
- &csp_ident);
- }
-
- if (csp_idroot)
- khc_close_space(csp_idroot);
-
- if (!csp_ident)
- return;
-
- if (d->life != d->tc_life.current) {
- d->life = d->tc_life.current;
- khc_write_int32(csp_ident, L"DefaultLifetime", (khm_int32) d->life);
- }
-
- if (d->renew_life != d->tc_renew.current) {
- d->renew_life = d->tc_renew.current;
- khc_write_int32(csp_ident, L"DefaultRenewLifetime", (khm_int32) d->renew_life);
- }
-
- b = (IsDlgButtonChecked(hw, IDC_CFG_RENEW) == BST_CHECKED);
- if (b != d->renewable) {
- d->renewable = b;
- khc_write_int32(csp_ident, L"Renewable", (khm_int32) b);
- }
-
- b = (IsDlgButtonChecked(hw, IDC_CFG_FORWARD) == BST_CHECKED);
- if (b != d->forwardable) {
- d->forwardable = b;
- khc_write_int32(csp_ident, L"Forwardable", (khm_int32) b);
- }
-
- b = (IsDlgButtonChecked(hw, IDC_CFG_ADDRESSLESS) == BST_CHECKED);
- if (b != d->addressless) {
- d->addressless = b;
- khc_write_int32(csp_ident, L"Addressless", (khm_int32) b);
- }
-
- SendDlgItemMessage(hw, IDC_CFG_PUBLICIP, IPM_GETADDRESS,
- 0, (LPARAM) &dwaddress);
-
- if (dwaddress != d->public_ip) {
- d->public_ip = dwaddress;
- khc_write_int32(csp_ident, L"PublicIP", (khm_int32) dwaddress);
- }
-
- GetDlgItemText(hw, IDC_CFG_CCACHE, ccache, ARRAYLENGTH(ccache));
-
- if (SUCCEEDED(StringCbLength(ccache, sizeof(ccache), &cb)) &&
- _wcsicmp(ccache, d->ccache)) {
- khc_write_string(csp_ident, L"DefaultCCName", ccache);
- StringCbCopy(d->ccache, sizeof(d->ccache), ccache);
- } else {
- khc_remove_value(csp_ident, L"DefaultCCName", KCONF_FLAG_USER);
- }
-
- if (csp_ident)
- khc_close_space(csp_ident);
-
- khui_cfg_set_flags_inst(&d->cfg,
- KHUI_CNFLAG_APPLIED,
- KHUI_CNFLAG_APPLIED | KHUI_CNFLAG_MODIFIED);
-}
-
-INT_PTR CALLBACK
-k5_id_tab_dlgproc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam) {
-
- k5_id_dlg_data * d;
-
- switch(uMsg) {
- case WM_INITDIALOG:
- d = PMALLOC(sizeof(*d));
-#ifdef DEBUG
- assert(d);
-#endif
- ZeroMemory(d, sizeof(*d));
-
- d->cfg = *((khui_config_init_data *) lParam);
-
-#pragma warning(push)
-#pragma warning(disable: 4244)
- SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) d);
-#pragma warning(pop)
-
- k5_id_read_params(d);
-
- khui_tracker_install(GetDlgItem(hwnd, IDC_CFG_DEFLIFE),
- &d->tc_life);
- khui_tracker_install(GetDlgItem(hwnd, IDC_CFG_DEFRLIFE),
- &d->tc_renew);
- khui_tracker_refresh(&d->tc_life);
- khui_tracker_refresh(&d->tc_renew);
-
- SetDlgItemText(hwnd, IDC_CFG_CCACHE, d->ccache);
-
- CheckDlgButton(hwnd, IDC_CFG_RENEW,
- (d->renewable? BST_CHECKED: BST_UNCHECKED));
-
- CheckDlgButton(hwnd, IDC_CFG_FORWARD,
- (d->forwardable? BST_CHECKED: BST_UNCHECKED));
-
- CheckDlgButton(hwnd, IDC_CFG_ADDRESSLESS,
- (d->addressless? BST_CHECKED: BST_UNCHECKED));
-
- SendDlgItemMessage(hwnd, IDC_CFG_PUBLICIP,
- IPM_SETADDRESS,
- 0, (LPARAM) d->public_ip);
- break;
-
- case WM_COMMAND:
- d = (k5_id_dlg_data *) (LONG_PTR)
- GetWindowLongPtr(hwnd, DWLP_USER);
-
- if (HIWORD(wParam) == EN_CHANGE ||
- HIWORD(wParam) == BN_CLICKED)
- k5_id_check_mod(hwnd, d);
- break;
-
- case KHUI_WM_CFG_NOTIFY:
- d = (k5_id_dlg_data *) (LONG_PTR)
- GetWindowLongPtr(hwnd, DWLP_USER);
-
- if (HIWORD(wParam) == WMCFG_APPLY) {
- k5_id_write_params(hwnd, d);
- }
- break;
-
- case WM_DESTROY:
- d = (k5_id_dlg_data *) (LONG_PTR)
- GetWindowLongPtr(hwnd, DWLP_USER);
-
- khui_tracker_kill_controls(&d->tc_life);
- khui_tracker_kill_controls(&d->tc_renew);
-
- if (d->ident)
- kcdb_identity_release(d->ident);
-
- PFREE(d);
- break;
- }
- return FALSE;
-}
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<krbcred.h>
+#include<krb5.h>
+#include<assert.h>
+#include<lm.h>
+#include<commctrl.h>
+#include<shlwapi.h>
+
+#include<strsafe.h>
+
+typedef struct tag_k5_id_dlg_data {
+ khui_config_init_data cfg;
+
+ khm_handle ident;
+
+ khui_tracker tc_life;
+ khui_tracker tc_renew;
+
+ wchar_t ccache[KRB5_MAXCCH_CCNAME];
+
+ khm_boolean renewable;
+ khm_boolean forwardable;
+ khm_boolean proxiable;
+ khm_boolean addressless;
+
+ DWORD public_ip;
+
+ time_t life;
+ time_t renew_life;
+} k5_id_dlg_data;
+
+static void
+k5_id_read_params(k5_id_dlg_data * d) {
+
+ wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
+ khm_size cb;
+ khm_int32 rv;
+ khm_int32 t;
+ khm_handle csp_ident;
+ khm_handle csp_idroot = NULL;
+
+ cb = sizeof(idname);
+ rv = khui_cfg_get_name(d->cfg.ctx_node, idname, &cb);
+#ifdef DEBUG
+ assert(KHM_SUCCEEDED(rv));
+#endif
+
+ rv = kcdb_identity_create(idname, 0, &d->ident);
+#ifdef DEBUG
+ assert(KHM_SUCCEEDED(rv));
+#endif
+
+ rv = kcdb_identity_get_config(d->ident, 0, &csp_idroot);
+ if (KHM_SUCCEEDED(rv) &&
+ KHM_SUCCEEDED(khc_open_space(csp_idroot, CSNAME_KRB5CRED, 0,
+ &csp_ident))) {
+ khc_shadow_space(csp_ident, csp_params);
+ } else {
+ csp_ident = csp_params;
+ }
+
+ if (csp_idroot)
+ khc_close_space(csp_idroot);
+
+ rv = khc_read_int32(csp_ident, L"DefaultLifetime", &t);
+ if (KHM_SUCCEEDED(rv))
+ d->life = t;
+ else
+ d->life = 36000;
+
+ rv = khc_read_int32(csp_ident, L"DefaultRenewLifetime", &t);
+ if (KHM_SUCCEEDED(rv))
+ d->renew_life = t;
+ else
+ d->renew_life = 604800;
+
+ rv = khc_read_int32(csp_ident, L"Renewable", &t);
+ if (KHM_SUCCEEDED(rv))
+ d->renewable = !!t;
+ else
+ d->renewable = TRUE;
+
+ rv = khc_read_int32(csp_ident, L"Forwardable", &t);
+ if (KHM_SUCCEEDED(rv))
+ d->forwardable = !!t;
+ else
+ d->forwardable = FALSE;
+
+ rv = khc_read_int32(csp_ident, L"Proxiable", &t);
+ if (KHM_SUCCEEDED(rv))
+ d->proxiable = !!t;
+ else
+ d->proxiable = FALSE;
+
+ rv = khc_read_int32(csp_ident, L"Addressless", &t);
+ if (KHM_SUCCEEDED(rv))
+ d->addressless = !!t;
+ else
+ d->addressless = TRUE;
+
+ rv = khc_read_int32(csp_ident, L"PublicIP", &t);
+ if (KHM_SUCCEEDED(rv))
+ d->public_ip = (khm_ui_4) t;
+ else
+ d->public_ip = 0;
+
+ cb = sizeof(d->ccache);
+ rv = khc_read_string(csp_ident, L"DefaultCCName", d->ccache, &cb);
+ if (KHM_FAILED(rv) || cb <= sizeof(wchar_t)) {
+ cb = sizeof(d->ccache);
+ if (KHM_FAILED(kcdb_identity_get_attr(d->ident, attr_id_krb5_ccname,
+ NULL, d->ccache, &cb)))
+ ZeroMemory(d->ccache, sizeof(d->ccache));
+ }
+
+ khui_tracker_initialize(&d->tc_life);
+ d->tc_life.current = d->life;
+ d->tc_life.min = 0;
+ d->tc_life.max = 3600 * 24 * 7;
+
+ khui_tracker_initialize(&d->tc_renew);
+ d->tc_renew.current = d->renew_life;
+ d->tc_renew.min = 0;
+ d->tc_renew.max = 3600 * 24 * 30;
+
+ if (csp_ident != csp_params)
+ khc_close_space(csp_ident);
+}
+
+static khm_boolean
+k5_id_is_mod(HWND hw, k5_id_dlg_data * d) {
+ wchar_t ccache[KRB5_MAXCCH_CCNAME];
+ DWORD dwaddress = 0;
+
+ GetDlgItemText(hw, IDC_CFG_CCACHE, ccache, ARRAYLENGTH(ccache));
+
+ SendDlgItemMessage(hw, IDC_CFG_PUBLICIP, IPM_GETADDRESS,
+ 0, (LPARAM) &dwaddress);
+
+ if (_wcsicmp(ccache, d->ccache) ||
+
+ d->tc_renew.current != d->renew_life ||
+
+ d->tc_life.current != d->life ||
+
+ (IsDlgButtonChecked(hw, IDC_CFG_RENEW) == BST_CHECKED) != d->renewable ||
+
+ (IsDlgButtonChecked(hw, IDC_CFG_FORWARD) == BST_CHECKED) != d->forwardable ||
+
+ (IsDlgButtonChecked(hw, IDC_CFG_ADDRESSLESS) == BST_CHECKED)
+ != d->addressless ||
+
+ dwaddress != d->public_ip)
+
+ return TRUE;
+
+ return FALSE;
+}
+
+static void
+k5_id_check_mod(HWND hw, k5_id_dlg_data * d) {
+ BOOL modified = k5_id_is_mod(hw, d);
+
+ khui_cfg_set_flags_inst(&d->cfg,
+ (modified)?KHUI_CNFLAG_MODIFIED:0,
+ KHUI_CNFLAG_MODIFIED);
+}
+
+static void
+k5_id_write_params(HWND hw, k5_id_dlg_data * d) {
+
+ khm_handle csp_idroot = NULL;
+ khm_handle csp_ident = NULL;
+ wchar_t ccache[KRB5_MAXCCH_CCNAME];
+ khm_size cb;
+ khm_int32 rv;
+ khm_boolean b;
+ DWORD dwaddress = 0;
+
+ if (!k5_id_is_mod(hw, d))
+ return;
+
+ rv = kcdb_identity_get_config(d->ident, KHM_FLAG_CREATE, &csp_idroot);
+ if (KHM_SUCCEEDED(rv)) {
+ khc_open_space(csp_idroot, CSNAME_KRB5CRED,
+ KHM_FLAG_CREATE,
+ &csp_ident);
+ }
+
+ if (csp_idroot)
+ khc_close_space(csp_idroot);
+
+ if (!csp_ident)
+ return;
+
+ if (d->life != d->tc_life.current) {
+ d->life = d->tc_life.current;
+ khc_write_int32(csp_ident, L"DefaultLifetime", (khm_int32) d->life);
+ }
+
+ if (d->renew_life != d->tc_renew.current) {
+ d->renew_life = d->tc_renew.current;
+ khc_write_int32(csp_ident, L"DefaultRenewLifetime", (khm_int32) d->renew_life);
+ }
+
+ b = (IsDlgButtonChecked(hw, IDC_CFG_RENEW) == BST_CHECKED);
+ if (b != d->renewable) {
+ d->renewable = b;
+ khc_write_int32(csp_ident, L"Renewable", (khm_int32) b);
+ }
+
+ b = (IsDlgButtonChecked(hw, IDC_CFG_FORWARD) == BST_CHECKED);
+ if (b != d->forwardable) {
+ d->forwardable = b;
+ khc_write_int32(csp_ident, L"Forwardable", (khm_int32) b);
+ }
+
+ b = (IsDlgButtonChecked(hw, IDC_CFG_ADDRESSLESS) == BST_CHECKED);
+ if (b != d->addressless) {
+ d->addressless = b;
+ khc_write_int32(csp_ident, L"Addressless", (khm_int32) b);
+ }
+
+ SendDlgItemMessage(hw, IDC_CFG_PUBLICIP, IPM_GETADDRESS,
+ 0, (LPARAM) &dwaddress);
+
+ if (dwaddress != d->public_ip) {
+ d->public_ip = dwaddress;
+ khc_write_int32(csp_ident, L"PublicIP", (khm_int32) dwaddress);
+ }
+
+ GetDlgItemText(hw, IDC_CFG_CCACHE, ccache, ARRAYLENGTH(ccache));
+
+ if (SUCCEEDED(StringCbLength(ccache, sizeof(ccache), &cb)) &&
+ _wcsicmp(ccache, d->ccache)) {
+ khc_write_string(csp_ident, L"DefaultCCName", ccache);
+ StringCbCopy(d->ccache, sizeof(d->ccache), ccache);
+ } else {
+ khc_remove_value(csp_ident, L"DefaultCCName", KCONF_FLAG_USER);
+ }
+
+ if (csp_ident)
+ khc_close_space(csp_ident);
+
+ khui_cfg_set_flags_inst(&d->cfg,
+ KHUI_CNFLAG_APPLIED,
+ KHUI_CNFLAG_APPLIED | KHUI_CNFLAG_MODIFIED);
+}
+
+INT_PTR CALLBACK
+k5_id_tab_dlgproc(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam) {
+
+ k5_id_dlg_data * d;
+
+ switch(uMsg) {
+ case WM_INITDIALOG:
+ d = PMALLOC(sizeof(*d));
+#ifdef DEBUG
+ assert(d);
+#endif
+ ZeroMemory(d, sizeof(*d));
+
+ d->cfg = *((khui_config_init_data *) lParam);
+
+#pragma warning(push)
+#pragma warning(disable: 4244)
+ SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) d);
+#pragma warning(pop)
+
+ k5_id_read_params(d);
+
+ khui_tracker_install(GetDlgItem(hwnd, IDC_CFG_DEFLIFE),
+ &d->tc_life);
+ khui_tracker_install(GetDlgItem(hwnd, IDC_CFG_DEFRLIFE),
+ &d->tc_renew);
+ khui_tracker_refresh(&d->tc_life);
+ khui_tracker_refresh(&d->tc_renew);
+
+ SetDlgItemText(hwnd, IDC_CFG_CCACHE, d->ccache);
+
+ CheckDlgButton(hwnd, IDC_CFG_RENEW,
+ (d->renewable? BST_CHECKED: BST_UNCHECKED));
+
+ CheckDlgButton(hwnd, IDC_CFG_FORWARD,
+ (d->forwardable? BST_CHECKED: BST_UNCHECKED));
+
+ CheckDlgButton(hwnd, IDC_CFG_ADDRESSLESS,
+ (d->addressless? BST_CHECKED: BST_UNCHECKED));
+
+ SendDlgItemMessage(hwnd, IDC_CFG_PUBLICIP,
+ IPM_SETADDRESS,
+ 0, (LPARAM) d->public_ip);
+ break;
+
+ case WM_COMMAND:
+ d = (k5_id_dlg_data *) (LONG_PTR)
+ GetWindowLongPtr(hwnd, DWLP_USER);
+
+ if (HIWORD(wParam) == EN_CHANGE ||
+ HIWORD(wParam) == BN_CLICKED)
+ k5_id_check_mod(hwnd, d);
+ break;
+
+ case KHUI_WM_CFG_NOTIFY:
+ d = (k5_id_dlg_data *) (LONG_PTR)
+ GetWindowLongPtr(hwnd, DWLP_USER);
+
+ if (HIWORD(wParam) == WMCFG_APPLY) {
+ k5_id_write_params(hwnd, d);
+ }
+ break;
+
+ case WM_DESTROY:
+ d = (k5_id_dlg_data *) (LONG_PTR)
+ GetWindowLongPtr(hwnd, DWLP_USER);
+
+ khui_tracker_kill_controls(&d->tc_life);
+ khui_tracker_kill_controls(&d->tc_renew);
+
+ if (d->ident)
+ kcdb_identity_release(d->ident);
+
+ PFREE(d);
+ break;
+ }
+ return FALSE;
+}
diff --git a/src/windows/identity/plugins/krb5/krb5configids.c b/src/windows/identity/plugins/krb5/krb5configids.c
index 5f4729253e..8d6afd4731 100644
--- a/src/windows/identity/plugins/krb5/krb5configids.c
+++ b/src/windows/identity/plugins/krb5/krb5configids.c
@@ -1,270 +1,270 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<krbcred.h>
-#include<krb5.h>
-#include<assert.h>
-#include<lm.h>
-#include<commctrl.h>
-#include<shlwapi.h>
-
-typedef struct tag_k5_ids_opts {
- khm_int32 renewable;
- khm_int32 forwardable;
- khm_int32 addressless;
-} k5_ids_opts;
-
-typedef struct tag_k5_ids_dlg_data {
- khui_config_init_data cfg;
-
- khui_tracker tc_life;
- khui_tracker tc_renew;
- khui_tracker tc_life_min;
- khui_tracker tc_life_max;
- khui_tracker tc_renew_min;
- khui_tracker tc_renew_max;
-
- time_t life;
- time_t renew_life;
- time_t life_min;
- time_t life_max;
- time_t renew_min;
- time_t renew_max;
-
- k5_ids_opts opt;
- k5_ids_opts opt_saved;
-
-} k5_ids_dlg_data;
-
-static khm_boolean
-k5_ids_is_mod(k5_ids_dlg_data * d) {
- if (d->life != d->tc_life.current ||
- d->renew_life != d->tc_renew.current ||
- d->life_max != d->tc_life_max.current ||
- d->life_min != d->tc_life_min.current ||
- d->renew_max != d->tc_renew_max.current ||
- d->renew_min != d->tc_renew_min.current ||
- !!d->opt.renewable != !!d->opt_saved.renewable ||
- !!d->opt.forwardable != !!d->opt_saved.forwardable ||
- !!d->opt.addressless != !!d->opt_saved.addressless)
- return TRUE;
- return FALSE;
-}
-
-static void
-k5_ids_check_mod(k5_ids_dlg_data * d) {
- BOOL modified = k5_ids_is_mod(d);
-
- khui_cfg_set_flags_inst(&d->cfg,
- (modified)?KHUI_CNFLAG_MODIFIED:0,
- KHUI_CNFLAG_MODIFIED);
-}
-
-static void
-k5_ids_write_params(k5_ids_dlg_data * d) {
-
- khm_int32 rv;
-
-#ifdef DEBUG
- assert(csp_params);
-#endif
-
- if (!k5_ids_is_mod(d))
- return;
-
-#define WRITEPARAM(po,pn,vn) \
- if (po != pn) { \
- po = pn; \
- rv = khc_write_int32(csp_params, vn, (khm_int32) po); \
- assert(KHM_SUCCEEDED(rv)); \
- }
-
- WRITEPARAM(d->life,d->tc_life.current, L"DefaultLifetime");
- WRITEPARAM(d->renew_life,d->tc_renew.current, L"DefaultRenewLifetime");
- WRITEPARAM(d->life_max,d->tc_life_max.current, L"MaxLifetime");
- WRITEPARAM(d->life_min,d->tc_life_min.current, L"MinLifetime");
- WRITEPARAM(d->renew_max,d->tc_renew_max.current, L"MaxRenewLifetime");
- WRITEPARAM(d->renew_min,d->tc_renew_min.current, L"MinRenewLifetime");
- WRITEPARAM(d->opt_saved.renewable, d->opt.renewable, L"Renewable");
- WRITEPARAM(d->opt_saved.forwardable, d->opt.forwardable, L"Forwardable");
- WRITEPARAM(d->opt_saved.addressless, d->opt.addressless, L"Addressless");
-
-#undef WRITEPARAM
-
- khui_cfg_set_flags_inst(&d->cfg,
- KHUI_CNFLAG_APPLIED,
- KHUI_CNFLAG_APPLIED | KHUI_CNFLAG_MODIFIED);
-}
-
-static void
-k5_ids_read_params(k5_ids_dlg_data * d) {
- k5_params p;
-
- khm_krb5_get_identity_params(NULL, &p);
-
- d->life = p.lifetime;
- d->life_max = p.lifetime_max;
- d->life_min = p.lifetime_min;
-
- d->renew_life = p.renew_life;
- d->renew_max = p.renew_life_max;
- d->renew_min = p.renew_life_min;
-
- d->opt_saved.forwardable = p.forwardable;
- d->opt_saved.renewable = p.renewable;
- d->opt_saved.addressless = p.addressless;
-
- d->opt = d->opt_saved;
-
- khui_tracker_initialize(&d->tc_life);
- d->tc_life.current = d->life;
- d->tc_life.min = 0;
- d->tc_life.max = 3600 * 24 * 7;
-
- khui_tracker_initialize(&d->tc_renew);
- d->tc_renew.current = d->renew_life;
- d->tc_renew.min = 0;
- d->tc_renew.max = 3600 * 24 * 30;
-
- khui_tracker_initialize(&d->tc_life_min);
- d->tc_life_min.current = d->life_min;
- d->tc_life_min.min = d->tc_life.min;
- d->tc_life_min.max = d->tc_life.max;
-
- khui_tracker_initialize(&d->tc_life_max);
- d->tc_life_max.current = d->life_max;
- d->tc_life_max.min = d->tc_life.min;
- d->tc_life_max.max = d->tc_life.max;
-
- khui_tracker_initialize(&d->tc_renew_min);
- d->tc_renew_min.current = d->renew_min;
- d->tc_renew_min.min = d->tc_renew.min;
- d->tc_renew_min.max = d->tc_renew.max;
-
- khui_tracker_initialize(&d->tc_renew_max);
- d->tc_renew_max.current = d->renew_max;
- d->tc_renew_max.min = d->tc_renew.min;
- d->tc_renew_max.max = d->tc_renew.max;
-}
-
-INT_PTR CALLBACK
-k5_ids_tab_dlgproc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam) {
- k5_ids_dlg_data * d;
-
- switch(uMsg) {
- case WM_INITDIALOG:
- d = PMALLOC(sizeof(*d));
-#ifdef DEBUG
- assert(d);
-#endif
- ZeroMemory(d, sizeof(*d));
-#pragma warning(push)
-#pragma warning(disable: 4244)
- SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) d);
-#pragma warning(pop)
-
- d->cfg = *((khui_config_init_data *) lParam);
-
- k5_ids_read_params(d);
-
- khui_tracker_install(GetDlgItem(hwnd, IDC_CFG_DEFLIFE),
- &d->tc_life);
- khui_tracker_install(GetDlgItem(hwnd, IDC_CFG_DEFRLIFE),
- &d->tc_renew);
- khui_tracker_install(GetDlgItem(hwnd, IDC_CFG_LRNG_MIN),
- &d->tc_life_min);
- khui_tracker_install(GetDlgItem(hwnd, IDC_CFG_LRNG_MAX),
- &d->tc_life_max);
- khui_tracker_install(GetDlgItem(hwnd, IDC_CFG_RLRNG_MIN),
- &d->tc_renew_min);
- khui_tracker_install(GetDlgItem(hwnd, IDC_CFG_RLRNG_MAX),
- &d->tc_renew_max);
- khui_tracker_refresh(&d->tc_life);
- khui_tracker_refresh(&d->tc_life_min);
- khui_tracker_refresh(&d->tc_life_max);
- khui_tracker_refresh(&d->tc_renew);
- khui_tracker_refresh(&d->tc_renew_min);
- khui_tracker_refresh(&d->tc_renew_max);
-
- CheckDlgButton(hwnd, IDC_CFG_RENEW, (d->opt.renewable ? BST_CHECKED: BST_UNCHECKED));
- CheckDlgButton(hwnd, IDC_CFG_FORWARD, (d->opt.forwardable ? BST_CHECKED: BST_UNCHECKED));
- CheckDlgButton(hwnd, IDC_CFG_ADDRESSLESS, (d->opt.addressless ? BST_CHECKED: BST_UNCHECKED));
- break;
-
- case WM_COMMAND:
- d = (k5_ids_dlg_data *) (LONG_PTR)
- GetWindowLongPtr(hwnd, DWLP_USER);
-
- if (HIWORD(wParam) == EN_CHANGE) {
- k5_ids_check_mod(d);
- } else if (HIWORD(wParam) == BN_CLICKED) {
- switch (LOWORD(wParam)) {
- case IDC_CFG_RENEW:
- d->opt.renewable = (IsDlgButtonChecked(hwnd, IDC_CFG_RENEW) == BST_CHECKED);
- break;
-
- case IDC_CFG_FORWARD:
- d->opt.forwardable = (IsDlgButtonChecked(hwnd, IDC_CFG_FORWARD) == BST_CHECKED);
- break;
-
- case IDC_CFG_ADDRESSLESS:
- d->opt.addressless = (IsDlgButtonChecked(hwnd, IDC_CFG_ADDRESSLESS) == BST_CHECKED);
- break;
- }
-
- k5_ids_check_mod(d);
- }
- break;
-
- case KHUI_WM_CFG_NOTIFY:
- d = (k5_ids_dlg_data *) (LONG_PTR)
- GetWindowLongPtr(hwnd, DWLP_USER);
- if (HIWORD(wParam) == WMCFG_APPLY) {
- k5_ids_write_params(d);
- }
- break;
-
- case WM_DESTROY:
- d = (k5_ids_dlg_data *) (LONG_PTR)
- GetWindowLongPtr(hwnd, DWLP_USER);
-
- khui_tracker_kill_controls(&d->tc_life);
- khui_tracker_kill_controls(&d->tc_renew);
- khui_tracker_kill_controls(&d->tc_life_min);
- khui_tracker_kill_controls(&d->tc_life_max);
- khui_tracker_kill_controls(&d->tc_renew_min);
- khui_tracker_kill_controls(&d->tc_renew_max);
-
- PFREE(d);
- break;
- }
- return FALSE;
-}
-
-
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<krbcred.h>
+#include<krb5.h>
+#include<assert.h>
+#include<lm.h>
+#include<commctrl.h>
+#include<shlwapi.h>
+
+typedef struct tag_k5_ids_opts {
+ khm_int32 renewable;
+ khm_int32 forwardable;
+ khm_int32 addressless;
+} k5_ids_opts;
+
+typedef struct tag_k5_ids_dlg_data {
+ khui_config_init_data cfg;
+
+ khui_tracker tc_life;
+ khui_tracker tc_renew;
+ khui_tracker tc_life_min;
+ khui_tracker tc_life_max;
+ khui_tracker tc_renew_min;
+ khui_tracker tc_renew_max;
+
+ time_t life;
+ time_t renew_life;
+ time_t life_min;
+ time_t life_max;
+ time_t renew_min;
+ time_t renew_max;
+
+ k5_ids_opts opt;
+ k5_ids_opts opt_saved;
+
+} k5_ids_dlg_data;
+
+static khm_boolean
+k5_ids_is_mod(k5_ids_dlg_data * d) {
+ if (d->life != d->tc_life.current ||
+ d->renew_life != d->tc_renew.current ||
+ d->life_max != d->tc_life_max.current ||
+ d->life_min != d->tc_life_min.current ||
+ d->renew_max != d->tc_renew_max.current ||
+ d->renew_min != d->tc_renew_min.current ||
+ !!d->opt.renewable != !!d->opt_saved.renewable ||
+ !!d->opt.forwardable != !!d->opt_saved.forwardable ||
+ !!d->opt.addressless != !!d->opt_saved.addressless)
+ return TRUE;
+ return FALSE;
+}
+
+static void
+k5_ids_check_mod(k5_ids_dlg_data * d) {
+ BOOL modified = k5_ids_is_mod(d);
+
+ khui_cfg_set_flags_inst(&d->cfg,
+ (modified)?KHUI_CNFLAG_MODIFIED:0,
+ KHUI_CNFLAG_MODIFIED);
+}
+
+static void
+k5_ids_write_params(k5_ids_dlg_data * d) {
+
+ khm_int32 rv;
+
+#ifdef DEBUG
+ assert(csp_params);
+#endif
+
+ if (!k5_ids_is_mod(d))
+ return;
+
+#define WRITEPARAM(po,pn,vn) \
+ if (po != pn) { \
+ po = pn; \
+ rv = khc_write_int32(csp_params, vn, (khm_int32) po); \
+ assert(KHM_SUCCEEDED(rv)); \
+ }
+
+ WRITEPARAM(d->life,d->tc_life.current, L"DefaultLifetime");
+ WRITEPARAM(d->renew_life,d->tc_renew.current, L"DefaultRenewLifetime");
+ WRITEPARAM(d->life_max,d->tc_life_max.current, L"MaxLifetime");
+ WRITEPARAM(d->life_min,d->tc_life_min.current, L"MinLifetime");
+ WRITEPARAM(d->renew_max,d->tc_renew_max.current, L"MaxRenewLifetime");
+ WRITEPARAM(d->renew_min,d->tc_renew_min.current, L"MinRenewLifetime");
+ WRITEPARAM(d->opt_saved.renewable, d->opt.renewable, L"Renewable");
+ WRITEPARAM(d->opt_saved.forwardable, d->opt.forwardable, L"Forwardable");
+ WRITEPARAM(d->opt_saved.addressless, d->opt.addressless, L"Addressless");
+
+#undef WRITEPARAM
+
+ khui_cfg_set_flags_inst(&d->cfg,
+ KHUI_CNFLAG_APPLIED,
+ KHUI_CNFLAG_APPLIED | KHUI_CNFLAG_MODIFIED);
+}
+
+static void
+k5_ids_read_params(k5_ids_dlg_data * d) {
+ k5_params p;
+
+ khm_krb5_get_identity_params(NULL, &p);
+
+ d->life = p.lifetime;
+ d->life_max = p.lifetime_max;
+ d->life_min = p.lifetime_min;
+
+ d->renew_life = p.renew_life;
+ d->renew_max = p.renew_life_max;
+ d->renew_min = p.renew_life_min;
+
+ d->opt_saved.forwardable = p.forwardable;
+ d->opt_saved.renewable = p.renewable;
+ d->opt_saved.addressless = p.addressless;
+
+ d->opt = d->opt_saved;
+
+ khui_tracker_initialize(&d->tc_life);
+ d->tc_life.current = d->life;
+ d->tc_life.min = 0;
+ d->tc_life.max = 3600 * 24 * 7;
+
+ khui_tracker_initialize(&d->tc_renew);
+ d->tc_renew.current = d->renew_life;
+ d->tc_renew.min = 0;
+ d->tc_renew.max = 3600 * 24 * 30;
+
+ khui_tracker_initialize(&d->tc_life_min);
+ d->tc_life_min.current = d->life_min;
+ d->tc_life_min.min = d->tc_life.min;
+ d->tc_life_min.max = d->tc_life.max;
+
+ khui_tracker_initialize(&d->tc_life_max);
+ d->tc_life_max.current = d->life_max;
+ d->tc_life_max.min = d->tc_life.min;
+ d->tc_life_max.max = d->tc_life.max;
+
+ khui_tracker_initialize(&d->tc_renew_min);
+ d->tc_renew_min.current = d->renew_min;
+ d->tc_renew_min.min = d->tc_renew.min;
+ d->tc_renew_min.max = d->tc_renew.max;
+
+ khui_tracker_initialize(&d->tc_renew_max);
+ d->tc_renew_max.current = d->renew_max;
+ d->tc_renew_max.min = d->tc_renew.min;
+ d->tc_renew_max.max = d->tc_renew.max;
+}
+
+INT_PTR CALLBACK
+k5_ids_tab_dlgproc(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam) {
+ k5_ids_dlg_data * d;
+
+ switch(uMsg) {
+ case WM_INITDIALOG:
+ d = PMALLOC(sizeof(*d));
+#ifdef DEBUG
+ assert(d);
+#endif
+ ZeroMemory(d, sizeof(*d));
+#pragma warning(push)
+#pragma warning(disable: 4244)
+ SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) d);
+#pragma warning(pop)
+
+ d->cfg = *((khui_config_init_data *) lParam);
+
+ k5_ids_read_params(d);
+
+ khui_tracker_install(GetDlgItem(hwnd, IDC_CFG_DEFLIFE),
+ &d->tc_life);
+ khui_tracker_install(GetDlgItem(hwnd, IDC_CFG_DEFRLIFE),
+ &d->tc_renew);
+ khui_tracker_install(GetDlgItem(hwnd, IDC_CFG_LRNG_MIN),
+ &d->tc_life_min);
+ khui_tracker_install(GetDlgItem(hwnd, IDC_CFG_LRNG_MAX),
+ &d->tc_life_max);
+ khui_tracker_install(GetDlgItem(hwnd, IDC_CFG_RLRNG_MIN),
+ &d->tc_renew_min);
+ khui_tracker_install(GetDlgItem(hwnd, IDC_CFG_RLRNG_MAX),
+ &d->tc_renew_max);
+ khui_tracker_refresh(&d->tc_life);
+ khui_tracker_refresh(&d->tc_life_min);
+ khui_tracker_refresh(&d->tc_life_max);
+ khui_tracker_refresh(&d->tc_renew);
+ khui_tracker_refresh(&d->tc_renew_min);
+ khui_tracker_refresh(&d->tc_renew_max);
+
+ CheckDlgButton(hwnd, IDC_CFG_RENEW, (d->opt.renewable ? BST_CHECKED: BST_UNCHECKED));
+ CheckDlgButton(hwnd, IDC_CFG_FORWARD, (d->opt.forwardable ? BST_CHECKED: BST_UNCHECKED));
+ CheckDlgButton(hwnd, IDC_CFG_ADDRESSLESS, (d->opt.addressless ? BST_CHECKED: BST_UNCHECKED));
+ break;
+
+ case WM_COMMAND:
+ d = (k5_ids_dlg_data *) (LONG_PTR)
+ GetWindowLongPtr(hwnd, DWLP_USER);
+
+ if (HIWORD(wParam) == EN_CHANGE) {
+ k5_ids_check_mod(d);
+ } else if (HIWORD(wParam) == BN_CLICKED) {
+ switch (LOWORD(wParam)) {
+ case IDC_CFG_RENEW:
+ d->opt.renewable = (IsDlgButtonChecked(hwnd, IDC_CFG_RENEW) == BST_CHECKED);
+ break;
+
+ case IDC_CFG_FORWARD:
+ d->opt.forwardable = (IsDlgButtonChecked(hwnd, IDC_CFG_FORWARD) == BST_CHECKED);
+ break;
+
+ case IDC_CFG_ADDRESSLESS:
+ d->opt.addressless = (IsDlgButtonChecked(hwnd, IDC_CFG_ADDRESSLESS) == BST_CHECKED);
+ break;
+ }
+
+ k5_ids_check_mod(d);
+ }
+ break;
+
+ case KHUI_WM_CFG_NOTIFY:
+ d = (k5_ids_dlg_data *) (LONG_PTR)
+ GetWindowLongPtr(hwnd, DWLP_USER);
+ if (HIWORD(wParam) == WMCFG_APPLY) {
+ k5_ids_write_params(d);
+ }
+ break;
+
+ case WM_DESTROY:
+ d = (k5_ids_dlg_data *) (LONG_PTR)
+ GetWindowLongPtr(hwnd, DWLP_USER);
+
+ khui_tracker_kill_controls(&d->tc_life);
+ khui_tracker_kill_controls(&d->tc_renew);
+ khui_tracker_kill_controls(&d->tc_life_min);
+ khui_tracker_kill_controls(&d->tc_life_max);
+ khui_tracker_kill_controls(&d->tc_renew_min);
+ khui_tracker_kill_controls(&d->tc_renew_max);
+
+ PFREE(d);
+ break;
+ }
+ return FALSE;
+}
+
+
diff --git a/src/windows/identity/plugins/krb5/krb5funcs.c b/src/windows/identity/plugins/krb5/krb5funcs.c
index e66e755a74..6f657e8519 100644
--- a/src/windows/identity/plugins/krb5/krb5funcs.c
+++ b/src/windows/identity/plugins/krb5/krb5funcs.c
@@ -1,3487 +1,3487 @@
-/*
-* Copyright (c) 2005 Massachusetts Institute of Technology
-* Copyright (c) 2006,2007 Secure Endpoints Inc.
-*
-* Permission is hereby granted, free of charge, to any person
-* obtaining a copy of this software and associated documentation
-* files (the "Software"), to deal in the Software without
-* restriction, including without limitation the rights to use, copy,
-* modify, merge, publish, distribute, sublicense, and/or sell copies
-* of the Software, and to permit persons to whom the Software is
-* furnished to do so, subject to the following conditions:
-*
-* The above copyright notice and this permission notice shall be
-* included in all copies or substantial portions of the Software.
-*
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
-* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
-* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-* SOFTWARE.
-*/
-
-/* $Id$ */
-
-/* Originally this was krb5routines.c in Leash sources. Subsequently
- * modified and adapted for NetIDMgr */
-
-#include<krbcred.h>
-#include<kherror.h>
-
-#define SECURITY_WIN32
-#include <security.h>
-
-#include <string.h>
-#include <time.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <strsafe.h>
-
-long
-khm_convert524(krb5_context alt_ctx)
-{
- krb5_context ctx = 0;
- krb5_error_code code = 0;
- int icode = 0;
- krb5_principal me = 0;
- krb5_principal server = 0;
- krb5_creds *v5creds = 0;
- krb5_creds increds;
- krb5_ccache cc = 0;
- CREDENTIALS * v4creds = NULL;
- static int init_ets = 1;
-
- if (!pkrb5_init_context ||
- !pkrb_in_tkt ||
- !pkrb524_init_ets ||
- !pkrb524_convert_creds_kdc)
- return 0;
-
- v4creds = (CREDENTIALS *) PMALLOC(sizeof(CREDENTIALS));
- memset((char *) v4creds, 0, sizeof(CREDENTIALS));
-
- memset((char *) &increds, 0, sizeof(increds));
- /*
- From this point on, we can goto cleanup because increds is
- initialized.
- */
-
- if (alt_ctx)
- {
- ctx = alt_ctx;
- }
- else
- {
- code = pkrb5_init_context(&ctx);
- if (code) goto cleanup;
- }
-
- code = pkrb5_cc_default(ctx, &cc);
- if (code) goto cleanup;
-
- if ( init_ets ) {
- pkrb524_init_ets(ctx);
- init_ets = 0;
- }
-
- if (code = pkrb5_cc_get_principal(ctx, cc, &me))
- goto cleanup;
-
- if ((code = pkrb5_build_principal(ctx,
- &server,
- krb5_princ_realm(ctx, me)->length,
- krb5_princ_realm(ctx, me)->data,
- "krbtgt",
- krb5_princ_realm(ctx, me)->data,
- NULL)))
- {
- goto cleanup;
- }
-
- increds.client = me;
- increds.server = server;
- increds.times.endtime = 0;
- increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC;
- if ((code = pkrb5_get_credentials(ctx, 0,
- cc,
- &increds,
- &v5creds)))
- {
- goto cleanup;
- }
-
- if ((icode = pkrb524_convert_creds_kdc(ctx,
- v5creds,
- v4creds)))
- {
- goto cleanup;
- }
-
- /* initialize ticket cache */
- if ((icode = pkrb_in_tkt(v4creds->pname, v4creds->pinst, v4creds->realm)
- != KSUCCESS))
- {
- goto cleanup;
- }
- /* stash ticket, session key, etc. for future use */
- if ((icode = pkrb_save_credentials(v4creds->service,
- v4creds->instance,
- v4creds->realm,
- v4creds->session,
- v4creds->lifetime,
- v4creds->kvno,
- &(v4creds->ticket_st),
- v4creds->issue_date)))
- {
- goto cleanup;
- }
-
-cleanup:
- memset(v4creds, 0, sizeof(v4creds));
- PFREE(v4creds);
-
- if (v5creds) {
- pkrb5_free_creds(ctx, v5creds);
- }
- if (increds.client == me)
- me = 0;
- if (increds.server == server)
- server = 0;
- pkrb5_free_cred_contents(ctx, &increds);
- if (server) {
- pkrb5_free_principal(ctx, server);
- }
- if (me) {
- pkrb5_free_principal(ctx, me);
- }
- pkrb5_cc_close(ctx, cc);
-
- if (ctx && (ctx != alt_ctx)) {
- pkrb5_free_context(ctx);
- }
- return !(code || icode);
-}
-
-#ifdef DEPRECATED_REMOVABLE
-int com_addr(void)
-{
- long ipAddr;
- char loc_addr[ADDR_SZ];
- CREDENTIALS cred;
- char service[40];
- char instance[40];
- // char addr[40];
- char realm[40];
- struct in_addr LocAddr;
- int k_errno;
-
- if (pkrb_get_cred == NULL)
- return(KSUCCESS);
-
- k_errno = (*pkrb_get_cred)(service,instance,realm,&cred);
- if (k_errno)
- return KRBERR(k_errno);
-
- while(1) {
- ipAddr = (*pLocalHostAddr)();
- LocAddr.s_addr = ipAddr;
- StringCbCopyA(loc_addr, sizeof(loc_addr), inet_ntoa(LocAddr));
- if ( strcmp(cred.address, loc_addr) != 0) {
- /* TODO: do something about this */
- //Leash_kdestroy ();
- break;
- }
- break;
- } // while()
- return 0;
-}
-#endif
-
-/* we use these structures to keep track of identities that we find
- while going through the API, FILE and MSLSA caches and enumerating
- credentials. The only identities we want to keep track of are the
- ones that have an initial ticket. We collect information for each
- of the identities we find that we have initial tickets for and
- then set the properties for the identities at once. */
-
-typedef struct tag_ident_data {
- khm_handle ident; /* handle to the identity */
- khm_int32 count; /* number of initial tickets we have
- found for this identity. */
- wchar_t ccname[MAX_PATH];
- FILETIME ft_issue;
- FILETIME ft_expire;
- FILETIME ft_renewexpire;
- khm_int32 krb5_flags;
-} ident_data;
-
-typedef struct tag_identlist {
- ident_data * list;
- khm_size n_list;
- khm_size nc_list;
-} identlist;
-
-#define IDLIST_ALLOC_INCR 8
-
-static void
-tc_prep_idlist(identlist * idlist) {
- khm_int32 rv;
- khm_size cb_ids = 0;
- khm_size n_ids = 0;
- khm_size i;
- wchar_t * ids = NULL;
- wchar_t *thisid;
-
- idlist->list = NULL;
- idlist->n_list = 0;
- idlist->nc_list = 0;
-
- do {
-
- if (ids) {
- PFREE(ids);
- ids = NULL;
- }
-
- rv = kcdb_identity_enum(KCDB_IDENT_FLAG_ACTIVE,
- KCDB_IDENT_FLAG_ACTIVE,
- NULL,
- &cb_ids,
- &n_ids);
-
- if (rv != KHM_ERROR_TOO_LONG)
- break; /* something else is wrong */
-
- if (n_ids == 0 || cb_ids == 0)
- break; /* no identities to process */
-
-#ifdef DEBUG
- assert(cb_ids > 0);
-#endif
-
- ids = PMALLOC(cb_ids);
-#ifdef DEBUG
- assert(ids != NULL);
-#endif
- if (ids == NULL)
- break;
-
- rv = kcdb_identity_enum(KCDB_IDENT_FLAG_ACTIVE,
- KCDB_IDENT_FLAG_ACTIVE,
- ids,
- &cb_ids,
- &n_ids);
-
- if (KHM_SUCCEEDED(rv))
- break;
-
- } while (TRUE);
-
- if (ids == NULL)
- return;
-
- if (KHM_FAILED(rv) || n_ids == 0) {
- if (ids)
- PFREE(ids);
- return;
- }
-
- idlist->nc_list = UBOUNDSS(n_ids, IDLIST_ALLOC_INCR, IDLIST_ALLOC_INCR);
-
- idlist->list = PCALLOC(idlist->nc_list, sizeof(idlist->list[0]));
-
- for (i = 0, thisid = ids;
- thisid && thisid[0];
- thisid = multi_string_next(thisid)) {
-
- khm_handle ident;
-
- rv = kcdb_identity_create(thisid, 0, &ident);
-
- if (KHM_FAILED(rv))
- continue;
-
- idlist->list[i].ident = ident;
- idlist->list[i].count = 0;
-
- i++;
- }
-
- idlist->n_list = i;
-
- PFREE(ids);
-}
-
-static ident_data *
-tc_add_ident_to_list(identlist * idlist, khm_handle ident) {
- khm_size i;
- ident_data * d;
-
- for (i=0; i < idlist->n_list; i++) {
- if (kcdb_identity_is_equal(ident, idlist->list[i].ident))
- break;
- }
-
- if (i < idlist->n_list) {
- /* we already have this identity on our list. Increment the
- count */
- idlist->list[i].count++;
- return &idlist->list[i];
- }
-
- /* it wasn't in our list. Add it */
-
- if (idlist->n_list + 1 > idlist->nc_list) {
- idlist->nc_list = UBOUNDSS(idlist->n_list + 1,
- IDLIST_ALLOC_INCR,
- IDLIST_ALLOC_INCR);
-#ifdef DEBUG
- assert(idlist->n_list + 1 <= idlist->nc_list);
-#endif
- idlist->list = PREALLOC(idlist->list,
- sizeof(idlist->list[0]) * idlist->nc_list);
-#ifdef DEBUG
- assert(idlist->list);
-#endif
- ZeroMemory(&idlist->list[idlist->n_list],
- sizeof(idlist->list[0]) *
- (idlist->nc_list - idlist->n_list));
- }
-
- d = &idlist->list[idlist->n_list];
-
- ZeroMemory(d, sizeof(*d));
-
- d->ident = ident;
- d->count = 1;
-
- idlist->n_list++;
-
- kcdb_identity_hold(ident);
-
- return d;
-}
-
-static void
-tc_set_ident_data(identlist * idlist) {
- khm_size i;
- wchar_t k5idtype[KCDB_MAXCCH_NAME];
-
- k5idtype[0] = L'\0';
- LoadString(hResModule, IDS_KRB5_NC_NAME,
- k5idtype, ARRAYLENGTH(k5idtype));
-
- for (i=0; i < idlist->n_list; i++) {
-#ifdef DEBUG
- assert(idlist->list[i].ident);
-#endif
-
- if (idlist->list[i].count > 0) {
- khm_int32 t;
-
- t = credtype_id_krb5;
- kcdb_identity_set_attr(idlist->list[i].ident,
- KCDB_ATTR_TYPE,
- &t,
- sizeof(t));
-
- /* We need to manually add the type name if we want the
- name to show up in the property list for the identity.
- The type name is only automatically calculated for
- credentials. */
- kcdb_identity_set_attr(idlist->list[i].ident,
- KCDB_ATTR_TYPE_NAME,
- k5idtype,
- KCDB_CBSIZE_AUTO);
-
- kcdb_identity_set_attr(idlist->list[i].ident,
- attr_id_krb5_ccname,
- idlist->list[i].ccname,
- KCDB_CBSIZE_AUTO);
-
- kcdb_identity_set_attr(idlist->list[i].ident,
- KCDB_ATTR_EXPIRE,
- &idlist->list[i].ft_expire,
- sizeof(idlist->list[i].ft_expire));
-
- kcdb_identity_set_attr(idlist->list[i].ident,
- KCDB_ATTR_ISSUE,
- &idlist->list[i].ft_issue,
- sizeof(idlist->list[i].ft_issue));
-
- kcdb_identity_set_attr(idlist->list[i].ident,
- attr_id_krb5_flags,
- &idlist->list[i].krb5_flags,
- sizeof(idlist->list[i].krb5_flags));
-
- if (idlist->list[i].ft_renewexpire.dwLowDateTime == 0 &&
- idlist->list[i].ft_renewexpire.dwHighDateTime == 0) {
- kcdb_identity_set_attr(idlist->list[i].ident,
- KCDB_ATTR_RENEW_EXPIRE,
- NULL, 0);
- } else {
- kcdb_identity_set_attr(idlist->list[i].ident,
- KCDB_ATTR_RENEW_EXPIRE,
- &idlist->list[i].ft_renewexpire,
- sizeof(idlist->list[i].ft_renewexpire));
- }
-
- } else {
- /* We didn't see any TGTs for this identity. We have to
- remove all the Krb5 supplied properties. */
-
- khm_int32 t;
- khm_size cb;
-
- cb = sizeof(t);
- if (KHM_SUCCEEDED(kcdb_identity_get_attr(idlist->list[i].ident,
- KCDB_ATTR_TYPE, NULL,
- &t,
- &cb)) &&
- t == credtype_id_krb5) {
-
- /* disown this and remove all our properties. the
- system will GC this identity if nobody claims it.*/
-
- kcdb_identity_set_attr(idlist->list[i].ident,
- KCDB_ATTR_TYPE, NULL, 0);
- kcdb_identity_set_attr(idlist->list[i].ident,
- KCDB_ATTR_TYPE_NAME, NULL, 0);
- kcdb_identity_set_attr(idlist->list[i].ident,
- attr_id_krb5_ccname, NULL, 0);
- kcdb_identity_set_attr(idlist->list[i].ident,
- KCDB_ATTR_EXPIRE, NULL, 0);
- kcdb_identity_set_attr(idlist->list[i].ident,
- KCDB_ATTR_ISSUE, NULL, 0);
- kcdb_identity_set_attr(idlist->list[i].ident,
- attr_id_krb5_flags, NULL, 0);
- kcdb_identity_set_attr(idlist->list[i].ident,
- KCDB_ATTR_RENEW_EXPIRE, NULL, 0);
- } else {
- /* otherwise, this identity doesn't belong to us. We
- should leave it as is. */
- }
- }
- }
-}
-
-static void
-tc_free_idlist(identlist * idlist) {
- khm_size i;
-
- for (i=0; i < idlist->n_list; i++) {
- if (idlist->list[i].ident != NULL) {
- kcdb_identity_release(idlist->list[i].ident);
- idlist->list[i].ident = NULL;
- }
- }
-
- if (idlist->list)
- PFREE(idlist->list);
- idlist->list = NULL;
- idlist->n_list = 0;
- idlist->nc_list = 0;
-}
-
-#ifndef ENCTYPE_LOCAL_RC4_MD4
-#define ENCTYPE_LOCAL_RC4_MD4 0xFFFFFF80
-#endif
-
-#define MAX_ADDRS 256
-
-static long get_tickets_from_cache(krb5_context ctx,
- krb5_ccache cache,
- identlist * idlist)
-{
- krb5_error_code code;
- krb5_principal KRBv5Principal;
- krb5_flags flags = 0;
- krb5_cc_cursor KRBv5Cursor;
- krb5_creds KRBv5Credentials;
- krb5_ticket *tkt=NULL;
- char *ClientName = NULL;
- char *PrincipalName = NULL;
- wchar_t wbuf[256]; /* temporary conversion buffer */
- wchar_t wcc_name[KRB5_MAXCCH_CCNAME]; /* credential cache name */
- char *sServerName = NULL;
- khm_handle ident = NULL;
- khm_handle cred = NULL;
- time_t tt;
- FILETIME ft, eft;
- khm_int32 ti;
-
-#ifdef KRB5_TC_NOTICKET
- flags = KRB5_TC_NOTICKET;
-#else
- flags = 0;
-#endif
-
- {
- const char * cc_name;
- const char * cc_type;
-
- cc_name = (*pkrb5_cc_get_name)(ctx, cache);
- if(cc_name) {
- cc_type = (*pkrb5_cc_get_type)(ctx, cache);
- if (cc_type) {
- StringCbPrintf(wcc_name, sizeof(wcc_name), L"%S:%S", cc_type, cc_name);
- } else {
- AnsiStrToUnicode(wcc_name, sizeof(wcc_name), cc_name);
- khm_krb5_canon_cc_name(wcc_name, sizeof(wcc_name));
- }
- } else {
- cc_type = (*pkrb5_cc_get_type)(ctx, cache);
- if (cc_type) {
- StringCbPrintf(wcc_name, sizeof(wcc_name), L"%S:", cc_type);
- } else {
-#ifdef DEBUG
- assert(FALSE);
-#endif
- StringCbCopy(wcc_name, sizeof(wcc_name), L"");
- }
- }
- }
-
- _reportf(L"Getting tickets from cache [%s]", wcc_name);
-
- if ((code = (*pkrb5_cc_set_flags)(ctx, cache, flags)))
- {
- if (code != KRB5_FCC_NOFILE && code != KRB5_CC_NOTFOUND)
- khm_krb5_error(code, "krb5_cc_set_flags()", 0, &ctx, &cache);
-
- goto _exit;
- }
-
- if ((code = (*pkrb5_cc_get_principal)(ctx, cache, &KRBv5Principal)))
- {
- if (code != KRB5_FCC_NOFILE && code != KRB5_CC_NOTFOUND)
- khm_krb5_error(code, "krb5_cc_get_principal()", 0, &ctx, &cache);
-
- goto _exit;
- }
-
- PrincipalName = NULL;
- ClientName = NULL;
- sServerName = NULL;
- if ((code = (*pkrb5_unparse_name)(ctx, KRBv5Principal,
- (char **)&PrincipalName)))
- {
- if (PrincipalName != NULL)
- (*pkrb5_free_unparsed_name)(ctx, PrincipalName);
-
- (*pkrb5_free_principal)(ctx, KRBv5Principal);
-
- goto _exit;
- }
-
- if (!strcspn(PrincipalName, "@" ))
- {
- if (PrincipalName != NULL)
- (*pkrb5_free_unparsed_name)(ctx, PrincipalName);
-
- (*pkrb5_free_principal)(ctx, KRBv5Principal);
-
- goto _exit;
- }
-
- AnsiStrToUnicode(wbuf, sizeof(wbuf), PrincipalName);
- if(KHM_FAILED(kcdb_identity_create(wbuf, KCDB_IDENT_FLAG_CREATE,
- &ident))) {
- /* something bad happened */
- code = 1;
- goto _exit;
- }
-
- _reportf(L"Found principal [%s]", wbuf);
-
- (*pkrb5_free_principal)(ctx, KRBv5Principal);
-
- if ((code = (*pkrb5_cc_start_seq_get)(ctx, cache, &KRBv5Cursor)))
- {
- goto _exit;
- }
-
- memset(&KRBv5Credentials, '\0', sizeof(KRBv5Credentials));
-
- ClientName = NULL;
- sServerName = NULL;
- cred = NULL;
-
- while (!(code = pkrb5_cc_next_cred(ctx, cache, &KRBv5Cursor,
- &KRBv5Credentials)))
- {
- khm_handle tident = NULL;
- khm_int32 cred_flags = 0;
-
- if(ClientName != NULL)
- (*pkrb5_free_unparsed_name)(ctx, ClientName);
- if(sServerName != NULL)
- (*pkrb5_free_unparsed_name)(ctx, sServerName);
- if(cred)
- kcdb_cred_release(cred);
-
- ClientName = NULL;
- sServerName = NULL;
- cred = NULL;
-
- if ((*pkrb5_unparse_name)(ctx, KRBv5Credentials.client, &ClientName))
- {
- (*pkrb5_free_cred_contents)(ctx, &KRBv5Credentials);
- khm_krb5_error(code, "krb5_free_cred_contents()", 0, &ctx, &cache);
- continue;
- }
-
- if ((*pkrb5_unparse_name)(ctx, KRBv5Credentials.server, &sServerName))
- {
- (*pkrb5_free_cred_contents)(ctx, &KRBv5Credentials);
- khm_krb5_error(code, "krb5_free_cred_contents()", 0, &ctx, &cache);
- continue;
- }
-
- /* if the ClientName differs from PrincipalName for some
- reason, we need to create a new identity */
- if(strcmp(ClientName, PrincipalName)) {
- AnsiStrToUnicode(wbuf, sizeof(wbuf), ClientName);
- if(KHM_FAILED(kcdb_identity_create(wbuf, KCDB_IDENT_FLAG_CREATE,
- &tident))) {
- (*pkrb5_free_cred_contents)(ctx, &KRBv5Credentials);
- continue;
- }
- } else {
- tident = ident;
- }
-
- AnsiStrToUnicode(wbuf, sizeof(wbuf), sServerName);
- if(KHM_FAILED(kcdb_cred_create(wbuf, tident, credtype_id_krb5,
- &cred))) {
- (*pkrb5_free_cred_contents)(ctx, &KRBv5Credentials);
- continue;
- }
-
- if (!KRBv5Credentials.times.starttime)
- KRBv5Credentials.times.starttime = KRBv5Credentials.times.authtime;
-
- tt = KRBv5Credentials.times.starttime;
- TimetToFileTime(tt, &ft);
- kcdb_cred_set_attr(cred, KCDB_ATTR_ISSUE, &ft, sizeof(ft));
-
- tt = KRBv5Credentials.times.endtime;
- TimetToFileTime(tt, &eft);
- kcdb_cred_set_attr(cred, KCDB_ATTR_EXPIRE, &eft, sizeof(eft));
-
- {
- FILETIME ftl;
-
- ftl = FtSub(&eft, &ft);
- kcdb_cred_set_attr(cred, KCDB_ATTR_LIFETIME, &ftl, sizeof(ftl));
- }
-
- if (KRBv5Credentials.times.renew_till > 0) {
- FILETIME ftl;
-
- tt = KRBv5Credentials.times.renew_till;
- TimetToFileTime(tt, &eft);
- kcdb_cred_set_attr(cred, KCDB_ATTR_RENEW_EXPIRE, &eft,
- sizeof(eft));
-
-
- ftl = FtSub(&eft, &ft);
- kcdb_cred_set_attr(cred, KCDB_ATTR_RENEW_LIFETIME, &ftl,
- sizeof(ftl));
- }
-
- ti = KRBv5Credentials.ticket_flags;
- kcdb_cred_set_attr(cred, attr_id_krb5_flags, &ti, sizeof(ti));
-
- /* special flags understood by NetIDMgr */
- {
- khm_int32 nflags = 0;
-
- if (ti & TKT_FLG_RENEWABLE)
- nflags |= KCDB_CRED_FLAG_RENEWABLE;
- if (ti & TKT_FLG_INITIAL)
- nflags |= KCDB_CRED_FLAG_INITIAL;
- else {
- krb5_data * c0, *c1, *r;
-
- /* these are macros that do not allocate any memory */
- c0 = krb5_princ_component(ctx,KRBv5Credentials.server,0);
- c1 = krb5_princ_component(ctx,KRBv5Credentials.server,1);
- r = krb5_princ_realm(ctx,KRBv5Credentials.server);
-
- if ( c0 && c1 && r && c1->length == r->length &&
- !strncmp(c1->data,r->data,r->length) &&
- !strncmp("krbtgt",c0->data,c0->length) )
- nflags |= KCDB_CRED_FLAG_INITIAL;
- }
-
- kcdb_cred_set_flags(cred, nflags, KCDB_CRED_FLAGMASK_EXT);
-
- cred_flags = nflags;
- }
-
- if ( !pkrb5_decode_ticket(&KRBv5Credentials.ticket, &tkt)) {
- ti = tkt->enc_part.enctype;
- kcdb_cred_set_attr(cred, attr_id_tkt_enctype, &ti, sizeof(ti));
- ti = tkt->enc_part.kvno;
- kcdb_cred_set_attr(cred, attr_id_kvno, &ti, sizeof(ti));
- pkrb5_free_ticket(ctx, tkt);
- tkt = NULL;
- }
-
- ti = KRBv5Credentials.keyblock.enctype;
- kcdb_cred_set_attr(cred, attr_id_key_enctype, &ti, sizeof(ti));
-
- kcdb_cred_set_attr(cred, KCDB_ATTR_LOCATION, wcc_name,
- KCDB_CBSIZE_AUTO);
-
- if ( KRBv5Credentials.addresses && KRBv5Credentials.addresses[0] ) {
- khm_int32 buffer[1024];
- void * bufp;
- khm_size cb;
- khm_int32 rv;
-
- bufp = (void *) buffer;
- cb = sizeof(buffer);
-
- rv = serialize_krb5_addresses(KRBv5Credentials.addresses,
- bufp,
- &cb);
- if (rv == KHM_ERROR_TOO_LONG) {
- bufp = PMALLOC(cb);
- rv = serialize_krb5_addresses(KRBv5Credentials.addresses,
- bufp,
- &cb);
- }
-
- if (KHM_SUCCEEDED(rv)) {
- kcdb_cred_set_attr(cred, attr_id_addr_list,
- bufp, cb);
- }
-
- if (bufp != (void *) buffer)
- PFREE(bufp);
- }
-
- if(cred_flags & KCDB_CRED_FLAG_INITIAL) {
- FILETIME ft_issue_new;
- FILETIME ft_expire_old;
- FILETIME ft_expire_new;
- ident_data * d;
-
- /* an initial ticket! Add it to the list of identities we
- have seen so far with initial tickets. */
- d = tc_add_ident_to_list(idlist, ident);
-#ifdef DEBUG
- assert(d);
- assert(d->count > 0);
-#endif
-
- tt = KRBv5Credentials.times.endtime;
- TimetToFileTime(tt, &ft_expire_new);
-
- tt = KRBv5Credentials.times.starttime;
- TimetToFileTime(tt, &ft_issue_new);
-
- /* so now, we have to set the properties of the identity
- based on the properties of this credential under the
- following circumstances:
-
- - If this is the first time we are hitting this
- identity.
-
- - If this is not the MSLSA: cache and the expiry time
- for this credential is longer than the time already
- found for this identity.
- */
-
- ft_expire_old = d->ft_expire;
-
- if(d->count == 1
- || (CompareFileTime(&ft_expire_new, &ft_expire_old) > 0 &&
- wcscmp(wcc_name, L"MSLSA:") != 0)) {
-
- _reportf(L"Setting properties for identity (count=%d)", d->count);
-
- StringCbCopy(d->ccname, sizeof(d->ccname),
- wcc_name);
- d->ft_expire = ft_expire_new;
- d->ft_issue = ft_issue_new;
-
- if (KRBv5Credentials.times.renew_till > 0) {
- tt = KRBv5Credentials.times.renew_till;
- TimetToFileTime(tt, &ft);
- d->ft_renewexpire = ft;
- } else {
- ZeroMemory(&d->ft_renewexpire, sizeof(d->ft_renewexpire));
- }
-
- d->krb5_flags = KRBv5Credentials.ticket_flags;
- }
- }
-
- kcdb_credset_add_cred(krb5_credset, cred, -1);
-
- (*pkrb5_free_cred_contents)(ctx, &KRBv5Credentials);
-
- if(tident != ident)
- kcdb_identity_release(tident);
- }
-
- if (PrincipalName != NULL)
- (*pkrb5_free_unparsed_name)(ctx, PrincipalName);
-
- if (ClientName != NULL)
- (*pkrb5_free_unparsed_name)(ctx, ClientName);
-
- if (sServerName != NULL)
- (*pkrb5_free_unparsed_name)(ctx, sServerName);
-
- if (cred)
- kcdb_cred_release(cred);
-
- if ((code == KRB5_CC_END) || (code == KRB5_CC_NOTFOUND))
- {
- if ((code = pkrb5_cc_end_seq_get(ctx, cache, &KRBv5Cursor)))
- {
- goto _exit;
- }
-
- flags = KRB5_TC_OPENCLOSE;
-#ifdef KRB5_TC_NOTICKET
- flags |= KRB5_TC_NOTICKET;
-#endif
- if ((code = pkrb5_cc_set_flags(ctx, cache, flags)))
- {
- goto _exit;
- }
- }
- else
- {
- goto _exit;
- }
-
-_exit:
-
- return code;
-}
-
-long
-khm_krb5_list_tickets(krb5_context *krbv5Context)
-{
- krb5_context ctx = NULL;
- krb5_ccache cache = NULL;
- krb5_error_code code = 0;
- apiCB * cc_ctx = NULL;
- struct _infoNC ** pNCi = NULL;
- int i;
- khm_int32 t;
- wchar_t * ms = NULL;
- khm_size cb;
- identlist idl;
-
- kcdb_credset_flush(krb5_credset);
- tc_prep_idlist(&idl);
-
- if((*krbv5Context == 0) && (code = (*pkrb5_init_context)(krbv5Context))) {
- goto _exit;
- }
-
- ctx = (*krbv5Context);
-
- if (!pcc_initialize ||
- !pcc_get_NC_info ||
- !pcc_free_NC_info ||
- !pcc_shutdown)
- goto _skip_cc_iter;
-
- code = pcc_initialize(&cc_ctx, CC_API_VER_2, NULL, NULL);
- if (code)
- goto _exit;
-
- code = pcc_get_NC_info(cc_ctx, &pNCi);
- if (code)
- goto _exit;
-
- for(i=0; pNCi[i]; i++) {
- char ccname[KRB5_MAXCCH_CCNAME];
-
- if (pNCi[i]->vers != CC_CRED_V5)
- continue;
-
- if (FAILED(StringCchPrintfA(ccname, sizeof(ccname), "API:%s",
- pNCi[i]->name)))
- continue;
-
- code = (*pkrb5_cc_resolve)(ctx, ccname, &cache);
-
- if (code)
- continue;
-
- code = get_tickets_from_cache(ctx, cache, &idl);
-
- if(ctx != NULL && cache != NULL)
- (*pkrb5_cc_close)(ctx, cache);
-
- cache = 0;
- }
-
- _skip_cc_iter:
-
- if (khc_read_multi_string(csp_params, L"FileCCList", NULL, &cb)
- == KHM_ERROR_TOO_LONG &&
- cb > sizeof(wchar_t) * 2) {
- wchar_t * t;
- char ccname[MAX_PATH + 6];
-
- ms = PMALLOC(cb);
-#ifdef DEBUG
- assert(ms);
-#endif
- khc_read_multi_string(csp_params, L"FileCCList", ms, &cb);
-
- for(t = ms; t && *t; t = multi_string_next(t)) {
- StringCchPrintfA(ccname, ARRAYLENGTH(ccname),
- "FILE:%S", t);
-
- code = (*pkrb5_cc_resolve)(ctx, ccname, &cache);
-
- if (code)
- continue;
-
- code = get_tickets_from_cache(ctx, cache, &idl);
-
- if (ctx != NULL && cache != NULL)
- (*pkrb5_cc_close)(ctx, cache);
- cache = 0;
- }
-
- PFREE(ms);
- }
-
- if (KHM_SUCCEEDED(khc_read_int32(csp_params, L"MsLsaList", &t)) && t) {
- code = (*pkrb5_cc_resolve)(ctx, "MSLSA:", &cache);
-
- if (code == 0 && cache) {
- code = get_tickets_from_cache(ctx, cache, &idl);
- }
-
- if (ctx != NULL && cache != NULL)
- (*pkrb5_cc_close)(ctx, cache);
- cache = 0;
- }
-
-_exit:
- if (pNCi)
- (*pcc_free_NC_info)(cc_ctx, &pNCi);
- if (cc_ctx)
- (*pcc_shutdown)(&cc_ctx);
-
- kcdb_credset_collect(NULL, krb5_credset, NULL, credtype_id_krb5, NULL);
- tc_set_ident_data(&idl);
- tc_free_idlist(&idl);
-
- return(code);
-}
-
-int
-khm_krb5_renew_cred(khm_handle cred)
-{
- khm_handle identity = NULL;
- krb5_error_code code = 0;
- krb5_context ctx = NULL;
- krb5_ccache cc = NULL;
- krb5_principal me = NULL, server = NULL;
- krb5_creds in_creds, cc_creds;
- krb5_creds * out_creds = NULL;
-
- wchar_t wname[512];
- khm_size cbname;
- char name[512];
- khm_boolean brenewIdentity = FALSE;
- khm_boolean istgt = FALSE;
-
- khm_int32 flags;
-
- cbname = sizeof(wname);
- kcdb_cred_get_name(cred, wname, &cbname);
- _reportf(L"Krb5 renew cred for %s", wname);
-
- kcdb_cred_get_flags(cred, &flags);
-
- if (!(flags & KCDB_CRED_FLAG_INITIAL)) {
- _reportf(L"Krb5 skipping renewal because this is not an initial credential");
- return 0;
- }
-
- memset(&in_creds, 0, sizeof(in_creds));
- memset(&cc_creds, 0, sizeof(cc_creds));
-
- if (cred == NULL) {
-#ifdef DEBUG
- assert(FALSE);
-#endif
- goto cleanup;
- }
-
- if (KHM_FAILED(kcdb_cred_get_identity(cred, &identity))) {
-#ifdef DEBUG
- assert(FALSE);
-#endif
- goto cleanup;
- }
-
- code = khm_krb5_initialize(identity, &ctx, &cc);
- if (code)
- goto cleanup;
-
- code = pkrb5_cc_get_principal(ctx, cc, &me);
- if (code)
- goto cleanup;
-
- cbname = sizeof(wname);
- if (KHM_FAILED(kcdb_cred_get_name(cred, wname, &cbname)))
- goto cleanup;
-
- UnicodeStrToAnsi(name, sizeof(name), wname);
-
- code = pkrb5_parse_name(ctx, name, &server);
- if (code)
- goto cleanup;
-
- in_creds.client = me;
- in_creds.server = server;
-
-#ifdef KRB5_TC_NOTICKET
- pkrb5_cc_set_flags(ctx, cc, 0);
-#endif
-
- if (strlen("krbtgt") != krb5_princ_name(ctx, server)->length ||
- strncmp("krbtgt", krb5_princ_name(ctx, server)->data, krb5_princ_name(ctx, server)->length))
- {
- code = pkrb5_get_renewed_creds(ctx, &cc_creds, me, cc, name);
- if (code) {
- code = pkrb5_cc_retrieve_cred(ctx, cc, 0, &in_creds, &cc_creds);
- if (code == 0) {
- code = pkrb5_cc_remove_cred(ctx, cc, 0, &cc_creds);
- if (code) {
- brenewIdentity = TRUE;
- goto cleanup;
- }
- }
- }
-
- code = pkrb5_get_credentials(ctx, 0, cc, &in_creds, &out_creds);
- } else {
- istgt = TRUE;
- code = pkrb5_get_renewed_creds(ctx, &cc_creds, me, cc, NULL);
- }
-
-#ifdef KRB5_TC_NOTICKET
- pkrb5_cc_set_flags(ctx, cc, KRB5_TC_NOTICKET);
-#endif
- if (code) {
- if ( code != KRB5KDC_ERR_ETYPE_NOSUPP ||
- code != KRB5_KDC_UNREACH)
- khm_krb5_error(code, "krb5_get_renewed_creds()", 0, &ctx, &cc);
- goto cleanup;
- }
-
- if (istgt) {
- code = pkrb5_cc_initialize(ctx, cc, me);
- if (code) goto cleanup;
-
- }
-
- code = pkrb5_cc_store_cred(ctx, cc, istgt ? &cc_creds : out_creds);
- if (code) goto cleanup;
-
-
- cleanup:
-
- if (in_creds.client == me)
- in_creds.client = NULL;
- if (in_creds.server == server)
- in_creds.server = NULL;
-
- if (me)
- pkrb5_free_principal(ctx, me);
-
- if (server)
- pkrb5_free_principal(ctx, server);
-
- pkrb5_free_cred_contents(ctx, &in_creds);
- pkrb5_free_cred_contents(ctx, &cc_creds);
-
- if (out_creds)
- pkrb5_free_creds(ctx, out_creds);
-
- if (cc && ctx)
- pkrb5_cc_close(ctx, cc);
-
- if (ctx)
- pkrb5_free_context(ctx);
-
- if (identity) {
- if (brenewIdentity)
- code = khm_krb5_renew_ident(identity);
- kcdb_identity_release(identity);
- }
-
- return code;
-}
-
-int
-khm_krb5_renew_ident(khm_handle identity)
-{
- krb5_error_code code = 0;
- krb5_context ctx = NULL;
- krb5_ccache cc = NULL;
- krb5_principal me = NULL;
- krb5_principal server = NULL;
- krb5_creds my_creds;
- krb5_data *realm = NULL;
- wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
- khm_size cb;
- khm_int32 k5_flags;
-
- memset(&my_creds, 0, sizeof(krb5_creds));
-
- if ( !pkrb5_init_context )
- goto cleanup;
-
- cb = sizeof(idname);
- kcdb_identity_get_name(identity, idname, &cb);
-
- if (khm_krb5_get_identity_flags(identity) & K5IDFLAG_IMPORTED) {
-#ifndef NO_REIMPORT_MSLSA_CREDS
- /* we are trying to renew the identity that was imported from
- MSLSA: */
- BOOL imported;
- BOOL retry_import = FALSE;
- char cidname[KCDB_IDENT_MAXCCH_NAME];
- khm_handle imported_id = NULL;
- khm_size cb;
- FILETIME ft_expire;
- FILETIME ft_now;
- FILETIME ft_threshold;
- krb5_principal princ = NULL;
-
- UnicodeStrToAnsi(cidname, sizeof(cidname), idname);
-
- imported = khm_krb5_ms2mit(cidname, FALSE, TRUE, &imported_id);
-
- if (imported == 0)
- goto import_failed;
-
- /* if the imported identity has already expired or will soon,
- we clear the cache and try again. */
- khm_krb5_list_tickets(&ctx);
-
- cb = sizeof(ft_expire);
- if (KHM_FAILED(kcdb_identity_get_attr(imported_id, KCDB_ATTR_EXPIRE,
- NULL, &ft_expire, &cb)))
- goto import_failed;
-
- GetSystemTimeAsFileTime(&ft_now);
- TimetToFileTimeInterval(5 * 60, &ft_threshold);
-
- ft_now = FtAdd(&ft_now, &ft_threshold);
-
- if (CompareFileTime(&ft_expire, &ft_now) < 0) {
- /* the ticket lifetime is not long enough */
-
- code = 0;
-
- if (ctx == NULL)
- code = pkrb5_init_context(&ctx);
- if (code)
- goto import_failed;
-
- code = pkrb5_cc_resolve(ctx, "MSLSA:", &cc);
- if (code)
- goto import_failed;
-
- code = pkrb5_cc_get_principal(ctx, cc, &princ);
- if (code)
- goto import_failed;
-
- pkrb5_cc_initialize(ctx, cc, princ);
-
- retry_import = TRUE;
- }
-
- import_failed:
-
- if (imported_id) {
- kcdb_identity_release(imported_id);
- imported_id = NULL;
- }
-
- if (ctx) {
- if (cc) {
- pkrb5_cc_close(ctx, cc);
- cc = NULL;
- }
-
- if (princ) {
- pkrb5_free_principal(ctx, princ);
- princ = NULL;
- }
-
- /* leave ctx so we can use it later */
- }
-
- if (retry_import)
- imported = khm_krb5_ms2mit(cidname, FALSE, TRUE, NULL);
-
- if (imported)
- goto cleanup;
-
- /* if the import failed, then we try to renew the identity via
- the usual procedure. */
-
-#else
- /* if we are suppressing further imports from MSLSA, we just
- skip renewing this identity. */
- goto cleanup;
-#endif
- }
-
- cb = sizeof(k5_flags);
- if (KHM_SUCCEEDED(kcdb_identity_get_attr(identity,
- attr_id_krb5_flags,
- NULL,
- &k5_flags,
- &cb)) &&
- !(k5_flags & TKT_FLG_RENEWABLE)) {
-
- code = KRB5KDC_ERR_BADOPTION;
- goto cleanup;
- }
-
- {
- FILETIME ft_now;
- FILETIME ft_exp;
-
- cb = sizeof(ft_exp);
- GetSystemTimeAsFileTime(&ft_now);
- if (KHM_SUCCEEDED(kcdb_identity_get_attr(identity,
- KCDB_ATTR_EXPIRE,
- NULL,
- &ft_exp,
- &cb)) &&
- CompareFileTime(&ft_exp, &ft_now) < 0) {
-
- code = KRB5KRB_AP_ERR_TKT_EXPIRED;
- goto cleanup;
-
- }
- }
-
- code = khm_krb5_initialize(identity, &ctx, &cc);
- if (code)
- goto cleanup;
-
- code = pkrb5_cc_get_principal(ctx, cc, &me);
- if (code)
- goto cleanup;
-
- realm = krb5_princ_realm(ctx, me);
-
- code = pkrb5_build_principal_ext(ctx, &server,
- realm->length,realm->data,
- KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME,
- realm->length,realm->data,
- 0);
-
- if (code)
- goto cleanup;
-
- my_creds.client = me;
- my_creds.server = server;
-
-#ifdef KRB5_TC_NOTICKET
- pkrb5_cc_set_flags(ctx, cc, 0);
-#endif
- code = pkrb5_get_renewed_creds(ctx, &my_creds, me, cc, NULL);
-#ifdef KRB5_TC_NOTICKET
- pkrb5_cc_set_flags(ctx, cc, KRB5_TC_NOTICKET);
-#endif
- if (code) {
- if ( code != KRB5KDC_ERR_ETYPE_NOSUPP ||
- code != KRB5_KDC_UNREACH)
- khm_krb5_error(code, "krb5_get_renewed_creds()", 0, &ctx, &cc);
- goto cleanup;
- }
-
- code = pkrb5_cc_initialize(ctx, cc, me);
- if (code) goto cleanup;
-
- code = pkrb5_cc_store_cred(ctx, cc, &my_creds);
- if (code) goto cleanup;
-
-cleanup:
- if (my_creds.client == me)
- my_creds.client = NULL;
- if (my_creds.server == server)
- my_creds.server = NULL;
-
- if (ctx) {
- pkrb5_free_cred_contents(ctx, &my_creds);
-
- if (me)
- pkrb5_free_principal(ctx, me);
- if (server)
- pkrb5_free_principal(ctx, server);
- if (cc)
- pkrb5_cc_close(ctx, cc);
- pkrb5_free_context(ctx);
- }
-
- return(code);
-}
-
-int
-khm_krb5_kinit(krb5_context alt_ctx,
- char * principal_name,
- char * password,
- char * ccache,
- krb5_deltat lifetime,
- DWORD forwardable,
- DWORD proxiable,
- krb5_deltat renew_life,
- DWORD addressless,
- DWORD publicIP,
- krb5_prompter_fct prompter,
- void * p_data)
-{
- krb5_error_code code = 0;
- krb5_context ctx = NULL;
- krb5_ccache cc = NULL;
- krb5_principal me = NULL;
- char* name = NULL;
- krb5_creds my_creds;
- krb5_get_init_creds_opt options;
- krb5_address ** addrs = NULL;
- int i = 0, addr_count = 0;
-
- if (!pkrb5_init_context)
- return 0;
-
- _reportf(L"In khm_krb5_kinit");
-
- pkrb5_get_init_creds_opt_init(&options);
- pkrb5_get_init_creds_opt_set_change_password_prompt(&options, 0);
-
- memset(&my_creds, 0, sizeof(my_creds));
-
- if (alt_ctx) {
- ctx = alt_ctx;
- } else {
- code = pkrb5_init_context(&ctx);
- if (code)
- goto cleanup;
- }
-
- if (ccache) {
- _reportf(L"Using supplied ccache name %S", ccache);
- code = pkrb5_cc_resolve(ctx, ccache, &cc);
- } else {
- khm_handle identity = NULL;
- khm_handle csp_ident = NULL;
- khm_handle csp_k5 = NULL;
- wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
- wchar_t wccname[MAX_PATH];
- char ccname[MAX_PATH];
- char * pccname = principal_name;
- khm_size cb;
-
- idname[0] = L'\0';
- AnsiStrToUnicode(idname, sizeof(idname), principal_name);
-
- cb = sizeof(wccname);
-
- if (KHM_SUCCEEDED(kcdb_identity_create(idname, 0, &identity)) &&
-
- KHM_SUCCEEDED(kcdb_identity_get_config(identity, 0, &csp_ident)) &&
-
- KHM_SUCCEEDED(khc_open_space(csp_ident, CSNAME_KRB5CRED, 0,
- &csp_k5)) &&
-
- KHM_SUCCEEDED(khc_read_string(csp_k5, L"DefaultCCName",
- wccname, &cb)) &&
-
- cb > sizeof(wchar_t)) {
-
- _reportf(L"Using DefaultCCName [%s] from identity", wccname);
-
- UnicodeStrToAnsi(ccname, sizeof(ccname), wccname);
- pccname = ccname;
- }
-
- if (csp_k5)
- khc_close_space(csp_k5);
- if (csp_ident)
- khc_close_space(csp_ident);
- if (identity)
- kcdb_identity_release(identity);
-
- code = pkrb5_cc_resolve(ctx, pccname, &cc);
- }
-
- _reportf(L"krb5_cc_resolve returns code %d", code);
-
- if (code) goto cleanup;
-
- code = pkrb5_parse_name(ctx, principal_name, &me);
- if (code) goto cleanup;
-
- code = pkrb5_unparse_name(ctx, me, &name);
- if (code) goto cleanup;
-
- if (lifetime == 0) {
- khc_read_int32(csp_params, L"DefaultLifetime", &lifetime);
- }
-
- if (lifetime)
- pkrb5_get_init_creds_opt_set_tkt_life(&options, lifetime);
-
- pkrb5_get_init_creds_opt_set_forwardable(&options,
- forwardable ? 1 : 0);
- pkrb5_get_init_creds_opt_set_proxiable(&options,
- proxiable ? 1 : 0);
- pkrb5_get_init_creds_opt_set_renew_life(&options,
- renew_life);
-
- if (addressless)
- pkrb5_get_init_creds_opt_set_address_list(&options,NULL);
- else {
- krb5_address ** local_addrs=NULL;
- DWORD netIPAddr;
-
- pkrb5_os_localaddr(ctx, &local_addrs);
- i = 0;
- while ( local_addrs[i++] );
- addr_count = i + 1;
-
- addrs = (krb5_address **) PMALLOC((addr_count+1) * sizeof(krb5_address *));
- if ( !addrs ) {
- pkrb5_free_addresses(ctx, local_addrs);
- assert(0);
- }
- memset(addrs, 0, sizeof(krb5_address *) * (addr_count+1));
- i = 0;
- while ( local_addrs[i] ) {
- addrs[i] = (krb5_address *)PMALLOC(sizeof(krb5_address));
- if (addrs[i] == NULL) {
- pkrb5_free_addresses(ctx, local_addrs);
- assert(0);
- }
-
- addrs[i]->magic = local_addrs[i]->magic;
- addrs[i]->addrtype = local_addrs[i]->addrtype;
- addrs[i]->length = local_addrs[i]->length;
- addrs[i]->contents = (unsigned char *)PMALLOC(addrs[i]->length);
- if (!addrs[i]->contents) {
- pkrb5_free_addresses(ctx, local_addrs);
- assert(0);
- }
-
- memcpy(addrs[i]->contents,local_addrs[i]->contents,
- local_addrs[i]->length); /* safe */
- i++;
- }
- pkrb5_free_addresses(ctx, local_addrs);
-
- if (publicIP) {
- // we are going to add the public IP address specified by the user
- // to the list provided by the operating system
- addrs[i] = (krb5_address *)PMALLOC(sizeof(krb5_address));
- if (addrs[i] == NULL)
- assert(0);
-
- addrs[i]->magic = KV5M_ADDRESS;
- addrs[i]->addrtype = AF_INET;
- addrs[i]->length = 4;
- addrs[i]->contents = (unsigned char *)PMALLOC(addrs[i]->length);
- if (!addrs[i]->contents)
- assert(0);
-
- netIPAddr = htonl(publicIP);
- memcpy(addrs[i]->contents,&netIPAddr,4);
- }
-
- pkrb5_get_init_creds_opt_set_address_list(&options,addrs);
- }
-
- code =
- pkrb5_get_init_creds_password(ctx,
- &my_creds,
- me,
- password, // password
- prompter, // prompter
- p_data, // prompter data
- 0, // start time
- 0, // service name
- &options);
- _reportf(L"krb5_get_init_creds_password returns code %d", code);
-
- if (code) goto cleanup;
-
- code = pkrb5_cc_initialize(ctx, cc, me);
- _reportf(L"krb5_cc_initialize returns code %d", code);
- if (code) goto cleanup;
-
- code = pkrb5_cc_store_cred(ctx, cc, &my_creds);
- _reportf(L"krb5_cc_store_cred returns code %d", code);
- if (code) goto cleanup;
-
-cleanup:
- if ( addrs ) {
- for ( i=0;i<addr_count;i++ ) {
- if ( addrs[i] ) {
- if ( addrs[i]->contents )
- PFREE(addrs[i]->contents);
- PFREE(addrs[i]);
- }
- }
- }
- if (my_creds.client == me)
- my_creds.client = 0;
- pkrb5_free_cred_contents(ctx, &my_creds);
- if (name)
- pkrb5_free_unparsed_name(ctx, name);
- if (me)
- pkrb5_free_principal(ctx, me);
- if (cc)
- pkrb5_cc_close(ctx, cc);
- if (ctx && (ctx != alt_ctx))
- pkrb5_free_context(ctx);
- return(code);
-}
-
-long
-khm_krb5_copy_ccache_by_name(krb5_context in_ctx,
- wchar_t * wscc_dest,
- wchar_t * wscc_src) {
- krb5_context ctx = NULL;
- krb5_error_code code = 0;
- khm_boolean free_ctx;
- krb5_ccache cc_src = NULL;
- krb5_ccache cc_dest = NULL;
- krb5_principal princ_src = NULL;
- char scc_dest[KRB5_MAXCCH_CCNAME];
- char scc_src[KRB5_MAXCCH_CCNAME];
- int t;
-
- t = UnicodeStrToAnsi(scc_dest, sizeof(scc_dest), wscc_dest);
- if (t == 0)
- return KHM_ERROR_TOO_LONG;
- t = UnicodeStrToAnsi(scc_src, sizeof(scc_src), wscc_src);
- if (t == 0)
- return KHM_ERROR_TOO_LONG;
-
- if (in_ctx) {
- ctx = in_ctx;
- free_ctx = FALSE;
- } else {
- code = pkrb5_init_context(&ctx);
- if (code) {
- if (ctx)
- pkrb5_free_context(ctx);
- return code;
- }
- free_ctx = TRUE;
- }
-
- code = pkrb5_cc_resolve(ctx, scc_dest, &cc_dest);
- if (code)
- goto _cleanup;
-
- code = pkrb5_cc_resolve(ctx, scc_src, &cc_src);
- if (code)
- goto _cleanup;
-
- code = pkrb5_cc_get_principal(ctx, cc_src, &princ_src);
- if (code)
- goto _cleanup;
-
- code = pkrb5_cc_initialize(ctx, cc_dest, princ_src);
- if (code)
- goto _cleanup;
-
- code = pkrb5_cc_copy_creds(ctx, cc_src, cc_dest);
-
- _cleanup:
- if (princ_src)
- pkrb5_free_principal(ctx, princ_src);
-
- if (cc_dest)
- pkrb5_cc_close(ctx, cc_dest);
-
- if (cc_src)
- pkrb5_cc_close(ctx, cc_src);
-
- if (free_ctx && ctx)
- pkrb5_free_context(ctx);
-
- return code;
-}
-
-long
-khm_krb5_canon_cc_name(wchar_t * wcc_name,
- size_t cb_cc_name) {
- size_t cb_len;
- wchar_t * colon;
-
- if (FAILED(StringCbLength(wcc_name,
- cb_cc_name,
- &cb_len))) {
-#ifdef DEBUG
- assert(FALSE);
-#else
- return KHM_ERROR_TOO_LONG;
-#endif
- }
-
- cb_len += sizeof(wchar_t);
-
- colon = wcschr(wcc_name, L':');
-
- if (colon) {
- /* if the colon is just 1 character away from the beginning,
- it's a FILE: cc */
- if (colon - wcc_name == 1) {
- if (cb_len + 5 * sizeof(wchar_t) > cb_cc_name)
- return KHM_ERROR_TOO_LONG;
-
- memmove(&wcc_name[5], &wcc_name[0], cb_len);
- memmove(&wcc_name[0], L"FILE:", sizeof(wchar_t) * 5);
- }
-
- return 0;
- }
-
- if (cb_len + 4 * sizeof(wchar_t) > cb_cc_name)
- return KHM_ERROR_TOO_LONG;
-
- memmove(&wcc_name[4], &wcc_name[0], cb_len);
- memmove(&wcc_name[0], L"API:", sizeof(wchar_t) * 4);
-
- return 0;
-}
-
-int
-khm_krb5_cc_name_cmp(const wchar_t * cc_name_1,
- const wchar_t * cc_name_2) {
- if (!wcsncmp(cc_name_1, L"API:", 4))
- cc_name_1 += 4;
-
- if (!wcsncmp(cc_name_2, L"API:", 4))
- cc_name_2 += 4;
-
- return wcscmp(cc_name_1, cc_name_2);
-}
-
-static khm_int32 KHMAPI
-khmint_location_comp_func(khm_handle cred1,
- khm_handle cred2,
- void * rock) {
- return kcdb_creds_comp_attr(cred1, cred2, KCDB_ATTR_LOCATION);
-}
-
-struct khmint_location_check {
- khm_handle credset;
- khm_handle cred;
- wchar_t * ccname;
- khm_boolean success;
-};
-
-static khm_int32 KHMAPI
-khmint_find_matching_cred_func(khm_handle cred,
- void * rock) {
- struct khmint_location_check * lc;
-
- lc = (struct khmint_location_check *) rock;
-
- if (!kcdb_creds_is_equal(cred, lc->cred))
- return KHM_ERROR_SUCCESS;
- if (kcdb_creds_comp_attr(cred, lc->cred, KCDB_ATTR_LOCATION))
- return KHM_ERROR_SUCCESS;
-
- /* found it */
- lc->success = TRUE;
-
- /* break the search */
- return !KHM_ERROR_SUCCESS;
-}
-
-static khm_int32 KHMAPI
-khmint_location_check_func(khm_handle cred,
- void * rock) {
- khm_int32 t;
- khm_size cb;
- wchar_t ccname[KRB5_MAXCCH_CCNAME];
- struct khmint_location_check * lc;
-
- lc = (struct khmint_location_check *) rock;
-
- if (KHM_FAILED(kcdb_cred_get_type(cred, &t)))
- return KHM_ERROR_SUCCESS;
-
- if (t != credtype_id_krb5)
- return KHM_ERROR_SUCCESS;
-
- cb = sizeof(ccname);
- if (KHM_FAILED(kcdb_cred_get_attr(cred,
- KCDB_ATTR_LOCATION,
- NULL,
- ccname,
- &cb)))
- return KHM_ERROR_SUCCESS;
-
- if(wcscmp(ccname, lc->ccname))
- return KHM_ERROR_SUCCESS;
-
- lc->cred = cred;
-
- lc->success = FALSE;
-
- kcdb_credset_apply(lc->credset,
- khmint_find_matching_cred_func,
- (void *) lc);
-
- if (!lc->success)
- return KHM_ERROR_NOT_FOUND;
- else
- return KHM_ERROR_SUCCESS;
-}
-
-static khm_int32 KHMAPI
-khmint_delete_location_func(khm_handle cred,
- void * rock) {
- wchar_t cc_cred[KRB5_MAXCCH_CCNAME];
- struct khmint_location_check * lc;
- khm_size cb;
-
- lc = (struct khmint_location_check *) rock;
-
- cb = sizeof(cc_cred);
-
- if (KHM_FAILED(kcdb_cred_get_attr(cred,
- KCDB_ATTR_LOCATION,
- NULL,
- cc_cred,
- &cb)))
- return KHM_ERROR_SUCCESS;
-
- if (wcscmp(cc_cred, lc->ccname))
- return KHM_ERROR_SUCCESS;
-
- kcdb_credset_del_cred_ref(lc->credset,
- cred);
-
- return KHM_ERROR_SUCCESS;
-}
-
-int
-khm_krb5_destroy_by_credset(khm_handle p_cs)
-{
- khm_handle d_cs = NULL;
- khm_int32 rv = KHM_ERROR_SUCCESS;
- khm_size s, cb;
- krb5_context ctx = NULL;
- krb5_error_code code = 0;
- int i;
- wchar_t ccname[KRB5_MAXCCH_CCNAME];
- struct khmint_location_check lc;
-
- rv = kcdb_credset_create(&d_cs);
-
- assert(KHM_SUCCEEDED(rv) && d_cs != NULL);
-
- kcdb_credset_extract(d_cs, p_cs, NULL, credtype_id_krb5);
-
- kcdb_credset_get_size(d_cs, &s);
-
- if (s == 0) {
- _reportf(L"No tickets to delete");
-
- kcdb_credset_delete(d_cs);
- return 0;
- }
-
- code = pkrb5_init_context(&ctx);
- if (code != 0) {
- rv = code;
- goto _cleanup;
- }
-
- /* we should synchronize the credential lists before we attempt to
- make any assumptions on the state of the root credset */
- khm_krb5_list_tickets(&ctx);
-
- /* so, we need to make a decision about whether to destroy entire
- ccaches or just individual credentials. Therefore we first
- sort them by ccache. */
- kcdb_credset_sort(d_cs,
- khmint_location_comp_func,
- NULL);
-
- /* now, for each ccache we encounter, we check if we have all the
- credentials from that ccache in the to-be-deleted list. */
- for (i=0; i < (int) s; i++) {
- khm_handle cred;
-
- if (KHM_FAILED(kcdb_credset_get_cred(d_cs,
- i,
- &cred)))
- continue;
-
- cb = sizeof(ccname);
- rv = kcdb_cred_get_attr(cred,
- KCDB_ATTR_LOCATION,
- NULL,
- ccname,
- &cb);
-
-#ifdef DEBUG
- assert(KHM_SUCCEEDED(rv));
-#endif
- kcdb_cred_release(cred);
-
- lc.credset = d_cs;
- lc.cred = NULL;
- lc.ccname = ccname;
- lc.success = FALSE;
-
- kcdb_credset_apply(NULL,
- khmint_location_check_func,
- (void *) &lc);
-
- if (lc.success) {
- /* ok the destroy the ccache */
- char a_ccname[KRB5_MAXCCH_CCNAME];
- krb5_ccache cc = NULL;
-
- _reportf(L"Destroying ccache [%s]", ccname);
-
- UnicodeStrToAnsi(a_ccname,
- sizeof(a_ccname),
- ccname);
-
- code = pkrb5_cc_resolve(ctx,
- a_ccname,
- &cc);
- if (code)
- goto _delete_this_set;
-
- code = pkrb5_cc_destroy(ctx, cc);
-
- if (code) {
- _reportf(L"krb5_cc_destroy returns code %d", code);
- }
-
- _delete_this_set:
-
- lc.credset = d_cs;
- lc.ccname = ccname;
-
- /* note that although we are deleting credentials off the
- credential set, the size of the credential set does not
- decrease since we are doing it from inside
- kcdb_credset_apply(). The deleted creds will simply be
- marked as deleted until kcdb_credset_purge() is
- called. */
-
- kcdb_credset_apply(d_cs,
- khmint_delete_location_func,
- (void *) &lc);
- }
- }
-
- kcdb_credset_purge(d_cs);
-
- /* the remainder need to be deleted one by one */
-
- kcdb_credset_get_size(d_cs, &s);
-
- for (i=0; i < (int) s; ) {
- khm_handle cred;
- char a_ccname[KRB5_MAXCCH_CCNAME];
- char a_srvname[KCDB_CRED_MAXCCH_NAME];
- wchar_t srvname[KCDB_CRED_MAXCCH_NAME];
- krb5_ccache cc;
- krb5_creds in_cred, out_cred;
- krb5_principal princ;
- khm_int32 etype;
-
- if (KHM_FAILED(kcdb_credset_get_cred(d_cs,
- i,
- &cred))) {
- i++;
- continue;
- }
-
- cb = sizeof(ccname);
- if (KHM_FAILED(kcdb_cred_get_attr(cred,
- KCDB_ATTR_LOCATION,
- NULL,
- ccname,
- &cb)))
- goto _done_with_this_cred;
-
- _reportf(L"Looking at ccache [%s]", ccname);
-
- UnicodeStrToAnsi(a_ccname,
- sizeof(a_ccname),
- ccname);
-
- code = pkrb5_cc_resolve(ctx,
- a_ccname,
- &cc);
-
- if (code)
- goto _skip_similar;
-
- code = pkrb5_cc_get_principal(ctx, cc, &princ);
-
- if (code) {
- pkrb5_cc_close(ctx, cc);
- goto _skip_similar;
- }
-
- _del_this_cred:
-
- cb = sizeof(etype);
-
- if (KHM_FAILED(kcdb_cred_get_attr(cred,
- attr_id_key_enctype,
- NULL,
- &etype,
- &cb)))
- goto _do_next_cred;
-
- cb = sizeof(srvname);
- if (KHM_FAILED(kcdb_cred_get_name(cred,
- srvname,
- &cb)))
- goto _do_next_cred;
-
- _reportf(L"Attempting to delete ticket %s", srvname);
-
- UnicodeStrToAnsi(a_srvname, sizeof(a_srvname), srvname);
-
- ZeroMemory(&in_cred, sizeof(in_cred));
-
- code = pkrb5_parse_name(ctx, a_srvname, &in_cred.server);
- if (code)
- goto _do_next_cred;
- in_cred.client = princ;
- in_cred.keyblock.enctype = etype;
-
- code = pkrb5_cc_retrieve_cred(ctx,
- cc,
- KRB5_TC_MATCH_SRV_NAMEONLY |
- KRB5_TC_SUPPORTED_KTYPES,
- &in_cred,
- &out_cred);
- if (code)
- goto _do_next_cred_0;
-
- code = pkrb5_cc_remove_cred(ctx, cc,
- KRB5_TC_MATCH_SRV_NAMEONLY |
- KRB5_TC_SUPPORTED_KTYPES |
- KRB5_TC_MATCH_AUTHDATA,
- &out_cred);
-
- pkrb5_free_cred_contents(ctx, &out_cred);
- _do_next_cred_0:
- pkrb5_free_principal(ctx, in_cred.server);
- _do_next_cred:
-
- /* check if the next cred is also of the same ccache */
- kcdb_cred_release(cred);
-
- for (i++; i < (int) s; i++) {
- if (KHM_FAILED(kcdb_credset_get_cred(d_cs,
- i,
- &cred)))
- continue;
- }
-
- if (i < (int) s) {
- wchar_t newcc[KRB5_MAXCCH_CCNAME];
-
- cb = sizeof(newcc);
- if (KHM_FAILED(kcdb_cred_get_attr(cred,
- KCDB_ATTR_LOCATION,
- NULL,
- newcc,
- &cb)) ||
- wcscmp(newcc, ccname)) {
- i--; /* we have to look at this again */
- goto _done_with_this_set;
- }
- goto _del_this_cred;
- }
-
-
- _done_with_this_set:
- pkrb5_free_principal(ctx, princ);
-
- pkrb5_cc_close(ctx, cc);
-
- _done_with_this_cred:
- kcdb_cred_release(cred);
- i++;
- continue;
-
- _skip_similar:
- kcdb_cred_release(cred);
-
- for (++i; i < (int) s; i++) {
- wchar_t newcc[KRB5_MAXCCH_CCNAME];
-
- if (KHM_FAILED(kcdb_credset_get_cred(d_cs,
- i,
- &cred)))
- continue;
-
- cb = sizeof(newcc);
- if (KHM_FAILED(kcdb_cred_get_attr(cred,
- KCDB_ATTR_LOCATION,
- NULL,
- &newcc,
- &cb))) {
- kcdb_cred_release(cred);
- continue;
- }
-
- if (wcscmp(newcc, ccname)) {
- kcdb_cred_release(cred);
- break;
- }
- }
- }
-
- _cleanup:
-
- if (d_cs)
- kcdb_credset_delete(&d_cs);
-
- if (ctx != NULL)
- pkrb5_free_context(ctx);
-
- return rv;
-}
-
-int
-khm_krb5_destroy_identity(khm_handle identity)
-{
- krb5_context ctx;
- krb5_ccache cache;
- krb5_error_code rc;
-
- ctx = NULL;
- cache = NULL;
-
- if (rc = khm_krb5_initialize(identity, &ctx, &cache))
- return(rc);
-
- rc = pkrb5_cc_destroy(ctx, cache);
-
- if (ctx != NULL)
- pkrb5_free_context(ctx);
-
- return(rc);
-}
-
-static BOOL
-GetSecurityLogonSessionData(PSECURITY_LOGON_SESSION_DATA * ppSessionData)
-{
- NTSTATUS Status = 0;
- HANDLE TokenHandle;
- TOKEN_STATISTICS Stats;
- DWORD ReqLen;
- BOOL Success;
-
- if (!ppSessionData)
- return FALSE;
- *ppSessionData = NULL;
-
- Success = OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &TokenHandle );
- if ( !Success )
- return FALSE;
-
- Success = GetTokenInformation( TokenHandle, TokenStatistics, &Stats, sizeof(TOKEN_STATISTICS), &ReqLen );
- CloseHandle( TokenHandle );
- if ( !Success )
- return FALSE;
-
- Status = pLsaGetLogonSessionData( &Stats.AuthenticationId, ppSessionData );
- if ( FAILED(Status) || !ppSessionData )
- return FALSE;
-
- return TRUE;
-}
-
-// IsKerberosLogon() does not validate whether or not there are valid
-// tickets in the cache. It validates whether or not it is reasonable
-// to assume that if we attempted to retrieve valid tickets we could
-// do so. Microsoft does not automatically renew expired tickets.
-// Therefore, the cache could contain expired or invalid tickets.
-// Microsoft also caches the user's password and will use it to
-// retrieve new TGTs if the cache is empty and tickets are requested.
-
-static BOOL
-IsKerberosLogon(VOID)
-{
- PSECURITY_LOGON_SESSION_DATA pSessionData = NULL;
- BOOL Success = FALSE;
-
- if ( GetSecurityLogonSessionData(&pSessionData) ) {
- if ( pSessionData->AuthenticationPackage.Buffer ) {
- WCHAR buffer[256];
- WCHAR *usBuffer;
- int usLength;
-
- Success = FALSE;
- usBuffer = (pSessionData->AuthenticationPackage).Buffer;
- usLength = (pSessionData->AuthenticationPackage).Length;
- if (usLength < 256)
- {
- lstrcpynW (buffer, usBuffer, usLength);
- StringCbCatW (buffer, sizeof(buffer), L"");
- if ( !lstrcmpW(L"Kerberos",buffer) )
- Success = TRUE;
- }
- }
- pLsaFreeReturnBuffer(pSessionData);
- }
- return Success;
-}
-
-
-BOOL
-khm_krb5_ms2mit(char * match_princ, BOOL match_realm, BOOL save_creds,
- khm_handle * ret_ident)
-{
-#ifdef NO_KRB5
- return(FALSE);
-#else /* NO_KRB5 */
- krb5_context kcontext = 0;
- krb5_error_code code = 0;
- krb5_ccache ccache=0;
- krb5_ccache mslsa_ccache=0;
- krb5_creds creds;
- krb5_cc_cursor cursor=0;
- krb5_principal princ = 0;
- khm_handle ident = NULL;
- wchar_t wname[KCDB_IDENT_MAXCCH_NAME];
- char cname[KCDB_IDENT_MAXCCH_NAME];
- char *cache_name = NULL;
- char *princ_name = NULL;
- BOOL rc = FALSE;
-
- kherr_reportf(L"Begin : khm_krb5_ms2mit. save_cred=%d\n", (int) save_creds);
-
- if ( !pkrb5_init_context )
- goto cleanup;
-
- if (code = pkrb5_init_context(&kcontext))
- goto cleanup;
-
- kherr_reportf(L"Resolving MSLSA\n");
-
- if (code = pkrb5_cc_resolve(kcontext, "MSLSA:", &mslsa_ccache))
- goto cleanup;
-
- if ( save_creds ) {
- kherr_reportf(L"Getting principal\n");
- if (code = pkrb5_cc_get_principal(kcontext, mslsa_ccache, &princ))
- goto cleanup;
-
- kherr_reportf(L"Unparsing name\n");
- if (code = pkrb5_unparse_name(kcontext, princ, &princ_name))
- goto cleanup;
-
- AnsiStrToUnicode(wname, sizeof(wname), princ_name);
-
- kherr_reportf(L"Unparsed name [%s]", wname);
-
- /* see if we have to match a specific principal */
- if (match_princ != NULL) {
- if (strcmp(princ_name, match_princ)) {
- kherr_reportf(L"Principal mismatch. Wanted [%S], found [%S]",
- match_princ, princ_name);
- goto cleanup;
- }
- } else if (match_realm) {
- wchar_t * wdefrealm;
- char defrealm[256];
- krb5_data * princ_realm;
-
- wdefrealm = khm_krb5_get_default_realm();
- if (wdefrealm == NULL) {
- kherr_reportf(L"Can't determine default realm");
- goto cleanup;
- }
-
- princ_realm = krb5_princ_realm(kcontext, princ);
- UnicodeStrToAnsi(defrealm, sizeof(defrealm), wdefrealm);
-
- if (strncmp(defrealm, princ_realm->data, princ_realm->length)) {
- kherr_reportf(L"Realm mismatch. Wanted [%S], found [%*S]",
- defrealm, princ_realm->length, princ_realm->data);
- PFREE(wdefrealm);
- goto cleanup;
- }
-
- PFREE(wdefrealm);
- }
-
- if (KHM_SUCCEEDED(kcdb_identity_create(wname,
- KCDB_IDENT_FLAG_CREATE,
- &ident))) {
- khm_handle idconfig = NULL;
- khm_handle k5config = NULL;
- khm_size cb;
-
- wname[0] = L'\0';
-
- kcdb_identity_get_config(ident, KHM_FLAG_CREATE, &idconfig);
- if (idconfig == NULL)
- goto _done_checking_config;
-
- khc_open_space(idconfig, CSNAME_KRB5CRED, KHM_FLAG_CREATE, &k5config);
- if (k5config == NULL)
- goto _done_checking_config;
-
- cb = sizeof(wname);
- khc_read_string(k5config,
- L"DefaultCCName",
- wname, &cb);
-
- _done_checking_config:
-
- if (idconfig)
- khc_close_space(idconfig);
- if (k5config)
- khc_close_space(k5config);
-
- if (wname[0]) {
- UnicodeStrToAnsi(cname, sizeof(cname), wname);
- } else {
- StringCbPrintfA(cname, sizeof(cname), "API:%s", princ_name);
- }
-
- cache_name = cname;
-
- } else {
- /* the identity could not be created. we just use the
- name of the principal as the ccache name. */
- StringCbPrintfA(cname, sizeof(cname), "API:%s", princ_name);
- cache_name = cname;
- }
-
- kherr_reportf(L"Resolving target cache [%S]\n", cache_name);
-
- if (code = pkrb5_cc_resolve(kcontext, cache_name, &ccache)) {
- kherr_reportf(L"Cannot resolve cache [%S] with code=%d. Trying default.\n", cache_name, code);
-
- if (code = pkrb5_cc_default(kcontext, &ccache)) {
- kherr_reportf(L"Failed to resolve default ccache. Code=%d", code);
- goto cleanup;
- }
- }
-
- kherr_reportf(L"Initializing ccache\n");
- if (code = pkrb5_cc_initialize(kcontext, ccache, princ))
- goto cleanup;
-
- kherr_reportf(L"Copying credentials\n");
- if (code = pkrb5_cc_copy_creds(kcontext, mslsa_ccache, ccache))
- goto cleanup;
-
- /* and mark the identity as having been imported */
- if (ident) {
- khm_krb5_set_identity_flags(ident, K5IDFLAG_IMPORTED, K5IDFLAG_IMPORTED);
-
- if (ret_ident) {
- *ret_ident = ident;
- kcdb_identity_hold(*ret_ident);
- }
- }
-
- rc = TRUE;
-
- } else {
- /* Enumerate tickets from cache looking for an initial ticket */
- if ((code = pkrb5_cc_start_seq_get(kcontext, mslsa_ccache, &cursor)))
- goto cleanup;
-
- while (!(code = pkrb5_cc_next_cred(kcontext, mslsa_ccache,
- &cursor, &creds))) {
- if ( creds.ticket_flags & TKT_FLG_INITIAL ) {
- rc = TRUE;
- pkrb5_free_cred_contents(kcontext, &creds);
- break;
- }
- pkrb5_free_cred_contents(kcontext, &creds);
- }
- pkrb5_cc_end_seq_get(kcontext, mslsa_ccache, &cursor);
- }
-
-cleanup:
- kherr_reportf(L" Received code=%d", code);
-
- if (princ_name)
- pkrb5_free_unparsed_name(kcontext, princ_name);
- if (princ)
- pkrb5_free_principal(kcontext, princ);
- if (ccache)
- pkrb5_cc_close(kcontext, ccache);
- if (mslsa_ccache)
- pkrb5_cc_close(kcontext, mslsa_ccache);
- if (kcontext)
- pkrb5_free_context(kcontext);
- if (ident)
- kcdb_identity_release(ident);
-
- return(rc);
-#endif /* NO_KRB5 */
-}
-
-#define KRB_FILE "KRB.CON"
-#define KRBREALM_FILE "KRBREALM.CON"
-#define KRB5_FILE "KRB5.INI"
-#define KRB5_TMP_FILE "KRB5.INI.TMP"
-
-BOOL
-khm_krb5_get_temp_profile_file(LPSTR confname, UINT szConfname)
-{
- GetTempPathA(szConfname, confname);
- confname[szConfname-1] = '\0';
- StringCchCatA(confname, szConfname, KRB5_TMP_FILE);
- confname[szConfname-1] = '\0';
- return FALSE;
-}
-
-#ifdef NOT_QUITE_IMPLEMENTED_YET
-BOOL
-khm_krb5_set_profile_file(krb5_context ctx, LPSTR confname)
-{
- char *conffiles[2];
-
- if (confname == NULL ||
- pkrb5_set_config_files == NULL ||
- ctx == NULL)
- return FALSE;
-
- conffiles[0] = confname;
- conffiles[1] = NULL;
-
- if (pkrb5_set_config_files(ctx, conffiles))
- return FALSE;
- else
- return TRUE;
-}
-#endif
-
-BOOL
-khm_krb5_get_profile_file(LPSTR confname, UINT szConfname)
-{
- char **configFile = NULL;
- if (pkrb5_get_default_config_files(&configFile))
- {
- GetWindowsDirectoryA(confname,szConfname);
- confname[szConfname-1] = '\0';
-
- StringCchCatA(confname, szConfname, "\\");
- StringCchCatA(confname, szConfname, KRB5_FILE);
-
- return FALSE;
- }
-
- *confname = 0;
-
- if (configFile)
- {
- StringCchCopyA(confname, szConfname, *configFile);
- pkrb5_free_config_files(configFile);
- }
-
- if (!*confname)
- {
- GetWindowsDirectoryA(confname,szConfname);
- confname[szConfname-1] = '\0';
- StringCchCatA(confname, szConfname, "\\");
- StringCchCatA(confname, szConfname, KRB5_FILE);
- }
-
- return FALSE;
-}
-
-BOOL
-khm_get_krb4_con_file(LPSTR confname, UINT szConfname)
-{
- if (hKrb5 && !hKrb4) { // hold krb.con where krb5.ini is located
- CHAR krbConFile[MAX_PATH]="";
- LPSTR pFind;
-
- //strcpy(krbConFile, CLeashApp::m_krbv5_profile->first_file->filename);
- if (khm_krb5_get_profile_file(krbConFile, sizeof(krbConFile))) {
- GetWindowsDirectoryA(krbConFile,sizeof(krbConFile));
- krbConFile[MAX_PATH-1] = '\0';
- StringCchCatA(confname, szConfname, "\\");
- }
-
- pFind = strrchr(krbConFile, '\\');
- if (pFind) {
- *pFind = '\0';
- StringCchCatA(krbConFile, ARRAYLENGTH(krbConFile), "\\");
- StringCchCatA(krbConFile, ARRAYLENGTH(krbConFile), KRB_FILE);
- }
- else
- krbConFile[0] = '\0';
-
- StringCchCopyA(confname, szConfname, krbConFile);
- }
- else if (hKrb4) {
- unsigned int size = szConfname;
- memset(confname, '\0', szConfname);
- if (!pkrb_get_krbconf2(confname, &size))
- { // Error has happened
- GetWindowsDirectoryA(confname,szConfname);
- confname[szConfname-1] = '\0';
- StringCchCatA(confname, szConfname, "\\");
- StringCchCatA(confname, szConfname, KRB_FILE);
- }
- }
- return FALSE;
-}
-
-int
-readstring(FILE * file, char * buf, int len)
-{
- int c,i;
- memset(buf, '\0', sizeof(buf));
- for (i=0, c=fgetc(file); c != EOF ; c=fgetc(file), i++) {
- if (i < sizeof(buf)) {
- if (c == '\n') {
- buf[i] = '\0';
- return i;
- } else {
- buf[i] = c;
- }
- } else {
- if (c == '\n') {
- buf[len-1] = '\0';
- return(i);
- }
- }
- }
- if (c == EOF) {
- if (i > 0 && i < len) {
- buf[i] = '\0';
- return(i);
- } else {
- buf[len-1] = '\0';
- return(-1);
- }
- }
- return(-1);
-}
-
-/*! \internal
- \brief Return a list of configured realms
-
- The string that is returned is a set of null terminated unicode
- strings, each of which denotes one realm. The set is terminated
- by a zero length null terminated string.
-
- The caller should free the returned string using free()
-
- \return The string with the list of realms or NULL if the
- operation fails.
-*/
-wchar_t *
-khm_krb5_get_realm_list(void)
-{
- wchar_t * rlist = NULL;
-
- if (pprofile_get_subsection_names && pprofile_free_list) {
- const char* rootSection[] = {"realms", NULL};
- const char** rootsec = rootSection;
- char **sections = NULL, **cpp = NULL, *value = NULL;
-
- char krb5_conf[MAX_PATH+1];
-
- if (!khm_krb5_get_profile_file(krb5_conf,sizeof(krb5_conf))) {
- profile_t profile;
- long retval;
- const char *filenames[2];
- wchar_t * d;
- size_t cbsize;
- size_t t;
-
- filenames[0] = krb5_conf;
- filenames[1] = NULL;
- retval = pprofile_init(filenames, &profile);
- if (!retval) {
- retval = pprofile_get_subsection_names(profile, rootsec,
- &sections);
-
- if (!retval)
- {
- /* first figure out how much space to allocate */
- cbsize = 0;
- for (cpp = sections; *cpp; cpp++)
- {
- cbsize += sizeof(wchar_t) * (strlen(*cpp) + 1);
- }
- cbsize += sizeof(wchar_t); /* double null terminated */
-
- rlist = PMALLOC(cbsize);
- d = rlist;
- for (cpp = sections; *cpp; cpp++)
- {
- AnsiStrToUnicode(d, cbsize, *cpp);
- t = wcslen(d) + 1;
- d += t;
- cbsize -= sizeof(wchar_t) * t;
- }
- *d = L'\0';
- }
-
- pprofile_free_list(sections);
-
-#if 0
- retval = pprofile_get_string(profile, "libdefaults","noaddresses", 0, "true", &value);
- if ( value ) {
- disable_noaddresses = config_boolean_to_int(value);
- pprofile_release_string(value);
- }
-#endif
- pprofile_release(profile);
- }
- }
- } else {
- FILE * file;
- char krb_conf[MAX_PATH+1];
- char * p;
- size_t cbsize, t;
- wchar_t * d;
-
- if (!khm_get_krb4_con_file(krb_conf,sizeof(krb_conf)) &&
-#if _MSC_VER >= 1400
- !fopen_s(&file, krb_conf, "rt")
-#else
- (file = fopen(krb_conf, "rt"))
-#endif
- )
- {
- char lineBuf[256];
-
- /*TODO: compute the actual required buffer size instead of hardcoding */
- cbsize = 16384; // arbitrary
- rlist = PMALLOC(cbsize);
- d = rlist;
-
- // Skip the default realm
- readstring(file,lineBuf,sizeof(lineBuf));
-
- // Read the defined realms
- while (TRUE)
- {
- if (readstring(file,lineBuf,sizeof(lineBuf)) < 0)
- break;
-
- if (*(lineBuf + strlen(lineBuf) - 1) == '\r')
- *(lineBuf + strlen(lineBuf) - 1) = 0;
-
- for (p=lineBuf; *p ; p++)
- {
- if (isspace(*p)) {
- *p = 0;
- break;
- }
- }
-
- if ( strncmp(".KERBEROS.OPTION.",lineBuf,17) ) {
- t = strlen(lineBuf) + 1;
- if(cbsize > (1 + t*sizeof(wchar_t))) {
- AnsiStrToUnicode(d, cbsize, lineBuf);
- d += t;
- cbsize -= t * sizeof(wchar_t);
- } else
- break;
- }
- }
-
- *d = L'\0';
-
- fclose(file);
- }
- }
-
- return rlist;
-}
-
-/*! \internal
- \brief Get the default realm
-
- A string will be returned that specifies the default realm. The
- caller should free the string using PFREE().
-
- Returns NULL if the operation fails.
-*/
-wchar_t *
-khm_krb5_get_default_realm(void)
-{
- wchar_t * realm;
- size_t cch;
- krb5_context ctx=0;
- char * def = 0;
-
- pkrb5_init_context(&ctx);
-
- if (ctx == 0)
- return NULL;
-
- pkrb5_get_default_realm(ctx,&def);
-
- if (def) {
- cch = strlen(def) + 1;
- realm = PMALLOC(sizeof(wchar_t) * cch);
- AnsiStrToUnicode(realm, sizeof(wchar_t) * cch, def);
- pkrb5_free_default_realm(ctx, def);
- } else
- realm = NULL;
-
- pkrb5_free_context(ctx);
-
- return realm;
-}
-
-long
-khm_krb5_set_default_realm(wchar_t * realm) {
- krb5_context ctx=0;
- char * def = 0;
- long rv = 0;
- char astr[K5_MAXCCH_REALM];
-
- UnicodeStrToAnsi(astr, sizeof(astr), realm);
-
- pkrb5_init_context(&ctx);
- pkrb5_get_default_realm(ctx,&def);
-
- if ((def && strcmp(def, astr)) ||
- !def) {
- rv = pkrb5_set_default_realm(ctx, astr);
- }
-
- if (def) {
- pkrb5_free_default_realm(ctx, def);
- }
-
- pkrb5_free_context(ctx);
-
- return rv;
-}
-
-wchar_t *
-khm_get_realm_from_princ(wchar_t * princ) {
- wchar_t * t;
-
- if(!princ)
- return NULL;
-
- for (t = princ; *t; t++) {
- if(*t == L'\\') { /* escape */
- t++;
- if(! *t) /* malformed */
- break;
- } else if (*t == L'@')
- break;
- }
-
- if (*t == '@' && *(t+1) != L'\0')
- return (t+1);
- else
- return NULL;
-}
-
-long
-khm_krb5_changepwd(char * principal,
- char * password,
- char * newpassword,
- char** error_str)
-{
- krb5_error_code rc = 0;
- int result_code = 0;
- krb5_data result_code_string, result_string;
- krb5_context context = 0;
- krb5_principal princ = 0;
- krb5_get_init_creds_opt opts;
- krb5_creds creds;
-
- result_string.data = 0;
- result_code_string.data = 0;
-
- if ( !pkrb5_init_context )
- goto cleanup;
-
- if (rc = pkrb5_init_context(&context)) {
- goto cleanup;
- }
-
- if (rc = pkrb5_parse_name(context, principal, &princ)) {
- goto cleanup;
- }
-
- pkrb5_get_init_creds_opt_init(&opts);
- pkrb5_get_init_creds_opt_set_tkt_life(&opts, 5*60);
- pkrb5_get_init_creds_opt_set_renew_life(&opts, 0);
- pkrb5_get_init_creds_opt_set_forwardable(&opts, 0);
- pkrb5_get_init_creds_opt_set_proxiable(&opts, 0);
- pkrb5_get_init_creds_opt_set_address_list(&opts,NULL);
-
- if (rc = pkrb5_get_init_creds_password(context, &creds, princ,
- password, 0, 0, 0,
- "kadmin/changepw", &opts)) {
- if (rc == KRB5KRB_AP_ERR_BAD_INTEGRITY) {
-#if 0
- com_err(argv[0], 0,
- "Password incorrect while getting initial ticket");
-#endif
- } else {
-#if 0
- com_err(argv[0], ret, "getting initial ticket");
-#endif
- }
- goto cleanup;
- }
-
- if (rc = pkrb5_change_password(context, &creds, newpassword,
- &result_code, &result_code_string,
- &result_string)) {
-#if 0
- com_err(argv[0], ret, "changing password");
-#endif
- goto cleanup;
- }
-
- if (result_code) {
- int len = result_code_string.length +
- (result_string.length ? (sizeof(": ") - 1) : 0) +
- result_string.length;
- if (len && error_str) {
- *error_str = PMALLOC(len + 1);
- if (*error_str)
- StringCchPrintfA(*error_str, len+1,
- "%.*s%s%.*s",
- result_code_string.length,
- result_code_string.data,
- result_string.length?": ":"",
- result_string.length,
- result_string.data);
- }
- rc = result_code;
- goto cleanup;
- }
-
- cleanup:
- if (result_string.data)
- pkrb5_free_data_contents(context, &result_string);
-
- if (result_code_string.data)
- pkrb5_free_data_contents(context, &result_code_string);
-
- if (princ)
- pkrb5_free_principal(context, princ);
-
- if (context)
- pkrb5_free_context(context);
-
- return rc;
-}
-
-khm_int32 KHMAPI
-khm_krb5_creds_is_equal(khm_handle vcred1, khm_handle vcred2, void * dummy) {
- if (kcdb_creds_comp_attr(vcred1, vcred2, KCDB_ATTR_LOCATION) ||
- kcdb_creds_comp_attr(vcred1, vcred2, attr_id_key_enctype) ||
- kcdb_creds_comp_attr(vcred1, vcred2, attr_id_tkt_enctype) ||
- kcdb_creds_comp_attr(vcred1, vcred2, attr_id_kvno))
- return 1;
- else
- return 0;
-}
-
-void
-khm_krb5_set_identity_flags(khm_handle identity,
- khm_int32 flag_mask,
- khm_int32 flag_value) {
-
- khm_int32 t = 0;
- khm_size cb;
-
- cb = sizeof(t);
- if (KHM_FAILED(kcdb_identity_get_attr(identity,
- attr_id_krb5_idflags,
- NULL,
- &t, &cb))) {
- t = 0;
- }
-
- t &= ~flag_mask;
- t |= (flag_value & flag_mask);
-
- kcdb_identity_set_attr(identity,
- attr_id_krb5_idflags,
- &t, sizeof(t));
-}
-
-khm_int32
-khm_krb5_get_identity_flags(khm_handle identity) {
- khm_int32 t = 0;
- khm_size cb;
-
- cb = sizeof(t);
- kcdb_identity_get_attr(identity,
- attr_id_krb5_idflags,
- NULL, &t, &cb);
-
- return t;
-}
-
-long
-khm_krb5_get_temp_ccache(krb5_context ctx,
- krb5_ccache * prcc) {
- int rnd = rand();
- char ccname[MAX_PATH];
- long code = 0;
- krb5_ccache cc = 0;
-
- StringCbPrintfA(ccname, sizeof(ccname), "MEMORY:TempCache%8x", rnd);
-
- code = pkrb5_cc_resolve(ctx, ccname, &cc);
-
- if (code == 0)
- *prcc = cc;
-
- return code;
-}
-
-/*
-
- The configuration information for each identity comes from a
- multitude of layers organized as follows. The ordering is
- decreasing in priority. When looking up a value, the value will be
- looked up in each layer in turn starting at level 0. The first
- instance of the value found will be the effective value.
-
- 0 : <identity configuration>\Krb5Cred
-
- 0.1: per user
-
- 0.2: per machine
-
- 1 : <plugin configuration>\Parameters\Realms\<realm of identity>
-
- 1.1: per user
-
- 1.2: per machine
-
- 2 : <plugin configuration>\Parameters
-
- 2.1: per user
-
- 2.2: per machine
-
- 2.3: schema
-
- */
-khm_int32
-khm_krb5_get_identity_config(khm_handle ident,
- khm_int32 flags,
- khm_handle * ret_csp) {
-
- khm_int32 rv = KHM_ERROR_SUCCESS;
- khm_handle csp_i = NULL;
- khm_handle csp_ik5 = NULL;
- khm_handle csp_realms = NULL;
- khm_handle csp_realm = NULL;
- khm_handle csp_plugins = NULL;
- khm_handle csp_krbcfg = NULL;
- khm_handle csp_rv = NULL;
- wchar_t realm[KCDB_IDENT_MAXCCH_NAME];
-
- realm[0] = L'\0';
-
- if (ident) {
- wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
- wchar_t * trealm;
- khm_size cb_idname = sizeof(idname);
-
- rv = kcdb_identity_get_name(ident, idname, &cb_idname);
- if (KHM_SUCCEEDED(rv) &&
- (trealm = khm_get_realm_from_princ(idname)) != NULL) {
- StringCbCopy(realm, sizeof(realm), trealm);
- }
- }
-
- if (ident) {
- rv = kcdb_identity_get_config(ident, flags, &csp_i);
- if (KHM_FAILED(rv))
- goto try_realm;
-
- rv = khc_open_space(csp_i, CSNAME_KRB5CRED, flags, &csp_ik5);
- if (KHM_FAILED(rv))
- goto try_realm;
-
- try_realm:
-
- if (realm[0] == L'\0')
- goto done_shadow_realm;
-
- rv = khc_open_space(csp_params, CSNAME_REALMS, flags, &csp_realms);
- if (KHM_FAILED(rv))
- goto done_shadow_realm;
-
- rv = khc_open_space(csp_realms, realm, flags, &csp_realm);
- if (KHM_FAILED(rv))
- goto done_shadow_realm;
-
- rv = khc_shadow_space(csp_realm, csp_params);
-
- done_shadow_realm:
-
- if (csp_ik5) {
- if (csp_realm)
- rv = khc_shadow_space(csp_ik5, csp_realm);
- else
- rv = khc_shadow_space(csp_ik5, csp_params);
-
- csp_rv = csp_ik5;
- } else {
- if (csp_realm)
- csp_rv = csp_realm;
- }
- }
-
- if (csp_rv == NULL) {
-
- /* No valid identity specified or the specified identity
- doesn't have any configuration. We default to the
- parameters key. */
-
- /* we don't just return csp_params since that's a global
- handle that we shouldn't close until the plugin is
- unloaded. The caller is going to close the returned handle
- when it is done. So we need to create a new csp_params
- that can safely be closed. */
-
- rv = kmm_get_plugins_config(0, &csp_plugins);
- if (KHM_FAILED(rv))
- goto done;
-
- rv = khc_open_space(csp_plugins, CSNAME_KRB5CRED, flags, &csp_krbcfg);
- if (KHM_FAILED(rv))
- goto done;
-
- rv = khc_open_space(csp_krbcfg, CSNAME_PARAMS, flags, &csp_rv);
- }
-
- done:
-
- *ret_csp = csp_rv;
-
- /* leave csp_ik5. If it's non-NULL, then it's the return value */
- /* leave csp_rv. It's the return value. */
- if (csp_i)
- khc_close_space(csp_i);
- if (csp_realms)
- khc_close_space(csp_realms);
-
- /* csp_realm can also be a return value if csp_ik5 was NULL */
- if (csp_realm && csp_realm != csp_rv)
- khc_close_space(csp_realm);
-
- if (csp_plugins)
- khc_close_space(csp_plugins);
- if (csp_krbcfg)
- khc_close_space(csp_krbcfg);
-
- return rv;
-}
-
-/* from get_in_tkt.c */
-static krb5_error_code
-get_libdefault_string(profile_t profile, const char * realm,
- const char * option, char ** ret_val) {
- char realmstr[K5_MAXCCH_REALM];
- char **nameval = NULL;
- const char * names[4];
- krb5_error_code code = 0;
-
- names[0] = "libdefaults";
-
- if (!realm || !realm[0])
- goto try_number_two;
-
- StringCbCopyA(realmstr, sizeof(realmstr), realm);
-
- /*
- * Try number one:
- *
- * [libdefaults]
- * REALM = {
- * option = <boolean>
- * }
- */
-
- names[1] = realmstr;
- names[2] = option;
- names[3] = 0;
- code = pprofile_get_values(profile, names, &nameval);
- if (code == 0 && nameval && nameval[0])
- goto goodbye;
-
- try_number_two:
-
- /*
- * Try number two:
- *
- * [libdefaults]
- * option = <boolean>
- */
-
- names[1] = option;
- names[2] = 0;
- code = pprofile_get_values(profile, names, &nameval);
- if (code == 0 && nameval && nameval[0])
- goto goodbye;
-
- goodbye:
- if (!nameval)
- return(ENOENT);
-
- if (!nameval[0]) {
- code = ENOENT;
- } else {
- size_t cb;
-
- if (FAILED(StringCbLengthA(nameval[0], K5_MAXCCH_REALM * sizeof(char), &cb))) {
- code = ENOMEM;
- } else {
- cb += sizeof(char);
- *ret_val = PMALLOC(cb);
-
- if (!*ret_val)
- code = ENOMEM;
- else {
- StringCbCopyA(*ret_val, cb, nameval[0]);
- code = 0;
- }
- }
- }
-
- pprofile_free_list(nameval);
-
- return code;
-}
-
-khm_int32
-khm_krb5_get_identity_params(khm_handle ident, k5_params * p) {
-
- khm_int32 rv = KHM_ERROR_SUCCESS;
- khm_handle csp_id = NULL;
- khm_int32 regf = 0;
- khm_int32 proff = 0;
- khm_int32 e;
- khm_int32 v;
- CHAR confname[MAX_PATH];
- CHAR realmname[K5_MAXCCH_REALM];
-
- ZeroMemory(p, sizeof(*p));
-
- rv = khm_krb5_get_identity_config(ident, 0, &csp_id);
- if (KHM_FAILED(rv))
- goto done_reg;
-
-
-#define GETVAL(vname, vfield, flag) \
- do { \
- e = khc_value_exists(csp_id, vname); \
- rv = khc_read_int32(csp_id, vname, &v); \
- if (KHM_FAILED(rv)) goto done_reg; \
- p->vfield = v; \
- if ((e & ~KCONF_FLAG_SCHEMA) != 0) regf |= flag; \
- } while(FALSE)
-
- /* Flags */
- GETVAL(L"Renewable", renewable, K5PARAM_F_RENEW);
- GETVAL(L"Forwardable", forwardable, K5PARAM_F_FORW);
- GETVAL(L"Proxiable", proxiable, K5PARAM_F_PROX);
- GETVAL(L"Addressless", addressless, K5PARAM_F_ADDL);
- GETVAL(L"PublicIP", publicIP, K5PARAM_F_PUBIP);
-
- /* Lifetime */
- GETVAL(L"DefaultLifetime", lifetime, K5PARAM_F_LIFE);
- GETVAL(L"MaxLifetime", lifetime_max, K5PARAM_F_LIFE_H);
- GETVAL(L"MinLifetime", lifetime_min, K5PARAM_F_LIFE_L);
-
- /* Renewable lifetime */
- GETVAL(L"DefaultRenewLifetime", renew_life, K5PARAM_F_RLIFE);
- GETVAL(L"MaxRenewLifetime", renew_life_max, K5PARAM_F_RLIFE_H);
- GETVAL(L"MinRenewLifetime", renew_life_min, K5PARAM_F_RLIFE_L);
-
-#undef GETVAL
-
- done_reg:
-
- if (csp_id)
- khc_close_space(csp_id);
-
- /* if all the parameters were read from the registry, then we have
- no reason to read from the profile file. */
- if (regf == K5PARAM_FM_ALL) {
- p->source_reg = regf;
- return KHM_ERROR_SUCCESS;
- }
-
- if (rv)
- return rv;
-
- /* we need to figure out the realm name, since there might be
- per-realm configuration in the profile file. */
-
- realmname[0] = '\0';
-
- if (ident) {
- wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
- khm_size cb;
-
- idname[0] = L'\0';
- cb = sizeof(idname);
- rv = kcdb_identity_get_name(ident, idname, &cb);
- if (KHM_SUCCEEDED(rv)) {
- wchar_t * wrealm;
-
- wrealm = khm_get_realm_from_princ(idname);
- if (wrealm) {
- UnicodeStrToAnsi(realmname, sizeof(realmname), wrealm);
- }
- }
- }
-
- /* If we get here, then some of the settings we read from the
- configuration actually came from the schema. In other words,
- the values weren't really defined for this identity. So we now
- have to read the values from the krb5 configuration file. */
-
- if (!khm_krb5_get_profile_file(confname, sizeof(confname))) {
- profile_t profile;
- const char * filenames[2];
- long retval;
-
- filenames[0] = confname;
- filenames[1] = NULL;
-
- if (!pprofile_init(filenames, &profile)) {
-
- /* default ticket lifetime */
- if (!(regf & K5PARAM_F_LIFE)) {
- char * value = NULL;
- retval = get_libdefault_string(profile, realmname,
- "ticket_lifetime", &value);
-
- if (retval == 0 && value) {
- krb5_deltat d;
-
- retval = pkrb5_string_to_deltat(value, &d);
- if (retval == KRB5_DELTAT_BADFORMAT) {
- /* Historically some sites use relations of
- the form 'ticket_lifetime = 24000' where
- the unit is left out but is assumed to be
- seconds. Then there are other sites which
- use the form 'ticket_lifetime = 600' where
- the unit is assumed to be minutes. While
- these are technically wrong (a unit needs
- to be specified), we try to accomodate for
- this using the safe assumption that the
- unit is seconds and tack an 's' to the end
- and see if that works. */
-
- size_t cch;
- char tmpbuf[256];
- char * buf;
-
- do {
- if (FAILED(StringCchLengthA(value, 1024 /* unresonably large size */,
- &cch)))
- break;
-
- cch += sizeof(char) * 2; /* NULL and new 's' */
- if (cch > ARRAYLENGTH(tmpbuf))
- buf = PMALLOC(cch * sizeof(char));
- else
- buf = tmpbuf;
-
- StringCchCopyA(buf, cch, value);
- StringCchCatA(buf, cch, "s");
-
- retval = pkrb5_string_to_deltat(buf, &d);
- if (retval == 0) {
- p->lifetime = d;
- proff |= K5PARAM_F_LIFE;
- }
-
- if (buf != tmpbuf)
- PFREE(buf);
-
- } while(0);
-
- } else if (retval == 0) {
- p->lifetime = d;
- proff |= K5PARAM_F_LIFE;
- }
-
- PFREE(value);
- }
- }
-
- if (!(regf & K5PARAM_F_RLIFE)) {
- char * value = NULL;
- retval = get_libdefault_string(profile, realmname,
- "renew_lifetime", &value);
- if (retval == 0 && value) {
- krb5_deltat d;
-
- retval = pkrb5_string_to_deltat(value, &d);
- if (retval == 0) {
- p->renew_life = d;
- proff |= K5PARAM_F_RLIFE;
- }
- PFREE(value);
- }
- }
-
- if (!(regf & K5PARAM_F_FORW)) {
- char * value = NULL;
- retval = get_libdefault_string(profile, realmname,
- "forwardable", &value);
- if (retval == 0 && value) {
- khm_boolean b;
-
- if (!khm_krb5_parse_boolean(value, &b))
- p->forwardable = b;
- else
- p->forwardable = FALSE;
- PFREE(value);
- proff |= K5PARAM_F_FORW;
- }
- }
-
- if (!(regf & K5PARAM_F_RENEW)) {
- char * value = NULL;
- retval = get_libdefault_string(profile, realmname,
- "renewable", &value);
- if (retval == 0 && value) {
- khm_boolean b;
-
- if (!khm_krb5_parse_boolean(value, &b))
- p->renewable = b;
- else
- p->renewable = TRUE;
- PFREE(value);
- proff |= K5PARAM_F_RENEW;
- }
- }
-
- if (!(regf & K5PARAM_F_ADDL)) {
- char * value = NULL;
- retval = get_libdefault_string(profile, realmname,
- "noaddresses", &value);
- if (retval == 0 && value) {
- khm_boolean b;
-
- if (!khm_krb5_parse_boolean(value, &b))
- p->addressless = b;
- else
- p->addressless = TRUE;
- PFREE(value);
- proff |= K5PARAM_F_ADDL;
- }
- }
-
- if (!(regf & K5PARAM_F_PROX)) {
- char * value = NULL;
- retval = get_libdefault_string(profile, realmname,
- "proxiable", &value);
- if (retval == 0 && value) {
- khm_boolean b;
-
- if (!khm_krb5_parse_boolean(value, &b))
- p->proxiable = b;
- else
- p->proxiable = FALSE;
- PFREE(value);
- proff |= K5PARAM_F_PROX;
- }
- }
-
- pprofile_release(profile);
- }
- }
-
- p->source_reg = regf;
- p->source_prof = proff;
-
- return rv;
-}
-
-/* Note that p->source_reg and p->source_prof is used in special ways
- here. All fields that are flagged in source_reg will be written to
- the configuration (if they are different from what
- khm_krb5_get_identity_params() reports). All fields that are
- flagged in source_prof will be removed from the configuration
- (thereby exposing the value defined in the profile file). */
-khm_int32
-khm_krb5_set_identity_params(khm_handle ident, const k5_params * p) {
- khm_int32 rv = KHM_ERROR_SUCCESS;
- khm_handle csp_id = NULL;
- k5_params p_s;
- khm_int32 source_reg = p->source_reg;
- khm_int32 source_prof = p->source_prof;
-
- rv = khm_krb5_get_identity_config(ident,
- KHM_PERM_WRITE | KHM_FLAG_CREATE |
- KCONF_FLAG_WRITEIFMOD,
- &csp_id);
- if (KHM_FAILED(rv))
- goto done_reg;
-
- khm_krb5_get_identity_params(ident, &p_s);
-
- /* Remove any bits that don't make sense. Not all values can be
- specified in the profile file. */
- source_prof &= K5PARAM_FM_PROF;
-
- /* if a flag appears in both source_prof and source_reg, remove
- the flag from source_reg. */
- source_reg &= ~source_prof;
-
- /* we only write values that have changed, and that are flagged in
- source_reg */
-
- if ((source_reg & K5PARAM_F_RENEW) &&
- !!p_s.renewable != !!p->renewable)
- khc_write_int32(csp_id, L"Renewable", !!p->renewable);
-
- if ((source_reg & K5PARAM_F_FORW) &&
- !!p_s.forwardable != !!p->forwardable)
- khc_write_int32(csp_id, L"Forwardable", !!p->forwardable);
-
- if ((source_reg & K5PARAM_F_PROX) &&
- !!p_s.proxiable != !!p->proxiable)
- khc_write_int32(csp_id, L"Proxiable", !!p->proxiable);
-
- if ((source_reg & K5PARAM_F_ADDL) &&
- !!p_s.addressless != !!p->addressless)
- khc_write_int32(csp_id, L"Addressless", !!p->addressless);
-
- if ((source_reg & K5PARAM_F_PUBIP) &&
- p_s.publicIP != p->publicIP)
- khc_write_int32(csp_id, L"PublicIP", p->publicIP);
-
- if ((source_reg & K5PARAM_F_LIFE) &&
- p_s.lifetime != p->lifetime)
- khc_write_int32(csp_id, L"DefaultLifetime", p->lifetime);
-
- if ((source_reg & K5PARAM_F_LIFE_H) &&
- p_s.lifetime_max != p->lifetime_max)
- khc_write_int32(csp_id, L"MaxLifetime", p->lifetime_max);
-
- if ((source_reg & K5PARAM_F_LIFE_L) &&
- p_s.lifetime_min != p->lifetime_min)
- khc_write_int32(csp_id, L"MinLifetime", p->lifetime_min);
-
- if ((source_reg & K5PARAM_F_RLIFE) &&
- p_s.renew_life != p->renew_life)
- khc_write_int32(csp_id, L"DefaultRenewLifetime", p->renew_life);
-
- if ((source_reg & K5PARAM_F_RLIFE_H) &&
- p_s.renew_life_max != p->renew_life_max)
- khc_write_int32(csp_id, L"MaxRenewLifetime", p->renew_life_max);
-
- if ((source_reg & K5PARAM_F_RLIFE_L) &&
- p_s.renew_life_min != p->renew_life_min)
- khc_write_int32(csp_id, L"MinRenewLifetime", p->renew_life_min);
-
- /* and now, remove the values that are present in source_prof.
- Not all values are removed since not all values can be
- specified in the profile file. */
- if (source_prof & K5PARAM_F_RENEW)
- khc_remove_value(csp_id, L"Renewable", 0);
-
- if (source_prof & K5PARAM_F_FORW)
- khc_remove_value(csp_id, L"Forwardable", 0);
-
- if (source_prof & K5PARAM_F_PROX)
- khc_remove_value(csp_id, L"Proxiable", 0);
-
- if (source_prof & K5PARAM_F_ADDL)
- khc_remove_value(csp_id, L"Addressless", 0);
-
- if (source_prof & K5PARAM_F_LIFE)
- khc_remove_value(csp_id, L"DefaultLifetime", 0);
-
- if (source_prof & K5PARAM_F_RLIFE)
- khc_remove_value(csp_id, L"DefaultRenewLifetime", 0);
-
- done_reg:
- if (csp_id != NULL)
- khc_close_space(csp_id);
-
- return rv;
-}
-
-static const char *const conf_yes[] = {
- "y", "yes", "true", "t", "1", "on",
- 0,
-};
-
-static const char *const conf_no[] = {
- "n", "no", "false", "nil", "0", "off",
- 0,
-};
-
-int
-khm_krb5_parse_boolean(const char *s, khm_boolean * b)
-{
- const char *const *p;
-
- for(p=conf_yes; *p; p++) {
- if (!_stricmp(*p,s)) {
- *b = TRUE;
- return 0;
- }
- }
-
- for(p=conf_no; *p; p++) {
- if (!_stricmp(*p,s)) {
- *b = FALSE;
- return 0;
- }
- }
-
- /* Default to "no" */
- return KHM_ERROR_INVALID_PARAM;
-}
+/*
+* Copyright (c) 2005 Massachusetts Institute of Technology
+* Copyright (c) 2006,2007 Secure Endpoints Inc.
+*
+* Permission is hereby granted, free of charge, to any person
+* obtaining a copy of this software and associated documentation
+* files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy,
+* modify, merge, publish, distribute, sublicense, and/or sell copies
+* of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be
+* included in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*/
+
+/* $Id$ */
+
+/* Originally this was krb5routines.c in Leash sources. Subsequently
+ * modified and adapted for NetIDMgr */
+
+#include<krbcred.h>
+#include<kherror.h>
+
+#define SECURITY_WIN32
+#include <security.h>
+
+#include <string.h>
+#include <time.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <strsafe.h>
+
+long
+khm_convert524(krb5_context alt_ctx)
+{
+ krb5_context ctx = 0;
+ krb5_error_code code = 0;
+ int icode = 0;
+ krb5_principal me = 0;
+ krb5_principal server = 0;
+ krb5_creds *v5creds = 0;
+ krb5_creds increds;
+ krb5_ccache cc = 0;
+ CREDENTIALS * v4creds = NULL;
+ static int init_ets = 1;
+
+ if (!pkrb5_init_context ||
+ !pkrb_in_tkt ||
+ !pkrb524_init_ets ||
+ !pkrb524_convert_creds_kdc)
+ return 0;
+
+ v4creds = (CREDENTIALS *) PMALLOC(sizeof(CREDENTIALS));
+ memset((char *) v4creds, 0, sizeof(CREDENTIALS));
+
+ memset((char *) &increds, 0, sizeof(increds));
+ /*
+ From this point on, we can goto cleanup because increds is
+ initialized.
+ */
+
+ if (alt_ctx)
+ {
+ ctx = alt_ctx;
+ }
+ else
+ {
+ code = pkrb5_init_context(&ctx);
+ if (code) goto cleanup;
+ }
+
+ code = pkrb5_cc_default(ctx, &cc);
+ if (code) goto cleanup;
+
+ if ( init_ets ) {
+ pkrb524_init_ets(ctx);
+ init_ets = 0;
+ }
+
+ if (code = pkrb5_cc_get_principal(ctx, cc, &me))
+ goto cleanup;
+
+ if ((code = pkrb5_build_principal(ctx,
+ &server,
+ krb5_princ_realm(ctx, me)->length,
+ krb5_princ_realm(ctx, me)->data,
+ "krbtgt",
+ krb5_princ_realm(ctx, me)->data,
+ NULL)))
+ {
+ goto cleanup;
+ }
+
+ increds.client = me;
+ increds.server = server;
+ increds.times.endtime = 0;
+ increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC;
+ if ((code = pkrb5_get_credentials(ctx, 0,
+ cc,
+ &increds,
+ &v5creds)))
+ {
+ goto cleanup;
+ }
+
+ if ((icode = pkrb524_convert_creds_kdc(ctx,
+ v5creds,
+ v4creds)))
+ {
+ goto cleanup;
+ }
+
+ /* initialize ticket cache */
+ if ((icode = pkrb_in_tkt(v4creds->pname, v4creds->pinst, v4creds->realm)
+ != KSUCCESS))
+ {
+ goto cleanup;
+ }
+ /* stash ticket, session key, etc. for future use */
+ if ((icode = pkrb_save_credentials(v4creds->service,
+ v4creds->instance,
+ v4creds->realm,
+ v4creds->session,
+ v4creds->lifetime,
+ v4creds->kvno,
+ &(v4creds->ticket_st),
+ v4creds->issue_date)))
+ {
+ goto cleanup;
+ }
+
+cleanup:
+ memset(v4creds, 0, sizeof(v4creds));
+ PFREE(v4creds);
+
+ if (v5creds) {
+ pkrb5_free_creds(ctx, v5creds);
+ }
+ if (increds.client == me)
+ me = 0;
+ if (increds.server == server)
+ server = 0;
+ pkrb5_free_cred_contents(ctx, &increds);
+ if (server) {
+ pkrb5_free_principal(ctx, server);
+ }
+ if (me) {
+ pkrb5_free_principal(ctx, me);
+ }
+ pkrb5_cc_close(ctx, cc);
+
+ if (ctx && (ctx != alt_ctx)) {
+ pkrb5_free_context(ctx);
+ }
+ return !(code || icode);
+}
+
+#ifdef DEPRECATED_REMOVABLE
+int com_addr(void)
+{
+ long ipAddr;
+ char loc_addr[ADDR_SZ];
+ CREDENTIALS cred;
+ char service[40];
+ char instance[40];
+ // char addr[40];
+ char realm[40];
+ struct in_addr LocAddr;
+ int k_errno;
+
+ if (pkrb_get_cred == NULL)
+ return(KSUCCESS);
+
+ k_errno = (*pkrb_get_cred)(service,instance,realm,&cred);
+ if (k_errno)
+ return KRBERR(k_errno);
+
+ while(1) {
+ ipAddr = (*pLocalHostAddr)();
+ LocAddr.s_addr = ipAddr;
+ StringCbCopyA(loc_addr, sizeof(loc_addr), inet_ntoa(LocAddr));
+ if ( strcmp(cred.address, loc_addr) != 0) {
+ /* TODO: do something about this */
+ //Leash_kdestroy ();
+ break;
+ }
+ break;
+ } // while()
+ return 0;
+}
+#endif
+
+/* we use these structures to keep track of identities that we find
+ while going through the API, FILE and MSLSA caches and enumerating
+ credentials. The only identities we want to keep track of are the
+ ones that have an initial ticket. We collect information for each
+ of the identities we find that we have initial tickets for and
+ then set the properties for the identities at once. */
+
+typedef struct tag_ident_data {
+ khm_handle ident; /* handle to the identity */
+ khm_int32 count; /* number of initial tickets we have
+ found for this identity. */
+ wchar_t ccname[MAX_PATH];
+ FILETIME ft_issue;
+ FILETIME ft_expire;
+ FILETIME ft_renewexpire;
+ khm_int32 krb5_flags;
+} ident_data;
+
+typedef struct tag_identlist {
+ ident_data * list;
+ khm_size n_list;
+ khm_size nc_list;
+} identlist;
+
+#define IDLIST_ALLOC_INCR 8
+
+static void
+tc_prep_idlist(identlist * idlist) {
+ khm_int32 rv;
+ khm_size cb_ids = 0;
+ khm_size n_ids = 0;
+ khm_size i;
+ wchar_t * ids = NULL;
+ wchar_t *thisid;
+
+ idlist->list = NULL;
+ idlist->n_list = 0;
+ idlist->nc_list = 0;
+
+ do {
+
+ if (ids) {
+ PFREE(ids);
+ ids = NULL;
+ }
+
+ rv = kcdb_identity_enum(KCDB_IDENT_FLAG_ACTIVE,
+ KCDB_IDENT_FLAG_ACTIVE,
+ NULL,
+ &cb_ids,
+ &n_ids);
+
+ if (rv != KHM_ERROR_TOO_LONG)
+ break; /* something else is wrong */
+
+ if (n_ids == 0 || cb_ids == 0)
+ break; /* no identities to process */
+
+#ifdef DEBUG
+ assert(cb_ids > 0);
+#endif
+
+ ids = PMALLOC(cb_ids);
+#ifdef DEBUG
+ assert(ids != NULL);
+#endif
+ if (ids == NULL)
+ break;
+
+ rv = kcdb_identity_enum(KCDB_IDENT_FLAG_ACTIVE,
+ KCDB_IDENT_FLAG_ACTIVE,
+ ids,
+ &cb_ids,
+ &n_ids);
+
+ if (KHM_SUCCEEDED(rv))
+ break;
+
+ } while (TRUE);
+
+ if (ids == NULL)
+ return;
+
+ if (KHM_FAILED(rv) || n_ids == 0) {
+ if (ids)
+ PFREE(ids);
+ return;
+ }
+
+ idlist->nc_list = UBOUNDSS(n_ids, IDLIST_ALLOC_INCR, IDLIST_ALLOC_INCR);
+
+ idlist->list = PCALLOC(idlist->nc_list, sizeof(idlist->list[0]));
+
+ for (i = 0, thisid = ids;
+ thisid && thisid[0];
+ thisid = multi_string_next(thisid)) {
+
+ khm_handle ident;
+
+ rv = kcdb_identity_create(thisid, 0, &ident);
+
+ if (KHM_FAILED(rv))
+ continue;
+
+ idlist->list[i].ident = ident;
+ idlist->list[i].count = 0;
+
+ i++;
+ }
+
+ idlist->n_list = i;
+
+ PFREE(ids);
+}
+
+static ident_data *
+tc_add_ident_to_list(identlist * idlist, khm_handle ident) {
+ khm_size i;
+ ident_data * d;
+
+ for (i=0; i < idlist->n_list; i++) {
+ if (kcdb_identity_is_equal(ident, idlist->list[i].ident))
+ break;
+ }
+
+ if (i < idlist->n_list) {
+ /* we already have this identity on our list. Increment the
+ count */
+ idlist->list[i].count++;
+ return &idlist->list[i];
+ }
+
+ /* it wasn't in our list. Add it */
+
+ if (idlist->n_list + 1 > idlist->nc_list) {
+ idlist->nc_list = UBOUNDSS(idlist->n_list + 1,
+ IDLIST_ALLOC_INCR,
+ IDLIST_ALLOC_INCR);
+#ifdef DEBUG
+ assert(idlist->n_list + 1 <= idlist->nc_list);
+#endif
+ idlist->list = PREALLOC(idlist->list,
+ sizeof(idlist->list[0]) * idlist->nc_list);
+#ifdef DEBUG
+ assert(idlist->list);
+#endif
+ ZeroMemory(&idlist->list[idlist->n_list],
+ sizeof(idlist->list[0]) *
+ (idlist->nc_list - idlist->n_list));
+ }
+
+ d = &idlist->list[idlist->n_list];
+
+ ZeroMemory(d, sizeof(*d));
+
+ d->ident = ident;
+ d->count = 1;
+
+ idlist->n_list++;
+
+ kcdb_identity_hold(ident);
+
+ return d;
+}
+
+static void
+tc_set_ident_data(identlist * idlist) {
+ khm_size i;
+ wchar_t k5idtype[KCDB_MAXCCH_NAME];
+
+ k5idtype[0] = L'\0';
+ LoadString(hResModule, IDS_KRB5_NC_NAME,
+ k5idtype, ARRAYLENGTH(k5idtype));
+
+ for (i=0; i < idlist->n_list; i++) {
+#ifdef DEBUG
+ assert(idlist->list[i].ident);
+#endif
+
+ if (idlist->list[i].count > 0) {
+ khm_int32 t;
+
+ t = credtype_id_krb5;
+ kcdb_identity_set_attr(idlist->list[i].ident,
+ KCDB_ATTR_TYPE,
+ &t,
+ sizeof(t));
+
+ /* We need to manually add the type name if we want the
+ name to show up in the property list for the identity.
+ The type name is only automatically calculated for
+ credentials. */
+ kcdb_identity_set_attr(idlist->list[i].ident,
+ KCDB_ATTR_TYPE_NAME,
+ k5idtype,
+ KCDB_CBSIZE_AUTO);
+
+ kcdb_identity_set_attr(idlist->list[i].ident,
+ attr_id_krb5_ccname,
+ idlist->list[i].ccname,
+ KCDB_CBSIZE_AUTO);
+
+ kcdb_identity_set_attr(idlist->list[i].ident,
+ KCDB_ATTR_EXPIRE,
+ &idlist->list[i].ft_expire,
+ sizeof(idlist->list[i].ft_expire));
+
+ kcdb_identity_set_attr(idlist->list[i].ident,
+ KCDB_ATTR_ISSUE,
+ &idlist->list[i].ft_issue,
+ sizeof(idlist->list[i].ft_issue));
+
+ kcdb_identity_set_attr(idlist->list[i].ident,
+ attr_id_krb5_flags,
+ &idlist->list[i].krb5_flags,
+ sizeof(idlist->list[i].krb5_flags));
+
+ if (idlist->list[i].ft_renewexpire.dwLowDateTime == 0 &&
+ idlist->list[i].ft_renewexpire.dwHighDateTime == 0) {
+ kcdb_identity_set_attr(idlist->list[i].ident,
+ KCDB_ATTR_RENEW_EXPIRE,
+ NULL, 0);
+ } else {
+ kcdb_identity_set_attr(idlist->list[i].ident,
+ KCDB_ATTR_RENEW_EXPIRE,
+ &idlist->list[i].ft_renewexpire,
+ sizeof(idlist->list[i].ft_renewexpire));
+ }
+
+ } else {
+ /* We didn't see any TGTs for this identity. We have to
+ remove all the Krb5 supplied properties. */
+
+ khm_int32 t;
+ khm_size cb;
+
+ cb = sizeof(t);
+ if (KHM_SUCCEEDED(kcdb_identity_get_attr(idlist->list[i].ident,
+ KCDB_ATTR_TYPE, NULL,
+ &t,
+ &cb)) &&
+ t == credtype_id_krb5) {
+
+ /* disown this and remove all our properties. the
+ system will GC this identity if nobody claims it.*/
+
+ kcdb_identity_set_attr(idlist->list[i].ident,
+ KCDB_ATTR_TYPE, NULL, 0);
+ kcdb_identity_set_attr(idlist->list[i].ident,
+ KCDB_ATTR_TYPE_NAME, NULL, 0);
+ kcdb_identity_set_attr(idlist->list[i].ident,
+ attr_id_krb5_ccname, NULL, 0);
+ kcdb_identity_set_attr(idlist->list[i].ident,
+ KCDB_ATTR_EXPIRE, NULL, 0);
+ kcdb_identity_set_attr(idlist->list[i].ident,
+ KCDB_ATTR_ISSUE, NULL, 0);
+ kcdb_identity_set_attr(idlist->list[i].ident,
+ attr_id_krb5_flags, NULL, 0);
+ kcdb_identity_set_attr(idlist->list[i].ident,
+ KCDB_ATTR_RENEW_EXPIRE, NULL, 0);
+ } else {
+ /* otherwise, this identity doesn't belong to us. We
+ should leave it as is. */
+ }
+ }
+ }
+}
+
+static void
+tc_free_idlist(identlist * idlist) {
+ khm_size i;
+
+ for (i=0; i < idlist->n_list; i++) {
+ if (idlist->list[i].ident != NULL) {
+ kcdb_identity_release(idlist->list[i].ident);
+ idlist->list[i].ident = NULL;
+ }
+ }
+
+ if (idlist->list)
+ PFREE(idlist->list);
+ idlist->list = NULL;
+ idlist->n_list = 0;
+ idlist->nc_list = 0;
+}
+
+#ifndef ENCTYPE_LOCAL_RC4_MD4
+#define ENCTYPE_LOCAL_RC4_MD4 0xFFFFFF80
+#endif
+
+#define MAX_ADDRS 256
+
+static long get_tickets_from_cache(krb5_context ctx,
+ krb5_ccache cache,
+ identlist * idlist)
+{
+ krb5_error_code code;
+ krb5_principal KRBv5Principal;
+ krb5_flags flags = 0;
+ krb5_cc_cursor KRBv5Cursor;
+ krb5_creds KRBv5Credentials;
+ krb5_ticket *tkt=NULL;
+ char *ClientName = NULL;
+ char *PrincipalName = NULL;
+ wchar_t wbuf[256]; /* temporary conversion buffer */
+ wchar_t wcc_name[KRB5_MAXCCH_CCNAME]; /* credential cache name */
+ char *sServerName = NULL;
+ khm_handle ident = NULL;
+ khm_handle cred = NULL;
+ time_t tt;
+ FILETIME ft, eft;
+ khm_int32 ti;
+
+#ifdef KRB5_TC_NOTICKET
+ flags = KRB5_TC_NOTICKET;
+#else
+ flags = 0;
+#endif
+
+ {
+ const char * cc_name;
+ const char * cc_type;
+
+ cc_name = (*pkrb5_cc_get_name)(ctx, cache);
+ if(cc_name) {
+ cc_type = (*pkrb5_cc_get_type)(ctx, cache);
+ if (cc_type) {
+ StringCbPrintf(wcc_name, sizeof(wcc_name), L"%S:%S", cc_type, cc_name);
+ } else {
+ AnsiStrToUnicode(wcc_name, sizeof(wcc_name), cc_name);
+ khm_krb5_canon_cc_name(wcc_name, sizeof(wcc_name));
+ }
+ } else {
+ cc_type = (*pkrb5_cc_get_type)(ctx, cache);
+ if (cc_type) {
+ StringCbPrintf(wcc_name, sizeof(wcc_name), L"%S:", cc_type);
+ } else {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ StringCbCopy(wcc_name, sizeof(wcc_name), L"");
+ }
+ }
+ }
+
+ _reportf(L"Getting tickets from cache [%s]", wcc_name);
+
+ if ((code = (*pkrb5_cc_set_flags)(ctx, cache, flags)))
+ {
+ if (code != KRB5_FCC_NOFILE && code != KRB5_CC_NOTFOUND)
+ khm_krb5_error(code, "krb5_cc_set_flags()", 0, &ctx, &cache);
+
+ goto _exit;
+ }
+
+ if ((code = (*pkrb5_cc_get_principal)(ctx, cache, &KRBv5Principal)))
+ {
+ if (code != KRB5_FCC_NOFILE && code != KRB5_CC_NOTFOUND)
+ khm_krb5_error(code, "krb5_cc_get_principal()", 0, &ctx, &cache);
+
+ goto _exit;
+ }
+
+ PrincipalName = NULL;
+ ClientName = NULL;
+ sServerName = NULL;
+ if ((code = (*pkrb5_unparse_name)(ctx, KRBv5Principal,
+ (char **)&PrincipalName)))
+ {
+ if (PrincipalName != NULL)
+ (*pkrb5_free_unparsed_name)(ctx, PrincipalName);
+
+ (*pkrb5_free_principal)(ctx, KRBv5Principal);
+
+ goto _exit;
+ }
+
+ if (!strcspn(PrincipalName, "@" ))
+ {
+ if (PrincipalName != NULL)
+ (*pkrb5_free_unparsed_name)(ctx, PrincipalName);
+
+ (*pkrb5_free_principal)(ctx, KRBv5Principal);
+
+ goto _exit;
+ }
+
+ AnsiStrToUnicode(wbuf, sizeof(wbuf), PrincipalName);
+ if(KHM_FAILED(kcdb_identity_create(wbuf, KCDB_IDENT_FLAG_CREATE,
+ &ident))) {
+ /* something bad happened */
+ code = 1;
+ goto _exit;
+ }
+
+ _reportf(L"Found principal [%s]", wbuf);
+
+ (*pkrb5_free_principal)(ctx, KRBv5Principal);
+
+ if ((code = (*pkrb5_cc_start_seq_get)(ctx, cache, &KRBv5Cursor)))
+ {
+ goto _exit;
+ }
+
+ memset(&KRBv5Credentials, '\0', sizeof(KRBv5Credentials));
+
+ ClientName = NULL;
+ sServerName = NULL;
+ cred = NULL;
+
+ while (!(code = pkrb5_cc_next_cred(ctx, cache, &KRBv5Cursor,
+ &KRBv5Credentials)))
+ {
+ khm_handle tident = NULL;
+ khm_int32 cred_flags = 0;
+
+ if(ClientName != NULL)
+ (*pkrb5_free_unparsed_name)(ctx, ClientName);
+ if(sServerName != NULL)
+ (*pkrb5_free_unparsed_name)(ctx, sServerName);
+ if(cred)
+ kcdb_cred_release(cred);
+
+ ClientName = NULL;
+ sServerName = NULL;
+ cred = NULL;
+
+ if ((*pkrb5_unparse_name)(ctx, KRBv5Credentials.client, &ClientName))
+ {
+ (*pkrb5_free_cred_contents)(ctx, &KRBv5Credentials);
+ khm_krb5_error(code, "krb5_free_cred_contents()", 0, &ctx, &cache);
+ continue;
+ }
+
+ if ((*pkrb5_unparse_name)(ctx, KRBv5Credentials.server, &sServerName))
+ {
+ (*pkrb5_free_cred_contents)(ctx, &KRBv5Credentials);
+ khm_krb5_error(code, "krb5_free_cred_contents()", 0, &ctx, &cache);
+ continue;
+ }
+
+ /* if the ClientName differs from PrincipalName for some
+ reason, we need to create a new identity */
+ if(strcmp(ClientName, PrincipalName)) {
+ AnsiStrToUnicode(wbuf, sizeof(wbuf), ClientName);
+ if(KHM_FAILED(kcdb_identity_create(wbuf, KCDB_IDENT_FLAG_CREATE,
+ &tident))) {
+ (*pkrb5_free_cred_contents)(ctx, &KRBv5Credentials);
+ continue;
+ }
+ } else {
+ tident = ident;
+ }
+
+ AnsiStrToUnicode(wbuf, sizeof(wbuf), sServerName);
+ if(KHM_FAILED(kcdb_cred_create(wbuf, tident, credtype_id_krb5,
+ &cred))) {
+ (*pkrb5_free_cred_contents)(ctx, &KRBv5Credentials);
+ continue;
+ }
+
+ if (!KRBv5Credentials.times.starttime)
+ KRBv5Credentials.times.starttime = KRBv5Credentials.times.authtime;
+
+ tt = KRBv5Credentials.times.starttime;
+ TimetToFileTime(tt, &ft);
+ kcdb_cred_set_attr(cred, KCDB_ATTR_ISSUE, &ft, sizeof(ft));
+
+ tt = KRBv5Credentials.times.endtime;
+ TimetToFileTime(tt, &eft);
+ kcdb_cred_set_attr(cred, KCDB_ATTR_EXPIRE, &eft, sizeof(eft));
+
+ {
+ FILETIME ftl;
+
+ ftl = FtSub(&eft, &ft);
+ kcdb_cred_set_attr(cred, KCDB_ATTR_LIFETIME, &ftl, sizeof(ftl));
+ }
+
+ if (KRBv5Credentials.times.renew_till > 0) {
+ FILETIME ftl;
+
+ tt = KRBv5Credentials.times.renew_till;
+ TimetToFileTime(tt, &eft);
+ kcdb_cred_set_attr(cred, KCDB_ATTR_RENEW_EXPIRE, &eft,
+ sizeof(eft));
+
+
+ ftl = FtSub(&eft, &ft);
+ kcdb_cred_set_attr(cred, KCDB_ATTR_RENEW_LIFETIME, &ftl,
+ sizeof(ftl));
+ }
+
+ ti = KRBv5Credentials.ticket_flags;
+ kcdb_cred_set_attr(cred, attr_id_krb5_flags, &ti, sizeof(ti));
+
+ /* special flags understood by NetIDMgr */
+ {
+ khm_int32 nflags = 0;
+
+ if (ti & TKT_FLG_RENEWABLE)
+ nflags |= KCDB_CRED_FLAG_RENEWABLE;
+ if (ti & TKT_FLG_INITIAL)
+ nflags |= KCDB_CRED_FLAG_INITIAL;
+ else {
+ krb5_data * c0, *c1, *r;
+
+ /* these are macros that do not allocate any memory */
+ c0 = krb5_princ_component(ctx,KRBv5Credentials.server,0);
+ c1 = krb5_princ_component(ctx,KRBv5Credentials.server,1);
+ r = krb5_princ_realm(ctx,KRBv5Credentials.server);
+
+ if ( c0 && c1 && r && c1->length == r->length &&
+ !strncmp(c1->data,r->data,r->length) &&
+ !strncmp("krbtgt",c0->data,c0->length) )
+ nflags |= KCDB_CRED_FLAG_INITIAL;
+ }
+
+ kcdb_cred_set_flags(cred, nflags, KCDB_CRED_FLAGMASK_EXT);
+
+ cred_flags = nflags;
+ }
+
+ if ( !pkrb5_decode_ticket(&KRBv5Credentials.ticket, &tkt)) {
+ ti = tkt->enc_part.enctype;
+ kcdb_cred_set_attr(cred, attr_id_tkt_enctype, &ti, sizeof(ti));
+ ti = tkt->enc_part.kvno;
+ kcdb_cred_set_attr(cred, attr_id_kvno, &ti, sizeof(ti));
+ pkrb5_free_ticket(ctx, tkt);
+ tkt = NULL;
+ }
+
+ ti = KRBv5Credentials.keyblock.enctype;
+ kcdb_cred_set_attr(cred, attr_id_key_enctype, &ti, sizeof(ti));
+
+ kcdb_cred_set_attr(cred, KCDB_ATTR_LOCATION, wcc_name,
+ KCDB_CBSIZE_AUTO);
+
+ if ( KRBv5Credentials.addresses && KRBv5Credentials.addresses[0] ) {
+ khm_int32 buffer[1024];
+ void * bufp;
+ khm_size cb;
+ khm_int32 rv;
+
+ bufp = (void *) buffer;
+ cb = sizeof(buffer);
+
+ rv = serialize_krb5_addresses(KRBv5Credentials.addresses,
+ bufp,
+ &cb);
+ if (rv == KHM_ERROR_TOO_LONG) {
+ bufp = PMALLOC(cb);
+ rv = serialize_krb5_addresses(KRBv5Credentials.addresses,
+ bufp,
+ &cb);
+ }
+
+ if (KHM_SUCCEEDED(rv)) {
+ kcdb_cred_set_attr(cred, attr_id_addr_list,
+ bufp, cb);
+ }
+
+ if (bufp != (void *) buffer)
+ PFREE(bufp);
+ }
+
+ if(cred_flags & KCDB_CRED_FLAG_INITIAL) {
+ FILETIME ft_issue_new;
+ FILETIME ft_expire_old;
+ FILETIME ft_expire_new;
+ ident_data * d;
+
+ /* an initial ticket! Add it to the list of identities we
+ have seen so far with initial tickets. */
+ d = tc_add_ident_to_list(idlist, ident);
+#ifdef DEBUG
+ assert(d);
+ assert(d->count > 0);
+#endif
+
+ tt = KRBv5Credentials.times.endtime;
+ TimetToFileTime(tt, &ft_expire_new);
+
+ tt = KRBv5Credentials.times.starttime;
+ TimetToFileTime(tt, &ft_issue_new);
+
+ /* so now, we have to set the properties of the identity
+ based on the properties of this credential under the
+ following circumstances:
+
+ - If this is the first time we are hitting this
+ identity.
+
+ - If this is not the MSLSA: cache and the expiry time
+ for this credential is longer than the time already
+ found for this identity.
+ */
+
+ ft_expire_old = d->ft_expire;
+
+ if(d->count == 1
+ || (CompareFileTime(&ft_expire_new, &ft_expire_old) > 0 &&
+ wcscmp(wcc_name, L"MSLSA:") != 0)) {
+
+ _reportf(L"Setting properties for identity (count=%d)", d->count);
+
+ StringCbCopy(d->ccname, sizeof(d->ccname),
+ wcc_name);
+ d->ft_expire = ft_expire_new;
+ d->ft_issue = ft_issue_new;
+
+ if (KRBv5Credentials.times.renew_till > 0) {
+ tt = KRBv5Credentials.times.renew_till;
+ TimetToFileTime(tt, &ft);
+ d->ft_renewexpire = ft;
+ } else {
+ ZeroMemory(&d->ft_renewexpire, sizeof(d->ft_renewexpire));
+ }
+
+ d->krb5_flags = KRBv5Credentials.ticket_flags;
+ }
+ }
+
+ kcdb_credset_add_cred(krb5_credset, cred, -1);
+
+ (*pkrb5_free_cred_contents)(ctx, &KRBv5Credentials);
+
+ if(tident != ident)
+ kcdb_identity_release(tident);
+ }
+
+ if (PrincipalName != NULL)
+ (*pkrb5_free_unparsed_name)(ctx, PrincipalName);
+
+ if (ClientName != NULL)
+ (*pkrb5_free_unparsed_name)(ctx, ClientName);
+
+ if (sServerName != NULL)
+ (*pkrb5_free_unparsed_name)(ctx, sServerName);
+
+ if (cred)
+ kcdb_cred_release(cred);
+
+ if ((code == KRB5_CC_END) || (code == KRB5_CC_NOTFOUND))
+ {
+ if ((code = pkrb5_cc_end_seq_get(ctx, cache, &KRBv5Cursor)))
+ {
+ goto _exit;
+ }
+
+ flags = KRB5_TC_OPENCLOSE;
+#ifdef KRB5_TC_NOTICKET
+ flags |= KRB5_TC_NOTICKET;
+#endif
+ if ((code = pkrb5_cc_set_flags(ctx, cache, flags)))
+ {
+ goto _exit;
+ }
+ }
+ else
+ {
+ goto _exit;
+ }
+
+_exit:
+
+ return code;
+}
+
+long
+khm_krb5_list_tickets(krb5_context *krbv5Context)
+{
+ krb5_context ctx = NULL;
+ krb5_ccache cache = NULL;
+ krb5_error_code code = 0;
+ apiCB * cc_ctx = NULL;
+ struct _infoNC ** pNCi = NULL;
+ int i;
+ khm_int32 t;
+ wchar_t * ms = NULL;
+ khm_size cb;
+ identlist idl;
+
+ kcdb_credset_flush(krb5_credset);
+ tc_prep_idlist(&idl);
+
+ if((*krbv5Context == 0) && (code = (*pkrb5_init_context)(krbv5Context))) {
+ goto _exit;
+ }
+
+ ctx = (*krbv5Context);
+
+ if (!pcc_initialize ||
+ !pcc_get_NC_info ||
+ !pcc_free_NC_info ||
+ !pcc_shutdown)
+ goto _skip_cc_iter;
+
+ code = pcc_initialize(&cc_ctx, CC_API_VER_2, NULL, NULL);
+ if (code)
+ goto _exit;
+
+ code = pcc_get_NC_info(cc_ctx, &pNCi);
+ if (code)
+ goto _exit;
+
+ for(i=0; pNCi[i]; i++) {
+ char ccname[KRB5_MAXCCH_CCNAME];
+
+ if (pNCi[i]->vers != CC_CRED_V5)
+ continue;
+
+ if (FAILED(StringCchPrintfA(ccname, sizeof(ccname), "API:%s",
+ pNCi[i]->name)))
+ continue;
+
+ code = (*pkrb5_cc_resolve)(ctx, ccname, &cache);
+
+ if (code)
+ continue;
+
+ code = get_tickets_from_cache(ctx, cache, &idl);
+
+ if(ctx != NULL && cache != NULL)
+ (*pkrb5_cc_close)(ctx, cache);
+
+ cache = 0;
+ }
+
+ _skip_cc_iter:
+
+ if (khc_read_multi_string(csp_params, L"FileCCList", NULL, &cb)
+ == KHM_ERROR_TOO_LONG &&
+ cb > sizeof(wchar_t) * 2) {
+ wchar_t * t;
+ char ccname[MAX_PATH + 6];
+
+ ms = PMALLOC(cb);
+#ifdef DEBUG
+ assert(ms);
+#endif
+ khc_read_multi_string(csp_params, L"FileCCList", ms, &cb);
+
+ for(t = ms; t && *t; t = multi_string_next(t)) {
+ StringCchPrintfA(ccname, ARRAYLENGTH(ccname),
+ "FILE:%S", t);
+
+ code = (*pkrb5_cc_resolve)(ctx, ccname, &cache);
+
+ if (code)
+ continue;
+
+ code = get_tickets_from_cache(ctx, cache, &idl);
+
+ if (ctx != NULL && cache != NULL)
+ (*pkrb5_cc_close)(ctx, cache);
+ cache = 0;
+ }
+
+ PFREE(ms);
+ }
+
+ if (KHM_SUCCEEDED(khc_read_int32(csp_params, L"MsLsaList", &t)) && t) {
+ code = (*pkrb5_cc_resolve)(ctx, "MSLSA:", &cache);
+
+ if (code == 0 && cache) {
+ code = get_tickets_from_cache(ctx, cache, &idl);
+ }
+
+ if (ctx != NULL && cache != NULL)
+ (*pkrb5_cc_close)(ctx, cache);
+ cache = 0;
+ }
+
+_exit:
+ if (pNCi)
+ (*pcc_free_NC_info)(cc_ctx, &pNCi);
+ if (cc_ctx)
+ (*pcc_shutdown)(&cc_ctx);
+
+ kcdb_credset_collect(NULL, krb5_credset, NULL, credtype_id_krb5, NULL);
+ tc_set_ident_data(&idl);
+ tc_free_idlist(&idl);
+
+ return(code);
+}
+
+int
+khm_krb5_renew_cred(khm_handle cred)
+{
+ khm_handle identity = NULL;
+ krb5_error_code code = 0;
+ krb5_context ctx = NULL;
+ krb5_ccache cc = NULL;
+ krb5_principal me = NULL, server = NULL;
+ krb5_creds in_creds, cc_creds;
+ krb5_creds * out_creds = NULL;
+
+ wchar_t wname[512];
+ khm_size cbname;
+ char name[512];
+ khm_boolean brenewIdentity = FALSE;
+ khm_boolean istgt = FALSE;
+
+ khm_int32 flags;
+
+ cbname = sizeof(wname);
+ kcdb_cred_get_name(cred, wname, &cbname);
+ _reportf(L"Krb5 renew cred for %s", wname);
+
+ kcdb_cred_get_flags(cred, &flags);
+
+ if (!(flags & KCDB_CRED_FLAG_INITIAL)) {
+ _reportf(L"Krb5 skipping renewal because this is not an initial credential");
+ return 0;
+ }
+
+ memset(&in_creds, 0, sizeof(in_creds));
+ memset(&cc_creds, 0, sizeof(cc_creds));
+
+ if (cred == NULL) {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ goto cleanup;
+ }
+
+ if (KHM_FAILED(kcdb_cred_get_identity(cred, &identity))) {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ goto cleanup;
+ }
+
+ code = khm_krb5_initialize(identity, &ctx, &cc);
+ if (code)
+ goto cleanup;
+
+ code = pkrb5_cc_get_principal(ctx, cc, &me);
+ if (code)
+ goto cleanup;
+
+ cbname = sizeof(wname);
+ if (KHM_FAILED(kcdb_cred_get_name(cred, wname, &cbname)))
+ goto cleanup;
+
+ UnicodeStrToAnsi(name, sizeof(name), wname);
+
+ code = pkrb5_parse_name(ctx, name, &server);
+ if (code)
+ goto cleanup;
+
+ in_creds.client = me;
+ in_creds.server = server;
+
+#ifdef KRB5_TC_NOTICKET
+ pkrb5_cc_set_flags(ctx, cc, 0);
+#endif
+
+ if (strlen("krbtgt") != krb5_princ_name(ctx, server)->length ||
+ strncmp("krbtgt", krb5_princ_name(ctx, server)->data, krb5_princ_name(ctx, server)->length))
+ {
+ code = pkrb5_get_renewed_creds(ctx, &cc_creds, me, cc, name);
+ if (code) {
+ code = pkrb5_cc_retrieve_cred(ctx, cc, 0, &in_creds, &cc_creds);
+ if (code == 0) {
+ code = pkrb5_cc_remove_cred(ctx, cc, 0, &cc_creds);
+ if (code) {
+ brenewIdentity = TRUE;
+ goto cleanup;
+ }
+ }
+ }
+
+ code = pkrb5_get_credentials(ctx, 0, cc, &in_creds, &out_creds);
+ } else {
+ istgt = TRUE;
+ code = pkrb5_get_renewed_creds(ctx, &cc_creds, me, cc, NULL);
+ }
+
+#ifdef KRB5_TC_NOTICKET
+ pkrb5_cc_set_flags(ctx, cc, KRB5_TC_NOTICKET);
+#endif
+ if (code) {
+ if ( code != KRB5KDC_ERR_ETYPE_NOSUPP ||
+ code != KRB5_KDC_UNREACH)
+ khm_krb5_error(code, "krb5_get_renewed_creds()", 0, &ctx, &cc);
+ goto cleanup;
+ }
+
+ if (istgt) {
+ code = pkrb5_cc_initialize(ctx, cc, me);
+ if (code) goto cleanup;
+
+ }
+
+ code = pkrb5_cc_store_cred(ctx, cc, istgt ? &cc_creds : out_creds);
+ if (code) goto cleanup;
+
+
+ cleanup:
+
+ if (in_creds.client == me)
+ in_creds.client = NULL;
+ if (in_creds.server == server)
+ in_creds.server = NULL;
+
+ if (me)
+ pkrb5_free_principal(ctx, me);
+
+ if (server)
+ pkrb5_free_principal(ctx, server);
+
+ pkrb5_free_cred_contents(ctx, &in_creds);
+ pkrb5_free_cred_contents(ctx, &cc_creds);
+
+ if (out_creds)
+ pkrb5_free_creds(ctx, out_creds);
+
+ if (cc && ctx)
+ pkrb5_cc_close(ctx, cc);
+
+ if (ctx)
+ pkrb5_free_context(ctx);
+
+ if (identity) {
+ if (brenewIdentity)
+ code = khm_krb5_renew_ident(identity);
+ kcdb_identity_release(identity);
+ }
+
+ return code;
+}
+
+int
+khm_krb5_renew_ident(khm_handle identity)
+{
+ krb5_error_code code = 0;
+ krb5_context ctx = NULL;
+ krb5_ccache cc = NULL;
+ krb5_principal me = NULL;
+ krb5_principal server = NULL;
+ krb5_creds my_creds;
+ krb5_data *realm = NULL;
+ wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
+ khm_size cb;
+ khm_int32 k5_flags;
+
+ memset(&my_creds, 0, sizeof(krb5_creds));
+
+ if ( !pkrb5_init_context )
+ goto cleanup;
+
+ cb = sizeof(idname);
+ kcdb_identity_get_name(identity, idname, &cb);
+
+ if (khm_krb5_get_identity_flags(identity) & K5IDFLAG_IMPORTED) {
+#ifndef NO_REIMPORT_MSLSA_CREDS
+ /* we are trying to renew the identity that was imported from
+ MSLSA: */
+ BOOL imported;
+ BOOL retry_import = FALSE;
+ char cidname[KCDB_IDENT_MAXCCH_NAME];
+ khm_handle imported_id = NULL;
+ khm_size cb;
+ FILETIME ft_expire;
+ FILETIME ft_now;
+ FILETIME ft_threshold;
+ krb5_principal princ = NULL;
+
+ UnicodeStrToAnsi(cidname, sizeof(cidname), idname);
+
+ imported = khm_krb5_ms2mit(cidname, FALSE, TRUE, &imported_id);
+
+ if (imported == 0)
+ goto import_failed;
+
+ /* if the imported identity has already expired or will soon,
+ we clear the cache and try again. */
+ khm_krb5_list_tickets(&ctx);
+
+ cb = sizeof(ft_expire);
+ if (KHM_FAILED(kcdb_identity_get_attr(imported_id, KCDB_ATTR_EXPIRE,
+ NULL, &ft_expire, &cb)))
+ goto import_failed;
+
+ GetSystemTimeAsFileTime(&ft_now);
+ TimetToFileTimeInterval(5 * 60, &ft_threshold);
+
+ ft_now = FtAdd(&ft_now, &ft_threshold);
+
+ if (CompareFileTime(&ft_expire, &ft_now) < 0) {
+ /* the ticket lifetime is not long enough */
+
+ code = 0;
+
+ if (ctx == NULL)
+ code = pkrb5_init_context(&ctx);
+ if (code)
+ goto import_failed;
+
+ code = pkrb5_cc_resolve(ctx, "MSLSA:", &cc);
+ if (code)
+ goto import_failed;
+
+ code = pkrb5_cc_get_principal(ctx, cc, &princ);
+ if (code)
+ goto import_failed;
+
+ pkrb5_cc_initialize(ctx, cc, princ);
+
+ retry_import = TRUE;
+ }
+
+ import_failed:
+
+ if (imported_id) {
+ kcdb_identity_release(imported_id);
+ imported_id = NULL;
+ }
+
+ if (ctx) {
+ if (cc) {
+ pkrb5_cc_close(ctx, cc);
+ cc = NULL;
+ }
+
+ if (princ) {
+ pkrb5_free_principal(ctx, princ);
+ princ = NULL;
+ }
+
+ /* leave ctx so we can use it later */
+ }
+
+ if (retry_import)
+ imported = khm_krb5_ms2mit(cidname, FALSE, TRUE, NULL);
+
+ if (imported)
+ goto cleanup;
+
+ /* if the import failed, then we try to renew the identity via
+ the usual procedure. */
+
+#else
+ /* if we are suppressing further imports from MSLSA, we just
+ skip renewing this identity. */
+ goto cleanup;
+#endif
+ }
+
+ cb = sizeof(k5_flags);
+ if (KHM_SUCCEEDED(kcdb_identity_get_attr(identity,
+ attr_id_krb5_flags,
+ NULL,
+ &k5_flags,
+ &cb)) &&
+ !(k5_flags & TKT_FLG_RENEWABLE)) {
+
+ code = KRB5KDC_ERR_BADOPTION;
+ goto cleanup;
+ }
+
+ {
+ FILETIME ft_now;
+ FILETIME ft_exp;
+
+ cb = sizeof(ft_exp);
+ GetSystemTimeAsFileTime(&ft_now);
+ if (KHM_SUCCEEDED(kcdb_identity_get_attr(identity,
+ KCDB_ATTR_EXPIRE,
+ NULL,
+ &ft_exp,
+ &cb)) &&
+ CompareFileTime(&ft_exp, &ft_now) < 0) {
+
+ code = KRB5KRB_AP_ERR_TKT_EXPIRED;
+ goto cleanup;
+
+ }
+ }
+
+ code = khm_krb5_initialize(identity, &ctx, &cc);
+ if (code)
+ goto cleanup;
+
+ code = pkrb5_cc_get_principal(ctx, cc, &me);
+ if (code)
+ goto cleanup;
+
+ realm = krb5_princ_realm(ctx, me);
+
+ code = pkrb5_build_principal_ext(ctx, &server,
+ realm->length,realm->data,
+ KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME,
+ realm->length,realm->data,
+ 0);
+
+ if (code)
+ goto cleanup;
+
+ my_creds.client = me;
+ my_creds.server = server;
+
+#ifdef KRB5_TC_NOTICKET
+ pkrb5_cc_set_flags(ctx, cc, 0);
+#endif
+ code = pkrb5_get_renewed_creds(ctx, &my_creds, me, cc, NULL);
+#ifdef KRB5_TC_NOTICKET
+ pkrb5_cc_set_flags(ctx, cc, KRB5_TC_NOTICKET);
+#endif
+ if (code) {
+ if ( code != KRB5KDC_ERR_ETYPE_NOSUPP ||
+ code != KRB5_KDC_UNREACH)
+ khm_krb5_error(code, "krb5_get_renewed_creds()", 0, &ctx, &cc);
+ goto cleanup;
+ }
+
+ code = pkrb5_cc_initialize(ctx, cc, me);
+ if (code) goto cleanup;
+
+ code = pkrb5_cc_store_cred(ctx, cc, &my_creds);
+ if (code) goto cleanup;
+
+cleanup:
+ if (my_creds.client == me)
+ my_creds.client = NULL;
+ if (my_creds.server == server)
+ my_creds.server = NULL;
+
+ if (ctx) {
+ pkrb5_free_cred_contents(ctx, &my_creds);
+
+ if (me)
+ pkrb5_free_principal(ctx, me);
+ if (server)
+ pkrb5_free_principal(ctx, server);
+ if (cc)
+ pkrb5_cc_close(ctx, cc);
+ pkrb5_free_context(ctx);
+ }
+
+ return(code);
+}
+
+int
+khm_krb5_kinit(krb5_context alt_ctx,
+ char * principal_name,
+ char * password,
+ char * ccache,
+ krb5_deltat lifetime,
+ DWORD forwardable,
+ DWORD proxiable,
+ krb5_deltat renew_life,
+ DWORD addressless,
+ DWORD publicIP,
+ krb5_prompter_fct prompter,
+ void * p_data)
+{
+ krb5_error_code code = 0;
+ krb5_context ctx = NULL;
+ krb5_ccache cc = NULL;
+ krb5_principal me = NULL;
+ char* name = NULL;
+ krb5_creds my_creds;
+ krb5_get_init_creds_opt options;
+ krb5_address ** addrs = NULL;
+ int i = 0, addr_count = 0;
+
+ if (!pkrb5_init_context)
+ return 0;
+
+ _reportf(L"In khm_krb5_kinit");
+
+ pkrb5_get_init_creds_opt_init(&options);
+ pkrb5_get_init_creds_opt_set_change_password_prompt(&options, 0);
+
+ memset(&my_creds, 0, sizeof(my_creds));
+
+ if (alt_ctx) {
+ ctx = alt_ctx;
+ } else {
+ code = pkrb5_init_context(&ctx);
+ if (code)
+ goto cleanup;
+ }
+
+ if (ccache) {
+ _reportf(L"Using supplied ccache name %S", ccache);
+ code = pkrb5_cc_resolve(ctx, ccache, &cc);
+ } else {
+ khm_handle identity = NULL;
+ khm_handle csp_ident = NULL;
+ khm_handle csp_k5 = NULL;
+ wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
+ wchar_t wccname[MAX_PATH];
+ char ccname[MAX_PATH];
+ char * pccname = principal_name;
+ khm_size cb;
+
+ idname[0] = L'\0';
+ AnsiStrToUnicode(idname, sizeof(idname), principal_name);
+
+ cb = sizeof(wccname);
+
+ if (KHM_SUCCEEDED(kcdb_identity_create(idname, 0, &identity)) &&
+
+ KHM_SUCCEEDED(kcdb_identity_get_config(identity, 0, &csp_ident)) &&
+
+ KHM_SUCCEEDED(khc_open_space(csp_ident, CSNAME_KRB5CRED, 0,
+ &csp_k5)) &&
+
+ KHM_SUCCEEDED(khc_read_string(csp_k5, L"DefaultCCName",
+ wccname, &cb)) &&
+
+ cb > sizeof(wchar_t)) {
+
+ _reportf(L"Using DefaultCCName [%s] from identity", wccname);
+
+ UnicodeStrToAnsi(ccname, sizeof(ccname), wccname);
+ pccname = ccname;
+ }
+
+ if (csp_k5)
+ khc_close_space(csp_k5);
+ if (csp_ident)
+ khc_close_space(csp_ident);
+ if (identity)
+ kcdb_identity_release(identity);
+
+ code = pkrb5_cc_resolve(ctx, pccname, &cc);
+ }
+
+ _reportf(L"krb5_cc_resolve returns code %d", code);
+
+ if (code) goto cleanup;
+
+ code = pkrb5_parse_name(ctx, principal_name, &me);
+ if (code) goto cleanup;
+
+ code = pkrb5_unparse_name(ctx, me, &name);
+ if (code) goto cleanup;
+
+ if (lifetime == 0) {
+ khc_read_int32(csp_params, L"DefaultLifetime", &lifetime);
+ }
+
+ if (lifetime)
+ pkrb5_get_init_creds_opt_set_tkt_life(&options, lifetime);
+
+ pkrb5_get_init_creds_opt_set_forwardable(&options,
+ forwardable ? 1 : 0);
+ pkrb5_get_init_creds_opt_set_proxiable(&options,
+ proxiable ? 1 : 0);
+ pkrb5_get_init_creds_opt_set_renew_life(&options,
+ renew_life);
+
+ if (addressless)
+ pkrb5_get_init_creds_opt_set_address_list(&options,NULL);
+ else {
+ krb5_address ** local_addrs=NULL;
+ DWORD netIPAddr;
+
+ pkrb5_os_localaddr(ctx, &local_addrs);
+ i = 0;
+ while ( local_addrs[i++] );
+ addr_count = i + 1;
+
+ addrs = (krb5_address **) PMALLOC((addr_count+1) * sizeof(krb5_address *));
+ if ( !addrs ) {
+ pkrb5_free_addresses(ctx, local_addrs);
+ assert(0);
+ }
+ memset(addrs, 0, sizeof(krb5_address *) * (addr_count+1));
+ i = 0;
+ while ( local_addrs[i] ) {
+ addrs[i] = (krb5_address *)PMALLOC(sizeof(krb5_address));
+ if (addrs[i] == NULL) {
+ pkrb5_free_addresses(ctx, local_addrs);
+ assert(0);
+ }
+
+ addrs[i]->magic = local_addrs[i]->magic;
+ addrs[i]->addrtype = local_addrs[i]->addrtype;
+ addrs[i]->length = local_addrs[i]->length;
+ addrs[i]->contents = (unsigned char *)PMALLOC(addrs[i]->length);
+ if (!addrs[i]->contents) {
+ pkrb5_free_addresses(ctx, local_addrs);
+ assert(0);
+ }
+
+ memcpy(addrs[i]->contents,local_addrs[i]->contents,
+ local_addrs[i]->length); /* safe */
+ i++;
+ }
+ pkrb5_free_addresses(ctx, local_addrs);
+
+ if (publicIP) {
+ // we are going to add the public IP address specified by the user
+ // to the list provided by the operating system
+ addrs[i] = (krb5_address *)PMALLOC(sizeof(krb5_address));
+ if (addrs[i] == NULL)
+ assert(0);
+
+ addrs[i]->magic = KV5M_ADDRESS;
+ addrs[i]->addrtype = AF_INET;
+ addrs[i]->length = 4;
+ addrs[i]->contents = (unsigned char *)PMALLOC(addrs[i]->length);
+ if (!addrs[i]->contents)
+ assert(0);
+
+ netIPAddr = htonl(publicIP);
+ memcpy(addrs[i]->contents,&netIPAddr,4);
+ }
+
+ pkrb5_get_init_creds_opt_set_address_list(&options,addrs);
+ }
+
+ code =
+ pkrb5_get_init_creds_password(ctx,
+ &my_creds,
+ me,
+ password, // password
+ prompter, // prompter
+ p_data, // prompter data
+ 0, // start time
+ 0, // service name
+ &options);
+ _reportf(L"krb5_get_init_creds_password returns code %d", code);
+
+ if (code) goto cleanup;
+
+ code = pkrb5_cc_initialize(ctx, cc, me);
+ _reportf(L"krb5_cc_initialize returns code %d", code);
+ if (code) goto cleanup;
+
+ code = pkrb5_cc_store_cred(ctx, cc, &my_creds);
+ _reportf(L"krb5_cc_store_cred returns code %d", code);
+ if (code) goto cleanup;
+
+cleanup:
+ if ( addrs ) {
+ for ( i=0;i<addr_count;i++ ) {
+ if ( addrs[i] ) {
+ if ( addrs[i]->contents )
+ PFREE(addrs[i]->contents);
+ PFREE(addrs[i]);
+ }
+ }
+ }
+ if (my_creds.client == me)
+ my_creds.client = 0;
+ pkrb5_free_cred_contents(ctx, &my_creds);
+ if (name)
+ pkrb5_free_unparsed_name(ctx, name);
+ if (me)
+ pkrb5_free_principal(ctx, me);
+ if (cc)
+ pkrb5_cc_close(ctx, cc);
+ if (ctx && (ctx != alt_ctx))
+ pkrb5_free_context(ctx);
+ return(code);
+}
+
+long
+khm_krb5_copy_ccache_by_name(krb5_context in_ctx,
+ wchar_t * wscc_dest,
+ wchar_t * wscc_src) {
+ krb5_context ctx = NULL;
+ krb5_error_code code = 0;
+ khm_boolean free_ctx;
+ krb5_ccache cc_src = NULL;
+ krb5_ccache cc_dest = NULL;
+ krb5_principal princ_src = NULL;
+ char scc_dest[KRB5_MAXCCH_CCNAME];
+ char scc_src[KRB5_MAXCCH_CCNAME];
+ int t;
+
+ t = UnicodeStrToAnsi(scc_dest, sizeof(scc_dest), wscc_dest);
+ if (t == 0)
+ return KHM_ERROR_TOO_LONG;
+ t = UnicodeStrToAnsi(scc_src, sizeof(scc_src), wscc_src);
+ if (t == 0)
+ return KHM_ERROR_TOO_LONG;
+
+ if (in_ctx) {
+ ctx = in_ctx;
+ free_ctx = FALSE;
+ } else {
+ code = pkrb5_init_context(&ctx);
+ if (code) {
+ if (ctx)
+ pkrb5_free_context(ctx);
+ return code;
+ }
+ free_ctx = TRUE;
+ }
+
+ code = pkrb5_cc_resolve(ctx, scc_dest, &cc_dest);
+ if (code)
+ goto _cleanup;
+
+ code = pkrb5_cc_resolve(ctx, scc_src, &cc_src);
+ if (code)
+ goto _cleanup;
+
+ code = pkrb5_cc_get_principal(ctx, cc_src, &princ_src);
+ if (code)
+ goto _cleanup;
+
+ code = pkrb5_cc_initialize(ctx, cc_dest, princ_src);
+ if (code)
+ goto _cleanup;
+
+ code = pkrb5_cc_copy_creds(ctx, cc_src, cc_dest);
+
+ _cleanup:
+ if (princ_src)
+ pkrb5_free_principal(ctx, princ_src);
+
+ if (cc_dest)
+ pkrb5_cc_close(ctx, cc_dest);
+
+ if (cc_src)
+ pkrb5_cc_close(ctx, cc_src);
+
+ if (free_ctx && ctx)
+ pkrb5_free_context(ctx);
+
+ return code;
+}
+
+long
+khm_krb5_canon_cc_name(wchar_t * wcc_name,
+ size_t cb_cc_name) {
+ size_t cb_len;
+ wchar_t * colon;
+
+ if (FAILED(StringCbLength(wcc_name,
+ cb_cc_name,
+ &cb_len))) {
+#ifdef DEBUG
+ assert(FALSE);
+#else
+ return KHM_ERROR_TOO_LONG;
+#endif
+ }
+
+ cb_len += sizeof(wchar_t);
+
+ colon = wcschr(wcc_name, L':');
+
+ if (colon) {
+ /* if the colon is just 1 character away from the beginning,
+ it's a FILE: cc */
+ if (colon - wcc_name == 1) {
+ if (cb_len + 5 * sizeof(wchar_t) > cb_cc_name)
+ return KHM_ERROR_TOO_LONG;
+
+ memmove(&wcc_name[5], &wcc_name[0], cb_len);
+ memmove(&wcc_name[0], L"FILE:", sizeof(wchar_t) * 5);
+ }
+
+ return 0;
+ }
+
+ if (cb_len + 4 * sizeof(wchar_t) > cb_cc_name)
+ return KHM_ERROR_TOO_LONG;
+
+ memmove(&wcc_name[4], &wcc_name[0], cb_len);
+ memmove(&wcc_name[0], L"API:", sizeof(wchar_t) * 4);
+
+ return 0;
+}
+
+int
+khm_krb5_cc_name_cmp(const wchar_t * cc_name_1,
+ const wchar_t * cc_name_2) {
+ if (!wcsncmp(cc_name_1, L"API:", 4))
+ cc_name_1 += 4;
+
+ if (!wcsncmp(cc_name_2, L"API:", 4))
+ cc_name_2 += 4;
+
+ return wcscmp(cc_name_1, cc_name_2);
+}
+
+static khm_int32 KHMAPI
+khmint_location_comp_func(khm_handle cred1,
+ khm_handle cred2,
+ void * rock) {
+ return kcdb_creds_comp_attr(cred1, cred2, KCDB_ATTR_LOCATION);
+}
+
+struct khmint_location_check {
+ khm_handle credset;
+ khm_handle cred;
+ wchar_t * ccname;
+ khm_boolean success;
+};
+
+static khm_int32 KHMAPI
+khmint_find_matching_cred_func(khm_handle cred,
+ void * rock) {
+ struct khmint_location_check * lc;
+
+ lc = (struct khmint_location_check *) rock;
+
+ if (!kcdb_creds_is_equal(cred, lc->cred))
+ return KHM_ERROR_SUCCESS;
+ if (kcdb_creds_comp_attr(cred, lc->cred, KCDB_ATTR_LOCATION))
+ return KHM_ERROR_SUCCESS;
+
+ /* found it */
+ lc->success = TRUE;
+
+ /* break the search */
+ return !KHM_ERROR_SUCCESS;
+}
+
+static khm_int32 KHMAPI
+khmint_location_check_func(khm_handle cred,
+ void * rock) {
+ khm_int32 t;
+ khm_size cb;
+ wchar_t ccname[KRB5_MAXCCH_CCNAME];
+ struct khmint_location_check * lc;
+
+ lc = (struct khmint_location_check *) rock;
+
+ if (KHM_FAILED(kcdb_cred_get_type(cred, &t)))
+ return KHM_ERROR_SUCCESS;
+
+ if (t != credtype_id_krb5)
+ return KHM_ERROR_SUCCESS;
+
+ cb = sizeof(ccname);
+ if (KHM_FAILED(kcdb_cred_get_attr(cred,
+ KCDB_ATTR_LOCATION,
+ NULL,
+ ccname,
+ &cb)))
+ return KHM_ERROR_SUCCESS;
+
+ if(wcscmp(ccname, lc->ccname))
+ return KHM_ERROR_SUCCESS;
+
+ lc->cred = cred;
+
+ lc->success = FALSE;
+
+ kcdb_credset_apply(lc->credset,
+ khmint_find_matching_cred_func,
+ (void *) lc);
+
+ if (!lc->success)
+ return KHM_ERROR_NOT_FOUND;
+ else
+ return KHM_ERROR_SUCCESS;
+}
+
+static khm_int32 KHMAPI
+khmint_delete_location_func(khm_handle cred,
+ void * rock) {
+ wchar_t cc_cred[KRB5_MAXCCH_CCNAME];
+ struct khmint_location_check * lc;
+ khm_size cb;
+
+ lc = (struct khmint_location_check *) rock;
+
+ cb = sizeof(cc_cred);
+
+ if (KHM_FAILED(kcdb_cred_get_attr(cred,
+ KCDB_ATTR_LOCATION,
+ NULL,
+ cc_cred,
+ &cb)))
+ return KHM_ERROR_SUCCESS;
+
+ if (wcscmp(cc_cred, lc->ccname))
+ return KHM_ERROR_SUCCESS;
+
+ kcdb_credset_del_cred_ref(lc->credset,
+ cred);
+
+ return KHM_ERROR_SUCCESS;
+}
+
+int
+khm_krb5_destroy_by_credset(khm_handle p_cs)
+{
+ khm_handle d_cs = NULL;
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+ khm_size s, cb;
+ krb5_context ctx = NULL;
+ krb5_error_code code = 0;
+ int i;
+ wchar_t ccname[KRB5_MAXCCH_CCNAME];
+ struct khmint_location_check lc;
+
+ rv = kcdb_credset_create(&d_cs);
+
+ assert(KHM_SUCCEEDED(rv) && d_cs != NULL);
+
+ kcdb_credset_extract(d_cs, p_cs, NULL, credtype_id_krb5);
+
+ kcdb_credset_get_size(d_cs, &s);
+
+ if (s == 0) {
+ _reportf(L"No tickets to delete");
+
+ kcdb_credset_delete(d_cs);
+ return 0;
+ }
+
+ code = pkrb5_init_context(&ctx);
+ if (code != 0) {
+ rv = code;
+ goto _cleanup;
+ }
+
+ /* we should synchronize the credential lists before we attempt to
+ make any assumptions on the state of the root credset */
+ khm_krb5_list_tickets(&ctx);
+
+ /* so, we need to make a decision about whether to destroy entire
+ ccaches or just individual credentials. Therefore we first
+ sort them by ccache. */
+ kcdb_credset_sort(d_cs,
+ khmint_location_comp_func,
+ NULL);
+
+ /* now, for each ccache we encounter, we check if we have all the
+ credentials from that ccache in the to-be-deleted list. */
+ for (i=0; i < (int) s; i++) {
+ khm_handle cred;
+
+ if (KHM_FAILED(kcdb_credset_get_cred(d_cs,
+ i,
+ &cred)))
+ continue;
+
+ cb = sizeof(ccname);
+ rv = kcdb_cred_get_attr(cred,
+ KCDB_ATTR_LOCATION,
+ NULL,
+ ccname,
+ &cb);
+
+#ifdef DEBUG
+ assert(KHM_SUCCEEDED(rv));
+#endif
+ kcdb_cred_release(cred);
+
+ lc.credset = d_cs;
+ lc.cred = NULL;
+ lc.ccname = ccname;
+ lc.success = FALSE;
+
+ kcdb_credset_apply(NULL,
+ khmint_location_check_func,
+ (void *) &lc);
+
+ if (lc.success) {
+ /* ok the destroy the ccache */
+ char a_ccname[KRB5_MAXCCH_CCNAME];
+ krb5_ccache cc = NULL;
+
+ _reportf(L"Destroying ccache [%s]", ccname);
+
+ UnicodeStrToAnsi(a_ccname,
+ sizeof(a_ccname),
+ ccname);
+
+ code = pkrb5_cc_resolve(ctx,
+ a_ccname,
+ &cc);
+ if (code)
+ goto _delete_this_set;
+
+ code = pkrb5_cc_destroy(ctx, cc);
+
+ if (code) {
+ _reportf(L"krb5_cc_destroy returns code %d", code);
+ }
+
+ _delete_this_set:
+
+ lc.credset = d_cs;
+ lc.ccname = ccname;
+
+ /* note that although we are deleting credentials off the
+ credential set, the size of the credential set does not
+ decrease since we are doing it from inside
+ kcdb_credset_apply(). The deleted creds will simply be
+ marked as deleted until kcdb_credset_purge() is
+ called. */
+
+ kcdb_credset_apply(d_cs,
+ khmint_delete_location_func,
+ (void *) &lc);
+ }
+ }
+
+ kcdb_credset_purge(d_cs);
+
+ /* the remainder need to be deleted one by one */
+
+ kcdb_credset_get_size(d_cs, &s);
+
+ for (i=0; i < (int) s; ) {
+ khm_handle cred;
+ char a_ccname[KRB5_MAXCCH_CCNAME];
+ char a_srvname[KCDB_CRED_MAXCCH_NAME];
+ wchar_t srvname[KCDB_CRED_MAXCCH_NAME];
+ krb5_ccache cc;
+ krb5_creds in_cred, out_cred;
+ krb5_principal princ;
+ khm_int32 etype;
+
+ if (KHM_FAILED(kcdb_credset_get_cred(d_cs,
+ i,
+ &cred))) {
+ i++;
+ continue;
+ }
+
+ cb = sizeof(ccname);
+ if (KHM_FAILED(kcdb_cred_get_attr(cred,
+ KCDB_ATTR_LOCATION,
+ NULL,
+ ccname,
+ &cb)))
+ goto _done_with_this_cred;
+
+ _reportf(L"Looking at ccache [%s]", ccname);
+
+ UnicodeStrToAnsi(a_ccname,
+ sizeof(a_ccname),
+ ccname);
+
+ code = pkrb5_cc_resolve(ctx,
+ a_ccname,
+ &cc);
+
+ if (code)
+ goto _skip_similar;
+
+ code = pkrb5_cc_get_principal(ctx, cc, &princ);
+
+ if (code) {
+ pkrb5_cc_close(ctx, cc);
+ goto _skip_similar;
+ }
+
+ _del_this_cred:
+
+ cb = sizeof(etype);
+
+ if (KHM_FAILED(kcdb_cred_get_attr(cred,
+ attr_id_key_enctype,
+ NULL,
+ &etype,
+ &cb)))
+ goto _do_next_cred;
+
+ cb = sizeof(srvname);
+ if (KHM_FAILED(kcdb_cred_get_name(cred,
+ srvname,
+ &cb)))
+ goto _do_next_cred;
+
+ _reportf(L"Attempting to delete ticket %s", srvname);
+
+ UnicodeStrToAnsi(a_srvname, sizeof(a_srvname), srvname);
+
+ ZeroMemory(&in_cred, sizeof(in_cred));
+
+ code = pkrb5_parse_name(ctx, a_srvname, &in_cred.server);
+ if (code)
+ goto _do_next_cred;
+ in_cred.client = princ;
+ in_cred.keyblock.enctype = etype;
+
+ code = pkrb5_cc_retrieve_cred(ctx,
+ cc,
+ KRB5_TC_MATCH_SRV_NAMEONLY |
+ KRB5_TC_SUPPORTED_KTYPES,
+ &in_cred,
+ &out_cred);
+ if (code)
+ goto _do_next_cred_0;
+
+ code = pkrb5_cc_remove_cred(ctx, cc,
+ KRB5_TC_MATCH_SRV_NAMEONLY |
+ KRB5_TC_SUPPORTED_KTYPES |
+ KRB5_TC_MATCH_AUTHDATA,
+ &out_cred);
+
+ pkrb5_free_cred_contents(ctx, &out_cred);
+ _do_next_cred_0:
+ pkrb5_free_principal(ctx, in_cred.server);
+ _do_next_cred:
+
+ /* check if the next cred is also of the same ccache */
+ kcdb_cred_release(cred);
+
+ for (i++; i < (int) s; i++) {
+ if (KHM_FAILED(kcdb_credset_get_cred(d_cs,
+ i,
+ &cred)))
+ continue;
+ }
+
+ if (i < (int) s) {
+ wchar_t newcc[KRB5_MAXCCH_CCNAME];
+
+ cb = sizeof(newcc);
+ if (KHM_FAILED(kcdb_cred_get_attr(cred,
+ KCDB_ATTR_LOCATION,
+ NULL,
+ newcc,
+ &cb)) ||
+ wcscmp(newcc, ccname)) {
+ i--; /* we have to look at this again */
+ goto _done_with_this_set;
+ }
+ goto _del_this_cred;
+ }
+
+
+ _done_with_this_set:
+ pkrb5_free_principal(ctx, princ);
+
+ pkrb5_cc_close(ctx, cc);
+
+ _done_with_this_cred:
+ kcdb_cred_release(cred);
+ i++;
+ continue;
+
+ _skip_similar:
+ kcdb_cred_release(cred);
+
+ for (++i; i < (int) s; i++) {
+ wchar_t newcc[KRB5_MAXCCH_CCNAME];
+
+ if (KHM_FAILED(kcdb_credset_get_cred(d_cs,
+ i,
+ &cred)))
+ continue;
+
+ cb = sizeof(newcc);
+ if (KHM_FAILED(kcdb_cred_get_attr(cred,
+ KCDB_ATTR_LOCATION,
+ NULL,
+ &newcc,
+ &cb))) {
+ kcdb_cred_release(cred);
+ continue;
+ }
+
+ if (wcscmp(newcc, ccname)) {
+ kcdb_cred_release(cred);
+ break;
+ }
+ }
+ }
+
+ _cleanup:
+
+ if (d_cs)
+ kcdb_credset_delete(&d_cs);
+
+ if (ctx != NULL)
+ pkrb5_free_context(ctx);
+
+ return rv;
+}
+
+int
+khm_krb5_destroy_identity(khm_handle identity)
+{
+ krb5_context ctx;
+ krb5_ccache cache;
+ krb5_error_code rc;
+
+ ctx = NULL;
+ cache = NULL;
+
+ if (rc = khm_krb5_initialize(identity, &ctx, &cache))
+ return(rc);
+
+ rc = pkrb5_cc_destroy(ctx, cache);
+
+ if (ctx != NULL)
+ pkrb5_free_context(ctx);
+
+ return(rc);
+}
+
+static BOOL
+GetSecurityLogonSessionData(PSECURITY_LOGON_SESSION_DATA * ppSessionData)
+{
+ NTSTATUS Status = 0;
+ HANDLE TokenHandle;
+ TOKEN_STATISTICS Stats;
+ DWORD ReqLen;
+ BOOL Success;
+
+ if (!ppSessionData)
+ return FALSE;
+ *ppSessionData = NULL;
+
+ Success = OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &TokenHandle );
+ if ( !Success )
+ return FALSE;
+
+ Success = GetTokenInformation( TokenHandle, TokenStatistics, &Stats, sizeof(TOKEN_STATISTICS), &ReqLen );
+ CloseHandle( TokenHandle );
+ if ( !Success )
+ return FALSE;
+
+ Status = pLsaGetLogonSessionData( &Stats.AuthenticationId, ppSessionData );
+ if ( FAILED(Status) || !ppSessionData )
+ return FALSE;
+
+ return TRUE;
+}
+
+// IsKerberosLogon() does not validate whether or not there are valid
+// tickets in the cache. It validates whether or not it is reasonable
+// to assume that if we attempted to retrieve valid tickets we could
+// do so. Microsoft does not automatically renew expired tickets.
+// Therefore, the cache could contain expired or invalid tickets.
+// Microsoft also caches the user's password and will use it to
+// retrieve new TGTs if the cache is empty and tickets are requested.
+
+static BOOL
+IsKerberosLogon(VOID)
+{
+ PSECURITY_LOGON_SESSION_DATA pSessionData = NULL;
+ BOOL Success = FALSE;
+
+ if ( GetSecurityLogonSessionData(&pSessionData) ) {
+ if ( pSessionData->AuthenticationPackage.Buffer ) {
+ WCHAR buffer[256];
+ WCHAR *usBuffer;
+ int usLength;
+
+ Success = FALSE;
+ usBuffer = (pSessionData->AuthenticationPackage).Buffer;
+ usLength = (pSessionData->AuthenticationPackage).Length;
+ if (usLength < 256)
+ {
+ lstrcpynW (buffer, usBuffer, usLength);
+ StringCbCatW (buffer, sizeof(buffer), L"");
+ if ( !lstrcmpW(L"Kerberos",buffer) )
+ Success = TRUE;
+ }
+ }
+ pLsaFreeReturnBuffer(pSessionData);
+ }
+ return Success;
+}
+
+
+BOOL
+khm_krb5_ms2mit(char * match_princ, BOOL match_realm, BOOL save_creds,
+ khm_handle * ret_ident)
+{
+#ifdef NO_KRB5
+ return(FALSE);
+#else /* NO_KRB5 */
+ krb5_context kcontext = 0;
+ krb5_error_code code = 0;
+ krb5_ccache ccache=0;
+ krb5_ccache mslsa_ccache=0;
+ krb5_creds creds;
+ krb5_cc_cursor cursor=0;
+ krb5_principal princ = 0;
+ khm_handle ident = NULL;
+ wchar_t wname[KCDB_IDENT_MAXCCH_NAME];
+ char cname[KCDB_IDENT_MAXCCH_NAME];
+ char *cache_name = NULL;
+ char *princ_name = NULL;
+ BOOL rc = FALSE;
+
+ kherr_reportf(L"Begin : khm_krb5_ms2mit. save_cred=%d\n", (int) save_creds);
+
+ if ( !pkrb5_init_context )
+ goto cleanup;
+
+ if (code = pkrb5_init_context(&kcontext))
+ goto cleanup;
+
+ kherr_reportf(L"Resolving MSLSA\n");
+
+ if (code = pkrb5_cc_resolve(kcontext, "MSLSA:", &mslsa_ccache))
+ goto cleanup;
+
+ if ( save_creds ) {
+ kherr_reportf(L"Getting principal\n");
+ if (code = pkrb5_cc_get_principal(kcontext, mslsa_ccache, &princ))
+ goto cleanup;
+
+ kherr_reportf(L"Unparsing name\n");
+ if (code = pkrb5_unparse_name(kcontext, princ, &princ_name))
+ goto cleanup;
+
+ AnsiStrToUnicode(wname, sizeof(wname), princ_name);
+
+ kherr_reportf(L"Unparsed name [%s]", wname);
+
+ /* see if we have to match a specific principal */
+ if (match_princ != NULL) {
+ if (strcmp(princ_name, match_princ)) {
+ kherr_reportf(L"Principal mismatch. Wanted [%S], found [%S]",
+ match_princ, princ_name);
+ goto cleanup;
+ }
+ } else if (match_realm) {
+ wchar_t * wdefrealm;
+ char defrealm[256];
+ krb5_data * princ_realm;
+
+ wdefrealm = khm_krb5_get_default_realm();
+ if (wdefrealm == NULL) {
+ kherr_reportf(L"Can't determine default realm");
+ goto cleanup;
+ }
+
+ princ_realm = krb5_princ_realm(kcontext, princ);
+ UnicodeStrToAnsi(defrealm, sizeof(defrealm), wdefrealm);
+
+ if (strncmp(defrealm, princ_realm->data, princ_realm->length)) {
+ kherr_reportf(L"Realm mismatch. Wanted [%S], found [%*S]",
+ defrealm, princ_realm->length, princ_realm->data);
+ PFREE(wdefrealm);
+ goto cleanup;
+ }
+
+ PFREE(wdefrealm);
+ }
+
+ if (KHM_SUCCEEDED(kcdb_identity_create(wname,
+ KCDB_IDENT_FLAG_CREATE,
+ &ident))) {
+ khm_handle idconfig = NULL;
+ khm_handle k5config = NULL;
+ khm_size cb;
+
+ wname[0] = L'\0';
+
+ kcdb_identity_get_config(ident, KHM_FLAG_CREATE, &idconfig);
+ if (idconfig == NULL)
+ goto _done_checking_config;
+
+ khc_open_space(idconfig, CSNAME_KRB5CRED, KHM_FLAG_CREATE, &k5config);
+ if (k5config == NULL)
+ goto _done_checking_config;
+
+ cb = sizeof(wname);
+ khc_read_string(k5config,
+ L"DefaultCCName",
+ wname, &cb);
+
+ _done_checking_config:
+
+ if (idconfig)
+ khc_close_space(idconfig);
+ if (k5config)
+ khc_close_space(k5config);
+
+ if (wname[0]) {
+ UnicodeStrToAnsi(cname, sizeof(cname), wname);
+ } else {
+ StringCbPrintfA(cname, sizeof(cname), "API:%s", princ_name);
+ }
+
+ cache_name = cname;
+
+ } else {
+ /* the identity could not be created. we just use the
+ name of the principal as the ccache name. */
+ StringCbPrintfA(cname, sizeof(cname), "API:%s", princ_name);
+ cache_name = cname;
+ }
+
+ kherr_reportf(L"Resolving target cache [%S]\n", cache_name);
+
+ if (code = pkrb5_cc_resolve(kcontext, cache_name, &ccache)) {
+ kherr_reportf(L"Cannot resolve cache [%S] with code=%d. Trying default.\n", cache_name, code);
+
+ if (code = pkrb5_cc_default(kcontext, &ccache)) {
+ kherr_reportf(L"Failed to resolve default ccache. Code=%d", code);
+ goto cleanup;
+ }
+ }
+
+ kherr_reportf(L"Initializing ccache\n");
+ if (code = pkrb5_cc_initialize(kcontext, ccache, princ))
+ goto cleanup;
+
+ kherr_reportf(L"Copying credentials\n");
+ if (code = pkrb5_cc_copy_creds(kcontext, mslsa_ccache, ccache))
+ goto cleanup;
+
+ /* and mark the identity as having been imported */
+ if (ident) {
+ khm_krb5_set_identity_flags(ident, K5IDFLAG_IMPORTED, K5IDFLAG_IMPORTED);
+
+ if (ret_ident) {
+ *ret_ident = ident;
+ kcdb_identity_hold(*ret_ident);
+ }
+ }
+
+ rc = TRUE;
+
+ } else {
+ /* Enumerate tickets from cache looking for an initial ticket */
+ if ((code = pkrb5_cc_start_seq_get(kcontext, mslsa_ccache, &cursor)))
+ goto cleanup;
+
+ while (!(code = pkrb5_cc_next_cred(kcontext, mslsa_ccache,
+ &cursor, &creds))) {
+ if ( creds.ticket_flags & TKT_FLG_INITIAL ) {
+ rc = TRUE;
+ pkrb5_free_cred_contents(kcontext, &creds);
+ break;
+ }
+ pkrb5_free_cred_contents(kcontext, &creds);
+ }
+ pkrb5_cc_end_seq_get(kcontext, mslsa_ccache, &cursor);
+ }
+
+cleanup:
+ kherr_reportf(L" Received code=%d", code);
+
+ if (princ_name)
+ pkrb5_free_unparsed_name(kcontext, princ_name);
+ if (princ)
+ pkrb5_free_principal(kcontext, princ);
+ if (ccache)
+ pkrb5_cc_close(kcontext, ccache);
+ if (mslsa_ccache)
+ pkrb5_cc_close(kcontext, mslsa_ccache);
+ if (kcontext)
+ pkrb5_free_context(kcontext);
+ if (ident)
+ kcdb_identity_release(ident);
+
+ return(rc);
+#endif /* NO_KRB5 */
+}
+
+#define KRB_FILE "KRB.CON"
+#define KRBREALM_FILE "KRBREALM.CON"
+#define KRB5_FILE "KRB5.INI"
+#define KRB5_TMP_FILE "KRB5.INI.TMP"
+
+BOOL
+khm_krb5_get_temp_profile_file(LPSTR confname, UINT szConfname)
+{
+ GetTempPathA(szConfname, confname);
+ confname[szConfname-1] = '\0';
+ StringCchCatA(confname, szConfname, KRB5_TMP_FILE);
+ confname[szConfname-1] = '\0';
+ return FALSE;
+}
+
+#ifdef NOT_QUITE_IMPLEMENTED_YET
+BOOL
+khm_krb5_set_profile_file(krb5_context ctx, LPSTR confname)
+{
+ char *conffiles[2];
+
+ if (confname == NULL ||
+ pkrb5_set_config_files == NULL ||
+ ctx == NULL)
+ return FALSE;
+
+ conffiles[0] = confname;
+ conffiles[1] = NULL;
+
+ if (pkrb5_set_config_files(ctx, conffiles))
+ return FALSE;
+ else
+ return TRUE;
+}
+#endif
+
+BOOL
+khm_krb5_get_profile_file(LPSTR confname, UINT szConfname)
+{
+ char **configFile = NULL;
+ if (pkrb5_get_default_config_files(&configFile))
+ {
+ GetWindowsDirectoryA(confname,szConfname);
+ confname[szConfname-1] = '\0';
+
+ StringCchCatA(confname, szConfname, "\\");
+ StringCchCatA(confname, szConfname, KRB5_FILE);
+
+ return FALSE;
+ }
+
+ *confname = 0;
+
+ if (configFile)
+ {
+ StringCchCopyA(confname, szConfname, *configFile);
+ pkrb5_free_config_files(configFile);
+ }
+
+ if (!*confname)
+ {
+ GetWindowsDirectoryA(confname,szConfname);
+ confname[szConfname-1] = '\0';
+ StringCchCatA(confname, szConfname, "\\");
+ StringCchCatA(confname, szConfname, KRB5_FILE);
+ }
+
+ return FALSE;
+}
+
+BOOL
+khm_get_krb4_con_file(LPSTR confname, UINT szConfname)
+{
+ if (hKrb5 && !hKrb4) { // hold krb.con where krb5.ini is located
+ CHAR krbConFile[MAX_PATH]="";
+ LPSTR pFind;
+
+ //strcpy(krbConFile, CLeashApp::m_krbv5_profile->first_file->filename);
+ if (khm_krb5_get_profile_file(krbConFile, sizeof(krbConFile))) {
+ GetWindowsDirectoryA(krbConFile,sizeof(krbConFile));
+ krbConFile[MAX_PATH-1] = '\0';
+ StringCchCatA(confname, szConfname, "\\");
+ }
+
+ pFind = strrchr(krbConFile, '\\');
+ if (pFind) {
+ *pFind = '\0';
+ StringCchCatA(krbConFile, ARRAYLENGTH(krbConFile), "\\");
+ StringCchCatA(krbConFile, ARRAYLENGTH(krbConFile), KRB_FILE);
+ }
+ else
+ krbConFile[0] = '\0';
+
+ StringCchCopyA(confname, szConfname, krbConFile);
+ }
+ else if (hKrb4) {
+ unsigned int size = szConfname;
+ memset(confname, '\0', szConfname);
+ if (!pkrb_get_krbconf2(confname, &size))
+ { // Error has happened
+ GetWindowsDirectoryA(confname,szConfname);
+ confname[szConfname-1] = '\0';
+ StringCchCatA(confname, szConfname, "\\");
+ StringCchCatA(confname, szConfname, KRB_FILE);
+ }
+ }
+ return FALSE;
+}
+
+int
+readstring(FILE * file, char * buf, int len)
+{
+ int c,i;
+ memset(buf, '\0', sizeof(buf));
+ for (i=0, c=fgetc(file); c != EOF ; c=fgetc(file), i++) {
+ if (i < sizeof(buf)) {
+ if (c == '\n') {
+ buf[i] = '\0';
+ return i;
+ } else {
+ buf[i] = c;
+ }
+ } else {
+ if (c == '\n') {
+ buf[len-1] = '\0';
+ return(i);
+ }
+ }
+ }
+ if (c == EOF) {
+ if (i > 0 && i < len) {
+ buf[i] = '\0';
+ return(i);
+ } else {
+ buf[len-1] = '\0';
+ return(-1);
+ }
+ }
+ return(-1);
+}
+
+/*! \internal
+ \brief Return a list of configured realms
+
+ The string that is returned is a set of null terminated unicode
+ strings, each of which denotes one realm. The set is terminated
+ by a zero length null terminated string.
+
+ The caller should free the returned string using free()
+
+ \return The string with the list of realms or NULL if the
+ operation fails.
+*/
+wchar_t *
+khm_krb5_get_realm_list(void)
+{
+ wchar_t * rlist = NULL;
+
+ if (pprofile_get_subsection_names && pprofile_free_list) {
+ const char* rootSection[] = {"realms", NULL};
+ const char** rootsec = rootSection;
+ char **sections = NULL, **cpp = NULL, *value = NULL;
+
+ char krb5_conf[MAX_PATH+1];
+
+ if (!khm_krb5_get_profile_file(krb5_conf,sizeof(krb5_conf))) {
+ profile_t profile;
+ long retval;
+ const char *filenames[2];
+ wchar_t * d;
+ size_t cbsize;
+ size_t t;
+
+ filenames[0] = krb5_conf;
+ filenames[1] = NULL;
+ retval = pprofile_init(filenames, &profile);
+ if (!retval) {
+ retval = pprofile_get_subsection_names(profile, rootsec,
+ &sections);
+
+ if (!retval)
+ {
+ /* first figure out how much space to allocate */
+ cbsize = 0;
+ for (cpp = sections; *cpp; cpp++)
+ {
+ cbsize += sizeof(wchar_t) * (strlen(*cpp) + 1);
+ }
+ cbsize += sizeof(wchar_t); /* double null terminated */
+
+ rlist = PMALLOC(cbsize);
+ d = rlist;
+ for (cpp = sections; *cpp; cpp++)
+ {
+ AnsiStrToUnicode(d, cbsize, *cpp);
+ t = wcslen(d) + 1;
+ d += t;
+ cbsize -= sizeof(wchar_t) * t;
+ }
+ *d = L'\0';
+ }
+
+ pprofile_free_list(sections);
+
+#if 0
+ retval = pprofile_get_string(profile, "libdefaults","noaddresses", 0, "true", &value);
+ if ( value ) {
+ disable_noaddresses = config_boolean_to_int(value);
+ pprofile_release_string(value);
+ }
+#endif
+ pprofile_release(profile);
+ }
+ }
+ } else {
+ FILE * file;
+ char krb_conf[MAX_PATH+1];
+ char * p;
+ size_t cbsize, t;
+ wchar_t * d;
+
+ if (!khm_get_krb4_con_file(krb_conf,sizeof(krb_conf)) &&
+#if _MSC_VER >= 1400
+ !fopen_s(&file, krb_conf, "rt")
+#else
+ (file = fopen(krb_conf, "rt"))
+#endif
+ )
+ {
+ char lineBuf[256];
+
+ /*TODO: compute the actual required buffer size instead of hardcoding */
+ cbsize = 16384; // arbitrary
+ rlist = PMALLOC(cbsize);
+ d = rlist;
+
+ // Skip the default realm
+ readstring(file,lineBuf,sizeof(lineBuf));
+
+ // Read the defined realms
+ while (TRUE)
+ {
+ if (readstring(file,lineBuf,sizeof(lineBuf)) < 0)
+ break;
+
+ if (*(lineBuf + strlen(lineBuf) - 1) == '\r')
+ *(lineBuf + strlen(lineBuf) - 1) = 0;
+
+ for (p=lineBuf; *p ; p++)
+ {
+ if (isspace(*p)) {
+ *p = 0;
+ break;
+ }
+ }
+
+ if ( strncmp(".KERBEROS.OPTION.",lineBuf,17) ) {
+ t = strlen(lineBuf) + 1;
+ if(cbsize > (1 + t*sizeof(wchar_t))) {
+ AnsiStrToUnicode(d, cbsize, lineBuf);
+ d += t;
+ cbsize -= t * sizeof(wchar_t);
+ } else
+ break;
+ }
+ }
+
+ *d = L'\0';
+
+ fclose(file);
+ }
+ }
+
+ return rlist;
+}
+
+/*! \internal
+ \brief Get the default realm
+
+ A string will be returned that specifies the default realm. The
+ caller should free the string using PFREE().
+
+ Returns NULL if the operation fails.
+*/
+wchar_t *
+khm_krb5_get_default_realm(void)
+{
+ wchar_t * realm;
+ size_t cch;
+ krb5_context ctx=0;
+ char * def = 0;
+
+ pkrb5_init_context(&ctx);
+
+ if (ctx == 0)
+ return NULL;
+
+ pkrb5_get_default_realm(ctx,&def);
+
+ if (def) {
+ cch = strlen(def) + 1;
+ realm = PMALLOC(sizeof(wchar_t) * cch);
+ AnsiStrToUnicode(realm, sizeof(wchar_t) * cch, def);
+ pkrb5_free_default_realm(ctx, def);
+ } else
+ realm = NULL;
+
+ pkrb5_free_context(ctx);
+
+ return realm;
+}
+
+long
+khm_krb5_set_default_realm(wchar_t * realm) {
+ krb5_context ctx=0;
+ char * def = 0;
+ long rv = 0;
+ char astr[K5_MAXCCH_REALM];
+
+ UnicodeStrToAnsi(astr, sizeof(astr), realm);
+
+ pkrb5_init_context(&ctx);
+ pkrb5_get_default_realm(ctx,&def);
+
+ if ((def && strcmp(def, astr)) ||
+ !def) {
+ rv = pkrb5_set_default_realm(ctx, astr);
+ }
+
+ if (def) {
+ pkrb5_free_default_realm(ctx, def);
+ }
+
+ pkrb5_free_context(ctx);
+
+ return rv;
+}
+
+wchar_t *
+khm_get_realm_from_princ(wchar_t * princ) {
+ wchar_t * t;
+
+ if(!princ)
+ return NULL;
+
+ for (t = princ; *t; t++) {
+ if(*t == L'\\') { /* escape */
+ t++;
+ if(! *t) /* malformed */
+ break;
+ } else if (*t == L'@')
+ break;
+ }
+
+ if (*t == '@' && *(t+1) != L'\0')
+ return (t+1);
+ else
+ return NULL;
+}
+
+long
+khm_krb5_changepwd(char * principal,
+ char * password,
+ char * newpassword,
+ char** error_str)
+{
+ krb5_error_code rc = 0;
+ int result_code = 0;
+ krb5_data result_code_string, result_string;
+ krb5_context context = 0;
+ krb5_principal princ = 0;
+ krb5_get_init_creds_opt opts;
+ krb5_creds creds;
+
+ result_string.data = 0;
+ result_code_string.data = 0;
+
+ if ( !pkrb5_init_context )
+ goto cleanup;
+
+ if (rc = pkrb5_init_context(&context)) {
+ goto cleanup;
+ }
+
+ if (rc = pkrb5_parse_name(context, principal, &princ)) {
+ goto cleanup;
+ }
+
+ pkrb5_get_init_creds_opt_init(&opts);
+ pkrb5_get_init_creds_opt_set_tkt_life(&opts, 5*60);
+ pkrb5_get_init_creds_opt_set_renew_life(&opts, 0);
+ pkrb5_get_init_creds_opt_set_forwardable(&opts, 0);
+ pkrb5_get_init_creds_opt_set_proxiable(&opts, 0);
+ pkrb5_get_init_creds_opt_set_address_list(&opts,NULL);
+
+ if (rc = pkrb5_get_init_creds_password(context, &creds, princ,
+ password, 0, 0, 0,
+ "kadmin/changepw", &opts)) {
+ if (rc == KRB5KRB_AP_ERR_BAD_INTEGRITY) {
+#if 0
+ com_err(argv[0], 0,
+ "Password incorrect while getting initial ticket");
+#endif
+ } else {
+#if 0
+ com_err(argv[0], ret, "getting initial ticket");
+#endif
+ }
+ goto cleanup;
+ }
+
+ if (rc = pkrb5_change_password(context, &creds, newpassword,
+ &result_code, &result_code_string,
+ &result_string)) {
+#if 0
+ com_err(argv[0], ret, "changing password");
+#endif
+ goto cleanup;
+ }
+
+ if (result_code) {
+ int len = result_code_string.length +
+ (result_string.length ? (sizeof(": ") - 1) : 0) +
+ result_string.length;
+ if (len && error_str) {
+ *error_str = PMALLOC(len + 1);
+ if (*error_str)
+ StringCchPrintfA(*error_str, len+1,
+ "%.*s%s%.*s",
+ result_code_string.length,
+ result_code_string.data,
+ result_string.length?": ":"",
+ result_string.length,
+ result_string.data);
+ }
+ rc = result_code;
+ goto cleanup;
+ }
+
+ cleanup:
+ if (result_string.data)
+ pkrb5_free_data_contents(context, &result_string);
+
+ if (result_code_string.data)
+ pkrb5_free_data_contents(context, &result_code_string);
+
+ if (princ)
+ pkrb5_free_principal(context, princ);
+
+ if (context)
+ pkrb5_free_context(context);
+
+ return rc;
+}
+
+khm_int32 KHMAPI
+khm_krb5_creds_is_equal(khm_handle vcred1, khm_handle vcred2, void * dummy) {
+ if (kcdb_creds_comp_attr(vcred1, vcred2, KCDB_ATTR_LOCATION) ||
+ kcdb_creds_comp_attr(vcred1, vcred2, attr_id_key_enctype) ||
+ kcdb_creds_comp_attr(vcred1, vcred2, attr_id_tkt_enctype) ||
+ kcdb_creds_comp_attr(vcred1, vcred2, attr_id_kvno))
+ return 1;
+ else
+ return 0;
+}
+
+void
+khm_krb5_set_identity_flags(khm_handle identity,
+ khm_int32 flag_mask,
+ khm_int32 flag_value) {
+
+ khm_int32 t = 0;
+ khm_size cb;
+
+ cb = sizeof(t);
+ if (KHM_FAILED(kcdb_identity_get_attr(identity,
+ attr_id_krb5_idflags,
+ NULL,
+ &t, &cb))) {
+ t = 0;
+ }
+
+ t &= ~flag_mask;
+ t |= (flag_value & flag_mask);
+
+ kcdb_identity_set_attr(identity,
+ attr_id_krb5_idflags,
+ &t, sizeof(t));
+}
+
+khm_int32
+khm_krb5_get_identity_flags(khm_handle identity) {
+ khm_int32 t = 0;
+ khm_size cb;
+
+ cb = sizeof(t);
+ kcdb_identity_get_attr(identity,
+ attr_id_krb5_idflags,
+ NULL, &t, &cb);
+
+ return t;
+}
+
+long
+khm_krb5_get_temp_ccache(krb5_context ctx,
+ krb5_ccache * prcc) {
+ int rnd = rand();
+ char ccname[MAX_PATH];
+ long code = 0;
+ krb5_ccache cc = 0;
+
+ StringCbPrintfA(ccname, sizeof(ccname), "MEMORY:TempCache%8x", rnd);
+
+ code = pkrb5_cc_resolve(ctx, ccname, &cc);
+
+ if (code == 0)
+ *prcc = cc;
+
+ return code;
+}
+
+/*
+
+ The configuration information for each identity comes from a
+ multitude of layers organized as follows. The ordering is
+ decreasing in priority. When looking up a value, the value will be
+ looked up in each layer in turn starting at level 0. The first
+ instance of the value found will be the effective value.
+
+ 0 : <identity configuration>\Krb5Cred
+
+ 0.1: per user
+
+ 0.2: per machine
+
+ 1 : <plugin configuration>\Parameters\Realms\<realm of identity>
+
+ 1.1: per user
+
+ 1.2: per machine
+
+ 2 : <plugin configuration>\Parameters
+
+ 2.1: per user
+
+ 2.2: per machine
+
+ 2.3: schema
+
+ */
+khm_int32
+khm_krb5_get_identity_config(khm_handle ident,
+ khm_int32 flags,
+ khm_handle * ret_csp) {
+
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+ khm_handle csp_i = NULL;
+ khm_handle csp_ik5 = NULL;
+ khm_handle csp_realms = NULL;
+ khm_handle csp_realm = NULL;
+ khm_handle csp_plugins = NULL;
+ khm_handle csp_krbcfg = NULL;
+ khm_handle csp_rv = NULL;
+ wchar_t realm[KCDB_IDENT_MAXCCH_NAME];
+
+ realm[0] = L'\0';
+
+ if (ident) {
+ wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
+ wchar_t * trealm;
+ khm_size cb_idname = sizeof(idname);
+
+ rv = kcdb_identity_get_name(ident, idname, &cb_idname);
+ if (KHM_SUCCEEDED(rv) &&
+ (trealm = khm_get_realm_from_princ(idname)) != NULL) {
+ StringCbCopy(realm, sizeof(realm), trealm);
+ }
+ }
+
+ if (ident) {
+ rv = kcdb_identity_get_config(ident, flags, &csp_i);
+ if (KHM_FAILED(rv))
+ goto try_realm;
+
+ rv = khc_open_space(csp_i, CSNAME_KRB5CRED, flags, &csp_ik5);
+ if (KHM_FAILED(rv))
+ goto try_realm;
+
+ try_realm:
+
+ if (realm[0] == L'\0')
+ goto done_shadow_realm;
+
+ rv = khc_open_space(csp_params, CSNAME_REALMS, flags, &csp_realms);
+ if (KHM_FAILED(rv))
+ goto done_shadow_realm;
+
+ rv = khc_open_space(csp_realms, realm, flags, &csp_realm);
+ if (KHM_FAILED(rv))
+ goto done_shadow_realm;
+
+ rv = khc_shadow_space(csp_realm, csp_params);
+
+ done_shadow_realm:
+
+ if (csp_ik5) {
+ if (csp_realm)
+ rv = khc_shadow_space(csp_ik5, csp_realm);
+ else
+ rv = khc_shadow_space(csp_ik5, csp_params);
+
+ csp_rv = csp_ik5;
+ } else {
+ if (csp_realm)
+ csp_rv = csp_realm;
+ }
+ }
+
+ if (csp_rv == NULL) {
+
+ /* No valid identity specified or the specified identity
+ doesn't have any configuration. We default to the
+ parameters key. */
+
+ /* we don't just return csp_params since that's a global
+ handle that we shouldn't close until the plugin is
+ unloaded. The caller is going to close the returned handle
+ when it is done. So we need to create a new csp_params
+ that can safely be closed. */
+
+ rv = kmm_get_plugins_config(0, &csp_plugins);
+ if (KHM_FAILED(rv))
+ goto done;
+
+ rv = khc_open_space(csp_plugins, CSNAME_KRB5CRED, flags, &csp_krbcfg);
+ if (KHM_FAILED(rv))
+ goto done;
+
+ rv = khc_open_space(csp_krbcfg, CSNAME_PARAMS, flags, &csp_rv);
+ }
+
+ done:
+
+ *ret_csp = csp_rv;
+
+ /* leave csp_ik5. If it's non-NULL, then it's the return value */
+ /* leave csp_rv. It's the return value. */
+ if (csp_i)
+ khc_close_space(csp_i);
+ if (csp_realms)
+ khc_close_space(csp_realms);
+
+ /* csp_realm can also be a return value if csp_ik5 was NULL */
+ if (csp_realm && csp_realm != csp_rv)
+ khc_close_space(csp_realm);
+
+ if (csp_plugins)
+ khc_close_space(csp_plugins);
+ if (csp_krbcfg)
+ khc_close_space(csp_krbcfg);
+
+ return rv;
+}
+
+/* from get_in_tkt.c */
+static krb5_error_code
+get_libdefault_string(profile_t profile, const char * realm,
+ const char * option, char ** ret_val) {
+ char realmstr[K5_MAXCCH_REALM];
+ char **nameval = NULL;
+ const char * names[4];
+ krb5_error_code code = 0;
+
+ names[0] = "libdefaults";
+
+ if (!realm || !realm[0])
+ goto try_number_two;
+
+ StringCbCopyA(realmstr, sizeof(realmstr), realm);
+
+ /*
+ * Try number one:
+ *
+ * [libdefaults]
+ * REALM = {
+ * option = <boolean>
+ * }
+ */
+
+ names[1] = realmstr;
+ names[2] = option;
+ names[3] = 0;
+ code = pprofile_get_values(profile, names, &nameval);
+ if (code == 0 && nameval && nameval[0])
+ goto goodbye;
+
+ try_number_two:
+
+ /*
+ * Try number two:
+ *
+ * [libdefaults]
+ * option = <boolean>
+ */
+
+ names[1] = option;
+ names[2] = 0;
+ code = pprofile_get_values(profile, names, &nameval);
+ if (code == 0 && nameval && nameval[0])
+ goto goodbye;
+
+ goodbye:
+ if (!nameval)
+ return(ENOENT);
+
+ if (!nameval[0]) {
+ code = ENOENT;
+ } else {
+ size_t cb;
+
+ if (FAILED(StringCbLengthA(nameval[0], K5_MAXCCH_REALM * sizeof(char), &cb))) {
+ code = ENOMEM;
+ } else {
+ cb += sizeof(char);
+ *ret_val = PMALLOC(cb);
+
+ if (!*ret_val)
+ code = ENOMEM;
+ else {
+ StringCbCopyA(*ret_val, cb, nameval[0]);
+ code = 0;
+ }
+ }
+ }
+
+ pprofile_free_list(nameval);
+
+ return code;
+}
+
+khm_int32
+khm_krb5_get_identity_params(khm_handle ident, k5_params * p) {
+
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+ khm_handle csp_id = NULL;
+ khm_int32 regf = 0;
+ khm_int32 proff = 0;
+ khm_int32 e;
+ khm_int32 v;
+ CHAR confname[MAX_PATH];
+ CHAR realmname[K5_MAXCCH_REALM];
+
+ ZeroMemory(p, sizeof(*p));
+
+ rv = khm_krb5_get_identity_config(ident, 0, &csp_id);
+ if (KHM_FAILED(rv))
+ goto done_reg;
+
+
+#define GETVAL(vname, vfield, flag) \
+ do { \
+ e = khc_value_exists(csp_id, vname); \
+ rv = khc_read_int32(csp_id, vname, &v); \
+ if (KHM_FAILED(rv)) goto done_reg; \
+ p->vfield = v; \
+ if ((e & ~KCONF_FLAG_SCHEMA) != 0) regf |= flag; \
+ } while(FALSE)
+
+ /* Flags */
+ GETVAL(L"Renewable", renewable, K5PARAM_F_RENEW);
+ GETVAL(L"Forwardable", forwardable, K5PARAM_F_FORW);
+ GETVAL(L"Proxiable", proxiable, K5PARAM_F_PROX);
+ GETVAL(L"Addressless", addressless, K5PARAM_F_ADDL);
+ GETVAL(L"PublicIP", publicIP, K5PARAM_F_PUBIP);
+
+ /* Lifetime */
+ GETVAL(L"DefaultLifetime", lifetime, K5PARAM_F_LIFE);
+ GETVAL(L"MaxLifetime", lifetime_max, K5PARAM_F_LIFE_H);
+ GETVAL(L"MinLifetime", lifetime_min, K5PARAM_F_LIFE_L);
+
+ /* Renewable lifetime */
+ GETVAL(L"DefaultRenewLifetime", renew_life, K5PARAM_F_RLIFE);
+ GETVAL(L"MaxRenewLifetime", renew_life_max, K5PARAM_F_RLIFE_H);
+ GETVAL(L"MinRenewLifetime", renew_life_min, K5PARAM_F_RLIFE_L);
+
+#undef GETVAL
+
+ done_reg:
+
+ if (csp_id)
+ khc_close_space(csp_id);
+
+ /* if all the parameters were read from the registry, then we have
+ no reason to read from the profile file. */
+ if (regf == K5PARAM_FM_ALL) {
+ p->source_reg = regf;
+ return KHM_ERROR_SUCCESS;
+ }
+
+ if (rv)
+ return rv;
+
+ /* we need to figure out the realm name, since there might be
+ per-realm configuration in the profile file. */
+
+ realmname[0] = '\0';
+
+ if (ident) {
+ wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
+ khm_size cb;
+
+ idname[0] = L'\0';
+ cb = sizeof(idname);
+ rv = kcdb_identity_get_name(ident, idname, &cb);
+ if (KHM_SUCCEEDED(rv)) {
+ wchar_t * wrealm;
+
+ wrealm = khm_get_realm_from_princ(idname);
+ if (wrealm) {
+ UnicodeStrToAnsi(realmname, sizeof(realmname), wrealm);
+ }
+ }
+ }
+
+ /* If we get here, then some of the settings we read from the
+ configuration actually came from the schema. In other words,
+ the values weren't really defined for this identity. So we now
+ have to read the values from the krb5 configuration file. */
+
+ if (!khm_krb5_get_profile_file(confname, sizeof(confname))) {
+ profile_t profile;
+ const char * filenames[2];
+ long retval;
+
+ filenames[0] = confname;
+ filenames[1] = NULL;
+
+ if (!pprofile_init(filenames, &profile)) {
+
+ /* default ticket lifetime */
+ if (!(regf & K5PARAM_F_LIFE)) {
+ char * value = NULL;
+ retval = get_libdefault_string(profile, realmname,
+ "ticket_lifetime", &value);
+
+ if (retval == 0 && value) {
+ krb5_deltat d;
+
+ retval = pkrb5_string_to_deltat(value, &d);
+ if (retval == KRB5_DELTAT_BADFORMAT) {
+ /* Historically some sites use relations of
+ the form 'ticket_lifetime = 24000' where
+ the unit is left out but is assumed to be
+ seconds. Then there are other sites which
+ use the form 'ticket_lifetime = 600' where
+ the unit is assumed to be minutes. While
+ these are technically wrong (a unit needs
+ to be specified), we try to accomodate for
+ this using the safe assumption that the
+ unit is seconds and tack an 's' to the end
+ and see if that works. */
+
+ size_t cch;
+ char tmpbuf[256];
+ char * buf;
+
+ do {
+ if (FAILED(StringCchLengthA(value, 1024 /* unresonably large size */,
+ &cch)))
+ break;
+
+ cch += sizeof(char) * 2; /* NULL and new 's' */
+ if (cch > ARRAYLENGTH(tmpbuf))
+ buf = PMALLOC(cch * sizeof(char));
+ else
+ buf = tmpbuf;
+
+ StringCchCopyA(buf, cch, value);
+ StringCchCatA(buf, cch, "s");
+
+ retval = pkrb5_string_to_deltat(buf, &d);
+ if (retval == 0) {
+ p->lifetime = d;
+ proff |= K5PARAM_F_LIFE;
+ }
+
+ if (buf != tmpbuf)
+ PFREE(buf);
+
+ } while(0);
+
+ } else if (retval == 0) {
+ p->lifetime = d;
+ proff |= K5PARAM_F_LIFE;
+ }
+
+ PFREE(value);
+ }
+ }
+
+ if (!(regf & K5PARAM_F_RLIFE)) {
+ char * value = NULL;
+ retval = get_libdefault_string(profile, realmname,
+ "renew_lifetime", &value);
+ if (retval == 0 && value) {
+ krb5_deltat d;
+
+ retval = pkrb5_string_to_deltat(value, &d);
+ if (retval == 0) {
+ p->renew_life = d;
+ proff |= K5PARAM_F_RLIFE;
+ }
+ PFREE(value);
+ }
+ }
+
+ if (!(regf & K5PARAM_F_FORW)) {
+ char * value = NULL;
+ retval = get_libdefault_string(profile, realmname,
+ "forwardable", &value);
+ if (retval == 0 && value) {
+ khm_boolean b;
+
+ if (!khm_krb5_parse_boolean(value, &b))
+ p->forwardable = b;
+ else
+ p->forwardable = FALSE;
+ PFREE(value);
+ proff |= K5PARAM_F_FORW;
+ }
+ }
+
+ if (!(regf & K5PARAM_F_RENEW)) {
+ char * value = NULL;
+ retval = get_libdefault_string(profile, realmname,
+ "renewable", &value);
+ if (retval == 0 && value) {
+ khm_boolean b;
+
+ if (!khm_krb5_parse_boolean(value, &b))
+ p->renewable = b;
+ else
+ p->renewable = TRUE;
+ PFREE(value);
+ proff |= K5PARAM_F_RENEW;
+ }
+ }
+
+ if (!(regf & K5PARAM_F_ADDL)) {
+ char * value = NULL;
+ retval = get_libdefault_string(profile, realmname,
+ "noaddresses", &value);
+ if (retval == 0 && value) {
+ khm_boolean b;
+
+ if (!khm_krb5_parse_boolean(value, &b))
+ p->addressless = b;
+ else
+ p->addressless = TRUE;
+ PFREE(value);
+ proff |= K5PARAM_F_ADDL;
+ }
+ }
+
+ if (!(regf & K5PARAM_F_PROX)) {
+ char * value = NULL;
+ retval = get_libdefault_string(profile, realmname,
+ "proxiable", &value);
+ if (retval == 0 && value) {
+ khm_boolean b;
+
+ if (!khm_krb5_parse_boolean(value, &b))
+ p->proxiable = b;
+ else
+ p->proxiable = FALSE;
+ PFREE(value);
+ proff |= K5PARAM_F_PROX;
+ }
+ }
+
+ pprofile_release(profile);
+ }
+ }
+
+ p->source_reg = regf;
+ p->source_prof = proff;
+
+ return rv;
+}
+
+/* Note that p->source_reg and p->source_prof is used in special ways
+ here. All fields that are flagged in source_reg will be written to
+ the configuration (if they are different from what
+ khm_krb5_get_identity_params() reports). All fields that are
+ flagged in source_prof will be removed from the configuration
+ (thereby exposing the value defined in the profile file). */
+khm_int32
+khm_krb5_set_identity_params(khm_handle ident, const k5_params * p) {
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+ khm_handle csp_id = NULL;
+ k5_params p_s;
+ khm_int32 source_reg = p->source_reg;
+ khm_int32 source_prof = p->source_prof;
+
+ rv = khm_krb5_get_identity_config(ident,
+ KHM_PERM_WRITE | KHM_FLAG_CREATE |
+ KCONF_FLAG_WRITEIFMOD,
+ &csp_id);
+ if (KHM_FAILED(rv))
+ goto done_reg;
+
+ khm_krb5_get_identity_params(ident, &p_s);
+
+ /* Remove any bits that don't make sense. Not all values can be
+ specified in the profile file. */
+ source_prof &= K5PARAM_FM_PROF;
+
+ /* if a flag appears in both source_prof and source_reg, remove
+ the flag from source_reg. */
+ source_reg &= ~source_prof;
+
+ /* we only write values that have changed, and that are flagged in
+ source_reg */
+
+ if ((source_reg & K5PARAM_F_RENEW) &&
+ !!p_s.renewable != !!p->renewable)
+ khc_write_int32(csp_id, L"Renewable", !!p->renewable);
+
+ if ((source_reg & K5PARAM_F_FORW) &&
+ !!p_s.forwardable != !!p->forwardable)
+ khc_write_int32(csp_id, L"Forwardable", !!p->forwardable);
+
+ if ((source_reg & K5PARAM_F_PROX) &&
+ !!p_s.proxiable != !!p->proxiable)
+ khc_write_int32(csp_id, L"Proxiable", !!p->proxiable);
+
+ if ((source_reg & K5PARAM_F_ADDL) &&
+ !!p_s.addressless != !!p->addressless)
+ khc_write_int32(csp_id, L"Addressless", !!p->addressless);
+
+ if ((source_reg & K5PARAM_F_PUBIP) &&
+ p_s.publicIP != p->publicIP)
+ khc_write_int32(csp_id, L"PublicIP", p->publicIP);
+
+ if ((source_reg & K5PARAM_F_LIFE) &&
+ p_s.lifetime != p->lifetime)
+ khc_write_int32(csp_id, L"DefaultLifetime", p->lifetime);
+
+ if ((source_reg & K5PARAM_F_LIFE_H) &&
+ p_s.lifetime_max != p->lifetime_max)
+ khc_write_int32(csp_id, L"MaxLifetime", p->lifetime_max);
+
+ if ((source_reg & K5PARAM_F_LIFE_L) &&
+ p_s.lifetime_min != p->lifetime_min)
+ khc_write_int32(csp_id, L"MinLifetime", p->lifetime_min);
+
+ if ((source_reg & K5PARAM_F_RLIFE) &&
+ p_s.renew_life != p->renew_life)
+ khc_write_int32(csp_id, L"DefaultRenewLifetime", p->renew_life);
+
+ if ((source_reg & K5PARAM_F_RLIFE_H) &&
+ p_s.renew_life_max != p->renew_life_max)
+ khc_write_int32(csp_id, L"MaxRenewLifetime", p->renew_life_max);
+
+ if ((source_reg & K5PARAM_F_RLIFE_L) &&
+ p_s.renew_life_min != p->renew_life_min)
+ khc_write_int32(csp_id, L"MinRenewLifetime", p->renew_life_min);
+
+ /* and now, remove the values that are present in source_prof.
+ Not all values are removed since not all values can be
+ specified in the profile file. */
+ if (source_prof & K5PARAM_F_RENEW)
+ khc_remove_value(csp_id, L"Renewable", 0);
+
+ if (source_prof & K5PARAM_F_FORW)
+ khc_remove_value(csp_id, L"Forwardable", 0);
+
+ if (source_prof & K5PARAM_F_PROX)
+ khc_remove_value(csp_id, L"Proxiable", 0);
+
+ if (source_prof & K5PARAM_F_ADDL)
+ khc_remove_value(csp_id, L"Addressless", 0);
+
+ if (source_prof & K5PARAM_F_LIFE)
+ khc_remove_value(csp_id, L"DefaultLifetime", 0);
+
+ if (source_prof & K5PARAM_F_RLIFE)
+ khc_remove_value(csp_id, L"DefaultRenewLifetime", 0);
+
+ done_reg:
+ if (csp_id != NULL)
+ khc_close_space(csp_id);
+
+ return rv;
+}
+
+static const char *const conf_yes[] = {
+ "y", "yes", "true", "t", "1", "on",
+ 0,
+};
+
+static const char *const conf_no[] = {
+ "n", "no", "false", "nil", "0", "off",
+ 0,
+};
+
+int
+khm_krb5_parse_boolean(const char *s, khm_boolean * b)
+{
+ const char *const *p;
+
+ for(p=conf_yes; *p; p++) {
+ if (!_stricmp(*p,s)) {
+ *b = TRUE;
+ return 0;
+ }
+ }
+
+ for(p=conf_no; *p; p++) {
+ if (!_stricmp(*p,s)) {
+ *b = FALSE;
+ return 0;
+ }
+ }
+
+ /* Default to "no" */
+ return KHM_ERROR_INVALID_PARAM;
+}
diff --git a/src/windows/identity/plugins/krb5/krb5funcs.h b/src/windows/identity/plugins/krb5/krb5funcs.h
index b4ab452b31..d2ec28b47f 100644
--- a/src/windows/identity/plugins/krb5/krb5funcs.h
+++ b/src/windows/identity/plugins/krb5/krb5funcs.h
@@ -1,217 +1,217 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-/* Adapted from multiple Leash header files */
-
-#ifndef __KHIMAIRA_KRB5FUNCS_H
-#define __KHIMAIRA_KRB5FUNCS_H
-
-#include<stdlib.h>
-#include<krb5.h>
-
-#include <windows.h>
-#define SECURITY_WIN32
-#include <security.h>
-
-#if _WIN32_WINNT < 0x0501
-#define KHM_SAVE_WIN32_WINNT _WIN32_WINNT
-#undef _WIN32_WINNT
-#define _WIN32_WINNT 0x0501
-#endif
-#include<ntsecapi.h>
-#ifdef KHM_SAVE_WIN32_WINNT
-#undef _WIN32_WINNT
-#define _WIN32_WINNT KHM_SAVE_WIN32_WINNT
-#undef KHM_SAVE_WIN32_WINNT
-#endif
-
-#include <krb5common.h>
-
-#define LEASH_DEBUG_CLASS_GENERIC 0
-#define LEASH_DEBUG_CLASS_KRB4 1
-#define LEASH_DEBUG_CLASS_KRB4_APP 2
-
-#define LEASH_PRIORITY_LOW 0
-#define LEASH_PRIORITY_HIGH 1
-
-#define KRB5_DEFAULT_LIFE 60*60*10 /* 10 hours */
-
-#define KRB5_MAXCCH_CCNAME 1024
-
-#define KRB5_CONF_YES "yes"
-#define KRB5_CONF_NO "no"
-
-typedef struct tag_k5params {
-
- khm_int32 source_reg; /* flags indicating which fields were
- retrieved using the registry */
- khm_int32 source_prof; /* flags indicating which fields were
- retrieved using krb5.ini */
-
- khm_boolean renewable;
- khm_boolean forwardable;
- khm_boolean proxiable;
- khm_boolean addressless;
-
- khm_ui_4 publicIP;
-
- krb5_deltat lifetime;
- krb5_deltat lifetime_min;
- krb5_deltat lifetime_max;
-
- krb5_deltat renew_life;
- krb5_deltat renew_life_min;
- krb5_deltat renew_life_max;
-
-} k5_params;
-
-#define K5PARAM_F_RENEW 0x00000001
-#define K5PARAM_F_FORW 0x00000002
-#define K5PARAM_F_PROX 0x00000004
-#define K5PARAM_F_ADDL 0x00000008
-#define K5PARAM_F_PUBIP 0x00000010
-#define K5PARAM_F_LIFE 0x00000020
-#define K5PARAM_F_RLIFE 0x00000040
-#define K5PARAM_F_LIFE_L 0x00000080
-#define K5PARAM_F_LIFE_H 0x00000100
-#define K5PARAM_F_RLIFE_L 0x00000200
-#define K5PARAM_F_RLIFE_H 0x00000400
-
-#define K5PARAM_FM_ALL 0x000007ff
-#define K5PARAM_FM_PROF 0x0000007f
-
-/* Credential and principal operations */
-
-BOOL
-khm_krb5_ms2mit(char * match_princ,
- BOOL match_realm,
- BOOL save_creds,
- khm_handle * ret_ident);
-
-int
-khm_krb5_kinit(krb5_context alt_ctx,
- char * principal_name,
- char * password,
- char * ccache,
- krb5_deltat lifetime,
- DWORD forwardable,
- DWORD proxiable,
- krb5_deltat renew_life,
- DWORD addressless,
- DWORD publicIP,
- krb5_prompter_fct prompter,
- void * p_data);
-
-long
-khm_krb5_changepwd(char * principal,
- char * password,
- char * newpassword,
- char** error_str);
-
-int
-khm_krb5_destroy_by_credset(khm_handle p_cs);
-
-int
-khm_krb5_destroy_identity(khm_handle identity);
-
-long
-khm_convert524(krb5_context ctx);
-
-int
-khm_krb5_renew_cred(khm_handle cred);
-
-int
-khm_krb5_renew_ident(khm_handle identity);
-
-long
-khm_krb5_list_tickets(krb5_context *krbv5Context);
-
-long
-khm_krb5_copy_ccache_by_name(krb5_context in_ctx,
- wchar_t * wscc_dest,
- wchar_t * wscc_src);
-
-long
-khm_krb5_get_temp_ccache(krb5_context ctx,
- krb5_ccache * cc);
-
-khm_int32 KHMAPI
-khm_krb5_creds_is_equal(khm_handle vcred1, khm_handle vcred2, void * dummy);
-
-
-/* Configuration */
-
-BOOL
-khm_krb5_get_profile_file(LPSTR confname, UINT szConfname);
-
-BOOL
-khm_krb5_get_temp_profile_file(LPSTR confname, UINT szConfname);
-
-wchar_t *
-khm_krb5_get_default_realm(void);
-
-long
-khm_krb5_set_default_realm(wchar_t * realm);
-
-wchar_t *
-khm_krb5_get_realm_list(void);
-
-khm_int32
-khm_krb5_get_identity_config(khm_handle ident,
- khm_int32 flags,
- khm_handle * ret_csp);
-
-void
-khm_krb5_set_identity_flags(khm_handle identity,
- khm_int32 flag_mask,
- khm_int32 flag_value);
-
-khm_int32
-khm_krb5_get_identity_flags(khm_handle identity);
-
-khm_int32
-khm_krb5_set_identity_params(khm_handle ident, const k5_params * p);
-
-khm_int32
-khm_krb5_get_identity_params(khm_handle ident, k5_params * p);
-
-/* Utility */
-
-wchar_t *
-khm_get_realm_from_princ(wchar_t * princ);
-
-long
-khm_krb5_canon_cc_name(wchar_t * wcc_name,
- size_t cb_cc_name);
-
-int
-khm_krb5_cc_name_cmp(const wchar_t * cc_name_1,
- const wchar_t * cc_name_2);
-
-int
-khm_krb5_parse_boolean(const char *s, khm_boolean * b);
-
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+/* Adapted from multiple Leash header files */
+
+#ifndef __KHIMAIRA_KRB5FUNCS_H
+#define __KHIMAIRA_KRB5FUNCS_H
+
+#include<stdlib.h>
+#include<krb5.h>
+
+#include <windows.h>
+#define SECURITY_WIN32
+#include <security.h>
+
+#if _WIN32_WINNT < 0x0501
+#define KHM_SAVE_WIN32_WINNT _WIN32_WINNT
+#undef _WIN32_WINNT
+#define _WIN32_WINNT 0x0501
+#endif
+#include<ntsecapi.h>
+#ifdef KHM_SAVE_WIN32_WINNT
+#undef _WIN32_WINNT
+#define _WIN32_WINNT KHM_SAVE_WIN32_WINNT
+#undef KHM_SAVE_WIN32_WINNT
+#endif
+
+#include <krb5common.h>
+
+#define LEASH_DEBUG_CLASS_GENERIC 0
+#define LEASH_DEBUG_CLASS_KRB4 1
+#define LEASH_DEBUG_CLASS_KRB4_APP 2
+
+#define LEASH_PRIORITY_LOW 0
+#define LEASH_PRIORITY_HIGH 1
+
+#define KRB5_DEFAULT_LIFE 60*60*10 /* 10 hours */
+
+#define KRB5_MAXCCH_CCNAME 1024
+
+#define KRB5_CONF_YES "yes"
+#define KRB5_CONF_NO "no"
+
+typedef struct tag_k5params {
+
+ khm_int32 source_reg; /* flags indicating which fields were
+ retrieved using the registry */
+ khm_int32 source_prof; /* flags indicating which fields were
+ retrieved using krb5.ini */
+
+ khm_boolean renewable;
+ khm_boolean forwardable;
+ khm_boolean proxiable;
+ khm_boolean addressless;
+
+ khm_ui_4 publicIP;
+
+ krb5_deltat lifetime;
+ krb5_deltat lifetime_min;
+ krb5_deltat lifetime_max;
+
+ krb5_deltat renew_life;
+ krb5_deltat renew_life_min;
+ krb5_deltat renew_life_max;
+
+} k5_params;
+
+#define K5PARAM_F_RENEW 0x00000001
+#define K5PARAM_F_FORW 0x00000002
+#define K5PARAM_F_PROX 0x00000004
+#define K5PARAM_F_ADDL 0x00000008
+#define K5PARAM_F_PUBIP 0x00000010
+#define K5PARAM_F_LIFE 0x00000020
+#define K5PARAM_F_RLIFE 0x00000040
+#define K5PARAM_F_LIFE_L 0x00000080
+#define K5PARAM_F_LIFE_H 0x00000100
+#define K5PARAM_F_RLIFE_L 0x00000200
+#define K5PARAM_F_RLIFE_H 0x00000400
+
+#define K5PARAM_FM_ALL 0x000007ff
+#define K5PARAM_FM_PROF 0x0000007f
+
+/* Credential and principal operations */
+
+BOOL
+khm_krb5_ms2mit(char * match_princ,
+ BOOL match_realm,
+ BOOL save_creds,
+ khm_handle * ret_ident);
+
+int
+khm_krb5_kinit(krb5_context alt_ctx,
+ char * principal_name,
+ char * password,
+ char * ccache,
+ krb5_deltat lifetime,
+ DWORD forwardable,
+ DWORD proxiable,
+ krb5_deltat renew_life,
+ DWORD addressless,
+ DWORD publicIP,
+ krb5_prompter_fct prompter,
+ void * p_data);
+
+long
+khm_krb5_changepwd(char * principal,
+ char * password,
+ char * newpassword,
+ char** error_str);
+
+int
+khm_krb5_destroy_by_credset(khm_handle p_cs);
+
+int
+khm_krb5_destroy_identity(khm_handle identity);
+
+long
+khm_convert524(krb5_context ctx);
+
+int
+khm_krb5_renew_cred(khm_handle cred);
+
+int
+khm_krb5_renew_ident(khm_handle identity);
+
+long
+khm_krb5_list_tickets(krb5_context *krbv5Context);
+
+long
+khm_krb5_copy_ccache_by_name(krb5_context in_ctx,
+ wchar_t * wscc_dest,
+ wchar_t * wscc_src);
+
+long
+khm_krb5_get_temp_ccache(krb5_context ctx,
+ krb5_ccache * cc);
+
+khm_int32 KHMAPI
+khm_krb5_creds_is_equal(khm_handle vcred1, khm_handle vcred2, void * dummy);
+
+
+/* Configuration */
+
+BOOL
+khm_krb5_get_profile_file(LPSTR confname, UINT szConfname);
+
+BOOL
+khm_krb5_get_temp_profile_file(LPSTR confname, UINT szConfname);
+
+wchar_t *
+khm_krb5_get_default_realm(void);
+
+long
+khm_krb5_set_default_realm(wchar_t * realm);
+
+wchar_t *
+khm_krb5_get_realm_list(void);
+
+khm_int32
+khm_krb5_get_identity_config(khm_handle ident,
+ khm_int32 flags,
+ khm_handle * ret_csp);
+
+void
+khm_krb5_set_identity_flags(khm_handle identity,
+ khm_int32 flag_mask,
+ khm_int32 flag_value);
+
+khm_int32
+khm_krb5_get_identity_flags(khm_handle identity);
+
+khm_int32
+khm_krb5_set_identity_params(khm_handle ident, const k5_params * p);
+
+khm_int32
+khm_krb5_get_identity_params(khm_handle ident, k5_params * p);
+
+/* Utility */
+
+wchar_t *
+khm_get_realm_from_princ(wchar_t * princ);
+
+long
+khm_krb5_canon_cc_name(wchar_t * wcc_name,
+ size_t cb_cc_name);
+
+int
+khm_krb5_cc_name_cmp(const wchar_t * cc_name_1,
+ const wchar_t * cc_name_2);
+
+int
+khm_krb5_parse_boolean(const char *s, khm_boolean * b);
+
+#endif
diff --git a/src/windows/identity/plugins/krb5/krb5identpro.c b/src/windows/identity/plugins/krb5/krb5identpro.c
index 0072b967d2..4d1120f39b 100644
--- a/src/windows/identity/plugins/krb5/krb5identpro.c
+++ b/src/windows/identity/plugins/krb5/krb5identpro.c
@@ -1,1881 +1,1881 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<krbcred.h>
-#include<kherror.h>
-#include<khmsgtypes.h>
-#include<commctrl.h>
-#include<strsafe.h>
-#include<krb5.h>
-#include<assert.h>
-
-#define K5_NCID_UN_LABEL (KHUI_CW_ID_MIN + 0)
-#define K5_NCID_UN (KHUI_CW_ID_MIN + 1)
-#define K5_NCID_REALM_LABEL (KHUI_CW_ID_MIN + 2)
-#define K5_NCID_REALM (KHUI_CW_ID_MIN + 3)
-
-#define NC_UNCHANGE_TIMEOUT 3000
-#define NC_UNCHANGE_TIMER 2
-#define NC_REALMCHANGE_TIMEOUT NC_UNCHANGE_TIMEOUT
-#define NC_REALMCHANGE_TIMER 3
-
-typedef struct tag_k5_new_cred_data {
- HWND hw_username_label;
- HWND hw_username;
- HWND hw_realm_label;
- HWND hw_realm;
-} k5_new_cred_data;
-
-static
-void
-trim_str(wchar_t * s, khm_size cch) {
- wchar_t * c, * last_ws;
-
- for (c = s; *c && iswspace(*c) && ((khm_size)(c - s)) < cch; c++);
-
- if (((khm_size)(c - s)) >= cch)
- return;
-
- if (c != s && ((khm_size)(c - s)) < cch) {
-#if _MSC_VER >= 1400
- wmemmove_s(s, cch, c, cch - ((khm_size)(c - s)));
-#else
- memmove(s, c, (cch - ((khm_size)(c - s))) * sizeof(wchar_t));
-#endif
- }
-
- last_ws = NULL;
- for (c = s; *c && ((khm_size)(c - s)) < cch; c++) {
- if (!iswspace(*c))
- last_ws = NULL;
- else if (last_ws == NULL)
- last_ws = c;
- }
-
- if (last_ws)
- *last_ws = L'\0';
-}
-
-/* Runs in the UI thread */
-int
-k5_get_realm_from_nc(khui_new_creds * nc,
- wchar_t * buf,
- khm_size cch_buf) {
- k5_new_cred_data * d;
- khm_size s;
-
- d = (k5_new_cred_data *) nc->ident_aux;
- buf[0] = L'\0';
- GetWindowText(d->hw_realm, buf, (int) cch_buf);
- trim_str(buf, cch_buf);
-
- StringCchLength(buf, cch_buf, &s);
-
- return (int) s;
-}
-
-/* set the primary identity of a new credentials dialog depending on
- the selection of the username and realm
-
- Runs in the UI thread
-*/
-static void
-set_identity_from_ui(khui_new_creds * nc,
- k5_new_cred_data * d) {
- wchar_t un[KCDB_IDENT_MAXCCH_NAME];
- wchar_t * realm;
- khm_size cch;
- khm_size cch_left;
- khm_handle ident;
- LRESULT idx = CB_ERR;
- khm_int32 rv = KHM_ERROR_SUCCESS;
-
- cch = GetWindowTextLength(d->hw_username);
-
- /* we already set the max length of the edit control to be this.
- shouldn't exceed it unless the edit control is confused. */
- assert(cch < KCDB_IDENT_MAXCCH_NAME - 1);
-
- GetWindowText(d->hw_username, un, ARRAYLENGTH(un));
- trim_str(un, ARRAYLENGTH(un));
-
- realm = khm_get_realm_from_princ(un);
- if (realm) /* realm was specified */
- goto _set_ident;
-
- /* the cch we got from GetWindowTextLength can not be trusted to
- be exact. For caveats see MSDN for GetWindowTextLength. */
- StringCchLength(un, KCDB_IDENT_MAXCCH_NAME, &cch);
-
- if (cch >= KCDB_IDENT_MAXCCH_NAME - 3) {
- /* has to allow space for the '@' and at least a single
- character realm, and the NULL terminator. */
- rv = KHM_ERROR_TOO_LONG;
- goto _set_null_ident;
- }
-
- realm = un + cch; /* now points at terminating NULL */
- cch_left = KCDB_IDENT_MAXCCH_NAME - cch;
-
- *realm++ = L'@';
- *realm = L'\0';
- cch_left--;
-
- cch = GetWindowTextLength(d->hw_realm);
- if (cch == 0 || cch >= cch_left) {
- rv = KHM_ERROR_INVALID_NAME;
- goto _set_null_ident;
- }
-
- GetWindowText(d->hw_realm, realm, (int) cch_left);
- trim_str(realm, cch_left);
-
- _set_ident:
- if (KHM_FAILED(rv = kcdb_identity_create(un,
- KCDB_IDENT_FLAG_CREATE,
- &ident))) {
- goto _set_null_ident;
- }
-
- khui_cw_set_primary_id(nc, ident);
-
- kcdb_identity_release(ident);
- return;
-
- _set_null_ident:
- {
- khui_new_creds_by_type * nct = NULL;
- wchar_t cmsg[256];
-
- khui_cw_find_type(nc, credtype_id_krb5, &nct);
- if (nct && nct->hwnd_panel) {
-
- switch(rv) {
- case KHM_ERROR_TOO_LONG:
- LoadString(hResModule, IDS_NCERR_IDENT_TOO_LONG,
- cmsg, ARRAYLENGTH(cmsg));
- break;
-
- case KHM_ERROR_INVALID_NAME:
- LoadString(hResModule, IDS_NCERR_IDENT_INVALID,
- cmsg, ARRAYLENGTH(cmsg));
- break;
-
- default:
- LoadString(hResModule, IDS_NCERR_IDENT_UNKNOWN,
- cmsg, ARRAYLENGTH(cmsg));
- }
-
- SendMessage(nct->hwnd_panel,
- KHUI_WM_NC_NOTIFY,
- MAKEWPARAM(0, K5_SET_CRED_MSG),
- (LPARAM) cmsg);
- }
-
- khui_cw_set_primary_id(nc, NULL);
- }
- return;
-}
-
-/* runs in the UI thread */
-static BOOL
-update_crossfeed(khui_new_creds * nc,
- k5_new_cred_data * d,
- int ctrl_id_src) {
- wchar_t un[KCDB_IDENT_MAXCCH_NAME];
- wchar_t * un_realm;
- wchar_t realm[KCDB_IDENT_MAXCCH_NAME];
- khm_size cch;
- khm_size cch_left;
- int idx;
-
- cch = (khm_size) GetWindowTextLength(d->hw_username);
-#ifdef DEBUG
- assert(cch < KCDB_IDENT_MAXCCH_NAME);
-#endif
- if (cch == 0)
- return FALSE;
-
- GetWindowText(d->hw_username,
- un,
- ARRAYLENGTH(un));
- trim_str(un, ARRAYLENGTH(un));
-
- un_realm = khm_get_realm_from_princ(un);
-
- if (un_realm == NULL) {
- EnableWindow(d->hw_realm, TRUE);
- return FALSE;
- }
-
- if (ctrl_id_src == K5_NCID_UN) {
-
- idx = (int)SendMessage(d->hw_realm,
- CB_FINDSTRINGEXACT,
- (WPARAM) -1,
- (LPARAM) un_realm);
-
- if (idx != CB_ERR) {
- wchar_t srealm[KCDB_IDENT_MAXCCH_NAME];
-
- cch = SendMessage(d->hw_realm,
- CB_GETLBTEXTLEN,
- (WPARAM) idx,
- 0);
-
-#ifdef DEBUG
- assert(cch < ARRAYLENGTH(srealm) - 1);
-#endif
- SendMessage(d->hw_realm,
- CB_GETLBTEXT,
- (WPARAM) idx,
- (LPARAM) srealm);
-
- if (!_wcsicmp(srealm, un_realm) && wcscmp(srealm, un_realm)) {
- /* differ only by case */
-
- StringCchCopy(un_realm, ARRAYLENGTH(un) - (un_realm - un),
- srealm);
-
- SetWindowText(d->hw_username, un);
- }
- }
-
- SendMessage(d->hw_realm,
- CB_SELECTSTRING,
- (WPARAM) -1,
- (LPARAM) un_realm);
-
- SetWindowText(d->hw_realm,
- un_realm);
-
- if (GetFocus() == d->hw_realm) {
- HWND hw_next = GetNextDlgTabItem(nc->hwnd, d->hw_realm,
- FALSE);
- if (hw_next)
- SetFocus(hw_next);
- }
-
- EnableWindow(d->hw_realm, FALSE);
-
- return TRUE;
- }
- /* else... */
-
- cch_left = KCDB_IDENT_MAXCCH_NAME - (un_realm - un);
-
- cch = (khm_size) GetWindowTextLength(d->hw_realm);
-
-#ifdef DEBUG
- assert(cch < KCDB_IDENT_MAXCCH_NAME);
-#endif
- if (cch == 0)
- return FALSE;
-
- GetWindowText(d->hw_realm, realm,
- ARRAYLENGTH(realm));
- trim_str(realm, ARRAYLENGTH(realm));
-
- idx = (int)SendMessage(d->hw_realm,
- CB_FINDSTRINGEXACT,
- (WPARAM) -1,
- (LPARAM) realm);
-
- if (idx != CB_ERR) {
- wchar_t srealm[KCDB_IDENT_MAXCCH_NAME];
-
- SendMessage(d->hw_realm,
- CB_GETLBTEXT,
- (WPARAM) idx,
- (LPARAM) srealm);
-
- if (!_wcsicmp(srealm, realm) && wcscmp(srealm, realm)) {
- StringCbCopy(realm, sizeof(realm), srealm);
-
- SetWindowText(d->hw_realm, srealm);
- }
- }
-
- StringCchCopy(un_realm, cch_left, realm);
-
- SendMessage(d->hw_username,
- CB_SELECTSTRING,
- (WPARAM) -1,
- (LPARAM) un);
-
- SetWindowText(d->hw_username, un);
-
- return TRUE;
-}
-
-/* Handle window messages for the identity specifiers
-
- runs in UI thread */
-static LRESULT
-handle_wnd_msg(khui_new_creds * nc,
- HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam) {
- k5_new_cred_data * d;
-
- d = (k5_new_cred_data *) nc->ident_aux;
-
- switch(uMsg) {
- case WM_COMMAND:
- switch(wParam) {
- case MAKEWPARAM(K5_NCID_UN, CBN_EDITCHANGE):
- /* the username has changed. Instead of handling this
- for every keystroke, set a timer that elapses some
- time afterwards and then handle the event. */
- SetTimer(hwnd, NC_UNCHANGE_TIMER,
- NC_UNCHANGE_TIMEOUT, NULL);
- return TRUE;
-
- case MAKEWPARAM(K5_NCID_UN, CBN_KILLFOCUS):
- case MAKEWPARAM(K5_NCID_UN, CBN_CLOSEUP):
- KillTimer(hwnd, NC_UNCHANGE_TIMER);
-
- update_crossfeed(nc,d,K5_NCID_UN);
- set_identity_from_ui(nc,d);
- return TRUE;
-
- case MAKEWPARAM(K5_NCID_REALM,CBN_EDITCHANGE):
- SetTimer(hwnd, NC_REALMCHANGE_TIMER,
- NC_REALMCHANGE_TIMEOUT, NULL);
- return TRUE;
-
- case MAKEWPARAM(K5_NCID_REALM,CBN_KILLFOCUS):
- case MAKEWPARAM(K5_NCID_REALM,CBN_CLOSEUP):
- KillTimer(hwnd, NC_REALMCHANGE_TIMER);
-
- update_crossfeed(nc,d,K5_NCID_REALM);
- set_identity_from_ui(nc, d);
- return TRUE;
- }
- break;
-
- case WM_TIMER:
- if(wParam == NC_UNCHANGE_TIMER) {
- KillTimer(hwnd, NC_UNCHANGE_TIMER);
-
- update_crossfeed(nc, d, K5_NCID_UN);
- set_identity_from_ui(nc,d);
- return TRUE;
- } else if (wParam == NC_REALMCHANGE_TIMER) {
- KillTimer(hwnd, NC_REALMCHANGE_TIMER);
-
- update_crossfeed(nc, d, K5_NCID_REALM);
- set_identity_from_ui(nc, d);
- return TRUE;
- }
- break;
- }
- return FALSE;
-}
-
-/* UI Callback
-
- runs in UI thread */
-static LRESULT KHMAPI
-ui_cb(khui_new_creds * nc,
- UINT cmd,
- HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam) {
-
- k5_new_cred_data * d;
-
- d = (k5_new_cred_data *) nc->ident_aux;
-
- switch(cmd) {
- case WMNC_IDENT_INIT:
- {
- wchar_t defident[KCDB_IDENT_MAXCCH_NAME];
- wchar_t wbuf[1024];
- wchar_t * ms = NULL;
- wchar_t * t;
- wchar_t * defrealm = NULL;
- LRESULT lr;
- khm_size cb_ms;
- khm_size cb;
- HWND hw_parent;
- khm_int32 rv;
- khm_handle hident;
-
- hw_parent = (HWND) lParam;
- defident[0] = L'\0';
-
-#ifdef DEBUG
- assert(d == NULL);
- assert(hw_parent != NULL);
-#endif
-
- d = PMALLOC(sizeof(*d));
- assert(d);
- ZeroMemory(d, sizeof(*d));
-
- khui_cw_lock_nc(nc);
- nc->ident_aux = (LPARAM) d;
- khui_cw_unlock_nc(nc);
-
- LoadString(hResModule, IDS_NC_USERNAME,
- wbuf, ARRAYLENGTH(wbuf));
-
- d->hw_username_label = CreateWindow
- (L"STATIC",
- wbuf,
- SS_SIMPLE | WS_CHILD | WS_VISIBLE,
- 0, 0, 100, 100, /* bogus values */
- hw_parent,
- (HMENU) K5_NCID_UN_LABEL,
- hInstance,
- NULL);
- assert(d->hw_username_label != NULL);
-
- d->hw_username = CreateWindow
- (L"COMBOBOX",
- L"",
- CBS_DROPDOWN | CBS_AUTOHSCROLL | CBS_SORT |
- WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL,
- 0, 0, 100, 100, /* bogus values */
- hw_parent,
- (HMENU) K5_NCID_UN,
- hInstance,
- NULL);
- assert(d->hw_username != NULL);
-
- SendMessage(d->hw_username,
- CB_LIMITTEXT,
- (WPARAM)(KCDB_IDENT_MAXCCH_NAME - 1),
- 0);
-
- SendMessage(d->hw_username,
- CB_SETEXTENDEDUI,
- (WPARAM) TRUE,
- 0);
-
- khui_cw_add_control_row(nc,
- d->hw_username_label,
- d->hw_username,
- KHUI_CTRLSIZE_SMALL);
-
- LoadString(hResModule, IDS_NC_REALM,
- wbuf, ARRAYLENGTH(wbuf));
-
- d->hw_realm_label = CreateWindow
- (L"STATIC",
- wbuf,
- SS_SIMPLE | WS_CHILD | WS_VISIBLE,
- 0, 0, 100, 100, /* bogus */
- hw_parent,
- (HMENU) K5_NCID_REALM_LABEL,
- hInstance,
- NULL);
- assert(d->hw_realm_label != NULL);
-
- d->hw_realm = CreateWindow
- (L"COMBOBOX",
- L"",
- CBS_DROPDOWN | CBS_AUTOHSCROLL | CBS_SORT |
- WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL,
- 0, 0, 100, 100, /* bogus */
- hw_parent,
- (HMENU) K5_NCID_REALM,
- hInstance,
- NULL);
- assert(d->hw_realm != NULL);
-
- SendMessage(d->hw_realm,
- CB_LIMITTEXT,
- (WPARAM) (KCDB_IDENT_MAXCCH_NAME - 1),
- 0);
-
- SendMessage(d->hw_realm,
- CB_SETEXTENDEDUI,
- (WPARAM) TRUE,
- 0);
-
- khui_cw_add_control_row(nc,
- d->hw_realm_label,
- d->hw_realm,
- KHUI_CTRLSIZE_SMALL);
-
- /* add the LRU realms and principals to the dropdown
- lists */
- rv = khc_read_multi_string(csp_params,
- L"LRUPrincipals",
- NULL,
- &cb_ms);
-
- if (rv != KHM_ERROR_TOO_LONG || cb_ms <= sizeof(wchar_t) * 2)
- goto _add_lru_realms;
-
- ms = PMALLOC(cb_ms);
- assert(ms != NULL);
-
- cb = cb_ms;
- rv = khc_read_multi_string(csp_params,
- L"LRUPrincipals",
- ms,
- &cb);
-
- assert(KHM_SUCCEEDED(rv));
-
- /* the first of these is considered the default identity
- if no other default is known */
- StringCbCopy(defident, sizeof(defident), ms);
-
- t = ms;
- while(t && *t) {
- SendMessage(d->hw_username,
- CB_ADDSTRING,
- 0,
- (LPARAM) t);
-
- t = multi_string_next(t);
- }
-
- _add_lru_realms:
- /* add the default realm first */
- defrealm = khm_krb5_get_default_realm();
- if (defrealm) {
- SendMessage(d->hw_realm,
- CB_ADDSTRING,
- 0,
- (LPARAM) defrealm);
- }
-
- rv = khc_read_multi_string(csp_params,
- L"LRURealms",
- NULL,
- &cb);
-
- if (rv != KHM_ERROR_TOO_LONG)
- goto _done_adding_lru;
-
- if (ms != NULL) {
- if (cb_ms < cb) {
- PFREE(ms);
- ms = PMALLOC(cb);
- assert(ms);
- cb_ms = cb;
- }
- } else {
- ms = PMALLOC(cb);
- cb_ms = cb;
- }
-
- rv = khc_read_multi_string(csp_params,
- L"LRURealms",
- ms,
- &cb);
-
- assert(KHM_SUCCEEDED(rv));
-
- for (t = ms; t && *t; t = multi_string_next(t)) {
- lr = SendMessage(d->hw_realm,
- CB_FINDSTRINGEXACT,
- (WPARAM) -1,
- (LPARAM) t);
- if (lr != CB_ERR)
- continue;
-
- SendMessage(d->hw_realm,
- CB_ADDSTRING,
- 0,
- (LPARAM) t);
- }
- _done_adding_lru:
-
- {
- khm_int32 inc_realms = 0;
-
- if (KHM_FAILED(khc_read_int32(csp_params,
- L"UseFullRealmList",
- &inc_realms)) ||
- !inc_realms)
- goto _done_adding_all_realms;
- }
-
- if(ms)
- PFREE(ms);
-
- ms = khm_krb5_get_realm_list();
- if(ms) {
- for (t = ms; t && *t; t = multi_string_next(t)) {
- lr = SendMessage(d->hw_realm,
- CB_FINDSTRINGEXACT,
- (WPARAM) -1,
- (LPARAM) t);
- if (lr != CB_ERR)
- continue;
-
- SendMessage(d->hw_realm,
- CB_ADDSTRING,
- 0,
- (LPARAM) t);
- }
- }
- _done_adding_all_realms:
-
- /* set the current selection of the realms list */
- if (defrealm) {
- SendMessage(d->hw_realm,
- CB_SELECTSTRING,
- (WPARAM) -1,
- (LPARAM) defrealm);
- } else {
- SendMessage(d->hw_realm,
- CB_SETCURSEL,
- (WPARAM) 0,
- (LPARAM) 0);
- }
-
- if (defrealm)
- PFREE(defrealm);
-
- if (ms)
- PFREE(ms);
-
- /* now see about that default identity */
- if (nc->ctx.identity) {
- cb = sizeof(defident);
- kcdb_identity_get_name(nc->ctx.identity,
- defident,
- &cb);
- }
-
- if (defident[0] == L'\0' &&
- KHM_SUCCEEDED(kcdb_identity_get_default(&hident))) {
- cb = sizeof(defident);
- kcdb_identity_get_name(hident, defident, &cb);
- kcdb_identity_release(hident);
- }
-
- if (defident[0] == L'\0') {
- DWORD dw;
-
- dw = ARRAYLENGTH(defident);
- GetUserName(defident, &dw);
- }
-
- t = khm_get_realm_from_princ(defident);
- if (t) {
- /* there is a realm */
- assert(t != defident);
- *--t = L'\0';
- t++;
-
- SendMessage(d->hw_realm,
- CB_SELECTSTRING,
- (WPARAM) -1,
- (LPARAM) t);
-
- SendMessage(d->hw_realm,
- WM_SETTEXT,
- 0,
- (LPARAM) t);
- }
-
- if (defident[0] != L'\0') {
- /* there is a username */
- SendMessage(d->hw_username,
- CB_SELECTSTRING,
- (WPARAM) -1,
- (LPARAM) defident);
-
- SendMessage(d->hw_username,
- WM_SETTEXT,
- 0,
- (LPARAM) defident);
- }
-
- set_identity_from_ui(nc, d);
- }
- return TRUE;
-
- case WMNC_IDENT_WMSG:
- return handle_wnd_msg(nc, hwnd, uMsg, wParam, lParam);
-
- case WMNC_IDENT_EXIT:
- {
-#ifdef DEBUG
- assert(d != NULL);
-#endif
- khui_cw_lock_nc(nc);
- nc->ident_aux = 0;
- khui_cw_unlock_nc(nc);
-
- /* since we created all the windows as child windows of
- the new creds window, they will be destroyed when that
- window is destroyed. */
- PFREE(d);
- }
- return TRUE;
- }
- return FALSE;
-}
-
-static khm_int32
-k5_ident_validate_name(khm_int32 msg_type,
- khm_int32 msg_subtype,
- khm_ui_4 uparam,
- void * vparam) {
- krb5_principal princ = NULL;
- char princ_name[KCDB_IDENT_MAXCCH_NAME];
- kcdb_ident_name_xfer * nx;
- krb5_error_code code;
- wchar_t * atsign;
-
- nx = (kcdb_ident_name_xfer *) vparam;
-
- if(UnicodeStrToAnsi(princ_name, sizeof(princ_name),
- nx->name_src) == 0) {
- nx->result = KHM_ERROR_INVALID_NAME;
- return KHM_ERROR_SUCCESS;
- }
-
- assert(k5_identpro_ctx != NULL);
-
- code = pkrb5_parse_name(k5_identpro_ctx,
- princ_name,
- &princ);
-
- if (code) {
- nx->result = KHM_ERROR_INVALID_NAME;
- return KHM_ERROR_SUCCESS;
- }
-
- if (princ != NULL)
- pkrb5_free_principal(k5_identpro_ctx,
- princ);
-
- /* krb5_parse_name() accepts principal names with no realm or an
- empty realm. We don't. */
- atsign = wcschr(nx->name_src, L'@');
- if (atsign == NULL || atsign[1] == L'\0') {
- nx->result = KHM_ERROR_INVALID_NAME;
- } else {
- nx->result = KHM_ERROR_SUCCESS;
- }
-
- return KHM_ERROR_SUCCESS;
-}
-
-static void
-k5_update_last_default_identity(khm_handle ident) {
- wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
- khm_size cb;
-
- cb = sizeof(idname);
- if (KHM_FAILED(kcdb_identity_get_name(ident, idname, &cb)))
- return;
-
- assert(csp_params);
-
- khc_write_string(csp_params, L"LastDefaultIdent", idname);
-}
-
-static khm_int32
-k5_ident_set_default_int(khm_handle def_ident) {
- wchar_t id_ccname[KRB5_MAXCCH_CCNAME];
- khm_size cb;
- DWORD dw;
- LONG l;
- HKEY hk_ccname;
- DWORD dwType;
- DWORD dwSize;
- wchar_t reg_ccname[KRB5_MAXCCH_CCNAME];
-
-#ifdef DEBUG
- assert(def_ident != NULL);
-#endif
-
- cb = sizeof(id_ccname);
- if (KHM_FAILED(kcdb_identity_get_attr(def_ident, attr_id_krb5_ccname, NULL,
- id_ccname, &cb))) {
- khm_handle csp_ident = NULL;
- khm_handle csp_k5 = NULL;
-
- _reportf(L"The specified identity does not have the Krb5CCName property");
-
- cb = sizeof(id_ccname);
- if (KHM_SUCCEEDED(kcdb_identity_get_config(def_ident, 0, &csp_ident)) &&
- KHM_SUCCEEDED(khc_open_space(csp_ident, CSNAME_KRB5CRED, 0, &csp_k5)) &&
- KHM_SUCCEEDED(khc_read_string(csp_k5, L"DefaultCCName",
- id_ccname, &cb))) {
-
- _reportf(L"Found CC name in configuration [%s]", id_ccname);
- } else {
- /* last resort, use the name of the identity as the cc
- name */
- cb = sizeof(id_ccname);
- if (KHM_FAILED(kcdb_identity_get_name(def_ident, id_ccname, &cb))) {
- _reportf(L"Can't use name of identity as CCName");
- _end_task();
-
- id_ccname[0] = L'\0';
- }
- }
-
- if (csp_k5)
- khc_close_space(csp_k5);
- if (csp_ident)
- khc_close_space(csp_ident);
-
- if (id_ccname[0] == L'\0')
- return KHM_ERROR_INVALID_PARAM;
- }
-
- khm_krb5_canon_cc_name(id_ccname, sizeof(id_ccname));
-
- _reportf(L"Found Krb5CCName property : %s", id_ccname);
-
- StringCbLength(id_ccname, sizeof(id_ccname), &cb);
- cb += sizeof(wchar_t);
-
- _reportf(L"Setting default CC name in the registry");
-
- l = RegOpenKeyEx(HKEY_CURRENT_USER, L"Software\\MIT\\kerberos5", 0,
- KEY_READ | KEY_WRITE, &hk_ccname);
-
- if (l != ERROR_SUCCESS)
- l = RegCreateKeyEx(HKEY_CURRENT_USER, L"Software\\MIT\\kerberos5", 0,
- NULL, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE,
- NULL, &hk_ccname, &dw);
-
- if (l != ERROR_SUCCESS) {
- _reportf(L"Can't create registry key : %d", l);
- _end_task();
- return KHM_ERROR_UNKNOWN;
- }
-
- dwSize = sizeof(reg_ccname);
-
- l = RegQueryValueEx(hk_ccname, L"ccname", NULL, &dwType, (LPBYTE) reg_ccname,
- &dwSize);
-
- if (l != ERROR_SUCCESS ||
- dwType != REG_SZ ||
- khm_krb5_cc_name_cmp(reg_ccname, id_ccname)) {
-
- /* we have to write the new value in */
-
- l = RegSetValueEx(hk_ccname, L"ccname", 0, REG_SZ, (BYTE *) id_ccname,
- (DWORD) cb);
- }
-
- RegCloseKey(hk_ccname);
-
- if (l == ERROR_SUCCESS) {
- _reportf(L"Successfully set the default ccache");
- k5_update_last_default_identity(def_ident);
- return KHM_ERROR_SUCCESS;
- } else {
- _reportf(L"Can't set the registry value : %d", l);
- return KHM_ERROR_UNKNOWN;
- }
-}
-
-static khm_int32
-k5_ident_set_default(khm_int32 msg_type,
- khm_int32 msg_subtype,
- khm_ui_4 uparam,
- void * vparam) {
-
- /*
- Currently, setting the default identity simply sets the
- "ccname" registry value at "Software\MIT\kerberos5".
- */
-
- if (uparam) {
- /* an identity is being made default */
- khm_handle def_ident = (khm_handle) vparam;
- khm_int32 rv;
-
-#ifdef DEBUG
- assert(def_ident != NULL);
-#endif
-
- {
- wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
- khm_size cb;
-
- cb = sizeof(idname);
- kcdb_identity_get_name(def_ident, idname, &cb);
-
- _begin_task(0);
- _report_cs1(KHERR_DEBUG_1, L"Setting default identity [%1!s!]", _cstr(idname));
- _describe();
- }
-
- rv = k5_ident_set_default_int(def_ident);
-
- _end_task();
-
- return rv;
-
- } else {
- /* the default identity is being forgotten */
-
- /* we don't really do anything about this case */
- }
-
- return KHM_ERROR_SUCCESS;
-}
-
-static khm_int32
-k5_ident_get_ui_cb(khm_int32 msg_type,
- khm_int32 msg_subtype,
- khm_ui_4 uparam,
- void * vparam) {
- khui_ident_new_creds_cb * cb;
-
- cb = (khui_ident_new_creds_cb *) vparam;
-
- *cb = ui_cb;
-
- return KHM_ERROR_SUCCESS;
-}
-
-static khm_int32
-k5_ident_notify_create(khm_int32 msg_type,
- khm_int32 msg_subtype,
- khm_ui_4 uparam,
- void * vparam) {
-
- /* a new identity has been created. What we want to do at
- this point is to check if the identity belongs to krb5
- and to see if it is the default. */
-
- krb5_ccache cc = NULL;
- krb5_error_code code;
- krb5_principal princ = NULL;
- char * princ_nameA = NULL;
- wchar_t princ_nameW[KCDB_IDENT_MAXCCH_NAME];
- wchar_t id_nameW[KCDB_IDENT_MAXCCH_NAME];
- khm_size cb;
- khm_handle ident;
-
- /* if there is a default identity already, we assume we don't need
- to check this one. */
-
- khm_handle def_ident;
-
- if (KHM_SUCCEEDED(kcdb_identity_get_default(&def_ident))) {
- kcdb_identity_release(def_ident);
-
- return KHM_ERROR_SUCCESS;
- }
-
- ident = (khm_handle) vparam;
-
- assert(k5_identpro_ctx != NULL);
-
- code = pkrb5_cc_default(k5_identpro_ctx, &cc);
- if (code)
- goto _nc_cleanup;
-
- code = pkrb5_cc_get_principal(k5_identpro_ctx,
- cc,
- &princ);
- if (code)
- goto _nc_cleanup;
-
- code = pkrb5_unparse_name(k5_identpro_ctx,
- princ,
- &princ_nameA);
- if (code)
- goto _nc_cleanup;
-
- AnsiStrToUnicode(princ_nameW,
- sizeof(princ_nameW),
- princ_nameA);
-
- cb = sizeof(id_nameW);
-
- if (KHM_FAILED(kcdb_identity_get_name(ident,
- id_nameW,
- &cb)))
- goto _nc_cleanup;
-
- if (!wcscmp(id_nameW, princ_nameW)) {
- kcdb_identity_set_default_int(ident);
- }
-
- _nc_cleanup:
- if (princ_nameA)
- pkrb5_free_unparsed_name(k5_identpro_ctx,
- princ_nameA);
- if (princ)
- pkrb5_free_principal(k5_identpro_ctx,
- princ);
- if (cc)
- pkrb5_cc_close(k5_identpro_ctx, cc);
-
- return KHM_ERROR_SUCCESS;
-}
-
-struct k5_ident_update_data {
- khm_handle identity;
-
- FILETIME ft_expire; /* expiration */
- FILETIME ft_issue; /* issue */
- FILETIME ft_rexpire; /* renew expiration */
- wchar_t ccname[KRB5_MAXCCH_CCNAME];
- khm_int32 k5_flags;
-};
-
-/* The logic here has to reflect the logic in khm_krb5_list_tickets().
- We use this to handle an identity update request because some other
- plug-in or maybe NetIDMgr itself is about to do something
- important(tm) with the identity and needs to make sure that the
- properties of the identity are up-to-date. */
-static khm_int32 KHMAPI
-k5_ident_update_apply_proc(khm_handle cred,
- void * rock) {
- struct k5_ident_update_data * d = (struct k5_ident_update_data *) rock;
- khm_handle ident = NULL;
- khm_int32 t;
- khm_int32 flags;
- FILETIME t_cexpire;
- FILETIME t_rexpire;
- khm_size cb;
- khm_int32 rv = KHM_ERROR_SUCCESS;
-
- if (KHM_FAILED(kcdb_cred_get_type(cred, &t)) ||
- t != credtype_id_krb5 ||
- KHM_FAILED(kcdb_cred_get_identity(cred, &ident)))
-
- return KHM_ERROR_SUCCESS;
-
- if (!kcdb_identity_is_equal(ident,d->identity))
-
- goto _cleanup;
-
- if (KHM_FAILED(kcdb_cred_get_flags(cred, &flags)))
-
- flags = 0;
-
- if (flags & KCDB_CRED_FLAG_INITIAL) {
- cb = sizeof(t_cexpire);
- if (KHM_SUCCEEDED(kcdb_cred_get_attr(cred,
- KCDB_ATTR_EXPIRE,
- NULL,
- &t_cexpire,
- &cb))) {
- if ((d->ft_expire.dwLowDateTime == 0 &&
- d->ft_expire.dwHighDateTime == 0) ||
- CompareFileTime(&t_cexpire, &d->ft_expire) > 0) {
- goto update_identity;
- }
- }
- }
-
- goto _cleanup;
-
- update_identity:
-
- d->ft_expire = t_cexpire;
-
- cb = sizeof(d->ccname);
- if (KHM_FAILED(kcdb_cred_get_attr(cred, KCDB_ATTR_LOCATION, NULL, d->ccname, &cb))) {
- d->ccname[0] = L'\0';
- }
-
- cb = sizeof(d->k5_flags);
- if (KHM_FAILED(kcdb_cred_get_attr(cred, attr_id_krb5_flags, NULL,
- &d->k5_flags, &cb))) {
- d->k5_flags = 0;
- }
-
- cb = sizeof(d->ft_issue);
- if (KHM_FAILED(kcdb_cred_get_attr(cred, KCDB_ATTR_ISSUE, NULL, &d->ft_issue, &cb))) {
- ZeroMemory(&d->ft_issue, sizeof(d->ft_issue));
- }
-
- cb = sizeof(t_rexpire);
- if ((d->k5_flags & TKT_FLG_RENEWABLE) &&
- KHM_SUCCEEDED(kcdb_cred_get_attr(cred,
- KCDB_ATTR_RENEW_EXPIRE,
- NULL,
- &t_rexpire,
- &cb))) {
- d->ft_rexpire = t_rexpire;
- } else {
- ZeroMemory(&d->ft_rexpire, sizeof(d->ft_rexpire));
- }
-
- _cleanup:
- if (ident)
- kcdb_identity_release(ident);
-
- return rv;
-}
-
-static khm_int32
-k5_ident_update(khm_int32 msg_type,
- khm_int32 msg_subtype,
- khm_ui_4 uparam,
- void * vparam) {
-
-#if 0
- struct k5_ident_update_data d;
-#endif
- khm_handle ident;
- khm_handle tident;
- krb5_ccache cc = NULL;
- char * ccname;
- krb5_error_code code;
- khm_size cb;
- wchar_t wid_ccname[MAX_PATH];
- wchar_t w_ccname[MAX_PATH];
-
- ident = (khm_handle) vparam;
- if (ident == NULL)
- return KHM_ERROR_SUCCESS;
-
-#if 0
- /* we are going to skip doing this here since
- khm_krb5_list_tickets() performs this function for us each time
- we enumerate tickets. Since it also gets run each time our
- list of tickets changes and since we are basing this operation
- on existing tickets, we are unlikely to find anything new
- here. */
- ZeroMemory(&d, sizeof(d));
- d.identity = ident;
-
- kcdb_credset_apply(NULL,
- k5_ident_update_apply_proc,
- (void *) &d);
-
- if (d.ft_expire.dwLowDateTime != 0 ||
- d.ft_expire.dwHighDateTime != 0) {
-
- /* we found a TGT */
-
- kcdb_identity_set_attr(ident, KCDB_ATTR_EXPIRE,
- &d.ft_expire, sizeof(d.ft_expire));
- if (d.ft_issue.dwLowDateTime != 0 ||
- d.ft_issue.dwHighDateTime != 0)
- kcdb_identity_set_attr(ident, KCDB_ATTR_ISSUE,
- &d.ft_issue, sizeof(d.ft_issue));
- else
- kcdb_identity_set_attr(ident, KCDB_ATTR_ISSUE, NULL, 0);
-
- if (d.ft_rexpire.dwLowDateTime != 0 ||
- d.ft_rexpire.dwHighDateTime != 0)
- kcdb_identity_set_attr(ident, KCDB_ATTR_RENEW_EXPIRE,
- &d.ft_rexpire, sizeof(d.ft_rexpire));
- else
- kcdb_identity_set_attr(ident, KCDB_ATTR_RENEW_EXPIRE, NULL, 0);
-
- kcdb_identity_set_attr(ident, attr_id_krb5_flags,
- &d.k5_flags, sizeof(d.k5_flags));
-
- if (d.ccname[0])
- kcdb_identity_set_attr(ident, attr_id_krb5_ccname,
- d.ccname, KCDB_CBSIZE_AUTO);
- else
- kcdb_identity_set_attr(ident, attr_id_krb5_ccname, NULL, 0);
-
- } else {
- /* Clear out the attributes. We don't have any information
- about this identity */
- kcdb_identity_set_attr(ident, KCDB_ATTR_EXPIRE, NULL, 0);
- kcdb_identity_set_attr(ident, KCDB_ATTR_ISSUE, NULL, 0);
- kcdb_identity_set_attr(ident, KCDB_ATTR_RENEW_EXPIRE, NULL, 0);
- kcdb_identity_set_attr(ident, attr_id_krb5_flags, NULL, 0);
- kcdb_identity_set_attr(ident, attr_id_krb5_ccname, NULL, 0);
- }
-#endif
-
- if (KHM_SUCCEEDED(kcdb_identity_get_default(&tident))) {
- kcdb_identity_release(tident);
- goto _iu_cleanup;
- }
-
- cb = sizeof(wid_ccname);
- if (KHM_FAILED(kcdb_identity_get_attr(ident,
- attr_id_krb5_ccname,
- NULL,
- wid_ccname,
- &cb)))
- goto _iu_cleanup;
-
- if(k5_identpro_ctx == NULL)
- goto _iu_cleanup;
-
- code = pkrb5_cc_default(k5_identpro_ctx, &cc);
- if (code)
- goto _iu_cleanup;
-
- ccname = pkrb5_cc_get_name(k5_identpro_ctx, cc);
- if (ccname == NULL)
- goto _iu_cleanup;
-
- AnsiStrToUnicode(w_ccname, sizeof(w_ccname), ccname);
-
- khm_krb5_canon_cc_name(w_ccname, sizeof(w_ccname));
- khm_krb5_canon_cc_name(wid_ccname, sizeof(wid_ccname));
-
- if (!_wcsicmp(w_ccname, wid_ccname))
- kcdb_identity_set_default_int(ident);
-
- _iu_cleanup:
- if (cc && k5_identpro_ctx)
- pkrb5_cc_close(k5_identpro_ctx, cc);
-
- return KHM_ERROR_SUCCESS;
-}
-
-static khm_boolean
-k5_refresh_default_identity(krb5_context ctx) {
- /* just like notify_create, except now we set the default identity
- based on what we find in the configuration */
- krb5_ccache cc = NULL;
- krb5_error_code code;
- krb5_principal princ = NULL;
- char * princ_nameA = NULL;
- wchar_t princ_nameW[KCDB_IDENT_MAXCCH_NAME];
- char * ccname = NULL;
- khm_handle ident = NULL;
- khm_boolean found_default = FALSE;
-
- assert(ctx != NULL);
-
- _begin_task(0);
- _report_cs0(KHERR_DEBUG_1, L"Refreshing default identity");
- _describe();
-
- code = pkrb5_cc_default(ctx, &cc);
- if (code) {
- _reportf(L"Can't open default ccache. code=%d", code);
- goto _nc_cleanup;
- }
-
- code = pkrb5_cc_get_principal(ctx, cc, &princ);
- if (code) {
- /* try to determine the identity from the ccache name */
- ccname = pkrb5_cc_get_name(ctx, cc);
-
- if (ccname) {
- char * namepart = strchr(ccname, ':');
-
- _reportf(L"CC name is [%S]", ccname);
-
- if (namepart == NULL)
- namepart = ccname;
- else
- namepart++;
-
- _reportf(L"Checking if [%S] is a valid identity name", namepart);
-
- AnsiStrToUnicode(princ_nameW, sizeof(princ_nameW), namepart);
- if (kcdb_identity_is_valid_name(princ_nameW)) {
- kcdb_identity_create(princ_nameW, KCDB_IDENT_FLAG_CREATE, &ident);
- if (ident) {
- _reportf(L"Setting [%S] as the default identity", namepart);
- kcdb_identity_set_default_int(ident);
- found_default = TRUE;
- }
- }
- } else {
- _reportf(L"Can't determine ccache name");
- }
-
- goto _nc_cleanup;
- }
-
- code = pkrb5_unparse_name(ctx, princ, &princ_nameA);
- if (code)
- goto _nc_cleanup;
-
- AnsiStrToUnicode(princ_nameW, sizeof(princ_nameW), princ_nameA);
-
- _reportf(L"Found principal [%s]", princ_nameW);
-
- if (KHM_FAILED(kcdb_identity_create(princ_nameW, KCDB_IDENT_FLAG_CREATE, &ident))) {
- _reportf(L"Failed to create identity");
- goto _nc_cleanup;
- }
-
- _reportf(L"Setting default identity to [%s]", princ_nameW);
- kcdb_identity_set_default_int(ident);
-
- found_default = TRUE;
-
- _nc_cleanup:
-
- _end_task();
-
- if (princ_nameA)
- pkrb5_free_unparsed_name(ctx, princ_nameA);
-
- if (princ)
- pkrb5_free_principal(ctx, princ);
-
- if (cc)
- pkrb5_cc_close(ctx, cc);
-
- if (ident)
- kcdb_identity_release(ident);
-
- return found_default;
-}
-
-static khm_int32
-k5_ident_init(khm_int32 msg_type,
- khm_int32 msg_subtype,
- khm_ui_4 uparam,
- void * vparam) {
-
- khm_boolean found_default;
- khm_handle ident;
-
- found_default = k5_refresh_default_identity(k5_identpro_ctx);
-
- if (!found_default) {
- wchar_t widname[KCDB_IDENT_MAXCCH_NAME];
- khm_size cb;
-
- cb = sizeof(widname);
-
- assert(csp_params);
-
- if (KHM_SUCCEEDED(khc_read_string(csp_params, L"LastDefaultIdent",
- widname, &cb))) {
- ident = NULL;
- kcdb_identity_create(widname, KCDB_IDENT_FLAG_CREATE, &ident);
- if (ident) {
- kcdb_identity_set_default_int(ident);
- kcdb_identity_release(ident);
-
- found_default = TRUE;
- }
- }
- }
-
- if (!found_default) {
-
- /* There was no default ccache and we don't have a
- "LastDefaultIdent" value. Next we see if there are any
- identities that have credentials which have a Krb5CCName
- property (i.e. an identity that has a Kerberos 5 TGT), and
- make it the default.
-
- Note that since the Krb5Ident plug-in has a dependency on
- Krb5Cred, by the time this code runs, we already have a
- listing of Kerberos 5 tickets and identities. */
-
- wchar_t * idlist = NULL;
- wchar_t * thisid;
- khm_size cb = 0;
- khm_size n_idents = 0;
- khm_int32 rv;
- wchar_t ccname[KRB5_MAXCCH_CCNAME];
- FILETIME ft_expire;
- FILETIME ft_now;
- FILETIME ft_threshold;
- BOOL match_all = FALSE;
-
- rv = kcdb_identity_enum(0, 0, NULL, &cb, &n_idents);
-
- TimetToFileTimeInterval(5 * 60, &ft_threshold);
- GetSystemTimeAsFileTime(&ft_now);
- ft_now = FtAdd(&ft_now, &ft_threshold);
-
- while (rv == KHM_ERROR_TOO_LONG && n_idents > 0) {
- if (idlist) {
- PFREE(idlist);
- idlist = NULL;
- }
-
- idlist = PMALLOC(cb);
-
- if (idlist == NULL)
- break;
-
- rv = kcdb_identity_enum(0, 0, idlist, &cb, &n_idents);
- }
-
- if (KHM_SUCCEEDED(rv)) {
-
- /* first we try to find an identity that has a valid TGT.
- If that fails, then we try to find an identity with
- *any* TGT. */
-
- try_again:
-
- for (thisid = idlist;
- thisid && *thisid && !found_default;
- thisid = multi_string_next(thisid)) {
-
- if (KHM_SUCCEEDED(kcdb_identity_create(thisid, 0, &ident))) {
- khm_size cb_ft = sizeof(FILETIME);
- cb = sizeof(ccname);
-
- if (KHM_SUCCEEDED(kcdb_identity_get_attr(ident, attr_id_krb5_ccname,
- NULL, ccname, &cb)) &&
- (match_all ||
- (KHM_SUCCEEDED(kcdb_identity_get_attr(ident, KCDB_ATTR_EXPIRE,
- NULL, &ft_expire, &cb_ft)) &&
- CompareFileTime(&ft_expire, &ft_now) > 0))) {
-
- /* found one */
- k5_ident_set_default_int(ident);
- kcdb_identity_set_default_int(ident);
- found_default = TRUE;
-
- }
-
- kcdb_identity_release(ident);
- ident = NULL;
- }
- }
-
- if (!found_default && !match_all) {
- match_all = TRUE;
- goto try_again;
- }
- }
-
- if (idlist) {
- PFREE(idlist);
- idlist = NULL;
- }
- }
-
- return KHM_ERROR_SUCCESS;
-}
-
-static khm_int32
-k5_ident_exit(khm_int32 msg_type,
- khm_int32 msg_subtype,
- khm_ui_4 uparam,
- void * vparam) {
- /* don't really do anything */
- return KHM_ERROR_SUCCESS;
-}
-
-/* forward dcl */
-khm_int32 KHMAPI
-k5_ident_name_comp_func(const void * dl, khm_size cb_dl,
- const void * dr, khm_size cb_dr);
-
-static khm_int32
-k5_ident_compare_name(khm_int32 msg_type,
- khm_int32 msg_subtype,
- khm_ui_4 uparam,
- void * vparam) {
- kcdb_ident_name_xfer *px;
-
- px = (kcdb_ident_name_xfer *) vparam;
-
- /* note that k5_ident_name_comp_func() ignores the size
- specifiers. So we can just pass in 0's. */
- px->result = k5_ident_name_comp_func(px->name_src, 0,
- px->name_alt, 0);
-
- return KHM_ERROR_SUCCESS;
-}
-
-#if 0
-/* copy and paste template for ident provider messages */
-static khm_int32
-k5_ident_(khm_int32 msg_type,
- khm_int32 msg_subtype,
- khm_ui_4 uparam,
- void * vparam) {
-}
-#endif
-
-khm_int32 KHMAPI
-k5_msg_ident(khm_int32 msg_type,
- khm_int32 msg_subtype,
- khm_ui_4 uparam,
- void * vparam)
-{
- switch(msg_subtype) {
- case KMSG_IDENT_INIT:
- return k5_ident_init(msg_type,
- msg_subtype,
- uparam,
- vparam);
-
- case KMSG_IDENT_EXIT:
- return k5_ident_exit(msg_type,
- msg_subtype,
- uparam,
- vparam);
-
- case KMSG_IDENT_VALIDATE_NAME:
- return k5_ident_validate_name(msg_type,
- msg_subtype,
- uparam,
- vparam);
-
- case KMSG_IDENT_VALIDATE_IDENTITY:
- /* TODO: handle KMSG_IDENT_VALIDATE_IDENTITY */
- break;
-
- case KMSG_IDENT_CANON_NAME:
- /* TODO: handle KMSG_IDENT_CANON_NAME */
- break;
-
- case KMSG_IDENT_COMPARE_NAME:
- return k5_ident_compare_name(msg_type,
- msg_subtype,
- uparam,
- vparam);
-
- case KMSG_IDENT_SET_DEFAULT:
- return k5_ident_set_default(msg_type,
- msg_subtype,
- uparam,
- vparam);
-
- case KMSG_IDENT_SET_SEARCHABLE:
- /* TODO: handle KMSG_IDENT_SET_SEARCHABLE */
- break;
-
- case KMSG_IDENT_GET_INFO:
- /* TODO: handle KMSG_IDENT_GET_INFO */
- break;
-
- case KMSG_IDENT_UPDATE:
- return k5_ident_update(msg_type,
- msg_subtype,
- uparam,
- vparam);
-
- case KMSG_IDENT_ENUM_KNOWN:
- /* TODO: handle KMSG_IDENT_ENUM_KNOWN */
- break;
-
- case KMSG_IDENT_GET_UI_CALLBACK:
- return k5_ident_get_ui_cb(msg_type,
- msg_subtype,
- uparam,
- vparam);
-
- case KMSG_IDENT_NOTIFY_CREATE:
- return k5_ident_notify_create(msg_type,
- msg_subtype,
- uparam,
- vparam);
- }
-
- return KHM_ERROR_SUCCESS;
-}
-
-/* note that we are ignoring the size specifiers. We can do that
- because we are guaranteed that dl and dr point to NULL terminated
- unicode strings when used with credential data buffers. We also
- use the fact that we are ignoring the size specifiers when we call
- this function from k5_ident_compare_name() to avoid calculating the
- length of the string. */
-khm_int32 KHMAPI
-k5_ident_name_comp_func(const void * dl, khm_size cb_dl,
- const void * dr, khm_size cb_dr) {
- wchar_t * idl = (wchar_t *) dl;
- wchar_t * idr = (wchar_t *) dr;
- wchar_t * rl;
- wchar_t * rr;
- khm_int32 r;
-
- rl = khm_get_realm_from_princ(idl);
- rr = khm_get_realm_from_princ(idr);
-
- if (rl == NULL && rr == NULL)
- return wcscmp(idl, idr);
- else if (rl == NULL)
- return 1;
- else if (rr == NULL)
- return -1;
-
- r = wcscmp(rl, rr);
- if (r == 0)
- return wcscmp(idl, idr);
- else
- return r;
-}
-
-
-/* Identity change notification thread */
-
-HANDLE h_ccname_exit_event;
-HANDLE h_ccname_thread;
-
-DWORD WINAPI k5_ccname_monitor_thread(LPVOID lpParameter) {
- krb5_context ctx = 0;
-
- HKEY hk_ccname;
- HANDLE h_notify;
- HANDLE h_waits[2];
-
- khm_int32 rv = KHM_ERROR_SUCCESS;
- DWORD dwType;
- DWORD dwSize;
- DWORD dwDisp;
- wchar_t reg_ccname[KRB5_MAXCCH_CCNAME];
- LONG l;
-
- PDESCTHREAD(L"Krb5 CCName Monitor", L"Krb5");
-
- l = RegOpenKeyEx(HKEY_CURRENT_USER,
- L"Software\\MIT\\kerberos5",
- 0,
- KEY_READ | KEY_WRITE,
- &hk_ccname);
-
- if (l != ERROR_SUCCESS)
- l = RegCreateKeyEx(HKEY_CURRENT_USER,
- L"Software\\MIT\\kerberos5",
- 0,
- NULL,
- REG_OPTION_NON_VOLATILE,
- KEY_READ | KEY_WRITE,
- NULL,
- &hk_ccname,
- &dwDisp);
-
- if (l != ERROR_SUCCESS) {
- rv = KHM_ERROR_UNKNOWN;
- goto _exit;
- }
-
- dwSize = sizeof(reg_ccname);
-
- l = RegQueryValueEx(hk_ccname,
- L"ccname",
- NULL,
- &dwType,
- (LPBYTE) reg_ccname,
- &dwSize);
-
- if (l != ERROR_SUCCESS ||
- dwType != REG_SZ) {
-
- reg_ccname[0] = L'\0';
- }
-
- l = pkrb5_init_context(&ctx);
-
- if (l)
- goto _exit_0;
-
- h_notify = CreateEvent(NULL, FALSE, FALSE, L"Local\\Krb5CCNameChangeNotifier");
-
- if (h_notify == NULL)
- goto _exit_0;
-
- /* begin wait loop */
-
- h_waits[0] = h_ccname_exit_event;
- h_waits[1] = h_notify;
-
- do {
- DWORD dwrv;
-
- l = RegNotifyChangeKeyValue(hk_ccname, FALSE,
- REG_NOTIFY_CHANGE_LAST_SET,
- h_notify, TRUE);
-
- if (l != ERROR_SUCCESS) {
- rv = KHM_ERROR_UNKNOWN;
- break;
- }
-
- dwrv = WaitForMultipleObjects(2, h_waits, FALSE, INFINITE);
-
- if (dwrv == WAIT_OBJECT_0) {
- /* exit! */
- break;
-
- } else if (dwrv == WAIT_OBJECT_0 + 1) {
- /* change notify! */
- wchar_t new_ccname[KRB5_MAXCCH_CCNAME];
-
- dwSize = sizeof(new_ccname);
-
- l = RegQueryValueEx(hk_ccname,
- L"ccname",
- NULL,
- &dwType,
- (LPBYTE) new_ccname,
- &dwSize);
-
- if (l != ERROR_SUCCESS ||
- dwType != REG_SZ) {
- new_ccname[0] = L'\0';
- }
-
- if (_wcsicmp(new_ccname, reg_ccname)) {
- k5_refresh_default_identity(ctx);
- StringCbCopy(reg_ccname, sizeof(reg_ccname), new_ccname);
- }
-
- } else {
- /* something went wrong */
- rv = KHM_ERROR_UNKNOWN;
- break;
- }
-
- } while (TRUE);
-
- CloseHandle(h_notify);
-
- _exit_0:
-
- RegCloseKey(hk_ccname);
-
- if (ctx)
- pkrb5_free_context(ctx);
-
- _exit:
- ExitThread(rv);
-
- /* not reached */
- return rv;
-}
-
-khm_int32
-k5_msg_system_idpro(khm_int32 msg_type, khm_int32 msg_subtype,
- khm_ui_4 uparam, void * vparam) {
-
- switch(msg_subtype) {
- case KMSG_SYSTEM_INIT:
- {
-
- pkrb5_init_context(&k5_identpro_ctx);
- kcdb_identity_set_type(credtype_id_krb5);
-
- if (KHM_FAILED(kcdb_type_get_id(TYPENAME_KRB5_PRINC,
- &type_id_krb5_princ))) {
- kcdb_type dt;
- kcdb_type * pstr;
-
- kcdb_type_get_info(KCDB_TYPE_STRING, &pstr);
-
- ZeroMemory(&dt, sizeof(dt));
- dt.name = TYPENAME_KRB5_PRINC;
- dt.id = KCDB_TYPE_INVALID;
- dt.flags = KCDB_TYPE_FLAG_CB_AUTO;
- dt.cb_min = pstr->cb_min;
- dt.cb_max = pstr->cb_max;
- dt.toString = pstr->toString;
- dt.isValid = pstr->isValid;
- dt.comp = k5_ident_name_comp_func;
- dt.dup = pstr->dup;
-
- kcdb_type_register(&dt, &type_id_krb5_princ);
-
- type_regd_krb5_princ = TRUE;
-
- kcdb_type_release_info(pstr);
- }
-
- if (type_id_krb5_princ != -1) {
- kcdb_attrib * attr;
-
- kcdb_attrib_get_info(KCDB_ATTR_ID_NAME, &attr);
-
- attr->type = type_id_krb5_princ;
-
- kcdb_attrib_release_info(attr);
- }
-
- h_ccname_exit_event = CreateEvent(NULL, FALSE, FALSE, NULL);
- if (h_ccname_exit_event) {
- h_ccname_thread = CreateThread(NULL,
- 200 * 1024,
- k5_ccname_monitor_thread,
- NULL,
- 0,
- NULL);
- } else {
- h_ccname_thread = NULL;
- }
- }
- break;
-
- case KMSG_SYSTEM_EXIT:
- {
-
- if (h_ccname_thread) {
- SetEvent(h_ccname_exit_event);
- WaitForSingleObject(h_ccname_thread, INFINITE);
- CloseHandle(h_ccname_thread);
- CloseHandle(h_ccname_exit_event);
-
- h_ccname_exit_event = NULL;
- h_ccname_thread = NULL;
- }
-
- if (k5_identpro_ctx) {
- pkrb5_free_context(k5_identpro_ctx);
- k5_identpro_ctx = NULL;
- }
-
- if (type_id_krb5_princ != -1) {
- kcdb_attrib * attr;
-
- kcdb_attrib_get_info(KCDB_ATTR_ID_NAME, &attr);
-
- attr->type = KCDB_TYPE_STRING;
-
- kcdb_attrib_release_info(attr);
- }
-
- /* allow a brief moment for any stale references to die */
- Sleep(100);
-
- if (type_regd_krb5_princ) {
- kcdb_type_unregister(type_id_krb5_princ);
- }
- }
- break;
- }
-
- return KHM_ERROR_SUCCESS;
-}
-
-khm_int32 KHMAPI
-k5_ident_callback(khm_int32 msg_type, khm_int32 msg_subtype,
- khm_ui_4 uparam, void * vparam) {
- switch(msg_type) {
- case KMSG_SYSTEM:
- return k5_msg_system_idpro(msg_type, msg_subtype, uparam, vparam);
-
- case KMSG_IDENT:
- return k5_msg_ident(msg_type, msg_subtype, uparam, vparam);
- }
-
- return KHM_ERROR_SUCCESS;
-}
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<krbcred.h>
+#include<kherror.h>
+#include<khmsgtypes.h>
+#include<commctrl.h>
+#include<strsafe.h>
+#include<krb5.h>
+#include<assert.h>
+
+#define K5_NCID_UN_LABEL (KHUI_CW_ID_MIN + 0)
+#define K5_NCID_UN (KHUI_CW_ID_MIN + 1)
+#define K5_NCID_REALM_LABEL (KHUI_CW_ID_MIN + 2)
+#define K5_NCID_REALM (KHUI_CW_ID_MIN + 3)
+
+#define NC_UNCHANGE_TIMEOUT 3000
+#define NC_UNCHANGE_TIMER 2
+#define NC_REALMCHANGE_TIMEOUT NC_UNCHANGE_TIMEOUT
+#define NC_REALMCHANGE_TIMER 3
+
+typedef struct tag_k5_new_cred_data {
+ HWND hw_username_label;
+ HWND hw_username;
+ HWND hw_realm_label;
+ HWND hw_realm;
+} k5_new_cred_data;
+
+static
+void
+trim_str(wchar_t * s, khm_size cch) {
+ wchar_t * c, * last_ws;
+
+ for (c = s; *c && iswspace(*c) && ((khm_size)(c - s)) < cch; c++);
+
+ if (((khm_size)(c - s)) >= cch)
+ return;
+
+ if (c != s && ((khm_size)(c - s)) < cch) {
+#if _MSC_VER >= 1400
+ wmemmove_s(s, cch, c, cch - ((khm_size)(c - s)));
+#else
+ memmove(s, c, (cch - ((khm_size)(c - s))) * sizeof(wchar_t));
+#endif
+ }
+
+ last_ws = NULL;
+ for (c = s; *c && ((khm_size)(c - s)) < cch; c++) {
+ if (!iswspace(*c))
+ last_ws = NULL;
+ else if (last_ws == NULL)
+ last_ws = c;
+ }
+
+ if (last_ws)
+ *last_ws = L'\0';
+}
+
+/* Runs in the UI thread */
+int
+k5_get_realm_from_nc(khui_new_creds * nc,
+ wchar_t * buf,
+ khm_size cch_buf) {
+ k5_new_cred_data * d;
+ khm_size s;
+
+ d = (k5_new_cred_data *) nc->ident_aux;
+ buf[0] = L'\0';
+ GetWindowText(d->hw_realm, buf, (int) cch_buf);
+ trim_str(buf, cch_buf);
+
+ StringCchLength(buf, cch_buf, &s);
+
+ return (int) s;
+}
+
+/* set the primary identity of a new credentials dialog depending on
+ the selection of the username and realm
+
+ Runs in the UI thread
+*/
+static void
+set_identity_from_ui(khui_new_creds * nc,
+ k5_new_cred_data * d) {
+ wchar_t un[KCDB_IDENT_MAXCCH_NAME];
+ wchar_t * realm;
+ khm_size cch;
+ khm_size cch_left;
+ khm_handle ident;
+ LRESULT idx = CB_ERR;
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+
+ cch = GetWindowTextLength(d->hw_username);
+
+ /* we already set the max length of the edit control to be this.
+ shouldn't exceed it unless the edit control is confused. */
+ assert(cch < KCDB_IDENT_MAXCCH_NAME - 1);
+
+ GetWindowText(d->hw_username, un, ARRAYLENGTH(un));
+ trim_str(un, ARRAYLENGTH(un));
+
+ realm = khm_get_realm_from_princ(un);
+ if (realm) /* realm was specified */
+ goto _set_ident;
+
+ /* the cch we got from GetWindowTextLength can not be trusted to
+ be exact. For caveats see MSDN for GetWindowTextLength. */
+ StringCchLength(un, KCDB_IDENT_MAXCCH_NAME, &cch);
+
+ if (cch >= KCDB_IDENT_MAXCCH_NAME - 3) {
+ /* has to allow space for the '@' and at least a single
+ character realm, and the NULL terminator. */
+ rv = KHM_ERROR_TOO_LONG;
+ goto _set_null_ident;
+ }
+
+ realm = un + cch; /* now points at terminating NULL */
+ cch_left = KCDB_IDENT_MAXCCH_NAME - cch;
+
+ *realm++ = L'@';
+ *realm = L'\0';
+ cch_left--;
+
+ cch = GetWindowTextLength(d->hw_realm);
+ if (cch == 0 || cch >= cch_left) {
+ rv = KHM_ERROR_INVALID_NAME;
+ goto _set_null_ident;
+ }
+
+ GetWindowText(d->hw_realm, realm, (int) cch_left);
+ trim_str(realm, cch_left);
+
+ _set_ident:
+ if (KHM_FAILED(rv = kcdb_identity_create(un,
+ KCDB_IDENT_FLAG_CREATE,
+ &ident))) {
+ goto _set_null_ident;
+ }
+
+ khui_cw_set_primary_id(nc, ident);
+
+ kcdb_identity_release(ident);
+ return;
+
+ _set_null_ident:
+ {
+ khui_new_creds_by_type * nct = NULL;
+ wchar_t cmsg[256];
+
+ khui_cw_find_type(nc, credtype_id_krb5, &nct);
+ if (nct && nct->hwnd_panel) {
+
+ switch(rv) {
+ case KHM_ERROR_TOO_LONG:
+ LoadString(hResModule, IDS_NCERR_IDENT_TOO_LONG,
+ cmsg, ARRAYLENGTH(cmsg));
+ break;
+
+ case KHM_ERROR_INVALID_NAME:
+ LoadString(hResModule, IDS_NCERR_IDENT_INVALID,
+ cmsg, ARRAYLENGTH(cmsg));
+ break;
+
+ default:
+ LoadString(hResModule, IDS_NCERR_IDENT_UNKNOWN,
+ cmsg, ARRAYLENGTH(cmsg));
+ }
+
+ SendMessage(nct->hwnd_panel,
+ KHUI_WM_NC_NOTIFY,
+ MAKEWPARAM(0, K5_SET_CRED_MSG),
+ (LPARAM) cmsg);
+ }
+
+ khui_cw_set_primary_id(nc, NULL);
+ }
+ return;
+}
+
+/* runs in the UI thread */
+static BOOL
+update_crossfeed(khui_new_creds * nc,
+ k5_new_cred_data * d,
+ int ctrl_id_src) {
+ wchar_t un[KCDB_IDENT_MAXCCH_NAME];
+ wchar_t * un_realm;
+ wchar_t realm[KCDB_IDENT_MAXCCH_NAME];
+ khm_size cch;
+ khm_size cch_left;
+ int idx;
+
+ cch = (khm_size) GetWindowTextLength(d->hw_username);
+#ifdef DEBUG
+ assert(cch < KCDB_IDENT_MAXCCH_NAME);
+#endif
+ if (cch == 0)
+ return FALSE;
+
+ GetWindowText(d->hw_username,
+ un,
+ ARRAYLENGTH(un));
+ trim_str(un, ARRAYLENGTH(un));
+
+ un_realm = khm_get_realm_from_princ(un);
+
+ if (un_realm == NULL) {
+ EnableWindow(d->hw_realm, TRUE);
+ return FALSE;
+ }
+
+ if (ctrl_id_src == K5_NCID_UN) {
+
+ idx = (int)SendMessage(d->hw_realm,
+ CB_FINDSTRINGEXACT,
+ (WPARAM) -1,
+ (LPARAM) un_realm);
+
+ if (idx != CB_ERR) {
+ wchar_t srealm[KCDB_IDENT_MAXCCH_NAME];
+
+ cch = SendMessage(d->hw_realm,
+ CB_GETLBTEXTLEN,
+ (WPARAM) idx,
+ 0);
+
+#ifdef DEBUG
+ assert(cch < ARRAYLENGTH(srealm) - 1);
+#endif
+ SendMessage(d->hw_realm,
+ CB_GETLBTEXT,
+ (WPARAM) idx,
+ (LPARAM) srealm);
+
+ if (!_wcsicmp(srealm, un_realm) && wcscmp(srealm, un_realm)) {
+ /* differ only by case */
+
+ StringCchCopy(un_realm, ARRAYLENGTH(un) - (un_realm - un),
+ srealm);
+
+ SetWindowText(d->hw_username, un);
+ }
+ }
+
+ SendMessage(d->hw_realm,
+ CB_SELECTSTRING,
+ (WPARAM) -1,
+ (LPARAM) un_realm);
+
+ SetWindowText(d->hw_realm,
+ un_realm);
+
+ if (GetFocus() == d->hw_realm) {
+ HWND hw_next = GetNextDlgTabItem(nc->hwnd, d->hw_realm,
+ FALSE);
+ if (hw_next)
+ SetFocus(hw_next);
+ }
+
+ EnableWindow(d->hw_realm, FALSE);
+
+ return TRUE;
+ }
+ /* else... */
+
+ cch_left = KCDB_IDENT_MAXCCH_NAME - (un_realm - un);
+
+ cch = (khm_size) GetWindowTextLength(d->hw_realm);
+
+#ifdef DEBUG
+ assert(cch < KCDB_IDENT_MAXCCH_NAME);
+#endif
+ if (cch == 0)
+ return FALSE;
+
+ GetWindowText(d->hw_realm, realm,
+ ARRAYLENGTH(realm));
+ trim_str(realm, ARRAYLENGTH(realm));
+
+ idx = (int)SendMessage(d->hw_realm,
+ CB_FINDSTRINGEXACT,
+ (WPARAM) -1,
+ (LPARAM) realm);
+
+ if (idx != CB_ERR) {
+ wchar_t srealm[KCDB_IDENT_MAXCCH_NAME];
+
+ SendMessage(d->hw_realm,
+ CB_GETLBTEXT,
+ (WPARAM) idx,
+ (LPARAM) srealm);
+
+ if (!_wcsicmp(srealm, realm) && wcscmp(srealm, realm)) {
+ StringCbCopy(realm, sizeof(realm), srealm);
+
+ SetWindowText(d->hw_realm, srealm);
+ }
+ }
+
+ StringCchCopy(un_realm, cch_left, realm);
+
+ SendMessage(d->hw_username,
+ CB_SELECTSTRING,
+ (WPARAM) -1,
+ (LPARAM) un);
+
+ SetWindowText(d->hw_username, un);
+
+ return TRUE;
+}
+
+/* Handle window messages for the identity specifiers
+
+ runs in UI thread */
+static LRESULT
+handle_wnd_msg(khui_new_creds * nc,
+ HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam) {
+ k5_new_cred_data * d;
+
+ d = (k5_new_cred_data *) nc->ident_aux;
+
+ switch(uMsg) {
+ case WM_COMMAND:
+ switch(wParam) {
+ case MAKEWPARAM(K5_NCID_UN, CBN_EDITCHANGE):
+ /* the username has changed. Instead of handling this
+ for every keystroke, set a timer that elapses some
+ time afterwards and then handle the event. */
+ SetTimer(hwnd, NC_UNCHANGE_TIMER,
+ NC_UNCHANGE_TIMEOUT, NULL);
+ return TRUE;
+
+ case MAKEWPARAM(K5_NCID_UN, CBN_KILLFOCUS):
+ case MAKEWPARAM(K5_NCID_UN, CBN_CLOSEUP):
+ KillTimer(hwnd, NC_UNCHANGE_TIMER);
+
+ update_crossfeed(nc,d,K5_NCID_UN);
+ set_identity_from_ui(nc,d);
+ return TRUE;
+
+ case MAKEWPARAM(K5_NCID_REALM,CBN_EDITCHANGE):
+ SetTimer(hwnd, NC_REALMCHANGE_TIMER,
+ NC_REALMCHANGE_TIMEOUT, NULL);
+ return TRUE;
+
+ case MAKEWPARAM(K5_NCID_REALM,CBN_KILLFOCUS):
+ case MAKEWPARAM(K5_NCID_REALM,CBN_CLOSEUP):
+ KillTimer(hwnd, NC_REALMCHANGE_TIMER);
+
+ update_crossfeed(nc,d,K5_NCID_REALM);
+ set_identity_from_ui(nc, d);
+ return TRUE;
+ }
+ break;
+
+ case WM_TIMER:
+ if(wParam == NC_UNCHANGE_TIMER) {
+ KillTimer(hwnd, NC_UNCHANGE_TIMER);
+
+ update_crossfeed(nc, d, K5_NCID_UN);
+ set_identity_from_ui(nc,d);
+ return TRUE;
+ } else if (wParam == NC_REALMCHANGE_TIMER) {
+ KillTimer(hwnd, NC_REALMCHANGE_TIMER);
+
+ update_crossfeed(nc, d, K5_NCID_REALM);
+ set_identity_from_ui(nc, d);
+ return TRUE;
+ }
+ break;
+ }
+ return FALSE;
+}
+
+/* UI Callback
+
+ runs in UI thread */
+static LRESULT KHMAPI
+ui_cb(khui_new_creds * nc,
+ UINT cmd,
+ HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam) {
+
+ k5_new_cred_data * d;
+
+ d = (k5_new_cred_data *) nc->ident_aux;
+
+ switch(cmd) {
+ case WMNC_IDENT_INIT:
+ {
+ wchar_t defident[KCDB_IDENT_MAXCCH_NAME];
+ wchar_t wbuf[1024];
+ wchar_t * ms = NULL;
+ wchar_t * t;
+ wchar_t * defrealm = NULL;
+ LRESULT lr;
+ khm_size cb_ms;
+ khm_size cb;
+ HWND hw_parent;
+ khm_int32 rv;
+ khm_handle hident;
+
+ hw_parent = (HWND) lParam;
+ defident[0] = L'\0';
+
+#ifdef DEBUG
+ assert(d == NULL);
+ assert(hw_parent != NULL);
+#endif
+
+ d = PMALLOC(sizeof(*d));
+ assert(d);
+ ZeroMemory(d, sizeof(*d));
+
+ khui_cw_lock_nc(nc);
+ nc->ident_aux = (LPARAM) d;
+ khui_cw_unlock_nc(nc);
+
+ LoadString(hResModule, IDS_NC_USERNAME,
+ wbuf, ARRAYLENGTH(wbuf));
+
+ d->hw_username_label = CreateWindow
+ (L"STATIC",
+ wbuf,
+ SS_SIMPLE | WS_CHILD | WS_VISIBLE,
+ 0, 0, 100, 100, /* bogus values */
+ hw_parent,
+ (HMENU) K5_NCID_UN_LABEL,
+ hInstance,
+ NULL);
+ assert(d->hw_username_label != NULL);
+
+ d->hw_username = CreateWindow
+ (L"COMBOBOX",
+ L"",
+ CBS_DROPDOWN | CBS_AUTOHSCROLL | CBS_SORT |
+ WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL,
+ 0, 0, 100, 100, /* bogus values */
+ hw_parent,
+ (HMENU) K5_NCID_UN,
+ hInstance,
+ NULL);
+ assert(d->hw_username != NULL);
+
+ SendMessage(d->hw_username,
+ CB_LIMITTEXT,
+ (WPARAM)(KCDB_IDENT_MAXCCH_NAME - 1),
+ 0);
+
+ SendMessage(d->hw_username,
+ CB_SETEXTENDEDUI,
+ (WPARAM) TRUE,
+ 0);
+
+ khui_cw_add_control_row(nc,
+ d->hw_username_label,
+ d->hw_username,
+ KHUI_CTRLSIZE_SMALL);
+
+ LoadString(hResModule, IDS_NC_REALM,
+ wbuf, ARRAYLENGTH(wbuf));
+
+ d->hw_realm_label = CreateWindow
+ (L"STATIC",
+ wbuf,
+ SS_SIMPLE | WS_CHILD | WS_VISIBLE,
+ 0, 0, 100, 100, /* bogus */
+ hw_parent,
+ (HMENU) K5_NCID_REALM_LABEL,
+ hInstance,
+ NULL);
+ assert(d->hw_realm_label != NULL);
+
+ d->hw_realm = CreateWindow
+ (L"COMBOBOX",
+ L"",
+ CBS_DROPDOWN | CBS_AUTOHSCROLL | CBS_SORT |
+ WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL,
+ 0, 0, 100, 100, /* bogus */
+ hw_parent,
+ (HMENU) K5_NCID_REALM,
+ hInstance,
+ NULL);
+ assert(d->hw_realm != NULL);
+
+ SendMessage(d->hw_realm,
+ CB_LIMITTEXT,
+ (WPARAM) (KCDB_IDENT_MAXCCH_NAME - 1),
+ 0);
+
+ SendMessage(d->hw_realm,
+ CB_SETEXTENDEDUI,
+ (WPARAM) TRUE,
+ 0);
+
+ khui_cw_add_control_row(nc,
+ d->hw_realm_label,
+ d->hw_realm,
+ KHUI_CTRLSIZE_SMALL);
+
+ /* add the LRU realms and principals to the dropdown
+ lists */
+ rv = khc_read_multi_string(csp_params,
+ L"LRUPrincipals",
+ NULL,
+ &cb_ms);
+
+ if (rv != KHM_ERROR_TOO_LONG || cb_ms <= sizeof(wchar_t) * 2)
+ goto _add_lru_realms;
+
+ ms = PMALLOC(cb_ms);
+ assert(ms != NULL);
+
+ cb = cb_ms;
+ rv = khc_read_multi_string(csp_params,
+ L"LRUPrincipals",
+ ms,
+ &cb);
+
+ assert(KHM_SUCCEEDED(rv));
+
+ /* the first of these is considered the default identity
+ if no other default is known */
+ StringCbCopy(defident, sizeof(defident), ms);
+
+ t = ms;
+ while(t && *t) {
+ SendMessage(d->hw_username,
+ CB_ADDSTRING,
+ 0,
+ (LPARAM) t);
+
+ t = multi_string_next(t);
+ }
+
+ _add_lru_realms:
+ /* add the default realm first */
+ defrealm = khm_krb5_get_default_realm();
+ if (defrealm) {
+ SendMessage(d->hw_realm,
+ CB_ADDSTRING,
+ 0,
+ (LPARAM) defrealm);
+ }
+
+ rv = khc_read_multi_string(csp_params,
+ L"LRURealms",
+ NULL,
+ &cb);
+
+ if (rv != KHM_ERROR_TOO_LONG)
+ goto _done_adding_lru;
+
+ if (ms != NULL) {
+ if (cb_ms < cb) {
+ PFREE(ms);
+ ms = PMALLOC(cb);
+ assert(ms);
+ cb_ms = cb;
+ }
+ } else {
+ ms = PMALLOC(cb);
+ cb_ms = cb;
+ }
+
+ rv = khc_read_multi_string(csp_params,
+ L"LRURealms",
+ ms,
+ &cb);
+
+ assert(KHM_SUCCEEDED(rv));
+
+ for (t = ms; t && *t; t = multi_string_next(t)) {
+ lr = SendMessage(d->hw_realm,
+ CB_FINDSTRINGEXACT,
+ (WPARAM) -1,
+ (LPARAM) t);
+ if (lr != CB_ERR)
+ continue;
+
+ SendMessage(d->hw_realm,
+ CB_ADDSTRING,
+ 0,
+ (LPARAM) t);
+ }
+ _done_adding_lru:
+
+ {
+ khm_int32 inc_realms = 0;
+
+ if (KHM_FAILED(khc_read_int32(csp_params,
+ L"UseFullRealmList",
+ &inc_realms)) ||
+ !inc_realms)
+ goto _done_adding_all_realms;
+ }
+
+ if(ms)
+ PFREE(ms);
+
+ ms = khm_krb5_get_realm_list();
+ if(ms) {
+ for (t = ms; t && *t; t = multi_string_next(t)) {
+ lr = SendMessage(d->hw_realm,
+ CB_FINDSTRINGEXACT,
+ (WPARAM) -1,
+ (LPARAM) t);
+ if (lr != CB_ERR)
+ continue;
+
+ SendMessage(d->hw_realm,
+ CB_ADDSTRING,
+ 0,
+ (LPARAM) t);
+ }
+ }
+ _done_adding_all_realms:
+
+ /* set the current selection of the realms list */
+ if (defrealm) {
+ SendMessage(d->hw_realm,
+ CB_SELECTSTRING,
+ (WPARAM) -1,
+ (LPARAM) defrealm);
+ } else {
+ SendMessage(d->hw_realm,
+ CB_SETCURSEL,
+ (WPARAM) 0,
+ (LPARAM) 0);
+ }
+
+ if (defrealm)
+ PFREE(defrealm);
+
+ if (ms)
+ PFREE(ms);
+
+ /* now see about that default identity */
+ if (nc->ctx.identity) {
+ cb = sizeof(defident);
+ kcdb_identity_get_name(nc->ctx.identity,
+ defident,
+ &cb);
+ }
+
+ if (defident[0] == L'\0' &&
+ KHM_SUCCEEDED(kcdb_identity_get_default(&hident))) {
+ cb = sizeof(defident);
+ kcdb_identity_get_name(hident, defident, &cb);
+ kcdb_identity_release(hident);
+ }
+
+ if (defident[0] == L'\0') {
+ DWORD dw;
+
+ dw = ARRAYLENGTH(defident);
+ GetUserName(defident, &dw);
+ }
+
+ t = khm_get_realm_from_princ(defident);
+ if (t) {
+ /* there is a realm */
+ assert(t != defident);
+ *--t = L'\0';
+ t++;
+
+ SendMessage(d->hw_realm,
+ CB_SELECTSTRING,
+ (WPARAM) -1,
+ (LPARAM) t);
+
+ SendMessage(d->hw_realm,
+ WM_SETTEXT,
+ 0,
+ (LPARAM) t);
+ }
+
+ if (defident[0] != L'\0') {
+ /* there is a username */
+ SendMessage(d->hw_username,
+ CB_SELECTSTRING,
+ (WPARAM) -1,
+ (LPARAM) defident);
+
+ SendMessage(d->hw_username,
+ WM_SETTEXT,
+ 0,
+ (LPARAM) defident);
+ }
+
+ set_identity_from_ui(nc, d);
+ }
+ return TRUE;
+
+ case WMNC_IDENT_WMSG:
+ return handle_wnd_msg(nc, hwnd, uMsg, wParam, lParam);
+
+ case WMNC_IDENT_EXIT:
+ {
+#ifdef DEBUG
+ assert(d != NULL);
+#endif
+ khui_cw_lock_nc(nc);
+ nc->ident_aux = 0;
+ khui_cw_unlock_nc(nc);
+
+ /* since we created all the windows as child windows of
+ the new creds window, they will be destroyed when that
+ window is destroyed. */
+ PFREE(d);
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static khm_int32
+k5_ident_validate_name(khm_int32 msg_type,
+ khm_int32 msg_subtype,
+ khm_ui_4 uparam,
+ void * vparam) {
+ krb5_principal princ = NULL;
+ char princ_name[KCDB_IDENT_MAXCCH_NAME];
+ kcdb_ident_name_xfer * nx;
+ krb5_error_code code;
+ wchar_t * atsign;
+
+ nx = (kcdb_ident_name_xfer *) vparam;
+
+ if(UnicodeStrToAnsi(princ_name, sizeof(princ_name),
+ nx->name_src) == 0) {
+ nx->result = KHM_ERROR_INVALID_NAME;
+ return KHM_ERROR_SUCCESS;
+ }
+
+ assert(k5_identpro_ctx != NULL);
+
+ code = pkrb5_parse_name(k5_identpro_ctx,
+ princ_name,
+ &princ);
+
+ if (code) {
+ nx->result = KHM_ERROR_INVALID_NAME;
+ return KHM_ERROR_SUCCESS;
+ }
+
+ if (princ != NULL)
+ pkrb5_free_principal(k5_identpro_ctx,
+ princ);
+
+ /* krb5_parse_name() accepts principal names with no realm or an
+ empty realm. We don't. */
+ atsign = wcschr(nx->name_src, L'@');
+ if (atsign == NULL || atsign[1] == L'\0') {
+ nx->result = KHM_ERROR_INVALID_NAME;
+ } else {
+ nx->result = KHM_ERROR_SUCCESS;
+ }
+
+ return KHM_ERROR_SUCCESS;
+}
+
+static void
+k5_update_last_default_identity(khm_handle ident) {
+ wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
+ khm_size cb;
+
+ cb = sizeof(idname);
+ if (KHM_FAILED(kcdb_identity_get_name(ident, idname, &cb)))
+ return;
+
+ assert(csp_params);
+
+ khc_write_string(csp_params, L"LastDefaultIdent", idname);
+}
+
+static khm_int32
+k5_ident_set_default_int(khm_handle def_ident) {
+ wchar_t id_ccname[KRB5_MAXCCH_CCNAME];
+ khm_size cb;
+ DWORD dw;
+ LONG l;
+ HKEY hk_ccname;
+ DWORD dwType;
+ DWORD dwSize;
+ wchar_t reg_ccname[KRB5_MAXCCH_CCNAME];
+
+#ifdef DEBUG
+ assert(def_ident != NULL);
+#endif
+
+ cb = sizeof(id_ccname);
+ if (KHM_FAILED(kcdb_identity_get_attr(def_ident, attr_id_krb5_ccname, NULL,
+ id_ccname, &cb))) {
+ khm_handle csp_ident = NULL;
+ khm_handle csp_k5 = NULL;
+
+ _reportf(L"The specified identity does not have the Krb5CCName property");
+
+ cb = sizeof(id_ccname);
+ if (KHM_SUCCEEDED(kcdb_identity_get_config(def_ident, 0, &csp_ident)) &&
+ KHM_SUCCEEDED(khc_open_space(csp_ident, CSNAME_KRB5CRED, 0, &csp_k5)) &&
+ KHM_SUCCEEDED(khc_read_string(csp_k5, L"DefaultCCName",
+ id_ccname, &cb))) {
+
+ _reportf(L"Found CC name in configuration [%s]", id_ccname);
+ } else {
+ /* last resort, use the name of the identity as the cc
+ name */
+ cb = sizeof(id_ccname);
+ if (KHM_FAILED(kcdb_identity_get_name(def_ident, id_ccname, &cb))) {
+ _reportf(L"Can't use name of identity as CCName");
+ _end_task();
+
+ id_ccname[0] = L'\0';
+ }
+ }
+
+ if (csp_k5)
+ khc_close_space(csp_k5);
+ if (csp_ident)
+ khc_close_space(csp_ident);
+
+ if (id_ccname[0] == L'\0')
+ return KHM_ERROR_INVALID_PARAM;
+ }
+
+ khm_krb5_canon_cc_name(id_ccname, sizeof(id_ccname));
+
+ _reportf(L"Found Krb5CCName property : %s", id_ccname);
+
+ StringCbLength(id_ccname, sizeof(id_ccname), &cb);
+ cb += sizeof(wchar_t);
+
+ _reportf(L"Setting default CC name in the registry");
+
+ l = RegOpenKeyEx(HKEY_CURRENT_USER, L"Software\\MIT\\kerberos5", 0,
+ KEY_READ | KEY_WRITE, &hk_ccname);
+
+ if (l != ERROR_SUCCESS)
+ l = RegCreateKeyEx(HKEY_CURRENT_USER, L"Software\\MIT\\kerberos5", 0,
+ NULL, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE,
+ NULL, &hk_ccname, &dw);
+
+ if (l != ERROR_SUCCESS) {
+ _reportf(L"Can't create registry key : %d", l);
+ _end_task();
+ return KHM_ERROR_UNKNOWN;
+ }
+
+ dwSize = sizeof(reg_ccname);
+
+ l = RegQueryValueEx(hk_ccname, L"ccname", NULL, &dwType, (LPBYTE) reg_ccname,
+ &dwSize);
+
+ if (l != ERROR_SUCCESS ||
+ dwType != REG_SZ ||
+ khm_krb5_cc_name_cmp(reg_ccname, id_ccname)) {
+
+ /* we have to write the new value in */
+
+ l = RegSetValueEx(hk_ccname, L"ccname", 0, REG_SZ, (BYTE *) id_ccname,
+ (DWORD) cb);
+ }
+
+ RegCloseKey(hk_ccname);
+
+ if (l == ERROR_SUCCESS) {
+ _reportf(L"Successfully set the default ccache");
+ k5_update_last_default_identity(def_ident);
+ return KHM_ERROR_SUCCESS;
+ } else {
+ _reportf(L"Can't set the registry value : %d", l);
+ return KHM_ERROR_UNKNOWN;
+ }
+}
+
+static khm_int32
+k5_ident_set_default(khm_int32 msg_type,
+ khm_int32 msg_subtype,
+ khm_ui_4 uparam,
+ void * vparam) {
+
+ /*
+ Currently, setting the default identity simply sets the
+ "ccname" registry value at "Software\MIT\kerberos5".
+ */
+
+ if (uparam) {
+ /* an identity is being made default */
+ khm_handle def_ident = (khm_handle) vparam;
+ khm_int32 rv;
+
+#ifdef DEBUG
+ assert(def_ident != NULL);
+#endif
+
+ {
+ wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
+ khm_size cb;
+
+ cb = sizeof(idname);
+ kcdb_identity_get_name(def_ident, idname, &cb);
+
+ _begin_task(0);
+ _report_cs1(KHERR_DEBUG_1, L"Setting default identity [%1!s!]", _cstr(idname));
+ _describe();
+ }
+
+ rv = k5_ident_set_default_int(def_ident);
+
+ _end_task();
+
+ return rv;
+
+ } else {
+ /* the default identity is being forgotten */
+
+ /* we don't really do anything about this case */
+ }
+
+ return KHM_ERROR_SUCCESS;
+}
+
+static khm_int32
+k5_ident_get_ui_cb(khm_int32 msg_type,
+ khm_int32 msg_subtype,
+ khm_ui_4 uparam,
+ void * vparam) {
+ khui_ident_new_creds_cb * cb;
+
+ cb = (khui_ident_new_creds_cb *) vparam;
+
+ *cb = ui_cb;
+
+ return KHM_ERROR_SUCCESS;
+}
+
+static khm_int32
+k5_ident_notify_create(khm_int32 msg_type,
+ khm_int32 msg_subtype,
+ khm_ui_4 uparam,
+ void * vparam) {
+
+ /* a new identity has been created. What we want to do at
+ this point is to check if the identity belongs to krb5
+ and to see if it is the default. */
+
+ krb5_ccache cc = NULL;
+ krb5_error_code code;
+ krb5_principal princ = NULL;
+ char * princ_nameA = NULL;
+ wchar_t princ_nameW[KCDB_IDENT_MAXCCH_NAME];
+ wchar_t id_nameW[KCDB_IDENT_MAXCCH_NAME];
+ khm_size cb;
+ khm_handle ident;
+
+ /* if there is a default identity already, we assume we don't need
+ to check this one. */
+
+ khm_handle def_ident;
+
+ if (KHM_SUCCEEDED(kcdb_identity_get_default(&def_ident))) {
+ kcdb_identity_release(def_ident);
+
+ return KHM_ERROR_SUCCESS;
+ }
+
+ ident = (khm_handle) vparam;
+
+ assert(k5_identpro_ctx != NULL);
+
+ code = pkrb5_cc_default(k5_identpro_ctx, &cc);
+ if (code)
+ goto _nc_cleanup;
+
+ code = pkrb5_cc_get_principal(k5_identpro_ctx,
+ cc,
+ &princ);
+ if (code)
+ goto _nc_cleanup;
+
+ code = pkrb5_unparse_name(k5_identpro_ctx,
+ princ,
+ &princ_nameA);
+ if (code)
+ goto _nc_cleanup;
+
+ AnsiStrToUnicode(princ_nameW,
+ sizeof(princ_nameW),
+ princ_nameA);
+
+ cb = sizeof(id_nameW);
+
+ if (KHM_FAILED(kcdb_identity_get_name(ident,
+ id_nameW,
+ &cb)))
+ goto _nc_cleanup;
+
+ if (!wcscmp(id_nameW, princ_nameW)) {
+ kcdb_identity_set_default_int(ident);
+ }
+
+ _nc_cleanup:
+ if (princ_nameA)
+ pkrb5_free_unparsed_name(k5_identpro_ctx,
+ princ_nameA);
+ if (princ)
+ pkrb5_free_principal(k5_identpro_ctx,
+ princ);
+ if (cc)
+ pkrb5_cc_close(k5_identpro_ctx, cc);
+
+ return KHM_ERROR_SUCCESS;
+}
+
+struct k5_ident_update_data {
+ khm_handle identity;
+
+ FILETIME ft_expire; /* expiration */
+ FILETIME ft_issue; /* issue */
+ FILETIME ft_rexpire; /* renew expiration */
+ wchar_t ccname[KRB5_MAXCCH_CCNAME];
+ khm_int32 k5_flags;
+};
+
+/* The logic here has to reflect the logic in khm_krb5_list_tickets().
+ We use this to handle an identity update request because some other
+ plug-in or maybe NetIDMgr itself is about to do something
+ important(tm) with the identity and needs to make sure that the
+ properties of the identity are up-to-date. */
+static khm_int32 KHMAPI
+k5_ident_update_apply_proc(khm_handle cred,
+ void * rock) {
+ struct k5_ident_update_data * d = (struct k5_ident_update_data *) rock;
+ khm_handle ident = NULL;
+ khm_int32 t;
+ khm_int32 flags;
+ FILETIME t_cexpire;
+ FILETIME t_rexpire;
+ khm_size cb;
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+
+ if (KHM_FAILED(kcdb_cred_get_type(cred, &t)) ||
+ t != credtype_id_krb5 ||
+ KHM_FAILED(kcdb_cred_get_identity(cred, &ident)))
+
+ return KHM_ERROR_SUCCESS;
+
+ if (!kcdb_identity_is_equal(ident,d->identity))
+
+ goto _cleanup;
+
+ if (KHM_FAILED(kcdb_cred_get_flags(cred, &flags)))
+
+ flags = 0;
+
+ if (flags & KCDB_CRED_FLAG_INITIAL) {
+ cb = sizeof(t_cexpire);
+ if (KHM_SUCCEEDED(kcdb_cred_get_attr(cred,
+ KCDB_ATTR_EXPIRE,
+ NULL,
+ &t_cexpire,
+ &cb))) {
+ if ((d->ft_expire.dwLowDateTime == 0 &&
+ d->ft_expire.dwHighDateTime == 0) ||
+ CompareFileTime(&t_cexpire, &d->ft_expire) > 0) {
+ goto update_identity;
+ }
+ }
+ }
+
+ goto _cleanup;
+
+ update_identity:
+
+ d->ft_expire = t_cexpire;
+
+ cb = sizeof(d->ccname);
+ if (KHM_FAILED(kcdb_cred_get_attr(cred, KCDB_ATTR_LOCATION, NULL, d->ccname, &cb))) {
+ d->ccname[0] = L'\0';
+ }
+
+ cb = sizeof(d->k5_flags);
+ if (KHM_FAILED(kcdb_cred_get_attr(cred, attr_id_krb5_flags, NULL,
+ &d->k5_flags, &cb))) {
+ d->k5_flags = 0;
+ }
+
+ cb = sizeof(d->ft_issue);
+ if (KHM_FAILED(kcdb_cred_get_attr(cred, KCDB_ATTR_ISSUE, NULL, &d->ft_issue, &cb))) {
+ ZeroMemory(&d->ft_issue, sizeof(d->ft_issue));
+ }
+
+ cb = sizeof(t_rexpire);
+ if ((d->k5_flags & TKT_FLG_RENEWABLE) &&
+ KHM_SUCCEEDED(kcdb_cred_get_attr(cred,
+ KCDB_ATTR_RENEW_EXPIRE,
+ NULL,
+ &t_rexpire,
+ &cb))) {
+ d->ft_rexpire = t_rexpire;
+ } else {
+ ZeroMemory(&d->ft_rexpire, sizeof(d->ft_rexpire));
+ }
+
+ _cleanup:
+ if (ident)
+ kcdb_identity_release(ident);
+
+ return rv;
+}
+
+static khm_int32
+k5_ident_update(khm_int32 msg_type,
+ khm_int32 msg_subtype,
+ khm_ui_4 uparam,
+ void * vparam) {
+
+#if 0
+ struct k5_ident_update_data d;
+#endif
+ khm_handle ident;
+ khm_handle tident;
+ krb5_ccache cc = NULL;
+ char * ccname;
+ krb5_error_code code;
+ khm_size cb;
+ wchar_t wid_ccname[MAX_PATH];
+ wchar_t w_ccname[MAX_PATH];
+
+ ident = (khm_handle) vparam;
+ if (ident == NULL)
+ return KHM_ERROR_SUCCESS;
+
+#if 0
+ /* we are going to skip doing this here since
+ khm_krb5_list_tickets() performs this function for us each time
+ we enumerate tickets. Since it also gets run each time our
+ list of tickets changes and since we are basing this operation
+ on existing tickets, we are unlikely to find anything new
+ here. */
+ ZeroMemory(&d, sizeof(d));
+ d.identity = ident;
+
+ kcdb_credset_apply(NULL,
+ k5_ident_update_apply_proc,
+ (void *) &d);
+
+ if (d.ft_expire.dwLowDateTime != 0 ||
+ d.ft_expire.dwHighDateTime != 0) {
+
+ /* we found a TGT */
+
+ kcdb_identity_set_attr(ident, KCDB_ATTR_EXPIRE,
+ &d.ft_expire, sizeof(d.ft_expire));
+ if (d.ft_issue.dwLowDateTime != 0 ||
+ d.ft_issue.dwHighDateTime != 0)
+ kcdb_identity_set_attr(ident, KCDB_ATTR_ISSUE,
+ &d.ft_issue, sizeof(d.ft_issue));
+ else
+ kcdb_identity_set_attr(ident, KCDB_ATTR_ISSUE, NULL, 0);
+
+ if (d.ft_rexpire.dwLowDateTime != 0 ||
+ d.ft_rexpire.dwHighDateTime != 0)
+ kcdb_identity_set_attr(ident, KCDB_ATTR_RENEW_EXPIRE,
+ &d.ft_rexpire, sizeof(d.ft_rexpire));
+ else
+ kcdb_identity_set_attr(ident, KCDB_ATTR_RENEW_EXPIRE, NULL, 0);
+
+ kcdb_identity_set_attr(ident, attr_id_krb5_flags,
+ &d.k5_flags, sizeof(d.k5_flags));
+
+ if (d.ccname[0])
+ kcdb_identity_set_attr(ident, attr_id_krb5_ccname,
+ d.ccname, KCDB_CBSIZE_AUTO);
+ else
+ kcdb_identity_set_attr(ident, attr_id_krb5_ccname, NULL, 0);
+
+ } else {
+ /* Clear out the attributes. We don't have any information
+ about this identity */
+ kcdb_identity_set_attr(ident, KCDB_ATTR_EXPIRE, NULL, 0);
+ kcdb_identity_set_attr(ident, KCDB_ATTR_ISSUE, NULL, 0);
+ kcdb_identity_set_attr(ident, KCDB_ATTR_RENEW_EXPIRE, NULL, 0);
+ kcdb_identity_set_attr(ident, attr_id_krb5_flags, NULL, 0);
+ kcdb_identity_set_attr(ident, attr_id_krb5_ccname, NULL, 0);
+ }
+#endif
+
+ if (KHM_SUCCEEDED(kcdb_identity_get_default(&tident))) {
+ kcdb_identity_release(tident);
+ goto _iu_cleanup;
+ }
+
+ cb = sizeof(wid_ccname);
+ if (KHM_FAILED(kcdb_identity_get_attr(ident,
+ attr_id_krb5_ccname,
+ NULL,
+ wid_ccname,
+ &cb)))
+ goto _iu_cleanup;
+
+ if(k5_identpro_ctx == NULL)
+ goto _iu_cleanup;
+
+ code = pkrb5_cc_default(k5_identpro_ctx, &cc);
+ if (code)
+ goto _iu_cleanup;
+
+ ccname = pkrb5_cc_get_name(k5_identpro_ctx, cc);
+ if (ccname == NULL)
+ goto _iu_cleanup;
+
+ AnsiStrToUnicode(w_ccname, sizeof(w_ccname), ccname);
+
+ khm_krb5_canon_cc_name(w_ccname, sizeof(w_ccname));
+ khm_krb5_canon_cc_name(wid_ccname, sizeof(wid_ccname));
+
+ if (!_wcsicmp(w_ccname, wid_ccname))
+ kcdb_identity_set_default_int(ident);
+
+ _iu_cleanup:
+ if (cc && k5_identpro_ctx)
+ pkrb5_cc_close(k5_identpro_ctx, cc);
+
+ return KHM_ERROR_SUCCESS;
+}
+
+static khm_boolean
+k5_refresh_default_identity(krb5_context ctx) {
+ /* just like notify_create, except now we set the default identity
+ based on what we find in the configuration */
+ krb5_ccache cc = NULL;
+ krb5_error_code code;
+ krb5_principal princ = NULL;
+ char * princ_nameA = NULL;
+ wchar_t princ_nameW[KCDB_IDENT_MAXCCH_NAME];
+ char * ccname = NULL;
+ khm_handle ident = NULL;
+ khm_boolean found_default = FALSE;
+
+ assert(ctx != NULL);
+
+ _begin_task(0);
+ _report_cs0(KHERR_DEBUG_1, L"Refreshing default identity");
+ _describe();
+
+ code = pkrb5_cc_default(ctx, &cc);
+ if (code) {
+ _reportf(L"Can't open default ccache. code=%d", code);
+ goto _nc_cleanup;
+ }
+
+ code = pkrb5_cc_get_principal(ctx, cc, &princ);
+ if (code) {
+ /* try to determine the identity from the ccache name */
+ ccname = pkrb5_cc_get_name(ctx, cc);
+
+ if (ccname) {
+ char * namepart = strchr(ccname, ':');
+
+ _reportf(L"CC name is [%S]", ccname);
+
+ if (namepart == NULL)
+ namepart = ccname;
+ else
+ namepart++;
+
+ _reportf(L"Checking if [%S] is a valid identity name", namepart);
+
+ AnsiStrToUnicode(princ_nameW, sizeof(princ_nameW), namepart);
+ if (kcdb_identity_is_valid_name(princ_nameW)) {
+ kcdb_identity_create(princ_nameW, KCDB_IDENT_FLAG_CREATE, &ident);
+ if (ident) {
+ _reportf(L"Setting [%S] as the default identity", namepart);
+ kcdb_identity_set_default_int(ident);
+ found_default = TRUE;
+ }
+ }
+ } else {
+ _reportf(L"Can't determine ccache name");
+ }
+
+ goto _nc_cleanup;
+ }
+
+ code = pkrb5_unparse_name(ctx, princ, &princ_nameA);
+ if (code)
+ goto _nc_cleanup;
+
+ AnsiStrToUnicode(princ_nameW, sizeof(princ_nameW), princ_nameA);
+
+ _reportf(L"Found principal [%s]", princ_nameW);
+
+ if (KHM_FAILED(kcdb_identity_create(princ_nameW, KCDB_IDENT_FLAG_CREATE, &ident))) {
+ _reportf(L"Failed to create identity");
+ goto _nc_cleanup;
+ }
+
+ _reportf(L"Setting default identity to [%s]", princ_nameW);
+ kcdb_identity_set_default_int(ident);
+
+ found_default = TRUE;
+
+ _nc_cleanup:
+
+ _end_task();
+
+ if (princ_nameA)
+ pkrb5_free_unparsed_name(ctx, princ_nameA);
+
+ if (princ)
+ pkrb5_free_principal(ctx, princ);
+
+ if (cc)
+ pkrb5_cc_close(ctx, cc);
+
+ if (ident)
+ kcdb_identity_release(ident);
+
+ return found_default;
+}
+
+static khm_int32
+k5_ident_init(khm_int32 msg_type,
+ khm_int32 msg_subtype,
+ khm_ui_4 uparam,
+ void * vparam) {
+
+ khm_boolean found_default;
+ khm_handle ident;
+
+ found_default = k5_refresh_default_identity(k5_identpro_ctx);
+
+ if (!found_default) {
+ wchar_t widname[KCDB_IDENT_MAXCCH_NAME];
+ khm_size cb;
+
+ cb = sizeof(widname);
+
+ assert(csp_params);
+
+ if (KHM_SUCCEEDED(khc_read_string(csp_params, L"LastDefaultIdent",
+ widname, &cb))) {
+ ident = NULL;
+ kcdb_identity_create(widname, KCDB_IDENT_FLAG_CREATE, &ident);
+ if (ident) {
+ kcdb_identity_set_default_int(ident);
+ kcdb_identity_release(ident);
+
+ found_default = TRUE;
+ }
+ }
+ }
+
+ if (!found_default) {
+
+ /* There was no default ccache and we don't have a
+ "LastDefaultIdent" value. Next we see if there are any
+ identities that have credentials which have a Krb5CCName
+ property (i.e. an identity that has a Kerberos 5 TGT), and
+ make it the default.
+
+ Note that since the Krb5Ident plug-in has a dependency on
+ Krb5Cred, by the time this code runs, we already have a
+ listing of Kerberos 5 tickets and identities. */
+
+ wchar_t * idlist = NULL;
+ wchar_t * thisid;
+ khm_size cb = 0;
+ khm_size n_idents = 0;
+ khm_int32 rv;
+ wchar_t ccname[KRB5_MAXCCH_CCNAME];
+ FILETIME ft_expire;
+ FILETIME ft_now;
+ FILETIME ft_threshold;
+ BOOL match_all = FALSE;
+
+ rv = kcdb_identity_enum(0, 0, NULL, &cb, &n_idents);
+
+ TimetToFileTimeInterval(5 * 60, &ft_threshold);
+ GetSystemTimeAsFileTime(&ft_now);
+ ft_now = FtAdd(&ft_now, &ft_threshold);
+
+ while (rv == KHM_ERROR_TOO_LONG && n_idents > 0) {
+ if (idlist) {
+ PFREE(idlist);
+ idlist = NULL;
+ }
+
+ idlist = PMALLOC(cb);
+
+ if (idlist == NULL)
+ break;
+
+ rv = kcdb_identity_enum(0, 0, idlist, &cb, &n_idents);
+ }
+
+ if (KHM_SUCCEEDED(rv)) {
+
+ /* first we try to find an identity that has a valid TGT.
+ If that fails, then we try to find an identity with
+ *any* TGT. */
+
+ try_again:
+
+ for (thisid = idlist;
+ thisid && *thisid && !found_default;
+ thisid = multi_string_next(thisid)) {
+
+ if (KHM_SUCCEEDED(kcdb_identity_create(thisid, 0, &ident))) {
+ khm_size cb_ft = sizeof(FILETIME);
+ cb = sizeof(ccname);
+
+ if (KHM_SUCCEEDED(kcdb_identity_get_attr(ident, attr_id_krb5_ccname,
+ NULL, ccname, &cb)) &&
+ (match_all ||
+ (KHM_SUCCEEDED(kcdb_identity_get_attr(ident, KCDB_ATTR_EXPIRE,
+ NULL, &ft_expire, &cb_ft)) &&
+ CompareFileTime(&ft_expire, &ft_now) > 0))) {
+
+ /* found one */
+ k5_ident_set_default_int(ident);
+ kcdb_identity_set_default_int(ident);
+ found_default = TRUE;
+
+ }
+
+ kcdb_identity_release(ident);
+ ident = NULL;
+ }
+ }
+
+ if (!found_default && !match_all) {
+ match_all = TRUE;
+ goto try_again;
+ }
+ }
+
+ if (idlist) {
+ PFREE(idlist);
+ idlist = NULL;
+ }
+ }
+
+ return KHM_ERROR_SUCCESS;
+}
+
+static khm_int32
+k5_ident_exit(khm_int32 msg_type,
+ khm_int32 msg_subtype,
+ khm_ui_4 uparam,
+ void * vparam) {
+ /* don't really do anything */
+ return KHM_ERROR_SUCCESS;
+}
+
+/* forward dcl */
+khm_int32 KHMAPI
+k5_ident_name_comp_func(const void * dl, khm_size cb_dl,
+ const void * dr, khm_size cb_dr);
+
+static khm_int32
+k5_ident_compare_name(khm_int32 msg_type,
+ khm_int32 msg_subtype,
+ khm_ui_4 uparam,
+ void * vparam) {
+ kcdb_ident_name_xfer *px;
+
+ px = (kcdb_ident_name_xfer *) vparam;
+
+ /* note that k5_ident_name_comp_func() ignores the size
+ specifiers. So we can just pass in 0's. */
+ px->result = k5_ident_name_comp_func(px->name_src, 0,
+ px->name_alt, 0);
+
+ return KHM_ERROR_SUCCESS;
+}
+
+#if 0
+/* copy and paste template for ident provider messages */
+static khm_int32
+k5_ident_(khm_int32 msg_type,
+ khm_int32 msg_subtype,
+ khm_ui_4 uparam,
+ void * vparam) {
+}
+#endif
+
+khm_int32 KHMAPI
+k5_msg_ident(khm_int32 msg_type,
+ khm_int32 msg_subtype,
+ khm_ui_4 uparam,
+ void * vparam)
+{
+ switch(msg_subtype) {
+ case KMSG_IDENT_INIT:
+ return k5_ident_init(msg_type,
+ msg_subtype,
+ uparam,
+ vparam);
+
+ case KMSG_IDENT_EXIT:
+ return k5_ident_exit(msg_type,
+ msg_subtype,
+ uparam,
+ vparam);
+
+ case KMSG_IDENT_VALIDATE_NAME:
+ return k5_ident_validate_name(msg_type,
+ msg_subtype,
+ uparam,
+ vparam);
+
+ case KMSG_IDENT_VALIDATE_IDENTITY:
+ /* TODO: handle KMSG_IDENT_VALIDATE_IDENTITY */
+ break;
+
+ case KMSG_IDENT_CANON_NAME:
+ /* TODO: handle KMSG_IDENT_CANON_NAME */
+ break;
+
+ case KMSG_IDENT_COMPARE_NAME:
+ return k5_ident_compare_name(msg_type,
+ msg_subtype,
+ uparam,
+ vparam);
+
+ case KMSG_IDENT_SET_DEFAULT:
+ return k5_ident_set_default(msg_type,
+ msg_subtype,
+ uparam,
+ vparam);
+
+ case KMSG_IDENT_SET_SEARCHABLE:
+ /* TODO: handle KMSG_IDENT_SET_SEARCHABLE */
+ break;
+
+ case KMSG_IDENT_GET_INFO:
+ /* TODO: handle KMSG_IDENT_GET_INFO */
+ break;
+
+ case KMSG_IDENT_UPDATE:
+ return k5_ident_update(msg_type,
+ msg_subtype,
+ uparam,
+ vparam);
+
+ case KMSG_IDENT_ENUM_KNOWN:
+ /* TODO: handle KMSG_IDENT_ENUM_KNOWN */
+ break;
+
+ case KMSG_IDENT_GET_UI_CALLBACK:
+ return k5_ident_get_ui_cb(msg_type,
+ msg_subtype,
+ uparam,
+ vparam);
+
+ case KMSG_IDENT_NOTIFY_CREATE:
+ return k5_ident_notify_create(msg_type,
+ msg_subtype,
+ uparam,
+ vparam);
+ }
+
+ return KHM_ERROR_SUCCESS;
+}
+
+/* note that we are ignoring the size specifiers. We can do that
+ because we are guaranteed that dl and dr point to NULL terminated
+ unicode strings when used with credential data buffers. We also
+ use the fact that we are ignoring the size specifiers when we call
+ this function from k5_ident_compare_name() to avoid calculating the
+ length of the string. */
+khm_int32 KHMAPI
+k5_ident_name_comp_func(const void * dl, khm_size cb_dl,
+ const void * dr, khm_size cb_dr) {
+ wchar_t * idl = (wchar_t *) dl;
+ wchar_t * idr = (wchar_t *) dr;
+ wchar_t * rl;
+ wchar_t * rr;
+ khm_int32 r;
+
+ rl = khm_get_realm_from_princ(idl);
+ rr = khm_get_realm_from_princ(idr);
+
+ if (rl == NULL && rr == NULL)
+ return wcscmp(idl, idr);
+ else if (rl == NULL)
+ return 1;
+ else if (rr == NULL)
+ return -1;
+
+ r = wcscmp(rl, rr);
+ if (r == 0)
+ return wcscmp(idl, idr);
+ else
+ return r;
+}
+
+
+/* Identity change notification thread */
+
+HANDLE h_ccname_exit_event;
+HANDLE h_ccname_thread;
+
+DWORD WINAPI k5_ccname_monitor_thread(LPVOID lpParameter) {
+ krb5_context ctx = 0;
+
+ HKEY hk_ccname;
+ HANDLE h_notify;
+ HANDLE h_waits[2];
+
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+ DWORD dwType;
+ DWORD dwSize;
+ DWORD dwDisp;
+ wchar_t reg_ccname[KRB5_MAXCCH_CCNAME];
+ LONG l;
+
+ PDESCTHREAD(L"Krb5 CCName Monitor", L"Krb5");
+
+ l = RegOpenKeyEx(HKEY_CURRENT_USER,
+ L"Software\\MIT\\kerberos5",
+ 0,
+ KEY_READ | KEY_WRITE,
+ &hk_ccname);
+
+ if (l != ERROR_SUCCESS)
+ l = RegCreateKeyEx(HKEY_CURRENT_USER,
+ L"Software\\MIT\\kerberos5",
+ 0,
+ NULL,
+ REG_OPTION_NON_VOLATILE,
+ KEY_READ | KEY_WRITE,
+ NULL,
+ &hk_ccname,
+ &dwDisp);
+
+ if (l != ERROR_SUCCESS) {
+ rv = KHM_ERROR_UNKNOWN;
+ goto _exit;
+ }
+
+ dwSize = sizeof(reg_ccname);
+
+ l = RegQueryValueEx(hk_ccname,
+ L"ccname",
+ NULL,
+ &dwType,
+ (LPBYTE) reg_ccname,
+ &dwSize);
+
+ if (l != ERROR_SUCCESS ||
+ dwType != REG_SZ) {
+
+ reg_ccname[0] = L'\0';
+ }
+
+ l = pkrb5_init_context(&ctx);
+
+ if (l)
+ goto _exit_0;
+
+ h_notify = CreateEvent(NULL, FALSE, FALSE, L"Local\\Krb5CCNameChangeNotifier");
+
+ if (h_notify == NULL)
+ goto _exit_0;
+
+ /* begin wait loop */
+
+ h_waits[0] = h_ccname_exit_event;
+ h_waits[1] = h_notify;
+
+ do {
+ DWORD dwrv;
+
+ l = RegNotifyChangeKeyValue(hk_ccname, FALSE,
+ REG_NOTIFY_CHANGE_LAST_SET,
+ h_notify, TRUE);
+
+ if (l != ERROR_SUCCESS) {
+ rv = KHM_ERROR_UNKNOWN;
+ break;
+ }
+
+ dwrv = WaitForMultipleObjects(2, h_waits, FALSE, INFINITE);
+
+ if (dwrv == WAIT_OBJECT_0) {
+ /* exit! */
+ break;
+
+ } else if (dwrv == WAIT_OBJECT_0 + 1) {
+ /* change notify! */
+ wchar_t new_ccname[KRB5_MAXCCH_CCNAME];
+
+ dwSize = sizeof(new_ccname);
+
+ l = RegQueryValueEx(hk_ccname,
+ L"ccname",
+ NULL,
+ &dwType,
+ (LPBYTE) new_ccname,
+ &dwSize);
+
+ if (l != ERROR_SUCCESS ||
+ dwType != REG_SZ) {
+ new_ccname[0] = L'\0';
+ }
+
+ if (_wcsicmp(new_ccname, reg_ccname)) {
+ k5_refresh_default_identity(ctx);
+ StringCbCopy(reg_ccname, sizeof(reg_ccname), new_ccname);
+ }
+
+ } else {
+ /* something went wrong */
+ rv = KHM_ERROR_UNKNOWN;
+ break;
+ }
+
+ } while (TRUE);
+
+ CloseHandle(h_notify);
+
+ _exit_0:
+
+ RegCloseKey(hk_ccname);
+
+ if (ctx)
+ pkrb5_free_context(ctx);
+
+ _exit:
+ ExitThread(rv);
+
+ /* not reached */
+ return rv;
+}
+
+khm_int32
+k5_msg_system_idpro(khm_int32 msg_type, khm_int32 msg_subtype,
+ khm_ui_4 uparam, void * vparam) {
+
+ switch(msg_subtype) {
+ case KMSG_SYSTEM_INIT:
+ {
+
+ pkrb5_init_context(&k5_identpro_ctx);
+ kcdb_identity_set_type(credtype_id_krb5);
+
+ if (KHM_FAILED(kcdb_type_get_id(TYPENAME_KRB5_PRINC,
+ &type_id_krb5_princ))) {
+ kcdb_type dt;
+ kcdb_type * pstr;
+
+ kcdb_type_get_info(KCDB_TYPE_STRING, &pstr);
+
+ ZeroMemory(&dt, sizeof(dt));
+ dt.name = TYPENAME_KRB5_PRINC;
+ dt.id = KCDB_TYPE_INVALID;
+ dt.flags = KCDB_TYPE_FLAG_CB_AUTO;
+ dt.cb_min = pstr->cb_min;
+ dt.cb_max = pstr->cb_max;
+ dt.toString = pstr->toString;
+ dt.isValid = pstr->isValid;
+ dt.comp = k5_ident_name_comp_func;
+ dt.dup = pstr->dup;
+
+ kcdb_type_register(&dt, &type_id_krb5_princ);
+
+ type_regd_krb5_princ = TRUE;
+
+ kcdb_type_release_info(pstr);
+ }
+
+ if (type_id_krb5_princ != -1) {
+ kcdb_attrib * attr;
+
+ kcdb_attrib_get_info(KCDB_ATTR_ID_NAME, &attr);
+
+ attr->type = type_id_krb5_princ;
+
+ kcdb_attrib_release_info(attr);
+ }
+
+ h_ccname_exit_event = CreateEvent(NULL, FALSE, FALSE, NULL);
+ if (h_ccname_exit_event) {
+ h_ccname_thread = CreateThread(NULL,
+ 200 * 1024,
+ k5_ccname_monitor_thread,
+ NULL,
+ 0,
+ NULL);
+ } else {
+ h_ccname_thread = NULL;
+ }
+ }
+ break;
+
+ case KMSG_SYSTEM_EXIT:
+ {
+
+ if (h_ccname_thread) {
+ SetEvent(h_ccname_exit_event);
+ WaitForSingleObject(h_ccname_thread, INFINITE);
+ CloseHandle(h_ccname_thread);
+ CloseHandle(h_ccname_exit_event);
+
+ h_ccname_exit_event = NULL;
+ h_ccname_thread = NULL;
+ }
+
+ if (k5_identpro_ctx) {
+ pkrb5_free_context(k5_identpro_ctx);
+ k5_identpro_ctx = NULL;
+ }
+
+ if (type_id_krb5_princ != -1) {
+ kcdb_attrib * attr;
+
+ kcdb_attrib_get_info(KCDB_ATTR_ID_NAME, &attr);
+
+ attr->type = KCDB_TYPE_STRING;
+
+ kcdb_attrib_release_info(attr);
+ }
+
+ /* allow a brief moment for any stale references to die */
+ Sleep(100);
+
+ if (type_regd_krb5_princ) {
+ kcdb_type_unregister(type_id_krb5_princ);
+ }
+ }
+ break;
+ }
+
+ return KHM_ERROR_SUCCESS;
+}
+
+khm_int32 KHMAPI
+k5_ident_callback(khm_int32 msg_type, khm_int32 msg_subtype,
+ khm_ui_4 uparam, void * vparam) {
+ switch(msg_type) {
+ case KMSG_SYSTEM:
+ return k5_msg_system_idpro(msg_type, msg_subtype, uparam, vparam);
+
+ case KMSG_IDENT:
+ return k5_msg_ident(msg_type, msg_subtype, uparam, vparam);
+ }
+
+ return KHM_ERROR_SUCCESS;
+}
diff --git a/src/windows/identity/plugins/krb5/krb5main.c b/src/windows/identity/plugins/krb5/krb5main.c
index 3d2f2c0e95..befa7a9808 100644
--- a/src/windows/identity/plugins/krb5/krb5main.c
+++ b/src/windows/identity/plugins/krb5/krb5main.c
@@ -1,497 +1,497 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<krbcred.h>
-#include<kherror.h>
-
-kmm_module h_khModule; /* KMM's handle to this module */
-HINSTANCE hInstance;
-HMODULE hResModule; /* HMODULE to the resource library */
-const wchar_t * k5_facility = L"Krb5Cred";
-
-khm_int32 type_id_enctype = -1;
-khm_int32 type_id_addr_list = -1;
-khm_int32 type_id_krb5_flags = -1;
-khm_int32 type_id_krb5_princ = -1;
-khm_int32 type_id_kvno = -1;
-
-BOOL type_regd_enctype = FALSE;
-BOOL type_regd_addr_list = FALSE;
-BOOL type_regd_krb5_flags = FALSE;
-BOOL type_regd_krb5_princ = FALSE;
-BOOL type_regd_kvno = FALSE;
-
-khm_int32 attr_id_key_enctype = -1;
-khm_int32 attr_id_tkt_enctype = -1;
-khm_int32 attr_id_addr_list = -1;
-khm_int32 attr_id_krb5_flags = -1;
-khm_int32 attr_id_krb5_ccname = -1;
-khm_int32 attr_id_kvno = -1;
-khm_int32 attr_id_krb5_idflags = -1;
-
-BOOL attr_regd_key_enctype = FALSE;
-BOOL attr_regd_tkt_enctype = FALSE;
-BOOL attr_regd_addr_list = FALSE;
-BOOL attr_regd_krb5_flags = FALSE;
-BOOL attr_regd_krb5_ccname = FALSE;
-BOOL attr_regd_kvno = FALSE;
-BOOL attr_regd_krb5_idflags = FALSE;
-
-khm_handle csp_plugins = NULL;
-khm_handle csp_krbcred = NULL;
-khm_handle csp_params = NULL;
-
-BOOL is_k5_identpro = TRUE;
-
-khm_ui_4 k5_commctl_version;
-
-kmm_module_locale locales[] = {
- LOCALE_DEF(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US), L"krb5cred_en_us.dll", KMM_MLOC_FLAG_DEFAULT)
-};
-int n_locales = ARRAYLENGTH(locales);
-
-/* These two should not do anything */
-void init_krb() {
-}
-
-void exit_krb() {
-}
-
-/* called by the NetIDMgr module manager */
-KHMEXP khm_int32 KHMAPI init_module(kmm_module h_module) {
- khm_int32 rv = KHM_ERROR_SUCCESS;
- kmm_plugin_reg pi;
- wchar_t buf[256];
-
- h_khModule = h_module;
-
- rv = kmm_set_locale_info(h_module, locales, n_locales);
- if(KHM_SUCCEEDED(rv)) {
- hResModule = kmm_get_resource_hmodule(h_module);
- } else
- goto _exit;
-
- k5_commctl_version = khm_get_commctl_version(NULL);
-
- /* register the plugin */
- ZeroMemory(&pi, sizeof(pi));
- pi.name = KRB5_PLUGIN_NAME;
- pi.type = KHM_PITYPE_CRED;
- pi.icon = LoadImage(hResModule, MAKEINTRESOURCE(IDI_PLUGIN),
- IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR | LR_DEFAULTSIZE);
- pi.flags = 0;
- pi.msg_proc = k5_msg_callback;
- pi.description = buf;
- pi.dependencies = NULL;
- LoadString(hResModule, IDS_PLUGIN_DESC,
- buf, ARRAYLENGTH(buf));
- kmm_provide_plugin(h_module, &pi);
-
- ZeroMemory(&pi, sizeof(pi));
- pi.name = KRB5_IDENTPRO_NAME;
- pi.type = KHM_PITYPE_IDENT;
- pi.icon = LoadImage(hResModule, MAKEINTRESOURCE(IDI_PLUGIN),
- IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR | LR_DEFAULTSIZE);
- pi.flags = 0;
- pi.msg_proc = k5_ident_callback;
- pi.description = buf;
- pi.dependencies = KRB5_PLUGIN_NAME L"\0";
- LoadString(hResModule, IDS_IDENTPRO_DESC,
- buf, ARRAYLENGTH(buf));
- kmm_provide_plugin(h_module, &pi);
-
- if(KHM_FAILED(rv = init_imports()))
- goto _exit;
-
- if(KHM_FAILED(rv = init_error_funcs()))
- goto _exit;
-
- /* Register common data types */
- if(KHM_FAILED(kcdb_type_get_id(TYPENAME_ENCTYPE, &type_id_enctype))) {
- kcdb_type type;
- kcdb_type *t32;
-
- kcdb_type_get_info(KCDB_TYPE_INT32, &t32);
-
- type.id = KCDB_TYPE_INVALID;
- type.name = TYPENAME_ENCTYPE;
- type.flags = KCDB_TYPE_FLAG_CB_FIXED;
- type.cb_max = t32->cb_max;
- type.cb_min = t32->cb_min;
- type.isValid = t32->isValid;
- type.comp = t32->comp;
- type.dup = t32->dup;
- type.toString = enctype_toString;
-
- rv = kcdb_type_register(&type, &type_id_enctype);
- kcdb_type_release_info(t32);
-
- if(KHM_FAILED(rv))
- goto _exit;
- type_regd_enctype = TRUE;
- }
-
- if(KHM_FAILED(kcdb_type_get_id(TYPENAME_ADDR_LIST, &type_id_addr_list))) {
- kcdb_type type;
- kcdb_type *tdata;
-
- kcdb_type_get_info(KCDB_TYPE_DATA, &tdata);
-
- type.id = KCDB_TYPE_INVALID;
- type.name = TYPENAME_ADDR_LIST;
- type.flags = KCDB_TYPE_FLAG_CB_MIN;
- type.cb_min = 0;
- type.cb_max = 0;
- type.isValid = tdata->isValid;
- type.comp = addr_list_comp;
- type.dup = tdata->dup;
- type.toString = addr_list_toString;
-
- rv = kcdb_type_register(&type, &type_id_addr_list);
- kcdb_type_release_info(tdata);
-
- if(KHM_FAILED(rv))
- goto _exit;
- type_regd_addr_list = TRUE;
- }
-
- if(KHM_FAILED(kcdb_type_get_id(TYPENAME_KRB5_FLAGS, &type_id_krb5_flags))) {
- kcdb_type type;
- kcdb_type *t32;
-
- kcdb_type_get_info(KCDB_TYPE_INT32, &t32);
-
- type.id = KCDB_TYPE_INVALID;
- type.name = TYPENAME_KRB5_FLAGS;
- type.flags = KCDB_TYPE_FLAG_CB_FIXED;
- type.cb_max = t32->cb_max;
- type.cb_min = t32->cb_min;
- type.isValid = t32->isValid;
- type.comp = t32->comp;
- type.dup = t32->dup;
- type.toString = krb5flags_toString;
-
- rv = kcdb_type_register(&type, &type_id_krb5_flags);
- kcdb_type_release_info(t32);
-
- if(KHM_FAILED(rv))
- goto _exit;
- type_regd_krb5_flags = TRUE;
- }
-
- if (KHM_FAILED(kcdb_type_get_id(TYPENAME_KVNO, &type_id_kvno))) {
- kcdb_type type;
- kcdb_type *t32;
-
- kcdb_type_get_info(KCDB_TYPE_INT32, &t32);
-
- type.id = KCDB_TYPE_INVALID;
- type.name = TYPENAME_KVNO;
- type.flags = KCDB_TYPE_FLAG_CB_FIXED;
- type.cb_max = t32->cb_max;
- type.cb_min = t32->cb_min;
- type.isValid = t32->isValid;
- type.comp = t32->comp;
- type.dup = t32->dup;
- type.toString = kvno_toString;
-
- rv = kcdb_type_register(&type, &type_id_kvno);
- kcdb_type_release_info(t32);
-
- if (KHM_FAILED(rv))
- goto _exit;
-
- type_regd_kvno = TRUE;
- }
-
- /* Register common attributes */
- if(KHM_FAILED(kcdb_attrib_get_id(ATTRNAME_KEY_ENCTYPE, &attr_id_key_enctype))) {
- kcdb_attrib attrib;
- wchar_t sbuf[KCDB_MAXCCH_SHORT_DESC];
- wchar_t lbuf[KCDB_MAXCCH_SHORT_DESC];
- /* although we are loading a long descriptoin, it still fits
- in the short descriptoin buffer */
-
- ZeroMemory(&attrib, sizeof(attrib));
-
- attrib.name = ATTRNAME_KEY_ENCTYPE;
- attrib.id = KCDB_ATTR_INVALID;
- attrib.type = type_id_enctype;
- attrib.flags = KCDB_ATTR_FLAG_TRANSIENT;
- LoadString(hResModule, IDS_KEY_ENCTYPE_SHORT_DESC, sbuf, ARRAYLENGTH(sbuf));
- LoadString(hResModule, IDS_KEY_ENCTYPE_LONG_DESC, lbuf, ARRAYLENGTH(lbuf));
- attrib.short_desc = sbuf;
- attrib.long_desc = lbuf;
-
- rv = kcdb_attrib_register(&attrib, &attr_id_key_enctype);
-
- if(KHM_FAILED(rv))
- goto _exit;
-
- attr_regd_key_enctype = TRUE;
- }
-
- if(KHM_FAILED(kcdb_attrib_get_id(ATTRNAME_TKT_ENCTYPE, &attr_id_tkt_enctype))) {
- kcdb_attrib attrib;
- wchar_t sbuf[KCDB_MAXCCH_SHORT_DESC];
- wchar_t lbuf[KCDB_MAXCCH_SHORT_DESC];
- /* although we are loading a long descriptoin, it still fits
- in the short descriptoin buffer */
-
- ZeroMemory(&attrib, sizeof(attrib));
-
- attrib.name = ATTRNAME_TKT_ENCTYPE;
- attrib.id = KCDB_ATTR_INVALID;
- attrib.type = type_id_enctype;
- attrib.flags = KCDB_ATTR_FLAG_TRANSIENT;
- LoadString(hResModule, IDS_TKT_ENCTYPE_SHORT_DESC, sbuf, ARRAYLENGTH(sbuf));
- LoadString(hResModule, IDS_TKT_ENCTYPE_LONG_DESC, lbuf, ARRAYLENGTH(lbuf));
- attrib.short_desc = sbuf;
- attrib.long_desc = lbuf;
-
- rv = kcdb_attrib_register(&attrib, &attr_id_tkt_enctype);
-
- if(KHM_FAILED(rv))
- goto _exit;
-
- attr_regd_tkt_enctype = TRUE;
- }
-
- if(KHM_FAILED(kcdb_attrib_get_id(ATTRNAME_ADDR_LIST, &attr_id_addr_list))) {
- kcdb_attrib attrib;
- wchar_t sbuf[KCDB_MAXCCH_SHORT_DESC];
- wchar_t lbuf[KCDB_MAXCCH_SHORT_DESC];
- /* although we are loading a long descriptoin, it still fits
- in the short descriptoin buffer */
-
- ZeroMemory(&attrib, sizeof(attrib));
-
- attrib.name = ATTRNAME_ADDR_LIST;
- attrib.id = KCDB_ATTR_INVALID;
- attrib.type = type_id_addr_list;
- attrib.flags = KCDB_ATTR_FLAG_TRANSIENT;
- LoadString(hResModule, IDS_ADDR_LIST_SHORT_DESC, sbuf, ARRAYLENGTH(sbuf));
- LoadString(hResModule, IDS_ADDR_LIST_LONG_DESC, lbuf, ARRAYLENGTH(lbuf));
- attrib.short_desc = sbuf;
- attrib.long_desc = lbuf;
-
- rv = kcdb_attrib_register(&attrib, &attr_id_addr_list);
-
- if(KHM_FAILED(rv))
- goto _exit;
-
- attr_regd_addr_list = TRUE;
- }
-
- if(KHM_FAILED(kcdb_attrib_get_id(ATTRNAME_KRB5_FLAGS, &attr_id_krb5_flags))) {
- kcdb_attrib attrib;
- wchar_t sbuf[KCDB_MAXCCH_SHORT_DESC];
-
- /* although we are loading a long descriptoin, it still fits
- in the short descriptoin buffer */
-
- ZeroMemory(&attrib, sizeof(attrib));
-
- attrib.name = ATTRNAME_KRB5_FLAGS;
- attrib.id = KCDB_ATTR_INVALID;
- attrib.type = type_id_krb5_flags;
- attrib.flags = KCDB_ATTR_FLAG_TRANSIENT;
- LoadString(hResModule, IDS_KRB5_FLAGS_SHORT_DESC, sbuf, ARRAYLENGTH(sbuf));
- attrib.short_desc = sbuf;
- attrib.long_desc = NULL;
-
- rv = kcdb_attrib_register(&attrib, &attr_id_krb5_flags);
-
- if(KHM_FAILED(rv))
- goto _exit;
-
- attr_regd_krb5_flags = TRUE;
- }
-
- if(KHM_FAILED(kcdb_attrib_get_id(ATTRNAME_KRB5_CCNAME, &attr_id_krb5_ccname))) {
- kcdb_attrib attrib;
- wchar_t sbuf[KCDB_MAXCCH_SHORT_DESC];
- wchar_t lbuf[KCDB_MAXCCH_SHORT_DESC];
- /* although we are loading a long descriptoin, it still fits
- in the short descriptoin buffer */
-
- ZeroMemory(&attrib, sizeof(attrib));
-
- attrib.name = ATTRNAME_KRB5_CCNAME;
- attrib.id = KCDB_ATTR_INVALID;
- attrib.type = KCDB_TYPE_STRING;
- attrib.flags =
- KCDB_ATTR_FLAG_PROPERTY |
- KCDB_ATTR_FLAG_TRANSIENT;
- LoadString(hResModule, IDS_KRB5_CCNAME_SHORT_DESC, sbuf, ARRAYLENGTH(sbuf));
- LoadString(hResModule, IDS_KRB5_CCNAME_LONG_DESC, lbuf, ARRAYLENGTH(lbuf));
- attrib.short_desc = sbuf;
- attrib.long_desc = lbuf;
-
- rv = kcdb_attrib_register(&attrib, &attr_id_krb5_ccname);
-
- if(KHM_FAILED(rv))
- goto _exit;
-
- attr_regd_krb5_ccname = TRUE;
- }
-
- if (KHM_FAILED(kcdb_attrib_get_id(ATTRNAME_KVNO, &attr_id_kvno))) {
- kcdb_attrib attrib;
- wchar_t sbuf[KCDB_MAXCCH_SHORT_DESC];
- wchar_t lbuf[KCDB_MAXCCH_LONG_DESC];
- /* although we are loading a long description, it still fits
- in the short description buffer */
-
- ZeroMemory(&attrib, sizeof(attrib));
-
- attrib.name = ATTRNAME_KVNO;
- attrib.id = KCDB_ATTR_INVALID;
- attrib.type = type_id_kvno;
- attrib.flags = KCDB_ATTR_FLAG_TRANSIENT;
- LoadString(hResModule, IDS_KVNO_SHORT_DESC, sbuf, ARRAYLENGTH(sbuf));
- LoadString(hResModule, IDS_KVNO_LONG_DESC, lbuf, ARRAYLENGTH(lbuf));
- attrib.short_desc = sbuf;
- attrib.long_desc = lbuf;
-
- rv = kcdb_attrib_register(&attrib, &attr_id_kvno);
-
- if (KHM_FAILED(rv))
- goto _exit;
-
- attr_regd_kvno = TRUE;
- }
-
- if (KHM_FAILED(kcdb_attrib_get_id(ATTRNAME_KRB5_IDFLAGS, &attr_id_krb5_idflags))) {
- kcdb_attrib attrib;
-
- ZeroMemory(&attrib, sizeof(attrib));
-
- attrib.name = ATTRNAME_KRB5_IDFLAGS;
- attrib.id = KCDB_ATTR_INVALID;
- attrib.type = KCDB_TYPE_INT32;
- attrib.flags = KCDB_ATTR_FLAG_PROPERTY |
- KCDB_ATTR_FLAG_HIDDEN;
- /* we don't bother localizing these strings since the
- attribute is hidden. The user will not see these
- descriptions anyway. */
- attrib.short_desc = L"Krb5 ID flags";
- attrib.long_desc = L"Kerberos 5 Identity Flags";
-
- rv = kcdb_attrib_register(&attrib, &attr_id_krb5_idflags);
-
- if (KHM_FAILED(rv))
- goto _exit;
-
- attr_regd_krb5_idflags = TRUE;
- }
-
- rv = kmm_get_plugins_config(0, &csp_plugins);
- if(KHM_FAILED(rv)) goto _exit;
-
- rv = khc_load_schema(csp_plugins, schema_krbconfig);
- if(KHM_FAILED(rv)) goto _exit;
-
- rv = khc_open_space(csp_plugins, CSNAME_KRB5CRED, 0, &csp_krbcred);
- if(KHM_FAILED(rv)) goto _exit;
-
- rv = khc_open_space(csp_krbcred, CSNAME_PARAMS, 0, &csp_params);
- if(KHM_FAILED(rv)) goto _exit;
-
-_exit:
- return rv;
-}
-
-/* called by the NetIDMgr module manager */
-KHMEXP khm_int32 KHMAPI exit_module(kmm_module h_module) {
- exit_imports();
- exit_error_funcs();
-
- if(attr_regd_key_enctype)
- kcdb_attrib_unregister(attr_id_key_enctype);
- if(attr_regd_tkt_enctype)
- kcdb_attrib_unregister(attr_id_tkt_enctype);
- if(attr_regd_addr_list)
- kcdb_attrib_unregister(attr_id_addr_list);
- if(attr_regd_krb5_flags)
- kcdb_attrib_unregister(attr_id_krb5_flags);
- if(attr_regd_krb5_ccname)
- kcdb_attrib_unregister(attr_id_krb5_ccname);
- if(attr_regd_kvno)
- kcdb_attrib_unregister(attr_id_kvno);
- if(attr_regd_krb5_idflags)
- kcdb_attrib_unregister(attr_id_krb5_idflags);
-
- if(type_regd_enctype)
- kcdb_type_unregister(type_id_enctype);
- if(type_regd_addr_list)
- kcdb_type_unregister(type_id_addr_list);
- if(type_regd_krb5_flags)
- kcdb_type_unregister(type_id_krb5_flags);
- if(type_regd_kvno)
- kcdb_type_unregister(type_id_kvno);
-
- if(csp_params) {
- khc_close_space(csp_params);
- csp_params = NULL;
- }
-
- if(csp_krbcred) {
- khc_close_space(csp_krbcred);
- csp_krbcred = NULL;
- }
-
- if(csp_plugins) {
- khc_unload_schema(csp_plugins, schema_krbconfig);
- khc_close_space(csp_plugins);
- csp_plugins = NULL;
- }
-
- return KHM_ERROR_SUCCESS; /* the return code is ignored */
-}
-
-BOOL WINAPI DllMain(
- HINSTANCE hinstDLL,
- DWORD fdwReason,
- LPVOID lpvReserved
-)
-{
- switch(fdwReason) {
- case DLL_PROCESS_ATTACH:
- hInstance = hinstDLL;
- init_krb();
- break;
- case DLL_PROCESS_DETACH:
- exit_krb();
- break;
- case DLL_THREAD_ATTACH:
- break;
- case DLL_THREAD_DETACH:
- break;
- }
-
- return TRUE;
-}
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<krbcred.h>
+#include<kherror.h>
+
+kmm_module h_khModule; /* KMM's handle to this module */
+HINSTANCE hInstance;
+HMODULE hResModule; /* HMODULE to the resource library */
+const wchar_t * k5_facility = L"Krb5Cred";
+
+khm_int32 type_id_enctype = -1;
+khm_int32 type_id_addr_list = -1;
+khm_int32 type_id_krb5_flags = -1;
+khm_int32 type_id_krb5_princ = -1;
+khm_int32 type_id_kvno = -1;
+
+BOOL type_regd_enctype = FALSE;
+BOOL type_regd_addr_list = FALSE;
+BOOL type_regd_krb5_flags = FALSE;
+BOOL type_regd_krb5_princ = FALSE;
+BOOL type_regd_kvno = FALSE;
+
+khm_int32 attr_id_key_enctype = -1;
+khm_int32 attr_id_tkt_enctype = -1;
+khm_int32 attr_id_addr_list = -1;
+khm_int32 attr_id_krb5_flags = -1;
+khm_int32 attr_id_krb5_ccname = -1;
+khm_int32 attr_id_kvno = -1;
+khm_int32 attr_id_krb5_idflags = -1;
+
+BOOL attr_regd_key_enctype = FALSE;
+BOOL attr_regd_tkt_enctype = FALSE;
+BOOL attr_regd_addr_list = FALSE;
+BOOL attr_regd_krb5_flags = FALSE;
+BOOL attr_regd_krb5_ccname = FALSE;
+BOOL attr_regd_kvno = FALSE;
+BOOL attr_regd_krb5_idflags = FALSE;
+
+khm_handle csp_plugins = NULL;
+khm_handle csp_krbcred = NULL;
+khm_handle csp_params = NULL;
+
+BOOL is_k5_identpro = TRUE;
+
+khm_ui_4 k5_commctl_version;
+
+kmm_module_locale locales[] = {
+ LOCALE_DEF(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US), L"krb5cred_en_us.dll", KMM_MLOC_FLAG_DEFAULT)
+};
+int n_locales = ARRAYLENGTH(locales);
+
+/* These two should not do anything */
+void init_krb() {
+}
+
+void exit_krb() {
+}
+
+/* called by the NetIDMgr module manager */
+KHMEXP khm_int32 KHMAPI init_module(kmm_module h_module) {
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+ kmm_plugin_reg pi;
+ wchar_t buf[256];
+
+ h_khModule = h_module;
+
+ rv = kmm_set_locale_info(h_module, locales, n_locales);
+ if(KHM_SUCCEEDED(rv)) {
+ hResModule = kmm_get_resource_hmodule(h_module);
+ } else
+ goto _exit;
+
+ k5_commctl_version = khm_get_commctl_version(NULL);
+
+ /* register the plugin */
+ ZeroMemory(&pi, sizeof(pi));
+ pi.name = KRB5_PLUGIN_NAME;
+ pi.type = KHM_PITYPE_CRED;
+ pi.icon = LoadImage(hResModule, MAKEINTRESOURCE(IDI_PLUGIN),
+ IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR | LR_DEFAULTSIZE);
+ pi.flags = 0;
+ pi.msg_proc = k5_msg_callback;
+ pi.description = buf;
+ pi.dependencies = NULL;
+ LoadString(hResModule, IDS_PLUGIN_DESC,
+ buf, ARRAYLENGTH(buf));
+ kmm_provide_plugin(h_module, &pi);
+
+ ZeroMemory(&pi, sizeof(pi));
+ pi.name = KRB5_IDENTPRO_NAME;
+ pi.type = KHM_PITYPE_IDENT;
+ pi.icon = LoadImage(hResModule, MAKEINTRESOURCE(IDI_PLUGIN),
+ IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR | LR_DEFAULTSIZE);
+ pi.flags = 0;
+ pi.msg_proc = k5_ident_callback;
+ pi.description = buf;
+ pi.dependencies = KRB5_PLUGIN_NAME L"\0";
+ LoadString(hResModule, IDS_IDENTPRO_DESC,
+ buf, ARRAYLENGTH(buf));
+ kmm_provide_plugin(h_module, &pi);
+
+ if(KHM_FAILED(rv = init_imports()))
+ goto _exit;
+
+ if(KHM_FAILED(rv = init_error_funcs()))
+ goto _exit;
+
+ /* Register common data types */
+ if(KHM_FAILED(kcdb_type_get_id(TYPENAME_ENCTYPE, &type_id_enctype))) {
+ kcdb_type type;
+ kcdb_type *t32;
+
+ kcdb_type_get_info(KCDB_TYPE_INT32, &t32);
+
+ type.id = KCDB_TYPE_INVALID;
+ type.name = TYPENAME_ENCTYPE;
+ type.flags = KCDB_TYPE_FLAG_CB_FIXED;
+ type.cb_max = t32->cb_max;
+ type.cb_min = t32->cb_min;
+ type.isValid = t32->isValid;
+ type.comp = t32->comp;
+ type.dup = t32->dup;
+ type.toString = enctype_toString;
+
+ rv = kcdb_type_register(&type, &type_id_enctype);
+ kcdb_type_release_info(t32);
+
+ if(KHM_FAILED(rv))
+ goto _exit;
+ type_regd_enctype = TRUE;
+ }
+
+ if(KHM_FAILED(kcdb_type_get_id(TYPENAME_ADDR_LIST, &type_id_addr_list))) {
+ kcdb_type type;
+ kcdb_type *tdata;
+
+ kcdb_type_get_info(KCDB_TYPE_DATA, &tdata);
+
+ type.id = KCDB_TYPE_INVALID;
+ type.name = TYPENAME_ADDR_LIST;
+ type.flags = KCDB_TYPE_FLAG_CB_MIN;
+ type.cb_min = 0;
+ type.cb_max = 0;
+ type.isValid = tdata->isValid;
+ type.comp = addr_list_comp;
+ type.dup = tdata->dup;
+ type.toString = addr_list_toString;
+
+ rv = kcdb_type_register(&type, &type_id_addr_list);
+ kcdb_type_release_info(tdata);
+
+ if(KHM_FAILED(rv))
+ goto _exit;
+ type_regd_addr_list = TRUE;
+ }
+
+ if(KHM_FAILED(kcdb_type_get_id(TYPENAME_KRB5_FLAGS, &type_id_krb5_flags))) {
+ kcdb_type type;
+ kcdb_type *t32;
+
+ kcdb_type_get_info(KCDB_TYPE_INT32, &t32);
+
+ type.id = KCDB_TYPE_INVALID;
+ type.name = TYPENAME_KRB5_FLAGS;
+ type.flags = KCDB_TYPE_FLAG_CB_FIXED;
+ type.cb_max = t32->cb_max;
+ type.cb_min = t32->cb_min;
+ type.isValid = t32->isValid;
+ type.comp = t32->comp;
+ type.dup = t32->dup;
+ type.toString = krb5flags_toString;
+
+ rv = kcdb_type_register(&type, &type_id_krb5_flags);
+ kcdb_type_release_info(t32);
+
+ if(KHM_FAILED(rv))
+ goto _exit;
+ type_regd_krb5_flags = TRUE;
+ }
+
+ if (KHM_FAILED(kcdb_type_get_id(TYPENAME_KVNO, &type_id_kvno))) {
+ kcdb_type type;
+ kcdb_type *t32;
+
+ kcdb_type_get_info(KCDB_TYPE_INT32, &t32);
+
+ type.id = KCDB_TYPE_INVALID;
+ type.name = TYPENAME_KVNO;
+ type.flags = KCDB_TYPE_FLAG_CB_FIXED;
+ type.cb_max = t32->cb_max;
+ type.cb_min = t32->cb_min;
+ type.isValid = t32->isValid;
+ type.comp = t32->comp;
+ type.dup = t32->dup;
+ type.toString = kvno_toString;
+
+ rv = kcdb_type_register(&type, &type_id_kvno);
+ kcdb_type_release_info(t32);
+
+ if (KHM_FAILED(rv))
+ goto _exit;
+
+ type_regd_kvno = TRUE;
+ }
+
+ /* Register common attributes */
+ if(KHM_FAILED(kcdb_attrib_get_id(ATTRNAME_KEY_ENCTYPE, &attr_id_key_enctype))) {
+ kcdb_attrib attrib;
+ wchar_t sbuf[KCDB_MAXCCH_SHORT_DESC];
+ wchar_t lbuf[KCDB_MAXCCH_SHORT_DESC];
+ /* although we are loading a long descriptoin, it still fits
+ in the short descriptoin buffer */
+
+ ZeroMemory(&attrib, sizeof(attrib));
+
+ attrib.name = ATTRNAME_KEY_ENCTYPE;
+ attrib.id = KCDB_ATTR_INVALID;
+ attrib.type = type_id_enctype;
+ attrib.flags = KCDB_ATTR_FLAG_TRANSIENT;
+ LoadString(hResModule, IDS_KEY_ENCTYPE_SHORT_DESC, sbuf, ARRAYLENGTH(sbuf));
+ LoadString(hResModule, IDS_KEY_ENCTYPE_LONG_DESC, lbuf, ARRAYLENGTH(lbuf));
+ attrib.short_desc = sbuf;
+ attrib.long_desc = lbuf;
+
+ rv = kcdb_attrib_register(&attrib, &attr_id_key_enctype);
+
+ if(KHM_FAILED(rv))
+ goto _exit;
+
+ attr_regd_key_enctype = TRUE;
+ }
+
+ if(KHM_FAILED(kcdb_attrib_get_id(ATTRNAME_TKT_ENCTYPE, &attr_id_tkt_enctype))) {
+ kcdb_attrib attrib;
+ wchar_t sbuf[KCDB_MAXCCH_SHORT_DESC];
+ wchar_t lbuf[KCDB_MAXCCH_SHORT_DESC];
+ /* although we are loading a long descriptoin, it still fits
+ in the short descriptoin buffer */
+
+ ZeroMemory(&attrib, sizeof(attrib));
+
+ attrib.name = ATTRNAME_TKT_ENCTYPE;
+ attrib.id = KCDB_ATTR_INVALID;
+ attrib.type = type_id_enctype;
+ attrib.flags = KCDB_ATTR_FLAG_TRANSIENT;
+ LoadString(hResModule, IDS_TKT_ENCTYPE_SHORT_DESC, sbuf, ARRAYLENGTH(sbuf));
+ LoadString(hResModule, IDS_TKT_ENCTYPE_LONG_DESC, lbuf, ARRAYLENGTH(lbuf));
+ attrib.short_desc = sbuf;
+ attrib.long_desc = lbuf;
+
+ rv = kcdb_attrib_register(&attrib, &attr_id_tkt_enctype);
+
+ if(KHM_FAILED(rv))
+ goto _exit;
+
+ attr_regd_tkt_enctype = TRUE;
+ }
+
+ if(KHM_FAILED(kcdb_attrib_get_id(ATTRNAME_ADDR_LIST, &attr_id_addr_list))) {
+ kcdb_attrib attrib;
+ wchar_t sbuf[KCDB_MAXCCH_SHORT_DESC];
+ wchar_t lbuf[KCDB_MAXCCH_SHORT_DESC];
+ /* although we are loading a long descriptoin, it still fits
+ in the short descriptoin buffer */
+
+ ZeroMemory(&attrib, sizeof(attrib));
+
+ attrib.name = ATTRNAME_ADDR_LIST;
+ attrib.id = KCDB_ATTR_INVALID;
+ attrib.type = type_id_addr_list;
+ attrib.flags = KCDB_ATTR_FLAG_TRANSIENT;
+ LoadString(hResModule, IDS_ADDR_LIST_SHORT_DESC, sbuf, ARRAYLENGTH(sbuf));
+ LoadString(hResModule, IDS_ADDR_LIST_LONG_DESC, lbuf, ARRAYLENGTH(lbuf));
+ attrib.short_desc = sbuf;
+ attrib.long_desc = lbuf;
+
+ rv = kcdb_attrib_register(&attrib, &attr_id_addr_list);
+
+ if(KHM_FAILED(rv))
+ goto _exit;
+
+ attr_regd_addr_list = TRUE;
+ }
+
+ if(KHM_FAILED(kcdb_attrib_get_id(ATTRNAME_KRB5_FLAGS, &attr_id_krb5_flags))) {
+ kcdb_attrib attrib;
+ wchar_t sbuf[KCDB_MAXCCH_SHORT_DESC];
+
+ /* although we are loading a long descriptoin, it still fits
+ in the short descriptoin buffer */
+
+ ZeroMemory(&attrib, sizeof(attrib));
+
+ attrib.name = ATTRNAME_KRB5_FLAGS;
+ attrib.id = KCDB_ATTR_INVALID;
+ attrib.type = type_id_krb5_flags;
+ attrib.flags = KCDB_ATTR_FLAG_TRANSIENT;
+ LoadString(hResModule, IDS_KRB5_FLAGS_SHORT_DESC, sbuf, ARRAYLENGTH(sbuf));
+ attrib.short_desc = sbuf;
+ attrib.long_desc = NULL;
+
+ rv = kcdb_attrib_register(&attrib, &attr_id_krb5_flags);
+
+ if(KHM_FAILED(rv))
+ goto _exit;
+
+ attr_regd_krb5_flags = TRUE;
+ }
+
+ if(KHM_FAILED(kcdb_attrib_get_id(ATTRNAME_KRB5_CCNAME, &attr_id_krb5_ccname))) {
+ kcdb_attrib attrib;
+ wchar_t sbuf[KCDB_MAXCCH_SHORT_DESC];
+ wchar_t lbuf[KCDB_MAXCCH_SHORT_DESC];
+ /* although we are loading a long descriptoin, it still fits
+ in the short descriptoin buffer */
+
+ ZeroMemory(&attrib, sizeof(attrib));
+
+ attrib.name = ATTRNAME_KRB5_CCNAME;
+ attrib.id = KCDB_ATTR_INVALID;
+ attrib.type = KCDB_TYPE_STRING;
+ attrib.flags =
+ KCDB_ATTR_FLAG_PROPERTY |
+ KCDB_ATTR_FLAG_TRANSIENT;
+ LoadString(hResModule, IDS_KRB5_CCNAME_SHORT_DESC, sbuf, ARRAYLENGTH(sbuf));
+ LoadString(hResModule, IDS_KRB5_CCNAME_LONG_DESC, lbuf, ARRAYLENGTH(lbuf));
+ attrib.short_desc = sbuf;
+ attrib.long_desc = lbuf;
+
+ rv = kcdb_attrib_register(&attrib, &attr_id_krb5_ccname);
+
+ if(KHM_FAILED(rv))
+ goto _exit;
+
+ attr_regd_krb5_ccname = TRUE;
+ }
+
+ if (KHM_FAILED(kcdb_attrib_get_id(ATTRNAME_KVNO, &attr_id_kvno))) {
+ kcdb_attrib attrib;
+ wchar_t sbuf[KCDB_MAXCCH_SHORT_DESC];
+ wchar_t lbuf[KCDB_MAXCCH_LONG_DESC];
+ /* although we are loading a long description, it still fits
+ in the short description buffer */
+
+ ZeroMemory(&attrib, sizeof(attrib));
+
+ attrib.name = ATTRNAME_KVNO;
+ attrib.id = KCDB_ATTR_INVALID;
+ attrib.type = type_id_kvno;
+ attrib.flags = KCDB_ATTR_FLAG_TRANSIENT;
+ LoadString(hResModule, IDS_KVNO_SHORT_DESC, sbuf, ARRAYLENGTH(sbuf));
+ LoadString(hResModule, IDS_KVNO_LONG_DESC, lbuf, ARRAYLENGTH(lbuf));
+ attrib.short_desc = sbuf;
+ attrib.long_desc = lbuf;
+
+ rv = kcdb_attrib_register(&attrib, &attr_id_kvno);
+
+ if (KHM_FAILED(rv))
+ goto _exit;
+
+ attr_regd_kvno = TRUE;
+ }
+
+ if (KHM_FAILED(kcdb_attrib_get_id(ATTRNAME_KRB5_IDFLAGS, &attr_id_krb5_idflags))) {
+ kcdb_attrib attrib;
+
+ ZeroMemory(&attrib, sizeof(attrib));
+
+ attrib.name = ATTRNAME_KRB5_IDFLAGS;
+ attrib.id = KCDB_ATTR_INVALID;
+ attrib.type = KCDB_TYPE_INT32;
+ attrib.flags = KCDB_ATTR_FLAG_PROPERTY |
+ KCDB_ATTR_FLAG_HIDDEN;
+ /* we don't bother localizing these strings since the
+ attribute is hidden. The user will not see these
+ descriptions anyway. */
+ attrib.short_desc = L"Krb5 ID flags";
+ attrib.long_desc = L"Kerberos 5 Identity Flags";
+
+ rv = kcdb_attrib_register(&attrib, &attr_id_krb5_idflags);
+
+ if (KHM_FAILED(rv))
+ goto _exit;
+
+ attr_regd_krb5_idflags = TRUE;
+ }
+
+ rv = kmm_get_plugins_config(0, &csp_plugins);
+ if(KHM_FAILED(rv)) goto _exit;
+
+ rv = khc_load_schema(csp_plugins, schema_krbconfig);
+ if(KHM_FAILED(rv)) goto _exit;
+
+ rv = khc_open_space(csp_plugins, CSNAME_KRB5CRED, 0, &csp_krbcred);
+ if(KHM_FAILED(rv)) goto _exit;
+
+ rv = khc_open_space(csp_krbcred, CSNAME_PARAMS, 0, &csp_params);
+ if(KHM_FAILED(rv)) goto _exit;
+
+_exit:
+ return rv;
+}
+
+/* called by the NetIDMgr module manager */
+KHMEXP khm_int32 KHMAPI exit_module(kmm_module h_module) {
+ exit_imports();
+ exit_error_funcs();
+
+ if(attr_regd_key_enctype)
+ kcdb_attrib_unregister(attr_id_key_enctype);
+ if(attr_regd_tkt_enctype)
+ kcdb_attrib_unregister(attr_id_tkt_enctype);
+ if(attr_regd_addr_list)
+ kcdb_attrib_unregister(attr_id_addr_list);
+ if(attr_regd_krb5_flags)
+ kcdb_attrib_unregister(attr_id_krb5_flags);
+ if(attr_regd_krb5_ccname)
+ kcdb_attrib_unregister(attr_id_krb5_ccname);
+ if(attr_regd_kvno)
+ kcdb_attrib_unregister(attr_id_kvno);
+ if(attr_regd_krb5_idflags)
+ kcdb_attrib_unregister(attr_id_krb5_idflags);
+
+ if(type_regd_enctype)
+ kcdb_type_unregister(type_id_enctype);
+ if(type_regd_addr_list)
+ kcdb_type_unregister(type_id_addr_list);
+ if(type_regd_krb5_flags)
+ kcdb_type_unregister(type_id_krb5_flags);
+ if(type_regd_kvno)
+ kcdb_type_unregister(type_id_kvno);
+
+ if(csp_params) {
+ khc_close_space(csp_params);
+ csp_params = NULL;
+ }
+
+ if(csp_krbcred) {
+ khc_close_space(csp_krbcred);
+ csp_krbcred = NULL;
+ }
+
+ if(csp_plugins) {
+ khc_unload_schema(csp_plugins, schema_krbconfig);
+ khc_close_space(csp_plugins);
+ csp_plugins = NULL;
+ }
+
+ return KHM_ERROR_SUCCESS; /* the return code is ignored */
+}
+
+BOOL WINAPI DllMain(
+ HINSTANCE hinstDLL,
+ DWORD fdwReason,
+ LPVOID lpvReserved
+)
+{
+ switch(fdwReason) {
+ case DLL_PROCESS_ATTACH:
+ hInstance = hinstDLL;
+ init_krb();
+ break;
+ case DLL_PROCESS_DETACH:
+ exit_krb();
+ break;
+ case DLL_THREAD_ATTACH:
+ break;
+ case DLL_THREAD_DETACH:
+ break;
+ }
+
+ return TRUE;
+}
diff --git a/src/windows/identity/plugins/krb5/krb5newcreds.c b/src/windows/identity/plugins/krb5/krb5newcreds.c
index edd64725da..d2458fe50e 100644
--- a/src/windows/identity/plugins/krb5/krb5newcreds.c
+++ b/src/windows/identity/plugins/krb5/krb5newcreds.c
@@ -1,2747 +1,2747 @@
-/*
- * Copyright (c) 2006 Secure Endpoints Inc.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<krbcred.h>
-#include<kherror.h>
-#include<khmsgtypes.h>
-#include<strsafe.h>
-#include<krb5.h>
-
-#include<commctrl.h>
-
-#include<assert.h>
-
-extern LPVOID k5_main_fiber;
-extern LPVOID k5_kinit_fiber;
-
-typedef struct k5_dlg_data_t {
- khui_new_creds * nc;
-
- khui_tracker tc_lifetime;
- khui_tracker tc_renew;
-
- BOOL dirty; /* is the data in sync with the
- configuration store? */
- BOOL sync; /* is the data in sync with the kinit
- request? */
- DWORD renewable;
- DWORD forwardable;
- DWORD proxiable;
- DWORD addressless;
- DWORD publicIP;
-
- wchar_t * cred_message; /* overrides the credential text, if
- non-NULL */
- BOOL pwd_change; /* force a password change */
-} k5_dlg_data;
-
-
-INT_PTR
-k5_handle_wm_initdialog(HWND hwnd,
- WPARAM wParam,
- LPARAM lParam)
-{
- HWND hw;
- k5_dlg_data * d;
- khui_new_creds_by_type * nct;
-
- d = PMALLOC(sizeof(*d));
- ZeroMemory(d, sizeof(*d));
- /* lParam is a pointer to a khui_new_creds structure */
- d->nc = (khui_new_creds *) lParam;
- khui_cw_find_type(d->nc, credtype_id_krb5, &nct);
-
-#pragma warning(push)
-#pragma warning(disable: 4244)
- SetWindowLongPtr(hwnd, DWLP_USER, (LPARAM) d);
-#pragma warning(pop)
-
- nct->aux = (LPARAM) d;
-
- if (d->nc->subtype == KMSG_CRED_NEW_CREDS) {
- khui_tracker_initialize(&d->tc_lifetime);
- khui_tracker_initialize(&d->tc_renew);
-
- hw = GetDlgItem(hwnd, IDC_NCK5_LIFETIME_EDIT);
- khui_tracker_install(hw, &d->tc_lifetime);
-
- hw = GetDlgItem(hwnd, IDC_NCK5_RENEW_EDIT);
- khui_tracker_install(hw, &d->tc_renew);
- }
- return TRUE;
-}
-
-INT_PTR
-k5_handle_wm_destroy(HWND hwnd,
- WPARAM wParam,
- LPARAM lParam)
-{
- k5_dlg_data * d;
- khui_new_creds_by_type * nct = NULL;
-
- d = (k5_dlg_data *) (LONG_PTR)
- GetWindowLongPtr(hwnd, DWLP_USER);
-
- if (!d)
- return TRUE;
-
- khui_cw_find_type(d->nc, credtype_id_krb5, &nct);
-
-#ifdef DEBUG
- assert(nct);
-#endif
-
- nct->aux = 0;
-
- if (d->nc->subtype == KMSG_CRED_NEW_CREDS) {
- khui_tracker_kill_controls(&d->tc_renew);
- khui_tracker_kill_controls(&d->tc_lifetime);
- }
-
- PFREE(d);
-
- return TRUE;
-}
-
-LRESULT
-k5_force_password_change(k5_dlg_data * d) {
- /* we are turning this dialog into a change password dialog... */
- wchar_t wbuf[KHUI_MAXCCH_BANNER];
-
- khui_cw_clear_prompts(d->nc);
-
- LoadString(hResModule, IDS_NC_PWD_BANNER,
- wbuf, ARRAYLENGTH(wbuf));
- khui_cw_begin_custom_prompts(d->nc, 3, NULL, wbuf);
-
- LoadString(hResModule, IDS_NC_PWD_PWD,
- wbuf, ARRAYLENGTH(wbuf));
- khui_cw_add_prompt(d->nc, KHUI_NCPROMPT_TYPE_PASSWORD,
- wbuf, NULL, KHUI_NCPROMPT_FLAG_HIDDEN);
-
- LoadString(hResModule, IDS_NC_PWD_NPWD,
- wbuf, ARRAYLENGTH(wbuf));
- khui_cw_add_prompt(d->nc, KHUI_NCPROMPT_TYPE_NEW_PASSWORD,
- wbuf, NULL, KHUI_NCPROMPT_FLAG_HIDDEN);
-
- LoadString(hResModule, IDS_NC_PWD_NPWD_AGAIN,
- wbuf, ARRAYLENGTH(wbuf));
- khui_cw_add_prompt(d->nc, KHUI_NCPROMPT_TYPE_NEW_PASSWORD_AGAIN,
- wbuf, NULL, KHUI_NCPROMPT_FLAG_HIDDEN);
-
- d->pwd_change = TRUE;
-
- if (is_k5_identpro &&
- d->nc->n_identities > 0 &&
- d->nc->identities[0]) {
-
- kcdb_identity_set_flags(d->nc->identities[0],
- KCDB_IDENT_FLAG_VALID,
- KCDB_IDENT_FLAG_VALID);
-
- }
-
- PostMessage(d->nc->hwnd, KHUI_WM_NC_NOTIFY,
- MAKEWPARAM(0, WMNC_UPDATE_CREDTEXT),
- (LPARAM) d->nc);
-
- return TRUE;
-}
-
-INT_PTR
-k5_handle_wmnc_notify(HWND hwnd,
- WPARAM wParam,
- LPARAM lParam)
-{
- switch(HIWORD(wParam)) {
- case WMNC_DIALOG_MOVE:
- {
- k5_dlg_data * d;
-
- d = (k5_dlg_data *)(LONG_PTR)
- GetWindowLongPtr(hwnd, DWLP_USER);
-
- if (d->nc->subtype == KMSG_CRED_NEW_CREDS) {
- khui_tracker_reposition(&d->tc_lifetime);
- khui_tracker_reposition(&d->tc_renew);
- }
-
- return TRUE;
- }
- break;
-
- case WMNC_DIALOG_SETUP:
- {
- k5_dlg_data * d;
- BOOL old_sync;
-
- d = (k5_dlg_data *)(LONG_PTR)
- GetWindowLongPtr(hwnd, DWLP_USER);
-
- if (d->nc->subtype == KMSG_CRED_PASSWORD)
- return TRUE;
-
- /* we save the value of the 'sync' field here because some
- of the notifications that are generated while setting
- the controls overwrite the field. */
- old_sync = d->sync;
-
- /* need to update the controls with d->* */
- SendDlgItemMessage(hwnd, IDC_NCK5_RENEWABLE,
- BM_SETCHECK,
- (d->renewable? BST_CHECKED : BST_UNCHECKED),
- 0);
- EnableWindow(GetDlgItem(hwnd, IDC_NCK5_RENEW_EDIT),
- !!d->renewable);
-
- khui_tracker_refresh(&d->tc_lifetime);
- khui_tracker_refresh(&d->tc_renew);
-
- SendDlgItemMessage(hwnd, IDC_NCK5_FORWARDABLE,
- BM_SETCHECK,
- (d->forwardable ? BST_CHECKED : BST_UNCHECKED),
- 0);
-
- SendDlgItemMessage(hwnd, IDC_NCK5_ADDRESS,
- BM_SETCHECK,
- (d->addressless ? BST_CHECKED : BST_UNCHECKED),
- 0);
-
- SendDlgItemMessage(hwnd, IDC_NCK5_PUBLICIP,
- IPM_SETADDRESS,
- 0, d->publicIP);
-
- EnableWindow(GetDlgItem(hwnd, IDC_NCK5_PUBLICIP), !d->addressless);
-
- d->sync = old_sync;
- }
- break;
-
- case WMNC_CREDTEXT_LINK:
- {
- k5_dlg_data * d;
- khui_htwnd_link * l;
- khui_new_creds * nc;
- wchar_t linktext[128];
-
- d = (k5_dlg_data *)(LONG_PTR)
- GetWindowLongPtr(hwnd, DWLP_USER);
- nc = d->nc;
- l = (khui_htwnd_link *) lParam;
-
- if (!l)
- break;
-
- StringCchCopyN(linktext, ARRAYLENGTH(linktext),
- l->id, l->id_len);
-
- if (!wcscmp(linktext, L"Krb5Cred:!Passwd")) {
- return k5_force_password_change(d);
- }
- }
- break;
-
- case WMNC_UPDATE_CREDTEXT:
- {
- k5_dlg_data * d;
- khui_new_creds * nc;
- khui_new_creds_by_type * nct;
- wchar_t sbuf[1024];
- wchar_t fbuf[256];
- wchar_t tbuf[256];
- size_t cbsize;
- khm_int32 flags;
-
- d = (k5_dlg_data *)(LONG_PTR)
- GetWindowLongPtr(hwnd, DWLP_USER);
- nc = d->nc;
- khui_cw_find_type(nc, credtype_id_krb5, &nct);
-
- if(nct == NULL)
- break;
-
- if(nct->credtext)
- PFREE(nct->credtext);
- nct->credtext = NULL;
-
- tbuf[0] = L'\0';
-
- if (nc->n_identities > 0 &&
- KHM_SUCCEEDED(kcdb_identity_get_flags(nc->identities[0],
- &flags)) &&
- (flags & KCDB_IDENT_FLAG_VALID) &&
- nc->subtype == KMSG_CRED_NEW_CREDS &&
- !d->pwd_change) {
-
- if (is_k5_identpro)
- k5_get_realm_from_nc(nc, tbuf, ARRAYLENGTH(tbuf));
- else
- GetDlgItemText(hwnd, IDC_NCK5_REALM, tbuf,
- ARRAYLENGTH(tbuf));
-
- /*TODO: if additional realms were specified, then those
- must be listed as well */
- LoadString(hResModule, IDS_KRB5_CREDTEXT_0,
- fbuf, ARRAYLENGTH(fbuf));
- StringCbPrintf(sbuf, sizeof(sbuf), fbuf,
- tbuf);
-
- StringCbLength(sbuf, sizeof(sbuf), &cbsize);
- cbsize += sizeof(wchar_t);
-
- nct->credtext = PMALLOC(cbsize);
-
- StringCbCopy(nct->credtext, cbsize, sbuf);
- } else if (nc->n_identities > 0 &&
- (nc->subtype == KMSG_CRED_PASSWORD ||
- (nc->subtype == KMSG_CRED_NEW_CREDS && d->pwd_change))) {
- cbsize = sizeof(tbuf);
- kcdb_identity_get_name(nc->identities[0], tbuf, &cbsize);
-
- LoadString(hResModule, IDS_KRB5_CREDTEXT_P0,
- fbuf, ARRAYLENGTH(fbuf));
- StringCbPrintf(sbuf, sizeof(sbuf), fbuf, tbuf);
-
- StringCbLength(sbuf, sizeof(sbuf), &cbsize);
- cbsize += sizeof(wchar_t);
-
- nct->credtext = PMALLOC(cbsize);
-
- StringCbCopy(nct->credtext, cbsize, sbuf);
- } else {
- if (d->cred_message) {
- StringCbLength(d->cred_message, KHUI_MAXCB_BANNER,
- &cbsize);
- cbsize += sizeof(wchar_t);
-
- nct->credtext = PMALLOC(cbsize);
-
- StringCbCopy(nct->credtext, cbsize, d->cred_message);
- }
- }
- }
- break;
-
- case WMNC_IDENTITY_CHANGE:
- {
- /* There has been a change of identity */
- k5_dlg_data * d;
-
- d = (k5_dlg_data *)(LONG_PTR)
- GetWindowLongPtr(hwnd, DWLP_USER);
-
- kmq_post_sub_msg(k5_sub, KMSG_CRED,
- KMSG_CRED_DIALOG_NEW_IDENTITY,
- 0, (void *) d->nc);
- }
- break;
-
- case WMNC_DIALOG_PREPROCESS:
- {
- k5_dlg_data * d;
-
- d = (k5_dlg_data *)(LONG_PTR)
- GetWindowLongPtr(hwnd, DWLP_USER);
-
- if(!d->sync && d->nc->result == KHUI_NC_RESULT_PROCESS) {
- kmq_post_sub_msg(k5_sub, KMSG_CRED,
- KMSG_CRED_DIALOG_NEW_OPTIONS,
- 0, (void *) d->nc);
- }
- }
- break;
-
- case K5_SET_CRED_MSG:
- {
- k5_dlg_data * d;
- khm_size cb;
- wchar_t * msg;
-
- d = (k5_dlg_data *) (LONG_PTR)
- GetWindowLongPtr(hwnd, DWLP_USER);
-
- msg = (wchar_t *) lParam;
-
- if (d->cred_message) {
- PFREE(d->cred_message);
- d->cred_message = NULL;
- }
-
- if (msg &&
- SUCCEEDED(StringCbLength(msg,
- KHUI_MAXCB_MESSAGE,
- &cb))) {
- cb += sizeof(wchar_t);
- d->cred_message = PMALLOC(cb);
-#ifdef DEBUG
- assert(d->cred_message);
-#endif
- StringCbCopy(d->cred_message, cb, msg);
- }
- }
- break;
- }
-
- return 0;
-}
-
-INT_PTR
-k5_handle_wm_notify(HWND hwnd,
- WPARAM wParam,
- LPARAM lParam) {
- LPNMHDR pnmh;
- k5_dlg_data * d;
-
- pnmh = (LPNMHDR) lParam;
- if (pnmh->idFrom == IDC_NCK5_PUBLICIP &&
- pnmh->code == IPN_FIELDCHANGED) {
-
- d = (k5_dlg_data *) (LONG_PTR) GetWindowLongPtr(hwnd, DWLP_USER);
-
- SendDlgItemMessage(hwnd, IDC_NCK5_PUBLICIP,
- IPM_GETADDRESS,
- 0, (LPARAM) &d->publicIP);
-
- d->dirty = TRUE;
- d->sync = FALSE;
-
- return TRUE;
- }
-
- return 0;
-}
-
-INT_PTR
-k5_handle_wm_command(HWND hwnd,
- WPARAM wParam,
- LPARAM lParam)
-{
- int cid;
- int notif;
- k5_dlg_data * d;
-
- d = (k5_dlg_data *)(LONG_PTR) GetWindowLongPtr(hwnd, DWLP_USER);
-
- cid = LOWORD(wParam);
- notif = HIWORD(wParam);
-
- if(notif == BN_CLICKED && cid == IDC_NCK5_RENEWABLE) {
- int c;
- c = (int) SendDlgItemMessage(hwnd, IDC_NCK5_RENEWABLE,
- BM_GETCHECK, 0, 0);
- if(c==BST_CHECKED) {
- EnableWindow(GetDlgItem(hwnd, IDC_NCK5_RENEW_EDIT), TRUE);
- d->renewable = TRUE;
- } else {
- EnableWindow(GetDlgItem(hwnd, IDC_NCK5_RENEW_EDIT), FALSE);
- d->renewable = FALSE;
- }
- d->dirty = TRUE;
- d->sync = FALSE;
- } else if(notif == BN_CLICKED && cid == IDC_NCK5_FORWARDABLE) {
- int c;
- c = (int) SendDlgItemMessage(hwnd, IDC_NCK5_FORWARDABLE,
- BM_GETCHECK, 0, 0);
- if(c==BST_CHECKED) {
- d->forwardable = TRUE;
- } else {
- d->forwardable = FALSE;
- }
- d->dirty = TRUE;
- d->sync = FALSE;
- } else if (notif == BN_CLICKED && cid == IDC_NCK5_ADDRESS) {
- int c;
-
- c = (int) SendDlgItemMessage(hwnd, IDC_NCK5_ADDRESS,
- BM_GETCHECK, 0, 0);
-
- if (c==BST_CHECKED) {
- d->addressless = TRUE;
- } else {
- d->addressless = FALSE;
- }
- d->dirty = TRUE;
- d->sync = FALSE;
-
- EnableWindow(GetDlgItem(hwnd, IDC_NCK5_PUBLICIP), !d->addressless);
- } else if (notif == EN_CHANGE && (cid == IDC_NCK5_RENEW_EDIT ||
- cid == IDC_NCK5_LIFETIME_EDIT)) {
- d->dirty = TRUE;
- d->sync = FALSE;
- } else if((notif == CBN_SELCHANGE ||
- notif == CBN_KILLFOCUS) &&
- cid == IDC_NCK5_REALM &&
- !is_k5_identpro) {
- /* find out what the realm of the current identity
- is, and if they are the same, then we don't do
- anything */
- wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
- wchar_t realm[KCDB_IDENT_MAXCCH_NAME];
- wchar_t *r;
- khm_size cbsize;
- khm_handle ident;
- int idx;
-
- if(d->nc->n_identities > 0) {
- if(notif == CBN_SELCHANGE) {
- idx = (int) SendDlgItemMessage(hwnd, IDC_NCK5_REALM,
- CB_GETCURSEL, 0, 0);
- SendDlgItemMessage(hwnd, IDC_NCK5_REALM,
- CB_GETLBTEXT, idx, (LPARAM) realm);
- } else {
- GetDlgItemText(hwnd, IDC_NCK5_REALM,
- realm, ARRAYLENGTH(realm));
- }
- cbsize = sizeof(idname);
- if(KHM_SUCCEEDED(kcdb_identity_get_name(d->nc->identities[0],
- idname, &cbsize))) {
- r = wcschr(idname, L'@');
- if(r && !wcscmp(realm, r+1))
- return 0; /* nothing to do */
-
- if(!r) {
- r = idname + wcslen(idname);
- *r++ = L'@';
- *r++ = 0;
- }
-
- /* if we get here, we have a new user */
- StringCchCopy(r+1,
- ARRAYLENGTH(idname) - ((r+1) - idname),
- realm);
- if(KHM_SUCCEEDED(kcdb_identity_create(idname,
- KCDB_IDENT_FLAG_CREATE,
- &ident))) {
- khui_cw_set_primary_id(d->nc, ident);
- kcdb_identity_release(ident);
- }
- return 0;
- }
- }
-
- /* if we get here, we have a new realm, but there is no
- identity */
- PostMessage(d->nc->hwnd, KHUI_WM_NC_NOTIFY,
- MAKEWPARAM(0, WMNC_UPDATE_CREDTEXT), 0);
- }
-
- return 0;
-}
-
-
-/* Dialog procedure for the Krb5 credentials type panel.
-
- NOTE: Runs in the context of the UI thread
-*/
-INT_PTR CALLBACK
-k5_nc_dlg_proc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam)
-{
- switch(uMsg) {
- case WM_INITDIALOG:
- return k5_handle_wm_initdialog(hwnd, wParam, lParam);
-
- case WM_COMMAND:
- return k5_handle_wm_command(hwnd, wParam, lParam);
-
- case KHUI_WM_NC_NOTIFY:
- return k5_handle_wmnc_notify(hwnd, wParam, lParam);
-
- case WM_NOTIFY:
- return k5_handle_wm_notify(hwnd, wParam, lParam);
-
- case WM_DESTROY:
- return k5_handle_wm_destroy(hwnd, wParam, lParam);
- }
- return FALSE;
-}
-
-/* forward dcl */
-krb5_error_code KRB5_CALLCONV
-k5_kinit_prompter(krb5_context context,
- void *data,
- const char *name,
- const char *banner,
- int num_prompts,
- krb5_prompt prompts[]);
-
-
-
-fiber_job g_fjob; /* global fiber job object */
-
-static BOOL
-k5_cached_kinit_prompter(void);
-
-static BOOL
-k5_cp_check_continue(void);
-
-/*
- Runs in the context of the krb5 plugin's slave fiber
-*/
-VOID CALLBACK
-k5_kinit_fiber_proc(PVOID lpParameter)
-{
- while(TRUE)
- {
- if(g_fjob.command == FIBER_CMD_KINIT) {
- g_fjob.state = FIBER_STATE_KINIT;
-
- g_fjob.prompt_set = 0;
-
- if (k5_cached_kinit_prompter()) {
- SwitchToFiber(k5_main_fiber);
-
- if (g_fjob.command != FIBER_CMD_CONTINUE)
- goto _switch_to_main;
-
- if (!k5_cp_check_continue()) {
- g_fjob.code = KRB5KRB_AP_ERR_BAD_INTEGRITY;
- goto _switch_to_main;
- }
- }
-
-#ifdef DEBUG
- /* log the state of g_fjob.* */
- _reportf(L"g_fjob state prior to calling khm_krb5_kinit() :");
- _reportf(L" g_fjob.principal = [%S]", g_fjob.principal);
- _reportf(L" g_fjob.code = %d", g_fjob.code);
- _reportf(L" g_fjob.state = %d", g_fjob.state);
- _reportf(L" g_fjob.prompt_set= %d", g_fjob.prompt_set);
- _reportf(L" g_fjob.valid_principal = %d", (int) g_fjob.valid_principal);
-#endif
-
- /* If we don't know if we have a valid principal, we
- restrict the options that are set when we call kinit.
- This way we will be able to use the response from the
- KDC to verify the principal. */
-
- g_fjob.retry_if_valid_principal = (g_fjob.forwardable ||
- g_fjob.proxiable ||
- g_fjob.renewable);
-
- retry_kinit:
- g_fjob.code =
- khm_krb5_kinit(0,
- g_fjob.principal,
- g_fjob.password,
- g_fjob.ccache,
- g_fjob.lifetime,
- g_fjob.valid_principal ? g_fjob.forwardable : 0,
- g_fjob.valid_principal ? g_fjob.proxiable : 0,
- (g_fjob.valid_principal && g_fjob.renewable ? g_fjob.renew_life : 0),
- g_fjob.addressless,
- g_fjob.publicIP,
- k5_kinit_prompter,
- &g_fjob);
-
- /* If the principal was found to be valid, and if we
- restricted the options that were being passed to kinit,
- then we need to retry the kinit call. This time we use
- the real options. */
- if (g_fjob.state == FIBER_STATE_RETRY_KINIT) {
-#ifdef DEBUG
- assert(g_fjob.valid_principal);
-#endif
- g_fjob.state = FIBER_STATE_KINIT;
- goto retry_kinit;
- }
- }
-
- _switch_to_main:
- g_fjob.state = FIBER_STATE_NONE;
-
- SwitchToFiber(k5_main_fiber);
- }
-}
-
-/* return TRUE if we should go ahead with creds acquisition */
-static BOOL
-k5_cp_check_continue(void) {
- khm_size i;
- khm_size n_p;
- khui_new_creds_prompt * p;
- size_t cch;
-
-#ifdef DEBUG
- assert(g_fjob.nc);
-#endif
-
- if (KHM_FAILED(khui_cw_get_prompt_count(g_fjob.nc, &n_p))) {
-#ifdef DEBUG
- assert(FALSE);
-#endif
- return TRUE;
- }
-
- khui_cw_sync_prompt_values(g_fjob.nc);
-
- g_fjob.null_password = FALSE;
-
- /* we are just checking whether there was a password field that
- was left empty, in which case we can't continue with the
- credentials acquisition. */
- for (i=0; i < n_p; i++) {
- if(KHM_FAILED(khui_cw_get_prompt(g_fjob.nc,
- (int) i,
- &p)))
- continue;
- if(p->type == KHUI_NCPROMPT_TYPE_PASSWORD) {
- if (p->value == NULL ||
- FAILED(StringCchLength(p->value, KHUI_MAXCCH_PROMPT,
- &cch)) ||
- cch == 0) {
- g_fjob.null_password = TRUE;
- return FALSE;
- } else
- break;
- }
- }
-
- return TRUE;
-}
-
-/* returns true if we find cached prompts */
-static BOOL
-k5_cached_kinit_prompter(void) {
- BOOL rv = FALSE;
- khm_handle ident;
- khm_handle csp_idconfig = NULL;
- khm_handle csp_k5config = NULL;
- khm_handle csp_prcache = NULL;
- khm_size cb;
- khm_size n_cur_prompts;
- khm_int32 n_prompts;
- khm_int32 i;
- khm_int64 iexpiry;
- FILETIME expiry;
- FILETIME current;
-
-#ifdef DEBUG
- assert(g_fjob.nc);
-#endif
-
- ident = g_fjob.identity;
- if (!ident)
- return FALSE;
-
- /* don't need to hold ident, since it is already held in g_fjob
- and it doesn't change until we return */
-
- if (KHM_FAILED(kcdb_identity_get_config(ident, 0, &csp_idconfig)) ||
-
- KHM_FAILED(khc_open_space(csp_idconfig, CSNAME_KRB5CRED,
- 0, &csp_k5config)) ||
-
- KHM_FAILED(khc_open_space(csp_k5config, CSNAME_PROMPTCACHE,
- 0, &csp_prcache)) ||
-
- KHM_FAILED(khc_read_int32(csp_prcache, L"PromptCount",
- &n_prompts)) ||
- n_prompts == 0)
-
- goto _cleanup;
-
- if (KHM_SUCCEEDED(khc_read_int64(csp_prcache, L"ExpiresOn", &iexpiry))) {
- /* has the cache expired? */
- expiry = IntToFt(iexpiry);
- GetSystemTimeAsFileTime(&current);
-
- if (CompareFileTime(&expiry, &current) < 0)
- /* already expired */
- goto _cleanup;
- } else {
- /* if there is no value for ExpiresOn, we assume the prompts
- have already expired. */
- goto _cleanup;
- }
-
- /* we found a prompt cache. We take this to imply that the
- principal is valid. */
- g_fjob.valid_principal = TRUE;
-
- /* check if there are any prompts currently showing. If there are
- we check if they are the same as the ones we are going to show.
- In which case we just reuse the exisitng prompts */
- if (KHM_FAILED(khui_cw_get_prompt_count(g_fjob.nc,
- &n_cur_prompts)) ||
- n_prompts != (khm_int32) n_cur_prompts)
- goto _show_new_prompts;
-
- for(i = 0; i < n_prompts; i++) {
- wchar_t wsname[8];
- wchar_t wprompt[KHUI_MAXCCH_PROMPT];
- khm_handle csp_p = NULL;
- khm_int32 p_type;
- khm_int32 p_flags;
- khui_new_creds_prompt * p;
-
- if (KHM_FAILED(khui_cw_get_prompt(g_fjob.nc, i, &p)))
- break;
-
- StringCbPrintf(wsname, sizeof(wsname), L"%d", i);
-
- if (KHM_FAILED(khc_open_space(csp_prcache, wsname, 0, &csp_p)))
- break;
-
- cb = sizeof(wprompt);
- if (KHM_FAILED(khc_read_string(csp_p, L"Prompt",
- wprompt, &cb))) {
- khc_close_space(csp_p);
- break;
- }
-
- if (KHM_FAILED(khc_read_int32(csp_p, L"Type", &p_type)))
- p_type = 0;
-
- if (KHM_FAILED(khc_read_int32(csp_p, L"Flags", &p_flags)))
- p_flags = 0;
-
- if ( /* if we received a prompt string,
- then it should be the same as the
- one that is displayed */
- (wprompt[0] &&
- (p->prompt == NULL ||
- wcscmp(wprompt, p->prompt))) ||
-
- /* if we didn't receive one, then
- there shouldn't be one displayed.
- This case really shouldn't happen
- in reality, but we check anyway. */
- (!wprompt[0] &&
- p->prompt != NULL) ||
-
- /* the type should match */
- (p_type != p->type) ||
-
- /* if this prompt should be hidden,
- then it must also be so */
- (p_flags != p->flags)
- ) {
-
- khc_close_space(csp_p);
- break;
-
- }
-
-
- khc_close_space(csp_p);
- }
-
- if (i == n_prompts) {
- rv = TRUE;
- goto _cleanup;
- }
-
- _show_new_prompts:
-
- khui_cw_clear_prompts(g_fjob.nc);
-
- {
- wchar_t wbanner[KHUI_MAXCCH_BANNER];
- wchar_t wpname[KHUI_MAXCCH_PNAME];
-
- cb = sizeof(wbanner);
- if (KHM_FAILED(khc_read_string(csp_prcache, L"Banner",
- wbanner, &cb)))
- wbanner[0] = 0;
-
- cb = sizeof(wpname);
- if (KHM_FAILED(khc_read_string(csp_prcache, L"Name",
- wpname, &cb)))
- wpname[0] = 0;
-
- khui_cw_begin_custom_prompts(g_fjob.nc,
- n_prompts,
- (wbanner[0]? wbanner: NULL),
- (wpname[0]? wpname: NULL));
- }
-
- for(i = 0; i < n_prompts; i++) {
- wchar_t wsname[8];
- wchar_t wprompt[KHUI_MAXCCH_PROMPT];
- khm_handle csp_p = NULL;
- khm_int32 p_type;
- khm_int32 p_flags;
-
- StringCbPrintf(wsname, sizeof(wsname), L"%d", i);
-
- if (KHM_FAILED(khc_open_space(csp_prcache, wsname, 0, &csp_p)))
- break;
-
- cb = sizeof(wprompt);
- if (KHM_FAILED(khc_read_string(csp_p, L"Prompt",
- wprompt, &cb))) {
- khc_close_space(csp_p);
- break;
- }
-
- if (KHM_FAILED(khc_read_int32(csp_p, L"Type", &p_type)))
- p_type = 0;
-
- if (KHM_FAILED(khc_read_int32(csp_p, L"Flags", &p_flags)))
- p_flags = 0;
-
- khui_cw_add_prompt(g_fjob.nc, p_type, wprompt, NULL, p_flags);
-
- khc_close_space(csp_p);
- }
-
- if (i < n_prompts) {
- khui_cw_clear_prompts(g_fjob.nc);
- } else {
- rv = TRUE;
- }
-
- _cleanup:
-
- if (csp_prcache)
- khc_close_space(csp_prcache);
-
- if (csp_k5config)
- khc_close_space(csp_k5config);
-
- if (csp_idconfig)
- khc_close_space(csp_idconfig);
-
- return rv;
-}
-
-/* Runs in the context of the Krb5 plugin's slave fiber */
-krb5_error_code KRB5_CALLCONV
-k5_kinit_prompter(krb5_context context,
- void *data,
- const char *name,
- const char *banner,
- int num_prompts,
- krb5_prompt prompts[])
-{
- int i;
- khui_new_creds * nc;
- krb5_prompt_type * ptypes;
- khm_size ncp;
- krb5_error_code code = 0;
- BOOL new_prompts = TRUE;
- khm_handle csp_prcache = NULL;
-
-#ifdef DEBUG
- _reportf(L"k5_kinit_prompter() received %d prompts with name=[%S] banner=[%S]",
- num_prompts,
- name, banner);
- for (i=0; i < num_prompts; i++) {
- _reportf(L"Prompt[%d]: string[%S]", i, prompts[i].prompt);
- }
-#endif
-
- /* we got prompts? Then we assume that the principal is valid */
-
- if (!g_fjob.valid_principal) {
- g_fjob.valid_principal = TRUE;
-
- /* if the flags that were used to call kinit were restricted
- because we didn't know the validity of the principal, then
- we need to go back and retry the call with the correct
- flags. */
- if (g_fjob.retry_if_valid_principal) {
- _reportf(L"Retrying kinit call due to restricted flags on first call.");
- g_fjob.state = FIBER_STATE_RETRY_KINIT;
- return KRB5_LIBOS_PWDINTR;
- }
- }
-
- nc = g_fjob.nc;
-
- if(pkrb5_get_prompt_types)
- ptypes = pkrb5_get_prompt_types(context);
- else
- ptypes = NULL;
-
- /* check if we are already showing the right prompts */
- khui_cw_get_prompt_count(nc, &ncp);
-
- if (num_prompts != (int) ncp)
- goto _show_new_prompts;
-
- for (i=0; i < num_prompts; i++) {
- wchar_t wprompt[KHUI_MAXCCH_PROMPT];
- khui_new_creds_prompt * p;
-
- if(prompts[i].prompt) {
- AnsiStrToUnicode(wprompt, sizeof(wprompt),
- prompts[i].prompt);
- } else {
- wprompt[0] = 0;
- }
-
- if (KHM_FAILED(khui_cw_get_prompt(nc, i, &p)))
- break;
-
- if ( /* if we received a prompt string,
- then it should be the same as the
- one that is displayed */
- (wprompt[0] &&
- (p->prompt == NULL ||
- wcscmp(wprompt, p->prompt))) ||
- /* if we didn't receive one, then
- there shouldn't be one displayed.
- This case really shouldn't happen
- in reality, but we check anyway. */
- (!wprompt[0] &&
- p->prompt != NULL) ||
- /* the type should match */
- (ptypes &&
- ptypes[i] != p->type) ||
- (!ptypes &&
- p->type != 0) ||
- /* if this prompt should be hidden,
- then it must also be so */
- (prompts[i].hidden &&
- !(p->flags & KHUI_NCPROMPT_FLAG_HIDDEN)) ||
- (!prompts[i].hidden &&
- (p->flags & KHUI_NCPROMPT_FLAG_HIDDEN))
- )
- break;
- }
-
- if (i < num_prompts)
- goto _show_new_prompts;
-
- new_prompts = FALSE;
-
- /* ok. looks like we are already showing the same set of prompts
- that we were supposed to show. Sync up the values and go
- ahead. */
- khui_cw_sync_prompt_values(nc);
- goto _process_prompts;
-
- _show_new_prompts:
- /* special case. if there are no actual input controls involved,
- then we have to show an alerter window and pass through */
- if (num_prompts == 0) {
- wchar_t wbanner[KHUI_MAXCCH_BANNER];
- wchar_t wname[KHUI_MAXCCH_PNAME];
- wchar_t wident[KCDB_IDENT_MAXCCH_NAME];
- wchar_t wmsg[KHUI_MAXCCH_MESSAGE];
- wchar_t wfmt[KHUI_MAXCCH_BANNER];
- khm_size cb;
-
- if (!banner) {
- code = 0;
- g_fjob.null_password = FALSE;
- goto _exit;
- } else {
- AnsiStrToUnicode(wbanner, sizeof(wbanner), banner);
- }
-
- if (name) {
- AnsiStrToUnicode(wname, sizeof(wname), name);
- } else {
- LoadString(hResModule,
- IDS_KRB5_WARNING,
- wname,
- ARRAYLENGTH(wname));
- }
-
- cb = sizeof(wident);
- if (KHM_FAILED(kcdb_identity_get_name(g_fjob.identity, wident, &cb)))
- wident[0] = L'\0';
-
- LoadString(hResModule,
- IDS_KRB5_WARN_FMT,
- wfmt,
- ARRAYLENGTH(wfmt));
-
- StringCbPrintf(wmsg, sizeof(wmsg), wfmt, wident, wbanner);
-
- khui_alert_show_simple(wname, wmsg, KHERR_WARNING);
-
- code = 0;
- g_fjob.null_password = FALSE;
- goto _exit;
- }
-
- /* in addition to showing new prompts, we also cache the set of
- prompts. */
- if(g_fjob.prompt_set == 0) {
- khm_handle csp_idconfig = NULL;
- khm_handle csp_idk5 = NULL;
-
- kcdb_identity_get_config(g_fjob.identity,
- KHM_FLAG_CREATE,
- &csp_idconfig);
-
- if (csp_idconfig != NULL)
- khc_open_space(csp_idconfig,
- CSNAME_KRB5CRED,
- KHM_FLAG_CREATE,
- &csp_idk5);
-
- if (csp_idk5 != NULL)
- khc_open_space(csp_idk5,
- CSNAME_PROMPTCACHE,
- KHM_FLAG_CREATE,
- &csp_prcache);
-
- khc_close_space(csp_idconfig);
- khc_close_space(csp_idk5);
- }
-
- {
- wchar_t wbanner[KHUI_MAXCCH_BANNER];
- wchar_t wname[KHUI_MAXCCH_PNAME];
- FILETIME current;
- FILETIME lifetime;
- FILETIME expiry;
- khm_int64 iexpiry;
- khm_int32 t = 0;
-
- if(banner)
- AnsiStrToUnicode(wbanner, sizeof(wbanner), banner);
- if(name)
- AnsiStrToUnicode(wname, sizeof(wname), name);
-
- khui_cw_clear_prompts(nc);
-
- khui_cw_begin_custom_prompts(
- nc,
- num_prompts,
- (banner)?wbanner:NULL,
- (name)?wname:NULL);
-
- if (csp_prcache) {
-
- if (banner)
- khc_write_string(csp_prcache,
- L"Banner",
- wbanner);
- else
- khc_write_string(csp_prcache,
- L"Banner",
- L"");
-
- if (name)
- khc_write_string(csp_prcache,
- L"Name",
- wname);
- else if (csp_prcache)
- khc_write_string(csp_prcache,
- L"Name",
- L"");
-
- khc_write_int32(csp_prcache,
- L"PromptCount",
- (khm_int32) num_prompts);
-
- GetSystemTimeAsFileTime(&current);
-#ifdef USE_PROMPT_CACHE_LIFETIME
- khc_read_int32(csp_params, L"PromptCacheLifetime", &t);
- if (t == 0)
- t = 172800; /* 48 hours */
-#else
- khc_read_int32(csp_params, L"MaxRenewLifetime", &t);
- if (t == 0)
- t = 2592000; /* 30 days */
- t += 604800; /* + 7 days */
-#endif
- TimetToFileTimeInterval(t, &lifetime);
- expiry = FtAdd(&current, &lifetime);
- iexpiry = FtToInt(&expiry);
-
- khc_write_int64(csp_prcache, L"ExpiresOn", iexpiry);
- }
- }
-
- for(i=0; i < num_prompts; i++) {
- wchar_t wprompt[KHUI_MAXCCH_PROMPT];
-
- if(prompts[i].prompt) {
- AnsiStrToUnicode(wprompt, sizeof(wprompt),
- prompts[i].prompt);
- } else {
- wprompt[0] = 0;
- }
-
- khui_cw_add_prompt(
- nc,
- (ptypes?ptypes[i]:0),
- wprompt,
- NULL,
- (prompts[i].hidden?KHUI_NCPROMPT_FLAG_HIDDEN:0));
-
- if (csp_prcache) {
- khm_handle csp_p = NULL;
- wchar_t wnum[8]; /* should be enough for 10
- million prompts */
-
- wnum[0] = 0;
- StringCbPrintf(wnum, sizeof(wnum), L"%d", i);
-
- khc_open_space(csp_prcache, wnum,
- KHM_FLAG_CREATE, &csp_p);
-
- if (csp_p) {
- khc_write_string(csp_p, L"Prompt", wprompt);
- khc_write_int32(csp_p, L"Type", (ptypes?ptypes[i]:0));
- khc_write_int32(csp_p, L"Flags",
- (prompts[i].hidden?
- KHUI_NCPROMPT_FLAG_HIDDEN:0));
-
- khc_close_space(csp_p);
- }
- }
- }
-
- if (csp_prcache) {
- khc_close_space(csp_prcache);
- csp_prcache = NULL;
- }
-
- _process_prompts:
- /* switch back to main thread if we showed new prompts */
- if (new_prompts)
- SwitchToFiber(k5_main_fiber);
-
- /* we get here after the user selects an action that either
- cancles the credentials acquisition operation or triggers the
- actual acquisition of credentials. */
- if(g_fjob.command != FIBER_CMD_CONTINUE &&
- g_fjob.command != FIBER_CMD_KINIT) {
- code = KRB5_LIBOS_PWDINTR;
- goto _exit;
- }
-
- g_fjob.null_password = FALSE;
-
- /* otherwise, we need to get the data back from the UI and
- return 0 */
- for(i=0; i<num_prompts; i++) {
- krb5_data * d;
- wchar_t wbuf[512];
- khm_size cbbuf;
- size_t cch;
-
- d = prompts[i].reply;
-
- cbbuf = sizeof(wbuf);
- if(KHM_SUCCEEDED(khui_cw_get_prompt_value(nc, i, wbuf, &cbbuf))) {
- UnicodeStrToAnsi(d->data, d->length, wbuf);
- if(SUCCEEDED(StringCchLengthA(d->data, d->length, &cch)))
- d->length = (unsigned int) cch;
- else
- d->length = 0;
- } else {
-#ifdef DEBUG
- assert(FALSE);
-#endif
- d->length = 0;
- }
-
- if (ptypes &&
- ptypes[i] == KRB5_PROMPT_TYPE_PASSWORD &&
- d->length == 0)
-
- g_fjob.null_password = TRUE;
- }
-
- _exit:
-
- g_fjob.prompt_set++;
-
- /* entering a NULL password is equivalent to cancelling out */
- if (g_fjob.null_password)
- return KRB5_LIBOS_PWDINTR;
- else
- return code;
-}
-
-
-void
-k5_read_dlg_params(k5_dlg_data * d, khm_handle identity)
-{
- k5_params p;
-
- khm_krb5_get_identity_params(identity, &p);
-
- d->renewable = p.renewable;
- d->forwardable = p.forwardable;
- d->proxiable = p.proxiable;
- d->addressless = p.addressless;
- d->publicIP = p.publicIP;
-
- d->tc_lifetime.current = p.lifetime;
- d->tc_lifetime.max = p.lifetime_max;
- d->tc_lifetime.min = p.lifetime_min;
-
- d->tc_renew.current = p.renew_life;
- d->tc_renew.max = p.renew_life_max;
- d->tc_renew.min = p.renew_life_min;
-
- /* however, if this has externally supplied defaults, we have to
- use them too. */
- if (d->nc && d->nc->ctx.vparam &&
- d->nc->ctx.cb_vparam == sizeof(NETID_DLGINFO)) {
- LPNETID_DLGINFO pdlginfo;
-
- pdlginfo = (LPNETID_DLGINFO) d->nc->ctx.vparam;
- if (pdlginfo->size == NETID_DLGINFO_V1_SZ &&
- pdlginfo->in.use_defaults == 0) {
- d->forwardable = pdlginfo->in.forwardable;
- d->addressless = pdlginfo->in.noaddresses;
- d->tc_lifetime.current = pdlginfo->in.lifetime;
- d->tc_renew.current = pdlginfo->in.renew_till;
-
- if (pdlginfo->in.renew_till == 0)
- d->renewable = FALSE;
- else
- d->renewable = TRUE;
-
- d->proxiable = pdlginfo->in.proxiable;
- d->publicIP = pdlginfo->in.publicip;
- }
- }
-
- /* once we read the new data, in, it is no longer considered
- dirty */
- d->dirty = FALSE;
- d->sync = FALSE;
-}
-
-void
-k5_write_dlg_params(k5_dlg_data * d, khm_handle identity)
-{
-
- k5_params p;
-
- ZeroMemory(&p, sizeof(p));
-
- p.source_reg = K5PARAM_FM_ALL; /* we want to write all the
- settings to the registry, if
- necessary. */
-
- p.renewable = d->renewable;
- p.forwardable = d->forwardable;
- p.proxiable = d->proxiable;
- p.addressless = d->addressless;
- p.publicIP = d->publicIP;
-
- p.lifetime = (krb5_deltat) d->tc_lifetime.current;
- p.lifetime_max = (krb5_deltat) d->tc_lifetime.max;
- p.lifetime_min = (krb5_deltat) d->tc_lifetime.min;
-
- p.renew_life = (krb5_deltat) d->tc_renew.current;
- p.renew_life_max = (krb5_deltat) d->tc_renew.max;
- p.renew_life_min = (krb5_deltat) d->tc_renew.min;
-
- khm_krb5_set_identity_params(identity, &p);
-
- /* as in k5_read_dlg_params, once we write the data in, the local
- data is no longer dirty */
- d->dirty = FALSE;
-}
-
-void
-k5_free_kinit_job(void)
-{
- if (g_fjob.principal)
- PFREE(g_fjob.principal);
-
- if (g_fjob.password)
- PFREE(g_fjob.password);
-
- if (g_fjob.identity)
- kcdb_identity_release(g_fjob.identity);
-
- if (g_fjob.ccache)
- PFREE(g_fjob.ccache);
-
- ZeroMemory(&g_fjob, sizeof(g_fjob));
-}
-
-void
-k5_prep_kinit_job(khui_new_creds * nc)
-{
- khui_new_creds_by_type * nct;
- k5_dlg_data * d;
- wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
- khm_size cbbuf;
- size_t size;
- khm_handle ident;
- LPNETID_DLGINFO pdlginfo;
-
- khui_cw_find_type(nc, credtype_id_krb5, &nct);
- if (!nct)
- return;
-
- d = (k5_dlg_data *)(LONG_PTR)
- GetWindowLongPtr(nct->hwnd_panel, DWLP_USER);
-
- if (!d)
- return;
-
- khui_cw_lock_nc(nc);
- ident = nc->identities[0];
- kcdb_identity_hold(ident);
- khui_cw_unlock_nc(nc);
-
- cbbuf = sizeof(idname);
- kcdb_identity_get_name(ident, idname, &cbbuf);
- StringCchLength(idname, ARRAYLENGTH(idname), &size);
- size++;
-
- k5_free_kinit_job();
-
- g_fjob.command = FIBER_CMD_KINIT;
- g_fjob.nc = nc;
- g_fjob.nct = nct;
- g_fjob.dialog = nct->hwnd_panel;
- g_fjob.principal = PMALLOC(size);
- UnicodeStrToAnsi(g_fjob.principal, size, idname);
- g_fjob.password = NULL;
- g_fjob.lifetime = (krb5_deltat) d->tc_lifetime.current;
- g_fjob.forwardable = d->forwardable;
- g_fjob.proxiable = d->proxiable;
- g_fjob.renewable = d->renewable;
- g_fjob.renew_life = (krb5_deltat) d->tc_renew.current;
- g_fjob.addressless = d->addressless;
- g_fjob.publicIP = d->publicIP;
- g_fjob.code = 0;
- g_fjob.identity = ident;
- g_fjob.prompt_set = 0;
- g_fjob.valid_principal = FALSE;
- g_fjob.retry_if_valid_principal = FALSE;
-
- /* the value for
- retry_if_valid_principal is not
- necessarily the correct value here,
- but the correct value will be
- assigned k5_kinit_fiber_proc(). */
-
- /* if we have external parameters, we should use them as well */
- if (nc->ctx.cb_vparam == sizeof(NETID_DLGINFO) &&
- (pdlginfo = nc->ctx.vparam) &&
- pdlginfo->size == NETID_DLGINFO_V1_SZ) {
- wchar_t * t;
-
- if (pdlginfo->in.ccache[0] &&
- SUCCEEDED(StringCchLength(pdlginfo->in.ccache,
- NETID_CCACHE_NAME_SZ,
- &size))) {
- g_fjob.ccache = PMALLOC(sizeof(char) * (size + 1));
-#ifdef DEBUG
- assert(g_fjob.ccache);
-#endif
- UnicodeStrToAnsi(g_fjob.ccache, size + 1,
- pdlginfo->in.ccache);
-
- /* this is the same as the output cache */
-
- StringCbCopy(pdlginfo->out.ccache, sizeof(pdlginfo->out.ccache),
- pdlginfo->in.ccache);
- } else {
- g_fjob.ccache = NULL;
-
- StringCbCopy(pdlginfo->out.ccache, sizeof(pdlginfo->out.ccache),
- idname);
-
- khm_krb5_canon_cc_name(pdlginfo->out.ccache,
- sizeof(pdlginfo->out.ccache));
- }
-
- t = khm_get_realm_from_princ(idname);
-
- if (t) {
- StringCbCopy(pdlginfo->out.realm,
- sizeof(pdlginfo->out.realm),
- t);
-
- if ((t - idname) > 1) {
- StringCchCopyN(pdlginfo->out.username,
- ARRAYLENGTH(pdlginfo->out.username),
- idname,
- (t - idname) - 1);
- } else {
- StringCbCopy(pdlginfo->out.username,
- sizeof(pdlginfo->out.username),
- L"");
- }
- } else {
- StringCbCopy(pdlginfo->out.username,
- sizeof(pdlginfo->out.username),
- idname);
- StringCbCopy(pdlginfo->out.realm,
- sizeof(pdlginfo->out.realm),
- L"");
- }
- }
-
- /* leave identity held, since we added a reference above */
-}
-
-static khm_int32 KHMAPI
-k5_find_tgt_filter(khm_handle cred,
- khm_int32 flags,
- void * rock) {
- khm_handle ident = (khm_handle) rock;
- khm_handle cident = NULL;
- khm_int32 f;
- khm_int32 rv;
-
- if (KHM_SUCCEEDED(kcdb_cred_get_identity(cred,
- &cident)) &&
- cident == ident &&
- KHM_SUCCEEDED(kcdb_cred_get_flags(cred, &f)) &&
- (f & KCDB_CRED_FLAG_INITIAL) &&
- !(f & KCDB_CRED_FLAG_EXPIRED))
- rv = 1;
- else
- rv = 0;
-
- if (cident)
- kcdb_identity_release(cident);
-
- return rv;
-}
-
-khm_int32
-k5_remove_from_LRU(khm_handle identity)
-{
- wchar_t * wbuf = NULL;
- wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
- khm_size cb;
- khm_size cb_ms;
- khm_int32 rv = KHM_ERROR_SUCCESS;
-
- cb = sizeof(idname);
- rv = kcdb_identity_get_name(identity, idname, &cb);
- assert(rv == KHM_ERROR_SUCCESS);
-
- rv = khc_read_multi_string(csp_params, L"LRUPrincipals", NULL, &cb_ms);
- if (rv != KHM_ERROR_TOO_LONG)
- cb_ms = sizeof(wchar_t) * 2;
-
- wbuf = PMALLOC(cb_ms);
- assert(wbuf);
-
- cb = cb_ms;
-
- if (rv == KHM_ERROR_TOO_LONG) {
- rv = khc_read_multi_string(csp_params, L"LRUPrincipals", wbuf, &cb);
- assert(KHM_SUCCEEDED(rv));
-
- if (multi_string_find(wbuf, idname, KHM_CASE_SENSITIVE) != NULL) {
- multi_string_delete(wbuf, idname, KHM_CASE_SENSITIVE);
- }
- } else {
- multi_string_init(wbuf, cb_ms);
- }
-
- rv = khc_write_multi_string(csp_params, L"LRUPrincipals", wbuf);
-
- if (wbuf)
- PFREE(wbuf);
-
- return rv;
-}
-
-khm_int32
-k5_update_LRU(khm_handle identity)
-{
- wchar_t * wbuf = NULL;
- wchar_t * idname = NULL;
- wchar_t * realm = NULL;
- khm_size cb;
- khm_size cb_ms;
- khm_int32 rv = KHM_ERROR_SUCCESS;
-
- rv = kcdb_identity_get_name(identity, NULL, &cb);
- assert(rv == KHM_ERROR_TOO_LONG);
-
- idname = PMALLOC(cb);
- assert(idname);
-
- rv = kcdb_identity_get_name(identity, idname, &cb);
- assert(KHM_SUCCEEDED(rv));
-
- rv = khc_read_multi_string(csp_params, L"LRUPrincipals", NULL, &cb_ms);
- if (rv != KHM_ERROR_TOO_LONG)
- cb_ms = cb + sizeof(wchar_t);
- else
- cb_ms += cb + sizeof(wchar_t);
-
- wbuf = PMALLOC(cb_ms);
- assert(wbuf);
-
- cb = cb_ms;
-
- if (rv == KHM_ERROR_TOO_LONG) {
- rv = khc_read_multi_string(csp_params, L"LRUPrincipals", wbuf, &cb);
- assert(KHM_SUCCEEDED(rv));
-
- if (multi_string_find(wbuf, idname, KHM_CASE_SENSITIVE) != NULL) {
- /* it's already there. We remove it here and add it at
- the top of the LRU list. */
- multi_string_delete(wbuf, idname, KHM_CASE_SENSITIVE);
- }
- } else {
- multi_string_init(wbuf, cb_ms);
- }
-
- cb = cb_ms;
- rv = multi_string_prepend(wbuf, &cb, idname);
- assert(KHM_SUCCEEDED(rv));
-
- rv = khc_write_multi_string(csp_params, L"LRUPrincipals", wbuf);
-
- realm = khm_get_realm_from_princ(idname);
- if (realm == NULL || *realm == L'\0')
- goto _done_with_LRU;
-
- cb = cb_ms;
- rv = khc_read_multi_string(csp_params, L"LRURealms", wbuf, &cb);
-
- if (rv == KHM_ERROR_TOO_LONG) {
- PFREE(wbuf);
- wbuf = PMALLOC(cb);
- assert(wbuf);
-
- cb_ms = cb;
-
- rv = khc_read_multi_string(csp_params, L"LRURealms", wbuf, &cb);
-
- assert(KHM_SUCCEEDED(rv));
- } else if (rv == KHM_ERROR_SUCCESS) {
- if (multi_string_find(wbuf, realm, KHM_CASE_SENSITIVE) != NULL) {
- /* remove the realm and add it at the top later. */
- multi_string_delete(wbuf, realm, KHM_CASE_SENSITIVE);
- }
- } else {
- multi_string_init(wbuf, cb_ms);
- }
-
- cb = cb_ms;
- rv = multi_string_prepend(wbuf, &cb, realm);
-
- if (rv == KHM_ERROR_TOO_LONG) {
- wbuf = PREALLOC(wbuf, cb);
-
- rv = multi_string_prepend(wbuf, &cb, realm);
-
- assert(KHM_SUCCEEDED(rv));
- }
-
- rv = khc_write_multi_string(csp_params, L"LRURealms", wbuf);
-
- assert(KHM_SUCCEEDED(rv));
-
- _done_with_LRU:
-
- if (wbuf)
- PFREE(wbuf);
- if (idname)
- PFREE(idname);
-
- return rv;
-}
-
-/* Handler for CRED type messages
-
- Runs in the context of the Krb5 plugin
-*/
-khm_int32 KHMAPI
-k5_msg_cred_dialog(khm_int32 msg_type,
- khm_int32 msg_subtype,
- khm_ui_4 uparam,
- void * vparam)
-{
- khm_int32 rv = KHM_ERROR_SUCCESS;
-
- switch(msg_subtype) {
-
- case KMSG_CRED_PASSWORD:
- case KMSG_CRED_NEW_CREDS:
- {
- khui_new_creds * nc;
- khui_new_creds_by_type * nct;
- wchar_t wbuf[256];
- size_t cbsize;
-
- nc = (khui_new_creds *) vparam;
-
- nct = PMALLOC(sizeof(*nct));
- ZeroMemory(nct, sizeof(*nct));
-
- nct->type = credtype_id_krb5;
- nct->ordinal = 1;
-
- LoadString(hResModule, IDS_KRB5_NC_NAME,
- wbuf, ARRAYLENGTH(wbuf));
- StringCbLength(wbuf, sizeof(wbuf), &cbsize);
- cbsize += sizeof(wchar_t);
-
- nct->name = PMALLOC(cbsize);
- StringCbCopy(nct->name, cbsize, wbuf);
-
- nct->h_module = hResModule;
- nct->dlg_proc = k5_nc_dlg_proc;
- if (nc->subtype == KMSG_CRED_PASSWORD)
- nct->dlg_template = MAKEINTRESOURCE(IDD_NC_KRB5_PASSWORD);
- else
- nct->dlg_template = MAKEINTRESOURCE(IDD_NC_KRB5);
-
- khui_cw_add_type(nc, nct);
- }
- break;
-
- case KMSG_CRED_RENEW_CREDS:
- {
- khui_new_creds * nc;
- khui_new_creds_by_type * nct;
-
- nc = (khui_new_creds *) vparam;
-
- nct = PMALLOC(sizeof(*nct));
- ZeroMemory(nct, sizeof(*nct));
-
- nct->type = credtype_id_krb5;
-
- khui_cw_add_type(nc, nct);
- }
- break;
-
- case KMSG_CRED_DIALOG_PRESTART:
- {
- khui_new_creds * nc;
- khui_new_creds_by_type * nct;
- k5_dlg_data * d;
- HWND hwnd;
- wchar_t * realms;
- wchar_t * t;
- wchar_t * defrealm;
-
- nc = (khui_new_creds *) vparam;
-
- khui_cw_find_type(nc, credtype_id_krb5, &nct);
-
- if(!nct)
- break;
-
- hwnd = nct->hwnd_panel;
- d = (k5_dlg_data *)(LONG_PTR)
- GetWindowLongPtr(nct->hwnd_panel, DWLP_USER);
-
- /* this can be NULL if the dialog was closed while the
- plug-in thread was processing. */
- if (d == NULL)
- break;
-
- if (!is_k5_identpro) {
-
- /* enumerate all realms and place in realms combo box */
- SendDlgItemMessage(hwnd, IDC_NCK5_REALM,
- CB_RESETCONTENT,
- 0, 0);
-
- realms = khm_krb5_get_realm_list();
- if(realms) {
- for (t = realms; t && *t; t = multi_string_next(t)) {
- SendDlgItemMessage(hwnd, IDC_NCK5_REALM,
- CB_ADDSTRING,
- 0, (LPARAM) t);
- }
- PFREE(realms);
- }
-
- /* and set the default realm */
- defrealm = khm_krb5_get_default_realm();
- if(defrealm) {
- SendDlgItemMessage(hwnd, IDC_NCK5_REALM,
- CB_SELECTSTRING,
- (WPARAM) -1,
- (LPARAM) defrealm);
-
- SendDlgItemMessage(hwnd, IDC_NCK5_REALM,
- WM_SETTEXT,
- 0, (LPARAM) defrealm);
- PFREE(defrealm);
- }
- } else { /* if krb5 is the identity provider */
- HWND hw_realms;
-
- /* in this case, the realm selection is done by the
- identity provider prompts. */
-
- hw_realms = GetDlgItem(hwnd, IDC_NCK5_REALM);
-#ifdef DEBUG
- assert(hw_realms);
-#endif
- EnableWindow(hw_realms, FALSE);
- }
-
- if (nc->subtype == KMSG_CRED_NEW_CREDS) {
- k5_read_dlg_params(d, NULL);
- }
-
- PostMessage(hwnd, KHUI_WM_NC_NOTIFY,
- MAKEWPARAM(0,WMNC_DIALOG_SETUP), 0);
- }
- break;
-
- case KMSG_CRED_DIALOG_NEW_IDENTITY:
- {
- khui_new_creds * nc;
- khui_new_creds_by_type * nct;
- k5_dlg_data * d;
-
- nc = (khui_new_creds *) vparam;
-
- khui_cw_find_type(nc, credtype_id_krb5, &nct);
- if (!nct)
- break;
-
- d = (k5_dlg_data *)(LONG_PTR)
- GetWindowLongPtr(nct->hwnd_panel, DWLP_USER);
-
- if (d == NULL)
- break;
-
- /* we only load the identity specific defaults if the user
- hasn't changed the options */
- khui_cw_lock_nc(nc);
-
- /* ?: It might be better to not load identity defaults if
- the user has already changed options in the dialog. */
- if(/* !d->dirty && */ nc->n_identities > 0 &&
- nc->subtype == KMSG_CRED_NEW_CREDS) {
-
- k5_read_dlg_params(d, nc->identities[0]);
-
- PostMessage(nct->hwnd_panel, KHUI_WM_NC_NOTIFY,
- MAKEWPARAM(0,WMNC_DIALOG_SETUP), 0);
- }
-
- khui_cw_unlock_nc(nc);
-
- /* reset the force-password-change flag if this is a new
- identity. */
- d->pwd_change = FALSE;
- }
-
- /* fallthrough */
- case KMSG_CRED_DIALOG_NEW_OPTIONS:
- {
- khui_new_creds * nc;
- khui_new_creds_by_type * nct;
- k5_dlg_data * d;
-
- nc = (khui_new_creds *) vparam;
-
- khui_cw_find_type(nc, credtype_id_krb5, &nct);
- if (!nct)
- break;
-
- d = (k5_dlg_data *)(LONG_PTR)
- GetWindowLongPtr(nct->hwnd_panel, DWLP_USER);
- if (d == NULL)
- break;
-
- if (nc->subtype == KMSG_CRED_PASSWORD) {
- khm_size n_prompts = 0;
-
- khui_cw_get_prompt_count(nc, &n_prompts);
-
- if (nc->n_identities == 0) {
- if (n_prompts)
- khui_cw_clear_prompts(nc);
- } else if (n_prompts != 3) {
- wchar_t wbuf[KHUI_MAXCCH_BANNER];
-
- khui_cw_clear_prompts(nc);
-
- LoadString(hResModule, IDS_NC_PWD_BANNER,
- wbuf, ARRAYLENGTH(wbuf));
- khui_cw_begin_custom_prompts(nc, 3, NULL, wbuf);
-
- LoadString(hResModule, IDS_NC_PWD_PWD,
- wbuf, ARRAYLENGTH(wbuf));
- khui_cw_add_prompt(nc, KHUI_NCPROMPT_TYPE_PASSWORD,
- wbuf, NULL, KHUI_NCPROMPT_FLAG_HIDDEN);
-
- LoadString(hResModule, IDS_NC_PWD_NPWD,
- wbuf, ARRAYLENGTH(wbuf));
- khui_cw_add_prompt(nc, KHUI_NCPROMPT_TYPE_NEW_PASSWORD,
- wbuf, NULL, KHUI_NCPROMPT_FLAG_HIDDEN);
-
- LoadString(hResModule, IDS_NC_PWD_NPWD_AGAIN,
- wbuf, ARRAYLENGTH(wbuf));
- khui_cw_add_prompt(nc, KHUI_NCPROMPT_TYPE_NEW_PASSWORD_AGAIN,
- wbuf, NULL, KHUI_NCPROMPT_FLAG_HIDDEN);
- }
-
- return KHM_ERROR_SUCCESS;
- }
- /* else; nc->subtype == KMSG_CRED_NEW_CREDS */
-
- assert(nc->subtype == KMSG_CRED_NEW_CREDS);
-
- /* If we are forcing a password change, then we don't do
- anything here. Note that if the identity changed, then
- this field would have been reset, so we would proceed
- as usual. */
- if (d->pwd_change)
- return KHM_ERROR_SUCCESS;
-
-#if 0
- /* Clearing the prompts at this point is a bad idea since
- the prompter depends on the prompts to know if this set
- of prompts is the same as the new set and if so, use
- the values entered in the old prompts as responses to
- the new one. */
- khui_cw_clear_prompts(nc);
-#endif
-
- /* if the fiber is already in a kinit, cancel it */
- if(g_fjob.state == FIBER_STATE_KINIT) {
- g_fjob.command = FIBER_CMD_CANCEL;
- SwitchToFiber(k5_kinit_fiber);
- /* we get here when the cancel operation completes */
- k5_free_kinit_job();
- }
-
- khui_cw_lock_nc(nc);
-
- if(nc->n_identities > 0) {
- khm_handle ident = nc->identities[0];
-
- kcdb_identity_hold(ident);
-
- k5_prep_kinit_job(nc);
-
- /* after the switch to the fiber, the dialog will be
- back in sync with the kinit thread. */
- d->sync = TRUE;
-
- khui_cw_unlock_nc(nc);
-
- SwitchToFiber(k5_kinit_fiber);
- /* we get here when the fiber switches back */
- if(g_fjob.state == FIBER_STATE_NONE) {
- wchar_t msg[KHUI_MAXCCH_BANNER];
- khm_size cb;
-
- /* Special case. If the users' password has
- expired, we force a password change dialog on
- top of the new credentials dialog using a set
- of custom prompts, but only if we are the
- identity provider. */
- if (g_fjob.code == KRB5KDC_ERR_KEY_EXP &&
- is_k5_identpro) {
-
- k5_force_password_change(d);
- goto done_with_bad_princ;
-
- }
-
- /* we can't possibly have succeeded without a
- password */
- if(g_fjob.code == KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN &&
- is_k5_identpro) {
- kcdb_identity_set_flags(ident,
- KCDB_IDENT_FLAG_INVALID,
- KCDB_IDENT_FLAG_INVALID);
-
- khui_cw_clear_prompts(nc);
- }
-
- if (d->cred_message) {
- PFREE(d->cred_message);
- d->cred_message = NULL;
- }
-
- msg[0] = L'\0';
-
- switch(g_fjob.code) {
- case KRB5KDC_ERR_NAME_EXP:
- /* principal expired */
- LoadString(hResModule, IDS_K5ERR_NAME_EXPIRED,
- msg, ARRAYLENGTH(msg));
- break;
-
- case KRB5KDC_ERR_KEY_EXP:
- {
- /* password needs changing. */
- LoadString(hResModule, IDS_K5ERR_KEY_EXPIRED,
- msg, ARRAYLENGTH(msg));
- }
- break;
-
- default:
- {
- DWORD dw_dummy;
- kherr_suggestion sug_dummy;
- wchar_t fmt[KHUI_MAXCCH_BANNER];
- wchar_t desc[KHUI_MAXCCH_BANNER];
-
- LoadString(hResModule, IDS_K5ERR_FMT,
- fmt, ARRAYLENGTH(fmt));
-
- khm_err_describe(g_fjob.code,
- desc,
- sizeof(desc),
- &dw_dummy,
- &sug_dummy);
-
- StringCbPrintf(msg, sizeof(msg), fmt, desc);
- }
- }
-
- if (msg[0]) {
- StringCbLength(msg, sizeof(msg), &cb);
- cb += sizeof(wchar_t);
-
- d->cred_message = PMALLOC(cb);
- StringCbCopy(d->cred_message, cb, msg);
- }
-
- done_with_bad_princ:
-
- k5_free_kinit_job();
-
- if (is_k5_identpro)
- kcdb_identity_set_flags(ident,
- KCDB_IDENT_FLAG_UNKNOWN,
- KCDB_IDENT_FLAG_UNKNOWN);
-
-
- } else if(g_fjob.state == FIBER_STATE_KINIT) {
- /* this is what we want. Leave the fiber there. */
-
- if(is_k5_identpro)
- kcdb_identity_set_flags(ident,
- KCDB_IDENT_FLAG_VALID,
- KCDB_IDENT_FLAG_VALID);
- } else {
- /* huh?? */
-#ifdef DEBUG
- assert(FALSE);
-#endif
- }
-
- /* since the attributes of the identity have changed,
- we should update the cred text as well */
- kcdb_identity_release(ident);
- khui_cw_lock_nc(nc);
- PostMessage(nc->hwnd, KHUI_WM_NC_NOTIFY,
- MAKEWPARAM(0, WMNC_UPDATE_CREDTEXT), 0);
- } else {
- khui_cw_unlock_nc(nc);
- khui_cw_clear_prompts(nc);
- khui_cw_lock_nc(nc);
- }
-
- khui_cw_unlock_nc(nc);
- }
- break;
-
- case KMSG_CRED_PROCESS:
- {
- khui_new_creds * nc;
- khui_new_creds_by_type * nct;
- k5_dlg_data * d;
-
- khm_int32 r = 0;
-
- nc = (khui_new_creds *) vparam;
-
- khui_cw_find_type(nc, credtype_id_krb5, &nct);
-
- if(!nct)
- break;
-
- /* reset the null_password flag, just in case */
- g_fjob.null_password = FALSE;
-
- if (nc->subtype == KMSG_CRED_NEW_CREDS) {
- d = (k5_dlg_data *) nct->aux;
- if (d == NULL)
- break;
-
- if (d->pwd_change) {
- /* we are forcing a password change */
- goto change_password;
- }
-
- _begin_task(0);
- _report_mr0(KHERR_NONE, MSG_CTX_INITAL_CREDS);
- _describe();
-
- if (g_fjob.state == FIBER_STATE_KINIT) {
- if(nc->result == KHUI_NC_RESULT_CANCEL) {
- g_fjob.command = FIBER_CMD_CANCEL;
- SwitchToFiber(k5_kinit_fiber);
-
- /* if we cancelled out, then we shouldn't care
- about the return code. */
-#ifdef DEBUG
- assert(g_fjob.state == FIBER_STATE_NONE);
-#endif
- g_fjob.code = 0;
-
- _reportf(L"Cancelling");
- } else if (nc->result == KHUI_NC_RESULT_PROCESS) {
- khui_cw_sync_prompt_values(nc);
- g_fjob.command = FIBER_CMD_CONTINUE;
- SwitchToFiber(k5_kinit_fiber);
-
- /* We get back here once the fiber finishes
- processing */
- }
-#ifdef DEBUG
- else {
- assert(FALSE);
- }
-#endif
- } else {
- /* we weren't in a KINIT state */
- if (nc->result == KHUI_NC_RESULT_CANCEL) {
- /* nothing to report */
- g_fjob.code = 0;
- } else if (nc->result == KHUI_NC_RESULT_PROCESS) {
- /* g_fjob.code should have the result of the
- last kinit attempt. We should leave it
- as-is */
- }
-#ifdef DEBUG
- else {
- /* unknown result */
- assert(FALSE);
- }
-#endif
- }
-
- /* special case: if there was no password entered, and
- if there is a valid TGT we allow the credential
- acquisition to go through */
- if (g_fjob.state == FIBER_STATE_NONE &&
- g_fjob.code &&
- g_fjob.null_password &&
-
- (nc->n_identities == 0 ||
- nc->identities[0] == NULL ||
- KHM_SUCCEEDED(kcdb_credset_find_filtered
- (NULL,
- -1,
- k5_find_tgt_filter,
- nc->identities[0],
- NULL,
- NULL)))) {
- _reportf(L"No password entered, but a valid TGT exists. Continuing");
- g_fjob.code = 0;
- } else if (g_fjob.state == FIBER_STATE_NONE &&
- g_fjob.code == 0 &&
- nc->n_identities > 0 &&
- nc->identities[0] != NULL) {
-
- /* we had a password and we used it to get
- tickets. We should reset the IMPORTED flag now
- since the tickets are not imported. */
-
- khm_krb5_set_identity_flags(nc->identities[0],
- K5IDFLAG_IMPORTED,
- 0);
- }
-
- if(g_fjob.code != 0) {
- wchar_t tbuf[1024];
- DWORD suggestion;
- kherr_suggestion suggest_code;
-
- khm_err_describe(g_fjob.code, tbuf, sizeof(tbuf),
- &suggestion, &suggest_code);
-
- _report_cs0(KHERR_ERROR, tbuf);
- if (suggestion != 0)
- _suggest_mr(suggestion, suggest_code);
-
- _resolve();
-
- r = KHUI_NC_RESPONSE_FAILED;
-
- if (suggest_code == KHERR_SUGGEST_RETRY) {
- r |= KHUI_NC_RESPONSE_NOEXIT |
- KHUI_NC_RESPONSE_PENDING;
- }
-
-#ifdef DEBUG
- assert(g_fjob.state == FIBER_STATE_NONE);
-#endif
-
- if (g_fjob.valid_principal &&
- nc->n_identities > 0 &&
- nc->identities[0]) {
- /* the principal was valid, so we can go ahead
- and update the LRU */
- k5_update_LRU(nc->identities[0]);
- }
-
- } else if (nc->result == KHUI_NC_RESULT_PROCESS &&
- g_fjob.state == FIBER_STATE_NONE) {
- krb5_context ctx = NULL;
-
- _reportf(L"Tickets successfully acquired");
-
- r = KHUI_NC_RESPONSE_SUCCESS |
- KHUI_NC_RESPONSE_EXIT;
-
- /* if we successfully obtained credentials, we
- should save the current settings in the
- identity config space */
-
- assert(nc->n_identities > 0);
- assert(nc->identities[0]);
-
- k5_write_dlg_params(d, nc->identities[0]);
-
- /* We should also quickly refresh the credentials
- so that the identity flags and ccache
- properties reflect the current state of
- affairs. This has to be done here so that
- other credentials providers which depend on
- Krb5 can properly find the initial creds to
- obtain their respective creds. */
-
- khm_krb5_list_tickets(&ctx);
-
- if (nc->set_default) {
- _reportf(L"Setting default identity");
- kcdb_identity_set_default(nc->identities[0]);
- }
-
- /* If there is no default identity, then make this the default */
- kcdb_identity_refresh(nc->identities[0]);
- {
- khm_handle tdefault = NULL;
-
- if (KHM_SUCCEEDED(kcdb_identity_get_default(&tdefault))) {
- kcdb_identity_release(tdefault);
- } else {
- _reportf(L"There was no default identity. Setting default");
- kcdb_identity_set_default(nc->identities[0]);
- }
- }
-
- /* and update the LRU */
- k5_update_LRU(nc->identities[0]);
-
- if (ctx != NULL)
- pkrb5_free_context(ctx);
- } else if (g_fjob.state == FIBER_STATE_NONE) {
- /* the user cancelled the operation */
- r = KHUI_NC_RESPONSE_EXIT |
- KHUI_NC_RESPONSE_SUCCESS;
- }
-
- if(g_fjob.state == FIBER_STATE_NONE) {
- khui_cw_set_response(nc, credtype_id_krb5, r);
-
- if (r & KHUI_NC_RESPONSE_NOEXIT) {
- /* if we are retrying the call, we should
- restart the kinit fiber */
-#ifdef DEBUG
- assert(r & KHUI_NC_RESPONSE_PENDING);
-#endif
-
- k5_prep_kinit_job(nc);
- SwitchToFiber(k5_kinit_fiber);
- } else {
- /* free up the fiber data fields. */
- k5_free_kinit_job();
- }
- } else {
- khui_cw_set_response(nc, credtype_id_krb5,
- KHUI_NC_RESPONSE_NOEXIT |
- KHUI_NC_RESPONSE_PENDING | r);
- }
-
- _end_task();
- } else if (nc->subtype == KMSG_CRED_RENEW_CREDS) {
-
- FILETIME ftidexp = {0,0};
- FILETIME ftcurrent;
- khm_size cb;
-
- GetSystemTimeAsFileTime(&ftcurrent);
-
- _begin_task(0);
- _report_mr0(KHERR_NONE, MSG_CTX_RENEW_CREDS);
- _describe();
-
- if (nc->ctx.scope == KHUI_SCOPE_IDENT ||
- (nc->ctx.scope == KHUI_SCOPE_CREDTYPE &&
- nc->ctx.cred_type == credtype_id_krb5) ||
- (nc->ctx.scope == KHUI_SCOPE_CRED &&
- nc->ctx.cred_type == credtype_id_krb5)) {
- int code;
-
- if (nc->ctx.scope == KHUI_SCOPE_CRED &&
- nc->ctx.cred != NULL) {
-
- /* get the expiration time for the identity first. */
- cb = sizeof(ftidexp);
-#ifdef DEBUG
- assert(nc->ctx.identity != NULL);
-#endif
- kcdb_identity_get_attr(nc->ctx.identity,
- KCDB_ATTR_EXPIRE,
- NULL,
- &ftidexp,
- &cb);
-
- code = khm_krb5_renew_cred(nc->ctx.cred);
-
- } else if (nc->ctx.scope == KHUI_SCOPE_IDENT &&
- nc->ctx.identity != 0) {
- /* get the current identity expiration time */
- cb = sizeof(ftidexp);
-
- kcdb_identity_get_attr(nc->ctx.identity,
- KCDB_ATTR_EXPIRE,
- NULL,
- &ftidexp,
- &cb);
-
- code = khm_krb5_renew_ident(nc->ctx.identity);
- } else {
-
- _reportf(L"No identity specified. Can't renew Kerberos tickets");
-
- code = 1; /* it just has to be non-zero */
- }
-
- if (code == 0) {
- _reportf(L"Tickets successfully renewed");
-
- khui_cw_set_response(nc, credtype_id_krb5,
- KHUI_NC_RESPONSE_EXIT |
- KHUI_NC_RESPONSE_SUCCESS);
- } else if (nc->ctx.identity == 0) {
-
- _report_mr0(KHERR_ERROR, MSG_ERR_NO_IDENTITY);
-
- khui_cw_set_response(nc, credtype_id_krb5,
- KHUI_NC_RESPONSE_EXIT |
- KHUI_NC_RESPONSE_FAILED);
- } else if (CompareFileTime(&ftcurrent, &ftidexp) < 0) {
- wchar_t tbuf[1024];
- DWORD suggestion;
- kherr_suggestion sug_id;
-
- /* if we failed to get new tickets, but the
- identity is still valid, then we assume that
- the current tickets are still good enough
- for other credential types to obtain their
- credentials. */
-
- khm_err_describe(code, tbuf, sizeof(tbuf),
- &suggestion, &sug_id);
-
- _report_cs0(KHERR_WARNING, tbuf);
- if (suggestion)
- _suggest_mr(suggestion, sug_id);
-
- _resolve();
-
- khui_cw_set_response(nc, credtype_id_krb5,
- KHUI_NC_RESPONSE_EXIT |
- KHUI_NC_RESPONSE_SUCCESS);
- } else {
- wchar_t tbuf[1024];
- DWORD suggestion;
- kherr_suggestion sug_id;
-
- khm_err_describe(code, tbuf, sizeof(tbuf),
- &suggestion, &sug_id);
-
- _report_cs0(KHERR_ERROR, tbuf);
- if (suggestion)
- _suggest_mr(suggestion, sug_id);
-
- _resolve();
-
- khui_cw_set_response(nc, credtype_id_krb5,
- ((sug_id == KHERR_SUGGEST_RETRY)?KHUI_NC_RESPONSE_NOEXIT:KHUI_NC_RESPONSE_EXIT) |
- KHUI_NC_RESPONSE_FAILED);
- }
- } else {
- khui_cw_set_response(nc, credtype_id_krb5,
- KHUI_NC_RESPONSE_EXIT |
- KHUI_NC_RESPONSE_SUCCESS);
- }
-
- _end_task();
- } else if (nc->subtype == KMSG_CRED_PASSWORD &&
- nc->result == KHUI_NC_RESULT_PROCESS) {
-
- change_password:
- /* we jump here if there was a password change forced */
-
- _begin_task(0);
- _report_mr0(KHERR_NONE, MSG_CTX_PASSWD);
- _describe();
-
- khui_cw_lock_nc(nc);
-
- if (nc->result == KHUI_NC_RESULT_CANCEL) {
-
- khui_cw_set_response(nc, credtype_id_krb5,
- KHUI_NC_RESPONSE_SUCCESS |
- KHUI_NC_RESPONSE_EXIT);
-
- } else if (nc->n_identities == 0 ||
- nc->identities[0] == NULL) {
- _report_mr0(KHERR_ERROR, MSG_PWD_NO_IDENTITY);
- _suggest_mr(MSG_PWD_S_NO_IDENTITY, KHERR_SUGGEST_RETRY);
-
- khui_cw_set_response(nc, credtype_id_krb5,
- KHUI_NC_RESPONSE_FAILED |
- KHUI_NC_RESPONSE_NOEXIT);
-
- } else {
- wchar_t widname[KCDB_IDENT_MAXCCH_NAME];
- char idname[KCDB_IDENT_MAXCCH_NAME];
- wchar_t wpwd[KHUI_MAXCCH_PASSWORD];
- char pwd[KHUI_MAXCCH_PASSWORD];
- wchar_t wnpwd[KHUI_MAXCCH_PASSWORD];
- char npwd[KHUI_MAXCCH_PASSWORD];
- wchar_t wnpwd2[KHUI_MAXCCH_PASSWORD];
- wchar_t * wresult;
- char * result;
- khm_size n_prompts = 0;
- khm_size cb;
- khm_int32 rv = KHM_ERROR_SUCCESS;
- long code = 0;
- khm_handle ident;
-
- khui_cw_get_prompt_count(nc, &n_prompts);
- assert(n_prompts == 3);
-
- ident = nc->identities[0];
- cb = sizeof(widname);
- rv = kcdb_identity_get_name(ident, widname, &cb);
- if (KHM_FAILED(rv)) {
-#ifdef DEBUG
- assert(FALSE);
-#endif
- _report_mr0(KHERR_ERROR, MSG_PWD_UNKNOWN);
- goto _pwd_exit;
- }
-
- cb = sizeof(wpwd);
- rv = khui_cw_get_prompt_value(nc, 0, wpwd, &cb);
- if (KHM_FAILED(rv)) {
-#ifdef DEBUG
- assert(FALSE);
-#endif
- _report_mr0(KHERR_ERROR, MSG_PWD_UNKNOWN);
- goto _pwd_exit;
- }
-
- cb = sizeof(wnpwd);
- rv = khui_cw_get_prompt_value(nc, 1, wnpwd, &cb);
- if (KHM_FAILED(rv)) {
-#ifdef DEBUG
- assert(FALSE);
-#endif
- _report_mr0(KHERR_ERROR, MSG_PWD_UNKNOWN);
- goto _pwd_exit;
- }
-
- cb = sizeof(wnpwd2);
- rv = khui_cw_get_prompt_value(nc, 2, wnpwd2, &cb);
- if (KHM_FAILED(rv)) {
-#ifdef DEBUG
- assert(FALSE);
-#endif
- _report_mr0(KHERR_ERROR, MSG_PWD_UNKNOWN);
- goto _pwd_exit;
- }
-
- if (wcscmp(wnpwd, wnpwd2)) {
- rv = KHM_ERROR_INVALID_PARAM;
- _report_mr0(KHERR_ERROR, MSG_PWD_NOT_SAME);
- _suggest_mr(MSG_PWD_S_NOT_SAME, KHERR_SUGGEST_INTERACT);
- goto _pwd_exit;
- }
-
- if (!wcscmp(wpwd, wnpwd)) {
- rv = KHM_ERROR_INVALID_PARAM;
- _report_mr0(KHERR_ERROR, MSG_PWD_SAME);
- _suggest_mr(MSG_PWD_S_SAME, KHERR_SUGGEST_INTERACT);
- goto _pwd_exit;
- }
-
- UnicodeStrToAnsi(idname, sizeof(idname), widname);
- UnicodeStrToAnsi(pwd, sizeof(pwd), wpwd);
- UnicodeStrToAnsi(npwd, sizeof(npwd), wnpwd);
-
- result = NULL;
-
- code = khm_krb5_changepwd(idname,
- pwd,
- npwd,
- &result);
-
- if (code)
- rv = KHM_ERROR_UNKNOWN;
- else {
- khm_handle csp_idcfg = NULL;
- krb5_context ctx = NULL;
-
- /* we set a new password. now we need to get
- initial credentials. */
-
- d = (k5_dlg_data *) nct->aux;
-
- if (d == NULL) {
- rv = KHM_ERROR_UNKNOWN;
- goto _pwd_exit;
- }
-
- if (nc->subtype == KMSG_CRED_PASSWORD) {
- /* since this was just a password change,
- we need to load new credentials options
- from the configuration store. */
-
- k5_read_dlg_params(d, nc->identities[0]);
- }
-
- /* the password change phase is now done */
- d->pwd_change = FALSE;
-
-#ifdef DEBUG
- _reportf(L"Calling khm_krb5_kinit()");
-#endif
- code = khm_krb5_kinit(NULL, /* context (create one) */
- idname, /* principal_name */
- npwd, /* new password */
- NULL, /* ccache name (figure out the identity cc)*/
- (krb5_deltat) d->tc_lifetime.current,
- d->forwardable,
- d->proxiable,
- (krb5_deltat)((d->renewable)?d->tc_renew.current:0),
- d->addressless, /* addressless */
- d->publicIP, /* public IP */
- NULL, /* prompter */
- NULL /* prompter data */);
-
- if (code) {
- rv = KHM_ERROR_UNKNOWN;
- goto _pwd_exit;
- }
-
- /* save the settings that we used for
- obtaining the ticket. */
- if (nc->subtype == KMSG_CRED_NEW_CREDS) {
-
- k5_write_dlg_params(d, nc->identities[0]);
-
- /* and then update the LRU too */
- k5_update_LRU(nc->identities[0]);
- }
-
- /* and do a quick refresh of the krb5 tickets
- so that other plug-ins that depend on krb5
- can look up tickets inside NetIDMgr */
- khm_krb5_list_tickets(&ctx);
-
- /* if there was no default identity, we make
- this one the default. */
- kcdb_identity_refresh(nc->identities[0]);
- {
- khm_handle tdefault = NULL;
-
- if (KHM_SUCCEEDED(kcdb_identity_get_default(&tdefault))) {
- kcdb_identity_release(tdefault);
- } else {
- _reportf(L"There was no default identity. Setting defualt");
- kcdb_identity_set_default(nc->identities[0]);
- }
- }
-
- if (ctx != NULL)
- pkrb5_free_context(ctx);
-
- if (nc->subtype == KMSG_CRED_PASSWORD) {
- /* if we obtained new credentials as a
- result of successfully changing the
- password, we also schedule an identity
- renewal for this identity. This allows
- the other credential types to obtain
- credentials for this identity. */
- khui_action_context ctx;
-
- _reportf(L"Scheduling renewal of [%s] after password change",
- widname);
-
- khui_context_create(&ctx,
- KHUI_SCOPE_IDENT,
- nc->identities[0],
- KCDB_CREDTYPE_INVALID,
- NULL);
- khui_action_trigger(KHUI_ACTION_RENEW_CRED,
- &ctx);
-
- khui_context_release(&ctx);
- }
- }
-
- /* result is only set when code != 0 */
- if (code && result) {
- size_t len;
-
- StringCchLengthA(result, KHERR_MAXCCH_STRING,
- &len);
- wresult = PMALLOC((len + 1) * sizeof(wchar_t));
-#ifdef DEBUG
- assert(wresult);
-#endif
- AnsiStrToUnicode(wresult, (len + 1) * sizeof(wchar_t),
- result);
-
- _report_cs1(KHERR_ERROR, L"%1!s!", _cstr(wresult));
- _resolve();
-
- PFREE(result);
- PFREE(wresult);
-
- /* we don't need to report anything more */
- code = 0;
- }
-
- _pwd_exit:
- if (KHM_FAILED(rv)) {
- if (code) {
- wchar_t tbuf[1024];
- DWORD suggestion;
- kherr_suggestion sug_id;
-
- khm_err_describe(code, tbuf, sizeof(tbuf),
- &suggestion, &sug_id);
- _report_cs0(KHERR_ERROR, tbuf);
-
- if (suggestion)
- _suggest_mr(suggestion, sug_id);
-
- _resolve();
- }
-
- khui_cw_set_response(nc, credtype_id_krb5,
- KHUI_NC_RESPONSE_NOEXIT|
- KHUI_NC_RESPONSE_FAILED);
- } else {
- khui_cw_set_response(nc, credtype_id_krb5,
- KHUI_NC_RESPONSE_SUCCESS |
- KHUI_NC_RESPONSE_EXIT);
- }
- }
-
- khui_cw_unlock_nc(nc);
-
- _end_task();
- } /* KMSG_CRED_PASSWORD */
- }
- break;
-
- case KMSG_CRED_END:
- {
- khui_new_creds * nc;
- khui_new_creds_by_type * nct;
-
- nc = (khui_new_creds *) vparam;
- khui_cw_find_type(nc, credtype_id_krb5, &nct);
-
- if(!nct)
- break;
-
- khui_cw_del_type(nc, credtype_id_krb5);
-
- if (nct->name)
- PFREE(nct->name);
- if (nct->credtext)
- PFREE(nct->credtext);
-
- PFREE(nct);
-
- k5_free_kinit_job();
- }
- break;
-
- case KMSG_CRED_IMPORT:
- {
- khm_int32 t = 0;
-
-#ifdef DEBUG
- assert(csp_params);
-#endif
- khc_read_int32(csp_params, L"MsLsaImport", &t);
-
- if (t != K5_LSAIMPORT_NEVER) {
- krb5_context ctx = NULL;
- khm_handle id_default = NULL;
- khm_handle id_imported = NULL;
- BOOL imported;
-
- imported = khm_krb5_ms2mit(NULL, (t == K5_LSAIMPORT_MATCH), TRUE,
- &id_imported);
- if (imported) {
- khm_krb5_list_tickets(&ctx);
-
- if (ctx)
- pkrb5_free_context(ctx);
-
- kcdb_identity_refresh(id_imported);
-
- if (KHM_SUCCEEDED(kcdb_identity_get_default(&id_default))) {
- kcdb_identity_release(id_default);
- id_default = NULL;
- } else {
- _reportf(L"There was no default identity. Setting default");
- kcdb_identity_set_default(id_imported);
- }
-
- /* and update the LRU */
- k5_update_LRU(id_imported);
- }
-
- if (id_imported)
- kcdb_identity_release(id_imported);
- }
- }
- break;
- }
-
- return rv;
-}
+/*
+ * Copyright (c) 2006 Secure Endpoints Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<krbcred.h>
+#include<kherror.h>
+#include<khmsgtypes.h>
+#include<strsafe.h>
+#include<krb5.h>
+
+#include<commctrl.h>
+
+#include<assert.h>
+
+extern LPVOID k5_main_fiber;
+extern LPVOID k5_kinit_fiber;
+
+typedef struct k5_dlg_data_t {
+ khui_new_creds * nc;
+
+ khui_tracker tc_lifetime;
+ khui_tracker tc_renew;
+
+ BOOL dirty; /* is the data in sync with the
+ configuration store? */
+ BOOL sync; /* is the data in sync with the kinit
+ request? */
+ DWORD renewable;
+ DWORD forwardable;
+ DWORD proxiable;
+ DWORD addressless;
+ DWORD publicIP;
+
+ wchar_t * cred_message; /* overrides the credential text, if
+ non-NULL */
+ BOOL pwd_change; /* force a password change */
+} k5_dlg_data;
+
+
+INT_PTR
+k5_handle_wm_initdialog(HWND hwnd,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ HWND hw;
+ k5_dlg_data * d;
+ khui_new_creds_by_type * nct;
+
+ d = PMALLOC(sizeof(*d));
+ ZeroMemory(d, sizeof(*d));
+ /* lParam is a pointer to a khui_new_creds structure */
+ d->nc = (khui_new_creds *) lParam;
+ khui_cw_find_type(d->nc, credtype_id_krb5, &nct);
+
+#pragma warning(push)
+#pragma warning(disable: 4244)
+ SetWindowLongPtr(hwnd, DWLP_USER, (LPARAM) d);
+#pragma warning(pop)
+
+ nct->aux = (LPARAM) d;
+
+ if (d->nc->subtype == KMSG_CRED_NEW_CREDS) {
+ khui_tracker_initialize(&d->tc_lifetime);
+ khui_tracker_initialize(&d->tc_renew);
+
+ hw = GetDlgItem(hwnd, IDC_NCK5_LIFETIME_EDIT);
+ khui_tracker_install(hw, &d->tc_lifetime);
+
+ hw = GetDlgItem(hwnd, IDC_NCK5_RENEW_EDIT);
+ khui_tracker_install(hw, &d->tc_renew);
+ }
+ return TRUE;
+}
+
+INT_PTR
+k5_handle_wm_destroy(HWND hwnd,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ k5_dlg_data * d;
+ khui_new_creds_by_type * nct = NULL;
+
+ d = (k5_dlg_data *) (LONG_PTR)
+ GetWindowLongPtr(hwnd, DWLP_USER);
+
+ if (!d)
+ return TRUE;
+
+ khui_cw_find_type(d->nc, credtype_id_krb5, &nct);
+
+#ifdef DEBUG
+ assert(nct);
+#endif
+
+ nct->aux = 0;
+
+ if (d->nc->subtype == KMSG_CRED_NEW_CREDS) {
+ khui_tracker_kill_controls(&d->tc_renew);
+ khui_tracker_kill_controls(&d->tc_lifetime);
+ }
+
+ PFREE(d);
+
+ return TRUE;
+}
+
+LRESULT
+k5_force_password_change(k5_dlg_data * d) {
+ /* we are turning this dialog into a change password dialog... */
+ wchar_t wbuf[KHUI_MAXCCH_BANNER];
+
+ khui_cw_clear_prompts(d->nc);
+
+ LoadString(hResModule, IDS_NC_PWD_BANNER,
+ wbuf, ARRAYLENGTH(wbuf));
+ khui_cw_begin_custom_prompts(d->nc, 3, NULL, wbuf);
+
+ LoadString(hResModule, IDS_NC_PWD_PWD,
+ wbuf, ARRAYLENGTH(wbuf));
+ khui_cw_add_prompt(d->nc, KHUI_NCPROMPT_TYPE_PASSWORD,
+ wbuf, NULL, KHUI_NCPROMPT_FLAG_HIDDEN);
+
+ LoadString(hResModule, IDS_NC_PWD_NPWD,
+ wbuf, ARRAYLENGTH(wbuf));
+ khui_cw_add_prompt(d->nc, KHUI_NCPROMPT_TYPE_NEW_PASSWORD,
+ wbuf, NULL, KHUI_NCPROMPT_FLAG_HIDDEN);
+
+ LoadString(hResModule, IDS_NC_PWD_NPWD_AGAIN,
+ wbuf, ARRAYLENGTH(wbuf));
+ khui_cw_add_prompt(d->nc, KHUI_NCPROMPT_TYPE_NEW_PASSWORD_AGAIN,
+ wbuf, NULL, KHUI_NCPROMPT_FLAG_HIDDEN);
+
+ d->pwd_change = TRUE;
+
+ if (is_k5_identpro &&
+ d->nc->n_identities > 0 &&
+ d->nc->identities[0]) {
+
+ kcdb_identity_set_flags(d->nc->identities[0],
+ KCDB_IDENT_FLAG_VALID,
+ KCDB_IDENT_FLAG_VALID);
+
+ }
+
+ PostMessage(d->nc->hwnd, KHUI_WM_NC_NOTIFY,
+ MAKEWPARAM(0, WMNC_UPDATE_CREDTEXT),
+ (LPARAM) d->nc);
+
+ return TRUE;
+}
+
+INT_PTR
+k5_handle_wmnc_notify(HWND hwnd,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ switch(HIWORD(wParam)) {
+ case WMNC_DIALOG_MOVE:
+ {
+ k5_dlg_data * d;
+
+ d = (k5_dlg_data *)(LONG_PTR)
+ GetWindowLongPtr(hwnd, DWLP_USER);
+
+ if (d->nc->subtype == KMSG_CRED_NEW_CREDS) {
+ khui_tracker_reposition(&d->tc_lifetime);
+ khui_tracker_reposition(&d->tc_renew);
+ }
+
+ return TRUE;
+ }
+ break;
+
+ case WMNC_DIALOG_SETUP:
+ {
+ k5_dlg_data * d;
+ BOOL old_sync;
+
+ d = (k5_dlg_data *)(LONG_PTR)
+ GetWindowLongPtr(hwnd, DWLP_USER);
+
+ if (d->nc->subtype == KMSG_CRED_PASSWORD)
+ return TRUE;
+
+ /* we save the value of the 'sync' field here because some
+ of the notifications that are generated while setting
+ the controls overwrite the field. */
+ old_sync = d->sync;
+
+ /* need to update the controls with d->* */
+ SendDlgItemMessage(hwnd, IDC_NCK5_RENEWABLE,
+ BM_SETCHECK,
+ (d->renewable? BST_CHECKED : BST_UNCHECKED),
+ 0);
+ EnableWindow(GetDlgItem(hwnd, IDC_NCK5_RENEW_EDIT),
+ !!d->renewable);
+
+ khui_tracker_refresh(&d->tc_lifetime);
+ khui_tracker_refresh(&d->tc_renew);
+
+ SendDlgItemMessage(hwnd, IDC_NCK5_FORWARDABLE,
+ BM_SETCHECK,
+ (d->forwardable ? BST_CHECKED : BST_UNCHECKED),
+ 0);
+
+ SendDlgItemMessage(hwnd, IDC_NCK5_ADDRESS,
+ BM_SETCHECK,
+ (d->addressless ? BST_CHECKED : BST_UNCHECKED),
+ 0);
+
+ SendDlgItemMessage(hwnd, IDC_NCK5_PUBLICIP,
+ IPM_SETADDRESS,
+ 0, d->publicIP);
+
+ EnableWindow(GetDlgItem(hwnd, IDC_NCK5_PUBLICIP), !d->addressless);
+
+ d->sync = old_sync;
+ }
+ break;
+
+ case WMNC_CREDTEXT_LINK:
+ {
+ k5_dlg_data * d;
+ khui_htwnd_link * l;
+ khui_new_creds * nc;
+ wchar_t linktext[128];
+
+ d = (k5_dlg_data *)(LONG_PTR)
+ GetWindowLongPtr(hwnd, DWLP_USER);
+ nc = d->nc;
+ l = (khui_htwnd_link *) lParam;
+
+ if (!l)
+ break;
+
+ StringCchCopyN(linktext, ARRAYLENGTH(linktext),
+ l->id, l->id_len);
+
+ if (!wcscmp(linktext, L"Krb5Cred:!Passwd")) {
+ return k5_force_password_change(d);
+ }
+ }
+ break;
+
+ case WMNC_UPDATE_CREDTEXT:
+ {
+ k5_dlg_data * d;
+ khui_new_creds * nc;
+ khui_new_creds_by_type * nct;
+ wchar_t sbuf[1024];
+ wchar_t fbuf[256];
+ wchar_t tbuf[256];
+ size_t cbsize;
+ khm_int32 flags;
+
+ d = (k5_dlg_data *)(LONG_PTR)
+ GetWindowLongPtr(hwnd, DWLP_USER);
+ nc = d->nc;
+ khui_cw_find_type(nc, credtype_id_krb5, &nct);
+
+ if(nct == NULL)
+ break;
+
+ if(nct->credtext)
+ PFREE(nct->credtext);
+ nct->credtext = NULL;
+
+ tbuf[0] = L'\0';
+
+ if (nc->n_identities > 0 &&
+ KHM_SUCCEEDED(kcdb_identity_get_flags(nc->identities[0],
+ &flags)) &&
+ (flags & KCDB_IDENT_FLAG_VALID) &&
+ nc->subtype == KMSG_CRED_NEW_CREDS &&
+ !d->pwd_change) {
+
+ if (is_k5_identpro)
+ k5_get_realm_from_nc(nc, tbuf, ARRAYLENGTH(tbuf));
+ else
+ GetDlgItemText(hwnd, IDC_NCK5_REALM, tbuf,
+ ARRAYLENGTH(tbuf));
+
+ /*TODO: if additional realms were specified, then those
+ must be listed as well */
+ LoadString(hResModule, IDS_KRB5_CREDTEXT_0,
+ fbuf, ARRAYLENGTH(fbuf));
+ StringCbPrintf(sbuf, sizeof(sbuf), fbuf,
+ tbuf);
+
+ StringCbLength(sbuf, sizeof(sbuf), &cbsize);
+ cbsize += sizeof(wchar_t);
+
+ nct->credtext = PMALLOC(cbsize);
+
+ StringCbCopy(nct->credtext, cbsize, sbuf);
+ } else if (nc->n_identities > 0 &&
+ (nc->subtype == KMSG_CRED_PASSWORD ||
+ (nc->subtype == KMSG_CRED_NEW_CREDS && d->pwd_change))) {
+ cbsize = sizeof(tbuf);
+ kcdb_identity_get_name(nc->identities[0], tbuf, &cbsize);
+
+ LoadString(hResModule, IDS_KRB5_CREDTEXT_P0,
+ fbuf, ARRAYLENGTH(fbuf));
+ StringCbPrintf(sbuf, sizeof(sbuf), fbuf, tbuf);
+
+ StringCbLength(sbuf, sizeof(sbuf), &cbsize);
+ cbsize += sizeof(wchar_t);
+
+ nct->credtext = PMALLOC(cbsize);
+
+ StringCbCopy(nct->credtext, cbsize, sbuf);
+ } else {
+ if (d->cred_message) {
+ StringCbLength(d->cred_message, KHUI_MAXCB_BANNER,
+ &cbsize);
+ cbsize += sizeof(wchar_t);
+
+ nct->credtext = PMALLOC(cbsize);
+
+ StringCbCopy(nct->credtext, cbsize, d->cred_message);
+ }
+ }
+ }
+ break;
+
+ case WMNC_IDENTITY_CHANGE:
+ {
+ /* There has been a change of identity */
+ k5_dlg_data * d;
+
+ d = (k5_dlg_data *)(LONG_PTR)
+ GetWindowLongPtr(hwnd, DWLP_USER);
+
+ kmq_post_sub_msg(k5_sub, KMSG_CRED,
+ KMSG_CRED_DIALOG_NEW_IDENTITY,
+ 0, (void *) d->nc);
+ }
+ break;
+
+ case WMNC_DIALOG_PREPROCESS:
+ {
+ k5_dlg_data * d;
+
+ d = (k5_dlg_data *)(LONG_PTR)
+ GetWindowLongPtr(hwnd, DWLP_USER);
+
+ if(!d->sync && d->nc->result == KHUI_NC_RESULT_PROCESS) {
+ kmq_post_sub_msg(k5_sub, KMSG_CRED,
+ KMSG_CRED_DIALOG_NEW_OPTIONS,
+ 0, (void *) d->nc);
+ }
+ }
+ break;
+
+ case K5_SET_CRED_MSG:
+ {
+ k5_dlg_data * d;
+ khm_size cb;
+ wchar_t * msg;
+
+ d = (k5_dlg_data *) (LONG_PTR)
+ GetWindowLongPtr(hwnd, DWLP_USER);
+
+ msg = (wchar_t *) lParam;
+
+ if (d->cred_message) {
+ PFREE(d->cred_message);
+ d->cred_message = NULL;
+ }
+
+ if (msg &&
+ SUCCEEDED(StringCbLength(msg,
+ KHUI_MAXCB_MESSAGE,
+ &cb))) {
+ cb += sizeof(wchar_t);
+ d->cred_message = PMALLOC(cb);
+#ifdef DEBUG
+ assert(d->cred_message);
+#endif
+ StringCbCopy(d->cred_message, cb, msg);
+ }
+ }
+ break;
+ }
+
+ return 0;
+}
+
+INT_PTR
+k5_handle_wm_notify(HWND hwnd,
+ WPARAM wParam,
+ LPARAM lParam) {
+ LPNMHDR pnmh;
+ k5_dlg_data * d;
+
+ pnmh = (LPNMHDR) lParam;
+ if (pnmh->idFrom == IDC_NCK5_PUBLICIP &&
+ pnmh->code == IPN_FIELDCHANGED) {
+
+ d = (k5_dlg_data *) (LONG_PTR) GetWindowLongPtr(hwnd, DWLP_USER);
+
+ SendDlgItemMessage(hwnd, IDC_NCK5_PUBLICIP,
+ IPM_GETADDRESS,
+ 0, (LPARAM) &d->publicIP);
+
+ d->dirty = TRUE;
+ d->sync = FALSE;
+
+ return TRUE;
+ }
+
+ return 0;
+}
+
+INT_PTR
+k5_handle_wm_command(HWND hwnd,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ int cid;
+ int notif;
+ k5_dlg_data * d;
+
+ d = (k5_dlg_data *)(LONG_PTR) GetWindowLongPtr(hwnd, DWLP_USER);
+
+ cid = LOWORD(wParam);
+ notif = HIWORD(wParam);
+
+ if(notif == BN_CLICKED && cid == IDC_NCK5_RENEWABLE) {
+ int c;
+ c = (int) SendDlgItemMessage(hwnd, IDC_NCK5_RENEWABLE,
+ BM_GETCHECK, 0, 0);
+ if(c==BST_CHECKED) {
+ EnableWindow(GetDlgItem(hwnd, IDC_NCK5_RENEW_EDIT), TRUE);
+ d->renewable = TRUE;
+ } else {
+ EnableWindow(GetDlgItem(hwnd, IDC_NCK5_RENEW_EDIT), FALSE);
+ d->renewable = FALSE;
+ }
+ d->dirty = TRUE;
+ d->sync = FALSE;
+ } else if(notif == BN_CLICKED && cid == IDC_NCK5_FORWARDABLE) {
+ int c;
+ c = (int) SendDlgItemMessage(hwnd, IDC_NCK5_FORWARDABLE,
+ BM_GETCHECK, 0, 0);
+ if(c==BST_CHECKED) {
+ d->forwardable = TRUE;
+ } else {
+ d->forwardable = FALSE;
+ }
+ d->dirty = TRUE;
+ d->sync = FALSE;
+ } else if (notif == BN_CLICKED && cid == IDC_NCK5_ADDRESS) {
+ int c;
+
+ c = (int) SendDlgItemMessage(hwnd, IDC_NCK5_ADDRESS,
+ BM_GETCHECK, 0, 0);
+
+ if (c==BST_CHECKED) {
+ d->addressless = TRUE;
+ } else {
+ d->addressless = FALSE;
+ }
+ d->dirty = TRUE;
+ d->sync = FALSE;
+
+ EnableWindow(GetDlgItem(hwnd, IDC_NCK5_PUBLICIP), !d->addressless);
+ } else if (notif == EN_CHANGE && (cid == IDC_NCK5_RENEW_EDIT ||
+ cid == IDC_NCK5_LIFETIME_EDIT)) {
+ d->dirty = TRUE;
+ d->sync = FALSE;
+ } else if((notif == CBN_SELCHANGE ||
+ notif == CBN_KILLFOCUS) &&
+ cid == IDC_NCK5_REALM &&
+ !is_k5_identpro) {
+ /* find out what the realm of the current identity
+ is, and if they are the same, then we don't do
+ anything */
+ wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
+ wchar_t realm[KCDB_IDENT_MAXCCH_NAME];
+ wchar_t *r;
+ khm_size cbsize;
+ khm_handle ident;
+ int idx;
+
+ if(d->nc->n_identities > 0) {
+ if(notif == CBN_SELCHANGE) {
+ idx = (int) SendDlgItemMessage(hwnd, IDC_NCK5_REALM,
+ CB_GETCURSEL, 0, 0);
+ SendDlgItemMessage(hwnd, IDC_NCK5_REALM,
+ CB_GETLBTEXT, idx, (LPARAM) realm);
+ } else {
+ GetDlgItemText(hwnd, IDC_NCK5_REALM,
+ realm, ARRAYLENGTH(realm));
+ }
+ cbsize = sizeof(idname);
+ if(KHM_SUCCEEDED(kcdb_identity_get_name(d->nc->identities[0],
+ idname, &cbsize))) {
+ r = wcschr(idname, L'@');
+ if(r && !wcscmp(realm, r+1))
+ return 0; /* nothing to do */
+
+ if(!r) {
+ r = idname + wcslen(idname);
+ *r++ = L'@';
+ *r++ = 0;
+ }
+
+ /* if we get here, we have a new user */
+ StringCchCopy(r+1,
+ ARRAYLENGTH(idname) - ((r+1) - idname),
+ realm);
+ if(KHM_SUCCEEDED(kcdb_identity_create(idname,
+ KCDB_IDENT_FLAG_CREATE,
+ &ident))) {
+ khui_cw_set_primary_id(d->nc, ident);
+ kcdb_identity_release(ident);
+ }
+ return 0;
+ }
+ }
+
+ /* if we get here, we have a new realm, but there is no
+ identity */
+ PostMessage(d->nc->hwnd, KHUI_WM_NC_NOTIFY,
+ MAKEWPARAM(0, WMNC_UPDATE_CREDTEXT), 0);
+ }
+
+ return 0;
+}
+
+
+/* Dialog procedure for the Krb5 credentials type panel.
+
+ NOTE: Runs in the context of the UI thread
+*/
+INT_PTR CALLBACK
+k5_nc_dlg_proc(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ switch(uMsg) {
+ case WM_INITDIALOG:
+ return k5_handle_wm_initdialog(hwnd, wParam, lParam);
+
+ case WM_COMMAND:
+ return k5_handle_wm_command(hwnd, wParam, lParam);
+
+ case KHUI_WM_NC_NOTIFY:
+ return k5_handle_wmnc_notify(hwnd, wParam, lParam);
+
+ case WM_NOTIFY:
+ return k5_handle_wm_notify(hwnd, wParam, lParam);
+
+ case WM_DESTROY:
+ return k5_handle_wm_destroy(hwnd, wParam, lParam);
+ }
+ return FALSE;
+}
+
+/* forward dcl */
+krb5_error_code KRB5_CALLCONV
+k5_kinit_prompter(krb5_context context,
+ void *data,
+ const char *name,
+ const char *banner,
+ int num_prompts,
+ krb5_prompt prompts[]);
+
+
+
+fiber_job g_fjob; /* global fiber job object */
+
+static BOOL
+k5_cached_kinit_prompter(void);
+
+static BOOL
+k5_cp_check_continue(void);
+
+/*
+ Runs in the context of the krb5 plugin's slave fiber
+*/
+VOID CALLBACK
+k5_kinit_fiber_proc(PVOID lpParameter)
+{
+ while(TRUE)
+ {
+ if(g_fjob.command == FIBER_CMD_KINIT) {
+ g_fjob.state = FIBER_STATE_KINIT;
+
+ g_fjob.prompt_set = 0;
+
+ if (k5_cached_kinit_prompter()) {
+ SwitchToFiber(k5_main_fiber);
+
+ if (g_fjob.command != FIBER_CMD_CONTINUE)
+ goto _switch_to_main;
+
+ if (!k5_cp_check_continue()) {
+ g_fjob.code = KRB5KRB_AP_ERR_BAD_INTEGRITY;
+ goto _switch_to_main;
+ }
+ }
+
+#ifdef DEBUG
+ /* log the state of g_fjob.* */
+ _reportf(L"g_fjob state prior to calling khm_krb5_kinit() :");
+ _reportf(L" g_fjob.principal = [%S]", g_fjob.principal);
+ _reportf(L" g_fjob.code = %d", g_fjob.code);
+ _reportf(L" g_fjob.state = %d", g_fjob.state);
+ _reportf(L" g_fjob.prompt_set= %d", g_fjob.prompt_set);
+ _reportf(L" g_fjob.valid_principal = %d", (int) g_fjob.valid_principal);
+#endif
+
+ /* If we don't know if we have a valid principal, we
+ restrict the options that are set when we call kinit.
+ This way we will be able to use the response from the
+ KDC to verify the principal. */
+
+ g_fjob.retry_if_valid_principal = (g_fjob.forwardable ||
+ g_fjob.proxiable ||
+ g_fjob.renewable);
+
+ retry_kinit:
+ g_fjob.code =
+ khm_krb5_kinit(0,
+ g_fjob.principal,
+ g_fjob.password,
+ g_fjob.ccache,
+ g_fjob.lifetime,
+ g_fjob.valid_principal ? g_fjob.forwardable : 0,
+ g_fjob.valid_principal ? g_fjob.proxiable : 0,
+ (g_fjob.valid_principal && g_fjob.renewable ? g_fjob.renew_life : 0),
+ g_fjob.addressless,
+ g_fjob.publicIP,
+ k5_kinit_prompter,
+ &g_fjob);
+
+ /* If the principal was found to be valid, and if we
+ restricted the options that were being passed to kinit,
+ then we need to retry the kinit call. This time we use
+ the real options. */
+ if (g_fjob.state == FIBER_STATE_RETRY_KINIT) {
+#ifdef DEBUG
+ assert(g_fjob.valid_principal);
+#endif
+ g_fjob.state = FIBER_STATE_KINIT;
+ goto retry_kinit;
+ }
+ }
+
+ _switch_to_main:
+ g_fjob.state = FIBER_STATE_NONE;
+
+ SwitchToFiber(k5_main_fiber);
+ }
+}
+
+/* return TRUE if we should go ahead with creds acquisition */
+static BOOL
+k5_cp_check_continue(void) {
+ khm_size i;
+ khm_size n_p;
+ khui_new_creds_prompt * p;
+ size_t cch;
+
+#ifdef DEBUG
+ assert(g_fjob.nc);
+#endif
+
+ if (KHM_FAILED(khui_cw_get_prompt_count(g_fjob.nc, &n_p))) {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ return TRUE;
+ }
+
+ khui_cw_sync_prompt_values(g_fjob.nc);
+
+ g_fjob.null_password = FALSE;
+
+ /* we are just checking whether there was a password field that
+ was left empty, in which case we can't continue with the
+ credentials acquisition. */
+ for (i=0; i < n_p; i++) {
+ if(KHM_FAILED(khui_cw_get_prompt(g_fjob.nc,
+ (int) i,
+ &p)))
+ continue;
+ if(p->type == KHUI_NCPROMPT_TYPE_PASSWORD) {
+ if (p->value == NULL ||
+ FAILED(StringCchLength(p->value, KHUI_MAXCCH_PROMPT,
+ &cch)) ||
+ cch == 0) {
+ g_fjob.null_password = TRUE;
+ return FALSE;
+ } else
+ break;
+ }
+ }
+
+ return TRUE;
+}
+
+/* returns true if we find cached prompts */
+static BOOL
+k5_cached_kinit_prompter(void) {
+ BOOL rv = FALSE;
+ khm_handle ident;
+ khm_handle csp_idconfig = NULL;
+ khm_handle csp_k5config = NULL;
+ khm_handle csp_prcache = NULL;
+ khm_size cb;
+ khm_size n_cur_prompts;
+ khm_int32 n_prompts;
+ khm_int32 i;
+ khm_int64 iexpiry;
+ FILETIME expiry;
+ FILETIME current;
+
+#ifdef DEBUG
+ assert(g_fjob.nc);
+#endif
+
+ ident = g_fjob.identity;
+ if (!ident)
+ return FALSE;
+
+ /* don't need to hold ident, since it is already held in g_fjob
+ and it doesn't change until we return */
+
+ if (KHM_FAILED(kcdb_identity_get_config(ident, 0, &csp_idconfig)) ||
+
+ KHM_FAILED(khc_open_space(csp_idconfig, CSNAME_KRB5CRED,
+ 0, &csp_k5config)) ||
+
+ KHM_FAILED(khc_open_space(csp_k5config, CSNAME_PROMPTCACHE,
+ 0, &csp_prcache)) ||
+
+ KHM_FAILED(khc_read_int32(csp_prcache, L"PromptCount",
+ &n_prompts)) ||
+ n_prompts == 0)
+
+ goto _cleanup;
+
+ if (KHM_SUCCEEDED(khc_read_int64(csp_prcache, L"ExpiresOn", &iexpiry))) {
+ /* has the cache expired? */
+ expiry = IntToFt(iexpiry);
+ GetSystemTimeAsFileTime(&current);
+
+ if (CompareFileTime(&expiry, &current) < 0)
+ /* already expired */
+ goto _cleanup;
+ } else {
+ /* if there is no value for ExpiresOn, we assume the prompts
+ have already expired. */
+ goto _cleanup;
+ }
+
+ /* we found a prompt cache. We take this to imply that the
+ principal is valid. */
+ g_fjob.valid_principal = TRUE;
+
+ /* check if there are any prompts currently showing. If there are
+ we check if they are the same as the ones we are going to show.
+ In which case we just reuse the exisitng prompts */
+ if (KHM_FAILED(khui_cw_get_prompt_count(g_fjob.nc,
+ &n_cur_prompts)) ||
+ n_prompts != (khm_int32) n_cur_prompts)
+ goto _show_new_prompts;
+
+ for(i = 0; i < n_prompts; i++) {
+ wchar_t wsname[8];
+ wchar_t wprompt[KHUI_MAXCCH_PROMPT];
+ khm_handle csp_p = NULL;
+ khm_int32 p_type;
+ khm_int32 p_flags;
+ khui_new_creds_prompt * p;
+
+ if (KHM_FAILED(khui_cw_get_prompt(g_fjob.nc, i, &p)))
+ break;
+
+ StringCbPrintf(wsname, sizeof(wsname), L"%d", i);
+
+ if (KHM_FAILED(khc_open_space(csp_prcache, wsname, 0, &csp_p)))
+ break;
+
+ cb = sizeof(wprompt);
+ if (KHM_FAILED(khc_read_string(csp_p, L"Prompt",
+ wprompt, &cb))) {
+ khc_close_space(csp_p);
+ break;
+ }
+
+ if (KHM_FAILED(khc_read_int32(csp_p, L"Type", &p_type)))
+ p_type = 0;
+
+ if (KHM_FAILED(khc_read_int32(csp_p, L"Flags", &p_flags)))
+ p_flags = 0;
+
+ if ( /* if we received a prompt string,
+ then it should be the same as the
+ one that is displayed */
+ (wprompt[0] &&
+ (p->prompt == NULL ||
+ wcscmp(wprompt, p->prompt))) ||
+
+ /* if we didn't receive one, then
+ there shouldn't be one displayed.
+ This case really shouldn't happen
+ in reality, but we check anyway. */
+ (!wprompt[0] &&
+ p->prompt != NULL) ||
+
+ /* the type should match */
+ (p_type != p->type) ||
+
+ /* if this prompt should be hidden,
+ then it must also be so */
+ (p_flags != p->flags)
+ ) {
+
+ khc_close_space(csp_p);
+ break;
+
+ }
+
+
+ khc_close_space(csp_p);
+ }
+
+ if (i == n_prompts) {
+ rv = TRUE;
+ goto _cleanup;
+ }
+
+ _show_new_prompts:
+
+ khui_cw_clear_prompts(g_fjob.nc);
+
+ {
+ wchar_t wbanner[KHUI_MAXCCH_BANNER];
+ wchar_t wpname[KHUI_MAXCCH_PNAME];
+
+ cb = sizeof(wbanner);
+ if (KHM_FAILED(khc_read_string(csp_prcache, L"Banner",
+ wbanner, &cb)))
+ wbanner[0] = 0;
+
+ cb = sizeof(wpname);
+ if (KHM_FAILED(khc_read_string(csp_prcache, L"Name",
+ wpname, &cb)))
+ wpname[0] = 0;
+
+ khui_cw_begin_custom_prompts(g_fjob.nc,
+ n_prompts,
+ (wbanner[0]? wbanner: NULL),
+ (wpname[0]? wpname: NULL));
+ }
+
+ for(i = 0; i < n_prompts; i++) {
+ wchar_t wsname[8];
+ wchar_t wprompt[KHUI_MAXCCH_PROMPT];
+ khm_handle csp_p = NULL;
+ khm_int32 p_type;
+ khm_int32 p_flags;
+
+ StringCbPrintf(wsname, sizeof(wsname), L"%d", i);
+
+ if (KHM_FAILED(khc_open_space(csp_prcache, wsname, 0, &csp_p)))
+ break;
+
+ cb = sizeof(wprompt);
+ if (KHM_FAILED(khc_read_string(csp_p, L"Prompt",
+ wprompt, &cb))) {
+ khc_close_space(csp_p);
+ break;
+ }
+
+ if (KHM_FAILED(khc_read_int32(csp_p, L"Type", &p_type)))
+ p_type = 0;
+
+ if (KHM_FAILED(khc_read_int32(csp_p, L"Flags", &p_flags)))
+ p_flags = 0;
+
+ khui_cw_add_prompt(g_fjob.nc, p_type, wprompt, NULL, p_flags);
+
+ khc_close_space(csp_p);
+ }
+
+ if (i < n_prompts) {
+ khui_cw_clear_prompts(g_fjob.nc);
+ } else {
+ rv = TRUE;
+ }
+
+ _cleanup:
+
+ if (csp_prcache)
+ khc_close_space(csp_prcache);
+
+ if (csp_k5config)
+ khc_close_space(csp_k5config);
+
+ if (csp_idconfig)
+ khc_close_space(csp_idconfig);
+
+ return rv;
+}
+
+/* Runs in the context of the Krb5 plugin's slave fiber */
+krb5_error_code KRB5_CALLCONV
+k5_kinit_prompter(krb5_context context,
+ void *data,
+ const char *name,
+ const char *banner,
+ int num_prompts,
+ krb5_prompt prompts[])
+{
+ int i;
+ khui_new_creds * nc;
+ krb5_prompt_type * ptypes;
+ khm_size ncp;
+ krb5_error_code code = 0;
+ BOOL new_prompts = TRUE;
+ khm_handle csp_prcache = NULL;
+
+#ifdef DEBUG
+ _reportf(L"k5_kinit_prompter() received %d prompts with name=[%S] banner=[%S]",
+ num_prompts,
+ name, banner);
+ for (i=0; i < num_prompts; i++) {
+ _reportf(L"Prompt[%d]: string[%S]", i, prompts[i].prompt);
+ }
+#endif
+
+ /* we got prompts? Then we assume that the principal is valid */
+
+ if (!g_fjob.valid_principal) {
+ g_fjob.valid_principal = TRUE;
+
+ /* if the flags that were used to call kinit were restricted
+ because we didn't know the validity of the principal, then
+ we need to go back and retry the call with the correct
+ flags. */
+ if (g_fjob.retry_if_valid_principal) {
+ _reportf(L"Retrying kinit call due to restricted flags on first call.");
+ g_fjob.state = FIBER_STATE_RETRY_KINIT;
+ return KRB5_LIBOS_PWDINTR;
+ }
+ }
+
+ nc = g_fjob.nc;
+
+ if(pkrb5_get_prompt_types)
+ ptypes = pkrb5_get_prompt_types(context);
+ else
+ ptypes = NULL;
+
+ /* check if we are already showing the right prompts */
+ khui_cw_get_prompt_count(nc, &ncp);
+
+ if (num_prompts != (int) ncp)
+ goto _show_new_prompts;
+
+ for (i=0; i < num_prompts; i++) {
+ wchar_t wprompt[KHUI_MAXCCH_PROMPT];
+ khui_new_creds_prompt * p;
+
+ if(prompts[i].prompt) {
+ AnsiStrToUnicode(wprompt, sizeof(wprompt),
+ prompts[i].prompt);
+ } else {
+ wprompt[0] = 0;
+ }
+
+ if (KHM_FAILED(khui_cw_get_prompt(nc, i, &p)))
+ break;
+
+ if ( /* if we received a prompt string,
+ then it should be the same as the
+ one that is displayed */
+ (wprompt[0] &&
+ (p->prompt == NULL ||
+ wcscmp(wprompt, p->prompt))) ||
+ /* if we didn't receive one, then
+ there shouldn't be one displayed.
+ This case really shouldn't happen
+ in reality, but we check anyway. */
+ (!wprompt[0] &&
+ p->prompt != NULL) ||
+ /* the type should match */
+ (ptypes &&
+ ptypes[i] != p->type) ||
+ (!ptypes &&
+ p->type != 0) ||
+ /* if this prompt should be hidden,
+ then it must also be so */
+ (prompts[i].hidden &&
+ !(p->flags & KHUI_NCPROMPT_FLAG_HIDDEN)) ||
+ (!prompts[i].hidden &&
+ (p->flags & KHUI_NCPROMPT_FLAG_HIDDEN))
+ )
+ break;
+ }
+
+ if (i < num_prompts)
+ goto _show_new_prompts;
+
+ new_prompts = FALSE;
+
+ /* ok. looks like we are already showing the same set of prompts
+ that we were supposed to show. Sync up the values and go
+ ahead. */
+ khui_cw_sync_prompt_values(nc);
+ goto _process_prompts;
+
+ _show_new_prompts:
+ /* special case. if there are no actual input controls involved,
+ then we have to show an alerter window and pass through */
+ if (num_prompts == 0) {
+ wchar_t wbanner[KHUI_MAXCCH_BANNER];
+ wchar_t wname[KHUI_MAXCCH_PNAME];
+ wchar_t wident[KCDB_IDENT_MAXCCH_NAME];
+ wchar_t wmsg[KHUI_MAXCCH_MESSAGE];
+ wchar_t wfmt[KHUI_MAXCCH_BANNER];
+ khm_size cb;
+
+ if (!banner) {
+ code = 0;
+ g_fjob.null_password = FALSE;
+ goto _exit;
+ } else {
+ AnsiStrToUnicode(wbanner, sizeof(wbanner), banner);
+ }
+
+ if (name) {
+ AnsiStrToUnicode(wname, sizeof(wname), name);
+ } else {
+ LoadString(hResModule,
+ IDS_KRB5_WARNING,
+ wname,
+ ARRAYLENGTH(wname));
+ }
+
+ cb = sizeof(wident);
+ if (KHM_FAILED(kcdb_identity_get_name(g_fjob.identity, wident, &cb)))
+ wident[0] = L'\0';
+
+ LoadString(hResModule,
+ IDS_KRB5_WARN_FMT,
+ wfmt,
+ ARRAYLENGTH(wfmt));
+
+ StringCbPrintf(wmsg, sizeof(wmsg), wfmt, wident, wbanner);
+
+ khui_alert_show_simple(wname, wmsg, KHERR_WARNING);
+
+ code = 0;
+ g_fjob.null_password = FALSE;
+ goto _exit;
+ }
+
+ /* in addition to showing new prompts, we also cache the set of
+ prompts. */
+ if(g_fjob.prompt_set == 0) {
+ khm_handle csp_idconfig = NULL;
+ khm_handle csp_idk5 = NULL;
+
+ kcdb_identity_get_config(g_fjob.identity,
+ KHM_FLAG_CREATE,
+ &csp_idconfig);
+
+ if (csp_idconfig != NULL)
+ khc_open_space(csp_idconfig,
+ CSNAME_KRB5CRED,
+ KHM_FLAG_CREATE,
+ &csp_idk5);
+
+ if (csp_idk5 != NULL)
+ khc_open_space(csp_idk5,
+ CSNAME_PROMPTCACHE,
+ KHM_FLAG_CREATE,
+ &csp_prcache);
+
+ khc_close_space(csp_idconfig);
+ khc_close_space(csp_idk5);
+ }
+
+ {
+ wchar_t wbanner[KHUI_MAXCCH_BANNER];
+ wchar_t wname[KHUI_MAXCCH_PNAME];
+ FILETIME current;
+ FILETIME lifetime;
+ FILETIME expiry;
+ khm_int64 iexpiry;
+ khm_int32 t = 0;
+
+ if(banner)
+ AnsiStrToUnicode(wbanner, sizeof(wbanner), banner);
+ if(name)
+ AnsiStrToUnicode(wname, sizeof(wname), name);
+
+ khui_cw_clear_prompts(nc);
+
+ khui_cw_begin_custom_prompts(
+ nc,
+ num_prompts,
+ (banner)?wbanner:NULL,
+ (name)?wname:NULL);
+
+ if (csp_prcache) {
+
+ if (banner)
+ khc_write_string(csp_prcache,
+ L"Banner",
+ wbanner);
+ else
+ khc_write_string(csp_prcache,
+ L"Banner",
+ L"");
+
+ if (name)
+ khc_write_string(csp_prcache,
+ L"Name",
+ wname);
+ else if (csp_prcache)
+ khc_write_string(csp_prcache,
+ L"Name",
+ L"");
+
+ khc_write_int32(csp_prcache,
+ L"PromptCount",
+ (khm_int32) num_prompts);
+
+ GetSystemTimeAsFileTime(&current);
+#ifdef USE_PROMPT_CACHE_LIFETIME
+ khc_read_int32(csp_params, L"PromptCacheLifetime", &t);
+ if (t == 0)
+ t = 172800; /* 48 hours */
+#else
+ khc_read_int32(csp_params, L"MaxRenewLifetime", &t);
+ if (t == 0)
+ t = 2592000; /* 30 days */
+ t += 604800; /* + 7 days */
+#endif
+ TimetToFileTimeInterval(t, &lifetime);
+ expiry = FtAdd(&current, &lifetime);
+ iexpiry = FtToInt(&expiry);
+
+ khc_write_int64(csp_prcache, L"ExpiresOn", iexpiry);
+ }
+ }
+
+ for(i=0; i < num_prompts; i++) {
+ wchar_t wprompt[KHUI_MAXCCH_PROMPT];
+
+ if(prompts[i].prompt) {
+ AnsiStrToUnicode(wprompt, sizeof(wprompt),
+ prompts[i].prompt);
+ } else {
+ wprompt[0] = 0;
+ }
+
+ khui_cw_add_prompt(
+ nc,
+ (ptypes?ptypes[i]:0),
+ wprompt,
+ NULL,
+ (prompts[i].hidden?KHUI_NCPROMPT_FLAG_HIDDEN:0));
+
+ if (csp_prcache) {
+ khm_handle csp_p = NULL;
+ wchar_t wnum[8]; /* should be enough for 10
+ million prompts */
+
+ wnum[0] = 0;
+ StringCbPrintf(wnum, sizeof(wnum), L"%d", i);
+
+ khc_open_space(csp_prcache, wnum,
+ KHM_FLAG_CREATE, &csp_p);
+
+ if (csp_p) {
+ khc_write_string(csp_p, L"Prompt", wprompt);
+ khc_write_int32(csp_p, L"Type", (ptypes?ptypes[i]:0));
+ khc_write_int32(csp_p, L"Flags",
+ (prompts[i].hidden?
+ KHUI_NCPROMPT_FLAG_HIDDEN:0));
+
+ khc_close_space(csp_p);
+ }
+ }
+ }
+
+ if (csp_prcache) {
+ khc_close_space(csp_prcache);
+ csp_prcache = NULL;
+ }
+
+ _process_prompts:
+ /* switch back to main thread if we showed new prompts */
+ if (new_prompts)
+ SwitchToFiber(k5_main_fiber);
+
+ /* we get here after the user selects an action that either
+ cancles the credentials acquisition operation or triggers the
+ actual acquisition of credentials. */
+ if(g_fjob.command != FIBER_CMD_CONTINUE &&
+ g_fjob.command != FIBER_CMD_KINIT) {
+ code = KRB5_LIBOS_PWDINTR;
+ goto _exit;
+ }
+
+ g_fjob.null_password = FALSE;
+
+ /* otherwise, we need to get the data back from the UI and
+ return 0 */
+ for(i=0; i<num_prompts; i++) {
+ krb5_data * d;
+ wchar_t wbuf[512];
+ khm_size cbbuf;
+ size_t cch;
+
+ d = prompts[i].reply;
+
+ cbbuf = sizeof(wbuf);
+ if(KHM_SUCCEEDED(khui_cw_get_prompt_value(nc, i, wbuf, &cbbuf))) {
+ UnicodeStrToAnsi(d->data, d->length, wbuf);
+ if(SUCCEEDED(StringCchLengthA(d->data, d->length, &cch)))
+ d->length = (unsigned int) cch;
+ else
+ d->length = 0;
+ } else {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ d->length = 0;
+ }
+
+ if (ptypes &&
+ ptypes[i] == KRB5_PROMPT_TYPE_PASSWORD &&
+ d->length == 0)
+
+ g_fjob.null_password = TRUE;
+ }
+
+ _exit:
+
+ g_fjob.prompt_set++;
+
+ /* entering a NULL password is equivalent to cancelling out */
+ if (g_fjob.null_password)
+ return KRB5_LIBOS_PWDINTR;
+ else
+ return code;
+}
+
+
+void
+k5_read_dlg_params(k5_dlg_data * d, khm_handle identity)
+{
+ k5_params p;
+
+ khm_krb5_get_identity_params(identity, &p);
+
+ d->renewable = p.renewable;
+ d->forwardable = p.forwardable;
+ d->proxiable = p.proxiable;
+ d->addressless = p.addressless;
+ d->publicIP = p.publicIP;
+
+ d->tc_lifetime.current = p.lifetime;
+ d->tc_lifetime.max = p.lifetime_max;
+ d->tc_lifetime.min = p.lifetime_min;
+
+ d->tc_renew.current = p.renew_life;
+ d->tc_renew.max = p.renew_life_max;
+ d->tc_renew.min = p.renew_life_min;
+
+ /* however, if this has externally supplied defaults, we have to
+ use them too. */
+ if (d->nc && d->nc->ctx.vparam &&
+ d->nc->ctx.cb_vparam == sizeof(NETID_DLGINFO)) {
+ LPNETID_DLGINFO pdlginfo;
+
+ pdlginfo = (LPNETID_DLGINFO) d->nc->ctx.vparam;
+ if (pdlginfo->size == NETID_DLGINFO_V1_SZ &&
+ pdlginfo->in.use_defaults == 0) {
+ d->forwardable = pdlginfo->in.forwardable;
+ d->addressless = pdlginfo->in.noaddresses;
+ d->tc_lifetime.current = pdlginfo->in.lifetime;
+ d->tc_renew.current = pdlginfo->in.renew_till;
+
+ if (pdlginfo->in.renew_till == 0)
+ d->renewable = FALSE;
+ else
+ d->renewable = TRUE;
+
+ d->proxiable = pdlginfo->in.proxiable;
+ d->publicIP = pdlginfo->in.publicip;
+ }
+ }
+
+ /* once we read the new data, in, it is no longer considered
+ dirty */
+ d->dirty = FALSE;
+ d->sync = FALSE;
+}
+
+void
+k5_write_dlg_params(k5_dlg_data * d, khm_handle identity)
+{
+
+ k5_params p;
+
+ ZeroMemory(&p, sizeof(p));
+
+ p.source_reg = K5PARAM_FM_ALL; /* we want to write all the
+ settings to the registry, if
+ necessary. */
+
+ p.renewable = d->renewable;
+ p.forwardable = d->forwardable;
+ p.proxiable = d->proxiable;
+ p.addressless = d->addressless;
+ p.publicIP = d->publicIP;
+
+ p.lifetime = (krb5_deltat) d->tc_lifetime.current;
+ p.lifetime_max = (krb5_deltat) d->tc_lifetime.max;
+ p.lifetime_min = (krb5_deltat) d->tc_lifetime.min;
+
+ p.renew_life = (krb5_deltat) d->tc_renew.current;
+ p.renew_life_max = (krb5_deltat) d->tc_renew.max;
+ p.renew_life_min = (krb5_deltat) d->tc_renew.min;
+
+ khm_krb5_set_identity_params(identity, &p);
+
+ /* as in k5_read_dlg_params, once we write the data in, the local
+ data is no longer dirty */
+ d->dirty = FALSE;
+}
+
+void
+k5_free_kinit_job(void)
+{
+ if (g_fjob.principal)
+ PFREE(g_fjob.principal);
+
+ if (g_fjob.password)
+ PFREE(g_fjob.password);
+
+ if (g_fjob.identity)
+ kcdb_identity_release(g_fjob.identity);
+
+ if (g_fjob.ccache)
+ PFREE(g_fjob.ccache);
+
+ ZeroMemory(&g_fjob, sizeof(g_fjob));
+}
+
+void
+k5_prep_kinit_job(khui_new_creds * nc)
+{
+ khui_new_creds_by_type * nct;
+ k5_dlg_data * d;
+ wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
+ khm_size cbbuf;
+ size_t size;
+ khm_handle ident;
+ LPNETID_DLGINFO pdlginfo;
+
+ khui_cw_find_type(nc, credtype_id_krb5, &nct);
+ if (!nct)
+ return;
+
+ d = (k5_dlg_data *)(LONG_PTR)
+ GetWindowLongPtr(nct->hwnd_panel, DWLP_USER);
+
+ if (!d)
+ return;
+
+ khui_cw_lock_nc(nc);
+ ident = nc->identities[0];
+ kcdb_identity_hold(ident);
+ khui_cw_unlock_nc(nc);
+
+ cbbuf = sizeof(idname);
+ kcdb_identity_get_name(ident, idname, &cbbuf);
+ StringCchLength(idname, ARRAYLENGTH(idname), &size);
+ size++;
+
+ k5_free_kinit_job();
+
+ g_fjob.command = FIBER_CMD_KINIT;
+ g_fjob.nc = nc;
+ g_fjob.nct = nct;
+ g_fjob.dialog = nct->hwnd_panel;
+ g_fjob.principal = PMALLOC(size);
+ UnicodeStrToAnsi(g_fjob.principal, size, idname);
+ g_fjob.password = NULL;
+ g_fjob.lifetime = (krb5_deltat) d->tc_lifetime.current;
+ g_fjob.forwardable = d->forwardable;
+ g_fjob.proxiable = d->proxiable;
+ g_fjob.renewable = d->renewable;
+ g_fjob.renew_life = (krb5_deltat) d->tc_renew.current;
+ g_fjob.addressless = d->addressless;
+ g_fjob.publicIP = d->publicIP;
+ g_fjob.code = 0;
+ g_fjob.identity = ident;
+ g_fjob.prompt_set = 0;
+ g_fjob.valid_principal = FALSE;
+ g_fjob.retry_if_valid_principal = FALSE;
+
+ /* the value for
+ retry_if_valid_principal is not
+ necessarily the correct value here,
+ but the correct value will be
+ assigned k5_kinit_fiber_proc(). */
+
+ /* if we have external parameters, we should use them as well */
+ if (nc->ctx.cb_vparam == sizeof(NETID_DLGINFO) &&
+ (pdlginfo = nc->ctx.vparam) &&
+ pdlginfo->size == NETID_DLGINFO_V1_SZ) {
+ wchar_t * t;
+
+ if (pdlginfo->in.ccache[0] &&
+ SUCCEEDED(StringCchLength(pdlginfo->in.ccache,
+ NETID_CCACHE_NAME_SZ,
+ &size))) {
+ g_fjob.ccache = PMALLOC(sizeof(char) * (size + 1));
+#ifdef DEBUG
+ assert(g_fjob.ccache);
+#endif
+ UnicodeStrToAnsi(g_fjob.ccache, size + 1,
+ pdlginfo->in.ccache);
+
+ /* this is the same as the output cache */
+
+ StringCbCopy(pdlginfo->out.ccache, sizeof(pdlginfo->out.ccache),
+ pdlginfo->in.ccache);
+ } else {
+ g_fjob.ccache = NULL;
+
+ StringCbCopy(pdlginfo->out.ccache, sizeof(pdlginfo->out.ccache),
+ idname);
+
+ khm_krb5_canon_cc_name(pdlginfo->out.ccache,
+ sizeof(pdlginfo->out.ccache));
+ }
+
+ t = khm_get_realm_from_princ(idname);
+
+ if (t) {
+ StringCbCopy(pdlginfo->out.realm,
+ sizeof(pdlginfo->out.realm),
+ t);
+
+ if ((t - idname) > 1) {
+ StringCchCopyN(pdlginfo->out.username,
+ ARRAYLENGTH(pdlginfo->out.username),
+ idname,
+ (t - idname) - 1);
+ } else {
+ StringCbCopy(pdlginfo->out.username,
+ sizeof(pdlginfo->out.username),
+ L"");
+ }
+ } else {
+ StringCbCopy(pdlginfo->out.username,
+ sizeof(pdlginfo->out.username),
+ idname);
+ StringCbCopy(pdlginfo->out.realm,
+ sizeof(pdlginfo->out.realm),
+ L"");
+ }
+ }
+
+ /* leave identity held, since we added a reference above */
+}
+
+static khm_int32 KHMAPI
+k5_find_tgt_filter(khm_handle cred,
+ khm_int32 flags,
+ void * rock) {
+ khm_handle ident = (khm_handle) rock;
+ khm_handle cident = NULL;
+ khm_int32 f;
+ khm_int32 rv;
+
+ if (KHM_SUCCEEDED(kcdb_cred_get_identity(cred,
+ &cident)) &&
+ cident == ident &&
+ KHM_SUCCEEDED(kcdb_cred_get_flags(cred, &f)) &&
+ (f & KCDB_CRED_FLAG_INITIAL) &&
+ !(f & KCDB_CRED_FLAG_EXPIRED))
+ rv = 1;
+ else
+ rv = 0;
+
+ if (cident)
+ kcdb_identity_release(cident);
+
+ return rv;
+}
+
+khm_int32
+k5_remove_from_LRU(khm_handle identity)
+{
+ wchar_t * wbuf = NULL;
+ wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
+ khm_size cb;
+ khm_size cb_ms;
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+
+ cb = sizeof(idname);
+ rv = kcdb_identity_get_name(identity, idname, &cb);
+ assert(rv == KHM_ERROR_SUCCESS);
+
+ rv = khc_read_multi_string(csp_params, L"LRUPrincipals", NULL, &cb_ms);
+ if (rv != KHM_ERROR_TOO_LONG)
+ cb_ms = sizeof(wchar_t) * 2;
+
+ wbuf = PMALLOC(cb_ms);
+ assert(wbuf);
+
+ cb = cb_ms;
+
+ if (rv == KHM_ERROR_TOO_LONG) {
+ rv = khc_read_multi_string(csp_params, L"LRUPrincipals", wbuf, &cb);
+ assert(KHM_SUCCEEDED(rv));
+
+ if (multi_string_find(wbuf, idname, KHM_CASE_SENSITIVE) != NULL) {
+ multi_string_delete(wbuf, idname, KHM_CASE_SENSITIVE);
+ }
+ } else {
+ multi_string_init(wbuf, cb_ms);
+ }
+
+ rv = khc_write_multi_string(csp_params, L"LRUPrincipals", wbuf);
+
+ if (wbuf)
+ PFREE(wbuf);
+
+ return rv;
+}
+
+khm_int32
+k5_update_LRU(khm_handle identity)
+{
+ wchar_t * wbuf = NULL;
+ wchar_t * idname = NULL;
+ wchar_t * realm = NULL;
+ khm_size cb;
+ khm_size cb_ms;
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+
+ rv = kcdb_identity_get_name(identity, NULL, &cb);
+ assert(rv == KHM_ERROR_TOO_LONG);
+
+ idname = PMALLOC(cb);
+ assert(idname);
+
+ rv = kcdb_identity_get_name(identity, idname, &cb);
+ assert(KHM_SUCCEEDED(rv));
+
+ rv = khc_read_multi_string(csp_params, L"LRUPrincipals", NULL, &cb_ms);
+ if (rv != KHM_ERROR_TOO_LONG)
+ cb_ms = cb + sizeof(wchar_t);
+ else
+ cb_ms += cb + sizeof(wchar_t);
+
+ wbuf = PMALLOC(cb_ms);
+ assert(wbuf);
+
+ cb = cb_ms;
+
+ if (rv == KHM_ERROR_TOO_LONG) {
+ rv = khc_read_multi_string(csp_params, L"LRUPrincipals", wbuf, &cb);
+ assert(KHM_SUCCEEDED(rv));
+
+ if (multi_string_find(wbuf, idname, KHM_CASE_SENSITIVE) != NULL) {
+ /* it's already there. We remove it here and add it at
+ the top of the LRU list. */
+ multi_string_delete(wbuf, idname, KHM_CASE_SENSITIVE);
+ }
+ } else {
+ multi_string_init(wbuf, cb_ms);
+ }
+
+ cb = cb_ms;
+ rv = multi_string_prepend(wbuf, &cb, idname);
+ assert(KHM_SUCCEEDED(rv));
+
+ rv = khc_write_multi_string(csp_params, L"LRUPrincipals", wbuf);
+
+ realm = khm_get_realm_from_princ(idname);
+ if (realm == NULL || *realm == L'\0')
+ goto _done_with_LRU;
+
+ cb = cb_ms;
+ rv = khc_read_multi_string(csp_params, L"LRURealms", wbuf, &cb);
+
+ if (rv == KHM_ERROR_TOO_LONG) {
+ PFREE(wbuf);
+ wbuf = PMALLOC(cb);
+ assert(wbuf);
+
+ cb_ms = cb;
+
+ rv = khc_read_multi_string(csp_params, L"LRURealms", wbuf, &cb);
+
+ assert(KHM_SUCCEEDED(rv));
+ } else if (rv == KHM_ERROR_SUCCESS) {
+ if (multi_string_find(wbuf, realm, KHM_CASE_SENSITIVE) != NULL) {
+ /* remove the realm and add it at the top later. */
+ multi_string_delete(wbuf, realm, KHM_CASE_SENSITIVE);
+ }
+ } else {
+ multi_string_init(wbuf, cb_ms);
+ }
+
+ cb = cb_ms;
+ rv = multi_string_prepend(wbuf, &cb, realm);
+
+ if (rv == KHM_ERROR_TOO_LONG) {
+ wbuf = PREALLOC(wbuf, cb);
+
+ rv = multi_string_prepend(wbuf, &cb, realm);
+
+ assert(KHM_SUCCEEDED(rv));
+ }
+
+ rv = khc_write_multi_string(csp_params, L"LRURealms", wbuf);
+
+ assert(KHM_SUCCEEDED(rv));
+
+ _done_with_LRU:
+
+ if (wbuf)
+ PFREE(wbuf);
+ if (idname)
+ PFREE(idname);
+
+ return rv;
+}
+
+/* Handler for CRED type messages
+
+ Runs in the context of the Krb5 plugin
+*/
+khm_int32 KHMAPI
+k5_msg_cred_dialog(khm_int32 msg_type,
+ khm_int32 msg_subtype,
+ khm_ui_4 uparam,
+ void * vparam)
+{
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+
+ switch(msg_subtype) {
+
+ case KMSG_CRED_PASSWORD:
+ case KMSG_CRED_NEW_CREDS:
+ {
+ khui_new_creds * nc;
+ khui_new_creds_by_type * nct;
+ wchar_t wbuf[256];
+ size_t cbsize;
+
+ nc = (khui_new_creds *) vparam;
+
+ nct = PMALLOC(sizeof(*nct));
+ ZeroMemory(nct, sizeof(*nct));
+
+ nct->type = credtype_id_krb5;
+ nct->ordinal = 1;
+
+ LoadString(hResModule, IDS_KRB5_NC_NAME,
+ wbuf, ARRAYLENGTH(wbuf));
+ StringCbLength(wbuf, sizeof(wbuf), &cbsize);
+ cbsize += sizeof(wchar_t);
+
+ nct->name = PMALLOC(cbsize);
+ StringCbCopy(nct->name, cbsize, wbuf);
+
+ nct->h_module = hResModule;
+ nct->dlg_proc = k5_nc_dlg_proc;
+ if (nc->subtype == KMSG_CRED_PASSWORD)
+ nct->dlg_template = MAKEINTRESOURCE(IDD_NC_KRB5_PASSWORD);
+ else
+ nct->dlg_template = MAKEINTRESOURCE(IDD_NC_KRB5);
+
+ khui_cw_add_type(nc, nct);
+ }
+ break;
+
+ case KMSG_CRED_RENEW_CREDS:
+ {
+ khui_new_creds * nc;
+ khui_new_creds_by_type * nct;
+
+ nc = (khui_new_creds *) vparam;
+
+ nct = PMALLOC(sizeof(*nct));
+ ZeroMemory(nct, sizeof(*nct));
+
+ nct->type = credtype_id_krb5;
+
+ khui_cw_add_type(nc, nct);
+ }
+ break;
+
+ case KMSG_CRED_DIALOG_PRESTART:
+ {
+ khui_new_creds * nc;
+ khui_new_creds_by_type * nct;
+ k5_dlg_data * d;
+ HWND hwnd;
+ wchar_t * realms;
+ wchar_t * t;
+ wchar_t * defrealm;
+
+ nc = (khui_new_creds *) vparam;
+
+ khui_cw_find_type(nc, credtype_id_krb5, &nct);
+
+ if(!nct)
+ break;
+
+ hwnd = nct->hwnd_panel;
+ d = (k5_dlg_data *)(LONG_PTR)
+ GetWindowLongPtr(nct->hwnd_panel, DWLP_USER);
+
+ /* this can be NULL if the dialog was closed while the
+ plug-in thread was processing. */
+ if (d == NULL)
+ break;
+
+ if (!is_k5_identpro) {
+
+ /* enumerate all realms and place in realms combo box */
+ SendDlgItemMessage(hwnd, IDC_NCK5_REALM,
+ CB_RESETCONTENT,
+ 0, 0);
+
+ realms = khm_krb5_get_realm_list();
+ if(realms) {
+ for (t = realms; t && *t; t = multi_string_next(t)) {
+ SendDlgItemMessage(hwnd, IDC_NCK5_REALM,
+ CB_ADDSTRING,
+ 0, (LPARAM) t);
+ }
+ PFREE(realms);
+ }
+
+ /* and set the default realm */
+ defrealm = khm_krb5_get_default_realm();
+ if(defrealm) {
+ SendDlgItemMessage(hwnd, IDC_NCK5_REALM,
+ CB_SELECTSTRING,
+ (WPARAM) -1,
+ (LPARAM) defrealm);
+
+ SendDlgItemMessage(hwnd, IDC_NCK5_REALM,
+ WM_SETTEXT,
+ 0, (LPARAM) defrealm);
+ PFREE(defrealm);
+ }
+ } else { /* if krb5 is the identity provider */
+ HWND hw_realms;
+
+ /* in this case, the realm selection is done by the
+ identity provider prompts. */
+
+ hw_realms = GetDlgItem(hwnd, IDC_NCK5_REALM);
+#ifdef DEBUG
+ assert(hw_realms);
+#endif
+ EnableWindow(hw_realms, FALSE);
+ }
+
+ if (nc->subtype == KMSG_CRED_NEW_CREDS) {
+ k5_read_dlg_params(d, NULL);
+ }
+
+ PostMessage(hwnd, KHUI_WM_NC_NOTIFY,
+ MAKEWPARAM(0,WMNC_DIALOG_SETUP), 0);
+ }
+ break;
+
+ case KMSG_CRED_DIALOG_NEW_IDENTITY:
+ {
+ khui_new_creds * nc;
+ khui_new_creds_by_type * nct;
+ k5_dlg_data * d;
+
+ nc = (khui_new_creds *) vparam;
+
+ khui_cw_find_type(nc, credtype_id_krb5, &nct);
+ if (!nct)
+ break;
+
+ d = (k5_dlg_data *)(LONG_PTR)
+ GetWindowLongPtr(nct->hwnd_panel, DWLP_USER);
+
+ if (d == NULL)
+ break;
+
+ /* we only load the identity specific defaults if the user
+ hasn't changed the options */
+ khui_cw_lock_nc(nc);
+
+ /* ?: It might be better to not load identity defaults if
+ the user has already changed options in the dialog. */
+ if(/* !d->dirty && */ nc->n_identities > 0 &&
+ nc->subtype == KMSG_CRED_NEW_CREDS) {
+
+ k5_read_dlg_params(d, nc->identities[0]);
+
+ PostMessage(nct->hwnd_panel, KHUI_WM_NC_NOTIFY,
+ MAKEWPARAM(0,WMNC_DIALOG_SETUP), 0);
+ }
+
+ khui_cw_unlock_nc(nc);
+
+ /* reset the force-password-change flag if this is a new
+ identity. */
+ d->pwd_change = FALSE;
+ }
+
+ /* fallthrough */
+ case KMSG_CRED_DIALOG_NEW_OPTIONS:
+ {
+ khui_new_creds * nc;
+ khui_new_creds_by_type * nct;
+ k5_dlg_data * d;
+
+ nc = (khui_new_creds *) vparam;
+
+ khui_cw_find_type(nc, credtype_id_krb5, &nct);
+ if (!nct)
+ break;
+
+ d = (k5_dlg_data *)(LONG_PTR)
+ GetWindowLongPtr(nct->hwnd_panel, DWLP_USER);
+ if (d == NULL)
+ break;
+
+ if (nc->subtype == KMSG_CRED_PASSWORD) {
+ khm_size n_prompts = 0;
+
+ khui_cw_get_prompt_count(nc, &n_prompts);
+
+ if (nc->n_identities == 0) {
+ if (n_prompts)
+ khui_cw_clear_prompts(nc);
+ } else if (n_prompts != 3) {
+ wchar_t wbuf[KHUI_MAXCCH_BANNER];
+
+ khui_cw_clear_prompts(nc);
+
+ LoadString(hResModule, IDS_NC_PWD_BANNER,
+ wbuf, ARRAYLENGTH(wbuf));
+ khui_cw_begin_custom_prompts(nc, 3, NULL, wbuf);
+
+ LoadString(hResModule, IDS_NC_PWD_PWD,
+ wbuf, ARRAYLENGTH(wbuf));
+ khui_cw_add_prompt(nc, KHUI_NCPROMPT_TYPE_PASSWORD,
+ wbuf, NULL, KHUI_NCPROMPT_FLAG_HIDDEN);
+
+ LoadString(hResModule, IDS_NC_PWD_NPWD,
+ wbuf, ARRAYLENGTH(wbuf));
+ khui_cw_add_prompt(nc, KHUI_NCPROMPT_TYPE_NEW_PASSWORD,
+ wbuf, NULL, KHUI_NCPROMPT_FLAG_HIDDEN);
+
+ LoadString(hResModule, IDS_NC_PWD_NPWD_AGAIN,
+ wbuf, ARRAYLENGTH(wbuf));
+ khui_cw_add_prompt(nc, KHUI_NCPROMPT_TYPE_NEW_PASSWORD_AGAIN,
+ wbuf, NULL, KHUI_NCPROMPT_FLAG_HIDDEN);
+ }
+
+ return KHM_ERROR_SUCCESS;
+ }
+ /* else; nc->subtype == KMSG_CRED_NEW_CREDS */
+
+ assert(nc->subtype == KMSG_CRED_NEW_CREDS);
+
+ /* If we are forcing a password change, then we don't do
+ anything here. Note that if the identity changed, then
+ this field would have been reset, so we would proceed
+ as usual. */
+ if (d->pwd_change)
+ return KHM_ERROR_SUCCESS;
+
+#if 0
+ /* Clearing the prompts at this point is a bad idea since
+ the prompter depends on the prompts to know if this set
+ of prompts is the same as the new set and if so, use
+ the values entered in the old prompts as responses to
+ the new one. */
+ khui_cw_clear_prompts(nc);
+#endif
+
+ /* if the fiber is already in a kinit, cancel it */
+ if(g_fjob.state == FIBER_STATE_KINIT) {
+ g_fjob.command = FIBER_CMD_CANCEL;
+ SwitchToFiber(k5_kinit_fiber);
+ /* we get here when the cancel operation completes */
+ k5_free_kinit_job();
+ }
+
+ khui_cw_lock_nc(nc);
+
+ if(nc->n_identities > 0) {
+ khm_handle ident = nc->identities[0];
+
+ kcdb_identity_hold(ident);
+
+ k5_prep_kinit_job(nc);
+
+ /* after the switch to the fiber, the dialog will be
+ back in sync with the kinit thread. */
+ d->sync = TRUE;
+
+ khui_cw_unlock_nc(nc);
+
+ SwitchToFiber(k5_kinit_fiber);
+ /* we get here when the fiber switches back */
+ if(g_fjob.state == FIBER_STATE_NONE) {
+ wchar_t msg[KHUI_MAXCCH_BANNER];
+ khm_size cb;
+
+ /* Special case. If the users' password has
+ expired, we force a password change dialog on
+ top of the new credentials dialog using a set
+ of custom prompts, but only if we are the
+ identity provider. */
+ if (g_fjob.code == KRB5KDC_ERR_KEY_EXP &&
+ is_k5_identpro) {
+
+ k5_force_password_change(d);
+ goto done_with_bad_princ;
+
+ }
+
+ /* we can't possibly have succeeded without a
+ password */
+ if(g_fjob.code == KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN &&
+ is_k5_identpro) {
+ kcdb_identity_set_flags(ident,
+ KCDB_IDENT_FLAG_INVALID,
+ KCDB_IDENT_FLAG_INVALID);
+
+ khui_cw_clear_prompts(nc);
+ }
+
+ if (d->cred_message) {
+ PFREE(d->cred_message);
+ d->cred_message = NULL;
+ }
+
+ msg[0] = L'\0';
+
+ switch(g_fjob.code) {
+ case KRB5KDC_ERR_NAME_EXP:
+ /* principal expired */
+ LoadString(hResModule, IDS_K5ERR_NAME_EXPIRED,
+ msg, ARRAYLENGTH(msg));
+ break;
+
+ case KRB5KDC_ERR_KEY_EXP:
+ {
+ /* password needs changing. */
+ LoadString(hResModule, IDS_K5ERR_KEY_EXPIRED,
+ msg, ARRAYLENGTH(msg));
+ }
+ break;
+
+ default:
+ {
+ DWORD dw_dummy;
+ kherr_suggestion sug_dummy;
+ wchar_t fmt[KHUI_MAXCCH_BANNER];
+ wchar_t desc[KHUI_MAXCCH_BANNER];
+
+ LoadString(hResModule, IDS_K5ERR_FMT,
+ fmt, ARRAYLENGTH(fmt));
+
+ khm_err_describe(g_fjob.code,
+ desc,
+ sizeof(desc),
+ &dw_dummy,
+ &sug_dummy);
+
+ StringCbPrintf(msg, sizeof(msg), fmt, desc);
+ }
+ }
+
+ if (msg[0]) {
+ StringCbLength(msg, sizeof(msg), &cb);
+ cb += sizeof(wchar_t);
+
+ d->cred_message = PMALLOC(cb);
+ StringCbCopy(d->cred_message, cb, msg);
+ }
+
+ done_with_bad_princ:
+
+ k5_free_kinit_job();
+
+ if (is_k5_identpro)
+ kcdb_identity_set_flags(ident,
+ KCDB_IDENT_FLAG_UNKNOWN,
+ KCDB_IDENT_FLAG_UNKNOWN);
+
+
+ } else if(g_fjob.state == FIBER_STATE_KINIT) {
+ /* this is what we want. Leave the fiber there. */
+
+ if(is_k5_identpro)
+ kcdb_identity_set_flags(ident,
+ KCDB_IDENT_FLAG_VALID,
+ KCDB_IDENT_FLAG_VALID);
+ } else {
+ /* huh?? */
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ }
+
+ /* since the attributes of the identity have changed,
+ we should update the cred text as well */
+ kcdb_identity_release(ident);
+ khui_cw_lock_nc(nc);
+ PostMessage(nc->hwnd, KHUI_WM_NC_NOTIFY,
+ MAKEWPARAM(0, WMNC_UPDATE_CREDTEXT), 0);
+ } else {
+ khui_cw_unlock_nc(nc);
+ khui_cw_clear_prompts(nc);
+ khui_cw_lock_nc(nc);
+ }
+
+ khui_cw_unlock_nc(nc);
+ }
+ break;
+
+ case KMSG_CRED_PROCESS:
+ {
+ khui_new_creds * nc;
+ khui_new_creds_by_type * nct;
+ k5_dlg_data * d;
+
+ khm_int32 r = 0;
+
+ nc = (khui_new_creds *) vparam;
+
+ khui_cw_find_type(nc, credtype_id_krb5, &nct);
+
+ if(!nct)
+ break;
+
+ /* reset the null_password flag, just in case */
+ g_fjob.null_password = FALSE;
+
+ if (nc->subtype == KMSG_CRED_NEW_CREDS) {
+ d = (k5_dlg_data *) nct->aux;
+ if (d == NULL)
+ break;
+
+ if (d->pwd_change) {
+ /* we are forcing a password change */
+ goto change_password;
+ }
+
+ _begin_task(0);
+ _report_mr0(KHERR_NONE, MSG_CTX_INITAL_CREDS);
+ _describe();
+
+ if (g_fjob.state == FIBER_STATE_KINIT) {
+ if(nc->result == KHUI_NC_RESULT_CANCEL) {
+ g_fjob.command = FIBER_CMD_CANCEL;
+ SwitchToFiber(k5_kinit_fiber);
+
+ /* if we cancelled out, then we shouldn't care
+ about the return code. */
+#ifdef DEBUG
+ assert(g_fjob.state == FIBER_STATE_NONE);
+#endif
+ g_fjob.code = 0;
+
+ _reportf(L"Cancelling");
+ } else if (nc->result == KHUI_NC_RESULT_PROCESS) {
+ khui_cw_sync_prompt_values(nc);
+ g_fjob.command = FIBER_CMD_CONTINUE;
+ SwitchToFiber(k5_kinit_fiber);
+
+ /* We get back here once the fiber finishes
+ processing */
+ }
+#ifdef DEBUG
+ else {
+ assert(FALSE);
+ }
+#endif
+ } else {
+ /* we weren't in a KINIT state */
+ if (nc->result == KHUI_NC_RESULT_CANCEL) {
+ /* nothing to report */
+ g_fjob.code = 0;
+ } else if (nc->result == KHUI_NC_RESULT_PROCESS) {
+ /* g_fjob.code should have the result of the
+ last kinit attempt. We should leave it
+ as-is */
+ }
+#ifdef DEBUG
+ else {
+ /* unknown result */
+ assert(FALSE);
+ }
+#endif
+ }
+
+ /* special case: if there was no password entered, and
+ if there is a valid TGT we allow the credential
+ acquisition to go through */
+ if (g_fjob.state == FIBER_STATE_NONE &&
+ g_fjob.code &&
+ g_fjob.null_password &&
+
+ (nc->n_identities == 0 ||
+ nc->identities[0] == NULL ||
+ KHM_SUCCEEDED(kcdb_credset_find_filtered
+ (NULL,
+ -1,
+ k5_find_tgt_filter,
+ nc->identities[0],
+ NULL,
+ NULL)))) {
+ _reportf(L"No password entered, but a valid TGT exists. Continuing");
+ g_fjob.code = 0;
+ } else if (g_fjob.state == FIBER_STATE_NONE &&
+ g_fjob.code == 0 &&
+ nc->n_identities > 0 &&
+ nc->identities[0] != NULL) {
+
+ /* we had a password and we used it to get
+ tickets. We should reset the IMPORTED flag now
+ since the tickets are not imported. */
+
+ khm_krb5_set_identity_flags(nc->identities[0],
+ K5IDFLAG_IMPORTED,
+ 0);
+ }
+
+ if(g_fjob.code != 0) {
+ wchar_t tbuf[1024];
+ DWORD suggestion;
+ kherr_suggestion suggest_code;
+
+ khm_err_describe(g_fjob.code, tbuf, sizeof(tbuf),
+ &suggestion, &suggest_code);
+
+ _report_cs0(KHERR_ERROR, tbuf);
+ if (suggestion != 0)
+ _suggest_mr(suggestion, suggest_code);
+
+ _resolve();
+
+ r = KHUI_NC_RESPONSE_FAILED;
+
+ if (suggest_code == KHERR_SUGGEST_RETRY) {
+ r |= KHUI_NC_RESPONSE_NOEXIT |
+ KHUI_NC_RESPONSE_PENDING;
+ }
+
+#ifdef DEBUG
+ assert(g_fjob.state == FIBER_STATE_NONE);
+#endif
+
+ if (g_fjob.valid_principal &&
+ nc->n_identities > 0 &&
+ nc->identities[0]) {
+ /* the principal was valid, so we can go ahead
+ and update the LRU */
+ k5_update_LRU(nc->identities[0]);
+ }
+
+ } else if (nc->result == KHUI_NC_RESULT_PROCESS &&
+ g_fjob.state == FIBER_STATE_NONE) {
+ krb5_context ctx = NULL;
+
+ _reportf(L"Tickets successfully acquired");
+
+ r = KHUI_NC_RESPONSE_SUCCESS |
+ KHUI_NC_RESPONSE_EXIT;
+
+ /* if we successfully obtained credentials, we
+ should save the current settings in the
+ identity config space */
+
+ assert(nc->n_identities > 0);
+ assert(nc->identities[0]);
+
+ k5_write_dlg_params(d, nc->identities[0]);
+
+ /* We should also quickly refresh the credentials
+ so that the identity flags and ccache
+ properties reflect the current state of
+ affairs. This has to be done here so that
+ other credentials providers which depend on
+ Krb5 can properly find the initial creds to
+ obtain their respective creds. */
+
+ khm_krb5_list_tickets(&ctx);
+
+ if (nc->set_default) {
+ _reportf(L"Setting default identity");
+ kcdb_identity_set_default(nc->identities[0]);
+ }
+
+ /* If there is no default identity, then make this the default */
+ kcdb_identity_refresh(nc->identities[0]);
+ {
+ khm_handle tdefault = NULL;
+
+ if (KHM_SUCCEEDED(kcdb_identity_get_default(&tdefault))) {
+ kcdb_identity_release(tdefault);
+ } else {
+ _reportf(L"There was no default identity. Setting default");
+ kcdb_identity_set_default(nc->identities[0]);
+ }
+ }
+
+ /* and update the LRU */
+ k5_update_LRU(nc->identities[0]);
+
+ if (ctx != NULL)
+ pkrb5_free_context(ctx);
+ } else if (g_fjob.state == FIBER_STATE_NONE) {
+ /* the user cancelled the operation */
+ r = KHUI_NC_RESPONSE_EXIT |
+ KHUI_NC_RESPONSE_SUCCESS;
+ }
+
+ if(g_fjob.state == FIBER_STATE_NONE) {
+ khui_cw_set_response(nc, credtype_id_krb5, r);
+
+ if (r & KHUI_NC_RESPONSE_NOEXIT) {
+ /* if we are retrying the call, we should
+ restart the kinit fiber */
+#ifdef DEBUG
+ assert(r & KHUI_NC_RESPONSE_PENDING);
+#endif
+
+ k5_prep_kinit_job(nc);
+ SwitchToFiber(k5_kinit_fiber);
+ } else {
+ /* free up the fiber data fields. */
+ k5_free_kinit_job();
+ }
+ } else {
+ khui_cw_set_response(nc, credtype_id_krb5,
+ KHUI_NC_RESPONSE_NOEXIT |
+ KHUI_NC_RESPONSE_PENDING | r);
+ }
+
+ _end_task();
+ } else if (nc->subtype == KMSG_CRED_RENEW_CREDS) {
+
+ FILETIME ftidexp = {0,0};
+ FILETIME ftcurrent;
+ khm_size cb;
+
+ GetSystemTimeAsFileTime(&ftcurrent);
+
+ _begin_task(0);
+ _report_mr0(KHERR_NONE, MSG_CTX_RENEW_CREDS);
+ _describe();
+
+ if (nc->ctx.scope == KHUI_SCOPE_IDENT ||
+ (nc->ctx.scope == KHUI_SCOPE_CREDTYPE &&
+ nc->ctx.cred_type == credtype_id_krb5) ||
+ (nc->ctx.scope == KHUI_SCOPE_CRED &&
+ nc->ctx.cred_type == credtype_id_krb5)) {
+ int code;
+
+ if (nc->ctx.scope == KHUI_SCOPE_CRED &&
+ nc->ctx.cred != NULL) {
+
+ /* get the expiration time for the identity first. */
+ cb = sizeof(ftidexp);
+#ifdef DEBUG
+ assert(nc->ctx.identity != NULL);
+#endif
+ kcdb_identity_get_attr(nc->ctx.identity,
+ KCDB_ATTR_EXPIRE,
+ NULL,
+ &ftidexp,
+ &cb);
+
+ code = khm_krb5_renew_cred(nc->ctx.cred);
+
+ } else if (nc->ctx.scope == KHUI_SCOPE_IDENT &&
+ nc->ctx.identity != 0) {
+ /* get the current identity expiration time */
+ cb = sizeof(ftidexp);
+
+ kcdb_identity_get_attr(nc->ctx.identity,
+ KCDB_ATTR_EXPIRE,
+ NULL,
+ &ftidexp,
+ &cb);
+
+ code = khm_krb5_renew_ident(nc->ctx.identity);
+ } else {
+
+ _reportf(L"No identity specified. Can't renew Kerberos tickets");
+
+ code = 1; /* it just has to be non-zero */
+ }
+
+ if (code == 0) {
+ _reportf(L"Tickets successfully renewed");
+
+ khui_cw_set_response(nc, credtype_id_krb5,
+ KHUI_NC_RESPONSE_EXIT |
+ KHUI_NC_RESPONSE_SUCCESS);
+ } else if (nc->ctx.identity == 0) {
+
+ _report_mr0(KHERR_ERROR, MSG_ERR_NO_IDENTITY);
+
+ khui_cw_set_response(nc, credtype_id_krb5,
+ KHUI_NC_RESPONSE_EXIT |
+ KHUI_NC_RESPONSE_FAILED);
+ } else if (CompareFileTime(&ftcurrent, &ftidexp) < 0) {
+ wchar_t tbuf[1024];
+ DWORD suggestion;
+ kherr_suggestion sug_id;
+
+ /* if we failed to get new tickets, but the
+ identity is still valid, then we assume that
+ the current tickets are still good enough
+ for other credential types to obtain their
+ credentials. */
+
+ khm_err_describe(code, tbuf, sizeof(tbuf),
+ &suggestion, &sug_id);
+
+ _report_cs0(KHERR_WARNING, tbuf);
+ if (suggestion)
+ _suggest_mr(suggestion, sug_id);
+
+ _resolve();
+
+ khui_cw_set_response(nc, credtype_id_krb5,
+ KHUI_NC_RESPONSE_EXIT |
+ KHUI_NC_RESPONSE_SUCCESS);
+ } else {
+ wchar_t tbuf[1024];
+ DWORD suggestion;
+ kherr_suggestion sug_id;
+
+ khm_err_describe(code, tbuf, sizeof(tbuf),
+ &suggestion, &sug_id);
+
+ _report_cs0(KHERR_ERROR, tbuf);
+ if (suggestion)
+ _suggest_mr(suggestion, sug_id);
+
+ _resolve();
+
+ khui_cw_set_response(nc, credtype_id_krb5,
+ ((sug_id == KHERR_SUGGEST_RETRY)?KHUI_NC_RESPONSE_NOEXIT:KHUI_NC_RESPONSE_EXIT) |
+ KHUI_NC_RESPONSE_FAILED);
+ }
+ } else {
+ khui_cw_set_response(nc, credtype_id_krb5,
+ KHUI_NC_RESPONSE_EXIT |
+ KHUI_NC_RESPONSE_SUCCESS);
+ }
+
+ _end_task();
+ } else if (nc->subtype == KMSG_CRED_PASSWORD &&
+ nc->result == KHUI_NC_RESULT_PROCESS) {
+
+ change_password:
+ /* we jump here if there was a password change forced */
+
+ _begin_task(0);
+ _report_mr0(KHERR_NONE, MSG_CTX_PASSWD);
+ _describe();
+
+ khui_cw_lock_nc(nc);
+
+ if (nc->result == KHUI_NC_RESULT_CANCEL) {
+
+ khui_cw_set_response(nc, credtype_id_krb5,
+ KHUI_NC_RESPONSE_SUCCESS |
+ KHUI_NC_RESPONSE_EXIT);
+
+ } else if (nc->n_identities == 0 ||
+ nc->identities[0] == NULL) {
+ _report_mr0(KHERR_ERROR, MSG_PWD_NO_IDENTITY);
+ _suggest_mr(MSG_PWD_S_NO_IDENTITY, KHERR_SUGGEST_RETRY);
+
+ khui_cw_set_response(nc, credtype_id_krb5,
+ KHUI_NC_RESPONSE_FAILED |
+ KHUI_NC_RESPONSE_NOEXIT);
+
+ } else {
+ wchar_t widname[KCDB_IDENT_MAXCCH_NAME];
+ char idname[KCDB_IDENT_MAXCCH_NAME];
+ wchar_t wpwd[KHUI_MAXCCH_PASSWORD];
+ char pwd[KHUI_MAXCCH_PASSWORD];
+ wchar_t wnpwd[KHUI_MAXCCH_PASSWORD];
+ char npwd[KHUI_MAXCCH_PASSWORD];
+ wchar_t wnpwd2[KHUI_MAXCCH_PASSWORD];
+ wchar_t * wresult;
+ char * result;
+ khm_size n_prompts = 0;
+ khm_size cb;
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+ long code = 0;
+ khm_handle ident;
+
+ khui_cw_get_prompt_count(nc, &n_prompts);
+ assert(n_prompts == 3);
+
+ ident = nc->identities[0];
+ cb = sizeof(widname);
+ rv = kcdb_identity_get_name(ident, widname, &cb);
+ if (KHM_FAILED(rv)) {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ _report_mr0(KHERR_ERROR, MSG_PWD_UNKNOWN);
+ goto _pwd_exit;
+ }
+
+ cb = sizeof(wpwd);
+ rv = khui_cw_get_prompt_value(nc, 0, wpwd, &cb);
+ if (KHM_FAILED(rv)) {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ _report_mr0(KHERR_ERROR, MSG_PWD_UNKNOWN);
+ goto _pwd_exit;
+ }
+
+ cb = sizeof(wnpwd);
+ rv = khui_cw_get_prompt_value(nc, 1, wnpwd, &cb);
+ if (KHM_FAILED(rv)) {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ _report_mr0(KHERR_ERROR, MSG_PWD_UNKNOWN);
+ goto _pwd_exit;
+ }
+
+ cb = sizeof(wnpwd2);
+ rv = khui_cw_get_prompt_value(nc, 2, wnpwd2, &cb);
+ if (KHM_FAILED(rv)) {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ _report_mr0(KHERR_ERROR, MSG_PWD_UNKNOWN);
+ goto _pwd_exit;
+ }
+
+ if (wcscmp(wnpwd, wnpwd2)) {
+ rv = KHM_ERROR_INVALID_PARAM;
+ _report_mr0(KHERR_ERROR, MSG_PWD_NOT_SAME);
+ _suggest_mr(MSG_PWD_S_NOT_SAME, KHERR_SUGGEST_INTERACT);
+ goto _pwd_exit;
+ }
+
+ if (!wcscmp(wpwd, wnpwd)) {
+ rv = KHM_ERROR_INVALID_PARAM;
+ _report_mr0(KHERR_ERROR, MSG_PWD_SAME);
+ _suggest_mr(MSG_PWD_S_SAME, KHERR_SUGGEST_INTERACT);
+ goto _pwd_exit;
+ }
+
+ UnicodeStrToAnsi(idname, sizeof(idname), widname);
+ UnicodeStrToAnsi(pwd, sizeof(pwd), wpwd);
+ UnicodeStrToAnsi(npwd, sizeof(npwd), wnpwd);
+
+ result = NULL;
+
+ code = khm_krb5_changepwd(idname,
+ pwd,
+ npwd,
+ &result);
+
+ if (code)
+ rv = KHM_ERROR_UNKNOWN;
+ else {
+ khm_handle csp_idcfg = NULL;
+ krb5_context ctx = NULL;
+
+ /* we set a new password. now we need to get
+ initial credentials. */
+
+ d = (k5_dlg_data *) nct->aux;
+
+ if (d == NULL) {
+ rv = KHM_ERROR_UNKNOWN;
+ goto _pwd_exit;
+ }
+
+ if (nc->subtype == KMSG_CRED_PASSWORD) {
+ /* since this was just a password change,
+ we need to load new credentials options
+ from the configuration store. */
+
+ k5_read_dlg_params(d, nc->identities[0]);
+ }
+
+ /* the password change phase is now done */
+ d->pwd_change = FALSE;
+
+#ifdef DEBUG
+ _reportf(L"Calling khm_krb5_kinit()");
+#endif
+ code = khm_krb5_kinit(NULL, /* context (create one) */
+ idname, /* principal_name */
+ npwd, /* new password */
+ NULL, /* ccache name (figure out the identity cc)*/
+ (krb5_deltat) d->tc_lifetime.current,
+ d->forwardable,
+ d->proxiable,
+ (krb5_deltat)((d->renewable)?d->tc_renew.current:0),
+ d->addressless, /* addressless */
+ d->publicIP, /* public IP */
+ NULL, /* prompter */
+ NULL /* prompter data */);
+
+ if (code) {
+ rv = KHM_ERROR_UNKNOWN;
+ goto _pwd_exit;
+ }
+
+ /* save the settings that we used for
+ obtaining the ticket. */
+ if (nc->subtype == KMSG_CRED_NEW_CREDS) {
+
+ k5_write_dlg_params(d, nc->identities[0]);
+
+ /* and then update the LRU too */
+ k5_update_LRU(nc->identities[0]);
+ }
+
+ /* and do a quick refresh of the krb5 tickets
+ so that other plug-ins that depend on krb5
+ can look up tickets inside NetIDMgr */
+ khm_krb5_list_tickets(&ctx);
+
+ /* if there was no default identity, we make
+ this one the default. */
+ kcdb_identity_refresh(nc->identities[0]);
+ {
+ khm_handle tdefault = NULL;
+
+ if (KHM_SUCCEEDED(kcdb_identity_get_default(&tdefault))) {
+ kcdb_identity_release(tdefault);
+ } else {
+ _reportf(L"There was no default identity. Setting defualt");
+ kcdb_identity_set_default(nc->identities[0]);
+ }
+ }
+
+ if (ctx != NULL)
+ pkrb5_free_context(ctx);
+
+ if (nc->subtype == KMSG_CRED_PASSWORD) {
+ /* if we obtained new credentials as a
+ result of successfully changing the
+ password, we also schedule an identity
+ renewal for this identity. This allows
+ the other credential types to obtain
+ credentials for this identity. */
+ khui_action_context ctx;
+
+ _reportf(L"Scheduling renewal of [%s] after password change",
+ widname);
+
+ khui_context_create(&ctx,
+ KHUI_SCOPE_IDENT,
+ nc->identities[0],
+ KCDB_CREDTYPE_INVALID,
+ NULL);
+ khui_action_trigger(KHUI_ACTION_RENEW_CRED,
+ &ctx);
+
+ khui_context_release(&ctx);
+ }
+ }
+
+ /* result is only set when code != 0 */
+ if (code && result) {
+ size_t len;
+
+ StringCchLengthA(result, KHERR_MAXCCH_STRING,
+ &len);
+ wresult = PMALLOC((len + 1) * sizeof(wchar_t));
+#ifdef DEBUG
+ assert(wresult);
+#endif
+ AnsiStrToUnicode(wresult, (len + 1) * sizeof(wchar_t),
+ result);
+
+ _report_cs1(KHERR_ERROR, L"%1!s!", _cstr(wresult));
+ _resolve();
+
+ PFREE(result);
+ PFREE(wresult);
+
+ /* we don't need to report anything more */
+ code = 0;
+ }
+
+ _pwd_exit:
+ if (KHM_FAILED(rv)) {
+ if (code) {
+ wchar_t tbuf[1024];
+ DWORD suggestion;
+ kherr_suggestion sug_id;
+
+ khm_err_describe(code, tbuf, sizeof(tbuf),
+ &suggestion, &sug_id);
+ _report_cs0(KHERR_ERROR, tbuf);
+
+ if (suggestion)
+ _suggest_mr(suggestion, sug_id);
+
+ _resolve();
+ }
+
+ khui_cw_set_response(nc, credtype_id_krb5,
+ KHUI_NC_RESPONSE_NOEXIT|
+ KHUI_NC_RESPONSE_FAILED);
+ } else {
+ khui_cw_set_response(nc, credtype_id_krb5,
+ KHUI_NC_RESPONSE_SUCCESS |
+ KHUI_NC_RESPONSE_EXIT);
+ }
+ }
+
+ khui_cw_unlock_nc(nc);
+
+ _end_task();
+ } /* KMSG_CRED_PASSWORD */
+ }
+ break;
+
+ case KMSG_CRED_END:
+ {
+ khui_new_creds * nc;
+ khui_new_creds_by_type * nct;
+
+ nc = (khui_new_creds *) vparam;
+ khui_cw_find_type(nc, credtype_id_krb5, &nct);
+
+ if(!nct)
+ break;
+
+ khui_cw_del_type(nc, credtype_id_krb5);
+
+ if (nct->name)
+ PFREE(nct->name);
+ if (nct->credtext)
+ PFREE(nct->credtext);
+
+ PFREE(nct);
+
+ k5_free_kinit_job();
+ }
+ break;
+
+ case KMSG_CRED_IMPORT:
+ {
+ khm_int32 t = 0;
+
+#ifdef DEBUG
+ assert(csp_params);
+#endif
+ khc_read_int32(csp_params, L"MsLsaImport", &t);
+
+ if (t != K5_LSAIMPORT_NEVER) {
+ krb5_context ctx = NULL;
+ khm_handle id_default = NULL;
+ khm_handle id_imported = NULL;
+ BOOL imported;
+
+ imported = khm_krb5_ms2mit(NULL, (t == K5_LSAIMPORT_MATCH), TRUE,
+ &id_imported);
+ if (imported) {
+ khm_krb5_list_tickets(&ctx);
+
+ if (ctx)
+ pkrb5_free_context(ctx);
+
+ kcdb_identity_refresh(id_imported);
+
+ if (KHM_SUCCEEDED(kcdb_identity_get_default(&id_default))) {
+ kcdb_identity_release(id_default);
+ id_default = NULL;
+ } else {
+ _reportf(L"There was no default identity. Setting default");
+ kcdb_identity_set_default(id_imported);
+ }
+
+ /* and update the LRU */
+ k5_update_LRU(id_imported);
+ }
+
+ if (id_imported)
+ kcdb_identity_release(id_imported);
+ }
+ }
+ break;
+ }
+
+ return rv;
+}
diff --git a/src/windows/identity/plugins/krb5/krb5plugin.c b/src/windows/identity/plugins/krb5/krb5plugin.c
index bb481e0fbe..61331f3844 100644
--- a/src/windows/identity/plugins/krb5/krb5plugin.c
+++ b/src/windows/identity/plugins/krb5/krb5plugin.c
@@ -1,265 +1,265 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<krbcred.h>
-#include<kherror.h>
-#include<khmsgtypes.h>
-#include<commctrl.h>
-#include<strsafe.h>
-#include<krb5.h>
-
-#ifdef DEBUG
-#include<assert.h>
-#endif
-
-khm_int32 credtype_id_krb5 = KCDB_CREDTYPE_INVALID;
-khm_boolean krb5_initialized = FALSE;
-khm_handle krb5_credset = NULL;
-
-khm_handle k5_sub = NULL;
-
-LPVOID k5_main_fiber = NULL;
-LPVOID k5_kinit_fiber = NULL;
-
-VOID CALLBACK k5_kinit_fiber_proc(PVOID lpParameter);
-
-krb5_context k5_identpro_ctx = NULL;
-
-/* The system message handler.
-
- Runs in the context of the plugin thread */
-khm_int32 KHMAPI
-k5_msg_system(khm_int32 msg_type, khm_int32 msg_subtype,
- khm_ui_4 uparam, void * vparam)
-{
- khm_int32 rv = KHM_ERROR_SUCCESS;
-
- switch(msg_subtype) {
- case KMSG_SYSTEM_INIT:
- {
- kcdb_credtype ct;
- wchar_t buf[KCDB_MAXCCH_SHORT_DESC];
- size_t cbsize;
-
- /* perform critical registrations and initialization
- stuff */
- ZeroMemory(&ct, sizeof(ct));
- ct.id = KCDB_CREDTYPE_AUTO;
- ct.name = KRB5_CREDTYPE_NAME;
-
- if(LoadString(hResModule, IDS_KRB5_SHORT_DESC,
- buf, ARRAYLENGTH(buf))) {
- StringCbLength(buf, KCDB_MAXCB_SHORT_DESC, &cbsize);
- cbsize += sizeof(wchar_t);
- ct.short_desc = PMALLOC(cbsize);
- StringCbCopy(ct.short_desc, cbsize, buf);
- }
-
- /* even though ideally we should be setting limits
- based KCDB_MAXCB_LONG_DESC, our long description
- actually fits nicely in KCDB_MAXCB_SHORT_DESC */
- if(LoadString(hResModule, IDS_KRB5_LONG_DESC,
- buf, ARRAYLENGTH(buf))) {
- StringCbLength(buf, KCDB_MAXCB_SHORT_DESC, &cbsize);
- cbsize += sizeof(wchar_t);
- ct.long_desc = PMALLOC(cbsize);
- StringCbCopy(ct.long_desc, cbsize, buf);
- }
-
- ct.icon = NULL; /* TODO: set a proper icon */
-
- kmq_create_subscription(k5_msg_callback, &ct.sub);
-
- ct.is_equal = khm_krb5_creds_is_equal;
-
- rv = kcdb_credtype_register(&ct, &credtype_id_krb5);
-
- if(KHM_SUCCEEDED(rv))
- rv = kcdb_credset_create(&krb5_credset);
-
- if(ct.short_desc)
- PFREE(ct.short_desc);
-
- if(ct.long_desc)
- PFREE(ct.long_desc);
-
- if(KHM_SUCCEEDED(rv)) {
- krb5_context ctx = NULL;
-
- krb5_initialized = TRUE;
-
- /* now convert this thread to a fiber and create a
- separate fiber to do kinit stuff */
- k5_main_fiber = ConvertThreadToFiber(NULL);
- k5_kinit_fiber = CreateFiber(0,k5_kinit_fiber_proc,NULL);
-
- ZeroMemory(&g_fjob, sizeof(g_fjob));
-
- kmq_create_subscription(k5_msg_callback, &k5_sub);
-
- k5_register_config_panels();
-
- khm_krb5_list_tickets(&ctx);
-
- if(ctx != NULL)
- pkrb5_free_context(ctx);
- }
- }
- break;
-
- case KMSG_SYSTEM_EXIT:
-
- k5_unregister_config_panels();
-
- if(credtype_id_krb5 >= 0) {
- /* basically just unregister the credential type */
- kcdb_credtype_unregister(credtype_id_krb5);
-
- /* kcdb knows how to deal with bad handles */
- kcdb_credset_delete(krb5_credset);
- krb5_credset = NULL;
- }
-
- if(k5_main_fiber != NULL) {
- if (k5_kinit_fiber) {
-#ifdef DEBUG
- assert(k5_kinit_fiber != GetCurrentFiber());
-#endif
-#ifdef CLEANUP_FIBERS_ON_EXIT
- DeleteFiber(k5_kinit_fiber);
- CloseHandle(k5_kinit_fiber);
-#endif
- k5_kinit_fiber = NULL;
- }
-
- k5_main_fiber = NULL;
- }
-
- if(k5_sub != NULL) {
- kmq_delete_subscription(k5_sub);
- k5_sub = NULL;
- }
-
- break;
- }
-
- return rv;
-}
-
-khm_int32 KHMAPI
-k5_msg_kcdb(khm_int32 msg_type, khm_int32 msg_subtype,
- khm_ui_4 uparam, void * vparam)
-{
- khm_int32 rv = KHM_ERROR_SUCCESS;
-
- switch(msg_subtype) {
- case KMSG_KCDB_IDENT:
- if (uparam == KCDB_OP_DELCONFIG) {
- k5_remove_from_LRU((khm_handle) vparam);
- }
- break;
- }
-
- return rv;
-}
-
-
-/* Handler for CRED type messages
-
- Runs in the context of the Krb5 plugin
-*/
-khm_int32 KHMAPI
-k5_msg_cred(khm_int32 msg_type, khm_int32 msg_subtype,
- khm_ui_4 uparam, void * vparam)
-{
- khm_int32 rv = KHM_ERROR_SUCCESS;
-
- switch(msg_subtype) {
- case KMSG_CRED_REFRESH:
- {
- krb5_context ctx = NULL;
-
- khm_krb5_list_tickets(&ctx);
-
- if(ctx != NULL)
- pkrb5_free_context(ctx);
- }
- break;
-
- case KMSG_CRED_DESTROY_CREDS:
- {
- khui_action_context * ctx;
-
- ctx = (khui_action_context *) vparam;
-
- if (ctx->credset) {
- _begin_task(0);
- _report_mr0(KHERR_INFO, MSG_ERR_CTX_DESTROY_CREDS);
- _describe();
-
- khm_krb5_destroy_by_credset(ctx->credset);
-
- _end_task();
- }
- }
- break;
-
- case KMSG_CRED_PP_BEGIN:
- k5_pp_begin((khui_property_sheet *) vparam);
- break;
-
- case KMSG_CRED_PP_END:
- k5_pp_end((khui_property_sheet *) vparam);
- break;
-
- default:
- if(IS_CRED_ACQ_MSG(msg_subtype))
- return k5_msg_cred_dialog(msg_type, msg_subtype,
- uparam, vparam);
- }
-
- return rv;
-}
-
-/* The main message handler. We don't do much here, except delegate
- to other message handlers
-
- Runs in the context of the Krb5 plugin
-*/
-khm_int32 KHMAPI
-k5_msg_callback(khm_int32 msg_type, khm_int32 msg_subtype,
- khm_ui_4 uparam, void * vparam)
-{
- switch(msg_type) {
- case KMSG_SYSTEM:
- return k5_msg_system(msg_type, msg_subtype, uparam, vparam);
- case KMSG_CRED:
- return k5_msg_cred(msg_type, msg_subtype, uparam, vparam);
- case KMSG_KCDB:
- return k5_msg_kcdb(msg_type, msg_subtype, uparam, vparam);
- }
- return KHM_ERROR_SUCCESS;
-}
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<krbcred.h>
+#include<kherror.h>
+#include<khmsgtypes.h>
+#include<commctrl.h>
+#include<strsafe.h>
+#include<krb5.h>
+
+#ifdef DEBUG
+#include<assert.h>
+#endif
+
+khm_int32 credtype_id_krb5 = KCDB_CREDTYPE_INVALID;
+khm_boolean krb5_initialized = FALSE;
+khm_handle krb5_credset = NULL;
+
+khm_handle k5_sub = NULL;
+
+LPVOID k5_main_fiber = NULL;
+LPVOID k5_kinit_fiber = NULL;
+
+VOID CALLBACK k5_kinit_fiber_proc(PVOID lpParameter);
+
+krb5_context k5_identpro_ctx = NULL;
+
+/* The system message handler.
+
+ Runs in the context of the plugin thread */
+khm_int32 KHMAPI
+k5_msg_system(khm_int32 msg_type, khm_int32 msg_subtype,
+ khm_ui_4 uparam, void * vparam)
+{
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+
+ switch(msg_subtype) {
+ case KMSG_SYSTEM_INIT:
+ {
+ kcdb_credtype ct;
+ wchar_t buf[KCDB_MAXCCH_SHORT_DESC];
+ size_t cbsize;
+
+ /* perform critical registrations and initialization
+ stuff */
+ ZeroMemory(&ct, sizeof(ct));
+ ct.id = KCDB_CREDTYPE_AUTO;
+ ct.name = KRB5_CREDTYPE_NAME;
+
+ if(LoadString(hResModule, IDS_KRB5_SHORT_DESC,
+ buf, ARRAYLENGTH(buf))) {
+ StringCbLength(buf, KCDB_MAXCB_SHORT_DESC, &cbsize);
+ cbsize += sizeof(wchar_t);
+ ct.short_desc = PMALLOC(cbsize);
+ StringCbCopy(ct.short_desc, cbsize, buf);
+ }
+
+ /* even though ideally we should be setting limits
+ based KCDB_MAXCB_LONG_DESC, our long description
+ actually fits nicely in KCDB_MAXCB_SHORT_DESC */
+ if(LoadString(hResModule, IDS_KRB5_LONG_DESC,
+ buf, ARRAYLENGTH(buf))) {
+ StringCbLength(buf, KCDB_MAXCB_SHORT_DESC, &cbsize);
+ cbsize += sizeof(wchar_t);
+ ct.long_desc = PMALLOC(cbsize);
+ StringCbCopy(ct.long_desc, cbsize, buf);
+ }
+
+ ct.icon = NULL; /* TODO: set a proper icon */
+
+ kmq_create_subscription(k5_msg_callback, &ct.sub);
+
+ ct.is_equal = khm_krb5_creds_is_equal;
+
+ rv = kcdb_credtype_register(&ct, &credtype_id_krb5);
+
+ if(KHM_SUCCEEDED(rv))
+ rv = kcdb_credset_create(&krb5_credset);
+
+ if(ct.short_desc)
+ PFREE(ct.short_desc);
+
+ if(ct.long_desc)
+ PFREE(ct.long_desc);
+
+ if(KHM_SUCCEEDED(rv)) {
+ krb5_context ctx = NULL;
+
+ krb5_initialized = TRUE;
+
+ /* now convert this thread to a fiber and create a
+ separate fiber to do kinit stuff */
+ k5_main_fiber = ConvertThreadToFiber(NULL);
+ k5_kinit_fiber = CreateFiber(0,k5_kinit_fiber_proc,NULL);
+
+ ZeroMemory(&g_fjob, sizeof(g_fjob));
+
+ kmq_create_subscription(k5_msg_callback, &k5_sub);
+
+ k5_register_config_panels();
+
+ khm_krb5_list_tickets(&ctx);
+
+ if(ctx != NULL)
+ pkrb5_free_context(ctx);
+ }
+ }
+ break;
+
+ case KMSG_SYSTEM_EXIT:
+
+ k5_unregister_config_panels();
+
+ if(credtype_id_krb5 >= 0) {
+ /* basically just unregister the credential type */
+ kcdb_credtype_unregister(credtype_id_krb5);
+
+ /* kcdb knows how to deal with bad handles */
+ kcdb_credset_delete(krb5_credset);
+ krb5_credset = NULL;
+ }
+
+ if(k5_main_fiber != NULL) {
+ if (k5_kinit_fiber) {
+#ifdef DEBUG
+ assert(k5_kinit_fiber != GetCurrentFiber());
+#endif
+#ifdef CLEANUP_FIBERS_ON_EXIT
+ DeleteFiber(k5_kinit_fiber);
+ CloseHandle(k5_kinit_fiber);
+#endif
+ k5_kinit_fiber = NULL;
+ }
+
+ k5_main_fiber = NULL;
+ }
+
+ if(k5_sub != NULL) {
+ kmq_delete_subscription(k5_sub);
+ k5_sub = NULL;
+ }
+
+ break;
+ }
+
+ return rv;
+}
+
+khm_int32 KHMAPI
+k5_msg_kcdb(khm_int32 msg_type, khm_int32 msg_subtype,
+ khm_ui_4 uparam, void * vparam)
+{
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+
+ switch(msg_subtype) {
+ case KMSG_KCDB_IDENT:
+ if (uparam == KCDB_OP_DELCONFIG) {
+ k5_remove_from_LRU((khm_handle) vparam);
+ }
+ break;
+ }
+
+ return rv;
+}
+
+
+/* Handler for CRED type messages
+
+ Runs in the context of the Krb5 plugin
+*/
+khm_int32 KHMAPI
+k5_msg_cred(khm_int32 msg_type, khm_int32 msg_subtype,
+ khm_ui_4 uparam, void * vparam)
+{
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+
+ switch(msg_subtype) {
+ case KMSG_CRED_REFRESH:
+ {
+ krb5_context ctx = NULL;
+
+ khm_krb5_list_tickets(&ctx);
+
+ if(ctx != NULL)
+ pkrb5_free_context(ctx);
+ }
+ break;
+
+ case KMSG_CRED_DESTROY_CREDS:
+ {
+ khui_action_context * ctx;
+
+ ctx = (khui_action_context *) vparam;
+
+ if (ctx->credset) {
+ _begin_task(0);
+ _report_mr0(KHERR_INFO, MSG_ERR_CTX_DESTROY_CREDS);
+ _describe();
+
+ khm_krb5_destroy_by_credset(ctx->credset);
+
+ _end_task();
+ }
+ }
+ break;
+
+ case KMSG_CRED_PP_BEGIN:
+ k5_pp_begin((khui_property_sheet *) vparam);
+ break;
+
+ case KMSG_CRED_PP_END:
+ k5_pp_end((khui_property_sheet *) vparam);
+ break;
+
+ default:
+ if(IS_CRED_ACQ_MSG(msg_subtype))
+ return k5_msg_cred_dialog(msg_type, msg_subtype,
+ uparam, vparam);
+ }
+
+ return rv;
+}
+
+/* The main message handler. We don't do much here, except delegate
+ to other message handlers
+
+ Runs in the context of the Krb5 plugin
+*/
+khm_int32 KHMAPI
+k5_msg_callback(khm_int32 msg_type, khm_int32 msg_subtype,
+ khm_ui_4 uparam, void * vparam)
+{
+ switch(msg_type) {
+ case KMSG_SYSTEM:
+ return k5_msg_system(msg_type, msg_subtype, uparam, vparam);
+ case KMSG_CRED:
+ return k5_msg_cred(msg_type, msg_subtype, uparam, vparam);
+ case KMSG_KCDB:
+ return k5_msg_kcdb(msg_type, msg_subtype, uparam, vparam);
+ }
+ return KHM_ERROR_SUCCESS;
+}
diff --git a/src/windows/identity/plugins/krb5/krb5props.c b/src/windows/identity/plugins/krb5/krb5props.c
index 0d8d27276e..312b576fd1 100644
--- a/src/windows/identity/plugins/krb5/krb5props.c
+++ b/src/windows/identity/plugins/krb5/krb5props.c
@@ -1,176 +1,176 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<krbcred.h>
-#include<kherror.h>
-#include<khmsgtypes.h>
-#include<commctrl.h>
-#include<strsafe.h>
-#include<krb5.h>
-#ifdef DEBUG
-#include<assert.h>
-#endif
-
-/* Property page
-
- Runs in the context of the UI thread.
- */
-INT_PTR CALLBACK krb5_pp_proc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam
- )
-{
- switch(uMsg) {
- case WM_INITDIALOG:
- {
- khui_property_sheet * s;
- PROPSHEETPAGE * p;
- wchar_t buf[512];
- wchar_t unavailable[64];
- khm_size cbsize;
- khm_int32 rv;
- khm_int32 tflags;
-
- p = (PROPSHEETPAGE *) lParam;
- s = (khui_property_sheet *) p->lParam;
-
-#pragma warning(push)
-#pragma warning(disable: 4244)
- SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) s);
-#pragma warning(pop)
-
- LoadString(hResModule, IDS_UNAVAILABLE,
- unavailable, ARRAYLENGTH(unavailable));
-
- if(s->cred) {
- cbsize = sizeof(buf);
- kcdb_cred_get_name(s->cred, buf, &cbsize);
- SetDlgItemText(hwnd, IDC_PPK5_NAME, buf);
-
- cbsize = sizeof(buf);
- rv = kcdb_cred_get_attr_string(s->cred,
- KCDB_ATTR_ISSUE,
- buf, &cbsize, 0);
- if (KHM_SUCCEEDED(rv))
- SetDlgItemText(hwnd, IDC_PPK5_ISSUE, buf);
- else
- SetDlgItemText(hwnd, IDC_PPK5_ISSUE, unavailable);
-
- cbsize = sizeof(buf);
- rv = kcdb_cred_get_attr_string(s->cred,
- KCDB_ATTR_EXPIRE,
- buf, &cbsize, 0);
- if (KHM_SUCCEEDED(rv))
- SetDlgItemText(hwnd, IDC_PPK5_VALID, buf);
- else
- SetDlgItemText(hwnd, IDC_PPK5_VALID, unavailable);
-
- cbsize = sizeof(buf);
- rv = kcdb_cred_get_attr_string(s->cred,
- KCDB_ATTR_RENEW_EXPIRE,
- buf, &cbsize, 0);
- if (KHM_SUCCEEDED(rv))
- SetDlgItemText(hwnd, IDC_PPK5_RENEW, buf);
- else
- SetDlgItemText(hwnd, IDC_PPK5_RENEW, unavailable);
-
- tflags = 0;
- cbsize = sizeof(tflags);
- rv = kcdb_cred_get_attr(s->cred,
- attr_id_krb5_flags,
- NULL,
- &tflags,
- &cbsize);
- if (KHM_SUCCEEDED(rv)) {
-
-#define ADDBITFLAG(f,s) \
- if (tflags & f) { \
- LoadString(hResModule, s, buf, ARRAYLENGTH(buf)); \
- SendDlgItemMessage(hwnd, IDC_PPK5_FLAGS, LB_ADDSTRING, 0, (LPARAM) buf); \
- }
-
- ADDBITFLAG(TKT_FLG_FORWARDABLE, IDS_FLG_FORWARDABLE);
- ADDBITFLAG(TKT_FLG_FORWARDED, IDS_FLG_FORWARDED);
- ADDBITFLAG(TKT_FLG_PROXIABLE, IDS_FLG_PROXIABLE);
- ADDBITFLAG(TKT_FLG_PROXY, IDS_FLG_PROXY);
- ADDBITFLAG(TKT_FLG_MAY_POSTDATE, IDS_FLG_MAY_POSTDATE);
- ADDBITFLAG(TKT_FLG_POSTDATED, IDS_FLG_POSTDATED);
- ADDBITFLAG(TKT_FLG_INVALID, IDS_FLG_INVALID);
- ADDBITFLAG(TKT_FLG_RENEWABLE, IDS_FLG_RENEWABLE);
- ADDBITFLAG(TKT_FLG_INITIAL, IDS_FLG_INITIAL);
- ADDBITFLAG(TKT_FLG_PRE_AUTH, IDS_FLG_PRE_AUTH);
- ADDBITFLAG(TKT_FLG_HW_AUTH, IDS_FLG_HW_AUTH);
- ADDBITFLAG(TKT_FLG_TRANSIT_POLICY_CHECKED, IDS_FLG_TRANSIT_POL);
- ADDBITFLAG(TKT_FLG_OK_AS_DELEGATE, IDS_FLG_OK_DELEGATE);
- ADDBITFLAG(TKT_FLG_ANONYMOUS, IDS_FLG_ANONYMOUS);
-
-#undef ADDBITFLAG
-
- }
- } else {
-#ifdef DEBUG
- assert(FALSE);
-#endif
- }
- }
- return FALSE;
- }
-
- return FALSE;
-}
-
-void k5_pp_begin(khui_property_sheet * s)
-{
- PROPSHEETPAGE *p;
-
- if(s->credtype == credtype_id_krb5 &&
- s->cred) {
- p = PMALLOC(sizeof(*p));
- ZeroMemory(p, sizeof(*p));
-
- p->dwSize = sizeof(*p);
- p->dwFlags = 0;
- p->hInstance = hResModule;
- p->pszTemplate = MAKEINTRESOURCE(IDD_PP_KRB5C);
- p->pfnDlgProc = krb5_pp_proc;
- p->lParam = (LPARAM) s;
- khui_ps_add_page(s, credtype_id_krb5, 0, p, NULL);
- }
-}
-
-void k5_pp_end(khui_property_sheet * s)
-{
- khui_property_page * p = NULL;
-
- khui_ps_find_page(s, credtype_id_krb5, &p);
- if(p) {
- if(p->p_page)
- PFREE(p->p_page);
- p->p_page = NULL;
- }
-}
-
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<krbcred.h>
+#include<kherror.h>
+#include<khmsgtypes.h>
+#include<commctrl.h>
+#include<strsafe.h>
+#include<krb5.h>
+#ifdef DEBUG
+#include<assert.h>
+#endif
+
+/* Property page
+
+ Runs in the context of the UI thread.
+ */
+INT_PTR CALLBACK krb5_pp_proc(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam
+ )
+{
+ switch(uMsg) {
+ case WM_INITDIALOG:
+ {
+ khui_property_sheet * s;
+ PROPSHEETPAGE * p;
+ wchar_t buf[512];
+ wchar_t unavailable[64];
+ khm_size cbsize;
+ khm_int32 rv;
+ khm_int32 tflags;
+
+ p = (PROPSHEETPAGE *) lParam;
+ s = (khui_property_sheet *) p->lParam;
+
+#pragma warning(push)
+#pragma warning(disable: 4244)
+ SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) s);
+#pragma warning(pop)
+
+ LoadString(hResModule, IDS_UNAVAILABLE,
+ unavailable, ARRAYLENGTH(unavailable));
+
+ if(s->cred) {
+ cbsize = sizeof(buf);
+ kcdb_cred_get_name(s->cred, buf, &cbsize);
+ SetDlgItemText(hwnd, IDC_PPK5_NAME, buf);
+
+ cbsize = sizeof(buf);
+ rv = kcdb_cred_get_attr_string(s->cred,
+ KCDB_ATTR_ISSUE,
+ buf, &cbsize, 0);
+ if (KHM_SUCCEEDED(rv))
+ SetDlgItemText(hwnd, IDC_PPK5_ISSUE, buf);
+ else
+ SetDlgItemText(hwnd, IDC_PPK5_ISSUE, unavailable);
+
+ cbsize = sizeof(buf);
+ rv = kcdb_cred_get_attr_string(s->cred,
+ KCDB_ATTR_EXPIRE,
+ buf, &cbsize, 0);
+ if (KHM_SUCCEEDED(rv))
+ SetDlgItemText(hwnd, IDC_PPK5_VALID, buf);
+ else
+ SetDlgItemText(hwnd, IDC_PPK5_VALID, unavailable);
+
+ cbsize = sizeof(buf);
+ rv = kcdb_cred_get_attr_string(s->cred,
+ KCDB_ATTR_RENEW_EXPIRE,
+ buf, &cbsize, 0);
+ if (KHM_SUCCEEDED(rv))
+ SetDlgItemText(hwnd, IDC_PPK5_RENEW, buf);
+ else
+ SetDlgItemText(hwnd, IDC_PPK5_RENEW, unavailable);
+
+ tflags = 0;
+ cbsize = sizeof(tflags);
+ rv = kcdb_cred_get_attr(s->cred,
+ attr_id_krb5_flags,
+ NULL,
+ &tflags,
+ &cbsize);
+ if (KHM_SUCCEEDED(rv)) {
+
+#define ADDBITFLAG(f,s) \
+ if (tflags & f) { \
+ LoadString(hResModule, s, buf, ARRAYLENGTH(buf)); \
+ SendDlgItemMessage(hwnd, IDC_PPK5_FLAGS, LB_ADDSTRING, 0, (LPARAM) buf); \
+ }
+
+ ADDBITFLAG(TKT_FLG_FORWARDABLE, IDS_FLG_FORWARDABLE);
+ ADDBITFLAG(TKT_FLG_FORWARDED, IDS_FLG_FORWARDED);
+ ADDBITFLAG(TKT_FLG_PROXIABLE, IDS_FLG_PROXIABLE);
+ ADDBITFLAG(TKT_FLG_PROXY, IDS_FLG_PROXY);
+ ADDBITFLAG(TKT_FLG_MAY_POSTDATE, IDS_FLG_MAY_POSTDATE);
+ ADDBITFLAG(TKT_FLG_POSTDATED, IDS_FLG_POSTDATED);
+ ADDBITFLAG(TKT_FLG_INVALID, IDS_FLG_INVALID);
+ ADDBITFLAG(TKT_FLG_RENEWABLE, IDS_FLG_RENEWABLE);
+ ADDBITFLAG(TKT_FLG_INITIAL, IDS_FLG_INITIAL);
+ ADDBITFLAG(TKT_FLG_PRE_AUTH, IDS_FLG_PRE_AUTH);
+ ADDBITFLAG(TKT_FLG_HW_AUTH, IDS_FLG_HW_AUTH);
+ ADDBITFLAG(TKT_FLG_TRANSIT_POLICY_CHECKED, IDS_FLG_TRANSIT_POL);
+ ADDBITFLAG(TKT_FLG_OK_AS_DELEGATE, IDS_FLG_OK_DELEGATE);
+ ADDBITFLAG(TKT_FLG_ANONYMOUS, IDS_FLG_ANONYMOUS);
+
+#undef ADDBITFLAG
+
+ }
+ } else {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ }
+ }
+ return FALSE;
+ }
+
+ return FALSE;
+}
+
+void k5_pp_begin(khui_property_sheet * s)
+{
+ PROPSHEETPAGE *p;
+
+ if(s->credtype == credtype_id_krb5 &&
+ s->cred) {
+ p = PMALLOC(sizeof(*p));
+ ZeroMemory(p, sizeof(*p));
+
+ p->dwSize = sizeof(*p);
+ p->dwFlags = 0;
+ p->hInstance = hResModule;
+ p->pszTemplate = MAKEINTRESOURCE(IDD_PP_KRB5C);
+ p->pfnDlgProc = krb5_pp_proc;
+ p->lParam = (LPARAM) s;
+ khui_ps_add_page(s, credtype_id_krb5, 0, p, NULL);
+ }
+}
+
+void k5_pp_end(khui_property_sheet * s)
+{
+ khui_property_page * p = NULL;
+
+ khui_ps_find_page(s, credtype_id_krb5, &p);
+ if(p) {
+ if(p->p_page)
+ PFREE(p->p_page);
+ p->p_page = NULL;
+ }
+}
+
diff --git a/src/windows/identity/plugins/krb5/krbcred.h b/src/windows/identity/plugins/krb5/krbcred.h
index d552fd0c8e..0048f7185e 100644
--- a/src/windows/identity/plugins/krb5/krbcred.h
+++ b/src/windows/identity/plugins/krb5/krbcred.h
@@ -1,244 +1,244 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#ifndef __KHIMAIRA_KRBAFSCRED_H
-#define __KHIMAIRA_KRBAFSCRED_H
-
-#include<windows.h>
-
-/* While we generally pull resources out of hResModule, the message
- strings for all the languages are kept in the main DLL. */
-#define KHERR_HMODULE hInstance
-#define KHERR_FACILITY k5_facility
-#define KHERR_FACILITY_ID 64
-
-#include<netidmgr.h>
-
-#include<krb5funcs.h>
-#include<krb5common.h>
-#include<errorfuncs.h>
-#include<dynimport.h>
-
-#include<langres.h>
-#include<datarep.h>
-#include<krb5_msgs.h>
-
-typedef enum tag_k5_lsa_import {
- K5_LSAIMPORT_NEVER = 0,
- K5_LSAIMPORT_ALWAYS = 1,
- K5_LSAIMPORT_MATCH = 2, /* only when the principal name matches */
-} k5_lsa_import;
-
-#define TYPENAME_ENCTYPE L"EncType"
-#define TYPENAME_ADDR_LIST L"AddrList"
-#define TYPENAME_KRB5_FLAGS L"Krb5Flags"
-#define TYPENAME_KRB5_PRINC L"Krb5Principal"
-#define TYPENAME_KVNO L"Kvno"
-
-#define ATTRNAME_KEY_ENCTYPE L"KeyEncType"
-#define ATTRNAME_TKT_ENCTYPE L"TktEncType"
-#define ATTRNAME_ADDR_LIST L"AddrList"
-#define ATTRNAME_KRB5_FLAGS L"Krb5Flags"
-#define ATTRNAME_KRB5_CCNAME L"Krb5CCName"
-#define ATTRNAME_KVNO L"Kvno"
-#define ATTRNAME_KRB5_IDFLAGS L"Krb5IDFlags"
-
-/* Flag bits for Krb5IDFlags property */
-
-/* identity was imported from MSLSA: */
-#define K5IDFLAG_IMPORTED 0x00000001
-
-void init_krb();
-void exit_krb();
-KHMEXP khm_int32 KHMAPI init_module(kmm_module h_module);
-KHMEXP khm_int32 KHMAPI exit_module(kmm_module h_module);
-
-/* globals */
-extern kmm_module h_khModule;
-extern HMODULE hResModule;
-extern HINSTANCE hInstance;
-extern const wchar_t * k5_facility;
-
-extern khm_int32 type_id_enctype;
-extern khm_int32 type_id_addr_list;
-extern khm_int32 type_id_krb5_flags;
-extern khm_int32 type_id_krb5_princ;
-extern khm_int32 type_id_kvno;
-
-extern BOOL type_regd_krb5_princ;
-
-extern khm_int32 attr_id_key_enctype;
-extern khm_int32 attr_id_tkt_enctype;
-extern khm_int32 attr_id_addr_list;
-extern khm_int32 attr_id_krb5_flags;
-extern khm_int32 attr_id_krb5_ccname;
-extern khm_int32 attr_id_kvno;
-extern khm_int32 attr_id_krb5_idflags;
-
-extern khm_ui_4 k5_commctl_version;
-
-#define IS_COMMCTL6() (k5_commctl_version >= 0x60000)
-
-/* Configuration spaces */
-#define CSNAME_KRB5CRED L"Krb5Cred"
-#define CSNAME_PARAMS L"Parameters"
-#define CSNAME_PROMPTCACHE L"PromptCache"
-#define CSNAME_REALMS L"Realms"
-
-/* plugin constants */
-#define KRB5_PLUGIN_NAME L"Krb5Cred"
-#define KRB5_IDENTPRO_NAME L"Krb5Ident"
-
-#define KRB5_CREDTYPE_NAME L"Krb5Cred"
-
-/* limits */
-/* maximum number of characters in a realm name */
-#define K5_MAXCCH_REALM 256
-
-/* maximum number of characters in a host name */
-#define K5_MAXCCH_HOST 128
-
-/* maximum number of KDC's per realm */
-#define K5_MAX_KDC 64
-
-/* maximum number of domains that map to a realm */
-#define K5_MAX_DOMAIN_MAPPINGS 32
-
-extern khm_handle csp_plugins;
-extern khm_handle csp_krbcred;
-extern khm_handle csp_params;
-
-extern kconf_schema schema_krbconfig[];
-
-/* other globals */
-extern khm_int32 credtype_id_krb5;
-
-extern khm_boolean krb5_initialized;
-
-extern khm_handle krb5_credset;
-
-extern khm_handle k5_sub;
-
-extern krb5_context k5_identpro_ctx;
-
-extern BOOL is_k5_identpro;
-
-/* plugin callbacks */
-khm_int32 KHMAPI k5_msg_callback(khm_int32 msg_type, khm_int32 msg_subtype, khm_ui_4 uparam, void * vparam);
-khm_int32 KHMAPI k5_ident_callback(khm_int32 msg_type, khm_int32 msg_subtype, khm_ui_4 uparam, void * vparam);
-
-/* kinit fiber */
-typedef struct _fiber_job_t {
- int command;
-
- khui_new_creds * nc;
- khui_new_creds_by_type * nct;
- HWND dialog;
-
- khm_handle identity;
- char * principal;
- char * password;
- char * ccache;
- krb5_deltat lifetime;
- DWORD forwardable;
- DWORD proxiable;
- DWORD renewable;
- krb5_deltat renew_life;
- DWORD addressless;
- DWORD publicIP;
-
- int code;
- int state;
- int prompt_set;
-
- BOOL null_password;
- BOOL valid_principal;
- BOOL retry_if_valid_principal;
-} fiber_job;
-
-extern fiber_job g_fjob; /* global fiber job object */
-
-#define FIBER_CMD_KINIT 1
-#define FIBER_CMD_CANCEL 2
-#define FIBER_CMD_CONTINUE 3
-
-#define FIBER_STATE_NONE 0
-#define FIBER_STATE_KINIT 1
-#define FIBER_STATE_RETRY_KINIT 2
-
-#define K5_SET_CRED_MSG WMNC_USER
-
-void
-k5_pp_begin(khui_property_sheet * s);
-
-void
-k5_pp_end(khui_property_sheet * s);
-
-khm_int32 KHMAPI
-k5_msg_cred_dialog(khm_int32 msg_type,
- khm_int32 msg_subtype,
- khm_ui_4 uparam,
- void * vparam);
-
-khm_int32 KHMAPI
-k5_msg_ident(khm_int32 msg_type,
- khm_int32 msg_subtype,
- khm_ui_4 uparam,
- void * vparam);
-
-khm_int32
-k5_remove_from_LRU(khm_handle identity);
-
-int
-k5_get_realm_from_nc(khui_new_creds * nc,
- wchar_t * buf,
- khm_size cch_buf);
-
-void
-k5_register_config_panels(void);
-
-void
-k5_unregister_config_panels(void);
-
-INT_PTR CALLBACK
-k5_ccconfig_dlgproc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam);
-
-INT_PTR CALLBACK
-k5_id_tab_dlgproc(HWND hwndDlg,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam);
-
-INT_PTR CALLBACK
-k5_ids_tab_dlgproc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam);
-
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __KHIMAIRA_KRBAFSCRED_H
+#define __KHIMAIRA_KRBAFSCRED_H
+
+#include<windows.h>
+
+/* While we generally pull resources out of hResModule, the message
+ strings for all the languages are kept in the main DLL. */
+#define KHERR_HMODULE hInstance
+#define KHERR_FACILITY k5_facility
+#define KHERR_FACILITY_ID 64
+
+#include<netidmgr.h>
+
+#include<krb5funcs.h>
+#include<krb5common.h>
+#include<errorfuncs.h>
+#include<dynimport.h>
+
+#include<langres.h>
+#include<datarep.h>
+#include<krb5_msgs.h>
+
+typedef enum tag_k5_lsa_import {
+ K5_LSAIMPORT_NEVER = 0,
+ K5_LSAIMPORT_ALWAYS = 1,
+ K5_LSAIMPORT_MATCH = 2, /* only when the principal name matches */
+} k5_lsa_import;
+
+#define TYPENAME_ENCTYPE L"EncType"
+#define TYPENAME_ADDR_LIST L"AddrList"
+#define TYPENAME_KRB5_FLAGS L"Krb5Flags"
+#define TYPENAME_KRB5_PRINC L"Krb5Principal"
+#define TYPENAME_KVNO L"Kvno"
+
+#define ATTRNAME_KEY_ENCTYPE L"KeyEncType"
+#define ATTRNAME_TKT_ENCTYPE L"TktEncType"
+#define ATTRNAME_ADDR_LIST L"AddrList"
+#define ATTRNAME_KRB5_FLAGS L"Krb5Flags"
+#define ATTRNAME_KRB5_CCNAME L"Krb5CCName"
+#define ATTRNAME_KVNO L"Kvno"
+#define ATTRNAME_KRB5_IDFLAGS L"Krb5IDFlags"
+
+/* Flag bits for Krb5IDFlags property */
+
+/* identity was imported from MSLSA: */
+#define K5IDFLAG_IMPORTED 0x00000001
+
+void init_krb();
+void exit_krb();
+KHMEXP khm_int32 KHMAPI init_module(kmm_module h_module);
+KHMEXP khm_int32 KHMAPI exit_module(kmm_module h_module);
+
+/* globals */
+extern kmm_module h_khModule;
+extern HMODULE hResModule;
+extern HINSTANCE hInstance;
+extern const wchar_t * k5_facility;
+
+extern khm_int32 type_id_enctype;
+extern khm_int32 type_id_addr_list;
+extern khm_int32 type_id_krb5_flags;
+extern khm_int32 type_id_krb5_princ;
+extern khm_int32 type_id_kvno;
+
+extern BOOL type_regd_krb5_princ;
+
+extern khm_int32 attr_id_key_enctype;
+extern khm_int32 attr_id_tkt_enctype;
+extern khm_int32 attr_id_addr_list;
+extern khm_int32 attr_id_krb5_flags;
+extern khm_int32 attr_id_krb5_ccname;
+extern khm_int32 attr_id_kvno;
+extern khm_int32 attr_id_krb5_idflags;
+
+extern khm_ui_4 k5_commctl_version;
+
+#define IS_COMMCTL6() (k5_commctl_version >= 0x60000)
+
+/* Configuration spaces */
+#define CSNAME_KRB5CRED L"Krb5Cred"
+#define CSNAME_PARAMS L"Parameters"
+#define CSNAME_PROMPTCACHE L"PromptCache"
+#define CSNAME_REALMS L"Realms"
+
+/* plugin constants */
+#define KRB5_PLUGIN_NAME L"Krb5Cred"
+#define KRB5_IDENTPRO_NAME L"Krb5Ident"
+
+#define KRB5_CREDTYPE_NAME L"Krb5Cred"
+
+/* limits */
+/* maximum number of characters in a realm name */
+#define K5_MAXCCH_REALM 256
+
+/* maximum number of characters in a host name */
+#define K5_MAXCCH_HOST 128
+
+/* maximum number of KDC's per realm */
+#define K5_MAX_KDC 64
+
+/* maximum number of domains that map to a realm */
+#define K5_MAX_DOMAIN_MAPPINGS 32
+
+extern khm_handle csp_plugins;
+extern khm_handle csp_krbcred;
+extern khm_handle csp_params;
+
+extern kconf_schema schema_krbconfig[];
+
+/* other globals */
+extern khm_int32 credtype_id_krb5;
+
+extern khm_boolean krb5_initialized;
+
+extern khm_handle krb5_credset;
+
+extern khm_handle k5_sub;
+
+extern krb5_context k5_identpro_ctx;
+
+extern BOOL is_k5_identpro;
+
+/* plugin callbacks */
+khm_int32 KHMAPI k5_msg_callback(khm_int32 msg_type, khm_int32 msg_subtype, khm_ui_4 uparam, void * vparam);
+khm_int32 KHMAPI k5_ident_callback(khm_int32 msg_type, khm_int32 msg_subtype, khm_ui_4 uparam, void * vparam);
+
+/* kinit fiber */
+typedef struct _fiber_job_t {
+ int command;
+
+ khui_new_creds * nc;
+ khui_new_creds_by_type * nct;
+ HWND dialog;
+
+ khm_handle identity;
+ char * principal;
+ char * password;
+ char * ccache;
+ krb5_deltat lifetime;
+ DWORD forwardable;
+ DWORD proxiable;
+ DWORD renewable;
+ krb5_deltat renew_life;
+ DWORD addressless;
+ DWORD publicIP;
+
+ int code;
+ int state;
+ int prompt_set;
+
+ BOOL null_password;
+ BOOL valid_principal;
+ BOOL retry_if_valid_principal;
+} fiber_job;
+
+extern fiber_job g_fjob; /* global fiber job object */
+
+#define FIBER_CMD_KINIT 1
+#define FIBER_CMD_CANCEL 2
+#define FIBER_CMD_CONTINUE 3
+
+#define FIBER_STATE_NONE 0
+#define FIBER_STATE_KINIT 1
+#define FIBER_STATE_RETRY_KINIT 2
+
+#define K5_SET_CRED_MSG WMNC_USER
+
+void
+k5_pp_begin(khui_property_sheet * s);
+
+void
+k5_pp_end(khui_property_sheet * s);
+
+khm_int32 KHMAPI
+k5_msg_cred_dialog(khm_int32 msg_type,
+ khm_int32 msg_subtype,
+ khm_ui_4 uparam,
+ void * vparam);
+
+khm_int32 KHMAPI
+k5_msg_ident(khm_int32 msg_type,
+ khm_int32 msg_subtype,
+ khm_ui_4 uparam,
+ void * vparam);
+
+khm_int32
+k5_remove_from_LRU(khm_handle identity);
+
+int
+k5_get_realm_from_nc(khui_new_creds * nc,
+ wchar_t * buf,
+ khm_size cch_buf);
+
+void
+k5_register_config_panels(void);
+
+void
+k5_unregister_config_panels(void);
+
+INT_PTR CALLBACK
+k5_ccconfig_dlgproc(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam);
+
+INT_PTR CALLBACK
+k5_id_tab_dlgproc(HWND hwndDlg,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam);
+
+INT_PTR CALLBACK
+k5_ids_tab_dlgproc(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam);
+
+#endif
diff --git a/src/windows/identity/plugins/krb5/langres.h b/src/windows/identity/plugins/krb5/langres.h
index 0e62ecda1d..117754b3e8 100644
--- a/src/windows/identity/plugins/krb5/langres.h
+++ b/src/windows/identity/plugins/krb5/langres.h
@@ -1,216 +1,216 @@
-//{{NO_DEPENDENCIES}}
-// Microsoft Visual C++ generated include file.
-// Used by C:\work\pismere\athena\auth\krb5\src\windows\identity\plugins\krb5\lang\en_us\langres.rc
-//
-#define IDS_UNK_ADDR_FMT 101
-#define IDD_NC_KRB5 102
-#define IDS_KRB5_CREDTEXT_0 102
-#define IDS_KRB5_CCNAME_SHORT_DESC 103
-#define IDS_KEY_ENCTYPE_SHORT_DESC 104
-#define IDD_CONFIG 104
-#define IDS_TKT_ENCTYPE_SHORT_DESC 105
-#define IDD_CFG_REALMS 105
-#define IDS_KEY_ENCTYPE_LONG_DESC 106
-#define IDD_CFG_IDS_TAB 106
-#define IDS_TKT_ENCTYPE_LONG_DESC 107
-#define IDD_PP_KRB5C 107
-#define IDS_ADDR_LIST_SHORT_DESC 108
-#define IDD_PP_KRB5 108
-#define IDS_ADDR_LIST_LONG_DESC 109
-#define IDD_CFG_ID_TAB 109
-#define IDS_ETYPE_NULL 110
-#define IDD_NC_KRB5_PASSWORD 110
-#define IDS_ETYPE_DES_CBC_CRC 111
-#define IDD_CFG_CACHES 111
-#define IDS_ETYPE_DES_CBC_MD4 112
-#define IDI_PLUGIN 112
-#define IDS_ETYPE_DES_CBC_MD5 113
-#define IDI_DELETED 113
-#define IDS_ETYPE_DES_CBC_RAW 114
-#define IDI_NEW 114
-#define IDS_ETYPE_DES3_CBC_SHA 115
-#define IDI_NORMAL 115
-#define IDS_ETYPE_DES3_CBC_RAW 116
-#define IDI_MODIFIED 116
-#define IDS_ETYPE_DES_HMAC_SHA1 117
-#define IDS_ETYPE_DES3_CBC_SHA1 118
-#define IDS_ETYPE_AES128_CTS_HMAC_SHA1_96 119
-#define IDS_ETYPE_AES256_CTS_HMAC_SHA1_96 120
-#define IDS_ETYPE_ARCFOUR_HMAC 121
-#define IDS_ETYPE_ARCFOUR_HMAC_EXP 122
-#define IDS_ETYPE_UNKNOWN 123
-#define IDS_ETYPE_LOCAL_DES3_HMAC_SHA1 124
-#define IDS_ETYPE_LOCAL_RC4_MD4 125
-#define IDS_KRB5_SHORT_DESC 126
-#define IDS_KRB5_LONG_DESC 127
-#define IDS_KRB4_SHORT_DESC 128
-#define IDS_KRB4_LONG_DESC 129
-#define IDS_KRB5_FLAGS_SHORT_DESC 130
-#define IDS_RENEW_TILL_SHORT_DESC 131
-#define IDS_RENEW_TILL_LONG_DESC 132
-#define IDS_RENEW_FOR_SHORT_DESC 133
-#define IDS_RENEW_FOR_LONG_DESC 134
-#define IDS_KRB5_CCNAME_LONG_DESC 135
-#define IDS_NC_USERNAME 136
-#define IDS_NC_REALM 137
-#define IDS_KRB5_WARNING 138
-#define IDS_K5ERR_NAME_EXPIRED 139
-#define IDS_K5ERR_KEY_EXPIRED 140
-#define IDS_KRB5_WARN_FMT 141
-#define IDS_K5ERR_FMT 142
-#define IDS_K5CFG_SHORT_DESC 143
-#define IDS_K5CFG_LONG_DESC 144
-#define IDS_K5RLM_SHORT_DESC 145
-#define IDS_K5RLM_LONG_DESC 146
-#define IDS_K5CFG_IDS_SHORT_DESC 147
-#define IDS_K5CFG_IDS_LONG_DESC 148
-#define IDS_K5CFG_ID_SHORT_DESC 149
-#define IDS_K5CFG_ID_LONG_DESC 150
-#define IDS_PLUGIN_DESC 151
-#define IDS_NC_PWD_BANNER 152
-#define IDS_NC_PWD_PWD 153
-#define IDS_NC_PWD_NPWD 154
-#define IDS_NC_PWD_NPWD_AGAIN 155
-#define IDS_KRB5_CREDTEXT_P0 156
-#define IDS_K5CFG_IMPORT_OPTIONS 157
-#define IDS_IDENTPRO_DESC 158
-#define IDS_K5CCC_SHORT_DESC 159
-#define IDS_K5CCC_LONG_DESC 160
-#define IDS_CFG_FCTITLE 161
-#define IDS_CFG_FCN_WARNING 162
-#define IDS_CFG_FCN_W_NOTFOUND 163
-#define IDS_CFG_FCN_W_RELATIVE 164
-#define IDS_CFG_FCOPENTITLE 165
-#define IDS_UNAVAILABLE 166
-#define IDS_FLG_FORWARDABLE 167
-#define IDS_FLG_FORWARDED 168
-#define IDS_FLG_PROXIABLE 169
-#define IDS_FLG_PROXY 170
-#define IDS_FLG_MAY_POSTDATE 171
-#define IDS_FLG_POSTDATED 172
-#define IDS_FLG_INVALID 173
-#define IDS_FLG_RENEWABLE 174
-#define IDS_FLG_INITIAL 175
-#define IDS_FLG_PRE_AUTH 176
-#define IDS_FLG_HW_AUTH 177
-#define IDS_FLG_TRANSIT_POL 178
-#define IDS_FLG_OK_DELEGATE 179
-#define IDS_FLG_ANONYMOUS 180
-#define IDS_K5ERR_CANTWRITEPROFILE 181
-#define IDS_K5ERR_PROFNOWRITE 182
-#define IDS_K5ERR_PROFUSETEMP 183
-#define IDS_K5ERR_PROFSUGGEST 184
-#define IDS_CFG_RE_REALMS 185
-#define IDS_CFG_RE_KDCS 186
-#define IDS_CFG_RE_DMAPS 187
-#define IDS_CFG_RE_KDCS_R 188
-#define IDS_CFG_RE_DMAPS_R 189
-#define IDS_CFG_RE_HEAD_SVR 190
-#define IDS_CFG_RE_HEAD_ADMIN 191
-#define IDS_CFG_RE_HEAD_MASTER 192
-#define IDS_CFG_RE_HEAD_DOMAIN 193
-#define IDS_CFG_RE_NEWREALM 194
-#define IDS_YES 195
-#define IDS_NO 196
-#define IDS_CFG_RE_NEWSERVER 197
-#define IDS_CFG_RE_NEWDMAP 198
-#define IDS_KRB5_NC_NAME 199
-#define IDS_NCERR_IDENT_TOO_LONG 200
-#define IDS_NCERR_IDENT_INVALID 201
-#define IDS_NCERR_IDENT_UNKNOWN 202
-#define IDS_CFG_RE_ARNUT 203
-#define IDS_CFG_RE_ARNUM 204
-#define IDS_CFG_RE_ASNUT 205
-#define IDS_CFG_RE_ASNUM 206
-#define IDS_CFG_RE_DMNUT 207
-#define IDS_CFG_RE_DMNUM 208
-#define IDS_CFG_RE_MNR 209
-#define IDS_CFG_RE_MDR 210
-#define IDS_CFG_RE_MNK 211
-#define IDS_CFG_RE_MDK 212
-#define IDS_CFG_RE_MAK 213
-#define IDS_CFG_RE_MMK 214
-#define IDS_CFG_RE_MND 215
-#define IDS_CFG_RE_MDD 216
-#define IDS_KVNO_SHORT_DESC 217
-#define IDS_KVNO_LONG_DESC 218
-#define IDC_NCK5_RENEWABLE 1002
-#define IDC_NCK5_FORWARDABLE 1004
-#define IDC_NCK5_REALM 1005
-#define IDC_NCK5_ADD_REALMS 1006
-#define IDC_NCK5_LIFETIME_EDIT 1008
-#define IDC_NCK5_RENEW_EDIT 1009
-#define IDC_PPK5_CRENEW 1014
-#define IDC_PPK5_CFORWARD 1015
-#define IDC_PPK5_CPROXY 1016
-#define IDC_PPK5_NAME 1017
-#define IDC_PPK5_ISSUE 1018
-#define IDC_PPK5_VALID 1019
-#define IDC_PPK5_RENEW 1020
-#define IDC_CHECK2 1022
-#define IDC_CHECK4 1024
-#define IDC_PPK5_LIFETIME 1024
-#define IDC_CHECK5 1025
-#define IDC_CFG_LBL_REALM 1025
-#define IDC_CFG_DEFREALM 1026
-#define IDC_CFG_LBL_CFGFILE 1029
-#define IDC_CFG_CFGFILE 1030
-#define IDC_CFG_WINGRP 1031
-#define IDC_LBL_IMPORT 1032
-#define IDC_CFG_IMPORT 1033
-#define IDC_CFG_LBL_HOSTNAME 1034
-#define IDC_CFG_HOSTNAME 1035
-#define IDC_CFG_LBL_DOMAIN 1036
-#define IDC_CFG_DOMAIN 1037
-#define IDC_CFG_CREATECONFIG 1038
-#define IDC_CFG_BROWSE 1039
-#define IDC_CFG_CFGFILEGRP 1040
-#define IDC_CFG_CFGREALMS 1041
-#define IDC_CFG_BROWSE2 1042
-#define IDC_CFG_REALMS 1044
-#define IDC_CFG_DOMAINGRP 1045
-#define IDC_CFG_SERVERSGRP 1046
-#define IDC_LIST3 1047
-#define IDC_CFG_KDC 1047
-#define IDC_LIST4 1048
-#define IDC_CFG_DMAP 1048
-#define IDC_CFG_LBL_DEFLIFE 1049
-#define IDC_CFG_DEFLIFE 1050
-#define IDC_CFG_LBL_DEFRLIFE 1051
-#define IDC_CFG_DEFRLIFE 1052
-#define IDC_CFG_LIFEGRP 1053
-#define IDC_CFG_LRNG_MIN 1054
-#define IDC_CFG_LRNG_MAX 1055
-#define IDC_CFG_RLRNG_MIN 1056
-#define IDC_CFG_RLRNG_MAX 1057
-#define IDC_CFG_CCACHE 1058
-#define IDC_CFG_FCGRP 1059
-#define IDC_CFG_FCLIST 1060
-#define IDC_CFG_FCNAME 1062
-#define IDC_CFG_ADD 1064
-#define IDC_CFG_REMOVE 1065
-#define IDC_CFG_INCAPI 1066
-#define IDC_CFG_INCMSLSA 1067
-#define IDC_PPK5_FLAGS 1072
-#define IDC_CFG_INCREALMS 1073
-#define IDC_NCK5_ADDRESS 1074
-#define IDC_IPADDRESS1 1075
-#define IDC_NCK5_PUBLICIP 1075
-#define IDC_CFG_PUBLICIP 1075
-#define IDC_CFG_RENEW 1076
-#define IDC_CHECK3 1077
-#define IDC_CFG_ADDRESSLESS 1077
-#define IDC_CFG_FORWARD 1078
-#define IDC_CHECK1 1079
-#define ID_FOO_BAR 40001
-
-// Next default values for new objects
-//
-#ifdef APSTUDIO_INVOKED
-#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE 219
-#define _APS_NEXT_COMMAND_VALUE 40002
-#define _APS_NEXT_CONTROL_VALUE 1080
-#define _APS_NEXT_SYMED_VALUE 101
-#endif
-#endif
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by C:\work\pismere\athena\auth\krb5\src\windows\identity\plugins\krb5\lang\en_us\langres.rc
+//
+#define IDS_UNK_ADDR_FMT 101
+#define IDD_NC_KRB5 102
+#define IDS_KRB5_CREDTEXT_0 102
+#define IDS_KRB5_CCNAME_SHORT_DESC 103
+#define IDS_KEY_ENCTYPE_SHORT_DESC 104
+#define IDD_CONFIG 104
+#define IDS_TKT_ENCTYPE_SHORT_DESC 105
+#define IDD_CFG_REALMS 105
+#define IDS_KEY_ENCTYPE_LONG_DESC 106
+#define IDD_CFG_IDS_TAB 106
+#define IDS_TKT_ENCTYPE_LONG_DESC 107
+#define IDD_PP_KRB5C 107
+#define IDS_ADDR_LIST_SHORT_DESC 108
+#define IDD_PP_KRB5 108
+#define IDS_ADDR_LIST_LONG_DESC 109
+#define IDD_CFG_ID_TAB 109
+#define IDS_ETYPE_NULL 110
+#define IDD_NC_KRB5_PASSWORD 110
+#define IDS_ETYPE_DES_CBC_CRC 111
+#define IDD_CFG_CACHES 111
+#define IDS_ETYPE_DES_CBC_MD4 112
+#define IDI_PLUGIN 112
+#define IDS_ETYPE_DES_CBC_MD5 113
+#define IDI_DELETED 113
+#define IDS_ETYPE_DES_CBC_RAW 114
+#define IDI_NEW 114
+#define IDS_ETYPE_DES3_CBC_SHA 115
+#define IDI_NORMAL 115
+#define IDS_ETYPE_DES3_CBC_RAW 116
+#define IDI_MODIFIED 116
+#define IDS_ETYPE_DES_HMAC_SHA1 117
+#define IDS_ETYPE_DES3_CBC_SHA1 118
+#define IDS_ETYPE_AES128_CTS_HMAC_SHA1_96 119
+#define IDS_ETYPE_AES256_CTS_HMAC_SHA1_96 120
+#define IDS_ETYPE_ARCFOUR_HMAC 121
+#define IDS_ETYPE_ARCFOUR_HMAC_EXP 122
+#define IDS_ETYPE_UNKNOWN 123
+#define IDS_ETYPE_LOCAL_DES3_HMAC_SHA1 124
+#define IDS_ETYPE_LOCAL_RC4_MD4 125
+#define IDS_KRB5_SHORT_DESC 126
+#define IDS_KRB5_LONG_DESC 127
+#define IDS_KRB4_SHORT_DESC 128
+#define IDS_KRB4_LONG_DESC 129
+#define IDS_KRB5_FLAGS_SHORT_DESC 130
+#define IDS_RENEW_TILL_SHORT_DESC 131
+#define IDS_RENEW_TILL_LONG_DESC 132
+#define IDS_RENEW_FOR_SHORT_DESC 133
+#define IDS_RENEW_FOR_LONG_DESC 134
+#define IDS_KRB5_CCNAME_LONG_DESC 135
+#define IDS_NC_USERNAME 136
+#define IDS_NC_REALM 137
+#define IDS_KRB5_WARNING 138
+#define IDS_K5ERR_NAME_EXPIRED 139
+#define IDS_K5ERR_KEY_EXPIRED 140
+#define IDS_KRB5_WARN_FMT 141
+#define IDS_K5ERR_FMT 142
+#define IDS_K5CFG_SHORT_DESC 143
+#define IDS_K5CFG_LONG_DESC 144
+#define IDS_K5RLM_SHORT_DESC 145
+#define IDS_K5RLM_LONG_DESC 146
+#define IDS_K5CFG_IDS_SHORT_DESC 147
+#define IDS_K5CFG_IDS_LONG_DESC 148
+#define IDS_K5CFG_ID_SHORT_DESC 149
+#define IDS_K5CFG_ID_LONG_DESC 150
+#define IDS_PLUGIN_DESC 151
+#define IDS_NC_PWD_BANNER 152
+#define IDS_NC_PWD_PWD 153
+#define IDS_NC_PWD_NPWD 154
+#define IDS_NC_PWD_NPWD_AGAIN 155
+#define IDS_KRB5_CREDTEXT_P0 156
+#define IDS_K5CFG_IMPORT_OPTIONS 157
+#define IDS_IDENTPRO_DESC 158
+#define IDS_K5CCC_SHORT_DESC 159
+#define IDS_K5CCC_LONG_DESC 160
+#define IDS_CFG_FCTITLE 161
+#define IDS_CFG_FCN_WARNING 162
+#define IDS_CFG_FCN_W_NOTFOUND 163
+#define IDS_CFG_FCN_W_RELATIVE 164
+#define IDS_CFG_FCOPENTITLE 165
+#define IDS_UNAVAILABLE 166
+#define IDS_FLG_FORWARDABLE 167
+#define IDS_FLG_FORWARDED 168
+#define IDS_FLG_PROXIABLE 169
+#define IDS_FLG_PROXY 170
+#define IDS_FLG_MAY_POSTDATE 171
+#define IDS_FLG_POSTDATED 172
+#define IDS_FLG_INVALID 173
+#define IDS_FLG_RENEWABLE 174
+#define IDS_FLG_INITIAL 175
+#define IDS_FLG_PRE_AUTH 176
+#define IDS_FLG_HW_AUTH 177
+#define IDS_FLG_TRANSIT_POL 178
+#define IDS_FLG_OK_DELEGATE 179
+#define IDS_FLG_ANONYMOUS 180
+#define IDS_K5ERR_CANTWRITEPROFILE 181
+#define IDS_K5ERR_PROFNOWRITE 182
+#define IDS_K5ERR_PROFUSETEMP 183
+#define IDS_K5ERR_PROFSUGGEST 184
+#define IDS_CFG_RE_REALMS 185
+#define IDS_CFG_RE_KDCS 186
+#define IDS_CFG_RE_DMAPS 187
+#define IDS_CFG_RE_KDCS_R 188
+#define IDS_CFG_RE_DMAPS_R 189
+#define IDS_CFG_RE_HEAD_SVR 190
+#define IDS_CFG_RE_HEAD_ADMIN 191
+#define IDS_CFG_RE_HEAD_MASTER 192
+#define IDS_CFG_RE_HEAD_DOMAIN 193
+#define IDS_CFG_RE_NEWREALM 194
+#define IDS_YES 195
+#define IDS_NO 196
+#define IDS_CFG_RE_NEWSERVER 197
+#define IDS_CFG_RE_NEWDMAP 198
+#define IDS_KRB5_NC_NAME 199
+#define IDS_NCERR_IDENT_TOO_LONG 200
+#define IDS_NCERR_IDENT_INVALID 201
+#define IDS_NCERR_IDENT_UNKNOWN 202
+#define IDS_CFG_RE_ARNUT 203
+#define IDS_CFG_RE_ARNUM 204
+#define IDS_CFG_RE_ASNUT 205
+#define IDS_CFG_RE_ASNUM 206
+#define IDS_CFG_RE_DMNUT 207
+#define IDS_CFG_RE_DMNUM 208
+#define IDS_CFG_RE_MNR 209
+#define IDS_CFG_RE_MDR 210
+#define IDS_CFG_RE_MNK 211
+#define IDS_CFG_RE_MDK 212
+#define IDS_CFG_RE_MAK 213
+#define IDS_CFG_RE_MMK 214
+#define IDS_CFG_RE_MND 215
+#define IDS_CFG_RE_MDD 216
+#define IDS_KVNO_SHORT_DESC 217
+#define IDS_KVNO_LONG_DESC 218
+#define IDC_NCK5_RENEWABLE 1002
+#define IDC_NCK5_FORWARDABLE 1004
+#define IDC_NCK5_REALM 1005
+#define IDC_NCK5_ADD_REALMS 1006
+#define IDC_NCK5_LIFETIME_EDIT 1008
+#define IDC_NCK5_RENEW_EDIT 1009
+#define IDC_PPK5_CRENEW 1014
+#define IDC_PPK5_CFORWARD 1015
+#define IDC_PPK5_CPROXY 1016
+#define IDC_PPK5_NAME 1017
+#define IDC_PPK5_ISSUE 1018
+#define IDC_PPK5_VALID 1019
+#define IDC_PPK5_RENEW 1020
+#define IDC_CHECK2 1022
+#define IDC_CHECK4 1024
+#define IDC_PPK5_LIFETIME 1024
+#define IDC_CHECK5 1025
+#define IDC_CFG_LBL_REALM 1025
+#define IDC_CFG_DEFREALM 1026
+#define IDC_CFG_LBL_CFGFILE 1029
+#define IDC_CFG_CFGFILE 1030
+#define IDC_CFG_WINGRP 1031
+#define IDC_LBL_IMPORT 1032
+#define IDC_CFG_IMPORT 1033
+#define IDC_CFG_LBL_HOSTNAME 1034
+#define IDC_CFG_HOSTNAME 1035
+#define IDC_CFG_LBL_DOMAIN 1036
+#define IDC_CFG_DOMAIN 1037
+#define IDC_CFG_CREATECONFIG 1038
+#define IDC_CFG_BROWSE 1039
+#define IDC_CFG_CFGFILEGRP 1040
+#define IDC_CFG_CFGREALMS 1041
+#define IDC_CFG_BROWSE2 1042
+#define IDC_CFG_REALMS 1044
+#define IDC_CFG_DOMAINGRP 1045
+#define IDC_CFG_SERVERSGRP 1046
+#define IDC_LIST3 1047
+#define IDC_CFG_KDC 1047
+#define IDC_LIST4 1048
+#define IDC_CFG_DMAP 1048
+#define IDC_CFG_LBL_DEFLIFE 1049
+#define IDC_CFG_DEFLIFE 1050
+#define IDC_CFG_LBL_DEFRLIFE 1051
+#define IDC_CFG_DEFRLIFE 1052
+#define IDC_CFG_LIFEGRP 1053
+#define IDC_CFG_LRNG_MIN 1054
+#define IDC_CFG_LRNG_MAX 1055
+#define IDC_CFG_RLRNG_MIN 1056
+#define IDC_CFG_RLRNG_MAX 1057
+#define IDC_CFG_CCACHE 1058
+#define IDC_CFG_FCGRP 1059
+#define IDC_CFG_FCLIST 1060
+#define IDC_CFG_FCNAME 1062
+#define IDC_CFG_ADD 1064
+#define IDC_CFG_REMOVE 1065
+#define IDC_CFG_INCAPI 1066
+#define IDC_CFG_INCMSLSA 1067
+#define IDC_PPK5_FLAGS 1072
+#define IDC_CFG_INCREALMS 1073
+#define IDC_NCK5_ADDRESS 1074
+#define IDC_IPADDRESS1 1075
+#define IDC_NCK5_PUBLICIP 1075
+#define IDC_CFG_PUBLICIP 1075
+#define IDC_CFG_RENEW 1076
+#define IDC_CHECK3 1077
+#define IDC_CFG_ADDRESSLESS 1077
+#define IDC_CFG_FORWARD 1078
+#define IDC_CHECK1 1079
+#define ID_FOO_BAR 40001
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 219
+#define _APS_NEXT_COMMAND_VALUE 40002
+#define _APS_NEXT_CONTROL_VALUE 1080
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/src/windows/identity/sample/templates/credprov/config_id.c b/src/windows/identity/sample/templates/credprov/config_id.c
index ed5b3e4c3d..8500162669 100644
--- a/src/windows/identity/sample/templates/credprov/config_id.c
+++ b/src/windows/identity/sample/templates/credprov/config_id.c
@@ -1,118 +1,118 @@
-/*
- * Copyright (c) 2006 Secure Endpoints Inc.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include "credprov.h"
-#include <assert.h>
-
-/* Dialog procedures and support functions for handling configuration
- dialogs for per-identity configuration. When the configuration
- dialog is activated, an instance of this dialog will be created for
- each identity that the user touches. */
-
-/* The structure that we use to hold state information for the
- dialog. */
-typedef struct tag_config_id_dlg_data {
- khui_config_init_data cfg; /* instance information for this
- dialog */
-
- khm_handle ident; /* handle to the identity for this
- dialog */
-
- /* TODO: Add any fields for holding state here */
-} config_id_dlg_data;
-
-INT_PTR CALLBACK
-config_id_dlgproc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam) {
-
- config_id_dlg_data * d;
-
- switch (uMsg) {
- case WM_INITDIALOG:
- {
- wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
- khm_size cb;
- khm_int32 rv;
-
- d = malloc(sizeof(*d));
- assert(d);
- ZeroMemory(d, sizeof(*d));
-
- /* for subpanels, lParam is a pointer to a
- khui_config_init_data strucutre that provides the
- instance and context information. It's not a
- persistent strucutre, so we have to make a copy. */
- d->cfg = *((khui_config_init_data *) lParam);
-
- cb = sizeof(idname);
- rv = khui_cfg_get_name(d->cfg.ctx_node, idname, &cb);
- assert(KHM_SUCCEEDED(rv));
-
- rv = kcdb_identity_create(idname, 0, &d->ident);
- assert(KHM_SUCCEEDED(rv));
-
- /* TODO: perform any other required initialization */
-
-#pragma warning(push)
-#pragma warning(disable: 4244)
- SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) d);
-#pragma warning(pop)
- }
- break;
-
- case KHUI_WM_CFG_NOTIFY:
- d = (config_id_dlg_data *)
- GetWindowLongPtr(hwnd, DWLP_USER);
-
- if (HIWORD(wParam) == WMCFG_APPLY) {
- /* TODO: apply changes */
-
- return TRUE;
- }
- break;
-
- case WM_DESTROY:
- {
- d = (config_id_dlg_data *)
- GetWindowLongPtr(hwnd, DWLP_USER);
-
- if (d) {
- if (d->ident)
- kcdb_identity_release(d->ident);
-
- /* TODO: perform any other required uninitialization */
-
- free(d);
- }
- }
- break;
- }
-
- return FALSE;
-
-}
+/*
+ * Copyright (c) 2006 Secure Endpoints Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include "credprov.h"
+#include <assert.h>
+
+/* Dialog procedures and support functions for handling configuration
+ dialogs for per-identity configuration. When the configuration
+ dialog is activated, an instance of this dialog will be created for
+ each identity that the user touches. */
+
+/* The structure that we use to hold state information for the
+ dialog. */
+typedef struct tag_config_id_dlg_data {
+ khui_config_init_data cfg; /* instance information for this
+ dialog */
+
+ khm_handle ident; /* handle to the identity for this
+ dialog */
+
+ /* TODO: Add any fields for holding state here */
+} config_id_dlg_data;
+
+INT_PTR CALLBACK
+config_id_dlgproc(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam) {
+
+ config_id_dlg_data * d;
+
+ switch (uMsg) {
+ case WM_INITDIALOG:
+ {
+ wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
+ khm_size cb;
+ khm_int32 rv;
+
+ d = malloc(sizeof(*d));
+ assert(d);
+ ZeroMemory(d, sizeof(*d));
+
+ /* for subpanels, lParam is a pointer to a
+ khui_config_init_data strucutre that provides the
+ instance and context information. It's not a
+ persistent strucutre, so we have to make a copy. */
+ d->cfg = *((khui_config_init_data *) lParam);
+
+ cb = sizeof(idname);
+ rv = khui_cfg_get_name(d->cfg.ctx_node, idname, &cb);
+ assert(KHM_SUCCEEDED(rv));
+
+ rv = kcdb_identity_create(idname, 0, &d->ident);
+ assert(KHM_SUCCEEDED(rv));
+
+ /* TODO: perform any other required initialization */
+
+#pragma warning(push)
+#pragma warning(disable: 4244)
+ SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) d);
+#pragma warning(pop)
+ }
+ break;
+
+ case KHUI_WM_CFG_NOTIFY:
+ d = (config_id_dlg_data *)
+ GetWindowLongPtr(hwnd, DWLP_USER);
+
+ if (HIWORD(wParam) == WMCFG_APPLY) {
+ /* TODO: apply changes */
+
+ return TRUE;
+ }
+ break;
+
+ case WM_DESTROY:
+ {
+ d = (config_id_dlg_data *)
+ GetWindowLongPtr(hwnd, DWLP_USER);
+
+ if (d) {
+ if (d->ident)
+ kcdb_identity_release(d->ident);
+
+ /* TODO: perform any other required uninitialization */
+
+ free(d);
+ }
+ }
+ break;
+ }
+
+ return FALSE;
+
+}
diff --git a/src/windows/identity/sample/templates/credprov/config_ids.c b/src/windows/identity/sample/templates/credprov/config_ids.c
index 4139512079..8d6f0081aa 100644
--- a/src/windows/identity/sample/templates/credprov/config_ids.c
+++ b/src/windows/identity/sample/templates/credprov/config_ids.c
@@ -1,96 +1,96 @@
-/*
- * Copyright (c) 2006 Secure Endpoints Inc.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include "credprov.h"
-#include<assert.h>
-
-/* Dialog procedures and support functions for handling configuration
- dialogs for all identities. */
-
-/* The structure that we use to hold state information for the
- dialog. */
-typedef struct tag_config_ids_dlg_data {
- khui_config_init_data cfg; /* instance information for this
- dialog */
-
- /* TODO: Add any fields for holding state here */
-} config_ids_dlg_data;
-
-INT_PTR CALLBACK
-config_ids_dlgproc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam) {
-
- config_ids_dlg_data * d;
-
- switch (uMsg) {
- case WM_INITDIALOG:
- {
- d = malloc(sizeof(*d));
- assert(d);
- ZeroMemory(d, sizeof(*d));
-
- /* for subpanels, lParam is a pointer to a
- khui_config_init_data strucutre that provides the
- instance and context information. It's not a
- persistent strucutre, so we have to make a copy. */
- d->cfg = *((khui_config_init_data *) lParam);
-
- /* TODO: perform any additional initialization */
-
-#pragma warning(push)
-#pragma warning(disable: 4244)
- SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) d);
-#pragma warning(pop)
- }
- break;
-
- case KHUI_WM_CFG_NOTIFY:
- d = (config_ids_dlg_data *)
- GetWindowLongPtr(hwnd, DWLP_USER);
-
- if (HIWORD(wParam) == WMCFG_APPLY) {
- /* TODO: apply changes */
-
- return TRUE;
- }
- break;
-
- case WM_DESTROY:
- d = (config_ids_dlg_data *)
- GetWindowLongPtr(hwnd, DWLP_USER);
-
- if (d) {
- /* TODO: Perform any additional uninitialization */
-
- free (d);
- }
- break;
- }
-
- return FALSE;
-}
+/*
+ * Copyright (c) 2006 Secure Endpoints Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include "credprov.h"
+#include<assert.h>
+
+/* Dialog procedures and support functions for handling configuration
+ dialogs for all identities. */
+
+/* The structure that we use to hold state information for the
+ dialog. */
+typedef struct tag_config_ids_dlg_data {
+ khui_config_init_data cfg; /* instance information for this
+ dialog */
+
+ /* TODO: Add any fields for holding state here */
+} config_ids_dlg_data;
+
+INT_PTR CALLBACK
+config_ids_dlgproc(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam) {
+
+ config_ids_dlg_data * d;
+
+ switch (uMsg) {
+ case WM_INITDIALOG:
+ {
+ d = malloc(sizeof(*d));
+ assert(d);
+ ZeroMemory(d, sizeof(*d));
+
+ /* for subpanels, lParam is a pointer to a
+ khui_config_init_data strucutre that provides the
+ instance and context information. It's not a
+ persistent strucutre, so we have to make a copy. */
+ d->cfg = *((khui_config_init_data *) lParam);
+
+ /* TODO: perform any additional initialization */
+
+#pragma warning(push)
+#pragma warning(disable: 4244)
+ SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) d);
+#pragma warning(pop)
+ }
+ break;
+
+ case KHUI_WM_CFG_NOTIFY:
+ d = (config_ids_dlg_data *)
+ GetWindowLongPtr(hwnd, DWLP_USER);
+
+ if (HIWORD(wParam) == WMCFG_APPLY) {
+ /* TODO: apply changes */
+
+ return TRUE;
+ }
+ break;
+
+ case WM_DESTROY:
+ d = (config_ids_dlg_data *)
+ GetWindowLongPtr(hwnd, DWLP_USER);
+
+ if (d) {
+ /* TODO: Perform any additional uninitialization */
+
+ free (d);
+ }
+ break;
+ }
+
+ return FALSE;
+}
diff --git a/src/windows/identity/sample/templates/credprov/config_main.c b/src/windows/identity/sample/templates/credprov/config_main.c
index 3461ac0ccc..87a2a15fc6 100644
--- a/src/windows/identity/sample/templates/credprov/config_main.c
+++ b/src/windows/identity/sample/templates/credprov/config_main.c
@@ -1,99 +1,99 @@
-/*
- * Copyright (c) 2006 Secure Endpoints Inc.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include "credprov.h"
-#include <assert.h>
-
-/* Dialog procedures and support functions for handling configuration
- dialogs for general plug-in configuration. */
-
-/* Structure for holding dialog data for the configuration window. */
-typedef struct tag_config_main_dlg_data {
- khui_config_node cnode;
-
- /* TODO: add fields as needed */
-} config_main_dlg_data;
-
-INT_PTR CALLBACK
-config_dlgproc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam) {
-
- config_main_dlg_data * d;
-
- switch (uMsg) {
- case WM_INITDIALOG:
- d = malloc(sizeof(*d));
- assert(d);
- ZeroMemory(d, sizeof(*d));
-
- /* for configuration panels that are not subpanels, lParam is
- a held handle to the configuration node. The handle will
- be held for the lifetime of the window. */
-
- d->cnode = (khui_config_node) lParam;
-
- /* TODO: perform any other required initialization stuff
- here */
-
-#pragma warning(push)
-#pragma warning(disable: 4244)
- SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) d);
-#pragma warning(pop)
-
- break;
-
- case KHUI_WM_CFG_NOTIFY:
- {
- d = (config_main_dlg_data *)
- GetWindowLongPtr(hwnd, DWLP_USER);
-
- /* WMCFG_APPLY is the only notification we care about */
-
- if (HIWORD(wParam) == WMCFG_APPLY) {
- /* TODO: Apply changes and update the state */
-
- return TRUE;
- }
- }
- break;
-
- case WM_DESTROY:
- d = (config_main_dlg_data *)
- GetWindowLongPtr(hwnd, DWLP_USER);
-
- /* TODO: perform any other required uninitialization here */
-
- if (d)
- free(d);
-
- break;
- }
-
- return FALSE;
-
-}
+/*
+ * Copyright (c) 2006 Secure Endpoints Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include "credprov.h"
+#include <assert.h>
+
+/* Dialog procedures and support functions for handling configuration
+ dialogs for general plug-in configuration. */
+
+/* Structure for holding dialog data for the configuration window. */
+typedef struct tag_config_main_dlg_data {
+ khui_config_node cnode;
+
+ /* TODO: add fields as needed */
+} config_main_dlg_data;
+
+INT_PTR CALLBACK
+config_dlgproc(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam) {
+
+ config_main_dlg_data * d;
+
+ switch (uMsg) {
+ case WM_INITDIALOG:
+ d = malloc(sizeof(*d));
+ assert(d);
+ ZeroMemory(d, sizeof(*d));
+
+ /* for configuration panels that are not subpanels, lParam is
+ a held handle to the configuration node. The handle will
+ be held for the lifetime of the window. */
+
+ d->cnode = (khui_config_node) lParam;
+
+ /* TODO: perform any other required initialization stuff
+ here */
+
+#pragma warning(push)
+#pragma warning(disable: 4244)
+ SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) d);
+#pragma warning(pop)
+
+ break;
+
+ case KHUI_WM_CFG_NOTIFY:
+ {
+ d = (config_main_dlg_data *)
+ GetWindowLongPtr(hwnd, DWLP_USER);
+
+ /* WMCFG_APPLY is the only notification we care about */
+
+ if (HIWORD(wParam) == WMCFG_APPLY) {
+ /* TODO: Apply changes and update the state */
+
+ return TRUE;
+ }
+ }
+ break;
+
+ case WM_DESTROY:
+ d = (config_main_dlg_data *)
+ GetWindowLongPtr(hwnd, DWLP_USER);
+
+ /* TODO: perform any other required uninitialization here */
+
+ if (d)
+ free(d);
+
+ break;
+ }
+
+ return FALSE;
+
+}
diff --git a/src/windows/identity/sample/templates/credprov/credacq.c b/src/windows/identity/sample/templates/credprov/credacq.c
index da07756dad..cd8db44ee3 100644
--- a/src/windows/identity/sample/templates/credprov/credacq.c
+++ b/src/windows/identity/sample/templates/credprov/credacq.c
@@ -1,405 +1,405 @@
-/*
- * Copyright (c) 2006 Secure Endpoints Inc.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include "credprov.h"
-#include<assert.h>
-
-/* This file provides handlers for the credentials acquisition
- messages including handling the user interface for the new
- credentials dialogs. */
-
-/*********************************************************************
-
-These are stubs for the Window message for the dialog panel. This
-dialog panel is the one that is added to the new credentials window
-for obtaining new credentials.
-
-Note that all the UI callbacks run under the UI thread.
-
- *********************************************************************/
-
-/* This structure will hold all the state information we will need to
- access from the new credentials panel for our credentials type. */
-struct nc_dialog_data {
- khui_new_creds * nc;
- khui_new_creds_by_type * nct;
-
- /* TODO: add any other state information here */
-};
-
-/* Note: This callback runs under the UI thread */
-INT_PTR
-handle_wm_initdialog(HWND hwnd, WPARAM wParam, LPARAM lParam) {
- khui_new_creds * nc = NULL;
- khui_new_creds_by_type * nct = NULL;
- struct nc_dialog_data * d = NULL;
-
- nc = (khui_new_creds *) lParam;
- khui_cw_find_type(nc, credtype_id, &nct);
-
- assert(nct);
-
- d = malloc(sizeof(*d));
- ZeroMemory(d, sizeof(*d));
-
- d->nc = nc;
- d->nct = nct;
-
-#pragma warning(push)
-#pragma warning(disable: 4244)
- SetWindowLongPtr(hwnd, DWLP_USER, (LPARAM) d);
-#pragma warning(pop)
-
- nct->aux = (LPARAM) d; /* we can use the auxiliary field to
- hold a pointer to d */
-
- /* TODO: Perform any additional initialization here */
-
- return FALSE;
-}
-
-/* Note: This callback runs under the UI thread */
-INT_PTR
-handle_khui_wm_nc_notify(HWND hwnd, WPARAM wParam, LPARAM lParam) {
-
- struct nc_dialog_data * d;
-
- /* Refer to the khui_wm_nc_notifications enumeration in the
- NetIDMgr SDK for the full list of notification messages that
- can be sent. */
-
- d = (struct nc_dialog_data *) GetWindowLongPtr(hwnd, DWLP_USER);
-
- if (!d)
- return TRUE;
-
- /* these should be set by now */
- assert(d->nc);
- assert(d->nct);
-
- switch (HIWORD(wParam)) {
- case WMNC_UPDATE_CREDTEXT:
- {
- wchar_t fmt[KHUI_MAXCCH_LONG_DESC];
- wchar_t tbuf[256];
-
- /* we are being requested to update the credentials
- text. We already allocated a buffer when we created the
- nct structure. So we can just set the text here.*/
-
- /* TODO: The credtext should reflect the credentials that
- will be obtained when the new credentials operation
- completes. */
-
- LoadString(hResModule, IDS_NC_CT_TEMPLATE,
- fmt, ARRAYLENGTH(fmt));
-
- LoadString(hResModule, IDS_GEN_NONE,
- tbuf, ARRAYLENGTH(tbuf));
-
- assert(d->nct->credtext);
-
- StringCbPrintf(d->nct->credtext, KHUI_MAXCB_LONG_DESC,
- fmt, tbuf);
- }
- break;
-
- case WMNC_CREDTEXT_LINK:
- break;
-
- case WMNC_IDENTITY_CHANGE:
- break;
-
- case WMNC_DIALOG_PREPROCESS:
- break;
- }
-
- return TRUE;
-}
-
-/* Note: This callback runs under the UI thread */
-INT_PTR
-handle_wm_command(HWND hwnd, WPARAM wParam, LPARAM lParam) {
-
- struct nc_dialog_data * d;
-
- d = (struct nc_dialog_data *) GetWindowLongPtr(hwnd, DWLP_USER);
-
- /* TODO: handle WM_COMMAND */
- return FALSE;
-}
-
-/* Note: This callback runs under the UI thread */
-INT_PTR
-handle_wm_destroy(HWND hwnd, WPARAM wParam, LPARAM lParam) {
-
- struct nc_dialog_data * d;
-
- d = (struct nc_dialog_data *) GetWindowLongPtr(hwnd, DWLP_USER);
-
- if (d) {
- d->nc = NULL;
- d->nct = NULL;
-
- free(d);
- }
-
- /* TODO: Perform any additional uninitialization */
-
- return FALSE;
-}
-
-/* Dialog procedure for the new credentials panel for our credentials
- type. We just dispatch messages here to other functions here.
-
- Note that this procedure runs under the UI thread.
- */
-INT_PTR CALLBACK
-nc_dlg_proc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam) {
-
- switch (uMsg) {
- case WM_INITDIALOG:
- return handle_wm_initdialog(hwnd, wParam, lParam);
-
- case WM_COMMAND:
- return handle_wm_command(hwnd, wParam, lParam);
-
- case KHUI_WM_NC_NOTIFY:
- return handle_khui_wm_nc_notify(hwnd, wParam, lParam);
-
- case WM_DESTROY:
- return handle_wm_destroy(hwnd, wParam, lParam);
-
- /* TODO: add code for handling other windows messages here. */
- }
-
- return FALSE;
-}
-
-/*******************************************************************
-
-The following section contains function stubs for each of the
-credentials messages that a credentials provider is likely to want to
-handle. It doesn't include a few messages, but they should be easy to
-add. Please see the documentation for each of the KMSG_CRED_*
-messages for documentation on how to handle each of the messages.
-
-********************************************************************/
-
-
-/* Handler for KMSG_CRED_NEW_CREDS */
-khm_int32
-handle_kmsg_cred_new_creds(khui_new_creds * nc) {
-
- wchar_t wshortdesc[KHUI_MAXCCH_SHORT_DESC];
- size_t cb = 0;
- khui_new_creds_by_type * nct = NULL;
-
- /* This is a minimal handler that just adds a dialog pane to the
- new credentials window to handle new credentials acquisition
- for this credentials type. */
-
- /* TODO: add additional initialization etc. as needed */
-
- nct = malloc(sizeof(*nct));
- ZeroMemory(nct, sizeof(*nct));
-
- nct->type = credtype_id;
- nct->ordinal = -1;
-
- LoadString(hResModule, IDS_CT_SHORT_DESC,
- wshortdesc, ARRAYLENGTH(wshortdesc));
- StringCbLength(wshortdesc, sizeof(wshortdesc), &cb);
-#ifdef DEBUG
- assert(cb > 0);
-#endif
- cb += sizeof(wchar_t);
-
- nct->name = malloc(cb);
- StringCbCopy(nct->name, cb, wshortdesc);
-
- /* while we are at it, we should also allocate space for the
- credential text. */
- nct->credtext = malloc(KHUI_MAXCB_LONG_DESC);
- ZeroMemory(nct->credtext, KHUI_MAXCB_LONG_DESC);
-
- nct->h_module = hResModule;
- nct->dlg_proc = nc_dlg_proc;
- nct->dlg_template = MAKEINTRESOURCE(IDD_NEW_CREDS);
-
- khui_cw_add_type(nc, nct);
-
- return KHM_ERROR_SUCCESS;
-}
-
-/* Handler for KMSG_CRED_RENEW_CREDS */
-khm_int32
-handle_kmsg_cred_renew_creds(khui_new_creds * nc) {
-
- khui_new_creds_by_type * nct;
-
- /* This is a minimal handler that just adds this credential type
- to the list of credential types that are participating in this
- renewal operation. */
-
- /* TODO: add additional initialization etc. as needed */
-
- nct = malloc(sizeof(*nct));
- ZeroMemory(nct, sizeof(*nct));
-
- nct->type = credtype_id;
-
- khui_cw_add_type(nc, nct);
-
- return KHM_ERROR_SUCCESS;
-}
-
-/* Handler for KMSG_CRED_DIALOG_PRESTART */
-khm_int32
-handle_kmsg_cred_dialog_prestart(khui_new_creds * nc) {
- /* TODO: Handle this message */
-
- /* The message is sent after the dialog has been created. The
- window handle for the created dialog can be accessed through
- the hwnd_panel member of the khui_new_creds_by_type structure
- that was added for this credentials type. */
- return KHM_ERROR_SUCCESS;
-}
-
-/* Handler for KMSG_CRED_DIALOG_NEW_IDENTITY */
-/* Not a message sent out by NetIDMgr. See documentation of
- KMSG_CRED_DIALOG_NEW_IDENTITY */
-khm_int32
-handle_kmsg_cred_dialog_new_identity(khm_ui_4 uparam,
- void * vparam) {
- /* TODO: Handle this message */
- return KHM_ERROR_SUCCESS;
-}
-
-/* Handler for KMSG_CRED_DIALOG_NEW_OPTIONS */
-/* Not a message sent out by NetIDMgr. See documentation of
- KMSG_CRED_DIALOG_NEW_OPTIONS */
-khm_int32
-handle_kmsg_cred_dialog_new_options(khm_ui_4 uparam,
- void * vparam) {
- /* TODO: Handle this message */
- return KHM_ERROR_SUCCESS;
-}
-
-/* Handler for KMSG_CRED_PROCESS */
-khm_int32
-handle_kmsg_cred_process(khui_new_creds * nc) {
- /* TODO: Handle this message */
-
- /* This is where the credentials acquisition should be performed
- as determined by the UI. Note that this message is sent even
- when the user clicks 'cancel'. The value of nc->result should
- be checked before performing any credentials acquisition. If
- the value is KHUI_NC_RESULT_CANCEL, then no credentials should
- be acquired. Otherwise, the value would be
- KHUI_NC_RESULT_PROCESS. */
-
- return KHM_ERROR_SUCCESS;
-}
-
-/* Handler for KMSG_CRED_END */
-khm_int32
-handle_kmsg_cred_end(khui_new_creds * nc) {
-
- khui_new_creds_by_type * nct = NULL;
-
- /* TODO: Perform any additional uninitialization as needed. */
-
- khui_cw_find_type(nc, credtype_id, &nct);
-
- if (nct) {
-
- khui_cw_del_type(nc, credtype_id);
-
- if (nct->name)
- free(nct->name);
- if (nct->credtext)
- free(nct->credtext);
-
- free(nct);
-
- }
-
- return KHM_ERROR_SUCCESS;
-}
-
-/* Handler for KMSG_CRED_IMPORT */
-khm_int32
-handle_kmsg_cred_import(void) {
-
- /* TODO: Handle this message */
-
- return KHM_ERROR_SUCCESS;
-}
-
-
-/******************************************************
- Dispatch each message to individual handlers above.
- */
-khm_int32 KHMAPI
-handle_cred_acq_msg(khm_int32 msg_type,
- khm_int32 msg_subtype,
- khm_ui_4 uparam,
- void * vparam) {
-
- khm_int32 rv = KHM_ERROR_SUCCESS;
-
- switch(msg_subtype) {
- case KMSG_CRED_NEW_CREDS:
- return handle_kmsg_cred_new_creds((khui_new_creds *) vparam);
-
- case KMSG_CRED_RENEW_CREDS:
- return handle_kmsg_cred_renew_creds((khui_new_creds *) vparam);
-
- case KMSG_CRED_DIALOG_PRESTART:
- return handle_kmsg_cred_dialog_prestart((khui_new_creds *) vparam);
-
- case KMSG_CRED_PROCESS:
- return handle_kmsg_cred_process((khui_new_creds *) vparam);
-
- case KMSG_CRED_DIALOG_NEW_IDENTITY:
- return handle_kmsg_cred_dialog_new_identity(uparam, vparam);
-
- case KMSG_CRED_DIALOG_NEW_OPTIONS:
- return handle_kmsg_cred_dialog_new_options(uparam, vparam);
-
- case KMSG_CRED_END:
- return handle_kmsg_cred_end((khui_new_creds *) vparam);
-
- case KMSG_CRED_IMPORT:
- return handle_kmsg_cred_import();
- }
-
- return rv;
-}
+/*
+ * Copyright (c) 2006 Secure Endpoints Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include "credprov.h"
+#include<assert.h>
+
+/* This file provides handlers for the credentials acquisition
+ messages including handling the user interface for the new
+ credentials dialogs. */
+
+/*********************************************************************
+
+These are stubs for the Window message for the dialog panel. This
+dialog panel is the one that is added to the new credentials window
+for obtaining new credentials.
+
+Note that all the UI callbacks run under the UI thread.
+
+ *********************************************************************/
+
+/* This structure will hold all the state information we will need to
+ access from the new credentials panel for our credentials type. */
+struct nc_dialog_data {
+ khui_new_creds * nc;
+ khui_new_creds_by_type * nct;
+
+ /* TODO: add any other state information here */
+};
+
+/* Note: This callback runs under the UI thread */
+INT_PTR
+handle_wm_initdialog(HWND hwnd, WPARAM wParam, LPARAM lParam) {
+ khui_new_creds * nc = NULL;
+ khui_new_creds_by_type * nct = NULL;
+ struct nc_dialog_data * d = NULL;
+
+ nc = (khui_new_creds *) lParam;
+ khui_cw_find_type(nc, credtype_id, &nct);
+
+ assert(nct);
+
+ d = malloc(sizeof(*d));
+ ZeroMemory(d, sizeof(*d));
+
+ d->nc = nc;
+ d->nct = nct;
+
+#pragma warning(push)
+#pragma warning(disable: 4244)
+ SetWindowLongPtr(hwnd, DWLP_USER, (LPARAM) d);
+#pragma warning(pop)
+
+ nct->aux = (LPARAM) d; /* we can use the auxiliary field to
+ hold a pointer to d */
+
+ /* TODO: Perform any additional initialization here */
+
+ return FALSE;
+}
+
+/* Note: This callback runs under the UI thread */
+INT_PTR
+handle_khui_wm_nc_notify(HWND hwnd, WPARAM wParam, LPARAM lParam) {
+
+ struct nc_dialog_data * d;
+
+ /* Refer to the khui_wm_nc_notifications enumeration in the
+ NetIDMgr SDK for the full list of notification messages that
+ can be sent. */
+
+ d = (struct nc_dialog_data *) GetWindowLongPtr(hwnd, DWLP_USER);
+
+ if (!d)
+ return TRUE;
+
+ /* these should be set by now */
+ assert(d->nc);
+ assert(d->nct);
+
+ switch (HIWORD(wParam)) {
+ case WMNC_UPDATE_CREDTEXT:
+ {
+ wchar_t fmt[KHUI_MAXCCH_LONG_DESC];
+ wchar_t tbuf[256];
+
+ /* we are being requested to update the credentials
+ text. We already allocated a buffer when we created the
+ nct structure. So we can just set the text here.*/
+
+ /* TODO: The credtext should reflect the credentials that
+ will be obtained when the new credentials operation
+ completes. */
+
+ LoadString(hResModule, IDS_NC_CT_TEMPLATE,
+ fmt, ARRAYLENGTH(fmt));
+
+ LoadString(hResModule, IDS_GEN_NONE,
+ tbuf, ARRAYLENGTH(tbuf));
+
+ assert(d->nct->credtext);
+
+ StringCbPrintf(d->nct->credtext, KHUI_MAXCB_LONG_DESC,
+ fmt, tbuf);
+ }
+ break;
+
+ case WMNC_CREDTEXT_LINK:
+ break;
+
+ case WMNC_IDENTITY_CHANGE:
+ break;
+
+ case WMNC_DIALOG_PREPROCESS:
+ break;
+ }
+
+ return TRUE;
+}
+
+/* Note: This callback runs under the UI thread */
+INT_PTR
+handle_wm_command(HWND hwnd, WPARAM wParam, LPARAM lParam) {
+
+ struct nc_dialog_data * d;
+
+ d = (struct nc_dialog_data *) GetWindowLongPtr(hwnd, DWLP_USER);
+
+ /* TODO: handle WM_COMMAND */
+ return FALSE;
+}
+
+/* Note: This callback runs under the UI thread */
+INT_PTR
+handle_wm_destroy(HWND hwnd, WPARAM wParam, LPARAM lParam) {
+
+ struct nc_dialog_data * d;
+
+ d = (struct nc_dialog_data *) GetWindowLongPtr(hwnd, DWLP_USER);
+
+ if (d) {
+ d->nc = NULL;
+ d->nct = NULL;
+
+ free(d);
+ }
+
+ /* TODO: Perform any additional uninitialization */
+
+ return FALSE;
+}
+
+/* Dialog procedure for the new credentials panel for our credentials
+ type. We just dispatch messages here to other functions here.
+
+ Note that this procedure runs under the UI thread.
+ */
+INT_PTR CALLBACK
+nc_dlg_proc(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam) {
+
+ switch (uMsg) {
+ case WM_INITDIALOG:
+ return handle_wm_initdialog(hwnd, wParam, lParam);
+
+ case WM_COMMAND:
+ return handle_wm_command(hwnd, wParam, lParam);
+
+ case KHUI_WM_NC_NOTIFY:
+ return handle_khui_wm_nc_notify(hwnd, wParam, lParam);
+
+ case WM_DESTROY:
+ return handle_wm_destroy(hwnd, wParam, lParam);
+
+ /* TODO: add code for handling other windows messages here. */
+ }
+
+ return FALSE;
+}
+
+/*******************************************************************
+
+The following section contains function stubs for each of the
+credentials messages that a credentials provider is likely to want to
+handle. It doesn't include a few messages, but they should be easy to
+add. Please see the documentation for each of the KMSG_CRED_*
+messages for documentation on how to handle each of the messages.
+
+********************************************************************/
+
+
+/* Handler for KMSG_CRED_NEW_CREDS */
+khm_int32
+handle_kmsg_cred_new_creds(khui_new_creds * nc) {
+
+ wchar_t wshortdesc[KHUI_MAXCCH_SHORT_DESC];
+ size_t cb = 0;
+ khui_new_creds_by_type * nct = NULL;
+
+ /* This is a minimal handler that just adds a dialog pane to the
+ new credentials window to handle new credentials acquisition
+ for this credentials type. */
+
+ /* TODO: add additional initialization etc. as needed */
+
+ nct = malloc(sizeof(*nct));
+ ZeroMemory(nct, sizeof(*nct));
+
+ nct->type = credtype_id;
+ nct->ordinal = -1;
+
+ LoadString(hResModule, IDS_CT_SHORT_DESC,
+ wshortdesc, ARRAYLENGTH(wshortdesc));
+ StringCbLength(wshortdesc, sizeof(wshortdesc), &cb);
+#ifdef DEBUG
+ assert(cb > 0);
+#endif
+ cb += sizeof(wchar_t);
+
+ nct->name = malloc(cb);
+ StringCbCopy(nct->name, cb, wshortdesc);
+
+ /* while we are at it, we should also allocate space for the
+ credential text. */
+ nct->credtext = malloc(KHUI_MAXCB_LONG_DESC);
+ ZeroMemory(nct->credtext, KHUI_MAXCB_LONG_DESC);
+
+ nct->h_module = hResModule;
+ nct->dlg_proc = nc_dlg_proc;
+ nct->dlg_template = MAKEINTRESOURCE(IDD_NEW_CREDS);
+
+ khui_cw_add_type(nc, nct);
+
+ return KHM_ERROR_SUCCESS;
+}
+
+/* Handler for KMSG_CRED_RENEW_CREDS */
+khm_int32
+handle_kmsg_cred_renew_creds(khui_new_creds * nc) {
+
+ khui_new_creds_by_type * nct;
+
+ /* This is a minimal handler that just adds this credential type
+ to the list of credential types that are participating in this
+ renewal operation. */
+
+ /* TODO: add additional initialization etc. as needed */
+
+ nct = malloc(sizeof(*nct));
+ ZeroMemory(nct, sizeof(*nct));
+
+ nct->type = credtype_id;
+
+ khui_cw_add_type(nc, nct);
+
+ return KHM_ERROR_SUCCESS;
+}
+
+/* Handler for KMSG_CRED_DIALOG_PRESTART */
+khm_int32
+handle_kmsg_cred_dialog_prestart(khui_new_creds * nc) {
+ /* TODO: Handle this message */
+
+ /* The message is sent after the dialog has been created. The
+ window handle for the created dialog can be accessed through
+ the hwnd_panel member of the khui_new_creds_by_type structure
+ that was added for this credentials type. */
+ return KHM_ERROR_SUCCESS;
+}
+
+/* Handler for KMSG_CRED_DIALOG_NEW_IDENTITY */
+/* Not a message sent out by NetIDMgr. See documentation of
+ KMSG_CRED_DIALOG_NEW_IDENTITY */
+khm_int32
+handle_kmsg_cred_dialog_new_identity(khm_ui_4 uparam,
+ void * vparam) {
+ /* TODO: Handle this message */
+ return KHM_ERROR_SUCCESS;
+}
+
+/* Handler for KMSG_CRED_DIALOG_NEW_OPTIONS */
+/* Not a message sent out by NetIDMgr. See documentation of
+ KMSG_CRED_DIALOG_NEW_OPTIONS */
+khm_int32
+handle_kmsg_cred_dialog_new_options(khm_ui_4 uparam,
+ void * vparam) {
+ /* TODO: Handle this message */
+ return KHM_ERROR_SUCCESS;
+}
+
+/* Handler for KMSG_CRED_PROCESS */
+khm_int32
+handle_kmsg_cred_process(khui_new_creds * nc) {
+ /* TODO: Handle this message */
+
+ /* This is where the credentials acquisition should be performed
+ as determined by the UI. Note that this message is sent even
+ when the user clicks 'cancel'. The value of nc->result should
+ be checked before performing any credentials acquisition. If
+ the value is KHUI_NC_RESULT_CANCEL, then no credentials should
+ be acquired. Otherwise, the value would be
+ KHUI_NC_RESULT_PROCESS. */
+
+ return KHM_ERROR_SUCCESS;
+}
+
+/* Handler for KMSG_CRED_END */
+khm_int32
+handle_kmsg_cred_end(khui_new_creds * nc) {
+
+ khui_new_creds_by_type * nct = NULL;
+
+ /* TODO: Perform any additional uninitialization as needed. */
+
+ khui_cw_find_type(nc, credtype_id, &nct);
+
+ if (nct) {
+
+ khui_cw_del_type(nc, credtype_id);
+
+ if (nct->name)
+ free(nct->name);
+ if (nct->credtext)
+ free(nct->credtext);
+
+ free(nct);
+
+ }
+
+ return KHM_ERROR_SUCCESS;
+}
+
+/* Handler for KMSG_CRED_IMPORT */
+khm_int32
+handle_kmsg_cred_import(void) {
+
+ /* TODO: Handle this message */
+
+ return KHM_ERROR_SUCCESS;
+}
+
+
+/******************************************************
+ Dispatch each message to individual handlers above.
+ */
+khm_int32 KHMAPI
+handle_cred_acq_msg(khm_int32 msg_type,
+ khm_int32 msg_subtype,
+ khm_ui_4 uparam,
+ void * vparam) {
+
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+
+ switch(msg_subtype) {
+ case KMSG_CRED_NEW_CREDS:
+ return handle_kmsg_cred_new_creds((khui_new_creds *) vparam);
+
+ case KMSG_CRED_RENEW_CREDS:
+ return handle_kmsg_cred_renew_creds((khui_new_creds *) vparam);
+
+ case KMSG_CRED_DIALOG_PRESTART:
+ return handle_kmsg_cred_dialog_prestart((khui_new_creds *) vparam);
+
+ case KMSG_CRED_PROCESS:
+ return handle_kmsg_cred_process((khui_new_creds *) vparam);
+
+ case KMSG_CRED_DIALOG_NEW_IDENTITY:
+ return handle_kmsg_cred_dialog_new_identity(uparam, vparam);
+
+ case KMSG_CRED_DIALOG_NEW_OPTIONS:
+ return handle_kmsg_cred_dialog_new_options(uparam, vparam);
+
+ case KMSG_CRED_END:
+ return handle_kmsg_cred_end((khui_new_creds *) vparam);
+
+ case KMSG_CRED_IMPORT:
+ return handle_kmsg_cred_import();
+ }
+
+ return rv;
+}
diff --git a/src/windows/identity/sample/templates/credprov/credprov.h b/src/windows/identity/sample/templates/credprov/credprov.h
index 1851eaa4b4..14670934d4 100644
--- a/src/windows/identity/sample/templates/credprov/credprov.h
+++ b/src/windows/identity/sample/templates/credprov/credprov.h
@@ -1,176 +1,176 @@
-/*
- * Copyright (c) 2006 Secure Endpoints Inc.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-/* only include this header file once */
-#pragma once
-
-#ifndef _UNICODE
-#ifndef RC_INVOKED
-/* This template relies on _UNICODE being defined to call the correct
- APIs. */
-#error This template needs to be compiled with _UNICODE
-#endif
-#endif
-
-/* Pull in configuration macros from the Makefile */
-#include "credacq_config.h"
-
-/* declare a few macros about our plugin */
-
-/* The following macro will be used throughout the template to refer
- to the name of the plugin. The macro is actually defined the
- Makefile generated configuration header file. Modify the
- PLUGINNAME Makefile macro.*/
-#ifndef MYPLUGIN_NAME
-#error MYPLUGIN_NAME not defined
-#endif
-
-/* Also define the unicde equivalent of the name. In general strings
- in NetIDMgr are unicode. */
-#define MYPLUGIN_NAMEW _T(MYPLUGIN_NAME)
-
-/* The name of the module. This is distinct from the name of the
- plugin for several reasons. One of which is that a single module
- can provide multiple plugins. Also, having a module name distinct
- from a plugin name allows multiple vendors to provide the same
- plugin. For example, the module name for the MIT Kerberos 5 plugin
- is MITKrb5 while the plugin name is Krb5Cred. The macro is
- actually defined in the Makefile generated configuration header
- file. Modify the MODULENAME Makefile macro.*/
-#ifndef MYMODULE_NAME
-#error MYMODULE_NAME not defined
-#endif
-
-#define MYMODULE_NAMEW _T(MYMODULE_NAME)
-
-/* When logging events from our plugin, the event logging API can
- optionally take a facility name to provide a friendly label to
- identify where each event came from. We will default to the plugin
- name, although it can be anything. */
-#define MYPLUGIN_FACILITYW MYPLUGIN_NAMEW
-
-/* Base name of the DLL that will be providing the plugin. We use it
- to construct names of the DLLs that will contain localized
- resources. This is defined in the Makefile and fed in to the build
- through there. The macro to change in the Makefile is
- DLLBASENAME. */
-#ifndef MYPLUGIN_DLLBASE
-#error MYPLUGIN_DLLBASE Not defined!
-#endif
-
-#define MYPLUGIN_DLLBASEW _T(MYPLUGIN_DLLBASE)
-
-/* Name of the credentials type that will be registered by the plugin.
- This macro is actually defined in the Makefile generated
- configuration header file. Change the CREDTYPENAME macro in the
- Makefile. */
-#ifndef MYCREDTYPE_NAME
-#error MYCREDTYPE_NAME not defined
-#endif
-
-#define MYCREDTYPE_NAMEW _T(MYCREDTYPE_NAME)
-
-/* Configuration node names. We just concatenate a few strings
- together, although you should feel free to completely define your
- own. */
-
-#define CONFIGNODE_MAIN MYCREDTYPE_NAMEW L"Config"
-#define CONFIGNODE_ALL_ID MYCREDTYPE_NAMEW L"AllIdents"
-#define CONFIGNODE_PER_ID MYCREDTYPE_NAMEW L"PerIdent"
-
-#include<windows.h>
-/* include the standard NetIDMgr header files */
-#include<netidmgr.h>
-#include<tchar.h>
-
-/* declarations for language resources */
-#include "langres.h"
-
-#ifndef NOSTRSAFE
-#include<strsafe.h>
-#endif
-
-/***************************************************
- Externals
-***************************************************/
-
-extern kmm_module h_khModule;
-extern HINSTANCE hInstance;
-extern HMODULE hResModule;
-
-extern const wchar_t * my_facility;
-
-extern khm_int32 credtype_id;
-
-/* Function declarations */
-
-/* in plugin.c */
-khm_int32 KHMAPI
-plugin_msg_proc(khm_int32 msg_type,
- khm_int32 msg_subtype,
- khm_ui_4 uparam,
- void * vparam);
-
-/* in credtype.c */
-khm_int32 KHMAPI
-cred_is_equal(khm_handle cred1,
- khm_handle cred2,
- void * rock);
-
-/* in credacq.c */
-khm_int32 KHMAPI
-handle_cred_acq_msg(khm_int32 msg_type,
- khm_int32 msg_subtype,
- khm_ui_4 uparam,
- void * vparam);
-
-/* in proppage.c */
-INT_PTR CALLBACK
-pp_cred_dlg_proc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam);
-
-/* in config_id.c */
-INT_PTR CALLBACK
-config_id_dlgproc(HWND hwndDlg,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam);
-
-/* in config_ids.c */
-INT_PTR CALLBACK
-config_ids_dlgproc(HWND hwndDlg,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam);
-
-/* in config_main.c */
-INT_PTR CALLBACK
-config_dlgproc(HWND hwndDlg,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam);
+/*
+ * Copyright (c) 2006 Secure Endpoints Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+/* only include this header file once */
+#pragma once
+
+#ifndef _UNICODE
+#ifndef RC_INVOKED
+/* This template relies on _UNICODE being defined to call the correct
+ APIs. */
+#error This template needs to be compiled with _UNICODE
+#endif
+#endif
+
+/* Pull in configuration macros from the Makefile */
+#include "credacq_config.h"
+
+/* declare a few macros about our plugin */
+
+/* The following macro will be used throughout the template to refer
+ to the name of the plugin. The macro is actually defined the
+ Makefile generated configuration header file. Modify the
+ PLUGINNAME Makefile macro.*/
+#ifndef MYPLUGIN_NAME
+#error MYPLUGIN_NAME not defined
+#endif
+
+/* Also define the unicde equivalent of the name. In general strings
+ in NetIDMgr are unicode. */
+#define MYPLUGIN_NAMEW _T(MYPLUGIN_NAME)
+
+/* The name of the module. This is distinct from the name of the
+ plugin for several reasons. One of which is that a single module
+ can provide multiple plugins. Also, having a module name distinct
+ from a plugin name allows multiple vendors to provide the same
+ plugin. For example, the module name for the MIT Kerberos 5 plugin
+ is MITKrb5 while the plugin name is Krb5Cred. The macro is
+ actually defined in the Makefile generated configuration header
+ file. Modify the MODULENAME Makefile macro.*/
+#ifndef MYMODULE_NAME
+#error MYMODULE_NAME not defined
+#endif
+
+#define MYMODULE_NAMEW _T(MYMODULE_NAME)
+
+/* When logging events from our plugin, the event logging API can
+ optionally take a facility name to provide a friendly label to
+ identify where each event came from. We will default to the plugin
+ name, although it can be anything. */
+#define MYPLUGIN_FACILITYW MYPLUGIN_NAMEW
+
+/* Base name of the DLL that will be providing the plugin. We use it
+ to construct names of the DLLs that will contain localized
+ resources. This is defined in the Makefile and fed in to the build
+ through there. The macro to change in the Makefile is
+ DLLBASENAME. */
+#ifndef MYPLUGIN_DLLBASE
+#error MYPLUGIN_DLLBASE Not defined!
+#endif
+
+#define MYPLUGIN_DLLBASEW _T(MYPLUGIN_DLLBASE)
+
+/* Name of the credentials type that will be registered by the plugin.
+ This macro is actually defined in the Makefile generated
+ configuration header file. Change the CREDTYPENAME macro in the
+ Makefile. */
+#ifndef MYCREDTYPE_NAME
+#error MYCREDTYPE_NAME not defined
+#endif
+
+#define MYCREDTYPE_NAMEW _T(MYCREDTYPE_NAME)
+
+/* Configuration node names. We just concatenate a few strings
+ together, although you should feel free to completely define your
+ own. */
+
+#define CONFIGNODE_MAIN MYCREDTYPE_NAMEW L"Config"
+#define CONFIGNODE_ALL_ID MYCREDTYPE_NAMEW L"AllIdents"
+#define CONFIGNODE_PER_ID MYCREDTYPE_NAMEW L"PerIdent"
+
+#include<windows.h>
+/* include the standard NetIDMgr header files */
+#include<netidmgr.h>
+#include<tchar.h>
+
+/* declarations for language resources */
+#include "langres.h"
+
+#ifndef NOSTRSAFE
+#include<strsafe.h>
+#endif
+
+/***************************************************
+ Externals
+***************************************************/
+
+extern kmm_module h_khModule;
+extern HINSTANCE hInstance;
+extern HMODULE hResModule;
+
+extern const wchar_t * my_facility;
+
+extern khm_int32 credtype_id;
+
+/* Function declarations */
+
+/* in plugin.c */
+khm_int32 KHMAPI
+plugin_msg_proc(khm_int32 msg_type,
+ khm_int32 msg_subtype,
+ khm_ui_4 uparam,
+ void * vparam);
+
+/* in credtype.c */
+khm_int32 KHMAPI
+cred_is_equal(khm_handle cred1,
+ khm_handle cred2,
+ void * rock);
+
+/* in credacq.c */
+khm_int32 KHMAPI
+handle_cred_acq_msg(khm_int32 msg_type,
+ khm_int32 msg_subtype,
+ khm_ui_4 uparam,
+ void * vparam);
+
+/* in proppage.c */
+INT_PTR CALLBACK
+pp_cred_dlg_proc(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam);
+
+/* in config_id.c */
+INT_PTR CALLBACK
+config_id_dlgproc(HWND hwndDlg,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam);
+
+/* in config_ids.c */
+INT_PTR CALLBACK
+config_ids_dlgproc(HWND hwndDlg,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam);
+
+/* in config_main.c */
+INT_PTR CALLBACK
+config_dlgproc(HWND hwndDlg,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam);
diff --git a/src/windows/identity/sample/templates/credprov/credtype.c b/src/windows/identity/sample/templates/credprov/credtype.c
index 039c644542..cee7df19a7 100644
--- a/src/windows/identity/sample/templates/credprov/credtype.c
+++ b/src/windows/identity/sample/templates/credprov/credtype.c
@@ -1,52 +1,52 @@
-/*
- * Copyright (c) 2006 Secure Endpoints Inc.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AND
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include "credprov.h"
-
-/* Functions for handling our credentials type.
-*/
-
-khm_int32 KHMAPI
-cred_is_equal(khm_handle cred1,
- khm_handle cred2,
- void * rock) {
-
- khm_int32 result;
-
- /* TODO: Check any additional fields to determine if the two
- credentials are equal or not. */
-
- /* Note that this is actually a comparison function. It should
- return 0 if the credentials are found to be equal, and non-zero
- if they are not. We just set this to 0 if we don't need to
- check any additional fields and accept the two credentials as
- being equal. By the time this function is called, the
- identity, name and type of the credentials have already been
- found to be equal. */
- result = 0;
-
- return result;
-}
+/*
+ * Copyright (c) 2006 Secure Endpoints Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AND
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include "credprov.h"
+
+/* Functions for handling our credentials type.
+*/
+
+khm_int32 KHMAPI
+cred_is_equal(khm_handle cred1,
+ khm_handle cred2,
+ void * rock) {
+
+ khm_int32 result;
+
+ /* TODO: Check any additional fields to determine if the two
+ credentials are equal or not. */
+
+ /* Note that this is actually a comparison function. It should
+ return 0 if the credentials are found to be equal, and non-zero
+ if they are not. We just set this to 0 if we don't need to
+ check any additional fields and accept the two credentials as
+ being equal. By the time this function is called, the
+ identity, name and type of the credentials have already been
+ found to be equal. */
+ result = 0;
+
+ return result;
+}
diff --git a/src/windows/identity/sample/templates/credprov/langres.h b/src/windows/identity/sample/templates/credprov/langres.h
index 2b81c554de..962c4cb223 100644
--- a/src/windows/identity/sample/templates/credprov/langres.h
+++ b/src/windows/identity/sample/templates/credprov/langres.h
@@ -1,34 +1,34 @@
-//{{NO_DEPENDENCIES}}
-// Microsoft Visual C++ generated include file.
-// Used by C:\work\pismere\athena\auth\krb5\src\windows\identity\sample\templates\credprov\lang\en_us\langres.rc
-//
-#define IDD_PP_CRED 106
-#define IDD_PP_IDENT 107
-#define IDS_PLUGIN_DESC 109
-#define IDS_CT_SHORT_DESC 110
-#define IDI_PLUGIN 110
-#define IDS_CT_LONG_DESC 111
-#define IDD_NEW_CREDS 112
-#define IDS_NC_CT_TEMPLATE 112
-#define IDS_NC_CT_TEMPLATE_NL 113
-#define IDD_CONFIG 113
-#define IDS_GEN_NONE 114
-#define IDD_CONFIG_ID 114
-#define IDS_CFG_SHORT_DESC 115
-#define IDD_CONFIG_IDS 115
-#define IDS_CFG_LONG_DESC 116
-#define IDS_CFG_IDS_SHORT_DESC 117
-#define IDS_CFG_IDS_LONG_DESC 118
-#define IDS_CFG_ID_SHORT_DESC 119
-#define IDS_CFG_ID_LONG_DESC 120
-
-// Next default values for new objects
-//
-#ifdef APSTUDIO_INVOKED
-#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE 116
-#define _APS_NEXT_COMMAND_VALUE 40001
-#define _APS_NEXT_CONTROL_VALUE 1039
-#define _APS_NEXT_SYMED_VALUE 101
-#endif
-#endif
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by C:\work\pismere\athena\auth\krb5\src\windows\identity\sample\templates\credprov\lang\en_us\langres.rc
+//
+#define IDD_PP_CRED 106
+#define IDD_PP_IDENT 107
+#define IDS_PLUGIN_DESC 109
+#define IDS_CT_SHORT_DESC 110
+#define IDI_PLUGIN 110
+#define IDS_CT_LONG_DESC 111
+#define IDD_NEW_CREDS 112
+#define IDS_NC_CT_TEMPLATE 112
+#define IDS_NC_CT_TEMPLATE_NL 113
+#define IDD_CONFIG 113
+#define IDS_GEN_NONE 114
+#define IDD_CONFIG_ID 114
+#define IDS_CFG_SHORT_DESC 115
+#define IDD_CONFIG_IDS 115
+#define IDS_CFG_LONG_DESC 116
+#define IDS_CFG_IDS_SHORT_DESC 117
+#define IDS_CFG_IDS_LONG_DESC 118
+#define IDS_CFG_ID_SHORT_DESC 119
+#define IDS_CFG_ID_LONG_DESC 120
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 116
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1039
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/src/windows/identity/sample/templates/credprov/main.c b/src/windows/identity/sample/templates/credprov/main.c
index 7a50205739..07da40d57c 100644
--- a/src/windows/identity/sample/templates/credprov/main.c
+++ b/src/windows/identity/sample/templates/credprov/main.c
@@ -1,171 +1,171 @@
-/*
- * Copyright (c) 2006 Secure Endpoints Inc.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include "credprov.h"
-
-/* This file provides the entry points for the module. The purpose of
- each entry point is explained below.
-*/
-
-kmm_module h_khModule; /* KMM's handle to this module */
-HINSTANCE hInstance; /* handle to our DLL */
-HMODULE hResModule; /* handle to DLL containing language specific resources */
-
-const wchar_t * my_facility = MYPLUGIN_FACILITYW;
-
-/* locales and n_locales are used to provide information to NetIDMgr
- about the locales that we support. Each locale that is supported
- is represented by a single line below. NetIDMgr will pick a
- suitable locale from this list as described in the documentation
- for kmm_set_locale_info(). */
-kmm_module_locale locales[] = {
-
- /* there needs to be at least one language that is supported.
- Here we declare that to be US English, and make it the
- default. */
- LOCALE_DEF(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),
- MYPLUGIN_DLLBASEW L"_en_us.dll", /* this is the name of
- the DLL. We paste a
- trailer to basename
- of the DLL. This
- DLL should reside in
- the same directory
- as the plugin
- DLL. */
- KMM_MLOC_FLAG_DEFAULT)
-};
-int n_locales = ARRAYLENGTH(locales);
-
-/*******************************************************************
- init_module
- *****************************************************************
-
- This is the entry point for the module. Each module can provide
- multiple plugins and each plugin will need a separate entry point.
- Generally, the module entry point will set up localized resources
- and register the plugins.
-
-*/
-KHMEXP khm_int32 KHMAPI init_module(kmm_module h_module) {
-
- khm_int32 rv = KHM_ERROR_SUCCESS;
- kmm_plugin_reg pi;
- wchar_t description[KMM_MAXCCH_DESC];
- int t;
-
- h_khModule = h_module;
-
- rv = kmm_set_locale_info(h_module, locales, n_locales);
- if(KHM_SUCCEEDED(rv)) {
- /* if the call succeeded, then NetIDMgr has picked a localized
- resource DLL for us to use. */
- hResModule = kmm_get_resource_hmodule(h_module);
- } else
- goto _exit;
-
- /* TODO: Perform any other required initialization operations. */
-
- /* register our plugin */
- ZeroMemory(&pi, sizeof(pi));
-
- pi.name = MYPLUGIN_NAMEW; /* name of the plugin */
- pi.type = KHM_PITYPE_CRED; /* type. This is a credentials
- provider. Setting this type has
- the effect of having the plugin
- entrypoint being automatically
- subscribed to credentials provider
- messages. */
-
- /* An icon is optional, but we provide one anyway. */
- pi.icon = LoadImage(hResModule, MAKEINTRESOURCE(IDI_PLUGIN),
- IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR | LR_DEFAULTSIZE);
- pi.flags = 0;
- pi.msg_proc = plugin_msg_proc;
- pi.description = description;
- pi.dependencies = NULL;
- t = LoadString(hResModule, IDS_PLUGIN_DESC,
- description, ARRAYLENGTH(description));
- if (!t)
- description[0] = L'\0';
- else
- description[ARRAYLENGTH(description) - 1] = L'\0';
-
- rv = kmm_provide_plugin(h_module, &pi);
-
- /* TODO: register any additional plugins */
-
- /* Returning a successful code (KHM_ERROR_SUCCESS) will cause the
- plugins to be initialized. If no plugin is successfully
- registered while processing init_module or if a code other than
- KHM_ERROR_SUCCESS is returned, the module will be immediately
- unloaded. */
-
- _exit:
- return rv;
-}
-
-/**********************************************************
- Exit module
- ********************************************************
-
- Called by the NetIDMgr module manager when unloading the module.
- This will get called even if the module is being unloaded due to an
- error code returned by init_module(). This callback is required. */
-KHMEXP khm_int32 KHMAPI exit_module(kmm_module h_module) {
-
- /* Unregistering the plugin is not required at this point. */
-
- /* TODO: Perform any other required cleanup here. */
-
- return KHM_ERROR_SUCCESS; /* the return code is ignored */
-}
-
-/* General DLL initialization. It is advisable to not do anything
- here and also keep in mind that the plugin will be loaded at a time
- where some threads have already started. So DLL_THREAD_ATTACH will
- not fire for every thread. In addition, the plugin will be
- unloaded before the application and all the threads terminate. */
-BOOL WINAPI DllMain(HINSTANCE hinstDLL,
- DWORD fdwReason,
- LPVOID lpvReserved)
-{
- switch(fdwReason) {
- case DLL_PROCESS_ATTACH:
- hInstance = hinstDLL;
- break;
-
- case DLL_PROCESS_DETACH:
- break;
-
- case DLL_THREAD_ATTACH:
- break;
-
- case DLL_THREAD_DETACH:
- break;
- }
-
- return TRUE;
-}
+/*
+ * Copyright (c) 2006 Secure Endpoints Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include "credprov.h"
+
+/* This file provides the entry points for the module. The purpose of
+ each entry point is explained below.
+*/
+
+kmm_module h_khModule; /* KMM's handle to this module */
+HINSTANCE hInstance; /* handle to our DLL */
+HMODULE hResModule; /* handle to DLL containing language specific resources */
+
+const wchar_t * my_facility = MYPLUGIN_FACILITYW;
+
+/* locales and n_locales are used to provide information to NetIDMgr
+ about the locales that we support. Each locale that is supported
+ is represented by a single line below. NetIDMgr will pick a
+ suitable locale from this list as described in the documentation
+ for kmm_set_locale_info(). */
+kmm_module_locale locales[] = {
+
+ /* there needs to be at least one language that is supported.
+ Here we declare that to be US English, and make it the
+ default. */
+ LOCALE_DEF(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),
+ MYPLUGIN_DLLBASEW L"_en_us.dll", /* this is the name of
+ the DLL. We paste a
+ trailer to basename
+ of the DLL. This
+ DLL should reside in
+ the same directory
+ as the plugin
+ DLL. */
+ KMM_MLOC_FLAG_DEFAULT)
+};
+int n_locales = ARRAYLENGTH(locales);
+
+/*******************************************************************
+ init_module
+ *****************************************************************
+
+ This is the entry point for the module. Each module can provide
+ multiple plugins and each plugin will need a separate entry point.
+ Generally, the module entry point will set up localized resources
+ and register the plugins.
+
+*/
+KHMEXP khm_int32 KHMAPI init_module(kmm_module h_module) {
+
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+ kmm_plugin_reg pi;
+ wchar_t description[KMM_MAXCCH_DESC];
+ int t;
+
+ h_khModule = h_module;
+
+ rv = kmm_set_locale_info(h_module, locales, n_locales);
+ if(KHM_SUCCEEDED(rv)) {
+ /* if the call succeeded, then NetIDMgr has picked a localized
+ resource DLL for us to use. */
+ hResModule = kmm_get_resource_hmodule(h_module);
+ } else
+ goto _exit;
+
+ /* TODO: Perform any other required initialization operations. */
+
+ /* register our plugin */
+ ZeroMemory(&pi, sizeof(pi));
+
+ pi.name = MYPLUGIN_NAMEW; /* name of the plugin */
+ pi.type = KHM_PITYPE_CRED; /* type. This is a credentials
+ provider. Setting this type has
+ the effect of having the plugin
+ entrypoint being automatically
+ subscribed to credentials provider
+ messages. */
+
+ /* An icon is optional, but we provide one anyway. */
+ pi.icon = LoadImage(hResModule, MAKEINTRESOURCE(IDI_PLUGIN),
+ IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR | LR_DEFAULTSIZE);
+ pi.flags = 0;
+ pi.msg_proc = plugin_msg_proc;
+ pi.description = description;
+ pi.dependencies = NULL;
+ t = LoadString(hResModule, IDS_PLUGIN_DESC,
+ description, ARRAYLENGTH(description));
+ if (!t)
+ description[0] = L'\0';
+ else
+ description[ARRAYLENGTH(description) - 1] = L'\0';
+
+ rv = kmm_provide_plugin(h_module, &pi);
+
+ /* TODO: register any additional plugins */
+
+ /* Returning a successful code (KHM_ERROR_SUCCESS) will cause the
+ plugins to be initialized. If no plugin is successfully
+ registered while processing init_module or if a code other than
+ KHM_ERROR_SUCCESS is returned, the module will be immediately
+ unloaded. */
+
+ _exit:
+ return rv;
+}
+
+/**********************************************************
+ Exit module
+ ********************************************************
+
+ Called by the NetIDMgr module manager when unloading the module.
+ This will get called even if the module is being unloaded due to an
+ error code returned by init_module(). This callback is required. */
+KHMEXP khm_int32 KHMAPI exit_module(kmm_module h_module) {
+
+ /* Unregistering the plugin is not required at this point. */
+
+ /* TODO: Perform any other required cleanup here. */
+
+ return KHM_ERROR_SUCCESS; /* the return code is ignored */
+}
+
+/* General DLL initialization. It is advisable to not do anything
+ here and also keep in mind that the plugin will be loaded at a time
+ where some threads have already started. So DLL_THREAD_ATTACH will
+ not fire for every thread. In addition, the plugin will be
+ unloaded before the application and all the threads terminate. */
+BOOL WINAPI DllMain(HINSTANCE hinstDLL,
+ DWORD fdwReason,
+ LPVOID lpvReserved)
+{
+ switch(fdwReason) {
+ case DLL_PROCESS_ATTACH:
+ hInstance = hinstDLL;
+ break;
+
+ case DLL_PROCESS_DETACH:
+ break;
+
+ case DLL_THREAD_ATTACH:
+ break;
+
+ case DLL_THREAD_DETACH:
+ break;
+ }
+
+ return TRUE;
+}
diff --git a/src/windows/identity/sample/templates/credprov/plugin.c b/src/windows/identity/sample/templates/credprov/plugin.c
index 31c9626a55..9b1b0ce94a 100644
--- a/src/windows/identity/sample/templates/credprov/plugin.c
+++ b/src/windows/identity/sample/templates/credprov/plugin.c
@@ -1,382 +1,382 @@
-/*
- * Copyright (c) 2006 Secure Endpoints Inc.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include "credprov.h"
-#include<assert.h>
-
-/* This file provides the message processing function and the support
- routines for implementing our plugin. Note that some of the
- message processing routines have been moved to other source files
- based on their use.
-*/
-
-khm_int32 credtype_id = KCDB_CREDTYPE_INVALID;
-khm_handle g_credset = NULL;
-
-/* Handler for system messages. The only two we handle are
- KMSG_SYSTEM_INIT and KMSG_SYSTEM_EXIT. */
-khm_int32 KHMAPI
-handle_kmsg_system(khm_int32 msg_type,
- khm_int32 msg_subtype,
- khm_ui_4 uparam,
- void * vparam) {
- khm_int32 rv = KHM_ERROR_SUCCESS;
-
- switch (msg_subtype) {
-
- /* This is the first message that will be received by a
- plugin. We use it to perform initialization operations
- such as registering any credential types, data types and
- attributes. */
- case KMSG_SYSTEM_INIT:
- {
- kcdb_credtype ct;
- wchar_t short_desc[KCDB_MAXCCH_SHORT_DESC];
- wchar_t long_desc[KCDB_MAXCCH_LONG_DESC];
- khui_config_node cnode;
- khui_config_node_reg creg;
-
- /* First and foremost, we need to register a credential
- type. */
- ZeroMemory(&ct, sizeof(ct));
- ct.id = KCDB_CREDTYPE_AUTO;
- ct.name = MYCREDTYPE_NAMEW;
-
- short_desc[0] = L'\0';
- LoadString(hResModule, IDS_CT_SHORT_DESC,
- short_desc, ARRAYLENGTH(short_desc));
-
- long_desc[0] = L'\0';
- LoadString(hResModule, IDS_CT_LONG_DESC,
- long_desc, ARRAYLENGTH(long_desc));
-
- ct.icon = NULL; /* We skip the icon for now, but you
- can assign a handle to an icon
- here. The icon will be used to
- represent the credentials type.*/
-
- kmq_create_subscription(plugin_msg_proc, &ct.sub);
-
- ct.is_equal = cred_is_equal;
-
- rv = kcdb_credtype_register(&ct, &credtype_id);
-
- /* We create a global credential set that we use in the
- plug-in thread. This alleviates the need to create one
- everytime we need one. Keep in mind that this should
- only be used in the plug-in thread and should not be
- touched from the UI thread or any other thread. */
- kcdb_credset_create(&g_credset);
-
- /* TODO: Perform additional initialization operations. */
-
- /* TODO: Also list out the credentials of this type that
- already exist. */
-
- /* Now we register our configuration panels. */
-
-
- /* This configuration panel is the one that controls
- general options. We leave the identity specific and
- identity defaults for other configuration panels. */
-
- ZeroMemory(&creg, sizeof(creg));
-
- short_desc[0] = L'\0';
-
- LoadString(hResModule, IDS_CFG_SHORT_DESC,
- short_desc, ARRAYLENGTH(short_desc));
-
- long_desc[0] = L'\0';
-
- LoadString(hResModule, IDS_CFG_LONG_DESC,
- long_desc, ARRAYLENGTH(long_desc));
-
- creg.name = CONFIGNODE_MAIN;
- creg.short_desc = short_desc;
- creg.long_desc = long_desc;
- creg.h_module = hResModule;
- creg.dlg_template = MAKEINTRESOURCE(IDD_CONFIG);
- creg.dlg_proc = config_dlgproc;
- creg.flags = 0;
-
- khui_cfg_register(NULL, &creg);
-
- /* Now we do the identity specific and identity default
- configuration panels. "KhmIdentities" is a predefined
- configuration node under which all the identity spcific
- configuration is managed. */
-
- if (KHM_FAILED(khui_cfg_open(NULL, L"KhmIdentities", &cnode))) {
- /* this should always work */
- assert(FALSE);
- rv = KHM_ERROR_NOT_FOUND;
- break;
- }
-
- /* First the tab panel for defaults for all identities */
-
- ZeroMemory(&creg, sizeof(creg));
-
- short_desc[0] = L'\0';
- LoadString(hResModule, IDS_CFG_IDS_SHORT_DESC,
- short_desc, ARRAYLENGTH(short_desc));
- long_desc[0] = L'\0';
- LoadString(hResModule, IDS_CFG_IDS_LONG_DESC,
- long_desc, ARRAYLENGTH(long_desc));
-
- creg.name = CONFIGNODE_ALL_ID;
- creg.short_desc = short_desc;
- creg.long_desc = long_desc;
- creg.h_module = hResModule;
- creg.dlg_template = MAKEINTRESOURCE(IDD_CONFIG_IDS);
- creg.dlg_proc = config_ids_dlgproc;
- creg.flags = KHUI_CNFLAG_SUBPANEL;
-
- khui_cfg_register(cnode, &creg);
-
- /* Now the panel for per identity configuration */
-
- ZeroMemory(&creg, sizeof(creg));
-
- short_desc[0] = L'\0';
- LoadString(hResModule, IDS_CFG_ID_SHORT_DESC,
- short_desc, ARRAYLENGTH(short_desc));
- long_desc[0] = L'\0';
- LoadString(hResModule, IDS_CFG_ID_LONG_DESC,
- long_desc, ARRAYLENGTH(long_desc));
-
- creg.name = CONFIGNODE_PER_ID;
- creg.short_desc = short_desc;
- creg.long_desc = long_desc;
- creg.h_module = hResModule;
- creg.dlg_template = MAKEINTRESOURCE(IDD_CONFIG_ID);
- creg.dlg_proc = config_id_dlgproc;
- creg.flags = KHUI_CNFLAG_SUBPANEL | KHUI_CNFLAG_PLURAL;
-
- khui_cfg_register(cnode, &creg);
-
- khui_cfg_release(cnode);
- }
- break;
-
- /* This is the last message that will be received by the
- plugin. */
- case KMSG_SYSTEM_EXIT:
- {
- khui_config_node cnode;
- khui_config_node cn_idents;
-
- /* It should not be assumed that initialization of the
- plugin went well at this point since we receive a
- KMSG_SYSTEM_EXIT even if the initialization failed. */
-
- if (credtype_id != KCDB_CREDTYPE_INVALID) {
- kcdb_credtype_unregister(credtype_id);
- credtype_id = KCDB_CREDTYPE_INVALID;
- }
-
- if (g_credset) {
- kcdb_credset_delete(g_credset);
- g_credset = NULL;
- }
-
- /* Now unregister any configuration nodes we registered. */
-
- if (KHM_SUCCEEDED(khui_cfg_open(NULL, CONFIGNODE_MAIN, &cnode))) {
- khui_cfg_remove(cnode);
- khui_cfg_release(cnode);
- }
-
- if (KHM_SUCCEEDED(khui_cfg_open(NULL, L"KhmIdentities", &cn_idents))) {
- if (KHM_SUCCEEDED(khui_cfg_open(cn_idents,
- CONFIGNODE_ALL_ID,
- &cnode))) {
- khui_cfg_remove(cnode);
- khui_cfg_release(cnode);
- }
-
- if (KHM_SUCCEEDED(khui_cfg_open(cn_idents,
- CONFIGNODE_PER_ID,
- &cnode))) {
- khui_cfg_remove(cnode);
- khui_cfg_release(cnode);
- }
-
- khui_cfg_release(cn_idents);
- }
-
- /* TODO: Perform additional uninitialization
- operations. */
- }
- break;
- }
-
- return rv;
-}
-
-/* Handler for credentials the refresh message. */
-khm_int32
-handle_kmsg_cred_refresh(void) {
- /* TODO: Re-enumerate the credentials of our credentials type */
-
- /*
- Re-enumerating credentials would look something like this:
-
- - flush all credentials from g_credset (kcdb_credset_flush())
-
- - list out the credentials and add them to g_credset
-
- - collect the credentials from g_credset to the root credentials
- set. (kcdb_credset_collect())
-
- Note that when listing credentials, each credential must be
- populated with enough information to locate the actual
- credential at a later time.
- */
-
- return KHM_ERROR_SUCCESS;
-}
-
-/* Handler for destroying credentials */
-khm_int32
-handle_kmsg_cred_destroy_creds(khui_action_context * ctx) {
- /* TODO: Destroy credentials of our type as specified by the
- action context passed in through vparam. */
-
- /* The credential set in ctx->credset contains the credentials
- that are to be destroyed. */
-
- return KHM_ERROR_SUCCESS;
-}
-
-/* Begin a property sheet */
-khm_int32
-handle_kmsg_cred_pp_begin(khui_property_sheet * ps) {
-
- /* TODO: Provide the information necessary to show a property
- page for a credentials belonging to our credential type. */
-
- PROPSHEETPAGE *p;
-
- if (ps->credtype == credtype_id &&
- ps->cred) {
- /* We have been requested to show a property sheet for one of
- our credentials. */
- p = malloc(sizeof(*p));
- ZeroMemory(p, sizeof(*p));
-
- p->dwSize = sizeof(*p);
- p->dwFlags = 0;
- p->hInstance = hResModule;
- p->pszTemplate = MAKEINTRESOURCE(IDD_PP_CRED);
- p->pfnDlgProc = pp_cred_dlg_proc;
- p->lParam = (LPARAM) ps;
- khui_ps_add_page(ps, credtype_id, 0, p, NULL);
- }
-
- return KHM_ERROR_SUCCESS;
-}
-
-/* End a property sheet */
-khm_int32
-handle_kmsg_cred_pp_end(khui_property_sheet * ps) {
- /* TODO: Handle the end of a property sheet. */
-
- khui_property_page * p = NULL;
-
- khui_ps_find_page(ps, credtype_id, &p);
- if (p) {
- if (p->p_page)
- free(p->p_page);
- p->p_page = NULL;
- }
-
- return KHM_ERROR_SUCCESS;
-}
-
-/* IP address change notification */
-khm_int32
-handle_kmsg_cred_addr_change(void) {
- /* TODO: Handle this message. */
-
- return KHM_ERROR_SUCCESS;
-}
-
-/* Message dispatcher for credentials messages. */
-khm_int32 KHMAPI
-handle_kmsg_cred(khm_int32 msg_type,
- khm_int32 msg_subtype,
- khm_ui_4 uparam,
- void * vparam) {
- khm_int32 rv = KHM_ERROR_SUCCESS;
-
- switch(msg_subtype) {
- case KMSG_CRED_REFRESH:
- return handle_kmsg_cred_refresh();
-
- case KMSG_CRED_DESTROY_CREDS:
- return handle_kmsg_cred_destroy_creds((khui_action_context *) vparam);
-
- case KMSG_CRED_PP_BEGIN:
- return handle_kmsg_cred_pp_begin((khui_property_sheet *) vparam);
-
- case KMSG_CRED_PP_END:
- return handle_kmsg_cred_pp_end((khui_property_sheet *) vparam);
-
- case KMSG_CRED_ADDR_CHANGE:
- return handle_kmsg_cred_addr_change();
-
- default:
- /* Credentials acquisition messages are all handled in a
- different source file. */
- if (IS_CRED_ACQ_MSG(msg_subtype))
- return handle_cred_acq_msg(msg_type, msg_subtype,
- uparam, vparam);
- }
-
- return rv;
-}
-
-
-/* This is the main message handler for our plugin. All the plugin
- messages end up here where we either handle it directly or dispatch
- it to other handlers. */
-khm_int32 KHMAPI plugin_msg_proc(khm_int32 msg_type,
- khm_int32 msg_subtype,
- khm_ui_4 uparam,
- void * vparam) {
-
- switch(msg_type) {
- case KMSG_SYSTEM:
- return handle_kmsg_system(msg_type, msg_subtype, uparam, vparam);
-
- case KMSG_CRED:
- return handle_kmsg_cred(msg_type, msg_subtype, uparam, vparam);
- }
-
- return KHM_ERROR_SUCCESS;
-}
+/*
+ * Copyright (c) 2006 Secure Endpoints Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include "credprov.h"
+#include<assert.h>
+
+/* This file provides the message processing function and the support
+ routines for implementing our plugin. Note that some of the
+ message processing routines have been moved to other source files
+ based on their use.
+*/
+
+khm_int32 credtype_id = KCDB_CREDTYPE_INVALID;
+khm_handle g_credset = NULL;
+
+/* Handler for system messages. The only two we handle are
+ KMSG_SYSTEM_INIT and KMSG_SYSTEM_EXIT. */
+khm_int32 KHMAPI
+handle_kmsg_system(khm_int32 msg_type,
+ khm_int32 msg_subtype,
+ khm_ui_4 uparam,
+ void * vparam) {
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+
+ switch (msg_subtype) {
+
+ /* This is the first message that will be received by a
+ plugin. We use it to perform initialization operations
+ such as registering any credential types, data types and
+ attributes. */
+ case KMSG_SYSTEM_INIT:
+ {
+ kcdb_credtype ct;
+ wchar_t short_desc[KCDB_MAXCCH_SHORT_DESC];
+ wchar_t long_desc[KCDB_MAXCCH_LONG_DESC];
+ khui_config_node cnode;
+ khui_config_node_reg creg;
+
+ /* First and foremost, we need to register a credential
+ type. */
+ ZeroMemory(&ct, sizeof(ct));
+ ct.id = KCDB_CREDTYPE_AUTO;
+ ct.name = MYCREDTYPE_NAMEW;
+
+ short_desc[0] = L'\0';
+ LoadString(hResModule, IDS_CT_SHORT_DESC,
+ short_desc, ARRAYLENGTH(short_desc));
+
+ long_desc[0] = L'\0';
+ LoadString(hResModule, IDS_CT_LONG_DESC,
+ long_desc, ARRAYLENGTH(long_desc));
+
+ ct.icon = NULL; /* We skip the icon for now, but you
+ can assign a handle to an icon
+ here. The icon will be used to
+ represent the credentials type.*/
+
+ kmq_create_subscription(plugin_msg_proc, &ct.sub);
+
+ ct.is_equal = cred_is_equal;
+
+ rv = kcdb_credtype_register(&ct, &credtype_id);
+
+ /* We create a global credential set that we use in the
+ plug-in thread. This alleviates the need to create one
+ everytime we need one. Keep in mind that this should
+ only be used in the plug-in thread and should not be
+ touched from the UI thread or any other thread. */
+ kcdb_credset_create(&g_credset);
+
+ /* TODO: Perform additional initialization operations. */
+
+ /* TODO: Also list out the credentials of this type that
+ already exist. */
+
+ /* Now we register our configuration panels. */
+
+
+ /* This configuration panel is the one that controls
+ general options. We leave the identity specific and
+ identity defaults for other configuration panels. */
+
+ ZeroMemory(&creg, sizeof(creg));
+
+ short_desc[0] = L'\0';
+
+ LoadString(hResModule, IDS_CFG_SHORT_DESC,
+ short_desc, ARRAYLENGTH(short_desc));
+
+ long_desc[0] = L'\0';
+
+ LoadString(hResModule, IDS_CFG_LONG_DESC,
+ long_desc, ARRAYLENGTH(long_desc));
+
+ creg.name = CONFIGNODE_MAIN;
+ creg.short_desc = short_desc;
+ creg.long_desc = long_desc;
+ creg.h_module = hResModule;
+ creg.dlg_template = MAKEINTRESOURCE(IDD_CONFIG);
+ creg.dlg_proc = config_dlgproc;
+ creg.flags = 0;
+
+ khui_cfg_register(NULL, &creg);
+
+ /* Now we do the identity specific and identity default
+ configuration panels. "KhmIdentities" is a predefined
+ configuration node under which all the identity spcific
+ configuration is managed. */
+
+ if (KHM_FAILED(khui_cfg_open(NULL, L"KhmIdentities", &cnode))) {
+ /* this should always work */
+ assert(FALSE);
+ rv = KHM_ERROR_NOT_FOUND;
+ break;
+ }
+
+ /* First the tab panel for defaults for all identities */
+
+ ZeroMemory(&creg, sizeof(creg));
+
+ short_desc[0] = L'\0';
+ LoadString(hResModule, IDS_CFG_IDS_SHORT_DESC,
+ short_desc, ARRAYLENGTH(short_desc));
+ long_desc[0] = L'\0';
+ LoadString(hResModule, IDS_CFG_IDS_LONG_DESC,
+ long_desc, ARRAYLENGTH(long_desc));
+
+ creg.name = CONFIGNODE_ALL_ID;
+ creg.short_desc = short_desc;
+ creg.long_desc = long_desc;
+ creg.h_module = hResModule;
+ creg.dlg_template = MAKEINTRESOURCE(IDD_CONFIG_IDS);
+ creg.dlg_proc = config_ids_dlgproc;
+ creg.flags = KHUI_CNFLAG_SUBPANEL;
+
+ khui_cfg_register(cnode, &creg);
+
+ /* Now the panel for per identity configuration */
+
+ ZeroMemory(&creg, sizeof(creg));
+
+ short_desc[0] = L'\0';
+ LoadString(hResModule, IDS_CFG_ID_SHORT_DESC,
+ short_desc, ARRAYLENGTH(short_desc));
+ long_desc[0] = L'\0';
+ LoadString(hResModule, IDS_CFG_ID_LONG_DESC,
+ long_desc, ARRAYLENGTH(long_desc));
+
+ creg.name = CONFIGNODE_PER_ID;
+ creg.short_desc = short_desc;
+ creg.long_desc = long_desc;
+ creg.h_module = hResModule;
+ creg.dlg_template = MAKEINTRESOURCE(IDD_CONFIG_ID);
+ creg.dlg_proc = config_id_dlgproc;
+ creg.flags = KHUI_CNFLAG_SUBPANEL | KHUI_CNFLAG_PLURAL;
+
+ khui_cfg_register(cnode, &creg);
+
+ khui_cfg_release(cnode);
+ }
+ break;
+
+ /* This is the last message that will be received by the
+ plugin. */
+ case KMSG_SYSTEM_EXIT:
+ {
+ khui_config_node cnode;
+ khui_config_node cn_idents;
+
+ /* It should not be assumed that initialization of the
+ plugin went well at this point since we receive a
+ KMSG_SYSTEM_EXIT even if the initialization failed. */
+
+ if (credtype_id != KCDB_CREDTYPE_INVALID) {
+ kcdb_credtype_unregister(credtype_id);
+ credtype_id = KCDB_CREDTYPE_INVALID;
+ }
+
+ if (g_credset) {
+ kcdb_credset_delete(g_credset);
+ g_credset = NULL;
+ }
+
+ /* Now unregister any configuration nodes we registered. */
+
+ if (KHM_SUCCEEDED(khui_cfg_open(NULL, CONFIGNODE_MAIN, &cnode))) {
+ khui_cfg_remove(cnode);
+ khui_cfg_release(cnode);
+ }
+
+ if (KHM_SUCCEEDED(khui_cfg_open(NULL, L"KhmIdentities", &cn_idents))) {
+ if (KHM_SUCCEEDED(khui_cfg_open(cn_idents,
+ CONFIGNODE_ALL_ID,
+ &cnode))) {
+ khui_cfg_remove(cnode);
+ khui_cfg_release(cnode);
+ }
+
+ if (KHM_SUCCEEDED(khui_cfg_open(cn_idents,
+ CONFIGNODE_PER_ID,
+ &cnode))) {
+ khui_cfg_remove(cnode);
+ khui_cfg_release(cnode);
+ }
+
+ khui_cfg_release(cn_idents);
+ }
+
+ /* TODO: Perform additional uninitialization
+ operations. */
+ }
+ break;
+ }
+
+ return rv;
+}
+
+/* Handler for credentials the refresh message. */
+khm_int32
+handle_kmsg_cred_refresh(void) {
+ /* TODO: Re-enumerate the credentials of our credentials type */
+
+ /*
+ Re-enumerating credentials would look something like this:
+
+ - flush all credentials from g_credset (kcdb_credset_flush())
+
+ - list out the credentials and add them to g_credset
+
+ - collect the credentials from g_credset to the root credentials
+ set. (kcdb_credset_collect())
+
+ Note that when listing credentials, each credential must be
+ populated with enough information to locate the actual
+ credential at a later time.
+ */
+
+ return KHM_ERROR_SUCCESS;
+}
+
+/* Handler for destroying credentials */
+khm_int32
+handle_kmsg_cred_destroy_creds(khui_action_context * ctx) {
+ /* TODO: Destroy credentials of our type as specified by the
+ action context passed in through vparam. */
+
+ /* The credential set in ctx->credset contains the credentials
+ that are to be destroyed. */
+
+ return KHM_ERROR_SUCCESS;
+}
+
+/* Begin a property sheet */
+khm_int32
+handle_kmsg_cred_pp_begin(khui_property_sheet * ps) {
+
+ /* TODO: Provide the information necessary to show a property
+ page for a credentials belonging to our credential type. */
+
+ PROPSHEETPAGE *p;
+
+ if (ps->credtype == credtype_id &&
+ ps->cred) {
+ /* We have been requested to show a property sheet for one of
+ our credentials. */
+ p = malloc(sizeof(*p));
+ ZeroMemory(p, sizeof(*p));
+
+ p->dwSize = sizeof(*p);
+ p->dwFlags = 0;
+ p->hInstance = hResModule;
+ p->pszTemplate = MAKEINTRESOURCE(IDD_PP_CRED);
+ p->pfnDlgProc = pp_cred_dlg_proc;
+ p->lParam = (LPARAM) ps;
+ khui_ps_add_page(ps, credtype_id, 0, p, NULL);
+ }
+
+ return KHM_ERROR_SUCCESS;
+}
+
+/* End a property sheet */
+khm_int32
+handle_kmsg_cred_pp_end(khui_property_sheet * ps) {
+ /* TODO: Handle the end of a property sheet. */
+
+ khui_property_page * p = NULL;
+
+ khui_ps_find_page(ps, credtype_id, &p);
+ if (p) {
+ if (p->p_page)
+ free(p->p_page);
+ p->p_page = NULL;
+ }
+
+ return KHM_ERROR_SUCCESS;
+}
+
+/* IP address change notification */
+khm_int32
+handle_kmsg_cred_addr_change(void) {
+ /* TODO: Handle this message. */
+
+ return KHM_ERROR_SUCCESS;
+}
+
+/* Message dispatcher for credentials messages. */
+khm_int32 KHMAPI
+handle_kmsg_cred(khm_int32 msg_type,
+ khm_int32 msg_subtype,
+ khm_ui_4 uparam,
+ void * vparam) {
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+
+ switch(msg_subtype) {
+ case KMSG_CRED_REFRESH:
+ return handle_kmsg_cred_refresh();
+
+ case KMSG_CRED_DESTROY_CREDS:
+ return handle_kmsg_cred_destroy_creds((khui_action_context *) vparam);
+
+ case KMSG_CRED_PP_BEGIN:
+ return handle_kmsg_cred_pp_begin((khui_property_sheet *) vparam);
+
+ case KMSG_CRED_PP_END:
+ return handle_kmsg_cred_pp_end((khui_property_sheet *) vparam);
+
+ case KMSG_CRED_ADDR_CHANGE:
+ return handle_kmsg_cred_addr_change();
+
+ default:
+ /* Credentials acquisition messages are all handled in a
+ different source file. */
+ if (IS_CRED_ACQ_MSG(msg_subtype))
+ return handle_cred_acq_msg(msg_type, msg_subtype,
+ uparam, vparam);
+ }
+
+ return rv;
+}
+
+
+/* This is the main message handler for our plugin. All the plugin
+ messages end up here where we either handle it directly or dispatch
+ it to other handlers. */
+khm_int32 KHMAPI plugin_msg_proc(khm_int32 msg_type,
+ khm_int32 msg_subtype,
+ khm_ui_4 uparam,
+ void * vparam) {
+
+ switch(msg_type) {
+ case KMSG_SYSTEM:
+ return handle_kmsg_system(msg_type, msg_subtype, uparam, vparam);
+
+ case KMSG_CRED:
+ return handle_kmsg_cred(msg_type, msg_subtype, uparam, vparam);
+ }
+
+ return KHM_ERROR_SUCCESS;
+}
diff --git a/src/windows/identity/sample/templates/credprov/proppage.c b/src/windows/identity/sample/templates/credprov/proppage.c
index 734a58ee4c..eaffde23e0 100644
--- a/src/windows/identity/sample/templates/credprov/proppage.c
+++ b/src/windows/identity/sample/templates/credprov/proppage.c
@@ -1,59 +1,59 @@
-/*
- * Copyright (c) 2006 Secure Endpoints Inc.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include "credprov.h"
-
-/* Dialog procedure and support code for displaying property sheets
- for credentials of type MyCred. */
-
-/* Dialog procedure for the property sheet. This will run under the
- UI thread when a property sheet is being displayed for one of our
- credentials.. */
-INT_PTR CALLBACK
-pp_cred_dlg_proc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam) {
-
- switch (uMsg) {
- case WM_INITDIALOG:
- {
- khui_property_sheet * ps;
- PROPSHEETPAGE * p;
-
- p = (PROPSHEETPAGE *) lParam;
- ps = (khui_property_sheet *) p->lParam;
-
- /* TODO: Populate the property sheet controls with values
- extracted from the credential. (ps->cred) */
-
- return FALSE;
- }
- }
-
- return FALSE;
-}
-
+/*
+ * Copyright (c) 2006 Secure Endpoints Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include "credprov.h"
+
+/* Dialog procedure and support code for displaying property sheets
+ for credentials of type MyCred. */
+
+/* Dialog procedure for the property sheet. This will run under the
+ UI thread when a property sheet is being displayed for one of our
+ credentials.. */
+INT_PTR CALLBACK
+pp_cred_dlg_proc(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam) {
+
+ switch (uMsg) {
+ case WM_INITDIALOG:
+ {
+ khui_property_sheet * ps;
+ PROPSHEETPAGE * p;
+
+ p = (PROPSHEETPAGE *) lParam;
+ ps = (khui_property_sheet *) p->lParam;
+
+ /* TODO: Populate the property sheet controls with values
+ extracted from the credential. (ps->cred) */
+
+ return FALSE;
+ }
+ }
+
+ return FALSE;
+}
+
diff --git a/src/windows/identity/ui/aboutwnd.c b/src/windows/identity/ui/aboutwnd.c
index 68aef02773..cc88705d74 100644
--- a/src/windows/identity/ui/aboutwnd.c
+++ b/src/windows/identity/ui/aboutwnd.c
@@ -1,154 +1,154 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<khmapp.h>
-#include<netidmgr_intver.h>
-#include<tlhelp32.h>
-
-#if DEBUG
-#include<assert.h>
-#endif
-
-INT_PTR CALLBACK
-about_dlg_proc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam) {
-
- switch(uMsg) {
- case WM_INITDIALOG:
- {
- HANDLE hsnap;
- HWND hw;
-
- SetDlgItemText(hwnd, IDC_PRODUCT,
- TEXT(KH_VERSTR_PRODUCT_1033));
- /* retain the original copyright strings */
-#ifdef OVERRIDE_COPYRIGHT
- SetDlgItemText(hwnd, IDC_COPYRIGHT,
- TEXT(KH_VERSTR_COPYRIGHT_1033));
-#endif
- SetDlgItemText(hwnd, IDC_BUILDINFO,
- TEXT(KH_VERSTR_BUILDINFO_1033));
-
- hsnap =
- CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,
- 0);
-
- if (hsnap != INVALID_HANDLE_VALUE) {
- LVCOLUMN lvc;
- MODULEENTRY32 mod;
- RECT r;
-
- hw = GetDlgItem(hwnd, IDC_MODULES);
-#ifdef DEBUG
- assert(hw != NULL);
-#endif
-
- GetWindowRect(hw, &r);
- OffsetRect(&r, -r.left, -r.top);
-
- ZeroMemory(&lvc, sizeof(lvc));
- lvc.mask = LVCF_TEXT | LVCF_WIDTH;
-
- lvc.pszText = L"Name";
- lvc.cx = r.right / 4;
-
- ListView_InsertColumn(hw, 0, &lvc);
-
- lvc.pszText = L"Path";
- lvc.cx = (r.right * 3) / 4;
- ListView_InsertColumn(hw, 1, &lvc);
-
- ZeroMemory(&mod, sizeof(mod));
- mod.dwSize = sizeof(mod);
-
- /* done with columns, now for the actual data */
- if (!Module32First(hsnap, &mod))
- goto _done_with_modules;
-
- do {
-
- LVITEM lvi;
- int idx;
-
- ZeroMemory(&lvi, sizeof(lvi));
-
- lvi.mask = LVIF_TEXT;
- lvi.pszText = mod.szModule;
- idx = ListView_InsertItem(hw, &lvi);
-
- lvi.mask = LVIF_TEXT;
- lvi.iItem = idx;
- lvi.iSubItem = 1;
- lvi.pszText = mod.szExePath;
- ListView_SetItem(hw, &lvi);
-
- ZeroMemory(&mod, sizeof(mod));
- mod.dwSize = sizeof(mod);
- } while(Module32Next(hsnap, &mod));
-
- _done_with_modules:
- CloseHandle(hsnap);
- }
-
- khm_add_dialog(hwnd);
- khm_enter_modal(hwnd);
- }
- return FALSE;
-
- case WM_DESTROY:
- khm_del_dialog(hwnd);
- return TRUE;
-
- case WM_CLOSE:
- khm_leave_modal();
- DestroyWindow(hwnd);
- return TRUE;
-
- case WM_COMMAND:
- if (wParam == MAKEWPARAM(IDOK, BN_CLICKED)) {
- khm_leave_modal();
- DestroyWindow(hwnd);
- }
- return TRUE;
- }
-
- return FALSE;
-}
-
-void
-khm_create_about_window(void) {
- HWND hwnd;
- hwnd = CreateDialog(khm_hInstance,
- MAKEINTRESOURCE(IDD_ABOUT),
- khm_hwnd_main,
- about_dlg_proc);
-
- ShowWindow(hwnd, SW_SHOW);
- /* no need to keep track of the hwnd, since we add it to the
- dialog chain in the dialog procedure */
-}
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<khmapp.h>
+#include<netidmgr_intver.h>
+#include<tlhelp32.h>
+
+#if DEBUG
+#include<assert.h>
+#endif
+
+INT_PTR CALLBACK
+about_dlg_proc(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam) {
+
+ switch(uMsg) {
+ case WM_INITDIALOG:
+ {
+ HANDLE hsnap;
+ HWND hw;
+
+ SetDlgItemText(hwnd, IDC_PRODUCT,
+ TEXT(KH_VERSTR_PRODUCT_1033));
+ /* retain the original copyright strings */
+#ifdef OVERRIDE_COPYRIGHT
+ SetDlgItemText(hwnd, IDC_COPYRIGHT,
+ TEXT(KH_VERSTR_COPYRIGHT_1033));
+#endif
+ SetDlgItemText(hwnd, IDC_BUILDINFO,
+ TEXT(KH_VERSTR_BUILDINFO_1033));
+
+ hsnap =
+ CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,
+ 0);
+
+ if (hsnap != INVALID_HANDLE_VALUE) {
+ LVCOLUMN lvc;
+ MODULEENTRY32 mod;
+ RECT r;
+
+ hw = GetDlgItem(hwnd, IDC_MODULES);
+#ifdef DEBUG
+ assert(hw != NULL);
+#endif
+
+ GetWindowRect(hw, &r);
+ OffsetRect(&r, -r.left, -r.top);
+
+ ZeroMemory(&lvc, sizeof(lvc));
+ lvc.mask = LVCF_TEXT | LVCF_WIDTH;
+
+ lvc.pszText = L"Name";
+ lvc.cx = r.right / 4;
+
+ ListView_InsertColumn(hw, 0, &lvc);
+
+ lvc.pszText = L"Path";
+ lvc.cx = (r.right * 3) / 4;
+ ListView_InsertColumn(hw, 1, &lvc);
+
+ ZeroMemory(&mod, sizeof(mod));
+ mod.dwSize = sizeof(mod);
+
+ /* done with columns, now for the actual data */
+ if (!Module32First(hsnap, &mod))
+ goto _done_with_modules;
+
+ do {
+
+ LVITEM lvi;
+ int idx;
+
+ ZeroMemory(&lvi, sizeof(lvi));
+
+ lvi.mask = LVIF_TEXT;
+ lvi.pszText = mod.szModule;
+ idx = ListView_InsertItem(hw, &lvi);
+
+ lvi.mask = LVIF_TEXT;
+ lvi.iItem = idx;
+ lvi.iSubItem = 1;
+ lvi.pszText = mod.szExePath;
+ ListView_SetItem(hw, &lvi);
+
+ ZeroMemory(&mod, sizeof(mod));
+ mod.dwSize = sizeof(mod);
+ } while(Module32Next(hsnap, &mod));
+
+ _done_with_modules:
+ CloseHandle(hsnap);
+ }
+
+ khm_add_dialog(hwnd);
+ khm_enter_modal(hwnd);
+ }
+ return FALSE;
+
+ case WM_DESTROY:
+ khm_del_dialog(hwnd);
+ return TRUE;
+
+ case WM_CLOSE:
+ khm_leave_modal();
+ DestroyWindow(hwnd);
+ return TRUE;
+
+ case WM_COMMAND:
+ if (wParam == MAKEWPARAM(IDOK, BN_CLICKED)) {
+ khm_leave_modal();
+ DestroyWindow(hwnd);
+ }
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+void
+khm_create_about_window(void) {
+ HWND hwnd;
+ hwnd = CreateDialog(khm_hInstance,
+ MAKEINTRESOURCE(IDD_ABOUT),
+ khm_hwnd_main,
+ about_dlg_proc);
+
+ ShowWindow(hwnd, SW_SHOW);
+ /* no need to keep track of the hwnd, since we add it to the
+ dialog chain in the dialog procedure */
+}
diff --git a/src/windows/identity/ui/aboutwnd.h b/src/windows/identity/ui/aboutwnd.h
index 81b7e90470..7da709d933 100644
--- a/src/windows/identity/ui/aboutwnd.h
+++ b/src/windows/identity/ui/aboutwnd.h
@@ -1,33 +1,33 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#ifndef __KHIMAIRA_ABOUTWND_H
-#define __KHIMAIRA_ABOUTWND_H
-
-void
-khm_create_about_window(void);
-
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __KHIMAIRA_ABOUTWND_H
+#define __KHIMAIRA_ABOUTWND_H
+
+void
+khm_create_about_window(void);
+
+#endif
diff --git a/src/windows/identity/ui/addrchange.c b/src/windows/identity/ui/addrchange.c
index b37fca5347..36ef2beeee 100644
--- a/src/windows/identity/ui/addrchange.c
+++ b/src/windows/identity/ui/addrchange.c
@@ -1,94 +1,94 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<khmapp.h>
-#include<iphlpapi.h>
-
-static HANDLE evt_terminate = NULL;
-static HANDLE h_thread = NULL;
-
-DWORD WINAPI
-addr_change_thread(LPVOID dummy) {
-
- HANDLE h_waits[2];
- HANDLE h_notify;
-
- OVERLAPPED overlap;
- DWORD ret;
-
- PDESCTHREAD(L"Address change waiter", L"App");
-
- ZeroMemory(&overlap, sizeof(overlap));
-
- h_notify = NULL;
- overlap.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
-
- do {
- ret = NotifyAddrChange(&h_notify, &overlap);
-
- if (ret != ERROR_IO_PENDING) {
- goto _end_thread; /* some error */
- }
-
- h_waits[0] = overlap.hEvent;
- h_waits[1] = evt_terminate;
-
- ret = WaitForMultipleObjects(2, h_waits, FALSE, INFINITE);
-
- if ( ret == WAIT_OBJECT_0 ) {
- Sleep(3000); /* wait for things to settle down */
- kmq_post_message(KMSG_CRED, KMSG_CRED_ADDR_CHANGE, 0, 0);
- } else {
- goto _end_thread;
- }
- } while(TRUE);
-
- _end_thread:
- ExitThread(0);
- return 0; /* unreachable */
-}
-
-void
-khm_addr_change_notifier_init(void) {
- evt_terminate = CreateEvent(NULL, FALSE, FALSE, NULL);
- h_thread = CreateThread(NULL,
- 64 * 4096,
- addr_change_thread,
- NULL,
- 0,
- NULL);
-}
-
-void
-khm_addr_change_notifier_exit(void) {
- if (h_thread && evt_terminate) {
- SetEvent(evt_terminate);
- WaitForSingleObject(h_thread, INFINITE);
-
- CloseHandle(h_thread);
- CloseHandle(evt_terminate);
- }
-}
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<khmapp.h>
+#include<iphlpapi.h>
+
+static HANDLE evt_terminate = NULL;
+static HANDLE h_thread = NULL;
+
+DWORD WINAPI
+addr_change_thread(LPVOID dummy) {
+
+ HANDLE h_waits[2];
+ HANDLE h_notify;
+
+ OVERLAPPED overlap;
+ DWORD ret;
+
+ PDESCTHREAD(L"Address change waiter", L"App");
+
+ ZeroMemory(&overlap, sizeof(overlap));
+
+ h_notify = NULL;
+ overlap.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+
+ do {
+ ret = NotifyAddrChange(&h_notify, &overlap);
+
+ if (ret != ERROR_IO_PENDING) {
+ goto _end_thread; /* some error */
+ }
+
+ h_waits[0] = overlap.hEvent;
+ h_waits[1] = evt_terminate;
+
+ ret = WaitForMultipleObjects(2, h_waits, FALSE, INFINITE);
+
+ if ( ret == WAIT_OBJECT_0 ) {
+ Sleep(3000); /* wait for things to settle down */
+ kmq_post_message(KMSG_CRED, KMSG_CRED_ADDR_CHANGE, 0, 0);
+ } else {
+ goto _end_thread;
+ }
+ } while(TRUE);
+
+ _end_thread:
+ ExitThread(0);
+ return 0; /* unreachable */
+}
+
+void
+khm_addr_change_notifier_init(void) {
+ evt_terminate = CreateEvent(NULL, FALSE, FALSE, NULL);
+ h_thread = CreateThread(NULL,
+ 64 * 4096,
+ addr_change_thread,
+ NULL,
+ 0,
+ NULL);
+}
+
+void
+khm_addr_change_notifier_exit(void) {
+ if (h_thread && evt_terminate) {
+ SetEvent(evt_terminate);
+ WaitForSingleObject(h_thread, INFINITE);
+
+ CloseHandle(h_thread);
+ CloseHandle(evt_terminate);
+ }
+}
diff --git a/src/windows/identity/ui/addrchange.h b/src/windows/identity/ui/addrchange.h
index 08c15041f4..2f605af8c3 100644
--- a/src/windows/identity/ui/addrchange.h
+++ b/src/windows/identity/ui/addrchange.h
@@ -1,36 +1,36 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#ifndef __NETIDMGR_ADDRCHANGE_H
-#define __NETIDMGR_ADDRCHANGE_H
-
-void
-khm_addr_change_notifier_init(void);
-
-void
-khm_addr_change_notifier_exit(void);
-
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __NETIDMGR_ADDRCHANGE_H
+#define __NETIDMGR_ADDRCHANGE_H
+
+void
+khm_addr_change_notifier_init(void);
+
+void
+khm_addr_change_notifier_exit(void);
+
+#endif
diff --git a/src/windows/identity/ui/appglobal.h b/src/windows/identity/ui/appglobal.h
index 3e44282d16..46e2d0dc93 100644
--- a/src/windows/identity/ui/appglobal.h
+++ b/src/windows/identity/ui/appglobal.h
@@ -1,143 +1,143 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#ifndef __KHIMAIRA_APPGLOBAL_H
-#define __KHIMAIRA_APPGLOBAL_H
-
-/* Helpfile */
-#define NIDM_HELPFILE L"netidmgr.chm"
-
-/* global data */
-extern HINSTANCE khm_hInstance;
-extern int khm_nCmdShow;
-extern const wchar_t * khm_facility;
-extern kconf_schema schema_uiconfig[];
-extern khm_ui_4 khm_commctl_version;
-extern const khm_version app_version;
-
-#define IS_COMMCTL6() (khm_commctl_version >= 0x60000)
-
-/* The structure used to send command-line options to a remote
- NetIDMgr session for versions prior to 1.2. */
-struct tag_khm_startup_options_v1 {
- BOOL seen;
- BOOL processing;
-
- BOOL init;
- BOOL import;
- BOOL renew;
- BOOL destroy;
-
- BOOL autoinit;
- BOOL exit;
- BOOL error_exit;
-
- BOOL no_main_window;
-};
-
-/* Used on NetIDMgr versions 1.2 and later */
-struct tag_khm_startup_options_v2 {
- khm_int32 magic;
- DWORD cb_size;
-
- BOOL init;
- BOOL import;
- BOOL renew;
- BOOL destroy;
-
- BOOL autoinit;
- BOOL remote_exit;
-
- khm_int32 code;
-} khm_startup_options_xfer;
-
-#define STARTUP_OPTIONS_MAGIC 0x1f280e41
-
-/* Used internally. */
-typedef struct tag_khm_startup_options_int {
- BOOL seen;
- BOOL processing;
- BOOL remote;
-
- BOOL init;
- BOOL import;
- BOOL renew;
- BOOL destroy;
-
- BOOL autoinit;
- BOOL exit;
- BOOL remote_exit;
-
- BOOL error_exit;
-
- BOOL no_main_window;
-
- LONG pending_renewals;
-} khm_startup_options;
-
-extern khm_startup_options khm_startup;
-
-/* Used to query a remote instance of NetIDMgr for the version. */
-typedef struct tag_khm_query_app_version_v1 {
- khm_int32 magic;
-
- khm_int32 code;
-
- khm_version ver_caller;
- khm_version ver_remote;
-
- khm_boolean request_swap;
-} khm_query_app_version;
-
-#define KHM_QUERY_APP_VER_MAGIC 0x38f8c2eb
-
-void khm_add_dialog(HWND dlg);
-void khm_del_dialog(HWND dlg);
-BOOL khm_is_dialog_active(void);
-
-void khm_enter_modal(HWND hwnd);
-void khm_leave_modal(void);
-
-void khm_add_property_sheet(khui_property_sheet * s);
-void khm_del_property_sheet(khui_property_sheet * s);
-
-void khm_init_gui(void);
-void khm_exit_gui(void);
-
-void khm_parse_commandline();
-void khm_register_window_classes(void);
-
-HWND khm_html_help(HWND hwnd, wchar_t * suffix, UINT command, DWORD_PTR data);
-
-WPARAM khm_message_loop_int(khm_boolean * p_exit);
-
-int khm_compare_version(const khm_version * v1, const khm_version * v2);
-
-#define MAX_RES_STRING 1024
-
-#define ELLIPSIS L"..."
-
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __KHIMAIRA_APPGLOBAL_H
+#define __KHIMAIRA_APPGLOBAL_H
+
+/* Helpfile */
+#define NIDM_HELPFILE L"netidmgr.chm"
+
+/* global data */
+extern HINSTANCE khm_hInstance;
+extern int khm_nCmdShow;
+extern const wchar_t * khm_facility;
+extern kconf_schema schema_uiconfig[];
+extern khm_ui_4 khm_commctl_version;
+extern const khm_version app_version;
+
+#define IS_COMMCTL6() (khm_commctl_version >= 0x60000)
+
+/* The structure used to send command-line options to a remote
+ NetIDMgr session for versions prior to 1.2. */
+struct tag_khm_startup_options_v1 {
+ BOOL seen;
+ BOOL processing;
+
+ BOOL init;
+ BOOL import;
+ BOOL renew;
+ BOOL destroy;
+
+ BOOL autoinit;
+ BOOL exit;
+ BOOL error_exit;
+
+ BOOL no_main_window;
+};
+
+/* Used on NetIDMgr versions 1.2 and later */
+struct tag_khm_startup_options_v2 {
+ khm_int32 magic;
+ DWORD cb_size;
+
+ BOOL init;
+ BOOL import;
+ BOOL renew;
+ BOOL destroy;
+
+ BOOL autoinit;
+ BOOL remote_exit;
+
+ khm_int32 code;
+} khm_startup_options_xfer;
+
+#define STARTUP_OPTIONS_MAGIC 0x1f280e41
+
+/* Used internally. */
+typedef struct tag_khm_startup_options_int {
+ BOOL seen;
+ BOOL processing;
+ BOOL remote;
+
+ BOOL init;
+ BOOL import;
+ BOOL renew;
+ BOOL destroy;
+
+ BOOL autoinit;
+ BOOL exit;
+ BOOL remote_exit;
+
+ BOOL error_exit;
+
+ BOOL no_main_window;
+
+ LONG pending_renewals;
+} khm_startup_options;
+
+extern khm_startup_options khm_startup;
+
+/* Used to query a remote instance of NetIDMgr for the version. */
+typedef struct tag_khm_query_app_version_v1 {
+ khm_int32 magic;
+
+ khm_int32 code;
+
+ khm_version ver_caller;
+ khm_version ver_remote;
+
+ khm_boolean request_swap;
+} khm_query_app_version;
+
+#define KHM_QUERY_APP_VER_MAGIC 0x38f8c2eb
+
+void khm_add_dialog(HWND dlg);
+void khm_del_dialog(HWND dlg);
+BOOL khm_is_dialog_active(void);
+
+void khm_enter_modal(HWND hwnd);
+void khm_leave_modal(void);
+
+void khm_add_property_sheet(khui_property_sheet * s);
+void khm_del_property_sheet(khui_property_sheet * s);
+
+void khm_init_gui(void);
+void khm_exit_gui(void);
+
+void khm_parse_commandline();
+void khm_register_window_classes(void);
+
+HWND khm_html_help(HWND hwnd, wchar_t * suffix, UINT command, DWORD_PTR data);
+
+WPARAM khm_message_loop_int(khm_boolean * p_exit);
+
+int khm_compare_version(const khm_version * v1, const khm_version * v2);
+
+#define MAX_RES_STRING 1024
+
+#define ELLIPSIS L"..."
+
+#endif
diff --git a/src/windows/identity/ui/cfg_appear_wnd.c b/src/windows/identity/ui/cfg_appear_wnd.c
index bca2709792..c7e9abc257 100644
--- a/src/windows/identity/ui/cfg_appear_wnd.c
+++ b/src/windows/identity/ui/cfg_appear_wnd.c
@@ -1,435 +1,435 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<khmapp.h>
-#include<assert.h>
-
-static int text_sizes[] = {
- 4,6,8,9,10,12,14,16,18
-};
-
-typedef struct tag_dlg_data {
- khui_config_node node;
- HWND hwnd;
- LOGFONT lf_base;
- LOGFONT lf_work;
- HFONT c_font_normal;
- HFONT c_font_bold;
- int size_idx[ARRAYLENGTH(text_sizes)];
-} dlg_data;
-
-static void
-read_params(HWND hwnd, dlg_data * d) {
-
- HDC hdc;
-
- hdc = GetWindowDC(hwnd);
-
- khm_get_cw_element_font(hdc,
- NULL,
- FALSE,
- &d->lf_base);
-
- d->lf_work = d->lf_base;
-
- ReleaseDC(hwnd, hdc);
-}
-
-
-static void
-write_params(dlg_data * d) {
- khm_boolean applied = FALSE;
-
- if (memcmp(&d->lf_work, &d->lf_base, sizeof(LOGFONT))) {
- khm_set_cw_element_font(NULL, &d->lf_work);
- d->lf_base = d->lf_work;
- applied = TRUE;
- }
-
- khui_cfg_set_flags(d->node,
- (applied)? KHUI_CNFLAG_APPLIED: 0,
- KHUI_CNFLAG_APPLIED | KHUI_CNFLAG_MODIFIED);
-}
-
-static void
-check_for_modification(dlg_data * d) {
-
- khui_cfg_set_flags(d->node,
- ((memcmp(&d->lf_work, &d->lf_base, sizeof(LOGFONT)))?
- KHUI_CNFLAG_MODIFIED: 0),
- KHUI_CNFLAG_MODIFIED);
-}
-
-static void
-refresh_view(HWND hwnd, dlg_data * d) {
- wchar_t sample[256];
- HFONT hf;
- LOGFONT lf;
-
- LoadString(khm_hInstance, IDS_APR_SAMPLE_TEXT_NORMAL,
- sample, ARRAYLENGTH(sample));
-
- SetDlgItemText(hwnd, IDC_CFG_SAMPLE_NORMAL, sample);
-
- LoadString(khm_hInstance, IDS_APR_SAMPLE_TEXT_SEL,
- sample, ARRAYLENGTH(sample));
-
- SetDlgItemText(hwnd, IDC_CFG_SAMPLE_BOLD, sample);
-
- lf = d->lf_work;
- hf = CreateFontIndirect(&lf);
- if (hf == NULL)
- return;
-
- SendDlgItemMessage(hwnd, IDC_CFG_SAMPLE_NORMAL, WM_SETFONT, (WPARAM) hf, TRUE);
-
- if (d->c_font_normal)
- DeleteObject(d->c_font_normal);
-
- d->c_font_normal = hf;
-
- lf.lfWeight = FW_BOLD;
-
- hf = CreateFontIndirect(&lf);
- if (hf == NULL)
- return;
-
- SendDlgItemMessage(hwnd, IDC_CFG_SAMPLE_BOLD, WM_SETFONT, (WPARAM) hf, TRUE);
-
- if (d->c_font_bold)
- DeleteObject(d->c_font_bold);
-
- d->c_font_bold = hf;
-}
-
-struct sel_update_blob {
- dlg_data * d;
- HDC hdc;
-};
-
-static int CALLBACK
-enum_font_proc(ENUMLOGFONTEXDV * plfe,
- ENUMTEXTMETRIC * pntm,
- DWORD font_type,
- LPARAM lParam) {
- struct sel_update_blob * blob = (struct sel_update_blob *) lParam;
- LOGFONT * plf = &plfe->elfEnumLogfontEx.elfLogFont;
- LRESULT lr;
-
- lr = SendDlgItemMessage(blob->d->hwnd,
- IDC_CFG_FONTS,
- CB_SELECTSTRING,
- (WPARAM) -1,
- (LPARAM) plf->lfFaceName);
-
- if (lr == CB_ERR) {
- SendDlgItemMessage(blob->d->hwnd,
- IDC_CFG_FONTS,
- CB_SELECTSTRING,
- (WPARAM) -1,
- (LPARAM) plfe->elfEnumLogfontEx.elfFullName);
- }
-
- return FALSE;
-}
-
-static void
-update_selection(dlg_data * d, BOOL update_fonts, BOOL update_effects) {
- LOGFONT lf;
- struct sel_update_blob blob;
- HDC hdc;
-
- if (update_fonts) {
-
- ZeroMemory(&lf, sizeof(lf));
-
- lf.lfCharSet = ANSI_CHARSET;
- StringCbCopy(lf.lfFaceName, sizeof(lf.lfFaceName),
- d->lf_work.lfFaceName);
-
- hdc = GetWindowDC(d->hwnd);
-
- blob.d = d;
- blob.hdc = hdc;
-
- EnumFontFamiliesEx(hdc, &lf, (FONTENUMPROC) enum_font_proc,
- (LPARAM) &blob, 0);
-
- ReleaseDC(d->hwnd, hdc);
- }
-
- if (update_effects) {
- int i;
- HDC hdc;
- int pt_height;
-
- if (d->lf_work.lfWeight >= FW_BOLD)
- CheckDlgButton(d->hwnd, IDC_CFG_BOLD, BST_CHECKED);
- else
- CheckDlgButton(d->hwnd, IDC_CFG_BOLD, BST_UNCHECKED);
-
- if (d->lf_work.lfItalic)
- CheckDlgButton(d->hwnd, IDC_CFG_ITALICS, BST_CHECKED);
- else
- CheckDlgButton(d->hwnd, IDC_CFG_ITALICS, BST_UNCHECKED);
-
- hdc = GetWindowDC(d->hwnd);
-
- pt_height = MulDiv(d->lf_work.lfHeight, 72,
- GetDeviceCaps(hdc, LOGPIXELSY));
-
-
- ReleaseDC(d->hwnd, hdc);
-
- if (pt_height < 0)
- pt_height = - pt_height;
-
- for (i=0; i < ARRAYLENGTH(text_sizes); i++) {
- if (text_sizes[i] >= pt_height)
- break;
- }
-
- if (i >= ARRAYLENGTH(text_sizes))
- i = ARRAYLENGTH(text_sizes) - 1;
-
- SendDlgItemMessage(d->hwnd, IDC_CFG_SIZE, CB_SETCURSEL,
- d->size_idx[i], 0);
- }
-}
-
-static int CALLBACK
-enum_font_families_proc(ENUMLOGFONTEXDV * plfe,
- ENUMTEXTMETRIC * pntm,
- DWORD font_type,
- LPARAM lParam) {
-
- dlg_data * d = (dlg_data *) lParam;
-
- SendDlgItemMessage(d->hwnd, IDC_CFG_FONTS,
- CB_ADDSTRING, 0,
- (LPARAM) plfe->elfEnumLogfontEx.elfLogFont.lfFaceName);
-
- return TRUE;
-}
-
-INT_PTR CALLBACK
-khm_cfg_appearance_proc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam) {
-
- dlg_data * d;
-
- switch(uMsg) {
- case WM_INITDIALOG:
- {
- HWND hw_cb;
- LOGFONT lf;
- HDC hdc;
- int i;
- wchar_t buf[4];
-
- d = PMALLOC(sizeof(*d));
-#ifdef DEBUG
- assert(d != NULL);
-#endif
-
-#pragma warning(push)
-#pragma warning(disable: 4244)
- SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) d);
-#pragma warning(pop)
-
- ZeroMemory(d, sizeof(*d));
-
- d->node = (khui_config_node) lParam;
- d->hwnd = hwnd;
-
- read_params(hwnd, d);
-
- hw_cb = GetDlgItem(hwnd, IDC_CFG_FONTS);
-#ifdef DEBUG
- assert(hw_cb);
-#endif
- SendMessage(hw_cb, CB_RESETCONTENT, 0, 0);
-
- ZeroMemory(&lf, sizeof(lf));
- lf.lfCharSet = ANSI_CHARSET;
-
- hdc = GetWindowDC(hwnd);
-
- EnumFontFamiliesEx(hdc, &lf, (FONTENUMPROC) enum_font_families_proc,
- (LPARAM) d, 0);
-
- ReleaseDC(hwnd, hdc);
-
-
- for (i=0; i < ARRAYLENGTH(text_sizes); i++) {
- LRESULT idx;
-
- StringCbPrintf(buf, sizeof(buf), L"%d", text_sizes[i]);
-
- idx = SendDlgItemMessage(hwnd, IDC_CFG_SIZE,
- CB_ADDSTRING, 0, (LPARAM) buf);
-
- SendDlgItemMessage(hwnd, IDC_CFG_SIZE,
- CB_SETITEMDATA, idx, text_sizes[i]);
-
- d->size_idx[i] = (int) idx;
- }
-
- update_selection(d, TRUE, TRUE);
-
- refresh_view(hwnd, d);
- }
- return FALSE;
-
- case WM_COMMAND:
- d = (dlg_data *) (LONG_PTR) GetWindowLongPtr(hwnd, DWLP_USER);
-
- if (wParam == MAKEWPARAM(IDC_CFG_FONTS, CBN_SELCHANGE)) {
- LRESULT idx;
- wchar_t facename[LF_FACESIZE];
-
- idx = SendDlgItemMessage(hwnd, IDC_CFG_FONTS,
- CB_GETCURSEL,
- 0, 0);
-
- if (idx == CB_ERR)
- return TRUE;
-
- if (SendDlgItemMessage(hwnd, IDC_CFG_FONTS,
- CB_GETLBTEXTLEN, idx, 0)
- >= ARRAYLENGTH(facename))
- return TRUE;
-
- SendDlgItemMessage(hwnd, IDC_CFG_FONTS,
- CB_GETLBTEXT, idx,
- (LPARAM) facename);
-
- ZeroMemory(d->lf_work.lfFaceName,
- sizeof(d->lf_work.lfFaceName));
-
- StringCbCopy(d->lf_work.lfFaceName,
- sizeof(d->lf_work.lfFaceName),
- facename);
-
- update_selection(d, FALSE, FALSE);
-
- refresh_view(hwnd, d);
-
- check_for_modification(d);
-
- } else if (wParam == MAKEWPARAM(IDC_CFG_BOLD, BN_CLICKED)) {
-
- if (IsDlgButtonChecked(hwnd, IDC_CFG_BOLD) == BST_CHECKED) {
- d->lf_work.lfWeight = FW_BOLD;
- } else {
- d->lf_work.lfWeight = 0;
- }
-
- refresh_view(hwnd, d);
-
- check_for_modification(d);
-
- } else if (wParam == MAKEWPARAM(IDC_CFG_ITALICS, BN_CLICKED)) {
-
- d->lf_work.lfItalic =
- (IsDlgButtonChecked(hwnd, IDC_CFG_ITALICS) == BST_CHECKED);
-
- refresh_view(hwnd, d);
-
- check_for_modification(d);
-
- } else if (wParam == MAKEWPARAM(IDC_CFG_REVERT, BN_CLICKED)) {
- HDC hdc;
-
- hdc = GetWindowDC(hwnd);
-
- khm_get_cw_element_font(hdc, NULL, TRUE, &d->lf_work);
-
- ReleaseDC(hwnd, hdc);
-
- update_selection(d, TRUE, TRUE);
-
- refresh_view(hwnd, d);
-
- check_for_modification(d);
-
- } else if (wParam == MAKEWPARAM(IDC_CFG_SIZE, CBN_SELCHANGE)) {
- HDC hdc;
- LPARAM idx;
- int points;
-
- idx = SendDlgItemMessage(hwnd, IDC_CFG_SIZE,
- CB_GETCURSEL, 0, 0);
- if (idx == CB_ERR)
- return TRUE;
-
- points = (int) SendDlgItemMessage(hwnd, IDC_CFG_SIZE,
- CB_GETITEMDATA, idx, 0);
-
- hdc = GetWindowDC(hwnd);
-
- d->lf_work.lfHeight = -MulDiv(points,
- GetDeviceCaps(hdc, LOGPIXELSY),
- 72);
-
- ReleaseDC(hwnd, hdc);
-
- refresh_view(hwnd, d);
-
- check_for_modification(d);
- }
-
- return TRUE;
-
- case WM_DESTROY:
- d = (dlg_data *) (LONG_PTR) GetWindowLongPtr(hwnd, DWLP_USER);
-
- if (d) {
- if (d->c_font_bold)
- DeleteObject(d->c_font_bold);
-
- if (d->c_font_normal)
- DeleteObject(d->c_font_normal);
-
- PFREE(d);
- }
- return TRUE;
-
- case KHUI_WM_CFG_NOTIFY:
- d = (dlg_data *) (LONG_PTR) GetWindowLongPtr(hwnd, DWLP_USER);
-
- if (HIWORD(wParam) == WMCFG_APPLY) {
- write_params(d);
- khui_action_trigger(KHUI_ACTION_LAYOUT_RELOAD, NULL);
- }
-
- return TRUE;
- }
-
- return FALSE;
-}
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<khmapp.h>
+#include<assert.h>
+
+static int text_sizes[] = {
+ 4,6,8,9,10,12,14,16,18
+};
+
+typedef struct tag_dlg_data {
+ khui_config_node node;
+ HWND hwnd;
+ LOGFONT lf_base;
+ LOGFONT lf_work;
+ HFONT c_font_normal;
+ HFONT c_font_bold;
+ int size_idx[ARRAYLENGTH(text_sizes)];
+} dlg_data;
+
+static void
+read_params(HWND hwnd, dlg_data * d) {
+
+ HDC hdc;
+
+ hdc = GetWindowDC(hwnd);
+
+ khm_get_cw_element_font(hdc,
+ NULL,
+ FALSE,
+ &d->lf_base);
+
+ d->lf_work = d->lf_base;
+
+ ReleaseDC(hwnd, hdc);
+}
+
+
+static void
+write_params(dlg_data * d) {
+ khm_boolean applied = FALSE;
+
+ if (memcmp(&d->lf_work, &d->lf_base, sizeof(LOGFONT))) {
+ khm_set_cw_element_font(NULL, &d->lf_work);
+ d->lf_base = d->lf_work;
+ applied = TRUE;
+ }
+
+ khui_cfg_set_flags(d->node,
+ (applied)? KHUI_CNFLAG_APPLIED: 0,
+ KHUI_CNFLAG_APPLIED | KHUI_CNFLAG_MODIFIED);
+}
+
+static void
+check_for_modification(dlg_data * d) {
+
+ khui_cfg_set_flags(d->node,
+ ((memcmp(&d->lf_work, &d->lf_base, sizeof(LOGFONT)))?
+ KHUI_CNFLAG_MODIFIED: 0),
+ KHUI_CNFLAG_MODIFIED);
+}
+
+static void
+refresh_view(HWND hwnd, dlg_data * d) {
+ wchar_t sample[256];
+ HFONT hf;
+ LOGFONT lf;
+
+ LoadString(khm_hInstance, IDS_APR_SAMPLE_TEXT_NORMAL,
+ sample, ARRAYLENGTH(sample));
+
+ SetDlgItemText(hwnd, IDC_CFG_SAMPLE_NORMAL, sample);
+
+ LoadString(khm_hInstance, IDS_APR_SAMPLE_TEXT_SEL,
+ sample, ARRAYLENGTH(sample));
+
+ SetDlgItemText(hwnd, IDC_CFG_SAMPLE_BOLD, sample);
+
+ lf = d->lf_work;
+ hf = CreateFontIndirect(&lf);
+ if (hf == NULL)
+ return;
+
+ SendDlgItemMessage(hwnd, IDC_CFG_SAMPLE_NORMAL, WM_SETFONT, (WPARAM) hf, TRUE);
+
+ if (d->c_font_normal)
+ DeleteObject(d->c_font_normal);
+
+ d->c_font_normal = hf;
+
+ lf.lfWeight = FW_BOLD;
+
+ hf = CreateFontIndirect(&lf);
+ if (hf == NULL)
+ return;
+
+ SendDlgItemMessage(hwnd, IDC_CFG_SAMPLE_BOLD, WM_SETFONT, (WPARAM) hf, TRUE);
+
+ if (d->c_font_bold)
+ DeleteObject(d->c_font_bold);
+
+ d->c_font_bold = hf;
+}
+
+struct sel_update_blob {
+ dlg_data * d;
+ HDC hdc;
+};
+
+static int CALLBACK
+enum_font_proc(ENUMLOGFONTEXDV * plfe,
+ ENUMTEXTMETRIC * pntm,
+ DWORD font_type,
+ LPARAM lParam) {
+ struct sel_update_blob * blob = (struct sel_update_blob *) lParam;
+ LOGFONT * plf = &plfe->elfEnumLogfontEx.elfLogFont;
+ LRESULT lr;
+
+ lr = SendDlgItemMessage(blob->d->hwnd,
+ IDC_CFG_FONTS,
+ CB_SELECTSTRING,
+ (WPARAM) -1,
+ (LPARAM) plf->lfFaceName);
+
+ if (lr == CB_ERR) {
+ SendDlgItemMessage(blob->d->hwnd,
+ IDC_CFG_FONTS,
+ CB_SELECTSTRING,
+ (WPARAM) -1,
+ (LPARAM) plfe->elfEnumLogfontEx.elfFullName);
+ }
+
+ return FALSE;
+}
+
+static void
+update_selection(dlg_data * d, BOOL update_fonts, BOOL update_effects) {
+ LOGFONT lf;
+ struct sel_update_blob blob;
+ HDC hdc;
+
+ if (update_fonts) {
+
+ ZeroMemory(&lf, sizeof(lf));
+
+ lf.lfCharSet = ANSI_CHARSET;
+ StringCbCopy(lf.lfFaceName, sizeof(lf.lfFaceName),
+ d->lf_work.lfFaceName);
+
+ hdc = GetWindowDC(d->hwnd);
+
+ blob.d = d;
+ blob.hdc = hdc;
+
+ EnumFontFamiliesEx(hdc, &lf, (FONTENUMPROC) enum_font_proc,
+ (LPARAM) &blob, 0);
+
+ ReleaseDC(d->hwnd, hdc);
+ }
+
+ if (update_effects) {
+ int i;
+ HDC hdc;
+ int pt_height;
+
+ if (d->lf_work.lfWeight >= FW_BOLD)
+ CheckDlgButton(d->hwnd, IDC_CFG_BOLD, BST_CHECKED);
+ else
+ CheckDlgButton(d->hwnd, IDC_CFG_BOLD, BST_UNCHECKED);
+
+ if (d->lf_work.lfItalic)
+ CheckDlgButton(d->hwnd, IDC_CFG_ITALICS, BST_CHECKED);
+ else
+ CheckDlgButton(d->hwnd, IDC_CFG_ITALICS, BST_UNCHECKED);
+
+ hdc = GetWindowDC(d->hwnd);
+
+ pt_height = MulDiv(d->lf_work.lfHeight, 72,
+ GetDeviceCaps(hdc, LOGPIXELSY));
+
+
+ ReleaseDC(d->hwnd, hdc);
+
+ if (pt_height < 0)
+ pt_height = - pt_height;
+
+ for (i=0; i < ARRAYLENGTH(text_sizes); i++) {
+ if (text_sizes[i] >= pt_height)
+ break;
+ }
+
+ if (i >= ARRAYLENGTH(text_sizes))
+ i = ARRAYLENGTH(text_sizes) - 1;
+
+ SendDlgItemMessage(d->hwnd, IDC_CFG_SIZE, CB_SETCURSEL,
+ d->size_idx[i], 0);
+ }
+}
+
+static int CALLBACK
+enum_font_families_proc(ENUMLOGFONTEXDV * plfe,
+ ENUMTEXTMETRIC * pntm,
+ DWORD font_type,
+ LPARAM lParam) {
+
+ dlg_data * d = (dlg_data *) lParam;
+
+ SendDlgItemMessage(d->hwnd, IDC_CFG_FONTS,
+ CB_ADDSTRING, 0,
+ (LPARAM) plfe->elfEnumLogfontEx.elfLogFont.lfFaceName);
+
+ return TRUE;
+}
+
+INT_PTR CALLBACK
+khm_cfg_appearance_proc(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam) {
+
+ dlg_data * d;
+
+ switch(uMsg) {
+ case WM_INITDIALOG:
+ {
+ HWND hw_cb;
+ LOGFONT lf;
+ HDC hdc;
+ int i;
+ wchar_t buf[4];
+
+ d = PMALLOC(sizeof(*d));
+#ifdef DEBUG
+ assert(d != NULL);
+#endif
+
+#pragma warning(push)
+#pragma warning(disable: 4244)
+ SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) d);
+#pragma warning(pop)
+
+ ZeroMemory(d, sizeof(*d));
+
+ d->node = (khui_config_node) lParam;
+ d->hwnd = hwnd;
+
+ read_params(hwnd, d);
+
+ hw_cb = GetDlgItem(hwnd, IDC_CFG_FONTS);
+#ifdef DEBUG
+ assert(hw_cb);
+#endif
+ SendMessage(hw_cb, CB_RESETCONTENT, 0, 0);
+
+ ZeroMemory(&lf, sizeof(lf));
+ lf.lfCharSet = ANSI_CHARSET;
+
+ hdc = GetWindowDC(hwnd);
+
+ EnumFontFamiliesEx(hdc, &lf, (FONTENUMPROC) enum_font_families_proc,
+ (LPARAM) d, 0);
+
+ ReleaseDC(hwnd, hdc);
+
+
+ for (i=0; i < ARRAYLENGTH(text_sizes); i++) {
+ LRESULT idx;
+
+ StringCbPrintf(buf, sizeof(buf), L"%d", text_sizes[i]);
+
+ idx = SendDlgItemMessage(hwnd, IDC_CFG_SIZE,
+ CB_ADDSTRING, 0, (LPARAM) buf);
+
+ SendDlgItemMessage(hwnd, IDC_CFG_SIZE,
+ CB_SETITEMDATA, idx, text_sizes[i]);
+
+ d->size_idx[i] = (int) idx;
+ }
+
+ update_selection(d, TRUE, TRUE);
+
+ refresh_view(hwnd, d);
+ }
+ return FALSE;
+
+ case WM_COMMAND:
+ d = (dlg_data *) (LONG_PTR) GetWindowLongPtr(hwnd, DWLP_USER);
+
+ if (wParam == MAKEWPARAM(IDC_CFG_FONTS, CBN_SELCHANGE)) {
+ LRESULT idx;
+ wchar_t facename[LF_FACESIZE];
+
+ idx = SendDlgItemMessage(hwnd, IDC_CFG_FONTS,
+ CB_GETCURSEL,
+ 0, 0);
+
+ if (idx == CB_ERR)
+ return TRUE;
+
+ if (SendDlgItemMessage(hwnd, IDC_CFG_FONTS,
+ CB_GETLBTEXTLEN, idx, 0)
+ >= ARRAYLENGTH(facename))
+ return TRUE;
+
+ SendDlgItemMessage(hwnd, IDC_CFG_FONTS,
+ CB_GETLBTEXT, idx,
+ (LPARAM) facename);
+
+ ZeroMemory(d->lf_work.lfFaceName,
+ sizeof(d->lf_work.lfFaceName));
+
+ StringCbCopy(d->lf_work.lfFaceName,
+ sizeof(d->lf_work.lfFaceName),
+ facename);
+
+ update_selection(d, FALSE, FALSE);
+
+ refresh_view(hwnd, d);
+
+ check_for_modification(d);
+
+ } else if (wParam == MAKEWPARAM(IDC_CFG_BOLD, BN_CLICKED)) {
+
+ if (IsDlgButtonChecked(hwnd, IDC_CFG_BOLD) == BST_CHECKED) {
+ d->lf_work.lfWeight = FW_BOLD;
+ } else {
+ d->lf_work.lfWeight = 0;
+ }
+
+ refresh_view(hwnd, d);
+
+ check_for_modification(d);
+
+ } else if (wParam == MAKEWPARAM(IDC_CFG_ITALICS, BN_CLICKED)) {
+
+ d->lf_work.lfItalic =
+ (IsDlgButtonChecked(hwnd, IDC_CFG_ITALICS) == BST_CHECKED);
+
+ refresh_view(hwnd, d);
+
+ check_for_modification(d);
+
+ } else if (wParam == MAKEWPARAM(IDC_CFG_REVERT, BN_CLICKED)) {
+ HDC hdc;
+
+ hdc = GetWindowDC(hwnd);
+
+ khm_get_cw_element_font(hdc, NULL, TRUE, &d->lf_work);
+
+ ReleaseDC(hwnd, hdc);
+
+ update_selection(d, TRUE, TRUE);
+
+ refresh_view(hwnd, d);
+
+ check_for_modification(d);
+
+ } else if (wParam == MAKEWPARAM(IDC_CFG_SIZE, CBN_SELCHANGE)) {
+ HDC hdc;
+ LPARAM idx;
+ int points;
+
+ idx = SendDlgItemMessage(hwnd, IDC_CFG_SIZE,
+ CB_GETCURSEL, 0, 0);
+ if (idx == CB_ERR)
+ return TRUE;
+
+ points = (int) SendDlgItemMessage(hwnd, IDC_CFG_SIZE,
+ CB_GETITEMDATA, idx, 0);
+
+ hdc = GetWindowDC(hwnd);
+
+ d->lf_work.lfHeight = -MulDiv(points,
+ GetDeviceCaps(hdc, LOGPIXELSY),
+ 72);
+
+ ReleaseDC(hwnd, hdc);
+
+ refresh_view(hwnd, d);
+
+ check_for_modification(d);
+ }
+
+ return TRUE;
+
+ case WM_DESTROY:
+ d = (dlg_data *) (LONG_PTR) GetWindowLongPtr(hwnd, DWLP_USER);
+
+ if (d) {
+ if (d->c_font_bold)
+ DeleteObject(d->c_font_bold);
+
+ if (d->c_font_normal)
+ DeleteObject(d->c_font_normal);
+
+ PFREE(d);
+ }
+ return TRUE;
+
+ case KHUI_WM_CFG_NOTIFY:
+ d = (dlg_data *) (LONG_PTR) GetWindowLongPtr(hwnd, DWLP_USER);
+
+ if (HIWORD(wParam) == WMCFG_APPLY) {
+ write_params(d);
+ khui_action_trigger(KHUI_ACTION_LAYOUT_RELOAD, NULL);
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
diff --git a/src/windows/identity/ui/cfg_general_wnd.c b/src/windows/identity/ui/cfg_general_wnd.c
index fa7ac6fd4b..1e92947f09 100644
--- a/src/windows/identity/ui/cfg_general_wnd.c
+++ b/src/windows/identity/ui/cfg_general_wnd.c
@@ -1,419 +1,419 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<shlwapi.h>
-#include<khmapp.h>
-#include<assert.h>
-
-typedef struct tag_cfg_data {
- BOOL auto_init;
- BOOL auto_start;
- BOOL auto_import;
- BOOL keep_running;
- BOOL auto_detect_net;
- BOOL log_to_file;
- BOOL destroy_creds;
- khm_int32 notif_action;
-} cfg_data;
-
-typedef struct tag_dlg_data {
- khui_config_node node;
- cfg_data saved;
- cfg_data work;
-} dlg_data;
-
-static void
-read_params(dlg_data * dd) {
- cfg_data * d;
- khm_handle csp_cw;
- khm_int32 t;
-
- d = &dd->saved;
-
- if (KHM_FAILED(khc_open_space(NULL, L"CredWindow", KHM_PERM_READ,
- &csp_cw))) {
-#ifdef DEBUG
- assert(FALSE);
-#endif
- return;
- }
-
- khc_read_int32(csp_cw, L"AutoInit", &t);
- d->auto_init = !!t;
-
- khc_read_int32(csp_cw, L"AutoStart", &t);
- d->auto_start = !!t;
-
- khc_read_int32(csp_cw, L"AutoImport", &t);
- d->auto_import = !!t;
-
- khc_read_int32(csp_cw, L"KeepRunning", &t);
- d->keep_running = !!t;
-
- khc_read_int32(csp_cw, L"AutoDetectNet", &t);
- d->auto_detect_net = !!t;
-
- khc_read_int32(csp_cw, L"LogToFile", &t);
- d->log_to_file = !!t;
-
- khc_read_int32(csp_cw, L"DestroyCredsOnExit", &t);
- d->destroy_creds = !!t;
-
- khc_read_int32(csp_cw, L"NotificationAction", &t);
- d->notif_action = t;
-
- khc_close_space(csp_cw);
-
- dd->work = *d;
-}
-
-static void
-write_params(dlg_data * dd) {
- cfg_data * d, * s;
- khm_handle csp_cw;
- BOOL applied = FALSE;
-
- d = &dd->work;
- s = &dd->saved;
-
- if (KHM_FAILED(khc_open_space(NULL, L"CredWindow", KHM_PERM_WRITE,
- &csp_cw))) {
-#ifdef DEBUG
- assert(FALSE);
-#endif
- return;
- }
-
- if (!!d->auto_init != !!s->auto_init) {
- khc_write_int32(csp_cw, L"AutoInit", d->auto_init);
- applied = TRUE;
- }
-
- if (!!d->auto_start != !!s->auto_start) {
- khc_write_int32(csp_cw, L"AutoStart", d->auto_start);
- applied = TRUE;
- }
-
- if (!!d->auto_import != !!s->auto_import) {
- khc_write_int32(csp_cw, L"AutoImport", d->auto_import);
- applied = TRUE;
- }
-
- if (!!d->keep_running != !!s->keep_running) {
- khc_write_int32(csp_cw, L"KeepRunning", d->keep_running);
- applied = TRUE;
- }
-
- if (!!d->auto_detect_net != !!s->auto_detect_net) {
- khc_write_int32(csp_cw, L"AutoDetectNet", d->auto_detect_net);
- applied = TRUE;
- }
-
- if (!!d->log_to_file != !!s->log_to_file) {
- khc_write_int32(csp_cw, L"LogToFile", d->log_to_file);
- applied = TRUE;
-
- if (d->log_to_file) {
- khm_start_file_log();
- } else {
- khm_stop_file_log();
- }
- }
-
- if (!!d->destroy_creds != !!s->destroy_creds) {
- khc_write_int32(csp_cw, L"DestroyCredsOnExit", d->destroy_creds);
- applied = TRUE;
- }
-
- if (d->notif_action != s->notif_action) {
- khc_write_int32(csp_cw, L"NotificationAction", d->notif_action);
- applied = TRUE;
- }
-
- khc_close_space(csp_cw);
-
- khui_cfg_set_flags(dd->node,
- (applied) ? KHUI_CNFLAG_APPLIED : 0,
- KHUI_CNFLAG_APPLIED | KHUI_CNFLAG_MODIFIED);
-
- *s = *d;
-}
-
-static void
-check_for_modification(dlg_data * dd) {
- cfg_data * d, * s;
- d = &dd->work;
- s = &dd->saved;
-
- if (!!d->auto_init != !!s->auto_init ||
- !!d->auto_start != !!s->auto_start ||
- !!d->auto_import != !!s->auto_import ||
- !!d->keep_running != !!s->keep_running ||
- !!d->auto_detect_net != !!s->auto_detect_net ||
- !!d->log_to_file != !!s->log_to_file ||
- !!d->destroy_creds != !!s->destroy_creds ||
- d->notif_action != s->notif_action) {
-
- khui_cfg_set_flags(dd->node,
- KHUI_CNFLAG_MODIFIED,
- KHUI_CNFLAG_MODIFIED);
-
- } else {
-
- khui_cfg_set_flags(dd->node,
- 0,
- KHUI_CNFLAG_MODIFIED);
-
- }
-}
-
-
-static void
-strip_ampersands(wchar_t * str) {
- wchar_t *f, *t;
-
- for(f = t = str; *f; f++)
- if (*f != L'&')
- *t++ = *f;
-
- *t = L'\0';
-}
-
-static void
-refresh_view(HWND hwnd, dlg_data * d) {
- wchar_t buf[512];
- khm_size i;
-
- CheckDlgButton(hwnd, IDC_CFG_AUTOINIT,
- (d->work.auto_init?BST_CHECKED:BST_UNCHECKED));
- CheckDlgButton(hwnd, IDC_CFG_AUTOSTART,
- (d->work.auto_start?BST_CHECKED:BST_UNCHECKED));
- CheckDlgButton(hwnd, IDC_CFG_AUTOIMPORT,
- (d->work.auto_import?BST_CHECKED:BST_UNCHECKED));
- CheckDlgButton(hwnd, IDC_CFG_KEEPRUNNING,
- (d->work.keep_running?BST_CHECKED:BST_UNCHECKED));
- CheckDlgButton(hwnd, IDC_CFG_NETDETECT,
- (d->work.auto_detect_net?BST_CHECKED:BST_UNCHECKED));
- CheckDlgButton(hwnd, IDC_CFG_LOGTOFILE,
- (d->work.log_to_file?BST_CHECKED:BST_UNCHECKED));
- CheckDlgButton(hwnd, IDC_CFG_DESTROYALL,
- (d->work.destroy_creds?BST_CHECKED:BST_UNCHECKED));
-
- /* we need populate the notification action combo box control and
- set the current selection to match the default action. */
-
- if (n_khm_notifier_actions != SendDlgItemMessage(hwnd, IDC_CFG_NOTACTION,
- CB_GETCOUNT, 0, 0)) {
-
- for (i=0; i < n_khm_notifier_actions; i++) {
- int idx;
-
- khm_get_action_caption(khm_notifier_actions[i],
- buf, sizeof(buf));
-
- strip_ampersands(buf);
-
- idx = (int) SendDlgItemMessage(hwnd, IDC_CFG_NOTACTION,
- CB_INSERTSTRING, i,
- (LPARAM) buf);
-
-#ifdef DEBUG
- if (idx != (int) i) {
- assert(FALSE);
- }
-#endif
- }
- }
-
- for (i=0; i < n_khm_notifier_actions; i++) {
- if (khm_notifier_actions[i] == d->work.notif_action)
- break;
- }
-
- if (i >= n_khm_notifier_actions) {
- d->work.notif_action = khm_notifier_actions[0];
- i = 0;
- }
-
- SendDlgItemMessage(hwnd, IDC_CFG_NOTACTION, CB_SETCURSEL, i, 0);
-
- /* in addition, we correct the label on the trace log control to
- reflect the actual path that is going to get used */
- if (GetDlgItemText(hwnd, IDC_CFG_LOGPATH, buf,
- ARRAYLENGTH(buf)) == 0) {
-
- khm_get_file_log_path(sizeof(buf), buf);
-
- SetDlgItemText(hwnd, IDC_CFG_LOGPATH, buf);
- }
-}
-
-static void
-refresh_data(HWND hwnd, dlg_data * d) {
- int idx;
-
- d->work.auto_init = (IsDlgButtonChecked(hwnd, IDC_CFG_AUTOINIT)
- == BST_CHECKED);
- d->work.auto_start = (IsDlgButtonChecked(hwnd, IDC_CFG_AUTOSTART)
- == BST_CHECKED);
- d->work.auto_import = (IsDlgButtonChecked(hwnd, IDC_CFG_AUTOIMPORT)
- == BST_CHECKED);
- d->work.keep_running = (IsDlgButtonChecked(hwnd, IDC_CFG_KEEPRUNNING)
- == BST_CHECKED);
- d->work.auto_detect_net = (IsDlgButtonChecked(hwnd, IDC_CFG_NETDETECT)
- == BST_CHECKED);
- d->work.log_to_file = (IsDlgButtonChecked(hwnd, IDC_CFG_LOGTOFILE)
- == BST_CHECKED);
- d->work.destroy_creds = (IsDlgButtonChecked(hwnd, IDC_CFG_DESTROYALL)
- == BST_CHECKED);
-
- idx = (int) SendDlgItemMessage(hwnd, IDC_CFG_NOTACTION, CB_GETCURSEL, 0, 0);
- if (idx < 0)
- idx = 0;
- else if (idx >= (int) n_khm_notifier_actions)
- idx = (int) n_khm_notifier_actions - 1;
-
- d->work.notif_action = khm_notifier_actions[idx];
-}
-
-INT_PTR CALLBACK
-khm_cfg_general_proc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam) {
- dlg_data * d;
-
- switch(uMsg) {
- case WM_INITDIALOG:
- d = PMALLOC(sizeof(*d));
-#ifdef DEBUG
- assert(d != NULL);
-#endif
-
-#pragma warning(push)
-#pragma warning(disable: 4244)
- SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) d);
-#pragma warning(pop)
-
- ZeroMemory(d, sizeof(*d));
-
- d->node = (khui_config_node) lParam;
-
- read_params(d);
-
- refresh_view(hwnd, d);
-
- return FALSE;
-
- case WM_DESTROY:
- d = (dlg_data *) (DWORD_PTR) GetWindowLongPtr(hwnd, DWLP_USER);
- if (d) {
- PFREE(d);
- }
- return TRUE;
-
- case WM_COMMAND:
- d = (dlg_data *) (DWORD_PTR) GetWindowLongPtr(hwnd, DWLP_USER);
-
- if (HIWORD(wParam) == BN_CLICKED) {
- if (LOWORD(wParam) == IDC_CFG_SHOWLOG) {
- /* we need to display the logfile */
- wchar_t buf[512];
-
- buf[0] = L'\0';
- khm_get_file_log_path(sizeof(buf), buf);
-
- if (!buf[0] ||
- !PathFileExists(buf)) {
-
- wchar_t title[256];
- wchar_t msg[550];
- wchar_t fmt[256];
-
- LoadString(khm_hInstance, IDS_CFG_LOGF_CS,
- title, ARRAYLENGTH(title));
- LoadString(khm_hInstance, IDS_CFG_LOGF_CSR,
- fmt, ARRAYLENGTH(fmt));
-
- StringCbPrintf(msg, sizeof(msg), fmt, buf);
-
- MessageBox(hwnd, title, msg, MB_OK);
-
- } else {
- wchar_t cmdline[550];
- STARTUPINFO si;
- PROCESS_INFORMATION pi;
-
- StringCbCopy(cmdline, sizeof(cmdline), L"notepad.exe ");
- StringCbCat(cmdline, sizeof(cmdline), L"\"");
- StringCbCat(cmdline, sizeof(cmdline), buf);
- StringCbCat(cmdline, sizeof(cmdline), L"\"");
-
- ZeroMemory(&si, sizeof(si));
- si.cb = sizeof(si);
- ZeroMemory(&pi, sizeof(pi));
-
- CreateProcess(NULL,
- cmdline,
- NULL, NULL,
- FALSE,
- 0, NULL, NULL,
- &si,
- &pi);
-
- if (pi.hProcess)
- CloseHandle(pi.hProcess);
- if (pi.hThread)
- CloseHandle(pi.hThread);
-
- }
- } else {
- refresh_data(hwnd, d);
- check_for_modification(d);
- }
- } else if (HIWORD(wParam) == CBN_SELCHANGE) {
- refresh_data(hwnd, d);
- check_for_modification(d);
- }
-
- khm_set_dialog_result(hwnd, 0);
-
- return TRUE;
-
- case KHUI_WM_CFG_NOTIFY:
- d = (dlg_data *) (DWORD_PTR) GetWindowLongPtr(hwnd, DWLP_USER);
-
- if (HIWORD(wParam) == WMCFG_APPLY) {
- write_params(d);
- }
-
- khm_set_dialog_result(hwnd, 0);
-
- return TRUE;
- }
-
- return FALSE;
-}
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<shlwapi.h>
+#include<khmapp.h>
+#include<assert.h>
+
+typedef struct tag_cfg_data {
+ BOOL auto_init;
+ BOOL auto_start;
+ BOOL auto_import;
+ BOOL keep_running;
+ BOOL auto_detect_net;
+ BOOL log_to_file;
+ BOOL destroy_creds;
+ khm_int32 notif_action;
+} cfg_data;
+
+typedef struct tag_dlg_data {
+ khui_config_node node;
+ cfg_data saved;
+ cfg_data work;
+} dlg_data;
+
+static void
+read_params(dlg_data * dd) {
+ cfg_data * d;
+ khm_handle csp_cw;
+ khm_int32 t;
+
+ d = &dd->saved;
+
+ if (KHM_FAILED(khc_open_space(NULL, L"CredWindow", KHM_PERM_READ,
+ &csp_cw))) {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ return;
+ }
+
+ khc_read_int32(csp_cw, L"AutoInit", &t);
+ d->auto_init = !!t;
+
+ khc_read_int32(csp_cw, L"AutoStart", &t);
+ d->auto_start = !!t;
+
+ khc_read_int32(csp_cw, L"AutoImport", &t);
+ d->auto_import = !!t;
+
+ khc_read_int32(csp_cw, L"KeepRunning", &t);
+ d->keep_running = !!t;
+
+ khc_read_int32(csp_cw, L"AutoDetectNet", &t);
+ d->auto_detect_net = !!t;
+
+ khc_read_int32(csp_cw, L"LogToFile", &t);
+ d->log_to_file = !!t;
+
+ khc_read_int32(csp_cw, L"DestroyCredsOnExit", &t);
+ d->destroy_creds = !!t;
+
+ khc_read_int32(csp_cw, L"NotificationAction", &t);
+ d->notif_action = t;
+
+ khc_close_space(csp_cw);
+
+ dd->work = *d;
+}
+
+static void
+write_params(dlg_data * dd) {
+ cfg_data * d, * s;
+ khm_handle csp_cw;
+ BOOL applied = FALSE;
+
+ d = &dd->work;
+ s = &dd->saved;
+
+ if (KHM_FAILED(khc_open_space(NULL, L"CredWindow", KHM_PERM_WRITE,
+ &csp_cw))) {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ return;
+ }
+
+ if (!!d->auto_init != !!s->auto_init) {
+ khc_write_int32(csp_cw, L"AutoInit", d->auto_init);
+ applied = TRUE;
+ }
+
+ if (!!d->auto_start != !!s->auto_start) {
+ khc_write_int32(csp_cw, L"AutoStart", d->auto_start);
+ applied = TRUE;
+ }
+
+ if (!!d->auto_import != !!s->auto_import) {
+ khc_write_int32(csp_cw, L"AutoImport", d->auto_import);
+ applied = TRUE;
+ }
+
+ if (!!d->keep_running != !!s->keep_running) {
+ khc_write_int32(csp_cw, L"KeepRunning", d->keep_running);
+ applied = TRUE;
+ }
+
+ if (!!d->auto_detect_net != !!s->auto_detect_net) {
+ khc_write_int32(csp_cw, L"AutoDetectNet", d->auto_detect_net);
+ applied = TRUE;
+ }
+
+ if (!!d->log_to_file != !!s->log_to_file) {
+ khc_write_int32(csp_cw, L"LogToFile", d->log_to_file);
+ applied = TRUE;
+
+ if (d->log_to_file) {
+ khm_start_file_log();
+ } else {
+ khm_stop_file_log();
+ }
+ }
+
+ if (!!d->destroy_creds != !!s->destroy_creds) {
+ khc_write_int32(csp_cw, L"DestroyCredsOnExit", d->destroy_creds);
+ applied = TRUE;
+ }
+
+ if (d->notif_action != s->notif_action) {
+ khc_write_int32(csp_cw, L"NotificationAction", d->notif_action);
+ applied = TRUE;
+ }
+
+ khc_close_space(csp_cw);
+
+ khui_cfg_set_flags(dd->node,
+ (applied) ? KHUI_CNFLAG_APPLIED : 0,
+ KHUI_CNFLAG_APPLIED | KHUI_CNFLAG_MODIFIED);
+
+ *s = *d;
+}
+
+static void
+check_for_modification(dlg_data * dd) {
+ cfg_data * d, * s;
+ d = &dd->work;
+ s = &dd->saved;
+
+ if (!!d->auto_init != !!s->auto_init ||
+ !!d->auto_start != !!s->auto_start ||
+ !!d->auto_import != !!s->auto_import ||
+ !!d->keep_running != !!s->keep_running ||
+ !!d->auto_detect_net != !!s->auto_detect_net ||
+ !!d->log_to_file != !!s->log_to_file ||
+ !!d->destroy_creds != !!s->destroy_creds ||
+ d->notif_action != s->notif_action) {
+
+ khui_cfg_set_flags(dd->node,
+ KHUI_CNFLAG_MODIFIED,
+ KHUI_CNFLAG_MODIFIED);
+
+ } else {
+
+ khui_cfg_set_flags(dd->node,
+ 0,
+ KHUI_CNFLAG_MODIFIED);
+
+ }
+}
+
+
+static void
+strip_ampersands(wchar_t * str) {
+ wchar_t *f, *t;
+
+ for(f = t = str; *f; f++)
+ if (*f != L'&')
+ *t++ = *f;
+
+ *t = L'\0';
+}
+
+static void
+refresh_view(HWND hwnd, dlg_data * d) {
+ wchar_t buf[512];
+ khm_size i;
+
+ CheckDlgButton(hwnd, IDC_CFG_AUTOINIT,
+ (d->work.auto_init?BST_CHECKED:BST_UNCHECKED));
+ CheckDlgButton(hwnd, IDC_CFG_AUTOSTART,
+ (d->work.auto_start?BST_CHECKED:BST_UNCHECKED));
+ CheckDlgButton(hwnd, IDC_CFG_AUTOIMPORT,
+ (d->work.auto_import?BST_CHECKED:BST_UNCHECKED));
+ CheckDlgButton(hwnd, IDC_CFG_KEEPRUNNING,
+ (d->work.keep_running?BST_CHECKED:BST_UNCHECKED));
+ CheckDlgButton(hwnd, IDC_CFG_NETDETECT,
+ (d->work.auto_detect_net?BST_CHECKED:BST_UNCHECKED));
+ CheckDlgButton(hwnd, IDC_CFG_LOGTOFILE,
+ (d->work.log_to_file?BST_CHECKED:BST_UNCHECKED));
+ CheckDlgButton(hwnd, IDC_CFG_DESTROYALL,
+ (d->work.destroy_creds?BST_CHECKED:BST_UNCHECKED));
+
+ /* we need populate the notification action combo box control and
+ set the current selection to match the default action. */
+
+ if (n_khm_notifier_actions != SendDlgItemMessage(hwnd, IDC_CFG_NOTACTION,
+ CB_GETCOUNT, 0, 0)) {
+
+ for (i=0; i < n_khm_notifier_actions; i++) {
+ int idx;
+
+ khm_get_action_caption(khm_notifier_actions[i],
+ buf, sizeof(buf));
+
+ strip_ampersands(buf);
+
+ idx = (int) SendDlgItemMessage(hwnd, IDC_CFG_NOTACTION,
+ CB_INSERTSTRING, i,
+ (LPARAM) buf);
+
+#ifdef DEBUG
+ if (idx != (int) i) {
+ assert(FALSE);
+ }
+#endif
+ }
+ }
+
+ for (i=0; i < n_khm_notifier_actions; i++) {
+ if (khm_notifier_actions[i] == d->work.notif_action)
+ break;
+ }
+
+ if (i >= n_khm_notifier_actions) {
+ d->work.notif_action = khm_notifier_actions[0];
+ i = 0;
+ }
+
+ SendDlgItemMessage(hwnd, IDC_CFG_NOTACTION, CB_SETCURSEL, i, 0);
+
+ /* in addition, we correct the label on the trace log control to
+ reflect the actual path that is going to get used */
+ if (GetDlgItemText(hwnd, IDC_CFG_LOGPATH, buf,
+ ARRAYLENGTH(buf)) == 0) {
+
+ khm_get_file_log_path(sizeof(buf), buf);
+
+ SetDlgItemText(hwnd, IDC_CFG_LOGPATH, buf);
+ }
+}
+
+static void
+refresh_data(HWND hwnd, dlg_data * d) {
+ int idx;
+
+ d->work.auto_init = (IsDlgButtonChecked(hwnd, IDC_CFG_AUTOINIT)
+ == BST_CHECKED);
+ d->work.auto_start = (IsDlgButtonChecked(hwnd, IDC_CFG_AUTOSTART)
+ == BST_CHECKED);
+ d->work.auto_import = (IsDlgButtonChecked(hwnd, IDC_CFG_AUTOIMPORT)
+ == BST_CHECKED);
+ d->work.keep_running = (IsDlgButtonChecked(hwnd, IDC_CFG_KEEPRUNNING)
+ == BST_CHECKED);
+ d->work.auto_detect_net = (IsDlgButtonChecked(hwnd, IDC_CFG_NETDETECT)
+ == BST_CHECKED);
+ d->work.log_to_file = (IsDlgButtonChecked(hwnd, IDC_CFG_LOGTOFILE)
+ == BST_CHECKED);
+ d->work.destroy_creds = (IsDlgButtonChecked(hwnd, IDC_CFG_DESTROYALL)
+ == BST_CHECKED);
+
+ idx = (int) SendDlgItemMessage(hwnd, IDC_CFG_NOTACTION, CB_GETCURSEL, 0, 0);
+ if (idx < 0)
+ idx = 0;
+ else if (idx >= (int) n_khm_notifier_actions)
+ idx = (int) n_khm_notifier_actions - 1;
+
+ d->work.notif_action = khm_notifier_actions[idx];
+}
+
+INT_PTR CALLBACK
+khm_cfg_general_proc(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam) {
+ dlg_data * d;
+
+ switch(uMsg) {
+ case WM_INITDIALOG:
+ d = PMALLOC(sizeof(*d));
+#ifdef DEBUG
+ assert(d != NULL);
+#endif
+
+#pragma warning(push)
+#pragma warning(disable: 4244)
+ SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) d);
+#pragma warning(pop)
+
+ ZeroMemory(d, sizeof(*d));
+
+ d->node = (khui_config_node) lParam;
+
+ read_params(d);
+
+ refresh_view(hwnd, d);
+
+ return FALSE;
+
+ case WM_DESTROY:
+ d = (dlg_data *) (DWORD_PTR) GetWindowLongPtr(hwnd, DWLP_USER);
+ if (d) {
+ PFREE(d);
+ }
+ return TRUE;
+
+ case WM_COMMAND:
+ d = (dlg_data *) (DWORD_PTR) GetWindowLongPtr(hwnd, DWLP_USER);
+
+ if (HIWORD(wParam) == BN_CLICKED) {
+ if (LOWORD(wParam) == IDC_CFG_SHOWLOG) {
+ /* we need to display the logfile */
+ wchar_t buf[512];
+
+ buf[0] = L'\0';
+ khm_get_file_log_path(sizeof(buf), buf);
+
+ if (!buf[0] ||
+ !PathFileExists(buf)) {
+
+ wchar_t title[256];
+ wchar_t msg[550];
+ wchar_t fmt[256];
+
+ LoadString(khm_hInstance, IDS_CFG_LOGF_CS,
+ title, ARRAYLENGTH(title));
+ LoadString(khm_hInstance, IDS_CFG_LOGF_CSR,
+ fmt, ARRAYLENGTH(fmt));
+
+ StringCbPrintf(msg, sizeof(msg), fmt, buf);
+
+ MessageBox(hwnd, title, msg, MB_OK);
+
+ } else {
+ wchar_t cmdline[550];
+ STARTUPINFO si;
+ PROCESS_INFORMATION pi;
+
+ StringCbCopy(cmdline, sizeof(cmdline), L"notepad.exe ");
+ StringCbCat(cmdline, sizeof(cmdline), L"\"");
+ StringCbCat(cmdline, sizeof(cmdline), buf);
+ StringCbCat(cmdline, sizeof(cmdline), L"\"");
+
+ ZeroMemory(&si, sizeof(si));
+ si.cb = sizeof(si);
+ ZeroMemory(&pi, sizeof(pi));
+
+ CreateProcess(NULL,
+ cmdline,
+ NULL, NULL,
+ FALSE,
+ 0, NULL, NULL,
+ &si,
+ &pi);
+
+ if (pi.hProcess)
+ CloseHandle(pi.hProcess);
+ if (pi.hThread)
+ CloseHandle(pi.hThread);
+
+ }
+ } else {
+ refresh_data(hwnd, d);
+ check_for_modification(d);
+ }
+ } else if (HIWORD(wParam) == CBN_SELCHANGE) {
+ refresh_data(hwnd, d);
+ check_for_modification(d);
+ }
+
+ khm_set_dialog_result(hwnd, 0);
+
+ return TRUE;
+
+ case KHUI_WM_CFG_NOTIFY:
+ d = (dlg_data *) (DWORD_PTR) GetWindowLongPtr(hwnd, DWLP_USER);
+
+ if (HIWORD(wParam) == WMCFG_APPLY) {
+ write_params(d);
+ }
+
+ khm_set_dialog_result(hwnd, 0);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
diff --git a/src/windows/identity/ui/cfg_identities_wnd.c b/src/windows/identity/ui/cfg_identities_wnd.c
index a8813d1164..d45288a3a9 100644
--- a/src/windows/identity/ui/cfg_identities_wnd.c
+++ b/src/windows/identity/ui/cfg_identities_wnd.c
@@ -1,1523 +1,1523 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<khmapp.h>
-#include<assert.h>
-
-static khui_config_node
-get_window_node(HWND hwnd) {
- return (khui_config_node) (LONG_PTR)
- GetWindowLongPtr(hwnd, DWLP_USER);
-}
-
-static void
-set_window_node(HWND hwnd, khui_config_node node) {
-#pragma warning(push)
-#pragma warning(disable: 4244)
- SetWindowLongPtr(hwnd, DWLP_USER,
- (LONG_PTR) node);
-#pragma warning(pop)
-}
-
-static void
-add_subpanels(HWND hwnd,
- khui_config_node ctx_node,
- khui_config_node ref_node) {
-
- HWND hw_tab;
- HWND hw_target;
- khui_config_node sub;
- khui_config_node_reg reg;
- khui_config_init_data idata;
- int idx;
-
- hw_tab = GetDlgItem(hwnd, IDC_CFG_TAB);
- hw_target = GetDlgItem(hwnd, IDC_CFG_TARGET);
-#ifdef DEBUG
- assert(hw_tab);
- assert(hw_target);
-#endif
-
- if (KHM_FAILED(khui_cfg_get_first_subpanel(ref_node, &sub))) {
-#ifdef DEBUG
- assert(FALSE);
-#endif
- return;
- }
-
- idx = 0;
- while(sub) {
- HWND hwnd_panel;
- TCITEM tci;
- int iid;
-
- khui_cfg_get_reg(sub, &reg);
-
- if ((ctx_node == ref_node && (reg.flags & KHUI_CNFLAG_PLURAL)) ||
- (ctx_node != ref_node && !(reg.flags & KHUI_CNFLAG_PLURAL)))
- goto _next_node;
-
- idata.ctx_node = ctx_node;
- idata.this_node = sub;
- idata.ref_node = ref_node;
-
- hwnd_panel = CreateDialogParam(reg.h_module,
- reg.dlg_template,
- hwnd,
- reg.dlg_proc,
- (LPARAM) &idata);
-
-#ifdef DEBUG
- assert(hwnd_panel);
-#endif
-
- ShowWindow(hwnd_panel, SW_HIDE);
-
- ZeroMemory(&tci, sizeof(tci));
-
- tci.mask = TCIF_PARAM | TCIF_TEXT;
- tci.lParam = (LPARAM) sub;
- tci.pszText = (LPWSTR) reg.short_desc;
-
- iid = TabCtrl_InsertItem(hw_tab, 0, &tci);
- idx++;
-
- if (reg.flags & KHUI_CNFLAG_PLURAL) {
- khui_cfg_set_param_inst(sub, ctx_node, iid);
- khui_cfg_set_hwnd_inst(sub, ctx_node, hwnd_panel);
- } else {
- khui_cfg_set_param(sub, iid);
- khui_cfg_set_hwnd(sub, hwnd_panel);
- }
-
- _next_node:
-
- khui_cfg_get_next_release(&sub);
- }
-
- TabCtrl_SetCurSel(hw_tab, 0);
-}
-
-static void
-apply_all(HWND hwnd,
- HWND hw_tab,
- khui_config_node noderef) {
- TCITEM tci;
- HWND hw;
- khui_config_node_reg reg;
- int idx;
- int count;
- BOOL cont = TRUE;
-
- count = TabCtrl_GetItemCount(hw_tab);
-
- for (idx = 0; idx < count && cont; idx++) {
-
- ZeroMemory(&tci, sizeof(tci));
-
- tci.mask = TCIF_PARAM;
- TabCtrl_GetItem(hw_tab,
- idx,
- &tci);
-
-#ifdef DEBUG
- assert(tci.lParam);
-#endif
- khui_cfg_get_reg((khui_config_node) tci.lParam, &reg);
- if (reg.flags & KHUI_CNFLAG_PLURAL)
- hw = khui_cfg_get_hwnd_inst((khui_config_node) tci.lParam,
- noderef);
- else
- hw = khui_cfg_get_hwnd((khui_config_node) tci.lParam);
-#ifdef DEBUG
- assert(hw);
-#endif
-
- SendMessage(hw, KHUI_WM_CFG_NOTIFY,
- MAKEWPARAM(0, WMCFG_APPLY), (LPARAM) &cont);
- }
-}
-
-static void
-show_tab_panel(HWND hwnd,
- khui_config_node node,
- HWND hw_tab,
- int idx,
- BOOL show) {
- TCITEM tci;
- HWND hw;
- HWND hw_target;
- HWND hw_firstctl;
- RECT r;
- RECT rref;
- khui_config_node_reg reg;
-
- ZeroMemory(&tci, sizeof(tci));
-
- tci.mask = TCIF_PARAM;
- TabCtrl_GetItem(hw_tab,
- idx,
- &tci);
-
-#ifdef DEBUG
- assert(tci.lParam);
-#endif
- khui_cfg_get_reg((khui_config_node) tci.lParam, &reg);
- if (reg.flags & KHUI_CNFLAG_PLURAL)
- hw = khui_cfg_get_hwnd_inst((khui_config_node) tci.lParam,
- node);
- else
- hw = khui_cfg_get_hwnd((khui_config_node) tci.lParam);
-#ifdef DEBUG
- assert(hw);
-#endif
-
- if (!show) {
- ShowWindow(hw, SW_HIDE);
- return;
- }
-
- hw_target = GetDlgItem(hwnd, IDC_CFG_TARGET);
-#ifdef DEBUG
- assert(hw_target);
-#endif
- GetWindowRect(hwnd, &rref);
- GetWindowRect(hw_target, &r);
-
- OffsetRect(&r, -rref.left, -rref.top);
-
- SetWindowPos(hw,
- hw_tab,
- r.left, r.top,
- r.right - r.left, r.bottom - r.top,
- SWP_NOACTIVATE | SWP_NOOWNERZORDER |
- SWP_SHOWWINDOW);
-
- hw_firstctl = GetNextDlgTabItem(hw, NULL, FALSE);
- if (hw_firstctl) {
- SetFocus(hw_firstctl);
- }
-}
-
-static INT_PTR
-handle_cfg_notify(HWND hwnd,
- WPARAM wParam,
- LPARAM lParam) {
- khui_config_node node;
- HWND hw;
-
- node = get_window_node(hwnd);
-
- if (HIWORD(wParam) == WMCFG_APPLY) {
-
- hw = GetDlgItem(hwnd, IDC_CFG_TAB);
-
- apply_all(hwnd,
- hw,
- node);
- }
-
- return TRUE;
-}
-
-static INT_PTR
-handle_notify(HWND hwnd,
- WPARAM wParam,
- LPARAM lParam) {
- LPNMHDR lpnm;
- int i;
-
-
- khui_config_node node;
-
- lpnm = (LPNMHDR) lParam;
- node = get_window_node(hwnd);
-
- if (lpnm->idFrom == IDC_CFG_TAB) {
- switch(lpnm->code) {
- case TCN_SELCHANGING:
- i = TabCtrl_GetCurSel(lpnm->hwndFrom);
-
- show_tab_panel(hwnd,
- node,
- lpnm->hwndFrom,
- i,
- FALSE);
- break;
-
- case TCN_SELCHANGE:
- i = TabCtrl_GetCurSel(lpnm->hwndFrom);
-
- show_tab_panel(hwnd,
- node,
- lpnm->hwndFrom,
- i,
- TRUE);
- break;
- }
- return TRUE;
- } else {
- return FALSE;
- }
-}
-
-typedef struct tag_ident_props {
- BOOL monitor;
- BOOL auto_renew;
- BOOL sticky;
-} ident_props;
-
-typedef struct tag_ident_data {
- khm_handle ident;
- wchar_t * idname;
- int lv_idx;
-
- BOOL removed;
- BOOL applied;
-
- khm_int32 flags;
-
- ident_props saved;
- ident_props work;
-
- HWND hwnd;
-} ident_data;
-
-typedef struct tag_global_props {
- BOOL monitor;
- BOOL auto_renew;
- BOOL sticky;
-} global_props;
-
-typedef struct tag_idents_data {
- BOOL valid;
-
- ident_data * idents;
- khm_size n_idents;
- khm_size nc_idents;
-#define IDENTS_DATA_ALLOC_INCR 8
-
- /* global options */
- global_props saved;
- global_props work;
- BOOL applied;
-
- int refcount;
-
- HIMAGELIST hi_status;
- int idx_id;
- int idx_default;
- int idx_modified;
- int idx_applied;
- int idx_deleted;
-
- HWND hwnd;
- khui_config_init_data cfg;
-} idents_data;
-
-static idents_data cfg_idents = {FALSE, NULL, 0, 0,
- {0, 0, 0},
- {0, 0, 0},
- FALSE,
-
- 0, NULL };
-
-static void
-read_params_ident(ident_data * d) {
- khm_handle csp_ident;
- khm_handle csp_cw;
- khm_int32 t;
-
- if (KHM_FAILED(kcdb_identity_get_config(d->ident,
- KHM_PERM_READ,
- &csp_ident))) {
- csp_ident = NULL;
- }
-
- if (KHM_SUCCEEDED(khc_open_space(NULL, L"CredWindow", KHM_PERM_READ,
- &csp_cw))) {
- if (csp_ident) {
- khc_shadow_space(csp_ident,
- csp_cw);
- khc_close_space(csp_cw);
- } else {
- csp_ident = csp_cw;
- }
- csp_cw = NULL;
- } else {
-#ifdef DEBUG
- assert(FALSE);
-#endif
- d->saved.monitor = TRUE;
- d->saved.auto_renew = TRUE;
- d->saved.sticky = FALSE;
- d->work = d->saved;
-
- if (csp_ident)
- khc_close_space(csp_ident);
-
- return;
- }
-
- if (KHM_FAILED(khc_read_int32(csp_ident, L"Monitor", &t))) {
-#ifdef DEBUG
- assert(FALSE);
-#endif
- d->saved.monitor = TRUE;
- } else {
- d->saved.monitor = !!t;
- }
-
- if (KHM_FAILED(khc_read_int32(csp_ident, L"AllowAutoRenew", &t))) {
-#ifdef DEBUG
- assert(FALSE);
-#endif
- d->saved.auto_renew = TRUE;
- } else {
- d->saved.auto_renew = !!t;
- }
-
- if (KHM_FAILED(khc_read_int32(csp_ident, L"Sticky", &t))) {
- d->saved.sticky = FALSE;
- } else {
- d->saved.sticky = !!t;
- }
-
- khc_close_space(csp_ident);
-
- d->work = d->saved;
- d->applied = FALSE;
-}
-
-static void
-write_params_ident(ident_data * d) {
- khm_handle csp_ident;
-
- if (d->saved.monitor == d->work.monitor &&
- d->saved.auto_renew == d->work.auto_renew &&
- d->saved.sticky == d->work.sticky &&
- !d->removed)
- return;
-
- if (KHM_FAILED(kcdb_identity_get_config(d->ident, KHM_PERM_WRITE,
- &csp_ident))) {
-#ifdef DEBUG
- assert(FALSE);
-#endif
- return;
- }
-
- if (d->removed) {
- khm_handle h = NULL;
- khm_int32 flags = 0;
-
- khc_remove_space(csp_ident);
-
- /* calling kcdb_identity_get_config() will update the
- KCDB_IDENT_FLAG_CONFIG flag for the identity to reflect the
- fact that it nolonger has a configuration. */
- kcdb_identity_get_config(d->ident, 0, &h);
- if (h) {
- /* what the ? */
-#ifdef DEBUG
- assert(FALSE);
-#endif
- khc_close_space(h);
- }
-#ifdef DEBUG
- kcdb_identity_get_flags(d->ident, &flags);
- assert(!(flags & KCDB_IDENT_FLAG_CONFIG));
-#endif
-
- } else {
-
- if (d->saved.monitor != d->work.monitor)
- khc_write_int32(csp_ident, L"Monitor", !!d->work.monitor);
-
- if (d->saved.auto_renew != d->work.auto_renew)
- khc_write_int32(csp_ident, L"AllowAutoRenew",
- !!d->work.auto_renew);
-
- if (d->saved.sticky != d->work.sticky) {
- kcdb_identity_set_flags(d->ident,
- (d->work.sticky)?KCDB_IDENT_FLAG_STICKY:0,
- KCDB_IDENT_FLAG_STICKY);
- }
- }
-
- khc_close_space(csp_ident);
-
- d->saved = d->work;
-
- d->applied = TRUE;
-
- if (d->hwnd)
- PostMessage(d->hwnd, KHUI_WM_CFG_NOTIFY,
- MAKEWPARAM(0, WMCFG_UPDATE_STATE), 0);
-
- khm_refresh_config();
-}
-
-static void
-write_params_idents(void) {
- khm_handle csp_cw = NULL;
-
- if (KHM_SUCCEEDED(khc_open_space(NULL, L"CredWindow",
- KHM_FLAG_CREATE, &csp_cw))) {
- if (cfg_idents.work.monitor != cfg_idents.saved.monitor) {
- khc_write_int32(csp_cw, L"DefaultMonitor",
- !!cfg_idents.work.monitor);
- cfg_idents.work.monitor = cfg_idents.saved.monitor;
- cfg_idents.applied = TRUE;
- }
- if (cfg_idents.work.auto_renew != cfg_idents.saved.auto_renew) {
- khc_write_int32(csp_cw, L"DefaultAllowAutoRenew",
- !!cfg_idents.work.auto_renew);
- cfg_idents.work.auto_renew = cfg_idents.saved.auto_renew;
- cfg_idents.applied = TRUE;
- }
- if (cfg_idents.work.sticky != cfg_idents.saved.sticky) {
- khc_write_int32(csp_cw, L"DefaultSticky",
- !!cfg_idents.work.sticky);
- cfg_idents.work.sticky = cfg_idents.saved.sticky;
- cfg_idents.applied = TRUE;
- }
-
- khc_close_space(csp_cw);
- csp_cw = NULL;
- }
-
-#if 0
- for (i=0; i < (int)cfg_idents.n_idents; i++) {
- write_params_ident(&cfg_idents.idents[i]);
- }
-#endif
-
- if (cfg_idents.hwnd)
- PostMessage(cfg_idents.hwnd, KHUI_WM_CFG_NOTIFY,
- MAKEWPARAM(0, WMCFG_UPDATE_STATE), 0);
-}
-
-static void
-init_idents_data(void) {
- khm_int32 rv;
- wchar_t * t;
- wchar_t * widnames = NULL;
- khm_size cb;
- int n_tries = 0;
- int i;
- khm_handle csp_cw = NULL;
-
- if (cfg_idents.valid)
- return;
-
-#ifdef DEBUG
- assert(cfg_idents.idents == NULL);
- assert(cfg_idents.n_idents == 0);
- assert(cfg_idents.nc_idents == 0);
-#endif
-
- if (KHM_SUCCEEDED(khc_open_space(NULL, L"CredWindow", 0, &csp_cw))) {
- khm_int32 t;
-
- if (KHM_SUCCEEDED(khc_read_int32(csp_cw, L"DefaultMonitor", &t)))
- cfg_idents.saved.monitor = !!t;
- else
- cfg_idents.saved.monitor = TRUE;
-
- if (KHM_SUCCEEDED(khc_read_int32(csp_cw, L"DefaultAllowAutoRenew", &t)))
- cfg_idents.saved.auto_renew = !!t;
- else
- cfg_idents.saved.auto_renew = TRUE;
-
- if (KHM_SUCCEEDED(khc_read_int32(csp_cw, L"DefaultSticky", &t)))
- cfg_idents.saved.sticky = !!t;
- else
- cfg_idents.saved.sticky = FALSE;
-
- khc_close_space(csp_cw);
- csp_cw = NULL;
-
- } else {
-
- cfg_idents.saved.monitor = TRUE;
- cfg_idents.saved.auto_renew = TRUE;
- cfg_idents.saved.sticky = FALSE;
-
- }
-
- cfg_idents.work = cfg_idents.saved;
- cfg_idents.applied = FALSE;
-
- do {
- rv = kcdb_identity_enum(KCDB_IDENT_FLAG_CONFIG,
- KCDB_IDENT_FLAG_CONFIG,
- NULL,
- &cb,
- &cfg_idents.n_idents);
-
- if (rv != KHM_ERROR_TOO_LONG ||
- cfg_idents.n_idents == 0 ||
- cb == 0)
- break;
-
- if (widnames)
- PFREE(widnames);
- widnames = PMALLOC(cb);
-#ifdef DEBUG
- assert(widnames);
-#endif
-
- rv = kcdb_identity_enum(KCDB_IDENT_FLAG_CONFIG,
- KCDB_IDENT_FLAG_CONFIG,
- widnames,
- &cb,
- &cfg_idents.n_idents);
- n_tries++;
- } while(KHM_FAILED(rv) &&
- n_tries < 5);
-
- if (KHM_FAILED(rv) ||
- cfg_idents.n_idents == 0) {
- cfg_idents.n_idents = 0;
- goto _cleanup;
- }
-
- cfg_idents.idents = PMALLOC(sizeof(*cfg_idents.idents) *
- cfg_idents.n_idents);
-#ifdef DEBUG
- assert(cfg_idents.idents);
-#endif
- ZeroMemory(cfg_idents.idents,
- sizeof(*cfg_idents.idents) * cfg_idents.n_idents);
- cfg_idents.nc_idents = cfg_idents.n_idents;
-
- i = 0;
- for (t = widnames; t && *t; t = multi_string_next(t)) {
- khm_handle ident;
-
- if (KHM_FAILED(kcdb_identity_create(t, 0, &ident))) {
- cfg_idents.n_idents--;
- continue;
- }
-
- StringCbLength(t, KCDB_IDENT_MAXCB_NAME, &cb);
- cb += sizeof(wchar_t);
-
- cfg_idents.idents[i].idname = PMALLOC(cb);
-#ifdef DEBUG
- assert(cfg_idents.idents[i].idname);
-#endif
- StringCbCopy(cfg_idents.idents[i].idname, cb, t);
-
- cfg_idents.idents[i].ident = ident;
- cfg_idents.idents[i].removed = FALSE;
-
- kcdb_identity_get_flags(ident, &cfg_idents.idents[i].flags);
-#ifdef DEBUG
- assert(cfg_idents.idents[i].flags & KCDB_IDENT_FLAG_CONFIG);
-#endif
-
- read_params_ident(&cfg_idents.idents[i]);
-
- i++;
- /* leave identity held */
- }
-
- _cleanup:
-
- cfg_idents.valid = TRUE;
-
- if (widnames)
- PFREE(widnames);
-}
-
-static void
-free_idents_data(void) {
- int i;
-
- if (!cfg_idents.valid)
- return;
-
- for (i=0; i< (int) cfg_idents.n_idents; i++) {
- if (cfg_idents.idents[i].ident)
- kcdb_identity_release(cfg_idents.idents[i].ident);
- if (cfg_idents.idents[i].idname)
- PFREE(cfg_idents.idents[i].idname);
- }
-
- if (cfg_idents.idents)
- PFREE(cfg_idents.idents);
-
- cfg_idents.idents = NULL;
- cfg_idents.n_idents = 0;
- cfg_idents.nc_idents = 0;
- cfg_idents.valid = FALSE;
-}
-
-static void
-hold_idents_data(void) {
- if (!cfg_idents.valid)
- init_idents_data();
-#ifdef DEBUG
- assert(cfg_idents.valid);
-#endif
- cfg_idents.refcount++;
-}
-
-static void
-release_idents_data(void) {
-#ifdef DEBUG
- assert(cfg_idents.valid);
-#endif
- cfg_idents.refcount--;
-
- if (cfg_idents.refcount == 0)
- free_idents_data();
-}
-
-
-static void
-refresh_data_idents(HWND hwnd) {
- cfg_idents.work.monitor =
- (IsDlgButtonChecked(hwnd, IDC_CFG_MONITOR) == BST_CHECKED);
- cfg_idents.work.auto_renew =
- (IsDlgButtonChecked(hwnd, IDC_CFG_RENEW) == BST_CHECKED);
- cfg_idents.work.sticky =
- (IsDlgButtonChecked(hwnd, IDC_CFG_STICKY) == BST_CHECKED);
-}
-
-static void
-refresh_view_idents_state(HWND hwnd) {
- BOOL modified;
- BOOL applied;
- khm_int32 flags = 0;
-
- applied = cfg_idents.applied;
- modified = (cfg_idents.work.monitor != cfg_idents.saved.monitor ||
- cfg_idents.work.auto_renew != cfg_idents.saved.auto_renew ||
- cfg_idents.work.sticky != cfg_idents.saved.sticky);
-
- if (modified)
- flags |= KHUI_CNFLAG_MODIFIED;
- if (applied)
- flags |= KHUI_CNFLAG_APPLIED;
-
- khui_cfg_set_flags_inst(&cfg_idents.cfg, flags,
- KHUI_CNFLAG_APPLIED | KHUI_CNFLAG_MODIFIED);
-}
-
-struct ctrl_row_dimensions {
- RECT enclosure;
- RECT label;
- RECT control;
-};
-
-typedef struct tag_add_ident_data {
- khui_new_creds * nc;
-
- struct ctrl_row_dimensions dim_small;
- struct ctrl_row_dimensions dim_medium;
- struct ctrl_row_dimensions dim_large;
- int row_gap;
-
- int current_y;
- int current_x;
-
- HWND hwnd_last_ctrl;
-} add_ident_data;
-
-void
-get_ctrl_row_metrics(struct ctrl_row_dimensions * dim, HWND hw_lbl, HWND hw_ctl) {
-
- assert(hw_lbl);
- assert(hw_ctl);
-
- GetWindowRect(hw_lbl, &dim->label);
- GetWindowRect(hw_ctl, &dim->control);
-
- UnionRect(&dim->enclosure, &dim->label, &dim->control);
- OffsetRect(&dim->label,
- -dim->enclosure.left,
- -dim->enclosure.top);
- OffsetRect(&dim->control,
- -dim->enclosure.left,
- -dim->enclosure.top);
- OffsetRect(&dim->enclosure,
- -dim->enclosure.left,
- -dim->enclosure.top);
-}
-
-/* dialog box procedure for the "Add new identity" dialog */
-INT_PTR CALLBACK
-khm_cfg_add_ident_proc(HWND hwnd,
- UINT umsg,
- WPARAM wParam,
- LPARAM lParam) {
- add_ident_data * d;
-
- switch(umsg) {
- case WM_INITDIALOG:
- /* we create a new credentials blob and pull in the identity
- selectors from the identity provider. */
- d = PMALLOC(sizeof(*d));
- ZeroMemory(d, sizeof(*d));
-
- khui_cw_create_cred_blob(&d->nc);
-#ifdef DEBUG
- assert(d->nc != NULL);
-#endif
- if (d->nc == NULL) {
- PFREE(d);
- break;
- }
-
- if (KHM_FAILED(kcdb_identpro_get_ui_cb(&d->nc->ident_cb))) {
- /* this should have worked. The only reason it would fail
- is if there is no identity provider or if the identity
- provider does not support providing idnetity
- selectors. */
- khui_cw_destroy_cred_blob(d->nc);
- PFREE(d);
- break;
- }
-
-#pragma warning(push)
-#pragma warning(disable: 4244)
- SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) d);
-#pragma warning(pop)
-
- /* get metrics for dynamic controls */
- get_ctrl_row_metrics(&d->dim_small,
- GetDlgItem(hwnd, IDC_SM_LBL),
- GetDlgItem(hwnd, IDC_SM_CTL));
- get_ctrl_row_metrics(&d->dim_medium,
- GetDlgItem(hwnd, IDC_MED_LBL),
- GetDlgItem(hwnd, IDC_MED_CTL));
- get_ctrl_row_metrics(&d->dim_large,
- GetDlgItem(hwnd, IDC_LG_LBL),
- GetDlgItem(hwnd, IDC_LG_CTL));
-
- {
- RECT rlbl;
- RECT rctl;
- RECT rwnd;
-
- GetWindowRect(GetDlgItem(hwnd, IDC_SM_LBL),
- &rlbl);
- GetWindowRect(GetDlgItem(hwnd, IDC_SM_CTL),
- &rctl);
- GetWindowRect(hwnd, &rwnd);
-
- OffsetRect(&rlbl, -rwnd.left, -rwnd.top);
- OffsetRect(&rctl, -rwnd.left, -rwnd.top);
-
- d->current_x = rlbl.left;
- d->current_y = rctl.top - GetSystemMetrics(SM_CYCAPTION);
-
- GetWindowRect(GetDlgItem(hwnd, IDC_MED_CTL),
- &rlbl);
- OffsetRect(&rlbl, -rwnd.left, -rwnd.top);
-
- d->row_gap = rlbl.top - rctl.bottom;
- }
-
- d->nc->hwnd = hwnd;
-
- /* now call the UI callback and make it create the
- controls. */
- d->nc->ident_cb(d->nc, WMNC_IDENT_INIT, NULL, 0, 0,
- (LPARAM) hwnd);
-
- break;
-
- case WM_DESTROY:
- d = (add_ident_data *)(LONG_PTR)
- GetWindowLongPtr(hwnd, DWLP_USER);
- if (d == NULL)
- break;
-
- d->nc->ident_cb(d->nc, WMNC_IDENT_EXIT, NULL, 0, 0, 0);
-
- khui_cw_destroy_cred_blob(d->nc);
- PFREE(d);
- break;
-
- case KHUI_WM_NC_NOTIFY:
- d = (add_ident_data *)(LONG_PTR)
- GetWindowLongPtr(hwnd, DWLP_USER);
-
- switch(HIWORD(wParam)) {
- case WMNC_ADD_CONTROL_ROW:
- {
- khui_control_row * row;
- RECT r_lbl, r_inp, r_enc;
- struct ctrl_row_dimensions * dim;
- HFONT hf;
-
- row = (khui_control_row *) lParam;
-
-#ifdef DEBUG
- assert(row->label);
- assert(row->input);
- assert(d);
-#endif
-
- if (row->size == KHUI_CTRLSIZE_SMALL) {
- dim = &d->dim_small;
- } else if (row->size == KHUI_CTRLSIZE_HALF) {
- dim = &d->dim_medium;
- } else {
- dim = &d->dim_large;
-#ifdef DEBUG
- assert(row->size == KHUI_CTRLSIZE_FULL);
-#endif
- }
-
- CopyRect(&r_enc, &dim->enclosure);
- CopyRect(&r_lbl, &dim->label);
- CopyRect(&r_inp, &dim->control);
-
- OffsetRect(&r_enc, d->current_x, d->current_y);
- OffsetRect(&r_lbl, r_enc.left, r_enc.top);
- OffsetRect(&r_inp, r_enc.left, r_enc.top);
-
- d->current_y += r_enc.bottom - r_enc.top;
-
- hf = (HFONT) SendDlgItemMessage(hwnd, IDOK, WM_GETFONT, 0, 0);
-
- if (row->label) {
- SetWindowPos(row->label,
- ((d->hwnd_last_ctrl != NULL)?
- d->hwnd_last_ctrl :
- HWND_TOP),
- r_lbl.left, r_lbl.top,
- r_lbl.right - r_lbl.left,
- r_lbl.bottom - r_lbl.top,
- SWP_DEFERERASE | SWP_NOACTIVATE |
- SWP_NOOWNERZORDER);
- if (hf)
- SendMessage(row->label, WM_SETFONT,
- (WPARAM) hf,
- TRUE);
- d->hwnd_last_ctrl = row->label;
- }
-
- if (row->input) {
- SetWindowPos(row->input,
- ((d->hwnd_last_ctrl != NULL)?
- d->hwnd_last_ctrl :
- HWND_TOP),
- r_inp.left, r_inp.top,
- r_inp.right - r_inp.left,
- r_inp.bottom - r_inp.top,
- SWP_DEFERERASE | SWP_NOACTIVATE |
- SWP_NOOWNERZORDER);
- if (hf)
- SendMessage(row->input, WM_SETFONT,
- (WPARAM) hf,
- TRUE);
- d->hwnd_last_ctrl = row->input;
- }
- }
- break;
-
- case WMNC_IDENTITY_CHANGE:
- break;
- }
- return TRUE;
-
- case WM_COMMAND:
- if (LOWORD(wParam) == IDOK) {
- wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
- wchar_t err_msg[1024];
- khm_handle ident = NULL;
- khm_handle csp_ident = NULL;
- khm_size cb;
- khm_int32 rv = KHM_ERROR_SUCCESS;
-
- d = (add_ident_data *)(LONG_PTR)
- GetWindowLongPtr(hwnd, DWLP_USER);
-
- if (!d || !d->nc)
- break;
-
- /* check if there was an identity selected */
- if (d->nc->n_identities == 0 ||
- d->nc->identities[0] == NULL) {
-
- StringCbCopy(idname, sizeof(idname), L"");
-
- LoadString(khm_hInstance, IDS_CFG_IDNAME_NON,
- err_msg, ARRAYLENGTH(err_msg));
-
- goto show_failure;
- }
-
- ident = d->nc->identities[0];
- kcdb_identity_hold(ident);
-
- cb = sizeof(idname);
- kcdb_identity_get_name(ident, idname, &cb);
-
- /* now we have to create the identity configuration. */
- if (KHM_FAILED(rv = kcdb_identity_get_config(ident,
- KHM_FLAG_CREATE,
- &csp_ident))) {
- wchar_t fmt[256];
-
- LoadString(khm_hInstance, IDS_CFG_IDNAME_CCC,
- fmt, ARRAYLENGTH(fmt));
- StringCbPrintf(err_msg, sizeof(err_msg), fmt, rv);
-
- kcdb_identity_release(ident);
-
- goto show_failure;
- }
-
- /* create a value so that the configuration space will
- actually be created in the registry. We don't want
- this new identity to be sticky. */
- khc_write_int32(csp_ident, L"Sticky", 0);
-
- khm_refresh_config();
-
- kcdb_identity_release(ident);
- khc_close_space(csp_ident);
-
- EndDialog(hwnd, 0);
- break;
-
- show_failure:
- {
- wchar_t title[512];
- wchar_t fmt[256];
-
- if (!err_msg[0])
- break;
-
- LoadString(khm_hInstance, IDS_CFG_IDNAME_PRB,
- fmt, ARRAYLENGTH(fmt));
- StringCbPrintf(title, sizeof(title), fmt, idname);
-
- MessageBox(hwnd, err_msg, title, MB_OK | MB_ICONSTOP);
-
- /* don't end the dialog yet */
- break;
- }
- break;
-
- } else if (LOWORD(wParam) == IDCANCEL) {
- EndDialog(hwnd, 1);
- } else {
- d = (add_ident_data *)(LONG_PTR)
- GetWindowLongPtr(hwnd, DWLP_USER);
-
- if (d && d->nc && d->nc->ident_cb) {
- return d->nc->ident_cb(d->nc, WMNC_IDENT_WMSG,
- hwnd, umsg, wParam, lParam);
- }
- }
- break;
- }
-
- return FALSE;
-}
-
-/* dialog procedure for the "general" pane of the "identities"
- configuration node. */
-INT_PTR CALLBACK
-khm_cfg_ids_tab_proc(HWND hwnd,
- UINT umsg,
- WPARAM wParam,
- LPARAM lParam) {
-
- switch(umsg) {
- case WM_INITDIALOG:
- {
- HICON hicon;
-
- hold_idents_data();
-
- cfg_idents.hwnd = hwnd;
- cfg_idents.cfg = *((khui_config_init_data *) lParam);
-
- /* add the status icons */
- if (cfg_idents.hi_status)
- goto _done_with_icons;
-
- cfg_idents.hi_status =
- ImageList_Create(GetSystemMetrics(SM_CXSMICON),
- GetSystemMetrics(SM_CYSMICON),
- ILC_COLOR8 | ILC_MASK,
- 4,4);
-
- hicon =
- LoadImage(khm_hInstance, MAKEINTRESOURCE(IDI_ID),
- IMAGE_ICON,
- GetSystemMetrics(SM_CXSMICON),
- GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR);
-
- cfg_idents.idx_id = ImageList_AddIcon(cfg_idents.hi_status,
- hicon);
-
- DestroyIcon(hicon);
-
- hicon = LoadImage(khm_hInstance, MAKEINTRESOURCE(IDI_CFG_DEFAULT),
- IMAGE_ICON, GetSystemMetrics(SM_CXSMICON),
- GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR);
-
- cfg_idents.idx_default = ImageList_AddIcon(cfg_idents.hi_status,
- hicon) + 1;
-
- DestroyIcon(hicon);
-
- hicon = LoadImage(khm_hInstance, MAKEINTRESOURCE(IDI_CFG_MODIFIED),
- IMAGE_ICON, GetSystemMetrics(SM_CXSMICON),
- GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR);
-
- cfg_idents.idx_modified = ImageList_AddIcon(cfg_idents.hi_status,
- hicon) + 1;
-
- DestroyIcon(hicon);
-
- hicon = LoadImage(khm_hInstance, MAKEINTRESOURCE(IDI_CFG_APPLIED),
- IMAGE_ICON, GetSystemMetrics(SM_CXSMICON),
- GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR);
-
- cfg_idents.idx_applied = ImageList_AddIcon(cfg_idents.hi_status,
- hicon) + 1;
-
- DestroyIcon(hicon);
-
- hicon = LoadImage(khm_hInstance, MAKEINTRESOURCE(IDI_CFG_DELETED),
- IMAGE_ICON, GetSystemMetrics(SM_CXSMICON),
- GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR);
-
- cfg_idents.idx_deleted = ImageList_AddIcon(cfg_idents.hi_status,
- hicon) + 1;
-
- DestroyIcon(hicon);
-
- _done_with_icons:
-
- CheckDlgButton(hwnd, IDC_CFG_MONITOR,
- (cfg_idents.work.monitor)?BST_CHECKED:BST_UNCHECKED);
- CheckDlgButton(hwnd, IDC_CFG_RENEW,
- (cfg_idents.work.auto_renew)?BST_CHECKED:BST_UNCHECKED);
- CheckDlgButton(hwnd, IDC_CFG_STICKY,
- (cfg_idents.work.sticky)?BST_CHECKED:BST_UNCHECKED);
-
- }
- return FALSE;
-
- case WM_COMMAND:
-
- if (HIWORD(wParam) == BN_CLICKED) {
- UINT ctrl = LOWORD(wParam);
-
- switch(ctrl) {
- case IDC_CFG_MONITOR:
- case IDC_CFG_RENEW:
- case IDC_CFG_STICKY:
- refresh_data_idents(hwnd);
- break;
-
- case IDC_CFG_ADDIDENT:
- DialogBoxParam(khm_hInstance,
- MAKEINTRESOURCE(IDD_CFG_ADDIDENT),
- hwnd,
- khm_cfg_add_ident_proc,
- (LPARAM) hwnd);
- break;
- }
-
- refresh_view_idents_state(hwnd);
- }
-
- khm_set_dialog_result(hwnd, 0);
- return TRUE;
-
- case KHUI_WM_CFG_NOTIFY:
- {
- switch(HIWORD(wParam)) {
- case WMCFG_APPLY:
- write_params_idents();
- break;
-
- case WMCFG_UPDATE_STATE:
- refresh_view_idents_state(hwnd);
- break;
- }
- }
- return TRUE;
-
- case WM_DESTROY:
- cfg_idents.hwnd = NULL;
-
- if (cfg_idents.hi_status != NULL) {
- ImageList_Destroy(cfg_idents.hi_status);
- cfg_idents.hi_status = NULL;
- }
- release_idents_data();
-
- khm_set_dialog_result(hwnd, 0);
-
- return TRUE;
- }
-
- return FALSE;
-}
-
-/* dialog procedure for the "Identities" configuration node */
-INT_PTR CALLBACK
-khm_cfg_identities_proc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam) {
- HWND hw;
- switch(uMsg) {
- case WM_INITDIALOG:
- set_window_node(hwnd, (khui_config_node) lParam);
- add_subpanels(hwnd, (khui_config_node) lParam,
- (khui_config_node) lParam);
- hw = GetDlgItem(hwnd, IDC_CFG_TAB);
- show_tab_panel(hwnd,
- (khui_config_node) lParam,
- hw,
- TabCtrl_GetCurSel(hw),
- TRUE);
- return FALSE;
-
- case WM_DESTROY:
- return 0;
-
- case KHUI_WM_CFG_NOTIFY:
- return handle_cfg_notify(hwnd, wParam, lParam);
-
- case WM_NOTIFY:
- return handle_notify(hwnd, wParam, lParam);
- }
-
- return FALSE;
-}
-
-static ident_data *
-find_ident_by_node(khui_config_node node) {
- khm_size cb;
- wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
- int i;
- khm_handle ident = NULL;
-
- cb = sizeof(idname);
- khui_cfg_get_name(node, idname, &cb);
-
- for (i=0; i < (int)cfg_idents.n_idents; i++) {
- if (!wcscmp(cfg_idents.idents[i].idname, idname))
- break;
- }
-
- if (i < (int)cfg_idents.n_idents)
- return &cfg_idents.idents[i];
-
- /* there is no identity data for this configuration node. We try
- to create it. */
- if (KHM_FAILED(kcdb_identity_create(idname, 0, &ident)))
- return NULL;
-
- if (cfg_idents.n_idents >= cfg_idents.nc_idents) {
- cfg_idents.nc_idents = UBOUNDSS(cfg_idents.n_idents + 1,
- IDENTS_DATA_ALLOC_INCR,
- IDENTS_DATA_ALLOC_INCR);
-#ifdef DEBUG
- assert(cfg_idents.nc_idents > cfg_idents.n_idents);
-#endif
- cfg_idents.idents = PREALLOC(cfg_idents.idents,
- sizeof(*cfg_idents.idents) *
- cfg_idents.nc_idents);
-#ifdef DEBUG
- assert(cfg_idents.idents);
-#endif
- ZeroMemory(&(cfg_idents.idents[cfg_idents.n_idents]),
- sizeof(*cfg_idents.idents) *
- (cfg_idents.nc_idents - cfg_idents.n_idents));
- }
-
- i = (int) cfg_idents.n_idents;
-
- StringCbLength(idname, KCDB_IDENT_MAXCB_NAME, &cb);
- cb += sizeof(wchar_t);
-
- cfg_idents.idents[i].idname = PMALLOC(cb);
-#ifdef DEBUG
- assert(cfg_idents.idents[i].idname);
-#endif
- StringCbCopy(cfg_idents.idents[i].idname, cb, idname);
-
- cfg_idents.idents[i].ident = ident;
- cfg_idents.idents[i].removed = FALSE;
-
- kcdb_identity_get_flags(ident, &cfg_idents.idents[i].flags);
-#ifdef DEBUG
- assert(cfg_idents.idents[i].flags & KCDB_IDENT_FLAG_CONFIG);
-#endif
-
- read_params_ident(&cfg_idents.idents[i]);
-
- cfg_idents.n_idents++;
-
- /* leave ident held. */
-
- return &cfg_idents.idents[i];
-}
-
-static void
-refresh_view_ident(HWND hwnd, khui_config_node node) {
- ident_data * d;
-
- d = find_ident_by_node(node);
-#ifdef DEBUG
- assert(d);
-#endif
-
- CheckDlgButton(hwnd, IDC_CFG_MONITOR,
- (d->work.monitor? BST_CHECKED: BST_UNCHECKED));
- CheckDlgButton(hwnd, IDC_CFG_RENEW,
- (d->work.auto_renew? BST_CHECKED: BST_UNCHECKED));
- CheckDlgButton(hwnd, IDC_CFG_STICKY,
- (d->work.sticky? BST_CHECKED: BST_UNCHECKED));
-}
-
-static void
-mark_remove_ident(HWND hwnd, khui_config_init_data * idata) {
- ident_data * d;
-
- d = find_ident_by_node(idata->ctx_node);
-#ifdef DEBUG
- assert(d);
-#endif
-
- if (d->removed)
- return;
-
- d->removed = TRUE;
-
- khui_cfg_set_flags_inst(idata, KHUI_CNFLAG_MODIFIED,
- KHUI_CNFLAG_MODIFIED);
-
- EnableWindow(GetDlgItem(hwnd, IDC_CFG_REMOVE), FALSE);
-}
-
-static void
-refresh_data_ident(HWND hwnd, khui_config_init_data * idata) {
- ident_data * d;
-
- d = find_ident_by_node(idata->ctx_node);
-#ifdef DEBUG
- assert(d);
-#endif
-
- if (IsDlgButtonChecked(hwnd, IDC_CFG_MONITOR) == BST_CHECKED)
- d->work.monitor = TRUE;
- else
- d->work.monitor = FALSE;
-
- if (IsDlgButtonChecked(hwnd, IDC_CFG_RENEW) == BST_CHECKED)
- d->work.auto_renew = TRUE;
- else
- d->work.auto_renew = FALSE;
-
- if (IsDlgButtonChecked(hwnd, IDC_CFG_STICKY) == BST_CHECKED)
- d->work.sticky = TRUE;
- else
- d->work.sticky = FALSE;
-
- if (d->work.monitor != d->saved.monitor ||
- d->work.auto_renew != d->saved.auto_renew ||
- d->work.sticky != d->saved.sticky) {
-
- khui_cfg_set_flags_inst(idata, KHUI_CNFLAG_MODIFIED,
- KHUI_CNFLAG_MODIFIED);
-
- } else {
- khui_cfg_set_flags_inst(idata, 0,
- KHUI_CNFLAG_MODIFIED);
- }
-}
-
-/* dialog procedure for the "general" pane of individual identity
- configuration nodes. */
-INT_PTR CALLBACK
-khm_cfg_id_tab_proc(HWND hwnd,
- UINT umsg,
- WPARAM wParam,
- LPARAM lParam) {
-
- khui_config_init_data * idata;
-
- switch(umsg) {
- case WM_INITDIALOG:
- {
- ident_data * d;
-
- hold_idents_data();
-
- idata = (khui_config_init_data *) lParam;
-
- khui_cfg_init_dialog_data(hwnd, idata, 0, NULL, NULL);
-
- refresh_view_ident(hwnd, idata->ctx_node);
-
- d = find_ident_by_node(idata->ctx_node);
- if (d)
- d->hwnd = hwnd;
-#ifdef DEBUG
- else
- assert(FALSE);
-#endif
- }
- return FALSE;
-
- case WM_COMMAND:
- khui_cfg_get_dialog_data(hwnd, &idata, NULL);
-
- if (HIWORD(wParam) == BN_CLICKED) {
- switch(LOWORD(wParam)) {
- case IDC_CFG_MONITOR:
- case IDC_CFG_RENEW:
- case IDC_CFG_STICKY:
-
- refresh_data_ident(hwnd, idata);
- if (cfg_idents.hwnd)
- PostMessage(cfg_idents.hwnd, KHUI_WM_CFG_NOTIFY,
- MAKEWPARAM(1, WMCFG_UPDATE_STATE), 0);
- break;
-
- case IDC_CFG_REMOVE:
- mark_remove_ident(hwnd, idata);
- if (cfg_idents.hwnd)
- PostMessage(cfg_idents.hwnd, KHUI_WM_CFG_NOTIFY,
- MAKEWPARAM(1, WMCFG_UPDATE_STATE), 0);
- break;
- }
- }
-
- khm_set_dialog_result(hwnd, 0);
- return TRUE;
-
- case WM_DESTROY:
- {
- ident_data * d;
-
- khui_cfg_get_dialog_data(hwnd, &idata, NULL);
-
- d = find_ident_by_node(idata->ctx_node);
- if (d)
- d->hwnd = NULL;
-
- release_idents_data();
- khui_cfg_free_dialog_data(hwnd);
- khm_set_dialog_result(hwnd, 0);
- }
- return TRUE;
-
- case KHUI_WM_CFG_NOTIFY:
- {
- ident_data * d;
- BOOL * cont;
-
- khui_cfg_get_dialog_data(hwnd, &idata, NULL);
-
- switch (HIWORD(wParam)) {
- case WMCFG_APPLY:
- cont = (BOOL *) lParam;
- d = find_ident_by_node(idata->ctx_node);
- write_params_ident(d);
- if (d->removed && cont)
- *cont = FALSE;
- khui_cfg_set_flags_inst(idata, KHUI_CNFLAG_APPLIED,
- KHUI_CNFLAG_APPLIED |
- KHUI_CNFLAG_MODIFIED);
- break;
-
- case WMCFG_UPDATE_STATE:
- refresh_view_ident(hwnd, idata->ctx_node);
- refresh_data_ident(hwnd, idata);
- break;
- }
- }
- return TRUE;
- }
-
- return FALSE;
-}
-
-/* dialog procedure for individual identity configuration nodes */
-INT_PTR CALLBACK
-khm_cfg_identity_proc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam) {
- HWND hw;
-
- switch(uMsg) {
- case WM_INITDIALOG:
- {
- khui_config_node refnode = NULL;
-
- set_window_node(hwnd, (khui_config_node) lParam);
-
- khui_cfg_open(NULL, L"KhmIdentities", &refnode);
-#ifdef DEBUG
- assert(refnode != NULL);
-#endif
- add_subpanels(hwnd,
- (khui_config_node) lParam,
- refnode);
-
- hw = GetDlgItem(hwnd, IDC_CFG_TAB);
-
- show_tab_panel(hwnd,
- (khui_config_node) lParam,
- hw,
- TabCtrl_GetCurSel(hw),
- TRUE);
-
- khui_cfg_release(refnode);
- }
- return FALSE;
-
- case WM_DESTROY:
- return 0;
-
- case KHUI_WM_CFG_NOTIFY:
- return handle_cfg_notify(hwnd, wParam, lParam);
-
- case WM_NOTIFY:
- return handle_notify(hwnd, wParam, lParam);
- }
- return FALSE;
-}
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<khmapp.h>
+#include<assert.h>
+
+static khui_config_node
+get_window_node(HWND hwnd) {
+ return (khui_config_node) (LONG_PTR)
+ GetWindowLongPtr(hwnd, DWLP_USER);
+}
+
+static void
+set_window_node(HWND hwnd, khui_config_node node) {
+#pragma warning(push)
+#pragma warning(disable: 4244)
+ SetWindowLongPtr(hwnd, DWLP_USER,
+ (LONG_PTR) node);
+#pragma warning(pop)
+}
+
+static void
+add_subpanels(HWND hwnd,
+ khui_config_node ctx_node,
+ khui_config_node ref_node) {
+
+ HWND hw_tab;
+ HWND hw_target;
+ khui_config_node sub;
+ khui_config_node_reg reg;
+ khui_config_init_data idata;
+ int idx;
+
+ hw_tab = GetDlgItem(hwnd, IDC_CFG_TAB);
+ hw_target = GetDlgItem(hwnd, IDC_CFG_TARGET);
+#ifdef DEBUG
+ assert(hw_tab);
+ assert(hw_target);
+#endif
+
+ if (KHM_FAILED(khui_cfg_get_first_subpanel(ref_node, &sub))) {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ return;
+ }
+
+ idx = 0;
+ while(sub) {
+ HWND hwnd_panel;
+ TCITEM tci;
+ int iid;
+
+ khui_cfg_get_reg(sub, &reg);
+
+ if ((ctx_node == ref_node && (reg.flags & KHUI_CNFLAG_PLURAL)) ||
+ (ctx_node != ref_node && !(reg.flags & KHUI_CNFLAG_PLURAL)))
+ goto _next_node;
+
+ idata.ctx_node = ctx_node;
+ idata.this_node = sub;
+ idata.ref_node = ref_node;
+
+ hwnd_panel = CreateDialogParam(reg.h_module,
+ reg.dlg_template,
+ hwnd,
+ reg.dlg_proc,
+ (LPARAM) &idata);
+
+#ifdef DEBUG
+ assert(hwnd_panel);
+#endif
+
+ ShowWindow(hwnd_panel, SW_HIDE);
+
+ ZeroMemory(&tci, sizeof(tci));
+
+ tci.mask = TCIF_PARAM | TCIF_TEXT;
+ tci.lParam = (LPARAM) sub;
+ tci.pszText = (LPWSTR) reg.short_desc;
+
+ iid = TabCtrl_InsertItem(hw_tab, 0, &tci);
+ idx++;
+
+ if (reg.flags & KHUI_CNFLAG_PLURAL) {
+ khui_cfg_set_param_inst(sub, ctx_node, iid);
+ khui_cfg_set_hwnd_inst(sub, ctx_node, hwnd_panel);
+ } else {
+ khui_cfg_set_param(sub, iid);
+ khui_cfg_set_hwnd(sub, hwnd_panel);
+ }
+
+ _next_node:
+
+ khui_cfg_get_next_release(&sub);
+ }
+
+ TabCtrl_SetCurSel(hw_tab, 0);
+}
+
+static void
+apply_all(HWND hwnd,
+ HWND hw_tab,
+ khui_config_node noderef) {
+ TCITEM tci;
+ HWND hw;
+ khui_config_node_reg reg;
+ int idx;
+ int count;
+ BOOL cont = TRUE;
+
+ count = TabCtrl_GetItemCount(hw_tab);
+
+ for (idx = 0; idx < count && cont; idx++) {
+
+ ZeroMemory(&tci, sizeof(tci));
+
+ tci.mask = TCIF_PARAM;
+ TabCtrl_GetItem(hw_tab,
+ idx,
+ &tci);
+
+#ifdef DEBUG
+ assert(tci.lParam);
+#endif
+ khui_cfg_get_reg((khui_config_node) tci.lParam, &reg);
+ if (reg.flags & KHUI_CNFLAG_PLURAL)
+ hw = khui_cfg_get_hwnd_inst((khui_config_node) tci.lParam,
+ noderef);
+ else
+ hw = khui_cfg_get_hwnd((khui_config_node) tci.lParam);
+#ifdef DEBUG
+ assert(hw);
+#endif
+
+ SendMessage(hw, KHUI_WM_CFG_NOTIFY,
+ MAKEWPARAM(0, WMCFG_APPLY), (LPARAM) &cont);
+ }
+}
+
+static void
+show_tab_panel(HWND hwnd,
+ khui_config_node node,
+ HWND hw_tab,
+ int idx,
+ BOOL show) {
+ TCITEM tci;
+ HWND hw;
+ HWND hw_target;
+ HWND hw_firstctl;
+ RECT r;
+ RECT rref;
+ khui_config_node_reg reg;
+
+ ZeroMemory(&tci, sizeof(tci));
+
+ tci.mask = TCIF_PARAM;
+ TabCtrl_GetItem(hw_tab,
+ idx,
+ &tci);
+
+#ifdef DEBUG
+ assert(tci.lParam);
+#endif
+ khui_cfg_get_reg((khui_config_node) tci.lParam, &reg);
+ if (reg.flags & KHUI_CNFLAG_PLURAL)
+ hw = khui_cfg_get_hwnd_inst((khui_config_node) tci.lParam,
+ node);
+ else
+ hw = khui_cfg_get_hwnd((khui_config_node) tci.lParam);
+#ifdef DEBUG
+ assert(hw);
+#endif
+
+ if (!show) {
+ ShowWindow(hw, SW_HIDE);
+ return;
+ }
+
+ hw_target = GetDlgItem(hwnd, IDC_CFG_TARGET);
+#ifdef DEBUG
+ assert(hw_target);
+#endif
+ GetWindowRect(hwnd, &rref);
+ GetWindowRect(hw_target, &r);
+
+ OffsetRect(&r, -rref.left, -rref.top);
+
+ SetWindowPos(hw,
+ hw_tab,
+ r.left, r.top,
+ r.right - r.left, r.bottom - r.top,
+ SWP_NOACTIVATE | SWP_NOOWNERZORDER |
+ SWP_SHOWWINDOW);
+
+ hw_firstctl = GetNextDlgTabItem(hw, NULL, FALSE);
+ if (hw_firstctl) {
+ SetFocus(hw_firstctl);
+ }
+}
+
+static INT_PTR
+handle_cfg_notify(HWND hwnd,
+ WPARAM wParam,
+ LPARAM lParam) {
+ khui_config_node node;
+ HWND hw;
+
+ node = get_window_node(hwnd);
+
+ if (HIWORD(wParam) == WMCFG_APPLY) {
+
+ hw = GetDlgItem(hwnd, IDC_CFG_TAB);
+
+ apply_all(hwnd,
+ hw,
+ node);
+ }
+
+ return TRUE;
+}
+
+static INT_PTR
+handle_notify(HWND hwnd,
+ WPARAM wParam,
+ LPARAM lParam) {
+ LPNMHDR lpnm;
+ int i;
+
+
+ khui_config_node node;
+
+ lpnm = (LPNMHDR) lParam;
+ node = get_window_node(hwnd);
+
+ if (lpnm->idFrom == IDC_CFG_TAB) {
+ switch(lpnm->code) {
+ case TCN_SELCHANGING:
+ i = TabCtrl_GetCurSel(lpnm->hwndFrom);
+
+ show_tab_panel(hwnd,
+ node,
+ lpnm->hwndFrom,
+ i,
+ FALSE);
+ break;
+
+ case TCN_SELCHANGE:
+ i = TabCtrl_GetCurSel(lpnm->hwndFrom);
+
+ show_tab_panel(hwnd,
+ node,
+ lpnm->hwndFrom,
+ i,
+ TRUE);
+ break;
+ }
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+typedef struct tag_ident_props {
+ BOOL monitor;
+ BOOL auto_renew;
+ BOOL sticky;
+} ident_props;
+
+typedef struct tag_ident_data {
+ khm_handle ident;
+ wchar_t * idname;
+ int lv_idx;
+
+ BOOL removed;
+ BOOL applied;
+
+ khm_int32 flags;
+
+ ident_props saved;
+ ident_props work;
+
+ HWND hwnd;
+} ident_data;
+
+typedef struct tag_global_props {
+ BOOL monitor;
+ BOOL auto_renew;
+ BOOL sticky;
+} global_props;
+
+typedef struct tag_idents_data {
+ BOOL valid;
+
+ ident_data * idents;
+ khm_size n_idents;
+ khm_size nc_idents;
+#define IDENTS_DATA_ALLOC_INCR 8
+
+ /* global options */
+ global_props saved;
+ global_props work;
+ BOOL applied;
+
+ int refcount;
+
+ HIMAGELIST hi_status;
+ int idx_id;
+ int idx_default;
+ int idx_modified;
+ int idx_applied;
+ int idx_deleted;
+
+ HWND hwnd;
+ khui_config_init_data cfg;
+} idents_data;
+
+static idents_data cfg_idents = {FALSE, NULL, 0, 0,
+ {0, 0, 0},
+ {0, 0, 0},
+ FALSE,
+
+ 0, NULL };
+
+static void
+read_params_ident(ident_data * d) {
+ khm_handle csp_ident;
+ khm_handle csp_cw;
+ khm_int32 t;
+
+ if (KHM_FAILED(kcdb_identity_get_config(d->ident,
+ KHM_PERM_READ,
+ &csp_ident))) {
+ csp_ident = NULL;
+ }
+
+ if (KHM_SUCCEEDED(khc_open_space(NULL, L"CredWindow", KHM_PERM_READ,
+ &csp_cw))) {
+ if (csp_ident) {
+ khc_shadow_space(csp_ident,
+ csp_cw);
+ khc_close_space(csp_cw);
+ } else {
+ csp_ident = csp_cw;
+ }
+ csp_cw = NULL;
+ } else {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ d->saved.monitor = TRUE;
+ d->saved.auto_renew = TRUE;
+ d->saved.sticky = FALSE;
+ d->work = d->saved;
+
+ if (csp_ident)
+ khc_close_space(csp_ident);
+
+ return;
+ }
+
+ if (KHM_FAILED(khc_read_int32(csp_ident, L"Monitor", &t))) {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ d->saved.monitor = TRUE;
+ } else {
+ d->saved.monitor = !!t;
+ }
+
+ if (KHM_FAILED(khc_read_int32(csp_ident, L"AllowAutoRenew", &t))) {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ d->saved.auto_renew = TRUE;
+ } else {
+ d->saved.auto_renew = !!t;
+ }
+
+ if (KHM_FAILED(khc_read_int32(csp_ident, L"Sticky", &t))) {
+ d->saved.sticky = FALSE;
+ } else {
+ d->saved.sticky = !!t;
+ }
+
+ khc_close_space(csp_ident);
+
+ d->work = d->saved;
+ d->applied = FALSE;
+}
+
+static void
+write_params_ident(ident_data * d) {
+ khm_handle csp_ident;
+
+ if (d->saved.monitor == d->work.monitor &&
+ d->saved.auto_renew == d->work.auto_renew &&
+ d->saved.sticky == d->work.sticky &&
+ !d->removed)
+ return;
+
+ if (KHM_FAILED(kcdb_identity_get_config(d->ident, KHM_PERM_WRITE,
+ &csp_ident))) {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ return;
+ }
+
+ if (d->removed) {
+ khm_handle h = NULL;
+ khm_int32 flags = 0;
+
+ khc_remove_space(csp_ident);
+
+ /* calling kcdb_identity_get_config() will update the
+ KCDB_IDENT_FLAG_CONFIG flag for the identity to reflect the
+ fact that it nolonger has a configuration. */
+ kcdb_identity_get_config(d->ident, 0, &h);
+ if (h) {
+ /* what the ? */
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ khc_close_space(h);
+ }
+#ifdef DEBUG
+ kcdb_identity_get_flags(d->ident, &flags);
+ assert(!(flags & KCDB_IDENT_FLAG_CONFIG));
+#endif
+
+ } else {
+
+ if (d->saved.monitor != d->work.monitor)
+ khc_write_int32(csp_ident, L"Monitor", !!d->work.monitor);
+
+ if (d->saved.auto_renew != d->work.auto_renew)
+ khc_write_int32(csp_ident, L"AllowAutoRenew",
+ !!d->work.auto_renew);
+
+ if (d->saved.sticky != d->work.sticky) {
+ kcdb_identity_set_flags(d->ident,
+ (d->work.sticky)?KCDB_IDENT_FLAG_STICKY:0,
+ KCDB_IDENT_FLAG_STICKY);
+ }
+ }
+
+ khc_close_space(csp_ident);
+
+ d->saved = d->work;
+
+ d->applied = TRUE;
+
+ if (d->hwnd)
+ PostMessage(d->hwnd, KHUI_WM_CFG_NOTIFY,
+ MAKEWPARAM(0, WMCFG_UPDATE_STATE), 0);
+
+ khm_refresh_config();
+}
+
+static void
+write_params_idents(void) {
+ khm_handle csp_cw = NULL;
+
+ if (KHM_SUCCEEDED(khc_open_space(NULL, L"CredWindow",
+ KHM_FLAG_CREATE, &csp_cw))) {
+ if (cfg_idents.work.monitor != cfg_idents.saved.monitor) {
+ khc_write_int32(csp_cw, L"DefaultMonitor",
+ !!cfg_idents.work.monitor);
+ cfg_idents.work.monitor = cfg_idents.saved.monitor;
+ cfg_idents.applied = TRUE;
+ }
+ if (cfg_idents.work.auto_renew != cfg_idents.saved.auto_renew) {
+ khc_write_int32(csp_cw, L"DefaultAllowAutoRenew",
+ !!cfg_idents.work.auto_renew);
+ cfg_idents.work.auto_renew = cfg_idents.saved.auto_renew;
+ cfg_idents.applied = TRUE;
+ }
+ if (cfg_idents.work.sticky != cfg_idents.saved.sticky) {
+ khc_write_int32(csp_cw, L"DefaultSticky",
+ !!cfg_idents.work.sticky);
+ cfg_idents.work.sticky = cfg_idents.saved.sticky;
+ cfg_idents.applied = TRUE;
+ }
+
+ khc_close_space(csp_cw);
+ csp_cw = NULL;
+ }
+
+#if 0
+ for (i=0; i < (int)cfg_idents.n_idents; i++) {
+ write_params_ident(&cfg_idents.idents[i]);
+ }
+#endif
+
+ if (cfg_idents.hwnd)
+ PostMessage(cfg_idents.hwnd, KHUI_WM_CFG_NOTIFY,
+ MAKEWPARAM(0, WMCFG_UPDATE_STATE), 0);
+}
+
+static void
+init_idents_data(void) {
+ khm_int32 rv;
+ wchar_t * t;
+ wchar_t * widnames = NULL;
+ khm_size cb;
+ int n_tries = 0;
+ int i;
+ khm_handle csp_cw = NULL;
+
+ if (cfg_idents.valid)
+ return;
+
+#ifdef DEBUG
+ assert(cfg_idents.idents == NULL);
+ assert(cfg_idents.n_idents == 0);
+ assert(cfg_idents.nc_idents == 0);
+#endif
+
+ if (KHM_SUCCEEDED(khc_open_space(NULL, L"CredWindow", 0, &csp_cw))) {
+ khm_int32 t;
+
+ if (KHM_SUCCEEDED(khc_read_int32(csp_cw, L"DefaultMonitor", &t)))
+ cfg_idents.saved.monitor = !!t;
+ else
+ cfg_idents.saved.monitor = TRUE;
+
+ if (KHM_SUCCEEDED(khc_read_int32(csp_cw, L"DefaultAllowAutoRenew", &t)))
+ cfg_idents.saved.auto_renew = !!t;
+ else
+ cfg_idents.saved.auto_renew = TRUE;
+
+ if (KHM_SUCCEEDED(khc_read_int32(csp_cw, L"DefaultSticky", &t)))
+ cfg_idents.saved.sticky = !!t;
+ else
+ cfg_idents.saved.sticky = FALSE;
+
+ khc_close_space(csp_cw);
+ csp_cw = NULL;
+
+ } else {
+
+ cfg_idents.saved.monitor = TRUE;
+ cfg_idents.saved.auto_renew = TRUE;
+ cfg_idents.saved.sticky = FALSE;
+
+ }
+
+ cfg_idents.work = cfg_idents.saved;
+ cfg_idents.applied = FALSE;
+
+ do {
+ rv = kcdb_identity_enum(KCDB_IDENT_FLAG_CONFIG,
+ KCDB_IDENT_FLAG_CONFIG,
+ NULL,
+ &cb,
+ &cfg_idents.n_idents);
+
+ if (rv != KHM_ERROR_TOO_LONG ||
+ cfg_idents.n_idents == 0 ||
+ cb == 0)
+ break;
+
+ if (widnames)
+ PFREE(widnames);
+ widnames = PMALLOC(cb);
+#ifdef DEBUG
+ assert(widnames);
+#endif
+
+ rv = kcdb_identity_enum(KCDB_IDENT_FLAG_CONFIG,
+ KCDB_IDENT_FLAG_CONFIG,
+ widnames,
+ &cb,
+ &cfg_idents.n_idents);
+ n_tries++;
+ } while(KHM_FAILED(rv) &&
+ n_tries < 5);
+
+ if (KHM_FAILED(rv) ||
+ cfg_idents.n_idents == 0) {
+ cfg_idents.n_idents = 0;
+ goto _cleanup;
+ }
+
+ cfg_idents.idents = PMALLOC(sizeof(*cfg_idents.idents) *
+ cfg_idents.n_idents);
+#ifdef DEBUG
+ assert(cfg_idents.idents);
+#endif
+ ZeroMemory(cfg_idents.idents,
+ sizeof(*cfg_idents.idents) * cfg_idents.n_idents);
+ cfg_idents.nc_idents = cfg_idents.n_idents;
+
+ i = 0;
+ for (t = widnames; t && *t; t = multi_string_next(t)) {
+ khm_handle ident;
+
+ if (KHM_FAILED(kcdb_identity_create(t, 0, &ident))) {
+ cfg_idents.n_idents--;
+ continue;
+ }
+
+ StringCbLength(t, KCDB_IDENT_MAXCB_NAME, &cb);
+ cb += sizeof(wchar_t);
+
+ cfg_idents.idents[i].idname = PMALLOC(cb);
+#ifdef DEBUG
+ assert(cfg_idents.idents[i].idname);
+#endif
+ StringCbCopy(cfg_idents.idents[i].idname, cb, t);
+
+ cfg_idents.idents[i].ident = ident;
+ cfg_idents.idents[i].removed = FALSE;
+
+ kcdb_identity_get_flags(ident, &cfg_idents.idents[i].flags);
+#ifdef DEBUG
+ assert(cfg_idents.idents[i].flags & KCDB_IDENT_FLAG_CONFIG);
+#endif
+
+ read_params_ident(&cfg_idents.idents[i]);
+
+ i++;
+ /* leave identity held */
+ }
+
+ _cleanup:
+
+ cfg_idents.valid = TRUE;
+
+ if (widnames)
+ PFREE(widnames);
+}
+
+static void
+free_idents_data(void) {
+ int i;
+
+ if (!cfg_idents.valid)
+ return;
+
+ for (i=0; i< (int) cfg_idents.n_idents; i++) {
+ if (cfg_idents.idents[i].ident)
+ kcdb_identity_release(cfg_idents.idents[i].ident);
+ if (cfg_idents.idents[i].idname)
+ PFREE(cfg_idents.idents[i].idname);
+ }
+
+ if (cfg_idents.idents)
+ PFREE(cfg_idents.idents);
+
+ cfg_idents.idents = NULL;
+ cfg_idents.n_idents = 0;
+ cfg_idents.nc_idents = 0;
+ cfg_idents.valid = FALSE;
+}
+
+static void
+hold_idents_data(void) {
+ if (!cfg_idents.valid)
+ init_idents_data();
+#ifdef DEBUG
+ assert(cfg_idents.valid);
+#endif
+ cfg_idents.refcount++;
+}
+
+static void
+release_idents_data(void) {
+#ifdef DEBUG
+ assert(cfg_idents.valid);
+#endif
+ cfg_idents.refcount--;
+
+ if (cfg_idents.refcount == 0)
+ free_idents_data();
+}
+
+
+static void
+refresh_data_idents(HWND hwnd) {
+ cfg_idents.work.monitor =
+ (IsDlgButtonChecked(hwnd, IDC_CFG_MONITOR) == BST_CHECKED);
+ cfg_idents.work.auto_renew =
+ (IsDlgButtonChecked(hwnd, IDC_CFG_RENEW) == BST_CHECKED);
+ cfg_idents.work.sticky =
+ (IsDlgButtonChecked(hwnd, IDC_CFG_STICKY) == BST_CHECKED);
+}
+
+static void
+refresh_view_idents_state(HWND hwnd) {
+ BOOL modified;
+ BOOL applied;
+ khm_int32 flags = 0;
+
+ applied = cfg_idents.applied;
+ modified = (cfg_idents.work.monitor != cfg_idents.saved.monitor ||
+ cfg_idents.work.auto_renew != cfg_idents.saved.auto_renew ||
+ cfg_idents.work.sticky != cfg_idents.saved.sticky);
+
+ if (modified)
+ flags |= KHUI_CNFLAG_MODIFIED;
+ if (applied)
+ flags |= KHUI_CNFLAG_APPLIED;
+
+ khui_cfg_set_flags_inst(&cfg_idents.cfg, flags,
+ KHUI_CNFLAG_APPLIED | KHUI_CNFLAG_MODIFIED);
+}
+
+struct ctrl_row_dimensions {
+ RECT enclosure;
+ RECT label;
+ RECT control;
+};
+
+typedef struct tag_add_ident_data {
+ khui_new_creds * nc;
+
+ struct ctrl_row_dimensions dim_small;
+ struct ctrl_row_dimensions dim_medium;
+ struct ctrl_row_dimensions dim_large;
+ int row_gap;
+
+ int current_y;
+ int current_x;
+
+ HWND hwnd_last_ctrl;
+} add_ident_data;
+
+void
+get_ctrl_row_metrics(struct ctrl_row_dimensions * dim, HWND hw_lbl, HWND hw_ctl) {
+
+ assert(hw_lbl);
+ assert(hw_ctl);
+
+ GetWindowRect(hw_lbl, &dim->label);
+ GetWindowRect(hw_ctl, &dim->control);
+
+ UnionRect(&dim->enclosure, &dim->label, &dim->control);
+ OffsetRect(&dim->label,
+ -dim->enclosure.left,
+ -dim->enclosure.top);
+ OffsetRect(&dim->control,
+ -dim->enclosure.left,
+ -dim->enclosure.top);
+ OffsetRect(&dim->enclosure,
+ -dim->enclosure.left,
+ -dim->enclosure.top);
+}
+
+/* dialog box procedure for the "Add new identity" dialog */
+INT_PTR CALLBACK
+khm_cfg_add_ident_proc(HWND hwnd,
+ UINT umsg,
+ WPARAM wParam,
+ LPARAM lParam) {
+ add_ident_data * d;
+
+ switch(umsg) {
+ case WM_INITDIALOG:
+ /* we create a new credentials blob and pull in the identity
+ selectors from the identity provider. */
+ d = PMALLOC(sizeof(*d));
+ ZeroMemory(d, sizeof(*d));
+
+ khui_cw_create_cred_blob(&d->nc);
+#ifdef DEBUG
+ assert(d->nc != NULL);
+#endif
+ if (d->nc == NULL) {
+ PFREE(d);
+ break;
+ }
+
+ if (KHM_FAILED(kcdb_identpro_get_ui_cb(&d->nc->ident_cb))) {
+ /* this should have worked. The only reason it would fail
+ is if there is no identity provider or if the identity
+ provider does not support providing idnetity
+ selectors. */
+ khui_cw_destroy_cred_blob(d->nc);
+ PFREE(d);
+ break;
+ }
+
+#pragma warning(push)
+#pragma warning(disable: 4244)
+ SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) d);
+#pragma warning(pop)
+
+ /* get metrics for dynamic controls */
+ get_ctrl_row_metrics(&d->dim_small,
+ GetDlgItem(hwnd, IDC_SM_LBL),
+ GetDlgItem(hwnd, IDC_SM_CTL));
+ get_ctrl_row_metrics(&d->dim_medium,
+ GetDlgItem(hwnd, IDC_MED_LBL),
+ GetDlgItem(hwnd, IDC_MED_CTL));
+ get_ctrl_row_metrics(&d->dim_large,
+ GetDlgItem(hwnd, IDC_LG_LBL),
+ GetDlgItem(hwnd, IDC_LG_CTL));
+
+ {
+ RECT rlbl;
+ RECT rctl;
+ RECT rwnd;
+
+ GetWindowRect(GetDlgItem(hwnd, IDC_SM_LBL),
+ &rlbl);
+ GetWindowRect(GetDlgItem(hwnd, IDC_SM_CTL),
+ &rctl);
+ GetWindowRect(hwnd, &rwnd);
+
+ OffsetRect(&rlbl, -rwnd.left, -rwnd.top);
+ OffsetRect(&rctl, -rwnd.left, -rwnd.top);
+
+ d->current_x = rlbl.left;
+ d->current_y = rctl.top - GetSystemMetrics(SM_CYCAPTION);
+
+ GetWindowRect(GetDlgItem(hwnd, IDC_MED_CTL),
+ &rlbl);
+ OffsetRect(&rlbl, -rwnd.left, -rwnd.top);
+
+ d->row_gap = rlbl.top - rctl.bottom;
+ }
+
+ d->nc->hwnd = hwnd;
+
+ /* now call the UI callback and make it create the
+ controls. */
+ d->nc->ident_cb(d->nc, WMNC_IDENT_INIT, NULL, 0, 0,
+ (LPARAM) hwnd);
+
+ break;
+
+ case WM_DESTROY:
+ d = (add_ident_data *)(LONG_PTR)
+ GetWindowLongPtr(hwnd, DWLP_USER);
+ if (d == NULL)
+ break;
+
+ d->nc->ident_cb(d->nc, WMNC_IDENT_EXIT, NULL, 0, 0, 0);
+
+ khui_cw_destroy_cred_blob(d->nc);
+ PFREE(d);
+ break;
+
+ case KHUI_WM_NC_NOTIFY:
+ d = (add_ident_data *)(LONG_PTR)
+ GetWindowLongPtr(hwnd, DWLP_USER);
+
+ switch(HIWORD(wParam)) {
+ case WMNC_ADD_CONTROL_ROW:
+ {
+ khui_control_row * row;
+ RECT r_lbl, r_inp, r_enc;
+ struct ctrl_row_dimensions * dim;
+ HFONT hf;
+
+ row = (khui_control_row *) lParam;
+
+#ifdef DEBUG
+ assert(row->label);
+ assert(row->input);
+ assert(d);
+#endif
+
+ if (row->size == KHUI_CTRLSIZE_SMALL) {
+ dim = &d->dim_small;
+ } else if (row->size == KHUI_CTRLSIZE_HALF) {
+ dim = &d->dim_medium;
+ } else {
+ dim = &d->dim_large;
+#ifdef DEBUG
+ assert(row->size == KHUI_CTRLSIZE_FULL);
+#endif
+ }
+
+ CopyRect(&r_enc, &dim->enclosure);
+ CopyRect(&r_lbl, &dim->label);
+ CopyRect(&r_inp, &dim->control);
+
+ OffsetRect(&r_enc, d->current_x, d->current_y);
+ OffsetRect(&r_lbl, r_enc.left, r_enc.top);
+ OffsetRect(&r_inp, r_enc.left, r_enc.top);
+
+ d->current_y += r_enc.bottom - r_enc.top;
+
+ hf = (HFONT) SendDlgItemMessage(hwnd, IDOK, WM_GETFONT, 0, 0);
+
+ if (row->label) {
+ SetWindowPos(row->label,
+ ((d->hwnd_last_ctrl != NULL)?
+ d->hwnd_last_ctrl :
+ HWND_TOP),
+ r_lbl.left, r_lbl.top,
+ r_lbl.right - r_lbl.left,
+ r_lbl.bottom - r_lbl.top,
+ SWP_DEFERERASE | SWP_NOACTIVATE |
+ SWP_NOOWNERZORDER);
+ if (hf)
+ SendMessage(row->label, WM_SETFONT,
+ (WPARAM) hf,
+ TRUE);
+ d->hwnd_last_ctrl = row->label;
+ }
+
+ if (row->input) {
+ SetWindowPos(row->input,
+ ((d->hwnd_last_ctrl != NULL)?
+ d->hwnd_last_ctrl :
+ HWND_TOP),
+ r_inp.left, r_inp.top,
+ r_inp.right - r_inp.left,
+ r_inp.bottom - r_inp.top,
+ SWP_DEFERERASE | SWP_NOACTIVATE |
+ SWP_NOOWNERZORDER);
+ if (hf)
+ SendMessage(row->input, WM_SETFONT,
+ (WPARAM) hf,
+ TRUE);
+ d->hwnd_last_ctrl = row->input;
+ }
+ }
+ break;
+
+ case WMNC_IDENTITY_CHANGE:
+ break;
+ }
+ return TRUE;
+
+ case WM_COMMAND:
+ if (LOWORD(wParam) == IDOK) {
+ wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
+ wchar_t err_msg[1024];
+ khm_handle ident = NULL;
+ khm_handle csp_ident = NULL;
+ khm_size cb;
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+
+ d = (add_ident_data *)(LONG_PTR)
+ GetWindowLongPtr(hwnd, DWLP_USER);
+
+ if (!d || !d->nc)
+ break;
+
+ /* check if there was an identity selected */
+ if (d->nc->n_identities == 0 ||
+ d->nc->identities[0] == NULL) {
+
+ StringCbCopy(idname, sizeof(idname), L"");
+
+ LoadString(khm_hInstance, IDS_CFG_IDNAME_NON,
+ err_msg, ARRAYLENGTH(err_msg));
+
+ goto show_failure;
+ }
+
+ ident = d->nc->identities[0];
+ kcdb_identity_hold(ident);
+
+ cb = sizeof(idname);
+ kcdb_identity_get_name(ident, idname, &cb);
+
+ /* now we have to create the identity configuration. */
+ if (KHM_FAILED(rv = kcdb_identity_get_config(ident,
+ KHM_FLAG_CREATE,
+ &csp_ident))) {
+ wchar_t fmt[256];
+
+ LoadString(khm_hInstance, IDS_CFG_IDNAME_CCC,
+ fmt, ARRAYLENGTH(fmt));
+ StringCbPrintf(err_msg, sizeof(err_msg), fmt, rv);
+
+ kcdb_identity_release(ident);
+
+ goto show_failure;
+ }
+
+ /* create a value so that the configuration space will
+ actually be created in the registry. We don't want
+ this new identity to be sticky. */
+ khc_write_int32(csp_ident, L"Sticky", 0);
+
+ khm_refresh_config();
+
+ kcdb_identity_release(ident);
+ khc_close_space(csp_ident);
+
+ EndDialog(hwnd, 0);
+ break;
+
+ show_failure:
+ {
+ wchar_t title[512];
+ wchar_t fmt[256];
+
+ if (!err_msg[0])
+ break;
+
+ LoadString(khm_hInstance, IDS_CFG_IDNAME_PRB,
+ fmt, ARRAYLENGTH(fmt));
+ StringCbPrintf(title, sizeof(title), fmt, idname);
+
+ MessageBox(hwnd, err_msg, title, MB_OK | MB_ICONSTOP);
+
+ /* don't end the dialog yet */
+ break;
+ }
+ break;
+
+ } else if (LOWORD(wParam) == IDCANCEL) {
+ EndDialog(hwnd, 1);
+ } else {
+ d = (add_ident_data *)(LONG_PTR)
+ GetWindowLongPtr(hwnd, DWLP_USER);
+
+ if (d && d->nc && d->nc->ident_cb) {
+ return d->nc->ident_cb(d->nc, WMNC_IDENT_WMSG,
+ hwnd, umsg, wParam, lParam);
+ }
+ }
+ break;
+ }
+
+ return FALSE;
+}
+
+/* dialog procedure for the "general" pane of the "identities"
+ configuration node. */
+INT_PTR CALLBACK
+khm_cfg_ids_tab_proc(HWND hwnd,
+ UINT umsg,
+ WPARAM wParam,
+ LPARAM lParam) {
+
+ switch(umsg) {
+ case WM_INITDIALOG:
+ {
+ HICON hicon;
+
+ hold_idents_data();
+
+ cfg_idents.hwnd = hwnd;
+ cfg_idents.cfg = *((khui_config_init_data *) lParam);
+
+ /* add the status icons */
+ if (cfg_idents.hi_status)
+ goto _done_with_icons;
+
+ cfg_idents.hi_status =
+ ImageList_Create(GetSystemMetrics(SM_CXSMICON),
+ GetSystemMetrics(SM_CYSMICON),
+ ILC_COLOR8 | ILC_MASK,
+ 4,4);
+
+ hicon =
+ LoadImage(khm_hInstance, MAKEINTRESOURCE(IDI_ID),
+ IMAGE_ICON,
+ GetSystemMetrics(SM_CXSMICON),
+ GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR);
+
+ cfg_idents.idx_id = ImageList_AddIcon(cfg_idents.hi_status,
+ hicon);
+
+ DestroyIcon(hicon);
+
+ hicon = LoadImage(khm_hInstance, MAKEINTRESOURCE(IDI_CFG_DEFAULT),
+ IMAGE_ICON, GetSystemMetrics(SM_CXSMICON),
+ GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR);
+
+ cfg_idents.idx_default = ImageList_AddIcon(cfg_idents.hi_status,
+ hicon) + 1;
+
+ DestroyIcon(hicon);
+
+ hicon = LoadImage(khm_hInstance, MAKEINTRESOURCE(IDI_CFG_MODIFIED),
+ IMAGE_ICON, GetSystemMetrics(SM_CXSMICON),
+ GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR);
+
+ cfg_idents.idx_modified = ImageList_AddIcon(cfg_idents.hi_status,
+ hicon) + 1;
+
+ DestroyIcon(hicon);
+
+ hicon = LoadImage(khm_hInstance, MAKEINTRESOURCE(IDI_CFG_APPLIED),
+ IMAGE_ICON, GetSystemMetrics(SM_CXSMICON),
+ GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR);
+
+ cfg_idents.idx_applied = ImageList_AddIcon(cfg_idents.hi_status,
+ hicon) + 1;
+
+ DestroyIcon(hicon);
+
+ hicon = LoadImage(khm_hInstance, MAKEINTRESOURCE(IDI_CFG_DELETED),
+ IMAGE_ICON, GetSystemMetrics(SM_CXSMICON),
+ GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR);
+
+ cfg_idents.idx_deleted = ImageList_AddIcon(cfg_idents.hi_status,
+ hicon) + 1;
+
+ DestroyIcon(hicon);
+
+ _done_with_icons:
+
+ CheckDlgButton(hwnd, IDC_CFG_MONITOR,
+ (cfg_idents.work.monitor)?BST_CHECKED:BST_UNCHECKED);
+ CheckDlgButton(hwnd, IDC_CFG_RENEW,
+ (cfg_idents.work.auto_renew)?BST_CHECKED:BST_UNCHECKED);
+ CheckDlgButton(hwnd, IDC_CFG_STICKY,
+ (cfg_idents.work.sticky)?BST_CHECKED:BST_UNCHECKED);
+
+ }
+ return FALSE;
+
+ case WM_COMMAND:
+
+ if (HIWORD(wParam) == BN_CLICKED) {
+ UINT ctrl = LOWORD(wParam);
+
+ switch(ctrl) {
+ case IDC_CFG_MONITOR:
+ case IDC_CFG_RENEW:
+ case IDC_CFG_STICKY:
+ refresh_data_idents(hwnd);
+ break;
+
+ case IDC_CFG_ADDIDENT:
+ DialogBoxParam(khm_hInstance,
+ MAKEINTRESOURCE(IDD_CFG_ADDIDENT),
+ hwnd,
+ khm_cfg_add_ident_proc,
+ (LPARAM) hwnd);
+ break;
+ }
+
+ refresh_view_idents_state(hwnd);
+ }
+
+ khm_set_dialog_result(hwnd, 0);
+ return TRUE;
+
+ case KHUI_WM_CFG_NOTIFY:
+ {
+ switch(HIWORD(wParam)) {
+ case WMCFG_APPLY:
+ write_params_idents();
+ break;
+
+ case WMCFG_UPDATE_STATE:
+ refresh_view_idents_state(hwnd);
+ break;
+ }
+ }
+ return TRUE;
+
+ case WM_DESTROY:
+ cfg_idents.hwnd = NULL;
+
+ if (cfg_idents.hi_status != NULL) {
+ ImageList_Destroy(cfg_idents.hi_status);
+ cfg_idents.hi_status = NULL;
+ }
+ release_idents_data();
+
+ khm_set_dialog_result(hwnd, 0);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/* dialog procedure for the "Identities" configuration node */
+INT_PTR CALLBACK
+khm_cfg_identities_proc(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam) {
+ HWND hw;
+ switch(uMsg) {
+ case WM_INITDIALOG:
+ set_window_node(hwnd, (khui_config_node) lParam);
+ add_subpanels(hwnd, (khui_config_node) lParam,
+ (khui_config_node) lParam);
+ hw = GetDlgItem(hwnd, IDC_CFG_TAB);
+ show_tab_panel(hwnd,
+ (khui_config_node) lParam,
+ hw,
+ TabCtrl_GetCurSel(hw),
+ TRUE);
+ return FALSE;
+
+ case WM_DESTROY:
+ return 0;
+
+ case KHUI_WM_CFG_NOTIFY:
+ return handle_cfg_notify(hwnd, wParam, lParam);
+
+ case WM_NOTIFY:
+ return handle_notify(hwnd, wParam, lParam);
+ }
+
+ return FALSE;
+}
+
+static ident_data *
+find_ident_by_node(khui_config_node node) {
+ khm_size cb;
+ wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
+ int i;
+ khm_handle ident = NULL;
+
+ cb = sizeof(idname);
+ khui_cfg_get_name(node, idname, &cb);
+
+ for (i=0; i < (int)cfg_idents.n_idents; i++) {
+ if (!wcscmp(cfg_idents.idents[i].idname, idname))
+ break;
+ }
+
+ if (i < (int)cfg_idents.n_idents)
+ return &cfg_idents.idents[i];
+
+ /* there is no identity data for this configuration node. We try
+ to create it. */
+ if (KHM_FAILED(kcdb_identity_create(idname, 0, &ident)))
+ return NULL;
+
+ if (cfg_idents.n_idents >= cfg_idents.nc_idents) {
+ cfg_idents.nc_idents = UBOUNDSS(cfg_idents.n_idents + 1,
+ IDENTS_DATA_ALLOC_INCR,
+ IDENTS_DATA_ALLOC_INCR);
+#ifdef DEBUG
+ assert(cfg_idents.nc_idents > cfg_idents.n_idents);
+#endif
+ cfg_idents.idents = PREALLOC(cfg_idents.idents,
+ sizeof(*cfg_idents.idents) *
+ cfg_idents.nc_idents);
+#ifdef DEBUG
+ assert(cfg_idents.idents);
+#endif
+ ZeroMemory(&(cfg_idents.idents[cfg_idents.n_idents]),
+ sizeof(*cfg_idents.idents) *
+ (cfg_idents.nc_idents - cfg_idents.n_idents));
+ }
+
+ i = (int) cfg_idents.n_idents;
+
+ StringCbLength(idname, KCDB_IDENT_MAXCB_NAME, &cb);
+ cb += sizeof(wchar_t);
+
+ cfg_idents.idents[i].idname = PMALLOC(cb);
+#ifdef DEBUG
+ assert(cfg_idents.idents[i].idname);
+#endif
+ StringCbCopy(cfg_idents.idents[i].idname, cb, idname);
+
+ cfg_idents.idents[i].ident = ident;
+ cfg_idents.idents[i].removed = FALSE;
+
+ kcdb_identity_get_flags(ident, &cfg_idents.idents[i].flags);
+#ifdef DEBUG
+ assert(cfg_idents.idents[i].flags & KCDB_IDENT_FLAG_CONFIG);
+#endif
+
+ read_params_ident(&cfg_idents.idents[i]);
+
+ cfg_idents.n_idents++;
+
+ /* leave ident held. */
+
+ return &cfg_idents.idents[i];
+}
+
+static void
+refresh_view_ident(HWND hwnd, khui_config_node node) {
+ ident_data * d;
+
+ d = find_ident_by_node(node);
+#ifdef DEBUG
+ assert(d);
+#endif
+
+ CheckDlgButton(hwnd, IDC_CFG_MONITOR,
+ (d->work.monitor? BST_CHECKED: BST_UNCHECKED));
+ CheckDlgButton(hwnd, IDC_CFG_RENEW,
+ (d->work.auto_renew? BST_CHECKED: BST_UNCHECKED));
+ CheckDlgButton(hwnd, IDC_CFG_STICKY,
+ (d->work.sticky? BST_CHECKED: BST_UNCHECKED));
+}
+
+static void
+mark_remove_ident(HWND hwnd, khui_config_init_data * idata) {
+ ident_data * d;
+
+ d = find_ident_by_node(idata->ctx_node);
+#ifdef DEBUG
+ assert(d);
+#endif
+
+ if (d->removed)
+ return;
+
+ d->removed = TRUE;
+
+ khui_cfg_set_flags_inst(idata, KHUI_CNFLAG_MODIFIED,
+ KHUI_CNFLAG_MODIFIED);
+
+ EnableWindow(GetDlgItem(hwnd, IDC_CFG_REMOVE), FALSE);
+}
+
+static void
+refresh_data_ident(HWND hwnd, khui_config_init_data * idata) {
+ ident_data * d;
+
+ d = find_ident_by_node(idata->ctx_node);
+#ifdef DEBUG
+ assert(d);
+#endif
+
+ if (IsDlgButtonChecked(hwnd, IDC_CFG_MONITOR) == BST_CHECKED)
+ d->work.monitor = TRUE;
+ else
+ d->work.monitor = FALSE;
+
+ if (IsDlgButtonChecked(hwnd, IDC_CFG_RENEW) == BST_CHECKED)
+ d->work.auto_renew = TRUE;
+ else
+ d->work.auto_renew = FALSE;
+
+ if (IsDlgButtonChecked(hwnd, IDC_CFG_STICKY) == BST_CHECKED)
+ d->work.sticky = TRUE;
+ else
+ d->work.sticky = FALSE;
+
+ if (d->work.monitor != d->saved.monitor ||
+ d->work.auto_renew != d->saved.auto_renew ||
+ d->work.sticky != d->saved.sticky) {
+
+ khui_cfg_set_flags_inst(idata, KHUI_CNFLAG_MODIFIED,
+ KHUI_CNFLAG_MODIFIED);
+
+ } else {
+ khui_cfg_set_flags_inst(idata, 0,
+ KHUI_CNFLAG_MODIFIED);
+ }
+}
+
+/* dialog procedure for the "general" pane of individual identity
+ configuration nodes. */
+INT_PTR CALLBACK
+khm_cfg_id_tab_proc(HWND hwnd,
+ UINT umsg,
+ WPARAM wParam,
+ LPARAM lParam) {
+
+ khui_config_init_data * idata;
+
+ switch(umsg) {
+ case WM_INITDIALOG:
+ {
+ ident_data * d;
+
+ hold_idents_data();
+
+ idata = (khui_config_init_data *) lParam;
+
+ khui_cfg_init_dialog_data(hwnd, idata, 0, NULL, NULL);
+
+ refresh_view_ident(hwnd, idata->ctx_node);
+
+ d = find_ident_by_node(idata->ctx_node);
+ if (d)
+ d->hwnd = hwnd;
+#ifdef DEBUG
+ else
+ assert(FALSE);
+#endif
+ }
+ return FALSE;
+
+ case WM_COMMAND:
+ khui_cfg_get_dialog_data(hwnd, &idata, NULL);
+
+ if (HIWORD(wParam) == BN_CLICKED) {
+ switch(LOWORD(wParam)) {
+ case IDC_CFG_MONITOR:
+ case IDC_CFG_RENEW:
+ case IDC_CFG_STICKY:
+
+ refresh_data_ident(hwnd, idata);
+ if (cfg_idents.hwnd)
+ PostMessage(cfg_idents.hwnd, KHUI_WM_CFG_NOTIFY,
+ MAKEWPARAM(1, WMCFG_UPDATE_STATE), 0);
+ break;
+
+ case IDC_CFG_REMOVE:
+ mark_remove_ident(hwnd, idata);
+ if (cfg_idents.hwnd)
+ PostMessage(cfg_idents.hwnd, KHUI_WM_CFG_NOTIFY,
+ MAKEWPARAM(1, WMCFG_UPDATE_STATE), 0);
+ break;
+ }
+ }
+
+ khm_set_dialog_result(hwnd, 0);
+ return TRUE;
+
+ case WM_DESTROY:
+ {
+ ident_data * d;
+
+ khui_cfg_get_dialog_data(hwnd, &idata, NULL);
+
+ d = find_ident_by_node(idata->ctx_node);
+ if (d)
+ d->hwnd = NULL;
+
+ release_idents_data();
+ khui_cfg_free_dialog_data(hwnd);
+ khm_set_dialog_result(hwnd, 0);
+ }
+ return TRUE;
+
+ case KHUI_WM_CFG_NOTIFY:
+ {
+ ident_data * d;
+ BOOL * cont;
+
+ khui_cfg_get_dialog_data(hwnd, &idata, NULL);
+
+ switch (HIWORD(wParam)) {
+ case WMCFG_APPLY:
+ cont = (BOOL *) lParam;
+ d = find_ident_by_node(idata->ctx_node);
+ write_params_ident(d);
+ if (d->removed && cont)
+ *cont = FALSE;
+ khui_cfg_set_flags_inst(idata, KHUI_CNFLAG_APPLIED,
+ KHUI_CNFLAG_APPLIED |
+ KHUI_CNFLAG_MODIFIED);
+ break;
+
+ case WMCFG_UPDATE_STATE:
+ refresh_view_ident(hwnd, idata->ctx_node);
+ refresh_data_ident(hwnd, idata);
+ break;
+ }
+ }
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/* dialog procedure for individual identity configuration nodes */
+INT_PTR CALLBACK
+khm_cfg_identity_proc(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam) {
+ HWND hw;
+
+ switch(uMsg) {
+ case WM_INITDIALOG:
+ {
+ khui_config_node refnode = NULL;
+
+ set_window_node(hwnd, (khui_config_node) lParam);
+
+ khui_cfg_open(NULL, L"KhmIdentities", &refnode);
+#ifdef DEBUG
+ assert(refnode != NULL);
+#endif
+ add_subpanels(hwnd,
+ (khui_config_node) lParam,
+ refnode);
+
+ hw = GetDlgItem(hwnd, IDC_CFG_TAB);
+
+ show_tab_panel(hwnd,
+ (khui_config_node) lParam,
+ hw,
+ TabCtrl_GetCurSel(hw),
+ TRUE);
+
+ khui_cfg_release(refnode);
+ }
+ return FALSE;
+
+ case WM_DESTROY:
+ return 0;
+
+ case KHUI_WM_CFG_NOTIFY:
+ return handle_cfg_notify(hwnd, wParam, lParam);
+
+ case WM_NOTIFY:
+ return handle_notify(hwnd, wParam, lParam);
+ }
+ return FALSE;
+}
diff --git a/src/windows/identity/ui/cfg_notif_wnd.c b/src/windows/identity/ui/cfg_notif_wnd.c
index ac5f930283..91650adb8c 100644
--- a/src/windows/identity/ui/cfg_notif_wnd.c
+++ b/src/windows/identity/ui/cfg_notif_wnd.c
@@ -1,341 +1,341 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<khmapp.h>
-#include<assert.h>
-
-typedef struct tag_notif_data {
- khui_config_node node;
-
- BOOL modified;
-
- BOOL monitor;
- BOOL renew;
- BOOL halflife;
- BOOL warn1;
- BOOL warn2;
-
- khui_tracker tc_renew;
- khui_tracker tc_warn1;
- khui_tracker tc_warn2;
-} notif_data;
-
-static void
-read_params(notif_data * d) {
- khm_handle csp_cw;
- khm_int32 rv;
- khm_int32 t;
-
- rv = khc_open_space(NULL, L"CredWindow", KHM_PERM_READ, &csp_cw);
- assert(KHM_SUCCEEDED(rv));
-
- rv = khc_read_int32(csp_cw, L"Monitor", &t);
- assert(KHM_SUCCEEDED(rv));
- d->monitor = !!t;
-
- rv = khc_read_int32(csp_cw, L"AllowAutoRenew", &t);
- assert(KHM_SUCCEEDED(rv));
- d->renew = !!t;
-
- rv = khc_read_int32(csp_cw, L"RenewAtHalfLife", &t);
- assert(KHM_SUCCEEDED(rv));
- d->halflife = !!t;
-
- rv = khc_read_int32(csp_cw, L"AllowWarn", &t);
- assert(KHM_SUCCEEDED(rv));
- d->warn1 = !!t;
-
- rv = khc_read_int32(csp_cw, L"AllowCritical", &t);
- assert(KHM_SUCCEEDED(rv));
- d->warn2 = !!t;
-
- rv = khc_read_int32(csp_cw, L"AutoRenewThreshold", &t);
- assert(KHM_SUCCEEDED(rv));
- d->tc_renew.current = t;
-
- rv = khc_read_int32(csp_cw, L"WarnThreshold", &t);
- assert(KHM_SUCCEEDED(rv));
- d->tc_warn1.current = t;
-
- rv = khc_read_int32(csp_cw, L"CriticalThreshold", &t);
- assert(KHM_SUCCEEDED(rv));
- d->tc_warn2.current = t;
-
- rv = khc_read_int32(csp_cw, L"MaxThreshold", &t);
- assert(KHM_SUCCEEDED(rv));
- d->tc_renew.max = t;
- d->tc_warn1.max = t;
- d->tc_warn2.max = t;
-
- rv = khc_read_int32(csp_cw, L"MinThreshold", &t);
- assert(KHM_SUCCEEDED(rv));
- d->tc_renew.min = t;
- d->tc_warn1.min = t;
- d->tc_warn2.min = t;
-
- khc_close_space(csp_cw);
-
- d->modified = FALSE;
-}
-
-static void
-check_for_modification(notif_data * d) {
- notif_data t;
-
- ZeroMemory(&t, sizeof(t));
-
- read_params(&t);
-
- if ((!!d->monitor) != (!!t.monitor) ||
- (!!d->renew) != (!!t.renew) ||
- (!!d->halflife) != (!!t.halflife) ||
- (!!d->warn1) != (!!t.warn1) ||
- (!!d->warn2) != (!!t.warn2) ||
- d->tc_renew.current != t.tc_renew.current ||
- d->tc_warn1.current != t.tc_warn1.current ||
- d->tc_warn2.current != t.tc_warn2.current) {
-
- khui_cfg_set_flags(d->node,
- KHUI_CNFLAG_MODIFIED,
- KHUI_CNFLAG_MODIFIED);
-
- d->modified = TRUE;
-
- } else {
- khui_cfg_set_flags(d->node,
- 0,
- KHUI_CNFLAG_MODIFIED);
-
- d->modified = FALSE;
- }
-}
-
-static void
-write_params(notif_data * d) {
- khm_handle csp_cw;
- khm_int32 rv;
-
- if (!d->modified)
- return;
-
- rv = khc_open_space(NULL, L"CredWindow", KHM_PERM_WRITE, &csp_cw);
- assert(KHM_SUCCEEDED(rv));
-
- rv = khc_write_int32(csp_cw, L"Monitor", d->monitor);
- assert(KHM_SUCCEEDED(rv));
-
- rv = khc_write_int32(csp_cw, L"AllowAutoRenew", d->renew);
- assert(KHM_SUCCEEDED(rv));
-
- rv = khc_write_int32(csp_cw, L"RenewAtHalfLife", d->halflife);
- assert(KHM_SUCCEEDED(rv));
-
- rv = khc_write_int32(csp_cw, L"AllowWarn", d->warn1);
- assert(KHM_SUCCEEDED(rv));
-
- rv = khc_write_int32(csp_cw, L"AllowCritical", d->warn2);
- assert(KHM_SUCCEEDED(rv));
-
-
- rv = khc_write_int32(csp_cw, L"AutoRenewThreshold",
- (khm_int32) d->tc_renew.current);
- assert(KHM_SUCCEEDED(rv));
-
- rv = khc_write_int32(csp_cw, L"WarnThreshold",
- (khm_int32) d->tc_warn1.current);
- assert(KHM_SUCCEEDED(rv));
-
- rv = khc_write_int32(csp_cw, L"CriticalThreshold",
- (khm_int32) d->tc_warn2.current);
- assert(KHM_SUCCEEDED(rv));
-
- khc_close_space(csp_cw);
-
- khui_cfg_set_flags(d->node,
- KHUI_CNFLAG_APPLIED,
- KHUI_CNFLAG_APPLIED | KHUI_CNFLAG_MODIFIED);
-
- khm_timer_refresh(hwnd_notifier);
-}
-
-static void
-refresh_view(HWND hwnd, notif_data * d) {
- CheckDlgButton(hwnd, IDC_NOTIF_MONITOR,
- (d->monitor?BST_CHECKED:BST_UNCHECKED));
- CheckDlgButton(hwnd, IDC_NOTIF_RENEW,
- (d->renew?BST_CHECKED:BST_UNCHECKED));
- CheckDlgButton(hwnd, IDC_NOTIF_HALFLIFE,
- (d->halflife?BST_CHECKED:BST_UNCHECKED));
- CheckDlgButton(hwnd, IDC_NOTIF_WARN1,
- (d->warn1?BST_CHECKED:BST_UNCHECKED));
- CheckDlgButton(hwnd, IDC_NOTIF_WARN2,
- (d->warn2?BST_CHECKED:BST_UNCHECKED));
- khui_tracker_refresh(&d->tc_renew);
- khui_tracker_refresh(&d->tc_warn1);
- khui_tracker_refresh(&d->tc_warn2);
- if (!d->monitor) {
- EnableWindow(GetDlgItem(hwnd, IDC_NOTIF_RENEW), FALSE);
- EnableWindow(GetDlgItem(hwnd, IDC_NOTIF_HALFLIFE), FALSE);
- EnableWindow(GetDlgItem(hwnd, IDC_NOTIF_WARN1), FALSE);
- EnableWindow(GetDlgItem(hwnd, IDC_NOTIF_WARN2), FALSE);
- EnableWindow(GetDlgItem(hwnd, IDC_NOTIF_RENEW_THR), FALSE);
- EnableWindow(GetDlgItem(hwnd, IDC_NOTIF_WARN1_THR), FALSE);
- EnableWindow(GetDlgItem(hwnd, IDC_NOTIF_WARN2_THR), FALSE);
- } else {
- EnableWindow(GetDlgItem(hwnd, IDC_NOTIF_RENEW), TRUE);
- EnableWindow(GetDlgItem(hwnd, IDC_NOTIF_HALFLIFE), TRUE);
- EnableWindow(GetDlgItem(hwnd, IDC_NOTIF_WARN1), TRUE);
- EnableWindow(GetDlgItem(hwnd, IDC_NOTIF_WARN2), TRUE);
- EnableWindow(GetDlgItem(hwnd, IDC_NOTIF_RENEW_THR), !!(d->renew));
- EnableWindow(GetDlgItem(hwnd, IDC_NOTIF_WARN1_THR), !!(d->warn1));
- EnableWindow(GetDlgItem(hwnd, IDC_NOTIF_WARN2_THR), !!(d->warn2));
- }
-}
-
-static void
-refresh_data(HWND hwnd, notif_data * d) {
- d->monitor = (IsDlgButtonChecked(hwnd, IDC_NOTIF_MONITOR)
- == BST_CHECKED);
- d->renew = (IsDlgButtonChecked(hwnd, IDC_NOTIF_RENEW)
- == BST_CHECKED);
- d->halflife = (IsDlgButtonChecked(hwnd, IDC_NOTIF_HALFLIFE)
- == BST_CHECKED);
- d->warn1 = (IsDlgButtonChecked(hwnd, IDC_NOTIF_WARN1)
- == BST_CHECKED);
- d->warn2 = (IsDlgButtonChecked(hwnd, IDC_NOTIF_WARN2)
- == BST_CHECKED);
-
- check_for_modification(d);
-}
-
-INT_PTR CALLBACK
-khm_cfg_notifications_proc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam) {
-
- notif_data * d;
-
- switch(uMsg) {
- case WM_INITDIALOG: {
- HWND hw;
-
- d = PMALLOC(sizeof(*d));
-#ifdef DEBUG
- assert(d != NULL);
-#endif
-
-#pragma warning(push)
-#pragma warning(disable: 4244)
- SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) d);
-#pragma warning(pop)
-
- ZeroMemory(d, sizeof(*d));
-
- d->node = (khui_config_node) lParam;
-
- khui_tracker_initialize(&d->tc_renew);
- khui_tracker_initialize(&d->tc_warn1);
- khui_tracker_initialize(&d->tc_warn2);
-
- read_params(d);
-
- hw = GetDlgItem(hwnd, IDC_NOTIF_RENEW_THR);
- khui_tracker_install(hw, &d->tc_renew);
-
- hw = GetDlgItem(hwnd, IDC_NOTIF_WARN1_THR);
- khui_tracker_install(hw, &d->tc_warn1);
-
- hw = GetDlgItem(hwnd, IDC_NOTIF_WARN2_THR);
- khui_tracker_install(hw, &d->tc_warn2);
-
- refresh_view(hwnd, d);
-
- /* normally we should return TRUE, but in this case we return
- FALSE since we don't want to inadvertently steal the focus
- from the treeview. */
- return FALSE;
- }
-
- case WM_COMMAND: {
- d = (notif_data *) (DWORD_PTR) GetWindowLongPtr(hwnd, DWLP_USER);
-
- if (HIWORD(wParam) == BN_CLICKED) {
- refresh_data(hwnd, d);
- refresh_view(hwnd, d);
-
- check_for_modification(d);
- } else if (HIWORD(wParam) == EN_CHANGE) {
- SetTimer(hwnd, 1, 500, NULL);
- }
-
- khm_set_dialog_result(hwnd, 0);
-
- return TRUE;
- }
-
- case WM_TIMER: {
- d = (notif_data *) (DWORD_PTR) GetWindowLongPtr(hwnd, DWLP_USER);
- KillTimer(hwnd, 1);
- check_for_modification(d);
-
- khm_set_dialog_result(hwnd, 0);
-
- return TRUE;
- }
-
- case WM_DESTROY: {
- d = (notif_data *) (DWORD_PTR) GetWindowLongPtr(hwnd, DWLP_USER);
-
- khui_tracker_kill_controls(&d->tc_renew);
- khui_tracker_kill_controls(&d->tc_warn1);
- khui_tracker_kill_controls(&d->tc_warn2);
-
- PFREE(d);
-
- SetWindowLongPtr(hwnd, DWLP_USER, 0);
-
- khm_set_dialog_result(hwnd, 0);
-
- return TRUE;
- }
-
- case KHUI_WM_CFG_NOTIFY: {
- d = (notif_data *) (DWORD_PTR) GetWindowLongPtr(hwnd, DWLP_USER);
-
- if (HIWORD(wParam) == WMCFG_APPLY) {
- write_params(d);
- }
-
- khm_set_dialog_result(hwnd, 0);
-
- return TRUE;
- }
-
- }
-
- return FALSE;
-}
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<khmapp.h>
+#include<assert.h>
+
+typedef struct tag_notif_data {
+ khui_config_node node;
+
+ BOOL modified;
+
+ BOOL monitor;
+ BOOL renew;
+ BOOL halflife;
+ BOOL warn1;
+ BOOL warn2;
+
+ khui_tracker tc_renew;
+ khui_tracker tc_warn1;
+ khui_tracker tc_warn2;
+} notif_data;
+
+static void
+read_params(notif_data * d) {
+ khm_handle csp_cw;
+ khm_int32 rv;
+ khm_int32 t;
+
+ rv = khc_open_space(NULL, L"CredWindow", KHM_PERM_READ, &csp_cw);
+ assert(KHM_SUCCEEDED(rv));
+
+ rv = khc_read_int32(csp_cw, L"Monitor", &t);
+ assert(KHM_SUCCEEDED(rv));
+ d->monitor = !!t;
+
+ rv = khc_read_int32(csp_cw, L"AllowAutoRenew", &t);
+ assert(KHM_SUCCEEDED(rv));
+ d->renew = !!t;
+
+ rv = khc_read_int32(csp_cw, L"RenewAtHalfLife", &t);
+ assert(KHM_SUCCEEDED(rv));
+ d->halflife = !!t;
+
+ rv = khc_read_int32(csp_cw, L"AllowWarn", &t);
+ assert(KHM_SUCCEEDED(rv));
+ d->warn1 = !!t;
+
+ rv = khc_read_int32(csp_cw, L"AllowCritical", &t);
+ assert(KHM_SUCCEEDED(rv));
+ d->warn2 = !!t;
+
+ rv = khc_read_int32(csp_cw, L"AutoRenewThreshold", &t);
+ assert(KHM_SUCCEEDED(rv));
+ d->tc_renew.current = t;
+
+ rv = khc_read_int32(csp_cw, L"WarnThreshold", &t);
+ assert(KHM_SUCCEEDED(rv));
+ d->tc_warn1.current = t;
+
+ rv = khc_read_int32(csp_cw, L"CriticalThreshold", &t);
+ assert(KHM_SUCCEEDED(rv));
+ d->tc_warn2.current = t;
+
+ rv = khc_read_int32(csp_cw, L"MaxThreshold", &t);
+ assert(KHM_SUCCEEDED(rv));
+ d->tc_renew.max = t;
+ d->tc_warn1.max = t;
+ d->tc_warn2.max = t;
+
+ rv = khc_read_int32(csp_cw, L"MinThreshold", &t);
+ assert(KHM_SUCCEEDED(rv));
+ d->tc_renew.min = t;
+ d->tc_warn1.min = t;
+ d->tc_warn2.min = t;
+
+ khc_close_space(csp_cw);
+
+ d->modified = FALSE;
+}
+
+static void
+check_for_modification(notif_data * d) {
+ notif_data t;
+
+ ZeroMemory(&t, sizeof(t));
+
+ read_params(&t);
+
+ if ((!!d->monitor) != (!!t.monitor) ||
+ (!!d->renew) != (!!t.renew) ||
+ (!!d->halflife) != (!!t.halflife) ||
+ (!!d->warn1) != (!!t.warn1) ||
+ (!!d->warn2) != (!!t.warn2) ||
+ d->tc_renew.current != t.tc_renew.current ||
+ d->tc_warn1.current != t.tc_warn1.current ||
+ d->tc_warn2.current != t.tc_warn2.current) {
+
+ khui_cfg_set_flags(d->node,
+ KHUI_CNFLAG_MODIFIED,
+ KHUI_CNFLAG_MODIFIED);
+
+ d->modified = TRUE;
+
+ } else {
+ khui_cfg_set_flags(d->node,
+ 0,
+ KHUI_CNFLAG_MODIFIED);
+
+ d->modified = FALSE;
+ }
+}
+
+static void
+write_params(notif_data * d) {
+ khm_handle csp_cw;
+ khm_int32 rv;
+
+ if (!d->modified)
+ return;
+
+ rv = khc_open_space(NULL, L"CredWindow", KHM_PERM_WRITE, &csp_cw);
+ assert(KHM_SUCCEEDED(rv));
+
+ rv = khc_write_int32(csp_cw, L"Monitor", d->monitor);
+ assert(KHM_SUCCEEDED(rv));
+
+ rv = khc_write_int32(csp_cw, L"AllowAutoRenew", d->renew);
+ assert(KHM_SUCCEEDED(rv));
+
+ rv = khc_write_int32(csp_cw, L"RenewAtHalfLife", d->halflife);
+ assert(KHM_SUCCEEDED(rv));
+
+ rv = khc_write_int32(csp_cw, L"AllowWarn", d->warn1);
+ assert(KHM_SUCCEEDED(rv));
+
+ rv = khc_write_int32(csp_cw, L"AllowCritical", d->warn2);
+ assert(KHM_SUCCEEDED(rv));
+
+
+ rv = khc_write_int32(csp_cw, L"AutoRenewThreshold",
+ (khm_int32) d->tc_renew.current);
+ assert(KHM_SUCCEEDED(rv));
+
+ rv = khc_write_int32(csp_cw, L"WarnThreshold",
+ (khm_int32) d->tc_warn1.current);
+ assert(KHM_SUCCEEDED(rv));
+
+ rv = khc_write_int32(csp_cw, L"CriticalThreshold",
+ (khm_int32) d->tc_warn2.current);
+ assert(KHM_SUCCEEDED(rv));
+
+ khc_close_space(csp_cw);
+
+ khui_cfg_set_flags(d->node,
+ KHUI_CNFLAG_APPLIED,
+ KHUI_CNFLAG_APPLIED | KHUI_CNFLAG_MODIFIED);
+
+ khm_timer_refresh(hwnd_notifier);
+}
+
+static void
+refresh_view(HWND hwnd, notif_data * d) {
+ CheckDlgButton(hwnd, IDC_NOTIF_MONITOR,
+ (d->monitor?BST_CHECKED:BST_UNCHECKED));
+ CheckDlgButton(hwnd, IDC_NOTIF_RENEW,
+ (d->renew?BST_CHECKED:BST_UNCHECKED));
+ CheckDlgButton(hwnd, IDC_NOTIF_HALFLIFE,
+ (d->halflife?BST_CHECKED:BST_UNCHECKED));
+ CheckDlgButton(hwnd, IDC_NOTIF_WARN1,
+ (d->warn1?BST_CHECKED:BST_UNCHECKED));
+ CheckDlgButton(hwnd, IDC_NOTIF_WARN2,
+ (d->warn2?BST_CHECKED:BST_UNCHECKED));
+ khui_tracker_refresh(&d->tc_renew);
+ khui_tracker_refresh(&d->tc_warn1);
+ khui_tracker_refresh(&d->tc_warn2);
+ if (!d->monitor) {
+ EnableWindow(GetDlgItem(hwnd, IDC_NOTIF_RENEW), FALSE);
+ EnableWindow(GetDlgItem(hwnd, IDC_NOTIF_HALFLIFE), FALSE);
+ EnableWindow(GetDlgItem(hwnd, IDC_NOTIF_WARN1), FALSE);
+ EnableWindow(GetDlgItem(hwnd, IDC_NOTIF_WARN2), FALSE);
+ EnableWindow(GetDlgItem(hwnd, IDC_NOTIF_RENEW_THR), FALSE);
+ EnableWindow(GetDlgItem(hwnd, IDC_NOTIF_WARN1_THR), FALSE);
+ EnableWindow(GetDlgItem(hwnd, IDC_NOTIF_WARN2_THR), FALSE);
+ } else {
+ EnableWindow(GetDlgItem(hwnd, IDC_NOTIF_RENEW), TRUE);
+ EnableWindow(GetDlgItem(hwnd, IDC_NOTIF_HALFLIFE), TRUE);
+ EnableWindow(GetDlgItem(hwnd, IDC_NOTIF_WARN1), TRUE);
+ EnableWindow(GetDlgItem(hwnd, IDC_NOTIF_WARN2), TRUE);
+ EnableWindow(GetDlgItem(hwnd, IDC_NOTIF_RENEW_THR), !!(d->renew));
+ EnableWindow(GetDlgItem(hwnd, IDC_NOTIF_WARN1_THR), !!(d->warn1));
+ EnableWindow(GetDlgItem(hwnd, IDC_NOTIF_WARN2_THR), !!(d->warn2));
+ }
+}
+
+static void
+refresh_data(HWND hwnd, notif_data * d) {
+ d->monitor = (IsDlgButtonChecked(hwnd, IDC_NOTIF_MONITOR)
+ == BST_CHECKED);
+ d->renew = (IsDlgButtonChecked(hwnd, IDC_NOTIF_RENEW)
+ == BST_CHECKED);
+ d->halflife = (IsDlgButtonChecked(hwnd, IDC_NOTIF_HALFLIFE)
+ == BST_CHECKED);
+ d->warn1 = (IsDlgButtonChecked(hwnd, IDC_NOTIF_WARN1)
+ == BST_CHECKED);
+ d->warn2 = (IsDlgButtonChecked(hwnd, IDC_NOTIF_WARN2)
+ == BST_CHECKED);
+
+ check_for_modification(d);
+}
+
+INT_PTR CALLBACK
+khm_cfg_notifications_proc(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam) {
+
+ notif_data * d;
+
+ switch(uMsg) {
+ case WM_INITDIALOG: {
+ HWND hw;
+
+ d = PMALLOC(sizeof(*d));
+#ifdef DEBUG
+ assert(d != NULL);
+#endif
+
+#pragma warning(push)
+#pragma warning(disable: 4244)
+ SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) d);
+#pragma warning(pop)
+
+ ZeroMemory(d, sizeof(*d));
+
+ d->node = (khui_config_node) lParam;
+
+ khui_tracker_initialize(&d->tc_renew);
+ khui_tracker_initialize(&d->tc_warn1);
+ khui_tracker_initialize(&d->tc_warn2);
+
+ read_params(d);
+
+ hw = GetDlgItem(hwnd, IDC_NOTIF_RENEW_THR);
+ khui_tracker_install(hw, &d->tc_renew);
+
+ hw = GetDlgItem(hwnd, IDC_NOTIF_WARN1_THR);
+ khui_tracker_install(hw, &d->tc_warn1);
+
+ hw = GetDlgItem(hwnd, IDC_NOTIF_WARN2_THR);
+ khui_tracker_install(hw, &d->tc_warn2);
+
+ refresh_view(hwnd, d);
+
+ /* normally we should return TRUE, but in this case we return
+ FALSE since we don't want to inadvertently steal the focus
+ from the treeview. */
+ return FALSE;
+ }
+
+ case WM_COMMAND: {
+ d = (notif_data *) (DWORD_PTR) GetWindowLongPtr(hwnd, DWLP_USER);
+
+ if (HIWORD(wParam) == BN_CLICKED) {
+ refresh_data(hwnd, d);
+ refresh_view(hwnd, d);
+
+ check_for_modification(d);
+ } else if (HIWORD(wParam) == EN_CHANGE) {
+ SetTimer(hwnd, 1, 500, NULL);
+ }
+
+ khm_set_dialog_result(hwnd, 0);
+
+ return TRUE;
+ }
+
+ case WM_TIMER: {
+ d = (notif_data *) (DWORD_PTR) GetWindowLongPtr(hwnd, DWLP_USER);
+ KillTimer(hwnd, 1);
+ check_for_modification(d);
+
+ khm_set_dialog_result(hwnd, 0);
+
+ return TRUE;
+ }
+
+ case WM_DESTROY: {
+ d = (notif_data *) (DWORD_PTR) GetWindowLongPtr(hwnd, DWLP_USER);
+
+ khui_tracker_kill_controls(&d->tc_renew);
+ khui_tracker_kill_controls(&d->tc_warn1);
+ khui_tracker_kill_controls(&d->tc_warn2);
+
+ PFREE(d);
+
+ SetWindowLongPtr(hwnd, DWLP_USER, 0);
+
+ khm_set_dialog_result(hwnd, 0);
+
+ return TRUE;
+ }
+
+ case KHUI_WM_CFG_NOTIFY: {
+ d = (notif_data *) (DWORD_PTR) GetWindowLongPtr(hwnd, DWLP_USER);
+
+ if (HIWORD(wParam) == WMCFG_APPLY) {
+ write_params(d);
+ }
+
+ khm_set_dialog_result(hwnd, 0);
+
+ return TRUE;
+ }
+
+ }
+
+ return FALSE;
+}
diff --git a/src/windows/identity/ui/cfg_plugins_wnd.c b/src/windows/identity/ui/cfg_plugins_wnd.c
index cab71c4ea2..6290d37032 100644
--- a/src/windows/identity/ui/cfg_plugins_wnd.c
+++ b/src/windows/identity/ui/cfg_plugins_wnd.c
@@ -1,646 +1,646 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<khmapp.h>
-#include<assert.h>
-
-#define MAX_PLUGINS 256
-
-typedef struct tag_plugin_data {
- kmm_plugin_info plugin;
- kmm_module_info module;
-} plugin_data;
-
-typedef struct tag_plugin_dlg_data {
- plugin_data * info[MAX_PLUGINS];
- khm_size n_info;
-
- plugin_data * selected;
- HICON plugin_ico;
-} plugin_dlg_data;
-
-void update_dialog_fields(HWND hwnd,
- plugin_dlg_data * d,
- plugin_data * info) {
- wchar_t buf[256];
- UINT resid;
- wchar_t * t;
- khm_handle csp_module = NULL;
-
- d->selected = info;
-
- if (info->plugin.reg.description)
- SetDlgItemText(hwnd, IDC_CFG_DESC, info->plugin.reg.description);
- else {
- wchar_t fmt[128];
-
- LoadString(khm_hInstance, IDS_CFG_NODESC, fmt, ARRAYLENGTH(fmt));
- StringCbPrintf(buf, sizeof(buf), fmt, info->plugin.reg.name);
- SetDlgItemText(hwnd, IDC_CFG_DESC, buf);
- }
-
- switch(info->plugin.state) {
- case KMM_PLUGIN_STATE_FAIL_INIT:
- resid = IDS_PISTATE_FAILINIT;
- break;
-
- case KMM_PLUGIN_STATE_FAIL_UNKNOWN:
- resid = IDS_PISTATE_FAILUNK;
- break;
-
- case KMM_PLUGIN_STATE_FAIL_MAX_FAILURE:
- resid = IDS_PISTATE_FAILMAX;
- break;
-
- case KMM_PLUGIN_STATE_FAIL_NOT_REGISTERED:
- resid = IDS_PISTATE_FAILREG;
- break;
-
- case KMM_PLUGIN_STATE_FAIL_DISABLED:
- resid = IDS_PISTATE_FAILDIS;
- break;
-
- case KMM_PLUGIN_STATE_FAIL_LOAD:
- resid = IDS_PISTATE_FAILLOD;
- break;
-
- case KMM_PLUGIN_STATE_NONE:
- case KMM_PLUGIN_STATE_PLACEHOLDER:
- resid = IDS_PISTATE_PLACEHOLD;
- break;
-
- case KMM_PLUGIN_STATE_REG:
- case KMM_PLUGIN_STATE_PREINIT:
- resid = IDS_PISTATE_REG;
- break;
-
- case KMM_PLUGIN_STATE_HOLD:
- resid = IDS_PISTATE_HOLD;
- break;
-
- case KMM_PLUGIN_STATE_INIT:
- resid = IDS_PISTATE_INIT;
- break;
-
- case KMM_PLUGIN_STATE_RUNNING:
- resid = IDS_PISTATE_RUN;
- break;
-
- case KMM_PLUGIN_STATE_EXITED:
- resid = IDS_PISTATE_EXIT;
- break;
-
- default:
-#ifdef DEBUG
- assert(FALSE);
-#endif
- resid = IDS_PISTATE_FAILUNK;
- }
-
- LoadString(khm_hInstance, resid,
- buf, ARRAYLENGTH(buf));
-
- SetDlgItemText(hwnd, IDC_CFG_STATE, buf);
-
- SendDlgItemMessage(hwnd, IDC_CFG_DEPS,
- LB_RESETCONTENT, 0, 0);
-
- for (t = info->plugin.reg.dependencies; t && *t;
- t = multi_string_next(t)) {
- SendDlgItemMessage(hwnd, IDC_CFG_DEPS,
- LB_INSERTSTRING, -1, (LPARAM) t);
- }
-
- if (info->plugin.reg.module)
- SetDlgItemText(hwnd, IDC_CFG_MODULE,
- info->plugin.reg.module);
- else
- SetDlgItemText(hwnd, IDC_CFG_MODULE,
- L"");
-
- if (info->module.reg.vendor)
- SetDlgItemText(hwnd, IDC_CFG_VENDOR,
- info->module.reg.vendor);
- else
- SetDlgItemText(hwnd, IDC_CFG_VENDOR,
- L"");
-
- StringCbPrintf(buf, sizeof(buf), L"%u.%u.%u.%u",
- (unsigned int) info->module.product_version.major,
- (unsigned int) info->module.product_version.minor,
- (unsigned int) info->module.product_version.patch,
- (unsigned int) info->module.product_version.aux);
-
- SetDlgItemText(hwnd, IDC_CFG_VERSION, buf);
-
- if (info->plugin.reg.icon) {
- SendDlgItemMessage(hwnd, IDC_CFG_ICON,
- STM_SETICON,
- (WPARAM) info->plugin.reg.icon,
- 0);
- } else {
- SendDlgItemMessage(hwnd, IDC_CFG_ICON,
- STM_SETICON,
- (WPARAM) d->plugin_ico,
- 0);
- }
-
- if (KHM_SUCCEEDED(kmm_get_module_config(info->module.reg.name,
- 0, &csp_module)) &&
- (khc_value_exists(csp_module, L"ImagePath") &
- (KCONF_FLAG_MACHINE | KCONF_FLAG_USER))) {
-
- EnableWindow(GetDlgItem(hwnd, IDC_CFG_UNREGISTER), TRUE);
- } else {
- EnableWindow(GetDlgItem(hwnd, IDC_CFG_UNREGISTER), FALSE);
- }
-
- if (csp_module)
- khc_close_space(csp_module);
-
- if (info->plugin.flags & KMM_PLUGIN_FLAG_DISABLED) {
- EnableWindow(GetDlgItem(hwnd, IDC_CFG_ENABLE), TRUE);
- EnableWindow(GetDlgItem(hwnd, IDC_CFG_DISABLE), FALSE);
- } else {
- EnableWindow(GetDlgItem(hwnd, IDC_CFG_ENABLE), FALSE);
- EnableWindow(GetDlgItem(hwnd, IDC_CFG_DISABLE), TRUE);
- }
-}
-
-#define IDX_PLUGIN_NORMAL 1
-#define IDX_PLUGIN_DISABLED 2
-#define IDX_PLUGIN_ERROR 3
-
-INT_PTR CALLBACK
-khm_cfg_plugins_proc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam) {
-
- plugin_dlg_data * d;
-
- switch(uMsg) {
- case WM_INITDIALOG:
- {
- kmm_plugin p;
- kmm_plugin pn;
- kmm_module m;
- khm_size i;
- LVCOLUMN lvc;
- RECT r;
- HWND hw;
- wchar_t buf[256];
- HIMAGELIST h_ilist;
- HICON h_icon;
-
- d = PMALLOC(sizeof(*d));
-#ifdef DEBUG
- assert(d);
-#endif
- ZeroMemory(d, sizeof(*d));
-#pragma warning(push)
-#pragma warning(disable: 4244)
- SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) d);
-#pragma warning(pop)
-
- p = NULL;
- i = 0;
- do {
- if (KHM_FAILED(kmm_get_next_plugin(p, &pn)))
- break;
-
- if (p)
- kmm_release_plugin(p);
- p = pn;
-
-#ifdef DEBUG
- assert(d->info[i] == NULL);
-#endif
- d->info[i] = PMALLOC(sizeof(*(d->info[i])));
-#ifdef DEBUG
- assert(d->info[i]);
-#endif
- ZeroMemory(&d->info[i]->plugin,
- sizeof(d->info[i]->plugin));
-
- if (KHM_FAILED(kmm_get_plugin_info_i(p, &d->info[i]->plugin))) {
- PFREE(d->info[i]);
- d->info[i] = NULL;
- break;
- }
-
- ZeroMemory(&d->info[i]->module,
- sizeof(d->info[i]->module));
-
- if (KHM_SUCCEEDED(kmm_load_module(d->info[i]->plugin.reg.module,
- KMM_LM_FLAG_NOLOAD,
- &m))) {
- kmm_get_module_info_i(m, &d->info[i]->module);
- kmm_release_module(m);
- }
-
- i ++;
-
- if (i == MAX_PLUGINS)
- break;
- } while(p);
-
- if (p)
- kmm_release_plugin(p);
-
- d->n_info = i;
-
- /* now populate the list view */
- hw = GetDlgItem(hwnd, IDC_CFG_PLUGINS);
-#ifdef DEBUG
- assert(hw);
-#endif
-
- h_ilist = ImageList_Create(GetSystemMetrics(SM_CXSMICON),
- GetSystemMetrics(SM_CYSMICON),
- ILC_COLOR8,
- 4, 4);
-
- h_icon = LoadImage(khm_hInstance,
- MAKEINTRESOURCE(IDI_CFG_PLUGIN),
- IMAGE_ICON,
- GetSystemMetrics(SM_CXSMICON),
- GetSystemMetrics(SM_CYSMICON),
- LR_DEFAULTCOLOR);
-#ifdef DEBUG
- assert(h_icon);
-#endif
- ImageList_AddIcon(h_ilist, h_icon);
- DestroyIcon(h_icon);
-
- h_icon = LoadImage(khm_hInstance,
- MAKEINTRESOURCE(IDI_CFG_PLUGIN_DIS),
- IMAGE_ICON,
- GetSystemMetrics(SM_CXSMICON),
- GetSystemMetrics(SM_CYSMICON),
- LR_DEFAULTCOLOR);
-#ifdef DEBUG
- assert(h_icon);
-#endif
- ImageList_AddIcon(h_ilist, h_icon);
- DestroyIcon(h_icon);
-
- h_icon = LoadImage(khm_hInstance,
- MAKEINTRESOURCE(IDI_CFG_PLUGIN_ERR),
- IMAGE_ICON,
- GetSystemMetrics(SM_CXSMICON),
- GetSystemMetrics(SM_CYSMICON),
- LR_DEFAULTCOLOR);
-#ifdef DEBUG
- assert(h_icon);
-#endif
- ImageList_AddIcon(h_ilist, h_icon);
- DestroyIcon(h_icon);
-
- ListView_SetImageList(hw, h_ilist, LVSIL_STATE);
-
- ZeroMemory(&lvc, sizeof(lvc));
-
- lvc.mask = LVCF_TEXT | LVCF_WIDTH;
- GetWindowRect(hw, &r);
- lvc.cx = ((r.right - r.left) * 95) / 100;
- lvc.pszText = buf;
-
- LoadString(khm_hInstance, IDS_CFG_PI_COL_PLUGINS,
- buf, ARRAYLENGTH(buf));
-
- ListView_InsertColumn(hw, 0, &lvc);
-
- for(i=0; i<d->n_info; i++) {
- LVITEM lvi;
-
- ZeroMemory(&lvi, sizeof(lvi));
-
- lvi.mask = LVIF_PARAM | LVIF_TEXT | LVIF_STATE;
- lvi.lParam = (LPARAM) d->info[i];
- lvi.pszText = d->info[i]->plugin.reg.name;
-
- if (d->info[i]->plugin.flags & KMM_PLUGIN_FLAG_DISABLED) {
- lvi.state = INDEXTOSTATEIMAGEMASK(IDX_PLUGIN_DISABLED);
- } else if (d->info[i]->plugin.state < 0) {
- lvi.state = INDEXTOSTATEIMAGEMASK(IDX_PLUGIN_ERROR);
- } else {
- lvi.state = INDEXTOSTATEIMAGEMASK(IDX_PLUGIN_NORMAL);
- }
-
- ListView_InsertItem(hw, &lvi);
- }
-
- d->plugin_ico =
- (HICON) LoadImage(khm_hInstance,
- MAKEINTRESOURCE(IDI_CFG_PLUGIN),
- IMAGE_ICON,
- GetSystemMetrics(SM_CXICON),
- GetSystemMetrics(SM_CYICON),
- LR_DEFAULTCOLOR);
- }
- return FALSE;
-
- case WM_NOTIFY:
- {
- LPNMHDR lpnm;
- HWND hw;
-
- d = (plugin_dlg_data *) (LONG_PTR)
- GetWindowLongPtr(hwnd, DWLP_USER);
-
- if (wParam == IDC_CFG_PLUGINS &&
- (lpnm = (LPNMHDR) lParam) &&
- lpnm->code == LVN_ITEMCHANGED) {
-
- LVITEM lvi;
-
- hw = GetDlgItem(hwnd, IDC_CFG_PLUGINS);
-#ifdef DEBUG
- assert(hw);
-#endif
- if (ListView_GetSelectedCount(hw) != 1) {
- SetDlgItemText(hwnd, IDC_CFG_DESC, L"");
- SetDlgItemText(hwnd, IDC_CFG_STATE, L"");
- SetDlgItemText(hwnd, IDC_CFG_MODULE, L"");
- SetDlgItemText(hwnd, IDC_CFG_VENDOR, L"");
- SetDlgItemText(hwnd, IDC_CFG_VERSION, L"");
- EnableWindow(GetDlgItem(hwnd, IDC_CFG_ENABLE), FALSE);
- EnableWindow(GetDlgItem(hwnd, IDC_CFG_DISABLE), FALSE);
- EnableWindow(GetDlgItem(hwnd, IDC_CFG_UNREGISTER), FALSE);
- SendDlgItemMessage(hwnd, IDC_CFG_DEPS,
- LB_RESETCONTENT, 0, 0);
- SendDlgItemMessage(hwnd, IDC_CFG_ICON, STM_SETICON,
- (WPARAM) d->plugin_ico, 0);
- d->selected = NULL;
- } else {
- int idx;
- plugin_data * info;
-
- idx = ListView_GetNextItem(hw, -1, LVNI_SELECTED);
-#ifdef DEBUG
- assert(idx != -1);
-#endif
- ZeroMemory(&lvi, sizeof(lvi));
- lvi.iItem = idx;
- lvi.iSubItem = 0;
- lvi.mask = LVIF_PARAM;
-
- ListView_GetItem(hw, &lvi);
-#ifdef DEBUG
- assert(lvi.lParam != 0);
-#endif
- info = (plugin_data *) lvi.lParam;
-
- update_dialog_fields(hwnd, d, info);
- }
- }
- }
- return TRUE;
-
- case WM_COMMAND:
- {
-
- d = (plugin_dlg_data *) (LONG_PTR)
- GetWindowLongPtr(hwnd, DWLP_USER);
-
- switch (wParam) {
- case MAKEWPARAM(IDC_CFG_ENABLE, BN_CLICKED):
- if (d->selected != NULL) {
- khui_alert * alert = NULL;
- wchar_t buf[KHUI_MAXCCH_MESSAGE];
- wchar_t fmt[KHUI_MAXCCH_MESSAGE];
- kmm_plugin p;
-
- khui_alert_create_empty(&alert);
-
- LoadString(khm_hInstance, IDS_CFG_P_ENBCNFT,
- fmt, ARRAYLENGTH(fmt));
- StringCbPrintf(buf, sizeof(buf), fmt, d->selected->plugin.reg.name);
- khui_alert_set_title(alert, buf);
-
- LoadString(khm_hInstance, IDS_CFG_P_ENBCNFM,
- fmt, ARRAYLENGTH(fmt));
- StringCbPrintf(buf, sizeof(buf), fmt, d->selected->plugin.reg.name);
- khui_alert_set_message(alert, buf);
-
- khui_alert_set_severity(alert, KHERR_INFO);
-
- khui_alert_show_modal(alert);
-
- kmm_enable_plugin(d->selected->plugin.h_plugin, TRUE);
-
- khui_alert_release(alert);
-
- p = d->selected->plugin.h_plugin;
- kmm_hold_plugin(p);
- kmm_release_plugin_info_i(&d->selected->plugin);
- kmm_get_plugin_info_i(p, &d->selected->plugin);
- kmm_release_plugin(p);
-
- update_dialog_fields(hwnd, d, d->selected);
- }
- break;
-
- case MAKEWPARAM(IDC_CFG_DISABLE, BN_CLICKED):
- if (d->selected != NULL) {
- khui_alert * alert = NULL;
- wchar_t buf[KHUI_MAXCCH_MESSAGE];
- wchar_t fmt[KHUI_MAXCCH_MESSAGE];
- wchar_t depends[KHUI_MAXCCH_MESSAGE];
- khm_size i;
- kmm_plugin p;
-
- khui_alert_create_empty(&alert);
-#ifdef DEBUG
- assert(alert);
-#endif
- if (alert == NULL)
- break;
-
- LoadString(khm_hInstance, IDS_CFG_P_DELCNFT,
- fmt, ARRAYLENGTH(fmt));
- StringCbPrintf(buf, sizeof(buf), fmt, d->selected->plugin.reg.name);
- khui_alert_set_title(alert, buf);
-
- LoadString(khm_hInstance, IDS_CFG_P_DELCNFM,
- fmt, ARRAYLENGTH(fmt));
- StringCbPrintf(buf, sizeof(buf), fmt, d->selected->plugin.reg.name);
- khui_alert_set_message(alert, buf);
-
- depends[0] = L'\0';
-
- for (i=0; i<d->n_info; i++) {
- wchar_t * t;
-
- t = d->info[i]->plugin.reg.dependencies;
-
- while(t) {
- if (!wcscmp(t, d->selected->plugin.reg.name)) {
- if (depends[0])
- StringCbCat(depends, sizeof(depends), L", ");
- StringCbCat(depends, sizeof(depends),
- d->info[i]->plugin.reg.name);
- break;
- }
- t = multi_string_next(t);
- }
- }
-
- if (depends[0]) {
- LoadString(khm_hInstance, IDS_CFG_P_DELCNFS,
- fmt, ARRAYLENGTH(fmt));
- StringCbPrintf(buf, sizeof(buf), fmt, depends);
- khui_alert_set_suggestion(alert, buf);
- } else {
- LoadString(khm_hInstance, IDS_CFG_P_DELNDEP,
- buf, ARRAYLENGTH(buf));
- khui_alert_set_suggestion(alert, buf);
- }
-
- khui_alert_add_command(alert, KHUI_PACTION_YES);
- khui_alert_add_command(alert, KHUI_PACTION_NO);
-
- khui_alert_set_severity(alert, KHERR_WARNING);
-
- if (KHM_SUCCEEDED(khui_alert_show_modal(alert)) &&
- alert->response == KHUI_PACTION_YES) {
- kmm_enable_plugin(d->selected->plugin.h_plugin, FALSE);
- }
-
- khui_alert_release(alert);
-
- p = d->selected->plugin.h_plugin;
- kmm_hold_plugin(p);
- kmm_release_plugin_info_i(&d->selected->plugin);
- kmm_get_plugin_info_i(p, &d->selected->plugin);
- kmm_release_plugin(p);
-
- update_dialog_fields(hwnd, d, d->selected);
- }
- break;
-
- case MAKEWPARAM(IDC_CFG_UNREGISTER, BN_CLICKED):
- {
- khui_alert * alert = NULL;
- wchar_t buf[KHUI_MAXCCH_MESSAGE];
- wchar_t fmt[KHUI_MAXCCH_MESSAGE];
- wchar_t plist[KHUI_MAXCCH_MESSAGE];
- khm_size i;
-
- if (d->selected == NULL) {
-#ifdef DEBUG
- assert(FALSE);
-#endif
- break;
- }
-
- khui_alert_create_empty(&alert);
-
- LoadString(khm_hInstance, IDS_CFG_P_UNRCNFT,
- fmt, ARRAYLENGTH(fmt));
- StringCbPrintf(buf, sizeof(buf), fmt,
- d->selected->plugin.reg.name);
-
- khui_alert_set_title(alert, buf);
-
- LoadString(khm_hInstance, IDS_CFG_P_UNRCNFM,
- fmt, ARRAYLENGTH(fmt));
- StringCbPrintf(buf, sizeof(buf), fmt,
- d->selected->plugin.reg.name);
-
- khui_alert_set_message(alert, buf);
-
- plist[0] = L'\0';
- for (i=0; i < d->n_info; i++) {
- if (!wcscmp(d->info[i]->module.reg.name,
- d->selected->module.reg.name)) {
- if (plist[0])
- StringCbCat(plist, sizeof(plist), L", ");
- StringCbCat(plist, sizeof(plist),
- d->info[i]->plugin.reg.name);
- }
- }
-
-#ifdef DEBUG
- /* there should have been at least one plugin */
- assert(plist[0]);
-#endif
-
- LoadString(khm_hInstance, IDS_CFG_P_UNRCNFS,
- fmt, ARRAYLENGTH(fmt));
- StringCbPrintf(buf, sizeof(buf), fmt, plist);
- khui_alert_set_suggestion(alert, buf);
-
- khui_alert_add_command(alert, KHUI_PACTION_YES);
- khui_alert_add_command(alert, KHUI_PACTION_NO);
-
- khui_alert_set_severity(alert, KHERR_WARNING);
-
- if (KHM_SUCCEEDED(khui_alert_show_modal(alert)) &&
- alert->response == KHUI_PACTION_YES) {
- kmm_unregister_module(d->selected->module.reg.name, 0);
-
- update_dialog_fields(hwnd, d, d->selected);
- }
- }
- break;
-
- case MAKEWPARAM(IDC_CFG_REGISTER, BN_CLICKED):
- {
-
- }
- break;
- }
- }
- return TRUE;
-
- case WM_DESTROY:
- {
- khm_size i;
-
- d = (plugin_dlg_data *) (LONG_PTR)
- GetWindowLongPtr(hwnd, DWLP_USER);
-#ifdef DEBUG
- assert(d);
-#endif
- for (i=0; i<d->n_info; i++) {
-#ifdef DEBUG
- assert(d->info[i]);
-#endif
- kmm_release_plugin_info_i(&d->info[i]->plugin);
- kmm_release_module_info_i(&d->info[i]->module);
- PFREE(d->info[i]);
- }
-
- PFREE(d);
-
- khm_set_dialog_result(hwnd, 0);
- }
- return TRUE;
- }
- return FALSE;
-}
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<khmapp.h>
+#include<assert.h>
+
+#define MAX_PLUGINS 256
+
+typedef struct tag_plugin_data {
+ kmm_plugin_info plugin;
+ kmm_module_info module;
+} plugin_data;
+
+typedef struct tag_plugin_dlg_data {
+ plugin_data * info[MAX_PLUGINS];
+ khm_size n_info;
+
+ plugin_data * selected;
+ HICON plugin_ico;
+} plugin_dlg_data;
+
+void update_dialog_fields(HWND hwnd,
+ plugin_dlg_data * d,
+ plugin_data * info) {
+ wchar_t buf[256];
+ UINT resid;
+ wchar_t * t;
+ khm_handle csp_module = NULL;
+
+ d->selected = info;
+
+ if (info->plugin.reg.description)
+ SetDlgItemText(hwnd, IDC_CFG_DESC, info->plugin.reg.description);
+ else {
+ wchar_t fmt[128];
+
+ LoadString(khm_hInstance, IDS_CFG_NODESC, fmt, ARRAYLENGTH(fmt));
+ StringCbPrintf(buf, sizeof(buf), fmt, info->plugin.reg.name);
+ SetDlgItemText(hwnd, IDC_CFG_DESC, buf);
+ }
+
+ switch(info->plugin.state) {
+ case KMM_PLUGIN_STATE_FAIL_INIT:
+ resid = IDS_PISTATE_FAILINIT;
+ break;
+
+ case KMM_PLUGIN_STATE_FAIL_UNKNOWN:
+ resid = IDS_PISTATE_FAILUNK;
+ break;
+
+ case KMM_PLUGIN_STATE_FAIL_MAX_FAILURE:
+ resid = IDS_PISTATE_FAILMAX;
+ break;
+
+ case KMM_PLUGIN_STATE_FAIL_NOT_REGISTERED:
+ resid = IDS_PISTATE_FAILREG;
+ break;
+
+ case KMM_PLUGIN_STATE_FAIL_DISABLED:
+ resid = IDS_PISTATE_FAILDIS;
+ break;
+
+ case KMM_PLUGIN_STATE_FAIL_LOAD:
+ resid = IDS_PISTATE_FAILLOD;
+ break;
+
+ case KMM_PLUGIN_STATE_NONE:
+ case KMM_PLUGIN_STATE_PLACEHOLDER:
+ resid = IDS_PISTATE_PLACEHOLD;
+ break;
+
+ case KMM_PLUGIN_STATE_REG:
+ case KMM_PLUGIN_STATE_PREINIT:
+ resid = IDS_PISTATE_REG;
+ break;
+
+ case KMM_PLUGIN_STATE_HOLD:
+ resid = IDS_PISTATE_HOLD;
+ break;
+
+ case KMM_PLUGIN_STATE_INIT:
+ resid = IDS_PISTATE_INIT;
+ break;
+
+ case KMM_PLUGIN_STATE_RUNNING:
+ resid = IDS_PISTATE_RUN;
+ break;
+
+ case KMM_PLUGIN_STATE_EXITED:
+ resid = IDS_PISTATE_EXIT;
+ break;
+
+ default:
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ resid = IDS_PISTATE_FAILUNK;
+ }
+
+ LoadString(khm_hInstance, resid,
+ buf, ARRAYLENGTH(buf));
+
+ SetDlgItemText(hwnd, IDC_CFG_STATE, buf);
+
+ SendDlgItemMessage(hwnd, IDC_CFG_DEPS,
+ LB_RESETCONTENT, 0, 0);
+
+ for (t = info->plugin.reg.dependencies; t && *t;
+ t = multi_string_next(t)) {
+ SendDlgItemMessage(hwnd, IDC_CFG_DEPS,
+ LB_INSERTSTRING, -1, (LPARAM) t);
+ }
+
+ if (info->plugin.reg.module)
+ SetDlgItemText(hwnd, IDC_CFG_MODULE,
+ info->plugin.reg.module);
+ else
+ SetDlgItemText(hwnd, IDC_CFG_MODULE,
+ L"");
+
+ if (info->module.reg.vendor)
+ SetDlgItemText(hwnd, IDC_CFG_VENDOR,
+ info->module.reg.vendor);
+ else
+ SetDlgItemText(hwnd, IDC_CFG_VENDOR,
+ L"");
+
+ StringCbPrintf(buf, sizeof(buf), L"%u.%u.%u.%u",
+ (unsigned int) info->module.product_version.major,
+ (unsigned int) info->module.product_version.minor,
+ (unsigned int) info->module.product_version.patch,
+ (unsigned int) info->module.product_version.aux);
+
+ SetDlgItemText(hwnd, IDC_CFG_VERSION, buf);
+
+ if (info->plugin.reg.icon) {
+ SendDlgItemMessage(hwnd, IDC_CFG_ICON,
+ STM_SETICON,
+ (WPARAM) info->plugin.reg.icon,
+ 0);
+ } else {
+ SendDlgItemMessage(hwnd, IDC_CFG_ICON,
+ STM_SETICON,
+ (WPARAM) d->plugin_ico,
+ 0);
+ }
+
+ if (KHM_SUCCEEDED(kmm_get_module_config(info->module.reg.name,
+ 0, &csp_module)) &&
+ (khc_value_exists(csp_module, L"ImagePath") &
+ (KCONF_FLAG_MACHINE | KCONF_FLAG_USER))) {
+
+ EnableWindow(GetDlgItem(hwnd, IDC_CFG_UNREGISTER), TRUE);
+ } else {
+ EnableWindow(GetDlgItem(hwnd, IDC_CFG_UNREGISTER), FALSE);
+ }
+
+ if (csp_module)
+ khc_close_space(csp_module);
+
+ if (info->plugin.flags & KMM_PLUGIN_FLAG_DISABLED) {
+ EnableWindow(GetDlgItem(hwnd, IDC_CFG_ENABLE), TRUE);
+ EnableWindow(GetDlgItem(hwnd, IDC_CFG_DISABLE), FALSE);
+ } else {
+ EnableWindow(GetDlgItem(hwnd, IDC_CFG_ENABLE), FALSE);
+ EnableWindow(GetDlgItem(hwnd, IDC_CFG_DISABLE), TRUE);
+ }
+}
+
+#define IDX_PLUGIN_NORMAL 1
+#define IDX_PLUGIN_DISABLED 2
+#define IDX_PLUGIN_ERROR 3
+
+INT_PTR CALLBACK
+khm_cfg_plugins_proc(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam) {
+
+ plugin_dlg_data * d;
+
+ switch(uMsg) {
+ case WM_INITDIALOG:
+ {
+ kmm_plugin p;
+ kmm_plugin pn;
+ kmm_module m;
+ khm_size i;
+ LVCOLUMN lvc;
+ RECT r;
+ HWND hw;
+ wchar_t buf[256];
+ HIMAGELIST h_ilist;
+ HICON h_icon;
+
+ d = PMALLOC(sizeof(*d));
+#ifdef DEBUG
+ assert(d);
+#endif
+ ZeroMemory(d, sizeof(*d));
+#pragma warning(push)
+#pragma warning(disable: 4244)
+ SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) d);
+#pragma warning(pop)
+
+ p = NULL;
+ i = 0;
+ do {
+ if (KHM_FAILED(kmm_get_next_plugin(p, &pn)))
+ break;
+
+ if (p)
+ kmm_release_plugin(p);
+ p = pn;
+
+#ifdef DEBUG
+ assert(d->info[i] == NULL);
+#endif
+ d->info[i] = PMALLOC(sizeof(*(d->info[i])));
+#ifdef DEBUG
+ assert(d->info[i]);
+#endif
+ ZeroMemory(&d->info[i]->plugin,
+ sizeof(d->info[i]->plugin));
+
+ if (KHM_FAILED(kmm_get_plugin_info_i(p, &d->info[i]->plugin))) {
+ PFREE(d->info[i]);
+ d->info[i] = NULL;
+ break;
+ }
+
+ ZeroMemory(&d->info[i]->module,
+ sizeof(d->info[i]->module));
+
+ if (KHM_SUCCEEDED(kmm_load_module(d->info[i]->plugin.reg.module,
+ KMM_LM_FLAG_NOLOAD,
+ &m))) {
+ kmm_get_module_info_i(m, &d->info[i]->module);
+ kmm_release_module(m);
+ }
+
+ i ++;
+
+ if (i == MAX_PLUGINS)
+ break;
+ } while(p);
+
+ if (p)
+ kmm_release_plugin(p);
+
+ d->n_info = i;
+
+ /* now populate the list view */
+ hw = GetDlgItem(hwnd, IDC_CFG_PLUGINS);
+#ifdef DEBUG
+ assert(hw);
+#endif
+
+ h_ilist = ImageList_Create(GetSystemMetrics(SM_CXSMICON),
+ GetSystemMetrics(SM_CYSMICON),
+ ILC_COLOR8,
+ 4, 4);
+
+ h_icon = LoadImage(khm_hInstance,
+ MAKEINTRESOURCE(IDI_CFG_PLUGIN),
+ IMAGE_ICON,
+ GetSystemMetrics(SM_CXSMICON),
+ GetSystemMetrics(SM_CYSMICON),
+ LR_DEFAULTCOLOR);
+#ifdef DEBUG
+ assert(h_icon);
+#endif
+ ImageList_AddIcon(h_ilist, h_icon);
+ DestroyIcon(h_icon);
+
+ h_icon = LoadImage(khm_hInstance,
+ MAKEINTRESOURCE(IDI_CFG_PLUGIN_DIS),
+ IMAGE_ICON,
+ GetSystemMetrics(SM_CXSMICON),
+ GetSystemMetrics(SM_CYSMICON),
+ LR_DEFAULTCOLOR);
+#ifdef DEBUG
+ assert(h_icon);
+#endif
+ ImageList_AddIcon(h_ilist, h_icon);
+ DestroyIcon(h_icon);
+
+ h_icon = LoadImage(khm_hInstance,
+ MAKEINTRESOURCE(IDI_CFG_PLUGIN_ERR),
+ IMAGE_ICON,
+ GetSystemMetrics(SM_CXSMICON),
+ GetSystemMetrics(SM_CYSMICON),
+ LR_DEFAULTCOLOR);
+#ifdef DEBUG
+ assert(h_icon);
+#endif
+ ImageList_AddIcon(h_ilist, h_icon);
+ DestroyIcon(h_icon);
+
+ ListView_SetImageList(hw, h_ilist, LVSIL_STATE);
+
+ ZeroMemory(&lvc, sizeof(lvc));
+
+ lvc.mask = LVCF_TEXT | LVCF_WIDTH;
+ GetWindowRect(hw, &r);
+ lvc.cx = ((r.right - r.left) * 95) / 100;
+ lvc.pszText = buf;
+
+ LoadString(khm_hInstance, IDS_CFG_PI_COL_PLUGINS,
+ buf, ARRAYLENGTH(buf));
+
+ ListView_InsertColumn(hw, 0, &lvc);
+
+ for(i=0; i<d->n_info; i++) {
+ LVITEM lvi;
+
+ ZeroMemory(&lvi, sizeof(lvi));
+
+ lvi.mask = LVIF_PARAM | LVIF_TEXT | LVIF_STATE;
+ lvi.lParam = (LPARAM) d->info[i];
+ lvi.pszText = d->info[i]->plugin.reg.name;
+
+ if (d->info[i]->plugin.flags & KMM_PLUGIN_FLAG_DISABLED) {
+ lvi.state = INDEXTOSTATEIMAGEMASK(IDX_PLUGIN_DISABLED);
+ } else if (d->info[i]->plugin.state < 0) {
+ lvi.state = INDEXTOSTATEIMAGEMASK(IDX_PLUGIN_ERROR);
+ } else {
+ lvi.state = INDEXTOSTATEIMAGEMASK(IDX_PLUGIN_NORMAL);
+ }
+
+ ListView_InsertItem(hw, &lvi);
+ }
+
+ d->plugin_ico =
+ (HICON) LoadImage(khm_hInstance,
+ MAKEINTRESOURCE(IDI_CFG_PLUGIN),
+ IMAGE_ICON,
+ GetSystemMetrics(SM_CXICON),
+ GetSystemMetrics(SM_CYICON),
+ LR_DEFAULTCOLOR);
+ }
+ return FALSE;
+
+ case WM_NOTIFY:
+ {
+ LPNMHDR lpnm;
+ HWND hw;
+
+ d = (plugin_dlg_data *) (LONG_PTR)
+ GetWindowLongPtr(hwnd, DWLP_USER);
+
+ if (wParam == IDC_CFG_PLUGINS &&
+ (lpnm = (LPNMHDR) lParam) &&
+ lpnm->code == LVN_ITEMCHANGED) {
+
+ LVITEM lvi;
+
+ hw = GetDlgItem(hwnd, IDC_CFG_PLUGINS);
+#ifdef DEBUG
+ assert(hw);
+#endif
+ if (ListView_GetSelectedCount(hw) != 1) {
+ SetDlgItemText(hwnd, IDC_CFG_DESC, L"");
+ SetDlgItemText(hwnd, IDC_CFG_STATE, L"");
+ SetDlgItemText(hwnd, IDC_CFG_MODULE, L"");
+ SetDlgItemText(hwnd, IDC_CFG_VENDOR, L"");
+ SetDlgItemText(hwnd, IDC_CFG_VERSION, L"");
+ EnableWindow(GetDlgItem(hwnd, IDC_CFG_ENABLE), FALSE);
+ EnableWindow(GetDlgItem(hwnd, IDC_CFG_DISABLE), FALSE);
+ EnableWindow(GetDlgItem(hwnd, IDC_CFG_UNREGISTER), FALSE);
+ SendDlgItemMessage(hwnd, IDC_CFG_DEPS,
+ LB_RESETCONTENT, 0, 0);
+ SendDlgItemMessage(hwnd, IDC_CFG_ICON, STM_SETICON,
+ (WPARAM) d->plugin_ico, 0);
+ d->selected = NULL;
+ } else {
+ int idx;
+ plugin_data * info;
+
+ idx = ListView_GetNextItem(hw, -1, LVNI_SELECTED);
+#ifdef DEBUG
+ assert(idx != -1);
+#endif
+ ZeroMemory(&lvi, sizeof(lvi));
+ lvi.iItem = idx;
+ lvi.iSubItem = 0;
+ lvi.mask = LVIF_PARAM;
+
+ ListView_GetItem(hw, &lvi);
+#ifdef DEBUG
+ assert(lvi.lParam != 0);
+#endif
+ info = (plugin_data *) lvi.lParam;
+
+ update_dialog_fields(hwnd, d, info);
+ }
+ }
+ }
+ return TRUE;
+
+ case WM_COMMAND:
+ {
+
+ d = (plugin_dlg_data *) (LONG_PTR)
+ GetWindowLongPtr(hwnd, DWLP_USER);
+
+ switch (wParam) {
+ case MAKEWPARAM(IDC_CFG_ENABLE, BN_CLICKED):
+ if (d->selected != NULL) {
+ khui_alert * alert = NULL;
+ wchar_t buf[KHUI_MAXCCH_MESSAGE];
+ wchar_t fmt[KHUI_MAXCCH_MESSAGE];
+ kmm_plugin p;
+
+ khui_alert_create_empty(&alert);
+
+ LoadString(khm_hInstance, IDS_CFG_P_ENBCNFT,
+ fmt, ARRAYLENGTH(fmt));
+ StringCbPrintf(buf, sizeof(buf), fmt, d->selected->plugin.reg.name);
+ khui_alert_set_title(alert, buf);
+
+ LoadString(khm_hInstance, IDS_CFG_P_ENBCNFM,
+ fmt, ARRAYLENGTH(fmt));
+ StringCbPrintf(buf, sizeof(buf), fmt, d->selected->plugin.reg.name);
+ khui_alert_set_message(alert, buf);
+
+ khui_alert_set_severity(alert, KHERR_INFO);
+
+ khui_alert_show_modal(alert);
+
+ kmm_enable_plugin(d->selected->plugin.h_plugin, TRUE);
+
+ khui_alert_release(alert);
+
+ p = d->selected->plugin.h_plugin;
+ kmm_hold_plugin(p);
+ kmm_release_plugin_info_i(&d->selected->plugin);
+ kmm_get_plugin_info_i(p, &d->selected->plugin);
+ kmm_release_plugin(p);
+
+ update_dialog_fields(hwnd, d, d->selected);
+ }
+ break;
+
+ case MAKEWPARAM(IDC_CFG_DISABLE, BN_CLICKED):
+ if (d->selected != NULL) {
+ khui_alert * alert = NULL;
+ wchar_t buf[KHUI_MAXCCH_MESSAGE];
+ wchar_t fmt[KHUI_MAXCCH_MESSAGE];
+ wchar_t depends[KHUI_MAXCCH_MESSAGE];
+ khm_size i;
+ kmm_plugin p;
+
+ khui_alert_create_empty(&alert);
+#ifdef DEBUG
+ assert(alert);
+#endif
+ if (alert == NULL)
+ break;
+
+ LoadString(khm_hInstance, IDS_CFG_P_DELCNFT,
+ fmt, ARRAYLENGTH(fmt));
+ StringCbPrintf(buf, sizeof(buf), fmt, d->selected->plugin.reg.name);
+ khui_alert_set_title(alert, buf);
+
+ LoadString(khm_hInstance, IDS_CFG_P_DELCNFM,
+ fmt, ARRAYLENGTH(fmt));
+ StringCbPrintf(buf, sizeof(buf), fmt, d->selected->plugin.reg.name);
+ khui_alert_set_message(alert, buf);
+
+ depends[0] = L'\0';
+
+ for (i=0; i<d->n_info; i++) {
+ wchar_t * t;
+
+ t = d->info[i]->plugin.reg.dependencies;
+
+ while(t) {
+ if (!wcscmp(t, d->selected->plugin.reg.name)) {
+ if (depends[0])
+ StringCbCat(depends, sizeof(depends), L", ");
+ StringCbCat(depends, sizeof(depends),
+ d->info[i]->plugin.reg.name);
+ break;
+ }
+ t = multi_string_next(t);
+ }
+ }
+
+ if (depends[0]) {
+ LoadString(khm_hInstance, IDS_CFG_P_DELCNFS,
+ fmt, ARRAYLENGTH(fmt));
+ StringCbPrintf(buf, sizeof(buf), fmt, depends);
+ khui_alert_set_suggestion(alert, buf);
+ } else {
+ LoadString(khm_hInstance, IDS_CFG_P_DELNDEP,
+ buf, ARRAYLENGTH(buf));
+ khui_alert_set_suggestion(alert, buf);
+ }
+
+ khui_alert_add_command(alert, KHUI_PACTION_YES);
+ khui_alert_add_command(alert, KHUI_PACTION_NO);
+
+ khui_alert_set_severity(alert, KHERR_WARNING);
+
+ if (KHM_SUCCEEDED(khui_alert_show_modal(alert)) &&
+ alert->response == KHUI_PACTION_YES) {
+ kmm_enable_plugin(d->selected->plugin.h_plugin, FALSE);
+ }
+
+ khui_alert_release(alert);
+
+ p = d->selected->plugin.h_plugin;
+ kmm_hold_plugin(p);
+ kmm_release_plugin_info_i(&d->selected->plugin);
+ kmm_get_plugin_info_i(p, &d->selected->plugin);
+ kmm_release_plugin(p);
+
+ update_dialog_fields(hwnd, d, d->selected);
+ }
+ break;
+
+ case MAKEWPARAM(IDC_CFG_UNREGISTER, BN_CLICKED):
+ {
+ khui_alert * alert = NULL;
+ wchar_t buf[KHUI_MAXCCH_MESSAGE];
+ wchar_t fmt[KHUI_MAXCCH_MESSAGE];
+ wchar_t plist[KHUI_MAXCCH_MESSAGE];
+ khm_size i;
+
+ if (d->selected == NULL) {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ break;
+ }
+
+ khui_alert_create_empty(&alert);
+
+ LoadString(khm_hInstance, IDS_CFG_P_UNRCNFT,
+ fmt, ARRAYLENGTH(fmt));
+ StringCbPrintf(buf, sizeof(buf), fmt,
+ d->selected->plugin.reg.name);
+
+ khui_alert_set_title(alert, buf);
+
+ LoadString(khm_hInstance, IDS_CFG_P_UNRCNFM,
+ fmt, ARRAYLENGTH(fmt));
+ StringCbPrintf(buf, sizeof(buf), fmt,
+ d->selected->plugin.reg.name);
+
+ khui_alert_set_message(alert, buf);
+
+ plist[0] = L'\0';
+ for (i=0; i < d->n_info; i++) {
+ if (!wcscmp(d->info[i]->module.reg.name,
+ d->selected->module.reg.name)) {
+ if (plist[0])
+ StringCbCat(plist, sizeof(plist), L", ");
+ StringCbCat(plist, sizeof(plist),
+ d->info[i]->plugin.reg.name);
+ }
+ }
+
+#ifdef DEBUG
+ /* there should have been at least one plugin */
+ assert(plist[0]);
+#endif
+
+ LoadString(khm_hInstance, IDS_CFG_P_UNRCNFS,
+ fmt, ARRAYLENGTH(fmt));
+ StringCbPrintf(buf, sizeof(buf), fmt, plist);
+ khui_alert_set_suggestion(alert, buf);
+
+ khui_alert_add_command(alert, KHUI_PACTION_YES);
+ khui_alert_add_command(alert, KHUI_PACTION_NO);
+
+ khui_alert_set_severity(alert, KHERR_WARNING);
+
+ if (KHM_SUCCEEDED(khui_alert_show_modal(alert)) &&
+ alert->response == KHUI_PACTION_YES) {
+ kmm_unregister_module(d->selected->module.reg.name, 0);
+
+ update_dialog_fields(hwnd, d, d->selected);
+ }
+ }
+ break;
+
+ case MAKEWPARAM(IDC_CFG_REGISTER, BN_CLICKED):
+ {
+
+ }
+ break;
+ }
+ }
+ return TRUE;
+
+ case WM_DESTROY:
+ {
+ khm_size i;
+
+ d = (plugin_dlg_data *) (LONG_PTR)
+ GetWindowLongPtr(hwnd, DWLP_USER);
+#ifdef DEBUG
+ assert(d);
+#endif
+ for (i=0; i<d->n_info; i++) {
+#ifdef DEBUG
+ assert(d->info[i]);
+#endif
+ kmm_release_plugin_info_i(&d->info[i]->plugin);
+ kmm_release_module_info_i(&d->info[i]->module);
+ PFREE(d->info[i]);
+ }
+
+ PFREE(d);
+
+ khm_set_dialog_result(hwnd, 0);
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
diff --git a/src/windows/identity/ui/configwnd.c b/src/windows/identity/ui/configwnd.c
index 03eec9ad5a..49ebfe48ec 100644
--- a/src/windows/identity/ui/configwnd.c
+++ b/src/windows/identity/ui/configwnd.c
@@ -1,1219 +1,1219 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<khmapp.h>
-#include<assert.h>
-
-static HWND cfgui_hwnd = NULL;
-
-typedef struct tag_cfgui_wnd_data {
- khui_config_node current;
- HWND hw_current;
- HWND hw_generic_pane;
- HBRUSH hbr_white;
- HFONT hf_title;
- khui_bitmap kbmp_logo;
- HIMAGELIST hi_status;
- BOOL modified;
- int idx_default;
- int idx_modified;
- int idx_applied;
-} cfgui_wnd_data;
-
-static cfgui_wnd_data *
-cfgui_get_wnd_data(HWND hwnd) {
- return (cfgui_wnd_data *)(LONG_PTR)
- GetWindowLongPtr(hwnd, DWLP_USER);
-}
-
-static void
-cfgui_set_wnd_data(HWND hwnd, cfgui_wnd_data * d) {
-#pragma warning(push)
-#pragma warning(disable: 4244)
- SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) d);
-#pragma warning(pop)
-}
-
-static void
-cfgui_add_node(cfgui_wnd_data * d,
- HWND hwtv,
- khui_config_node node,
- khui_config_node parent,
- BOOL sorted) {
-
- khui_config_node_reg reg;
- khui_config_node c;
- wchar_t wbuf[256];
- const wchar_t * short_desc;
- TVINSERTSTRUCT s;
- HTREEITEM hItem;
-
- if (node) {
- khui_cfg_get_reg(node, &reg);
- short_desc = reg.short_desc;
- } else {
- short_desc = wbuf;
- LoadString(khm_hInstance, IDS_CFG_ROOT_NAME,
- wbuf, ARRAYLENGTH(wbuf));
- reg.flags = 0;
- }
-
- ZeroMemory(&s, sizeof(s));
-
- s.hParent = (node)?
- (HTREEITEM) khui_cfg_get_param(parent):
- TVI_ROOT;
-
- s.hInsertAfter = (sorted)? TVI_SORT: TVI_FIRST;
-
- s.itemex.mask =
- TVIF_CHILDREN |
- TVIF_PARAM |
- TVIF_TEXT |
- TVIF_STATE;
-
- {
- khui_config_node n;
-
- if (KHM_SUCCEEDED(khui_cfg_get_first_child(node,
- &n))) {
- s.itemex.cChildren = 1;
- s.itemex.state = TVIS_EXPANDED;
- s.itemex.stateMask = TVIS_EXPANDED;
- khui_cfg_release(n);
- } else {
- s.itemex.cChildren = 0;
- s.itemex.state = 0;
- s.itemex.stateMask = TVIS_EXPANDED;
- }
-
- s.itemex.state |= INDEXTOSTATEIMAGEMASK(d->idx_default);
- s.itemex.stateMask |= TVIS_STATEIMAGEMASK;
- }
-
- s.itemex.lParam = (LPARAM) node;
- khui_cfg_hold(node);
-
- s.itemex.pszText = (LPWSTR) short_desc;
-
- hItem = TreeView_InsertItem(hwtv, &s);
-
- khui_cfg_set_param(node, (LPARAM) hItem);
-
- if (KHM_SUCCEEDED(khui_cfg_get_first_child(node,
- &c))) {
- do {
- cfgui_add_node(d, hwtv, c, node,
- !!(reg.flags & KHUI_CNFLAG_SORT_CHILDREN));
- } while (KHM_SUCCEEDED(khui_cfg_get_next_release(&c)));
- }
-}
-
-static void
-cfgui_initialize_dialog(HWND hwnd) {
- cfgui_wnd_data * d;
- HWND hwtv;
- HWND hwtitle;
- HFONT hf;
- HDC hdc;
- HICON hicon;
-
- d = cfgui_get_wnd_data(hwnd);
-
- /* create and fill the image list for the treeview */
-
- d->hi_status = ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON),
- ILC_COLOR8 | ILC_MASK,
- 4,4);
-
- hicon = LoadImage(khm_hInstance, MAKEINTRESOURCE(IDI_CFG_DEFAULT),
- IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR);
-
- /* note that we can't use index 0 because that is used to indicate
- that there is no state image for the node */
- do {
- d->idx_default = ImageList_AddIcon(d->hi_status, hicon);
- } while(d->idx_default == 0);
-
- DestroyIcon(hicon);
-
- hicon = LoadImage(khm_hInstance, MAKEINTRESOURCE(IDI_CFG_MODIFIED),
- IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR);
-
- d->idx_modified = ImageList_AddIcon(d->hi_status, hicon);
-
- DestroyIcon(hicon);
-
- hicon = LoadImage(khm_hInstance, MAKEINTRESOURCE(IDI_CFG_APPLIED),
- IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR);
-
- d->idx_applied = ImageList_AddIcon(d->hi_status, hicon);
-
- DestroyIcon(hicon);
-
- /* now for the treeview */
- hwtv = GetDlgItem(hwnd, IDC_CFG_NODELIST);
-
- TreeView_SetImageList(hwtv, d->hi_status, TVSIL_STATE);
-
- cfgui_add_node(d, hwtv, NULL, NULL, FALSE);
-
- hdc = GetDC(hwnd);
- hf = CreateFont(-MulDiv(12,
- GetDeviceCaps(hdc, LOGPIXELSY),
- 72),
- 0, /* nWidth */
- 0, /* nEscapement */
- 0, /* nOrientation */
- FW_BOLD, /* fnWeight */
- TRUE, /* fdwItalic */
- FALSE, /* fdwUnderline */
- FALSE, /* fdwStrikeOut */
- DEFAULT_CHARSET, /* fdwCharSet */
- OUT_DEFAULT_PRECIS, /* fdwOutputPrecision */
- CLIP_DEFAULT_PRECIS, /* fdwClipPrecision */
- DEFAULT_QUALITY, /* fdwQuality */
- FF_SWISS | DEFAULT_PITCH, /* pitch&family */
- NULL); /* face */
- ReleaseDC(hwnd, hdc);
-
- d->hf_title = hf;
-
- hwtitle = GetDlgItem(hwnd, IDC_CFG_TITLE);
-
- SendMessage(hwtitle,
- WM_SETFONT,
- (WPARAM) hf,
- (LPARAM) FALSE);
-}
-
-static void
-cfgui_free_node(HWND hwtv, HTREEITEM hItem) {
- TVITEMEX iex;
- HTREEITEM hChItem;
-
- ZeroMemory(&iex, sizeof(iex));
-
- iex.mask = TVIF_PARAM;
- iex.hItem = hItem;
-
- if (TreeView_GetItem(hwtv, &iex)) {
- khui_config_node node;
-
- node = (khui_config_node) iex.lParam;
- khui_cfg_release(node);
- }
-
- hChItem = TreeView_GetChild(hwtv, hItem);
- while(hChItem) {
- cfgui_free_node(hwtv, hChItem);
-
- hChItem = TreeView_GetNextSibling(hwtv, hChItem);
- }
-}
-
-static void
-cfgui_uninitialize_dialog(HWND hwnd) {
- cfgui_wnd_data * d;
- HWND hwtv;
-
- d = cfgui_get_wnd_data(hwnd);
-
- hwtv = GetDlgItem(hwnd, IDC_CFG_NODELIST);
-
- cfgui_free_node(hwtv, TreeView_GetRoot(hwtv));
-
- if (d->hf_title)
- DeleteObject(d->hf_title);
-
- if (d->hi_status)
- ImageList_Destroy(d->hi_status);
-}
-
-static HWND
-cfgui_create_config_node_window(HWND hwnd, khui_config_node node) {
- khui_config_node_reg reg;
- khm_int32 rv;
- HWND hw_new;
-
- khui_config_node parent;
-
- if (KHM_SUCCEEDED(khui_cfg_get_parent(node, &parent))) {
- HWND hwp;
-
- hwp = khui_cfg_get_hwnd(parent);
-
- if (hwp == NULL)
- cfgui_create_config_node_window(hwnd, parent);
-
- khui_cfg_release(parent);
- }
-
- rv = khui_cfg_get_reg(node, &reg);
-#ifdef DEBUG
- assert(KHM_SUCCEEDED(rv));
-#endif
- hw_new = CreateDialogParam(reg.h_module,
- reg.dlg_template,
- hwnd,
- reg.dlg_proc,
- (LPARAM) node);
-#ifdef DEBUG
- assert(hw_new);
-#endif
- khui_cfg_set_hwnd(node, hw_new);
-
- return hw_new;
-}
-
-static void
-cfgui_activate_node(HWND hwnd, khui_config_node node) {
-
- cfgui_wnd_data * d;
- HTREEITEM hItem;
- HWND hw_new;
- HWND hwtv;
-
- d = cfgui_get_wnd_data(hwnd);
- hwtv = GetDlgItem(hwnd, IDC_CFG_NODELIST);
- hItem = (HTREEITEM) khui_cfg_get_param(node);
-
-#ifdef DEBUG
- assert(hItem);
- assert(hwtv);
-#endif
-
- if (node == NULL) {
- hw_new = d->hw_generic_pane;
- } else {
-
- hw_new = khui_cfg_get_hwnd(node);
-
- if (hw_new == NULL) {
- hw_new = cfgui_create_config_node_window(hwnd, node);
- }
- }
-
- if (hw_new == d->hw_current)
- return; /* nothing to do */
-
- {
- RECT r_title;
- RECT r_pane;
- HWND hw;
-
- if (d->hw_current)
- ShowWindow(d->hw_current, SW_HIDE);
-
- hw = GetDlgItem(hwnd, IDC_CFG_TITLE);
-#ifdef DEBUG
- assert(hw);
-#endif
- GetWindowRect(hw, &r_title);
-
- hw = GetDlgItem(hwnd, IDC_CFG_PANE);
-#ifdef DEBUG
- assert(hw);
-#endif
- GetWindowRect(hw, &r_pane);
-
- OffsetRect(&r_pane, -r_title.left, -r_title.top);
-
- SetWindowPos(hw_new,
- hwtv,
- r_pane.left, r_pane.top,
- r_pane.right - r_pane.left,
- r_pane.bottom - r_pane.top,
- SWP_NOOWNERZORDER |
- SWP_SHOWWINDOW |
- SWP_NOACTIVATE);
- }
-
- if (node == NULL) {
- wchar_t wbuf[256];
-
- LoadString(khm_hInstance, IDS_CFG_ROOT_TITLE,
- wbuf, ARRAYLENGTH(wbuf));
-
- SetDlgItemText(hwnd, IDC_CFG_TITLE, wbuf);
- } else {
- khm_int32 rv;
- khui_config_node_reg reg;
-
- rv = khui_cfg_get_reg(node, &reg);
-#ifdef DEBUG
- assert(KHM_SUCCEEDED(rv));
-#endif
- SetDlgItemText(hwnd, IDC_CFG_TITLE, reg.long_desc);
- }
-
- d->hw_current = hw_new;
- d->current = node;
-
- TreeView_SelectItem(hwtv, hItem);
-}
-
-static BOOL
-cfgui_check_mod_state(khui_config_node node) {
- khm_int32 flags;
- khui_config_node c = NULL;
- BOOL rv = FALSE;
-
- flags = khui_cfg_get_flags(node);
-
- if (flags & KHUI_CNFLAG_MODIFIED)
- return TRUE;
-
- if (KHM_FAILED(khui_cfg_get_first_child(node, &c)))
- return FALSE;
-
- while(c) {
- rv = (rv || cfgui_check_mod_state(c));
- khui_cfg_get_next_release(&c);
- }
-
- return rv;
-}
-
-static void
-cfgui_apply_settings(khui_config_node node) {
- HWND hwnd;
- khui_config_node c;
- khm_int32 flags;
-
- hwnd = khui_cfg_get_hwnd(node);
- flags = khui_cfg_get_flags(node);
-
- if (hwnd && (flags & KHUI_CNFLAG_MODIFIED)) {
- SendMessage(hwnd, KHUI_WM_CFG_NOTIFY,
- MAKEWPARAM(0, WMCFG_APPLY),
- (LPARAM) node);
- }
-
- if (KHM_FAILED(khui_cfg_get_first_child(node, &c)))
- return;
-
- while (c) {
- cfgui_apply_settings(c);
- khui_cfg_get_next_release(&c);
- }
-}
-
-static void
-cfgui_remove_item(HWND hwtv,
- HTREEITEM hItem) {
- khui_config_node node;
- HTREEITEM hChild;
- TVITEMEX itemex;
-
- for (hChild = TreeView_GetChild(hwtv, hItem);
- hChild;
- hChild = TreeView_GetChild(hwtv, hItem)) {
-
- cfgui_remove_item(hwtv, hChild);
-
- }
-
- ZeroMemory(&itemex, sizeof(itemex));
-
- itemex.mask = TVIF_PARAM;
- itemex.hItem = hItem;
-
- TreeView_GetChild(hwtv, &itemex);
-
- node = (khui_config_node) itemex.lParam;
-
- if (node) {
- HWND hw;
- hw = khui_cfg_get_hwnd(node);
-
- if (hw)
- DestroyWindow(hw);
-
- khui_cfg_release(node);
- }
-
- TreeView_DeleteItem(hwtv, hItem);
-}
-
-struct cfgui_child_info {
- HTREEITEM hItem;
- khui_config_node node;
- BOOL checked;
-};
-
-#define CI_ALLOC_INCR 8
-
-static void
-cfgui_sync_node(cfgui_wnd_data * d,
- HWND hwtv,
- khui_config_node c,
- HTREEITEM hItem) {
- khui_config_node child;
- HTREEITEM hChild;
- struct cfgui_child_info * childinfo = NULL;
- khm_size n_childinfo = 0;
- khm_size nc_childinfo = 0;
- khm_size i;
-
- /* first, get the list of children from the treeview control */
- for (hChild = TreeView_GetChild(hwtv, hItem);
- hChild;
- hChild = TreeView_GetNextSibling(hwtv, hChild)) {
-
- if (n_childinfo >= nc_childinfo) {
- nc_childinfo = UBOUNDSS(n_childinfo + 1,
- CI_ALLOC_INCR, CI_ALLOC_INCR);
-#ifdef DEBUG
- assert(nc_childinfo > n_childinfo);
-#endif
- childinfo = PREALLOC(childinfo,
- sizeof(*childinfo) * nc_childinfo);
-#ifdef DEBUG
- assert(childinfo);
-#endif
- }
-
- ZeroMemory(&childinfo[n_childinfo],
- sizeof(childinfo[n_childinfo]));
-
- childinfo[n_childinfo].hItem = hChild;
- childinfo[n_childinfo].checked = FALSE;
- n_childinfo++;
- }
-
- /* now, go through the list of actual nodes and make sure they
- match up */
- child = NULL;
- for (khui_cfg_get_first_child(c, &child);
- child;
- khui_cfg_get_next_release(&child)) {
-
- hChild = (HTREEITEM) khui_cfg_get_param(child);
-
- for (i=0; i < n_childinfo; i++) {
- if (childinfo[i].hItem == hChild)
- break;
- }
-
- if (i < n_childinfo) {
- childinfo[i].checked = TRUE;
- } else {
- /* add it to the list, so we can create the node in the
- tree view control later. */
- if (n_childinfo >= nc_childinfo) {
- nc_childinfo = UBOUNDSS(n_childinfo + 1,
- CI_ALLOC_INCR, CI_ALLOC_INCR);
-#ifdef DEBUG
- assert(nc_childinfo > n_childinfo);
-#endif
- childinfo = PREALLOC(childinfo,
- sizeof(*childinfo) * nc_childinfo);
-#ifdef DEBUG
- assert(childinfo);
-#endif
- }
-
- ZeroMemory(&childinfo[n_childinfo],
- sizeof(childinfo[n_childinfo]));
-
- childinfo[n_childinfo].node = child;
- khui_cfg_hold(child);
- n_childinfo++;
- }
- }
-
- /* by this point, the childinfo list contains items of the
- following forms:
-
- 1. childinfo[i].hItem != NULL && childinfo[i].checked == TRUE
-
- Corresponds to a tree view item that has a matching
- configuration node. Nothing to do here.
-
- 2. childinfo[i].hItem != NULL && childinfo[i].checked == FALSE
-
- Corresponds to a tree view item that has no matching
- configuration node. These should be removed.
-
- 3. childinfo[i].hItem == NULL && childinfo[i].node != NULL
-
- Corresponds to a configuration node that has no matching
- tree view item. These nodes should be added.
- */
-
- /* first do the removals */
- for (i=0; i < n_childinfo; i++) {
- if (childinfo[i].hItem == NULL)
- break; /* nothing more to see from this point
- on */
- if (!childinfo[i].checked) {
- /* remove! */
- cfgui_remove_item(hwtv, childinfo[i].hItem);
- }
- }
-
- /* continue from where the previous loop left off */
- for (; i < n_childinfo; i++) {
-#ifdef DEBUG
- assert(childinfo[i].hItem == NULL);
- assert(childinfo[i].node != NULL);
-#endif
-
- cfgui_add_node(d, hwtv, childinfo[i].node, c, FALSE);
-
- khui_cfg_release(childinfo[i].node);
- childinfo[i].node = NULL;
- }
-
- if (childinfo)
- PFREE(childinfo);
-
- /* finally recurse through to the next level */
- for (hChild = TreeView_GetChild(hwtv, hItem);
- hChild;
- hChild = TreeView_GetNextSibling(hwtv, hChild)) {
-
- TVITEMEX itemex;
-
- ZeroMemory(&itemex, sizeof(itemex));
-
- itemex.mask = TVIF_PARAM;
- itemex.hItem = hChild;
-
- TreeView_GetItem(hwtv, &itemex);
-
- if (itemex.lParam) {
- child = (khui_config_node) itemex.lParam;
-
- cfgui_sync_node(d, hwtv, child, hChild);
- }
- }
-}
-
-static void
-cfgui_sync_node_list(cfgui_wnd_data * d, HWND hwnd) {
- HWND hwtv;
- HTREEITEM hItem;
-
- hwtv = GetDlgItem(hwnd, IDC_CFG_NODELIST);
- hItem = TreeView_GetRoot(hwtv);
-
- cfgui_sync_node(d, hwtv, NULL, hItem);
-}
-
-static void
-cfgui_update_state(HWND hwnd,
- khm_int32 flags,
- khui_config_node node) {
- cfgui_wnd_data * d;
- HWND hwtv;
- HTREEITEM hItem;
- TVITEMEX itx;
- int idx;
-
- d = cfgui_get_wnd_data(hwnd);
- hwtv = GetDlgItem(hwnd, IDC_CFG_NODELIST);
- hItem = (HTREEITEM) khui_cfg_get_param(node);
-
- ZeroMemory(&itx, sizeof(itx));
-
- if (flags & KHUI_CNFLAG_MODIFIED)
- idx = d->idx_modified;
- else if (flags & KHUI_CNFLAG_APPLIED)
- idx = d->idx_applied;
- else
- idx = d->idx_default;
-
- itx.hItem = hItem;
- itx.mask = TVIF_STATE;
- itx.state = INDEXTOSTATEIMAGEMASK(idx);
- itx.stateMask = TVIS_STATEIMAGEMASK;
-
- TreeView_SetItem(hwtv, &itx);
-
- if(cfgui_check_mod_state(NULL)) {
- EnableWindow(GetDlgItem(hwnd, IDAPPLY), TRUE);
- } else {
- EnableWindow(GetDlgItem(hwnd, IDAPPLY), FALSE);
- }
-}
-
-
-/* dialog procedure for the generic dialog */
-static INT_PTR CALLBACK
-cfgui_dlgproc_generic(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam) {
- cfgui_wnd_data * d;
-
- switch(uMsg) {
- case WM_INITDIALOG:
- d = (cfgui_wnd_data *) lParam;
- cfgui_set_wnd_data(hwnd, d);
- return TRUE;
-
- case WM_CTLCOLORSTATIC:
- d = cfgui_get_wnd_data(hwnd);
- return (BOOL)(DWORD_PTR) d->hbr_white;
-
- case WM_ERASEBKGND:
- {
- HDC hdc = (HDC) wParam;
- RECT r_client;
- RECT r_logo;
- RECT r_fill;
-
- d = cfgui_get_wnd_data(hwnd);
-
- GetClientRect(hwnd, &r_client);
- SetRectEmpty(&r_logo);
-
- r_logo.right = d->kbmp_logo.cx;
- r_logo.bottom = d->kbmp_logo.cy;
-
- OffsetRect(&r_logo,
- r_client.right - r_logo.right,
- r_client.bottom - r_logo.bottom);
-
- khui_draw_bitmap(hdc,
- r_logo.left,
- r_logo.top,
- &d->kbmp_logo);
-
- r_fill.left = 0;
- r_fill.top = 0;
- r_fill.right = r_logo.left;
- r_fill.bottom = r_client.bottom;
- FillRect(hdc, &r_fill, d->hbr_white);
-
- r_fill.left = r_logo.left;
- r_fill.right = r_client.right;
- r_fill.bottom = r_logo.top;
- FillRect(hdc, &r_fill, d->hbr_white);
-
- SetWindowLongPtr(hwnd, DWLP_MSGRESULT, (LONG) TRUE);
- }
- return TRUE;
- }
-
- return FALSE;
-}
-
-static INT_PTR CALLBACK
-cfgui_dlgproc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam) {
-
- khui_config_node node;
- cfgui_wnd_data * d;
-
- switch(uMsg) {
- case WM_INITDIALOG:
- node = (khui_config_node) lParam;
-
- khui_cfg_clear_params();
-
- khui_cfg_set_configui_handle(hwnd);
-
- d = PMALLOC(sizeof(*d));
- ZeroMemory(d, sizeof(*d));
-
- d->hbr_white = CreateSolidBrush(RGB(255,255,255));
-
- d->hw_generic_pane =
- CreateDialogParam(khm_hInstance,
- MAKEINTRESOURCE(IDD_CFG_GENERIC),
- hwnd,
- cfgui_dlgproc_generic,
- (LPARAM) d);
-
- khui_bitmap_from_hbmp(&d->kbmp_logo,
- LoadImage(
- khm_hInstance,
- MAKEINTRESOURCE(IDB_LOGO_OPAQUE),
- IMAGE_BITMAP,
- 0,
- 0,
- LR_DEFAULTCOLOR));
-
- cfgui_set_wnd_data(hwnd, d);
-
- cfgui_initialize_dialog(hwnd);
-
- cfgui_activate_node(hwnd, node);
-
- khm_add_dialog(hwnd);
- khm_enter_modal(hwnd);
-
- return TRUE;
-
- case WM_DESTROY:
- cfgui_hwnd = NULL;
-
- khui_cfg_set_configui_handle(NULL);
-
- cfgui_uninitialize_dialog(hwnd);
-
- d = cfgui_get_wnd_data(hwnd);
- khui_delete_bitmap(&d->kbmp_logo);
- DeleteObject(d->hbr_white);
-
- cfgui_set_wnd_data(hwnd, NULL);
-
- khm_del_dialog(hwnd);
-
- SetForegroundWindow(khm_hwnd_main);
-
- PFREE(d);
-
- return FALSE;
-
- case WM_NOTIFY:
- {
- LPNMHDR lpnm;
- LPNMTREEVIEW lptv;
- LPNMTVGETINFOTIP lpgi;
- khui_config_node node;
-
- lpnm = (LPNMHDR) lParam;
-
- switch (lpnm->code) {
- case TVN_SELCHANGED:
- lptv = (LPNMTREEVIEW) lParam;
- cfgui_activate_node(hwnd,
- (khui_config_node)
- lptv->itemNew.lParam);
- return TRUE;
-
- case TVN_GETINFOTIP:
- lpgi = (LPNMTVGETINFOTIP) lParam;
- node = (khui_config_node) lpgi->lParam;
-
- if (node) {
- khm_int32 flags = 0;
-
- flags = khui_cfg_get_flags(node);
-
- if (flags & KHUI_CNFLAG_MODIFIED) {
- LoadString(khm_hInstance, IDS_CFG_IT_MOD,
- lpgi->pszText, lpgi->cchTextMax);
- } else if (flags & KHUI_CNFLAG_APPLIED) {
- LoadString(khm_hInstance, IDS_CFG_IT_APP,
- lpgi->pszText, lpgi->cchTextMax);
- } else {
- LoadString(khm_hInstance, IDS_CFG_IT_NONE,
- lpgi->pszText, lpgi->cchTextMax);
- }
- } else {
- StringCchCopy(lpgi->pszText, lpgi->cchTextMax, L"");
- }
-
- return TRUE;
- }
- }
- return TRUE;
-
- case WM_CTLCOLORSTATIC:
- {
- d = cfgui_get_wnd_data(hwnd);
- return (BOOL)(DWORD_PTR) d->hbr_white;
- }
- /* implicit break */
-
- case WM_COMMAND:
- switch(wParam) {
- case MAKEWPARAM(IDCANCEL, BN_CLICKED):
- khm_leave_modal();
- DestroyWindow(hwnd);
- break;
-
- case MAKEWPARAM(IDAPPLY, BN_CLICKED):
- cfgui_apply_settings(NULL);
- break;
-
- case MAKEWPARAM(IDOK, BN_CLICKED):
- cfgui_apply_settings(NULL);
- khm_leave_modal();
- DestroyWindow(hwnd);
- break;
- }
- return TRUE;
-
- case KHUI_WM_CFG_NOTIFY:
- switch(HIWORD(wParam)) {
- case WMCFG_SHOW_NODE:
- cfgui_activate_node(hwnd, (khui_config_node) lParam);
- break;
-
- case WMCFG_UPDATE_STATE:
- cfgui_update_state(hwnd, LOWORD(wParam),
- (khui_config_node) lParam);
- break;
-
- case WMCFG_SYNC_NODE_LIST:
- d = cfgui_get_wnd_data(hwnd);
- cfgui_sync_node_list(d, hwnd);
- break;
- }
-
- return TRUE;
- }
-
- return FALSE;
-}
-
-static void
-cfgui_create_window(khui_config_node node) {
-#ifdef DEBUG
- assert(cfgui_hwnd == NULL);
-#endif
-
- khm_refresh_config();
-
- cfgui_hwnd = CreateDialogParam(khm_hInstance,
- MAKEINTRESOURCE(IDD_CFG_MAIN),
- khm_hwnd_main,
- cfgui_dlgproc,
- (LPARAM) node);
-#ifdef DEBUG
- assert(cfgui_hwnd != NULL);
-#endif
- ShowWindow(cfgui_hwnd,SW_SHOW);
-}
-
-static void
-cfgui_destroy_window(void) {
- if (cfgui_hwnd)
- DestroyWindow(cfgui_hwnd);
- /* cfgui_hwnd will be set to NULL in the dialog proc */
-}
-
-void
-khm_show_config_pane(khui_config_node node) {
- if (cfgui_hwnd != NULL) {
- SendMessage(cfgui_hwnd, KHUI_WM_CFG_NOTIFY,
- MAKEWPARAM(0, WMCFG_SHOW_NODE),
- (LPARAM) node);
- } else {
- cfgui_create_window(node);
- }
-}
-
-void khm_refresh_config(void) {
- khm_size cb;
- khm_size n_idents;
- wchar_t * idents = NULL;
- wchar_t * t;
- khm_int32 rv;
- int n_tries = 0;
- khui_config_node cfg_ids = NULL;
- khui_config_node cfg_r = NULL;
- khui_config_node cfg_iter = NULL;
- khui_menu_def * omenu;
- khm_boolean refresh_menu = FALSE;
-
- do {
- rv = kcdb_identity_enum(KCDB_IDENT_FLAG_CONFIG,
- KCDB_IDENT_FLAG_CONFIG,
- NULL,
- &cb,
- &n_idents);
-
- if (rv != KHM_ERROR_TOO_LONG ||
- n_idents == 0)
- return;
-
- if (idents)
- PFREE(idents);
- idents = PMALLOC(cb);
-#ifdef DEBUG
- assert(idents);
-#endif
-
- rv = kcdb_identity_enum(KCDB_IDENT_FLAG_CONFIG,
- KCDB_IDENT_FLAG_CONFIG,
- idents,
- &cb,
- &n_idents);
-
- n_tries++;
- } while(KHM_FAILED(rv) &&
- n_tries < 5);
-
- if (KHM_FAILED(rv))
- goto _cleanup;
-
- if (KHM_FAILED(khui_cfg_open(NULL,
- L"KhmIdentities",
- &cfg_ids)))
- goto _cleanup;
-
- for(t = idents; t && *t; t = multi_string_next(t)) {
- khui_config_node cfg_id = NULL;
-
- rv = khui_cfg_open(cfg_ids,
- t,
- &cfg_id);
-
- if (KHM_FAILED(rv)) {
- khui_config_node_reg reg;
- wchar_t wshort[KHUI_MAXCCH_SHORT_DESC];
- wchar_t wlong[KHUI_MAXCCH_LONG_DESC];
- wchar_t wfmt[KHUI_MAXCCH_SHORT_DESC];
-
- ZeroMemory(&reg, sizeof(reg));
-
- reg.name = t;
- reg.short_desc = wshort;
- reg.long_desc = wlong;
- reg.h_module = khm_hInstance;
- reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_IDENTITY);
- reg.dlg_proc = khm_cfg_identity_proc;
- reg.flags = 0;
-
- LoadString(khm_hInstance, IDS_CFG_IDENTITY_SHORT,
- wfmt, ARRAYLENGTH(wfmt));
- StringCbPrintf(wshort, sizeof(wshort), wfmt, t);
-
- LoadString(khm_hInstance, IDS_CFG_IDENTITY_LONG,
- wfmt, ARRAYLENGTH(wfmt));
- StringCbPrintf(wlong, sizeof(wlong), wfmt, t);
-
- khui_cfg_register(cfg_ids,
- &reg);
- } else {
- khui_cfg_release(cfg_id);
- }
- }
-
- for (khui_cfg_get_first_child(cfg_ids, &cfg_iter);
- cfg_iter;
- khui_cfg_get_next_release(&cfg_iter)) {
-
- wchar_t cfgname[KCDB_IDENT_MAXCCH_NAME];
- khm_size cb;
- khm_handle tident = NULL;
- khm_int32 tflags = 0;
-
- cb = sizeof(cfgname);
- khui_cfg_get_name(cfg_iter, cfgname, &cb);
-
- if (KHM_FAILED(kcdb_identity_create(cfgname, 0, &tident)) ||
- KHM_FAILED(kcdb_identity_get_flags(tident, &tflags)) ||
- !(tflags & KCDB_IDENT_FLAG_ACTIVE) ||
- !(tflags & KCDB_IDENT_FLAG_CONFIG)) {
-
- /* this configuration node needs to be removed */
-
- khui_cfg_remove(cfg_iter);
- }
-
- if (tident)
- kcdb_identity_release(tident);
- }
-
- /* Now iterate through the root level configuration nodes and make
- sure we have a menu item for each of them. */
- if (KHM_FAILED(khui_cfg_get_first_child(NULL, &cfg_r)))
- goto _cleanup;
-
- omenu = khui_find_menu(KHUI_MENU_OPTIONS);
- if (omenu == NULL)
- goto _cleanup;
-
- khui_action_lock();
-
- do {
- khm_int32 action;
- khm_int32 flags;
- khui_action * paction;
- wchar_t cname[KHUI_MAXCCH_NAME];
- wchar_t wshort[KHUI_MAXCCH_SHORT_DESC];
- khm_size cb;
- khm_handle sub;
- khui_config_node_reg reg;
-
- flags = khui_cfg_get_flags(cfg_r);
- if (flags & KHUI_CNFLAG_SYSTEM)
- goto _next_cfg;
-
- cb = sizeof(cname);
- if (KHM_FAILED(khui_cfg_get_name(cfg_r, cname, &cb))) {
-#ifdef DEBUG
- assert(FALSE);
-#endif
- goto _next_cfg;
- }
-
- paction = khui_find_named_action(cname);
-
- if (!paction) {
- khui_cfg_get_reg(cfg_r, &reg);
-
- kmq_create_hwnd_subscription(khm_hwnd_main, &sub);
-
- StringCbCopy(wshort, sizeof(wshort), reg.short_desc);
- StringCbCat(wshort, sizeof(wshort), L" ...");
-
- action = khui_action_create(cname,
- wshort,
- reg.long_desc,
- (void *) CFGACTION_MAGIC,
- KHUI_ACTIONTYPE_TRIGGER,
- sub);
-
- if (action == 0) {
-#ifdef DEBUG
- assert(FALSE);
-#endif
- goto _next_cfg;
- }
-
- khui_menu_insert_action(omenu, -1, action, 0);
-
- refresh_menu = TRUE;
- }
-
- _next_cfg:
- if (KHM_FAILED(khui_cfg_get_next_release(&cfg_r)))
- break;
- } while(cfg_r);
-
- khui_action_unlock();
-
- if (refresh_menu) {
- khui_refresh_actions();
- }
-
- _cleanup:
- if (cfg_ids)
- khui_cfg_release(cfg_ids);
-
- if (cfg_r)
- khui_cfg_release(cfg_r);
-
- if (idents)
- PFREE(idents);
-}
-
-void khm_init_config(void) {
- wchar_t wshort[KHUI_MAXCCH_SHORT_DESC];
- wchar_t wlong[KHUI_MAXCCH_LONG_DESC];
- khui_config_node_reg reg;
- khui_config_node node;
-
- reg.short_desc = wshort;
- reg.long_desc = wlong;
- reg.h_module = khm_hInstance;
- reg.flags = KHUI_CNFLAG_SYSTEM;
-
- reg.name = L"KhmGeneral";
- reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_GENERAL);
- reg.dlg_proc = khm_cfg_general_proc;
- LoadString(khm_hInstance, IDS_CFG_GENERAL_SHORT,
- wshort, ARRAYLENGTH(wshort));
- LoadString(khm_hInstance, IDS_CFG_GENERAL_LONG,
- wlong, ARRAYLENGTH(wlong));
-
- khui_cfg_register(NULL, &reg);
-
- reg.name = L"KhmAppear";
- reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_APPEAR);
- reg.dlg_proc = khm_cfg_appearance_proc;
- LoadString(khm_hInstance, IDS_CFG_APPEAR_SHORT,
- wshort, ARRAYLENGTH(wshort));
- LoadString(khm_hInstance, IDS_CFG_APPEAR_LONG,
- wlong, ARRAYLENGTH(wlong));
-
- khui_cfg_register(NULL, &reg);
-
- reg.name = L"KhmIdentities";
- reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_IDENTITIES);
- reg.dlg_proc = khm_cfg_identities_proc;
- LoadString(khm_hInstance, IDS_CFG_IDENTITIES_SHORT,
- wshort, ARRAYLENGTH(wshort));
- LoadString(khm_hInstance, IDS_CFG_IDENTITIES_LONG,
- wlong, ARRAYLENGTH(wlong));
-
- khui_cfg_register(NULL, &reg);
-
- node = NULL;
- khui_cfg_open(NULL, L"KhmIdentities", &node);
-#ifdef DEBUG
- assert(node);
-#endif
-
- reg.name = L"KhmIdentitiesTab";
- reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_IDS_TAB);
- reg.dlg_proc = khm_cfg_ids_tab_proc;
- LoadString(khm_hInstance, IDS_CFG_IDS_TAB_SHORT,
- wshort, ARRAYLENGTH(wshort));
- LoadString(khm_hInstance, IDS_CFG_IDS_TAB_LONG,
- wlong, ARRAYLENGTH(wlong));
- reg.flags = KHUI_CNFLAG_SUBPANEL | KHUI_CNFLAG_SYSTEM;
-
- khui_cfg_register(node, &reg);
-
- reg.name = L"KhmIdentitiesTabPlural";
- reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_ID_TAB);
- reg.dlg_proc = khm_cfg_id_tab_proc;
- LoadString(khm_hInstance, IDS_CFG_ID_TAB_SHORT,
- wshort, ARRAYLENGTH(wshort));
- LoadString(khm_hInstance, IDS_CFG_ID_TAB_LONG,
- wlong, ARRAYLENGTH(wlong));
- reg.flags = KHUI_CNFLAG_PLURAL | KHUI_CNFLAG_SUBPANEL | KHUI_CNFLAG_SYSTEM;
-
- khui_cfg_register(node, &reg);
-
- reg.flags = KHUI_CNFLAG_SYSTEM;
- khui_cfg_release(node);
-
- reg.name = L"KhmNotifications";
- reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_NOTIF);
- reg.dlg_proc = khm_cfg_notifications_proc;
- LoadString(khm_hInstance, IDS_CFG_NOTIF_SHORT,
- wshort, ARRAYLENGTH(wshort));
- LoadString(khm_hInstance, IDS_CFG_NOTIF_LONG,
- wlong, ARRAYLENGTH(wlong));
-
- khui_cfg_register(NULL, &reg);
-
- reg.name = L"KhmPlugins";
- reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_PLUGINS);
- reg.dlg_proc = khm_cfg_plugins_proc;
- LoadString(khm_hInstance, IDS_CFG_PLUGINS_SHORT,
- wshort, ARRAYLENGTH(wshort));
- LoadString(khm_hInstance, IDS_CFG_PLUGINS_LONG,
- wlong, ARRAYLENGTH(wlong));
-
- khui_cfg_register(NULL, &reg);
-}
-
-void khm_exit_config(void) {
-}
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<khmapp.h>
+#include<assert.h>
+
+static HWND cfgui_hwnd = NULL;
+
+typedef struct tag_cfgui_wnd_data {
+ khui_config_node current;
+ HWND hw_current;
+ HWND hw_generic_pane;
+ HBRUSH hbr_white;
+ HFONT hf_title;
+ khui_bitmap kbmp_logo;
+ HIMAGELIST hi_status;
+ BOOL modified;
+ int idx_default;
+ int idx_modified;
+ int idx_applied;
+} cfgui_wnd_data;
+
+static cfgui_wnd_data *
+cfgui_get_wnd_data(HWND hwnd) {
+ return (cfgui_wnd_data *)(LONG_PTR)
+ GetWindowLongPtr(hwnd, DWLP_USER);
+}
+
+static void
+cfgui_set_wnd_data(HWND hwnd, cfgui_wnd_data * d) {
+#pragma warning(push)
+#pragma warning(disable: 4244)
+ SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) d);
+#pragma warning(pop)
+}
+
+static void
+cfgui_add_node(cfgui_wnd_data * d,
+ HWND hwtv,
+ khui_config_node node,
+ khui_config_node parent,
+ BOOL sorted) {
+
+ khui_config_node_reg reg;
+ khui_config_node c;
+ wchar_t wbuf[256];
+ const wchar_t * short_desc;
+ TVINSERTSTRUCT s;
+ HTREEITEM hItem;
+
+ if (node) {
+ khui_cfg_get_reg(node, &reg);
+ short_desc = reg.short_desc;
+ } else {
+ short_desc = wbuf;
+ LoadString(khm_hInstance, IDS_CFG_ROOT_NAME,
+ wbuf, ARRAYLENGTH(wbuf));
+ reg.flags = 0;
+ }
+
+ ZeroMemory(&s, sizeof(s));
+
+ s.hParent = (node)?
+ (HTREEITEM) khui_cfg_get_param(parent):
+ TVI_ROOT;
+
+ s.hInsertAfter = (sorted)? TVI_SORT: TVI_FIRST;
+
+ s.itemex.mask =
+ TVIF_CHILDREN |
+ TVIF_PARAM |
+ TVIF_TEXT |
+ TVIF_STATE;
+
+ {
+ khui_config_node n;
+
+ if (KHM_SUCCEEDED(khui_cfg_get_first_child(node,
+ &n))) {
+ s.itemex.cChildren = 1;
+ s.itemex.state = TVIS_EXPANDED;
+ s.itemex.stateMask = TVIS_EXPANDED;
+ khui_cfg_release(n);
+ } else {
+ s.itemex.cChildren = 0;
+ s.itemex.state = 0;
+ s.itemex.stateMask = TVIS_EXPANDED;
+ }
+
+ s.itemex.state |= INDEXTOSTATEIMAGEMASK(d->idx_default);
+ s.itemex.stateMask |= TVIS_STATEIMAGEMASK;
+ }
+
+ s.itemex.lParam = (LPARAM) node;
+ khui_cfg_hold(node);
+
+ s.itemex.pszText = (LPWSTR) short_desc;
+
+ hItem = TreeView_InsertItem(hwtv, &s);
+
+ khui_cfg_set_param(node, (LPARAM) hItem);
+
+ if (KHM_SUCCEEDED(khui_cfg_get_first_child(node,
+ &c))) {
+ do {
+ cfgui_add_node(d, hwtv, c, node,
+ !!(reg.flags & KHUI_CNFLAG_SORT_CHILDREN));
+ } while (KHM_SUCCEEDED(khui_cfg_get_next_release(&c)));
+ }
+}
+
+static void
+cfgui_initialize_dialog(HWND hwnd) {
+ cfgui_wnd_data * d;
+ HWND hwtv;
+ HWND hwtitle;
+ HFONT hf;
+ HDC hdc;
+ HICON hicon;
+
+ d = cfgui_get_wnd_data(hwnd);
+
+ /* create and fill the image list for the treeview */
+
+ d->hi_status = ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON),
+ ILC_COLOR8 | ILC_MASK,
+ 4,4);
+
+ hicon = LoadImage(khm_hInstance, MAKEINTRESOURCE(IDI_CFG_DEFAULT),
+ IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR);
+
+ /* note that we can't use index 0 because that is used to indicate
+ that there is no state image for the node */
+ do {
+ d->idx_default = ImageList_AddIcon(d->hi_status, hicon);
+ } while(d->idx_default == 0);
+
+ DestroyIcon(hicon);
+
+ hicon = LoadImage(khm_hInstance, MAKEINTRESOURCE(IDI_CFG_MODIFIED),
+ IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR);
+
+ d->idx_modified = ImageList_AddIcon(d->hi_status, hicon);
+
+ DestroyIcon(hicon);
+
+ hicon = LoadImage(khm_hInstance, MAKEINTRESOURCE(IDI_CFG_APPLIED),
+ IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR);
+
+ d->idx_applied = ImageList_AddIcon(d->hi_status, hicon);
+
+ DestroyIcon(hicon);
+
+ /* now for the treeview */
+ hwtv = GetDlgItem(hwnd, IDC_CFG_NODELIST);
+
+ TreeView_SetImageList(hwtv, d->hi_status, TVSIL_STATE);
+
+ cfgui_add_node(d, hwtv, NULL, NULL, FALSE);
+
+ hdc = GetDC(hwnd);
+ hf = CreateFont(-MulDiv(12,
+ GetDeviceCaps(hdc, LOGPIXELSY),
+ 72),
+ 0, /* nWidth */
+ 0, /* nEscapement */
+ 0, /* nOrientation */
+ FW_BOLD, /* fnWeight */
+ TRUE, /* fdwItalic */
+ FALSE, /* fdwUnderline */
+ FALSE, /* fdwStrikeOut */
+ DEFAULT_CHARSET, /* fdwCharSet */
+ OUT_DEFAULT_PRECIS, /* fdwOutputPrecision */
+ CLIP_DEFAULT_PRECIS, /* fdwClipPrecision */
+ DEFAULT_QUALITY, /* fdwQuality */
+ FF_SWISS | DEFAULT_PITCH, /* pitch&family */
+ NULL); /* face */
+ ReleaseDC(hwnd, hdc);
+
+ d->hf_title = hf;
+
+ hwtitle = GetDlgItem(hwnd, IDC_CFG_TITLE);
+
+ SendMessage(hwtitle,
+ WM_SETFONT,
+ (WPARAM) hf,
+ (LPARAM) FALSE);
+}
+
+static void
+cfgui_free_node(HWND hwtv, HTREEITEM hItem) {
+ TVITEMEX iex;
+ HTREEITEM hChItem;
+
+ ZeroMemory(&iex, sizeof(iex));
+
+ iex.mask = TVIF_PARAM;
+ iex.hItem = hItem;
+
+ if (TreeView_GetItem(hwtv, &iex)) {
+ khui_config_node node;
+
+ node = (khui_config_node) iex.lParam;
+ khui_cfg_release(node);
+ }
+
+ hChItem = TreeView_GetChild(hwtv, hItem);
+ while(hChItem) {
+ cfgui_free_node(hwtv, hChItem);
+
+ hChItem = TreeView_GetNextSibling(hwtv, hChItem);
+ }
+}
+
+static void
+cfgui_uninitialize_dialog(HWND hwnd) {
+ cfgui_wnd_data * d;
+ HWND hwtv;
+
+ d = cfgui_get_wnd_data(hwnd);
+
+ hwtv = GetDlgItem(hwnd, IDC_CFG_NODELIST);
+
+ cfgui_free_node(hwtv, TreeView_GetRoot(hwtv));
+
+ if (d->hf_title)
+ DeleteObject(d->hf_title);
+
+ if (d->hi_status)
+ ImageList_Destroy(d->hi_status);
+}
+
+static HWND
+cfgui_create_config_node_window(HWND hwnd, khui_config_node node) {
+ khui_config_node_reg reg;
+ khm_int32 rv;
+ HWND hw_new;
+
+ khui_config_node parent;
+
+ if (KHM_SUCCEEDED(khui_cfg_get_parent(node, &parent))) {
+ HWND hwp;
+
+ hwp = khui_cfg_get_hwnd(parent);
+
+ if (hwp == NULL)
+ cfgui_create_config_node_window(hwnd, parent);
+
+ khui_cfg_release(parent);
+ }
+
+ rv = khui_cfg_get_reg(node, &reg);
+#ifdef DEBUG
+ assert(KHM_SUCCEEDED(rv));
+#endif
+ hw_new = CreateDialogParam(reg.h_module,
+ reg.dlg_template,
+ hwnd,
+ reg.dlg_proc,
+ (LPARAM) node);
+#ifdef DEBUG
+ assert(hw_new);
+#endif
+ khui_cfg_set_hwnd(node, hw_new);
+
+ return hw_new;
+}
+
+static void
+cfgui_activate_node(HWND hwnd, khui_config_node node) {
+
+ cfgui_wnd_data * d;
+ HTREEITEM hItem;
+ HWND hw_new;
+ HWND hwtv;
+
+ d = cfgui_get_wnd_data(hwnd);
+ hwtv = GetDlgItem(hwnd, IDC_CFG_NODELIST);
+ hItem = (HTREEITEM) khui_cfg_get_param(node);
+
+#ifdef DEBUG
+ assert(hItem);
+ assert(hwtv);
+#endif
+
+ if (node == NULL) {
+ hw_new = d->hw_generic_pane;
+ } else {
+
+ hw_new = khui_cfg_get_hwnd(node);
+
+ if (hw_new == NULL) {
+ hw_new = cfgui_create_config_node_window(hwnd, node);
+ }
+ }
+
+ if (hw_new == d->hw_current)
+ return; /* nothing to do */
+
+ {
+ RECT r_title;
+ RECT r_pane;
+ HWND hw;
+
+ if (d->hw_current)
+ ShowWindow(d->hw_current, SW_HIDE);
+
+ hw = GetDlgItem(hwnd, IDC_CFG_TITLE);
+#ifdef DEBUG
+ assert(hw);
+#endif
+ GetWindowRect(hw, &r_title);
+
+ hw = GetDlgItem(hwnd, IDC_CFG_PANE);
+#ifdef DEBUG
+ assert(hw);
+#endif
+ GetWindowRect(hw, &r_pane);
+
+ OffsetRect(&r_pane, -r_title.left, -r_title.top);
+
+ SetWindowPos(hw_new,
+ hwtv,
+ r_pane.left, r_pane.top,
+ r_pane.right - r_pane.left,
+ r_pane.bottom - r_pane.top,
+ SWP_NOOWNERZORDER |
+ SWP_SHOWWINDOW |
+ SWP_NOACTIVATE);
+ }
+
+ if (node == NULL) {
+ wchar_t wbuf[256];
+
+ LoadString(khm_hInstance, IDS_CFG_ROOT_TITLE,
+ wbuf, ARRAYLENGTH(wbuf));
+
+ SetDlgItemText(hwnd, IDC_CFG_TITLE, wbuf);
+ } else {
+ khm_int32 rv;
+ khui_config_node_reg reg;
+
+ rv = khui_cfg_get_reg(node, &reg);
+#ifdef DEBUG
+ assert(KHM_SUCCEEDED(rv));
+#endif
+ SetDlgItemText(hwnd, IDC_CFG_TITLE, reg.long_desc);
+ }
+
+ d->hw_current = hw_new;
+ d->current = node;
+
+ TreeView_SelectItem(hwtv, hItem);
+}
+
+static BOOL
+cfgui_check_mod_state(khui_config_node node) {
+ khm_int32 flags;
+ khui_config_node c = NULL;
+ BOOL rv = FALSE;
+
+ flags = khui_cfg_get_flags(node);
+
+ if (flags & KHUI_CNFLAG_MODIFIED)
+ return TRUE;
+
+ if (KHM_FAILED(khui_cfg_get_first_child(node, &c)))
+ return FALSE;
+
+ while(c) {
+ rv = (rv || cfgui_check_mod_state(c));
+ khui_cfg_get_next_release(&c);
+ }
+
+ return rv;
+}
+
+static void
+cfgui_apply_settings(khui_config_node node) {
+ HWND hwnd;
+ khui_config_node c;
+ khm_int32 flags;
+
+ hwnd = khui_cfg_get_hwnd(node);
+ flags = khui_cfg_get_flags(node);
+
+ if (hwnd && (flags & KHUI_CNFLAG_MODIFIED)) {
+ SendMessage(hwnd, KHUI_WM_CFG_NOTIFY,
+ MAKEWPARAM(0, WMCFG_APPLY),
+ (LPARAM) node);
+ }
+
+ if (KHM_FAILED(khui_cfg_get_first_child(node, &c)))
+ return;
+
+ while (c) {
+ cfgui_apply_settings(c);
+ khui_cfg_get_next_release(&c);
+ }
+}
+
+static void
+cfgui_remove_item(HWND hwtv,
+ HTREEITEM hItem) {
+ khui_config_node node;
+ HTREEITEM hChild;
+ TVITEMEX itemex;
+
+ for (hChild = TreeView_GetChild(hwtv, hItem);
+ hChild;
+ hChild = TreeView_GetChild(hwtv, hItem)) {
+
+ cfgui_remove_item(hwtv, hChild);
+
+ }
+
+ ZeroMemory(&itemex, sizeof(itemex));
+
+ itemex.mask = TVIF_PARAM;
+ itemex.hItem = hItem;
+
+ TreeView_GetChild(hwtv, &itemex);
+
+ node = (khui_config_node) itemex.lParam;
+
+ if (node) {
+ HWND hw;
+ hw = khui_cfg_get_hwnd(node);
+
+ if (hw)
+ DestroyWindow(hw);
+
+ khui_cfg_release(node);
+ }
+
+ TreeView_DeleteItem(hwtv, hItem);
+}
+
+struct cfgui_child_info {
+ HTREEITEM hItem;
+ khui_config_node node;
+ BOOL checked;
+};
+
+#define CI_ALLOC_INCR 8
+
+static void
+cfgui_sync_node(cfgui_wnd_data * d,
+ HWND hwtv,
+ khui_config_node c,
+ HTREEITEM hItem) {
+ khui_config_node child;
+ HTREEITEM hChild;
+ struct cfgui_child_info * childinfo = NULL;
+ khm_size n_childinfo = 0;
+ khm_size nc_childinfo = 0;
+ khm_size i;
+
+ /* first, get the list of children from the treeview control */
+ for (hChild = TreeView_GetChild(hwtv, hItem);
+ hChild;
+ hChild = TreeView_GetNextSibling(hwtv, hChild)) {
+
+ if (n_childinfo >= nc_childinfo) {
+ nc_childinfo = UBOUNDSS(n_childinfo + 1,
+ CI_ALLOC_INCR, CI_ALLOC_INCR);
+#ifdef DEBUG
+ assert(nc_childinfo > n_childinfo);
+#endif
+ childinfo = PREALLOC(childinfo,
+ sizeof(*childinfo) * nc_childinfo);
+#ifdef DEBUG
+ assert(childinfo);
+#endif
+ }
+
+ ZeroMemory(&childinfo[n_childinfo],
+ sizeof(childinfo[n_childinfo]));
+
+ childinfo[n_childinfo].hItem = hChild;
+ childinfo[n_childinfo].checked = FALSE;
+ n_childinfo++;
+ }
+
+ /* now, go through the list of actual nodes and make sure they
+ match up */
+ child = NULL;
+ for (khui_cfg_get_first_child(c, &child);
+ child;
+ khui_cfg_get_next_release(&child)) {
+
+ hChild = (HTREEITEM) khui_cfg_get_param(child);
+
+ for (i=0; i < n_childinfo; i++) {
+ if (childinfo[i].hItem == hChild)
+ break;
+ }
+
+ if (i < n_childinfo) {
+ childinfo[i].checked = TRUE;
+ } else {
+ /* add it to the list, so we can create the node in the
+ tree view control later. */
+ if (n_childinfo >= nc_childinfo) {
+ nc_childinfo = UBOUNDSS(n_childinfo + 1,
+ CI_ALLOC_INCR, CI_ALLOC_INCR);
+#ifdef DEBUG
+ assert(nc_childinfo > n_childinfo);
+#endif
+ childinfo = PREALLOC(childinfo,
+ sizeof(*childinfo) * nc_childinfo);
+#ifdef DEBUG
+ assert(childinfo);
+#endif
+ }
+
+ ZeroMemory(&childinfo[n_childinfo],
+ sizeof(childinfo[n_childinfo]));
+
+ childinfo[n_childinfo].node = child;
+ khui_cfg_hold(child);
+ n_childinfo++;
+ }
+ }
+
+ /* by this point, the childinfo list contains items of the
+ following forms:
+
+ 1. childinfo[i].hItem != NULL && childinfo[i].checked == TRUE
+
+ Corresponds to a tree view item that has a matching
+ configuration node. Nothing to do here.
+
+ 2. childinfo[i].hItem != NULL && childinfo[i].checked == FALSE
+
+ Corresponds to a tree view item that has no matching
+ configuration node. These should be removed.
+
+ 3. childinfo[i].hItem == NULL && childinfo[i].node != NULL
+
+ Corresponds to a configuration node that has no matching
+ tree view item. These nodes should be added.
+ */
+
+ /* first do the removals */
+ for (i=0; i < n_childinfo; i++) {
+ if (childinfo[i].hItem == NULL)
+ break; /* nothing more to see from this point
+ on */
+ if (!childinfo[i].checked) {
+ /* remove! */
+ cfgui_remove_item(hwtv, childinfo[i].hItem);
+ }
+ }
+
+ /* continue from where the previous loop left off */
+ for (; i < n_childinfo; i++) {
+#ifdef DEBUG
+ assert(childinfo[i].hItem == NULL);
+ assert(childinfo[i].node != NULL);
+#endif
+
+ cfgui_add_node(d, hwtv, childinfo[i].node, c, FALSE);
+
+ khui_cfg_release(childinfo[i].node);
+ childinfo[i].node = NULL;
+ }
+
+ if (childinfo)
+ PFREE(childinfo);
+
+ /* finally recurse through to the next level */
+ for (hChild = TreeView_GetChild(hwtv, hItem);
+ hChild;
+ hChild = TreeView_GetNextSibling(hwtv, hChild)) {
+
+ TVITEMEX itemex;
+
+ ZeroMemory(&itemex, sizeof(itemex));
+
+ itemex.mask = TVIF_PARAM;
+ itemex.hItem = hChild;
+
+ TreeView_GetItem(hwtv, &itemex);
+
+ if (itemex.lParam) {
+ child = (khui_config_node) itemex.lParam;
+
+ cfgui_sync_node(d, hwtv, child, hChild);
+ }
+ }
+}
+
+static void
+cfgui_sync_node_list(cfgui_wnd_data * d, HWND hwnd) {
+ HWND hwtv;
+ HTREEITEM hItem;
+
+ hwtv = GetDlgItem(hwnd, IDC_CFG_NODELIST);
+ hItem = TreeView_GetRoot(hwtv);
+
+ cfgui_sync_node(d, hwtv, NULL, hItem);
+}
+
+static void
+cfgui_update_state(HWND hwnd,
+ khm_int32 flags,
+ khui_config_node node) {
+ cfgui_wnd_data * d;
+ HWND hwtv;
+ HTREEITEM hItem;
+ TVITEMEX itx;
+ int idx;
+
+ d = cfgui_get_wnd_data(hwnd);
+ hwtv = GetDlgItem(hwnd, IDC_CFG_NODELIST);
+ hItem = (HTREEITEM) khui_cfg_get_param(node);
+
+ ZeroMemory(&itx, sizeof(itx));
+
+ if (flags & KHUI_CNFLAG_MODIFIED)
+ idx = d->idx_modified;
+ else if (flags & KHUI_CNFLAG_APPLIED)
+ idx = d->idx_applied;
+ else
+ idx = d->idx_default;
+
+ itx.hItem = hItem;
+ itx.mask = TVIF_STATE;
+ itx.state = INDEXTOSTATEIMAGEMASK(idx);
+ itx.stateMask = TVIS_STATEIMAGEMASK;
+
+ TreeView_SetItem(hwtv, &itx);
+
+ if(cfgui_check_mod_state(NULL)) {
+ EnableWindow(GetDlgItem(hwnd, IDAPPLY), TRUE);
+ } else {
+ EnableWindow(GetDlgItem(hwnd, IDAPPLY), FALSE);
+ }
+}
+
+
+/* dialog procedure for the generic dialog */
+static INT_PTR CALLBACK
+cfgui_dlgproc_generic(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam) {
+ cfgui_wnd_data * d;
+
+ switch(uMsg) {
+ case WM_INITDIALOG:
+ d = (cfgui_wnd_data *) lParam;
+ cfgui_set_wnd_data(hwnd, d);
+ return TRUE;
+
+ case WM_CTLCOLORSTATIC:
+ d = cfgui_get_wnd_data(hwnd);
+ return (BOOL)(DWORD_PTR) d->hbr_white;
+
+ case WM_ERASEBKGND:
+ {
+ HDC hdc = (HDC) wParam;
+ RECT r_client;
+ RECT r_logo;
+ RECT r_fill;
+
+ d = cfgui_get_wnd_data(hwnd);
+
+ GetClientRect(hwnd, &r_client);
+ SetRectEmpty(&r_logo);
+
+ r_logo.right = d->kbmp_logo.cx;
+ r_logo.bottom = d->kbmp_logo.cy;
+
+ OffsetRect(&r_logo,
+ r_client.right - r_logo.right,
+ r_client.bottom - r_logo.bottom);
+
+ khui_draw_bitmap(hdc,
+ r_logo.left,
+ r_logo.top,
+ &d->kbmp_logo);
+
+ r_fill.left = 0;
+ r_fill.top = 0;
+ r_fill.right = r_logo.left;
+ r_fill.bottom = r_client.bottom;
+ FillRect(hdc, &r_fill, d->hbr_white);
+
+ r_fill.left = r_logo.left;
+ r_fill.right = r_client.right;
+ r_fill.bottom = r_logo.top;
+ FillRect(hdc, &r_fill, d->hbr_white);
+
+ SetWindowLongPtr(hwnd, DWLP_MSGRESULT, (LONG) TRUE);
+ }
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static INT_PTR CALLBACK
+cfgui_dlgproc(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam) {
+
+ khui_config_node node;
+ cfgui_wnd_data * d;
+
+ switch(uMsg) {
+ case WM_INITDIALOG:
+ node = (khui_config_node) lParam;
+
+ khui_cfg_clear_params();
+
+ khui_cfg_set_configui_handle(hwnd);
+
+ d = PMALLOC(sizeof(*d));
+ ZeroMemory(d, sizeof(*d));
+
+ d->hbr_white = CreateSolidBrush(RGB(255,255,255));
+
+ d->hw_generic_pane =
+ CreateDialogParam(khm_hInstance,
+ MAKEINTRESOURCE(IDD_CFG_GENERIC),
+ hwnd,
+ cfgui_dlgproc_generic,
+ (LPARAM) d);
+
+ khui_bitmap_from_hbmp(&d->kbmp_logo,
+ LoadImage(
+ khm_hInstance,
+ MAKEINTRESOURCE(IDB_LOGO_OPAQUE),
+ IMAGE_BITMAP,
+ 0,
+ 0,
+ LR_DEFAULTCOLOR));
+
+ cfgui_set_wnd_data(hwnd, d);
+
+ cfgui_initialize_dialog(hwnd);
+
+ cfgui_activate_node(hwnd, node);
+
+ khm_add_dialog(hwnd);
+ khm_enter_modal(hwnd);
+
+ return TRUE;
+
+ case WM_DESTROY:
+ cfgui_hwnd = NULL;
+
+ khui_cfg_set_configui_handle(NULL);
+
+ cfgui_uninitialize_dialog(hwnd);
+
+ d = cfgui_get_wnd_data(hwnd);
+ khui_delete_bitmap(&d->kbmp_logo);
+ DeleteObject(d->hbr_white);
+
+ cfgui_set_wnd_data(hwnd, NULL);
+
+ khm_del_dialog(hwnd);
+
+ SetForegroundWindow(khm_hwnd_main);
+
+ PFREE(d);
+
+ return FALSE;
+
+ case WM_NOTIFY:
+ {
+ LPNMHDR lpnm;
+ LPNMTREEVIEW lptv;
+ LPNMTVGETINFOTIP lpgi;
+ khui_config_node node;
+
+ lpnm = (LPNMHDR) lParam;
+
+ switch (lpnm->code) {
+ case TVN_SELCHANGED:
+ lptv = (LPNMTREEVIEW) lParam;
+ cfgui_activate_node(hwnd,
+ (khui_config_node)
+ lptv->itemNew.lParam);
+ return TRUE;
+
+ case TVN_GETINFOTIP:
+ lpgi = (LPNMTVGETINFOTIP) lParam;
+ node = (khui_config_node) lpgi->lParam;
+
+ if (node) {
+ khm_int32 flags = 0;
+
+ flags = khui_cfg_get_flags(node);
+
+ if (flags & KHUI_CNFLAG_MODIFIED) {
+ LoadString(khm_hInstance, IDS_CFG_IT_MOD,
+ lpgi->pszText, lpgi->cchTextMax);
+ } else if (flags & KHUI_CNFLAG_APPLIED) {
+ LoadString(khm_hInstance, IDS_CFG_IT_APP,
+ lpgi->pszText, lpgi->cchTextMax);
+ } else {
+ LoadString(khm_hInstance, IDS_CFG_IT_NONE,
+ lpgi->pszText, lpgi->cchTextMax);
+ }
+ } else {
+ StringCchCopy(lpgi->pszText, lpgi->cchTextMax, L"");
+ }
+
+ return TRUE;
+ }
+ }
+ return TRUE;
+
+ case WM_CTLCOLORSTATIC:
+ {
+ d = cfgui_get_wnd_data(hwnd);
+ return (BOOL)(DWORD_PTR) d->hbr_white;
+ }
+ /* implicit break */
+
+ case WM_COMMAND:
+ switch(wParam) {
+ case MAKEWPARAM(IDCANCEL, BN_CLICKED):
+ khm_leave_modal();
+ DestroyWindow(hwnd);
+ break;
+
+ case MAKEWPARAM(IDAPPLY, BN_CLICKED):
+ cfgui_apply_settings(NULL);
+ break;
+
+ case MAKEWPARAM(IDOK, BN_CLICKED):
+ cfgui_apply_settings(NULL);
+ khm_leave_modal();
+ DestroyWindow(hwnd);
+ break;
+ }
+ return TRUE;
+
+ case KHUI_WM_CFG_NOTIFY:
+ switch(HIWORD(wParam)) {
+ case WMCFG_SHOW_NODE:
+ cfgui_activate_node(hwnd, (khui_config_node) lParam);
+ break;
+
+ case WMCFG_UPDATE_STATE:
+ cfgui_update_state(hwnd, LOWORD(wParam),
+ (khui_config_node) lParam);
+ break;
+
+ case WMCFG_SYNC_NODE_LIST:
+ d = cfgui_get_wnd_data(hwnd);
+ cfgui_sync_node_list(d, hwnd);
+ break;
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+cfgui_create_window(khui_config_node node) {
+#ifdef DEBUG
+ assert(cfgui_hwnd == NULL);
+#endif
+
+ khm_refresh_config();
+
+ cfgui_hwnd = CreateDialogParam(khm_hInstance,
+ MAKEINTRESOURCE(IDD_CFG_MAIN),
+ khm_hwnd_main,
+ cfgui_dlgproc,
+ (LPARAM) node);
+#ifdef DEBUG
+ assert(cfgui_hwnd != NULL);
+#endif
+ ShowWindow(cfgui_hwnd,SW_SHOW);
+}
+
+static void
+cfgui_destroy_window(void) {
+ if (cfgui_hwnd)
+ DestroyWindow(cfgui_hwnd);
+ /* cfgui_hwnd will be set to NULL in the dialog proc */
+}
+
+void
+khm_show_config_pane(khui_config_node node) {
+ if (cfgui_hwnd != NULL) {
+ SendMessage(cfgui_hwnd, KHUI_WM_CFG_NOTIFY,
+ MAKEWPARAM(0, WMCFG_SHOW_NODE),
+ (LPARAM) node);
+ } else {
+ cfgui_create_window(node);
+ }
+}
+
+void khm_refresh_config(void) {
+ khm_size cb;
+ khm_size n_idents;
+ wchar_t * idents = NULL;
+ wchar_t * t;
+ khm_int32 rv;
+ int n_tries = 0;
+ khui_config_node cfg_ids = NULL;
+ khui_config_node cfg_r = NULL;
+ khui_config_node cfg_iter = NULL;
+ khui_menu_def * omenu;
+ khm_boolean refresh_menu = FALSE;
+
+ do {
+ rv = kcdb_identity_enum(KCDB_IDENT_FLAG_CONFIG,
+ KCDB_IDENT_FLAG_CONFIG,
+ NULL,
+ &cb,
+ &n_idents);
+
+ if (rv != KHM_ERROR_TOO_LONG ||
+ n_idents == 0)
+ return;
+
+ if (idents)
+ PFREE(idents);
+ idents = PMALLOC(cb);
+#ifdef DEBUG
+ assert(idents);
+#endif
+
+ rv = kcdb_identity_enum(KCDB_IDENT_FLAG_CONFIG,
+ KCDB_IDENT_FLAG_CONFIG,
+ idents,
+ &cb,
+ &n_idents);
+
+ n_tries++;
+ } while(KHM_FAILED(rv) &&
+ n_tries < 5);
+
+ if (KHM_FAILED(rv))
+ goto _cleanup;
+
+ if (KHM_FAILED(khui_cfg_open(NULL,
+ L"KhmIdentities",
+ &cfg_ids)))
+ goto _cleanup;
+
+ for(t = idents; t && *t; t = multi_string_next(t)) {
+ khui_config_node cfg_id = NULL;
+
+ rv = khui_cfg_open(cfg_ids,
+ t,
+ &cfg_id);
+
+ if (KHM_FAILED(rv)) {
+ khui_config_node_reg reg;
+ wchar_t wshort[KHUI_MAXCCH_SHORT_DESC];
+ wchar_t wlong[KHUI_MAXCCH_LONG_DESC];
+ wchar_t wfmt[KHUI_MAXCCH_SHORT_DESC];
+
+ ZeroMemory(&reg, sizeof(reg));
+
+ reg.name = t;
+ reg.short_desc = wshort;
+ reg.long_desc = wlong;
+ reg.h_module = khm_hInstance;
+ reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_IDENTITY);
+ reg.dlg_proc = khm_cfg_identity_proc;
+ reg.flags = 0;
+
+ LoadString(khm_hInstance, IDS_CFG_IDENTITY_SHORT,
+ wfmt, ARRAYLENGTH(wfmt));
+ StringCbPrintf(wshort, sizeof(wshort), wfmt, t);
+
+ LoadString(khm_hInstance, IDS_CFG_IDENTITY_LONG,
+ wfmt, ARRAYLENGTH(wfmt));
+ StringCbPrintf(wlong, sizeof(wlong), wfmt, t);
+
+ khui_cfg_register(cfg_ids,
+ &reg);
+ } else {
+ khui_cfg_release(cfg_id);
+ }
+ }
+
+ for (khui_cfg_get_first_child(cfg_ids, &cfg_iter);
+ cfg_iter;
+ khui_cfg_get_next_release(&cfg_iter)) {
+
+ wchar_t cfgname[KCDB_IDENT_MAXCCH_NAME];
+ khm_size cb;
+ khm_handle tident = NULL;
+ khm_int32 tflags = 0;
+
+ cb = sizeof(cfgname);
+ khui_cfg_get_name(cfg_iter, cfgname, &cb);
+
+ if (KHM_FAILED(kcdb_identity_create(cfgname, 0, &tident)) ||
+ KHM_FAILED(kcdb_identity_get_flags(tident, &tflags)) ||
+ !(tflags & KCDB_IDENT_FLAG_ACTIVE) ||
+ !(tflags & KCDB_IDENT_FLAG_CONFIG)) {
+
+ /* this configuration node needs to be removed */
+
+ khui_cfg_remove(cfg_iter);
+ }
+
+ if (tident)
+ kcdb_identity_release(tident);
+ }
+
+ /* Now iterate through the root level configuration nodes and make
+ sure we have a menu item for each of them. */
+ if (KHM_FAILED(khui_cfg_get_first_child(NULL, &cfg_r)))
+ goto _cleanup;
+
+ omenu = khui_find_menu(KHUI_MENU_OPTIONS);
+ if (omenu == NULL)
+ goto _cleanup;
+
+ khui_action_lock();
+
+ do {
+ khm_int32 action;
+ khm_int32 flags;
+ khui_action * paction;
+ wchar_t cname[KHUI_MAXCCH_NAME];
+ wchar_t wshort[KHUI_MAXCCH_SHORT_DESC];
+ khm_size cb;
+ khm_handle sub;
+ khui_config_node_reg reg;
+
+ flags = khui_cfg_get_flags(cfg_r);
+ if (flags & KHUI_CNFLAG_SYSTEM)
+ goto _next_cfg;
+
+ cb = sizeof(cname);
+ if (KHM_FAILED(khui_cfg_get_name(cfg_r, cname, &cb))) {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ goto _next_cfg;
+ }
+
+ paction = khui_find_named_action(cname);
+
+ if (!paction) {
+ khui_cfg_get_reg(cfg_r, &reg);
+
+ kmq_create_hwnd_subscription(khm_hwnd_main, &sub);
+
+ StringCbCopy(wshort, sizeof(wshort), reg.short_desc);
+ StringCbCat(wshort, sizeof(wshort), L" ...");
+
+ action = khui_action_create(cname,
+ wshort,
+ reg.long_desc,
+ (void *) CFGACTION_MAGIC,
+ KHUI_ACTIONTYPE_TRIGGER,
+ sub);
+
+ if (action == 0) {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ goto _next_cfg;
+ }
+
+ khui_menu_insert_action(omenu, -1, action, 0);
+
+ refresh_menu = TRUE;
+ }
+
+ _next_cfg:
+ if (KHM_FAILED(khui_cfg_get_next_release(&cfg_r)))
+ break;
+ } while(cfg_r);
+
+ khui_action_unlock();
+
+ if (refresh_menu) {
+ khui_refresh_actions();
+ }
+
+ _cleanup:
+ if (cfg_ids)
+ khui_cfg_release(cfg_ids);
+
+ if (cfg_r)
+ khui_cfg_release(cfg_r);
+
+ if (idents)
+ PFREE(idents);
+}
+
+void khm_init_config(void) {
+ wchar_t wshort[KHUI_MAXCCH_SHORT_DESC];
+ wchar_t wlong[KHUI_MAXCCH_LONG_DESC];
+ khui_config_node_reg reg;
+ khui_config_node node;
+
+ reg.short_desc = wshort;
+ reg.long_desc = wlong;
+ reg.h_module = khm_hInstance;
+ reg.flags = KHUI_CNFLAG_SYSTEM;
+
+ reg.name = L"KhmGeneral";
+ reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_GENERAL);
+ reg.dlg_proc = khm_cfg_general_proc;
+ LoadString(khm_hInstance, IDS_CFG_GENERAL_SHORT,
+ wshort, ARRAYLENGTH(wshort));
+ LoadString(khm_hInstance, IDS_CFG_GENERAL_LONG,
+ wlong, ARRAYLENGTH(wlong));
+
+ khui_cfg_register(NULL, &reg);
+
+ reg.name = L"KhmAppear";
+ reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_APPEAR);
+ reg.dlg_proc = khm_cfg_appearance_proc;
+ LoadString(khm_hInstance, IDS_CFG_APPEAR_SHORT,
+ wshort, ARRAYLENGTH(wshort));
+ LoadString(khm_hInstance, IDS_CFG_APPEAR_LONG,
+ wlong, ARRAYLENGTH(wlong));
+
+ khui_cfg_register(NULL, &reg);
+
+ reg.name = L"KhmIdentities";
+ reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_IDENTITIES);
+ reg.dlg_proc = khm_cfg_identities_proc;
+ LoadString(khm_hInstance, IDS_CFG_IDENTITIES_SHORT,
+ wshort, ARRAYLENGTH(wshort));
+ LoadString(khm_hInstance, IDS_CFG_IDENTITIES_LONG,
+ wlong, ARRAYLENGTH(wlong));
+
+ khui_cfg_register(NULL, &reg);
+
+ node = NULL;
+ khui_cfg_open(NULL, L"KhmIdentities", &node);
+#ifdef DEBUG
+ assert(node);
+#endif
+
+ reg.name = L"KhmIdentitiesTab";
+ reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_IDS_TAB);
+ reg.dlg_proc = khm_cfg_ids_tab_proc;
+ LoadString(khm_hInstance, IDS_CFG_IDS_TAB_SHORT,
+ wshort, ARRAYLENGTH(wshort));
+ LoadString(khm_hInstance, IDS_CFG_IDS_TAB_LONG,
+ wlong, ARRAYLENGTH(wlong));
+ reg.flags = KHUI_CNFLAG_SUBPANEL | KHUI_CNFLAG_SYSTEM;
+
+ khui_cfg_register(node, &reg);
+
+ reg.name = L"KhmIdentitiesTabPlural";
+ reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_ID_TAB);
+ reg.dlg_proc = khm_cfg_id_tab_proc;
+ LoadString(khm_hInstance, IDS_CFG_ID_TAB_SHORT,
+ wshort, ARRAYLENGTH(wshort));
+ LoadString(khm_hInstance, IDS_CFG_ID_TAB_LONG,
+ wlong, ARRAYLENGTH(wlong));
+ reg.flags = KHUI_CNFLAG_PLURAL | KHUI_CNFLAG_SUBPANEL | KHUI_CNFLAG_SYSTEM;
+
+ khui_cfg_register(node, &reg);
+
+ reg.flags = KHUI_CNFLAG_SYSTEM;
+ khui_cfg_release(node);
+
+ reg.name = L"KhmNotifications";
+ reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_NOTIF);
+ reg.dlg_proc = khm_cfg_notifications_proc;
+ LoadString(khm_hInstance, IDS_CFG_NOTIF_SHORT,
+ wshort, ARRAYLENGTH(wshort));
+ LoadString(khm_hInstance, IDS_CFG_NOTIF_LONG,
+ wlong, ARRAYLENGTH(wlong));
+
+ khui_cfg_register(NULL, &reg);
+
+ reg.name = L"KhmPlugins";
+ reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_PLUGINS);
+ reg.dlg_proc = khm_cfg_plugins_proc;
+ LoadString(khm_hInstance, IDS_CFG_PLUGINS_SHORT,
+ wshort, ARRAYLENGTH(wshort));
+ LoadString(khm_hInstance, IDS_CFG_PLUGINS_LONG,
+ wlong, ARRAYLENGTH(wlong));
+
+ khui_cfg_register(NULL, &reg);
+}
+
+void khm_exit_config(void) {
+}
diff --git a/src/windows/identity/ui/configwnd.h b/src/windows/identity/ui/configwnd.h
index 693ec7d72a..712805fc14 100644
--- a/src/windows/identity/ui/configwnd.h
+++ b/src/windows/identity/ui/configwnd.h
@@ -1,88 +1,88 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#ifndef __KHIMAIRA_CONFIGWND_H
-#define __KHIMAIRA_CONFIGWND_H
-
-#define CFGACTION_MAGIC 0x38f8
-
-void
-khm_show_config_pane(khui_config_node node);
-
-void khm_init_config(void);
-void khm_exit_config(void);
-
-void khm_refresh_config(void);
-
-/* window procedures for other configuration windows */
-INT_PTR CALLBACK
-khm_cfg_general_proc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam);
-
-INT_PTR CALLBACK
-khm_cfg_identities_proc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam);
-
-INT_PTR CALLBACK
-khm_cfg_identity_proc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam);
-
-INT_PTR CALLBACK
-khm_cfg_id_tab_proc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam);
-
-INT_PTR CALLBACK
-khm_cfg_ids_tab_proc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam);
-
-INT_PTR CALLBACK
-khm_cfg_notifications_proc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam);
-
-INT_PTR CALLBACK
-khm_cfg_plugins_proc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam);
-
-INT_PTR CALLBACK
-khm_cfg_appearance_proc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam);
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __KHIMAIRA_CONFIGWND_H
+#define __KHIMAIRA_CONFIGWND_H
+
+#define CFGACTION_MAGIC 0x38f8
+
+void
+khm_show_config_pane(khui_config_node node);
+
+void khm_init_config(void);
+void khm_exit_config(void);
+
+void khm_refresh_config(void);
+
+/* window procedures for other configuration windows */
+INT_PTR CALLBACK
+khm_cfg_general_proc(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam);
+
+INT_PTR CALLBACK
+khm_cfg_identities_proc(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam);
+
+INT_PTR CALLBACK
+khm_cfg_identity_proc(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam);
+
+INT_PTR CALLBACK
+khm_cfg_id_tab_proc(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam);
+
+INT_PTR CALLBACK
+khm_cfg_ids_tab_proc(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam);
+
+INT_PTR CALLBACK
+khm_cfg_notifications_proc(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam);
+
+INT_PTR CALLBACK
+khm_cfg_plugins_proc(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam);
+
+INT_PTR CALLBACK
+khm_cfg_appearance_proc(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam);
+#endif
diff --git a/src/windows/identity/ui/credfuncs.c b/src/windows/identity/ui/credfuncs.c
index 2f1ac8033d..8eeba14a31 100644
--- a/src/windows/identity/ui/credfuncs.c
+++ b/src/windows/identity/ui/credfuncs.c
@@ -1,1398 +1,1398 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- * Copyright (c) 2007 Secure Endpoints Inc.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<khmapp.h>
-#include<assert.h>
-
-static BOOL in_dialog = FALSE;
-static CRITICAL_SECTION cs_dialog;
-static HANDLE in_dialog_evt = NULL;
-static LONG init_dialog = 0;
-static khm_int32 dialog_result = 0;
-static wchar_t dialog_identity[KCDB_IDENT_MAXCCH_NAME];
-static khui_new_creds * dialog_nc = NULL;
-
-static void
-dialog_sync_init(void) {
- if (InterlockedIncrement(&init_dialog) == 1) {
-#ifdef DEBUG
- assert(in_dialog_evt == NULL);
- assert(in_dialog == FALSE);
-#endif
-
- InitializeCriticalSection(&cs_dialog);
-
- in_dialog_evt = CreateEvent(NULL,
- TRUE,
- TRUE,
- L"DialogCompletionEvent");
- } else {
- InterlockedDecrement(&init_dialog);
- if (in_dialog_evt == NULL) {
- Sleep(100);
- }
- }
-}
-
-BOOL
-khm_cred_begin_dialog(void) {
- BOOL rv;
-
- dialog_sync_init();
-
- EnterCriticalSection(&cs_dialog);
-
- if (in_dialog) {
- rv = FALSE;
-
- /* if a dialog is being displayed and we got a another request
- to show one, we bring the existing one to the
- foreground. */
- if (dialog_nc && dialog_nc->hwnd) {
- khm_int32 t = 0;
-
- if (KHM_SUCCEEDED(khc_read_int32(NULL,
- L"CredWindow\\Windows\\NewCred\\ForceToTop",
- &t)) &&
- t != 0) {
-
- khm_activate_main_window();
-
- SetWindowPos(dialog_nc->hwnd, HWND_TOP, 0, 0, 0, 0,
- (SWP_NOMOVE | SWP_NOSIZE));
- }
- }
-
- } else {
- rv = TRUE;
- in_dialog = TRUE;
- ResetEvent(in_dialog_evt);
- }
-
- LeaveCriticalSection(&cs_dialog);
- return rv;
-}
-
-void
-khm_cred_end_dialog(khui_new_creds * nc) {
- dialog_sync_init();
-
- EnterCriticalSection(&cs_dialog);
- if (in_dialog) {
- in_dialog = FALSE;
- SetEvent(in_dialog_evt);
- }
- dialog_result = nc->result;
-#ifdef DEBUG
- assert(dialog_nc == nc);
-#endif
- dialog_nc = NULL;
- if (nc->subtype == KMSG_CRED_NEW_CREDS &&
- nc->n_identities > 0 &&
- nc->identities[0]) {
- khm_size cb;
-
- cb = sizeof(dialog_identity);
- if (KHM_FAILED(kcdb_identity_get_name(nc->identities[0],
- dialog_identity,
- &cb)))
- dialog_identity[0] = 0;
- } else {
- dialog_identity[0] = 0;
- }
- LeaveCriticalSection(&cs_dialog);
-}
-
-BOOL
-khm_cred_is_in_dialog(void) {
- BOOL rv;
-
- dialog_sync_init();
-
- EnterCriticalSection(&cs_dialog);
- rv = in_dialog;
- LeaveCriticalSection(&cs_dialog);
-
- return rv;
-}
-
-khm_int32
-khm_cred_wait_for_dialog(DWORD timeout, khm_int32 * result,
- wchar_t * ident, khm_size cb_ident) {
- khm_int32 rv;
-
- dialog_sync_init();
-
- EnterCriticalSection(&cs_dialog);
- if (!in_dialog)
- rv = KHM_ERROR_NOT_FOUND;
- else {
- DWORD dw;
-
- do {
- LeaveCriticalSection(&cs_dialog);
-
- dw = WaitForSingleObject(in_dialog_evt, timeout);
-
- EnterCriticalSection(&cs_dialog);
-
- if (!in_dialog) {
- rv = KHM_ERROR_SUCCESS;
- if (result) {
- *result = dialog_result;
- }
- if (ident) {
- StringCbCopy(ident, cb_ident, dialog_identity);
- }
- break;
- } else if(dw == WAIT_TIMEOUT) {
- rv = KHM_ERROR_TIMEOUT;
- break;
- }
- } while(TRUE);
- }
- LeaveCriticalSection(&cs_dialog);
-
- return rv;
-}
-
-/* Completion handler for KMSG_CRED messages. We control the overall
- logic of credentials acquisition and other operations here. Once a
- credentials operation is triggered, each successive message
- completion notification will be used to dispatch the messages for
- the next step in processing the operation. */
-void KHMAPI
-kmsg_cred_completion(kmq_message *m)
-{
- khui_new_creds * nc;
-
-#ifdef DEBUG
- assert(m->type == KMSG_CRED);
-#else
- if(m->type != KMSG_CRED)
- return; /* huh? */
-#endif
-
- switch(m->subtype) {
- case KMSG_CRED_PASSWORD:
- /* fallthrough */
- case KMSG_CRED_NEW_CREDS:
- /* Cred types have attached themselves. Trigger the next
- phase. */
- kmq_post_message(KMSG_CRED, KMSG_CRED_DIALOG_SETUP, 0,
- m->vparam);
- break;
-
- case KMSG_CRED_RENEW_CREDS:
- nc = (khui_new_creds *) m->vparam;
-
- /* khm_cred_dispatch_process_message() deals with the case
- where there are no credential types that wants to
- participate in this operation. */
- khm_cred_dispatch_process_message(nc);
- break;
-
- case KMSG_CRED_DIALOG_SETUP:
- nc = (khui_new_creds *) m->vparam;
-
- khm_prep_newcredwnd(nc->hwnd);
-
- /* all the controls have been created. Now initialize them */
- if (nc->n_types > 0) {
- kmq_post_subs_msg(nc->type_subs,
- nc->n_types,
- KMSG_CRED,
- KMSG_CRED_DIALOG_PRESTART,
- 0,
- m->vparam);
- } else {
- PostMessage(nc->hwnd, KHUI_WM_NC_NOTIFY,
- MAKEWPARAM(0, WMNC_DIALOG_PROCESS_COMPLETE), 0);
- }
- break;
-
- case KMSG_CRED_DIALOG_PRESTART:
- /* all prestart stuff is done. Now to activate the dialog */
- nc = (khui_new_creds *) m->vparam;
- khm_show_newcredwnd(nc->hwnd);
-
- kmq_post_subs_msg(nc->type_subs,
- nc->n_types,
- KMSG_CRED,
- KMSG_CRED_DIALOG_START,
- 0,
- m->vparam);
- /* at this point, the dialog window takes over. We let it run
- the show until KMSG_CRED_DIALOG_END is posted by the dialog
- procedure. */
- break;
-
- case KMSG_CRED_PROCESS:
- /* a wave of these messages have completed. We should check
- if there's more */
- nc = (khui_new_creds *) m->vparam;
-
- /* if we are done processing all the plug-ins, then check if
- there were any errors reported. Otherwise we dispatch
- another set of messages. */
- if(!khm_cred_dispatch_process_level(nc)) {
-
- if(kherr_is_error()) {
- khui_alert * alert;
- kherr_event * evt;
- kherr_context * ctx;
- wchar_t ws_tfmt[512];
- wchar_t w_idname[KCDB_IDENT_MAXCCH_NAME];
- wchar_t ws_title[ARRAYLENGTH(ws_tfmt) + KCDB_IDENT_MAXCCH_NAME];
- khm_size cb;
-
- /* For renewals, we suppress the error message for the
- following case:
-
- - The renewal was for an identity
-
- - There are no identity credentials for the
- identity (no credentials that have the same type
- as the identity provider). */
-
- if (nc->subtype == KMSG_CRED_RENEW_CREDS &&
- nc->ctx.scope == KHUI_SCOPE_IDENT &&
- nc->ctx.identity != NULL) {
- khm_handle tcs = NULL; /* credential set */
- khm_size count = 0;
- khm_int32 id_ctype = KCDB_CREDTYPE_INVALID;
- khm_int32 delta = 0;
-
- kcdb_identity_get_type(&id_ctype);
- kcdb_credset_create(&tcs);
- kcdb_credset_collect(tcs, NULL,
- nc->ctx.identity,
- id_ctype,
- &delta);
- kcdb_credset_get_size(tcs, &count);
- kcdb_credset_delete(tcs);
-
- if (count == 0) {
- goto done_with_op;
- }
- }
-
- ctx = kherr_peek_context();
- evt = kherr_get_err_event(ctx);
- kherr_evaluate_event(evt);
-
- khui_alert_create_empty(&alert);
-
- if (nc->subtype == KMSG_CRED_NEW_CREDS) {
-
- khui_alert_set_type(alert, KHUI_ALERTTYPE_ACQUIREFAIL);
-
- cb = sizeof(w_idname);
- if (nc->n_identities == 0 ||
- KHM_FAILED(kcdb_identity_get_name(nc->identities[0],
- w_idname, &cb))) {
- /* an identity could not be determined */
- LoadString(khm_hInstance, IDS_NC_FAILED_TITLE,
- ws_title, ARRAYLENGTH(ws_title));
- } else {
- LoadString(khm_hInstance, IDS_NC_FAILED_TITLE_I,
- ws_tfmt, ARRAYLENGTH(ws_tfmt));
- StringCbPrintf(ws_title, sizeof(ws_title),
- ws_tfmt, w_idname);
- khui_alert_set_ctx(alert,
- KHUI_SCOPE_IDENT,
- nc->identities[0],
- KCDB_CREDTYPE_INVALID,
- NULL);
- }
-
- } else if (nc->subtype == KMSG_CRED_PASSWORD) {
-
- khui_alert_set_type(alert, KHUI_ALERTTYPE_CHPW);
-
- cb = sizeof(w_idname);
- if (nc->n_identities == 0 ||
- KHM_FAILED(kcdb_identity_get_name(nc->identities[0],
- w_idname, &cb))) {
- LoadString(khm_hInstance, IDS_NC_PWD_FAILED_TITLE,
- ws_title, ARRAYLENGTH(ws_title));
- } else {
- LoadString(khm_hInstance, IDS_NC_PWD_FAILED_TITLE_I,
- ws_tfmt, ARRAYLENGTH(ws_tfmt));
- StringCbPrintf(ws_title, sizeof(ws_title),
- ws_tfmt, w_idname);
- khui_alert_set_ctx(alert,
- KHUI_SCOPE_IDENT,
- nc->identities[0],
- KCDB_CREDTYPE_INVALID,
- NULL);
- }
-
- } else if (nc->subtype == KMSG_CRED_RENEW_CREDS) {
-
- khui_alert_set_type(alert, KHUI_ALERTTYPE_RENEWFAIL);
-
- cb = sizeof(w_idname);
- if (nc->ctx.identity == NULL ||
- KHM_FAILED(kcdb_identity_get_name(nc->ctx.identity,
- w_idname, &cb))) {
- LoadString(khm_hInstance, IDS_NC_REN_FAILED_TITLE,
- ws_title, ARRAYLENGTH(ws_title));
- } else {
- LoadString(khm_hInstance, IDS_NC_REN_FAILED_TITLE_I,
- ws_tfmt, ARRAYLENGTH(ws_tfmt));
- StringCbPrintf(ws_title, sizeof(ws_title),
- ws_tfmt, w_idname);
- khui_alert_set_ctx(alert,
- KHUI_SCOPE_IDENT,
- nc->ctx.identity,
- KCDB_CREDTYPE_INVALID,
- NULL);
- }
-
- } else {
-#ifdef DEBUG
- assert(FALSE);
-#endif
- }
-
- khui_alert_set_title(alert, ws_title);
- khui_alert_set_severity(alert, evt->severity);
-
- if(!evt->long_desc)
- khui_alert_set_message(alert, evt->short_desc);
- else
- khui_alert_set_message(alert, evt->long_desc);
-
- if(evt->suggestion)
- khui_alert_set_suggestion(alert, evt->suggestion);
-
- if (nc->subtype == KMSG_CRED_RENEW_CREDS &&
- nc->ctx.identity != NULL) {
-
- khm_int32 n_cmd;
-
- n_cmd = khm_get_identity_new_creds_action(nc->ctx.identity);
-
- if (n_cmd != 0) {
- khui_alert_add_command(alert, n_cmd);
- khui_alert_add_command(alert, KHUI_PACTION_CLOSE);
-
- khui_alert_set_flags(alert, KHUI_ALERT_FLAG_DISPATCH_CMD,
- KHUI_ALERT_FLAG_DISPATCH_CMD);
- }
- }
-
- khui_alert_show(alert);
- khui_alert_release(alert);
-
- kherr_release_context(ctx);
-
- kherr_clear_error();
- }
-
- done_with_op:
-
- if (nc->subtype == KMSG_CRED_RENEW_CREDS) {
- kmq_post_message(KMSG_CRED, KMSG_CRED_END, 0,
- m->vparam);
- } else {
- PostMessage(nc->hwnd, KHUI_WM_NC_NOTIFY,
- MAKEWPARAM(0, WMNC_DIALOG_PROCESS_COMPLETE),
- 0);
- }
- }
- break;
-
- case KMSG_CRED_END:
- /* all is done. */
- {
- khui_new_creds * nc;
- khm_boolean continue_cmdline = TRUE;
-
- nc = (khui_new_creds *) m->vparam;
-
- if (nc->subtype == KMSG_CRED_NEW_CREDS ||
- nc->subtype == KMSG_CRED_PASSWORD) {
-
- khm_cred_end_dialog(nc);
-
- } else if (nc->subtype == KMSG_CRED_RENEW_CREDS) {
-
- /* if this is a renewal that was triggered while we
- were processing the commandline, then we need to
- update the pending renewal count. */
-
- if (khm_startup.processing) {
- LONG renewals;
- renewals = InterlockedDecrement(&khm_startup.pending_renewals);
-
- if (renewals != 0) {
- continue_cmdline = FALSE;
- }
- }
- }
-
- khui_cw_destroy_cred_blob(nc);
-
- kmq_post_message(KMSG_CRED, KMSG_CRED_REFRESH, 0, 0);
-
- if (continue_cmdline)
- kmq_post_message(KMSG_ACT, KMSG_ACT_CONTINUE_CMDLINE, 0, 0);
- }
- break;
-
- /* property sheet stuff */
-
- case KMSG_CRED_PP_BEGIN:
- /* all the pages should have been added by now. Just send out
- the precreate message */
- kmq_post_message(KMSG_CRED, KMSG_CRED_PP_PRECREATE, 0,
- m->vparam);
- break;
-
- case KMSG_CRED_PP_END:
- kmq_post_message(KMSG_CRED, KMSG_CRED_PP_DESTROY, 0,
- m->vparam);
- break;
-
- case KMSG_CRED_DESTROY_CREDS:
-#ifdef DEBUG
- assert(m->vparam != NULL);
-#endif
- khui_context_release((khui_action_context *) m->vparam);
- PFREE(m->vparam);
-
- kmq_post_message(KMSG_CRED, KMSG_CRED_REFRESH, 0, 0);
-
- kmq_post_message(KMSG_ACT, KMSG_ACT_CONTINUE_CMDLINE, 0, 0);
- break;
-
- case KMSG_CRED_IMPORT:
- {
- khm_boolean continue_cmdline = FALSE;
- LONG pending_renewals;
-
- /* once an import operation ends, we have to trigger a
- renewal so that other plug-ins that didn't participate
- in the import operation can have a chance at getting
- the necessary credentials.
-
- If we are in the middle of processing the commandline,
- we have to be a little bit careful. We can't issue a
- commandline conituation message right now because the
- import action is still ongoing (since the renewals are
- part of the action). Once the renewals have completed,
- the completion handler will automatically issue a
- commandline continuation message. However, if there
- were no identities to renew, then we have to issue the
- message ourselves.
- */
-
- InterlockedIncrement(&khm_startup.pending_renewals);
-
- khm_cred_renew_all_identities();
-
- pending_renewals = InterlockedDecrement(&khm_startup.pending_renewals);
-
- if (pending_renewals == 0 && khm_startup.processing)
- kmq_post_message(KMSG_ACT, KMSG_ACT_CONTINUE_CMDLINE, 0, 0);
- }
- break;
-
- case KMSG_CRED_REFRESH:
- kcdb_identity_refresh_all();
- break;
- }
-}
-
-void khm_cred_import(void)
-{
- _begin_task(KHERR_CF_TRANSITIVE);
- _report_sr0(KHERR_NONE, IDS_CTX_IMPORT);
- _describe();
-
- kmq_post_message(KMSG_CRED, KMSG_CRED_IMPORT, 0, 0);
-
- _end_task();
-}
-
-void khm_cred_set_default(void)
-{
- khui_action_context ctx;
- khm_int32 rv;
-
- khui_context_get(&ctx);
-
- if (ctx.identity) {
- rv = kcdb_identity_set_default(ctx.identity);
- }
-
- khui_context_release(&ctx);
-}
-
-void khm_cred_destroy_creds(khm_boolean sync, khm_boolean quiet)
-{
- khui_action_context * pctx;
-
- pctx = PMALLOC(sizeof(*pctx));
-#ifdef DEBUG
- assert(pctx);
-#endif
-
- khui_context_get(pctx);
-
- if(pctx->scope == KHUI_SCOPE_NONE && !quiet) {
- /* this really shouldn't be necessary once we start enabling
- and disbling actions based on context */
- wchar_t title[256];
- wchar_t message[256];
-
- LoadString(khm_hInstance,
- IDS_ALERT_NOSEL_TITLE,
- title,
- ARRAYLENGTH(title));
-
- LoadString(khm_hInstance,
- IDS_ALERT_NOSEL,
- message,
- ARRAYLENGTH(message));
-
- khui_alert_show_simple(title,
- message,
- KHERR_WARNING);
-
- khui_context_release(pctx);
- PFREE(pctx);
-
- return;
- }
-
- _begin_task(KHERR_CF_TRANSITIVE);
- _report_sr0(KHERR_NONE, IDS_CTX_DESTROY_CREDS);
- _describe();
-
- if (sync)
- kmq_send_message(KMSG_CRED,
- KMSG_CRED_DESTROY_CREDS,
- 0,
- (void *) pctx);
- else
- kmq_post_message(KMSG_CRED,
- KMSG_CRED_DESTROY_CREDS,
- 0,
- (void *) pctx);
-
- _end_task();
-}
-
-void khm_cred_destroy_identity(khm_handle identity)
-{
- khui_action_context * pctx;
- wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
- khm_size cb;
-
- if (identity == NULL)
- return;
-
- pctx = PMALLOC(sizeof(*pctx));
-#ifdef DEBUG
- assert(pctx);
-#endif
-
- khui_context_create(pctx,
- KHUI_SCOPE_IDENT,
- identity,
- KCDB_CREDTYPE_INVALID,
- NULL);
-
- cb = sizeof(idname);
- kcdb_identity_get_name(identity, idname, &cb);
-
- _begin_task(KHERR_CF_TRANSITIVE);
- _report_sr1(KHERR_NONE, IDS_CTX_DESTROY_ID, _dupstr(idname));
- _describe();
-
- kmq_post_message(KMSG_CRED,
- KMSG_CRED_DESTROY_CREDS,
- 0,
- (void *) pctx);
-
- _end_task();
-}
-
-void khm_cred_renew_all_identities(void)
-{
- khm_size count;
- khm_size cb = 0;
- khm_size n_idents = 0;
- khm_int32 rv;
- wchar_t * ident_names = NULL;
- wchar_t * this_ident;
-
- kcdb_credset_get_size(NULL, &count);
-
- /* if there are no credentials, we just skip over the renew
- action. */
-
- if (count == 0)
- return;
-
- ident_names = NULL;
-
- while (TRUE) {
- if (ident_names) {
- PFREE(ident_names);
- ident_names = NULL;
- }
-
- cb = 0;
- rv = kcdb_identity_enum(KCDB_IDENT_FLAG_EMPTY, 0,
- NULL,
- &cb, &n_idents);
-
- if (n_idents == 0 || rv != KHM_ERROR_TOO_LONG ||
- cb == 0)
- break;
-
- ident_names = PMALLOC(cb);
- ident_names[0] = L'\0';
-
- rv = kcdb_identity_enum(KCDB_IDENT_FLAG_EMPTY, 0,
- ident_names,
- &cb, &n_idents);
-
- if (KHM_SUCCEEDED(rv))
- break;
- }
-
- if (ident_names) {
- for (this_ident = ident_names;
- this_ident && *this_ident;
- this_ident = multi_string_next(this_ident)) {
- khm_handle ident;
-
- if (KHM_FAILED(kcdb_identity_create(this_ident, 0,
- &ident)))
- continue;
-
- khm_cred_renew_identity(ident);
-
- kcdb_identity_release(ident);
- }
-
- PFREE(ident_names);
- ident_names = NULL;
- }
-}
-
-void khm_cred_renew_identity(khm_handle identity)
-{
- khui_new_creds * c;
-
- khui_cw_create_cred_blob(&c);
-
- c->subtype = KMSG_CRED_RENEW_CREDS;
- c->result = KHUI_NC_RESULT_PROCESS;
- khui_context_create(&c->ctx,
- KHUI_SCOPE_IDENT,
- identity,
- KCDB_CREDTYPE_INVALID,
- NULL);
-
- _begin_task(KHERR_CF_TRANSITIVE);
- _report_sr0(KHERR_NONE, IDS_CTX_RENEW_CREDS);
- _describe();
-
- /* if we are calling this while processing startup actions, we
- need to keep track of how many we have issued. */
- if (khm_startup.processing) {
- InterlockedIncrement(&khm_startup.pending_renewals);
- }
-
- kmq_post_message(KMSG_CRED, KMSG_CRED_RENEW_CREDS, 0, (void *) c);
-
- _end_task();
-}
-
-void khm_cred_renew_cred(khm_handle cred)
-{
- khui_new_creds * c;
-
- khui_cw_create_cred_blob(&c);
-
- c->subtype = KMSG_CRED_RENEW_CREDS;
- c->result = KHUI_NC_RESULT_PROCESS;
- khui_context_create(&c->ctx,
- KHUI_SCOPE_CRED,
- NULL,
- KCDB_CREDTYPE_INVALID,
- cred);
-
- _begin_task(KHERR_CF_TRANSITIVE);
- _report_sr0(KHERR_NONE, IDS_CTX_RENEW_CREDS);
- _describe();
-
- /* if we are calling this while processing startup actions, we
- need to keep track of how many we have issued. */
- if (khm_startup.processing) {
- InterlockedIncrement(&khm_startup.pending_renewals);
- }
-
- kmq_post_message(KMSG_CRED, KMSG_CRED_RENEW_CREDS, 0, (void *) c);
-
- _end_task();
-}
-
-void khm_cred_renew_creds(void)
-{
- khui_new_creds * c;
-
- khui_cw_create_cred_blob(&c);
- c->subtype = KMSG_CRED_RENEW_CREDS;
- c->result = KHUI_NC_RESULT_PROCESS;
- khui_context_get(&c->ctx);
-
- _begin_task(KHERR_CF_TRANSITIVE);
- _report_sr0(KHERR_NONE, IDS_CTX_RENEW_CREDS);
- _describe();
-
- /* if we are calling this while processing startup actions, we
- need to keep track of how many we have issued. */
- if (khm_startup.processing) {
- InterlockedIncrement(&khm_startup.pending_renewals);
- }
-
- kmq_post_message(KMSG_CRED, KMSG_CRED_RENEW_CREDS, 0, (void *) c);
-
- _end_task();
-}
-
-void khm_cred_change_password(wchar_t * title)
-{
- khui_new_creds * nc;
- LPNETID_DLGINFO pdlginfo;
- khm_size cb;
-
- if (!khm_cred_begin_dialog())
- return;
-
- khui_cw_create_cred_blob(&nc);
- nc->subtype = KMSG_CRED_PASSWORD;
- dialog_nc = nc;
-
- khui_context_get(&nc->ctx);
-
- kcdb_identpro_get_ui_cb((void *) &nc->ident_cb);
-
- assert(nc->ident_cb);
-
- if (title) {
-
- if (SUCCEEDED(StringCbLength(title, KHUI_MAXCB_TITLE, &cb))) {
- cb += sizeof(wchar_t);
-
- nc->window_title = PMALLOC(cb);
-#ifdef DEBUG
- assert(nc->window_title);
-#endif
- StringCbCopy(nc->window_title, cb, title);
- }
- } else if (nc->ctx.cb_vparam == sizeof(NETID_DLGINFO) &&
- (pdlginfo = nc->ctx.vparam) &&
- pdlginfo->size == NETID_DLGINFO_V1_SZ &&
- pdlginfo->in.title[0] &&
- SUCCEEDED(StringCchLength(pdlginfo->in.title,
- NETID_TITLE_SZ,
- &cb))) {
-
- cb = (cb + 1) * sizeof(wchar_t);
- nc->window_title = PMALLOC(cb);
-#ifdef DEBUG
- assert(nc->window_title);
-#endif
- StringCbCopy(nc->window_title, cb, pdlginfo->in.title);
- }
-
- khm_create_newcredwnd(khm_hwnd_main, nc);
-
- if (nc->hwnd != NULL) {
- _begin_task(KHERR_CF_TRANSITIVE);
- _report_sr0(KHERR_NONE, IDS_CTX_PASSWORD);
- _describe();
-
- kmq_post_message(KMSG_CRED, KMSG_CRED_PASSWORD, 0,
- (void *) nc);
-
- _end_task();
- } else {
- khui_cw_destroy_cred_blob(nc);
- }
-}
-
-void
-khm_cred_obtain_new_creds_for_ident(khm_handle ident, wchar_t * title)
-{
- khui_action_context ctx;
-
- if (ident == NULL)
- khm_cred_obtain_new_creds(title);
-
- khui_context_get(&ctx);
-
- khui_context_set(KHUI_SCOPE_IDENT,
- ident,
- KCDB_CREDTYPE_INVALID,
- NULL,
- NULL,
- 0,
- NULL);
-
- khm_cred_obtain_new_creds(title);
-
- khui_context_set_indirect(&ctx);
-
- khui_context_release(&ctx);
-}
-
-void khm_cred_obtain_new_creds(wchar_t * title)
-{
- khui_new_creds * nc;
- LPNETID_DLGINFO pdlginfo;
- khm_size cb;
-
- if (!khm_cred_begin_dialog())
- return;
-
- khui_cw_create_cred_blob(&nc);
- nc->subtype = KMSG_CRED_NEW_CREDS;
- dialog_nc = nc;
-
- khui_context_get(&nc->ctx);
-
- kcdb_identpro_get_ui_cb((void *) &nc->ident_cb);
-
- if (nc->ident_cb == NULL) {
- wchar_t title[256];
- wchar_t msg[512];
- wchar_t suggestion[512];
- khui_alert * a;
-
- LoadString(khm_hInstance, IDS_ERR_TITLE_NO_IDENTPRO,
- title, ARRAYLENGTH(title));
- LoadString(khm_hInstance, IDS_ERR_MSG_NO_IDENTPRO,
- msg, ARRAYLENGTH(msg));
- LoadString(khm_hInstance, IDS_ERR_SUGG_NO_IDENTPRO,
- suggestion, ARRAYLENGTH(suggestion));
-
- khui_alert_create_simple(title,
- msg,
- KHERR_ERROR,
- &a);
- khui_alert_set_suggestion(a, suggestion);
-
- khui_alert_show(a);
-
- khui_alert_release(a);
-
- khui_context_release(&nc->ctx);
- nc->result = KHUI_NC_RESULT_CANCEL;
- khm_cred_end_dialog(nc);
- khui_cw_destroy_cred_blob(nc);
- return;
- }
-
- if (title) {
- if (SUCCEEDED(StringCbLength(title, KHUI_MAXCB_TITLE, &cb))) {
- cb += sizeof(wchar_t);
-
- nc->window_title = PMALLOC(cb);
-#ifdef DEBUG
- assert(nc->window_title);
-#endif
- StringCbCopy(nc->window_title, cb, title);
- }
- } else if (nc->ctx.cb_vparam == sizeof(NETID_DLGINFO) &&
- (pdlginfo = nc->ctx.vparam) &&
- pdlginfo->size == NETID_DLGINFO_V1_SZ &&
- pdlginfo->in.title[0] &&
- SUCCEEDED(StringCchLength(pdlginfo->in.title,
- NETID_TITLE_SZ,
- &cb))) {
-
- cb = (cb + 1) * sizeof(wchar_t);
- nc->window_title = PMALLOC(cb);
-#ifdef DEBUG
- assert(nc->window_title);
-#endif
- StringCbCopy(nc->window_title, cb, pdlginfo->in.title);
- }
-
- khm_create_newcredwnd(khm_hwnd_main, nc);
-
- if (nc->hwnd != NULL) {
- _begin_task(KHERR_CF_TRANSITIVE);
- _report_sr0(KHERR_NONE, IDS_CTX_NEW_CREDS);
- _describe();
-
- kmq_post_message(KMSG_CRED, KMSG_CRED_NEW_CREDS, 0,
- (void *) nc);
-
- _end_task();
- } else {
- khui_context_release(&nc->ctx);
- nc->result = KHUI_NC_RESULT_CANCEL;
- khm_cred_end_dialog(nc);
- khui_cw_destroy_cred_blob(nc);
- }
-}
-
-/* this is called by khm_cred_dispatch_process_message and the
- kmsg_cred_completion to initiate and continue checked broadcasts of
- KMSG_CRED_DIALOG_PROCESS messages.
-
- Returns TRUE if more KMSG_CRED_DIALOG_PROCESS messages were
- posted. */
-BOOL khm_cred_dispatch_process_level(khui_new_creds *nc)
-{
- khm_size i,j;
- khm_handle subs[KHUI_MAX_NCTYPES];
- int n_subs = 0;
- BOOL cont = FALSE;
- khui_new_creds_by_type *t, *d;
-
- /* at each level, we dispatch a wave of notifications to plug-ins
- who's dependencies are all satisfied */
- EnterCriticalSection(&nc->cs);
-
- /* if any types have already completed, we mark them are processed
- and skip them */
- for (i=0; i < nc->n_types; i++) {
- t = nc->types[i];
- if(t->flags & KHUI_NC_RESPONSE_COMPLETED)
- t->flags |= KHUI_NCT_FLAG_PROCESSED;
- }
-
- for(i=0; i<nc->n_types; i++) {
- t = nc->types[i];
-
- if((t->flags & KHUI_NCT_FLAG_PROCESSED) ||
- (t->flags & KHUI_NC_RESPONSE_COMPLETED))
- continue;
-
- for(j=0; j<t->n_type_deps; j++) {
- if(KHM_FAILED(khui_cw_find_type(nc, t->type_deps[j], &d)))
- break;
-
- if(!(d->flags & KHUI_NC_RESPONSE_COMPLETED))
- break;
- }
-
- if(j<t->n_type_deps) /* there are unmet dependencies */
- continue;
-
- /* all dependencies for this type have been met. */
- subs[n_subs++] = kcdb_credtype_get_sub(t->type);
- t->flags |= KHUI_NCT_FLAG_PROCESSED;
- cont = TRUE;
- }
-
- LeaveCriticalSection(&nc->cs);
-
- /* the reason why we are posting messages in batches is because
- when the message has completed we know that all the types that
- have the KHUI_NCT_FLAG_PROCESSED set have completed processing.
- Otherwise we have to individually track each message and update
- the type */
- if(n_subs > 0)
- kmq_post_subs_msg(subs, n_subs, KMSG_CRED, KMSG_CRED_PROCESS, 0,
- (void *) nc);
-
- return cont;
-}
-
-void
-khm_cred_dispatch_process_message(khui_new_creds *nc)
-{
- khm_size i;
- BOOL pending;
- wchar_t wsinsert[512];
- khm_size cbsize;
-
- /* see if there's anything to do. We can check this without
- obtaining a lock */
- if(nc->n_types == 0 ||
- (nc->subtype == KMSG_CRED_NEW_CREDS &&
- nc->n_identities == 0) ||
- (nc->subtype == KMSG_CRED_PASSWORD &&
- nc->n_identities == 0))
- goto _terminate_job;
-
- /* check dependencies and stuff first */
- EnterCriticalSection(&nc->cs);
- for(i=0; i<nc->n_types; i++) {
- nc->types[i]->flags &= ~ KHUI_NCT_FLAG_PROCESSED;
- }
- LeaveCriticalSection(&nc->cs);
-
- /* Consindering all that can go wrong here and the desire to
- handle errors here separately from others, we create a new task
- for the purpose of tracking the credentials acquisition
- process. */
- _begin_task(KHERR_CF_TRANSITIVE);
-
- /* Describe the context */
- if(nc->subtype == KMSG_CRED_NEW_CREDS) {
- cbsize = sizeof(wsinsert);
- kcdb_identity_get_name(nc->identities[0], wsinsert, &cbsize);
-
- _report_sr1(KHERR_NONE, IDS_CTX_PROC_NEW_CREDS,
- _cstr(wsinsert));
- _resolve();
- } else if (nc->subtype == KMSG_CRED_RENEW_CREDS) {
- cbsize = sizeof(wsinsert);
-
- if (nc->ctx.scope == KHUI_SCOPE_IDENT)
- kcdb_identity_get_name(nc->ctx.identity, wsinsert, &cbsize);
- else if (nc->ctx.scope == KHUI_SCOPE_CREDTYPE) {
- if (nc->ctx.identity != NULL)
- kcdb_identity_get_name(nc->ctx.identity, wsinsert,
- &cbsize);
- else
- kcdb_credtype_get_name(nc->ctx.cred_type, wsinsert,
- &cbsize);
- } else if (nc->ctx.scope == KHUI_SCOPE_CRED) {
- kcdb_cred_get_name(nc->ctx.cred, wsinsert, &cbsize);
- } else {
- StringCbCopy(wsinsert, sizeof(wsinsert), L"(?)");
- }
-
- _report_sr1(KHERR_NONE, IDS_CTX_PROC_RENEW_CREDS,
- _cstr(wsinsert));
- _resolve();
- } else if (nc->subtype == KMSG_CRED_PASSWORD) {
- cbsize = sizeof(wsinsert);
- kcdb_identity_get_name(nc->identities[0], wsinsert, &cbsize);
-
- _report_sr1(KHERR_NONE, IDS_CTX_PROC_PASSWORD,
- _cstr(wsinsert));
- _resolve();
- } else {
- assert(FALSE);
- }
-
- _describe();
-
- pending = khm_cred_dispatch_process_level(nc);
-
- _end_task();
-
- if(!pending)
- goto _terminate_job;
-
- return;
-
- _terminate_job:
- if (nc->subtype == KMSG_CRED_RENEW_CREDS)
- kmq_post_message(KMSG_CRED, KMSG_CRED_END, 0, (void *) nc);
- else
- PostMessage(nc->hwnd, KHUI_WM_NC_NOTIFY,
- MAKEWPARAM(0, WMNC_DIALOG_PROCESS_COMPLETE), 0);
-}
-
-void
-khm_cred_process_startup_actions(void) {
- khm_handle defident = NULL;
-
- if (!khm_startup.processing)
- return;
-
- if (khm_startup.init ||
- khm_startup.renew ||
- khm_startup.destroy ||
- khm_startup.autoinit) {
- kcdb_identity_get_default(&defident);
- }
-
- /* For asynchronous actions, we trigger the action and then exit
- the loop. Once the action completes, the completion handler
- will trigger a continuation message which will result in this
- function getting called again. Then we can proceed with the
- rest of the startup actions. */
- do {
- if (khm_startup.init) {
- if (defident)
- khui_context_set(KHUI_SCOPE_IDENT,
- defident,
- KCDB_CREDTYPE_INVALID,
- NULL, NULL, 0,
- NULL);
- else
- khui_context_reset();
-
- khm_cred_obtain_new_creds(NULL);
- khm_startup.init = FALSE;
- break;
- }
-
- if (khm_startup.import) {
- khm_cred_import();
- khm_startup.import = FALSE;
-
- /* we also set the renew command to false here because we
- trigger a renewal for all the identities at the end of
- the import operation anyway. */
- khm_startup.renew = FALSE;
- break;
- }
-
- if (khm_startup.renew) {
- LONG pending_renewals;
-
- /* if there are no credentials, we just skip over the
- renew action. */
-
- khm_startup.renew = FALSE;
-
- InterlockedIncrement(&khm_startup.pending_renewals);
-
- khm_cred_renew_all_identities();
-
- pending_renewals = InterlockedDecrement(&khm_startup.pending_renewals);
-
- if (pending_renewals != 0)
- break;
-
- /* if there were no pending renewals, then we just fall
- through. This means that either there were no
- identities to renew, or all the renewals completed. If
- all the renewals completed, then the commandline
- contiuation message wasn't triggered. Either way, we
- must fall through if the count is zero. */
- }
-
- if (khm_startup.destroy) {
-
- khm_startup.destroy = FALSE;
-
- if (defident) {
- khui_context_set(KHUI_SCOPE_IDENT,
- defident,
- KCDB_CREDTYPE_INVALID,
- NULL, NULL, 0,
- NULL);
-
- khm_cred_destroy_creds(FALSE, FALSE);
- break;
- }
- }
-
- if (khm_startup.autoinit) {
- khm_size count = 0;
- khm_handle credset = NULL;
- khm_int32 ctype_ident = KCDB_CREDTYPE_INVALID;
- khm_int32 delta = 0;
-
- khm_startup.autoinit = FALSE;
-
- kcdb_credset_create(&credset);
- kcdb_identity_get_type(&ctype_ident);
-
- kcdb_credset_collect(credset, NULL,
- defident, ctype_ident,
- &delta);
-
- kcdb_credset_get_size(credset, &count);
-
- kcdb_credset_delete(credset);
-
- if (count == 0) {
- if (defident)
- khui_context_set(KHUI_SCOPE_IDENT,
- defident,
- KCDB_CREDTYPE_INVALID,
- NULL, NULL, 0,
- NULL);
- else
- khui_context_reset();
-
- khm_cred_obtain_new_creds(NULL);
- break;
- }
- }
-
- if (khm_startup.exit) {
- PostMessage(khm_hwnd_main,
- WM_COMMAND,
- MAKEWPARAM(KHUI_ACTION_EXIT, 0), 0);
- khm_startup.exit = FALSE;
- break;
- }
-
- /* when we get here, then we are all done with the command
- line stuff */
- khm_startup.processing = FALSE;
- khm_startup.remote = FALSE;
-
- kmq_post_message(KMSG_ACT, KMSG_ACT_END_CMDLINE, 0, 0);
- } while(FALSE);
-
- if (defident)
- kcdb_identity_release(defident);
-}
-
-void
-khm_cred_begin_startup_actions(void) {
- khm_handle csp_cw;
-
- if (khm_startup.seen)
- return;
-
- if (!khm_startup.remote &&
- KHM_SUCCEEDED(khc_open_space(NULL, L"CredWindow", 0, &csp_cw))) {
-
- khm_int32 t = 0;
-
- khc_read_int32(csp_cw, L"Autoinit", &t);
- if (t)
- khm_startup.autoinit = TRUE;
-
- t = 0;
- khc_read_int32(csp_cw, L"AutoImport", &t);
- if (t)
- khm_startup.import = TRUE;
-
- khc_close_space(csp_cw);
-
- }
-
- khm_startup.seen = TRUE;
- khm_startup.processing = TRUE;
-
- khm_cred_process_startup_actions();
-}
-
-void
-khm_cred_refresh(void) {
- kmq_post_message(KMSG_CRED, KMSG_CRED_REFRESH, 0, NULL);
-}
-
-void
-khm_cred_addr_change(void) {
- khm_handle csp_cw = NULL;
- khm_int32 check_net = 0;
-
- wchar_t * ids = NULL;
- wchar_t * t;
- khm_size cb;
- khm_size n_idents;
-
- FILETIME ft_now;
- FILETIME ft_exp;
- FILETIME ft_issue;
-
- if (KHM_SUCCEEDED(khc_open_space(NULL, L"CredWindow",
- 0, &csp_cw))) {
- khc_read_int32(csp_cw, L"AutoDetectNet", &check_net);
-
- khc_close_space(csp_cw);
- }
-
- if (!check_net)
- return;
-
- while(TRUE) {
- if (ids)
- PFREE(ids);
- ids = NULL;
-
- if (kcdb_identity_enum(KCDB_IDENT_FLAG_VALID |
- KCDB_IDENT_FLAG_RENEWABLE,
- KCDB_IDENT_FLAG_VALID |
- KCDB_IDENT_FLAG_RENEWABLE,
- NULL,
- &cb,
- &n_idents) != KHM_ERROR_TOO_LONG)
- break;
-
- ids = PMALLOC(cb);
-
- if (KHM_SUCCEEDED
- (kcdb_identity_enum(KCDB_IDENT_FLAG_VALID |
- KCDB_IDENT_FLAG_RENEWABLE,
- KCDB_IDENT_FLAG_VALID |
- KCDB_IDENT_FLAG_RENEWABLE,
- ids,
- &cb,
- &n_idents)))
- break;
- }
-
- if (!ids)
- return;
-
- GetSystemTimeAsFileTime(&ft_now);
-
- for (t=ids; t && *t; t = multi_string_next(t)) {
- khm_handle ident;
-
-
- if (KHM_FAILED
- (kcdb_identity_create(t, 0, &ident)))
- continue;
-
- cb = sizeof(ft_issue);
-
- if (KHM_SUCCEEDED
- (kcdb_identity_get_attr(ident, KCDB_ATTR_ISSUE, NULL,
- &ft_issue, &cb)) &&
-
- (cb = sizeof(ft_exp)) &&
- KHM_SUCCEEDED
- (kcdb_identity_get_attr(ident, KCDB_ATTR_EXPIRE, NULL,
- &ft_exp, &cb)) &&
-
- CompareFileTime(&ft_now, &ft_exp) < 0) {
-
- khm_int64 i_issue;
- khm_int64 i_exp;
- khm_int64 i_now;
-
- i_issue = FtToInt(&ft_issue);
- i_exp = FtToInt(&ft_exp);
- i_now = FtToInt(&ft_now);
-
- if (i_now > (i_issue + i_exp) / 2) {
-
- khm_cred_renew_identity(ident);
-
- }
- }
-
- kcdb_identity_release(ident);
- }
-}
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ * Copyright (c) 2007 Secure Endpoints Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<khmapp.h>
+#include<assert.h>
+
+static BOOL in_dialog = FALSE;
+static CRITICAL_SECTION cs_dialog;
+static HANDLE in_dialog_evt = NULL;
+static LONG init_dialog = 0;
+static khm_int32 dialog_result = 0;
+static wchar_t dialog_identity[KCDB_IDENT_MAXCCH_NAME];
+static khui_new_creds * dialog_nc = NULL;
+
+static void
+dialog_sync_init(void) {
+ if (InterlockedIncrement(&init_dialog) == 1) {
+#ifdef DEBUG
+ assert(in_dialog_evt == NULL);
+ assert(in_dialog == FALSE);
+#endif
+
+ InitializeCriticalSection(&cs_dialog);
+
+ in_dialog_evt = CreateEvent(NULL,
+ TRUE,
+ TRUE,
+ L"DialogCompletionEvent");
+ } else {
+ InterlockedDecrement(&init_dialog);
+ if (in_dialog_evt == NULL) {
+ Sleep(100);
+ }
+ }
+}
+
+BOOL
+khm_cred_begin_dialog(void) {
+ BOOL rv;
+
+ dialog_sync_init();
+
+ EnterCriticalSection(&cs_dialog);
+
+ if (in_dialog) {
+ rv = FALSE;
+
+ /* if a dialog is being displayed and we got a another request
+ to show one, we bring the existing one to the
+ foreground. */
+ if (dialog_nc && dialog_nc->hwnd) {
+ khm_int32 t = 0;
+
+ if (KHM_SUCCEEDED(khc_read_int32(NULL,
+ L"CredWindow\\Windows\\NewCred\\ForceToTop",
+ &t)) &&
+ t != 0) {
+
+ khm_activate_main_window();
+
+ SetWindowPos(dialog_nc->hwnd, HWND_TOP, 0, 0, 0, 0,
+ (SWP_NOMOVE | SWP_NOSIZE));
+ }
+ }
+
+ } else {
+ rv = TRUE;
+ in_dialog = TRUE;
+ ResetEvent(in_dialog_evt);
+ }
+
+ LeaveCriticalSection(&cs_dialog);
+ return rv;
+}
+
+void
+khm_cred_end_dialog(khui_new_creds * nc) {
+ dialog_sync_init();
+
+ EnterCriticalSection(&cs_dialog);
+ if (in_dialog) {
+ in_dialog = FALSE;
+ SetEvent(in_dialog_evt);
+ }
+ dialog_result = nc->result;
+#ifdef DEBUG
+ assert(dialog_nc == nc);
+#endif
+ dialog_nc = NULL;
+ if (nc->subtype == KMSG_CRED_NEW_CREDS &&
+ nc->n_identities > 0 &&
+ nc->identities[0]) {
+ khm_size cb;
+
+ cb = sizeof(dialog_identity);
+ if (KHM_FAILED(kcdb_identity_get_name(nc->identities[0],
+ dialog_identity,
+ &cb)))
+ dialog_identity[0] = 0;
+ } else {
+ dialog_identity[0] = 0;
+ }
+ LeaveCriticalSection(&cs_dialog);
+}
+
+BOOL
+khm_cred_is_in_dialog(void) {
+ BOOL rv;
+
+ dialog_sync_init();
+
+ EnterCriticalSection(&cs_dialog);
+ rv = in_dialog;
+ LeaveCriticalSection(&cs_dialog);
+
+ return rv;
+}
+
+khm_int32
+khm_cred_wait_for_dialog(DWORD timeout, khm_int32 * result,
+ wchar_t * ident, khm_size cb_ident) {
+ khm_int32 rv;
+
+ dialog_sync_init();
+
+ EnterCriticalSection(&cs_dialog);
+ if (!in_dialog)
+ rv = KHM_ERROR_NOT_FOUND;
+ else {
+ DWORD dw;
+
+ do {
+ LeaveCriticalSection(&cs_dialog);
+
+ dw = WaitForSingleObject(in_dialog_evt, timeout);
+
+ EnterCriticalSection(&cs_dialog);
+
+ if (!in_dialog) {
+ rv = KHM_ERROR_SUCCESS;
+ if (result) {
+ *result = dialog_result;
+ }
+ if (ident) {
+ StringCbCopy(ident, cb_ident, dialog_identity);
+ }
+ break;
+ } else if(dw == WAIT_TIMEOUT) {
+ rv = KHM_ERROR_TIMEOUT;
+ break;
+ }
+ } while(TRUE);
+ }
+ LeaveCriticalSection(&cs_dialog);
+
+ return rv;
+}
+
+/* Completion handler for KMSG_CRED messages. We control the overall
+ logic of credentials acquisition and other operations here. Once a
+ credentials operation is triggered, each successive message
+ completion notification will be used to dispatch the messages for
+ the next step in processing the operation. */
+void KHMAPI
+kmsg_cred_completion(kmq_message *m)
+{
+ khui_new_creds * nc;
+
+#ifdef DEBUG
+ assert(m->type == KMSG_CRED);
+#else
+ if(m->type != KMSG_CRED)
+ return; /* huh? */
+#endif
+
+ switch(m->subtype) {
+ case KMSG_CRED_PASSWORD:
+ /* fallthrough */
+ case KMSG_CRED_NEW_CREDS:
+ /* Cred types have attached themselves. Trigger the next
+ phase. */
+ kmq_post_message(KMSG_CRED, KMSG_CRED_DIALOG_SETUP, 0,
+ m->vparam);
+ break;
+
+ case KMSG_CRED_RENEW_CREDS:
+ nc = (khui_new_creds *) m->vparam;
+
+ /* khm_cred_dispatch_process_message() deals with the case
+ where there are no credential types that wants to
+ participate in this operation. */
+ khm_cred_dispatch_process_message(nc);
+ break;
+
+ case KMSG_CRED_DIALOG_SETUP:
+ nc = (khui_new_creds *) m->vparam;
+
+ khm_prep_newcredwnd(nc->hwnd);
+
+ /* all the controls have been created. Now initialize them */
+ if (nc->n_types > 0) {
+ kmq_post_subs_msg(nc->type_subs,
+ nc->n_types,
+ KMSG_CRED,
+ KMSG_CRED_DIALOG_PRESTART,
+ 0,
+ m->vparam);
+ } else {
+ PostMessage(nc->hwnd, KHUI_WM_NC_NOTIFY,
+ MAKEWPARAM(0, WMNC_DIALOG_PROCESS_COMPLETE), 0);
+ }
+ break;
+
+ case KMSG_CRED_DIALOG_PRESTART:
+ /* all prestart stuff is done. Now to activate the dialog */
+ nc = (khui_new_creds *) m->vparam;
+ khm_show_newcredwnd(nc->hwnd);
+
+ kmq_post_subs_msg(nc->type_subs,
+ nc->n_types,
+ KMSG_CRED,
+ KMSG_CRED_DIALOG_START,
+ 0,
+ m->vparam);
+ /* at this point, the dialog window takes over. We let it run
+ the show until KMSG_CRED_DIALOG_END is posted by the dialog
+ procedure. */
+ break;
+
+ case KMSG_CRED_PROCESS:
+ /* a wave of these messages have completed. We should check
+ if there's more */
+ nc = (khui_new_creds *) m->vparam;
+
+ /* if we are done processing all the plug-ins, then check if
+ there were any errors reported. Otherwise we dispatch
+ another set of messages. */
+ if(!khm_cred_dispatch_process_level(nc)) {
+
+ if(kherr_is_error()) {
+ khui_alert * alert;
+ kherr_event * evt;
+ kherr_context * ctx;
+ wchar_t ws_tfmt[512];
+ wchar_t w_idname[KCDB_IDENT_MAXCCH_NAME];
+ wchar_t ws_title[ARRAYLENGTH(ws_tfmt) + KCDB_IDENT_MAXCCH_NAME];
+ khm_size cb;
+
+ /* For renewals, we suppress the error message for the
+ following case:
+
+ - The renewal was for an identity
+
+ - There are no identity credentials for the
+ identity (no credentials that have the same type
+ as the identity provider). */
+
+ if (nc->subtype == KMSG_CRED_RENEW_CREDS &&
+ nc->ctx.scope == KHUI_SCOPE_IDENT &&
+ nc->ctx.identity != NULL) {
+ khm_handle tcs = NULL; /* credential set */
+ khm_size count = 0;
+ khm_int32 id_ctype = KCDB_CREDTYPE_INVALID;
+ khm_int32 delta = 0;
+
+ kcdb_identity_get_type(&id_ctype);
+ kcdb_credset_create(&tcs);
+ kcdb_credset_collect(tcs, NULL,
+ nc->ctx.identity,
+ id_ctype,
+ &delta);
+ kcdb_credset_get_size(tcs, &count);
+ kcdb_credset_delete(tcs);
+
+ if (count == 0) {
+ goto done_with_op;
+ }
+ }
+
+ ctx = kherr_peek_context();
+ evt = kherr_get_err_event(ctx);
+ kherr_evaluate_event(evt);
+
+ khui_alert_create_empty(&alert);
+
+ if (nc->subtype == KMSG_CRED_NEW_CREDS) {
+
+ khui_alert_set_type(alert, KHUI_ALERTTYPE_ACQUIREFAIL);
+
+ cb = sizeof(w_idname);
+ if (nc->n_identities == 0 ||
+ KHM_FAILED(kcdb_identity_get_name(nc->identities[0],
+ w_idname, &cb))) {
+ /* an identity could not be determined */
+ LoadString(khm_hInstance, IDS_NC_FAILED_TITLE,
+ ws_title, ARRAYLENGTH(ws_title));
+ } else {
+ LoadString(khm_hInstance, IDS_NC_FAILED_TITLE_I,
+ ws_tfmt, ARRAYLENGTH(ws_tfmt));
+ StringCbPrintf(ws_title, sizeof(ws_title),
+ ws_tfmt, w_idname);
+ khui_alert_set_ctx(alert,
+ KHUI_SCOPE_IDENT,
+ nc->identities[0],
+ KCDB_CREDTYPE_INVALID,
+ NULL);
+ }
+
+ } else if (nc->subtype == KMSG_CRED_PASSWORD) {
+
+ khui_alert_set_type(alert, KHUI_ALERTTYPE_CHPW);
+
+ cb = sizeof(w_idname);
+ if (nc->n_identities == 0 ||
+ KHM_FAILED(kcdb_identity_get_name(nc->identities[0],
+ w_idname, &cb))) {
+ LoadString(khm_hInstance, IDS_NC_PWD_FAILED_TITLE,
+ ws_title, ARRAYLENGTH(ws_title));
+ } else {
+ LoadString(khm_hInstance, IDS_NC_PWD_FAILED_TITLE_I,
+ ws_tfmt, ARRAYLENGTH(ws_tfmt));
+ StringCbPrintf(ws_title, sizeof(ws_title),
+ ws_tfmt, w_idname);
+ khui_alert_set_ctx(alert,
+ KHUI_SCOPE_IDENT,
+ nc->identities[0],
+ KCDB_CREDTYPE_INVALID,
+ NULL);
+ }
+
+ } else if (nc->subtype == KMSG_CRED_RENEW_CREDS) {
+
+ khui_alert_set_type(alert, KHUI_ALERTTYPE_RENEWFAIL);
+
+ cb = sizeof(w_idname);
+ if (nc->ctx.identity == NULL ||
+ KHM_FAILED(kcdb_identity_get_name(nc->ctx.identity,
+ w_idname, &cb))) {
+ LoadString(khm_hInstance, IDS_NC_REN_FAILED_TITLE,
+ ws_title, ARRAYLENGTH(ws_title));
+ } else {
+ LoadString(khm_hInstance, IDS_NC_REN_FAILED_TITLE_I,
+ ws_tfmt, ARRAYLENGTH(ws_tfmt));
+ StringCbPrintf(ws_title, sizeof(ws_title),
+ ws_tfmt, w_idname);
+ khui_alert_set_ctx(alert,
+ KHUI_SCOPE_IDENT,
+ nc->ctx.identity,
+ KCDB_CREDTYPE_INVALID,
+ NULL);
+ }
+
+ } else {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ }
+
+ khui_alert_set_title(alert, ws_title);
+ khui_alert_set_severity(alert, evt->severity);
+
+ if(!evt->long_desc)
+ khui_alert_set_message(alert, evt->short_desc);
+ else
+ khui_alert_set_message(alert, evt->long_desc);
+
+ if(evt->suggestion)
+ khui_alert_set_suggestion(alert, evt->suggestion);
+
+ if (nc->subtype == KMSG_CRED_RENEW_CREDS &&
+ nc->ctx.identity != NULL) {
+
+ khm_int32 n_cmd;
+
+ n_cmd = khm_get_identity_new_creds_action(nc->ctx.identity);
+
+ if (n_cmd != 0) {
+ khui_alert_add_command(alert, n_cmd);
+ khui_alert_add_command(alert, KHUI_PACTION_CLOSE);
+
+ khui_alert_set_flags(alert, KHUI_ALERT_FLAG_DISPATCH_CMD,
+ KHUI_ALERT_FLAG_DISPATCH_CMD);
+ }
+ }
+
+ khui_alert_show(alert);
+ khui_alert_release(alert);
+
+ kherr_release_context(ctx);
+
+ kherr_clear_error();
+ }
+
+ done_with_op:
+
+ if (nc->subtype == KMSG_CRED_RENEW_CREDS) {
+ kmq_post_message(KMSG_CRED, KMSG_CRED_END, 0,
+ m->vparam);
+ } else {
+ PostMessage(nc->hwnd, KHUI_WM_NC_NOTIFY,
+ MAKEWPARAM(0, WMNC_DIALOG_PROCESS_COMPLETE),
+ 0);
+ }
+ }
+ break;
+
+ case KMSG_CRED_END:
+ /* all is done. */
+ {
+ khui_new_creds * nc;
+ khm_boolean continue_cmdline = TRUE;
+
+ nc = (khui_new_creds *) m->vparam;
+
+ if (nc->subtype == KMSG_CRED_NEW_CREDS ||
+ nc->subtype == KMSG_CRED_PASSWORD) {
+
+ khm_cred_end_dialog(nc);
+
+ } else if (nc->subtype == KMSG_CRED_RENEW_CREDS) {
+
+ /* if this is a renewal that was triggered while we
+ were processing the commandline, then we need to
+ update the pending renewal count. */
+
+ if (khm_startup.processing) {
+ LONG renewals;
+ renewals = InterlockedDecrement(&khm_startup.pending_renewals);
+
+ if (renewals != 0) {
+ continue_cmdline = FALSE;
+ }
+ }
+ }
+
+ khui_cw_destroy_cred_blob(nc);
+
+ kmq_post_message(KMSG_CRED, KMSG_CRED_REFRESH, 0, 0);
+
+ if (continue_cmdline)
+ kmq_post_message(KMSG_ACT, KMSG_ACT_CONTINUE_CMDLINE, 0, 0);
+ }
+ break;
+
+ /* property sheet stuff */
+
+ case KMSG_CRED_PP_BEGIN:
+ /* all the pages should have been added by now. Just send out
+ the precreate message */
+ kmq_post_message(KMSG_CRED, KMSG_CRED_PP_PRECREATE, 0,
+ m->vparam);
+ break;
+
+ case KMSG_CRED_PP_END:
+ kmq_post_message(KMSG_CRED, KMSG_CRED_PP_DESTROY, 0,
+ m->vparam);
+ break;
+
+ case KMSG_CRED_DESTROY_CREDS:
+#ifdef DEBUG
+ assert(m->vparam != NULL);
+#endif
+ khui_context_release((khui_action_context *) m->vparam);
+ PFREE(m->vparam);
+
+ kmq_post_message(KMSG_CRED, KMSG_CRED_REFRESH, 0, 0);
+
+ kmq_post_message(KMSG_ACT, KMSG_ACT_CONTINUE_CMDLINE, 0, 0);
+ break;
+
+ case KMSG_CRED_IMPORT:
+ {
+ khm_boolean continue_cmdline = FALSE;
+ LONG pending_renewals;
+
+ /* once an import operation ends, we have to trigger a
+ renewal so that other plug-ins that didn't participate
+ in the import operation can have a chance at getting
+ the necessary credentials.
+
+ If we are in the middle of processing the commandline,
+ we have to be a little bit careful. We can't issue a
+ commandline conituation message right now because the
+ import action is still ongoing (since the renewals are
+ part of the action). Once the renewals have completed,
+ the completion handler will automatically issue a
+ commandline continuation message. However, if there
+ were no identities to renew, then we have to issue the
+ message ourselves.
+ */
+
+ InterlockedIncrement(&khm_startup.pending_renewals);
+
+ khm_cred_renew_all_identities();
+
+ pending_renewals = InterlockedDecrement(&khm_startup.pending_renewals);
+
+ if (pending_renewals == 0 && khm_startup.processing)
+ kmq_post_message(KMSG_ACT, KMSG_ACT_CONTINUE_CMDLINE, 0, 0);
+ }
+ break;
+
+ case KMSG_CRED_REFRESH:
+ kcdb_identity_refresh_all();
+ break;
+ }
+}
+
+void khm_cred_import(void)
+{
+ _begin_task(KHERR_CF_TRANSITIVE);
+ _report_sr0(KHERR_NONE, IDS_CTX_IMPORT);
+ _describe();
+
+ kmq_post_message(KMSG_CRED, KMSG_CRED_IMPORT, 0, 0);
+
+ _end_task();
+}
+
+void khm_cred_set_default(void)
+{
+ khui_action_context ctx;
+ khm_int32 rv;
+
+ khui_context_get(&ctx);
+
+ if (ctx.identity) {
+ rv = kcdb_identity_set_default(ctx.identity);
+ }
+
+ khui_context_release(&ctx);
+}
+
+void khm_cred_destroy_creds(khm_boolean sync, khm_boolean quiet)
+{
+ khui_action_context * pctx;
+
+ pctx = PMALLOC(sizeof(*pctx));
+#ifdef DEBUG
+ assert(pctx);
+#endif
+
+ khui_context_get(pctx);
+
+ if(pctx->scope == KHUI_SCOPE_NONE && !quiet) {
+ /* this really shouldn't be necessary once we start enabling
+ and disbling actions based on context */
+ wchar_t title[256];
+ wchar_t message[256];
+
+ LoadString(khm_hInstance,
+ IDS_ALERT_NOSEL_TITLE,
+ title,
+ ARRAYLENGTH(title));
+
+ LoadString(khm_hInstance,
+ IDS_ALERT_NOSEL,
+ message,
+ ARRAYLENGTH(message));
+
+ khui_alert_show_simple(title,
+ message,
+ KHERR_WARNING);
+
+ khui_context_release(pctx);
+ PFREE(pctx);
+
+ return;
+ }
+
+ _begin_task(KHERR_CF_TRANSITIVE);
+ _report_sr0(KHERR_NONE, IDS_CTX_DESTROY_CREDS);
+ _describe();
+
+ if (sync)
+ kmq_send_message(KMSG_CRED,
+ KMSG_CRED_DESTROY_CREDS,
+ 0,
+ (void *) pctx);
+ else
+ kmq_post_message(KMSG_CRED,
+ KMSG_CRED_DESTROY_CREDS,
+ 0,
+ (void *) pctx);
+
+ _end_task();
+}
+
+void khm_cred_destroy_identity(khm_handle identity)
+{
+ khui_action_context * pctx;
+ wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
+ khm_size cb;
+
+ if (identity == NULL)
+ return;
+
+ pctx = PMALLOC(sizeof(*pctx));
+#ifdef DEBUG
+ assert(pctx);
+#endif
+
+ khui_context_create(pctx,
+ KHUI_SCOPE_IDENT,
+ identity,
+ KCDB_CREDTYPE_INVALID,
+ NULL);
+
+ cb = sizeof(idname);
+ kcdb_identity_get_name(identity, idname, &cb);
+
+ _begin_task(KHERR_CF_TRANSITIVE);
+ _report_sr1(KHERR_NONE, IDS_CTX_DESTROY_ID, _dupstr(idname));
+ _describe();
+
+ kmq_post_message(KMSG_CRED,
+ KMSG_CRED_DESTROY_CREDS,
+ 0,
+ (void *) pctx);
+
+ _end_task();
+}
+
+void khm_cred_renew_all_identities(void)
+{
+ khm_size count;
+ khm_size cb = 0;
+ khm_size n_idents = 0;
+ khm_int32 rv;
+ wchar_t * ident_names = NULL;
+ wchar_t * this_ident;
+
+ kcdb_credset_get_size(NULL, &count);
+
+ /* if there are no credentials, we just skip over the renew
+ action. */
+
+ if (count == 0)
+ return;
+
+ ident_names = NULL;
+
+ while (TRUE) {
+ if (ident_names) {
+ PFREE(ident_names);
+ ident_names = NULL;
+ }
+
+ cb = 0;
+ rv = kcdb_identity_enum(KCDB_IDENT_FLAG_EMPTY, 0,
+ NULL,
+ &cb, &n_idents);
+
+ if (n_idents == 0 || rv != KHM_ERROR_TOO_LONG ||
+ cb == 0)
+ break;
+
+ ident_names = PMALLOC(cb);
+ ident_names[0] = L'\0';
+
+ rv = kcdb_identity_enum(KCDB_IDENT_FLAG_EMPTY, 0,
+ ident_names,
+ &cb, &n_idents);
+
+ if (KHM_SUCCEEDED(rv))
+ break;
+ }
+
+ if (ident_names) {
+ for (this_ident = ident_names;
+ this_ident && *this_ident;
+ this_ident = multi_string_next(this_ident)) {
+ khm_handle ident;
+
+ if (KHM_FAILED(kcdb_identity_create(this_ident, 0,
+ &ident)))
+ continue;
+
+ khm_cred_renew_identity(ident);
+
+ kcdb_identity_release(ident);
+ }
+
+ PFREE(ident_names);
+ ident_names = NULL;
+ }
+}
+
+void khm_cred_renew_identity(khm_handle identity)
+{
+ khui_new_creds * c;
+
+ khui_cw_create_cred_blob(&c);
+
+ c->subtype = KMSG_CRED_RENEW_CREDS;
+ c->result = KHUI_NC_RESULT_PROCESS;
+ khui_context_create(&c->ctx,
+ KHUI_SCOPE_IDENT,
+ identity,
+ KCDB_CREDTYPE_INVALID,
+ NULL);
+
+ _begin_task(KHERR_CF_TRANSITIVE);
+ _report_sr0(KHERR_NONE, IDS_CTX_RENEW_CREDS);
+ _describe();
+
+ /* if we are calling this while processing startup actions, we
+ need to keep track of how many we have issued. */
+ if (khm_startup.processing) {
+ InterlockedIncrement(&khm_startup.pending_renewals);
+ }
+
+ kmq_post_message(KMSG_CRED, KMSG_CRED_RENEW_CREDS, 0, (void *) c);
+
+ _end_task();
+}
+
+void khm_cred_renew_cred(khm_handle cred)
+{
+ khui_new_creds * c;
+
+ khui_cw_create_cred_blob(&c);
+
+ c->subtype = KMSG_CRED_RENEW_CREDS;
+ c->result = KHUI_NC_RESULT_PROCESS;
+ khui_context_create(&c->ctx,
+ KHUI_SCOPE_CRED,
+ NULL,
+ KCDB_CREDTYPE_INVALID,
+ cred);
+
+ _begin_task(KHERR_CF_TRANSITIVE);
+ _report_sr0(KHERR_NONE, IDS_CTX_RENEW_CREDS);
+ _describe();
+
+ /* if we are calling this while processing startup actions, we
+ need to keep track of how many we have issued. */
+ if (khm_startup.processing) {
+ InterlockedIncrement(&khm_startup.pending_renewals);
+ }
+
+ kmq_post_message(KMSG_CRED, KMSG_CRED_RENEW_CREDS, 0, (void *) c);
+
+ _end_task();
+}
+
+void khm_cred_renew_creds(void)
+{
+ khui_new_creds * c;
+
+ khui_cw_create_cred_blob(&c);
+ c->subtype = KMSG_CRED_RENEW_CREDS;
+ c->result = KHUI_NC_RESULT_PROCESS;
+ khui_context_get(&c->ctx);
+
+ _begin_task(KHERR_CF_TRANSITIVE);
+ _report_sr0(KHERR_NONE, IDS_CTX_RENEW_CREDS);
+ _describe();
+
+ /* if we are calling this while processing startup actions, we
+ need to keep track of how many we have issued. */
+ if (khm_startup.processing) {
+ InterlockedIncrement(&khm_startup.pending_renewals);
+ }
+
+ kmq_post_message(KMSG_CRED, KMSG_CRED_RENEW_CREDS, 0, (void *) c);
+
+ _end_task();
+}
+
+void khm_cred_change_password(wchar_t * title)
+{
+ khui_new_creds * nc;
+ LPNETID_DLGINFO pdlginfo;
+ khm_size cb;
+
+ if (!khm_cred_begin_dialog())
+ return;
+
+ khui_cw_create_cred_blob(&nc);
+ nc->subtype = KMSG_CRED_PASSWORD;
+ dialog_nc = nc;
+
+ khui_context_get(&nc->ctx);
+
+ kcdb_identpro_get_ui_cb((void *) &nc->ident_cb);
+
+ assert(nc->ident_cb);
+
+ if (title) {
+
+ if (SUCCEEDED(StringCbLength(title, KHUI_MAXCB_TITLE, &cb))) {
+ cb += sizeof(wchar_t);
+
+ nc->window_title = PMALLOC(cb);
+#ifdef DEBUG
+ assert(nc->window_title);
+#endif
+ StringCbCopy(nc->window_title, cb, title);
+ }
+ } else if (nc->ctx.cb_vparam == sizeof(NETID_DLGINFO) &&
+ (pdlginfo = nc->ctx.vparam) &&
+ pdlginfo->size == NETID_DLGINFO_V1_SZ &&
+ pdlginfo->in.title[0] &&
+ SUCCEEDED(StringCchLength(pdlginfo->in.title,
+ NETID_TITLE_SZ,
+ &cb))) {
+
+ cb = (cb + 1) * sizeof(wchar_t);
+ nc->window_title = PMALLOC(cb);
+#ifdef DEBUG
+ assert(nc->window_title);
+#endif
+ StringCbCopy(nc->window_title, cb, pdlginfo->in.title);
+ }
+
+ khm_create_newcredwnd(khm_hwnd_main, nc);
+
+ if (nc->hwnd != NULL) {
+ _begin_task(KHERR_CF_TRANSITIVE);
+ _report_sr0(KHERR_NONE, IDS_CTX_PASSWORD);
+ _describe();
+
+ kmq_post_message(KMSG_CRED, KMSG_CRED_PASSWORD, 0,
+ (void *) nc);
+
+ _end_task();
+ } else {
+ khui_cw_destroy_cred_blob(nc);
+ }
+}
+
+void
+khm_cred_obtain_new_creds_for_ident(khm_handle ident, wchar_t * title)
+{
+ khui_action_context ctx;
+
+ if (ident == NULL)
+ khm_cred_obtain_new_creds(title);
+
+ khui_context_get(&ctx);
+
+ khui_context_set(KHUI_SCOPE_IDENT,
+ ident,
+ KCDB_CREDTYPE_INVALID,
+ NULL,
+ NULL,
+ 0,
+ NULL);
+
+ khm_cred_obtain_new_creds(title);
+
+ khui_context_set_indirect(&ctx);
+
+ khui_context_release(&ctx);
+}
+
+void khm_cred_obtain_new_creds(wchar_t * title)
+{
+ khui_new_creds * nc;
+ LPNETID_DLGINFO pdlginfo;
+ khm_size cb;
+
+ if (!khm_cred_begin_dialog())
+ return;
+
+ khui_cw_create_cred_blob(&nc);
+ nc->subtype = KMSG_CRED_NEW_CREDS;
+ dialog_nc = nc;
+
+ khui_context_get(&nc->ctx);
+
+ kcdb_identpro_get_ui_cb((void *) &nc->ident_cb);
+
+ if (nc->ident_cb == NULL) {
+ wchar_t title[256];
+ wchar_t msg[512];
+ wchar_t suggestion[512];
+ khui_alert * a;
+
+ LoadString(khm_hInstance, IDS_ERR_TITLE_NO_IDENTPRO,
+ title, ARRAYLENGTH(title));
+ LoadString(khm_hInstance, IDS_ERR_MSG_NO_IDENTPRO,
+ msg, ARRAYLENGTH(msg));
+ LoadString(khm_hInstance, IDS_ERR_SUGG_NO_IDENTPRO,
+ suggestion, ARRAYLENGTH(suggestion));
+
+ khui_alert_create_simple(title,
+ msg,
+ KHERR_ERROR,
+ &a);
+ khui_alert_set_suggestion(a, suggestion);
+
+ khui_alert_show(a);
+
+ khui_alert_release(a);
+
+ khui_context_release(&nc->ctx);
+ nc->result = KHUI_NC_RESULT_CANCEL;
+ khm_cred_end_dialog(nc);
+ khui_cw_destroy_cred_blob(nc);
+ return;
+ }
+
+ if (title) {
+ if (SUCCEEDED(StringCbLength(title, KHUI_MAXCB_TITLE, &cb))) {
+ cb += sizeof(wchar_t);
+
+ nc->window_title = PMALLOC(cb);
+#ifdef DEBUG
+ assert(nc->window_title);
+#endif
+ StringCbCopy(nc->window_title, cb, title);
+ }
+ } else if (nc->ctx.cb_vparam == sizeof(NETID_DLGINFO) &&
+ (pdlginfo = nc->ctx.vparam) &&
+ pdlginfo->size == NETID_DLGINFO_V1_SZ &&
+ pdlginfo->in.title[0] &&
+ SUCCEEDED(StringCchLength(pdlginfo->in.title,
+ NETID_TITLE_SZ,
+ &cb))) {
+
+ cb = (cb + 1) * sizeof(wchar_t);
+ nc->window_title = PMALLOC(cb);
+#ifdef DEBUG
+ assert(nc->window_title);
+#endif
+ StringCbCopy(nc->window_title, cb, pdlginfo->in.title);
+ }
+
+ khm_create_newcredwnd(khm_hwnd_main, nc);
+
+ if (nc->hwnd != NULL) {
+ _begin_task(KHERR_CF_TRANSITIVE);
+ _report_sr0(KHERR_NONE, IDS_CTX_NEW_CREDS);
+ _describe();
+
+ kmq_post_message(KMSG_CRED, KMSG_CRED_NEW_CREDS, 0,
+ (void *) nc);
+
+ _end_task();
+ } else {
+ khui_context_release(&nc->ctx);
+ nc->result = KHUI_NC_RESULT_CANCEL;
+ khm_cred_end_dialog(nc);
+ khui_cw_destroy_cred_blob(nc);
+ }
+}
+
+/* this is called by khm_cred_dispatch_process_message and the
+ kmsg_cred_completion to initiate and continue checked broadcasts of
+ KMSG_CRED_DIALOG_PROCESS messages.
+
+ Returns TRUE if more KMSG_CRED_DIALOG_PROCESS messages were
+ posted. */
+BOOL khm_cred_dispatch_process_level(khui_new_creds *nc)
+{
+ khm_size i,j;
+ khm_handle subs[KHUI_MAX_NCTYPES];
+ int n_subs = 0;
+ BOOL cont = FALSE;
+ khui_new_creds_by_type *t, *d;
+
+ /* at each level, we dispatch a wave of notifications to plug-ins
+ who's dependencies are all satisfied */
+ EnterCriticalSection(&nc->cs);
+
+ /* if any types have already completed, we mark them are processed
+ and skip them */
+ for (i=0; i < nc->n_types; i++) {
+ t = nc->types[i];
+ if(t->flags & KHUI_NC_RESPONSE_COMPLETED)
+ t->flags |= KHUI_NCT_FLAG_PROCESSED;
+ }
+
+ for(i=0; i<nc->n_types; i++) {
+ t = nc->types[i];
+
+ if((t->flags & KHUI_NCT_FLAG_PROCESSED) ||
+ (t->flags & KHUI_NC_RESPONSE_COMPLETED))
+ continue;
+
+ for(j=0; j<t->n_type_deps; j++) {
+ if(KHM_FAILED(khui_cw_find_type(nc, t->type_deps[j], &d)))
+ break;
+
+ if(!(d->flags & KHUI_NC_RESPONSE_COMPLETED))
+ break;
+ }
+
+ if(j<t->n_type_deps) /* there are unmet dependencies */
+ continue;
+
+ /* all dependencies for this type have been met. */
+ subs[n_subs++] = kcdb_credtype_get_sub(t->type);
+ t->flags |= KHUI_NCT_FLAG_PROCESSED;
+ cont = TRUE;
+ }
+
+ LeaveCriticalSection(&nc->cs);
+
+ /* the reason why we are posting messages in batches is because
+ when the message has completed we know that all the types that
+ have the KHUI_NCT_FLAG_PROCESSED set have completed processing.
+ Otherwise we have to individually track each message and update
+ the type */
+ if(n_subs > 0)
+ kmq_post_subs_msg(subs, n_subs, KMSG_CRED, KMSG_CRED_PROCESS, 0,
+ (void *) nc);
+
+ return cont;
+}
+
+void
+khm_cred_dispatch_process_message(khui_new_creds *nc)
+{
+ khm_size i;
+ BOOL pending;
+ wchar_t wsinsert[512];
+ khm_size cbsize;
+
+ /* see if there's anything to do. We can check this without
+ obtaining a lock */
+ if(nc->n_types == 0 ||
+ (nc->subtype == KMSG_CRED_NEW_CREDS &&
+ nc->n_identities == 0) ||
+ (nc->subtype == KMSG_CRED_PASSWORD &&
+ nc->n_identities == 0))
+ goto _terminate_job;
+
+ /* check dependencies and stuff first */
+ EnterCriticalSection(&nc->cs);
+ for(i=0; i<nc->n_types; i++) {
+ nc->types[i]->flags &= ~ KHUI_NCT_FLAG_PROCESSED;
+ }
+ LeaveCriticalSection(&nc->cs);
+
+ /* Consindering all that can go wrong here and the desire to
+ handle errors here separately from others, we create a new task
+ for the purpose of tracking the credentials acquisition
+ process. */
+ _begin_task(KHERR_CF_TRANSITIVE);
+
+ /* Describe the context */
+ if(nc->subtype == KMSG_CRED_NEW_CREDS) {
+ cbsize = sizeof(wsinsert);
+ kcdb_identity_get_name(nc->identities[0], wsinsert, &cbsize);
+
+ _report_sr1(KHERR_NONE, IDS_CTX_PROC_NEW_CREDS,
+ _cstr(wsinsert));
+ _resolve();
+ } else if (nc->subtype == KMSG_CRED_RENEW_CREDS) {
+ cbsize = sizeof(wsinsert);
+
+ if (nc->ctx.scope == KHUI_SCOPE_IDENT)
+ kcdb_identity_get_name(nc->ctx.identity, wsinsert, &cbsize);
+ else if (nc->ctx.scope == KHUI_SCOPE_CREDTYPE) {
+ if (nc->ctx.identity != NULL)
+ kcdb_identity_get_name(nc->ctx.identity, wsinsert,
+ &cbsize);
+ else
+ kcdb_credtype_get_name(nc->ctx.cred_type, wsinsert,
+ &cbsize);
+ } else if (nc->ctx.scope == KHUI_SCOPE_CRED) {
+ kcdb_cred_get_name(nc->ctx.cred, wsinsert, &cbsize);
+ } else {
+ StringCbCopy(wsinsert, sizeof(wsinsert), L"(?)");
+ }
+
+ _report_sr1(KHERR_NONE, IDS_CTX_PROC_RENEW_CREDS,
+ _cstr(wsinsert));
+ _resolve();
+ } else if (nc->subtype == KMSG_CRED_PASSWORD) {
+ cbsize = sizeof(wsinsert);
+ kcdb_identity_get_name(nc->identities[0], wsinsert, &cbsize);
+
+ _report_sr1(KHERR_NONE, IDS_CTX_PROC_PASSWORD,
+ _cstr(wsinsert));
+ _resolve();
+ } else {
+ assert(FALSE);
+ }
+
+ _describe();
+
+ pending = khm_cred_dispatch_process_level(nc);
+
+ _end_task();
+
+ if(!pending)
+ goto _terminate_job;
+
+ return;
+
+ _terminate_job:
+ if (nc->subtype == KMSG_CRED_RENEW_CREDS)
+ kmq_post_message(KMSG_CRED, KMSG_CRED_END, 0, (void *) nc);
+ else
+ PostMessage(nc->hwnd, KHUI_WM_NC_NOTIFY,
+ MAKEWPARAM(0, WMNC_DIALOG_PROCESS_COMPLETE), 0);
+}
+
+void
+khm_cred_process_startup_actions(void) {
+ khm_handle defident = NULL;
+
+ if (!khm_startup.processing)
+ return;
+
+ if (khm_startup.init ||
+ khm_startup.renew ||
+ khm_startup.destroy ||
+ khm_startup.autoinit) {
+ kcdb_identity_get_default(&defident);
+ }
+
+ /* For asynchronous actions, we trigger the action and then exit
+ the loop. Once the action completes, the completion handler
+ will trigger a continuation message which will result in this
+ function getting called again. Then we can proceed with the
+ rest of the startup actions. */
+ do {
+ if (khm_startup.init) {
+ if (defident)
+ khui_context_set(KHUI_SCOPE_IDENT,
+ defident,
+ KCDB_CREDTYPE_INVALID,
+ NULL, NULL, 0,
+ NULL);
+ else
+ khui_context_reset();
+
+ khm_cred_obtain_new_creds(NULL);
+ khm_startup.init = FALSE;
+ break;
+ }
+
+ if (khm_startup.import) {
+ khm_cred_import();
+ khm_startup.import = FALSE;
+
+ /* we also set the renew command to false here because we
+ trigger a renewal for all the identities at the end of
+ the import operation anyway. */
+ khm_startup.renew = FALSE;
+ break;
+ }
+
+ if (khm_startup.renew) {
+ LONG pending_renewals;
+
+ /* if there are no credentials, we just skip over the
+ renew action. */
+
+ khm_startup.renew = FALSE;
+
+ InterlockedIncrement(&khm_startup.pending_renewals);
+
+ khm_cred_renew_all_identities();
+
+ pending_renewals = InterlockedDecrement(&khm_startup.pending_renewals);
+
+ if (pending_renewals != 0)
+ break;
+
+ /* if there were no pending renewals, then we just fall
+ through. This means that either there were no
+ identities to renew, or all the renewals completed. If
+ all the renewals completed, then the commandline
+ contiuation message wasn't triggered. Either way, we
+ must fall through if the count is zero. */
+ }
+
+ if (khm_startup.destroy) {
+
+ khm_startup.destroy = FALSE;
+
+ if (defident) {
+ khui_context_set(KHUI_SCOPE_IDENT,
+ defident,
+ KCDB_CREDTYPE_INVALID,
+ NULL, NULL, 0,
+ NULL);
+
+ khm_cred_destroy_creds(FALSE, FALSE);
+ break;
+ }
+ }
+
+ if (khm_startup.autoinit) {
+ khm_size count = 0;
+ khm_handle credset = NULL;
+ khm_int32 ctype_ident = KCDB_CREDTYPE_INVALID;
+ khm_int32 delta = 0;
+
+ khm_startup.autoinit = FALSE;
+
+ kcdb_credset_create(&credset);
+ kcdb_identity_get_type(&ctype_ident);
+
+ kcdb_credset_collect(credset, NULL,
+ defident, ctype_ident,
+ &delta);
+
+ kcdb_credset_get_size(credset, &count);
+
+ kcdb_credset_delete(credset);
+
+ if (count == 0) {
+ if (defident)
+ khui_context_set(KHUI_SCOPE_IDENT,
+ defident,
+ KCDB_CREDTYPE_INVALID,
+ NULL, NULL, 0,
+ NULL);
+ else
+ khui_context_reset();
+
+ khm_cred_obtain_new_creds(NULL);
+ break;
+ }
+ }
+
+ if (khm_startup.exit) {
+ PostMessage(khm_hwnd_main,
+ WM_COMMAND,
+ MAKEWPARAM(KHUI_ACTION_EXIT, 0), 0);
+ khm_startup.exit = FALSE;
+ break;
+ }
+
+ /* when we get here, then we are all done with the command
+ line stuff */
+ khm_startup.processing = FALSE;
+ khm_startup.remote = FALSE;
+
+ kmq_post_message(KMSG_ACT, KMSG_ACT_END_CMDLINE, 0, 0);
+ } while(FALSE);
+
+ if (defident)
+ kcdb_identity_release(defident);
+}
+
+void
+khm_cred_begin_startup_actions(void) {
+ khm_handle csp_cw;
+
+ if (khm_startup.seen)
+ return;
+
+ if (!khm_startup.remote &&
+ KHM_SUCCEEDED(khc_open_space(NULL, L"CredWindow", 0, &csp_cw))) {
+
+ khm_int32 t = 0;
+
+ khc_read_int32(csp_cw, L"Autoinit", &t);
+ if (t)
+ khm_startup.autoinit = TRUE;
+
+ t = 0;
+ khc_read_int32(csp_cw, L"AutoImport", &t);
+ if (t)
+ khm_startup.import = TRUE;
+
+ khc_close_space(csp_cw);
+
+ }
+
+ khm_startup.seen = TRUE;
+ khm_startup.processing = TRUE;
+
+ khm_cred_process_startup_actions();
+}
+
+void
+khm_cred_refresh(void) {
+ kmq_post_message(KMSG_CRED, KMSG_CRED_REFRESH, 0, NULL);
+}
+
+void
+khm_cred_addr_change(void) {
+ khm_handle csp_cw = NULL;
+ khm_int32 check_net = 0;
+
+ wchar_t * ids = NULL;
+ wchar_t * t;
+ khm_size cb;
+ khm_size n_idents;
+
+ FILETIME ft_now;
+ FILETIME ft_exp;
+ FILETIME ft_issue;
+
+ if (KHM_SUCCEEDED(khc_open_space(NULL, L"CredWindow",
+ 0, &csp_cw))) {
+ khc_read_int32(csp_cw, L"AutoDetectNet", &check_net);
+
+ khc_close_space(csp_cw);
+ }
+
+ if (!check_net)
+ return;
+
+ while(TRUE) {
+ if (ids)
+ PFREE(ids);
+ ids = NULL;
+
+ if (kcdb_identity_enum(KCDB_IDENT_FLAG_VALID |
+ KCDB_IDENT_FLAG_RENEWABLE,
+ KCDB_IDENT_FLAG_VALID |
+ KCDB_IDENT_FLAG_RENEWABLE,
+ NULL,
+ &cb,
+ &n_idents) != KHM_ERROR_TOO_LONG)
+ break;
+
+ ids = PMALLOC(cb);
+
+ if (KHM_SUCCEEDED
+ (kcdb_identity_enum(KCDB_IDENT_FLAG_VALID |
+ KCDB_IDENT_FLAG_RENEWABLE,
+ KCDB_IDENT_FLAG_VALID |
+ KCDB_IDENT_FLAG_RENEWABLE,
+ ids,
+ &cb,
+ &n_idents)))
+ break;
+ }
+
+ if (!ids)
+ return;
+
+ GetSystemTimeAsFileTime(&ft_now);
+
+ for (t=ids; t && *t; t = multi_string_next(t)) {
+ khm_handle ident;
+
+
+ if (KHM_FAILED
+ (kcdb_identity_create(t, 0, &ident)))
+ continue;
+
+ cb = sizeof(ft_issue);
+
+ if (KHM_SUCCEEDED
+ (kcdb_identity_get_attr(ident, KCDB_ATTR_ISSUE, NULL,
+ &ft_issue, &cb)) &&
+
+ (cb = sizeof(ft_exp)) &&
+ KHM_SUCCEEDED
+ (kcdb_identity_get_attr(ident, KCDB_ATTR_EXPIRE, NULL,
+ &ft_exp, &cb)) &&
+
+ CompareFileTime(&ft_now, &ft_exp) < 0) {
+
+ khm_int64 i_issue;
+ khm_int64 i_exp;
+ khm_int64 i_now;
+
+ i_issue = FtToInt(&ft_issue);
+ i_exp = FtToInt(&ft_exp);
+ i_now = FtToInt(&ft_now);
+
+ if (i_now > (i_issue + i_exp) / 2) {
+
+ khm_cred_renew_identity(ident);
+
+ }
+ }
+
+ kcdb_identity_release(ident);
+ }
+}
diff --git a/src/windows/identity/ui/credfuncs.h b/src/windows/identity/ui/credfuncs.h
index 761cbf5062..0a4e2531a6 100644
--- a/src/windows/identity/ui/credfuncs.h
+++ b/src/windows/identity/ui/credfuncs.h
@@ -1,93 +1,93 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- * Copyright (c) 2007 Secure Endpoints Inc.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#ifndef __KHIMAIRA_CREDFUNCS_H
-#define __KHIMAIRA_CREDFUNCS_H
-
-void KHMAPI
-kmsg_cred_completion(kmq_message *m);
-
-void
-khm_cred_destroy_creds(khm_boolean sync,
- khm_boolean quiet);
-
-void
-khm_cred_destroy_identity(khm_handle identity);
-
-void
-khm_cred_renew_all_identities(void);
-
-void
-khm_cred_renew_identity(khm_handle identity);
-
-void
-khm_cred_renew_cred(khm_handle cred);
-
-void
-khm_cred_renew_creds(void);
-
-void
-khm_cred_obtain_new_creds(wchar_t * window_title);
-
-void
-khm_cred_obtain_new_creds_for_ident(khm_handle ident, wchar_t * title);
-
-void
-khm_cred_set_default(void);
-
-void
-khm_cred_change_password(wchar_t * window_title);
-
-void
-khm_cred_dispatch_process_message(khui_new_creds *nc);
-
-BOOL
-khm_cred_dispatch_process_level(khui_new_creds *nc);
-
-BOOL
-khm_cred_is_in_dialog(void);
-
-khm_int32
-khm_cred_wait_for_dialog(DWORD timeout, khm_int32 * result,
- wchar_t * ident, khm_size cb_ident);
-
-void
-khm_cred_begin_startup_actions(void);
-
-void
-khm_cred_process_startup_actions(void);
-
-void
-khm_cred_refresh(void);
-
-void
-khm_cred_addr_change(void);
-
-void
-khm_cred_import(void);
-
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ * Copyright (c) 2007 Secure Endpoints Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __KHIMAIRA_CREDFUNCS_H
+#define __KHIMAIRA_CREDFUNCS_H
+
+void KHMAPI
+kmsg_cred_completion(kmq_message *m);
+
+void
+khm_cred_destroy_creds(khm_boolean sync,
+ khm_boolean quiet);
+
+void
+khm_cred_destroy_identity(khm_handle identity);
+
+void
+khm_cred_renew_all_identities(void);
+
+void
+khm_cred_renew_identity(khm_handle identity);
+
+void
+khm_cred_renew_cred(khm_handle cred);
+
+void
+khm_cred_renew_creds(void);
+
+void
+khm_cred_obtain_new_creds(wchar_t * window_title);
+
+void
+khm_cred_obtain_new_creds_for_ident(khm_handle ident, wchar_t * title);
+
+void
+khm_cred_set_default(void);
+
+void
+khm_cred_change_password(wchar_t * window_title);
+
+void
+khm_cred_dispatch_process_message(khui_new_creds *nc);
+
+BOOL
+khm_cred_dispatch_process_level(khui_new_creds *nc);
+
+BOOL
+khm_cred_is_in_dialog(void);
+
+khm_int32
+khm_cred_wait_for_dialog(DWORD timeout, khm_int32 * result,
+ wchar_t * ident, khm_size cb_ident);
+
+void
+khm_cred_begin_startup_actions(void);
+
+void
+khm_cred_process_startup_actions(void);
+
+void
+khm_cred_refresh(void);
+
+void
+khm_cred_addr_change(void);
+
+void
+khm_cred_import(void);
+
+#endif
diff --git a/src/windows/identity/ui/credwnd.c b/src/windows/identity/ui/credwnd.c
index d72d1693e5..50e6c4efcd 100644
--- a/src/windows/identity/ui/credwnd.c
+++ b/src/windows/identity/ui/credwnd.c
@@ -1,5497 +1,5497 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<khmapp.h>
-#include<prsht.h>
-#include<assert.h>
-
-ATOM khui_credwnd_cls;
-khm_int32 khui_cw_flag_id;
-
-khm_int32 attr_to_action[KCDB_ATTR_MAX_ID + 1];
-
-void
-khm_set_cw_element_font(wchar_t * name, LOGFONT * pfont) {
- khm_handle csp_cw = NULL;
- wchar_t * element_name;
-
- if (name == NULL)
- element_name = L"FontBase";
- else
- element_name = name;
-
- if (KHM_FAILED(khc_open_space(NULL, L"CredWindow", KHM_PERM_WRITE,
- &csp_cw)))
- return;
-
- khc_write_binary(csp_cw, element_name, pfont, sizeof(LOGFONT));
-
- khc_close_space(csp_cw);
-}
-
-void
-khm_get_cw_element_font(HDC hdc, wchar_t * name, BOOL use_default, LOGFONT * pfont) {
- khm_handle csp_cw = NULL;
- khm_size cb;
- wchar_t * element_name;
- khm_boolean try_derive = FALSE;
-
- if (name == NULL)
- element_name = L"FontBase";
- else
- element_name = name;
-
- if (use_default)
- goto _use_defaults;
-
- if (KHM_FAILED(khc_open_space(NULL, L"CredWindow", 0,
- &csp_cw)))
- goto _use_defaults;
-
- cb = sizeof(LOGFONT);
- if (KHM_FAILED(khc_read_binary(csp_cw, element_name, pfont,
- &cb)) ||
- cb != sizeof(LOGFONT)) {
- try_derive = TRUE;
- }
-
- if (try_derive) {
- cb = sizeof(LOGFONT);
- if (!name ||
- KHM_FAILED(khc_read_binary(csp_cw, L"FontBase", pfont,
- &cb)) ||
- cb != sizeof(LOGFONT)) {
- khc_close_space(csp_cw);
- goto _use_defaults;
- }
-
- if (!wcscmp(name, L"FontHeaderBold") ||
- !wcscmp(name, L"FontBold")) {
-
- pfont->lfWeight = FW_BOLD;
-
- }
- }
-
- khc_close_space(csp_cw);
-
- return;
-
- _use_defaults:
-
- ZeroMemory(pfont, sizeof(*pfont));
-
- if (name == NULL) {
- LOGFONT lf = {
- -MulDiv(8, GetDeviceCaps(hdc, LOGPIXELSY), 72), 0, /* width/height */
- 0,0, /* escapement */
- FW_THIN,
- FALSE,
- FALSE,
- FALSE,
- DEFAULT_CHARSET,
- OUT_DEFAULT_PRECIS,
- CLIP_DEFAULT_PRECIS,
- DEFAULT_QUALITY,
- FF_SWISS,
- L"MS Shell Dlg"};
-
- *pfont = lf;
-
- } else if (!wcscmp(name, L"FontHeader")) {
- LOGFONT lf = {
- -MulDiv(8, GetDeviceCaps(hdc, LOGPIXELSY), 72), 0, /* width/height */
- 0,0, /* escapement */
- FW_THIN,
- FALSE,
- FALSE,
- FALSE,
- DEFAULT_CHARSET,
- OUT_DEFAULT_PRECIS,
- CLIP_DEFAULT_PRECIS,
- DEFAULT_QUALITY,
- FF_SWISS,
- L"MS Shell Dlg"};
-
- *pfont = lf;
-
- } else if (!wcscmp(name, L"FontHeaderBold")) {
- LOGFONT lf = {
- -MulDiv(8, GetDeviceCaps(hdc, LOGPIXELSY), 72), 0, /* width/height */
- 0,0, /* escapement */
- FW_BOLD,
- FALSE,
- FALSE,
- FALSE,
- DEFAULT_CHARSET,
- OUT_DEFAULT_PRECIS,
- CLIP_DEFAULT_PRECIS,
- DEFAULT_QUALITY,
- FF_SWISS,
- L"MS Shell Dlg"};
-
- *pfont = lf;
-
- } else if (!wcscmp(name, L"FontNormal")) {
- LOGFONT lf = {
- -MulDiv(8, GetDeviceCaps(hdc, LOGPIXELSY), 72), 0, /* width/height */
- 0,0, /* escapement */
- FW_THIN,
- FALSE,
- FALSE,
- FALSE,
- DEFAULT_CHARSET,
- OUT_DEFAULT_PRECIS,
- CLIP_DEFAULT_PRECIS,
- DEFAULT_QUALITY,
- FF_SWISS,
- L"MS Shell Dlg"};
-
- *pfont = lf;
-
- } else if (!wcscmp(name, L"FontBold")) {
- LOGFONT lf = {
- -MulDiv(8, GetDeviceCaps(hdc, LOGPIXELSY), 72), 0, /* width/height */
- 0,0, /* escapement */
- FW_BOLD,
- FALSE,
- FALSE,
- FALSE,
- DEFAULT_CHARSET,
- OUT_DEFAULT_PRECIS,
- CLIP_DEFAULT_PRECIS,
- DEFAULT_QUALITY,
- FF_SWISS,
- L"MS Shell Dlg"};
-
- *pfont = lf;
-
- } else {
-#ifdef DEBUG
- assert(FALSE);
-#endif
- }
-}
-
-void
-cw_refresh_attribs(HWND hwnd) {
- khm_int32 act;
- kcdb_attrib * attrib;
- khui_menu_def * menu;
- khm_int32 i;
-
- menu = khui_find_menu(KHUI_MENU_COLUMNS);
-#ifdef DEBUG
- assert(menu);
-#endif
-
- for (i=0; i <= KCDB_ATTR_MAX_ID; i++) {
- if (KHM_FAILED(kcdb_attrib_get_info(i, &attrib))) {
- if (attr_to_action[i] != 0) {
- /* the action should be removed */
- khui_menu_remove_action(menu, attr_to_action[i]);
- khui_action_delete(attr_to_action[i]);
- attr_to_action[i] = 0;
- }
- } else {
- if (attr_to_action[i] == 0 &&
- !(attrib->flags & KCDB_ATTR_FLAG_HIDDEN) &&
- (attrib->short_desc || attrib->long_desc)) {
- /* new action */
- khm_handle sub = NULL;
-
- kmq_create_hwnd_subscription(hwnd, &sub);
-
- act = khui_action_create(attrib->name,
- (attrib->short_desc?
- attrib->short_desc: attrib->long_desc),
- NULL,
- (void *)(UINT_PTR) i,
- KHUI_ACTIONTYPE_TOGGLE,
- sub);
-
- attr_to_action[i] = act;
-
- khui_menu_insert_action(menu, 5000, act, 0);
- }
-
- kcdb_attrib_release_info(attrib);
- }
- }
-}
-
-khm_int32
-cw_get_custom_attr_id(wchar_t * s)
-{
- if(!wcscmp(s, CW_CANAME_FLAGS))
- return CW_CA_FLAGS;
- if(!wcscmp(s, CW_CANAME_TYPEICON))
- return CW_CA_TYPEICON;
- return 0;
-}
-
-const wchar_t *
-cw_get_custom_attr_string(khm_int32 attr_id)
-{
- if (attr_id == CW_CA_FLAGS)
- return CW_CANAME_FLAGS;
- if (attr_id == CW_CA_TYPEICON)
- return CW_CANAME_TYPEICON;
- return NULL;
-}
-
-void
-cw_save_view(khui_credwnd_tbl * tbl, wchar_t * view_name) {
- wchar_t * col_list = NULL;
- khm_size cb_col_list;
- khm_handle csp_cw = NULL;
- khm_handle csp_views = NULL;
- khm_handle csp_view = NULL;
- khm_handle csp_cols = NULL;
- khm_size cb;
- int i;
-
- if (tbl->n_cols == 0)
- return;
-
- cb_col_list = (KCONF_MAXCB_NAME + 1) * tbl->n_cols;
-
- col_list = PMALLOC(cb_col_list);
-#ifdef DEBUG
- assert(col_list);
-#endif
-
- if (!col_list)
- goto _cleanup;
-
- multi_string_init(col_list, cb_col_list);
-
- /* if we aren't saving to a specific view, and the view has been
- customized, then we save it to "Custom_0", unless we are in the
- mini mode, in which case we save it to "Custom_1" */
- if (!view_name && (tbl->flags & KHUI_CW_TBL_CUSTVIEW)) {
- if (!(tbl->flags & KHUI_CW_TBL_EXPIDENT)) {
- view_name = L"Custom_0";
- } else {
- view_name = L"Custom_1";
- }
- }
-
- if (view_name) {
- if (KHM_FAILED(khc_open_space(NULL, L"CredWindow",
- KHM_PERM_READ | KHM_PERM_WRITE, &csp_cw)))
- goto _cleanup;
-
- if (KHM_FAILED(khc_open_space(csp_cw, L"Views", KHM_PERM_READ, &csp_views)))
- goto _cleanup;
-
- if (KHM_FAILED(khc_open_space(csp_views, view_name,
- KHM_PERM_WRITE | KHM_FLAG_CREATE,
- &csp_view)))
- goto _cleanup;
-
- /* if we are switching to a custom view, then we should mark
- that as the default. */
- if (tbl->flags & KHUI_CW_TBL_CUSTVIEW) {
- khc_write_string(csp_cw, ((!(tbl->flags & KHUI_CW_TBL_EXPIDENT))?
- L"DefaultView":
- L"DefaultViewMini"), view_name);
- }
-
- } else {
- csp_view = tbl->csp_view;
- }
-
- if (!csp_view)
- goto _cleanup;
-
- if (tbl->flags & KHUI_CW_TBL_EXPIDENT) {
- khc_write_int32(csp_view, L"ExpandedIdentity", 1);
- } else {
- khm_int32 t;
- if (KHM_SUCCEEDED(khc_read_int32(csp_view, L"ExpandedIdentity", &t)) && t)
- khc_write_int32(csp_view, L"ExpandedIdentity", 0);
- }
-
- if (tbl->flags & KHUI_CW_TBL_NOHEADER) {
- khc_write_int32(csp_view, L"NoHeader", 1);
- } else {
- khm_int32 t;
- if (KHM_SUCCEEDED(khc_read_int32(csp_view, L"NoHeader", &t)) && t)
- khc_write_int32(csp_view, L"NoHeader", 0);
- }
-
- if (KHM_FAILED(khc_open_space(csp_view, L"Columns",
- KHM_PERM_WRITE | KHM_FLAG_CREATE,
- &csp_cols)))
- goto _cleanup;
-
- for (i=0; i < tbl->n_cols; i++) {
- const wchar_t * attr_name;
- kcdb_attrib * attrib = NULL;
- khm_handle csp_col = NULL;
-
- if (tbl->cols[i].attr_id < 0) {
- attr_name = cw_get_custom_attr_string(tbl->cols[i].attr_id);
- } else {
- if (KHM_FAILED(kcdb_attrib_get_info(tbl->cols[i].attr_id,
- &attrib))) {
-#ifdef DEBUG
- assert(FALSE);
-#endif
- goto _clean_col;
- }
-
- attr_name = attrib->name;
- }
-#ifdef DEBUG
- assert(attr_name);
-#endif
-
- cb = cb_col_list;
- multi_string_append(col_list, &cb, attr_name);
-
- if (KHM_FAILED(khc_open_space(csp_cols, attr_name,
- KHM_PERM_WRITE | KHM_FLAG_CREATE,
- &csp_col)))
- goto _clean_col;
-
- khc_write_int32(csp_col, L"Width", tbl->cols[i].width);
- khc_write_int32(csp_col, L"SortIndex", tbl->cols[i].sort_index);
- khc_write_int32(csp_col, L"Flags", tbl->cols[i].flags);
-
- _clean_col:
-
- if (csp_col)
- khc_close_space(csp_col);
-
- if (attrib)
- kcdb_attrib_release_info(attrib);
- }
-
- khc_write_multi_string(csp_view, L"ColumnList", col_list);
-
- {
- khm_version v = app_version;
-
- khc_write_binary(csp_view, L"_AppVersion", &v, sizeof(v));
- }
-
- _cleanup:
-
- if (view_name) {
- if (csp_view)
- khc_close_space(csp_view);
-
- if (csp_views)
- khc_close_space(csp_views);
-
- if (csp_cw)
- khc_close_space(csp_cw);
- }
-
- if (csp_cols)
- khc_close_space(csp_cols);
-
- if (col_list)
- PFREE(col_list);
-}
-
-static COLORREF
-cw_mix_colors(COLORREF c1, COLORREF c2, int alpha) {
- int r = (GetRValue(c1) * alpha + GetRValue(c2) * (255 - alpha)) / 255;
- int g = (GetGValue(c1) * alpha + GetGValue(c2) * (255 - alpha)) / 255;
- int b = (GetBValue(c1) * alpha + GetBValue(c2) * (255 - alpha)) / 255;
-
-#ifdef DEBUG
- assert(alpha >= 0 && alpha < 256);
-#endif
-
- return RGB(r,g,b);
-}
-
-void
-cw_load_view(khui_credwnd_tbl * tbl, wchar_t * view, HWND hwnd) {
- khm_handle hc_cw = NULL;
- khm_handle hc_vs = NULL;
- khm_handle hc_v = NULL;
- khm_handle hc_cs = NULL;
- khm_handle hc_c = NULL;
- wchar_t buf[KCONF_MAXCCH_NAME];
- wchar_t * clist = NULL;
- khm_size cbsize;
- wchar_t * iter = NULL;
- int i;
- HDC hdc;
- LOGFONT log_font;
- khm_int32 t;
- const wchar_t * viewval;
- khm_boolean reopen_csp = FALSE;
-
- tbl->hwnd = hwnd;
-
- if (khm_main_wnd_mode == KHM_MAIN_WND_MINI)
- viewval = L"DefaultViewMini";
- else
- viewval = L"DefaultView";
-
- if(KHM_FAILED(khc_open_space(NULL, L"CredWindow", KHM_PERM_READ | KHM_PERM_WRITE,
- &hc_cw)))
- return;
-
- if(KHM_FAILED(khc_open_space(hc_cw, L"Views", KHM_PERM_READ, &hc_vs)))
- goto _exit;
-
- if(!view) {
- cbsize = sizeof(buf);
- if(KHM_FAILED(khc_read_string(hc_cw, viewval, buf, &cbsize)))
- goto _exit;
- view = buf;
- } else {
- khc_write_string(hc_cw, viewval, view);
- }
-
- /* in addition, if we are loading the default view, we should
- also check the appropriate menu item */
-
- if (!wcscmp(view, L"ByIdentity"))
- khui_check_radio_action(khui_find_menu(KHUI_MENU_LAYOUT),
- KHUI_ACTION_LAYOUT_ID);
- else if (!wcscmp(view, L"ByLocation"))
- khui_check_radio_action(khui_find_menu(KHUI_MENU_LAYOUT),
- KHUI_ACTION_LAYOUT_LOC);
- else if (!wcscmp(view, L"ByType"))
- khui_check_radio_action(khui_find_menu(KHUI_MENU_LAYOUT),
- KHUI_ACTION_LAYOUT_TYPE);
- else if (!wcscmp(view, L"Custom_0"))
- khui_check_radio_action(khui_find_menu(KHUI_MENU_LAYOUT),
- KHUI_ACTION_LAYOUT_CUST);
- else {
- /* do nothing */
- }
-
- kmq_post_message(KMSG_ACT, KMSG_ACT_REFRESH, 0, 0);
-
- if(KHM_FAILED(khc_open_space(hc_vs, view, 0, &hc_v)))
- goto _exit;
-
- /* view data is very sensitive to version changes. We need to
- check if this configuration data was created with this version
- of NetIDMgr. If not, we switch to using a schema handle. */
- {
- khm_version this_v = app_version;
- khm_version cfg_v;
-
- cbsize = sizeof(cfg_v);
- if (KHM_FAILED(khc_read_binary(hc_v, L"_AppVersion", &cfg_v, &cbsize)) ||
- khm_compare_version(&cfg_v, &this_v) != 0) {
-
- khc_close_space(hc_v);
-
- if (KHM_FAILED(khc_open_space(hc_vs, view, KCONF_FLAG_SCHEMA,
- &hc_v)) &&
- (wcscmp(view, L"Custom_1") ||
- KHM_FAILED(khc_open_space(hc_vs, L"CompactIdentity",
- KCONF_FLAG_SCHEMA, &hc_v)))) {
- goto _exit;
- }
-
- reopen_csp = TRUE;
- }
- }
-
- tbl->csp_view = hc_v;
-
- if(KHM_FAILED(khc_open_space(hc_v, L"Columns",
- KHM_PERM_READ | (reopen_csp ? KCONF_FLAG_SCHEMA : 0),
- &hc_cs)))
- goto _exit;
-
- cbsize = 0;
- if(khc_read_multi_string(hc_v, L"ColumnList", NULL, &cbsize) != KHM_ERROR_TOO_LONG)
- goto _exit;
-
- /* temporary */
- clist = PMALLOC(cbsize);
-
- if(KHM_FAILED(khc_read_multi_string(hc_v, L"ColumnList", clist, &cbsize)))
- goto _exit;
-
- tbl->n_cols = (int) multi_string_length_n(clist);
- tbl->n_total_cols = UBOUNDSS(tbl->n_cols,
- KHUI_CW_COL_INITIAL, KHUI_CW_COL_INCREMENT);
- tbl->cols = PMALLOC(sizeof(khui_credwnd_col) * tbl->n_total_cols);
- ZeroMemory(tbl->cols, sizeof(khui_credwnd_col) * tbl->n_total_cols);
-
- tbl->flags &= ~(KHUI_CW_TBL_CUSTVIEW | KHUI_CW_TBL_COLSKIP);
-
- if (KHM_SUCCEEDED(khc_read_int32(hc_v, L"ExpandedIdentity", &t)) && t) {
- tbl->flags |= KHUI_CW_TBL_EXPIDENT;
- } else {
- tbl->flags &= ~KHUI_CW_TBL_EXPIDENT;
- }
-
- if (KHM_SUCCEEDED(khc_read_int32(hc_v, L"NoHeader", &t)) && t) {
- tbl->flags |= KHUI_CW_TBL_NOHEADER;
- } else {
- tbl->flags &= ~KHUI_CW_TBL_NOHEADER;
- }
-
- iter = clist;
- i = 0;
- while(iter) {
- khm_int32 attr_id;
-
- attr_id = cw_get_custom_attr_id(iter);
- if(!attr_id) {
- /* a KCDB attribute */
- if(KHM_FAILED(kcdb_attrib_get_id(iter, &attr_id))) {
- tbl->flags |= KHUI_CW_TBL_COLSKIP;
- goto _skip_col;
- }
-
- if(kcdb_attrib_describe(attr_id, NULL,
- &cbsize, KCDB_TS_SHORT) != KHM_ERROR_TOO_LONG ||
- cbsize == 0) {
- tbl->flags |= KHUI_CW_TBL_COLSKIP;
- goto _skip_col;
- }
-
- tbl->cols[i].title = PMALLOC(cbsize);
- kcdb_attrib_describe(attr_id, tbl->cols[i].title, &cbsize, KCDB_TS_SHORT);
-
- if (attr_id >= 0 &&
- attr_id <= KCDB_ATTR_MAX_ID &&
- attr_to_action[attr_id]) {
- khui_check_action(attr_to_action[attr_id], TRUE);
- }
-
- } else {
- /* All current custom attributes are represented by icons,
- not names */
- tbl->cols[i].title = NULL;
- }
-
- tbl->cols[i].attr_id = attr_id;
-
- if(KHM_SUCCEEDED(khc_open_space(hc_cs, iter,
- KHM_PERM_READ | (reopen_csp ? KCONF_FLAG_SCHEMA : 0),
- &hc_c))) {
- if(KHM_FAILED(khc_read_int32(hc_c, L"Flags", &(tbl->cols[i].flags))))
- tbl->cols[i].flags = 0;
- if(KHM_FAILED(khc_read_int32(hc_c, L"Width", &(tbl->cols[i].width))))
- tbl->cols[i].width = 100;
- if(KHM_FAILED(khc_read_int32(hc_c, L"SortIndex",
- &(tbl->cols[i].sort_index))))
- tbl->cols[i].sort_index = -1;
- khc_close_space(hc_c);
- hc_c = NULL;
- } else {
- tbl->cols[i].flags = 0;
- tbl->cols[i].width = -1;
- tbl->cols[i].sort_index = -1;
- }
- i++;
-_skip_col:
- iter = multi_string_next(iter);
- }
-
- /* refresh the menus since we checked a few items */
- kmq_post_message(KMSG_ACT, KMSG_ACT_REFRESH, 0, 0);
-
- /* adjust the number of columns. We may have skipped columns due to
- inconsistencies above */
- tbl->n_cols = i;
-
- /* now that all the columns have been loaded, load the view
- parameters */
- if(KHM_FAILED(khc_read_int32(hc_v, L"PaddingHorizontal", &(tbl->hpad))))
- khc_read_int32(hc_cw, L"PaddingHorizontal", &(tbl->hpad));
- if(KHM_FAILED(khc_read_int32(hc_v, L"PaddingVertical", &(tbl->vpad))))
- khc_read_int32(hc_cw, L"PaddingVertical", &(tbl->vpad));
- if(KHM_FAILED(khc_read_int32(hc_v, L"PaddingHeader", &(tbl->hpad_h))))
- khc_read_int32(hc_cw, L"PaddingHeader", &(tbl->hpad_h));
- if(KHM_FAILED(khc_read_int32(hc_v, L"WarnThreshold", &(tbl->threshold_warn))))
- khc_read_int32(hc_cw, L"WarnThreshold", &(tbl->threshold_warn));
- if(KHM_FAILED(khc_read_int32(hc_v, L"CriticalThreshold",
- &(tbl->threshold_critical))))
- khc_read_int32(hc_cw, L"CriticalThreshold",
- &(tbl->threshold_critical));
-
- /* and the font resources and stuff */
-
- tbl->flags |= KHUI_CW_TBL_INITIALIZED | KHUI_CW_TBL_COL_DIRTY | KHUI_CW_TBL_ACTIVE;
-
- /*TODO: the graphics objects should be customizable */
-
- hdc = GetWindowDC(hwnd);
-
- khm_get_cw_element_font(hdc, L"FontHeader", FALSE, &log_font);
- tbl->hf_header = CreateFontIndirect(&log_font);
-
- if(tbl->hf_header && tbl->hwnd_header)
- SendMessage(tbl->hwnd_header, WM_SETFONT, (WPARAM) tbl->hf_header, 0);
-
- khm_get_cw_element_font(hdc, L"FontHeaderBold", FALSE, &log_font);
- tbl->hf_bold_header = CreateFontIndirect(&log_font);
-
-
- khm_get_cw_element_font(hdc, L"FontNormal", FALSE, &log_font);
- tbl->hf_normal = CreateFontIndirect(&log_font);
-
- khm_get_cw_element_font(hdc, L"FontBold", FALSE, &log_font);
- tbl->hf_bold = CreateFontIndirect(&log_font);
-
- ReleaseDC(hwnd, hdc);
-
- khui_bitmap_from_hbmp(&(tbl->kbm_logo_shade),
- LoadImage(khm_hInstance,
- MAKEINTRESOURCE(IDB_LOGO_SHADE),
- IMAGE_BITMAP,
- 0,
- 0,
- LR_DEFAULTCOLOR));
-
- {
-#define SEL_ALPHA 50
-
- COLORREF bg_s = GetSysColor(COLOR_HIGHLIGHT);
- COLORREF bg_normal = GetSysColor(COLOR_WINDOW);
- COLORREF bg_gray = RGB(240,240,240);
- COLORREF bg_hdr = RGB(240,240,240);
- COLORREF bg_hdr_warn = RGB(235,235,134);
- COLORREF bg_hdr_crit = RGB(235,184,134);
- COLORREF bg_hdr_exp = RGB(235,134,134);
- COLORREF bg_hdr_def = RGB(184,235,134);
-
- tbl->cr_normal = GetSysColor(COLOR_WINDOWTEXT);
- tbl->cr_s = GetSysColor(COLOR_WINDOWTEXT);
- tbl->cr_hdr_outline = RGB(0,0,0);
- tbl->cr_hdr_normal = GetSysColor(COLOR_WINDOWTEXT);
- tbl->cr_hdr_s = GetSysColor(COLOR_WINDOWTEXT);
- tbl->cr_hdr_gray = GetSysColor(COLOR_GRAYTEXT);
- tbl->cr_hdr_gray_s = GetSysColor(COLOR_HIGHLIGHTTEXT);
-
- if (khm_main_wnd_mode == KHM_MAIN_WND_MINI) {
- bg_hdr = bg_normal;
- tbl->cr_hdr_outline = bg_gray;
- }
-
- tbl->hb_normal = CreateSolidBrush(bg_normal);
- tbl->hb_grey = CreateSolidBrush(bg_gray);
- tbl->hb_s = CreateSolidBrush(cw_mix_colors(bg_s, bg_normal, SEL_ALPHA));
-
- tbl->hb_hdr_bg = CreateSolidBrush(bg_hdr);
- tbl->hb_hdr_bg_warn = CreateSolidBrush(bg_hdr_warn);
- tbl->hb_hdr_bg_crit = CreateSolidBrush(bg_hdr_crit);
- tbl->hb_hdr_bg_exp = CreateSolidBrush(bg_hdr_exp);
- tbl->hb_hdr_bg_def = CreateSolidBrush(bg_hdr_def);
-
- tbl->hb_hdr_bg_s = CreateSolidBrush(cw_mix_colors(bg_s, bg_hdr, SEL_ALPHA));
- tbl->hb_hdr_bg_warn_s = CreateSolidBrush(cw_mix_colors(bg_s, bg_hdr_warn, SEL_ALPHA));
- tbl->hb_hdr_bg_crit_s = CreateSolidBrush(cw_mix_colors(bg_s, bg_hdr_crit, SEL_ALPHA));
- tbl->hb_hdr_bg_exp_s = CreateSolidBrush(cw_mix_colors(bg_s, bg_hdr_exp, SEL_ALPHA));
- tbl->hb_hdr_bg_def_s = CreateSolidBrush(cw_mix_colors(bg_s, bg_hdr_def, SEL_ALPHA));
- }
-
- tbl->ilist = khui_create_ilist(KHUI_SMICON_CX, KHUI_SMICON_CY-1, 20, 8, 0);
- {
- HBITMAP hbm;
-
-#define ADD_BITMAP(i) \
- hbm = LoadImage(khm_hInstance, MAKEINTRESOURCE(i), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR); \
- if(hbm) { \
- khui_ilist_add_masked_id(tbl->ilist, hbm, KHUI_TOOLBAR_BGCOLOR, i); \
- DeleteObject(hbm); \
- }
-
- ADD_BITMAP(IDB_WDG_COLLAPSE);
- ADD_BITMAP(IDB_WDG_EXPAND);
- ADD_BITMAP(IDB_ID_SM);
- ADD_BITMAP(IDB_ID_DIS_SM);
-
- ADD_BITMAP(IDB_TK_NEW_SM);
- ADD_BITMAP(IDB_TK_REFRESH_SM);
- ADD_BITMAP(IDB_WDG_COLLAPSE_HI);
- ADD_BITMAP(IDB_WDG_EXPAND_HI);
-
- ADD_BITMAP(IDB_WDG_FLAG);
- ADD_BITMAP(IDB_WDG_CREDTYPE);
- ADD_BITMAP(IDB_FLAG_WARN);
- ADD_BITMAP(IDB_FLAG_EXPIRED);
-
- ADD_BITMAP(IDB_FLAG_CRITICAL);
- ADD_BITMAP(IDB_FLAG_RENEW);
- ADD_BITMAP(IDB_WDG_STUCK);
- ADD_BITMAP(IDB_WDG_STUCK_HI);
-
- ADD_BITMAP(IDB_WDG_STICK);
- ADD_BITMAP(IDB_WDG_STICK_HI);
- ADD_BITMAP(IDB_TK_SM);
-
-#undef ADD_BITMAP
- }
-
- if (tbl->flags & KHUI_CW_TBL_EXPIDENT) {
- tbl->hi_lg_ident = LoadImage(khm_hInstance, MAKEINTRESOURCE(IDI_MAIN_APP),
- IMAGE_ICON,
- GetSystemMetrics(SM_CXICON),
- GetSystemMetrics(SM_CYICON),
- LR_DEFAULTCOLOR);
- }
-
- tbl->cursor_row = -1;
- tbl->scr_left = 0;
- tbl->scr_top = 0;
- tbl->ext_height = 0;
- tbl->ext_width = 0;
-
- if (reopen_csp) {
- khc_close_space(hc_v);
-
- hc_v = NULL;
-
- khc_open_space(hc_vs, view, 0, &hc_v);
-
- tbl->csp_view = hc_v;
- }
-
-_exit:
- if(hc_cw)
- khc_close_space(hc_cw);
- if(hc_vs)
- khc_close_space(hc_vs);
- if(hc_cs)
- khc_close_space(hc_cs);
- if(clist)
- PFREE(clist);
- /* we leave hc_v held, because tbl->csp_view is the same handle.
- We keep that open until the view is unloaded. */
-}
-
-khui_credwnd_ident *
-cw_find_ident(khui_credwnd_tbl * tbl, khm_handle ident) {
- khm_size i;
-
- for (i=0; i < tbl->n_idents; i++) {
- if (kcdb_identity_is_equal(ident, tbl->idents[i].ident))
- break;
- }
-
- if (i < tbl->n_idents)
- return &tbl->idents[i];
- else
- return NULL;
-}
-
-khm_int32 KHMAPI
-cw_credset_iter_func(khm_handle cred, void * rock) {
- khui_credwnd_tbl * tbl = (khui_credwnd_tbl *) rock;
- khm_handle ident = NULL;
- khm_size i;
- khui_credwnd_ident * cwi = NULL;
- khm_int32 cred_credtype = KCDB_CREDTYPE_INVALID;
- khm_int32 cred_flags = 0;
-
- kcdb_cred_get_identity(cred, &ident);
-
- if (ident == NULL)
- goto _cleanup;
-
- for (i=0; i < tbl->n_idents; i++) {
- if (kcdb_identity_is_equal(ident, tbl->idents[i].ident))
- break;
- }
-
- if (i >= tbl->n_idents) {
- khm_size cb;
-
- /* need to add this one */
- if (tbl->n_idents == tbl->nc_idents) {
- tbl->nc_idents = UBOUNDSS(tbl->n_idents + 1,
- CW_IDENT_ALLOC_INCR,
- CW_IDENT_ALLOC_INCR);
-#ifdef DEBUG
- assert(tbl->nc_idents > tbl->n_idents);
-#endif
- tbl->idents = PREALLOC(tbl->idents, sizeof(tbl->idents[0]) * tbl->nc_idents);
-#ifdef DEBUG
- assert(tbl->idents);
-#endif
- ZeroMemory(&tbl->idents[tbl->n_idents],
- sizeof(tbl->idents[0]) * (tbl->nc_idents - tbl->n_idents));
- }
-
- i = tbl->n_idents;
- cwi = &tbl->idents[tbl->n_idents++];
-
- ZeroMemory(cwi, sizeof(*cwi));
-
- cwi->ident = ident;
- kcdb_identity_hold(ident);
-
- cb = sizeof(cwi->name);
- kcdb_identity_get_name(ident, cwi->name, &cb);
- }
-
- cwi = &tbl->idents[i];
-
- /* this is the first time we are seeing this identity. */
- if (cwi->credcount == 0) {
- khm_size cb;
-
- cb = sizeof(cwi->credtype);
- if (KHM_SUCCEEDED(kcdb_identity_get_attr(ident, KCDB_ATTR_TYPE, NULL,
- &cwi->credtype, &cb))) {
- cwi->credtype_name[0] = L'\0';
-
- cb = sizeof(cwi->credtype_name);
- if (KHM_FAILED(kcdb_identity_get_attr(ident, KCDB_ATTR_TYPE_NAME, NULL,
- &cwi->credtype, &cb))) {
- cb = sizeof(cwi->credtype_name);
- kcdb_credtype_describe(cwi->credtype, cwi->credtype_name,
- &cb, KCDB_TS_SHORT);
- }
- } else {
- cwi->credtype = KCDB_CREDTYPE_INVALID;
- cwi->credtype_name[0] = L'\0';
- }
-
- cb = sizeof(cwi->ft_expire);
- if (KHM_FAILED(kcdb_identity_get_attr(ident, KCDB_ATTR_EXPIRE, NULL,
- &cwi->ft_expire, &cb))) {
- cwi->ft_expire = IntToFt(0);
- }
-
- kcdb_identity_get_flags(cwi->ident, &cwi->ident_flags);
- }
-
- cwi->credcount++;
-
- kcdb_cred_get_type(cred, &cred_credtype);
- if (cred_credtype >= 0 && cred_credtype == cwi->credtype) {
- cwi->id_credcount++;
-
- kcdb_cred_get_flags(cred, &cred_flags);
- if (cred_flags & KCDB_CRED_FLAG_INITIAL) {
- cwi->init_credcount++;
- }
- }
-
- _cleanup:
- if (ident)
- kcdb_identity_release(ident);
-
- return KHM_ERROR_SUCCESS;
-}
-
-void
-cw_update_creds(khui_credwnd_tbl * tbl)
-{
- kcdb_cred_comp_field * fields;
- kcdb_cred_comp_order comp_order;
- int i;
- khm_int32 n;
- khm_int32 delta;
- khm_handle hc;
- khm_int32 flags;
-
- if(!tbl->credset) {
- if(KHM_FAILED(kcdb_credset_create(&(tbl->credset))))
- return;
- }
-
- kcdb_credset_purge(tbl->credset);
-
- kcdb_identity_refresh_all();
-
- kcdb_credset_collect(
- tbl->credset,
- NULL,
- NULL,
- KCDB_CREDTYPE_ALL,
- &delta);
-
- /* now we need to figure out how to sort the credentials */
- fields = PMALLOC(sizeof(kcdb_cred_comp_field) * tbl->n_cols);
- ZeroMemory(fields, sizeof(kcdb_cred_comp_field) * tbl->n_cols);
-
- for(i=0, n=0; i<tbl->n_cols; i++) {
- if((tbl->cols[i].flags & KHUI_CW_COL_SORT_INC) ||
- (tbl->cols[i].flags & KHUI_CW_COL_SORT_DEC) ||
- (tbl->cols[i].flags & KHUI_CW_COL_GROUP)) {
- int si;
- /* we need to sort by this column */
- si = tbl->cols[i].sort_index;
-
- if(si < 0 || si >= (int) tbl->n_cols)
- {
- /* this shouldn't happen */
- tbl->cols[i].flags &= ~(KHUI_CW_COL_SORT_INC |
- KHUI_CW_COL_SORT_DEC |
- KHUI_CW_COL_GROUP);
- continue;
- }
-
- fields[si].attrib = tbl->cols[i].attr_id;
- if(tbl->cols[i].flags & KHUI_CW_COL_SORT_DEC)
- fields[si].order = KCDB_CRED_COMP_DECREASING;
- else
- fields[si].order = KCDB_CRED_COMP_INCREASING;
-
- /* special case. if we are sorting by name, we group
- initial tickets before non-initial tickets.
-
- Also, if we are sorting by credential type name, then
- we allow the primary credential type first before
- others. */
-
- if (fields[si].attrib == KCDB_ATTR_NAME ||
- fields[si].attrib == KCDB_ATTR_TYPE_NAME)
- fields[si].order |= KCDB_CRED_COMP_INITIAL_FIRST;
-
- if(si >= n)
- n = si+1;
- }
- }
-
- /* we assume that the sort order is sane */
- /*TODO: don't assume; check if the sort order is sane */
-
- comp_order.nFields = n;
- comp_order.fields = fields;
-
- kcdb_credset_sort(tbl->credset,
- kcdb_cred_comp_generic,
- (void *) &comp_order);
-
- /* also, if new credentials were added, initialize the UI flag
- attribute to 0 */
- if(delta & KCDB_DELTA_ADD) {
- khm_size s;
-
- kcdb_credset_get_size(tbl->credset, &s);
- for(i=0;i< (int) s;i++) {
- if(KHM_FAILED(kcdb_credset_get_cred(tbl->credset,
- (khm_int32) i, &hc)))
- continue; /* lost a race */
- if(KHM_FAILED(kcdb_cred_get_attr(hc, khui_cw_flag_id, NULL,
- NULL, NULL))) {
- flags = 0;
- kcdb_cred_set_attr(hc, khui_cw_flag_id, &flags, sizeof(flags));
- }
- kcdb_cred_release(hc);
- }
- }
-
- /* refresh the per-identity information */
- for (i=0; i < (int) tbl->n_idents; i++) {
- tbl->idents[i].credcount = 0;
- tbl->idents[i].id_credcount = 0;
- tbl->idents[i].init_credcount = 0;
- }
-
- kcdb_credset_apply(tbl->credset, cw_credset_iter_func, (void *) tbl);
-
- if (fields)
- PFREE(fields);
-}
-
-void
-cw_del_outline(khui_credwnd_outline *o) {
- khui_credwnd_outline * c;
- if(!o)
- return;
-
- /* the outline object is still in a list */
- if(o->next || o->prev)
- return;
-
- if(o->header)
- PFREE(o->header);
-
- if ((o->flags & KHUI_CW_O_DATAALLOC) &&
- o->data)
- PFREE(o->data);
-
- if ((o->flags & KHUI_CW_O_RELIDENT) &&
- o->data)
- kcdb_identity_release((khm_handle) o->data);
-
- LPOP(&(o->children), &c);
- while(c) {
- cw_del_outline(c);
- LPOP(&(o->children), &c);
- }
-
- ZeroMemory(o, sizeof(*o));
- PFREE(o);
-}
-
-khui_credwnd_outline *
-cw_new_outline_node(wchar_t * heading) {
- khui_credwnd_outline * o;
- size_t cblen;
-
- o = PMALLOC(sizeof(khui_credwnd_outline));
- ZeroMemory(o, sizeof(khui_credwnd_outline));
-
- if(SUCCEEDED(StringCbLength(heading, KHUI_MAXCB_HEADING, &cblen))) {
- cblen += sizeof(wchar_t);
- o->header = PMALLOC(cblen);
- StringCbCopy(o->header, cblen, heading);
- }
- o->start = -1;
-
- return o;
-}
-
-/* buf is a handle to a credential or an identity. the kcdb_buf_*
- functions work with either. */
-khm_int32
-cw_get_buf_exp_flags(khui_credwnd_tbl * tbl, khm_handle buf)
-{
- khm_int32 flags;
- long s;
- FILETIME ft_expire;
- FILETIME ft_current;
- FILETIME ft_difference;
- khm_size cbsize;
-
- cbsize = sizeof(ft_expire);
- if(KHM_FAILED(kcdb_buf_get_attr(buf, KCDB_ATTR_EXPIRE, NULL,
- &ft_expire, &cbsize)))
- return 0;
-
- GetSystemTimeAsFileTime(&ft_current);
- ft_difference = FtSub(&ft_expire, &ft_current);
-
- s = FtIntervalToSeconds(&ft_difference);
-
- flags = 0;
- if(s < 0)
- flags = CW_EXPSTATE_EXPIRED;
- else if(s < tbl->threshold_critical)
- flags = CW_EXPSTATE_CRITICAL;
- else if(s < tbl->threshold_warn)
- flags = CW_EXPSTATE_WARN;
- else
- flags = CW_EXPSTATE_NONE;
-
- return flags;
-}
-
-void cw_update_outline(khui_credwnd_tbl * tbl);
-
-static void
-cw_update_selection_state(khui_credwnd_tbl * tbl);
-
-VOID CALLBACK
-cw_timer_proc(HWND hwnd,
- UINT uMsg,
- UINT_PTR idEvent,
- DWORD dwTime)
-{
- khui_credwnd_tbl * tbl;
- khui_credwnd_row * r;
- khm_int32 nflags;
- int nr;
- long ms;
- FILETIME ft;
- khm_size cbsize;
- int timer_set = 0;
-
- KillTimer(hwnd, idEvent);
-
- tbl = (khui_credwnd_tbl *)(LONG_PTR) GetWindowLongPtr(hwnd, 0);
- r = (khui_credwnd_row *) idEvent;
- r->flags &= ~KHUI_CW_ROW_TIMERSET;
-
- nr = (int)(r - tbl->rows);
-
- if(nr < 0 || nr >= tbl->n_rows)
- return;
-
- if(r->flags & KHUI_CW_ROW_CRED) {
-
- nflags = cw_get_buf_exp_flags(tbl, (khm_handle) r->data);
- if((r->flags & CW_EXPSTATE_MASK) != nflags) {
- /* flags have changed */
- /* the outline needs to be updated */
- cw_update_outline(tbl);
- InvalidateRect(tbl->hwnd, NULL, FALSE);
- } else {
- /* just invalidate the row */
- RECT rc,rr,ri;
-
- GetClientRect(tbl->hwnd, &rc);
- rc.top += tbl->header_height;
-
- rr = r->r_ext;
- OffsetRect(&rr, 0, tbl->header_height - tbl->scr_top);
-
- if(IntersectRect(&ri, &rc, &rr))
- InvalidateRect(tbl->hwnd, &ri, FALSE);
-
- cbsize = sizeof(ft);
- if(KHM_SUCCEEDED(kcdb_cred_get_attr((khm_handle) r->data,
- KCDB_ATTR_TIMELEFT, NULL,
- &ft, &cbsize))) {
- ms = FtIntervalMsToRepChange(&ft);
- if(ms > 0) {
- SetTimer(tbl->hwnd, (UINT_PTR) r, ms + 100, cw_timer_proc);
- timer_set = 1;
- }
- }
-
- if (timer_set)
- r->flags |= KHUI_CW_ROW_TIMERSET;
- }
- } else {
- khui_credwnd_outline * o;
- khui_credwnd_ident * cwi;
- FILETIME ft_now;
-
- o = (khui_credwnd_outline *) r->data;
-#ifdef DEBUG
- assert(r->flags & KHUI_CW_ROW_EXPVIEW);
- assert(o->attr_id == KCDB_ATTR_ID);
- assert(tbl->flags & KHUI_CW_TBL_EXPIDENT);
-#endif
-
- nflags = cw_get_buf_exp_flags(tbl, (khm_handle) o->data);
- if ((o->flags & CW_EXPSTATE_MASK) != nflags) {
- cw_update_outline(tbl);
- InvalidateRect(tbl->hwnd, NULL, FALSE);
- } else {
- RECT rc, rr, ri;
-
- GetClientRect(tbl->hwnd, &rc);
- rc.top += tbl->header_height;
-
- rr = r->r_ext;
- OffsetRect(&rr, 0, tbl->header_height - tbl->scr_top);
-
- if (IntersectRect(&ri, &rc, &rr))
- InvalidateRect(tbl->hwnd, &ri, FALSE);
-
- cwi = cw_find_ident(tbl, o->data);
-
- GetSystemTimeAsFileTime(&ft_now);
- if (CompareFileTime(&cwi->ft_expire, &ft_now) > 0) {
- ft = FtSub(&cwi->ft_expire, &ft_now);
- ms = FtIntervalMsToRepChange(&ft);
- if (ms > 0) {
- SetTimer(tbl->hwnd, (UINT_PTR) r, ms + 100, cw_timer_proc);
- timer_set = 1;
- }
- }
-
- if (timer_set)
- r->flags |= KHUI_CW_ROW_TIMERSET;
- }
- }
-}
-
-void
-cw_set_tbl_row_cred(khui_credwnd_tbl * tbl,
- int row,
- khm_handle cred,
- int col)
-{
- FILETIME ft;
- long ms;
- khm_size cbsize;
-
- if((int) tbl->n_total_rows <= row) {
- /* we need to resize the allocation */
- khui_credwnd_row * newrows;
- int newsize;
-
- newsize = UBOUNDSS(row+1,KHUI_CW_ROW_INITIAL, KHUI_CW_ROW_INCREMENT);
- newrows = PMALLOC(sizeof(khui_credwnd_row) * newsize);
- memcpy(newrows, tbl->rows, sizeof(khui_credwnd_row) * tbl->n_rows);
- PFREE(tbl->rows);
- tbl->rows = newrows;
- tbl->n_total_rows = newsize;
- }
-
- tbl->rows[row].col = col;
- tbl->rows[row].data = cred;
- tbl->rows[row].flags = KHUI_CW_ROW_CRED;
-
- /* Set any required timer events */
- cbsize = sizeof(ft);
- if(KHM_SUCCEEDED(kcdb_cred_get_attr(cred, KCDB_ATTR_TIMELEFT, NULL, &ft, &cbsize))) {
- ms = FtIntervalMsToRepChange(&ft);
- if(ms > 0) {
- SetTimer(tbl->hwnd, (UINT_PTR) &(tbl->rows[row]), ms + 100, cw_timer_proc);
- tbl->rows[row].flags |= KHUI_CW_ROW_TIMERSET;
- }
- }
-}
-
-void
-cw_set_tbl_row_header(khui_credwnd_tbl * tbl,
- int row, int col,
- khui_credwnd_outline * o)
-{
- if((int) tbl->n_total_rows <= row) {
- /* we need to resize the allocation */
- khui_credwnd_row * newrows;
- int newsize;
-
- newsize = UBOUNDSS(row+1,KHUI_CW_ROW_INITIAL, KHUI_CW_ROW_INCREMENT);
- newrows = PMALLOC(sizeof(khui_credwnd_row) * newsize);
- memcpy(newrows, tbl->rows, sizeof(khui_credwnd_row) * tbl->n_rows);
- PFREE(tbl->rows);
- tbl->rows = newrows;
- tbl->n_total_rows = newsize;
- }
-
- tbl->rows[row].col = col;
- tbl->rows[row].data = (khm_handle) o;
- tbl->rows[row].flags = KHUI_CW_ROW_HEADER;
- if(o->flags & KHUI_CW_O_SELECTED)
- tbl->rows[row].flags |= KHUI_CW_ROW_SELECTED;
-
- /* if we are showing expanded identity information, we need to set
- a timer so that we can update the identity row when the
- identity changes. */
- if ((tbl->flags & KHUI_CW_TBL_EXPIDENT) &&
- tbl->cols[col].attr_id == KCDB_ATTR_ID_NAME) {
-
- khui_credwnd_ident * cwi;
-
- tbl->rows[row].flags |= KHUI_CW_ROW_EXPVIEW;
-
- cwi = cw_find_ident(tbl, o->data);
- if (cwi && FtToInt(&cwi->ft_expire) != 0) {
- FILETIME ft;
- FILETIME ft_now;
-
- ft = cwi->ft_expire;
- GetSystemTimeAsFileTime(&ft_now);
-
- if (CompareFileTime(&ft, &ft_now) > 0) {
- long ms;
-
- ft = FtSub(&ft, &ft_now);
- ms = FtIntervalMsToRepChange(&ft);
- if (ms > 0) {
- SetTimer(tbl->hwnd, (UINT_PTR) &(tbl->rows[row]), ms + 100,
- cw_timer_proc);
- tbl->rows[row].flags |= KHUI_CW_ROW_TIMERSET;
- }
- }
- }
- }
-}
-
-static int
-iwcscmp(const void * p1, const void * p2) {
- const wchar_t * s1 = *(wchar_t **) p1;
- const wchar_t * s2 = *(wchar_t **) p2;
-
- return wcscmp(s1, s2);
-}
-
-void
-cw_update_outline(khui_credwnd_tbl * tbl)
-{
- int i,j,n_rows;
- int level;
- int visible;
- khm_size n_creds = 0;
- khm_handle prevcred = NULL;
- khm_handle thiscred = NULL;
- /* grouping[0..n_grouping-1] are the columns that we are going to
- group the display by. Say we are grouping by identity and then
- by type, then grouping[0]=col# of identity and grouping[1]=col#
- of type */
- khm_int32 * grouping = NULL;
- khui_credwnd_outline * ol = NULL;
- int n_grouping;
- wchar_t buf[256];
- khm_size cbbuf;
- khm_int32 flags;
- int selected;
- khm_int32 expstate = 0;
-
- /* this is called after calling cw_update_creds, so we assume
- that the credentials are all loaded and sorted according to
- grouping rules */
-
- /* if the columns have changed, then any outline info we have
- cached are unreliable */
- if(tbl->flags & KHUI_CW_TBL_COL_DIRTY) {
- khui_credwnd_outline * o;
- LPOP(&(tbl->outline), &o);
- while(o) {
- cw_del_outline(o);
- LPOP(&(tbl->outline), &o);
- }
- tbl->n_rows = 0;
- }
-
- /* Otherwise, we should reset the outline indices. Just the first
- level is enough */
- if (tbl->outline) {
- khui_credwnd_outline * o;
-
- o = tbl->outline;
- while(o) {
- o->start = -1;
- o = LNEXT(o);
- }
- }
-
- /* determine the grouping order */
- grouping = PMALLOC(sizeof(khm_int32) * tbl->n_cols);
- for(i=0; i < (int) tbl->n_cols; i++)
- grouping[i] = -1;
- n_grouping = 0;
-
- for(i=0; i < (int) tbl->n_cols; i++) {
- /* since cw_update_creds has run, the KHUI_CW_COL_GROUP flag
- only exists for columns that has a valid sort_index */
- if(tbl->cols[i].flags & KHUI_CW_COL_GROUP) {
- grouping[tbl->cols[i].sort_index] = i;
- if(n_grouping <= tbl->cols[i].sort_index)
- n_grouping = tbl->cols[i].sort_index + 1;
- }
- }
-
- /* if we have sorted by an index without grouping by it, we can't
- establish any grouping beyond that index. */
- for(i=0; i < n_grouping; i++) {
- if(grouping[i] == -1)
- break;
- }
- n_grouping = i;
-
- if(!tbl->rows) {
- /* we haven't allocated memory yet */
- tbl->n_total_rows = KHUI_CW_ROW_INITIAL;
- tbl->n_rows = 0;
- tbl->rows = PMALLOC(sizeof(khui_credwnd_row) * tbl->n_total_rows);
- } else {
- /* kill any pending timers */
- for(i=0; i < (int) tbl->n_rows; i++)
- if(tbl->rows[i].flags & KHUI_CW_ROW_TIMERSET)
- {
- KillTimer(tbl->hwnd, (UINT_PTR) &(tbl->rows[i]));
- tbl->rows[i].flags &= ~KHUI_CW_ROW_TIMERSET;
- }
- }
-
- if(KHM_FAILED(kcdb_credset_get_size(tbl->credset, &n_creds)))
- goto _exit;
-
- n_rows = 0;
- prevcred = NULL;
- ol = NULL;
-
- for(i=0; i < (int) n_creds; i++) {
- if(KHM_FAILED(kcdb_credset_get_cred(tbl->credset, i, &thiscred)))
- continue;
-
- /* if this credential appears to be the same as another for
- this view, we skip it. */
- if(prevcred && n_grouping > 0) {
- for(j=0; j < (int) tbl->n_cols; j++) {
- if(kcdb_creds_comp_attr(prevcred, thiscred,
- tbl->cols[j].attr_id))
- break;
- }
-
- if(j >= (int) tbl->n_cols) {
- if (n_rows > 0) {
- tbl->rows[n_rows - 1].idx_end = i;
- }
- continue;
- }
- }
-
- if(!prevcred)
- level = 0;
- else {
- for(j=0; j < n_grouping; j++) {
- /* determine the grouping level at which thiscred
- differs from prevcred */
- if(kcdb_creds_comp_attr(prevcred,thiscred,
- tbl->cols[grouping[j]].attr_id))
- break;
- }
- level = j;
- }
-
- /* now we have to walk up until we get to the parent of the
- outline level we should be in */
- while(ol && ol->level >= level) {
- ol->length = n_rows - ol->start;
- ol->idx_end = i - 1;
- ol = TPARENT(ol);
- }
-
- if(ol) {
- visible = (ol->flags & KHUI_CW_O_VISIBLE) &&
- (ol->flags & KHUI_CW_O_EXPAND);
- selected = (ol->flags & KHUI_CW_O_SELECTED);
- } else {
- visible = TRUE;
- selected = FALSE;
- }
-
- /* now ol points to an outline node at the next highest level
- or is NULL if level = 0 */
-
- for(j=level; j < n_grouping; j++) {
- khui_credwnd_outline * to;
- /* now we search for an outline object at the next level
- which matches the heading */
- cbbuf = sizeof(buf);
- buf[0] = L'\0';
- if(KHM_FAILED
- (kcdb_cred_get_attr_string(thiscred,
- tbl->cols[grouping[j]].attr_id,
- buf, &cbbuf, 0))) {
- cbbuf = sizeof(wchar_t);
- buf[0] = L'\0';
- }
-
- if(ol)
- to = TFIRSTCHILD(ol);
- else
- to = tbl->outline;
-
- while(to) {
- if(!wcscmp(buf, to->header))
- break;
- to = LNEXT(to);
- }
-
- if(to) {
- /* found it */
- ol = to;
- } else {
- /* not found. create */
- to = cw_new_outline_node(buf);
- if(ol) {
- TADDCHILD(ol, to);
- } else {
- LPUSH(&(tbl->outline), to);
- }
- ol = to;
- ol->flags = KHUI_CW_O_EXPAND;
- ol->level = j;
- ol->col = grouping[j];
-
- if(tbl->cols[grouping[j]].attr_id == KCDB_ATTR_ID_NAME) {
- khm_handle h;
- if(KHM_SUCCEEDED(kcdb_identity_create(buf, 0, &h))) {
- ol->attr_id = KCDB_ATTR_ID;
- ol->data = (void *) h;
-
- /* the outline only lasts as long as the
- credential, and the credential has a hold
- on the identity. */
- kcdb_identity_release(h);
- }
- else
- ol->data = 0;
- } else if(tbl->cols[grouping[j]].attr_id ==
- KCDB_ATTR_TYPE_NAME) {
- khm_int32 t;
-
- ol->attr_id = KCDB_ATTR_TYPE;
- if(KHM_SUCCEEDED(kcdb_cred_get_type(thiscred, &t)))
- ol->data = (void *)(ssize_t) t;
- else
- ol->data = (void *)(ssize_t) KCDB_CREDTYPE_INVALID;
- } else {
- khm_int32 rv;
- khm_int32 alt_id;
- kcdb_attrib * attrib;
-
- rv =
- kcdb_attrib_get_info(tbl->cols[grouping[j]].attr_id,
- &attrib);
- assert(KHM_SUCCEEDED(rv));
-
- if (attrib->flags & KCDB_ATTR_FLAG_ALTVIEW)
- alt_id = attrib->alt_id;
- else
- alt_id = tbl->cols[grouping[j]].attr_id;
-
- ol->attr_id = alt_id;
-
- kcdb_attrib_release_info(attrib);
-
- rv = kcdb_cred_get_attr(thiscred,
- alt_id,
- NULL,
- NULL,
- &cbbuf);
- if (rv != KHM_ERROR_TOO_LONG || cbbuf == 0) {
- ol->data = NULL;
- } else {
- ol->data = PMALLOC(cbbuf);
- assert(ol->data);
- rv = kcdb_cred_get_attr(thiscred,
- alt_id,
- NULL,
- ol->data,
- &cbbuf);
- assert(KHM_SUCCEEDED(rv));
- ol->cb_data = cbbuf;
- ol->flags |= KHUI_CW_O_DATAALLOC;
- }
- }
- }
-
- /* now ol points at the node at level j we want to be
- in */
- ol->start = n_rows;
- ol->length = 0;
- ol->idx_start = i;
- ol->idx_end = i;
- ol->flags &= ~(CW_EXPSTATE_MASK |
- KHUI_CW_O_SHOWFLAG |
- KHUI_CW_O_STICKY |
- KHUI_CW_O_EMPTY);
-
- /* if the outline node is for an identity, then we have to
- check the expiration state for the identity. */
-
- if (ol->attr_id == KCDB_ATTR_ID) {
- khm_handle ident = (khm_handle) ol->data;
-
- flags = cw_get_buf_exp_flags(tbl, ident);
-
- if (flags) {
- ol->flags |= flags;
- ol->flags |= KHUI_CW_O_SHOWFLAG;
- expstate |= flags;
- } else if (grouping[j] == tbl->n_cols - 1) {
- /* if we aren't showing any creds under this
- outline level, we should also show any
- flags. */
- ol->flags |= KHUI_CW_O_SHOWFLAG;
- }
- }
-
- if (grouping[j] == tbl->n_cols - 1) {
- ol->flags |= KHUI_CW_O_NOOUTLINE;
- } else {
- ol->flags &= ~KHUI_CW_O_NOOUTLINE;
- }
-
- if(selected) {
- ol->flags |= KHUI_CW_O_SELECTED;
- }
- if(visible) {
- cw_set_tbl_row_header(tbl, n_rows, grouping[j], ol);
- n_rows ++;
- ol->flags |= KHUI_CW_O_VISIBLE;
- } else {
- ol->flags &= ~KHUI_CW_O_VISIBLE;
- }
- visible = visible && (ol->flags & KHUI_CW_O_EXPAND);
- selected = (selected || (ol->flags & KHUI_CW_O_SELECTED));
-
- }
-
- /* we need to do this here too just in case we were already at
- the level we were supposed to be in */
- if (ol)
- visible = visible && (ol->flags & KHUI_CW_O_EXPAND);
-
- if(visible && n_grouping > 0 &&
- grouping[n_grouping - 1] < tbl->n_cols - 1) {
- khm_int32 c_flags;
-
- cw_set_tbl_row_cred(tbl, n_rows, thiscred,
- grouping[n_grouping-1]);
-
- flags = cw_get_buf_exp_flags(tbl, thiscred);
- if(flags) {
- tbl->rows[n_rows].flags |= flags;
- }
-
- kcdb_cred_get_flags(thiscred, &c_flags);
- if(selected ||
- (c_flags & KCDB_CRED_FLAG_SELECTED)) {
- tbl->rows[n_rows].flags |= KHUI_CW_ROW_SELECTED;
- }
-
- tbl->rows[n_rows].idx_start = i;
- tbl->rows[n_rows].idx_end = i;
-
- n_rows++;
- }
-
- if(prevcred)
- kcdb_cred_release(prevcred);
- prevcred = thiscred;
- }
-
- while(ol) {
- ol->length = n_rows - ol->start;
- ol->idx_end = i - 1;
- ol = TPARENT(ol);
- }
-
- if(prevcred) {
- kcdb_cred_release(prevcred);
- prevcred = NULL;
- }
-
- /* Add any default identities with no credentials and sticky
- identities that we haven't seen yet */
- if (n_grouping > 0 &&
- tbl->cols[grouping[0]].attr_id == KCDB_ATTR_ID_NAME) {
-
- khui_credwnd_outline * o;
- wchar_t * idnames = NULL;
- wchar_t * t;
- khm_size n_idents;
- khm_size cb_names;
- wchar_t ** idarray = NULL;
- int i;
-
- /* see if the defualt identity is in the list */
- {
- khm_handle id_def = NULL;
- wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
- khm_size cb;
- khm_int32 flags;
-
- if (KHM_FAILED(kcdb_identity_get_default(&id_def))) {
- goto done_with_defident;
- }
-
- kcdb_identity_get_flags(id_def, &flags);
- cb = sizeof(idname);
- kcdb_identity_get_name(id_def, idname, &cb);
-
- for (o = tbl->outline; o; o = LNEXT(o)) {
- if (!wcscmp(idname, o->header))
- break;
- }
-
- if (o == NULL) {
- o = cw_new_outline_node(idname);
- LPUSH(&tbl->outline, o);
- o->flags = KHUI_CW_O_VISIBLE | KHUI_CW_O_RELIDENT | KHUI_CW_O_EMPTY;
- o->level = 0;
- o->col = grouping[0];
- o->data = id_def;
- o->attr_id = KCDB_ATTR_ID;
- o->start = -1;
- } else {
- kcdb_identity_release(id_def);
- }
-
- if (o->start != -1)
- goto done_with_defident;
-
- if (flags & KCDB_IDENT_FLAG_STICKY)
- o->flags |= KHUI_CW_O_STICKY;
- else
- o->flags &= ~KHUI_CW_O_STICKY;
-
- o->start = n_rows;
- o->length = 1;
- o->idx_start = -1;
- o->idx_end = -1;
-
- if (grouping[0] == tbl->n_cols - 1)
- o->flags |= KHUI_CW_O_NOOUTLINE;
-
- cw_set_tbl_row_header(tbl, n_rows, grouping[0], o);
-
- n_rows ++;
-
- done_with_defident:
- ;
- }
-
- if (kcdb_identity_enum(KCDB_IDENT_FLAG_STICKY,
- KCDB_IDENT_FLAG_STICKY,
- NULL,
- &cb_names,
- &n_idents) != KHM_ERROR_TOO_LONG ||
- n_idents == 0 ||
- cb_names == 0)
- goto _cleanup_sticky;
-
- idnames = PMALLOC(cb_names);
- idarray = PMALLOC(n_idents * sizeof(*idarray));
-#ifdef DEBUG
- assert(idnames);
- assert(idarray);
-#endif
-
- if (KHM_FAILED(kcdb_identity_enum(KCDB_IDENT_FLAG_STICKY,
- KCDB_IDENT_FLAG_STICKY,
- idnames,
- &cb_names,
- &n_idents)))
- goto _cleanup_sticky;
-
- for (i=0, t=idnames; t && *t; t = multi_string_next(t), i++) {
- idarray[i] = t;
- }
-
- qsort(idarray, n_idents, sizeof(*idarray), iwcscmp);
-
- for (i=0; i < (int) n_idents; i++) {
- khm_handle h;
-
- if (KHM_FAILED(kcdb_identity_create(idarray[i],
- KCDB_IDENT_FLAG_CREATE, &h)))
- continue;
-
- for (o = tbl->outline; o; o = LNEXT(o)) {
- if (!wcscmp(idarray[i], o->header))
- break;
- }
-
- if (o) {
- /* found it */
- if (o->start != -1) /* already visible? */
- continue;
- o->flags &= KHUI_CW_O_RELIDENT;
- o->flags |= KHUI_CW_O_STICKY | KHUI_CW_O_VISIBLE | KHUI_CW_O_EMPTY;
-
- if (!kcdb_identity_is_equal(o->data, h)) {
- if (o->flags & KHUI_CW_O_RELIDENT)
- kcdb_identity_release(o->data);
- o->data = h;
- o->flags |= KHUI_CW_O_RELIDENT;
- kcdb_identity_hold(h);
- }
- } else {
- /* not found. create */
- o = cw_new_outline_node(idarray[i]);
- LPUSH(&tbl->outline, o);
- o->flags = KHUI_CW_O_STICKY | KHUI_CW_O_VISIBLE | KHUI_CW_O_EMPTY | KHUI_CW_O_RELIDENT;
- o->level = 0;
- o->col = grouping[0];
- o->data = h;
- kcdb_identity_hold(h);
- o->attr_id = KCDB_ATTR_ID;
- }
-
- if (grouping[0] == tbl->n_cols - 1)
- o->flags |= KHUI_CW_O_NOOUTLINE;
-
- kcdb_identity_release(h);
-
- o->flags &= ~KHUI_CW_O_EXPAND;
- o->start = n_rows;
- o->length = 1;
- o->idx_start = -1;
- o->idx_end = -1;
-
- cw_set_tbl_row_header(tbl, n_rows, grouping[0], o);
-
- n_rows ++;
- }
-
- _cleanup_sticky:
- if (idnames)
- PFREE(idnames);
- if (idarray)
- PFREE(idarray);
- }
-
- tbl->n_rows = n_rows;
- tbl->flags |= KHUI_CW_TBL_ROW_DIRTY;
-
- tbl->flags &= ~KHUI_CW_TBL_COL_DIRTY;
-
- if (tbl->cursor_row >= tbl->n_rows)
- tbl->cursor_row = tbl->n_rows - 1;
- if (tbl->cursor_row < 0)
- tbl->cursor_row = 0;
-_exit:
- if(grouping)
- PFREE(grouping);
-
- /* note that the expstate is derived from whether or not
- * we have expiration states set for any active identities */
- if (n_creds == 0)
- khm_notify_icon_expstate(KHM_NOTIF_EMPTY);
- else if ((expstate & CW_EXPSTATE_EXPIRED) == CW_EXPSTATE_EXPIRED)
- khm_notify_icon_expstate(KHM_NOTIF_EXP);
- else if ((expstate & CW_EXPSTATE_WARN) == CW_EXPSTATE_WARN ||
- (expstate & CW_EXPSTATE_CRITICAL) == CW_EXPSTATE_CRITICAL)
- khm_notify_icon_expstate(KHM_NOTIF_WARN);
- else
- khm_notify_icon_expstate(KHM_NOTIF_OK);
-}
-
-void
-cw_unload_view(khui_credwnd_tbl * tbl)
-{
-#define SafeDeleteObject(o) \
- do { \
- if(o) { \
- DeleteObject(o); \
- o = NULL; \
- } \
- } while(0)
-
- SafeDeleteObject(tbl->hf_header);
- SafeDeleteObject(tbl->hf_normal);
- SafeDeleteObject(tbl->hf_bold);
- SafeDeleteObject(tbl->hf_bold_header);
-
- SafeDeleteObject(tbl->hb_grey);
- SafeDeleteObject(tbl->hb_normal);
- SafeDeleteObject(tbl->hb_s);
-
- SafeDeleteObject(tbl->hb_hdr_bg);
- SafeDeleteObject(tbl->hb_hdr_bg_crit);
- SafeDeleteObject(tbl->hb_hdr_bg_exp);
- SafeDeleteObject(tbl->hb_hdr_bg_warn);
- SafeDeleteObject(tbl->hb_hdr_bg_def);
-
- SafeDeleteObject(tbl->hb_hdr_bg_s);
- SafeDeleteObject(tbl->hb_hdr_bg_crit_s);
- SafeDeleteObject(tbl->hb_hdr_bg_exp_s);
- SafeDeleteObject(tbl->hb_hdr_bg_warn_s);
- SafeDeleteObject(tbl->hb_hdr_bg_def_s);
-
-#undef SafeDeleteObject
-
- if (tbl->hi_lg_ident) {
- DestroyIcon(tbl->hi_lg_ident);
- tbl->hi_lg_ident = NULL;
- }
-
- if(tbl->credset) {
- kcdb_credset_delete(tbl->credset);
- tbl->credset = NULL;
- }
- if(tbl->ilist) {
- khui_delete_ilist(tbl->ilist);
- tbl->ilist = NULL;
- }
-
- if(tbl->cols) {
- int i;
-
- for(i=0; i < tbl->n_cols; i++) {
- if(tbl->cols[i].title)
- PFREE(tbl->cols[i].title);
- Header_DeleteItem(tbl->hwnd_header, 0);
-
- if (tbl->cols[i].attr_id >= 0 &&
- tbl->cols[i].attr_id <= KCDB_ATTR_MAX_ID &&
- attr_to_action[tbl->cols[i].attr_id]) {
-
- khui_check_action(attr_to_action[tbl->cols[i].attr_id], FALSE);
-
- }
- }
- PFREE(tbl->cols);
- tbl->cols = NULL;
- tbl->n_cols = 0;
- tbl->n_total_cols = 0;
-
- kmq_post_message(KMSG_ACT, KMSG_ACT_REFRESH, 0, 0);
- }
-
- if(tbl->rows) {
- PFREE(tbl->rows);
- tbl->rows = NULL;
- tbl->n_rows = 0;
- tbl->n_total_rows = 0;
- }
-
- khui_delete_bitmap(&tbl->kbm_logo_shade);
-
- if (tbl->csp_view) {
- khc_close_space(tbl->csp_view);
- tbl->csp_view = NULL;
- }
-
- tbl->cell_height = 0; /* recalculate cell height next time */
-
- if (tbl->idents) {
- khm_size i;
-
- for (i=0; i < tbl->n_idents; i++) {
- if (tbl->idents[i].ident) {
- kcdb_identity_release(tbl->idents[i].ident);
- }
- }
-
- PFREE(tbl->idents);
- tbl->idents = NULL;
- tbl->n_idents = 0;
- tbl->nc_idents = 0;
- }
-}
-
-void
-cw_hditem_from_tbl_col(khui_credwnd_col * col, HDITEM *phi)
-{
- size_t cchsize;
-
- phi->mask = HDI_FORMAT | HDI_LPARAM | HDI_WIDTH;
- if(cw_is_custom_attr(col->attr_id)) {
- if(col->attr_id == CW_CA_FLAGS) {
- phi->fmt = 0;
- } else if(col->attr_id == CW_CA_TYPEICON) {
- phi->fmt = 0;
- } else {
- /* what the? */
- /*TODO: throw up and die */
- }
- } else {
- phi->mask |= HDI_TEXT;
- phi->pszText = col->title;
- StringCchLength(col->title, KCDB_MAXCCH_SHORT_DESC, &cchsize);
- phi->cchTextMax = (int) cchsize;
- phi->fmt = HDF_CENTER | HDF_STRING;
- }
- phi->lParam = col->attr_id;
-#if (_WIN32_WINNT >= 0x501)
- if (IS_COMMCTL6()) {
- if(col->flags & KHUI_CW_COL_SORT_INC) {
- phi->fmt |= HDF_SORTUP;
- } else if(col->flags & KHUI_CW_COL_SORT_DEC) {
- phi->fmt |= HDF_SORTDOWN;
- }
- }
-#endif
- if(col->width < 0) {
- /*TODO: come up with a better way to handle this case */
- col->width = 200;
- }
- phi->cxy = col->width;
-}
-
-int
-cw_get_cell_height(HDC hdc, HFONT hf) {
- SIZE size;
- size_t cbbuf;
- wchar_t buf[64];
- HFONT hfold = NULL;
-
- if (hf)
- hfold = SelectFont(hdc, hf);
-
- LoadString(khm_hInstance, IDS_SAMPLE_STRING, buf, sizeof(buf)/sizeof(buf[0]));
- StringCchLength(buf, sizeof(buf)/sizeof(buf[0]), &cbbuf);
- GetTextExtentPoint32(hdc, buf, (int) cbbuf, &size);
-
- if (hf)
- SelectFont(hdc, hfold);
-
- return size.cy;
-}
-
-int
-cw_update_header_column_width(khui_credwnd_tbl * tbl, int c) {
- int idx;
- HDITEM hi;
-
-#ifdef DEBUG
- assert(c >= 0 && c < tbl->n_cols);
-#endif
-
- if (tbl->hwnd_header == NULL)
- return 0;
-
- idx = Header_OrderToIndex(tbl->hwnd_header, c);
- ZeroMemory(&hi, sizeof(hi));
- hi.mask = HDI_WIDTH;
- hi.cxy = tbl->cols[c].width;
- return Header_SetItem(tbl->hwnd_header, idx, &hi);
-}
-
-/* returns a bitmask indicating which measures were changed */
-int
-cw_update_extents(khui_credwnd_tbl * tbl,
- khm_boolean update_scroll) {
- int ext_x = 0;
- int ext_y = 0;
- int i;
- int filler_col = -1;
- int fill_adjusted = 0;
-
- recompute_columns:
-
- ext_x = 0;
- for(i=0; i < (int) tbl->n_cols; i++) {
- tbl->cols[i].x = ext_x;
- if (tbl->cols[i].flags & KHUI_CW_COL_FILLER) {
- if (filler_col == -1)
- filler_col = i;
- }
- ext_x += tbl->cols[i].width;
- }
-
- if (filler_col != -1 && !fill_adjusted) {
- RECT r;
- int delta;
-
- GetClientRect(tbl->hwnd, &r);
-
- /* we decrement the width so that the width data area is
- strictly less than the width of the client area. Windows
- doesn't disable a scrollbar unless the range is strictly
- less than the page size. */
- delta = ((r.right - r.left) - 1) - ext_x;
-
- if (tbl->cols[filler_col].width + delta <= GetSystemMetrics(SM_CXSMICON)) {
- tbl->cols[filler_col].width = GetSystemMetrics(SM_CXICON);
- } else {
- tbl->cols[filler_col].width += delta;
- }
-
- cw_update_header_column_width(tbl, filler_col);
-
- fill_adjusted = 1;
- goto recompute_columns;
- }
-
- if(!tbl->cell_height) {
- HDC dc;
- int maxheight = 0;
- int height;
-
- dc = GetWindowDC(tbl->hwnd);
-
- maxheight = cw_get_cell_height(dc, tbl->hf_normal);
- height = cw_get_cell_height(dc, tbl->hf_bold);
- if (height > maxheight)
- maxheight = height;
- height = cw_get_cell_height(dc, tbl->hf_header);
- if (height > maxheight)
- maxheight = height;
- height = cw_get_cell_height(dc, tbl->hf_bold_header);
- if (height > maxheight)
- maxheight = height;
-
- ReleaseDC(tbl->hwnd, dc);
-
- tbl->cell_height = height + tbl->vpad * 2;
- }
-
- if (tbl->flags & KHUI_CW_TBL_EXPIDENT) {
- RECT r;
-
- ext_y = 0;
- r.left = 0;
- r.right = ext_x;
-
- for (i=0; i < (int) tbl->n_rows; i++) {
- r.top = ext_y;
- if (tbl->rows[i].flags & KHUI_CW_ROW_EXPVIEW) {
- ext_y += tbl->cell_height * CW_EXP_ROW_MULT;
- } else {
- ext_y += tbl->cell_height;
- }
- r.bottom = ext_y;
- tbl->rows[i].r_ext = r;
- }
- } else {
- RECT r;
-
- r.left = 0;
- r.right = ext_x;
-
- for (i=0; i < (int) tbl->n_rows; i++) {
- r.top = i * tbl->cell_height;
- r.bottom = r.top + tbl->cell_height;
-
- tbl->rows[i].r_ext = r;
- }
-
- ext_y = (int) tbl->n_rows * tbl->cell_height;
- }
-
- tbl->ext_width = ext_x;
- tbl->ext_height = ext_y;
-
- /* useful in the future when implementing variable height rows.
- The KHUI_CW_TBL_ROW_DIRTY bit indicates that the rows have
- changed and that the y extent has to be recalculated. */
- tbl->flags &= ~KHUI_CW_TBL_ROW_DIRTY;
-
- if(update_scroll) {
- RECT r;
- int cl_w;
- int cl_h;
- SCROLLINFO si;
- WINDOWPOS pw;
- HDLAYOUT hdl;
-
- /* update the header control first */
-
- retry_update_scroll:
- GetClientRect(tbl->hwnd, &r);
-
- cl_w = r.right - r.left;
- cl_h = (r.bottom - r.top);
- cl_h -= tbl->header_height;
-
- if(tbl->scr_top < 0 || tbl->ext_height < cl_h)
- tbl->scr_top = 0;
- else if(tbl->scr_top > tbl->ext_height - cl_h)
- tbl->scr_top = tbl->ext_height - cl_h;
- if(tbl->scr_left < 0 || tbl->ext_width < cl_w)
- tbl->scr_left = 0;
- else if(tbl->scr_left > tbl->ext_width - cl_w)
- tbl->scr_left = tbl->ext_width - cl_w;
-
- /* adjustments for scrolling */
- r.left -= tbl->scr_left;
- r.right = max(tbl->ext_width + r.left, r.right);
-
- hdl.prc = &r;
- hdl.pwpos = &pw;
-
- Header_Layout(tbl->hwnd_header, &hdl);
-
- if(tbl->header_height == 0) {
- tbl->header_height = pw.cy;
- goto retry_update_scroll;
- } else
- tbl->header_height = pw.cy;
-
- SetWindowPos(
- tbl->hwnd_header,
- pw.hwndInsertAfter,
- pw.x,
- pw.y,
- pw.cx,
- pw.cy,
- pw.flags);
-
- si.cbSize = sizeof(si);
- si.nMin = 0;
- si.nMax = tbl->ext_height;
- si.nPage = cl_h;
- si.nPos = tbl->scr_top;
- si.fMask = SIF_ALL | SIF_DISABLENOSCROLL;
- SetScrollInfo(tbl->hwnd, SB_VERT, &si, TRUE);
-
- si.cbSize = sizeof(si);
- si.nMin = 0;
- si.nMax = tbl->ext_width;
- si.nPage = cl_w;
- si.nPos = tbl->scr_left;
- si.fMask = SIF_ALL | SIF_DISABLENOSCROLL;
- SetScrollInfo(tbl->hwnd, SB_HORZ, &si, TRUE);
- }
-
- return 0;
-}
-
-void
-cw_insert_header_cols(khui_credwnd_tbl * tbl) {
- HWND hdr;
- HDITEM hi;
- int i;
-
- hdr = tbl->hwnd_header;
-
- for(i=0; i < (int) tbl->n_cols; i++) {
- cw_hditem_from_tbl_col(&(tbl->cols[i]), &hi);
- Header_InsertItem(hdr, 512, &hi);
- }
-}
-
-#define CW_ER_BLANK 0
-#define CW_ER_GREY 1
-#define CW_ER_SEL 2
-
-void
-cw_erase_rect(HDC hdc,
- khui_credwnd_tbl * tbl,
- RECT * r_wnd,
- RECT * r_erase,
- int type)
-{
- RECT rlogo;
- RECT ri;
- RECT t;
- BOOL rie;
- HBRUSH hbr;
-
- switch(type) {
- case CW_ER_BLANK:
- hbr = tbl->hb_normal;
- break;
-
- case CW_ER_GREY:
- hbr = tbl->hb_grey;
- break;
-
- case CW_ER_SEL:
- hbr = tbl->hb_s;
- break;
-
- default:
- return;
- }
-
- if(tbl->kbm_logo_shade.cx != -1 && type == CW_ER_BLANK) {
- rlogo.left = r_wnd->right - tbl->kbm_logo_shade.cx;
- rlogo.right = r_wnd->right;
- rlogo.top = r_wnd->bottom - tbl->kbm_logo_shade.cy;
- rlogo.bottom = r_wnd->bottom;
- rie = IntersectRect(&ri, r_erase, &rlogo);
- } else {
- ZeroMemory(&rlogo, sizeof(rlogo));
- ZeroMemory(&ri, sizeof(ri));
- rie = FALSE;
- }
-
- if(!rie) {
- FillRect(hdc, r_erase, hbr);
- } else {
- HDC hdcb = CreateCompatibleDC(hdc);
- HBITMAP hbmold = SelectObject(hdcb, tbl->kbm_logo_shade.hbmp);
-
- BitBlt(hdc, ri.left, ri.top, ri.right - ri.left, ri.bottom - ri.top,
- hdcb, ri.left - rlogo.left, ri.top - rlogo.top, SRCCOPY);
-
- SelectObject(hdcb, hbmold);
- DeleteDC(hdcb);
-
- if(r_erase->top < ri.top && r_erase->left < ri.left) {
- t.left = r_erase->left;
- t.top = r_erase->top;
- t.right = ri.left;
- t.bottom = ri.top;
- FillRect(hdc, &t, hbr);
- }
-
- if(r_erase->left < ri.left) {
- t.left = r_erase->left;
- t.top = ri.top;
- t.right = ri.left;
- t.bottom = ri.bottom;
- FillRect(hdc, &t, hbr);
- }
-
- if(r_erase->top < ri.top) {
- t.left = ri.left;
- t.top = r_erase->top;
- t.right = ri.right;
- t.bottom = ri.top;
- FillRect(hdc, &t, hbr);
- }
- }
-}
-
-void
-cw_draw_header(HDC hdc,
- khui_credwnd_tbl * tbl,
- int row,
- RECT * r)
-{
- int colattr;
- HPEN pl, pold;
- khui_credwnd_row * cr;
- khui_credwnd_outline * o;
- int selected = 0;
- khm_int32 idf = 0;
-
- /* each header consists of a couple of widgets and some text */
- /* we need to figure out the background color first */
-
- cr = &(tbl->rows[row]);
- o = (khui_credwnd_outline *) cr->data;
-
- colattr = tbl->cols[cr->col].attr_id;
-
- if (colattr == KCDB_ATTR_ID_NAME) {
- khm_handle ident = o->data;
-
- kcdb_identity_get_flags(ident, &idf);
- }
-
- selected = o->flags & KHUI_CW_O_SELECTED;
-
- {
- HBRUSH hbr;
-
- if(selected) {
- if ((o->flags & CW_EXPSTATE_MASK) == CW_EXPSTATE_EXPIRED)
- hbr = tbl->hb_hdr_bg_exp_s;
- else if ((o->flags & CW_EXPSTATE_MASK) == CW_EXPSTATE_CRITICAL)
- hbr = tbl->hb_hdr_bg_crit_s;
- else if ((o->flags & CW_EXPSTATE_MASK) == CW_EXPSTATE_WARN)
- hbr = tbl->hb_hdr_bg_warn_s;
- else if (idf & KCDB_IDENT_FLAG_DEFAULT)
- hbr = tbl->hb_hdr_bg_def_s;
- else
- hbr = tbl->hb_hdr_bg_s;
- } else {
- if ((o->flags & CW_EXPSTATE_MASK) == CW_EXPSTATE_EXPIRED)
- hbr = tbl->hb_hdr_bg_exp;
- else if ((o->flags & CW_EXPSTATE_MASK) == CW_EXPSTATE_CRITICAL)
- hbr = tbl->hb_hdr_bg_crit;
- else if ((o->flags & CW_EXPSTATE_MASK) == CW_EXPSTATE_WARN)
- hbr = tbl->hb_hdr_bg_warn;
- else if (idf & KCDB_IDENT_FLAG_DEFAULT)
- hbr = tbl->hb_hdr_bg_def;
- else
- hbr = tbl->hb_hdr_bg;
- }
-
- FillRect(hdc, r, hbr);
- }
-
- /* draw the background */
- pl = CreatePen(PS_SOLID, 0, tbl->cr_hdr_outline);
- pold = SelectObject(hdc, pl);
- MoveToEx(hdc, r->left, r->bottom - 1, NULL);
- LineTo(hdc,r->right,r->bottom - 1);
- SelectObject(hdc, pold);
- DeleteObject(pl);
-
- if (!(o->flags & KHUI_CW_O_NOOUTLINE) &&
- !(o->flags & KHUI_CW_O_EMPTY)) {
- if((tbl->mouse_state & CW_MOUSE_WOUTLINE) &&
- tbl->mouse_row == row) {
- if(o->flags & KHUI_CW_O_EXPAND) {
- khui_ilist_draw_id(tbl->ilist, IDB_WDG_EXPAND_HI,
- hdc, r->left,
- (r->top + r->bottom - KHUI_SMICON_CY) / 2, 0);
- } else {
- khui_ilist_draw_id(tbl->ilist, IDB_WDG_COLLAPSE_HI,
- hdc, r->left,
- (r->top + r->bottom - KHUI_SMICON_CY) / 2, 0);
- }
- } else {
- if(o->flags & KHUI_CW_O_EXPAND) {
- khui_ilist_draw_id(tbl->ilist, IDB_WDG_EXPAND,
- hdc, r->left,
- (r->top + r->bottom - KHUI_SMICON_CY) / 2, 0);
- } else {
- khui_ilist_draw_id(tbl->ilist, IDB_WDG_COLLAPSE,
- hdc, r->left,
- (r->top + r->bottom - KHUI_SMICON_CY) / 2, 0);
- }
- }
-
- r->left += KHUI_SMICON_CX * 3 / 2;
- } else if (!(o->flags & KHUI_CW_O_NOOUTLINE)) {
- r->left += KHUI_SMICON_CX * 3 / 2;
- }
-
- /* try to draw the icon, if there is one */
- if(colattr == KCDB_ATTR_ID_NAME) {
-
- khui_ilist_draw_id(tbl->ilist,
- (((tbl->mouse_state & CW_MOUSE_WSTICKY) &&
- tbl->mouse_row == row)?
- ((idf & KCDB_IDENT_FLAG_STICKY)?
- IDB_WDG_STUCK_HI:
- IDB_WDG_STICK_HI):
- ((idf & KCDB_IDENT_FLAG_STICKY)?
- IDB_WDG_STUCK:
- IDB_WDG_STICK)),
- hdc,
- r->left,
- (r->top + r->bottom - KHUI_SMICON_CY) / 2, 0);
-
- r->left += KHUI_SMICON_CX * 3 / 2;
-
- /* the TRUE part of the 'if' is for drawing large icons. It's
- disabled for now until we have new icons. */
- if ((cr->flags & KHUI_CW_ROW_EXPVIEW) && FALSE) {
- int cx = GetSystemMetrics(SM_CXICON);
- int cy = GetSystemMetrics(SM_CYICON);
-
- DrawIcon(hdc, r->left, (r->top + r->bottom - cy) / 2, tbl->hi_lg_ident);
-
- r->left += cx + KHUI_SMICON_CX / 2;
-
- } else {
- khui_ilist_draw_id(tbl->ilist,
- ((o->flags & KHUI_CW_O_EMPTY)?
- IDB_ID_DIS_SM:
- IDB_ID_SM),
- hdc,
- r->left,
- (r->top + r->bottom - KHUI_SMICON_CY) / 2, 0);
- r->left += KHUI_SMICON_CX * 3 / 2 ;
- }
- }
-
-
- if (!(cr->flags & KHUI_CW_ROW_EXPVIEW)) {
-
- SetTextAlign(hdc, TA_BOTTOM | TA_LEFT);
-
- if(selected)
- SetTextColor(hdc, tbl->cr_hdr_s);
- else
- SetTextColor(hdc, tbl->cr_hdr_normal);
-
- TextOut(hdc, r->left, r->bottom - tbl->vpad, o->header, (int) wcslen(o->header));
-
- if (colattr == KCDB_ATTR_ID_NAME &&
- (idf & KCDB_IDENT_FLAG_DEFAULT)) {
- wchar_t defstr[64];
- SIZE size;
-
- LoadString(khm_hInstance, IDS_CW_DEFAULT,
- defstr, ARRAYLENGTH(defstr));
-
- GetTextExtentPoint32(hdc, o->header, (int) wcslen(o->header),
- &size);
-
- r->left += size.cx + KHUI_SMICON_CX * 2;
-
- TextOut(hdc, r->left, r->bottom - tbl->vpad,
- defstr, (int) wcslen(defstr));
- }
- } else {
-
- RECT tr;
- int len;
- wchar_t typestr[128];
- int cx_id;
- SIZE size;
- khui_credwnd_ident * cwi;
-
- /* expanded view */
-#ifdef DEBUG
- assert(colattr == KCDB_ATTR_ID_NAME);
-#endif
-
- cwi = cw_find_ident(tbl, o->data);
-
- CopyRect(&tr, r);
- tr.bottom -= (tr.bottom - tr.top) / 2; /* drawing two lines of text */
-
- if (selected)
- SetTextColor(hdc, tbl->cr_hdr_s);
- else
- SetTextColor(hdc, tbl->cr_hdr_normal);
-
- len = (int) wcslen(o->header);
- DrawText(hdc, o->header, len, &tr, DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS);
- GetTextExtentPoint32(hdc, o->header, (int) len, &size);
- cx_id = size.cx;
-
- typestr[0] = L'\0';
-
- if ((idf & KCDB_IDENT_FLAG_DEFAULT)) {
- if (cwi && cwi->credtype_name[0]) {
- wchar_t fmt[64];
-
- LoadString(khm_hInstance, IDS_CW_DEFAULTTF,
- fmt, ARRAYLENGTH(fmt));
- StringCbPrintf(typestr, sizeof(typestr), fmt,
- cwi->credtype_name);
- } else {
- LoadString(khm_hInstance, IDS_CW_DEFAULT,
- typestr, ARRAYLENGTH(typestr));
- }
- } else if (cwi && cwi->credtype_name[0]) {
- wchar_t fmt[64];
-
- LoadString(khm_hInstance, IDS_CW_TYPEF,
- fmt, ARRAYLENGTH(fmt));
- StringCbPrintf(typestr, sizeof(typestr), fmt,
- cwi->credtype_name);
- }
-
- if (typestr[0]) {
- int cx_str;
-
- len = (int) wcslen(typestr);
- GetTextExtentPoint32(hdc, typestr, (int) len, &size);
- cx_str = size.cx + KHUI_SMICON_CX / 2;
-
- tr.left = max(tr.right - cx_str, tr.left + cx_id + KHUI_SMICON_CX * 2);
- if (selected)
- SetTextColor(hdc, tbl->cr_hdr_gray_s);
- else
- SetTextColor(hdc, tbl->cr_hdr_gray);
- DrawText(hdc, typestr, len, &tr, DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS);
- }
-
- CopyRect(&tr, r);
- tr.top += (tr.bottom - tr.top) / 2;
-
- if (1) {
- wchar_t buf[128];
- khui_credwnd_ident * cwi;
-
- buf[0] = L'\0';
- cwi = cw_find_ident(tbl, o->data);
-
- if (cwi) {
-#ifdef SHOW_CREDENTIAL_COUNTS
- if (cwi->credcount == 0)
- LoadString(khm_hInstance, IDS_IDEXPDISP_NOCRED,
- buf, ARRAYLENGTH(buf));
- else if (cwi->credcount == 1)
- LoadString(khm_hInstance, IDS_IDEXPDISP_1CRED,
- buf, ARRAYLENGTH(buf));
- else {
- wchar_t fmt[128];
- LoadString(khm_hInstance, IDS_IDEXPDISP_NCRED,
- fmt, ARRAYLENGTH(fmt));
- StringCbPrintf(buf, sizeof(buf), fmt, (int) cwi->credcount);
- }
-#else
- if (FtToInt(&cwi->ft_expire) != 0) {
- FILETIME ft_now;
-
- GetSystemTimeAsFileTime(&ft_now);
- if (CompareFileTime(&cwi->ft_expire, &ft_now) > 0) {
- wchar_t fmt[64];
- wchar_t intstr[128];
- FILETIME ft;
- khm_size cb;
-
- ft = FtSub(&cwi->ft_expire, &ft_now);
- intstr[0] = L'\0';
- cb = sizeof(intstr);
- FtIntervalToString(&ft, intstr, &cb);
-
- LoadString(khm_hInstance, IDS_CW_EXPIREF,
- fmt, ARRAYLENGTH(fmt));
- StringCbPrintf(buf, sizeof(buf), fmt, intstr);
- } else {
- LoadString(khm_hInstance, IDS_CW_EXPIRED,
- buf, ARRAYLENGTH(buf));
- }
- }
-#endif
-
- len = (int) wcslen(buf);
-
- if (selected)
- SetTextColor(hdc, tbl->cr_hdr_gray_s);
- else
- SetTextColor(hdc, tbl->cr_hdr_gray);
- DrawText(hdc, buf, len, &tr, DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS);
- }
- }
- }
-}
-
-LRESULT
-cw_handle_header_msg(khui_credwnd_tbl * tbl, LPNMHEADER ph) {
- RECT r;
- HDITEM hi;
-
- switch(ph->hdr.code) {
- /*TODO:Make it track smoother */
- case HDN_BEGINTRACK:
- {
- ZeroMemory(&hi, sizeof(hi));
- hi.mask = HDI_ORDER;
- Header_GetItem(tbl->hwnd_header, ph->iItem, &hi);
-
- if(tbl->cols[hi.iOrder].flags & KHUI_CW_COL_FIXED_WIDTH)
- return TRUE;
- else
- return FALSE;
- }
-
- case HDN_TRACK:
- return FALSE;
-
- case HDN_ENDTRACK:
- {
- int width;
- hi.mask = HDI_ORDER;
- Header_GetItem(ph->hdr.hwndFrom, ph->iItem, &hi);
- Header_GetItemRect(ph->hdr.hwndFrom, ph->iItem, &r);
- width = r.right - r.left;
- if(width != tbl->cols[hi.iOrder].width) {
- tbl->cols[hi.iOrder].width = width;
- cw_update_extents(tbl, TRUE);
- InvalidateRect(tbl->hwnd, NULL, FALSE);
- }
- }
- break;
-
- case HDN_BEGINDRAG:
- {
-
- ZeroMemory(&hi, sizeof(hi));
- hi.mask = HDI_ORDER;
- Header_GetItem(tbl->hwnd_header, ph->iItem, &hi);
-
- if (tbl->cols[hi.iOrder].flags & KHUI_CW_COL_FIXED_POS) {
- return TRUE;
- } else {
- return FALSE;
- }
- }
- break;
-
- case HDN_ENDDRAG:
- {
- int drag_start_index;
- int drag_end_index;
- int i;
- khui_credwnd_col tcol;
- int sort_index = 0;
- khm_int32 old_flags;
-
- if (ph->pitem == NULL)
- return TRUE;
-
- hi.mask = HDI_ORDER;
- Header_GetItem(tbl->hwnd_header, ph->iItem, &hi);
- drag_start_index = hi.iOrder;
- drag_end_index = ph->pitem->iOrder;
-
- /* the user dragged the column which was at drag_start_index
- to drag_end_index. */
-
- if (drag_end_index == drag_start_index)
- return TRUE;
-
- /* we don't allow dragging in to the "fixed" area. */
- for (i=0; i < tbl->n_cols; i++) {
- if (!(tbl->cols[i].flags & KHUI_CW_COL_FIXED_POS))
- break;
- }
-
- if (drag_end_index <= i)
- return TRUE;
-
- tcol = tbl->cols[drag_start_index];
- if (drag_end_index < drag_start_index) {
- MoveMemory(&tbl->cols[drag_end_index + 1],
- &tbl->cols[drag_end_index],
- sizeof(tbl->cols[0]) *
- (drag_start_index - drag_end_index));
- } else {
- MoveMemory(&tbl->cols[drag_start_index],
- &tbl->cols[drag_start_index + 1],
- sizeof(tbl->cols[0]) *
- (drag_end_index - drag_start_index));
- }
- tbl->cols[drag_end_index] = tcol;
-
- old_flags = tbl->cols[drag_end_index].flags;
-
- if (drag_end_index < tbl->n_cols - 1) {
- khm_int32 tflags = tbl->cols[drag_end_index + 1].flags;
-
- if (tflags & KHUI_CW_COL_GROUP) {
- tbl->cols[drag_end_index].flags |= KHUI_CW_COL_GROUP;
- }
-
- if ((tflags & (KHUI_CW_COL_SORT_INC | KHUI_CW_COL_SORT_DEC)) &&
- !(old_flags & (KHUI_CW_COL_SORT_INC | KHUI_CW_COL_SORT_DEC)))
- tbl->cols[drag_end_index].flags |= KHUI_CW_COL_SORT_INC;
- }
-
- if (drag_end_index > 0) {
- khm_int32 tflags = tbl->cols[drag_end_index - 1].flags;
-
- if (!(tflags & KHUI_CW_COL_GROUP))
- tbl->cols[drag_end_index].flags &= ~KHUI_CW_COL_GROUP;
-
- if (!(tflags & (KHUI_CW_COL_SORT_INC | KHUI_CW_COL_SORT_DEC)))
- tbl->cols[drag_end_index].flags &=
- ~(KHUI_CW_COL_SORT_INC | KHUI_CW_COL_SORT_DEC);
- }
-
- if (old_flags != tbl->cols[drag_end_index].flags) {
- cw_hditem_from_tbl_col(&tbl->cols[drag_end_index], &hi);
- hi.mask = HDI_FORMAT;
- Header_SetItem(tbl->hwnd_header, ph->iItem, &hi);
- }
-
- if ((old_flags ^ tbl->cols[drag_end_index].flags) &
- KHUI_CW_COL_GROUP)
- tbl->flags |= KHUI_CW_TBL_COL_DIRTY;
-
- for (i=0; i < tbl->n_cols; i++) {
- if (tbl->cols[i].attr_id < 0)
- continue;
-
- if (tbl->cols[i].flags &
- (KHUI_CW_COL_GROUP |
- KHUI_CW_COL_SORT_INC |
- KHUI_CW_COL_SORT_DEC))
- tbl->cols[i].sort_index = sort_index++;
- else
- break;
- }
-
- tbl->flags |= KHUI_CW_TBL_CUSTVIEW;
-
- cw_update_creds(tbl);
- cw_update_outline(tbl);
- cw_update_extents(tbl, TRUE);
-
- InvalidateRect(tbl->hwnd, NULL, FALSE);
-
- return FALSE;
- }
- break;
-
- case HDN_ITEMCLICK:
- {
- int idx;
- int hidx;
-
- hi.mask = HDI_ORDER;
- Header_GetItem(tbl->hwnd_header, ph->iItem, &hi);
- idx = hi.iOrder;
-
- if (idx < 0 || idx >= tbl->n_cols)
- return FALSE;
-
- if (tbl->cols[idx].flags & KHUI_CW_COL_META)
- return FALSE;
-
- if (tbl->cols[idx].flags &
- (KHUI_CW_COL_SORT_INC | KHUI_CW_COL_SORT_DEC)) {
-
- tbl->cols[idx].flags ^=
- (KHUI_CW_COL_SORT_INC | KHUI_CW_COL_SORT_DEC);
-
- cw_hditem_from_tbl_col(&tbl->cols[idx], &hi);
- hi.mask = HDI_FORMAT;
- Header_SetItem(tbl->hwnd_header, ph->iItem, &hi);
-
- } else {
- int i;
- int sort_idx = 0;
-
- for (i=0; i <= idx; i++) {
- if (tbl->cols[i].attr_id < 0)
- continue;
-
- if (!(tbl->flags &
- (KHUI_CW_COL_SORT_INC | KHUI_CW_COL_SORT_DEC))) {
- tbl->cols[i].flags |= KHUI_CW_COL_SORT_INC;
-
- cw_hditem_from_tbl_col(&tbl->cols[i], &hi);
- hi.mask = HDI_FORMAT;
- hidx = Header_OrderToIndex(tbl->hwnd_header, i);
- Header_SetItem(tbl->hwnd_header, hidx, &hi);
- }
-
- tbl->cols[i].sort_index = sort_idx++;
- }
- }
-
- tbl->flags |= KHUI_CW_TBL_CUSTVIEW;
-
- cw_update_creds(tbl);
- cw_update_outline(tbl);
- cw_update_extents(tbl, TRUE);
-
- InvalidateRect(tbl->hwnd, NULL, FALSE);
-
- }
- break;
-
- case HDN_ITEMDBLCLICK:
- {
- int idx;
- int hidx;
-
- hi.mask = HDI_ORDER;
- Header_GetItem(tbl->hwnd_header, ph->iItem, &hi);
- idx = hi.iOrder;
-
- if (idx == 0 || idx >= tbl->n_cols)
- return FALSE;
-
- if (tbl->cols[idx].flags & KHUI_CW_COL_GROUP) {
- /* we are removing grouping from this level */
-
- int i;
-
- for (i=idx; i < tbl->n_cols; i++) {
- if (!(tbl->cols[i].flags & KHUI_CW_COL_GROUP))
- break;
-
- tbl->cols[i].flags &= ~KHUI_CW_COL_GROUP;
-
- cw_hditem_from_tbl_col(&tbl->cols[idx], &hi);
- hi.mask = HDI_FORMAT;
- hidx = Header_OrderToIndex(tbl->hwnd_header, i);
- Header_SetItem(tbl->hwnd_header, hidx, &hi);
- }
-
-#if 0
- } else if (tbl->cols[idx].flags &
- (KHUI_CW_COL_SORT_INC |
- KHUI_CW_COL_SORT_DEC)) {
- int i;
-
- /* remove the sort condition from a column */
-
- for (i=idx; i < tbl->n_cols; i++) {
- if (!tbl->cols[i].flags &
- (KHUI_CW_COL_SORT_INC |
- KHUI_CW_COL_SORT_DEC))
- break;
-
- tbl->cols[i].flags &=
- ~(KHUI_CW_COL_SORT_INC |
- KHUI_CW_COL_SORT_DEC);
-
- cw_hditem_from_tbl_col(&tbl->cols[idx], &hi);
- hi.mask = HDI_FORMAT;
- hidx = Header_OrderToIndex(tbl->hwnd_header, i);
- Header_SetItem(tbl->hwnd_header, hidx, &hi);
- }
-#endif
- } else {
- int i;
- int sort_index = 0;
-
- for (i=0; i <= idx; i++) {
- if (tbl->cols[i].attr_id < 0)
- continue;
-
- if (!(tbl->cols[i].flags & KHUI_CW_COL_GROUP)) {
- tbl->cols[i].flags |= KHUI_CW_COL_GROUP;
-
- if (!(tbl->cols[i].flags &
- (KHUI_CW_COL_SORT_INC |
- KHUI_CW_COL_SORT_DEC)))
- tbl->cols[i].flags |= KHUI_CW_COL_SORT_INC;
-
- cw_hditem_from_tbl_col(&tbl->cols[i], &hi);
- hi.mask = HDI_FORMAT;
- hidx = Header_OrderToIndex(tbl->hwnd_header, i);
- Header_SetItem(tbl->hwnd_header, hidx, &hi);
- }
-
- tbl->cols[i].sort_index = sort_index++;
- }
- }
-
- tbl->flags |= KHUI_CW_TBL_COL_DIRTY;
- tbl->flags |= KHUI_CW_TBL_CUSTVIEW;
-
- cw_update_creds(tbl);
- cw_update_outline(tbl);
- cw_update_extents(tbl, TRUE);
-
- InvalidateRect(tbl->hwnd, NULL, FALSE);
- }
- break;
-
- case NM_CUSTOMDRAW:
- {
- LPNMCUSTOMDRAW cd;
- int idx;
-
- cd = (LPNMCUSTOMDRAW) ph;
- switch(cd->dwDrawStage) {
- case CDDS_PREPAINT:
- return CDRF_NOTIFYITEMDRAW;
-
- case CDDS_ITEMPREPAINT:
- return CDRF_NOTIFYPOSTPAINT;
-
- case CDDS_ITEMPOSTPAINT:
- if(cd->lItemlParam == CW_CA_FLAGS)
- idx = IDB_WDG_FLAG;
- else if(cd->lItemlParam == CW_CA_TYPEICON)
- idx = IDB_WDG_CREDTYPE;
- else
- idx = -1;
-
- khui_ilist_draw_id(tbl->ilist, idx, cd->hdc, cd->rc.left, cd->rc.top, 0);
- return 0;
- }
- }
- break;
- }
- return 0;
-}
-
-LRESULT
-cw_wm_create(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
- khui_credwnd_tbl * tbl;
-
- kmq_subscribe_hwnd(KMSG_CRED, hwnd);
- kmq_subscribe_hwnd(KMSG_KCDB, hwnd);
- kmq_subscribe_hwnd(KMSG_KMM, hwnd);
-
- /* freed in cw_wm_destroy */
- tbl = PMALLOC(sizeof(*tbl));
- ZeroMemory(tbl, sizeof(*tbl));
-
- /* some versions of VC generate portability warnings for
- SetWindowLongPtr */
-#pragma warning(push)
-#pragma warning(disable: 4244)
- SetWindowLongPtr(hwnd, 0, (LONG_PTR) tbl);
-#pragma warning(pop)
-
- cw_refresh_attribs(hwnd);
-
- tbl->hwnd_header = CreateWindowEx(
- 0,
- WC_HEADER,
- (LPWSTR) NULL,
- WS_CHILD | HDS_BUTTONS |
- HDS_FULLDRAG | HDS_HORZ | HDS_HOTTRACK |
- HDS_DRAGDROP
-#if (_WIN32_WINNT >= 0x501)
- | ((IS_COMMCTL6())?HDS_FLAT:0)
-#endif
- ,
- 0,0,0,0,hwnd, (HMENU) 0, khm_hInstance, NULL);
-
- cw_load_view(tbl, NULL /* default view */, hwnd);
- cw_insert_header_cols(tbl);
-
- cw_update_creds(tbl);
- cw_update_outline(tbl);
- cw_update_selection_state(tbl);
- cw_update_extents(tbl, FALSE);
-
- {
- RECT rect;
- WINDOWPOS pw;
- HDLAYOUT hdl;
-
- hdl.prc = &rect;
- hdl.pwpos = &pw;
- GetClientRect(hwnd, &rect);
-
- Header_Layout(tbl->hwnd_header, &hdl);
-
- SetWindowPos(
- tbl->hwnd_header,
- pw.hwndInsertAfter,
- pw.x,
- pw.y,
- pw.cx,
- pw.cy,
- pw.flags | SWP_SHOWWINDOW);
- }
-
- return DefWindowProc(hwnd, uMsg, wParam, lParam);
-}
-
-LRESULT
-cw_wm_destroy(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
- khui_credwnd_tbl * tbl;
-
- kmq_unsubscribe_hwnd(KMSG_CRED, hwnd);
- kmq_unsubscribe_hwnd(KMSG_KCDB, hwnd);
- kmq_unsubscribe_hwnd(KMSG_KMM, hwnd);
-
- tbl = (khui_credwnd_tbl *)(LONG_PTR) GetWindowLongPtr(hwnd, 0);
-
- cw_save_view(tbl, NULL);
-
- cw_unload_view(tbl);
-
- PFREE(tbl);
- return DefWindowProc(hwnd, uMsg, wParam, lParam);
-}
-
-/* handles WM_PAINT and WM_PRINTCLIENT */
-LRESULT
-cw_wm_paint(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
- khui_credwnd_tbl * tbl;
- HDC hdc;
- PAINTSTRUCT ps;
- RECT r,rh;
- HFONT hf_old = NULL;
- int row_s, row_e;
- int col_s, col_e;
- int i,j,x,y,xs,xe,ys,ye;
- int flag_col = -1;
- int d_x = -1;
- int selected = 0;
- int rowheight = 0;
- BOOL has_dc = FALSE;
-
- tbl = (khui_credwnd_tbl *)(LONG_PTR) GetWindowLongPtr(hwnd, 0);
-
- if (wParam != 0) {
- /* we assume that if wParam != 0, then that contains a device
- context for us to draw in. Otherwise, we have to call
- BeginPaint() to get one. */
- hdc = (HDC) wParam;
- has_dc = TRUE;
- }
-
- if(!has_dc && !GetUpdateRect(hwnd, &r, FALSE)) {
-#ifdef DEBUG
- assert(FALSE);
-#endif
- goto _exit;
- }
-
- if (!has_dc)
- hdc = BeginPaint(hwnd, &ps);
-
- if(tbl->hf_normal)
- hf_old = SelectFont(hdc, tbl->hf_normal);
- SetTextAlign(hdc, TA_LEFT | TA_TOP | TA_NOUPDATECP);
- SetBkMode(hdc, TRANSPARENT);
-
- GetClientRect(hwnd,&r);
- r.top += tbl->header_height;
-
- if(tbl->n_rows) {
- /* remove the notification window if there is one */
- if(tbl->hwnd_notif) {
- DestroyWindow(tbl->hwnd_notif);
- tbl->hwnd_notif = NULL;
- }
- /* we compute the visible area in terms of rows and columns */
- /* row_s : first visible row */
- /* col_s : first visible column */
- /* row_e : last visible row */
- /* col_e : last visible column */
- /* ys : top edge of first visible row */
- /* xs : left edge of first visible column */
-
- /* We *NEED* all the meta columns to be on the left */
-
- row_s = 0;
- ys = 0;
- row_e = (int) tbl->n_rows;
- x = 0;
- col_s = -1;
- col_e = -1;
- xs = 0;
- for(i=0; i < (int) tbl->n_cols; i++) {
- if(col_e == -1 && x >= tbl->scr_left + (r.right - r.left)) {
- col_e = i;
- }
- if(tbl->cols[i].attr_id == CW_CA_FLAGS)
- flag_col = i;
- if(d_x == -1 && !cw_is_custom_attr(tbl->cols[i].attr_id))
- d_x = x;
- x += tbl->cols[i].width;
- if(col_s == -1 && x > tbl->scr_left) {
- col_s = i;
- xs = tbl->cols[i].x;
- }
- }
-
- if(col_e == -1)
- col_e = i;
-
- if(col_s == -1)
- col_s = i;
-
- if(d_x != -1)
- d_x += r.left - tbl->scr_left;
-
- xs += r.left - tbl->scr_left;
- ys += r.top - tbl->scr_top;
- xe = r.left + tbl->ext_width - tbl->scr_left;
- ye = r.top + tbl->ext_height - tbl->scr_top;
-
- /* now draw */
- y = ys;
- for(i=row_s; i < row_e; i++) {
- selected = tbl->rows[i].flags & KHUI_CW_ROW_SELECTED;
- rowheight = (tbl->rows[i].flags & KHUI_CW_ROW_EXPVIEW)? tbl->cell_height * CW_EXP_ROW_MULT : tbl->cell_height;
-
- if(tbl->cursor_row == i) {
- if (tbl->rows[i].flags & KHUI_CW_ROW_HEADER)
- SelectFont(hdc, tbl->hf_bold_header);
- else
- SelectFont(hdc, tbl->hf_bold);
- } else if (tbl->rows[i].flags & KHUI_CW_ROW_HEADER) {
- SelectFont(hdc, tbl->hf_header);
- }
-
- x = xs;
- if(tbl->rows[i].flags & KHUI_CW_ROW_HEADER) {
- rh.left = xs;
- rh.right = xs;
- for(j=col_s; j < tbl->rows[i].col; j++)
- rh.right += tbl->cols[j].width;
- rh.top = y;
- rh.bottom = y + rowheight;
- if(rh.right > rh.left) {
- cw_erase_rect(hdc, tbl, &r, &rh, (selected)?CW_ER_SEL:CW_ER_BLANK);
- }
- rh.left = rh.right;
- rh.right = xe;
-
- cw_draw_header(hdc, tbl, i, &rh);
- }
-
- if(selected)
- SetTextColor(hdc, tbl->cr_s);
- else
- SetTextColor(hdc, tbl->cr_normal);
-
- x = xs;
- rh.top = y;
- rh.bottom = y + rowheight;
- for(j=col_s; j < col_e; x += tbl->cols[j++].width) {
- wchar_t buf[256];
- khm_size cbbuf;
-
- rh.left = x;
- rh.right = x + tbl->cols[j].width;
-
- if(!cw_is_custom_attr(tbl->cols[j].attr_id)) {
- if(!(tbl->rows[i].flags & KHUI_CW_ROW_HEADER)) {
- cw_erase_rect(hdc, tbl, &r, &rh, (selected)?CW_ER_SEL:CW_ER_BLANK);
-
- if(j > tbl->rows[i].col) {
- cbbuf = sizeof(buf);
- if(KHM_FAILED(kcdb_cred_get_attr_string((khm_handle) tbl->rows[i].data,
- tbl->cols[j].attr_id, buf,
- &cbbuf, KCDB_TS_SHORT)))
- continue;
-
- rh.left += tbl->hpad;
- rh.right -= tbl->hpad;
-
- SetTextAlign(hdc, 0);
- DrawText(hdc, buf, (int)((cbbuf / sizeof(wchar_t)) - 1), &rh,
- DT_LEFT | DT_VCENTER | DT_NOCLIP | DT_SINGLELINE | DT_END_ELLIPSIS);
- }
- }
- } else {
- cw_erase_rect(hdc, tbl, &r, &rh, (selected)?CW_ER_SEL:CW_ER_BLANK);
-
- if(tbl->cols[j].attr_id == CW_CA_FLAGS) {
- khui_credwnd_outline * o;
- khm_int32 flag;
-
- if(tbl->rows[i].flags & KHUI_CW_ROW_HEADER) {
- o = ((khui_credwnd_outline *) tbl->rows[i].data);
- if(o->flags & KHUI_CW_O_SHOWFLAG)
- flag = o->flags;
- else
- flag = 0;
- } else {
- flag = tbl->rows[i].flags;
- }
-
- flag &= CW_EXPSTATE_MASK;
-
- if(flag == CW_EXPSTATE_WARN) {
- khui_ilist_draw_id(tbl->ilist, IDB_FLAG_WARN, hdc, x, y, 0);
- } else if(flag == CW_EXPSTATE_CRITICAL) {
- khui_ilist_draw_id(tbl->ilist, IDB_FLAG_CRITICAL, hdc, x, y, 0);
- } else if(flag == CW_EXPSTATE_EXPIRED) {
- khui_ilist_draw_id(tbl->ilist, IDB_FLAG_EXPIRED, hdc, x, y, 0);
- } else if(!(tbl->rows[i].flags & KHUI_CW_ROW_HEADER)) {
- khm_int32 flags;
-
- if (KHM_SUCCEEDED(kcdb_cred_get_flags((khm_handle) tbl->rows[i].data, &flags)) &&
- (flags & KCDB_CRED_FLAG_RENEWABLE)) {
- khui_ilist_draw_id(tbl->ilist,
- IDB_FLAG_RENEW,
- hdc,
- x, y, 0);
- } else {
- khui_ilist_draw_id(tbl->ilist,
- IDB_TK_SM,
- hdc,
- x, y, 0);
- }
- }
- }
- }
- }
-
- if(tbl->cursor_row == i) {
- rh.left = tbl->scr_left;
- rh.right = tbl->scr_left + tbl->ext_width;
- DrawFocusRect(hdc, &rh);
- }
-
- if (tbl->cursor_row == i ||
- (tbl->rows[i].flags & KHUI_CW_ROW_HEADER)) {
- SelectFont(hdc, tbl->hf_normal);
- }
-
- y += rowheight;
-
- }
-
- if(xe < r.right) {
- rh.left = xe;
- rh.right = r.right;
- rh.top = r.top;
- rh.bottom = r.bottom;
-
- cw_erase_rect(hdc, tbl, &r, &rh, CW_ER_BLANK);
- }
-
- if(ye < r.bottom) {
- rh.left = r.left;
- rh.right = (xe < r.right)?xe:r.right;
- rh.top = ye;
- rh.bottom = r.bottom;
-
- cw_erase_rect(hdc, tbl, &r, &rh, CW_ER_BLANK);
- }
-
- } else {
- wchar_t buf[512];
- cw_erase_rect(hdc, tbl, &r, &r, CW_ER_BLANK);
-
- if(tbl->hwnd_notif == NULL) {
- LoadString(khm_hInstance, IDS_NO_CREDS, buf, sizeof(buf)/sizeof(buf[0]));
- tbl->hwnd_notif = khm_create_htwnd(
- tbl->hwnd,
- buf,
- r.left,r.top,r.right - r.left,tbl->cell_height * 4,
- 0, /* This can be WS_EX_TRANSPARENT, but
- we don't fully support it yet. */
- WS_VISIBLE);
- if(tbl->hwnd_notif) {
- SendMessage(tbl->hwnd_notif, WM_SETFONT, (WPARAM) tbl->hf_normal, (LPARAM) FALSE);
- ShowWindow(tbl->hwnd_notif, SW_SHOW);
- }
- }
- }
-
- if(tbl->hf_normal)
- SelectFont(hdc, hf_old);
-
- if (!has_dc)
- EndPaint(hwnd,&ps);
-
- _exit:
- return TRUE;
-}
-
-LRESULT
-cw_wm_size(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
- RECT rect;
- khui_credwnd_tbl * tbl;
-
- tbl = (khui_credwnd_tbl *)(LONG_PTR) GetWindowLongPtr(hwnd, 0);
-
- cw_update_extents(tbl, TRUE);
-
- GetClientRect(hwnd, &rect);
-
- if(tbl->hwnd_notif) {
- SetWindowPos(
- tbl->hwnd_notif,
- tbl->hwnd_header,
- rect.left,
- tbl->header_height,
- rect.right - rect.left,
- tbl->cell_height * 4,
- 0);
- }
- return DefWindowProc(hwnd, uMsg, wParam, lParam);
-}
-
-LRESULT
-cw_wm_notify(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
- khui_credwnd_tbl * tbl;
- LPNMHDR pnmh;
- tbl = (khui_credwnd_tbl *)(LONG_PTR) GetWindowLongPtr(hwnd, 0);
- pnmh = (LPNMHDR) lParam;
- if(pnmh->hwndFrom == tbl->hwnd_header) {
- LPNMHEADER ph;
- ph = (LPNMHEADER) lParam;
- return cw_handle_header_msg(tbl, ph);
- }
-
- return DefWindowProc(hwnd, uMsg, wParam, lParam);
-}
-
-static void cw_pp_begin(khui_property_sheet * s);
-static void cw_pp_precreate(khui_property_sheet * s);
-static void cw_pp_end(khui_property_sheet * s);
-static void cw_pp_destroy(khui_property_sheet *ps);
-
-LRESULT
-cw_kmq_wm_dispatch(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
- kmq_message * m;
- khm_int32 rv = KHM_ERROR_SUCCESS;
- khui_credwnd_tbl * tbl;
-
- tbl = (khui_credwnd_tbl *)(LONG_PTR) GetWindowLongPtr(hwnd, 0);
-
- kmq_wm_begin(lParam, &m);
-
- if(m->type == KMSG_CRED) {
- switch (m->subtype) {
- case KMSG_CRED_ROOTDELTA:
- cw_update_creds(tbl);
- cw_update_outline(tbl);
- cw_update_extents(tbl, TRUE);
- InvalidateRect(hwnd, NULL, FALSE);
- break;
-
- case KMSG_CRED_PP_BEGIN:
- cw_pp_begin((khui_property_sheet *) m->vparam);
- break;
-
- case KMSG_CRED_PP_PRECREATE:
- cw_pp_precreate((khui_property_sheet *) m->vparam);
- break;
-
- case KMSG_CRED_PP_END:
- cw_pp_end((khui_property_sheet *) m->vparam);
- break;
-
- case KMSG_CRED_PP_DESTROY:
- cw_pp_destroy((khui_property_sheet *) m->vparam);
- break;
- }
- } else if (m->type == KMSG_KCDB) {
- if (m->subtype == KMSG_KCDB_IDENT &&
- m->uparam == KCDB_OP_MODIFY) {
-
- cw_update_outline(tbl);
- cw_update_extents(tbl, TRUE);
- InvalidateRect(hwnd, NULL, FALSE);
-
- }
- else if (m->subtype == KMSG_KCDB_IDENT &&
- m->uparam == KCDB_OP_NEW_DEFAULT) {
-
- cw_update_outline(tbl);
- cw_update_extents(tbl, TRUE);
- InvalidateRect(hwnd, NULL, FALSE);
-
- }
- else if (m->subtype == KMSG_KCDB_ATTRIB &&
- (m->uparam == KCDB_OP_INSERT ||
- m->uparam == KCDB_OP_DELETE)) {
-
- cw_refresh_attribs(hwnd);
-
- }
- } else if (m->type == KMSG_KMM &&
- m->subtype == KMSG_KMM_I_DONE) {
-
- if (tbl->flags & KHUI_CW_TBL_COLSKIP) {
- wchar_t cname[KCONF_MAXCCH_NAME];
- khm_size cb;
-
- cname[0] = L'\0';
-
- if (tbl->csp_view) {
- cb = sizeof(cname);
- khc_get_config_space_name(tbl->csp_view,
- cname,
- &cb);
- }
-
- cw_unload_view(tbl);
-
- cw_load_view(tbl, ((cname[0])?cname: NULL), hwnd);
- cw_insert_header_cols(tbl);
-
- cw_update_creds(tbl);
- cw_update_outline(tbl);
- cw_update_selection_state(tbl);
- cw_update_extents(tbl, TRUE);
-
- InvalidateRect(tbl->hwnd, NULL, TRUE);
- }
-
- } else if (m->type == KMSG_ACT &&
- m->subtype == KMSG_ACT_ACTIVATE) {
- /* a column selector menu item was activated */
-
- khm_int32 attr_id;
- khm_int32 action;
- khui_action * paction;
- int i;
- int first_non_fixed = -1;
-
- action = m->uparam;
- paction = khui_find_action(action);
-
- if (paction == NULL)
- goto _skip_action;
-
- attr_id = (khm_int32)(INT_PTR) paction->data;
-
- if (attr_id < 0 || attr_id > KCDB_ATTR_MAX_ID)
- goto _skip_action;
-
- for (i=0; i < tbl->n_cols; i++) {
- if (tbl->cols[i].attr_id >= 0 &&
- first_non_fixed == -1)
- first_non_fixed = i;
-
- if (tbl->cols[i].attr_id == attr_id)
- break;
- }
-
- if (first_non_fixed == i &&
- i == tbl->n_cols - 1) {
- /* this is the only non-fixed column. We don't allow
- deleting it, althoguh there's nothing wrong with doing
- so other than not being very useful. */
- goto _skip_action;
- }
-
- if (i < tbl->n_cols) {
- khm_int32 sort_index;
-
- /* we need to remove a column */
-
- Header_DeleteItem(tbl->hwnd_header, i);
- sort_index = tbl->cols[i].sort_index;
-
- if (tbl->cols[i].title)
- PFREE(tbl->cols[i].title);
- tbl->cols[i].title = NULL;
-
- if (i < tbl->n_cols - 1) {
- MoveMemory(&tbl->cols[i], &tbl->cols[i+1],
- sizeof(tbl->cols[0]) * (tbl->n_cols - (i + 1)));
- }
- tbl->n_cols--;
-
- /* fix the sort index */
- if (sort_index >= 0) {
- for (i=0; i < tbl->n_cols; i++) {
- if (tbl->cols[i].sort_index > sort_index)
- tbl->cols[i].sort_index--;
- }
- }
-
- tbl->flags |= KHUI_CW_TBL_COL_DIRTY;
-
- cw_update_creds(tbl);
- cw_update_outline(tbl);
- cw_update_extents(tbl, TRUE);
-
- InvalidateRect(tbl->hwnd, NULL, TRUE);
-
- khui_check_action(attr_to_action[attr_id], FALSE);
-
- tbl->flags |= KHUI_CW_TBL_CUSTVIEW;
-
- } else {
- /* we need to add a column */
- wchar_t buf[KCDB_MAXCCH_SHORT_DESC];
- khm_size cb;
- khm_int32 idx = tbl->n_cols;
- HDITEM hi;
-
- /* for now, we only allow KHUI_CW_COL_INITIAL columns */
- if (tbl->n_rows == tbl->n_total_rows)
- goto _skip_action;
-
- cb = sizeof(buf);
- if (KHM_FAILED(kcdb_attrib_describe(attr_id,
- buf,
- &cb,
- KCDB_TS_SHORT)))
- goto _skip_action;
-
- tbl->cols[idx].attr_id = attr_id;
- tbl->cols[idx].width = 100;
- tbl->cols[idx].x = -1;
- tbl->cols[idx].flags = 0;
- tbl->cols[idx].sort_index = -1;
- tbl->cols[idx].title = PMALLOC(cb);
-#ifdef DEBUG
- assert(tbl->cols[idx].title);
-#endif
- if (!tbl->cols[idx].title)
- goto _skip_action;
-
- StringCbCopy(tbl->cols[idx].title,
- cb,
- buf);
-
- tbl->n_cols++;
-
- cw_hditem_from_tbl_col(&(tbl->cols[idx]), &hi);
- Header_InsertItem(tbl->hwnd_header, 512, &hi);
-
- tbl->flags |= KHUI_CW_TBL_COL_DIRTY;
-
- cw_update_creds(tbl);
- cw_update_outline(tbl);
- cw_update_extents(tbl, TRUE);
-
- InvalidateRect(tbl->hwnd, NULL, TRUE);
-
- khui_check_action(attr_to_action[attr_id], TRUE);
-
- tbl->flags |= KHUI_CW_TBL_CUSTVIEW;
- }
-
- kmq_post_message(KMSG_ACT, KMSG_ACT_REFRESH, 0, 0);
-
- _skip_action:
- ;
- }
-
- return kmq_wm_end(m, rv);
-}
-
-static void
-cw_select_outline_level(khui_credwnd_outline * o,
- BOOL select)
-{
- while(o) {
- if (select)
- o->flags |= KHUI_CW_O_SELECTED;
- else
- o->flags &= ~KHUI_CW_O_SELECTED;
- cw_select_outline_level(TFIRSTCHILD(o), select);
- o = LNEXT(o);
- }
-}
-
-static void
-cw_select_outline(khui_credwnd_outline * o,
- BOOL select)
-{
- if (select)
- o->flags |= KHUI_CW_O_SELECTED;
- else
- o->flags &= ~KHUI_CW_O_SELECTED;
-}
-
-static void
-cw_select_row_creds(khui_credwnd_tbl * tbl, int row, int selected) {
-
- khm_size j;
- khm_size idx_start, idx_end;
-
-#ifdef DEBUG
- assert(row >= 0 && row < tbl->n_rows);
-#endif
-
- if (row >= tbl->n_rows)
- return;
-
- if (tbl->rows[row].flags & KHUI_CW_ROW_HEADER) {
- khui_credwnd_outline * o;
-
- o = (khui_credwnd_outline *) tbl->rows[row].data;
- if (o->col == tbl->n_cols - 1) {
- /* this is a special case where the outline column is the
- last displayed column. In this case, the credentials
- do not occupy any rows, and this header row acts as a
- group credential row. */
- idx_start = o->idx_start;
- idx_end = o->idx_end;
- } else {
- return;
- }
- } else {
- idx_start = tbl->rows[row].idx_start;
- idx_end = tbl->rows[row].idx_end;
- }
-
- if (idx_start == -1 || idx_end == -1)
- return;
-
- for (j = idx_start; j <= idx_end; j++) {
- khm_handle cred = NULL;
-
- kcdb_credset_get_cred(tbl->credset, (khm_int32) j, &cred);
-
- if (cred) {
- kcdb_cred_set_flags(cred, ((selected)?KCDB_CRED_FLAG_SELECTED:0),
- KCDB_CRED_FLAG_SELECTED);
- kcdb_cred_release(cred);
- }
- }
-}
-
-static void
-cw_unselect_all(khui_credwnd_tbl * tbl)
-{
- int i;
-
- for(i=0; i<tbl->n_rows; i++) {
- tbl->rows[i].flags &= ~KHUI_CW_ROW_SELECTED;
-
- cw_select_row_creds(tbl, i, FALSE);
- }
-
- cw_select_outline_level(tbl->outline, FALSE);
-}
-
-static void
-cw_update_outline_selection_state(khui_credwnd_tbl * tbl,
- khui_credwnd_outline * o)
-{
- BOOL select = TRUE;
- int j;
-
- for (j = o->start + 1; j < o->start + o->length; j++) {
- if (tbl->rows[j].flags & KHUI_CW_ROW_HEADER) {
- cw_update_outline_selection_state(tbl,
- (khui_credwnd_outline *)
- tbl->rows[j].data);
- }
-
- if (!(tbl->rows[j].flags & KHUI_CW_ROW_SELECTED)) {
- select = FALSE;
- }
-
- if (tbl->rows[j].flags & KHUI_CW_ROW_HEADER) {
- j += ((khui_credwnd_outline *) tbl->rows[j].data)->length - 1;
- }
- }
-
- /* special case : the header has been collapsed and we are just
- using one row. In this case, the for loop above will do
- nothing. */
-
- if (o->length == 1) {
- select = (tbl->rows[o->start].flags & KHUI_CW_ROW_SELECTED);
- }
-
- cw_select_outline(o, select);
-
- if (select) {
- tbl->rows[o->start].flags |= KHUI_CW_ROW_SELECTED;
- } else {
- tbl->rows[o->start].flags &= ~KHUI_CW_ROW_SELECTED;
- }
-}
-
-static void
-cw_update_selection_state(khui_credwnd_tbl * tbl)
-{
- int i;
-
- cw_select_outline_level(tbl->outline, FALSE);
-
- for (i=0; i < tbl->n_rows; i++) {
- if (tbl->rows[i].flags & KHUI_CW_ROW_HEADER) {
- khui_credwnd_outline * o;
-
- o = (khui_credwnd_outline *) tbl->rows[i].data;
-
- cw_update_outline_selection_state(tbl, o);
-
- i += o->length - 1;
- }
- }
-}
-
-/* Examine the current row and set the UI context */
-static void
-cw_set_row_context(khui_credwnd_tbl * tbl, int row)
-{
- khui_credwnd_outline * o;
- BOOL set_context = TRUE;
-
- if (row < 0 || row >= (int) tbl->n_rows) {
- if (tbl->n_rows > 0)
- row = 0;
- else {
- khui_context_reset();
- return;
- }
- }
-
- if (tbl->rows[row].flags & KHUI_CW_ROW_HEADER) {
-
- o = (khui_credwnd_outline *) tbl->rows[row].data;
-
- if (tbl->cols[o->col].attr_id == KCDB_ATTR_ID_NAME) {
- if (TPARENT(o) != NULL) {
- khui_credwnd_outline * op;
-
- op = TPARENT(o);
-
- if (tbl->cols[op->col].attr_id == KCDB_ATTR_TYPE_NAME &&
- TPARENT(op) == NULL) {
- /* selected a credential type */
- khui_context_set(KHUI_SCOPE_CREDTYPE,
- (khm_handle) o->data,
- (khm_int32) (DWORD_PTR) op->data,
- NULL,
- NULL,
- 0,
- tbl->credset);
- } else {
- /* we can't narrow it down using the standard set
- of scopes. We consider this to be an identity
- selection because the user right-clicked on an
- identity header. */
- khui_context_set(KHUI_SCOPE_IDENT,
- (khm_handle) o->data,
- KCDB_CREDTYPE_INVALID,
- NULL,
- NULL,
- 0,
- tbl->credset);
- }
- } else {
- /* The user clicked on an identity header. Even
- though not all credentials belonging to the
- identity maybe within the scope right now, we still
- consider this to be an identity scope. */
- khui_context_set(KHUI_SCOPE_IDENT,
- (khm_handle) o->data,
- KCDB_CREDTYPE_INVALID,
- NULL,
- NULL,
- 0,
- tbl->credset);
- }
- } else if (tbl->cols[o->col].attr_id == KCDB_ATTR_TYPE_NAME) {
- if (TPARENT(o) == NULL) {
- /* selected an entire cred type */
- khui_context_set(KHUI_SCOPE_CREDTYPE,
- NULL,
- (khm_int32) (DWORD_PTR) o->data,
- NULL,
- NULL,
- 0,
- tbl->credset);
- } else {
- khui_credwnd_outline * op;
-
- op = TPARENT(o);
- if (tbl->cols[op->col].attr_id == KCDB_ATTR_ID_NAME) {
- /* credtype under an identity. Even though not
- all the credentials of this credtype belonging
- to this identity might be within the scope, we
- still consider this to be a type selection
- under a specific identity. */
- khui_context_set(KHUI_SCOPE_CREDTYPE,
- (khm_handle) op->data,
- (khm_int32) (DWORD_PTR) o->data,
- NULL,
- NULL,
- 0,
- tbl->credset);
- } else {
- set_context = FALSE;
- }
- }
- } else {
- set_context = FALSE;
- }
-
- if (!set_context) {
- /* woohoo. cred group. yay. */
- khui_header headers[KHUI_MAX_HEADERS];
- khm_size n_headers = 0;
-
- do {
- headers[n_headers].attr_id =
- o->attr_id;
- if (tbl->cols[o->col].attr_id ==
- KCDB_ATTR_ID_NAME) {
- headers[n_headers].data = &(o->data);
- headers[n_headers].cb_data = sizeof(khm_handle);
- } else if (tbl->cols[o->col].attr_id ==
- KCDB_ATTR_TYPE_NAME) {
- headers[n_headers].data = &(o->data);
- headers[n_headers].cb_data = sizeof(khm_int32);
- } else {
- headers[n_headers].data = o->data;
- headers[n_headers].cb_data = o->cb_data;
- }
-
- n_headers++;
-
- o = TPARENT(o);
- } while(o);
-
- khui_context_set(KHUI_SCOPE_GROUP,
- NULL,
- KCDB_CREDTYPE_INVALID,
- NULL,
- headers,
- n_headers,
- tbl->credset);
- }
-
- } else {
- khm_handle cred;
-
- cred = (khm_handle) tbl->rows[row].data;
-
- khui_context_set(KHUI_SCOPE_CRED,
- NULL,
- KCDB_CREDTYPE_INVALID,
- cred,
- NULL,
- 0,
- tbl->credset);
- }
-}
-
-static void
-cw_select_all(khui_credwnd_tbl * tbl)
-{
- int i;
-
- for(i=0; i<tbl->n_rows; i++) {
- tbl->rows[i].flags |= KHUI_CW_ROW_SELECTED;
- cw_select_row_creds(tbl, i, TRUE);
- }
-
- cw_select_outline_level(tbl->outline, TRUE);
-
- cw_update_selection_state(tbl);
-
- cw_set_row_context(tbl, tbl->cursor_row);
-
- InvalidateRect(tbl->hwnd, NULL, FALSE);
-}
-
-static void
-cw_select_row(khui_credwnd_tbl * tbl, int row, WPARAM wParam)
-{
- int i;
- BOOL toggle;
- BOOL extend;
- int group_begin;
- int group_end;
-
- if (wParam & MK_CONTROL) {
- toggle = TRUE;
- extend = FALSE;
- } else if (wParam & MK_SHIFT) {
- toggle = FALSE;
- extend = TRUE;
- } else {
- toggle = FALSE;
- extend = FALSE;
- }
-
- if (row < 0 || row >= (int) tbl->n_rows)
- return;
-
- if (tbl->rows[row].flags & KHUI_CW_ROW_HEADER) {
- khui_credwnd_outline * o;
-
- o = (khui_credwnd_outline *) tbl->rows[row].data;
-
- group_begin = o->start;
- group_end = o->start + o->length - 1;
- } else {
- group_begin = row;
- group_end = row;
- }
-
- if (!toggle && !extend) {
- /* selecting a single row */
- cw_unselect_all(tbl);
-
- tbl->cursor_row = row;
- tbl->anchor_row = row;
-
- for (i = group_begin; i <= group_end; i++) {
- tbl->rows[i].flags |= KHUI_CW_ROW_SELECTED;
- cw_select_row_creds(tbl, i, TRUE);
- }
- } else if (toggle) {
- BOOL select;
-
- tbl->cursor_row = row;
- tbl->anchor_row = row;
-
- select = !(tbl->rows[row].flags & KHUI_CW_ROW_SELECTED);
-
- for (i = group_begin; i <= group_end; i++) {
- if (select)
- tbl->rows[i].flags |= KHUI_CW_ROW_SELECTED;
- else
- tbl->rows[i].flags &= ~KHUI_CW_ROW_SELECTED;
-
- cw_select_row_creds(tbl, i, select);
- }
- } else if (extend) {
- int range_begin;
- int range_end;
-
- cw_unselect_all(tbl);
-
- range_begin = min(row, tbl->anchor_row);
- range_end = max(row, tbl->anchor_row);
-
- for (i = range_begin; i <= range_end; i++) {
- tbl->rows[i].flags |= KHUI_CW_ROW_SELECTED;
-
- cw_select_row_creds(tbl, i, TRUE);
- }
-
- tbl->cursor_row = row;
- }
-
- cw_update_selection_state(tbl);
-
- cw_set_row_context(tbl, tbl->cursor_row);
-
- InvalidateRect(tbl->hwnd, NULL, FALSE);
-}
-
-static void
-cw_toggle_outline_state(khui_credwnd_tbl * tbl,
- khui_credwnd_outline * o) {
-
- int old_range_begin;
- int old_range_end;
- int new_range_begin;
- int new_range_end;
-
- old_range_begin = o->start;
- old_range_end = o->start + o->length - 1;
-
- o->flags ^= KHUI_CW_O_EXPAND;
-
- cw_update_outline(tbl);
- cw_update_extents(tbl, TRUE);
-
- new_range_begin = o->start;
- new_range_end = o->start + o->length - 1;
-
- if (tbl->cursor_row > old_range_end) {
- tbl->cursor_row -= old_range_end - new_range_end;
- } else if (tbl->cursor_row >= old_range_begin &&
- tbl->cursor_row <= old_range_end) {
- tbl->cursor_row = new_range_begin;
- }
-
- if (tbl->anchor_row > old_range_end) {
- tbl->anchor_row -= old_range_end - new_range_end;
- } else if (tbl->anchor_row >= old_range_begin &&
- tbl->anchor_row <= old_range_end) {
- tbl->anchor_row = new_range_begin;
- }
-
- InvalidateRect(tbl->hwnd, NULL, TRUE);
-
-}
-
-LRESULT cw_properties(HWND hwnd);
-
-LRESULT
-cw_wm_mouse(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
- khui_credwnd_tbl * tbl;
- int x,y;
- RECT r;
- int row;
- int col;
- int i;
- int nm_state,nm_row,nm_col;
-
- tbl = (khui_credwnd_tbl *)(LONG_PTR) GetWindowLongPtr(hwnd, 0);
-
- /* we are basically trying to capture events where the mouse is
- hovering over one of the 'hotspots'. There are two kinds of
- hotspots one is the little widget thinggy that you click on to
- expand or collapse an outline. The other is a text cell that
- is partially concealed. */
-
- x = GET_X_LPARAM(lParam);
- y = GET_Y_LPARAM(lParam);
- x += tbl->scr_left;
- y += tbl->scr_top - tbl->header_height;
-
- row = -1;
-
- for (i=0; i < tbl->n_rows; i++) {
- if (y >= tbl->rows[i].r_ext.top &&
- y < tbl->rows[i].r_ext.bottom) {
- row = i;
- break;
- }
- }
-
- col = -1;
- nm_state = CW_MOUSE_NONE;
- nm_row = nm_col = -1;
-
- for(i=0; i < (int) tbl->n_cols; i++) {
- if(x >= tbl->cols[i].x &&
- x < tbl->cols[i].x + tbl->cols[i].width) {
- col = i;
- break;
- }
- }
-
- if(wParam & MK_LBUTTON)
- nm_state = CW_MOUSE_LDOWN;
-
- if(row >= 0 && row < (int) tbl->n_rows) {
- nm_state |= CW_MOUSE_ROW;
- nm_row = row;
- nm_col = col;
- if(tbl->rows[row].flags & KHUI_CW_ROW_HEADER) {
- khui_credwnd_outline * o;
-
- o = (khui_credwnd_outline *) tbl->rows[row].data;
-
- /* are we on a widget then? */
- x -= tbl->cols[o->col].x;
-
- if (!(o->flags & KHUI_CW_O_NOOUTLINE)) {
- if(x >= 0 && x < KHUI_SMICON_CX) /* hit */ {
- nm_state |= CW_MOUSE_WOUTLINE | CW_MOUSE_WIDGET;
- } else if (tbl->cols[tbl->rows[row].col].attr_id ==
- KCDB_ATTR_ID_NAME &&
- col == tbl->rows[row].col &&
- x >= KHUI_SMICON_CX * 3 / 2 &&
- x < KHUI_SMICON_CX * 5 / 2){
- nm_state |= CW_MOUSE_WSTICKY | CW_MOUSE_WIDGET;
- } else if (tbl->cols[tbl->rows[row].col].attr_id ==
- KCDB_ATTR_ID_NAME &&
- col == tbl->rows[row].col &&
- x >= KHUI_SMICON_CX * 3 &&
- x < KHUI_SMICON_CX * 4) {
- nm_state |= CW_MOUSE_WICON | CW_MOUSE_WIDGET;
- }
- } else if (tbl->cols[o->col].attr_id == KCDB_ATTR_ID_NAME) {
- if (col == tbl->rows[row].col &&
- x >= 0 &&
- x < KHUI_SMICON_CX){
-
- nm_state |= CW_MOUSE_WSTICKY | CW_MOUSE_WIDGET;
-
- } else if (col == tbl->rows[row].col &&
- x >= KHUI_SMICON_CX * 3 / 2 &&
- x < KHUI_SMICON_CX * 5 / 2) {
- nm_state |= CW_MOUSE_WICON | CW_MOUSE_WIDGET;
- }
- }
- }
- }
-
- /* did the user drag the cursor off the current row? */
- if((tbl->mouse_state & CW_MOUSE_LDOWN) &&
- (nm_row != tbl->mouse_row)) {
- nm_state &= ~CW_MOUSE_WMASK;
- }
-
- if(!(nm_state & CW_MOUSE_LDOWN) &&
- (tbl->mouse_state & CW_MOUSE_LDOWN) &&
- tbl->mouse_row == nm_row) {
-
- if((nm_state & CW_MOUSE_WOUTLINE) &&
- (tbl->mouse_state & CW_MOUSE_WOUTLINE)) {
- /* click on an outline widget */
- khui_credwnd_outline * o;
-
- o = (khui_credwnd_outline *) tbl->rows[nm_row].data;
- tbl->mouse_state = CW_MOUSE_WIDGET | CW_MOUSE_WOUTLINE;
-
- cw_toggle_outline_state(tbl, o);
-
- return 0;
- } else if ((nm_state & CW_MOUSE_WSTICKY) &&
- (tbl->mouse_state & CW_MOUSE_WSTICKY)) {
-
- khui_credwnd_outline * o;
- khm_handle ident;
- khm_int32 idf = 0;
-
- o = tbl->rows[nm_row].data;
- ident = o->data;
-
- kcdb_identity_get_flags(ident, &idf);
- idf &= KCDB_IDENT_FLAG_STICKY;
- kcdb_identity_set_flags(ident, (idf ^ KCDB_IDENT_FLAG_STICKY),
- KCDB_IDENT_FLAG_STICKY);
-
- tbl->mouse_state = CW_MOUSE_WIDGET | CW_MOUSE_WSTICKY;
-
- return 0;
- } else if ((nm_state & CW_MOUSE_WICON) &&
- (tbl->mouse_state & CW_MOUSE_WICON)) {
- /* click on an row icon */
- cw_select_row(tbl, nm_row, wParam);
- cw_properties(hwnd);
- } else {
- /* click on a row */
- cw_select_row(tbl, nm_row, wParam);
-
- if (tbl->mouse_col == nm_col &&
- nm_col >= 0 &&
- tbl->cols[nm_col].attr_id == CW_CA_FLAGS &&
- !(tbl->rows[nm_row].flags & KHUI_CW_ROW_HEADER)) {
- /* clicked on a cred icon */
-
- cw_properties(hwnd);
- }
- }
- }
-
- /* ok, now if we are changing state, we need to invalidate a few
- regions */
- if (((tbl->mouse_state ^ nm_state) & (CW_MOUSE_WIDGET |
- CW_MOUSE_WOUTLINE |
- CW_MOUSE_WSTICKY)) ||
- tbl->mouse_row != nm_row) {
-
- if(tbl->mouse_state & CW_MOUSE_WOUTLINE) {
- r.left = tbl->cols[tbl->mouse_col].x - tbl->scr_left;
- r.top = tbl->mouse_row * tbl->cell_height +
- tbl->header_height - tbl->scr_top;
- r.right = r.left + KHUI_SMICON_CX;
- r.bottom = r.top + tbl->cell_height;
- InvalidateRect(tbl->hwnd, &r, TRUE);
- }
- if(tbl->mouse_state & CW_MOUSE_WSTICKY) {
- if (tbl->flags & KHUI_CW_TBL_EXPIDENT) {
-
- if (tbl->mouse_row >= 0 && tbl->mouse_row < tbl->n_rows) {
- r = tbl->rows[tbl->mouse_row].r_ext;
- OffsetRect(&r, -tbl->scr_left, tbl->header_height - tbl->scr_top);
- r.right = r.left + KHUI_SMICON_CX;
- InvalidateRect(tbl->hwnd, &r, TRUE);
- }
-
- } else {
- r.left = KHUI_SMICON_CX * 3 / 2 +
- tbl->cols[tbl->mouse_col].x - tbl->scr_left;
- r.top = tbl->mouse_row * tbl->cell_height +
- tbl->header_height - tbl->scr_top;
- r.right = r.left + KHUI_SMICON_CX;
- r.bottom = r.top + tbl->cell_height;
- }
- InvalidateRect(tbl->hwnd, &r, TRUE);
- }
-
- if ((tbl->mouse_state & nm_state) & CW_MOUSE_LDOWN) {
- if (tbl->mouse_row == nm_row)
- tbl->mouse_col = nm_col;
- } else {
- tbl->mouse_col = nm_col;
- tbl->mouse_row = nm_row;
- }
- tbl->mouse_state = nm_state;
-
- /* same code block as above */
- if(tbl->mouse_state & CW_MOUSE_WOUTLINE) {
- r.left = tbl->cols[tbl->mouse_col].x - tbl->scr_left;
- r.top = tbl->mouse_row * tbl->cell_height +
- tbl->header_height - tbl->scr_top;
- r.right = r.left + KHUI_SMICON_CX;
- r.bottom = r.top + tbl->cell_height;
- InvalidateRect(tbl->hwnd, &r, TRUE);
- }
- if(tbl->mouse_state & CW_MOUSE_WSTICKY) {
- if (tbl->flags & KHUI_CW_TBL_EXPIDENT) {
-
- if (tbl->mouse_row >= 0 && tbl->mouse_row < tbl->n_rows) {
- r = tbl->rows[tbl->mouse_row].r_ext;
- OffsetRect(&r, -tbl->scr_left, tbl->header_height - tbl->scr_top);
- r.right = r.left + KHUI_SMICON_CX;
- InvalidateRect(tbl->hwnd, &r, TRUE);
- }
-
- } else {
- r.left = KHUI_SMICON_CX * 3 / 2 +
- tbl->cols[tbl->mouse_col].x - tbl->scr_left;
- r.top = tbl->mouse_row * tbl->cell_height +
- tbl->header_height - tbl->scr_top;
- r.right = r.left + KHUI_SMICON_CX;
- r.bottom = r.top + tbl->cell_height;
- }
- InvalidateRect(tbl->hwnd, &r, TRUE);
- }
- } else if(tbl->mouse_state != nm_state) {
-
- if ((tbl->mouse_state & nm_state) & CW_MOUSE_LDOWN) {
- if (tbl->mouse_row == nm_row) {
- tbl->mouse_col = nm_col;
- tbl->mouse_state = nm_state;
- }
- } else {
- tbl->mouse_col = nm_col;
- tbl->mouse_row = nm_row;
- tbl->mouse_state = nm_state;
- }
- }
-
- /* if it was a double click, also show the property
- window */
- if (uMsg == WM_LBUTTONDBLCLK) {
- cw_properties(hwnd);
- }
-
- return 0;
-}
-
-LRESULT
-cw_wm_hscroll(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
- khui_credwnd_tbl * tbl;
- SCROLLINFO si;
- RECT cr;
- RECT lr;
- RECT sr;
- int dx;
- int newpos;
-
- tbl = (khui_credwnd_tbl *) (LONG_PTR) GetWindowLongPtr(hwnd, 0);
- GetClientRect(hwnd, &cr);
- dx = tbl->scr_left;
-
- switch(LOWORD(wParam)) {
- case SB_LEFT:
- newpos = 0;
- break;
-
- case SB_RIGHT:
- newpos = tbl->ext_width;
- break;
-
- case SB_LINELEFT:
- newpos = tbl->scr_left - (tbl->ext_width / 12);
- break;
-
- case SB_LINERIGHT:
- newpos = tbl->scr_left + (tbl->ext_width / 12);
- break;
-
- case SB_PAGELEFT:
- newpos = tbl->scr_left - (cr.right - cr.left);
- break;
-
- case SB_PAGERIGHT:
- newpos = tbl->scr_left + (cr.right - cr.left);
- break;
-
- case SB_THUMBTRACK:
- case SB_THUMBPOSITION:
- ZeroMemory(&si, sizeof(si));
- si.cbSize = sizeof(si);
- si.fMask = SIF_TRACKPOS;
- GetScrollInfo(hwnd, SB_HORZ, &si);
-
- newpos = si.nTrackPos;
- break;
-
- default:
- return DefWindowProc(hwnd, uMsg, wParam, lParam);
- }
-
- //cr.top += tbl->header_height;
- tbl->scr_left = newpos;
- cw_update_extents(tbl, TRUE);
-
- dx -= tbl->scr_left;
-
- /* exclude the watermark */
- lr.bottom = cr.bottom;
- lr.right = cr.right;
- lr.top = max(cr.bottom - tbl->kbm_logo_shade.cy, cr.top);
- lr.left = max(cr.right - tbl->kbm_logo_shade.cx, cr.left);
-
- if(cr.top < lr.top && cr.left < cr.right) {
- sr.left = cr.left;
- sr.right = cr.right;
- sr.top = cr.top;
- sr.bottom = lr.top;
- ScrollWindowEx(
- hwnd,
- dx,
- 0,
- &sr,
- &sr,
- NULL,
- NULL,
- SW_INVALIDATE | SW_SCROLLCHILDREN);
- }
-
- if(cr.left < lr.left && lr.top < lr.bottom) {
- sr.left = cr.left;
- sr.right = lr.left;
- sr.top = lr.top;
- sr.bottom = lr.bottom;
- ScrollWindowEx(
- hwnd,
- dx,
- 0,
- &sr,
- &sr,
- NULL,
- NULL,
- SW_INVALIDATE | SW_SCROLLCHILDREN);
- }
-
- if(lr.top < lr.bottom && lr.left < lr.right) {
- InvalidateRect(hwnd, &lr, FALSE);
- }
-
- return DefWindowProc(hwnd, uMsg, wParam, lParam);
-}
-
-static void
-cw_vscroll_to_pos(HWND hwnd, khui_credwnd_tbl * tbl, int newpos) {
- RECT cr;
- RECT sr;
- RECT lr;
- int dy;
-
- GetClientRect(hwnd, &cr);
- cr.top += tbl->header_height;
- dy = tbl->scr_top;
-
- tbl->scr_top = newpos;
- cw_update_extents(tbl, TRUE);
-
- dy -= tbl->scr_top;
-
- /* exclude watermark */
- lr.bottom = cr.bottom;
- lr.right = cr.right;
- lr.top = max(cr.bottom - tbl->kbm_logo_shade.cy, cr.top);
- lr.left = max(cr.right - tbl->kbm_logo_shade.cx, cr.left);
-
- if(cr.left < lr.left && cr.top < cr.bottom) {
- sr.left = cr.left;
- sr.right = lr.left;
- sr.top = cr.top;
- sr.bottom = cr.bottom;
- ScrollWindowEx(
- hwnd,
- 0,
- dy,
- &sr,
- &sr,
- NULL,
- NULL,
- SW_INVALIDATE);
- }
-
- if(lr.left < lr.right && cr.top < lr.top) {
- sr.left = lr.left;
- sr.right = lr.right;
- sr.top = cr.top;
- sr.bottom = lr.top;
- ScrollWindowEx(
- hwnd,
- 0,
- dy,
- &sr,
- &sr,
- NULL,
- NULL,
- SW_INVALIDATE);
- }
-
- if(lr.top < lr.bottom && lr.left < lr.right) {
- InvalidateRect(hwnd, &lr, FALSE);
- }
-}
-
-LRESULT
-cw_wm_vscroll(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
- khui_credwnd_tbl * tbl;
- SCROLLINFO si;
- int newpos;
- RECT cr;
-
- tbl = (khui_credwnd_tbl *)(LONG_PTR) GetWindowLongPtr(hwnd, 0);
-
- GetClientRect(hwnd, &cr);
- cr.top += tbl->header_height;
-
- switch(LOWORD(wParam)) {
- case SB_LEFT:
- newpos = 0;
- break;
-
- case SB_BOTTOM:
- newpos = tbl->ext_height;
- break;
-
- case SB_LINEUP:
- newpos = tbl->scr_top - (tbl->ext_height / 12);
- break;
-
- case SB_LINEDOWN:
- newpos = tbl->scr_top + (tbl->ext_height / 12);
- break;
-
- case SB_PAGEUP:
- newpos = tbl->scr_top - (cr.bottom - cr.top);
- break;
-
- case SB_PAGEDOWN:
- newpos = tbl->scr_top + (cr.bottom - cr.top);
- break;
-
- case SB_THUMBTRACK:
- case SB_THUMBPOSITION:
- ZeroMemory(&si, sizeof(si));
- si.cbSize = sizeof(si);
- si.fMask = SIF_TRACKPOS;
- GetScrollInfo(hwnd, SB_VERT, &si);
-
- newpos = si.nTrackPos;
- break;
-
- default:
- return DefWindowProc(hwnd, uMsg, wParam, lParam);
- }
-
- cw_vscroll_to_pos(hwnd, tbl, newpos);
-
- return DefWindowProc(hwnd, uMsg, wParam, lParam);
-}
-
-static void
-cw_ensure_row_visible(HWND hwnd, khui_credwnd_tbl * tbl, int row) {
- RECT r;
- int newpos;
-
- if (row < 0)
- row = 0;
- else if (row >= (int) tbl->n_rows)
- row = (int) tbl->n_rows - 1;
-
- GetClientRect(hwnd, &r);
- r.top += tbl->header_height;
-
- if (row * tbl->cell_height < tbl->scr_top) {
- newpos = row * tbl->cell_height;
- } else if ((row + 1) * tbl->cell_height
- > tbl->scr_top + (r.bottom - r.top)) {
- newpos = ((row + 1) * tbl->cell_height) - (r.bottom - r.top);
- } else
- return;
-
- cw_vscroll_to_pos(hwnd, tbl, newpos);
-}
-
-static INT_PTR CALLBACK
-cw_pp_ident_proc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam)
-{
- khui_property_sheet * s;
-
- switch(uMsg) {
- case WM_INITDIALOG:
- {
- PROPSHEETPAGE * p;
- khm_handle ident;
- wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
- khm_size t;
- khm_int32 i;
-
- p = (PROPSHEETPAGE *) lParam;
- s = (khui_property_sheet *) p->lParam;
-
-#pragma warning(push)
-#pragma warning(disable: 4244)
- SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) s);
-#pragma warning(pop)
-
- ident = s->identity;
-
- t = sizeof(idname);
- kcdb_identity_get_name(ident, idname, &t);
- SetDlgItemText(hwnd, IDC_PP_IDNAME, idname);
-
- kcdb_identity_get_flags(ident, &i);
-
- CheckDlgButton(hwnd, IDC_PP_IDDEF,
- ((i & KCDB_IDENT_FLAG_DEFAULT)?BST_CHECKED:
- BST_UNCHECKED));
-
- /* if it's default, you can't change it further */
- if (i & KCDB_IDENT_FLAG_DEFAULT) {
- EnableWindow(GetDlgItem(hwnd, IDC_PP_IDDEF), FALSE);
- }
-
- CheckDlgButton(hwnd, IDC_PP_IDSEARCH,
- ((i & KCDB_IDENT_FLAG_SEARCHABLE)?BST_CHECKED:
- BST_UNCHECKED));
-
- CheckDlgButton(hwnd, IDC_PP_STICKY,
- ((i & KCDB_IDENT_FLAG_STICKY)?BST_CHECKED:
- BST_UNCHECKED));
-
- khui_property_wnd_set_record(GetDlgItem(hwnd, IDC_PP_PROPLIST),
- ident);
- }
- return TRUE;
-
- case WM_COMMAND:
- s = (khui_property_sheet *) (LONG_PTR)
- GetWindowLongPtr(hwnd, DWLP_USER);
-
- switch(wParam) {
- case MAKEWPARAM(IDC_PP_IDDEF, BN_CLICKED):
- /* fallthrough */
- case MAKEWPARAM(IDC_PP_STICKY, BN_CLICKED):
-
- if (s->status != KHUI_PS_STATUS_NONE)
- PropSheet_Changed(s->hwnd, hwnd);
- return TRUE;
-
- case MAKEWPARAM(IDC_PP_CONFIG, BN_CLICKED):
- {
- khui_config_node cfg_id = NULL;
- khui_config_node cfg_ids = NULL;
- wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
- khm_size cb;
- khm_int32 rv;
-
- khm_refresh_config();
-
- rv = khui_cfg_open(NULL,
- L"KhmIdentities",
- &cfg_ids);
-
- if (KHM_FAILED(rv))
- return TRUE;
-
- cb = sizeof(idname);
- if (KHM_SUCCEEDED(kcdb_identity_get_name(s->identity,
- idname,
- &cb))) {
- rv = khui_cfg_open(cfg_ids,
- idname,
- &cfg_id);
- }
-
- if (cfg_id)
- khm_show_config_pane(cfg_id);
- else
- khm_show_config_pane(cfg_ids);
-
- if (cfg_ids)
- khui_cfg_release(cfg_ids);
- if (cfg_id)
- khui_cfg_release(cfg_id);
- }
- return TRUE;
- }
- return FALSE;
-
- case WM_NOTIFY:
- {
- LPPSHNOTIFY lpp;
- khm_int32 flags;
-
- lpp = (LPPSHNOTIFY) lParam;
- s = (khui_property_sheet *) (LONG_PTR)
- GetWindowLongPtr(hwnd, DWLP_USER);
-
- switch(lpp->hdr.code) {
- case PSN_APPLY:
- flags = 0;
- if (IsDlgButtonChecked(hwnd, IDC_PP_STICKY) == BST_CHECKED)
- flags |= KCDB_IDENT_FLAG_STICKY;
- if (IsDlgButtonChecked(hwnd, IDC_PP_IDDEF) == BST_CHECKED)
- flags |= KCDB_IDENT_FLAG_DEFAULT;
-
- kcdb_identity_set_flags(s->identity, flags,
- KCDB_IDENT_FLAG_STICKY |
- KCDB_IDENT_FLAG_DEFAULT);
- return TRUE;
-
- case PSN_RESET:
- kcdb_identity_get_flags(s->identity, &flags);
-
- CheckDlgButton(hwnd,
- IDC_PP_IDDEF,
- ((flags & KCDB_IDENT_FLAG_DEFAULT)?BST_CHECKED:
- BST_UNCHECKED));
-
- /* if it's default, you can't change it further */
- if (flags & KCDB_IDENT_FLAG_DEFAULT) {
- EnableWindow(GetDlgItem(hwnd, IDC_PP_IDDEF), FALSE);
- }
-
- CheckDlgButton(hwnd, IDC_PP_IDSEARCH,
- ((flags & KCDB_IDENT_FLAG_SEARCHABLE)?BST_CHECKED:BST_UNCHECKED));
-
- CheckDlgButton(hwnd, IDC_PP_STICKY,
- ((flags & KCDB_IDENT_FLAG_STICKY)?BST_CHECKED:BST_UNCHECKED));
- return TRUE;
- }
- }
- break;
- }
- return FALSE;
-}
-
-static INT_PTR CALLBACK
-cw_pp_cred_proc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam
- )
-{
- switch(uMsg) {
- case WM_INITDIALOG:
- {
- khui_property_sheet * s;
- PROPSHEETPAGE * p;
- khm_handle cred;
-
- p = (PROPSHEETPAGE *) lParam;
- s = (khui_property_sheet *) p->lParam;
-
-#pragma warning(push)
-#pragma warning(disable: 4244)
- SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) s);
-#pragma warning(pop)
-
- cred = s->cred;
-
- khui_property_wnd_set_record(
- GetDlgItem(hwnd, IDC_PP_CPROPLIST),
- cred);
- }
- return TRUE;
- }
- return FALSE;
-}
-
-static void
-cw_pp_begin(khui_property_sheet * s)
-{
- PROPSHEETPAGE *p;
-
- if(s->identity) {
- p = PMALLOC(sizeof(*p));
- ZeroMemory(p, sizeof(*p));
-
- p->dwSize = sizeof(*p);
- p->dwFlags = 0;
- p->hInstance = khm_hInstance;
- p->pszTemplate = MAKEINTRESOURCE(IDD_PP_IDENT);
- p->pfnDlgProc = cw_pp_ident_proc;
- p->lParam = (LPARAM) s;
-
- khui_ps_add_page(s, KHUI_PPCT_IDENTITY, 129, p, NULL);
- }
-
- if(s->cred) {
- p = PMALLOC(sizeof(*p));
- ZeroMemory(p, sizeof(*p));
-
- p->dwSize = sizeof(*p);
- p->dwFlags = 0;
- p->hInstance = khm_hInstance;
- p->pszTemplate = MAKEINTRESOURCE(IDD_PP_CRED);
- p->pfnDlgProc = cw_pp_cred_proc;
- p->lParam = (LPARAM) s;
-
- khui_ps_add_page(s, KHUI_PPCT_CREDENTIAL, 128, p, NULL);
- }
-}
-
-static void
-cw_pp_precreate(khui_property_sheet * s)
-{
- khui_ps_show_sheet(khm_hwnd_main, s);
-
- khm_add_property_sheet(s);
-}
-
-static void
-cw_pp_end(khui_property_sheet * s)
-{
- khui_property_page * p = NULL;
-
- khui_ps_find_page(s, KHUI_PPCT_IDENTITY, &p);
- if(p) {
- PFREE(p->p_page);
- p->p_page = NULL;
- }
-
- p = NULL;
-
- khui_ps_find_page(s, KHUI_PPCT_CREDENTIAL, &p);
- if(p) {
- PFREE(p->p_page);
- p->p_page = NULL;
- }
-}
-
-static void
-cw_pp_destroy(khui_property_sheet *ps)
-{
- if(ps->ctx.scope == KHUI_SCOPE_CRED) {
- if(ps->header.pszCaption)
- PFREE((LPWSTR) ps->header.pszCaption);
- }
-
- khui_context_release(&ps->ctx);
-
- khui_ps_destroy_sheet(ps);
-
- /* this is pretty weird because ps gets freed when
- khui_ps_destroy_sheet() is called. However, since destroying
- ps involves sending a WM_DESTROY message to the property sheet,
- we still need to keep it on the property sheet chain (or else
- the messages will not be delivered). This is only safe because
- we are not relinquishing the thread in-between destroying ps
- and removing it from the chain. */
-
- /* TODO: fix this */
- khm_del_property_sheet(ps);
-}
-
-LRESULT
-cw_properties(HWND hwnd)
-{
- /* show a property sheet of some sort */
- khui_action_context ctx;
- khui_property_sheet * ps;
- khui_credwnd_tbl * tbl;
-
- khui_context_get(&ctx);
- tbl = (khui_credwnd_tbl *)(LONG_PTR) GetWindowLongPtr(hwnd, 0);
-
- if(ctx.scope == KHUI_SCOPE_NONE) {
- khui_context_release(&ctx);
- return FALSE;
-
- /* While it seems like a good idea, doing this is not */
-#if 0
- /* try to establish a context based on the current cursor
- position */
- if(tbl->cursor_row >= 0 && tbl->cursor_row < (int) tbl->n_rows) {
- if(tbl->rows[tbl->cursor_row].flags & KHUI_CW_ROW_HEADER) {
- if(tbl->cols[tbl->rows[tbl->cursor_row].col].attr_id == KCDB_ATTR_ID_NAME) {
- /* identity context */
- ctx.ctx = KHUI_SCOPE_IDENT;
- ctx.identity = (khm_handle)
- ((khui_credwnd_outline *) tbl->rows[tbl->cursor_row].data)->data;
- } else if(tbl->cols[tbl->rows[tbl->cursor_row].col].attr_id == KCDB_ATTR_TYPE_NAME) {
- ctx.ctx = KHUI_SCOPE_CREDTYPE;
- ctx.cred_type = (khm_int32) (DWORD_PTR)
- ((khui_credwnd_outline *) tbl->rows[tbl->cursor_row].data)->data;
- } else {
- ctx.ctx = KHUI_SCOPE_GROUP;
- //ctx.parm = (khm_lparm) tbl->rows[tbl->cursor_row].data;
- /* TODO: Figure out method of establishing a credgroup */
- }
- } else {
- /* a credential context */
- ctx.ctx = KHUI_SCOPE_CRED;
- ctx.cred = (khm_handle) tbl->rows[tbl->cursor_row].data;
- }
- }
-#endif
- }
-
- /* if still no context, then we can't show a property sheet */
- if(ctx.scope == KHUI_SCOPE_NONE) {
- khui_context_release(&ctx);
- return FALSE;
- }
-
- khui_ps_create_sheet(&ps);
-
- if(ctx.scope == KHUI_SCOPE_IDENT) {
- khm_handle ident;
- khm_size t;
-
- ident = ctx.identity;
-
- ps->header.hInstance = khm_hInstance;
- ps->header.pszIcon = MAKEINTRESOURCE(IDI_MAIN_APP);
-
- kcdb_identity_get_name(ident, NULL, &t);
-
- if(t > 0) {
- ps->header.pszCaption = PMALLOC(t);
- kcdb_identity_get_name(ident,
- (wchar_t *) ps->header.pszCaption, &t);
- } else {
- ps->header.pszCaption = NULL;
- }
-
- ps->ctx = ctx;
- ps->identity = ident;
- ps->credtype = KCDB_CREDTYPE_INVALID;
-
- kmq_post_message(KMSG_CRED, KMSG_CRED_PP_BEGIN, 0, (void *) ps);
-
- } else if(ctx.scope == KHUI_SCOPE_CREDTYPE) {
- khm_size t = 0;
- khm_int32 cred_type;
-
- if (ctx.identity == NULL) {
- /* currently, we can't show a property sheet at this point
- since most credentials providers don't provide a
- property sheet that works without an identity. */
-
- khui_context_release(&ctx);
- khui_ps_destroy_sheet(ps);
- return TRUE;
- }
-
- cred_type = ctx.cred_type;
-
- ps->header.hInstance = khm_hInstance;
- ps->header.pszIcon = MAKEINTRESOURCE(IDI_MAIN_APP);
-
- ps->ctx = ctx;
- ps->credtype = cred_type;
-
- if(ctx.identity) {
- ps->identity = ctx.identity;
- /* also, if there is an associated identity, we assume that
- the properties are for the specified credentials type
- specific to the identity. Hence we change the title to
- something else */
- kcdb_identity_get_name(ctx.identity, NULL, &t);
- if (t > 0) {
- ps->header.pszCaption = PMALLOC(t);
- kcdb_identity_get_name(ctx.identity, (wchar_t *) ps->header.pszCaption, &t);
- } else {
- ps->header.pszCaption = NULL;
- }
- } else {
- /* we don't actually reach here since we handle this case
- above */
- kcdb_credtype_describe(cred_type, NULL, &t, KCDB_TS_LONG);
- if(t > 0) {
- ps->header.pszCaption = PMALLOC(t);
- kcdb_credtype_describe(cred_type, (wchar_t *) ps->header.pszCaption, &t, KCDB_TS_LONG);
- } else {
- ps->header.pszCaption = NULL;
- }
- }
-
- kmq_post_message(KMSG_CRED, KMSG_CRED_PP_BEGIN, 0, (void *) ps);
- } else if(ctx.scope == KHUI_SCOPE_CRED) {
- khm_handle cred;
- khm_size t;
-
- cred = ctx.cred;
-
- ps->header.hInstance = khm_hInstance;
- ps->header.pszIcon = MAKEINTRESOURCE(IDI_MAIN_APP);
- ps->ctx = ctx;
-
- kcdb_cred_get_name(cred, NULL, &t);
- ps->header.pszCaption = PMALLOC(t);
- kcdb_cred_get_name(cred, (LPWSTR) ps->header.pszCaption, &t);
-
- kcdb_cred_get_identity(cred, &ps->identity);
- kcdb_cred_get_type(cred, &ps->credtype);
- ps->cred = cred;
-
- kmq_post_message(KMSG_CRED, KMSG_CRED_PP_BEGIN, 0, (void *) ps);
- } else {
- khui_context_release(&ctx);
- khui_ps_destroy_sheet(ps);
- }
-
- /* by the way, if we are actually opening a property sheet, we
- leave ctx held (which is now copied to ps->ctx). it will be
- released when the property sheet is destroyed */
-
- return TRUE;
-}
-
-LRESULT
-cw_wm_command(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
- khui_credwnd_tbl * tbl;
-
- tbl = (khui_credwnd_tbl *)(LONG_PTR) GetWindowLongPtr(hwnd, 0);
-
- if(HIWORD(wParam) == BN_CLICKED &&
- LOWORD(wParam) == KHUI_HTWND_CTLID) {
-
- wchar_t wid[256];
- /* a hyperlink was activated */
- khui_htwnd_link * l;
- l = (khui_htwnd_link *) lParam;
- StringCchCopyN(wid, ARRAYLENGTH(wid), l->id, l->id_len);
- wid[l->id_len] = 0;
-
- if(!wcscmp(wid, L"NewCreds")) {
- PostMessage(khm_hwnd_main, WM_COMMAND,
- MAKEWPARAM(KHUI_ACTION_NEW_CRED,0), 0);
- }
- return TRUE;
- }
-
- switch(LOWORD(wParam))
- {
- case KHUI_PACTION_ENTER:
- /* enter key is a synonym for the default action, on the
- context, which is to lauch a property sheet */
- /* fallthrough */
- case KHUI_ACTION_PROPERTIES:
- {
- return cw_properties(hwnd);
- }
- break;
-
- case KHUI_ACTION_LAYOUT_RELOAD:
- {
- wchar_t cname[KCONF_MAXCCH_NAME];
- khm_size cb;
-
- cname[0] = L'\0';
-
- if (tbl->csp_view) {
- cb = sizeof(cname);
- khc_get_config_space_name(tbl->csp_view,
- cname,
- &cb);
- }
-
- cw_unload_view(tbl);
-
- cw_load_view(tbl, ((cname[0])?cname: NULL), hwnd);
- cw_insert_header_cols(tbl);
-
- cw_update_creds(tbl);
- cw_update_outline(tbl);
- cw_update_selection_state(tbl);
- cw_update_extents(tbl, TRUE);
-
- InvalidateRect(tbl->hwnd, NULL, TRUE);
- }
- break;
-
- case KHUI_ACTION_LAYOUT_ID:
- {
- cw_save_view(tbl, NULL);
- cw_unload_view(tbl);
-
- cw_load_view(tbl, L"ByIdentity", hwnd);
- cw_insert_header_cols(tbl);
-
- cw_update_creds(tbl);
- cw_update_outline(tbl);
- cw_update_selection_state(tbl);
- cw_update_extents(tbl, TRUE);
-
- InvalidateRect(tbl->hwnd, NULL, TRUE);
-
- }
- break;
-
- case KHUI_ACTION_LAYOUT_LOC:
- {
- cw_save_view(tbl, NULL);
- cw_unload_view(tbl);
-
- cw_load_view(tbl, L"ByLocation", hwnd);
- cw_insert_header_cols(tbl);
-
- cw_update_creds(tbl);
- cw_update_outline(tbl);
- cw_update_selection_state(tbl);
- cw_update_extents(tbl, TRUE);
-
- InvalidateRect(tbl->hwnd, NULL, TRUE);
-
- }
- break;
-
- case KHUI_ACTION_LAYOUT_TYPE:
- {
- cw_save_view(tbl, NULL);
- cw_unload_view(tbl);
-
- cw_load_view(tbl, L"ByType", hwnd);
- cw_insert_header_cols(tbl);
-
- cw_update_creds(tbl);
- cw_update_outline(tbl);
- cw_update_selection_state(tbl);
- cw_update_extents(tbl, TRUE);
-
- InvalidateRect(tbl->hwnd, NULL, TRUE);
-
- }
- break;
-
- case KHUI_ACTION_LAYOUT_CUST:
- {
- cw_save_view(tbl, NULL);
- cw_unload_view(tbl);
-
- cw_load_view(tbl, L"Custom_0", hwnd);
- cw_insert_header_cols(tbl);
-
- cw_update_creds(tbl);
- cw_update_outline(tbl);
- cw_update_selection_state(tbl);
- cw_update_extents(tbl, TRUE);
-
- InvalidateRect(tbl->hwnd, NULL, TRUE);
-
- }
- break;
-
- case KHUI_ACTION_LAYOUT_MINI:
- {
- cw_save_view(tbl, NULL);
- cw_unload_view(tbl);
-
- cw_load_view(tbl, NULL, hwnd);
- cw_insert_header_cols(tbl);
-
- cw_update_creds(tbl);
- cw_update_outline(tbl);
- cw_update_selection_state(tbl);
- cw_update_extents(tbl, TRUE);
-
- InvalidateRect(tbl->hwnd, NULL, TRUE);
- }
- break;
-
- case KHUI_PACTION_UP:
- case KHUI_PACTION_UP_EXTEND:
- case KHUI_PACTION_UP_TOGGLE:
- { /* cursor up */
- khm_int32 new_row;
- WPARAM wp = 0;
-
- new_row = tbl->cursor_row - 1;
-
- /* checking both bounds. we make no assumption about the
- value of cursor_row before this message */
- if(new_row < 0)
- new_row = 0;
- if(new_row >= (int) tbl->n_rows)
- new_row = (int) tbl->n_rows - 1;
-
- if (LOWORD(wParam) == KHUI_PACTION_UP)
- wp = 0;
- else if (LOWORD(wParam) == KHUI_PACTION_UP_EXTEND)
- wp = MK_SHIFT;
- else if (LOWORD(wParam) == KHUI_PACTION_UP_TOGGLE)
- wp = 0; //MK_CONTROL;
- else {
-#ifdef DEBUG
- assert(FALSE);
-#endif
- }
-
- cw_select_row(tbl, new_row, wp);
- cw_ensure_row_visible(hwnd, tbl, new_row);
- }
- break;
-
- case KHUI_PACTION_PGUP_EXTEND:
- case KHUI_PACTION_PGUP:
- {
- khm_int32 new_row;
- WPARAM wp;
- RECT r;
-
- if (LOWORD(wParam) == KHUI_PACTION_PGUP_EXTEND)
- wp = MK_SHIFT;
- else
- wp = 0;
-
- GetClientRect(hwnd, &r);
-
- new_row = tbl->cursor_row -
- ((r.bottom - r.top) - tbl->header_height) / tbl->cell_height;
-
- if (new_row < 0)
- new_row = 0;
- if (new_row >= (int) tbl->n_rows)
- new_row = (int) tbl->n_rows - 1;
-
- cw_select_row(tbl, new_row, wp);
- cw_ensure_row_visible(hwnd, tbl, new_row);
- }
- break;
-
- case KHUI_PACTION_DOWN:
- case KHUI_PACTION_DOWN_EXTEND:
- case KHUI_PACTION_DOWN_TOGGLE:
- { /* cursor down */
- khm_int32 new_row;
- WPARAM wp = 0;
-
- new_row = tbl->cursor_row + 1;
-
- /* checking both bounds. we make no assumption about the
- value of cursor_row before this message */
- if(new_row < 0)
- new_row = 0;
- if(new_row >= (int) tbl->n_rows)
- new_row = (int) tbl->n_rows - 1;
-
- if (LOWORD(wParam) == KHUI_PACTION_DOWN)
- wp = 0;
- else if (LOWORD(wParam) == KHUI_PACTION_DOWN_EXTEND)
- wp = MK_SHIFT;
- else if (LOWORD(wParam) == KHUI_PACTION_DOWN_TOGGLE)
- wp = 0; //MK_CONTROL;
- else {
-#ifdef DEBUG
- assert(FALSE);
-#endif
- }
-
- cw_select_row(tbl, new_row, wp);
- cw_ensure_row_visible(hwnd, tbl, new_row);
- }
- break;
-
- case KHUI_PACTION_PGDN_EXTEND:
- case KHUI_PACTION_PGDN:
- {
- khm_int32 new_row;
- RECT r;
- WPARAM wp;
-
- if (LOWORD(wParam) == KHUI_PACTION_PGDN_EXTEND)
- wp = MK_SHIFT;
- else
- wp = 0;
-
- GetClientRect(hwnd, &r);
-
- new_row = tbl->cursor_row +
- ((r.bottom - r.top) - tbl->header_height) / tbl->cell_height;
-
- if (new_row < 0)
- new_row = 0;
- if (new_row >= (int) tbl->n_rows)
- new_row = (int) tbl->n_rows - 1;
-
- cw_select_row(tbl, new_row, wp);
- cw_ensure_row_visible(hwnd, tbl, new_row);
- }
- break;
-
- case KHUI_PACTION_SELALL:
- {
- cw_select_all(tbl);
- }
- break;
-
- case KHUI_PACTION_LEFT:
- { /* collapse and up*/
- khui_credwnd_outline * o;
- int r;
-
- if(tbl->cursor_row < 0 || tbl->cursor_row >= (int) tbl->n_rows) {
- cw_select_row(tbl, 0, 0);
- break;
- }
-
- for(r = tbl->cursor_row;
- (r >= 0 && !(tbl->rows[r].flags & KHUI_CW_ROW_HEADER));
- r--);
-
- if(r < 0)
- break;
-
- /* If we were not on a header, we collapse the innermost
- outline. Otherwise, we collpase up to the parent
- outline level */
-
- if(r != tbl->cursor_row) {
- o = (khui_credwnd_outline *) tbl->rows[r].data;
-
- cw_toggle_outline_state(tbl, o);
- } else {
- o = (khui_credwnd_outline *) tbl->rows[r].data;
-
- if(o->flags & KHUI_CW_O_EXPAND) {
- cw_toggle_outline_state(tbl, o);
- } else {
- o = TPARENT(o);
- if(o) {
- cw_toggle_outline_state(tbl, o);
- r = o->start;
- } else if(r > 0)
- r--;
- }
- }
-
- cw_select_row(tbl, r, 0);
- }
- break;
-
- case KHUI_PACTION_RIGHT:
- { /* expand and down*/
- khui_credwnd_outline * o;
- int r;
-
- if(tbl->cursor_row < 0 ||
- tbl->cursor_row >= (int) tbl->n_rows) {
- cw_select_row(tbl, 0, 0);
- break;
- }
-
- r = tbl->cursor_row;
-
- if(tbl->rows[r].flags & KHUI_CW_ROW_HEADER) {
- o = (khui_credwnd_outline *) tbl->rows[r].data;
- if(!(o->flags & KHUI_CW_O_EXPAND)) {
- cw_toggle_outline_state(tbl, o);
- }
- }
-
- r++;
- if (r >= (int) tbl->n_rows)
- r = (int)tbl->n_rows - 1;
-
- cw_select_row(tbl, r, 0);
- }
- break;
- }
- return DefWindowProc(hwnd, uMsg, wParam, lParam);
-}
-
-LRESULT
-cw_wm_contextmenu(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
- RECT r;
- int x,y;
- int row;
- khui_credwnd_tbl * tbl;
-
- tbl = (khui_credwnd_tbl *)(LONG_PTR) GetWindowLongPtr(hwnd, 0);
-
- GetWindowRect(hwnd, &r);
-
- x = GET_X_LPARAM(lParam);
- y = GET_Y_LPARAM(lParam);
-
- x += tbl->scr_left - r.left;
- y += tbl->scr_top - tbl->header_height - r.top;
-
- if (y < 0) {
- /* context menu for header control */
- khm_menu_show_panel(KHUI_MENU_CWHEADER_CTX,
- GET_X_LPARAM(lParam),
- GET_Y_LPARAM(lParam));
-
- return DefWindowProc(hwnd, uMsg, wParam, lParam);
- }
-
- if (tbl->flags & KHUI_CW_TBL_EXPIDENT) {
- int i, yt;
-
- yt = 0;
- for (i=0; i < tbl->n_rows && yt < y; i++) {
- if (tbl->rows[i].flags & KHUI_CW_ROW_EXPVIEW)
- yt += tbl->cell_height * CW_EXP_ROW_MULT;
- else
- yt += tbl->cell_height;
- if (yt > y)
- break;
- }
-
- row = i;
-
- } else {
- row = y / tbl->cell_height;
- }
-
- if(row < 0 || row >= (int) tbl->n_rows)
- return FALSE;
-
- cw_set_row_context(tbl, row);
-
- khm_menu_show_panel(KHUI_MENU_IDENT_CTX, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
-
-#if 0
- /* calling cw_set_row_context() should take care of enabling or
- disabling actions as appropriate. We don't need to
- differentiate between IDENT_CTX and TOK_CTX here. */
- if((tbl->rows[row].flags & KHUI_CW_ROW_HEADER) &&
- (tbl->cols[tbl->rows[row].col].attr_id == KCDB_ATTR_ID_NAME)) {
- khm_menu_show_panel(KHUI_MENU_IDENT_CTX, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
- //khui_context_reset();
- } else {
- khm_menu_show_panel(KHUI_MENU_TOK_CTX, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
- //khui_context_reset();
- }
-#endif
-
- return DefWindowProc(hwnd, uMsg, wParam, lParam);
-}
-
-/* copy and paste template */
-#if 0
-LRESULT
-cw_wm_msg(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
- return DefWindowProc(hwnd, uMsg, wParam, lParam);
-}
-#endif
-
-LRESULT CALLBACK
-khm_credwnd_proc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam)
-{
- switch(uMsg) {
- case WM_COMMAND:
- return cw_wm_command(hwnd, uMsg, wParam, lParam);
-
- case WM_CREATE:
- return cw_wm_create(hwnd, uMsg, wParam, lParam);
-
- case WM_DESTROY:
- return cw_wm_destroy(hwnd, uMsg, wParam, lParam);
-
- case WM_ERASEBKGND:
- /* we don't bother wasting cycles erasing the background
- because the foreground elements completely cover the
- client area */
- return FALSE;
-
- case WM_PAINT:
- return cw_wm_paint(hwnd, uMsg, wParam, lParam);
-
- case WM_PRINTCLIENT:
- return cw_wm_paint(hwnd, uMsg, wParam, lParam);
-
- case WM_SIZE:
- return cw_wm_size(hwnd, uMsg, wParam, lParam);
-
- case WM_NOTIFY:
- return cw_wm_notify(hwnd, uMsg, wParam, lParam);
-
- case WM_HSCROLL:
- return cw_wm_hscroll(hwnd, uMsg, wParam, lParam);
-
- case WM_VSCROLL:
- return cw_wm_vscroll(hwnd, uMsg, wParam, lParam);
-
- case KMQ_WM_DISPATCH:
- return cw_kmq_wm_dispatch(hwnd, uMsg, wParam, lParam);
-
- case WM_LBUTTONDBLCLK:
- case WM_LBUTTONDOWN:
- case WM_MOUSEMOVE:
- case WM_LBUTTONUP:
- return cw_wm_mouse(hwnd, uMsg, wParam, lParam);
-
- case WM_CONTEXTMENU:
- return cw_wm_contextmenu(hwnd, uMsg, wParam, lParam);
- }
-
- return DefWindowProc(hwnd,uMsg,wParam,lParam);
-}
-
-void
-khm_register_credwnd_class(void) {
- WNDCLASSEX wcx;
- kcdb_attrib attrib;
- khm_int32 attr_id;
-
- wcx.cbSize = sizeof(wcx);
- wcx.style = CS_DBLCLKS | CS_OWNDC;
- wcx.lpfnWndProc = khm_credwnd_proc;
- wcx.cbClsExtra = 0;
- wcx.cbWndExtra = sizeof(LONG_PTR);
- wcx.hInstance = khm_hInstance;
- wcx.hIcon = NULL;
- wcx.hCursor = LoadCursor((HINSTANCE) NULL, IDC_ARROW);
- wcx.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
- wcx.lpszMenuName = NULL;
- wcx.lpszClassName = KHUI_CREDWND_CLASS_NAME;
- wcx.hIconSm = NULL;
-
- khui_credwnd_cls = RegisterClassEx(&wcx);
-
- /* while we are at it, register the credwnd attribute type as well, and
- obtain the type ID */
- if(KHM_FAILED(kcdb_attrib_get_id(KHUI_CREDWND_FLAG_ATTRNAME, &attr_id))) {
- ZeroMemory(&attrib, sizeof(attrib));
- attrib.id = KCDB_ATTR_INVALID;
- attrib.flags = KCDB_ATTR_FLAG_HIDDEN;
- attrib.type = KCDB_TYPE_INT32;
- attrib.name = KHUI_CREDWND_FLAG_ATTRNAME;
-
- kcdb_attrib_register(&attrib, &attr_id);
- }
-
- khui_cw_flag_id = attr_id;
-}
-
-void
-khm_unregister_credwnd_class(void) {
- UnregisterClass(MAKEINTATOM(khui_credwnd_cls), khm_hInstance);
-}
-
-HWND
-khm_create_credwnd(HWND parent) {
- RECT r;
- HWND hwnd;
-
- ZeroMemory(attr_to_action, sizeof(attr_to_action));
-
- GetClientRect(parent, &r);
-
- hwnd = CreateWindowEx
- (0,
- MAKEINTATOM(khui_credwnd_cls),
- L"",
- WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
- r.left,
- r.top,
- r.right - r.left,
- r.bottom - r.top,
- parent,
- NULL,
- khm_hInstance,
- NULL);
-
- return hwnd;
-}
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<khmapp.h>
+#include<prsht.h>
+#include<assert.h>
+
+ATOM khui_credwnd_cls;
+khm_int32 khui_cw_flag_id;
+
+khm_int32 attr_to_action[KCDB_ATTR_MAX_ID + 1];
+
+void
+khm_set_cw_element_font(wchar_t * name, LOGFONT * pfont) {
+ khm_handle csp_cw = NULL;
+ wchar_t * element_name;
+
+ if (name == NULL)
+ element_name = L"FontBase";
+ else
+ element_name = name;
+
+ if (KHM_FAILED(khc_open_space(NULL, L"CredWindow", KHM_PERM_WRITE,
+ &csp_cw)))
+ return;
+
+ khc_write_binary(csp_cw, element_name, pfont, sizeof(LOGFONT));
+
+ khc_close_space(csp_cw);
+}
+
+void
+khm_get_cw_element_font(HDC hdc, wchar_t * name, BOOL use_default, LOGFONT * pfont) {
+ khm_handle csp_cw = NULL;
+ khm_size cb;
+ wchar_t * element_name;
+ khm_boolean try_derive = FALSE;
+
+ if (name == NULL)
+ element_name = L"FontBase";
+ else
+ element_name = name;
+
+ if (use_default)
+ goto _use_defaults;
+
+ if (KHM_FAILED(khc_open_space(NULL, L"CredWindow", 0,
+ &csp_cw)))
+ goto _use_defaults;
+
+ cb = sizeof(LOGFONT);
+ if (KHM_FAILED(khc_read_binary(csp_cw, element_name, pfont,
+ &cb)) ||
+ cb != sizeof(LOGFONT)) {
+ try_derive = TRUE;
+ }
+
+ if (try_derive) {
+ cb = sizeof(LOGFONT);
+ if (!name ||
+ KHM_FAILED(khc_read_binary(csp_cw, L"FontBase", pfont,
+ &cb)) ||
+ cb != sizeof(LOGFONT)) {
+ khc_close_space(csp_cw);
+ goto _use_defaults;
+ }
+
+ if (!wcscmp(name, L"FontHeaderBold") ||
+ !wcscmp(name, L"FontBold")) {
+
+ pfont->lfWeight = FW_BOLD;
+
+ }
+ }
+
+ khc_close_space(csp_cw);
+
+ return;
+
+ _use_defaults:
+
+ ZeroMemory(pfont, sizeof(*pfont));
+
+ if (name == NULL) {
+ LOGFONT lf = {
+ -MulDiv(8, GetDeviceCaps(hdc, LOGPIXELSY), 72), 0, /* width/height */
+ 0,0, /* escapement */
+ FW_THIN,
+ FALSE,
+ FALSE,
+ FALSE,
+ DEFAULT_CHARSET,
+ OUT_DEFAULT_PRECIS,
+ CLIP_DEFAULT_PRECIS,
+ DEFAULT_QUALITY,
+ FF_SWISS,
+ L"MS Shell Dlg"};
+
+ *pfont = lf;
+
+ } else if (!wcscmp(name, L"FontHeader")) {
+ LOGFONT lf = {
+ -MulDiv(8, GetDeviceCaps(hdc, LOGPIXELSY), 72), 0, /* width/height */
+ 0,0, /* escapement */
+ FW_THIN,
+ FALSE,
+ FALSE,
+ FALSE,
+ DEFAULT_CHARSET,
+ OUT_DEFAULT_PRECIS,
+ CLIP_DEFAULT_PRECIS,
+ DEFAULT_QUALITY,
+ FF_SWISS,
+ L"MS Shell Dlg"};
+
+ *pfont = lf;
+
+ } else if (!wcscmp(name, L"FontHeaderBold")) {
+ LOGFONT lf = {
+ -MulDiv(8, GetDeviceCaps(hdc, LOGPIXELSY), 72), 0, /* width/height */
+ 0,0, /* escapement */
+ FW_BOLD,
+ FALSE,
+ FALSE,
+ FALSE,
+ DEFAULT_CHARSET,
+ OUT_DEFAULT_PRECIS,
+ CLIP_DEFAULT_PRECIS,
+ DEFAULT_QUALITY,
+ FF_SWISS,
+ L"MS Shell Dlg"};
+
+ *pfont = lf;
+
+ } else if (!wcscmp(name, L"FontNormal")) {
+ LOGFONT lf = {
+ -MulDiv(8, GetDeviceCaps(hdc, LOGPIXELSY), 72), 0, /* width/height */
+ 0,0, /* escapement */
+ FW_THIN,
+ FALSE,
+ FALSE,
+ FALSE,
+ DEFAULT_CHARSET,
+ OUT_DEFAULT_PRECIS,
+ CLIP_DEFAULT_PRECIS,
+ DEFAULT_QUALITY,
+ FF_SWISS,
+ L"MS Shell Dlg"};
+
+ *pfont = lf;
+
+ } else if (!wcscmp(name, L"FontBold")) {
+ LOGFONT lf = {
+ -MulDiv(8, GetDeviceCaps(hdc, LOGPIXELSY), 72), 0, /* width/height */
+ 0,0, /* escapement */
+ FW_BOLD,
+ FALSE,
+ FALSE,
+ FALSE,
+ DEFAULT_CHARSET,
+ OUT_DEFAULT_PRECIS,
+ CLIP_DEFAULT_PRECIS,
+ DEFAULT_QUALITY,
+ FF_SWISS,
+ L"MS Shell Dlg"};
+
+ *pfont = lf;
+
+ } else {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ }
+}
+
+void
+cw_refresh_attribs(HWND hwnd) {
+ khm_int32 act;
+ kcdb_attrib * attrib;
+ khui_menu_def * menu;
+ khm_int32 i;
+
+ menu = khui_find_menu(KHUI_MENU_COLUMNS);
+#ifdef DEBUG
+ assert(menu);
+#endif
+
+ for (i=0; i <= KCDB_ATTR_MAX_ID; i++) {
+ if (KHM_FAILED(kcdb_attrib_get_info(i, &attrib))) {
+ if (attr_to_action[i] != 0) {
+ /* the action should be removed */
+ khui_menu_remove_action(menu, attr_to_action[i]);
+ khui_action_delete(attr_to_action[i]);
+ attr_to_action[i] = 0;
+ }
+ } else {
+ if (attr_to_action[i] == 0 &&
+ !(attrib->flags & KCDB_ATTR_FLAG_HIDDEN) &&
+ (attrib->short_desc || attrib->long_desc)) {
+ /* new action */
+ khm_handle sub = NULL;
+
+ kmq_create_hwnd_subscription(hwnd, &sub);
+
+ act = khui_action_create(attrib->name,
+ (attrib->short_desc?
+ attrib->short_desc: attrib->long_desc),
+ NULL,
+ (void *)(UINT_PTR) i,
+ KHUI_ACTIONTYPE_TOGGLE,
+ sub);
+
+ attr_to_action[i] = act;
+
+ khui_menu_insert_action(menu, 5000, act, 0);
+ }
+
+ kcdb_attrib_release_info(attrib);
+ }
+ }
+}
+
+khm_int32
+cw_get_custom_attr_id(wchar_t * s)
+{
+ if(!wcscmp(s, CW_CANAME_FLAGS))
+ return CW_CA_FLAGS;
+ if(!wcscmp(s, CW_CANAME_TYPEICON))
+ return CW_CA_TYPEICON;
+ return 0;
+}
+
+const wchar_t *
+cw_get_custom_attr_string(khm_int32 attr_id)
+{
+ if (attr_id == CW_CA_FLAGS)
+ return CW_CANAME_FLAGS;
+ if (attr_id == CW_CA_TYPEICON)
+ return CW_CANAME_TYPEICON;
+ return NULL;
+}
+
+void
+cw_save_view(khui_credwnd_tbl * tbl, wchar_t * view_name) {
+ wchar_t * col_list = NULL;
+ khm_size cb_col_list;
+ khm_handle csp_cw = NULL;
+ khm_handle csp_views = NULL;
+ khm_handle csp_view = NULL;
+ khm_handle csp_cols = NULL;
+ khm_size cb;
+ int i;
+
+ if (tbl->n_cols == 0)
+ return;
+
+ cb_col_list = (KCONF_MAXCB_NAME + 1) * tbl->n_cols;
+
+ col_list = PMALLOC(cb_col_list);
+#ifdef DEBUG
+ assert(col_list);
+#endif
+
+ if (!col_list)
+ goto _cleanup;
+
+ multi_string_init(col_list, cb_col_list);
+
+ /* if we aren't saving to a specific view, and the view has been
+ customized, then we save it to "Custom_0", unless we are in the
+ mini mode, in which case we save it to "Custom_1" */
+ if (!view_name && (tbl->flags & KHUI_CW_TBL_CUSTVIEW)) {
+ if (!(tbl->flags & KHUI_CW_TBL_EXPIDENT)) {
+ view_name = L"Custom_0";
+ } else {
+ view_name = L"Custom_1";
+ }
+ }
+
+ if (view_name) {
+ if (KHM_FAILED(khc_open_space(NULL, L"CredWindow",
+ KHM_PERM_READ | KHM_PERM_WRITE, &csp_cw)))
+ goto _cleanup;
+
+ if (KHM_FAILED(khc_open_space(csp_cw, L"Views", KHM_PERM_READ, &csp_views)))
+ goto _cleanup;
+
+ if (KHM_FAILED(khc_open_space(csp_views, view_name,
+ KHM_PERM_WRITE | KHM_FLAG_CREATE,
+ &csp_view)))
+ goto _cleanup;
+
+ /* if we are switching to a custom view, then we should mark
+ that as the default. */
+ if (tbl->flags & KHUI_CW_TBL_CUSTVIEW) {
+ khc_write_string(csp_cw, ((!(tbl->flags & KHUI_CW_TBL_EXPIDENT))?
+ L"DefaultView":
+ L"DefaultViewMini"), view_name);
+ }
+
+ } else {
+ csp_view = tbl->csp_view;
+ }
+
+ if (!csp_view)
+ goto _cleanup;
+
+ if (tbl->flags & KHUI_CW_TBL_EXPIDENT) {
+ khc_write_int32(csp_view, L"ExpandedIdentity", 1);
+ } else {
+ khm_int32 t;
+ if (KHM_SUCCEEDED(khc_read_int32(csp_view, L"ExpandedIdentity", &t)) && t)
+ khc_write_int32(csp_view, L"ExpandedIdentity", 0);
+ }
+
+ if (tbl->flags & KHUI_CW_TBL_NOHEADER) {
+ khc_write_int32(csp_view, L"NoHeader", 1);
+ } else {
+ khm_int32 t;
+ if (KHM_SUCCEEDED(khc_read_int32(csp_view, L"NoHeader", &t)) && t)
+ khc_write_int32(csp_view, L"NoHeader", 0);
+ }
+
+ if (KHM_FAILED(khc_open_space(csp_view, L"Columns",
+ KHM_PERM_WRITE | KHM_FLAG_CREATE,
+ &csp_cols)))
+ goto _cleanup;
+
+ for (i=0; i < tbl->n_cols; i++) {
+ const wchar_t * attr_name;
+ kcdb_attrib * attrib = NULL;
+ khm_handle csp_col = NULL;
+
+ if (tbl->cols[i].attr_id < 0) {
+ attr_name = cw_get_custom_attr_string(tbl->cols[i].attr_id);
+ } else {
+ if (KHM_FAILED(kcdb_attrib_get_info(tbl->cols[i].attr_id,
+ &attrib))) {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ goto _clean_col;
+ }
+
+ attr_name = attrib->name;
+ }
+#ifdef DEBUG
+ assert(attr_name);
+#endif
+
+ cb = cb_col_list;
+ multi_string_append(col_list, &cb, attr_name);
+
+ if (KHM_FAILED(khc_open_space(csp_cols, attr_name,
+ KHM_PERM_WRITE | KHM_FLAG_CREATE,
+ &csp_col)))
+ goto _clean_col;
+
+ khc_write_int32(csp_col, L"Width", tbl->cols[i].width);
+ khc_write_int32(csp_col, L"SortIndex", tbl->cols[i].sort_index);
+ khc_write_int32(csp_col, L"Flags", tbl->cols[i].flags);
+
+ _clean_col:
+
+ if (csp_col)
+ khc_close_space(csp_col);
+
+ if (attrib)
+ kcdb_attrib_release_info(attrib);
+ }
+
+ khc_write_multi_string(csp_view, L"ColumnList", col_list);
+
+ {
+ khm_version v = app_version;
+
+ khc_write_binary(csp_view, L"_AppVersion", &v, sizeof(v));
+ }
+
+ _cleanup:
+
+ if (view_name) {
+ if (csp_view)
+ khc_close_space(csp_view);
+
+ if (csp_views)
+ khc_close_space(csp_views);
+
+ if (csp_cw)
+ khc_close_space(csp_cw);
+ }
+
+ if (csp_cols)
+ khc_close_space(csp_cols);
+
+ if (col_list)
+ PFREE(col_list);
+}
+
+static COLORREF
+cw_mix_colors(COLORREF c1, COLORREF c2, int alpha) {
+ int r = (GetRValue(c1) * alpha + GetRValue(c2) * (255 - alpha)) / 255;
+ int g = (GetGValue(c1) * alpha + GetGValue(c2) * (255 - alpha)) / 255;
+ int b = (GetBValue(c1) * alpha + GetBValue(c2) * (255 - alpha)) / 255;
+
+#ifdef DEBUG
+ assert(alpha >= 0 && alpha < 256);
+#endif
+
+ return RGB(r,g,b);
+}
+
+void
+cw_load_view(khui_credwnd_tbl * tbl, wchar_t * view, HWND hwnd) {
+ khm_handle hc_cw = NULL;
+ khm_handle hc_vs = NULL;
+ khm_handle hc_v = NULL;
+ khm_handle hc_cs = NULL;
+ khm_handle hc_c = NULL;
+ wchar_t buf[KCONF_MAXCCH_NAME];
+ wchar_t * clist = NULL;
+ khm_size cbsize;
+ wchar_t * iter = NULL;
+ int i;
+ HDC hdc;
+ LOGFONT log_font;
+ khm_int32 t;
+ const wchar_t * viewval;
+ khm_boolean reopen_csp = FALSE;
+
+ tbl->hwnd = hwnd;
+
+ if (khm_main_wnd_mode == KHM_MAIN_WND_MINI)
+ viewval = L"DefaultViewMini";
+ else
+ viewval = L"DefaultView";
+
+ if(KHM_FAILED(khc_open_space(NULL, L"CredWindow", KHM_PERM_READ | KHM_PERM_WRITE,
+ &hc_cw)))
+ return;
+
+ if(KHM_FAILED(khc_open_space(hc_cw, L"Views", KHM_PERM_READ, &hc_vs)))
+ goto _exit;
+
+ if(!view) {
+ cbsize = sizeof(buf);
+ if(KHM_FAILED(khc_read_string(hc_cw, viewval, buf, &cbsize)))
+ goto _exit;
+ view = buf;
+ } else {
+ khc_write_string(hc_cw, viewval, view);
+ }
+
+ /* in addition, if we are loading the default view, we should
+ also check the appropriate menu item */
+
+ if (!wcscmp(view, L"ByIdentity"))
+ khui_check_radio_action(khui_find_menu(KHUI_MENU_LAYOUT),
+ KHUI_ACTION_LAYOUT_ID);
+ else if (!wcscmp(view, L"ByLocation"))
+ khui_check_radio_action(khui_find_menu(KHUI_MENU_LAYOUT),
+ KHUI_ACTION_LAYOUT_LOC);
+ else if (!wcscmp(view, L"ByType"))
+ khui_check_radio_action(khui_find_menu(KHUI_MENU_LAYOUT),
+ KHUI_ACTION_LAYOUT_TYPE);
+ else if (!wcscmp(view, L"Custom_0"))
+ khui_check_radio_action(khui_find_menu(KHUI_MENU_LAYOUT),
+ KHUI_ACTION_LAYOUT_CUST);
+ else {
+ /* do nothing */
+ }
+
+ kmq_post_message(KMSG_ACT, KMSG_ACT_REFRESH, 0, 0);
+
+ if(KHM_FAILED(khc_open_space(hc_vs, view, 0, &hc_v)))
+ goto _exit;
+
+ /* view data is very sensitive to version changes. We need to
+ check if this configuration data was created with this version
+ of NetIDMgr. If not, we switch to using a schema handle. */
+ {
+ khm_version this_v = app_version;
+ khm_version cfg_v;
+
+ cbsize = sizeof(cfg_v);
+ if (KHM_FAILED(khc_read_binary(hc_v, L"_AppVersion", &cfg_v, &cbsize)) ||
+ khm_compare_version(&cfg_v, &this_v) != 0) {
+
+ khc_close_space(hc_v);
+
+ if (KHM_FAILED(khc_open_space(hc_vs, view, KCONF_FLAG_SCHEMA,
+ &hc_v)) &&
+ (wcscmp(view, L"Custom_1") ||
+ KHM_FAILED(khc_open_space(hc_vs, L"CompactIdentity",
+ KCONF_FLAG_SCHEMA, &hc_v)))) {
+ goto _exit;
+ }
+
+ reopen_csp = TRUE;
+ }
+ }
+
+ tbl->csp_view = hc_v;
+
+ if(KHM_FAILED(khc_open_space(hc_v, L"Columns",
+ KHM_PERM_READ | (reopen_csp ? KCONF_FLAG_SCHEMA : 0),
+ &hc_cs)))
+ goto _exit;
+
+ cbsize = 0;
+ if(khc_read_multi_string(hc_v, L"ColumnList", NULL, &cbsize) != KHM_ERROR_TOO_LONG)
+ goto _exit;
+
+ /* temporary */
+ clist = PMALLOC(cbsize);
+
+ if(KHM_FAILED(khc_read_multi_string(hc_v, L"ColumnList", clist, &cbsize)))
+ goto _exit;
+
+ tbl->n_cols = (int) multi_string_length_n(clist);
+ tbl->n_total_cols = UBOUNDSS(tbl->n_cols,
+ KHUI_CW_COL_INITIAL, KHUI_CW_COL_INCREMENT);
+ tbl->cols = PMALLOC(sizeof(khui_credwnd_col) * tbl->n_total_cols);
+ ZeroMemory(tbl->cols, sizeof(khui_credwnd_col) * tbl->n_total_cols);
+
+ tbl->flags &= ~(KHUI_CW_TBL_CUSTVIEW | KHUI_CW_TBL_COLSKIP);
+
+ if (KHM_SUCCEEDED(khc_read_int32(hc_v, L"ExpandedIdentity", &t)) && t) {
+ tbl->flags |= KHUI_CW_TBL_EXPIDENT;
+ } else {
+ tbl->flags &= ~KHUI_CW_TBL_EXPIDENT;
+ }
+
+ if (KHM_SUCCEEDED(khc_read_int32(hc_v, L"NoHeader", &t)) && t) {
+ tbl->flags |= KHUI_CW_TBL_NOHEADER;
+ } else {
+ tbl->flags &= ~KHUI_CW_TBL_NOHEADER;
+ }
+
+ iter = clist;
+ i = 0;
+ while(iter) {
+ khm_int32 attr_id;
+
+ attr_id = cw_get_custom_attr_id(iter);
+ if(!attr_id) {
+ /* a KCDB attribute */
+ if(KHM_FAILED(kcdb_attrib_get_id(iter, &attr_id))) {
+ tbl->flags |= KHUI_CW_TBL_COLSKIP;
+ goto _skip_col;
+ }
+
+ if(kcdb_attrib_describe(attr_id, NULL,
+ &cbsize, KCDB_TS_SHORT) != KHM_ERROR_TOO_LONG ||
+ cbsize == 0) {
+ tbl->flags |= KHUI_CW_TBL_COLSKIP;
+ goto _skip_col;
+ }
+
+ tbl->cols[i].title = PMALLOC(cbsize);
+ kcdb_attrib_describe(attr_id, tbl->cols[i].title, &cbsize, KCDB_TS_SHORT);
+
+ if (attr_id >= 0 &&
+ attr_id <= KCDB_ATTR_MAX_ID &&
+ attr_to_action[attr_id]) {
+ khui_check_action(attr_to_action[attr_id], TRUE);
+ }
+
+ } else {
+ /* All current custom attributes are represented by icons,
+ not names */
+ tbl->cols[i].title = NULL;
+ }
+
+ tbl->cols[i].attr_id = attr_id;
+
+ if(KHM_SUCCEEDED(khc_open_space(hc_cs, iter,
+ KHM_PERM_READ | (reopen_csp ? KCONF_FLAG_SCHEMA : 0),
+ &hc_c))) {
+ if(KHM_FAILED(khc_read_int32(hc_c, L"Flags", &(tbl->cols[i].flags))))
+ tbl->cols[i].flags = 0;
+ if(KHM_FAILED(khc_read_int32(hc_c, L"Width", &(tbl->cols[i].width))))
+ tbl->cols[i].width = 100;
+ if(KHM_FAILED(khc_read_int32(hc_c, L"SortIndex",
+ &(tbl->cols[i].sort_index))))
+ tbl->cols[i].sort_index = -1;
+ khc_close_space(hc_c);
+ hc_c = NULL;
+ } else {
+ tbl->cols[i].flags = 0;
+ tbl->cols[i].width = -1;
+ tbl->cols[i].sort_index = -1;
+ }
+ i++;
+_skip_col:
+ iter = multi_string_next(iter);
+ }
+
+ /* refresh the menus since we checked a few items */
+ kmq_post_message(KMSG_ACT, KMSG_ACT_REFRESH, 0, 0);
+
+ /* adjust the number of columns. We may have skipped columns due to
+ inconsistencies above */
+ tbl->n_cols = i;
+
+ /* now that all the columns have been loaded, load the view
+ parameters */
+ if(KHM_FAILED(khc_read_int32(hc_v, L"PaddingHorizontal", &(tbl->hpad))))
+ khc_read_int32(hc_cw, L"PaddingHorizontal", &(tbl->hpad));
+ if(KHM_FAILED(khc_read_int32(hc_v, L"PaddingVertical", &(tbl->vpad))))
+ khc_read_int32(hc_cw, L"PaddingVertical", &(tbl->vpad));
+ if(KHM_FAILED(khc_read_int32(hc_v, L"PaddingHeader", &(tbl->hpad_h))))
+ khc_read_int32(hc_cw, L"PaddingHeader", &(tbl->hpad_h));
+ if(KHM_FAILED(khc_read_int32(hc_v, L"WarnThreshold", &(tbl->threshold_warn))))
+ khc_read_int32(hc_cw, L"WarnThreshold", &(tbl->threshold_warn));
+ if(KHM_FAILED(khc_read_int32(hc_v, L"CriticalThreshold",
+ &(tbl->threshold_critical))))
+ khc_read_int32(hc_cw, L"CriticalThreshold",
+ &(tbl->threshold_critical));
+
+ /* and the font resources and stuff */
+
+ tbl->flags |= KHUI_CW_TBL_INITIALIZED | KHUI_CW_TBL_COL_DIRTY | KHUI_CW_TBL_ACTIVE;
+
+ /*TODO: the graphics objects should be customizable */
+
+ hdc = GetWindowDC(hwnd);
+
+ khm_get_cw_element_font(hdc, L"FontHeader", FALSE, &log_font);
+ tbl->hf_header = CreateFontIndirect(&log_font);
+
+ if(tbl->hf_header && tbl->hwnd_header)
+ SendMessage(tbl->hwnd_header, WM_SETFONT, (WPARAM) tbl->hf_header, 0);
+
+ khm_get_cw_element_font(hdc, L"FontHeaderBold", FALSE, &log_font);
+ tbl->hf_bold_header = CreateFontIndirect(&log_font);
+
+
+ khm_get_cw_element_font(hdc, L"FontNormal", FALSE, &log_font);
+ tbl->hf_normal = CreateFontIndirect(&log_font);
+
+ khm_get_cw_element_font(hdc, L"FontBold", FALSE, &log_font);
+ tbl->hf_bold = CreateFontIndirect(&log_font);
+
+ ReleaseDC(hwnd, hdc);
+
+ khui_bitmap_from_hbmp(&(tbl->kbm_logo_shade),
+ LoadImage(khm_hInstance,
+ MAKEINTRESOURCE(IDB_LOGO_SHADE),
+ IMAGE_BITMAP,
+ 0,
+ 0,
+ LR_DEFAULTCOLOR));
+
+ {
+#define SEL_ALPHA 50
+
+ COLORREF bg_s = GetSysColor(COLOR_HIGHLIGHT);
+ COLORREF bg_normal = GetSysColor(COLOR_WINDOW);
+ COLORREF bg_gray = RGB(240,240,240);
+ COLORREF bg_hdr = RGB(240,240,240);
+ COLORREF bg_hdr_warn = RGB(235,235,134);
+ COLORREF bg_hdr_crit = RGB(235,184,134);
+ COLORREF bg_hdr_exp = RGB(235,134,134);
+ COLORREF bg_hdr_def = RGB(184,235,134);
+
+ tbl->cr_normal = GetSysColor(COLOR_WINDOWTEXT);
+ tbl->cr_s = GetSysColor(COLOR_WINDOWTEXT);
+ tbl->cr_hdr_outline = RGB(0,0,0);
+ tbl->cr_hdr_normal = GetSysColor(COLOR_WINDOWTEXT);
+ tbl->cr_hdr_s = GetSysColor(COLOR_WINDOWTEXT);
+ tbl->cr_hdr_gray = GetSysColor(COLOR_GRAYTEXT);
+ tbl->cr_hdr_gray_s = GetSysColor(COLOR_HIGHLIGHTTEXT);
+
+ if (khm_main_wnd_mode == KHM_MAIN_WND_MINI) {
+ bg_hdr = bg_normal;
+ tbl->cr_hdr_outline = bg_gray;
+ }
+
+ tbl->hb_normal = CreateSolidBrush(bg_normal);
+ tbl->hb_grey = CreateSolidBrush(bg_gray);
+ tbl->hb_s = CreateSolidBrush(cw_mix_colors(bg_s, bg_normal, SEL_ALPHA));
+
+ tbl->hb_hdr_bg = CreateSolidBrush(bg_hdr);
+ tbl->hb_hdr_bg_warn = CreateSolidBrush(bg_hdr_warn);
+ tbl->hb_hdr_bg_crit = CreateSolidBrush(bg_hdr_crit);
+ tbl->hb_hdr_bg_exp = CreateSolidBrush(bg_hdr_exp);
+ tbl->hb_hdr_bg_def = CreateSolidBrush(bg_hdr_def);
+
+ tbl->hb_hdr_bg_s = CreateSolidBrush(cw_mix_colors(bg_s, bg_hdr, SEL_ALPHA));
+ tbl->hb_hdr_bg_warn_s = CreateSolidBrush(cw_mix_colors(bg_s, bg_hdr_warn, SEL_ALPHA));
+ tbl->hb_hdr_bg_crit_s = CreateSolidBrush(cw_mix_colors(bg_s, bg_hdr_crit, SEL_ALPHA));
+ tbl->hb_hdr_bg_exp_s = CreateSolidBrush(cw_mix_colors(bg_s, bg_hdr_exp, SEL_ALPHA));
+ tbl->hb_hdr_bg_def_s = CreateSolidBrush(cw_mix_colors(bg_s, bg_hdr_def, SEL_ALPHA));
+ }
+
+ tbl->ilist = khui_create_ilist(KHUI_SMICON_CX, KHUI_SMICON_CY-1, 20, 8, 0);
+ {
+ HBITMAP hbm;
+
+#define ADD_BITMAP(i) \
+ hbm = LoadImage(khm_hInstance, MAKEINTRESOURCE(i), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR); \
+ if(hbm) { \
+ khui_ilist_add_masked_id(tbl->ilist, hbm, KHUI_TOOLBAR_BGCOLOR, i); \
+ DeleteObject(hbm); \
+ }
+
+ ADD_BITMAP(IDB_WDG_COLLAPSE);
+ ADD_BITMAP(IDB_WDG_EXPAND);
+ ADD_BITMAP(IDB_ID_SM);
+ ADD_BITMAP(IDB_ID_DIS_SM);
+
+ ADD_BITMAP(IDB_TK_NEW_SM);
+ ADD_BITMAP(IDB_TK_REFRESH_SM);
+ ADD_BITMAP(IDB_WDG_COLLAPSE_HI);
+ ADD_BITMAP(IDB_WDG_EXPAND_HI);
+
+ ADD_BITMAP(IDB_WDG_FLAG);
+ ADD_BITMAP(IDB_WDG_CREDTYPE);
+ ADD_BITMAP(IDB_FLAG_WARN);
+ ADD_BITMAP(IDB_FLAG_EXPIRED);
+
+ ADD_BITMAP(IDB_FLAG_CRITICAL);
+ ADD_BITMAP(IDB_FLAG_RENEW);
+ ADD_BITMAP(IDB_WDG_STUCK);
+ ADD_BITMAP(IDB_WDG_STUCK_HI);
+
+ ADD_BITMAP(IDB_WDG_STICK);
+ ADD_BITMAP(IDB_WDG_STICK_HI);
+ ADD_BITMAP(IDB_TK_SM);
+
+#undef ADD_BITMAP
+ }
+
+ if (tbl->flags & KHUI_CW_TBL_EXPIDENT) {
+ tbl->hi_lg_ident = LoadImage(khm_hInstance, MAKEINTRESOURCE(IDI_MAIN_APP),
+ IMAGE_ICON,
+ GetSystemMetrics(SM_CXICON),
+ GetSystemMetrics(SM_CYICON),
+ LR_DEFAULTCOLOR);
+ }
+
+ tbl->cursor_row = -1;
+ tbl->scr_left = 0;
+ tbl->scr_top = 0;
+ tbl->ext_height = 0;
+ tbl->ext_width = 0;
+
+ if (reopen_csp) {
+ khc_close_space(hc_v);
+
+ hc_v = NULL;
+
+ khc_open_space(hc_vs, view, 0, &hc_v);
+
+ tbl->csp_view = hc_v;
+ }
+
+_exit:
+ if(hc_cw)
+ khc_close_space(hc_cw);
+ if(hc_vs)
+ khc_close_space(hc_vs);
+ if(hc_cs)
+ khc_close_space(hc_cs);
+ if(clist)
+ PFREE(clist);
+ /* we leave hc_v held, because tbl->csp_view is the same handle.
+ We keep that open until the view is unloaded. */
+}
+
+khui_credwnd_ident *
+cw_find_ident(khui_credwnd_tbl * tbl, khm_handle ident) {
+ khm_size i;
+
+ for (i=0; i < tbl->n_idents; i++) {
+ if (kcdb_identity_is_equal(ident, tbl->idents[i].ident))
+ break;
+ }
+
+ if (i < tbl->n_idents)
+ return &tbl->idents[i];
+ else
+ return NULL;
+}
+
+khm_int32 KHMAPI
+cw_credset_iter_func(khm_handle cred, void * rock) {
+ khui_credwnd_tbl * tbl = (khui_credwnd_tbl *) rock;
+ khm_handle ident = NULL;
+ khm_size i;
+ khui_credwnd_ident * cwi = NULL;
+ khm_int32 cred_credtype = KCDB_CREDTYPE_INVALID;
+ khm_int32 cred_flags = 0;
+
+ kcdb_cred_get_identity(cred, &ident);
+
+ if (ident == NULL)
+ goto _cleanup;
+
+ for (i=0; i < tbl->n_idents; i++) {
+ if (kcdb_identity_is_equal(ident, tbl->idents[i].ident))
+ break;
+ }
+
+ if (i >= tbl->n_idents) {
+ khm_size cb;
+
+ /* need to add this one */
+ if (tbl->n_idents == tbl->nc_idents) {
+ tbl->nc_idents = UBOUNDSS(tbl->n_idents + 1,
+ CW_IDENT_ALLOC_INCR,
+ CW_IDENT_ALLOC_INCR);
+#ifdef DEBUG
+ assert(tbl->nc_idents > tbl->n_idents);
+#endif
+ tbl->idents = PREALLOC(tbl->idents, sizeof(tbl->idents[0]) * tbl->nc_idents);
+#ifdef DEBUG
+ assert(tbl->idents);
+#endif
+ ZeroMemory(&tbl->idents[tbl->n_idents],
+ sizeof(tbl->idents[0]) * (tbl->nc_idents - tbl->n_idents));
+ }
+
+ i = tbl->n_idents;
+ cwi = &tbl->idents[tbl->n_idents++];
+
+ ZeroMemory(cwi, sizeof(*cwi));
+
+ cwi->ident = ident;
+ kcdb_identity_hold(ident);
+
+ cb = sizeof(cwi->name);
+ kcdb_identity_get_name(ident, cwi->name, &cb);
+ }
+
+ cwi = &tbl->idents[i];
+
+ /* this is the first time we are seeing this identity. */
+ if (cwi->credcount == 0) {
+ khm_size cb;
+
+ cb = sizeof(cwi->credtype);
+ if (KHM_SUCCEEDED(kcdb_identity_get_attr(ident, KCDB_ATTR_TYPE, NULL,
+ &cwi->credtype, &cb))) {
+ cwi->credtype_name[0] = L'\0';
+
+ cb = sizeof(cwi->credtype_name);
+ if (KHM_FAILED(kcdb_identity_get_attr(ident, KCDB_ATTR_TYPE_NAME, NULL,
+ &cwi->credtype, &cb))) {
+ cb = sizeof(cwi->credtype_name);
+ kcdb_credtype_describe(cwi->credtype, cwi->credtype_name,
+ &cb, KCDB_TS_SHORT);
+ }
+ } else {
+ cwi->credtype = KCDB_CREDTYPE_INVALID;
+ cwi->credtype_name[0] = L'\0';
+ }
+
+ cb = sizeof(cwi->ft_expire);
+ if (KHM_FAILED(kcdb_identity_get_attr(ident, KCDB_ATTR_EXPIRE, NULL,
+ &cwi->ft_expire, &cb))) {
+ cwi->ft_expire = IntToFt(0);
+ }
+
+ kcdb_identity_get_flags(cwi->ident, &cwi->ident_flags);
+ }
+
+ cwi->credcount++;
+
+ kcdb_cred_get_type(cred, &cred_credtype);
+ if (cred_credtype >= 0 && cred_credtype == cwi->credtype) {
+ cwi->id_credcount++;
+
+ kcdb_cred_get_flags(cred, &cred_flags);
+ if (cred_flags & KCDB_CRED_FLAG_INITIAL) {
+ cwi->init_credcount++;
+ }
+ }
+
+ _cleanup:
+ if (ident)
+ kcdb_identity_release(ident);
+
+ return KHM_ERROR_SUCCESS;
+}
+
+void
+cw_update_creds(khui_credwnd_tbl * tbl)
+{
+ kcdb_cred_comp_field * fields;
+ kcdb_cred_comp_order comp_order;
+ int i;
+ khm_int32 n;
+ khm_int32 delta;
+ khm_handle hc;
+ khm_int32 flags;
+
+ if(!tbl->credset) {
+ if(KHM_FAILED(kcdb_credset_create(&(tbl->credset))))
+ return;
+ }
+
+ kcdb_credset_purge(tbl->credset);
+
+ kcdb_identity_refresh_all();
+
+ kcdb_credset_collect(
+ tbl->credset,
+ NULL,
+ NULL,
+ KCDB_CREDTYPE_ALL,
+ &delta);
+
+ /* now we need to figure out how to sort the credentials */
+ fields = PMALLOC(sizeof(kcdb_cred_comp_field) * tbl->n_cols);
+ ZeroMemory(fields, sizeof(kcdb_cred_comp_field) * tbl->n_cols);
+
+ for(i=0, n=0; i<tbl->n_cols; i++) {
+ if((tbl->cols[i].flags & KHUI_CW_COL_SORT_INC) ||
+ (tbl->cols[i].flags & KHUI_CW_COL_SORT_DEC) ||
+ (tbl->cols[i].flags & KHUI_CW_COL_GROUP)) {
+ int si;
+ /* we need to sort by this column */
+ si = tbl->cols[i].sort_index;
+
+ if(si < 0 || si >= (int) tbl->n_cols)
+ {
+ /* this shouldn't happen */
+ tbl->cols[i].flags &= ~(KHUI_CW_COL_SORT_INC |
+ KHUI_CW_COL_SORT_DEC |
+ KHUI_CW_COL_GROUP);
+ continue;
+ }
+
+ fields[si].attrib = tbl->cols[i].attr_id;
+ if(tbl->cols[i].flags & KHUI_CW_COL_SORT_DEC)
+ fields[si].order = KCDB_CRED_COMP_DECREASING;
+ else
+ fields[si].order = KCDB_CRED_COMP_INCREASING;
+
+ /* special case. if we are sorting by name, we group
+ initial tickets before non-initial tickets.
+
+ Also, if we are sorting by credential type name, then
+ we allow the primary credential type first before
+ others. */
+
+ if (fields[si].attrib == KCDB_ATTR_NAME ||
+ fields[si].attrib == KCDB_ATTR_TYPE_NAME)
+ fields[si].order |= KCDB_CRED_COMP_INITIAL_FIRST;
+
+ if(si >= n)
+ n = si+1;
+ }
+ }
+
+ /* we assume that the sort order is sane */
+ /*TODO: don't assume; check if the sort order is sane */
+
+ comp_order.nFields = n;
+ comp_order.fields = fields;
+
+ kcdb_credset_sort(tbl->credset,
+ kcdb_cred_comp_generic,
+ (void *) &comp_order);
+
+ /* also, if new credentials were added, initialize the UI flag
+ attribute to 0 */
+ if(delta & KCDB_DELTA_ADD) {
+ khm_size s;
+
+ kcdb_credset_get_size(tbl->credset, &s);
+ for(i=0;i< (int) s;i++) {
+ if(KHM_FAILED(kcdb_credset_get_cred(tbl->credset,
+ (khm_int32) i, &hc)))
+ continue; /* lost a race */
+ if(KHM_FAILED(kcdb_cred_get_attr(hc, khui_cw_flag_id, NULL,
+ NULL, NULL))) {
+ flags = 0;
+ kcdb_cred_set_attr(hc, khui_cw_flag_id, &flags, sizeof(flags));
+ }
+ kcdb_cred_release(hc);
+ }
+ }
+
+ /* refresh the per-identity information */
+ for (i=0; i < (int) tbl->n_idents; i++) {
+ tbl->idents[i].credcount = 0;
+ tbl->idents[i].id_credcount = 0;
+ tbl->idents[i].init_credcount = 0;
+ }
+
+ kcdb_credset_apply(tbl->credset, cw_credset_iter_func, (void *) tbl);
+
+ if (fields)
+ PFREE(fields);
+}
+
+void
+cw_del_outline(khui_credwnd_outline *o) {
+ khui_credwnd_outline * c;
+ if(!o)
+ return;
+
+ /* the outline object is still in a list */
+ if(o->next || o->prev)
+ return;
+
+ if(o->header)
+ PFREE(o->header);
+
+ if ((o->flags & KHUI_CW_O_DATAALLOC) &&
+ o->data)
+ PFREE(o->data);
+
+ if ((o->flags & KHUI_CW_O_RELIDENT) &&
+ o->data)
+ kcdb_identity_release((khm_handle) o->data);
+
+ LPOP(&(o->children), &c);
+ while(c) {
+ cw_del_outline(c);
+ LPOP(&(o->children), &c);
+ }
+
+ ZeroMemory(o, sizeof(*o));
+ PFREE(o);
+}
+
+khui_credwnd_outline *
+cw_new_outline_node(wchar_t * heading) {
+ khui_credwnd_outline * o;
+ size_t cblen;
+
+ o = PMALLOC(sizeof(khui_credwnd_outline));
+ ZeroMemory(o, sizeof(khui_credwnd_outline));
+
+ if(SUCCEEDED(StringCbLength(heading, KHUI_MAXCB_HEADING, &cblen))) {
+ cblen += sizeof(wchar_t);
+ o->header = PMALLOC(cblen);
+ StringCbCopy(o->header, cblen, heading);
+ }
+ o->start = -1;
+
+ return o;
+}
+
+/* buf is a handle to a credential or an identity. the kcdb_buf_*
+ functions work with either. */
+khm_int32
+cw_get_buf_exp_flags(khui_credwnd_tbl * tbl, khm_handle buf)
+{
+ khm_int32 flags;
+ long s;
+ FILETIME ft_expire;
+ FILETIME ft_current;
+ FILETIME ft_difference;
+ khm_size cbsize;
+
+ cbsize = sizeof(ft_expire);
+ if(KHM_FAILED(kcdb_buf_get_attr(buf, KCDB_ATTR_EXPIRE, NULL,
+ &ft_expire, &cbsize)))
+ return 0;
+
+ GetSystemTimeAsFileTime(&ft_current);
+ ft_difference = FtSub(&ft_expire, &ft_current);
+
+ s = FtIntervalToSeconds(&ft_difference);
+
+ flags = 0;
+ if(s < 0)
+ flags = CW_EXPSTATE_EXPIRED;
+ else if(s < tbl->threshold_critical)
+ flags = CW_EXPSTATE_CRITICAL;
+ else if(s < tbl->threshold_warn)
+ flags = CW_EXPSTATE_WARN;
+ else
+ flags = CW_EXPSTATE_NONE;
+
+ return flags;
+}
+
+void cw_update_outline(khui_credwnd_tbl * tbl);
+
+static void
+cw_update_selection_state(khui_credwnd_tbl * tbl);
+
+VOID CALLBACK
+cw_timer_proc(HWND hwnd,
+ UINT uMsg,
+ UINT_PTR idEvent,
+ DWORD dwTime)
+{
+ khui_credwnd_tbl * tbl;
+ khui_credwnd_row * r;
+ khm_int32 nflags;
+ int nr;
+ long ms;
+ FILETIME ft;
+ khm_size cbsize;
+ int timer_set = 0;
+
+ KillTimer(hwnd, idEvent);
+
+ tbl = (khui_credwnd_tbl *)(LONG_PTR) GetWindowLongPtr(hwnd, 0);
+ r = (khui_credwnd_row *) idEvent;
+ r->flags &= ~KHUI_CW_ROW_TIMERSET;
+
+ nr = (int)(r - tbl->rows);
+
+ if(nr < 0 || nr >= tbl->n_rows)
+ return;
+
+ if(r->flags & KHUI_CW_ROW_CRED) {
+
+ nflags = cw_get_buf_exp_flags(tbl, (khm_handle) r->data);
+ if((r->flags & CW_EXPSTATE_MASK) != nflags) {
+ /* flags have changed */
+ /* the outline needs to be updated */
+ cw_update_outline(tbl);
+ InvalidateRect(tbl->hwnd, NULL, FALSE);
+ } else {
+ /* just invalidate the row */
+ RECT rc,rr,ri;
+
+ GetClientRect(tbl->hwnd, &rc);
+ rc.top += tbl->header_height;
+
+ rr = r->r_ext;
+ OffsetRect(&rr, 0, tbl->header_height - tbl->scr_top);
+
+ if(IntersectRect(&ri, &rc, &rr))
+ InvalidateRect(tbl->hwnd, &ri, FALSE);
+
+ cbsize = sizeof(ft);
+ if(KHM_SUCCEEDED(kcdb_cred_get_attr((khm_handle) r->data,
+ KCDB_ATTR_TIMELEFT, NULL,
+ &ft, &cbsize))) {
+ ms = FtIntervalMsToRepChange(&ft);
+ if(ms > 0) {
+ SetTimer(tbl->hwnd, (UINT_PTR) r, ms + 100, cw_timer_proc);
+ timer_set = 1;
+ }
+ }
+
+ if (timer_set)
+ r->flags |= KHUI_CW_ROW_TIMERSET;
+ }
+ } else {
+ khui_credwnd_outline * o;
+ khui_credwnd_ident * cwi;
+ FILETIME ft_now;
+
+ o = (khui_credwnd_outline *) r->data;
+#ifdef DEBUG
+ assert(r->flags & KHUI_CW_ROW_EXPVIEW);
+ assert(o->attr_id == KCDB_ATTR_ID);
+ assert(tbl->flags & KHUI_CW_TBL_EXPIDENT);
+#endif
+
+ nflags = cw_get_buf_exp_flags(tbl, (khm_handle) o->data);
+ if ((o->flags & CW_EXPSTATE_MASK) != nflags) {
+ cw_update_outline(tbl);
+ InvalidateRect(tbl->hwnd, NULL, FALSE);
+ } else {
+ RECT rc, rr, ri;
+
+ GetClientRect(tbl->hwnd, &rc);
+ rc.top += tbl->header_height;
+
+ rr = r->r_ext;
+ OffsetRect(&rr, 0, tbl->header_height - tbl->scr_top);
+
+ if (IntersectRect(&ri, &rc, &rr))
+ InvalidateRect(tbl->hwnd, &ri, FALSE);
+
+ cwi = cw_find_ident(tbl, o->data);
+
+ GetSystemTimeAsFileTime(&ft_now);
+ if (CompareFileTime(&cwi->ft_expire, &ft_now) > 0) {
+ ft = FtSub(&cwi->ft_expire, &ft_now);
+ ms = FtIntervalMsToRepChange(&ft);
+ if (ms > 0) {
+ SetTimer(tbl->hwnd, (UINT_PTR) r, ms + 100, cw_timer_proc);
+ timer_set = 1;
+ }
+ }
+
+ if (timer_set)
+ r->flags |= KHUI_CW_ROW_TIMERSET;
+ }
+ }
+}
+
+void
+cw_set_tbl_row_cred(khui_credwnd_tbl * tbl,
+ int row,
+ khm_handle cred,
+ int col)
+{
+ FILETIME ft;
+ long ms;
+ khm_size cbsize;
+
+ if((int) tbl->n_total_rows <= row) {
+ /* we need to resize the allocation */
+ khui_credwnd_row * newrows;
+ int newsize;
+
+ newsize = UBOUNDSS(row+1,KHUI_CW_ROW_INITIAL, KHUI_CW_ROW_INCREMENT);
+ newrows = PMALLOC(sizeof(khui_credwnd_row) * newsize);
+ memcpy(newrows, tbl->rows, sizeof(khui_credwnd_row) * tbl->n_rows);
+ PFREE(tbl->rows);
+ tbl->rows = newrows;
+ tbl->n_total_rows = newsize;
+ }
+
+ tbl->rows[row].col = col;
+ tbl->rows[row].data = cred;
+ tbl->rows[row].flags = KHUI_CW_ROW_CRED;
+
+ /* Set any required timer events */
+ cbsize = sizeof(ft);
+ if(KHM_SUCCEEDED(kcdb_cred_get_attr(cred, KCDB_ATTR_TIMELEFT, NULL, &ft, &cbsize))) {
+ ms = FtIntervalMsToRepChange(&ft);
+ if(ms > 0) {
+ SetTimer(tbl->hwnd, (UINT_PTR) &(tbl->rows[row]), ms + 100, cw_timer_proc);
+ tbl->rows[row].flags |= KHUI_CW_ROW_TIMERSET;
+ }
+ }
+}
+
+void
+cw_set_tbl_row_header(khui_credwnd_tbl * tbl,
+ int row, int col,
+ khui_credwnd_outline * o)
+{
+ if((int) tbl->n_total_rows <= row) {
+ /* we need to resize the allocation */
+ khui_credwnd_row * newrows;
+ int newsize;
+
+ newsize = UBOUNDSS(row+1,KHUI_CW_ROW_INITIAL, KHUI_CW_ROW_INCREMENT);
+ newrows = PMALLOC(sizeof(khui_credwnd_row) * newsize);
+ memcpy(newrows, tbl->rows, sizeof(khui_credwnd_row) * tbl->n_rows);
+ PFREE(tbl->rows);
+ tbl->rows = newrows;
+ tbl->n_total_rows = newsize;
+ }
+
+ tbl->rows[row].col = col;
+ tbl->rows[row].data = (khm_handle) o;
+ tbl->rows[row].flags = KHUI_CW_ROW_HEADER;
+ if(o->flags & KHUI_CW_O_SELECTED)
+ tbl->rows[row].flags |= KHUI_CW_ROW_SELECTED;
+
+ /* if we are showing expanded identity information, we need to set
+ a timer so that we can update the identity row when the
+ identity changes. */
+ if ((tbl->flags & KHUI_CW_TBL_EXPIDENT) &&
+ tbl->cols[col].attr_id == KCDB_ATTR_ID_NAME) {
+
+ khui_credwnd_ident * cwi;
+
+ tbl->rows[row].flags |= KHUI_CW_ROW_EXPVIEW;
+
+ cwi = cw_find_ident(tbl, o->data);
+ if (cwi && FtToInt(&cwi->ft_expire) != 0) {
+ FILETIME ft;
+ FILETIME ft_now;
+
+ ft = cwi->ft_expire;
+ GetSystemTimeAsFileTime(&ft_now);
+
+ if (CompareFileTime(&ft, &ft_now) > 0) {
+ long ms;
+
+ ft = FtSub(&ft, &ft_now);
+ ms = FtIntervalMsToRepChange(&ft);
+ if (ms > 0) {
+ SetTimer(tbl->hwnd, (UINT_PTR) &(tbl->rows[row]), ms + 100,
+ cw_timer_proc);
+ tbl->rows[row].flags |= KHUI_CW_ROW_TIMERSET;
+ }
+ }
+ }
+ }
+}
+
+static int
+iwcscmp(const void * p1, const void * p2) {
+ const wchar_t * s1 = *(wchar_t **) p1;
+ const wchar_t * s2 = *(wchar_t **) p2;
+
+ return wcscmp(s1, s2);
+}
+
+void
+cw_update_outline(khui_credwnd_tbl * tbl)
+{
+ int i,j,n_rows;
+ int level;
+ int visible;
+ khm_size n_creds = 0;
+ khm_handle prevcred = NULL;
+ khm_handle thiscred = NULL;
+ /* grouping[0..n_grouping-1] are the columns that we are going to
+ group the display by. Say we are grouping by identity and then
+ by type, then grouping[0]=col# of identity and grouping[1]=col#
+ of type */
+ khm_int32 * grouping = NULL;
+ khui_credwnd_outline * ol = NULL;
+ int n_grouping;
+ wchar_t buf[256];
+ khm_size cbbuf;
+ khm_int32 flags;
+ int selected;
+ khm_int32 expstate = 0;
+
+ /* this is called after calling cw_update_creds, so we assume
+ that the credentials are all loaded and sorted according to
+ grouping rules */
+
+ /* if the columns have changed, then any outline info we have
+ cached are unreliable */
+ if(tbl->flags & KHUI_CW_TBL_COL_DIRTY) {
+ khui_credwnd_outline * o;
+ LPOP(&(tbl->outline), &o);
+ while(o) {
+ cw_del_outline(o);
+ LPOP(&(tbl->outline), &o);
+ }
+ tbl->n_rows = 0;
+ }
+
+ /* Otherwise, we should reset the outline indices. Just the first
+ level is enough */
+ if (tbl->outline) {
+ khui_credwnd_outline * o;
+
+ o = tbl->outline;
+ while(o) {
+ o->start = -1;
+ o = LNEXT(o);
+ }
+ }
+
+ /* determine the grouping order */
+ grouping = PMALLOC(sizeof(khm_int32) * tbl->n_cols);
+ for(i=0; i < (int) tbl->n_cols; i++)
+ grouping[i] = -1;
+ n_grouping = 0;
+
+ for(i=0; i < (int) tbl->n_cols; i++) {
+ /* since cw_update_creds has run, the KHUI_CW_COL_GROUP flag
+ only exists for columns that has a valid sort_index */
+ if(tbl->cols[i].flags & KHUI_CW_COL_GROUP) {
+ grouping[tbl->cols[i].sort_index] = i;
+ if(n_grouping <= tbl->cols[i].sort_index)
+ n_grouping = tbl->cols[i].sort_index + 1;
+ }
+ }
+
+ /* if we have sorted by an index without grouping by it, we can't
+ establish any grouping beyond that index. */
+ for(i=0; i < n_grouping; i++) {
+ if(grouping[i] == -1)
+ break;
+ }
+ n_grouping = i;
+
+ if(!tbl->rows) {
+ /* we haven't allocated memory yet */
+ tbl->n_total_rows = KHUI_CW_ROW_INITIAL;
+ tbl->n_rows = 0;
+ tbl->rows = PMALLOC(sizeof(khui_credwnd_row) * tbl->n_total_rows);
+ } else {
+ /* kill any pending timers */
+ for(i=0; i < (int) tbl->n_rows; i++)
+ if(tbl->rows[i].flags & KHUI_CW_ROW_TIMERSET)
+ {
+ KillTimer(tbl->hwnd, (UINT_PTR) &(tbl->rows[i]));
+ tbl->rows[i].flags &= ~KHUI_CW_ROW_TIMERSET;
+ }
+ }
+
+ if(KHM_FAILED(kcdb_credset_get_size(tbl->credset, &n_creds)))
+ goto _exit;
+
+ n_rows = 0;
+ prevcred = NULL;
+ ol = NULL;
+
+ for(i=0; i < (int) n_creds; i++) {
+ if(KHM_FAILED(kcdb_credset_get_cred(tbl->credset, i, &thiscred)))
+ continue;
+
+ /* if this credential appears to be the same as another for
+ this view, we skip it. */
+ if(prevcred && n_grouping > 0) {
+ for(j=0; j < (int) tbl->n_cols; j++) {
+ if(kcdb_creds_comp_attr(prevcred, thiscred,
+ tbl->cols[j].attr_id))
+ break;
+ }
+
+ if(j >= (int) tbl->n_cols) {
+ if (n_rows > 0) {
+ tbl->rows[n_rows - 1].idx_end = i;
+ }
+ continue;
+ }
+ }
+
+ if(!prevcred)
+ level = 0;
+ else {
+ for(j=0; j < n_grouping; j++) {
+ /* determine the grouping level at which thiscred
+ differs from prevcred */
+ if(kcdb_creds_comp_attr(prevcred,thiscred,
+ tbl->cols[grouping[j]].attr_id))
+ break;
+ }
+ level = j;
+ }
+
+ /* now we have to walk up until we get to the parent of the
+ outline level we should be in */
+ while(ol && ol->level >= level) {
+ ol->length = n_rows - ol->start;
+ ol->idx_end = i - 1;
+ ol = TPARENT(ol);
+ }
+
+ if(ol) {
+ visible = (ol->flags & KHUI_CW_O_VISIBLE) &&
+ (ol->flags & KHUI_CW_O_EXPAND);
+ selected = (ol->flags & KHUI_CW_O_SELECTED);
+ } else {
+ visible = TRUE;
+ selected = FALSE;
+ }
+
+ /* now ol points to an outline node at the next highest level
+ or is NULL if level = 0 */
+
+ for(j=level; j < n_grouping; j++) {
+ khui_credwnd_outline * to;
+ /* now we search for an outline object at the next level
+ which matches the heading */
+ cbbuf = sizeof(buf);
+ buf[0] = L'\0';
+ if(KHM_FAILED
+ (kcdb_cred_get_attr_string(thiscred,
+ tbl->cols[grouping[j]].attr_id,
+ buf, &cbbuf, 0))) {
+ cbbuf = sizeof(wchar_t);
+ buf[0] = L'\0';
+ }
+
+ if(ol)
+ to = TFIRSTCHILD(ol);
+ else
+ to = tbl->outline;
+
+ while(to) {
+ if(!wcscmp(buf, to->header))
+ break;
+ to = LNEXT(to);
+ }
+
+ if(to) {
+ /* found it */
+ ol = to;
+ } else {
+ /* not found. create */
+ to = cw_new_outline_node(buf);
+ if(ol) {
+ TADDCHILD(ol, to);
+ } else {
+ LPUSH(&(tbl->outline), to);
+ }
+ ol = to;
+ ol->flags = KHUI_CW_O_EXPAND;
+ ol->level = j;
+ ol->col = grouping[j];
+
+ if(tbl->cols[grouping[j]].attr_id == KCDB_ATTR_ID_NAME) {
+ khm_handle h;
+ if(KHM_SUCCEEDED(kcdb_identity_create(buf, 0, &h))) {
+ ol->attr_id = KCDB_ATTR_ID;
+ ol->data = (void *) h;
+
+ /* the outline only lasts as long as the
+ credential, and the credential has a hold
+ on the identity. */
+ kcdb_identity_release(h);
+ }
+ else
+ ol->data = 0;
+ } else if(tbl->cols[grouping[j]].attr_id ==
+ KCDB_ATTR_TYPE_NAME) {
+ khm_int32 t;
+
+ ol->attr_id = KCDB_ATTR_TYPE;
+ if(KHM_SUCCEEDED(kcdb_cred_get_type(thiscred, &t)))
+ ol->data = (void *)(ssize_t) t;
+ else
+ ol->data = (void *)(ssize_t) KCDB_CREDTYPE_INVALID;
+ } else {
+ khm_int32 rv;
+ khm_int32 alt_id;
+ kcdb_attrib * attrib;
+
+ rv =
+ kcdb_attrib_get_info(tbl->cols[grouping[j]].attr_id,
+ &attrib);
+ assert(KHM_SUCCEEDED(rv));
+
+ if (attrib->flags & KCDB_ATTR_FLAG_ALTVIEW)
+ alt_id = attrib->alt_id;
+ else
+ alt_id = tbl->cols[grouping[j]].attr_id;
+
+ ol->attr_id = alt_id;
+
+ kcdb_attrib_release_info(attrib);
+
+ rv = kcdb_cred_get_attr(thiscred,
+ alt_id,
+ NULL,
+ NULL,
+ &cbbuf);
+ if (rv != KHM_ERROR_TOO_LONG || cbbuf == 0) {
+ ol->data = NULL;
+ } else {
+ ol->data = PMALLOC(cbbuf);
+ assert(ol->data);
+ rv = kcdb_cred_get_attr(thiscred,
+ alt_id,
+ NULL,
+ ol->data,
+ &cbbuf);
+ assert(KHM_SUCCEEDED(rv));
+ ol->cb_data = cbbuf;
+ ol->flags |= KHUI_CW_O_DATAALLOC;
+ }
+ }
+ }
+
+ /* now ol points at the node at level j we want to be
+ in */
+ ol->start = n_rows;
+ ol->length = 0;
+ ol->idx_start = i;
+ ol->idx_end = i;
+ ol->flags &= ~(CW_EXPSTATE_MASK |
+ KHUI_CW_O_SHOWFLAG |
+ KHUI_CW_O_STICKY |
+ KHUI_CW_O_EMPTY);
+
+ /* if the outline node is for an identity, then we have to
+ check the expiration state for the identity. */
+
+ if (ol->attr_id == KCDB_ATTR_ID) {
+ khm_handle ident = (khm_handle) ol->data;
+
+ flags = cw_get_buf_exp_flags(tbl, ident);
+
+ if (flags) {
+ ol->flags |= flags;
+ ol->flags |= KHUI_CW_O_SHOWFLAG;
+ expstate |= flags;
+ } else if (grouping[j] == tbl->n_cols - 1) {
+ /* if we aren't showing any creds under this
+ outline level, we should also show any
+ flags. */
+ ol->flags |= KHUI_CW_O_SHOWFLAG;
+ }
+ }
+
+ if (grouping[j] == tbl->n_cols - 1) {
+ ol->flags |= KHUI_CW_O_NOOUTLINE;
+ } else {
+ ol->flags &= ~KHUI_CW_O_NOOUTLINE;
+ }
+
+ if(selected) {
+ ol->flags |= KHUI_CW_O_SELECTED;
+ }
+ if(visible) {
+ cw_set_tbl_row_header(tbl, n_rows, grouping[j], ol);
+ n_rows ++;
+ ol->flags |= KHUI_CW_O_VISIBLE;
+ } else {
+ ol->flags &= ~KHUI_CW_O_VISIBLE;
+ }
+ visible = visible && (ol->flags & KHUI_CW_O_EXPAND);
+ selected = (selected || (ol->flags & KHUI_CW_O_SELECTED));
+
+ }
+
+ /* we need to do this here too just in case we were already at
+ the level we were supposed to be in */
+ if (ol)
+ visible = visible && (ol->flags & KHUI_CW_O_EXPAND);
+
+ if(visible && n_grouping > 0 &&
+ grouping[n_grouping - 1] < tbl->n_cols - 1) {
+ khm_int32 c_flags;
+
+ cw_set_tbl_row_cred(tbl, n_rows, thiscred,
+ grouping[n_grouping-1]);
+
+ flags = cw_get_buf_exp_flags(tbl, thiscred);
+ if(flags) {
+ tbl->rows[n_rows].flags |= flags;
+ }
+
+ kcdb_cred_get_flags(thiscred, &c_flags);
+ if(selected ||
+ (c_flags & KCDB_CRED_FLAG_SELECTED)) {
+ tbl->rows[n_rows].flags |= KHUI_CW_ROW_SELECTED;
+ }
+
+ tbl->rows[n_rows].idx_start = i;
+ tbl->rows[n_rows].idx_end = i;
+
+ n_rows++;
+ }
+
+ if(prevcred)
+ kcdb_cred_release(prevcred);
+ prevcred = thiscred;
+ }
+
+ while(ol) {
+ ol->length = n_rows - ol->start;
+ ol->idx_end = i - 1;
+ ol = TPARENT(ol);
+ }
+
+ if(prevcred) {
+ kcdb_cred_release(prevcred);
+ prevcred = NULL;
+ }
+
+ /* Add any default identities with no credentials and sticky
+ identities that we haven't seen yet */
+ if (n_grouping > 0 &&
+ tbl->cols[grouping[0]].attr_id == KCDB_ATTR_ID_NAME) {
+
+ khui_credwnd_outline * o;
+ wchar_t * idnames = NULL;
+ wchar_t * t;
+ khm_size n_idents;
+ khm_size cb_names;
+ wchar_t ** idarray = NULL;
+ int i;
+
+ /* see if the defualt identity is in the list */
+ {
+ khm_handle id_def = NULL;
+ wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
+ khm_size cb;
+ khm_int32 flags;
+
+ if (KHM_FAILED(kcdb_identity_get_default(&id_def))) {
+ goto done_with_defident;
+ }
+
+ kcdb_identity_get_flags(id_def, &flags);
+ cb = sizeof(idname);
+ kcdb_identity_get_name(id_def, idname, &cb);
+
+ for (o = tbl->outline; o; o = LNEXT(o)) {
+ if (!wcscmp(idname, o->header))
+ break;
+ }
+
+ if (o == NULL) {
+ o = cw_new_outline_node(idname);
+ LPUSH(&tbl->outline, o);
+ o->flags = KHUI_CW_O_VISIBLE | KHUI_CW_O_RELIDENT | KHUI_CW_O_EMPTY;
+ o->level = 0;
+ o->col = grouping[0];
+ o->data = id_def;
+ o->attr_id = KCDB_ATTR_ID;
+ o->start = -1;
+ } else {
+ kcdb_identity_release(id_def);
+ }
+
+ if (o->start != -1)
+ goto done_with_defident;
+
+ if (flags & KCDB_IDENT_FLAG_STICKY)
+ o->flags |= KHUI_CW_O_STICKY;
+ else
+ o->flags &= ~KHUI_CW_O_STICKY;
+
+ o->start = n_rows;
+ o->length = 1;
+ o->idx_start = -1;
+ o->idx_end = -1;
+
+ if (grouping[0] == tbl->n_cols - 1)
+ o->flags |= KHUI_CW_O_NOOUTLINE;
+
+ cw_set_tbl_row_header(tbl, n_rows, grouping[0], o);
+
+ n_rows ++;
+
+ done_with_defident:
+ ;
+ }
+
+ if (kcdb_identity_enum(KCDB_IDENT_FLAG_STICKY,
+ KCDB_IDENT_FLAG_STICKY,
+ NULL,
+ &cb_names,
+ &n_idents) != KHM_ERROR_TOO_LONG ||
+ n_idents == 0 ||
+ cb_names == 0)
+ goto _cleanup_sticky;
+
+ idnames = PMALLOC(cb_names);
+ idarray = PMALLOC(n_idents * sizeof(*idarray));
+#ifdef DEBUG
+ assert(idnames);
+ assert(idarray);
+#endif
+
+ if (KHM_FAILED(kcdb_identity_enum(KCDB_IDENT_FLAG_STICKY,
+ KCDB_IDENT_FLAG_STICKY,
+ idnames,
+ &cb_names,
+ &n_idents)))
+ goto _cleanup_sticky;
+
+ for (i=0, t=idnames; t && *t; t = multi_string_next(t), i++) {
+ idarray[i] = t;
+ }
+
+ qsort(idarray, n_idents, sizeof(*idarray), iwcscmp);
+
+ for (i=0; i < (int) n_idents; i++) {
+ khm_handle h;
+
+ if (KHM_FAILED(kcdb_identity_create(idarray[i],
+ KCDB_IDENT_FLAG_CREATE, &h)))
+ continue;
+
+ for (o = tbl->outline; o; o = LNEXT(o)) {
+ if (!wcscmp(idarray[i], o->header))
+ break;
+ }
+
+ if (o) {
+ /* found it */
+ if (o->start != -1) /* already visible? */
+ continue;
+ o->flags &= KHUI_CW_O_RELIDENT;
+ o->flags |= KHUI_CW_O_STICKY | KHUI_CW_O_VISIBLE | KHUI_CW_O_EMPTY;
+
+ if (!kcdb_identity_is_equal(o->data, h)) {
+ if (o->flags & KHUI_CW_O_RELIDENT)
+ kcdb_identity_release(o->data);
+ o->data = h;
+ o->flags |= KHUI_CW_O_RELIDENT;
+ kcdb_identity_hold(h);
+ }
+ } else {
+ /* not found. create */
+ o = cw_new_outline_node(idarray[i]);
+ LPUSH(&tbl->outline, o);
+ o->flags = KHUI_CW_O_STICKY | KHUI_CW_O_VISIBLE | KHUI_CW_O_EMPTY | KHUI_CW_O_RELIDENT;
+ o->level = 0;
+ o->col = grouping[0];
+ o->data = h;
+ kcdb_identity_hold(h);
+ o->attr_id = KCDB_ATTR_ID;
+ }
+
+ if (grouping[0] == tbl->n_cols - 1)
+ o->flags |= KHUI_CW_O_NOOUTLINE;
+
+ kcdb_identity_release(h);
+
+ o->flags &= ~KHUI_CW_O_EXPAND;
+ o->start = n_rows;
+ o->length = 1;
+ o->idx_start = -1;
+ o->idx_end = -1;
+
+ cw_set_tbl_row_header(tbl, n_rows, grouping[0], o);
+
+ n_rows ++;
+ }
+
+ _cleanup_sticky:
+ if (idnames)
+ PFREE(idnames);
+ if (idarray)
+ PFREE(idarray);
+ }
+
+ tbl->n_rows = n_rows;
+ tbl->flags |= KHUI_CW_TBL_ROW_DIRTY;
+
+ tbl->flags &= ~KHUI_CW_TBL_COL_DIRTY;
+
+ if (tbl->cursor_row >= tbl->n_rows)
+ tbl->cursor_row = tbl->n_rows - 1;
+ if (tbl->cursor_row < 0)
+ tbl->cursor_row = 0;
+_exit:
+ if(grouping)
+ PFREE(grouping);
+
+ /* note that the expstate is derived from whether or not
+ * we have expiration states set for any active identities */
+ if (n_creds == 0)
+ khm_notify_icon_expstate(KHM_NOTIF_EMPTY);
+ else if ((expstate & CW_EXPSTATE_EXPIRED) == CW_EXPSTATE_EXPIRED)
+ khm_notify_icon_expstate(KHM_NOTIF_EXP);
+ else if ((expstate & CW_EXPSTATE_WARN) == CW_EXPSTATE_WARN ||
+ (expstate & CW_EXPSTATE_CRITICAL) == CW_EXPSTATE_CRITICAL)
+ khm_notify_icon_expstate(KHM_NOTIF_WARN);
+ else
+ khm_notify_icon_expstate(KHM_NOTIF_OK);
+}
+
+void
+cw_unload_view(khui_credwnd_tbl * tbl)
+{
+#define SafeDeleteObject(o) \
+ do { \
+ if(o) { \
+ DeleteObject(o); \
+ o = NULL; \
+ } \
+ } while(0)
+
+ SafeDeleteObject(tbl->hf_header);
+ SafeDeleteObject(tbl->hf_normal);
+ SafeDeleteObject(tbl->hf_bold);
+ SafeDeleteObject(tbl->hf_bold_header);
+
+ SafeDeleteObject(tbl->hb_grey);
+ SafeDeleteObject(tbl->hb_normal);
+ SafeDeleteObject(tbl->hb_s);
+
+ SafeDeleteObject(tbl->hb_hdr_bg);
+ SafeDeleteObject(tbl->hb_hdr_bg_crit);
+ SafeDeleteObject(tbl->hb_hdr_bg_exp);
+ SafeDeleteObject(tbl->hb_hdr_bg_warn);
+ SafeDeleteObject(tbl->hb_hdr_bg_def);
+
+ SafeDeleteObject(tbl->hb_hdr_bg_s);
+ SafeDeleteObject(tbl->hb_hdr_bg_crit_s);
+ SafeDeleteObject(tbl->hb_hdr_bg_exp_s);
+ SafeDeleteObject(tbl->hb_hdr_bg_warn_s);
+ SafeDeleteObject(tbl->hb_hdr_bg_def_s);
+
+#undef SafeDeleteObject
+
+ if (tbl->hi_lg_ident) {
+ DestroyIcon(tbl->hi_lg_ident);
+ tbl->hi_lg_ident = NULL;
+ }
+
+ if(tbl->credset) {
+ kcdb_credset_delete(tbl->credset);
+ tbl->credset = NULL;
+ }
+ if(tbl->ilist) {
+ khui_delete_ilist(tbl->ilist);
+ tbl->ilist = NULL;
+ }
+
+ if(tbl->cols) {
+ int i;
+
+ for(i=0; i < tbl->n_cols; i++) {
+ if(tbl->cols[i].title)
+ PFREE(tbl->cols[i].title);
+ Header_DeleteItem(tbl->hwnd_header, 0);
+
+ if (tbl->cols[i].attr_id >= 0 &&
+ tbl->cols[i].attr_id <= KCDB_ATTR_MAX_ID &&
+ attr_to_action[tbl->cols[i].attr_id]) {
+
+ khui_check_action(attr_to_action[tbl->cols[i].attr_id], FALSE);
+
+ }
+ }
+ PFREE(tbl->cols);
+ tbl->cols = NULL;
+ tbl->n_cols = 0;
+ tbl->n_total_cols = 0;
+
+ kmq_post_message(KMSG_ACT, KMSG_ACT_REFRESH, 0, 0);
+ }
+
+ if(tbl->rows) {
+ PFREE(tbl->rows);
+ tbl->rows = NULL;
+ tbl->n_rows = 0;
+ tbl->n_total_rows = 0;
+ }
+
+ khui_delete_bitmap(&tbl->kbm_logo_shade);
+
+ if (tbl->csp_view) {
+ khc_close_space(tbl->csp_view);
+ tbl->csp_view = NULL;
+ }
+
+ tbl->cell_height = 0; /* recalculate cell height next time */
+
+ if (tbl->idents) {
+ khm_size i;
+
+ for (i=0; i < tbl->n_idents; i++) {
+ if (tbl->idents[i].ident) {
+ kcdb_identity_release(tbl->idents[i].ident);
+ }
+ }
+
+ PFREE(tbl->idents);
+ tbl->idents = NULL;
+ tbl->n_idents = 0;
+ tbl->nc_idents = 0;
+ }
+}
+
+void
+cw_hditem_from_tbl_col(khui_credwnd_col * col, HDITEM *phi)
+{
+ size_t cchsize;
+
+ phi->mask = HDI_FORMAT | HDI_LPARAM | HDI_WIDTH;
+ if(cw_is_custom_attr(col->attr_id)) {
+ if(col->attr_id == CW_CA_FLAGS) {
+ phi->fmt = 0;
+ } else if(col->attr_id == CW_CA_TYPEICON) {
+ phi->fmt = 0;
+ } else {
+ /* what the? */
+ /*TODO: throw up and die */
+ }
+ } else {
+ phi->mask |= HDI_TEXT;
+ phi->pszText = col->title;
+ StringCchLength(col->title, KCDB_MAXCCH_SHORT_DESC, &cchsize);
+ phi->cchTextMax = (int) cchsize;
+ phi->fmt = HDF_CENTER | HDF_STRING;
+ }
+ phi->lParam = col->attr_id;
+#if (_WIN32_WINNT >= 0x501)
+ if (IS_COMMCTL6()) {
+ if(col->flags & KHUI_CW_COL_SORT_INC) {
+ phi->fmt |= HDF_SORTUP;
+ } else if(col->flags & KHUI_CW_COL_SORT_DEC) {
+ phi->fmt |= HDF_SORTDOWN;
+ }
+ }
+#endif
+ if(col->width < 0) {
+ /*TODO: come up with a better way to handle this case */
+ col->width = 200;
+ }
+ phi->cxy = col->width;
+}
+
+int
+cw_get_cell_height(HDC hdc, HFONT hf) {
+ SIZE size;
+ size_t cbbuf;
+ wchar_t buf[64];
+ HFONT hfold = NULL;
+
+ if (hf)
+ hfold = SelectFont(hdc, hf);
+
+ LoadString(khm_hInstance, IDS_SAMPLE_STRING, buf, sizeof(buf)/sizeof(buf[0]));
+ StringCchLength(buf, sizeof(buf)/sizeof(buf[0]), &cbbuf);
+ GetTextExtentPoint32(hdc, buf, (int) cbbuf, &size);
+
+ if (hf)
+ SelectFont(hdc, hfold);
+
+ return size.cy;
+}
+
+int
+cw_update_header_column_width(khui_credwnd_tbl * tbl, int c) {
+ int idx;
+ HDITEM hi;
+
+#ifdef DEBUG
+ assert(c >= 0 && c < tbl->n_cols);
+#endif
+
+ if (tbl->hwnd_header == NULL)
+ return 0;
+
+ idx = Header_OrderToIndex(tbl->hwnd_header, c);
+ ZeroMemory(&hi, sizeof(hi));
+ hi.mask = HDI_WIDTH;
+ hi.cxy = tbl->cols[c].width;
+ return Header_SetItem(tbl->hwnd_header, idx, &hi);
+}
+
+/* returns a bitmask indicating which measures were changed */
+int
+cw_update_extents(khui_credwnd_tbl * tbl,
+ khm_boolean update_scroll) {
+ int ext_x = 0;
+ int ext_y = 0;
+ int i;
+ int filler_col = -1;
+ int fill_adjusted = 0;
+
+ recompute_columns:
+
+ ext_x = 0;
+ for(i=0; i < (int) tbl->n_cols; i++) {
+ tbl->cols[i].x = ext_x;
+ if (tbl->cols[i].flags & KHUI_CW_COL_FILLER) {
+ if (filler_col == -1)
+ filler_col = i;
+ }
+ ext_x += tbl->cols[i].width;
+ }
+
+ if (filler_col != -1 && !fill_adjusted) {
+ RECT r;
+ int delta;
+
+ GetClientRect(tbl->hwnd, &r);
+
+ /* we decrement the width so that the width data area is
+ strictly less than the width of the client area. Windows
+ doesn't disable a scrollbar unless the range is strictly
+ less than the page size. */
+ delta = ((r.right - r.left) - 1) - ext_x;
+
+ if (tbl->cols[filler_col].width + delta <= GetSystemMetrics(SM_CXSMICON)) {
+ tbl->cols[filler_col].width = GetSystemMetrics(SM_CXICON);
+ } else {
+ tbl->cols[filler_col].width += delta;
+ }
+
+ cw_update_header_column_width(tbl, filler_col);
+
+ fill_adjusted = 1;
+ goto recompute_columns;
+ }
+
+ if(!tbl->cell_height) {
+ HDC dc;
+ int maxheight = 0;
+ int height;
+
+ dc = GetWindowDC(tbl->hwnd);
+
+ maxheight = cw_get_cell_height(dc, tbl->hf_normal);
+ height = cw_get_cell_height(dc, tbl->hf_bold);
+ if (height > maxheight)
+ maxheight = height;
+ height = cw_get_cell_height(dc, tbl->hf_header);
+ if (height > maxheight)
+ maxheight = height;
+ height = cw_get_cell_height(dc, tbl->hf_bold_header);
+ if (height > maxheight)
+ maxheight = height;
+
+ ReleaseDC(tbl->hwnd, dc);
+
+ tbl->cell_height = height + tbl->vpad * 2;
+ }
+
+ if (tbl->flags & KHUI_CW_TBL_EXPIDENT) {
+ RECT r;
+
+ ext_y = 0;
+ r.left = 0;
+ r.right = ext_x;
+
+ for (i=0; i < (int) tbl->n_rows; i++) {
+ r.top = ext_y;
+ if (tbl->rows[i].flags & KHUI_CW_ROW_EXPVIEW) {
+ ext_y += tbl->cell_height * CW_EXP_ROW_MULT;
+ } else {
+ ext_y += tbl->cell_height;
+ }
+ r.bottom = ext_y;
+ tbl->rows[i].r_ext = r;
+ }
+ } else {
+ RECT r;
+
+ r.left = 0;
+ r.right = ext_x;
+
+ for (i=0; i < (int) tbl->n_rows; i++) {
+ r.top = i * tbl->cell_height;
+ r.bottom = r.top + tbl->cell_height;
+
+ tbl->rows[i].r_ext = r;
+ }
+
+ ext_y = (int) tbl->n_rows * tbl->cell_height;
+ }
+
+ tbl->ext_width = ext_x;
+ tbl->ext_height = ext_y;
+
+ /* useful in the future when implementing variable height rows.
+ The KHUI_CW_TBL_ROW_DIRTY bit indicates that the rows have
+ changed and that the y extent has to be recalculated. */
+ tbl->flags &= ~KHUI_CW_TBL_ROW_DIRTY;
+
+ if(update_scroll) {
+ RECT r;
+ int cl_w;
+ int cl_h;
+ SCROLLINFO si;
+ WINDOWPOS pw;
+ HDLAYOUT hdl;
+
+ /* update the header control first */
+
+ retry_update_scroll:
+ GetClientRect(tbl->hwnd, &r);
+
+ cl_w = r.right - r.left;
+ cl_h = (r.bottom - r.top);
+ cl_h -= tbl->header_height;
+
+ if(tbl->scr_top < 0 || tbl->ext_height < cl_h)
+ tbl->scr_top = 0;
+ else if(tbl->scr_top > tbl->ext_height - cl_h)
+ tbl->scr_top = tbl->ext_height - cl_h;
+ if(tbl->scr_left < 0 || tbl->ext_width < cl_w)
+ tbl->scr_left = 0;
+ else if(tbl->scr_left > tbl->ext_width - cl_w)
+ tbl->scr_left = tbl->ext_width - cl_w;
+
+ /* adjustments for scrolling */
+ r.left -= tbl->scr_left;
+ r.right = max(tbl->ext_width + r.left, r.right);
+
+ hdl.prc = &r;
+ hdl.pwpos = &pw;
+
+ Header_Layout(tbl->hwnd_header, &hdl);
+
+ if(tbl->header_height == 0) {
+ tbl->header_height = pw.cy;
+ goto retry_update_scroll;
+ } else
+ tbl->header_height = pw.cy;
+
+ SetWindowPos(
+ tbl->hwnd_header,
+ pw.hwndInsertAfter,
+ pw.x,
+ pw.y,
+ pw.cx,
+ pw.cy,
+ pw.flags);
+
+ si.cbSize = sizeof(si);
+ si.nMin = 0;
+ si.nMax = tbl->ext_height;
+ si.nPage = cl_h;
+ si.nPos = tbl->scr_top;
+ si.fMask = SIF_ALL | SIF_DISABLENOSCROLL;
+ SetScrollInfo(tbl->hwnd, SB_VERT, &si, TRUE);
+
+ si.cbSize = sizeof(si);
+ si.nMin = 0;
+ si.nMax = tbl->ext_width;
+ si.nPage = cl_w;
+ si.nPos = tbl->scr_left;
+ si.fMask = SIF_ALL | SIF_DISABLENOSCROLL;
+ SetScrollInfo(tbl->hwnd, SB_HORZ, &si, TRUE);
+ }
+
+ return 0;
+}
+
+void
+cw_insert_header_cols(khui_credwnd_tbl * tbl) {
+ HWND hdr;
+ HDITEM hi;
+ int i;
+
+ hdr = tbl->hwnd_header;
+
+ for(i=0; i < (int) tbl->n_cols; i++) {
+ cw_hditem_from_tbl_col(&(tbl->cols[i]), &hi);
+ Header_InsertItem(hdr, 512, &hi);
+ }
+}
+
+#define CW_ER_BLANK 0
+#define CW_ER_GREY 1
+#define CW_ER_SEL 2
+
+void
+cw_erase_rect(HDC hdc,
+ khui_credwnd_tbl * tbl,
+ RECT * r_wnd,
+ RECT * r_erase,
+ int type)
+{
+ RECT rlogo;
+ RECT ri;
+ RECT t;
+ BOOL rie;
+ HBRUSH hbr;
+
+ switch(type) {
+ case CW_ER_BLANK:
+ hbr = tbl->hb_normal;
+ break;
+
+ case CW_ER_GREY:
+ hbr = tbl->hb_grey;
+ break;
+
+ case CW_ER_SEL:
+ hbr = tbl->hb_s;
+ break;
+
+ default:
+ return;
+ }
+
+ if(tbl->kbm_logo_shade.cx != -1 && type == CW_ER_BLANK) {
+ rlogo.left = r_wnd->right - tbl->kbm_logo_shade.cx;
+ rlogo.right = r_wnd->right;
+ rlogo.top = r_wnd->bottom - tbl->kbm_logo_shade.cy;
+ rlogo.bottom = r_wnd->bottom;
+ rie = IntersectRect(&ri, r_erase, &rlogo);
+ } else {
+ ZeroMemory(&rlogo, sizeof(rlogo));
+ ZeroMemory(&ri, sizeof(ri));
+ rie = FALSE;
+ }
+
+ if(!rie) {
+ FillRect(hdc, r_erase, hbr);
+ } else {
+ HDC hdcb = CreateCompatibleDC(hdc);
+ HBITMAP hbmold = SelectObject(hdcb, tbl->kbm_logo_shade.hbmp);
+
+ BitBlt(hdc, ri.left, ri.top, ri.right - ri.left, ri.bottom - ri.top,
+ hdcb, ri.left - rlogo.left, ri.top - rlogo.top, SRCCOPY);
+
+ SelectObject(hdcb, hbmold);
+ DeleteDC(hdcb);
+
+ if(r_erase->top < ri.top && r_erase->left < ri.left) {
+ t.left = r_erase->left;
+ t.top = r_erase->top;
+ t.right = ri.left;
+ t.bottom = ri.top;
+ FillRect(hdc, &t, hbr);
+ }
+
+ if(r_erase->left < ri.left) {
+ t.left = r_erase->left;
+ t.top = ri.top;
+ t.right = ri.left;
+ t.bottom = ri.bottom;
+ FillRect(hdc, &t, hbr);
+ }
+
+ if(r_erase->top < ri.top) {
+ t.left = ri.left;
+ t.top = r_erase->top;
+ t.right = ri.right;
+ t.bottom = ri.top;
+ FillRect(hdc, &t, hbr);
+ }
+ }
+}
+
+void
+cw_draw_header(HDC hdc,
+ khui_credwnd_tbl * tbl,
+ int row,
+ RECT * r)
+{
+ int colattr;
+ HPEN pl, pold;
+ khui_credwnd_row * cr;
+ khui_credwnd_outline * o;
+ int selected = 0;
+ khm_int32 idf = 0;
+
+ /* each header consists of a couple of widgets and some text */
+ /* we need to figure out the background color first */
+
+ cr = &(tbl->rows[row]);
+ o = (khui_credwnd_outline *) cr->data;
+
+ colattr = tbl->cols[cr->col].attr_id;
+
+ if (colattr == KCDB_ATTR_ID_NAME) {
+ khm_handle ident = o->data;
+
+ kcdb_identity_get_flags(ident, &idf);
+ }
+
+ selected = o->flags & KHUI_CW_O_SELECTED;
+
+ {
+ HBRUSH hbr;
+
+ if(selected) {
+ if ((o->flags & CW_EXPSTATE_MASK) == CW_EXPSTATE_EXPIRED)
+ hbr = tbl->hb_hdr_bg_exp_s;
+ else if ((o->flags & CW_EXPSTATE_MASK) == CW_EXPSTATE_CRITICAL)
+ hbr = tbl->hb_hdr_bg_crit_s;
+ else if ((o->flags & CW_EXPSTATE_MASK) == CW_EXPSTATE_WARN)
+ hbr = tbl->hb_hdr_bg_warn_s;
+ else if (idf & KCDB_IDENT_FLAG_DEFAULT)
+ hbr = tbl->hb_hdr_bg_def_s;
+ else
+ hbr = tbl->hb_hdr_bg_s;
+ } else {
+ if ((o->flags & CW_EXPSTATE_MASK) == CW_EXPSTATE_EXPIRED)
+ hbr = tbl->hb_hdr_bg_exp;
+ else if ((o->flags & CW_EXPSTATE_MASK) == CW_EXPSTATE_CRITICAL)
+ hbr = tbl->hb_hdr_bg_crit;
+ else if ((o->flags & CW_EXPSTATE_MASK) == CW_EXPSTATE_WARN)
+ hbr = tbl->hb_hdr_bg_warn;
+ else if (idf & KCDB_IDENT_FLAG_DEFAULT)
+ hbr = tbl->hb_hdr_bg_def;
+ else
+ hbr = tbl->hb_hdr_bg;
+ }
+
+ FillRect(hdc, r, hbr);
+ }
+
+ /* draw the background */
+ pl = CreatePen(PS_SOLID, 0, tbl->cr_hdr_outline);
+ pold = SelectObject(hdc, pl);
+ MoveToEx(hdc, r->left, r->bottom - 1, NULL);
+ LineTo(hdc,r->right,r->bottom - 1);
+ SelectObject(hdc, pold);
+ DeleteObject(pl);
+
+ if (!(o->flags & KHUI_CW_O_NOOUTLINE) &&
+ !(o->flags & KHUI_CW_O_EMPTY)) {
+ if((tbl->mouse_state & CW_MOUSE_WOUTLINE) &&
+ tbl->mouse_row == row) {
+ if(o->flags & KHUI_CW_O_EXPAND) {
+ khui_ilist_draw_id(tbl->ilist, IDB_WDG_EXPAND_HI,
+ hdc, r->left,
+ (r->top + r->bottom - KHUI_SMICON_CY) / 2, 0);
+ } else {
+ khui_ilist_draw_id(tbl->ilist, IDB_WDG_COLLAPSE_HI,
+ hdc, r->left,
+ (r->top + r->bottom - KHUI_SMICON_CY) / 2, 0);
+ }
+ } else {
+ if(o->flags & KHUI_CW_O_EXPAND) {
+ khui_ilist_draw_id(tbl->ilist, IDB_WDG_EXPAND,
+ hdc, r->left,
+ (r->top + r->bottom - KHUI_SMICON_CY) / 2, 0);
+ } else {
+ khui_ilist_draw_id(tbl->ilist, IDB_WDG_COLLAPSE,
+ hdc, r->left,
+ (r->top + r->bottom - KHUI_SMICON_CY) / 2, 0);
+ }
+ }
+
+ r->left += KHUI_SMICON_CX * 3 / 2;
+ } else if (!(o->flags & KHUI_CW_O_NOOUTLINE)) {
+ r->left += KHUI_SMICON_CX * 3 / 2;
+ }
+
+ /* try to draw the icon, if there is one */
+ if(colattr == KCDB_ATTR_ID_NAME) {
+
+ khui_ilist_draw_id(tbl->ilist,
+ (((tbl->mouse_state & CW_MOUSE_WSTICKY) &&
+ tbl->mouse_row == row)?
+ ((idf & KCDB_IDENT_FLAG_STICKY)?
+ IDB_WDG_STUCK_HI:
+ IDB_WDG_STICK_HI):
+ ((idf & KCDB_IDENT_FLAG_STICKY)?
+ IDB_WDG_STUCK:
+ IDB_WDG_STICK)),
+ hdc,
+ r->left,
+ (r->top + r->bottom - KHUI_SMICON_CY) / 2, 0);
+
+ r->left += KHUI_SMICON_CX * 3 / 2;
+
+ /* the TRUE part of the 'if' is for drawing large icons. It's
+ disabled for now until we have new icons. */
+ if ((cr->flags & KHUI_CW_ROW_EXPVIEW) && FALSE) {
+ int cx = GetSystemMetrics(SM_CXICON);
+ int cy = GetSystemMetrics(SM_CYICON);
+
+ DrawIcon(hdc, r->left, (r->top + r->bottom - cy) / 2, tbl->hi_lg_ident);
+
+ r->left += cx + KHUI_SMICON_CX / 2;
+
+ } else {
+ khui_ilist_draw_id(tbl->ilist,
+ ((o->flags & KHUI_CW_O_EMPTY)?
+ IDB_ID_DIS_SM:
+ IDB_ID_SM),
+ hdc,
+ r->left,
+ (r->top + r->bottom - KHUI_SMICON_CY) / 2, 0);
+ r->left += KHUI_SMICON_CX * 3 / 2 ;
+ }
+ }
+
+
+ if (!(cr->flags & KHUI_CW_ROW_EXPVIEW)) {
+
+ SetTextAlign(hdc, TA_BOTTOM | TA_LEFT);
+
+ if(selected)
+ SetTextColor(hdc, tbl->cr_hdr_s);
+ else
+ SetTextColor(hdc, tbl->cr_hdr_normal);
+
+ TextOut(hdc, r->left, r->bottom - tbl->vpad, o->header, (int) wcslen(o->header));
+
+ if (colattr == KCDB_ATTR_ID_NAME &&
+ (idf & KCDB_IDENT_FLAG_DEFAULT)) {
+ wchar_t defstr[64];
+ SIZE size;
+
+ LoadString(khm_hInstance, IDS_CW_DEFAULT,
+ defstr, ARRAYLENGTH(defstr));
+
+ GetTextExtentPoint32(hdc, o->header, (int) wcslen(o->header),
+ &size);
+
+ r->left += size.cx + KHUI_SMICON_CX * 2;
+
+ TextOut(hdc, r->left, r->bottom - tbl->vpad,
+ defstr, (int) wcslen(defstr));
+ }
+ } else {
+
+ RECT tr;
+ int len;
+ wchar_t typestr[128];
+ int cx_id;
+ SIZE size;
+ khui_credwnd_ident * cwi;
+
+ /* expanded view */
+#ifdef DEBUG
+ assert(colattr == KCDB_ATTR_ID_NAME);
+#endif
+
+ cwi = cw_find_ident(tbl, o->data);
+
+ CopyRect(&tr, r);
+ tr.bottom -= (tr.bottom - tr.top) / 2; /* drawing two lines of text */
+
+ if (selected)
+ SetTextColor(hdc, tbl->cr_hdr_s);
+ else
+ SetTextColor(hdc, tbl->cr_hdr_normal);
+
+ len = (int) wcslen(o->header);
+ DrawText(hdc, o->header, len, &tr, DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS);
+ GetTextExtentPoint32(hdc, o->header, (int) len, &size);
+ cx_id = size.cx;
+
+ typestr[0] = L'\0';
+
+ if ((idf & KCDB_IDENT_FLAG_DEFAULT)) {
+ if (cwi && cwi->credtype_name[0]) {
+ wchar_t fmt[64];
+
+ LoadString(khm_hInstance, IDS_CW_DEFAULTTF,
+ fmt, ARRAYLENGTH(fmt));
+ StringCbPrintf(typestr, sizeof(typestr), fmt,
+ cwi->credtype_name);
+ } else {
+ LoadString(khm_hInstance, IDS_CW_DEFAULT,
+ typestr, ARRAYLENGTH(typestr));
+ }
+ } else if (cwi && cwi->credtype_name[0]) {
+ wchar_t fmt[64];
+
+ LoadString(khm_hInstance, IDS_CW_TYPEF,
+ fmt, ARRAYLENGTH(fmt));
+ StringCbPrintf(typestr, sizeof(typestr), fmt,
+ cwi->credtype_name);
+ }
+
+ if (typestr[0]) {
+ int cx_str;
+
+ len = (int) wcslen(typestr);
+ GetTextExtentPoint32(hdc, typestr, (int) len, &size);
+ cx_str = size.cx + KHUI_SMICON_CX / 2;
+
+ tr.left = max(tr.right - cx_str, tr.left + cx_id + KHUI_SMICON_CX * 2);
+ if (selected)
+ SetTextColor(hdc, tbl->cr_hdr_gray_s);
+ else
+ SetTextColor(hdc, tbl->cr_hdr_gray);
+ DrawText(hdc, typestr, len, &tr, DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS);
+ }
+
+ CopyRect(&tr, r);
+ tr.top += (tr.bottom - tr.top) / 2;
+
+ if (1) {
+ wchar_t buf[128];
+ khui_credwnd_ident * cwi;
+
+ buf[0] = L'\0';
+ cwi = cw_find_ident(tbl, o->data);
+
+ if (cwi) {
+#ifdef SHOW_CREDENTIAL_COUNTS
+ if (cwi->credcount == 0)
+ LoadString(khm_hInstance, IDS_IDEXPDISP_NOCRED,
+ buf, ARRAYLENGTH(buf));
+ else if (cwi->credcount == 1)
+ LoadString(khm_hInstance, IDS_IDEXPDISP_1CRED,
+ buf, ARRAYLENGTH(buf));
+ else {
+ wchar_t fmt[128];
+ LoadString(khm_hInstance, IDS_IDEXPDISP_NCRED,
+ fmt, ARRAYLENGTH(fmt));
+ StringCbPrintf(buf, sizeof(buf), fmt, (int) cwi->credcount);
+ }
+#else
+ if (FtToInt(&cwi->ft_expire) != 0) {
+ FILETIME ft_now;
+
+ GetSystemTimeAsFileTime(&ft_now);
+ if (CompareFileTime(&cwi->ft_expire, &ft_now) > 0) {
+ wchar_t fmt[64];
+ wchar_t intstr[128];
+ FILETIME ft;
+ khm_size cb;
+
+ ft = FtSub(&cwi->ft_expire, &ft_now);
+ intstr[0] = L'\0';
+ cb = sizeof(intstr);
+ FtIntervalToString(&ft, intstr, &cb);
+
+ LoadString(khm_hInstance, IDS_CW_EXPIREF,
+ fmt, ARRAYLENGTH(fmt));
+ StringCbPrintf(buf, sizeof(buf), fmt, intstr);
+ } else {
+ LoadString(khm_hInstance, IDS_CW_EXPIRED,
+ buf, ARRAYLENGTH(buf));
+ }
+ }
+#endif
+
+ len = (int) wcslen(buf);
+
+ if (selected)
+ SetTextColor(hdc, tbl->cr_hdr_gray_s);
+ else
+ SetTextColor(hdc, tbl->cr_hdr_gray);
+ DrawText(hdc, buf, len, &tr, DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS);
+ }
+ }
+ }
+}
+
+LRESULT
+cw_handle_header_msg(khui_credwnd_tbl * tbl, LPNMHEADER ph) {
+ RECT r;
+ HDITEM hi;
+
+ switch(ph->hdr.code) {
+ /*TODO:Make it track smoother */
+ case HDN_BEGINTRACK:
+ {
+ ZeroMemory(&hi, sizeof(hi));
+ hi.mask = HDI_ORDER;
+ Header_GetItem(tbl->hwnd_header, ph->iItem, &hi);
+
+ if(tbl->cols[hi.iOrder].flags & KHUI_CW_COL_FIXED_WIDTH)
+ return TRUE;
+ else
+ return FALSE;
+ }
+
+ case HDN_TRACK:
+ return FALSE;
+
+ case HDN_ENDTRACK:
+ {
+ int width;
+ hi.mask = HDI_ORDER;
+ Header_GetItem(ph->hdr.hwndFrom, ph->iItem, &hi);
+ Header_GetItemRect(ph->hdr.hwndFrom, ph->iItem, &r);
+ width = r.right - r.left;
+ if(width != tbl->cols[hi.iOrder].width) {
+ tbl->cols[hi.iOrder].width = width;
+ cw_update_extents(tbl, TRUE);
+ InvalidateRect(tbl->hwnd, NULL, FALSE);
+ }
+ }
+ break;
+
+ case HDN_BEGINDRAG:
+ {
+
+ ZeroMemory(&hi, sizeof(hi));
+ hi.mask = HDI_ORDER;
+ Header_GetItem(tbl->hwnd_header, ph->iItem, &hi);
+
+ if (tbl->cols[hi.iOrder].flags & KHUI_CW_COL_FIXED_POS) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+ }
+ break;
+
+ case HDN_ENDDRAG:
+ {
+ int drag_start_index;
+ int drag_end_index;
+ int i;
+ khui_credwnd_col tcol;
+ int sort_index = 0;
+ khm_int32 old_flags;
+
+ if (ph->pitem == NULL)
+ return TRUE;
+
+ hi.mask = HDI_ORDER;
+ Header_GetItem(tbl->hwnd_header, ph->iItem, &hi);
+ drag_start_index = hi.iOrder;
+ drag_end_index = ph->pitem->iOrder;
+
+ /* the user dragged the column which was at drag_start_index
+ to drag_end_index. */
+
+ if (drag_end_index == drag_start_index)
+ return TRUE;
+
+ /* we don't allow dragging in to the "fixed" area. */
+ for (i=0; i < tbl->n_cols; i++) {
+ if (!(tbl->cols[i].flags & KHUI_CW_COL_FIXED_POS))
+ break;
+ }
+
+ if (drag_end_index <= i)
+ return TRUE;
+
+ tcol = tbl->cols[drag_start_index];
+ if (drag_end_index < drag_start_index) {
+ MoveMemory(&tbl->cols[drag_end_index + 1],
+ &tbl->cols[drag_end_index],
+ sizeof(tbl->cols[0]) *
+ (drag_start_index - drag_end_index));
+ } else {
+ MoveMemory(&tbl->cols[drag_start_index],
+ &tbl->cols[drag_start_index + 1],
+ sizeof(tbl->cols[0]) *
+ (drag_end_index - drag_start_index));
+ }
+ tbl->cols[drag_end_index] = tcol;
+
+ old_flags = tbl->cols[drag_end_index].flags;
+
+ if (drag_end_index < tbl->n_cols - 1) {
+ khm_int32 tflags = tbl->cols[drag_end_index + 1].flags;
+
+ if (tflags & KHUI_CW_COL_GROUP) {
+ tbl->cols[drag_end_index].flags |= KHUI_CW_COL_GROUP;
+ }
+
+ if ((tflags & (KHUI_CW_COL_SORT_INC | KHUI_CW_COL_SORT_DEC)) &&
+ !(old_flags & (KHUI_CW_COL_SORT_INC | KHUI_CW_COL_SORT_DEC)))
+ tbl->cols[drag_end_index].flags |= KHUI_CW_COL_SORT_INC;
+ }
+
+ if (drag_end_index > 0) {
+ khm_int32 tflags = tbl->cols[drag_end_index - 1].flags;
+
+ if (!(tflags & KHUI_CW_COL_GROUP))
+ tbl->cols[drag_end_index].flags &= ~KHUI_CW_COL_GROUP;
+
+ if (!(tflags & (KHUI_CW_COL_SORT_INC | KHUI_CW_COL_SORT_DEC)))
+ tbl->cols[drag_end_index].flags &=
+ ~(KHUI_CW_COL_SORT_INC | KHUI_CW_COL_SORT_DEC);
+ }
+
+ if (old_flags != tbl->cols[drag_end_index].flags) {
+ cw_hditem_from_tbl_col(&tbl->cols[drag_end_index], &hi);
+ hi.mask = HDI_FORMAT;
+ Header_SetItem(tbl->hwnd_header, ph->iItem, &hi);
+ }
+
+ if ((old_flags ^ tbl->cols[drag_end_index].flags) &
+ KHUI_CW_COL_GROUP)
+ tbl->flags |= KHUI_CW_TBL_COL_DIRTY;
+
+ for (i=0; i < tbl->n_cols; i++) {
+ if (tbl->cols[i].attr_id < 0)
+ continue;
+
+ if (tbl->cols[i].flags &
+ (KHUI_CW_COL_GROUP |
+ KHUI_CW_COL_SORT_INC |
+ KHUI_CW_COL_SORT_DEC))
+ tbl->cols[i].sort_index = sort_index++;
+ else
+ break;
+ }
+
+ tbl->flags |= KHUI_CW_TBL_CUSTVIEW;
+
+ cw_update_creds(tbl);
+ cw_update_outline(tbl);
+ cw_update_extents(tbl, TRUE);
+
+ InvalidateRect(tbl->hwnd, NULL, FALSE);
+
+ return FALSE;
+ }
+ break;
+
+ case HDN_ITEMCLICK:
+ {
+ int idx;
+ int hidx;
+
+ hi.mask = HDI_ORDER;
+ Header_GetItem(tbl->hwnd_header, ph->iItem, &hi);
+ idx = hi.iOrder;
+
+ if (idx < 0 || idx >= tbl->n_cols)
+ return FALSE;
+
+ if (tbl->cols[idx].flags & KHUI_CW_COL_META)
+ return FALSE;
+
+ if (tbl->cols[idx].flags &
+ (KHUI_CW_COL_SORT_INC | KHUI_CW_COL_SORT_DEC)) {
+
+ tbl->cols[idx].flags ^=
+ (KHUI_CW_COL_SORT_INC | KHUI_CW_COL_SORT_DEC);
+
+ cw_hditem_from_tbl_col(&tbl->cols[idx], &hi);
+ hi.mask = HDI_FORMAT;
+ Header_SetItem(tbl->hwnd_header, ph->iItem, &hi);
+
+ } else {
+ int i;
+ int sort_idx = 0;
+
+ for (i=0; i <= idx; i++) {
+ if (tbl->cols[i].attr_id < 0)
+ continue;
+
+ if (!(tbl->flags &
+ (KHUI_CW_COL_SORT_INC | KHUI_CW_COL_SORT_DEC))) {
+ tbl->cols[i].flags |= KHUI_CW_COL_SORT_INC;
+
+ cw_hditem_from_tbl_col(&tbl->cols[i], &hi);
+ hi.mask = HDI_FORMAT;
+ hidx = Header_OrderToIndex(tbl->hwnd_header, i);
+ Header_SetItem(tbl->hwnd_header, hidx, &hi);
+ }
+
+ tbl->cols[i].sort_index = sort_idx++;
+ }
+ }
+
+ tbl->flags |= KHUI_CW_TBL_CUSTVIEW;
+
+ cw_update_creds(tbl);
+ cw_update_outline(tbl);
+ cw_update_extents(tbl, TRUE);
+
+ InvalidateRect(tbl->hwnd, NULL, FALSE);
+
+ }
+ break;
+
+ case HDN_ITEMDBLCLICK:
+ {
+ int idx;
+ int hidx;
+
+ hi.mask = HDI_ORDER;
+ Header_GetItem(tbl->hwnd_header, ph->iItem, &hi);
+ idx = hi.iOrder;
+
+ if (idx == 0 || idx >= tbl->n_cols)
+ return FALSE;
+
+ if (tbl->cols[idx].flags & KHUI_CW_COL_GROUP) {
+ /* we are removing grouping from this level */
+
+ int i;
+
+ for (i=idx; i < tbl->n_cols; i++) {
+ if (!(tbl->cols[i].flags & KHUI_CW_COL_GROUP))
+ break;
+
+ tbl->cols[i].flags &= ~KHUI_CW_COL_GROUP;
+
+ cw_hditem_from_tbl_col(&tbl->cols[idx], &hi);
+ hi.mask = HDI_FORMAT;
+ hidx = Header_OrderToIndex(tbl->hwnd_header, i);
+ Header_SetItem(tbl->hwnd_header, hidx, &hi);
+ }
+
+#if 0
+ } else if (tbl->cols[idx].flags &
+ (KHUI_CW_COL_SORT_INC |
+ KHUI_CW_COL_SORT_DEC)) {
+ int i;
+
+ /* remove the sort condition from a column */
+
+ for (i=idx; i < tbl->n_cols; i++) {
+ if (!tbl->cols[i].flags &
+ (KHUI_CW_COL_SORT_INC |
+ KHUI_CW_COL_SORT_DEC))
+ break;
+
+ tbl->cols[i].flags &=
+ ~(KHUI_CW_COL_SORT_INC |
+ KHUI_CW_COL_SORT_DEC);
+
+ cw_hditem_from_tbl_col(&tbl->cols[idx], &hi);
+ hi.mask = HDI_FORMAT;
+ hidx = Header_OrderToIndex(tbl->hwnd_header, i);
+ Header_SetItem(tbl->hwnd_header, hidx, &hi);
+ }
+#endif
+ } else {
+ int i;
+ int sort_index = 0;
+
+ for (i=0; i <= idx; i++) {
+ if (tbl->cols[i].attr_id < 0)
+ continue;
+
+ if (!(tbl->cols[i].flags & KHUI_CW_COL_GROUP)) {
+ tbl->cols[i].flags |= KHUI_CW_COL_GROUP;
+
+ if (!(tbl->cols[i].flags &
+ (KHUI_CW_COL_SORT_INC |
+ KHUI_CW_COL_SORT_DEC)))
+ tbl->cols[i].flags |= KHUI_CW_COL_SORT_INC;
+
+ cw_hditem_from_tbl_col(&tbl->cols[i], &hi);
+ hi.mask = HDI_FORMAT;
+ hidx = Header_OrderToIndex(tbl->hwnd_header, i);
+ Header_SetItem(tbl->hwnd_header, hidx, &hi);
+ }
+
+ tbl->cols[i].sort_index = sort_index++;
+ }
+ }
+
+ tbl->flags |= KHUI_CW_TBL_COL_DIRTY;
+ tbl->flags |= KHUI_CW_TBL_CUSTVIEW;
+
+ cw_update_creds(tbl);
+ cw_update_outline(tbl);
+ cw_update_extents(tbl, TRUE);
+
+ InvalidateRect(tbl->hwnd, NULL, FALSE);
+ }
+ break;
+
+ case NM_CUSTOMDRAW:
+ {
+ LPNMCUSTOMDRAW cd;
+ int idx;
+
+ cd = (LPNMCUSTOMDRAW) ph;
+ switch(cd->dwDrawStage) {
+ case CDDS_PREPAINT:
+ return CDRF_NOTIFYITEMDRAW;
+
+ case CDDS_ITEMPREPAINT:
+ return CDRF_NOTIFYPOSTPAINT;
+
+ case CDDS_ITEMPOSTPAINT:
+ if(cd->lItemlParam == CW_CA_FLAGS)
+ idx = IDB_WDG_FLAG;
+ else if(cd->lItemlParam == CW_CA_TYPEICON)
+ idx = IDB_WDG_CREDTYPE;
+ else
+ idx = -1;
+
+ khui_ilist_draw_id(tbl->ilist, idx, cd->hdc, cd->rc.left, cd->rc.top, 0);
+ return 0;
+ }
+ }
+ break;
+ }
+ return 0;
+}
+
+LRESULT
+cw_wm_create(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ khui_credwnd_tbl * tbl;
+
+ kmq_subscribe_hwnd(KMSG_CRED, hwnd);
+ kmq_subscribe_hwnd(KMSG_KCDB, hwnd);
+ kmq_subscribe_hwnd(KMSG_KMM, hwnd);
+
+ /* freed in cw_wm_destroy */
+ tbl = PMALLOC(sizeof(*tbl));
+ ZeroMemory(tbl, sizeof(*tbl));
+
+ /* some versions of VC generate portability warnings for
+ SetWindowLongPtr */
+#pragma warning(push)
+#pragma warning(disable: 4244)
+ SetWindowLongPtr(hwnd, 0, (LONG_PTR) tbl);
+#pragma warning(pop)
+
+ cw_refresh_attribs(hwnd);
+
+ tbl->hwnd_header = CreateWindowEx(
+ 0,
+ WC_HEADER,
+ (LPWSTR) NULL,
+ WS_CHILD | HDS_BUTTONS |
+ HDS_FULLDRAG | HDS_HORZ | HDS_HOTTRACK |
+ HDS_DRAGDROP
+#if (_WIN32_WINNT >= 0x501)
+ | ((IS_COMMCTL6())?HDS_FLAT:0)
+#endif
+ ,
+ 0,0,0,0,hwnd, (HMENU) 0, khm_hInstance, NULL);
+
+ cw_load_view(tbl, NULL /* default view */, hwnd);
+ cw_insert_header_cols(tbl);
+
+ cw_update_creds(tbl);
+ cw_update_outline(tbl);
+ cw_update_selection_state(tbl);
+ cw_update_extents(tbl, FALSE);
+
+ {
+ RECT rect;
+ WINDOWPOS pw;
+ HDLAYOUT hdl;
+
+ hdl.prc = &rect;
+ hdl.pwpos = &pw;
+ GetClientRect(hwnd, &rect);
+
+ Header_Layout(tbl->hwnd_header, &hdl);
+
+ SetWindowPos(
+ tbl->hwnd_header,
+ pw.hwndInsertAfter,
+ pw.x,
+ pw.y,
+ pw.cx,
+ pw.cy,
+ pw.flags | SWP_SHOWWINDOW);
+ }
+
+ return DefWindowProc(hwnd, uMsg, wParam, lParam);
+}
+
+LRESULT
+cw_wm_destroy(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ khui_credwnd_tbl * tbl;
+
+ kmq_unsubscribe_hwnd(KMSG_CRED, hwnd);
+ kmq_unsubscribe_hwnd(KMSG_KCDB, hwnd);
+ kmq_unsubscribe_hwnd(KMSG_KMM, hwnd);
+
+ tbl = (khui_credwnd_tbl *)(LONG_PTR) GetWindowLongPtr(hwnd, 0);
+
+ cw_save_view(tbl, NULL);
+
+ cw_unload_view(tbl);
+
+ PFREE(tbl);
+ return DefWindowProc(hwnd, uMsg, wParam, lParam);
+}
+
+/* handles WM_PAINT and WM_PRINTCLIENT */
+LRESULT
+cw_wm_paint(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ khui_credwnd_tbl * tbl;
+ HDC hdc;
+ PAINTSTRUCT ps;
+ RECT r,rh;
+ HFONT hf_old = NULL;
+ int row_s, row_e;
+ int col_s, col_e;
+ int i,j,x,y,xs,xe,ys,ye;
+ int flag_col = -1;
+ int d_x = -1;
+ int selected = 0;
+ int rowheight = 0;
+ BOOL has_dc = FALSE;
+
+ tbl = (khui_credwnd_tbl *)(LONG_PTR) GetWindowLongPtr(hwnd, 0);
+
+ if (wParam != 0) {
+ /* we assume that if wParam != 0, then that contains a device
+ context for us to draw in. Otherwise, we have to call
+ BeginPaint() to get one. */
+ hdc = (HDC) wParam;
+ has_dc = TRUE;
+ }
+
+ if(!has_dc && !GetUpdateRect(hwnd, &r, FALSE)) {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ goto _exit;
+ }
+
+ if (!has_dc)
+ hdc = BeginPaint(hwnd, &ps);
+
+ if(tbl->hf_normal)
+ hf_old = SelectFont(hdc, tbl->hf_normal);
+ SetTextAlign(hdc, TA_LEFT | TA_TOP | TA_NOUPDATECP);
+ SetBkMode(hdc, TRANSPARENT);
+
+ GetClientRect(hwnd,&r);
+ r.top += tbl->header_height;
+
+ if(tbl->n_rows) {
+ /* remove the notification window if there is one */
+ if(tbl->hwnd_notif) {
+ DestroyWindow(tbl->hwnd_notif);
+ tbl->hwnd_notif = NULL;
+ }
+ /* we compute the visible area in terms of rows and columns */
+ /* row_s : first visible row */
+ /* col_s : first visible column */
+ /* row_e : last visible row */
+ /* col_e : last visible column */
+ /* ys : top edge of first visible row */
+ /* xs : left edge of first visible column */
+
+ /* We *NEED* all the meta columns to be on the left */
+
+ row_s = 0;
+ ys = 0;
+ row_e = (int) tbl->n_rows;
+ x = 0;
+ col_s = -1;
+ col_e = -1;
+ xs = 0;
+ for(i=0; i < (int) tbl->n_cols; i++) {
+ if(col_e == -1 && x >= tbl->scr_left + (r.right - r.left)) {
+ col_e = i;
+ }
+ if(tbl->cols[i].attr_id == CW_CA_FLAGS)
+ flag_col = i;
+ if(d_x == -1 && !cw_is_custom_attr(tbl->cols[i].attr_id))
+ d_x = x;
+ x += tbl->cols[i].width;
+ if(col_s == -1 && x > tbl->scr_left) {
+ col_s = i;
+ xs = tbl->cols[i].x;
+ }
+ }
+
+ if(col_e == -1)
+ col_e = i;
+
+ if(col_s == -1)
+ col_s = i;
+
+ if(d_x != -1)
+ d_x += r.left - tbl->scr_left;
+
+ xs += r.left - tbl->scr_left;
+ ys += r.top - tbl->scr_top;
+ xe = r.left + tbl->ext_width - tbl->scr_left;
+ ye = r.top + tbl->ext_height - tbl->scr_top;
+
+ /* now draw */
+ y = ys;
+ for(i=row_s; i < row_e; i++) {
+ selected = tbl->rows[i].flags & KHUI_CW_ROW_SELECTED;
+ rowheight = (tbl->rows[i].flags & KHUI_CW_ROW_EXPVIEW)? tbl->cell_height * CW_EXP_ROW_MULT : tbl->cell_height;
+
+ if(tbl->cursor_row == i) {
+ if (tbl->rows[i].flags & KHUI_CW_ROW_HEADER)
+ SelectFont(hdc, tbl->hf_bold_header);
+ else
+ SelectFont(hdc, tbl->hf_bold);
+ } else if (tbl->rows[i].flags & KHUI_CW_ROW_HEADER) {
+ SelectFont(hdc, tbl->hf_header);
+ }
+
+ x = xs;
+ if(tbl->rows[i].flags & KHUI_CW_ROW_HEADER) {
+ rh.left = xs;
+ rh.right = xs;
+ for(j=col_s; j < tbl->rows[i].col; j++)
+ rh.right += tbl->cols[j].width;
+ rh.top = y;
+ rh.bottom = y + rowheight;
+ if(rh.right > rh.left) {
+ cw_erase_rect(hdc, tbl, &r, &rh, (selected)?CW_ER_SEL:CW_ER_BLANK);
+ }
+ rh.left = rh.right;
+ rh.right = xe;
+
+ cw_draw_header(hdc, tbl, i, &rh);
+ }
+
+ if(selected)
+ SetTextColor(hdc, tbl->cr_s);
+ else
+ SetTextColor(hdc, tbl->cr_normal);
+
+ x = xs;
+ rh.top = y;
+ rh.bottom = y + rowheight;
+ for(j=col_s; j < col_e; x += tbl->cols[j++].width) {
+ wchar_t buf[256];
+ khm_size cbbuf;
+
+ rh.left = x;
+ rh.right = x + tbl->cols[j].width;
+
+ if(!cw_is_custom_attr(tbl->cols[j].attr_id)) {
+ if(!(tbl->rows[i].flags & KHUI_CW_ROW_HEADER)) {
+ cw_erase_rect(hdc, tbl, &r, &rh, (selected)?CW_ER_SEL:CW_ER_BLANK);
+
+ if(j > tbl->rows[i].col) {
+ cbbuf = sizeof(buf);
+ if(KHM_FAILED(kcdb_cred_get_attr_string((khm_handle) tbl->rows[i].data,
+ tbl->cols[j].attr_id, buf,
+ &cbbuf, KCDB_TS_SHORT)))
+ continue;
+
+ rh.left += tbl->hpad;
+ rh.right -= tbl->hpad;
+
+ SetTextAlign(hdc, 0);
+ DrawText(hdc, buf, (int)((cbbuf / sizeof(wchar_t)) - 1), &rh,
+ DT_LEFT | DT_VCENTER | DT_NOCLIP | DT_SINGLELINE | DT_END_ELLIPSIS);
+ }
+ }
+ } else {
+ cw_erase_rect(hdc, tbl, &r, &rh, (selected)?CW_ER_SEL:CW_ER_BLANK);
+
+ if(tbl->cols[j].attr_id == CW_CA_FLAGS) {
+ khui_credwnd_outline * o;
+ khm_int32 flag;
+
+ if(tbl->rows[i].flags & KHUI_CW_ROW_HEADER) {
+ o = ((khui_credwnd_outline *) tbl->rows[i].data);
+ if(o->flags & KHUI_CW_O_SHOWFLAG)
+ flag = o->flags;
+ else
+ flag = 0;
+ } else {
+ flag = tbl->rows[i].flags;
+ }
+
+ flag &= CW_EXPSTATE_MASK;
+
+ if(flag == CW_EXPSTATE_WARN) {
+ khui_ilist_draw_id(tbl->ilist, IDB_FLAG_WARN, hdc, x, y, 0);
+ } else if(flag == CW_EXPSTATE_CRITICAL) {
+ khui_ilist_draw_id(tbl->ilist, IDB_FLAG_CRITICAL, hdc, x, y, 0);
+ } else if(flag == CW_EXPSTATE_EXPIRED) {
+ khui_ilist_draw_id(tbl->ilist, IDB_FLAG_EXPIRED, hdc, x, y, 0);
+ } else if(!(tbl->rows[i].flags & KHUI_CW_ROW_HEADER)) {
+ khm_int32 flags;
+
+ if (KHM_SUCCEEDED(kcdb_cred_get_flags((khm_handle) tbl->rows[i].data, &flags)) &&
+ (flags & KCDB_CRED_FLAG_RENEWABLE)) {
+ khui_ilist_draw_id(tbl->ilist,
+ IDB_FLAG_RENEW,
+ hdc,
+ x, y, 0);
+ } else {
+ khui_ilist_draw_id(tbl->ilist,
+ IDB_TK_SM,
+ hdc,
+ x, y, 0);
+ }
+ }
+ }
+ }
+ }
+
+ if(tbl->cursor_row == i) {
+ rh.left = tbl->scr_left;
+ rh.right = tbl->scr_left + tbl->ext_width;
+ DrawFocusRect(hdc, &rh);
+ }
+
+ if (tbl->cursor_row == i ||
+ (tbl->rows[i].flags & KHUI_CW_ROW_HEADER)) {
+ SelectFont(hdc, tbl->hf_normal);
+ }
+
+ y += rowheight;
+
+ }
+
+ if(xe < r.right) {
+ rh.left = xe;
+ rh.right = r.right;
+ rh.top = r.top;
+ rh.bottom = r.bottom;
+
+ cw_erase_rect(hdc, tbl, &r, &rh, CW_ER_BLANK);
+ }
+
+ if(ye < r.bottom) {
+ rh.left = r.left;
+ rh.right = (xe < r.right)?xe:r.right;
+ rh.top = ye;
+ rh.bottom = r.bottom;
+
+ cw_erase_rect(hdc, tbl, &r, &rh, CW_ER_BLANK);
+ }
+
+ } else {
+ wchar_t buf[512];
+ cw_erase_rect(hdc, tbl, &r, &r, CW_ER_BLANK);
+
+ if(tbl->hwnd_notif == NULL) {
+ LoadString(khm_hInstance, IDS_NO_CREDS, buf, sizeof(buf)/sizeof(buf[0]));
+ tbl->hwnd_notif = khm_create_htwnd(
+ tbl->hwnd,
+ buf,
+ r.left,r.top,r.right - r.left,tbl->cell_height * 4,
+ 0, /* This can be WS_EX_TRANSPARENT, but
+ we don't fully support it yet. */
+ WS_VISIBLE);
+ if(tbl->hwnd_notif) {
+ SendMessage(tbl->hwnd_notif, WM_SETFONT, (WPARAM) tbl->hf_normal, (LPARAM) FALSE);
+ ShowWindow(tbl->hwnd_notif, SW_SHOW);
+ }
+ }
+ }
+
+ if(tbl->hf_normal)
+ SelectFont(hdc, hf_old);
+
+ if (!has_dc)
+ EndPaint(hwnd,&ps);
+
+ _exit:
+ return TRUE;
+}
+
+LRESULT
+cw_wm_size(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ RECT rect;
+ khui_credwnd_tbl * tbl;
+
+ tbl = (khui_credwnd_tbl *)(LONG_PTR) GetWindowLongPtr(hwnd, 0);
+
+ cw_update_extents(tbl, TRUE);
+
+ GetClientRect(hwnd, &rect);
+
+ if(tbl->hwnd_notif) {
+ SetWindowPos(
+ tbl->hwnd_notif,
+ tbl->hwnd_header,
+ rect.left,
+ tbl->header_height,
+ rect.right - rect.left,
+ tbl->cell_height * 4,
+ 0);
+ }
+ return DefWindowProc(hwnd, uMsg, wParam, lParam);
+}
+
+LRESULT
+cw_wm_notify(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ khui_credwnd_tbl * tbl;
+ LPNMHDR pnmh;
+ tbl = (khui_credwnd_tbl *)(LONG_PTR) GetWindowLongPtr(hwnd, 0);
+ pnmh = (LPNMHDR) lParam;
+ if(pnmh->hwndFrom == tbl->hwnd_header) {
+ LPNMHEADER ph;
+ ph = (LPNMHEADER) lParam;
+ return cw_handle_header_msg(tbl, ph);
+ }
+
+ return DefWindowProc(hwnd, uMsg, wParam, lParam);
+}
+
+static void cw_pp_begin(khui_property_sheet * s);
+static void cw_pp_precreate(khui_property_sheet * s);
+static void cw_pp_end(khui_property_sheet * s);
+static void cw_pp_destroy(khui_property_sheet *ps);
+
+LRESULT
+cw_kmq_wm_dispatch(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ kmq_message * m;
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+ khui_credwnd_tbl * tbl;
+
+ tbl = (khui_credwnd_tbl *)(LONG_PTR) GetWindowLongPtr(hwnd, 0);
+
+ kmq_wm_begin(lParam, &m);
+
+ if(m->type == KMSG_CRED) {
+ switch (m->subtype) {
+ case KMSG_CRED_ROOTDELTA:
+ cw_update_creds(tbl);
+ cw_update_outline(tbl);
+ cw_update_extents(tbl, TRUE);
+ InvalidateRect(hwnd, NULL, FALSE);
+ break;
+
+ case KMSG_CRED_PP_BEGIN:
+ cw_pp_begin((khui_property_sheet *) m->vparam);
+ break;
+
+ case KMSG_CRED_PP_PRECREATE:
+ cw_pp_precreate((khui_property_sheet *) m->vparam);
+ break;
+
+ case KMSG_CRED_PP_END:
+ cw_pp_end((khui_property_sheet *) m->vparam);
+ break;
+
+ case KMSG_CRED_PP_DESTROY:
+ cw_pp_destroy((khui_property_sheet *) m->vparam);
+ break;
+ }
+ } else if (m->type == KMSG_KCDB) {
+ if (m->subtype == KMSG_KCDB_IDENT &&
+ m->uparam == KCDB_OP_MODIFY) {
+
+ cw_update_outline(tbl);
+ cw_update_extents(tbl, TRUE);
+ InvalidateRect(hwnd, NULL, FALSE);
+
+ }
+ else if (m->subtype == KMSG_KCDB_IDENT &&
+ m->uparam == KCDB_OP_NEW_DEFAULT) {
+
+ cw_update_outline(tbl);
+ cw_update_extents(tbl, TRUE);
+ InvalidateRect(hwnd, NULL, FALSE);
+
+ }
+ else if (m->subtype == KMSG_KCDB_ATTRIB &&
+ (m->uparam == KCDB_OP_INSERT ||
+ m->uparam == KCDB_OP_DELETE)) {
+
+ cw_refresh_attribs(hwnd);
+
+ }
+ } else if (m->type == KMSG_KMM &&
+ m->subtype == KMSG_KMM_I_DONE) {
+
+ if (tbl->flags & KHUI_CW_TBL_COLSKIP) {
+ wchar_t cname[KCONF_MAXCCH_NAME];
+ khm_size cb;
+
+ cname[0] = L'\0';
+
+ if (tbl->csp_view) {
+ cb = sizeof(cname);
+ khc_get_config_space_name(tbl->csp_view,
+ cname,
+ &cb);
+ }
+
+ cw_unload_view(tbl);
+
+ cw_load_view(tbl, ((cname[0])?cname: NULL), hwnd);
+ cw_insert_header_cols(tbl);
+
+ cw_update_creds(tbl);
+ cw_update_outline(tbl);
+ cw_update_selection_state(tbl);
+ cw_update_extents(tbl, TRUE);
+
+ InvalidateRect(tbl->hwnd, NULL, TRUE);
+ }
+
+ } else if (m->type == KMSG_ACT &&
+ m->subtype == KMSG_ACT_ACTIVATE) {
+ /* a column selector menu item was activated */
+
+ khm_int32 attr_id;
+ khm_int32 action;
+ khui_action * paction;
+ int i;
+ int first_non_fixed = -1;
+
+ action = m->uparam;
+ paction = khui_find_action(action);
+
+ if (paction == NULL)
+ goto _skip_action;
+
+ attr_id = (khm_int32)(INT_PTR) paction->data;
+
+ if (attr_id < 0 || attr_id > KCDB_ATTR_MAX_ID)
+ goto _skip_action;
+
+ for (i=0; i < tbl->n_cols; i++) {
+ if (tbl->cols[i].attr_id >= 0 &&
+ first_non_fixed == -1)
+ first_non_fixed = i;
+
+ if (tbl->cols[i].attr_id == attr_id)
+ break;
+ }
+
+ if (first_non_fixed == i &&
+ i == tbl->n_cols - 1) {
+ /* this is the only non-fixed column. We don't allow
+ deleting it, althoguh there's nothing wrong with doing
+ so other than not being very useful. */
+ goto _skip_action;
+ }
+
+ if (i < tbl->n_cols) {
+ khm_int32 sort_index;
+
+ /* we need to remove a column */
+
+ Header_DeleteItem(tbl->hwnd_header, i);
+ sort_index = tbl->cols[i].sort_index;
+
+ if (tbl->cols[i].title)
+ PFREE(tbl->cols[i].title);
+ tbl->cols[i].title = NULL;
+
+ if (i < tbl->n_cols - 1) {
+ MoveMemory(&tbl->cols[i], &tbl->cols[i+1],
+ sizeof(tbl->cols[0]) * (tbl->n_cols - (i + 1)));
+ }
+ tbl->n_cols--;
+
+ /* fix the sort index */
+ if (sort_index >= 0) {
+ for (i=0; i < tbl->n_cols; i++) {
+ if (tbl->cols[i].sort_index > sort_index)
+ tbl->cols[i].sort_index--;
+ }
+ }
+
+ tbl->flags |= KHUI_CW_TBL_COL_DIRTY;
+
+ cw_update_creds(tbl);
+ cw_update_outline(tbl);
+ cw_update_extents(tbl, TRUE);
+
+ InvalidateRect(tbl->hwnd, NULL, TRUE);
+
+ khui_check_action(attr_to_action[attr_id], FALSE);
+
+ tbl->flags |= KHUI_CW_TBL_CUSTVIEW;
+
+ } else {
+ /* we need to add a column */
+ wchar_t buf[KCDB_MAXCCH_SHORT_DESC];
+ khm_size cb;
+ khm_int32 idx = tbl->n_cols;
+ HDITEM hi;
+
+ /* for now, we only allow KHUI_CW_COL_INITIAL columns */
+ if (tbl->n_rows == tbl->n_total_rows)
+ goto _skip_action;
+
+ cb = sizeof(buf);
+ if (KHM_FAILED(kcdb_attrib_describe(attr_id,
+ buf,
+ &cb,
+ KCDB_TS_SHORT)))
+ goto _skip_action;
+
+ tbl->cols[idx].attr_id = attr_id;
+ tbl->cols[idx].width = 100;
+ tbl->cols[idx].x = -1;
+ tbl->cols[idx].flags = 0;
+ tbl->cols[idx].sort_index = -1;
+ tbl->cols[idx].title = PMALLOC(cb);
+#ifdef DEBUG
+ assert(tbl->cols[idx].title);
+#endif
+ if (!tbl->cols[idx].title)
+ goto _skip_action;
+
+ StringCbCopy(tbl->cols[idx].title,
+ cb,
+ buf);
+
+ tbl->n_cols++;
+
+ cw_hditem_from_tbl_col(&(tbl->cols[idx]), &hi);
+ Header_InsertItem(tbl->hwnd_header, 512, &hi);
+
+ tbl->flags |= KHUI_CW_TBL_COL_DIRTY;
+
+ cw_update_creds(tbl);
+ cw_update_outline(tbl);
+ cw_update_extents(tbl, TRUE);
+
+ InvalidateRect(tbl->hwnd, NULL, TRUE);
+
+ khui_check_action(attr_to_action[attr_id], TRUE);
+
+ tbl->flags |= KHUI_CW_TBL_CUSTVIEW;
+ }
+
+ kmq_post_message(KMSG_ACT, KMSG_ACT_REFRESH, 0, 0);
+
+ _skip_action:
+ ;
+ }
+
+ return kmq_wm_end(m, rv);
+}
+
+static void
+cw_select_outline_level(khui_credwnd_outline * o,
+ BOOL select)
+{
+ while(o) {
+ if (select)
+ o->flags |= KHUI_CW_O_SELECTED;
+ else
+ o->flags &= ~KHUI_CW_O_SELECTED;
+ cw_select_outline_level(TFIRSTCHILD(o), select);
+ o = LNEXT(o);
+ }
+}
+
+static void
+cw_select_outline(khui_credwnd_outline * o,
+ BOOL select)
+{
+ if (select)
+ o->flags |= KHUI_CW_O_SELECTED;
+ else
+ o->flags &= ~KHUI_CW_O_SELECTED;
+}
+
+static void
+cw_select_row_creds(khui_credwnd_tbl * tbl, int row, int selected) {
+
+ khm_size j;
+ khm_size idx_start, idx_end;
+
+#ifdef DEBUG
+ assert(row >= 0 && row < tbl->n_rows);
+#endif
+
+ if (row >= tbl->n_rows)
+ return;
+
+ if (tbl->rows[row].flags & KHUI_CW_ROW_HEADER) {
+ khui_credwnd_outline * o;
+
+ o = (khui_credwnd_outline *) tbl->rows[row].data;
+ if (o->col == tbl->n_cols - 1) {
+ /* this is a special case where the outline column is the
+ last displayed column. In this case, the credentials
+ do not occupy any rows, and this header row acts as a
+ group credential row. */
+ idx_start = o->idx_start;
+ idx_end = o->idx_end;
+ } else {
+ return;
+ }
+ } else {
+ idx_start = tbl->rows[row].idx_start;
+ idx_end = tbl->rows[row].idx_end;
+ }
+
+ if (idx_start == -1 || idx_end == -1)
+ return;
+
+ for (j = idx_start; j <= idx_end; j++) {
+ khm_handle cred = NULL;
+
+ kcdb_credset_get_cred(tbl->credset, (khm_int32) j, &cred);
+
+ if (cred) {
+ kcdb_cred_set_flags(cred, ((selected)?KCDB_CRED_FLAG_SELECTED:0),
+ KCDB_CRED_FLAG_SELECTED);
+ kcdb_cred_release(cred);
+ }
+ }
+}
+
+static void
+cw_unselect_all(khui_credwnd_tbl * tbl)
+{
+ int i;
+
+ for(i=0; i<tbl->n_rows; i++) {
+ tbl->rows[i].flags &= ~KHUI_CW_ROW_SELECTED;
+
+ cw_select_row_creds(tbl, i, FALSE);
+ }
+
+ cw_select_outline_level(tbl->outline, FALSE);
+}
+
+static void
+cw_update_outline_selection_state(khui_credwnd_tbl * tbl,
+ khui_credwnd_outline * o)
+{
+ BOOL select = TRUE;
+ int j;
+
+ for (j = o->start + 1; j < o->start + o->length; j++) {
+ if (tbl->rows[j].flags & KHUI_CW_ROW_HEADER) {
+ cw_update_outline_selection_state(tbl,
+ (khui_credwnd_outline *)
+ tbl->rows[j].data);
+ }
+
+ if (!(tbl->rows[j].flags & KHUI_CW_ROW_SELECTED)) {
+ select = FALSE;
+ }
+
+ if (tbl->rows[j].flags & KHUI_CW_ROW_HEADER) {
+ j += ((khui_credwnd_outline *) tbl->rows[j].data)->length - 1;
+ }
+ }
+
+ /* special case : the header has been collapsed and we are just
+ using one row. In this case, the for loop above will do
+ nothing. */
+
+ if (o->length == 1) {
+ select = (tbl->rows[o->start].flags & KHUI_CW_ROW_SELECTED);
+ }
+
+ cw_select_outline(o, select);
+
+ if (select) {
+ tbl->rows[o->start].flags |= KHUI_CW_ROW_SELECTED;
+ } else {
+ tbl->rows[o->start].flags &= ~KHUI_CW_ROW_SELECTED;
+ }
+}
+
+static void
+cw_update_selection_state(khui_credwnd_tbl * tbl)
+{
+ int i;
+
+ cw_select_outline_level(tbl->outline, FALSE);
+
+ for (i=0; i < tbl->n_rows; i++) {
+ if (tbl->rows[i].flags & KHUI_CW_ROW_HEADER) {
+ khui_credwnd_outline * o;
+
+ o = (khui_credwnd_outline *) tbl->rows[i].data;
+
+ cw_update_outline_selection_state(tbl, o);
+
+ i += o->length - 1;
+ }
+ }
+}
+
+/* Examine the current row and set the UI context */
+static void
+cw_set_row_context(khui_credwnd_tbl * tbl, int row)
+{
+ khui_credwnd_outline * o;
+ BOOL set_context = TRUE;
+
+ if (row < 0 || row >= (int) tbl->n_rows) {
+ if (tbl->n_rows > 0)
+ row = 0;
+ else {
+ khui_context_reset();
+ return;
+ }
+ }
+
+ if (tbl->rows[row].flags & KHUI_CW_ROW_HEADER) {
+
+ o = (khui_credwnd_outline *) tbl->rows[row].data;
+
+ if (tbl->cols[o->col].attr_id == KCDB_ATTR_ID_NAME) {
+ if (TPARENT(o) != NULL) {
+ khui_credwnd_outline * op;
+
+ op = TPARENT(o);
+
+ if (tbl->cols[op->col].attr_id == KCDB_ATTR_TYPE_NAME &&
+ TPARENT(op) == NULL) {
+ /* selected a credential type */
+ khui_context_set(KHUI_SCOPE_CREDTYPE,
+ (khm_handle) o->data,
+ (khm_int32) (DWORD_PTR) op->data,
+ NULL,
+ NULL,
+ 0,
+ tbl->credset);
+ } else {
+ /* we can't narrow it down using the standard set
+ of scopes. We consider this to be an identity
+ selection because the user right-clicked on an
+ identity header. */
+ khui_context_set(KHUI_SCOPE_IDENT,
+ (khm_handle) o->data,
+ KCDB_CREDTYPE_INVALID,
+ NULL,
+ NULL,
+ 0,
+ tbl->credset);
+ }
+ } else {
+ /* The user clicked on an identity header. Even
+ though not all credentials belonging to the
+ identity maybe within the scope right now, we still
+ consider this to be an identity scope. */
+ khui_context_set(KHUI_SCOPE_IDENT,
+ (khm_handle) o->data,
+ KCDB_CREDTYPE_INVALID,
+ NULL,
+ NULL,
+ 0,
+ tbl->credset);
+ }
+ } else if (tbl->cols[o->col].attr_id == KCDB_ATTR_TYPE_NAME) {
+ if (TPARENT(o) == NULL) {
+ /* selected an entire cred type */
+ khui_context_set(KHUI_SCOPE_CREDTYPE,
+ NULL,
+ (khm_int32) (DWORD_PTR) o->data,
+ NULL,
+ NULL,
+ 0,
+ tbl->credset);
+ } else {
+ khui_credwnd_outline * op;
+
+ op = TPARENT(o);
+ if (tbl->cols[op->col].attr_id == KCDB_ATTR_ID_NAME) {
+ /* credtype under an identity. Even though not
+ all the credentials of this credtype belonging
+ to this identity might be within the scope, we
+ still consider this to be a type selection
+ under a specific identity. */
+ khui_context_set(KHUI_SCOPE_CREDTYPE,
+ (khm_handle) op->data,
+ (khm_int32) (DWORD_PTR) o->data,
+ NULL,
+ NULL,
+ 0,
+ tbl->credset);
+ } else {
+ set_context = FALSE;
+ }
+ }
+ } else {
+ set_context = FALSE;
+ }
+
+ if (!set_context) {
+ /* woohoo. cred group. yay. */
+ khui_header headers[KHUI_MAX_HEADERS];
+ khm_size n_headers = 0;
+
+ do {
+ headers[n_headers].attr_id =
+ o->attr_id;
+ if (tbl->cols[o->col].attr_id ==
+ KCDB_ATTR_ID_NAME) {
+ headers[n_headers].data = &(o->data);
+ headers[n_headers].cb_data = sizeof(khm_handle);
+ } else if (tbl->cols[o->col].attr_id ==
+ KCDB_ATTR_TYPE_NAME) {
+ headers[n_headers].data = &(o->data);
+ headers[n_headers].cb_data = sizeof(khm_int32);
+ } else {
+ headers[n_headers].data = o->data;
+ headers[n_headers].cb_data = o->cb_data;
+ }
+
+ n_headers++;
+
+ o = TPARENT(o);
+ } while(o);
+
+ khui_context_set(KHUI_SCOPE_GROUP,
+ NULL,
+ KCDB_CREDTYPE_INVALID,
+ NULL,
+ headers,
+ n_headers,
+ tbl->credset);
+ }
+
+ } else {
+ khm_handle cred;
+
+ cred = (khm_handle) tbl->rows[row].data;
+
+ khui_context_set(KHUI_SCOPE_CRED,
+ NULL,
+ KCDB_CREDTYPE_INVALID,
+ cred,
+ NULL,
+ 0,
+ tbl->credset);
+ }
+}
+
+static void
+cw_select_all(khui_credwnd_tbl * tbl)
+{
+ int i;
+
+ for(i=0; i<tbl->n_rows; i++) {
+ tbl->rows[i].flags |= KHUI_CW_ROW_SELECTED;
+ cw_select_row_creds(tbl, i, TRUE);
+ }
+
+ cw_select_outline_level(tbl->outline, TRUE);
+
+ cw_update_selection_state(tbl);
+
+ cw_set_row_context(tbl, tbl->cursor_row);
+
+ InvalidateRect(tbl->hwnd, NULL, FALSE);
+}
+
+static void
+cw_select_row(khui_credwnd_tbl * tbl, int row, WPARAM wParam)
+{
+ int i;
+ BOOL toggle;
+ BOOL extend;
+ int group_begin;
+ int group_end;
+
+ if (wParam & MK_CONTROL) {
+ toggle = TRUE;
+ extend = FALSE;
+ } else if (wParam & MK_SHIFT) {
+ toggle = FALSE;
+ extend = TRUE;
+ } else {
+ toggle = FALSE;
+ extend = FALSE;
+ }
+
+ if (row < 0 || row >= (int) tbl->n_rows)
+ return;
+
+ if (tbl->rows[row].flags & KHUI_CW_ROW_HEADER) {
+ khui_credwnd_outline * o;
+
+ o = (khui_credwnd_outline *) tbl->rows[row].data;
+
+ group_begin = o->start;
+ group_end = o->start + o->length - 1;
+ } else {
+ group_begin = row;
+ group_end = row;
+ }
+
+ if (!toggle && !extend) {
+ /* selecting a single row */
+ cw_unselect_all(tbl);
+
+ tbl->cursor_row = row;
+ tbl->anchor_row = row;
+
+ for (i = group_begin; i <= group_end; i++) {
+ tbl->rows[i].flags |= KHUI_CW_ROW_SELECTED;
+ cw_select_row_creds(tbl, i, TRUE);
+ }
+ } else if (toggle) {
+ BOOL select;
+
+ tbl->cursor_row = row;
+ tbl->anchor_row = row;
+
+ select = !(tbl->rows[row].flags & KHUI_CW_ROW_SELECTED);
+
+ for (i = group_begin; i <= group_end; i++) {
+ if (select)
+ tbl->rows[i].flags |= KHUI_CW_ROW_SELECTED;
+ else
+ tbl->rows[i].flags &= ~KHUI_CW_ROW_SELECTED;
+
+ cw_select_row_creds(tbl, i, select);
+ }
+ } else if (extend) {
+ int range_begin;
+ int range_end;
+
+ cw_unselect_all(tbl);
+
+ range_begin = min(row, tbl->anchor_row);
+ range_end = max(row, tbl->anchor_row);
+
+ for (i = range_begin; i <= range_end; i++) {
+ tbl->rows[i].flags |= KHUI_CW_ROW_SELECTED;
+
+ cw_select_row_creds(tbl, i, TRUE);
+ }
+
+ tbl->cursor_row = row;
+ }
+
+ cw_update_selection_state(tbl);
+
+ cw_set_row_context(tbl, tbl->cursor_row);
+
+ InvalidateRect(tbl->hwnd, NULL, FALSE);
+}
+
+static void
+cw_toggle_outline_state(khui_credwnd_tbl * tbl,
+ khui_credwnd_outline * o) {
+
+ int old_range_begin;
+ int old_range_end;
+ int new_range_begin;
+ int new_range_end;
+
+ old_range_begin = o->start;
+ old_range_end = o->start + o->length - 1;
+
+ o->flags ^= KHUI_CW_O_EXPAND;
+
+ cw_update_outline(tbl);
+ cw_update_extents(tbl, TRUE);
+
+ new_range_begin = o->start;
+ new_range_end = o->start + o->length - 1;
+
+ if (tbl->cursor_row > old_range_end) {
+ tbl->cursor_row -= old_range_end - new_range_end;
+ } else if (tbl->cursor_row >= old_range_begin &&
+ tbl->cursor_row <= old_range_end) {
+ tbl->cursor_row = new_range_begin;
+ }
+
+ if (tbl->anchor_row > old_range_end) {
+ tbl->anchor_row -= old_range_end - new_range_end;
+ } else if (tbl->anchor_row >= old_range_begin &&
+ tbl->anchor_row <= old_range_end) {
+ tbl->anchor_row = new_range_begin;
+ }
+
+ InvalidateRect(tbl->hwnd, NULL, TRUE);
+
+}
+
+LRESULT cw_properties(HWND hwnd);
+
+LRESULT
+cw_wm_mouse(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ khui_credwnd_tbl * tbl;
+ int x,y;
+ RECT r;
+ int row;
+ int col;
+ int i;
+ int nm_state,nm_row,nm_col;
+
+ tbl = (khui_credwnd_tbl *)(LONG_PTR) GetWindowLongPtr(hwnd, 0);
+
+ /* we are basically trying to capture events where the mouse is
+ hovering over one of the 'hotspots'. There are two kinds of
+ hotspots one is the little widget thinggy that you click on to
+ expand or collapse an outline. The other is a text cell that
+ is partially concealed. */
+
+ x = GET_X_LPARAM(lParam);
+ y = GET_Y_LPARAM(lParam);
+ x += tbl->scr_left;
+ y += tbl->scr_top - tbl->header_height;
+
+ row = -1;
+
+ for (i=0; i < tbl->n_rows; i++) {
+ if (y >= tbl->rows[i].r_ext.top &&
+ y < tbl->rows[i].r_ext.bottom) {
+ row = i;
+ break;
+ }
+ }
+
+ col = -1;
+ nm_state = CW_MOUSE_NONE;
+ nm_row = nm_col = -1;
+
+ for(i=0; i < (int) tbl->n_cols; i++) {
+ if(x >= tbl->cols[i].x &&
+ x < tbl->cols[i].x + tbl->cols[i].width) {
+ col = i;
+ break;
+ }
+ }
+
+ if(wParam & MK_LBUTTON)
+ nm_state = CW_MOUSE_LDOWN;
+
+ if(row >= 0 && row < (int) tbl->n_rows) {
+ nm_state |= CW_MOUSE_ROW;
+ nm_row = row;
+ nm_col = col;
+ if(tbl->rows[row].flags & KHUI_CW_ROW_HEADER) {
+ khui_credwnd_outline * o;
+
+ o = (khui_credwnd_outline *) tbl->rows[row].data;
+
+ /* are we on a widget then? */
+ x -= tbl->cols[o->col].x;
+
+ if (!(o->flags & KHUI_CW_O_NOOUTLINE)) {
+ if(x >= 0 && x < KHUI_SMICON_CX) /* hit */ {
+ nm_state |= CW_MOUSE_WOUTLINE | CW_MOUSE_WIDGET;
+ } else if (tbl->cols[tbl->rows[row].col].attr_id ==
+ KCDB_ATTR_ID_NAME &&
+ col == tbl->rows[row].col &&
+ x >= KHUI_SMICON_CX * 3 / 2 &&
+ x < KHUI_SMICON_CX * 5 / 2){
+ nm_state |= CW_MOUSE_WSTICKY | CW_MOUSE_WIDGET;
+ } else if (tbl->cols[tbl->rows[row].col].attr_id ==
+ KCDB_ATTR_ID_NAME &&
+ col == tbl->rows[row].col &&
+ x >= KHUI_SMICON_CX * 3 &&
+ x < KHUI_SMICON_CX * 4) {
+ nm_state |= CW_MOUSE_WICON | CW_MOUSE_WIDGET;
+ }
+ } else if (tbl->cols[o->col].attr_id == KCDB_ATTR_ID_NAME) {
+ if (col == tbl->rows[row].col &&
+ x >= 0 &&
+ x < KHUI_SMICON_CX){
+
+ nm_state |= CW_MOUSE_WSTICKY | CW_MOUSE_WIDGET;
+
+ } else if (col == tbl->rows[row].col &&
+ x >= KHUI_SMICON_CX * 3 / 2 &&
+ x < KHUI_SMICON_CX * 5 / 2) {
+ nm_state |= CW_MOUSE_WICON | CW_MOUSE_WIDGET;
+ }
+ }
+ }
+ }
+
+ /* did the user drag the cursor off the current row? */
+ if((tbl->mouse_state & CW_MOUSE_LDOWN) &&
+ (nm_row != tbl->mouse_row)) {
+ nm_state &= ~CW_MOUSE_WMASK;
+ }
+
+ if(!(nm_state & CW_MOUSE_LDOWN) &&
+ (tbl->mouse_state & CW_MOUSE_LDOWN) &&
+ tbl->mouse_row == nm_row) {
+
+ if((nm_state & CW_MOUSE_WOUTLINE) &&
+ (tbl->mouse_state & CW_MOUSE_WOUTLINE)) {
+ /* click on an outline widget */
+ khui_credwnd_outline * o;
+
+ o = (khui_credwnd_outline *) tbl->rows[nm_row].data;
+ tbl->mouse_state = CW_MOUSE_WIDGET | CW_MOUSE_WOUTLINE;
+
+ cw_toggle_outline_state(tbl, o);
+
+ return 0;
+ } else if ((nm_state & CW_MOUSE_WSTICKY) &&
+ (tbl->mouse_state & CW_MOUSE_WSTICKY)) {
+
+ khui_credwnd_outline * o;
+ khm_handle ident;
+ khm_int32 idf = 0;
+
+ o = tbl->rows[nm_row].data;
+ ident = o->data;
+
+ kcdb_identity_get_flags(ident, &idf);
+ idf &= KCDB_IDENT_FLAG_STICKY;
+ kcdb_identity_set_flags(ident, (idf ^ KCDB_IDENT_FLAG_STICKY),
+ KCDB_IDENT_FLAG_STICKY);
+
+ tbl->mouse_state = CW_MOUSE_WIDGET | CW_MOUSE_WSTICKY;
+
+ return 0;
+ } else if ((nm_state & CW_MOUSE_WICON) &&
+ (tbl->mouse_state & CW_MOUSE_WICON)) {
+ /* click on an row icon */
+ cw_select_row(tbl, nm_row, wParam);
+ cw_properties(hwnd);
+ } else {
+ /* click on a row */
+ cw_select_row(tbl, nm_row, wParam);
+
+ if (tbl->mouse_col == nm_col &&
+ nm_col >= 0 &&
+ tbl->cols[nm_col].attr_id == CW_CA_FLAGS &&
+ !(tbl->rows[nm_row].flags & KHUI_CW_ROW_HEADER)) {
+ /* clicked on a cred icon */
+
+ cw_properties(hwnd);
+ }
+ }
+ }
+
+ /* ok, now if we are changing state, we need to invalidate a few
+ regions */
+ if (((tbl->mouse_state ^ nm_state) & (CW_MOUSE_WIDGET |
+ CW_MOUSE_WOUTLINE |
+ CW_MOUSE_WSTICKY)) ||
+ tbl->mouse_row != nm_row) {
+
+ if(tbl->mouse_state & CW_MOUSE_WOUTLINE) {
+ r.left = tbl->cols[tbl->mouse_col].x - tbl->scr_left;
+ r.top = tbl->mouse_row * tbl->cell_height +
+ tbl->header_height - tbl->scr_top;
+ r.right = r.left + KHUI_SMICON_CX;
+ r.bottom = r.top + tbl->cell_height;
+ InvalidateRect(tbl->hwnd, &r, TRUE);
+ }
+ if(tbl->mouse_state & CW_MOUSE_WSTICKY) {
+ if (tbl->flags & KHUI_CW_TBL_EXPIDENT) {
+
+ if (tbl->mouse_row >= 0 && tbl->mouse_row < tbl->n_rows) {
+ r = tbl->rows[tbl->mouse_row].r_ext;
+ OffsetRect(&r, -tbl->scr_left, tbl->header_height - tbl->scr_top);
+ r.right = r.left + KHUI_SMICON_CX;
+ InvalidateRect(tbl->hwnd, &r, TRUE);
+ }
+
+ } else {
+ r.left = KHUI_SMICON_CX * 3 / 2 +
+ tbl->cols[tbl->mouse_col].x - tbl->scr_left;
+ r.top = tbl->mouse_row * tbl->cell_height +
+ tbl->header_height - tbl->scr_top;
+ r.right = r.left + KHUI_SMICON_CX;
+ r.bottom = r.top + tbl->cell_height;
+ }
+ InvalidateRect(tbl->hwnd, &r, TRUE);
+ }
+
+ if ((tbl->mouse_state & nm_state) & CW_MOUSE_LDOWN) {
+ if (tbl->mouse_row == nm_row)
+ tbl->mouse_col = nm_col;
+ } else {
+ tbl->mouse_col = nm_col;
+ tbl->mouse_row = nm_row;
+ }
+ tbl->mouse_state = nm_state;
+
+ /* same code block as above */
+ if(tbl->mouse_state & CW_MOUSE_WOUTLINE) {
+ r.left = tbl->cols[tbl->mouse_col].x - tbl->scr_left;
+ r.top = tbl->mouse_row * tbl->cell_height +
+ tbl->header_height - tbl->scr_top;
+ r.right = r.left + KHUI_SMICON_CX;
+ r.bottom = r.top + tbl->cell_height;
+ InvalidateRect(tbl->hwnd, &r, TRUE);
+ }
+ if(tbl->mouse_state & CW_MOUSE_WSTICKY) {
+ if (tbl->flags & KHUI_CW_TBL_EXPIDENT) {
+
+ if (tbl->mouse_row >= 0 && tbl->mouse_row < tbl->n_rows) {
+ r = tbl->rows[tbl->mouse_row].r_ext;
+ OffsetRect(&r, -tbl->scr_left, tbl->header_height - tbl->scr_top);
+ r.right = r.left + KHUI_SMICON_CX;
+ InvalidateRect(tbl->hwnd, &r, TRUE);
+ }
+
+ } else {
+ r.left = KHUI_SMICON_CX * 3 / 2 +
+ tbl->cols[tbl->mouse_col].x - tbl->scr_left;
+ r.top = tbl->mouse_row * tbl->cell_height +
+ tbl->header_height - tbl->scr_top;
+ r.right = r.left + KHUI_SMICON_CX;
+ r.bottom = r.top + tbl->cell_height;
+ }
+ InvalidateRect(tbl->hwnd, &r, TRUE);
+ }
+ } else if(tbl->mouse_state != nm_state) {
+
+ if ((tbl->mouse_state & nm_state) & CW_MOUSE_LDOWN) {
+ if (tbl->mouse_row == nm_row) {
+ tbl->mouse_col = nm_col;
+ tbl->mouse_state = nm_state;
+ }
+ } else {
+ tbl->mouse_col = nm_col;
+ tbl->mouse_row = nm_row;
+ tbl->mouse_state = nm_state;
+ }
+ }
+
+ /* if it was a double click, also show the property
+ window */
+ if (uMsg == WM_LBUTTONDBLCLK) {
+ cw_properties(hwnd);
+ }
+
+ return 0;
+}
+
+LRESULT
+cw_wm_hscroll(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ khui_credwnd_tbl * tbl;
+ SCROLLINFO si;
+ RECT cr;
+ RECT lr;
+ RECT sr;
+ int dx;
+ int newpos;
+
+ tbl = (khui_credwnd_tbl *) (LONG_PTR) GetWindowLongPtr(hwnd, 0);
+ GetClientRect(hwnd, &cr);
+ dx = tbl->scr_left;
+
+ switch(LOWORD(wParam)) {
+ case SB_LEFT:
+ newpos = 0;
+ break;
+
+ case SB_RIGHT:
+ newpos = tbl->ext_width;
+ break;
+
+ case SB_LINELEFT:
+ newpos = tbl->scr_left - (tbl->ext_width / 12);
+ break;
+
+ case SB_LINERIGHT:
+ newpos = tbl->scr_left + (tbl->ext_width / 12);
+ break;
+
+ case SB_PAGELEFT:
+ newpos = tbl->scr_left - (cr.right - cr.left);
+ break;
+
+ case SB_PAGERIGHT:
+ newpos = tbl->scr_left + (cr.right - cr.left);
+ break;
+
+ case SB_THUMBTRACK:
+ case SB_THUMBPOSITION:
+ ZeroMemory(&si, sizeof(si));
+ si.cbSize = sizeof(si);
+ si.fMask = SIF_TRACKPOS;
+ GetScrollInfo(hwnd, SB_HORZ, &si);
+
+ newpos = si.nTrackPos;
+ break;
+
+ default:
+ return DefWindowProc(hwnd, uMsg, wParam, lParam);
+ }
+
+ //cr.top += tbl->header_height;
+ tbl->scr_left = newpos;
+ cw_update_extents(tbl, TRUE);
+
+ dx -= tbl->scr_left;
+
+ /* exclude the watermark */
+ lr.bottom = cr.bottom;
+ lr.right = cr.right;
+ lr.top = max(cr.bottom - tbl->kbm_logo_shade.cy, cr.top);
+ lr.left = max(cr.right - tbl->kbm_logo_shade.cx, cr.left);
+
+ if(cr.top < lr.top && cr.left < cr.right) {
+ sr.left = cr.left;
+ sr.right = cr.right;
+ sr.top = cr.top;
+ sr.bottom = lr.top;
+ ScrollWindowEx(
+ hwnd,
+ dx,
+ 0,
+ &sr,
+ &sr,
+ NULL,
+ NULL,
+ SW_INVALIDATE | SW_SCROLLCHILDREN);
+ }
+
+ if(cr.left < lr.left && lr.top < lr.bottom) {
+ sr.left = cr.left;
+ sr.right = lr.left;
+ sr.top = lr.top;
+ sr.bottom = lr.bottom;
+ ScrollWindowEx(
+ hwnd,
+ dx,
+ 0,
+ &sr,
+ &sr,
+ NULL,
+ NULL,
+ SW_INVALIDATE | SW_SCROLLCHILDREN);
+ }
+
+ if(lr.top < lr.bottom && lr.left < lr.right) {
+ InvalidateRect(hwnd, &lr, FALSE);
+ }
+
+ return DefWindowProc(hwnd, uMsg, wParam, lParam);
+}
+
+static void
+cw_vscroll_to_pos(HWND hwnd, khui_credwnd_tbl * tbl, int newpos) {
+ RECT cr;
+ RECT sr;
+ RECT lr;
+ int dy;
+
+ GetClientRect(hwnd, &cr);
+ cr.top += tbl->header_height;
+ dy = tbl->scr_top;
+
+ tbl->scr_top = newpos;
+ cw_update_extents(tbl, TRUE);
+
+ dy -= tbl->scr_top;
+
+ /* exclude watermark */
+ lr.bottom = cr.bottom;
+ lr.right = cr.right;
+ lr.top = max(cr.bottom - tbl->kbm_logo_shade.cy, cr.top);
+ lr.left = max(cr.right - tbl->kbm_logo_shade.cx, cr.left);
+
+ if(cr.left < lr.left && cr.top < cr.bottom) {
+ sr.left = cr.left;
+ sr.right = lr.left;
+ sr.top = cr.top;
+ sr.bottom = cr.bottom;
+ ScrollWindowEx(
+ hwnd,
+ 0,
+ dy,
+ &sr,
+ &sr,
+ NULL,
+ NULL,
+ SW_INVALIDATE);
+ }
+
+ if(lr.left < lr.right && cr.top < lr.top) {
+ sr.left = lr.left;
+ sr.right = lr.right;
+ sr.top = cr.top;
+ sr.bottom = lr.top;
+ ScrollWindowEx(
+ hwnd,
+ 0,
+ dy,
+ &sr,
+ &sr,
+ NULL,
+ NULL,
+ SW_INVALIDATE);
+ }
+
+ if(lr.top < lr.bottom && lr.left < lr.right) {
+ InvalidateRect(hwnd, &lr, FALSE);
+ }
+}
+
+LRESULT
+cw_wm_vscroll(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ khui_credwnd_tbl * tbl;
+ SCROLLINFO si;
+ int newpos;
+ RECT cr;
+
+ tbl = (khui_credwnd_tbl *)(LONG_PTR) GetWindowLongPtr(hwnd, 0);
+
+ GetClientRect(hwnd, &cr);
+ cr.top += tbl->header_height;
+
+ switch(LOWORD(wParam)) {
+ case SB_LEFT:
+ newpos = 0;
+ break;
+
+ case SB_BOTTOM:
+ newpos = tbl->ext_height;
+ break;
+
+ case SB_LINEUP:
+ newpos = tbl->scr_top - (tbl->ext_height / 12);
+ break;
+
+ case SB_LINEDOWN:
+ newpos = tbl->scr_top + (tbl->ext_height / 12);
+ break;
+
+ case SB_PAGEUP:
+ newpos = tbl->scr_top - (cr.bottom - cr.top);
+ break;
+
+ case SB_PAGEDOWN:
+ newpos = tbl->scr_top + (cr.bottom - cr.top);
+ break;
+
+ case SB_THUMBTRACK:
+ case SB_THUMBPOSITION:
+ ZeroMemory(&si, sizeof(si));
+ si.cbSize = sizeof(si);
+ si.fMask = SIF_TRACKPOS;
+ GetScrollInfo(hwnd, SB_VERT, &si);
+
+ newpos = si.nTrackPos;
+ break;
+
+ default:
+ return DefWindowProc(hwnd, uMsg, wParam, lParam);
+ }
+
+ cw_vscroll_to_pos(hwnd, tbl, newpos);
+
+ return DefWindowProc(hwnd, uMsg, wParam, lParam);
+}
+
+static void
+cw_ensure_row_visible(HWND hwnd, khui_credwnd_tbl * tbl, int row) {
+ RECT r;
+ int newpos;
+
+ if (row < 0)
+ row = 0;
+ else if (row >= (int) tbl->n_rows)
+ row = (int) tbl->n_rows - 1;
+
+ GetClientRect(hwnd, &r);
+ r.top += tbl->header_height;
+
+ if (row * tbl->cell_height < tbl->scr_top) {
+ newpos = row * tbl->cell_height;
+ } else if ((row + 1) * tbl->cell_height
+ > tbl->scr_top + (r.bottom - r.top)) {
+ newpos = ((row + 1) * tbl->cell_height) - (r.bottom - r.top);
+ } else
+ return;
+
+ cw_vscroll_to_pos(hwnd, tbl, newpos);
+}
+
+static INT_PTR CALLBACK
+cw_pp_ident_proc(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ khui_property_sheet * s;
+
+ switch(uMsg) {
+ case WM_INITDIALOG:
+ {
+ PROPSHEETPAGE * p;
+ khm_handle ident;
+ wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
+ khm_size t;
+ khm_int32 i;
+
+ p = (PROPSHEETPAGE *) lParam;
+ s = (khui_property_sheet *) p->lParam;
+
+#pragma warning(push)
+#pragma warning(disable: 4244)
+ SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) s);
+#pragma warning(pop)
+
+ ident = s->identity;
+
+ t = sizeof(idname);
+ kcdb_identity_get_name(ident, idname, &t);
+ SetDlgItemText(hwnd, IDC_PP_IDNAME, idname);
+
+ kcdb_identity_get_flags(ident, &i);
+
+ CheckDlgButton(hwnd, IDC_PP_IDDEF,
+ ((i & KCDB_IDENT_FLAG_DEFAULT)?BST_CHECKED:
+ BST_UNCHECKED));
+
+ /* if it's default, you can't change it further */
+ if (i & KCDB_IDENT_FLAG_DEFAULT) {
+ EnableWindow(GetDlgItem(hwnd, IDC_PP_IDDEF), FALSE);
+ }
+
+ CheckDlgButton(hwnd, IDC_PP_IDSEARCH,
+ ((i & KCDB_IDENT_FLAG_SEARCHABLE)?BST_CHECKED:
+ BST_UNCHECKED));
+
+ CheckDlgButton(hwnd, IDC_PP_STICKY,
+ ((i & KCDB_IDENT_FLAG_STICKY)?BST_CHECKED:
+ BST_UNCHECKED));
+
+ khui_property_wnd_set_record(GetDlgItem(hwnd, IDC_PP_PROPLIST),
+ ident);
+ }
+ return TRUE;
+
+ case WM_COMMAND:
+ s = (khui_property_sheet *) (LONG_PTR)
+ GetWindowLongPtr(hwnd, DWLP_USER);
+
+ switch(wParam) {
+ case MAKEWPARAM(IDC_PP_IDDEF, BN_CLICKED):
+ /* fallthrough */
+ case MAKEWPARAM(IDC_PP_STICKY, BN_CLICKED):
+
+ if (s->status != KHUI_PS_STATUS_NONE)
+ PropSheet_Changed(s->hwnd, hwnd);
+ return TRUE;
+
+ case MAKEWPARAM(IDC_PP_CONFIG, BN_CLICKED):
+ {
+ khui_config_node cfg_id = NULL;
+ khui_config_node cfg_ids = NULL;
+ wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
+ khm_size cb;
+ khm_int32 rv;
+
+ khm_refresh_config();
+
+ rv = khui_cfg_open(NULL,
+ L"KhmIdentities",
+ &cfg_ids);
+
+ if (KHM_FAILED(rv))
+ return TRUE;
+
+ cb = sizeof(idname);
+ if (KHM_SUCCEEDED(kcdb_identity_get_name(s->identity,
+ idname,
+ &cb))) {
+ rv = khui_cfg_open(cfg_ids,
+ idname,
+ &cfg_id);
+ }
+
+ if (cfg_id)
+ khm_show_config_pane(cfg_id);
+ else
+ khm_show_config_pane(cfg_ids);
+
+ if (cfg_ids)
+ khui_cfg_release(cfg_ids);
+ if (cfg_id)
+ khui_cfg_release(cfg_id);
+ }
+ return TRUE;
+ }
+ return FALSE;
+
+ case WM_NOTIFY:
+ {
+ LPPSHNOTIFY lpp;
+ khm_int32 flags;
+
+ lpp = (LPPSHNOTIFY) lParam;
+ s = (khui_property_sheet *) (LONG_PTR)
+ GetWindowLongPtr(hwnd, DWLP_USER);
+
+ switch(lpp->hdr.code) {
+ case PSN_APPLY:
+ flags = 0;
+ if (IsDlgButtonChecked(hwnd, IDC_PP_STICKY) == BST_CHECKED)
+ flags |= KCDB_IDENT_FLAG_STICKY;
+ if (IsDlgButtonChecked(hwnd, IDC_PP_IDDEF) == BST_CHECKED)
+ flags |= KCDB_IDENT_FLAG_DEFAULT;
+
+ kcdb_identity_set_flags(s->identity, flags,
+ KCDB_IDENT_FLAG_STICKY |
+ KCDB_IDENT_FLAG_DEFAULT);
+ return TRUE;
+
+ case PSN_RESET:
+ kcdb_identity_get_flags(s->identity, &flags);
+
+ CheckDlgButton(hwnd,
+ IDC_PP_IDDEF,
+ ((flags & KCDB_IDENT_FLAG_DEFAULT)?BST_CHECKED:
+ BST_UNCHECKED));
+
+ /* if it's default, you can't change it further */
+ if (flags & KCDB_IDENT_FLAG_DEFAULT) {
+ EnableWindow(GetDlgItem(hwnd, IDC_PP_IDDEF), FALSE);
+ }
+
+ CheckDlgButton(hwnd, IDC_PP_IDSEARCH,
+ ((flags & KCDB_IDENT_FLAG_SEARCHABLE)?BST_CHECKED:BST_UNCHECKED));
+
+ CheckDlgButton(hwnd, IDC_PP_STICKY,
+ ((flags & KCDB_IDENT_FLAG_STICKY)?BST_CHECKED:BST_UNCHECKED));
+ return TRUE;
+ }
+ }
+ break;
+ }
+ return FALSE;
+}
+
+static INT_PTR CALLBACK
+cw_pp_cred_proc(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam
+ )
+{
+ switch(uMsg) {
+ case WM_INITDIALOG:
+ {
+ khui_property_sheet * s;
+ PROPSHEETPAGE * p;
+ khm_handle cred;
+
+ p = (PROPSHEETPAGE *) lParam;
+ s = (khui_property_sheet *) p->lParam;
+
+#pragma warning(push)
+#pragma warning(disable: 4244)
+ SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) s);
+#pragma warning(pop)
+
+ cred = s->cred;
+
+ khui_property_wnd_set_record(
+ GetDlgItem(hwnd, IDC_PP_CPROPLIST),
+ cred);
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static void
+cw_pp_begin(khui_property_sheet * s)
+{
+ PROPSHEETPAGE *p;
+
+ if(s->identity) {
+ p = PMALLOC(sizeof(*p));
+ ZeroMemory(p, sizeof(*p));
+
+ p->dwSize = sizeof(*p);
+ p->dwFlags = 0;
+ p->hInstance = khm_hInstance;
+ p->pszTemplate = MAKEINTRESOURCE(IDD_PP_IDENT);
+ p->pfnDlgProc = cw_pp_ident_proc;
+ p->lParam = (LPARAM) s;
+
+ khui_ps_add_page(s, KHUI_PPCT_IDENTITY, 129, p, NULL);
+ }
+
+ if(s->cred) {
+ p = PMALLOC(sizeof(*p));
+ ZeroMemory(p, sizeof(*p));
+
+ p->dwSize = sizeof(*p);
+ p->dwFlags = 0;
+ p->hInstance = khm_hInstance;
+ p->pszTemplate = MAKEINTRESOURCE(IDD_PP_CRED);
+ p->pfnDlgProc = cw_pp_cred_proc;
+ p->lParam = (LPARAM) s;
+
+ khui_ps_add_page(s, KHUI_PPCT_CREDENTIAL, 128, p, NULL);
+ }
+}
+
+static void
+cw_pp_precreate(khui_property_sheet * s)
+{
+ khui_ps_show_sheet(khm_hwnd_main, s);
+
+ khm_add_property_sheet(s);
+}
+
+static void
+cw_pp_end(khui_property_sheet * s)
+{
+ khui_property_page * p = NULL;
+
+ khui_ps_find_page(s, KHUI_PPCT_IDENTITY, &p);
+ if(p) {
+ PFREE(p->p_page);
+ p->p_page = NULL;
+ }
+
+ p = NULL;
+
+ khui_ps_find_page(s, KHUI_PPCT_CREDENTIAL, &p);
+ if(p) {
+ PFREE(p->p_page);
+ p->p_page = NULL;
+ }
+}
+
+static void
+cw_pp_destroy(khui_property_sheet *ps)
+{
+ if(ps->ctx.scope == KHUI_SCOPE_CRED) {
+ if(ps->header.pszCaption)
+ PFREE((LPWSTR) ps->header.pszCaption);
+ }
+
+ khui_context_release(&ps->ctx);
+
+ khui_ps_destroy_sheet(ps);
+
+ /* this is pretty weird because ps gets freed when
+ khui_ps_destroy_sheet() is called. However, since destroying
+ ps involves sending a WM_DESTROY message to the property sheet,
+ we still need to keep it on the property sheet chain (or else
+ the messages will not be delivered). This is only safe because
+ we are not relinquishing the thread in-between destroying ps
+ and removing it from the chain. */
+
+ /* TODO: fix this */
+ khm_del_property_sheet(ps);
+}
+
+LRESULT
+cw_properties(HWND hwnd)
+{
+ /* show a property sheet of some sort */
+ khui_action_context ctx;
+ khui_property_sheet * ps;
+ khui_credwnd_tbl * tbl;
+
+ khui_context_get(&ctx);
+ tbl = (khui_credwnd_tbl *)(LONG_PTR) GetWindowLongPtr(hwnd, 0);
+
+ if(ctx.scope == KHUI_SCOPE_NONE) {
+ khui_context_release(&ctx);
+ return FALSE;
+
+ /* While it seems like a good idea, doing this is not */
+#if 0
+ /* try to establish a context based on the current cursor
+ position */
+ if(tbl->cursor_row >= 0 && tbl->cursor_row < (int) tbl->n_rows) {
+ if(tbl->rows[tbl->cursor_row].flags & KHUI_CW_ROW_HEADER) {
+ if(tbl->cols[tbl->rows[tbl->cursor_row].col].attr_id == KCDB_ATTR_ID_NAME) {
+ /* identity context */
+ ctx.ctx = KHUI_SCOPE_IDENT;
+ ctx.identity = (khm_handle)
+ ((khui_credwnd_outline *) tbl->rows[tbl->cursor_row].data)->data;
+ } else if(tbl->cols[tbl->rows[tbl->cursor_row].col].attr_id == KCDB_ATTR_TYPE_NAME) {
+ ctx.ctx = KHUI_SCOPE_CREDTYPE;
+ ctx.cred_type = (khm_int32) (DWORD_PTR)
+ ((khui_credwnd_outline *) tbl->rows[tbl->cursor_row].data)->data;
+ } else {
+ ctx.ctx = KHUI_SCOPE_GROUP;
+ //ctx.parm = (khm_lparm) tbl->rows[tbl->cursor_row].data;
+ /* TODO: Figure out method of establishing a credgroup */
+ }
+ } else {
+ /* a credential context */
+ ctx.ctx = KHUI_SCOPE_CRED;
+ ctx.cred = (khm_handle) tbl->rows[tbl->cursor_row].data;
+ }
+ }
+#endif
+ }
+
+ /* if still no context, then we can't show a property sheet */
+ if(ctx.scope == KHUI_SCOPE_NONE) {
+ khui_context_release(&ctx);
+ return FALSE;
+ }
+
+ khui_ps_create_sheet(&ps);
+
+ if(ctx.scope == KHUI_SCOPE_IDENT) {
+ khm_handle ident;
+ khm_size t;
+
+ ident = ctx.identity;
+
+ ps->header.hInstance = khm_hInstance;
+ ps->header.pszIcon = MAKEINTRESOURCE(IDI_MAIN_APP);
+
+ kcdb_identity_get_name(ident, NULL, &t);
+
+ if(t > 0) {
+ ps->header.pszCaption = PMALLOC(t);
+ kcdb_identity_get_name(ident,
+ (wchar_t *) ps->header.pszCaption, &t);
+ } else {
+ ps->header.pszCaption = NULL;
+ }
+
+ ps->ctx = ctx;
+ ps->identity = ident;
+ ps->credtype = KCDB_CREDTYPE_INVALID;
+
+ kmq_post_message(KMSG_CRED, KMSG_CRED_PP_BEGIN, 0, (void *) ps);
+
+ } else if(ctx.scope == KHUI_SCOPE_CREDTYPE) {
+ khm_size t = 0;
+ khm_int32 cred_type;
+
+ if (ctx.identity == NULL) {
+ /* currently, we can't show a property sheet at this point
+ since most credentials providers don't provide a
+ property sheet that works without an identity. */
+
+ khui_context_release(&ctx);
+ khui_ps_destroy_sheet(ps);
+ return TRUE;
+ }
+
+ cred_type = ctx.cred_type;
+
+ ps->header.hInstance = khm_hInstance;
+ ps->header.pszIcon = MAKEINTRESOURCE(IDI_MAIN_APP);
+
+ ps->ctx = ctx;
+ ps->credtype = cred_type;
+
+ if(ctx.identity) {
+ ps->identity = ctx.identity;
+ /* also, if there is an associated identity, we assume that
+ the properties are for the specified credentials type
+ specific to the identity. Hence we change the title to
+ something else */
+ kcdb_identity_get_name(ctx.identity, NULL, &t);
+ if (t > 0) {
+ ps->header.pszCaption = PMALLOC(t);
+ kcdb_identity_get_name(ctx.identity, (wchar_t *) ps->header.pszCaption, &t);
+ } else {
+ ps->header.pszCaption = NULL;
+ }
+ } else {
+ /* we don't actually reach here since we handle this case
+ above */
+ kcdb_credtype_describe(cred_type, NULL, &t, KCDB_TS_LONG);
+ if(t > 0) {
+ ps->header.pszCaption = PMALLOC(t);
+ kcdb_credtype_describe(cred_type, (wchar_t *) ps->header.pszCaption, &t, KCDB_TS_LONG);
+ } else {
+ ps->header.pszCaption = NULL;
+ }
+ }
+
+ kmq_post_message(KMSG_CRED, KMSG_CRED_PP_BEGIN, 0, (void *) ps);
+ } else if(ctx.scope == KHUI_SCOPE_CRED) {
+ khm_handle cred;
+ khm_size t;
+
+ cred = ctx.cred;
+
+ ps->header.hInstance = khm_hInstance;
+ ps->header.pszIcon = MAKEINTRESOURCE(IDI_MAIN_APP);
+ ps->ctx = ctx;
+
+ kcdb_cred_get_name(cred, NULL, &t);
+ ps->header.pszCaption = PMALLOC(t);
+ kcdb_cred_get_name(cred, (LPWSTR) ps->header.pszCaption, &t);
+
+ kcdb_cred_get_identity(cred, &ps->identity);
+ kcdb_cred_get_type(cred, &ps->credtype);
+ ps->cred = cred;
+
+ kmq_post_message(KMSG_CRED, KMSG_CRED_PP_BEGIN, 0, (void *) ps);
+ } else {
+ khui_context_release(&ctx);
+ khui_ps_destroy_sheet(ps);
+ }
+
+ /* by the way, if we are actually opening a property sheet, we
+ leave ctx held (which is now copied to ps->ctx). it will be
+ released when the property sheet is destroyed */
+
+ return TRUE;
+}
+
+LRESULT
+cw_wm_command(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ khui_credwnd_tbl * tbl;
+
+ tbl = (khui_credwnd_tbl *)(LONG_PTR) GetWindowLongPtr(hwnd, 0);
+
+ if(HIWORD(wParam) == BN_CLICKED &&
+ LOWORD(wParam) == KHUI_HTWND_CTLID) {
+
+ wchar_t wid[256];
+ /* a hyperlink was activated */
+ khui_htwnd_link * l;
+ l = (khui_htwnd_link *) lParam;
+ StringCchCopyN(wid, ARRAYLENGTH(wid), l->id, l->id_len);
+ wid[l->id_len] = 0;
+
+ if(!wcscmp(wid, L"NewCreds")) {
+ PostMessage(khm_hwnd_main, WM_COMMAND,
+ MAKEWPARAM(KHUI_ACTION_NEW_CRED,0), 0);
+ }
+ return TRUE;
+ }
+
+ switch(LOWORD(wParam))
+ {
+ case KHUI_PACTION_ENTER:
+ /* enter key is a synonym for the default action, on the
+ context, which is to lauch a property sheet */
+ /* fallthrough */
+ case KHUI_ACTION_PROPERTIES:
+ {
+ return cw_properties(hwnd);
+ }
+ break;
+
+ case KHUI_ACTION_LAYOUT_RELOAD:
+ {
+ wchar_t cname[KCONF_MAXCCH_NAME];
+ khm_size cb;
+
+ cname[0] = L'\0';
+
+ if (tbl->csp_view) {
+ cb = sizeof(cname);
+ khc_get_config_space_name(tbl->csp_view,
+ cname,
+ &cb);
+ }
+
+ cw_unload_view(tbl);
+
+ cw_load_view(tbl, ((cname[0])?cname: NULL), hwnd);
+ cw_insert_header_cols(tbl);
+
+ cw_update_creds(tbl);
+ cw_update_outline(tbl);
+ cw_update_selection_state(tbl);
+ cw_update_extents(tbl, TRUE);
+
+ InvalidateRect(tbl->hwnd, NULL, TRUE);
+ }
+ break;
+
+ case KHUI_ACTION_LAYOUT_ID:
+ {
+ cw_save_view(tbl, NULL);
+ cw_unload_view(tbl);
+
+ cw_load_view(tbl, L"ByIdentity", hwnd);
+ cw_insert_header_cols(tbl);
+
+ cw_update_creds(tbl);
+ cw_update_outline(tbl);
+ cw_update_selection_state(tbl);
+ cw_update_extents(tbl, TRUE);
+
+ InvalidateRect(tbl->hwnd, NULL, TRUE);
+
+ }
+ break;
+
+ case KHUI_ACTION_LAYOUT_LOC:
+ {
+ cw_save_view(tbl, NULL);
+ cw_unload_view(tbl);
+
+ cw_load_view(tbl, L"ByLocation", hwnd);
+ cw_insert_header_cols(tbl);
+
+ cw_update_creds(tbl);
+ cw_update_outline(tbl);
+ cw_update_selection_state(tbl);
+ cw_update_extents(tbl, TRUE);
+
+ InvalidateRect(tbl->hwnd, NULL, TRUE);
+
+ }
+ break;
+
+ case KHUI_ACTION_LAYOUT_TYPE:
+ {
+ cw_save_view(tbl, NULL);
+ cw_unload_view(tbl);
+
+ cw_load_view(tbl, L"ByType", hwnd);
+ cw_insert_header_cols(tbl);
+
+ cw_update_creds(tbl);
+ cw_update_outline(tbl);
+ cw_update_selection_state(tbl);
+ cw_update_extents(tbl, TRUE);
+
+ InvalidateRect(tbl->hwnd, NULL, TRUE);
+
+ }
+ break;
+
+ case KHUI_ACTION_LAYOUT_CUST:
+ {
+ cw_save_view(tbl, NULL);
+ cw_unload_view(tbl);
+
+ cw_load_view(tbl, L"Custom_0", hwnd);
+ cw_insert_header_cols(tbl);
+
+ cw_update_creds(tbl);
+ cw_update_outline(tbl);
+ cw_update_selection_state(tbl);
+ cw_update_extents(tbl, TRUE);
+
+ InvalidateRect(tbl->hwnd, NULL, TRUE);
+
+ }
+ break;
+
+ case KHUI_ACTION_LAYOUT_MINI:
+ {
+ cw_save_view(tbl, NULL);
+ cw_unload_view(tbl);
+
+ cw_load_view(tbl, NULL, hwnd);
+ cw_insert_header_cols(tbl);
+
+ cw_update_creds(tbl);
+ cw_update_outline(tbl);
+ cw_update_selection_state(tbl);
+ cw_update_extents(tbl, TRUE);
+
+ InvalidateRect(tbl->hwnd, NULL, TRUE);
+ }
+ break;
+
+ case KHUI_PACTION_UP:
+ case KHUI_PACTION_UP_EXTEND:
+ case KHUI_PACTION_UP_TOGGLE:
+ { /* cursor up */
+ khm_int32 new_row;
+ WPARAM wp = 0;
+
+ new_row = tbl->cursor_row - 1;
+
+ /* checking both bounds. we make no assumption about the
+ value of cursor_row before this message */
+ if(new_row < 0)
+ new_row = 0;
+ if(new_row >= (int) tbl->n_rows)
+ new_row = (int) tbl->n_rows - 1;
+
+ if (LOWORD(wParam) == KHUI_PACTION_UP)
+ wp = 0;
+ else if (LOWORD(wParam) == KHUI_PACTION_UP_EXTEND)
+ wp = MK_SHIFT;
+ else if (LOWORD(wParam) == KHUI_PACTION_UP_TOGGLE)
+ wp = 0; //MK_CONTROL;
+ else {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ }
+
+ cw_select_row(tbl, new_row, wp);
+ cw_ensure_row_visible(hwnd, tbl, new_row);
+ }
+ break;
+
+ case KHUI_PACTION_PGUP_EXTEND:
+ case KHUI_PACTION_PGUP:
+ {
+ khm_int32 new_row;
+ WPARAM wp;
+ RECT r;
+
+ if (LOWORD(wParam) == KHUI_PACTION_PGUP_EXTEND)
+ wp = MK_SHIFT;
+ else
+ wp = 0;
+
+ GetClientRect(hwnd, &r);
+
+ new_row = tbl->cursor_row -
+ ((r.bottom - r.top) - tbl->header_height) / tbl->cell_height;
+
+ if (new_row < 0)
+ new_row = 0;
+ if (new_row >= (int) tbl->n_rows)
+ new_row = (int) tbl->n_rows - 1;
+
+ cw_select_row(tbl, new_row, wp);
+ cw_ensure_row_visible(hwnd, tbl, new_row);
+ }
+ break;
+
+ case KHUI_PACTION_DOWN:
+ case KHUI_PACTION_DOWN_EXTEND:
+ case KHUI_PACTION_DOWN_TOGGLE:
+ { /* cursor down */
+ khm_int32 new_row;
+ WPARAM wp = 0;
+
+ new_row = tbl->cursor_row + 1;
+
+ /* checking both bounds. we make no assumption about the
+ value of cursor_row before this message */
+ if(new_row < 0)
+ new_row = 0;
+ if(new_row >= (int) tbl->n_rows)
+ new_row = (int) tbl->n_rows - 1;
+
+ if (LOWORD(wParam) == KHUI_PACTION_DOWN)
+ wp = 0;
+ else if (LOWORD(wParam) == KHUI_PACTION_DOWN_EXTEND)
+ wp = MK_SHIFT;
+ else if (LOWORD(wParam) == KHUI_PACTION_DOWN_TOGGLE)
+ wp = 0; //MK_CONTROL;
+ else {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ }
+
+ cw_select_row(tbl, new_row, wp);
+ cw_ensure_row_visible(hwnd, tbl, new_row);
+ }
+ break;
+
+ case KHUI_PACTION_PGDN_EXTEND:
+ case KHUI_PACTION_PGDN:
+ {
+ khm_int32 new_row;
+ RECT r;
+ WPARAM wp;
+
+ if (LOWORD(wParam) == KHUI_PACTION_PGDN_EXTEND)
+ wp = MK_SHIFT;
+ else
+ wp = 0;
+
+ GetClientRect(hwnd, &r);
+
+ new_row = tbl->cursor_row +
+ ((r.bottom - r.top) - tbl->header_height) / tbl->cell_height;
+
+ if (new_row < 0)
+ new_row = 0;
+ if (new_row >= (int) tbl->n_rows)
+ new_row = (int) tbl->n_rows - 1;
+
+ cw_select_row(tbl, new_row, wp);
+ cw_ensure_row_visible(hwnd, tbl, new_row);
+ }
+ break;
+
+ case KHUI_PACTION_SELALL:
+ {
+ cw_select_all(tbl);
+ }
+ break;
+
+ case KHUI_PACTION_LEFT:
+ { /* collapse and up*/
+ khui_credwnd_outline * o;
+ int r;
+
+ if(tbl->cursor_row < 0 || tbl->cursor_row >= (int) tbl->n_rows) {
+ cw_select_row(tbl, 0, 0);
+ break;
+ }
+
+ for(r = tbl->cursor_row;
+ (r >= 0 && !(tbl->rows[r].flags & KHUI_CW_ROW_HEADER));
+ r--);
+
+ if(r < 0)
+ break;
+
+ /* If we were not on a header, we collapse the innermost
+ outline. Otherwise, we collpase up to the parent
+ outline level */
+
+ if(r != tbl->cursor_row) {
+ o = (khui_credwnd_outline *) tbl->rows[r].data;
+
+ cw_toggle_outline_state(tbl, o);
+ } else {
+ o = (khui_credwnd_outline *) tbl->rows[r].data;
+
+ if(o->flags & KHUI_CW_O_EXPAND) {
+ cw_toggle_outline_state(tbl, o);
+ } else {
+ o = TPARENT(o);
+ if(o) {
+ cw_toggle_outline_state(tbl, o);
+ r = o->start;
+ } else if(r > 0)
+ r--;
+ }
+ }
+
+ cw_select_row(tbl, r, 0);
+ }
+ break;
+
+ case KHUI_PACTION_RIGHT:
+ { /* expand and down*/
+ khui_credwnd_outline * o;
+ int r;
+
+ if(tbl->cursor_row < 0 ||
+ tbl->cursor_row >= (int) tbl->n_rows) {
+ cw_select_row(tbl, 0, 0);
+ break;
+ }
+
+ r = tbl->cursor_row;
+
+ if(tbl->rows[r].flags & KHUI_CW_ROW_HEADER) {
+ o = (khui_credwnd_outline *) tbl->rows[r].data;
+ if(!(o->flags & KHUI_CW_O_EXPAND)) {
+ cw_toggle_outline_state(tbl, o);
+ }
+ }
+
+ r++;
+ if (r >= (int) tbl->n_rows)
+ r = (int)tbl->n_rows - 1;
+
+ cw_select_row(tbl, r, 0);
+ }
+ break;
+ }
+ return DefWindowProc(hwnd, uMsg, wParam, lParam);
+}
+
+LRESULT
+cw_wm_contextmenu(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ RECT r;
+ int x,y;
+ int row;
+ khui_credwnd_tbl * tbl;
+
+ tbl = (khui_credwnd_tbl *)(LONG_PTR) GetWindowLongPtr(hwnd, 0);
+
+ GetWindowRect(hwnd, &r);
+
+ x = GET_X_LPARAM(lParam);
+ y = GET_Y_LPARAM(lParam);
+
+ x += tbl->scr_left - r.left;
+ y += tbl->scr_top - tbl->header_height - r.top;
+
+ if (y < 0) {
+ /* context menu for header control */
+ khm_menu_show_panel(KHUI_MENU_CWHEADER_CTX,
+ GET_X_LPARAM(lParam),
+ GET_Y_LPARAM(lParam));
+
+ return DefWindowProc(hwnd, uMsg, wParam, lParam);
+ }
+
+ if (tbl->flags & KHUI_CW_TBL_EXPIDENT) {
+ int i, yt;
+
+ yt = 0;
+ for (i=0; i < tbl->n_rows && yt < y; i++) {
+ if (tbl->rows[i].flags & KHUI_CW_ROW_EXPVIEW)
+ yt += tbl->cell_height * CW_EXP_ROW_MULT;
+ else
+ yt += tbl->cell_height;
+ if (yt > y)
+ break;
+ }
+
+ row = i;
+
+ } else {
+ row = y / tbl->cell_height;
+ }
+
+ if(row < 0 || row >= (int) tbl->n_rows)
+ return FALSE;
+
+ cw_set_row_context(tbl, row);
+
+ khm_menu_show_panel(KHUI_MENU_IDENT_CTX, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
+
+#if 0
+ /* calling cw_set_row_context() should take care of enabling or
+ disabling actions as appropriate. We don't need to
+ differentiate between IDENT_CTX and TOK_CTX here. */
+ if((tbl->rows[row].flags & KHUI_CW_ROW_HEADER) &&
+ (tbl->cols[tbl->rows[row].col].attr_id == KCDB_ATTR_ID_NAME)) {
+ khm_menu_show_panel(KHUI_MENU_IDENT_CTX, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
+ //khui_context_reset();
+ } else {
+ khm_menu_show_panel(KHUI_MENU_TOK_CTX, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
+ //khui_context_reset();
+ }
+#endif
+
+ return DefWindowProc(hwnd, uMsg, wParam, lParam);
+}
+
+/* copy and paste template */
+#if 0
+LRESULT
+cw_wm_msg(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ return DefWindowProc(hwnd, uMsg, wParam, lParam);
+}
+#endif
+
+LRESULT CALLBACK
+khm_credwnd_proc(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ switch(uMsg) {
+ case WM_COMMAND:
+ return cw_wm_command(hwnd, uMsg, wParam, lParam);
+
+ case WM_CREATE:
+ return cw_wm_create(hwnd, uMsg, wParam, lParam);
+
+ case WM_DESTROY:
+ return cw_wm_destroy(hwnd, uMsg, wParam, lParam);
+
+ case WM_ERASEBKGND:
+ /* we don't bother wasting cycles erasing the background
+ because the foreground elements completely cover the
+ client area */
+ return FALSE;
+
+ case WM_PAINT:
+ return cw_wm_paint(hwnd, uMsg, wParam, lParam);
+
+ case WM_PRINTCLIENT:
+ return cw_wm_paint(hwnd, uMsg, wParam, lParam);
+
+ case WM_SIZE:
+ return cw_wm_size(hwnd, uMsg, wParam, lParam);
+
+ case WM_NOTIFY:
+ return cw_wm_notify(hwnd, uMsg, wParam, lParam);
+
+ case WM_HSCROLL:
+ return cw_wm_hscroll(hwnd, uMsg, wParam, lParam);
+
+ case WM_VSCROLL:
+ return cw_wm_vscroll(hwnd, uMsg, wParam, lParam);
+
+ case KMQ_WM_DISPATCH:
+ return cw_kmq_wm_dispatch(hwnd, uMsg, wParam, lParam);
+
+ case WM_LBUTTONDBLCLK:
+ case WM_LBUTTONDOWN:
+ case WM_MOUSEMOVE:
+ case WM_LBUTTONUP:
+ return cw_wm_mouse(hwnd, uMsg, wParam, lParam);
+
+ case WM_CONTEXTMENU:
+ return cw_wm_contextmenu(hwnd, uMsg, wParam, lParam);
+ }
+
+ return DefWindowProc(hwnd,uMsg,wParam,lParam);
+}
+
+void
+khm_register_credwnd_class(void) {
+ WNDCLASSEX wcx;
+ kcdb_attrib attrib;
+ khm_int32 attr_id;
+
+ wcx.cbSize = sizeof(wcx);
+ wcx.style = CS_DBLCLKS | CS_OWNDC;
+ wcx.lpfnWndProc = khm_credwnd_proc;
+ wcx.cbClsExtra = 0;
+ wcx.cbWndExtra = sizeof(LONG_PTR);
+ wcx.hInstance = khm_hInstance;
+ wcx.hIcon = NULL;
+ wcx.hCursor = LoadCursor((HINSTANCE) NULL, IDC_ARROW);
+ wcx.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
+ wcx.lpszMenuName = NULL;
+ wcx.lpszClassName = KHUI_CREDWND_CLASS_NAME;
+ wcx.hIconSm = NULL;
+
+ khui_credwnd_cls = RegisterClassEx(&wcx);
+
+ /* while we are at it, register the credwnd attribute type as well, and
+ obtain the type ID */
+ if(KHM_FAILED(kcdb_attrib_get_id(KHUI_CREDWND_FLAG_ATTRNAME, &attr_id))) {
+ ZeroMemory(&attrib, sizeof(attrib));
+ attrib.id = KCDB_ATTR_INVALID;
+ attrib.flags = KCDB_ATTR_FLAG_HIDDEN;
+ attrib.type = KCDB_TYPE_INT32;
+ attrib.name = KHUI_CREDWND_FLAG_ATTRNAME;
+
+ kcdb_attrib_register(&attrib, &attr_id);
+ }
+
+ khui_cw_flag_id = attr_id;
+}
+
+void
+khm_unregister_credwnd_class(void) {
+ UnregisterClass(MAKEINTATOM(khui_credwnd_cls), khm_hInstance);
+}
+
+HWND
+khm_create_credwnd(HWND parent) {
+ RECT r;
+ HWND hwnd;
+
+ ZeroMemory(attr_to_action, sizeof(attr_to_action));
+
+ GetClientRect(parent, &r);
+
+ hwnd = CreateWindowEx
+ (0,
+ MAKEINTATOM(khui_credwnd_cls),
+ L"",
+ WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
+ r.left,
+ r.top,
+ r.right - r.left,
+ r.bottom - r.top,
+ parent,
+ NULL,
+ khm_hInstance,
+ NULL);
+
+ return hwnd;
+}
diff --git a/src/windows/identity/ui/credwnd.h b/src/windows/identity/ui/credwnd.h
index adecb9f072..47f8a745e1 100644
--- a/src/windows/identity/ui/credwnd.h
+++ b/src/windows/identity/ui/credwnd.h
@@ -1,300 +1,300 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#ifndef __KHIMAIRA_CREDWND_H
-#define __KHIMAIRA_CREDWND_H
-
-#define KHUI_CREDWND_CLASS_NAME L"NetIDMgrCredWnd"
-
-#define KHUI_CREDWND_FLAG_ATTRNAME L"CredWndFlags"
-
-extern khm_int32 khui_cw_flag_id;
-
-/* The expiration states */
-#define CW_EXPSTATE_NONE 0x00000000
-#define CW_EXPSTATE_WARN 0x00000400
-#define CW_EXPSTATE_CRITICAL 0x00000800
-#define CW_EXPSTATE_EXPIRED 0x00000c00
-
-#define CW_EXPSTATE_MASK 0x00000c00
-
-typedef struct khui_credwnd_outline_t {
- khm_int32 flags; /* combination of KHUI_CW_O_* */
- khm_int32 start; /* first row of outline */
- khm_int32 length; /* number of rows in outline */
- khm_int32 level; /* outline level */
- khm_int32 col; /* outline column */
- wchar_t *header; /* character string associated with header */
- khm_int32 attr_id;
- void * data; /* level specific data :
- Identity -> handle to identity
- Type -> type ID
- otherwise -> canonical data buffer
- */
- khm_size cb_data;
-
- khm_size idx_start; /* index of the first cred in the credset */
- khm_size idx_end; /* index of the last cred in the credset */
- TDCL(struct khui_credwnd_outline_t);
-} khui_credwnd_outline;
-
-#define KHUI_CW_O_EXPAND 0x00000001
-#define KHUI_CW_O_STICKY 0x00000002
-#define KHUI_CW_O_VISIBLE 0x00000004
-#define KHUI_CW_O_SHOWFLAG 0x00000008
-#define KHUI_CW_O_SELECTED 0x00000010
-#define KHUI_CW_O_DATAALLOC 0x00000020
-#define KHUI_CW_O_NOOUTLINE 0x00000040
-#define KHUI_CW_O_RELIDENT 0x00000080
-#define KHUI_CW_O_EMPTY 0x00000100
-/* NOTE: KHUI_CW_O_* shares the same bit-space as CW_EXPSTATE_* */
-
-typedef struct khui_credwnd_row_t {
- khm_int32 flags;
- khm_int32 col;
- khm_handle data;
- khm_size idx_start;
- khm_size idx_end;
- RECT r_ext; /* extents of this row */
-} khui_credwnd_row;
-
-#define KHUI_CW_ROW_CRED 0x00000002
-#define KHUI_CW_ROW_HEADER 0x00000004
-#define KHUI_CW_ROW_TIMERSET 0x00000008
-#define KHUI_CW_ROW_SELECTED 0x00000010
-#define KHUI_CW_ROW_EXPVIEW 0x00000020
-/* NOTE: KHUI_CW_ROW_* shares the same bit-space as CW_EXPSTATE_* */
-
-/* row allocation */
-/* initial number of rows to be allocated */
-#define KHUI_CW_ROW_INITIAL 512
-/* allocation increment, if we run out of space */
-#define KHUI_CW_ROW_INCREMENT 512
-
-typedef struct khui_credwnd_col_t {
- khm_int32 attr_id;
- khm_int32 width; /* width of the column (screen units) */
- khm_int32 x; /* starting x coordinate (screen units) */
- khm_int32 flags; /* combination of KHUI_CW_COL_* */
- khm_int32 sort_index;
- wchar_t * title;
-} khui_credwnd_col;
-
-/* column allocation */
-/* initial number of columns to be allocated */
-#define KHUI_CW_COL_INITIAL 16
-/* allocation increment, if we run out of space */
-#define KHUI_CW_COL_INCREMENT 16
-
-#define KHUI_CW_COL_AUTOSIZE 0x00000001
-#define KHUI_CW_COL_SORT_INC 0x00000002
-#define KHUI_CW_COL_SORT_DEC 0x00000004
-#define KHUI_CW_COL_GROUP 0x00000008
-#define KHUI_CW_COL_FIXED_WIDTH 0x00000010
-#define KHUI_CW_COL_FIXED_POS 0x00000020
-#define KHUI_CW_COL_META 0x00000040
-#define KHUI_CW_COL_FILLER 0x00000080
-
-/* Custom column attributes (are not kcdb attributes) */
-#define CW_CA_FLAGS -1
-#define CW_CANAME_FLAGS L"_CWFlags"
-
-#define CW_CA_TYPEICON -2
-#define CW_CANAME_TYPEICON L"_CWTypeIcon"
-
-#define cw_is_custom_attr(i) ((i)<0)
-
-typedef struct tag_khui_credwnd_ident {
-
- khm_handle ident;
- khm_int32 ident_flags;
- khm_int32 credtype;
- wchar_t name[KCDB_IDENT_MAXCCH_NAME];
- wchar_t credtype_name[KCDB_MAXCCH_NAME];
-
- khm_size credcount; /* count of all credentials */
- khm_size id_credcount; /* count of identity credentials
- (credentials that are of the
- identity type */
- khm_size init_credcount; /* count of initial credentials */
- FILETIME ft_expire;
-
-} khui_credwnd_ident;
-
-#define CW_IDENT_ALLOC_INCR 4
-
-#define CW_EXP_ROW_MULT 2
-
-typedef struct khui_credwnd_tbl_t {
- HWND hwnd; /* the window that this table belongs to */
-
- khm_handle csp_view; /* handle to the configuration space
- that defined the view */
-
- khm_int32 scr_top; /* screen units */
- khm_int32 scr_left; /* screen units */
- khm_int32 ext_width; /* screen units */
- khm_int32 ext_height; /* screen units */
- khm_int32 cell_height; /* screen units */
-
- HWND hwnd_header; /* header control */
- khm_int32 header_height; /* height of the header */
- HWND hwnd_notif; /* notification control */
-
- khui_credwnd_col * cols; /* n_cols elements */
- khui_credwnd_row * rows; /* n_rows elements */
- int n_cols;
- int n_total_cols; /* number of columns actually
- allocated in cols */
- int n_rows;
- int n_total_rows; /* number of rows actually allocated
- in rows */
-
- khui_credwnd_outline * outline;
-
- khm_int32 flags; /* combo of KHUI_CW_TBL_* */
-
- int cursor_row; /* cursor and selection */
- int anchor_row; /* anchor, for range selections */
-
- /* view parameters */
- khm_int32 hpad;
- khm_int32 vpad;
- khm_int32 hpad_h; /* horizontal padding correction for headers */
- khm_int32 threshold_warn; /* Warning threshold, in seconds*/
- khm_int32 threshold_critical; /* Critical threshold, in seconds */
-
- /* graphics objects we are going to need. */
- HFONT hf_normal; /* normal text */
- HFONT hf_header; /* header text */
- HFONT hf_bold; /* bold text */
- HFONT hf_bold_header; /* bold header text */
-
- HBRUSH hb_normal; /* normal background brush */
- HBRUSH hb_grey; /* normal background brush (greyed) */
- HBRUSH hb_s; /* normal background brush (selected) */
-
- HBRUSH hb_hdr_bg; /* header background brush (normal) */
- HBRUSH hb_hdr_bg_exp; /* header background brush (expired) */
- HBRUSH hb_hdr_bg_warn; /* header background brush (warn) */
- HBRUSH hb_hdr_bg_crit; /* header background brush (critical) */
- HBRUSH hb_hdr_bg_def; /* header background brush (default) */
-
- HBRUSH hb_hdr_bg_s; /* header background brush (selected) */
- HBRUSH hb_hdr_bg_exp_s; /* header background brush (expired,selected) */
- HBRUSH hb_hdr_bg_warn_s;/* header background brush (warn,selected) */
- HBRUSH hb_hdr_bg_crit_s;/* header background brush (critical,selected) */
- HBRUSH hb_hdr_bg_def_s; /* header background brush (default,selected) */
-
- COLORREF cr_normal; /* text color (normal) */
- COLORREF cr_s; /* text color (selected) */
- COLORREF cr_hdr_normal; /* header text color (normal) */
- COLORREF cr_hdr_s; /* header text color (selected) */
- COLORREF cr_hdr_gray; /* header text color (greyed) */
- COLORREF cr_hdr_gray_s; /* header text color (greyed,selected) */
-
- COLORREF cr_hdr_outline;/* header outline color */
-
- HCURSOR hc_hand; /* the HAND cursor */
- khui_ilist * ilist; /* image list */
-
- HICON hi_lg_ident; /* large identity icon */
-
- /* mouse state */
- khm_int32 mouse_state; /* state of the mouse can be combo of CW_MOUSE_* values */
- khm_int32 mouse_row; /* row that the mouse state applies to */
- khm_int32 mouse_col; /* col that the mouse state applies to */
-
- khui_bitmap kbm_logo_shade;
-
- /* the credentials set */
- khm_handle credset;
-
- khui_credwnd_ident * idents;
- khm_size n_idents;
- khm_size nc_idents;
-
-} khui_credwnd_tbl;
-
-#define KHUI_MAXCB_HEADING 256
-
-/* table flags */
-#define KHUI_CW_TBL_INITIALIZED 0x00000001
-#define KHUI_CW_TBL_COL_DIRTY 0x00000002
-#define KHUI_CW_TBL_ROW_DIRTY 0x00000004
-#define KHUI_CW_TBL_ACTIVE 0x00000100
-#define KHUI_CW_TBL_CUSTVIEW 0x00000200
-#define KHUI_CW_TBL_COLSKIP 0x00000400
-#define KHUI_CW_TBL_EXPIDENT 0x00000800
-#define KHUI_CW_TBL_NOHEADER 0x00001000
-
-/* mouse_state constants */
-#define CW_MOUSE_NONE 0x00000000 /* nothing interesting */
-#define CW_MOUSE_WIDGET 0x00000001 /* mouse is highlighting a
- widget */
-#define CW_MOUSE_LDOWN 0x00000002 /* left button is down */
-#define CW_MOUSE_ROW 0x00000004 /* mouse is acive over a valid
- row */
-#define CW_MOUSE_WOUTLINE 0x00000008 /* mouse is highlighting an
- outline widget */
-#define CW_MOUSE_WSTICKY 0x00000010 /* mouse is highlighting a
- sticky widget */
-#define CW_MOUSE_WICON 0x00000020 /* an icon widget. represents
- the icon next to identities
- and next to credentials. */
-
-#define CW_MOUSE_WMASK 0x00000039 /* all widget bits */
-
-void khm_unregister_credwnd_class(void);
-
-void khm_register_credwnd_class(void);
-
-HWND khm_create_credwnd(HWND parent);
-
-LRESULT CALLBACK khm_credwnd_proc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam
- );
-
-void cw_load_view(khui_credwnd_tbl * tbl, wchar_t * viewname, HWND hwnd);
-
-void cw_update_creds(khui_credwnd_tbl * tbl);
-
-void cw_unload_view(khui_credwnd_tbl * tbl);
-
-void cw_hditem_from_tbl_col(khui_credwnd_col * col, HDITEM *phi);
-
-int cw_update_extents(khui_credwnd_tbl * tbl, khm_boolean update_scroll);
-
-void cw_insert_header_cols(khui_credwnd_tbl * tbl);
-
-void khm_get_cw_element_font(HDC hdc, wchar_t * name, BOOL use_default,
- LOGFONT * pfont);
-
-void khm_set_cw_element_font(wchar_t * name, LOGFONT * pfont);
-
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __KHIMAIRA_CREDWND_H
+#define __KHIMAIRA_CREDWND_H
+
+#define KHUI_CREDWND_CLASS_NAME L"NetIDMgrCredWnd"
+
+#define KHUI_CREDWND_FLAG_ATTRNAME L"CredWndFlags"
+
+extern khm_int32 khui_cw_flag_id;
+
+/* The expiration states */
+#define CW_EXPSTATE_NONE 0x00000000
+#define CW_EXPSTATE_WARN 0x00000400
+#define CW_EXPSTATE_CRITICAL 0x00000800
+#define CW_EXPSTATE_EXPIRED 0x00000c00
+
+#define CW_EXPSTATE_MASK 0x00000c00
+
+typedef struct khui_credwnd_outline_t {
+ khm_int32 flags; /* combination of KHUI_CW_O_* */
+ khm_int32 start; /* first row of outline */
+ khm_int32 length; /* number of rows in outline */
+ khm_int32 level; /* outline level */
+ khm_int32 col; /* outline column */
+ wchar_t *header; /* character string associated with header */
+ khm_int32 attr_id;
+ void * data; /* level specific data :
+ Identity -> handle to identity
+ Type -> type ID
+ otherwise -> canonical data buffer
+ */
+ khm_size cb_data;
+
+ khm_size idx_start; /* index of the first cred in the credset */
+ khm_size idx_end; /* index of the last cred in the credset */
+ TDCL(struct khui_credwnd_outline_t);
+} khui_credwnd_outline;
+
+#define KHUI_CW_O_EXPAND 0x00000001
+#define KHUI_CW_O_STICKY 0x00000002
+#define KHUI_CW_O_VISIBLE 0x00000004
+#define KHUI_CW_O_SHOWFLAG 0x00000008
+#define KHUI_CW_O_SELECTED 0x00000010
+#define KHUI_CW_O_DATAALLOC 0x00000020
+#define KHUI_CW_O_NOOUTLINE 0x00000040
+#define KHUI_CW_O_RELIDENT 0x00000080
+#define KHUI_CW_O_EMPTY 0x00000100
+/* NOTE: KHUI_CW_O_* shares the same bit-space as CW_EXPSTATE_* */
+
+typedef struct khui_credwnd_row_t {
+ khm_int32 flags;
+ khm_int32 col;
+ khm_handle data;
+ khm_size idx_start;
+ khm_size idx_end;
+ RECT r_ext; /* extents of this row */
+} khui_credwnd_row;
+
+#define KHUI_CW_ROW_CRED 0x00000002
+#define KHUI_CW_ROW_HEADER 0x00000004
+#define KHUI_CW_ROW_TIMERSET 0x00000008
+#define KHUI_CW_ROW_SELECTED 0x00000010
+#define KHUI_CW_ROW_EXPVIEW 0x00000020
+/* NOTE: KHUI_CW_ROW_* shares the same bit-space as CW_EXPSTATE_* */
+
+/* row allocation */
+/* initial number of rows to be allocated */
+#define KHUI_CW_ROW_INITIAL 512
+/* allocation increment, if we run out of space */
+#define KHUI_CW_ROW_INCREMENT 512
+
+typedef struct khui_credwnd_col_t {
+ khm_int32 attr_id;
+ khm_int32 width; /* width of the column (screen units) */
+ khm_int32 x; /* starting x coordinate (screen units) */
+ khm_int32 flags; /* combination of KHUI_CW_COL_* */
+ khm_int32 sort_index;
+ wchar_t * title;
+} khui_credwnd_col;
+
+/* column allocation */
+/* initial number of columns to be allocated */
+#define KHUI_CW_COL_INITIAL 16
+/* allocation increment, if we run out of space */
+#define KHUI_CW_COL_INCREMENT 16
+
+#define KHUI_CW_COL_AUTOSIZE 0x00000001
+#define KHUI_CW_COL_SORT_INC 0x00000002
+#define KHUI_CW_COL_SORT_DEC 0x00000004
+#define KHUI_CW_COL_GROUP 0x00000008
+#define KHUI_CW_COL_FIXED_WIDTH 0x00000010
+#define KHUI_CW_COL_FIXED_POS 0x00000020
+#define KHUI_CW_COL_META 0x00000040
+#define KHUI_CW_COL_FILLER 0x00000080
+
+/* Custom column attributes (are not kcdb attributes) */
+#define CW_CA_FLAGS -1
+#define CW_CANAME_FLAGS L"_CWFlags"
+
+#define CW_CA_TYPEICON -2
+#define CW_CANAME_TYPEICON L"_CWTypeIcon"
+
+#define cw_is_custom_attr(i) ((i)<0)
+
+typedef struct tag_khui_credwnd_ident {
+
+ khm_handle ident;
+ khm_int32 ident_flags;
+ khm_int32 credtype;
+ wchar_t name[KCDB_IDENT_MAXCCH_NAME];
+ wchar_t credtype_name[KCDB_MAXCCH_NAME];
+
+ khm_size credcount; /* count of all credentials */
+ khm_size id_credcount; /* count of identity credentials
+ (credentials that are of the
+ identity type */
+ khm_size init_credcount; /* count of initial credentials */
+ FILETIME ft_expire;
+
+} khui_credwnd_ident;
+
+#define CW_IDENT_ALLOC_INCR 4
+
+#define CW_EXP_ROW_MULT 2
+
+typedef struct khui_credwnd_tbl_t {
+ HWND hwnd; /* the window that this table belongs to */
+
+ khm_handle csp_view; /* handle to the configuration space
+ that defined the view */
+
+ khm_int32 scr_top; /* screen units */
+ khm_int32 scr_left; /* screen units */
+ khm_int32 ext_width; /* screen units */
+ khm_int32 ext_height; /* screen units */
+ khm_int32 cell_height; /* screen units */
+
+ HWND hwnd_header; /* header control */
+ khm_int32 header_height; /* height of the header */
+ HWND hwnd_notif; /* notification control */
+
+ khui_credwnd_col * cols; /* n_cols elements */
+ khui_credwnd_row * rows; /* n_rows elements */
+ int n_cols;
+ int n_total_cols; /* number of columns actually
+ allocated in cols */
+ int n_rows;
+ int n_total_rows; /* number of rows actually allocated
+ in rows */
+
+ khui_credwnd_outline * outline;
+
+ khm_int32 flags; /* combo of KHUI_CW_TBL_* */
+
+ int cursor_row; /* cursor and selection */
+ int anchor_row; /* anchor, for range selections */
+
+ /* view parameters */
+ khm_int32 hpad;
+ khm_int32 vpad;
+ khm_int32 hpad_h; /* horizontal padding correction for headers */
+ khm_int32 threshold_warn; /* Warning threshold, in seconds*/
+ khm_int32 threshold_critical; /* Critical threshold, in seconds */
+
+ /* graphics objects we are going to need. */
+ HFONT hf_normal; /* normal text */
+ HFONT hf_header; /* header text */
+ HFONT hf_bold; /* bold text */
+ HFONT hf_bold_header; /* bold header text */
+
+ HBRUSH hb_normal; /* normal background brush */
+ HBRUSH hb_grey; /* normal background brush (greyed) */
+ HBRUSH hb_s; /* normal background brush (selected) */
+
+ HBRUSH hb_hdr_bg; /* header background brush (normal) */
+ HBRUSH hb_hdr_bg_exp; /* header background brush (expired) */
+ HBRUSH hb_hdr_bg_warn; /* header background brush (warn) */
+ HBRUSH hb_hdr_bg_crit; /* header background brush (critical) */
+ HBRUSH hb_hdr_bg_def; /* header background brush (default) */
+
+ HBRUSH hb_hdr_bg_s; /* header background brush (selected) */
+ HBRUSH hb_hdr_bg_exp_s; /* header background brush (expired,selected) */
+ HBRUSH hb_hdr_bg_warn_s;/* header background brush (warn,selected) */
+ HBRUSH hb_hdr_bg_crit_s;/* header background brush (critical,selected) */
+ HBRUSH hb_hdr_bg_def_s; /* header background brush (default,selected) */
+
+ COLORREF cr_normal; /* text color (normal) */
+ COLORREF cr_s; /* text color (selected) */
+ COLORREF cr_hdr_normal; /* header text color (normal) */
+ COLORREF cr_hdr_s; /* header text color (selected) */
+ COLORREF cr_hdr_gray; /* header text color (greyed) */
+ COLORREF cr_hdr_gray_s; /* header text color (greyed,selected) */
+
+ COLORREF cr_hdr_outline;/* header outline color */
+
+ HCURSOR hc_hand; /* the HAND cursor */
+ khui_ilist * ilist; /* image list */
+
+ HICON hi_lg_ident; /* large identity icon */
+
+ /* mouse state */
+ khm_int32 mouse_state; /* state of the mouse can be combo of CW_MOUSE_* values */
+ khm_int32 mouse_row; /* row that the mouse state applies to */
+ khm_int32 mouse_col; /* col that the mouse state applies to */
+
+ khui_bitmap kbm_logo_shade;
+
+ /* the credentials set */
+ khm_handle credset;
+
+ khui_credwnd_ident * idents;
+ khm_size n_idents;
+ khm_size nc_idents;
+
+} khui_credwnd_tbl;
+
+#define KHUI_MAXCB_HEADING 256
+
+/* table flags */
+#define KHUI_CW_TBL_INITIALIZED 0x00000001
+#define KHUI_CW_TBL_COL_DIRTY 0x00000002
+#define KHUI_CW_TBL_ROW_DIRTY 0x00000004
+#define KHUI_CW_TBL_ACTIVE 0x00000100
+#define KHUI_CW_TBL_CUSTVIEW 0x00000200
+#define KHUI_CW_TBL_COLSKIP 0x00000400
+#define KHUI_CW_TBL_EXPIDENT 0x00000800
+#define KHUI_CW_TBL_NOHEADER 0x00001000
+
+/* mouse_state constants */
+#define CW_MOUSE_NONE 0x00000000 /* nothing interesting */
+#define CW_MOUSE_WIDGET 0x00000001 /* mouse is highlighting a
+ widget */
+#define CW_MOUSE_LDOWN 0x00000002 /* left button is down */
+#define CW_MOUSE_ROW 0x00000004 /* mouse is acive over a valid
+ row */
+#define CW_MOUSE_WOUTLINE 0x00000008 /* mouse is highlighting an
+ outline widget */
+#define CW_MOUSE_WSTICKY 0x00000010 /* mouse is highlighting a
+ sticky widget */
+#define CW_MOUSE_WICON 0x00000020 /* an icon widget. represents
+ the icon next to identities
+ and next to credentials. */
+
+#define CW_MOUSE_WMASK 0x00000039 /* all widget bits */
+
+void khm_unregister_credwnd_class(void);
+
+void khm_register_credwnd_class(void);
+
+HWND khm_create_credwnd(HWND parent);
+
+LRESULT CALLBACK khm_credwnd_proc(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam
+ );
+
+void cw_load_view(khui_credwnd_tbl * tbl, wchar_t * viewname, HWND hwnd);
+
+void cw_update_creds(khui_credwnd_tbl * tbl);
+
+void cw_unload_view(khui_credwnd_tbl * tbl);
+
+void cw_hditem_from_tbl_col(khui_credwnd_col * col, HDITEM *phi);
+
+int cw_update_extents(khui_credwnd_tbl * tbl, khm_boolean update_scroll);
+
+void cw_insert_header_cols(khui_credwnd_tbl * tbl);
+
+void khm_get_cw_element_font(HDC hdc, wchar_t * name, BOOL use_default,
+ LOGFONT * pfont);
+
+void khm_set_cw_element_font(wchar_t * name, LOGFONT * pfont);
+
+#endif
diff --git a/src/windows/identity/ui/debugfuncs.c b/src/windows/identity/ui/debugfuncs.c
index 7df6e9d651..3e30f117e4 100644
--- a/src/windows/identity/ui/debugfuncs.c
+++ b/src/windows/identity/ui/debugfuncs.c
@@ -1,256 +1,256 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<tchar.h>
-
-#include<shlwapi.h>
-#include<khmapp.h>
-
-#include<stdio.h>
-
-#if DEBUG
-#include<assert.h>
-#endif
-
-#define LOGFILENAME "nidmdbg.log"
-
-CRITICAL_SECTION cs_log;
-FILE * logfile = NULL;
-BOOL log_started = FALSE;
-
-wchar_t *
-severity_string(kherr_severity severity) {
- switch(severity) {
- case KHERR_FATAL:
- return L"FATAL";
-
- case KHERR_ERROR:
- return L"ERROR";
-
- case KHERR_WARNING:
- return L"Warning";
-
- case KHERR_INFO:
- return L"Info";
-
- case KHERR_DEBUG_3:
- return L"Debug(3)";
-
- case KHERR_DEBUG_2:
- return L"Debug(2)";
-
- case KHERR_DEBUG_1:
- return L"Debug(1)";
-
- case KHERR_NONE:
- return L"(None)";
-
- default:
- return L"(Unknown severity)";
- }
-}
-
-void
-fprint_systime(FILE * f, SYSTEMTIME *psystime) {
- fprintf(logfile,
- "%d-%d-%d %02d:%02d:%02d.%03d",
-
- (int) psystime->wYear,
- (int) psystime->wMonth,
- (int) psystime->wDay,
-
- (int) psystime->wHour,
- (int) psystime->wMinute,
- (int) psystime->wSecond,
- (int) psystime->wMilliseconds);
-}
-
-void KHMAPI
-debug_event_handler(enum kherr_ctx_event e,
- kherr_context * c) {
- kherr_event * evt;
-
- EnterCriticalSection(&cs_log);
-
- if (!logfile)
- goto _done;
-
- if (e == KHERR_CTX_BEGIN) {
- SYSTEMTIME systime;
-
- GetSystemTime(&systime);
- fprintf(logfile,
- "%d\t",
- c->serial);
-
- fprint_systime(logfile, &systime);
-
- fprintf(logfile,
- "\t<< Context begin --\n");
-
- } else if (e == KHERR_CTX_DESCRIBE) {
- evt = kherr_get_desc_event(c);
- if (evt) {
- kherr_evaluate_event(evt);
- fprintf(logfile,
- "%d\t Description: %S\n",
- c->serial,
- (evt->long_desc)? evt->long_desc: evt->short_desc);
- }
- } else if (e == KHERR_CTX_END) {
- SYSTEMTIME systime;
-
- fprintf(logfile,
- "%d\t",
- c->serial);
-
- GetSystemTime(&systime);
- fprint_systime(logfile, &systime);
-
- fprintf(logfile,
- "\t>> Context end --\n");
-
- } else if (e == KHERR_CTX_EVTCOMMIT) {
- evt = kherr_get_last_event(c);
- if (evt && (evt->short_desc || evt->long_desc)) {
- SYSTEMTIME systime;
-
- kherr_evaluate_event(evt);
- FileTimeToSystemTime(&evt->time_ft, &systime);
-
- fprintf(logfile,
- "%d[%d](%S)\t",
- c->serial,
- evt->thread_id,
- (evt->facility ? evt->facility: L""));
-
- fprint_systime(logfile, &systime);
-
- fprintf(logfile,
- "\t%S: %S %S%S%S %S%S%S\n",
-
- severity_string(evt->severity),
-
- (evt->short_desc ? evt->short_desc: L""),
-
- (evt->short_desc ? L"(":L""),
- (evt->long_desc ? evt->long_desc: L""),
- (evt->short_desc ? L")":L""),
-
- (evt->suggestion ? L"[":L""),
- (evt->suggestion ? evt->suggestion: L""),
- (evt->suggestion ? L"]":L"")
- );
- }
- }
-
- _done:
-
- LeaveCriticalSection(&cs_log);
-}
-
-void khm_get_file_log_path(khm_size cb_buf, wchar_t * buf) {
-#ifdef DEBUG
- assert(cb_buf > sizeof(wchar_t));
-#endif
- *buf = L'\0';
-
- GetTempPath((DWORD) cb_buf / sizeof(wchar_t), buf);
-
- StringCbCat(buf, cb_buf, _T(LOGFILENAME));
-}
-
-void khm_start_file_log(void) {
- wchar_t temppath[MAX_PATH];
- khm_handle cs_cw = NULL;
- khm_int32 t = 0;
-
- EnterCriticalSection(&cs_log);
-
- if (log_started)
- goto _done;
-
- if (KHM_FAILED(khc_open_space(NULL, L"CredWindow", 0, &cs_cw)))
- goto _done;
-
- if (KHM_FAILED(khc_read_int32(cs_cw, L"LogToFile", &t)) ||
- !t)
- goto _done;
-
- khm_get_file_log_path(sizeof(temppath), temppath);
-
- logfile = NULL;
-#if _MSC_VER >= 1400
- _wfopen_s(&logfile, temppath, L"w");
-#else
- logfile = _wfopen(temppath, L"w");
-#endif
- kherr_add_ctx_handler(debug_event_handler,
- KHERR_CTX_BEGIN |
- KHERR_CTX_END |
- KHERR_CTX_DESCRIBE |
- KHERR_CTX_EVTCOMMIT,
- 0);
-
- log_started = TRUE;
-
- _done:
- if (cs_cw)
- khc_close_space(cs_cw);
-
- LeaveCriticalSection(&cs_log);
-}
-
-void khm_stop_file_log(void) {
-
- EnterCriticalSection(&cs_log);
-
- if (!log_started)
- goto _done;
-
- kherr_remove_ctx_handler(debug_event_handler, 0);
-
- if (logfile)
- fclose (logfile);
- logfile = NULL;
-
- log_started = FALSE;
-
- _done:
- LeaveCriticalSection(&cs_log);
-}
-
-void khm_init_debug(void) {
- InitializeCriticalSection(&cs_log);
-
- khm_start_file_log();
-}
-
-void khm_exit_debug(void) {
- khm_stop_file_log();
-
- DeleteCriticalSection(&cs_log);
-}
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<tchar.h>
+
+#include<shlwapi.h>
+#include<khmapp.h>
+
+#include<stdio.h>
+
+#if DEBUG
+#include<assert.h>
+#endif
+
+#define LOGFILENAME "nidmdbg.log"
+
+CRITICAL_SECTION cs_log;
+FILE * logfile = NULL;
+BOOL log_started = FALSE;
+
+wchar_t *
+severity_string(kherr_severity severity) {
+ switch(severity) {
+ case KHERR_FATAL:
+ return L"FATAL";
+
+ case KHERR_ERROR:
+ return L"ERROR";
+
+ case KHERR_WARNING:
+ return L"Warning";
+
+ case KHERR_INFO:
+ return L"Info";
+
+ case KHERR_DEBUG_3:
+ return L"Debug(3)";
+
+ case KHERR_DEBUG_2:
+ return L"Debug(2)";
+
+ case KHERR_DEBUG_1:
+ return L"Debug(1)";
+
+ case KHERR_NONE:
+ return L"(None)";
+
+ default:
+ return L"(Unknown severity)";
+ }
+}
+
+void
+fprint_systime(FILE * f, SYSTEMTIME *psystime) {
+ fprintf(logfile,
+ "%d-%d-%d %02d:%02d:%02d.%03d",
+
+ (int) psystime->wYear,
+ (int) psystime->wMonth,
+ (int) psystime->wDay,
+
+ (int) psystime->wHour,
+ (int) psystime->wMinute,
+ (int) psystime->wSecond,
+ (int) psystime->wMilliseconds);
+}
+
+void KHMAPI
+debug_event_handler(enum kherr_ctx_event e,
+ kherr_context * c) {
+ kherr_event * evt;
+
+ EnterCriticalSection(&cs_log);
+
+ if (!logfile)
+ goto _done;
+
+ if (e == KHERR_CTX_BEGIN) {
+ SYSTEMTIME systime;
+
+ GetSystemTime(&systime);
+ fprintf(logfile,
+ "%d\t",
+ c->serial);
+
+ fprint_systime(logfile, &systime);
+
+ fprintf(logfile,
+ "\t<< Context begin --\n");
+
+ } else if (e == KHERR_CTX_DESCRIBE) {
+ evt = kherr_get_desc_event(c);
+ if (evt) {
+ kherr_evaluate_event(evt);
+ fprintf(logfile,
+ "%d\t Description: %S\n",
+ c->serial,
+ (evt->long_desc)? evt->long_desc: evt->short_desc);
+ }
+ } else if (e == KHERR_CTX_END) {
+ SYSTEMTIME systime;
+
+ fprintf(logfile,
+ "%d\t",
+ c->serial);
+
+ GetSystemTime(&systime);
+ fprint_systime(logfile, &systime);
+
+ fprintf(logfile,
+ "\t>> Context end --\n");
+
+ } else if (e == KHERR_CTX_EVTCOMMIT) {
+ evt = kherr_get_last_event(c);
+ if (evt && (evt->short_desc || evt->long_desc)) {
+ SYSTEMTIME systime;
+
+ kherr_evaluate_event(evt);
+ FileTimeToSystemTime(&evt->time_ft, &systime);
+
+ fprintf(logfile,
+ "%d[%d](%S)\t",
+ c->serial,
+ evt->thread_id,
+ (evt->facility ? evt->facility: L""));
+
+ fprint_systime(logfile, &systime);
+
+ fprintf(logfile,
+ "\t%S: %S %S%S%S %S%S%S\n",
+
+ severity_string(evt->severity),
+
+ (evt->short_desc ? evt->short_desc: L""),
+
+ (evt->short_desc ? L"(":L""),
+ (evt->long_desc ? evt->long_desc: L""),
+ (evt->short_desc ? L")":L""),
+
+ (evt->suggestion ? L"[":L""),
+ (evt->suggestion ? evt->suggestion: L""),
+ (evt->suggestion ? L"]":L"")
+ );
+ }
+ }
+
+ _done:
+
+ LeaveCriticalSection(&cs_log);
+}
+
+void khm_get_file_log_path(khm_size cb_buf, wchar_t * buf) {
+#ifdef DEBUG
+ assert(cb_buf > sizeof(wchar_t));
+#endif
+ *buf = L'\0';
+
+ GetTempPath((DWORD) cb_buf / sizeof(wchar_t), buf);
+
+ StringCbCat(buf, cb_buf, _T(LOGFILENAME));
+}
+
+void khm_start_file_log(void) {
+ wchar_t temppath[MAX_PATH];
+ khm_handle cs_cw = NULL;
+ khm_int32 t = 0;
+
+ EnterCriticalSection(&cs_log);
+
+ if (log_started)
+ goto _done;
+
+ if (KHM_FAILED(khc_open_space(NULL, L"CredWindow", 0, &cs_cw)))
+ goto _done;
+
+ if (KHM_FAILED(khc_read_int32(cs_cw, L"LogToFile", &t)) ||
+ !t)
+ goto _done;
+
+ khm_get_file_log_path(sizeof(temppath), temppath);
+
+ logfile = NULL;
+#if _MSC_VER >= 1400
+ _wfopen_s(&logfile, temppath, L"w");
+#else
+ logfile = _wfopen(temppath, L"w");
+#endif
+ kherr_add_ctx_handler(debug_event_handler,
+ KHERR_CTX_BEGIN |
+ KHERR_CTX_END |
+ KHERR_CTX_DESCRIBE |
+ KHERR_CTX_EVTCOMMIT,
+ 0);
+
+ log_started = TRUE;
+
+ _done:
+ if (cs_cw)
+ khc_close_space(cs_cw);
+
+ LeaveCriticalSection(&cs_log);
+}
+
+void khm_stop_file_log(void) {
+
+ EnterCriticalSection(&cs_log);
+
+ if (!log_started)
+ goto _done;
+
+ kherr_remove_ctx_handler(debug_event_handler, 0);
+
+ if (logfile)
+ fclose (logfile);
+ logfile = NULL;
+
+ log_started = FALSE;
+
+ _done:
+ LeaveCriticalSection(&cs_log);
+}
+
+void khm_init_debug(void) {
+ InitializeCriticalSection(&cs_log);
+
+ khm_start_file_log();
+}
+
+void khm_exit_debug(void) {
+ khm_stop_file_log();
+
+ DeleteCriticalSection(&cs_log);
+}
diff --git a/src/windows/identity/ui/debugfuncs.h b/src/windows/identity/ui/debugfuncs.h
index 4c378a3a1b..6467185f3a 100644
--- a/src/windows/identity/ui/debugfuncs.h
+++ b/src/windows/identity/ui/debugfuncs.h
@@ -1,37 +1,37 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#ifndef __NETIDMGR_DEBUGFUNCS_H
-#define __NETIDMGR_DEBUGFUNCS_H
-
-void khm_init_debug(void);
-void khm_exit_debug(void);
-
-void khm_start_file_log(void);
-void khm_stop_file_log(void);
-void khm_get_file_log_path(khm_size cb_buf, wchar_t * buf);
-
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __NETIDMGR_DEBUGFUNCS_H
+#define __NETIDMGR_DEBUGFUNCS_H
+
+void khm_init_debug(void);
+void khm_exit_debug(void);
+
+void khm_start_file_log(void);
+void khm_stop_file_log(void);
+void khm_get_file_log_path(khm_size cb_buf, wchar_t * buf);
+
+#endif
diff --git a/src/windows/identity/ui/htwnd.c b/src/windows/identity/ui/htwnd.c
index b7c0378668..a65ceceeed 100644
--- a/src/windows/identity/ui/htwnd.c
+++ b/src/windows/identity/ui/htwnd.c
@@ -1,1286 +1,1286 @@
-/*
-* Copyright (c) 2005 Massachusetts Institute of Technology
-*
-* Permission is hereby granted, free of charge, to any person
-* obtaining a copy of this software and associated documentation
-* files (the "Software"), to deal in the Software without
-* restriction, including without limitation the rights to use, copy,
-* modify, merge, publish, distribute, sublicense, and/or sell copies
-* of the Software, and to permit persons to whom the Software is
-* furnished to do so, subject to the following conditions:
-*
-* The above copyright notice and this permission notice shall be
-* included in all copies or substantial portions of the Software.
-*
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
-* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
-* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-* SOFTWARE.
-*/
-
-/* $Id$ */
-
-#include<khmapp.h>
-#include<crtdbg.h>
-
-ATOM khui_htwnd_cls;
-
-#define HTW_STYLE_NORMAL 0
-
-/* There are currently 4 style "bits" and 3 sizes, which means
- there can be 2^4*3=48 possible styles max. If someone is
- feeling adventurous you can slightly improve performance of
- the parser using this little fact. For now, I don't care.
- (hint: combine size and style bits to form a single number
- and use it as an index into the styles array)
-*/
-#define HTW_STYLE_MAX 48
-
-#define HTW_FORMAT_MAX 128
-
-#define HTW_TAB_MAX 8
-
-#define HTW_DEFAULT (-1)
-
-#define HTW_NORMAL_SIZE 8
-#define HTW_LARGE_SIZE 12
-#define HTW_HUGE_SIZE 20
-
-/* font variant */
-#define FV_ABSOLUTE 0x10000000
-
-#define FV_ITALIC 0x00000002
-#define FV_UNDERLINE 0x00000004
-#define FV_STRIKEOUT 0x00000008
-#define FV_BOLD 0x00000010
-
-#define FV_NOITALIC 0x00020000
-#define FV_NOUNDERLINE 0x00040000
-#define FV_NOSTRIKEOUT 0x00080000
-#define FV_NOBOLD 0x00100000
-
-#define FV_NONE 0x00000000
-#define FV_MASK 0x0000001f
-
-#define HTW_LINK_ALLOC 8
-
-#define ALIGN_LEFT 0
-#define ALIGN_CENTER 1
-#define ALIGN_RIGHT 2
-
-struct tx_tbl_t {
- wchar_t * string;
- LONG value;
-}
-
-htw_color_table[] = {
- {L"black", RGB(0,0,0)},
- {L"white", RGB(255,255,255)},
- {L"red", RGB(255,0,0)},
- {L"green", RGB(0,255,0)},
- {L"blue", RGB(0,0,255)},
- {L"grey", RGB(128,128,128)}
-},
-
-htw_size_table[] = {
- {L"normal", HTW_NORMAL_SIZE},
- {L"large", HTW_LARGE_SIZE},
- {L"huge", HTW_HUGE_SIZE}
-},
-
-htw_align_table[] = {
- {L"left", ALIGN_LEFT},
- {L"center", ALIGN_CENTER},
- {L"right", ALIGN_RIGHT}
-};
-
-typedef struct khui_htwnd_style_t {
- LONG height;
- LONG variation; /* combination of FV_* */
-
- HFONT font;
-} khui_htwnd_style;
-
-typedef struct khui_format_t {
- int style_idx;
- COLORREF color;
-} khui_format;
-
-typedef struct format_stack_t {
- khui_format stack[HTW_FORMAT_MAX];
- int stack_top;
-} format_stack;
-
-typedef struct khui_htwnd_data_t {
- int id; /* control ID */
- int flags;
- wchar_t * text;
- int scroll_left;
- int scroll_top;
- int ext_width;
- int ext_height;
- COLORREF bk_color;
- HCURSOR hc_hand;
- int l_pixel_y;
-
- khui_htwnd_style styles[HTW_STYLE_MAX];
- int n_styles;
-
- khui_htwnd_link ** links;
- int n_links;
- int max_links;
- int active_link;
- int md_link;
-
- int tabs[HTW_TAB_MAX];
- int n_tabs;
-} khui_htwnd_data;
-
-static LONG table_lookup(struct tx_tbl_t * tbl, int n, wchar_t * v, int len)
-{
- int i;
-
- for(i=0; i<n; i++) {
- if(!_wcsnicmp(tbl[i].string, v, len))
- return tbl[i].value;
- }
-
- return -1;
-}
-
-static void clear_styles(khui_htwnd_data * d)
-{
- int i;
-
- for(i=0; i<d->n_styles; i++) {
- if(d->styles[i].font != NULL) {
- DeleteObject(d->styles[i].font);
- d->styles[i].font = NULL;
- }
- }
-
- d->n_styles = 0;
-}
-
-static void format_init(format_stack * s)
-{
- s->stack_top = -1;
- ZeroMemory(s->stack, sizeof(s->stack));
-}
-
-static khui_format * format_current(format_stack * s)
-{
- if(s->stack_top >= 0)
- return &(s->stack[s->stack_top]);
- else
- return NULL;
-}
-
-static int format_style(format_stack * s)
-{
- if(s->stack_top >= 0)
- return s->stack[s->stack_top].style_idx;
- else
- return 0;
-}
-
-static COLORREF format_color(format_stack * s)
-{
- if(s->stack_top >= 0)
- return s->stack[s->stack_top].color;
- else
- return 0;
-}
-
-static int format_level(format_stack * s)
-{
- return s->stack_top;
-}
-
-static void format_unwind(format_stack * s, int level)
-{
- s->stack_top = level;
-}
-
-static void format_push(format_stack * s, khui_htwnd_data * d, LONG height, LONG variation, COLORREF color)
-{
- int i;
- khui_format * top;
- khui_htwnd_style * style;
-
- _ASSERT(s->stack_top < (HTW_FORMAT_MAX-1));
-
- /* formatting is additive unless FV_NORMAL is set in variation */
- top = format_current(s);
- if(top) {
- style = &(d->styles[top->style_idx]);
- if(height == HTW_DEFAULT)
- height = style->height;
-
- if(variation == HTW_DEFAULT)
- variation = style->variation;
- else if(!(variation & FV_ABSOLUTE))
- variation |= style->variation;
-
- if(color == HTW_DEFAULT)
- color = top->color;
- }
-
- variation &= ~FV_ABSOLUTE;
- variation ^= variation & (variation>>16);
- variation &= FV_MASK;
-
- /* now look for an existing style that matches the requested one */
- for(i=0; i<d->n_styles; i++) {
- style = &(d->styles[i]);
-
- if(style->height == height &&
- style->variation == variation)
- break;
- }
-
- s->stack_top++;
-
- if(i<d->n_styles) {
- s->stack[s->stack_top].style_idx = i;
- } else {
- if(d->n_styles == HTW_STYLE_MAX) {
- s->stack[s->stack_top].style_idx = 0;
- } else {
- s->stack[s->stack_top].style_idx = d->n_styles;
- d->styles[d->n_styles].font = NULL;
- d->styles[d->n_styles].height = height;
- d->styles[d->n_styles].variation = variation;
- d->n_styles++;
- }
- }
- s->stack[s->stack_top].color = color;
-}
-
-static void format_pop(format_stack * s) {
- if(s->stack_top >= 0)
- s->stack_top--;
-}
-
-static wchar_t * token_end(wchar_t * s) {
- while(iswalnum(*s) || *s == L'/')
- s++;
- return s;
-}
-
-static wchar_t * skip_ws(wchar_t * s) {
- while(iswspace(*s))
- s++;
- return s;
-}
-
-/* s points to something like " = \"value\""
- start and len will point to the start and
- length of value. return value will point to the
- character following the last double quote. */
-static wchar_t * read_attr(wchar_t * s, wchar_t ** start, int * len)
-{
- wchar_t *e;
-
- *start = NULL;
- *len = 0;
-
- do {
- s = skip_ws(s);
- if(*s != L'=')
- break;
- s = skip_ws(++s);
- if(*s != L'"')
- break;
- e = wcschr(++s, L'"');
- if(!e)
- break;
-
- *start = s;
- *len = (int) (e - s);
-
- s = e + 1;
- } while(FALSE);
-
- return s;
-}
-
-/*
-We currently support the following tags:
-
-<a [id="string"] [param="paramstring"]>link text</a>
-<b>foo</b>
-<u>foo</u>
-<i>foo</i>
-
-<font [color="(color)"] [size="normal|large|huge|(point size)"]>foo</font>
- (color)=black|white|red|green|blue|grey
-<large>foo</large>
-<huge>foo</huge>
-
-<center>foo</center>
-<left>foo</left>
-<right>foo</right>
-
-<p [align="left|center|right"]>foo</p>
-<settab pos="(pos)">
-<tab>
-*/
-
-static int htw_parse_tag(
- wchar_t * start,
- wchar_t ** end,
- int * align,
- khui_htwnd_data * d,
- format_stack * s,
- PPOINT p_abs,
- PPOINT p_rel,
- int lh,
- BOOL dry_run)
-{
- wchar_t * c;
- int n = 0;
-
- /* start initially points to the starting '<' */
- c = token_end(++start);
-
- if(!_wcsnicmp(start,L"a",c-start)) {
- /* start of an 'a' tag */
- wchar_t * id_start = NULL;
- int id_len = 0;
- wchar_t * param_start = NULL;
- int param_len = 0;
-
- /* We don't need to parse the link
- if it is just a dry run */
- if(dry_run) {
- format_push(s, d, HTW_DEFAULT, HTW_DEFAULT, RGB(0,0,255));
- *end = wcschr(start, L'>');
- return FALSE;
- }
-
- while(c && *c && *c != L'>') {
- wchar_t * e;
-
- c = skip_ws(c);
- e = token_end(c);
-
- if(c==e)
- break;
-
- if(!_wcsnicmp(c,L"id",e-c)) {
- c = read_attr(e, &id_start, &id_len);
- } else if(!_wcsnicmp(c,L"param",e-c)) {
- c = read_attr(e, &param_start, &param_len);
- }
- }
-
- if(d->active_link == d->n_links)
- format_push(s,d, HTW_DEFAULT, FV_UNDERLINE, RGB(0,0,255));
- else
- format_push(s,d, HTW_DEFAULT, FV_NONE, RGB(0,0,255));
-
- {
- khui_htwnd_link * l;
-
- if(!d->links) {
- d->links = PMALLOC(sizeof(khui_htwnd_link *) * HTW_LINK_ALLOC);
- ZeroMemory(d->links, sizeof(khui_htwnd_link *) * HTW_LINK_ALLOC);
- d->max_links = HTW_LINK_ALLOC;
- d->n_links = 0;
- }
-
- if(d->n_links >= d->max_links) {
- khui_htwnd_link ** ll;
- int n_new;
-
- n_new = UBOUNDSS(d->n_links + 1, HTW_LINK_ALLOC, HTW_LINK_ALLOC);
-
- ll = PMALLOC(sizeof(khui_htwnd_link *) * n_new);
- ZeroMemory(ll, sizeof(khui_htwnd_link *) * n_new);
- memcpy(ll, d->links, sizeof(khui_htwnd_link *) * d->max_links);
- PFREE(d->links);
- d->links = ll;
- d->max_links = n_new;
- }
-
- l = d->links[d->n_links];
- if(!l) {
- l = PMALLOC(sizeof(khui_htwnd_link));
- d->links[d->n_links] = l;
- }
-
- l->id = id_start;
- l->id_len = id_len;
- l->param = param_start;
- l->param_len = param_len;
-
- l->r.left = p_abs->x;
- l->r.top = p_abs->y;
-
- d->n_links++;
- }
-
- } else if(!_wcsnicmp(start, L"/a", c - start)) {
- khui_htwnd_link * l;
-
- c = wcschr(c,L'>');
- if(!c)
- c = c + wcslen(c);
-
- format_pop(s);
-
- if(!dry_run) {
- l = d->links[d->n_links - 1]; /* last link */
- l->r.right = p_abs->x;
- l->r.bottom = p_abs->y + lh;
- }
- } else if(!_wcsnicmp(start, L"p", c - start)) {
- wchar_t * e;
- wchar_t * align_s = NULL;
- int align_len = 0;
-
- c = skip_ws(c);
- e = token_end(c);
-
- if(c != e && !_wcsnicmp(c,L"align",e-c)) {
- c = read_attr(e, &align_s, &align_len);
- }
-
- c = wcschr(c, L'>');
- if(!c)
- c = c + wcslen(c);
-
-
- if(align_s)
- *align = table_lookup(htw_align_table, ARRAYLENGTH(htw_align_table), align_s, align_len);
- else
- *align = ALIGN_LEFT;
-
- n = 1;
- } else if(!_wcsnicmp(start, L"b", c - start)) {
- format_push(s,d, HTW_DEFAULT, FV_BOLD, HTW_DEFAULT);
- } else if(!_wcsnicmp(start, L"/b", c - start)) {
- format_pop(s);
- } else if(!_wcsnicmp(start, L"u", c - start)) {
- format_push(s,d, HTW_DEFAULT, FV_UNDERLINE, HTW_DEFAULT);
- } else if(!_wcsnicmp(start, L"/u", c - start)) {
- format_pop(s);
- } else if(!_wcsnicmp(start, L"i", c - start)) {
- format_push(s,d, HTW_DEFAULT, FV_ITALIC, HTW_DEFAULT);
- } else if(!_wcsnicmp(start, L"/i", c - start)) {
- format_pop(s);
- } else if(!_wcsnicmp(start, L"large", c - start)) {
- format_push(s,d,-MulDiv(HTW_LARGE_SIZE, d->l_pixel_y, 72), HTW_DEFAULT, HTW_DEFAULT);
- } else if(!_wcsnicmp(start, L"/large", c - start)) {
- format_pop(s);
- } else if(!_wcsnicmp(start, L"huge", c - start)) {
- format_push(s,d,-MulDiv(HTW_HUGE_SIZE, d->l_pixel_y, 72), HTW_DEFAULT, HTW_DEFAULT);
- } else if(!_wcsnicmp(start, L"/huge", c - start)) {
- format_pop(s);
- } else if(!_wcsnicmp(start, L"center", c - start)) {
- c = wcschr(c, L'>');
- if(!c)
- c = c + wcslen(c);
- *align = ALIGN_CENTER;
- n = 1;
- } else if(!_wcsnicmp(start, L"left", c - start) ||
- !_wcsnicmp(start, L"p", c - start))
- {
- c = wcschr(c, L'>');
- if(!c)
- c = c + wcslen(c);
- *align = ALIGN_LEFT;
- n = 1;
- } else if(!_wcsnicmp(start, L"right", c - start)) {
- c = wcschr(c, L'>');
- if(!c)
- c = c + wcslen(c);
- *align = ALIGN_RIGHT;
- n = 1;
- } else if(!_wcsnicmp(start, L"/center", c - start) ||
- !_wcsnicmp(start, L"/left", c - start) ||
- !_wcsnicmp(start, L"/right", c - start) ||
- !_wcsnicmp(start, L"/p", c - start)) {
- c = wcschr(c, L'>');
- if(!c)
- c = c + wcslen(c);
- *align = ALIGN_LEFT;
- n = 1;
- } else if(!_wcsnicmp(start, L"font", c - start)) {
- wchar_t * color_s = NULL;
- int color_len = 0;
- wchar_t * size_s = NULL;
- int size_len = 0;
- LONG color = HTW_DEFAULT;
- LONG h = HTW_DEFAULT;
-
- while(c && *c && *c != L'>') {
- wchar_t * e;
-
- c = skip_ws(c);
- e = token_end(c);
-
- if(c==e)
- break;
-
- if(!_wcsnicmp(c,L"color",e-c)) {
- c = read_attr(e, &color_s, &color_len);
- } else if(!_wcsnicmp(c,L"size",e-c)) {
- c = read_attr(e, &size_s, &size_len);
- }
- }
-
- if(color_s)
- color = table_lookup(htw_color_table, ARRAYLENGTH(htw_color_table), color_s, color_len);
- if(size_s) {
- h = table_lookup(htw_size_table, ARRAYLENGTH(htw_size_table), size_s, size_len);
- if(h)
- h = -MulDiv(h, d->l_pixel_y, 72);
- else
- h = -MulDiv(HTW_NORMAL_SIZE, d->l_pixel_y, 72);
- }
-
- format_push(s,d,h,HTW_DEFAULT,color);
- } else if(!_wcsnicmp(start, L"/font", c - start)) {
- format_pop(s);
- } else if(!_wcsnicmp(start, L"settab", c - start)) {
- wchar_t * e;
- wchar_t * pos_s = NULL;
- int pos_len;
-
- c = skip_ws(c);
- e = token_end(c);
-
- if(c != e && !_wcsnicmp(c,L"pos",e-c)) {
- c = read_attr(e, &pos_s, &pos_len);
- }
-
- c = wcschr(c, L'>');
- if(!c)
- c = c + wcslen(c);
-
- if(pos_s && d->n_tabs < HTW_TAB_MAX && !dry_run) {
- wchar_t * dummy;
- LONG bu;
- int bx;
- int dx;
-
- bu = GetDialogBaseUnits();
- bx = LOWORD(bu);
-
- dx = wcstol(pos_s, &dummy, 10);
-
- d->tabs[d->n_tabs++] = MulDiv(dx, bx, 4);
- }
- } else if(!_wcsnicmp(start, L"tab", c - start)) {
- int i;
-
- if(!dry_run) {
- for(i=0; i < d->n_tabs; i++) {
- if(d->tabs[i] > p_rel->x) {
- p_rel->x = d->tabs[i];
- break;
- }
- }
- }
- }
-
- if(*c)
- c++;
- *end = c;
-
- return n;
-}
-
-static void htw_assert_style(HDC hdc, khui_htwnd_data * d, int style)
-{
- LOGFONT lf;
-
- if(d->styles[style].font)
- return;
-
- /*TODO: we need select different fonts depending on system locale */
- lf.lfHeight = d->styles[style].height; //-MulDiv(8, GetDeviceCaps(hdc, LOGPIXELSY), 72);
- lf.lfWidth = 0;
- lf.lfEscapement = 0;
- lf.lfOrientation = 0;
- lf.lfWeight = (d->styles[style].variation & FV_BOLD)? FW_BOLD: FW_NORMAL;
- lf.lfItalic = !!(d->styles[style].variation & FV_ITALIC);
- lf.lfUnderline = !!(d->styles[style].variation & FV_UNDERLINE);
- lf.lfStrikeOut = !!(d->styles[style].variation & FV_STRIKEOUT);
- lf.lfCharSet = DEFAULT_CHARSET;
- lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
- lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
- lf.lfQuality = DEFAULT_QUALITY;
- lf.lfPitchAndFamily = DEFAULT_PITCH;
-
- LoadString(khm_hInstance, IDS_DEFAULT_FONT, lf.lfFaceName, ARRAYLENGTH(lf.lfFaceName));
-
- d->styles[style].font = CreateFontIndirect(&lf);
-}
-
-static LRESULT htw_paint(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
- PAINTSTRUCT ps;
- HBRUSH hbk;
- khui_htwnd_data * d;
- RECT r;
- SIZE s;
- HDC hdc;
- wchar_t * text;
- format_stack s_stack;
-
- int align;
- int y;
- wchar_t * par_start;
- int ext_width = 0;
- int ext_height = 0;
-
- d = (khui_htwnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, 0);
-
- if(!GetUpdateRect(hwnd, &r, !(d->flags & KHUI_HTWND_TRANSPARENT)))
- return 0;
-
- if(d->text == NULL)
- return 0;
-
- text = d->text;
-
- hdc = BeginPaint(hwnd, &ps);
-
- GetClientRect(hwnd, &r);
-
-#ifdef DRAW_HTWND_CLIENT_EDGE
- /* for the moment, we are skipping on the client edge. */
- if(d->flags & KHUI_HTWND_CLIENTEDGE)
- DrawEdge(hdc, &r, EDGE_SUNKEN, BF_ADJUST | BF_RECT | BF_FLAT);
-#endif
-
- hbk = GetSysColorBrush(COLOR_WINDOW);
- FillRect(hdc, &r, hbk);
- hbk = NULL; /* We don't need to destroy system
- brushes */
-
- /* push the default format */
- format_init(&s_stack);
-
- d->l_pixel_y = GetDeviceCaps(hdc, LOGPIXELSY);
- format_push(&s_stack,d, -MulDiv(HTW_NORMAL_SIZE, d->l_pixel_y, 72), FV_NONE, RGB(0,0,0));
-
- y = r.top - d->scroll_top;
-
- par_start = text;
-
- align = ALIGN_LEFT;
-
- SetTextAlign(hdc, TA_TOP | TA_LEFT | TA_NOUPDATECP);
- if(d->flags & KHUI_HTWND_TRANSPARENT)
- SetBkMode(hdc, TRANSPARENT);
-
- d->n_links = 0;
- d->n_tabs = 0;
-
- while(*par_start) {
- wchar_t * p = par_start;
- wchar_t * c = NULL;
- int p_width = 0;
- int s_start;
- int l_height = 0;
- int x = 0;
- POINT pt;
- POINT pt_rel;
-
- s_start = format_level(&s_stack);
-
- /* begin dry run */
- while(*p) {
- if(*p == L'<') {
- int talign = -1;
- int n = htw_parse_tag(p,&c,&talign,d,&s_stack,NULL,NULL,0,TRUE);
-
- if(n && p_width)
- break;
-
- p = c;
-
- if(n && talign >= 0)
- align = talign;
- } else {
- HFONT hfold;
- c = wcschr(p, L'<');
- if(!c)
- c = p + wcslen(p);
-
- htw_assert_style(hdc, d, format_style(&s_stack));
- hfold = SelectFont(hdc, d->styles[format_style(&s_stack)].font);
- GetTextExtentPoint32(hdc, p, (int)(c - p), &s);
- SelectFont(hdc, hfold);
-
- p_width += s.cx;
- if(s.cy > l_height)
- l_height = s.cy;
-
- p = c;
- }
- }
-
- /* dry run ends */
-
- x = r.left - d->scroll_left;
-
- if(align == ALIGN_CENTER) {
- if (r.right - r.left > p_width)
- x += (r.right - r.left)/2 - p_width / 2;
- }
-
- else if(align == ALIGN_RIGHT) {
- if (r.right - r.left > p_width)
- x += (r.right - r.left) - p_width;
- }
-
- /* begin wet run */
- p = par_start;
- format_unwind(&s_stack, s_start); /* unwind format stack */
-
- p_width = 0;
-
- while(p && *p) {
- if(*p == L'<') {
- int talign = -1;
- int n;
-
- pt.x = x + p_width;
- pt.y = y;
- pt_rel.x = p_width;
- pt_rel.y = 0;
-
- n = htw_parse_tag(p, &c, &talign, d, &s_stack, &pt, &pt_rel, l_height, FALSE);
-
- if(n && p_width) {
- break;
- }
-
- p_width = pt_rel.x;
-
- p = c;
- if(n && talign >= 0)
- align = talign;
- } else {
- HFONT hfold;
- RECT rd;
-
- c = wcschr(p, L'<');
- if(!c)
- c = p + wcslen(p);
-
- htw_assert_style(hdc, d, format_style(&s_stack));
- hfold = SelectFont(hdc, d->styles[format_style(&s_stack)].font);
- SetTextColor(hdc, format_color(&s_stack));
-
- GetTextExtentPoint32(hdc, p, (int)(c - p), &s);
- rd.left = x + p_width;
- rd.top = y;
- rd.right = rd.left + s.cx;
- rd.bottom = rd.top + l_height;
-
- DrawText(hdc, p, (int)(c - p), &rd,
- DT_BOTTOM | DT_LEFT | DT_SINGLELINE | DT_NOPREFIX);
-
- p_width += s.cx;
-
- SelectFont(hdc, hfold);
- p = c;
- }
- }
-
- if (p_width > ext_width)
- ext_width = p_width;
-
- y += l_height;
- par_start = p;
- }
-
- if (y > ext_height)
- ext_height = y;
-
- EndPaint(hwnd, &ps);
-
- if (d->ext_width < ext_width ||
- d->ext_height < ext_height) {
- SCROLLINFO si;
- LONG l;
-
- /* the extents need to be adjusted. But first check if we
- have exactly the right scroll bars we need. */
- if ((ext_width > (r.right - r.left) &&
- !(d->flags & KHUI_HTWND_HSCROLL)) ||
- (ext_height > (r.bottom - r.top) &&
- !(d->flags & KHUI_HTWND_VSCROLL)) ||
-
- (ext_width <= (r.right - r.left) &&
- (d->flags & KHUI_HTWND_HSCROLL)) ||
- (ext_height <= (r.bottom - r.top) &&
- (d->flags & KHUI_HTWND_VSCROLL))) {
-
- /* need to add scroll bars */
- if (ext_width > (r.right - r.left))
- d->flags |= KHUI_HTWND_HSCROLL;
- else
- d->flags &= ~KHUI_HTWND_HSCROLL;
-
- if (ext_height > (r.bottom - r.top))
- d->flags |= KHUI_HTWND_VSCROLL;
- else
- d->flags &= ~KHUI_HTWND_VSCROLL;
-
- l = GetWindowLongPtr(hwnd, GWL_STYLE);
- l &= ~(WS_HSCROLL | WS_VSCROLL);
-
- l |= ((d->flags & KHUI_HTWND_HSCROLL) ? WS_HSCROLL : 0) |
- ((d->flags & KHUI_HTWND_VSCROLL) ? WS_VSCROLL : 0);
-
- SetWindowLongPtr(hwnd, GWL_STYLE, l);
-
- InvalidateRect(hwnd, NULL, FALSE);
- /* since the client area changed, we do another redraw
- before updating the scroll bar positions. */
- } else {
- d->ext_width = ext_width;
- d->ext_height = ext_height;
-
- if (d->flags & KHUI_HTWND_HSCROLL) {
- ZeroMemory(&si, sizeof(si));
- si.cbSize = sizeof(si);
- si.fMask = SIF_ALL | SIF_DISABLENOSCROLL;
- si.nMin = 0;
- si.nMax = ext_width;
- si.nPage = r.right - r.left;
- si.nPos = d->scroll_left;
-
- SetScrollInfo(hwnd, SB_HORZ, &si, TRUE);
- }
-
- if (d->flags & KHUI_HTWND_VSCROLL) {
- ZeroMemory(&si, sizeof(si));
- si.cbSize = sizeof(si);
- si.fMask = SIF_ALL | SIF_DISABLENOSCROLL;
- si.nMin = 0;
- si.nMax = ext_height;
- si.nPage = r.bottom - r.top;
- si.nPos = d->scroll_top;
-
- SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
- }
- }
- }
-
- return 0;
-}
-
-LRESULT CALLBACK khui_htwnd_proc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam
- )
-{
- switch(uMsg) {
- case WM_CREATE:
- {
- CREATESTRUCT * cs;
- khui_htwnd_data * d;
- size_t cbsize;
-
- cs = (CREATESTRUCT *) lParam;
-
- d = PMALLOC(sizeof(*d));
- ZeroMemory(d, sizeof(*d));
-
- if(cs->dwExStyle & WS_EX_TRANSPARENT) {
- d->flags |= KHUI_HTWND_TRANSPARENT;
- }
- if(cs->dwExStyle & WS_EX_CLIENTEDGE) {
- d->flags |= KHUI_HTWND_CLIENTEDGE;
- }
- if(cs->style & WS_HSCROLL) {
- d->flags |= KHUI_HTWND_HSCROLL;
- }
- if(cs->style & WS_VSCROLL) {
- d->flags |= KHUI_HTWND_VSCROLL;
- }
- d->id = (int)(INT_PTR) cs->hMenu;
-
- d->active_link = -1;
- d->bk_color = RGB(255,255,255);
- d->hc_hand = LoadCursor(NULL, IDC_HAND);
-
- if(SUCCEEDED(StringCbLength(cs->lpszName, KHUI_HTWND_MAXCB_TEXT, &cbsize))) {
- cbsize += sizeof(wchar_t);
- d->text = PMALLOC(cbsize);
- StringCbCopy(d->text, cbsize, cs->lpszName);
- }
-
- /* this is just a flag to the WM_PAINT handler that the
- extents haven't been set yet. */
- d->ext_width = -1;
-
-#pragma warning(push)
-#pragma warning(disable: 4244)
- SetWindowLongPtr(hwnd, 0, (LONG_PTR) d);
-#pragma warning(pop)
-
- return 0;
- }
- break;
-
- case WM_SETTEXT:
- {
- wchar_t * newtext;
- size_t cbsize;
- khui_htwnd_data * d;
- BOOL rv;
-
- d = (khui_htwnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, 0);
- newtext = (wchar_t *) lParam;
-
- if(d->text) {
- PFREE(d->text);
- d->text = NULL;
- }
-
- if(SUCCEEDED(StringCbLength(newtext, KHUI_HTWND_MAXCB_TEXT, &cbsize))) {
- cbsize += sizeof(wchar_t);
- d->text = PMALLOC(cbsize);
- StringCbCopy(d->text, cbsize, newtext);
- rv = TRUE;
- } else
- rv = FALSE;
-
- clear_styles(d);
-
- d->ext_width = -1;
- d->scroll_left = 0;
- d->scroll_top = 0;
-
- InvalidateRect(hwnd, NULL, TRUE);
-
- return rv;
- }
- break;
-
- case WM_DESTROY:
- {
- khui_htwnd_data * d;
- int i;
-
- d = (khui_htwnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, 0);
- if(d->text)
- PFREE(d->text);
- d->text = 0;
-
- if(d->links) {
- for(i=0;i<d->max_links;i++) {
- if(d->links[i])
- PFREE(d->links[i]);
- }
- PFREE(d->links);
- }
-
- clear_styles(d);
-
- PFREE(d);
- }
- break;
-
- case WM_ERASEBKGND:
- {
- HDC hdc = (HDC) wParam;
- khui_htwnd_data * d;
- HBRUSH hbr;
- RECT r;
-
- d = (khui_htwnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, 0);
-
- GetClientRect(hwnd, &r);
- hbr = GetSysColorBrush(COLOR_WINDOW);
- FillRect(hdc, &r, hbr);
-
- /* no need to destroy the brush since it's a system
- brush. */
-
- return TRUE;
- }
-
- case WM_SIZE:
- {
- khui_htwnd_data * d;
-
- d = (khui_htwnd_data *) (LONG_PTR) GetWindowLongPtr(hwnd, 0);
-
- if (d) {
- d->ext_width = 0;
- d->ext_height = 0;
- }
- }
- return 0;
-
- case WM_PAINT:
- htw_paint(hwnd, uMsg, wParam, lParam);
- return 0;
-
- case WM_SETCURSOR:
- {
- khui_htwnd_data * d;
-
- if(hwnd != (HWND)wParam)
- break;
-
- d = (khui_htwnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, 0);
-
- if(d->active_link >= 0) {
- SetCursor(d->hc_hand);
- return TRUE;
- }
- }
- break;
-
- case WM_SETFOCUS:
- {
- khui_htwnd_data * d;
-
- d = (khui_htwnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, 0);
-
- d->flags |= KHUI_HTWND_FOCUS;
-
- InvalidateRect(hwnd, NULL, TRUE);
- }
- break;
-
- case WM_KILLFOCUS:
- {
- khui_htwnd_data * d;
-
- d = (khui_htwnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, 0);
-
- d->flags &= ~KHUI_HTWND_FOCUS;
-
- InvalidateRect(hwnd, NULL, TRUE);
- }
- break;
-
- case WM_LBUTTONDOWN:
- {
- khui_htwnd_data * d;
-
- d = (khui_htwnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, 0);
-
- d->md_link = d->active_link;
-
- SetCapture(hwnd);
- }
- break;
-
- case WM_LBUTTONUP:
- {
- khui_htwnd_data * d;
-
- d = (khui_htwnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, 0);
-
- if(d->md_link == d->active_link && d->md_link >= 0) {
- /* clicked */
- SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(d->id, BN_CLICKED), (LPARAM) d->links[d->md_link]);
- }
-
- ReleaseCapture();
- }
- break;
-
- case WM_HSCROLL:
- {
- khui_htwnd_data * d;
- int old_pos;
- int new_pos;
- int ext;
- SCROLLINFO si;
- RECT r;
-
- d = (khui_htwnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, 0);
-
- old_pos = new_pos = d->scroll_left;
- ext = d->ext_width;
-
- switch(LOWORD(wParam)) {
- case SB_THUMBPOSITION:
- case SB_ENDSCROLL:
- ZeroMemory(&si, sizeof(si));
- si.cbSize = sizeof(si);
- si.fMask = SIF_POS;
- GetScrollInfo(hwnd, SB_HORZ, &si);
- new_pos = si.nPos;
- break;
-
- case SB_THUMBTRACK:
- ZeroMemory(&si, sizeof(si));
- si.cbSize = sizeof(si);
- si.fMask = SIF_TRACKPOS;
- GetScrollInfo(hwnd, SB_HORZ, &si);
- new_pos = si.nTrackPos;
- break;
-
- case SB_LINELEFT:
- new_pos -= ext / 12; /* arbitrary unit */
- break;
-
- case SB_LINERIGHT:
- new_pos += ext / 12; /* arbitrary unit */
- break;
-
- case SB_PAGELEFT:
- GetClientRect(hwnd, &r);
- new_pos -= r.right - r.left;
- break;
-
- case SB_PAGERIGHT:
- GetClientRect(hwnd, &r);
- new_pos += r.right - r.left;
- break;
- }
-
- if (new_pos == old_pos)
- break;
-
- GetClientRect(hwnd, &r);
-
- if (new_pos > ext - (r.right - r.left))
- new_pos = ext - (r.right - r.left);
-
- if (new_pos < 0)
- new_pos = 0;
-
- if (new_pos == old_pos)
- break;
-
- ZeroMemory(&si, sizeof(si));
- si.cbSize = sizeof(si);
- si.fMask = SIF_POS;
- si.nPos = new_pos;
- SetScrollInfo(hwnd, SB_HORZ, &si, TRUE);
- /* note that Windows sometimes adjusts the position after
- setting it with SetScrollInfo. We have to look it up
- again to see what value it ended up at. */
- GetScrollInfo(hwnd, SB_HORZ, &si);
- new_pos = si.nPos;
-
- if (new_pos == old_pos)
- break;
-
- d->scroll_left = new_pos;
-
- ScrollWindow(hwnd, old_pos - new_pos, 0, NULL, NULL);
-
- return 0;
- }
- break;
-
- case WM_MOUSEMOVE:
- {
- khui_htwnd_data * d;
- int i;
- POINT p;
- int nl;
-
- d = (khui_htwnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, 0);
- p.x = GET_X_LPARAM(lParam) + d->scroll_left;
- p.y = GET_Y_LPARAM(lParam) + d->scroll_top;
-
- for(i=0; i<d->n_links; i++) {
- if(d->links && d->links[i] && PtInRect(&(d->links[i]->r), p))
- break;
- }
-
- if(i == d->n_links)
- nl = -1;
- else
- nl = i;
-
- if(d->active_link != nl) {
- if(d->active_link >= 0) {
- if(d->flags & KHUI_HTWND_TRANSPARENT) {
- HWND parent = GetParent(hwnd);
- if(parent) {
- RECT rdest = d->links[d->active_link]->r;
-
- MapWindowPoints(hwnd, parent, (LPPOINT) &rdest, 2);
- InvalidateRect(parent, &rdest, TRUE);
- }
- }
- /* although we are invalidating the rect before setting active_link,
- WM_PAINT will not be issued until wndproc returns */
- InvalidateRect(hwnd, &(d->links[d->active_link]->r), TRUE);
- }
- d->active_link = nl;
- if(d->active_link >= 0) {
- /* although we are invalidating the rect before setting active_link,
- WM_PAINT will not be issued until wndproc returns */
- if(d->flags & KHUI_HTWND_TRANSPARENT) {
- HWND parent = GetParent(hwnd);
- if(parent) {
- RECT rdest = d->links[d->active_link]->r;
-
- MapWindowPoints(hwnd, parent, (LPPOINT) &rdest, 2);
- InvalidateRect(parent, &rdest, TRUE);
- }
- }
- InvalidateRect(hwnd, &(d->links[d->active_link]->r), TRUE);
- }
- }
- }
- break;
- }
-
- return DefWindowProc(hwnd, uMsg,wParam,lParam);
-}
-
-void khm_register_htwnd_class(void)
-{
- WNDCLASSEX wcx;
-
- wcx.cbSize = sizeof(wcx);
- wcx.style = CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
- wcx.lpfnWndProc = khui_htwnd_proc;
- wcx.cbClsExtra = 0;
- wcx.cbWndExtra = sizeof(LONG_PTR);
- wcx.hInstance = khm_hInstance;
- wcx.hIcon = NULL;
- wcx.hCursor = LoadCursor((HINSTANCE) NULL, IDC_ARROW);
- wcx.hbrBackground = CreateSolidBrush(RGB(255,255,255));
- wcx.lpszMenuName = NULL;
- wcx.lpszClassName = KHUI_HTWND_CLASS;
- wcx.hIconSm = NULL;
-
- khui_htwnd_cls = RegisterClassEx(&wcx);
-}
-
-void khm_unregister_htwnd_class(void)
-{
- UnregisterClass(MAKEINTATOM(khui_htwnd_cls), khm_hInstance);
-}
-
-HWND khm_create_htwnd(HWND parent, LPWSTR text, int x, int y, int width, int height, DWORD ex_style, DWORD style)
-{
-
- return CreateWindowEx(
- ex_style,
- MAKEINTATOM(khui_htwnd_cls),
- text,
- style | WS_CHILD,
- x,y,width,height,
- parent,
- (HMENU) KHUI_HTWND_CTLID,
- khm_hInstance,
- NULL);
-}
+/*
+* Copyright (c) 2005 Massachusetts Institute of Technology
+*
+* Permission is hereby granted, free of charge, to any person
+* obtaining a copy of this software and associated documentation
+* files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy,
+* modify, merge, publish, distribute, sublicense, and/or sell copies
+* of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be
+* included in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*/
+
+/* $Id$ */
+
+#include<khmapp.h>
+#include<crtdbg.h>
+
+ATOM khui_htwnd_cls;
+
+#define HTW_STYLE_NORMAL 0
+
+/* There are currently 4 style "bits" and 3 sizes, which means
+ there can be 2^4*3=48 possible styles max. If someone is
+ feeling adventurous you can slightly improve performance of
+ the parser using this little fact. For now, I don't care.
+ (hint: combine size and style bits to form a single number
+ and use it as an index into the styles array)
+*/
+#define HTW_STYLE_MAX 48
+
+#define HTW_FORMAT_MAX 128
+
+#define HTW_TAB_MAX 8
+
+#define HTW_DEFAULT (-1)
+
+#define HTW_NORMAL_SIZE 8
+#define HTW_LARGE_SIZE 12
+#define HTW_HUGE_SIZE 20
+
+/* font variant */
+#define FV_ABSOLUTE 0x10000000
+
+#define FV_ITALIC 0x00000002
+#define FV_UNDERLINE 0x00000004
+#define FV_STRIKEOUT 0x00000008
+#define FV_BOLD 0x00000010
+
+#define FV_NOITALIC 0x00020000
+#define FV_NOUNDERLINE 0x00040000
+#define FV_NOSTRIKEOUT 0x00080000
+#define FV_NOBOLD 0x00100000
+
+#define FV_NONE 0x00000000
+#define FV_MASK 0x0000001f
+
+#define HTW_LINK_ALLOC 8
+
+#define ALIGN_LEFT 0
+#define ALIGN_CENTER 1
+#define ALIGN_RIGHT 2
+
+struct tx_tbl_t {
+ wchar_t * string;
+ LONG value;
+}
+
+htw_color_table[] = {
+ {L"black", RGB(0,0,0)},
+ {L"white", RGB(255,255,255)},
+ {L"red", RGB(255,0,0)},
+ {L"green", RGB(0,255,0)},
+ {L"blue", RGB(0,0,255)},
+ {L"grey", RGB(128,128,128)}
+},
+
+htw_size_table[] = {
+ {L"normal", HTW_NORMAL_SIZE},
+ {L"large", HTW_LARGE_SIZE},
+ {L"huge", HTW_HUGE_SIZE}
+},
+
+htw_align_table[] = {
+ {L"left", ALIGN_LEFT},
+ {L"center", ALIGN_CENTER},
+ {L"right", ALIGN_RIGHT}
+};
+
+typedef struct khui_htwnd_style_t {
+ LONG height;
+ LONG variation; /* combination of FV_* */
+
+ HFONT font;
+} khui_htwnd_style;
+
+typedef struct khui_format_t {
+ int style_idx;
+ COLORREF color;
+} khui_format;
+
+typedef struct format_stack_t {
+ khui_format stack[HTW_FORMAT_MAX];
+ int stack_top;
+} format_stack;
+
+typedef struct khui_htwnd_data_t {
+ int id; /* control ID */
+ int flags;
+ wchar_t * text;
+ int scroll_left;
+ int scroll_top;
+ int ext_width;
+ int ext_height;
+ COLORREF bk_color;
+ HCURSOR hc_hand;
+ int l_pixel_y;
+
+ khui_htwnd_style styles[HTW_STYLE_MAX];
+ int n_styles;
+
+ khui_htwnd_link ** links;
+ int n_links;
+ int max_links;
+ int active_link;
+ int md_link;
+
+ int tabs[HTW_TAB_MAX];
+ int n_tabs;
+} khui_htwnd_data;
+
+static LONG table_lookup(struct tx_tbl_t * tbl, int n, wchar_t * v, int len)
+{
+ int i;
+
+ for(i=0; i<n; i++) {
+ if(!_wcsnicmp(tbl[i].string, v, len))
+ return tbl[i].value;
+ }
+
+ return -1;
+}
+
+static void clear_styles(khui_htwnd_data * d)
+{
+ int i;
+
+ for(i=0; i<d->n_styles; i++) {
+ if(d->styles[i].font != NULL) {
+ DeleteObject(d->styles[i].font);
+ d->styles[i].font = NULL;
+ }
+ }
+
+ d->n_styles = 0;
+}
+
+static void format_init(format_stack * s)
+{
+ s->stack_top = -1;
+ ZeroMemory(s->stack, sizeof(s->stack));
+}
+
+static khui_format * format_current(format_stack * s)
+{
+ if(s->stack_top >= 0)
+ return &(s->stack[s->stack_top]);
+ else
+ return NULL;
+}
+
+static int format_style(format_stack * s)
+{
+ if(s->stack_top >= 0)
+ return s->stack[s->stack_top].style_idx;
+ else
+ return 0;
+}
+
+static COLORREF format_color(format_stack * s)
+{
+ if(s->stack_top >= 0)
+ return s->stack[s->stack_top].color;
+ else
+ return 0;
+}
+
+static int format_level(format_stack * s)
+{
+ return s->stack_top;
+}
+
+static void format_unwind(format_stack * s, int level)
+{
+ s->stack_top = level;
+}
+
+static void format_push(format_stack * s, khui_htwnd_data * d, LONG height, LONG variation, COLORREF color)
+{
+ int i;
+ khui_format * top;
+ khui_htwnd_style * style;
+
+ _ASSERT(s->stack_top < (HTW_FORMAT_MAX-1));
+
+ /* formatting is additive unless FV_NORMAL is set in variation */
+ top = format_current(s);
+ if(top) {
+ style = &(d->styles[top->style_idx]);
+ if(height == HTW_DEFAULT)
+ height = style->height;
+
+ if(variation == HTW_DEFAULT)
+ variation = style->variation;
+ else if(!(variation & FV_ABSOLUTE))
+ variation |= style->variation;
+
+ if(color == HTW_DEFAULT)
+ color = top->color;
+ }
+
+ variation &= ~FV_ABSOLUTE;
+ variation ^= variation & (variation>>16);
+ variation &= FV_MASK;
+
+ /* now look for an existing style that matches the requested one */
+ for(i=0; i<d->n_styles; i++) {
+ style = &(d->styles[i]);
+
+ if(style->height == height &&
+ style->variation == variation)
+ break;
+ }
+
+ s->stack_top++;
+
+ if(i<d->n_styles) {
+ s->stack[s->stack_top].style_idx = i;
+ } else {
+ if(d->n_styles == HTW_STYLE_MAX) {
+ s->stack[s->stack_top].style_idx = 0;
+ } else {
+ s->stack[s->stack_top].style_idx = d->n_styles;
+ d->styles[d->n_styles].font = NULL;
+ d->styles[d->n_styles].height = height;
+ d->styles[d->n_styles].variation = variation;
+ d->n_styles++;
+ }
+ }
+ s->stack[s->stack_top].color = color;
+}
+
+static void format_pop(format_stack * s) {
+ if(s->stack_top >= 0)
+ s->stack_top--;
+}
+
+static wchar_t * token_end(wchar_t * s) {
+ while(iswalnum(*s) || *s == L'/')
+ s++;
+ return s;
+}
+
+static wchar_t * skip_ws(wchar_t * s) {
+ while(iswspace(*s))
+ s++;
+ return s;
+}
+
+/* s points to something like " = \"value\""
+ start and len will point to the start and
+ length of value. return value will point to the
+ character following the last double quote. */
+static wchar_t * read_attr(wchar_t * s, wchar_t ** start, int * len)
+{
+ wchar_t *e;
+
+ *start = NULL;
+ *len = 0;
+
+ do {
+ s = skip_ws(s);
+ if(*s != L'=')
+ break;
+ s = skip_ws(++s);
+ if(*s != L'"')
+ break;
+ e = wcschr(++s, L'"');
+ if(!e)
+ break;
+
+ *start = s;
+ *len = (int) (e - s);
+
+ s = e + 1;
+ } while(FALSE);
+
+ return s;
+}
+
+/*
+We currently support the following tags:
+
+<a [id="string"] [param="paramstring"]>link text</a>
+<b>foo</b>
+<u>foo</u>
+<i>foo</i>
+
+<font [color="(color)"] [size="normal|large|huge|(point size)"]>foo</font>
+ (color)=black|white|red|green|blue|grey
+<large>foo</large>
+<huge>foo</huge>
+
+<center>foo</center>
+<left>foo</left>
+<right>foo</right>
+
+<p [align="left|center|right"]>foo</p>
+<settab pos="(pos)">
+<tab>
+*/
+
+static int htw_parse_tag(
+ wchar_t * start,
+ wchar_t ** end,
+ int * align,
+ khui_htwnd_data * d,
+ format_stack * s,
+ PPOINT p_abs,
+ PPOINT p_rel,
+ int lh,
+ BOOL dry_run)
+{
+ wchar_t * c;
+ int n = 0;
+
+ /* start initially points to the starting '<' */
+ c = token_end(++start);
+
+ if(!_wcsnicmp(start,L"a",c-start)) {
+ /* start of an 'a' tag */
+ wchar_t * id_start = NULL;
+ int id_len = 0;
+ wchar_t * param_start = NULL;
+ int param_len = 0;
+
+ /* We don't need to parse the link
+ if it is just a dry run */
+ if(dry_run) {
+ format_push(s, d, HTW_DEFAULT, HTW_DEFAULT, RGB(0,0,255));
+ *end = wcschr(start, L'>');
+ return FALSE;
+ }
+
+ while(c && *c && *c != L'>') {
+ wchar_t * e;
+
+ c = skip_ws(c);
+ e = token_end(c);
+
+ if(c==e)
+ break;
+
+ if(!_wcsnicmp(c,L"id",e-c)) {
+ c = read_attr(e, &id_start, &id_len);
+ } else if(!_wcsnicmp(c,L"param",e-c)) {
+ c = read_attr(e, &param_start, &param_len);
+ }
+ }
+
+ if(d->active_link == d->n_links)
+ format_push(s,d, HTW_DEFAULT, FV_UNDERLINE, RGB(0,0,255));
+ else
+ format_push(s,d, HTW_DEFAULT, FV_NONE, RGB(0,0,255));
+
+ {
+ khui_htwnd_link * l;
+
+ if(!d->links) {
+ d->links = PMALLOC(sizeof(khui_htwnd_link *) * HTW_LINK_ALLOC);
+ ZeroMemory(d->links, sizeof(khui_htwnd_link *) * HTW_LINK_ALLOC);
+ d->max_links = HTW_LINK_ALLOC;
+ d->n_links = 0;
+ }
+
+ if(d->n_links >= d->max_links) {
+ khui_htwnd_link ** ll;
+ int n_new;
+
+ n_new = UBOUNDSS(d->n_links + 1, HTW_LINK_ALLOC, HTW_LINK_ALLOC);
+
+ ll = PMALLOC(sizeof(khui_htwnd_link *) * n_new);
+ ZeroMemory(ll, sizeof(khui_htwnd_link *) * n_new);
+ memcpy(ll, d->links, sizeof(khui_htwnd_link *) * d->max_links);
+ PFREE(d->links);
+ d->links = ll;
+ d->max_links = n_new;
+ }
+
+ l = d->links[d->n_links];
+ if(!l) {
+ l = PMALLOC(sizeof(khui_htwnd_link));
+ d->links[d->n_links] = l;
+ }
+
+ l->id = id_start;
+ l->id_len = id_len;
+ l->param = param_start;
+ l->param_len = param_len;
+
+ l->r.left = p_abs->x;
+ l->r.top = p_abs->y;
+
+ d->n_links++;
+ }
+
+ } else if(!_wcsnicmp(start, L"/a", c - start)) {
+ khui_htwnd_link * l;
+
+ c = wcschr(c,L'>');
+ if(!c)
+ c = c + wcslen(c);
+
+ format_pop(s);
+
+ if(!dry_run) {
+ l = d->links[d->n_links - 1]; /* last link */
+ l->r.right = p_abs->x;
+ l->r.bottom = p_abs->y + lh;
+ }
+ } else if(!_wcsnicmp(start, L"p", c - start)) {
+ wchar_t * e;
+ wchar_t * align_s = NULL;
+ int align_len = 0;
+
+ c = skip_ws(c);
+ e = token_end(c);
+
+ if(c != e && !_wcsnicmp(c,L"align",e-c)) {
+ c = read_attr(e, &align_s, &align_len);
+ }
+
+ c = wcschr(c, L'>');
+ if(!c)
+ c = c + wcslen(c);
+
+
+ if(align_s)
+ *align = table_lookup(htw_align_table, ARRAYLENGTH(htw_align_table), align_s, align_len);
+ else
+ *align = ALIGN_LEFT;
+
+ n = 1;
+ } else if(!_wcsnicmp(start, L"b", c - start)) {
+ format_push(s,d, HTW_DEFAULT, FV_BOLD, HTW_DEFAULT);
+ } else if(!_wcsnicmp(start, L"/b", c - start)) {
+ format_pop(s);
+ } else if(!_wcsnicmp(start, L"u", c - start)) {
+ format_push(s,d, HTW_DEFAULT, FV_UNDERLINE, HTW_DEFAULT);
+ } else if(!_wcsnicmp(start, L"/u", c - start)) {
+ format_pop(s);
+ } else if(!_wcsnicmp(start, L"i", c - start)) {
+ format_push(s,d, HTW_DEFAULT, FV_ITALIC, HTW_DEFAULT);
+ } else if(!_wcsnicmp(start, L"/i", c - start)) {
+ format_pop(s);
+ } else if(!_wcsnicmp(start, L"large", c - start)) {
+ format_push(s,d,-MulDiv(HTW_LARGE_SIZE, d->l_pixel_y, 72), HTW_DEFAULT, HTW_DEFAULT);
+ } else if(!_wcsnicmp(start, L"/large", c - start)) {
+ format_pop(s);
+ } else if(!_wcsnicmp(start, L"huge", c - start)) {
+ format_push(s,d,-MulDiv(HTW_HUGE_SIZE, d->l_pixel_y, 72), HTW_DEFAULT, HTW_DEFAULT);
+ } else if(!_wcsnicmp(start, L"/huge", c - start)) {
+ format_pop(s);
+ } else if(!_wcsnicmp(start, L"center", c - start)) {
+ c = wcschr(c, L'>');
+ if(!c)
+ c = c + wcslen(c);
+ *align = ALIGN_CENTER;
+ n = 1;
+ } else if(!_wcsnicmp(start, L"left", c - start) ||
+ !_wcsnicmp(start, L"p", c - start))
+ {
+ c = wcschr(c, L'>');
+ if(!c)
+ c = c + wcslen(c);
+ *align = ALIGN_LEFT;
+ n = 1;
+ } else if(!_wcsnicmp(start, L"right", c - start)) {
+ c = wcschr(c, L'>');
+ if(!c)
+ c = c + wcslen(c);
+ *align = ALIGN_RIGHT;
+ n = 1;
+ } else if(!_wcsnicmp(start, L"/center", c - start) ||
+ !_wcsnicmp(start, L"/left", c - start) ||
+ !_wcsnicmp(start, L"/right", c - start) ||
+ !_wcsnicmp(start, L"/p", c - start)) {
+ c = wcschr(c, L'>');
+ if(!c)
+ c = c + wcslen(c);
+ *align = ALIGN_LEFT;
+ n = 1;
+ } else if(!_wcsnicmp(start, L"font", c - start)) {
+ wchar_t * color_s = NULL;
+ int color_len = 0;
+ wchar_t * size_s = NULL;
+ int size_len = 0;
+ LONG color = HTW_DEFAULT;
+ LONG h = HTW_DEFAULT;
+
+ while(c && *c && *c != L'>') {
+ wchar_t * e;
+
+ c = skip_ws(c);
+ e = token_end(c);
+
+ if(c==e)
+ break;
+
+ if(!_wcsnicmp(c,L"color",e-c)) {
+ c = read_attr(e, &color_s, &color_len);
+ } else if(!_wcsnicmp(c,L"size",e-c)) {
+ c = read_attr(e, &size_s, &size_len);
+ }
+ }
+
+ if(color_s)
+ color = table_lookup(htw_color_table, ARRAYLENGTH(htw_color_table), color_s, color_len);
+ if(size_s) {
+ h = table_lookup(htw_size_table, ARRAYLENGTH(htw_size_table), size_s, size_len);
+ if(h)
+ h = -MulDiv(h, d->l_pixel_y, 72);
+ else
+ h = -MulDiv(HTW_NORMAL_SIZE, d->l_pixel_y, 72);
+ }
+
+ format_push(s,d,h,HTW_DEFAULT,color);
+ } else if(!_wcsnicmp(start, L"/font", c - start)) {
+ format_pop(s);
+ } else if(!_wcsnicmp(start, L"settab", c - start)) {
+ wchar_t * e;
+ wchar_t * pos_s = NULL;
+ int pos_len;
+
+ c = skip_ws(c);
+ e = token_end(c);
+
+ if(c != e && !_wcsnicmp(c,L"pos",e-c)) {
+ c = read_attr(e, &pos_s, &pos_len);
+ }
+
+ c = wcschr(c, L'>');
+ if(!c)
+ c = c + wcslen(c);
+
+ if(pos_s && d->n_tabs < HTW_TAB_MAX && !dry_run) {
+ wchar_t * dummy;
+ LONG bu;
+ int bx;
+ int dx;
+
+ bu = GetDialogBaseUnits();
+ bx = LOWORD(bu);
+
+ dx = wcstol(pos_s, &dummy, 10);
+
+ d->tabs[d->n_tabs++] = MulDiv(dx, bx, 4);
+ }
+ } else if(!_wcsnicmp(start, L"tab", c - start)) {
+ int i;
+
+ if(!dry_run) {
+ for(i=0; i < d->n_tabs; i++) {
+ if(d->tabs[i] > p_rel->x) {
+ p_rel->x = d->tabs[i];
+ break;
+ }
+ }
+ }
+ }
+
+ if(*c)
+ c++;
+ *end = c;
+
+ return n;
+}
+
+static void htw_assert_style(HDC hdc, khui_htwnd_data * d, int style)
+{
+ LOGFONT lf;
+
+ if(d->styles[style].font)
+ return;
+
+ /*TODO: we need select different fonts depending on system locale */
+ lf.lfHeight = d->styles[style].height; //-MulDiv(8, GetDeviceCaps(hdc, LOGPIXELSY), 72);
+ lf.lfWidth = 0;
+ lf.lfEscapement = 0;
+ lf.lfOrientation = 0;
+ lf.lfWeight = (d->styles[style].variation & FV_BOLD)? FW_BOLD: FW_NORMAL;
+ lf.lfItalic = !!(d->styles[style].variation & FV_ITALIC);
+ lf.lfUnderline = !!(d->styles[style].variation & FV_UNDERLINE);
+ lf.lfStrikeOut = !!(d->styles[style].variation & FV_STRIKEOUT);
+ lf.lfCharSet = DEFAULT_CHARSET;
+ lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
+ lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
+ lf.lfQuality = DEFAULT_QUALITY;
+ lf.lfPitchAndFamily = DEFAULT_PITCH;
+
+ LoadString(khm_hInstance, IDS_DEFAULT_FONT, lf.lfFaceName, ARRAYLENGTH(lf.lfFaceName));
+
+ d->styles[style].font = CreateFontIndirect(&lf);
+}
+
+static LRESULT htw_paint(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ PAINTSTRUCT ps;
+ HBRUSH hbk;
+ khui_htwnd_data * d;
+ RECT r;
+ SIZE s;
+ HDC hdc;
+ wchar_t * text;
+ format_stack s_stack;
+
+ int align;
+ int y;
+ wchar_t * par_start;
+ int ext_width = 0;
+ int ext_height = 0;
+
+ d = (khui_htwnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, 0);
+
+ if(!GetUpdateRect(hwnd, &r, !(d->flags & KHUI_HTWND_TRANSPARENT)))
+ return 0;
+
+ if(d->text == NULL)
+ return 0;
+
+ text = d->text;
+
+ hdc = BeginPaint(hwnd, &ps);
+
+ GetClientRect(hwnd, &r);
+
+#ifdef DRAW_HTWND_CLIENT_EDGE
+ /* for the moment, we are skipping on the client edge. */
+ if(d->flags & KHUI_HTWND_CLIENTEDGE)
+ DrawEdge(hdc, &r, EDGE_SUNKEN, BF_ADJUST | BF_RECT | BF_FLAT);
+#endif
+
+ hbk = GetSysColorBrush(COLOR_WINDOW);
+ FillRect(hdc, &r, hbk);
+ hbk = NULL; /* We don't need to destroy system
+ brushes */
+
+ /* push the default format */
+ format_init(&s_stack);
+
+ d->l_pixel_y = GetDeviceCaps(hdc, LOGPIXELSY);
+ format_push(&s_stack,d, -MulDiv(HTW_NORMAL_SIZE, d->l_pixel_y, 72), FV_NONE, RGB(0,0,0));
+
+ y = r.top - d->scroll_top;
+
+ par_start = text;
+
+ align = ALIGN_LEFT;
+
+ SetTextAlign(hdc, TA_TOP | TA_LEFT | TA_NOUPDATECP);
+ if(d->flags & KHUI_HTWND_TRANSPARENT)
+ SetBkMode(hdc, TRANSPARENT);
+
+ d->n_links = 0;
+ d->n_tabs = 0;
+
+ while(*par_start) {
+ wchar_t * p = par_start;
+ wchar_t * c = NULL;
+ int p_width = 0;
+ int s_start;
+ int l_height = 0;
+ int x = 0;
+ POINT pt;
+ POINT pt_rel;
+
+ s_start = format_level(&s_stack);
+
+ /* begin dry run */
+ while(*p) {
+ if(*p == L'<') {
+ int talign = -1;
+ int n = htw_parse_tag(p,&c,&talign,d,&s_stack,NULL,NULL,0,TRUE);
+
+ if(n && p_width)
+ break;
+
+ p = c;
+
+ if(n && talign >= 0)
+ align = talign;
+ } else {
+ HFONT hfold;
+ c = wcschr(p, L'<');
+ if(!c)
+ c = p + wcslen(p);
+
+ htw_assert_style(hdc, d, format_style(&s_stack));
+ hfold = SelectFont(hdc, d->styles[format_style(&s_stack)].font);
+ GetTextExtentPoint32(hdc, p, (int)(c - p), &s);
+ SelectFont(hdc, hfold);
+
+ p_width += s.cx;
+ if(s.cy > l_height)
+ l_height = s.cy;
+
+ p = c;
+ }
+ }
+
+ /* dry run ends */
+
+ x = r.left - d->scroll_left;
+
+ if(align == ALIGN_CENTER) {
+ if (r.right - r.left > p_width)
+ x += (r.right - r.left)/2 - p_width / 2;
+ }
+
+ else if(align == ALIGN_RIGHT) {
+ if (r.right - r.left > p_width)
+ x += (r.right - r.left) - p_width;
+ }
+
+ /* begin wet run */
+ p = par_start;
+ format_unwind(&s_stack, s_start); /* unwind format stack */
+
+ p_width = 0;
+
+ while(p && *p) {
+ if(*p == L'<') {
+ int talign = -1;
+ int n;
+
+ pt.x = x + p_width;
+ pt.y = y;
+ pt_rel.x = p_width;
+ pt_rel.y = 0;
+
+ n = htw_parse_tag(p, &c, &talign, d, &s_stack, &pt, &pt_rel, l_height, FALSE);
+
+ if(n && p_width) {
+ break;
+ }
+
+ p_width = pt_rel.x;
+
+ p = c;
+ if(n && talign >= 0)
+ align = talign;
+ } else {
+ HFONT hfold;
+ RECT rd;
+
+ c = wcschr(p, L'<');
+ if(!c)
+ c = p + wcslen(p);
+
+ htw_assert_style(hdc, d, format_style(&s_stack));
+ hfold = SelectFont(hdc, d->styles[format_style(&s_stack)].font);
+ SetTextColor(hdc, format_color(&s_stack));
+
+ GetTextExtentPoint32(hdc, p, (int)(c - p), &s);
+ rd.left = x + p_width;
+ rd.top = y;
+ rd.right = rd.left + s.cx;
+ rd.bottom = rd.top + l_height;
+
+ DrawText(hdc, p, (int)(c - p), &rd,
+ DT_BOTTOM | DT_LEFT | DT_SINGLELINE | DT_NOPREFIX);
+
+ p_width += s.cx;
+
+ SelectFont(hdc, hfold);
+ p = c;
+ }
+ }
+
+ if (p_width > ext_width)
+ ext_width = p_width;
+
+ y += l_height;
+ par_start = p;
+ }
+
+ if (y > ext_height)
+ ext_height = y;
+
+ EndPaint(hwnd, &ps);
+
+ if (d->ext_width < ext_width ||
+ d->ext_height < ext_height) {
+ SCROLLINFO si;
+ LONG l;
+
+ /* the extents need to be adjusted. But first check if we
+ have exactly the right scroll bars we need. */
+ if ((ext_width > (r.right - r.left) &&
+ !(d->flags & KHUI_HTWND_HSCROLL)) ||
+ (ext_height > (r.bottom - r.top) &&
+ !(d->flags & KHUI_HTWND_VSCROLL)) ||
+
+ (ext_width <= (r.right - r.left) &&
+ (d->flags & KHUI_HTWND_HSCROLL)) ||
+ (ext_height <= (r.bottom - r.top) &&
+ (d->flags & KHUI_HTWND_VSCROLL))) {
+
+ /* need to add scroll bars */
+ if (ext_width > (r.right - r.left))
+ d->flags |= KHUI_HTWND_HSCROLL;
+ else
+ d->flags &= ~KHUI_HTWND_HSCROLL;
+
+ if (ext_height > (r.bottom - r.top))
+ d->flags |= KHUI_HTWND_VSCROLL;
+ else
+ d->flags &= ~KHUI_HTWND_VSCROLL;
+
+ l = GetWindowLongPtr(hwnd, GWL_STYLE);
+ l &= ~(WS_HSCROLL | WS_VSCROLL);
+
+ l |= ((d->flags & KHUI_HTWND_HSCROLL) ? WS_HSCROLL : 0) |
+ ((d->flags & KHUI_HTWND_VSCROLL) ? WS_VSCROLL : 0);
+
+ SetWindowLongPtr(hwnd, GWL_STYLE, l);
+
+ InvalidateRect(hwnd, NULL, FALSE);
+ /* since the client area changed, we do another redraw
+ before updating the scroll bar positions. */
+ } else {
+ d->ext_width = ext_width;
+ d->ext_height = ext_height;
+
+ if (d->flags & KHUI_HTWND_HSCROLL) {
+ ZeroMemory(&si, sizeof(si));
+ si.cbSize = sizeof(si);
+ si.fMask = SIF_ALL | SIF_DISABLENOSCROLL;
+ si.nMin = 0;
+ si.nMax = ext_width;
+ si.nPage = r.right - r.left;
+ si.nPos = d->scroll_left;
+
+ SetScrollInfo(hwnd, SB_HORZ, &si, TRUE);
+ }
+
+ if (d->flags & KHUI_HTWND_VSCROLL) {
+ ZeroMemory(&si, sizeof(si));
+ si.cbSize = sizeof(si);
+ si.fMask = SIF_ALL | SIF_DISABLENOSCROLL;
+ si.nMin = 0;
+ si.nMax = ext_height;
+ si.nPage = r.bottom - r.top;
+ si.nPos = d->scroll_top;
+
+ SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
+ }
+ }
+ }
+
+ return 0;
+}
+
+LRESULT CALLBACK khui_htwnd_proc(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam
+ )
+{
+ switch(uMsg) {
+ case WM_CREATE:
+ {
+ CREATESTRUCT * cs;
+ khui_htwnd_data * d;
+ size_t cbsize;
+
+ cs = (CREATESTRUCT *) lParam;
+
+ d = PMALLOC(sizeof(*d));
+ ZeroMemory(d, sizeof(*d));
+
+ if(cs->dwExStyle & WS_EX_TRANSPARENT) {
+ d->flags |= KHUI_HTWND_TRANSPARENT;
+ }
+ if(cs->dwExStyle & WS_EX_CLIENTEDGE) {
+ d->flags |= KHUI_HTWND_CLIENTEDGE;
+ }
+ if(cs->style & WS_HSCROLL) {
+ d->flags |= KHUI_HTWND_HSCROLL;
+ }
+ if(cs->style & WS_VSCROLL) {
+ d->flags |= KHUI_HTWND_VSCROLL;
+ }
+ d->id = (int)(INT_PTR) cs->hMenu;
+
+ d->active_link = -1;
+ d->bk_color = RGB(255,255,255);
+ d->hc_hand = LoadCursor(NULL, IDC_HAND);
+
+ if(SUCCEEDED(StringCbLength(cs->lpszName, KHUI_HTWND_MAXCB_TEXT, &cbsize))) {
+ cbsize += sizeof(wchar_t);
+ d->text = PMALLOC(cbsize);
+ StringCbCopy(d->text, cbsize, cs->lpszName);
+ }
+
+ /* this is just a flag to the WM_PAINT handler that the
+ extents haven't been set yet. */
+ d->ext_width = -1;
+
+#pragma warning(push)
+#pragma warning(disable: 4244)
+ SetWindowLongPtr(hwnd, 0, (LONG_PTR) d);
+#pragma warning(pop)
+
+ return 0;
+ }
+ break;
+
+ case WM_SETTEXT:
+ {
+ wchar_t * newtext;
+ size_t cbsize;
+ khui_htwnd_data * d;
+ BOOL rv;
+
+ d = (khui_htwnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, 0);
+ newtext = (wchar_t *) lParam;
+
+ if(d->text) {
+ PFREE(d->text);
+ d->text = NULL;
+ }
+
+ if(SUCCEEDED(StringCbLength(newtext, KHUI_HTWND_MAXCB_TEXT, &cbsize))) {
+ cbsize += sizeof(wchar_t);
+ d->text = PMALLOC(cbsize);
+ StringCbCopy(d->text, cbsize, newtext);
+ rv = TRUE;
+ } else
+ rv = FALSE;
+
+ clear_styles(d);
+
+ d->ext_width = -1;
+ d->scroll_left = 0;
+ d->scroll_top = 0;
+
+ InvalidateRect(hwnd, NULL, TRUE);
+
+ return rv;
+ }
+ break;
+
+ case WM_DESTROY:
+ {
+ khui_htwnd_data * d;
+ int i;
+
+ d = (khui_htwnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, 0);
+ if(d->text)
+ PFREE(d->text);
+ d->text = 0;
+
+ if(d->links) {
+ for(i=0;i<d->max_links;i++) {
+ if(d->links[i])
+ PFREE(d->links[i]);
+ }
+ PFREE(d->links);
+ }
+
+ clear_styles(d);
+
+ PFREE(d);
+ }
+ break;
+
+ case WM_ERASEBKGND:
+ {
+ HDC hdc = (HDC) wParam;
+ khui_htwnd_data * d;
+ HBRUSH hbr;
+ RECT r;
+
+ d = (khui_htwnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, 0);
+
+ GetClientRect(hwnd, &r);
+ hbr = GetSysColorBrush(COLOR_WINDOW);
+ FillRect(hdc, &r, hbr);
+
+ /* no need to destroy the brush since it's a system
+ brush. */
+
+ return TRUE;
+ }
+
+ case WM_SIZE:
+ {
+ khui_htwnd_data * d;
+
+ d = (khui_htwnd_data *) (LONG_PTR) GetWindowLongPtr(hwnd, 0);
+
+ if (d) {
+ d->ext_width = 0;
+ d->ext_height = 0;
+ }
+ }
+ return 0;
+
+ case WM_PAINT:
+ htw_paint(hwnd, uMsg, wParam, lParam);
+ return 0;
+
+ case WM_SETCURSOR:
+ {
+ khui_htwnd_data * d;
+
+ if(hwnd != (HWND)wParam)
+ break;
+
+ d = (khui_htwnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, 0);
+
+ if(d->active_link >= 0) {
+ SetCursor(d->hc_hand);
+ return TRUE;
+ }
+ }
+ break;
+
+ case WM_SETFOCUS:
+ {
+ khui_htwnd_data * d;
+
+ d = (khui_htwnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, 0);
+
+ d->flags |= KHUI_HTWND_FOCUS;
+
+ InvalidateRect(hwnd, NULL, TRUE);
+ }
+ break;
+
+ case WM_KILLFOCUS:
+ {
+ khui_htwnd_data * d;
+
+ d = (khui_htwnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, 0);
+
+ d->flags &= ~KHUI_HTWND_FOCUS;
+
+ InvalidateRect(hwnd, NULL, TRUE);
+ }
+ break;
+
+ case WM_LBUTTONDOWN:
+ {
+ khui_htwnd_data * d;
+
+ d = (khui_htwnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, 0);
+
+ d->md_link = d->active_link;
+
+ SetCapture(hwnd);
+ }
+ break;
+
+ case WM_LBUTTONUP:
+ {
+ khui_htwnd_data * d;
+
+ d = (khui_htwnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, 0);
+
+ if(d->md_link == d->active_link && d->md_link >= 0) {
+ /* clicked */
+ SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(d->id, BN_CLICKED), (LPARAM) d->links[d->md_link]);
+ }
+
+ ReleaseCapture();
+ }
+ break;
+
+ case WM_HSCROLL:
+ {
+ khui_htwnd_data * d;
+ int old_pos;
+ int new_pos;
+ int ext;
+ SCROLLINFO si;
+ RECT r;
+
+ d = (khui_htwnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, 0);
+
+ old_pos = new_pos = d->scroll_left;
+ ext = d->ext_width;
+
+ switch(LOWORD(wParam)) {
+ case SB_THUMBPOSITION:
+ case SB_ENDSCROLL:
+ ZeroMemory(&si, sizeof(si));
+ si.cbSize = sizeof(si);
+ si.fMask = SIF_POS;
+ GetScrollInfo(hwnd, SB_HORZ, &si);
+ new_pos = si.nPos;
+ break;
+
+ case SB_THUMBTRACK:
+ ZeroMemory(&si, sizeof(si));
+ si.cbSize = sizeof(si);
+ si.fMask = SIF_TRACKPOS;
+ GetScrollInfo(hwnd, SB_HORZ, &si);
+ new_pos = si.nTrackPos;
+ break;
+
+ case SB_LINELEFT:
+ new_pos -= ext / 12; /* arbitrary unit */
+ break;
+
+ case SB_LINERIGHT:
+ new_pos += ext / 12; /* arbitrary unit */
+ break;
+
+ case SB_PAGELEFT:
+ GetClientRect(hwnd, &r);
+ new_pos -= r.right - r.left;
+ break;
+
+ case SB_PAGERIGHT:
+ GetClientRect(hwnd, &r);
+ new_pos += r.right - r.left;
+ break;
+ }
+
+ if (new_pos == old_pos)
+ break;
+
+ GetClientRect(hwnd, &r);
+
+ if (new_pos > ext - (r.right - r.left))
+ new_pos = ext - (r.right - r.left);
+
+ if (new_pos < 0)
+ new_pos = 0;
+
+ if (new_pos == old_pos)
+ break;
+
+ ZeroMemory(&si, sizeof(si));
+ si.cbSize = sizeof(si);
+ si.fMask = SIF_POS;
+ si.nPos = new_pos;
+ SetScrollInfo(hwnd, SB_HORZ, &si, TRUE);
+ /* note that Windows sometimes adjusts the position after
+ setting it with SetScrollInfo. We have to look it up
+ again to see what value it ended up at. */
+ GetScrollInfo(hwnd, SB_HORZ, &si);
+ new_pos = si.nPos;
+
+ if (new_pos == old_pos)
+ break;
+
+ d->scroll_left = new_pos;
+
+ ScrollWindow(hwnd, old_pos - new_pos, 0, NULL, NULL);
+
+ return 0;
+ }
+ break;
+
+ case WM_MOUSEMOVE:
+ {
+ khui_htwnd_data * d;
+ int i;
+ POINT p;
+ int nl;
+
+ d = (khui_htwnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, 0);
+ p.x = GET_X_LPARAM(lParam) + d->scroll_left;
+ p.y = GET_Y_LPARAM(lParam) + d->scroll_top;
+
+ for(i=0; i<d->n_links; i++) {
+ if(d->links && d->links[i] && PtInRect(&(d->links[i]->r), p))
+ break;
+ }
+
+ if(i == d->n_links)
+ nl = -1;
+ else
+ nl = i;
+
+ if(d->active_link != nl) {
+ if(d->active_link >= 0) {
+ if(d->flags & KHUI_HTWND_TRANSPARENT) {
+ HWND parent = GetParent(hwnd);
+ if(parent) {
+ RECT rdest = d->links[d->active_link]->r;
+
+ MapWindowPoints(hwnd, parent, (LPPOINT) &rdest, 2);
+ InvalidateRect(parent, &rdest, TRUE);
+ }
+ }
+ /* although we are invalidating the rect before setting active_link,
+ WM_PAINT will not be issued until wndproc returns */
+ InvalidateRect(hwnd, &(d->links[d->active_link]->r), TRUE);
+ }
+ d->active_link = nl;
+ if(d->active_link >= 0) {
+ /* although we are invalidating the rect before setting active_link,
+ WM_PAINT will not be issued until wndproc returns */
+ if(d->flags & KHUI_HTWND_TRANSPARENT) {
+ HWND parent = GetParent(hwnd);
+ if(parent) {
+ RECT rdest = d->links[d->active_link]->r;
+
+ MapWindowPoints(hwnd, parent, (LPPOINT) &rdest, 2);
+ InvalidateRect(parent, &rdest, TRUE);
+ }
+ }
+ InvalidateRect(hwnd, &(d->links[d->active_link]->r), TRUE);
+ }
+ }
+ }
+ break;
+ }
+
+ return DefWindowProc(hwnd, uMsg,wParam,lParam);
+}
+
+void khm_register_htwnd_class(void)
+{
+ WNDCLASSEX wcx;
+
+ wcx.cbSize = sizeof(wcx);
+ wcx.style = CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
+ wcx.lpfnWndProc = khui_htwnd_proc;
+ wcx.cbClsExtra = 0;
+ wcx.cbWndExtra = sizeof(LONG_PTR);
+ wcx.hInstance = khm_hInstance;
+ wcx.hIcon = NULL;
+ wcx.hCursor = LoadCursor((HINSTANCE) NULL, IDC_ARROW);
+ wcx.hbrBackground = CreateSolidBrush(RGB(255,255,255));
+ wcx.lpszMenuName = NULL;
+ wcx.lpszClassName = KHUI_HTWND_CLASS;
+ wcx.hIconSm = NULL;
+
+ khui_htwnd_cls = RegisterClassEx(&wcx);
+}
+
+void khm_unregister_htwnd_class(void)
+{
+ UnregisterClass(MAKEINTATOM(khui_htwnd_cls), khm_hInstance);
+}
+
+HWND khm_create_htwnd(HWND parent, LPWSTR text, int x, int y, int width, int height, DWORD ex_style, DWORD style)
+{
+
+ return CreateWindowEx(
+ ex_style,
+ MAKEINTATOM(khui_htwnd_cls),
+ text,
+ style | WS_CHILD,
+ x,y,width,height,
+ parent,
+ (HMENU) KHUI_HTWND_CTLID,
+ khm_hInstance,
+ NULL);
+}
diff --git a/src/windows/identity/ui/htwnd.h b/src/windows/identity/ui/htwnd.h
index 2ca8c261b8..f842d2d39d 100644
--- a/src/windows/identity/ui/htwnd.h
+++ b/src/windows/identity/ui/htwnd.h
@@ -1,57 +1,57 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#ifndef __KHIMAIRA_HTWND_H
-#define __KHIMAIRA_HTWND_H
-
-#include<khuidefs.h>
-
-/*
-We currently support the following tags:
-
-<a [id="string"] [param="paramstring"]>link text</a>
-<center>foo</center>
-<left>foo</left>
-<right>foo</right>
-*/
-
-#define KHUI_HTWND_TRANSPARENT 1
-#define KHUI_HTWND_CLIENTEDGE 2
-#define KHUI_HTWND_HSCROLL 4
-#define KHUI_HTWND_VSCROLL 8
-#define KHUI_HTWND_FOCUS 2048
-
-#define KHUI_HTWND_CLASS L"KhmHtWnd"
-#define KHUI_HTWND_CTLID 2040
-
-#define KHUI_HTWND_MAXCCH_TEXT 2048
-#define KHUI_HTWND_MAXCB_TEXT (sizeof(wchar_t) * KHUI_HTWND_MAXCCH_TEXT)
-
-HWND khm_create_htwnd(HWND parent, LPWSTR text, int x, int y, int width, int height, DWORD ex_style, DWORD style);
-void khm_unregister_htwnd_class(void);
-void khm_register_htwnd_class(void);
-
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __KHIMAIRA_HTWND_H
+#define __KHIMAIRA_HTWND_H
+
+#include<khuidefs.h>
+
+/*
+We currently support the following tags:
+
+<a [id="string"] [param="paramstring"]>link text</a>
+<center>foo</center>
+<left>foo</left>
+<right>foo</right>
+*/
+
+#define KHUI_HTWND_TRANSPARENT 1
+#define KHUI_HTWND_CLIENTEDGE 2
+#define KHUI_HTWND_HSCROLL 4
+#define KHUI_HTWND_VSCROLL 8
+#define KHUI_HTWND_FOCUS 2048
+
+#define KHUI_HTWND_CLASS L"KhmHtWnd"
+#define KHUI_HTWND_CTLID 2040
+
+#define KHUI_HTWND_MAXCCH_TEXT 2048
+#define KHUI_HTWND_MAXCB_TEXT (sizeof(wchar_t) * KHUI_HTWND_MAXCCH_TEXT)
+
+HWND khm_create_htwnd(HWND parent, LPWSTR text, int x, int y, int width, int height, DWORD ex_style, DWORD style);
+void khm_unregister_htwnd_class(void);
+void khm_register_htwnd_class(void);
+
+#endif
diff --git a/src/windows/identity/ui/khmapp.h b/src/windows/identity/ui/khmapp.h
index 54beb2a12d..ba036c6492 100644
--- a/src/windows/identity/ui/khmapp.h
+++ b/src/windows/identity/ui/khmapp.h
@@ -1,70 +1,70 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#ifndef __KHIMAIRA_KHIMAIRA_H
-#define __KHIMAIRA_KHIMAIRA_H
-
-#include<windows.h>
-#include<windowsx.h>
-#include<strsafe.h>
-#include<commctrl.h>
-#include<htmlhelp.h>
-
-#define KHERR_HMODULE khm_hInstance
-#define KHERR_FACILITY khm_facility
-#define KHERR_FACILITY_ID 3
-
-#define NOEXPORT
-
-#include<netidmgr.h>
-
-#include<khhelp.h>
-#include<intaction.h>
-#include<intalert.h>
-
-#include<resource.h>
-#include<credfuncs.h>
-#include<appglobal.h>
-#include<mainwnd.h>
-#include<mainmenu.h>
-#include<toolbar.h>
-#include<statusbar.h>
-#include<credwnd.h>
-#include<htwnd.h>
-#include<passwnd.h>
-#include<newcredwnd.h>
-#include<propertywnd.h>
-#include<configwnd.h>
-#include<aboutwnd.h>
-#include<debugfuncs.h>
-#include<taskbar.h>
-
-#include<reqdaemon.h>
-#include<notifier.h>
-#include<timer.h>
-#include<addrchange.h>
-
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __KHIMAIRA_KHIMAIRA_H
+#define __KHIMAIRA_KHIMAIRA_H
+
+#include<windows.h>
+#include<windowsx.h>
+#include<strsafe.h>
+#include<commctrl.h>
+#include<htmlhelp.h>
+
+#define KHERR_HMODULE khm_hInstance
+#define KHERR_FACILITY khm_facility
+#define KHERR_FACILITY_ID 3
+
+#define NOEXPORT
+
+#include<netidmgr.h>
+
+#include<khhelp.h>
+#include<intaction.h>
+#include<intalert.h>
+
+#include<resource.h>
+#include<credfuncs.h>
+#include<appglobal.h>
+#include<mainwnd.h>
+#include<mainmenu.h>
+#include<toolbar.h>
+#include<statusbar.h>
+#include<credwnd.h>
+#include<htwnd.h>
+#include<passwnd.h>
+#include<newcredwnd.h>
+#include<propertywnd.h>
+#include<configwnd.h>
+#include<aboutwnd.h>
+#include<debugfuncs.h>
+#include<taskbar.h>
+
+#include<reqdaemon.h>
+#include<notifier.h>
+#include<timer.h>
+#include<addrchange.h>
+
+#endif
diff --git a/src/windows/identity/ui/main.c b/src/windows/identity/ui/main.c
index 3e3a94f673..e094f02731 100644
--- a/src/windows/identity/ui/main.c
+++ b/src/windows/identity/ui/main.c
@@ -1,897 +1,897 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<shlwapi.h>
-#include<khmapp.h>
-#include<netidmgr_intver.h>
-
-#if DEBUG
-#include<assert.h>
-
-#if defined(KH_BUILD_PRIVATE) || defined(KH_BUILD_SPECIAL)
-/* needed for writing out leaked allocation and handle report */
-#include<stdio.h>
-#endif
-
-#endif
-
-HINSTANCE khm_hInstance;
-const wchar_t * khm_facility = L"NetIDMgr";
-int khm_nCmdShow;
-khm_ui_4 khm_commctl_version = 0;
-
-khm_startup_options khm_startup;
-
-const khm_version app_version = {KH_VERSION_LIST};
-
-HRESULT hr_coinitialize = S_OK;
-
-void khm_init_gui(void) {
-
- hr_coinitialize = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
-
- khui_init_actions();
- khui_init_rescache();
- khui_init_menu();
- khui_init_toolbar();
- khm_init_notifier();
- khm_init_config();
- khm_init_debug();
- khm_init_taskbar_funcs();
-}
-
-void khm_exit_gui(void) {
- khm_exit_taskbar_funcs();
- khm_exit_debug();
- khm_exit_config();
- khm_exit_notifier();
- khui_exit_toolbar();
- khui_exit_menu();
- khui_exit_rescache();
- khui_exit_actions();
-
- if (hr_coinitialize == S_OK ||
- hr_coinitialize == S_FALSE) {
- CoUninitialize();
- }
-}
-
-void khm_parse_commandline(void) {
- LPWSTR wcmdline;
- LPWSTR * wargs;
- int wargc;
- int i;
-
- ZeroMemory(&khm_startup, sizeof(khm_startup));
-
- wcmdline = GetCommandLine();
- wargs = CommandLineToArgvW(wcmdline, &wargc);
-
- for (i=1; i<wargc; i++) {
- if (!wcscmp(wargs[i], L"-i") ||
- !wcscmp(wargs[i], L"--kinit") ||
- !wcscmp(wargs[i], L"-kinit")) {
- khm_startup.init = TRUE;
- khm_startup.exit = TRUE;
- khm_startup.no_main_window = TRUE;
- }
- else if (!wcscmp(wargs[i], L"-m") ||
- !wcscmp(wargs[i], L"--import") ||
- !wcscmp(wargs[i], L"-import")) {
- khm_startup.import = TRUE;
- khm_startup.exit = TRUE;
- khm_startup.no_main_window = TRUE;
- }
- else if (!wcscmp(wargs[i], L"-r") ||
- !wcscmp(wargs[i], L"--renew") ||
- !wcscmp(wargs[i], L"-renew")) {
- khm_startup.renew = TRUE;
- khm_startup.exit = TRUE;
- khm_startup.no_main_window = TRUE;
- }
- else if (!wcscmp(wargs[i], L"-d") ||
- !wcscmp(wargs[i], L"--destroy") ||
- !wcscmp(wargs[i], L"-destroy")) {
- khm_startup.destroy = TRUE;
- khm_startup.exit = TRUE;
- khm_startup.no_main_window = TRUE;
- }
- else if (!wcscmp(wargs[i], L"-a") ||
- !wcscmp(wargs[i], L"--autoinit") ||
- !wcscmp(wargs[i], L"-autoinit")) {
- khm_startup.autoinit = TRUE;
- }
- else if (!wcscmp(wargs[i], L"-x") ||
- !wcscmp(wargs[i], L"--exit") ||
- !wcscmp(wargs[i], L"-exit")) {
- khm_startup.exit = TRUE;
- khm_startup.remote_exit = TRUE;
- khm_startup.no_main_window = TRUE;
- }
- else {
- wchar_t help[2048];
-
- LoadString(khm_hInstance, IDS_CMDLINE_HELP,
- help, ARRAYLENGTH(help));
-
- MessageBox(NULL, help, L"NetIDMgr", MB_OK);
-
- khm_startup.error_exit = TRUE;
- break;
- }
- }
-
- /* special: always enable renew when other options aren't specified */
- if (!khm_startup.exit &&
- !khm_startup.destroy &&
- !khm_startup.init &&
- !khm_startup.remote_exit)
- khm_startup.renew = TRUE;
-}
-
-void khm_register_window_classes(void) {
- INITCOMMONCONTROLSEX ics;
-
- ZeroMemory(&ics, sizeof(ics));
- ics.dwSize = sizeof(ics);
- ics.dwICC =
- ICC_COOL_CLASSES |
- ICC_BAR_CLASSES |
- ICC_DATE_CLASSES |
- ICC_HOTKEY_CLASS |
- ICC_LISTVIEW_CLASSES |
- ICC_TAB_CLASSES |
- ICC_INTERNET_CLASSES |
-#if (_WIN32_WINNT >= 0x501)
- ((IS_COMMCTL6())?
- ICC_LINK_CLASS |
- ICC_STANDARD_CLASSES :
- 0) |
-#endif
- 0;
-
- InitCommonControlsEx(&ics);
-
- khm_register_main_wnd_class();
- khm_register_credwnd_class();
- khm_register_htwnd_class();
- khm_register_passwnd_class();
- khm_register_newcredwnd_class();
- khm_register_propertywnd_class();
-}
-
-void khm_unregister_window_classes(void) {
- khm_unregister_main_wnd_class();
- khm_unregister_credwnd_class();
- khm_unregister_htwnd_class();
- khm_unregister_passwnd_class();
- khm_unregister_newcredwnd_class();
- khm_unregister_propertywnd_class();
-}
-
-
-/* we support up to 16 simutaneous dialogs. In reality, more than two
- is pretty unlikely. Property sheets are special and are handled
- separately. */
-#define MAX_UI_DIALOGS 16
-
-typedef struct tag_khui_dialog {
- HWND hwnd;
- HWND hwnd_next;
- BOOL active;
-} khui_dialog;
-
-static khui_dialog khui_dialogs[MAX_UI_DIALOGS];
-static int n_khui_dialogs = 0;
-static HWND khui_modal_dialog = NULL;
-static BOOL khui_main_window_active;
-
-/* should only be called from the UI thread */
-void khm_add_dialog(HWND dlg) {
- if(n_khui_dialogs < MAX_UI_DIALOGS - 1) {
- khui_dialogs[n_khui_dialogs].hwnd = dlg;
- khui_dialogs[n_khui_dialogs].hwnd_next = NULL;
- khui_dialogs[n_khui_dialogs].active = TRUE;
- n_khui_dialogs++;
- } else {
-#if DEBUG
- assert(FALSE);
-#endif
- }
-}
-
-/* should only be called from the UI thread */
-void khm_enter_modal(HWND hwnd) {
- int i;
-
- if (khui_modal_dialog) {
-
- /* we are already in a modal loop. */
-
-#ifdef DEBUG
- assert(hwnd != khui_modal_dialog);
-#endif
-
- for (i=0; i < n_khui_dialogs; i++) {
- if (khui_dialogs[i].hwnd == khui_modal_dialog) {
- khui_dialogs[i].active = TRUE;
- EnableWindow(khui_modal_dialog, FALSE);
- break;
- }
- }
-
-#ifdef DEBUG
- assert(i < n_khui_dialogs);
-#endif
-
- for (i=0; i < n_khui_dialogs; i++) {
- if (khui_dialogs[i].hwnd == hwnd) {
- khui_dialogs[i].hwnd_next = khui_modal_dialog;
- break;
- }
- }
-
-#ifdef DEBUG
- assert(i < n_khui_dialogs);
-#endif
-
- khui_modal_dialog = hwnd;
-
- } else {
-
- /* we are entering a modal loop. preserve the active state of
- the overlapped dialogs and proceed with the modal
- dialog. */
-
- for (i=0; i < n_khui_dialogs; i++) {
- if(khui_dialogs[i].hwnd != hwnd) {
- khui_dialogs[i].active = IsWindowEnabled(khui_dialogs[i].hwnd);
- EnableWindow(khui_dialogs[i].hwnd, FALSE);
- }
- }
-
- khui_main_window_active = khm_is_main_window_active();
- EnableWindow(khm_hwnd_main, FALSE);
-
- khui_modal_dialog = hwnd;
-
- SetForegroundWindow(hwnd);
- }
-}
-
-/* should only be called from the UI thread */
-void khm_leave_modal(void) {
- int i;
-
- for (i=0; i < n_khui_dialogs; i++) {
- if (khui_dialogs[i].hwnd == khui_modal_dialog)
- break;
- }
-
-#ifdef DEBUG
- assert(i < n_khui_dialogs);
-#endif
-
- if (i < n_khui_dialogs && khui_dialogs[i].hwnd_next) {
-
- /* we need to proceed to the next one down the modal dialog
- chain. We are not exiting a modal loop. */
-
- khui_modal_dialog = khui_dialogs[i].hwnd_next;
- khui_dialogs[i].hwnd_next = FALSE;
-
- EnableWindow(khui_modal_dialog, TRUE);
-
- } else {
-
- HWND last_dialog = NULL;
-
- /* we are exiting a modal loop. */
-
- for (i=0; i < n_khui_dialogs; i++) {
- if(khui_dialogs[i].hwnd != khui_modal_dialog) {
- EnableWindow(khui_dialogs[i].hwnd, khui_dialogs[i].active);
- last_dialog = khui_dialogs[i].hwnd;
- }
- }
-
- EnableWindow(khm_hwnd_main, TRUE);
-
- khui_modal_dialog = NULL;
-
- if(last_dialog)
- SetActiveWindow(last_dialog);
- else
- SetActiveWindow(khm_hwnd_main);
- }
-}
-
-/* should only be called from the UI thread */
-void khm_del_dialog(HWND dlg) {
- int i;
- for(i=0;i < n_khui_dialogs; i++) {
- if(khui_dialogs[i].hwnd == dlg)
- break;
- }
-
- if(i < n_khui_dialogs)
- n_khui_dialogs--;
- else
- return;
-
- for(;i < n_khui_dialogs; i++) {
- khui_dialogs[i] = khui_dialogs[i+1];
- }
-}
-
-BOOL khm_check_dlg_message(LPMSG pmsg) {
- int i;
- BOOL found = FALSE;
- for(i=0;i<n_khui_dialogs;i++) {
- if(IsDialogMessage(khui_dialogs[i].hwnd, pmsg)) {
- found = TRUE;
- break;
- }
- }
-
- return found;
-}
-
-BOOL khm_is_dialog_active(void) {
- HWND hwnd;
- int i;
-
- hwnd = GetForegroundWindow();
-
- for (i=0; i<n_khui_dialogs; i++) {
- if (khui_dialogs[i].hwnd == hwnd)
- return TRUE;
- }
-
- return FALSE;
-}
-
-/* We support at most 256 property sheets simultaneously. 256
- property sheets should be enough for everybody. */
-#define MAX_UI_PROPSHEETS 256
-
-khui_property_sheet *_ui_propsheets[MAX_UI_PROPSHEETS];
-int _n_ui_propsheets = 0;
-
-void khm_add_property_sheet(khui_property_sheet * s) {
- if(_n_ui_propsheets < MAX_UI_PROPSHEETS)
- _ui_propsheets[_n_ui_propsheets++] = s;
- else {
-#ifdef DEBUG
- assert(FALSE);
-#endif
- }
-}
-
-void khm_del_property_sheet(khui_property_sheet * s) {
- int i;
-
- for(i=0;i < _n_ui_propsheets; i++) {
- if(_ui_propsheets[i] == s)
- break;
- }
-
- if(i < _n_ui_propsheets)
- _n_ui_propsheets--;
- else
- return;
-
- for(;i < _n_ui_propsheets; i++) {
- _ui_propsheets[i] = _ui_propsheets[i+1];
- }
-}
-
-BOOL khm_check_ps_message(LPMSG pmsg) {
- int i;
- khui_property_sheet * ps;
- for(i=0;i<_n_ui_propsheets;i++) {
- if(khui_ps_check_message(_ui_propsheets[i], pmsg)) {
- if(_ui_propsheets[i]->status == KHUI_PS_STATUS_DONE) {
- ps = _ui_propsheets[i];
-
- ps->status = KHUI_PS_STATUS_DESTROY;
- kmq_post_message(KMSG_CRED, KMSG_CRED_PP_END, 0, (void *) ps);
-
- return TRUE;
- }
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
-static HACCEL ha_menu;
-
-WPARAM khm_message_loop_int(khm_boolean * p_exit) {
- int r;
- MSG msg;
-
- while((r = GetMessage(&msg, NULL, 0,0)) &&
- (p_exit == NULL || *p_exit)) {
- if(r == -1)
- break;
- if(!khm_check_dlg_message(&msg) &&
- !khm_check_ps_message(&msg) &&
- !TranslateAccelerator(khm_hwnd_main, ha_menu, &msg)) {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- }
-
- return msg.wParam;
-}
-
-WPARAM khm_message_loop(void) {
- WPARAM w;
- ha_menu = khui_create_global_accel_table();
- w = khm_message_loop_int(NULL);
- DestroyAcceleratorTable(ha_menu);
- return w;
-}
-
-/* Handles all context closures which have a signalled error state.
- If the context is a top level context, then the errors are
- displayed. */
-void KHMAPI
-khm_err_ctx_completion_handler(enum kherr_ctx_event evt,
- kherr_context * c) {
- kherr_event * e;
- khui_alert * a;
-
- /* we only handle top level contexts here. For others, we allow
- the child contexts to fold upward silently. */
- if (c->parent || !kherr_is_error_i(c))
- return;
-
- for(e = kherr_get_first_event(c);
- e;
- e = kherr_get_next_event(e)) {
-
- if (e->severity != KHERR_ERROR && e->severity != KHERR_WARNING)
- continue;
-
- kherr_evaluate_event(e);
-
- /* we only report errors if there is enough information to
- present a message. */
- if (e->short_desc && e->long_desc) {
-
- khui_alert_create_empty(&a);
-
- khui_alert_set_severity(a, e->severity);
- khui_alert_set_title(a, e->short_desc);
- khui_alert_set_message(a, e->long_desc);
- if (e->suggestion)
- khui_alert_set_suggestion(a, e->suggestion);
-
- khui_alert_queue(a);
-
- khui_alert_release(a);
- }
- }
-}
-
-static wchar_t helpfile[MAX_PATH] = L"";
-
-HWND khm_html_help(HWND hwnd, wchar_t * suffix,
- UINT command, DWORD_PTR data) {
-
- wchar_t gpath[MAX_PATH + MAX_PATH];
-
- if (!*helpfile) {
- DWORD dw;
- wchar_t ppath[MAX_PATH];
-
- dw = GetModuleFileName(NULL, ppath, ARRAYLENGTH(ppath));
-
- if (dw == 0) {
- StringCbCopy(helpfile, sizeof(helpfile), NIDM_HELPFILE);
- } else {
- PathRemoveFileSpec(ppath);
- PathAppend(ppath, NIDM_HELPFILE);
- StringCbCopy(helpfile, sizeof(helpfile), ppath);
- }
- }
-
- StringCbCopy(gpath, sizeof(gpath), helpfile);
-
- if (suffix)
- StringCbCat(gpath, sizeof(gpath), suffix);
-
- return HtmlHelp(hwnd, gpath, command, data);
-}
-
-void khm_load_default_modules(void) {
- kmm_load_default_modules();
-}
-
-int khm_compare_version(const khm_version * v1, const khm_version * v2) {
-
- if (v1->major != v2->major)
- return ((int)v1->major) - ((int)v2->major);
-
- if (v1->minor != v2->minor)
- return ((int)v1->minor) - ((int)v2->minor);
-
- if (v1->patch != v2->patch)
- return ((int)v1->patch) - ((int)v2->patch);
-
- return ((int)v1->aux - ((int)v2->aux));
-}
-
-int WINAPI WinMain(HINSTANCE hInstance,
- HINSTANCE hPrevInstance,
- LPSTR lpCmdLine,
- int nCmdShow)
-{
- int rv = 0;
- HANDLE h_appmutex;
- BOOL slave = FALSE;
- int mutex_retries = 5;
-
- khm_hInstance = hInstance;
- khm_nCmdShow = nCmdShow;
-
- khm_parse_commandline();
-
- if (khm_startup.error_exit)
- return 0;
-
- _retry_mutex:
-
- if (--mutex_retries < 0)
- return 2;
-
- h_appmutex = CreateMutex(NULL, FALSE, L"Local\\NetIDMgr_GlobalAppMutex");
- if (h_appmutex == NULL)
- return 5;
- if (GetLastError() == ERROR_ALREADY_EXISTS)
- slave = TRUE;
-
- khc_load_schema(NULL, schema_uiconfig);
-
- _start_app:
-
- if(!slave) {
-
- PDESCTHREAD(L"UI", L"App");
-
- /* set this so that we don't accidently invoke an API that
- inadvertently puts up the new creds dialog at an
- inopportune moment, like, say, during the new creds dialog
- is open. This only affects this process, and any child
- processes started by plugins. */
- SetEnvironmentVariable(L"KERBEROSLOGIN_NEVER_PROMPT", L"1");
-
- khm_version_init();
-
- khm_commctl_version = khm_get_commctl_version(NULL);
-
- /* we only open a main window if this is the only instance
- of the application that is running. */
- kmq_init();
- khm_init_gui();
- kmm_init();
-
- kmq_set_completion_handler(KMSG_CRED, kmsg_cred_completion);
-
- kherr_add_ctx_handler(khm_err_ctx_completion_handler,
- KHERR_CTX_END,
- 0);
-
- /* load the standard plugins */
- khm_load_default_modules();
-
- khm_register_window_classes();
-
- khm_init_request_daemon();
-
- khm_create_main_window();
-
- if (!khm_startup.no_main_window)
- khm_show_main_window();
-
- khm_refresh_config();
-
- rv = (int) khm_message_loop();
-
- kmq_set_completion_handler(KMSG_CRED, NULL);
-
- khm_exit_request_daemon();
-
- kmm_exit();
- khm_exit_gui();
- khm_unregister_window_classes();
- kmq_exit();
-
- CloseHandle(h_appmutex);
- } else {
- HWND hwnd = NULL;
- int retries = 5;
- HANDLE hmap;
- wchar_t mapname[256];
- DWORD tid;
- void * xfer;
- khm_query_app_version query_app_version;
- khm_version v;
- BOOL use_cmd_v2 = TRUE;
- khm_size cb = 0;
-
- CloseHandle(h_appmutex);
-
- while (hwnd == NULL && retries) {
- hwnd = FindWindowEx(NULL, NULL, KHUI_MAIN_WINDOW_CLASS, NULL);
-
- if (hwnd)
- break;
-
- retries--;
-
- /* if the app was just starting, we might have to wait
- till the main window is created. */
-
- Sleep(1000);
- }
-
- if (!hwnd) {
-
- /* if the app was just exiting, we might see the mutex but
- not the window. We go back and check if the mutex is
- still there. */
-
- goto _retry_mutex;
- }
-
- /* first check if the remote instance supports a version
- query */
-
- StringCbPrintf(mapname, sizeof(mapname),
- QUERY_APP_VER_MAP_FMT,
- (tid = GetCurrentThreadId()));
-
- hmap = CreateFileMapping(INVALID_HANDLE_VALUE,
- NULL,
- PAGE_READWRITE,
- 0,
- 4096,
- mapname);
-
- if (hmap == NULL)
- return 3;
-
- xfer = MapViewOfFile(hmap, FILE_MAP_WRITE, 0, 0,
- sizeof(query_app_version));
-
- ZeroMemory(&query_app_version, sizeof(query_app_version));
-
- if (xfer) {
- query_app_version.magic = KHM_QUERY_APP_VER_MAGIC;
- query_app_version.code = KHM_ERROR_NOT_IMPLEMENTED;
- query_app_version.ver_caller = app_version;
-
- query_app_version.request_swap = TRUE;
-
- memcpy(xfer, &query_app_version, sizeof(query_app_version));
-
- SendMessage(hwnd, WM_KHUI_QUERY_APP_VERSION,
- 0, (LPARAM) tid);
-
- memcpy(&query_app_version, xfer, sizeof(query_app_version));
-
- UnmapViewOfFile(xfer);
- xfer = NULL;
- }
-
- CloseHandle(hmap);
- hmap = NULL;
-
- if (query_app_version.magic != KHM_QUERY_APP_VER_MAGIC ||
- query_app_version.code != KHM_ERROR_SUCCESS) {
-
- /* We managed to communicate with the remote instance, but
- it didn't send us useful information. The remote
- instance is not running an actual NetIDMgr instance.
- However, it owns a top level window that was registered
- with our classname. This instance won't function
- properly if we let it proceed.
- */
-
- wchar_t error_msg[1024];
- wchar_t error_title[256];
-
- LoadString(khm_hInstance, IDS_REMOTE_FAIL_TITLE,
- error_title, ARRAYLENGTH(error_title));
- LoadString(khm_hInstance, IDS_REMOTE_FAIL,
- error_msg, ARRAYLENGTH(error_msg));
-
- MessageBox(NULL, error_msg, error_title,
- MB_OK);
-
- goto done_with_remote;
- }
-
- if (query_app_version.code == KHM_ERROR_SUCCESS &&
- query_app_version.request_swap) {
- /* the request for swap was granted. We can now
- initialize our instance as the master instance. */
-
- slave = FALSE;
- goto _start_app;
- }
-
- /* Now we can work on sending the command-line to the remote
- instance. However we need to figure out which version of
- the startup structure it supports. */
- v.major = 1;
- v.minor = 2;
- v.patch = 0;
- v.aux = 0;
-
- if (khm_compare_version(&query_app_version.ver_remote, &app_version) == 0 ||
- khm_compare_version(&query_app_version.ver_remote, &v) > 0)
- use_cmd_v2 = TRUE;
- else
- use_cmd_v2 = FALSE;
-
- StringCbPrintf(mapname, sizeof(mapname),
- COMMANDLINE_MAP_FMT,
- (tid = GetCurrentThreadId()));
-
- cb = max(sizeof(struct tag_khm_startup_options_v1),
- sizeof(struct tag_khm_startup_options_v2));
-
- cb = UBOUNDSS(cb, 4096, 4096);
-
-#ifdef DEBUG
- assert(cb >= 4096);
-#endif
-
- hmap = CreateFileMapping(INVALID_HANDLE_VALUE,
- NULL,
- PAGE_READWRITE,
- 0,
- (DWORD) cb,
- mapname);
-
- if (hmap == NULL)
- return 3;
-
- /* make the call */
-
- if (use_cmd_v2) {
- /* use the v2 structure */
- struct tag_khm_startup_options_v2 v2opt;
-
- ZeroMemory(&v2opt, sizeof(v2opt));
-
- v2opt.magic = STARTUP_OPTIONS_MAGIC;
- v2opt.cb_size = sizeof(v2opt);
-
- v2opt.init = khm_startup.init;
- v2opt.import = khm_startup.import;
- v2opt.renew = khm_startup.renew;
- v2opt.destroy = khm_startup.destroy;
-
- v2opt.autoinit = khm_startup.autoinit;
- v2opt.remote_exit = khm_startup.remote_exit;
-
- v2opt.code = KHM_ERROR_NOT_IMPLEMENTED;
-
- xfer = MapViewOfFile(hmap,
- FILE_MAP_WRITE,
- 0, 0,
- sizeof(v2opt));
-
- if (xfer) {
- memcpy(xfer, &v2opt, sizeof(v2opt));
-
- SendMessage(hwnd, WM_KHUI_ASSIGN_COMMANDLINE_V2,
- 0, (LPARAM) tid);
-
- memcpy(&v2opt, xfer, sizeof(v2opt));
-
- /* If the request looks like it wasn't processed, we
- fallback to the v1 request. */
-
- if (v2opt.code == KHM_ERROR_NOT_IMPLEMENTED)
- use_cmd_v2 = FALSE;
-
- UnmapViewOfFile(xfer);
- xfer = NULL;
- }
- }
-
- if (!use_cmd_v2) {
- /* use the v1 structure */
-
- struct tag_khm_startup_options_v1 v1opt;
-
- ZeroMemory(&v1opt, sizeof(v1opt));
-
- v1opt.init = khm_startup.init;
- v1opt.import = khm_startup.import;
- v1opt.renew = khm_startup.renew;
- v1opt.destroy = khm_startup.destroy;
- v1opt.autoinit = khm_startup.autoinit;
-
- xfer = MapViewOfFile(hmap,
- FILE_MAP_WRITE,
- 0, 0,
- sizeof(v1opt));
-
- if (xfer) {
- memcpy(xfer, &v1opt, sizeof(v1opt));
-
- SendMessage(hwnd, WM_KHUI_ASSIGN_COMMANDLINE_V1,
- 0, (LPARAM) tid);
-
- UnmapViewOfFile(xfer);
- xfer = NULL;
- }
- }
-
- done_with_remote:
-
- if (hmap)
- CloseHandle(hmap);
- }
-
-#if defined(DEBUG) && (defined(KH_BUILD_PRIVATE) || defined(KH_BUILD_SPECIAL))
- {
- FILE * f = NULL;
-
- KHMEXP void KHMAPI khcint_dump_handles(FILE * f);
- KHMEXP void KHMAPI perf_dump(FILE * f);
- KHMEXP void KHMAPI kmqint_dump(FILE * f);
-
-#if _MSC_VER >= 1400
- if (fopen_s(&f, "memleak.txt", "w") != 0)
- goto done_with_dump;
-#else
- f = fopen("memleak.txt", "w");
- if (f == NULL)
- goto done_with_dump;
-#endif
-
- perf_dump(f);
- khcint_dump_handles(f);
- kmqint_dump(f);
-
- fclose(f);
-
- done_with_dump:
- ;
- }
-#endif
-
- return rv;
-}
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<shlwapi.h>
+#include<khmapp.h>
+#include<netidmgr_intver.h>
+
+#if DEBUG
+#include<assert.h>
+
+#if defined(KH_BUILD_PRIVATE) || defined(KH_BUILD_SPECIAL)
+/* needed for writing out leaked allocation and handle report */
+#include<stdio.h>
+#endif
+
+#endif
+
+HINSTANCE khm_hInstance;
+const wchar_t * khm_facility = L"NetIDMgr";
+int khm_nCmdShow;
+khm_ui_4 khm_commctl_version = 0;
+
+khm_startup_options khm_startup;
+
+const khm_version app_version = {KH_VERSION_LIST};
+
+HRESULT hr_coinitialize = S_OK;
+
+void khm_init_gui(void) {
+
+ hr_coinitialize = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
+
+ khui_init_actions();
+ khui_init_rescache();
+ khui_init_menu();
+ khui_init_toolbar();
+ khm_init_notifier();
+ khm_init_config();
+ khm_init_debug();
+ khm_init_taskbar_funcs();
+}
+
+void khm_exit_gui(void) {
+ khm_exit_taskbar_funcs();
+ khm_exit_debug();
+ khm_exit_config();
+ khm_exit_notifier();
+ khui_exit_toolbar();
+ khui_exit_menu();
+ khui_exit_rescache();
+ khui_exit_actions();
+
+ if (hr_coinitialize == S_OK ||
+ hr_coinitialize == S_FALSE) {
+ CoUninitialize();
+ }
+}
+
+void khm_parse_commandline(void) {
+ LPWSTR wcmdline;
+ LPWSTR * wargs;
+ int wargc;
+ int i;
+
+ ZeroMemory(&khm_startup, sizeof(khm_startup));
+
+ wcmdline = GetCommandLine();
+ wargs = CommandLineToArgvW(wcmdline, &wargc);
+
+ for (i=1; i<wargc; i++) {
+ if (!wcscmp(wargs[i], L"-i") ||
+ !wcscmp(wargs[i], L"--kinit") ||
+ !wcscmp(wargs[i], L"-kinit")) {
+ khm_startup.init = TRUE;
+ khm_startup.exit = TRUE;
+ khm_startup.no_main_window = TRUE;
+ }
+ else if (!wcscmp(wargs[i], L"-m") ||
+ !wcscmp(wargs[i], L"--import") ||
+ !wcscmp(wargs[i], L"-import")) {
+ khm_startup.import = TRUE;
+ khm_startup.exit = TRUE;
+ khm_startup.no_main_window = TRUE;
+ }
+ else if (!wcscmp(wargs[i], L"-r") ||
+ !wcscmp(wargs[i], L"--renew") ||
+ !wcscmp(wargs[i], L"-renew")) {
+ khm_startup.renew = TRUE;
+ khm_startup.exit = TRUE;
+ khm_startup.no_main_window = TRUE;
+ }
+ else if (!wcscmp(wargs[i], L"-d") ||
+ !wcscmp(wargs[i], L"--destroy") ||
+ !wcscmp(wargs[i], L"-destroy")) {
+ khm_startup.destroy = TRUE;
+ khm_startup.exit = TRUE;
+ khm_startup.no_main_window = TRUE;
+ }
+ else if (!wcscmp(wargs[i], L"-a") ||
+ !wcscmp(wargs[i], L"--autoinit") ||
+ !wcscmp(wargs[i], L"-autoinit")) {
+ khm_startup.autoinit = TRUE;
+ }
+ else if (!wcscmp(wargs[i], L"-x") ||
+ !wcscmp(wargs[i], L"--exit") ||
+ !wcscmp(wargs[i], L"-exit")) {
+ khm_startup.exit = TRUE;
+ khm_startup.remote_exit = TRUE;
+ khm_startup.no_main_window = TRUE;
+ }
+ else {
+ wchar_t help[2048];
+
+ LoadString(khm_hInstance, IDS_CMDLINE_HELP,
+ help, ARRAYLENGTH(help));
+
+ MessageBox(NULL, help, L"NetIDMgr", MB_OK);
+
+ khm_startup.error_exit = TRUE;
+ break;
+ }
+ }
+
+ /* special: always enable renew when other options aren't specified */
+ if (!khm_startup.exit &&
+ !khm_startup.destroy &&
+ !khm_startup.init &&
+ !khm_startup.remote_exit)
+ khm_startup.renew = TRUE;
+}
+
+void khm_register_window_classes(void) {
+ INITCOMMONCONTROLSEX ics;
+
+ ZeroMemory(&ics, sizeof(ics));
+ ics.dwSize = sizeof(ics);
+ ics.dwICC =
+ ICC_COOL_CLASSES |
+ ICC_BAR_CLASSES |
+ ICC_DATE_CLASSES |
+ ICC_HOTKEY_CLASS |
+ ICC_LISTVIEW_CLASSES |
+ ICC_TAB_CLASSES |
+ ICC_INTERNET_CLASSES |
+#if (_WIN32_WINNT >= 0x501)
+ ((IS_COMMCTL6())?
+ ICC_LINK_CLASS |
+ ICC_STANDARD_CLASSES :
+ 0) |
+#endif
+ 0;
+
+ InitCommonControlsEx(&ics);
+
+ khm_register_main_wnd_class();
+ khm_register_credwnd_class();
+ khm_register_htwnd_class();
+ khm_register_passwnd_class();
+ khm_register_newcredwnd_class();
+ khm_register_propertywnd_class();
+}
+
+void khm_unregister_window_classes(void) {
+ khm_unregister_main_wnd_class();
+ khm_unregister_credwnd_class();
+ khm_unregister_htwnd_class();
+ khm_unregister_passwnd_class();
+ khm_unregister_newcredwnd_class();
+ khm_unregister_propertywnd_class();
+}
+
+
+/* we support up to 16 simutaneous dialogs. In reality, more than two
+ is pretty unlikely. Property sheets are special and are handled
+ separately. */
+#define MAX_UI_DIALOGS 16
+
+typedef struct tag_khui_dialog {
+ HWND hwnd;
+ HWND hwnd_next;
+ BOOL active;
+} khui_dialog;
+
+static khui_dialog khui_dialogs[MAX_UI_DIALOGS];
+static int n_khui_dialogs = 0;
+static HWND khui_modal_dialog = NULL;
+static BOOL khui_main_window_active;
+
+/* should only be called from the UI thread */
+void khm_add_dialog(HWND dlg) {
+ if(n_khui_dialogs < MAX_UI_DIALOGS - 1) {
+ khui_dialogs[n_khui_dialogs].hwnd = dlg;
+ khui_dialogs[n_khui_dialogs].hwnd_next = NULL;
+ khui_dialogs[n_khui_dialogs].active = TRUE;
+ n_khui_dialogs++;
+ } else {
+#if DEBUG
+ assert(FALSE);
+#endif
+ }
+}
+
+/* should only be called from the UI thread */
+void khm_enter_modal(HWND hwnd) {
+ int i;
+
+ if (khui_modal_dialog) {
+
+ /* we are already in a modal loop. */
+
+#ifdef DEBUG
+ assert(hwnd != khui_modal_dialog);
+#endif
+
+ for (i=0; i < n_khui_dialogs; i++) {
+ if (khui_dialogs[i].hwnd == khui_modal_dialog) {
+ khui_dialogs[i].active = TRUE;
+ EnableWindow(khui_modal_dialog, FALSE);
+ break;
+ }
+ }
+
+#ifdef DEBUG
+ assert(i < n_khui_dialogs);
+#endif
+
+ for (i=0; i < n_khui_dialogs; i++) {
+ if (khui_dialogs[i].hwnd == hwnd) {
+ khui_dialogs[i].hwnd_next = khui_modal_dialog;
+ break;
+ }
+ }
+
+#ifdef DEBUG
+ assert(i < n_khui_dialogs);
+#endif
+
+ khui_modal_dialog = hwnd;
+
+ } else {
+
+ /* we are entering a modal loop. preserve the active state of
+ the overlapped dialogs and proceed with the modal
+ dialog. */
+
+ for (i=0; i < n_khui_dialogs; i++) {
+ if(khui_dialogs[i].hwnd != hwnd) {
+ khui_dialogs[i].active = IsWindowEnabled(khui_dialogs[i].hwnd);
+ EnableWindow(khui_dialogs[i].hwnd, FALSE);
+ }
+ }
+
+ khui_main_window_active = khm_is_main_window_active();
+ EnableWindow(khm_hwnd_main, FALSE);
+
+ khui_modal_dialog = hwnd;
+
+ SetForegroundWindow(hwnd);
+ }
+}
+
+/* should only be called from the UI thread */
+void khm_leave_modal(void) {
+ int i;
+
+ for (i=0; i < n_khui_dialogs; i++) {
+ if (khui_dialogs[i].hwnd == khui_modal_dialog)
+ break;
+ }
+
+#ifdef DEBUG
+ assert(i < n_khui_dialogs);
+#endif
+
+ if (i < n_khui_dialogs && khui_dialogs[i].hwnd_next) {
+
+ /* we need to proceed to the next one down the modal dialog
+ chain. We are not exiting a modal loop. */
+
+ khui_modal_dialog = khui_dialogs[i].hwnd_next;
+ khui_dialogs[i].hwnd_next = FALSE;
+
+ EnableWindow(khui_modal_dialog, TRUE);
+
+ } else {
+
+ HWND last_dialog = NULL;
+
+ /* we are exiting a modal loop. */
+
+ for (i=0; i < n_khui_dialogs; i++) {
+ if(khui_dialogs[i].hwnd != khui_modal_dialog) {
+ EnableWindow(khui_dialogs[i].hwnd, khui_dialogs[i].active);
+ last_dialog = khui_dialogs[i].hwnd;
+ }
+ }
+
+ EnableWindow(khm_hwnd_main, TRUE);
+
+ khui_modal_dialog = NULL;
+
+ if(last_dialog)
+ SetActiveWindow(last_dialog);
+ else
+ SetActiveWindow(khm_hwnd_main);
+ }
+}
+
+/* should only be called from the UI thread */
+void khm_del_dialog(HWND dlg) {
+ int i;
+ for(i=0;i < n_khui_dialogs; i++) {
+ if(khui_dialogs[i].hwnd == dlg)
+ break;
+ }
+
+ if(i < n_khui_dialogs)
+ n_khui_dialogs--;
+ else
+ return;
+
+ for(;i < n_khui_dialogs; i++) {
+ khui_dialogs[i] = khui_dialogs[i+1];
+ }
+}
+
+BOOL khm_check_dlg_message(LPMSG pmsg) {
+ int i;
+ BOOL found = FALSE;
+ for(i=0;i<n_khui_dialogs;i++) {
+ if(IsDialogMessage(khui_dialogs[i].hwnd, pmsg)) {
+ found = TRUE;
+ break;
+ }
+ }
+
+ return found;
+}
+
+BOOL khm_is_dialog_active(void) {
+ HWND hwnd;
+ int i;
+
+ hwnd = GetForegroundWindow();
+
+ for (i=0; i<n_khui_dialogs; i++) {
+ if (khui_dialogs[i].hwnd == hwnd)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/* We support at most 256 property sheets simultaneously. 256
+ property sheets should be enough for everybody. */
+#define MAX_UI_PROPSHEETS 256
+
+khui_property_sheet *_ui_propsheets[MAX_UI_PROPSHEETS];
+int _n_ui_propsheets = 0;
+
+void khm_add_property_sheet(khui_property_sheet * s) {
+ if(_n_ui_propsheets < MAX_UI_PROPSHEETS)
+ _ui_propsheets[_n_ui_propsheets++] = s;
+ else {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ }
+}
+
+void khm_del_property_sheet(khui_property_sheet * s) {
+ int i;
+
+ for(i=0;i < _n_ui_propsheets; i++) {
+ if(_ui_propsheets[i] == s)
+ break;
+ }
+
+ if(i < _n_ui_propsheets)
+ _n_ui_propsheets--;
+ else
+ return;
+
+ for(;i < _n_ui_propsheets; i++) {
+ _ui_propsheets[i] = _ui_propsheets[i+1];
+ }
+}
+
+BOOL khm_check_ps_message(LPMSG pmsg) {
+ int i;
+ khui_property_sheet * ps;
+ for(i=0;i<_n_ui_propsheets;i++) {
+ if(khui_ps_check_message(_ui_propsheets[i], pmsg)) {
+ if(_ui_propsheets[i]->status == KHUI_PS_STATUS_DONE) {
+ ps = _ui_propsheets[i];
+
+ ps->status = KHUI_PS_STATUS_DESTROY;
+ kmq_post_message(KMSG_CRED, KMSG_CRED_PP_END, 0, (void *) ps);
+
+ return TRUE;
+ }
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+static HACCEL ha_menu;
+
+WPARAM khm_message_loop_int(khm_boolean * p_exit) {
+ int r;
+ MSG msg;
+
+ while((r = GetMessage(&msg, NULL, 0,0)) &&
+ (p_exit == NULL || *p_exit)) {
+ if(r == -1)
+ break;
+ if(!khm_check_dlg_message(&msg) &&
+ !khm_check_ps_message(&msg) &&
+ !TranslateAccelerator(khm_hwnd_main, ha_menu, &msg)) {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ }
+
+ return msg.wParam;
+}
+
+WPARAM khm_message_loop(void) {
+ WPARAM w;
+ ha_menu = khui_create_global_accel_table();
+ w = khm_message_loop_int(NULL);
+ DestroyAcceleratorTable(ha_menu);
+ return w;
+}
+
+/* Handles all context closures which have a signalled error state.
+ If the context is a top level context, then the errors are
+ displayed. */
+void KHMAPI
+khm_err_ctx_completion_handler(enum kherr_ctx_event evt,
+ kherr_context * c) {
+ kherr_event * e;
+ khui_alert * a;
+
+ /* we only handle top level contexts here. For others, we allow
+ the child contexts to fold upward silently. */
+ if (c->parent || !kherr_is_error_i(c))
+ return;
+
+ for(e = kherr_get_first_event(c);
+ e;
+ e = kherr_get_next_event(e)) {
+
+ if (e->severity != KHERR_ERROR && e->severity != KHERR_WARNING)
+ continue;
+
+ kherr_evaluate_event(e);
+
+ /* we only report errors if there is enough information to
+ present a message. */
+ if (e->short_desc && e->long_desc) {
+
+ khui_alert_create_empty(&a);
+
+ khui_alert_set_severity(a, e->severity);
+ khui_alert_set_title(a, e->short_desc);
+ khui_alert_set_message(a, e->long_desc);
+ if (e->suggestion)
+ khui_alert_set_suggestion(a, e->suggestion);
+
+ khui_alert_queue(a);
+
+ khui_alert_release(a);
+ }
+ }
+}
+
+static wchar_t helpfile[MAX_PATH] = L"";
+
+HWND khm_html_help(HWND hwnd, wchar_t * suffix,
+ UINT command, DWORD_PTR data) {
+
+ wchar_t gpath[MAX_PATH + MAX_PATH];
+
+ if (!*helpfile) {
+ DWORD dw;
+ wchar_t ppath[MAX_PATH];
+
+ dw = GetModuleFileName(NULL, ppath, ARRAYLENGTH(ppath));
+
+ if (dw == 0) {
+ StringCbCopy(helpfile, sizeof(helpfile), NIDM_HELPFILE);
+ } else {
+ PathRemoveFileSpec(ppath);
+ PathAppend(ppath, NIDM_HELPFILE);
+ StringCbCopy(helpfile, sizeof(helpfile), ppath);
+ }
+ }
+
+ StringCbCopy(gpath, sizeof(gpath), helpfile);
+
+ if (suffix)
+ StringCbCat(gpath, sizeof(gpath), suffix);
+
+ return HtmlHelp(hwnd, gpath, command, data);
+}
+
+void khm_load_default_modules(void) {
+ kmm_load_default_modules();
+}
+
+int khm_compare_version(const khm_version * v1, const khm_version * v2) {
+
+ if (v1->major != v2->major)
+ return ((int)v1->major) - ((int)v2->major);
+
+ if (v1->minor != v2->minor)
+ return ((int)v1->minor) - ((int)v2->minor);
+
+ if (v1->patch != v2->patch)
+ return ((int)v1->patch) - ((int)v2->patch);
+
+ return ((int)v1->aux - ((int)v2->aux));
+}
+
+int WINAPI WinMain(HINSTANCE hInstance,
+ HINSTANCE hPrevInstance,
+ LPSTR lpCmdLine,
+ int nCmdShow)
+{
+ int rv = 0;
+ HANDLE h_appmutex;
+ BOOL slave = FALSE;
+ int mutex_retries = 5;
+
+ khm_hInstance = hInstance;
+ khm_nCmdShow = nCmdShow;
+
+ khm_parse_commandline();
+
+ if (khm_startup.error_exit)
+ return 0;
+
+ _retry_mutex:
+
+ if (--mutex_retries < 0)
+ return 2;
+
+ h_appmutex = CreateMutex(NULL, FALSE, L"Local\\NetIDMgr_GlobalAppMutex");
+ if (h_appmutex == NULL)
+ return 5;
+ if (GetLastError() == ERROR_ALREADY_EXISTS)
+ slave = TRUE;
+
+ khc_load_schema(NULL, schema_uiconfig);
+
+ _start_app:
+
+ if(!slave) {
+
+ PDESCTHREAD(L"UI", L"App");
+
+ /* set this so that we don't accidently invoke an API that
+ inadvertently puts up the new creds dialog at an
+ inopportune moment, like, say, during the new creds dialog
+ is open. This only affects this process, and any child
+ processes started by plugins. */
+ SetEnvironmentVariable(L"KERBEROSLOGIN_NEVER_PROMPT", L"1");
+
+ khm_version_init();
+
+ khm_commctl_version = khm_get_commctl_version(NULL);
+
+ /* we only open a main window if this is the only instance
+ of the application that is running. */
+ kmq_init();
+ khm_init_gui();
+ kmm_init();
+
+ kmq_set_completion_handler(KMSG_CRED, kmsg_cred_completion);
+
+ kherr_add_ctx_handler(khm_err_ctx_completion_handler,
+ KHERR_CTX_END,
+ 0);
+
+ /* load the standard plugins */
+ khm_load_default_modules();
+
+ khm_register_window_classes();
+
+ khm_init_request_daemon();
+
+ khm_create_main_window();
+
+ if (!khm_startup.no_main_window)
+ khm_show_main_window();
+
+ khm_refresh_config();
+
+ rv = (int) khm_message_loop();
+
+ kmq_set_completion_handler(KMSG_CRED, NULL);
+
+ khm_exit_request_daemon();
+
+ kmm_exit();
+ khm_exit_gui();
+ khm_unregister_window_classes();
+ kmq_exit();
+
+ CloseHandle(h_appmutex);
+ } else {
+ HWND hwnd = NULL;
+ int retries = 5;
+ HANDLE hmap;
+ wchar_t mapname[256];
+ DWORD tid;
+ void * xfer;
+ khm_query_app_version query_app_version;
+ khm_version v;
+ BOOL use_cmd_v2 = TRUE;
+ khm_size cb = 0;
+
+ CloseHandle(h_appmutex);
+
+ while (hwnd == NULL && retries) {
+ hwnd = FindWindowEx(NULL, NULL, KHUI_MAIN_WINDOW_CLASS, NULL);
+
+ if (hwnd)
+ break;
+
+ retries--;
+
+ /* if the app was just starting, we might have to wait
+ till the main window is created. */
+
+ Sleep(1000);
+ }
+
+ if (!hwnd) {
+
+ /* if the app was just exiting, we might see the mutex but
+ not the window. We go back and check if the mutex is
+ still there. */
+
+ goto _retry_mutex;
+ }
+
+ /* first check if the remote instance supports a version
+ query */
+
+ StringCbPrintf(mapname, sizeof(mapname),
+ QUERY_APP_VER_MAP_FMT,
+ (tid = GetCurrentThreadId()));
+
+ hmap = CreateFileMapping(INVALID_HANDLE_VALUE,
+ NULL,
+ PAGE_READWRITE,
+ 0,
+ 4096,
+ mapname);
+
+ if (hmap == NULL)
+ return 3;
+
+ xfer = MapViewOfFile(hmap, FILE_MAP_WRITE, 0, 0,
+ sizeof(query_app_version));
+
+ ZeroMemory(&query_app_version, sizeof(query_app_version));
+
+ if (xfer) {
+ query_app_version.magic = KHM_QUERY_APP_VER_MAGIC;
+ query_app_version.code = KHM_ERROR_NOT_IMPLEMENTED;
+ query_app_version.ver_caller = app_version;
+
+ query_app_version.request_swap = TRUE;
+
+ memcpy(xfer, &query_app_version, sizeof(query_app_version));
+
+ SendMessage(hwnd, WM_KHUI_QUERY_APP_VERSION,
+ 0, (LPARAM) tid);
+
+ memcpy(&query_app_version, xfer, sizeof(query_app_version));
+
+ UnmapViewOfFile(xfer);
+ xfer = NULL;
+ }
+
+ CloseHandle(hmap);
+ hmap = NULL;
+
+ if (query_app_version.magic != KHM_QUERY_APP_VER_MAGIC ||
+ query_app_version.code != KHM_ERROR_SUCCESS) {
+
+ /* We managed to communicate with the remote instance, but
+ it didn't send us useful information. The remote
+ instance is not running an actual NetIDMgr instance.
+ However, it owns a top level window that was registered
+ with our classname. This instance won't function
+ properly if we let it proceed.
+ */
+
+ wchar_t error_msg[1024];
+ wchar_t error_title[256];
+
+ LoadString(khm_hInstance, IDS_REMOTE_FAIL_TITLE,
+ error_title, ARRAYLENGTH(error_title));
+ LoadString(khm_hInstance, IDS_REMOTE_FAIL,
+ error_msg, ARRAYLENGTH(error_msg));
+
+ MessageBox(NULL, error_msg, error_title,
+ MB_OK);
+
+ goto done_with_remote;
+ }
+
+ if (query_app_version.code == KHM_ERROR_SUCCESS &&
+ query_app_version.request_swap) {
+ /* the request for swap was granted. We can now
+ initialize our instance as the master instance. */
+
+ slave = FALSE;
+ goto _start_app;
+ }
+
+ /* Now we can work on sending the command-line to the remote
+ instance. However we need to figure out which version of
+ the startup structure it supports. */
+ v.major = 1;
+ v.minor = 2;
+ v.patch = 0;
+ v.aux = 0;
+
+ if (khm_compare_version(&query_app_version.ver_remote, &app_version) == 0 ||
+ khm_compare_version(&query_app_version.ver_remote, &v) > 0)
+ use_cmd_v2 = TRUE;
+ else
+ use_cmd_v2 = FALSE;
+
+ StringCbPrintf(mapname, sizeof(mapname),
+ COMMANDLINE_MAP_FMT,
+ (tid = GetCurrentThreadId()));
+
+ cb = max(sizeof(struct tag_khm_startup_options_v1),
+ sizeof(struct tag_khm_startup_options_v2));
+
+ cb = UBOUNDSS(cb, 4096, 4096);
+
+#ifdef DEBUG
+ assert(cb >= 4096);
+#endif
+
+ hmap = CreateFileMapping(INVALID_HANDLE_VALUE,
+ NULL,
+ PAGE_READWRITE,
+ 0,
+ (DWORD) cb,
+ mapname);
+
+ if (hmap == NULL)
+ return 3;
+
+ /* make the call */
+
+ if (use_cmd_v2) {
+ /* use the v2 structure */
+ struct tag_khm_startup_options_v2 v2opt;
+
+ ZeroMemory(&v2opt, sizeof(v2opt));
+
+ v2opt.magic = STARTUP_OPTIONS_MAGIC;
+ v2opt.cb_size = sizeof(v2opt);
+
+ v2opt.init = khm_startup.init;
+ v2opt.import = khm_startup.import;
+ v2opt.renew = khm_startup.renew;
+ v2opt.destroy = khm_startup.destroy;
+
+ v2opt.autoinit = khm_startup.autoinit;
+ v2opt.remote_exit = khm_startup.remote_exit;
+
+ v2opt.code = KHM_ERROR_NOT_IMPLEMENTED;
+
+ xfer = MapViewOfFile(hmap,
+ FILE_MAP_WRITE,
+ 0, 0,
+ sizeof(v2opt));
+
+ if (xfer) {
+ memcpy(xfer, &v2opt, sizeof(v2opt));
+
+ SendMessage(hwnd, WM_KHUI_ASSIGN_COMMANDLINE_V2,
+ 0, (LPARAM) tid);
+
+ memcpy(&v2opt, xfer, sizeof(v2opt));
+
+ /* If the request looks like it wasn't processed, we
+ fallback to the v1 request. */
+
+ if (v2opt.code == KHM_ERROR_NOT_IMPLEMENTED)
+ use_cmd_v2 = FALSE;
+
+ UnmapViewOfFile(xfer);
+ xfer = NULL;
+ }
+ }
+
+ if (!use_cmd_v2) {
+ /* use the v1 structure */
+
+ struct tag_khm_startup_options_v1 v1opt;
+
+ ZeroMemory(&v1opt, sizeof(v1opt));
+
+ v1opt.init = khm_startup.init;
+ v1opt.import = khm_startup.import;
+ v1opt.renew = khm_startup.renew;
+ v1opt.destroy = khm_startup.destroy;
+ v1opt.autoinit = khm_startup.autoinit;
+
+ xfer = MapViewOfFile(hmap,
+ FILE_MAP_WRITE,
+ 0, 0,
+ sizeof(v1opt));
+
+ if (xfer) {
+ memcpy(xfer, &v1opt, sizeof(v1opt));
+
+ SendMessage(hwnd, WM_KHUI_ASSIGN_COMMANDLINE_V1,
+ 0, (LPARAM) tid);
+
+ UnmapViewOfFile(xfer);
+ xfer = NULL;
+ }
+ }
+
+ done_with_remote:
+
+ if (hmap)
+ CloseHandle(hmap);
+ }
+
+#if defined(DEBUG) && (defined(KH_BUILD_PRIVATE) || defined(KH_BUILD_SPECIAL))
+ {
+ FILE * f = NULL;
+
+ KHMEXP void KHMAPI khcint_dump_handles(FILE * f);
+ KHMEXP void KHMAPI perf_dump(FILE * f);
+ KHMEXP void KHMAPI kmqint_dump(FILE * f);
+
+#if _MSC_VER >= 1400
+ if (fopen_s(&f, "memleak.txt", "w") != 0)
+ goto done_with_dump;
+#else
+ f = fopen("memleak.txt", "w");
+ if (f == NULL)
+ goto done_with_dump;
+#endif
+
+ perf_dump(f);
+ khcint_dump_handles(f);
+ kmqint_dump(f);
+
+ fclose(f);
+
+ done_with_dump:
+ ;
+ }
+#endif
+
+ return rv;
+}
diff --git a/src/windows/identity/ui/mainmenu.c b/src/windows/identity/ui/mainmenu.c
index 6634549b4c..bc45bddb3b 100644
--- a/src/windows/identity/ui/mainmenu.c
+++ b/src/windows/identity/ui/mainmenu.c
@@ -1,1139 +1,1139 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- * Copyright (c) 2007 Secure Endpoints Inc.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<khmapp.h>
-#include<assert.h>
-
-HWND khui_main_menu_toolbar;
-int mm_last_hot_item = -1;
-int mm_next_hot_item = -1;
-BOOL mm_hot_track = FALSE;
-
-#define MAX_ILIST 256
-/* not the same as MENU_SIZE_ICON_* */
-#define ILIST_ICON_X 16
-#define ILIST_ICON_Y 15
-
-khui_ilist * il_icon;
-int il_icon_id[MAX_ILIST];
-
-void khui_init_menu(void) {
- int i;
-
- il_icon = khui_create_ilist(ILIST_ICON_X,
- ILIST_ICON_Y,
- MAX_ILIST, 5, 0);
- for(i=0;i<MAX_ILIST;i++)
- il_icon_id[i] = -1;
-
- khm_refresh_identity_menus();
-}
-
-void khui_exit_menu(void) {
- khui_delete_ilist(il_icon);
-}
-
-int khui_get_icon_index(int id) {
- int i;
- HBITMAP hbm;
-
- for(i=0;i<MAX_ILIST;i++)
- if(il_icon_id[i] == id) {
- return i;
- }
-
- hbm = LoadImage(khm_hInstance,
- MAKEINTRESOURCE(id),
- IMAGE_BITMAP,
- ILIST_ICON_X, ILIST_ICON_Y,
- LR_DEFAULTCOLOR);
- i = khui_ilist_add_masked(il_icon, hbm, KHUI_TOOLBAR_BGCOLOR);
- il_icon_id[i] = id;
- DeleteObject(hbm);
-
- return i;
-}
-
-void khm_get_action_caption(khm_int32 action, wchar_t * buf, khm_size cb_buf) {
- khui_action * act;
-
- StringCbCopy(buf, cb_buf, L"");
-
- khui_action_lock();
- act = khui_find_action(action);
-
- if (act == NULL)
- goto done;
-
- if (act->caption) {
- StringCbCopy(buf, cb_buf, act->caption);
- } else if (act->is_caption) {
- LoadString(khm_hInstance, act->is_caption,
- buf, (int)(cb_buf / sizeof(wchar_t)));
- }
-
- done:
- khui_action_unlock();
-}
-
-void khm_get_action_tooltip(khm_int32 action, wchar_t * buf, khm_size cb_buf) {
- khui_action * act;
-
- StringCbCopy(buf, cb_buf, L"");
-
- khui_action_lock();
- act = khui_find_action(action);
-
- if (act == NULL)
- goto done;
-
- if (act->tooltip) {
- StringCbCopy(buf, cb_buf, act->tooltip);
- } else if (act->is_tooltip) {
- LoadString(khm_hInstance, act->is_tooltip,
- buf, (int) (cb_buf / sizeof(wchar_t)));
- }
-
- done:
- khui_action_unlock();
-}
-
-void add_action_to_menu(HMENU hm, khui_action * act,
- int idx, int flags) {
- MENUITEMINFO mii;
- wchar_t buf[MAX_RES_STRING] = L"";
- wchar_t accel[MAX_RES_STRING] = L"";
-
- assert(!act || act->cmd);
-
- mii.cbSize = sizeof(mii);
- mii.fMask = 0;
-
- if(act == NULL) {
- mii.fMask = MIIM_FTYPE;
- mii.fType = MFT_SEPARATOR;
- } else {
- khui_menu_def * def;
-
- khm_get_action_caption(act->cmd, buf, sizeof(buf));
-
- if(khui_get_cmd_accel_string(act->cmd, accel,
- ARRAYLENGTH(accel))) {
- StringCbCat(buf, sizeof(buf), L"\t");
- StringCbCat(buf, sizeof(buf), accel);
- }
-
- mii.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_ID;
- mii.fType = MFT_STRING;
-
- mii.dwTypeData = buf;
- mii.cch = (int) wcslen(buf);
-
- mii.wID = act->cmd;
-
- if(act->state & KHUI_ACTIONSTATE_DISABLED) {
- mii.fMask |= MIIM_STATE;
- mii.fState = MFS_DISABLED;
- } else {
- mii.fState = 0;
- }
-
- if((act->type & KHUI_ACTIONTYPE_TOGGLE) &&
- (act->state & KHUI_ACTIONSTATE_CHECKED)) {
- mii.fMask |= MIIM_STATE;
- mii.fState |= MFS_CHECKED;
- }
-
- if(act->ib_icon) {
- mii.fMask |= MIIM_BITMAP;
- mii.hbmpItem = HBMMENU_CALLBACK;
- }
-
- if (flags & KHUI_ACTIONREF_SUBMENU) {
- def = khui_find_menu(act->cmd);
- if(def) {
- mii.fMask |= MIIM_SUBMENU;
- mii.hSubMenu = mm_create_menu_from_def(def, FALSE);
- }
- }
-
- if(flags & KHUI_ACTIONREF_DEFAULT) {
- mii.fMask |= MIIM_STATE;
- mii.fState |= MFS_DEFAULT;
- }
- }
-
- InsertMenuItem(hm,idx,TRUE,&mii);
-}
-
-static void refresh_menu(HMENU hm, khui_menu_def * def);
-
-static int refresh_menu_item(HMENU hm, khui_action * act,
- int idx, int flags) {
- MENUITEMINFO mii;
- khui_menu_def * def;
-
- mii.cbSize = sizeof(mii);
- mii.fMask = 0;
-
- if (flags & KHUI_ACTIONREF_END) {
- /* we have been asked to assert that the menu doesn't have
- more than idx items */
- mii.fMask = MIIM_FTYPE;
- while (GetMenuItemInfo(hm, idx, TRUE, &mii)) {
- RemoveMenu(hm, idx, MF_BYPOSITION);
- mii.fMask = MIIM_FTYPE;
- }
-
- return 0;
- }
-
- /* Check if the menu item is there. Otherwise we need to add
- it. */
- mii.fMask = MIIM_STATE | MIIM_ID | MIIM_FTYPE;
- if (!GetMenuItemInfo(hm, idx, TRUE, &mii) ||
- ((flags & KHUI_ACTIONREF_SEP) && !(mii.fType & MFT_SEPARATOR)) ||
- (!(flags & KHUI_ACTIONREF_SEP) && mii.wID != act->cmd)) {
- add_action_to_menu(hm, ((flags & KHUI_ACTIONREF_SEP)? NULL : act),
- idx, flags);
- return 0;
- }
-
- if (flags & KHUI_ACTIONREF_SEP)
- return 0;
-
-#ifdef DEBUG
- assert(act);
-#endif
- if (!act)
- return 0;
-
- if (flags & KHUI_ACTIONREF_DEFAULT) {
- if (!(mii.fState & MFS_DEFAULT)) {
- mii.fMask |= MIIM_STATE;
- mii.fState |= MFS_DEFAULT;
- }
- } else {
- if (mii.fState & MFS_DEFAULT) {
- RemoveMenu(hm, idx, MF_BYPOSITION);
- add_action_to_menu(hm, act, idx, flags);
- return 0;
- }
- }
-
- mii.fMask = 0;
-
- if(act->state & KHUI_ACTIONSTATE_DISABLED) {
- mii.fMask |= MIIM_STATE;
- mii.fState &= ~MFS_ENABLED;
- mii.fState |= MFS_DISABLED;
- } else {
- mii.fMask |= MIIM_STATE;
- mii.fState &= ~MFS_DISABLED;
- mii.fState |= MFS_ENABLED;
- }
-
- if(act->type & KHUI_ACTIONTYPE_TOGGLE) {
- mii.fMask |= MIIM_STATE;
- if (act->state & KHUI_ACTIONSTATE_CHECKED) {
- mii.fState &= ~MFS_UNCHECKED;
- mii.fState |= MFS_CHECKED;
- } else {
- mii.fState &= ~MFS_CHECKED;
- mii.fState |= MFS_UNCHECKED;
- }
- }
-
- SetMenuItemInfo(hm, act->cmd, FALSE, &mii);
-
- def = khui_find_menu(act->cmd);
-
- if(def) {
- MENUITEMINFO mii2;
-
- mii2.cbSize = sizeof(mii2);
- mii2.fMask = MIIM_SUBMENU;
-
- if (GetMenuItemInfo(hm, act->cmd, FALSE, &mii2)) {
- refresh_menu(mii2.hSubMenu, def);
- }
- }
-
- return 0;
-}
-
-
-static void refresh_menu(HMENU hm, khui_menu_def * def) {
- khui_action_ref * act;
- khm_size i, n;
-
- for(i = 0, n = khui_menu_get_size(def); i < n; i++) {
- act = khui_menu_get_action(def, i);
- refresh_menu_item(hm, khui_find_action(act->action), (int) i, act->flags);
- }
-
- refresh_menu_item(hm, NULL, (int) i, KHUI_ACTIONREF_END);
-}
-
-static HMENU mm_create_menu_from_def(khui_menu_def * def, BOOL main) {
- HMENU hm;
- khui_action_ref * act;
- khm_size i, n;
-
- if (main)
- hm = CreateMenu();
- else
- hm = CreatePopupMenu();
-
- for (i = 0, n = khui_menu_get_size(def); i < n; i++) {
- act = khui_menu_get_action(def, i);
- add_action_to_menu(hm, khui_find_action(act->action), (int) i, act->flags);
- }
-
- return hm;
-}
-
-void mm_begin_hot_track(void);
-void mm_end_hot_track(void);
-
-static void mm_show_panel_def(khui_menu_def * def, LONG x, LONG y)
-{
- HMENU hm;
-
- hm = mm_create_menu_from_def(def, FALSE);
-
- mm_hot_track = (mm_last_hot_item >= 0);
-
- if (mm_hot_track)
- mm_begin_hot_track();
-
- TrackPopupMenuEx(hm,
- TPM_LEFTALIGN | TPM_TOPALIGN |
- TPM_VERPOSANIMATION,
- x, y, khm_hwnd_main, NULL);
-
- mm_last_hot_item = -1;
-
- if (mm_hot_track)
- mm_end_hot_track();
-
- mm_hot_track = FALSE;
-
- DestroyMenu(hm);
-}
-
-void khm_menu_show_panel(int id, LONG x, LONG y) {
- khui_menu_def * def;
-
- def = khui_find_menu(id);
- if(!def)
- return;
-
- mm_show_panel_def(def, x, y);
-}
-
-LRESULT khm_menu_activate(int menu_id) {
- khui_menu_def * mmdef;
- int nmm;
-
- mmdef = khui_find_menu(KHUI_MENU_MAIN);
- nmm = (int) khui_action_list_length(mmdef->items);
-
- if(menu_id == MENU_ACTIVATE_DEFAULT) {
- if (mm_last_hot_item != -1)
- menu_id = mm_last_hot_item;
- else
- menu_id = 0;
- } else if(menu_id == MENU_ACTIVATE_LEFT) {
- menu_id = (mm_last_hot_item > 0)?
- mm_last_hot_item - 1:
- ((mm_last_hot_item == 0)? nmm - 1: 0);
- } else if(menu_id == MENU_ACTIVATE_RIGHT) {
- menu_id = (mm_last_hot_item >=0 && mm_last_hot_item < nmm - 1)?
- mm_last_hot_item + 1:
- 0;
- } else if(menu_id == MENU_ACTIVATE_NONE) {
- menu_id = -1;
- }
-
- SendMessage(khui_main_menu_toolbar,
- TB_SETHOTITEM,
- menu_id,
- 0);
-
- khm_menu_track_current();
-
- return TRUE;
-}
-
-LRESULT khm_menu_measure_item(WPARAM wParam, LPARAM lParam) {
- /* all menu icons have a fixed size */
- LPMEASUREITEMSTRUCT lpm = (LPMEASUREITEMSTRUCT) lParam;
- lpm->itemWidth = MENU_SIZE_ICON_X;
- lpm->itemHeight = MENU_SIZE_ICON_Y;
- return TRUE;
-}
-
-LRESULT khm_menu_draw_item(WPARAM wParam, LPARAM lParam) {
- LPDRAWITEMSTRUCT lpd;
- khui_action * act;
- int resid;
- int iidx;
- UINT style;
-
- lpd = (LPDRAWITEMSTRUCT) lParam;
- act = khui_find_action(lpd->itemID);
-
- resid = 0;
- if((lpd->itemState & ODS_DISABLED) || (lpd->itemState & ODS_GRAYED)) {
- resid = act->ib_icon_dis;
- }
- if(!resid)
- resid = act->ib_icon;
-
- if(!resid) /* nothing to draw */
- return TRUE;
-
-
- iidx = khui_get_icon_index(resid);
- if(iidx == -1)
- return TRUE;
-
-
- style = ILD_TRANSPARENT;
- if(lpd->itemState & ODS_HOTLIGHT || lpd->itemState & ODS_SELECTED) {
- style |= ILD_SELECTED;
- }
-
- khui_ilist_draw(il_icon,
- iidx,
- lpd->hDC,
- lpd->rcItem.left, lpd->rcItem.top, style);
-
- return TRUE;
-}
-
-void khm_track_menu(int menu) {
- TBBUTTON bi;
- RECT r;
- RECT wr;
-
- if (menu != -1)
- mm_last_hot_item = menu;
-
- if (mm_last_hot_item != -1) {
- SendMessage(khui_main_menu_toolbar,
- TB_GETBUTTON,
- mm_last_hot_item,
- (LPARAM) &bi);
-
- SendMessage(khui_main_menu_toolbar,
- TB_GETITEMRECT,
- mm_last_hot_item,
- (LPARAM) &r);
-
- GetWindowRect(khui_main_menu_toolbar, &wr);
-
- khm_menu_show_panel(bi.idCommand, wr.left + r.left, wr.top + r.bottom);
-
- r.left = 0;
-
- if (mm_next_hot_item != -1) {
- mm_last_hot_item = mm_next_hot_item;
- mm_next_hot_item = -1;
-
- PostMessage(khm_hwnd_main, WM_COMMAND,
- MAKEWPARAM(KHUI_PACTION_MENU,0),
- MAKELPARAM(mm_last_hot_item,1));
- }
- }
-}
-
-void khm_menu_track_current(void) {
- khm_track_menu(-1);
-}
-
-LRESULT khm_menu_handle_select(WPARAM wParam, LPARAM lParam) {
- if((HIWORD(wParam) == 0xffff && lParam == 0) ||
- (HIWORD(wParam) & MF_POPUP)) {
- /* the menu was closed */
- khm_statusbar_set_part(KHUI_SBPART_INFO, NULL, NULL);
- } else {
- khui_action * act;
- int id;
- wchar_t buf[MAX_RES_STRING] = L"";
-
- id = LOWORD(wParam);
- act = khui_find_action(id);
- if(act == NULL || (act->is_tooltip == 0 && act->tooltip == NULL))
- khm_statusbar_set_part(KHUI_SBPART_INFO, NULL, NULL);
- else {
- khm_get_action_tooltip(act->cmd, buf, sizeof(buf));
-
- khm_statusbar_set_part(KHUI_SBPART_INFO, NULL, buf);
- }
- }
- return 0;
-}
-
-HHOOK mm_hevt_hook = NULL;
-HWND mm_hwnd_menu_panel = NULL;
-
-LRESULT CALLBACK mm_event_filter(int code,
- WPARAM wParam,
- LPARAM lParam) {
- MSG * m;
- RECT r;
- int x,y;
-
- if (code == MSGF_MENU) {
- /* do stuff */
- m = (MSG *) lParam;
- GetWindowRect(khui_main_menu_toolbar, &r);
-
- if (m->hwnd != khm_hwnd_main)
- mm_hwnd_menu_panel = m->hwnd;
-
- switch(m->message) {
- case WM_MOUSEMOVE:
-
- x = GET_X_LPARAM(m->lParam);
- y = GET_Y_LPARAM(m->lParam);
- x -= r.left;
- y -= r.top;
-
- SendMessage(khui_main_menu_toolbar,
- m->message,
- m->wParam,
- MAKELPARAM(x,y));
- break;
- }
- }
-
- return CallNextHookEx(mm_hevt_hook, code, wParam, lParam);
-}
-
-
-void mm_begin_hot_track(void) {
-
- if (mm_hevt_hook)
- UnhookWindowsHookEx(mm_hevt_hook);
-
- mm_hevt_hook = SetWindowsHookEx(WH_MSGFILTER,
- mm_event_filter,
- NULL,
- GetCurrentThreadId());
-}
-
-void mm_end_hot_track(void) {
- if (mm_hevt_hook)
- UnhookWindowsHookEx(mm_hevt_hook);
-
- mm_hevt_hook = NULL;
- mm_hwnd_menu_panel = NULL;
-}
-
-void mm_cancel_menu(void) {
- if (mm_hwnd_menu_panel)
- SendMessage(mm_hwnd_menu_panel, WM_CANCELMODE, 0, 0);
-}
-
-LRESULT khm_menu_notify_main(LPNMHDR notice) {
- LPNMTOOLBAR nmt;
- LRESULT ret = FALSE;
- RECT r;
- khui_menu_def * mmdef;
- khui_action_ref * mm;
- int nmm;
-
- mmdef = khui_find_menu(KHUI_MENU_MAIN);
- mm = mmdef->items;
- nmm = (int) khui_action_list_length(mm);
-
- GetWindowRect(khui_main_menu_toolbar, &r);
-
- nmt = (LPNMTOOLBAR) notice;
- switch(notice->code) {
- case TBN_DROPDOWN:
- khm_track_menu(-1);
- /*
- khm_menu_show_panel(nmt->iItem,
- r.left + nmt->rcButton.left,
- r.top + nmt->rcButton.bottom);
- */
- ret = TBDDRET_DEFAULT;
- break;
-
- case TBN_HOTITEMCHANGE:
- {
- LPNMTBHOTITEM nmhi;
- int new_item = -1;
-
- nmhi = (LPNMTBHOTITEM) notice;
-
- if(nmhi->dwFlags & HICF_LEAVING)
- new_item = -1;
- else {
- int i;
- for(i=0; i < nmm; i++) {
- if(mm[i].action == nmhi->idNew) {
- new_item = i;
- break;
- }
- }
- }
-
- if (mm_hot_track &&
- new_item != mm_last_hot_item &&
- new_item != -1 &&
- mm_last_hot_item != -1) {
-
- EndMenu();
- mm_next_hot_item = new_item;
-
- }
-
- ret = 0;
-
- if (!mm_hot_track || new_item != -1)
- mm_last_hot_item = new_item;
-
- } break;
-
- default:
- /* hmm. what to do */
- ret = FALSE;
- }
- return ret;
-}
-
-struct identity_action_map {
- khm_handle identity;
- khm_int32 renew_cmd;
- khm_int32 destroy_cmd;
- khm_int32 new_cmd;
- int refreshcycle;
-};
-
-#define IDMAP_ALLOC_INCR 8
-
-struct identity_action_map * id_action_map = NULL;
-khm_size n_id_action_map = 0;
-khm_size nc_id_action_map = 0;
-
-int idcmd_refreshcycle = 0;
-
-static struct identity_action_map *
-create_identity_cmd_map(khm_handle ident) {
-
- struct identity_action_map * actmap;
- wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
- wchar_t fmt[128];
- wchar_t caption[KHUI_MAXCCH_SHORT_DESC];
- wchar_t tooltip[KHUI_MAXCCH_SHORT_DESC];
- wchar_t actionname[KHUI_MAXCCH_NAME];
- khm_size cb;
-
- if (n_id_action_map + 1 > nc_id_action_map) {
- nc_id_action_map = UBOUNDSS(n_id_action_map + 1,
- IDMAP_ALLOC_INCR,
- IDMAP_ALLOC_INCR);
-#ifdef DEBUG
- assert(nc_id_action_map > n_id_action_map + 1);
-#endif
- id_action_map = PREALLOC(id_action_map,
- nc_id_action_map * sizeof(id_action_map[0]));
-#ifdef DEBUG
- assert(id_action_map);
-#endif
- ZeroMemory(&id_action_map[n_id_action_map],
- sizeof(id_action_map[0]) * (nc_id_action_map - n_id_action_map));
- }
-
- actmap = &id_action_map[n_id_action_map];
- n_id_action_map++;
-
- cb = sizeof(idname);
- kcdb_identity_get_name(ident, idname, &cb);
-
- actmap->identity = ident;
- kcdb_identity_hold(ident);
-
-#define GETFORMAT(I) do { fmt[0] = L'\0'; LoadString(khm_hInstance, I, fmt, ARRAYLENGTH(fmt)); } while(0)
-#define EXPFORMAT(d,s) do { StringCbPrintf(d, sizeof(d), fmt, s); } while(0)
- /* renew */
-
- GETFORMAT(IDS_IDACTIONT_RENEW);
- EXPFORMAT(tooltip, idname);
-
- GETFORMAT(IDS_IDACTION_RENEW);
- EXPFORMAT(caption, idname);
-
- StringCbPrintf(actionname, sizeof(actionname), L"R:%s", idname);
-
- actmap->renew_cmd =
- khui_action_create(actionname, caption, tooltip, NULL,
- KHUI_ACTIONTYPE_TRIGGER, NULL);
-
- /* destroy */
-
- GETFORMAT(IDS_IDACTIONT_DESTROY);
- EXPFORMAT(tooltip, idname);
-
- GETFORMAT(IDS_IDACTION_DESTROY);
- EXPFORMAT(caption, idname);
-
- StringCbPrintf(actionname, sizeof(actionname), L"D:%s", idname);
-
- actmap->destroy_cmd =
- khui_action_create(actionname, caption, tooltip, NULL,
- KHUI_ACTIONTYPE_TRIGGER, NULL);
-
- /* new */
-
- GETFORMAT(IDS_IDACTIONT_NEW);
- EXPFORMAT(tooltip, idname);
-
- GETFORMAT(IDS_IDACTION_NEW);
- EXPFORMAT(caption, idname);
-
- StringCbPrintf(actionname, sizeof(actionname), L"N:%s", idname);
-
- actmap->new_cmd =
- khui_action_create(actionname, caption, tooltip, NULL,
- KHUI_ACTIONTYPE_TRIGGER, NULL);
-
- actmap->refreshcycle = idcmd_refreshcycle;
-
-#undef GETFORMAT
-#undef EXPFORMAT
-
- return actmap;
-}
-
-static void
-purge_identity_cmd_map(void) {
- khm_size i;
-
- for (i=0; i < n_id_action_map; i++) {
- khm_handle ident;
-
- if (id_action_map[i].refreshcycle != idcmd_refreshcycle) {
- ident = id_action_map[i].identity;
- id_action_map[i].identity = NULL;
- kcdb_identity_release(ident);
-
- khui_action_delete(id_action_map[i].renew_cmd);
- khui_action_delete(id_action_map[i].destroy_cmd);
-
- id_action_map[i].renew_cmd = 0;
- id_action_map[i].destroy_cmd = 0;
- }
- }
-}
-
-static struct identity_action_map *
-get_identity_cmd_map(khm_handle ident) {
- khm_size i;
-
- for (i=0; i < n_id_action_map; i++) {
- if (kcdb_identity_is_equal(id_action_map[i].identity,
- ident))
- break;
- }
-
- if (i < n_id_action_map) {
- id_action_map[i].refreshcycle = idcmd_refreshcycle;
- return &id_action_map[i];
- } else {
- return create_identity_cmd_map(ident);
- }
-}
-
-khm_int32
-khm_get_identity_renew_action(khm_handle ident) {
- struct identity_action_map * map;
-
- map = get_identity_cmd_map(ident);
-
- if (map)
- return map->renew_cmd;
- else
- return 0;
-}
-
-khm_int32
-khm_get_identity_destroy_action(khm_handle ident) {
- struct identity_action_map * map;
-
- map = get_identity_cmd_map(ident);
-
- if (map)
- return map->destroy_cmd;
- else
- return 0;
-}
-
-khm_int32
-khm_get_identity_new_creds_action(khm_handle ident) {
- struct identity_action_map * map;
-
- map = get_identity_cmd_map(ident);
-
- if (map)
- return map->new_cmd;
- else
- return 0;
-}
-
-void
-khm_refresh_identity_menus(void) {
- khui_menu_def * renew_def = NULL;
- khui_menu_def * dest_def = NULL;
- wchar_t * idlist = NULL;
- wchar_t * idname = NULL;
- khm_size cb = 0;
- khm_size n_idents = 0;
- khm_size t;
- khm_int32 rv = KHM_ERROR_SUCCESS;
- khm_handle csp_cw = NULL;
- khm_int32 idflags;
- khm_int32 def_sticky = 0;
- khm_boolean sticky_done = FALSE;
-
- if (KHM_SUCCEEDED(khc_open_space(NULL, L"CredWindow", 0, &csp_cw))) {
- khc_read_int32(csp_cw, L"DefaultSticky", &def_sticky);
- khc_close_space(csp_cw);
- csp_cw = NULL;
- }
-
- kcdb_identity_refresh_all();
-
- khui_action_lock();
-
- idcmd_refreshcycle++;
-
- do {
- if (idlist)
- PFREE(idlist);
- idlist = NULL;
- cb = 0;
-
- rv = kcdb_identity_enum(KCDB_IDENT_FLAG_ACTIVE | KCDB_IDENT_FLAG_EMPTY,
- KCDB_IDENT_FLAG_ACTIVE,
- NULL,
- &cb,
- &n_idents);
- if (rv != KHM_ERROR_TOO_LONG || cb == 0 || cb == sizeof(wchar_t) * 2)
- break;
-
- idlist = PMALLOC(cb);
-#ifdef DEBUG
- assert(idlist);
-#endif
-
- rv = kcdb_identity_enum(KCDB_IDENT_FLAG_ACTIVE | KCDB_IDENT_FLAG_EMPTY,
- KCDB_IDENT_FLAG_ACTIVE,
- idlist,
- &cb,
- &n_idents);
- if (rv == KHM_ERROR_TOO_LONG)
- continue;
-
- if (KHM_FAILED(rv)) {
- /* something else went wrong. hmm. */
- if (idlist)
- PFREE(idlist);
- idlist = NULL;
- }
- break;
-
- } while(TRUE);
-
- if (idlist != NULL && n_idents > 0) {
- khui_enable_action(KHUI_MENU_RENEW_CRED, TRUE);
- khui_enable_action(KHUI_MENU_DESTROY_CRED, TRUE);
- khui_enable_action(KHUI_ACTION_RENEW_CRED, TRUE);
- khui_enable_action(KHUI_ACTION_DESTROY_CRED, TRUE);
- } else {
- khui_enable_action(KHUI_MENU_RENEW_CRED, FALSE);
- khui_enable_action(KHUI_MENU_DESTROY_CRED, FALSE);
- khui_enable_action(KHUI_ACTION_RENEW_CRED, FALSE);
- khui_enable_action(KHUI_ACTION_DESTROY_CRED, FALSE);
- }
-
- renew_def = khui_find_menu(KHUI_MENU_RENEW_CRED);
- dest_def = khui_find_menu(KHUI_MENU_DESTROY_CRED);
-#ifdef DEBUG
- assert(renew_def);
- assert(dest_def);
-#endif
-
- t = khui_menu_get_size(renew_def);
- while(t) {
- khui_menu_remove_action(renew_def, 0);
- t--;
- }
-
- t = khui_menu_get_size(dest_def);
- while(t) {
- khui_menu_remove_action(dest_def, 0);
- t--;
- }
-
- if (idlist != NULL && n_idents > 1) {
- khui_menu_insert_action(renew_def, 0, KHUI_ACTION_RENEW_ALL, 0);
- khui_menu_insert_action(renew_def, 1, KHUI_MENU_SEP, 0);
-
- khui_menu_insert_action(dest_def, 0, KHUI_ACTION_DESTROY_ALL, 0);
- khui_menu_insert_action(dest_def, 1, KHUI_MENU_SEP, 0);
- }
-
- for (idname = idlist; idname && idname[0];
- idname = multi_string_next(idname)) {
- khm_handle identity = NULL;
-
- if (KHM_FAILED(kcdb_identity_create(idname, 0, &identity))) {
-#ifdef DEBUG
- assert(FALSE);
-#endif
- continue;
- }
-
- khui_menu_insert_action(renew_def, 1000,
- khm_get_identity_renew_action(identity),
- 0);
-
- khui_menu_insert_action(dest_def, 1000,
- khm_get_identity_destroy_action(identity),
- 0);
-
- idflags = 0;
- kcdb_identity_get_flags(identity, &idflags);
-
- if (!(idflags & KCDB_IDENT_FLAG_STICKY) && def_sticky) {
- kcdb_identity_set_flags(identity,
- KCDB_IDENT_FLAG_STICKY,
- KCDB_IDENT_FLAG_STICKY);
- sticky_done = TRUE;
- }
- }
-
- if (idlist)
- PFREE(idlist);
-
- purge_identity_cmd_map();
-
- khui_action_unlock();
-
- khui_refresh_actions();
-
- if (sticky_done) {
- InvalidateRect(khm_hwnd_main_cred, NULL, TRUE);
- }
-}
-
-khm_boolean
-khm_check_identity_menu_action(khm_int32 act_id) {
-
- if (act_id == KHUI_ACTION_DESTROY_ALL) {
- khm_size i;
-
- for (i=0; i < n_id_action_map; i++) {
- if (id_action_map[i].identity != NULL) {
- khm_cred_destroy_identity(id_action_map[i].identity);
- }
- }
-
- return TRUE;
- } else if (act_id == KHUI_ACTION_RENEW_ALL) {
- khm_size i;
-
- for (i=0; i < n_id_action_map; i++) {
- if (id_action_map[i].identity != NULL) {
- khm_cred_renew_identity(id_action_map[i].identity);
- }
- }
-
- return TRUE;
- } else {
- khm_size i;
-
- for (i=0; i < n_id_action_map; i++) {
- if (id_action_map[i].identity == NULL)
- continue;
-
- if (id_action_map[i].renew_cmd == act_id) {
- khm_cred_renew_identity(id_action_map[i].identity);
- return TRUE;
- }
-
- if (id_action_map[i].destroy_cmd == act_id) {
- khm_cred_destroy_identity(id_action_map[i].identity);
- return TRUE;
- }
-
- if (id_action_map[i].new_cmd == act_id) {
- khm_cred_obtain_new_creds_for_ident(id_action_map[i].identity,
- NULL);
- return TRUE;
- }
- }
- }
-
- return FALSE;
-}
-
-
-HMENU khui_hmenu_main = NULL;
-
-void khm_menu_refresh_items(void) {
- khui_menu_def * def;
-
- if (!khui_hmenu_main)
- return;
-
- khui_action_lock();
-
- def = khui_find_menu(KHUI_MENU_MAIN);
-
- refresh_menu(khui_hmenu_main, def);
-
- khui_action_unlock();
-
- DrawMenuBar(khm_hwnd_main);
-}
-
-void khm_menu_create_main(HWND parent) {
- HMENU hmenu;
- khui_menu_def * def;
-
- def = khui_find_menu(KHUI_MENU_MAIN);
-
- hmenu = mm_create_menu_from_def(def, TRUE);
-
- SetMenu(parent, hmenu);
-
- khui_hmenu_main = hmenu;
-
- return;
-
-#ifdef USE_EXPLORER_STYLE_MENU_BAR
- HWND hwtb;
- REBARBANDINFO rbi;
- SIZE sz;
- int i;
- khui_menu_def * mmdef;
- khui_action_ref * mm;
- int nmm;
-
- mmdef = khui_find_menu(KHUI_MENU_MAIN);
- mm = mmdef->items;
- nmm = (int) khui_action_list_length(mm);
-
- hwtb = CreateWindowEx(0
-#if (_WIN32_IE >= 0x0501)
- | TBSTYLE_EX_MIXEDBUTTONS
-#endif
- ,
- TOOLBARCLASSNAME,
- (LPWSTR) NULL,
- WS_CHILD |
- CCS_ADJUSTABLE |
- TBSTYLE_FLAT |
- TBSTYLE_AUTOSIZE |
- TBSTYLE_LIST |
- CCS_NORESIZE |
- CCS_NOPARENTALIGN |
- CCS_NODIVIDER,
- 0, 0, 0, 0, rebar,
- (HMENU) NULL, khm_hInstance,
- NULL);
-
- if(!hwtb) {
-#ifdef DEBUG
- assert(FALSE);
-#endif
- return;
- }
-
- khui_main_menu_toolbar = hwtb;
-
- SendMessage(hwtb,
- TB_BUTTONSTRUCTSIZE,
- (WPARAM) sizeof(TBBUTTON),
- 0);
-
- for(i=0; i<nmm; i++) {
- khui_add_action_to_toolbar(hwtb,
- khui_find_action(mm[i].action),
- KHUI_TOOLBAR_ADD_TEXT |
- KHUI_TOOLBAR_ADD_DROPDOWN |
- KHUI_TOOLBAR_VARSIZE,
- NULL);
- }
-
- SendMessage(hwtb,
- TB_AUTOSIZE,
- 0,0);
-
- SendMessage(hwtb,
- TB_GETMAXSIZE,
- 0,
- (LPARAM) &sz);
-
- ZeroMemory(&rbi, sizeof(rbi));
-
- rbi.cbSize = sizeof(rbi);
-
- rbi.fMask =
- RBBIM_ID |
- RBBIM_STYLE |
- RBBIM_CHILD |
- RBBIM_CHILDSIZE |
- RBBIM_SIZE |
- RBBIM_IDEALSIZE;
-
- rbi.fStyle =
- RBBS_USECHEVRON;
-
- rbi.hwndChild = hwtb;
- rbi.wID = KHUI_MENU_MAIN;
- rbi.cx = sz.cx;
- rbi.cxMinChild = rbi.cx;
- rbi.cxIdeal = rbi.cx;
- rbi.cyMinChild = sz.cy;
- rbi.cyChild = rbi.cyMinChild;
- rbi.cyIntegral = rbi.cyMinChild;
- rbi.cyMaxChild = rbi.cyMinChild;
-
- SendMessage(rebar,
- RB_INSERTBAND,
- 0,
- (LPARAM) &rbi);
-#endif
-}
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ * Copyright (c) 2007 Secure Endpoints Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<khmapp.h>
+#include<assert.h>
+
+HWND khui_main_menu_toolbar;
+int mm_last_hot_item = -1;
+int mm_next_hot_item = -1;
+BOOL mm_hot_track = FALSE;
+
+#define MAX_ILIST 256
+/* not the same as MENU_SIZE_ICON_* */
+#define ILIST_ICON_X 16
+#define ILIST_ICON_Y 15
+
+khui_ilist * il_icon;
+int il_icon_id[MAX_ILIST];
+
+void khui_init_menu(void) {
+ int i;
+
+ il_icon = khui_create_ilist(ILIST_ICON_X,
+ ILIST_ICON_Y,
+ MAX_ILIST, 5, 0);
+ for(i=0;i<MAX_ILIST;i++)
+ il_icon_id[i] = -1;
+
+ khm_refresh_identity_menus();
+}
+
+void khui_exit_menu(void) {
+ khui_delete_ilist(il_icon);
+}
+
+int khui_get_icon_index(int id) {
+ int i;
+ HBITMAP hbm;
+
+ for(i=0;i<MAX_ILIST;i++)
+ if(il_icon_id[i] == id) {
+ return i;
+ }
+
+ hbm = LoadImage(khm_hInstance,
+ MAKEINTRESOURCE(id),
+ IMAGE_BITMAP,
+ ILIST_ICON_X, ILIST_ICON_Y,
+ LR_DEFAULTCOLOR);
+ i = khui_ilist_add_masked(il_icon, hbm, KHUI_TOOLBAR_BGCOLOR);
+ il_icon_id[i] = id;
+ DeleteObject(hbm);
+
+ return i;
+}
+
+void khm_get_action_caption(khm_int32 action, wchar_t * buf, khm_size cb_buf) {
+ khui_action * act;
+
+ StringCbCopy(buf, cb_buf, L"");
+
+ khui_action_lock();
+ act = khui_find_action(action);
+
+ if (act == NULL)
+ goto done;
+
+ if (act->caption) {
+ StringCbCopy(buf, cb_buf, act->caption);
+ } else if (act->is_caption) {
+ LoadString(khm_hInstance, act->is_caption,
+ buf, (int)(cb_buf / sizeof(wchar_t)));
+ }
+
+ done:
+ khui_action_unlock();
+}
+
+void khm_get_action_tooltip(khm_int32 action, wchar_t * buf, khm_size cb_buf) {
+ khui_action * act;
+
+ StringCbCopy(buf, cb_buf, L"");
+
+ khui_action_lock();
+ act = khui_find_action(action);
+
+ if (act == NULL)
+ goto done;
+
+ if (act->tooltip) {
+ StringCbCopy(buf, cb_buf, act->tooltip);
+ } else if (act->is_tooltip) {
+ LoadString(khm_hInstance, act->is_tooltip,
+ buf, (int) (cb_buf / sizeof(wchar_t)));
+ }
+
+ done:
+ khui_action_unlock();
+}
+
+void add_action_to_menu(HMENU hm, khui_action * act,
+ int idx, int flags) {
+ MENUITEMINFO mii;
+ wchar_t buf[MAX_RES_STRING] = L"";
+ wchar_t accel[MAX_RES_STRING] = L"";
+
+ assert(!act || act->cmd);
+
+ mii.cbSize = sizeof(mii);
+ mii.fMask = 0;
+
+ if(act == NULL) {
+ mii.fMask = MIIM_FTYPE;
+ mii.fType = MFT_SEPARATOR;
+ } else {
+ khui_menu_def * def;
+
+ khm_get_action_caption(act->cmd, buf, sizeof(buf));
+
+ if(khui_get_cmd_accel_string(act->cmd, accel,
+ ARRAYLENGTH(accel))) {
+ StringCbCat(buf, sizeof(buf), L"\t");
+ StringCbCat(buf, sizeof(buf), accel);
+ }
+
+ mii.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_ID;
+ mii.fType = MFT_STRING;
+
+ mii.dwTypeData = buf;
+ mii.cch = (int) wcslen(buf);
+
+ mii.wID = act->cmd;
+
+ if(act->state & KHUI_ACTIONSTATE_DISABLED) {
+ mii.fMask |= MIIM_STATE;
+ mii.fState = MFS_DISABLED;
+ } else {
+ mii.fState = 0;
+ }
+
+ if((act->type & KHUI_ACTIONTYPE_TOGGLE) &&
+ (act->state & KHUI_ACTIONSTATE_CHECKED)) {
+ mii.fMask |= MIIM_STATE;
+ mii.fState |= MFS_CHECKED;
+ }
+
+ if(act->ib_icon) {
+ mii.fMask |= MIIM_BITMAP;
+ mii.hbmpItem = HBMMENU_CALLBACK;
+ }
+
+ if (flags & KHUI_ACTIONREF_SUBMENU) {
+ def = khui_find_menu(act->cmd);
+ if(def) {
+ mii.fMask |= MIIM_SUBMENU;
+ mii.hSubMenu = mm_create_menu_from_def(def, FALSE);
+ }
+ }
+
+ if(flags & KHUI_ACTIONREF_DEFAULT) {
+ mii.fMask |= MIIM_STATE;
+ mii.fState |= MFS_DEFAULT;
+ }
+ }
+
+ InsertMenuItem(hm,idx,TRUE,&mii);
+}
+
+static void refresh_menu(HMENU hm, khui_menu_def * def);
+
+static int refresh_menu_item(HMENU hm, khui_action * act,
+ int idx, int flags) {
+ MENUITEMINFO mii;
+ khui_menu_def * def;
+
+ mii.cbSize = sizeof(mii);
+ mii.fMask = 0;
+
+ if (flags & KHUI_ACTIONREF_END) {
+ /* we have been asked to assert that the menu doesn't have
+ more than idx items */
+ mii.fMask = MIIM_FTYPE;
+ while (GetMenuItemInfo(hm, idx, TRUE, &mii)) {
+ RemoveMenu(hm, idx, MF_BYPOSITION);
+ mii.fMask = MIIM_FTYPE;
+ }
+
+ return 0;
+ }
+
+ /* Check if the menu item is there. Otherwise we need to add
+ it. */
+ mii.fMask = MIIM_STATE | MIIM_ID | MIIM_FTYPE;
+ if (!GetMenuItemInfo(hm, idx, TRUE, &mii) ||
+ ((flags & KHUI_ACTIONREF_SEP) && !(mii.fType & MFT_SEPARATOR)) ||
+ (!(flags & KHUI_ACTIONREF_SEP) && mii.wID != act->cmd)) {
+ add_action_to_menu(hm, ((flags & KHUI_ACTIONREF_SEP)? NULL : act),
+ idx, flags);
+ return 0;
+ }
+
+ if (flags & KHUI_ACTIONREF_SEP)
+ return 0;
+
+#ifdef DEBUG
+ assert(act);
+#endif
+ if (!act)
+ return 0;
+
+ if (flags & KHUI_ACTIONREF_DEFAULT) {
+ if (!(mii.fState & MFS_DEFAULT)) {
+ mii.fMask |= MIIM_STATE;
+ mii.fState |= MFS_DEFAULT;
+ }
+ } else {
+ if (mii.fState & MFS_DEFAULT) {
+ RemoveMenu(hm, idx, MF_BYPOSITION);
+ add_action_to_menu(hm, act, idx, flags);
+ return 0;
+ }
+ }
+
+ mii.fMask = 0;
+
+ if(act->state & KHUI_ACTIONSTATE_DISABLED) {
+ mii.fMask |= MIIM_STATE;
+ mii.fState &= ~MFS_ENABLED;
+ mii.fState |= MFS_DISABLED;
+ } else {
+ mii.fMask |= MIIM_STATE;
+ mii.fState &= ~MFS_DISABLED;
+ mii.fState |= MFS_ENABLED;
+ }
+
+ if(act->type & KHUI_ACTIONTYPE_TOGGLE) {
+ mii.fMask |= MIIM_STATE;
+ if (act->state & KHUI_ACTIONSTATE_CHECKED) {
+ mii.fState &= ~MFS_UNCHECKED;
+ mii.fState |= MFS_CHECKED;
+ } else {
+ mii.fState &= ~MFS_CHECKED;
+ mii.fState |= MFS_UNCHECKED;
+ }
+ }
+
+ SetMenuItemInfo(hm, act->cmd, FALSE, &mii);
+
+ def = khui_find_menu(act->cmd);
+
+ if(def) {
+ MENUITEMINFO mii2;
+
+ mii2.cbSize = sizeof(mii2);
+ mii2.fMask = MIIM_SUBMENU;
+
+ if (GetMenuItemInfo(hm, act->cmd, FALSE, &mii2)) {
+ refresh_menu(mii2.hSubMenu, def);
+ }
+ }
+
+ return 0;
+}
+
+
+static void refresh_menu(HMENU hm, khui_menu_def * def) {
+ khui_action_ref * act;
+ khm_size i, n;
+
+ for(i = 0, n = khui_menu_get_size(def); i < n; i++) {
+ act = khui_menu_get_action(def, i);
+ refresh_menu_item(hm, khui_find_action(act->action), (int) i, act->flags);
+ }
+
+ refresh_menu_item(hm, NULL, (int) i, KHUI_ACTIONREF_END);
+}
+
+static HMENU mm_create_menu_from_def(khui_menu_def * def, BOOL main) {
+ HMENU hm;
+ khui_action_ref * act;
+ khm_size i, n;
+
+ if (main)
+ hm = CreateMenu();
+ else
+ hm = CreatePopupMenu();
+
+ for (i = 0, n = khui_menu_get_size(def); i < n; i++) {
+ act = khui_menu_get_action(def, i);
+ add_action_to_menu(hm, khui_find_action(act->action), (int) i, act->flags);
+ }
+
+ return hm;
+}
+
+void mm_begin_hot_track(void);
+void mm_end_hot_track(void);
+
+static void mm_show_panel_def(khui_menu_def * def, LONG x, LONG y)
+{
+ HMENU hm;
+
+ hm = mm_create_menu_from_def(def, FALSE);
+
+ mm_hot_track = (mm_last_hot_item >= 0);
+
+ if (mm_hot_track)
+ mm_begin_hot_track();
+
+ TrackPopupMenuEx(hm,
+ TPM_LEFTALIGN | TPM_TOPALIGN |
+ TPM_VERPOSANIMATION,
+ x, y, khm_hwnd_main, NULL);
+
+ mm_last_hot_item = -1;
+
+ if (mm_hot_track)
+ mm_end_hot_track();
+
+ mm_hot_track = FALSE;
+
+ DestroyMenu(hm);
+}
+
+void khm_menu_show_panel(int id, LONG x, LONG y) {
+ khui_menu_def * def;
+
+ def = khui_find_menu(id);
+ if(!def)
+ return;
+
+ mm_show_panel_def(def, x, y);
+}
+
+LRESULT khm_menu_activate(int menu_id) {
+ khui_menu_def * mmdef;
+ int nmm;
+
+ mmdef = khui_find_menu(KHUI_MENU_MAIN);
+ nmm = (int) khui_action_list_length(mmdef->items);
+
+ if(menu_id == MENU_ACTIVATE_DEFAULT) {
+ if (mm_last_hot_item != -1)
+ menu_id = mm_last_hot_item;
+ else
+ menu_id = 0;
+ } else if(menu_id == MENU_ACTIVATE_LEFT) {
+ menu_id = (mm_last_hot_item > 0)?
+ mm_last_hot_item - 1:
+ ((mm_last_hot_item == 0)? nmm - 1: 0);
+ } else if(menu_id == MENU_ACTIVATE_RIGHT) {
+ menu_id = (mm_last_hot_item >=0 && mm_last_hot_item < nmm - 1)?
+ mm_last_hot_item + 1:
+ 0;
+ } else if(menu_id == MENU_ACTIVATE_NONE) {
+ menu_id = -1;
+ }
+
+ SendMessage(khui_main_menu_toolbar,
+ TB_SETHOTITEM,
+ menu_id,
+ 0);
+
+ khm_menu_track_current();
+
+ return TRUE;
+}
+
+LRESULT khm_menu_measure_item(WPARAM wParam, LPARAM lParam) {
+ /* all menu icons have a fixed size */
+ LPMEASUREITEMSTRUCT lpm = (LPMEASUREITEMSTRUCT) lParam;
+ lpm->itemWidth = MENU_SIZE_ICON_X;
+ lpm->itemHeight = MENU_SIZE_ICON_Y;
+ return TRUE;
+}
+
+LRESULT khm_menu_draw_item(WPARAM wParam, LPARAM lParam) {
+ LPDRAWITEMSTRUCT lpd;
+ khui_action * act;
+ int resid;
+ int iidx;
+ UINT style;
+
+ lpd = (LPDRAWITEMSTRUCT) lParam;
+ act = khui_find_action(lpd->itemID);
+
+ resid = 0;
+ if((lpd->itemState & ODS_DISABLED) || (lpd->itemState & ODS_GRAYED)) {
+ resid = act->ib_icon_dis;
+ }
+ if(!resid)
+ resid = act->ib_icon;
+
+ if(!resid) /* nothing to draw */
+ return TRUE;
+
+
+ iidx = khui_get_icon_index(resid);
+ if(iidx == -1)
+ return TRUE;
+
+
+ style = ILD_TRANSPARENT;
+ if(lpd->itemState & ODS_HOTLIGHT || lpd->itemState & ODS_SELECTED) {
+ style |= ILD_SELECTED;
+ }
+
+ khui_ilist_draw(il_icon,
+ iidx,
+ lpd->hDC,
+ lpd->rcItem.left, lpd->rcItem.top, style);
+
+ return TRUE;
+}
+
+void khm_track_menu(int menu) {
+ TBBUTTON bi;
+ RECT r;
+ RECT wr;
+
+ if (menu != -1)
+ mm_last_hot_item = menu;
+
+ if (mm_last_hot_item != -1) {
+ SendMessage(khui_main_menu_toolbar,
+ TB_GETBUTTON,
+ mm_last_hot_item,
+ (LPARAM) &bi);
+
+ SendMessage(khui_main_menu_toolbar,
+ TB_GETITEMRECT,
+ mm_last_hot_item,
+ (LPARAM) &r);
+
+ GetWindowRect(khui_main_menu_toolbar, &wr);
+
+ khm_menu_show_panel(bi.idCommand, wr.left + r.left, wr.top + r.bottom);
+
+ r.left = 0;
+
+ if (mm_next_hot_item != -1) {
+ mm_last_hot_item = mm_next_hot_item;
+ mm_next_hot_item = -1;
+
+ PostMessage(khm_hwnd_main, WM_COMMAND,
+ MAKEWPARAM(KHUI_PACTION_MENU,0),
+ MAKELPARAM(mm_last_hot_item,1));
+ }
+ }
+}
+
+void khm_menu_track_current(void) {
+ khm_track_menu(-1);
+}
+
+LRESULT khm_menu_handle_select(WPARAM wParam, LPARAM lParam) {
+ if((HIWORD(wParam) == 0xffff && lParam == 0) ||
+ (HIWORD(wParam) & MF_POPUP)) {
+ /* the menu was closed */
+ khm_statusbar_set_part(KHUI_SBPART_INFO, NULL, NULL);
+ } else {
+ khui_action * act;
+ int id;
+ wchar_t buf[MAX_RES_STRING] = L"";
+
+ id = LOWORD(wParam);
+ act = khui_find_action(id);
+ if(act == NULL || (act->is_tooltip == 0 && act->tooltip == NULL))
+ khm_statusbar_set_part(KHUI_SBPART_INFO, NULL, NULL);
+ else {
+ khm_get_action_tooltip(act->cmd, buf, sizeof(buf));
+
+ khm_statusbar_set_part(KHUI_SBPART_INFO, NULL, buf);
+ }
+ }
+ return 0;
+}
+
+HHOOK mm_hevt_hook = NULL;
+HWND mm_hwnd_menu_panel = NULL;
+
+LRESULT CALLBACK mm_event_filter(int code,
+ WPARAM wParam,
+ LPARAM lParam) {
+ MSG * m;
+ RECT r;
+ int x,y;
+
+ if (code == MSGF_MENU) {
+ /* do stuff */
+ m = (MSG *) lParam;
+ GetWindowRect(khui_main_menu_toolbar, &r);
+
+ if (m->hwnd != khm_hwnd_main)
+ mm_hwnd_menu_panel = m->hwnd;
+
+ switch(m->message) {
+ case WM_MOUSEMOVE:
+
+ x = GET_X_LPARAM(m->lParam);
+ y = GET_Y_LPARAM(m->lParam);
+ x -= r.left;
+ y -= r.top;
+
+ SendMessage(khui_main_menu_toolbar,
+ m->message,
+ m->wParam,
+ MAKELPARAM(x,y));
+ break;
+ }
+ }
+
+ return CallNextHookEx(mm_hevt_hook, code, wParam, lParam);
+}
+
+
+void mm_begin_hot_track(void) {
+
+ if (mm_hevt_hook)
+ UnhookWindowsHookEx(mm_hevt_hook);
+
+ mm_hevt_hook = SetWindowsHookEx(WH_MSGFILTER,
+ mm_event_filter,
+ NULL,
+ GetCurrentThreadId());
+}
+
+void mm_end_hot_track(void) {
+ if (mm_hevt_hook)
+ UnhookWindowsHookEx(mm_hevt_hook);
+
+ mm_hevt_hook = NULL;
+ mm_hwnd_menu_panel = NULL;
+}
+
+void mm_cancel_menu(void) {
+ if (mm_hwnd_menu_panel)
+ SendMessage(mm_hwnd_menu_panel, WM_CANCELMODE, 0, 0);
+}
+
+LRESULT khm_menu_notify_main(LPNMHDR notice) {
+ LPNMTOOLBAR nmt;
+ LRESULT ret = FALSE;
+ RECT r;
+ khui_menu_def * mmdef;
+ khui_action_ref * mm;
+ int nmm;
+
+ mmdef = khui_find_menu(KHUI_MENU_MAIN);
+ mm = mmdef->items;
+ nmm = (int) khui_action_list_length(mm);
+
+ GetWindowRect(khui_main_menu_toolbar, &r);
+
+ nmt = (LPNMTOOLBAR) notice;
+ switch(notice->code) {
+ case TBN_DROPDOWN:
+ khm_track_menu(-1);
+ /*
+ khm_menu_show_panel(nmt->iItem,
+ r.left + nmt->rcButton.left,
+ r.top + nmt->rcButton.bottom);
+ */
+ ret = TBDDRET_DEFAULT;
+ break;
+
+ case TBN_HOTITEMCHANGE:
+ {
+ LPNMTBHOTITEM nmhi;
+ int new_item = -1;
+
+ nmhi = (LPNMTBHOTITEM) notice;
+
+ if(nmhi->dwFlags & HICF_LEAVING)
+ new_item = -1;
+ else {
+ int i;
+ for(i=0; i < nmm; i++) {
+ if(mm[i].action == nmhi->idNew) {
+ new_item = i;
+ break;
+ }
+ }
+ }
+
+ if (mm_hot_track &&
+ new_item != mm_last_hot_item &&
+ new_item != -1 &&
+ mm_last_hot_item != -1) {
+
+ EndMenu();
+ mm_next_hot_item = new_item;
+
+ }
+
+ ret = 0;
+
+ if (!mm_hot_track || new_item != -1)
+ mm_last_hot_item = new_item;
+
+ } break;
+
+ default:
+ /* hmm. what to do */
+ ret = FALSE;
+ }
+ return ret;
+}
+
+struct identity_action_map {
+ khm_handle identity;
+ khm_int32 renew_cmd;
+ khm_int32 destroy_cmd;
+ khm_int32 new_cmd;
+ int refreshcycle;
+};
+
+#define IDMAP_ALLOC_INCR 8
+
+struct identity_action_map * id_action_map = NULL;
+khm_size n_id_action_map = 0;
+khm_size nc_id_action_map = 0;
+
+int idcmd_refreshcycle = 0;
+
+static struct identity_action_map *
+create_identity_cmd_map(khm_handle ident) {
+
+ struct identity_action_map * actmap;
+ wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
+ wchar_t fmt[128];
+ wchar_t caption[KHUI_MAXCCH_SHORT_DESC];
+ wchar_t tooltip[KHUI_MAXCCH_SHORT_DESC];
+ wchar_t actionname[KHUI_MAXCCH_NAME];
+ khm_size cb;
+
+ if (n_id_action_map + 1 > nc_id_action_map) {
+ nc_id_action_map = UBOUNDSS(n_id_action_map + 1,
+ IDMAP_ALLOC_INCR,
+ IDMAP_ALLOC_INCR);
+#ifdef DEBUG
+ assert(nc_id_action_map > n_id_action_map + 1);
+#endif
+ id_action_map = PREALLOC(id_action_map,
+ nc_id_action_map * sizeof(id_action_map[0]));
+#ifdef DEBUG
+ assert(id_action_map);
+#endif
+ ZeroMemory(&id_action_map[n_id_action_map],
+ sizeof(id_action_map[0]) * (nc_id_action_map - n_id_action_map));
+ }
+
+ actmap = &id_action_map[n_id_action_map];
+ n_id_action_map++;
+
+ cb = sizeof(idname);
+ kcdb_identity_get_name(ident, idname, &cb);
+
+ actmap->identity = ident;
+ kcdb_identity_hold(ident);
+
+#define GETFORMAT(I) do { fmt[0] = L'\0'; LoadString(khm_hInstance, I, fmt, ARRAYLENGTH(fmt)); } while(0)
+#define EXPFORMAT(d,s) do { StringCbPrintf(d, sizeof(d), fmt, s); } while(0)
+ /* renew */
+
+ GETFORMAT(IDS_IDACTIONT_RENEW);
+ EXPFORMAT(tooltip, idname);
+
+ GETFORMAT(IDS_IDACTION_RENEW);
+ EXPFORMAT(caption, idname);
+
+ StringCbPrintf(actionname, sizeof(actionname), L"R:%s", idname);
+
+ actmap->renew_cmd =
+ khui_action_create(actionname, caption, tooltip, NULL,
+ KHUI_ACTIONTYPE_TRIGGER, NULL);
+
+ /* destroy */
+
+ GETFORMAT(IDS_IDACTIONT_DESTROY);
+ EXPFORMAT(tooltip, idname);
+
+ GETFORMAT(IDS_IDACTION_DESTROY);
+ EXPFORMAT(caption, idname);
+
+ StringCbPrintf(actionname, sizeof(actionname), L"D:%s", idname);
+
+ actmap->destroy_cmd =
+ khui_action_create(actionname, caption, tooltip, NULL,
+ KHUI_ACTIONTYPE_TRIGGER, NULL);
+
+ /* new */
+
+ GETFORMAT(IDS_IDACTIONT_NEW);
+ EXPFORMAT(tooltip, idname);
+
+ GETFORMAT(IDS_IDACTION_NEW);
+ EXPFORMAT(caption, idname);
+
+ StringCbPrintf(actionname, sizeof(actionname), L"N:%s", idname);
+
+ actmap->new_cmd =
+ khui_action_create(actionname, caption, tooltip, NULL,
+ KHUI_ACTIONTYPE_TRIGGER, NULL);
+
+ actmap->refreshcycle = idcmd_refreshcycle;
+
+#undef GETFORMAT
+#undef EXPFORMAT
+
+ return actmap;
+}
+
+static void
+purge_identity_cmd_map(void) {
+ khm_size i;
+
+ for (i=0; i < n_id_action_map; i++) {
+ khm_handle ident;
+
+ if (id_action_map[i].refreshcycle != idcmd_refreshcycle) {
+ ident = id_action_map[i].identity;
+ id_action_map[i].identity = NULL;
+ kcdb_identity_release(ident);
+
+ khui_action_delete(id_action_map[i].renew_cmd);
+ khui_action_delete(id_action_map[i].destroy_cmd);
+
+ id_action_map[i].renew_cmd = 0;
+ id_action_map[i].destroy_cmd = 0;
+ }
+ }
+}
+
+static struct identity_action_map *
+get_identity_cmd_map(khm_handle ident) {
+ khm_size i;
+
+ for (i=0; i < n_id_action_map; i++) {
+ if (kcdb_identity_is_equal(id_action_map[i].identity,
+ ident))
+ break;
+ }
+
+ if (i < n_id_action_map) {
+ id_action_map[i].refreshcycle = idcmd_refreshcycle;
+ return &id_action_map[i];
+ } else {
+ return create_identity_cmd_map(ident);
+ }
+}
+
+khm_int32
+khm_get_identity_renew_action(khm_handle ident) {
+ struct identity_action_map * map;
+
+ map = get_identity_cmd_map(ident);
+
+ if (map)
+ return map->renew_cmd;
+ else
+ return 0;
+}
+
+khm_int32
+khm_get_identity_destroy_action(khm_handle ident) {
+ struct identity_action_map * map;
+
+ map = get_identity_cmd_map(ident);
+
+ if (map)
+ return map->destroy_cmd;
+ else
+ return 0;
+}
+
+khm_int32
+khm_get_identity_new_creds_action(khm_handle ident) {
+ struct identity_action_map * map;
+
+ map = get_identity_cmd_map(ident);
+
+ if (map)
+ return map->new_cmd;
+ else
+ return 0;
+}
+
+void
+khm_refresh_identity_menus(void) {
+ khui_menu_def * renew_def = NULL;
+ khui_menu_def * dest_def = NULL;
+ wchar_t * idlist = NULL;
+ wchar_t * idname = NULL;
+ khm_size cb = 0;
+ khm_size n_idents = 0;
+ khm_size t;
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+ khm_handle csp_cw = NULL;
+ khm_int32 idflags;
+ khm_int32 def_sticky = 0;
+ khm_boolean sticky_done = FALSE;
+
+ if (KHM_SUCCEEDED(khc_open_space(NULL, L"CredWindow", 0, &csp_cw))) {
+ khc_read_int32(csp_cw, L"DefaultSticky", &def_sticky);
+ khc_close_space(csp_cw);
+ csp_cw = NULL;
+ }
+
+ kcdb_identity_refresh_all();
+
+ khui_action_lock();
+
+ idcmd_refreshcycle++;
+
+ do {
+ if (idlist)
+ PFREE(idlist);
+ idlist = NULL;
+ cb = 0;
+
+ rv = kcdb_identity_enum(KCDB_IDENT_FLAG_ACTIVE | KCDB_IDENT_FLAG_EMPTY,
+ KCDB_IDENT_FLAG_ACTIVE,
+ NULL,
+ &cb,
+ &n_idents);
+ if (rv != KHM_ERROR_TOO_LONG || cb == 0 || cb == sizeof(wchar_t) * 2)
+ break;
+
+ idlist = PMALLOC(cb);
+#ifdef DEBUG
+ assert(idlist);
+#endif
+
+ rv = kcdb_identity_enum(KCDB_IDENT_FLAG_ACTIVE | KCDB_IDENT_FLAG_EMPTY,
+ KCDB_IDENT_FLAG_ACTIVE,
+ idlist,
+ &cb,
+ &n_idents);
+ if (rv == KHM_ERROR_TOO_LONG)
+ continue;
+
+ if (KHM_FAILED(rv)) {
+ /* something else went wrong. hmm. */
+ if (idlist)
+ PFREE(idlist);
+ idlist = NULL;
+ }
+ break;
+
+ } while(TRUE);
+
+ if (idlist != NULL && n_idents > 0) {
+ khui_enable_action(KHUI_MENU_RENEW_CRED, TRUE);
+ khui_enable_action(KHUI_MENU_DESTROY_CRED, TRUE);
+ khui_enable_action(KHUI_ACTION_RENEW_CRED, TRUE);
+ khui_enable_action(KHUI_ACTION_DESTROY_CRED, TRUE);
+ } else {
+ khui_enable_action(KHUI_MENU_RENEW_CRED, FALSE);
+ khui_enable_action(KHUI_MENU_DESTROY_CRED, FALSE);
+ khui_enable_action(KHUI_ACTION_RENEW_CRED, FALSE);
+ khui_enable_action(KHUI_ACTION_DESTROY_CRED, FALSE);
+ }
+
+ renew_def = khui_find_menu(KHUI_MENU_RENEW_CRED);
+ dest_def = khui_find_menu(KHUI_MENU_DESTROY_CRED);
+#ifdef DEBUG
+ assert(renew_def);
+ assert(dest_def);
+#endif
+
+ t = khui_menu_get_size(renew_def);
+ while(t) {
+ khui_menu_remove_action(renew_def, 0);
+ t--;
+ }
+
+ t = khui_menu_get_size(dest_def);
+ while(t) {
+ khui_menu_remove_action(dest_def, 0);
+ t--;
+ }
+
+ if (idlist != NULL && n_idents > 1) {
+ khui_menu_insert_action(renew_def, 0, KHUI_ACTION_RENEW_ALL, 0);
+ khui_menu_insert_action(renew_def, 1, KHUI_MENU_SEP, 0);
+
+ khui_menu_insert_action(dest_def, 0, KHUI_ACTION_DESTROY_ALL, 0);
+ khui_menu_insert_action(dest_def, 1, KHUI_MENU_SEP, 0);
+ }
+
+ for (idname = idlist; idname && idname[0];
+ idname = multi_string_next(idname)) {
+ khm_handle identity = NULL;
+
+ if (KHM_FAILED(kcdb_identity_create(idname, 0, &identity))) {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ continue;
+ }
+
+ khui_menu_insert_action(renew_def, 1000,
+ khm_get_identity_renew_action(identity),
+ 0);
+
+ khui_menu_insert_action(dest_def, 1000,
+ khm_get_identity_destroy_action(identity),
+ 0);
+
+ idflags = 0;
+ kcdb_identity_get_flags(identity, &idflags);
+
+ if (!(idflags & KCDB_IDENT_FLAG_STICKY) && def_sticky) {
+ kcdb_identity_set_flags(identity,
+ KCDB_IDENT_FLAG_STICKY,
+ KCDB_IDENT_FLAG_STICKY);
+ sticky_done = TRUE;
+ }
+ }
+
+ if (idlist)
+ PFREE(idlist);
+
+ purge_identity_cmd_map();
+
+ khui_action_unlock();
+
+ khui_refresh_actions();
+
+ if (sticky_done) {
+ InvalidateRect(khm_hwnd_main_cred, NULL, TRUE);
+ }
+}
+
+khm_boolean
+khm_check_identity_menu_action(khm_int32 act_id) {
+
+ if (act_id == KHUI_ACTION_DESTROY_ALL) {
+ khm_size i;
+
+ for (i=0; i < n_id_action_map; i++) {
+ if (id_action_map[i].identity != NULL) {
+ khm_cred_destroy_identity(id_action_map[i].identity);
+ }
+ }
+
+ return TRUE;
+ } else if (act_id == KHUI_ACTION_RENEW_ALL) {
+ khm_size i;
+
+ for (i=0; i < n_id_action_map; i++) {
+ if (id_action_map[i].identity != NULL) {
+ khm_cred_renew_identity(id_action_map[i].identity);
+ }
+ }
+
+ return TRUE;
+ } else {
+ khm_size i;
+
+ for (i=0; i < n_id_action_map; i++) {
+ if (id_action_map[i].identity == NULL)
+ continue;
+
+ if (id_action_map[i].renew_cmd == act_id) {
+ khm_cred_renew_identity(id_action_map[i].identity);
+ return TRUE;
+ }
+
+ if (id_action_map[i].destroy_cmd == act_id) {
+ khm_cred_destroy_identity(id_action_map[i].identity);
+ return TRUE;
+ }
+
+ if (id_action_map[i].new_cmd == act_id) {
+ khm_cred_obtain_new_creds_for_ident(id_action_map[i].identity,
+ NULL);
+ return TRUE;
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+
+HMENU khui_hmenu_main = NULL;
+
+void khm_menu_refresh_items(void) {
+ khui_menu_def * def;
+
+ if (!khui_hmenu_main)
+ return;
+
+ khui_action_lock();
+
+ def = khui_find_menu(KHUI_MENU_MAIN);
+
+ refresh_menu(khui_hmenu_main, def);
+
+ khui_action_unlock();
+
+ DrawMenuBar(khm_hwnd_main);
+}
+
+void khm_menu_create_main(HWND parent) {
+ HMENU hmenu;
+ khui_menu_def * def;
+
+ def = khui_find_menu(KHUI_MENU_MAIN);
+
+ hmenu = mm_create_menu_from_def(def, TRUE);
+
+ SetMenu(parent, hmenu);
+
+ khui_hmenu_main = hmenu;
+
+ return;
+
+#ifdef USE_EXPLORER_STYLE_MENU_BAR
+ HWND hwtb;
+ REBARBANDINFO rbi;
+ SIZE sz;
+ int i;
+ khui_menu_def * mmdef;
+ khui_action_ref * mm;
+ int nmm;
+
+ mmdef = khui_find_menu(KHUI_MENU_MAIN);
+ mm = mmdef->items;
+ nmm = (int) khui_action_list_length(mm);
+
+ hwtb = CreateWindowEx(0
+#if (_WIN32_IE >= 0x0501)
+ | TBSTYLE_EX_MIXEDBUTTONS
+#endif
+ ,
+ TOOLBARCLASSNAME,
+ (LPWSTR) NULL,
+ WS_CHILD |
+ CCS_ADJUSTABLE |
+ TBSTYLE_FLAT |
+ TBSTYLE_AUTOSIZE |
+ TBSTYLE_LIST |
+ CCS_NORESIZE |
+ CCS_NOPARENTALIGN |
+ CCS_NODIVIDER,
+ 0, 0, 0, 0, rebar,
+ (HMENU) NULL, khm_hInstance,
+ NULL);
+
+ if(!hwtb) {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ return;
+ }
+
+ khui_main_menu_toolbar = hwtb;
+
+ SendMessage(hwtb,
+ TB_BUTTONSTRUCTSIZE,
+ (WPARAM) sizeof(TBBUTTON),
+ 0);
+
+ for(i=0; i<nmm; i++) {
+ khui_add_action_to_toolbar(hwtb,
+ khui_find_action(mm[i].action),
+ KHUI_TOOLBAR_ADD_TEXT |
+ KHUI_TOOLBAR_ADD_DROPDOWN |
+ KHUI_TOOLBAR_VARSIZE,
+ NULL);
+ }
+
+ SendMessage(hwtb,
+ TB_AUTOSIZE,
+ 0,0);
+
+ SendMessage(hwtb,
+ TB_GETMAXSIZE,
+ 0,
+ (LPARAM) &sz);
+
+ ZeroMemory(&rbi, sizeof(rbi));
+
+ rbi.cbSize = sizeof(rbi);
+
+ rbi.fMask =
+ RBBIM_ID |
+ RBBIM_STYLE |
+ RBBIM_CHILD |
+ RBBIM_CHILDSIZE |
+ RBBIM_SIZE |
+ RBBIM_IDEALSIZE;
+
+ rbi.fStyle =
+ RBBS_USECHEVRON;
+
+ rbi.hwndChild = hwtb;
+ rbi.wID = KHUI_MENU_MAIN;
+ rbi.cx = sz.cx;
+ rbi.cxMinChild = rbi.cx;
+ rbi.cxIdeal = rbi.cx;
+ rbi.cyMinChild = sz.cy;
+ rbi.cyChild = rbi.cyMinChild;
+ rbi.cyIntegral = rbi.cyMinChild;
+ rbi.cyMaxChild = rbi.cyMinChild;
+
+ SendMessage(rebar,
+ RB_INSERTBAND,
+ 0,
+ (LPARAM) &rbi);
+#endif
+}
diff --git a/src/windows/identity/ui/mainmenu.h b/src/windows/identity/ui/mainmenu.h
index e8da77f39f..54504d5fb2 100644
--- a/src/windows/identity/ui/mainmenu.h
+++ b/src/windows/identity/ui/mainmenu.h
@@ -1,68 +1,68 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- * Copyright (c) 2007 Secure Endpoints Inc.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#ifndef __KHIMAIRA_MAINMENU_H
-#define __KHIMAIRA_MAINMENU_H
-
-extern HWND khui_main_menu_toolbar;
-
-#define MENU_ACTIVATE_DEFAULT -1
-#define MENU_ACTIVATE_LEFT -2
-#define MENU_ACTIVATE_RIGHT -3
-#define MENU_ACTIVATE_NONE -4
-
-extern int mm_last_hot_item;
-extern BOOL mm_hot_track;
-
-void khm_menu_create_main(HWND rebar);
-LRESULT khm_menu_handle_select(WPARAM wParam, LPARAM lParam);
-LRESULT khm_menu_notify_main(LPNMHDR notice);
-LRESULT khm_menu_activate(int menu_id);
-void khm_menu_show_panel(int id, LONG x, LONG y);
-void khm_menu_track_current(void);
-LRESULT khm_menu_measure_item(WPARAM wParam, LPARAM lparam);
-LRESULT khm_menu_draw_item(WPARAM wParam, LPARAM lparam);
-void khm_menu_refresh_items(void);
-khm_boolean khm_check_identity_menu_action(khm_int32 act_id);
-void khm_refresh_identity_menus(void);
-void khm_get_action_tooltip(khm_int32 action, wchar_t * buf, khm_size cb_buf);
-void khm_get_action_caption(khm_int32 action, wchar_t * buf, khm_size cb_buf);
-
-khm_int32 khm_get_identity_destroy_action(khm_handle ident);
-khm_int32 khm_get_identity_renew_action(khm_handle ident);
-khm_int32 khm_get_identity_new_creds_action(khm_handle ident);
-
-static HMENU mm_create_menu_from_def(khui_menu_def * def, BOOL main);
-static void mm_show_panel_def(khui_menu_def * def, LONG x, LONG y);
-
-void khui_init_menu(void);
-void khui_exit_menu(void);
-
-#define MENU_SIZE_ICON_X 16
-#define MENU_SIZE_ICON_Y 16
-
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ * Copyright (c) 2007 Secure Endpoints Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __KHIMAIRA_MAINMENU_H
+#define __KHIMAIRA_MAINMENU_H
+
+extern HWND khui_main_menu_toolbar;
+
+#define MENU_ACTIVATE_DEFAULT -1
+#define MENU_ACTIVATE_LEFT -2
+#define MENU_ACTIVATE_RIGHT -3
+#define MENU_ACTIVATE_NONE -4
+
+extern int mm_last_hot_item;
+extern BOOL mm_hot_track;
+
+void khm_menu_create_main(HWND rebar);
+LRESULT khm_menu_handle_select(WPARAM wParam, LPARAM lParam);
+LRESULT khm_menu_notify_main(LPNMHDR notice);
+LRESULT khm_menu_activate(int menu_id);
+void khm_menu_show_panel(int id, LONG x, LONG y);
+void khm_menu_track_current(void);
+LRESULT khm_menu_measure_item(WPARAM wParam, LPARAM lparam);
+LRESULT khm_menu_draw_item(WPARAM wParam, LPARAM lparam);
+void khm_menu_refresh_items(void);
+khm_boolean khm_check_identity_menu_action(khm_int32 act_id);
+void khm_refresh_identity_menus(void);
+void khm_get_action_tooltip(khm_int32 action, wchar_t * buf, khm_size cb_buf);
+void khm_get_action_caption(khm_int32 action, wchar_t * buf, khm_size cb_buf);
+
+khm_int32 khm_get_identity_destroy_action(khm_handle ident);
+khm_int32 khm_get_identity_renew_action(khm_handle ident);
+khm_int32 khm_get_identity_new_creds_action(khm_handle ident);
+
+static HMENU mm_create_menu_from_def(khui_menu_def * def, BOOL main);
+static void mm_show_panel_def(khui_menu_def * def, LONG x, LONG y);
+
+void khui_init_menu(void);
+void khui_exit_menu(void);
+
+#define MENU_SIZE_ICON_X 16
+#define MENU_SIZE_ICON_Y 16
+
+#endif
diff --git a/src/windows/identity/ui/mainwnd.h b/src/windows/identity/ui/mainwnd.h
index 7b14d35a28..5a00631c1a 100644
--- a/src/windows/identity/ui/mainwnd.h
+++ b/src/windows/identity/ui/mainwnd.h
@@ -1,82 +1,82 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#ifndef __KHIMAIRA_MAINWND_H
-#define __KHIMAIRA_MAINWND_H
-
-#define KHUI_MAIN_WINDOW_CLASS L"KhmMainWindowClass"
-#define KHUI_NULL_WINDOW_CLASS L"KhmNullWindowClass"
-
-extern ATOM khm_main_window_class;
-extern HWND khm_hwnd_main;
-extern HWND khm_hwnd_rebar;
-extern HWND khm_hwnd_main_cred;
-
-#define KHM_MAIN_WND_NORMAL 0
-#define KHM_MAIN_WND_MINI 1
-
-extern int khm_main_wnd_mode;
-
-void khm_register_main_wnd_class(void);
-void khm_unregister_main_wnd_class(void);
-void khm_create_main_window_controls(HWND);
-void khm_create_main_window(void);
-void khm_activate_main_window(void);
-void khm_show_main_window(void);
-void khm_set_main_window_mode(int mode);
-void khm_close_main_window(void);
-void khm_hide_main_window(void);
-BOOL khm_is_main_window_visible(void);
-BOOL khm_is_main_window_active(void);
-void khm_adjust_window_dimensions_for_display(RECT * pr, int dock);
-LRESULT khm_rebar_notify(LPNMHDR lpnm);
-
-void
-khm_set_dialog_result(HWND hwnd, LRESULT lr);
-
-LRESULT CALLBACK
-khm_main_wnd_proc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam);
-
-#define WM_KHUI_QUERY_APP_VERSION 32809
-#define WM_KHUI_ASSIGN_COMMANDLINE_V1 32808
-#define WM_KHUI_ASSIGN_COMMANDLINE_V2 32810
-
-#define COMMANDLINE_MAP_FMT L"Local\\NetIDMgr_Cmdline_%lu"
-#define QUERY_APP_VER_MAP_FMT L"Local\\NetIDMgr_QueryVer_%lu"
-
-/* dock values for window positioning */
-#define KHM_DOCK_NONE 0
-#define KHM_DOCK_TOPLEFT 1
-#define KHM_DOCK_TOPRIGHT 2
-#define KHM_DOCK_BOTTOMRIGHT 3
-#define KHM_DOCK_BOTTOMLEFT 4
-#define KHM_DOCK_AUTO 256
-#define KHM_DOCKF_DOCKHINT 0x0000ffff
-#define KHM_DOCKF_XBORDER 0x00010000
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __KHIMAIRA_MAINWND_H
+#define __KHIMAIRA_MAINWND_H
+
+#define KHUI_MAIN_WINDOW_CLASS L"KhmMainWindowClass"
+#define KHUI_NULL_WINDOW_CLASS L"KhmNullWindowClass"
+
+extern ATOM khm_main_window_class;
+extern HWND khm_hwnd_main;
+extern HWND khm_hwnd_rebar;
+extern HWND khm_hwnd_main_cred;
+
+#define KHM_MAIN_WND_NORMAL 0
+#define KHM_MAIN_WND_MINI 1
+
+extern int khm_main_wnd_mode;
+
+void khm_register_main_wnd_class(void);
+void khm_unregister_main_wnd_class(void);
+void khm_create_main_window_controls(HWND);
+void khm_create_main_window(void);
+void khm_activate_main_window(void);
+void khm_show_main_window(void);
+void khm_set_main_window_mode(int mode);
+void khm_close_main_window(void);
+void khm_hide_main_window(void);
+BOOL khm_is_main_window_visible(void);
+BOOL khm_is_main_window_active(void);
+void khm_adjust_window_dimensions_for_display(RECT * pr, int dock);
+LRESULT khm_rebar_notify(LPNMHDR lpnm);
+
+void
+khm_set_dialog_result(HWND hwnd, LRESULT lr);
+
+LRESULT CALLBACK
+khm_main_wnd_proc(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam);
+
+#define WM_KHUI_QUERY_APP_VERSION 32809
+#define WM_KHUI_ASSIGN_COMMANDLINE_V1 32808
+#define WM_KHUI_ASSIGN_COMMANDLINE_V2 32810
+
+#define COMMANDLINE_MAP_FMT L"Local\\NetIDMgr_Cmdline_%lu"
+#define QUERY_APP_VER_MAP_FMT L"Local\\NetIDMgr_QueryVer_%lu"
+
+/* dock values for window positioning */
+#define KHM_DOCK_NONE 0
+#define KHM_DOCK_TOPLEFT 1
+#define KHM_DOCK_TOPRIGHT 2
+#define KHM_DOCK_BOTTOMRIGHT 3
+#define KHM_DOCK_BOTTOMLEFT 4
+#define KHM_DOCK_AUTO 256
+#define KHM_DOCKF_DOCKHINT 0x0000ffff
+#define KHM_DOCKF_XBORDER 0x00010000
+#endif
diff --git a/src/windows/identity/ui/notifier.c b/src/windows/identity/ui/notifier.c
index e0582eb94a..afc7749129 100644
--- a/src/windows/identity/ui/notifier.c
+++ b/src/windows/identity/ui/notifier.c
@@ -1,3160 +1,3160 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#define OEMRESOURCE
-
-#include<khmapp.h>
-#include<assert.h>
-
-#define KHUI_NOTIFIER_CLASS L"KhuiNotifierMsgWindowClass"
-#define KHUI_ALERTER_CLASS L"KhuiAlerterWindowClass"
-#define KHUI_ALERTBIN_CLASS L"KhuiAlertBinWindowClass"
-
-#define KHUI_NOTIFIER_WINDOW L"KhuiNotifierMsgWindow"
-
-
-/* The commands that are available as default actions when the user
- clicks the notification icon. */
-
-khm_int32 khm_notifier_actions[] = {
- KHUI_ACTION_OPEN_APP,
- KHUI_ACTION_NEW_CRED
-};
-
-khm_size n_khm_notifier_actions = ARRAYLENGTH(khm_notifier_actions);
-
-/* notifier message for notification icon */
-#define KHUI_WM_NOTIFIER WM_COMMAND
-
-#define DRAWTEXTOPTIONS (DT_CALCRECT | DT_NOPREFIX | DT_WORDBREAK)
-
-/* are we showing an alert? */
-#define ALERT_DISPLAYED() (balloon_alert != NULL || khui_alert_windows != NULL)
-
-/* Forward declarations */
-
-struct tag_alerter_wnd_data;
-typedef struct tag_alerter_wnd_data alerter_wnd_data;
-
-struct tag_alert_list;
-typedef struct tag_alert_list alert_list;
-
-static khm_int32
-alert_show(khui_alert * a);
-
-static khm_int32
-alert_show_minimized(khui_alert * a);
-
-static khm_int32
-alert_show_normal(khui_alert * a);
-
-static khm_int32
-alert_show_list(alert_list * alist);
-
-static khm_int32
-alert_enqueue(khui_alert * a);
-
-static khm_boolean
-alert_is_equal(khui_alert * a1, khui_alert * a2);
-
-static void
-check_for_queued_alerts(void);
-
-static void
-show_queued_alerts(void);
-
-static khm_int32
-alert_consolidate(alert_list * alist,
- khui_alert * alert,
- khm_boolean add_from_queue);
-
-static khm_int32
-get_default_notifier_action(void);
-
-/* Globals */
-
-/* window class registration atom for message only notifier window
- class */
-ATOM atom_notifier = 0;
-
-/* window class registration atom for alert windows */
-ATOM atom_alerter = 0;
-/* window class registration atom for the alert "bin", which is the
- window that holds all the alerts. */
-ATOM atom_alert_bin = 0;
-
-/* notifier message window */
-HWND hwnd_notifier = NULL;
-
-BOOL notifier_ready = FALSE;
-
-/* The list of alert windows currently active */
-alerter_wnd_data * khui_alert_windows = NULL;
-
-/* Notification icon for when there are no alerts to be displayed */
-int iid_normal = IDI_NOTIFY_NONE;
-
-/* The alert currently being displayed in a balloon */
-khui_alert * balloon_alert = NULL;
-
-/**********************************************************************
- Alert Queue
-
- The alert queue is the data structure that keeps track of all the
- alerts that are waiting to be displayed. Alerts will be placed on
- the queue if they cannot be immediately displayed for some reason
- (e.g. another alert is being displayed, or the user is working in
- another window).
-***********************************************************************/
-
-#define KHUI_ALERT_QUEUE_MAX 64
-
-khui_alert * alert_queue[KHUI_ALERT_QUEUE_MAX];
-khm_int32 alert_queue_head = 0;
-khm_int32 alert_queue_tail = 0;
-
-#define is_alert_queue_empty() (alert_queue_head == alert_queue_tail)
-#define is_alert_queue_full() (((alert_queue_tail + 1) % KHUI_ALERT_QUEUE_MAX) == alert_queue_head)
-
-/* NOTE: the alert queue functions are unsafe to call from any thread
- other than the UI thread. */
-
-static void
-alert_queue_put_alert(khui_alert * a) {
- if (is_alert_queue_full()) return;
- alert_queue[alert_queue_tail++] = a;
- khui_alert_hold(a);
- alert_queue_tail %= KHUI_ALERT_QUEUE_MAX;
-}
-
-/* the caller needs to release the alert that's returned */
-static khui_alert *
-alert_queue_get_alert(void) {
- khui_alert * a;
-
- if (is_alert_queue_empty()) return NULL;
- a = alert_queue[alert_queue_head++];
- alert_queue_head %= KHUI_ALERT_QUEUE_MAX;
-
- return a; /* held */
-}
-
-static int
-alert_queue_get_size(void) {
- if (is_alert_queue_empty())
- return 0;
-
- if (alert_queue_tail < alert_queue_head) {
- return (alert_queue_tail + KHUI_ALERT_QUEUE_MAX - alert_queue_head);
- } else {
- return alert_queue_tail - alert_queue_head;
- }
-}
-
-static khui_alert *
-alert_queue_get_alert_by_pos(int pos) {
- khui_alert * a;
-
- if (is_alert_queue_empty() ||
- pos >= alert_queue_get_size() ||
- pos < 0) {
- return NULL;
- }
-
- a = alert_queue[(alert_queue_head + pos) % KHUI_ALERT_QUEUE_MAX];
- if (a) {
- khui_alert_hold(a);
- }
- return a;
-}
-
-static int
-alert_queue_delete_alert(khui_alert * a) {
- int idx;
- int succ;
-
- idx = alert_queue_head;
- while(idx != alert_queue_tail) {
- if (alert_queue[idx] == a)
- break;
-
- idx = (idx + 1) % KHUI_ALERT_QUEUE_MAX;
- }
-
- if (idx == alert_queue_tail)
- return 0;
-
-#ifdef DEBUG
- assert(alert_queue[idx]);
-#endif
- khui_alert_release(alert_queue[idx]);
-
- succ = (idx + 1) % KHUI_ALERT_QUEUE_MAX;
- while(succ != alert_queue_tail) {
- alert_queue[idx] = alert_queue[succ];
-
- succ = (succ + 1) % KHUI_ALERT_QUEUE_MAX;
- idx = (idx + 1) % KHUI_ALERT_QUEUE_MAX;
- }
-
- alert_queue_tail = idx;
- return 1;
-}
-
-/* the caller needs to release the alert that's returned */
-static khui_alert *
-alert_queue_peek(void) {
- khui_alert * a;
-
- if (is_alert_queue_empty())
- return NULL;
-
- a = alert_queue[alert_queue_head];
- khui_alert_hold(a);
-
- return a;
-}
-
-/**********************************************************************
- Alert List
-
- A list of alerts. Currently has a fixed upper limit, but the limit
- is high enough for now.
-***********************************************************************/
-
-typedef struct tag_alert_list {
- khui_alert * alerts[KHUI_ALERT_QUEUE_MAX];
- int n_alerts;
- wchar_t title[KHUI_MAXCCH_TITLE];
-} alert_list;
-
-static void
-alert_list_init(alert_list * alist) {
- ZeroMemory(alist, sizeof(*alist));
-}
-
-static void
-alert_list_set_title(alert_list * alist, wchar_t * title) {
- StringCbCopy(alist->title, sizeof(alist->title), title);
-}
-
-static khm_int32
-alert_list_add_alert(alert_list * alist,
- khui_alert * alert) {
-
- if (alist->n_alerts == ARRAYLENGTH(alist->alerts))
- return KHM_ERROR_NO_RESOURCES;
-
- khui_alert_hold(alert);
- alist->alerts[alist->n_alerts++] = alert;
-
- return KHM_ERROR_SUCCESS;
-}
-
-static void
-alert_list_destroy(alert_list * alist) {
- int i;
-
- for (i=0; i < alist->n_alerts; i++) {
- if (alist->alerts[i] != NULL) {
- khui_alert_release(alist->alerts[i]);
- alist->alerts[i] = NULL;
- }
- }
-
- alist->n_alerts = 0;
-}
-
-
-/**********************************************************************
- Notifier Window
-
- The notifier window manages the notification icon and handles
- KMSG_ALERT messages sent from the UI library. The window will exist
- for the lifetime of the application.
-***********************************************************************/
-
-/* These are defined for APPVER >= 0x501. We are defining them here
- so that we can build with APPVER = 0x500 and use the same binaries
- with Win XP. */
-
-#ifndef NIN_BALLOONSHOW
-#define NIN_BALLOONSHOW (WM_USER + 2)
-#endif
-
-#ifndef NIN_BALLOONHIDE
-#define NIN_BALLOONHIDE (WM_USER + 3)
-#endif
-
-#ifndef NIN_BALLOONTIMEOUT
-#define NIN_BALLOONTIMEOUT (WM_USER + 4)
-#endif
-
-#ifndef NIN_BALLOONUSERCLICK
-#define NIN_BALLOONUSERCLICK (WM_USER + 5)
-#endif
-
-
-static LRESULT CALLBACK
-notifier_wnd_proc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam)
-{
- kmq_message * m;
- khm_int32 rv;
-
- if(uMsg == KMQ_WM_DISPATCH) {
- kmq_wm_begin(lParam, &m);
- rv = KHM_ERROR_SUCCESS;
-
- if(m->type == KMSG_ALERT) {
- /* handle notifier messages */
- switch(m->subtype) {
- case KMSG_ALERT_SHOW:
- {
- khui_alert * a;
-
- a = (khui_alert *) m->vparam;
-#ifdef DEBUG
- assert(a != NULL);
-#endif
- rv = alert_show(a);
- khui_alert_release(a);
- }
- break;
-
- case KMSG_ALERT_QUEUE:
- {
- khui_alert * a;
-
- a = (khui_alert *) m->vparam;
-#ifdef DEBUG
- assert(a != NULL);
-#endif
- rv = alert_enqueue(a);
- khui_alert_release(a);
- }
- break;
-
- case KMSG_ALERT_CHECK_QUEUE:
- check_for_queued_alerts();
- break;
-
- case KMSG_ALERT_SHOW_QUEUED:
- show_queued_alerts();
- break;
-
- case KMSG_ALERT_SHOW_MODAL:
- {
- khui_alert * a;
-
- a = (khui_alert *) m->vparam;
-#ifdef DEBUG
- assert(a != NULL);
-#endif
- khui_alert_lock(a);
- a->flags |= KHUI_ALERT_FLAG_MODAL;
- khui_alert_unlock(a);
-
- rv = alert_show(a);
-
- if (KHM_SUCCEEDED(rv)) {
- khm_message_loop_int(&a->displayed);
- }
-
- khui_alert_release(a);
- }
- break;
- }
- } else if (m->type == KMSG_CRED &&
- m->subtype == KMSG_CRED_ROOTDELTA) {
-
- KillTimer(hwnd, KHUI_REFRESH_TIMER_ID);
- SetTimer(hwnd, KHUI_REFRESH_TIMER_ID,
- KHUI_REFRESH_TIMEOUT,
- NULL);
-
- }
-
- return kmq_wm_end(m, rv);
- } else if (uMsg == KHUI_WM_NOTIFIER) {
- /* Handle events generated from the notification icon */
-
- /* wParam is the identifier of the notify icon, but we only
- have one. */
- switch(lParam) {
- case WM_CONTEXTMENU:
- {
- POINT pt;
- int menu_id;
- khui_menu_def * mdef;
- khui_action_ref * act;
- khm_size i, n;
- khm_int32 def_cmd;
-
- /* before we show the context menu, we need to make
- sure that the default action for the notification
- icon is present in the menu and that it is marked
- as the default. */
-
- def_cmd = get_default_notifier_action();
-
- if (khm_is_main_window_visible()) {
- menu_id = KHUI_MENU_ICO_CTX_NORMAL;
-
- if (def_cmd == KHUI_ACTION_OPEN_APP)
- def_cmd = KHUI_ACTION_CLOSE_APP;
- } else {
- menu_id = KHUI_MENU_ICO_CTX_MIN;
- }
-
- mdef = khui_find_menu(menu_id);
-
-#ifdef DEBUG
- assert(mdef);
-#endif
- n = khui_menu_get_size(mdef);
- for (i=0; i < n; i++) {
- act = khui_menu_get_action(mdef, i);
- if (!(act->flags & KHUI_ACTIONREF_PACTION) &&
- (act->action == def_cmd))
- break;
- }
-
- if (i < n) {
- if (!(act->flags & KHUI_ACTIONREF_DEFAULT)) {
- khui_menu_remove_action(mdef, i);
- khui_menu_insert_action(mdef, i, def_cmd, KHUI_ACTIONREF_DEFAULT);
- } else {
- /* we are all set */
- }
- } else {
- /* the default action was not found on the context
- menu */
-#ifdef DEBUG
- assert(FALSE);
-#endif
- khui_menu_insert_action(mdef, 0, def_cmd, KHUI_ACTIONREF_DEFAULT);
- }
-
- SetForegroundWindow(khm_hwnd_main);
-
- GetCursorPos(&pt);
- khm_menu_show_panel(menu_id, pt.x, pt.y);
-
- PostMessage(khm_hwnd_main, WM_NULL, 0, 0);
- }
- break;
-
- case NIN_SELECT:
- /* fall through */
- case NIN_KEYSELECT:
- /* If there were any alerts waiting to be shown, we show
- them. Otherwise we perform the default action. */
- khm_notify_icon_activate();
- break;
-
- case NIN_BALLOONUSERCLICK:
- if (balloon_alert) {
- khui_alert * a;
-
- khm_notify_icon_change(KHERR_NONE);
-
- a = balloon_alert;
- balloon_alert = NULL;
-
- khui_alert_lock(a);
- a->displayed = FALSE;
-
- if ((a->flags & KHUI_ALERT_FLAG_DEFACTION) &&
- !(a->flags & KHUI_ALERT_FLAG_REQUEST_WINDOW) &&
- a->n_alert_commands > 0) {
- PostMessage(khm_hwnd_main, WM_COMMAND,
- MAKEWPARAM(a->alert_commands[0],
- 0),
- 0);
- } else if (a->flags &
- KHUI_ALERT_FLAG_REQUEST_WINDOW) {
- khm_show_main_window();
- alert_show_normal(a);
- }
-
- khui_alert_unlock(a);
- khui_alert_release(a);
- } else {
-#ifdef DEBUG
- assert(FALSE);
-#endif
- }
- break;
-
- case NIN_BALLOONHIDE:
- case NIN_BALLOONTIMEOUT:
- khm_notify_icon_change(KHERR_NONE);
- if (balloon_alert) {
- khui_alert * a;
- a = balloon_alert;
- balloon_alert = NULL;
-
- khui_alert_lock(a);
- a->displayed = FALSE;
- khui_alert_unlock(a);
-
- khui_alert_release(a);
- }
- break;
- }
- } else if (uMsg == WM_TIMER) {
- if (wParam == KHUI_TRIGGER_TIMER_ID) {
- KillTimer(hwnd, KHUI_TRIGGER_TIMER_ID);
- khm_timer_fire(hwnd);
- } else if (wParam == KHUI_REFRESH_TIMER_ID) {
- KillTimer(hwnd, KHUI_REFRESH_TIMER_ID);
- kcdb_identity_refresh_all();
- khm_timer_refresh(hwnd);
- }
- }
-
- return DefWindowProc(hwnd, uMsg, wParam, lParam);
-}
-
-ATOM
-khm_register_notifier_wnd_class(void)
-{
- WNDCLASSEX wcx;
-
- ZeroMemory(&wcx, sizeof(wcx));
-
- wcx.cbSize = sizeof(wcx);
- wcx.style = 0;
- wcx.lpfnWndProc = notifier_wnd_proc;
- wcx.cbClsExtra = 0;
- wcx.cbWndExtra = 0;
- wcx.hInstance = khm_hInstance;
- wcx.hIcon = NULL;
- wcx.hCursor = NULL;
- wcx.hbrBackground = NULL;
- wcx.lpszMenuName = NULL;
- wcx.lpszClassName = KHUI_NOTIFIER_CLASS;
- wcx.hIconSm = NULL;
-
- atom_notifier = RegisterClassEx(&wcx);
-
- return atom_notifier;
-}
-
-/*********************************************************************
- Alerter
-**********************************************************************/
-
-typedef struct tag_alerter_alert_data {
- khui_alert * alert;
-
- BOOL seen; /* has the user seen this alert? */
-
- BOOL has_commands; /* we cache the value here. otherwise
- we'll have to get a lock on the
- alert each time we have to find out
- whether there are any commands for
- this alert. */
-
- RECT r_alert; /* the entire alert, relative to self. */
-
- /* the following rects are relative to the top left of r_alert. */
-
- RECT r_title; /* the title. deflate by padding to
- get the text rect. */
- RECT r_icon; /* rect for icon */
- RECT r_message; /* rect for the text. no padding
- necessary. */
- RECT r_suggestion; /* rect for the suggestion. deflate
- by padding to get the suggestion
- rect. The suggestion rect includes
- space for the small icon on the
- left and padding between the icon
- and the text. The size of the small
- icon are as per system metrics
- SM_C{X,Y}SMICON. Padding is
- s_pad.cx vertical. */
-
- int n_cmd_buttons; /* number of command buttons in this alert. */
-
- RECT r_buttons[KHUI_MAX_ALERT_COMMANDS];
- /* rects for the command buttons. */
-
- HWND hwnd_buttons[KHUI_MAX_ALERT_COMMANDS];
- /* handles for the command buttons */
-
- HWND hwnd_marker;
- /* handle to the marker window used as
- a tab-stop target when there are
- not buttons associated with the
- alert. */
-
- LDCL(struct tag_alerter_alert_data);
-} alerter_alert_data;
-
-typedef struct tag_alerter_wnd_data {
- HWND hwnd;
- HFONT hfont;
-
- wchar_t caption[KHUI_MAXCCH_TITLE]; /* the original
- caption for the
- dialog. */
-
- HWND hw_bin;
- HWND hw_scroll;
- HWND hw_close;
-
- int scroll_top;
-
- int n_cmd_buttons; /* total number of command buttons
- in all the alerts being shown in
- this dialog. */
-
- int c_alert; /* current selected alert. */
-
- /* various metrics */
- /* calculated during WM_CREATE */
- SIZE s_button; /* minimum dimensions for command button */
- SIZE s_margin;
- RECT r_text; /* only .left and .right are used. rest are 0 */
- RECT r_title; /* only .left, .right and .bottom are used. .top=0 */
- SIZE s_icon;
- SIZE s_pad;
-
- int cx_wnd;
- int cy_max_wnd;
-
- /* derived from the alert sizes */
- SIZE s_alerts;
-
- QDCL(alerter_alert_data); /* queue of alerts that are being
- shown in this window. */
-
- LDCL(struct tag_alerter_wnd_data); /* for adding to
- khui_alert_windows list. */
-
- int n_alerts;
-
-} alerter_wnd_data;
-
-#define NTF_PARAM DWLP_USER
-
-/* dialog sizes in base dialog units */
-
-#define NTF_MARGIN 5
-#define NTF_WIDTH 200
-#define NTF_MAXHEIGHT 150
-
-#define NTF_TITLE_X NTF_MARGIN
-#define NTF_TITLE_WIDTH (NTF_WIDTH - NTF_MARGIN*2)
-#define NTF_TITLE_HEIGHT 10
-
-#define NTF_TEXT_PAD 2
-
-#define NTF_BUTTON_HEIGHT 14
-
-#define NTF_TIMEOUT 20000
-
-#define ALERT_WINDOW_EX_SYLES (WS_EX_DLGMODALFRAME | WS_EX_CONTEXTHELP)
-#define ALERT_WINDOW_STYLES (WS_DLGFRAME | WS_POPUPWINDOW | WS_CLIPCHILDREN | DS_NOIDLEMSG)
-
-/* Control ids */
-#define IDC_NTF_ALERTBIN 998
-#define IDC_NTF_CLOSE 999
-
-#define IDC_NTF_CMDBUTTONS 1001
-#define IDC_FROM_IDX(alert, bn) ((alert) * (KHUI_MAX_ALERT_COMMANDS + 1) + (bn) + 1 + IDC_NTF_CMDBUTTONS)
-#define ALERT_FROM_IDC(idc) (((idc) - IDC_NTF_CMDBUTTONS) / (KHUI_MAX_ALERT_COMMANDS + 1))
-#define BUTTON_FROM_IDC(idc) (((idc) - IDC_NTF_CMDBUTTONS) % (KHUI_MAX_ALERT_COMMANDS + 1) - 1)
-
-/* if the only command in an alert is "Close", we assume that the
- alert has no commands. */
-#define ALERT_HAS_CMDS(a) ((a)->n_alert_commands > 1 || ((a)->n_alert_commands == 1 && (a)->alert_commands[0] != KHUI_PACTION_CLOSE))
-
-#define SCROLL_LINE_SIZE(d) ((d)->cy_max_wnd / 12)
-
-static void
-add_alert_to_wnd_data(alerter_wnd_data * d,
- khui_alert * a) {
- alerter_alert_data * aiter;
- khm_boolean exists = 0;
-
- khui_alert_lock(a);
-
- /* check if the alert is already there */
- aiter = QTOP(d);
- while(aiter && !exists) {
- if (aiter->alert) {
- khui_alert_lock(aiter->alert);
-
- if (alert_is_equal(aiter->alert, a)) {
- exists = TRUE;
- }
-
- khui_alert_unlock(aiter->alert);
- }
-
- aiter = QNEXT(aiter);
- }
-
- a->flags |= KHUI_ALERT_FLAG_DISPLAY_WINDOW;
-
- if (!exists) {
- a->displayed = TRUE;
- }
-
- khui_alert_unlock(a);
-
- if (!exists) {
- alerter_alert_data * adata;
-
- adata = PMALLOC(sizeof(*adata));
- ZeroMemory(adata, sizeof(*adata));
-
- adata->alert = a;
- khui_alert_hold(a);
-
- QPUT(d, adata);
- d->n_alerts ++;
- }
-}
-
-static alerter_wnd_data *
-create_alerter_wnd_data(HWND hwnd, alert_list * l) {
- alerter_wnd_data * d;
- int i;
- LONG dlgb;
-
- d = PMALLOC(sizeof(*d));
- ZeroMemory(d, sizeof(*d));
-
- d->hwnd = hwnd;
-
- GetWindowText(hwnd, d->caption, ARRAYLENGTH(d->caption));
-
- for (i=0; i < l->n_alerts; i++) {
- add_alert_to_wnd_data(d, l->alerts[i]);
- }
-
- d->n_alerts = l->n_alerts;
-
- LPUSH(&khui_alert_windows, d);
-
- /* Compute a few metrics first */
-
- dlgb = GetDialogBaseUnits();
-
-#define DLG2SCNX(x) MulDiv((x), LOWORD(dlgb), 4)
-#define DLG2SCNY(y) MulDiv((y), HIWORD(dlgb), 8)
-
- d->cx_wnd = DLG2SCNX(NTF_WIDTH);
- d->cy_max_wnd = DLG2SCNY(NTF_MAXHEIGHT);
-
- d->s_margin.cx = DLG2SCNX(NTF_MARGIN);
- d->s_margin.cy = DLG2SCNY(NTF_MARGIN);
-
- d->r_title.left = DLG2SCNX(NTF_TITLE_X);
- d->r_title.right = DLG2SCNX(NTF_TITLE_X + NTF_TITLE_WIDTH);
- d->r_title.top = 0;
- d->r_title.bottom = DLG2SCNY(NTF_TITLE_HEIGHT);
-
- d->s_pad.cx = DLG2SCNX(NTF_TEXT_PAD);
- d->s_pad.cy = DLG2SCNY(NTF_TEXT_PAD);
-
- d->s_icon.cx = GetSystemMetrics(SM_CXICON);
- d->s_icon.cy = GetSystemMetrics(SM_CYICON);
-
- d->r_text.left = d->s_margin.cx * 2 + d->s_icon.cx;
- d->r_text.right = d->cx_wnd - d->s_margin.cx;
- d->r_text.top = 0;
- d->r_text.bottom = 0;
-
- d->s_button.cx = ((d->r_text.right - d->r_text.left) - (KHUI_MAX_ALERT_COMMANDS - 1) * d->s_margin.cx) / KHUI_MAX_ALERT_COMMANDS;
- d->s_button.cy = DLG2SCNY(NTF_BUTTON_HEIGHT);
-
-#undef DLG2SCNX
-#undef DLG2SCNY
-
- d->c_alert = -1;
-
- return d;
-}
-
-static void
-layout_alert(HDC hdc, alerter_wnd_data * d,
- alerter_alert_data * adata) {
- RECT r;
- size_t len;
- int y;
- int icon_y;
-
-#ifdef DEBUG
- assert(adata->alert);
-#endif
-
- khui_alert_lock(adata->alert);
-
- y = 0;
-
- /* Title */
-
- y += d->s_margin.cy;
-
- /* If there is a title and it differs from the title of the
- alerter window, then we have to show the alert title
- separately. */
- if (adata->alert->title &&
- wcscmp(adata->alert->title, d->caption)) {
-
- CopyRect(&adata->r_title, &d->r_title);
- OffsetRect(&adata->r_title, 0, y);
-
- y = adata->r_title.bottom + d->s_margin.cy;
-
- } else {
-
- SetRectEmpty(&adata->r_title);
-
- }
-
- /* Icon */
-
- SetRect(&adata->r_icon, d->s_margin.cx, y,
- d->s_margin.cx + d->s_icon.cx,
- y + d->s_icon.cy);
-
- icon_y = adata->r_icon.bottom + d->s_margin.cy; /* the bottom of the icon */
-
- /* Message */
-
- if (adata->alert->message &&
- SUCCEEDED(StringCchLength(adata->alert->message,
- KHUI_MAXCCH_MESSAGE,
- &len))) {
-
- CopyRect(&r, &d->r_text);
-
- DrawTextEx(hdc, adata->alert->message, (int) len,
- &r,
- DRAWTEXTOPTIONS,
- NULL);
-
- OffsetRect(&r, 0, y);
- CopyRect(&adata->r_message, &r);
-
- y = r.bottom + d->s_margin.cy;
-
- } else {
-
- SetRectEmpty(&adata->r_message);
-
- }
-
- /* Suggestion */
-
- if (adata->alert->suggestion &&
- SUCCEEDED(StringCchLength(adata->alert->suggestion,
- KHUI_MAXCCH_SUGGESTION,
- &len))) {
- int pad = d->s_pad.cx + GetSystemMetrics(SM_CXSMICON);
-
- CopyRect(&r, &d->r_text);
- r.left += pad;
-
- DrawTextEx(hdc, adata->alert->suggestion, (int) len,
- &r,
- DRAWTEXTOPTIONS,
- NULL);
-
- r.left -= pad;
-
- InflateRect(&r, d->s_pad.cx, d->s_pad.cy);
- OffsetRect(&r, 0, -r.top + y);
- CopyRect(&adata->r_suggestion, &r);
-
- y = r.bottom + d->s_margin.cy;
-
- } else {
-
- SetRectEmpty(&adata->r_suggestion);
-
- }
-
- y = max(y, icon_y);
-
- /* Buttons */
-
- if (ALERT_HAS_CMDS(adata->alert)) {
- khm_int32 i;
- int x, width;
- wchar_t caption[KHUI_MAXCCH_SHORT_DESC];
- size_t len;
- SIZE s;
- int skip_close;
-
- adata->has_commands = TRUE;
-
- if (d->n_alerts > 1)
- skip_close = TRUE;
- else
- skip_close = FALSE;
-
- x = d->r_text.left;
-
-#ifdef DEBUG
- assert(adata->alert->n_alert_commands <= KHUI_MAX_ALERT_COMMANDS);
-#endif
-
- for (i=0; i < adata->alert->n_alert_commands; i++) {
-
- if (adata->alert->alert_commands[i] == KHUI_PACTION_CLOSE && skip_close) {
- SetRectEmpty(&adata->r_buttons[i]);
- continue;
- }
-
- caption[0] = L'\0';
- len = 0;
- khm_get_action_caption(adata->alert->alert_commands[i],
- caption, sizeof(caption));
- StringCchLength(caption, ARRAYLENGTH(caption), &len);
-
- if (!GetTextExtentPoint32(hdc, caption, (int) len, &s)) {
- width = d->s_button.cx;
- } else {
- width = s.cx + d->s_margin.cx * 2;
- }
-
- if (width < d->s_button.cx)
- width = d->s_button.cx;
- else if (width > (d->r_text.right - d->r_text.left))
- width = d->r_text.right - d->r_text.left;
-
- if (x + width > d->r_text.right) {
- /* new line */
- x = d->r_text.left;
- y += d->s_button.cy + d->s_pad.cy;
- }
-
- SetRect(&adata->r_buttons[i], x, y, x + width, y + d->s_button.cy);
-
- x += width + d->s_margin.cx;
- }
-
- y += d->s_button.cy + d->s_margin.cy;
- }
-
- khui_alert_unlock(adata->alert);
-
- /* Now set the rect for the whole alert */
- SetRect(&adata->r_alert, 0, 0, d->cx_wnd, y);
-
-}
-
-static void
-pick_title_for_alerter_window(alerter_wnd_data * d) {
- alerter_alert_data * adata;
- wchar_t caption[KHUI_MAXCCH_TITLE];
- khm_boolean common_caption = TRUE;
- khui_alert_type ctype = KHUI_ALERTTYPE_NONE;
- khm_boolean common_type = TRUE;
-
- /* - If all the alerts have the same title, then we use the common
- title.
-
- - If all the alerts are of the same type, then we pick a title
- that is suitable for the type.
-
- - All else fails, we use a default caption for the window.
- */
-
- caption[0] = L'\0';
- adata = QTOP(d);
- while (adata && (common_caption || common_type)) {
-
- if (adata->alert) {
- khui_alert_lock(adata->alert);
-
- if (common_caption) {
- if (caption[0] == L'\0') {
- if (adata->alert->title)
- StringCbCopy(caption, sizeof(caption), adata->alert->title);
- } else if (adata->alert->title &&
- wcscmp(caption, adata->alert->title)) {
- common_caption = FALSE;
- }
- }
-
- if (common_type) {
- if (ctype == KHUI_ALERTTYPE_NONE)
- ctype = adata->alert->alert_type;
- else if (ctype != adata->alert->alert_type)
- common_type = FALSE;
- }
-
- khui_alert_unlock(adata->alert);
- }
-
- adata = QNEXT(adata);
- }
-
- /* just in case someone changes d->caption to a pointer from an
- array */
-#ifdef DEBUG
- assert(sizeof(d->caption) > sizeof(wchar_t *));
-#endif
-
- if (common_caption && caption[0] != L'\0') {
- StringCbCopy(d->caption, sizeof(d->caption), caption);
- } else if (common_type && ctype != KHUI_ALERTTYPE_NONE) {
- switch(ctype) {
- case KHUI_ALERTTYPE_PLUGIN:
- LoadString(khm_hInstance, IDS_ALERTTYPE_PLUGIN,
- d->caption, ARRAYLENGTH(d->caption));
- break;
-
- case KHUI_ALERTTYPE_EXPIRE:
- LoadString(khm_hInstance, IDS_ALERTTYPE_EXPIRE,
- d->caption, ARRAYLENGTH(d->caption));
- break;
-
- case KHUI_ALERTTYPE_RENEWFAIL:
- LoadString(khm_hInstance, IDS_ALERTTYPE_RENEWFAIL,
- d->caption, ARRAYLENGTH(d->caption));
- break;
-
- case KHUI_ALERTTYPE_ACQUIREFAIL:
- LoadString(khm_hInstance, IDS_ALERTTYPE_ACQUIREFAIL,
- d->caption, ARRAYLENGTH(d->caption));
- break;
-
- case KHUI_ALERTTYPE_CHPW:
- LoadString(khm_hInstance, IDS_ALERTTYPE_CHPW,
- d->caption, ARRAYLENGTH(d->caption));
- break;
-
- default:
- LoadString(khm_hInstance, IDS_ALERT_DEFAULT,
- d->caption, ARRAYLENGTH(d->caption));
- }
- } else {
- LoadString(khm_hInstance, IDS_ALERT_DEFAULT,
- d->caption, ARRAYLENGTH(d->caption));
- }
-
- SetWindowText(d->hwnd, d->caption);
-}
-
-static void
-estimate_alerter_wnd_sizes(alerter_wnd_data * d) {
- HDC hdc;
- HFONT hf_old;
- int height = 0;
-
- alerter_alert_data * adata;
-
- pick_title_for_alerter_window(d);
-
- hdc = GetDC(d->hwnd);
-#ifdef DEBUG
- assert(hdc);
-#endif
-
- if (d->hfont == NULL)
- d->hfont = (HFONT) GetStockObject(DEFAULT_GUI_FONT);
-
-#ifdef DEBUG
- assert(d->hfont);
-#endif
-
- hf_old = SelectFont(hdc, d->hfont);
-
- adata = QTOP(d);
- while(adata) {
- layout_alert(hdc, d, adata);
-
- height += adata->r_alert.bottom;
-
- adata = QNEXT(adata);
- }
-
- SelectFont(hdc, hf_old);
- ReleaseDC(d->hwnd, hdc);
-
- d->s_alerts.cx = d->cx_wnd;
- d->s_alerts.cy = height;
-}
-
-static void
-layout_command_buttons(alerter_wnd_data * d) {
-
- alerter_alert_data * adata;
- HDWP hdefer;
- int y;
-
- hdefer = BeginDeferWindowPos(d->n_cmd_buttons);
-
- y = 0;
- adata = QTOP(d);
- while (adata) {
- RECT r;
- int i;
-
- if (!adata->has_commands)
- goto done;
-
- for (i=0; i < adata->n_cmd_buttons; i++) {
- if (IsRectEmpty(&adata->r_buttons[i])) {
- /* the button is no longer needed */
- if (adata->hwnd_buttons[i] != NULL) {
- DestroyWindow(adata->hwnd_buttons[i]);
- adata->hwnd_buttons[i] = NULL;
- }
-
- continue;
- }
-
- if (adata->hwnd_buttons[i] == NULL) {
- continue;
- }
-
- CopyRect(&r, &adata->r_buttons[i]);
- OffsetRect(&r, 0, y - d->scroll_top);
-
- DeferWindowPos(hdefer,
- adata->hwnd_buttons[i], NULL,
- r.left, r.top, 0, 0,
- SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER |
- SWP_NOSIZE);
- }
-
- done:
- y += adata->r_alert.bottom;
- adata = QNEXT(adata);
- }
-
- EndDeferWindowPos(hdefer);
-}
-
-static void
-setup_alerter_window_controls(alerter_wnd_data * d) {
-
- RECT r_alerts;
- RECT r_window;
- RECT r_client;
- RECT r_parent;
- HWND hw_parent;
- HWND hw_focus = NULL;
- BOOL close_button = FALSE;
- BOOL scrollbar = FALSE;
- BOOL redraw_scollbar = FALSE;
-
- /* estimate_alerter_wnd_sizes() must be called before calling
- this. */
-#ifdef DEBUG
- assert(d->s_alerts.cy > 0);
-#endif
-
- r_alerts.left = 0;
- r_alerts.top = 0;
- r_alerts.right = d->cx_wnd;
-
- if (d->s_alerts.cy > d->cy_max_wnd) {
-
- BOOL redraw = FALSE;
-
- r_alerts.right += GetSystemMetrics(SM_CXVSCROLL);
- r_alerts.bottom = d->cy_max_wnd;
-
- CopyRect(&r_client, &r_alerts);
- r_client.bottom += d->s_margin.cy + d->s_button.cy + d->s_pad.cy;
- close_button = TRUE;
-
- if (d->scroll_top > d->s_alerts.cy - d->cy_max_wnd)
- d->scroll_top = d->s_alerts.cy - d->cy_max_wnd;
-
- scrollbar = TRUE;
- } else {
- r_alerts.bottom = d->s_alerts.cy;
-
- CopyRect(&r_client, &r_alerts);
-
- if (d->n_alerts == 1) {
-
- if (!QTOP(d)->has_commands) {
- r_client.bottom += d->s_margin.cy * 2 + d->s_button.cy;
- close_button = TRUE;
- }
-
- } else {
-
- r_client.bottom += d->s_margin.cy * 2 + d->s_button.cy;
- close_button = TRUE;
- }
-
- d->scroll_top = 0;
- }
-
- if (d->hw_bin == NULL) {
- d->hw_bin = CreateWindowEx(WS_EX_CONTROLPARENT,
- MAKEINTATOM(atom_alert_bin),
- L"Alert Container",
- WS_CHILD | WS_CLIPCHILDREN |
- WS_VISIBLE |
- ((scrollbar)? WS_VSCROLL : 0),
- r_alerts.left, r_alerts.top,
- r_alerts.right - r_alerts.left,
- r_alerts.bottom - r_alerts.top,
- d->hwnd,
- (HMENU) IDC_NTF_ALERTBIN,
- khm_hInstance,
- (LPVOID) d);
- } else {
- redraw_scollbar = TRUE;
- SetWindowLongPtr(d->hw_bin, GWL_STYLE,
- WS_CHILD | WS_CLIPCHILDREN |
- WS_VISIBLE |
- ((scrollbar)? WS_VSCROLL : 0));
- SetWindowPos(d->hw_bin, NULL,
- r_alerts.left, r_alerts.top,
- r_alerts.right - r_alerts.left,
- r_alerts.bottom - r_alerts.top,
- SWP_NOOWNERZORDER | SWP_NOZORDER | SWP_NOACTIVATE);
- }
-
- if (scrollbar) {
- SCROLLINFO si;
-
- ZeroMemory(&si, sizeof(si));
- si.cbSize = sizeof(si);
- si.fMask = SIF_PAGE | SIF_POS | SIF_RANGE;
- si.nMin = 0;
- si.nMax = d->s_alerts.cy;
- si.nPage = d->cy_max_wnd;
- si.nPos = d->scroll_top;
-
- SetScrollInfo(d->hw_bin, SB_VERT, &si, redraw_scollbar);
- }
-
- /* create the action buttons */
- {
- alerter_alert_data * adata;
- int y;
- int idx;
- HWND last_window = HWND_TOP;
- int n_buttons = 0;
-
- idx = 0;
- y = - d->scroll_top;
- adata = QTOP(d);
- while(adata) {
- if (adata->has_commands) {
- int i;
- wchar_t caption[KHUI_MAXCCH_SHORT_DESC];
- RECT r;
-
- if (adata->hwnd_marker) {
- DestroyWindow(adata->hwnd_marker);
- adata->hwnd_marker = NULL;
- }
-
- khui_alert_lock(adata->alert);
-
- adata->n_cmd_buttons = adata->alert->n_alert_commands;
-
- for (i=0; i < adata->alert->n_alert_commands; i++) {
-
- n_buttons ++;
-
- if (IsRectEmpty(&adata->r_buttons[i])) {
- /* this button is not necessary */
- if (adata->hwnd_buttons[i]) {
- DestroyWindow(adata->hwnd_buttons[i]);
- adata->hwnd_buttons[i] = NULL;
- }
-
- continue;
- }
-
- if (adata->hwnd_buttons[i] != NULL) {
- /* already there */
- CopyRect(&r, &adata->r_buttons[i]);
- OffsetRect(&r, 0, y);
-
- SetWindowPos(adata->hwnd_buttons[i], last_window,
- r.left, r.top,
- r.right - r.left,
- r.bottom - r.top,
- SWP_NOACTIVATE | SWP_NOOWNERZORDER |
- SWP_SHOWWINDOW);
-
- last_window = adata->hwnd_buttons[i];
-
- if (hw_focus == NULL)
- hw_focus = adata->hwnd_buttons[i];
-
- continue;
- }
-
- khm_get_action_caption(adata->alert->alert_commands[i],
- caption, sizeof(caption));
-
- CopyRect(&r, &adata->r_buttons[i]);
- OffsetRect(&r, 0, y);
-
- adata->hwnd_buttons[i] =
- CreateWindowEx(0,
- L"BUTTON",
- caption,
- WS_CHILD | WS_TABSTOP | BS_NOTIFY,
- r.left, r.top,
- r.right - r.left,
- r.bottom - r.top,
- d->hw_bin,
- (HMENU) (INT_PTR) IDC_FROM_IDX(idx, i),
- khm_hInstance,
- NULL);
-#ifdef DEBUG
- assert(adata->hwnd_buttons[i]);
-#endif
-
- if (d->hfont) {
- SendMessage(adata->hwnd_buttons[i], WM_SETFONT,
- (WPARAM) d->hfont, FALSE);
- }
-
- SetWindowPos(adata->hwnd_buttons[i], last_window,
- 0, 0, 0, 0,
- SWP_NOACTIVATE | SWP_NOOWNERZORDER |
- SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
-
- last_window = adata->hwnd_buttons[i];
-
- if (hw_focus == NULL)
- hw_focus = adata->hwnd_buttons[i];
- }
-
- khui_alert_unlock(adata->alert);
- } else {
- int i;
-
- /* Destroy any buttons that belong to the alert. We
- might have some left over, if there were command
- belonging to the alert that were ignored.*/
-
- for (i=0; i < adata->n_cmd_buttons; i++) {
- if (adata->hwnd_buttons[i]) {
- DestroyWindow(adata->hwnd_buttons[i]);
- adata->hwnd_buttons[i] = NULL;
- }
- }
-
- adata->n_cmd_buttons = 0;
-
- if (adata->hwnd_marker == NULL) {
- adata->hwnd_marker =
- CreateWindowEx(0,
- L"BUTTON",
- L"Marker",
- WS_CHILD | WS_TABSTOP | WS_VISIBLE | BS_NOTIFY,
- -10, 0,
- 5, 5,
- d->hw_bin,
- (HMENU) (INT_PTR) IDC_FROM_IDX(idx, -1),
- khm_hInstance,
- NULL);
-#ifdef DEBUG
- assert(adata->hwnd_marker);
-#endif
- }
-
- SetWindowPos(adata->hwnd_marker, last_window,
- 0, 0, 0, 0,
- SWP_NOACTIVATE | SWP_NOOWNERZORDER |
- SWP_NOMOVE | SWP_NOSIZE);
-
- last_window = adata->hwnd_marker;
-
- if (scrollbar) {
- EnableWindow(adata->hwnd_marker, TRUE);
- if (hw_focus == NULL)
- hw_focus = adata->hwnd_marker;
- } else {
- EnableWindow(adata->hwnd_marker, FALSE);
- }
- }
-
- y += adata->r_alert.bottom;
- adata = QNEXT(adata);
- idx++;
- }
-
- d->n_cmd_buttons = n_buttons;
- }
-
- if (close_button) {
- if (d->hw_close == NULL) {
- wchar_t caption[256];
-
- khm_get_action_caption(KHUI_PACTION_CLOSE, caption, sizeof(caption));
-
- d->hw_close = CreateWindowEx(0,
- L"BUTTON",
- caption,
- WS_CHILD | BS_DEFPUSHBUTTON | WS_TABSTOP | BS_NOTIFY,
- 0,0,100,100,
- d->hwnd,
- (HMENU) IDC_NTF_CLOSE,
- khm_hInstance,
- NULL);
-
-#ifdef DEBUG
- assert(d->hw_close);
- assert(d->hfont);
-#endif
- if (d->hfont)
- SendMessage(d->hw_close, WM_SETFONT, (WPARAM) d->hfont, FALSE);
- }
-
- {
- int x,y,width,height;
-
- x = d->r_text.left;
- y = r_client.bottom - (d->s_margin.cy + d->s_button.cy);
- width = d->s_button.cx;
- height = d->s_button.cy;
-
- SetWindowPos(d->hw_close, NULL,
- x, y, width, height,
- SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER |
- SWP_SHOWWINDOW);
- }
-
- if (hw_focus == NULL || d->n_cmd_buttons == 0)
- hw_focus = d->hw_close;
-
- } else {
- if (d->hw_close != NULL) {
- DestroyWindow(d->hw_close);
- d->hw_close = NULL;
- }
- }
-
- CopyRect(&r_window, &r_client);
- AdjustWindowRectEx(&r_window, ALERT_WINDOW_STYLES,
- FALSE, ALERT_WINDOW_EX_SYLES);
- OffsetRect(&r_window, -r_window.left, -r_window.top);
-
- /* center the window above the parent window. */
-
- hw_parent = GetWindow(d->hwnd, GW_OWNER);
- GetWindowRect(hw_parent, &r_parent);
-
- {
- int x,y;
-
- x = (r_parent.left + r_parent.right - (r_window.right - r_window.left)) / 2;
- y = (r_parent.top + r_parent.bottom - (r_window.bottom - r_window.top)) / 2;
-
- SetWindowPos(d->hwnd,
- HWND_TOP,
- x, y,
- r_window.right - r_window.left,
- r_window.bottom - r_window.top,
- SWP_SHOWWINDOW | SWP_NOOWNERZORDER);
- }
-
- if (hw_focus != NULL)
- PostMessage(d->hwnd, WM_NEXTDLGCTL, (WPARAM) hw_focus, MAKELPARAM(TRUE, 0));
-}
-
-static void
-scroll_to_position(alerter_wnd_data * d, int new_pos, khm_boolean redraw_scrollbar) {
- int delta;
- SCROLLINFO si;
- HWND hwnd = d->hw_bin;
-
- if (new_pos < 0)
- new_pos = 0;
- else if (new_pos > d->s_alerts.cy - d->cy_max_wnd)
- new_pos = d->s_alerts.cy - d->cy_max_wnd;
-
- if (new_pos == d->scroll_top)
- return;
-
- delta = d->scroll_top - new_pos;
-
- d->scroll_top -= delta;
-
- ScrollWindowEx(hwnd, 0, delta,
- NULL, NULL, NULL, NULL,
- SW_INVALIDATE | SW_ERASE);
-
- layout_command_buttons(d);
-
- ZeroMemory(&si, sizeof(si));
-
- si.fMask = SIF_POS;
- si.nPos = d->scroll_top;
-
- SetScrollInfo(hwnd, SB_VERT, &si, redraw_scrollbar);
-}
-
-static void
-select_alert(alerter_wnd_data * d, int alert) {
-
- int y;
- RECT old_sel, new_sel;
- alerter_alert_data * adata;
- int idx;
-
- if (d->n_alerts == 1 ||
- alert < 0 ||
- alert > d->n_alerts ||
- d->c_alert == alert)
- return;
-
- SetRectEmpty(&old_sel);
- SetRectEmpty(&new_sel);
- idx = 0; y = -d->scroll_top;
- adata = QTOP(d);
- while(adata && (idx <= d->c_alert || idx <= alert)) {
-
- if (idx == d->c_alert) {
- CopyRect(&old_sel, &adata->r_alert);
- OffsetRect(&old_sel, 0, y);
- }
-
- if (idx == alert) {
- CopyRect(&new_sel, &adata->r_alert);
- OffsetRect(&new_sel, 0, y);
- }
-
- y += adata->r_alert.bottom;
- idx ++;
- adata = QNEXT(adata);
- }
-
- d->c_alert = alert;
- if (!IsRectEmpty(&old_sel))
- InvalidateRect(d->hw_bin, &old_sel, TRUE);
- if (!IsRectEmpty(&new_sel))
- InvalidateRect(d->hw_bin, &new_sel, TRUE);
-}
-
-static void
-ensure_command_is_visible(alerter_wnd_data * d, int id) {
- int alert_idx;
- int y = 0;
- alerter_alert_data * adata;
- int new_pos = 0;
-
- alert_idx = ALERT_FROM_IDC(id);
-
-#ifdef DEBUG
- assert(alert_idx >= 0 && alert_idx < d->n_alerts);
-#endif
- if (alert_idx >= d->n_alerts || alert_idx < 0)
- return;
-
- adata = QTOP(d);
- while(adata && alert_idx > 0) {
- y += adata->r_alert.bottom;
- alert_idx--;
- adata = QNEXT(adata);
- }
-
-#ifdef DEBUG
- assert(alert_idx == 0);
- assert(adata);
- assert(adata->alert);
-#endif
- if (adata == NULL || alert_idx != 0)
- return;
-
- new_pos = d->scroll_top;
- if (y < d->scroll_top) {
- new_pos = y;
- } else if (y + adata->r_alert.bottom > d->scroll_top + d->cy_max_wnd) {
- new_pos = y + adata->r_alert.bottom - d->cy_max_wnd;
- }
-
- if (new_pos != d->scroll_top)
- scroll_to_position(d, new_pos, TRUE);
-
- select_alert(d, ALERT_FROM_IDC(id));
-}
-
-static void
-handle_mouse_select(alerter_wnd_data * d, int mouse_x, int mouse_y) {
- int y;
- alerter_alert_data * adata;
-
- y = -d->scroll_top;
- adata = QTOP(d);
- while(adata) {
- if (y <= mouse_y && (y + adata->r_alert.bottom) > mouse_y) {
- HWND hw = NULL;
-
- if (adata->n_cmd_buttons > 0)
- hw = adata->hwnd_buttons[0];
- else
- hw = adata->hwnd_marker;
-
- if (hw && !IsWindowEnabled(hw))
- hw = GetNextDlgTabItem(d->hwnd, hw, FALSE);
-
- if (hw)
- PostMessage(d->hwnd, WM_NEXTDLGCTL, (WPARAM) hw, MAKELPARAM(TRUE, 0));
-
- return;
- }
-
- y += adata->r_alert.bottom;
- adata = QNEXT(adata);
- }
-}
-
-static void
-process_command_button(alerter_wnd_data * d, int id) {
- int alert_idx;
- int cmd_idx;
- khm_int32 flags = 0;
- khm_int32 cmd = 0;
- alerter_alert_data * adata;
- int i;
-
- alert_idx = ALERT_FROM_IDC(id);
- cmd_idx = BUTTON_FROM_IDC(id);
-
-#ifdef DEBUG
- assert(alert_idx >= 0 && alert_idx < d->n_alerts);
-#endif
- if (alert_idx >= d->n_alerts || alert_idx < 0)
- return;
-
- if (cmd_idx < 0) {
- /* the user selected a marker button. Nothing to do. */
- return;
- }
-
- adata = QTOP(d);
- while(adata && alert_idx > 0) {
- alert_idx--;
- adata = QNEXT(adata);
- }
-
-#ifdef DEBUG
- assert(alert_idx == 0);
- assert(adata);
- assert(adata->alert);
-#endif
- if (adata == NULL || alert_idx != 0)
- return;
-
- khui_alert_lock(adata->alert);
-#ifdef DEBUG
- assert(cmd_idx >= 0 && cmd_idx < adata->alert->n_alert_commands);
-#endif
-
- if (cmd_idx >= 0 && cmd_idx < adata->alert->n_alert_commands) {
- cmd = adata->alert->alert_commands[cmd_idx];
- }
-
- flags = adata->alert->flags;
-
- adata->alert->response = cmd;
-
- khui_alert_unlock(adata->alert);
-
- /* if we were supposed to dispatch the command, do so */
- if (cmd != 0 &&
- cmd != KHUI_PACTION_CLOSE &&
- (flags & KHUI_ALERT_FLAG_DISPATCH_CMD)) {
- PostMessage(khm_hwnd_main, WM_COMMAND,
- MAKEWPARAM(cmd, 0), 0);
- }
-
- /* if this was the only alert in the alert group and its close
- button was clicked, we close the alert window. Otherwise, the
- alert window creates its own close button that closes the
- window. */
- if (d->n_alerts == 1) {
- PostMessage(d->hwnd, WM_CLOSE, 0, 0);
- }
-
- /* While we are at it, we should disable the buttons for this
- alert since we have already dispatched the command for it. */
- if (cmd != 0) {
- HWND hw_focus = GetFocus();
- khm_boolean focus_trapped = FALSE;
-
- for (i=0; i < adata->n_cmd_buttons; i++) {
- if (adata->hwnd_buttons[i]) {
- if (hw_focus == adata->hwnd_buttons[i])
- focus_trapped = TRUE;
-
- EnableWindow(adata->hwnd_buttons[i], FALSE);
- }
- }
-
- if (focus_trapped) {
- hw_focus = GetNextDlgTabItem(d->hwnd, hw_focus, FALSE);
- if (hw_focus)
- PostMessage(d->hwnd, WM_NEXTDLGCTL, (WPARAM) hw_focus, MAKELPARAM(TRUE,0));
- }
- }
-}
-
-static void
-destroy_alerter_wnd_data(alerter_wnd_data * d) {
- alerter_alert_data * adata;
-
- LDELETE(&khui_alert_windows, d);
-
- QGET(d, &adata);
- while(adata) {
-
- if (adata->alert) {
-
- khui_alert_lock(adata->alert);
-
- adata->alert->displayed = FALSE;
-
- khui_alert_unlock(adata->alert);
-
- khui_alert_release(adata->alert);
- adata->alert = NULL;
- }
-
- PFREE(adata);
-
- QGET(d, &adata);
- }
-
- PFREE(d);
-}
-
-/* both ref and to_add must be locked and held */
-static khm_boolean
-alert_can_consolidate(khui_alert * ref,
- khui_alert * to_add,
- alert_list * alist) {
-
- /* first check if we can add anything */
- if (alist->n_alerts == ARRAYLENGTH(alist->alerts))
- return FALSE;
-
-#ifdef DEBUG
- assert(to_add != NULL);
-#endif
-
- if (ref == NULL) {
- /* we are testing whether to_add should be added to the alist
- on its own. */
- if ((to_add->flags & KHUI_ALERT_FLAG_DISPLAY_BALLOON) &&
- !(to_add->flags & KHUI_ALERT_FLAG_DISPLAY_WINDOW)) {
- /* already displayed */
- return FALSE;
- }
-
- if ((to_add->flags & (KHUI_ALERT_FLAG_REQUEST_BALLOON |
- KHUI_ALERT_FLAG_REQUEST_WINDOW)) == KHUI_ALERT_FLAG_REQUEST_BALLOON) {
- /* needs to be shown in a balloon */
- return FALSE;
- }
-
- return TRUE;
- }
-
- /* if the ref or to_add are marked for modal, then we can't
- consolidate them */
- if ((ref->flags & KHUI_ALERT_FLAG_MODAL) ||
- (to_add->flags & KHUI_ALERT_FLAG_MODAL))
- return FALSE;
-
- /* also, if either of them have requested to be exclusively shown
- in a balloon, then we can't consolidate them. */
- if (((ref->flags & (KHUI_ALERT_FLAG_REQUEST_BALLOON |
- KHUI_ALERT_FLAG_REQUEST_WINDOW)) == KHUI_ALERT_FLAG_REQUEST_BALLOON)
-
- ||
-
- ((to_add->flags & (KHUI_ALERT_FLAG_REQUEST_BALLOON |
- KHUI_ALERT_FLAG_REQUEST_WINDOW)) == KHUI_ALERT_FLAG_REQUEST_BALLOON))
- return FALSE;
-
- /* for now, all we check if whether they are of the same type. */
- if (ref->alert_type != KHUI_ALERTTYPE_NONE &&
- ref->alert_type == to_add->alert_type)
- return TRUE;
- else
- return FALSE;
-}
-
-/* both a1 and a2 must be locked */
-static khm_boolean
-alert_is_equal(khui_alert * a1, khui_alert * a2) {
- khm_int32 i;
-
- if ((a1->severity != a2->severity) ||
- (a1->n_alert_commands != a2->n_alert_commands) ||
- (a1->title && (!a2->title || wcscmp(a1->title, a2->title))) ||
- (!a1->title && a2->title) ||
- (a1->message && (!a2->message || wcscmp(a1->message, a2->message))) ||
- (!a1->message && a2->message) ||
- (a1->suggestion && (!a2->suggestion || wcscmp(a1->suggestion, a2->suggestion))) ||
- (!a1->suggestion && a2->suggestion)) {
-
- return FALSE;
-
- }
-
- for (i=0; i < a1->n_alert_commands; i++) {
- if (a1->alert_commands[i] != a2->alert_commands[i])
- return FALSE;
- }
-
- return TRUE;
-}
-
-/* the return value is the number of alerts added to alist */
-static khm_int32
-alert_consolidate(alert_list * alist,
- khui_alert * alert,
- khm_boolean add_from_queue) {
-
- khui_alert * listtop;
- int queue_size = 0;
- int i;
- khm_int32 n_added = 0;
-
-#ifdef DEBUG
- assert(alist);
-#endif
-
- if (alist->n_alerts == ARRAYLENGTH(alist->alerts)) {
- /* can't add anything */
-
- return 0;
- }
-
- /* if the list is empty, we just add one alert */
- if (alist->n_alerts == 0) {
-
- if (alert) {
- khui_alert_lock(alert);
- if (alert_can_consolidate(NULL, alert, alist)) {
- alert_list_add_alert(alist, alert);
- n_added ++;
- alert = NULL;
- }
- khui_alert_unlock(alert);
- }
-
- if (n_added == 0 && add_from_queue) {
- khui_alert * q;
- int i;
-
- queue_size = alert_queue_get_size();
- for (i=0; i < queue_size && n_added == 0; i++) {
- q = alert_queue_get_alert_by_pos(i);
- if (q) {
- khui_alert_lock(q);
- if (alert_can_consolidate(NULL, q, alist)) {
- alert_list_add_alert(alist, q);
- n_added++;
- alert_queue_delete_alert(q);
- }
- khui_alert_unlock(q);
- khui_alert_release(q);
- }
- }
- }
-
- if (n_added == 0) {
- /* nothing to add */
- return 0;
- }
- }
-
- /* at this point, the alert list is not empty */
-#ifdef DEBUG
- assert(alist->n_alerts != 0);
- assert(alist->alerts[0]);
-#endif
-
- listtop = alist->alerts[0];
- khui_alert_hold(listtop);
- khui_alert_lock(listtop);
-
- queue_size = alert_queue_get_size();
-
- if (alert) {
- khui_alert_lock(alert);
- if (alert_can_consolidate(listtop, alert, alist)) {
- alert_list_add_alert(alist, alert);
- n_added ++;
- }
- khui_alert_unlock(alert);
- }
-
- if (add_from_queue) {
- for (i=0; i < queue_size; i++) {
- khui_alert * a;
-
- a = alert_queue_get_alert_by_pos(i);
- if (a == NULL)
- continue;
-
- khui_alert_lock(a);
- if (alert_can_consolidate(listtop, a, alist)) {
- alert_queue_delete_alert(a);
- alert_list_add_alert(alist, a);
- n_added ++;
-
- queue_size--;
- i--;
-#ifdef DEBUG
- assert(alert_queue_get_size() == queue_size);
-#endif
- }
- khui_alert_unlock(a);
- khui_alert_release(a);
- }
- }
-
- khui_alert_unlock(listtop);
- khui_alert_release(listtop);
-
- return n_added;
-}
-
-static khm_int32
-alert_check_consolidate_window(alerter_wnd_data * d, khui_alert * a) {
- alert_list alist;
- alerter_alert_data * adata;
- int n_added;
-
- alert_list_init(&alist);
-
- adata = QTOP(d);
- while(adata) {
-
-#ifdef DEBUG
- assert(adata->alert);
-#endif
- alert_list_add_alert(&alist, adata->alert);
-
- adata = QNEXT(adata);
- }
-
- n_added = alert_consolidate(&alist, a, FALSE);
-
- alert_list_destroy(&alist);
-
- return n_added;
-}
-
-static khm_int32
-alert_show_minimized(khui_alert * a) {
- wchar_t tbuf[64]; /* corresponds to NOTIFYICONDATA::szInfoTitle[] */
- wchar_t mbuf[256]; /* corresponds to NOTIFYICONDATA::szInfo[] */
-
-#ifdef DEBUG
- assert(a);
-#endif
- if (a == NULL)
- return KHM_ERROR_INVALID_PARAM;
-
- khui_alert_lock(a);
-
- if (a->message == NULL)
- goto done;
-
- if (a->title == NULL) {
- LoadString(khm_hInstance, IDS_ALERT_DEFAULT,
- tbuf, ARRAYLENGTH(tbuf));
- } else {
- StringCbCopy(tbuf, sizeof(tbuf), a->title);
- }
-
- if (FAILED(StringCbCopy(mbuf, sizeof(mbuf), a->message)) ||
- (!(a->flags & KHUI_ALERT_FLAG_DEFACTION) &&
- (a->n_alert_commands > 0 ||
- a->suggestion ||
- (a->flags & KHUI_ALERT_FLAG_VALID_ERROR)))) {
- /* if mbuf wasn't big enough, this should have copied a
- truncated version of it */
- size_t cch_m, cch_p;
- wchar_t postfix[256];
-
- cch_p = LoadString(khm_hInstance, IDS_ALERT_MOREINFO, postfix,
- ARRAYLENGTH(postfix));
- cch_p++; /* account for NULL */
-
- StringCchLength(mbuf, ARRAYLENGTH(mbuf), &cch_m);
- cch_m = min(cch_m, ARRAYLENGTH(mbuf) - cch_p);
-
- StringCchCopy(mbuf + cch_m, ARRAYLENGTH(mbuf) - cch_m,
- postfix);
-
- a->flags |= KHUI_ALERT_FLAG_REQUEST_WINDOW;
- }
-
- a->flags |= KHUI_ALERT_FLAG_DISPLAY_BALLOON;
-
-#ifdef DEBUG
- assert(balloon_alert == NULL);
-#endif
-
- if (balloon_alert) {
- khui_alert_lock(balloon_alert);
- balloon_alert->displayed = FALSE;
- khui_alert_unlock(balloon_alert);
- khui_alert_release(balloon_alert);
- balloon_alert = NULL;
- }
-
- balloon_alert = a;
- khui_alert_hold(a);
-
- a->displayed = TRUE;
-
- khm_notify_icon_balloon(a->severity,
- tbuf,
- mbuf,
- NTF_TIMEOUT);
-
- done:
- khui_alert_unlock(a);
-
- return KHM_ERROR_SUCCESS;
-}
-
-static khm_int32
-alert_show_normal(khui_alert * a) {
- wchar_t buf[256];
- wchar_t * title;
- alert_list alist;
-
- khui_alert_lock(a);
-
- if(a->title == NULL) {
- LoadString(khm_hInstance, IDS_ALERT_DEFAULT,
- buf, ARRAYLENGTH(buf));
- title = buf;
- } else
- title = a->title;
-
- khui_alert_unlock(a);
-
- alert_list_init(&alist);
- alert_list_set_title(&alist, title);
- alert_list_add_alert(&alist, a);
-
- alert_show_list(&alist);
-
- alert_list_destroy(&alist);
-
- return KHM_ERROR_SUCCESS;
-}
-
-static khm_int32
-alert_show_list(alert_list * alist) {
- HWND hwa;
-
- /* we don't need to keep track of the window handle
- because the window procedure adds it to the dialog
- list automatically */
-
- hwa =
- CreateWindowEx(ALERT_WINDOW_EX_SYLES,
- MAKEINTATOM(atom_alerter),
- alist->title,
- ALERT_WINDOW_STYLES,
- 0, 0, 300, 300, // bogus values
- khm_hwnd_main,
- (HMENU) NULL,
- khm_hInstance,
- (LPVOID) alist);
-
- ShowWindow(hwa, SW_SHOW);
-
- return (hwa != NULL);
-}
-
-static khm_int32
-alert_show(khui_alert * a) {
- khm_boolean show_normal = FALSE;
- khm_boolean show_mini = FALSE;
-
- khui_alert_lock(a);
-
- /* is there an alert already? If so, we just enqueue the message
- and let it sit. */
- if (ALERT_DISPLAYED() &&
- !(a->flags & KHUI_ALERT_FLAG_MODAL)) {
- khm_int32 rv;
- alerter_wnd_data * wdata;
-
- khui_alert_unlock(a);
-
- /* if there are any alerter windows displayed, check if this
- alert can be consolidated with any of them. If so, we
- should consolidate it. Otherwise, just enqueue it. */
- for(wdata = khui_alert_windows;
- wdata;
- wdata = LNEXT(wdata)) {
- if (alert_check_consolidate_window(wdata, a)) {
-
- add_alert_to_wnd_data(wdata, a);
- estimate_alerter_wnd_sizes(wdata);
- setup_alerter_window_controls(wdata);
-
- return KHM_ERROR_SUCCESS;
-
- }
- }
-
- rv = alert_enqueue(a);
-
- if (KHM_SUCCEEDED(rv))
- return KHM_ERROR_HELD;
- else
- return rv;
- }
-
- if((a->flags & KHUI_ALERT_FLAG_DISPLAY_WINDOW) ||
- ((a->flags & KHUI_ALERT_FLAG_DISPLAY_BALLOON) &&
- !(a->flags & KHUI_ALERT_FLAG_REQUEST_WINDOW))) {
-
- /* The alert has already been displayed. */
-
- show_normal = FALSE;
- show_mini = FALSE;
-
- } else {
-
- if(a->err_context != NULL ||
- a->err_event != NULL) {
- a->flags |= KHUI_ALERT_FLAG_VALID_ERROR;
- }
-
- /* depending on the state of the main window, we
- need to either show a window or a balloon */
- if ((a->flags & KHUI_ALERT_FLAG_MODAL) ||
- (khm_is_main_window_active() &&
- !(a->flags & KHUI_ALERT_FLAG_REQUEST_BALLOON)) ||
- (a->flags & KHUI_ALERT_FLAG_REQUEST_WINDOW)) {
-
- show_normal = TRUE;
-
- } else {
-
- show_mini = TRUE;
-
- }
- }
-
- khui_alert_unlock(a);
-
- if (show_normal)
- return alert_show_normal(a);
- else if (show_mini)
- return alert_show_minimized(a);
- else
- return KHM_ERROR_SUCCESS;
-}
-
-static void
-show_queued_alerts(void) {
-
- if (!ALERT_DISPLAYED()) {
-
- /* show next consolidated batch */
- alert_list alist;
- int n;
-
- alert_list_init(&alist);
- n = alert_consolidate(&alist, NULL, TRUE);
-
- if (n) {
- if (n == 1) {
- khui_alert_lock(alist.alerts[0]);
-
- if (alist.alerts[0]->title) {
- alert_list_set_title(&alist, alist.alerts[0]->title);
- } else {
- wchar_t title[KHUI_MAXCCH_TITLE];
- LoadString(khm_hInstance, IDS_ALERT_DEFAULT,
- title, ARRAYLENGTH(title));
- alert_list_set_title(&alist, title);
- }
-
- khui_alert_unlock(alist.alerts[0]);
- } else {
- wchar_t title[KHUI_MAXCCH_TITLE];
- LoadString(khm_hInstance, IDS_ALERT_DEFAULT,
- title, ARRAYLENGTH(title));
- alert_list_set_title(&alist, title);
- }
-
- alert_show_list(&alist);
- }
-
- alert_list_destroy(&alist);
-
- if (n == 0) {
- khui_alert * a;
-
- /* no alerts were shown above. This maybe because none of
- the alerts were consolidatable or they were requested
- to be shown in a balloon. In this case, we just take
- the first alert from the queue and show it manually. */
-
- a = alert_queue_get_alert();
- if (a) {
- alert_show(a);
- khui_alert_release(a);
- }
- }
-
- check_for_queued_alerts();
- }
-}
-
-
-static void
-check_for_queued_alerts(void) {
- if (!is_alert_queue_empty()) {
- khui_alert * a;
-
- a = alert_queue_peek();
-
- khui_alert_lock(a);
-
- if (a->title) {
- HICON hi;
- int res;
-
- if (a->severity == KHERR_ERROR)
- res = OIC_ERROR;
- else if (a->severity == KHERR_WARNING)
- res = OIC_WARNING;
- else
- res = OIC_INFORMATION;
-
- hi = LoadImage(0, MAKEINTRESOURCE(res),
- IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON),
- LR_SHARED);
-
- khm_statusbar_set_part(KHUI_SBPART_NOTICE,
- hi,
- a->title);
- } else {
- khm_statusbar_set_part(KHUI_SBPART_NOTICE,
- NULL, NULL);
-#ifdef DEBUG
- DebugBreak();
-#endif
- }
-
- khui_alert_unlock(a);
- khui_alert_release(a);
-
- } else {
- khm_statusbar_set_part(KHUI_SBPART_NOTICE,
- NULL, NULL);
- }
-}
-
-static khm_int32
-alert_enqueue(khui_alert * a) {
- if (is_alert_queue_full())
- return KHM_ERROR_NO_RESOURCES;
-
- alert_queue_put_alert(a);
- check_for_queued_alerts();
-
- return KHM_ERROR_SUCCESS;
-}
-
-/* the alerter window is actually a dialog */
-static LRESULT CALLBACK
-alerter_wnd_proc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam)
-{
- switch(uMsg) {
- case WM_CREATE:
- {
- LPCREATESTRUCT lpcs;
- alert_list * alist;
- alerter_wnd_data * d;
-
- lpcs = (LPCREATESTRUCT) lParam;
- alist = (alert_list *) lpcs->lpCreateParams;
-
- d = create_alerter_wnd_data(hwnd, alist);
-
-#pragma warning(push)
-#pragma warning(disable: 4244)
- SetWindowLongPtr(hwnd, NTF_PARAM, (LONG_PTR) d);
-#pragma warning(pop)
-
- khm_add_dialog(hwnd);
- khm_enter_modal(hwnd);
-
- estimate_alerter_wnd_sizes(d);
- setup_alerter_window_controls(d);
-
- if (d->hw_close) {
- SetFocus(d->hw_close);
- }
-
- return TRUE;
- }
- break; /* not reached */
-
- case WM_DESTROY:
- {
- alerter_wnd_data * d;
-
- /* khm_leave_modal() could be here, but instead it is in
- the WM_COMMAND handler. This is because the modal loop
- has to be exited before DestroyWindow() is issued. */
- //khm_leave_modal();
- khm_del_dialog(hwnd);
-
- d = (alerter_wnd_data *)(LONG_PTR)
- GetWindowLongPtr(hwnd, NTF_PARAM);
-
- destroy_alerter_wnd_data(d);
-
- return TRUE;
- }
- break;
-
- case WM_COMMAND:
- {
- alerter_wnd_data * d;
-
- d = (alerter_wnd_data *)(LONG_PTR)
- GetWindowLongPtr(hwnd, NTF_PARAM);
-
- if(HIWORD(wParam) == BN_CLICKED) {
- if (LOWORD(wParam) == IDC_NTF_CLOSE ||
- LOWORD(wParam) == KHUI_PACTION_NEXT) {
-
- khm_leave_modal();
-
- DestroyWindow(hwnd);
-
- return 0;
- }
- }
- }
- break;
-
- case WM_CLOSE:
- {
- khm_leave_modal();
-
- DestroyWindow(hwnd);
-
- return 0;
- }
- }
-
- /* Since this is a custom built dialog, we use DefDlgProc instead
- of DefWindowProc. */
- return DefDlgProc(hwnd, uMsg, wParam, lParam);
-}
-
-static LRESULT CALLBACK
-alert_bin_wnd_proc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam)
-{
- BOOL in_printclient = FALSE;
-
- switch(uMsg) {
- case WM_CREATE:
- {
- LPCREATESTRUCT lpcs;
- alerter_wnd_data * d;
-
- lpcs = (LPCREATESTRUCT) lParam;
- d = (alerter_wnd_data *) lpcs->lpCreateParams;
-
-#pragma warning(push)
-#pragma warning(disable: 4244)
- SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) d);
-#pragma warning(pop)
- }
- return 0;
-
- case WM_ERASEBKGND:
- /* we erase the background when we are drawing the alerts
- anyway. */
- return 0;
-
- case WM_PRINTCLIENT:
- in_printclient = TRUE;
- /* fallthrough */
- case WM_PAINT:
- {
- HDC hdc;
- PAINTSTRUCT ps;
- RECT r;
- HFONT hf_old;
- int y;
- alerter_wnd_data * d;
- alerter_alert_data * adata;
- size_t len;
- int idx;
-
- d = (alerter_wnd_data *) (LONG_PTR) GetWindowLongPtr(hwnd, GWLP_USERDATA);
-#ifdef DEBUG
- assert(d);
-#endif
-
- if (in_printclient) {
- hdc = (HDC) wParam;
- } else {
- hdc = BeginPaint(hwnd, &ps);
- }
-
-#ifdef DEBUG
- assert(hdc);
- assert(d->hfont);
-#endif
-
-#ifdef ALERT_STATIC_BACKGROUND
- if (in_printclient || ps.fErase) {
- HBRUSH hb_background;
-
- hb_background = GetSysColorBrush(COLOR_BTNFACE);
-
- GetClientRect(hwnd, &r);
- FillRect(hdc, &r, hb_background);
- }
-#endif
-
- SetBkMode(hdc, TRANSPARENT);
-
- hf_old = SelectFont(hdc, d->hfont);
-
- y = -d->scroll_top;
- idx = 0;
- /* go through the alerts and display them */
- adata = QTOP(d);
- while(adata) {
- khui_alert * a;
-
-#ifndef ALERT_STATIC_BACKGROUND
-#define MIX_C(v1, v2, p) (((int)v1) * p + (((int) v2) * (256 - p)))
-#define ALPHA 50
- if (in_printclient || ps.fErase) {
- TRIVERTEX v[2];
- GRADIENT_RECT gr;
- COLORREF clr;
- COLORREF clr2;
-
- CopyRect(&r, &adata->r_alert);
- OffsetRect(&r, 0, y);
-
- v[0].x = r.left;
- v[0].y = r.top;
- v[0].Alpha = 0;
-
- v[1].x = r.right;
- v[1].y = r.bottom;
- v[1].Alpha = 0;
-
- if (idx == d->c_alert) {
- clr = GetSysColor(COLOR_HOTLIGHT);
-
- clr2 = GetSysColor(COLOR_BTNHIGHLIGHT);
- v[0].Red = MIX_C(GetRValue(clr), GetRValue(clr2), ALPHA);
- v[0].Green = MIX_C(GetGValue(clr), GetGValue(clr2), ALPHA);
- v[0].Blue = MIX_C(GetBValue(clr), GetBValue(clr2), ALPHA);
-
- clr2 = GetSysColor(COLOR_BTNFACE);
- v[1].Red = MIX_C(GetRValue(clr), GetRValue(clr2), ALPHA);
- v[1].Green = MIX_C(GetGValue(clr), GetGValue(clr2), ALPHA);
- v[1].Blue = MIX_C(GetBValue(clr), GetBValue(clr2), ALPHA);
- } else {
- clr = GetSysColor(COLOR_BTNHIGHLIGHT);
- v[0].Red = ((int)GetRValue(clr)) << 8;
- v[0].Green = ((int)GetGValue(clr)) << 8;
- v[0].Blue = ((int)GetBValue(clr)) << 8;
-
- clr = GetSysColor(COLOR_BTNFACE);
- v[1].Red = ((int)GetRValue(clr)) << 8;
- v[1].Green = ((int)GetGValue(clr)) << 8;
- v[1].Blue = ((int)GetBValue(clr)) << 8;
- }
-
- gr.UpperLeft = 0;
- gr.LowerRight = 1;
- GradientFill(hdc, v, 2, &gr, 1, GRADIENT_FILL_RECT_V);
- }
-#undef ALPHA
-#undef MIX_C
-#endif
-
- a = adata->alert;
-#ifdef DEBUG
- assert(a != NULL);
-#endif
- khui_alert_lock(a);
-
- if (!IsRectEmpty(&adata->r_title)) {
-
- CopyRect(&r, &adata->r_title);
- OffsetRect(&r, 0, y);
-
- StringCchLength(a->title, KHUI_MAXCCH_TITLE, &len);
-
- DrawEdge(hdc, &r, EDGE_RAISED, BF_RECT | BF_MIDDLE);
-
- InflateRect(&r, -d->s_pad.cx, -d->s_pad.cy);
-
- DrawText(hdc, a->title, (int) len, &r,
- DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS);
- }
-
- {
- HICON hicon;
- int iid;
-
- CopyRect(&r, &adata->r_icon);
- OffsetRect(&r, 0, y);
-
- if(a->severity == KHERR_ERROR)
- iid = OIC_HAND;
- else if(a->severity == KHERR_WARNING)
- iid = OIC_BANG;
- else
- iid = OIC_NOTE;
-
- hicon = (HICON) LoadImage(NULL,
- MAKEINTRESOURCE(iid),
- IMAGE_ICON,
- GetSystemMetrics(SM_CXICON),
- GetSystemMetrics(SM_CYICON),
- LR_SHARED);
-
- DrawIcon(hdc, r.left, r.top, hicon);
- }
-
- if (a->message) {
-
- CopyRect(&r, &adata->r_message);
- OffsetRect(&r, 0, y);
-
- StringCchLength(a->message, KHUI_MAXCCH_MESSAGE, &len);
-
- DrawText(hdc, a->message, (int) len, &r,
- DT_WORDBREAK);
- }
-
- if (a->suggestion) {
- HICON hicon;
- SIZE sz;
-
- CopyRect(&r, &adata->r_suggestion);
- OffsetRect(&r, 0, y);
-
- DrawEdge(hdc, &r, EDGE_SUNKEN, BF_RECT | BF_MIDDLE);
-
- InflateRect(&r, -d->s_pad.cx, -d->s_pad.cy);
-
- sz.cx = GetSystemMetrics(SM_CXSMICON);
- sz.cy = GetSystemMetrics(SM_CYSMICON);
-
- hicon = (HICON) LoadImage(NULL,
- MAKEINTRESOURCE(OIC_NOTE),
- IMAGE_ICON,
- sz.cx,
- sz.cy,
- LR_SHARED);
-
- DrawIconEx(hdc, r.left, r.top, hicon, sz.cx, sz.cy, 0, NULL,
- DI_NORMAL);
-
- r.left += d->s_pad.cx + GetSystemMetrics(SM_CXSMICON);
-
- StringCchLength(a->suggestion, KHUI_MAXCCH_SUGGESTION, &len);
-
- DrawText(hdc, a->suggestion, (int) len, &r,
- DT_WORDBREAK);
- }
- khui_alert_unlock(a);
-
- y += adata->r_alert.bottom;
- idx++;
-
- adata = QNEXT(adata);
- }
-
- SelectFont(hdc, hf_old);
-
- if (!in_printclient) {
- EndPaint(hwnd, &ps);
- }
- }
- return 0;
-
- case WM_VSCROLL:
- {
- alerter_wnd_data * d;
- int new_pos = 0;
- SCROLLINFO si;
-
- d = (alerter_wnd_data *) (LONG_PTR) GetWindowLongPtr(hwnd, GWLP_USERDATA);
-#ifdef DEBUG
- assert(d);
-#endif
- if (d == NULL)
- break; /* we can't handle the message */
-
- ZeroMemory(&si, sizeof(si));
-
- switch(LOWORD(wParam)) {
- case SB_BOTTOM:
- new_pos = d->s_alerts.cy - d->cy_max_wnd;
- break;
-
- case SB_LINEDOWN:
- new_pos = d->scroll_top + SCROLL_LINE_SIZE(d);
- break;
-
- case SB_LINEUP:
- new_pos = d->scroll_top - SCROLL_LINE_SIZE(d);
- break;
-
- case SB_PAGEDOWN:
- new_pos = d->scroll_top + d->cy_max_wnd;
- break;
-
- case SB_PAGEUP:
- new_pos = d->scroll_top - d->cy_max_wnd;
- break;
-
- case SB_THUMBPOSITION:
- case SB_THUMBTRACK:
- si.fMask = SIF_TRACKPOS;
- GetScrollInfo(hwnd, SB_VERT, &si);
- new_pos = si.nTrackPos;
- break;
-
- case SB_TOP:
- new_pos = 0;
- break;
-
- case SB_ENDSCROLL:
- si.fMask = SIF_POS;
- si.nPos = d->scroll_top;
- SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
- return 0;
-
- default:
- return 0;
- }
-
- scroll_to_position(d, new_pos, FALSE);
- }
- return 0;
-
- case WM_COMMAND:
- {
- alerter_wnd_data * d;
-
- d = (alerter_wnd_data *) (LONG_PTR) GetWindowLongPtr(hwnd, GWLP_USERDATA);
-#ifdef DEBUG
- assert(d);
-#endif
- if (d == NULL)
- break;
-
- if (HIWORD(wParam) == BN_CLICKED) {
- process_command_button(d, LOWORD(wParam));
- return 0;
- } else if (HIWORD(wParam) == BN_SETFOCUS) {
- ensure_command_is_visible(d, LOWORD(wParam));
- return 0;
- }
- }
- break;
-
- case WM_LBUTTONUP:
- {
- alerter_wnd_data * d;
- int x,y;
-
- d = (alerter_wnd_data *) (LONG_PTR) GetWindowLongPtr(hwnd, GWLP_USERDATA);
-#ifdef DEBUG
- assert(d);
-#endif
- if (d == NULL)
- break;
-
- x = GET_X_LPARAM(lParam);
- y = GET_Y_LPARAM(lParam);
-
- handle_mouse_select(d, x, y);
- }
- break;
-
- case WM_SIZE:
- {
- InvalidateRect(hwnd, NULL, TRUE);
- }
- break;
-
- case WM_DESTROY:
- {
- /* nothing needs to be done here */
- }
- return 0;
- }
-
- return DefWindowProc(hwnd, uMsg, wParam, lParam);
-}
-
-ATOM khm_register_alerter_wnd_class(void)
-{
- WNDCLASSEX wcx;
-
- ZeroMemory(&wcx, sizeof(wcx));
-
- wcx.cbSize = sizeof(wcx);
- wcx.style =
- CS_OWNDC |
-#if(_WIN32_WINNT >= 0x0501)
- ((IS_COMMCTL6())? CS_DROPSHADOW: 0) |
-#endif
- 0;
- wcx.lpfnWndProc = alerter_wnd_proc;
- wcx.cbClsExtra = 0;
- wcx.cbWndExtra = DLGWINDOWEXTRA + sizeof(LONG_PTR);
- wcx.hInstance = khm_hInstance;
- wcx.hIcon = LoadIcon(khm_hInstance, MAKEINTRESOURCE(IDI_MAIN_APP));
- wcx.hCursor = LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW));
- wcx.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
- wcx.lpszMenuName = NULL;
- wcx.lpszClassName = KHUI_ALERTER_CLASS;
- wcx.hIconSm = NULL;
-
- atom_alerter = RegisterClassEx(&wcx);
-
- return atom_alerter;
-}
-
-ATOM khm_register_alert_bin_wnd_class(void)
-{
- WNDCLASSEX wcx;
-
- ZeroMemory(&wcx, sizeof(wcx));
-
- wcx.cbSize = sizeof(wcx);
- wcx.style = CS_OWNDC;
-
- wcx.lpfnWndProc = alert_bin_wnd_proc;
- wcx.cbClsExtra = 0;
- wcx.cbWndExtra = sizeof(LONG_PTR);
- wcx.hInstance = khm_hInstance;
- wcx.hIcon = NULL;
- wcx.hCursor = LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW));
- wcx.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
- wcx.lpszMenuName = NULL;
- wcx.lpszClassName = KHUI_ALERTBIN_CLASS;
- wcx.hIconSm = NULL;
-
- atom_alert_bin = RegisterClassEx(&wcx);
-
- return atom_alert_bin;
-}
-
-/**********************************************************************
- Notification Icon
-***********************************************************************/
-
-#define KHUI_NOTIFY_ICON_ID 0
-
-void khm_notify_icon_add(void) {
- NOTIFYICONDATA ni;
- wchar_t buf[256];
-
- ZeroMemory(&ni, sizeof(ni));
-
- ni.cbSize = sizeof(ni);
- ni.hWnd = hwnd_notifier;
- ni.uID = KHUI_NOTIFY_ICON_ID;
- ni.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
- ni.hIcon = LoadIcon(khm_hInstance, MAKEINTRESOURCE(iid_normal));
- ni.uCallbackMessage = KHUI_WM_NOTIFIER;
- LoadString(khm_hInstance, IDS_NOTIFY_PREFIX, buf, ARRAYLENGTH(buf));
- StringCbCopy(ni.szTip, sizeof(ni.szTip), buf);
- LoadString(khm_hInstance, IDS_NOTIFY_READY, buf, ARRAYLENGTH(buf));
- StringCbCat(ni.szTip, sizeof(ni.szTip), buf);
-
- Shell_NotifyIcon(NIM_ADD, &ni);
-
- DestroyIcon(ni.hIcon);
-
- ni.cbSize = sizeof(ni);
- ni.uVersion = NOTIFYICON_VERSION;
- Shell_NotifyIcon(NIM_SETVERSION, &ni);
-}
-
-void
-khm_notify_icon_balloon(khm_int32 severity,
- wchar_t * title,
- wchar_t * msg,
- khm_int32 timeout) {
- NOTIFYICONDATA ni;
- int iid;
-
- if (!msg || !title)
- return;
-
- ZeroMemory(&ni, sizeof(ni));
- ni.cbSize = sizeof(ni);
-
- if (severity == KHERR_INFO) {
- ni.dwInfoFlags = NIIF_INFO;
- iid = IDI_NOTIFY_INFO;
- } else if (severity == KHERR_WARNING) {
- ni.dwInfoFlags = NIIF_WARNING;
- iid = IDI_NOTIFY_WARN;
- } else if (severity == KHERR_ERROR) {
- ni.dwInfoFlags = NIIF_ERROR;
- iid = IDI_NOTIFY_ERROR;
- } else {
- ni.dwInfoFlags = NIIF_NONE;
- iid = iid_normal;
- }
-
- ni.hWnd = hwnd_notifier;
- ni.uID = KHUI_NOTIFY_ICON_ID;
- ni.uFlags = NIF_INFO | NIF_ICON;
- ni.hIcon = LoadIcon(khm_hInstance, MAKEINTRESOURCE(iid));
-
- if (FAILED(StringCbCopy(ni.szInfo, sizeof(ni.szInfo), msg))) {
- /* too long? */
- StringCchCopyN(ni.szInfo, ARRAYLENGTH(ni.szInfo),
- msg,
- ARRAYLENGTH(ni.szInfo) - ARRAYLENGTH(ELLIPSIS));
- StringCchCat(ni.szInfo, ARRAYLENGTH(ni.szInfo),
- ELLIPSIS);
- }
-
- if (FAILED(StringCbCopy(ni.szInfoTitle, sizeof(ni.szInfoTitle),
- title))) {
- StringCchCopyN(ni.szInfoTitle, ARRAYLENGTH(ni.szInfoTitle),
- title,
- ARRAYLENGTH(ni.szInfoTitle) - ARRAYLENGTH(ELLIPSIS));
- StringCchCat(ni.szInfoTitle, ARRAYLENGTH(ni.szInfoTitle),
- ELLIPSIS);
- }
-
- ni.uTimeout = timeout;
-
- Shell_NotifyIcon(NIM_MODIFY, &ni);
-
- DestroyIcon(ni.hIcon);
-}
-
-void khm_notify_icon_expstate(enum khm_notif_expstate expseverity) {
- int new_iid;
-
- if (expseverity == KHM_NOTIF_OK)
- new_iid = IDI_APPICON_OK;
- else if (expseverity == KHM_NOTIF_WARN)
- new_iid = IDI_APPICON_WARN;
- else if (expseverity == KHM_NOTIF_EXP)
- new_iid = IDI_APPICON_EXP;
- else
- new_iid = IDI_NOTIFY_NONE;
-
- if (iid_normal == new_iid)
- return;
-
- iid_normal = new_iid;
-
- if (balloon_alert == NULL)
- khm_notify_icon_change(KHERR_NONE);
-}
-
-void khm_notify_icon_change(khm_int32 severity) {
- NOTIFYICONDATA ni;
- wchar_t buf[256];
- int iid;
-
- if (severity == KHERR_INFO)
- iid = IDI_NOTIFY_INFO;
- else if (severity == KHERR_WARNING)
- iid = IDI_NOTIFY_WARN;
- else if (severity == KHERR_ERROR)
- iid = IDI_NOTIFY_ERROR;
- else
- iid = iid_normal;
-
- ZeroMemory(&ni, sizeof(ni));
-
- ni.cbSize = sizeof(ni);
- ni.hWnd = hwnd_notifier;
- ni.uID = KHUI_NOTIFY_ICON_ID;
- ni.uFlags = NIF_ICON | NIF_TIP;
- ni.hIcon = LoadIcon(khm_hInstance, MAKEINTRESOURCE(iid));
- LoadString(khm_hInstance, IDS_NOTIFY_PREFIX, buf, ARRAYLENGTH(buf));
- StringCbCopy(ni.szTip, sizeof(ni.szTip), buf);
- if(severity == KHERR_NONE)
- LoadString(khm_hInstance, IDS_NOTIFY_READY, buf, ARRAYLENGTH(buf));
- else
- LoadString(khm_hInstance, IDS_NOTIFY_ATTENTION, buf, ARRAYLENGTH(buf));
- StringCbCat(ni.szTip, sizeof(ni.szTip), buf);
-
- Shell_NotifyIcon(NIM_MODIFY, &ni);
-
- DestroyIcon(ni.hIcon);
-}
-
-void khm_notify_icon_remove(void) {
- NOTIFYICONDATA ni;
-
- ZeroMemory(&ni, sizeof(ni));
-
- ni.cbSize = sizeof(ni);
- ni.hWnd = hwnd_notifier;
- ni.uID = KHUI_NOTIFY_ICON_ID;
-
- Shell_NotifyIcon(NIM_DELETE, &ni);
-}
-
-static khm_int32
-get_default_notifier_action(void) {
- khm_int32 def_cmd = KHUI_ACTION_OPEN_APP;
- khm_handle csp_cw = NULL;
- khm_size i;
-
- if (KHM_FAILED(khc_open_space(NULL, L"CredWindow", KHM_PERM_READ,
- &csp_cw)))
- def_cmd;
-
- khc_read_int32(csp_cw, L"NotificationAction", &def_cmd);
-
- khc_close_space(csp_cw);
-
- for (i=0; i < n_khm_notifier_actions; i++) {
- if (khm_notifier_actions[i] == def_cmd)
- break;
- }
-
- if (i < n_khm_notifier_actions)
- return def_cmd;
- else
- return KHUI_ACTION_OPEN_APP;
-}
-
-void khm_notify_icon_activate(void) {
- /* if there are any notifications waiting to be shown and there
- are no alerts already being shown, we show them. Otherwise we
- execute the default action. */
-
- khm_notify_icon_change(KHERR_NONE);
-
- if (balloon_alert != NULL && khui_alert_windows == NULL) {
-
- khui_alert * a;
- khm_boolean alert_done = FALSE;
-
- a = balloon_alert;
- balloon_alert = NULL;
-
- khui_alert_lock(a);
-
- a->displayed = FALSE;
-
- if ((a->flags & KHUI_ALERT_FLAG_DEFACTION) &&
- (a->n_alert_commands > 0)) {
-
- PostMessage(khm_hwnd_main, WM_COMMAND,
- MAKEWPARAM(a->alert_commands[0],
- 0),
- 0);
- alert_done = TRUE;
-
- } else if (a->flags & KHUI_ALERT_FLAG_REQUEST_WINDOW) {
-
- alert_show_normal(a);
- alert_done = TRUE;
-
- }
- khui_alert_unlock(a);
- khui_alert_release(a);
-
- if (alert_done)
- return;
- }
-
- if (!is_alert_queue_empty() && !ALERT_DISPLAYED()) {
-
- khm_show_main_window();
- show_queued_alerts();
-
- return;
- }
-
-
- /* if none of the above applied, then we perform the default
- action for the notification icon. */
- {
- khm_int32 cmd = 0;
-
- cmd = get_default_notifier_action();
-
- if (cmd == KHUI_ACTION_OPEN_APP) {
- if (khm_is_main_window_visible()) {
- khm_hide_main_window();
- } else {
- khm_show_main_window();
- }
- } else {
- khui_action_trigger(cmd, NULL);
- }
-
- check_for_queued_alerts();
- }
-}
-
-/*********************************************************************
- Initialization
-**********************************************************************/
-
-void khm_init_notifier(void)
-{
- if(!khm_register_notifier_wnd_class())
- return;
-
- if(!khm_register_alerter_wnd_class())
- return;
-
- if(!khm_register_alert_bin_wnd_class())
- return;
-
- hwnd_notifier = CreateWindowEx(0,
- MAKEINTATOM(atom_notifier),
- KHUI_NOTIFIER_WINDOW,
- 0,
- 0,0,0,0,
- HWND_MESSAGE,
- NULL,
- khm_hInstance,
- NULL);
-
- if(hwnd_notifier != NULL) {
- kmq_subscribe_hwnd(KMSG_ALERT, hwnd_notifier);
- kmq_subscribe_hwnd(KMSG_CRED, hwnd_notifier);
- notifier_ready = TRUE;
-
- khm_notify_icon_add();
- } else {
-#ifdef DEBUG
- assert(hwnd_notifier != NULL);
-#endif
- }
- khm_timer_init();
-
- khm_addr_change_notifier_init();
-}
-
-void khm_exit_notifier(void)
-{
- khm_addr_change_notifier_exit();
-
- khm_timer_exit();
-
- if(hwnd_notifier != NULL) {
- khm_notify_icon_remove();
- kmq_unsubscribe_hwnd(KMSG_ALERT, hwnd_notifier);
- kmq_unsubscribe_hwnd(KMSG_CRED, hwnd_notifier);
- DestroyWindow(hwnd_notifier);
- hwnd_notifier = NULL;
- }
-
- if(atom_notifier != 0) {
- UnregisterClass(MAKEINTATOM(atom_notifier), khm_hInstance);
- atom_notifier = 0;
- }
-
- if(atom_alerter != 0) {
- UnregisterClass(MAKEINTATOM(atom_alerter), khm_hInstance);
- atom_alerter = 0;
- }
-
- if(atom_alert_bin != 0) {
- UnregisterClass(MAKEINTATOM(atom_alert_bin), khm_hInstance);
- atom_alert_bin = 0;
- }
-
- notifier_ready = FALSE;
-}
-
-/***** testing *****/
-
-void
-create_test_alerts(void) {
-
- khui_alert * a;
- int i;
-
- for (i=0; i < 50; i++) {
- wchar_t buf[128];
-
- StringCbPrintf(buf, sizeof(buf), L"Foo bar baz. This is alert number %d", i);
- khui_alert_create_simple(L"Title", buf, KHERR_INFO, &a);
- khui_alert_set_type(a, KHUI_ALERTTYPE_PLUGIN);
- khui_alert_set_suggestion(a, L"This is a suggestion. It is kinda long to see if the word wrapping actually works as we expect it to. Just in case, here's a line feed.\n\nDoes this show up on a different line? Cool!");
-
- khui_alert_add_command(a, KHUI_ACTION_NEW_CRED);
- khui_alert_add_command(a, KHUI_ACTION_CLOSE_APP);
- khui_alert_add_command(a, KHUI_ACTION_PROPERTIES);
- khui_alert_add_command(a, KHUI_ACTION_OPEN_APP);
- khui_alert_add_command(a, KHUI_ACTION_VIEW_REFRESH);
-
- khui_alert_show(a);
- khui_alert_release(a);
- }
-}
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#define OEMRESOURCE
+
+#include<khmapp.h>
+#include<assert.h>
+
+#define KHUI_NOTIFIER_CLASS L"KhuiNotifierMsgWindowClass"
+#define KHUI_ALERTER_CLASS L"KhuiAlerterWindowClass"
+#define KHUI_ALERTBIN_CLASS L"KhuiAlertBinWindowClass"
+
+#define KHUI_NOTIFIER_WINDOW L"KhuiNotifierMsgWindow"
+
+
+/* The commands that are available as default actions when the user
+ clicks the notification icon. */
+
+khm_int32 khm_notifier_actions[] = {
+ KHUI_ACTION_OPEN_APP,
+ KHUI_ACTION_NEW_CRED
+};
+
+khm_size n_khm_notifier_actions = ARRAYLENGTH(khm_notifier_actions);
+
+/* notifier message for notification icon */
+#define KHUI_WM_NOTIFIER WM_COMMAND
+
+#define DRAWTEXTOPTIONS (DT_CALCRECT | DT_NOPREFIX | DT_WORDBREAK)
+
+/* are we showing an alert? */
+#define ALERT_DISPLAYED() (balloon_alert != NULL || khui_alert_windows != NULL)
+
+/* Forward declarations */
+
+struct tag_alerter_wnd_data;
+typedef struct tag_alerter_wnd_data alerter_wnd_data;
+
+struct tag_alert_list;
+typedef struct tag_alert_list alert_list;
+
+static khm_int32
+alert_show(khui_alert * a);
+
+static khm_int32
+alert_show_minimized(khui_alert * a);
+
+static khm_int32
+alert_show_normal(khui_alert * a);
+
+static khm_int32
+alert_show_list(alert_list * alist);
+
+static khm_int32
+alert_enqueue(khui_alert * a);
+
+static khm_boolean
+alert_is_equal(khui_alert * a1, khui_alert * a2);
+
+static void
+check_for_queued_alerts(void);
+
+static void
+show_queued_alerts(void);
+
+static khm_int32
+alert_consolidate(alert_list * alist,
+ khui_alert * alert,
+ khm_boolean add_from_queue);
+
+static khm_int32
+get_default_notifier_action(void);
+
+/* Globals */
+
+/* window class registration atom for message only notifier window
+ class */
+ATOM atom_notifier = 0;
+
+/* window class registration atom for alert windows */
+ATOM atom_alerter = 0;
+/* window class registration atom for the alert "bin", which is the
+ window that holds all the alerts. */
+ATOM atom_alert_bin = 0;
+
+/* notifier message window */
+HWND hwnd_notifier = NULL;
+
+BOOL notifier_ready = FALSE;
+
+/* The list of alert windows currently active */
+alerter_wnd_data * khui_alert_windows = NULL;
+
+/* Notification icon for when there are no alerts to be displayed */
+int iid_normal = IDI_NOTIFY_NONE;
+
+/* The alert currently being displayed in a balloon */
+khui_alert * balloon_alert = NULL;
+
+/**********************************************************************
+ Alert Queue
+
+ The alert queue is the data structure that keeps track of all the
+ alerts that are waiting to be displayed. Alerts will be placed on
+ the queue if they cannot be immediately displayed for some reason
+ (e.g. another alert is being displayed, or the user is working in
+ another window).
+***********************************************************************/
+
+#define KHUI_ALERT_QUEUE_MAX 64
+
+khui_alert * alert_queue[KHUI_ALERT_QUEUE_MAX];
+khm_int32 alert_queue_head = 0;
+khm_int32 alert_queue_tail = 0;
+
+#define is_alert_queue_empty() (alert_queue_head == alert_queue_tail)
+#define is_alert_queue_full() (((alert_queue_tail + 1) % KHUI_ALERT_QUEUE_MAX) == alert_queue_head)
+
+/* NOTE: the alert queue functions are unsafe to call from any thread
+ other than the UI thread. */
+
+static void
+alert_queue_put_alert(khui_alert * a) {
+ if (is_alert_queue_full()) return;
+ alert_queue[alert_queue_tail++] = a;
+ khui_alert_hold(a);
+ alert_queue_tail %= KHUI_ALERT_QUEUE_MAX;
+}
+
+/* the caller needs to release the alert that's returned */
+static khui_alert *
+alert_queue_get_alert(void) {
+ khui_alert * a;
+
+ if (is_alert_queue_empty()) return NULL;
+ a = alert_queue[alert_queue_head++];
+ alert_queue_head %= KHUI_ALERT_QUEUE_MAX;
+
+ return a; /* held */
+}
+
+static int
+alert_queue_get_size(void) {
+ if (is_alert_queue_empty())
+ return 0;
+
+ if (alert_queue_tail < alert_queue_head) {
+ return (alert_queue_tail + KHUI_ALERT_QUEUE_MAX - alert_queue_head);
+ } else {
+ return alert_queue_tail - alert_queue_head;
+ }
+}
+
+static khui_alert *
+alert_queue_get_alert_by_pos(int pos) {
+ khui_alert * a;
+
+ if (is_alert_queue_empty() ||
+ pos >= alert_queue_get_size() ||
+ pos < 0) {
+ return NULL;
+ }
+
+ a = alert_queue[(alert_queue_head + pos) % KHUI_ALERT_QUEUE_MAX];
+ if (a) {
+ khui_alert_hold(a);
+ }
+ return a;
+}
+
+static int
+alert_queue_delete_alert(khui_alert * a) {
+ int idx;
+ int succ;
+
+ idx = alert_queue_head;
+ while(idx != alert_queue_tail) {
+ if (alert_queue[idx] == a)
+ break;
+
+ idx = (idx + 1) % KHUI_ALERT_QUEUE_MAX;
+ }
+
+ if (idx == alert_queue_tail)
+ return 0;
+
+#ifdef DEBUG
+ assert(alert_queue[idx]);
+#endif
+ khui_alert_release(alert_queue[idx]);
+
+ succ = (idx + 1) % KHUI_ALERT_QUEUE_MAX;
+ while(succ != alert_queue_tail) {
+ alert_queue[idx] = alert_queue[succ];
+
+ succ = (succ + 1) % KHUI_ALERT_QUEUE_MAX;
+ idx = (idx + 1) % KHUI_ALERT_QUEUE_MAX;
+ }
+
+ alert_queue_tail = idx;
+ return 1;
+}
+
+/* the caller needs to release the alert that's returned */
+static khui_alert *
+alert_queue_peek(void) {
+ khui_alert * a;
+
+ if (is_alert_queue_empty())
+ return NULL;
+
+ a = alert_queue[alert_queue_head];
+ khui_alert_hold(a);
+
+ return a;
+}
+
+/**********************************************************************
+ Alert List
+
+ A list of alerts. Currently has a fixed upper limit, but the limit
+ is high enough for now.
+***********************************************************************/
+
+typedef struct tag_alert_list {
+ khui_alert * alerts[KHUI_ALERT_QUEUE_MAX];
+ int n_alerts;
+ wchar_t title[KHUI_MAXCCH_TITLE];
+} alert_list;
+
+static void
+alert_list_init(alert_list * alist) {
+ ZeroMemory(alist, sizeof(*alist));
+}
+
+static void
+alert_list_set_title(alert_list * alist, wchar_t * title) {
+ StringCbCopy(alist->title, sizeof(alist->title), title);
+}
+
+static khm_int32
+alert_list_add_alert(alert_list * alist,
+ khui_alert * alert) {
+
+ if (alist->n_alerts == ARRAYLENGTH(alist->alerts))
+ return KHM_ERROR_NO_RESOURCES;
+
+ khui_alert_hold(alert);
+ alist->alerts[alist->n_alerts++] = alert;
+
+ return KHM_ERROR_SUCCESS;
+}
+
+static void
+alert_list_destroy(alert_list * alist) {
+ int i;
+
+ for (i=0; i < alist->n_alerts; i++) {
+ if (alist->alerts[i] != NULL) {
+ khui_alert_release(alist->alerts[i]);
+ alist->alerts[i] = NULL;
+ }
+ }
+
+ alist->n_alerts = 0;
+}
+
+
+/**********************************************************************
+ Notifier Window
+
+ The notifier window manages the notification icon and handles
+ KMSG_ALERT messages sent from the UI library. The window will exist
+ for the lifetime of the application.
+***********************************************************************/
+
+/* These are defined for APPVER >= 0x501. We are defining them here
+ so that we can build with APPVER = 0x500 and use the same binaries
+ with Win XP. */
+
+#ifndef NIN_BALLOONSHOW
+#define NIN_BALLOONSHOW (WM_USER + 2)
+#endif
+
+#ifndef NIN_BALLOONHIDE
+#define NIN_BALLOONHIDE (WM_USER + 3)
+#endif
+
+#ifndef NIN_BALLOONTIMEOUT
+#define NIN_BALLOONTIMEOUT (WM_USER + 4)
+#endif
+
+#ifndef NIN_BALLOONUSERCLICK
+#define NIN_BALLOONUSERCLICK (WM_USER + 5)
+#endif
+
+
+static LRESULT CALLBACK
+notifier_wnd_proc(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ kmq_message * m;
+ khm_int32 rv;
+
+ if(uMsg == KMQ_WM_DISPATCH) {
+ kmq_wm_begin(lParam, &m);
+ rv = KHM_ERROR_SUCCESS;
+
+ if(m->type == KMSG_ALERT) {
+ /* handle notifier messages */
+ switch(m->subtype) {
+ case KMSG_ALERT_SHOW:
+ {
+ khui_alert * a;
+
+ a = (khui_alert *) m->vparam;
+#ifdef DEBUG
+ assert(a != NULL);
+#endif
+ rv = alert_show(a);
+ khui_alert_release(a);
+ }
+ break;
+
+ case KMSG_ALERT_QUEUE:
+ {
+ khui_alert * a;
+
+ a = (khui_alert *) m->vparam;
+#ifdef DEBUG
+ assert(a != NULL);
+#endif
+ rv = alert_enqueue(a);
+ khui_alert_release(a);
+ }
+ break;
+
+ case KMSG_ALERT_CHECK_QUEUE:
+ check_for_queued_alerts();
+ break;
+
+ case KMSG_ALERT_SHOW_QUEUED:
+ show_queued_alerts();
+ break;
+
+ case KMSG_ALERT_SHOW_MODAL:
+ {
+ khui_alert * a;
+
+ a = (khui_alert *) m->vparam;
+#ifdef DEBUG
+ assert(a != NULL);
+#endif
+ khui_alert_lock(a);
+ a->flags |= KHUI_ALERT_FLAG_MODAL;
+ khui_alert_unlock(a);
+
+ rv = alert_show(a);
+
+ if (KHM_SUCCEEDED(rv)) {
+ khm_message_loop_int(&a->displayed);
+ }
+
+ khui_alert_release(a);
+ }
+ break;
+ }
+ } else if (m->type == KMSG_CRED &&
+ m->subtype == KMSG_CRED_ROOTDELTA) {
+
+ KillTimer(hwnd, KHUI_REFRESH_TIMER_ID);
+ SetTimer(hwnd, KHUI_REFRESH_TIMER_ID,
+ KHUI_REFRESH_TIMEOUT,
+ NULL);
+
+ }
+
+ return kmq_wm_end(m, rv);
+ } else if (uMsg == KHUI_WM_NOTIFIER) {
+ /* Handle events generated from the notification icon */
+
+ /* wParam is the identifier of the notify icon, but we only
+ have one. */
+ switch(lParam) {
+ case WM_CONTEXTMENU:
+ {
+ POINT pt;
+ int menu_id;
+ khui_menu_def * mdef;
+ khui_action_ref * act;
+ khm_size i, n;
+ khm_int32 def_cmd;
+
+ /* before we show the context menu, we need to make
+ sure that the default action for the notification
+ icon is present in the menu and that it is marked
+ as the default. */
+
+ def_cmd = get_default_notifier_action();
+
+ if (khm_is_main_window_visible()) {
+ menu_id = KHUI_MENU_ICO_CTX_NORMAL;
+
+ if (def_cmd == KHUI_ACTION_OPEN_APP)
+ def_cmd = KHUI_ACTION_CLOSE_APP;
+ } else {
+ menu_id = KHUI_MENU_ICO_CTX_MIN;
+ }
+
+ mdef = khui_find_menu(menu_id);
+
+#ifdef DEBUG
+ assert(mdef);
+#endif
+ n = khui_menu_get_size(mdef);
+ for (i=0; i < n; i++) {
+ act = khui_menu_get_action(mdef, i);
+ if (!(act->flags & KHUI_ACTIONREF_PACTION) &&
+ (act->action == def_cmd))
+ break;
+ }
+
+ if (i < n) {
+ if (!(act->flags & KHUI_ACTIONREF_DEFAULT)) {
+ khui_menu_remove_action(mdef, i);
+ khui_menu_insert_action(mdef, i, def_cmd, KHUI_ACTIONREF_DEFAULT);
+ } else {
+ /* we are all set */
+ }
+ } else {
+ /* the default action was not found on the context
+ menu */
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ khui_menu_insert_action(mdef, 0, def_cmd, KHUI_ACTIONREF_DEFAULT);
+ }
+
+ SetForegroundWindow(khm_hwnd_main);
+
+ GetCursorPos(&pt);
+ khm_menu_show_panel(menu_id, pt.x, pt.y);
+
+ PostMessage(khm_hwnd_main, WM_NULL, 0, 0);
+ }
+ break;
+
+ case NIN_SELECT:
+ /* fall through */
+ case NIN_KEYSELECT:
+ /* If there were any alerts waiting to be shown, we show
+ them. Otherwise we perform the default action. */
+ khm_notify_icon_activate();
+ break;
+
+ case NIN_BALLOONUSERCLICK:
+ if (balloon_alert) {
+ khui_alert * a;
+
+ khm_notify_icon_change(KHERR_NONE);
+
+ a = balloon_alert;
+ balloon_alert = NULL;
+
+ khui_alert_lock(a);
+ a->displayed = FALSE;
+
+ if ((a->flags & KHUI_ALERT_FLAG_DEFACTION) &&
+ !(a->flags & KHUI_ALERT_FLAG_REQUEST_WINDOW) &&
+ a->n_alert_commands > 0) {
+ PostMessage(khm_hwnd_main, WM_COMMAND,
+ MAKEWPARAM(a->alert_commands[0],
+ 0),
+ 0);
+ } else if (a->flags &
+ KHUI_ALERT_FLAG_REQUEST_WINDOW) {
+ khm_show_main_window();
+ alert_show_normal(a);
+ }
+
+ khui_alert_unlock(a);
+ khui_alert_release(a);
+ } else {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ }
+ break;
+
+ case NIN_BALLOONHIDE:
+ case NIN_BALLOONTIMEOUT:
+ khm_notify_icon_change(KHERR_NONE);
+ if (balloon_alert) {
+ khui_alert * a;
+ a = balloon_alert;
+ balloon_alert = NULL;
+
+ khui_alert_lock(a);
+ a->displayed = FALSE;
+ khui_alert_unlock(a);
+
+ khui_alert_release(a);
+ }
+ break;
+ }
+ } else if (uMsg == WM_TIMER) {
+ if (wParam == KHUI_TRIGGER_TIMER_ID) {
+ KillTimer(hwnd, KHUI_TRIGGER_TIMER_ID);
+ khm_timer_fire(hwnd);
+ } else if (wParam == KHUI_REFRESH_TIMER_ID) {
+ KillTimer(hwnd, KHUI_REFRESH_TIMER_ID);
+ kcdb_identity_refresh_all();
+ khm_timer_refresh(hwnd);
+ }
+ }
+
+ return DefWindowProc(hwnd, uMsg, wParam, lParam);
+}
+
+ATOM
+khm_register_notifier_wnd_class(void)
+{
+ WNDCLASSEX wcx;
+
+ ZeroMemory(&wcx, sizeof(wcx));
+
+ wcx.cbSize = sizeof(wcx);
+ wcx.style = 0;
+ wcx.lpfnWndProc = notifier_wnd_proc;
+ wcx.cbClsExtra = 0;
+ wcx.cbWndExtra = 0;
+ wcx.hInstance = khm_hInstance;
+ wcx.hIcon = NULL;
+ wcx.hCursor = NULL;
+ wcx.hbrBackground = NULL;
+ wcx.lpszMenuName = NULL;
+ wcx.lpszClassName = KHUI_NOTIFIER_CLASS;
+ wcx.hIconSm = NULL;
+
+ atom_notifier = RegisterClassEx(&wcx);
+
+ return atom_notifier;
+}
+
+/*********************************************************************
+ Alerter
+**********************************************************************/
+
+typedef struct tag_alerter_alert_data {
+ khui_alert * alert;
+
+ BOOL seen; /* has the user seen this alert? */
+
+ BOOL has_commands; /* we cache the value here. otherwise
+ we'll have to get a lock on the
+ alert each time we have to find out
+ whether there are any commands for
+ this alert. */
+
+ RECT r_alert; /* the entire alert, relative to self. */
+
+ /* the following rects are relative to the top left of r_alert. */
+
+ RECT r_title; /* the title. deflate by padding to
+ get the text rect. */
+ RECT r_icon; /* rect for icon */
+ RECT r_message; /* rect for the text. no padding
+ necessary. */
+ RECT r_suggestion; /* rect for the suggestion. deflate
+ by padding to get the suggestion
+ rect. The suggestion rect includes
+ space for the small icon on the
+ left and padding between the icon
+ and the text. The size of the small
+ icon are as per system metrics
+ SM_C{X,Y}SMICON. Padding is
+ s_pad.cx vertical. */
+
+ int n_cmd_buttons; /* number of command buttons in this alert. */
+
+ RECT r_buttons[KHUI_MAX_ALERT_COMMANDS];
+ /* rects for the command buttons. */
+
+ HWND hwnd_buttons[KHUI_MAX_ALERT_COMMANDS];
+ /* handles for the command buttons */
+
+ HWND hwnd_marker;
+ /* handle to the marker window used as
+ a tab-stop target when there are
+ not buttons associated with the
+ alert. */
+
+ LDCL(struct tag_alerter_alert_data);
+} alerter_alert_data;
+
+typedef struct tag_alerter_wnd_data {
+ HWND hwnd;
+ HFONT hfont;
+
+ wchar_t caption[KHUI_MAXCCH_TITLE]; /* the original
+ caption for the
+ dialog. */
+
+ HWND hw_bin;
+ HWND hw_scroll;
+ HWND hw_close;
+
+ int scroll_top;
+
+ int n_cmd_buttons; /* total number of command buttons
+ in all the alerts being shown in
+ this dialog. */
+
+ int c_alert; /* current selected alert. */
+
+ /* various metrics */
+ /* calculated during WM_CREATE */
+ SIZE s_button; /* minimum dimensions for command button */
+ SIZE s_margin;
+ RECT r_text; /* only .left and .right are used. rest are 0 */
+ RECT r_title; /* only .left, .right and .bottom are used. .top=0 */
+ SIZE s_icon;
+ SIZE s_pad;
+
+ int cx_wnd;
+ int cy_max_wnd;
+
+ /* derived from the alert sizes */
+ SIZE s_alerts;
+
+ QDCL(alerter_alert_data); /* queue of alerts that are being
+ shown in this window. */
+
+ LDCL(struct tag_alerter_wnd_data); /* for adding to
+ khui_alert_windows list. */
+
+ int n_alerts;
+
+} alerter_wnd_data;
+
+#define NTF_PARAM DWLP_USER
+
+/* dialog sizes in base dialog units */
+
+#define NTF_MARGIN 5
+#define NTF_WIDTH 200
+#define NTF_MAXHEIGHT 150
+
+#define NTF_TITLE_X NTF_MARGIN
+#define NTF_TITLE_WIDTH (NTF_WIDTH - NTF_MARGIN*2)
+#define NTF_TITLE_HEIGHT 10
+
+#define NTF_TEXT_PAD 2
+
+#define NTF_BUTTON_HEIGHT 14
+
+#define NTF_TIMEOUT 20000
+
+#define ALERT_WINDOW_EX_SYLES (WS_EX_DLGMODALFRAME | WS_EX_CONTEXTHELP)
+#define ALERT_WINDOW_STYLES (WS_DLGFRAME | WS_POPUPWINDOW | WS_CLIPCHILDREN | DS_NOIDLEMSG)
+
+/* Control ids */
+#define IDC_NTF_ALERTBIN 998
+#define IDC_NTF_CLOSE 999
+
+#define IDC_NTF_CMDBUTTONS 1001
+#define IDC_FROM_IDX(alert, bn) ((alert) * (KHUI_MAX_ALERT_COMMANDS + 1) + (bn) + 1 + IDC_NTF_CMDBUTTONS)
+#define ALERT_FROM_IDC(idc) (((idc) - IDC_NTF_CMDBUTTONS) / (KHUI_MAX_ALERT_COMMANDS + 1))
+#define BUTTON_FROM_IDC(idc) (((idc) - IDC_NTF_CMDBUTTONS) % (KHUI_MAX_ALERT_COMMANDS + 1) - 1)
+
+/* if the only command in an alert is "Close", we assume that the
+ alert has no commands. */
+#define ALERT_HAS_CMDS(a) ((a)->n_alert_commands > 1 || ((a)->n_alert_commands == 1 && (a)->alert_commands[0] != KHUI_PACTION_CLOSE))
+
+#define SCROLL_LINE_SIZE(d) ((d)->cy_max_wnd / 12)
+
+static void
+add_alert_to_wnd_data(alerter_wnd_data * d,
+ khui_alert * a) {
+ alerter_alert_data * aiter;
+ khm_boolean exists = 0;
+
+ khui_alert_lock(a);
+
+ /* check if the alert is already there */
+ aiter = QTOP(d);
+ while(aiter && !exists) {
+ if (aiter->alert) {
+ khui_alert_lock(aiter->alert);
+
+ if (alert_is_equal(aiter->alert, a)) {
+ exists = TRUE;
+ }
+
+ khui_alert_unlock(aiter->alert);
+ }
+
+ aiter = QNEXT(aiter);
+ }
+
+ a->flags |= KHUI_ALERT_FLAG_DISPLAY_WINDOW;
+
+ if (!exists) {
+ a->displayed = TRUE;
+ }
+
+ khui_alert_unlock(a);
+
+ if (!exists) {
+ alerter_alert_data * adata;
+
+ adata = PMALLOC(sizeof(*adata));
+ ZeroMemory(adata, sizeof(*adata));
+
+ adata->alert = a;
+ khui_alert_hold(a);
+
+ QPUT(d, adata);
+ d->n_alerts ++;
+ }
+}
+
+static alerter_wnd_data *
+create_alerter_wnd_data(HWND hwnd, alert_list * l) {
+ alerter_wnd_data * d;
+ int i;
+ LONG dlgb;
+
+ d = PMALLOC(sizeof(*d));
+ ZeroMemory(d, sizeof(*d));
+
+ d->hwnd = hwnd;
+
+ GetWindowText(hwnd, d->caption, ARRAYLENGTH(d->caption));
+
+ for (i=0; i < l->n_alerts; i++) {
+ add_alert_to_wnd_data(d, l->alerts[i]);
+ }
+
+ d->n_alerts = l->n_alerts;
+
+ LPUSH(&khui_alert_windows, d);
+
+ /* Compute a few metrics first */
+
+ dlgb = GetDialogBaseUnits();
+
+#define DLG2SCNX(x) MulDiv((x), LOWORD(dlgb), 4)
+#define DLG2SCNY(y) MulDiv((y), HIWORD(dlgb), 8)
+
+ d->cx_wnd = DLG2SCNX(NTF_WIDTH);
+ d->cy_max_wnd = DLG2SCNY(NTF_MAXHEIGHT);
+
+ d->s_margin.cx = DLG2SCNX(NTF_MARGIN);
+ d->s_margin.cy = DLG2SCNY(NTF_MARGIN);
+
+ d->r_title.left = DLG2SCNX(NTF_TITLE_X);
+ d->r_title.right = DLG2SCNX(NTF_TITLE_X + NTF_TITLE_WIDTH);
+ d->r_title.top = 0;
+ d->r_title.bottom = DLG2SCNY(NTF_TITLE_HEIGHT);
+
+ d->s_pad.cx = DLG2SCNX(NTF_TEXT_PAD);
+ d->s_pad.cy = DLG2SCNY(NTF_TEXT_PAD);
+
+ d->s_icon.cx = GetSystemMetrics(SM_CXICON);
+ d->s_icon.cy = GetSystemMetrics(SM_CYICON);
+
+ d->r_text.left = d->s_margin.cx * 2 + d->s_icon.cx;
+ d->r_text.right = d->cx_wnd - d->s_margin.cx;
+ d->r_text.top = 0;
+ d->r_text.bottom = 0;
+
+ d->s_button.cx = ((d->r_text.right - d->r_text.left) - (KHUI_MAX_ALERT_COMMANDS - 1) * d->s_margin.cx) / KHUI_MAX_ALERT_COMMANDS;
+ d->s_button.cy = DLG2SCNY(NTF_BUTTON_HEIGHT);
+
+#undef DLG2SCNX
+#undef DLG2SCNY
+
+ d->c_alert = -1;
+
+ return d;
+}
+
+static void
+layout_alert(HDC hdc, alerter_wnd_data * d,
+ alerter_alert_data * adata) {
+ RECT r;
+ size_t len;
+ int y;
+ int icon_y;
+
+#ifdef DEBUG
+ assert(adata->alert);
+#endif
+
+ khui_alert_lock(adata->alert);
+
+ y = 0;
+
+ /* Title */
+
+ y += d->s_margin.cy;
+
+ /* If there is a title and it differs from the title of the
+ alerter window, then we have to show the alert title
+ separately. */
+ if (adata->alert->title &&
+ wcscmp(adata->alert->title, d->caption)) {
+
+ CopyRect(&adata->r_title, &d->r_title);
+ OffsetRect(&adata->r_title, 0, y);
+
+ y = adata->r_title.bottom + d->s_margin.cy;
+
+ } else {
+
+ SetRectEmpty(&adata->r_title);
+
+ }
+
+ /* Icon */
+
+ SetRect(&adata->r_icon, d->s_margin.cx, y,
+ d->s_margin.cx + d->s_icon.cx,
+ y + d->s_icon.cy);
+
+ icon_y = adata->r_icon.bottom + d->s_margin.cy; /* the bottom of the icon */
+
+ /* Message */
+
+ if (adata->alert->message &&
+ SUCCEEDED(StringCchLength(adata->alert->message,
+ KHUI_MAXCCH_MESSAGE,
+ &len))) {
+
+ CopyRect(&r, &d->r_text);
+
+ DrawTextEx(hdc, adata->alert->message, (int) len,
+ &r,
+ DRAWTEXTOPTIONS,
+ NULL);
+
+ OffsetRect(&r, 0, y);
+ CopyRect(&adata->r_message, &r);
+
+ y = r.bottom + d->s_margin.cy;
+
+ } else {
+
+ SetRectEmpty(&adata->r_message);
+
+ }
+
+ /* Suggestion */
+
+ if (adata->alert->suggestion &&
+ SUCCEEDED(StringCchLength(adata->alert->suggestion,
+ KHUI_MAXCCH_SUGGESTION,
+ &len))) {
+ int pad = d->s_pad.cx + GetSystemMetrics(SM_CXSMICON);
+
+ CopyRect(&r, &d->r_text);
+ r.left += pad;
+
+ DrawTextEx(hdc, adata->alert->suggestion, (int) len,
+ &r,
+ DRAWTEXTOPTIONS,
+ NULL);
+
+ r.left -= pad;
+
+ InflateRect(&r, d->s_pad.cx, d->s_pad.cy);
+ OffsetRect(&r, 0, -r.top + y);
+ CopyRect(&adata->r_suggestion, &r);
+
+ y = r.bottom + d->s_margin.cy;
+
+ } else {
+
+ SetRectEmpty(&adata->r_suggestion);
+
+ }
+
+ y = max(y, icon_y);
+
+ /* Buttons */
+
+ if (ALERT_HAS_CMDS(adata->alert)) {
+ khm_int32 i;
+ int x, width;
+ wchar_t caption[KHUI_MAXCCH_SHORT_DESC];
+ size_t len;
+ SIZE s;
+ int skip_close;
+
+ adata->has_commands = TRUE;
+
+ if (d->n_alerts > 1)
+ skip_close = TRUE;
+ else
+ skip_close = FALSE;
+
+ x = d->r_text.left;
+
+#ifdef DEBUG
+ assert(adata->alert->n_alert_commands <= KHUI_MAX_ALERT_COMMANDS);
+#endif
+
+ for (i=0; i < adata->alert->n_alert_commands; i++) {
+
+ if (adata->alert->alert_commands[i] == KHUI_PACTION_CLOSE && skip_close) {
+ SetRectEmpty(&adata->r_buttons[i]);
+ continue;
+ }
+
+ caption[0] = L'\0';
+ len = 0;
+ khm_get_action_caption(adata->alert->alert_commands[i],
+ caption, sizeof(caption));
+ StringCchLength(caption, ARRAYLENGTH(caption), &len);
+
+ if (!GetTextExtentPoint32(hdc, caption, (int) len, &s)) {
+ width = d->s_button.cx;
+ } else {
+ width = s.cx + d->s_margin.cx * 2;
+ }
+
+ if (width < d->s_button.cx)
+ width = d->s_button.cx;
+ else if (width > (d->r_text.right - d->r_text.left))
+ width = d->r_text.right - d->r_text.left;
+
+ if (x + width > d->r_text.right) {
+ /* new line */
+ x = d->r_text.left;
+ y += d->s_button.cy + d->s_pad.cy;
+ }
+
+ SetRect(&adata->r_buttons[i], x, y, x + width, y + d->s_button.cy);
+
+ x += width + d->s_margin.cx;
+ }
+
+ y += d->s_button.cy + d->s_margin.cy;
+ }
+
+ khui_alert_unlock(adata->alert);
+
+ /* Now set the rect for the whole alert */
+ SetRect(&adata->r_alert, 0, 0, d->cx_wnd, y);
+
+}
+
+static void
+pick_title_for_alerter_window(alerter_wnd_data * d) {
+ alerter_alert_data * adata;
+ wchar_t caption[KHUI_MAXCCH_TITLE];
+ khm_boolean common_caption = TRUE;
+ khui_alert_type ctype = KHUI_ALERTTYPE_NONE;
+ khm_boolean common_type = TRUE;
+
+ /* - If all the alerts have the same title, then we use the common
+ title.
+
+ - If all the alerts are of the same type, then we pick a title
+ that is suitable for the type.
+
+ - All else fails, we use a default caption for the window.
+ */
+
+ caption[0] = L'\0';
+ adata = QTOP(d);
+ while (adata && (common_caption || common_type)) {
+
+ if (adata->alert) {
+ khui_alert_lock(adata->alert);
+
+ if (common_caption) {
+ if (caption[0] == L'\0') {
+ if (adata->alert->title)
+ StringCbCopy(caption, sizeof(caption), adata->alert->title);
+ } else if (adata->alert->title &&
+ wcscmp(caption, adata->alert->title)) {
+ common_caption = FALSE;
+ }
+ }
+
+ if (common_type) {
+ if (ctype == KHUI_ALERTTYPE_NONE)
+ ctype = adata->alert->alert_type;
+ else if (ctype != adata->alert->alert_type)
+ common_type = FALSE;
+ }
+
+ khui_alert_unlock(adata->alert);
+ }
+
+ adata = QNEXT(adata);
+ }
+
+ /* just in case someone changes d->caption to a pointer from an
+ array */
+#ifdef DEBUG
+ assert(sizeof(d->caption) > sizeof(wchar_t *));
+#endif
+
+ if (common_caption && caption[0] != L'\0') {
+ StringCbCopy(d->caption, sizeof(d->caption), caption);
+ } else if (common_type && ctype != KHUI_ALERTTYPE_NONE) {
+ switch(ctype) {
+ case KHUI_ALERTTYPE_PLUGIN:
+ LoadString(khm_hInstance, IDS_ALERTTYPE_PLUGIN,
+ d->caption, ARRAYLENGTH(d->caption));
+ break;
+
+ case KHUI_ALERTTYPE_EXPIRE:
+ LoadString(khm_hInstance, IDS_ALERTTYPE_EXPIRE,
+ d->caption, ARRAYLENGTH(d->caption));
+ break;
+
+ case KHUI_ALERTTYPE_RENEWFAIL:
+ LoadString(khm_hInstance, IDS_ALERTTYPE_RENEWFAIL,
+ d->caption, ARRAYLENGTH(d->caption));
+ break;
+
+ case KHUI_ALERTTYPE_ACQUIREFAIL:
+ LoadString(khm_hInstance, IDS_ALERTTYPE_ACQUIREFAIL,
+ d->caption, ARRAYLENGTH(d->caption));
+ break;
+
+ case KHUI_ALERTTYPE_CHPW:
+ LoadString(khm_hInstance, IDS_ALERTTYPE_CHPW,
+ d->caption, ARRAYLENGTH(d->caption));
+ break;
+
+ default:
+ LoadString(khm_hInstance, IDS_ALERT_DEFAULT,
+ d->caption, ARRAYLENGTH(d->caption));
+ }
+ } else {
+ LoadString(khm_hInstance, IDS_ALERT_DEFAULT,
+ d->caption, ARRAYLENGTH(d->caption));
+ }
+
+ SetWindowText(d->hwnd, d->caption);
+}
+
+static void
+estimate_alerter_wnd_sizes(alerter_wnd_data * d) {
+ HDC hdc;
+ HFONT hf_old;
+ int height = 0;
+
+ alerter_alert_data * adata;
+
+ pick_title_for_alerter_window(d);
+
+ hdc = GetDC(d->hwnd);
+#ifdef DEBUG
+ assert(hdc);
+#endif
+
+ if (d->hfont == NULL)
+ d->hfont = (HFONT) GetStockObject(DEFAULT_GUI_FONT);
+
+#ifdef DEBUG
+ assert(d->hfont);
+#endif
+
+ hf_old = SelectFont(hdc, d->hfont);
+
+ adata = QTOP(d);
+ while(adata) {
+ layout_alert(hdc, d, adata);
+
+ height += adata->r_alert.bottom;
+
+ adata = QNEXT(adata);
+ }
+
+ SelectFont(hdc, hf_old);
+ ReleaseDC(d->hwnd, hdc);
+
+ d->s_alerts.cx = d->cx_wnd;
+ d->s_alerts.cy = height;
+}
+
+static void
+layout_command_buttons(alerter_wnd_data * d) {
+
+ alerter_alert_data * adata;
+ HDWP hdefer;
+ int y;
+
+ hdefer = BeginDeferWindowPos(d->n_cmd_buttons);
+
+ y = 0;
+ adata = QTOP(d);
+ while (adata) {
+ RECT r;
+ int i;
+
+ if (!adata->has_commands)
+ goto done;
+
+ for (i=0; i < adata->n_cmd_buttons; i++) {
+ if (IsRectEmpty(&adata->r_buttons[i])) {
+ /* the button is no longer needed */
+ if (adata->hwnd_buttons[i] != NULL) {
+ DestroyWindow(adata->hwnd_buttons[i]);
+ adata->hwnd_buttons[i] = NULL;
+ }
+
+ continue;
+ }
+
+ if (adata->hwnd_buttons[i] == NULL) {
+ continue;
+ }
+
+ CopyRect(&r, &adata->r_buttons[i]);
+ OffsetRect(&r, 0, y - d->scroll_top);
+
+ DeferWindowPos(hdefer,
+ adata->hwnd_buttons[i], NULL,
+ r.left, r.top, 0, 0,
+ SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER |
+ SWP_NOSIZE);
+ }
+
+ done:
+ y += adata->r_alert.bottom;
+ adata = QNEXT(adata);
+ }
+
+ EndDeferWindowPos(hdefer);
+}
+
+static void
+setup_alerter_window_controls(alerter_wnd_data * d) {
+
+ RECT r_alerts;
+ RECT r_window;
+ RECT r_client;
+ RECT r_parent;
+ HWND hw_parent;
+ HWND hw_focus = NULL;
+ BOOL close_button = FALSE;
+ BOOL scrollbar = FALSE;
+ BOOL redraw_scollbar = FALSE;
+
+ /* estimate_alerter_wnd_sizes() must be called before calling
+ this. */
+#ifdef DEBUG
+ assert(d->s_alerts.cy > 0);
+#endif
+
+ r_alerts.left = 0;
+ r_alerts.top = 0;
+ r_alerts.right = d->cx_wnd;
+
+ if (d->s_alerts.cy > d->cy_max_wnd) {
+
+ BOOL redraw = FALSE;
+
+ r_alerts.right += GetSystemMetrics(SM_CXVSCROLL);
+ r_alerts.bottom = d->cy_max_wnd;
+
+ CopyRect(&r_client, &r_alerts);
+ r_client.bottom += d->s_margin.cy + d->s_button.cy + d->s_pad.cy;
+ close_button = TRUE;
+
+ if (d->scroll_top > d->s_alerts.cy - d->cy_max_wnd)
+ d->scroll_top = d->s_alerts.cy - d->cy_max_wnd;
+
+ scrollbar = TRUE;
+ } else {
+ r_alerts.bottom = d->s_alerts.cy;
+
+ CopyRect(&r_client, &r_alerts);
+
+ if (d->n_alerts == 1) {
+
+ if (!QTOP(d)->has_commands) {
+ r_client.bottom += d->s_margin.cy * 2 + d->s_button.cy;
+ close_button = TRUE;
+ }
+
+ } else {
+
+ r_client.bottom += d->s_margin.cy * 2 + d->s_button.cy;
+ close_button = TRUE;
+ }
+
+ d->scroll_top = 0;
+ }
+
+ if (d->hw_bin == NULL) {
+ d->hw_bin = CreateWindowEx(WS_EX_CONTROLPARENT,
+ MAKEINTATOM(atom_alert_bin),
+ L"Alert Container",
+ WS_CHILD | WS_CLIPCHILDREN |
+ WS_VISIBLE |
+ ((scrollbar)? WS_VSCROLL : 0),
+ r_alerts.left, r_alerts.top,
+ r_alerts.right - r_alerts.left,
+ r_alerts.bottom - r_alerts.top,
+ d->hwnd,
+ (HMENU) IDC_NTF_ALERTBIN,
+ khm_hInstance,
+ (LPVOID) d);
+ } else {
+ redraw_scollbar = TRUE;
+ SetWindowLongPtr(d->hw_bin, GWL_STYLE,
+ WS_CHILD | WS_CLIPCHILDREN |
+ WS_VISIBLE |
+ ((scrollbar)? WS_VSCROLL : 0));
+ SetWindowPos(d->hw_bin, NULL,
+ r_alerts.left, r_alerts.top,
+ r_alerts.right - r_alerts.left,
+ r_alerts.bottom - r_alerts.top,
+ SWP_NOOWNERZORDER | SWP_NOZORDER | SWP_NOACTIVATE);
+ }
+
+ if (scrollbar) {
+ SCROLLINFO si;
+
+ ZeroMemory(&si, sizeof(si));
+ si.cbSize = sizeof(si);
+ si.fMask = SIF_PAGE | SIF_POS | SIF_RANGE;
+ si.nMin = 0;
+ si.nMax = d->s_alerts.cy;
+ si.nPage = d->cy_max_wnd;
+ si.nPos = d->scroll_top;
+
+ SetScrollInfo(d->hw_bin, SB_VERT, &si, redraw_scollbar);
+ }
+
+ /* create the action buttons */
+ {
+ alerter_alert_data * adata;
+ int y;
+ int idx;
+ HWND last_window = HWND_TOP;
+ int n_buttons = 0;
+
+ idx = 0;
+ y = - d->scroll_top;
+ adata = QTOP(d);
+ while(adata) {
+ if (adata->has_commands) {
+ int i;
+ wchar_t caption[KHUI_MAXCCH_SHORT_DESC];
+ RECT r;
+
+ if (adata->hwnd_marker) {
+ DestroyWindow(adata->hwnd_marker);
+ adata->hwnd_marker = NULL;
+ }
+
+ khui_alert_lock(adata->alert);
+
+ adata->n_cmd_buttons = adata->alert->n_alert_commands;
+
+ for (i=0; i < adata->alert->n_alert_commands; i++) {
+
+ n_buttons ++;
+
+ if (IsRectEmpty(&adata->r_buttons[i])) {
+ /* this button is not necessary */
+ if (adata->hwnd_buttons[i]) {
+ DestroyWindow(adata->hwnd_buttons[i]);
+ adata->hwnd_buttons[i] = NULL;
+ }
+
+ continue;
+ }
+
+ if (adata->hwnd_buttons[i] != NULL) {
+ /* already there */
+ CopyRect(&r, &adata->r_buttons[i]);
+ OffsetRect(&r, 0, y);
+
+ SetWindowPos(adata->hwnd_buttons[i], last_window,
+ r.left, r.top,
+ r.right - r.left,
+ r.bottom - r.top,
+ SWP_NOACTIVATE | SWP_NOOWNERZORDER |
+ SWP_SHOWWINDOW);
+
+ last_window = adata->hwnd_buttons[i];
+
+ if (hw_focus == NULL)
+ hw_focus = adata->hwnd_buttons[i];
+
+ continue;
+ }
+
+ khm_get_action_caption(adata->alert->alert_commands[i],
+ caption, sizeof(caption));
+
+ CopyRect(&r, &adata->r_buttons[i]);
+ OffsetRect(&r, 0, y);
+
+ adata->hwnd_buttons[i] =
+ CreateWindowEx(0,
+ L"BUTTON",
+ caption,
+ WS_CHILD | WS_TABSTOP | BS_NOTIFY,
+ r.left, r.top,
+ r.right - r.left,
+ r.bottom - r.top,
+ d->hw_bin,
+ (HMENU) (INT_PTR) IDC_FROM_IDX(idx, i),
+ khm_hInstance,
+ NULL);
+#ifdef DEBUG
+ assert(adata->hwnd_buttons[i]);
+#endif
+
+ if (d->hfont) {
+ SendMessage(adata->hwnd_buttons[i], WM_SETFONT,
+ (WPARAM) d->hfont, FALSE);
+ }
+
+ SetWindowPos(adata->hwnd_buttons[i], last_window,
+ 0, 0, 0, 0,
+ SWP_NOACTIVATE | SWP_NOOWNERZORDER |
+ SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
+
+ last_window = adata->hwnd_buttons[i];
+
+ if (hw_focus == NULL)
+ hw_focus = adata->hwnd_buttons[i];
+ }
+
+ khui_alert_unlock(adata->alert);
+ } else {
+ int i;
+
+ /* Destroy any buttons that belong to the alert. We
+ might have some left over, if there were command
+ belonging to the alert that were ignored.*/
+
+ for (i=0; i < adata->n_cmd_buttons; i++) {
+ if (adata->hwnd_buttons[i]) {
+ DestroyWindow(adata->hwnd_buttons[i]);
+ adata->hwnd_buttons[i] = NULL;
+ }
+ }
+
+ adata->n_cmd_buttons = 0;
+
+ if (adata->hwnd_marker == NULL) {
+ adata->hwnd_marker =
+ CreateWindowEx(0,
+ L"BUTTON",
+ L"Marker",
+ WS_CHILD | WS_TABSTOP | WS_VISIBLE | BS_NOTIFY,
+ -10, 0,
+ 5, 5,
+ d->hw_bin,
+ (HMENU) (INT_PTR) IDC_FROM_IDX(idx, -1),
+ khm_hInstance,
+ NULL);
+#ifdef DEBUG
+ assert(adata->hwnd_marker);
+#endif
+ }
+
+ SetWindowPos(adata->hwnd_marker, last_window,
+ 0, 0, 0, 0,
+ SWP_NOACTIVATE | SWP_NOOWNERZORDER |
+ SWP_NOMOVE | SWP_NOSIZE);
+
+ last_window = adata->hwnd_marker;
+
+ if (scrollbar) {
+ EnableWindow(adata->hwnd_marker, TRUE);
+ if (hw_focus == NULL)
+ hw_focus = adata->hwnd_marker;
+ } else {
+ EnableWindow(adata->hwnd_marker, FALSE);
+ }
+ }
+
+ y += adata->r_alert.bottom;
+ adata = QNEXT(adata);
+ idx++;
+ }
+
+ d->n_cmd_buttons = n_buttons;
+ }
+
+ if (close_button) {
+ if (d->hw_close == NULL) {
+ wchar_t caption[256];
+
+ khm_get_action_caption(KHUI_PACTION_CLOSE, caption, sizeof(caption));
+
+ d->hw_close = CreateWindowEx(0,
+ L"BUTTON",
+ caption,
+ WS_CHILD | BS_DEFPUSHBUTTON | WS_TABSTOP | BS_NOTIFY,
+ 0,0,100,100,
+ d->hwnd,
+ (HMENU) IDC_NTF_CLOSE,
+ khm_hInstance,
+ NULL);
+
+#ifdef DEBUG
+ assert(d->hw_close);
+ assert(d->hfont);
+#endif
+ if (d->hfont)
+ SendMessage(d->hw_close, WM_SETFONT, (WPARAM) d->hfont, FALSE);
+ }
+
+ {
+ int x,y,width,height;
+
+ x = d->r_text.left;
+ y = r_client.bottom - (d->s_margin.cy + d->s_button.cy);
+ width = d->s_button.cx;
+ height = d->s_button.cy;
+
+ SetWindowPos(d->hw_close, NULL,
+ x, y, width, height,
+ SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER |
+ SWP_SHOWWINDOW);
+ }
+
+ if (hw_focus == NULL || d->n_cmd_buttons == 0)
+ hw_focus = d->hw_close;
+
+ } else {
+ if (d->hw_close != NULL) {
+ DestroyWindow(d->hw_close);
+ d->hw_close = NULL;
+ }
+ }
+
+ CopyRect(&r_window, &r_client);
+ AdjustWindowRectEx(&r_window, ALERT_WINDOW_STYLES,
+ FALSE, ALERT_WINDOW_EX_SYLES);
+ OffsetRect(&r_window, -r_window.left, -r_window.top);
+
+ /* center the window above the parent window. */
+
+ hw_parent = GetWindow(d->hwnd, GW_OWNER);
+ GetWindowRect(hw_parent, &r_parent);
+
+ {
+ int x,y;
+
+ x = (r_parent.left + r_parent.right - (r_window.right - r_window.left)) / 2;
+ y = (r_parent.top + r_parent.bottom - (r_window.bottom - r_window.top)) / 2;
+
+ SetWindowPos(d->hwnd,
+ HWND_TOP,
+ x, y,
+ r_window.right - r_window.left,
+ r_window.bottom - r_window.top,
+ SWP_SHOWWINDOW | SWP_NOOWNERZORDER);
+ }
+
+ if (hw_focus != NULL)
+ PostMessage(d->hwnd, WM_NEXTDLGCTL, (WPARAM) hw_focus, MAKELPARAM(TRUE, 0));
+}
+
+static void
+scroll_to_position(alerter_wnd_data * d, int new_pos, khm_boolean redraw_scrollbar) {
+ int delta;
+ SCROLLINFO si;
+ HWND hwnd = d->hw_bin;
+
+ if (new_pos < 0)
+ new_pos = 0;
+ else if (new_pos > d->s_alerts.cy - d->cy_max_wnd)
+ new_pos = d->s_alerts.cy - d->cy_max_wnd;
+
+ if (new_pos == d->scroll_top)
+ return;
+
+ delta = d->scroll_top - new_pos;
+
+ d->scroll_top -= delta;
+
+ ScrollWindowEx(hwnd, 0, delta,
+ NULL, NULL, NULL, NULL,
+ SW_INVALIDATE | SW_ERASE);
+
+ layout_command_buttons(d);
+
+ ZeroMemory(&si, sizeof(si));
+
+ si.fMask = SIF_POS;
+ si.nPos = d->scroll_top;
+
+ SetScrollInfo(hwnd, SB_VERT, &si, redraw_scrollbar);
+}
+
+static void
+select_alert(alerter_wnd_data * d, int alert) {
+
+ int y;
+ RECT old_sel, new_sel;
+ alerter_alert_data * adata;
+ int idx;
+
+ if (d->n_alerts == 1 ||
+ alert < 0 ||
+ alert > d->n_alerts ||
+ d->c_alert == alert)
+ return;
+
+ SetRectEmpty(&old_sel);
+ SetRectEmpty(&new_sel);
+ idx = 0; y = -d->scroll_top;
+ adata = QTOP(d);
+ while(adata && (idx <= d->c_alert || idx <= alert)) {
+
+ if (idx == d->c_alert) {
+ CopyRect(&old_sel, &adata->r_alert);
+ OffsetRect(&old_sel, 0, y);
+ }
+
+ if (idx == alert) {
+ CopyRect(&new_sel, &adata->r_alert);
+ OffsetRect(&new_sel, 0, y);
+ }
+
+ y += adata->r_alert.bottom;
+ idx ++;
+ adata = QNEXT(adata);
+ }
+
+ d->c_alert = alert;
+ if (!IsRectEmpty(&old_sel))
+ InvalidateRect(d->hw_bin, &old_sel, TRUE);
+ if (!IsRectEmpty(&new_sel))
+ InvalidateRect(d->hw_bin, &new_sel, TRUE);
+}
+
+static void
+ensure_command_is_visible(alerter_wnd_data * d, int id) {
+ int alert_idx;
+ int y = 0;
+ alerter_alert_data * adata;
+ int new_pos = 0;
+
+ alert_idx = ALERT_FROM_IDC(id);
+
+#ifdef DEBUG
+ assert(alert_idx >= 0 && alert_idx < d->n_alerts);
+#endif
+ if (alert_idx >= d->n_alerts || alert_idx < 0)
+ return;
+
+ adata = QTOP(d);
+ while(adata && alert_idx > 0) {
+ y += adata->r_alert.bottom;
+ alert_idx--;
+ adata = QNEXT(adata);
+ }
+
+#ifdef DEBUG
+ assert(alert_idx == 0);
+ assert(adata);
+ assert(adata->alert);
+#endif
+ if (adata == NULL || alert_idx != 0)
+ return;
+
+ new_pos = d->scroll_top;
+ if (y < d->scroll_top) {
+ new_pos = y;
+ } else if (y + adata->r_alert.bottom > d->scroll_top + d->cy_max_wnd) {
+ new_pos = y + adata->r_alert.bottom - d->cy_max_wnd;
+ }
+
+ if (new_pos != d->scroll_top)
+ scroll_to_position(d, new_pos, TRUE);
+
+ select_alert(d, ALERT_FROM_IDC(id));
+}
+
+static void
+handle_mouse_select(alerter_wnd_data * d, int mouse_x, int mouse_y) {
+ int y;
+ alerter_alert_data * adata;
+
+ y = -d->scroll_top;
+ adata = QTOP(d);
+ while(adata) {
+ if (y <= mouse_y && (y + adata->r_alert.bottom) > mouse_y) {
+ HWND hw = NULL;
+
+ if (adata->n_cmd_buttons > 0)
+ hw = adata->hwnd_buttons[0];
+ else
+ hw = adata->hwnd_marker;
+
+ if (hw && !IsWindowEnabled(hw))
+ hw = GetNextDlgTabItem(d->hwnd, hw, FALSE);
+
+ if (hw)
+ PostMessage(d->hwnd, WM_NEXTDLGCTL, (WPARAM) hw, MAKELPARAM(TRUE, 0));
+
+ return;
+ }
+
+ y += adata->r_alert.bottom;
+ adata = QNEXT(adata);
+ }
+}
+
+static void
+process_command_button(alerter_wnd_data * d, int id) {
+ int alert_idx;
+ int cmd_idx;
+ khm_int32 flags = 0;
+ khm_int32 cmd = 0;
+ alerter_alert_data * adata;
+ int i;
+
+ alert_idx = ALERT_FROM_IDC(id);
+ cmd_idx = BUTTON_FROM_IDC(id);
+
+#ifdef DEBUG
+ assert(alert_idx >= 0 && alert_idx < d->n_alerts);
+#endif
+ if (alert_idx >= d->n_alerts || alert_idx < 0)
+ return;
+
+ if (cmd_idx < 0) {
+ /* the user selected a marker button. Nothing to do. */
+ return;
+ }
+
+ adata = QTOP(d);
+ while(adata && alert_idx > 0) {
+ alert_idx--;
+ adata = QNEXT(adata);
+ }
+
+#ifdef DEBUG
+ assert(alert_idx == 0);
+ assert(adata);
+ assert(adata->alert);
+#endif
+ if (adata == NULL || alert_idx != 0)
+ return;
+
+ khui_alert_lock(adata->alert);
+#ifdef DEBUG
+ assert(cmd_idx >= 0 && cmd_idx < adata->alert->n_alert_commands);
+#endif
+
+ if (cmd_idx >= 0 && cmd_idx < adata->alert->n_alert_commands) {
+ cmd = adata->alert->alert_commands[cmd_idx];
+ }
+
+ flags = adata->alert->flags;
+
+ adata->alert->response = cmd;
+
+ khui_alert_unlock(adata->alert);
+
+ /* if we were supposed to dispatch the command, do so */
+ if (cmd != 0 &&
+ cmd != KHUI_PACTION_CLOSE &&
+ (flags & KHUI_ALERT_FLAG_DISPATCH_CMD)) {
+ PostMessage(khm_hwnd_main, WM_COMMAND,
+ MAKEWPARAM(cmd, 0), 0);
+ }
+
+ /* if this was the only alert in the alert group and its close
+ button was clicked, we close the alert window. Otherwise, the
+ alert window creates its own close button that closes the
+ window. */
+ if (d->n_alerts == 1) {
+ PostMessage(d->hwnd, WM_CLOSE, 0, 0);
+ }
+
+ /* While we are at it, we should disable the buttons for this
+ alert since we have already dispatched the command for it. */
+ if (cmd != 0) {
+ HWND hw_focus = GetFocus();
+ khm_boolean focus_trapped = FALSE;
+
+ for (i=0; i < adata->n_cmd_buttons; i++) {
+ if (adata->hwnd_buttons[i]) {
+ if (hw_focus == adata->hwnd_buttons[i])
+ focus_trapped = TRUE;
+
+ EnableWindow(adata->hwnd_buttons[i], FALSE);
+ }
+ }
+
+ if (focus_trapped) {
+ hw_focus = GetNextDlgTabItem(d->hwnd, hw_focus, FALSE);
+ if (hw_focus)
+ PostMessage(d->hwnd, WM_NEXTDLGCTL, (WPARAM) hw_focus, MAKELPARAM(TRUE,0));
+ }
+ }
+}
+
+static void
+destroy_alerter_wnd_data(alerter_wnd_data * d) {
+ alerter_alert_data * adata;
+
+ LDELETE(&khui_alert_windows, d);
+
+ QGET(d, &adata);
+ while(adata) {
+
+ if (adata->alert) {
+
+ khui_alert_lock(adata->alert);
+
+ adata->alert->displayed = FALSE;
+
+ khui_alert_unlock(adata->alert);
+
+ khui_alert_release(adata->alert);
+ adata->alert = NULL;
+ }
+
+ PFREE(adata);
+
+ QGET(d, &adata);
+ }
+
+ PFREE(d);
+}
+
+/* both ref and to_add must be locked and held */
+static khm_boolean
+alert_can_consolidate(khui_alert * ref,
+ khui_alert * to_add,
+ alert_list * alist) {
+
+ /* first check if we can add anything */
+ if (alist->n_alerts == ARRAYLENGTH(alist->alerts))
+ return FALSE;
+
+#ifdef DEBUG
+ assert(to_add != NULL);
+#endif
+
+ if (ref == NULL) {
+ /* we are testing whether to_add should be added to the alist
+ on its own. */
+ if ((to_add->flags & KHUI_ALERT_FLAG_DISPLAY_BALLOON) &&
+ !(to_add->flags & KHUI_ALERT_FLAG_DISPLAY_WINDOW)) {
+ /* already displayed */
+ return FALSE;
+ }
+
+ if ((to_add->flags & (KHUI_ALERT_FLAG_REQUEST_BALLOON |
+ KHUI_ALERT_FLAG_REQUEST_WINDOW)) == KHUI_ALERT_FLAG_REQUEST_BALLOON) {
+ /* needs to be shown in a balloon */
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+ /* if the ref or to_add are marked for modal, then we can't
+ consolidate them */
+ if ((ref->flags & KHUI_ALERT_FLAG_MODAL) ||
+ (to_add->flags & KHUI_ALERT_FLAG_MODAL))
+ return FALSE;
+
+ /* also, if either of them have requested to be exclusively shown
+ in a balloon, then we can't consolidate them. */
+ if (((ref->flags & (KHUI_ALERT_FLAG_REQUEST_BALLOON |
+ KHUI_ALERT_FLAG_REQUEST_WINDOW)) == KHUI_ALERT_FLAG_REQUEST_BALLOON)
+
+ ||
+
+ ((to_add->flags & (KHUI_ALERT_FLAG_REQUEST_BALLOON |
+ KHUI_ALERT_FLAG_REQUEST_WINDOW)) == KHUI_ALERT_FLAG_REQUEST_BALLOON))
+ return FALSE;
+
+ /* for now, all we check if whether they are of the same type. */
+ if (ref->alert_type != KHUI_ALERTTYPE_NONE &&
+ ref->alert_type == to_add->alert_type)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+/* both a1 and a2 must be locked */
+static khm_boolean
+alert_is_equal(khui_alert * a1, khui_alert * a2) {
+ khm_int32 i;
+
+ if ((a1->severity != a2->severity) ||
+ (a1->n_alert_commands != a2->n_alert_commands) ||
+ (a1->title && (!a2->title || wcscmp(a1->title, a2->title))) ||
+ (!a1->title && a2->title) ||
+ (a1->message && (!a2->message || wcscmp(a1->message, a2->message))) ||
+ (!a1->message && a2->message) ||
+ (a1->suggestion && (!a2->suggestion || wcscmp(a1->suggestion, a2->suggestion))) ||
+ (!a1->suggestion && a2->suggestion)) {
+
+ return FALSE;
+
+ }
+
+ for (i=0; i < a1->n_alert_commands; i++) {
+ if (a1->alert_commands[i] != a2->alert_commands[i])
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/* the return value is the number of alerts added to alist */
+static khm_int32
+alert_consolidate(alert_list * alist,
+ khui_alert * alert,
+ khm_boolean add_from_queue) {
+
+ khui_alert * listtop;
+ int queue_size = 0;
+ int i;
+ khm_int32 n_added = 0;
+
+#ifdef DEBUG
+ assert(alist);
+#endif
+
+ if (alist->n_alerts == ARRAYLENGTH(alist->alerts)) {
+ /* can't add anything */
+
+ return 0;
+ }
+
+ /* if the list is empty, we just add one alert */
+ if (alist->n_alerts == 0) {
+
+ if (alert) {
+ khui_alert_lock(alert);
+ if (alert_can_consolidate(NULL, alert, alist)) {
+ alert_list_add_alert(alist, alert);
+ n_added ++;
+ alert = NULL;
+ }
+ khui_alert_unlock(alert);
+ }
+
+ if (n_added == 0 && add_from_queue) {
+ khui_alert * q;
+ int i;
+
+ queue_size = alert_queue_get_size();
+ for (i=0; i < queue_size && n_added == 0; i++) {
+ q = alert_queue_get_alert_by_pos(i);
+ if (q) {
+ khui_alert_lock(q);
+ if (alert_can_consolidate(NULL, q, alist)) {
+ alert_list_add_alert(alist, q);
+ n_added++;
+ alert_queue_delete_alert(q);
+ }
+ khui_alert_unlock(q);
+ khui_alert_release(q);
+ }
+ }
+ }
+
+ if (n_added == 0) {
+ /* nothing to add */
+ return 0;
+ }
+ }
+
+ /* at this point, the alert list is not empty */
+#ifdef DEBUG
+ assert(alist->n_alerts != 0);
+ assert(alist->alerts[0]);
+#endif
+
+ listtop = alist->alerts[0];
+ khui_alert_hold(listtop);
+ khui_alert_lock(listtop);
+
+ queue_size = alert_queue_get_size();
+
+ if (alert) {
+ khui_alert_lock(alert);
+ if (alert_can_consolidate(listtop, alert, alist)) {
+ alert_list_add_alert(alist, alert);
+ n_added ++;
+ }
+ khui_alert_unlock(alert);
+ }
+
+ if (add_from_queue) {
+ for (i=0; i < queue_size; i++) {
+ khui_alert * a;
+
+ a = alert_queue_get_alert_by_pos(i);
+ if (a == NULL)
+ continue;
+
+ khui_alert_lock(a);
+ if (alert_can_consolidate(listtop, a, alist)) {
+ alert_queue_delete_alert(a);
+ alert_list_add_alert(alist, a);
+ n_added ++;
+
+ queue_size--;
+ i--;
+#ifdef DEBUG
+ assert(alert_queue_get_size() == queue_size);
+#endif
+ }
+ khui_alert_unlock(a);
+ khui_alert_release(a);
+ }
+ }
+
+ khui_alert_unlock(listtop);
+ khui_alert_release(listtop);
+
+ return n_added;
+}
+
+static khm_int32
+alert_check_consolidate_window(alerter_wnd_data * d, khui_alert * a) {
+ alert_list alist;
+ alerter_alert_data * adata;
+ int n_added;
+
+ alert_list_init(&alist);
+
+ adata = QTOP(d);
+ while(adata) {
+
+#ifdef DEBUG
+ assert(adata->alert);
+#endif
+ alert_list_add_alert(&alist, adata->alert);
+
+ adata = QNEXT(adata);
+ }
+
+ n_added = alert_consolidate(&alist, a, FALSE);
+
+ alert_list_destroy(&alist);
+
+ return n_added;
+}
+
+static khm_int32
+alert_show_minimized(khui_alert * a) {
+ wchar_t tbuf[64]; /* corresponds to NOTIFYICONDATA::szInfoTitle[] */
+ wchar_t mbuf[256]; /* corresponds to NOTIFYICONDATA::szInfo[] */
+
+#ifdef DEBUG
+ assert(a);
+#endif
+ if (a == NULL)
+ return KHM_ERROR_INVALID_PARAM;
+
+ khui_alert_lock(a);
+
+ if (a->message == NULL)
+ goto done;
+
+ if (a->title == NULL) {
+ LoadString(khm_hInstance, IDS_ALERT_DEFAULT,
+ tbuf, ARRAYLENGTH(tbuf));
+ } else {
+ StringCbCopy(tbuf, sizeof(tbuf), a->title);
+ }
+
+ if (FAILED(StringCbCopy(mbuf, sizeof(mbuf), a->message)) ||
+ (!(a->flags & KHUI_ALERT_FLAG_DEFACTION) &&
+ (a->n_alert_commands > 0 ||
+ a->suggestion ||
+ (a->flags & KHUI_ALERT_FLAG_VALID_ERROR)))) {
+ /* if mbuf wasn't big enough, this should have copied a
+ truncated version of it */
+ size_t cch_m, cch_p;
+ wchar_t postfix[256];
+
+ cch_p = LoadString(khm_hInstance, IDS_ALERT_MOREINFO, postfix,
+ ARRAYLENGTH(postfix));
+ cch_p++; /* account for NULL */
+
+ StringCchLength(mbuf, ARRAYLENGTH(mbuf), &cch_m);
+ cch_m = min(cch_m, ARRAYLENGTH(mbuf) - cch_p);
+
+ StringCchCopy(mbuf + cch_m, ARRAYLENGTH(mbuf) - cch_m,
+ postfix);
+
+ a->flags |= KHUI_ALERT_FLAG_REQUEST_WINDOW;
+ }
+
+ a->flags |= KHUI_ALERT_FLAG_DISPLAY_BALLOON;
+
+#ifdef DEBUG
+ assert(balloon_alert == NULL);
+#endif
+
+ if (balloon_alert) {
+ khui_alert_lock(balloon_alert);
+ balloon_alert->displayed = FALSE;
+ khui_alert_unlock(balloon_alert);
+ khui_alert_release(balloon_alert);
+ balloon_alert = NULL;
+ }
+
+ balloon_alert = a;
+ khui_alert_hold(a);
+
+ a->displayed = TRUE;
+
+ khm_notify_icon_balloon(a->severity,
+ tbuf,
+ mbuf,
+ NTF_TIMEOUT);
+
+ done:
+ khui_alert_unlock(a);
+
+ return KHM_ERROR_SUCCESS;
+}
+
+static khm_int32
+alert_show_normal(khui_alert * a) {
+ wchar_t buf[256];
+ wchar_t * title;
+ alert_list alist;
+
+ khui_alert_lock(a);
+
+ if(a->title == NULL) {
+ LoadString(khm_hInstance, IDS_ALERT_DEFAULT,
+ buf, ARRAYLENGTH(buf));
+ title = buf;
+ } else
+ title = a->title;
+
+ khui_alert_unlock(a);
+
+ alert_list_init(&alist);
+ alert_list_set_title(&alist, title);
+ alert_list_add_alert(&alist, a);
+
+ alert_show_list(&alist);
+
+ alert_list_destroy(&alist);
+
+ return KHM_ERROR_SUCCESS;
+}
+
+static khm_int32
+alert_show_list(alert_list * alist) {
+ HWND hwa;
+
+ /* we don't need to keep track of the window handle
+ because the window procedure adds it to the dialog
+ list automatically */
+
+ hwa =
+ CreateWindowEx(ALERT_WINDOW_EX_SYLES,
+ MAKEINTATOM(atom_alerter),
+ alist->title,
+ ALERT_WINDOW_STYLES,
+ 0, 0, 300, 300, // bogus values
+ khm_hwnd_main,
+ (HMENU) NULL,
+ khm_hInstance,
+ (LPVOID) alist);
+
+ ShowWindow(hwa, SW_SHOW);
+
+ return (hwa != NULL);
+}
+
+static khm_int32
+alert_show(khui_alert * a) {
+ khm_boolean show_normal = FALSE;
+ khm_boolean show_mini = FALSE;
+
+ khui_alert_lock(a);
+
+ /* is there an alert already? If so, we just enqueue the message
+ and let it sit. */
+ if (ALERT_DISPLAYED() &&
+ !(a->flags & KHUI_ALERT_FLAG_MODAL)) {
+ khm_int32 rv;
+ alerter_wnd_data * wdata;
+
+ khui_alert_unlock(a);
+
+ /* if there are any alerter windows displayed, check if this
+ alert can be consolidated with any of them. If so, we
+ should consolidate it. Otherwise, just enqueue it. */
+ for(wdata = khui_alert_windows;
+ wdata;
+ wdata = LNEXT(wdata)) {
+ if (alert_check_consolidate_window(wdata, a)) {
+
+ add_alert_to_wnd_data(wdata, a);
+ estimate_alerter_wnd_sizes(wdata);
+ setup_alerter_window_controls(wdata);
+
+ return KHM_ERROR_SUCCESS;
+
+ }
+ }
+
+ rv = alert_enqueue(a);
+
+ if (KHM_SUCCEEDED(rv))
+ return KHM_ERROR_HELD;
+ else
+ return rv;
+ }
+
+ if((a->flags & KHUI_ALERT_FLAG_DISPLAY_WINDOW) ||
+ ((a->flags & KHUI_ALERT_FLAG_DISPLAY_BALLOON) &&
+ !(a->flags & KHUI_ALERT_FLAG_REQUEST_WINDOW))) {
+
+ /* The alert has already been displayed. */
+
+ show_normal = FALSE;
+ show_mini = FALSE;
+
+ } else {
+
+ if(a->err_context != NULL ||
+ a->err_event != NULL) {
+ a->flags |= KHUI_ALERT_FLAG_VALID_ERROR;
+ }
+
+ /* depending on the state of the main window, we
+ need to either show a window or a balloon */
+ if ((a->flags & KHUI_ALERT_FLAG_MODAL) ||
+ (khm_is_main_window_active() &&
+ !(a->flags & KHUI_ALERT_FLAG_REQUEST_BALLOON)) ||
+ (a->flags & KHUI_ALERT_FLAG_REQUEST_WINDOW)) {
+
+ show_normal = TRUE;
+
+ } else {
+
+ show_mini = TRUE;
+
+ }
+ }
+
+ khui_alert_unlock(a);
+
+ if (show_normal)
+ return alert_show_normal(a);
+ else if (show_mini)
+ return alert_show_minimized(a);
+ else
+ return KHM_ERROR_SUCCESS;
+}
+
+static void
+show_queued_alerts(void) {
+
+ if (!ALERT_DISPLAYED()) {
+
+ /* show next consolidated batch */
+ alert_list alist;
+ int n;
+
+ alert_list_init(&alist);
+ n = alert_consolidate(&alist, NULL, TRUE);
+
+ if (n) {
+ if (n == 1) {
+ khui_alert_lock(alist.alerts[0]);
+
+ if (alist.alerts[0]->title) {
+ alert_list_set_title(&alist, alist.alerts[0]->title);
+ } else {
+ wchar_t title[KHUI_MAXCCH_TITLE];
+ LoadString(khm_hInstance, IDS_ALERT_DEFAULT,
+ title, ARRAYLENGTH(title));
+ alert_list_set_title(&alist, title);
+ }
+
+ khui_alert_unlock(alist.alerts[0]);
+ } else {
+ wchar_t title[KHUI_MAXCCH_TITLE];
+ LoadString(khm_hInstance, IDS_ALERT_DEFAULT,
+ title, ARRAYLENGTH(title));
+ alert_list_set_title(&alist, title);
+ }
+
+ alert_show_list(&alist);
+ }
+
+ alert_list_destroy(&alist);
+
+ if (n == 0) {
+ khui_alert * a;
+
+ /* no alerts were shown above. This maybe because none of
+ the alerts were consolidatable or they were requested
+ to be shown in a balloon. In this case, we just take
+ the first alert from the queue and show it manually. */
+
+ a = alert_queue_get_alert();
+ if (a) {
+ alert_show(a);
+ khui_alert_release(a);
+ }
+ }
+
+ check_for_queued_alerts();
+ }
+}
+
+
+static void
+check_for_queued_alerts(void) {
+ if (!is_alert_queue_empty()) {
+ khui_alert * a;
+
+ a = alert_queue_peek();
+
+ khui_alert_lock(a);
+
+ if (a->title) {
+ HICON hi;
+ int res;
+
+ if (a->severity == KHERR_ERROR)
+ res = OIC_ERROR;
+ else if (a->severity == KHERR_WARNING)
+ res = OIC_WARNING;
+ else
+ res = OIC_INFORMATION;
+
+ hi = LoadImage(0, MAKEINTRESOURCE(res),
+ IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON),
+ LR_SHARED);
+
+ khm_statusbar_set_part(KHUI_SBPART_NOTICE,
+ hi,
+ a->title);
+ } else {
+ khm_statusbar_set_part(KHUI_SBPART_NOTICE,
+ NULL, NULL);
+#ifdef DEBUG
+ DebugBreak();
+#endif
+ }
+
+ khui_alert_unlock(a);
+ khui_alert_release(a);
+
+ } else {
+ khm_statusbar_set_part(KHUI_SBPART_NOTICE,
+ NULL, NULL);
+ }
+}
+
+static khm_int32
+alert_enqueue(khui_alert * a) {
+ if (is_alert_queue_full())
+ return KHM_ERROR_NO_RESOURCES;
+
+ alert_queue_put_alert(a);
+ check_for_queued_alerts();
+
+ return KHM_ERROR_SUCCESS;
+}
+
+/* the alerter window is actually a dialog */
+static LRESULT CALLBACK
+alerter_wnd_proc(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ switch(uMsg) {
+ case WM_CREATE:
+ {
+ LPCREATESTRUCT lpcs;
+ alert_list * alist;
+ alerter_wnd_data * d;
+
+ lpcs = (LPCREATESTRUCT) lParam;
+ alist = (alert_list *) lpcs->lpCreateParams;
+
+ d = create_alerter_wnd_data(hwnd, alist);
+
+#pragma warning(push)
+#pragma warning(disable: 4244)
+ SetWindowLongPtr(hwnd, NTF_PARAM, (LONG_PTR) d);
+#pragma warning(pop)
+
+ khm_add_dialog(hwnd);
+ khm_enter_modal(hwnd);
+
+ estimate_alerter_wnd_sizes(d);
+ setup_alerter_window_controls(d);
+
+ if (d->hw_close) {
+ SetFocus(d->hw_close);
+ }
+
+ return TRUE;
+ }
+ break; /* not reached */
+
+ case WM_DESTROY:
+ {
+ alerter_wnd_data * d;
+
+ /* khm_leave_modal() could be here, but instead it is in
+ the WM_COMMAND handler. This is because the modal loop
+ has to be exited before DestroyWindow() is issued. */
+ //khm_leave_modal();
+ khm_del_dialog(hwnd);
+
+ d = (alerter_wnd_data *)(LONG_PTR)
+ GetWindowLongPtr(hwnd, NTF_PARAM);
+
+ destroy_alerter_wnd_data(d);
+
+ return TRUE;
+ }
+ break;
+
+ case WM_COMMAND:
+ {
+ alerter_wnd_data * d;
+
+ d = (alerter_wnd_data *)(LONG_PTR)
+ GetWindowLongPtr(hwnd, NTF_PARAM);
+
+ if(HIWORD(wParam) == BN_CLICKED) {
+ if (LOWORD(wParam) == IDC_NTF_CLOSE ||
+ LOWORD(wParam) == KHUI_PACTION_NEXT) {
+
+ khm_leave_modal();
+
+ DestroyWindow(hwnd);
+
+ return 0;
+ }
+ }
+ }
+ break;
+
+ case WM_CLOSE:
+ {
+ khm_leave_modal();
+
+ DestroyWindow(hwnd);
+
+ return 0;
+ }
+ }
+
+ /* Since this is a custom built dialog, we use DefDlgProc instead
+ of DefWindowProc. */
+ return DefDlgProc(hwnd, uMsg, wParam, lParam);
+}
+
+static LRESULT CALLBACK
+alert_bin_wnd_proc(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ BOOL in_printclient = FALSE;
+
+ switch(uMsg) {
+ case WM_CREATE:
+ {
+ LPCREATESTRUCT lpcs;
+ alerter_wnd_data * d;
+
+ lpcs = (LPCREATESTRUCT) lParam;
+ d = (alerter_wnd_data *) lpcs->lpCreateParams;
+
+#pragma warning(push)
+#pragma warning(disable: 4244)
+ SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) d);
+#pragma warning(pop)
+ }
+ return 0;
+
+ case WM_ERASEBKGND:
+ /* we erase the background when we are drawing the alerts
+ anyway. */
+ return 0;
+
+ case WM_PRINTCLIENT:
+ in_printclient = TRUE;
+ /* fallthrough */
+ case WM_PAINT:
+ {
+ HDC hdc;
+ PAINTSTRUCT ps;
+ RECT r;
+ HFONT hf_old;
+ int y;
+ alerter_wnd_data * d;
+ alerter_alert_data * adata;
+ size_t len;
+ int idx;
+
+ d = (alerter_wnd_data *) (LONG_PTR) GetWindowLongPtr(hwnd, GWLP_USERDATA);
+#ifdef DEBUG
+ assert(d);
+#endif
+
+ if (in_printclient) {
+ hdc = (HDC) wParam;
+ } else {
+ hdc = BeginPaint(hwnd, &ps);
+ }
+
+#ifdef DEBUG
+ assert(hdc);
+ assert(d->hfont);
+#endif
+
+#ifdef ALERT_STATIC_BACKGROUND
+ if (in_printclient || ps.fErase) {
+ HBRUSH hb_background;
+
+ hb_background = GetSysColorBrush(COLOR_BTNFACE);
+
+ GetClientRect(hwnd, &r);
+ FillRect(hdc, &r, hb_background);
+ }
+#endif
+
+ SetBkMode(hdc, TRANSPARENT);
+
+ hf_old = SelectFont(hdc, d->hfont);
+
+ y = -d->scroll_top;
+ idx = 0;
+ /* go through the alerts and display them */
+ adata = QTOP(d);
+ while(adata) {
+ khui_alert * a;
+
+#ifndef ALERT_STATIC_BACKGROUND
+#define MIX_C(v1, v2, p) (((int)v1) * p + (((int) v2) * (256 - p)))
+#define ALPHA 50
+ if (in_printclient || ps.fErase) {
+ TRIVERTEX v[2];
+ GRADIENT_RECT gr;
+ COLORREF clr;
+ COLORREF clr2;
+
+ CopyRect(&r, &adata->r_alert);
+ OffsetRect(&r, 0, y);
+
+ v[0].x = r.left;
+ v[0].y = r.top;
+ v[0].Alpha = 0;
+
+ v[1].x = r.right;
+ v[1].y = r.bottom;
+ v[1].Alpha = 0;
+
+ if (idx == d->c_alert) {
+ clr = GetSysColor(COLOR_HOTLIGHT);
+
+ clr2 = GetSysColor(COLOR_BTNHIGHLIGHT);
+ v[0].Red = MIX_C(GetRValue(clr), GetRValue(clr2), ALPHA);
+ v[0].Green = MIX_C(GetGValue(clr), GetGValue(clr2), ALPHA);
+ v[0].Blue = MIX_C(GetBValue(clr), GetBValue(clr2), ALPHA);
+
+ clr2 = GetSysColor(COLOR_BTNFACE);
+ v[1].Red = MIX_C(GetRValue(clr), GetRValue(clr2), ALPHA);
+ v[1].Green = MIX_C(GetGValue(clr), GetGValue(clr2), ALPHA);
+ v[1].Blue = MIX_C(GetBValue(clr), GetBValue(clr2), ALPHA);
+ } else {
+ clr = GetSysColor(COLOR_BTNHIGHLIGHT);
+ v[0].Red = ((int)GetRValue(clr)) << 8;
+ v[0].Green = ((int)GetGValue(clr)) << 8;
+ v[0].Blue = ((int)GetBValue(clr)) << 8;
+
+ clr = GetSysColor(COLOR_BTNFACE);
+ v[1].Red = ((int)GetRValue(clr)) << 8;
+ v[1].Green = ((int)GetGValue(clr)) << 8;
+ v[1].Blue = ((int)GetBValue(clr)) << 8;
+ }
+
+ gr.UpperLeft = 0;
+ gr.LowerRight = 1;
+ GradientFill(hdc, v, 2, &gr, 1, GRADIENT_FILL_RECT_V);
+ }
+#undef ALPHA
+#undef MIX_C
+#endif
+
+ a = adata->alert;
+#ifdef DEBUG
+ assert(a != NULL);
+#endif
+ khui_alert_lock(a);
+
+ if (!IsRectEmpty(&adata->r_title)) {
+
+ CopyRect(&r, &adata->r_title);
+ OffsetRect(&r, 0, y);
+
+ StringCchLength(a->title, KHUI_MAXCCH_TITLE, &len);
+
+ DrawEdge(hdc, &r, EDGE_RAISED, BF_RECT | BF_MIDDLE);
+
+ InflateRect(&r, -d->s_pad.cx, -d->s_pad.cy);
+
+ DrawText(hdc, a->title, (int) len, &r,
+ DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS);
+ }
+
+ {
+ HICON hicon;
+ int iid;
+
+ CopyRect(&r, &adata->r_icon);
+ OffsetRect(&r, 0, y);
+
+ if(a->severity == KHERR_ERROR)
+ iid = OIC_HAND;
+ else if(a->severity == KHERR_WARNING)
+ iid = OIC_BANG;
+ else
+ iid = OIC_NOTE;
+
+ hicon = (HICON) LoadImage(NULL,
+ MAKEINTRESOURCE(iid),
+ IMAGE_ICON,
+ GetSystemMetrics(SM_CXICON),
+ GetSystemMetrics(SM_CYICON),
+ LR_SHARED);
+
+ DrawIcon(hdc, r.left, r.top, hicon);
+ }
+
+ if (a->message) {
+
+ CopyRect(&r, &adata->r_message);
+ OffsetRect(&r, 0, y);
+
+ StringCchLength(a->message, KHUI_MAXCCH_MESSAGE, &len);
+
+ DrawText(hdc, a->message, (int) len, &r,
+ DT_WORDBREAK);
+ }
+
+ if (a->suggestion) {
+ HICON hicon;
+ SIZE sz;
+
+ CopyRect(&r, &adata->r_suggestion);
+ OffsetRect(&r, 0, y);
+
+ DrawEdge(hdc, &r, EDGE_SUNKEN, BF_RECT | BF_MIDDLE);
+
+ InflateRect(&r, -d->s_pad.cx, -d->s_pad.cy);
+
+ sz.cx = GetSystemMetrics(SM_CXSMICON);
+ sz.cy = GetSystemMetrics(SM_CYSMICON);
+
+ hicon = (HICON) LoadImage(NULL,
+ MAKEINTRESOURCE(OIC_NOTE),
+ IMAGE_ICON,
+ sz.cx,
+ sz.cy,
+ LR_SHARED);
+
+ DrawIconEx(hdc, r.left, r.top, hicon, sz.cx, sz.cy, 0, NULL,
+ DI_NORMAL);
+
+ r.left += d->s_pad.cx + GetSystemMetrics(SM_CXSMICON);
+
+ StringCchLength(a->suggestion, KHUI_MAXCCH_SUGGESTION, &len);
+
+ DrawText(hdc, a->suggestion, (int) len, &r,
+ DT_WORDBREAK);
+ }
+ khui_alert_unlock(a);
+
+ y += adata->r_alert.bottom;
+ idx++;
+
+ adata = QNEXT(adata);
+ }
+
+ SelectFont(hdc, hf_old);
+
+ if (!in_printclient) {
+ EndPaint(hwnd, &ps);
+ }
+ }
+ return 0;
+
+ case WM_VSCROLL:
+ {
+ alerter_wnd_data * d;
+ int new_pos = 0;
+ SCROLLINFO si;
+
+ d = (alerter_wnd_data *) (LONG_PTR) GetWindowLongPtr(hwnd, GWLP_USERDATA);
+#ifdef DEBUG
+ assert(d);
+#endif
+ if (d == NULL)
+ break; /* we can't handle the message */
+
+ ZeroMemory(&si, sizeof(si));
+
+ switch(LOWORD(wParam)) {
+ case SB_BOTTOM:
+ new_pos = d->s_alerts.cy - d->cy_max_wnd;
+ break;
+
+ case SB_LINEDOWN:
+ new_pos = d->scroll_top + SCROLL_LINE_SIZE(d);
+ break;
+
+ case SB_LINEUP:
+ new_pos = d->scroll_top - SCROLL_LINE_SIZE(d);
+ break;
+
+ case SB_PAGEDOWN:
+ new_pos = d->scroll_top + d->cy_max_wnd;
+ break;
+
+ case SB_PAGEUP:
+ new_pos = d->scroll_top - d->cy_max_wnd;
+ break;
+
+ case SB_THUMBPOSITION:
+ case SB_THUMBTRACK:
+ si.fMask = SIF_TRACKPOS;
+ GetScrollInfo(hwnd, SB_VERT, &si);
+ new_pos = si.nTrackPos;
+ break;
+
+ case SB_TOP:
+ new_pos = 0;
+ break;
+
+ case SB_ENDSCROLL:
+ si.fMask = SIF_POS;
+ si.nPos = d->scroll_top;
+ SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
+ return 0;
+
+ default:
+ return 0;
+ }
+
+ scroll_to_position(d, new_pos, FALSE);
+ }
+ return 0;
+
+ case WM_COMMAND:
+ {
+ alerter_wnd_data * d;
+
+ d = (alerter_wnd_data *) (LONG_PTR) GetWindowLongPtr(hwnd, GWLP_USERDATA);
+#ifdef DEBUG
+ assert(d);
+#endif
+ if (d == NULL)
+ break;
+
+ if (HIWORD(wParam) == BN_CLICKED) {
+ process_command_button(d, LOWORD(wParam));
+ return 0;
+ } else if (HIWORD(wParam) == BN_SETFOCUS) {
+ ensure_command_is_visible(d, LOWORD(wParam));
+ return 0;
+ }
+ }
+ break;
+
+ case WM_LBUTTONUP:
+ {
+ alerter_wnd_data * d;
+ int x,y;
+
+ d = (alerter_wnd_data *) (LONG_PTR) GetWindowLongPtr(hwnd, GWLP_USERDATA);
+#ifdef DEBUG
+ assert(d);
+#endif
+ if (d == NULL)
+ break;
+
+ x = GET_X_LPARAM(lParam);
+ y = GET_Y_LPARAM(lParam);
+
+ handle_mouse_select(d, x, y);
+ }
+ break;
+
+ case WM_SIZE:
+ {
+ InvalidateRect(hwnd, NULL, TRUE);
+ }
+ break;
+
+ case WM_DESTROY:
+ {
+ /* nothing needs to be done here */
+ }
+ return 0;
+ }
+
+ return DefWindowProc(hwnd, uMsg, wParam, lParam);
+}
+
+ATOM khm_register_alerter_wnd_class(void)
+{
+ WNDCLASSEX wcx;
+
+ ZeroMemory(&wcx, sizeof(wcx));
+
+ wcx.cbSize = sizeof(wcx);
+ wcx.style =
+ CS_OWNDC |
+#if(_WIN32_WINNT >= 0x0501)
+ ((IS_COMMCTL6())? CS_DROPSHADOW: 0) |
+#endif
+ 0;
+ wcx.lpfnWndProc = alerter_wnd_proc;
+ wcx.cbClsExtra = 0;
+ wcx.cbWndExtra = DLGWINDOWEXTRA + sizeof(LONG_PTR);
+ wcx.hInstance = khm_hInstance;
+ wcx.hIcon = LoadIcon(khm_hInstance, MAKEINTRESOURCE(IDI_MAIN_APP));
+ wcx.hCursor = LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW));
+ wcx.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
+ wcx.lpszMenuName = NULL;
+ wcx.lpszClassName = KHUI_ALERTER_CLASS;
+ wcx.hIconSm = NULL;
+
+ atom_alerter = RegisterClassEx(&wcx);
+
+ return atom_alerter;
+}
+
+ATOM khm_register_alert_bin_wnd_class(void)
+{
+ WNDCLASSEX wcx;
+
+ ZeroMemory(&wcx, sizeof(wcx));
+
+ wcx.cbSize = sizeof(wcx);
+ wcx.style = CS_OWNDC;
+
+ wcx.lpfnWndProc = alert_bin_wnd_proc;
+ wcx.cbClsExtra = 0;
+ wcx.cbWndExtra = sizeof(LONG_PTR);
+ wcx.hInstance = khm_hInstance;
+ wcx.hIcon = NULL;
+ wcx.hCursor = LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW));
+ wcx.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
+ wcx.lpszMenuName = NULL;
+ wcx.lpszClassName = KHUI_ALERTBIN_CLASS;
+ wcx.hIconSm = NULL;
+
+ atom_alert_bin = RegisterClassEx(&wcx);
+
+ return atom_alert_bin;
+}
+
+/**********************************************************************
+ Notification Icon
+***********************************************************************/
+
+#define KHUI_NOTIFY_ICON_ID 0
+
+void khm_notify_icon_add(void) {
+ NOTIFYICONDATA ni;
+ wchar_t buf[256];
+
+ ZeroMemory(&ni, sizeof(ni));
+
+ ni.cbSize = sizeof(ni);
+ ni.hWnd = hwnd_notifier;
+ ni.uID = KHUI_NOTIFY_ICON_ID;
+ ni.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
+ ni.hIcon = LoadIcon(khm_hInstance, MAKEINTRESOURCE(iid_normal));
+ ni.uCallbackMessage = KHUI_WM_NOTIFIER;
+ LoadString(khm_hInstance, IDS_NOTIFY_PREFIX, buf, ARRAYLENGTH(buf));
+ StringCbCopy(ni.szTip, sizeof(ni.szTip), buf);
+ LoadString(khm_hInstance, IDS_NOTIFY_READY, buf, ARRAYLENGTH(buf));
+ StringCbCat(ni.szTip, sizeof(ni.szTip), buf);
+
+ Shell_NotifyIcon(NIM_ADD, &ni);
+
+ DestroyIcon(ni.hIcon);
+
+ ni.cbSize = sizeof(ni);
+ ni.uVersion = NOTIFYICON_VERSION;
+ Shell_NotifyIcon(NIM_SETVERSION, &ni);
+}
+
+void
+khm_notify_icon_balloon(khm_int32 severity,
+ wchar_t * title,
+ wchar_t * msg,
+ khm_int32 timeout) {
+ NOTIFYICONDATA ni;
+ int iid;
+
+ if (!msg || !title)
+ return;
+
+ ZeroMemory(&ni, sizeof(ni));
+ ni.cbSize = sizeof(ni);
+
+ if (severity == KHERR_INFO) {
+ ni.dwInfoFlags = NIIF_INFO;
+ iid = IDI_NOTIFY_INFO;
+ } else if (severity == KHERR_WARNING) {
+ ni.dwInfoFlags = NIIF_WARNING;
+ iid = IDI_NOTIFY_WARN;
+ } else if (severity == KHERR_ERROR) {
+ ni.dwInfoFlags = NIIF_ERROR;
+ iid = IDI_NOTIFY_ERROR;
+ } else {
+ ni.dwInfoFlags = NIIF_NONE;
+ iid = iid_normal;
+ }
+
+ ni.hWnd = hwnd_notifier;
+ ni.uID = KHUI_NOTIFY_ICON_ID;
+ ni.uFlags = NIF_INFO | NIF_ICON;
+ ni.hIcon = LoadIcon(khm_hInstance, MAKEINTRESOURCE(iid));
+
+ if (FAILED(StringCbCopy(ni.szInfo, sizeof(ni.szInfo), msg))) {
+ /* too long? */
+ StringCchCopyN(ni.szInfo, ARRAYLENGTH(ni.szInfo),
+ msg,
+ ARRAYLENGTH(ni.szInfo) - ARRAYLENGTH(ELLIPSIS));
+ StringCchCat(ni.szInfo, ARRAYLENGTH(ni.szInfo),
+ ELLIPSIS);
+ }
+
+ if (FAILED(StringCbCopy(ni.szInfoTitle, sizeof(ni.szInfoTitle),
+ title))) {
+ StringCchCopyN(ni.szInfoTitle, ARRAYLENGTH(ni.szInfoTitle),
+ title,
+ ARRAYLENGTH(ni.szInfoTitle) - ARRAYLENGTH(ELLIPSIS));
+ StringCchCat(ni.szInfoTitle, ARRAYLENGTH(ni.szInfoTitle),
+ ELLIPSIS);
+ }
+
+ ni.uTimeout = timeout;
+
+ Shell_NotifyIcon(NIM_MODIFY, &ni);
+
+ DestroyIcon(ni.hIcon);
+}
+
+void khm_notify_icon_expstate(enum khm_notif_expstate expseverity) {
+ int new_iid;
+
+ if (expseverity == KHM_NOTIF_OK)
+ new_iid = IDI_APPICON_OK;
+ else if (expseverity == KHM_NOTIF_WARN)
+ new_iid = IDI_APPICON_WARN;
+ else if (expseverity == KHM_NOTIF_EXP)
+ new_iid = IDI_APPICON_EXP;
+ else
+ new_iid = IDI_NOTIFY_NONE;
+
+ if (iid_normal == new_iid)
+ return;
+
+ iid_normal = new_iid;
+
+ if (balloon_alert == NULL)
+ khm_notify_icon_change(KHERR_NONE);
+}
+
+void khm_notify_icon_change(khm_int32 severity) {
+ NOTIFYICONDATA ni;
+ wchar_t buf[256];
+ int iid;
+
+ if (severity == KHERR_INFO)
+ iid = IDI_NOTIFY_INFO;
+ else if (severity == KHERR_WARNING)
+ iid = IDI_NOTIFY_WARN;
+ else if (severity == KHERR_ERROR)
+ iid = IDI_NOTIFY_ERROR;
+ else
+ iid = iid_normal;
+
+ ZeroMemory(&ni, sizeof(ni));
+
+ ni.cbSize = sizeof(ni);
+ ni.hWnd = hwnd_notifier;
+ ni.uID = KHUI_NOTIFY_ICON_ID;
+ ni.uFlags = NIF_ICON | NIF_TIP;
+ ni.hIcon = LoadIcon(khm_hInstance, MAKEINTRESOURCE(iid));
+ LoadString(khm_hInstance, IDS_NOTIFY_PREFIX, buf, ARRAYLENGTH(buf));
+ StringCbCopy(ni.szTip, sizeof(ni.szTip), buf);
+ if(severity == KHERR_NONE)
+ LoadString(khm_hInstance, IDS_NOTIFY_READY, buf, ARRAYLENGTH(buf));
+ else
+ LoadString(khm_hInstance, IDS_NOTIFY_ATTENTION, buf, ARRAYLENGTH(buf));
+ StringCbCat(ni.szTip, sizeof(ni.szTip), buf);
+
+ Shell_NotifyIcon(NIM_MODIFY, &ni);
+
+ DestroyIcon(ni.hIcon);
+}
+
+void khm_notify_icon_remove(void) {
+ NOTIFYICONDATA ni;
+
+ ZeroMemory(&ni, sizeof(ni));
+
+ ni.cbSize = sizeof(ni);
+ ni.hWnd = hwnd_notifier;
+ ni.uID = KHUI_NOTIFY_ICON_ID;
+
+ Shell_NotifyIcon(NIM_DELETE, &ni);
+}
+
+static khm_int32
+get_default_notifier_action(void) {
+ khm_int32 def_cmd = KHUI_ACTION_OPEN_APP;
+ khm_handle csp_cw = NULL;
+ khm_size i;
+
+ if (KHM_FAILED(khc_open_space(NULL, L"CredWindow", KHM_PERM_READ,
+ &csp_cw)))
+ def_cmd;
+
+ khc_read_int32(csp_cw, L"NotificationAction", &def_cmd);
+
+ khc_close_space(csp_cw);
+
+ for (i=0; i < n_khm_notifier_actions; i++) {
+ if (khm_notifier_actions[i] == def_cmd)
+ break;
+ }
+
+ if (i < n_khm_notifier_actions)
+ return def_cmd;
+ else
+ return KHUI_ACTION_OPEN_APP;
+}
+
+void khm_notify_icon_activate(void) {
+ /* if there are any notifications waiting to be shown and there
+ are no alerts already being shown, we show them. Otherwise we
+ execute the default action. */
+
+ khm_notify_icon_change(KHERR_NONE);
+
+ if (balloon_alert != NULL && khui_alert_windows == NULL) {
+
+ khui_alert * a;
+ khm_boolean alert_done = FALSE;
+
+ a = balloon_alert;
+ balloon_alert = NULL;
+
+ khui_alert_lock(a);
+
+ a->displayed = FALSE;
+
+ if ((a->flags & KHUI_ALERT_FLAG_DEFACTION) &&
+ (a->n_alert_commands > 0)) {
+
+ PostMessage(khm_hwnd_main, WM_COMMAND,
+ MAKEWPARAM(a->alert_commands[0],
+ 0),
+ 0);
+ alert_done = TRUE;
+
+ } else if (a->flags & KHUI_ALERT_FLAG_REQUEST_WINDOW) {
+
+ alert_show_normal(a);
+ alert_done = TRUE;
+
+ }
+ khui_alert_unlock(a);
+ khui_alert_release(a);
+
+ if (alert_done)
+ return;
+ }
+
+ if (!is_alert_queue_empty() && !ALERT_DISPLAYED()) {
+
+ khm_show_main_window();
+ show_queued_alerts();
+
+ return;
+ }
+
+
+ /* if none of the above applied, then we perform the default
+ action for the notification icon. */
+ {
+ khm_int32 cmd = 0;
+
+ cmd = get_default_notifier_action();
+
+ if (cmd == KHUI_ACTION_OPEN_APP) {
+ if (khm_is_main_window_visible()) {
+ khm_hide_main_window();
+ } else {
+ khm_show_main_window();
+ }
+ } else {
+ khui_action_trigger(cmd, NULL);
+ }
+
+ check_for_queued_alerts();
+ }
+}
+
+/*********************************************************************
+ Initialization
+**********************************************************************/
+
+void khm_init_notifier(void)
+{
+ if(!khm_register_notifier_wnd_class())
+ return;
+
+ if(!khm_register_alerter_wnd_class())
+ return;
+
+ if(!khm_register_alert_bin_wnd_class())
+ return;
+
+ hwnd_notifier = CreateWindowEx(0,
+ MAKEINTATOM(atom_notifier),
+ KHUI_NOTIFIER_WINDOW,
+ 0,
+ 0,0,0,0,
+ HWND_MESSAGE,
+ NULL,
+ khm_hInstance,
+ NULL);
+
+ if(hwnd_notifier != NULL) {
+ kmq_subscribe_hwnd(KMSG_ALERT, hwnd_notifier);
+ kmq_subscribe_hwnd(KMSG_CRED, hwnd_notifier);
+ notifier_ready = TRUE;
+
+ khm_notify_icon_add();
+ } else {
+#ifdef DEBUG
+ assert(hwnd_notifier != NULL);
+#endif
+ }
+ khm_timer_init();
+
+ khm_addr_change_notifier_init();
+}
+
+void khm_exit_notifier(void)
+{
+ khm_addr_change_notifier_exit();
+
+ khm_timer_exit();
+
+ if(hwnd_notifier != NULL) {
+ khm_notify_icon_remove();
+ kmq_unsubscribe_hwnd(KMSG_ALERT, hwnd_notifier);
+ kmq_unsubscribe_hwnd(KMSG_CRED, hwnd_notifier);
+ DestroyWindow(hwnd_notifier);
+ hwnd_notifier = NULL;
+ }
+
+ if(atom_notifier != 0) {
+ UnregisterClass(MAKEINTATOM(atom_notifier), khm_hInstance);
+ atom_notifier = 0;
+ }
+
+ if(atom_alerter != 0) {
+ UnregisterClass(MAKEINTATOM(atom_alerter), khm_hInstance);
+ atom_alerter = 0;
+ }
+
+ if(atom_alert_bin != 0) {
+ UnregisterClass(MAKEINTATOM(atom_alert_bin), khm_hInstance);
+ atom_alert_bin = 0;
+ }
+
+ notifier_ready = FALSE;
+}
+
+/***** testing *****/
+
+void
+create_test_alerts(void) {
+
+ khui_alert * a;
+ int i;
+
+ for (i=0; i < 50; i++) {
+ wchar_t buf[128];
+
+ StringCbPrintf(buf, sizeof(buf), L"Foo bar baz. This is alert number %d", i);
+ khui_alert_create_simple(L"Title", buf, KHERR_INFO, &a);
+ khui_alert_set_type(a, KHUI_ALERTTYPE_PLUGIN);
+ khui_alert_set_suggestion(a, L"This is a suggestion. It is kinda long to see if the word wrapping actually works as we expect it to. Just in case, here's a line feed.\n\nDoes this show up on a different line? Cool!");
+
+ khui_alert_add_command(a, KHUI_ACTION_NEW_CRED);
+ khui_alert_add_command(a, KHUI_ACTION_CLOSE_APP);
+ khui_alert_add_command(a, KHUI_ACTION_PROPERTIES);
+ khui_alert_add_command(a, KHUI_ACTION_OPEN_APP);
+ khui_alert_add_command(a, KHUI_ACTION_VIEW_REFRESH);
+
+ khui_alert_show(a);
+ khui_alert_release(a);
+ }
+}
diff --git a/src/windows/identity/ui/notifier.h b/src/windows/identity/ui/notifier.h
index a42e63f1fe..b0cd5dc2c8 100644
--- a/src/windows/identity/ui/notifier.h
+++ b/src/windows/identity/ui/notifier.h
@@ -1,63 +1,63 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#ifndef __KHIMAIRA_NOTIFIER_H
-#define __KHIMAIRA_NOTIFIER_H
-
-extern HWND hwnd_notifier;
-
-enum khm_notif_expstate {
- KHM_NOTIF_EMPTY,
- KHM_NOTIF_OK,
- KHM_NOTIF_WARN,
- KHM_NOTIF_EXP
-};
-
-extern khm_int32 khm_notifier_actions[];
-extern khm_size n_khm_notifier_actions;
-
-void
-khm_init_notifier(void);
-
-void
-khm_exit_notifier(void);
-
-void
-khm_notify_icon_change(khm_int32 severity);
-
-void
-khm_notify_icon_balloon(khm_int32 severity,
- wchar_t * title,
- wchar_t * msg,
- khm_int32 timeout);
-
-void
-khm_notify_icon_expstate(enum khm_notif_expstate expseverity);
-
-void
-khm_notify_icon_activate(void);
-
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __KHIMAIRA_NOTIFIER_H
+#define __KHIMAIRA_NOTIFIER_H
+
+extern HWND hwnd_notifier;
+
+enum khm_notif_expstate {
+ KHM_NOTIF_EMPTY,
+ KHM_NOTIF_OK,
+ KHM_NOTIF_WARN,
+ KHM_NOTIF_EXP
+};
+
+extern khm_int32 khm_notifier_actions[];
+extern khm_size n_khm_notifier_actions;
+
+void
+khm_init_notifier(void);
+
+void
+khm_exit_notifier(void);
+
+void
+khm_notify_icon_change(khm_int32 severity);
+
+void
+khm_notify_icon_balloon(khm_int32 severity,
+ wchar_t * title,
+ wchar_t * msg,
+ khm_int32 timeout);
+
+void
+khm_notify_icon_expstate(enum khm_notif_expstate expseverity);
+
+void
+khm_notify_icon_activate(void);
+
+#endif
diff --git a/src/windows/identity/ui/passwnd.c b/src/windows/identity/ui/passwnd.c
index 4084ede413..65cc06fe76 100644
--- a/src/windows/identity/ui/passwnd.c
+++ b/src/windows/identity/ui/passwnd.c
@@ -1,133 +1,133 @@
-#include<khmapp.h>
-
-static ATOM sAtom = 0;
-static HINSTANCE shInstance = 0;
-
-/* Callback for the MITPasswordControl
-This is a replacement for the normal edit control. It does not show the
-annoying password char in the edit box so that the number of chars in the
-password are not known.
-*/
-
-#define PASSWORDCHAR L'#'
-#define DLGHT(ht) (HIWORD(GetDialogBaseUnits())*(ht)/8)
-#define DLGWD(wd) (LOWORD(GetDialogBaseUnits())*(wd)/4)
-
-static
-LRESULT
-CALLBACK
-MITPasswordEditProc(
- HWND hWnd,
- UINT message,
- WPARAM wParam,
- LPARAM lParam
- )
-{
- static SIZE pwdcharsz;
- BOOL pass_the_buck = FALSE;
-
- if (message > WM_USER && message < 0x7FFF)
- pass_the_buck = TRUE;
-
- switch(message)
- {
- case WM_GETTEXT:
- case WM_GETTEXTLENGTH:
- case WM_SETTEXT:
- pass_the_buck = TRUE;
- break;
- case WM_PAINT:
- {
- HDC hdc;
- PAINTSTRUCT ps;
- RECT r;
-
- hdc = BeginPaint(hWnd, &ps);
- GetClientRect(hWnd, &r);
- Rectangle(hdc, 0, 0, r.right, r.bottom);
- EndPaint(hWnd, &ps);
- }
- break;
- case WM_SIZE:
- {
- MoveWindow(GetDlgItem(hWnd, 1), DLGWD(2), DLGHT(2),
- pwdcharsz.cx / 2, pwdcharsz.cy, TRUE);
- }
- break;
- case WM_LBUTTONDOWN:
- case WM_SETFOCUS:
- {
- SetFocus(GetDlgItem(hWnd, 1));
- }
- break;
- case WM_CREATE:
- {
- HWND heditchild;
- wchar_t pwdchar = PASSWORDCHAR;
- HDC hdc;
- /* Create a child window of this control for default processing. */
- hdc = GetDC(hWnd);
- GetTextExtentPoint32(hdc, &pwdchar, 1, &pwdcharsz);
- ReleaseDC(hWnd, hdc);
-
- heditchild =
- CreateWindow(L"edit", L"", WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL |
- ES_LEFT | ES_PASSWORD | WS_TABSTOP,
- 0, 0, 0, 0,
- hWnd,
- (HMENU)1,
- ((LPCREATESTRUCT)lParam)->hInstance,
- NULL);
- SendMessage(heditchild, EM_SETPASSWORDCHAR, PASSWORDCHAR, 0L);
- }
- break;
- }
-
- if (pass_the_buck)
- return SendMessage(GetDlgItem(hWnd, 1), message, wParam, lParam);
- return DefWindowProc(hWnd, message, wParam, lParam);
-}
-
-khm_int32
-khm_register_passwnd_class(void)
-{
- if (!sAtom) {
- WNDCLASS wndclass;
-
- memset(&wndclass, 0, sizeof(WNDCLASS));
-
- shInstance = khm_hInstance;
-
- wndclass.style = CS_HREDRAW | CS_VREDRAW;
- wndclass.lpfnWndProc = (WNDPROC)MITPasswordEditProc;
- wndclass.cbClsExtra = sizeof(HWND);
- wndclass.cbWndExtra = 0;
- wndclass.hInstance = shInstance;
- wndclass.hbrBackground = (void *)(COLOR_WINDOW + 1);
- wndclass.lpszClassName = MIT_PWD_DLL_CLASS;
- wndclass.hCursor = LoadCursor((HINSTANCE)NULL, IDC_IBEAM);
-
- sAtom = RegisterClass(&wndclass);
- }
-
- return (sAtom)?KHM_ERROR_SUCCESS:KHM_ERROR_UNKNOWN;
-}
-
-khm_int32
-khm_unregister_passwnd_class(void)
-{
- BOOL result = TRUE;
-
- if ((khm_hInstance != shInstance) || !sAtom) {
- return KHM_ERROR_INVALID_OPERATION;
- }
-
- result = UnregisterClass(MIT_PWD_DLL_CLASS, khm_hInstance);
- if (result) {
- sAtom = 0;
- shInstance = 0;
- return KHM_ERROR_SUCCESS;
- } else {
- return KHM_ERROR_UNKNOWN;
- }
-}
+#include<khmapp.h>
+
+static ATOM sAtom = 0;
+static HINSTANCE shInstance = 0;
+
+/* Callback for the MITPasswordControl
+This is a replacement for the normal edit control. It does not show the
+annoying password char in the edit box so that the number of chars in the
+password are not known.
+*/
+
+#define PASSWORDCHAR L'#'
+#define DLGHT(ht) (HIWORD(GetDialogBaseUnits())*(ht)/8)
+#define DLGWD(wd) (LOWORD(GetDialogBaseUnits())*(wd)/4)
+
+static
+LRESULT
+CALLBACK
+MITPasswordEditProc(
+ HWND hWnd,
+ UINT message,
+ WPARAM wParam,
+ LPARAM lParam
+ )
+{
+ static SIZE pwdcharsz;
+ BOOL pass_the_buck = FALSE;
+
+ if (message > WM_USER && message < 0x7FFF)
+ pass_the_buck = TRUE;
+
+ switch(message)
+ {
+ case WM_GETTEXT:
+ case WM_GETTEXTLENGTH:
+ case WM_SETTEXT:
+ pass_the_buck = TRUE;
+ break;
+ case WM_PAINT:
+ {
+ HDC hdc;
+ PAINTSTRUCT ps;
+ RECT r;
+
+ hdc = BeginPaint(hWnd, &ps);
+ GetClientRect(hWnd, &r);
+ Rectangle(hdc, 0, 0, r.right, r.bottom);
+ EndPaint(hWnd, &ps);
+ }
+ break;
+ case WM_SIZE:
+ {
+ MoveWindow(GetDlgItem(hWnd, 1), DLGWD(2), DLGHT(2),
+ pwdcharsz.cx / 2, pwdcharsz.cy, TRUE);
+ }
+ break;
+ case WM_LBUTTONDOWN:
+ case WM_SETFOCUS:
+ {
+ SetFocus(GetDlgItem(hWnd, 1));
+ }
+ break;
+ case WM_CREATE:
+ {
+ HWND heditchild;
+ wchar_t pwdchar = PASSWORDCHAR;
+ HDC hdc;
+ /* Create a child window of this control for default processing. */
+ hdc = GetDC(hWnd);
+ GetTextExtentPoint32(hdc, &pwdchar, 1, &pwdcharsz);
+ ReleaseDC(hWnd, hdc);
+
+ heditchild =
+ CreateWindow(L"edit", L"", WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL |
+ ES_LEFT | ES_PASSWORD | WS_TABSTOP,
+ 0, 0, 0, 0,
+ hWnd,
+ (HMENU)1,
+ ((LPCREATESTRUCT)lParam)->hInstance,
+ NULL);
+ SendMessage(heditchild, EM_SETPASSWORDCHAR, PASSWORDCHAR, 0L);
+ }
+ break;
+ }
+
+ if (pass_the_buck)
+ return SendMessage(GetDlgItem(hWnd, 1), message, wParam, lParam);
+ return DefWindowProc(hWnd, message, wParam, lParam);
+}
+
+khm_int32
+khm_register_passwnd_class(void)
+{
+ if (!sAtom) {
+ WNDCLASS wndclass;
+
+ memset(&wndclass, 0, sizeof(WNDCLASS));
+
+ shInstance = khm_hInstance;
+
+ wndclass.style = CS_HREDRAW | CS_VREDRAW;
+ wndclass.lpfnWndProc = (WNDPROC)MITPasswordEditProc;
+ wndclass.cbClsExtra = sizeof(HWND);
+ wndclass.cbWndExtra = 0;
+ wndclass.hInstance = shInstance;
+ wndclass.hbrBackground = (void *)(COLOR_WINDOW + 1);
+ wndclass.lpszClassName = MIT_PWD_DLL_CLASS;
+ wndclass.hCursor = LoadCursor((HINSTANCE)NULL, IDC_IBEAM);
+
+ sAtom = RegisterClass(&wndclass);
+ }
+
+ return (sAtom)?KHM_ERROR_SUCCESS:KHM_ERROR_UNKNOWN;
+}
+
+khm_int32
+khm_unregister_passwnd_class(void)
+{
+ BOOL result = TRUE;
+
+ if ((khm_hInstance != shInstance) || !sAtom) {
+ return KHM_ERROR_INVALID_OPERATION;
+ }
+
+ result = UnregisterClass(MIT_PWD_DLL_CLASS, khm_hInstance);
+ if (result) {
+ sAtom = 0;
+ shInstance = 0;
+ return KHM_ERROR_SUCCESS;
+ } else {
+ return KHM_ERROR_UNKNOWN;
+ }
+}
diff --git a/src/windows/identity/ui/passwnd.h b/src/windows/identity/ui/passwnd.h
index b0adcf6893..c3ab8ef314 100644
--- a/src/windows/identity/ui/passwnd.h
+++ b/src/windows/identity/ui/passwnd.h
@@ -1,39 +1,39 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#ifndef __KHIMAIRA_PASSWND_H
-#define __KHIMAIRA_PASSWND_H
-
-/* Declarations for the MIT password change control. Functionally the
- same as the regular Windows password edit control but doesn't
- display the '*' password character. */
-
-#define MIT_PWD_DLL_CLASS L"MITPasswordWnd"
-
-khm_int32 khm_unregister_passwnd_class(void);
-khm_int32 khm_register_passwnd_class(void);
-
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __KHIMAIRA_PASSWND_H
+#define __KHIMAIRA_PASSWND_H
+
+/* Declarations for the MIT password change control. Functionally the
+ same as the regular Windows password edit control but doesn't
+ display the '*' password character. */
+
+#define MIT_PWD_DLL_CLASS L"MITPasswordWnd"
+
+khm_int32 khm_unregister_passwnd_class(void);
+khm_int32 khm_register_passwnd_class(void);
+
+#endif
diff --git a/src/windows/identity/ui/propertywnd.c b/src/windows/identity/ui/propertywnd.c
index 4061cd78d2..4255b481be 100644
--- a/src/windows/identity/ui/propertywnd.c
+++ b/src/windows/identity/ui/propertywnd.c
@@ -1,248 +1,248 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<khmapp.h>
-#include<assert.h>
-
-typedef struct tag_pw_data {
- khm_handle record;
- HWND hwnd_lv;
-} pw_data;
-
-ATOM khui_propertywnd_cls;
-
-#define ID_LISTVIEW 1
-
-#define PW_WM_SET_RECORD WM_USER
-
-void pw_update_property_data(HWND hw, pw_data * d)
-{
- HWND hwnd_lv;
- khm_int32 * attrs = NULL;
-
- hwnd_lv = d->hwnd_lv;
-
- if(hwnd_lv == NULL)
- return;
-
- ListView_DeleteAllItems(hwnd_lv);
-
- if(d->record != NULL) {
- wchar_t * buffer;
- khm_size attr_count;
- khm_size i;
- khm_size cb_buf;
- khm_size t;
- LVITEM lvi;
- int idx;
-
- if(KHM_FAILED(kcdb_attrib_get_count(
- KCDB_ATTR_FLAG_VOLATILE |
- KCDB_ATTR_FLAG_HIDDEN,
- 0,
- &attr_count)))
- return;
-
- attrs = PMALLOC(sizeof(khm_int32) * attr_count);
- assert(attrs != NULL);
-
- kcdb_attrib_get_ids(
- KCDB_ATTR_FLAG_VOLATILE |
- KCDB_ATTR_FLAG_HIDDEN,
- 0,
- attrs,
- &attr_count);
-
- cb_buf = sizeof(wchar_t) * 2048;
- buffer = PMALLOC(cb_buf);
- assert(buffer != NULL);
-
- for(i=0; i<attr_count; i++) {
- if(KHM_FAILED(kcdb_buf_get_attr(d->record, attrs[i], NULL, NULL, NULL)))
- continue;
-
- ZeroMemory(&lvi, sizeof(lvi));
- lvi.mask = LVIF_TEXT | LVIF_PARAM;
- lvi.iItem = (int) i;
- lvi.iSubItem = 0;
- lvi.pszText = buffer;
- lvi.lParam = (LPARAM) attrs[i];
-
- t = cb_buf;
- kcdb_attrib_describe(attrs[i], buffer, &t, KCDB_TS_SHORT);
-
- idx = ListView_InsertItem(hwnd_lv, &lvi);
-
- ZeroMemory(&lvi, sizeof(lvi));
- lvi.mask = LVIF_TEXT;
- lvi.iItem = idx;
- lvi.iSubItem = 1;
- lvi.pszText = buffer;
-
- t = cb_buf;
- kcdb_buf_get_attr_string(d->record, attrs[i], buffer, &t, 0);
-
- ListView_SetItem(hwnd_lv, &lvi);
- }
-
- PFREE(attrs);
- PFREE(buffer);
- }
-}
-
-LRESULT CALLBACK khui_property_wnd_proc(
- HWND hwnd,
- UINT msg,
- WPARAM wParam,
- LPARAM lParam)
-{
- BOOL child_msg = FALSE;
- pw_data * child;
-
- switch(msg) {
- case WM_CREATE:
- {
- CREATESTRUCT * cs;
- LVCOLUMN lvc;
- wchar_t sz_title[256];
-
- cs = (CREATESTRUCT *) lParam;
-
- child = PMALLOC(sizeof(*child));
- ZeroMemory(child, sizeof(*child));
-
-#pragma warning(push)
-#pragma warning(disable:4244)
- SetWindowLongPtr(hwnd, 0, (LONG_PTR) child);
-#pragma warning(pop)
-
- child->hwnd_lv = CreateWindow(
- WC_LISTVIEW,
- L"",
- WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL |
- LVS_REPORT | LVS_SORTASCENDING,
- 0, 0,
- cs->cx, cs->cy,
- hwnd,
- (HMENU) ID_LISTVIEW,
- khm_hInstance,
- NULL);
-
- ListView_SetExtendedListViewStyle(child->hwnd_lv,
- LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);
-
- ZeroMemory(&lvc, sizeof(lvc));
- lvc.mask = LVCF_FMT | LVCF_ORDER | LVCF_TEXT | LVCF_WIDTH;
- lvc.fmt = LVCFMT_LEFT;
- lvc.cx = (cs->cx * 2)/ 5;
- lvc.pszText = sz_title;
- lvc.iSubItem = 0;
- lvc.iOrder = 0;
- LoadString(khm_hInstance, IDS_PROP_COL_PROPERTY, sz_title, ARRAYLENGTH(sz_title));
-
- ListView_InsertColumn(child->hwnd_lv, 0, &lvc);
-
- ZeroMemory(&lvc, sizeof(lvc));
- lvc.mask = LVCF_FMT | LVCF_ORDER | LVCF_SUBITEM | LVCF_TEXT | LVCF_WIDTH;
- lvc.fmt = LVCFMT_LEFT;
- lvc.cx = (cs->cx * 3)/ 5;
- lvc.pszText = sz_title;
- lvc.iSubItem = 1;
- lvc.iOrder = 1;
- LoadString(khm_hInstance, IDS_PROP_COL_VALUE, sz_title, ARRAYLENGTH(sz_title));
-
- ListView_InsertColumn(child->hwnd_lv, 1, &lvc);
-
- if(cs->lpCreateParams != NULL) {
- child->record = cs->lpCreateParams;
- kcdb_buf_hold(child->record);
- pw_update_property_data(hwnd, child);
- }
- }
- break;
-
- case PW_WM_SET_RECORD:
- {
- child = (pw_data *)(LONG_PTR) GetWindowLongPtr(hwnd, 0);
- kcdb_buf_release(child->record);
- child->record = (khm_handle) lParam;
- kcdb_buf_hold(child->record);
- pw_update_property_data(hwnd, child);
- }
- return 0;
-
- case WM_DESTROY:
- {
- child = (pw_data *)(LONG_PTR) GetWindowLongPtr(hwnd, 0);
- kcdb_buf_release(child->record);
- PFREE(child);
- }
- break;
-
- case WM_PAINT:
- break;
-
- default:
- child = (pw_data *)(LONG_PTR) GetWindowLongPtr(hwnd, 0);
- child_msg = TRUE;
- }
-
- /*
- if(child_msg && child && child->hwnd_lv)
- return SendMessage(child->hwnd_lv, msg, wParam, lParam);
- else
- */
- return DefWindowProc(hwnd, msg, wParam, lParam);
-}
-
-khm_int32 khm_register_propertywnd_class(void)
-{
- WNDCLASSEX wcx;
-
- wcx.cbSize = sizeof(wcx);
- wcx.style = CS_DBLCLKS;
- wcx.lpfnWndProc = khui_property_wnd_proc;
- wcx.cbClsExtra = 0;
- wcx.cbWndExtra = sizeof(LONG_PTR);
- wcx.hInstance = khm_hInstance;
- wcx.hIcon = NULL;
- wcx.hCursor = LoadCursor((HINSTANCE) NULL, IDC_ARROW);
- wcx.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1);
- wcx.lpszMenuName = NULL;
- wcx.lpszClassName = KHUI_PROPERTYWND_CLASS_NAME;
- wcx.hIconSm = NULL;
-
- khui_propertywnd_cls = RegisterClassEx(&wcx);
-
- return (khui_propertywnd_cls == 0)?KHM_ERROR_UNKNOWN:KHM_ERROR_SUCCESS;
-}
-
-khm_int32 khm_unregister_propertywnd_class(void)
-{
- UnregisterClass(MAKEINTATOM(khui_propertywnd_cls), khm_hInstance);
-
- return KHM_ERROR_SUCCESS;
-}
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<khmapp.h>
+#include<assert.h>
+
+typedef struct tag_pw_data {
+ khm_handle record;
+ HWND hwnd_lv;
+} pw_data;
+
+ATOM khui_propertywnd_cls;
+
+#define ID_LISTVIEW 1
+
+#define PW_WM_SET_RECORD WM_USER
+
+void pw_update_property_data(HWND hw, pw_data * d)
+{
+ HWND hwnd_lv;
+ khm_int32 * attrs = NULL;
+
+ hwnd_lv = d->hwnd_lv;
+
+ if(hwnd_lv == NULL)
+ return;
+
+ ListView_DeleteAllItems(hwnd_lv);
+
+ if(d->record != NULL) {
+ wchar_t * buffer;
+ khm_size attr_count;
+ khm_size i;
+ khm_size cb_buf;
+ khm_size t;
+ LVITEM lvi;
+ int idx;
+
+ if(KHM_FAILED(kcdb_attrib_get_count(
+ KCDB_ATTR_FLAG_VOLATILE |
+ KCDB_ATTR_FLAG_HIDDEN,
+ 0,
+ &attr_count)))
+ return;
+
+ attrs = PMALLOC(sizeof(khm_int32) * attr_count);
+ assert(attrs != NULL);
+
+ kcdb_attrib_get_ids(
+ KCDB_ATTR_FLAG_VOLATILE |
+ KCDB_ATTR_FLAG_HIDDEN,
+ 0,
+ attrs,
+ &attr_count);
+
+ cb_buf = sizeof(wchar_t) * 2048;
+ buffer = PMALLOC(cb_buf);
+ assert(buffer != NULL);
+
+ for(i=0; i<attr_count; i++) {
+ if(KHM_FAILED(kcdb_buf_get_attr(d->record, attrs[i], NULL, NULL, NULL)))
+ continue;
+
+ ZeroMemory(&lvi, sizeof(lvi));
+ lvi.mask = LVIF_TEXT | LVIF_PARAM;
+ lvi.iItem = (int) i;
+ lvi.iSubItem = 0;
+ lvi.pszText = buffer;
+ lvi.lParam = (LPARAM) attrs[i];
+
+ t = cb_buf;
+ kcdb_attrib_describe(attrs[i], buffer, &t, KCDB_TS_SHORT);
+
+ idx = ListView_InsertItem(hwnd_lv, &lvi);
+
+ ZeroMemory(&lvi, sizeof(lvi));
+ lvi.mask = LVIF_TEXT;
+ lvi.iItem = idx;
+ lvi.iSubItem = 1;
+ lvi.pszText = buffer;
+
+ t = cb_buf;
+ kcdb_buf_get_attr_string(d->record, attrs[i], buffer, &t, 0);
+
+ ListView_SetItem(hwnd_lv, &lvi);
+ }
+
+ PFREE(attrs);
+ PFREE(buffer);
+ }
+}
+
+LRESULT CALLBACK khui_property_wnd_proc(
+ HWND hwnd,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ BOOL child_msg = FALSE;
+ pw_data * child;
+
+ switch(msg) {
+ case WM_CREATE:
+ {
+ CREATESTRUCT * cs;
+ LVCOLUMN lvc;
+ wchar_t sz_title[256];
+
+ cs = (CREATESTRUCT *) lParam;
+
+ child = PMALLOC(sizeof(*child));
+ ZeroMemory(child, sizeof(*child));
+
+#pragma warning(push)
+#pragma warning(disable:4244)
+ SetWindowLongPtr(hwnd, 0, (LONG_PTR) child);
+#pragma warning(pop)
+
+ child->hwnd_lv = CreateWindow(
+ WC_LISTVIEW,
+ L"",
+ WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL |
+ LVS_REPORT | LVS_SORTASCENDING,
+ 0, 0,
+ cs->cx, cs->cy,
+ hwnd,
+ (HMENU) ID_LISTVIEW,
+ khm_hInstance,
+ NULL);
+
+ ListView_SetExtendedListViewStyle(child->hwnd_lv,
+ LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);
+
+ ZeroMemory(&lvc, sizeof(lvc));
+ lvc.mask = LVCF_FMT | LVCF_ORDER | LVCF_TEXT | LVCF_WIDTH;
+ lvc.fmt = LVCFMT_LEFT;
+ lvc.cx = (cs->cx * 2)/ 5;
+ lvc.pszText = sz_title;
+ lvc.iSubItem = 0;
+ lvc.iOrder = 0;
+ LoadString(khm_hInstance, IDS_PROP_COL_PROPERTY, sz_title, ARRAYLENGTH(sz_title));
+
+ ListView_InsertColumn(child->hwnd_lv, 0, &lvc);
+
+ ZeroMemory(&lvc, sizeof(lvc));
+ lvc.mask = LVCF_FMT | LVCF_ORDER | LVCF_SUBITEM | LVCF_TEXT | LVCF_WIDTH;
+ lvc.fmt = LVCFMT_LEFT;
+ lvc.cx = (cs->cx * 3)/ 5;
+ lvc.pszText = sz_title;
+ lvc.iSubItem = 1;
+ lvc.iOrder = 1;
+ LoadString(khm_hInstance, IDS_PROP_COL_VALUE, sz_title, ARRAYLENGTH(sz_title));
+
+ ListView_InsertColumn(child->hwnd_lv, 1, &lvc);
+
+ if(cs->lpCreateParams != NULL) {
+ child->record = cs->lpCreateParams;
+ kcdb_buf_hold(child->record);
+ pw_update_property_data(hwnd, child);
+ }
+ }
+ break;
+
+ case PW_WM_SET_RECORD:
+ {
+ child = (pw_data *)(LONG_PTR) GetWindowLongPtr(hwnd, 0);
+ kcdb_buf_release(child->record);
+ child->record = (khm_handle) lParam;
+ kcdb_buf_hold(child->record);
+ pw_update_property_data(hwnd, child);
+ }
+ return 0;
+
+ case WM_DESTROY:
+ {
+ child = (pw_data *)(LONG_PTR) GetWindowLongPtr(hwnd, 0);
+ kcdb_buf_release(child->record);
+ PFREE(child);
+ }
+ break;
+
+ case WM_PAINT:
+ break;
+
+ default:
+ child = (pw_data *)(LONG_PTR) GetWindowLongPtr(hwnd, 0);
+ child_msg = TRUE;
+ }
+
+ /*
+ if(child_msg && child && child->hwnd_lv)
+ return SendMessage(child->hwnd_lv, msg, wParam, lParam);
+ else
+ */
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+}
+
+khm_int32 khm_register_propertywnd_class(void)
+{
+ WNDCLASSEX wcx;
+
+ wcx.cbSize = sizeof(wcx);
+ wcx.style = CS_DBLCLKS;
+ wcx.lpfnWndProc = khui_property_wnd_proc;
+ wcx.cbClsExtra = 0;
+ wcx.cbWndExtra = sizeof(LONG_PTR);
+ wcx.hInstance = khm_hInstance;
+ wcx.hIcon = NULL;
+ wcx.hCursor = LoadCursor((HINSTANCE) NULL, IDC_ARROW);
+ wcx.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1);
+ wcx.lpszMenuName = NULL;
+ wcx.lpszClassName = KHUI_PROPERTYWND_CLASS_NAME;
+ wcx.hIconSm = NULL;
+
+ khui_propertywnd_cls = RegisterClassEx(&wcx);
+
+ return (khui_propertywnd_cls == 0)?KHM_ERROR_UNKNOWN:KHM_ERROR_SUCCESS;
+}
+
+khm_int32 khm_unregister_propertywnd_class(void)
+{
+ UnregisterClass(MAKEINTATOM(khui_propertywnd_cls), khm_hInstance);
+
+ return KHM_ERROR_SUCCESS;
+}
diff --git a/src/windows/identity/ui/propertywnd.h b/src/windows/identity/ui/propertywnd.h
index 89305dd7ba..c4a738eafc 100644
--- a/src/windows/identity/ui/propertywnd.h
+++ b/src/windows/identity/ui/propertywnd.h
@@ -1,36 +1,36 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#ifndef __KHIMAIRA_PROPERTYWND_H
-#define __KHIMAIRA_PROPERTYWND_H
-
-#define KHUI_PROPERTYWND_CLASS_NAME L"NetIDMgrPropertyWnd"
-
-khm_int32 khm_register_propertywnd_class(void);
-
-khm_int32 khm_unregister_propertywnd_class(void);
-
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __KHIMAIRA_PROPERTYWND_H
+#define __KHIMAIRA_PROPERTYWND_H
+
+#define KHUI_PROPERTYWND_CLASS_NAME L"NetIDMgrPropertyWnd"
+
+khm_int32 khm_register_propertywnd_class(void);
+
+khm_int32 khm_unregister_propertywnd_class(void);
+
+#endif
diff --git a/src/windows/identity/ui/reqdaemon.c b/src/windows/identity/ui/reqdaemon.c
index e72e3e22b8..20b126e275 100644
--- a/src/windows/identity/ui/reqdaemon.c
+++ b/src/windows/identity/ui/reqdaemon.c
@@ -1,453 +1,453 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- * Copyright (c) 2007 Secure Endpoints Inc.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<khmapp.h>
-#include<assert.h>
-
-ATOM reqdaemon_atom = 0;
-HANDLE reqdaemon_thread = NULL;
-HWND reqdaemon_hwnd = NULL;
-
-LRESULT CALLBACK
-reqdaemonwnd_proc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam) {
-
- switch(uMsg) {
- case WM_CREATE:
- break;
-
- case WM_CLOSE:
- DestroyWindow(hwnd);
- break;
-
- case WM_DESTROY:
- reqdaemon_hwnd = NULL;
- PostQuitMessage(0);
- break;
-
- /* Leash compatibility */
- case ID_OBTAIN_TGT_WITH_LPARAM:
- {
- wchar_t widname[KCDB_IDENT_MAXCCH_NAME];
- wchar_t wmapping[ARRAYLENGTH(KHUI_REQD_MAPPING_FORMAT) + 10];
- khm_handle identity = NULL;
- LPNETID_DLGINFO pdlginfo;
- LRESULT lr = 1;
- khm_int32 result;
- HANDLE hmap = NULL;
- HRESULT hr;
-
- hr = StringCbPrintf(wmapping, sizeof(wmapping),
- KHUI_REQD_MAPPING_FORMAT, (DWORD) lParam);
-#ifdef DEBUG
- assert(SUCCEEDED(hr));
-#endif
- hmap = CreateFileMapping(INVALID_HANDLE_VALUE,
- NULL,
- PAGE_READWRITE,
- 0, 4096,
- wmapping);
-
- if (hmap == NULL) {
- return -1;
- } else if (hmap != NULL && GetLastError() != ERROR_ALREADY_EXISTS) {
- CloseHandle(hmap);
- return -1;
- }
-
- pdlginfo = MapViewOfFile(hmap,
- FILE_MAP_WRITE,
- 0, 0,
- sizeof(*pdlginfo));
-
- if (pdlginfo == NULL) {
- CloseHandle(hmap);
- return 1;
- }
-
- if (pdlginfo->in.username[0] &&
- pdlginfo->in.realm[0] &&
- SUCCEEDED(StringCbPrintf(widname,
- sizeof(widname),
- L"%s@%s",
- pdlginfo->in.username,
- pdlginfo->in.realm))) {
-
- kcdb_identity_create(widname,
- KCDB_IDENT_FLAG_CREATE,
- &identity);
- }
-
- widname[0] = 0;
-
- do {
- if (khm_cred_is_in_dialog()) {
- khm_cred_wait_for_dialog(INFINITE, NULL, NULL, 0);
- }
-
- if (identity)
- khui_context_set_ex(KHUI_SCOPE_IDENT,
- identity,
- KCDB_CREDTYPE_INVALID,
- NULL,
- NULL,
- 0,
- NULL,
- pdlginfo,
- sizeof(*pdlginfo));
- else
- khui_context_reset();
-
- if (pdlginfo->dlgtype == NETID_DLGTYPE_TGT)
- SendMessage(khm_hwnd_main, WM_COMMAND,
- MAKEWPARAM(KHUI_ACTION_NEW_CRED, 0), 0);
- else if (pdlginfo->dlgtype == NETID_DLGTYPE_CHPASSWD)
- SendMessage(khm_hwnd_main, WM_COMMAND,
- MAKEWPARAM(KHUI_ACTION_PASSWD_ID, 0), 0);
- else
- break;
-
- if (KHM_FAILED(khm_cred_wait_for_dialog(INFINITE, &result,
- widname,
- sizeof(widname))))
- continue;
- else {
- lr = (result != KHUI_NC_RESULT_PROCESS);
- break;
- }
- } while(TRUE);
-
-#ifdef DEBUG
- assert(lr || pdlginfo->dlgtype != NETID_DLGTYPE_TGT ||
- widname[0]);
-#endif
-
- if (!lr && pdlginfo->dlgtype == NETID_DLGTYPE_TGT &&
- widname[0]) {
- khm_handle out_ident;
- wchar_t * atsign;
-
- atsign = wcsrchr(widname, L'@');
-
- if (atsign == NULL)
- goto _exit;
-
- if (KHM_SUCCEEDED(kcdb_identity_create(widname,
- 0,
- &out_ident))) {
- khm_size cb;
-
- pdlginfo->out.ccache[0] = 0;
-
- cb = sizeof(pdlginfo->out.ccache);
- kcdb_identity_get_attrib(out_ident,
- L"Krb5CCName",
- NULL,
- pdlginfo->out.ccache,
- &cb);
- kcdb_identity_release(out_ident);
- } else {
-#ifdef DEBUG
- assert(FALSE);
-#endif
- }
-
- *atsign++ = 0;
-
- StringCbCopy(pdlginfo->out.username,
- sizeof(pdlginfo->out.username),
- widname);
-
- StringCbCopy(pdlginfo->out.realm,
- sizeof(pdlginfo->out.realm),
- atsign);
- }
-
- _exit:
-
- if (pdlginfo)
- UnmapViewOfFile(pdlginfo);
- if (hmap)
- CloseHandle(hmap);
- if (identity)
- kcdb_identity_release(identity);
-
- return lr;
- }
-
-#ifdef DEPRECATED_REMOTE_CALL
- /* deprecated */
- case ID_OBTAIN_TGT_WITH_LPARAM:
- {
- char * param = (char *) GlobalLock((HGLOBAL) lParam);
- char * username = NULL;
- char * realm = NULL;
- char * title = NULL;
- char * ccache = NULL;
- wchar_t widname[KCDB_IDENT_MAXCCH_NAME];
- wchar_t wtitle[KHUI_MAXCCH_TITLE];
- size_t cch;
- khm_int32 rv = KHM_ERROR_SUCCESS;
- khm_handle identity = NULL;
- NETID_DLGINFO dlginfo;
-
- if (param) {
- if (*param)
- title = param;
-
- if (FAILED(StringCchLengthA(param, KHUI_MAXCCH_TITLE, &cch))) {
-#ifdef DEBUG
- assert(FALSE);
-#endif
- rv = KHM_ERROR_INVALID_PARAM;
- goto _exit_tgt_with_lparam;
- }
-
- param += cch + 1;
-
- if (*param)
- username = param;
-
- if (FAILED(StringCchLengthA(param, KCDB_IDENT_MAXCCH_NAME, &cch))) {
-#ifdef DEBUG
- assert(FALSE);
-#endif
- rv = KHM_ERROR_INVALID_PARAM;
- goto _exit_tgt_with_lparam;
- }
-
- param += cch + 1;
-
- if (*param)
- realm = param;
-
- if (FAILED(StringCchLengthA(param, KCDB_IDENT_MAXCCH_NAME, &cch))) {
-#ifdef DEBUG
- assert(FALSE);
-#endif
- rv = KHM_ERROR_INVALID_PARAM;
- goto _exit_tgt_with_lparam;
- }
-
- param += cch + 1;
-
- if (*param)
- ccache = param;
- }
-
- if (username && realm) {
-
- if (FAILED(StringCbPrintf(widname, sizeof(widname),
- L"%hs@%hs", username, realm))) {
- rv = KHM_ERROR_INVALID_PARAM;
- goto _exit_tgt_with_lparam;
- }
-
- rv = kcdb_identity_create(widname,
- KCDB_IDENT_FLAG_CREATE,
- &identity);
- if (KHM_FAILED(rv)) {
- goto _exit_tgt_with_lparam;
- }
- }
-
- ZeroMemory(&dlginfo, sizeof(dlginfo));
-
- dlginfo.size = NETID_DLGINFO_V1_SZ;
- dlginfo.dlgtype = NETID_DLGTYPE_TGT;
-
- if (title)
- StringCbCopy(dlginfo.in.title, sizeof(dlginfo.in.title),
- wtitle);
- if (username)
- AnsiStrToUnicode(dlginfo.in.username, sizeof(dlginfo.in.username),
- username);
- if (realm)
- AnsiStrToUnicode(dlginfo.in.realm, sizeof(dlginfo.in.realm),
- realm);
-
- if (ccache)
- AnsiStrToUnicode(dlginfo.in.ccache, sizeof(dlginfo.in.ccache),
- ccache);
-
- dlginfo.in.use_defaults = TRUE;
-
- do {
- if (khm_cred_is_in_dialog()) {
- khm_cred_wait_for_dialog(INFINITE);
- }
-
- khui_context_set_ex(KHUI_SCOPE_IDENT,
- identity,
- KCDB_CREDTYPE_INVALID,
- NULL,
- NULL,
- 0,
- NULL,
- &dlginfo,
- sizeof(dlginfo));
-
- if (title) {
- AnsiStrToUnicode(wtitle, sizeof(wtitle),
- title);
-
- khm_cred_obtain_new_creds(wtitle);
- } else {
- khm_cred_obtain_new_creds(NULL);
- }
-
- if (KHM_FAILED(khm_cred_wait_for_dialog(INFINITE)))
- continue;
- else
- break;
- } while(TRUE);
-
- _exit_tgt_with_lparam:
- if (identity)
- kcdb_identity_release(identity);
-
- GlobalUnlock((HGLOBAL) lParam);
- }
- return 0;
-#endif
-
- }
-
- return DefWindowProc(hwnd, uMsg, wParam, lParam);
-}
-
-DWORD WINAPI
-khm_reqdaemon_thread_proc(LPVOID vparam) {
- BOOL rv;
- MSG msg;
-#ifdef DEBUG
- DWORD dw;
-#endif
-
- PDESCTHREAD(L"Remote Request Daemon", L"App");
-
- khm_register_reqdaemonwnd_class();
-
-#ifdef DEBUG
- assert(reqdaemon_atom != 0);
-#endif
-
- reqdaemon_hwnd = CreateWindowEx(0,
- MAKEINTATOM(reqdaemon_atom),
- KHUI_REQDAEMONWND_NAME,
- 0,
- 0,0,0,0,
- HWND_MESSAGE,
- NULL,
- khm_hInstance,
- NULL);
-
-#ifdef DEBUG
- dw = GetLastError();
- assert(reqdaemon_hwnd != NULL);
-#endif
-
- while(rv = GetMessage(&msg, NULL, 0, 0)) {
- if (rv == -1) {
-#ifdef DEBUG
- assert(FALSE);
-#endif
- break;
- } else {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- }
-
- reqdaemon_thread = NULL;
-
- khm_unregister_reqdaemonwnd_class();
-
- return 0;
-}
-
-void
-khm_register_reqdaemonwnd_class(void) {
- WNDCLASSEX wcx;
-
- ZeroMemory(&wcx, sizeof(wcx));
-
- wcx.cbSize = sizeof(wcx);
- wcx.style = 0;
- wcx.lpfnWndProc = reqdaemonwnd_proc;
- wcx.cbClsExtra = 0;
- wcx.cbWndExtra = 0;
- wcx.hInstance = khm_hInstance;
- wcx.hIcon = NULL;
- wcx.hCursor = NULL;
- wcx.hbrBackground = NULL;
- wcx.lpszMenuName = NULL;
- wcx.lpszClassName = KHUI_REQDAEMONWND_CLASS;
- wcx.hIconSm = NULL;
-
- reqdaemon_atom = RegisterClassEx(&wcx);
-
-#ifdef DEBUG
- assert(reqdaemon_atom != 0);
-#endif
-}
-
-void
-khm_unregister_reqdaemonwnd_class(void) {
- if (reqdaemon_atom != 0) {
- UnregisterClass(MAKEINTATOM(reqdaemon_atom), khm_hInstance);
- reqdaemon_atom = 0;
- }
-}
-
-void
-khm_init_request_daemon(void) {
-#ifdef DEBUG
- assert(reqdaemon_thread == NULL);
-#endif
-
- reqdaemon_thread = CreateThread(NULL,
- 0,
- khm_reqdaemon_thread_proc,
- NULL,
- 0,
- NULL);
-
-#ifdef DEBUG
- assert(reqdaemon_thread != NULL);
-#endif
-}
-
-void
-khm_exit_request_daemon(void) {
- if (reqdaemon_hwnd == NULL)
- return;
-
- SendMessage(reqdaemon_hwnd, WM_CLOSE, 0, 0);
-}
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ * Copyright (c) 2007 Secure Endpoints Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<khmapp.h>
+#include<assert.h>
+
+ATOM reqdaemon_atom = 0;
+HANDLE reqdaemon_thread = NULL;
+HWND reqdaemon_hwnd = NULL;
+
+LRESULT CALLBACK
+reqdaemonwnd_proc(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam) {
+
+ switch(uMsg) {
+ case WM_CREATE:
+ break;
+
+ case WM_CLOSE:
+ DestroyWindow(hwnd);
+ break;
+
+ case WM_DESTROY:
+ reqdaemon_hwnd = NULL;
+ PostQuitMessage(0);
+ break;
+
+ /* Leash compatibility */
+ case ID_OBTAIN_TGT_WITH_LPARAM:
+ {
+ wchar_t widname[KCDB_IDENT_MAXCCH_NAME];
+ wchar_t wmapping[ARRAYLENGTH(KHUI_REQD_MAPPING_FORMAT) + 10];
+ khm_handle identity = NULL;
+ LPNETID_DLGINFO pdlginfo;
+ LRESULT lr = 1;
+ khm_int32 result;
+ HANDLE hmap = NULL;
+ HRESULT hr;
+
+ hr = StringCbPrintf(wmapping, sizeof(wmapping),
+ KHUI_REQD_MAPPING_FORMAT, (DWORD) lParam);
+#ifdef DEBUG
+ assert(SUCCEEDED(hr));
+#endif
+ hmap = CreateFileMapping(INVALID_HANDLE_VALUE,
+ NULL,
+ PAGE_READWRITE,
+ 0, 4096,
+ wmapping);
+
+ if (hmap == NULL) {
+ return -1;
+ } else if (hmap != NULL && GetLastError() != ERROR_ALREADY_EXISTS) {
+ CloseHandle(hmap);
+ return -1;
+ }
+
+ pdlginfo = MapViewOfFile(hmap,
+ FILE_MAP_WRITE,
+ 0, 0,
+ sizeof(*pdlginfo));
+
+ if (pdlginfo == NULL) {
+ CloseHandle(hmap);
+ return 1;
+ }
+
+ if (pdlginfo->in.username[0] &&
+ pdlginfo->in.realm[0] &&
+ SUCCEEDED(StringCbPrintf(widname,
+ sizeof(widname),
+ L"%s@%s",
+ pdlginfo->in.username,
+ pdlginfo->in.realm))) {
+
+ kcdb_identity_create(widname,
+ KCDB_IDENT_FLAG_CREATE,
+ &identity);
+ }
+
+ widname[0] = 0;
+
+ do {
+ if (khm_cred_is_in_dialog()) {
+ khm_cred_wait_for_dialog(INFINITE, NULL, NULL, 0);
+ }
+
+ if (identity)
+ khui_context_set_ex(KHUI_SCOPE_IDENT,
+ identity,
+ KCDB_CREDTYPE_INVALID,
+ NULL,
+ NULL,
+ 0,
+ NULL,
+ pdlginfo,
+ sizeof(*pdlginfo));
+ else
+ khui_context_reset();
+
+ if (pdlginfo->dlgtype == NETID_DLGTYPE_TGT)
+ SendMessage(khm_hwnd_main, WM_COMMAND,
+ MAKEWPARAM(KHUI_ACTION_NEW_CRED, 0), 0);
+ else if (pdlginfo->dlgtype == NETID_DLGTYPE_CHPASSWD)
+ SendMessage(khm_hwnd_main, WM_COMMAND,
+ MAKEWPARAM(KHUI_ACTION_PASSWD_ID, 0), 0);
+ else
+ break;
+
+ if (KHM_FAILED(khm_cred_wait_for_dialog(INFINITE, &result,
+ widname,
+ sizeof(widname))))
+ continue;
+ else {
+ lr = (result != KHUI_NC_RESULT_PROCESS);
+ break;
+ }
+ } while(TRUE);
+
+#ifdef DEBUG
+ assert(lr || pdlginfo->dlgtype != NETID_DLGTYPE_TGT ||
+ widname[0]);
+#endif
+
+ if (!lr && pdlginfo->dlgtype == NETID_DLGTYPE_TGT &&
+ widname[0]) {
+ khm_handle out_ident;
+ wchar_t * atsign;
+
+ atsign = wcsrchr(widname, L'@');
+
+ if (atsign == NULL)
+ goto _exit;
+
+ if (KHM_SUCCEEDED(kcdb_identity_create(widname,
+ 0,
+ &out_ident))) {
+ khm_size cb;
+
+ pdlginfo->out.ccache[0] = 0;
+
+ cb = sizeof(pdlginfo->out.ccache);
+ kcdb_identity_get_attrib(out_ident,
+ L"Krb5CCName",
+ NULL,
+ pdlginfo->out.ccache,
+ &cb);
+ kcdb_identity_release(out_ident);
+ } else {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ }
+
+ *atsign++ = 0;
+
+ StringCbCopy(pdlginfo->out.username,
+ sizeof(pdlginfo->out.username),
+ widname);
+
+ StringCbCopy(pdlginfo->out.realm,
+ sizeof(pdlginfo->out.realm),
+ atsign);
+ }
+
+ _exit:
+
+ if (pdlginfo)
+ UnmapViewOfFile(pdlginfo);
+ if (hmap)
+ CloseHandle(hmap);
+ if (identity)
+ kcdb_identity_release(identity);
+
+ return lr;
+ }
+
+#ifdef DEPRECATED_REMOTE_CALL
+ /* deprecated */
+ case ID_OBTAIN_TGT_WITH_LPARAM:
+ {
+ char * param = (char *) GlobalLock((HGLOBAL) lParam);
+ char * username = NULL;
+ char * realm = NULL;
+ char * title = NULL;
+ char * ccache = NULL;
+ wchar_t widname[KCDB_IDENT_MAXCCH_NAME];
+ wchar_t wtitle[KHUI_MAXCCH_TITLE];
+ size_t cch;
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+ khm_handle identity = NULL;
+ NETID_DLGINFO dlginfo;
+
+ if (param) {
+ if (*param)
+ title = param;
+
+ if (FAILED(StringCchLengthA(param, KHUI_MAXCCH_TITLE, &cch))) {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ rv = KHM_ERROR_INVALID_PARAM;
+ goto _exit_tgt_with_lparam;
+ }
+
+ param += cch + 1;
+
+ if (*param)
+ username = param;
+
+ if (FAILED(StringCchLengthA(param, KCDB_IDENT_MAXCCH_NAME, &cch))) {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ rv = KHM_ERROR_INVALID_PARAM;
+ goto _exit_tgt_with_lparam;
+ }
+
+ param += cch + 1;
+
+ if (*param)
+ realm = param;
+
+ if (FAILED(StringCchLengthA(param, KCDB_IDENT_MAXCCH_NAME, &cch))) {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ rv = KHM_ERROR_INVALID_PARAM;
+ goto _exit_tgt_with_lparam;
+ }
+
+ param += cch + 1;
+
+ if (*param)
+ ccache = param;
+ }
+
+ if (username && realm) {
+
+ if (FAILED(StringCbPrintf(widname, sizeof(widname),
+ L"%hs@%hs", username, realm))) {
+ rv = KHM_ERROR_INVALID_PARAM;
+ goto _exit_tgt_with_lparam;
+ }
+
+ rv = kcdb_identity_create(widname,
+ KCDB_IDENT_FLAG_CREATE,
+ &identity);
+ if (KHM_FAILED(rv)) {
+ goto _exit_tgt_with_lparam;
+ }
+ }
+
+ ZeroMemory(&dlginfo, sizeof(dlginfo));
+
+ dlginfo.size = NETID_DLGINFO_V1_SZ;
+ dlginfo.dlgtype = NETID_DLGTYPE_TGT;
+
+ if (title)
+ StringCbCopy(dlginfo.in.title, sizeof(dlginfo.in.title),
+ wtitle);
+ if (username)
+ AnsiStrToUnicode(dlginfo.in.username, sizeof(dlginfo.in.username),
+ username);
+ if (realm)
+ AnsiStrToUnicode(dlginfo.in.realm, sizeof(dlginfo.in.realm),
+ realm);
+
+ if (ccache)
+ AnsiStrToUnicode(dlginfo.in.ccache, sizeof(dlginfo.in.ccache),
+ ccache);
+
+ dlginfo.in.use_defaults = TRUE;
+
+ do {
+ if (khm_cred_is_in_dialog()) {
+ khm_cred_wait_for_dialog(INFINITE);
+ }
+
+ khui_context_set_ex(KHUI_SCOPE_IDENT,
+ identity,
+ KCDB_CREDTYPE_INVALID,
+ NULL,
+ NULL,
+ 0,
+ NULL,
+ &dlginfo,
+ sizeof(dlginfo));
+
+ if (title) {
+ AnsiStrToUnicode(wtitle, sizeof(wtitle),
+ title);
+
+ khm_cred_obtain_new_creds(wtitle);
+ } else {
+ khm_cred_obtain_new_creds(NULL);
+ }
+
+ if (KHM_FAILED(khm_cred_wait_for_dialog(INFINITE)))
+ continue;
+ else
+ break;
+ } while(TRUE);
+
+ _exit_tgt_with_lparam:
+ if (identity)
+ kcdb_identity_release(identity);
+
+ GlobalUnlock((HGLOBAL) lParam);
+ }
+ return 0;
+#endif
+
+ }
+
+ return DefWindowProc(hwnd, uMsg, wParam, lParam);
+}
+
+DWORD WINAPI
+khm_reqdaemon_thread_proc(LPVOID vparam) {
+ BOOL rv;
+ MSG msg;
+#ifdef DEBUG
+ DWORD dw;
+#endif
+
+ PDESCTHREAD(L"Remote Request Daemon", L"App");
+
+ khm_register_reqdaemonwnd_class();
+
+#ifdef DEBUG
+ assert(reqdaemon_atom != 0);
+#endif
+
+ reqdaemon_hwnd = CreateWindowEx(0,
+ MAKEINTATOM(reqdaemon_atom),
+ KHUI_REQDAEMONWND_NAME,
+ 0,
+ 0,0,0,0,
+ HWND_MESSAGE,
+ NULL,
+ khm_hInstance,
+ NULL);
+
+#ifdef DEBUG
+ dw = GetLastError();
+ assert(reqdaemon_hwnd != NULL);
+#endif
+
+ while(rv = GetMessage(&msg, NULL, 0, 0)) {
+ if (rv == -1) {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ break;
+ } else {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ }
+
+ reqdaemon_thread = NULL;
+
+ khm_unregister_reqdaemonwnd_class();
+
+ return 0;
+}
+
+void
+khm_register_reqdaemonwnd_class(void) {
+ WNDCLASSEX wcx;
+
+ ZeroMemory(&wcx, sizeof(wcx));
+
+ wcx.cbSize = sizeof(wcx);
+ wcx.style = 0;
+ wcx.lpfnWndProc = reqdaemonwnd_proc;
+ wcx.cbClsExtra = 0;
+ wcx.cbWndExtra = 0;
+ wcx.hInstance = khm_hInstance;
+ wcx.hIcon = NULL;
+ wcx.hCursor = NULL;
+ wcx.hbrBackground = NULL;
+ wcx.lpszMenuName = NULL;
+ wcx.lpszClassName = KHUI_REQDAEMONWND_CLASS;
+ wcx.hIconSm = NULL;
+
+ reqdaemon_atom = RegisterClassEx(&wcx);
+
+#ifdef DEBUG
+ assert(reqdaemon_atom != 0);
+#endif
+}
+
+void
+khm_unregister_reqdaemonwnd_class(void) {
+ if (reqdaemon_atom != 0) {
+ UnregisterClass(MAKEINTATOM(reqdaemon_atom), khm_hInstance);
+ reqdaemon_atom = 0;
+ }
+}
+
+void
+khm_init_request_daemon(void) {
+#ifdef DEBUG
+ assert(reqdaemon_thread == NULL);
+#endif
+
+ reqdaemon_thread = CreateThread(NULL,
+ 0,
+ khm_reqdaemon_thread_proc,
+ NULL,
+ 0,
+ NULL);
+
+#ifdef DEBUG
+ assert(reqdaemon_thread != NULL);
+#endif
+}
+
+void
+khm_exit_request_daemon(void) {
+ if (reqdaemon_hwnd == NULL)
+ return;
+
+ SendMessage(reqdaemon_hwnd, WM_CLOSE, 0, 0);
+}
diff --git a/src/windows/identity/ui/reqdaemon.h b/src/windows/identity/ui/reqdaemon.h
index b55e93c992..99a50f5e0a 100644
--- a/src/windows/identity/ui/reqdaemon.h
+++ b/src/windows/identity/ui/reqdaemon.h
@@ -1,42 +1,42 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#ifndef __KHIMAIRA_REQDAEMON_H
-#define __KHIMAIRA_REQDAEMON_H
-
-void
-khm_register_reqdaemonwnd_class(void);
-
-void
-khm_unregister_reqdaemonwnd_class(void);
-
-void
-khm_init_request_daemon(void);
-
-void
-khm_exit_request_daemon(void);
-
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __KHIMAIRA_REQDAEMON_H
+#define __KHIMAIRA_REQDAEMON_H
+
+void
+khm_register_reqdaemonwnd_class(void);
+
+void
+khm_unregister_reqdaemonwnd_class(void);
+
+void
+khm_init_request_daemon(void);
+
+void
+khm_exit_request_daemon(void);
+
+#endif
diff --git a/src/windows/identity/ui/resource.h b/src/windows/identity/ui/resource.h
index 7be9a84bef..1a3c35b239 100644
--- a/src/windows/identity/ui/resource.h
+++ b/src/windows/identity/ui/resource.h
@@ -1,415 +1,415 @@
-//{{NO_DEPENDENCIES}}
-// Microsoft Visual C++ generated include file.
-// Used by C:\work\pismere\athena\auth\krb5\src\windows\identity\ui\lang\en_us\khapp.rc
-//
-#define IDI_MAIN_APP 104
-#define IDD_PP_CRED 106
-#define IDD_PP_IDENT 107
-#define IDB_TK_REFRESH 108
-#define IDS_MAIN_WINDOW_TITLE 108
-#define IDS_MENU_FILE 109
-#define IDB_ID 110
-#define IDS_MENU_CRED 110
-#define IDB_ID_DELETE 111
-#define IDS_MENU_VIEW 111
-#define IDB_ID_NEW 112
-#define IDS_MENU_OPTIONS 112
-#define IDB_ID_REFRESH 113
-#define IDS_MENU_HELP 113
-#define IDB_TK 114
-#define IDS_ACTION_PROPERTIES 114
-#define IDB_TK_DELETE 115
-#define IDS_ACTION_EXIT 115
-#define IDB_TK_NEW 116
-#define IDS_CFG_ROOT_NAME 116
-#define IDS_ACTION_SET_DEF_ID 117
-#define IDS_ACTION_SET_SRCH_ID 118
-#define IDB_VW_REFRESH_SM 118
-#define IDR_MENU_BAR 119
-#define IDS_CFG_ROOT_TITLE 119
-#define IDS_CFG_GENERAL_SHORT 120
-#define IDB_TB_BLANK 121
-#define IDS_ACTION_NEW_CRED 121
-#define IDS_ACTION_PASSWD_ID 122
-#define IDS_ACTION_CHOOSE_COLS 123
-#define IDB_TB_BLANK_SM 123
-#define IDS_ACTION_DEBUG_WINDOW 124
-#define IDB_VW_REFRESH 124
-#define IDS_ACTION_VIEW_REFRESH 125
-#define IDB_ID_DELETE_DIS 125
-#define IDS_MENU_LAYOUT 126
-#define IDB_ID_DELETE_DIS_SM 126
-#define IDS_MENU_TOOLBARS 127
-#define IDB_ID_DELETE_SM 127
-#define IDS_ACTION_LAYOUT_ID 128
-#define IDB_ID_DIS 128
-#define IDS_ACTION_LAYOUT_TYPE 129
-#define IDB_ID_DIS_SM 129
-#define IDS_ACTION_LAYOUT_LOC 130
-#define IDB_ID_NEW_DIS 130
-#define IDS_ACTION_TB_STANDARD 131
-#define IDB_ID_NEW_DIS_SM 131
-#define IDS_ACTION_OPT_KHIM 132
-#define IDB_ID_NEW_SM 132
-#define IDB_ID_REFRESH_DIS 133
-#define IDS_ACTION_OPT_IDENTS 133
-#define IDS_ACTION_OPT_NOTIF 134
-#define IDB_ID_REFRESH_SM 134
-#define IDS_ACTION_HELP_CTX 135
-#define IDB_ID_REFRESH_DIS_SM 135
-#define IDS_ACTION_HELP_CONTENTS 136
-#define IDB_TK_DELETE_DIS 136
-#define IDS_ACTION_HELP_INDEX 137
-#define IDB_TK_DELETE_DIS_SM 137
-#define IDS_ACTION_HELP_ABOUT 138
-#define IDB_TK_DELETE_SM 138
-#define IDB_TK_DIS_SM 139
-#define IDS_CFG_GENERAL_LONG 139
-#define IDB_TK_NEW_DIS 140
-#define IDS_SAMPLE_STRING 140
-#define IDB_TK_NEW_DIS_SM 141
-#define IDS_NO_CREDS 141
-#define IDB_TK_NEW_SM 142
-#define IDS_WT_INIT_CREDS 142
-#define IDB_TK_REFRESH_DIS 143
-#define IDS_WT_NEW_CREDS 143
-#define IDB_TK_REFRESH_DIS_SM 144
-#define IDS_NC_IDENTITY 144
-#define IDB_TK_REFRESH_SM 145
-#define IDS_NC_IDENTS 145
-#define IDB_TK_SM 146
-#define IDS_NC_CREDTEXT_ID_NONE 146
-#define IDB_HELP_SM 147
-#define IDS_NC_CREDTEXT_ID_ONE 147
-#define IDB_HELP 148
-#define IDS_NC_CREDTEXT_ID_MANY 148
-#define IDB_LOGO_SHADE 149
-#define IDS_NC_CREDTEXT_ID_INVALID 149
-#define IDS_WTPOST_INIT_CREDS 150
-#define IDS_WTPOST_NEW_CREDS 151
-#define IDB_WDG_EXPAND 152
-#define IDS_ACTION_RENEW_CRED 152
-#define IDB_WDG_COLLAPSE 153
-#define IDS_ACTION_DESTROY_CRED 153
-#define IDB_ID_SM 154
-#define IDS_DEFAULT_FONT 154
-#define IDB_WDG_EXPAND_HI 155
-#define IDS_NC_CREDTEXT_TABS 155
-#define IDB_WDG_COLLAPSE_HI 156
-#define IDS_NOTIFY_PREFIX 156
-#define IDB_WDG_CREDTYPE 157
-#define IDS_NOTIFY_READY 157
-#define IDB_WDG_FLAG 158
-#define IDS_NOTIFY_ATTENTION 158
-#define IDB_FLAG_WARN 159
-#define IDS_ALERT_DEFAULT 159
-#define IDB_FLAG_EXPIRED 160
-#define IDS_PACTION_OK 160
-#define IDB_FLAG_CRITICAL 161
-#define IDS_PACTION_CANCEL 161
-#define IDS_PACTION_CLOSE 162
-#define IDD_NC_NEWCRED 162
-#define IDD_NC_BBAR 163
-#define IDS_ALERT_NOSEL_TITLE 163
-#define IDS_ALERT_NOSEL 164
-#define IDI_ENABLED 165
-#define IDS_NC_CREDTEXT_ID_VALID 165
-#define IDI_DISABLED 166
-#define IDS_NC_CREDTEXT_ID_UNCHECKED 166
-#define IDS_PROP_COL_PROPERTY 167
-#define IDS_PROP_COL_VALUE 168
-#define IDI_NOTIFY_NONE 169
-#define IDS_NC_NEW_IDENT 169
-#define IDI_NOTIFY_INFO 170
-#define IDS_NC_CREDTEXT_ID_CHECKING 170
-#define IDI_NOTIFY_WARN 171
-#define IDS_ACTION_OPEN_APP 171
-#define IDI_NOTIFY_ERROR 172
-#define IDS_CTX_NEW_IDENT 172
-#define IDS_CTX_NEW_CREDS 173
-#define IDD_CFG_MAIN 173
-#define IDS_CTX_RENEW_CREDS 174
-#define IDD_CFG_GENERIC 174
-#define IDS_CTX_PROC_NEW_IDENT 175
-#define IDB_LOGO_OPAQUE 175
-#define IDS_CTX_PROC_NEW_CREDS 176
-#define IDD_CFG_GENERAL 176
-#define IDS_CTX_PROC_RENEW_CREDS 177
-#define IDD_CFG_IDENTITIES 177
-#define IDS_ACTION_CLOSE_APP 178
-#define IDD_CFG_NOTIF 178
-#define IDS_NC_FAILED_TITLE 179
-#define IDD_CFG_PLUGINS 179
-#define IDS_CFG_IDENTITIES_SHORT 180
-#define IDD_CFG_IDENTITY 180
-#define IDS_CFG_IDENTITIES_LONG 181
-#define IDI_CFG_DEFAULT 181
-#define IDS_CFG_NOTIF_SHORT 182
-#define IDI_CFG_MODIFIED 182
-#define IDS_CFG_NOTIF_LONG 183
-#define IDI_CFG_APPLIED 183
-#define IDS_CFG_PLUGINS_SHORT 184
-#define IDD_CFG_IDS_TAB 184
-#define IDS_CFG_PLUGINS_LONG 185
-#define IDD_CFG_ID_TAB 185
-#define IDS_CFG_IDENTITY_SHORT 186
-#define IDI_CFG_DELETED 186
-#define IDS_CFG_IDENTITY_LONG 187
-#define IDI_ID 187
-#define IDS_CTX_DESTROY_CREDS 188
-#define IDB_IMPORT_SM_DIS 188
-#define IDS_WARN_EXPIRE 189
-#define IDB_IMPORT 189
-#define IDS_WARN_TITLE 190
-#define IDB_IMPORT_DIS 190
-#define IDS_ALERT_MOREINFO 191
-#define IDB_IMPORT_SM 191
-#define IDS_WARN_EXPIRED 192
-#define IDB_CHPW_SM 192
-#define IDS_WARN_EXPIRE_ID 193
-#define IDB_CHPW 193
-#define IDS_WARN_EXPIRED_ID 194
-#define IDB_CHPW_DIS 194
-#define IDS_WARN_WM_TITLE 195
-#define IDB_CHPW_DIS_SM 195
-#define IDS_WARN_WM_MSG 196
-#define IDD_ABOUT 196
-#define IDS_CFG_ID_TAB_SHORT 197
-#define IDB_TB_SPACE 197
-#define IDS_CFG_ID_TAB_LONG 198
-#define IDB_WDG_STUCK_HI 198
-#define IDS_CFG_IDS_TAB_SHORT 199
-#define IDB_WDG_STICK 199
-#define IDS_CFG_IDS_TAB_LONG 200
-#define IDB_WDG_STICK_HI 200
-#define IDS_CFG_IDS_IDENTITY 201
-#define IDB_WDG_STUCK 201
-#define IDS_ACTION_IMPORT 202
-#define IDS_CTX_IMPORT 203
-#define IDB_FLAG_RENEW 203
-#define IDS_CFG_PI_COL_PLUGINS 204
-#define IDI_APPICON_WARN 204
-#define IDS_PISTATE_FAILUNK 205
-#define IDI_APPICON_EXP 205
-#define IDS_PISTATE_FAILMAX 206
-#define IDI_APPICON_OK 206
-#define IDS_PISTATE_FAILREG 207
-#define IDI_CFG_PLUGIN 207
-#define IDS_PISTATE_FAILDIS 208
-#define IDI_CFG_PLUGIN_ERR 208
-#define IDS_PISTATE_FAILLOD 209
-#define IDI_CFG_PLUGIN_DIS 209
-#define IDS_PISTATE_PLACEHOLD 210
-#define IDD_CFG_APPEAR 210
-#define IDS_PISTATE_REG 211
-#define IDD_CFG_ADDIDENT 211
-#define IDS_PISTATE_HOLD 212
-#define IDS_PISTATE_INIT 213
-#define IDS_PISTATE_RUN 214
-#define IDS_PISTATE_EXIT 215
-#define IDS_CTX_PASSWORD 216
-#define IDS_WT_PASSWORD 217
-#define IDS_WTPOST_PASSWORD 218
-#define IDS_CTX_PROC_PASSWORD 219
-#define IDS_NC_PWD_FAILED_TITLE 220
-#define IDS_CMDLINE_HELP 221
-#define IDS_PACTION_NEXT 222
-#define IDS_ERR_TITLE_NO_IDENTPRO 223
-#define IDS_ERR_MSG_NO_IDENTPRO 224
-#define IDS_ERR_SUGG_NO_IDENTPRO 225
-#define IDS_NC_REN_FAILED_TITLE 226
-#define IDS_CW_DEFAULT 227
-#define IDS_ACTION_OPT_PLUGINS 228
-#define IDS_NC_SETDEF 229
-#define IDS_NC_ID_DEF 230
-#define IDS_NC_ID_WDEF 231
-#define IDS_NC_ID_NDEF 232
-#define IDS_PACTION_YES 233
-#define IDS_PACTION_NO 234
-#define IDS_PACTION_YESALL 235
-#define IDS_PACTION_NOALL 236
-#define IDS_PACTION_KEEP 237
-#define IDS_PACTION_REMOVE 238
-#define IDS_PACTION_DISCARD 239
-#define IDS_CFG_IT_MOD 240
-#define IDS_CFG_IT_APP 241
-#define IDS_CFG_IT_NONE 242
-#define IDS_CFG_NODESC 243
-#define IDS_CFG_P_DELCNFT 244
-#define IDS_CFG_P_DELCNFM 245
-#define IDS_CFG_P_DELCNFS 246
-#define IDS_CFG_P_DELNDEP 247
-#define IDS_CFG_P_ENBCNFT 248
-#define IDS_CFG_P_ENBCNFM 249
-#define IDS_PISTATE_FAILINIT 250
-#define IDS_CFG_P_UNRCNFT 251
-#define IDS_CFG_P_UNRCNFM 252
-#define IDS_CFG_P_UNRCNFS 253
-#define IDS_ACTION_LAYOUT_CUST 254
-#define IDS_APR_HEADER_TEXT 255
-#define IDS_APR_HEADER_TEXT_BOLD 256
-#define IDS_APR_TEXT 257
-#define IDS_APR_TEXT_BOLD 258
-#define IDS_APR_SAMPLE_TEXT_NORMAL 259
-#define IDS_CFG_APPEAR_SHORT 260
-#define IDS_CFG_APPEAR_LONG 261
-#define IDS_ACTION_OPT_APPEAR 262
-#define IDS_APR_SAMPLE_TEXT_SEL 263
-#define IDS_CFG_IDNAME_INV 264
-#define IDS_CFG_IDNAME_PRB 265
-#define IDS_CFG_IDNAME_EXT 266
-#define IDS_CFG_IDNAME_CCR 267
-#define IDS_CFG_IDNAME_CCC 268
-#define IDS_CFG_LOGF_CS 269
-#define IDS_CFG_LOGF_CSR 270
-#define IDS_ACTIONT_PROPERTIES 271
-#define IDS_ACTIONT_EXIT 272
-#define IDS_ACTIONT_SET_DEF_ID 273
-#define IDS_ACTIONT_PASSWD_ID 274
-#define IDS_ACTIONT_NEW_CRED 275
-#define IDS_ACTIONT_RENEW_CRED 276
-#define IDS_ACTIONT_DESTROY_CRED 277
-#define IDS_ACTIONT_VIEW_REFRESH 278
-#define IDS_ACTIONT_OPT_IDENTS 279
-#define IDS_ACTIONT_OPT_KHIM 280
-#define IDS_ACTIONT_OPT_NOTIF 281
-#define IDS_ACTIONT_OPT_PLUGINS 282
-#define IDS_ACTIONT_OPT_APPEAR 283
-#define IDS_ACTIONT_HELP_CTX 284
-#define IDS_ACTIONT_IMPORT 285
-#define IDS_NC_FAILED_TITLE_I 286
-#define IDS_NC_PWD_FAILED_TITLE_I 287
-#define IDS_NC_REN_FAILED_TITLE_I 288
-#define IDS_CFG_IDNAME_NON 289
-#define IDS_MENU_DESTROY_CRED 290
-#define IDS_MENU_RENEW_CRED 291
-#define IDS_ACTION_DESTROY_ALL 292
-#define IDS_ACTION_RENEW_ALL 293
-#define IDS_IDACTION_RENEW 294
-#define IDS_IDACTION_DESTROY 295
-#define IDS_CTX_DESTROY_ID 296
-#define IDS_NCN_IDENT_INVALID 297
-#define IDS_NCN_IDENT_CHECKING 298
-#define IDS_NCN_IDENT_UNKNOWN 299
-#define IDS_REMOTE_FAIL 300
-#define IDS_REMOTE_FAIL_TITLE 301
-#define IDS_IDACTION_NEW 302
-#define IDS_IDACTIONT_NEW 303
-#define IDS_IDACTIONT_RENEW 304
-#define IDS_IDACTIONT_DESTROY 305
-#define IDS_ALERTTYPE_PLUGIN 306
-#define IDS_ALERTTYPE_EXPIRE 307
-#define IDS_ALERTTYPE_RENEWFAIL 308
-#define IDS_ALERTTYPE_ACQUIREFAIL 309
-#define IDS_ALERTTYPE_CHPW 310
-#define IDS_ACTION_LAYOUT_MINI 311
-#define IDS_IDEXPDISP_NOCRED 312
-#define IDS_IDEXPDISP_1CRED 313
-#define IDS_IDEXPDISP_NCRED 314
-#define IDS_CW_DEFAULTTF 315
-#define IDS_CW_TYPEF 316
-#define IDS_CW_EXPIREF 317
-#define IDS_CW_EXPIRED 318
-#define IDC_NC_CREDTEXT_LABEL 1009
-#define IDC_NC_CREDTEXT 1012
-#define IDC_NC_HELP 1017
-#define IDC_NC_ADVANCED 1019
-#define IDC_PP_IDNAME 1026
-#define IDC_PP_IDDEF 1027
-#define IDC_PP_IDSEARCH 1028
-#define IDC_PP_PROPLIST 1035
-#define IDC_PP_CPROPLIST 1036
-#define IDC_NC_TPL_ROW 1039
-#define IDC_NC_TPL_PANEL 1040
-#define IDC_NC_TPL_LABEL 1041
-#define IDC_NC_TPL_INPUT 1042
-#define IDC_NC_TPL_LABEL_LG 1043
-#define IDC_NC_TPL_INPUT_LG 1044
-#define IDC_NC_TPL_ROW_LG 1045
-#define IDC_CFG_NODELIST 1045
-#define IDAPPLY 1048
-#define IDC_CFG_TITLE 1050
-#define IDC_CFG_PANE 1051
-#define IDC_NOTIF_MONITOR 1053
-#define IDC_PP_DUMMY 1054
-#define IDC_NOTIF_RENEW 1055
-#define IDC_NOTIF_RENEW_THR 1056
-#define IDC_NOTIF_WARN1 1057
-#define IDC_NOTIF_WARN1_THR 1058
-#define IDC_NOTIF_WARN2 1059
-#define IDC_NOTIF_WARN2_THR 1060
-#define IDC_CFG_KEEPRUNNING 1061
-#define IDC_CFG_STARTUP_GROUP 1062
-#define IDC_CFG_AUTOSTART 1063
-#define IDC_CFG_AUTOIMPORT 1064
-#define IDC_CFG_AUTOINIT 1065
-#define IDC_CFG_OTHER 1066
-#define IDC_CFG_MONITOR 1069
-#define IDC_CFG_STICKY 1070
-#define IDC_CFG_RENEW 1075
-#define IDC_CFG_REMOVE 1076
-#define IDC_CFG_TAB 1077
-#define IDC_CFG_TARGET 1078
-#define IDC_CFG_PLUGINS 1079
-#define IDC_CFG_DESC 1084
-#define IDC_CFG_LBL_STATE 1085
-#define IDC_CFG_STATE 1086
-#define IDC_CFG_LBL_DEPS 1087
-#define IDC_CFG_DEPS 1088
-#define IDC_CFG_DISABLE 1089
-#define IDC_CFG_ENABLE 1090
-#define IDC_CFG_LBL_MOD 1092
-#define IDC_CFG_MODULE 1093
-#define IDC_CFG_LBL_VEN 1094
-#define IDC_CFG_VENDOR 1095
-#define IDC_CFG_REGISTER 1097
-#define IDC_CFG_NETDETECT 1098
-#define IDC_PP_STICKY 1099
-#define IDC_PRODUCT 1100
-#define IDC_COPYRIGHT 1101
-#define IDC_BUILDINFO 1102
-#define IDC_MODULES 1103
-#define IDC_PP_CONFIG 1104
-#define IDC_CFG_UNREGISTER 1107
-#define IDC_CFG_VERSION 1108
-#define IDC_CFG_ICON 1109
-#define IDC_CFG_LOGTOFILE 1110
-#define IDC_CFG_LOGPATH 1111
-#define IDC_NOTIF_HALFLIFE 1112
-#define IDC_CFG_DESTROYALL 1113
-#define IDC_CFG_SAMPLE_NORMAL 1123
-#define IDC_CFG_REVERT 1127
-#define IDC_CFG_FONTS 1128
-#define IDC_CFG_SAMPLE_BOLD 1129
-#define IDC_CFG_SIZE 1130
-#define IDC_CFG_BOLD 1131
-#define IDC_CFG_ITALICS 1132
-#define IDC_CFG_ADDIDENT 1133
-#define IDC_SM_CTL 1134
-#define IDC_CFG_SHOWLOG 1135
-#define IDC_MED_CTL 1135
-#define IDC_LG_CTL 1136
-#define IDC_SM_LBL 1137
-#define IDC_MED_LBL 1138
-#define IDC_LG_LBL 1139
-#define IDC_CFG_NOTACTION 1141
-#define IDC_CFG_NOTACT_STATIC 1142
-#define IDC_NC_BASIC 1143
-#define IDA_ACTIVATE_MENU 40003
-#define IDA_UP 40004
-#define IDA_DOWN 40005
-#define IDA_LEFT 40006
-#define IDA_RIGHT 40007
-#define IDA_ESC 40008
-#define IDA_ENTER 40009
-
-// Next default values for new objects
-//
-#ifdef APSTUDIO_INVOKED
-#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE 212
-#define _APS_NEXT_COMMAND_VALUE 40010
-#define _APS_NEXT_CONTROL_VALUE 1144
-#define _APS_NEXT_SYMED_VALUE 101
-#endif
-#endif
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by C:\work\pismere\athena\auth\krb5\src\windows\identity\ui\lang\en_us\khapp.rc
+//
+#define IDI_MAIN_APP 104
+#define IDD_PP_CRED 106
+#define IDD_PP_IDENT 107
+#define IDB_TK_REFRESH 108
+#define IDS_MAIN_WINDOW_TITLE 108
+#define IDS_MENU_FILE 109
+#define IDB_ID 110
+#define IDS_MENU_CRED 110
+#define IDB_ID_DELETE 111
+#define IDS_MENU_VIEW 111
+#define IDB_ID_NEW 112
+#define IDS_MENU_OPTIONS 112
+#define IDB_ID_REFRESH 113
+#define IDS_MENU_HELP 113
+#define IDB_TK 114
+#define IDS_ACTION_PROPERTIES 114
+#define IDB_TK_DELETE 115
+#define IDS_ACTION_EXIT 115
+#define IDB_TK_NEW 116
+#define IDS_CFG_ROOT_NAME 116
+#define IDS_ACTION_SET_DEF_ID 117
+#define IDS_ACTION_SET_SRCH_ID 118
+#define IDB_VW_REFRESH_SM 118
+#define IDR_MENU_BAR 119
+#define IDS_CFG_ROOT_TITLE 119
+#define IDS_CFG_GENERAL_SHORT 120
+#define IDB_TB_BLANK 121
+#define IDS_ACTION_NEW_CRED 121
+#define IDS_ACTION_PASSWD_ID 122
+#define IDS_ACTION_CHOOSE_COLS 123
+#define IDB_TB_BLANK_SM 123
+#define IDS_ACTION_DEBUG_WINDOW 124
+#define IDB_VW_REFRESH 124
+#define IDS_ACTION_VIEW_REFRESH 125
+#define IDB_ID_DELETE_DIS 125
+#define IDS_MENU_LAYOUT 126
+#define IDB_ID_DELETE_DIS_SM 126
+#define IDS_MENU_TOOLBARS 127
+#define IDB_ID_DELETE_SM 127
+#define IDS_ACTION_LAYOUT_ID 128
+#define IDB_ID_DIS 128
+#define IDS_ACTION_LAYOUT_TYPE 129
+#define IDB_ID_DIS_SM 129
+#define IDS_ACTION_LAYOUT_LOC 130
+#define IDB_ID_NEW_DIS 130
+#define IDS_ACTION_TB_STANDARD 131
+#define IDB_ID_NEW_DIS_SM 131
+#define IDS_ACTION_OPT_KHIM 132
+#define IDB_ID_NEW_SM 132
+#define IDB_ID_REFRESH_DIS 133
+#define IDS_ACTION_OPT_IDENTS 133
+#define IDS_ACTION_OPT_NOTIF 134
+#define IDB_ID_REFRESH_SM 134
+#define IDS_ACTION_HELP_CTX 135
+#define IDB_ID_REFRESH_DIS_SM 135
+#define IDS_ACTION_HELP_CONTENTS 136
+#define IDB_TK_DELETE_DIS 136
+#define IDS_ACTION_HELP_INDEX 137
+#define IDB_TK_DELETE_DIS_SM 137
+#define IDS_ACTION_HELP_ABOUT 138
+#define IDB_TK_DELETE_SM 138
+#define IDB_TK_DIS_SM 139
+#define IDS_CFG_GENERAL_LONG 139
+#define IDB_TK_NEW_DIS 140
+#define IDS_SAMPLE_STRING 140
+#define IDB_TK_NEW_DIS_SM 141
+#define IDS_NO_CREDS 141
+#define IDB_TK_NEW_SM 142
+#define IDS_WT_INIT_CREDS 142
+#define IDB_TK_REFRESH_DIS 143
+#define IDS_WT_NEW_CREDS 143
+#define IDB_TK_REFRESH_DIS_SM 144
+#define IDS_NC_IDENTITY 144
+#define IDB_TK_REFRESH_SM 145
+#define IDS_NC_IDENTS 145
+#define IDB_TK_SM 146
+#define IDS_NC_CREDTEXT_ID_NONE 146
+#define IDB_HELP_SM 147
+#define IDS_NC_CREDTEXT_ID_ONE 147
+#define IDB_HELP 148
+#define IDS_NC_CREDTEXT_ID_MANY 148
+#define IDB_LOGO_SHADE 149
+#define IDS_NC_CREDTEXT_ID_INVALID 149
+#define IDS_WTPOST_INIT_CREDS 150
+#define IDS_WTPOST_NEW_CREDS 151
+#define IDB_WDG_EXPAND 152
+#define IDS_ACTION_RENEW_CRED 152
+#define IDB_WDG_COLLAPSE 153
+#define IDS_ACTION_DESTROY_CRED 153
+#define IDB_ID_SM 154
+#define IDS_DEFAULT_FONT 154
+#define IDB_WDG_EXPAND_HI 155
+#define IDS_NC_CREDTEXT_TABS 155
+#define IDB_WDG_COLLAPSE_HI 156
+#define IDS_NOTIFY_PREFIX 156
+#define IDB_WDG_CREDTYPE 157
+#define IDS_NOTIFY_READY 157
+#define IDB_WDG_FLAG 158
+#define IDS_NOTIFY_ATTENTION 158
+#define IDB_FLAG_WARN 159
+#define IDS_ALERT_DEFAULT 159
+#define IDB_FLAG_EXPIRED 160
+#define IDS_PACTION_OK 160
+#define IDB_FLAG_CRITICAL 161
+#define IDS_PACTION_CANCEL 161
+#define IDS_PACTION_CLOSE 162
+#define IDD_NC_NEWCRED 162
+#define IDD_NC_BBAR 163
+#define IDS_ALERT_NOSEL_TITLE 163
+#define IDS_ALERT_NOSEL 164
+#define IDI_ENABLED 165
+#define IDS_NC_CREDTEXT_ID_VALID 165
+#define IDI_DISABLED 166
+#define IDS_NC_CREDTEXT_ID_UNCHECKED 166
+#define IDS_PROP_COL_PROPERTY 167
+#define IDS_PROP_COL_VALUE 168
+#define IDI_NOTIFY_NONE 169
+#define IDS_NC_NEW_IDENT 169
+#define IDI_NOTIFY_INFO 170
+#define IDS_NC_CREDTEXT_ID_CHECKING 170
+#define IDI_NOTIFY_WARN 171
+#define IDS_ACTION_OPEN_APP 171
+#define IDI_NOTIFY_ERROR 172
+#define IDS_CTX_NEW_IDENT 172
+#define IDS_CTX_NEW_CREDS 173
+#define IDD_CFG_MAIN 173
+#define IDS_CTX_RENEW_CREDS 174
+#define IDD_CFG_GENERIC 174
+#define IDS_CTX_PROC_NEW_IDENT 175
+#define IDB_LOGO_OPAQUE 175
+#define IDS_CTX_PROC_NEW_CREDS 176
+#define IDD_CFG_GENERAL 176
+#define IDS_CTX_PROC_RENEW_CREDS 177
+#define IDD_CFG_IDENTITIES 177
+#define IDS_ACTION_CLOSE_APP 178
+#define IDD_CFG_NOTIF 178
+#define IDS_NC_FAILED_TITLE 179
+#define IDD_CFG_PLUGINS 179
+#define IDS_CFG_IDENTITIES_SHORT 180
+#define IDD_CFG_IDENTITY 180
+#define IDS_CFG_IDENTITIES_LONG 181
+#define IDI_CFG_DEFAULT 181
+#define IDS_CFG_NOTIF_SHORT 182
+#define IDI_CFG_MODIFIED 182
+#define IDS_CFG_NOTIF_LONG 183
+#define IDI_CFG_APPLIED 183
+#define IDS_CFG_PLUGINS_SHORT 184
+#define IDD_CFG_IDS_TAB 184
+#define IDS_CFG_PLUGINS_LONG 185
+#define IDD_CFG_ID_TAB 185
+#define IDS_CFG_IDENTITY_SHORT 186
+#define IDI_CFG_DELETED 186
+#define IDS_CFG_IDENTITY_LONG 187
+#define IDI_ID 187
+#define IDS_CTX_DESTROY_CREDS 188
+#define IDB_IMPORT_SM_DIS 188
+#define IDS_WARN_EXPIRE 189
+#define IDB_IMPORT 189
+#define IDS_WARN_TITLE 190
+#define IDB_IMPORT_DIS 190
+#define IDS_ALERT_MOREINFO 191
+#define IDB_IMPORT_SM 191
+#define IDS_WARN_EXPIRED 192
+#define IDB_CHPW_SM 192
+#define IDS_WARN_EXPIRE_ID 193
+#define IDB_CHPW 193
+#define IDS_WARN_EXPIRED_ID 194
+#define IDB_CHPW_DIS 194
+#define IDS_WARN_WM_TITLE 195
+#define IDB_CHPW_DIS_SM 195
+#define IDS_WARN_WM_MSG 196
+#define IDD_ABOUT 196
+#define IDS_CFG_ID_TAB_SHORT 197
+#define IDB_TB_SPACE 197
+#define IDS_CFG_ID_TAB_LONG 198
+#define IDB_WDG_STUCK_HI 198
+#define IDS_CFG_IDS_TAB_SHORT 199
+#define IDB_WDG_STICK 199
+#define IDS_CFG_IDS_TAB_LONG 200
+#define IDB_WDG_STICK_HI 200
+#define IDS_CFG_IDS_IDENTITY 201
+#define IDB_WDG_STUCK 201
+#define IDS_ACTION_IMPORT 202
+#define IDS_CTX_IMPORT 203
+#define IDB_FLAG_RENEW 203
+#define IDS_CFG_PI_COL_PLUGINS 204
+#define IDI_APPICON_WARN 204
+#define IDS_PISTATE_FAILUNK 205
+#define IDI_APPICON_EXP 205
+#define IDS_PISTATE_FAILMAX 206
+#define IDI_APPICON_OK 206
+#define IDS_PISTATE_FAILREG 207
+#define IDI_CFG_PLUGIN 207
+#define IDS_PISTATE_FAILDIS 208
+#define IDI_CFG_PLUGIN_ERR 208
+#define IDS_PISTATE_FAILLOD 209
+#define IDI_CFG_PLUGIN_DIS 209
+#define IDS_PISTATE_PLACEHOLD 210
+#define IDD_CFG_APPEAR 210
+#define IDS_PISTATE_REG 211
+#define IDD_CFG_ADDIDENT 211
+#define IDS_PISTATE_HOLD 212
+#define IDS_PISTATE_INIT 213
+#define IDS_PISTATE_RUN 214
+#define IDS_PISTATE_EXIT 215
+#define IDS_CTX_PASSWORD 216
+#define IDS_WT_PASSWORD 217
+#define IDS_WTPOST_PASSWORD 218
+#define IDS_CTX_PROC_PASSWORD 219
+#define IDS_NC_PWD_FAILED_TITLE 220
+#define IDS_CMDLINE_HELP 221
+#define IDS_PACTION_NEXT 222
+#define IDS_ERR_TITLE_NO_IDENTPRO 223
+#define IDS_ERR_MSG_NO_IDENTPRO 224
+#define IDS_ERR_SUGG_NO_IDENTPRO 225
+#define IDS_NC_REN_FAILED_TITLE 226
+#define IDS_CW_DEFAULT 227
+#define IDS_ACTION_OPT_PLUGINS 228
+#define IDS_NC_SETDEF 229
+#define IDS_NC_ID_DEF 230
+#define IDS_NC_ID_WDEF 231
+#define IDS_NC_ID_NDEF 232
+#define IDS_PACTION_YES 233
+#define IDS_PACTION_NO 234
+#define IDS_PACTION_YESALL 235
+#define IDS_PACTION_NOALL 236
+#define IDS_PACTION_KEEP 237
+#define IDS_PACTION_REMOVE 238
+#define IDS_PACTION_DISCARD 239
+#define IDS_CFG_IT_MOD 240
+#define IDS_CFG_IT_APP 241
+#define IDS_CFG_IT_NONE 242
+#define IDS_CFG_NODESC 243
+#define IDS_CFG_P_DELCNFT 244
+#define IDS_CFG_P_DELCNFM 245
+#define IDS_CFG_P_DELCNFS 246
+#define IDS_CFG_P_DELNDEP 247
+#define IDS_CFG_P_ENBCNFT 248
+#define IDS_CFG_P_ENBCNFM 249
+#define IDS_PISTATE_FAILINIT 250
+#define IDS_CFG_P_UNRCNFT 251
+#define IDS_CFG_P_UNRCNFM 252
+#define IDS_CFG_P_UNRCNFS 253
+#define IDS_ACTION_LAYOUT_CUST 254
+#define IDS_APR_HEADER_TEXT 255
+#define IDS_APR_HEADER_TEXT_BOLD 256
+#define IDS_APR_TEXT 257
+#define IDS_APR_TEXT_BOLD 258
+#define IDS_APR_SAMPLE_TEXT_NORMAL 259
+#define IDS_CFG_APPEAR_SHORT 260
+#define IDS_CFG_APPEAR_LONG 261
+#define IDS_ACTION_OPT_APPEAR 262
+#define IDS_APR_SAMPLE_TEXT_SEL 263
+#define IDS_CFG_IDNAME_INV 264
+#define IDS_CFG_IDNAME_PRB 265
+#define IDS_CFG_IDNAME_EXT 266
+#define IDS_CFG_IDNAME_CCR 267
+#define IDS_CFG_IDNAME_CCC 268
+#define IDS_CFG_LOGF_CS 269
+#define IDS_CFG_LOGF_CSR 270
+#define IDS_ACTIONT_PROPERTIES 271
+#define IDS_ACTIONT_EXIT 272
+#define IDS_ACTIONT_SET_DEF_ID 273
+#define IDS_ACTIONT_PASSWD_ID 274
+#define IDS_ACTIONT_NEW_CRED 275
+#define IDS_ACTIONT_RENEW_CRED 276
+#define IDS_ACTIONT_DESTROY_CRED 277
+#define IDS_ACTIONT_VIEW_REFRESH 278
+#define IDS_ACTIONT_OPT_IDENTS 279
+#define IDS_ACTIONT_OPT_KHIM 280
+#define IDS_ACTIONT_OPT_NOTIF 281
+#define IDS_ACTIONT_OPT_PLUGINS 282
+#define IDS_ACTIONT_OPT_APPEAR 283
+#define IDS_ACTIONT_HELP_CTX 284
+#define IDS_ACTIONT_IMPORT 285
+#define IDS_NC_FAILED_TITLE_I 286
+#define IDS_NC_PWD_FAILED_TITLE_I 287
+#define IDS_NC_REN_FAILED_TITLE_I 288
+#define IDS_CFG_IDNAME_NON 289
+#define IDS_MENU_DESTROY_CRED 290
+#define IDS_MENU_RENEW_CRED 291
+#define IDS_ACTION_DESTROY_ALL 292
+#define IDS_ACTION_RENEW_ALL 293
+#define IDS_IDACTION_RENEW 294
+#define IDS_IDACTION_DESTROY 295
+#define IDS_CTX_DESTROY_ID 296
+#define IDS_NCN_IDENT_INVALID 297
+#define IDS_NCN_IDENT_CHECKING 298
+#define IDS_NCN_IDENT_UNKNOWN 299
+#define IDS_REMOTE_FAIL 300
+#define IDS_REMOTE_FAIL_TITLE 301
+#define IDS_IDACTION_NEW 302
+#define IDS_IDACTIONT_NEW 303
+#define IDS_IDACTIONT_RENEW 304
+#define IDS_IDACTIONT_DESTROY 305
+#define IDS_ALERTTYPE_PLUGIN 306
+#define IDS_ALERTTYPE_EXPIRE 307
+#define IDS_ALERTTYPE_RENEWFAIL 308
+#define IDS_ALERTTYPE_ACQUIREFAIL 309
+#define IDS_ALERTTYPE_CHPW 310
+#define IDS_ACTION_LAYOUT_MINI 311
+#define IDS_IDEXPDISP_NOCRED 312
+#define IDS_IDEXPDISP_1CRED 313
+#define IDS_IDEXPDISP_NCRED 314
+#define IDS_CW_DEFAULTTF 315
+#define IDS_CW_TYPEF 316
+#define IDS_CW_EXPIREF 317
+#define IDS_CW_EXPIRED 318
+#define IDC_NC_CREDTEXT_LABEL 1009
+#define IDC_NC_CREDTEXT 1012
+#define IDC_NC_HELP 1017
+#define IDC_NC_ADVANCED 1019
+#define IDC_PP_IDNAME 1026
+#define IDC_PP_IDDEF 1027
+#define IDC_PP_IDSEARCH 1028
+#define IDC_PP_PROPLIST 1035
+#define IDC_PP_CPROPLIST 1036
+#define IDC_NC_TPL_ROW 1039
+#define IDC_NC_TPL_PANEL 1040
+#define IDC_NC_TPL_LABEL 1041
+#define IDC_NC_TPL_INPUT 1042
+#define IDC_NC_TPL_LABEL_LG 1043
+#define IDC_NC_TPL_INPUT_LG 1044
+#define IDC_NC_TPL_ROW_LG 1045
+#define IDC_CFG_NODELIST 1045
+#define IDAPPLY 1048
+#define IDC_CFG_TITLE 1050
+#define IDC_CFG_PANE 1051
+#define IDC_NOTIF_MONITOR 1053
+#define IDC_PP_DUMMY 1054
+#define IDC_NOTIF_RENEW 1055
+#define IDC_NOTIF_RENEW_THR 1056
+#define IDC_NOTIF_WARN1 1057
+#define IDC_NOTIF_WARN1_THR 1058
+#define IDC_NOTIF_WARN2 1059
+#define IDC_NOTIF_WARN2_THR 1060
+#define IDC_CFG_KEEPRUNNING 1061
+#define IDC_CFG_STARTUP_GROUP 1062
+#define IDC_CFG_AUTOSTART 1063
+#define IDC_CFG_AUTOIMPORT 1064
+#define IDC_CFG_AUTOINIT 1065
+#define IDC_CFG_OTHER 1066
+#define IDC_CFG_MONITOR 1069
+#define IDC_CFG_STICKY 1070
+#define IDC_CFG_RENEW 1075
+#define IDC_CFG_REMOVE 1076
+#define IDC_CFG_TAB 1077
+#define IDC_CFG_TARGET 1078
+#define IDC_CFG_PLUGINS 1079
+#define IDC_CFG_DESC 1084
+#define IDC_CFG_LBL_STATE 1085
+#define IDC_CFG_STATE 1086
+#define IDC_CFG_LBL_DEPS 1087
+#define IDC_CFG_DEPS 1088
+#define IDC_CFG_DISABLE 1089
+#define IDC_CFG_ENABLE 1090
+#define IDC_CFG_LBL_MOD 1092
+#define IDC_CFG_MODULE 1093
+#define IDC_CFG_LBL_VEN 1094
+#define IDC_CFG_VENDOR 1095
+#define IDC_CFG_REGISTER 1097
+#define IDC_CFG_NETDETECT 1098
+#define IDC_PP_STICKY 1099
+#define IDC_PRODUCT 1100
+#define IDC_COPYRIGHT 1101
+#define IDC_BUILDINFO 1102
+#define IDC_MODULES 1103
+#define IDC_PP_CONFIG 1104
+#define IDC_CFG_UNREGISTER 1107
+#define IDC_CFG_VERSION 1108
+#define IDC_CFG_ICON 1109
+#define IDC_CFG_LOGTOFILE 1110
+#define IDC_CFG_LOGPATH 1111
+#define IDC_NOTIF_HALFLIFE 1112
+#define IDC_CFG_DESTROYALL 1113
+#define IDC_CFG_SAMPLE_NORMAL 1123
+#define IDC_CFG_REVERT 1127
+#define IDC_CFG_FONTS 1128
+#define IDC_CFG_SAMPLE_BOLD 1129
+#define IDC_CFG_SIZE 1130
+#define IDC_CFG_BOLD 1131
+#define IDC_CFG_ITALICS 1132
+#define IDC_CFG_ADDIDENT 1133
+#define IDC_SM_CTL 1134
+#define IDC_CFG_SHOWLOG 1135
+#define IDC_MED_CTL 1135
+#define IDC_LG_CTL 1136
+#define IDC_SM_LBL 1137
+#define IDC_MED_LBL 1138
+#define IDC_LG_LBL 1139
+#define IDC_CFG_NOTACTION 1141
+#define IDC_CFG_NOTACT_STATIC 1142
+#define IDC_NC_BASIC 1143
+#define IDA_ACTIVATE_MENU 40003
+#define IDA_UP 40004
+#define IDA_DOWN 40005
+#define IDA_LEFT 40006
+#define IDA_RIGHT 40007
+#define IDA_ESC 40008
+#define IDA_ENTER 40009
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 212
+#define _APS_NEXT_COMMAND_VALUE 40010
+#define _APS_NEXT_CONTROL_VALUE 1144
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/src/windows/identity/ui/statusbar.c b/src/windows/identity/ui/statusbar.c
index e5f7e20090..b785dfdd03 100644
--- a/src/windows/identity/ui/statusbar.c
+++ b/src/windows/identity/ui/statusbar.c
@@ -1,208 +1,208 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<khmapp.h>
-#ifdef DEBUG
-#include<assert.h>
-#endif
-
-khm_statusbar_part khm_statusbar_parts[] = {
- {KHUI_SBPART_INFO, 0, KHUI_SB_WTYPE_FILLER, NULL},
- {KHUI_SBPART_NOTICE, 40, KHUI_SB_WTYPE_RELATIVE, NULL},
-#if 0
- /* Not implemented. This was originally intended to provide
- location information. */
- {KHUI_SBPART_LOC, 40, KHUI_SB_WTYPE_ABSOLUTE, NULL}
-#endif
-};
-
-int khm_n_statusbar_parts = sizeof(khm_statusbar_parts) / sizeof(khm_statusbar_part);
-
-HWND khm_hwnd_statusbar = NULL;
-
-LRESULT
-khm_statusbar_notify(LPNMHDR nmhdr) {
- LPNMMOUSE pnmm;
-
- switch(nmhdr->code) {
- case NM_CLICK:
- case NM_DBLCLK:
- pnmm = (LPNMMOUSE) nmhdr;
-
- if (pnmm->dwItemSpec >= (DWORD) khm_n_statusbar_parts)
- return TRUE;
-
- if (khm_statusbar_parts[pnmm->dwItemSpec].id == KHUI_SBPART_NOTICE) {
- /* means, show next notification */
- kmq_post_message(KMSG_ALERT, KMSG_ALERT_SHOW_QUEUED, 0, 0);
- }
-
- return TRUE;
- }
-
- return FALSE;
-}
-
-void
-khui_statusbar_set_parts(HWND parent) {
- int i;
- int fillerwidth;
- int staticwidth;
- int lastx;
- int width;
- RECT r;
- INT * parts;
-
- GetClientRect(parent, &r);
- width = r.right - r.left;
-
- /* calculate fillerwidth and staticwidth */
- staticwidth = 0;
- for(i=0;i<khm_n_statusbar_parts;i++) {
- if(khm_statusbar_parts[i].wtype == KHUI_SB_WTYPE_ABSOLUTE) {
- staticwidth += khm_statusbar_parts[i].width;
- } else if(khm_statusbar_parts[i].wtype == KHUI_SB_WTYPE_RELATIVE) {
- staticwidth += (khm_statusbar_parts[i].width * width) / 100;
- }
- }
-
- fillerwidth = width - staticwidth;
-
- parts = PMALLOC(sizeof(INT) * khm_n_statusbar_parts);
-
- lastx = 0;
- for(i=0;i<khm_n_statusbar_parts;i++) {
- int w = 0;
- switch(khm_statusbar_parts[i].wtype) {
- case KHUI_SB_WTYPE_ABSOLUTE:
- w = khm_statusbar_parts[i].width;
- break;
-
- case KHUI_SB_WTYPE_RELATIVE:
- w = (khm_statusbar_parts[i].width * width) / 100;
- break;
-
- case KHUI_SB_WTYPE_FILLER:
- w = fillerwidth;
- break;
-
- default:
- w = 0;
-#ifdef DEBUG
- assert(FALSE);
-#endif
- }
- lastx += w;
-
- if(i==khm_n_statusbar_parts - 1)
- parts[i] = -1;
- else
- parts[i] = lastx;
- }
-
- SendMessage(
- khm_hwnd_statusbar,
- SB_SETPARTS,
- khm_n_statusbar_parts,
- (LPARAM) parts);
-
- PFREE(parts);
-}
-
-void khm_create_statusbar(HWND parent) {
- HWND hwsb;
-
- hwsb = CreateWindowEx(
- 0,
- STATUSCLASSNAME,
- NULL,
- SBARS_SIZEGRIP | WS_CHILD | WS_VISIBLE,
- 0,0,0,0,
- parent,
- NULL,
- khm_hInstance,
- NULL);
-
- if(!hwsb)
- return;
-
- khm_hwnd_statusbar = hwsb;
-
- khui_statusbar_set_parts(parent);
-
- kmq_post_message(KMSG_ALERT, KMSG_ALERT_CHECK_QUEUE, 0, 0);
-}
-
-void khm_update_statusbar(HWND parent) {
- MoveWindow(khm_hwnd_statusbar, 0, 0, 0, 0, TRUE);
- khui_statusbar_set_parts(parent);
-}
-
-int sb_find_index(int id) {
- int i;
-
- for(i=0;i<khm_n_statusbar_parts;i++) {
- if(khm_statusbar_parts[i].id == id)
- return i;
- }
-
- return -1;
-}
-
-void khm_statusbar_set_part(int id, HICON icon, wchar_t * text) {
- int idx;
-
- if (!khm_hwnd_statusbar)
- return;
-
- idx = sb_find_index(id);
- if(idx < 0)
- return;
-
- if (khm_statusbar_parts[idx].hIcon != NULL) {
- DestroyIcon(khm_statusbar_parts[idx].hIcon);
- khm_statusbar_parts[idx].hIcon = NULL;
- }
-
- if (icon) {
- khm_statusbar_parts[idx].hIcon = CopyImage(icon, IMAGE_ICON,
- GetSystemMetrics(SM_CXSMICON),
- GetSystemMetrics(SM_CYSMICON),
- LR_COPYFROMRESOURCE);
- }
-
- SendMessage(khm_hwnd_statusbar,
- SB_SETICON,
- idx,
- (LPARAM) (khm_statusbar_parts[idx].hIcon ? khm_statusbar_parts[idx].hIcon:icon));
-
- SendMessage(khm_hwnd_statusbar,
- SB_SETTEXT,
- idx,
- (LPARAM) text);
-}
-
-
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<khmapp.h>
+#ifdef DEBUG
+#include<assert.h>
+#endif
+
+khm_statusbar_part khm_statusbar_parts[] = {
+ {KHUI_SBPART_INFO, 0, KHUI_SB_WTYPE_FILLER, NULL},
+ {KHUI_SBPART_NOTICE, 40, KHUI_SB_WTYPE_RELATIVE, NULL},
+#if 0
+ /* Not implemented. This was originally intended to provide
+ location information. */
+ {KHUI_SBPART_LOC, 40, KHUI_SB_WTYPE_ABSOLUTE, NULL}
+#endif
+};
+
+int khm_n_statusbar_parts = sizeof(khm_statusbar_parts) / sizeof(khm_statusbar_part);
+
+HWND khm_hwnd_statusbar = NULL;
+
+LRESULT
+khm_statusbar_notify(LPNMHDR nmhdr) {
+ LPNMMOUSE pnmm;
+
+ switch(nmhdr->code) {
+ case NM_CLICK:
+ case NM_DBLCLK:
+ pnmm = (LPNMMOUSE) nmhdr;
+
+ if (pnmm->dwItemSpec >= (DWORD) khm_n_statusbar_parts)
+ return TRUE;
+
+ if (khm_statusbar_parts[pnmm->dwItemSpec].id == KHUI_SBPART_NOTICE) {
+ /* means, show next notification */
+ kmq_post_message(KMSG_ALERT, KMSG_ALERT_SHOW_QUEUED, 0, 0);
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+void
+khui_statusbar_set_parts(HWND parent) {
+ int i;
+ int fillerwidth;
+ int staticwidth;
+ int lastx;
+ int width;
+ RECT r;
+ INT * parts;
+
+ GetClientRect(parent, &r);
+ width = r.right - r.left;
+
+ /* calculate fillerwidth and staticwidth */
+ staticwidth = 0;
+ for(i=0;i<khm_n_statusbar_parts;i++) {
+ if(khm_statusbar_parts[i].wtype == KHUI_SB_WTYPE_ABSOLUTE) {
+ staticwidth += khm_statusbar_parts[i].width;
+ } else if(khm_statusbar_parts[i].wtype == KHUI_SB_WTYPE_RELATIVE) {
+ staticwidth += (khm_statusbar_parts[i].width * width) / 100;
+ }
+ }
+
+ fillerwidth = width - staticwidth;
+
+ parts = PMALLOC(sizeof(INT) * khm_n_statusbar_parts);
+
+ lastx = 0;
+ for(i=0;i<khm_n_statusbar_parts;i++) {
+ int w = 0;
+ switch(khm_statusbar_parts[i].wtype) {
+ case KHUI_SB_WTYPE_ABSOLUTE:
+ w = khm_statusbar_parts[i].width;
+ break;
+
+ case KHUI_SB_WTYPE_RELATIVE:
+ w = (khm_statusbar_parts[i].width * width) / 100;
+ break;
+
+ case KHUI_SB_WTYPE_FILLER:
+ w = fillerwidth;
+ break;
+
+ default:
+ w = 0;
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ }
+ lastx += w;
+
+ if(i==khm_n_statusbar_parts - 1)
+ parts[i] = -1;
+ else
+ parts[i] = lastx;
+ }
+
+ SendMessage(
+ khm_hwnd_statusbar,
+ SB_SETPARTS,
+ khm_n_statusbar_parts,
+ (LPARAM) parts);
+
+ PFREE(parts);
+}
+
+void khm_create_statusbar(HWND parent) {
+ HWND hwsb;
+
+ hwsb = CreateWindowEx(
+ 0,
+ STATUSCLASSNAME,
+ NULL,
+ SBARS_SIZEGRIP | WS_CHILD | WS_VISIBLE,
+ 0,0,0,0,
+ parent,
+ NULL,
+ khm_hInstance,
+ NULL);
+
+ if(!hwsb)
+ return;
+
+ khm_hwnd_statusbar = hwsb;
+
+ khui_statusbar_set_parts(parent);
+
+ kmq_post_message(KMSG_ALERT, KMSG_ALERT_CHECK_QUEUE, 0, 0);
+}
+
+void khm_update_statusbar(HWND parent) {
+ MoveWindow(khm_hwnd_statusbar, 0, 0, 0, 0, TRUE);
+ khui_statusbar_set_parts(parent);
+}
+
+int sb_find_index(int id) {
+ int i;
+
+ for(i=0;i<khm_n_statusbar_parts;i++) {
+ if(khm_statusbar_parts[i].id == id)
+ return i;
+ }
+
+ return -1;
+}
+
+void khm_statusbar_set_part(int id, HICON icon, wchar_t * text) {
+ int idx;
+
+ if (!khm_hwnd_statusbar)
+ return;
+
+ idx = sb_find_index(id);
+ if(idx < 0)
+ return;
+
+ if (khm_statusbar_parts[idx].hIcon != NULL) {
+ DestroyIcon(khm_statusbar_parts[idx].hIcon);
+ khm_statusbar_parts[idx].hIcon = NULL;
+ }
+
+ if (icon) {
+ khm_statusbar_parts[idx].hIcon = CopyImage(icon, IMAGE_ICON,
+ GetSystemMetrics(SM_CXSMICON),
+ GetSystemMetrics(SM_CYSMICON),
+ LR_COPYFROMRESOURCE);
+ }
+
+ SendMessage(khm_hwnd_statusbar,
+ SB_SETICON,
+ idx,
+ (LPARAM) (khm_statusbar_parts[idx].hIcon ? khm_statusbar_parts[idx].hIcon:icon));
+
+ SendMessage(khm_hwnd_statusbar,
+ SB_SETTEXT,
+ idx,
+ (LPARAM) text);
+}
+
+
diff --git a/src/windows/identity/ui/statusbar.h b/src/windows/identity/ui/statusbar.h
index 6a2b3ddfb6..7b79f69b01 100644
--- a/src/windows/identity/ui/statusbar.h
+++ b/src/windows/identity/ui/statusbar.h
@@ -1,55 +1,55 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#ifndef __KHIMAIRA_STATUSBAR_H
-#define __KHIMAIRA_STATUSBAR_H
-
-typedef struct khm_statusbar_part_t {
- int id;
- int width;
- int wtype; /* one of KHUI_SB_WTYPE_* */
- HICON hIcon;
-} khm_statusbar_part;
-
-#define KHUI_SB_WTYPE_RELATIVE 1
-#define KHUI_SB_WTYPE_ABSOLUTE 2
-#define KHUI_SB_WTYPE_FILLER 4
-
-/* statusbar parts */
-#define KHUI_SBPART_INFO 1
-#define KHUI_SBPART_NOTICE 2
-#define KHUI_SBPART_LOC 3
-
-extern HWND khm_hwnd_statusbar;
-extern khm_statusbar_part khm_statusbar_parts[];
-extern int khm_n_statusbar_parts;
-
-void khm_create_statusbar(HWND p);
-void khm_update_statusbar(HWND parent);
-void khm_statusbar_set_part(int id, HICON icon, wchar_t * text);
-LRESULT khm_statusbar_notify(LPNMHDR nmhdr);
-
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __KHIMAIRA_STATUSBAR_H
+#define __KHIMAIRA_STATUSBAR_H
+
+typedef struct khm_statusbar_part_t {
+ int id;
+ int width;
+ int wtype; /* one of KHUI_SB_WTYPE_* */
+ HICON hIcon;
+} khm_statusbar_part;
+
+#define KHUI_SB_WTYPE_RELATIVE 1
+#define KHUI_SB_WTYPE_ABSOLUTE 2
+#define KHUI_SB_WTYPE_FILLER 4
+
+/* statusbar parts */
+#define KHUI_SBPART_INFO 1
+#define KHUI_SBPART_NOTICE 2
+#define KHUI_SBPART_LOC 3
+
+extern HWND khm_hwnd_statusbar;
+extern khm_statusbar_part khm_statusbar_parts[];
+extern int khm_n_statusbar_parts;
+
+void khm_create_statusbar(HWND p);
+void khm_update_statusbar(HWND parent);
+void khm_statusbar_set_part(int id, HICON icon, wchar_t * text);
+LRESULT khm_statusbar_notify(LPNMHDR nmhdr);
+
+#endif
diff --git a/src/windows/identity/ui/timer.c b/src/windows/identity/ui/timer.c
index 7024481c4a..9a270c3eed 100644
--- a/src/windows/identity/ui/timer.c
+++ b/src/windows/identity/ui/timer.c
@@ -1,1015 +1,1015 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<khmapp.h>
-#include<assert.h>
-
-/* The minimum half time interval is 60 seconds*/
-#define TT_MIN_HALFLIFE_INTERVAL 60
-
-/* as above, in FILETIME units of 100ns */
-#define FT_MIN_HALFLIFE_INTERVAL (TT_MIN_HALFLIFE_INTERVAL * 10000000i64)
-
-/* in seconds */
-#if 0
-khm_int32 khui_timeout_warn = KHUI_DEF_TIMEOUT_WARN;
-khm_int32 khui_timeout_crit = KHUI_DEF_TIMEOUT_CRIT;
-khm_int32 khui_timeout_renew = KHUI_DEF_TIMEOUT_RENEW;
-
-khm_boolean khui_do_renew = TRUE;
-khm_boolean khui_do_warn = TRUE;
-khm_boolean khui_do_crit = TRUE;
-#endif
-
-khui_timer_event * khui_timers = NULL;
-khm_size khui_n_timers = 0;
-khm_size khui_nc_timers = 0;
-
-CRITICAL_SECTION cs_timers;
-
-/*********************************************************************
- Timers
- *********************************************************************/
-
-
-#define KHUI_TIMER_ALLOC_INCR 16
-
-void
-khm_timer_init(void) {
-#ifdef DEBUG
- assert(khui_timers == NULL);
-#endif
-
- khui_nc_timers = KHUI_TIMER_ALLOC_INCR;
- khui_n_timers = 0;
- khui_timers = PMALLOC(sizeof(*khui_timers) * khui_nc_timers);
-
-#ifdef DEBUG
- assert(khui_timers != NULL);
-#endif
-
- InitializeCriticalSection(&cs_timers);
-}
-
-void
-khm_timer_exit(void) {
- EnterCriticalSection(&cs_timers);
-
- if (khui_timers)
- PFREE(khui_timers);
- khui_timers = NULL;
- khui_n_timers = 0;
- khui_nc_timers = 0;
-
- LeaveCriticalSection(&cs_timers);
- DeleteCriticalSection(&cs_timers);
-}
-
-/* called with cs_timers held */
-static void
-tmr_fire_timer(void) {
- int i;
- khm_int64 curtime;
- khm_int64 err;
- khm_int64 next_event;
- int tmr_count[KHUI_N_TTYPES];
- khm_int64 tmr_offset[KHUI_N_TTYPES];
- int t;
- khm_handle eff_ident = NULL;
- khui_timer_type eff_type = 0; /* meaningless */
- int fire_count = 0;
- FILETIME ft;
-
- _begin_task(0);
- _report_cs0(KHERR_DEBUG_1, L"Checking for expired timers");
- _describe();
-
- TimetToFileTimeInterval(KHUI_TIMEEQ_ERROR_SMALL, &ft);
- err = FtToInt(&ft);
- GetSystemTimeAsFileTime(&ft);
- curtime = FtToInt(&ft);
-
- next_event = 0;
-
- ZeroMemory(tmr_count, sizeof(tmr_count));
- ZeroMemory(tmr_offset, sizeof(tmr_offset));
-
- for (i=0; i < (int) khui_n_timers; i++) {
- if (!(khui_timers[i].flags &
- (KHUI_TE_FLAG_STALE | KHUI_TE_FLAG_EXPIRED)) &&
- khui_timers[i].type != KHUI_TTYPE_ID_MARK &&
- khui_timers[i].expire < curtime + err) {
-
- _report_cs3(KHERR_DEBUG_1, L"Expiring timer index=%1!d!, type=%2!d!, key=%3!p!",
- _int32(i), _int32(khui_timers[i].type),
- _cptr(khui_timers[i].key));
-
- t = khui_timers[i].type;
-
- switch(t) {
- case KHUI_TTYPE_ID_RENEW:
- _report_cs1(KHERR_DEBUG_1, L"Renewing identity %1!p!",
- _cptr(khui_timers[i].key));
- khm_cred_renew_identity(khui_timers[i].key);
- khui_timers[i].flags |= KHUI_TE_FLAG_EXPIRED;
- break;
-
- case KHUI_TTYPE_CRED_RENEW:
- /* the equivalence threshold for setting the timer is
- a lot larger than what we are testing for here
- (KHUI_TIMEEQ_ERROR vs KHUI_TIMEEQ_ERROR_SMALL) so
- we assume that it is safe to trigger a renew_cred
- call here without checking if there's an imminent
- renew_identity call. */
- _report_cs1(KHERR_DEBUG_1, L"Renewing credential %1!p!",
- _cptr(khui_timers[i].key));
- khm_cred_renew_cred(khui_timers[i].key);
- khui_timers[i].flags |= KHUI_TE_FLAG_EXPIRED;
- break;
-
- default:
- if (t < KHUI_N_TTYPES) {
- tmr_count[t]++;
- if (tmr_offset[t] == 0 ||
- tmr_offset[t] > khui_timers[i].offset)
- tmr_offset[t] = khui_timers[i].offset;
- if (next_event == 0 ||
- next_event >
- khui_timers[i].expire + khui_timers[i].offset)
- next_event = khui_timers[i].expire +
- khui_timers[i].offset;
-
- if (eff_ident == NULL &&
- (t == KHUI_TTYPE_ID_EXP ||
- t == KHUI_TTYPE_ID_CRIT ||
- t == KHUI_TTYPE_ID_WARN)) {
- /* we don't need a hold since we will be done
- with the handle before the marker is
- expired (the marker is the timer with the
- KHUI_TTYPE_ID_MARK which contains a held
- handle and is not really a timer.) */
- eff_ident = khui_timers[i].key;
- eff_type = t;
- }
-
- fire_count++;
-
- khui_timers[i].flags |= KHUI_TE_FLAG_EXPIRED;
- }
- else {
-#ifdef DEBUG
- assert(FALSE);
-#endif
- }
- }
- }
- }
-
- /* See if we have anything to do */
- if (next_event == 0)
- return;
- else {
- wchar_t fmt[128];
- wchar_t wtime[128];
- wchar_t wmsg[256];
- wchar_t wtitle[64];
- khm_int64 second;
- khui_alert * alert = NULL;
-
- khm_size cb;
-
- next_event -= curtime;
-
- /* Due to measurement errors we may be slightly off on our
- next_event calculation which shows up as '4 mins 59
- seconds' instead of '5 mins' and so on when converting to a
- string. So we add half a second to make the message
- neater. */
- TimetToFileTimeInterval(1, &ft);
- second = FtToInt(&ft);
- next_event += second / 2;
-
- cb = sizeof(wtime);
- ft = IntToFt(next_event);
- FtIntervalToString(&ft,
- wtime,
- &cb);
-
- if (fire_count == 1 &&
- eff_ident != NULL &&
- (eff_type == KHUI_TTYPE_ID_EXP ||
- eff_type == KHUI_TTYPE_ID_CRIT ||
- eff_type == KHUI_TTYPE_ID_WARN)) {
-
- wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
-
- cb = sizeof(idname);
- kcdb_identity_get_name(eff_ident, idname, &cb);
-
- if (next_event < second) {
- LoadString(khm_hInstance, IDS_WARN_EXPIRED_ID,
- fmt, ARRAYLENGTH(fmt));
-
- StringCbPrintf(wmsg, sizeof(wmsg), fmt, idname);
- } else {
- LoadString(khm_hInstance, IDS_WARN_EXPIRE_ID,
- fmt, ARRAYLENGTH(fmt));
-
- StringCbPrintf(wmsg, sizeof(wmsg), fmt, idname, wtime);
- }
- } else {
- if (next_event < second) {
- LoadString(khm_hInstance, IDS_WARN_EXPIRED,
- wmsg, ARRAYLENGTH(wmsg));
- } else {
- LoadString(khm_hInstance, IDS_WARN_EXPIRE,
- fmt, ARRAYLENGTH(fmt));
-
- StringCbPrintf(wmsg, sizeof(wmsg), fmt, wtime);
- }
- }
-
- LoadString(khm_hInstance, IDS_WARN_TITLE,
- wtitle, ARRAYLENGTH(wtitle));
-
- khui_alert_create_simple(wtitle, wmsg, KHERR_WARNING, &alert);
- khui_alert_set_flags(alert,
- KHUI_ALERT_FLAG_REQUEST_BALLOON | KHUI_ALERT_FLAG_DISPATCH_CMD,
- KHUI_ALERT_FLAG_REQUEST_BALLOON | KHUI_ALERT_FLAG_DISPATCH_CMD);
-
- if (eff_ident != NULL) {
- khm_int32 cmd;
-
- cmd = khm_get_identity_new_creds_action(eff_ident);
-
- if (cmd) {
- khui_alert_add_command(alert, cmd);
- khui_alert_add_command(alert, KHUI_PACTION_CLOSE);
- }
- }
-
- khui_alert_show(alert);
- khui_alert_release(alert);
- }
-
- _end_task();
-
-}
-
-void
-khm_timer_fire(HWND hwnd) {
- EnterCriticalSection(&cs_timers);
- tmr_fire_timer();
- LeaveCriticalSection(&cs_timers);
-
- khm_timer_refresh(hwnd);
-}
-
-static int
-tmr_update(khm_handle key, khui_timer_type type, __int64 expire,
- __int64 offset, void * data, khm_boolean reinstate) {
- int i;
- wchar_t name[KCDB_MAXCCH_NAME];
- wchar_t tstamp[128];
- wchar_t *type_str = NULL;
- SYSTEMTIME st;
- FILETIME ft;
- FILETIME ftl;
- khm_size cb;
-
- switch(type) {
- case KHUI_TTYPE_ID_MARK:
- type_str = L"marker";
- break;
-
- case KHUI_TTYPE_CRED_WARN:
- case KHUI_TTYPE_ID_WARN:
- type_str = L"warning";
- break;
-
- case KHUI_TTYPE_CRED_CRIT:
- case KHUI_TTYPE_ID_CRIT:
- type_str = L"critical";
- break;
-
- case KHUI_TTYPE_CRED_EXP:
- case KHUI_TTYPE_ID_EXP:
- type_str = L"expiry";
- break;
-
- case KHUI_TTYPE_CRED_RENEW:
- case KHUI_TTYPE_ID_RENEW:
- type_str = L"renew";
- break;
- }
-
- ft = IntToFt(expire);
- FileTimeToLocalFileTime(&ft, &ftl);
- FileTimeToSystemTime(&ftl, &st);
- StringCbPrintf(tstamp, sizeof(tstamp),
- L"%d-%d-%d %d:%d:%d",
- st.wYear, st.wMonth, st.wDay,
- st.wHour, st.wMinute, st.wSecond);
-
- cb = sizeof(name); name[0] = L'\0';
- if (type_str == NULL) {
-
- _report_cs2(KHERR_DEBUG_1,
- L"Updating uknown timer of type %1!d! exp(%2!s!)",
- _int32(type),
- _cstr(tstamp));
- _resolve();
-
- } else if (type == KHUI_TTYPE_ID_MARK ||
- type == KHUI_TTYPE_ID_WARN ||
- type == KHUI_TTYPE_ID_CRIT ||
- type == KHUI_TTYPE_ID_EXP ||
- type == KHUI_TTYPE_ID_RENEW) {
-
- kcdb_identity_get_name(key, name, &cb);
- _report_cs3(KHERR_DEBUG_1,
- L"Updating identity %1!s! timer for %2!s! exp(%3!s!)",
- _cstr(type_str),
- _cstr(name),
- _cstr(tstamp));
- _resolve();
-
- } else if (type == KHUI_TTYPE_CRED_RENEW ||
- type == KHUI_TTYPE_CRED_WARN ||
- type == KHUI_TTYPE_CRED_CRIT ||
- type == KHUI_TTYPE_CRED_EXP) {
-
- kcdb_cred_get_name(key, name, &cb);
- _report_cs3(KHERR_DEBUG_1,
- L"Updating credential %1!s! timer for %2!s! exp(%3!s!)",
- _cstr(type_str),
- _cstr(name),
- _cstr(tstamp));
- _resolve();
-
- }
-
- for (i=0; i < (int) khui_n_timers; i++) {
- if (khui_timers[i].key == key &&
- khui_timers[i].type == type)
- break;
- }
-
- if (i >= (int) khui_n_timers) {
- i = (int) khui_n_timers;
-
- if (i >= (int) khui_nc_timers) {
- khui_timer_event * nt;
-#ifdef DEBUG
- assert(khui_timers);
-#endif
- khui_nc_timers = UBOUNDSS(i+1, KHUI_TIMER_ALLOC_INCR,
- KHUI_TIMER_ALLOC_INCR);
- nt = PMALLOC(sizeof(*nt) * khui_nc_timers);
-#ifdef DEBUG
- assert(nt);
-#endif
- memcpy(nt, khui_timers, sizeof(*nt) * khui_n_timers);
-
- PFREE(khui_timers);
- khui_timers = nt;
- }
-
- khui_timers[i].key = key;
- khui_timers[i].type = type;
- khui_timers[i].flags = 0;
- khui_n_timers++;
- }
-
- khui_timers[i].expire = expire;
- khui_timers[i].offset = offset;
- khui_timers[i].data = data;
-
- khui_timers[i].flags &= ~KHUI_TE_FLAG_STALE;
- if (reinstate)
- khui_timers[i].flags &= ~KHUI_TE_FLAG_EXPIRED;
-
- return i;
-}
-
-/* called with cs_timers held */
-static int
-tmr_find(khm_handle key, khui_timer_type type,
- khm_int32 and_flags, khm_int32 eq_flags) {
- int i;
-
- eq_flags &= and_flags;
-
- for (i=0; i < (int) khui_n_timers; i++) {
- if (khui_timers[i].key == key &&
- khui_timers[i].type == type &&
- (khui_timers[i].flags & and_flags) == eq_flags)
- break;
- }
-
- if (i < (int) khui_n_timers)
- return i;
- else
- return -1;
-}
-
-/* called with cs_timers held. */
-static FILETIME
-tmr_next_halflife_timeout(int idx, FILETIME * issue, FILETIME * expire) {
- FILETIME lifetime;
- FILETIME current;
- FILETIME ret;
-
- khm_int64 ilife;
- khm_int64 icurrent;
- khm_int64 iexpire;
-
- khm_int64 iret;
-
- GetSystemTimeAsFileTime(&current);
-
- /* wha?? */
- if (CompareFileTime(issue, expire) >= 0)
- return current;
-
- lifetime = FtSub(expire, issue);
- icurrent = FtToInt(&current);
- iexpire = FtToInt(expire);
-
- ilife = FtToInt(&lifetime);
-
- while(ilife / 2 > FT_MIN_HALFLIFE_INTERVAL) {
- ilife /= 2;
-
- /* is this the next renewal time? */
- if (iexpire - ilife > icurrent) {
- if (idx >= 0 &&
- khui_timers[idx].expire == iexpire - ilife &&
- (khui_timers[idx].flags & KHUI_TE_FLAG_EXPIRED)) {
-
- /* if this renewal time has already been triggered
- (note that when the timer fires, it also fires all
- events that are within a few seconds of the current
- time) then we need to set the alarm for the next
- slot down the line. */
-
- continue;
-
- } else {
- break;
- }
- }
- }
-
- iret = iexpire - ilife;
-
- ret = IntToFt(iret);
-
- /* if the previous renew timer had fired, we need to mark it as
- not expired. However, we leave it to the caller to update the
- actual timer and mark it as not stale. */
- if (idx >= 0 &&
- khui_timers[idx].expire < iret) {
-
- khui_timers[idx].flags &= ~KHUI_TE_FLAG_EXPIRED;
- khui_timers[idx].expire = iret;
- }
-
- return ret;
-}
-
-/* called with cs_timers held. Called once for each credential in the
- root credentials set. */
-static khm_int32 KHMAPI
-tmr_cred_apply_proc(khm_handle cred, void * rock) {
- khm_handle ident = NULL;
- int mark_idx;
- int idx;
- FILETIME ft_expiry;
- FILETIME ft_current;
- FILETIME ft_creinst;
- FILETIME ft_cred_expiry;
- FILETIME ft_cred_issue;
- FILETIME ft_issue;
- FILETIME ft;
- FILETIME fte;
- FILETIME ft_reinst;
- khm_size cb;
- wchar_t wname[KCDB_MAXCCH_NAME];
-
- cb = sizeof(wname);
- wname[0] = L'\0';
- kcdb_cred_get_name(cred, wname, &cb);
-
- _report_cs1(KHERR_DEBUG_1, L"Looking at cred [%1!s!]",
- _cstr(wname));
- _resolve();
-
- kcdb_cred_get_identity(cred, &ident);
-#ifdef DEBUG
- assert(ident);
-#endif
-
- /* now get the expiry for the identity*/
- cb = sizeof(ft_expiry);
- if (KHM_FAILED(kcdb_identity_get_attr(ident, KCDB_ATTR_EXPIRE,
- NULL,
- &ft_expiry, &cb))) {
-
- /* failing which, we get the expiry for this credential */
- cb = sizeof(ft_expiry);
- if (KHM_FAILED(kcdb_cred_get_attr(cred, KCDB_ATTR_EXPIRE,
- NULL,
- &ft_expiry, &cb))) {
- /* we don't have an expiry time to work with */
- _report_cs1(KHERR_DEBUG_1, L"Skipping cred [%1!s!]. No expiry time",
- _cstr(wname));
- _resolve();
-
- kcdb_identity_release(ident);
- return KHM_ERROR_SUCCESS;
- } else {
- /* and the time of issue */
- cb = sizeof(ft_issue);
- if (KHM_FAILED(kcdb_cred_get_attr(cred, KCDB_ATTR_ISSUE,
- NULL, &ft_issue, &cb)))
- ZeroMemory(&ft_issue, sizeof(ft_issue));
- }
-
- } else {
- /* also try to get the time of issue. */
- cb = sizeof(ft_issue);
- if (KHM_FAILED(kcdb_identity_get_attr(ident, KCDB_ATTR_ISSUE,
- NULL, &ft_issue, &cb)))
- /* if we fail, we just zero out the time of issue and
- failover to using the threshold value to set the expiry
- timer instead of the half life algorithm. */
- ZeroMemory(&ft_issue, sizeof(ft_issue));
- }
-
- /* and the current time */
- GetSystemTimeAsFileTime(&ft_current);
-
- TimetToFileTimeInterval(KHUI_TIMEEQ_ERROR, &ft_reinst);
-
- ft_creinst = FtAdd(&ft_current, &ft_reinst);
-
- mark_idx = tmr_find(ident, KHUI_TTYPE_ID_MARK, 0, 0);
-
- if (mark_idx < 0) {
- mark_idx = tmr_update(ident, KHUI_TTYPE_ID_MARK, 0, 0, 0, FALSE);
- kcdb_identity_hold(ident);
-#ifdef DEBUG
- assert(mark_idx >= 0);
-#endif
- khui_timers[mark_idx].flags |= KHUI_TE_FLAG_STALE;
- }
-
- if (khui_timers[mark_idx].flags & KHUI_TE_FLAG_STALE) {
- /* first time we are touching this */
- khm_handle csp_cw = NULL;
- khm_handle csp_id = NULL;
- khm_int32 rv;
- khm_int32 t;
- khm_boolean do_warn = TRUE;
- khm_boolean do_crit = TRUE;
- khm_boolean do_renew = TRUE;
- khm_boolean do_halflife = TRUE;
- khm_boolean renew_done = FALSE;
- khm_boolean monitor = TRUE;
- khm_int32 to_warn = KHUI_DEF_TIMEOUT_WARN;
- khm_int32 to_crit = KHUI_DEF_TIMEOUT_CRIT;
- khm_int32 to_renew = KHUI_DEF_TIMEOUT_RENEW;
-
- if (CompareFileTime(&ft_expiry, &ft_current) < 0)
- /* already expired */
- goto _done_with_ident;
-
- rv = khc_open_space(NULL, L"CredWindow", KHM_PERM_READ,
- &csp_cw);
-
- assert(KHM_SUCCEEDED(rv));
-
- rv = kcdb_identity_get_config(ident, KHM_PERM_READ, &csp_id);
- if (KHM_SUCCEEDED(rv)) {
- khc_shadow_space(csp_id, csp_cw);
- khc_close_space(csp_cw);
- } else {
- csp_id = csp_cw;
- }
- csp_cw = NULL;
-
- rv = khc_read_int32(csp_id, L"Monitor", &t);
- if (KHM_SUCCEEDED(rv))
- monitor = t;
-
- rv = khc_read_int32(csp_id, L"AllowWarn", &t);
- if (KHM_SUCCEEDED(rv))
- do_warn = t;
-
- rv = khc_read_int32(csp_id, L"AllowCritical", &t);
- if (KHM_SUCCEEDED(rv))
- do_crit = t;
-
- rv = khc_read_int32(csp_id, L"AllowAutoRenew", &t);
- if (KHM_SUCCEEDED(rv))
- do_renew = t;
-
- rv = khc_read_int32(csp_id, L"RenewAtHalfLife", &t);
- if (KHM_SUCCEEDED(rv))
- do_halflife = t;
-
- rv = khc_read_int32(csp_id, L"WarnThreshold", &t);
- if (KHM_SUCCEEDED(rv))
- to_warn = t;
-
- rv = khc_read_int32(csp_id, L"CriticalThreshold", &t);
- if (KHM_SUCCEEDED(rv))
- to_crit = t;
-
- rv = khc_read_int32(csp_id, L"AutoRenewThreshold", &t);
- if (KHM_SUCCEEDED(rv))
- to_renew = t;
-
- khc_close_space(csp_id);
-
- if (monitor && do_renew) {
- int prev;
-
- TimetToFileTimeInterval(to_renew, &ft);
-
- prev =
- tmr_find(ident, KHUI_TTYPE_ID_RENEW, 0, 0);
-
- if (do_halflife && (ft_issue.dwLowDateTime != 0 ||
- ft_issue.dwHighDateTime != 0))
- fte = tmr_next_halflife_timeout(prev, &ft_issue, &ft_expiry);
- else
- fte = FtSub(&ft_expiry, &ft);
-
- /* we set off a renew notification immediately if the
- renew threshold has passed but a renew was never sent.
- This maybe because that NetIDMgr was started at the
- last minute, or because for some reason the renew timer
- could not be triggered earlier. */
-
- if (CompareFileTime(&fte, &ft_current) > 0 ||
- prev == -1 ||
- !(khui_timers[prev].flags & KHUI_TE_FLAG_EXPIRED)) {
-
- if (CompareFileTime(&fte, &ft_current) < 0)
- fte = ft_current;
-
- tmr_update(ident, KHUI_TTYPE_ID_RENEW,
- FtToInt(&fte), FtToInt(&ft), 0,
- CompareFileTime(&fte,&ft_creinst) > 0);
- renew_done = TRUE;
-
- } else {
-
- /* special case. If the renew timer was in the past
- and it was expired, then we retain the record as
- long as the credentials are around. If the renewal
- failed we don't want to automatically retry
- everytime we check the timers. */
-
- tmr_update(ident, KHUI_TTYPE_ID_RENEW,
- FtToInt(&fte), FtToInt(&ft), 0, FALSE);
-
- }
- }
-
- if (monitor && do_warn && !renew_done) {
-
- TimetToFileTimeInterval(to_warn, &ft);
- fte = FtSub(&ft_expiry, &ft);
-
- if (CompareFileTime(&fte, &ft_current) > 0)
- tmr_update(ident, KHUI_TTYPE_ID_WARN,
- FtToInt(&fte), FtToInt(&ft), 0,
- CompareFileTime(&fte, &ft_creinst) > 0);
- }
-
- if (monitor && do_crit && !renew_done) {
- TimetToFileTimeInterval(to_crit, &ft);
- fte = FtSub(&ft_expiry, &ft);
-
- if (CompareFileTime(&fte, &ft_current) > 0)
- tmr_update(ident, KHUI_TTYPE_ID_CRIT,
- FtToInt(&fte), FtToInt(&ft), 0,
- CompareFileTime(&fte, &ft_creinst) > 0);
- }
-
- if (monitor && !renew_done) {
- if (CompareFileTime(&ft_expiry, &ft_current) > 0)
- tmr_update(ident, KHUI_TTYPE_ID_EXP,
- FtToInt(&ft_expiry), 0, 0,
- CompareFileTime(&fte, &ft_creinst) > 0);
- }
-
- _done_with_ident:
- khui_timers[mark_idx].flags &= ~KHUI_TE_FLAG_STALE;
- }
-
- cb = sizeof(ft_cred_expiry);
- if (KHM_FAILED(kcdb_cred_get_attr(cred, KCDB_ATTR_EXPIRE,
- NULL,
- &ft_cred_expiry,
- &cb))) {
- _report_cs1(KHERR_DEBUG_1, L"Skipping cred [%1!s!]. Can't lookup cred expiry",
- _cstr(wname));
- _resolve();
- goto _cleanup;
- }
-
- cb = sizeof(ft_cred_issue);
- if (KHM_FAILED(kcdb_cred_get_attr(cred, KCDB_ATTR_ISSUE,
- NULL,
- &ft_cred_issue,
- &cb))) {
-
- ZeroMemory(&ft_cred_issue, sizeof(ft_cred_issue));
-
- }
-
- TimetToFileTimeInterval(KHUI_TIMEEQ_ERROR, &ft);
-
- {
- /* if the credential has a longer lifetime than the identity,
- or it expires within KHUI_TIMEEQ_ERROR seconds of the
- identity, then we don't need to set any alerts for this
- credential. */
-
- FILETIME ft_delta;
-
- ft_delta = FtSub(&ft_expiry, &ft_cred_expiry);
-
- if (CompareFileTime(&ft_cred_expiry, &ft_expiry) >= 0 ||
- CompareFileTime(&ft_delta, &ft) < 0) {
-
- _report_cs1(KHERR_DEBUG_1,
- L"Skipping credential [%1!s!]. The expiry time is too close to the identity expiry.",
- _cstr(wname));
- _resolve();
- goto _cleanup;
- }
- }
-
- if ((idx = tmr_find(ident, KHUI_TTYPE_ID_WARN, 0, 0)) >= 0 &&
- !(khui_timers[idx].flags & KHUI_TE_FLAG_STALE)) {
-
- fte = IntToFt(FtToInt(&ft_cred_expiry) - khui_timers[idx].offset);
- if (CompareFileTime(&fte, &ft_current) > 0) {
- tmr_update(cred, KHUI_TTYPE_CRED_WARN,
- FtToInt(&fte),
- khui_timers[idx].offset, 0,
- CompareFileTime(&fte, &ft_creinst) > 0);
- kcdb_cred_hold(cred);
- }
- }
-
- if ((idx = tmr_find(ident, KHUI_TTYPE_ID_CRIT, 0, 0)) >= 0 &&
- !(khui_timers[idx].flags & KHUI_TE_FLAG_STALE)) {
-
- fte = IntToFt(FtToInt(&ft_cred_expiry) - khui_timers[idx].offset);
- if (CompareFileTime(&fte, &ft_current) > 0) {
- tmr_update(cred, KHUI_TTYPE_CRED_CRIT,
- FtToInt(&fte),
- khui_timers[idx].offset, 0,
- CompareFileTime(&fte, &ft_creinst) > 0);
- kcdb_cred_hold(cred);
- }
- }
-
- if ((idx = tmr_find(ident, KHUI_TTYPE_ID_RENEW, 0, 0)) >= 0 &&
- !(khui_timers[idx].flags & KHUI_TE_FLAG_STALE)) {
-
- int cidx = tmr_find(cred, KHUI_TTYPE_CRED_RENEW, 0, 0);
-
- if (ft_cred_issue.dwLowDateTime == 0 &&
- ft_cred_issue.dwHighDateTime == 0) {
- fte = IntToFt(FtToInt(&ft_cred_expiry) - khui_timers[idx].offset);
- /* a special case, for a credential whose remaining
- lifetime is less than the offset, we try half life on
- the current time and the expiry. */
- if (CompareFileTime(&fte, &ft_current) <= 0 &&
- CompareFileTime(&ft_current, &ft_expiry) < 0) {
- fte = tmr_next_halflife_timeout(cidx, &ft_current, &ft_cred_expiry);
-#if 0
- /* now, if we already have a renew timer for this
- credential that hasn't expired yet and that is set
- for earlier than fte, we let it be. */
- if (cidx >= 0 &&
- khui_timers[cidx].expire < FtToInt(&fte) &&
- khui_timers[cidx].expire > FtToInt(&ft_current) &&
- !(khui_timers[cidx].flags & KHUI_TE_FLAG_EXPIRED)) {
-
- fte = IntToFt(khui_timers[cidx].expire);
-
- }
-#endif
- }
- } else {
- fte = tmr_next_halflife_timeout(cidx, &ft_cred_issue, &ft_cred_expiry);
- }
-
- if (CompareFileTime(&fte, &ft_current) > 0) {
- tmr_update(cred, KHUI_TTYPE_CRED_RENEW,
- FtToInt(&fte),
- khui_timers[idx].offset, 0,
- CompareFileTime(&fte, &ft_creinst) > 0);
- kcdb_cred_hold(cred);
- }
- }
-
- if ((idx = tmr_find(ident, KHUI_TTYPE_ID_EXP, 0, 0)) >= 0 &&
- !(khui_timers[idx].flags & KHUI_TE_FLAG_STALE)) {
-
- if (CompareFileTime(&ft_cred_expiry, &ft_current) > 0) {
- tmr_update(cred, KHUI_TTYPE_CRED_EXP,
- FtToInt(&ft_cred_expiry),
- 0, 0,
- CompareFileTime(&ft_cred_expiry, &ft_creinst) > 0);
- }
- }
-
- _cleanup:
-
- if (ident)
- kcdb_identity_release(ident);
-
- return KHM_ERROR_SUCCESS;
-}
-
-/* called with cs_timers held */
-static void
-tmr_purge(void) {
- int i, j;
-
- for (i=0,j=0; i < (int) khui_n_timers; i++) {
- if (khui_timers[i].flags & KHUI_TE_FLAG_STALE) {
- if (khui_timers[i].type == KHUI_TTYPE_ID_MARK) {
- kcdb_identity_release(khui_timers[i].key);
-#ifdef DEBUG
- {
- int idx;
-
- idx = tmr_find(khui_timers[i].key,
- KHUI_TTYPE_ID_CRIT, 0, 0);
- assert(idx < 0 ||
- (khui_timers[idx].flags &
- KHUI_TE_FLAG_STALE));
-
- idx = tmr_find(khui_timers[i].key,
- KHUI_TTYPE_ID_RENEW, 0, 0);
- assert(idx < 0 ||
- (khui_timers[idx].flags &
- KHUI_TE_FLAG_STALE));
-
- idx = tmr_find(khui_timers[i].key,
- KHUI_TTYPE_ID_WARN, 0, 0);
- assert(idx < 0 ||
- (khui_timers[idx].flags &
- KHUI_TE_FLAG_STALE));
-
- idx = tmr_find(khui_timers[i].key,
- KHUI_TTYPE_ID_EXP, 0, 0);
- assert(idx < 0 ||
- (khui_timers[idx].flags &
- KHUI_TE_FLAG_STALE));
- }
-#endif
- } else if (khui_timers[i].type == KHUI_TTYPE_CRED_WARN ||
- khui_timers[i].type == KHUI_TTYPE_CRED_CRIT ||
- khui_timers[i].type == KHUI_TTYPE_CRED_RENEW ||
- khui_timers[i].type == KHUI_TTYPE_CRED_EXP) {
- kcdb_cred_release(khui_timers[i].key);
- }
- } else {
- if (i != j)
- khui_timers[j] = khui_timers[i];
- j++;
- }
- }
-
- khui_n_timers = j;
-}
-
-/* go through all the credentials and set timers as appropriate. hwnd
- is the window that will receive the timer events.*/
-void
-khm_timer_refresh(HWND hwnd) {
- int i;
- khm_int64 next_event = 0;
- khm_int64 curtime;
- khm_int64 diff;
-
- _begin_task(0);
- _report_cs0(KHERR_DEBUG_1, L"Refreshing timers");
- _describe();
-
- EnterCriticalSection(&cs_timers);
-
- KillTimer(hwnd, KHUI_TRIGGER_TIMER_ID);
-
- /* When refreshing timers, we go through all of them and mark them
- as stale. Then we go through the credentials in the root
- credential set and add or refresh the timers associated with
- each identity and credential. Once this is done, we remove the
- timers that are still stale, since they are no longer in
- use. */
-
- for (i=0; i < (int) khui_n_timers; i++) {
-#ifdef NOT_IMPLEMENTED_YET
- if (khui_timers[i].type == KHUI_TTYPE_BMSG ||
- khui_timers[i].type == KHUI_TTYPE_SMSG) {
- khui_timers[i].flags &= ~KHUI_TE_FLAG_STALE;
- } else {
-#endif
-
- khui_timers[i].flags |= KHUI_TE_FLAG_STALE;
-
-#ifdef NOT_IMPLEMENTED_YET
- }
-#endif
- }
-
- _report_cs1(KHERR_DEBUG_1, L"Starting with %1!d! timers",
- _int32(khui_n_timers));
-
- kcdb_credset_apply(NULL,
- tmr_cred_apply_proc,
- NULL);
-
- tmr_purge();
-
- _report_cs1(KHERR_DEBUG_1, L"Leaving with %1!d! timers",
- _int32(khui_n_timers));
-
- _check_next_event:
-
- /* Before we return, we should check if any timers are set to
- expire right now. If there are, we should fire the timer
- before returning. */
-
- next_event = 0;
- for (i=0; i < (int) khui_n_timers; i++) {
- if (!(khui_timers[i].flags & KHUI_TE_FLAG_EXPIRED) &&
- khui_timers[i].type != KHUI_TTYPE_ID_MARK &&
- (next_event == 0 ||
- next_event > khui_timers[i].expire)) {
-
- next_event = khui_timers[i].expire;
-
- }
- }
-
- if (next_event != 0) {
- FILETIME ft;
-
- GetSystemTimeAsFileTime(&ft);
- curtime = FtToInt(&ft);
-
- TimetToFileTimeInterval(KHUI_TIMEEQ_ERROR_SMALL, &ft);
- diff = FtToInt(&ft);
-
- if (curtime + diff > next_event) {
- tmr_fire_timer();
- goto _check_next_event;
- } else {
- diff = next_event - curtime;
- ft = IntToFt(diff);
- SetTimer(hwnd,
- KHUI_TRIGGER_TIMER_ID,
- FtIntervalToMilliseconds(&ft),
- NULL);
- }
- }
-
- LeaveCriticalSection(&cs_timers);
-
- _end_task();
-}
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<khmapp.h>
+#include<assert.h>
+
+/* The minimum half time interval is 60 seconds*/
+#define TT_MIN_HALFLIFE_INTERVAL 60
+
+/* as above, in FILETIME units of 100ns */
+#define FT_MIN_HALFLIFE_INTERVAL (TT_MIN_HALFLIFE_INTERVAL * 10000000i64)
+
+/* in seconds */
+#if 0
+khm_int32 khui_timeout_warn = KHUI_DEF_TIMEOUT_WARN;
+khm_int32 khui_timeout_crit = KHUI_DEF_TIMEOUT_CRIT;
+khm_int32 khui_timeout_renew = KHUI_DEF_TIMEOUT_RENEW;
+
+khm_boolean khui_do_renew = TRUE;
+khm_boolean khui_do_warn = TRUE;
+khm_boolean khui_do_crit = TRUE;
+#endif
+
+khui_timer_event * khui_timers = NULL;
+khm_size khui_n_timers = 0;
+khm_size khui_nc_timers = 0;
+
+CRITICAL_SECTION cs_timers;
+
+/*********************************************************************
+ Timers
+ *********************************************************************/
+
+
+#define KHUI_TIMER_ALLOC_INCR 16
+
+void
+khm_timer_init(void) {
+#ifdef DEBUG
+ assert(khui_timers == NULL);
+#endif
+
+ khui_nc_timers = KHUI_TIMER_ALLOC_INCR;
+ khui_n_timers = 0;
+ khui_timers = PMALLOC(sizeof(*khui_timers) * khui_nc_timers);
+
+#ifdef DEBUG
+ assert(khui_timers != NULL);
+#endif
+
+ InitializeCriticalSection(&cs_timers);
+}
+
+void
+khm_timer_exit(void) {
+ EnterCriticalSection(&cs_timers);
+
+ if (khui_timers)
+ PFREE(khui_timers);
+ khui_timers = NULL;
+ khui_n_timers = 0;
+ khui_nc_timers = 0;
+
+ LeaveCriticalSection(&cs_timers);
+ DeleteCriticalSection(&cs_timers);
+}
+
+/* called with cs_timers held */
+static void
+tmr_fire_timer(void) {
+ int i;
+ khm_int64 curtime;
+ khm_int64 err;
+ khm_int64 next_event;
+ int tmr_count[KHUI_N_TTYPES];
+ khm_int64 tmr_offset[KHUI_N_TTYPES];
+ int t;
+ khm_handle eff_ident = NULL;
+ khui_timer_type eff_type = 0; /* meaningless */
+ int fire_count = 0;
+ FILETIME ft;
+
+ _begin_task(0);
+ _report_cs0(KHERR_DEBUG_1, L"Checking for expired timers");
+ _describe();
+
+ TimetToFileTimeInterval(KHUI_TIMEEQ_ERROR_SMALL, &ft);
+ err = FtToInt(&ft);
+ GetSystemTimeAsFileTime(&ft);
+ curtime = FtToInt(&ft);
+
+ next_event = 0;
+
+ ZeroMemory(tmr_count, sizeof(tmr_count));
+ ZeroMemory(tmr_offset, sizeof(tmr_offset));
+
+ for (i=0; i < (int) khui_n_timers; i++) {
+ if (!(khui_timers[i].flags &
+ (KHUI_TE_FLAG_STALE | KHUI_TE_FLAG_EXPIRED)) &&
+ khui_timers[i].type != KHUI_TTYPE_ID_MARK &&
+ khui_timers[i].expire < curtime + err) {
+
+ _report_cs3(KHERR_DEBUG_1, L"Expiring timer index=%1!d!, type=%2!d!, key=%3!p!",
+ _int32(i), _int32(khui_timers[i].type),
+ _cptr(khui_timers[i].key));
+
+ t = khui_timers[i].type;
+
+ switch(t) {
+ case KHUI_TTYPE_ID_RENEW:
+ _report_cs1(KHERR_DEBUG_1, L"Renewing identity %1!p!",
+ _cptr(khui_timers[i].key));
+ khm_cred_renew_identity(khui_timers[i].key);
+ khui_timers[i].flags |= KHUI_TE_FLAG_EXPIRED;
+ break;
+
+ case KHUI_TTYPE_CRED_RENEW:
+ /* the equivalence threshold for setting the timer is
+ a lot larger than what we are testing for here
+ (KHUI_TIMEEQ_ERROR vs KHUI_TIMEEQ_ERROR_SMALL) so
+ we assume that it is safe to trigger a renew_cred
+ call here without checking if there's an imminent
+ renew_identity call. */
+ _report_cs1(KHERR_DEBUG_1, L"Renewing credential %1!p!",
+ _cptr(khui_timers[i].key));
+ khm_cred_renew_cred(khui_timers[i].key);
+ khui_timers[i].flags |= KHUI_TE_FLAG_EXPIRED;
+ break;
+
+ default:
+ if (t < KHUI_N_TTYPES) {
+ tmr_count[t]++;
+ if (tmr_offset[t] == 0 ||
+ tmr_offset[t] > khui_timers[i].offset)
+ tmr_offset[t] = khui_timers[i].offset;
+ if (next_event == 0 ||
+ next_event >
+ khui_timers[i].expire + khui_timers[i].offset)
+ next_event = khui_timers[i].expire +
+ khui_timers[i].offset;
+
+ if (eff_ident == NULL &&
+ (t == KHUI_TTYPE_ID_EXP ||
+ t == KHUI_TTYPE_ID_CRIT ||
+ t == KHUI_TTYPE_ID_WARN)) {
+ /* we don't need a hold since we will be done
+ with the handle before the marker is
+ expired (the marker is the timer with the
+ KHUI_TTYPE_ID_MARK which contains a held
+ handle and is not really a timer.) */
+ eff_ident = khui_timers[i].key;
+ eff_type = t;
+ }
+
+ fire_count++;
+
+ khui_timers[i].flags |= KHUI_TE_FLAG_EXPIRED;
+ }
+ else {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ }
+ }
+ }
+ }
+
+ /* See if we have anything to do */
+ if (next_event == 0)
+ return;
+ else {
+ wchar_t fmt[128];
+ wchar_t wtime[128];
+ wchar_t wmsg[256];
+ wchar_t wtitle[64];
+ khm_int64 second;
+ khui_alert * alert = NULL;
+
+ khm_size cb;
+
+ next_event -= curtime;
+
+ /* Due to measurement errors we may be slightly off on our
+ next_event calculation which shows up as '4 mins 59
+ seconds' instead of '5 mins' and so on when converting to a
+ string. So we add half a second to make the message
+ neater. */
+ TimetToFileTimeInterval(1, &ft);
+ second = FtToInt(&ft);
+ next_event += second / 2;
+
+ cb = sizeof(wtime);
+ ft = IntToFt(next_event);
+ FtIntervalToString(&ft,
+ wtime,
+ &cb);
+
+ if (fire_count == 1 &&
+ eff_ident != NULL &&
+ (eff_type == KHUI_TTYPE_ID_EXP ||
+ eff_type == KHUI_TTYPE_ID_CRIT ||
+ eff_type == KHUI_TTYPE_ID_WARN)) {
+
+ wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
+
+ cb = sizeof(idname);
+ kcdb_identity_get_name(eff_ident, idname, &cb);
+
+ if (next_event < second) {
+ LoadString(khm_hInstance, IDS_WARN_EXPIRED_ID,
+ fmt, ARRAYLENGTH(fmt));
+
+ StringCbPrintf(wmsg, sizeof(wmsg), fmt, idname);
+ } else {
+ LoadString(khm_hInstance, IDS_WARN_EXPIRE_ID,
+ fmt, ARRAYLENGTH(fmt));
+
+ StringCbPrintf(wmsg, sizeof(wmsg), fmt, idname, wtime);
+ }
+ } else {
+ if (next_event < second) {
+ LoadString(khm_hInstance, IDS_WARN_EXPIRED,
+ wmsg, ARRAYLENGTH(wmsg));
+ } else {
+ LoadString(khm_hInstance, IDS_WARN_EXPIRE,
+ fmt, ARRAYLENGTH(fmt));
+
+ StringCbPrintf(wmsg, sizeof(wmsg), fmt, wtime);
+ }
+ }
+
+ LoadString(khm_hInstance, IDS_WARN_TITLE,
+ wtitle, ARRAYLENGTH(wtitle));
+
+ khui_alert_create_simple(wtitle, wmsg, KHERR_WARNING, &alert);
+ khui_alert_set_flags(alert,
+ KHUI_ALERT_FLAG_REQUEST_BALLOON | KHUI_ALERT_FLAG_DISPATCH_CMD,
+ KHUI_ALERT_FLAG_REQUEST_BALLOON | KHUI_ALERT_FLAG_DISPATCH_CMD);
+
+ if (eff_ident != NULL) {
+ khm_int32 cmd;
+
+ cmd = khm_get_identity_new_creds_action(eff_ident);
+
+ if (cmd) {
+ khui_alert_add_command(alert, cmd);
+ khui_alert_add_command(alert, KHUI_PACTION_CLOSE);
+ }
+ }
+
+ khui_alert_show(alert);
+ khui_alert_release(alert);
+ }
+
+ _end_task();
+
+}
+
+void
+khm_timer_fire(HWND hwnd) {
+ EnterCriticalSection(&cs_timers);
+ tmr_fire_timer();
+ LeaveCriticalSection(&cs_timers);
+
+ khm_timer_refresh(hwnd);
+}
+
+static int
+tmr_update(khm_handle key, khui_timer_type type, __int64 expire,
+ __int64 offset, void * data, khm_boolean reinstate) {
+ int i;
+ wchar_t name[KCDB_MAXCCH_NAME];
+ wchar_t tstamp[128];
+ wchar_t *type_str = NULL;
+ SYSTEMTIME st;
+ FILETIME ft;
+ FILETIME ftl;
+ khm_size cb;
+
+ switch(type) {
+ case KHUI_TTYPE_ID_MARK:
+ type_str = L"marker";
+ break;
+
+ case KHUI_TTYPE_CRED_WARN:
+ case KHUI_TTYPE_ID_WARN:
+ type_str = L"warning";
+ break;
+
+ case KHUI_TTYPE_CRED_CRIT:
+ case KHUI_TTYPE_ID_CRIT:
+ type_str = L"critical";
+ break;
+
+ case KHUI_TTYPE_CRED_EXP:
+ case KHUI_TTYPE_ID_EXP:
+ type_str = L"expiry";
+ break;
+
+ case KHUI_TTYPE_CRED_RENEW:
+ case KHUI_TTYPE_ID_RENEW:
+ type_str = L"renew";
+ break;
+ }
+
+ ft = IntToFt(expire);
+ FileTimeToLocalFileTime(&ft, &ftl);
+ FileTimeToSystemTime(&ftl, &st);
+ StringCbPrintf(tstamp, sizeof(tstamp),
+ L"%d-%d-%d %d:%d:%d",
+ st.wYear, st.wMonth, st.wDay,
+ st.wHour, st.wMinute, st.wSecond);
+
+ cb = sizeof(name); name[0] = L'\0';
+ if (type_str == NULL) {
+
+ _report_cs2(KHERR_DEBUG_1,
+ L"Updating uknown timer of type %1!d! exp(%2!s!)",
+ _int32(type),
+ _cstr(tstamp));
+ _resolve();
+
+ } else if (type == KHUI_TTYPE_ID_MARK ||
+ type == KHUI_TTYPE_ID_WARN ||
+ type == KHUI_TTYPE_ID_CRIT ||
+ type == KHUI_TTYPE_ID_EXP ||
+ type == KHUI_TTYPE_ID_RENEW) {
+
+ kcdb_identity_get_name(key, name, &cb);
+ _report_cs3(KHERR_DEBUG_1,
+ L"Updating identity %1!s! timer for %2!s! exp(%3!s!)",
+ _cstr(type_str),
+ _cstr(name),
+ _cstr(tstamp));
+ _resolve();
+
+ } else if (type == KHUI_TTYPE_CRED_RENEW ||
+ type == KHUI_TTYPE_CRED_WARN ||
+ type == KHUI_TTYPE_CRED_CRIT ||
+ type == KHUI_TTYPE_CRED_EXP) {
+
+ kcdb_cred_get_name(key, name, &cb);
+ _report_cs3(KHERR_DEBUG_1,
+ L"Updating credential %1!s! timer for %2!s! exp(%3!s!)",
+ _cstr(type_str),
+ _cstr(name),
+ _cstr(tstamp));
+ _resolve();
+
+ }
+
+ for (i=0; i < (int) khui_n_timers; i++) {
+ if (khui_timers[i].key == key &&
+ khui_timers[i].type == type)
+ break;
+ }
+
+ if (i >= (int) khui_n_timers) {
+ i = (int) khui_n_timers;
+
+ if (i >= (int) khui_nc_timers) {
+ khui_timer_event * nt;
+#ifdef DEBUG
+ assert(khui_timers);
+#endif
+ khui_nc_timers = UBOUNDSS(i+1, KHUI_TIMER_ALLOC_INCR,
+ KHUI_TIMER_ALLOC_INCR);
+ nt = PMALLOC(sizeof(*nt) * khui_nc_timers);
+#ifdef DEBUG
+ assert(nt);
+#endif
+ memcpy(nt, khui_timers, sizeof(*nt) * khui_n_timers);
+
+ PFREE(khui_timers);
+ khui_timers = nt;
+ }
+
+ khui_timers[i].key = key;
+ khui_timers[i].type = type;
+ khui_timers[i].flags = 0;
+ khui_n_timers++;
+ }
+
+ khui_timers[i].expire = expire;
+ khui_timers[i].offset = offset;
+ khui_timers[i].data = data;
+
+ khui_timers[i].flags &= ~KHUI_TE_FLAG_STALE;
+ if (reinstate)
+ khui_timers[i].flags &= ~KHUI_TE_FLAG_EXPIRED;
+
+ return i;
+}
+
+/* called with cs_timers held */
+static int
+tmr_find(khm_handle key, khui_timer_type type,
+ khm_int32 and_flags, khm_int32 eq_flags) {
+ int i;
+
+ eq_flags &= and_flags;
+
+ for (i=0; i < (int) khui_n_timers; i++) {
+ if (khui_timers[i].key == key &&
+ khui_timers[i].type == type &&
+ (khui_timers[i].flags & and_flags) == eq_flags)
+ break;
+ }
+
+ if (i < (int) khui_n_timers)
+ return i;
+ else
+ return -1;
+}
+
+/* called with cs_timers held. */
+static FILETIME
+tmr_next_halflife_timeout(int idx, FILETIME * issue, FILETIME * expire) {
+ FILETIME lifetime;
+ FILETIME current;
+ FILETIME ret;
+
+ khm_int64 ilife;
+ khm_int64 icurrent;
+ khm_int64 iexpire;
+
+ khm_int64 iret;
+
+ GetSystemTimeAsFileTime(&current);
+
+ /* wha?? */
+ if (CompareFileTime(issue, expire) >= 0)
+ return current;
+
+ lifetime = FtSub(expire, issue);
+ icurrent = FtToInt(&current);
+ iexpire = FtToInt(expire);
+
+ ilife = FtToInt(&lifetime);
+
+ while(ilife / 2 > FT_MIN_HALFLIFE_INTERVAL) {
+ ilife /= 2;
+
+ /* is this the next renewal time? */
+ if (iexpire - ilife > icurrent) {
+ if (idx >= 0 &&
+ khui_timers[idx].expire == iexpire - ilife &&
+ (khui_timers[idx].flags & KHUI_TE_FLAG_EXPIRED)) {
+
+ /* if this renewal time has already been triggered
+ (note that when the timer fires, it also fires all
+ events that are within a few seconds of the current
+ time) then we need to set the alarm for the next
+ slot down the line. */
+
+ continue;
+
+ } else {
+ break;
+ }
+ }
+ }
+
+ iret = iexpire - ilife;
+
+ ret = IntToFt(iret);
+
+ /* if the previous renew timer had fired, we need to mark it as
+ not expired. However, we leave it to the caller to update the
+ actual timer and mark it as not stale. */
+ if (idx >= 0 &&
+ khui_timers[idx].expire < iret) {
+
+ khui_timers[idx].flags &= ~KHUI_TE_FLAG_EXPIRED;
+ khui_timers[idx].expire = iret;
+ }
+
+ return ret;
+}
+
+/* called with cs_timers held. Called once for each credential in the
+ root credentials set. */
+static khm_int32 KHMAPI
+tmr_cred_apply_proc(khm_handle cred, void * rock) {
+ khm_handle ident = NULL;
+ int mark_idx;
+ int idx;
+ FILETIME ft_expiry;
+ FILETIME ft_current;
+ FILETIME ft_creinst;
+ FILETIME ft_cred_expiry;
+ FILETIME ft_cred_issue;
+ FILETIME ft_issue;
+ FILETIME ft;
+ FILETIME fte;
+ FILETIME ft_reinst;
+ khm_size cb;
+ wchar_t wname[KCDB_MAXCCH_NAME];
+
+ cb = sizeof(wname);
+ wname[0] = L'\0';
+ kcdb_cred_get_name(cred, wname, &cb);
+
+ _report_cs1(KHERR_DEBUG_1, L"Looking at cred [%1!s!]",
+ _cstr(wname));
+ _resolve();
+
+ kcdb_cred_get_identity(cred, &ident);
+#ifdef DEBUG
+ assert(ident);
+#endif
+
+ /* now get the expiry for the identity*/
+ cb = sizeof(ft_expiry);
+ if (KHM_FAILED(kcdb_identity_get_attr(ident, KCDB_ATTR_EXPIRE,
+ NULL,
+ &ft_expiry, &cb))) {
+
+ /* failing which, we get the expiry for this credential */
+ cb = sizeof(ft_expiry);
+ if (KHM_FAILED(kcdb_cred_get_attr(cred, KCDB_ATTR_EXPIRE,
+ NULL,
+ &ft_expiry, &cb))) {
+ /* we don't have an expiry time to work with */
+ _report_cs1(KHERR_DEBUG_1, L"Skipping cred [%1!s!]. No expiry time",
+ _cstr(wname));
+ _resolve();
+
+ kcdb_identity_release(ident);
+ return KHM_ERROR_SUCCESS;
+ } else {
+ /* and the time of issue */
+ cb = sizeof(ft_issue);
+ if (KHM_FAILED(kcdb_cred_get_attr(cred, KCDB_ATTR_ISSUE,
+ NULL, &ft_issue, &cb)))
+ ZeroMemory(&ft_issue, sizeof(ft_issue));
+ }
+
+ } else {
+ /* also try to get the time of issue. */
+ cb = sizeof(ft_issue);
+ if (KHM_FAILED(kcdb_identity_get_attr(ident, KCDB_ATTR_ISSUE,
+ NULL, &ft_issue, &cb)))
+ /* if we fail, we just zero out the time of issue and
+ failover to using the threshold value to set the expiry
+ timer instead of the half life algorithm. */
+ ZeroMemory(&ft_issue, sizeof(ft_issue));
+ }
+
+ /* and the current time */
+ GetSystemTimeAsFileTime(&ft_current);
+
+ TimetToFileTimeInterval(KHUI_TIMEEQ_ERROR, &ft_reinst);
+
+ ft_creinst = FtAdd(&ft_current, &ft_reinst);
+
+ mark_idx = tmr_find(ident, KHUI_TTYPE_ID_MARK, 0, 0);
+
+ if (mark_idx < 0) {
+ mark_idx = tmr_update(ident, KHUI_TTYPE_ID_MARK, 0, 0, 0, FALSE);
+ kcdb_identity_hold(ident);
+#ifdef DEBUG
+ assert(mark_idx >= 0);
+#endif
+ khui_timers[mark_idx].flags |= KHUI_TE_FLAG_STALE;
+ }
+
+ if (khui_timers[mark_idx].flags & KHUI_TE_FLAG_STALE) {
+ /* first time we are touching this */
+ khm_handle csp_cw = NULL;
+ khm_handle csp_id = NULL;
+ khm_int32 rv;
+ khm_int32 t;
+ khm_boolean do_warn = TRUE;
+ khm_boolean do_crit = TRUE;
+ khm_boolean do_renew = TRUE;
+ khm_boolean do_halflife = TRUE;
+ khm_boolean renew_done = FALSE;
+ khm_boolean monitor = TRUE;
+ khm_int32 to_warn = KHUI_DEF_TIMEOUT_WARN;
+ khm_int32 to_crit = KHUI_DEF_TIMEOUT_CRIT;
+ khm_int32 to_renew = KHUI_DEF_TIMEOUT_RENEW;
+
+ if (CompareFileTime(&ft_expiry, &ft_current) < 0)
+ /* already expired */
+ goto _done_with_ident;
+
+ rv = khc_open_space(NULL, L"CredWindow", KHM_PERM_READ,
+ &csp_cw);
+
+ assert(KHM_SUCCEEDED(rv));
+
+ rv = kcdb_identity_get_config(ident, KHM_PERM_READ, &csp_id);
+ if (KHM_SUCCEEDED(rv)) {
+ khc_shadow_space(csp_id, csp_cw);
+ khc_close_space(csp_cw);
+ } else {
+ csp_id = csp_cw;
+ }
+ csp_cw = NULL;
+
+ rv = khc_read_int32(csp_id, L"Monitor", &t);
+ if (KHM_SUCCEEDED(rv))
+ monitor = t;
+
+ rv = khc_read_int32(csp_id, L"AllowWarn", &t);
+ if (KHM_SUCCEEDED(rv))
+ do_warn = t;
+
+ rv = khc_read_int32(csp_id, L"AllowCritical", &t);
+ if (KHM_SUCCEEDED(rv))
+ do_crit = t;
+
+ rv = khc_read_int32(csp_id, L"AllowAutoRenew", &t);
+ if (KHM_SUCCEEDED(rv))
+ do_renew = t;
+
+ rv = khc_read_int32(csp_id, L"RenewAtHalfLife", &t);
+ if (KHM_SUCCEEDED(rv))
+ do_halflife = t;
+
+ rv = khc_read_int32(csp_id, L"WarnThreshold", &t);
+ if (KHM_SUCCEEDED(rv))
+ to_warn = t;
+
+ rv = khc_read_int32(csp_id, L"CriticalThreshold", &t);
+ if (KHM_SUCCEEDED(rv))
+ to_crit = t;
+
+ rv = khc_read_int32(csp_id, L"AutoRenewThreshold", &t);
+ if (KHM_SUCCEEDED(rv))
+ to_renew = t;
+
+ khc_close_space(csp_id);
+
+ if (monitor && do_renew) {
+ int prev;
+
+ TimetToFileTimeInterval(to_renew, &ft);
+
+ prev =
+ tmr_find(ident, KHUI_TTYPE_ID_RENEW, 0, 0);
+
+ if (do_halflife && (ft_issue.dwLowDateTime != 0 ||
+ ft_issue.dwHighDateTime != 0))
+ fte = tmr_next_halflife_timeout(prev, &ft_issue, &ft_expiry);
+ else
+ fte = FtSub(&ft_expiry, &ft);
+
+ /* we set off a renew notification immediately if the
+ renew threshold has passed but a renew was never sent.
+ This maybe because that NetIDMgr was started at the
+ last minute, or because for some reason the renew timer
+ could not be triggered earlier. */
+
+ if (CompareFileTime(&fte, &ft_current) > 0 ||
+ prev == -1 ||
+ !(khui_timers[prev].flags & KHUI_TE_FLAG_EXPIRED)) {
+
+ if (CompareFileTime(&fte, &ft_current) < 0)
+ fte = ft_current;
+
+ tmr_update(ident, KHUI_TTYPE_ID_RENEW,
+ FtToInt(&fte), FtToInt(&ft), 0,
+ CompareFileTime(&fte,&ft_creinst) > 0);
+ renew_done = TRUE;
+
+ } else {
+
+ /* special case. If the renew timer was in the past
+ and it was expired, then we retain the record as
+ long as the credentials are around. If the renewal
+ failed we don't want to automatically retry
+ everytime we check the timers. */
+
+ tmr_update(ident, KHUI_TTYPE_ID_RENEW,
+ FtToInt(&fte), FtToInt(&ft), 0, FALSE);
+
+ }
+ }
+
+ if (monitor && do_warn && !renew_done) {
+
+ TimetToFileTimeInterval(to_warn, &ft);
+ fte = FtSub(&ft_expiry, &ft);
+
+ if (CompareFileTime(&fte, &ft_current) > 0)
+ tmr_update(ident, KHUI_TTYPE_ID_WARN,
+ FtToInt(&fte), FtToInt(&ft), 0,
+ CompareFileTime(&fte, &ft_creinst) > 0);
+ }
+
+ if (monitor && do_crit && !renew_done) {
+ TimetToFileTimeInterval(to_crit, &ft);
+ fte = FtSub(&ft_expiry, &ft);
+
+ if (CompareFileTime(&fte, &ft_current) > 0)
+ tmr_update(ident, KHUI_TTYPE_ID_CRIT,
+ FtToInt(&fte), FtToInt(&ft), 0,
+ CompareFileTime(&fte, &ft_creinst) > 0);
+ }
+
+ if (monitor && !renew_done) {
+ if (CompareFileTime(&ft_expiry, &ft_current) > 0)
+ tmr_update(ident, KHUI_TTYPE_ID_EXP,
+ FtToInt(&ft_expiry), 0, 0,
+ CompareFileTime(&fte, &ft_creinst) > 0);
+ }
+
+ _done_with_ident:
+ khui_timers[mark_idx].flags &= ~KHUI_TE_FLAG_STALE;
+ }
+
+ cb = sizeof(ft_cred_expiry);
+ if (KHM_FAILED(kcdb_cred_get_attr(cred, KCDB_ATTR_EXPIRE,
+ NULL,
+ &ft_cred_expiry,
+ &cb))) {
+ _report_cs1(KHERR_DEBUG_1, L"Skipping cred [%1!s!]. Can't lookup cred expiry",
+ _cstr(wname));
+ _resolve();
+ goto _cleanup;
+ }
+
+ cb = sizeof(ft_cred_issue);
+ if (KHM_FAILED(kcdb_cred_get_attr(cred, KCDB_ATTR_ISSUE,
+ NULL,
+ &ft_cred_issue,
+ &cb))) {
+
+ ZeroMemory(&ft_cred_issue, sizeof(ft_cred_issue));
+
+ }
+
+ TimetToFileTimeInterval(KHUI_TIMEEQ_ERROR, &ft);
+
+ {
+ /* if the credential has a longer lifetime than the identity,
+ or it expires within KHUI_TIMEEQ_ERROR seconds of the
+ identity, then we don't need to set any alerts for this
+ credential. */
+
+ FILETIME ft_delta;
+
+ ft_delta = FtSub(&ft_expiry, &ft_cred_expiry);
+
+ if (CompareFileTime(&ft_cred_expiry, &ft_expiry) >= 0 ||
+ CompareFileTime(&ft_delta, &ft) < 0) {
+
+ _report_cs1(KHERR_DEBUG_1,
+ L"Skipping credential [%1!s!]. The expiry time is too close to the identity expiry.",
+ _cstr(wname));
+ _resolve();
+ goto _cleanup;
+ }
+ }
+
+ if ((idx = tmr_find(ident, KHUI_TTYPE_ID_WARN, 0, 0)) >= 0 &&
+ !(khui_timers[idx].flags & KHUI_TE_FLAG_STALE)) {
+
+ fte = IntToFt(FtToInt(&ft_cred_expiry) - khui_timers[idx].offset);
+ if (CompareFileTime(&fte, &ft_current) > 0) {
+ tmr_update(cred, KHUI_TTYPE_CRED_WARN,
+ FtToInt(&fte),
+ khui_timers[idx].offset, 0,
+ CompareFileTime(&fte, &ft_creinst) > 0);
+ kcdb_cred_hold(cred);
+ }
+ }
+
+ if ((idx = tmr_find(ident, KHUI_TTYPE_ID_CRIT, 0, 0)) >= 0 &&
+ !(khui_timers[idx].flags & KHUI_TE_FLAG_STALE)) {
+
+ fte = IntToFt(FtToInt(&ft_cred_expiry) - khui_timers[idx].offset);
+ if (CompareFileTime(&fte, &ft_current) > 0) {
+ tmr_update(cred, KHUI_TTYPE_CRED_CRIT,
+ FtToInt(&fte),
+ khui_timers[idx].offset, 0,
+ CompareFileTime(&fte, &ft_creinst) > 0);
+ kcdb_cred_hold(cred);
+ }
+ }
+
+ if ((idx = tmr_find(ident, KHUI_TTYPE_ID_RENEW, 0, 0)) >= 0 &&
+ !(khui_timers[idx].flags & KHUI_TE_FLAG_STALE)) {
+
+ int cidx = tmr_find(cred, KHUI_TTYPE_CRED_RENEW, 0, 0);
+
+ if (ft_cred_issue.dwLowDateTime == 0 &&
+ ft_cred_issue.dwHighDateTime == 0) {
+ fte = IntToFt(FtToInt(&ft_cred_expiry) - khui_timers[idx].offset);
+ /* a special case, for a credential whose remaining
+ lifetime is less than the offset, we try half life on
+ the current time and the expiry. */
+ if (CompareFileTime(&fte, &ft_current) <= 0 &&
+ CompareFileTime(&ft_current, &ft_expiry) < 0) {
+ fte = tmr_next_halflife_timeout(cidx, &ft_current, &ft_cred_expiry);
+#if 0
+ /* now, if we already have a renew timer for this
+ credential that hasn't expired yet and that is set
+ for earlier than fte, we let it be. */
+ if (cidx >= 0 &&
+ khui_timers[cidx].expire < FtToInt(&fte) &&
+ khui_timers[cidx].expire > FtToInt(&ft_current) &&
+ !(khui_timers[cidx].flags & KHUI_TE_FLAG_EXPIRED)) {
+
+ fte = IntToFt(khui_timers[cidx].expire);
+
+ }
+#endif
+ }
+ } else {
+ fte = tmr_next_halflife_timeout(cidx, &ft_cred_issue, &ft_cred_expiry);
+ }
+
+ if (CompareFileTime(&fte, &ft_current) > 0) {
+ tmr_update(cred, KHUI_TTYPE_CRED_RENEW,
+ FtToInt(&fte),
+ khui_timers[idx].offset, 0,
+ CompareFileTime(&fte, &ft_creinst) > 0);
+ kcdb_cred_hold(cred);
+ }
+ }
+
+ if ((idx = tmr_find(ident, KHUI_TTYPE_ID_EXP, 0, 0)) >= 0 &&
+ !(khui_timers[idx].flags & KHUI_TE_FLAG_STALE)) {
+
+ if (CompareFileTime(&ft_cred_expiry, &ft_current) > 0) {
+ tmr_update(cred, KHUI_TTYPE_CRED_EXP,
+ FtToInt(&ft_cred_expiry),
+ 0, 0,
+ CompareFileTime(&ft_cred_expiry, &ft_creinst) > 0);
+ }
+ }
+
+ _cleanup:
+
+ if (ident)
+ kcdb_identity_release(ident);
+
+ return KHM_ERROR_SUCCESS;
+}
+
+/* called with cs_timers held */
+static void
+tmr_purge(void) {
+ int i, j;
+
+ for (i=0,j=0; i < (int) khui_n_timers; i++) {
+ if (khui_timers[i].flags & KHUI_TE_FLAG_STALE) {
+ if (khui_timers[i].type == KHUI_TTYPE_ID_MARK) {
+ kcdb_identity_release(khui_timers[i].key);
+#ifdef DEBUG
+ {
+ int idx;
+
+ idx = tmr_find(khui_timers[i].key,
+ KHUI_TTYPE_ID_CRIT, 0, 0);
+ assert(idx < 0 ||
+ (khui_timers[idx].flags &
+ KHUI_TE_FLAG_STALE));
+
+ idx = tmr_find(khui_timers[i].key,
+ KHUI_TTYPE_ID_RENEW, 0, 0);
+ assert(idx < 0 ||
+ (khui_timers[idx].flags &
+ KHUI_TE_FLAG_STALE));
+
+ idx = tmr_find(khui_timers[i].key,
+ KHUI_TTYPE_ID_WARN, 0, 0);
+ assert(idx < 0 ||
+ (khui_timers[idx].flags &
+ KHUI_TE_FLAG_STALE));
+
+ idx = tmr_find(khui_timers[i].key,
+ KHUI_TTYPE_ID_EXP, 0, 0);
+ assert(idx < 0 ||
+ (khui_timers[idx].flags &
+ KHUI_TE_FLAG_STALE));
+ }
+#endif
+ } else if (khui_timers[i].type == KHUI_TTYPE_CRED_WARN ||
+ khui_timers[i].type == KHUI_TTYPE_CRED_CRIT ||
+ khui_timers[i].type == KHUI_TTYPE_CRED_RENEW ||
+ khui_timers[i].type == KHUI_TTYPE_CRED_EXP) {
+ kcdb_cred_release(khui_timers[i].key);
+ }
+ } else {
+ if (i != j)
+ khui_timers[j] = khui_timers[i];
+ j++;
+ }
+ }
+
+ khui_n_timers = j;
+}
+
+/* go through all the credentials and set timers as appropriate. hwnd
+ is the window that will receive the timer events.*/
+void
+khm_timer_refresh(HWND hwnd) {
+ int i;
+ khm_int64 next_event = 0;
+ khm_int64 curtime;
+ khm_int64 diff;
+
+ _begin_task(0);
+ _report_cs0(KHERR_DEBUG_1, L"Refreshing timers");
+ _describe();
+
+ EnterCriticalSection(&cs_timers);
+
+ KillTimer(hwnd, KHUI_TRIGGER_TIMER_ID);
+
+ /* When refreshing timers, we go through all of them and mark them
+ as stale. Then we go through the credentials in the root
+ credential set and add or refresh the timers associated with
+ each identity and credential. Once this is done, we remove the
+ timers that are still stale, since they are no longer in
+ use. */
+
+ for (i=0; i < (int) khui_n_timers; i++) {
+#ifdef NOT_IMPLEMENTED_YET
+ if (khui_timers[i].type == KHUI_TTYPE_BMSG ||
+ khui_timers[i].type == KHUI_TTYPE_SMSG) {
+ khui_timers[i].flags &= ~KHUI_TE_FLAG_STALE;
+ } else {
+#endif
+
+ khui_timers[i].flags |= KHUI_TE_FLAG_STALE;
+
+#ifdef NOT_IMPLEMENTED_YET
+ }
+#endif
+ }
+
+ _report_cs1(KHERR_DEBUG_1, L"Starting with %1!d! timers",
+ _int32(khui_n_timers));
+
+ kcdb_credset_apply(NULL,
+ tmr_cred_apply_proc,
+ NULL);
+
+ tmr_purge();
+
+ _report_cs1(KHERR_DEBUG_1, L"Leaving with %1!d! timers",
+ _int32(khui_n_timers));
+
+ _check_next_event:
+
+ /* Before we return, we should check if any timers are set to
+ expire right now. If there are, we should fire the timer
+ before returning. */
+
+ next_event = 0;
+ for (i=0; i < (int) khui_n_timers; i++) {
+ if (!(khui_timers[i].flags & KHUI_TE_FLAG_EXPIRED) &&
+ khui_timers[i].type != KHUI_TTYPE_ID_MARK &&
+ (next_event == 0 ||
+ next_event > khui_timers[i].expire)) {
+
+ next_event = khui_timers[i].expire;
+
+ }
+ }
+
+ if (next_event != 0) {
+ FILETIME ft;
+
+ GetSystemTimeAsFileTime(&ft);
+ curtime = FtToInt(&ft);
+
+ TimetToFileTimeInterval(KHUI_TIMEEQ_ERROR_SMALL, &ft);
+ diff = FtToInt(&ft);
+
+ if (curtime + diff > next_event) {
+ tmr_fire_timer();
+ goto _check_next_event;
+ } else {
+ diff = next_event - curtime;
+ ft = IntToFt(diff);
+ SetTimer(hwnd,
+ KHUI_TRIGGER_TIMER_ID,
+ FtIntervalToMilliseconds(&ft),
+ NULL);
+ }
+ }
+
+ LeaveCriticalSection(&cs_timers);
+
+ _end_task();
+}
diff --git a/src/windows/identity/ui/timer.h b/src/windows/identity/ui/timer.h
index 130ae999ac..af4ece7234 100644
--- a/src/windows/identity/ui/timer.h
+++ b/src/windows/identity/ui/timer.h
@@ -1,100 +1,100 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#ifndef __KHIMAIRA_TIMER_H
-#define __KHIMAIRA_TIMER_H
-
-/* note that the ordering of the first few enum constants are
- significant. The values of the constants up to KHUI_N_TTYPES are
- used as indices. */
-typedef enum tag_khui_timer_type {
- KHUI_TTYPE_ID_EXP = 0, /* Identity expiration */
- KHUI_TTYPE_ID_CRIT, /* Identity critical */
- KHUI_TTYPE_ID_WARN, /* Identity warning */
- KHUI_TTYPE_CRED_EXP, /* Credential expiration */
- KHUI_TTYPE_CRED_CRIT, /* Credential critical */
- KHUI_TTYPE_CRED_WARN, /* Credential warning */
-
- KHUI_N_TTYPES, /* Count of the timers that we
- aggregate for notifications */
-
- KHUI_TTYPE_ID_MARK, /* Identity marker */
-
- KHUI_TTYPE_ID_RENEW, /* Identity auto renewal */
- KHUI_TTYPE_CRED_RENEW, /* Credential renewal */
-
-#if 0
- KHUI_TTYPE_BMSG, /* Custom. Sends broadcast message
- when triggered.*/
- KHUI_TTYPE_SMSG, /* Custom. Sends subscription message
- when triggered. */
-#endif
-} khui_timer_type;
-
-typedef struct tag_khui_timer_event {
- khm_handle key;
- khui_timer_type type;
-
- khm_int64 expire; /* time at which the timer expires */
- khm_int64 offset; /* time offset at which the event that the
- timer warns of happens */
- void * data;
- khm_int32 flags;
-} khui_timer_event;
-
-#define KHUI_TRIGGER_TIMER_ID 48
-#define KHUI_REFRESH_TIMER_ID 49
-
-#define KHUI_REFRESH_TIMEOUT 5000
-
-#define KHUI_TE_FLAG_EXPIRED 0x00000001
-#define KHUI_TE_FLAG_STALE 0x00000002
-
-#define KHUI_DEF_TIMEOUT_WARN 900
-#define KHUI_DEF_TIMEOUT_CRIT 300
-#define KHUI_DEF_TIMEOUT_RENEW 60
-
-/* the max absolute difference between two timers (in seconds) that
- can exist where we consider both timers to be in the same
- timeslot. */
-#define KHUI_TIMEEQ_ERROR 20
-
-/* the small error. */
-#define KHUI_TIMEEQ_ERROR_SMALL 1
-
-void
-khm_timer_refresh(HWND hwnd);
-
-void
-khm_timer_fire(HWND hwnd);
-
-void
-khm_timer_init(void);
-
-void
-khm_timer_exit(void);
-
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __KHIMAIRA_TIMER_H
+#define __KHIMAIRA_TIMER_H
+
+/* note that the ordering of the first few enum constants are
+ significant. The values of the constants up to KHUI_N_TTYPES are
+ used as indices. */
+typedef enum tag_khui_timer_type {
+ KHUI_TTYPE_ID_EXP = 0, /* Identity expiration */
+ KHUI_TTYPE_ID_CRIT, /* Identity critical */
+ KHUI_TTYPE_ID_WARN, /* Identity warning */
+ KHUI_TTYPE_CRED_EXP, /* Credential expiration */
+ KHUI_TTYPE_CRED_CRIT, /* Credential critical */
+ KHUI_TTYPE_CRED_WARN, /* Credential warning */
+
+ KHUI_N_TTYPES, /* Count of the timers that we
+ aggregate for notifications */
+
+ KHUI_TTYPE_ID_MARK, /* Identity marker */
+
+ KHUI_TTYPE_ID_RENEW, /* Identity auto renewal */
+ KHUI_TTYPE_CRED_RENEW, /* Credential renewal */
+
+#if 0
+ KHUI_TTYPE_BMSG, /* Custom. Sends broadcast message
+ when triggered.*/
+ KHUI_TTYPE_SMSG, /* Custom. Sends subscription message
+ when triggered. */
+#endif
+} khui_timer_type;
+
+typedef struct tag_khui_timer_event {
+ khm_handle key;
+ khui_timer_type type;
+
+ khm_int64 expire; /* time at which the timer expires */
+ khm_int64 offset; /* time offset at which the event that the
+ timer warns of happens */
+ void * data;
+ khm_int32 flags;
+} khui_timer_event;
+
+#define KHUI_TRIGGER_TIMER_ID 48
+#define KHUI_REFRESH_TIMER_ID 49
+
+#define KHUI_REFRESH_TIMEOUT 5000
+
+#define KHUI_TE_FLAG_EXPIRED 0x00000001
+#define KHUI_TE_FLAG_STALE 0x00000002
+
+#define KHUI_DEF_TIMEOUT_WARN 900
+#define KHUI_DEF_TIMEOUT_CRIT 300
+#define KHUI_DEF_TIMEOUT_RENEW 60
+
+/* the max absolute difference between two timers (in seconds) that
+ can exist where we consider both timers to be in the same
+ timeslot. */
+#define KHUI_TIMEEQ_ERROR 20
+
+/* the small error. */
+#define KHUI_TIMEEQ_ERROR_SMALL 1
+
+void
+khm_timer_refresh(HWND hwnd);
+
+void
+khm_timer_fire(HWND hwnd);
+
+void
+khm_timer_init(void);
+
+void
+khm_timer_exit(void);
+
+#endif
diff --git a/src/windows/identity/ui/toolbar.c b/src/windows/identity/ui/toolbar.c
index a464009fc6..c543e69236 100644
--- a/src/windows/identity/ui/toolbar.c
+++ b/src/windows/identity/ui/toolbar.c
@@ -1,471 +1,471 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- * Copyright (c) 2007 Secure Endpoints Inc.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<khmapp.h>
-#include<assert.h>
-
-HWND khui_hwnd_standard_toolbar;
-int khui_tb_blank;
-
-khui_ilist * ilist_toolbar;
-
-void khui_init_toolbar(void) {
- ilist_toolbar = khui_create_ilist(KHUI_TOOLBAR_IMAGE_WIDTH, KHUI_TOOLBAR_IMAGE_HEIGHT, KHUI_TOOLBAR_MAX_BTNS, 5, 0);
-}
-
-void khui_exit_toolbar(void) {
- khui_delete_ilist(ilist_toolbar);
-}
-
-LRESULT khm_toolbar_notify(LPNMHDR notice) {
- switch(notice->code) {
- case TBN_GETINFOTIP:
- {
- LPNMTBGETINFOTIP git = (LPNMTBGETINFOTIP) notice;
- int cmd;
- khui_action * a;
-
- cmd = git->iItem;
- a = khui_find_action(cmd);
-
- if (a) {
- if (a->caption) {
- StringCchCopy(git->pszText, git->cchTextMax, a->caption);
- } else if (a->tooltip) {
- StringCchCopy(git->pszText, git->cchTextMax, a->tooltip);
- } else if (a->is_caption) {
- wchar_t buf[INFOTIPSIZE];
-
- buf[0] = L'\0';
- LoadString(khm_hInstance, a->is_caption,
- buf, ARRAYLENGTH(buf));
-
- StringCchCopy(git->pszText, git->cchTextMax, buf);
- } else {
- StringCchCopy(git->pszText, git->cchTextMax, L"");
- }
- } else {
- StringCchCopy(git->pszText,
- git->cchTextMax,
- L"");
- }
- }
- break;
-
- case TBN_HOTITEMCHANGE:
- {
- LPNMTBHOTITEM hi = (LPNMTBHOTITEM) notice;
-
- if (hi->dwFlags & HICF_LEAVING) {
- khm_statusbar_set_part(KHUI_SBPART_INFO, NULL, L"");
- } else {
- khui_action * a;
- int cmd;
- wchar_t buf[256];
-
- cmd = hi->idNew;
- a = khui_find_action(cmd);
-
- buf[0] = L'\0';
-
- if (a) {
- if (a->tooltip)
- StringCbCopy(buf, sizeof(buf), a->tooltip);
- else if (a->is_tooltip) {
- LoadString(khm_hInstance, a->is_tooltip,
- buf, ARRAYLENGTH(buf));
- }
- }
-
- khm_statusbar_set_part(KHUI_SBPART_INFO, NULL, buf);
- }
- }
- break;
-
- case TBN_DROPDOWN:
- {
- LPNMTOOLBAR nmtb = (LPNMTOOLBAR) notice;
- RECT r;
-
- GetWindowRect(khui_hwnd_standard_toolbar, &r);
- if (nmtb->iItem == KHUI_ACTION_DESTROY_CRED) {
- khm_menu_show_panel(KHUI_MENU_DESTROY_CRED,
- r.left + nmtb->rcButton.left,
- r.top + nmtb->rcButton.bottom);
- } else if (nmtb->iItem == KHUI_ACTION_RENEW_CRED) {
- khm_menu_show_panel(KHUI_MENU_RENEW_CRED,
- r.left + nmtb->rcButton.left,
- r.top + nmtb->rcButton.bottom);
- } else {
- return TBDDRET_NODEFAULT;
- }
-
- return TBDDRET_DEFAULT;
- }
- break;
-
- case NM_CUSTOMDRAW:
- {
- LPNMTBCUSTOMDRAW nmcd = (LPNMTBCUSTOMDRAW) notice;
- if(nmcd->nmcd.dwDrawStage == CDDS_PREPAINT) {
- return CDRF_NOTIFYITEMDRAW | CDRF_NOTIFYPOSTERASE;
- } else if(nmcd->nmcd.dwDrawStage == CDDS_ITEMPREPAINT) {
- return CDRF_NOTIFYPOSTPAINT;
- } else if(nmcd->nmcd.dwDrawStage == CDDS_ITEMPOSTPAINT) {
- /* draw the actual icon */
- int iidx;
- int ibmp;
- HBITMAP hbmp;
- RECT r;
-
- khui_action * act =
- khui_find_action((int) nmcd->nmcd.dwItemSpec);
-
- if(!act || !act->ib_normal)
- return CDRF_DODEFAULT;
-
- if((act->state & KHUI_ACTIONSTATE_DISABLED) &&
- act->ib_disabled) {
- ibmp = act->ib_disabled;
- } else if(act->ib_hot &&
- ((nmcd->nmcd.uItemState & CDIS_HOT) ||
- (nmcd->nmcd.uItemState & CDIS_SELECTED))){
- ibmp = act->ib_hot;
- } else {
- ibmp = act->ib_normal;
- }
-
- iidx = khui_ilist_lookup_id(ilist_toolbar, ibmp);
- if(iidx < 0) {
- hbmp = LoadImage(khm_hInstance,
- MAKEINTRESOURCE(ibmp),
- IMAGE_BITMAP,
- KHUI_TOOLBAR_IMAGE_WIDTH,
- KHUI_TOOLBAR_IMAGE_HEIGHT, 0);
- iidx =
- khui_ilist_add_masked_id(ilist_toolbar,
- hbmp,
- KHUI_TOOLBAR_BGCOLOR,
- ibmp);
- DeleteObject(hbmp);
- }
-
- if(iidx < 0)
- return CDRF_DODEFAULT;
-
- CopyRect(&r, &(nmcd->nmcd.rc));
- r.left += ((r.bottom - r.top) -
- KHUI_TOOLBAR_IMAGE_HEIGHT) / 2;
- r.top += ((r.bottom - r.top) -
- KHUI_TOOLBAR_IMAGE_HEIGHT) / 2;
-#if 0
- r.left += ((r.right - r.left) -
- KHUI_TOOLBAR_IMAGE_WIDTH) / 2;
-#endif
- khui_ilist_draw(ilist_toolbar,
- iidx,
- nmcd->nmcd.hdc,
- r.left,
- r.top,
- 0);
-
- return CDRF_DODEFAULT;
- }
- }
- break;
- }
- return 0;
-}
-
-void khui_add_action_to_toolbar(HWND tb, khui_action *a, int opt, HIMAGELIST hiList) {
- wchar_t buf[MAX_RES_STRING] = L"";
- int idx_caption = 0;
- TBBUTTON bn;
- LRESULT lr;
-
- ZeroMemory(&bn,sizeof(bn));
-
- if(opt & KHUI_TOOLBAR_ADD_SEP) {
- bn.fsStyle = BTNS_SEP;
- bn.iBitmap = 3;
-
- lr = SendMessage(tb,
- TB_ADDBUTTONS,
- 1,
- (LPARAM) &bn);
-#ifdef DEBUG
- assert(lr);
-#endif
- return;
- }
-
- bn.fsStyle = BTNS_BUTTON;
-
- if(opt & KHUI_TOOLBAR_VARSIZE) {
- bn.fsStyle |= BTNS_AUTOSIZE;
- }
-
- if(opt & KHUI_TOOLBAR_ADD_TEXT) {
- int sid = 0;
- if((opt & KHUI_TOOLBAR_ADD_LONGTEXT) ==
- KHUI_TOOLBAR_ADD_LONGTEXT) {
- sid = a->is_tooltip;
- }
- if(!sid)
- sid = a->is_caption;
- if(sid) {
- LoadString(khm_hInstance,
- sid,
- buf, ARRAYLENGTH(buf));
- buf[wcslen(buf) + 1] = L'\0';
- idx_caption = (int) SendMessage(tb,
- TB_ADDSTRING,
- (WPARAM) NULL,
- (LPARAM) buf);
-#if (_WIN32_IE >= 0x0501)
- bn.fsStyle |= BTNS_SHOWTEXT;
-#endif
- bn.iString = idx_caption;
- }
- }
-
- if(opt & KHUI_TOOLBAR_ADD_DROPDOWN) {
- bn.fsStyle |= BTNS_DROPDOWN;
- }
-
- if((opt & KHUI_TOOLBAR_ADD_BITMAP) && a->ib_normal) {
- bn.fsStyle |= TBSTYLE_CUSTOMERASE;
- bn.iBitmap = khui_tb_blank;
- } else {
-#if (_WIN32_IE >= 0x0501)
- bn.iBitmap = I_IMAGENONE;
-#endif
- }
-
- bn.idCommand = a->cmd;
-
- if(a->state & KHUI_ACTIONSTATE_DISABLED) {
- bn.fsState = 0;
- } else {
- bn.fsState = TBSTATE_ENABLED;
- }
-
- if(a->state & KHUI_ACTIONSTATE_CHECKED) {
- bn.fsState |= TBSTATE_CHECKED;
- }
-
- bn.dwData = 0;
-
- lr = SendMessage(
- tb,
- TB_ADDBUTTONS,
- 1,
- (LPARAM) &bn);
-
-#ifdef DEBUG
- assert(lr);
-#endif
-}
-
-void khm_update_standard_toolbar(void)
-{
- khui_menu_def * def;
- khui_action_ref * aref;
- khui_action * act;
-
- def = khui_find_menu(KHUI_TOOLBAR_STANDARD);
-
- aref = def->items;
-
- while(aref && aref->action != KHUI_MENU_END) {
- if(aref->action == KHUI_MENU_SEP) {
- aref++;
- continue;
- }
-
- act = khui_find_action(aref->action);
- if(act) {
- BOOL enable;
-
- enable = !(act->state & KHUI_ACTIONSTATE_DISABLED);
- SendMessage(khui_hwnd_standard_toolbar,
- TB_ENABLEBUTTON,
- (WPARAM) act->cmd,
- MAKELPARAM(enable, 0));
- }
-
- aref++;
- }
-}
-
-void khm_create_standard_toolbar(HWND rebar) {
- HWND hwtb;
- SIZE sz;
- HBITMAP hbm_blank;
- HIMAGELIST hiList;
- REBARBANDINFO rbi;
- khui_menu_def * def;
- khui_action * act;
- khui_action_ref * aref;
- int idx_blank;
-
- def = khui_find_menu(KHUI_TOOLBAR_STANDARD);
-
- if (!def) {
-#ifdef DEBUG
- assert(FALSE);
-#endif
- return;
- }
-
- hwtb = CreateWindowEx(0 ,
- TOOLBARCLASSNAME,
- (LPWSTR) NULL,
- WS_CHILD |
- TBSTYLE_FLAT |
- TBSTYLE_AUTOSIZE |
- TBSTYLE_TOOLTIPS |
- CCS_NORESIZE |
- CCS_NOPARENTALIGN |
- CCS_ADJUSTABLE |
- CCS_NODIVIDER,
- 0, 0, 0, 0, rebar,
- (HMENU) NULL, khm_hInstance,
- NULL);
-
- if(!hwtb) {
-#ifdef DEBUG
- assert(FALSE);
-#endif
- return;
- }
-
-#if (_WIN32_IE >= 0x0501)
- SendMessage(hwtb, TB_SETEXTENDEDSTYLE, 0,
- TBSTYLE_EX_MIXEDBUTTONS | TBSTYLE_EX_DRAWDDARROWS);
-#endif
-
- hiList = ImageList_Create(
- KHUI_TOOLBAR_IMAGE_WIDTH,
- KHUI_TOOLBAR_IMAGE_HEIGHT,
- ILC_MASK,
- (int) khui_action_list_length(def->items),
- 3);
-
- hbm_blank = LoadImage(khm_hInstance,
- MAKEINTRESOURCE(IDB_TB_BLANK),
- IMAGE_BITMAP,
- KHUI_TOOLBAR_IMAGE_WIDTH,
- KHUI_TOOLBAR_IMAGE_HEIGHT, 0);
- idx_blank = ImageList_AddMasked(hiList, hbm_blank, RGB(0,0,0));
-
- khui_hwnd_standard_toolbar = hwtb;
- khui_tb_blank = idx_blank;
-
- def = khui_find_menu(KHUI_TOOLBAR_STANDARD);
-
- aref = def->items;
-
- SendMessage(hwtb,
- TB_BUTTONSTRUCTSIZE,
- sizeof(TBBUTTON),
- 0);
-
- SendMessage(hwtb,
- TB_SETBITMAPSIZE,
- 0,
- MAKELONG(KHUI_TOOLBAR_IMAGE_WIDTH,KHUI_TOOLBAR_IMAGE_HEIGHT));
-
- SendMessage(hwtb,
- TB_SETIMAGELIST,
- 0,
- (LPARAM) hiList);
-
- SendMessage(hwtb,
- TB_SETBUTTONSIZE,
- 0,
- MAKELONG(KHUI_TOOLBAR_IMAGE_WIDTH,KHUI_TOOLBAR_IMAGE_HEIGHT));
-
- while(aref && aref->action != KHUI_MENU_END) {
- if(aref->action == KHUI_MENU_SEP) {
- khui_add_action_to_toolbar(hwtb,
- NULL,
- KHUI_TOOLBAR_ADD_SEP,
- hiList);
- } else {
- act = khui_find_action(aref->action);
- khui_add_action_to_toolbar(hwtb,
- act,
- KHUI_TOOLBAR_ADD_BITMAP |
- ((aref->flags & KHUI_ACTIONREF_SUBMENU)?
- KHUI_TOOLBAR_ADD_DROPDOWN: 0),
- hiList);
- }
- aref ++;
- }
-
- SendMessage(hwtb,
- TB_AUTOSIZE,
- 0,0);
-
- SendMessage(hwtb,
- TB_GETMAXSIZE,
- 0,
- (LPARAM) &sz);
-
- sz.cy += 5;
-
- ZeroMemory(&rbi, sizeof(rbi));
-
- rbi.cbSize = sizeof(rbi);
- rbi.fMask =
- RBBIM_ID |
- RBBIM_CHILD |
- RBBIM_CHILDSIZE |
- RBBIM_IDEALSIZE |
- RBBIM_SIZE |
- RBBIM_STYLE;
- rbi.fStyle =
- RBBS_USECHEVRON |
- RBBS_BREAK;
- rbi.hwndChild = hwtb;
-
- rbi.wID = KHUI_TOOLBAR_STANDARD;
- rbi.cx = sz.cx;
- rbi.cxMinChild = sz.cx;
- rbi.cyMinChild = sz.cy;
- rbi.cyChild = rbi.cyMinChild;
- rbi.cyMaxChild = rbi.cyMinChild;
- rbi.cyIntegral = rbi.cyMinChild;
-
- rbi.cxIdeal = rbi.cx;
-
- SendMessage(rebar,
- RB_INSERTBAND,
- 0,
- (LPARAM) &rbi);
-}
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ * Copyright (c) 2007 Secure Endpoints Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<khmapp.h>
+#include<assert.h>
+
+HWND khui_hwnd_standard_toolbar;
+int khui_tb_blank;
+
+khui_ilist * ilist_toolbar;
+
+void khui_init_toolbar(void) {
+ ilist_toolbar = khui_create_ilist(KHUI_TOOLBAR_IMAGE_WIDTH, KHUI_TOOLBAR_IMAGE_HEIGHT, KHUI_TOOLBAR_MAX_BTNS, 5, 0);
+}
+
+void khui_exit_toolbar(void) {
+ khui_delete_ilist(ilist_toolbar);
+}
+
+LRESULT khm_toolbar_notify(LPNMHDR notice) {
+ switch(notice->code) {
+ case TBN_GETINFOTIP:
+ {
+ LPNMTBGETINFOTIP git = (LPNMTBGETINFOTIP) notice;
+ int cmd;
+ khui_action * a;
+
+ cmd = git->iItem;
+ a = khui_find_action(cmd);
+
+ if (a) {
+ if (a->caption) {
+ StringCchCopy(git->pszText, git->cchTextMax, a->caption);
+ } else if (a->tooltip) {
+ StringCchCopy(git->pszText, git->cchTextMax, a->tooltip);
+ } else if (a->is_caption) {
+ wchar_t buf[INFOTIPSIZE];
+
+ buf[0] = L'\0';
+ LoadString(khm_hInstance, a->is_caption,
+ buf, ARRAYLENGTH(buf));
+
+ StringCchCopy(git->pszText, git->cchTextMax, buf);
+ } else {
+ StringCchCopy(git->pszText, git->cchTextMax, L"");
+ }
+ } else {
+ StringCchCopy(git->pszText,
+ git->cchTextMax,
+ L"");
+ }
+ }
+ break;
+
+ case TBN_HOTITEMCHANGE:
+ {
+ LPNMTBHOTITEM hi = (LPNMTBHOTITEM) notice;
+
+ if (hi->dwFlags & HICF_LEAVING) {
+ khm_statusbar_set_part(KHUI_SBPART_INFO, NULL, L"");
+ } else {
+ khui_action * a;
+ int cmd;
+ wchar_t buf[256];
+
+ cmd = hi->idNew;
+ a = khui_find_action(cmd);
+
+ buf[0] = L'\0';
+
+ if (a) {
+ if (a->tooltip)
+ StringCbCopy(buf, sizeof(buf), a->tooltip);
+ else if (a->is_tooltip) {
+ LoadString(khm_hInstance, a->is_tooltip,
+ buf, ARRAYLENGTH(buf));
+ }
+ }
+
+ khm_statusbar_set_part(KHUI_SBPART_INFO, NULL, buf);
+ }
+ }
+ break;
+
+ case TBN_DROPDOWN:
+ {
+ LPNMTOOLBAR nmtb = (LPNMTOOLBAR) notice;
+ RECT r;
+
+ GetWindowRect(khui_hwnd_standard_toolbar, &r);
+ if (nmtb->iItem == KHUI_ACTION_DESTROY_CRED) {
+ khm_menu_show_panel(KHUI_MENU_DESTROY_CRED,
+ r.left + nmtb->rcButton.left,
+ r.top + nmtb->rcButton.bottom);
+ } else if (nmtb->iItem == KHUI_ACTION_RENEW_CRED) {
+ khm_menu_show_panel(KHUI_MENU_RENEW_CRED,
+ r.left + nmtb->rcButton.left,
+ r.top + nmtb->rcButton.bottom);
+ } else {
+ return TBDDRET_NODEFAULT;
+ }
+
+ return TBDDRET_DEFAULT;
+ }
+ break;
+
+ case NM_CUSTOMDRAW:
+ {
+ LPNMTBCUSTOMDRAW nmcd = (LPNMTBCUSTOMDRAW) notice;
+ if(nmcd->nmcd.dwDrawStage == CDDS_PREPAINT) {
+ return CDRF_NOTIFYITEMDRAW | CDRF_NOTIFYPOSTERASE;
+ } else if(nmcd->nmcd.dwDrawStage == CDDS_ITEMPREPAINT) {
+ return CDRF_NOTIFYPOSTPAINT;
+ } else if(nmcd->nmcd.dwDrawStage == CDDS_ITEMPOSTPAINT) {
+ /* draw the actual icon */
+ int iidx;
+ int ibmp;
+ HBITMAP hbmp;
+ RECT r;
+
+ khui_action * act =
+ khui_find_action((int) nmcd->nmcd.dwItemSpec);
+
+ if(!act || !act->ib_normal)
+ return CDRF_DODEFAULT;
+
+ if((act->state & KHUI_ACTIONSTATE_DISABLED) &&
+ act->ib_disabled) {
+ ibmp = act->ib_disabled;
+ } else if(act->ib_hot &&
+ ((nmcd->nmcd.uItemState & CDIS_HOT) ||
+ (nmcd->nmcd.uItemState & CDIS_SELECTED))){
+ ibmp = act->ib_hot;
+ } else {
+ ibmp = act->ib_normal;
+ }
+
+ iidx = khui_ilist_lookup_id(ilist_toolbar, ibmp);
+ if(iidx < 0) {
+ hbmp = LoadImage(khm_hInstance,
+ MAKEINTRESOURCE(ibmp),
+ IMAGE_BITMAP,
+ KHUI_TOOLBAR_IMAGE_WIDTH,
+ KHUI_TOOLBAR_IMAGE_HEIGHT, 0);
+ iidx =
+ khui_ilist_add_masked_id(ilist_toolbar,
+ hbmp,
+ KHUI_TOOLBAR_BGCOLOR,
+ ibmp);
+ DeleteObject(hbmp);
+ }
+
+ if(iidx < 0)
+ return CDRF_DODEFAULT;
+
+ CopyRect(&r, &(nmcd->nmcd.rc));
+ r.left += ((r.bottom - r.top) -
+ KHUI_TOOLBAR_IMAGE_HEIGHT) / 2;
+ r.top += ((r.bottom - r.top) -
+ KHUI_TOOLBAR_IMAGE_HEIGHT) / 2;
+#if 0
+ r.left += ((r.right - r.left) -
+ KHUI_TOOLBAR_IMAGE_WIDTH) / 2;
+#endif
+ khui_ilist_draw(ilist_toolbar,
+ iidx,
+ nmcd->nmcd.hdc,
+ r.left,
+ r.top,
+ 0);
+
+ return CDRF_DODEFAULT;
+ }
+ }
+ break;
+ }
+ return 0;
+}
+
+void khui_add_action_to_toolbar(HWND tb, khui_action *a, int opt, HIMAGELIST hiList) {
+ wchar_t buf[MAX_RES_STRING] = L"";
+ int idx_caption = 0;
+ TBBUTTON bn;
+ LRESULT lr;
+
+ ZeroMemory(&bn,sizeof(bn));
+
+ if(opt & KHUI_TOOLBAR_ADD_SEP) {
+ bn.fsStyle = BTNS_SEP;
+ bn.iBitmap = 3;
+
+ lr = SendMessage(tb,
+ TB_ADDBUTTONS,
+ 1,
+ (LPARAM) &bn);
+#ifdef DEBUG
+ assert(lr);
+#endif
+ return;
+ }
+
+ bn.fsStyle = BTNS_BUTTON;
+
+ if(opt & KHUI_TOOLBAR_VARSIZE) {
+ bn.fsStyle |= BTNS_AUTOSIZE;
+ }
+
+ if(opt & KHUI_TOOLBAR_ADD_TEXT) {
+ int sid = 0;
+ if((opt & KHUI_TOOLBAR_ADD_LONGTEXT) ==
+ KHUI_TOOLBAR_ADD_LONGTEXT) {
+ sid = a->is_tooltip;
+ }
+ if(!sid)
+ sid = a->is_caption;
+ if(sid) {
+ LoadString(khm_hInstance,
+ sid,
+ buf, ARRAYLENGTH(buf));
+ buf[wcslen(buf) + 1] = L'\0';
+ idx_caption = (int) SendMessage(tb,
+ TB_ADDSTRING,
+ (WPARAM) NULL,
+ (LPARAM) buf);
+#if (_WIN32_IE >= 0x0501)
+ bn.fsStyle |= BTNS_SHOWTEXT;
+#endif
+ bn.iString = idx_caption;
+ }
+ }
+
+ if(opt & KHUI_TOOLBAR_ADD_DROPDOWN) {
+ bn.fsStyle |= BTNS_DROPDOWN;
+ }
+
+ if((opt & KHUI_TOOLBAR_ADD_BITMAP) && a->ib_normal) {
+ bn.fsStyle |= TBSTYLE_CUSTOMERASE;
+ bn.iBitmap = khui_tb_blank;
+ } else {
+#if (_WIN32_IE >= 0x0501)
+ bn.iBitmap = I_IMAGENONE;
+#endif
+ }
+
+ bn.idCommand = a->cmd;
+
+ if(a->state & KHUI_ACTIONSTATE_DISABLED) {
+ bn.fsState = 0;
+ } else {
+ bn.fsState = TBSTATE_ENABLED;
+ }
+
+ if(a->state & KHUI_ACTIONSTATE_CHECKED) {
+ bn.fsState |= TBSTATE_CHECKED;
+ }
+
+ bn.dwData = 0;
+
+ lr = SendMessage(
+ tb,
+ TB_ADDBUTTONS,
+ 1,
+ (LPARAM) &bn);
+
+#ifdef DEBUG
+ assert(lr);
+#endif
+}
+
+void khm_update_standard_toolbar(void)
+{
+ khui_menu_def * def;
+ khui_action_ref * aref;
+ khui_action * act;
+
+ def = khui_find_menu(KHUI_TOOLBAR_STANDARD);
+
+ aref = def->items;
+
+ while(aref && aref->action != KHUI_MENU_END) {
+ if(aref->action == KHUI_MENU_SEP) {
+ aref++;
+ continue;
+ }
+
+ act = khui_find_action(aref->action);
+ if(act) {
+ BOOL enable;
+
+ enable = !(act->state & KHUI_ACTIONSTATE_DISABLED);
+ SendMessage(khui_hwnd_standard_toolbar,
+ TB_ENABLEBUTTON,
+ (WPARAM) act->cmd,
+ MAKELPARAM(enable, 0));
+ }
+
+ aref++;
+ }
+}
+
+void khm_create_standard_toolbar(HWND rebar) {
+ HWND hwtb;
+ SIZE sz;
+ HBITMAP hbm_blank;
+ HIMAGELIST hiList;
+ REBARBANDINFO rbi;
+ khui_menu_def * def;
+ khui_action * act;
+ khui_action_ref * aref;
+ int idx_blank;
+
+ def = khui_find_menu(KHUI_TOOLBAR_STANDARD);
+
+ if (!def) {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ return;
+ }
+
+ hwtb = CreateWindowEx(0 ,
+ TOOLBARCLASSNAME,
+ (LPWSTR) NULL,
+ WS_CHILD |
+ TBSTYLE_FLAT |
+ TBSTYLE_AUTOSIZE |
+ TBSTYLE_TOOLTIPS |
+ CCS_NORESIZE |
+ CCS_NOPARENTALIGN |
+ CCS_ADJUSTABLE |
+ CCS_NODIVIDER,
+ 0, 0, 0, 0, rebar,
+ (HMENU) NULL, khm_hInstance,
+ NULL);
+
+ if(!hwtb) {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ return;
+ }
+
+#if (_WIN32_IE >= 0x0501)
+ SendMessage(hwtb, TB_SETEXTENDEDSTYLE, 0,
+ TBSTYLE_EX_MIXEDBUTTONS | TBSTYLE_EX_DRAWDDARROWS);
+#endif
+
+ hiList = ImageList_Create(
+ KHUI_TOOLBAR_IMAGE_WIDTH,
+ KHUI_TOOLBAR_IMAGE_HEIGHT,
+ ILC_MASK,
+ (int) khui_action_list_length(def->items),
+ 3);
+
+ hbm_blank = LoadImage(khm_hInstance,
+ MAKEINTRESOURCE(IDB_TB_BLANK),
+ IMAGE_BITMAP,
+ KHUI_TOOLBAR_IMAGE_WIDTH,
+ KHUI_TOOLBAR_IMAGE_HEIGHT, 0);
+ idx_blank = ImageList_AddMasked(hiList, hbm_blank, RGB(0,0,0));
+
+ khui_hwnd_standard_toolbar = hwtb;
+ khui_tb_blank = idx_blank;
+
+ def = khui_find_menu(KHUI_TOOLBAR_STANDARD);
+
+ aref = def->items;
+
+ SendMessage(hwtb,
+ TB_BUTTONSTRUCTSIZE,
+ sizeof(TBBUTTON),
+ 0);
+
+ SendMessage(hwtb,
+ TB_SETBITMAPSIZE,
+ 0,
+ MAKELONG(KHUI_TOOLBAR_IMAGE_WIDTH,KHUI_TOOLBAR_IMAGE_HEIGHT));
+
+ SendMessage(hwtb,
+ TB_SETIMAGELIST,
+ 0,
+ (LPARAM) hiList);
+
+ SendMessage(hwtb,
+ TB_SETBUTTONSIZE,
+ 0,
+ MAKELONG(KHUI_TOOLBAR_IMAGE_WIDTH,KHUI_TOOLBAR_IMAGE_HEIGHT));
+
+ while(aref && aref->action != KHUI_MENU_END) {
+ if(aref->action == KHUI_MENU_SEP) {
+ khui_add_action_to_toolbar(hwtb,
+ NULL,
+ KHUI_TOOLBAR_ADD_SEP,
+ hiList);
+ } else {
+ act = khui_find_action(aref->action);
+ khui_add_action_to_toolbar(hwtb,
+ act,
+ KHUI_TOOLBAR_ADD_BITMAP |
+ ((aref->flags & KHUI_ACTIONREF_SUBMENU)?
+ KHUI_TOOLBAR_ADD_DROPDOWN: 0),
+ hiList);
+ }
+ aref ++;
+ }
+
+ SendMessage(hwtb,
+ TB_AUTOSIZE,
+ 0,0);
+
+ SendMessage(hwtb,
+ TB_GETMAXSIZE,
+ 0,
+ (LPARAM) &sz);
+
+ sz.cy += 5;
+
+ ZeroMemory(&rbi, sizeof(rbi));
+
+ rbi.cbSize = sizeof(rbi);
+ rbi.fMask =
+ RBBIM_ID |
+ RBBIM_CHILD |
+ RBBIM_CHILDSIZE |
+ RBBIM_IDEALSIZE |
+ RBBIM_SIZE |
+ RBBIM_STYLE;
+ rbi.fStyle =
+ RBBS_USECHEVRON |
+ RBBS_BREAK;
+ rbi.hwndChild = hwtb;
+
+ rbi.wID = KHUI_TOOLBAR_STANDARD;
+ rbi.cx = sz.cx;
+ rbi.cxMinChild = sz.cx;
+ rbi.cyMinChild = sz.cy;
+ rbi.cyChild = rbi.cyMinChild;
+ rbi.cyMaxChild = rbi.cyMinChild;
+ rbi.cyIntegral = rbi.cyMinChild;
+
+ rbi.cxIdeal = rbi.cx;
+
+ SendMessage(rebar,
+ RB_INSERTBAND,
+ 0,
+ (LPARAM) &rbi);
+}
diff --git a/src/windows/identity/ui/toolbar.h b/src/windows/identity/ui/toolbar.h
index 8068a6be24..ac09c6619b 100644
--- a/src/windows/identity/ui/toolbar.h
+++ b/src/windows/identity/ui/toolbar.h
@@ -1,52 +1,52 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#ifndef __KHIMAIRA_TOOLBAR_H
-#define __KHIMAIRA_TOOLBAR_H
-
-extern HWND khui_hwnd_standard_toolbar;
-
-void khui_init_toolbar(void);
-void khui_exit_toolbar(void);
-LRESULT khm_toolbar_notify(LPNMHDR notice);
-void khm_create_standard_toolbar(HWND rebar);
-void khui_add_action_to_toolbar(HWND toolbar, khui_action * act, int opt, HIMAGELIST hiList);
-void khm_update_standard_toolbar(void);
-
-/* options for khui_add_action_to_toolbar */
-#define KHUI_TOOLBAR_ADD_TEXT 0x00000001
-#define KHUI_TOOLBAR_ADD_BITMAP 0x00000002
-#define KHUI_TOOLBAR_ADD_LONGTEXT 0x00000005
-#define KHUI_TOOLBAR_ADD_DROPDOWN 0x00000008
-#define KHUI_TOOLBAR_ADD_SEP 0x00000010
-#define KHUI_TOOLBAR_VARSIZE 0x00000020
-
-#define KHUI_TOOLBAR_IMAGE_WIDTH 29
-#define KHUI_TOOLBAR_IMAGE_HEIGHT 27
-#define KHUI_TOOLBAR_BGCOLOR RGB(0xd7,0xd7,0xd7)
-#define KHUI_TOOLBAR_MAX_BTNS 64
-
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __KHIMAIRA_TOOLBAR_H
+#define __KHIMAIRA_TOOLBAR_H
+
+extern HWND khui_hwnd_standard_toolbar;
+
+void khui_init_toolbar(void);
+void khui_exit_toolbar(void);
+LRESULT khm_toolbar_notify(LPNMHDR notice);
+void khm_create_standard_toolbar(HWND rebar);
+void khui_add_action_to_toolbar(HWND toolbar, khui_action * act, int opt, HIMAGELIST hiList);
+void khm_update_standard_toolbar(void);
+
+/* options for khui_add_action_to_toolbar */
+#define KHUI_TOOLBAR_ADD_TEXT 0x00000001
+#define KHUI_TOOLBAR_ADD_BITMAP 0x00000002
+#define KHUI_TOOLBAR_ADD_LONGTEXT 0x00000005
+#define KHUI_TOOLBAR_ADD_DROPDOWN 0x00000008
+#define KHUI_TOOLBAR_ADD_SEP 0x00000010
+#define KHUI_TOOLBAR_VARSIZE 0x00000020
+
+#define KHUI_TOOLBAR_IMAGE_WIDTH 29
+#define KHUI_TOOLBAR_IMAGE_HEIGHT 27
+#define KHUI_TOOLBAR_BGCOLOR RGB(0xd7,0xd7,0xd7)
+#define KHUI_TOOLBAR_MAX_BTNS 64
+
+#endif
diff --git a/src/windows/identity/uilib/action.c b/src/windows/identity/uilib/action.c
index ae017e1d0a..d5556620d4 100644
--- a/src/windows/identity/uilib/action.c
+++ b/src/windows/identity/uilib/action.c
@@ -1,1656 +1,1656 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- * Copyright (c) 2007 Secure Endpoints Inc.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#define NOEXPORT
-#include<khuidefs.h>
-#include<intaction.h>
-#include<utils.h>
-#include<assert.h>
-
-#include<strsafe.h>
-
-khui_action_ref khui_main_menu[] = {
- MENU_SUBMENU(KHUI_MENU_FILE),
- MENU_SUBMENU(KHUI_MENU_CRED),
- MENU_SUBMENU(KHUI_MENU_VIEW),
- MENU_SUBMENU(KHUI_MENU_OPTIONS),
- MENU_SUBMENU(KHUI_MENU_HELP),
- MENU_END()
-};
-
-khui_action_ref khui_menu_file[] = {
- MENU_ACTION(KHUI_ACTION_PROPERTIES),
- MENU_SEP(),
- MENU_ACTION(KHUI_ACTION_EXIT),
- MENU_END()
-};
-
-khui_action_ref khui_menu_cred[] = {
- MENU_ACTION(KHUI_ACTION_NEW_CRED),
- MENU_SEP(),
- MENU_SUBMENU(KHUI_MENU_RENEW_CRED),
- MENU_ACTION(KHUI_ACTION_IMPORT),
- MENU_SUBMENU(KHUI_MENU_DESTROY_CRED),
- MENU_SEP(),
- MENU_ACTION(KHUI_ACTION_SET_DEF_ID),
-#if 0
- /* not implemented yet */
- MENU_ACTION(KHUI_ACTION_SET_SRCH_ID),
-#endif
- MENU_SEP(),
- MENU_ACTION(KHUI_ACTION_PASSWD_ID),
- MENU_END()
-};
-
-khui_action_ref khui_menu_layout[] = {
- MENU_ACTION(KHUI_ACTION_LAYOUT_ID),
- MENU_ACTION(KHUI_ACTION_LAYOUT_TYPE),
- MENU_ACTION(KHUI_ACTION_LAYOUT_LOC),
- MENU_ACTION(KHUI_ACTION_LAYOUT_CUST),
- MENU_END()
-};
-
-khui_action_ref khui_menu_toolbars[] = {
- MENU_ACTION(KHUI_ACTION_TB_STANDARD),
- MENU_END()
-};
-
-khui_action_ref khui_menu_view[] = {
- MENU_ACTION(KHUI_ACTION_LAYOUT_MINI),
- MENU_SUBMENU(KHUI_MENU_COLUMNS),
- MENU_SUBMENU(KHUI_MENU_LAYOUT),
-#if 0
- /* not implemented yet */
- MENU_SUBMENU(KHUI_MENU_TOOLBARS),
-#endif
- MENU_SEP(),
-#if 0
- /* not implemented yet */
- MENU_ACTION(KHUI_ACTION_DEBUG_WINDOW),
- MENU_SEP(),
-#endif
- MENU_ACTION(KHUI_ACTION_VIEW_REFRESH),
- MENU_END()
-};
-
-khui_action_ref khui_menu_options[] = {
- MENU_ACTION(KHUI_ACTION_OPT_KHIM),
- MENU_ACTION(KHUI_ACTION_OPT_APPEAR),
- MENU_ACTION(KHUI_ACTION_OPT_IDENTS),
- MENU_ACTION(KHUI_ACTION_OPT_NOTIF),
- MENU_ACTION(KHUI_ACTION_OPT_PLUGINS),
- MENU_SEP(),
- MENU_END()
-};
-
-khui_action_ref khui_menu_help[] = {
- MENU_ACTION(KHUI_ACTION_HELP_CTX),
- MENU_SEP(),
- MENU_ACTION(KHUI_ACTION_HELP_INDEX),
- MENU_SEP(),
- MENU_ACTION(KHUI_ACTION_HELP_ABOUT),
- MENU_END()
-};
-
-khui_action_ref khui_toolbar_standard[] = {
- MENU_ACTION(KHUI_ACTION_NEW_CRED),
- MENU_SUBMENU(KHUI_ACTION_RENEW_CRED),
- MENU_ACTION(KHUI_ACTION_IMPORT),
- MENU_SUBMENU(KHUI_ACTION_DESTROY_CRED),
- MENU_SEP(),
- MENU_ACTION(KHUI_ACTION_PASSWD_ID),
- MENU_SEP(),
- MENU_ACTION(KHUI_ACTION_VIEW_REFRESH),
- MENU_ACTION(KHUI_PACTION_BLANK),
- MENU_ACTION(KHUI_ACTION_HELP_CTX),
- MENU_END()
-};
-
-khui_action_ref khui_menu_ident_ctx[] = {
- MENU_ACTION(KHUI_ACTION_PROPERTIES),
- MENU_SEP(),
- MENU_ACTION(KHUI_ACTION_SET_DEF_ID),
- MENU_ACTION(KHUI_ACTION_SET_SRCH_ID),
- MENU_SEP(),
- MENU_ACTION(KHUI_ACTION_NEW_CRED),
- MENU_ACTION(KHUI_ACTION_RENEW_CRED),
- MENU_ACTION(KHUI_ACTION_DESTROY_CRED),
- MENU_END()
-};
-
-khui_action_ref khui_menu_tok_ctx[] = {
- MENU_ACTION(KHUI_ACTION_PROPERTIES),
- MENU_SEP(),
- MENU_ACTION(KHUI_ACTION_NEW_CRED),
- MENU_ACTION(KHUI_ACTION_RENEW_CRED),
- MENU_ACTION(KHUI_ACTION_DESTROY_CRED),
- MENU_END()
-};
-
-khui_action_ref khui_menu_ico_ctx_min[] = {
- MENU_DEFACTION(KHUI_ACTION_OPEN_APP),
- MENU_SEP(),
- MENU_ACTION(KHUI_ACTION_NEW_CRED),
- MENU_SUBMENU(KHUI_MENU_RENEW_CRED),
- MENU_ACTION(KHUI_ACTION_IMPORT),
- MENU_SUBMENU(KHUI_MENU_DESTROY_CRED),
- MENU_SEP(),
- MENU_ACTION(KHUI_ACTION_PASSWD_ID),
- MENU_SEP(),
- MENU_ACTION(KHUI_ACTION_HELP_CTX),
- MENU_ACTION(KHUI_ACTION_HELP_ABOUT),
- MENU_SEP(),
- MENU_ACTION(KHUI_ACTION_EXIT),
- MENU_END()
-};
-
-khui_action_ref khui_menu_ico_ctx_normal[] = {
- MENU_DEFACTION(KHUI_ACTION_CLOSE_APP),
- MENU_SEP(),
- MENU_ACTION(KHUI_ACTION_NEW_CRED),
- MENU_SUBMENU(KHUI_MENU_RENEW_CRED),
- MENU_ACTION(KHUI_ACTION_IMPORT),
- MENU_SUBMENU(KHUI_MENU_DESTROY_CRED),
- MENU_SEP(),
- MENU_ACTION(KHUI_ACTION_PASSWD_ID),
- MENU_SEP(),
- MENU_ACTION(KHUI_ACTION_HELP_CTX),
- MENU_ACTION(KHUI_ACTION_HELP_ABOUT),
- MENU_SEP(),
- MENU_ACTION(KHUI_ACTION_EXIT),
- MENU_END()
-};
-
-khui_action_ref khui_menu_cwheader_ctx[] = {
- MENU_SUBMENU(KHUI_MENU_COLUMNS),
- MENU_SUBMENU(KHUI_MENU_LAYOUT),
- MENU_END()
-};
-
-khui_action_ref khui_menu_columns[] = {
- MENU_END()
-};
-
-khui_action_ref khui_menu_destroy_cred[] = {
- MENU_DEFACTION(KHUI_ACTION_DESTROY_ALL),
- MENU_END()
-};
-
-khui_action_ref khui_menu_renew_cred[] = {
- MENU_DEFACTION(KHUI_ACTION_RENEW_ALL),
- MENU_END()
-};
-
-khui_action_ref khui_pmenu_tok_sel[] = {
- MENU_ACTION(KHUI_ACTION_RENEW_CRED),
- MENU_ACTION(KHUI_ACTION_DESTROY_CRED),
- MENU_END()
-};
-
-khui_action_ref khui_pmenu_id_sel[] = {
- MENU_ACTION(KHUI_ACTION_DESTROY_CRED),
- MENU_ACTION(KHUI_ACTION_RENEW_CRED),
- MENU_END()
-};
-
-/* all stock menus and toolbars */
-khui_menu_def khui_all_menus[] = {
- CONSTMENU(KHUI_MENU_MAIN, KHUI_MENUSTATE_CONSTANT | KHUI_MENUSTATE_SYSTEM, khui_main_menu),
- CONSTMENU(KHUI_MENU_FILE, KHUI_MENUSTATE_CONSTANT | KHUI_MENUSTATE_SYSTEM, khui_menu_file),
- CONSTMENU(KHUI_MENU_CRED, KHUI_MENUSTATE_CONSTANT | KHUI_MENUSTATE_SYSTEM, khui_menu_cred),
- CONSTMENU(KHUI_MENU_VIEW, KHUI_MENUSTATE_CONSTANT | KHUI_MENUSTATE_SYSTEM, khui_menu_view),
- CONSTMENU(KHUI_MENU_LAYOUT, KHUI_MENUSTATE_CONSTANT | KHUI_MENUSTATE_SYSTEM, khui_menu_layout),
- CONSTMENU(KHUI_MENU_TOOLBARS, KHUI_MENUSTATE_CONSTANT | KHUI_MENUSTATE_SYSTEM, khui_menu_toolbars),
- CONSTMENU(KHUI_MENU_OPTIONS, KHUI_MENUSTATE_CONSTANT | KHUI_MENUSTATE_SYSTEM, khui_menu_options),
- CONSTMENU(KHUI_MENU_HELP, KHUI_MENUSTATE_CONSTANT | KHUI_MENUSTATE_SYSTEM, khui_menu_help),
- CONSTMENU(KHUI_MENU_COLUMNS, KHUI_MENUSTATE_CONSTANT | KHUI_MENUSTATE_SYSTEM, khui_menu_columns),
- CONSTMENU(KHUI_MENU_RENEW_CRED, KHUI_MENUSTATE_CONSTANT | KHUI_MENUSTATE_SYSTEM, khui_menu_renew_cred),
- CONSTMENU(KHUI_MENU_DESTROY_CRED, KHUI_MENUSTATE_CONSTANT | KHUI_MENUSTATE_SYSTEM, khui_menu_destroy_cred),
-
- /* toolbars */
- CONSTMENU(KHUI_TOOLBAR_STANDARD, KHUI_MENUSTATE_CONSTANT | KHUI_MENUSTATE_SYSTEM, khui_toolbar_standard),
-
- /* context menus */
- CONSTMENU(KHUI_MENU_IDENT_CTX, KHUI_MENUSTATE_CONSTANT, khui_menu_ident_ctx),
- CONSTMENU(KHUI_MENU_TOK_CTX, KHUI_MENUSTATE_CONSTANT, khui_menu_tok_ctx),
- CONSTMENU(KHUI_MENU_ICO_CTX_MIN, KHUI_MENUSTATE_CONSTANT, khui_menu_ico_ctx_min),
- CONSTMENU(KHUI_MENU_ICO_CTX_NORMAL, KHUI_MENUSTATE_CONSTANT, khui_menu_ico_ctx_normal),
- CONSTMENU(KHUI_MENU_CWHEADER_CTX, KHUI_MENUSTATE_CONSTANT, khui_menu_cwheader_ctx),
-
- /* pseudo menus */
- CONSTMENU(KHUI_PMENU_TOK_SEL, KHUI_MENUSTATE_CONSTANT, khui_pmenu_tok_sel),
- CONSTMENU(KHUI_PMENU_ID_SEL, KHUI_MENUSTATE_CONSTANT, khui_pmenu_id_sel)
-};
-
-int khui_n_all_menus = sizeof(khui_all_menus) / sizeof(khui_menu_def);
-khui_menu_def ** khui_cust_menus = NULL;
-int khui_nc_cust_menus = 0;
-int khui_n_cust_menus = 0;
-CRITICAL_SECTION cs_actions;
-
-#define CACT_NC_ALLOC 32
-
-khui_action ** khui_cust_actions = NULL;
-int khui_nc_cust_actions = 0;
-int khui_n_cust_actions = 0;
-
-HWND khui_hwnd_main; /* main window, for notifying
- action launches and
- dispatching messages to the
- application. */
-
-KHMEXP void KHMAPI
-khui_init_actions(void) {
- InitializeCriticalSection(&cs_actions);
-}
-
-KHMEXP void KHMAPI
-khui_exit_actions(void) {
- DeleteCriticalSection(&cs_actions);
-}
-
-KHMEXP void KHMAPI
-khui_refresh_actions(void) {
- kmq_post_message(KMSG_ACT, KMSG_ACT_REFRESH, 0, 0);
-}
-
-KHMEXP void KHMAPI
-khui_action_lock(void) {
- EnterCriticalSection(&cs_actions);
-}
-
-KHMEXP void KHMAPI
-khui_action_unlock(void) {
- LeaveCriticalSection(&cs_actions);
-}
-
-KHMEXP khm_int32 KHMAPI
-khui_action_create(const wchar_t * name,
- const wchar_t * caption,
- const wchar_t * tooltip,
- void * userdata,
- khm_int32 type,
- khm_handle hsub) {
- khui_action * act;
- khm_int32 action = 0;
- int i;
- size_t s;
-
- if ((name && FAILED(StringCchLength(name, KHUI_MAXCCH_NAME, &s))) ||
- !caption ||
- FAILED(StringCchLength(caption, KHUI_MAXCCH_SHORT_DESC, &s)) ||
- (tooltip && FAILED(StringCchLength(tooltip, KHUI_MAXCCH_SHORT_DESC, &s))) ||
- (type != KHUI_ACTIONTYPE_TRIGGER && type != KHUI_ACTIONTYPE_TOGGLE)) {
- return 0;
- }
-
- EnterCriticalSection(&cs_actions);
- if (name && (act = khui_find_named_action(name))) {
- /* named action already exists */
- action = act->cmd;
- goto _done;
- }
-
- for (i=0; i < khui_n_cust_actions; i++) {
- if (khui_cust_actions[i] == NULL ||
- (khui_cust_actions[i]->state & KHUI_ACTIONSTATE_DELETED))
- break;
- }
-
- if (i >= khui_n_cust_actions &&
- (khui_cust_actions == NULL ||
- khui_n_cust_actions + 1 > khui_nc_cust_actions)) {
-
- khui_nc_cust_actions = UBOUNDSS(khui_n_cust_actions + 1,
- CACT_NC_ALLOC,
- CACT_NC_ALLOC);
-#ifdef DEBUG
- assert(khui_nc_cust_actions > khui_n_cust_actions + 1);
-#endif
- khui_cust_actions = PREALLOC(khui_cust_actions,
- sizeof(*khui_cust_actions) * khui_nc_cust_actions);
-#ifdef DEBUG
- assert(khui_cust_actions);
-#endif
- }
-
- if (i >= khui_n_cust_actions) {
- i = khui_n_cust_actions ++;
- act = PMALLOC(sizeof(khui_action));
- } else {
- act = khui_cust_actions[i];
- if (act == NULL)
- act = PMALLOC(sizeof(khui_action));
- }
-
-#ifdef DEBUG
- assert(act);
-#endif
-
- khui_cust_actions[i] = act;
-
- ZeroMemory(act, sizeof(*act));
-
- act->cmd = KHUI_USERACTION_BASE + i;
- act->type = type;
- act->name = (name? PWCSDUP(name) : 0);
- act->caption = PWCSDUP(caption);
- act->tooltip = (tooltip? PWCSDUP(tooltip) : 0);
- act->listener = hsub;
- act->data = userdata;
- act->state = 0;
-
- action = act->cmd;
-
- _done:
- LeaveCriticalSection(&cs_actions);
-
- if (action)
- kmq_post_message(KMSG_ACT, KMSG_ACT_NEW, action, NULL);
-
- return action;
-}
-
-KHMEXP void * KHMAPI
-khui_action_get_data(khm_int32 action) {
- khui_action * act;
- void * data;
-
- EnterCriticalSection(&cs_actions);
- act = khui_find_action(action);
- if (act == NULL || (act->state & KHUI_ACTIONSTATE_DELETED))
- data = NULL;
- else
- data = act->data;
- LeaveCriticalSection(&cs_actions);
-
- return data;
-}
-
-KHMEXP void KHMAPI
-khui_action_delete(khm_int32 action) {
- khui_action * act;
-
- EnterCriticalSection(&cs_actions);
-
- act = khui_find_action(action);
-
- if (act == NULL) {
- LeaveCriticalSection(&cs_actions);
- return;
- }
-
- /* for the moment, even when the action is deleted, we don't free
- up the block of memory used by the khui_action structure. When
- a new action is created, it will reuse deleted action
- structures. */
- act->state |= KHUI_ACTIONSTATE_DELETED;
- if (act->name)
- PFREE(act->name);
- if (act->caption)
- PFREE(act->caption);
- if (act->tooltip)
- PFREE(act->tooltip);
- if (act->listener)
- kmq_delete_subscription(act->listener);
- act->name = NULL;
- act->caption = NULL;
- act->tooltip = NULL;
- act->listener = NULL;
- LeaveCriticalSection(&cs_actions);
-
- kmq_post_message(KMSG_ACT, KMSG_ACT_DELETE, action, NULL);
-}
-
-#define MENU_NC_ITEMS 8
-
-KHMEXP khui_menu_def * KHMAPI
-khui_menu_create(khm_int32 action)
-{
- khui_menu_def * d;
-
- d = PMALLOC(sizeof(*d));
- ZeroMemory(d, sizeof(*d));
-
- d->cmd = action;
- d->nc_items = MENU_NC_ITEMS;
- d->items = PMALLOC(sizeof(*(d->items)) * d->nc_items);
-
- d->state = KHUI_MENUSTATE_ALLOCD;
-
- if (action) {
- int i;
- EnterCriticalSection(&cs_actions);
-
- for (i=0; i < khui_n_cust_menus; i++) {
- if (khui_cust_menus[i] == NULL)
- break;
- }
-
- if (i >= khui_n_cust_menus) {
-
- if (khui_n_cust_menus + 1 >= khui_nc_cust_menus) {
- khui_nc_cust_menus = UBOUNDSS(khui_n_cust_menus + 1,
- CACT_NC_ALLOC, CACT_NC_ALLOC);
- khui_cust_menus =
- PREALLOC(khui_cust_menus,
- sizeof(khui_cust_menus[0]) * khui_nc_cust_menus);
- }
-
- i = khui_n_cust_menus ++;
- }
-
- khui_cust_menus[i] = d;
-
- LeaveCriticalSection(&cs_actions);
- }
-
- return d;
-}
-
-KHMEXP void KHMAPI
-khui_set_main_window(HWND hwnd) {
- khui_hwnd_main = hwnd;
-}
-
-KHMEXP void KHMAPI
-khui_action_trigger(khm_int32 action, khui_action_context * ctx) {
- khui_action_context save;
-
- if (!khui_hwnd_main)
- return;
-
- if (ctx) {
- khui_context_get(&save);
-
- khui_context_set_indirect(ctx);
- }
-
- SendMessage(khui_hwnd_main, WM_COMMAND,
- MAKEWPARAM(action, 0), (LPARAM) 0);
-
- if (ctx) {
- khui_context_set_indirect(&save);
- }
-}
-
-KHMEXP khui_menu_def * KHMAPI
-khui_menu_dup(khui_menu_def * src)
-{
- khui_menu_def * d;
- size_t i;
- size_t n;
-
- EnterCriticalSection(&cs_actions);
-
- d = khui_menu_create(src->cmd);
-
- if (!(src->state & KHUI_MENUSTATE_ALLOCD))
- n = khui_action_list_length(src->items);
- else
- n = src->n_items;
-
- for (i=0; i<n; i++) {
- if (src->items[i].flags & KHUI_ACTIONREF_PACTION) {
- khui_menu_insert_paction(d, -1, src->items[i].p_action, src->items[i].flags);
- } else {
- khui_menu_insert_action(d, -1, src->items[i].action, 0);
- }
- }
-
- LeaveCriticalSection(&cs_actions);
-
- return d;
-}
-
-KHMEXP void KHMAPI
-khui_menu_delete(khui_menu_def * d)
-{
- int i;
-
- /* non-allocated menus are assumed to have no pointers to other
- allocated blocks */
- if(!(d->state & KHUI_MENUSTATE_ALLOCD)) {
- /* we shouldn't have tried to delete a constant menu */
-#ifdef DEBUG
- assert(FALSE);
-#endif
- return;
- }
-
- EnterCriticalSection(&cs_actions);
-
- for (i=0; i < khui_n_cust_menus; i++) {
- if (khui_cust_menus[i] == d) {
- khui_cust_menus[i] = NULL;
- break;
- }
- }
-
- for(i=0; i< (int) d->n_items; i++) {
- if(d->items[i].flags & KHUI_ACTIONREF_FREE_PACTION)
- PFREE(d->items[i].p_action);
- }
-
- if(d->items)
- PFREE(d->items);
- PFREE(d);
-
- LeaveCriticalSection(&cs_actions);
-}
-
-static void
-menu_assert_size(khui_menu_def * d, size_t n)
-{
-
- assert(d->state & KHUI_MENUSTATE_ALLOCD);
-
- if(n > (int) d->nc_items) {
- khui_action_ref * ni;
-
- d->nc_items = UBOUNDSS(n, MENU_NC_ITEMS, MENU_NC_ITEMS);
- ni = PMALLOC(sizeof(*(d->items)) * d->nc_items);
- memcpy(ni, d->items, sizeof(*(d->items)) * d->n_items);
- PFREE(d->items);
- d->items = ni;
- }
-}
-
-static void
-menu_const_to_allocd(khui_menu_def * d)
-{
- khui_action_ref * olist;
- khui_action_ref * nlist;
- khm_size n;
-
- assert(!(d->state & KHUI_MENUSTATE_ALLOCD));
-
- olist = d->items;
- n = khui_action_list_length(d->items);
-
- d->nc_items = UBOUNDSS(n, MENU_NC_ITEMS, MENU_NC_ITEMS);
- nlist = PMALLOC(sizeof(d->items[0]) * d->nc_items);
- memcpy(nlist, olist, sizeof(d->items[0]) * n);
-
- d->items = nlist;
- d->n_items = n;
- d->state |= KHUI_MENUSTATE_ALLOCD;
-}
-
-KHMEXP void KHMAPI
-khui_menu_insert_action(khui_menu_def * d, khm_size idx, khm_int32 action, khm_int32 flags)
-{
- khm_size i;
-
- EnterCriticalSection(&cs_actions);
-
- if (!(d->state & KHUI_MENUSTATE_ALLOCD))
- menu_const_to_allocd(d);
-
- assert(d->state & KHUI_MENUSTATE_ALLOCD);
- assert(action == KHUI_MENU_SEP || action > 0);
-
- if (idx < 0 || idx > d->n_items)
- idx = d->n_items;
-
- menu_assert_size(d, d->n_items + 1);
-
- if (idx < d->n_items) {
- memmove(&d->items[idx + 1], &d->items[idx], (d->n_items - idx) * sizeof(d->items[0]));
- }
-
- d->items[idx].flags = flags;
- d->items[idx].action = action;
- if (action == KHUI_MENU_SEP)
- d->items[idx].flags |= KHUI_ACTIONREF_SEP;
-
- d->n_items++;
-
- /* only one action is allowed to have the KHUI_ACTIONREF_DEFAULT
- flag */
- if (flags & KHUI_ACTIONREF_DEFAULT) {
- for (i=0; i < d->n_items; i++) {
- if (i != idx && (d->items[i].flags & KHUI_ACTIONREF_DEFAULT))
- d->items[i].flags &= ~KHUI_ACTIONREF_DEFAULT;
- }
- }
-
- LeaveCriticalSection(&cs_actions);
-}
-
-KHMEXP void KHMAPI
-khui_menu_insert_paction(khui_menu_def * d, khm_size idx, khui_action * paction, int flags)
-{
- khm_size i;
-
- if (paction == NULL)
- return;
-
- EnterCriticalSection(&cs_actions);
-
- if (!(d->state & KHUI_MENUSTATE_ALLOCD))
- menu_const_to_allocd(d);
-
- assert(d->state & KHUI_MENUSTATE_ALLOCD);
-
- if (idx < 0 || idx > d->n_items)
- idx = d->n_items;
-
- menu_assert_size(d, d->n_items + 1);
-
- if (idx < d->n_items) {
- memmove(&d->items[idx + 1], &d->items[idx], (d->n_items - idx) * sizeof(d->items[0]));
- }
-
- d->items[idx].flags = flags | KHUI_ACTIONREF_PACTION;
- d->items[idx].p_action = paction;
-
- d->n_items++;
-
- /* only one action is allowed to have the KHUI_ACTIONREF_DEFAULT
- flag */
- if (flags & KHUI_ACTIONREF_DEFAULT) {
- for (i=0; i < d->n_items; i++) {
- if (i != idx && (d->items[i].flags & KHUI_ACTIONREF_DEFAULT))
- d->items[i].flags &= ~KHUI_ACTIONREF_DEFAULT;
- }
- }
-
- LeaveCriticalSection(&cs_actions);
-}
-
-KHMEXP void KHMAPI
-khui_menu_remove_action(khui_menu_def * d, khm_size idx) {
-
- EnterCriticalSection(&cs_actions);
-
- if (!(d->state & KHUI_MENUSTATE_ALLOCD))
- menu_const_to_allocd(d);
-
- assert(d->state & KHUI_MENUSTATE_ALLOCD);
-
- if (idx >= 0 && idx < d->n_items) {
-
- if (idx < d->n_items - 1) {
- memmove(&d->items[idx], &d->items[idx + 1],
- ((d->n_items - 1) - idx) * sizeof(d->items[0]));
- }
-
- d->n_items--;
-
- }
-
- LeaveCriticalSection(&cs_actions);
-}
-
-KHMEXP khm_size KHMAPI
-khui_menu_get_size(khui_menu_def * d) {
-
- khm_size size;
-
- EnterCriticalSection(&cs_actions);
-
- if (d->state & KHUI_MENUSTATE_ALLOCD)
- size = d->n_items;
- else
- size = khui_action_list_length(d->items);
-
- LeaveCriticalSection(&cs_actions);
-
- return size;
-}
-
-KHMEXP khui_action_ref *
-khui_menu_get_action(khui_menu_def * d, khm_size idx) {
-
- khui_action_ref * act = NULL;
- khm_size n;
-
- EnterCriticalSection(&cs_actions);
-
- if (d->state & KHUI_MENUSTATE_ALLOCD)
- n = d->n_items;
- else
- n = khui_action_list_length(d->items);
-
- if (idx < 0 || idx >= n)
- act = NULL;
- else
- act = &d->items[idx];
-
- LeaveCriticalSection(&cs_actions);
-
- return act;
-}
-
-KHMEXP khui_menu_def * KHMAPI
-khui_find_menu(khm_int32 id) {
- khui_menu_def * d;
- int i;
-
- if (id < KHUI_USERACTION_BASE) {
-
- /* the list of system menus are considered immutable. */
-
- d = khui_all_menus;
- for(i=0;i<khui_n_all_menus;i++) {
- if(id == d[i].cmd)
- return &d[i];
- }
-
- return NULL;
- } else {
- d = NULL;
-
- EnterCriticalSection(&cs_actions);
- for (i=0; i < khui_n_cust_menus; i++) {
- if (khui_cust_menus[i] &&
- khui_cust_menus[i]->cmd == id) {
- d = khui_cust_menus[i];
- break;
- }
- }
- LeaveCriticalSection(&cs_actions);
-
- return d;
- }
-}
-
-KHMEXP khui_action * KHMAPI
-khui_find_action(khm_int32 id) {
- khui_action * act;
- int i;
-
- act = khui_actions;
- for(i=0;i<khui_n_actions;i++) {
- if(act[i].cmd == id)
- return &act[i];
- }
-
- act = NULL;
-
- EnterCriticalSection(&cs_actions);
- if (id >= KHUI_USERACTION_BASE &&
- (id - KHUI_USERACTION_BASE) < khui_n_cust_actions) {
- act = khui_cust_actions[id - KHUI_USERACTION_BASE];
-#ifdef DEBUG
- assert(!act || act->cmd == id);
-#endif
- if (act && (act->state & KHUI_ACTIONSTATE_DELETED))
- act = NULL;
- }
- LeaveCriticalSection(&cs_actions);
-
- return act;
-}
-
-KHMEXP khui_action * KHMAPI
-khui_find_named_action(const wchar_t * name) {
- int i;
- khui_action * act;
- khui_action ** pact;
-
- if(!name)
- return NULL;
-
- act = khui_actions;
- for(i=0;i<khui_n_actions;i++) {
- if(!act[i].name)
- continue;
- if(!wcscmp(act[i].name, name))
- return &act[i];
- }
-
- act = NULL;
-
- EnterCriticalSection(&cs_actions);
-
- pact = khui_cust_actions;
- for(i=0;i<khui_n_cust_actions;i++) {
- if(!pact[i] || !pact[i]->name)
- continue;
-
- if(!wcscmp(pact[i]->name, name)) {
-
- if (!(pact[i]->state & KHUI_ACTIONSTATE_DELETED)) {
- act = pact[i];
- }
- break;
- }
- }
-
- LeaveCriticalSection(&cs_actions);
-
- return act;
-}
-
-KHMEXP size_t KHMAPI
-khui_action_list_length(khui_action_ref * ref) {
- size_t c = 0;
-
- EnterCriticalSection(&cs_actions);
-
- while(ref && ref->action != KHUI_MENU_END &&
- !(ref->flags & KHUI_ACTIONREF_END)) {
- c++;
- ref++;
- }
-
- LeaveCriticalSection(&cs_actions);
-
- return c;
-}
-
-KHMEXP void KHMAPI
-khui_check_radio_action(khui_menu_def * d, khm_int32 cmd)
-{
- khui_action_ref * r;
- khui_action * act;
-
- EnterCriticalSection(&cs_actions);
-
- r = d->items;
- while(r && r->action != KHUI_MENU_END &&
- (!(d->state & KHUI_MENUSTATE_ALLOCD) || (r - d->items) < (int) d->n_items)) {
- if(r->flags & KHUI_ACTIONREF_PACTION) {
- act = r->p_action;
- } else {
- act = khui_find_action(r->action);
- }
-
- if(act) {
- if(act->cmd == cmd)
- act->state |= KHUI_ACTIONSTATE_CHECKED;
- else
- act->state &= ~KHUI_ACTIONSTATE_CHECKED;
- }
- r++;
- }
-
- LeaveCriticalSection(&cs_actions);
-
- kmq_post_message(KMSG_ACT, KMSG_ACT_CHECK, 0, 0);
-}
-
-KHMEXP void KHMAPI
-khui_check_action(khm_int32 cmd, khm_boolean check) {
- khui_action * act;
-
- act = khui_find_action(cmd);
- if (!act)
- return;
-
- EnterCriticalSection(&cs_actions);
-
- if (check && !(act->state & KHUI_ACTIONSTATE_CHECKED))
- act->state |= KHUI_ACTIONSTATE_CHECKED;
- else if (!check && (act->state & KHUI_ACTIONSTATE_CHECKED))
- act->state &= ~KHUI_ACTIONSTATE_CHECKED;
- else {
- LeaveCriticalSection(&cs_actions);
- return;
- }
-
- LeaveCriticalSection(&cs_actions);
-
- kmq_post_message(KMSG_ACT, KMSG_ACT_CHECK, 0, 0);
-}
-
-KHMEXP void KHMAPI
-khui_enable_actions(khui_menu_def * d, khm_boolean enable)
-{
- khui_action_ref * r;
- int delta = FALSE;
- khui_action * act;
-
- EnterCriticalSection(&cs_actions);
-
- r = d->items;
- while(r && r->action != KHUI_MENU_END &&
- (!(d->state & KHUI_MENUSTATE_ALLOCD) || (r - d->items) < (int) d->n_items)) {
- if(r->flags & KHUI_ACTIONREF_PACTION) {
- act = r->p_action;
- } else {
- act = khui_find_action(r->action);
- }
-
- if(act) {
- int old_state = act->state;
-
- if(enable)
- act->state &= ~KHUI_ACTIONSTATE_DISABLED;
- else
- act->state |= KHUI_ACTIONSTATE_DISABLED;
-
- if(old_state != act->state)
- delta = TRUE;
- }
- r++;
- }
-
- LeaveCriticalSection(&cs_actions);
-
- if(delta) {
- kmq_post_message(KMSG_ACT, KMSG_ACT_ENABLE, 0, 0);
- }
-}
-
-KHMEXP void KHMAPI
-khui_enable_action(khm_int32 cmd, khm_boolean enable) {
- khui_action * act;
-
- act = khui_find_action(cmd);
- if (!act)
- return;
-
- EnterCriticalSection(&cs_actions);
-
- if (enable && (act->state & KHUI_ACTIONSTATE_DISABLED)) {
- act->state &= ~KHUI_ACTIONSTATE_DISABLED;
- } else if (!enable && !(act->state & KHUI_ACTIONSTATE_DISABLED)) {
- act->state |= KHUI_ACTIONSTATE_DISABLED;
- } else {
- LeaveCriticalSection(&cs_actions);
- return;
- }
-
- LeaveCriticalSection(&cs_actions);
-
- kmq_post_message(KMSG_ACT, KMSG_ACT_ENABLE, 0, 0);
-}
-
-KHMEXP HACCEL KHMAPI
-khui_create_global_accel_table(void) {
- int i;
- ACCEL * accels;
- HACCEL ha;
-
- accels = PMALLOC(sizeof(ACCEL) * khui_n_accel_global);
- for(i=0;i<khui_n_accel_global;i++) {
- accels[i].cmd = khui_accel_global[i].cmd;
- accels[i].fVirt = khui_accel_global[i].mod;
- accels[i].key = khui_accel_global[i].key;
- }
-
- ha = CreateAcceleratorTable(accels, khui_n_accel_global);
-
- PFREE(accels);
-
- return ha;
-}
-
-KHMEXP khm_boolean KHMAPI
-khui_get_cmd_accel_string(khm_int32 cmd,
- wchar_t * buf,
- khm_size bufsiz) {
- int i;
- khui_accel_def * def;
-
- /* should at least hold 2 characters */
- if(bufsiz < sizeof(wchar_t) * 2)
- return FALSE;
-
- buf[0] = L'\0';
-
- for(i=0;i<khui_n_accel_global;i++) {
- if(khui_accel_global[i].cmd == cmd)
- break;
- }
-
- if(i==khui_n_accel_global)
- return FALSE;
-
- def = &khui_accel_global[i];
-
- if(def->mod & FALT) {
- if(FAILED(StringCbCat(buf, bufsiz, L"Alt+")))
- return FALSE;
- }
-
-
- if(def->mod & FCONTROL) {
- if(FAILED(StringCbCat(buf, bufsiz, L"Ctrl+")))
- return FALSE;
- }
-
- if(def->mod & FSHIFT) {
- if(FAILED(StringCbCat(buf, bufsiz, L"Shift+")))
- return FALSE;
- }
-
- if(def->mod & FVIRTKEY) {
- wchar_t mbuf[6];
- wchar_t * ap = NULL;
- switch(def->key) {
- case VK_TAB:
- ap = L"Tab";
- break;
-
- case VK_ESCAPE:
- ap = L"Esc";
- break;
-
- case VK_RETURN:
- ap = L"Enter";
- break;
-
- case VK_F1:
- ap = L"F1";
- break;
-
- case VK_F2:
- ap = L"F2";
- break;
-
- case VK_F3:
- ap = L"F3";
- break;
-
- case VK_F4:
- ap = L"F4";
- break;
-
- case VK_F5:
- ap = L"F5";
- break;
-
- case VK_F6:
- ap = L"F6";
- break;
-
- case VK_F7:
- ap = L"F7";
- break;
-
- case VK_F8:
- ap = L"F8";
- break;
-
- case VK_F9:
- ap = L"F9";
- break;
-
- case VK_F10:
- ap = L"F10";
- break;
-
- case VK_F11:
- ap = L"F11";
- break;
-
- case VK_F12:
- ap = L"F12";
- break;
-
- case VK_DELETE:
- ap = L"Del";
- break;
-
- default:
- if((def->key >= '0' &&
- def->key <= '9') ||
- (def->key >= 'A' &&
- def->key <= 'Z')) {
- ap = mbuf;
- mbuf[0] = (wchar_t) def->key;
- mbuf[1] = L'\0';
- }
- }
- if(ap) {
- if(FAILED(StringCbCat(buf, bufsiz, ap)))
- return FALSE;
- }
- else {
- if(FAILED(StringCbCat(buf, bufsiz,L"???")))
- return FALSE;
- }
-
- } else {
- wchar_t mbuf[2];
-
- mbuf[0] = def->key;
- mbuf[1] = L'\0';
-
- if(FAILED(StringCbCat(buf, bufsiz, mbuf)))
- return FALSE;
- }
-
- return TRUE;
-}
-
-/******************************************/
-/* contexts */
-
-#define KHUI_ACTION_CONTEXT_MAGIC 0x39c49db5
-
-static khm_int32 KHMAPI
-khuiint_filter_selected(khm_handle cred,
- khm_int32 vflags,
- void * rock) {
- khm_int32 flags;
- if (KHM_SUCCEEDED(kcdb_cred_get_flags(cred, &flags)) &&
- (flags & KCDB_CRED_FLAG_SELECTED))
- return TRUE;
- else
- return FALSE;
-}
-
-static void
-khuiint_context_release(khui_action_context * ctx) {
- ctx->scope = KHUI_SCOPE_NONE;
- if (ctx->identity)
- kcdb_identity_release(ctx->identity);
- ctx->identity = NULL;
- ctx->cred_type = KCDB_CREDTYPE_INVALID;
- if (ctx->cred)
- kcdb_cred_release(ctx->cred);
- ctx->cred = NULL;
- ctx->n_headers = 0;
- if (ctx->credset)
- kcdb_credset_flush(ctx->credset);
- ctx->n_sel_creds = 0;
- ctx->int_cb_used = 0;
- ctx->vparam = NULL;
- ctx->cb_vparam = 0;
-}
-
-static void
-khuiint_copy_context(khui_action_context * ctxdest,
- const khui_action_context * ctxsrc)
-{
- ctxdest->scope = ctxsrc->scope;
-
- if (ctxsrc->scope == KHUI_SCOPE_IDENT) {
- ctxdest->identity = ctxsrc->identity;
- kcdb_identity_hold(ctxsrc->identity);
- } else if (ctxsrc->scope == KHUI_SCOPE_CREDTYPE) {
- ctxdest->identity = ctxsrc->identity;
- ctxdest->cred_type = ctxsrc->cred_type;
- if (ctxsrc->identity != NULL)
- kcdb_identity_hold(ctxsrc->identity);
- } else if (ctxsrc->scope == KHUI_SCOPE_CRED) {
- kcdb_cred_get_identity(ctxsrc->cred, &ctxdest->identity);
- kcdb_cred_get_type(ctxsrc->cred, &ctxdest->cred_type);
- ctxdest->cred = ctxsrc->cred;
- kcdb_cred_hold(ctxsrc->cred);
- } else if (ctxsrc->scope == KHUI_SCOPE_GROUP) {
- khm_size cb_total;
- int i;
-
- ctxdest->n_headers = ctxsrc->n_headers;
- cb_total = 0;
- for (i=0; i < (int) ctxsrc->n_headers; i++) {
- cb_total += UBOUND32(ctxsrc->headers[i].cb_data);
- }
-
- if (ctxdest->int_cb_buf < cb_total) {
-
- if (ctxdest->int_buf)
- PFREE(ctxdest->int_buf);
-
- ctxdest->int_cb_buf = cb_total;
- ctxdest->int_buf = PMALLOC(cb_total);
- }
-
-#ifdef DEBUG
- assert(ctxdest->int_buf || cb_total == 0);
-#endif
- ctxdest->int_cb_used = 0;
-
- for (i=0; i < (int) ctxsrc->n_headers; i++) {
- ctxdest->headers[i].attr_id = ctxsrc->headers[i].attr_id;
- ctxdest->headers[i].cb_data = ctxsrc->headers[i].cb_data;
- if (ctxsrc->headers[i].cb_data > 0) {
- ctxdest->headers[i].data =
- BYTEOFFSET(ctxdest->int_buf,
- ctxdest->int_cb_used);
- memcpy(ctxdest->headers[i].data,
- ctxsrc->headers[i].data,
- ctxsrc->headers[i].cb_data);
- ctxdest->int_cb_used +=
- UBOUND32(ctxsrc->headers[i].cb_data);
- } else {
- ctxdest->headers[i].data = NULL;
- }
- }
- }
-
- if (ctxsrc->credset) {
-
- if (ctxdest->credset == NULL)
- kcdb_credset_create(&ctxdest->credset);
-#ifdef DEBUG
- assert(ctxdest->credset != NULL);
-#endif
-
- kcdb_credset_flush(ctxdest->credset);
-
- kcdb_credset_extract_filtered(ctxdest->credset,
- ctxsrc->credset,
- khuiint_filter_selected,
- NULL);
-
- kcdb_credset_get_size(ctxdest->credset,
- &ctxdest->n_sel_creds);
- } else {
- if (ctxdest->credset != NULL)
- kcdb_credset_flush(ctxdest->credset);
- ctxdest->n_sel_creds = 0;
- }
-
- /* For now, we simply transfer the vparam buffer into the new
- context. If we are copying, we also need to modify
- khui_context_release() to free the allocated buffer */
-#if 0
- if (ctxsrc->vparam && ctxsrc->cb_vparam) {
- ctxdest->vparam = PMALLOC(ctxsrc->cb_vparam);
-#ifdef DEBUG
- assert(ctxdest->vparam);
-#endif
- memcpy(ctxdest->vparam, ctxsrc->vparam, ctxsrc->cb_vparam);
- ctxdest->cb_vparam = ctxsrc->cb_vparam;
- } else {
-#endif
- ctxdest->vparam = ctxsrc->vparam;
- ctxdest->cb_vparam = ctxsrc->cb_vparam;
-#if 0
- }
-#endif
-}
-
-static void
-khuiint_context_init(khui_action_context * ctx) {
- ctx->magic = KHUI_ACTION_CONTEXT_MAGIC;
- ctx->scope = KHUI_SCOPE_NONE;
- ctx->identity = NULL;
- ctx->cred_type = KCDB_CREDTYPE_INVALID;
- ctx->cred = NULL;
- ZeroMemory(ctx->headers, sizeof(ctx->headers));
- ctx->n_headers = 0;
- ctx->credset = NULL;
- ctx->n_sel_creds = 0;
- ctx->int_buf = NULL;
- ctx->int_cb_buf = 0;
- ctx->int_cb_used = 0;
- ctx->vparam = NULL;
- ctx->cb_vparam = 0;
-}
-
-khui_action_context khui_ctx = {
- KHUI_ACTION_CONTEXT_MAGIC,
- KHUI_SCOPE_NONE,
- NULL,
- KCDB_CREDTYPE_INVALID,
- NULL,
- {
- {KCDB_ATTR_INVALID,NULL,0},
- {KCDB_ATTR_INVALID,NULL,0},
- {KCDB_ATTR_INVALID,NULL,0},
- {KCDB_ATTR_INVALID,NULL,0},
- {KCDB_ATTR_INVALID,NULL,0},
- {KCDB_ATTR_INVALID,NULL,0}
- },
- 0,
- NULL,
- 0,
- NULL,
- 0,
- 0,
- NULL,
- 0};
-
-khm_int32 KHMAPI
-set_cred_select_flag(khm_handle cred, void * rock) {
- kcdb_cred_set_flags(cred, KCDB_CRED_FLAG_SELECTED,
- KCDB_CRED_FLAG_SELECTED);
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP void KHMAPI
-khui_context_create(khui_action_context * ctx,
- khui_scope scope,
- khm_handle identity,
- khm_int32 cred_type,
- khm_handle cred)
-{
- khui_action_context tctx;
-
- khuiint_context_init(&tctx);
- khuiint_context_init(ctx);
-
- tctx.scope = scope;
- tctx.identity = identity;
- tctx.cred_type = cred_type;
- tctx.cred = cred;
-
- /* fill up the credset based on the scope */
- if (scope != KHUI_SCOPE_NONE) {
- if (tctx.credset == NULL)
- kcdb_credset_create(&tctx.credset);
- else
- kcdb_credset_flush(tctx.credset);
-
- if (scope == KHUI_SCOPE_IDENT) {
- kcdb_credset_extract(tctx.credset,
- NULL,
- tctx.identity,
- KCDB_CREDTYPE_INVALID);
- } else if (scope == KHUI_SCOPE_CREDTYPE) {
- kcdb_credset_extract(tctx.credset,
- NULL,
- tctx.identity,
- tctx.cred_type);
- } else if (scope == KHUI_SCOPE_CRED) {
- khm_handle dupcred = NULL;
- kcdb_cred_dup(cred, &dupcred);
-
- kcdb_credset_add_cred(tctx.credset, dupcred, -1);
- } else {
-#ifdef DEBUG
- /* KHUI_SCOPE_GROUP is not used with
- khui_context_create() */
- assert(FALSE);
-#endif
- }
-
- kcdb_credset_apply(tctx.credset, set_cred_select_flag,
- NULL);
-
- kcdb_credset_seal(tctx.credset);
- }
-
- khuiint_copy_context(ctx, &tctx);
-}
-
-KHMEXP void KHMAPI
-khui_context_set(khui_scope scope,
- khm_handle identity,
- khm_int32 cred_type,
- khm_handle cred,
- khui_header *headers,
- khm_size n_headers,
- khm_handle cs_src) {
-
- khui_context_set_ex(scope,
- identity,
- cred_type,
- cred,
- headers,
- n_headers,
- cs_src,
- NULL,
- 0);
-}
-
-KHMEXP void KHMAPI
-khui_context_set_ex(khui_scope scope,
- khm_handle identity,
- khm_int32 cred_type,
- khm_handle cred,
- khui_header *headers,
- khm_size n_headers,
- khm_handle cs_src,
- void * vparam,
- khm_size cb_vparam)
-{
- khui_action_context tctx;
-
- EnterCriticalSection(&cs_actions);
-
- khuiint_context_release(&khui_ctx);
-
- khuiint_context_init(&tctx);
-
- tctx.scope = scope;
- tctx.identity = identity;
- tctx.cred_type = cred_type;
- tctx.cred = cred;
- if (headers) {
- tctx.n_headers = n_headers;
- memcpy(tctx.headers,
- headers,
- sizeof(*headers) * n_headers);
- } else {
- tctx.n_headers = 0;
- }
- tctx.credset = cs_src;
- tctx.n_sel_creds = 0; /* ignored */
- tctx.vparam = vparam;
- tctx.cb_vparam = cb_vparam;
- tctx.int_buf = NULL;
- tctx.int_cb_buf = 0;
- tctx.int_cb_used = 0;
-
- khuiint_copy_context(&khui_ctx, &tctx);
-
- khui_context_refresh();
-
- LeaveCriticalSection(&cs_actions);
-}
-
-KHMEXP void KHMAPI
-khui_context_set_indirect(khui_action_context * ctx)
-{
- EnterCriticalSection(&cs_actions);
-
- khuiint_context_release(&khui_ctx);
-
- khuiint_copy_context(&khui_ctx, ctx);
-
- khui_context_refresh();
-
- LeaveCriticalSection(&cs_actions);
-}
-
-KHMEXP void KHMAPI
-khui_context_refresh(void) {
- khm_int32 flags;
-
- EnterCriticalSection(&cs_actions);
- if (khui_ctx.identity) {
- /* an identity is selected */
-
- if (KHM_SUCCEEDED(kcdb_identity_get_flags(khui_ctx.identity,
- &flags)) &&
- (flags & KCDB_IDENT_FLAG_DEFAULT)) {
- khui_check_action(KHUI_ACTION_SET_DEF_ID, TRUE);
- khui_enable_action(KHUI_ACTION_SET_DEF_ID, FALSE);
- } else {
- khui_check_action(KHUI_ACTION_SET_DEF_ID, FALSE);
- khui_enable_action(KHUI_ACTION_SET_DEF_ID, TRUE);
- }
- } else {
- khui_check_action(KHUI_ACTION_SET_DEF_ID, FALSE);
- khui_enable_action(KHUI_ACTION_SET_DEF_ID, FALSE);
- }
-
- if (khui_ctx.scope != KHUI_SCOPE_NONE) {
- khui_enable_action(KHUI_ACTION_PROPERTIES, TRUE);
- } else {
- khui_enable_action(KHUI_ACTION_PROPERTIES, FALSE);
- }
-
- LeaveCriticalSection(&cs_actions);
-
- kmq_post_message(KMSG_ACT, KMSG_ACT_REFRESH, 0, 0);
-}
-
-KHMEXP void KHMAPI
-khui_context_get(khui_action_context * ctx)
-{
- EnterCriticalSection(&cs_actions);
-
- khuiint_context_init(ctx);
- khuiint_copy_context(ctx, &khui_ctx);
-
- if (ctx->credset) {
- kcdb_credset_seal(ctx->credset);
- }
-
- LeaveCriticalSection(&cs_actions);
-}
-
-KHMEXP void KHMAPI
-khui_context_release(khui_action_context * ctx)
-{
-#ifdef DEBUG
- assert(ctx->magic == KHUI_ACTION_CONTEXT_MAGIC);
-#endif
-
- khuiint_context_release(ctx);
- if (ctx->credset) {
- kcdb_credset_unseal(ctx->credset);
- kcdb_credset_delete(ctx->credset);
- }
- ctx->credset = NULL;
- if (ctx->int_buf)
- PFREE(ctx->int_buf);
- ctx->int_buf = NULL;
-#if 0
- if (ctx->vparam && ctx->cb_vparam > 0) {
- PFREE(ctx->vparam);
- ctx->vparam = NULL;
- }
- ctx->cb_vparam = 0;
-#else
- ctx->vparam = 0;
- ctx->cb_vparam = 0;
-#endif
-}
-
-KHMEXP void KHMAPI
-khui_context_reset(void)
-{
- EnterCriticalSection(&cs_actions);
-
- khuiint_context_release(&khui_ctx);
-
- khui_context_refresh();
-
- LeaveCriticalSection(&cs_actions);
-}
-
-KHMEXP khm_int32 KHMAPI
-khui_context_cursor_filter(khm_handle cred,
- khm_int32 flags,
- void * rock) {
- khui_action_context * ctx = (khui_action_context *) rock;
- khm_int32 rv;
-
- if (ctx->scope == KHUI_SCOPE_NONE)
- return 0;
- else if (ctx->scope == KHUI_SCOPE_IDENT) {
- khm_handle c_ident;
-
- if (KHM_FAILED(kcdb_cred_get_identity(cred, &c_ident)))
- return 0;
-
- rv = (c_ident == ctx->identity);
-
- kcdb_identity_release(c_ident);
-
- return rv;
- } else if (ctx->scope == KHUI_SCOPE_CREDTYPE) {
- khm_handle c_ident;
- khm_int32 c_type;
-
- if (KHM_FAILED(kcdb_cred_get_type(cred, &c_type)) ||
- c_type != ctx->cred_type)
- return 0;
-
- if (ctx->identity == NULL)
- return 1;
-
- if (KHM_FAILED(kcdb_cred_get_identity(cred, &c_ident)))
- return 0;
-
- rv = (c_ident == ctx->identity);
-
- kcdb_identity_release(c_ident);
-
- return rv;
- } else if (ctx->scope == KHUI_SCOPE_CRED) {
- return kcdb_creds_is_equal(cred, ctx->cred);
- } else if (ctx->scope == KHUI_SCOPE_GROUP) {
- int i;
-
- rv = 1;
-
- for (i=0; i < (int) ctx->n_headers && rv; i++) {
- kcdb_attrib * pattr;
- kcdb_type * ptype;
- DWORD buffer[1024]; /* 4096 bytes */
- khm_size cb;
-
- if (kcdb_cred_get_attr(cred, ctx->headers[i].attr_id,
- NULL,
- NULL,
- &cb) != KHM_ERROR_TOO_LONG) {
- /* the header doesn't exist anyway */
- rv = (ctx->headers[i].cb_data == 0);
- continue;
- }
-#ifdef DEBUG
- assert(cb <= sizeof(buffer));
-#endif
- cb = sizeof(buffer);
-
- if (KHM_FAILED(kcdb_cred_get_attr(cred,
- ctx->headers[i].attr_id,
- NULL,
- (void *) buffer,
- &cb))) {
- rv = 0;
- continue;
- }
-
- if (KHM_FAILED(kcdb_attrib_get_info(ctx->headers[i].attr_id,
- &pattr))) {
- rv = 0;
- continue;
- }
-
- if (KHM_FAILED(kcdb_type_get_info(pattr->type, &ptype))) {
- rv = 0;
- kcdb_attrib_release_info(pattr);
- continue;
- }
-
- if ((*ptype->comp)(ctx->headers[i].data,
- ctx->headers[i].cb_data,
- (void *) buffer,
- cb) != 0)
- rv = 1;
-
- kcdb_type_release_info(ptype);
- kcdb_attrib_release_info(pattr);
- }
-
- return rv;
- } else
- return 0;
-}
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ * Copyright (c) 2007 Secure Endpoints Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#define NOEXPORT
+#include<khuidefs.h>
+#include<intaction.h>
+#include<utils.h>
+#include<assert.h>
+
+#include<strsafe.h>
+
+khui_action_ref khui_main_menu[] = {
+ MENU_SUBMENU(KHUI_MENU_FILE),
+ MENU_SUBMENU(KHUI_MENU_CRED),
+ MENU_SUBMENU(KHUI_MENU_VIEW),
+ MENU_SUBMENU(KHUI_MENU_OPTIONS),
+ MENU_SUBMENU(KHUI_MENU_HELP),
+ MENU_END()
+};
+
+khui_action_ref khui_menu_file[] = {
+ MENU_ACTION(KHUI_ACTION_PROPERTIES),
+ MENU_SEP(),
+ MENU_ACTION(KHUI_ACTION_EXIT),
+ MENU_END()
+};
+
+khui_action_ref khui_menu_cred[] = {
+ MENU_ACTION(KHUI_ACTION_NEW_CRED),
+ MENU_SEP(),
+ MENU_SUBMENU(KHUI_MENU_RENEW_CRED),
+ MENU_ACTION(KHUI_ACTION_IMPORT),
+ MENU_SUBMENU(KHUI_MENU_DESTROY_CRED),
+ MENU_SEP(),
+ MENU_ACTION(KHUI_ACTION_SET_DEF_ID),
+#if 0
+ /* not implemented yet */
+ MENU_ACTION(KHUI_ACTION_SET_SRCH_ID),
+#endif
+ MENU_SEP(),
+ MENU_ACTION(KHUI_ACTION_PASSWD_ID),
+ MENU_END()
+};
+
+khui_action_ref khui_menu_layout[] = {
+ MENU_ACTION(KHUI_ACTION_LAYOUT_ID),
+ MENU_ACTION(KHUI_ACTION_LAYOUT_TYPE),
+ MENU_ACTION(KHUI_ACTION_LAYOUT_LOC),
+ MENU_ACTION(KHUI_ACTION_LAYOUT_CUST),
+ MENU_END()
+};
+
+khui_action_ref khui_menu_toolbars[] = {
+ MENU_ACTION(KHUI_ACTION_TB_STANDARD),
+ MENU_END()
+};
+
+khui_action_ref khui_menu_view[] = {
+ MENU_ACTION(KHUI_ACTION_LAYOUT_MINI),
+ MENU_SUBMENU(KHUI_MENU_COLUMNS),
+ MENU_SUBMENU(KHUI_MENU_LAYOUT),
+#if 0
+ /* not implemented yet */
+ MENU_SUBMENU(KHUI_MENU_TOOLBARS),
+#endif
+ MENU_SEP(),
+#if 0
+ /* not implemented yet */
+ MENU_ACTION(KHUI_ACTION_DEBUG_WINDOW),
+ MENU_SEP(),
+#endif
+ MENU_ACTION(KHUI_ACTION_VIEW_REFRESH),
+ MENU_END()
+};
+
+khui_action_ref khui_menu_options[] = {
+ MENU_ACTION(KHUI_ACTION_OPT_KHIM),
+ MENU_ACTION(KHUI_ACTION_OPT_APPEAR),
+ MENU_ACTION(KHUI_ACTION_OPT_IDENTS),
+ MENU_ACTION(KHUI_ACTION_OPT_NOTIF),
+ MENU_ACTION(KHUI_ACTION_OPT_PLUGINS),
+ MENU_SEP(),
+ MENU_END()
+};
+
+khui_action_ref khui_menu_help[] = {
+ MENU_ACTION(KHUI_ACTION_HELP_CTX),
+ MENU_SEP(),
+ MENU_ACTION(KHUI_ACTION_HELP_INDEX),
+ MENU_SEP(),
+ MENU_ACTION(KHUI_ACTION_HELP_ABOUT),
+ MENU_END()
+};
+
+khui_action_ref khui_toolbar_standard[] = {
+ MENU_ACTION(KHUI_ACTION_NEW_CRED),
+ MENU_SUBMENU(KHUI_ACTION_RENEW_CRED),
+ MENU_ACTION(KHUI_ACTION_IMPORT),
+ MENU_SUBMENU(KHUI_ACTION_DESTROY_CRED),
+ MENU_SEP(),
+ MENU_ACTION(KHUI_ACTION_PASSWD_ID),
+ MENU_SEP(),
+ MENU_ACTION(KHUI_ACTION_VIEW_REFRESH),
+ MENU_ACTION(KHUI_PACTION_BLANK),
+ MENU_ACTION(KHUI_ACTION_HELP_CTX),
+ MENU_END()
+};
+
+khui_action_ref khui_menu_ident_ctx[] = {
+ MENU_ACTION(KHUI_ACTION_PROPERTIES),
+ MENU_SEP(),
+ MENU_ACTION(KHUI_ACTION_SET_DEF_ID),
+ MENU_ACTION(KHUI_ACTION_SET_SRCH_ID),
+ MENU_SEP(),
+ MENU_ACTION(KHUI_ACTION_NEW_CRED),
+ MENU_ACTION(KHUI_ACTION_RENEW_CRED),
+ MENU_ACTION(KHUI_ACTION_DESTROY_CRED),
+ MENU_END()
+};
+
+khui_action_ref khui_menu_tok_ctx[] = {
+ MENU_ACTION(KHUI_ACTION_PROPERTIES),
+ MENU_SEP(),
+ MENU_ACTION(KHUI_ACTION_NEW_CRED),
+ MENU_ACTION(KHUI_ACTION_RENEW_CRED),
+ MENU_ACTION(KHUI_ACTION_DESTROY_CRED),
+ MENU_END()
+};
+
+khui_action_ref khui_menu_ico_ctx_min[] = {
+ MENU_DEFACTION(KHUI_ACTION_OPEN_APP),
+ MENU_SEP(),
+ MENU_ACTION(KHUI_ACTION_NEW_CRED),
+ MENU_SUBMENU(KHUI_MENU_RENEW_CRED),
+ MENU_ACTION(KHUI_ACTION_IMPORT),
+ MENU_SUBMENU(KHUI_MENU_DESTROY_CRED),
+ MENU_SEP(),
+ MENU_ACTION(KHUI_ACTION_PASSWD_ID),
+ MENU_SEP(),
+ MENU_ACTION(KHUI_ACTION_HELP_CTX),
+ MENU_ACTION(KHUI_ACTION_HELP_ABOUT),
+ MENU_SEP(),
+ MENU_ACTION(KHUI_ACTION_EXIT),
+ MENU_END()
+};
+
+khui_action_ref khui_menu_ico_ctx_normal[] = {
+ MENU_DEFACTION(KHUI_ACTION_CLOSE_APP),
+ MENU_SEP(),
+ MENU_ACTION(KHUI_ACTION_NEW_CRED),
+ MENU_SUBMENU(KHUI_MENU_RENEW_CRED),
+ MENU_ACTION(KHUI_ACTION_IMPORT),
+ MENU_SUBMENU(KHUI_MENU_DESTROY_CRED),
+ MENU_SEP(),
+ MENU_ACTION(KHUI_ACTION_PASSWD_ID),
+ MENU_SEP(),
+ MENU_ACTION(KHUI_ACTION_HELP_CTX),
+ MENU_ACTION(KHUI_ACTION_HELP_ABOUT),
+ MENU_SEP(),
+ MENU_ACTION(KHUI_ACTION_EXIT),
+ MENU_END()
+};
+
+khui_action_ref khui_menu_cwheader_ctx[] = {
+ MENU_SUBMENU(KHUI_MENU_COLUMNS),
+ MENU_SUBMENU(KHUI_MENU_LAYOUT),
+ MENU_END()
+};
+
+khui_action_ref khui_menu_columns[] = {
+ MENU_END()
+};
+
+khui_action_ref khui_menu_destroy_cred[] = {
+ MENU_DEFACTION(KHUI_ACTION_DESTROY_ALL),
+ MENU_END()
+};
+
+khui_action_ref khui_menu_renew_cred[] = {
+ MENU_DEFACTION(KHUI_ACTION_RENEW_ALL),
+ MENU_END()
+};
+
+khui_action_ref khui_pmenu_tok_sel[] = {
+ MENU_ACTION(KHUI_ACTION_RENEW_CRED),
+ MENU_ACTION(KHUI_ACTION_DESTROY_CRED),
+ MENU_END()
+};
+
+khui_action_ref khui_pmenu_id_sel[] = {
+ MENU_ACTION(KHUI_ACTION_DESTROY_CRED),
+ MENU_ACTION(KHUI_ACTION_RENEW_CRED),
+ MENU_END()
+};
+
+/* all stock menus and toolbars */
+khui_menu_def khui_all_menus[] = {
+ CONSTMENU(KHUI_MENU_MAIN, KHUI_MENUSTATE_CONSTANT | KHUI_MENUSTATE_SYSTEM, khui_main_menu),
+ CONSTMENU(KHUI_MENU_FILE, KHUI_MENUSTATE_CONSTANT | KHUI_MENUSTATE_SYSTEM, khui_menu_file),
+ CONSTMENU(KHUI_MENU_CRED, KHUI_MENUSTATE_CONSTANT | KHUI_MENUSTATE_SYSTEM, khui_menu_cred),
+ CONSTMENU(KHUI_MENU_VIEW, KHUI_MENUSTATE_CONSTANT | KHUI_MENUSTATE_SYSTEM, khui_menu_view),
+ CONSTMENU(KHUI_MENU_LAYOUT, KHUI_MENUSTATE_CONSTANT | KHUI_MENUSTATE_SYSTEM, khui_menu_layout),
+ CONSTMENU(KHUI_MENU_TOOLBARS, KHUI_MENUSTATE_CONSTANT | KHUI_MENUSTATE_SYSTEM, khui_menu_toolbars),
+ CONSTMENU(KHUI_MENU_OPTIONS, KHUI_MENUSTATE_CONSTANT | KHUI_MENUSTATE_SYSTEM, khui_menu_options),
+ CONSTMENU(KHUI_MENU_HELP, KHUI_MENUSTATE_CONSTANT | KHUI_MENUSTATE_SYSTEM, khui_menu_help),
+ CONSTMENU(KHUI_MENU_COLUMNS, KHUI_MENUSTATE_CONSTANT | KHUI_MENUSTATE_SYSTEM, khui_menu_columns),
+ CONSTMENU(KHUI_MENU_RENEW_CRED, KHUI_MENUSTATE_CONSTANT | KHUI_MENUSTATE_SYSTEM, khui_menu_renew_cred),
+ CONSTMENU(KHUI_MENU_DESTROY_CRED, KHUI_MENUSTATE_CONSTANT | KHUI_MENUSTATE_SYSTEM, khui_menu_destroy_cred),
+
+ /* toolbars */
+ CONSTMENU(KHUI_TOOLBAR_STANDARD, KHUI_MENUSTATE_CONSTANT | KHUI_MENUSTATE_SYSTEM, khui_toolbar_standard),
+
+ /* context menus */
+ CONSTMENU(KHUI_MENU_IDENT_CTX, KHUI_MENUSTATE_CONSTANT, khui_menu_ident_ctx),
+ CONSTMENU(KHUI_MENU_TOK_CTX, KHUI_MENUSTATE_CONSTANT, khui_menu_tok_ctx),
+ CONSTMENU(KHUI_MENU_ICO_CTX_MIN, KHUI_MENUSTATE_CONSTANT, khui_menu_ico_ctx_min),
+ CONSTMENU(KHUI_MENU_ICO_CTX_NORMAL, KHUI_MENUSTATE_CONSTANT, khui_menu_ico_ctx_normal),
+ CONSTMENU(KHUI_MENU_CWHEADER_CTX, KHUI_MENUSTATE_CONSTANT, khui_menu_cwheader_ctx),
+
+ /* pseudo menus */
+ CONSTMENU(KHUI_PMENU_TOK_SEL, KHUI_MENUSTATE_CONSTANT, khui_pmenu_tok_sel),
+ CONSTMENU(KHUI_PMENU_ID_SEL, KHUI_MENUSTATE_CONSTANT, khui_pmenu_id_sel)
+};
+
+int khui_n_all_menus = sizeof(khui_all_menus) / sizeof(khui_menu_def);
+khui_menu_def ** khui_cust_menus = NULL;
+int khui_nc_cust_menus = 0;
+int khui_n_cust_menus = 0;
+CRITICAL_SECTION cs_actions;
+
+#define CACT_NC_ALLOC 32
+
+khui_action ** khui_cust_actions = NULL;
+int khui_nc_cust_actions = 0;
+int khui_n_cust_actions = 0;
+
+HWND khui_hwnd_main; /* main window, for notifying
+ action launches and
+ dispatching messages to the
+ application. */
+
+KHMEXP void KHMAPI
+khui_init_actions(void) {
+ InitializeCriticalSection(&cs_actions);
+}
+
+KHMEXP void KHMAPI
+khui_exit_actions(void) {
+ DeleteCriticalSection(&cs_actions);
+}
+
+KHMEXP void KHMAPI
+khui_refresh_actions(void) {
+ kmq_post_message(KMSG_ACT, KMSG_ACT_REFRESH, 0, 0);
+}
+
+KHMEXP void KHMAPI
+khui_action_lock(void) {
+ EnterCriticalSection(&cs_actions);
+}
+
+KHMEXP void KHMAPI
+khui_action_unlock(void) {
+ LeaveCriticalSection(&cs_actions);
+}
+
+KHMEXP khm_int32 KHMAPI
+khui_action_create(const wchar_t * name,
+ const wchar_t * caption,
+ const wchar_t * tooltip,
+ void * userdata,
+ khm_int32 type,
+ khm_handle hsub) {
+ khui_action * act;
+ khm_int32 action = 0;
+ int i;
+ size_t s;
+
+ if ((name && FAILED(StringCchLength(name, KHUI_MAXCCH_NAME, &s))) ||
+ !caption ||
+ FAILED(StringCchLength(caption, KHUI_MAXCCH_SHORT_DESC, &s)) ||
+ (tooltip && FAILED(StringCchLength(tooltip, KHUI_MAXCCH_SHORT_DESC, &s))) ||
+ (type != KHUI_ACTIONTYPE_TRIGGER && type != KHUI_ACTIONTYPE_TOGGLE)) {
+ return 0;
+ }
+
+ EnterCriticalSection(&cs_actions);
+ if (name && (act = khui_find_named_action(name))) {
+ /* named action already exists */
+ action = act->cmd;
+ goto _done;
+ }
+
+ for (i=0; i < khui_n_cust_actions; i++) {
+ if (khui_cust_actions[i] == NULL ||
+ (khui_cust_actions[i]->state & KHUI_ACTIONSTATE_DELETED))
+ break;
+ }
+
+ if (i >= khui_n_cust_actions &&
+ (khui_cust_actions == NULL ||
+ khui_n_cust_actions + 1 > khui_nc_cust_actions)) {
+
+ khui_nc_cust_actions = UBOUNDSS(khui_n_cust_actions + 1,
+ CACT_NC_ALLOC,
+ CACT_NC_ALLOC);
+#ifdef DEBUG
+ assert(khui_nc_cust_actions > khui_n_cust_actions + 1);
+#endif
+ khui_cust_actions = PREALLOC(khui_cust_actions,
+ sizeof(*khui_cust_actions) * khui_nc_cust_actions);
+#ifdef DEBUG
+ assert(khui_cust_actions);
+#endif
+ }
+
+ if (i >= khui_n_cust_actions) {
+ i = khui_n_cust_actions ++;
+ act = PMALLOC(sizeof(khui_action));
+ } else {
+ act = khui_cust_actions[i];
+ if (act == NULL)
+ act = PMALLOC(sizeof(khui_action));
+ }
+
+#ifdef DEBUG
+ assert(act);
+#endif
+
+ khui_cust_actions[i] = act;
+
+ ZeroMemory(act, sizeof(*act));
+
+ act->cmd = KHUI_USERACTION_BASE + i;
+ act->type = type;
+ act->name = (name? PWCSDUP(name) : 0);
+ act->caption = PWCSDUP(caption);
+ act->tooltip = (tooltip? PWCSDUP(tooltip) : 0);
+ act->listener = hsub;
+ act->data = userdata;
+ act->state = 0;
+
+ action = act->cmd;
+
+ _done:
+ LeaveCriticalSection(&cs_actions);
+
+ if (action)
+ kmq_post_message(KMSG_ACT, KMSG_ACT_NEW, action, NULL);
+
+ return action;
+}
+
+KHMEXP void * KHMAPI
+khui_action_get_data(khm_int32 action) {
+ khui_action * act;
+ void * data;
+
+ EnterCriticalSection(&cs_actions);
+ act = khui_find_action(action);
+ if (act == NULL || (act->state & KHUI_ACTIONSTATE_DELETED))
+ data = NULL;
+ else
+ data = act->data;
+ LeaveCriticalSection(&cs_actions);
+
+ return data;
+}
+
+KHMEXP void KHMAPI
+khui_action_delete(khm_int32 action) {
+ khui_action * act;
+
+ EnterCriticalSection(&cs_actions);
+
+ act = khui_find_action(action);
+
+ if (act == NULL) {
+ LeaveCriticalSection(&cs_actions);
+ return;
+ }
+
+ /* for the moment, even when the action is deleted, we don't free
+ up the block of memory used by the khui_action structure. When
+ a new action is created, it will reuse deleted action
+ structures. */
+ act->state |= KHUI_ACTIONSTATE_DELETED;
+ if (act->name)
+ PFREE(act->name);
+ if (act->caption)
+ PFREE(act->caption);
+ if (act->tooltip)
+ PFREE(act->tooltip);
+ if (act->listener)
+ kmq_delete_subscription(act->listener);
+ act->name = NULL;
+ act->caption = NULL;
+ act->tooltip = NULL;
+ act->listener = NULL;
+ LeaveCriticalSection(&cs_actions);
+
+ kmq_post_message(KMSG_ACT, KMSG_ACT_DELETE, action, NULL);
+}
+
+#define MENU_NC_ITEMS 8
+
+KHMEXP khui_menu_def * KHMAPI
+khui_menu_create(khm_int32 action)
+{
+ khui_menu_def * d;
+
+ d = PMALLOC(sizeof(*d));
+ ZeroMemory(d, sizeof(*d));
+
+ d->cmd = action;
+ d->nc_items = MENU_NC_ITEMS;
+ d->items = PMALLOC(sizeof(*(d->items)) * d->nc_items);
+
+ d->state = KHUI_MENUSTATE_ALLOCD;
+
+ if (action) {
+ int i;
+ EnterCriticalSection(&cs_actions);
+
+ for (i=0; i < khui_n_cust_menus; i++) {
+ if (khui_cust_menus[i] == NULL)
+ break;
+ }
+
+ if (i >= khui_n_cust_menus) {
+
+ if (khui_n_cust_menus + 1 >= khui_nc_cust_menus) {
+ khui_nc_cust_menus = UBOUNDSS(khui_n_cust_menus + 1,
+ CACT_NC_ALLOC, CACT_NC_ALLOC);
+ khui_cust_menus =
+ PREALLOC(khui_cust_menus,
+ sizeof(khui_cust_menus[0]) * khui_nc_cust_menus);
+ }
+
+ i = khui_n_cust_menus ++;
+ }
+
+ khui_cust_menus[i] = d;
+
+ LeaveCriticalSection(&cs_actions);
+ }
+
+ return d;
+}
+
+KHMEXP void KHMAPI
+khui_set_main_window(HWND hwnd) {
+ khui_hwnd_main = hwnd;
+}
+
+KHMEXP void KHMAPI
+khui_action_trigger(khm_int32 action, khui_action_context * ctx) {
+ khui_action_context save;
+
+ if (!khui_hwnd_main)
+ return;
+
+ if (ctx) {
+ khui_context_get(&save);
+
+ khui_context_set_indirect(ctx);
+ }
+
+ SendMessage(khui_hwnd_main, WM_COMMAND,
+ MAKEWPARAM(action, 0), (LPARAM) 0);
+
+ if (ctx) {
+ khui_context_set_indirect(&save);
+ }
+}
+
+KHMEXP khui_menu_def * KHMAPI
+khui_menu_dup(khui_menu_def * src)
+{
+ khui_menu_def * d;
+ size_t i;
+ size_t n;
+
+ EnterCriticalSection(&cs_actions);
+
+ d = khui_menu_create(src->cmd);
+
+ if (!(src->state & KHUI_MENUSTATE_ALLOCD))
+ n = khui_action_list_length(src->items);
+ else
+ n = src->n_items;
+
+ for (i=0; i<n; i++) {
+ if (src->items[i].flags & KHUI_ACTIONREF_PACTION) {
+ khui_menu_insert_paction(d, -1, src->items[i].p_action, src->items[i].flags);
+ } else {
+ khui_menu_insert_action(d, -1, src->items[i].action, 0);
+ }
+ }
+
+ LeaveCriticalSection(&cs_actions);
+
+ return d;
+}
+
+KHMEXP void KHMAPI
+khui_menu_delete(khui_menu_def * d)
+{
+ int i;
+
+ /* non-allocated menus are assumed to have no pointers to other
+ allocated blocks */
+ if(!(d->state & KHUI_MENUSTATE_ALLOCD)) {
+ /* we shouldn't have tried to delete a constant menu */
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ return;
+ }
+
+ EnterCriticalSection(&cs_actions);
+
+ for (i=0; i < khui_n_cust_menus; i++) {
+ if (khui_cust_menus[i] == d) {
+ khui_cust_menus[i] = NULL;
+ break;
+ }
+ }
+
+ for(i=0; i< (int) d->n_items; i++) {
+ if(d->items[i].flags & KHUI_ACTIONREF_FREE_PACTION)
+ PFREE(d->items[i].p_action);
+ }
+
+ if(d->items)
+ PFREE(d->items);
+ PFREE(d);
+
+ LeaveCriticalSection(&cs_actions);
+}
+
+static void
+menu_assert_size(khui_menu_def * d, size_t n)
+{
+
+ assert(d->state & KHUI_MENUSTATE_ALLOCD);
+
+ if(n > (int) d->nc_items) {
+ khui_action_ref * ni;
+
+ d->nc_items = UBOUNDSS(n, MENU_NC_ITEMS, MENU_NC_ITEMS);
+ ni = PMALLOC(sizeof(*(d->items)) * d->nc_items);
+ memcpy(ni, d->items, sizeof(*(d->items)) * d->n_items);
+ PFREE(d->items);
+ d->items = ni;
+ }
+}
+
+static void
+menu_const_to_allocd(khui_menu_def * d)
+{
+ khui_action_ref * olist;
+ khui_action_ref * nlist;
+ khm_size n;
+
+ assert(!(d->state & KHUI_MENUSTATE_ALLOCD));
+
+ olist = d->items;
+ n = khui_action_list_length(d->items);
+
+ d->nc_items = UBOUNDSS(n, MENU_NC_ITEMS, MENU_NC_ITEMS);
+ nlist = PMALLOC(sizeof(d->items[0]) * d->nc_items);
+ memcpy(nlist, olist, sizeof(d->items[0]) * n);
+
+ d->items = nlist;
+ d->n_items = n;
+ d->state |= KHUI_MENUSTATE_ALLOCD;
+}
+
+KHMEXP void KHMAPI
+khui_menu_insert_action(khui_menu_def * d, khm_size idx, khm_int32 action, khm_int32 flags)
+{
+ khm_size i;
+
+ EnterCriticalSection(&cs_actions);
+
+ if (!(d->state & KHUI_MENUSTATE_ALLOCD))
+ menu_const_to_allocd(d);
+
+ assert(d->state & KHUI_MENUSTATE_ALLOCD);
+ assert(action == KHUI_MENU_SEP || action > 0);
+
+ if (idx < 0 || idx > d->n_items)
+ idx = d->n_items;
+
+ menu_assert_size(d, d->n_items + 1);
+
+ if (idx < d->n_items) {
+ memmove(&d->items[idx + 1], &d->items[idx], (d->n_items - idx) * sizeof(d->items[0]));
+ }
+
+ d->items[idx].flags = flags;
+ d->items[idx].action = action;
+ if (action == KHUI_MENU_SEP)
+ d->items[idx].flags |= KHUI_ACTIONREF_SEP;
+
+ d->n_items++;
+
+ /* only one action is allowed to have the KHUI_ACTIONREF_DEFAULT
+ flag */
+ if (flags & KHUI_ACTIONREF_DEFAULT) {
+ for (i=0; i < d->n_items; i++) {
+ if (i != idx && (d->items[i].flags & KHUI_ACTIONREF_DEFAULT))
+ d->items[i].flags &= ~KHUI_ACTIONREF_DEFAULT;
+ }
+ }
+
+ LeaveCriticalSection(&cs_actions);
+}
+
+KHMEXP void KHMAPI
+khui_menu_insert_paction(khui_menu_def * d, khm_size idx, khui_action * paction, int flags)
+{
+ khm_size i;
+
+ if (paction == NULL)
+ return;
+
+ EnterCriticalSection(&cs_actions);
+
+ if (!(d->state & KHUI_MENUSTATE_ALLOCD))
+ menu_const_to_allocd(d);
+
+ assert(d->state & KHUI_MENUSTATE_ALLOCD);
+
+ if (idx < 0 || idx > d->n_items)
+ idx = d->n_items;
+
+ menu_assert_size(d, d->n_items + 1);
+
+ if (idx < d->n_items) {
+ memmove(&d->items[idx + 1], &d->items[idx], (d->n_items - idx) * sizeof(d->items[0]));
+ }
+
+ d->items[idx].flags = flags | KHUI_ACTIONREF_PACTION;
+ d->items[idx].p_action = paction;
+
+ d->n_items++;
+
+ /* only one action is allowed to have the KHUI_ACTIONREF_DEFAULT
+ flag */
+ if (flags & KHUI_ACTIONREF_DEFAULT) {
+ for (i=0; i < d->n_items; i++) {
+ if (i != idx && (d->items[i].flags & KHUI_ACTIONREF_DEFAULT))
+ d->items[i].flags &= ~KHUI_ACTIONREF_DEFAULT;
+ }
+ }
+
+ LeaveCriticalSection(&cs_actions);
+}
+
+KHMEXP void KHMAPI
+khui_menu_remove_action(khui_menu_def * d, khm_size idx) {
+
+ EnterCriticalSection(&cs_actions);
+
+ if (!(d->state & KHUI_MENUSTATE_ALLOCD))
+ menu_const_to_allocd(d);
+
+ assert(d->state & KHUI_MENUSTATE_ALLOCD);
+
+ if (idx >= 0 && idx < d->n_items) {
+
+ if (idx < d->n_items - 1) {
+ memmove(&d->items[idx], &d->items[idx + 1],
+ ((d->n_items - 1) - idx) * sizeof(d->items[0]));
+ }
+
+ d->n_items--;
+
+ }
+
+ LeaveCriticalSection(&cs_actions);
+}
+
+KHMEXP khm_size KHMAPI
+khui_menu_get_size(khui_menu_def * d) {
+
+ khm_size size;
+
+ EnterCriticalSection(&cs_actions);
+
+ if (d->state & KHUI_MENUSTATE_ALLOCD)
+ size = d->n_items;
+ else
+ size = khui_action_list_length(d->items);
+
+ LeaveCriticalSection(&cs_actions);
+
+ return size;
+}
+
+KHMEXP khui_action_ref *
+khui_menu_get_action(khui_menu_def * d, khm_size idx) {
+
+ khui_action_ref * act = NULL;
+ khm_size n;
+
+ EnterCriticalSection(&cs_actions);
+
+ if (d->state & KHUI_MENUSTATE_ALLOCD)
+ n = d->n_items;
+ else
+ n = khui_action_list_length(d->items);
+
+ if (idx < 0 || idx >= n)
+ act = NULL;
+ else
+ act = &d->items[idx];
+
+ LeaveCriticalSection(&cs_actions);
+
+ return act;
+}
+
+KHMEXP khui_menu_def * KHMAPI
+khui_find_menu(khm_int32 id) {
+ khui_menu_def * d;
+ int i;
+
+ if (id < KHUI_USERACTION_BASE) {
+
+ /* the list of system menus are considered immutable. */
+
+ d = khui_all_menus;
+ for(i=0;i<khui_n_all_menus;i++) {
+ if(id == d[i].cmd)
+ return &d[i];
+ }
+
+ return NULL;
+ } else {
+ d = NULL;
+
+ EnterCriticalSection(&cs_actions);
+ for (i=0; i < khui_n_cust_menus; i++) {
+ if (khui_cust_menus[i] &&
+ khui_cust_menus[i]->cmd == id) {
+ d = khui_cust_menus[i];
+ break;
+ }
+ }
+ LeaveCriticalSection(&cs_actions);
+
+ return d;
+ }
+}
+
+KHMEXP khui_action * KHMAPI
+khui_find_action(khm_int32 id) {
+ khui_action * act;
+ int i;
+
+ act = khui_actions;
+ for(i=0;i<khui_n_actions;i++) {
+ if(act[i].cmd == id)
+ return &act[i];
+ }
+
+ act = NULL;
+
+ EnterCriticalSection(&cs_actions);
+ if (id >= KHUI_USERACTION_BASE &&
+ (id - KHUI_USERACTION_BASE) < khui_n_cust_actions) {
+ act = khui_cust_actions[id - KHUI_USERACTION_BASE];
+#ifdef DEBUG
+ assert(!act || act->cmd == id);
+#endif
+ if (act && (act->state & KHUI_ACTIONSTATE_DELETED))
+ act = NULL;
+ }
+ LeaveCriticalSection(&cs_actions);
+
+ return act;
+}
+
+KHMEXP khui_action * KHMAPI
+khui_find_named_action(const wchar_t * name) {
+ int i;
+ khui_action * act;
+ khui_action ** pact;
+
+ if(!name)
+ return NULL;
+
+ act = khui_actions;
+ for(i=0;i<khui_n_actions;i++) {
+ if(!act[i].name)
+ continue;
+ if(!wcscmp(act[i].name, name))
+ return &act[i];
+ }
+
+ act = NULL;
+
+ EnterCriticalSection(&cs_actions);
+
+ pact = khui_cust_actions;
+ for(i=0;i<khui_n_cust_actions;i++) {
+ if(!pact[i] || !pact[i]->name)
+ continue;
+
+ if(!wcscmp(pact[i]->name, name)) {
+
+ if (!(pact[i]->state & KHUI_ACTIONSTATE_DELETED)) {
+ act = pact[i];
+ }
+ break;
+ }
+ }
+
+ LeaveCriticalSection(&cs_actions);
+
+ return act;
+}
+
+KHMEXP size_t KHMAPI
+khui_action_list_length(khui_action_ref * ref) {
+ size_t c = 0;
+
+ EnterCriticalSection(&cs_actions);
+
+ while(ref && ref->action != KHUI_MENU_END &&
+ !(ref->flags & KHUI_ACTIONREF_END)) {
+ c++;
+ ref++;
+ }
+
+ LeaveCriticalSection(&cs_actions);
+
+ return c;
+}
+
+KHMEXP void KHMAPI
+khui_check_radio_action(khui_menu_def * d, khm_int32 cmd)
+{
+ khui_action_ref * r;
+ khui_action * act;
+
+ EnterCriticalSection(&cs_actions);
+
+ r = d->items;
+ while(r && r->action != KHUI_MENU_END &&
+ (!(d->state & KHUI_MENUSTATE_ALLOCD) || (r - d->items) < (int) d->n_items)) {
+ if(r->flags & KHUI_ACTIONREF_PACTION) {
+ act = r->p_action;
+ } else {
+ act = khui_find_action(r->action);
+ }
+
+ if(act) {
+ if(act->cmd == cmd)
+ act->state |= KHUI_ACTIONSTATE_CHECKED;
+ else
+ act->state &= ~KHUI_ACTIONSTATE_CHECKED;
+ }
+ r++;
+ }
+
+ LeaveCriticalSection(&cs_actions);
+
+ kmq_post_message(KMSG_ACT, KMSG_ACT_CHECK, 0, 0);
+}
+
+KHMEXP void KHMAPI
+khui_check_action(khm_int32 cmd, khm_boolean check) {
+ khui_action * act;
+
+ act = khui_find_action(cmd);
+ if (!act)
+ return;
+
+ EnterCriticalSection(&cs_actions);
+
+ if (check && !(act->state & KHUI_ACTIONSTATE_CHECKED))
+ act->state |= KHUI_ACTIONSTATE_CHECKED;
+ else if (!check && (act->state & KHUI_ACTIONSTATE_CHECKED))
+ act->state &= ~KHUI_ACTIONSTATE_CHECKED;
+ else {
+ LeaveCriticalSection(&cs_actions);
+ return;
+ }
+
+ LeaveCriticalSection(&cs_actions);
+
+ kmq_post_message(KMSG_ACT, KMSG_ACT_CHECK, 0, 0);
+}
+
+KHMEXP void KHMAPI
+khui_enable_actions(khui_menu_def * d, khm_boolean enable)
+{
+ khui_action_ref * r;
+ int delta = FALSE;
+ khui_action * act;
+
+ EnterCriticalSection(&cs_actions);
+
+ r = d->items;
+ while(r && r->action != KHUI_MENU_END &&
+ (!(d->state & KHUI_MENUSTATE_ALLOCD) || (r - d->items) < (int) d->n_items)) {
+ if(r->flags & KHUI_ACTIONREF_PACTION) {
+ act = r->p_action;
+ } else {
+ act = khui_find_action(r->action);
+ }
+
+ if(act) {
+ int old_state = act->state;
+
+ if(enable)
+ act->state &= ~KHUI_ACTIONSTATE_DISABLED;
+ else
+ act->state |= KHUI_ACTIONSTATE_DISABLED;
+
+ if(old_state != act->state)
+ delta = TRUE;
+ }
+ r++;
+ }
+
+ LeaveCriticalSection(&cs_actions);
+
+ if(delta) {
+ kmq_post_message(KMSG_ACT, KMSG_ACT_ENABLE, 0, 0);
+ }
+}
+
+KHMEXP void KHMAPI
+khui_enable_action(khm_int32 cmd, khm_boolean enable) {
+ khui_action * act;
+
+ act = khui_find_action(cmd);
+ if (!act)
+ return;
+
+ EnterCriticalSection(&cs_actions);
+
+ if (enable && (act->state & KHUI_ACTIONSTATE_DISABLED)) {
+ act->state &= ~KHUI_ACTIONSTATE_DISABLED;
+ } else if (!enable && !(act->state & KHUI_ACTIONSTATE_DISABLED)) {
+ act->state |= KHUI_ACTIONSTATE_DISABLED;
+ } else {
+ LeaveCriticalSection(&cs_actions);
+ return;
+ }
+
+ LeaveCriticalSection(&cs_actions);
+
+ kmq_post_message(KMSG_ACT, KMSG_ACT_ENABLE, 0, 0);
+}
+
+KHMEXP HACCEL KHMAPI
+khui_create_global_accel_table(void) {
+ int i;
+ ACCEL * accels;
+ HACCEL ha;
+
+ accels = PMALLOC(sizeof(ACCEL) * khui_n_accel_global);
+ for(i=0;i<khui_n_accel_global;i++) {
+ accels[i].cmd = khui_accel_global[i].cmd;
+ accels[i].fVirt = khui_accel_global[i].mod;
+ accels[i].key = khui_accel_global[i].key;
+ }
+
+ ha = CreateAcceleratorTable(accels, khui_n_accel_global);
+
+ PFREE(accels);
+
+ return ha;
+}
+
+KHMEXP khm_boolean KHMAPI
+khui_get_cmd_accel_string(khm_int32 cmd,
+ wchar_t * buf,
+ khm_size bufsiz) {
+ int i;
+ khui_accel_def * def;
+
+ /* should at least hold 2 characters */
+ if(bufsiz < sizeof(wchar_t) * 2)
+ return FALSE;
+
+ buf[0] = L'\0';
+
+ for(i=0;i<khui_n_accel_global;i++) {
+ if(khui_accel_global[i].cmd == cmd)
+ break;
+ }
+
+ if(i==khui_n_accel_global)
+ return FALSE;
+
+ def = &khui_accel_global[i];
+
+ if(def->mod & FALT) {
+ if(FAILED(StringCbCat(buf, bufsiz, L"Alt+")))
+ return FALSE;
+ }
+
+
+ if(def->mod & FCONTROL) {
+ if(FAILED(StringCbCat(buf, bufsiz, L"Ctrl+")))
+ return FALSE;
+ }
+
+ if(def->mod & FSHIFT) {
+ if(FAILED(StringCbCat(buf, bufsiz, L"Shift+")))
+ return FALSE;
+ }
+
+ if(def->mod & FVIRTKEY) {
+ wchar_t mbuf[6];
+ wchar_t * ap = NULL;
+ switch(def->key) {
+ case VK_TAB:
+ ap = L"Tab";
+ break;
+
+ case VK_ESCAPE:
+ ap = L"Esc";
+ break;
+
+ case VK_RETURN:
+ ap = L"Enter";
+ break;
+
+ case VK_F1:
+ ap = L"F1";
+ break;
+
+ case VK_F2:
+ ap = L"F2";
+ break;
+
+ case VK_F3:
+ ap = L"F3";
+ break;
+
+ case VK_F4:
+ ap = L"F4";
+ break;
+
+ case VK_F5:
+ ap = L"F5";
+ break;
+
+ case VK_F6:
+ ap = L"F6";
+ break;
+
+ case VK_F7:
+ ap = L"F7";
+ break;
+
+ case VK_F8:
+ ap = L"F8";
+ break;
+
+ case VK_F9:
+ ap = L"F9";
+ break;
+
+ case VK_F10:
+ ap = L"F10";
+ break;
+
+ case VK_F11:
+ ap = L"F11";
+ break;
+
+ case VK_F12:
+ ap = L"F12";
+ break;
+
+ case VK_DELETE:
+ ap = L"Del";
+ break;
+
+ default:
+ if((def->key >= '0' &&
+ def->key <= '9') ||
+ (def->key >= 'A' &&
+ def->key <= 'Z')) {
+ ap = mbuf;
+ mbuf[0] = (wchar_t) def->key;
+ mbuf[1] = L'\0';
+ }
+ }
+ if(ap) {
+ if(FAILED(StringCbCat(buf, bufsiz, ap)))
+ return FALSE;
+ }
+ else {
+ if(FAILED(StringCbCat(buf, bufsiz,L"???")))
+ return FALSE;
+ }
+
+ } else {
+ wchar_t mbuf[2];
+
+ mbuf[0] = def->key;
+ mbuf[1] = L'\0';
+
+ if(FAILED(StringCbCat(buf, bufsiz, mbuf)))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/******************************************/
+/* contexts */
+
+#define KHUI_ACTION_CONTEXT_MAGIC 0x39c49db5
+
+static khm_int32 KHMAPI
+khuiint_filter_selected(khm_handle cred,
+ khm_int32 vflags,
+ void * rock) {
+ khm_int32 flags;
+ if (KHM_SUCCEEDED(kcdb_cred_get_flags(cred, &flags)) &&
+ (flags & KCDB_CRED_FLAG_SELECTED))
+ return TRUE;
+ else
+ return FALSE;
+}
+
+static void
+khuiint_context_release(khui_action_context * ctx) {
+ ctx->scope = KHUI_SCOPE_NONE;
+ if (ctx->identity)
+ kcdb_identity_release(ctx->identity);
+ ctx->identity = NULL;
+ ctx->cred_type = KCDB_CREDTYPE_INVALID;
+ if (ctx->cred)
+ kcdb_cred_release(ctx->cred);
+ ctx->cred = NULL;
+ ctx->n_headers = 0;
+ if (ctx->credset)
+ kcdb_credset_flush(ctx->credset);
+ ctx->n_sel_creds = 0;
+ ctx->int_cb_used = 0;
+ ctx->vparam = NULL;
+ ctx->cb_vparam = 0;
+}
+
+static void
+khuiint_copy_context(khui_action_context * ctxdest,
+ const khui_action_context * ctxsrc)
+{
+ ctxdest->scope = ctxsrc->scope;
+
+ if (ctxsrc->scope == KHUI_SCOPE_IDENT) {
+ ctxdest->identity = ctxsrc->identity;
+ kcdb_identity_hold(ctxsrc->identity);
+ } else if (ctxsrc->scope == KHUI_SCOPE_CREDTYPE) {
+ ctxdest->identity = ctxsrc->identity;
+ ctxdest->cred_type = ctxsrc->cred_type;
+ if (ctxsrc->identity != NULL)
+ kcdb_identity_hold(ctxsrc->identity);
+ } else if (ctxsrc->scope == KHUI_SCOPE_CRED) {
+ kcdb_cred_get_identity(ctxsrc->cred, &ctxdest->identity);
+ kcdb_cred_get_type(ctxsrc->cred, &ctxdest->cred_type);
+ ctxdest->cred = ctxsrc->cred;
+ kcdb_cred_hold(ctxsrc->cred);
+ } else if (ctxsrc->scope == KHUI_SCOPE_GROUP) {
+ khm_size cb_total;
+ int i;
+
+ ctxdest->n_headers = ctxsrc->n_headers;
+ cb_total = 0;
+ for (i=0; i < (int) ctxsrc->n_headers; i++) {
+ cb_total += UBOUND32(ctxsrc->headers[i].cb_data);
+ }
+
+ if (ctxdest->int_cb_buf < cb_total) {
+
+ if (ctxdest->int_buf)
+ PFREE(ctxdest->int_buf);
+
+ ctxdest->int_cb_buf = cb_total;
+ ctxdest->int_buf = PMALLOC(cb_total);
+ }
+
+#ifdef DEBUG
+ assert(ctxdest->int_buf || cb_total == 0);
+#endif
+ ctxdest->int_cb_used = 0;
+
+ for (i=0; i < (int) ctxsrc->n_headers; i++) {
+ ctxdest->headers[i].attr_id = ctxsrc->headers[i].attr_id;
+ ctxdest->headers[i].cb_data = ctxsrc->headers[i].cb_data;
+ if (ctxsrc->headers[i].cb_data > 0) {
+ ctxdest->headers[i].data =
+ BYTEOFFSET(ctxdest->int_buf,
+ ctxdest->int_cb_used);
+ memcpy(ctxdest->headers[i].data,
+ ctxsrc->headers[i].data,
+ ctxsrc->headers[i].cb_data);
+ ctxdest->int_cb_used +=
+ UBOUND32(ctxsrc->headers[i].cb_data);
+ } else {
+ ctxdest->headers[i].data = NULL;
+ }
+ }
+ }
+
+ if (ctxsrc->credset) {
+
+ if (ctxdest->credset == NULL)
+ kcdb_credset_create(&ctxdest->credset);
+#ifdef DEBUG
+ assert(ctxdest->credset != NULL);
+#endif
+
+ kcdb_credset_flush(ctxdest->credset);
+
+ kcdb_credset_extract_filtered(ctxdest->credset,
+ ctxsrc->credset,
+ khuiint_filter_selected,
+ NULL);
+
+ kcdb_credset_get_size(ctxdest->credset,
+ &ctxdest->n_sel_creds);
+ } else {
+ if (ctxdest->credset != NULL)
+ kcdb_credset_flush(ctxdest->credset);
+ ctxdest->n_sel_creds = 0;
+ }
+
+ /* For now, we simply transfer the vparam buffer into the new
+ context. If we are copying, we also need to modify
+ khui_context_release() to free the allocated buffer */
+#if 0
+ if (ctxsrc->vparam && ctxsrc->cb_vparam) {
+ ctxdest->vparam = PMALLOC(ctxsrc->cb_vparam);
+#ifdef DEBUG
+ assert(ctxdest->vparam);
+#endif
+ memcpy(ctxdest->vparam, ctxsrc->vparam, ctxsrc->cb_vparam);
+ ctxdest->cb_vparam = ctxsrc->cb_vparam;
+ } else {
+#endif
+ ctxdest->vparam = ctxsrc->vparam;
+ ctxdest->cb_vparam = ctxsrc->cb_vparam;
+#if 0
+ }
+#endif
+}
+
+static void
+khuiint_context_init(khui_action_context * ctx) {
+ ctx->magic = KHUI_ACTION_CONTEXT_MAGIC;
+ ctx->scope = KHUI_SCOPE_NONE;
+ ctx->identity = NULL;
+ ctx->cred_type = KCDB_CREDTYPE_INVALID;
+ ctx->cred = NULL;
+ ZeroMemory(ctx->headers, sizeof(ctx->headers));
+ ctx->n_headers = 0;
+ ctx->credset = NULL;
+ ctx->n_sel_creds = 0;
+ ctx->int_buf = NULL;
+ ctx->int_cb_buf = 0;
+ ctx->int_cb_used = 0;
+ ctx->vparam = NULL;
+ ctx->cb_vparam = 0;
+}
+
+khui_action_context khui_ctx = {
+ KHUI_ACTION_CONTEXT_MAGIC,
+ KHUI_SCOPE_NONE,
+ NULL,
+ KCDB_CREDTYPE_INVALID,
+ NULL,
+ {
+ {KCDB_ATTR_INVALID,NULL,0},
+ {KCDB_ATTR_INVALID,NULL,0},
+ {KCDB_ATTR_INVALID,NULL,0},
+ {KCDB_ATTR_INVALID,NULL,0},
+ {KCDB_ATTR_INVALID,NULL,0},
+ {KCDB_ATTR_INVALID,NULL,0}
+ },
+ 0,
+ NULL,
+ 0,
+ NULL,
+ 0,
+ 0,
+ NULL,
+ 0};
+
+khm_int32 KHMAPI
+set_cred_select_flag(khm_handle cred, void * rock) {
+ kcdb_cred_set_flags(cred, KCDB_CRED_FLAG_SELECTED,
+ KCDB_CRED_FLAG_SELECTED);
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP void KHMAPI
+khui_context_create(khui_action_context * ctx,
+ khui_scope scope,
+ khm_handle identity,
+ khm_int32 cred_type,
+ khm_handle cred)
+{
+ khui_action_context tctx;
+
+ khuiint_context_init(&tctx);
+ khuiint_context_init(ctx);
+
+ tctx.scope = scope;
+ tctx.identity = identity;
+ tctx.cred_type = cred_type;
+ tctx.cred = cred;
+
+ /* fill up the credset based on the scope */
+ if (scope != KHUI_SCOPE_NONE) {
+ if (tctx.credset == NULL)
+ kcdb_credset_create(&tctx.credset);
+ else
+ kcdb_credset_flush(tctx.credset);
+
+ if (scope == KHUI_SCOPE_IDENT) {
+ kcdb_credset_extract(tctx.credset,
+ NULL,
+ tctx.identity,
+ KCDB_CREDTYPE_INVALID);
+ } else if (scope == KHUI_SCOPE_CREDTYPE) {
+ kcdb_credset_extract(tctx.credset,
+ NULL,
+ tctx.identity,
+ tctx.cred_type);
+ } else if (scope == KHUI_SCOPE_CRED) {
+ khm_handle dupcred = NULL;
+ kcdb_cred_dup(cred, &dupcred);
+
+ kcdb_credset_add_cred(tctx.credset, dupcred, -1);
+ } else {
+#ifdef DEBUG
+ /* KHUI_SCOPE_GROUP is not used with
+ khui_context_create() */
+ assert(FALSE);
+#endif
+ }
+
+ kcdb_credset_apply(tctx.credset, set_cred_select_flag,
+ NULL);
+
+ kcdb_credset_seal(tctx.credset);
+ }
+
+ khuiint_copy_context(ctx, &tctx);
+}
+
+KHMEXP void KHMAPI
+khui_context_set(khui_scope scope,
+ khm_handle identity,
+ khm_int32 cred_type,
+ khm_handle cred,
+ khui_header *headers,
+ khm_size n_headers,
+ khm_handle cs_src) {
+
+ khui_context_set_ex(scope,
+ identity,
+ cred_type,
+ cred,
+ headers,
+ n_headers,
+ cs_src,
+ NULL,
+ 0);
+}
+
+KHMEXP void KHMAPI
+khui_context_set_ex(khui_scope scope,
+ khm_handle identity,
+ khm_int32 cred_type,
+ khm_handle cred,
+ khui_header *headers,
+ khm_size n_headers,
+ khm_handle cs_src,
+ void * vparam,
+ khm_size cb_vparam)
+{
+ khui_action_context tctx;
+
+ EnterCriticalSection(&cs_actions);
+
+ khuiint_context_release(&khui_ctx);
+
+ khuiint_context_init(&tctx);
+
+ tctx.scope = scope;
+ tctx.identity = identity;
+ tctx.cred_type = cred_type;
+ tctx.cred = cred;
+ if (headers) {
+ tctx.n_headers = n_headers;
+ memcpy(tctx.headers,
+ headers,
+ sizeof(*headers) * n_headers);
+ } else {
+ tctx.n_headers = 0;
+ }
+ tctx.credset = cs_src;
+ tctx.n_sel_creds = 0; /* ignored */
+ tctx.vparam = vparam;
+ tctx.cb_vparam = cb_vparam;
+ tctx.int_buf = NULL;
+ tctx.int_cb_buf = 0;
+ tctx.int_cb_used = 0;
+
+ khuiint_copy_context(&khui_ctx, &tctx);
+
+ khui_context_refresh();
+
+ LeaveCriticalSection(&cs_actions);
+}
+
+KHMEXP void KHMAPI
+khui_context_set_indirect(khui_action_context * ctx)
+{
+ EnterCriticalSection(&cs_actions);
+
+ khuiint_context_release(&khui_ctx);
+
+ khuiint_copy_context(&khui_ctx, ctx);
+
+ khui_context_refresh();
+
+ LeaveCriticalSection(&cs_actions);
+}
+
+KHMEXP void KHMAPI
+khui_context_refresh(void) {
+ khm_int32 flags;
+
+ EnterCriticalSection(&cs_actions);
+ if (khui_ctx.identity) {
+ /* an identity is selected */
+
+ if (KHM_SUCCEEDED(kcdb_identity_get_flags(khui_ctx.identity,
+ &flags)) &&
+ (flags & KCDB_IDENT_FLAG_DEFAULT)) {
+ khui_check_action(KHUI_ACTION_SET_DEF_ID, TRUE);
+ khui_enable_action(KHUI_ACTION_SET_DEF_ID, FALSE);
+ } else {
+ khui_check_action(KHUI_ACTION_SET_DEF_ID, FALSE);
+ khui_enable_action(KHUI_ACTION_SET_DEF_ID, TRUE);
+ }
+ } else {
+ khui_check_action(KHUI_ACTION_SET_DEF_ID, FALSE);
+ khui_enable_action(KHUI_ACTION_SET_DEF_ID, FALSE);
+ }
+
+ if (khui_ctx.scope != KHUI_SCOPE_NONE) {
+ khui_enable_action(KHUI_ACTION_PROPERTIES, TRUE);
+ } else {
+ khui_enable_action(KHUI_ACTION_PROPERTIES, FALSE);
+ }
+
+ LeaveCriticalSection(&cs_actions);
+
+ kmq_post_message(KMSG_ACT, KMSG_ACT_REFRESH, 0, 0);
+}
+
+KHMEXP void KHMAPI
+khui_context_get(khui_action_context * ctx)
+{
+ EnterCriticalSection(&cs_actions);
+
+ khuiint_context_init(ctx);
+ khuiint_copy_context(ctx, &khui_ctx);
+
+ if (ctx->credset) {
+ kcdb_credset_seal(ctx->credset);
+ }
+
+ LeaveCriticalSection(&cs_actions);
+}
+
+KHMEXP void KHMAPI
+khui_context_release(khui_action_context * ctx)
+{
+#ifdef DEBUG
+ assert(ctx->magic == KHUI_ACTION_CONTEXT_MAGIC);
+#endif
+
+ khuiint_context_release(ctx);
+ if (ctx->credset) {
+ kcdb_credset_unseal(ctx->credset);
+ kcdb_credset_delete(ctx->credset);
+ }
+ ctx->credset = NULL;
+ if (ctx->int_buf)
+ PFREE(ctx->int_buf);
+ ctx->int_buf = NULL;
+#if 0
+ if (ctx->vparam && ctx->cb_vparam > 0) {
+ PFREE(ctx->vparam);
+ ctx->vparam = NULL;
+ }
+ ctx->cb_vparam = 0;
+#else
+ ctx->vparam = 0;
+ ctx->cb_vparam = 0;
+#endif
+}
+
+KHMEXP void KHMAPI
+khui_context_reset(void)
+{
+ EnterCriticalSection(&cs_actions);
+
+ khuiint_context_release(&khui_ctx);
+
+ khui_context_refresh();
+
+ LeaveCriticalSection(&cs_actions);
+}
+
+KHMEXP khm_int32 KHMAPI
+khui_context_cursor_filter(khm_handle cred,
+ khm_int32 flags,
+ void * rock) {
+ khui_action_context * ctx = (khui_action_context *) rock;
+ khm_int32 rv;
+
+ if (ctx->scope == KHUI_SCOPE_NONE)
+ return 0;
+ else if (ctx->scope == KHUI_SCOPE_IDENT) {
+ khm_handle c_ident;
+
+ if (KHM_FAILED(kcdb_cred_get_identity(cred, &c_ident)))
+ return 0;
+
+ rv = (c_ident == ctx->identity);
+
+ kcdb_identity_release(c_ident);
+
+ return rv;
+ } else if (ctx->scope == KHUI_SCOPE_CREDTYPE) {
+ khm_handle c_ident;
+ khm_int32 c_type;
+
+ if (KHM_FAILED(kcdb_cred_get_type(cred, &c_type)) ||
+ c_type != ctx->cred_type)
+ return 0;
+
+ if (ctx->identity == NULL)
+ return 1;
+
+ if (KHM_FAILED(kcdb_cred_get_identity(cred, &c_ident)))
+ return 0;
+
+ rv = (c_ident == ctx->identity);
+
+ kcdb_identity_release(c_ident);
+
+ return rv;
+ } else if (ctx->scope == KHUI_SCOPE_CRED) {
+ return kcdb_creds_is_equal(cred, ctx->cred);
+ } else if (ctx->scope == KHUI_SCOPE_GROUP) {
+ int i;
+
+ rv = 1;
+
+ for (i=0; i < (int) ctx->n_headers && rv; i++) {
+ kcdb_attrib * pattr;
+ kcdb_type * ptype;
+ DWORD buffer[1024]; /* 4096 bytes */
+ khm_size cb;
+
+ if (kcdb_cred_get_attr(cred, ctx->headers[i].attr_id,
+ NULL,
+ NULL,
+ &cb) != KHM_ERROR_TOO_LONG) {
+ /* the header doesn't exist anyway */
+ rv = (ctx->headers[i].cb_data == 0);
+ continue;
+ }
+#ifdef DEBUG
+ assert(cb <= sizeof(buffer));
+#endif
+ cb = sizeof(buffer);
+
+ if (KHM_FAILED(kcdb_cred_get_attr(cred,
+ ctx->headers[i].attr_id,
+ NULL,
+ (void *) buffer,
+ &cb))) {
+ rv = 0;
+ continue;
+ }
+
+ if (KHM_FAILED(kcdb_attrib_get_info(ctx->headers[i].attr_id,
+ &pattr))) {
+ rv = 0;
+ continue;
+ }
+
+ if (KHM_FAILED(kcdb_type_get_info(pattr->type, &ptype))) {
+ rv = 0;
+ kcdb_attrib_release_info(pattr);
+ continue;
+ }
+
+ if ((*ptype->comp)(ctx->headers[i].data,
+ ctx->headers[i].cb_data,
+ (void *) buffer,
+ cb) != 0)
+ rv = 1;
+
+ kcdb_type_release_info(ptype);
+ kcdb_attrib_release_info(pattr);
+ }
+
+ return rv;
+ } else
+ return 0;
+}
diff --git a/src/windows/identity/uilib/alert.c b/src/windows/identity/uilib/alert.c
index e398690e92..376eab6e1c 100644
--- a/src/windows/identity/uilib/alert.c
+++ b/src/windows/identity/uilib/alert.c
@@ -1,437 +1,437 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<khuidefs.h>
-#include<utils.h>
-#include<intalert.h>
-#include<assert.h>
-
-#include<strsafe.h>
-
-/***********************************************************************
- Alerter
-***********************************************************************/
-
-khui_alert * kh_alerts = NULL;
-CRITICAL_SECTION cs_alerts;
-
-void
-alert_init(void)
-{
- InitializeCriticalSection(&cs_alerts);
-}
-
-void
-alert_exit(void)
-{
- DeleteCriticalSection(&cs_alerts);
-}
-
-KHMEXP khm_int32 KHMAPI
-khui_alert_create_empty(khui_alert ** result)
-{
- khui_alert * a;
-
- a = PMALLOC(sizeof(*a));
- ZeroMemory(a, sizeof(*a));
-
- a->magic = KHUI_ALERT_MAGIC;
-
- /* set defaults */
- a->severity = KHERR_INFO;
- a->flags = KHUI_ALERT_FLAG_FREE_STRUCT;
- a->alert_type = KHUI_ALERTTYPE_NONE;
- khui_context_create(&a->ctx, KHUI_SCOPE_NONE,
- NULL, KCDB_CREDTYPE_INVALID,
- NULL);
-
- khui_alert_hold(a);
- EnterCriticalSection(&cs_alerts);
- LPUSH(&kh_alerts, a);
- LeaveCriticalSection(&cs_alerts);
-
- *result = a;
-
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP khm_int32 KHMAPI
-khui_alert_create_simple(const wchar_t * title,
- const wchar_t * message,
- khm_int32 severity,
- khui_alert ** result)
-{
- khui_alert * a;
-
- khui_alert_create_empty(&a);
- khui_alert_set_title(a, title);
- khui_alert_set_message(a, message);
- khui_alert_set_severity(a, severity);
-
- *result = a;
-
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP khm_int32 KHMAPI
-khui_alert_set_title(khui_alert * alert, const wchar_t * title)
-{
- size_t cb = 0;
-
- assert(alert->magic == KHUI_ALERT_MAGIC);
-
- if(title) {
- if(FAILED(StringCbLength(title,
- KHUI_MAXCB_TITLE,
- &cb))) {
- return KHM_ERROR_INVALID_PARAM;
- }
- cb += sizeof(wchar_t);
- }
-
- EnterCriticalSection(&cs_alerts);
- if(alert->title && (alert->flags & KHUI_ALERT_FLAG_FREE_TITLE)) {
- PFREE(alert->title);
- alert->title = NULL;
- alert->flags &= ~KHUI_ALERT_FLAG_FREE_TITLE;
- }
- if(title) {
- alert->title = PMALLOC(cb);
- StringCbCopy(alert->title, cb, title);
- alert->flags |= KHUI_ALERT_FLAG_FREE_TITLE;
- }
- LeaveCriticalSection(&cs_alerts);
-
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP khm_int32 KHMAPI
-khui_alert_set_flags(khui_alert * alert, khm_int32 mask, khm_int32 flags)
-{
- assert(alert->magic == KHUI_ALERT_MAGIC);
-
- if (mask & ~KHUI_ALERT_FLAGMASK_RDWR)
- return KHM_ERROR_INVALID_PARAM;
-
- EnterCriticalSection(&cs_alerts);
- alert->flags =
- (alert->flags & ~mask) |
- (flags & mask);
- LeaveCriticalSection(&cs_alerts);
-
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP khm_int32 KHMAPI
-khui_alert_set_severity(khui_alert * alert, khm_int32 severity)
-{
-
- assert(alert->magic == KHUI_ALERT_MAGIC);
-
- EnterCriticalSection(&cs_alerts);
- alert->severity = severity;
- LeaveCriticalSection(&cs_alerts);
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP khm_int32 KHMAPI
-khui_alert_set_suggestion(khui_alert * alert,
- const wchar_t * suggestion) {
- size_t cb = 0;
-
- assert(alert->magic == KHUI_ALERT_MAGIC);
-
- if(suggestion) {
- if(FAILED(StringCbLength(suggestion,
- KHUI_MAXCB_MESSAGE - sizeof(wchar_t),
- &cb))) {
- return KHM_ERROR_INVALID_PARAM;
- }
- cb += sizeof(wchar_t);
- }
-
- EnterCriticalSection(&cs_alerts);
- if(alert->suggestion &&
- (alert->flags & KHUI_ALERT_FLAG_FREE_SUGGEST)) {
-
- PFREE(alert->suggestion);
- alert->suggestion = NULL;
- alert->flags &= ~KHUI_ALERT_FLAG_FREE_SUGGEST;
-
- }
-
- if(suggestion) {
- alert->suggestion = PMALLOC(cb);
- StringCbCopy(alert->suggestion, cb, suggestion);
- alert->flags |= KHUI_ALERT_FLAG_FREE_SUGGEST;
- }
- LeaveCriticalSection(&cs_alerts);
-
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP khm_int32 KHMAPI
-khui_alert_set_message(khui_alert * alert, const wchar_t * message)
-{
- size_t cb = 0;
-
- assert(alert->magic == KHUI_ALERT_MAGIC);
-
- if(message) {
- if(FAILED(StringCbLength(message,
- KHUI_MAXCB_MESSAGE - sizeof(wchar_t),
- &cb))) {
- return KHM_ERROR_INVALID_PARAM;
- }
- cb += sizeof(wchar_t);
- }
-
- EnterCriticalSection(&cs_alerts);
- if(alert->message &&
- (alert->flags & KHUI_ALERT_FLAG_FREE_MESSAGE)) {
-
- PFREE(alert->message);
- alert->flags &= ~KHUI_ALERT_FLAG_FREE_MESSAGE;
- }
-
- alert->message = NULL;
-
- if(message) {
- alert->message = PMALLOC(cb);
- StringCbCopy(alert->message, cb, message);
- alert->flags |= KHUI_ALERT_FLAG_FREE_MESSAGE;
- }
- LeaveCriticalSection(&cs_alerts);
-
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP khm_int32 KHMAPI
-khui_alert_clear_commands(khui_alert * alert)
-{
- assert(alert->magic == KHUI_ALERT_MAGIC);
-
- EnterCriticalSection(&cs_alerts);
- alert->n_alert_commands = 0;
- LeaveCriticalSection(&cs_alerts);
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP khm_int32 KHMAPI
-khui_alert_add_command(khui_alert * alert, khm_int32 command_id)
-{
- khm_int32 rv = KHM_ERROR_SUCCESS;
-
- assert(alert->magic == KHUI_ALERT_MAGIC);
-
- EnterCriticalSection(&cs_alerts);
- if(alert->n_alert_commands >= KHUI_MAX_ALERT_COMMANDS)
- rv = KHM_ERROR_NO_RESOURCES;
- else {
- alert->alert_commands[alert->n_alert_commands++] = command_id;
- }
- LeaveCriticalSection(&cs_alerts);
-
- return rv;
-}
-
-KHMEXP khm_int32 KHMAPI
-khui_alert_set_type(khui_alert * alert, khui_alert_type alert_type)
-{
- khm_int32 rv = KHM_ERROR_SUCCESS;
-
- assert(alert->magic == KHUI_ALERT_MAGIC);
-
- EnterCriticalSection(&cs_alerts);
- alert->alert_type = alert_type;
- LeaveCriticalSection(&cs_alerts);
-
- return rv;
-}
-
-KHMEXP khm_int32 KHMAPI
-khui_alert_set_ctx(khui_alert * alert,
- khui_scope scope,
- khm_handle identity,
- khm_int32 cred_type,
- khm_handle cred)
-{
- khm_int32 rv = KHM_ERROR_SUCCESS;
-
- assert(alert->magic == KHUI_ALERT_MAGIC);
-
- EnterCriticalSection(&cs_alerts);
- khui_context_release(&alert->ctx);
- khui_context_create(&alert->ctx,
- scope,
- identity,
- cred_type,
- cred);
- LeaveCriticalSection(&cs_alerts);
-
- return rv;
-}
-
-KHMEXP khm_int32 KHMAPI
-khui_alert_get_response(khui_alert * alert)
-{
- khm_int32 response = 0;
-
- assert(alert->magic == KHUI_ALERT_MAGIC);
-
- EnterCriticalSection(&cs_alerts);
- response = alert->response;
- LeaveCriticalSection(&cs_alerts);
-
- return response;
-}
-
-KHMEXP khm_int32 KHMAPI
-khui_alert_show(khui_alert * alert)
-{
- assert(alert->magic == KHUI_ALERT_MAGIC);
-
- khui_alert_hold(alert);
- /* the alert will be released when the message is processed */
- kmq_post_message(KMSG_ALERT, KMSG_ALERT_SHOW, 0, (void *) alert);
-
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP khm_int32 KHMAPI
-khui_alert_show_modal(khui_alert * alert)
-{
- khm_int32 rv;
-
- assert(alert->magic == KHUI_ALERT_MAGIC);
-
- khui_alert_hold(alert);
- rv = kmq_send_message(KMSG_ALERT, KMSG_ALERT_SHOW_MODAL, 0,
- (void *) alert);
-
- return rv;
-}
-
-KHMEXP khm_int32 KHMAPI
-khui_alert_queue(khui_alert * alert)
-{
- assert(alert->magic == KHUI_ALERT_MAGIC);
-
- khui_alert_hold(alert);
- kmq_post_message(KMSG_ALERT, KMSG_ALERT_QUEUE, 0, (void *) alert);
-
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP khm_int32 KHMAPI
-khui_alert_show_simple(const wchar_t * title,
- const wchar_t * message,
- khm_int32 severity)
-{
- khui_alert * a = NULL;
- khm_int32 rv;
-
- rv = khui_alert_create_simple(title, message, severity, &a);
-
- if(KHM_FAILED(rv))
- return rv;
-
- rv = khui_alert_show(a);
-
- khui_alert_release(a);
-
- return rv;
-}
-
-KHMEXP khm_int32 KHMAPI
-khui_alert_hold(khui_alert * alert)
-{
- assert(alert->magic == KHUI_ALERT_MAGIC);
-
- EnterCriticalSection(&cs_alerts);
- alert->refcount++;
- LeaveCriticalSection(&cs_alerts);
- return KHM_ERROR_SUCCESS;
-}
-
-/* called with cs_alert held */
-static void
-free_alert(khui_alert * alert)
-{
- assert(alert->magic == KHUI_ALERT_MAGIC);
-
- LDELETE(&kh_alerts, alert);
-
- if(alert->flags & KHUI_ALERT_FLAG_FREE_TITLE) {
- assert(alert->title);
- PFREE(alert->title);
- alert->title = NULL;
- alert->flags &= ~KHUI_ALERT_FLAG_FREE_TITLE;
- }
- if(alert->flags & KHUI_ALERT_FLAG_FREE_MESSAGE) {
- assert(alert->message);
- PFREE(alert->message);
- alert->message = NULL;
- alert->flags &= ~KHUI_ALERT_FLAG_FREE_MESSAGE;
- }
- if(alert->flags & KHUI_ALERT_FLAG_FREE_SUGGEST) {
- assert(alert->suggestion);
- PFREE(alert->suggestion);
- alert->suggestion = NULL;
- alert->flags &= ~KHUI_ALERT_FLAG_FREE_SUGGEST;
- }
-
- khui_context_release(&alert->ctx);
-
- if(alert->flags & KHUI_ALERT_FLAG_FREE_STRUCT) {
- alert->flags &= ~KHUI_ALERT_FLAG_FREE_STRUCT;
- alert->magic = 0;
- PFREE(alert);
- }
-}
-
-KHMEXP khm_int32 KHMAPI
-khui_alert_release(khui_alert * alert)
-{
- assert(alert->magic == KHUI_ALERT_MAGIC);
-
- EnterCriticalSection(&cs_alerts);
- if((--(alert->refcount)) == 0) {
- free_alert(alert);
- }
- LeaveCriticalSection(&cs_alerts);
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP void KHMAPI khui_alert_lock(khui_alert * alert)
-{
- EnterCriticalSection(&cs_alerts);
-}
-
-KHMEXP void KHMAPI khui_alert_unlock(khui_alert * alert)
-{
- LeaveCriticalSection(&cs_alerts);
-}
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<khuidefs.h>
+#include<utils.h>
+#include<intalert.h>
+#include<assert.h>
+
+#include<strsafe.h>
+
+/***********************************************************************
+ Alerter
+***********************************************************************/
+
+khui_alert * kh_alerts = NULL;
+CRITICAL_SECTION cs_alerts;
+
+void
+alert_init(void)
+{
+ InitializeCriticalSection(&cs_alerts);
+}
+
+void
+alert_exit(void)
+{
+ DeleteCriticalSection(&cs_alerts);
+}
+
+KHMEXP khm_int32 KHMAPI
+khui_alert_create_empty(khui_alert ** result)
+{
+ khui_alert * a;
+
+ a = PMALLOC(sizeof(*a));
+ ZeroMemory(a, sizeof(*a));
+
+ a->magic = KHUI_ALERT_MAGIC;
+
+ /* set defaults */
+ a->severity = KHERR_INFO;
+ a->flags = KHUI_ALERT_FLAG_FREE_STRUCT;
+ a->alert_type = KHUI_ALERTTYPE_NONE;
+ khui_context_create(&a->ctx, KHUI_SCOPE_NONE,
+ NULL, KCDB_CREDTYPE_INVALID,
+ NULL);
+
+ khui_alert_hold(a);
+ EnterCriticalSection(&cs_alerts);
+ LPUSH(&kh_alerts, a);
+ LeaveCriticalSection(&cs_alerts);
+
+ *result = a;
+
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP khm_int32 KHMAPI
+khui_alert_create_simple(const wchar_t * title,
+ const wchar_t * message,
+ khm_int32 severity,
+ khui_alert ** result)
+{
+ khui_alert * a;
+
+ khui_alert_create_empty(&a);
+ khui_alert_set_title(a, title);
+ khui_alert_set_message(a, message);
+ khui_alert_set_severity(a, severity);
+
+ *result = a;
+
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP khm_int32 KHMAPI
+khui_alert_set_title(khui_alert * alert, const wchar_t * title)
+{
+ size_t cb = 0;
+
+ assert(alert->magic == KHUI_ALERT_MAGIC);
+
+ if(title) {
+ if(FAILED(StringCbLength(title,
+ KHUI_MAXCB_TITLE,
+ &cb))) {
+ return KHM_ERROR_INVALID_PARAM;
+ }
+ cb += sizeof(wchar_t);
+ }
+
+ EnterCriticalSection(&cs_alerts);
+ if(alert->title && (alert->flags & KHUI_ALERT_FLAG_FREE_TITLE)) {
+ PFREE(alert->title);
+ alert->title = NULL;
+ alert->flags &= ~KHUI_ALERT_FLAG_FREE_TITLE;
+ }
+ if(title) {
+ alert->title = PMALLOC(cb);
+ StringCbCopy(alert->title, cb, title);
+ alert->flags |= KHUI_ALERT_FLAG_FREE_TITLE;
+ }
+ LeaveCriticalSection(&cs_alerts);
+
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP khm_int32 KHMAPI
+khui_alert_set_flags(khui_alert * alert, khm_int32 mask, khm_int32 flags)
+{
+ assert(alert->magic == KHUI_ALERT_MAGIC);
+
+ if (mask & ~KHUI_ALERT_FLAGMASK_RDWR)
+ return KHM_ERROR_INVALID_PARAM;
+
+ EnterCriticalSection(&cs_alerts);
+ alert->flags =
+ (alert->flags & ~mask) |
+ (flags & mask);
+ LeaveCriticalSection(&cs_alerts);
+
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP khm_int32 KHMAPI
+khui_alert_set_severity(khui_alert * alert, khm_int32 severity)
+{
+
+ assert(alert->magic == KHUI_ALERT_MAGIC);
+
+ EnterCriticalSection(&cs_alerts);
+ alert->severity = severity;
+ LeaveCriticalSection(&cs_alerts);
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP khm_int32 KHMAPI
+khui_alert_set_suggestion(khui_alert * alert,
+ const wchar_t * suggestion) {
+ size_t cb = 0;
+
+ assert(alert->magic == KHUI_ALERT_MAGIC);
+
+ if(suggestion) {
+ if(FAILED(StringCbLength(suggestion,
+ KHUI_MAXCB_MESSAGE - sizeof(wchar_t),
+ &cb))) {
+ return KHM_ERROR_INVALID_PARAM;
+ }
+ cb += sizeof(wchar_t);
+ }
+
+ EnterCriticalSection(&cs_alerts);
+ if(alert->suggestion &&
+ (alert->flags & KHUI_ALERT_FLAG_FREE_SUGGEST)) {
+
+ PFREE(alert->suggestion);
+ alert->suggestion = NULL;
+ alert->flags &= ~KHUI_ALERT_FLAG_FREE_SUGGEST;
+
+ }
+
+ if(suggestion) {
+ alert->suggestion = PMALLOC(cb);
+ StringCbCopy(alert->suggestion, cb, suggestion);
+ alert->flags |= KHUI_ALERT_FLAG_FREE_SUGGEST;
+ }
+ LeaveCriticalSection(&cs_alerts);
+
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP khm_int32 KHMAPI
+khui_alert_set_message(khui_alert * alert, const wchar_t * message)
+{
+ size_t cb = 0;
+
+ assert(alert->magic == KHUI_ALERT_MAGIC);
+
+ if(message) {
+ if(FAILED(StringCbLength(message,
+ KHUI_MAXCB_MESSAGE - sizeof(wchar_t),
+ &cb))) {
+ return KHM_ERROR_INVALID_PARAM;
+ }
+ cb += sizeof(wchar_t);
+ }
+
+ EnterCriticalSection(&cs_alerts);
+ if(alert->message &&
+ (alert->flags & KHUI_ALERT_FLAG_FREE_MESSAGE)) {
+
+ PFREE(alert->message);
+ alert->flags &= ~KHUI_ALERT_FLAG_FREE_MESSAGE;
+ }
+
+ alert->message = NULL;
+
+ if(message) {
+ alert->message = PMALLOC(cb);
+ StringCbCopy(alert->message, cb, message);
+ alert->flags |= KHUI_ALERT_FLAG_FREE_MESSAGE;
+ }
+ LeaveCriticalSection(&cs_alerts);
+
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP khm_int32 KHMAPI
+khui_alert_clear_commands(khui_alert * alert)
+{
+ assert(alert->magic == KHUI_ALERT_MAGIC);
+
+ EnterCriticalSection(&cs_alerts);
+ alert->n_alert_commands = 0;
+ LeaveCriticalSection(&cs_alerts);
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP khm_int32 KHMAPI
+khui_alert_add_command(khui_alert * alert, khm_int32 command_id)
+{
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+
+ assert(alert->magic == KHUI_ALERT_MAGIC);
+
+ EnterCriticalSection(&cs_alerts);
+ if(alert->n_alert_commands >= KHUI_MAX_ALERT_COMMANDS)
+ rv = KHM_ERROR_NO_RESOURCES;
+ else {
+ alert->alert_commands[alert->n_alert_commands++] = command_id;
+ }
+ LeaveCriticalSection(&cs_alerts);
+
+ return rv;
+}
+
+KHMEXP khm_int32 KHMAPI
+khui_alert_set_type(khui_alert * alert, khui_alert_type alert_type)
+{
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+
+ assert(alert->magic == KHUI_ALERT_MAGIC);
+
+ EnterCriticalSection(&cs_alerts);
+ alert->alert_type = alert_type;
+ LeaveCriticalSection(&cs_alerts);
+
+ return rv;
+}
+
+KHMEXP khm_int32 KHMAPI
+khui_alert_set_ctx(khui_alert * alert,
+ khui_scope scope,
+ khm_handle identity,
+ khm_int32 cred_type,
+ khm_handle cred)
+{
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+
+ assert(alert->magic == KHUI_ALERT_MAGIC);
+
+ EnterCriticalSection(&cs_alerts);
+ khui_context_release(&alert->ctx);
+ khui_context_create(&alert->ctx,
+ scope,
+ identity,
+ cred_type,
+ cred);
+ LeaveCriticalSection(&cs_alerts);
+
+ return rv;
+}
+
+KHMEXP khm_int32 KHMAPI
+khui_alert_get_response(khui_alert * alert)
+{
+ khm_int32 response = 0;
+
+ assert(alert->magic == KHUI_ALERT_MAGIC);
+
+ EnterCriticalSection(&cs_alerts);
+ response = alert->response;
+ LeaveCriticalSection(&cs_alerts);
+
+ return response;
+}
+
+KHMEXP khm_int32 KHMAPI
+khui_alert_show(khui_alert * alert)
+{
+ assert(alert->magic == KHUI_ALERT_MAGIC);
+
+ khui_alert_hold(alert);
+ /* the alert will be released when the message is processed */
+ kmq_post_message(KMSG_ALERT, KMSG_ALERT_SHOW, 0, (void *) alert);
+
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP khm_int32 KHMAPI
+khui_alert_show_modal(khui_alert * alert)
+{
+ khm_int32 rv;
+
+ assert(alert->magic == KHUI_ALERT_MAGIC);
+
+ khui_alert_hold(alert);
+ rv = kmq_send_message(KMSG_ALERT, KMSG_ALERT_SHOW_MODAL, 0,
+ (void *) alert);
+
+ return rv;
+}
+
+KHMEXP khm_int32 KHMAPI
+khui_alert_queue(khui_alert * alert)
+{
+ assert(alert->magic == KHUI_ALERT_MAGIC);
+
+ khui_alert_hold(alert);
+ kmq_post_message(KMSG_ALERT, KMSG_ALERT_QUEUE, 0, (void *) alert);
+
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP khm_int32 KHMAPI
+khui_alert_show_simple(const wchar_t * title,
+ const wchar_t * message,
+ khm_int32 severity)
+{
+ khui_alert * a = NULL;
+ khm_int32 rv;
+
+ rv = khui_alert_create_simple(title, message, severity, &a);
+
+ if(KHM_FAILED(rv))
+ return rv;
+
+ rv = khui_alert_show(a);
+
+ khui_alert_release(a);
+
+ return rv;
+}
+
+KHMEXP khm_int32 KHMAPI
+khui_alert_hold(khui_alert * alert)
+{
+ assert(alert->magic == KHUI_ALERT_MAGIC);
+
+ EnterCriticalSection(&cs_alerts);
+ alert->refcount++;
+ LeaveCriticalSection(&cs_alerts);
+ return KHM_ERROR_SUCCESS;
+}
+
+/* called with cs_alert held */
+static void
+free_alert(khui_alert * alert)
+{
+ assert(alert->magic == KHUI_ALERT_MAGIC);
+
+ LDELETE(&kh_alerts, alert);
+
+ if(alert->flags & KHUI_ALERT_FLAG_FREE_TITLE) {
+ assert(alert->title);
+ PFREE(alert->title);
+ alert->title = NULL;
+ alert->flags &= ~KHUI_ALERT_FLAG_FREE_TITLE;
+ }
+ if(alert->flags & KHUI_ALERT_FLAG_FREE_MESSAGE) {
+ assert(alert->message);
+ PFREE(alert->message);
+ alert->message = NULL;
+ alert->flags &= ~KHUI_ALERT_FLAG_FREE_MESSAGE;
+ }
+ if(alert->flags & KHUI_ALERT_FLAG_FREE_SUGGEST) {
+ assert(alert->suggestion);
+ PFREE(alert->suggestion);
+ alert->suggestion = NULL;
+ alert->flags &= ~KHUI_ALERT_FLAG_FREE_SUGGEST;
+ }
+
+ khui_context_release(&alert->ctx);
+
+ if(alert->flags & KHUI_ALERT_FLAG_FREE_STRUCT) {
+ alert->flags &= ~KHUI_ALERT_FLAG_FREE_STRUCT;
+ alert->magic = 0;
+ PFREE(alert);
+ }
+}
+
+KHMEXP khm_int32 KHMAPI
+khui_alert_release(khui_alert * alert)
+{
+ assert(alert->magic == KHUI_ALERT_MAGIC);
+
+ EnterCriticalSection(&cs_alerts);
+ if((--(alert->refcount)) == 0) {
+ free_alert(alert);
+ }
+ LeaveCriticalSection(&cs_alerts);
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP void KHMAPI khui_alert_lock(khui_alert * alert)
+{
+ EnterCriticalSection(&cs_alerts);
+}
+
+KHMEXP void KHMAPI khui_alert_unlock(khui_alert * alert)
+{
+ LeaveCriticalSection(&cs_alerts);
+}
diff --git a/src/windows/identity/uilib/configui.c b/src/windows/identity/uilib/configui.c
index c8c61f5cb3..3de2573ea1 100644
--- a/src/windows/identity/uilib/configui.c
+++ b/src/windows/identity/uilib/configui.c
@@ -1,1085 +1,1085 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<khuidefs.h>
-#include<kmm.h>
-#include<configui.h>
-#include<utils.h>
-#include<assert.h>
-
-#include<strsafe.h>
-
-khm_int32 cfgui_node_serial;
-LONG init_once = 0;
-CRITICAL_SECTION cs_cfgui;
-khui_config_node_i * cfgui_root_config;
-HWND hwnd_cfgui = NULL;
-
-static khui_config_node_i *
-cfgui_create_new_node(void) {
- khui_config_node_i * node;
-
- node = PMALLOC(sizeof(*node));
-#ifdef DEBUG
- assert(node);
-#endif
- ZeroMemory(node, sizeof(*node));
- node->magic = KHUI_CONFIG_NODE_MAGIC;
-
- EnterCriticalSection(&cs_cfgui);
- node->id = ++cfgui_node_serial;
- LeaveCriticalSection(&cs_cfgui);
-
- return node;
-}
-
-/* called with cs_cfgui held */
-static void
-cfgui_free_node(khui_config_node_i * node) {
- if (!cfgui_is_valid_node(node))
- return;
-
- if (node->reg.name)
- PFREE((void *) node->reg.name);
-
- if (node->reg.short_desc)
- PFREE((void *) node->reg.short_desc);
-
- if (node->reg.long_desc)
- PFREE((void *) node->reg.long_desc);
-
- node->magic = 0;
-
- if (node->owner)
- kmm_release_plugin(node->owner);
-
- ZeroMemory(node, sizeof(*node));
-
- PFREE(node);
-}
-
-
-static void
-cfgui_hold_node(khui_config_node_i * node) {
- EnterCriticalSection(&cs_cfgui);
- node->refcount++;
- LeaveCriticalSection(&cs_cfgui);
-}
-
-
-static void
-cfgui_release_node(khui_config_node_i * node) {
- EnterCriticalSection(&cs_cfgui);
- node->refcount--;
- if (node->refcount == 0 &&
- (node->flags & KHUI_CN_FLAG_DELETED)) {
- khui_config_node_i * parent;
- parent = TPARENT(node);
-#ifdef DEBUG
- assert(TFIRSTCHILD(node) == NULL);
- assert(parent != NULL);
-#endif
- TDELCHILD(parent, node);
- cfgui_free_node(node);
- cfgui_release_node(parent);
- }
- LeaveCriticalSection(&cs_cfgui);
-}
-
-static void
-cfgui_init_once(void) {
- if (init_once == 0 &&
- InterlockedIncrement(&init_once) == 1) {
- InitializeCriticalSection(&cs_cfgui);
- cfgui_root_config = cfgui_create_new_node();
- cfgui_node_serial = 0;
- hwnd_cfgui = NULL;
- }
-}
-
-KHMEXP khm_int32 KHMAPI
-khui_cfg_register(khui_config_node vparent,
- const khui_config_node_reg * reg) {
-
- size_t cb_name;
- size_t cb_short_desc;
- size_t cb_long_desc;
- khui_config_node_i * node;
- khui_config_node_i * parent;
- khui_config_node t;
- wchar_t * name;
- wchar_t * short_desc;
- wchar_t * long_desc;
-
- cfgui_init_once();
-
- if (!reg ||
- FAILED(StringCbLength(reg->name,
- KHUI_MAXCB_NAME,
- &cb_name)) ||
- FAILED(StringCbLength(reg->short_desc,
- KHUI_MAXCB_SHORT_DESC,
- &cb_short_desc)) ||
- FAILED(StringCbLength(reg->long_desc,
- KHUI_MAXCB_LONG_DESC,
- &cb_long_desc)) ||
- (vparent &&
- !cfgui_is_valid_node_handle(vparent)))
- return KHM_ERROR_INVALID_PARAM;
-
- if (KHM_SUCCEEDED(khui_cfg_open(vparent,
- reg->name,
- &t))) {
- khui_cfg_release(t);
- return KHM_ERROR_DUPLICATE;
- }
-
- cb_name += sizeof(wchar_t);
- cb_short_desc += sizeof(wchar_t);
- cb_long_desc += sizeof(wchar_t);
-
- node = cfgui_create_new_node();
-
- node->reg = *reg;
- node->reg.flags &= KHUI_CNFLAGMASK_STATIC;
-
- name = PMALLOC(cb_name);
- StringCbCopy(name, cb_name, reg->name);
- short_desc = PMALLOC(cb_short_desc);
- StringCbCopy(short_desc, cb_short_desc, reg->short_desc);
- long_desc = PMALLOC(cb_long_desc);
- StringCbCopy(long_desc, cb_long_desc, reg->long_desc);
-
- node->reg.name = name;
- node->reg.short_desc = short_desc;
- node->reg.long_desc = long_desc;
- node->flags = node->reg.flags;
-
- if (vparent == NULL) {
- parent = cfgui_root_config;
- } else {
- parent = cfgui_node_i_from_handle(vparent);
- }
-
- /* plugin handles should not be obtained lightly. For the moment,
- the cleanup of nodes doesn't happen until module unload and
- module unload doesn't happen until all the plugin and module
- handles have been freed. */
- /* node->owner = kmm_this_plugin(); */
-
- EnterCriticalSection(&cs_cfgui);
- TADDCHILD(parent, node);
-
- if (hwnd_cfgui) {
- SendMessage(hwnd_cfgui, KHUI_WM_CFG_NOTIFY,
- MAKEWPARAM(0, WMCFG_SYNC_NODE_LIST), 0);
- }
-
- LeaveCriticalSection(&cs_cfgui);
-
- /* when the root config list changes, we need to notify the UI.
- this way, the Options menu can be kept in sync. */
- if (parent == cfgui_root_config) {
- kmq_post_message(KMSG_ACT, KMSG_ACT_SYNC_CFG, 0, 0);
- }
-
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP khm_int32 KHMAPI
-khui_cfg_open(khui_config_node vparent,
- const wchar_t * name,
- khui_config_node * result) {
- khui_config_node_i * parent;
- khui_config_node_i * c;
- size_t sz;
-
- cfgui_init_once();
-
- if ((vparent &&
- !cfgui_is_valid_node_handle(vparent)) ||
- FAILED(StringCbLength(name, KHUI_MAXCCH_NAME, &sz)) ||
- !result)
- return KHM_ERROR_INVALID_PARAM;
-
- EnterCriticalSection(&cs_cfgui);
- if (vparent)
- parent = cfgui_node_i_from_handle(vparent);
- else
- parent = cfgui_root_config;
-
- c = TFIRSTCHILD(parent);
- while(c) {
- if (!(c->flags & KHUI_CN_FLAG_DELETED) &&
- !wcscmp(c->reg.name, name))
- break;
- c = LNEXT(c);
- }
-
- if (c) {
- *result = cfgui_handle_from_node_i(c);
- cfgui_hold_node(c);
- } else {
- *result = NULL;
- }
- LeaveCriticalSection(&cs_cfgui);
-
- if (*result)
- return KHM_ERROR_SUCCESS;
- else
- return KHM_ERROR_NOT_FOUND;
-}
-
-KHMEXP khm_int32 KHMAPI
-khui_cfg_remove(khui_config_node vnode) {
- khui_config_node_i * node;
- if (!cfgui_is_valid_node_handle(vnode))
- return KHM_ERROR_INVALID_PARAM;
-
- EnterCriticalSection(&cs_cfgui);
- node = cfgui_node_i_from_handle(vnode);
- node->flags |= KHUI_CN_FLAG_DELETED;
-
- if (hwnd_cfgui) {
- SendMessage(hwnd_cfgui, KHUI_WM_CFG_NOTIFY,
- MAKEWPARAM(0, WMCFG_SYNC_NODE_LIST), 0);
- }
-
- LeaveCriticalSection(&cs_cfgui);
-
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP khm_int32 KHMAPI
-khui_cfg_hold(khui_config_node vnode) {
- if (!cfgui_is_valid_node_handle(vnode))
- return KHM_ERROR_INVALID_PARAM;
-
- cfgui_hold_node(cfgui_node_i_from_handle(vnode));
-
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP khm_int32 KHMAPI
-khui_cfg_release(khui_config_node vnode) {
- if (!cfgui_is_valid_node_handle(vnode))
- return KHM_ERROR_INVALID_PARAM;
-
- cfgui_release_node(cfgui_node_i_from_handle(vnode));
-
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP khm_int32 KHMAPI
-khui_cfg_get_parent(khui_config_node vnode,
- khui_config_node * result) {
-
- khui_config_node_i * node;
- khui_config_node_i * parent;
-
- if(!cfgui_is_valid_node_handle(vnode) ||
- !result)
- return KHM_ERROR_INVALID_PARAM;
-
- EnterCriticalSection(&cs_cfgui);
- if (cfgui_is_valid_node_handle(vnode)) {
- node = cfgui_node_i_from_handle(vnode);
- parent = TPARENT(node);
- if (parent == cfgui_root_config)
- parent = NULL;
- } else {
- parent = NULL;
- }
- if (parent) {
- cfgui_hold_node(parent);
- }
- LeaveCriticalSection(&cs_cfgui);
-
- *result = parent;
-
- if (parent)
- return KHM_ERROR_SUCCESS;
- else
- return KHM_ERROR_NOT_FOUND;
-}
-
-KHMEXP khm_int32 KHMAPI
-khui_cfg_get_first_child(khui_config_node vparent,
- khui_config_node * result) {
- khui_config_node_i * parent;
- khui_config_node_i * c;
-
- cfgui_init_once();
-
- if((vparent && !cfgui_is_valid_node_handle(vparent)) ||
- !result)
- return KHM_ERROR_INVALID_PARAM;
-
- EnterCriticalSection(&cs_cfgui);
- if (cfgui_is_valid_node_handle(vparent)) {
- parent = cfgui_node_i_from_handle(vparent);
- } else if (!vparent) {
- parent = cfgui_root_config;
- } else {
- parent = NULL;
- }
-
- if (parent) {
- for(c = TFIRSTCHILD(parent);
- c &&
- ((c->reg.flags & KHUI_CNFLAG_SUBPANEL) ||
- (c->flags & KHUI_CN_FLAG_DELETED));
- c = LNEXT(c));
- } else {
- c = NULL;
- }
-
- if (c)
- cfgui_hold_node(c);
- LeaveCriticalSection(&cs_cfgui);
-
- *result = c;
-
- if (c)
- return KHM_ERROR_SUCCESS;
- else
- return KHM_ERROR_NOT_FOUND;
-}
-
-KHMEXP khm_int32 KHMAPI
-khui_cfg_get_first_subpanel(khui_config_node vparent,
- khui_config_node * result) {
- khui_config_node_i * parent;
- khui_config_node_i * c;
-
- cfgui_init_once();
-
- if((vparent && !cfgui_is_valid_node_handle(vparent)) ||
- !result)
- return KHM_ERROR_INVALID_PARAM;
-
- EnterCriticalSection(&cs_cfgui);
- if (cfgui_is_valid_node_handle(vparent)) {
- parent = cfgui_node_i_from_handle(vparent);
- } else if (!vparent) {
- parent = cfgui_root_config;
- } else {
- parent = NULL;
- }
-
- if (parent) {
- for(c = TFIRSTCHILD(parent);
- c &&
- (!(c->reg.flags & KHUI_CNFLAG_SUBPANEL) ||
- (c->flags & KHUI_CN_FLAG_DELETED));
- c = LNEXT(c));
- } else {
- c = NULL;
- }
-
- if (c)
- cfgui_hold_node(c);
- LeaveCriticalSection(&cs_cfgui);
-
- *result = c;
-
- if (c)
- return KHM_ERROR_SUCCESS;
- else
- return KHM_ERROR_NOT_FOUND;
-}
-
-
-KHMEXP khm_int32 KHMAPI
-khui_cfg_get_next(khui_config_node vnode,
- khui_config_node * result) {
-
- khui_config_node_i * node;
- khui_config_node_i * nxt_node;
-
- if (!cfgui_is_valid_node_handle(vnode) ||
- !result)
- return KHM_ERROR_INVALID_PARAM;
-
- EnterCriticalSection(&cs_cfgui);
- if (cfgui_is_valid_node_handle(vnode)) {
- node = cfgui_node_i_from_handle(vnode);
- for(nxt_node = LNEXT(node);
- nxt_node &&
- ((node->reg.flags ^ nxt_node->reg.flags) &
- KHUI_CNFLAG_SUBPANEL);
- nxt_node = LNEXT(nxt_node));
- if (nxt_node)
- cfgui_hold_node(nxt_node);
- } else {
- nxt_node = NULL;
- }
- LeaveCriticalSection(&cs_cfgui);
-
- *result = cfgui_handle_from_node_i(nxt_node);
-
- if (nxt_node)
- return KHM_ERROR_SUCCESS;
- else
- return KHM_ERROR_NOT_FOUND;
-}
-
-KHMEXP khm_int32 KHMAPI
-khui_cfg_get_next_release(khui_config_node * pvnode) {
-
- khui_config_node_i * node;
- khui_config_node_i * nxt_node;
-
- if (!pvnode ||
- !cfgui_is_valid_node_handle(*pvnode))
- return KHM_ERROR_INVALID_PARAM;
-
- EnterCriticalSection(&cs_cfgui);
- if (cfgui_is_valid_node_handle(*pvnode)) {
- node = cfgui_node_i_from_handle(*pvnode);
- for(nxt_node = LNEXT(node);
- nxt_node &&
- (((node->reg.flags ^ nxt_node->reg.flags) &
- KHUI_CNFLAG_SUBPANEL) ||
- (nxt_node->flags & KHUI_CN_FLAG_DELETED));
- nxt_node = LNEXT(nxt_node));
- if (nxt_node)
- cfgui_hold_node(nxt_node);
- cfgui_release_node(node);
- } else {
- nxt_node = NULL;
- }
- LeaveCriticalSection(&cs_cfgui);
-
- *pvnode = cfgui_handle_from_node_i(nxt_node);
-
- if (nxt_node)
- return KHM_ERROR_SUCCESS;
- else
- return KHM_ERROR_NOT_FOUND;
-}
-
-KHMEXP khm_int32 KHMAPI
-khui_cfg_get_reg(khui_config_node vnode,
- khui_config_node_reg * reg) {
-
- khui_config_node_i * node;
-
- cfgui_init_once();
-
- if ((vnode && !cfgui_is_valid_node_handle(vnode)) ||
- !reg)
- return KHM_ERROR_INVALID_PARAM;
-
- EnterCriticalSection(&cs_cfgui);
- if (cfgui_is_valid_node_handle(vnode)) {
- node = cfgui_node_i_from_handle(vnode);
- *reg = node->reg;
- } else if (!vnode) {
- node = cfgui_root_config;
- *reg = node->reg;
- } else {
- node = NULL;
- ZeroMemory(reg, sizeof(*reg));
- }
- LeaveCriticalSection(&cs_cfgui);
-
- if (node)
- return KHM_ERROR_SUCCESS;
- else
- return KHM_ERROR_INVALID_PARAM;
-}
-
-KHMEXP HWND KHMAPI
-khui_cfg_get_hwnd(khui_config_node vnode) {
- khui_config_node_i * node;
- HWND hwnd;
-
- cfgui_init_once();
-
- if (vnode &&
- !cfgui_is_valid_node_handle(vnode))
- return NULL;
-
- EnterCriticalSection(&cs_cfgui);
- if (cfgui_is_valid_node_handle(vnode))
- node = cfgui_node_i_from_handle(vnode);
- else if (!vnode)
- node = cfgui_root_config;
- else
- node = NULL;
-
- if (node)
- hwnd = node->hwnd;
- else
- hwnd = NULL;
- LeaveCriticalSection(&cs_cfgui);
-
- return hwnd;
-}
-
-KHMEXP LPARAM KHMAPI
-khui_cfg_get_param(khui_config_node vnode) {
- khui_config_node_i * node;
- LPARAM param;
-
- cfgui_init_once();
-
- if (vnode &&
- !cfgui_is_valid_node_handle(vnode))
- return 0;
-
- EnterCriticalSection(&cs_cfgui);
- if (cfgui_is_valid_node_handle(vnode))
- node = cfgui_node_i_from_handle(vnode);
- else if (!vnode)
- node = cfgui_root_config;
- else
- node = NULL;
-
- if (node)
- param = node->param;
- else
- param = 0;
- LeaveCriticalSection(&cs_cfgui);
-
- return param;
-}
-
-KHMEXP void KHMAPI
-khui_cfg_set_hwnd(khui_config_node vnode, HWND hwnd) {
- khui_config_node_i * node;
-
- cfgui_init_once();
-
- if (vnode &&
- !cfgui_is_valid_node_handle(vnode))
- return;
-
- EnterCriticalSection(&cs_cfgui);
- if (cfgui_is_valid_node_handle(vnode))
- node = cfgui_node_i_from_handle(vnode);
- else if (!vnode)
- node = cfgui_root_config;
- else
- node = NULL;
-
- if (node)
- node->hwnd = hwnd;
- LeaveCriticalSection(&cs_cfgui);
-}
-
-KHMEXP void KHMAPI
-khui_cfg_set_param(khui_config_node vnode, LPARAM param) {
- khui_config_node_i * node;
-
- cfgui_init_once();
-
- if (vnode &&
- !cfgui_is_valid_node_handle(vnode))
- return;
-
- EnterCriticalSection(&cs_cfgui);
- if (cfgui_is_valid_node_handle(vnode))
- node = cfgui_node_i_from_handle(vnode);
- else if (!vnode)
- node = cfgui_root_config;
- else
- node = NULL;
-
- if (node)
- node->param = param;
- LeaveCriticalSection(&cs_cfgui);
-}
-
-static void
-clear_node_data(khui_config_node_i * node) {
- node->n_data = 0;
-}
-
-static cfg_node_data *
-get_node_data(khui_config_node_i * node,
- void * key,
- khm_boolean create) {
- khm_size i;
-
- for (i=0; i<node->n_data; i++) {
- if (node->data[i].key == key)
- return &(node->data[i]);
- }
-
- if (!create)
- return NULL;
-
- if (node->n_data + 1 > node->nc_data) {
- cfg_node_data * newdata;
-
- node->nc_data = UBOUNDSS((node->n_data + 1),
- KHUI_NODEDATA_ALLOC_INCR,
- KHUI_NODEDATA_ALLOC_INCR);
-#ifdef DEBUG
- assert(node->nc_data >= node->n_data + 1);
-#endif
- newdata = PMALLOC(sizeof(*newdata) * node->nc_data);
-#ifdef DEBUG
- assert(newdata);
-#endif
- ZeroMemory(newdata, sizeof(*newdata) * node->nc_data);
-
- if (node->data && node->n_data > 0) {
- memcpy(newdata, node->data, node->n_data * sizeof(*newdata));
- PFREE(node->data);
- }
- node->data = newdata;
- }
-
- node->data[node->n_data].key = key;
- node->data[node->n_data].hwnd = NULL;
- node->data[node->n_data].param = 0;
- node->data[node->n_data].flags = 0;
-
- node->n_data++;
-
- return &(node->data[node->n_data - 1]);
-}
-
-KHMEXP HWND KHMAPI
-khui_cfg_get_hwnd_inst(khui_config_node vnode,
- khui_config_node noderef) {
- khui_config_node_i * node;
- cfg_node_data * data;
- HWND hwnd;
-
- cfgui_init_once();
-
- if (vnode &&
- !cfgui_is_valid_node_handle(vnode))
- return NULL;
-
- EnterCriticalSection(&cs_cfgui);
- if (cfgui_is_valid_node_handle(vnode))
- node = cfgui_node_i_from_handle(vnode);
- else if (!vnode)
- node = cfgui_root_config;
- else
- node = NULL;
-
- if (node) {
- data = get_node_data(node, noderef, FALSE);
- if (data)
- hwnd = data->hwnd;
- else
- hwnd = NULL;
- } else
- hwnd = NULL;
- LeaveCriticalSection(&cs_cfgui);
-
- return hwnd;
-}
-
-KHMEXP LPARAM KHMAPI
-khui_cfg_get_param_inst(khui_config_node vnode,
- khui_config_node noderef) {
- khui_config_node_i * node;
- cfg_node_data * data;
- LPARAM lParam;
-
- cfgui_init_once();
-
- if (vnode &&
- !cfgui_is_valid_node_handle(vnode))
- return 0;
-
- EnterCriticalSection(&cs_cfgui);
- if (cfgui_is_valid_node_handle(vnode))
- node = cfgui_node_i_from_handle(vnode);
- else if (!vnode)
- node = cfgui_root_config;
- else
- node = NULL;
-
- if (node) {
- data = get_node_data(node, noderef, FALSE);
- if (data)
- lParam = data->param;
- else
- lParam = 0;
- } else
- lParam = 0;
- LeaveCriticalSection(&cs_cfgui);
-
- return lParam;
-}
-
-KHMEXP void KHMAPI
-khui_cfg_set_hwnd_inst(khui_config_node vnode,
- khui_config_node noderef,
- HWND hwnd) {
- khui_config_node_i * node;
- cfg_node_data * data;
-
- cfgui_init_once();
-
- if (vnode &&
- !cfgui_is_valid_node_handle(vnode))
- return;
-
- EnterCriticalSection(&cs_cfgui);
- if (cfgui_is_valid_node_handle(vnode))
- node = cfgui_node_i_from_handle(vnode);
- else if (!vnode)
- node = cfgui_root_config;
- else
- node = NULL;
-
- if (node) {
- data = get_node_data(node, noderef, TRUE);
- if (data)
- data->hwnd = hwnd;
- }
- LeaveCriticalSection(&cs_cfgui);
-}
-
-KHMEXP void KHMAPI
-khui_cfg_set_param_inst(khui_config_node vnode,
- khui_config_node noderef,
- LPARAM param) {
- khui_config_node_i * node;
- cfg_node_data * data;
-
- cfgui_init_once();
-
- if (vnode &&
- !cfgui_is_valid_node_handle(vnode))
- return;
-
- EnterCriticalSection(&cs_cfgui);
- if (cfgui_is_valid_node_handle(vnode))
- node = cfgui_node_i_from_handle(vnode);
- else if (!vnode)
- node = cfgui_root_config;
- else
- node = NULL;
-
- if (node) {
- data = get_node_data(node, noderef, TRUE);
- if (data)
- data->param = param;
- }
- LeaveCriticalSection(&cs_cfgui);
-}
-
-
-/* called with cs_cfgui held */
-static void
-cfgui_clear_params(khui_config_node_i * node) {
- khui_config_node_i * c;
-
- node->hwnd = NULL;
- node->param = 0;
- node->flags &= KHUI_CNFLAGMASK_STATIC;
- clear_node_data(node);
-
- c = TFIRSTCHILD(node);
- while(c) {
- cfgui_clear_params(c);
- c = LNEXT(c);
- }
-}
-
-KHMEXP void KHMAPI
-khui_cfg_clear_params(void) {
-
- cfgui_init_once();
-
- EnterCriticalSection(&cs_cfgui);
- cfgui_clear_params(cfgui_root_config);
- LeaveCriticalSection(&cs_cfgui);
-}
-
-KHMEXP void KHMAPI
-khui_cfg_set_configui_handle(HWND hwnd) {
- EnterCriticalSection(&cs_cfgui);
- hwnd_cfgui = hwnd;
- LeaveCriticalSection(&cs_cfgui);
-}
-
-KHMEXP void KHMAPI
-khui_cfg_set_flags(khui_config_node vnode,
- khm_int32 flags,
- khm_int32 mask) {
- khui_config_node_i * node;
- khm_int32 newflags;
-
- if (vnode &&
- !cfgui_is_valid_node_handle(vnode))
- return;
-
- mask &= KHUI_CNFLAGMASK_DYNAMIC;
-
- EnterCriticalSection(&cs_cfgui);
- if (cfgui_is_valid_node_handle(vnode)) {
-
- node = cfgui_node_i_from_handle(vnode);
-
- newflags =
- (flags & mask) |
- (node->flags & ~mask);
-
- if (newflags != node->flags) {
- node->flags = newflags;
-
- if (hwnd_cfgui)
- PostMessage(hwnd_cfgui, KHUI_WM_CFG_NOTIFY,
- MAKEWPARAM((WORD)newflags, WMCFG_UPDATE_STATE),
- (LPARAM) vnode);
- }
- }
- LeaveCriticalSection(&cs_cfgui);
-}
-
-/* called with cs_cfgui held */
-static void
-recalc_node_flags(khui_config_node vnode, khm_boolean plural) {
- khui_config_node_i * node;
- khui_config_node_i * parent;
- khui_config_node_i * subpanel;
- cfg_node_data * data;
- khm_int32 flags;
-
-#ifdef DEBUG
- assert(cfgui_is_valid_node_handle(vnode));
-#endif
-
- node = cfgui_node_i_from_handle(vnode);
-
- if (plural)
- parent = TPARENT(node);
- else
- parent = node;
-#ifdef DEBUG
- assert(parent);
-#endif
-
- flags = 0;
-
- for(subpanel = TFIRSTCHILD(parent); subpanel;
- subpanel = LNEXT(subpanel)) {
- if (!(subpanel->reg.flags & KHUI_CNFLAG_SUBPANEL) ||
- (plural && !(subpanel->reg.flags & KHUI_CNFLAG_PLURAL)) ||
- (!plural && (subpanel->reg.flags & KHUI_CNFLAG_PLURAL)))
- continue;
-
- data = get_node_data(subpanel,
- vnode,
- FALSE);
-
- if (data) {
- flags |= data->flags;
- }
- }
-
- flags &= KHUI_CNFLAGMASK_DYNAMIC;
-
- if ((node->flags & KHUI_CNFLAGMASK_DYNAMIC) == flags)
- return;
-
- node->flags = (node->flags & ~KHUI_CNFLAGMASK_DYNAMIC) | flags;
-
- if (hwnd_cfgui)
- PostMessage(hwnd_cfgui, KHUI_WM_CFG_NOTIFY,
- MAKEWPARAM((WORD) node->flags, WMCFG_UPDATE_STATE),
- (LPARAM) vnode);
-}
-
-KHMEXP void KHMAPI
-khui_cfg_set_flags_inst(khui_config_init_data * d,
- khm_int32 flags,
- khm_int32 mask) {
- khui_config_node_i * node;
- cfg_node_data * data;
-
- cfgui_init_once();
- if (!cfgui_is_valid_node_handle(d->this_node))
- return;
-
- mask &= KHUI_CNFLAGMASK_DYNAMIC;
-
- EnterCriticalSection(&cs_cfgui);
- if (cfgui_is_valid_node_handle(d->this_node))
- node = cfgui_node_i_from_handle(d->this_node);
- else
- node = NULL;
-
- if (node) {
- data = get_node_data(node, d->ctx_node, TRUE);
- if (data) {
- khm_int32 new_flags;
-
- new_flags = (flags & mask) |
- (data->flags & ~mask);
-
- if (new_flags != data->flags) {
- data->flags = new_flags;
-
- if (d->ctx_node != d->ref_node)
- recalc_node_flags(d->ctx_node, TRUE);
- else
- recalc_node_flags(d->ctx_node, FALSE);
- }
- }
- }
- LeaveCriticalSection(&cs_cfgui);
-}
-
-KHMEXP khm_int32 KHMAPI
-khui_cfg_get_flags(khui_config_node vnode) {
- khui_config_node_i * node;
- khm_int32 flags = 0;
-
- if (vnode &&
- !cfgui_is_valid_node_handle(vnode))
- return 0;
-
- EnterCriticalSection(&cs_cfgui);
- if (cfgui_is_valid_node_handle(vnode)) {
-
- node = cfgui_node_i_from_handle(vnode);
-
- flags = node->flags;
- }
- LeaveCriticalSection(&cs_cfgui);
-
- return flags;
-}
-
-KHMEXP khm_int32 KHMAPI
-khui_cfg_get_name(khui_config_node vnode,
- wchar_t * buf,
- khm_size * cb_buf) {
- khui_config_node_i * node;
- khm_int32 rv = KHM_ERROR_SUCCESS;
-
- if (!cb_buf ||
- !cfgui_is_valid_node_handle(vnode))
- return KHM_ERROR_INVALID_PARAM;
-
- EnterCriticalSection(&cs_cfgui);
- if (cfgui_is_valid_node_handle(vnode)) {
- khm_size cb;
-
- node = cfgui_node_i_from_handle(vnode);
-
- StringCbLength(node->reg.name, KHUI_MAXCCH_NAME, &cb);
-
- if (buf == NULL || cb > *cb_buf) {
- *cb_buf = cb;
- rv = KHM_ERROR_TOO_LONG;
- } else {
- StringCbCopy(buf, *cb_buf, node->reg.name);
- *cb_buf = cb;
- }
- } else {
- rv = KHM_ERROR_INVALID_PARAM;
- }
- LeaveCriticalSection(&cs_cfgui);
-
- return rv;
-}
-
-KHMEXP khm_int32 KHMAPI
-khui_cfg_init_dialog_data(HWND hwnd_dlg,
- const khui_config_init_data * data,
- khm_size cb_extra,
- khui_config_init_data ** new_data,
- void ** extra) {
- khm_size cb;
- khui_config_init_data * d;
-
- cb = sizeof(khui_config_init_data) + cb_extra;
- d = PMALLOC(cb);
-#ifdef DEBUG
- assert(d);
-#endif
- ZeroMemory(d, cb);
-
- *d = *data;
-
- if (d->ctx_node)
- khui_cfg_hold(d->ctx_node);
- if (d->this_node)
- khui_cfg_hold(d->this_node);
- if (d->ref_node)
- khui_cfg_hold(d->ref_node);
-
-#pragma warning(push)
-#pragma warning(disable: 4244)
- SetWindowLongPtr(hwnd_dlg, DWLP_USER, (LONG_PTR) d);
-#pragma warning(pop)
-
- if (new_data)
- *new_data = d;
- if (extra)
- *extra = (void *) (d + 1);
-
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP khm_int32 KHMAPI
-khui_cfg_get_dialog_data(HWND hwnd_dlg,
- khui_config_init_data ** data,
- void ** extra) {
- khui_config_init_data * d;
-
- d = (khui_config_init_data *) (LONG_PTR) GetWindowLongPtr(hwnd_dlg,
- DWLP_USER);
-#ifdef DEBUG
- assert(d);
-#endif
-
- *data = d;
- if (extra)
- *extra = (void *) (d + 1);
-
- return (d)?KHM_ERROR_SUCCESS: KHM_ERROR_NOT_FOUND;
-}
-
-KHMEXP khm_int32 KHMAPI
-khui_cfg_free_dialog_data(HWND hwnd_dlg) {
- khui_config_init_data * d;
-
- d = (khui_config_init_data *) (LONG_PTR) GetWindowLongPtr(hwnd_dlg,
- DWLP_USER);
-#ifdef DEBUG
- assert(d);
-#endif
-
- if (d) {
- PFREE(d);
- }
-
- return (d)?KHM_ERROR_SUCCESS: KHM_ERROR_NOT_FOUND;
-}
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<khuidefs.h>
+#include<kmm.h>
+#include<configui.h>
+#include<utils.h>
+#include<assert.h>
+
+#include<strsafe.h>
+
+khm_int32 cfgui_node_serial;
+LONG init_once = 0;
+CRITICAL_SECTION cs_cfgui;
+khui_config_node_i * cfgui_root_config;
+HWND hwnd_cfgui = NULL;
+
+static khui_config_node_i *
+cfgui_create_new_node(void) {
+ khui_config_node_i * node;
+
+ node = PMALLOC(sizeof(*node));
+#ifdef DEBUG
+ assert(node);
+#endif
+ ZeroMemory(node, sizeof(*node));
+ node->magic = KHUI_CONFIG_NODE_MAGIC;
+
+ EnterCriticalSection(&cs_cfgui);
+ node->id = ++cfgui_node_serial;
+ LeaveCriticalSection(&cs_cfgui);
+
+ return node;
+}
+
+/* called with cs_cfgui held */
+static void
+cfgui_free_node(khui_config_node_i * node) {
+ if (!cfgui_is_valid_node(node))
+ return;
+
+ if (node->reg.name)
+ PFREE((void *) node->reg.name);
+
+ if (node->reg.short_desc)
+ PFREE((void *) node->reg.short_desc);
+
+ if (node->reg.long_desc)
+ PFREE((void *) node->reg.long_desc);
+
+ node->magic = 0;
+
+ if (node->owner)
+ kmm_release_plugin(node->owner);
+
+ ZeroMemory(node, sizeof(*node));
+
+ PFREE(node);
+}
+
+
+static void
+cfgui_hold_node(khui_config_node_i * node) {
+ EnterCriticalSection(&cs_cfgui);
+ node->refcount++;
+ LeaveCriticalSection(&cs_cfgui);
+}
+
+
+static void
+cfgui_release_node(khui_config_node_i * node) {
+ EnterCriticalSection(&cs_cfgui);
+ node->refcount--;
+ if (node->refcount == 0 &&
+ (node->flags & KHUI_CN_FLAG_DELETED)) {
+ khui_config_node_i * parent;
+ parent = TPARENT(node);
+#ifdef DEBUG
+ assert(TFIRSTCHILD(node) == NULL);
+ assert(parent != NULL);
+#endif
+ TDELCHILD(parent, node);
+ cfgui_free_node(node);
+ cfgui_release_node(parent);
+ }
+ LeaveCriticalSection(&cs_cfgui);
+}
+
+static void
+cfgui_init_once(void) {
+ if (init_once == 0 &&
+ InterlockedIncrement(&init_once) == 1) {
+ InitializeCriticalSection(&cs_cfgui);
+ cfgui_root_config = cfgui_create_new_node();
+ cfgui_node_serial = 0;
+ hwnd_cfgui = NULL;
+ }
+}
+
+KHMEXP khm_int32 KHMAPI
+khui_cfg_register(khui_config_node vparent,
+ const khui_config_node_reg * reg) {
+
+ size_t cb_name;
+ size_t cb_short_desc;
+ size_t cb_long_desc;
+ khui_config_node_i * node;
+ khui_config_node_i * parent;
+ khui_config_node t;
+ wchar_t * name;
+ wchar_t * short_desc;
+ wchar_t * long_desc;
+
+ cfgui_init_once();
+
+ if (!reg ||
+ FAILED(StringCbLength(reg->name,
+ KHUI_MAXCB_NAME,
+ &cb_name)) ||
+ FAILED(StringCbLength(reg->short_desc,
+ KHUI_MAXCB_SHORT_DESC,
+ &cb_short_desc)) ||
+ FAILED(StringCbLength(reg->long_desc,
+ KHUI_MAXCB_LONG_DESC,
+ &cb_long_desc)) ||
+ (vparent &&
+ !cfgui_is_valid_node_handle(vparent)))
+ return KHM_ERROR_INVALID_PARAM;
+
+ if (KHM_SUCCEEDED(khui_cfg_open(vparent,
+ reg->name,
+ &t))) {
+ khui_cfg_release(t);
+ return KHM_ERROR_DUPLICATE;
+ }
+
+ cb_name += sizeof(wchar_t);
+ cb_short_desc += sizeof(wchar_t);
+ cb_long_desc += sizeof(wchar_t);
+
+ node = cfgui_create_new_node();
+
+ node->reg = *reg;
+ node->reg.flags &= KHUI_CNFLAGMASK_STATIC;
+
+ name = PMALLOC(cb_name);
+ StringCbCopy(name, cb_name, reg->name);
+ short_desc = PMALLOC(cb_short_desc);
+ StringCbCopy(short_desc, cb_short_desc, reg->short_desc);
+ long_desc = PMALLOC(cb_long_desc);
+ StringCbCopy(long_desc, cb_long_desc, reg->long_desc);
+
+ node->reg.name = name;
+ node->reg.short_desc = short_desc;
+ node->reg.long_desc = long_desc;
+ node->flags = node->reg.flags;
+
+ if (vparent == NULL) {
+ parent = cfgui_root_config;
+ } else {
+ parent = cfgui_node_i_from_handle(vparent);
+ }
+
+ /* plugin handles should not be obtained lightly. For the moment,
+ the cleanup of nodes doesn't happen until module unload and
+ module unload doesn't happen until all the plugin and module
+ handles have been freed. */
+ /* node->owner = kmm_this_plugin(); */
+
+ EnterCriticalSection(&cs_cfgui);
+ TADDCHILD(parent, node);
+
+ if (hwnd_cfgui) {
+ SendMessage(hwnd_cfgui, KHUI_WM_CFG_NOTIFY,
+ MAKEWPARAM(0, WMCFG_SYNC_NODE_LIST), 0);
+ }
+
+ LeaveCriticalSection(&cs_cfgui);
+
+ /* when the root config list changes, we need to notify the UI.
+ this way, the Options menu can be kept in sync. */
+ if (parent == cfgui_root_config) {
+ kmq_post_message(KMSG_ACT, KMSG_ACT_SYNC_CFG, 0, 0);
+ }
+
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP khm_int32 KHMAPI
+khui_cfg_open(khui_config_node vparent,
+ const wchar_t * name,
+ khui_config_node * result) {
+ khui_config_node_i * parent;
+ khui_config_node_i * c;
+ size_t sz;
+
+ cfgui_init_once();
+
+ if ((vparent &&
+ !cfgui_is_valid_node_handle(vparent)) ||
+ FAILED(StringCbLength(name, KHUI_MAXCCH_NAME, &sz)) ||
+ !result)
+ return KHM_ERROR_INVALID_PARAM;
+
+ EnterCriticalSection(&cs_cfgui);
+ if (vparent)
+ parent = cfgui_node_i_from_handle(vparent);
+ else
+ parent = cfgui_root_config;
+
+ c = TFIRSTCHILD(parent);
+ while(c) {
+ if (!(c->flags & KHUI_CN_FLAG_DELETED) &&
+ !wcscmp(c->reg.name, name))
+ break;
+ c = LNEXT(c);
+ }
+
+ if (c) {
+ *result = cfgui_handle_from_node_i(c);
+ cfgui_hold_node(c);
+ } else {
+ *result = NULL;
+ }
+ LeaveCriticalSection(&cs_cfgui);
+
+ if (*result)
+ return KHM_ERROR_SUCCESS;
+ else
+ return KHM_ERROR_NOT_FOUND;
+}
+
+KHMEXP khm_int32 KHMAPI
+khui_cfg_remove(khui_config_node vnode) {
+ khui_config_node_i * node;
+ if (!cfgui_is_valid_node_handle(vnode))
+ return KHM_ERROR_INVALID_PARAM;
+
+ EnterCriticalSection(&cs_cfgui);
+ node = cfgui_node_i_from_handle(vnode);
+ node->flags |= KHUI_CN_FLAG_DELETED;
+
+ if (hwnd_cfgui) {
+ SendMessage(hwnd_cfgui, KHUI_WM_CFG_NOTIFY,
+ MAKEWPARAM(0, WMCFG_SYNC_NODE_LIST), 0);
+ }
+
+ LeaveCriticalSection(&cs_cfgui);
+
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP khm_int32 KHMAPI
+khui_cfg_hold(khui_config_node vnode) {
+ if (!cfgui_is_valid_node_handle(vnode))
+ return KHM_ERROR_INVALID_PARAM;
+
+ cfgui_hold_node(cfgui_node_i_from_handle(vnode));
+
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP khm_int32 KHMAPI
+khui_cfg_release(khui_config_node vnode) {
+ if (!cfgui_is_valid_node_handle(vnode))
+ return KHM_ERROR_INVALID_PARAM;
+
+ cfgui_release_node(cfgui_node_i_from_handle(vnode));
+
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP khm_int32 KHMAPI
+khui_cfg_get_parent(khui_config_node vnode,
+ khui_config_node * result) {
+
+ khui_config_node_i * node;
+ khui_config_node_i * parent;
+
+ if(!cfgui_is_valid_node_handle(vnode) ||
+ !result)
+ return KHM_ERROR_INVALID_PARAM;
+
+ EnterCriticalSection(&cs_cfgui);
+ if (cfgui_is_valid_node_handle(vnode)) {
+ node = cfgui_node_i_from_handle(vnode);
+ parent = TPARENT(node);
+ if (parent == cfgui_root_config)
+ parent = NULL;
+ } else {
+ parent = NULL;
+ }
+ if (parent) {
+ cfgui_hold_node(parent);
+ }
+ LeaveCriticalSection(&cs_cfgui);
+
+ *result = parent;
+
+ if (parent)
+ return KHM_ERROR_SUCCESS;
+ else
+ return KHM_ERROR_NOT_FOUND;
+}
+
+KHMEXP khm_int32 KHMAPI
+khui_cfg_get_first_child(khui_config_node vparent,
+ khui_config_node * result) {
+ khui_config_node_i * parent;
+ khui_config_node_i * c;
+
+ cfgui_init_once();
+
+ if((vparent && !cfgui_is_valid_node_handle(vparent)) ||
+ !result)
+ return KHM_ERROR_INVALID_PARAM;
+
+ EnterCriticalSection(&cs_cfgui);
+ if (cfgui_is_valid_node_handle(vparent)) {
+ parent = cfgui_node_i_from_handle(vparent);
+ } else if (!vparent) {
+ parent = cfgui_root_config;
+ } else {
+ parent = NULL;
+ }
+
+ if (parent) {
+ for(c = TFIRSTCHILD(parent);
+ c &&
+ ((c->reg.flags & KHUI_CNFLAG_SUBPANEL) ||
+ (c->flags & KHUI_CN_FLAG_DELETED));
+ c = LNEXT(c));
+ } else {
+ c = NULL;
+ }
+
+ if (c)
+ cfgui_hold_node(c);
+ LeaveCriticalSection(&cs_cfgui);
+
+ *result = c;
+
+ if (c)
+ return KHM_ERROR_SUCCESS;
+ else
+ return KHM_ERROR_NOT_FOUND;
+}
+
+KHMEXP khm_int32 KHMAPI
+khui_cfg_get_first_subpanel(khui_config_node vparent,
+ khui_config_node * result) {
+ khui_config_node_i * parent;
+ khui_config_node_i * c;
+
+ cfgui_init_once();
+
+ if((vparent && !cfgui_is_valid_node_handle(vparent)) ||
+ !result)
+ return KHM_ERROR_INVALID_PARAM;
+
+ EnterCriticalSection(&cs_cfgui);
+ if (cfgui_is_valid_node_handle(vparent)) {
+ parent = cfgui_node_i_from_handle(vparent);
+ } else if (!vparent) {
+ parent = cfgui_root_config;
+ } else {
+ parent = NULL;
+ }
+
+ if (parent) {
+ for(c = TFIRSTCHILD(parent);
+ c &&
+ (!(c->reg.flags & KHUI_CNFLAG_SUBPANEL) ||
+ (c->flags & KHUI_CN_FLAG_DELETED));
+ c = LNEXT(c));
+ } else {
+ c = NULL;
+ }
+
+ if (c)
+ cfgui_hold_node(c);
+ LeaveCriticalSection(&cs_cfgui);
+
+ *result = c;
+
+ if (c)
+ return KHM_ERROR_SUCCESS;
+ else
+ return KHM_ERROR_NOT_FOUND;
+}
+
+
+KHMEXP khm_int32 KHMAPI
+khui_cfg_get_next(khui_config_node vnode,
+ khui_config_node * result) {
+
+ khui_config_node_i * node;
+ khui_config_node_i * nxt_node;
+
+ if (!cfgui_is_valid_node_handle(vnode) ||
+ !result)
+ return KHM_ERROR_INVALID_PARAM;
+
+ EnterCriticalSection(&cs_cfgui);
+ if (cfgui_is_valid_node_handle(vnode)) {
+ node = cfgui_node_i_from_handle(vnode);
+ for(nxt_node = LNEXT(node);
+ nxt_node &&
+ ((node->reg.flags ^ nxt_node->reg.flags) &
+ KHUI_CNFLAG_SUBPANEL);
+ nxt_node = LNEXT(nxt_node));
+ if (nxt_node)
+ cfgui_hold_node(nxt_node);
+ } else {
+ nxt_node = NULL;
+ }
+ LeaveCriticalSection(&cs_cfgui);
+
+ *result = cfgui_handle_from_node_i(nxt_node);
+
+ if (nxt_node)
+ return KHM_ERROR_SUCCESS;
+ else
+ return KHM_ERROR_NOT_FOUND;
+}
+
+KHMEXP khm_int32 KHMAPI
+khui_cfg_get_next_release(khui_config_node * pvnode) {
+
+ khui_config_node_i * node;
+ khui_config_node_i * nxt_node;
+
+ if (!pvnode ||
+ !cfgui_is_valid_node_handle(*pvnode))
+ return KHM_ERROR_INVALID_PARAM;
+
+ EnterCriticalSection(&cs_cfgui);
+ if (cfgui_is_valid_node_handle(*pvnode)) {
+ node = cfgui_node_i_from_handle(*pvnode);
+ for(nxt_node = LNEXT(node);
+ nxt_node &&
+ (((node->reg.flags ^ nxt_node->reg.flags) &
+ KHUI_CNFLAG_SUBPANEL) ||
+ (nxt_node->flags & KHUI_CN_FLAG_DELETED));
+ nxt_node = LNEXT(nxt_node));
+ if (nxt_node)
+ cfgui_hold_node(nxt_node);
+ cfgui_release_node(node);
+ } else {
+ nxt_node = NULL;
+ }
+ LeaveCriticalSection(&cs_cfgui);
+
+ *pvnode = cfgui_handle_from_node_i(nxt_node);
+
+ if (nxt_node)
+ return KHM_ERROR_SUCCESS;
+ else
+ return KHM_ERROR_NOT_FOUND;
+}
+
+KHMEXP khm_int32 KHMAPI
+khui_cfg_get_reg(khui_config_node vnode,
+ khui_config_node_reg * reg) {
+
+ khui_config_node_i * node;
+
+ cfgui_init_once();
+
+ if ((vnode && !cfgui_is_valid_node_handle(vnode)) ||
+ !reg)
+ return KHM_ERROR_INVALID_PARAM;
+
+ EnterCriticalSection(&cs_cfgui);
+ if (cfgui_is_valid_node_handle(vnode)) {
+ node = cfgui_node_i_from_handle(vnode);
+ *reg = node->reg;
+ } else if (!vnode) {
+ node = cfgui_root_config;
+ *reg = node->reg;
+ } else {
+ node = NULL;
+ ZeroMemory(reg, sizeof(*reg));
+ }
+ LeaveCriticalSection(&cs_cfgui);
+
+ if (node)
+ return KHM_ERROR_SUCCESS;
+ else
+ return KHM_ERROR_INVALID_PARAM;
+}
+
+KHMEXP HWND KHMAPI
+khui_cfg_get_hwnd(khui_config_node vnode) {
+ khui_config_node_i * node;
+ HWND hwnd;
+
+ cfgui_init_once();
+
+ if (vnode &&
+ !cfgui_is_valid_node_handle(vnode))
+ return NULL;
+
+ EnterCriticalSection(&cs_cfgui);
+ if (cfgui_is_valid_node_handle(vnode))
+ node = cfgui_node_i_from_handle(vnode);
+ else if (!vnode)
+ node = cfgui_root_config;
+ else
+ node = NULL;
+
+ if (node)
+ hwnd = node->hwnd;
+ else
+ hwnd = NULL;
+ LeaveCriticalSection(&cs_cfgui);
+
+ return hwnd;
+}
+
+KHMEXP LPARAM KHMAPI
+khui_cfg_get_param(khui_config_node vnode) {
+ khui_config_node_i * node;
+ LPARAM param;
+
+ cfgui_init_once();
+
+ if (vnode &&
+ !cfgui_is_valid_node_handle(vnode))
+ return 0;
+
+ EnterCriticalSection(&cs_cfgui);
+ if (cfgui_is_valid_node_handle(vnode))
+ node = cfgui_node_i_from_handle(vnode);
+ else if (!vnode)
+ node = cfgui_root_config;
+ else
+ node = NULL;
+
+ if (node)
+ param = node->param;
+ else
+ param = 0;
+ LeaveCriticalSection(&cs_cfgui);
+
+ return param;
+}
+
+KHMEXP void KHMAPI
+khui_cfg_set_hwnd(khui_config_node vnode, HWND hwnd) {
+ khui_config_node_i * node;
+
+ cfgui_init_once();
+
+ if (vnode &&
+ !cfgui_is_valid_node_handle(vnode))
+ return;
+
+ EnterCriticalSection(&cs_cfgui);
+ if (cfgui_is_valid_node_handle(vnode))
+ node = cfgui_node_i_from_handle(vnode);
+ else if (!vnode)
+ node = cfgui_root_config;
+ else
+ node = NULL;
+
+ if (node)
+ node->hwnd = hwnd;
+ LeaveCriticalSection(&cs_cfgui);
+}
+
+KHMEXP void KHMAPI
+khui_cfg_set_param(khui_config_node vnode, LPARAM param) {
+ khui_config_node_i * node;
+
+ cfgui_init_once();
+
+ if (vnode &&
+ !cfgui_is_valid_node_handle(vnode))
+ return;
+
+ EnterCriticalSection(&cs_cfgui);
+ if (cfgui_is_valid_node_handle(vnode))
+ node = cfgui_node_i_from_handle(vnode);
+ else if (!vnode)
+ node = cfgui_root_config;
+ else
+ node = NULL;
+
+ if (node)
+ node->param = param;
+ LeaveCriticalSection(&cs_cfgui);
+}
+
+static void
+clear_node_data(khui_config_node_i * node) {
+ node->n_data = 0;
+}
+
+static cfg_node_data *
+get_node_data(khui_config_node_i * node,
+ void * key,
+ khm_boolean create) {
+ khm_size i;
+
+ for (i=0; i<node->n_data; i++) {
+ if (node->data[i].key == key)
+ return &(node->data[i]);
+ }
+
+ if (!create)
+ return NULL;
+
+ if (node->n_data + 1 > node->nc_data) {
+ cfg_node_data * newdata;
+
+ node->nc_data = UBOUNDSS((node->n_data + 1),
+ KHUI_NODEDATA_ALLOC_INCR,
+ KHUI_NODEDATA_ALLOC_INCR);
+#ifdef DEBUG
+ assert(node->nc_data >= node->n_data + 1);
+#endif
+ newdata = PMALLOC(sizeof(*newdata) * node->nc_data);
+#ifdef DEBUG
+ assert(newdata);
+#endif
+ ZeroMemory(newdata, sizeof(*newdata) * node->nc_data);
+
+ if (node->data && node->n_data > 0) {
+ memcpy(newdata, node->data, node->n_data * sizeof(*newdata));
+ PFREE(node->data);
+ }
+ node->data = newdata;
+ }
+
+ node->data[node->n_data].key = key;
+ node->data[node->n_data].hwnd = NULL;
+ node->data[node->n_data].param = 0;
+ node->data[node->n_data].flags = 0;
+
+ node->n_data++;
+
+ return &(node->data[node->n_data - 1]);
+}
+
+KHMEXP HWND KHMAPI
+khui_cfg_get_hwnd_inst(khui_config_node vnode,
+ khui_config_node noderef) {
+ khui_config_node_i * node;
+ cfg_node_data * data;
+ HWND hwnd;
+
+ cfgui_init_once();
+
+ if (vnode &&
+ !cfgui_is_valid_node_handle(vnode))
+ return NULL;
+
+ EnterCriticalSection(&cs_cfgui);
+ if (cfgui_is_valid_node_handle(vnode))
+ node = cfgui_node_i_from_handle(vnode);
+ else if (!vnode)
+ node = cfgui_root_config;
+ else
+ node = NULL;
+
+ if (node) {
+ data = get_node_data(node, noderef, FALSE);
+ if (data)
+ hwnd = data->hwnd;
+ else
+ hwnd = NULL;
+ } else
+ hwnd = NULL;
+ LeaveCriticalSection(&cs_cfgui);
+
+ return hwnd;
+}
+
+KHMEXP LPARAM KHMAPI
+khui_cfg_get_param_inst(khui_config_node vnode,
+ khui_config_node noderef) {
+ khui_config_node_i * node;
+ cfg_node_data * data;
+ LPARAM lParam;
+
+ cfgui_init_once();
+
+ if (vnode &&
+ !cfgui_is_valid_node_handle(vnode))
+ return 0;
+
+ EnterCriticalSection(&cs_cfgui);
+ if (cfgui_is_valid_node_handle(vnode))
+ node = cfgui_node_i_from_handle(vnode);
+ else if (!vnode)
+ node = cfgui_root_config;
+ else
+ node = NULL;
+
+ if (node) {
+ data = get_node_data(node, noderef, FALSE);
+ if (data)
+ lParam = data->param;
+ else
+ lParam = 0;
+ } else
+ lParam = 0;
+ LeaveCriticalSection(&cs_cfgui);
+
+ return lParam;
+}
+
+KHMEXP void KHMAPI
+khui_cfg_set_hwnd_inst(khui_config_node vnode,
+ khui_config_node noderef,
+ HWND hwnd) {
+ khui_config_node_i * node;
+ cfg_node_data * data;
+
+ cfgui_init_once();
+
+ if (vnode &&
+ !cfgui_is_valid_node_handle(vnode))
+ return;
+
+ EnterCriticalSection(&cs_cfgui);
+ if (cfgui_is_valid_node_handle(vnode))
+ node = cfgui_node_i_from_handle(vnode);
+ else if (!vnode)
+ node = cfgui_root_config;
+ else
+ node = NULL;
+
+ if (node) {
+ data = get_node_data(node, noderef, TRUE);
+ if (data)
+ data->hwnd = hwnd;
+ }
+ LeaveCriticalSection(&cs_cfgui);
+}
+
+KHMEXP void KHMAPI
+khui_cfg_set_param_inst(khui_config_node vnode,
+ khui_config_node noderef,
+ LPARAM param) {
+ khui_config_node_i * node;
+ cfg_node_data * data;
+
+ cfgui_init_once();
+
+ if (vnode &&
+ !cfgui_is_valid_node_handle(vnode))
+ return;
+
+ EnterCriticalSection(&cs_cfgui);
+ if (cfgui_is_valid_node_handle(vnode))
+ node = cfgui_node_i_from_handle(vnode);
+ else if (!vnode)
+ node = cfgui_root_config;
+ else
+ node = NULL;
+
+ if (node) {
+ data = get_node_data(node, noderef, TRUE);
+ if (data)
+ data->param = param;
+ }
+ LeaveCriticalSection(&cs_cfgui);
+}
+
+
+/* called with cs_cfgui held */
+static void
+cfgui_clear_params(khui_config_node_i * node) {
+ khui_config_node_i * c;
+
+ node->hwnd = NULL;
+ node->param = 0;
+ node->flags &= KHUI_CNFLAGMASK_STATIC;
+ clear_node_data(node);
+
+ c = TFIRSTCHILD(node);
+ while(c) {
+ cfgui_clear_params(c);
+ c = LNEXT(c);
+ }
+}
+
+KHMEXP void KHMAPI
+khui_cfg_clear_params(void) {
+
+ cfgui_init_once();
+
+ EnterCriticalSection(&cs_cfgui);
+ cfgui_clear_params(cfgui_root_config);
+ LeaveCriticalSection(&cs_cfgui);
+}
+
+KHMEXP void KHMAPI
+khui_cfg_set_configui_handle(HWND hwnd) {
+ EnterCriticalSection(&cs_cfgui);
+ hwnd_cfgui = hwnd;
+ LeaveCriticalSection(&cs_cfgui);
+}
+
+KHMEXP void KHMAPI
+khui_cfg_set_flags(khui_config_node vnode,
+ khm_int32 flags,
+ khm_int32 mask) {
+ khui_config_node_i * node;
+ khm_int32 newflags;
+
+ if (vnode &&
+ !cfgui_is_valid_node_handle(vnode))
+ return;
+
+ mask &= KHUI_CNFLAGMASK_DYNAMIC;
+
+ EnterCriticalSection(&cs_cfgui);
+ if (cfgui_is_valid_node_handle(vnode)) {
+
+ node = cfgui_node_i_from_handle(vnode);
+
+ newflags =
+ (flags & mask) |
+ (node->flags & ~mask);
+
+ if (newflags != node->flags) {
+ node->flags = newflags;
+
+ if (hwnd_cfgui)
+ PostMessage(hwnd_cfgui, KHUI_WM_CFG_NOTIFY,
+ MAKEWPARAM((WORD)newflags, WMCFG_UPDATE_STATE),
+ (LPARAM) vnode);
+ }
+ }
+ LeaveCriticalSection(&cs_cfgui);
+}
+
+/* called with cs_cfgui held */
+static void
+recalc_node_flags(khui_config_node vnode, khm_boolean plural) {
+ khui_config_node_i * node;
+ khui_config_node_i * parent;
+ khui_config_node_i * subpanel;
+ cfg_node_data * data;
+ khm_int32 flags;
+
+#ifdef DEBUG
+ assert(cfgui_is_valid_node_handle(vnode));
+#endif
+
+ node = cfgui_node_i_from_handle(vnode);
+
+ if (plural)
+ parent = TPARENT(node);
+ else
+ parent = node;
+#ifdef DEBUG
+ assert(parent);
+#endif
+
+ flags = 0;
+
+ for(subpanel = TFIRSTCHILD(parent); subpanel;
+ subpanel = LNEXT(subpanel)) {
+ if (!(subpanel->reg.flags & KHUI_CNFLAG_SUBPANEL) ||
+ (plural && !(subpanel->reg.flags & KHUI_CNFLAG_PLURAL)) ||
+ (!plural && (subpanel->reg.flags & KHUI_CNFLAG_PLURAL)))
+ continue;
+
+ data = get_node_data(subpanel,
+ vnode,
+ FALSE);
+
+ if (data) {
+ flags |= data->flags;
+ }
+ }
+
+ flags &= KHUI_CNFLAGMASK_DYNAMIC;
+
+ if ((node->flags & KHUI_CNFLAGMASK_DYNAMIC) == flags)
+ return;
+
+ node->flags = (node->flags & ~KHUI_CNFLAGMASK_DYNAMIC) | flags;
+
+ if (hwnd_cfgui)
+ PostMessage(hwnd_cfgui, KHUI_WM_CFG_NOTIFY,
+ MAKEWPARAM((WORD) node->flags, WMCFG_UPDATE_STATE),
+ (LPARAM) vnode);
+}
+
+KHMEXP void KHMAPI
+khui_cfg_set_flags_inst(khui_config_init_data * d,
+ khm_int32 flags,
+ khm_int32 mask) {
+ khui_config_node_i * node;
+ cfg_node_data * data;
+
+ cfgui_init_once();
+ if (!cfgui_is_valid_node_handle(d->this_node))
+ return;
+
+ mask &= KHUI_CNFLAGMASK_DYNAMIC;
+
+ EnterCriticalSection(&cs_cfgui);
+ if (cfgui_is_valid_node_handle(d->this_node))
+ node = cfgui_node_i_from_handle(d->this_node);
+ else
+ node = NULL;
+
+ if (node) {
+ data = get_node_data(node, d->ctx_node, TRUE);
+ if (data) {
+ khm_int32 new_flags;
+
+ new_flags = (flags & mask) |
+ (data->flags & ~mask);
+
+ if (new_flags != data->flags) {
+ data->flags = new_flags;
+
+ if (d->ctx_node != d->ref_node)
+ recalc_node_flags(d->ctx_node, TRUE);
+ else
+ recalc_node_flags(d->ctx_node, FALSE);
+ }
+ }
+ }
+ LeaveCriticalSection(&cs_cfgui);
+}
+
+KHMEXP khm_int32 KHMAPI
+khui_cfg_get_flags(khui_config_node vnode) {
+ khui_config_node_i * node;
+ khm_int32 flags = 0;
+
+ if (vnode &&
+ !cfgui_is_valid_node_handle(vnode))
+ return 0;
+
+ EnterCriticalSection(&cs_cfgui);
+ if (cfgui_is_valid_node_handle(vnode)) {
+
+ node = cfgui_node_i_from_handle(vnode);
+
+ flags = node->flags;
+ }
+ LeaveCriticalSection(&cs_cfgui);
+
+ return flags;
+}
+
+KHMEXP khm_int32 KHMAPI
+khui_cfg_get_name(khui_config_node vnode,
+ wchar_t * buf,
+ khm_size * cb_buf) {
+ khui_config_node_i * node;
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+
+ if (!cb_buf ||
+ !cfgui_is_valid_node_handle(vnode))
+ return KHM_ERROR_INVALID_PARAM;
+
+ EnterCriticalSection(&cs_cfgui);
+ if (cfgui_is_valid_node_handle(vnode)) {
+ khm_size cb;
+
+ node = cfgui_node_i_from_handle(vnode);
+
+ StringCbLength(node->reg.name, KHUI_MAXCCH_NAME, &cb);
+
+ if (buf == NULL || cb > *cb_buf) {
+ *cb_buf = cb;
+ rv = KHM_ERROR_TOO_LONG;
+ } else {
+ StringCbCopy(buf, *cb_buf, node->reg.name);
+ *cb_buf = cb;
+ }
+ } else {
+ rv = KHM_ERROR_INVALID_PARAM;
+ }
+ LeaveCriticalSection(&cs_cfgui);
+
+ return rv;
+}
+
+KHMEXP khm_int32 KHMAPI
+khui_cfg_init_dialog_data(HWND hwnd_dlg,
+ const khui_config_init_data * data,
+ khm_size cb_extra,
+ khui_config_init_data ** new_data,
+ void ** extra) {
+ khm_size cb;
+ khui_config_init_data * d;
+
+ cb = sizeof(khui_config_init_data) + cb_extra;
+ d = PMALLOC(cb);
+#ifdef DEBUG
+ assert(d);
+#endif
+ ZeroMemory(d, cb);
+
+ *d = *data;
+
+ if (d->ctx_node)
+ khui_cfg_hold(d->ctx_node);
+ if (d->this_node)
+ khui_cfg_hold(d->this_node);
+ if (d->ref_node)
+ khui_cfg_hold(d->ref_node);
+
+#pragma warning(push)
+#pragma warning(disable: 4244)
+ SetWindowLongPtr(hwnd_dlg, DWLP_USER, (LONG_PTR) d);
+#pragma warning(pop)
+
+ if (new_data)
+ *new_data = d;
+ if (extra)
+ *extra = (void *) (d + 1);
+
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP khm_int32 KHMAPI
+khui_cfg_get_dialog_data(HWND hwnd_dlg,
+ khui_config_init_data ** data,
+ void ** extra) {
+ khui_config_init_data * d;
+
+ d = (khui_config_init_data *) (LONG_PTR) GetWindowLongPtr(hwnd_dlg,
+ DWLP_USER);
+#ifdef DEBUG
+ assert(d);
+#endif
+
+ *data = d;
+ if (extra)
+ *extra = (void *) (d + 1);
+
+ return (d)?KHM_ERROR_SUCCESS: KHM_ERROR_NOT_FOUND;
+}
+
+KHMEXP khm_int32 KHMAPI
+khui_cfg_free_dialog_data(HWND hwnd_dlg) {
+ khui_config_init_data * d;
+
+ d = (khui_config_init_data *) (LONG_PTR) GetWindowLongPtr(hwnd_dlg,
+ DWLP_USER);
+#ifdef DEBUG
+ assert(d);
+#endif
+
+ if (d) {
+ PFREE(d);
+ }
+
+ return (d)?KHM_ERROR_SUCCESS: KHM_ERROR_NOT_FOUND;
+}
diff --git a/src/windows/identity/uilib/configui.h b/src/windows/identity/uilib/configui.h
index c7ff88bdb1..bd3a13e8ef 100644
--- a/src/windows/identity/uilib/configui.h
+++ b/src/windows/identity/uilib/configui.h
@@ -1,74 +1,74 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#ifndef __KHIMAIRA_CONFIGUI_H
-#define __KHIMAIRA_CONFIGUI_H
-
-typedef struct tag_cfg_node_data {
- void * key;
- HWND hwnd;
- LPARAM param;
- khm_int32 flags;
-} cfg_node_data;
-
-typedef struct tag_khui_config_node_i {
- khm_int32 magic;
-
- khui_config_node_reg reg;
- kmm_plugin owner;
- khm_int32 id;
-
- HWND hwnd;
- LPARAM param;
-
- cfg_node_data * data;
- khm_size n_data;
- khm_size nc_data;
-
- khm_int32 refcount;
- khm_int32 flags;
- TDCL(struct tag_khui_config_node_i);
-} khui_config_node_i;
-
-#define KHUI_CONFIG_NODE_MAGIC 0x38f4cb52
-
-#define KHUI_NODEDATA_ALLOC_INCR 8
-
-#define KHUI_CN_FLAG_DELETED 0x0008
-
-#define cfgui_is_valid_node_handle(v) \
-((v) && ((khui_config_node_i *) (v))->magic == KHUI_CONFIG_NODE_MAGIC)
-
-#define cfgui_is_valid_node(n) \
-((n)->magic == KHUI_CONFIG_NODE_MAGIC)
-
-#define cfgui_node_i_from_handle(v) \
-((khui_config_node_i *) v)
-
-#define cfgui_handle_from_node_i(n) \
-((khui_config_node) n)
-
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __KHIMAIRA_CONFIGUI_H
+#define __KHIMAIRA_CONFIGUI_H
+
+typedef struct tag_cfg_node_data {
+ void * key;
+ HWND hwnd;
+ LPARAM param;
+ khm_int32 flags;
+} cfg_node_data;
+
+typedef struct tag_khui_config_node_i {
+ khm_int32 magic;
+
+ khui_config_node_reg reg;
+ kmm_plugin owner;
+ khm_int32 id;
+
+ HWND hwnd;
+ LPARAM param;
+
+ cfg_node_data * data;
+ khm_size n_data;
+ khm_size nc_data;
+
+ khm_int32 refcount;
+ khm_int32 flags;
+ TDCL(struct tag_khui_config_node_i);
+} khui_config_node_i;
+
+#define KHUI_CONFIG_NODE_MAGIC 0x38f4cb52
+
+#define KHUI_NODEDATA_ALLOC_INCR 8
+
+#define KHUI_CN_FLAG_DELETED 0x0008
+
+#define cfgui_is_valid_node_handle(v) \
+((v) && ((khui_config_node_i *) (v))->magic == KHUI_CONFIG_NODE_MAGIC)
+
+#define cfgui_is_valid_node(n) \
+((n)->magic == KHUI_CONFIG_NODE_MAGIC)
+
+#define cfgui_node_i_from_handle(v) \
+((khui_config_node_i *) v)
+
+#define cfgui_handle_from_node_i(n) \
+((khui_config_node) n)
+
+#endif
diff --git a/src/windows/identity/uilib/creddlg.c b/src/windows/identity/uilib/creddlg.c
index c89a446203..08b0a149d6 100644
--- a/src/windows/identity/uilib/creddlg.c
+++ b/src/windows/identity/uilib/creddlg.c
@@ -1,718 +1,718 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<khuidefs.h>
-#include<utils.h>
-#include<assert.h>
-
-#include<strsafe.h>
-
-#define CW_ALLOC_INCR 8
-
-static void cw_free_prompts(khui_new_creds * c);
-
-static void cw_free_prompt(khui_new_creds_prompt * p);
-
-static khui_new_creds_prompt *
-cw_create_prompt(
- khm_size idx,
- khm_int32 type,
- wchar_t * prompt,
- wchar_t * def,
- khm_int32 flags);
-
-KHMEXP khm_int32 KHMAPI
-khui_cw_create_cred_blob(khui_new_creds ** ppnc)
-{
- khui_new_creds * c;
-
- c = PMALLOC(sizeof(*c));
- ZeroMemory(c, sizeof(*c));
-
- c->magic = KHUI_NC_MAGIC;
- InitializeCriticalSection(&c->cs);
- c->result = KHUI_NC_RESULT_CANCEL;
- c->mode = KHUI_NC_MODE_MINI;
-
- khui_context_create(&c->ctx, KHUI_SCOPE_NONE, NULL, KCDB_CREDTYPE_INVALID, NULL);
-
- *ppnc = c;
-
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP khm_int32 KHMAPI
-khui_cw_destroy_cred_blob(khui_new_creds *c)
-{
- khm_size i;
- size_t len;
- EnterCriticalSection(&c->cs);
- for(i=0;i<c->n_identities;i++) {
- kcdb_identity_release(c->identities[i]);
- }
- cw_free_prompts(c);
- khui_context_release(&c->ctx);
- LeaveCriticalSection(&c->cs);
- DeleteCriticalSection(&c->cs);
-
- if (c->password) {
- len = wcslen(c->password);
- SecureZeroMemory(c->password, sizeof(wchar_t) * len);
- PFREE(c->password);
- }
-
- if (c->identities)
- PFREE(c->identities);
-
- if (c->types)
- PFREE(c->types);
-
- if (c->type_subs)
- PFREE(c->type_subs);
-
- if (c->window_title)
- PFREE(c->window_title);
-
- PFREE(c);
-
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP khm_int32 KHMAPI
-khui_cw_lock_nc(khui_new_creds * c)
-{
- EnterCriticalSection(&c->cs);
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP khm_int32 KHMAPI
-khui_cw_unlock_nc(khui_new_creds * c)
-{
- LeaveCriticalSection(&c->cs);
- return KHM_ERROR_SUCCESS;
-}
-
-#define NC_N_IDENTITIES 4
-
-KHMEXP khm_int32 KHMAPI
-khui_cw_add_identity(khui_new_creds * c,
- khm_handle id)
-{
- if(id == NULL)
- return KHM_ERROR_SUCCESS; /* we return success because adding
- a NULL id is equivalent to adding
- nothing. */
- EnterCriticalSection(&(c->cs));
-
- if(c->identities == NULL) {
- c->nc_identities = NC_N_IDENTITIES;
- c->identities = PMALLOC(sizeof(*(c->identities)) *
- c->nc_identities);
- c->n_identities = 0;
- } else if(c->n_identities + 1 > c->nc_identities) {
- khm_handle * ni;
-
- c->nc_identities = UBOUNDSS(c->n_identities + 1,
- NC_N_IDENTITIES,
- NC_N_IDENTITIES);
- ni = PMALLOC(sizeof(*(c->identities)) * c->nc_identities);
- memcpy(ni, c->identities,
- sizeof(*(c->identities)) * c->n_identities);
- PFREE(c->identities);
- c->identities = ni;
- }
-
- kcdb_identity_hold(id);
- c->identities[c->n_identities++] = id;
- LeaveCriticalSection(&(c->cs));
-
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP khm_int32 KHMAPI
-khui_cw_set_primary_id(khui_new_creds * c,
- khm_handle id)
-{
- khm_size i;
- khm_int32 rv;
-
- EnterCriticalSection(&c->cs);
-
- /* no change */
- if((c->n_identities > 0 && c->identities[0] == id) ||
- (c->n_identities == 0 && id == NULL)) {
- LeaveCriticalSection(&c->cs);
- return KHM_ERROR_SUCCESS;
- }
-
- for(i=0; i<c->n_identities; i++) {
- kcdb_identity_release(c->identities[i]);
- }
- c->n_identities = 0;
-
- LeaveCriticalSection(&(c->cs));
- rv = khui_cw_add_identity(c,id);
- if(c->hwnd != NULL) {
- PostMessage(c->hwnd, KHUI_WM_NC_NOTIFY,
- MAKEWPARAM(0, WMNC_IDENTITY_CHANGE), 0);
- }
- return rv;
-}
-
-KHMEXP khm_int32 KHMAPI
-khui_cw_add_type(khui_new_creds * c,
- khui_new_creds_by_type * t)
-{
- EnterCriticalSection(&c->cs);
-
- if(c->n_types >= KHUI_MAX_NCTYPES) {
- LeaveCriticalSection(&c->cs);
- return KHM_ERROR_OUT_OF_BOUNDS;
- }
-
- if(c->types == NULL) {
- c->nc_types = CW_ALLOC_INCR;
- c->types = PMALLOC(sizeof(*(c->types)) * c->nc_types);
- c->type_subs = PMALLOC(sizeof(*(c->type_subs)) * c->nc_types);
- c->n_types = 0;
- }
-
- if(c->nc_types < c->n_types + 1) {
- void * t;
- khm_size n;
-
- n = UBOUNDSS(c->n_types + 1, CW_ALLOC_INCR, CW_ALLOC_INCR);
-
- t = PMALLOC(sizeof(*(c->types)) * n);
- memcpy(t, (void *) c->types, sizeof(*(c->types)) * c->n_types);
- PFREE(c->types);
- c->types = t;
-
- t = PMALLOC(sizeof(*(c->type_subs)) * n);
- memcpy(t, (void *) c->type_subs, sizeof(*(c->type_subs)) * c->n_types);
- PFREE(c->type_subs);
- c->type_subs = t;
-
- c->nc_types = n;
- }
-
- c->type_subs[c->n_types] = kcdb_credtype_get_sub(t->type);
- c->types[c->n_types++] = t;
- t->nc = c;
- LeaveCriticalSection(&c->cs);
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP khm_int32 KHMAPI
-khui_cw_del_type(khui_new_creds * c,
- khm_int32 type_id)
-{
- khm_size i;
-
- EnterCriticalSection(&c->cs);
- for(i=0; i < c->n_types; i++) {
- if(c->types[i]->type == type_id)
- break;
- }
- if(i >= c->n_types) {
- LeaveCriticalSection(&c->cs);
- return KHM_ERROR_NOT_FOUND;
- }
- c->n_types--;
- for(;i < c->n_types; i++) {
- c->types[i] = c->types[i+1];
- c->type_subs[i] = c->type_subs[i+1];
- }
- LeaveCriticalSection(&c->cs);
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP khm_int32 KHMAPI
-khui_cw_find_type(khui_new_creds * c,
- khm_int32 type,
- khui_new_creds_by_type **t)
-{
- khm_size i;
-
- EnterCriticalSection(&c->cs);
- *t = NULL;
- for(i=0;i<c->n_types;i++) {
- if(c->types[i]->type == type) {
- *t = c->types[i];
- break;
- }
- }
- LeaveCriticalSection(&c->cs);
-
- if(*t)
- return KHM_ERROR_SUCCESS;
- return KHM_ERROR_NOT_FOUND;
-}
-
-
-KHMEXP khm_int32 KHMAPI
-khui_cw_enable_type(khui_new_creds * c,
- khm_int32 type,
- khm_boolean enable)
-{
- khui_new_creds_by_type * t = NULL;
- BOOL delta = FALSE;
-
- EnterCriticalSection(&c->cs);
- if(KHM_SUCCEEDED(khui_cw_find_type(c, type, &t))) {
- if(enable) {
- delta = t->flags & KHUI_NCT_FLAG_DISABLED;
- t->flags &= ~KHUI_NCT_FLAG_DISABLED;
- }
- else {
- delta = !(t->flags & KHUI_NCT_FLAG_DISABLED);
- t->flags |= KHUI_NCT_FLAG_DISABLED;
- }
- }
- LeaveCriticalSection(&c->cs);
-
- if(delta)
- PostMessage(c->hwnd, KHUI_WM_NC_NOTIFY, MAKEWPARAM(0,WMNC_TYPE_STATE), (LPARAM) type);
-
- return (t)?KHM_ERROR_SUCCESS:KHM_ERROR_NOT_FOUND;
-}
-
-KHMEXP khm_boolean KHMAPI
-khui_cw_type_succeeded(khui_new_creds * c,
- khm_int32 type)
-{
- khui_new_creds_by_type * t;
- khm_boolean s;
-
- EnterCriticalSection(&c->cs);
- if(KHM_SUCCEEDED(khui_cw_find_type(c, type, &t))) {
- s = (t->flags & KHUI_NCT_FLAG_PROCESSED) && !(t->flags & KHUI_NC_RESPONSE_FAILED);
- } else {
- s = FALSE;
- }
- LeaveCriticalSection(&c->cs);
-
- return s;
-}
-
-static khui_new_creds_prompt *
-cw_create_prompt(khm_size idx,
- khm_int32 type,
- wchar_t * prompt,
- wchar_t * def,
- khm_int32 flags)
-{
- khui_new_creds_prompt * p;
- size_t cb_prompt = 0;
- size_t cb_def = 0;
-
- if(prompt && FAILED(StringCbLength(prompt, KHUI_MAXCB_PROMPT, &cb_prompt)))
- return NULL;
- if(def && FAILED(StringCbLength(def, KHUI_MAXCB_PROMPT_VALUE, &cb_def)))
- return NULL;
-
- p = PMALLOC(sizeof(*p));
- ZeroMemory(p, sizeof(*p));
-
- if(prompt) {
- cb_prompt += sizeof(wchar_t);
- p->prompt = PMALLOC(cb_prompt);
- StringCbCopy(p->prompt, cb_prompt, prompt);
- }
-
- if(def && cb_def > 0) {
- cb_def += sizeof(wchar_t);
- p->def = PMALLOC(cb_def);
- StringCbCopy(p->def, cb_def, def);
- }
-
- p->value = PMALLOC(KHUI_MAXCB_PROMPT_VALUE);
- ZeroMemory(p->value, KHUI_MAXCB_PROMPT_VALUE);
-
- p->type = type;
- p->flags = flags;
- p->index = idx;
-
- return p;
-}
-
-static void
-cw_free_prompt(khui_new_creds_prompt * p) {
- size_t cb;
-
- if(p->prompt) {
- if(SUCCEEDED(StringCbLength(p->prompt, KHUI_MAXCB_PROMPT, &cb)))
- SecureZeroMemory(p->prompt, cb);
- PFREE(p->prompt);
- }
-
- if(p->def) {
- if(SUCCEEDED(StringCbLength(p->def, KHUI_MAXCB_PROMPT, &cb)))
- SecureZeroMemory(p->def, cb);
- PFREE(p->def);
- }
-
- if(p->value) {
- if(SUCCEEDED(StringCbLength(p->value, KHUI_MAXCB_PROMPT_VALUE, &cb)))
- SecureZeroMemory(p->value, cb);
- PFREE(p->value);
- }
-
- PFREE(p);
-}
-
-static void
-cw_free_prompts(khui_new_creds * c)
-{
- khm_size i;
-
- if(c->banner != NULL) {
- PFREE(c->banner);
- c->banner = NULL;
- }
-
- if(c->pname != NULL) {
- PFREE(c->pname);
- c->pname = NULL;
- }
-
- for(i=0;i < c->n_prompts; i++) {
- if(c->prompts[i]) {
- cw_free_prompt(c->prompts[i]);
- c->prompts[i] = NULL;
- }
- }
-
- if(c->prompts != NULL) {
- PFREE(c->prompts);
- c->prompts = NULL;
- }
-
- c->nc_prompts = 0;
- c->n_prompts = 0;
-}
-
-KHMEXP khm_int32 KHMAPI
-khui_cw_clear_prompts(khui_new_creds * c)
-{
- /* the WMNC_CLEAR_PROMPT message needs to be sent before freeing
- the prompts, because the prompts structure still holds the
- window handles for the custom prompt controls. */
- SendMessage(c->hwnd, KHUI_WM_NC_NOTIFY,
- MAKEWPARAM(0,WMNC_CLEAR_PROMPTS), (LPARAM) c);
-
- EnterCriticalSection(&c->cs);
- cw_free_prompts(c);
- LeaveCriticalSection(&c->cs);
-
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP khm_int32 KHMAPI
-khui_cw_begin_custom_prompts(khui_new_creds * c,
- khm_size n_prompts,
- wchar_t * banner,
- wchar_t * pname)
-{
- size_t cb;
-
- PostMessage(c->hwnd, KHUI_WM_NC_NOTIFY,
- MAKEWPARAM(0,WMNC_CLEAR_PROMPTS), (LPARAM) c);
-
- EnterCriticalSection(&c->cs);
-#ifdef DEBUG
- assert(c->n_prompts == 0);
-#endif
- cw_free_prompts(c);
-
- if(SUCCEEDED(StringCbLength(banner, KHUI_MAXCB_BANNER, &cb)) &&
- cb > 0) {
- cb += sizeof(wchar_t);
- c->banner = PMALLOC(cb);
- StringCbCopy(c->banner, cb, banner);
- } else {
- c->banner = NULL;
- }
-
- if(SUCCEEDED(StringCbLength(pname, KHUI_MAXCB_PNAME, &cb)) &&
- cb > 0) {
-
- cb += sizeof(wchar_t);
- c->pname = PMALLOC(cb);
- StringCbCopy(c->pname, cb, pname);
-
- } else {
-
- c->pname = NULL;
-
- }
-
- if(n_prompts > 0) {
- c->prompts = PMALLOC(sizeof(*(c->prompts)) * n_prompts);
- ZeroMemory(c->prompts, sizeof(*(c->prompts)) * n_prompts);
- c->nc_prompts = n_prompts;
- c->n_prompts = 0;
-
- } else {
-
- c->prompts = NULL;
- c->n_prompts = 0;
- c->nc_prompts = 0;
-
- PostMessage(c->hwnd, KHUI_WM_NC_NOTIFY,
- MAKEWPARAM(0, WMNC_SET_PROMPTS), (LPARAM) c);
- }
-
- LeaveCriticalSection(&c->cs);
-
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP khm_int32 KHMAPI
-khui_cw_add_prompt(khui_new_creds * c,
- khm_int32 type,
- wchar_t * prompt,
- wchar_t * def,
- khm_int32 flags)
-{
- khui_new_creds_prompt * p;
-
- if(c->nc_prompts == 0 ||
- c->n_prompts == c->nc_prompts)
- return KHM_ERROR_INVALID_OPERATION;
-
-#ifdef DEBUG
- assert(c->prompts != NULL);
-#endif
-
- EnterCriticalSection(&c->cs);
- p = cw_create_prompt(c->n_prompts, type, prompt, def, flags);
- if(p == NULL) {
- LeaveCriticalSection(&c->cs);
- return KHM_ERROR_INVALID_PARAM;
- }
- c->prompts[c->n_prompts++] = p;
- LeaveCriticalSection(&c->cs);
-
- if(c->n_prompts == c->nc_prompts) {
- PostMessage(c->hwnd, KHUI_WM_NC_NOTIFY,
- MAKEWPARAM(0, WMNC_SET_PROMPTS), (LPARAM) c);
- /* once we are done adding prompts, switch to the auth
- panel */
-#if 0
- /* Actually, don't. Doing so can mean an unexpected panel
- switch if fiddling on some other panel causes a change in
- custom prompts. */
- SendMessage(c->hwnd, KHUI_WM_NC_NOTIFY,
- MAKEWPARAM(0, WMNC_DIALOG_SWITCH_PANEL),
- (LPARAM) c);
-#endif
- }
-
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP khm_int32 KHMAPI
-khui_cw_get_prompt_count(khui_new_creds * c,
- khm_size * np) {
-
- EnterCriticalSection(&c->cs);
- *np = c->n_prompts;
- LeaveCriticalSection(&c->cs);
-
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP khm_int32 KHMAPI
-khui_cw_get_prompt(khui_new_creds * c,
- khm_size idx,
- khui_new_creds_prompt ** prompt)
-{
- khm_int32 rv;
-
- EnterCriticalSection(&c->cs);
- if(c->n_prompts <= idx ||
- c->prompts == NULL) {
-
- rv = KHM_ERROR_OUT_OF_BOUNDS;
- *prompt = NULL;
- } else {
-
- *prompt = c->prompts[idx];
- rv = KHM_ERROR_SUCCESS;
- }
- LeaveCriticalSection(&c->cs);
-
- return rv;
-}
-
-void
-khuiint_trim_str(wchar_t * s, khm_size cch) {
- wchar_t * c, * last_ws;
-
- for (c = s; *c && iswspace(*c) && ((khm_size)(c - s)) < cch; c++);
-
- if (((khm_size)(c - s)) >= cch)
- return;
-
- if (c != s && ((khm_size)(c - s)) < cch) {
-#if _MSC_VER >= 1400
- wmemmove_s(s, cch, c, cch - ((khm_size)(c - s)));
-#else
- memmove(s, c, (cch - ((khm_size)(c - s)))* sizeof(wchar_t));
-#endif
- }
-
- last_ws = NULL;
- for (c = s; *c && ((khm_size)(c - s)) < cch; c++) {
- if (!iswspace(*c))
- last_ws = NULL;
- else if (last_ws == NULL)
- last_ws = c;
- }
-
- if (last_ws)
- *last_ws = L'\0';
-}
-
-KHMEXP khm_int32 KHMAPI
-khui_cw_sync_prompt_values(khui_new_creds * c)
-{
- khm_size i;
- khm_size n;
- HWND hw;
- wchar_t tmpbuf[KHUI_MAXCCH_PROMPT_VALUE];
-
- EnterCriticalSection(&c->cs);
- redo_loop:
- n = c->n_prompts;
- for(i=0; i<n; i++) {
- khui_new_creds_prompt * p;
-
- p = c->prompts[i];
- if(p->hwnd_edit) {
- hw = p->hwnd_edit;
- LeaveCriticalSection(&c->cs);
-
- GetWindowText(hw, tmpbuf, ARRAYLENGTH(tmpbuf));
- khuiint_trim_str(tmpbuf, ARRAYLENGTH(tmpbuf));
-
- EnterCriticalSection(&c->cs);
- if (n != c->n_prompts)
- goto redo_loop;
- SecureZeroMemory(p->value, KHUI_MAXCB_PROMPT_VALUE);
- StringCchCopy(p->value, KHUI_MAXCCH_PROMPT_VALUE,
- tmpbuf);
- }
- }
- LeaveCriticalSection(&c->cs);
-
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP khm_int32 KHMAPI
-khui_cw_get_prompt_value(khui_new_creds * c,
- khm_size idx,
- wchar_t * buf,
- khm_size *cbbuf)
-{
- khui_new_creds_prompt * p;
- khm_int32 rv;
- size_t cb;
-
- rv = khui_cw_get_prompt(c, idx, &p);
- if(KHM_FAILED(rv))
- return rv;
-
- EnterCriticalSection(&c->cs);
-
- if(FAILED(StringCbLength(p->value, KHUI_MAXCB_PROMPT_VALUE, &cb))) {
- *cbbuf = 0;
- if(buf != NULL)
- *buf = 0;
- LeaveCriticalSection(&c->cs);
- return KHM_ERROR_SUCCESS;
- }
- cb += sizeof(wchar_t);
-
- if(buf == NULL || *cbbuf < cb) {
- *cbbuf = cb;
- LeaveCriticalSection(&c->cs);
- return KHM_ERROR_TOO_LONG;
- }
-
- StringCbCopy(buf, *cbbuf, p->value);
- *cbbuf = cb;
- LeaveCriticalSection(&c->cs);
-
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP khm_int32 KHMAPI
-khui_cw_set_response(khui_new_creds * c,
- khm_int32 type,
- khm_int32 response)
-{
- khui_new_creds_by_type * t = NULL;
- EnterCriticalSection(&c->cs);
- khui_cw_find_type(c, type, &t);
- c->response |= response & KHUI_NCMASK_RESPONSE;
- if(t) {
- t->flags &= ~KHUI_NCMASK_RESULT;
- t->flags |= (response & KHUI_NCMASK_RESULT);
-
- if (!(response & KHUI_NC_RESPONSE_NOEXIT) &&
- !(response & KHUI_NC_RESPONSE_PENDING))
- t->flags |= KHUI_NC_RESPONSE_COMPLETED;
- }
- LeaveCriticalSection(&c->cs);
- return KHM_ERROR_SUCCESS;
-}
-
-/* only called from a identity provider callback */
-KHMEXP khm_int32 KHMAPI
-khui_cw_add_control_row(khui_new_creds * c,
- HWND label,
- HWND input,
- khui_control_size size)
-{
- if (c && c->hwnd) {
- khui_control_row row;
-
- row.label = label;
- row.input = input;
- row.size = size;
-
- SendMessage(c->hwnd,
- KHUI_WM_NC_NOTIFY,
- MAKEWPARAM(0, WMNC_ADD_CONTROL_ROW),
- (LPARAM) &row);
-
- return KHM_ERROR_SUCCESS;
- } else {
- return KHM_ERROR_INVALID_PARAM;
- }
-}
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<khuidefs.h>
+#include<utils.h>
+#include<assert.h>
+
+#include<strsafe.h>
+
+#define CW_ALLOC_INCR 8
+
+static void cw_free_prompts(khui_new_creds * c);
+
+static void cw_free_prompt(khui_new_creds_prompt * p);
+
+static khui_new_creds_prompt *
+cw_create_prompt(
+ khm_size idx,
+ khm_int32 type,
+ wchar_t * prompt,
+ wchar_t * def,
+ khm_int32 flags);
+
+KHMEXP khm_int32 KHMAPI
+khui_cw_create_cred_blob(khui_new_creds ** ppnc)
+{
+ khui_new_creds * c;
+
+ c = PMALLOC(sizeof(*c));
+ ZeroMemory(c, sizeof(*c));
+
+ c->magic = KHUI_NC_MAGIC;
+ InitializeCriticalSection(&c->cs);
+ c->result = KHUI_NC_RESULT_CANCEL;
+ c->mode = KHUI_NC_MODE_MINI;
+
+ khui_context_create(&c->ctx, KHUI_SCOPE_NONE, NULL, KCDB_CREDTYPE_INVALID, NULL);
+
+ *ppnc = c;
+
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP khm_int32 KHMAPI
+khui_cw_destroy_cred_blob(khui_new_creds *c)
+{
+ khm_size i;
+ size_t len;
+ EnterCriticalSection(&c->cs);
+ for(i=0;i<c->n_identities;i++) {
+ kcdb_identity_release(c->identities[i]);
+ }
+ cw_free_prompts(c);
+ khui_context_release(&c->ctx);
+ LeaveCriticalSection(&c->cs);
+ DeleteCriticalSection(&c->cs);
+
+ if (c->password) {
+ len = wcslen(c->password);
+ SecureZeroMemory(c->password, sizeof(wchar_t) * len);
+ PFREE(c->password);
+ }
+
+ if (c->identities)
+ PFREE(c->identities);
+
+ if (c->types)
+ PFREE(c->types);
+
+ if (c->type_subs)
+ PFREE(c->type_subs);
+
+ if (c->window_title)
+ PFREE(c->window_title);
+
+ PFREE(c);
+
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP khm_int32 KHMAPI
+khui_cw_lock_nc(khui_new_creds * c)
+{
+ EnterCriticalSection(&c->cs);
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP khm_int32 KHMAPI
+khui_cw_unlock_nc(khui_new_creds * c)
+{
+ LeaveCriticalSection(&c->cs);
+ return KHM_ERROR_SUCCESS;
+}
+
+#define NC_N_IDENTITIES 4
+
+KHMEXP khm_int32 KHMAPI
+khui_cw_add_identity(khui_new_creds * c,
+ khm_handle id)
+{
+ if(id == NULL)
+ return KHM_ERROR_SUCCESS; /* we return success because adding
+ a NULL id is equivalent to adding
+ nothing. */
+ EnterCriticalSection(&(c->cs));
+
+ if(c->identities == NULL) {
+ c->nc_identities = NC_N_IDENTITIES;
+ c->identities = PMALLOC(sizeof(*(c->identities)) *
+ c->nc_identities);
+ c->n_identities = 0;
+ } else if(c->n_identities + 1 > c->nc_identities) {
+ khm_handle * ni;
+
+ c->nc_identities = UBOUNDSS(c->n_identities + 1,
+ NC_N_IDENTITIES,
+ NC_N_IDENTITIES);
+ ni = PMALLOC(sizeof(*(c->identities)) * c->nc_identities);
+ memcpy(ni, c->identities,
+ sizeof(*(c->identities)) * c->n_identities);
+ PFREE(c->identities);
+ c->identities = ni;
+ }
+
+ kcdb_identity_hold(id);
+ c->identities[c->n_identities++] = id;
+ LeaveCriticalSection(&(c->cs));
+
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP khm_int32 KHMAPI
+khui_cw_set_primary_id(khui_new_creds * c,
+ khm_handle id)
+{
+ khm_size i;
+ khm_int32 rv;
+
+ EnterCriticalSection(&c->cs);
+
+ /* no change */
+ if((c->n_identities > 0 && c->identities[0] == id) ||
+ (c->n_identities == 0 && id == NULL)) {
+ LeaveCriticalSection(&c->cs);
+ return KHM_ERROR_SUCCESS;
+ }
+
+ for(i=0; i<c->n_identities; i++) {
+ kcdb_identity_release(c->identities[i]);
+ }
+ c->n_identities = 0;
+
+ LeaveCriticalSection(&(c->cs));
+ rv = khui_cw_add_identity(c,id);
+ if(c->hwnd != NULL) {
+ PostMessage(c->hwnd, KHUI_WM_NC_NOTIFY,
+ MAKEWPARAM(0, WMNC_IDENTITY_CHANGE), 0);
+ }
+ return rv;
+}
+
+KHMEXP khm_int32 KHMAPI
+khui_cw_add_type(khui_new_creds * c,
+ khui_new_creds_by_type * t)
+{
+ EnterCriticalSection(&c->cs);
+
+ if(c->n_types >= KHUI_MAX_NCTYPES) {
+ LeaveCriticalSection(&c->cs);
+ return KHM_ERROR_OUT_OF_BOUNDS;
+ }
+
+ if(c->types == NULL) {
+ c->nc_types = CW_ALLOC_INCR;
+ c->types = PMALLOC(sizeof(*(c->types)) * c->nc_types);
+ c->type_subs = PMALLOC(sizeof(*(c->type_subs)) * c->nc_types);
+ c->n_types = 0;
+ }
+
+ if(c->nc_types < c->n_types + 1) {
+ void * t;
+ khm_size n;
+
+ n = UBOUNDSS(c->n_types + 1, CW_ALLOC_INCR, CW_ALLOC_INCR);
+
+ t = PMALLOC(sizeof(*(c->types)) * n);
+ memcpy(t, (void *) c->types, sizeof(*(c->types)) * c->n_types);
+ PFREE(c->types);
+ c->types = t;
+
+ t = PMALLOC(sizeof(*(c->type_subs)) * n);
+ memcpy(t, (void *) c->type_subs, sizeof(*(c->type_subs)) * c->n_types);
+ PFREE(c->type_subs);
+ c->type_subs = t;
+
+ c->nc_types = n;
+ }
+
+ c->type_subs[c->n_types] = kcdb_credtype_get_sub(t->type);
+ c->types[c->n_types++] = t;
+ t->nc = c;
+ LeaveCriticalSection(&c->cs);
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP khm_int32 KHMAPI
+khui_cw_del_type(khui_new_creds * c,
+ khm_int32 type_id)
+{
+ khm_size i;
+
+ EnterCriticalSection(&c->cs);
+ for(i=0; i < c->n_types; i++) {
+ if(c->types[i]->type == type_id)
+ break;
+ }
+ if(i >= c->n_types) {
+ LeaveCriticalSection(&c->cs);
+ return KHM_ERROR_NOT_FOUND;
+ }
+ c->n_types--;
+ for(;i < c->n_types; i++) {
+ c->types[i] = c->types[i+1];
+ c->type_subs[i] = c->type_subs[i+1];
+ }
+ LeaveCriticalSection(&c->cs);
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP khm_int32 KHMAPI
+khui_cw_find_type(khui_new_creds * c,
+ khm_int32 type,
+ khui_new_creds_by_type **t)
+{
+ khm_size i;
+
+ EnterCriticalSection(&c->cs);
+ *t = NULL;
+ for(i=0;i<c->n_types;i++) {
+ if(c->types[i]->type == type) {
+ *t = c->types[i];
+ break;
+ }
+ }
+ LeaveCriticalSection(&c->cs);
+
+ if(*t)
+ return KHM_ERROR_SUCCESS;
+ return KHM_ERROR_NOT_FOUND;
+}
+
+
+KHMEXP khm_int32 KHMAPI
+khui_cw_enable_type(khui_new_creds * c,
+ khm_int32 type,
+ khm_boolean enable)
+{
+ khui_new_creds_by_type * t = NULL;
+ BOOL delta = FALSE;
+
+ EnterCriticalSection(&c->cs);
+ if(KHM_SUCCEEDED(khui_cw_find_type(c, type, &t))) {
+ if(enable) {
+ delta = t->flags & KHUI_NCT_FLAG_DISABLED;
+ t->flags &= ~KHUI_NCT_FLAG_DISABLED;
+ }
+ else {
+ delta = !(t->flags & KHUI_NCT_FLAG_DISABLED);
+ t->flags |= KHUI_NCT_FLAG_DISABLED;
+ }
+ }
+ LeaveCriticalSection(&c->cs);
+
+ if(delta)
+ PostMessage(c->hwnd, KHUI_WM_NC_NOTIFY, MAKEWPARAM(0,WMNC_TYPE_STATE), (LPARAM) type);
+
+ return (t)?KHM_ERROR_SUCCESS:KHM_ERROR_NOT_FOUND;
+}
+
+KHMEXP khm_boolean KHMAPI
+khui_cw_type_succeeded(khui_new_creds * c,
+ khm_int32 type)
+{
+ khui_new_creds_by_type * t;
+ khm_boolean s;
+
+ EnterCriticalSection(&c->cs);
+ if(KHM_SUCCEEDED(khui_cw_find_type(c, type, &t))) {
+ s = (t->flags & KHUI_NCT_FLAG_PROCESSED) && !(t->flags & KHUI_NC_RESPONSE_FAILED);
+ } else {
+ s = FALSE;
+ }
+ LeaveCriticalSection(&c->cs);
+
+ return s;
+}
+
+static khui_new_creds_prompt *
+cw_create_prompt(khm_size idx,
+ khm_int32 type,
+ wchar_t * prompt,
+ wchar_t * def,
+ khm_int32 flags)
+{
+ khui_new_creds_prompt * p;
+ size_t cb_prompt = 0;
+ size_t cb_def = 0;
+
+ if(prompt && FAILED(StringCbLength(prompt, KHUI_MAXCB_PROMPT, &cb_prompt)))
+ return NULL;
+ if(def && FAILED(StringCbLength(def, KHUI_MAXCB_PROMPT_VALUE, &cb_def)))
+ return NULL;
+
+ p = PMALLOC(sizeof(*p));
+ ZeroMemory(p, sizeof(*p));
+
+ if(prompt) {
+ cb_prompt += sizeof(wchar_t);
+ p->prompt = PMALLOC(cb_prompt);
+ StringCbCopy(p->prompt, cb_prompt, prompt);
+ }
+
+ if(def && cb_def > 0) {
+ cb_def += sizeof(wchar_t);
+ p->def = PMALLOC(cb_def);
+ StringCbCopy(p->def, cb_def, def);
+ }
+
+ p->value = PMALLOC(KHUI_MAXCB_PROMPT_VALUE);
+ ZeroMemory(p->value, KHUI_MAXCB_PROMPT_VALUE);
+
+ p->type = type;
+ p->flags = flags;
+ p->index = idx;
+
+ return p;
+}
+
+static void
+cw_free_prompt(khui_new_creds_prompt * p) {
+ size_t cb;
+
+ if(p->prompt) {
+ if(SUCCEEDED(StringCbLength(p->prompt, KHUI_MAXCB_PROMPT, &cb)))
+ SecureZeroMemory(p->prompt, cb);
+ PFREE(p->prompt);
+ }
+
+ if(p->def) {
+ if(SUCCEEDED(StringCbLength(p->def, KHUI_MAXCB_PROMPT, &cb)))
+ SecureZeroMemory(p->def, cb);
+ PFREE(p->def);
+ }
+
+ if(p->value) {
+ if(SUCCEEDED(StringCbLength(p->value, KHUI_MAXCB_PROMPT_VALUE, &cb)))
+ SecureZeroMemory(p->value, cb);
+ PFREE(p->value);
+ }
+
+ PFREE(p);
+}
+
+static void
+cw_free_prompts(khui_new_creds * c)
+{
+ khm_size i;
+
+ if(c->banner != NULL) {
+ PFREE(c->banner);
+ c->banner = NULL;
+ }
+
+ if(c->pname != NULL) {
+ PFREE(c->pname);
+ c->pname = NULL;
+ }
+
+ for(i=0;i < c->n_prompts; i++) {
+ if(c->prompts[i]) {
+ cw_free_prompt(c->prompts[i]);
+ c->prompts[i] = NULL;
+ }
+ }
+
+ if(c->prompts != NULL) {
+ PFREE(c->prompts);
+ c->prompts = NULL;
+ }
+
+ c->nc_prompts = 0;
+ c->n_prompts = 0;
+}
+
+KHMEXP khm_int32 KHMAPI
+khui_cw_clear_prompts(khui_new_creds * c)
+{
+ /* the WMNC_CLEAR_PROMPT message needs to be sent before freeing
+ the prompts, because the prompts structure still holds the
+ window handles for the custom prompt controls. */
+ SendMessage(c->hwnd, KHUI_WM_NC_NOTIFY,
+ MAKEWPARAM(0,WMNC_CLEAR_PROMPTS), (LPARAM) c);
+
+ EnterCriticalSection(&c->cs);
+ cw_free_prompts(c);
+ LeaveCriticalSection(&c->cs);
+
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP khm_int32 KHMAPI
+khui_cw_begin_custom_prompts(khui_new_creds * c,
+ khm_size n_prompts,
+ wchar_t * banner,
+ wchar_t * pname)
+{
+ size_t cb;
+
+ PostMessage(c->hwnd, KHUI_WM_NC_NOTIFY,
+ MAKEWPARAM(0,WMNC_CLEAR_PROMPTS), (LPARAM) c);
+
+ EnterCriticalSection(&c->cs);
+#ifdef DEBUG
+ assert(c->n_prompts == 0);
+#endif
+ cw_free_prompts(c);
+
+ if(SUCCEEDED(StringCbLength(banner, KHUI_MAXCB_BANNER, &cb)) &&
+ cb > 0) {
+ cb += sizeof(wchar_t);
+ c->banner = PMALLOC(cb);
+ StringCbCopy(c->banner, cb, banner);
+ } else {
+ c->banner = NULL;
+ }
+
+ if(SUCCEEDED(StringCbLength(pname, KHUI_MAXCB_PNAME, &cb)) &&
+ cb > 0) {
+
+ cb += sizeof(wchar_t);
+ c->pname = PMALLOC(cb);
+ StringCbCopy(c->pname, cb, pname);
+
+ } else {
+
+ c->pname = NULL;
+
+ }
+
+ if(n_prompts > 0) {
+ c->prompts = PMALLOC(sizeof(*(c->prompts)) * n_prompts);
+ ZeroMemory(c->prompts, sizeof(*(c->prompts)) * n_prompts);
+ c->nc_prompts = n_prompts;
+ c->n_prompts = 0;
+
+ } else {
+
+ c->prompts = NULL;
+ c->n_prompts = 0;
+ c->nc_prompts = 0;
+
+ PostMessage(c->hwnd, KHUI_WM_NC_NOTIFY,
+ MAKEWPARAM(0, WMNC_SET_PROMPTS), (LPARAM) c);
+ }
+
+ LeaveCriticalSection(&c->cs);
+
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP khm_int32 KHMAPI
+khui_cw_add_prompt(khui_new_creds * c,
+ khm_int32 type,
+ wchar_t * prompt,
+ wchar_t * def,
+ khm_int32 flags)
+{
+ khui_new_creds_prompt * p;
+
+ if(c->nc_prompts == 0 ||
+ c->n_prompts == c->nc_prompts)
+ return KHM_ERROR_INVALID_OPERATION;
+
+#ifdef DEBUG
+ assert(c->prompts != NULL);
+#endif
+
+ EnterCriticalSection(&c->cs);
+ p = cw_create_prompt(c->n_prompts, type, prompt, def, flags);
+ if(p == NULL) {
+ LeaveCriticalSection(&c->cs);
+ return KHM_ERROR_INVALID_PARAM;
+ }
+ c->prompts[c->n_prompts++] = p;
+ LeaveCriticalSection(&c->cs);
+
+ if(c->n_prompts == c->nc_prompts) {
+ PostMessage(c->hwnd, KHUI_WM_NC_NOTIFY,
+ MAKEWPARAM(0, WMNC_SET_PROMPTS), (LPARAM) c);
+ /* once we are done adding prompts, switch to the auth
+ panel */
+#if 0
+ /* Actually, don't. Doing so can mean an unexpected panel
+ switch if fiddling on some other panel causes a change in
+ custom prompts. */
+ SendMessage(c->hwnd, KHUI_WM_NC_NOTIFY,
+ MAKEWPARAM(0, WMNC_DIALOG_SWITCH_PANEL),
+ (LPARAM) c);
+#endif
+ }
+
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP khm_int32 KHMAPI
+khui_cw_get_prompt_count(khui_new_creds * c,
+ khm_size * np) {
+
+ EnterCriticalSection(&c->cs);
+ *np = c->n_prompts;
+ LeaveCriticalSection(&c->cs);
+
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP khm_int32 KHMAPI
+khui_cw_get_prompt(khui_new_creds * c,
+ khm_size idx,
+ khui_new_creds_prompt ** prompt)
+{
+ khm_int32 rv;
+
+ EnterCriticalSection(&c->cs);
+ if(c->n_prompts <= idx ||
+ c->prompts == NULL) {
+
+ rv = KHM_ERROR_OUT_OF_BOUNDS;
+ *prompt = NULL;
+ } else {
+
+ *prompt = c->prompts[idx];
+ rv = KHM_ERROR_SUCCESS;
+ }
+ LeaveCriticalSection(&c->cs);
+
+ return rv;
+}
+
+void
+khuiint_trim_str(wchar_t * s, khm_size cch) {
+ wchar_t * c, * last_ws;
+
+ for (c = s; *c && iswspace(*c) && ((khm_size)(c - s)) < cch; c++);
+
+ if (((khm_size)(c - s)) >= cch)
+ return;
+
+ if (c != s && ((khm_size)(c - s)) < cch) {
+#if _MSC_VER >= 1400
+ wmemmove_s(s, cch, c, cch - ((khm_size)(c - s)));
+#else
+ memmove(s, c, (cch - ((khm_size)(c - s)))* sizeof(wchar_t));
+#endif
+ }
+
+ last_ws = NULL;
+ for (c = s; *c && ((khm_size)(c - s)) < cch; c++) {
+ if (!iswspace(*c))
+ last_ws = NULL;
+ else if (last_ws == NULL)
+ last_ws = c;
+ }
+
+ if (last_ws)
+ *last_ws = L'\0';
+}
+
+KHMEXP khm_int32 KHMAPI
+khui_cw_sync_prompt_values(khui_new_creds * c)
+{
+ khm_size i;
+ khm_size n;
+ HWND hw;
+ wchar_t tmpbuf[KHUI_MAXCCH_PROMPT_VALUE];
+
+ EnterCriticalSection(&c->cs);
+ redo_loop:
+ n = c->n_prompts;
+ for(i=0; i<n; i++) {
+ khui_new_creds_prompt * p;
+
+ p = c->prompts[i];
+ if(p->hwnd_edit) {
+ hw = p->hwnd_edit;
+ LeaveCriticalSection(&c->cs);
+
+ GetWindowText(hw, tmpbuf, ARRAYLENGTH(tmpbuf));
+ khuiint_trim_str(tmpbuf, ARRAYLENGTH(tmpbuf));
+
+ EnterCriticalSection(&c->cs);
+ if (n != c->n_prompts)
+ goto redo_loop;
+ SecureZeroMemory(p->value, KHUI_MAXCB_PROMPT_VALUE);
+ StringCchCopy(p->value, KHUI_MAXCCH_PROMPT_VALUE,
+ tmpbuf);
+ }
+ }
+ LeaveCriticalSection(&c->cs);
+
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP khm_int32 KHMAPI
+khui_cw_get_prompt_value(khui_new_creds * c,
+ khm_size idx,
+ wchar_t * buf,
+ khm_size *cbbuf)
+{
+ khui_new_creds_prompt * p;
+ khm_int32 rv;
+ size_t cb;
+
+ rv = khui_cw_get_prompt(c, idx, &p);
+ if(KHM_FAILED(rv))
+ return rv;
+
+ EnterCriticalSection(&c->cs);
+
+ if(FAILED(StringCbLength(p->value, KHUI_MAXCB_PROMPT_VALUE, &cb))) {
+ *cbbuf = 0;
+ if(buf != NULL)
+ *buf = 0;
+ LeaveCriticalSection(&c->cs);
+ return KHM_ERROR_SUCCESS;
+ }
+ cb += sizeof(wchar_t);
+
+ if(buf == NULL || *cbbuf < cb) {
+ *cbbuf = cb;
+ LeaveCriticalSection(&c->cs);
+ return KHM_ERROR_TOO_LONG;
+ }
+
+ StringCbCopy(buf, *cbbuf, p->value);
+ *cbbuf = cb;
+ LeaveCriticalSection(&c->cs);
+
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP khm_int32 KHMAPI
+khui_cw_set_response(khui_new_creds * c,
+ khm_int32 type,
+ khm_int32 response)
+{
+ khui_new_creds_by_type * t = NULL;
+ EnterCriticalSection(&c->cs);
+ khui_cw_find_type(c, type, &t);
+ c->response |= response & KHUI_NCMASK_RESPONSE;
+ if(t) {
+ t->flags &= ~KHUI_NCMASK_RESULT;
+ t->flags |= (response & KHUI_NCMASK_RESULT);
+
+ if (!(response & KHUI_NC_RESPONSE_NOEXIT) &&
+ !(response & KHUI_NC_RESPONSE_PENDING))
+ t->flags |= KHUI_NC_RESPONSE_COMPLETED;
+ }
+ LeaveCriticalSection(&c->cs);
+ return KHM_ERROR_SUCCESS;
+}
+
+/* only called from a identity provider callback */
+KHMEXP khm_int32 KHMAPI
+khui_cw_add_control_row(khui_new_creds * c,
+ HWND label,
+ HWND input,
+ khui_control_size size)
+{
+ if (c && c->hwnd) {
+ khui_control_row row;
+
+ row.label = label;
+ row.input = input;
+ row.size = size;
+
+ SendMessage(c->hwnd,
+ KHUI_WM_NC_NOTIFY,
+ MAKEWPARAM(0, WMNC_ADD_CONTROL_ROW),
+ (LPARAM) &row);
+
+ return KHM_ERROR_SUCCESS;
+ } else {
+ return KHM_ERROR_INVALID_PARAM;
+ }
+}
diff --git a/src/windows/identity/uilib/intaction.h b/src/windows/identity/uilib/intaction.h
index 44348b9bbb..2b7aa973a3 100644
--- a/src/windows/identity/uilib/intaction.h
+++ b/src/windows/identity/uilib/intaction.h
@@ -1,108 +1,108 @@
-/*
- * Copyright (c) 2007 Secure Endpoints Inc.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#ifndef __NETIDMGR_ACTION_H_INTERNAL
-#define __NETIDMGR_ACTION_H_INTERNAL
-
-/* Internal declarations for exports and data structured used in
- nidmgr32.dll and netidmgr.exe */
-
-extern HWND khui_hwnd_main;
-
-typedef struct tag_khui_ui_callback_data {
- khm_int32 magic;
- khm_ui_callback cb;
- void * rock;
- khm_int32 rv;
-} khui_ui_callback_data;
-
-#define KHUI_UICBDATA_MAGIC 0x8a08572a
-
-/*! \addtogroup khui_actions
-@{ */
-
-/*! \brief An action */
-typedef struct tag_khui_action {
- khm_int32 cmd; /*!< action identifier */
- khm_int32 type; /*!< combination of KHUI_ACTIONTYPE_* */
- wchar_t * name; /*!< name for named actions. NULL if
- not named. */
-
- /* The following fields are only for use by NetIDMgr */
- khm_int16 ib_normal; /*!< (internal) normal bitmap (index) (toolbar sized icon) */
- khm_int16 ib_hot; /*!< (internal) hot bitmap (index) (toolbar sized icon) */
- khm_int16 ib_disabled; /*!< (internal) disabled bitmap (index) (toolbar sized icon) */
-
- khm_int16 ib_icon; /*!< (internal) index of small (16x16) icon (for menu) (small icon) */
- khm_int16 ib_icon_dis; /*!< (internal) index of disabled (greyed) icon (small icon) */
-
- khm_int16 is_caption; /*!< (internal) index of string resource for caption */
- khm_int16 is_tooltip; /*!< (internal) same for description / tooltip */
- khm_int16 ih_topic; /*!< (internal) help topic */
-
- /* The following fields are specified for custom actions */
- wchar_t * caption; /*!< Caption (localized) (limited by
- KHUI_MAXCCH_SHORT_DESC). The
- caption is used for representing the
- action in menus and toolbars. */
- wchar_t * tooltip; /*!< Tooltip (localized) (limited by
- KHUI_MAXCCH_SHORT_DESC). If this is
- specified, whenever the user hovers
- over the menu item or toolbar button
- representing the action, the tooltip
- will be displayed either on a
- tooltip window or in the status
- bar. */
- khm_handle listener; /*!< Listener of this action. Should be
- a handle to a message
- subscription. When the action is
- invoked, a message of type
- ::KMSG_ACT and subtype
- ::KMSG_ACT_ACTIVATE will be posted
- to this subscriber. The \a uparam
- parameter of the message will have
- the identifier of the action. */
- void * data; /*!< User data for custom action. This
- field is not used by the UI library.
- It is reserved for plugins to store
- data that is specific for this
- action. The data that's passed in
- in the \a userdata parameter to
- khui_action_create() will be stored
- here and can be retrieved by calling
- khui_action_get_data(). */
- void * reserved1; /*!< Reserved. */
- void * reserved2; /*!< Reserved. */
- void * reserved3; /*!< Reserved. */
-
- /* For all actions */
- int state; /*!< current state. combination of
- KHUI_ACTIONSTATE_* */
-} khui_action;
-
-/*@}*/
-
-#endif
+/*
+ * Copyright (c) 2007 Secure Endpoints Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __NETIDMGR_ACTION_H_INTERNAL
+#define __NETIDMGR_ACTION_H_INTERNAL
+
+/* Internal declarations for exports and data structured used in
+ nidmgr32.dll and netidmgr.exe */
+
+extern HWND khui_hwnd_main;
+
+typedef struct tag_khui_ui_callback_data {
+ khm_int32 magic;
+ khm_ui_callback cb;
+ void * rock;
+ khm_int32 rv;
+} khui_ui_callback_data;
+
+#define KHUI_UICBDATA_MAGIC 0x8a08572a
+
+/*! \addtogroup khui_actions
+@{ */
+
+/*! \brief An action */
+typedef struct tag_khui_action {
+ khm_int32 cmd; /*!< action identifier */
+ khm_int32 type; /*!< combination of KHUI_ACTIONTYPE_* */
+ wchar_t * name; /*!< name for named actions. NULL if
+ not named. */
+
+ /* The following fields are only for use by NetIDMgr */
+ khm_int16 ib_normal; /*!< (internal) normal bitmap (index) (toolbar sized icon) */
+ khm_int16 ib_hot; /*!< (internal) hot bitmap (index) (toolbar sized icon) */
+ khm_int16 ib_disabled; /*!< (internal) disabled bitmap (index) (toolbar sized icon) */
+
+ khm_int16 ib_icon; /*!< (internal) index of small (16x16) icon (for menu) (small icon) */
+ khm_int16 ib_icon_dis; /*!< (internal) index of disabled (greyed) icon (small icon) */
+
+ khm_int16 is_caption; /*!< (internal) index of string resource for caption */
+ khm_int16 is_tooltip; /*!< (internal) same for description / tooltip */
+ khm_int16 ih_topic; /*!< (internal) help topic */
+
+ /* The following fields are specified for custom actions */
+ wchar_t * caption; /*!< Caption (localized) (limited by
+ KHUI_MAXCCH_SHORT_DESC). The
+ caption is used for representing the
+ action in menus and toolbars. */
+ wchar_t * tooltip; /*!< Tooltip (localized) (limited by
+ KHUI_MAXCCH_SHORT_DESC). If this is
+ specified, whenever the user hovers
+ over the menu item or toolbar button
+ representing the action, the tooltip
+ will be displayed either on a
+ tooltip window or in the status
+ bar. */
+ khm_handle listener; /*!< Listener of this action. Should be
+ a handle to a message
+ subscription. When the action is
+ invoked, a message of type
+ ::KMSG_ACT and subtype
+ ::KMSG_ACT_ACTIVATE will be posted
+ to this subscriber. The \a uparam
+ parameter of the message will have
+ the identifier of the action. */
+ void * data; /*!< User data for custom action. This
+ field is not used by the UI library.
+ It is reserved for plugins to store
+ data that is specific for this
+ action. The data that's passed in
+ in the \a userdata parameter to
+ khui_action_create() will be stored
+ here and can be retrieved by calling
+ khui_action_get_data(). */
+ void * reserved1; /*!< Reserved. */
+ void * reserved2; /*!< Reserved. */
+ void * reserved3; /*!< Reserved. */
+
+ /* For all actions */
+ int state; /*!< current state. combination of
+ KHUI_ACTIONSTATE_* */
+} khui_action;
+
+/*@}*/
+
+#endif
diff --git a/src/windows/identity/uilib/khaction.h b/src/windows/identity/uilib/khaction.h
index 92fa7b0fa6..8182682c48 100644
--- a/src/windows/identity/uilib/khaction.h
+++ b/src/windows/identity/uilib/khaction.h
@@ -1,1005 +1,1005 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#ifndef __KHIMAIRA_ACTION_H
-#define __KHIMAIRA_ACTION_H
-
-/*! \addtogroup khui
- @{*/
-/*! \defgroup khui_actions Actions
- @{*/
-
-struct tag_khui_action;
-typedef struct tag_khui_action khui_action;
-
-/*! \brief Unknown action type
-
- Unknown action type.
- */
-#define KHUI_ACTIONTYPE_NONE 0
-
-/*! \brief A trigger type action
-
- A trigger action usually triggers some event, which is what pretty
- much every action does.
-*/
-#define KHUI_ACTIONTYPE_TRIGGER 1
-
-/*! \brief A toggle type action
-
- A toggle type action typically changes the CHECKED state of the
- action each time it is invoked.
- */
-#define KHUI_ACTIONTYPE_TOGGLE 2
-
-/*! \brief The action is enabled
-
- This is the default if no other state is specified. Just means
- not-disabled.
-*/
-#define KHUI_ACTIONSTATE_ENABLED 0
-
-/*! \brief The action is diabled */
-#define KHUI_ACTIONSTATE_DISABLED 1
-
-/*! \brief For toggle type actions, the action is checked */
-#define KHUI_ACTIONSTATE_CHECKED 2
-
-/*! \brief The action is hot
-
- Typically this means that the user is hovering the pointing device
- over a UI element representing the action.
- */
-#define KHUI_ACTIONSTATE_HOT 4
-
-/*! \brief The action has been marked for deletion
-
- For custom actions, this means that the custom action was deleted.
- The contents of the custom action fields are no longer valid.
- */
-#define KHUI_ACTIONSTATE_DELETED 8
-
-#ifdef NOEXPORT
-#define ACTION_SIMPLE(c,cap,des,top) \
- {c,KHUI_ACTIONTYPE_TRIGGER,NULL,0,0,0,0,0,cap,des,top,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0}
-
-#define ACTION_FULL(cmd,type,name,inormal,ihot,idis,isml,ismld,capt,toolt,topic,state) \
- {cmd,type,name,inormal,ihot,idis,isml,ismld,capt,toolt,topic,NULL,NULL,NULL,NULL,NULL,NULL,NULL,state}
-
-#define ACTION_SIMPLE_IMAGE(c,inormal, ihot, idis, isml, ismld,cap, des, top) \
- {c,KHUI_ACTIONTYPE_TRIGGER,NULL,inormal,ihot,idis,isml,ismld,cap,des,top,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0}
-#endif
-
-/*! \brief A reference to an action
-
- If the \a flags member has the KHUI_ACTIONREF_PACTION bit set,
- then the action is referenced by the \a p_action member of the
- union. Otherwise the identifier for the action is specified by \a
- action member.
-*/
-typedef struct tag_khui_action_ref {
- int flags; /*!< A combination of KHUI_ACTIONREF_* */
- union {
- khm_int32 action; /*!< The action identifier for the
- action that is being referrred to.
- Only valid if
- ::KHUI_ACTIONREF_PACTION is not set
- in \a flags. */
- khui_action * p_action; /*!< A pointer to the ::khui_action
- structure that describes the action
- that is being referred to. Only
- valid if ::KHUI_ACTIONREF_PACTION is
- set. */
- };
-} khui_action_ref;
-
-/*! \brief A submenu
-
- There should exist a menu associated with the action that is being
- referred. When displaying this action in a menu, the contents of
- the associated menu will appear as a submenu.
- */
-#define KHUI_ACTIONREF_SUBMENU 0x01
-
-/*! \brief Separator
-
- This is not an actual action, but represents a separator between
- actions. When displaying this action in a menu or a toolbar, a
- separating line will be drawn in place of this action. The \a
- action and \a p_action members of the structures are unused if
- this flag is set.
- */
-#define KHUI_ACTIONREF_SEP 0x02
-
-/*! \brief Action by reference
-
- The \a p_action member of the structure points to the
- ::khui_action structure that describes the action.
- */
-#define KHUI_ACTIONREF_PACTION 0x04
-
-#ifdef NOEXPORT
-/*! \brief Action should be freed
-
- \note This flag is reserved for internal use in the NetIDMgr
- application. Do not use.
- */
-#define KHUI_ACTIONREF_FREE_PACTION 0x08
-
-/*! \brief Marks the end of an action sequence
-
- \note THis flag is reserved for internal use in the NetIDMgr
- application. Do not use.
- */
-#define KHUI_ACTIONREF_END 0x10
-#endif
-
-/*! \brief The default action
-
- When this bit is set in an action reference that describes a menu,
- the menu item will be the default item and will be rendered
- differently from other menu items. Only useful when defining
- context menus. In general, it is good practice to place the
- default item at the top of a menu, although the UI library does
- not enforce this. This is purely meant as a rendering hint.
-
- Only one action is allowed to have this flag set. When an action
- is added to a menu using khui_menu_insert_action() or
- khui_menu_insert_paction() and this flag is set, all other menu
- items will be stripped of this flag.
- */
-#define KHUI_ACTIONREF_DEFAULT 0x20
-
-#ifdef NOEXPORT
-#define MENU_ACTION(c) {0,c}
-#define MENU_DEFACTION(c) {KHUI_ACTIONREF_DEFAULT, c}
-#define MENU_SUBMENU(s) {KHUI_ACTIONREF_SUBMENU,s}
-#define MENU_SEP() {KHUI_ACTIONREF_SEP,KHUI_MENU_SEP}
-#define MENU_END() {KHUI_ACTIONREF_END,KHUI_MENU_END}
-#endif
-
-/*! \brief Menu definition
-
- Use the khui_menu_create(), khui_menu_insert_action(),
- khui_menu_insert_paction(), khui_menu_get_size(),
- khui_menu_get_action() functions to create and manipulate custom
- menus. Do not manipulate this structure directly as doing so may
- cause inconsistencies in the UI library.
-*/
-typedef struct tag_khui_menu_def {
- khm_int32 cmd; /*!< Action associated with menu */
- khm_int32 state; /*!< combination of KHUI_MENUSTATE_* */
- khm_size n_items; /*!< The number of actions in the \a items
- list. If this is a custom menu, the
- ::KHUI_MENUSTATE_ALLOCD bit will be set,
- and the contents of this field will be
- valid. Otherwise, the contents of this
- field is ignored and the list of actions
- must be terminated with a
- ACTION_LIST_END action. */
- khm_size nc_items; /*!< max number of items in the buffer
- alocated for items. Ignored if
- ::KHUI_MENUSTATE_ALLOCD is not set in \a
- state. */
- khui_action_ref *items; /*!< Action list terminated by,
- ACTION_LIST_END. If \a n_items is set
- to a value other than -1, the list
- doesn't necessarily have to end with a
- ACTION_LIST_END. When constructing a
- menu using khui_menu_* functions, they
- will set the size of this list in the \a
- n_items member, and there will be no
- ACTION_LIST_END action to terminate the
- list. */
-} khui_menu_def;
-
-#ifdef NOEXPORT
-#define CONSTMENU(c,s,i) {c,s,-1,-1,i}
-#endif
-
-/*! \brief Unspecified menu
-
- Used when there is no single command associated with the entire
- menu, such as for ad-hoc context menus.
- */
-#define KHUI_MENU_NONE -3
-
-/*! \brief Menu end indicator
-
- For static or constant menus this indicates that this action marks
- the end of the list of actions which defined the menu. This is
- invalid if used in a dynamic menu (a menu with the
- ::KHUI_MENUSTATE_ALLOCD bit set).
- */
-#define KHUI_MENU_END -2
-
-/*! \brief Menu separator
-
- A separator for actions. When displaying a menu or showing a
- toolbar based on a menu definition, a separator is rendered as a
- bar separating the user interface elements for the actions on
- either side of this.
-*/
-#define KHUI_MENU_SEP -1
-
-/*! \brief Constant menu
-
- The contents of the menu cannot be modified (individual actions in
- the menu may be modified, but the order and the contents of the
- menu itself cannot be modified.
-
- This is the default if ::KHUI_MENUSTATE_ALLOCD is not specified.
- */
-#define KHUI_MENUSTATE_CONSTANT 0
-
-/*! \brief Variable menu
-
- The menu is dnamically allocated. The list of actions contained
- in the menu can be modified.
-*/
-#define KHUI_MENUSTATE_ALLOCD 1
-
-#ifdef NOEXPORT
-/* predefined system menu */
-#define KHUI_MENUSTATE_SYSTEM 2
-#endif
-
-#ifdef NOEXPORT
-
-/*! \brief Accelerator definition */
-typedef struct tag_khui_accel_def {
- int cmd;
- int mod;
- int key;
- int scope;
-} khui_accel_def;
-
-#define KHUI_ACCEL_SCOPE_GLOBAL 0
-
-extern khui_accel_def khui_accel_global[];
-extern int khui_n_accel_global;
-
-extern khui_action khui_actions[];
-extern int khui_n_actions;
-
-extern khui_menu_def khui_all_menus[];
-extern int khui_n_all_menus;
-
-#endif /* NOEXPORT */
-
-/* functions */
-
-/*! \brief Refresh the global action table
-
- Changes to system menus and toolbars may not be immediately
- reflected in the user interface. Calling this function forces the
- UI to reparse the action tables and menus and refresh the
- application menu bar and toolbars.
-
- */
-KHMEXP void KHMAPI
-khui_refresh_actions(void);
-
-/*! \brief Lock the action and menu tables
-
- This function, along with khui_action_unlock() is used to prevent
- changes from being made to shared menus and actions while they are
- being updated. In particular, changes to shared menus usually
- need to be done in a batch and may suffer corruption of other
- threads access or modify the menu while one thread is updating it.
- Operations on shared menus should always be done with the actions
- locked.
-*/
-KHMEXP void KHMAPI
-khui_action_lock(void);
-
-/*! \brief Unlock the action and menu tables
-
- Unlocks the action and menu tables after a call to
- khui_action_lock().
-
- \see khui_action_lock()
- */
-KHMEXP void KHMAPI
-khui_action_unlock(void);
-
-/*! \brief Create a new menu
-
- Creates a new menu. The returned data structure must be freed by
- a call to khui_menu_delete(). Custom menus that are created this
- way are not reference counted or maintained by the UI library.
- The caller is responsible for calling khui_menu_delete() when the
- data is no longer needed.
-
- Specifiying an action in the \a action parameter will associate
- the menu with the specified action. In this case, if the action
- is added to another menu with the ::KHUI_ACTIONREF_SUBMENU flag,
- this menu will appear as a submenu within that menu. Only one
- menu can be associated with any given action. Custom menus can
- not be associated with standard actions.
- */
-KHMEXP khui_menu_def * KHMAPI
-khui_menu_create(khm_int32 action);
-
-/*! \brief Duplicate a menu
-
- Creates a copy of the specified menu. The returned data structure
- must be freed by a call to khui_menu_delete(). Custom menus are
- not reference counted or maintained by the UI library. The caller
- is responsible for calling khui_menu_delete() when the data is no
- longer needed.
-
- Note that even if the original menu was associated with an action,
- the duplicate will not be. Modifying the duplicate will not
- modify the original menu. Only one menu can be associated with an
- action.
- */
-KHMEXP khui_menu_def * KHMAPI
-khui_menu_dup(khui_menu_def * src);
-
-/*! \brief Delete a menu
-
- Deletes a menu created by a call to khui_menu_create() or
- khui_menu_dup(). This frees up the memory and associated
- resources used by the menu definition. The pointer that is passed
- in will no longer be valid.
- */
-KHMEXP void KHMAPI
-khui_menu_delete(khui_menu_def * d);
-
-/*! \brief Insert an action into a menu
-
- The action specified by \a cmd will be inserted in to the menu \a
- d at index \a idx.
-
- \param[in] d The menu to insert the action into
-
- \param[in] idx The index at which to insert the action. The index
- is zero based. If \a idx is (-1) or larger than the largest
- index in the menu, the item is appended to the menu.
-
- \param[in] cmd The command representing the action to insert into
- the menu. This should be either a standard action, a user
- action created with khui_action_create(), or certain pseudo
- actions. Not all pseudo actions can be placed on a menu.
-
- \param[in] flags Flags for the action. This is a combination of
- KHUI_ACTIONREF_* constants. Currently, the only constants
- that are valid for this function are: ::KHUI_ACTIONREF_SEP,
- ::KHUI_ACTIONREF_SUBMENU, ::KHUI_ACTIONREF_DEFAULT.
- ::KHUI_ACTIONREF_SEP will be automatically added if the
- command is ::KHUI_MENU_SEP. If ::KHUI_ACTIONREF_DEFAULT is
- specified, then all other items in the menu will be stripped
- of that flag leaving this action as the only one with that
- flag set.
- */
-KHMEXP void KHMAPI
-khui_menu_insert_action(khui_menu_def * d, khm_size idx, khm_int32 cmd, khm_int32 flags);
-
-#define khui_menu_add_action(d,c) khui_menu_insert_action((d),-1,(c),0)
-#pragma deprecated(khui_menu_add_action)
-
-#ifdef NOEXPORT
-
-/*! \brief Insert an action by reference into a menu
-
- The action specified by \a act will be inserted into the menu \a d
- at index \a idx.
-
- \param[in] d The menu to inser the action into.
-
- \param[in] idx The index at which to insert the action. The index
- is zero based. If the index is (-1) or is larger than the
- largest index in the menu, then the action is appended to the
- menu.
-
- \param[in] act The action to insert. This is added by reference.
- It is the callers reponsibility to ensure that the structure
- pointed to by \a act is available throughout the lifetime of
- the menu.
-
- \param[in] flags Flags for the action. This is a combination of
- KHUI_ACTIONREF_* constants. Currently, the only constants
- that are valid for this function are: ::KHUI_ACTIONREF_SEP,
- ::KHUI_ACTIONREF_SUBMENU, ::KHUI_ACTIONREF_DEFAULT. For this
- function, ::KHUI_ACTIONREF_PACTION will automatically be aded
- when adding the action. ::KHUI_ACTIONREF_SEP will be
- automatically added if the command is ::KHUI_MENU_SEP. If
- ::KHUI_ACTIONREF_DEFAULT is specified, then all other items in
- the menu will be stripped of that flag leaving this action as
- the only one with that flag set.
-*/
-KHMEXP void KHMAPI
-khui_menu_insert_paction(khui_menu_def * d, khm_size idx, khui_action * act, khm_int32 flags);
-
-#define khui_menu_add_paction(d,a,f) khui_menu_insert_paction((d),-1,(a),(f))
-#pragma deprecated(khui_menu_add_paction)
-
-#endif
-
-/*! \brief Remove an action from a menu
-
- The action at the specified index will be removed from the menu.
- */
-KHMEXP void KHMAPI
-khui_menu_remove_action(khui_menu_def * d, khm_size idx);
-
-/*! \brief Get the number of items in the menu
-
- Note that the count includes menu separators. The indices of the
- menu items range from 0 to one less than the value returned by
- this function.
- */
-KHMEXP khm_size KHMAPI
-khui_menu_get_size(khui_menu_def * d);
-
-/*! \brief Get the menu item at a specified index
-
- The returned reference is only valid while the ::khui_menu_def
- structure is valid. In addition, the reference becomes invalid if
- the list of actions in the menu data structure is modified in any
- way.
-
- If the specified index is out of bounds, then the function returns
- NULL.
-
- */
-KHMEXP khui_action_ref *
-khui_menu_get_action(khui_menu_def * d, khm_size idx);
-
-/*! \brief Action scope identifiers
-
- The scope identifier is a value which describes the scope of the
- cursor context. See documentation on individual scope identifiers
- for details.
-
- The role of the scope identifier is to provide a summary of the
- current cursor context. Specifically, these identify several
- special cases of credential selection, such as the selection of an
- entire identity, a credential type or a single credential. If
- none of these are applicable, then the generic scope identifier
- ::KHUI_SCOPE_GROUP is set or ::KHUI_SCOPE_NONE if there is nothing
- selected.
-
- Note that the scope typically only apply to cursor contexts and
- not the selection context. Please see
- \ref khui_context "UI Contexts" for more information.
-
- \see \ref khui_context "UI Contexts"
-*/
-typedef enum tag_khui_scope {
- KHUI_SCOPE_NONE,
- /*!< No context. Nothing is selected. */
-
- KHUI_SCOPE_IDENT,
- /*!< Identity. The selection is the entire identity specified in
- the \a identity field of the context. */
-
- KHUI_SCOPE_CREDTYPE,
- /*!< A credentials type. The selection is an entire credentials
- type. If \a identity is non-NULL, then the scope is all the
- credentials of type \a cred_type which belong to \a identity.
- Otherwise, the selection is all credentials of type \a
- cred_type.
-
- \note The \a identity can be non-NULL even for the case where
- all credentials of type \a cred_type under \a identity is the
- same scope as all credentials of type \a cred_type under all
- identities. */
-
- KHUI_SCOPE_GROUP,
- /*!< A grouping of credentials. The scope is a group of
- credentials which can not be simplified using one of the other
- context identifiers. The \a headers array contains \a n_headers
- elements describing the outline level that has been selected.
-
- \see ::khui_header
- \see \ref khui_context_sel_ctx_grp "KHUI_SCOPE_GROUP description" */
-
- KHUI_SCOPE_CRED
- /*!< A single credential. Only a single credential was
- selected. The \a cred field of the context specifies the
- credential. The \a identity and \a cred_type fields specify the
- identity and the credential type respectively. */
-} khui_scope;
-
-
-/*! \brief Outline header
-
- Describes an outline header in the user interface.
-
- \see \ref khui_context_sel_ctx_grp "KHUI_SCOPE_GROUP description"
- */
-typedef struct tag_khui_header {
- khm_int32 attr_id; /*!< Attribute ID */
- void * data; /*!< Value of attribute */
- khm_size cb_data; /*!< Size of the value */
-} khui_header;
-
-/*! \brief Maximum number of outline headers
-
- This is the maximum number of fields that the credentials view can
- be grouped by.
- */
-#define KHUI_MAX_HEADERS 6
-
-/*! \brief Action context
-
- Represents the UI context for an action.
- */
-typedef struct tag_khui_action_context {
- khm_int32 magic; /*!< Internal. */
- khui_scope scope; /*!< Context scope. One of ::khui_scope*/
- khm_handle identity; /*!< Identity */
- khm_int32 cred_type; /*!< Credential type ID */
- khm_handle cred; /*!< Credential */
-
- khui_header headers[KHUI_MAX_HEADERS];
- /*!< The ordered set of outline
- headers which define the current
- cursor location. */
-
- khm_size n_headers; /*!< Number of actual headers defined
- above */
-
- khm_handle credset; /*!< Handle to a credential set
- containing the currently selected
- credentials. When the context is
- obtained through khui_context_get(),
- this credential is returned in a
- sealed state. */
-
- khm_size n_sel_creds; /*!< Number of selected credentials */
-
- void * int_buf; /*!< Internal. Do not use. */
- khm_size int_cb_buf; /*!< Internal. Do not use. */
- khm_size int_cb_used; /*!< Internal. Do not use. */
-
- void * vparam; /*!< Optional data */
- khm_size cb_vparam; /*!< Size of optional data */
-} khui_action_context;
-
-/*! \brief Set the current context
-
- Changes the UI context to that represented by the parameters to
- the function. Note that specifying a valid \a identity or \a cred
- parameter will result in an automatic hold on the respective
- object. The hold will stay until another call to
- khui_context_set() overwrites the identity or credential handle or
- a call to khui_context_reset() is made.
-
- While this API is available, it is only called from the main
- NetIDMgr application. Plugins do not have a good reason to call
- this API directly and should not do so.
-
- \param[in] scope The new context scope
-
- \param[in] identity A handle to an identity. If this is not NULL,
- then it should be a valid handle to an identity. Required if
- \a scope specifies ::KHUI_SCOPE_IDENT. Optional if \a scope
- specifies ::KHUI_SCOPE_CREDTYPE. Ignored otherwise.
-
- \param[in] cred_type A credentials type. Specify
- ::KCDB_CREDTYPE_INVALID if this parameter is not given or not
- relevant. Required if \a scope specifies
- ::KHUI_SCOPE_CREDTYPE. Ignored otherwise.
-
- \param[in] cred A handle to a credential. If this parameter is
- not NULL it is expected to be a valid handle to a credential.
- Required if \a scope specifies ::KHUI_SCOPE_CRED. Ignored
- otherwise.
-
- \param[in] headers An array of headers. The \a n_headers
- parameter specifies the number of elements in the array. Set
- to NULL if not specified. Required if \a scope specifies
- ::KHUI_SCOPE_GROUP.
-
- \param[in] n_headers Number of elements in \a headers. Must be
- less than or equal to ::KHUI_MAX_HEADERS. Required if \a
- headers is not NULL. Ignored otherwise.
-
- \param[in] cs_src A handle to a credential set from which the
- selected credentials will be extracted. The credentials that
- are selected must have the ::KCDB_CRED_FLAG_SELECTED flag set.
-
- \note This function should only be called from the UI thread.
- */
-KHMEXP void KHMAPI
-khui_context_set(khui_scope scope,
- khm_handle identity,
- khm_int32 cred_type,
- khm_handle cred,
- khui_header *headers,
- khm_size n_headers,
- khm_handle cs_src);
-
-/*! \brief Set the current context
-
- Changes the UI context to that represented by the parameters to
- the function. Note that specifying a valid \a identity or \a cred
- parameter will result in an automatic hold on the respective
- object. The hold will stay until another call to
- khui_context_set() overwrites the identity or credential handle or
- a call to khui_context_reset() is made.
-
- While this API is available, it is only called from the main
- NetIDMgr application. Plugins do not have a good reason to call
- this API directly and should not do so.
-
- \param[in] scope The new context scope
-
- \param[in] identity A handle to an identity. If this is not NULL,
- then it should be a valid handle to an identity. Required if
- \a scope specifies ::KHUI_SCOPE_IDENT. Optional if \a scope
- specifies ::KHUI_SCOPE_CREDTYPE. Ignored otherwise.
-
- \param[in] cred_type A credentials type. Specify
- ::KCDB_CREDTYPE_INVALID if this parameter is not given or not
- relevant. Required if \a scope specifies
- ::KHUI_SCOPE_CREDTYPE. Ignored otherwise.
-
- \param[in] cred A handle to a credential. If this parameter is
- not NULL it is expected to be a valid handle to a credential.
- Required if \a scope specifies ::KHUI_SCOPE_CRED. Ignored
- otherwise.
-
- \param[in] headers An array of headers. The \a n_headers
- parameter specifies the number of elements in the array. Set
- to NULL if not specified. Required if \a scope specifies
- ::KHUI_SCOPE_GROUP.
-
- \param[in] n_headers Number of elements in \a headers. Must be
- less than or equal to ::KHUI_MAX_HEADERS. Required if \a
- headers is not NULL. Ignored otherwise.
-
- \param[in] cs_src A handle to a credential set from which the
- selected credentials will be extracted. The credentials that
- are selected must have the ::KCDB_CRED_FLAG_SELECTED flag set.
-
- \param[in] vparam Optional parameter blob
-
- \param[in] cb_vparam Size of parameter blob
-
- \note This function should only be called from the UI thread.
- */
-KHMEXP void KHMAPI
-khui_context_set_ex(khui_scope scope,
- khm_handle identity,
- khm_int32 cred_type,
- khm_handle cred,
- khui_header *headers,
- khm_size n_headers,
- khm_handle cs_src,
- void * vparam,
- khm_size cb_vparam);
-
-/*! \brief Set the current UI context using an existing context
-
- Copies the context specified in \a ctx into the active UI context.
-
- \param[in] ctx A pointer to a ::khui_action_context structure that
- specifies the new UI context. Cannot be NULL.
-*/
-KHMEXP void KHMAPI
-khui_context_set_indirect(khui_action_context * ctx);
-
-/*! \brief Obtain the current UI context
-
- The parameter specified by \a ctx will receive the current UI
- context. If the context contains an identity or a credential
- handle, a hold will be obtained on the relevant object. Use
- khui_context_release() to release the holds obtained in a prior
- call to khui_context_get().
-
- \note The returned context should not be modified prior to calling
- khui_context_release().
-*/
-KHMEXP void KHMAPI
-khui_context_get(khui_action_context * ctx);
-
-/*! \brief Create a new UI context
-
- The created context does not have any relation to the current UI
- context. This function is provided for use in situations where an
- application needs to provide a scope description through a
- ::khui_action_context structure.
-
- Once the application is done with the context, it should call
- khui_context_release() to release the created context.
- */
-KHMEXP void KHMAPI
-khui_context_create(khui_action_context * ctx,
- khui_scope scope,
- khm_handle identity,
- khm_int32 cred_type,
- khm_handle cred);
-
-/*! \brief Release a context obtained using khui_context_get()
-
- Releases all holds obtained on related objects in a prior call to
- khui_context_get() and nullifies the context.
-
- \note The context should not have been modified between calling
- khui_context_get() and khui_context_release()
- */
-KHMEXP void KHMAPI
-khui_context_release(khui_action_context * ctx);
-
-/*! \brief Reset the UI context
-
- Nullifies the current UI context and releases any holds obtained
- on objects related to the previous context.
-*/
-KHMEXP void KHMAPI
-khui_context_reset(void);
-
-/*! \brief Refresh context data
-
- Setting the UI context involves other side effects such as
- activation of or disabling certain actions based on the selection.
- If an operation is performed which may affect the side effects,
- khui_context_refresh() is called to refresh them.
-
- An example is when setting the default identity. The state of the
- action ::KHUI_ACTION_SET_DEF_ID depends on whether the currently
- selected identity is the default. However, if the currently
- selected identity becomes the default after selection, then
- khui_context_refresh() should be called to adjust the state of the
- ::KHUI_ACTION_SET_DEF_ID action.
- */
-KHMEXP void KHMAPI
-khui_context_refresh(void);
-
-/*! \brief A filter function that filters for credentials in the cursor context
-
- This is a function of type ::kcdb_cred_filter_func which can be
- used to filter for credentials that are included in the cursor
- context.
-
- The \a rock parameter should be a pointer to a
- ::khui_action_context structure which will be used as the filter.
-
- For example, the following code will extract the cursor context
- credentials into the credential set \a my_credset based on the UI
- context \a my context:
-
- \code
- kcdb_credset_extract_filtered(my_credset,
- NULL,
- khui_context_cursor_filter,
- (void *) my_context);
- \endcode
-*/
-KHMEXP khm_int32 KHMAPI
-khui_context_cursor_filter(khm_handle cred,
- khm_int32 flags,
- void * rock);
-
-/*! \brief Get a string representation of an accelerator
-
- \param[in] cmd Command for which to obtain the accelerator string for
- \param[out] buf Buffer to receive the accelerator string
- \param[in] bufsiz Size of the buffer in bytes. Note that the size of the
- buffer must be sufficient to hold at least one character and a
- NULL terminator.
-
- \return TRUE if the operation was successful. FALSE otherwise.
- */
-KHMEXP khm_boolean KHMAPI khui_get_cmd_accel_string(khm_int32 cmd, wchar_t * buf, khm_size bufsiz);
-
-#ifdef NOEXPORT
-/*! \brief Initializes the global accelerator table
- */
-KHMEXP HACCEL KHMAPI khui_create_global_accel_table(void);
-#endif
-
-/*! \brief Find a menu by id
-
- Finds the menu that is associated with the specified action.
- */
-KHMEXP khui_menu_def * KHMAPI khui_find_menu(khm_int32 action);
-
-#ifdef NOEXPORT
-
-/* internal */
-KHMEXP void KHMAPI
-khui_set_main_window(HWND hwnd);
-
-#endif
-
-/*! \brief Trigger an action
-
- Triggers the specified action using the specified UI context.
-
- This function does not return until the specified action has been
- processed. Many standard actions are asynchronous and they will
- return before processing will complete.
-
- Pseudo actions should not be triggered using khui_action_trigger()
- as they only carry meaning when invoked from specific windows or
- contexts.
-
- \param[in] action Action. Should be one of the standard actions
- or an action created by khui_action_create()
-
- \param[in] ctx The UI context to use for the action. If this is
- NULL, the action will be triggered under the current UI context.
- */
-KHMEXP void KHMAPI
-khui_action_trigger(khm_int32 action, khui_action_context * ctx);
-
-/*! \brief Find an action by id
-
- \note This function should not be used by plugins. It is there
- for use by the NetIDMgr application.
-*/
-KHMEXP khui_action * KHMAPI khui_find_action(khm_int32 action);
-
-#ifdef NOEXPORT
-/*! \brief Get the length of the action list */
-KHMEXP size_t KHMAPI khui_action_list_length(khui_action_ref * ref);
-#endif
-
-/*! \brief Create a new action
-
- Creates a new custom action. The created custom action can be
- added to menus, toolbars and can be triggered by
- khui_action_trigger().
-
- When the action is triggered as a result of the user selecting a
- menu item, a toolbar item or as a result of calling
- khui_action_trigger(), the subscription identified by \a hsub will
- received a message of type ::KMSG_ACT, subtype
- ::KMSG_ACT_ACTIVATE. The \a uparam for the message will be the
- action identifier that was returned by khui_action_create(). The
- \a vparam of the message will currently be set to \a NULL.
-
- Actions can optionally be named. The name is not actively used by
- the Network Identity Manager framework, but can be used to label
- actions so that they can be looked up later using
- khui_find_named_action().
-
- \param[in] name Name for a named action. The name must be unique
- among all registered actions. (limited by KHUI_MAXCCH_NAME).
- (Optional. Set to NULL if the action is not a named action.)
- See \a note below for additional restrictions on the name of
- the action.
-
- \param[in] caption The localized caption for the action. This
- will be shown in menus, toolbars and buttons when the action
- needs to be represented. (limited by KHUI_MAXCCH_SHORT_DESC)
- (Required)
-
- \param[in] tooltip The localized tooltip for the action. (limited
- by KHUI_MAXCCH_SHORT_DESC) (Optional, set to NULL if there is
- no tooltip associated with the action)
-
- \param[in] userdata A custom value.
-
- \param[in] type The type of the action. Currently it should be
- set to either ::KHUI_ACTIONTYPE_TRIGGER or
- ::KHUI_ACTIONTYPE_TOGGLE. For ::KHUI_ACTIONTYPE_TOGGLE, the
- initial state will be unchecked. Use khui_check_action()
- function to change the checked state of the action.
-
- \param[in] hsub The subscription that is notified when the action
- is triggered. (Optional) The subscription must be created with
- kmq_create_subscription(). The handle will be released when
- it is no longer needed. Hence, the caller should not release
- it.
-
- \return The identifier of the new action or zero if the action
- could not be created.
-
- \note For named custom actions, the name of the action can not be
- the same as the name of a configuration node. See
- khui_cfg_register_node().
- */
-KHMEXP khm_int32 KHMAPI
-khui_action_create(const wchar_t * name,
- const wchar_t * caption,
- const wchar_t * tooltip,
- void * userdata,
- khm_int32 type,
- khm_handle hsub);
-
-/* \brief Delete a custom action
-
- Deletes a custom action created by a call to khui_action_create().
- Custom actions should only be deleted when unloading a plugin.
- */
-KHMEXP void KHMAPI
-khui_action_delete(khm_int32 action);
-
-/*! \brief Get the user data associated with a custom action
-
- This function returns the user data that was specified when the
- custom action was created usng khui_action_create(). If the
- custom action identifier is invalid or if the custom action does
- not contain any user data, this function will return NULL.
- */
-KHMEXP void * KHMAPI
-khui_action_get_data(khm_int32 action);
-
-/*! \brief Find an action by name */
-KHMEXP khui_action * KHMAPI khui_find_named_action(const wchar_t * name);
-
-/*! \brief Enables or disables a group of actions
-
- The group of actions are specified by the menu definition. All
- valid action entries in the menu are marked as enabled or disabled
- according to the value of \a enable.
- */
-KHMEXP void KHMAPI khui_enable_actions(khui_menu_def * d, khm_boolean enable);
-
-/*! \brief Enables or disables an action
-
- The action designated by the command \a action will either be enabled
- or disabled depending on the \a enable parameter. If \a enable is
- TRUE then the action is enabled.
- */
-KHMEXP void KHMAPI khui_enable_action(khm_int32 action, khm_boolean enable);
-
-/*! \brief Check an action in an action group
-
- Marks the action denoted by \a action as checked and resets the
- checked bit in all other actions.
-
- \param[in] d A menu definition.
-
- \param[in] action A command identifier. Setting this to -1 will
- reset the checked bit in all the actions in the menu
- definition.
- */
-KHMEXP void KHMAPI khui_check_radio_action(khui_menu_def * d, khm_int32 action);
-
-/*! \brief Check an action
-
- For toggle typed actions, this sets or resets the check.
- */
-KHMEXP void KHMAPI khui_check_action(khm_int32 cmd, khm_boolean check);
-
-#ifdef NOEXPORT
-/*!\cond INTERNAL */
-
-/*! \brief Initialize actions
-
- \note Only called by the NetIDMgr application
- */
-KHMEXP void KHMAPI khui_init_actions(void);
-
-/*! \brief Exit actions
-
- \note Only called by the NetIDMgr application
- */
-KHMEXP void KHMAPI khui_exit_actions(void);
-
-/*! \endcond */
-#endif
-
-/*@}*/
-/*@}*/
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __KHIMAIRA_ACTION_H
+#define __KHIMAIRA_ACTION_H
+
+/*! \addtogroup khui
+ @{*/
+/*! \defgroup khui_actions Actions
+ @{*/
+
+struct tag_khui_action;
+typedef struct tag_khui_action khui_action;
+
+/*! \brief Unknown action type
+
+ Unknown action type.
+ */
+#define KHUI_ACTIONTYPE_NONE 0
+
+/*! \brief A trigger type action
+
+ A trigger action usually triggers some event, which is what pretty
+ much every action does.
+*/
+#define KHUI_ACTIONTYPE_TRIGGER 1
+
+/*! \brief A toggle type action
+
+ A toggle type action typically changes the CHECKED state of the
+ action each time it is invoked.
+ */
+#define KHUI_ACTIONTYPE_TOGGLE 2
+
+/*! \brief The action is enabled
+
+ This is the default if no other state is specified. Just means
+ not-disabled.
+*/
+#define KHUI_ACTIONSTATE_ENABLED 0
+
+/*! \brief The action is diabled */
+#define KHUI_ACTIONSTATE_DISABLED 1
+
+/*! \brief For toggle type actions, the action is checked */
+#define KHUI_ACTIONSTATE_CHECKED 2
+
+/*! \brief The action is hot
+
+ Typically this means that the user is hovering the pointing device
+ over a UI element representing the action.
+ */
+#define KHUI_ACTIONSTATE_HOT 4
+
+/*! \brief The action has been marked for deletion
+
+ For custom actions, this means that the custom action was deleted.
+ The contents of the custom action fields are no longer valid.
+ */
+#define KHUI_ACTIONSTATE_DELETED 8
+
+#ifdef NOEXPORT
+#define ACTION_SIMPLE(c,cap,des,top) \
+ {c,KHUI_ACTIONTYPE_TRIGGER,NULL,0,0,0,0,0,cap,des,top,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0}
+
+#define ACTION_FULL(cmd,type,name,inormal,ihot,idis,isml,ismld,capt,toolt,topic,state) \
+ {cmd,type,name,inormal,ihot,idis,isml,ismld,capt,toolt,topic,NULL,NULL,NULL,NULL,NULL,NULL,NULL,state}
+
+#define ACTION_SIMPLE_IMAGE(c,inormal, ihot, idis, isml, ismld,cap, des, top) \
+ {c,KHUI_ACTIONTYPE_TRIGGER,NULL,inormal,ihot,idis,isml,ismld,cap,des,top,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0}
+#endif
+
+/*! \brief A reference to an action
+
+ If the \a flags member has the KHUI_ACTIONREF_PACTION bit set,
+ then the action is referenced by the \a p_action member of the
+ union. Otherwise the identifier for the action is specified by \a
+ action member.
+*/
+typedef struct tag_khui_action_ref {
+ int flags; /*!< A combination of KHUI_ACTIONREF_* */
+ union {
+ khm_int32 action; /*!< The action identifier for the
+ action that is being referrred to.
+ Only valid if
+ ::KHUI_ACTIONREF_PACTION is not set
+ in \a flags. */
+ khui_action * p_action; /*!< A pointer to the ::khui_action
+ structure that describes the action
+ that is being referred to. Only
+ valid if ::KHUI_ACTIONREF_PACTION is
+ set. */
+ };
+} khui_action_ref;
+
+/*! \brief A submenu
+
+ There should exist a menu associated with the action that is being
+ referred. When displaying this action in a menu, the contents of
+ the associated menu will appear as a submenu.
+ */
+#define KHUI_ACTIONREF_SUBMENU 0x01
+
+/*! \brief Separator
+
+ This is not an actual action, but represents a separator between
+ actions. When displaying this action in a menu or a toolbar, a
+ separating line will be drawn in place of this action. The \a
+ action and \a p_action members of the structures are unused if
+ this flag is set.
+ */
+#define KHUI_ACTIONREF_SEP 0x02
+
+/*! \brief Action by reference
+
+ The \a p_action member of the structure points to the
+ ::khui_action structure that describes the action.
+ */
+#define KHUI_ACTIONREF_PACTION 0x04
+
+#ifdef NOEXPORT
+/*! \brief Action should be freed
+
+ \note This flag is reserved for internal use in the NetIDMgr
+ application. Do not use.
+ */
+#define KHUI_ACTIONREF_FREE_PACTION 0x08
+
+/*! \brief Marks the end of an action sequence
+
+ \note THis flag is reserved for internal use in the NetIDMgr
+ application. Do not use.
+ */
+#define KHUI_ACTIONREF_END 0x10
+#endif
+
+/*! \brief The default action
+
+ When this bit is set in an action reference that describes a menu,
+ the menu item will be the default item and will be rendered
+ differently from other menu items. Only useful when defining
+ context menus. In general, it is good practice to place the
+ default item at the top of a menu, although the UI library does
+ not enforce this. This is purely meant as a rendering hint.
+
+ Only one action is allowed to have this flag set. When an action
+ is added to a menu using khui_menu_insert_action() or
+ khui_menu_insert_paction() and this flag is set, all other menu
+ items will be stripped of this flag.
+ */
+#define KHUI_ACTIONREF_DEFAULT 0x20
+
+#ifdef NOEXPORT
+#define MENU_ACTION(c) {0,c}
+#define MENU_DEFACTION(c) {KHUI_ACTIONREF_DEFAULT, c}
+#define MENU_SUBMENU(s) {KHUI_ACTIONREF_SUBMENU,s}
+#define MENU_SEP() {KHUI_ACTIONREF_SEP,KHUI_MENU_SEP}
+#define MENU_END() {KHUI_ACTIONREF_END,KHUI_MENU_END}
+#endif
+
+/*! \brief Menu definition
+
+ Use the khui_menu_create(), khui_menu_insert_action(),
+ khui_menu_insert_paction(), khui_menu_get_size(),
+ khui_menu_get_action() functions to create and manipulate custom
+ menus. Do not manipulate this structure directly as doing so may
+ cause inconsistencies in the UI library.
+*/
+typedef struct tag_khui_menu_def {
+ khm_int32 cmd; /*!< Action associated with menu */
+ khm_int32 state; /*!< combination of KHUI_MENUSTATE_* */
+ khm_size n_items; /*!< The number of actions in the \a items
+ list. If this is a custom menu, the
+ ::KHUI_MENUSTATE_ALLOCD bit will be set,
+ and the contents of this field will be
+ valid. Otherwise, the contents of this
+ field is ignored and the list of actions
+ must be terminated with a
+ ACTION_LIST_END action. */
+ khm_size nc_items; /*!< max number of items in the buffer
+ alocated for items. Ignored if
+ ::KHUI_MENUSTATE_ALLOCD is not set in \a
+ state. */
+ khui_action_ref *items; /*!< Action list terminated by,
+ ACTION_LIST_END. If \a n_items is set
+ to a value other than -1, the list
+ doesn't necessarily have to end with a
+ ACTION_LIST_END. When constructing a
+ menu using khui_menu_* functions, they
+ will set the size of this list in the \a
+ n_items member, and there will be no
+ ACTION_LIST_END action to terminate the
+ list. */
+} khui_menu_def;
+
+#ifdef NOEXPORT
+#define CONSTMENU(c,s,i) {c,s,-1,-1,i}
+#endif
+
+/*! \brief Unspecified menu
+
+ Used when there is no single command associated with the entire
+ menu, such as for ad-hoc context menus.
+ */
+#define KHUI_MENU_NONE -3
+
+/*! \brief Menu end indicator
+
+ For static or constant menus this indicates that this action marks
+ the end of the list of actions which defined the menu. This is
+ invalid if used in a dynamic menu (a menu with the
+ ::KHUI_MENUSTATE_ALLOCD bit set).
+ */
+#define KHUI_MENU_END -2
+
+/*! \brief Menu separator
+
+ A separator for actions. When displaying a menu or showing a
+ toolbar based on a menu definition, a separator is rendered as a
+ bar separating the user interface elements for the actions on
+ either side of this.
+*/
+#define KHUI_MENU_SEP -1
+
+/*! \brief Constant menu
+
+ The contents of the menu cannot be modified (individual actions in
+ the menu may be modified, but the order and the contents of the
+ menu itself cannot be modified.
+
+ This is the default if ::KHUI_MENUSTATE_ALLOCD is not specified.
+ */
+#define KHUI_MENUSTATE_CONSTANT 0
+
+/*! \brief Variable menu
+
+ The menu is dnamically allocated. The list of actions contained
+ in the menu can be modified.
+*/
+#define KHUI_MENUSTATE_ALLOCD 1
+
+#ifdef NOEXPORT
+/* predefined system menu */
+#define KHUI_MENUSTATE_SYSTEM 2
+#endif
+
+#ifdef NOEXPORT
+
+/*! \brief Accelerator definition */
+typedef struct tag_khui_accel_def {
+ int cmd;
+ int mod;
+ int key;
+ int scope;
+} khui_accel_def;
+
+#define KHUI_ACCEL_SCOPE_GLOBAL 0
+
+extern khui_accel_def khui_accel_global[];
+extern int khui_n_accel_global;
+
+extern khui_action khui_actions[];
+extern int khui_n_actions;
+
+extern khui_menu_def khui_all_menus[];
+extern int khui_n_all_menus;
+
+#endif /* NOEXPORT */
+
+/* functions */
+
+/*! \brief Refresh the global action table
+
+ Changes to system menus and toolbars may not be immediately
+ reflected in the user interface. Calling this function forces the
+ UI to reparse the action tables and menus and refresh the
+ application menu bar and toolbars.
+
+ */
+KHMEXP void KHMAPI
+khui_refresh_actions(void);
+
+/*! \brief Lock the action and menu tables
+
+ This function, along with khui_action_unlock() is used to prevent
+ changes from being made to shared menus and actions while they are
+ being updated. In particular, changes to shared menus usually
+ need to be done in a batch and may suffer corruption of other
+ threads access or modify the menu while one thread is updating it.
+ Operations on shared menus should always be done with the actions
+ locked.
+*/
+KHMEXP void KHMAPI
+khui_action_lock(void);
+
+/*! \brief Unlock the action and menu tables
+
+ Unlocks the action and menu tables after a call to
+ khui_action_lock().
+
+ \see khui_action_lock()
+ */
+KHMEXP void KHMAPI
+khui_action_unlock(void);
+
+/*! \brief Create a new menu
+
+ Creates a new menu. The returned data structure must be freed by
+ a call to khui_menu_delete(). Custom menus that are created this
+ way are not reference counted or maintained by the UI library.
+ The caller is responsible for calling khui_menu_delete() when the
+ data is no longer needed.
+
+ Specifiying an action in the \a action parameter will associate
+ the menu with the specified action. In this case, if the action
+ is added to another menu with the ::KHUI_ACTIONREF_SUBMENU flag,
+ this menu will appear as a submenu within that menu. Only one
+ menu can be associated with any given action. Custom menus can
+ not be associated with standard actions.
+ */
+KHMEXP khui_menu_def * KHMAPI
+khui_menu_create(khm_int32 action);
+
+/*! \brief Duplicate a menu
+
+ Creates a copy of the specified menu. The returned data structure
+ must be freed by a call to khui_menu_delete(). Custom menus are
+ not reference counted or maintained by the UI library. The caller
+ is responsible for calling khui_menu_delete() when the data is no
+ longer needed.
+
+ Note that even if the original menu was associated with an action,
+ the duplicate will not be. Modifying the duplicate will not
+ modify the original menu. Only one menu can be associated with an
+ action.
+ */
+KHMEXP khui_menu_def * KHMAPI
+khui_menu_dup(khui_menu_def * src);
+
+/*! \brief Delete a menu
+
+ Deletes a menu created by a call to khui_menu_create() or
+ khui_menu_dup(). This frees up the memory and associated
+ resources used by the menu definition. The pointer that is passed
+ in will no longer be valid.
+ */
+KHMEXP void KHMAPI
+khui_menu_delete(khui_menu_def * d);
+
+/*! \brief Insert an action into a menu
+
+ The action specified by \a cmd will be inserted in to the menu \a
+ d at index \a idx.
+
+ \param[in] d The menu to insert the action into
+
+ \param[in] idx The index at which to insert the action. The index
+ is zero based. If \a idx is (-1) or larger than the largest
+ index in the menu, the item is appended to the menu.
+
+ \param[in] cmd The command representing the action to insert into
+ the menu. This should be either a standard action, a user
+ action created with khui_action_create(), or certain pseudo
+ actions. Not all pseudo actions can be placed on a menu.
+
+ \param[in] flags Flags for the action. This is a combination of
+ KHUI_ACTIONREF_* constants. Currently, the only constants
+ that are valid for this function are: ::KHUI_ACTIONREF_SEP,
+ ::KHUI_ACTIONREF_SUBMENU, ::KHUI_ACTIONREF_DEFAULT.
+ ::KHUI_ACTIONREF_SEP will be automatically added if the
+ command is ::KHUI_MENU_SEP. If ::KHUI_ACTIONREF_DEFAULT is
+ specified, then all other items in the menu will be stripped
+ of that flag leaving this action as the only one with that
+ flag set.
+ */
+KHMEXP void KHMAPI
+khui_menu_insert_action(khui_menu_def * d, khm_size idx, khm_int32 cmd, khm_int32 flags);
+
+#define khui_menu_add_action(d,c) khui_menu_insert_action((d),-1,(c),0)
+#pragma deprecated(khui_menu_add_action)
+
+#ifdef NOEXPORT
+
+/*! \brief Insert an action by reference into a menu
+
+ The action specified by \a act will be inserted into the menu \a d
+ at index \a idx.
+
+ \param[in] d The menu to inser the action into.
+
+ \param[in] idx The index at which to insert the action. The index
+ is zero based. If the index is (-1) or is larger than the
+ largest index in the menu, then the action is appended to the
+ menu.
+
+ \param[in] act The action to insert. This is added by reference.
+ It is the callers reponsibility to ensure that the structure
+ pointed to by \a act is available throughout the lifetime of
+ the menu.
+
+ \param[in] flags Flags for the action. This is a combination of
+ KHUI_ACTIONREF_* constants. Currently, the only constants
+ that are valid for this function are: ::KHUI_ACTIONREF_SEP,
+ ::KHUI_ACTIONREF_SUBMENU, ::KHUI_ACTIONREF_DEFAULT. For this
+ function, ::KHUI_ACTIONREF_PACTION will automatically be aded
+ when adding the action. ::KHUI_ACTIONREF_SEP will be
+ automatically added if the command is ::KHUI_MENU_SEP. If
+ ::KHUI_ACTIONREF_DEFAULT is specified, then all other items in
+ the menu will be stripped of that flag leaving this action as
+ the only one with that flag set.
+*/
+KHMEXP void KHMAPI
+khui_menu_insert_paction(khui_menu_def * d, khm_size idx, khui_action * act, khm_int32 flags);
+
+#define khui_menu_add_paction(d,a,f) khui_menu_insert_paction((d),-1,(a),(f))
+#pragma deprecated(khui_menu_add_paction)
+
+#endif
+
+/*! \brief Remove an action from a menu
+
+ The action at the specified index will be removed from the menu.
+ */
+KHMEXP void KHMAPI
+khui_menu_remove_action(khui_menu_def * d, khm_size idx);
+
+/*! \brief Get the number of items in the menu
+
+ Note that the count includes menu separators. The indices of the
+ menu items range from 0 to one less than the value returned by
+ this function.
+ */
+KHMEXP khm_size KHMAPI
+khui_menu_get_size(khui_menu_def * d);
+
+/*! \brief Get the menu item at a specified index
+
+ The returned reference is only valid while the ::khui_menu_def
+ structure is valid. In addition, the reference becomes invalid if
+ the list of actions in the menu data structure is modified in any
+ way.
+
+ If the specified index is out of bounds, then the function returns
+ NULL.
+
+ */
+KHMEXP khui_action_ref *
+khui_menu_get_action(khui_menu_def * d, khm_size idx);
+
+/*! \brief Action scope identifiers
+
+ The scope identifier is a value which describes the scope of the
+ cursor context. See documentation on individual scope identifiers
+ for details.
+
+ The role of the scope identifier is to provide a summary of the
+ current cursor context. Specifically, these identify several
+ special cases of credential selection, such as the selection of an
+ entire identity, a credential type or a single credential. If
+ none of these are applicable, then the generic scope identifier
+ ::KHUI_SCOPE_GROUP is set or ::KHUI_SCOPE_NONE if there is nothing
+ selected.
+
+ Note that the scope typically only apply to cursor contexts and
+ not the selection context. Please see
+ \ref khui_context "UI Contexts" for more information.
+
+ \see \ref khui_context "UI Contexts"
+*/
+typedef enum tag_khui_scope {
+ KHUI_SCOPE_NONE,
+ /*!< No context. Nothing is selected. */
+
+ KHUI_SCOPE_IDENT,
+ /*!< Identity. The selection is the entire identity specified in
+ the \a identity field of the context. */
+
+ KHUI_SCOPE_CREDTYPE,
+ /*!< A credentials type. The selection is an entire credentials
+ type. If \a identity is non-NULL, then the scope is all the
+ credentials of type \a cred_type which belong to \a identity.
+ Otherwise, the selection is all credentials of type \a
+ cred_type.
+
+ \note The \a identity can be non-NULL even for the case where
+ all credentials of type \a cred_type under \a identity is the
+ same scope as all credentials of type \a cred_type under all
+ identities. */
+
+ KHUI_SCOPE_GROUP,
+ /*!< A grouping of credentials. The scope is a group of
+ credentials which can not be simplified using one of the other
+ context identifiers. The \a headers array contains \a n_headers
+ elements describing the outline level that has been selected.
+
+ \see ::khui_header
+ \see \ref khui_context_sel_ctx_grp "KHUI_SCOPE_GROUP description" */
+
+ KHUI_SCOPE_CRED
+ /*!< A single credential. Only a single credential was
+ selected. The \a cred field of the context specifies the
+ credential. The \a identity and \a cred_type fields specify the
+ identity and the credential type respectively. */
+} khui_scope;
+
+
+/*! \brief Outline header
+
+ Describes an outline header in the user interface.
+
+ \see \ref khui_context_sel_ctx_grp "KHUI_SCOPE_GROUP description"
+ */
+typedef struct tag_khui_header {
+ khm_int32 attr_id; /*!< Attribute ID */
+ void * data; /*!< Value of attribute */
+ khm_size cb_data; /*!< Size of the value */
+} khui_header;
+
+/*! \brief Maximum number of outline headers
+
+ This is the maximum number of fields that the credentials view can
+ be grouped by.
+ */
+#define KHUI_MAX_HEADERS 6
+
+/*! \brief Action context
+
+ Represents the UI context for an action.
+ */
+typedef struct tag_khui_action_context {
+ khm_int32 magic; /*!< Internal. */
+ khui_scope scope; /*!< Context scope. One of ::khui_scope*/
+ khm_handle identity; /*!< Identity */
+ khm_int32 cred_type; /*!< Credential type ID */
+ khm_handle cred; /*!< Credential */
+
+ khui_header headers[KHUI_MAX_HEADERS];
+ /*!< The ordered set of outline
+ headers which define the current
+ cursor location. */
+
+ khm_size n_headers; /*!< Number of actual headers defined
+ above */
+
+ khm_handle credset; /*!< Handle to a credential set
+ containing the currently selected
+ credentials. When the context is
+ obtained through khui_context_get(),
+ this credential is returned in a
+ sealed state. */
+
+ khm_size n_sel_creds; /*!< Number of selected credentials */
+
+ void * int_buf; /*!< Internal. Do not use. */
+ khm_size int_cb_buf; /*!< Internal. Do not use. */
+ khm_size int_cb_used; /*!< Internal. Do not use. */
+
+ void * vparam; /*!< Optional data */
+ khm_size cb_vparam; /*!< Size of optional data */
+} khui_action_context;
+
+/*! \brief Set the current context
+
+ Changes the UI context to that represented by the parameters to
+ the function. Note that specifying a valid \a identity or \a cred
+ parameter will result in an automatic hold on the respective
+ object. The hold will stay until another call to
+ khui_context_set() overwrites the identity or credential handle or
+ a call to khui_context_reset() is made.
+
+ While this API is available, it is only called from the main
+ NetIDMgr application. Plugins do not have a good reason to call
+ this API directly and should not do so.
+
+ \param[in] scope The new context scope
+
+ \param[in] identity A handle to an identity. If this is not NULL,
+ then it should be a valid handle to an identity. Required if
+ \a scope specifies ::KHUI_SCOPE_IDENT. Optional if \a scope
+ specifies ::KHUI_SCOPE_CREDTYPE. Ignored otherwise.
+
+ \param[in] cred_type A credentials type. Specify
+ ::KCDB_CREDTYPE_INVALID if this parameter is not given or not
+ relevant. Required if \a scope specifies
+ ::KHUI_SCOPE_CREDTYPE. Ignored otherwise.
+
+ \param[in] cred A handle to a credential. If this parameter is
+ not NULL it is expected to be a valid handle to a credential.
+ Required if \a scope specifies ::KHUI_SCOPE_CRED. Ignored
+ otherwise.
+
+ \param[in] headers An array of headers. The \a n_headers
+ parameter specifies the number of elements in the array. Set
+ to NULL if not specified. Required if \a scope specifies
+ ::KHUI_SCOPE_GROUP.
+
+ \param[in] n_headers Number of elements in \a headers. Must be
+ less than or equal to ::KHUI_MAX_HEADERS. Required if \a
+ headers is not NULL. Ignored otherwise.
+
+ \param[in] cs_src A handle to a credential set from which the
+ selected credentials will be extracted. The credentials that
+ are selected must have the ::KCDB_CRED_FLAG_SELECTED flag set.
+
+ \note This function should only be called from the UI thread.
+ */
+KHMEXP void KHMAPI
+khui_context_set(khui_scope scope,
+ khm_handle identity,
+ khm_int32 cred_type,
+ khm_handle cred,
+ khui_header *headers,
+ khm_size n_headers,
+ khm_handle cs_src);
+
+/*! \brief Set the current context
+
+ Changes the UI context to that represented by the parameters to
+ the function. Note that specifying a valid \a identity or \a cred
+ parameter will result in an automatic hold on the respective
+ object. The hold will stay until another call to
+ khui_context_set() overwrites the identity or credential handle or
+ a call to khui_context_reset() is made.
+
+ While this API is available, it is only called from the main
+ NetIDMgr application. Plugins do not have a good reason to call
+ this API directly and should not do so.
+
+ \param[in] scope The new context scope
+
+ \param[in] identity A handle to an identity. If this is not NULL,
+ then it should be a valid handle to an identity. Required if
+ \a scope specifies ::KHUI_SCOPE_IDENT. Optional if \a scope
+ specifies ::KHUI_SCOPE_CREDTYPE. Ignored otherwise.
+
+ \param[in] cred_type A credentials type. Specify
+ ::KCDB_CREDTYPE_INVALID if this parameter is not given or not
+ relevant. Required if \a scope specifies
+ ::KHUI_SCOPE_CREDTYPE. Ignored otherwise.
+
+ \param[in] cred A handle to a credential. If this parameter is
+ not NULL it is expected to be a valid handle to a credential.
+ Required if \a scope specifies ::KHUI_SCOPE_CRED. Ignored
+ otherwise.
+
+ \param[in] headers An array of headers. The \a n_headers
+ parameter specifies the number of elements in the array. Set
+ to NULL if not specified. Required if \a scope specifies
+ ::KHUI_SCOPE_GROUP.
+
+ \param[in] n_headers Number of elements in \a headers. Must be
+ less than or equal to ::KHUI_MAX_HEADERS. Required if \a
+ headers is not NULL. Ignored otherwise.
+
+ \param[in] cs_src A handle to a credential set from which the
+ selected credentials will be extracted. The credentials that
+ are selected must have the ::KCDB_CRED_FLAG_SELECTED flag set.
+
+ \param[in] vparam Optional parameter blob
+
+ \param[in] cb_vparam Size of parameter blob
+
+ \note This function should only be called from the UI thread.
+ */
+KHMEXP void KHMAPI
+khui_context_set_ex(khui_scope scope,
+ khm_handle identity,
+ khm_int32 cred_type,
+ khm_handle cred,
+ khui_header *headers,
+ khm_size n_headers,
+ khm_handle cs_src,
+ void * vparam,
+ khm_size cb_vparam);
+
+/*! \brief Set the current UI context using an existing context
+
+ Copies the context specified in \a ctx into the active UI context.
+
+ \param[in] ctx A pointer to a ::khui_action_context structure that
+ specifies the new UI context. Cannot be NULL.
+*/
+KHMEXP void KHMAPI
+khui_context_set_indirect(khui_action_context * ctx);
+
+/*! \brief Obtain the current UI context
+
+ The parameter specified by \a ctx will receive the current UI
+ context. If the context contains an identity or a credential
+ handle, a hold will be obtained on the relevant object. Use
+ khui_context_release() to release the holds obtained in a prior
+ call to khui_context_get().
+
+ \note The returned context should not be modified prior to calling
+ khui_context_release().
+*/
+KHMEXP void KHMAPI
+khui_context_get(khui_action_context * ctx);
+
+/*! \brief Create a new UI context
+
+ The created context does not have any relation to the current UI
+ context. This function is provided for use in situations where an
+ application needs to provide a scope description through a
+ ::khui_action_context structure.
+
+ Once the application is done with the context, it should call
+ khui_context_release() to release the created context.
+ */
+KHMEXP void KHMAPI
+khui_context_create(khui_action_context * ctx,
+ khui_scope scope,
+ khm_handle identity,
+ khm_int32 cred_type,
+ khm_handle cred);
+
+/*! \brief Release a context obtained using khui_context_get()
+
+ Releases all holds obtained on related objects in a prior call to
+ khui_context_get() and nullifies the context.
+
+ \note The context should not have been modified between calling
+ khui_context_get() and khui_context_release()
+ */
+KHMEXP void KHMAPI
+khui_context_release(khui_action_context * ctx);
+
+/*! \brief Reset the UI context
+
+ Nullifies the current UI context and releases any holds obtained
+ on objects related to the previous context.
+*/
+KHMEXP void KHMAPI
+khui_context_reset(void);
+
+/*! \brief Refresh context data
+
+ Setting the UI context involves other side effects such as
+ activation of or disabling certain actions based on the selection.
+ If an operation is performed which may affect the side effects,
+ khui_context_refresh() is called to refresh them.
+
+ An example is when setting the default identity. The state of the
+ action ::KHUI_ACTION_SET_DEF_ID depends on whether the currently
+ selected identity is the default. However, if the currently
+ selected identity becomes the default after selection, then
+ khui_context_refresh() should be called to adjust the state of the
+ ::KHUI_ACTION_SET_DEF_ID action.
+ */
+KHMEXP void KHMAPI
+khui_context_refresh(void);
+
+/*! \brief A filter function that filters for credentials in the cursor context
+
+ This is a function of type ::kcdb_cred_filter_func which can be
+ used to filter for credentials that are included in the cursor
+ context.
+
+ The \a rock parameter should be a pointer to a
+ ::khui_action_context structure which will be used as the filter.
+
+ For example, the following code will extract the cursor context
+ credentials into the credential set \a my_credset based on the UI
+ context \a my context:
+
+ \code
+ kcdb_credset_extract_filtered(my_credset,
+ NULL,
+ khui_context_cursor_filter,
+ (void *) my_context);
+ \endcode
+*/
+KHMEXP khm_int32 KHMAPI
+khui_context_cursor_filter(khm_handle cred,
+ khm_int32 flags,
+ void * rock);
+
+/*! \brief Get a string representation of an accelerator
+
+ \param[in] cmd Command for which to obtain the accelerator string for
+ \param[out] buf Buffer to receive the accelerator string
+ \param[in] bufsiz Size of the buffer in bytes. Note that the size of the
+ buffer must be sufficient to hold at least one character and a
+ NULL terminator.
+
+ \return TRUE if the operation was successful. FALSE otherwise.
+ */
+KHMEXP khm_boolean KHMAPI khui_get_cmd_accel_string(khm_int32 cmd, wchar_t * buf, khm_size bufsiz);
+
+#ifdef NOEXPORT
+/*! \brief Initializes the global accelerator table
+ */
+KHMEXP HACCEL KHMAPI khui_create_global_accel_table(void);
+#endif
+
+/*! \brief Find a menu by id
+
+ Finds the menu that is associated with the specified action.
+ */
+KHMEXP khui_menu_def * KHMAPI khui_find_menu(khm_int32 action);
+
+#ifdef NOEXPORT
+
+/* internal */
+KHMEXP void KHMAPI
+khui_set_main_window(HWND hwnd);
+
+#endif
+
+/*! \brief Trigger an action
+
+ Triggers the specified action using the specified UI context.
+
+ This function does not return until the specified action has been
+ processed. Many standard actions are asynchronous and they will
+ return before processing will complete.
+
+ Pseudo actions should not be triggered using khui_action_trigger()
+ as they only carry meaning when invoked from specific windows or
+ contexts.
+
+ \param[in] action Action. Should be one of the standard actions
+ or an action created by khui_action_create()
+
+ \param[in] ctx The UI context to use for the action. If this is
+ NULL, the action will be triggered under the current UI context.
+ */
+KHMEXP void KHMAPI
+khui_action_trigger(khm_int32 action, khui_action_context * ctx);
+
+/*! \brief Find an action by id
+
+ \note This function should not be used by plugins. It is there
+ for use by the NetIDMgr application.
+*/
+KHMEXP khui_action * KHMAPI khui_find_action(khm_int32 action);
+
+#ifdef NOEXPORT
+/*! \brief Get the length of the action list */
+KHMEXP size_t KHMAPI khui_action_list_length(khui_action_ref * ref);
+#endif
+
+/*! \brief Create a new action
+
+ Creates a new custom action. The created custom action can be
+ added to menus, toolbars and can be triggered by
+ khui_action_trigger().
+
+ When the action is triggered as a result of the user selecting a
+ menu item, a toolbar item or as a result of calling
+ khui_action_trigger(), the subscription identified by \a hsub will
+ received a message of type ::KMSG_ACT, subtype
+ ::KMSG_ACT_ACTIVATE. The \a uparam for the message will be the
+ action identifier that was returned by khui_action_create(). The
+ \a vparam of the message will currently be set to \a NULL.
+
+ Actions can optionally be named. The name is not actively used by
+ the Network Identity Manager framework, but can be used to label
+ actions so that they can be looked up later using
+ khui_find_named_action().
+
+ \param[in] name Name for a named action. The name must be unique
+ among all registered actions. (limited by KHUI_MAXCCH_NAME).
+ (Optional. Set to NULL if the action is not a named action.)
+ See \a note below for additional restrictions on the name of
+ the action.
+
+ \param[in] caption The localized caption for the action. This
+ will be shown in menus, toolbars and buttons when the action
+ needs to be represented. (limited by KHUI_MAXCCH_SHORT_DESC)
+ (Required)
+
+ \param[in] tooltip The localized tooltip for the action. (limited
+ by KHUI_MAXCCH_SHORT_DESC) (Optional, set to NULL if there is
+ no tooltip associated with the action)
+
+ \param[in] userdata A custom value.
+
+ \param[in] type The type of the action. Currently it should be
+ set to either ::KHUI_ACTIONTYPE_TRIGGER or
+ ::KHUI_ACTIONTYPE_TOGGLE. For ::KHUI_ACTIONTYPE_TOGGLE, the
+ initial state will be unchecked. Use khui_check_action()
+ function to change the checked state of the action.
+
+ \param[in] hsub The subscription that is notified when the action
+ is triggered. (Optional) The subscription must be created with
+ kmq_create_subscription(). The handle will be released when
+ it is no longer needed. Hence, the caller should not release
+ it.
+
+ \return The identifier of the new action or zero if the action
+ could not be created.
+
+ \note For named custom actions, the name of the action can not be
+ the same as the name of a configuration node. See
+ khui_cfg_register_node().
+ */
+KHMEXP khm_int32 KHMAPI
+khui_action_create(const wchar_t * name,
+ const wchar_t * caption,
+ const wchar_t * tooltip,
+ void * userdata,
+ khm_int32 type,
+ khm_handle hsub);
+
+/* \brief Delete a custom action
+
+ Deletes a custom action created by a call to khui_action_create().
+ Custom actions should only be deleted when unloading a plugin.
+ */
+KHMEXP void KHMAPI
+khui_action_delete(khm_int32 action);
+
+/*! \brief Get the user data associated with a custom action
+
+ This function returns the user data that was specified when the
+ custom action was created usng khui_action_create(). If the
+ custom action identifier is invalid or if the custom action does
+ not contain any user data, this function will return NULL.
+ */
+KHMEXP void * KHMAPI
+khui_action_get_data(khm_int32 action);
+
+/*! \brief Find an action by name */
+KHMEXP khui_action * KHMAPI khui_find_named_action(const wchar_t * name);
+
+/*! \brief Enables or disables a group of actions
+
+ The group of actions are specified by the menu definition. All
+ valid action entries in the menu are marked as enabled or disabled
+ according to the value of \a enable.
+ */
+KHMEXP void KHMAPI khui_enable_actions(khui_menu_def * d, khm_boolean enable);
+
+/*! \brief Enables or disables an action
+
+ The action designated by the command \a action will either be enabled
+ or disabled depending on the \a enable parameter. If \a enable is
+ TRUE then the action is enabled.
+ */
+KHMEXP void KHMAPI khui_enable_action(khm_int32 action, khm_boolean enable);
+
+/*! \brief Check an action in an action group
+
+ Marks the action denoted by \a action as checked and resets the
+ checked bit in all other actions.
+
+ \param[in] d A menu definition.
+
+ \param[in] action A command identifier. Setting this to -1 will
+ reset the checked bit in all the actions in the menu
+ definition.
+ */
+KHMEXP void KHMAPI khui_check_radio_action(khui_menu_def * d, khm_int32 action);
+
+/*! \brief Check an action
+
+ For toggle typed actions, this sets or resets the check.
+ */
+KHMEXP void KHMAPI khui_check_action(khm_int32 cmd, khm_boolean check);
+
+#ifdef NOEXPORT
+/*!\cond INTERNAL */
+
+/*! \brief Initialize actions
+
+ \note Only called by the NetIDMgr application
+ */
+KHMEXP void KHMAPI khui_init_actions(void);
+
+/*! \brief Exit actions
+
+ \note Only called by the NetIDMgr application
+ */
+KHMEXP void KHMAPI khui_exit_actions(void);
+
+/*! \endcond */
+#endif
+
+/*@}*/
+/*@}*/
+#endif
diff --git a/src/windows/identity/uilib/khactiondef.h b/src/windows/identity/uilib/khactiondef.h
index 87e2355f1e..08dbad2ad3 100644
--- a/src/windows/identity/uilib/khactiondef.h
+++ b/src/windows/identity/uilib/khactiondef.h
@@ -1,168 +1,168 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- * Copyright (c) 2007 Secure Endpoints Inc.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#ifndef __KHIMAIRA_ACTIONDEF_H
-#define __KHIMAIRA_ACTIONDEF_H
-
-/*! \ingroup khui_actions
- @{*/
-/*! \defgroup khui_std_actions Standard Actions
-@{ */
-
-/*!\name Standard actions
- @{*/
-#define KHUI_ACTION_BASE 50000
-
-#define KHUI_ACTION_PROPERTIES (KHUI_ACTION_BASE + 0)
-#define KHUI_ACTION_EXIT (KHUI_ACTION_BASE + 1)
-#define KHUI_ACTION_SET_DEF_ID (KHUI_ACTION_BASE + 3)
-#define KHUI_ACTION_SET_SRCH_ID (KHUI_ACTION_BASE + 4)
-#define KHUI_ACTION_PASSWD_ID (KHUI_ACTION_BASE + 7)
-#define KHUI_ACTION_NEW_CRED (KHUI_ACTION_BASE + 8)
-#define KHUI_ACTION_DEBUG_WINDOW (KHUI_ACTION_BASE + 10)
-#define KHUI_ACTION_VIEW_REFRESH (KHUI_ACTION_BASE + 11)
-#define KHUI_ACTION_LAYOUT_ID (KHUI_ACTION_BASE + 12)
-#define KHUI_ACTION_LAYOUT_TYPE (KHUI_ACTION_BASE + 13)
-#define KHUI_ACTION_LAYOUT_LOC (KHUI_ACTION_BASE + 14)
-#define KHUI_ACTION_TB_STANDARD (KHUI_ACTION_BASE + 15)
-#define KHUI_ACTION_OPT_KHIM (KHUI_ACTION_BASE + 16)
-#define KHUI_ACTION_OPT_IDENTS (KHUI_ACTION_BASE + 17)
-#define KHUI_ACTION_OPT_NOTIF (KHUI_ACTION_BASE + 18)
-#define KHUI_ACTION_HELP_CTX (KHUI_ACTION_BASE + 19)
-#define KHUI_ACTION_HELP_CONTENTS (KHUI_ACTION_BASE + 20)
-#define KHUI_ACTION_HELP_INDEX (KHUI_ACTION_BASE + 21)
-#define KHUI_ACTION_HELP_ABOUT (KHUI_ACTION_BASE + 22)
-#define KHUI_ACTION_DESTROY_CRED (KHUI_ACTION_BASE + 23)
-#define KHUI_ACTION_RENEW_CRED (KHUI_ACTION_BASE + 24)
-#define KHUI_ACTION_OPEN_APP (KHUI_ACTION_BASE + 25)
-#define KHUI_ACTION_MENU_ACTIVATE (KHUI_ACTION_BASE + 26)
-#define KHUI_ACTION_CLOSE_APP (KHUI_ACTION_BASE + 27)
-#define KHUI_ACTION_IMPORT (KHUI_ACTION_BASE + 28)
-#define KHUI_ACTION_OPT_PLUGINS (KHUI_ACTION_BASE + 29)
-#define KHUI_ACTION_LAYOUT_CUST (KHUI_ACTION_BASE + 30)
-#define KHUI_ACTION_OPT_APPEAR (KHUI_ACTION_BASE + 31)
-#define KHUI_ACTION_LAYOUT_RELOAD (KHUI_ACTION_BASE + 32)
-#define KHUI_ACTION_RENEW_ALL (KHUI_ACTION_BASE + 33)
-#define KHUI_ACTION_DESTROY_ALL (KHUI_ACTION_BASE + 34)
-#define KHUI_ACTION_UICB (KHUI_ACTION_BASE + 35)
-#define KHUI_ACTION_LAYOUT_MINI (KHUI_ACTION_BASE + 36)
-/*@}*/
-
-/*! \name Pseudo actions
-
-Pseudo actions do not trigger any specific function, but acts as a
-signal of some generic event which will be interpreted based on
-context.
-
-@{*/
-#define KHUI_PACTION_BASE (KHUI_ACTION_BASE + 500)
-
-#define KHUI_PACTION_MENU (KHUI_PACTION_BASE + 0)
-#define KHUI_PACTION_UP (KHUI_PACTION_BASE + 1)
-#define KHUI_PACTION_DOWN (KHUI_PACTION_BASE + 2)
-#define KHUI_PACTION_LEFT (KHUI_PACTION_BASE + 3)
-#define KHUI_PACTION_RIGHT (KHUI_PACTION_BASE + 4)
-#define KHUI_PACTION_ENTER (KHUI_PACTION_BASE + 5)
-#define KHUI_PACTION_ESC (KHUI_PACTION_BASE + 6)
-#define KHUI_PACTION_OK (KHUI_PACTION_BASE + 7)
-#define KHUI_PACTION_CANCEL (KHUI_PACTION_BASE + 8)
-#define KHUI_PACTION_CLOSE (KHUI_PACTION_BASE + 9)
-#define KHUI_PACTION_DELETE (KHUI_PACTION_BASE + 10)
-#define KHUI_PACTION_UP_EXTEND (KHUI_PACTION_BASE + 11)
-#define KHUI_PACTION_UP_TOGGLE (KHUI_PACTION_BASE + 12)
-#define KHUI_PACTION_DOWN_EXTEND (KHUI_PACTION_BASE + 13)
-#define KHUI_PACTION_DOWN_TOGGLE (KHUI_PACTION_BASE + 14)
-#define KHUI_PACTION_BLANK (KHUI_PACTION_BASE + 15)
-#define KHUI_PACTION_NEXT (KHUI_PACTION_BASE + 16)
-#define KHUI_PACTION_SELALL (KHUI_PACTION_BASE + 17)
-#define KHUI_PACTION_YES (KHUI_PACTION_BASE + 18)
-#define KHUI_PACTION_NO (KHUI_PACTION_BASE + 19)
-#define KHUI_PACTION_YESALL (KHUI_PACTION_BASE + 20)
-#define KHUI_PACTION_NOALL (KHUI_PACTION_BASE + 21)
-#define KHUI_PACTION_REMOVE (KHUI_PACTION_BASE + 22)
-#define KHUI_PACTION_KEEP (KHUI_PACTION_BASE + 23)
-#define KHUI_PACTION_DISCARD (KHUI_PACTION_BASE + 24)
-#define KHUI_PACTION_PGDN (KHUI_PACTION_BASE + 25)
-#define KHUI_PACTION_PGUP (KHUI_PACTION_BASE + 26)
-#define KHUI_PACTION_PGUP_EXTEND (KHUI_PACTION_BASE + 27)
-#define KHUI_PACTION_PGDN_EXTEND (KHUI_PACTION_BASE + 28)
-
-/*@}*/
-
-/*! \name Menus
-
-Stock menus.
-
-@{*/
-#define KHUI_MENU_BASE (KHUI_ACTION_BASE + 1000)
-
-#define KHUI_MENU_MAIN (KHUI_MENU_BASE + 0)
-#define KHUI_MENU_FILE (KHUI_MENU_BASE + 1)
-#define KHUI_MENU_CRED (KHUI_MENU_BASE + 2)
-#define KHUI_MENU_VIEW (KHUI_MENU_BASE + 3)
-#define KHUI_MENU_OPTIONS (KHUI_MENU_BASE + 4)
-#define KHUI_MENU_HELP (KHUI_MENU_BASE + 5)
-
-#define KHUI_MENU_LAYOUT (KHUI_MENU_BASE + 6)
-#define KHUI_MENU_TOOLBARS (KHUI_MENU_BASE + 7)
-
-#define KHUI_MENU_IDENT_CTX (KHUI_MENU_BASE + 8)
-#define KHUI_MENU_TOK_CTX (KHUI_MENU_BASE + 9)
-#define KHUI_MENU_ICO_CTX_MIN (KHUI_MENU_BASE + 12)
-#define KHUI_MENU_ICO_CTX_NORMAL (KHUI_MENU_BASE + 13)
-#define KHUI_MENU_CWHEADER_CTX (KHUI_MENU_BASE + 14)
-
-#define KHUI_MENU_COLUMNS (KHUI_MENU_BASE + 15)
-
-#define KHUI_PMENU_TOK_SEL (KHUI_MENU_BASE + 10)
-#define KHUI_PMENU_ID_SEL (KHUI_MENU_BASE + 11)
-
-#define KHUI_MENU_DESTROY_CRED (KHUI_MENU_BASE + 16)
-#define KHUI_MENU_RENEW_CRED (KHUI_MENU_BASE + 17)
-
-/*@}*/
-
-/*! \name Toolbars
-@{*/
-#define KHUI_TOOLBAR_BASE (KHUI_ACTION_BASE + 2000)
-
-#define KHUI_TOOLBAR_STANDARD (KHUI_TOOLBAR_BASE + 0)
-/*@}*/
-
-/*! \brief Base for user actions
-
- When creating new actions, the UI library will allocate command
- identifiers starting with this one.
-*/
-#define KHUI_USERACTION_BASE (KHUI_ACTION_BASE + 10000)
-
-/*! \brief Does this command represent a user action? */
-#define IS_USERACTION(cmd) ((cmd) >= KHUI_USERACTION_BASE)
-/*@}*/
-/*@}*/
-
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ * Copyright (c) 2007 Secure Endpoints Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __KHIMAIRA_ACTIONDEF_H
+#define __KHIMAIRA_ACTIONDEF_H
+
+/*! \ingroup khui_actions
+ @{*/
+/*! \defgroup khui_std_actions Standard Actions
+@{ */
+
+/*!\name Standard actions
+ @{*/
+#define KHUI_ACTION_BASE 50000
+
+#define KHUI_ACTION_PROPERTIES (KHUI_ACTION_BASE + 0)
+#define KHUI_ACTION_EXIT (KHUI_ACTION_BASE + 1)
+#define KHUI_ACTION_SET_DEF_ID (KHUI_ACTION_BASE + 3)
+#define KHUI_ACTION_SET_SRCH_ID (KHUI_ACTION_BASE + 4)
+#define KHUI_ACTION_PASSWD_ID (KHUI_ACTION_BASE + 7)
+#define KHUI_ACTION_NEW_CRED (KHUI_ACTION_BASE + 8)
+#define KHUI_ACTION_DEBUG_WINDOW (KHUI_ACTION_BASE + 10)
+#define KHUI_ACTION_VIEW_REFRESH (KHUI_ACTION_BASE + 11)
+#define KHUI_ACTION_LAYOUT_ID (KHUI_ACTION_BASE + 12)
+#define KHUI_ACTION_LAYOUT_TYPE (KHUI_ACTION_BASE + 13)
+#define KHUI_ACTION_LAYOUT_LOC (KHUI_ACTION_BASE + 14)
+#define KHUI_ACTION_TB_STANDARD (KHUI_ACTION_BASE + 15)
+#define KHUI_ACTION_OPT_KHIM (KHUI_ACTION_BASE + 16)
+#define KHUI_ACTION_OPT_IDENTS (KHUI_ACTION_BASE + 17)
+#define KHUI_ACTION_OPT_NOTIF (KHUI_ACTION_BASE + 18)
+#define KHUI_ACTION_HELP_CTX (KHUI_ACTION_BASE + 19)
+#define KHUI_ACTION_HELP_CONTENTS (KHUI_ACTION_BASE + 20)
+#define KHUI_ACTION_HELP_INDEX (KHUI_ACTION_BASE + 21)
+#define KHUI_ACTION_HELP_ABOUT (KHUI_ACTION_BASE + 22)
+#define KHUI_ACTION_DESTROY_CRED (KHUI_ACTION_BASE + 23)
+#define KHUI_ACTION_RENEW_CRED (KHUI_ACTION_BASE + 24)
+#define KHUI_ACTION_OPEN_APP (KHUI_ACTION_BASE + 25)
+#define KHUI_ACTION_MENU_ACTIVATE (KHUI_ACTION_BASE + 26)
+#define KHUI_ACTION_CLOSE_APP (KHUI_ACTION_BASE + 27)
+#define KHUI_ACTION_IMPORT (KHUI_ACTION_BASE + 28)
+#define KHUI_ACTION_OPT_PLUGINS (KHUI_ACTION_BASE + 29)
+#define KHUI_ACTION_LAYOUT_CUST (KHUI_ACTION_BASE + 30)
+#define KHUI_ACTION_OPT_APPEAR (KHUI_ACTION_BASE + 31)
+#define KHUI_ACTION_LAYOUT_RELOAD (KHUI_ACTION_BASE + 32)
+#define KHUI_ACTION_RENEW_ALL (KHUI_ACTION_BASE + 33)
+#define KHUI_ACTION_DESTROY_ALL (KHUI_ACTION_BASE + 34)
+#define KHUI_ACTION_UICB (KHUI_ACTION_BASE + 35)
+#define KHUI_ACTION_LAYOUT_MINI (KHUI_ACTION_BASE + 36)
+/*@}*/
+
+/*! \name Pseudo actions
+
+Pseudo actions do not trigger any specific function, but acts as a
+signal of some generic event which will be interpreted based on
+context.
+
+@{*/
+#define KHUI_PACTION_BASE (KHUI_ACTION_BASE + 500)
+
+#define KHUI_PACTION_MENU (KHUI_PACTION_BASE + 0)
+#define KHUI_PACTION_UP (KHUI_PACTION_BASE + 1)
+#define KHUI_PACTION_DOWN (KHUI_PACTION_BASE + 2)
+#define KHUI_PACTION_LEFT (KHUI_PACTION_BASE + 3)
+#define KHUI_PACTION_RIGHT (KHUI_PACTION_BASE + 4)
+#define KHUI_PACTION_ENTER (KHUI_PACTION_BASE + 5)
+#define KHUI_PACTION_ESC (KHUI_PACTION_BASE + 6)
+#define KHUI_PACTION_OK (KHUI_PACTION_BASE + 7)
+#define KHUI_PACTION_CANCEL (KHUI_PACTION_BASE + 8)
+#define KHUI_PACTION_CLOSE (KHUI_PACTION_BASE + 9)
+#define KHUI_PACTION_DELETE (KHUI_PACTION_BASE + 10)
+#define KHUI_PACTION_UP_EXTEND (KHUI_PACTION_BASE + 11)
+#define KHUI_PACTION_UP_TOGGLE (KHUI_PACTION_BASE + 12)
+#define KHUI_PACTION_DOWN_EXTEND (KHUI_PACTION_BASE + 13)
+#define KHUI_PACTION_DOWN_TOGGLE (KHUI_PACTION_BASE + 14)
+#define KHUI_PACTION_BLANK (KHUI_PACTION_BASE + 15)
+#define KHUI_PACTION_NEXT (KHUI_PACTION_BASE + 16)
+#define KHUI_PACTION_SELALL (KHUI_PACTION_BASE + 17)
+#define KHUI_PACTION_YES (KHUI_PACTION_BASE + 18)
+#define KHUI_PACTION_NO (KHUI_PACTION_BASE + 19)
+#define KHUI_PACTION_YESALL (KHUI_PACTION_BASE + 20)
+#define KHUI_PACTION_NOALL (KHUI_PACTION_BASE + 21)
+#define KHUI_PACTION_REMOVE (KHUI_PACTION_BASE + 22)
+#define KHUI_PACTION_KEEP (KHUI_PACTION_BASE + 23)
+#define KHUI_PACTION_DISCARD (KHUI_PACTION_BASE + 24)
+#define KHUI_PACTION_PGDN (KHUI_PACTION_BASE + 25)
+#define KHUI_PACTION_PGUP (KHUI_PACTION_BASE + 26)
+#define KHUI_PACTION_PGUP_EXTEND (KHUI_PACTION_BASE + 27)
+#define KHUI_PACTION_PGDN_EXTEND (KHUI_PACTION_BASE + 28)
+
+/*@}*/
+
+/*! \name Menus
+
+Stock menus.
+
+@{*/
+#define KHUI_MENU_BASE (KHUI_ACTION_BASE + 1000)
+
+#define KHUI_MENU_MAIN (KHUI_MENU_BASE + 0)
+#define KHUI_MENU_FILE (KHUI_MENU_BASE + 1)
+#define KHUI_MENU_CRED (KHUI_MENU_BASE + 2)
+#define KHUI_MENU_VIEW (KHUI_MENU_BASE + 3)
+#define KHUI_MENU_OPTIONS (KHUI_MENU_BASE + 4)
+#define KHUI_MENU_HELP (KHUI_MENU_BASE + 5)
+
+#define KHUI_MENU_LAYOUT (KHUI_MENU_BASE + 6)
+#define KHUI_MENU_TOOLBARS (KHUI_MENU_BASE + 7)
+
+#define KHUI_MENU_IDENT_CTX (KHUI_MENU_BASE + 8)
+#define KHUI_MENU_TOK_CTX (KHUI_MENU_BASE + 9)
+#define KHUI_MENU_ICO_CTX_MIN (KHUI_MENU_BASE + 12)
+#define KHUI_MENU_ICO_CTX_NORMAL (KHUI_MENU_BASE + 13)
+#define KHUI_MENU_CWHEADER_CTX (KHUI_MENU_BASE + 14)
+
+#define KHUI_MENU_COLUMNS (KHUI_MENU_BASE + 15)
+
+#define KHUI_PMENU_TOK_SEL (KHUI_MENU_BASE + 10)
+#define KHUI_PMENU_ID_SEL (KHUI_MENU_BASE + 11)
+
+#define KHUI_MENU_DESTROY_CRED (KHUI_MENU_BASE + 16)
+#define KHUI_MENU_RENEW_CRED (KHUI_MENU_BASE + 17)
+
+/*@}*/
+
+/*! \name Toolbars
+@{*/
+#define KHUI_TOOLBAR_BASE (KHUI_ACTION_BASE + 2000)
+
+#define KHUI_TOOLBAR_STANDARD (KHUI_TOOLBAR_BASE + 0)
+/*@}*/
+
+/*! \brief Base for user actions
+
+ When creating new actions, the UI library will allocate command
+ identifiers starting with this one.
+*/
+#define KHUI_USERACTION_BASE (KHUI_ACTION_BASE + 10000)
+
+/*! \brief Does this command represent a user action? */
+#define IS_USERACTION(cmd) ((cmd) >= KHUI_USERACTION_BASE)
+/*@}*/
+/*@}*/
+
+#endif
diff --git a/src/windows/identity/uilib/khalerts.h b/src/windows/identity/uilib/khalerts.h
index 7f0e624b44..751abce013 100644
--- a/src/windows/identity/uilib/khalerts.h
+++ b/src/windows/identity/uilib/khalerts.h
@@ -1,403 +1,403 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#ifndef __KHIMAIRA_KHALERTS_H
-#define __KHIMAIRA_KHALERTS_H
-
-/*********************************************************************
- Alerter and error reporting
-**********************************************************************/
-
-/*! \addtogroup khui
-@{ */
-
-/*!\defgroup khui_alert Alerter and Error Reporting
-@{*/
-
-struct tag_khui_alert;
-typedef struct tag_khui_alert khui_alert;
-
-#define KHUI_MAX_ALERT_COMMANDS 4
-
-/*! \brief Maximum number of characters in title including terminating NULL
- */
-#define KHUI_MAXCCH_TITLE 256
-
-/*! \brief Maximum number of bytes in title including terminating NULL
- */
-#define KHUI_MAXCB_TITLE (KHUI_MAXCCH_TITLE * sizeof(wchar_t))
-
-/*! \brief Maximum number of characters in message including terminating NULL
- */
-#define KHUI_MAXCCH_MESSAGE 1024
-
-/*! \brief Maximum number of bytes in message including terminating NULL
- */
-#define KHUI_MAXCB_MESSAGE (KHUI_MAXCCH_MESSAGE * sizeof(wchar_t))
-
-/*! \brief Maxumum number of characters in a suggestion including terminating NULL */
-#define KHUI_MAXCCH_SUGGESTION 1024
-
-/*! \brief Maximum number of bytes in a suggestion, including terminating NULL */
-#define KHUI_MAXCB_SUGGESTION (KHUI_MAXCCH_SUGGESTION * sizeof(wchar_t))
-
-/*! \brief Flags for an alert */
-enum khui_alert_flags {
- KHUI_ALERT_FLAG_FREE_STRUCT =0x00000001,
- /*!< Internal. Free the structure once the alert is done. */
-
- KHUI_ALERT_FLAG_FREE_TITLE =0x00000002,
- /*!< Internal. Free the \a title field when the alert is done.*/
-
- KHUI_ALERT_FLAG_FREE_MESSAGE =0x00000004,
- /*!< Internal. Free the \a message field when the alert is done. */
-
- KHUI_ALERT_FLAG_FREE_SUGGEST =0x00000008,
- /*!< Internal. Free the \a suggest field when the alert is done */
-
- KHUI_ALERT_FLAG_DEFACTION =0x00000010,
- /*!< If the message is displayed as a balloon prompt, then perform
- the default action when it is clicked. The default action is
- the first action added to the alert. Cannot be used if there
- are no actions or if ::KHUI_ALERT_FLAG_REQUEST_WINDOW is
- specified.*/
-
- KHUI_ALERT_FLAG_DISPATCH_CMD =0x00000020,
- /*!< If the message has commands, when the user clicks on one of
- the command buttons, the corresponding command will be
- immediately dispatched as if khui_action_trigger() is called
- with a NULL UI context. Otherwise, the selected command will be
- stored in the alert and can be retrieved via a call to
- khui_alert_get_response(). */
-
- KHUI_ALERT_FLAG_VALID_TARGET =0x00010000,
- /*!< Internal. There is a valid target for the alert */
-
- KHUI_ALERT_FLAG_VALID_ERROR =0x00020000,
- /*!< Internal. There is a valid error context associated with the alert */
-
- KHUI_ALERT_FLAG_DISPLAY_WINDOW =0x01000000,
- /*!< The alert has been displayed in a window */
-
- KHUI_ALERT_FLAG_DISPLAY_BALLOON =0x02000000,
- /*!< The alert has been displayed in a ballon */
-
- KHUI_ALERT_FLAG_REQUEST_WINDOW =0x04000000,
- /*!< The alert should be displayed in a window */
-
- KHUI_ALERT_FLAG_REQUEST_BALLOON =0x08000000,
- /*!< The alert should be displayed in a balloon */
-
- KHUI_ALERT_FLAG_MODAL =0x10000000,
- /*!< Internal. Modal alert. Do not set direclty. */
-
- KHUI_ALERT_FLAGMASK_RDWR =0x0C000030,
- /*!< Bit mask of flags that can be set by khui_alert_set_flags() */
-};
-
-/*! \brief Alert types
-
- These types can be set with khui_alert_set_type() to indicate
- which type of alert this is. The types defined here are
- identified by the Network Identity Manager and will receive
- special handling whereever appropriate.
-
- The type is a hint to the application and will not guarantee a
- particular behavior.
- */
-typedef enum tag_khui_alert_types {
- KHUI_ALERTTYPE_NONE = 0, /*!< No specific alert type */
- KHUI_ALERTTYPE_PLUGIN, /*!< Plug-in or module load related
- alert */
- KHUI_ALERTTYPE_EXPIRE, /*!< Credential or identity expiration
- warning */
- KHUI_ALERTTYPE_RENEWFAIL, /*!< Failed to renew credentials */
- KHUI_ALERTTYPE_ACQUIREFAIL, /*!< Failed to acquire credentials */
- KHUI_ALERTTYPE_CHPW, /*!< Failed to change password */
-} khui_alert_type;
-
-/*! \brief Create an empty alert object
-
- The returned result is a held pointer to a ::khui_alert object.
- Use khui_alert_release() to release the object.
- */
-KHMEXP khm_int32 KHMAPI
-khui_alert_create_empty(khui_alert ** result);
-
-/*! \brief Create a simple alert object
-
- The returned result is a held pointer to a ::khui_alert object.
- Use khui_alert_release() to release the object.
-
- \param[in] title The title of the alert. (Required, Localized)
- Limited by ::KHUI_MAXCCH_TITLE.
-
- \param[in] message The message. (Required. Localized). Limited
- by ::KHUI_MAXCCH_MESSAGE.
-
- \param[in] severity One of ::tag_kherr_severity
-
- \param[out] result Receives a held pointer to a ::khui_alert
- object upon successful completion.
- */
-KHMEXP khm_int32 KHMAPI
-khui_alert_create_simple(const wchar_t * title,
- const wchar_t * message,
- khm_int32 severity,
- khui_alert ** result);
-
-/*! \brief Set the title of an alert object
-
- The title is limited by ::KHUI_MAXCCH_TITLE.
- */
-KHMEXP khm_int32 KHMAPI
-khui_alert_set_title(khui_alert * alert,
- const wchar_t * title);
-
-/*! \brief Set the message of an alert object
-
- The message is limited by ::KHUI_MAXCCH_MESSAGE.
- */
-KHMEXP khm_int32 KHMAPI
-khui_alert_set_message(khui_alert * alert,
- const wchar_t * message);
-
-/*! \brief Set the suggestion of an alert object
-
- The suggestion is limited by ::KHUI_MAXCCH_SUGGESTION
- */
-KHMEXP khm_int32 KHMAPI
-khui_alert_set_suggestion(khui_alert * alert,
- const wchar_t * suggestion);
-
-/*! \brief Set the severity of the alert object
-
- The severity value is one of ::tag_kherr_severity
- */
-KHMEXP khm_int32 KHMAPI
-khui_alert_set_severity(khui_alert * alert,
- khm_int32 severity);
-
-/*! \brief Sets the flags of the alert
-
- The flags are as defined in ::khui_alert_flags. The bits that are
- on in \a mask will be set to the corresponding values in \a flags.
- Only the bits specified in ::KHUI_ALERT_FLAGMASK_RDWR can be
- specified in \a mask.
- */
-KHMEXP khm_int32 KHMAPI
-khui_alert_set_flags(khui_alert * alert, khm_int32 mask, khm_int32 flags);
-
-/*! \brief Clear all the commands from an alert object
-
- \see khui_alert_add_command()
- */
-KHMEXP khm_int32 KHMAPI
-khui_alert_clear_commands(khui_alert * alert);
-
-/*! \brief Add a command to an alert object
-
- The command ID should be a valid registered action.
- */
-KHMEXP khm_int32 KHMAPI
-khui_alert_add_command(khui_alert * alert,
- khm_int32 command_id);
-
-/*! \brief Set the type of alert
- */
-KHMEXP khm_int32 KHMAPI
-khui_alert_set_type(khui_alert * alert,
- khui_alert_type type);
-
-/*! \brief Set the action context for the alert */
-KHMEXP khm_int32 KHMAPI
-khui_alert_set_ctx(khui_alert * alert,
- khui_scope scope,
- khm_handle identity,
- khm_int32 cred_type,
- khm_handle cred);
-
-/*! \brief Get the response code from an alert
-
- Once an alert has been displayed to the user, the user may choose
- a command from the list of commands provided in the alert (see
- khui_alert_add_command() ). This function can retrieve the
- selected command from the alert.
-
- \return The selected command or \a 0 if no commands were selected.
- */
-KHMEXP khm_int32 KHMAPI
-khui_alert_get_response(khui_alert * alert);
-
-
-/*! \brief Display an alert
-
- The alert must have a valid \a severity, \a title and a \a message
- to be displayed. Otherwise the function immediately returns with
- a failure code.
-
- The method used to display the alert is as follows:
-
- - A balloon alert will be shown if one of the following is true:
- - The NetIDMgr application is minimized or in the background.
- - ::KHUI_ALERT_FLAG_REQUEST_BALLOON is specified in \a flags.
- - Otherwise an alert window will be shown.
-
- If the message, title of the alert is too long to fit in a balloon
- prompt, there's a suggestion or if there are custom commands then
- a placeholder balloon prompt will be shown which when clicked on,
- shows the actual alert in an alert window.
-
- An exception is when ::KHUI_ALERT_FLAG_DEFACTION is specified in
- flags. In this case instead of a placeholder balloon prompt, one
- will be shown with the actual title and message (truncated if
- necessary). Clicking on the balloon will cause the first command
- in the command list to be performed.
-
- The placeholder balloon prompt will have a title derived from the
- first 63 characters of the \a title field in the alert and a
- message notifying the user that they should click the balloon
- prompt for more information.
-
- To this end, it is beneficial to limit the length of the title to
- 63 characters (64 counting the terminating NULL). This limit is
- enforced on Windows. Also, try to make the title descriptive.
-
- User interaction with the alert will be as follows:
-
- - If the alert contains no commands, then the alert will be
- displayed to the user as described above. A 'close' button will
- be added to the alert if the alert is being displayed in a
- window.
-
- - If the alert contains commands, has the
- ::KHUI_ALERT_FLAG_DEFACTION flag set and is displayed in a
- balloon and the user clicks on it, the first command in the
- command list will be executed.
-
- - If the alert contains commands and does not have the
- ::KHUI_ALERT_FLAG_DEFACTION and has the
- ::KHUI_ALERT_FLAG_DISPATCH_CMD flag set, then when the user
- selects one of the command buttons, the corresponding command
- will immediately be dispatched. (see
- ::KHUI_ALERT_FLAG_DISPATCH_CMD).
-
- - If the alert contains command and have neither
- ::KHUI_ALERT_FLAG_DEFACTION nor ::KHUI_ALERT_FLAG_DISPATCH_CMD,
- then when the user selects one of the command buttons, the
- selected command will be stored along with the alert. It can be
- retrieved via a call to khui_alert_get_response().
-
- */
-KHMEXP khm_int32 KHMAPI
-khui_alert_show(khui_alert * alert);
-
-/*! \brief Display a modal alert
-
- Similar to khui_alert_show(), but shows a modal alert dialog. The
- function does not return until the user has closed the alert.
-
- This function always opens an alert window (never shows a
- balloon).
-
- */
-KHMEXP khm_int32 KHMAPI
-khui_alert_show_modal(khui_alert * alert);
-
-/*! \brief Queue an alert
-
- Instead of displaying the alert immediately, the alert is queued
- and the status bar updated to notify the user that there is a
- pending alert. Once the user activates the pending alert, it will
- be displayed as if khui_alert_show() was called.
- */
-KHMEXP khm_int32 KHMAPI
-khui_alert_queue(khui_alert * alert);
-
-/*! \brief Display a simple alert
-
- \see khui_alert_show()
- */
-KHMEXP khm_int32 KHMAPI
-khui_alert_show_simple(const wchar_t * title,
- const wchar_t * message,
- khm_int32 severity);
-
-/*! \brief Obtain a hold on the alert
-
- An alert structure is only considered valid for the duration that
- there is a hold on it.
-
- Use khui_alert_release() to release the hold.
- */
-KHMEXP khm_int32 KHMAPI
-khui_alert_hold(khui_alert * alert);
-
-/*! \brief Release the hold on the alert
-
- Holds obtained on an alert using any of the functions that either
- return a held pointer to an alert or implicitly obtains a hold on
- it need to be undone through a call to khui_alert_release().
- */
-KHMEXP khm_int32 KHMAPI
-khui_alert_release(khui_alert * alert);
-
-/*! \brief Lock an alert
-
- Locking an alert disallows any other thread from accessing the
- alert at the same time. NetIDMgr keeps a global list of all alert
- objects and the user interface may access any of them at various
- points in time. Locking the alert allows a thread to modify an
- alert without causing another thread to be exposed to an
- inconsistent state.
-
- Once a thread obtains a lock on the alert, it must call
- khui_alert_unlock() to unlock it. Otherwise no other thread will
- be able to access the alert.
-
- \note Currently the alert lock is global. Locking one alert
- disallows access to all other alerts as well.
-
- \note Calling khui_alert_lock() is only necessary if you are
- accessing the ::khui_alert structure directly. Calling any of
- the khui_alert_* functions to modify the alert does not
- require obtaining a lock, as they perform synchronization
- internally.
-*/
-KHMEXP void KHMAPI
-khui_alert_lock(khui_alert * alert);
-
-/*! \brief Unlock an alert
-
- \see khui_alert_lock()
-*/
-KHMEXP void KHMAPI
-khui_alert_unlock(khui_alert * alert);
-
-/*!@}*/
-/*!@}*/
-
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __KHIMAIRA_KHALERTS_H
+#define __KHIMAIRA_KHALERTS_H
+
+/*********************************************************************
+ Alerter and error reporting
+**********************************************************************/
+
+/*! \addtogroup khui
+@{ */
+
+/*!\defgroup khui_alert Alerter and Error Reporting
+@{*/
+
+struct tag_khui_alert;
+typedef struct tag_khui_alert khui_alert;
+
+#define KHUI_MAX_ALERT_COMMANDS 4
+
+/*! \brief Maximum number of characters in title including terminating NULL
+ */
+#define KHUI_MAXCCH_TITLE 256
+
+/*! \brief Maximum number of bytes in title including terminating NULL
+ */
+#define KHUI_MAXCB_TITLE (KHUI_MAXCCH_TITLE * sizeof(wchar_t))
+
+/*! \brief Maximum number of characters in message including terminating NULL
+ */
+#define KHUI_MAXCCH_MESSAGE 1024
+
+/*! \brief Maximum number of bytes in message including terminating NULL
+ */
+#define KHUI_MAXCB_MESSAGE (KHUI_MAXCCH_MESSAGE * sizeof(wchar_t))
+
+/*! \brief Maxumum number of characters in a suggestion including terminating NULL */
+#define KHUI_MAXCCH_SUGGESTION 1024
+
+/*! \brief Maximum number of bytes in a suggestion, including terminating NULL */
+#define KHUI_MAXCB_SUGGESTION (KHUI_MAXCCH_SUGGESTION * sizeof(wchar_t))
+
+/*! \brief Flags for an alert */
+enum khui_alert_flags {
+ KHUI_ALERT_FLAG_FREE_STRUCT =0x00000001,
+ /*!< Internal. Free the structure once the alert is done. */
+
+ KHUI_ALERT_FLAG_FREE_TITLE =0x00000002,
+ /*!< Internal. Free the \a title field when the alert is done.*/
+
+ KHUI_ALERT_FLAG_FREE_MESSAGE =0x00000004,
+ /*!< Internal. Free the \a message field when the alert is done. */
+
+ KHUI_ALERT_FLAG_FREE_SUGGEST =0x00000008,
+ /*!< Internal. Free the \a suggest field when the alert is done */
+
+ KHUI_ALERT_FLAG_DEFACTION =0x00000010,
+ /*!< If the message is displayed as a balloon prompt, then perform
+ the default action when it is clicked. The default action is
+ the first action added to the alert. Cannot be used if there
+ are no actions or if ::KHUI_ALERT_FLAG_REQUEST_WINDOW is
+ specified.*/
+
+ KHUI_ALERT_FLAG_DISPATCH_CMD =0x00000020,
+ /*!< If the message has commands, when the user clicks on one of
+ the command buttons, the corresponding command will be
+ immediately dispatched as if khui_action_trigger() is called
+ with a NULL UI context. Otherwise, the selected command will be
+ stored in the alert and can be retrieved via a call to
+ khui_alert_get_response(). */
+
+ KHUI_ALERT_FLAG_VALID_TARGET =0x00010000,
+ /*!< Internal. There is a valid target for the alert */
+
+ KHUI_ALERT_FLAG_VALID_ERROR =0x00020000,
+ /*!< Internal. There is a valid error context associated with the alert */
+
+ KHUI_ALERT_FLAG_DISPLAY_WINDOW =0x01000000,
+ /*!< The alert has been displayed in a window */
+
+ KHUI_ALERT_FLAG_DISPLAY_BALLOON =0x02000000,
+ /*!< The alert has been displayed in a ballon */
+
+ KHUI_ALERT_FLAG_REQUEST_WINDOW =0x04000000,
+ /*!< The alert should be displayed in a window */
+
+ KHUI_ALERT_FLAG_REQUEST_BALLOON =0x08000000,
+ /*!< The alert should be displayed in a balloon */
+
+ KHUI_ALERT_FLAG_MODAL =0x10000000,
+ /*!< Internal. Modal alert. Do not set direclty. */
+
+ KHUI_ALERT_FLAGMASK_RDWR =0x0C000030,
+ /*!< Bit mask of flags that can be set by khui_alert_set_flags() */
+};
+
+/*! \brief Alert types
+
+ These types can be set with khui_alert_set_type() to indicate
+ which type of alert this is. The types defined here are
+ identified by the Network Identity Manager and will receive
+ special handling whereever appropriate.
+
+ The type is a hint to the application and will not guarantee a
+ particular behavior.
+ */
+typedef enum tag_khui_alert_types {
+ KHUI_ALERTTYPE_NONE = 0, /*!< No specific alert type */
+ KHUI_ALERTTYPE_PLUGIN, /*!< Plug-in or module load related
+ alert */
+ KHUI_ALERTTYPE_EXPIRE, /*!< Credential or identity expiration
+ warning */
+ KHUI_ALERTTYPE_RENEWFAIL, /*!< Failed to renew credentials */
+ KHUI_ALERTTYPE_ACQUIREFAIL, /*!< Failed to acquire credentials */
+ KHUI_ALERTTYPE_CHPW, /*!< Failed to change password */
+} khui_alert_type;
+
+/*! \brief Create an empty alert object
+
+ The returned result is a held pointer to a ::khui_alert object.
+ Use khui_alert_release() to release the object.
+ */
+KHMEXP khm_int32 KHMAPI
+khui_alert_create_empty(khui_alert ** result);
+
+/*! \brief Create a simple alert object
+
+ The returned result is a held pointer to a ::khui_alert object.
+ Use khui_alert_release() to release the object.
+
+ \param[in] title The title of the alert. (Required, Localized)
+ Limited by ::KHUI_MAXCCH_TITLE.
+
+ \param[in] message The message. (Required. Localized). Limited
+ by ::KHUI_MAXCCH_MESSAGE.
+
+ \param[in] severity One of ::tag_kherr_severity
+
+ \param[out] result Receives a held pointer to a ::khui_alert
+ object upon successful completion.
+ */
+KHMEXP khm_int32 KHMAPI
+khui_alert_create_simple(const wchar_t * title,
+ const wchar_t * message,
+ khm_int32 severity,
+ khui_alert ** result);
+
+/*! \brief Set the title of an alert object
+
+ The title is limited by ::KHUI_MAXCCH_TITLE.
+ */
+KHMEXP khm_int32 KHMAPI
+khui_alert_set_title(khui_alert * alert,
+ const wchar_t * title);
+
+/*! \brief Set the message of an alert object
+
+ The message is limited by ::KHUI_MAXCCH_MESSAGE.
+ */
+KHMEXP khm_int32 KHMAPI
+khui_alert_set_message(khui_alert * alert,
+ const wchar_t * message);
+
+/*! \brief Set the suggestion of an alert object
+
+ The suggestion is limited by ::KHUI_MAXCCH_SUGGESTION
+ */
+KHMEXP khm_int32 KHMAPI
+khui_alert_set_suggestion(khui_alert * alert,
+ const wchar_t * suggestion);
+
+/*! \brief Set the severity of the alert object
+
+ The severity value is one of ::tag_kherr_severity
+ */
+KHMEXP khm_int32 KHMAPI
+khui_alert_set_severity(khui_alert * alert,
+ khm_int32 severity);
+
+/*! \brief Sets the flags of the alert
+
+ The flags are as defined in ::khui_alert_flags. The bits that are
+ on in \a mask will be set to the corresponding values in \a flags.
+ Only the bits specified in ::KHUI_ALERT_FLAGMASK_RDWR can be
+ specified in \a mask.
+ */
+KHMEXP khm_int32 KHMAPI
+khui_alert_set_flags(khui_alert * alert, khm_int32 mask, khm_int32 flags);
+
+/*! \brief Clear all the commands from an alert object
+
+ \see khui_alert_add_command()
+ */
+KHMEXP khm_int32 KHMAPI
+khui_alert_clear_commands(khui_alert * alert);
+
+/*! \brief Add a command to an alert object
+
+ The command ID should be a valid registered action.
+ */
+KHMEXP khm_int32 KHMAPI
+khui_alert_add_command(khui_alert * alert,
+ khm_int32 command_id);
+
+/*! \brief Set the type of alert
+ */
+KHMEXP khm_int32 KHMAPI
+khui_alert_set_type(khui_alert * alert,
+ khui_alert_type type);
+
+/*! \brief Set the action context for the alert */
+KHMEXP khm_int32 KHMAPI
+khui_alert_set_ctx(khui_alert * alert,
+ khui_scope scope,
+ khm_handle identity,
+ khm_int32 cred_type,
+ khm_handle cred);
+
+/*! \brief Get the response code from an alert
+
+ Once an alert has been displayed to the user, the user may choose
+ a command from the list of commands provided in the alert (see
+ khui_alert_add_command() ). This function can retrieve the
+ selected command from the alert.
+
+ \return The selected command or \a 0 if no commands were selected.
+ */
+KHMEXP khm_int32 KHMAPI
+khui_alert_get_response(khui_alert * alert);
+
+
+/*! \brief Display an alert
+
+ The alert must have a valid \a severity, \a title and a \a message
+ to be displayed. Otherwise the function immediately returns with
+ a failure code.
+
+ The method used to display the alert is as follows:
+
+ - A balloon alert will be shown if one of the following is true:
+ - The NetIDMgr application is minimized or in the background.
+ - ::KHUI_ALERT_FLAG_REQUEST_BALLOON is specified in \a flags.
+ - Otherwise an alert window will be shown.
+
+ If the message, title of the alert is too long to fit in a balloon
+ prompt, there's a suggestion or if there are custom commands then
+ a placeholder balloon prompt will be shown which when clicked on,
+ shows the actual alert in an alert window.
+
+ An exception is when ::KHUI_ALERT_FLAG_DEFACTION is specified in
+ flags. In this case instead of a placeholder balloon prompt, one
+ will be shown with the actual title and message (truncated if
+ necessary). Clicking on the balloon will cause the first command
+ in the command list to be performed.
+
+ The placeholder balloon prompt will have a title derived from the
+ first 63 characters of the \a title field in the alert and a
+ message notifying the user that they should click the balloon
+ prompt for more information.
+
+ To this end, it is beneficial to limit the length of the title to
+ 63 characters (64 counting the terminating NULL). This limit is
+ enforced on Windows. Also, try to make the title descriptive.
+
+ User interaction with the alert will be as follows:
+
+ - If the alert contains no commands, then the alert will be
+ displayed to the user as described above. A 'close' button will
+ be added to the alert if the alert is being displayed in a
+ window.
+
+ - If the alert contains commands, has the
+ ::KHUI_ALERT_FLAG_DEFACTION flag set and is displayed in a
+ balloon and the user clicks on it, the first command in the
+ command list will be executed.
+
+ - If the alert contains commands and does not have the
+ ::KHUI_ALERT_FLAG_DEFACTION and has the
+ ::KHUI_ALERT_FLAG_DISPATCH_CMD flag set, then when the user
+ selects one of the command buttons, the corresponding command
+ will immediately be dispatched. (see
+ ::KHUI_ALERT_FLAG_DISPATCH_CMD).
+
+ - If the alert contains command and have neither
+ ::KHUI_ALERT_FLAG_DEFACTION nor ::KHUI_ALERT_FLAG_DISPATCH_CMD,
+ then when the user selects one of the command buttons, the
+ selected command will be stored along with the alert. It can be
+ retrieved via a call to khui_alert_get_response().
+
+ */
+KHMEXP khm_int32 KHMAPI
+khui_alert_show(khui_alert * alert);
+
+/*! \brief Display a modal alert
+
+ Similar to khui_alert_show(), but shows a modal alert dialog. The
+ function does not return until the user has closed the alert.
+
+ This function always opens an alert window (never shows a
+ balloon).
+
+ */
+KHMEXP khm_int32 KHMAPI
+khui_alert_show_modal(khui_alert * alert);
+
+/*! \brief Queue an alert
+
+ Instead of displaying the alert immediately, the alert is queued
+ and the status bar updated to notify the user that there is a
+ pending alert. Once the user activates the pending alert, it will
+ be displayed as if khui_alert_show() was called.
+ */
+KHMEXP khm_int32 KHMAPI
+khui_alert_queue(khui_alert * alert);
+
+/*! \brief Display a simple alert
+
+ \see khui_alert_show()
+ */
+KHMEXP khm_int32 KHMAPI
+khui_alert_show_simple(const wchar_t * title,
+ const wchar_t * message,
+ khm_int32 severity);
+
+/*! \brief Obtain a hold on the alert
+
+ An alert structure is only considered valid for the duration that
+ there is a hold on it.
+
+ Use khui_alert_release() to release the hold.
+ */
+KHMEXP khm_int32 KHMAPI
+khui_alert_hold(khui_alert * alert);
+
+/*! \brief Release the hold on the alert
+
+ Holds obtained on an alert using any of the functions that either
+ return a held pointer to an alert or implicitly obtains a hold on
+ it need to be undone through a call to khui_alert_release().
+ */
+KHMEXP khm_int32 KHMAPI
+khui_alert_release(khui_alert * alert);
+
+/*! \brief Lock an alert
+
+ Locking an alert disallows any other thread from accessing the
+ alert at the same time. NetIDMgr keeps a global list of all alert
+ objects and the user interface may access any of them at various
+ points in time. Locking the alert allows a thread to modify an
+ alert without causing another thread to be exposed to an
+ inconsistent state.
+
+ Once a thread obtains a lock on the alert, it must call
+ khui_alert_unlock() to unlock it. Otherwise no other thread will
+ be able to access the alert.
+
+ \note Currently the alert lock is global. Locking one alert
+ disallows access to all other alerts as well.
+
+ \note Calling khui_alert_lock() is only necessary if you are
+ accessing the ::khui_alert structure directly. Calling any of
+ the khui_alert_* functions to modify the alert does not
+ require obtaining a lock, as they perform synchronization
+ internally.
+*/
+KHMEXP void KHMAPI
+khui_alert_lock(khui_alert * alert);
+
+/*! \brief Unlock an alert
+
+ \see khui_alert_lock()
+*/
+KHMEXP void KHMAPI
+khui_alert_unlock(khui_alert * alert);
+
+/*!@}*/
+/*!@}*/
+
+#endif
diff --git a/src/windows/identity/uilib/khconfigui.h b/src/windows/identity/uilib/khconfigui.h
index efe14789d3..bbc712a367 100644
--- a/src/windows/identity/uilib/khconfigui.h
+++ b/src/windows/identity/uilib/khconfigui.h
@@ -1,627 +1,627 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#ifndef __KHIMAIRA_KHCONFIGUI_H
-#define __KHIMAIRA_KHCONFIGUI_H
-
-/*! \addtogroup khui
-@{ */
-
-/*! \defgroup khui_cfg Configuration Panels
-
- Configuration panels are the primary means from which the user is
- presented with an interface to change NetIDMgr and plugin
- configuration.
-
-@{ */
-
-/*! \brief Configuration window notification message
-
- This is the message that will be used to notify dialog panels.
-
- The format of the message is :
- - uMsg : KHUI_WM_CFG_NOTIFY
- - HIWORD(wParam) : one of ::khui_wm_cfg_notifications
-
- \note This is the same as ::KHUI_WM_NC_NOTIFY
- */
-#define KHUI_WM_CFG_NOTIFY (WM_APP + 0x101)
-
-/*! \brief Configuration notifications
-
- These are sent thorugh a ::KHUI_WM_CFG_NOTIFY message.
-
- The format of the message is :
- - uMsg : KHUI_WM_CFG_NOTIFY
- - HIWORD(wParam) : one of ::khui_wm_cfg_notifications
- */
-enum khui_wm_cfg_notifications {
- WMCFG_SHOW_NODE = 1,
- /*!< Sent to the configuration dialog to request that the panel
- for the specified node be shown. The \a lParam message
- parameter will contain a held ::khui_config_node handle. The
- sender of the mssage is responsible for releasing the handle.*/
-
- WMCFG_UPDATE_STATE = 2,
- /*!< Sent to the configuration dialog to indicate that the state
- flags for the specified configuration node have changed.
-
- - LOWORD(wParam) : new flags
- - lParam : ::khui_config_node for the node*/
-
- WMCFG_APPLY = 3,
- /*!< Sent to all the configuration panels when the user clicks the
- 'Apply' button or the 'Ok' button. The panels are responsible
- for applying the configuration changes and updating their flags
- using khui_cfg_set_flags(). */
-
- WMCFG_SYNC_NODE_LIST = 4,
- /*!< Sent from the UI library to the configuration window to
- notify the window that the node list has changed. This message
- is sent synchronously before the node is removed. */
-};
-
-/*! \brief Registration information for a configuration node
-
- \see khui_cfg_register_node()
-*/
-typedef struct tag_khui_config_node_reg {
- const wchar_t * name; /*!< Internal identifier
- (not-localized, required). The name
- is required to be unique among
- sibling nodes. However it is not
- required to be unique globally. The
- size of the name is constrained by
- ::KHUI_MAXCCH_NAME*/
-
- const wchar_t * short_desc; /*!< Short description (Localized,
- required). This is the name which
- identifies the node within a
- collection of siblings. The size of
- the string is constrained by
- ::KHUI_MAXCCH_SHORT_DESC*/
-
- const wchar_t * long_desc; /*!< Global name of the node.
- (Localized, required). This
- uniquely identifies the node in the
- collection of all configuration
- nodes. The size of the string is
- constrained by
- ::KHUI_MAXCCH_LONG_DESC.*/
-
- HMODULE h_module; /*!< Module which contains the dialog
- resource specified in \a
- dlg_template */
-
- LPWSTR dlg_template; /*!< Dialog template for the
- configuration window */
-
- DLGPROC dlg_proc; /*!< Dialog procedure */
-
- khm_int32 flags; /*!< Flags. Can be a combination of
- ::KHUI_CNFLAG_SORT_CHILDREN and
- ::KHUI_CNFLAG_SUBPANEL*/
-
-} khui_config_node_reg;
-
-/*! \brief Sort the child nodes by short description */
-#define KHUI_CNFLAG_SORT_CHILDREN 0x0001
-
-/*! \brief Is a subpanel */
-#define KHUI_CNFLAG_SUBPANEL 0x0002
-
-/*! \brief Node represents a panel that is replicated for all child nodes */
-#define KHUI_CNFLAG_PLURAL 0x0004
-
-/*! \brief System node
-
- \note For internal use by the NetIDMgr application. Do not use.
-*/
-#define KHUI_CNFLAG_SYSTEM 0x0010
-
-/*! \brief Settings have been modified
-
- Settings for this configuration panel have been modified. This
- flag should be cleared once the settings have been successfully
- applied.
- */
-#define KHUI_CNFLAG_MODIFIED 0x0100
-
-/*! \brief Settings have been applied
-
- Set once any modified settings were successfully applied.
- */
-#define KHUI_CNFLAG_APPLIED 0x0200
-
-#define KHUI_CNFLAGMASK_STATIC 0x00ff
-#define KHUI_CNFLAGMASK_DYNAMIC 0x0f00
-
-/*! \brief Maximum length of the name in characters
-
- The length includes the terminating NULL
- */
-#define KHUI_MAXCCH_NAME 256
-
-/*! \brief Maximum length of the name in bytes
-
- The length includes the terminating NULL
- */
-#define KHUI_MAXCB_NAME (KHUI_MAXCCH_NAME * sizeof(wchar_t))
-
-/*! \brief Maximum length of the long description in characters
-
- The length includes the terminating NULL
- */
-#define KHUI_MAXCCH_LONG_DESC 1024
-
-/*! \brief Maximum length of the long description in bytes
-
- The length includes the terminating NULL
- */
-#define KHUI_MAXCB_LONG_DESC (KHUI_MAXCCH_LONG_DESC * sizeof(wchar_t))
-
-/*! \brief Maximum length of the short description in chracters
-
- The length includes the terminating NULL
- */
-#define KHUI_MAXCCH_SHORT_DESC 256
-
-/*! \brief Maximum length of the short description in bytes
-
- The length includes the terminating NULL
- */
-#define KHUI_MAXCB_SHORT_DESC (KHUI_MAXCCH_SHORT_DESC * sizeof(wchar_t))
-
-/*! \brief Width of a configuration dialog in dialog units
-
- ::CFGDLG_WIDTH and ::CFGDLG_HEIGHT specify the dimensions of a
- configuration dialog width and height in dialog units. The dialog
- will be created as a child of the configuration dialog and placed
- within it.
- */
-#define CFGDLG_WIDTH 255
-
-/*! \brief Height of a configuration dialog in dialog units
-
- \see ::CFGDLG_WIDTH
-*/
-#define CFGDLG_HEIGHT 182
-
-/*! \brief Width of a configuration tab dialog in dialog units
-
- ::CFGDLG_TAB_WIDTH and ::CFGDLG_TAB_HEIGHT specify the dimensions
- (in dialog units) of a dialog that will be placed within a tab
- control for dialogs where multiple display panels need to be
- shown.
- */
-#define CFGDLG_TAB_WIDTH 235
-
-/*! \brief Height of configuration tab dialog in dialog units
-
- \see ::CFGDLG_TAB_WIDTH
- */
-#define CFGDLG_TAB_HEIGHT 151
-
-/*! \brief A handle to a configuration node
-
- \see khui_cfg_open_node(), khui_cfg_close_node()
-*/
-typedef khm_handle khui_config_node;
-
-/*! \brief Initialization data passed in to a subpanel
-
- When creating a subpanel, a pointer to the following strucutred
- will be passed in as the creation parameter for the dialog.
-*/
-typedef struct tag_khui_config_init_data {
- khui_config_node ctx_node; /*!< The node under which the current
- dialog subpanel is being created. */
-
- khui_config_node this_node; /*!< The node which provided the
- registration information for the
- creation of the subpanel. */
-
- khui_config_node ref_node; /*!< The parent node of the subpanel
- node. In nodes which have the
- ::KHUI_CNFLAG_PLURAL, this would be
- different from the \a node. This is
- the node under which the subpanel
- was registered. */
-} khui_config_init_data;
-
-/*! \brief Register a configuration node
-
- The caller fills the registration information in the
- ::khui_config_node_reg structre. If the call succeeds, the
- function will return KHM_ERROR_SUCCESS.
-
- \param[in] parent Parent of the node to be registered. Set to
- NULL if the parent is the root node.
-
- \param[in] reg Registration information
-
- \param[out] new_id Receives the new unique identifier of the
- configuration node. Pass in NULL if the new identifier is not
- required.
-
- \retval KHM_ERROR_SUCCESS Success
- \retval KHM_ERROR_INVALID_PARAM One or more parameters, or fields
- of reg were invalid
- \retval KHM_ERROR_DUPLICATE A node with the same name exists as a
- child of the specified parent node.
-
- \note The name (not the short or long description) of the node can
- not be the same as the name of a custom action. See
- khui_action_create().
- */
-KHMEXP khm_int32 KHMAPI
-khui_cfg_register(khui_config_node parent,
- const khui_config_node_reg * reg);
-
-/*!\brief Open a configuration node by name
-
- If successful, the \a result parameter will receive a handle to
- the configuration node. Use khui_cfg_release() to release
- the handle.
-
- \param[in] parent Parent node. Set to NULL to specify root node.
- */
-KHMEXP khm_int32 KHMAPI
-khui_cfg_open(khui_config_node parent,
- const wchar_t * name,
- khui_config_node * result);
-
-/*! \brief Remove a configuration node
-
- Marks a configuration node as deleted. Once all the handles,
- including the handle specified in \a node have been released, it
- will be deleted.
- */
-KHMEXP khm_int32 KHMAPI
-khui_cfg_remove(khui_config_node node);
-
-/*! \brief Hold a handle to a configuration node
-
- Obtains an additional hold on the handle specified by \a node.
- The hold must be released with a call to \a
- khui_cfg_release()
- */
-KHMEXP khm_int32 KHMAPI
-khui_cfg_hold(khui_config_node node);
-
-/*! \brief Release a handle to a configuration node
-
- \see khui_cfg_hold()
- */
-KHMEXP khm_int32 KHMAPI
-khui_cfg_release(khui_config_node node);
-
-/*! \brief Get the parent of a node
-
- Returns a held handle to the parent of the node, or NULL if the
- current node is a top level node. The returned handle must be
- released with khui_cfg_release().
-
- \retval KHM_ERROR_SUCCESS The handle to the parent node is in \a result
- \retval KHM_ERROR_NOT_FOUND The node is a top level node
- */
-KHMEXP khm_int32 KHMAPI
-khui_cfg_get_parent(khui_config_node vnode,
- khui_config_node * result);
-
-/*! \brief Get a handle to the first child node
-
- If the call is successful, \a result will receieve a handle to the
- first child node of the specified node. The returned handle must
- be released with a call to khui_cfg_release()
-
- If \a parent does not have any child nodes, the function will
- return KHM_ERROR_NOT_FOUND and set \a result to NULL.
-
- \param[in] parent Parent node. Set to NULL to specify root node.
- \param[out] result Receives a held handle to the first child node.
-
- \see khui_cfg_get_next()
- */
-KHMEXP khm_int32 KHMAPI
-khui_cfg_get_first_child(khui_config_node parent,
- khui_config_node * result);
-
-/*! \brief Get a handle to the first subpanel
-
- If the call is successful, \a result will receieve a handle to the
- first subpanel node of the specified node. The returned handle
- must be released with a call to khui_cfg_release()
-
- If \a parent does not have any subpanels, the function will return
- KHM_ERROR_NOT_FOUND and set \a result to NULL.
-
- A subpanel node is a node which has the ::KHUI_CNFLAG_SUBPANEL
- flag set.
-
- \param[in] parent Parent node. Set to NULL to specify root node.
- \param[out] result Receives a held handle to the first subpanel node.
-
- \see khui_cfg_get_next()
- */
-KHMEXP khm_int32 KHMAPI
-khui_cfg_get_first_subpanel(khui_config_node vparent,
- khui_config_node * result);
-
-/*! \brief Get a handle to the next sibling node
-
- If the call is successful, \a result will receive a held handle to
- the next sibling node. The returned handle must be released with
- a call to khui_cfg_release().
-
- If there are no more sibling nodes, then the function return
- KHM_ERROR_NOT_FOUND and set \a result to NULL.
-
- This function can be used to traverse a list of child nodes as
- well as a list of subpanel nodes.
-
- */
-KHMEXP khm_int32 KHMAPI
-khui_cfg_get_next(khui_config_node node,
- khui_config_node * result);
-
-/*! \brief Get a handle to the next sibling node
-
- Similar to khui_cfg_get_next(), but implicitly releases the handle
- that was supplied. Equivalent to doing :
-
- \code
- khui_cfg_get_next(node, &next);
- khui_cfg_release(node);
- node = next;
- \endcode
-
- \param[in,out] node On entry, specifies the node whose sibling
- needs to be fetched. On exit, will have either NULL or a held
- handle to the sibling node. The handle which was supplied to
- the function is released.
-
- \retval KHM_ERROR_SUCCESS The next node is now in \a node
- \retval KHM_ERROR_INVALID_PARAM \a node was not a valid handle
- \retval KHM_ERROR_NOT_FOUND There are no more siblings. \a node
- is set to NULL.
-
- \note Even if there are no more siblings, the handle specified in
- \a node on entry is released.
- */
-KHMEXP khm_int32 KHMAPI
-khui_cfg_get_next_release(khui_config_node * node);
-
-/*! \brief Get the name of a configuration node
-
- Gets the name (not the short description or the long description)
- of the given configuration node.
-*/
-KHMEXP khm_int32 KHMAPI
-khui_cfg_get_name(khui_config_node node,
- wchar_t * buf,
- khm_size * cb_buf);
-
-/*! \brief Get registration information for a node
-
- The registration information that is returned is a shallow copy of
- the data kept by NetIDMgr. In particular, the strings that will
- be returned actually point to internal buffers and should not be
- modified.
-
- No further action is necessary to release the information.
- However, the returned data ceases to be valid when \a node is
- released with a call to khui_cfg_release().
-
- \param[in] node Node for which information is requested. Can be NULL if requesting information about the root node.
- \param[out] reg Pointer to a ::khui_config_node_reg structure.
- */
-KHMEXP khm_int32 KHMAPI
-khui_cfg_get_reg(khui_config_node node,
- khui_config_node_reg * reg);
-
-/*! \brief Internal use
-
- This function is used internally by NetIDMgr. Do not use.
-*/
-KHMEXP HWND KHMAPI
-khui_cfg_get_hwnd_inst(khui_config_node node,
- khui_config_node noderef);
-
-/*! \brief Internal use
-
- This function is used internally by NetIDMgr. Do not use.
-*/
-KHMEXP LPARAM KHMAPI
-khui_cfg_get_param_inst(khui_config_node node,
- khui_config_node noderef);
-
-/*! \brief Internal use
-
- This function is used internally by NetIDMgr. Do not use.
-*/
-KHMEXP void KHMAPI
-khui_cfg_set_hwnd_inst(khui_config_node node,
- khui_config_node noderef,
- HWND hwnd);
-
-/*! \brief Internal use
-
- This function is used internally by NetIDMgr. Do not use.
-*/
-KHMEXP void KHMAPI
-khui_cfg_set_param_inst(khui_config_node node,
- khui_config_node noderef,
- LPARAM param);
-
-/*! \brief Internal use
-
- This function is used internally by NetIDMgr. Do not use.
-*/
-KHMEXP HWND KHMAPI
-khui_cfg_get_hwnd(khui_config_node node);
-
-/*! \brief Internal use
-
- This function is used internally by NetIDMgr. Do not use.
-*/
-KHMEXP LPARAM KHMAPI
-khui_cfg_get_param(khui_config_node node);
-
-/*! \brief Internal use
-
- This function is used internally by NetIDMgr. Do not use.
-*/
-KHMEXP void KHMAPI
-khui_cfg_set_hwnd(khui_config_node node, HWND hwnd);
-
-/*! \brief Internal use
-
- This function is used internally by NetIDMgr. Do not use.
-*/
-KHMEXP void KHMAPI
-khui_cfg_set_param(khui_config_node node, LPARAM param);
-
-/*! \brief Internal use
-
- This function is used internally by NetIDMgr. Do not use.
-*/
-KHMEXP void KHMAPI
-khui_cfg_clear_params(void);
-
-/*! \brief Internal use
-
- This function is used internally by NetIDMgr. Do not use.
-*/
-KHMEXP void KHMAPI
-khui_cfg_set_configui_handle(HWND hwnd);
-
-/*! \brief Update the state for the specified node
-
- \param[in] node ::khui_config_node handle for the configuration node.
-
- \param[in] flags New flags. Combination of ::KHUI_CNFLAG_APPLIED and ::KHUI_CNFLAG_MODIFIED
-
- \param[in] mask Valid bits in \a flags
-
- \note Should only be called from within the dialog procedure for
- the configuration node.
- */
-KHMEXP void KHMAPI
-khui_cfg_set_flags(khui_config_node vnode, khm_int32 flags, khm_int32 mask);
-
-/*! \brief Retrieve the state flags for the configuration node
-
- \see khui_cfg_set_flags()
- */
-KHMEXP khm_int32 KHMAPI
-khui_cfg_get_flags(khui_config_node vnode);
-
-/*! \brief Utility function: Initialize dialog box window data
-
- This function initializes the dialog box window data using the
- ::khui_config_init_data that was passed into the WM_INITDIALOG
- message.
-
- A new block of memory will be alocated to store the dialog data as
- well as any extra space specified. A pointer to this memory block
- will be stored in the \a DWLP_USER slot in the dialog box.
-
- The allocated block of memory must be freed by a call to
- khui_cfg_free_dialog_data(). While handling other messages, the
- dialog data can be retrieved using khui_cfg_get_dialog_data().
-
- \param[in] hwnd_dlg Handle to the dialog box
-
- \param[in] data Pointer to the ::khui_config_init_data that was
- passed in to WM_INITDIALOG (this is the value of \a lParam)
-
- \param[in] cb_extra Number of extra bytes to allocate, along with
- the space required to store the contents of
- ::khui_config_init_data. The extra space will be initialized
- to zero.
-
- \param[out] new_data Receives a pointer to the copy of the
- initialization data that was allocated. Optional. Pass in
- NULL if this value is not required.
-
- \param[out] extra Receives a pointer to the block of extra memory
- allocated as specified in \a cb_extra. If \a cb_extra is 0,
- then this receives a NULL.
-
- \see khui_cfg_get_dialog_data(), khui_cfg_free_dialog_data()
- */
-KHMEXP khm_int32 KHMAPI
-khui_cfg_init_dialog_data(HWND hwnd_dlg,
- const khui_config_init_data * data,
- khm_size cb_extra,
- khui_config_init_data ** new_data,
- void ** extra);
-
-/*! \brief Utility function: Retrieves dialog data
-
- Retrieves the dialog data previoulsy stored using
- khui_cfg_init_dialog_data().
-
- \param[in] hwnd_dlg Handle to the dialog box
-
- \param[out] data Receives a pointer to the ::khui_config_init_data
- block.
-
- \param[out] extra Receives a pointer to the extra memory
- allocated. Optional (set to NULL if this value is not needed).
-*/
-KHMEXP khm_int32 KHMAPI
-khui_cfg_get_dialog_data(HWND hwnd_dlg,
- khui_config_init_data ** data,
- void ** extra);
-
-/*! \brief Utility function: Free dialog data
-
- Deallocates the memory allcated in a previous call to
- khui_cfg_init_dialog_data()
- */
-KHMEXP khm_int32 KHMAPI
-khui_cfg_free_dialog_data(HWND hwnd_dlg);
-
-/*! \brief Sets the instance flags for a subpanel
-
- Since there can be more than one subpanel in a configuration
- panel, they shouldn't modify the flags of the configuration node
- directly. Instead, they should call this function to set the
- instance flags.
-
- The instance flags will be merged with the flags for the
- configuration node automatically.
- */
-KHMEXP void KHMAPI
-khui_cfg_set_flags_inst(khui_config_init_data * d,
- khm_int32 flags,
- khm_int32 mask);
-
-/*!@} */
-/*!@} */
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __KHIMAIRA_KHCONFIGUI_H
+#define __KHIMAIRA_KHCONFIGUI_H
+
+/*! \addtogroup khui
+@{ */
+
+/*! \defgroup khui_cfg Configuration Panels
+
+ Configuration panels are the primary means from which the user is
+ presented with an interface to change NetIDMgr and plugin
+ configuration.
+
+@{ */
+
+/*! \brief Configuration window notification message
+
+ This is the message that will be used to notify dialog panels.
+
+ The format of the message is :
+ - uMsg : KHUI_WM_CFG_NOTIFY
+ - HIWORD(wParam) : one of ::khui_wm_cfg_notifications
+
+ \note This is the same as ::KHUI_WM_NC_NOTIFY
+ */
+#define KHUI_WM_CFG_NOTIFY (WM_APP + 0x101)
+
+/*! \brief Configuration notifications
+
+ These are sent thorugh a ::KHUI_WM_CFG_NOTIFY message.
+
+ The format of the message is :
+ - uMsg : KHUI_WM_CFG_NOTIFY
+ - HIWORD(wParam) : one of ::khui_wm_cfg_notifications
+ */
+enum khui_wm_cfg_notifications {
+ WMCFG_SHOW_NODE = 1,
+ /*!< Sent to the configuration dialog to request that the panel
+ for the specified node be shown. The \a lParam message
+ parameter will contain a held ::khui_config_node handle. The
+ sender of the mssage is responsible for releasing the handle.*/
+
+ WMCFG_UPDATE_STATE = 2,
+ /*!< Sent to the configuration dialog to indicate that the state
+ flags for the specified configuration node have changed.
+
+ - LOWORD(wParam) : new flags
+ - lParam : ::khui_config_node for the node*/
+
+ WMCFG_APPLY = 3,
+ /*!< Sent to all the configuration panels when the user clicks the
+ 'Apply' button or the 'Ok' button. The panels are responsible
+ for applying the configuration changes and updating their flags
+ using khui_cfg_set_flags(). */
+
+ WMCFG_SYNC_NODE_LIST = 4,
+ /*!< Sent from the UI library to the configuration window to
+ notify the window that the node list has changed. This message
+ is sent synchronously before the node is removed. */
+};
+
+/*! \brief Registration information for a configuration node
+
+ \see khui_cfg_register_node()
+*/
+typedef struct tag_khui_config_node_reg {
+ const wchar_t * name; /*!< Internal identifier
+ (not-localized, required). The name
+ is required to be unique among
+ sibling nodes. However it is not
+ required to be unique globally. The
+ size of the name is constrained by
+ ::KHUI_MAXCCH_NAME*/
+
+ const wchar_t * short_desc; /*!< Short description (Localized,
+ required). This is the name which
+ identifies the node within a
+ collection of siblings. The size of
+ the string is constrained by
+ ::KHUI_MAXCCH_SHORT_DESC*/
+
+ const wchar_t * long_desc; /*!< Global name of the node.
+ (Localized, required). This
+ uniquely identifies the node in the
+ collection of all configuration
+ nodes. The size of the string is
+ constrained by
+ ::KHUI_MAXCCH_LONG_DESC.*/
+
+ HMODULE h_module; /*!< Module which contains the dialog
+ resource specified in \a
+ dlg_template */
+
+ LPWSTR dlg_template; /*!< Dialog template for the
+ configuration window */
+
+ DLGPROC dlg_proc; /*!< Dialog procedure */
+
+ khm_int32 flags; /*!< Flags. Can be a combination of
+ ::KHUI_CNFLAG_SORT_CHILDREN and
+ ::KHUI_CNFLAG_SUBPANEL*/
+
+} khui_config_node_reg;
+
+/*! \brief Sort the child nodes by short description */
+#define KHUI_CNFLAG_SORT_CHILDREN 0x0001
+
+/*! \brief Is a subpanel */
+#define KHUI_CNFLAG_SUBPANEL 0x0002
+
+/*! \brief Node represents a panel that is replicated for all child nodes */
+#define KHUI_CNFLAG_PLURAL 0x0004
+
+/*! \brief System node
+
+ \note For internal use by the NetIDMgr application. Do not use.
+*/
+#define KHUI_CNFLAG_SYSTEM 0x0010
+
+/*! \brief Settings have been modified
+
+ Settings for this configuration panel have been modified. This
+ flag should be cleared once the settings have been successfully
+ applied.
+ */
+#define KHUI_CNFLAG_MODIFIED 0x0100
+
+/*! \brief Settings have been applied
+
+ Set once any modified settings were successfully applied.
+ */
+#define KHUI_CNFLAG_APPLIED 0x0200
+
+#define KHUI_CNFLAGMASK_STATIC 0x00ff
+#define KHUI_CNFLAGMASK_DYNAMIC 0x0f00
+
+/*! \brief Maximum length of the name in characters
+
+ The length includes the terminating NULL
+ */
+#define KHUI_MAXCCH_NAME 256
+
+/*! \brief Maximum length of the name in bytes
+
+ The length includes the terminating NULL
+ */
+#define KHUI_MAXCB_NAME (KHUI_MAXCCH_NAME * sizeof(wchar_t))
+
+/*! \brief Maximum length of the long description in characters
+
+ The length includes the terminating NULL
+ */
+#define KHUI_MAXCCH_LONG_DESC 1024
+
+/*! \brief Maximum length of the long description in bytes
+
+ The length includes the terminating NULL
+ */
+#define KHUI_MAXCB_LONG_DESC (KHUI_MAXCCH_LONG_DESC * sizeof(wchar_t))
+
+/*! \brief Maximum length of the short description in chracters
+
+ The length includes the terminating NULL
+ */
+#define KHUI_MAXCCH_SHORT_DESC 256
+
+/*! \brief Maximum length of the short description in bytes
+
+ The length includes the terminating NULL
+ */
+#define KHUI_MAXCB_SHORT_DESC (KHUI_MAXCCH_SHORT_DESC * sizeof(wchar_t))
+
+/*! \brief Width of a configuration dialog in dialog units
+
+ ::CFGDLG_WIDTH and ::CFGDLG_HEIGHT specify the dimensions of a
+ configuration dialog width and height in dialog units. The dialog
+ will be created as a child of the configuration dialog and placed
+ within it.
+ */
+#define CFGDLG_WIDTH 255
+
+/*! \brief Height of a configuration dialog in dialog units
+
+ \see ::CFGDLG_WIDTH
+*/
+#define CFGDLG_HEIGHT 182
+
+/*! \brief Width of a configuration tab dialog in dialog units
+
+ ::CFGDLG_TAB_WIDTH and ::CFGDLG_TAB_HEIGHT specify the dimensions
+ (in dialog units) of a dialog that will be placed within a tab
+ control for dialogs where multiple display panels need to be
+ shown.
+ */
+#define CFGDLG_TAB_WIDTH 235
+
+/*! \brief Height of configuration tab dialog in dialog units
+
+ \see ::CFGDLG_TAB_WIDTH
+ */
+#define CFGDLG_TAB_HEIGHT 151
+
+/*! \brief A handle to a configuration node
+
+ \see khui_cfg_open_node(), khui_cfg_close_node()
+*/
+typedef khm_handle khui_config_node;
+
+/*! \brief Initialization data passed in to a subpanel
+
+ When creating a subpanel, a pointer to the following strucutred
+ will be passed in as the creation parameter for the dialog.
+*/
+typedef struct tag_khui_config_init_data {
+ khui_config_node ctx_node; /*!< The node under which the current
+ dialog subpanel is being created. */
+
+ khui_config_node this_node; /*!< The node which provided the
+ registration information for the
+ creation of the subpanel. */
+
+ khui_config_node ref_node; /*!< The parent node of the subpanel
+ node. In nodes which have the
+ ::KHUI_CNFLAG_PLURAL, this would be
+ different from the \a node. This is
+ the node under which the subpanel
+ was registered. */
+} khui_config_init_data;
+
+/*! \brief Register a configuration node
+
+ The caller fills the registration information in the
+ ::khui_config_node_reg structre. If the call succeeds, the
+ function will return KHM_ERROR_SUCCESS.
+
+ \param[in] parent Parent of the node to be registered. Set to
+ NULL if the parent is the root node.
+
+ \param[in] reg Registration information
+
+ \param[out] new_id Receives the new unique identifier of the
+ configuration node. Pass in NULL if the new identifier is not
+ required.
+
+ \retval KHM_ERROR_SUCCESS Success
+ \retval KHM_ERROR_INVALID_PARAM One or more parameters, or fields
+ of reg were invalid
+ \retval KHM_ERROR_DUPLICATE A node with the same name exists as a
+ child of the specified parent node.
+
+ \note The name (not the short or long description) of the node can
+ not be the same as the name of a custom action. See
+ khui_action_create().
+ */
+KHMEXP khm_int32 KHMAPI
+khui_cfg_register(khui_config_node parent,
+ const khui_config_node_reg * reg);
+
+/*!\brief Open a configuration node by name
+
+ If successful, the \a result parameter will receive a handle to
+ the configuration node. Use khui_cfg_release() to release
+ the handle.
+
+ \param[in] parent Parent node. Set to NULL to specify root node.
+ */
+KHMEXP khm_int32 KHMAPI
+khui_cfg_open(khui_config_node parent,
+ const wchar_t * name,
+ khui_config_node * result);
+
+/*! \brief Remove a configuration node
+
+ Marks a configuration node as deleted. Once all the handles,
+ including the handle specified in \a node have been released, it
+ will be deleted.
+ */
+KHMEXP khm_int32 KHMAPI
+khui_cfg_remove(khui_config_node node);
+
+/*! \brief Hold a handle to a configuration node
+
+ Obtains an additional hold on the handle specified by \a node.
+ The hold must be released with a call to \a
+ khui_cfg_release()
+ */
+KHMEXP khm_int32 KHMAPI
+khui_cfg_hold(khui_config_node node);
+
+/*! \brief Release a handle to a configuration node
+
+ \see khui_cfg_hold()
+ */
+KHMEXP khm_int32 KHMAPI
+khui_cfg_release(khui_config_node node);
+
+/*! \brief Get the parent of a node
+
+ Returns a held handle to the parent of the node, or NULL if the
+ current node is a top level node. The returned handle must be
+ released with khui_cfg_release().
+
+ \retval KHM_ERROR_SUCCESS The handle to the parent node is in \a result
+ \retval KHM_ERROR_NOT_FOUND The node is a top level node
+ */
+KHMEXP khm_int32 KHMAPI
+khui_cfg_get_parent(khui_config_node vnode,
+ khui_config_node * result);
+
+/*! \brief Get a handle to the first child node
+
+ If the call is successful, \a result will receieve a handle to the
+ first child node of the specified node. The returned handle must
+ be released with a call to khui_cfg_release()
+
+ If \a parent does not have any child nodes, the function will
+ return KHM_ERROR_NOT_FOUND and set \a result to NULL.
+
+ \param[in] parent Parent node. Set to NULL to specify root node.
+ \param[out] result Receives a held handle to the first child node.
+
+ \see khui_cfg_get_next()
+ */
+KHMEXP khm_int32 KHMAPI
+khui_cfg_get_first_child(khui_config_node parent,
+ khui_config_node * result);
+
+/*! \brief Get a handle to the first subpanel
+
+ If the call is successful, \a result will receieve a handle to the
+ first subpanel node of the specified node. The returned handle
+ must be released with a call to khui_cfg_release()
+
+ If \a parent does not have any subpanels, the function will return
+ KHM_ERROR_NOT_FOUND and set \a result to NULL.
+
+ A subpanel node is a node which has the ::KHUI_CNFLAG_SUBPANEL
+ flag set.
+
+ \param[in] parent Parent node. Set to NULL to specify root node.
+ \param[out] result Receives a held handle to the first subpanel node.
+
+ \see khui_cfg_get_next()
+ */
+KHMEXP khm_int32 KHMAPI
+khui_cfg_get_first_subpanel(khui_config_node vparent,
+ khui_config_node * result);
+
+/*! \brief Get a handle to the next sibling node
+
+ If the call is successful, \a result will receive a held handle to
+ the next sibling node. The returned handle must be released with
+ a call to khui_cfg_release().
+
+ If there are no more sibling nodes, then the function return
+ KHM_ERROR_NOT_FOUND and set \a result to NULL.
+
+ This function can be used to traverse a list of child nodes as
+ well as a list of subpanel nodes.
+
+ */
+KHMEXP khm_int32 KHMAPI
+khui_cfg_get_next(khui_config_node node,
+ khui_config_node * result);
+
+/*! \brief Get a handle to the next sibling node
+
+ Similar to khui_cfg_get_next(), but implicitly releases the handle
+ that was supplied. Equivalent to doing :
+
+ \code
+ khui_cfg_get_next(node, &next);
+ khui_cfg_release(node);
+ node = next;
+ \endcode
+
+ \param[in,out] node On entry, specifies the node whose sibling
+ needs to be fetched. On exit, will have either NULL or a held
+ handle to the sibling node. The handle which was supplied to
+ the function is released.
+
+ \retval KHM_ERROR_SUCCESS The next node is now in \a node
+ \retval KHM_ERROR_INVALID_PARAM \a node was not a valid handle
+ \retval KHM_ERROR_NOT_FOUND There are no more siblings. \a node
+ is set to NULL.
+
+ \note Even if there are no more siblings, the handle specified in
+ \a node on entry is released.
+ */
+KHMEXP khm_int32 KHMAPI
+khui_cfg_get_next_release(khui_config_node * node);
+
+/*! \brief Get the name of a configuration node
+
+ Gets the name (not the short description or the long description)
+ of the given configuration node.
+*/
+KHMEXP khm_int32 KHMAPI
+khui_cfg_get_name(khui_config_node node,
+ wchar_t * buf,
+ khm_size * cb_buf);
+
+/*! \brief Get registration information for a node
+
+ The registration information that is returned is a shallow copy of
+ the data kept by NetIDMgr. In particular, the strings that will
+ be returned actually point to internal buffers and should not be
+ modified.
+
+ No further action is necessary to release the information.
+ However, the returned data ceases to be valid when \a node is
+ released with a call to khui_cfg_release().
+
+ \param[in] node Node for which information is requested. Can be NULL if requesting information about the root node.
+ \param[out] reg Pointer to a ::khui_config_node_reg structure.
+ */
+KHMEXP khm_int32 KHMAPI
+khui_cfg_get_reg(khui_config_node node,
+ khui_config_node_reg * reg);
+
+/*! \brief Internal use
+
+ This function is used internally by NetIDMgr. Do not use.
+*/
+KHMEXP HWND KHMAPI
+khui_cfg_get_hwnd_inst(khui_config_node node,
+ khui_config_node noderef);
+
+/*! \brief Internal use
+
+ This function is used internally by NetIDMgr. Do not use.
+*/
+KHMEXP LPARAM KHMAPI
+khui_cfg_get_param_inst(khui_config_node node,
+ khui_config_node noderef);
+
+/*! \brief Internal use
+
+ This function is used internally by NetIDMgr. Do not use.
+*/
+KHMEXP void KHMAPI
+khui_cfg_set_hwnd_inst(khui_config_node node,
+ khui_config_node noderef,
+ HWND hwnd);
+
+/*! \brief Internal use
+
+ This function is used internally by NetIDMgr. Do not use.
+*/
+KHMEXP void KHMAPI
+khui_cfg_set_param_inst(khui_config_node node,
+ khui_config_node noderef,
+ LPARAM param);
+
+/*! \brief Internal use
+
+ This function is used internally by NetIDMgr. Do not use.
+*/
+KHMEXP HWND KHMAPI
+khui_cfg_get_hwnd(khui_config_node node);
+
+/*! \brief Internal use
+
+ This function is used internally by NetIDMgr. Do not use.
+*/
+KHMEXP LPARAM KHMAPI
+khui_cfg_get_param(khui_config_node node);
+
+/*! \brief Internal use
+
+ This function is used internally by NetIDMgr. Do not use.
+*/
+KHMEXP void KHMAPI
+khui_cfg_set_hwnd(khui_config_node node, HWND hwnd);
+
+/*! \brief Internal use
+
+ This function is used internally by NetIDMgr. Do not use.
+*/
+KHMEXP void KHMAPI
+khui_cfg_set_param(khui_config_node node, LPARAM param);
+
+/*! \brief Internal use
+
+ This function is used internally by NetIDMgr. Do not use.
+*/
+KHMEXP void KHMAPI
+khui_cfg_clear_params(void);
+
+/*! \brief Internal use
+
+ This function is used internally by NetIDMgr. Do not use.
+*/
+KHMEXP void KHMAPI
+khui_cfg_set_configui_handle(HWND hwnd);
+
+/*! \brief Update the state for the specified node
+
+ \param[in] node ::khui_config_node handle for the configuration node.
+
+ \param[in] flags New flags. Combination of ::KHUI_CNFLAG_APPLIED and ::KHUI_CNFLAG_MODIFIED
+
+ \param[in] mask Valid bits in \a flags
+
+ \note Should only be called from within the dialog procedure for
+ the configuration node.
+ */
+KHMEXP void KHMAPI
+khui_cfg_set_flags(khui_config_node vnode, khm_int32 flags, khm_int32 mask);
+
+/*! \brief Retrieve the state flags for the configuration node
+
+ \see khui_cfg_set_flags()
+ */
+KHMEXP khm_int32 KHMAPI
+khui_cfg_get_flags(khui_config_node vnode);
+
+/*! \brief Utility function: Initialize dialog box window data
+
+ This function initializes the dialog box window data using the
+ ::khui_config_init_data that was passed into the WM_INITDIALOG
+ message.
+
+ A new block of memory will be alocated to store the dialog data as
+ well as any extra space specified. A pointer to this memory block
+ will be stored in the \a DWLP_USER slot in the dialog box.
+
+ The allocated block of memory must be freed by a call to
+ khui_cfg_free_dialog_data(). While handling other messages, the
+ dialog data can be retrieved using khui_cfg_get_dialog_data().
+
+ \param[in] hwnd_dlg Handle to the dialog box
+
+ \param[in] data Pointer to the ::khui_config_init_data that was
+ passed in to WM_INITDIALOG (this is the value of \a lParam)
+
+ \param[in] cb_extra Number of extra bytes to allocate, along with
+ the space required to store the contents of
+ ::khui_config_init_data. The extra space will be initialized
+ to zero.
+
+ \param[out] new_data Receives a pointer to the copy of the
+ initialization data that was allocated. Optional. Pass in
+ NULL if this value is not required.
+
+ \param[out] extra Receives a pointer to the block of extra memory
+ allocated as specified in \a cb_extra. If \a cb_extra is 0,
+ then this receives a NULL.
+
+ \see khui_cfg_get_dialog_data(), khui_cfg_free_dialog_data()
+ */
+KHMEXP khm_int32 KHMAPI
+khui_cfg_init_dialog_data(HWND hwnd_dlg,
+ const khui_config_init_data * data,
+ khm_size cb_extra,
+ khui_config_init_data ** new_data,
+ void ** extra);
+
+/*! \brief Utility function: Retrieves dialog data
+
+ Retrieves the dialog data previoulsy stored using
+ khui_cfg_init_dialog_data().
+
+ \param[in] hwnd_dlg Handle to the dialog box
+
+ \param[out] data Receives a pointer to the ::khui_config_init_data
+ block.
+
+ \param[out] extra Receives a pointer to the extra memory
+ allocated. Optional (set to NULL if this value is not needed).
+*/
+KHMEXP khm_int32 KHMAPI
+khui_cfg_get_dialog_data(HWND hwnd_dlg,
+ khui_config_init_data ** data,
+ void ** extra);
+
+/*! \brief Utility function: Free dialog data
+
+ Deallocates the memory allcated in a previous call to
+ khui_cfg_init_dialog_data()
+ */
+KHMEXP khm_int32 KHMAPI
+khui_cfg_free_dialog_data(HWND hwnd_dlg);
+
+/*! \brief Sets the instance flags for a subpanel
+
+ Since there can be more than one subpanel in a configuration
+ panel, they shouldn't modify the flags of the configuration node
+ directly. Instead, they should call this function to set the
+ instance flags.
+
+ The instance flags will be merged with the flags for the
+ configuration node automatically.
+ */
+KHMEXP void KHMAPI
+khui_cfg_set_flags_inst(khui_config_init_data * d,
+ khm_int32 flags,
+ khm_int32 mask);
+
+/*!@} */
+/*!@} */
+#endif
diff --git a/src/windows/identity/uilib/khhtlink.h b/src/windows/identity/uilib/khhtlink.h
index 1246923e23..be6abb21c0 100644
--- a/src/windows/identity/uilib/khhtlink.h
+++ b/src/windows/identity/uilib/khhtlink.h
@@ -1,77 +1,77 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#ifndef __KHIMAIRA_KHHTLINK_H
-#define __KHIMAIRA_KHHTLINK_H
-
-/*! \addtogroup khui
-@{ */
-
-/*! \defgroup khui_hyperlink Hyperlink
-@{*/
-
-/*! \brief A hyperlink
-
- When a link in a hypertext window is clicked, this structure is
- passed along with the message.
-
- The link text fields do to point to NULL terminated strings.
- Instead, the length fields should be used to extract the string.
- */
-typedef struct tag_khui_htwnd_link {
- RECT r; /*!< The enclosing rectangle of the
- hyperlink. Units are screen units
- and the coordinates are relative to
- the top left hand corner of the
- hypertext area. */
- wchar_t * id; /*!< The value of the \a id attribute
- of the link or \a NULL if there was
- no \a id attribute. This does not
- point to a \a NULL terminated
- string. The length of the string is
- given by the \a id_len field. */
- int id_len; /*!< The length of the string pointed
- to by \a id in characters.
- Undefined if \a id is \a NULL. */
- wchar_t * param; /*!< The value of the \a param
- attribute of the link or \a NULL if
- there was no \a param attribute.
- This does not point to a \a NULL
- terminated string. The length of
- the string is given by the \a
- param_len field.*/
- int param_len; /*!< Length of the string pointed to
- by \a param in characters.
- Undefined if \a param is \a NULL. */
-} khui_htwnd_link;
-
-#define KHUI_MAXCCH_HTLINK_FIELD 256
-#define KHUI_MAXCB_HTLINK_FIELD (KHUI_MAXCCH_HTLINK_FIELD * sizeof(wchar_t))
-
-/*!@}*/
-/*!@}*/
-
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __KHIMAIRA_KHHTLINK_H
+#define __KHIMAIRA_KHHTLINK_H
+
+/*! \addtogroup khui
+@{ */
+
+/*! \defgroup khui_hyperlink Hyperlink
+@{*/
+
+/*! \brief A hyperlink
+
+ When a link in a hypertext window is clicked, this structure is
+ passed along with the message.
+
+ The link text fields do to point to NULL terminated strings.
+ Instead, the length fields should be used to extract the string.
+ */
+typedef struct tag_khui_htwnd_link {
+ RECT r; /*!< The enclosing rectangle of the
+ hyperlink. Units are screen units
+ and the coordinates are relative to
+ the top left hand corner of the
+ hypertext area. */
+ wchar_t * id; /*!< The value of the \a id attribute
+ of the link or \a NULL if there was
+ no \a id attribute. This does not
+ point to a \a NULL terminated
+ string. The length of the string is
+ given by the \a id_len field. */
+ int id_len; /*!< The length of the string pointed
+ to by \a id in characters.
+ Undefined if \a id is \a NULL. */
+ wchar_t * param; /*!< The value of the \a param
+ attribute of the link or \a NULL if
+ there was no \a param attribute.
+ This does not point to a \a NULL
+ terminated string. The length of
+ the string is given by the \a
+ param_len field.*/
+ int param_len; /*!< Length of the string pointed to
+ by \a param in characters.
+ Undefined if \a param is \a NULL. */
+} khui_htwnd_link;
+
+#define KHUI_MAXCCH_HTLINK_FIELD 256
+#define KHUI_MAXCB_HTLINK_FIELD (KHUI_MAXCCH_HTLINK_FIELD * sizeof(wchar_t))
+
+/*!@}*/
+/*!@}*/
+
+#endif
diff --git a/src/windows/identity/uilib/khnewcred.h b/src/windows/identity/uilib/khnewcred.h
index e22e1f77f2..c3ef5dabf2 100644
--- a/src/windows/identity/uilib/khnewcred.h
+++ b/src/windows/identity/uilib/khnewcred.h
@@ -1,985 +1,985 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#ifndef __KHIMAIRA_KHNEWCRED_H
-#define __KHIMAIRA_KHNEWCRED_H
-
-/********************************************************************
- New credentials windows
-*********************************************************************/
-
-/*! \addtogroup khui
-@{ */
-
-/*! \defgroup khui_cred Credentials acquisition
-
- Declarations associated with credentials acquisition.
-
-@{ */
-
-/*! \brief Window message sent to credentials type panels
-
- This message is sent to the child windows.
-
- The format of the message is :
- - uMsg : KHUI_WM_NC_NOTIFY
- - HIWORD(wParam) : one of ::khui_wm_nc_notifications
- - LPARAM : pointer to the ::khui_new_creds structure
-*/
-#define KHUI_WM_NC_NOTIFY (WM_APP + 0x101)
-
-/*! \brief The first control ID that may be used by an identity provider */
-#define KHUI_CW_ID_MIN 8016
-
-/*! \brief The maximum number of controls that may be created by an identity provider*/
-#define KHUI_CW_MAX_CTRLS 8
-
-/*! \brief The maximum control ID that may be used by an identity provider */
-#define KHUI_CW_ID_MAX (KHUI_CW_ID_MIN + KHUI_CW_MAX_CTRLS - 1)
-
-
-/*! \brief Credentials dialog notifications
-
- These notifications will be sent to the individual dialog
- procedures of the credential type panels as a ::KHUI_WM_NC_NOTIFY
- message.
-*/
-enum khui_wm_nc_notifications {
- WMNC_DIALOG_EXPAND = 1,
- /*!< The dialog is switching from basic to advanced mode or vice
- versa.
-
- This message is sent to the new creds dialog to set the dialog
- to expanded mode. In expanded mode, all credentials type panels
- are visible as opposed to the compressed mode where they are not
- visible. The message is not sent to credentials type panels.*/
-
- WMNC_DIALOG_SETUP,
- /*!< Sent by NetIDMgr to the new creds window to notify it that
- the dialog should create all the type configuration panels.
-
- Until this message is issued, none of the credentials type
- panels exist. The credentials type panels will receive
- WM_INITDIALOG etc as per the normal dialog creation process. */
-
- WMNC_DIALOG_ACTIVATE,
- /*!< Sent by NetIDMgr to the new creds window to notify it that
- the dialog should do final initialization work and activate. */
-
- WMNC_DIALOG_MOVE,
- /*!< Sent by the new creds widnow to all the panels notifying them
- that the NC window is moving. */
-
- WMNC_DIALOG_SWITCH_PANEL,
- /*!< Sent to the new creds window to cause it to switch to the
- panel identified by LOWORD(wParam).
-
- Does nothing if the specified panel is already the current
- panel. If the dialog is in compact mode and making the
- specified panel visible requires switching to expanded mode, the
- dialog will do so. */
-
- WMNC_UPDATE_CREDTEXT,
- /*!< Sent to all the credential type panels for a credentials
- window to request them to update the credential text.
-
- When sent to the new credentials window, causes it to send the
- WMNC_UPDATE_CREDTEXT message to all the credential type panels
- and update the cred text window.*/
-
- WMNC_CREDTEXT_LINK,
- /*!< Sent to a panel dialog proc when a user clicks a credtext
- embedded link that belongs to that panel. The \a lParam
- parameter of the message is a pointer to a ::khui_htwnd_link
- structure describing the link. */
-
- WMNC_IDENTITY_CHANGE,
- /*!< The primary identity has changed */
-
- WMNC_CLEAR_PROMPTS,
- /*!< Sent to the new creds window to clear any custom prompts */
-
- WMNC_SET_PROMPTS,
- /*!< Sent to the new creds window to set custom prompts */
-
- WMNC_DIALOG_PREPROCESS,
- /*!< Sent to all the credentials type panels to notify them that
- the dialog is about to be processed */
-
- WMNC_DIALOG_PROCESS,
- /*!< Process the dialog and signal whether to exit the dialog or
- not */
-
- WMNC_DIALOG_PROCESS_COMPLETE,
- /*!< Sent to the new creds window to indicate that the all the
- threads have completed processing.*/
-
- WMNC_TYPE_STATE,
- /*!< Sent to the new creds window as notification that a
- particular credentials type has changed state from enabled to
- disabled or vice versa. The LPARAM member of the message
- specifies the credentials type identifier for the changed
- type */
-
- WMNC_ADD_CONTROL_ROW,
- /*!< Add a row of controls to a new cred dialog. This is an
- internal message. */
-
- WMNC_UPDATE_LAYOUT,
- /*!< Update the layout of a dialog or window. This is an internal
- message. */
-};
-
-/*! \brief Plugins can use WMNC_NOTIFY message codes from here on up
-
- \see ::KHUI_WM_NC_NOTIFY
- */
-#define WMNC_USER 2048
-
-/*! \brief Notifications to the identity provider
-
- These notifications are sent through to the identity provider's UI
- callback that was obtained using a ::KMSG_IDENT_GET_UI_CB message.
-
- The callback routine is called from the context of the UI thread
- and is expected to not make any blocking calls. One of the
- following commands will be passed in as the \a cmd parameter to
- the callback.
- */
-enum khui_wm_nc_ident_notify {
- WMNC_IDENT_INIT,
- /*!< Initialize an identity selector for a new credentials
- dialog. The \a lParam parameter contains a handle to the
- dialog window which will contain the identity selector
- controls. The identity provider may make use of the \a
- ident_aux field of the ::khui_new_creds structure to hold any
- data pertaining to the credentials acquisition dialog.*/
-
- WMNC_IDENT_WMSG,
- /*!< Windows message. Presumably sent from one of the controls
- that was created by the identity provider. The callback is
- expected to return TRUE if it processed the message or FALSE
- if it did not. The \a uMsg, \a wParam and \a lParam
- parameters are set to the values passed in by Windows. */
-
- WMNC_IDENT_EXIT,
- /*!< Terminate a credentials acquisition dialog. Sent just before
- the dialog is terminated. */
-};
-
-/*! \name Standard credtext link IDs
-@{*/
-
-/*! \brief Switch the panel
-
- The \a id attribute of the link specifies the ordinal of the panel
- to switch to.
-*/
-#define CTLINKID_SWITCH_PANEL L"SwitchPanel"
-
-/*@}*/
-
-/*forward dcl*/
-struct tag_khui_new_creds_by_type;
-typedef struct tag_khui_new_creds_by_type khui_new_creds_by_type;
-struct tag_khui_new_creds_prompt;
-typedef struct tag_khui_new_creds_prompt khui_new_creds_prompt;
-struct tag_khui_new_creds;
-typedef struct tag_khui_new_creds khui_new_creds;
-
-typedef LRESULT
-(KHMAPI *khui_ident_new_creds_cb)(khui_new_creds * nc,
- UINT cmd,
- HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam);
-
-/*! \brief New credentials acquisition blob
-
- A pointer to an object of this type is passed in along with the
- credentials acquisition messages.
-
- \see \ref cred_acq for more information
-*/
-typedef struct tag_khui_new_creds {
- khm_int32 magic; /*!< Internal use */
-
- khm_int32 subtype; /*!< Subtype of the request that is
- being handled through this object.
- One of ::KMSG_CRED_NEW_CREDS,
- ::KMSG_CRED_RENEW_CREDS or
- ::KMSG_CRED_PASSWORD */
-
- CRITICAL_SECTION cs; /*!< Internal use */
-
- khm_boolean set_default; /*!< After a successfull credentials
- acquisition, set the primary
- identity as the default. */
-
- khm_handle *identities; /*!< The list of identities associated
- with this request. The first
- identity in this list (\a
- identities[0]) is the primary
- identity. */
-
- khm_size n_identities; /*!< Number of identities in the list
- \a identities */
-
- khm_size nc_identities; /*!< Internal use */
-
- khui_action_context ctx; /*!< An action context specifying the
- context in which the credentials
- acquisition operation was
- launced. */
-
- khm_int32 mode; /*!< The mode of the user interface.
- One of ::KHUI_NC_MODE_MINI or
- ::KHUI_NC_MODE_EXPANDED. */
-
- HWND hwnd; /*!< Handle to the new credentials
- window. */
-
- struct tag_khui_new_creds_by_type **types;
- /*!< Internal use */
- khm_handle *type_subs; /*!< Internal use */
- khm_size n_types; /*!< Internal use */
- khm_size nc_types; /*!< Internal use */
-
- khm_int32 result; /*!< One of ::KHUI_NC_RESULT_CANCEL or
- ::KHUI_NC_RESULT_PROCESS indicating
- the result of the dialog with the
- user */
-
- khm_int32 response; /*!< Response. See individual message
- documentation for info on what to do
- with this field */
-
- wchar_t *password; /*!< Not used. */
-
- /* UI stuff */
-
- wchar_t *banner; /*!< Internal use */
- wchar_t *pname; /*!< Internal use */
- khm_size n_prompts; /*!< Internal use */
- khm_size nc_prompts; /*!< Internal use */
- struct tag_khui_new_creds_prompt ** prompts; /*!< Internal use */
-
- khui_ident_new_creds_cb ident_cb; /*!< Internal use */
-
- wchar_t *window_title; /*!< Internal use */
-
- LPARAM ident_aux; /*!< Auxilliary field which is
- reserved for use by the identity
- provider during the course of
- conducting this dialog. */
-
-} khui_new_creds;
-
-#define KHUI_NC_MAGIC 0x84270427
-
-/*!\name Result values for khui_new_creds_t::result
- @{*/
-#define KHUI_NC_RESULT_PROCESS 0
-#define KHUI_NC_RESULT_CANCEL 1
-/*@}*/
-
-/*!\name Mode values for khui_new_creds_t::mode
- @{*/
-#define KHUI_NC_MODE_MINI 0
-#define KHUI_NC_MODE_EXPANDED 1
-/*@}*/
-
-/*!\name Response values for khui_new_creds_t::response
- @{*/
-/*!\brief No known response */
-#define KHUI_NC_RESPONSE_NONE 0
-
-/*!\brief It is okay to exit the dialog now
-
- This is the default, which is why it has a value of zero. In
- order to prevent the dialog from exiting, set the
- KHUI_NC_RESPONSE_NOEXIT response bit. */
-#define KHUI_NC_RESPONSE_EXIT 0
-
-/*!\brief It is NOT okay to exit the dialog now
-
- Used to indicate that further user-interaction is necessary to
- process the dialog. Usually this is accompanied by setting
- necessary custom prompts and notifications so the user knows why
- the dialog is prompting for more information.
- */
-#define KHUI_NC_RESPONSE_NOEXIT 0x00000002
-
-/*!\brief The dialog was processed successfully
-
- Since this is the default response, the value is zero. Use one of
- KHUI_NC_RESPONSE_FAILED or KHUI_NC_RESPONSE_PENDING to indicate an
- error or pending status.
- */
-#define KHUI_NC_RESPONSE_SUCCESS 0
-
-/*!\brief The processing of the dialog failed
-
- Self explanatory. More information about the failure should have
- been reported using the khlog API, however, this response value
- indicates to other credential types that depend on this credential
- type that whatever it was that this credential type was supposed
- to do didn't happen.
-*/
-#define KHUI_NC_RESPONSE_FAILED 0x00000008
-
-/*!\brief Further interaction required
-
- Set along with KHUI_NC_RESPONSE_NOEXIT although it is not
- required. Setting this bit will automatically add the
- KHUI_NC_RESPONSE_NOEXIT.
-
- If this bit is set, all dependent plugins will be set on hold
- until another round of processing clears the pending bit.
- */
-#define KHUI_NC_RESPONSE_PENDING 0x00000010
-
-/*! \brief Completed
-
- This is automatically set if the plugin sets a response which does
- not indicate either KHUI_NC_RESPONSE_NOEXIT or
- KHUI_NC_RESPONSE_PENDING, which is considered to mean that the
- plugin is completed processing.
-
- This flag cannot be explicitly specified in a response.
- */
-#define KHUI_NC_RESPONSE_COMPLETED 0x00000020
-
-/*! \brief Processing
-
- This is an internal flag set while the credentials acquisition
- process is executing.
- */
-#define KHUI_NC_RESPONSE_PROCESSING 0x00010000
-
-#define KHUI_NCMASK_RESPONSE (KHUI_NC_RESPONSE_EXIT|KHUI_NC_RESPONSE_NOEXIT)
-#define KHUI_NCMASK_RESULT (KHUI_NC_RESPONSE_SUCCESS|KHUI_NC_RESPONSE_FAILED|KHUI_NC_RESPONSE_PENDING)
-/*@}*/
-
-/*!\brief Maximum number of dependencies for a credentials type */
-#define KHUI_MAX_TYPE_DEPS 8
-
-/*!\brief Maximum number of credential types for a new creds window */
-#define KHUI_MAX_NCTYPES 16
-
-/*!\brief Maximum number of characters in a password
-
- Length includes the termininating NULL
-*/
-#define KHUI_MAXCCH_PASSWORD 512
-
-/*! \brief Maximum number of bytes in a password
-
- Includes terminating NULL
-*/
-#define KHUI_MAXCB_PASSWORD (KHUI_MAXCCH_PASSWORD * sizeof(wchar_t))
-
-/*! \brief Maximum number of characters in a custom banner
-
- Length includes terminating NULL
-*/
-#define KHUI_MAXCCH_BANNER 256
-
-
-/*! \brief Maximum number of bytes in a custom banner
-
- Length includes terminating NULL
-*/
-#define KHUI_MAXCB_BANNER (KHUI_MAXCCH_BANNER * sizeof(wchar_t))
-
-/*! \brief Maximum number of characters in a panel name
-
- Length includes terminating NULL
-*/
-#define KHUI_MAXCCH_PNAME 256
-
-/*! \brief Maximum number of bytes in a panel name
-
- Length includes terminating NULL
-*/
-#define KHUI_MAXCB_PNAME (KHUI_MAXCCH_PNAME * sizeof(wchar_t))
-
-/*! \brief A descriptor of a panel in the new credentials acquisition tab
-
- When processing certain credentials messages such as
- ::KMSG_CRED_PASSWORD, ::KMSG_CRED_NEW_CREDS,
- ::KMSG_CRED_RENEW_CREDS, a pointer to a ::khui_new_creds structure
- will be passed in to the message handler. If the handler of the
- message needs to add one or more credentials types as participants
- of the operation, the handler will need to call khui_cw_add_type()
- and specify a ::khui_new_creds_by_type structure.
-
- Note that the memory address passed in to the call to
- khui_cw_add_type() will not be copied. Therefore, the block of
- memory should remain as-is for the lifetime of the
- ::khui_new_creds structure or until it is removed with a call to
- khui_cw_del_type().
-
- Some of the credentials messages that require specifying a
- ::khui_new_creds_by_type structure require providing a
- user-interface. In these cases, the fields marked for providing a
- UI may be required to hold valid values. If the message does not
- require providing a UI, these fields will be ignored.
-*/
-typedef struct tag_khui_new_creds_by_type {
- khui_new_creds * nc; /*!< Internal use. Do not set */
- khm_int32 flags; /*!< Internal use. Do not set */
-
- khm_int32 type; /*!< The identifier of the credentials
- type. This is a credentials type
- identifier allocated with a call to
- kcdb_credtype_register(). */
-
- khm_int32 type_deps[KHUI_MAX_TYPE_DEPS];
- /*!< credentials types that this
- credential type depends on. Each
- element defines a credentials type
- identifier that this type depends
- on for this operation. The number
- of valid values in this array
- should be specified in the \a
- n_type_deps field. */
-
- khm_size n_type_deps; /*!< Number of dependencies listed
- above. Should be between 0 and
- ::KHUI_MAX_TYPE_DEPS. Specify 0 if
- there are no dependencies. */
-
- khm_size ordinal; /*!< The requested ordinal. The UI
- would attempt to place this panel at
- the reqested order in the list of
- panels. Set to -1 if the order does
- not matter. Once the dialog is
- activated this field will be updated
- to reflect the actual ordinal of the
- panel. */
-
- wchar_t *name; /*!< Name of the panel (localized,
- optional). If NULL, the localized
- name of the credentials type is
- used. Only used if providing a
- user-interface. */
-
- HICON icon; /*!< Icon for the panel (optional).
- Only used if providing a
- user-interface. */
-
- wchar_t *tooltip; /*!< Tooltip for the panel (localized,
- optional). If NULL, no tooltip will
- be assigned for the panel. Only
- used if providing a
- user-interface. */
-
- HMODULE h_module; /*!< Handle to the module containing
- the dialog resource. Only used if
- providing a user-interface. */
-
- LPWSTR dlg_template; /*!< The dialog resource. Only used
- if providing a user-interface. */
- DLGPROC dlg_proc; /*!< The dialog procedure. Only used
- if providing a user-interface. */
-
- HWND hwnd_panel; /*!< The dialog window. Once the
- dialog panel is created, a handle to
- the panel will be assigned here.
- Note that the handle is assigned
- after a successful call to
- CreateDialogParam and hence would
- not be available when handling the
- WM_INITDIALOG message from the
- dialog procedure. Only used of
- providing a user-interface. */
-
- HWND hwnd_tc; /*!< Internal use. Do not set */
-
- wchar_t *credtext; /*!< A brief description of the
- current state of this cred
- type. (localized, optional). Only
- used if providing a
- user-interface. If this field is
- non-NULL, then it should point to a
- NULL terminated string that does not
- exceed ::KHUI_MAXCCH_LONG_DESC
- characters in length including the
- terminating NULL.
-
- \see \ref khui_htwnd for information
- on how to format the string for this
- field.
- */
-
- LPARAM aux; /*!< auxilliary field. For use by the
- plug-in. */
-} khui_new_creds_by_type;
-
-/*!\name Flags for khui_new_creds_by_type
-
- Note that KHUI_NC_RESPONSE_SUCCESS, KHUI_NC_RESPONSE_FAILED,
- KHUI_NC_RESPONSE_PENDING are also stored in the flags.
-
-@{*/
-#define KHUI_NCT_FLAG_PROCESSED 1024
-#define KHUI_NCT_FLAG_DISABLED 2048
-/*@}*/
-
-/*! \brief Width of a new creds dialog panel in dialog units*/
-#define NCDLG_WIDTH 300
-/*! \brief Height of a new creds dialog panel in dialog units*/
-#define NCDLG_HEIGHT 166
-
-/*! \brief A custom prompt */
-typedef struct tag_khui_new_creds_prompt {
- khm_size index; /*!< Set to the zero based index
- of this prompt. */
-
- khm_int32 type; /*!< one of KHUI_NCPROMPT_TYPE_* */
- wchar_t * prompt; /*!< prompt string. Cannot exceed
- KHUI_MAXCCH_PROMPT */
- wchar_t * def; /*!< default value. Cannot exceed
- KHUI_MAXCCH_PROMPT_VALUE */
- wchar_t * value; /*!< On completion, this is set to the
- value that the user entered. Will
- not exceed
- KHUI_MAXCCH_PROMPT_VALUE */
-
- khm_int32 flags; /*!< Combination of
- KHUI_NCPROMPT_FLAG_* */
-
- HWND hwnd_static; /* internal use */
- HWND hwnd_edit; /* internal use */
-} khui_new_creds_prompt;
-
-/*! \brief The prompt input is hidden
-
- The input is hidden for prompts which accept passwords. The
- control which represents the input will display an asterisk or a
- small circle corresponding to each character typed in, but will
- not show the actual character.
- */
-#define KHUI_NCPROMPT_FLAG_HIDDEN 1
-
-/*! \brief Internal use */
-#define KHUI_NCPROMPT_FLAG_STOCK 2
-
-/*! \brief Maximum number of characters in a prompt
-
- Refers to the prompt text that accompanies an input control. THe
- length includes the terminating NULL.
- */
-#define KHUI_MAXCCH_PROMPT 256
-
-/*! \brief Maximum number of bytes in a prompt
-
- Refers to the prompt text that accompanies an input control. THe
- length includes the terminating NULL.
- */
-#define KHUI_MAXCB_PROMPT (KHUI_MAXCCH_PROMPT * sizeof(wchar_t))
-
-/*! \brief Maximum number of characters that can be entered in an input control
-
- Refers to the input control of a prompt. The length includes the
- terminating NULL.
- */
-#define KHUI_MAXCCH_PROMPT_VALUE 256
-
-/*! \brief Maximum number of bytes that can be entered in an input control
-
- Refers to the input control of a prompt. The length includes the
- terminating NULL.
- */
-#define KHUI_MAXCB_PROMPT_VALUE (KHUI_MAXCCH_PROMPT_VALUE * sizeof(wchar_t))
-
-/* from krb5.h. Redefining here because we don't want to depend on
- krb5.h for all credential types */
-
-/*! \brief A password control */
-#define KHUI_NCPROMPT_TYPE_PASSWORD 1
-
-/*! \brief New password control
-
- Used when changing the password
- */
-#define KHUI_NCPROMPT_TYPE_NEW_PASSWORD 2
-
-/*! \brief New password again control
-
- Used when changing the password
- */
-#define KHUI_NCPROMPT_TYPE_NEW_PASSWORD_AGAIN 3
-
-/*! \brief Preauthentication (reserved) */
-#define KHUI_NCPROMPT_TYPE_PREAUTH 4
-
-/*! \brief Control sizes */
-typedef enum tag_khui_control_size {
- KHUI_CTRLSIZE_SMALL,
- /*!< A small control fits in about 1/5 the width of the new
- credentials panel */
- KHUI_CTRLSIZE_HALF,
- /*!< Half size controls fit in 1/2 the width of the new
- credentials panel */
- KHUI_CTRLSIZE_FULL,
- /*!< Takes up the whole width of the crednetials panel */
-} khui_control_size;
-
-/*! \brief Internal use */
-typedef struct tag_khui_control_row {
- HWND label;
- HWND input;
- khui_control_size size;
-} khui_control_row;
-
-/*! \brief Create a ::khui_new_creds object
-
- Creates and initializes a ::khui_new_creds object. The created
- object must be destroyed using the khui_cw_destroy_cred_blob()
- function.
-
- \note Plugins should not call this function directly. The
- necessary ::khui_new_creds objects will be created by
- NetIDMgr.
-
- \see khui_cw_destroy_cred_blob()
- */
-KHMEXP khm_int32 KHMAPI
-khui_cw_create_cred_blob(khui_new_creds ** c);
-
-/*! \brief Destroy a ::khui_new_creds object
-
- Destroys a ::khui_new_creds object that was fomerly created using
- a call to khui_cw_create_cred_blob().
-
- \note Plugins should not call this function directly. The
- necessary ::khui_new_creds objects will be created by
- NetIDMgr.
-
- \see khui_cw_create_cred_blob()
-*/
-KHMEXP khm_int32 KHMAPI
-khui_cw_destroy_cred_blob(khui_new_creds *c);
-
-/*! \brief Lock the new_creds object
-
- When a plugin is accessing the fields of a ::khui_new_creds
- object, it must first obtain a lock on the object so that other
- threads will not modify the fields at the same time. Locking the
- object ensures that the fields of the object will be consistent.
-
- Use khui_cw_unlock_nc() to undo the lock obtained through a call
- to khui_cw_lock_nc().
-
- It is not necessary to lock a new credentials object when
- modifying it using the NetIDMgr API.
- */
-KHMEXP khm_int32 KHMAPI
-khui_cw_lock_nc(khui_new_creds * c);
-
-/*! \brief Unlock a new_creds object
-
- \see khui_cw_lock_nc()
- */
-KHMEXP khm_int32 KHMAPI
-khui_cw_unlock_nc(khui_new_creds * c);
-
-/*! \brief Add a new panel to a new credentials acquisition window
-
- See the description of ::khui_new_cred_panel for information on
- how to populate it to describe a credentials type panel.
-
- Note that the structure pointed to by \a t is added by reference.
- The memory pointed to by \a t is not copied. Hence, the block of
- memory and any other blocks pointed to by the
- ::khui_new_creds_by_type structure located there should remain
- intact for the lifetime of the ::khui_new_creds structure pointed
- to by \a c or until the credentials type panel is removed from the
- ::khui_new_creds structure with a call to khui_cw_del_type().
-
- Generally, a plug-in that calls this function should allocate a
- block of memory to contain the ::khui_new_creds_by_type structure,
- fill it in and then pass in the address in a call to
- khui_cw_add_type() while handling a ::KMSG_CRED_PASSWORD,
- ::KMSG_CRED_NEW_CREDS or ::KMSG_CRED_RENEW_CREDS message. Then
- the plug-in should remove the reference with a call to
- khui_cw_del_type() while processing ::KMSG_CRED_END.
-
- \see khui_cw_del_type()
- \see \ref cred_acq_panel_spec
- \see ::khui_new_cred_panel
- \see ::khui_new_creds
-*/
-KHMEXP khm_int32 KHMAPI
-khui_cw_add_type(khui_new_creds * c,
- khui_new_creds_by_type * t);
-
-/*! \brief Remove a panel from a new credentials acquisition window
-
- \see khui_cw_add_type()
- */
-KHMEXP khm_int32 KHMAPI
-khui_cw_del_type(khui_new_creds * c,
- khm_int32 type);
-
-/*! \brief Find the panel belonging to a particular credentials type
-
- This panel would have been added to the new credentials window
- using khui_cw_add_type().
-
- \see khui_cw_add_type()
- */
-KHMEXP khm_int32 KHMAPI
-khui_cw_find_type(khui_new_creds * c,
- khm_int32 type,
- khui_new_creds_by_type **t);
-
-/*! \brief Enable/disable a particular credentials type
-
- Enables or disables the panel associated with a particular
- credentials type. Does not preclude the credentials type from
- participating in the new credentials acquisition. However, the
- user will be prevented from interacting with the specific panel.
- */
-KHMEXP khm_int32 KHMAPI
-khui_cw_enable_type(khui_new_creds * c,
- khm_int32 type,
- khm_boolean enable);
-
-/*! \brief Set the primary identity in a new credentials acuisition
-
- The primary identity dictates many of the defaults and the
- semantics associated with the credentials acquision process.
- Setting the primary identity also triggers the
- ::WMNC_IDENTITY_CHANGE notification which will be sent to all the
- credentials type panels.
-
- Has no effect if the primary identity is already the same as the
- one specified in \a id. Specify NULL for \a id if the current
- primary identity is to be cleared.
-
- If the primary identity is changed, then all the additional
- identities associated with the new credentials acquisition dialog
- will also be discarded.
- */
-KHMEXP khm_int32 KHMAPI
-khui_cw_set_primary_id(khui_new_creds * c,
- khm_handle id);
-
-/*! \brief Add an additional identity to the new credentials acquisition
-
- Individual plugins are free to decide how to handle additional
- identities. Generally, they would attempt to obtain credentials
- for the primary and additional identities, but would not consider
- it an error if an additional identity failed to obtain
- credentials.
-
- Calling this function with \a id of NULL does nothing.
-*/
-KHMEXP khm_int32 KHMAPI
-khui_cw_add_identity(khui_new_creds * c,
- khm_handle id);
-
-/*! \brief Clear all custom prompts
-
- Removes all the custom prompts from the new credentials dialog.
- */
-KHMEXP khm_int32 KHMAPI
-khui_cw_clear_prompts(khui_new_creds * c);
-
-/*! \brief Synchronize custom prompt values
-
- It is important to synchronize the values before accessing their
- values. The controls associated with custom prompts update the
- values in the ::khui_new_creds object periodically. However, the
- values may lose sync intermittently.
- */
-KHMEXP khm_int32 KHMAPI
-khui_cw_sync_prompt_values(khui_new_creds * c);
-
-/*! \brief Begin custom prompting
-
- Begins the process of defining custom prompts. Implicity removes
- all the custom prompts that are currently being displayed. The \a
- banner and \a name will be displayed in separate controls above
- the set of new custom prompts.
-
- The controls associated with the prompts will not actually be
- created until all the prompts have been added using
- khui_cw_add_prompt(). The number of promtps that can be added
- will be exactly \a n_prompts.
- */
-KHMEXP khm_int32 KHMAPI
-khui_cw_begin_custom_prompts(khui_new_creds * c,
- khm_size n_prompts,
- wchar_t * banner,
- wchar_t * name);
-
-/*! \brief Add a custom prompt
-
- After khui_cw_begin_custom_prompts() is called, the plugin should
- call khui_cw_add_prompt() to add the actual prompts. The number
- of prompts that can be added is the \a n_prompts value specified
- in the earlier call to \a khui_cw_begin_custom_prompts().
-
- Once \a n_prompts prompts have been added, the new prompts will
- automatically be created and shown in the user interface.
- However, if less than that prompts are added, nothing is displayed
- to the user.
-
- \param[in] c Pointer to ::khui_new_creds structure
-
- \param[in] type Type of prompt. One of
- ::KHUI_NCPROMPT_TYPE_PREAUTH, ::KHUI_NCPROMPT_TYPE_PASSWORD,
- ::KHUI_NCPROMPT_TYPE_NEW_PASSWORD,
- ::KHUI_NCPROMPT_TYPE_NEW_PASSWORD_AGAIN
-
- \param[in] prompt Text of the prompt. Constrained by
- ::KHUI_MAXCCH_PROMPT. (Localized, required)
-
- \param[in] def Default value. (optional). Constrained by
- ::KHUI_MAXCCH_PROMPT_VALUE. Set to NULL if not provided.
-
- \param[in] flags Flags. Combination of
- ::KHUI_NCPROMPT_FLAG_HIDDEN
- */
-KHMEXP khm_int32 KHMAPI
-khui_cw_add_prompt(khui_new_creds * c,
- khm_int32 type,
- wchar_t * prompt,
- wchar_t * def,
- khm_int32 flags);
-
-/*! \brief Retrieve a custom prompt
-
- Retrieves an individual prompt. The \a idx parameter is a
- zero-based index of the prompt to retrieve. The ordering is the
- same as the order in which khui_cw_add_prompt() was called.
- */
-KHMEXP khm_int32 KHMAPI
-khui_cw_get_prompt(khui_new_creds * c,
- khm_size idx,
- khui_new_creds_prompt ** prompt);
-
-/*! \brief Get the number of custom prompts
-
- Retrieves the number of custom prompts currently displayed. If
- this function is called between calling
- khui_cw_begin_custom_prompts() and adding all the prompts, the
- number returned will be the number of prompts that is expected to
- be registered (i.e. the \a n_prompts parameter passed to
- khui_cw_begin_custom_prompts()).
- */
-KHMEXP khm_int32 KHMAPI
-khui_cw_get_prompt_count(khui_new_creds * c,
- khm_size * np);
-
-
-/*! \brief Get the value of a custom prompt
-
- Retrieve the value of a specific prompt. The value is the string
- that was typed into the input control associated with a custom
- prompt. The \a idx parameter is the zero-based index of the
- prompt from which to retrieve the value from. The ordering is the
- same as the order in which khui_cw_add_prompt() was called.
-
- It is important to call khui_cw_sync_prompt_values() before
- starting to call khui_cw_get_prompt_value() so that the values
- returned are up-to-date.
- */
-KHMEXP khm_int32 KHMAPI
-khui_cw_get_prompt_value(khui_new_creds * c,
- khm_size idx,
- wchar_t * buf,
- khm_size *cbbuf);
-
-/*! \brief Set the response for a plugin
-
- When handling ::KMSG_CRED_DIALOG_PROCESS from within the plugin
- thread, it is important to set the response by calling this
- function. The response can be used to signal whether the plugin
- successfully obtained credentials or whether further interaction
- is required, or the credentials acquisition failed.
-
- The response is a combination of :
- - ::KHUI_NC_RESPONSE_PENDING
- - ::KHUI_NC_RESPONSE_FAILED
- - ::KHUI_NC_RESPONSE_PENDING
- - ::KHUI_NC_RESPONSE_SUCCESS
- - ::KHUI_NC_RESPONSE_NOEXIT
- - ::KHUI_NC_RESPONSE_EXIT
- */
-KHMEXP khm_int32 KHMAPI
-khui_cw_set_response(khui_new_creds * c,
- khm_int32 type,
- khm_int32 response);
-
-/*! \brief Check whether a specified credential type panel succeeded
-
- This is called during the processing of ::KMSG_CRED_DIALOG_PROCESS
- to determine whether a specified credential type succeeded in
- obtaining credentials. The credential type that is being queried
- should have also been listed as a dependency when adding the
- current credentials type, otherwise the type queried may not have
- been invoked yet.
-
- \return TRUE iff the queried type has reported that it successfully
- completed the credentials acquision operation.
- */
-KHMEXP khm_boolean KHMAPI
-khui_cw_type_succeeded(khui_new_creds * c,
- khm_int32 type);
-
-/*! \brief Add a row of controls to the identity specifier area
-
- Only for use by identity provider callbacks that wish to add an
- identity selector control. A row of controls consist of a label
- control and some input control.
-
- When the ::WMNC_IDENT_INIT message is sent to the identity
- provider, it receives a handle to the dialog panel in the \a
- lParam parameter which should be the parent window of both the
- windows specified here. The control ID for any controls created
- must fall within the ::KHUI_CW_ID_MIN and ::KHUI_CW_ID_MAX range.
-
- Both controls will be resized to fit in the row.
-
- If \a long_label is TRUE then the size of the label will be larger
- than normal and will accomodate more text.
- */
-KHMEXP khm_int32 KHMAPI
-khui_cw_add_control_row(khui_new_creds * c,
- HWND label,
- HWND input,
- khui_control_size size);
-
-/*!@}*/ /* Credentials acquisition */
-/*!@}*/
-
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __KHIMAIRA_KHNEWCRED_H
+#define __KHIMAIRA_KHNEWCRED_H
+
+/********************************************************************
+ New credentials windows
+*********************************************************************/
+
+/*! \addtogroup khui
+@{ */
+
+/*! \defgroup khui_cred Credentials acquisition
+
+ Declarations associated with credentials acquisition.
+
+@{ */
+
+/*! \brief Window message sent to credentials type panels
+
+ This message is sent to the child windows.
+
+ The format of the message is :
+ - uMsg : KHUI_WM_NC_NOTIFY
+ - HIWORD(wParam) : one of ::khui_wm_nc_notifications
+ - LPARAM : pointer to the ::khui_new_creds structure
+*/
+#define KHUI_WM_NC_NOTIFY (WM_APP + 0x101)
+
+/*! \brief The first control ID that may be used by an identity provider */
+#define KHUI_CW_ID_MIN 8016
+
+/*! \brief The maximum number of controls that may be created by an identity provider*/
+#define KHUI_CW_MAX_CTRLS 8
+
+/*! \brief The maximum control ID that may be used by an identity provider */
+#define KHUI_CW_ID_MAX (KHUI_CW_ID_MIN + KHUI_CW_MAX_CTRLS - 1)
+
+
+/*! \brief Credentials dialog notifications
+
+ These notifications will be sent to the individual dialog
+ procedures of the credential type panels as a ::KHUI_WM_NC_NOTIFY
+ message.
+*/
+enum khui_wm_nc_notifications {
+ WMNC_DIALOG_EXPAND = 1,
+ /*!< The dialog is switching from basic to advanced mode or vice
+ versa.
+
+ This message is sent to the new creds dialog to set the dialog
+ to expanded mode. In expanded mode, all credentials type panels
+ are visible as opposed to the compressed mode where they are not
+ visible. The message is not sent to credentials type panels.*/
+
+ WMNC_DIALOG_SETUP,
+ /*!< Sent by NetIDMgr to the new creds window to notify it that
+ the dialog should create all the type configuration panels.
+
+ Until this message is issued, none of the credentials type
+ panels exist. The credentials type panels will receive
+ WM_INITDIALOG etc as per the normal dialog creation process. */
+
+ WMNC_DIALOG_ACTIVATE,
+ /*!< Sent by NetIDMgr to the new creds window to notify it that
+ the dialog should do final initialization work and activate. */
+
+ WMNC_DIALOG_MOVE,
+ /*!< Sent by the new creds widnow to all the panels notifying them
+ that the NC window is moving. */
+
+ WMNC_DIALOG_SWITCH_PANEL,
+ /*!< Sent to the new creds window to cause it to switch to the
+ panel identified by LOWORD(wParam).
+
+ Does nothing if the specified panel is already the current
+ panel. If the dialog is in compact mode and making the
+ specified panel visible requires switching to expanded mode, the
+ dialog will do so. */
+
+ WMNC_UPDATE_CREDTEXT,
+ /*!< Sent to all the credential type panels for a credentials
+ window to request them to update the credential text.
+
+ When sent to the new credentials window, causes it to send the
+ WMNC_UPDATE_CREDTEXT message to all the credential type panels
+ and update the cred text window.*/
+
+ WMNC_CREDTEXT_LINK,
+ /*!< Sent to a panel dialog proc when a user clicks a credtext
+ embedded link that belongs to that panel. The \a lParam
+ parameter of the message is a pointer to a ::khui_htwnd_link
+ structure describing the link. */
+
+ WMNC_IDENTITY_CHANGE,
+ /*!< The primary identity has changed */
+
+ WMNC_CLEAR_PROMPTS,
+ /*!< Sent to the new creds window to clear any custom prompts */
+
+ WMNC_SET_PROMPTS,
+ /*!< Sent to the new creds window to set custom prompts */
+
+ WMNC_DIALOG_PREPROCESS,
+ /*!< Sent to all the credentials type panels to notify them that
+ the dialog is about to be processed */
+
+ WMNC_DIALOG_PROCESS,
+ /*!< Process the dialog and signal whether to exit the dialog or
+ not */
+
+ WMNC_DIALOG_PROCESS_COMPLETE,
+ /*!< Sent to the new creds window to indicate that the all the
+ threads have completed processing.*/
+
+ WMNC_TYPE_STATE,
+ /*!< Sent to the new creds window as notification that a
+ particular credentials type has changed state from enabled to
+ disabled or vice versa. The LPARAM member of the message
+ specifies the credentials type identifier for the changed
+ type */
+
+ WMNC_ADD_CONTROL_ROW,
+ /*!< Add a row of controls to a new cred dialog. This is an
+ internal message. */
+
+ WMNC_UPDATE_LAYOUT,
+ /*!< Update the layout of a dialog or window. This is an internal
+ message. */
+};
+
+/*! \brief Plugins can use WMNC_NOTIFY message codes from here on up
+
+ \see ::KHUI_WM_NC_NOTIFY
+ */
+#define WMNC_USER 2048
+
+/*! \brief Notifications to the identity provider
+
+ These notifications are sent through to the identity provider's UI
+ callback that was obtained using a ::KMSG_IDENT_GET_UI_CB message.
+
+ The callback routine is called from the context of the UI thread
+ and is expected to not make any blocking calls. One of the
+ following commands will be passed in as the \a cmd parameter to
+ the callback.
+ */
+enum khui_wm_nc_ident_notify {
+ WMNC_IDENT_INIT,
+ /*!< Initialize an identity selector for a new credentials
+ dialog. The \a lParam parameter contains a handle to the
+ dialog window which will contain the identity selector
+ controls. The identity provider may make use of the \a
+ ident_aux field of the ::khui_new_creds structure to hold any
+ data pertaining to the credentials acquisition dialog.*/
+
+ WMNC_IDENT_WMSG,
+ /*!< Windows message. Presumably sent from one of the controls
+ that was created by the identity provider. The callback is
+ expected to return TRUE if it processed the message or FALSE
+ if it did not. The \a uMsg, \a wParam and \a lParam
+ parameters are set to the values passed in by Windows. */
+
+ WMNC_IDENT_EXIT,
+ /*!< Terminate a credentials acquisition dialog. Sent just before
+ the dialog is terminated. */
+};
+
+/*! \name Standard credtext link IDs
+@{*/
+
+/*! \brief Switch the panel
+
+ The \a id attribute of the link specifies the ordinal of the panel
+ to switch to.
+*/
+#define CTLINKID_SWITCH_PANEL L"SwitchPanel"
+
+/*@}*/
+
+/*forward dcl*/
+struct tag_khui_new_creds_by_type;
+typedef struct tag_khui_new_creds_by_type khui_new_creds_by_type;
+struct tag_khui_new_creds_prompt;
+typedef struct tag_khui_new_creds_prompt khui_new_creds_prompt;
+struct tag_khui_new_creds;
+typedef struct tag_khui_new_creds khui_new_creds;
+
+typedef LRESULT
+(KHMAPI *khui_ident_new_creds_cb)(khui_new_creds * nc,
+ UINT cmd,
+ HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam);
+
+/*! \brief New credentials acquisition blob
+
+ A pointer to an object of this type is passed in along with the
+ credentials acquisition messages.
+
+ \see \ref cred_acq for more information
+*/
+typedef struct tag_khui_new_creds {
+ khm_int32 magic; /*!< Internal use */
+
+ khm_int32 subtype; /*!< Subtype of the request that is
+ being handled through this object.
+ One of ::KMSG_CRED_NEW_CREDS,
+ ::KMSG_CRED_RENEW_CREDS or
+ ::KMSG_CRED_PASSWORD */
+
+ CRITICAL_SECTION cs; /*!< Internal use */
+
+ khm_boolean set_default; /*!< After a successfull credentials
+ acquisition, set the primary
+ identity as the default. */
+
+ khm_handle *identities; /*!< The list of identities associated
+ with this request. The first
+ identity in this list (\a
+ identities[0]) is the primary
+ identity. */
+
+ khm_size n_identities; /*!< Number of identities in the list
+ \a identities */
+
+ khm_size nc_identities; /*!< Internal use */
+
+ khui_action_context ctx; /*!< An action context specifying the
+ context in which the credentials
+ acquisition operation was
+ launced. */
+
+ khm_int32 mode; /*!< The mode of the user interface.
+ One of ::KHUI_NC_MODE_MINI or
+ ::KHUI_NC_MODE_EXPANDED. */
+
+ HWND hwnd; /*!< Handle to the new credentials
+ window. */
+
+ struct tag_khui_new_creds_by_type **types;
+ /*!< Internal use */
+ khm_handle *type_subs; /*!< Internal use */
+ khm_size n_types; /*!< Internal use */
+ khm_size nc_types; /*!< Internal use */
+
+ khm_int32 result; /*!< One of ::KHUI_NC_RESULT_CANCEL or
+ ::KHUI_NC_RESULT_PROCESS indicating
+ the result of the dialog with the
+ user */
+
+ khm_int32 response; /*!< Response. See individual message
+ documentation for info on what to do
+ with this field */
+
+ wchar_t *password; /*!< Not used. */
+
+ /* UI stuff */
+
+ wchar_t *banner; /*!< Internal use */
+ wchar_t *pname; /*!< Internal use */
+ khm_size n_prompts; /*!< Internal use */
+ khm_size nc_prompts; /*!< Internal use */
+ struct tag_khui_new_creds_prompt ** prompts; /*!< Internal use */
+
+ khui_ident_new_creds_cb ident_cb; /*!< Internal use */
+
+ wchar_t *window_title; /*!< Internal use */
+
+ LPARAM ident_aux; /*!< Auxilliary field which is
+ reserved for use by the identity
+ provider during the course of
+ conducting this dialog. */
+
+} khui_new_creds;
+
+#define KHUI_NC_MAGIC 0x84270427
+
+/*!\name Result values for khui_new_creds_t::result
+ @{*/
+#define KHUI_NC_RESULT_PROCESS 0
+#define KHUI_NC_RESULT_CANCEL 1
+/*@}*/
+
+/*!\name Mode values for khui_new_creds_t::mode
+ @{*/
+#define KHUI_NC_MODE_MINI 0
+#define KHUI_NC_MODE_EXPANDED 1
+/*@}*/
+
+/*!\name Response values for khui_new_creds_t::response
+ @{*/
+/*!\brief No known response */
+#define KHUI_NC_RESPONSE_NONE 0
+
+/*!\brief It is okay to exit the dialog now
+
+ This is the default, which is why it has a value of zero. In
+ order to prevent the dialog from exiting, set the
+ KHUI_NC_RESPONSE_NOEXIT response bit. */
+#define KHUI_NC_RESPONSE_EXIT 0
+
+/*!\brief It is NOT okay to exit the dialog now
+
+ Used to indicate that further user-interaction is necessary to
+ process the dialog. Usually this is accompanied by setting
+ necessary custom prompts and notifications so the user knows why
+ the dialog is prompting for more information.
+ */
+#define KHUI_NC_RESPONSE_NOEXIT 0x00000002
+
+/*!\brief The dialog was processed successfully
+
+ Since this is the default response, the value is zero. Use one of
+ KHUI_NC_RESPONSE_FAILED or KHUI_NC_RESPONSE_PENDING to indicate an
+ error or pending status.
+ */
+#define KHUI_NC_RESPONSE_SUCCESS 0
+
+/*!\brief The processing of the dialog failed
+
+ Self explanatory. More information about the failure should have
+ been reported using the khlog API, however, this response value
+ indicates to other credential types that depend on this credential
+ type that whatever it was that this credential type was supposed
+ to do didn't happen.
+*/
+#define KHUI_NC_RESPONSE_FAILED 0x00000008
+
+/*!\brief Further interaction required
+
+ Set along with KHUI_NC_RESPONSE_NOEXIT although it is not
+ required. Setting this bit will automatically add the
+ KHUI_NC_RESPONSE_NOEXIT.
+
+ If this bit is set, all dependent plugins will be set on hold
+ until another round of processing clears the pending bit.
+ */
+#define KHUI_NC_RESPONSE_PENDING 0x00000010
+
+/*! \brief Completed
+
+ This is automatically set if the plugin sets a response which does
+ not indicate either KHUI_NC_RESPONSE_NOEXIT or
+ KHUI_NC_RESPONSE_PENDING, which is considered to mean that the
+ plugin is completed processing.
+
+ This flag cannot be explicitly specified in a response.
+ */
+#define KHUI_NC_RESPONSE_COMPLETED 0x00000020
+
+/*! \brief Processing
+
+ This is an internal flag set while the credentials acquisition
+ process is executing.
+ */
+#define KHUI_NC_RESPONSE_PROCESSING 0x00010000
+
+#define KHUI_NCMASK_RESPONSE (KHUI_NC_RESPONSE_EXIT|KHUI_NC_RESPONSE_NOEXIT)
+#define KHUI_NCMASK_RESULT (KHUI_NC_RESPONSE_SUCCESS|KHUI_NC_RESPONSE_FAILED|KHUI_NC_RESPONSE_PENDING)
+/*@}*/
+
+/*!\brief Maximum number of dependencies for a credentials type */
+#define KHUI_MAX_TYPE_DEPS 8
+
+/*!\brief Maximum number of credential types for a new creds window */
+#define KHUI_MAX_NCTYPES 16
+
+/*!\brief Maximum number of characters in a password
+
+ Length includes the termininating NULL
+*/
+#define KHUI_MAXCCH_PASSWORD 512
+
+/*! \brief Maximum number of bytes in a password
+
+ Includes terminating NULL
+*/
+#define KHUI_MAXCB_PASSWORD (KHUI_MAXCCH_PASSWORD * sizeof(wchar_t))
+
+/*! \brief Maximum number of characters in a custom banner
+
+ Length includes terminating NULL
+*/
+#define KHUI_MAXCCH_BANNER 256
+
+
+/*! \brief Maximum number of bytes in a custom banner
+
+ Length includes terminating NULL
+*/
+#define KHUI_MAXCB_BANNER (KHUI_MAXCCH_BANNER * sizeof(wchar_t))
+
+/*! \brief Maximum number of characters in a panel name
+
+ Length includes terminating NULL
+*/
+#define KHUI_MAXCCH_PNAME 256
+
+/*! \brief Maximum number of bytes in a panel name
+
+ Length includes terminating NULL
+*/
+#define KHUI_MAXCB_PNAME (KHUI_MAXCCH_PNAME * sizeof(wchar_t))
+
+/*! \brief A descriptor of a panel in the new credentials acquisition tab
+
+ When processing certain credentials messages such as
+ ::KMSG_CRED_PASSWORD, ::KMSG_CRED_NEW_CREDS,
+ ::KMSG_CRED_RENEW_CREDS, a pointer to a ::khui_new_creds structure
+ will be passed in to the message handler. If the handler of the
+ message needs to add one or more credentials types as participants
+ of the operation, the handler will need to call khui_cw_add_type()
+ and specify a ::khui_new_creds_by_type structure.
+
+ Note that the memory address passed in to the call to
+ khui_cw_add_type() will not be copied. Therefore, the block of
+ memory should remain as-is for the lifetime of the
+ ::khui_new_creds structure or until it is removed with a call to
+ khui_cw_del_type().
+
+ Some of the credentials messages that require specifying a
+ ::khui_new_creds_by_type structure require providing a
+ user-interface. In these cases, the fields marked for providing a
+ UI may be required to hold valid values. If the message does not
+ require providing a UI, these fields will be ignored.
+*/
+typedef struct tag_khui_new_creds_by_type {
+ khui_new_creds * nc; /*!< Internal use. Do not set */
+ khm_int32 flags; /*!< Internal use. Do not set */
+
+ khm_int32 type; /*!< The identifier of the credentials
+ type. This is a credentials type
+ identifier allocated with a call to
+ kcdb_credtype_register(). */
+
+ khm_int32 type_deps[KHUI_MAX_TYPE_DEPS];
+ /*!< credentials types that this
+ credential type depends on. Each
+ element defines a credentials type
+ identifier that this type depends
+ on for this operation. The number
+ of valid values in this array
+ should be specified in the \a
+ n_type_deps field. */
+
+ khm_size n_type_deps; /*!< Number of dependencies listed
+ above. Should be between 0 and
+ ::KHUI_MAX_TYPE_DEPS. Specify 0 if
+ there are no dependencies. */
+
+ khm_size ordinal; /*!< The requested ordinal. The UI
+ would attempt to place this panel at
+ the reqested order in the list of
+ panels. Set to -1 if the order does
+ not matter. Once the dialog is
+ activated this field will be updated
+ to reflect the actual ordinal of the
+ panel. */
+
+ wchar_t *name; /*!< Name of the panel (localized,
+ optional). If NULL, the localized
+ name of the credentials type is
+ used. Only used if providing a
+ user-interface. */
+
+ HICON icon; /*!< Icon for the panel (optional).
+ Only used if providing a
+ user-interface. */
+
+ wchar_t *tooltip; /*!< Tooltip for the panel (localized,
+ optional). If NULL, no tooltip will
+ be assigned for the panel. Only
+ used if providing a
+ user-interface. */
+
+ HMODULE h_module; /*!< Handle to the module containing
+ the dialog resource. Only used if
+ providing a user-interface. */
+
+ LPWSTR dlg_template; /*!< The dialog resource. Only used
+ if providing a user-interface. */
+ DLGPROC dlg_proc; /*!< The dialog procedure. Only used
+ if providing a user-interface. */
+
+ HWND hwnd_panel; /*!< The dialog window. Once the
+ dialog panel is created, a handle to
+ the panel will be assigned here.
+ Note that the handle is assigned
+ after a successful call to
+ CreateDialogParam and hence would
+ not be available when handling the
+ WM_INITDIALOG message from the
+ dialog procedure. Only used of
+ providing a user-interface. */
+
+ HWND hwnd_tc; /*!< Internal use. Do not set */
+
+ wchar_t *credtext; /*!< A brief description of the
+ current state of this cred
+ type. (localized, optional). Only
+ used if providing a
+ user-interface. If this field is
+ non-NULL, then it should point to a
+ NULL terminated string that does not
+ exceed ::KHUI_MAXCCH_LONG_DESC
+ characters in length including the
+ terminating NULL.
+
+ \see \ref khui_htwnd for information
+ on how to format the string for this
+ field.
+ */
+
+ LPARAM aux; /*!< auxilliary field. For use by the
+ plug-in. */
+} khui_new_creds_by_type;
+
+/*!\name Flags for khui_new_creds_by_type
+
+ Note that KHUI_NC_RESPONSE_SUCCESS, KHUI_NC_RESPONSE_FAILED,
+ KHUI_NC_RESPONSE_PENDING are also stored in the flags.
+
+@{*/
+#define KHUI_NCT_FLAG_PROCESSED 1024
+#define KHUI_NCT_FLAG_DISABLED 2048
+/*@}*/
+
+/*! \brief Width of a new creds dialog panel in dialog units*/
+#define NCDLG_WIDTH 300
+/*! \brief Height of a new creds dialog panel in dialog units*/
+#define NCDLG_HEIGHT 166
+
+/*! \brief A custom prompt */
+typedef struct tag_khui_new_creds_prompt {
+ khm_size index; /*!< Set to the zero based index
+ of this prompt. */
+
+ khm_int32 type; /*!< one of KHUI_NCPROMPT_TYPE_* */
+ wchar_t * prompt; /*!< prompt string. Cannot exceed
+ KHUI_MAXCCH_PROMPT */
+ wchar_t * def; /*!< default value. Cannot exceed
+ KHUI_MAXCCH_PROMPT_VALUE */
+ wchar_t * value; /*!< On completion, this is set to the
+ value that the user entered. Will
+ not exceed
+ KHUI_MAXCCH_PROMPT_VALUE */
+
+ khm_int32 flags; /*!< Combination of
+ KHUI_NCPROMPT_FLAG_* */
+
+ HWND hwnd_static; /* internal use */
+ HWND hwnd_edit; /* internal use */
+} khui_new_creds_prompt;
+
+/*! \brief The prompt input is hidden
+
+ The input is hidden for prompts which accept passwords. The
+ control which represents the input will display an asterisk or a
+ small circle corresponding to each character typed in, but will
+ not show the actual character.
+ */
+#define KHUI_NCPROMPT_FLAG_HIDDEN 1
+
+/*! \brief Internal use */
+#define KHUI_NCPROMPT_FLAG_STOCK 2
+
+/*! \brief Maximum number of characters in a prompt
+
+ Refers to the prompt text that accompanies an input control. THe
+ length includes the terminating NULL.
+ */
+#define KHUI_MAXCCH_PROMPT 256
+
+/*! \brief Maximum number of bytes in a prompt
+
+ Refers to the prompt text that accompanies an input control. THe
+ length includes the terminating NULL.
+ */
+#define KHUI_MAXCB_PROMPT (KHUI_MAXCCH_PROMPT * sizeof(wchar_t))
+
+/*! \brief Maximum number of characters that can be entered in an input control
+
+ Refers to the input control of a prompt. The length includes the
+ terminating NULL.
+ */
+#define KHUI_MAXCCH_PROMPT_VALUE 256
+
+/*! \brief Maximum number of bytes that can be entered in an input control
+
+ Refers to the input control of a prompt. The length includes the
+ terminating NULL.
+ */
+#define KHUI_MAXCB_PROMPT_VALUE (KHUI_MAXCCH_PROMPT_VALUE * sizeof(wchar_t))
+
+/* from krb5.h. Redefining here because we don't want to depend on
+ krb5.h for all credential types */
+
+/*! \brief A password control */
+#define KHUI_NCPROMPT_TYPE_PASSWORD 1
+
+/*! \brief New password control
+
+ Used when changing the password
+ */
+#define KHUI_NCPROMPT_TYPE_NEW_PASSWORD 2
+
+/*! \brief New password again control
+
+ Used when changing the password
+ */
+#define KHUI_NCPROMPT_TYPE_NEW_PASSWORD_AGAIN 3
+
+/*! \brief Preauthentication (reserved) */
+#define KHUI_NCPROMPT_TYPE_PREAUTH 4
+
+/*! \brief Control sizes */
+typedef enum tag_khui_control_size {
+ KHUI_CTRLSIZE_SMALL,
+ /*!< A small control fits in about 1/5 the width of the new
+ credentials panel */
+ KHUI_CTRLSIZE_HALF,
+ /*!< Half size controls fit in 1/2 the width of the new
+ credentials panel */
+ KHUI_CTRLSIZE_FULL,
+ /*!< Takes up the whole width of the crednetials panel */
+} khui_control_size;
+
+/*! \brief Internal use */
+typedef struct tag_khui_control_row {
+ HWND label;
+ HWND input;
+ khui_control_size size;
+} khui_control_row;
+
+/*! \brief Create a ::khui_new_creds object
+
+ Creates and initializes a ::khui_new_creds object. The created
+ object must be destroyed using the khui_cw_destroy_cred_blob()
+ function.
+
+ \note Plugins should not call this function directly. The
+ necessary ::khui_new_creds objects will be created by
+ NetIDMgr.
+
+ \see khui_cw_destroy_cred_blob()
+ */
+KHMEXP khm_int32 KHMAPI
+khui_cw_create_cred_blob(khui_new_creds ** c);
+
+/*! \brief Destroy a ::khui_new_creds object
+
+ Destroys a ::khui_new_creds object that was fomerly created using
+ a call to khui_cw_create_cred_blob().
+
+ \note Plugins should not call this function directly. The
+ necessary ::khui_new_creds objects will be created by
+ NetIDMgr.
+
+ \see khui_cw_create_cred_blob()
+*/
+KHMEXP khm_int32 KHMAPI
+khui_cw_destroy_cred_blob(khui_new_creds *c);
+
+/*! \brief Lock the new_creds object
+
+ When a plugin is accessing the fields of a ::khui_new_creds
+ object, it must first obtain a lock on the object so that other
+ threads will not modify the fields at the same time. Locking the
+ object ensures that the fields of the object will be consistent.
+
+ Use khui_cw_unlock_nc() to undo the lock obtained through a call
+ to khui_cw_lock_nc().
+
+ It is not necessary to lock a new credentials object when
+ modifying it using the NetIDMgr API.
+ */
+KHMEXP khm_int32 KHMAPI
+khui_cw_lock_nc(khui_new_creds * c);
+
+/*! \brief Unlock a new_creds object
+
+ \see khui_cw_lock_nc()
+ */
+KHMEXP khm_int32 KHMAPI
+khui_cw_unlock_nc(khui_new_creds * c);
+
+/*! \brief Add a new panel to a new credentials acquisition window
+
+ See the description of ::khui_new_cred_panel for information on
+ how to populate it to describe a credentials type panel.
+
+ Note that the structure pointed to by \a t is added by reference.
+ The memory pointed to by \a t is not copied. Hence, the block of
+ memory and any other blocks pointed to by the
+ ::khui_new_creds_by_type structure located there should remain
+ intact for the lifetime of the ::khui_new_creds structure pointed
+ to by \a c or until the credentials type panel is removed from the
+ ::khui_new_creds structure with a call to khui_cw_del_type().
+
+ Generally, a plug-in that calls this function should allocate a
+ block of memory to contain the ::khui_new_creds_by_type structure,
+ fill it in and then pass in the address in a call to
+ khui_cw_add_type() while handling a ::KMSG_CRED_PASSWORD,
+ ::KMSG_CRED_NEW_CREDS or ::KMSG_CRED_RENEW_CREDS message. Then
+ the plug-in should remove the reference with a call to
+ khui_cw_del_type() while processing ::KMSG_CRED_END.
+
+ \see khui_cw_del_type()
+ \see \ref cred_acq_panel_spec
+ \see ::khui_new_cred_panel
+ \see ::khui_new_creds
+*/
+KHMEXP khm_int32 KHMAPI
+khui_cw_add_type(khui_new_creds * c,
+ khui_new_creds_by_type * t);
+
+/*! \brief Remove a panel from a new credentials acquisition window
+
+ \see khui_cw_add_type()
+ */
+KHMEXP khm_int32 KHMAPI
+khui_cw_del_type(khui_new_creds * c,
+ khm_int32 type);
+
+/*! \brief Find the panel belonging to a particular credentials type
+
+ This panel would have been added to the new credentials window
+ using khui_cw_add_type().
+
+ \see khui_cw_add_type()
+ */
+KHMEXP khm_int32 KHMAPI
+khui_cw_find_type(khui_new_creds * c,
+ khm_int32 type,
+ khui_new_creds_by_type **t);
+
+/*! \brief Enable/disable a particular credentials type
+
+ Enables or disables the panel associated with a particular
+ credentials type. Does not preclude the credentials type from
+ participating in the new credentials acquisition. However, the
+ user will be prevented from interacting with the specific panel.
+ */
+KHMEXP khm_int32 KHMAPI
+khui_cw_enable_type(khui_new_creds * c,
+ khm_int32 type,
+ khm_boolean enable);
+
+/*! \brief Set the primary identity in a new credentials acuisition
+
+ The primary identity dictates many of the defaults and the
+ semantics associated with the credentials acquision process.
+ Setting the primary identity also triggers the
+ ::WMNC_IDENTITY_CHANGE notification which will be sent to all the
+ credentials type panels.
+
+ Has no effect if the primary identity is already the same as the
+ one specified in \a id. Specify NULL for \a id if the current
+ primary identity is to be cleared.
+
+ If the primary identity is changed, then all the additional
+ identities associated with the new credentials acquisition dialog
+ will also be discarded.
+ */
+KHMEXP khm_int32 KHMAPI
+khui_cw_set_primary_id(khui_new_creds * c,
+ khm_handle id);
+
+/*! \brief Add an additional identity to the new credentials acquisition
+
+ Individual plugins are free to decide how to handle additional
+ identities. Generally, they would attempt to obtain credentials
+ for the primary and additional identities, but would not consider
+ it an error if an additional identity failed to obtain
+ credentials.
+
+ Calling this function with \a id of NULL does nothing.
+*/
+KHMEXP khm_int32 KHMAPI
+khui_cw_add_identity(khui_new_creds * c,
+ khm_handle id);
+
+/*! \brief Clear all custom prompts
+
+ Removes all the custom prompts from the new credentials dialog.
+ */
+KHMEXP khm_int32 KHMAPI
+khui_cw_clear_prompts(khui_new_creds * c);
+
+/*! \brief Synchronize custom prompt values
+
+ It is important to synchronize the values before accessing their
+ values. The controls associated with custom prompts update the
+ values in the ::khui_new_creds object periodically. However, the
+ values may lose sync intermittently.
+ */
+KHMEXP khm_int32 KHMAPI
+khui_cw_sync_prompt_values(khui_new_creds * c);
+
+/*! \brief Begin custom prompting
+
+ Begins the process of defining custom prompts. Implicity removes
+ all the custom prompts that are currently being displayed. The \a
+ banner and \a name will be displayed in separate controls above
+ the set of new custom prompts.
+
+ The controls associated with the prompts will not actually be
+ created until all the prompts have been added using
+ khui_cw_add_prompt(). The number of promtps that can be added
+ will be exactly \a n_prompts.
+ */
+KHMEXP khm_int32 KHMAPI
+khui_cw_begin_custom_prompts(khui_new_creds * c,
+ khm_size n_prompts,
+ wchar_t * banner,
+ wchar_t * name);
+
+/*! \brief Add a custom prompt
+
+ After khui_cw_begin_custom_prompts() is called, the plugin should
+ call khui_cw_add_prompt() to add the actual prompts. The number
+ of prompts that can be added is the \a n_prompts value specified
+ in the earlier call to \a khui_cw_begin_custom_prompts().
+
+ Once \a n_prompts prompts have been added, the new prompts will
+ automatically be created and shown in the user interface.
+ However, if less than that prompts are added, nothing is displayed
+ to the user.
+
+ \param[in] c Pointer to ::khui_new_creds structure
+
+ \param[in] type Type of prompt. One of
+ ::KHUI_NCPROMPT_TYPE_PREAUTH, ::KHUI_NCPROMPT_TYPE_PASSWORD,
+ ::KHUI_NCPROMPT_TYPE_NEW_PASSWORD,
+ ::KHUI_NCPROMPT_TYPE_NEW_PASSWORD_AGAIN
+
+ \param[in] prompt Text of the prompt. Constrained by
+ ::KHUI_MAXCCH_PROMPT. (Localized, required)
+
+ \param[in] def Default value. (optional). Constrained by
+ ::KHUI_MAXCCH_PROMPT_VALUE. Set to NULL if not provided.
+
+ \param[in] flags Flags. Combination of
+ ::KHUI_NCPROMPT_FLAG_HIDDEN
+ */
+KHMEXP khm_int32 KHMAPI
+khui_cw_add_prompt(khui_new_creds * c,
+ khm_int32 type,
+ wchar_t * prompt,
+ wchar_t * def,
+ khm_int32 flags);
+
+/*! \brief Retrieve a custom prompt
+
+ Retrieves an individual prompt. The \a idx parameter is a
+ zero-based index of the prompt to retrieve. The ordering is the
+ same as the order in which khui_cw_add_prompt() was called.
+ */
+KHMEXP khm_int32 KHMAPI
+khui_cw_get_prompt(khui_new_creds * c,
+ khm_size idx,
+ khui_new_creds_prompt ** prompt);
+
+/*! \brief Get the number of custom prompts
+
+ Retrieves the number of custom prompts currently displayed. If
+ this function is called between calling
+ khui_cw_begin_custom_prompts() and adding all the prompts, the
+ number returned will be the number of prompts that is expected to
+ be registered (i.e. the \a n_prompts parameter passed to
+ khui_cw_begin_custom_prompts()).
+ */
+KHMEXP khm_int32 KHMAPI
+khui_cw_get_prompt_count(khui_new_creds * c,
+ khm_size * np);
+
+
+/*! \brief Get the value of a custom prompt
+
+ Retrieve the value of a specific prompt. The value is the string
+ that was typed into the input control associated with a custom
+ prompt. The \a idx parameter is the zero-based index of the
+ prompt from which to retrieve the value from. The ordering is the
+ same as the order in which khui_cw_add_prompt() was called.
+
+ It is important to call khui_cw_sync_prompt_values() before
+ starting to call khui_cw_get_prompt_value() so that the values
+ returned are up-to-date.
+ */
+KHMEXP khm_int32 KHMAPI
+khui_cw_get_prompt_value(khui_new_creds * c,
+ khm_size idx,
+ wchar_t * buf,
+ khm_size *cbbuf);
+
+/*! \brief Set the response for a plugin
+
+ When handling ::KMSG_CRED_DIALOG_PROCESS from within the plugin
+ thread, it is important to set the response by calling this
+ function. The response can be used to signal whether the plugin
+ successfully obtained credentials or whether further interaction
+ is required, or the credentials acquisition failed.
+
+ The response is a combination of :
+ - ::KHUI_NC_RESPONSE_PENDING
+ - ::KHUI_NC_RESPONSE_FAILED
+ - ::KHUI_NC_RESPONSE_PENDING
+ - ::KHUI_NC_RESPONSE_SUCCESS
+ - ::KHUI_NC_RESPONSE_NOEXIT
+ - ::KHUI_NC_RESPONSE_EXIT
+ */
+KHMEXP khm_int32 KHMAPI
+khui_cw_set_response(khui_new_creds * c,
+ khm_int32 type,
+ khm_int32 response);
+
+/*! \brief Check whether a specified credential type panel succeeded
+
+ This is called during the processing of ::KMSG_CRED_DIALOG_PROCESS
+ to determine whether a specified credential type succeeded in
+ obtaining credentials. The credential type that is being queried
+ should have also been listed as a dependency when adding the
+ current credentials type, otherwise the type queried may not have
+ been invoked yet.
+
+ \return TRUE iff the queried type has reported that it successfully
+ completed the credentials acquision operation.
+ */
+KHMEXP khm_boolean KHMAPI
+khui_cw_type_succeeded(khui_new_creds * c,
+ khm_int32 type);
+
+/*! \brief Add a row of controls to the identity specifier area
+
+ Only for use by identity provider callbacks that wish to add an
+ identity selector control. A row of controls consist of a label
+ control and some input control.
+
+ When the ::WMNC_IDENT_INIT message is sent to the identity
+ provider, it receives a handle to the dialog panel in the \a
+ lParam parameter which should be the parent window of both the
+ windows specified here. The control ID for any controls created
+ must fall within the ::KHUI_CW_ID_MIN and ::KHUI_CW_ID_MAX range.
+
+ Both controls will be resized to fit in the row.
+
+ If \a long_label is TRUE then the size of the label will be larger
+ than normal and will accomodate more text.
+ */
+KHMEXP khm_int32 KHMAPI
+khui_cw_add_control_row(khui_new_creds * c,
+ HWND label,
+ HWND input,
+ khui_control_size size);
+
+/*!@}*/ /* Credentials acquisition */
+/*!@}*/
+
+#endif
diff --git a/src/windows/identity/uilib/khprops.h b/src/windows/identity/uilib/khprops.h
index c0977b80cb..a00c65f7fc 100644
--- a/src/windows/identity/uilib/khprops.h
+++ b/src/windows/identity/uilib/khprops.h
@@ -1,209 +1,209 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#ifndef __KHIMAIRA_KHPROPS_H
-#define __KHIMAIRA_KHPROPS_H
-
-#include<prsht.h>
-
-/*********************************************************************
- Property sheets
-**********************************************************************/
-
-/*! \addtogroup khui
-
-@{*/
-
-/*!\defgroup khui_pp Property sheets
-@{*/
-
-/* forward dcl */
-struct tag_khui_property_page;
-
-/*! \brief A property sheet
- */
-typedef struct tag_khui_property_sheet {
- PROPSHEETHEADER header; /*!< property sheet header */
- khm_int32 status; /*!< status of property sheet. One of
- ::KHUI_PS_STATUS_NONE,
- ::KHUI_PS_STATUS_RUNNING or
- ::KHUI_PS_STATUS_DONE */
-
- HWND hwnd; /*!< handle to the property sheet window.
- Only valid when \a status is NOT
- ::KHUI_PS_STATUS_NONE */
-
- HWND hwnd_page; /*!< handle to the current page in the
- property sheet. Only valid when \a
- status is ::KHUI_PS_STATUS_RUNNING */
-
- khui_action_context ctx; /*!< Context for the property sheet. See
- documentation for
- ::khui_action_context */
-
- khm_handle identity; /*!< Handle to the associated identity,
- if applicable */
- khm_int32 credtype; /*!< Type ID of the credentials type, if
- applicable */
- khm_handle cred; /*!< Handle to the associated credential,
- if applicable */
-
- khm_int32 n_pages; /*!< Number of property pages.
- Upperbound of ::KHUI_PS_MAX_PSP */
-
- QDCL(struct tag_khui_property_page);
-} khui_property_sheet;
-
-/*! \brief The property sheet hasn't been created yet */
-#define KHUI_PS_STATUS_NONE 0
-
-/*! \brief The property sheet is visible and running */
-#define KHUI_PS_STATUS_RUNNING 1
-
-/*! \brief The property sheet has completed running.
-
- At this point, it is safe to call khui_ps_destroy_sheet() to
- destroy the property sheet.
-*/
-#define KHUI_PS_STATUS_DONE 2
-
-/*! \brief The property sheet is in the process of being destroyed
- */
-#define KHUI_PS_STATUS_DESTROY 3
-
-/*! \brief Maximum number of property sheet pages in a property sheet */
-#define KHUI_PS_MAX_PSP 16
-
-
-/*! \brief A property sheet page
- */
-typedef struct tag_khui_property_page {
- HPROPSHEETPAGE h_page;
- LPPROPSHEETPAGE p_page;
- HWND hwnd;
- khm_int32 credtype;
- khm_int32 ordinal;
-
- LDCL(struct tag_khui_property_page);
-} khui_property_page;
-
-/*! \brief Special pseudo credtype for identity page
- */
-#define KHUI_PPCT_IDENTITY (-8)
-
-/*! \brief Special pseudo credtype for credential page
- */
-#define KHUI_PPCT_CREDENTIAL (-9)
-
-/*! \brief Create a property sheet
-
- \note Only called by the NetIDMgr application.
- */
-KHMEXP khm_int32 KHMAPI
-khui_ps_create_sheet(khui_property_sheet ** sheet);
-
-/*! \brief Add a page to a property sheet
-
- Called by a plugin or the NetIDMgr application to add a page to a
- property sheet.
-
- Pages can only be added before the property sheet is made visible
- to the user.
-
- \param[in] sheet The property sheet to add the page to
-
- \param[in] credtype The credentials type ID of the owner of the
- property page. This should be set to ::KCDB_CREDTYPE_INVALID
- if the type is not relevant.
-
- \param[in] ordinal Requested ordinal. A positive integer which is
- used to order the pages in a property sheet. The pages are
- ordered based on ordinal first and then alphabetically by
- credentials type name. If the type is unavailable, then the
- ordering is undefined. Ordinals for credential type property
- pages can be in the range from 0 to 127. Ordinals 128 and
- above are reserved. Passing in 0 will work for credentials
- providers unless they provide more than one property page per
- credential, in which case the ordinal should be used to
- enforce an order.
-
- \param[in] ppage Pointer to structure that will be passed to
- CreatePropertySheetPage() to create the property page. The
- structure is not managed by NetIDMgr at all, and must exist
- until the status of the property sheet changes to
- ::KHUI_PS_STATUS_RUNNING. The same pointer will be found in
- the \a p_page member of the ::khui_property_page structure.
-
- \param[out] page A pointer will be returned here that will point
- to the newly created khui_property_page structure. Specify
- NULL if this value is not required. You can use
- khui_ps_find_page() to retrieve a pointer to the structure
- later.
- */
-KHMEXP khm_int32 KHMAPI
-khui_ps_add_page(khui_property_sheet * sheet,
- khm_int32 credtype,
- khm_int32 ordinal,
- LPPROPSHEETPAGE ppage,
- khui_property_page ** page);
-
-/*! \brief Retrieve a property page structure from a property sheet
- */
-KHMEXP khm_int32 KHMAPI
-khui_ps_find_page(khui_property_sheet * sheet,
- khm_int32 credtype,
- khui_property_page ** page);
-
-/*! \brief Display the property sheet
-
- \note Only called by the NetIDMgr application
- */
-KHMEXP HWND KHMAPI
-khui_ps_show_sheet(HWND parent,
- khui_property_sheet * sheet);
-
-/*! \brief Check if the given message belongs to the property sheet
-
- \note Only called by the NetIDMgr application
- */
-KHMEXP LRESULT KHMAPI
-khui_ps_check_message(khui_property_sheet * sheet,
- PMSG msg);
-
-/*! \brief Destroy a property sheet and all associated data structures.
-
- \note Only called by the NetIDMgr application.
-*/
-KHMEXP khm_int32 KHMAPI
-khui_ps_destroy_sheet(khui_property_sheet * sheet);
-
-KHMEXP khm_int32 KHMAPI
-khui_property_wnd_set_record(HWND hwnd_pwnd, khm_handle record);
-
-/*!@}*/
-/*!@}*/
-
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __KHIMAIRA_KHPROPS_H
+#define __KHIMAIRA_KHPROPS_H
+
+#include<prsht.h>
+
+/*********************************************************************
+ Property sheets
+**********************************************************************/
+
+/*! \addtogroup khui
+
+@{*/
+
+/*!\defgroup khui_pp Property sheets
+@{*/
+
+/* forward dcl */
+struct tag_khui_property_page;
+
+/*! \brief A property sheet
+ */
+typedef struct tag_khui_property_sheet {
+ PROPSHEETHEADER header; /*!< property sheet header */
+ khm_int32 status; /*!< status of property sheet. One of
+ ::KHUI_PS_STATUS_NONE,
+ ::KHUI_PS_STATUS_RUNNING or
+ ::KHUI_PS_STATUS_DONE */
+
+ HWND hwnd; /*!< handle to the property sheet window.
+ Only valid when \a status is NOT
+ ::KHUI_PS_STATUS_NONE */
+
+ HWND hwnd_page; /*!< handle to the current page in the
+ property sheet. Only valid when \a
+ status is ::KHUI_PS_STATUS_RUNNING */
+
+ khui_action_context ctx; /*!< Context for the property sheet. See
+ documentation for
+ ::khui_action_context */
+
+ khm_handle identity; /*!< Handle to the associated identity,
+ if applicable */
+ khm_int32 credtype; /*!< Type ID of the credentials type, if
+ applicable */
+ khm_handle cred; /*!< Handle to the associated credential,
+ if applicable */
+
+ khm_int32 n_pages; /*!< Number of property pages.
+ Upperbound of ::KHUI_PS_MAX_PSP */
+
+ QDCL(struct tag_khui_property_page);
+} khui_property_sheet;
+
+/*! \brief The property sheet hasn't been created yet */
+#define KHUI_PS_STATUS_NONE 0
+
+/*! \brief The property sheet is visible and running */
+#define KHUI_PS_STATUS_RUNNING 1
+
+/*! \brief The property sheet has completed running.
+
+ At this point, it is safe to call khui_ps_destroy_sheet() to
+ destroy the property sheet.
+*/
+#define KHUI_PS_STATUS_DONE 2
+
+/*! \brief The property sheet is in the process of being destroyed
+ */
+#define KHUI_PS_STATUS_DESTROY 3
+
+/*! \brief Maximum number of property sheet pages in a property sheet */
+#define KHUI_PS_MAX_PSP 16
+
+
+/*! \brief A property sheet page
+ */
+typedef struct tag_khui_property_page {
+ HPROPSHEETPAGE h_page;
+ LPPROPSHEETPAGE p_page;
+ HWND hwnd;
+ khm_int32 credtype;
+ khm_int32 ordinal;
+
+ LDCL(struct tag_khui_property_page);
+} khui_property_page;
+
+/*! \brief Special pseudo credtype for identity page
+ */
+#define KHUI_PPCT_IDENTITY (-8)
+
+/*! \brief Special pseudo credtype for credential page
+ */
+#define KHUI_PPCT_CREDENTIAL (-9)
+
+/*! \brief Create a property sheet
+
+ \note Only called by the NetIDMgr application.
+ */
+KHMEXP khm_int32 KHMAPI
+khui_ps_create_sheet(khui_property_sheet ** sheet);
+
+/*! \brief Add a page to a property sheet
+
+ Called by a plugin or the NetIDMgr application to add a page to a
+ property sheet.
+
+ Pages can only be added before the property sheet is made visible
+ to the user.
+
+ \param[in] sheet The property sheet to add the page to
+
+ \param[in] credtype The credentials type ID of the owner of the
+ property page. This should be set to ::KCDB_CREDTYPE_INVALID
+ if the type is not relevant.
+
+ \param[in] ordinal Requested ordinal. A positive integer which is
+ used to order the pages in a property sheet. The pages are
+ ordered based on ordinal first and then alphabetically by
+ credentials type name. If the type is unavailable, then the
+ ordering is undefined. Ordinals for credential type property
+ pages can be in the range from 0 to 127. Ordinals 128 and
+ above are reserved. Passing in 0 will work for credentials
+ providers unless they provide more than one property page per
+ credential, in which case the ordinal should be used to
+ enforce an order.
+
+ \param[in] ppage Pointer to structure that will be passed to
+ CreatePropertySheetPage() to create the property page. The
+ structure is not managed by NetIDMgr at all, and must exist
+ until the status of the property sheet changes to
+ ::KHUI_PS_STATUS_RUNNING. The same pointer will be found in
+ the \a p_page member of the ::khui_property_page structure.
+
+ \param[out] page A pointer will be returned here that will point
+ to the newly created khui_property_page structure. Specify
+ NULL if this value is not required. You can use
+ khui_ps_find_page() to retrieve a pointer to the structure
+ later.
+ */
+KHMEXP khm_int32 KHMAPI
+khui_ps_add_page(khui_property_sheet * sheet,
+ khm_int32 credtype,
+ khm_int32 ordinal,
+ LPPROPSHEETPAGE ppage,
+ khui_property_page ** page);
+
+/*! \brief Retrieve a property page structure from a property sheet
+ */
+KHMEXP khm_int32 KHMAPI
+khui_ps_find_page(khui_property_sheet * sheet,
+ khm_int32 credtype,
+ khui_property_page ** page);
+
+/*! \brief Display the property sheet
+
+ \note Only called by the NetIDMgr application
+ */
+KHMEXP HWND KHMAPI
+khui_ps_show_sheet(HWND parent,
+ khui_property_sheet * sheet);
+
+/*! \brief Check if the given message belongs to the property sheet
+
+ \note Only called by the NetIDMgr application
+ */
+KHMEXP LRESULT KHMAPI
+khui_ps_check_message(khui_property_sheet * sheet,
+ PMSG msg);
+
+/*! \brief Destroy a property sheet and all associated data structures.
+
+ \note Only called by the NetIDMgr application.
+*/
+KHMEXP khm_int32 KHMAPI
+khui_ps_destroy_sheet(khui_property_sheet * sheet);
+
+KHMEXP khm_int32 KHMAPI
+khui_property_wnd_set_record(HWND hwnd_pwnd, khm_handle record);
+
+/*!@}*/
+/*!@}*/
+
+#endif
diff --git a/src/windows/identity/uilib/khremote.h b/src/windows/identity/uilib/khremote.h
index 5de877da61..3a79d65552 100644
--- a/src/windows/identity/uilib/khremote.h
+++ b/src/windows/identity/uilib/khremote.h
@@ -1,84 +1,84 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#ifndef __KHIMAIRA_REMOTE_H
-#define __KHIMAIRA_REMOTE_H
-
-/*! \addtogroup khui
- @{*/
-/*! \defgroup khui_remote Connecting to NetIDMgr from another process
- @{*/
-
-/* Leash compatibility */
-#define ID_OBTAIN_TGT_WITH_LPARAM 32810
-
-#define KHUI_REQDAEMONWND_CLASS L"IDMgrRequestDaemonCls"
-#define KHUI_REQDAEMONWND_NAME L"IDMgrRequestDaemon"
-
-#define KHUI_REQD_MAPPING_FORMAT L"Local\\NetIDMgr_DlgInfo_%lu"
-
-#define NETID_USERNAME_SZ 128
-#define NETID_REALM_SZ 192
-#define NETID_TITLE_SZ 256
-#define NETID_CCACHE_NAME_SZ 264
-
-#define NETID_DLGTYPE_TGT 0
-#define NETID_DLGTYPE_CHPASSWD 1
-typedef struct {
- DWORD size;
- DWORD dlgtype;
- // Tells whether dialog box is in change pwd mode or init ticket mode
- struct {
- WCHAR title[NETID_TITLE_SZ];
- WCHAR username[NETID_USERNAME_SZ];
- WCHAR realm[NETID_REALM_SZ];
- WCHAR ccache[NETID_CCACHE_NAME_SZ];
- DWORD use_defaults;
- DWORD forwardable;
- DWORD noaddresses;
- DWORD lifetime;
- DWORD renew_till;
- DWORD proxiable;
- DWORD publicip;
- DWORD must_use_specified_principal;
- } in;
- struct {
- WCHAR username[NETID_USERNAME_SZ];
- WCHAR realm[NETID_REALM_SZ];
- WCHAR ccache[NETID_CCACHE_NAME_SZ];
- } out;
- // Version 1 of this structure ends here
-} NETID_DLGINFO, *LPNETID_DLGINFO;
-
-#define NETID_DLGINFO_V1_SZ (10 * sizeof(DWORD) \
- + sizeof(WCHAR) * (NETID_TITLE_SZ + \
- 2 * NETID_USERNAME_SZ + 2 * NETID_REALM_SZ + \
- 2 * NETID_CCACHE_NAME_SZ))
-
-/*!@} */
-/*!@} */
-
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __KHIMAIRA_REMOTE_H
+#define __KHIMAIRA_REMOTE_H
+
+/*! \addtogroup khui
+ @{*/
+/*! \defgroup khui_remote Connecting to NetIDMgr from another process
+ @{*/
+
+/* Leash compatibility */
+#define ID_OBTAIN_TGT_WITH_LPARAM 32810
+
+#define KHUI_REQDAEMONWND_CLASS L"IDMgrRequestDaemonCls"
+#define KHUI_REQDAEMONWND_NAME L"IDMgrRequestDaemon"
+
+#define KHUI_REQD_MAPPING_FORMAT L"Local\\NetIDMgr_DlgInfo_%lu"
+
+#define NETID_USERNAME_SZ 128
+#define NETID_REALM_SZ 192
+#define NETID_TITLE_SZ 256
+#define NETID_CCACHE_NAME_SZ 264
+
+#define NETID_DLGTYPE_TGT 0
+#define NETID_DLGTYPE_CHPASSWD 1
+typedef struct {
+ DWORD size;
+ DWORD dlgtype;
+ // Tells whether dialog box is in change pwd mode or init ticket mode
+ struct {
+ WCHAR title[NETID_TITLE_SZ];
+ WCHAR username[NETID_USERNAME_SZ];
+ WCHAR realm[NETID_REALM_SZ];
+ WCHAR ccache[NETID_CCACHE_NAME_SZ];
+ DWORD use_defaults;
+ DWORD forwardable;
+ DWORD noaddresses;
+ DWORD lifetime;
+ DWORD renew_till;
+ DWORD proxiable;
+ DWORD publicip;
+ DWORD must_use_specified_principal;
+ } in;
+ struct {
+ WCHAR username[NETID_USERNAME_SZ];
+ WCHAR realm[NETID_REALM_SZ];
+ WCHAR ccache[NETID_CCACHE_NAME_SZ];
+ } out;
+ // Version 1 of this structure ends here
+} NETID_DLGINFO, *LPNETID_DLGINFO;
+
+#define NETID_DLGINFO_V1_SZ (10 * sizeof(DWORD) \
+ + sizeof(WCHAR) * (NETID_TITLE_SZ + \
+ 2 * NETID_USERNAME_SZ + 2 * NETID_REALM_SZ + \
+ 2 * NETID_CCACHE_NAME_SZ))
+
+/*!@} */
+/*!@} */
+
+#endif
diff --git a/src/windows/identity/uilib/khrescache.h b/src/windows/identity/uilib/khrescache.h
index eeb4f6585c..63baa1f722 100644
--- a/src/windows/identity/uilib/khrescache.h
+++ b/src/windows/identity/uilib/khrescache.h
@@ -1,100 +1,100 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#ifndef __KHIMAIRA_RESCACHE_H
-#define __KHIMAIRA_RESCACHE_H
-
-#include<khdefs.h>
-
-KHMEXP void KHMAPI
-khui_init_rescache(void);
-
-KHMEXP void KHMAPI
-khui_exit_rescache(void);
-
-KHMEXP void KHMAPI
-khui_cache_bitmap(UINT id, HBITMAP hbm);
-
-KHMEXP HBITMAP KHMAPI
-khui_get_cached_bitmap(UINT id);
-
-typedef struct khui_ilist_t {
- int cx;
- int cy;
- int n;
- int ng;
- int nused;
- HBITMAP img;
- HBITMAP mask;
- int *idlist;
-} khui_ilist;
-
-typedef struct khui_bitmap_t {
- HBITMAP hbmp;
- int cx;
- int cy;
-} khui_bitmap;
-
-KHMEXP void KHMAPI
-khui_bitmap_from_hbmp(khui_bitmap * kbm, HBITMAP hbm);
-
-KHMEXP void KHMAPI
-khui_delete_bitmap(khui_bitmap * kbm);
-
-KHMEXP void KHMAPI
-khui_draw_bitmap(HDC hdc, int x, int y, khui_bitmap * kbm);
-
-/* image lists */
-KHMEXP khui_ilist * KHMAPI
-khui_create_ilist(int cx, int cy, int n, int ng, int opt);
-
-KHMEXP BOOL KHMAPI
-khui_delete_ilist(khui_ilist * il);
-
-KHMEXP int KHMAPI
-khui_ilist_add_masked(khui_ilist * il, HBITMAP hbm, COLORREF cbkg);
-
-KHMEXP int KHMAPI
-khui_ilist_add_masked_id(khui_ilist *il, HBITMAP hbm,
- COLORREF cbkg, int id);
-
-KHMEXP int KHMAPI
-khui_ilist_lookup_id(khui_ilist *il, int id);
-
-KHMEXP void KHMAPI
-khui_ilist_draw(khui_ilist * il, int idx, HDC dc, int x, int y, int opt);
-
-KHMEXP void KHMAPI
-khui_ilist_draw_bg(khui_ilist * il, int idx, HDC dc, int x, int y,
- int opt, COLORREF bgcolor);
-
-#define khui_ilist_draw_id(il, id, dc, x, y, opt) \
- khui_ilist_draw((il),khui_ilist_lookup_id((il),(id)),(dc),(x),(y),(opt))
-
-#define KHUI_SMICON_CX 16
-#define KHUI_SMICON_CY 16
-
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __KHIMAIRA_RESCACHE_H
+#define __KHIMAIRA_RESCACHE_H
+
+#include<khdefs.h>
+
+KHMEXP void KHMAPI
+khui_init_rescache(void);
+
+KHMEXP void KHMAPI
+khui_exit_rescache(void);
+
+KHMEXP void KHMAPI
+khui_cache_bitmap(UINT id, HBITMAP hbm);
+
+KHMEXP HBITMAP KHMAPI
+khui_get_cached_bitmap(UINT id);
+
+typedef struct khui_ilist_t {
+ int cx;
+ int cy;
+ int n;
+ int ng;
+ int nused;
+ HBITMAP img;
+ HBITMAP mask;
+ int *idlist;
+} khui_ilist;
+
+typedef struct khui_bitmap_t {
+ HBITMAP hbmp;
+ int cx;
+ int cy;
+} khui_bitmap;
+
+KHMEXP void KHMAPI
+khui_bitmap_from_hbmp(khui_bitmap * kbm, HBITMAP hbm);
+
+KHMEXP void KHMAPI
+khui_delete_bitmap(khui_bitmap * kbm);
+
+KHMEXP void KHMAPI
+khui_draw_bitmap(HDC hdc, int x, int y, khui_bitmap * kbm);
+
+/* image lists */
+KHMEXP khui_ilist * KHMAPI
+khui_create_ilist(int cx, int cy, int n, int ng, int opt);
+
+KHMEXP BOOL KHMAPI
+khui_delete_ilist(khui_ilist * il);
+
+KHMEXP int KHMAPI
+khui_ilist_add_masked(khui_ilist * il, HBITMAP hbm, COLORREF cbkg);
+
+KHMEXP int KHMAPI
+khui_ilist_add_masked_id(khui_ilist *il, HBITMAP hbm,
+ COLORREF cbkg, int id);
+
+KHMEXP int KHMAPI
+khui_ilist_lookup_id(khui_ilist *il, int id);
+
+KHMEXP void KHMAPI
+khui_ilist_draw(khui_ilist * il, int idx, HDC dc, int x, int y, int opt);
+
+KHMEXP void KHMAPI
+khui_ilist_draw_bg(khui_ilist * il, int idx, HDC dc, int x, int y,
+ int opt, COLORREF bgcolor);
+
+#define khui_ilist_draw_id(il, id, dc, x, y, opt) \
+ khui_ilist_draw((il),khui_ilist_lookup_id((il),(id)),(dc),(x),(y),(opt))
+
+#define KHUI_SMICON_CX 16
+#define KHUI_SMICON_CY 16
+
+#endif
diff --git a/src/windows/identity/uilib/khtracker.h b/src/windows/identity/uilib/khtracker.h
index c12cd4fac6..38be29a134 100644
--- a/src/windows/identity/uilib/khtracker.h
+++ b/src/windows/identity/uilib/khtracker.h
@@ -1,114 +1,114 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#ifndef __KHIMAIRA_TRACKERWND_H
-#define __KHIMAIRA_TRACKERWND_H
-
-#include<time.h>
-
-/*! \addtogroup khui
-
-@{ */
-
-/*!\defgroup khui_trk Duration sliders
-
-The duration sliders in the UI are pseudo-log-scaled. This is based
-on the assumption that people don't really need 1 minute accuracy when
-setting a duration that's several hours long. As a result, it is
-easier to hone in on the duration that you want without having
-wizardly mouse maneuvering skillz.
-
-Following are the duration ranges and the granularity that is offered
-in each range:
-
-<table>
-<tr><td> Range </td><td> Increment</td></tr>
-<tr><td> 0..5m </td><td> 1 min </td></tr>
-<tr><td> 5m..1hr </td><td> 5 min </td></tr>
-<tr><td> 1hr..4hr </td><td> 15 min </td></tr>
-<tr><td> 4hr..10hr </td><td> 30 min </td></tr>
-<tr><td> 10hr..24hr</td><td> 1 hr </td></tr>
-<tr><td> 24hr..4d </td><td> 6 hr </td></tr>
-<tr><td> 4d.. </td><td> 1 day </td></tr>
-</table>
-
-We don't really adjust for durations over 4 days. The ranges we are
-concerned with don't get much larger.
-
-For the purpose of writing this piece of code, I have chosen the term
-"tick" to refer to a period of granularity. The number of periods of
-granularity (inclusive) within a certain duration interval is referred
-to as the number of ticks in the interval. For example, there are 4
-ticks between the interval of 3 minutes to 10 minutes. Each occuring
-at the start of 3min, 4, 5 and 10mins. And thusly the slider control
-will display 4 ticks if it is displaying the interval 3-10mins.
-
-@{*/
-
-/*! \brief Tracker data */
-typedef struct tag_khui_tracker {
- WNDPROC fn_edit;
- WNDPROC fn_tracker;
- HWND hw_slider;
- HWND hw_edit;
- int lbl_y;
- int lbl_lx;
- int lbl_rx;
- DWORD act_time;
-
- time_t current; /*!< Current selection */
- time_t min; /*!< Minimum (inclusive) */
- time_t max; /*!< Maximum (inclusive) */
-} khui_tracker;
-
-/*! \brief Install a tracker into an edit control
-
- Once installed, the edit control becomes a duration editor. The
- tracker data structure that is supplied should remain as is for
- the lifetime of the edit control.
-
- The tracker strucutre should have been initialized with a call to
- khui_tracker_initialize() and should have valid values in the \a
- min, \a max and \a current fields.
- */
-KHMEXP void KHMAPI
-khui_tracker_install(HWND hwnd_edit, khui_tracker * tc);
-
-KHMEXP void KHMAPI
-khui_tracker_reposition(khui_tracker * tc);
-
-KHMEXP void KHMAPI
-khui_tracker_initialize(khui_tracker * tc);
-
-KHMEXP void KHMAPI
-khui_tracker_refresh(khui_tracker * tc);
-
-KHMEXP void KHMAPI
-khui_tracker_kill_controls(khui_tracker * tc);
-/*!@}*/
-/*!@}*/
-
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __KHIMAIRA_TRACKERWND_H
+#define __KHIMAIRA_TRACKERWND_H
+
+#include<time.h>
+
+/*! \addtogroup khui
+
+@{ */
+
+/*!\defgroup khui_trk Duration sliders
+
+The duration sliders in the UI are pseudo-log-scaled. This is based
+on the assumption that people don't really need 1 minute accuracy when
+setting a duration that's several hours long. As a result, it is
+easier to hone in on the duration that you want without having
+wizardly mouse maneuvering skillz.
+
+Following are the duration ranges and the granularity that is offered
+in each range:
+
+<table>
+<tr><td> Range </td><td> Increment</td></tr>
+<tr><td> 0..5m </td><td> 1 min </td></tr>
+<tr><td> 5m..1hr </td><td> 5 min </td></tr>
+<tr><td> 1hr..4hr </td><td> 15 min </td></tr>
+<tr><td> 4hr..10hr </td><td> 30 min </td></tr>
+<tr><td> 10hr..24hr</td><td> 1 hr </td></tr>
+<tr><td> 24hr..4d </td><td> 6 hr </td></tr>
+<tr><td> 4d.. </td><td> 1 day </td></tr>
+</table>
+
+We don't really adjust for durations over 4 days. The ranges we are
+concerned with don't get much larger.
+
+For the purpose of writing this piece of code, I have chosen the term
+"tick" to refer to a period of granularity. The number of periods of
+granularity (inclusive) within a certain duration interval is referred
+to as the number of ticks in the interval. For example, there are 4
+ticks between the interval of 3 minutes to 10 minutes. Each occuring
+at the start of 3min, 4, 5 and 10mins. And thusly the slider control
+will display 4 ticks if it is displaying the interval 3-10mins.
+
+@{*/
+
+/*! \brief Tracker data */
+typedef struct tag_khui_tracker {
+ WNDPROC fn_edit;
+ WNDPROC fn_tracker;
+ HWND hw_slider;
+ HWND hw_edit;
+ int lbl_y;
+ int lbl_lx;
+ int lbl_rx;
+ DWORD act_time;
+
+ time_t current; /*!< Current selection */
+ time_t min; /*!< Minimum (inclusive) */
+ time_t max; /*!< Maximum (inclusive) */
+} khui_tracker;
+
+/*! \brief Install a tracker into an edit control
+
+ Once installed, the edit control becomes a duration editor. The
+ tracker data structure that is supplied should remain as is for
+ the lifetime of the edit control.
+
+ The tracker strucutre should have been initialized with a call to
+ khui_tracker_initialize() and should have valid values in the \a
+ min, \a max and \a current fields.
+ */
+KHMEXP void KHMAPI
+khui_tracker_install(HWND hwnd_edit, khui_tracker * tc);
+
+KHMEXP void KHMAPI
+khui_tracker_reposition(khui_tracker * tc);
+
+KHMEXP void KHMAPI
+khui_tracker_initialize(khui_tracker * tc);
+
+KHMEXP void KHMAPI
+khui_tracker_refresh(khui_tracker * tc);
+
+KHMEXP void KHMAPI
+khui_tracker_kill_controls(khui_tracker * tc);
+/*!@}*/
+/*!@}*/
+
+#endif
diff --git a/src/windows/identity/uilib/khuidefs.h b/src/windows/identity/uilib/khuidefs.h
index 9b3855614c..16c4474f7a 100644
--- a/src/windows/identity/uilib/khuidefs.h
+++ b/src/windows/identity/uilib/khuidefs.h
@@ -1,146 +1,146 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- * Copyright (c) 2007 Secure Endpoints Inc.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#ifndef __KHIMAIRA_KHUIDEFS_H
-#define __KHIMAIRA_KHUIDEFS_H
-
-#include<windows.h>
-#include<kmq.h>
-#include<kcreddb.h>
-#include<kherror.h>
-#include<kherr.h>
-#include<khmsgtypes.h>
-
-#include<khaction.h>
-#include<khactiondef.h>
-#include<khhtlink.h>
-#include<khnewcred.h>
-#include<khprops.h>
-#include<khalerts.h>
-#include<khconfigui.h>
-#include<khtracker.h>
-
-#ifdef NOEXPORT
-#include<khrescache.h>
-#endif
-
-#include<khremote.h>
-
-/*! \internal */
-KHMEXP void KHMAPI
-khm_version_init(void);
-
-/*! \defgroup khui User Interface
-
- Functions and data structures for interacting with the user
- interface.
-
-@{*/
-
-/*! \brief Get the version of the NetIDMgr library
-
- \param[out] libver Receives the version of the library.
-
- \param[out] apiver Receives the API version of the library.
- Optional. Set to NULL if this value is not required.
-
- \note When the NetIDMgr framework loads a plugin, it checks the
- version information of the plugin against the version of the
- library to determine if the plugin is compatible.
- */
-KHMEXP void KHMAPI
-khm_get_lib_version(khm_version * libver, khm_ui_4 * apiver);
-
-/*! \brief Return the version of Common Control library
-
- Can be used to check the version of the Windows Common Control
- library that is currently loaded. The return value of the
- function is the packed version value obatained by the macro :
-
- \code
- MAKELONG(vesion->dwMinorVersion, version->dwMajorVersion);
- \endcode
-
- The \a pdvi parameter is optional. Specify NULL if this is not
- required.
- */
-KHMEXP khm_ui_4 KHMAPI
-khm_get_commctl_version(khm_version * pdvi);
-
-/*! \brief UI callback function
-
- Used with khui_request_UI_callback().
-
- \see khui_request_UI_callback()
- */
-typedef khm_int32
-(KHMAPI *khm_ui_callback)(HWND hwnd_main_wnd, void * rock);
-
-/*! \brief Request a UI callback
-
- In general, plug-ins in Network Identity Manager run in their own
- thread and will not be able to interact with the user directly by
- creating windows of its own. There are exceptions to this, such
- as when the plug-in is responding to a new credentials request or
- if the plug-in provides configuration panels. However, if a
- plug-in needs to provide a user interface to the user outside of
- the provisions already provided by Network Identity Manager, it
- needs to do so from within the user interface thread.
-
- To do so, a plug-in would provide a callback function of the type
- ::khm_ui_callback to this function. The Network Identity Manager
- will then call the callback function from within the user
- interface thread. At this point, the callback function can create
- any windows it wishes to create and interact with the user
- directly.
-
- The callback function would be called synchronously.
- khui_request_UI_callback() will not return until the user
- interface processes the request and calls the callback function.
- The return code of khui_request_UI_callback() will be the return
- code of the callback.
-
- \param[in] cb The callback function which will be called from the
- user interface thread.
-
- \param[in] rock An arbitrary parameter which will be passed into
- the callback function.
-
- \return The return value of \a cb.
-
- \note When the plug-in creates any windows, it should specify the
- window handle provided via the \a hwnd_main_wnd parameter as
- the parent window.
-
- \see ::khm_ui_callback
- */
-KHMEXP khm_int32 KHMAPI
-khui_request_UI_callback(khm_ui_callback cb, void * rock);
-
-/*!@}*/
-
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ * Copyright (c) 2007 Secure Endpoints Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __KHIMAIRA_KHUIDEFS_H
+#define __KHIMAIRA_KHUIDEFS_H
+
+#include<windows.h>
+#include<kmq.h>
+#include<kcreddb.h>
+#include<kherror.h>
+#include<kherr.h>
+#include<khmsgtypes.h>
+
+#include<khaction.h>
+#include<khactiondef.h>
+#include<khhtlink.h>
+#include<khnewcred.h>
+#include<khprops.h>
+#include<khalerts.h>
+#include<khconfigui.h>
+#include<khtracker.h>
+
+#ifdef NOEXPORT
+#include<khrescache.h>
+#endif
+
+#include<khremote.h>
+
+/*! \internal */
+KHMEXP void KHMAPI
+khm_version_init(void);
+
+/*! \defgroup khui User Interface
+
+ Functions and data structures for interacting with the user
+ interface.
+
+@{*/
+
+/*! \brief Get the version of the NetIDMgr library
+
+ \param[out] libver Receives the version of the library.
+
+ \param[out] apiver Receives the API version of the library.
+ Optional. Set to NULL if this value is not required.
+
+ \note When the NetIDMgr framework loads a plugin, it checks the
+ version information of the plugin against the version of the
+ library to determine if the plugin is compatible.
+ */
+KHMEXP void KHMAPI
+khm_get_lib_version(khm_version * libver, khm_ui_4 * apiver);
+
+/*! \brief Return the version of Common Control library
+
+ Can be used to check the version of the Windows Common Control
+ library that is currently loaded. The return value of the
+ function is the packed version value obatained by the macro :
+
+ \code
+ MAKELONG(vesion->dwMinorVersion, version->dwMajorVersion);
+ \endcode
+
+ The \a pdvi parameter is optional. Specify NULL if this is not
+ required.
+ */
+KHMEXP khm_ui_4 KHMAPI
+khm_get_commctl_version(khm_version * pdvi);
+
+/*! \brief UI callback function
+
+ Used with khui_request_UI_callback().
+
+ \see khui_request_UI_callback()
+ */
+typedef khm_int32
+(KHMAPI *khm_ui_callback)(HWND hwnd_main_wnd, void * rock);
+
+/*! \brief Request a UI callback
+
+ In general, plug-ins in Network Identity Manager run in their own
+ thread and will not be able to interact with the user directly by
+ creating windows of its own. There are exceptions to this, such
+ as when the plug-in is responding to a new credentials request or
+ if the plug-in provides configuration panels. However, if a
+ plug-in needs to provide a user interface to the user outside of
+ the provisions already provided by Network Identity Manager, it
+ needs to do so from within the user interface thread.
+
+ To do so, a plug-in would provide a callback function of the type
+ ::khm_ui_callback to this function. The Network Identity Manager
+ will then call the callback function from within the user
+ interface thread. At this point, the callback function can create
+ any windows it wishes to create and interact with the user
+ directly.
+
+ The callback function would be called synchronously.
+ khui_request_UI_callback() will not return until the user
+ interface processes the request and calls the callback function.
+ The return code of khui_request_UI_callback() will be the return
+ code of the callback.
+
+ \param[in] cb The callback function which will be called from the
+ user interface thread.
+
+ \param[in] rock An arbitrary parameter which will be passed into
+ the callback function.
+
+ \return The return value of \a cb.
+
+ \note When the plug-in creates any windows, it should specify the
+ window handle provided via the \a hwnd_main_wnd parameter as
+ the parent window.
+
+ \see ::khm_ui_callback
+ */
+KHMEXP khm_int32 KHMAPI
+khui_request_UI_callback(khm_ui_callback cb, void * rock);
+
+/*!@}*/
+
+#endif
diff --git a/src/windows/identity/uilib/propsheet.c b/src/windows/identity/uilib/propsheet.c
index 705dd96a39..55c6cbb1b7 100644
--- a/src/windows/identity/uilib/propsheet.c
+++ b/src/windows/identity/uilib/propsheet.c
@@ -1,230 +1,230 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<khuidefs.h>
-#include<utils.h>
-#ifdef DEBUG
-#include<assert.h>
-#endif
-
-CRITICAL_SECTION cs_props;
-
-void
-ps_init(void) {
- InitializeCriticalSection(&cs_props);
-}
-
-void
-ps_exit(void) {
- DeleteCriticalSection(&cs_props);
-}
-
-KHMEXP khm_int32 KHMAPI
-khui_ps_create_sheet(khui_property_sheet ** sheet)
-{
- khui_property_sheet * ps;
-
- ps = PMALLOC(sizeof(*ps));
- ZeroMemory(ps, sizeof(*ps));
-
- ps->header.dwSize = sizeof(ps->header);
- ps->header.dwFlags = PSH_MODELESS | PSH_PROPTITLE;
- ps->status = KHUI_PS_STATUS_NONE;
-
- *sheet = ps;
-
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP khm_int32 KHMAPI
-khui_ps_add_page(khui_property_sheet * sheet,
- khm_int32 credtype,
- khm_int32 ordinal,
- LPPROPSHEETPAGE ppage,
- khui_property_page ** page)
-{
- khui_property_page * p;
-
- p = PMALLOC(sizeof(*p));
- ZeroMemory(p, sizeof(*p));
-
- p->credtype = credtype;
- p->ordinal = ordinal;
- p->p_page = ppage;
-
- EnterCriticalSection(&cs_props);
- QPUT(sheet, p);
- sheet->n_pages++;
- LeaveCriticalSection(&cs_props);
-
- if(page)
- *page = p;
-
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP khm_int32 KHMAPI
-khui_ps_find_page(khui_property_sheet * sheet,
- khm_int32 credtype,
- khui_property_page ** page)
-{
- khui_property_page * p;
-
- EnterCriticalSection(&cs_props);
- p = QTOP(sheet);
-
- while(p) {
- if(p->credtype == credtype)
- break;
- p = QNEXT(p);
- }
- LeaveCriticalSection(&cs_props);
-
- if(p) {
- *page = p;
- return KHM_ERROR_SUCCESS;
- } else {
- *page = NULL;
- return KHM_ERROR_NOT_FOUND;
- }
-}
-
-int __cdecl
-ps_order_func(const void *l, const void * r) {
- khui_property_page * lp;
- khui_property_page * rp;
-
- lp = *(khui_property_page **)l;
- rp = *(khui_property_page **)r;
-
- if (lp->ordinal == rp->ordinal)
- return lp->credtype - rp->credtype;
- else
- return lp->ordinal - rp->ordinal;
-}
-
-KHMEXP HWND KHMAPI
-khui_ps_show_sheet(HWND parent, khui_property_sheet * s)
-{
- khui_property_page * p;
- HPROPSHEETPAGE phpsp[KHUI_PS_MAX_PSP];
- khui_property_page * ppgs[KHUI_PS_MAX_PSP];
- int i;
- INT_PTR prv;
- HWND hw;
-
- EnterCriticalSection(&cs_props);
-
- s->header.hwndParent = parent;
- s->header.nPages = s->n_pages;
-
- p = QTOP(s);
- i = 0;
- while(p) {
- p->h_page = CreatePropertySheetPage(p->p_page);
-#ifdef DEBUG
- assert(p->h_page);
-#endif
- ppgs[i++] = p;
- p = QNEXT(p);
- }
-
-#ifdef DEBUG
- assert(i == s->n_pages);
-#endif
-
- qsort(ppgs, s->n_pages, sizeof(ppgs[0]), ps_order_func);
-
- for (i=0; i < s->n_pages; i++) {
- phpsp[i] = ppgs[i]->h_page;
- }
-
- s->header.phpage = phpsp;
-
- prv = PropertySheet(&s->header);
-
- s->header.phpage = NULL;
-
- if(prv <= 0) {
-#ifdef DEBUG
- assert(FALSE);
-#endif
- /*TODO: better handling for this */
- hw = NULL;
- } else {
- s->status = KHUI_PS_STATUS_RUNNING;
-
- hw = (HWND) prv;
- s->hwnd = hw;
- s->hwnd_page = PropSheet_GetCurrentPageHwnd(hw);
- }
- LeaveCriticalSection(&cs_props);
-
- return hw;
-}
-
-KHMEXP LRESULT KHMAPI
-khui_ps_check_message(khui_property_sheet * sheet,
- PMSG pmsg)
-{
- LRESULT lr;
-
- if(sheet->hwnd == NULL)
- return FALSE;
-
- lr = PropSheet_IsDialogMessage(sheet->hwnd, pmsg);
- if(lr) {
- sheet->hwnd_page = PropSheet_GetCurrentPageHwnd(sheet->hwnd);
- if(sheet->hwnd_page == NULL &&
- sheet->status == KHUI_PS_STATUS_RUNNING)
-
- sheet->status = KHUI_PS_STATUS_DONE;
- }
-
- return lr;
-}
-
-KHMEXP khm_int32 KHMAPI
-khui_ps_destroy_sheet(khui_property_sheet * sheet)
-{
- khui_property_page * p;
-
- EnterCriticalSection(&cs_props);
-
- DestroyWindow(sheet->hwnd);
- sheet->hwnd = NULL;
-
- QGET(sheet, &p);
- while(p) {
- PFREE(p);
- QGET(sheet, &p);
- }
- PFREE(sheet);
-
- LeaveCriticalSection(&cs_props);
-
- return KHM_ERROR_SUCCESS;
-}
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<khuidefs.h>
+#include<utils.h>
+#ifdef DEBUG
+#include<assert.h>
+#endif
+
+CRITICAL_SECTION cs_props;
+
+void
+ps_init(void) {
+ InitializeCriticalSection(&cs_props);
+}
+
+void
+ps_exit(void) {
+ DeleteCriticalSection(&cs_props);
+}
+
+KHMEXP khm_int32 KHMAPI
+khui_ps_create_sheet(khui_property_sheet ** sheet)
+{
+ khui_property_sheet * ps;
+
+ ps = PMALLOC(sizeof(*ps));
+ ZeroMemory(ps, sizeof(*ps));
+
+ ps->header.dwSize = sizeof(ps->header);
+ ps->header.dwFlags = PSH_MODELESS | PSH_PROPTITLE;
+ ps->status = KHUI_PS_STATUS_NONE;
+
+ *sheet = ps;
+
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP khm_int32 KHMAPI
+khui_ps_add_page(khui_property_sheet * sheet,
+ khm_int32 credtype,
+ khm_int32 ordinal,
+ LPPROPSHEETPAGE ppage,
+ khui_property_page ** page)
+{
+ khui_property_page * p;
+
+ p = PMALLOC(sizeof(*p));
+ ZeroMemory(p, sizeof(*p));
+
+ p->credtype = credtype;
+ p->ordinal = ordinal;
+ p->p_page = ppage;
+
+ EnterCriticalSection(&cs_props);
+ QPUT(sheet, p);
+ sheet->n_pages++;
+ LeaveCriticalSection(&cs_props);
+
+ if(page)
+ *page = p;
+
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP khm_int32 KHMAPI
+khui_ps_find_page(khui_property_sheet * sheet,
+ khm_int32 credtype,
+ khui_property_page ** page)
+{
+ khui_property_page * p;
+
+ EnterCriticalSection(&cs_props);
+ p = QTOP(sheet);
+
+ while(p) {
+ if(p->credtype == credtype)
+ break;
+ p = QNEXT(p);
+ }
+ LeaveCriticalSection(&cs_props);
+
+ if(p) {
+ *page = p;
+ return KHM_ERROR_SUCCESS;
+ } else {
+ *page = NULL;
+ return KHM_ERROR_NOT_FOUND;
+ }
+}
+
+int __cdecl
+ps_order_func(const void *l, const void * r) {
+ khui_property_page * lp;
+ khui_property_page * rp;
+
+ lp = *(khui_property_page **)l;
+ rp = *(khui_property_page **)r;
+
+ if (lp->ordinal == rp->ordinal)
+ return lp->credtype - rp->credtype;
+ else
+ return lp->ordinal - rp->ordinal;
+}
+
+KHMEXP HWND KHMAPI
+khui_ps_show_sheet(HWND parent, khui_property_sheet * s)
+{
+ khui_property_page * p;
+ HPROPSHEETPAGE phpsp[KHUI_PS_MAX_PSP];
+ khui_property_page * ppgs[KHUI_PS_MAX_PSP];
+ int i;
+ INT_PTR prv;
+ HWND hw;
+
+ EnterCriticalSection(&cs_props);
+
+ s->header.hwndParent = parent;
+ s->header.nPages = s->n_pages;
+
+ p = QTOP(s);
+ i = 0;
+ while(p) {
+ p->h_page = CreatePropertySheetPage(p->p_page);
+#ifdef DEBUG
+ assert(p->h_page);
+#endif
+ ppgs[i++] = p;
+ p = QNEXT(p);
+ }
+
+#ifdef DEBUG
+ assert(i == s->n_pages);
+#endif
+
+ qsort(ppgs, s->n_pages, sizeof(ppgs[0]), ps_order_func);
+
+ for (i=0; i < s->n_pages; i++) {
+ phpsp[i] = ppgs[i]->h_page;
+ }
+
+ s->header.phpage = phpsp;
+
+ prv = PropertySheet(&s->header);
+
+ s->header.phpage = NULL;
+
+ if(prv <= 0) {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ /*TODO: better handling for this */
+ hw = NULL;
+ } else {
+ s->status = KHUI_PS_STATUS_RUNNING;
+
+ hw = (HWND) prv;
+ s->hwnd = hw;
+ s->hwnd_page = PropSheet_GetCurrentPageHwnd(hw);
+ }
+ LeaveCriticalSection(&cs_props);
+
+ return hw;
+}
+
+KHMEXP LRESULT KHMAPI
+khui_ps_check_message(khui_property_sheet * sheet,
+ PMSG pmsg)
+{
+ LRESULT lr;
+
+ if(sheet->hwnd == NULL)
+ return FALSE;
+
+ lr = PropSheet_IsDialogMessage(sheet->hwnd, pmsg);
+ if(lr) {
+ sheet->hwnd_page = PropSheet_GetCurrentPageHwnd(sheet->hwnd);
+ if(sheet->hwnd_page == NULL &&
+ sheet->status == KHUI_PS_STATUS_RUNNING)
+
+ sheet->status = KHUI_PS_STATUS_DONE;
+ }
+
+ return lr;
+}
+
+KHMEXP khm_int32 KHMAPI
+khui_ps_destroy_sheet(khui_property_sheet * sheet)
+{
+ khui_property_page * p;
+
+ EnterCriticalSection(&cs_props);
+
+ DestroyWindow(sheet->hwnd);
+ sheet->hwnd = NULL;
+
+ QGET(sheet, &p);
+ while(p) {
+ PFREE(p);
+ QGET(sheet, &p);
+ }
+ PFREE(sheet);
+
+ LeaveCriticalSection(&cs_props);
+
+ return KHM_ERROR_SUCCESS;
+}
diff --git a/src/windows/identity/uilib/propwnd.c b/src/windows/identity/uilib/propwnd.c
index 5ae93a7a5b..2116f5ed4d 100644
--- a/src/windows/identity/uilib/propwnd.c
+++ b/src/windows/identity/uilib/propwnd.c
@@ -1,37 +1,37 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<khuidefs.h>
-
-
-#define PW_WM_SET_RECORD WM_USER
-
-KHMEXP khm_int32 KHMAPI khui_property_wnd_set_record(HWND hwnd_pwnd, khm_handle record)
-{
- SendMessage(hwnd_pwnd, PW_WM_SET_RECORD, 0, (LPARAM) record);
-
- return KHM_ERROR_SUCCESS;
-}
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<khuidefs.h>
+
+
+#define PW_WM_SET_RECORD WM_USER
+
+KHMEXP khm_int32 KHMAPI khui_property_wnd_set_record(HWND hwnd_pwnd, khm_handle record)
+{
+ SendMessage(hwnd_pwnd, PW_WM_SET_RECORD, 0, (LPARAM) record);
+
+ return KHM_ERROR_SUCCESS;
+}
diff --git a/src/windows/identity/uilib/rescache.c b/src/windows/identity/uilib/rescache.c
index b84608a8e4..3134df825e 100644
--- a/src/windows/identity/uilib/rescache.c
+++ b/src/windows/identity/uilib/rescache.c
@@ -1,303 +1,303 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#define NOEXPORT
-
-#include<khuidefs.h>
-#include<utils.h>
-
-hashtable * h_bitmaps;
-
-khm_int32
-hash_id(const void *p) {
-#pragma warning(push)
-#pragma warning(disable: 4311)
- return (khm_int32) p;
-#pragma warning(pop)
-}
-
-khm_int32
-comp_id(const void *p1, const void *p2) {
-#pragma warning(push)
-#pragma warning(disable: 4311)
- return ((khm_int32)p1) - ((khm_int32)p2);
-#pragma warning(pop)
-}
-
-void
-del_ref_object(const void *k, void * data) {
- DeleteObject((HGDIOBJ) data);
-}
-
-KHMEXP void KHMAPI
-khui_init_rescache(void) {
- h_bitmaps = hash_new_hashtable(127, hash_id, comp_id, NULL,
- del_ref_object);
-}
-
-KHMEXP void KHMAPI
-khui_exit_rescache(void) {
- hash_del_hashtable(h_bitmaps);
-}
-
-KHMEXP void KHMAPI
-khui_cache_bitmap(UINT id, HBITMAP hbm) {
- hash_add(h_bitmaps, (void *)(size_t) id, (void *) hbm);
-}
-
-KHMEXP HBITMAP KHMAPI
-khui_get_cached_bitmap(UINT id) {
- return (HBITMAP) hash_lookup(h_bitmaps, (void *)(size_t) id);
-}
-
-KHMEXP khui_ilist * KHMAPI
-khui_create_ilist(int cx, int cy, int n, int ng, int opt) {
- BITMAPV5HEADER head;
- HDC hdc;
-
- khui_ilist * il = PMALLOC(sizeof(khui_ilist));
- il->cx = cx;
- il->cy = cy;
- il->n = n;
- il->ng = ng;
- il->nused = 0;
- hdc = GetDC(NULL);
- head.bV5Size = sizeof(head);
- head.bV5Width = cx * n;
- head.bV5Height = cy;
- head.bV5Planes = 1;
- head.bV5BitCount = 24;
- head.bV5Compression = BI_RGB;
- head.bV5SizeImage = 0;
- head.bV5XPelsPerMeter = 2835;
- head.bV5YPelsPerMeter = 2835;
- head.bV5ClrUsed = 0;
- head.bV5ClrImportant = 0;
- head.bV5AlphaMask = 0;
- head.bV5CSType = LCS_WINDOWS_COLOR_SPACE;
- head.bV5Intent = LCS_GM_GRAPHICS;
- head.bV5ProfileData = 0;
- head.bV5ProfileSize = 0;
- head.bV5Reserved = 0;
- il->img = CreateDIBitmap(hdc, (BITMAPINFOHEADER *) &head, 0, NULL, NULL, DIB_RGB_COLORS);
- il->mask = CreateBitmap(cx * n, cy, 1, 1, NULL);
- il->idlist = PMALLOC(sizeof(int) * n);
-
- return il;
-}
-
-KHMEXP BOOL KHMAPI
-khui_delete_ilist(khui_ilist * il) {
- DeleteObject(il->img);
- DeleteObject(il->mask);
- PFREE(il->idlist);
- PFREE(il);
-
- return TRUE;
-}
-
-KHMEXP int KHMAPI
-khui_ilist_add_masked_id(khui_ilist *il,
- HBITMAP hbm,
- COLORREF cbkg,
- int id) {
- int idx;
-
- idx = khui_ilist_add_masked(il,hbm,cbkg);
- if(idx >= 0) {
- il->idlist[idx] = id;
- }
-
- return idx;
-}
-
-KHMEXP int KHMAPI
-khui_ilist_lookup_id(khui_ilist *il, int id) {
- int i;
-
- for(i=0;i<il->nused;i++) {
- if(il->idlist[i] == id)
- return i;
- }
-
- return -1;
-}
-
-KHMEXP int KHMAPI
-khui_ilist_add_masked(khui_ilist * il, HBITMAP hbm, COLORREF cbkg) {
- HDC dcr,dci,dct,dcb;
- HBITMAP hb_oldb, hb_oldi, hb_oldt;
- int sx, i;
- int x,y;
-
- dcr = GetDC(NULL);
- dci = CreateCompatibleDC(dcr);
- dct = CreateCompatibleDC(dcr);
- dcb = CreateCompatibleDC(dcr);
- ReleaseDC(NULL,dcr);
-
- i = il->nused++;
- il->idlist[i] = -1;
- sx = i * il->cx;
-
- hb_oldb = SelectObject(dcb, hbm);
- hb_oldi = SelectObject(dci, il->img);
- hb_oldt = SelectObject(dct, il->mask);
-
- SetBkColor(dct, RGB(0,0,0));
- SetTextColor(dct, RGB(255,255,255));
-
- BitBlt(dci, sx, 0, il->cx, il->cy, dcb, 0, 0, SRCCOPY);
- for(y=0;y < il->cy; y++)
- for(x=0; x<il->cx; x++) {
- COLORREF c = GetPixel(dcb, x, y);
- if(c==cbkg) {
- SetPixel(dct, sx + x, y, RGB(255,255,255));
- SetPixel(dci, sx + x, y, RGB(0,0,0));
- } else {
- SetPixel(dct, sx + x, y, RGB(0,0,0));
- }
- }
-
- SelectObject(dct, hb_oldt);
- SelectObject(dci, hb_oldi);
- SelectObject(dcb, hb_oldb);
-
- DeleteDC(dcb);
- DeleteDC(dct);
- DeleteDC(dci);
-
- return i;
-}
-
-KHMEXP void KHMAPI
-khui_ilist_draw(khui_ilist * il,
- int idx,
- HDC dc,
- int x,
- int y,
- int opt) {
- HDC dci;
- HBITMAP hb_oldi;
-
- if(idx < 0)
- return;
-
- dci = CreateCompatibleDC(dc);
-
- hb_oldi = SelectObject(dci, il->img);
-
- /*BitBlt(dc, x, y, il->cx, il->cy, dci, idx*il->cx, 0, SRCCOPY); */
- MaskBlt(dc, x, y, il->cx, il->cy, dci, idx * il->cx, 0, il->mask, idx * il->cx, 0, MAKEROP4(SRCPAINT, SRCCOPY));
-/* MaskBlt(dc, x, y, il->cx, il->cy, dci, idx * il->cx, 0, il->mask, idx * il->cx, 0, MAKEROP4(SRCINVERT, SRCCOPY)); */
-
- SelectObject(dci, hb_oldi);
-
- DeleteDC(dci);
-}
-
-KHMEXP void KHMAPI
-khui_ilist_draw_bg(khui_ilist * il,
- int idx,
- HDC dc,
- int x,
- int y,
- int opt,
- COLORREF bgcolor) {
- HDC dcm;
- HBITMAP hb_oldm, hb_mem;
- HBRUSH hbr;
- RECT r;
-
- dcm = CreateCompatibleDC(dc);
-
- hb_mem = CreateCompatibleBitmap(dc, il->cx, il->cy);
-
- hb_oldm = SelectObject(dcm, hb_mem);
-
- hbr = CreateSolidBrush(bgcolor);
-
- r.left = 0;
- r.top = 0;
- r.right = il->cx;
- r.bottom = il->cy;
-
- FillRect(dcm, &r, hbr);
-
- khui_ilist_draw(il,idx,dcm,0,0,opt);
-
- BitBlt(dc,x,y,il->cx,il->cy,dcm,0,0,SRCCOPY);
-
- SelectObject(dcm, hb_oldm);
-
- DeleteObject(hb_mem);
- DeleteObject(hbr);
-
- DeleteDC(dcm);
-}
-
-
-KHMEXP void KHMAPI
-khui_bitmap_from_hbmp(khui_bitmap * kbm, HBITMAP hbm)
-{
- HDC hdc;
- BITMAPINFO bmi;
-
- hdc = CreateCompatibleDC(NULL);
-
- bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
-
- kbm->hbmp = hbm;
-
- if(GetDIBits(hdc, hbm, 0, 0, NULL, &bmi, DIB_RGB_COLORS)) {
- kbm->cx = bmi.bmiHeader.biWidth;
- kbm->cy = bmi.bmiHeader.biHeight;
- } else {
- kbm->cx = -1;
- kbm->cy = -1;
- }
-
- DeleteDC(hdc);
-}
-
-KHMEXP void KHMAPI
-khui_delete_bitmap(khui_bitmap * kbm) {
- if (kbm->hbmp)
- DeleteObject(kbm->hbmp);
- kbm->hbmp = NULL;
-}
-
-KHMEXP void KHMAPI
-khui_draw_bitmap(HDC hdc, int x, int y, khui_bitmap * kbm) {
- HDC hdcb = CreateCompatibleDC(hdc);
- HBITMAP hbmold = SelectObject(hdcb, kbm->hbmp);
-
- BitBlt(hdc, x, y, kbm->cx, kbm->cy,
- hdcb, 0, 0, SRCCOPY);
-
- SelectObject(hdcb, hbmold);
- DeleteDC(hdcb);
-}
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#define NOEXPORT
+
+#include<khuidefs.h>
+#include<utils.h>
+
+hashtable * h_bitmaps;
+
+khm_int32
+hash_id(const void *p) {
+#pragma warning(push)
+#pragma warning(disable: 4311)
+ return (khm_int32) p;
+#pragma warning(pop)
+}
+
+khm_int32
+comp_id(const void *p1, const void *p2) {
+#pragma warning(push)
+#pragma warning(disable: 4311)
+ return ((khm_int32)p1) - ((khm_int32)p2);
+#pragma warning(pop)
+}
+
+void
+del_ref_object(const void *k, void * data) {
+ DeleteObject((HGDIOBJ) data);
+}
+
+KHMEXP void KHMAPI
+khui_init_rescache(void) {
+ h_bitmaps = hash_new_hashtable(127, hash_id, comp_id, NULL,
+ del_ref_object);
+}
+
+KHMEXP void KHMAPI
+khui_exit_rescache(void) {
+ hash_del_hashtable(h_bitmaps);
+}
+
+KHMEXP void KHMAPI
+khui_cache_bitmap(UINT id, HBITMAP hbm) {
+ hash_add(h_bitmaps, (void *)(size_t) id, (void *) hbm);
+}
+
+KHMEXP HBITMAP KHMAPI
+khui_get_cached_bitmap(UINT id) {
+ return (HBITMAP) hash_lookup(h_bitmaps, (void *)(size_t) id);
+}
+
+KHMEXP khui_ilist * KHMAPI
+khui_create_ilist(int cx, int cy, int n, int ng, int opt) {
+ BITMAPV5HEADER head;
+ HDC hdc;
+
+ khui_ilist * il = PMALLOC(sizeof(khui_ilist));
+ il->cx = cx;
+ il->cy = cy;
+ il->n = n;
+ il->ng = ng;
+ il->nused = 0;
+ hdc = GetDC(NULL);
+ head.bV5Size = sizeof(head);
+ head.bV5Width = cx * n;
+ head.bV5Height = cy;
+ head.bV5Planes = 1;
+ head.bV5BitCount = 24;
+ head.bV5Compression = BI_RGB;
+ head.bV5SizeImage = 0;
+ head.bV5XPelsPerMeter = 2835;
+ head.bV5YPelsPerMeter = 2835;
+ head.bV5ClrUsed = 0;
+ head.bV5ClrImportant = 0;
+ head.bV5AlphaMask = 0;
+ head.bV5CSType = LCS_WINDOWS_COLOR_SPACE;
+ head.bV5Intent = LCS_GM_GRAPHICS;
+ head.bV5ProfileData = 0;
+ head.bV5ProfileSize = 0;
+ head.bV5Reserved = 0;
+ il->img = CreateDIBitmap(hdc, (BITMAPINFOHEADER *) &head, 0, NULL, NULL, DIB_RGB_COLORS);
+ il->mask = CreateBitmap(cx * n, cy, 1, 1, NULL);
+ il->idlist = PMALLOC(sizeof(int) * n);
+
+ return il;
+}
+
+KHMEXP BOOL KHMAPI
+khui_delete_ilist(khui_ilist * il) {
+ DeleteObject(il->img);
+ DeleteObject(il->mask);
+ PFREE(il->idlist);
+ PFREE(il);
+
+ return TRUE;
+}
+
+KHMEXP int KHMAPI
+khui_ilist_add_masked_id(khui_ilist *il,
+ HBITMAP hbm,
+ COLORREF cbkg,
+ int id) {
+ int idx;
+
+ idx = khui_ilist_add_masked(il,hbm,cbkg);
+ if(idx >= 0) {
+ il->idlist[idx] = id;
+ }
+
+ return idx;
+}
+
+KHMEXP int KHMAPI
+khui_ilist_lookup_id(khui_ilist *il, int id) {
+ int i;
+
+ for(i=0;i<il->nused;i++) {
+ if(il->idlist[i] == id)
+ return i;
+ }
+
+ return -1;
+}
+
+KHMEXP int KHMAPI
+khui_ilist_add_masked(khui_ilist * il, HBITMAP hbm, COLORREF cbkg) {
+ HDC dcr,dci,dct,dcb;
+ HBITMAP hb_oldb, hb_oldi, hb_oldt;
+ int sx, i;
+ int x,y;
+
+ dcr = GetDC(NULL);
+ dci = CreateCompatibleDC(dcr);
+ dct = CreateCompatibleDC(dcr);
+ dcb = CreateCompatibleDC(dcr);
+ ReleaseDC(NULL,dcr);
+
+ i = il->nused++;
+ il->idlist[i] = -1;
+ sx = i * il->cx;
+
+ hb_oldb = SelectObject(dcb, hbm);
+ hb_oldi = SelectObject(dci, il->img);
+ hb_oldt = SelectObject(dct, il->mask);
+
+ SetBkColor(dct, RGB(0,0,0));
+ SetTextColor(dct, RGB(255,255,255));
+
+ BitBlt(dci, sx, 0, il->cx, il->cy, dcb, 0, 0, SRCCOPY);
+ for(y=0;y < il->cy; y++)
+ for(x=0; x<il->cx; x++) {
+ COLORREF c = GetPixel(dcb, x, y);
+ if(c==cbkg) {
+ SetPixel(dct, sx + x, y, RGB(255,255,255));
+ SetPixel(dci, sx + x, y, RGB(0,0,0));
+ } else {
+ SetPixel(dct, sx + x, y, RGB(0,0,0));
+ }
+ }
+
+ SelectObject(dct, hb_oldt);
+ SelectObject(dci, hb_oldi);
+ SelectObject(dcb, hb_oldb);
+
+ DeleteDC(dcb);
+ DeleteDC(dct);
+ DeleteDC(dci);
+
+ return i;
+}
+
+KHMEXP void KHMAPI
+khui_ilist_draw(khui_ilist * il,
+ int idx,
+ HDC dc,
+ int x,
+ int y,
+ int opt) {
+ HDC dci;
+ HBITMAP hb_oldi;
+
+ if(idx < 0)
+ return;
+
+ dci = CreateCompatibleDC(dc);
+
+ hb_oldi = SelectObject(dci, il->img);
+
+ /*BitBlt(dc, x, y, il->cx, il->cy, dci, idx*il->cx, 0, SRCCOPY); */
+ MaskBlt(dc, x, y, il->cx, il->cy, dci, idx * il->cx, 0, il->mask, idx * il->cx, 0, MAKEROP4(SRCPAINT, SRCCOPY));
+/* MaskBlt(dc, x, y, il->cx, il->cy, dci, idx * il->cx, 0, il->mask, idx * il->cx, 0, MAKEROP4(SRCINVERT, SRCCOPY)); */
+
+ SelectObject(dci, hb_oldi);
+
+ DeleteDC(dci);
+}
+
+KHMEXP void KHMAPI
+khui_ilist_draw_bg(khui_ilist * il,
+ int idx,
+ HDC dc,
+ int x,
+ int y,
+ int opt,
+ COLORREF bgcolor) {
+ HDC dcm;
+ HBITMAP hb_oldm, hb_mem;
+ HBRUSH hbr;
+ RECT r;
+
+ dcm = CreateCompatibleDC(dc);
+
+ hb_mem = CreateCompatibleBitmap(dc, il->cx, il->cy);
+
+ hb_oldm = SelectObject(dcm, hb_mem);
+
+ hbr = CreateSolidBrush(bgcolor);
+
+ r.left = 0;
+ r.top = 0;
+ r.right = il->cx;
+ r.bottom = il->cy;
+
+ FillRect(dcm, &r, hbr);
+
+ khui_ilist_draw(il,idx,dcm,0,0,opt);
+
+ BitBlt(dc,x,y,il->cx,il->cy,dcm,0,0,SRCCOPY);
+
+ SelectObject(dcm, hb_oldm);
+
+ DeleteObject(hb_mem);
+ DeleteObject(hbr);
+
+ DeleteDC(dcm);
+}
+
+
+KHMEXP void KHMAPI
+khui_bitmap_from_hbmp(khui_bitmap * kbm, HBITMAP hbm)
+{
+ HDC hdc;
+ BITMAPINFO bmi;
+
+ hdc = CreateCompatibleDC(NULL);
+
+ bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+
+ kbm->hbmp = hbm;
+
+ if(GetDIBits(hdc, hbm, 0, 0, NULL, &bmi, DIB_RGB_COLORS)) {
+ kbm->cx = bmi.bmiHeader.biWidth;
+ kbm->cy = bmi.bmiHeader.biHeight;
+ } else {
+ kbm->cx = -1;
+ kbm->cy = -1;
+ }
+
+ DeleteDC(hdc);
+}
+
+KHMEXP void KHMAPI
+khui_delete_bitmap(khui_bitmap * kbm) {
+ if (kbm->hbmp)
+ DeleteObject(kbm->hbmp);
+ kbm->hbmp = NULL;
+}
+
+KHMEXP void KHMAPI
+khui_draw_bitmap(HDC hdc, int x, int y, khui_bitmap * kbm) {
+ HDC hdcb = CreateCompatibleDC(hdc);
+ HBITMAP hbmold = SelectObject(hdcb, kbm->hbmp);
+
+ BitBlt(hdc, x, y, kbm->cx, kbm->cy,
+ hdcb, 0, 0, SRCCOPY);
+
+ SelectObject(hdcb, hbmold);
+ DeleteDC(hdcb);
+}
diff --git a/src/windows/identity/uilib/trackerwnd.c b/src/windows/identity/uilib/trackerwnd.c
index b0da7d15d6..1ec2fda28e 100644
--- a/src/windows/identity/uilib/trackerwnd.c
+++ b/src/windows/identity/uilib/trackerwnd.c
@@ -1,474 +1,474 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<khuidefs.h>
-#include<commctrl.h>
-#include<assert.h>
-
-#define K5_SLIDER_WIDTH 208
-#define K5_SLIDER_HEIGHT 40
-
-#define K5_SLIDER_LBL_HPAD 5
-#define K5_SLIDER_LBL_VPAD 22
-
-#define KHUI_TRACKER_PROP L"KhmTrackerData"
-
-
-/* Count the number of ticks between tmin and tmax, inclusive
-*/
-int time_t_to_ticks(time_t tmin, time_t tmax)
-{
- int c = 0;
- time_t lo, hi;
-
- tmin -= tmin % 60; /* our smallest gran is 1 min */
- if(tmax % 60)
- tmax += 60 - (tmax % 60);
-
- lo = tmin;
-
-#define TFORWARD(limit,gran) \
- if(lo < limit && lo < tmax) { \
- hi = min(tmax, limit); \
- c += (int)((hi - lo) / (gran)); \
- lo = hi; \
- }
-
- TFORWARD(300,60);
- TFORWARD(3600,300);
- TFORWARD(3600*4, 60*15);
- TFORWARD(3600*10,60*30);
- TFORWARD(3600*24,3600);
- TFORWARD(3600*24*4,3600*6);
- TFORWARD(((time_t)(INFINITE & INT_MAX)),3600*24);
-
-#undef TFORWARD
-
- return c;
-}
-
-/* Compute tmax given tmin and ticks such that there are ticks ticks
- between tmin and tmax
- */
-time_t ticks_to_time_t(int ticks, time_t tmin)
-{
- int c = 0;
- tmin -= tmin % 60; /* our smallest gran is 1 min */
-
-#define SFORWARD(limit,gran) \
- if(tmin < limit && ticks > 0) { \
- c = (int) min(ticks, (limit - tmin) / (gran)); \
- tmin += c * gran; \
- ticks -= c; \
- }
-
- SFORWARD(300,60);
- SFORWARD(3600,300);
- SFORWARD(3600*4,60*15);
- SFORWARD(3600*10,60*30);
- SFORWARD(3600*24,3600);
- SFORWARD(3600*24*4,3600*6);
- SFORWARD(((time_t)(INFINITE & INT_MAX)),3600*24);
-
-#undef SFORWARD
-
- return tmin;
-}
-
-/* Prep a tracker control which works in conjunction with the
- duration edit control.
-
- NOTE: Runs in the context of the UI thread
-*/
-void
-initialize_tracker(HWND hwnd,
- khui_tracker * tc)
-{
- RECT r;
- FILETIME ft;
- wchar_t wbuf[256];
- khm_size cbbuf;
-
- SendMessage(tc->hw_slider, TBM_SETRANGE, 0, MAKELONG(0, time_t_to_ticks(tc->min, tc->max)));
- SendMessage(tc->hw_slider, TBM_SETPOS, TRUE, (LPARAM) time_t_to_ticks(tc->min, tc->current));
-
- r.left = K5_SLIDER_LBL_HPAD;
- r.top = K5_SLIDER_LBL_VPAD;
- r.right = K5_SLIDER_WIDTH - K5_SLIDER_LBL_HPAD;
- r.bottom = r.top;
-
- MapDialogRect(hwnd, &r);
-
- tc->lbl_y = r.top;
- tc->lbl_lx = r.left;
- tc->lbl_rx = r.right;
-
- TimetToFileTimeInterval(tc->current, &ft);
- cbbuf = sizeof(wbuf);
- FtIntervalToString(&ft, wbuf, &cbbuf);
-
- SendMessage(tc->hw_edit, WM_SETTEXT, 0, (LPARAM)wbuf);
-}
-
-
-/* We instance-subclass each tracker control to provide the
- functionality that we need. This is the replacement window
- procedure
-
- NOTE: Runs in the context of the UI thread
- */
-LRESULT CALLBACK
-duration_tracker_proc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam)
-{
- khui_tracker * tc;
-
- tc = (khui_tracker *) GetProp(hwnd, KHUI_TRACKER_PROP);
-#ifdef DEBUG
- assert(tc != NULL);
-#endif
-
- switch(uMsg) {
- case WM_PAINT:
- {
- HDC hdc;
- HFONT hf, hfold;
- LRESULT lr;
- FILETIME ft;
- wchar_t buf[256];
- khm_size cbbuf;
-
- lr = CallWindowProc(tc->fn_tracker, hwnd, uMsg, wParam, lParam);
-
- /* Can't use BeginPaint here, since we already called the
- window proc */
- hdc = GetWindowDC(hwnd);
-
- hf = (HFONT) SendMessage(tc->hw_edit, WM_GETFONT, 0, 0);
-
- hfold = ((HFONT) SelectObject((hdc), (HGDIOBJ)(HFONT)(hf)));
-
- TimetToFileTimeInterval(tc->min, &ft);
- cbbuf = sizeof(buf);
- FtIntervalToString(&ft, buf, &cbbuf);
-
- SetTextColor(hdc, RGB(0,0,0));
- SetBkMode(hdc, TRANSPARENT);
-
- SetTextAlign(hdc, TA_LEFT | TA_TOP | TA_NOUPDATECP);
- TextOut(hdc, tc->lbl_lx, tc->lbl_y, buf, (int) wcslen(buf));
-
- TimetToFileTimeInterval(tc->max, &ft);
- cbbuf = sizeof(buf);
- FtIntervalToString(&ft, buf, &cbbuf);
-
- SetTextAlign(hdc, TA_RIGHT | TA_TOP | TA_NOUPDATECP);
- TextOut(hdc, tc->lbl_rx, tc->lbl_y, buf, (int) wcslen(buf));
-
- ((HFONT) SelectObject((hdc), (HGDIOBJ)(HFONT)(hfold)));
-
- ReleaseDC(hwnd, hdc);
-
- return lr;
- }
- break;
-
- case WM_KILLFOCUS:
- {
- if((HWND)wParam != tc->hw_edit)
- ShowWindow(hwnd, SW_HIDE);
- }
- break;
-
- case WM_LBUTTONUP:
- case WM_MOUSEMOVE:
- {
- LRESULT lr;
-
- lr = CallWindowProc(tc->fn_tracker, hwnd, uMsg, wParam, lParam);
-
- if(wParam & MK_LBUTTON) {
- int c = (int) SendMessage(hwnd, TBM_GETPOS, 0, 0);
- time_t t = ticks_to_time_t(c, tc->min);
-
- if(t != tc->current) {
- wchar_t buf[256];
- FILETIME ft;
- khm_size cbbuf;
-
- tc->current = t;
- //d->dirty = TRUE;
- cbbuf = sizeof(buf);
- TimetToFileTimeInterval(t, &ft);
- FtIntervalToString(&ft, buf, &cbbuf);
- SendMessage(tc->hw_edit, WM_SETTEXT, 0, (LPARAM) buf);
- }
- }
- return lr;
- }
- }
-
- return CallWindowProc(tc->fn_tracker, hwnd, uMsg, wParam, lParam);
-}
-
-
-/* Create the subclassed duration slider on behalf of an edit control */
-void
-create_edit_sliders(HWND hwnd,
- HWND hwnd_dlg,
- khui_tracker * tc)
-{
- RECT r;
- RECT rs;
-
- GetWindowRect(hwnd, &r);
-
- rs.top = 0;
- rs.left = 0;
- rs.right = K5_SLIDER_WIDTH;
- rs.bottom = K5_SLIDER_HEIGHT;
- MapDialogRect(hwnd_dlg, &rs);
- rs.right -= rs.left;
- rs.bottom -= rs.top;
-
- tc->hw_slider =
- CreateWindowEx(WS_EX_OVERLAPPEDWINDOW,
- TRACKBAR_CLASS,
- L"NetIDMgrTimeTickerTrackbar",
- WS_POPUP | TBS_AUTOTICKS | TBS_BOTTOM |
-#if (_WIN32_IE >= 0x0501)
- TBS_DOWNISLEFT |
-#endif
- TBS_HORZ | WS_CLIPCHILDREN,
- r.left,r.bottom,rs.right,rs.bottom,
- hwnd,
- NULL,
- (HINSTANCE)(DWORD_PTR)
- GetWindowLongPtr(hwnd, GWLP_HINSTANCE),
- NULL);
-
- SetProp(tc->hw_slider, KHUI_TRACKER_PROP,
- (HANDLE) tc);
-
-#pragma warning(push)
-#pragma warning(disable: 4244)
- tc->fn_tracker = (WNDPROC)(LONG_PTR) SetWindowLongPtr(tc->hw_slider, GWLP_WNDPROC, (LONG_PTR) duration_tracker_proc);
-#pragma warning(pop)
-}
-
-/* An edit control is instance-subclassed to create an edit control
- that holds a duration. Welcome to the window procedure.
-
- NOTE: Runs in the context of the UI thread
- */
-LRESULT CALLBACK
-duration_edit_proc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam)
-{
- khui_tracker * tc;
-
- tc = (khui_tracker *) GetProp(hwnd, KHUI_TRACKER_PROP);
-
-#ifdef DEBUG
- assert(tc != NULL);
-#endif
-
- switch(uMsg) {
- case WM_SETFOCUS:
- {
- HWND p;
-
- p = GetParent(hwnd);
-
- /* we are being activated. */
- if(tc->hw_slider == NULL) {
- create_edit_sliders(hwnd, p, tc);
- initialize_tracker(p, tc);
- }
-
- khui_tracker_reposition(tc);
-
-#ifdef SHOW_PANEL_ON_FIRST_ACTIVATE
- ShowWindow(tc->hw_slider, SW_SHOWNOACTIVATE);
-#endif
-
- tc->act_time = GetTickCount();
- }
- break;
-
- case WM_KILLFOCUS:
- {
- wchar_t wbuf[256];
- FILETIME ft;
- khm_size cbbuf;
-
- if((HWND) wParam != tc->hw_slider)
- ShowWindow(tc->hw_slider, SW_HIDE);
-
- TimetToFileTimeInterval(tc->current, &ft);
- cbbuf = sizeof(wbuf);
- FtIntervalToString(&ft, wbuf, &cbbuf);
-
- SendMessage(tc->hw_edit, WM_SETTEXT, 0, (LPARAM)wbuf);
- }
- break;
-
- case KHUI_WM_NC_NOTIFY:
- if(HIWORD(wParam) == WMNC_DIALOG_SETUP) {
- HWND p;
-
- p = GetParent(hwnd);
-
- if(tc->hw_slider == NULL) {
- create_edit_sliders(hwnd,p,tc);
- }
-
- initialize_tracker(p, tc);
- }
- return TRUE;
-
- case WM_LBUTTONUP:
- if (IsWindowVisible(tc->hw_slider)) {
- DWORD tm;
-
- tm = GetTickCount();
- if (tm - tc->act_time > 000)
- ShowWindow(tc->hw_slider, SW_HIDE);
- } else {
- ShowWindow(tc->hw_slider, SW_SHOWNOACTIVATE);
- }
- break;
-
- /* these messages can potentially change the text in the edit
- control. We intercept them and see what changed. We may
- need to grab and handle them */
- case EM_REPLACESEL:
- case EM_UNDO:
- case WM_UNDO:
- case WM_CHAR:
-#if (_WIN32_WINNT >= 0x0501)
- case WM_UNICHAR:
-#endif
- {
- wchar_t buf[256];
- size_t nchars;
- time_t ts;
- FILETIME ft;
- BOOL modified;
- LRESULT lr = CallWindowProc(tc->fn_edit, hwnd, uMsg, wParam, lParam);
-
- modified = (BOOL) SendMessage(hwnd, EM_GETMODIFY, 0, 0);
- if(modified) {
- /* parse the string */
- if(nchars = (size_t) SendMessage(hwnd, WM_GETTEXT, ARRAYLENGTH(buf), (LPARAM) buf)) {
- buf[nchars] = 0;
-
- if(KHM_SUCCEEDED(IntervalStringToFt(&ft, buf))) {
- ts = FtIntervalToSeconds(&ft);
- if(ts >= tc->min && ts <= tc->max) {
- tc->current = ts;
- //d->dirty = TRUE;
- if(tc->hw_slider != NULL)
- SendMessage(tc->hw_slider, TBM_SETPOS, TRUE, (LPARAM) time_t_to_ticks(tc->min, tc->current));
- }
- }
- }
- SendMessage(hwnd, EM_SETMODIFY, FALSE, 0);
- }
-
- return lr;
- }
- }
-
- return CallWindowProc(tc->fn_edit, hwnd, uMsg, wParam, lParam);
-}
-
-KHMEXP void KHMAPI
-khui_tracker_install(HWND hwnd_edit, khui_tracker * tc) {
-#ifdef DEBUG
- assert(hwnd_edit);
- assert(tc);
-#endif
-
- tc->hw_edit = hwnd_edit;
-
- SetProp(hwnd_edit, KHUI_TRACKER_PROP, (HANDLE) tc);
-
-#pragma warning(push)
-#pragma warning(disable: 4244)
- tc->fn_edit = (WNDPROC)(LONG_PTR)
- SetWindowLongPtr(hwnd_edit, GWLP_WNDPROC,
- (LONG_PTR) duration_edit_proc);
-#pragma warning(pop)
-}
-
-KHMEXP void KHMAPI
-khui_tracker_reposition(khui_tracker * tc) {
- RECT r;
-
- if(tc->hw_slider && tc->hw_edit) {
- GetWindowRect(tc->hw_edit, &r);
- SetWindowPos(tc->hw_slider,
- NULL,
- r.left, r.bottom,
- 0, 0,
- SWP_NOOWNERZORDER | SWP_NOSIZE |
- SWP_NOZORDER | SWP_NOACTIVATE);
- }
-}
-
-KHMEXP void KHMAPI
-khui_tracker_initialize(khui_tracker * tc) {
- ZeroMemory(tc, sizeof(*tc));
-}
-
-KHMEXP void KHMAPI
-khui_tracker_refresh(khui_tracker * tc) {
- if (!tc->hw_edit)
- return;
-
- SendMessage(tc->hw_edit,
- KHUI_WM_NC_NOTIFY,
- MAKEWPARAM(0,WMNC_DIALOG_SETUP), 0);
-}
-
-KHMEXP void KHMAPI
-khui_tracker_kill_controls(khui_tracker * tc) {
- if (tc->hw_slider)
- DestroyWindow(tc->hw_slider);
- if (tc->hw_edit)
- DestroyWindow(tc->hw_edit);
- tc->hw_slider = NULL;
- tc->hw_edit = NULL;
- tc->fn_edit = NULL;
- tc->fn_tracker = NULL;
-}
-
-
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<khuidefs.h>
+#include<commctrl.h>
+#include<assert.h>
+
+#define K5_SLIDER_WIDTH 208
+#define K5_SLIDER_HEIGHT 40
+
+#define K5_SLIDER_LBL_HPAD 5
+#define K5_SLIDER_LBL_VPAD 22
+
+#define KHUI_TRACKER_PROP L"KhmTrackerData"
+
+
+/* Count the number of ticks between tmin and tmax, inclusive
+*/
+int time_t_to_ticks(time_t tmin, time_t tmax)
+{
+ int c = 0;
+ time_t lo, hi;
+
+ tmin -= tmin % 60; /* our smallest gran is 1 min */
+ if(tmax % 60)
+ tmax += 60 - (tmax % 60);
+
+ lo = tmin;
+
+#define TFORWARD(limit,gran) \
+ if(lo < limit && lo < tmax) { \
+ hi = min(tmax, limit); \
+ c += (int)((hi - lo) / (gran)); \
+ lo = hi; \
+ }
+
+ TFORWARD(300,60);
+ TFORWARD(3600,300);
+ TFORWARD(3600*4, 60*15);
+ TFORWARD(3600*10,60*30);
+ TFORWARD(3600*24,3600);
+ TFORWARD(3600*24*4,3600*6);
+ TFORWARD(((time_t)(INFINITE & INT_MAX)),3600*24);
+
+#undef TFORWARD
+
+ return c;
+}
+
+/* Compute tmax given tmin and ticks such that there are ticks ticks
+ between tmin and tmax
+ */
+time_t ticks_to_time_t(int ticks, time_t tmin)
+{
+ int c = 0;
+ tmin -= tmin % 60; /* our smallest gran is 1 min */
+
+#define SFORWARD(limit,gran) \
+ if(tmin < limit && ticks > 0) { \
+ c = (int) min(ticks, (limit - tmin) / (gran)); \
+ tmin += c * gran; \
+ ticks -= c; \
+ }
+
+ SFORWARD(300,60);
+ SFORWARD(3600,300);
+ SFORWARD(3600*4,60*15);
+ SFORWARD(3600*10,60*30);
+ SFORWARD(3600*24,3600);
+ SFORWARD(3600*24*4,3600*6);
+ SFORWARD(((time_t)(INFINITE & INT_MAX)),3600*24);
+
+#undef SFORWARD
+
+ return tmin;
+}
+
+/* Prep a tracker control which works in conjunction with the
+ duration edit control.
+
+ NOTE: Runs in the context of the UI thread
+*/
+void
+initialize_tracker(HWND hwnd,
+ khui_tracker * tc)
+{
+ RECT r;
+ FILETIME ft;
+ wchar_t wbuf[256];
+ khm_size cbbuf;
+
+ SendMessage(tc->hw_slider, TBM_SETRANGE, 0, MAKELONG(0, time_t_to_ticks(tc->min, tc->max)));
+ SendMessage(tc->hw_slider, TBM_SETPOS, TRUE, (LPARAM) time_t_to_ticks(tc->min, tc->current));
+
+ r.left = K5_SLIDER_LBL_HPAD;
+ r.top = K5_SLIDER_LBL_VPAD;
+ r.right = K5_SLIDER_WIDTH - K5_SLIDER_LBL_HPAD;
+ r.bottom = r.top;
+
+ MapDialogRect(hwnd, &r);
+
+ tc->lbl_y = r.top;
+ tc->lbl_lx = r.left;
+ tc->lbl_rx = r.right;
+
+ TimetToFileTimeInterval(tc->current, &ft);
+ cbbuf = sizeof(wbuf);
+ FtIntervalToString(&ft, wbuf, &cbbuf);
+
+ SendMessage(tc->hw_edit, WM_SETTEXT, 0, (LPARAM)wbuf);
+}
+
+
+/* We instance-subclass each tracker control to provide the
+ functionality that we need. This is the replacement window
+ procedure
+
+ NOTE: Runs in the context of the UI thread
+ */
+LRESULT CALLBACK
+duration_tracker_proc(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ khui_tracker * tc;
+
+ tc = (khui_tracker *) GetProp(hwnd, KHUI_TRACKER_PROP);
+#ifdef DEBUG
+ assert(tc != NULL);
+#endif
+
+ switch(uMsg) {
+ case WM_PAINT:
+ {
+ HDC hdc;
+ HFONT hf, hfold;
+ LRESULT lr;
+ FILETIME ft;
+ wchar_t buf[256];
+ khm_size cbbuf;
+
+ lr = CallWindowProc(tc->fn_tracker, hwnd, uMsg, wParam, lParam);
+
+ /* Can't use BeginPaint here, since we already called the
+ window proc */
+ hdc = GetWindowDC(hwnd);
+
+ hf = (HFONT) SendMessage(tc->hw_edit, WM_GETFONT, 0, 0);
+
+ hfold = ((HFONT) SelectObject((hdc), (HGDIOBJ)(HFONT)(hf)));
+
+ TimetToFileTimeInterval(tc->min, &ft);
+ cbbuf = sizeof(buf);
+ FtIntervalToString(&ft, buf, &cbbuf);
+
+ SetTextColor(hdc, RGB(0,0,0));
+ SetBkMode(hdc, TRANSPARENT);
+
+ SetTextAlign(hdc, TA_LEFT | TA_TOP | TA_NOUPDATECP);
+ TextOut(hdc, tc->lbl_lx, tc->lbl_y, buf, (int) wcslen(buf));
+
+ TimetToFileTimeInterval(tc->max, &ft);
+ cbbuf = sizeof(buf);
+ FtIntervalToString(&ft, buf, &cbbuf);
+
+ SetTextAlign(hdc, TA_RIGHT | TA_TOP | TA_NOUPDATECP);
+ TextOut(hdc, tc->lbl_rx, tc->lbl_y, buf, (int) wcslen(buf));
+
+ ((HFONT) SelectObject((hdc), (HGDIOBJ)(HFONT)(hfold)));
+
+ ReleaseDC(hwnd, hdc);
+
+ return lr;
+ }
+ break;
+
+ case WM_KILLFOCUS:
+ {
+ if((HWND)wParam != tc->hw_edit)
+ ShowWindow(hwnd, SW_HIDE);
+ }
+ break;
+
+ case WM_LBUTTONUP:
+ case WM_MOUSEMOVE:
+ {
+ LRESULT lr;
+
+ lr = CallWindowProc(tc->fn_tracker, hwnd, uMsg, wParam, lParam);
+
+ if(wParam & MK_LBUTTON) {
+ int c = (int) SendMessage(hwnd, TBM_GETPOS, 0, 0);
+ time_t t = ticks_to_time_t(c, tc->min);
+
+ if(t != tc->current) {
+ wchar_t buf[256];
+ FILETIME ft;
+ khm_size cbbuf;
+
+ tc->current = t;
+ //d->dirty = TRUE;
+ cbbuf = sizeof(buf);
+ TimetToFileTimeInterval(t, &ft);
+ FtIntervalToString(&ft, buf, &cbbuf);
+ SendMessage(tc->hw_edit, WM_SETTEXT, 0, (LPARAM) buf);
+ }
+ }
+ return lr;
+ }
+ }
+
+ return CallWindowProc(tc->fn_tracker, hwnd, uMsg, wParam, lParam);
+}
+
+
+/* Create the subclassed duration slider on behalf of an edit control */
+void
+create_edit_sliders(HWND hwnd,
+ HWND hwnd_dlg,
+ khui_tracker * tc)
+{
+ RECT r;
+ RECT rs;
+
+ GetWindowRect(hwnd, &r);
+
+ rs.top = 0;
+ rs.left = 0;
+ rs.right = K5_SLIDER_WIDTH;
+ rs.bottom = K5_SLIDER_HEIGHT;
+ MapDialogRect(hwnd_dlg, &rs);
+ rs.right -= rs.left;
+ rs.bottom -= rs.top;
+
+ tc->hw_slider =
+ CreateWindowEx(WS_EX_OVERLAPPEDWINDOW,
+ TRACKBAR_CLASS,
+ L"NetIDMgrTimeTickerTrackbar",
+ WS_POPUP | TBS_AUTOTICKS | TBS_BOTTOM |
+#if (_WIN32_IE >= 0x0501)
+ TBS_DOWNISLEFT |
+#endif
+ TBS_HORZ | WS_CLIPCHILDREN,
+ r.left,r.bottom,rs.right,rs.bottom,
+ hwnd,
+ NULL,
+ (HINSTANCE)(DWORD_PTR)
+ GetWindowLongPtr(hwnd, GWLP_HINSTANCE),
+ NULL);
+
+ SetProp(tc->hw_slider, KHUI_TRACKER_PROP,
+ (HANDLE) tc);
+
+#pragma warning(push)
+#pragma warning(disable: 4244)
+ tc->fn_tracker = (WNDPROC)(LONG_PTR) SetWindowLongPtr(tc->hw_slider, GWLP_WNDPROC, (LONG_PTR) duration_tracker_proc);
+#pragma warning(pop)
+}
+
+/* An edit control is instance-subclassed to create an edit control
+ that holds a duration. Welcome to the window procedure.
+
+ NOTE: Runs in the context of the UI thread
+ */
+LRESULT CALLBACK
+duration_edit_proc(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ khui_tracker * tc;
+
+ tc = (khui_tracker *) GetProp(hwnd, KHUI_TRACKER_PROP);
+
+#ifdef DEBUG
+ assert(tc != NULL);
+#endif
+
+ switch(uMsg) {
+ case WM_SETFOCUS:
+ {
+ HWND p;
+
+ p = GetParent(hwnd);
+
+ /* we are being activated. */
+ if(tc->hw_slider == NULL) {
+ create_edit_sliders(hwnd, p, tc);
+ initialize_tracker(p, tc);
+ }
+
+ khui_tracker_reposition(tc);
+
+#ifdef SHOW_PANEL_ON_FIRST_ACTIVATE
+ ShowWindow(tc->hw_slider, SW_SHOWNOACTIVATE);
+#endif
+
+ tc->act_time = GetTickCount();
+ }
+ break;
+
+ case WM_KILLFOCUS:
+ {
+ wchar_t wbuf[256];
+ FILETIME ft;
+ khm_size cbbuf;
+
+ if((HWND) wParam != tc->hw_slider)
+ ShowWindow(tc->hw_slider, SW_HIDE);
+
+ TimetToFileTimeInterval(tc->current, &ft);
+ cbbuf = sizeof(wbuf);
+ FtIntervalToString(&ft, wbuf, &cbbuf);
+
+ SendMessage(tc->hw_edit, WM_SETTEXT, 0, (LPARAM)wbuf);
+ }
+ break;
+
+ case KHUI_WM_NC_NOTIFY:
+ if(HIWORD(wParam) == WMNC_DIALOG_SETUP) {
+ HWND p;
+
+ p = GetParent(hwnd);
+
+ if(tc->hw_slider == NULL) {
+ create_edit_sliders(hwnd,p,tc);
+ }
+
+ initialize_tracker(p, tc);
+ }
+ return TRUE;
+
+ case WM_LBUTTONUP:
+ if (IsWindowVisible(tc->hw_slider)) {
+ DWORD tm;
+
+ tm = GetTickCount();
+ if (tm - tc->act_time > 000)
+ ShowWindow(tc->hw_slider, SW_HIDE);
+ } else {
+ ShowWindow(tc->hw_slider, SW_SHOWNOACTIVATE);
+ }
+ break;
+
+ /* these messages can potentially change the text in the edit
+ control. We intercept them and see what changed. We may
+ need to grab and handle them */
+ case EM_REPLACESEL:
+ case EM_UNDO:
+ case WM_UNDO:
+ case WM_CHAR:
+#if (_WIN32_WINNT >= 0x0501)
+ case WM_UNICHAR:
+#endif
+ {
+ wchar_t buf[256];
+ size_t nchars;
+ time_t ts;
+ FILETIME ft;
+ BOOL modified;
+ LRESULT lr = CallWindowProc(tc->fn_edit, hwnd, uMsg, wParam, lParam);
+
+ modified = (BOOL) SendMessage(hwnd, EM_GETMODIFY, 0, 0);
+ if(modified) {
+ /* parse the string */
+ if(nchars = (size_t) SendMessage(hwnd, WM_GETTEXT, ARRAYLENGTH(buf), (LPARAM) buf)) {
+ buf[nchars] = 0;
+
+ if(KHM_SUCCEEDED(IntervalStringToFt(&ft, buf))) {
+ ts = FtIntervalToSeconds(&ft);
+ if(ts >= tc->min && ts <= tc->max) {
+ tc->current = ts;
+ //d->dirty = TRUE;
+ if(tc->hw_slider != NULL)
+ SendMessage(tc->hw_slider, TBM_SETPOS, TRUE, (LPARAM) time_t_to_ticks(tc->min, tc->current));
+ }
+ }
+ }
+ SendMessage(hwnd, EM_SETMODIFY, FALSE, 0);
+ }
+
+ return lr;
+ }
+ }
+
+ return CallWindowProc(tc->fn_edit, hwnd, uMsg, wParam, lParam);
+}
+
+KHMEXP void KHMAPI
+khui_tracker_install(HWND hwnd_edit, khui_tracker * tc) {
+#ifdef DEBUG
+ assert(hwnd_edit);
+ assert(tc);
+#endif
+
+ tc->hw_edit = hwnd_edit;
+
+ SetProp(hwnd_edit, KHUI_TRACKER_PROP, (HANDLE) tc);
+
+#pragma warning(push)
+#pragma warning(disable: 4244)
+ tc->fn_edit = (WNDPROC)(LONG_PTR)
+ SetWindowLongPtr(hwnd_edit, GWLP_WNDPROC,
+ (LONG_PTR) duration_edit_proc);
+#pragma warning(pop)
+}
+
+KHMEXP void KHMAPI
+khui_tracker_reposition(khui_tracker * tc) {
+ RECT r;
+
+ if(tc->hw_slider && tc->hw_edit) {
+ GetWindowRect(tc->hw_edit, &r);
+ SetWindowPos(tc->hw_slider,
+ NULL,
+ r.left, r.bottom,
+ 0, 0,
+ SWP_NOOWNERZORDER | SWP_NOSIZE |
+ SWP_NOZORDER | SWP_NOACTIVATE);
+ }
+}
+
+KHMEXP void KHMAPI
+khui_tracker_initialize(khui_tracker * tc) {
+ ZeroMemory(tc, sizeof(*tc));
+}
+
+KHMEXP void KHMAPI
+khui_tracker_refresh(khui_tracker * tc) {
+ if (!tc->hw_edit)
+ return;
+
+ SendMessage(tc->hw_edit,
+ KHUI_WM_NC_NOTIFY,
+ MAKEWPARAM(0,WMNC_DIALOG_SETUP), 0);
+}
+
+KHMEXP void KHMAPI
+khui_tracker_kill_controls(khui_tracker * tc) {
+ if (tc->hw_slider)
+ DestroyWindow(tc->hw_slider);
+ if (tc->hw_edit)
+ DestroyWindow(tc->hw_edit);
+ tc->hw_slider = NULL;
+ tc->hw_edit = NULL;
+ tc->fn_edit = NULL;
+ tc->fn_tracker = NULL;
+}
+
+
diff --git a/src/windows/identity/uilib/uibind.c b/src/windows/identity/uilib/uibind.c
index 11da4e4bfa..be183b68f8 100644
--- a/src/windows/identity/uilib/uibind.c
+++ b/src/windows/identity/uilib/uibind.c
@@ -1,59 +1,59 @@
-/*
- * Copyright (c) 2007 Secure Endpoints Inc.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<khuidefs.h>
-#include<intaction.h>
-
-#ifdef DEBUG
-#include <assert.h>
-#endif
-
-KHMEXP khm_int32 KHMAPI
-khui_request_UI_callback(khm_ui_callback cb, void * rock) {
-
- khui_ui_callback_data cbdata;
-
-#ifdef DEBUG
- assert(khui_hwnd_main);
-#endif
-
- if (khui_hwnd_main == NULL)
- return KHM_ERROR_NOT_READY;
-
- ZeroMemory(&cbdata, sizeof(cbdata));
- cbdata.magic = KHUI_UICBDATA_MAGIC;
- cbdata.cb = cb;
- cbdata.rock = rock;
- cbdata.rv = KHM_ERROR_NOT_IMPLEMENTED;
-
- SendMessage(khui_hwnd_main, WM_COMMAND,
- MAKEWPARAM(KHUI_ACTION_UICB, 0),
- (LPARAM) &cbdata);
-
- return cbdata.rv;
-}
-
-
+/*
+ * Copyright (c) 2007 Secure Endpoints Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<khuidefs.h>
+#include<intaction.h>
+
+#ifdef DEBUG
+#include <assert.h>
+#endif
+
+KHMEXP khm_int32 KHMAPI
+khui_request_UI_callback(khm_ui_callback cb, void * rock) {
+
+ khui_ui_callback_data cbdata;
+
+#ifdef DEBUG
+ assert(khui_hwnd_main);
+#endif
+
+ if (khui_hwnd_main == NULL)
+ return KHM_ERROR_NOT_READY;
+
+ ZeroMemory(&cbdata, sizeof(cbdata));
+ cbdata.magic = KHUI_UICBDATA_MAGIC;
+ cbdata.cb = cb;
+ cbdata.rock = rock;
+ cbdata.rv = KHM_ERROR_NOT_IMPLEMENTED;
+
+ SendMessage(khui_hwnd_main, WM_COMMAND,
+ MAKEWPARAM(KHUI_ACTION_UICB, 0),
+ (LPARAM) &cbdata);
+
+ return cbdata.rv;
+}
+
+
diff --git a/src/windows/identity/uilib/uilibmain.c b/src/windows/identity/uilib/uilibmain.c
index 4d0b012f11..5c13ad424c 100644
--- a/src/windows/identity/uilib/uilibmain.c
+++ b/src/windows/identity/uilib/uilibmain.c
@@ -1,44 +1,44 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<khuidefs.h>
-
-extern void alert_init(void);
-extern void alert_exit(void);
-extern void ps_init(void);
-extern void ps_exit(void);
-
-void
-uilib_process_attach(void) {
- alert_init();
- ps_init();
-}
-
-void
-uilib_process_detach(void) {
- ps_exit();
- alert_exit();
-}
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<khuidefs.h>
+
+extern void alert_init(void);
+extern void alert_exit(void);
+extern void ps_init(void);
+extern void ps_exit(void);
+
+void
+uilib_process_attach(void) {
+ alert_init();
+ ps_init();
+}
+
+void
+uilib_process_detach(void) {
+ ps_exit();
+ alert_exit();
+}
diff --git a/src/windows/identity/uilib/version.c b/src/windows/identity/uilib/version.c
index cf7f702bf1..6e3e48fe63 100644
--- a/src/windows/identity/uilib/version.c
+++ b/src/windows/identity/uilib/version.c
@@ -1,83 +1,83 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<shlwapi.h>
-#include<khuidefs.h>
-#include<netidmgr_intver.h>
-
-DLLVERSIONINFO ver_commctl;
-
-static void
-get_dll_version(wchar_t * dllname, DLLVERSIONINFO * pdvi) {
- HINSTANCE hdll;
-
- hdll = LoadLibrary(dllname);
-
- ZeroMemory(pdvi, sizeof(*pdvi));
-
- if(hdll) {
- DLLGETVERSIONPROC pDllGetVersion;
-
- pDllGetVersion = (DLLGETVERSIONPROC) GetProcAddress(hdll, "DllGetVersion");
- if(pDllGetVersion) {
- pdvi->cbSize = sizeof(*pdvi);
-
- (*pDllGetVersion)(pdvi);
- }
- FreeLibrary(hdll);
- }
-}
-
-KHMEXP void KHMAPI
-khm_version_init(void) {
- get_dll_version(L"comctl32.dll", &ver_commctl);
-}
-
-KHMEXP void KHMAPI
-khm_get_lib_version(khm_version * libver, khm_ui_4 * apiver) {
- if (!libver)
- return;
-
- libver->major = KH_VERSION_MAJOR;
- libver->minor = KH_VERSION_MINOR;
- libver->patch = KH_VERSION_PATCH;
- libver->aux = KH_VERSION_AUX;
-
- if (apiver)
- *apiver = KH_VERSION_API;
-}
-
-KHMEXP khm_ui_4 KHMAPI
-khm_get_commctl_version(khm_version * pdvi) {
- if (pdvi) {
- pdvi->major = (khm_ui_2) ver_commctl.dwMajorVersion;
- pdvi->minor = (khm_ui_2) ver_commctl.dwMinorVersion;
- pdvi->patch = (khm_ui_2) ver_commctl.dwBuildNumber;
- pdvi->aux = (khm_ui_2) ver_commctl.dwPlatformID;
- }
-
- return MAKELONG(ver_commctl.dwMinorVersion, ver_commctl.dwMajorVersion);
-}
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<shlwapi.h>
+#include<khuidefs.h>
+#include<netidmgr_intver.h>
+
+DLLVERSIONINFO ver_commctl;
+
+static void
+get_dll_version(wchar_t * dllname, DLLVERSIONINFO * pdvi) {
+ HINSTANCE hdll;
+
+ hdll = LoadLibrary(dllname);
+
+ ZeroMemory(pdvi, sizeof(*pdvi));
+
+ if(hdll) {
+ DLLGETVERSIONPROC pDllGetVersion;
+
+ pDllGetVersion = (DLLGETVERSIONPROC) GetProcAddress(hdll, "DllGetVersion");
+ if(pDllGetVersion) {
+ pdvi->cbSize = sizeof(*pdvi);
+
+ (*pDllGetVersion)(pdvi);
+ }
+ FreeLibrary(hdll);
+ }
+}
+
+KHMEXP void KHMAPI
+khm_version_init(void) {
+ get_dll_version(L"comctl32.dll", &ver_commctl);
+}
+
+KHMEXP void KHMAPI
+khm_get_lib_version(khm_version * libver, khm_ui_4 * apiver) {
+ if (!libver)
+ return;
+
+ libver->major = KH_VERSION_MAJOR;
+ libver->minor = KH_VERSION_MINOR;
+ libver->patch = KH_VERSION_PATCH;
+ libver->aux = KH_VERSION_AUX;
+
+ if (apiver)
+ *apiver = KH_VERSION_API;
+}
+
+KHMEXP khm_ui_4 KHMAPI
+khm_get_commctl_version(khm_version * pdvi) {
+ if (pdvi) {
+ pdvi->major = (khm_ui_2) ver_commctl.dwMajorVersion;
+ pdvi->minor = (khm_ui_2) ver_commctl.dwMinorVersion;
+ pdvi->patch = (khm_ui_2) ver_commctl.dwBuildNumber;
+ pdvi->aux = (khm_ui_2) ver_commctl.dwPlatformID;
+ }
+
+ return MAKELONG(ver_commctl.dwMinorVersion, ver_commctl.dwMajorVersion);
+}
diff --git a/src/windows/identity/util/hashtable.c b/src/windows/identity/util/hashtable.c
index ddf7b1bf8f..5773d8021c 100644
--- a/src/windows/identity/util/hashtable.c
+++ b/src/windows/identity/util/hashtable.c
@@ -1,171 +1,171 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<perfstat.h>
-#include<hashtable.h>
-#include<stdlib.h>
-
-KHMEXP hashtable * KHMAPI hash_new_hashtable(khm_int32 n,
- hash_function_t hash,
- comp_function_t comp,
- add_ref_function_t addr,
- del_ref_function_t delr)
-{
- hashtable * h;
-
- h = PMALLOC(sizeof(hashtable));
-
- h->n = n;
- h->addr = addr;
- h->comp = comp;
- h->delr = delr;
- h->hash = hash;
-
- h->bins = PCALLOC(sizeof(hash_bin *), n);
-
- return h;
-}
-
-KHMEXP void KHMAPI hash_del_hashtable(hashtable * h) {
- hash_bin * b;
- int i;
-
- for(i=0;i<h->n;i++) {
- LPOP(&h->bins[i], &b);
- while(b) {
- if(h->delr)
- h->delr(b->key, b->data);
- PFREE(b);
- LPOP(&h->bins[i], &b);
- }
- }
-
- if (h->bins)
- PFREE(h->bins);
-
- PFREE(h);
-}
-
-KHMEXP void KHMAPI hash_add(hashtable * h, const void * key, void * data) {
- int hv;
- hash_bin * b;
-
- hv = h->hash(key) % h->n;
- b = h->bins[hv];
- while(b) {
- if(!h->comp(b->key, key)) {
- /* found an existing value */
- if(h->delr)
- h->delr(b->key, b->data);
- b->key = key;
- b->data = data;
- if(h->addr)
- h->addr(b->key, b->data);
- break;
- }
- b = LNEXT(b);
- }
-
- if(!b) {
- b = PMALLOC(sizeof(hash_bin));
- b->data = data;
- b->key = key;
- LINIT(b);
- LPUSH(&h->bins[hv], b);
- if(h->addr)
- h->addr(b->key, b->data);
- }
-}
-
-KHMEXP void KHMAPI hash_del(hashtable * h, const void * key) {
- hash_bin * b;
- int hv;
-
- hv = h->hash(key) % h->n;
-
- b = h->bins[hv];
- while(b) {
- if(!h->comp(b->key, key)) {
- /* found it */
- LDELETE(&h->bins[hv], b);
- if(h->delr)
- h->delr(b->key, b->data);
- PFREE(b);
- break;
- }
- b = LNEXT(b);
- }
-}
-
-KHMEXP void * KHMAPI hash_lookup(hashtable * h, const void * key) {
- hash_bin * b;
- int hv;
-
- hv = h->hash(key) % h->n;
-
- b = h->bins[hv];
-
- while(b) {
- if(!h->comp(b->key, key)) {
- return b->data;
- }
- b = LNEXT(b);
- }
-
- return NULL;
-}
-
-KHMEXP khm_boolean KHMAPI hash_exist(hashtable * h, const void * key) {
- hash_bin * b;
- int hv;
-
- hv = h->hash(key) % h->n;
- b = h->bins[hv];
- while(b) {
- if(!h->comp(b->key, key))
- return 1;
- b = LNEXT(b);
- }
-
- return 0;
-}
-
-KHMEXP khm_int32 hash_string(const void *vs) {
- /* DJB algorithm */
-
- khm_int32 hv = 13331;
- wchar_t * c;
-
- for(c = (wchar_t *) vs; *c; c++) {
- hv = ((hv<<5) + hv) + (khm_int32) *c;
- }
-
- return (hv & KHM_INT32_MAX);
-}
-
-KHMEXP khm_int32 hash_string_comp(const void *vs1, const void *vs2) {
- return wcscmp((const wchar_t *) vs1, (const wchar_t *) vs2);
-}
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<perfstat.h>
+#include<hashtable.h>
+#include<stdlib.h>
+
+KHMEXP hashtable * KHMAPI hash_new_hashtable(khm_int32 n,
+ hash_function_t hash,
+ comp_function_t comp,
+ add_ref_function_t addr,
+ del_ref_function_t delr)
+{
+ hashtable * h;
+
+ h = PMALLOC(sizeof(hashtable));
+
+ h->n = n;
+ h->addr = addr;
+ h->comp = comp;
+ h->delr = delr;
+ h->hash = hash;
+
+ h->bins = PCALLOC(sizeof(hash_bin *), n);
+
+ return h;
+}
+
+KHMEXP void KHMAPI hash_del_hashtable(hashtable * h) {
+ hash_bin * b;
+ int i;
+
+ for(i=0;i<h->n;i++) {
+ LPOP(&h->bins[i], &b);
+ while(b) {
+ if(h->delr)
+ h->delr(b->key, b->data);
+ PFREE(b);
+ LPOP(&h->bins[i], &b);
+ }
+ }
+
+ if (h->bins)
+ PFREE(h->bins);
+
+ PFREE(h);
+}
+
+KHMEXP void KHMAPI hash_add(hashtable * h, const void * key, void * data) {
+ int hv;
+ hash_bin * b;
+
+ hv = h->hash(key) % h->n;
+ b = h->bins[hv];
+ while(b) {
+ if(!h->comp(b->key, key)) {
+ /* found an existing value */
+ if(h->delr)
+ h->delr(b->key, b->data);
+ b->key = key;
+ b->data = data;
+ if(h->addr)
+ h->addr(b->key, b->data);
+ break;
+ }
+ b = LNEXT(b);
+ }
+
+ if(!b) {
+ b = PMALLOC(sizeof(hash_bin));
+ b->data = data;
+ b->key = key;
+ LINIT(b);
+ LPUSH(&h->bins[hv], b);
+ if(h->addr)
+ h->addr(b->key, b->data);
+ }
+}
+
+KHMEXP void KHMAPI hash_del(hashtable * h, const void * key) {
+ hash_bin * b;
+ int hv;
+
+ hv = h->hash(key) % h->n;
+
+ b = h->bins[hv];
+ while(b) {
+ if(!h->comp(b->key, key)) {
+ /* found it */
+ LDELETE(&h->bins[hv], b);
+ if(h->delr)
+ h->delr(b->key, b->data);
+ PFREE(b);
+ break;
+ }
+ b = LNEXT(b);
+ }
+}
+
+KHMEXP void * KHMAPI hash_lookup(hashtable * h, const void * key) {
+ hash_bin * b;
+ int hv;
+
+ hv = h->hash(key) % h->n;
+
+ b = h->bins[hv];
+
+ while(b) {
+ if(!h->comp(b->key, key)) {
+ return b->data;
+ }
+ b = LNEXT(b);
+ }
+
+ return NULL;
+}
+
+KHMEXP khm_boolean KHMAPI hash_exist(hashtable * h, const void * key) {
+ hash_bin * b;
+ int hv;
+
+ hv = h->hash(key) % h->n;
+ b = h->bins[hv];
+ while(b) {
+ if(!h->comp(b->key, key))
+ return 1;
+ b = LNEXT(b);
+ }
+
+ return 0;
+}
+
+KHMEXP khm_int32 hash_string(const void *vs) {
+ /* DJB algorithm */
+
+ khm_int32 hv = 13331;
+ wchar_t * c;
+
+ for(c = (wchar_t *) vs; *c; c++) {
+ hv = ((hv<<5) + hv) + (khm_int32) *c;
+ }
+
+ return (hv & KHM_INT32_MAX);
+}
+
+KHMEXP khm_int32 hash_string_comp(const void *vs1, const void *vs2) {
+ return wcscmp((const wchar_t *) vs1, (const wchar_t *) vs2);
+}
diff --git a/src/windows/identity/util/hashtable.h b/src/windows/identity/util/hashtable.h
index 1a3fb4b86e..72fff2294b 100644
--- a/src/windows/identity/util/hashtable.h
+++ b/src/windows/identity/util/hashtable.h
@@ -1,231 +1,231 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#ifndef __KHIMAIRA_HASHTABLE_H
-#define __KHIMAIRA_HASHTABLE_H
-
-/*! \addtogroup util
- @{ */
-
-/*! \defgroup util_ht Hashtable
- @{*/
-
-#include<khdefs.h>
-#include<khlist.h>
-
-/*! \brief A hash function
-
- The function should take a key as a parameter and return an
- khm_int32 that serves as the hash of the key.
- */
-typedef khm_int32 (*hash_function_t)(const void *key);
-
-/*! \brief A comparison function
-
- The function takes two keys and returns a value indicating the
- relative ordering of the two keys.
-
- The return value should be:
- - \b Zero if \a key1 == \a key2
- - \b Negative if \a key1 &lt; \a key2
- - \b Positive if \a key1 &gt; \a key2
- */
-typedef khm_int32 (*comp_function_t)(const void *key1, const void *key2);
-
-/*! \brief Add-reference function
-
- When an object is successfully added to a hashtable, this function
- will be called with the \a key and \a data used to add the object.
- The function is allowed to modify \a data, however, the
- modification should not alter the \a key or the relationship
- between \a key and \a data.
- */
-typedef void (*add_ref_function_t)(const void *key, void *data);
-
-/*! \brief Delete-reference function
-
- When an object is successfully removed from the hashtable, this
- function will be called. As with the add-ref function, the object
- can be modified, but the \a key and the relationship between \a
- key and \a data should remain intact.
-
- An object is removed if it is explicitly removed from the
- hashtable or another object with the same \a key is added to the
- hashtable. There should be a 1-1 correspondence with keys and
- objects in the hashtable. The delete-reference function will be
- called on all the remaining objects in the hashtable when the
- hashtable is deleted.
- */
-typedef void (*del_ref_function_t)(const void *key, void *data);
-
-typedef struct tag_hash_bin {
- void * data;
- const void * key;
-
- LDCL(struct tag_hash_bin);
-} hash_bin;
-
-typedef struct hashtable_t {
- khm_int32 n;
- hash_function_t hash;
- comp_function_t comp;
- add_ref_function_t addr;
- del_ref_function_t delr;
- hash_bin ** bins;
-} hashtable;
-
-/*! \brief Create a new hashtable
-
- \param[in] n Number of bins in hashtable.
- \param[in] hash A hash function. Required.
- \param[in] comp A comparator. Required.
- \param[in] addr An add-ref function. Optional; can be NULL.
- \param[in] delr A del-ref function. Optional; can be NULL.
-
- */
-KHMEXP hashtable * KHMAPI hash_new_hashtable(khm_int32 n,
- hash_function_t hash,
- comp_function_t comp,
- add_ref_function_t addr,
- del_ref_function_t delr);
-
-/*! \brief Delete a hashtable
-
- \note Not thread-safe. Applications must serialize calls that
- reference the same hashtable.
- */
-KHMEXP void KHMAPI hash_del_hashtable(hashtable * h);
-
-/*! \brief Add an object to a hashtable
-
- Creates an association between the \a key and \a data in the
- hashtable \a h. If there is an add-ref function defined for the
- hashtable, it will be called with \a key and \data after the
- object is added. If there is already an object with the same key
- in the hashtable, that object will be removed (and the del-ref
- function called, if appilcable) before adding the new object and
- before the add-ref function is called for the new object.
-
- Note that two keys \a key1 and \a key2 are equal (or same) in a
- hashtable if the comparator returns zero when called with \a key1
- and \a key2.
-
- Also note that all additions and removals to the hashtable are
- done by reference. No data is copied. Any objects pointed to are
- expected to exist for the duration that the object and key are
- contained in the hashtable.
-
- \param[in] h Hashtable
- \param[in] key A key. If \a key points to a location in memory,
- it should be within the object pointed to by \a data, or be a
- constant. Can be NULL.
- \param[in] data Data. Cannot be NULL.
-
- \note Not thread-safe. Applications must serialize calls that
- reference the same hashtable.
- */
-KHMEXP void KHMAPI hash_add(hashtable * h, const void * key, void * data);
-
-/*! \brief Delete an object from a hashtable
-
- Deletes the object in the hashtable \a h that is associated with
- key \a key. An object is associated with key \a key if the key \a
- key_o that the object is associated with is the same as \a key as
- determined by the comparator. If the del-ref function is defined
- for the hash-table, it will be called with the \a key_o and \a
- data that was used to add the object.
-
- \note Not thread-safe. Applications must serialize calls that
- reference the same hashtable.
- */
-KHMEXP void KHMAPI hash_del(hashtable * h, const void * key);
-
-/*! \brief Resolve and association
-
- Return the object that is associated with key \a key in hashtable
- \a h. An object \a data is associated with key \a key in \a h if
- the key \a key_o that was used to add \a data to \a h is equal to
- \a key as determined by the comparator.
-
- Returns NULL if no association is found.
-
- \note Not thread-safe. Applications must serialize calls that
- reference the same hashtable.
- */
-KHMEXP void * KHMAPI hash_lookup(hashtable * h, const void * key);
-
-/*! \brief Check for the presence of an association
-
- Returns non-zero if there exists an association between key \a key
- and some object in hashtable \a h. See hash_lookup() for
- definition of "association".
-
- Returns zero if there is no association.
-
- \note (hash_lookup(h,key) == NULL) iff (hash_exist(h,key)==0)
-
- \note Not thead-safe. Application must serialize calls that
- reference the same hashtable.
- */
-KHMEXP khm_boolean KHMAPI hash_exist(hashtable * h, const void * key);
-
-/*! \brief Compute a hashvalue for a unicode string
-
- The hash value is computed using DJB with parameter 13331.
-
- This function is suitable for use as the hash function for a
- hashtable if the keys are NULL terminated safe unicode strings
- that are either part of the data objects or are constants.
-
- \param[in] str A pointer to a NULL terminated wchar_t string cast
- as (void *).
-
- \note This function does not check the length of the string \a
- str. If the string is not \a NULL terminated, the behavior is
- undefined.
- */
-KHMEXP khm_int32 hash_string(const void *str);
-
-/*! \brief Compare two strings
-
- Compares two strings are returns a value that is in accordance
- with the comparator for a hashtable.
-
- \param[in] vs1 A pointer to a NULL terminated wchar_t string cast
- as (void *).
- \param[in] vs2 A pointer to a NULL terminated wchar_t string cast
- as (void *).
-
- \note This function does not check the length of the strings \a
- vs1 and \a vs2. If the strings are not NULL terminated, the
- behavior is undefined.
- */
-KHMEXP khm_int32 hash_string_comp(const void *vs1, const void *vs2);
-
-/*@}*/
-/*@}*/
-
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __KHIMAIRA_HASHTABLE_H
+#define __KHIMAIRA_HASHTABLE_H
+
+/*! \addtogroup util
+ @{ */
+
+/*! \defgroup util_ht Hashtable
+ @{*/
+
+#include<khdefs.h>
+#include<khlist.h>
+
+/*! \brief A hash function
+
+ The function should take a key as a parameter and return an
+ khm_int32 that serves as the hash of the key.
+ */
+typedef khm_int32 (*hash_function_t)(const void *key);
+
+/*! \brief A comparison function
+
+ The function takes two keys and returns a value indicating the
+ relative ordering of the two keys.
+
+ The return value should be:
+ - \b Zero if \a key1 == \a key2
+ - \b Negative if \a key1 &lt; \a key2
+ - \b Positive if \a key1 &gt; \a key2
+ */
+typedef khm_int32 (*comp_function_t)(const void *key1, const void *key2);
+
+/*! \brief Add-reference function
+
+ When an object is successfully added to a hashtable, this function
+ will be called with the \a key and \a data used to add the object.
+ The function is allowed to modify \a data, however, the
+ modification should not alter the \a key or the relationship
+ between \a key and \a data.
+ */
+typedef void (*add_ref_function_t)(const void *key, void *data);
+
+/*! \brief Delete-reference function
+
+ When an object is successfully removed from the hashtable, this
+ function will be called. As with the add-ref function, the object
+ can be modified, but the \a key and the relationship between \a
+ key and \a data should remain intact.
+
+ An object is removed if it is explicitly removed from the
+ hashtable or another object with the same \a key is added to the
+ hashtable. There should be a 1-1 correspondence with keys and
+ objects in the hashtable. The delete-reference function will be
+ called on all the remaining objects in the hashtable when the
+ hashtable is deleted.
+ */
+typedef void (*del_ref_function_t)(const void *key, void *data);
+
+typedef struct tag_hash_bin {
+ void * data;
+ const void * key;
+
+ LDCL(struct tag_hash_bin);
+} hash_bin;
+
+typedef struct hashtable_t {
+ khm_int32 n;
+ hash_function_t hash;
+ comp_function_t comp;
+ add_ref_function_t addr;
+ del_ref_function_t delr;
+ hash_bin ** bins;
+} hashtable;
+
+/*! \brief Create a new hashtable
+
+ \param[in] n Number of bins in hashtable.
+ \param[in] hash A hash function. Required.
+ \param[in] comp A comparator. Required.
+ \param[in] addr An add-ref function. Optional; can be NULL.
+ \param[in] delr A del-ref function. Optional; can be NULL.
+
+ */
+KHMEXP hashtable * KHMAPI hash_new_hashtable(khm_int32 n,
+ hash_function_t hash,
+ comp_function_t comp,
+ add_ref_function_t addr,
+ del_ref_function_t delr);
+
+/*! \brief Delete a hashtable
+
+ \note Not thread-safe. Applications must serialize calls that
+ reference the same hashtable.
+ */
+KHMEXP void KHMAPI hash_del_hashtable(hashtable * h);
+
+/*! \brief Add an object to a hashtable
+
+ Creates an association between the \a key and \a data in the
+ hashtable \a h. If there is an add-ref function defined for the
+ hashtable, it will be called with \a key and \data after the
+ object is added. If there is already an object with the same key
+ in the hashtable, that object will be removed (and the del-ref
+ function called, if appilcable) before adding the new object and
+ before the add-ref function is called for the new object.
+
+ Note that two keys \a key1 and \a key2 are equal (or same) in a
+ hashtable if the comparator returns zero when called with \a key1
+ and \a key2.
+
+ Also note that all additions and removals to the hashtable are
+ done by reference. No data is copied. Any objects pointed to are
+ expected to exist for the duration that the object and key are
+ contained in the hashtable.
+
+ \param[in] h Hashtable
+ \param[in] key A key. If \a key points to a location in memory,
+ it should be within the object pointed to by \a data, or be a
+ constant. Can be NULL.
+ \param[in] data Data. Cannot be NULL.
+
+ \note Not thread-safe. Applications must serialize calls that
+ reference the same hashtable.
+ */
+KHMEXP void KHMAPI hash_add(hashtable * h, const void * key, void * data);
+
+/*! \brief Delete an object from a hashtable
+
+ Deletes the object in the hashtable \a h that is associated with
+ key \a key. An object is associated with key \a key if the key \a
+ key_o that the object is associated with is the same as \a key as
+ determined by the comparator. If the del-ref function is defined
+ for the hash-table, it will be called with the \a key_o and \a
+ data that was used to add the object.
+
+ \note Not thread-safe. Applications must serialize calls that
+ reference the same hashtable.
+ */
+KHMEXP void KHMAPI hash_del(hashtable * h, const void * key);
+
+/*! \brief Resolve and association
+
+ Return the object that is associated with key \a key in hashtable
+ \a h. An object \a data is associated with key \a key in \a h if
+ the key \a key_o that was used to add \a data to \a h is equal to
+ \a key as determined by the comparator.
+
+ Returns NULL if no association is found.
+
+ \note Not thread-safe. Applications must serialize calls that
+ reference the same hashtable.
+ */
+KHMEXP void * KHMAPI hash_lookup(hashtable * h, const void * key);
+
+/*! \brief Check for the presence of an association
+
+ Returns non-zero if there exists an association between key \a key
+ and some object in hashtable \a h. See hash_lookup() for
+ definition of "association".
+
+ Returns zero if there is no association.
+
+ \note (hash_lookup(h,key) == NULL) iff (hash_exist(h,key)==0)
+
+ \note Not thead-safe. Application must serialize calls that
+ reference the same hashtable.
+ */
+KHMEXP khm_boolean KHMAPI hash_exist(hashtable * h, const void * key);
+
+/*! \brief Compute a hashvalue for a unicode string
+
+ The hash value is computed using DJB with parameter 13331.
+
+ This function is suitable for use as the hash function for a
+ hashtable if the keys are NULL terminated safe unicode strings
+ that are either part of the data objects or are constants.
+
+ \param[in] str A pointer to a NULL terminated wchar_t string cast
+ as (void *).
+
+ \note This function does not check the length of the string \a
+ str. If the string is not \a NULL terminated, the behavior is
+ undefined.
+ */
+KHMEXP khm_int32 hash_string(const void *str);
+
+/*! \brief Compare two strings
+
+ Compares two strings are returns a value that is in accordance
+ with the comparator for a hashtable.
+
+ \param[in] vs1 A pointer to a NULL terminated wchar_t string cast
+ as (void *).
+ \param[in] vs2 A pointer to a NULL terminated wchar_t string cast
+ as (void *).
+
+ \note This function does not check the length of the strings \a
+ vs1 and \a vs2. If the strings are not NULL terminated, the
+ behavior is undefined.
+ */
+KHMEXP khm_int32 hash_string_comp(const void *vs1, const void *vs2);
+
+/*@}*/
+/*@}*/
+
+#endif
diff --git a/src/windows/identity/util/mstring.c b/src/windows/identity/util/mstring.c
index b642d1af88..d9eb9d3507 100644
--- a/src/windows/identity/util/mstring.c
+++ b/src/windows/identity/util/mstring.c
@@ -1,510 +1,510 @@
-/*
-* Copyright (c) 2005 Massachusetts Institute of Technology
-*
-* Permission is hereby granted, free of charge, to any person
-* obtaining a copy of this software and associated documentation
-* files (the "Software"), to deal in the Software without
-* restriction, including without limitation the rights to use, copy,
-* modify, merge, publish, distribute, sublicense, and/or sell copies
-* of the Software, and to permit persons to whom the Software is
-* furnished to do so, subject to the following conditions:
-*
-* The above copyright notice and this permission notice shall be
-* included in all copies or substantial portions of the Software.
-*
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
-* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
-* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-* SOFTWARE.
-*/
-
-/* $Id$ */
-
-#include<mstring.h>
-#include<kherror.h>
-#include<strsafe.h>
-#include<stdlib.h>
-
-#define TRUE 1
-#define FALSE 0
-
-KHMEXP khm_int32 KHMAPI
-multi_string_init(wchar_t * ms,
- khm_size cb_ms) {
- if (!ms || cb_ms < sizeof(wchar_t) * 2)
- return KHM_ERROR_INVALID_PARAM;
-
- memset(ms, 0, cb_ms);
-
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP khm_int32 KHMAPI
-multi_string_append(wchar_t * ms,
- khm_size * pcb_ms,
- const wchar_t * str)
-{
- wchar_t * s;
- size_t cch_s;
- size_t cch_t;
- size_t cch_r;
-
- if(!ms || !pcb_ms || !str)
- return KHM_ERROR_INVALID_PARAM;
-
- if(FAILED(StringCchLength(str, KHM_MAXCCH_STRING, &cch_s)) || cch_s == 0)
- return KHM_ERROR_INVALID_PARAM;
- cch_s++;
-
- s = ms;
-
- while(*s && ((s - ms) < KHM_MAXCCH_STRING)) {
- if(FAILED(StringCchLength(s, KHM_MAXCB_STRING, &cch_t)))
- return KHM_ERROR_INVALID_PARAM;
- s += cch_t + 1;
- }
-
- if(*s || (s - ms) >= KHM_MAXCCH_STRING) {
- return KHM_ERROR_INVALID_PARAM;
- }
-
- /* now s points to the second NULL of the terminating double NULL */
-
- cch_r = ((s - ms) + cch_s + 1) * sizeof(wchar_t);
- if(*pcb_ms < cch_r) {
- *pcb_ms = cch_r;
- return KHM_ERROR_TOO_LONG;
- }
-
- *pcb_ms = cch_r;
-
- StringCchCopy(s, cch_s, str);
- s += cch_s;
- *s = 0;
-
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP khm_int32 KHMAPI
-multi_string_prepend(wchar_t * ms,
- khm_size * pcb_ms,
- const wchar_t * str)
-{
- size_t cch_s;
- size_t cch_t;
- size_t cch_r;
- khm_size cb_r;
-
- if(!ms || !pcb_ms || !str)
- return KHM_ERROR_INVALID_PARAM;
-
- if(FAILED(StringCchLength(str, KHM_MAXCCH_STRING, &cch_s)) || cch_s == 0)
- return KHM_ERROR_INVALID_PARAM;
- cch_s++;
-
- if(KHM_FAILED(multi_string_length_cch(ms,
- KHM_MAXCCH_STRING,
- &cch_r)))
- return KHM_ERROR_INVALID_PARAM;
-
- cch_t = cch_s + cch_r;
- cb_r = cch_t * sizeof(wchar_t);
-
- if (*pcb_ms < cb_r) {
- *pcb_ms = cb_r;
- return KHM_ERROR_TOO_LONG;
- }
-
- memmove(ms + cch_s, ms, cch_r * sizeof(wchar_t));
- memcpy(ms, str, cch_s * sizeof(wchar_t));
-
- *pcb_ms = cb_r;
-
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP khm_int32 KHMAPI
-multi_string_delete(wchar_t * ms,
- const wchar_t * str,
- const khm_int32 flags)
-{
- wchar_t * s;
- wchar_t * n;
- wchar_t * e;
- size_t cch;
-
- if(!ms || !str)
- return KHM_ERROR_INVALID_PARAM;
-
- s = multi_string_find(ms, str, flags);
- if(!s)
- return KHM_ERROR_NOT_FOUND;
-
- e = s;
- n = NULL;
- while(*e && (e - s) < KHM_MAXCCH_STRING) {
- if(FAILED(StringCchLength(e, KHM_MAXCCH_STRING, &cch)))
- return KHM_ERROR_INVALID_PARAM;
- e += cch + 1;
-
- if(!n)
- n = e;
- }
-
- if(*e || (e - s) >= KHM_MAXCCH_STRING)
- return KHM_ERROR_INVALID_PARAM;
-
- if(e == s)
- return KHM_ERROR_SUCCESS;
-
- memmove((void *) s, (void *) n, ((e - n) + 1) * sizeof(wchar_t));
-
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP wchar_t * KHMAPI
-multi_string_find(const wchar_t * ms,
- const wchar_t * str,
- const khm_int32 flags)
-{
- const wchar_t *s;
- size_t cch;
- size_t cch_s;
-
- if(!ms || !str)
- return NULL;
-
- if(FAILED(StringCchLength(str, KHM_MAXCCH_STRING, &cch_s)))
- return NULL;
-
- s = ms;
-
- while(*s && (s - ms) < KHM_MAXCCH_STRING) {
- if(FAILED(StringCchLength(s, KHM_MAXCCH_STRING, &cch)))
- return NULL;
- /* cch++ at end */
-
- if(flags & KHM_PREFIX) {
- if(((flags & KHM_CASE_SENSITIVE) && !wcsncmp(s, str, cch_s)) ||
- (!(flags & KHM_CASE_SENSITIVE) && !_wcsnicmp(s, str, cch_s)))
- return (wchar_t *) s;
- } else {
- if((cch == cch_s) &&
- ((flags & KHM_CASE_SENSITIVE) && !wcsncmp(s, str, cch)) ||
- (!(flags & KHM_CASE_SENSITIVE) && !_wcsnicmp(s, str, cch)))
- return (wchar_t *) s;
- }
-
- s += cch + 1;
- }
-
- return NULL;
-}
-
-KHMEXP khm_int32 KHMAPI
-multi_string_to_csv(wchar_t * csvbuf,
- khm_size * pcb_csvbuf,
- const wchar_t * ms)
-{
- size_t cb;
- size_t cbt;
- const wchar_t * t;
- wchar_t * d;
-
- if(!pcb_csvbuf || !ms)
- return KHM_ERROR_INVALID_PARAM;
-
- /* dry run */
- cbt = 0;
- t = ms;
- while(*t && cbt <= KHM_MAXCB_STRING) {
- khm_boolean quotes = FALSE;
-
- if(FAILED(StringCbLength(t, KHM_MAXCB_STRING, &cb)))
- return KHM_ERROR_INVALID_PARAM;
- cb += sizeof(wchar_t);
-
- cbt += cb;
-
- if(wcschr(t, L','))
- quotes = TRUE;
-
- d = (wchar_t *) t;
- while(d = wcschr(d, L'"')) {
- cbt += sizeof(wchar_t); /* '"'-> '""' */
- d++;
- quotes = TRUE;
- }
-
- if(quotes)
- cbt += 2*sizeof(wchar_t); /* make room for quotes */
-
- t += cb / sizeof(wchar_t);
- }
-
- if(cbt > KHM_MAXCB_STRING)
- return KHM_ERROR_INVALID_PARAM;
-
- /* happens if the multi string contained no strings */
- if(cbt == 0)
- cbt = sizeof(wchar_t);
-
- if(!csvbuf || *pcb_csvbuf < cbt)
- {
- *pcb_csvbuf = cbt;
- return KHM_ERROR_TOO_LONG;
- }
-
- *pcb_csvbuf = cbt;
-
- /* wet run */
- t = ms;
- d = csvbuf;
- *csvbuf = 0;
- while(*t) {
- const wchar_t * s;
-
- StringCbLength(t, KHM_MAXCB_STRING, &cb);
- cb += sizeof(wchar_t);
-
- if(d != csvbuf)
- *d++ = L',';
- if(wcschr(t, L',') || wcschr(t, L'"')) {
- *d++ = L'"';
- s = t;
- while(*s) {
- if(*s == L'"') {
- *d++ = L'"';
- *d++ = L'"';
- } else
- *d++ = *s;
- s++;
- }
- *d++ = L'"';
- *d = 0;
- } else {
- StringCbCopy(d, cbt - ((d - csvbuf) * sizeof(wchar_t)), t);
- d += cb / sizeof(wchar_t) - 1;
- }
- t += cb / sizeof(wchar_t);
- }
-
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP khm_int32 KHMAPI
-csv_to_multi_string(wchar_t * ms,
- khm_size * pcb_ms,
- const wchar_t * csv)
-{
- const wchar_t * t;
- wchar_t * p;
- size_t cchr;
- int field = 1;
-
-
- if(!pcb_ms || !csv)
- return KHM_ERROR_INVALID_PARAM;
-
- cchr = 0;
-
- /* dry run */
- t = csv;
- while(*t && (t - csv) < KHM_MAXCCH_STRING) {
- if(field && *t == L'"') {
- t++;
- while(*t && (t - csv) < KHM_MAXCCH_STRING) {
- if(*t == L'"') {
- t++;
- if(*t != L'"')
- break;
- }
- cchr++;
- t++;
- }
- }
-
- if(*t) {
- cchr++;
- if(*t == L',')
- field = 1;
- else
- field = 0;
-
- t++;
- }
- }
-
- if((t - csv) >= KHM_MAXCCH_STRING)
- return KHM_ERROR_INVALID_PARAM;
-
- cchr++; /* last string ends */
- cchr++; /* double NULL */
-
- if(!ms || *pcb_ms < (cchr * sizeof(wchar_t))) {
- *pcb_ms = cchr * sizeof(wchar_t);
- return KHM_ERROR_TOO_LONG;
- }
-
- /* wet run */
- t = csv;
- p = ms;
- field = 1;
- while(*t) {
- if(field && *t == L'"') {
- t++;
- while(*t) {
- if(*t == L'"') {
- t++;
- if(*t != L'"')
- break;
- }
- *p++ = *t;
- t++;
- }
- }
-
- if(*t == L',') {
- *p++ = 0;
- field = 1;
- t++;
- } else if(*t) {
- *p++ = *t;
- field = 0;
- t++;
- }
- }
-
- *p++ = 0; /* last string ends */
- *p++ = 0; /* double NULL */
-
- *pcb_ms = (p - ms) * sizeof(wchar_t);
-
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP wchar_t * KHMAPI
-multi_string_next(const wchar_t * str)
-{
- size_t cch;
-
- if(*str) {
- if(FAILED(StringCchLength(str, KHM_MAXCCH_STRING, &cch)))
- return NULL;
- str += cch + 1;
- if(*str)
- return (wchar_t *) str;
- else
- return NULL;
- } else {
- return NULL;
- }
-}
-
-KHMEXP khm_size KHMAPI
-multi_string_length_n(const wchar_t * str)
-{
- size_t n = 0;
- const wchar_t * c = str;
-
- while(c) {
- n++;
- c = multi_string_next(c);
- }
-
- return n;
-}
-
-KHMEXP khm_int32 KHMAPI
-multi_string_length_cb(const wchar_t * str,
- khm_size max_cb,
- khm_size * len_cb)
-{
- khm_size cch;
- khm_int32 rv;
-
- rv = multi_string_length_cch(str, max_cb / sizeof(wchar_t), &cch);
-
- if(KHM_FAILED(rv))
- return rv;
-
- if(len_cb)
- *len_cb = cch * sizeof(wchar_t);
-
- return rv;
-}
-
-KHMEXP khm_int32 KHMAPI
-multi_string_length_cch(const wchar_t * str,
- khm_size max_cch,
- khm_size * len_cch)
-{
- const wchar_t * s;
- khm_size cch;
- size_t tcch;
-
- if(!str)
- return KHM_ERROR_INVALID_PARAM;
-
- s = str;
- cch = 0;
- while(*s && (cch < max_cch)) {
- if(FAILED(StringCchLength(s, max_cch, &tcch)))
- return KHM_ERROR_TOO_LONG;
- cch += ++tcch;
- s += tcch;
- }
-
- if(cch >= max_cch)
- return KHM_ERROR_TOO_LONG;
-
- if(len_cch) {
- *len_cch = ++cch;
- }
-
- return KHM_ERROR_SUCCESS;
-}
-
-KHMEXP khm_int32 KHMAPI
-multi_string_copy_cb(wchar_t * s_dest,
- khm_size max_cb_dest,
- const wchar_t * src)
-{
- khm_size cb_dest;
- khm_int32 rv = KHM_ERROR_SUCCESS;
-
- if(!s_dest)
- return KHM_ERROR_INVALID_PARAM;
-
- rv = multi_string_length_cb(src, max_cb_dest, &cb_dest);
- if(KHM_FAILED(rv))
- return rv;
-
- memmove(s_dest, src, cb_dest);
-
- return rv;
-}
-
-KHMEXP khm_int32 KHMAPI
-multi_string_copy_cch(wchar_t * s_dest,
- khm_size max_cch_dest,
- const wchar_t * src)
-{
- khm_size cch_dest;
- khm_int32 rv = KHM_ERROR_SUCCESS;
-
- if(!s_dest)
- return KHM_ERROR_INVALID_PARAM;
-
- rv = multi_string_length_cch(src, max_cch_dest, &cch_dest);
- if(KHM_FAILED(rv))
- return rv;
-
- memmove(s_dest, src, cch_dest * sizeof(wchar_t));
-
- return rv;
-}
+/*
+* Copyright (c) 2005 Massachusetts Institute of Technology
+*
+* Permission is hereby granted, free of charge, to any person
+* obtaining a copy of this software and associated documentation
+* files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy,
+* modify, merge, publish, distribute, sublicense, and/or sell copies
+* of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be
+* included in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*/
+
+/* $Id$ */
+
+#include<mstring.h>
+#include<kherror.h>
+#include<strsafe.h>
+#include<stdlib.h>
+
+#define TRUE 1
+#define FALSE 0
+
+KHMEXP khm_int32 KHMAPI
+multi_string_init(wchar_t * ms,
+ khm_size cb_ms) {
+ if (!ms || cb_ms < sizeof(wchar_t) * 2)
+ return KHM_ERROR_INVALID_PARAM;
+
+ memset(ms, 0, cb_ms);
+
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP khm_int32 KHMAPI
+multi_string_append(wchar_t * ms,
+ khm_size * pcb_ms,
+ const wchar_t * str)
+{
+ wchar_t * s;
+ size_t cch_s;
+ size_t cch_t;
+ size_t cch_r;
+
+ if(!ms || !pcb_ms || !str)
+ return KHM_ERROR_INVALID_PARAM;
+
+ if(FAILED(StringCchLength(str, KHM_MAXCCH_STRING, &cch_s)) || cch_s == 0)
+ return KHM_ERROR_INVALID_PARAM;
+ cch_s++;
+
+ s = ms;
+
+ while(*s && ((s - ms) < KHM_MAXCCH_STRING)) {
+ if(FAILED(StringCchLength(s, KHM_MAXCB_STRING, &cch_t)))
+ return KHM_ERROR_INVALID_PARAM;
+ s += cch_t + 1;
+ }
+
+ if(*s || (s - ms) >= KHM_MAXCCH_STRING) {
+ return KHM_ERROR_INVALID_PARAM;
+ }
+
+ /* now s points to the second NULL of the terminating double NULL */
+
+ cch_r = ((s - ms) + cch_s + 1) * sizeof(wchar_t);
+ if(*pcb_ms < cch_r) {
+ *pcb_ms = cch_r;
+ return KHM_ERROR_TOO_LONG;
+ }
+
+ *pcb_ms = cch_r;
+
+ StringCchCopy(s, cch_s, str);
+ s += cch_s;
+ *s = 0;
+
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP khm_int32 KHMAPI
+multi_string_prepend(wchar_t * ms,
+ khm_size * pcb_ms,
+ const wchar_t * str)
+{
+ size_t cch_s;
+ size_t cch_t;
+ size_t cch_r;
+ khm_size cb_r;
+
+ if(!ms || !pcb_ms || !str)
+ return KHM_ERROR_INVALID_PARAM;
+
+ if(FAILED(StringCchLength(str, KHM_MAXCCH_STRING, &cch_s)) || cch_s == 0)
+ return KHM_ERROR_INVALID_PARAM;
+ cch_s++;
+
+ if(KHM_FAILED(multi_string_length_cch(ms,
+ KHM_MAXCCH_STRING,
+ &cch_r)))
+ return KHM_ERROR_INVALID_PARAM;
+
+ cch_t = cch_s + cch_r;
+ cb_r = cch_t * sizeof(wchar_t);
+
+ if (*pcb_ms < cb_r) {
+ *pcb_ms = cb_r;
+ return KHM_ERROR_TOO_LONG;
+ }
+
+ memmove(ms + cch_s, ms, cch_r * sizeof(wchar_t));
+ memcpy(ms, str, cch_s * sizeof(wchar_t));
+
+ *pcb_ms = cb_r;
+
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP khm_int32 KHMAPI
+multi_string_delete(wchar_t * ms,
+ const wchar_t * str,
+ const khm_int32 flags)
+{
+ wchar_t * s;
+ wchar_t * n;
+ wchar_t * e;
+ size_t cch;
+
+ if(!ms || !str)
+ return KHM_ERROR_INVALID_PARAM;
+
+ s = multi_string_find(ms, str, flags);
+ if(!s)
+ return KHM_ERROR_NOT_FOUND;
+
+ e = s;
+ n = NULL;
+ while(*e && (e - s) < KHM_MAXCCH_STRING) {
+ if(FAILED(StringCchLength(e, KHM_MAXCCH_STRING, &cch)))
+ return KHM_ERROR_INVALID_PARAM;
+ e += cch + 1;
+
+ if(!n)
+ n = e;
+ }
+
+ if(*e || (e - s) >= KHM_MAXCCH_STRING)
+ return KHM_ERROR_INVALID_PARAM;
+
+ if(e == s)
+ return KHM_ERROR_SUCCESS;
+
+ memmove((void *) s, (void *) n, ((e - n) + 1) * sizeof(wchar_t));
+
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP wchar_t * KHMAPI
+multi_string_find(const wchar_t * ms,
+ const wchar_t * str,
+ const khm_int32 flags)
+{
+ const wchar_t *s;
+ size_t cch;
+ size_t cch_s;
+
+ if(!ms || !str)
+ return NULL;
+
+ if(FAILED(StringCchLength(str, KHM_MAXCCH_STRING, &cch_s)))
+ return NULL;
+
+ s = ms;
+
+ while(*s && (s - ms) < KHM_MAXCCH_STRING) {
+ if(FAILED(StringCchLength(s, KHM_MAXCCH_STRING, &cch)))
+ return NULL;
+ /* cch++ at end */
+
+ if(flags & KHM_PREFIX) {
+ if(((flags & KHM_CASE_SENSITIVE) && !wcsncmp(s, str, cch_s)) ||
+ (!(flags & KHM_CASE_SENSITIVE) && !_wcsnicmp(s, str, cch_s)))
+ return (wchar_t *) s;
+ } else {
+ if((cch == cch_s) &&
+ ((flags & KHM_CASE_SENSITIVE) && !wcsncmp(s, str, cch)) ||
+ (!(flags & KHM_CASE_SENSITIVE) && !_wcsnicmp(s, str, cch)))
+ return (wchar_t *) s;
+ }
+
+ s += cch + 1;
+ }
+
+ return NULL;
+}
+
+KHMEXP khm_int32 KHMAPI
+multi_string_to_csv(wchar_t * csvbuf,
+ khm_size * pcb_csvbuf,
+ const wchar_t * ms)
+{
+ size_t cb;
+ size_t cbt;
+ const wchar_t * t;
+ wchar_t * d;
+
+ if(!pcb_csvbuf || !ms)
+ return KHM_ERROR_INVALID_PARAM;
+
+ /* dry run */
+ cbt = 0;
+ t = ms;
+ while(*t && cbt <= KHM_MAXCB_STRING) {
+ khm_boolean quotes = FALSE;
+
+ if(FAILED(StringCbLength(t, KHM_MAXCB_STRING, &cb)))
+ return KHM_ERROR_INVALID_PARAM;
+ cb += sizeof(wchar_t);
+
+ cbt += cb;
+
+ if(wcschr(t, L','))
+ quotes = TRUE;
+
+ d = (wchar_t *) t;
+ while(d = wcschr(d, L'"')) {
+ cbt += sizeof(wchar_t); /* '"'-> '""' */
+ d++;
+ quotes = TRUE;
+ }
+
+ if(quotes)
+ cbt += 2*sizeof(wchar_t); /* make room for quotes */
+
+ t += cb / sizeof(wchar_t);
+ }
+
+ if(cbt > KHM_MAXCB_STRING)
+ return KHM_ERROR_INVALID_PARAM;
+
+ /* happens if the multi string contained no strings */
+ if(cbt == 0)
+ cbt = sizeof(wchar_t);
+
+ if(!csvbuf || *pcb_csvbuf < cbt)
+ {
+ *pcb_csvbuf = cbt;
+ return KHM_ERROR_TOO_LONG;
+ }
+
+ *pcb_csvbuf = cbt;
+
+ /* wet run */
+ t = ms;
+ d = csvbuf;
+ *csvbuf = 0;
+ while(*t) {
+ const wchar_t * s;
+
+ StringCbLength(t, KHM_MAXCB_STRING, &cb);
+ cb += sizeof(wchar_t);
+
+ if(d != csvbuf)
+ *d++ = L',';
+ if(wcschr(t, L',') || wcschr(t, L'"')) {
+ *d++ = L'"';
+ s = t;
+ while(*s) {
+ if(*s == L'"') {
+ *d++ = L'"';
+ *d++ = L'"';
+ } else
+ *d++ = *s;
+ s++;
+ }
+ *d++ = L'"';
+ *d = 0;
+ } else {
+ StringCbCopy(d, cbt - ((d - csvbuf) * sizeof(wchar_t)), t);
+ d += cb / sizeof(wchar_t) - 1;
+ }
+ t += cb / sizeof(wchar_t);
+ }
+
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP khm_int32 KHMAPI
+csv_to_multi_string(wchar_t * ms,
+ khm_size * pcb_ms,
+ const wchar_t * csv)
+{
+ const wchar_t * t;
+ wchar_t * p;
+ size_t cchr;
+ int field = 1;
+
+
+ if(!pcb_ms || !csv)
+ return KHM_ERROR_INVALID_PARAM;
+
+ cchr = 0;
+
+ /* dry run */
+ t = csv;
+ while(*t && (t - csv) < KHM_MAXCCH_STRING) {
+ if(field && *t == L'"') {
+ t++;
+ while(*t && (t - csv) < KHM_MAXCCH_STRING) {
+ if(*t == L'"') {
+ t++;
+ if(*t != L'"')
+ break;
+ }
+ cchr++;
+ t++;
+ }
+ }
+
+ if(*t) {
+ cchr++;
+ if(*t == L',')
+ field = 1;
+ else
+ field = 0;
+
+ t++;
+ }
+ }
+
+ if((t - csv) >= KHM_MAXCCH_STRING)
+ return KHM_ERROR_INVALID_PARAM;
+
+ cchr++; /* last string ends */
+ cchr++; /* double NULL */
+
+ if(!ms || *pcb_ms < (cchr * sizeof(wchar_t))) {
+ *pcb_ms = cchr * sizeof(wchar_t);
+ return KHM_ERROR_TOO_LONG;
+ }
+
+ /* wet run */
+ t = csv;
+ p = ms;
+ field = 1;
+ while(*t) {
+ if(field && *t == L'"') {
+ t++;
+ while(*t) {
+ if(*t == L'"') {
+ t++;
+ if(*t != L'"')
+ break;
+ }
+ *p++ = *t;
+ t++;
+ }
+ }
+
+ if(*t == L',') {
+ *p++ = 0;
+ field = 1;
+ t++;
+ } else if(*t) {
+ *p++ = *t;
+ field = 0;
+ t++;
+ }
+ }
+
+ *p++ = 0; /* last string ends */
+ *p++ = 0; /* double NULL */
+
+ *pcb_ms = (p - ms) * sizeof(wchar_t);
+
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP wchar_t * KHMAPI
+multi_string_next(const wchar_t * str)
+{
+ size_t cch;
+
+ if(*str) {
+ if(FAILED(StringCchLength(str, KHM_MAXCCH_STRING, &cch)))
+ return NULL;
+ str += cch + 1;
+ if(*str)
+ return (wchar_t *) str;
+ else
+ return NULL;
+ } else {
+ return NULL;
+ }
+}
+
+KHMEXP khm_size KHMAPI
+multi_string_length_n(const wchar_t * str)
+{
+ size_t n = 0;
+ const wchar_t * c = str;
+
+ while(c) {
+ n++;
+ c = multi_string_next(c);
+ }
+
+ return n;
+}
+
+KHMEXP khm_int32 KHMAPI
+multi_string_length_cb(const wchar_t * str,
+ khm_size max_cb,
+ khm_size * len_cb)
+{
+ khm_size cch;
+ khm_int32 rv;
+
+ rv = multi_string_length_cch(str, max_cb / sizeof(wchar_t), &cch);
+
+ if(KHM_FAILED(rv))
+ return rv;
+
+ if(len_cb)
+ *len_cb = cch * sizeof(wchar_t);
+
+ return rv;
+}
+
+KHMEXP khm_int32 KHMAPI
+multi_string_length_cch(const wchar_t * str,
+ khm_size max_cch,
+ khm_size * len_cch)
+{
+ const wchar_t * s;
+ khm_size cch;
+ size_t tcch;
+
+ if(!str)
+ return KHM_ERROR_INVALID_PARAM;
+
+ s = str;
+ cch = 0;
+ while(*s && (cch < max_cch)) {
+ if(FAILED(StringCchLength(s, max_cch, &tcch)))
+ return KHM_ERROR_TOO_LONG;
+ cch += ++tcch;
+ s += tcch;
+ }
+
+ if(cch >= max_cch)
+ return KHM_ERROR_TOO_LONG;
+
+ if(len_cch) {
+ *len_cch = ++cch;
+ }
+
+ return KHM_ERROR_SUCCESS;
+}
+
+KHMEXP khm_int32 KHMAPI
+multi_string_copy_cb(wchar_t * s_dest,
+ khm_size max_cb_dest,
+ const wchar_t * src)
+{
+ khm_size cb_dest;
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+
+ if(!s_dest)
+ return KHM_ERROR_INVALID_PARAM;
+
+ rv = multi_string_length_cb(src, max_cb_dest, &cb_dest);
+ if(KHM_FAILED(rv))
+ return rv;
+
+ memmove(s_dest, src, cb_dest);
+
+ return rv;
+}
+
+KHMEXP khm_int32 KHMAPI
+multi_string_copy_cch(wchar_t * s_dest,
+ khm_size max_cch_dest,
+ const wchar_t * src)
+{
+ khm_size cch_dest;
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+
+ if(!s_dest)
+ return KHM_ERROR_INVALID_PARAM;
+
+ rv = multi_string_length_cch(src, max_cch_dest, &cch_dest);
+ if(KHM_FAILED(rv))
+ return rv;
+
+ memmove(s_dest, src, cch_dest * sizeof(wchar_t));
+
+ return rv;
+}
diff --git a/src/windows/identity/util/mstring.h b/src/windows/identity/util/mstring.h
index a7f6cf5234..497cb777d4 100644
--- a/src/windows/identity/util/mstring.h
+++ b/src/windows/identity/util/mstring.h
@@ -1,361 +1,361 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#ifndef __KHIMAIRA_MSTRING_H
-#define __KHIMAIRA_MSTRING_H
-
-#include<khdefs.h>
-
-/*! \addtogroup util
- @{ */
-
-/*! \defgroup util_mstring Multi String and CSV functions
- @{*/
-
-#define KHM_PREFIX 8
-
-#define KHM_CASE_SENSITIVE 16
-
-#define KHM_MAXCCH_STRING 16384
-
-#define KHM_MAXCB_STRING (KHM_MAXCCH_STRING * sizeof(wchar_t))
-
-/*! \brief Initialize a multi-string
- */
-KHMEXP khm_int32 KHMAPI
-multi_string_init(wchar_t * ms,
- khm_size cb_ms);
-
-/*! \brief Prepend a string to a multi string
-
- Adds the string \a str to the beginning of multi-string \a ms.
-
- \param[in,out] ms The multi-string to be modified.
-
- \param[in,out] pcb_ms A pointer to the size of the multistring.
- On entry this specifies the size of the buffer pointed to by
- \a ms. If the call is successful, on exit this will receive
- the new size of the multi string in bytes. If the buffer is
- insufficient, the function will return KHM_ERROR_TOO_LONG and
- set this to the required size of the buffer in bytes.
-
- \param[in] str The string to prepend to \a ms. This cannot be
- longer than KHM_MAXCCH_STRING in characters including the
- terminating NULL.
- */
-KHMEXP khm_int32 KHMAPI
-multi_string_prepend(wchar_t * ms,
- khm_size * pcb_ms,
- const wchar_t * str);
-
-/*! \brief Append a string to a multi-string
-
- Appends the string specified by \a str to the multi string
- specified by \a ms. The size of the multi string in characters
- including terminating NULLs after appending \a str can not exceed
- KHM_MAXCCH_STRING.
-
- \param[in] ms The buffer containing the multi string
-
- \param[in,out] pcb_ms Points to a khm_int32 indicating the size of
- the buffer pointed to by \a ms. On entry this contains the
- size (in bytes) of the buffer pointed to by \a ms. On exit,
- contains the new size of the multi string in bytes.
-
- \param[in] str The string to append to the multi string. This
- string cannot be NULL or an empty (zero length) string. The
- length of \a str cannot exceed KHM_MAXCCH_STRING in
- characters including terminating NULL.
-
- \retval KHM_ERROR_SUCCESS The string was appended to the multi string
-
- \retval KHM_ERROR_TOO_LONG The buffer pointed to by \a ms was
- insufficient. The required size of the buffer is in \a pcb_ms
-
- \retval KHM_ERROR_INVALID_PARAM One of more of the parameters were invalid.
- */
-KHMEXP khm_int32 KHMAPI
-multi_string_append(wchar_t * ms,
- khm_size * pcb_ms,
- const wchar_t * str);
-
-/*! \brief Deletes a string from a multi string
-
- Deletes the string specified by \a str from the multi string
- specified by \a ms. How the string is matched to the strings in
- \a ms is determined by \a flags. If more than one match is found,
- then only the first match is deleted.
-
- \param[in] ms The multi string to modify. The length of the multi
- string in characters cannot exceed KHM_MAXCCH_STRING.
-
- \param[in] str The string to search for
-
- \param[in] flags How \a str is to be matched to existing strings
- in \a ms. This could be a combination of KHM_PREFIX and
- KHM_CASE_SENSITIVE. If KHM_PREFIX is used, then \a ms is
- searched for a string that begins with \a str. Otherwise, \a
- str must match the an entire string in the multi string. If
- KHM_CASE_SENSITIVE is specified, then a case sensitive match
- is performed. The defualt is to use a case insensitive
- search.
-
- \retval KHM_ERROR_SUCCESS A string was matched and deleted from \a ms
-
- \retval KHM_ERROR_NOT_FOUND No matches were found
-
- \retval KHM_ERROR_INVALID_PARAM One or more parameters were incorrect.
-
- \note The search for the existing string is done with
- multi_string_find()
- */
-KHMEXP khm_int32 KHMAPI
-multi_string_delete(wchar_t * ms,
- const wchar_t * str,
- const khm_int32 flags);
-
-/*! \brief Search a multi string for a string
-
- Searches the string specified by \a ms for a string that matches
- \a str. How the match is performed is determined by \a flags.
- Returns a poitner to the start of the matched string in \a ms. If
- more than one string in \a ms matches \a str, then only the first
- match is returned.
-
- \param[in] ms The multi string to search in. The length of the
- multi string cannot exceed KHM_MAXCCH_STRING in characters.
-
- \param[in] str The string to search for
-
- \param[in] flags How \a str is to be matched to existing strings
- in \a ms. This could be a combination of KHM_PREFIX and
- KHM_CASE_SENSITIVE. If KHM_PREFIX is used, then \a ms is
- searched for a string that begins with \a str. Otherwise, \a
- str must match the an entire string in the multi string. If
- KHM_CASE_SENSITIVE is specified, then a case sensitive match
- is performed. The defualt is to use a case insensitive
- search.
-
- \return A pointer to the start of the first matched string or
- NULL if no matches were found.
-
- */
-KHMEXP wchar_t * KHMAPI
-multi_string_find(const wchar_t * ms,
- const wchar_t * str,
- const khm_int32 flags);
-
-/*! \brief Convert a multi string to CSV
-
- Converts a multi string to a comma separated value string based on
- the following rules.
-
- - Each string in the multi string is treated an individual field
-
- - A field is quoted if it has double quotes or commas
-
- - Double quotes within quoted fields are escaped by two
- consecutive double quotes.
-
- For example:
-
- \code
- multi_string = L"foo\0bar\0baz,quux\0ab\"cd\0";
- csv_string = L"foo,bar,\"baz,quux\",\"ab\"\"cd\"";
- \endcode
-
- If multi_string_to_csv() is called on \a multi_string above,
- you would obtain \a csv_string.
-
- \param[out] csvbuf The buffer to place the CSV string in. Can be
- NULL if only teh size of the needed buffer is required.
-
- \param[in,out] pcb_csvbuf On entry, points to a khm_int32 that
- holds the size of the buffer pointed to by \a csvbuf. On
- exit, gets the number of bytes writted to \a csvbuf or the
- required size of \a csvbuf if the buffer is too small or \a
- csvbuf is NULL.
-
- \param[in] ms The mutli string to convert to a CSV.
-
- \retval KHM_ERROR_SUCCESS The multi string was successfully
- converted to a CSV string. The number of bytes written is in
- \a pcb_csvbuf. The count includes the terminating NULL.
-
- \retval KHM_ERROR_TOO_LONG The buffer was too small or \a csvbuf
- was NULL. The required number of bytes in the buffer is in \a
- pcb_csvbuf.
-
- \retval KHM_ERROR_INVALID_PARAM One or more parameters were ivnalid.
-
- \see csv_to_multi_string()
-*/
-KHMEXP khm_int32 KHMAPI
-multi_string_to_csv(wchar_t * csvbuf,
- khm_size * pcb_csvbuf,
- const wchar_t * ms);
-
-/*! \brief Converts a CSV to a multi string
-
- Undoes what multi_string_to_csv() does.
-
- \param[out] ms The buffer that recieves the multi string. This
- can be NULL if only the size of the buffer is requried.
-
- \param[in,out] pcb_ms On entry contains the number of bytes ni the
- buffer poitned to by \a ms. On exit contains the number of
- bytes that were copied to \a ms including terminating NULLs,
- or if the buffer was too small or \a ms was NULL, holds the
- size in bytes of the requied buffer.
-
- \param[in] csv The CSV string.
-
- \retval KHM_ERROR_SUCCESS The CSV string was successfully
- converted. The number of bytes written is in \a pcb_ms.
-
- \retval KHM_ERROR_TOO_LONG The provided buffer was too small or \a
- ms was NULL. The required size of the buffer in bytes is in \a
- pcb_ms.
-
- \retval KHM_ERROR_INVALID_PARAM One or more parameters were invalid.
-
- */
-KHMEXP khm_int32 KHMAPI
-csv_to_multi_string(wchar_t * ms,
- khm_size * pcb_ms,
- const wchar_t * csv);
-
-/*! \brief Get the next string in a multi string
-
- When \a str is pointing to a string that is in a multi string,
- this function returns a pointer to the next string in the multi
- string.
-
- Typically, one would start by having \a str point to the start of
- the multi string (which is the first string in the multi string),
- and then call this function repeatedly, until it returns NULL, at
- which point the end of the multi string has been reached.
-
- \param[in] str Pointer to a string in a multi string. Each string
- in a multi string cannot exceed KHM_MAXCCH_STRING in charaters
- including the terminating NULL.
-
- \return A pointer to the start of the next string in the multi
- string or NULL if there is no more strings.
- */
-KHMEXP wchar_t * KHMAPI
-multi_string_next(const wchar_t * str);
-
-/*! \brief Get the length of a multi string in bytes
-
- The returned length includes the trailing double \a NULL and any
- other \a NULL inbetween.
-
- \param[in] str Pointer to a multi string.
- \param[in] max_cb Maximum size that the str can be. This can not
- be larger than KHM_MAXCB_STRING.
- \param[out] len_cb The length of the string in bytes if the call
- is successful.
-
- \retval KHM_ERROR_SUCCESS The length of the string is in \a len_cb
- \retval KHM_ERROR_INVALID_PARAM One or more parameters were invalid
- \retval KHM_ERROR_TOO_LONG The multi string is longer than \a
- max_cb bytes.
- */
-KHMEXP khm_int32 KHMAPI
-multi_string_length_cb(const wchar_t * str,
- khm_size max_cb,
- khm_size * len_cb);
-
-/*! \brief Get the length of a multi string in characters
-
- The returned length includes the trailing double \a NULL and any
- other \a NULL inbetween.
-
- \param[in] str Pointer to a multi string.
- \param[in] max_cch Maximum size that the str can be. This can not
- be larger than KHM_MAXCCH_STRING.
- \param[out] len_cch The length of the string in characters if the call
- is successful.
-
- \retval KHM_ERROR_SUCCESS The length of the string is in \a len_cch
- \retval KHM_ERROR_INVALID_PARAM One or more parameters were invalid
- \retval KHM_ERROR_TOO_LONG The multi string is longer than \a
- max_cch characters.
- */
-KHMEXP khm_int32 KHMAPI
-multi_string_length_cch(const wchar_t * str,
- khm_size max_cch,
- khm_size * len_cch);
-
-/*! \brief Get the number of strings in a multi string
- */
-KHMEXP khm_size KHMAPI
-multi_string_length_n(const wchar_t * str);
-
-/*! \brief Copy a multi string with byte counts
-
- Copy a multi string from one location to another.
-
- \param[out] s_dest Receives a copy of the multi string
- \param[in] max_cb_dest Number of bytes in the buffer pointed to by
- \a s_dest.
- \param[in] src The source multi string
-
- \retval KHM_ERROR_SUCCESS The multi string was copied successfully
- \retval KHM_ERROR_INVALID_PARAM One or more parameters were
- invalid.
- \retval KHM_ERROR_TOO_LONG The size of the destination buffer was
- insufficient.
- */
-KHMEXP khm_int32 KHMAPI
-multi_string_copy_cb(wchar_t * s_dest,
- khm_size max_cb_dest,
- const wchar_t * src);
-
-/*! \brief Copy a multi string with character count
-
- Copy a multi string from one location to another.
-
- \param[out] s_dest Receives a copy of the multi string
- \param[in] max_cb_dest Number of characters in the buffer pointed
- to by \a s_dest.
- \param[in] src The source multi string
-
- \retval KHM_ERROR_SUCCESS The multi string was copied successfully
- \retval KHM_ERROR_INVALID_PARAM One or more parameters were
- invalid.
- \retval KHM_ERROR_TOO_LONG The size of the destination buffer was
- insufficient.
- */
-KHMEXP khm_int32 KHMAPI
-multi_string_copy_cch(wchar_t * s_dest,
- khm_size max_cch_dest,
- const wchar_t * src);
-
-/*@}*/
-
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __KHIMAIRA_MSTRING_H
+#define __KHIMAIRA_MSTRING_H
+
+#include<khdefs.h>
+
+/*! \addtogroup util
+ @{ */
+
+/*! \defgroup util_mstring Multi String and CSV functions
+ @{*/
+
+#define KHM_PREFIX 8
+
+#define KHM_CASE_SENSITIVE 16
+
+#define KHM_MAXCCH_STRING 16384
+
+#define KHM_MAXCB_STRING (KHM_MAXCCH_STRING * sizeof(wchar_t))
+
+/*! \brief Initialize a multi-string
+ */
+KHMEXP khm_int32 KHMAPI
+multi_string_init(wchar_t * ms,
+ khm_size cb_ms);
+
+/*! \brief Prepend a string to a multi string
+
+ Adds the string \a str to the beginning of multi-string \a ms.
+
+ \param[in,out] ms The multi-string to be modified.
+
+ \param[in,out] pcb_ms A pointer to the size of the multistring.
+ On entry this specifies the size of the buffer pointed to by
+ \a ms. If the call is successful, on exit this will receive
+ the new size of the multi string in bytes. If the buffer is
+ insufficient, the function will return KHM_ERROR_TOO_LONG and
+ set this to the required size of the buffer in bytes.
+
+ \param[in] str The string to prepend to \a ms. This cannot be
+ longer than KHM_MAXCCH_STRING in characters including the
+ terminating NULL.
+ */
+KHMEXP khm_int32 KHMAPI
+multi_string_prepend(wchar_t * ms,
+ khm_size * pcb_ms,
+ const wchar_t * str);
+
+/*! \brief Append a string to a multi-string
+
+ Appends the string specified by \a str to the multi string
+ specified by \a ms. The size of the multi string in characters
+ including terminating NULLs after appending \a str can not exceed
+ KHM_MAXCCH_STRING.
+
+ \param[in] ms The buffer containing the multi string
+
+ \param[in,out] pcb_ms Points to a khm_int32 indicating the size of
+ the buffer pointed to by \a ms. On entry this contains the
+ size (in bytes) of the buffer pointed to by \a ms. On exit,
+ contains the new size of the multi string in bytes.
+
+ \param[in] str The string to append to the multi string. This
+ string cannot be NULL or an empty (zero length) string. The
+ length of \a str cannot exceed KHM_MAXCCH_STRING in
+ characters including terminating NULL.
+
+ \retval KHM_ERROR_SUCCESS The string was appended to the multi string
+
+ \retval KHM_ERROR_TOO_LONG The buffer pointed to by \a ms was
+ insufficient. The required size of the buffer is in \a pcb_ms
+
+ \retval KHM_ERROR_INVALID_PARAM One of more of the parameters were invalid.
+ */
+KHMEXP khm_int32 KHMAPI
+multi_string_append(wchar_t * ms,
+ khm_size * pcb_ms,
+ const wchar_t * str);
+
+/*! \brief Deletes a string from a multi string
+
+ Deletes the string specified by \a str from the multi string
+ specified by \a ms. How the string is matched to the strings in
+ \a ms is determined by \a flags. If more than one match is found,
+ then only the first match is deleted.
+
+ \param[in] ms The multi string to modify. The length of the multi
+ string in characters cannot exceed KHM_MAXCCH_STRING.
+
+ \param[in] str The string to search for
+
+ \param[in] flags How \a str is to be matched to existing strings
+ in \a ms. This could be a combination of KHM_PREFIX and
+ KHM_CASE_SENSITIVE. If KHM_PREFIX is used, then \a ms is
+ searched for a string that begins with \a str. Otherwise, \a
+ str must match the an entire string in the multi string. If
+ KHM_CASE_SENSITIVE is specified, then a case sensitive match
+ is performed. The defualt is to use a case insensitive
+ search.
+
+ \retval KHM_ERROR_SUCCESS A string was matched and deleted from \a ms
+
+ \retval KHM_ERROR_NOT_FOUND No matches were found
+
+ \retval KHM_ERROR_INVALID_PARAM One or more parameters were incorrect.
+
+ \note The search for the existing string is done with
+ multi_string_find()
+ */
+KHMEXP khm_int32 KHMAPI
+multi_string_delete(wchar_t * ms,
+ const wchar_t * str,
+ const khm_int32 flags);
+
+/*! \brief Search a multi string for a string
+
+ Searches the string specified by \a ms for a string that matches
+ \a str. How the match is performed is determined by \a flags.
+ Returns a poitner to the start of the matched string in \a ms. If
+ more than one string in \a ms matches \a str, then only the first
+ match is returned.
+
+ \param[in] ms The multi string to search in. The length of the
+ multi string cannot exceed KHM_MAXCCH_STRING in characters.
+
+ \param[in] str The string to search for
+
+ \param[in] flags How \a str is to be matched to existing strings
+ in \a ms. This could be a combination of KHM_PREFIX and
+ KHM_CASE_SENSITIVE. If KHM_PREFIX is used, then \a ms is
+ searched for a string that begins with \a str. Otherwise, \a
+ str must match the an entire string in the multi string. If
+ KHM_CASE_SENSITIVE is specified, then a case sensitive match
+ is performed. The defualt is to use a case insensitive
+ search.
+
+ \return A pointer to the start of the first matched string or
+ NULL if no matches were found.
+
+ */
+KHMEXP wchar_t * KHMAPI
+multi_string_find(const wchar_t * ms,
+ const wchar_t * str,
+ const khm_int32 flags);
+
+/*! \brief Convert a multi string to CSV
+
+ Converts a multi string to a comma separated value string based on
+ the following rules.
+
+ - Each string in the multi string is treated an individual field
+
+ - A field is quoted if it has double quotes or commas
+
+ - Double quotes within quoted fields are escaped by two
+ consecutive double quotes.
+
+ For example:
+
+ \code
+ multi_string = L"foo\0bar\0baz,quux\0ab\"cd\0";
+ csv_string = L"foo,bar,\"baz,quux\",\"ab\"\"cd\"";
+ \endcode
+
+ If multi_string_to_csv() is called on \a multi_string above,
+ you would obtain \a csv_string.
+
+ \param[out] csvbuf The buffer to place the CSV string in. Can be
+ NULL if only teh size of the needed buffer is required.
+
+ \param[in,out] pcb_csvbuf On entry, points to a khm_int32 that
+ holds the size of the buffer pointed to by \a csvbuf. On
+ exit, gets the number of bytes writted to \a csvbuf or the
+ required size of \a csvbuf if the buffer is too small or \a
+ csvbuf is NULL.
+
+ \param[in] ms The mutli string to convert to a CSV.
+
+ \retval KHM_ERROR_SUCCESS The multi string was successfully
+ converted to a CSV string. The number of bytes written is in
+ \a pcb_csvbuf. The count includes the terminating NULL.
+
+ \retval KHM_ERROR_TOO_LONG The buffer was too small or \a csvbuf
+ was NULL. The required number of bytes in the buffer is in \a
+ pcb_csvbuf.
+
+ \retval KHM_ERROR_INVALID_PARAM One or more parameters were ivnalid.
+
+ \see csv_to_multi_string()
+*/
+KHMEXP khm_int32 KHMAPI
+multi_string_to_csv(wchar_t * csvbuf,
+ khm_size * pcb_csvbuf,
+ const wchar_t * ms);
+
+/*! \brief Converts a CSV to a multi string
+
+ Undoes what multi_string_to_csv() does.
+
+ \param[out] ms The buffer that recieves the multi string. This
+ can be NULL if only the size of the buffer is requried.
+
+ \param[in,out] pcb_ms On entry contains the number of bytes ni the
+ buffer poitned to by \a ms. On exit contains the number of
+ bytes that were copied to \a ms including terminating NULLs,
+ or if the buffer was too small or \a ms was NULL, holds the
+ size in bytes of the requied buffer.
+
+ \param[in] csv The CSV string.
+
+ \retval KHM_ERROR_SUCCESS The CSV string was successfully
+ converted. The number of bytes written is in \a pcb_ms.
+
+ \retval KHM_ERROR_TOO_LONG The provided buffer was too small or \a
+ ms was NULL. The required size of the buffer in bytes is in \a
+ pcb_ms.
+
+ \retval KHM_ERROR_INVALID_PARAM One or more parameters were invalid.
+
+ */
+KHMEXP khm_int32 KHMAPI
+csv_to_multi_string(wchar_t * ms,
+ khm_size * pcb_ms,
+ const wchar_t * csv);
+
+/*! \brief Get the next string in a multi string
+
+ When \a str is pointing to a string that is in a multi string,
+ this function returns a pointer to the next string in the multi
+ string.
+
+ Typically, one would start by having \a str point to the start of
+ the multi string (which is the first string in the multi string),
+ and then call this function repeatedly, until it returns NULL, at
+ which point the end of the multi string has been reached.
+
+ \param[in] str Pointer to a string in a multi string. Each string
+ in a multi string cannot exceed KHM_MAXCCH_STRING in charaters
+ including the terminating NULL.
+
+ \return A pointer to the start of the next string in the multi
+ string or NULL if there is no more strings.
+ */
+KHMEXP wchar_t * KHMAPI
+multi_string_next(const wchar_t * str);
+
+/*! \brief Get the length of a multi string in bytes
+
+ The returned length includes the trailing double \a NULL and any
+ other \a NULL inbetween.
+
+ \param[in] str Pointer to a multi string.
+ \param[in] max_cb Maximum size that the str can be. This can not
+ be larger than KHM_MAXCB_STRING.
+ \param[out] len_cb The length of the string in bytes if the call
+ is successful.
+
+ \retval KHM_ERROR_SUCCESS The length of the string is in \a len_cb
+ \retval KHM_ERROR_INVALID_PARAM One or more parameters were invalid
+ \retval KHM_ERROR_TOO_LONG The multi string is longer than \a
+ max_cb bytes.
+ */
+KHMEXP khm_int32 KHMAPI
+multi_string_length_cb(const wchar_t * str,
+ khm_size max_cb,
+ khm_size * len_cb);
+
+/*! \brief Get the length of a multi string in characters
+
+ The returned length includes the trailing double \a NULL and any
+ other \a NULL inbetween.
+
+ \param[in] str Pointer to a multi string.
+ \param[in] max_cch Maximum size that the str can be. This can not
+ be larger than KHM_MAXCCH_STRING.
+ \param[out] len_cch The length of the string in characters if the call
+ is successful.
+
+ \retval KHM_ERROR_SUCCESS The length of the string is in \a len_cch
+ \retval KHM_ERROR_INVALID_PARAM One or more parameters were invalid
+ \retval KHM_ERROR_TOO_LONG The multi string is longer than \a
+ max_cch characters.
+ */
+KHMEXP khm_int32 KHMAPI
+multi_string_length_cch(const wchar_t * str,
+ khm_size max_cch,
+ khm_size * len_cch);
+
+/*! \brief Get the number of strings in a multi string
+ */
+KHMEXP khm_size KHMAPI
+multi_string_length_n(const wchar_t * str);
+
+/*! \brief Copy a multi string with byte counts
+
+ Copy a multi string from one location to another.
+
+ \param[out] s_dest Receives a copy of the multi string
+ \param[in] max_cb_dest Number of bytes in the buffer pointed to by
+ \a s_dest.
+ \param[in] src The source multi string
+
+ \retval KHM_ERROR_SUCCESS The multi string was copied successfully
+ \retval KHM_ERROR_INVALID_PARAM One or more parameters were
+ invalid.
+ \retval KHM_ERROR_TOO_LONG The size of the destination buffer was
+ insufficient.
+ */
+KHMEXP khm_int32 KHMAPI
+multi_string_copy_cb(wchar_t * s_dest,
+ khm_size max_cb_dest,
+ const wchar_t * src);
+
+/*! \brief Copy a multi string with character count
+
+ Copy a multi string from one location to another.
+
+ \param[out] s_dest Receives a copy of the multi string
+ \param[in] max_cb_dest Number of characters in the buffer pointed
+ to by \a s_dest.
+ \param[in] src The source multi string
+
+ \retval KHM_ERROR_SUCCESS The multi string was copied successfully
+ \retval KHM_ERROR_INVALID_PARAM One or more parameters were
+ invalid.
+ \retval KHM_ERROR_TOO_LONG The size of the destination buffer was
+ insufficient.
+ */
+KHMEXP khm_int32 KHMAPI
+multi_string_copy_cch(wchar_t * s_dest,
+ khm_size max_cch_dest,
+ const wchar_t * src);
+
+/*@}*/
+
+#endif
diff --git a/src/windows/identity/util/perfstat.c b/src/windows/identity/util/perfstat.c
index cc27d93bd0..6a9dd81034 100644
--- a/src/windows/identity/util/perfstat.c
+++ b/src/windows/identity/util/perfstat.c
@@ -1,411 +1,411 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<windows.h>
-#include<utils.h>
-#include<malloc.h>
-#include<stdio.h>
-#include<strsafe.h>
-#include<assert.h>
-
-#define HASHSIZE 1151
-#define ALLOCBLOCK 1024
-
-#define HASHPTR(p) (((size_t) (p)) % HASHSIZE)
-
-typedef struct tag_allocation {
- const char * file;
- int line;
- size_t size;
- void * ptr;
-#ifdef _WIN32
- DWORD thread;
-#endif
-
- LDCL(struct tag_allocation);
-} allocation;
-
-static allocation * ht[HASHSIZE];
-
-static allocation * next_alloc = NULL;
-static size_t idx_next_alloc = 0;
-static allocation * free_alloc = NULL;
-
-typedef struct tag_thread_info {
-#ifdef _WIN32
- DWORD thread;
-#else
-#error Unsupported platform
-#endif
- wchar_t name[128];
- wchar_t creator[128];
-
- const char * file;
- int line;
-
- LDCL(struct tag_thread_info);
-} thread_info;
-
-static thread_info * threads = NULL;
-
-static hashtable fn_hash;
-
-static CRITICAL_SECTION cs_alloc;
-static LONG ctr = 0;
-static int perf_ready = 0;
-
-static DWORD init_thread = 0;
-
-static khm_int32 hash_stringA(const void * vs) {
- /* DJB algorithm */
-
- khm_int32 hv = 13331;
- char * c;
-
- for (c = (char *) vs; *c; c++) {
- hv = ((hv << 5) + hv) + (khm_int32) *c;
- }
-
- return (hv & KHM_INT32_MAX);
-}
-
-static khm_int32 hash_string_compA(const void * vs1,
- const void * vs2) {
- return strcmp((const char *) vs1, (const char *) vs2);
-}
-
-static void perf_once(void) {
- if (InterlockedIncrement(&ctr) == 1) {
- InitializeCriticalSection(&cs_alloc);
- ZeroMemory(ht, sizeof(ht));
-
- next_alloc = malloc(sizeof(allocation) * ALLOCBLOCK);
- assert(next_alloc);
- idx_next_alloc = 0;
- free_alloc = NULL;
-
- ZeroMemory(&fn_hash, sizeof(fn_hash));
- fn_hash.n = 13;
- fn_hash.hash = hash_stringA;
- fn_hash.comp = hash_string_compA;
- fn_hash.bins = calloc(sizeof(hash_bin *), fn_hash.n);
-
- perf_ready = 1;
- } else {
- DWORD this_thread = GetCurrentThreadId();
-
- while(!perf_ready &&
- init_thread != this_thread) {
- Sleep(0); /* relinquish control to the thread
- that is initializing the alloc
- data. */
- }
- }
-}
-
-static allocation * get_allocation(void) {
- allocation * a;
-
- LPOP(&free_alloc, &a);
- if (!a) {
- if (idx_next_alloc == ALLOCBLOCK) {
- next_alloc = malloc(sizeof(allocation) * ALLOCBLOCK);
- assert(next_alloc);
- idx_next_alloc = 0;
- }
-
- a = &next_alloc[idx_next_alloc];
- idx_next_alloc++;
- }
-
- return a;
-}
-
-#define MAXCB_STR 32768
-
-KHMEXP wchar_t *
-perf_wcsdup(const char * file, int line, const wchar_t * str) {
- size_t cb;
- wchar_t * dest;
-
- if (FAILED(StringCbLength(str, MAXCB_STR, &cb)))
- return NULL;
- cb += sizeof(wchar_t);
-
- dest = (wchar_t *) perf_malloc(file, line, cb);
- StringCbCopy(dest, cb, str);
-
- return dest;
-}
-
-KHMEXP char *
-perf_strdup(const char * file, int line, const char * str) {
- size_t cb;
- char * dest;
-
- if (FAILED(StringCbLengthA(str, MAXCB_STR, &cb)))
- return NULL;
- cb += sizeof(char);
-
- dest = (char *) perf_malloc(file, line, cb);
- StringCbCopyA(dest, cb, str);
-
- return dest;
-}
-
-KHMEXP void *
-perf_calloc(const char * file, int line, size_t num, size_t size) {
- void * ptr;
- size_t tsize;
-
- tsize = num * size;
-
- ptr = perf_malloc(file,line,tsize);
-
- if (ptr) {
- ZeroMemory(ptr, tsize);
- }
-
- return ptr;
-}
-
-KHMEXP void *
-perf_malloc(const char * file, int line, size_t s) {
- allocation * a;
- void * ptr;
- size_t h;
- char * fn_copy = NULL;
-
- perf_once();
-
- assert(s > 0);
-
- EnterCriticalSection(&cs_alloc);
- a = get_allocation();
-
- ptr = malloc(s);
-
- assert(ptr); /* TODO: handle this gracefully */
-
- if (file[0] == '.' && file[1] == '\\')
- file += 2;
-
- fn_copy = hash_lookup(&fn_hash, file);
- if (fn_copy == NULL) {
-
- size_t cblen = 0;
- if (FAILED(StringCbLengthA(file, MAX_PATH * sizeof(char),
- &cblen)))
- fn_copy = NULL;
- else {
- fn_copy = malloc(cblen + sizeof(char));
- if (fn_copy) {
- hash_bin * b;
- int hv;
-
- StringCbCopyA(fn_copy, cblen + sizeof(char), file);
-
- hv = fn_hash.hash(fn_copy) % fn_hash.n;
-
- b = malloc(sizeof(*b));
- b->data = fn_copy;
- b->key = fn_copy;
- LINIT(b);
- LPUSH(&fn_hash.bins[hv], b);
- }
- }
- }
-
- a->file = fn_copy;
- a->line = line;
- a->size = s;
- a->ptr = ptr;
-#ifdef _WIN32
- a->thread = GetCurrentThreadId();
-#endif
-
- h = HASHPTR(ptr);
-
- LPUSH(&ht[h], a);
- LeaveCriticalSection(&cs_alloc);
-
- return ptr;
-}
-
-KHMEXP void *
-perf_realloc(const char * file, int line, void * data, size_t s) {
- void * n_data;
- allocation * a;
- size_t h;
-
- if (data == NULL)
- return perf_malloc(file, line, s);
-
- perf_once();
- h = HASHPTR(data);
-
- n_data = realloc(data, s);
-
- assert(n_data);
-
- EnterCriticalSection(&cs_alloc);
- for (a = ht[h]; a; a = LNEXT(a)) {
- if (a->ptr == data)
- break;
- }
-
- assert(a);
-
- LDELETE(&ht[h], a);
-
- a->size = s;
- a->ptr = n_data;
-
- h = HASHPTR(n_data);
- LPUSH(&ht[h], a);
- LeaveCriticalSection(&cs_alloc);
-
- return n_data;
-}
-
-KHMEXP void
-perf_free (void * b) {
- size_t h;
- allocation * a;
-
- perf_once();
- h = HASHPTR(b);
-
- EnterCriticalSection(&cs_alloc);
- for(a = ht[h]; a; a = LNEXT(a)) {
- if (a->ptr == b)
- break;
- }
-
- assert(a);
-
- LDELETE(&ht[h], a);
- LPUSH(&free_alloc, a);
- LeaveCriticalSection(&cs_alloc);
-}
-
-KHMEXP void KHMAPI
-perf_dump(FILE * f) {
- size_t i;
- allocation * a;
- size_t total = 0;
- thread_info * t;
-
- perf_once();
-
- EnterCriticalSection(&cs_alloc);
-
- fprintf(f, "p00\t*** Threads ***\n");
- fprintf(f, "p00\tFile\tLine\tThread\tName\tCreated by\n");
-
- for (t = threads; t; t = LNEXT(t)) {
- fprintf(f, "p01\t%s\t%6d\t%6d\t%S\t%S\n",
- t->file, t->line, t->thread,
- t->name, t->creator);
- }
-
- fprintf(f, "p02\t--- End Threads ---\n");
-
- fprintf(f, "p10\t*** Leaked allocations list ***\n");
- fprintf(f, "p11\tFile\tLine\tThread\tSize\tAddress\n");
-
- for (i=0; i < HASHSIZE; i++) {
- for (a = ht[i]; a; a = LNEXT(a)) {
- fprintf(f, "p12\t%s\t%6d\t%6d\t%6d\t0x%p\n", a->file, a->line,
- a->thread, a->size, a->ptr);
- total += a->size;
- }
- }
-
- fprintf(f, "p20\t----------------------------------------\n");
- fprintf(f, "p21\tTotal\t\t%d\n", total);
- fprintf(f, "p22\t----------------- End ------------------\n");
-
- LeaveCriticalSection(&cs_alloc);
-}
-
-KHMEXP void
-perf_set_thread_desc(const char * file, int line,
- const wchar_t * name, const wchar_t * creator) {
- thread_info * t;
- char * fn_copy;
-
- perf_once();
-
- t = malloc(sizeof(*t));
- ZeroMemory(t, sizeof(*t));
-
-#ifdef _WIN32
- t->thread = GetCurrentThreadId();
-#else
-#error Unsupported platform
-#endif
-
- StringCbCopy(t->name, sizeof(t->name), name);
- if (creator)
- StringCbCopy(t->creator, sizeof(t->creator), creator);
-
- if (file[0] == '.' && file[1] == '\\')
- file += 2;
-
- EnterCriticalSection(&cs_alloc);
-
- fn_copy = hash_lookup(&fn_hash, file);
- if (fn_copy == NULL) {
- size_t cblen = 0;
- if (FAILED(StringCbLengthA(file, MAX_PATH * sizeof(char),
- &cblen)))
- fn_copy = NULL;
- else {
- fn_copy = malloc(cblen + sizeof(char));
- if (fn_copy) {
- hash_bin * b;
- int hv;
-
- StringCbCopyA(fn_copy, cblen + sizeof(char), file);
-
- hv = fn_hash.hash(fn_copy) % fn_hash.n;
-
- b = malloc(sizeof(*b));
- b->data = fn_copy;
- b->key = fn_copy;
- LINIT(b);
- LPUSH(&fn_hash.bins[hv], b);
- }
- }
- }
-
- t->file = fn_copy;
- t->line = line;
-
- LPUSH(&threads, t);
- LeaveCriticalSection(&cs_alloc);
-}
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<windows.h>
+#include<utils.h>
+#include<malloc.h>
+#include<stdio.h>
+#include<strsafe.h>
+#include<assert.h>
+
+#define HASHSIZE 1151
+#define ALLOCBLOCK 1024
+
+#define HASHPTR(p) (((size_t) (p)) % HASHSIZE)
+
+typedef struct tag_allocation {
+ const char * file;
+ int line;
+ size_t size;
+ void * ptr;
+#ifdef _WIN32
+ DWORD thread;
+#endif
+
+ LDCL(struct tag_allocation);
+} allocation;
+
+static allocation * ht[HASHSIZE];
+
+static allocation * next_alloc = NULL;
+static size_t idx_next_alloc = 0;
+static allocation * free_alloc = NULL;
+
+typedef struct tag_thread_info {
+#ifdef _WIN32
+ DWORD thread;
+#else
+#error Unsupported platform
+#endif
+ wchar_t name[128];
+ wchar_t creator[128];
+
+ const char * file;
+ int line;
+
+ LDCL(struct tag_thread_info);
+} thread_info;
+
+static thread_info * threads = NULL;
+
+static hashtable fn_hash;
+
+static CRITICAL_SECTION cs_alloc;
+static LONG ctr = 0;
+static int perf_ready = 0;
+
+static DWORD init_thread = 0;
+
+static khm_int32 hash_stringA(const void * vs) {
+ /* DJB algorithm */
+
+ khm_int32 hv = 13331;
+ char * c;
+
+ for (c = (char *) vs; *c; c++) {
+ hv = ((hv << 5) + hv) + (khm_int32) *c;
+ }
+
+ return (hv & KHM_INT32_MAX);
+}
+
+static khm_int32 hash_string_compA(const void * vs1,
+ const void * vs2) {
+ return strcmp((const char *) vs1, (const char *) vs2);
+}
+
+static void perf_once(void) {
+ if (InterlockedIncrement(&ctr) == 1) {
+ InitializeCriticalSection(&cs_alloc);
+ ZeroMemory(ht, sizeof(ht));
+
+ next_alloc = malloc(sizeof(allocation) * ALLOCBLOCK);
+ assert(next_alloc);
+ idx_next_alloc = 0;
+ free_alloc = NULL;
+
+ ZeroMemory(&fn_hash, sizeof(fn_hash));
+ fn_hash.n = 13;
+ fn_hash.hash = hash_stringA;
+ fn_hash.comp = hash_string_compA;
+ fn_hash.bins = calloc(sizeof(hash_bin *), fn_hash.n);
+
+ perf_ready = 1;
+ } else {
+ DWORD this_thread = GetCurrentThreadId();
+
+ while(!perf_ready &&
+ init_thread != this_thread) {
+ Sleep(0); /* relinquish control to the thread
+ that is initializing the alloc
+ data. */
+ }
+ }
+}
+
+static allocation * get_allocation(void) {
+ allocation * a;
+
+ LPOP(&free_alloc, &a);
+ if (!a) {
+ if (idx_next_alloc == ALLOCBLOCK) {
+ next_alloc = malloc(sizeof(allocation) * ALLOCBLOCK);
+ assert(next_alloc);
+ idx_next_alloc = 0;
+ }
+
+ a = &next_alloc[idx_next_alloc];
+ idx_next_alloc++;
+ }
+
+ return a;
+}
+
+#define MAXCB_STR 32768
+
+KHMEXP wchar_t *
+perf_wcsdup(const char * file, int line, const wchar_t * str) {
+ size_t cb;
+ wchar_t * dest;
+
+ if (FAILED(StringCbLength(str, MAXCB_STR, &cb)))
+ return NULL;
+ cb += sizeof(wchar_t);
+
+ dest = (wchar_t *) perf_malloc(file, line, cb);
+ StringCbCopy(dest, cb, str);
+
+ return dest;
+}
+
+KHMEXP char *
+perf_strdup(const char * file, int line, const char * str) {
+ size_t cb;
+ char * dest;
+
+ if (FAILED(StringCbLengthA(str, MAXCB_STR, &cb)))
+ return NULL;
+ cb += sizeof(char);
+
+ dest = (char *) perf_malloc(file, line, cb);
+ StringCbCopyA(dest, cb, str);
+
+ return dest;
+}
+
+KHMEXP void *
+perf_calloc(const char * file, int line, size_t num, size_t size) {
+ void * ptr;
+ size_t tsize;
+
+ tsize = num * size;
+
+ ptr = perf_malloc(file,line,tsize);
+
+ if (ptr) {
+ ZeroMemory(ptr, tsize);
+ }
+
+ return ptr;
+}
+
+KHMEXP void *
+perf_malloc(const char * file, int line, size_t s) {
+ allocation * a;
+ void * ptr;
+ size_t h;
+ char * fn_copy = NULL;
+
+ perf_once();
+
+ assert(s > 0);
+
+ EnterCriticalSection(&cs_alloc);
+ a = get_allocation();
+
+ ptr = malloc(s);
+
+ assert(ptr); /* TODO: handle this gracefully */
+
+ if (file[0] == '.' && file[1] == '\\')
+ file += 2;
+
+ fn_copy = hash_lookup(&fn_hash, file);
+ if (fn_copy == NULL) {
+
+ size_t cblen = 0;
+ if (FAILED(StringCbLengthA(file, MAX_PATH * sizeof(char),
+ &cblen)))
+ fn_copy = NULL;
+ else {
+ fn_copy = malloc(cblen + sizeof(char));
+ if (fn_copy) {
+ hash_bin * b;
+ int hv;
+
+ StringCbCopyA(fn_copy, cblen + sizeof(char), file);
+
+ hv = fn_hash.hash(fn_copy) % fn_hash.n;
+
+ b = malloc(sizeof(*b));
+ b->data = fn_copy;
+ b->key = fn_copy;
+ LINIT(b);
+ LPUSH(&fn_hash.bins[hv], b);
+ }
+ }
+ }
+
+ a->file = fn_copy;
+ a->line = line;
+ a->size = s;
+ a->ptr = ptr;
+#ifdef _WIN32
+ a->thread = GetCurrentThreadId();
+#endif
+
+ h = HASHPTR(ptr);
+
+ LPUSH(&ht[h], a);
+ LeaveCriticalSection(&cs_alloc);
+
+ return ptr;
+}
+
+KHMEXP void *
+perf_realloc(const char * file, int line, void * data, size_t s) {
+ void * n_data;
+ allocation * a;
+ size_t h;
+
+ if (data == NULL)
+ return perf_malloc(file, line, s);
+
+ perf_once();
+ h = HASHPTR(data);
+
+ n_data = realloc(data, s);
+
+ assert(n_data);
+
+ EnterCriticalSection(&cs_alloc);
+ for (a = ht[h]; a; a = LNEXT(a)) {
+ if (a->ptr == data)
+ break;
+ }
+
+ assert(a);
+
+ LDELETE(&ht[h], a);
+
+ a->size = s;
+ a->ptr = n_data;
+
+ h = HASHPTR(n_data);
+ LPUSH(&ht[h], a);
+ LeaveCriticalSection(&cs_alloc);
+
+ return n_data;
+}
+
+KHMEXP void
+perf_free (void * b) {
+ size_t h;
+ allocation * a;
+
+ perf_once();
+ h = HASHPTR(b);
+
+ EnterCriticalSection(&cs_alloc);
+ for(a = ht[h]; a; a = LNEXT(a)) {
+ if (a->ptr == b)
+ break;
+ }
+
+ assert(a);
+
+ LDELETE(&ht[h], a);
+ LPUSH(&free_alloc, a);
+ LeaveCriticalSection(&cs_alloc);
+}
+
+KHMEXP void KHMAPI
+perf_dump(FILE * f) {
+ size_t i;
+ allocation * a;
+ size_t total = 0;
+ thread_info * t;
+
+ perf_once();
+
+ EnterCriticalSection(&cs_alloc);
+
+ fprintf(f, "p00\t*** Threads ***\n");
+ fprintf(f, "p00\tFile\tLine\tThread\tName\tCreated by\n");
+
+ for (t = threads; t; t = LNEXT(t)) {
+ fprintf(f, "p01\t%s\t%6d\t%6d\t%S\t%S\n",
+ t->file, t->line, t->thread,
+ t->name, t->creator);
+ }
+
+ fprintf(f, "p02\t--- End Threads ---\n");
+
+ fprintf(f, "p10\t*** Leaked allocations list ***\n");
+ fprintf(f, "p11\tFile\tLine\tThread\tSize\tAddress\n");
+
+ for (i=0; i < HASHSIZE; i++) {
+ for (a = ht[i]; a; a = LNEXT(a)) {
+ fprintf(f, "p12\t%s\t%6d\t%6d\t%6d\t0x%p\n", a->file, a->line,
+ a->thread, a->size, a->ptr);
+ total += a->size;
+ }
+ }
+
+ fprintf(f, "p20\t----------------------------------------\n");
+ fprintf(f, "p21\tTotal\t\t%d\n", total);
+ fprintf(f, "p22\t----------------- End ------------------\n");
+
+ LeaveCriticalSection(&cs_alloc);
+}
+
+KHMEXP void
+perf_set_thread_desc(const char * file, int line,
+ const wchar_t * name, const wchar_t * creator) {
+ thread_info * t;
+ char * fn_copy;
+
+ perf_once();
+
+ t = malloc(sizeof(*t));
+ ZeroMemory(t, sizeof(*t));
+
+#ifdef _WIN32
+ t->thread = GetCurrentThreadId();
+#else
+#error Unsupported platform
+#endif
+
+ StringCbCopy(t->name, sizeof(t->name), name);
+ if (creator)
+ StringCbCopy(t->creator, sizeof(t->creator), creator);
+
+ if (file[0] == '.' && file[1] == '\\')
+ file += 2;
+
+ EnterCriticalSection(&cs_alloc);
+
+ fn_copy = hash_lookup(&fn_hash, file);
+ if (fn_copy == NULL) {
+ size_t cblen = 0;
+ if (FAILED(StringCbLengthA(file, MAX_PATH * sizeof(char),
+ &cblen)))
+ fn_copy = NULL;
+ else {
+ fn_copy = malloc(cblen + sizeof(char));
+ if (fn_copy) {
+ hash_bin * b;
+ int hv;
+
+ StringCbCopyA(fn_copy, cblen + sizeof(char), file);
+
+ hv = fn_hash.hash(fn_copy) % fn_hash.n;
+
+ b = malloc(sizeof(*b));
+ b->data = fn_copy;
+ b->key = fn_copy;
+ LINIT(b);
+ LPUSH(&fn_hash.bins[hv], b);
+ }
+ }
+ }
+
+ t->file = fn_copy;
+ t->line = line;
+
+ LPUSH(&threads, t);
+ LeaveCriticalSection(&cs_alloc);
+}
diff --git a/src/windows/identity/util/perfstat.h b/src/windows/identity/util/perfstat.h
index a4a0f2750f..816a13681e 100644
--- a/src/windows/identity/util/perfstat.h
+++ b/src/windows/identity/util/perfstat.h
@@ -1,74 +1,74 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#ifndef __KHIMAIRA_PERFSTAT_H
-#define __KHIMAIRA_PERFSTAT_H
-
-#include<khdefs.h>
-
-#ifdef DEBUG
-#define PMALLOC(s) perf_malloc(__FILE__,__LINE__,s)
-#define PCALLOC(n,s) perf_calloc(__FILE__,__LINE__,n,s)
-#define PREALLOC(d,s) perf_realloc(__FILE__,__LINE__,d,s)
-#define PFREE(p) perf_free(p)
-#define PDUMP(f) perf_dump(f)
-#define PWCSDUP(s) perf_wcsdup(__FILE__,__LINE__,s)
-#define PSTRDUP(s) perf_strdup(__FILE__,__LINE__,s)
-#define PDESCTHREAD(n,c) perf_set_thread_desc(__FILE__,__LINE__,n,c);
-#else
-#define PMALLOC(s) malloc(s)
-#define PCALLOC(n,s) calloc(n,s)
-#define PREALLOC(d,s) realloc(d,s)
-#define PFREE(p) free(p)
-#define PDUMP(f) ((void) 0)
-#define PWCSDUP(s) wcsdup(s)
-#define PSTRDUP(s) strdup(s)
-#define PDESCTHREAD(n,c)
-#endif
-
-KHMEXP void *
-perf_malloc(const char * file, int line, size_t s);
-
-KHMEXP void *
-perf_realloc(const char * file, int line, void * data, size_t s);
-
-KHMEXP void
-perf_free (void * b);
-
-KHMEXP wchar_t *
-perf_wcsdup(const char * file, int line, const wchar_t * str);
-
-KHMEXP char *
-perf_strdup(const char * file, int line, const char * str);
-
-KHMEXP void *
-perf_calloc(const char * file, int line, size_t num, size_t size);
-
-KHMEXP void
-perf_set_thread_desc(const char * file, int line,
- const wchar_t * name, const wchar_t * creator);
-
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __KHIMAIRA_PERFSTAT_H
+#define __KHIMAIRA_PERFSTAT_H
+
+#include<khdefs.h>
+
+#ifdef DEBUG
+#define PMALLOC(s) perf_malloc(__FILE__,__LINE__,s)
+#define PCALLOC(n,s) perf_calloc(__FILE__,__LINE__,n,s)
+#define PREALLOC(d,s) perf_realloc(__FILE__,__LINE__,d,s)
+#define PFREE(p) perf_free(p)
+#define PDUMP(f) perf_dump(f)
+#define PWCSDUP(s) perf_wcsdup(__FILE__,__LINE__,s)
+#define PSTRDUP(s) perf_strdup(__FILE__,__LINE__,s)
+#define PDESCTHREAD(n,c) perf_set_thread_desc(__FILE__,__LINE__,n,c);
+#else
+#define PMALLOC(s) malloc(s)
+#define PCALLOC(n,s) calloc(n,s)
+#define PREALLOC(d,s) realloc(d,s)
+#define PFREE(p) free(p)
+#define PDUMP(f) ((void) 0)
+#define PWCSDUP(s) wcsdup(s)
+#define PSTRDUP(s) strdup(s)
+#define PDESCTHREAD(n,c)
+#endif
+
+KHMEXP void *
+perf_malloc(const char * file, int line, size_t s);
+
+KHMEXP void *
+perf_realloc(const char * file, int line, void * data, size_t s);
+
+KHMEXP void
+perf_free (void * b);
+
+KHMEXP wchar_t *
+perf_wcsdup(const char * file, int line, const wchar_t * str);
+
+KHMEXP char *
+perf_strdup(const char * file, int line, const char * str);
+
+KHMEXP void *
+perf_calloc(const char * file, int line, size_t num, size_t size);
+
+KHMEXP void
+perf_set_thread_desc(const char * file, int line,
+ const wchar_t * name, const wchar_t * creator);
+
+#endif
diff --git a/src/windows/identity/util/sync.c b/src/windows/identity/util/sync.c
index d811eb99da..c829ada7c9 100644
--- a/src/windows/identity/util/sync.c
+++ b/src/windows/identity/util/sync.c
@@ -1,130 +1,130 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#include<windows.h>
-#include<sync.h>
-#include<assert.h>
-
-#define LOCK_OPEN 0
-#define LOCK_READING 1
-#define LOCK_WRITING 2
-
-KHMEXP void KHMAPI InitializeRwLock(PRWLOCK pLock)
-{
- pLock->locks = 0;
- pLock->status = LOCK_OPEN;
- InitializeCriticalSection(&(pLock->cs));
- pLock->writewx = CreateEvent(NULL,
- FALSE, /* Manual reset */
- TRUE, /* Initial state */
- NULL);
- pLock->readwx = CreateEvent(NULL,
- TRUE, /* Manual reset */
- TRUE, /* Initial state */
- NULL);
-}
-
-KHMEXP void KHMAPI DeleteRwLock(PRWLOCK pLock)
-{
- EnterCriticalSection(&pLock->cs);
-
- CloseHandle(pLock->readwx);
- CloseHandle(pLock->writewx);
- pLock->readwx = NULL;
- pLock->writewx = NULL;
-
- LeaveCriticalSection(&pLock->cs);
- DeleteCriticalSection(&(pLock->cs));
-}
-
-KHMEXP void KHMAPI LockObtainRead(PRWLOCK pLock)
-{
- while(1) {
- WaitForSingleObject(pLock->readwx, INFINITE);
- EnterCriticalSection(&pLock->cs);
- if(pLock->status == LOCK_WRITING) {
- LeaveCriticalSection(&(pLock->cs));
- continue;
- } else
- break;
- }
- pLock->locks ++;
- pLock->status = LOCK_READING;
- ResetEvent(pLock->writewx);
- LeaveCriticalSection(&(pLock->cs));
-}
-
-KHMEXP void KHMAPI LockReleaseRead(PRWLOCK pLock)
-{
- EnterCriticalSection(&(pLock->cs));
- assert(pLock->status == LOCK_READING);
- pLock->locks--;
- if(!pLock->locks) {
- pLock->status = LOCK_OPEN;
- SetEvent(pLock->readwx);
- SetEvent(pLock->writewx);
- }
- LeaveCriticalSection(&(pLock->cs));
-}
-
-KHMEXP void KHMAPI LockObtainWrite(PRWLOCK pLock)
-{
- EnterCriticalSection(&(pLock->cs));
- if(pLock->status == LOCK_WRITING &&
- pLock->writer == GetCurrentThreadId()) {
- pLock->locks++;
- LeaveCriticalSection(&(pLock->cs));
- return;
- }
- LeaveCriticalSection(&(pLock->cs));
- while(1) {
- WaitForSingleObject(pLock->writewx, INFINITE);
- EnterCriticalSection(&(pLock->cs));
- if(pLock->status == LOCK_OPEN)
- break;
- LeaveCriticalSection(&(pLock->cs));
- }
- pLock->status = LOCK_WRITING;
- pLock->locks++;
- pLock->writer = GetCurrentThreadId();
- ResetEvent(pLock->readwx);
- ResetEvent(pLock->writewx);
- LeaveCriticalSection(&(pLock->cs));
-}
-
-KHMEXP void KHMAPI LockReleaseWrite(PRWLOCK pLock)
-{
- EnterCriticalSection(&(pLock->cs));
- assert(pLock->status == LOCK_WRITING);
- pLock->locks--;
- if(!pLock->locks) {
- pLock->status = LOCK_OPEN;
- pLock->writer = 0;
- SetEvent(pLock->readwx);
- SetEvent(pLock->writewx);
- }
- LeaveCriticalSection(&(pLock->cs));
-}
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<windows.h>
+#include<sync.h>
+#include<assert.h>
+
+#define LOCK_OPEN 0
+#define LOCK_READING 1
+#define LOCK_WRITING 2
+
+KHMEXP void KHMAPI InitializeRwLock(PRWLOCK pLock)
+{
+ pLock->locks = 0;
+ pLock->status = LOCK_OPEN;
+ InitializeCriticalSection(&(pLock->cs));
+ pLock->writewx = CreateEvent(NULL,
+ FALSE, /* Manual reset */
+ TRUE, /* Initial state */
+ NULL);
+ pLock->readwx = CreateEvent(NULL,
+ TRUE, /* Manual reset */
+ TRUE, /* Initial state */
+ NULL);
+}
+
+KHMEXP void KHMAPI DeleteRwLock(PRWLOCK pLock)
+{
+ EnterCriticalSection(&pLock->cs);
+
+ CloseHandle(pLock->readwx);
+ CloseHandle(pLock->writewx);
+ pLock->readwx = NULL;
+ pLock->writewx = NULL;
+
+ LeaveCriticalSection(&pLock->cs);
+ DeleteCriticalSection(&(pLock->cs));
+}
+
+KHMEXP void KHMAPI LockObtainRead(PRWLOCK pLock)
+{
+ while(1) {
+ WaitForSingleObject(pLock->readwx, INFINITE);
+ EnterCriticalSection(&pLock->cs);
+ if(pLock->status == LOCK_WRITING) {
+ LeaveCriticalSection(&(pLock->cs));
+ continue;
+ } else
+ break;
+ }
+ pLock->locks ++;
+ pLock->status = LOCK_READING;
+ ResetEvent(pLock->writewx);
+ LeaveCriticalSection(&(pLock->cs));
+}
+
+KHMEXP void KHMAPI LockReleaseRead(PRWLOCK pLock)
+{
+ EnterCriticalSection(&(pLock->cs));
+ assert(pLock->status == LOCK_READING);
+ pLock->locks--;
+ if(!pLock->locks) {
+ pLock->status = LOCK_OPEN;
+ SetEvent(pLock->readwx);
+ SetEvent(pLock->writewx);
+ }
+ LeaveCriticalSection(&(pLock->cs));
+}
+
+KHMEXP void KHMAPI LockObtainWrite(PRWLOCK pLock)
+{
+ EnterCriticalSection(&(pLock->cs));
+ if(pLock->status == LOCK_WRITING &&
+ pLock->writer == GetCurrentThreadId()) {
+ pLock->locks++;
+ LeaveCriticalSection(&(pLock->cs));
+ return;
+ }
+ LeaveCriticalSection(&(pLock->cs));
+ while(1) {
+ WaitForSingleObject(pLock->writewx, INFINITE);
+ EnterCriticalSection(&(pLock->cs));
+ if(pLock->status == LOCK_OPEN)
+ break;
+ LeaveCriticalSection(&(pLock->cs));
+ }
+ pLock->status = LOCK_WRITING;
+ pLock->locks++;
+ pLock->writer = GetCurrentThreadId();
+ ResetEvent(pLock->readwx);
+ ResetEvent(pLock->writewx);
+ LeaveCriticalSection(&(pLock->cs));
+}
+
+KHMEXP void KHMAPI LockReleaseWrite(PRWLOCK pLock)
+{
+ EnterCriticalSection(&(pLock->cs));
+ assert(pLock->status == LOCK_WRITING);
+ pLock->locks--;
+ if(!pLock->locks) {
+ pLock->status = LOCK_OPEN;
+ pLock->writer = 0;
+ SetEvent(pLock->readwx);
+ SetEvent(pLock->writewx);
+ }
+ LeaveCriticalSection(&(pLock->cs));
+}
diff --git a/src/windows/identity/util/sync.h b/src/windows/identity/util/sync.h
index e423e6766f..a95db207ec 100644
--- a/src/windows/identity/util/sync.h
+++ b/src/windows/identity/util/sync.h
@@ -1,128 +1,128 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#ifndef __KHIMAIRA_SYNC_H
-#define __KHIMAIRA_SYNC_H
-
-#include<khdefs.h>
-
-/*! \addtogroup util
- @{ */
-
-/*! \defgroup util_sync Synchronization
- @{*/
-
-/*! \brief A read/write lock
-
- A classic read/write lock. Allows multiple readers or a single
- writer to access a protected object. Readers will wait for any
- pending writer to release the lock, while a writer will wait for
- any pending readers to release the lock.
-*/
-typedef struct tag_rwlock {
- int locks;
- int status;
- CRITICAL_SECTION cs;
- HANDLE readwx;
- HANDLE writewx;
-
- DWORD writer; /* TID of writer thread */
-} rw_lock_t;
-
-typedef rw_lock_t RWLOCK, *PRWLOCK;
-
-/*! \brief Initialize a read/write lock.
-
- A lock <b>must</b> be initialized before it can be used.
- Initializing the lock does not grant the caller any locks on the
- object.
-*/
-KHMEXP void KHMAPI InitializeRwLock(PRWLOCK pLock);
-
-/*! \brief Delete a read/write lock
-
- Once the application is done using the read/write lock, it must be
- deleted with a call to DeleteRwLock()
-*/
-KHMEXP void KHMAPI DeleteRwLock(PRWLOCK pLock);
-
-/*! \brief Obtains a read lock on the read/write lock
-
- Multiple readers can obtain read locks on the same r/w lock.
- However, if any thread attempts to obtain a write lock on the
- object, it will wait until all readers have released the read
- locks.
-
- Call LockReleaseRead() to release the read lock. While the same
- thread may obtain multiple read locks on the same object, each
- call to LockObtainRead() must have a corresponding call to
- LockReleaseRead() to properly relinquish the lock.
-
- \see LockReleaseRead()
-*/
-KHMEXP void KHMAPI LockObtainRead(PRWLOCK pLock);
-
-/*! \brief Relase a read lock obtained on a read/write lock
-
- Each call to LockObtainRead() must have a corresponding call to
- LockReleaseRead(). Once all read locks are released, any threads
- waiting on write locks on the object will be woken and assigned a
- write lock.
-
- \see LockObtainRead()
-*/
-KHMEXP void KHMAPI LockReleaseRead(PRWLOCK pLock);
-
-/*! \brief Obtains a write lock on the read/write lock
-
- Only a single writer is allowed to lock a single r/w lock.
- However, if any thread attempts to obtain a read lock on the
- object, it will wait until the writer has released the lock.
-
- Call LockReleaseWrite() to release the write lock. While the same
- thread may obtain multiple write locks on the same object, each
- call to LockObtainWrite() must have a corresponding call to
- LockReleaseWrite() to properly relinquish the lock.
-
- \see LockReleaseWrite()
-*/
-KHMEXP void KHMAPI LockObtainWrite(PRWLOCK pLock);
-
-/*! \brief Relase a write lock obtained on a read/write lock
-
- Each call to LockObtainWrite() must have a corresponding call to
- LockReleaseWrite(). Once the write lock is released, any threads
- waiting for read or write locks on the object will be woken and
- assigned the proper lock.
-
- \see LockObtainWrite()
-*/
-KHMEXP void KHMAPI LockReleaseWrite(PRWLOCK pLock);
-
-/*@}*/
-/*@}*/
-
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __KHIMAIRA_SYNC_H
+#define __KHIMAIRA_SYNC_H
+
+#include<khdefs.h>
+
+/*! \addtogroup util
+ @{ */
+
+/*! \defgroup util_sync Synchronization
+ @{*/
+
+/*! \brief A read/write lock
+
+ A classic read/write lock. Allows multiple readers or a single
+ writer to access a protected object. Readers will wait for any
+ pending writer to release the lock, while a writer will wait for
+ any pending readers to release the lock.
+*/
+typedef struct tag_rwlock {
+ int locks;
+ int status;
+ CRITICAL_SECTION cs;
+ HANDLE readwx;
+ HANDLE writewx;
+
+ DWORD writer; /* TID of writer thread */
+} rw_lock_t;
+
+typedef rw_lock_t RWLOCK, *PRWLOCK;
+
+/*! \brief Initialize a read/write lock.
+
+ A lock <b>must</b> be initialized before it can be used.
+ Initializing the lock does not grant the caller any locks on the
+ object.
+*/
+KHMEXP void KHMAPI InitializeRwLock(PRWLOCK pLock);
+
+/*! \brief Delete a read/write lock
+
+ Once the application is done using the read/write lock, it must be
+ deleted with a call to DeleteRwLock()
+*/
+KHMEXP void KHMAPI DeleteRwLock(PRWLOCK pLock);
+
+/*! \brief Obtains a read lock on the read/write lock
+
+ Multiple readers can obtain read locks on the same r/w lock.
+ However, if any thread attempts to obtain a write lock on the
+ object, it will wait until all readers have released the read
+ locks.
+
+ Call LockReleaseRead() to release the read lock. While the same
+ thread may obtain multiple read locks on the same object, each
+ call to LockObtainRead() must have a corresponding call to
+ LockReleaseRead() to properly relinquish the lock.
+
+ \see LockReleaseRead()
+*/
+KHMEXP void KHMAPI LockObtainRead(PRWLOCK pLock);
+
+/*! \brief Relase a read lock obtained on a read/write lock
+
+ Each call to LockObtainRead() must have a corresponding call to
+ LockReleaseRead(). Once all read locks are released, any threads
+ waiting on write locks on the object will be woken and assigned a
+ write lock.
+
+ \see LockObtainRead()
+*/
+KHMEXP void KHMAPI LockReleaseRead(PRWLOCK pLock);
+
+/*! \brief Obtains a write lock on the read/write lock
+
+ Only a single writer is allowed to lock a single r/w lock.
+ However, if any thread attempts to obtain a read lock on the
+ object, it will wait until the writer has released the lock.
+
+ Call LockReleaseWrite() to release the write lock. While the same
+ thread may obtain multiple write locks on the same object, each
+ call to LockObtainWrite() must have a corresponding call to
+ LockReleaseWrite() to properly relinquish the lock.
+
+ \see LockReleaseWrite()
+*/
+KHMEXP void KHMAPI LockObtainWrite(PRWLOCK pLock);
+
+/*! \brief Relase a write lock obtained on a read/write lock
+
+ Each call to LockObtainWrite() must have a corresponding call to
+ LockReleaseWrite(). Once the write lock is released, any threads
+ waiting for read or write locks on the object will be woken and
+ assigned the proper lock.
+
+ \see LockObtainWrite()
+*/
+KHMEXP void KHMAPI LockReleaseWrite(PRWLOCK pLock);
+
+/*@}*/
+/*@}*/
+
+#endif
diff --git a/src/windows/identity/util/utils.h b/src/windows/identity/util/utils.h
index 4ba86f6edb..4c3bef52ff 100644
--- a/src/windows/identity/util/utils.h
+++ b/src/windows/identity/util/utils.h
@@ -1,37 +1,37 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* $Id$ */
-
-#ifndef __KHIMAIRA_UTIL_H
-#define __KHIMAIRA_UTIL_H
-
-/*! \defgroup util Utilities
- */
-#include<hashtable.h>
-#include<sync.h>
-#include<mstring.h>
-#include<perfstat.h>
-
-#endif
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __KHIMAIRA_UTIL_H
+#define __KHIMAIRA_UTIL_H
+
+/*! \defgroup util Utilities
+ */
+#include<hashtable.h>
+#include<sync.h>
+#include<mstring.h>
+#include<perfstat.h>
+
+#endif
diff --git a/src/windows/kfwlogon/kfwcommon.c b/src/windows/kfwlogon/kfwcommon.c
index ea9410ea61..c07bd81c3f 100644
--- a/src/windows/kfwlogon/kfwcommon.c
+++ b/src/windows/kfwlogon/kfwcommon.c
@@ -1,1352 +1,1352 @@
-/*
-Copyright 2005,2006 by the Massachusetts Institute of Technology
-Copyright 2007 by Secure Endpoints Inc.
-
-All rights reserved.
-
-Permission to use, copy, modify, and distribute this software and its
-documentation for any purpose and without fee is hereby granted,
-provided that the above copyright notice appear in all copies and that
-both that copyright notice and this permission notice appear in
-supporting documentation, and that the name of the Massachusetts
-Institute of Technology (M.I.T.) not be used in advertising or publicity
-pertaining to distribution of the software without specific, written
-prior permission.
-
-M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
-M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
-WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
-ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
-SOFTWARE.
-
-*/
-
-#include "kfwlogon.h"
-#include <windows.h>
-#include <Aclapi.h>
-#include <userenv.h>
-#include <Sddl.h>
-
-#include <io.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <fcntl.h>
-
-#include <winsock2.h>
-#include <lm.h>
-#include <nb30.h>
-
-#include <errno.h>
-#include <malloc.h>
-
-
-/* Function Pointer Declarations for Delayed Loading */
-// CCAPI
-DECL_FUNC_PTR(cc_initialize);
-DECL_FUNC_PTR(cc_shutdown);
-DECL_FUNC_PTR(cc_get_NC_info);
-DECL_FUNC_PTR(cc_free_NC_info);
-
-// leash functions
-DECL_FUNC_PTR(Leash_get_default_lifetime);
-DECL_FUNC_PTR(Leash_get_default_forwardable);
-DECL_FUNC_PTR(Leash_get_default_renew_till);
-DECL_FUNC_PTR(Leash_get_default_noaddresses);
-DECL_FUNC_PTR(Leash_get_default_proxiable);
-DECL_FUNC_PTR(Leash_get_default_publicip);
-DECL_FUNC_PTR(Leash_get_default_use_krb4);
-DECL_FUNC_PTR(Leash_get_default_life_min);
-DECL_FUNC_PTR(Leash_get_default_life_max);
-DECL_FUNC_PTR(Leash_get_default_renew_min);
-DECL_FUNC_PTR(Leash_get_default_renew_max);
-DECL_FUNC_PTR(Leash_get_default_renewable);
-DECL_FUNC_PTR(Leash_get_default_mslsa_import);
-
-// krb5 functions
-DECL_FUNC_PTR(krb5_change_password);
-DECL_FUNC_PTR(krb5_get_init_creds_opt_init);
-DECL_FUNC_PTR(krb5_get_init_creds_opt_set_tkt_life);
-DECL_FUNC_PTR(krb5_get_init_creds_opt_set_renew_life);
-DECL_FUNC_PTR(krb5_get_init_creds_opt_set_forwardable);
-DECL_FUNC_PTR(krb5_get_init_creds_opt_set_proxiable);
-DECL_FUNC_PTR(krb5_get_init_creds_opt_set_address_list);
-DECL_FUNC_PTR(krb5_get_init_creds_password);
-DECL_FUNC_PTR(krb5_build_principal_ext);
-DECL_FUNC_PTR(krb5_cc_get_name);
-DECL_FUNC_PTR(krb5_cc_resolve);
-DECL_FUNC_PTR(krb5_cc_default);
-DECL_FUNC_PTR(krb5_cc_default_name);
-DECL_FUNC_PTR(krb5_cc_set_default_name);
-DECL_FUNC_PTR(krb5_cc_initialize);
-DECL_FUNC_PTR(krb5_cc_destroy);
-DECL_FUNC_PTR(krb5_cc_close);
-DECL_FUNC_PTR(krb5_cc_store_cred);
-DECL_FUNC_PTR(krb5_cc_copy_creds);
-DECL_FUNC_PTR(krb5_cc_retrieve_cred);
-DECL_FUNC_PTR(krb5_cc_get_principal);
-DECL_FUNC_PTR(krb5_cc_start_seq_get);
-DECL_FUNC_PTR(krb5_cc_next_cred);
-DECL_FUNC_PTR(krb5_cc_end_seq_get);
-DECL_FUNC_PTR(krb5_cc_remove_cred);
-DECL_FUNC_PTR(krb5_cc_set_flags);
-DECL_FUNC_PTR(krb5_cc_get_type);
-DECL_FUNC_PTR(krb5_free_context);
-DECL_FUNC_PTR(krb5_free_cred_contents);
-DECL_FUNC_PTR(krb5_free_principal);
-DECL_FUNC_PTR(krb5_get_in_tkt_with_password);
-DECL_FUNC_PTR(krb5_init_context);
-DECL_FUNC_PTR(krb5_parse_name);
-DECL_FUNC_PTR(krb5_timeofday);
-DECL_FUNC_PTR(krb5_timestamp_to_sfstring);
-DECL_FUNC_PTR(krb5_unparse_name);
-DECL_FUNC_PTR(krb5_get_credentials);
-DECL_FUNC_PTR(krb5_mk_req);
-DECL_FUNC_PTR(krb5_sname_to_principal);
-DECL_FUNC_PTR(krb5_get_credentials_renew);
-DECL_FUNC_PTR(krb5_free_data);
-DECL_FUNC_PTR(krb5_free_data_contents);
-DECL_FUNC_PTR(krb5_free_unparsed_name);
-DECL_FUNC_PTR(krb5_os_localaddr);
-DECL_FUNC_PTR(krb5_copy_keyblock_contents);
-DECL_FUNC_PTR(krb5_copy_data);
-DECL_FUNC_PTR(krb5_free_creds);
-DECL_FUNC_PTR(krb5_build_principal);
-DECL_FUNC_PTR(krb5_get_renewed_creds);
-DECL_FUNC_PTR(krb5_get_default_config_files);
-DECL_FUNC_PTR(krb5_free_config_files);
-DECL_FUNC_PTR(krb5_get_default_realm);
-DECL_FUNC_PTR(krb5_free_default_realm);
-DECL_FUNC_PTR(krb5_free_ticket);
-DECL_FUNC_PTR(krb5_decode_ticket);
-DECL_FUNC_PTR(krb5_get_host_realm);
-DECL_FUNC_PTR(krb5_free_host_realm);
-DECL_FUNC_PTR(krb5_free_addresses);
-DECL_FUNC_PTR(krb5_c_random_make_octets);
-
-// ComErr functions
-DECL_FUNC_PTR(com_err);
-DECL_FUNC_PTR(error_message);
-
-// Profile functions
-DECL_FUNC_PTR(profile_init);
-DECL_FUNC_PTR(profile_release);
-DECL_FUNC_PTR(profile_get_subsection_names);
-DECL_FUNC_PTR(profile_free_list);
-DECL_FUNC_PTR(profile_get_string);
-DECL_FUNC_PTR(profile_release_string);
-
-// Service functions
-DECL_FUNC_PTR(OpenSCManagerA);
-DECL_FUNC_PTR(OpenServiceA);
-DECL_FUNC_PTR(QueryServiceStatus);
-DECL_FUNC_PTR(CloseServiceHandle);
-DECL_FUNC_PTR(LsaNtStatusToWinError);
-
-// LSA Functions
-DECL_FUNC_PTR(LsaConnectUntrusted);
-DECL_FUNC_PTR(LsaLookupAuthenticationPackage);
-DECL_FUNC_PTR(LsaCallAuthenticationPackage);
-DECL_FUNC_PTR(LsaFreeReturnBuffer);
-DECL_FUNC_PTR(LsaGetLogonSessionData);
-
-// CCAPI
-FUNC_INFO ccapi_fi[] = {
- MAKE_FUNC_INFO(cc_initialize),
- MAKE_FUNC_INFO(cc_shutdown),
- MAKE_FUNC_INFO(cc_get_NC_info),
- MAKE_FUNC_INFO(cc_free_NC_info),
- END_FUNC_INFO
-};
-
-FUNC_INFO leash_fi[] = {
- MAKE_FUNC_INFO(Leash_get_default_lifetime),
- MAKE_FUNC_INFO(Leash_get_default_renew_till),
- MAKE_FUNC_INFO(Leash_get_default_forwardable),
- MAKE_FUNC_INFO(Leash_get_default_noaddresses),
- MAKE_FUNC_INFO(Leash_get_default_proxiable),
- MAKE_FUNC_INFO(Leash_get_default_publicip),
- MAKE_FUNC_INFO(Leash_get_default_use_krb4),
- MAKE_FUNC_INFO(Leash_get_default_life_min),
- MAKE_FUNC_INFO(Leash_get_default_life_max),
- MAKE_FUNC_INFO(Leash_get_default_renew_min),
- MAKE_FUNC_INFO(Leash_get_default_renew_max),
- MAKE_FUNC_INFO(Leash_get_default_renewable),
- END_FUNC_INFO
-};
-
-FUNC_INFO leash_opt_fi[] = {
- MAKE_FUNC_INFO(Leash_get_default_mslsa_import),
- END_FUNC_INFO
-};
-
-FUNC_INFO k5_fi[] = {
- MAKE_FUNC_INFO(krb5_change_password),
- MAKE_FUNC_INFO(krb5_get_init_creds_opt_init),
- MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_tkt_life),
- MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_renew_life),
- MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_forwardable),
- MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_proxiable),
- MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_address_list),
- MAKE_FUNC_INFO(krb5_get_init_creds_password),
- MAKE_FUNC_INFO(krb5_build_principal_ext),
- MAKE_FUNC_INFO(krb5_cc_get_name),
- MAKE_FUNC_INFO(krb5_cc_resolve),
- MAKE_FUNC_INFO(krb5_cc_default),
- MAKE_FUNC_INFO(krb5_cc_default_name),
- MAKE_FUNC_INFO(krb5_cc_set_default_name),
- MAKE_FUNC_INFO(krb5_cc_initialize),
- MAKE_FUNC_INFO(krb5_cc_destroy),
- MAKE_FUNC_INFO(krb5_cc_close),
- MAKE_FUNC_INFO(krb5_cc_copy_creds),
- MAKE_FUNC_INFO(krb5_cc_store_cred),
- MAKE_FUNC_INFO(krb5_cc_retrieve_cred),
- MAKE_FUNC_INFO(krb5_cc_get_principal),
- MAKE_FUNC_INFO(krb5_cc_start_seq_get),
- MAKE_FUNC_INFO(krb5_cc_next_cred),
- MAKE_FUNC_INFO(krb5_cc_end_seq_get),
- MAKE_FUNC_INFO(krb5_cc_remove_cred),
- MAKE_FUNC_INFO(krb5_cc_set_flags),
- MAKE_FUNC_INFO(krb5_cc_get_type),
- MAKE_FUNC_INFO(krb5_free_context),
- MAKE_FUNC_INFO(krb5_free_cred_contents),
- MAKE_FUNC_INFO(krb5_free_principal),
- MAKE_FUNC_INFO(krb5_get_in_tkt_with_password),
- MAKE_FUNC_INFO(krb5_init_context),
- MAKE_FUNC_INFO(krb5_parse_name),
- MAKE_FUNC_INFO(krb5_timeofday),
- MAKE_FUNC_INFO(krb5_timestamp_to_sfstring),
- MAKE_FUNC_INFO(krb5_unparse_name),
- MAKE_FUNC_INFO(krb5_get_credentials),
- MAKE_FUNC_INFO(krb5_mk_req),
- MAKE_FUNC_INFO(krb5_sname_to_principal),
- MAKE_FUNC_INFO(krb5_get_credentials_renew),
- MAKE_FUNC_INFO(krb5_free_data),
- MAKE_FUNC_INFO(krb5_free_data_contents),
- MAKE_FUNC_INFO(krb5_free_unparsed_name),
- MAKE_FUNC_INFO(krb5_os_localaddr),
- MAKE_FUNC_INFO(krb5_copy_keyblock_contents),
- MAKE_FUNC_INFO(krb5_copy_data),
- MAKE_FUNC_INFO(krb5_free_creds),
- MAKE_FUNC_INFO(krb5_build_principal),
- MAKE_FUNC_INFO(krb5_get_renewed_creds),
- MAKE_FUNC_INFO(krb5_free_addresses),
- MAKE_FUNC_INFO(krb5_get_default_config_files),
- MAKE_FUNC_INFO(krb5_free_config_files),
- MAKE_FUNC_INFO(krb5_get_default_realm),
- MAKE_FUNC_INFO(krb5_free_default_realm),
- MAKE_FUNC_INFO(krb5_free_ticket),
- MAKE_FUNC_INFO(krb5_decode_ticket),
- MAKE_FUNC_INFO(krb5_get_host_realm),
- MAKE_FUNC_INFO(krb5_free_host_realm),
- MAKE_FUNC_INFO(krb5_free_addresses),
- MAKE_FUNC_INFO(krb5_c_random_make_octets),
- END_FUNC_INFO
-};
-
-FUNC_INFO profile_fi[] = {
- MAKE_FUNC_INFO(profile_init),
- MAKE_FUNC_INFO(profile_release),
- MAKE_FUNC_INFO(profile_get_subsection_names),
- MAKE_FUNC_INFO(profile_free_list),
- MAKE_FUNC_INFO(profile_get_string),
- MAKE_FUNC_INFO(profile_release_string),
- END_FUNC_INFO
-};
-
-FUNC_INFO ce_fi[] = {
- MAKE_FUNC_INFO(com_err),
- MAKE_FUNC_INFO(error_message),
- END_FUNC_INFO
-};
-
-FUNC_INFO service_fi[] = {
- MAKE_FUNC_INFO(OpenSCManagerA),
- MAKE_FUNC_INFO(OpenServiceA),
- MAKE_FUNC_INFO(QueryServiceStatus),
- MAKE_FUNC_INFO(CloseServiceHandle),
- MAKE_FUNC_INFO(LsaNtStatusToWinError),
- END_FUNC_INFO
-};
-
-FUNC_INFO lsa_fi[] = {
- MAKE_FUNC_INFO(LsaConnectUntrusted),
- MAKE_FUNC_INFO(LsaLookupAuthenticationPackage),
- MAKE_FUNC_INFO(LsaCallAuthenticationPackage),
- MAKE_FUNC_INFO(LsaFreeReturnBuffer),
- MAKE_FUNC_INFO(LsaGetLogonSessionData),
- END_FUNC_INFO
-};
-
-/* Static Declarations */
-static int inited = 0;
-static HINSTANCE hKrb5 = 0;
-static HINSTANCE hKrb524 = 0;
-static HINSTANCE hSecur32 = 0;
-static HINSTANCE hAdvApi32 = 0;
-static HINSTANCE hComErr = 0;
-static HINSTANCE hService = 0;
-static HINSTANCE hProfile = 0;
-static HINSTANCE hLeash = 0;
-static HINSTANCE hLeashOpt = 0;
-static HINSTANCE hCCAPI = 0;
-
-static DWORD TraceOption = 0;
-static HANDLE hDLL;
-
-BOOL IsDebugLogging(void)
-{
- DWORD LSPsize;
- HKEY NPKey;
- DWORD dwDebug = FALSE;
-
- if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
- "System\\CurrentControlSet\\Services\\MIT Kerberos\\NetworkProvider",
- 0, KEY_QUERY_VALUE, &NPKey) == ERROR_SUCCESS)
- {
- LSPsize=sizeof(dwDebug);
- if (RegQueryValueEx(NPKey, "Debug", NULL, NULL, (LPBYTE)&dwDebug, &LSPsize) != ERROR_SUCCESS)
- {
- dwDebug = FALSE;
- }
- RegCloseKey (NPKey);
- }
-
- return(dwDebug ? TRUE : FALSE);
-}
-
-void DebugEvent0(char *a)
-{
- HANDLE h; char *ptbuf[1];
-
- if (IsDebugLogging()) {
- h = RegisterEventSource(NULL, KFW_LOGON_EVENT_NAME);
- if (h) {
- ptbuf[0] = a;
- ReportEvent(h, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, (const char **)ptbuf, NULL);
- DeregisterEventSource(h);
- }
- }
-}
-
-#define MAXBUF_ 512
-void DebugEvent(char *b,...)
-{
- HANDLE h; char *ptbuf[1],buf[MAXBUF_+1];
- va_list marker;
-
- if (IsDebugLogging()) {
- h = RegisterEventSource(NULL, KFW_LOGON_EVENT_NAME);
- if (h) {
- va_start(marker,b);
- StringCbVPrintf(buf, MAXBUF_+1,b,marker);
- buf[MAXBUF_] = '\0';
- ptbuf[0] = buf;
- ReportEvent(h, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, (const char **)ptbuf, NULL);
- DeregisterEventSource(h);
- va_end(marker);
- }
- }
-}
-
-void
-UnloadFuncs(
- FUNC_INFO fi[],
- HINSTANCE h
- )
-{
- int n;
- if (fi)
- for (n = 0; fi[n].func_ptr_var; n++)
- *(fi[n].func_ptr_var) = 0;
- if (h) FreeLibrary(h);
-}
-
-int
-LoadFuncs(
- const char* dll_name,
- FUNC_INFO fi[],
- HINSTANCE* ph, // [out, optional] - DLL handle
- int* pindex, // [out, optional] - index of last func loaded (-1 if none)
- int cleanup, // cleanup function pointers and unload on error
- int go_on, // continue loading even if some functions cannot be loaded
- int silent // do not pop-up a system dialog if DLL cannot be loaded
- )
-{
- HINSTANCE h;
- int i, n, last_i;
- int error = 0;
- UINT em;
-
- if (ph) *ph = 0;
- if (pindex) *pindex = -1;
-
- for (n = 0; fi[n].func_ptr_var; n++)
- *(fi[n].func_ptr_var) = 0;
-
- if (silent)
- em = SetErrorMode(SEM_FAILCRITICALERRORS);
- h = LoadLibrary(dll_name);
- if (silent)
- SetErrorMode(em);
-
- if (!h)
- return 0;
-
- last_i = -1;
- for (i = 0; (go_on || !error) && (i < n); i++)
- {
- void* p = (void*)GetProcAddress(h, fi[i].func_name);
- if (!p)
- error = 1;
- else
- {
- last_i = i;
- *(fi[i].func_ptr_var) = p;
- }
- }
- if (pindex) *pindex = last_i;
- if (error && cleanup && !go_on) {
- for (i = 0; i < n; i++) {
- *(fi[i].func_ptr_var) = 0;
- }
- FreeLibrary(h);
- return 0;
- }
- if (ph) *ph = h;
- if (error) return 0;
- return 1;
-}
-
-static HANDLE hInitMutex = NULL;
-static BOOL bInit = FALSE;
-
-/* KFW_initialize cannot be called from DllEntryPoint */
-void
-KFW_initialize(void)
-{
- static int inited = 0;
-
- if ( !inited ) {
- char mutexName[MAX_PATH];
- HANDLE hMutex = NULL;
-
- sprintf(mutexName, "AFS KFW Init pid=%d", getpid());
-
- hMutex = CreateMutex( NULL, TRUE, mutexName );
- if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
- if ( WaitForSingleObject( hMutex, INFINITE ) != WAIT_OBJECT_0 ) {
- return;
- }
- }
- if ( !inited ) {
- inited = 1;
- LoadFuncs(KRB5_DLL, k5_fi, &hKrb5, 0, 1, 0, 0);
- LoadFuncs(COMERR_DLL, ce_fi, &hComErr, 0, 0, 1, 0);
- LoadFuncs(SERVICE_DLL, service_fi, &hService, 0, 1, 0, 0);
- LoadFuncs(SECUR32_DLL, lsa_fi, &hSecur32, 0, 1, 1, 1);
- LoadFuncs(PROFILE_DLL, profile_fi, &hProfile, 0, 1, 0, 0);
- LoadFuncs(LEASH_DLL, leash_fi, &hLeash, 0, 1, 0, 0);
- LoadFuncs(CCAPI_DLL, ccapi_fi, &hCCAPI, 0, 1, 0, 0);
- LoadFuncs(LEASH_DLL, leash_opt_fi, &hLeashOpt, 0, 1, 0, 0);
- }
- ReleaseMutex(hMutex);
- CloseHandle(hMutex);
- }
-}
-
-void
-KFW_cleanup(void)
-{
- if (hLeashOpt)
- FreeLibrary(hLeashOpt);
- if (hCCAPI)
- FreeLibrary(hCCAPI);
- if (hLeash)
- FreeLibrary(hLeash);
- if (hKrb524)
- FreeLibrary(hKrb524);
- if (hSecur32)
- FreeLibrary(hSecur32);
- if (hService)
- FreeLibrary(hService);
- if (hComErr)
- FreeLibrary(hComErr);
- if (hProfile)
- FreeLibrary(hProfile);
- if (hKrb5)
- FreeLibrary(hKrb5);
-}
-
-
-int
-KFW_is_available(void)
-{
- KFW_initialize();
- if ( hKrb5 && hComErr && hService &&
-#ifdef USE_MS2MIT
- hSecur32 &&
-#endif /* USE_MS2MIT */
- hProfile && hLeash && hCCAPI )
- return TRUE;
-
- return FALSE;
-}
-
-/* Given a principal return an existing ccache or create one and return */
-int
-KFW_get_ccache(krb5_context alt_ctx, krb5_principal principal, krb5_ccache * cc)
-{
- krb5_context ctx;
- char * pname = 0;
- char * ccname = 0;
- krb5_error_code code;
-
- if (!pkrb5_init_context)
- return 0;
-
- if ( alt_ctx ) {
- ctx = alt_ctx;
- } else {
- code = pkrb5_init_context(&ctx);
- if (code) goto cleanup;
- }
-
- if ( principal ) {
- code = pkrb5_unparse_name(ctx, principal, &pname);
- if (code) goto cleanup;
-
- ccname = (char *)malloc(strlen(pname) + 5);
- sprintf(ccname,"API:%s",pname);
-
- DebugEvent0(ccname);
- code = pkrb5_cc_resolve(ctx, ccname, cc);
- } else {
- code = pkrb5_cc_default(ctx, cc);
- if (code) goto cleanup;
- }
-
- cleanup:
- if (ccname)
- free(ccname);
- if (pname)
- pkrb5_free_unparsed_name(ctx,pname);
- if (ctx && (ctx != alt_ctx))
- pkrb5_free_context(ctx);
- return(code);
-}
-
-
-int
-KFW_kinit( krb5_context alt_ctx,
- krb5_ccache alt_cc,
- HWND hParent,
- char *principal_name,
- char *password,
- krb5_deltat lifetime,
- DWORD forwardable,
- DWORD proxiable,
- krb5_deltat renew_life,
- DWORD addressless,
- DWORD publicIP
- )
-{
- krb5_error_code code = 0;
- krb5_context ctx = 0;
- krb5_ccache cc = 0;
- krb5_principal me = 0;
- char* name = 0;
- krb5_creds my_creds;
- krb5_get_init_creds_opt options;
- krb5_address ** addrs = NULL;
- int i = 0, addr_count = 0;
-
- if (!pkrb5_init_context)
- return 0;
-
- pkrb5_get_init_creds_opt_init(&options);
- memset(&my_creds, 0, sizeof(my_creds));
-
- if (alt_ctx)
- {
- ctx = alt_ctx;
- }
- else
- {
- code = pkrb5_init_context(&ctx);
- if (code) goto cleanup;
- }
-
- if ( alt_cc ) {
- cc = alt_cc;
- } else {
- code = pkrb5_cc_default(ctx, &cc);
- if (code) goto cleanup;
- }
-
- code = pkrb5_parse_name(ctx, principal_name, &me);
- if (code)
- goto cleanup;
-
- code = pkrb5_unparse_name(ctx, me, &name);
- if (code)
- goto cleanup;
-
- if (lifetime == 0)
- lifetime = pLeash_get_default_lifetime();
- lifetime *= 60;
-
- if (renew_life > 0)
- renew_life *= 60;
-
- if (lifetime)
- pkrb5_get_init_creds_opt_set_tkt_life(&options, lifetime);
- pkrb5_get_init_creds_opt_set_forwardable(&options,
- forwardable ? 1 : 0);
- pkrb5_get_init_creds_opt_set_proxiable(&options,
- proxiable ? 1 : 0);
- pkrb5_get_init_creds_opt_set_renew_life(&options,
- renew_life);
- if (addressless)
- pkrb5_get_init_creds_opt_set_address_list(&options,NULL);
- else {
- if (publicIP)
- {
- // we are going to add the public IP address specified by the user
- // to the list provided by the operating system
- krb5_address ** local_addrs=NULL;
- DWORD netIPAddr;
-
- pkrb5_os_localaddr(ctx, &local_addrs);
- while ( local_addrs[i++] );
- addr_count = i + 1;
-
- addrs = (krb5_address **) malloc((addr_count+1) * sizeof(krb5_address *));
- if ( !addrs ) {
- pkrb5_free_addresses(ctx, local_addrs);
- goto cleanup;
- }
- memset(addrs, 0, sizeof(krb5_address *) * (addr_count+1));
- i = 0;
- while ( local_addrs[i] ) {
- addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
- if (addrs[i] == NULL) {
- pkrb5_free_addresses(ctx, local_addrs);
- goto cleanup;
- }
-
- addrs[i]->magic = local_addrs[i]->magic;
- addrs[i]->addrtype = local_addrs[i]->addrtype;
- addrs[i]->length = local_addrs[i]->length;
- addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
- if (!addrs[i]->contents) {
- pkrb5_free_addresses(ctx, local_addrs);
- goto cleanup;
- }
-
- memcpy(addrs[i]->contents,local_addrs[i]->contents,
- local_addrs[i]->length); /* safe */
- i++;
- }
- pkrb5_free_addresses(ctx, local_addrs);
-
- addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
- if (addrs[i] == NULL)
- goto cleanup;
-
- addrs[i]->magic = KV5M_ADDRESS;
- addrs[i]->addrtype = AF_INET;
- addrs[i]->length = 4;
- addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
- if (!addrs[i]->contents)
- goto cleanup;
-
- netIPAddr = htonl(publicIP);
- memcpy(addrs[i]->contents,&netIPAddr,4);
-
- pkrb5_get_init_creds_opt_set_address_list(&options,addrs);
-
- }
- }
-
- code = pkrb5_get_init_creds_password(ctx,
- &my_creds,
- me,
- password, // password
- NULL, // no prompter
- hParent, // prompter data
- 0, // start time
- 0, // service name
- &options);
- if (code)
- goto cleanup;
-
- code = pkrb5_cc_initialize(ctx, cc, me);
- if (code)
- goto cleanup;
-
- code = pkrb5_cc_store_cred(ctx, cc, &my_creds);
- if (code)
- goto cleanup;
-
- cleanup:
- if ( addrs ) {
- for ( i=0;i<addr_count;i++ ) {
- if ( addrs[i] ) {
- if ( addrs[i]->contents )
- free(addrs[i]->contents);
- free(addrs[i]);
- }
- }
- }
- if (my_creds.client == me)
- my_creds.client = 0;
- pkrb5_free_cred_contents(ctx, &my_creds);
- if (name)
- pkrb5_free_unparsed_name(ctx, name);
- if (me)
- pkrb5_free_principal(ctx, me);
- if (cc && (cc != alt_cc))
- pkrb5_cc_close(ctx, cc);
- if (ctx && (ctx != alt_ctx))
- pkrb5_free_context(ctx);
- return(code);
-}
-
-
-int
-KFW_get_cred( char * username,
- char * password,
- int lifetime,
- char ** reasonP )
-{
- krb5_context ctx = 0;
- krb5_ccache cc = 0;
- char * realm = 0;
- krb5_principal principal = 0;
- char * pname = 0;
- krb5_error_code code;
-
- if (!pkrb5_init_context || !username || !password || !password[0])
- return 0;
-
- DebugEvent0(username);
-
- code = pkrb5_init_context(&ctx);
- if ( code ) goto cleanup;
-
- code = pkrb5_get_default_realm(ctx, &realm);
-
- if (realm) {
- pname = malloc(strlen(username) + strlen(realm) + 2);
- if (!pname)
- goto cleanup;
- strcpy(pname, username);
- strcat(pname, "@");
- strcat(pname, realm);
- } else {
- goto cleanup;
- }
-
- DebugEvent0(realm);
- DebugEvent0(pname);
-
- code = pkrb5_parse_name(ctx, pname, &principal);
- if ( code ) goto cleanup;
-
- DebugEvent0("parsed name");
- code = KFW_get_ccache(ctx, principal, &cc);
- if ( code ) goto cleanup;
-
- DebugEvent0("got ccache");
-
- if ( lifetime == 0 )
- lifetime = pLeash_get_default_lifetime();
-
- DebugEvent0("got lifetime");
-
- code = KFW_kinit( ctx, cc, HWND_DESKTOP,
- pname,
- password,
- lifetime,
- pLeash_get_default_forwardable(),
- pLeash_get_default_proxiable(),
- pLeash_get_default_renewable() ? pLeash_get_default_renew_till() : 0,
- pLeash_get_default_noaddresses(),
- pLeash_get_default_publicip());
- DebugEvent0("kinit returned");
- if ( code ) goto cleanup;
-
- cleanup:
- if ( pname )
- free(pname);
- if ( realm )
- pkrb5_free_default_realm(ctx, realm);
- if ( cc )
- pkrb5_cc_close(ctx, cc);
-
- if ( code && reasonP ) {
- *reasonP = (char *)perror_message(code);
- }
- return(code);
-}
-
-int KFW_set_ccache_dacl(char *filename, HANDLE hUserToken)
-{
- // SID_IDENTIFIER_AUTHORITY authority = SECURITY_NT_SID_AUTHORITY;
- PSID pSystemSID = NULL;
- DWORD SystemSIDlength = 0, UserSIDlength = 0;
- PACL ccacheACL = NULL;
- DWORD ccacheACLlength = 0;
- PTOKEN_USER pTokenUser = NULL;
- DWORD retLen;
- DWORD gle;
- int ret = 0;
-
- if (!filename) {
- DebugEvent0("KFW_set_ccache_dacl - invalid parms");
- return 1;
- }
-
- DebugEvent0("KFW_set_ccache_dacl");
-
- /* Get System SID */
- if (!ConvertStringSidToSid("S-1-5-18", &pSystemSID)) {
- DebugEvent("KFW_set_ccache_dacl - ConvertStringSidToSid GLE = 0x%x", GetLastError());
- ret = 1;
- goto cleanup;
- }
-
- /* Create ACL */
- SystemSIDlength = GetLengthSid(pSystemSID);
- ccacheACLlength = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE)
- + SystemSIDlength - sizeof(DWORD);
-
- if (hUserToken) {
- if (!GetTokenInformation(hUserToken, TokenUser, NULL, 0, &retLen))
- {
- if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER ) {
- pTokenUser = (PTOKEN_USER) LocalAlloc(LPTR, retLen);
-
- if (!GetTokenInformation(hUserToken, TokenUser, pTokenUser, retLen, &retLen))
- {
- DebugEvent("GetTokenInformation failed: GLE = %lX", GetLastError());
- }
- }
- }
-
- if (pTokenUser) {
- UserSIDlength = GetLengthSid(pTokenUser->User.Sid);
-
- ccacheACLlength += sizeof(ACCESS_ALLOWED_ACE) + UserSIDlength
- - sizeof(DWORD);
- }
- }
-
- ccacheACL = (PACL) LocalAlloc(LPTR, ccacheACLlength);
- if (!ccacheACL) {
- DebugEvent("KFW_set_ccache_dacl - LocalAlloc GLE = 0x%x", GetLastError());
- ret = 1;
- goto cleanup;
- }
-
- InitializeAcl(ccacheACL, ccacheACLlength, ACL_REVISION);
- AddAccessAllowedAceEx(ccacheACL, ACL_REVISION, 0,
- STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL,
- pSystemSID);
- if (pTokenUser) {
- AddAccessAllowedAceEx(ccacheACL, ACL_REVISION, 0,
- STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL,
- pTokenUser->User.Sid);
- if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT,
- DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION,
- NULL,
- NULL,
- ccacheACL,
- NULL)) {
- gle = GetLastError();
- DebugEvent("SetNamedSecurityInfo DACL (1) failed: GLE = 0x%lX", gle);
- if (gle != ERROR_NO_TOKEN)
- ret = 1;
- }
- if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT,
- OWNER_SECURITY_INFORMATION,
- pTokenUser->User.Sid,
- NULL,
- NULL,
- NULL)) {
- gle = GetLastError();
- DebugEvent("SetNamedSecurityInfo OWNER (2) failed: GLE = 0x%lX", gle);
- if (gle != ERROR_NO_TOKEN)
- ret = 1;
- }
- } else {
- if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT,
- DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION,
- NULL,
- NULL,
- ccacheACL,
- NULL)) {
- gle = GetLastError();
- DebugEvent("SetNamedSecurityInfo DACL (3) failed: GLE = 0x%lX", gle);
- if (gle != ERROR_NO_TOKEN)
- ret = 1;
- }
- }
-
- cleanup:
- if (pSystemSID)
- LocalFree(pSystemSID);
- if (pTokenUser)
- LocalFree(pTokenUser);
- if (ccacheACL)
- LocalFree(ccacheACL);
- return ret;
-}
-
-int KFW_set_ccache_dacl_with_user_sid(char *filename, PSID pUserSID)
-{
- // SID_IDENTIFIER_AUTHORITY authority = SECURITY_NT_SID_AUTHORITY;
- PSID pSystemSID = NULL;
- DWORD SystemSIDlength = 0, UserSIDlength = 0;
- PACL ccacheACL = NULL;
- DWORD ccacheACLlength = 0;
- DWORD gle;
- int ret = 0;
-
- if (!filename) {
- DebugEvent0("KFW_set_ccache_dacl_with_user_sid - invalid parms");
- return 1;
- }
-
- DebugEvent0("KFW_set_ccache_dacl_with_user_sid");
-
- /* Get System SID */
- if (!ConvertStringSidToSid("S-1-5-18", &pSystemSID)) {
- DebugEvent("KFW_set_ccache_dacl - ConvertStringSidToSid GLE = 0x%x", GetLastError());
- ret = 1;
- goto cleanup;
- }
-
- /* Create ACL */
- SystemSIDlength = GetLengthSid(pSystemSID);
- ccacheACLlength = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE)
- + SystemSIDlength - sizeof(DWORD);
-
- if (pUserSID) {
- UserSIDlength = GetLengthSid(pUserSID);
-
- ccacheACLlength += sizeof(ACCESS_ALLOWED_ACE) + UserSIDlength
- - sizeof(DWORD);
- }
-
- ccacheACL = (PACL) LocalAlloc(LPTR, ccacheACLlength);
- if (!ccacheACL) {
- DebugEvent("KFW_set_ccache_dacl - LocalAlloc GLE = 0x%x", GetLastError());
- ret = 1;
- goto cleanup;
- }
-
- InitializeAcl(ccacheACL, ccacheACLlength, ACL_REVISION);
- AddAccessAllowedAceEx(ccacheACL, ACL_REVISION, 0,
- STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL,
- pSystemSID);
- if (pUserSID) {
- AddAccessAllowedAceEx(ccacheACL, ACL_REVISION, 0,
- STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL,
- pUserSID);
- if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT,
- DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION,
- NULL,
- NULL,
- ccacheACL,
- NULL)) {
- gle = GetLastError();
- DebugEvent("SetNamedSecurityInfo DACL (4) failed: GLE = 0x%lX", gle);
- if (gle != ERROR_NO_TOKEN)
- ret = 1;
- }
- if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT,
- OWNER_SECURITY_INFORMATION,
- pUserSID,
- NULL,
- NULL,
- NULL)) {
- gle = GetLastError();
- DebugEvent("SetNamedSecurityInfo OWNER (5) failed: GLE = 0x%lX", gle);
- if (gle != ERROR_NO_TOKEN)
- ret = 1;
- }
- } else {
- if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT,
- DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION,
- NULL,
- NULL,
- ccacheACL,
- NULL)) {
- gle = GetLastError();
- DebugEvent("SetNamedSecurityInfo DACL (6) failed: GLE = 0x%lX", gle);
- if (gle != ERROR_NO_TOKEN)
- ret = 1;
- }
- }
-
- cleanup:
- if (pSystemSID)
- LocalFree(pSystemSID);
- if (ccacheACL)
- LocalFree(ccacheACL);
- return ret;
-}
-
-int KFW_obtain_user_temp_directory(HANDLE hUserToken, char *newfilename, int size)
-{
- int retval = 0;
- DWORD dwSize = size-1; /* leave room for nul */
- DWORD dwLen = 0;
-
- if (!hUserToken || !newfilename || size <= 0)
- return 1;
-
- *newfilename = '\0';
-
- dwLen = ExpandEnvironmentStringsForUser(hUserToken, "%TEMP%", newfilename, dwSize);
- if ( !dwLen || dwLen > dwSize )
- dwLen = ExpandEnvironmentStringsForUser(hUserToken, "%TMP%", newfilename, dwSize);
- if ( !dwLen || dwLen > dwSize )
- return 1;
-
- newfilename[dwSize] = '\0';
- return 0;
-}
-
-void
-KFW_copy_cache_to_system_file(const char * user, const char * filename)
-{
- char cachename[MAX_PATH + 8] = "FILE:";
- krb5_context ctx = 0;
- krb5_error_code code;
- krb5_principal princ = 0;
- krb5_ccache cc = 0;
- krb5_ccache ncc = 0;
- PSECURITY_ATTRIBUTES pSA = NULL;
-
- if (!pkrb5_init_context || !user || !filename)
- return;
-
- strncat(cachename, filename, sizeof(cachename));
- cachename[sizeof(cachename)-1] = '\0';
-
- DebugEvent("KFW_Logon_Event - ccache %s", cachename);
-
- DeleteFile(filename);
-
- code = pkrb5_init_context(&ctx);
- if (code) goto cleanup;
-
- code = pkrb5_parse_name(ctx, user, &princ);
- if (code) goto cleanup;
-
- code = KFW_get_ccache(ctx, princ, &cc);
- if (code) goto cleanup;
-
- code = pkrb5_cc_resolve(ctx, cachename, &ncc);
- if (code) goto cleanup;
-
- code = pkrb5_cc_initialize(ctx, ncc, princ);
- if (code) goto cleanup;
-
- code = KFW_set_ccache_dacl(filename, NULL);
- if (code) goto cleanup;
-
- code = pkrb5_cc_copy_creds(ctx,cc,ncc);
-
- cleanup:
- if ( cc ) {
- pkrb5_cc_close(ctx, cc);
- cc = 0;
- }
- if ( ncc ) {
- pkrb5_cc_close(ctx, ncc);
- ncc = 0;
- }
- if ( princ ) {
- pkrb5_free_principal(ctx, princ);
- princ = 0;
- }
-
- if (ctx)
- pkrb5_free_context(ctx);
-}
-
-int
-KFW_copy_file_cache_to_default_cache(char * filename)
-{
- char cachename[MAX_PATH + 8] = "FILE:";
- krb5_context ctx = 0;
- krb5_error_code code;
- krb5_principal princ = 0;
- krb5_ccache cc = 0;
- krb5_ccache ncc = 0;
- int retval = 1;
-
- if (!pkrb5_init_context || !filename)
- return 1;
-
- if ( strlen(filename) + sizeof("FILE:") > sizeof(cachename) )
- return 1;
-
- code = pkrb5_init_context(&ctx);
- if (code) return 1;
-
- strcat(cachename, filename);
-
- code = pkrb5_cc_resolve(ctx, cachename, &cc);
- if (code) {
- DebugEvent0("kfwcpcc krb5_cc_resolve failed");
- goto cleanup;
- }
-
- code = pkrb5_cc_get_principal(ctx, cc, &princ);
- if (code) {
- DebugEvent0("kfwcpcc krb5_cc_get_principal failed");
- goto cleanup;
- }
-
- code = pkrb5_cc_default(ctx, &ncc);
- if (code) {
- DebugEvent0("kfwcpcc krb5_cc_default failed");
- goto cleanup;
- }
- if (!code) {
- code = pkrb5_cc_initialize(ctx, ncc, princ);
-
- if (!code)
- code = pkrb5_cc_copy_creds(ctx,cc,ncc);
- if (code) {
- DebugEvent0("kfwcpcc krb5_cc_copy_creds failed");
- goto cleanup;
- }
- }
- if ( ncc ) {
- pkrb5_cc_close(ctx, ncc);
- ncc = 0;
- }
-
- retval=0; /* success */
-
- cleanup:
- if ( cc ) {
- pkrb5_cc_close(ctx, cc);
- cc = 0;
- }
-
- DeleteFile(filename);
-
- if ( princ ) {
- pkrb5_free_principal(ctx, princ);
- princ = 0;
- }
-
- if (ctx)
- pkrb5_free_context(ctx);
-
- return 0;
-}
-
-
-int
-KFW_copy_file_cache_to_api_cache(char * filename)
-{
- char cachename[MAX_PATH + 8] = "FILE:";
- krb5_context ctx = 0;
- krb5_error_code code;
- krb5_principal princ = 0;
- krb5_ccache cc = 0;
- krb5_ccache ncc = 0;
- char *name = NULL;
- int retval = 1;
-
- if (!pkrb5_init_context || !filename)
- return 1;
-
- if ( strlen(filename) + sizeof("FILE:") > sizeof(cachename) )
- return 1;
-
- code = pkrb5_init_context(&ctx);
- if (code) return 1;
-
- strcat(cachename, filename);
-
- code = pkrb5_cc_resolve(ctx, cachename, &cc);
- if (code) {
- DebugEvent0("kfwcpcc krb5_cc_resolve failed");
- goto cleanup;
- }
-
- code = pkrb5_cc_get_principal(ctx, cc, &princ);
- if (code) {
- DebugEvent0("kfwcpcc krb5_cc_get_principal failed");
- goto cleanup;
- }
-
- code = pkrb5_unparse_name(ctx, princ, &name);
- if (code) {
- DebugEvent0("kfwcpcc krb5_unparse_name failed");
- goto cleanup;
- }
-
- sprintf(cachename, "API:%s", name);
-
- code = pkrb5_cc_resolve(ctx, cachename, &ncc);
- if (code) {
- DebugEvent0("kfwcpcc krb5_cc_default failed");
- goto cleanup;
- }
- if (!code) {
- code = pkrb5_cc_initialize(ctx, ncc, princ);
-
- if (!code)
- code = pkrb5_cc_copy_creds(ctx,cc,ncc);
- if (code) {
- DebugEvent0("kfwcpcc krb5_cc_copy_creds failed");
- goto cleanup;
- }
- }
- if ( ncc ) {
- pkrb5_cc_close(ctx, ncc);
- ncc = 0;
- }
-
- retval=0; /* success */
-
- cleanup:
- if (name)
- pkrb5_free_unparsed_name(ctx, name);
-
- if ( cc ) {
- pkrb5_cc_close(ctx, cc);
- cc = 0;
- }
-
- DeleteFile(filename);
-
- if ( princ ) {
- pkrb5_free_principal(ctx, princ);
- princ = 0;
- }
-
- if (ctx)
- pkrb5_free_context(ctx);
-
- return 0;
-}
-
-
-int
-KFW_destroy_tickets_for_principal(char * user)
-{
- krb5_context ctx = 0;
- krb5_error_code code;
- krb5_principal princ = 0;
- krb5_ccache cc = 0;
-
- if (!pkrb5_init_context)
- return 0;
-
- code = pkrb5_init_context(&ctx);
- if (code) return 1;
-
- code = pkrb5_parse_name(ctx, user, &princ);
- if (code) goto loop_cleanup;
-
- code = KFW_get_ccache(ctx, princ, &cc);
- if (code) goto loop_cleanup;
-
- code = pkrb5_cc_destroy(ctx, cc);
- if (!code) cc = 0;
-
- loop_cleanup:
- if ( cc ) {
- pkrb5_cc_close(ctx, cc);
- cc = 0;
- }
- if ( princ ) {
- pkrb5_free_principal(ctx, princ);
- princ = 0;
- }
-
- pkrb5_free_context(ctx);
- return 0;
-}
-
-
-/* There are scenarios in which an interactive logon will not
- * result in the LogonScript being executed. This will result
- * in orphaned cache files being left in the Temp directory.
- * This function will search for cache files in the Temp
- * directory and delete any that are older than five minutes.
- */
-void
-KFW_cleanup_orphaned_caches(void)
-{
- char * temppath = NULL;
- char * curdir = NULL;
- DWORD count, count2;
- WIN32_FIND_DATA FindFileData;
- HANDLE hFind = INVALID_HANDLE_VALUE;
- FILETIME now;
- ULARGE_INTEGER uli_now;
- FILETIME expired;
-
- count = GetTempPath(0, NULL);
- if (count <= 0)
- return;
- temppath = (char *) malloc(count);
- if (!temppath)
- goto cleanup;
- count2 = GetTempPath(count, temppath);
- if (count2 <= 0 || count2 > count)
- goto cleanup;
-
- count = GetCurrentDirectory(0, NULL);
- curdir = (char *)malloc(count);
- if (!curdir)
- goto cleanup;
- count2 = GetCurrentDirectory(count, curdir);
- if (count2 <= 0 || count2 > count)
- goto cleanup;
-
- if (!SetCurrentDirectory(temppath))
- goto cleanup;
-
- GetSystemTimeAsFileTime(&now);
- uli_now.u.LowPart = now.dwLowDateTime;
- uli_now.u.HighPart = now.dwHighDateTime;
-
- uli_now.QuadPart -= 3000000000; /* 5 minutes == 3 billion 100 nano seconds */
-
- expired.dwLowDateTime = uli_now.u.LowPart;
- expired.dwHighDateTime = uli_now.u.HighPart;
-
- hFind = FindFirstFile("kfwlogon-*", &FindFileData);
- if (hFind != INVALID_HANDLE_VALUE) {
- do {
- if (CompareFileTime(&FindFileData.ftCreationTime, &expired) < 0) {
- DebugEvent("Deleting orphaned cache file: \"%s\"", FindFileData.cFileName);
- DeleteFile(FindFileData.cFileName);
- }
- } while ( FindNextFile(hFind, &FindFileData) );
- }
-
- SetCurrentDirectory(curdir);
-
- cleanup:
- if (temppath)
- free(temppath);
- if (hFind != INVALID_HANDLE_VALUE)
- FindClose(hFind);
- if (curdir)
- free(curdir);
-}
+/*
+Copyright 2005,2006 by the Massachusetts Institute of Technology
+Copyright 2007 by Secure Endpoints Inc.
+
+All rights reserved.
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of the Massachusetts
+Institute of Technology (M.I.T.) not be used in advertising or publicity
+pertaining to distribution of the software without specific, written
+prior permission.
+
+M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+*/
+
+#include "kfwlogon.h"
+#include <windows.h>
+#include <Aclapi.h>
+#include <userenv.h>
+#include <Sddl.h>
+
+#include <io.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+
+#include <winsock2.h>
+#include <lm.h>
+#include <nb30.h>
+
+#include <errno.h>
+#include <malloc.h>
+
+
+/* Function Pointer Declarations for Delayed Loading */
+// CCAPI
+DECL_FUNC_PTR(cc_initialize);
+DECL_FUNC_PTR(cc_shutdown);
+DECL_FUNC_PTR(cc_get_NC_info);
+DECL_FUNC_PTR(cc_free_NC_info);
+
+// leash functions
+DECL_FUNC_PTR(Leash_get_default_lifetime);
+DECL_FUNC_PTR(Leash_get_default_forwardable);
+DECL_FUNC_PTR(Leash_get_default_renew_till);
+DECL_FUNC_PTR(Leash_get_default_noaddresses);
+DECL_FUNC_PTR(Leash_get_default_proxiable);
+DECL_FUNC_PTR(Leash_get_default_publicip);
+DECL_FUNC_PTR(Leash_get_default_use_krb4);
+DECL_FUNC_PTR(Leash_get_default_life_min);
+DECL_FUNC_PTR(Leash_get_default_life_max);
+DECL_FUNC_PTR(Leash_get_default_renew_min);
+DECL_FUNC_PTR(Leash_get_default_renew_max);
+DECL_FUNC_PTR(Leash_get_default_renewable);
+DECL_FUNC_PTR(Leash_get_default_mslsa_import);
+
+// krb5 functions
+DECL_FUNC_PTR(krb5_change_password);
+DECL_FUNC_PTR(krb5_get_init_creds_opt_init);
+DECL_FUNC_PTR(krb5_get_init_creds_opt_set_tkt_life);
+DECL_FUNC_PTR(krb5_get_init_creds_opt_set_renew_life);
+DECL_FUNC_PTR(krb5_get_init_creds_opt_set_forwardable);
+DECL_FUNC_PTR(krb5_get_init_creds_opt_set_proxiable);
+DECL_FUNC_PTR(krb5_get_init_creds_opt_set_address_list);
+DECL_FUNC_PTR(krb5_get_init_creds_password);
+DECL_FUNC_PTR(krb5_build_principal_ext);
+DECL_FUNC_PTR(krb5_cc_get_name);
+DECL_FUNC_PTR(krb5_cc_resolve);
+DECL_FUNC_PTR(krb5_cc_default);
+DECL_FUNC_PTR(krb5_cc_default_name);
+DECL_FUNC_PTR(krb5_cc_set_default_name);
+DECL_FUNC_PTR(krb5_cc_initialize);
+DECL_FUNC_PTR(krb5_cc_destroy);
+DECL_FUNC_PTR(krb5_cc_close);
+DECL_FUNC_PTR(krb5_cc_store_cred);
+DECL_FUNC_PTR(krb5_cc_copy_creds);
+DECL_FUNC_PTR(krb5_cc_retrieve_cred);
+DECL_FUNC_PTR(krb5_cc_get_principal);
+DECL_FUNC_PTR(krb5_cc_start_seq_get);
+DECL_FUNC_PTR(krb5_cc_next_cred);
+DECL_FUNC_PTR(krb5_cc_end_seq_get);
+DECL_FUNC_PTR(krb5_cc_remove_cred);
+DECL_FUNC_PTR(krb5_cc_set_flags);
+DECL_FUNC_PTR(krb5_cc_get_type);
+DECL_FUNC_PTR(krb5_free_context);
+DECL_FUNC_PTR(krb5_free_cred_contents);
+DECL_FUNC_PTR(krb5_free_principal);
+DECL_FUNC_PTR(krb5_get_in_tkt_with_password);
+DECL_FUNC_PTR(krb5_init_context);
+DECL_FUNC_PTR(krb5_parse_name);
+DECL_FUNC_PTR(krb5_timeofday);
+DECL_FUNC_PTR(krb5_timestamp_to_sfstring);
+DECL_FUNC_PTR(krb5_unparse_name);
+DECL_FUNC_PTR(krb5_get_credentials);
+DECL_FUNC_PTR(krb5_mk_req);
+DECL_FUNC_PTR(krb5_sname_to_principal);
+DECL_FUNC_PTR(krb5_get_credentials_renew);
+DECL_FUNC_PTR(krb5_free_data);
+DECL_FUNC_PTR(krb5_free_data_contents);
+DECL_FUNC_PTR(krb5_free_unparsed_name);
+DECL_FUNC_PTR(krb5_os_localaddr);
+DECL_FUNC_PTR(krb5_copy_keyblock_contents);
+DECL_FUNC_PTR(krb5_copy_data);
+DECL_FUNC_PTR(krb5_free_creds);
+DECL_FUNC_PTR(krb5_build_principal);
+DECL_FUNC_PTR(krb5_get_renewed_creds);
+DECL_FUNC_PTR(krb5_get_default_config_files);
+DECL_FUNC_PTR(krb5_free_config_files);
+DECL_FUNC_PTR(krb5_get_default_realm);
+DECL_FUNC_PTR(krb5_free_default_realm);
+DECL_FUNC_PTR(krb5_free_ticket);
+DECL_FUNC_PTR(krb5_decode_ticket);
+DECL_FUNC_PTR(krb5_get_host_realm);
+DECL_FUNC_PTR(krb5_free_host_realm);
+DECL_FUNC_PTR(krb5_free_addresses);
+DECL_FUNC_PTR(krb5_c_random_make_octets);
+
+// ComErr functions
+DECL_FUNC_PTR(com_err);
+DECL_FUNC_PTR(error_message);
+
+// Profile functions
+DECL_FUNC_PTR(profile_init);
+DECL_FUNC_PTR(profile_release);
+DECL_FUNC_PTR(profile_get_subsection_names);
+DECL_FUNC_PTR(profile_free_list);
+DECL_FUNC_PTR(profile_get_string);
+DECL_FUNC_PTR(profile_release_string);
+
+// Service functions
+DECL_FUNC_PTR(OpenSCManagerA);
+DECL_FUNC_PTR(OpenServiceA);
+DECL_FUNC_PTR(QueryServiceStatus);
+DECL_FUNC_PTR(CloseServiceHandle);
+DECL_FUNC_PTR(LsaNtStatusToWinError);
+
+// LSA Functions
+DECL_FUNC_PTR(LsaConnectUntrusted);
+DECL_FUNC_PTR(LsaLookupAuthenticationPackage);
+DECL_FUNC_PTR(LsaCallAuthenticationPackage);
+DECL_FUNC_PTR(LsaFreeReturnBuffer);
+DECL_FUNC_PTR(LsaGetLogonSessionData);
+
+// CCAPI
+FUNC_INFO ccapi_fi[] = {
+ MAKE_FUNC_INFO(cc_initialize),
+ MAKE_FUNC_INFO(cc_shutdown),
+ MAKE_FUNC_INFO(cc_get_NC_info),
+ MAKE_FUNC_INFO(cc_free_NC_info),
+ END_FUNC_INFO
+};
+
+FUNC_INFO leash_fi[] = {
+ MAKE_FUNC_INFO(Leash_get_default_lifetime),
+ MAKE_FUNC_INFO(Leash_get_default_renew_till),
+ MAKE_FUNC_INFO(Leash_get_default_forwardable),
+ MAKE_FUNC_INFO(Leash_get_default_noaddresses),
+ MAKE_FUNC_INFO(Leash_get_default_proxiable),
+ MAKE_FUNC_INFO(Leash_get_default_publicip),
+ MAKE_FUNC_INFO(Leash_get_default_use_krb4),
+ MAKE_FUNC_INFO(Leash_get_default_life_min),
+ MAKE_FUNC_INFO(Leash_get_default_life_max),
+ MAKE_FUNC_INFO(Leash_get_default_renew_min),
+ MAKE_FUNC_INFO(Leash_get_default_renew_max),
+ MAKE_FUNC_INFO(Leash_get_default_renewable),
+ END_FUNC_INFO
+};
+
+FUNC_INFO leash_opt_fi[] = {
+ MAKE_FUNC_INFO(Leash_get_default_mslsa_import),
+ END_FUNC_INFO
+};
+
+FUNC_INFO k5_fi[] = {
+ MAKE_FUNC_INFO(krb5_change_password),
+ MAKE_FUNC_INFO(krb5_get_init_creds_opt_init),
+ MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_tkt_life),
+ MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_renew_life),
+ MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_forwardable),
+ MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_proxiable),
+ MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_address_list),
+ MAKE_FUNC_INFO(krb5_get_init_creds_password),
+ MAKE_FUNC_INFO(krb5_build_principal_ext),
+ MAKE_FUNC_INFO(krb5_cc_get_name),
+ MAKE_FUNC_INFO(krb5_cc_resolve),
+ MAKE_FUNC_INFO(krb5_cc_default),
+ MAKE_FUNC_INFO(krb5_cc_default_name),
+ MAKE_FUNC_INFO(krb5_cc_set_default_name),
+ MAKE_FUNC_INFO(krb5_cc_initialize),
+ MAKE_FUNC_INFO(krb5_cc_destroy),
+ MAKE_FUNC_INFO(krb5_cc_close),
+ MAKE_FUNC_INFO(krb5_cc_copy_creds),
+ MAKE_FUNC_INFO(krb5_cc_store_cred),
+ MAKE_FUNC_INFO(krb5_cc_retrieve_cred),
+ MAKE_FUNC_INFO(krb5_cc_get_principal),
+ MAKE_FUNC_INFO(krb5_cc_start_seq_get),
+ MAKE_FUNC_INFO(krb5_cc_next_cred),
+ MAKE_FUNC_INFO(krb5_cc_end_seq_get),
+ MAKE_FUNC_INFO(krb5_cc_remove_cred),
+ MAKE_FUNC_INFO(krb5_cc_set_flags),
+ MAKE_FUNC_INFO(krb5_cc_get_type),
+ MAKE_FUNC_INFO(krb5_free_context),
+ MAKE_FUNC_INFO(krb5_free_cred_contents),
+ MAKE_FUNC_INFO(krb5_free_principal),
+ MAKE_FUNC_INFO(krb5_get_in_tkt_with_password),
+ MAKE_FUNC_INFO(krb5_init_context),
+ MAKE_FUNC_INFO(krb5_parse_name),
+ MAKE_FUNC_INFO(krb5_timeofday),
+ MAKE_FUNC_INFO(krb5_timestamp_to_sfstring),
+ MAKE_FUNC_INFO(krb5_unparse_name),
+ MAKE_FUNC_INFO(krb5_get_credentials),
+ MAKE_FUNC_INFO(krb5_mk_req),
+ MAKE_FUNC_INFO(krb5_sname_to_principal),
+ MAKE_FUNC_INFO(krb5_get_credentials_renew),
+ MAKE_FUNC_INFO(krb5_free_data),
+ MAKE_FUNC_INFO(krb5_free_data_contents),
+ MAKE_FUNC_INFO(krb5_free_unparsed_name),
+ MAKE_FUNC_INFO(krb5_os_localaddr),
+ MAKE_FUNC_INFO(krb5_copy_keyblock_contents),
+ MAKE_FUNC_INFO(krb5_copy_data),
+ MAKE_FUNC_INFO(krb5_free_creds),
+ MAKE_FUNC_INFO(krb5_build_principal),
+ MAKE_FUNC_INFO(krb5_get_renewed_creds),
+ MAKE_FUNC_INFO(krb5_free_addresses),
+ MAKE_FUNC_INFO(krb5_get_default_config_files),
+ MAKE_FUNC_INFO(krb5_free_config_files),
+ MAKE_FUNC_INFO(krb5_get_default_realm),
+ MAKE_FUNC_INFO(krb5_free_default_realm),
+ MAKE_FUNC_INFO(krb5_free_ticket),
+ MAKE_FUNC_INFO(krb5_decode_ticket),
+ MAKE_FUNC_INFO(krb5_get_host_realm),
+ MAKE_FUNC_INFO(krb5_free_host_realm),
+ MAKE_FUNC_INFO(krb5_free_addresses),
+ MAKE_FUNC_INFO(krb5_c_random_make_octets),
+ END_FUNC_INFO
+};
+
+FUNC_INFO profile_fi[] = {
+ MAKE_FUNC_INFO(profile_init),
+ MAKE_FUNC_INFO(profile_release),
+ MAKE_FUNC_INFO(profile_get_subsection_names),
+ MAKE_FUNC_INFO(profile_free_list),
+ MAKE_FUNC_INFO(profile_get_string),
+ MAKE_FUNC_INFO(profile_release_string),
+ END_FUNC_INFO
+};
+
+FUNC_INFO ce_fi[] = {
+ MAKE_FUNC_INFO(com_err),
+ MAKE_FUNC_INFO(error_message),
+ END_FUNC_INFO
+};
+
+FUNC_INFO service_fi[] = {
+ MAKE_FUNC_INFO(OpenSCManagerA),
+ MAKE_FUNC_INFO(OpenServiceA),
+ MAKE_FUNC_INFO(QueryServiceStatus),
+ MAKE_FUNC_INFO(CloseServiceHandle),
+ MAKE_FUNC_INFO(LsaNtStatusToWinError),
+ END_FUNC_INFO
+};
+
+FUNC_INFO lsa_fi[] = {
+ MAKE_FUNC_INFO(LsaConnectUntrusted),
+ MAKE_FUNC_INFO(LsaLookupAuthenticationPackage),
+ MAKE_FUNC_INFO(LsaCallAuthenticationPackage),
+ MAKE_FUNC_INFO(LsaFreeReturnBuffer),
+ MAKE_FUNC_INFO(LsaGetLogonSessionData),
+ END_FUNC_INFO
+};
+
+/* Static Declarations */
+static int inited = 0;
+static HINSTANCE hKrb5 = 0;
+static HINSTANCE hKrb524 = 0;
+static HINSTANCE hSecur32 = 0;
+static HINSTANCE hAdvApi32 = 0;
+static HINSTANCE hComErr = 0;
+static HINSTANCE hService = 0;
+static HINSTANCE hProfile = 0;
+static HINSTANCE hLeash = 0;
+static HINSTANCE hLeashOpt = 0;
+static HINSTANCE hCCAPI = 0;
+
+static DWORD TraceOption = 0;
+static HANDLE hDLL;
+
+BOOL IsDebugLogging(void)
+{
+ DWORD LSPsize;
+ HKEY NPKey;
+ DWORD dwDebug = FALSE;
+
+ if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+ "System\\CurrentControlSet\\Services\\MIT Kerberos\\NetworkProvider",
+ 0, KEY_QUERY_VALUE, &NPKey) == ERROR_SUCCESS)
+ {
+ LSPsize=sizeof(dwDebug);
+ if (RegQueryValueEx(NPKey, "Debug", NULL, NULL, (LPBYTE)&dwDebug, &LSPsize) != ERROR_SUCCESS)
+ {
+ dwDebug = FALSE;
+ }
+ RegCloseKey (NPKey);
+ }
+
+ return(dwDebug ? TRUE : FALSE);
+}
+
+void DebugEvent0(char *a)
+{
+ HANDLE h; char *ptbuf[1];
+
+ if (IsDebugLogging()) {
+ h = RegisterEventSource(NULL, KFW_LOGON_EVENT_NAME);
+ if (h) {
+ ptbuf[0] = a;
+ ReportEvent(h, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, (const char **)ptbuf, NULL);
+ DeregisterEventSource(h);
+ }
+ }
+}
+
+#define MAXBUF_ 512
+void DebugEvent(char *b,...)
+{
+ HANDLE h; char *ptbuf[1],buf[MAXBUF_+1];
+ va_list marker;
+
+ if (IsDebugLogging()) {
+ h = RegisterEventSource(NULL, KFW_LOGON_EVENT_NAME);
+ if (h) {
+ va_start(marker,b);
+ StringCbVPrintf(buf, MAXBUF_+1,b,marker);
+ buf[MAXBUF_] = '\0';
+ ptbuf[0] = buf;
+ ReportEvent(h, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, (const char **)ptbuf, NULL);
+ DeregisterEventSource(h);
+ va_end(marker);
+ }
+ }
+}
+
+void
+UnloadFuncs(
+ FUNC_INFO fi[],
+ HINSTANCE h
+ )
+{
+ int n;
+ if (fi)
+ for (n = 0; fi[n].func_ptr_var; n++)
+ *(fi[n].func_ptr_var) = 0;
+ if (h) FreeLibrary(h);
+}
+
+int
+LoadFuncs(
+ const char* dll_name,
+ FUNC_INFO fi[],
+ HINSTANCE* ph, // [out, optional] - DLL handle
+ int* pindex, // [out, optional] - index of last func loaded (-1 if none)
+ int cleanup, // cleanup function pointers and unload on error
+ int go_on, // continue loading even if some functions cannot be loaded
+ int silent // do not pop-up a system dialog if DLL cannot be loaded
+ )
+{
+ HINSTANCE h;
+ int i, n, last_i;
+ int error = 0;
+ UINT em;
+
+ if (ph) *ph = 0;
+ if (pindex) *pindex = -1;
+
+ for (n = 0; fi[n].func_ptr_var; n++)
+ *(fi[n].func_ptr_var) = 0;
+
+ if (silent)
+ em = SetErrorMode(SEM_FAILCRITICALERRORS);
+ h = LoadLibrary(dll_name);
+ if (silent)
+ SetErrorMode(em);
+
+ if (!h)
+ return 0;
+
+ last_i = -1;
+ for (i = 0; (go_on || !error) && (i < n); i++)
+ {
+ void* p = (void*)GetProcAddress(h, fi[i].func_name);
+ if (!p)
+ error = 1;
+ else
+ {
+ last_i = i;
+ *(fi[i].func_ptr_var) = p;
+ }
+ }
+ if (pindex) *pindex = last_i;
+ if (error && cleanup && !go_on) {
+ for (i = 0; i < n; i++) {
+ *(fi[i].func_ptr_var) = 0;
+ }
+ FreeLibrary(h);
+ return 0;
+ }
+ if (ph) *ph = h;
+ if (error) return 0;
+ return 1;
+}
+
+static HANDLE hInitMutex = NULL;
+static BOOL bInit = FALSE;
+
+/* KFW_initialize cannot be called from DllEntryPoint */
+void
+KFW_initialize(void)
+{
+ static int inited = 0;
+
+ if ( !inited ) {
+ char mutexName[MAX_PATH];
+ HANDLE hMutex = NULL;
+
+ sprintf(mutexName, "AFS KFW Init pid=%d", getpid());
+
+ hMutex = CreateMutex( NULL, TRUE, mutexName );
+ if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
+ if ( WaitForSingleObject( hMutex, INFINITE ) != WAIT_OBJECT_0 ) {
+ return;
+ }
+ }
+ if ( !inited ) {
+ inited = 1;
+ LoadFuncs(KRB5_DLL, k5_fi, &hKrb5, 0, 1, 0, 0);
+ LoadFuncs(COMERR_DLL, ce_fi, &hComErr, 0, 0, 1, 0);
+ LoadFuncs(SERVICE_DLL, service_fi, &hService, 0, 1, 0, 0);
+ LoadFuncs(SECUR32_DLL, lsa_fi, &hSecur32, 0, 1, 1, 1);
+ LoadFuncs(PROFILE_DLL, profile_fi, &hProfile, 0, 1, 0, 0);
+ LoadFuncs(LEASH_DLL, leash_fi, &hLeash, 0, 1, 0, 0);
+ LoadFuncs(CCAPI_DLL, ccapi_fi, &hCCAPI, 0, 1, 0, 0);
+ LoadFuncs(LEASH_DLL, leash_opt_fi, &hLeashOpt, 0, 1, 0, 0);
+ }
+ ReleaseMutex(hMutex);
+ CloseHandle(hMutex);
+ }
+}
+
+void
+KFW_cleanup(void)
+{
+ if (hLeashOpt)
+ FreeLibrary(hLeashOpt);
+ if (hCCAPI)
+ FreeLibrary(hCCAPI);
+ if (hLeash)
+ FreeLibrary(hLeash);
+ if (hKrb524)
+ FreeLibrary(hKrb524);
+ if (hSecur32)
+ FreeLibrary(hSecur32);
+ if (hService)
+ FreeLibrary(hService);
+ if (hComErr)
+ FreeLibrary(hComErr);
+ if (hProfile)
+ FreeLibrary(hProfile);
+ if (hKrb5)
+ FreeLibrary(hKrb5);
+}
+
+
+int
+KFW_is_available(void)
+{
+ KFW_initialize();
+ if ( hKrb5 && hComErr && hService &&
+#ifdef USE_MS2MIT
+ hSecur32 &&
+#endif /* USE_MS2MIT */
+ hProfile && hLeash && hCCAPI )
+ return TRUE;
+
+ return FALSE;
+}
+
+/* Given a principal return an existing ccache or create one and return */
+int
+KFW_get_ccache(krb5_context alt_ctx, krb5_principal principal, krb5_ccache * cc)
+{
+ krb5_context ctx;
+ char * pname = 0;
+ char * ccname = 0;
+ krb5_error_code code;
+
+ if (!pkrb5_init_context)
+ return 0;
+
+ if ( alt_ctx ) {
+ ctx = alt_ctx;
+ } else {
+ code = pkrb5_init_context(&ctx);
+ if (code) goto cleanup;
+ }
+
+ if ( principal ) {
+ code = pkrb5_unparse_name(ctx, principal, &pname);
+ if (code) goto cleanup;
+
+ ccname = (char *)malloc(strlen(pname) + 5);
+ sprintf(ccname,"API:%s",pname);
+
+ DebugEvent0(ccname);
+ code = pkrb5_cc_resolve(ctx, ccname, cc);
+ } else {
+ code = pkrb5_cc_default(ctx, cc);
+ if (code) goto cleanup;
+ }
+
+ cleanup:
+ if (ccname)
+ free(ccname);
+ if (pname)
+ pkrb5_free_unparsed_name(ctx,pname);
+ if (ctx && (ctx != alt_ctx))
+ pkrb5_free_context(ctx);
+ return(code);
+}
+
+
+int
+KFW_kinit( krb5_context alt_ctx,
+ krb5_ccache alt_cc,
+ HWND hParent,
+ char *principal_name,
+ char *password,
+ krb5_deltat lifetime,
+ DWORD forwardable,
+ DWORD proxiable,
+ krb5_deltat renew_life,
+ DWORD addressless,
+ DWORD publicIP
+ )
+{
+ krb5_error_code code = 0;
+ krb5_context ctx = 0;
+ krb5_ccache cc = 0;
+ krb5_principal me = 0;
+ char* name = 0;
+ krb5_creds my_creds;
+ krb5_get_init_creds_opt options;
+ krb5_address ** addrs = NULL;
+ int i = 0, addr_count = 0;
+
+ if (!pkrb5_init_context)
+ return 0;
+
+ pkrb5_get_init_creds_opt_init(&options);
+ memset(&my_creds, 0, sizeof(my_creds));
+
+ if (alt_ctx)
+ {
+ ctx = alt_ctx;
+ }
+ else
+ {
+ code = pkrb5_init_context(&ctx);
+ if (code) goto cleanup;
+ }
+
+ if ( alt_cc ) {
+ cc = alt_cc;
+ } else {
+ code = pkrb5_cc_default(ctx, &cc);
+ if (code) goto cleanup;
+ }
+
+ code = pkrb5_parse_name(ctx, principal_name, &me);
+ if (code)
+ goto cleanup;
+
+ code = pkrb5_unparse_name(ctx, me, &name);
+ if (code)
+ goto cleanup;
+
+ if (lifetime == 0)
+ lifetime = pLeash_get_default_lifetime();
+ lifetime *= 60;
+
+ if (renew_life > 0)
+ renew_life *= 60;
+
+ if (lifetime)
+ pkrb5_get_init_creds_opt_set_tkt_life(&options, lifetime);
+ pkrb5_get_init_creds_opt_set_forwardable(&options,
+ forwardable ? 1 : 0);
+ pkrb5_get_init_creds_opt_set_proxiable(&options,
+ proxiable ? 1 : 0);
+ pkrb5_get_init_creds_opt_set_renew_life(&options,
+ renew_life);
+ if (addressless)
+ pkrb5_get_init_creds_opt_set_address_list(&options,NULL);
+ else {
+ if (publicIP)
+ {
+ // we are going to add the public IP address specified by the user
+ // to the list provided by the operating system
+ krb5_address ** local_addrs=NULL;
+ DWORD netIPAddr;
+
+ pkrb5_os_localaddr(ctx, &local_addrs);
+ while ( local_addrs[i++] );
+ addr_count = i + 1;
+
+ addrs = (krb5_address **) malloc((addr_count+1) * sizeof(krb5_address *));
+ if ( !addrs ) {
+ pkrb5_free_addresses(ctx, local_addrs);
+ goto cleanup;
+ }
+ memset(addrs, 0, sizeof(krb5_address *) * (addr_count+1));
+ i = 0;
+ while ( local_addrs[i] ) {
+ addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
+ if (addrs[i] == NULL) {
+ pkrb5_free_addresses(ctx, local_addrs);
+ goto cleanup;
+ }
+
+ addrs[i]->magic = local_addrs[i]->magic;
+ addrs[i]->addrtype = local_addrs[i]->addrtype;
+ addrs[i]->length = local_addrs[i]->length;
+ addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
+ if (!addrs[i]->contents) {
+ pkrb5_free_addresses(ctx, local_addrs);
+ goto cleanup;
+ }
+
+ memcpy(addrs[i]->contents,local_addrs[i]->contents,
+ local_addrs[i]->length); /* safe */
+ i++;
+ }
+ pkrb5_free_addresses(ctx, local_addrs);
+
+ addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
+ if (addrs[i] == NULL)
+ goto cleanup;
+
+ addrs[i]->magic = KV5M_ADDRESS;
+ addrs[i]->addrtype = AF_INET;
+ addrs[i]->length = 4;
+ addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
+ if (!addrs[i]->contents)
+ goto cleanup;
+
+ netIPAddr = htonl(publicIP);
+ memcpy(addrs[i]->contents,&netIPAddr,4);
+
+ pkrb5_get_init_creds_opt_set_address_list(&options,addrs);
+
+ }
+ }
+
+ code = pkrb5_get_init_creds_password(ctx,
+ &my_creds,
+ me,
+ password, // password
+ NULL, // no prompter
+ hParent, // prompter data
+ 0, // start time
+ 0, // service name
+ &options);
+ if (code)
+ goto cleanup;
+
+ code = pkrb5_cc_initialize(ctx, cc, me);
+ if (code)
+ goto cleanup;
+
+ code = pkrb5_cc_store_cred(ctx, cc, &my_creds);
+ if (code)
+ goto cleanup;
+
+ cleanup:
+ if ( addrs ) {
+ for ( i=0;i<addr_count;i++ ) {
+ if ( addrs[i] ) {
+ if ( addrs[i]->contents )
+ free(addrs[i]->contents);
+ free(addrs[i]);
+ }
+ }
+ }
+ if (my_creds.client == me)
+ my_creds.client = 0;
+ pkrb5_free_cred_contents(ctx, &my_creds);
+ if (name)
+ pkrb5_free_unparsed_name(ctx, name);
+ if (me)
+ pkrb5_free_principal(ctx, me);
+ if (cc && (cc != alt_cc))
+ pkrb5_cc_close(ctx, cc);
+ if (ctx && (ctx != alt_ctx))
+ pkrb5_free_context(ctx);
+ return(code);
+}
+
+
+int
+KFW_get_cred( char * username,
+ char * password,
+ int lifetime,
+ char ** reasonP )
+{
+ krb5_context ctx = 0;
+ krb5_ccache cc = 0;
+ char * realm = 0;
+ krb5_principal principal = 0;
+ char * pname = 0;
+ krb5_error_code code;
+
+ if (!pkrb5_init_context || !username || !password || !password[0])
+ return 0;
+
+ DebugEvent0(username);
+
+ code = pkrb5_init_context(&ctx);
+ if ( code ) goto cleanup;
+
+ code = pkrb5_get_default_realm(ctx, &realm);
+
+ if (realm) {
+ pname = malloc(strlen(username) + strlen(realm) + 2);
+ if (!pname)
+ goto cleanup;
+ strcpy(pname, username);
+ strcat(pname, "@");
+ strcat(pname, realm);
+ } else {
+ goto cleanup;
+ }
+
+ DebugEvent0(realm);
+ DebugEvent0(pname);
+
+ code = pkrb5_parse_name(ctx, pname, &principal);
+ if ( code ) goto cleanup;
+
+ DebugEvent0("parsed name");
+ code = KFW_get_ccache(ctx, principal, &cc);
+ if ( code ) goto cleanup;
+
+ DebugEvent0("got ccache");
+
+ if ( lifetime == 0 )
+ lifetime = pLeash_get_default_lifetime();
+
+ DebugEvent0("got lifetime");
+
+ code = KFW_kinit( ctx, cc, HWND_DESKTOP,
+ pname,
+ password,
+ lifetime,
+ pLeash_get_default_forwardable(),
+ pLeash_get_default_proxiable(),
+ pLeash_get_default_renewable() ? pLeash_get_default_renew_till() : 0,
+ pLeash_get_default_noaddresses(),
+ pLeash_get_default_publicip());
+ DebugEvent0("kinit returned");
+ if ( code ) goto cleanup;
+
+ cleanup:
+ if ( pname )
+ free(pname);
+ if ( realm )
+ pkrb5_free_default_realm(ctx, realm);
+ if ( cc )
+ pkrb5_cc_close(ctx, cc);
+
+ if ( code && reasonP ) {
+ *reasonP = (char *)perror_message(code);
+ }
+ return(code);
+}
+
+int KFW_set_ccache_dacl(char *filename, HANDLE hUserToken)
+{
+ // SID_IDENTIFIER_AUTHORITY authority = SECURITY_NT_SID_AUTHORITY;
+ PSID pSystemSID = NULL;
+ DWORD SystemSIDlength = 0, UserSIDlength = 0;
+ PACL ccacheACL = NULL;
+ DWORD ccacheACLlength = 0;
+ PTOKEN_USER pTokenUser = NULL;
+ DWORD retLen;
+ DWORD gle;
+ int ret = 0;
+
+ if (!filename) {
+ DebugEvent0("KFW_set_ccache_dacl - invalid parms");
+ return 1;
+ }
+
+ DebugEvent0("KFW_set_ccache_dacl");
+
+ /* Get System SID */
+ if (!ConvertStringSidToSid("S-1-5-18", &pSystemSID)) {
+ DebugEvent("KFW_set_ccache_dacl - ConvertStringSidToSid GLE = 0x%x", GetLastError());
+ ret = 1;
+ goto cleanup;
+ }
+
+ /* Create ACL */
+ SystemSIDlength = GetLengthSid(pSystemSID);
+ ccacheACLlength = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE)
+ + SystemSIDlength - sizeof(DWORD);
+
+ if (hUserToken) {
+ if (!GetTokenInformation(hUserToken, TokenUser, NULL, 0, &retLen))
+ {
+ if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER ) {
+ pTokenUser = (PTOKEN_USER) LocalAlloc(LPTR, retLen);
+
+ if (!GetTokenInformation(hUserToken, TokenUser, pTokenUser, retLen, &retLen))
+ {
+ DebugEvent("GetTokenInformation failed: GLE = %lX", GetLastError());
+ }
+ }
+ }
+
+ if (pTokenUser) {
+ UserSIDlength = GetLengthSid(pTokenUser->User.Sid);
+
+ ccacheACLlength += sizeof(ACCESS_ALLOWED_ACE) + UserSIDlength
+ - sizeof(DWORD);
+ }
+ }
+
+ ccacheACL = (PACL) LocalAlloc(LPTR, ccacheACLlength);
+ if (!ccacheACL) {
+ DebugEvent("KFW_set_ccache_dacl - LocalAlloc GLE = 0x%x", GetLastError());
+ ret = 1;
+ goto cleanup;
+ }
+
+ InitializeAcl(ccacheACL, ccacheACLlength, ACL_REVISION);
+ AddAccessAllowedAceEx(ccacheACL, ACL_REVISION, 0,
+ STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL,
+ pSystemSID);
+ if (pTokenUser) {
+ AddAccessAllowedAceEx(ccacheACL, ACL_REVISION, 0,
+ STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL,
+ pTokenUser->User.Sid);
+ if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT,
+ DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION,
+ NULL,
+ NULL,
+ ccacheACL,
+ NULL)) {
+ gle = GetLastError();
+ DebugEvent("SetNamedSecurityInfo DACL (1) failed: GLE = 0x%lX", gle);
+ if (gle != ERROR_NO_TOKEN)
+ ret = 1;
+ }
+ if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT,
+ OWNER_SECURITY_INFORMATION,
+ pTokenUser->User.Sid,
+ NULL,
+ NULL,
+ NULL)) {
+ gle = GetLastError();
+ DebugEvent("SetNamedSecurityInfo OWNER (2) failed: GLE = 0x%lX", gle);
+ if (gle != ERROR_NO_TOKEN)
+ ret = 1;
+ }
+ } else {
+ if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT,
+ DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION,
+ NULL,
+ NULL,
+ ccacheACL,
+ NULL)) {
+ gle = GetLastError();
+ DebugEvent("SetNamedSecurityInfo DACL (3) failed: GLE = 0x%lX", gle);
+ if (gle != ERROR_NO_TOKEN)
+ ret = 1;
+ }
+ }
+
+ cleanup:
+ if (pSystemSID)
+ LocalFree(pSystemSID);
+ if (pTokenUser)
+ LocalFree(pTokenUser);
+ if (ccacheACL)
+ LocalFree(ccacheACL);
+ return ret;
+}
+
+int KFW_set_ccache_dacl_with_user_sid(char *filename, PSID pUserSID)
+{
+ // SID_IDENTIFIER_AUTHORITY authority = SECURITY_NT_SID_AUTHORITY;
+ PSID pSystemSID = NULL;
+ DWORD SystemSIDlength = 0, UserSIDlength = 0;
+ PACL ccacheACL = NULL;
+ DWORD ccacheACLlength = 0;
+ DWORD gle;
+ int ret = 0;
+
+ if (!filename) {
+ DebugEvent0("KFW_set_ccache_dacl_with_user_sid - invalid parms");
+ return 1;
+ }
+
+ DebugEvent0("KFW_set_ccache_dacl_with_user_sid");
+
+ /* Get System SID */
+ if (!ConvertStringSidToSid("S-1-5-18", &pSystemSID)) {
+ DebugEvent("KFW_set_ccache_dacl - ConvertStringSidToSid GLE = 0x%x", GetLastError());
+ ret = 1;
+ goto cleanup;
+ }
+
+ /* Create ACL */
+ SystemSIDlength = GetLengthSid(pSystemSID);
+ ccacheACLlength = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE)
+ + SystemSIDlength - sizeof(DWORD);
+
+ if (pUserSID) {
+ UserSIDlength = GetLengthSid(pUserSID);
+
+ ccacheACLlength += sizeof(ACCESS_ALLOWED_ACE) + UserSIDlength
+ - sizeof(DWORD);
+ }
+
+ ccacheACL = (PACL) LocalAlloc(LPTR, ccacheACLlength);
+ if (!ccacheACL) {
+ DebugEvent("KFW_set_ccache_dacl - LocalAlloc GLE = 0x%x", GetLastError());
+ ret = 1;
+ goto cleanup;
+ }
+
+ InitializeAcl(ccacheACL, ccacheACLlength, ACL_REVISION);
+ AddAccessAllowedAceEx(ccacheACL, ACL_REVISION, 0,
+ STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL,
+ pSystemSID);
+ if (pUserSID) {
+ AddAccessAllowedAceEx(ccacheACL, ACL_REVISION, 0,
+ STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL,
+ pUserSID);
+ if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT,
+ DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION,
+ NULL,
+ NULL,
+ ccacheACL,
+ NULL)) {
+ gle = GetLastError();
+ DebugEvent("SetNamedSecurityInfo DACL (4) failed: GLE = 0x%lX", gle);
+ if (gle != ERROR_NO_TOKEN)
+ ret = 1;
+ }
+ if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT,
+ OWNER_SECURITY_INFORMATION,
+ pUserSID,
+ NULL,
+ NULL,
+ NULL)) {
+ gle = GetLastError();
+ DebugEvent("SetNamedSecurityInfo OWNER (5) failed: GLE = 0x%lX", gle);
+ if (gle != ERROR_NO_TOKEN)
+ ret = 1;
+ }
+ } else {
+ if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT,
+ DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION,
+ NULL,
+ NULL,
+ ccacheACL,
+ NULL)) {
+ gle = GetLastError();
+ DebugEvent("SetNamedSecurityInfo DACL (6) failed: GLE = 0x%lX", gle);
+ if (gle != ERROR_NO_TOKEN)
+ ret = 1;
+ }
+ }
+
+ cleanup:
+ if (pSystemSID)
+ LocalFree(pSystemSID);
+ if (ccacheACL)
+ LocalFree(ccacheACL);
+ return ret;
+}
+
+int KFW_obtain_user_temp_directory(HANDLE hUserToken, char *newfilename, int size)
+{
+ int retval = 0;
+ DWORD dwSize = size-1; /* leave room for nul */
+ DWORD dwLen = 0;
+
+ if (!hUserToken || !newfilename || size <= 0)
+ return 1;
+
+ *newfilename = '\0';
+
+ dwLen = ExpandEnvironmentStringsForUser(hUserToken, "%TEMP%", newfilename, dwSize);
+ if ( !dwLen || dwLen > dwSize )
+ dwLen = ExpandEnvironmentStringsForUser(hUserToken, "%TMP%", newfilename, dwSize);
+ if ( !dwLen || dwLen > dwSize )
+ return 1;
+
+ newfilename[dwSize] = '\0';
+ return 0;
+}
+
+void
+KFW_copy_cache_to_system_file(const char * user, const char * filename)
+{
+ char cachename[MAX_PATH + 8] = "FILE:";
+ krb5_context ctx = 0;
+ krb5_error_code code;
+ krb5_principal princ = 0;
+ krb5_ccache cc = 0;
+ krb5_ccache ncc = 0;
+ PSECURITY_ATTRIBUTES pSA = NULL;
+
+ if (!pkrb5_init_context || !user || !filename)
+ return;
+
+ strncat(cachename, filename, sizeof(cachename));
+ cachename[sizeof(cachename)-1] = '\0';
+
+ DebugEvent("KFW_Logon_Event - ccache %s", cachename);
+
+ DeleteFile(filename);
+
+ code = pkrb5_init_context(&ctx);
+ if (code) goto cleanup;
+
+ code = pkrb5_parse_name(ctx, user, &princ);
+ if (code) goto cleanup;
+
+ code = KFW_get_ccache(ctx, princ, &cc);
+ if (code) goto cleanup;
+
+ code = pkrb5_cc_resolve(ctx, cachename, &ncc);
+ if (code) goto cleanup;
+
+ code = pkrb5_cc_initialize(ctx, ncc, princ);
+ if (code) goto cleanup;
+
+ code = KFW_set_ccache_dacl(filename, NULL);
+ if (code) goto cleanup;
+
+ code = pkrb5_cc_copy_creds(ctx,cc,ncc);
+
+ cleanup:
+ if ( cc ) {
+ pkrb5_cc_close(ctx, cc);
+ cc = 0;
+ }
+ if ( ncc ) {
+ pkrb5_cc_close(ctx, ncc);
+ ncc = 0;
+ }
+ if ( princ ) {
+ pkrb5_free_principal(ctx, princ);
+ princ = 0;
+ }
+
+ if (ctx)
+ pkrb5_free_context(ctx);
+}
+
+int
+KFW_copy_file_cache_to_default_cache(char * filename)
+{
+ char cachename[MAX_PATH + 8] = "FILE:";
+ krb5_context ctx = 0;
+ krb5_error_code code;
+ krb5_principal princ = 0;
+ krb5_ccache cc = 0;
+ krb5_ccache ncc = 0;
+ int retval = 1;
+
+ if (!pkrb5_init_context || !filename)
+ return 1;
+
+ if ( strlen(filename) + sizeof("FILE:") > sizeof(cachename) )
+ return 1;
+
+ code = pkrb5_init_context(&ctx);
+ if (code) return 1;
+
+ strcat(cachename, filename);
+
+ code = pkrb5_cc_resolve(ctx, cachename, &cc);
+ if (code) {
+ DebugEvent0("kfwcpcc krb5_cc_resolve failed");
+ goto cleanup;
+ }
+
+ code = pkrb5_cc_get_principal(ctx, cc, &princ);
+ if (code) {
+ DebugEvent0("kfwcpcc krb5_cc_get_principal failed");
+ goto cleanup;
+ }
+
+ code = pkrb5_cc_default(ctx, &ncc);
+ if (code) {
+ DebugEvent0("kfwcpcc krb5_cc_default failed");
+ goto cleanup;
+ }
+ if (!code) {
+ code = pkrb5_cc_initialize(ctx, ncc, princ);
+
+ if (!code)
+ code = pkrb5_cc_copy_creds(ctx,cc,ncc);
+ if (code) {
+ DebugEvent0("kfwcpcc krb5_cc_copy_creds failed");
+ goto cleanup;
+ }
+ }
+ if ( ncc ) {
+ pkrb5_cc_close(ctx, ncc);
+ ncc = 0;
+ }
+
+ retval=0; /* success */
+
+ cleanup:
+ if ( cc ) {
+ pkrb5_cc_close(ctx, cc);
+ cc = 0;
+ }
+
+ DeleteFile(filename);
+
+ if ( princ ) {
+ pkrb5_free_principal(ctx, princ);
+ princ = 0;
+ }
+
+ if (ctx)
+ pkrb5_free_context(ctx);
+
+ return 0;
+}
+
+
+int
+KFW_copy_file_cache_to_api_cache(char * filename)
+{
+ char cachename[MAX_PATH + 8] = "FILE:";
+ krb5_context ctx = 0;
+ krb5_error_code code;
+ krb5_principal princ = 0;
+ krb5_ccache cc = 0;
+ krb5_ccache ncc = 0;
+ char *name = NULL;
+ int retval = 1;
+
+ if (!pkrb5_init_context || !filename)
+ return 1;
+
+ if ( strlen(filename) + sizeof("FILE:") > sizeof(cachename) )
+ return 1;
+
+ code = pkrb5_init_context(&ctx);
+ if (code) return 1;
+
+ strcat(cachename, filename);
+
+ code = pkrb5_cc_resolve(ctx, cachename, &cc);
+ if (code) {
+ DebugEvent0("kfwcpcc krb5_cc_resolve failed");
+ goto cleanup;
+ }
+
+ code = pkrb5_cc_get_principal(ctx, cc, &princ);
+ if (code) {
+ DebugEvent0("kfwcpcc krb5_cc_get_principal failed");
+ goto cleanup;
+ }
+
+ code = pkrb5_unparse_name(ctx, princ, &name);
+ if (code) {
+ DebugEvent0("kfwcpcc krb5_unparse_name failed");
+ goto cleanup;
+ }
+
+ sprintf(cachename, "API:%s", name);
+
+ code = pkrb5_cc_resolve(ctx, cachename, &ncc);
+ if (code) {
+ DebugEvent0("kfwcpcc krb5_cc_default failed");
+ goto cleanup;
+ }
+ if (!code) {
+ code = pkrb5_cc_initialize(ctx, ncc, princ);
+
+ if (!code)
+ code = pkrb5_cc_copy_creds(ctx,cc,ncc);
+ if (code) {
+ DebugEvent0("kfwcpcc krb5_cc_copy_creds failed");
+ goto cleanup;
+ }
+ }
+ if ( ncc ) {
+ pkrb5_cc_close(ctx, ncc);
+ ncc = 0;
+ }
+
+ retval=0; /* success */
+
+ cleanup:
+ if (name)
+ pkrb5_free_unparsed_name(ctx, name);
+
+ if ( cc ) {
+ pkrb5_cc_close(ctx, cc);
+ cc = 0;
+ }
+
+ DeleteFile(filename);
+
+ if ( princ ) {
+ pkrb5_free_principal(ctx, princ);
+ princ = 0;
+ }
+
+ if (ctx)
+ pkrb5_free_context(ctx);
+
+ return 0;
+}
+
+
+int
+KFW_destroy_tickets_for_principal(char * user)
+{
+ krb5_context ctx = 0;
+ krb5_error_code code;
+ krb5_principal princ = 0;
+ krb5_ccache cc = 0;
+
+ if (!pkrb5_init_context)
+ return 0;
+
+ code = pkrb5_init_context(&ctx);
+ if (code) return 1;
+
+ code = pkrb5_parse_name(ctx, user, &princ);
+ if (code) goto loop_cleanup;
+
+ code = KFW_get_ccache(ctx, princ, &cc);
+ if (code) goto loop_cleanup;
+
+ code = pkrb5_cc_destroy(ctx, cc);
+ if (!code) cc = 0;
+
+ loop_cleanup:
+ if ( cc ) {
+ pkrb5_cc_close(ctx, cc);
+ cc = 0;
+ }
+ if ( princ ) {
+ pkrb5_free_principal(ctx, princ);
+ princ = 0;
+ }
+
+ pkrb5_free_context(ctx);
+ return 0;
+}
+
+
+/* There are scenarios in which an interactive logon will not
+ * result in the LogonScript being executed. This will result
+ * in orphaned cache files being left in the Temp directory.
+ * This function will search for cache files in the Temp
+ * directory and delete any that are older than five minutes.
+ */
+void
+KFW_cleanup_orphaned_caches(void)
+{
+ char * temppath = NULL;
+ char * curdir = NULL;
+ DWORD count, count2;
+ WIN32_FIND_DATA FindFileData;
+ HANDLE hFind = INVALID_HANDLE_VALUE;
+ FILETIME now;
+ ULARGE_INTEGER uli_now;
+ FILETIME expired;
+
+ count = GetTempPath(0, NULL);
+ if (count <= 0)
+ return;
+ temppath = (char *) malloc(count);
+ if (!temppath)
+ goto cleanup;
+ count2 = GetTempPath(count, temppath);
+ if (count2 <= 0 || count2 > count)
+ goto cleanup;
+
+ count = GetCurrentDirectory(0, NULL);
+ curdir = (char *)malloc(count);
+ if (!curdir)
+ goto cleanup;
+ count2 = GetCurrentDirectory(count, curdir);
+ if (count2 <= 0 || count2 > count)
+ goto cleanup;
+
+ if (!SetCurrentDirectory(temppath))
+ goto cleanup;
+
+ GetSystemTimeAsFileTime(&now);
+ uli_now.u.LowPart = now.dwLowDateTime;
+ uli_now.u.HighPart = now.dwHighDateTime;
+
+ uli_now.QuadPart -= 3000000000; /* 5 minutes == 3 billion 100 nano seconds */
+
+ expired.dwLowDateTime = uli_now.u.LowPart;
+ expired.dwHighDateTime = uli_now.u.HighPart;
+
+ hFind = FindFirstFile("kfwlogon-*", &FindFileData);
+ if (hFind != INVALID_HANDLE_VALUE) {
+ do {
+ if (CompareFileTime(&FindFileData.ftCreationTime, &expired) < 0) {
+ DebugEvent("Deleting orphaned cache file: \"%s\"", FindFileData.cFileName);
+ DeleteFile(FindFileData.cFileName);
+ }
+ } while ( FindNextFile(hFind, &FindFileData) );
+ }
+
+ SetCurrentDirectory(curdir);
+
+ cleanup:
+ if (temppath)
+ free(temppath);
+ if (hFind != INVALID_HANDLE_VALUE)
+ FindClose(hFind);
+ if (curdir)
+ free(curdir);
+}
diff --git a/src/windows/kfwlogon/kfwcpcc.c b/src/windows/kfwlogon/kfwcpcc.c
index 5ff7785527..fb0861e474 100644
--- a/src/windows/kfwlogon/kfwcpcc.c
+++ b/src/windows/kfwlogon/kfwcpcc.c
@@ -1,39 +1,39 @@
-/*
-
-Copyright 2005 by the Massachusetts Institute of Technology
-
-All rights reserved.
-
-Permission to use, copy, modify, and distribute this software and its
-documentation for any purpose and without fee is hereby granted,
-provided that the above copyright notice appear in all copies and that
-both that copyright notice and this permission notice appear in
-supporting documentation, and that the name of the Massachusetts
-Institute of Technology (M.I.T.) not be used in advertising or publicity
-pertaining to distribution of the software without specific, written
-prior permission.
-
-M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
-M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
-WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
-ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
-SOFTWARE.
-
-*/
-
-#include <windows.h>
-#include "kfwlogon.h"
-
-int main(int argc, char *argv[])
-{
- if ( argc != 2 )
- return 1;
-
- KFW_initialize();
-
- return KFW_copy_file_cache_to_api_cache(argv[1]);
-}
-
-
+/*
+
+Copyright 2005 by the Massachusetts Institute of Technology
+
+All rights reserved.
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of the Massachusetts
+Institute of Technology (M.I.T.) not be used in advertising or publicity
+pertaining to distribution of the software without specific, written
+prior permission.
+
+M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+*/
+
+#include <windows.h>
+#include "kfwlogon.h"
+
+int main(int argc, char *argv[])
+{
+ if ( argc != 2 )
+ return 1;
+
+ KFW_initialize();
+
+ return KFW_copy_file_cache_to_api_cache(argv[1]);
+}
+
+
diff --git a/src/windows/kfwlogon/kfwlogon.c b/src/windows/kfwlogon/kfwlogon.c
index 8422f58b11..54d7a5a1d6 100644
--- a/src/windows/kfwlogon/kfwlogon.c
+++ b/src/windows/kfwlogon/kfwlogon.c
@@ -1,634 +1,634 @@
-/*
-Copyright 2005,2006 by the Massachusetts Institute of Technology
-Copyright 2007 by Secure Endpoints Inc.
-
-All rights reserved.
-
-Permission to use, copy, modify, and distribute this software and its
-documentation for any purpose and without fee is hereby granted,
-provided that the above copyright notice appear in all copies and that
-both that copyright notice and this permission notice appear in
-supporting documentation, and that the name of the Massachusetts
-Institute of Technology (M.I.T.) not be used in advertising or publicity
-pertaining to distribution of the software without specific, written
-prior permission.
-
-M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
-M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
-WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
-ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
-SOFTWARE.
-
-*/
-
-#include "kfwlogon.h"
-
-#include <io.h>
-#include <stdio.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <fcntl.h>
-
-#include <winsock2.h>
-#include <lm.h>
-#include <nb30.h>
-
-static HANDLE hDLL;
-
-static HANDLE hInitMutex = NULL;
-static BOOL bInit = FALSE;
-
-
-BOOLEAN APIENTRY DllEntryPoint(HANDLE dll, DWORD reason, PVOID reserved)
-{
- hDLL = dll;
- switch (reason) {
- case DLL_PROCESS_ATTACH:
- /* Initialization Mutex */
- hInitMutex = CreateMutex(NULL, FALSE, NULL);
- break;
-
- case DLL_PROCESS_DETACH:
- CloseHandle(hInitMutex);
- break;
-
- case DLL_THREAD_ATTACH:
- case DLL_THREAD_DETACH:
- default:
- /* Everything else succeeds but does nothing. */
- break;
- }
-
- return TRUE;
-}
-
-DWORD APIENTRY NPGetCaps(DWORD index)
-{
- switch (index) {
- case WNNC_NET_TYPE:
- /* We aren't a file system; We don't have our own type; use somebody else's. */
- return WNNC_NET_SUN_PC_NFS;
- case WNNC_START:
- /* Say we are already started, even though we might wait after we receive NPLogonNotify */
- return 1;
-
- default:
- return 0;
- }
-}
-
-
-static BOOL
-WINAPI
-UnicodeStringToANSI(UNICODE_STRING uInputString, LPSTR lpszOutputString, int nOutStringLen)
-{
- CPINFO CodePageInfo;
-
- GetCPInfo(CP_ACP, &CodePageInfo);
-
- if (CodePageInfo.MaxCharSize > 1)
- // Only supporting non-Unicode strings
- return FALSE;
-
- if (uInputString.Buffer && ((LPBYTE) uInputString.Buffer)[1] == '\0')
- {
- // Looks like unicode, better translate it
- // UNICODE_STRING specifies the length of the buffer string in Bytes not WCHARS
- WideCharToMultiByte(CP_ACP, 0, (LPCWSTR) uInputString.Buffer, uInputString.Length/2,
- lpszOutputString, nOutStringLen-1, NULL, NULL);
- lpszOutputString[min(uInputString.Length/2,nOutStringLen-1)] = '\0';
- return TRUE;
- }
-
- lpszOutputString[0] = '\0';
- return FALSE;
-} // UnicodeStringToANSI
-
-
-static BOOL
-is_windows_vista(void)
-{
- static BOOL fChecked = FALSE;
- static BOOL fIsWinVista = FALSE;
-
- if (!fChecked)
- {
- OSVERSIONINFO Version;
-
- memset (&Version, 0x00, sizeof(Version));
- Version.dwOSVersionInfoSize = sizeof(Version);
-
- if (GetVersionEx (&Version))
- {
- if (Version.dwPlatformId == VER_PLATFORM_WIN32_NT &&
- Version.dwMajorVersion >= 6)
- fIsWinVista = TRUE;
- }
- fChecked = TRUE;
- }
-
- return fIsWinVista;
-}
-
-
-/* Construct a Logon Script that will cause the LogonEventHandler to be executed
- * under in the logon session
- */
-
-#define RUNDLL32_CMDLINE "rundll32.exe kfwlogon.dll,LogonEventHandler "
-VOID
-ConfigureLogonScript(LPWSTR *lpLogonScript, char * filename) {
- DWORD dwLogonScriptLen;
- LPWSTR lpScript;
- LPSTR lpTemp;
-
- if (!lpLogonScript)
- return;
- *lpLogonScript = NULL;
-
- if (!filename)
- return;
-
- dwLogonScriptLen = strlen(RUNDLL32_CMDLINE) + strlen(filename) + 2;
- lpTemp = (LPSTR) malloc(dwLogonScriptLen);
- if (!lpTemp)
- return;
-
- _snprintf(lpTemp, dwLogonScriptLen, "%s%s", RUNDLL32_CMDLINE, filename);
-
- SetLastError(0);
- dwLogonScriptLen = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, lpTemp, -1, NULL, 0);
- DebugEvent("ConfigureLogonScript %s requires %d bytes gle=0x%x", lpTemp, dwLogonScriptLen, GetLastError());
-
- lpScript = LocalAlloc(LMEM_ZEROINIT, dwLogonScriptLen * 2);
- if (lpScript) {
- if (MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, lpTemp, -1, lpScript, 2 * dwLogonScriptLen))
- *lpLogonScript = lpScript;
- else {
- DebugEvent("ConfigureLogonScript - MultiByteToWideChar failed gle = 0x%x", GetLastError());
- LocalFree(lpScript);
- }
- } else {
- DebugEvent("LocalAlloc failed gle=0x%x", GetLastError());
- }
- free(lpTemp);
-}
-
-
-DWORD APIENTRY NPLogonNotify(
- PLUID lpLogonId,
- LPCWSTR lpAuthentInfoType,
- LPVOID lpAuthentInfo,
- LPCWSTR lpPreviousAuthentInfoType,
- LPVOID lpPreviousAuthentInfo,
- LPWSTR lpStationName,
- LPVOID StationHandle,
- LPWSTR *lpLogonScript)
-{
- char uname[MAX_USERNAME_LENGTH+1]="";
- char password[MAX_PASSWORD_LENGTH+1]="";
- char logonDomain[MAX_DOMAIN_LENGTH+1]="";
-
- MSV1_0_INTERACTIVE_LOGON *IL;
-
- DWORD code = 0;
-
- char *reason;
- char *ctemp;
-
- BOOLEAN interactive = TRUE;
- HWND hwndOwner = (HWND)StationHandle;
- BOOLEAN lowercased_name = TRUE;
-
- /* Can we load KFW binaries? */
- if ( !KFW_is_available() )
- return 0;
-
- DebugEvent0("NPLogonNotify start");
-
- /* Remote Desktop / Terminal Server connections to existing sessions
- * are interactive logons. Unfortunately, because the session already
- * exists the logon script does not get executed and this prevents
- * us from being able to execute the rundll32 entrypoint
- * LogonEventHandlerA which would process the credential cache this
- * routine will produce. Therefore, we must cleanup orphaned cache
- * files from this routine. We will take care of it before doing
- * anything else.
- */
- KFW_cleanup_orphaned_caches();
-
- /* Are we interactive? */
- if (lpStationName)
- interactive = (wcsicmp(lpStationName, L"WinSta0") == 0);
-
- if ( !interactive ) {
- char station[64]="station";
- DWORD rv;
-
- SetLastError(0);
- rv = WideCharToMultiByte(CP_UTF8, 0, lpStationName, -1,
- station, sizeof(station), NULL, NULL);
- DebugEvent("Skipping NPLogonNotify- LoginId(%d,%d) - Interactive(%d:%s) - gle %d",
- lpLogonId->HighPart, lpLogonId->LowPart, interactive, rv != 0 ? station : "failure", GetLastError());
- return 0;
- } else
- DebugEvent("NPLogonNotify - LoginId(%d,%d)", lpLogonId->HighPart, lpLogonId->LowPart);
-
- /* Initialize Logon Script to none */
- *lpLogonScript=NULL;
-
- /* MSV1_0_INTERACTIVE_LOGON and KERB_INTERACTIVE_LOGON are equivalent for
- * our purposes */
-
- if ( wcsicmp(lpAuthentInfoType,L"MSV1_0:Interactive") &&
- wcsicmp(lpAuthentInfoType,L"Kerberos:Interactive") )
- {
- char msg[64];
- WideCharToMultiByte(CP_ACP, 0, lpAuthentInfoType, -1,
- msg, sizeof(msg), NULL, NULL);
- msg[sizeof(msg)-1]='\0';
- DebugEvent("NPLogonNotify - Unsupported Authentication Info Type: %s", msg);
- return 0;
- }
-
- IL = (MSV1_0_INTERACTIVE_LOGON *) lpAuthentInfo;
-
- /* Convert from Unicode to ANSI */
-
- /*TODO: Use SecureZeroMemory to erase passwords */
- if (!UnicodeStringToANSI(IL->UserName, uname, MAX_USERNAME_LENGTH) ||
- !UnicodeStringToANSI(IL->Password, password, MAX_PASSWORD_LENGTH) ||
- !UnicodeStringToANSI(IL->LogonDomainName, logonDomain, MAX_DOMAIN_LENGTH))
- return 0;
-
- /* Make sure AD-DOMAINS sent from login that is sent to us is stripped */
- ctemp = strchr(uname, '@');
- if (ctemp) *ctemp = 0;
-
- /* is the name all lowercase? */
- for ( ctemp = uname; *ctemp ; ctemp++) {
- if ( !islower(*ctemp) ) {
- lowercased_name = FALSE;
- break;
- }
- }
-
- code = KFW_get_cred(uname, password, 0, &reason);
- DebugEvent("NPLogonNotify - KFW_get_cred uname=[%s] code=[%d]",uname, code);
-
- /* remove any kerberos 5 tickets currently held by the SYSTEM account
- * for this user
- */
- if (!code) {
- char filename[MAX_PATH+1] = "";
- char acctname[MAX_USERNAME_LENGTH+MAX_DOMAIN_LENGTH+3]="";
- PSID pUserSid = NULL;
- LPTSTR pReferencedDomainName = NULL;
- DWORD dwSidLen = 0, dwDomainLen = 0, count;
- SID_NAME_USE eUse;
-
- if (_snprintf(acctname, sizeof(acctname), "%s\\%s", logonDomain, uname) < 0) {
- code = -1;
- goto cleanup;
- }
-
- count = GetTempPath(sizeof(filename), filename);
- if (count == 0 || count > (sizeof(filename)-1)) {
- code = -1;
- goto cleanup;
- }
-
- if (_snprintf(filename, sizeof(filename), "%s\\kfwlogon-%x.%x",
- filename, lpLogonId->HighPart, lpLogonId->LowPart) < 0)
- {
- code = -1;
- goto cleanup;
- }
-
- KFW_copy_cache_to_system_file(uname, filename);
-
- /* Need to determine the SID */
-
- /* First get the size of the required buffers */
- LookupAccountName (NULL,
- acctname,
- pUserSid,
- &dwSidLen,
- pReferencedDomainName,
- &dwDomainLen,
- &eUse);
- if(dwSidLen){
- pUserSid = (PSID) malloc (dwSidLen);
- memset(pUserSid,0,dwSidLen);
- }
-
- if(dwDomainLen){
- pReferencedDomainName = (LPTSTR) malloc (dwDomainLen * sizeof(TCHAR));
- memset(pReferencedDomainName,0,dwDomainLen * sizeof(TCHAR));
- }
-
- //Now get the SID and the domain name
- if (pUserSid && LookupAccountName( NULL,
- acctname,
- pUserSid,
- &dwSidLen,
- pReferencedDomainName,
- &dwDomainLen,
- &eUse))
- {
- DebugEvent("LookupAccountName obtained user %s sid in domain %s", acctname, pReferencedDomainName);
- code = KFW_set_ccache_dacl_with_user_sid(filename, pUserSid);
-
-#ifdef USE_WINLOGON_EVENT
- /* If we are on Vista, setup a LogonScript
- * that will execute the LogonEventHandler entry point via rundll32.exe
- */
- if (is_windows_vista()) {
- ConfigureLogonScript(lpLogonScript, filename);
- if (*lpLogonScript)
- DebugEvent0("LogonScript assigned");
- else
- DebugEvent0("No Logon Script");
- }
-#else
- ConfigureLogonScript(lpLogonScript, filename);
- if (*lpLogonScript)
- DebugEvent0("LogonScript assigned");
- else
- DebugEvent0("No Logon Script");
-#endif
- } else {
- DebugEvent0("LookupAccountName failed");
- DeleteFile(filename);
- code = -1;
- }
-
- cleanup:
- if (pUserSid)
- free(pUserSid);
- if (pReferencedDomainName)
- free(pReferencedDomainName);
- }
-
- KFW_destroy_tickets_for_principal(uname);
-
- if (code) {
- char msg[128];
- HANDLE h;
- char *ptbuf[1];
-
- StringCbPrintf(msg, sizeof(msg), "Kerberos ticket acquisition failed: %s", reason);
-
- h = RegisterEventSource(NULL, KFW_LOGON_EVENT_NAME);
- ptbuf[0] = msg;
- ReportEvent(h, EVENTLOG_WARNING_TYPE, 0, 1008, NULL, 1, 0, ptbuf, NULL);
- DeregisterEventSource(h);
- SetLastError(code);
- }
-
- if (code)
- DebugEvent0("NPLogonNotify failure");
- else
- DebugEvent0("NPLogonNotify success");
-
- return code;
-}
-
-
-DWORD APIENTRY NPPasswordChangeNotify(
- LPCWSTR lpAuthentInfoType,
- LPVOID lpAuthentInfo,
- LPCWSTR lpPreviousAuthentInfoType,
- LPVOID lpPreviousAuthentInfo,
- LPWSTR lpStationName,
- LPVOID StationHandle,
- DWORD dwChangeInfo)
-{
- return 0;
-}
-
-#include <userenv.h>
-#include <Winwlx.h>
-
-#ifdef COMMENT
-typedef struct _WLX_NOTIFICATION_INFO {
- ULONG Size;
- ULONG Flags;
- PWSTR UserName;
- PWSTR Domain;
- PWSTR WindowStation;
- HANDLE hToken;
- HDESK hDesktop;
- PFNMSGECALLBACK pStatusCallback;
-} WLX_NOTIFICATION_INFO, *PWLX_NOTIFICATION_INFO;
-#endif
-
-VOID KFW_Startup_Event( PWLX_NOTIFICATION_INFO pInfo )
-{
- DebugEvent0("KFW_Startup_Event");
-}
-
-static BOOL
-GetSecurityLogonSessionData(HANDLE hToken, PSECURITY_LOGON_SESSION_DATA * ppSessionData)
-{
- NTSTATUS Status = 0;
-#if 0
- HANDLE TokenHandle;
-#endif
- TOKEN_STATISTICS Stats;
- DWORD ReqLen;
- BOOL Success;
-
- if (!ppSessionData)
- return FALSE;
- *ppSessionData = NULL;
-
-#if 0
- Success = OpenProcessToken( HANDLE GetCurrentProcess(), TOKEN_QUERY, &TokenHandle );
- if ( !Success )
- return FALSE;
-#endif
-
- Success = GetTokenInformation( hToken, TokenStatistics, &Stats, sizeof(TOKEN_STATISTICS), &ReqLen );
-#if 0
- CloseHandle( TokenHandle );
-#endif
- if ( !Success )
- return FALSE;
-
- Status = LsaGetLogonSessionData( &Stats.AuthenticationId, ppSessionData );
- if ( FAILED(Status) || !ppSessionData )
- return FALSE;
-
- return TRUE;
-}
-
-VOID KFW_Logon_Event( PWLX_NOTIFICATION_INFO pInfo )
-{
-#ifdef USE_WINLOGON_EVENT
- WCHAR szUserW[128] = L"";
- char szUserA[128] = "";
- char szPath[MAX_PATH] = "";
- char szLogonId[128] = "";
- DWORD count;
- char filename[MAX_PATH] = "";
- char newfilename[MAX_PATH] = "";
- char commandline[MAX_PATH+256] = "";
- STARTUPINFO startupinfo;
- PROCESS_INFORMATION procinfo;
- HANDLE hf = NULL;
-
- LUID LogonId = {0, 0};
- PSECURITY_LOGON_SESSION_DATA pLogonSessionData = NULL;
-
- HKEY hKey1 = NULL, hKey2 = NULL;
-
- DebugEvent0("KFW_Logon_Event - Start");
-
- GetSecurityLogonSessionData( pInfo->hToken, &pLogonSessionData );
-
- if ( pLogonSessionData ) {
- LogonId = pLogonSessionData->LogonId;
- DebugEvent("KFW_Logon_Event - LogonId(%d,%d)", LogonId.HighPart, LogonId.LowPart);
-
- _snprintf(szLogonId, sizeof(szLogonId), "kfwlogon-%d.%d",LogonId.HighPart, LogonId.LowPart);
- LsaFreeReturnBuffer( pLogonSessionData );
- } else {
- DebugEvent0("KFW_Logon_Event - Unable to determine LogonId");
- return;
- }
-
- count = GetEnvironmentVariable("TEMP", filename, sizeof(filename));
- if ( count > sizeof(filename) || count == 0 ) {
- GetWindowsDirectory(filename, sizeof(filename));
- }
-
- if ( strlen(filename) + strlen(szLogonId) + 2 > sizeof(filename) ) {
- DebugEvent0("KFW_Logon_Event - filename too long");
- return;
- }
-
- strcat(filename, "\\");
- strcat(filename, szLogonId);
-
- hf = CreateFile(filename, FILE_ALL_ACCESS, 0, NULL, OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL, NULL);
- if (hf == INVALID_HANDLE_VALUE) {
- DebugEvent0("KFW_Logon_Event - file cannot be opened");
- return;
- }
- CloseHandle(hf);
-
- if (KFW_set_ccache_dacl(filename, pInfo->hToken)) {
- DebugEvent0("KFW_Logon_Event - unable to set dacl");
- DeleteFile(filename);
- return;
- }
-
- if (KFW_obtain_user_temp_directory(pInfo->hToken, newfilename, sizeof(newfilename))) {
- DebugEvent0("KFW_Logon_Event - unable to obtain temp directory");
- return;
- }
-
- if ( strlen(newfilename) + strlen(szLogonId) + 2 > sizeof(newfilename) ) {
- DebugEvent0("KFW_Logon_Event - new filename too long");
- return;
- }
-
- strcat(newfilename, "\\");
- strcat(newfilename, szLogonId);
-
- if (!MoveFileEx(filename, newfilename,
- MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH)) {
- DebugEvent("KFW_Logon_Event - MoveFileEx failed GLE = 0x%x", GetLastError());
- return;
- }
-
- _snprintf(commandline, sizeof(commandline), "kfwcpcc.exe \"%s\"", newfilename);
-
- GetStartupInfo(&startupinfo);
- if (CreateProcessAsUser( pInfo->hToken,
- "kfwcpcc.exe",
- commandline,
- NULL,
- NULL,
- FALSE,
- CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS,
- NULL,
- NULL,
- &startupinfo,
- &procinfo))
- {
- DebugEvent("KFW_Logon_Event - CommandLine %s", commandline);
-
- WaitForSingleObject(procinfo.hProcess, 30000);
-
- CloseHandle(procinfo.hThread);
- CloseHandle(procinfo.hProcess);
- } else {
- DebugEvent0("KFW_Logon_Event - CreateProcessFailed");
- }
-
- DeleteFile(newfilename);
-
- DebugEvent0("KFW_Logon_Event - End");
-#endif /* USE_WINLOGON_EVENT */
-}
-
-
-/* Documentation on the use of RunDll32 entrypoints can be found
- * at http://support.microsoft.com/kb/164787
- */
-void CALLBACK
-LogonEventHandlerA(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
-{
- HANDLE hf = NULL;
- char commandline[MAX_PATH+256] = "";
- STARTUPINFO startupinfo;
- PROCESS_INFORMATION procinfo;
-
- DebugEvent0("LogonEventHandler - Start");
-
- /* Validate lpszCmdLine as a file */
- hf = CreateFile(lpszCmdLine, GENERIC_READ | DELETE, 0, NULL, OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL, NULL);
- if (hf == INVALID_HANDLE_VALUE) {
- DebugEvent("LogonEventHandler - \"%s\" cannot be opened", lpszCmdLine);
- return;
- }
- CloseHandle(hf);
-
-
- _snprintf(commandline, sizeof(commandline), "kfwcpcc.exe \"%s\"", lpszCmdLine);
-
- GetStartupInfo(&startupinfo);
- SetLastError(0);
- if (CreateProcess( NULL,
- commandline,
- NULL,
- NULL,
- FALSE,
- CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS,
- NULL,
- NULL,
- &startupinfo,
- &procinfo))
- {
- DebugEvent("KFW_Logon_Event - CommandLine %s", commandline);
-
- WaitForSingleObject(procinfo.hProcess, 30000);
-
- CloseHandle(procinfo.hThread);
- CloseHandle(procinfo.hProcess);
- } else {
- DebugEvent("KFW_Logon_Event - CreateProcessFailed \"%s\" GLE 0x%x",
- commandline, GetLastError());
- DebugEvent("KFW_Logon_Event PATH %s", getenv("PATH"));
- }
-
- DeleteFile(lpszCmdLine);
-
- DebugEvent0("KFW_Logon_Event - End");
-}
+/*
+Copyright 2005,2006 by the Massachusetts Institute of Technology
+Copyright 2007 by Secure Endpoints Inc.
+
+All rights reserved.
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of the Massachusetts
+Institute of Technology (M.I.T.) not be used in advertising or publicity
+pertaining to distribution of the software without specific, written
+prior permission.
+
+M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+*/
+
+#include "kfwlogon.h"
+
+#include <io.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+
+#include <winsock2.h>
+#include <lm.h>
+#include <nb30.h>
+
+static HANDLE hDLL;
+
+static HANDLE hInitMutex = NULL;
+static BOOL bInit = FALSE;
+
+
+BOOLEAN APIENTRY DllEntryPoint(HANDLE dll, DWORD reason, PVOID reserved)
+{
+ hDLL = dll;
+ switch (reason) {
+ case DLL_PROCESS_ATTACH:
+ /* Initialization Mutex */
+ hInitMutex = CreateMutex(NULL, FALSE, NULL);
+ break;
+
+ case DLL_PROCESS_DETACH:
+ CloseHandle(hInitMutex);
+ break;
+
+ case DLL_THREAD_ATTACH:
+ case DLL_THREAD_DETACH:
+ default:
+ /* Everything else succeeds but does nothing. */
+ break;
+ }
+
+ return TRUE;
+}
+
+DWORD APIENTRY NPGetCaps(DWORD index)
+{
+ switch (index) {
+ case WNNC_NET_TYPE:
+ /* We aren't a file system; We don't have our own type; use somebody else's. */
+ return WNNC_NET_SUN_PC_NFS;
+ case WNNC_START:
+ /* Say we are already started, even though we might wait after we receive NPLogonNotify */
+ return 1;
+
+ default:
+ return 0;
+ }
+}
+
+
+static BOOL
+WINAPI
+UnicodeStringToANSI(UNICODE_STRING uInputString, LPSTR lpszOutputString, int nOutStringLen)
+{
+ CPINFO CodePageInfo;
+
+ GetCPInfo(CP_ACP, &CodePageInfo);
+
+ if (CodePageInfo.MaxCharSize > 1)
+ // Only supporting non-Unicode strings
+ return FALSE;
+
+ if (uInputString.Buffer && ((LPBYTE) uInputString.Buffer)[1] == '\0')
+ {
+ // Looks like unicode, better translate it
+ // UNICODE_STRING specifies the length of the buffer string in Bytes not WCHARS
+ WideCharToMultiByte(CP_ACP, 0, (LPCWSTR) uInputString.Buffer, uInputString.Length/2,
+ lpszOutputString, nOutStringLen-1, NULL, NULL);
+ lpszOutputString[min(uInputString.Length/2,nOutStringLen-1)] = '\0';
+ return TRUE;
+ }
+
+ lpszOutputString[0] = '\0';
+ return FALSE;
+} // UnicodeStringToANSI
+
+
+static BOOL
+is_windows_vista(void)
+{
+ static BOOL fChecked = FALSE;
+ static BOOL fIsWinVista = FALSE;
+
+ if (!fChecked)
+ {
+ OSVERSIONINFO Version;
+
+ memset (&Version, 0x00, sizeof(Version));
+ Version.dwOSVersionInfoSize = sizeof(Version);
+
+ if (GetVersionEx (&Version))
+ {
+ if (Version.dwPlatformId == VER_PLATFORM_WIN32_NT &&
+ Version.dwMajorVersion >= 6)
+ fIsWinVista = TRUE;
+ }
+ fChecked = TRUE;
+ }
+
+ return fIsWinVista;
+}
+
+
+/* Construct a Logon Script that will cause the LogonEventHandler to be executed
+ * under in the logon session
+ */
+
+#define RUNDLL32_CMDLINE "rundll32.exe kfwlogon.dll,LogonEventHandler "
+VOID
+ConfigureLogonScript(LPWSTR *lpLogonScript, char * filename) {
+ DWORD dwLogonScriptLen;
+ LPWSTR lpScript;
+ LPSTR lpTemp;
+
+ if (!lpLogonScript)
+ return;
+ *lpLogonScript = NULL;
+
+ if (!filename)
+ return;
+
+ dwLogonScriptLen = strlen(RUNDLL32_CMDLINE) + strlen(filename) + 2;
+ lpTemp = (LPSTR) malloc(dwLogonScriptLen);
+ if (!lpTemp)
+ return;
+
+ _snprintf(lpTemp, dwLogonScriptLen, "%s%s", RUNDLL32_CMDLINE, filename);
+
+ SetLastError(0);
+ dwLogonScriptLen = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, lpTemp, -1, NULL, 0);
+ DebugEvent("ConfigureLogonScript %s requires %d bytes gle=0x%x", lpTemp, dwLogonScriptLen, GetLastError());
+
+ lpScript = LocalAlloc(LMEM_ZEROINIT, dwLogonScriptLen * 2);
+ if (lpScript) {
+ if (MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, lpTemp, -1, lpScript, 2 * dwLogonScriptLen))
+ *lpLogonScript = lpScript;
+ else {
+ DebugEvent("ConfigureLogonScript - MultiByteToWideChar failed gle = 0x%x", GetLastError());
+ LocalFree(lpScript);
+ }
+ } else {
+ DebugEvent("LocalAlloc failed gle=0x%x", GetLastError());
+ }
+ free(lpTemp);
+}
+
+
+DWORD APIENTRY NPLogonNotify(
+ PLUID lpLogonId,
+ LPCWSTR lpAuthentInfoType,
+ LPVOID lpAuthentInfo,
+ LPCWSTR lpPreviousAuthentInfoType,
+ LPVOID lpPreviousAuthentInfo,
+ LPWSTR lpStationName,
+ LPVOID StationHandle,
+ LPWSTR *lpLogonScript)
+{
+ char uname[MAX_USERNAME_LENGTH+1]="";
+ char password[MAX_PASSWORD_LENGTH+1]="";
+ char logonDomain[MAX_DOMAIN_LENGTH+1]="";
+
+ MSV1_0_INTERACTIVE_LOGON *IL;
+
+ DWORD code = 0;
+
+ char *reason;
+ char *ctemp;
+
+ BOOLEAN interactive = TRUE;
+ HWND hwndOwner = (HWND)StationHandle;
+ BOOLEAN lowercased_name = TRUE;
+
+ /* Can we load KFW binaries? */
+ if ( !KFW_is_available() )
+ return 0;
+
+ DebugEvent0("NPLogonNotify start");
+
+ /* Remote Desktop / Terminal Server connections to existing sessions
+ * are interactive logons. Unfortunately, because the session already
+ * exists the logon script does not get executed and this prevents
+ * us from being able to execute the rundll32 entrypoint
+ * LogonEventHandlerA which would process the credential cache this
+ * routine will produce. Therefore, we must cleanup orphaned cache
+ * files from this routine. We will take care of it before doing
+ * anything else.
+ */
+ KFW_cleanup_orphaned_caches();
+
+ /* Are we interactive? */
+ if (lpStationName)
+ interactive = (wcsicmp(lpStationName, L"WinSta0") == 0);
+
+ if ( !interactive ) {
+ char station[64]="station";
+ DWORD rv;
+
+ SetLastError(0);
+ rv = WideCharToMultiByte(CP_UTF8, 0, lpStationName, -1,
+ station, sizeof(station), NULL, NULL);
+ DebugEvent("Skipping NPLogonNotify- LoginId(%d,%d) - Interactive(%d:%s) - gle %d",
+ lpLogonId->HighPart, lpLogonId->LowPart, interactive, rv != 0 ? station : "failure", GetLastError());
+ return 0;
+ } else
+ DebugEvent("NPLogonNotify - LoginId(%d,%d)", lpLogonId->HighPart, lpLogonId->LowPart);
+
+ /* Initialize Logon Script to none */
+ *lpLogonScript=NULL;
+
+ /* MSV1_0_INTERACTIVE_LOGON and KERB_INTERACTIVE_LOGON are equivalent for
+ * our purposes */
+
+ if ( wcsicmp(lpAuthentInfoType,L"MSV1_0:Interactive") &&
+ wcsicmp(lpAuthentInfoType,L"Kerberos:Interactive") )
+ {
+ char msg[64];
+ WideCharToMultiByte(CP_ACP, 0, lpAuthentInfoType, -1,
+ msg, sizeof(msg), NULL, NULL);
+ msg[sizeof(msg)-1]='\0';
+ DebugEvent("NPLogonNotify - Unsupported Authentication Info Type: %s", msg);
+ return 0;
+ }
+
+ IL = (MSV1_0_INTERACTIVE_LOGON *) lpAuthentInfo;
+
+ /* Convert from Unicode to ANSI */
+
+ /*TODO: Use SecureZeroMemory to erase passwords */
+ if (!UnicodeStringToANSI(IL->UserName, uname, MAX_USERNAME_LENGTH) ||
+ !UnicodeStringToANSI(IL->Password, password, MAX_PASSWORD_LENGTH) ||
+ !UnicodeStringToANSI(IL->LogonDomainName, logonDomain, MAX_DOMAIN_LENGTH))
+ return 0;
+
+ /* Make sure AD-DOMAINS sent from login that is sent to us is stripped */
+ ctemp = strchr(uname, '@');
+ if (ctemp) *ctemp = 0;
+
+ /* is the name all lowercase? */
+ for ( ctemp = uname; *ctemp ; ctemp++) {
+ if ( !islower(*ctemp) ) {
+ lowercased_name = FALSE;
+ break;
+ }
+ }
+
+ code = KFW_get_cred(uname, password, 0, &reason);
+ DebugEvent("NPLogonNotify - KFW_get_cred uname=[%s] code=[%d]",uname, code);
+
+ /* remove any kerberos 5 tickets currently held by the SYSTEM account
+ * for this user
+ */
+ if (!code) {
+ char filename[MAX_PATH+1] = "";
+ char acctname[MAX_USERNAME_LENGTH+MAX_DOMAIN_LENGTH+3]="";
+ PSID pUserSid = NULL;
+ LPTSTR pReferencedDomainName = NULL;
+ DWORD dwSidLen = 0, dwDomainLen = 0, count;
+ SID_NAME_USE eUse;
+
+ if (_snprintf(acctname, sizeof(acctname), "%s\\%s", logonDomain, uname) < 0) {
+ code = -1;
+ goto cleanup;
+ }
+
+ count = GetTempPath(sizeof(filename), filename);
+ if (count == 0 || count > (sizeof(filename)-1)) {
+ code = -1;
+ goto cleanup;
+ }
+
+ if (_snprintf(filename, sizeof(filename), "%s\\kfwlogon-%x.%x",
+ filename, lpLogonId->HighPart, lpLogonId->LowPart) < 0)
+ {
+ code = -1;
+ goto cleanup;
+ }
+
+ KFW_copy_cache_to_system_file(uname, filename);
+
+ /* Need to determine the SID */
+
+ /* First get the size of the required buffers */
+ LookupAccountName (NULL,
+ acctname,
+ pUserSid,
+ &dwSidLen,
+ pReferencedDomainName,
+ &dwDomainLen,
+ &eUse);
+ if(dwSidLen){
+ pUserSid = (PSID) malloc (dwSidLen);
+ memset(pUserSid,0,dwSidLen);
+ }
+
+ if(dwDomainLen){
+ pReferencedDomainName = (LPTSTR) malloc (dwDomainLen * sizeof(TCHAR));
+ memset(pReferencedDomainName,0,dwDomainLen * sizeof(TCHAR));
+ }
+
+ //Now get the SID and the domain name
+ if (pUserSid && LookupAccountName( NULL,
+ acctname,
+ pUserSid,
+ &dwSidLen,
+ pReferencedDomainName,
+ &dwDomainLen,
+ &eUse))
+ {
+ DebugEvent("LookupAccountName obtained user %s sid in domain %s", acctname, pReferencedDomainName);
+ code = KFW_set_ccache_dacl_with_user_sid(filename, pUserSid);
+
+#ifdef USE_WINLOGON_EVENT
+ /* If we are on Vista, setup a LogonScript
+ * that will execute the LogonEventHandler entry point via rundll32.exe
+ */
+ if (is_windows_vista()) {
+ ConfigureLogonScript(lpLogonScript, filename);
+ if (*lpLogonScript)
+ DebugEvent0("LogonScript assigned");
+ else
+ DebugEvent0("No Logon Script");
+ }
+#else
+ ConfigureLogonScript(lpLogonScript, filename);
+ if (*lpLogonScript)
+ DebugEvent0("LogonScript assigned");
+ else
+ DebugEvent0("No Logon Script");
+#endif
+ } else {
+ DebugEvent0("LookupAccountName failed");
+ DeleteFile(filename);
+ code = -1;
+ }
+
+ cleanup:
+ if (pUserSid)
+ free(pUserSid);
+ if (pReferencedDomainName)
+ free(pReferencedDomainName);
+ }
+
+ KFW_destroy_tickets_for_principal(uname);
+
+ if (code) {
+ char msg[128];
+ HANDLE h;
+ char *ptbuf[1];
+
+ StringCbPrintf(msg, sizeof(msg), "Kerberos ticket acquisition failed: %s", reason);
+
+ h = RegisterEventSource(NULL, KFW_LOGON_EVENT_NAME);
+ ptbuf[0] = msg;
+ ReportEvent(h, EVENTLOG_WARNING_TYPE, 0, 1008, NULL, 1, 0, ptbuf, NULL);
+ DeregisterEventSource(h);
+ SetLastError(code);
+ }
+
+ if (code)
+ DebugEvent0("NPLogonNotify failure");
+ else
+ DebugEvent0("NPLogonNotify success");
+
+ return code;
+}
+
+
+DWORD APIENTRY NPPasswordChangeNotify(
+ LPCWSTR lpAuthentInfoType,
+ LPVOID lpAuthentInfo,
+ LPCWSTR lpPreviousAuthentInfoType,
+ LPVOID lpPreviousAuthentInfo,
+ LPWSTR lpStationName,
+ LPVOID StationHandle,
+ DWORD dwChangeInfo)
+{
+ return 0;
+}
+
+#include <userenv.h>
+#include <Winwlx.h>
+
+#ifdef COMMENT
+typedef struct _WLX_NOTIFICATION_INFO {
+ ULONG Size;
+ ULONG Flags;
+ PWSTR UserName;
+ PWSTR Domain;
+ PWSTR WindowStation;
+ HANDLE hToken;
+ HDESK hDesktop;
+ PFNMSGECALLBACK pStatusCallback;
+} WLX_NOTIFICATION_INFO, *PWLX_NOTIFICATION_INFO;
+#endif
+
+VOID KFW_Startup_Event( PWLX_NOTIFICATION_INFO pInfo )
+{
+ DebugEvent0("KFW_Startup_Event");
+}
+
+static BOOL
+GetSecurityLogonSessionData(HANDLE hToken, PSECURITY_LOGON_SESSION_DATA * ppSessionData)
+{
+ NTSTATUS Status = 0;
+#if 0
+ HANDLE TokenHandle;
+#endif
+ TOKEN_STATISTICS Stats;
+ DWORD ReqLen;
+ BOOL Success;
+
+ if (!ppSessionData)
+ return FALSE;
+ *ppSessionData = NULL;
+
+#if 0
+ Success = OpenProcessToken( HANDLE GetCurrentProcess(), TOKEN_QUERY, &TokenHandle );
+ if ( !Success )
+ return FALSE;
+#endif
+
+ Success = GetTokenInformation( hToken, TokenStatistics, &Stats, sizeof(TOKEN_STATISTICS), &ReqLen );
+#if 0
+ CloseHandle( TokenHandle );
+#endif
+ if ( !Success )
+ return FALSE;
+
+ Status = LsaGetLogonSessionData( &Stats.AuthenticationId, ppSessionData );
+ if ( FAILED(Status) || !ppSessionData )
+ return FALSE;
+
+ return TRUE;
+}
+
+VOID KFW_Logon_Event( PWLX_NOTIFICATION_INFO pInfo )
+{
+#ifdef USE_WINLOGON_EVENT
+ WCHAR szUserW[128] = L"";
+ char szUserA[128] = "";
+ char szPath[MAX_PATH] = "";
+ char szLogonId[128] = "";
+ DWORD count;
+ char filename[MAX_PATH] = "";
+ char newfilename[MAX_PATH] = "";
+ char commandline[MAX_PATH+256] = "";
+ STARTUPINFO startupinfo;
+ PROCESS_INFORMATION procinfo;
+ HANDLE hf = NULL;
+
+ LUID LogonId = {0, 0};
+ PSECURITY_LOGON_SESSION_DATA pLogonSessionData = NULL;
+
+ HKEY hKey1 = NULL, hKey2 = NULL;
+
+ DebugEvent0("KFW_Logon_Event - Start");
+
+ GetSecurityLogonSessionData( pInfo->hToken, &pLogonSessionData );
+
+ if ( pLogonSessionData ) {
+ LogonId = pLogonSessionData->LogonId;
+ DebugEvent("KFW_Logon_Event - LogonId(%d,%d)", LogonId.HighPart, LogonId.LowPart);
+
+ _snprintf(szLogonId, sizeof(szLogonId), "kfwlogon-%d.%d",LogonId.HighPart, LogonId.LowPart);
+ LsaFreeReturnBuffer( pLogonSessionData );
+ } else {
+ DebugEvent0("KFW_Logon_Event - Unable to determine LogonId");
+ return;
+ }
+
+ count = GetEnvironmentVariable("TEMP", filename, sizeof(filename));
+ if ( count > sizeof(filename) || count == 0 ) {
+ GetWindowsDirectory(filename, sizeof(filename));
+ }
+
+ if ( strlen(filename) + strlen(szLogonId) + 2 > sizeof(filename) ) {
+ DebugEvent0("KFW_Logon_Event - filename too long");
+ return;
+ }
+
+ strcat(filename, "\\");
+ strcat(filename, szLogonId);
+
+ hf = CreateFile(filename, FILE_ALL_ACCESS, 0, NULL, OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL, NULL);
+ if (hf == INVALID_HANDLE_VALUE) {
+ DebugEvent0("KFW_Logon_Event - file cannot be opened");
+ return;
+ }
+ CloseHandle(hf);
+
+ if (KFW_set_ccache_dacl(filename, pInfo->hToken)) {
+ DebugEvent0("KFW_Logon_Event - unable to set dacl");
+ DeleteFile(filename);
+ return;
+ }
+
+ if (KFW_obtain_user_temp_directory(pInfo->hToken, newfilename, sizeof(newfilename))) {
+ DebugEvent0("KFW_Logon_Event - unable to obtain temp directory");
+ return;
+ }
+
+ if ( strlen(newfilename) + strlen(szLogonId) + 2 > sizeof(newfilename) ) {
+ DebugEvent0("KFW_Logon_Event - new filename too long");
+ return;
+ }
+
+ strcat(newfilename, "\\");
+ strcat(newfilename, szLogonId);
+
+ if (!MoveFileEx(filename, newfilename,
+ MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH)) {
+ DebugEvent("KFW_Logon_Event - MoveFileEx failed GLE = 0x%x", GetLastError());
+ return;
+ }
+
+ _snprintf(commandline, sizeof(commandline), "kfwcpcc.exe \"%s\"", newfilename);
+
+ GetStartupInfo(&startupinfo);
+ if (CreateProcessAsUser( pInfo->hToken,
+ "kfwcpcc.exe",
+ commandline,
+ NULL,
+ NULL,
+ FALSE,
+ CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS,
+ NULL,
+ NULL,
+ &startupinfo,
+ &procinfo))
+ {
+ DebugEvent("KFW_Logon_Event - CommandLine %s", commandline);
+
+ WaitForSingleObject(procinfo.hProcess, 30000);
+
+ CloseHandle(procinfo.hThread);
+ CloseHandle(procinfo.hProcess);
+ } else {
+ DebugEvent0("KFW_Logon_Event - CreateProcessFailed");
+ }
+
+ DeleteFile(newfilename);
+
+ DebugEvent0("KFW_Logon_Event - End");
+#endif /* USE_WINLOGON_EVENT */
+}
+
+
+/* Documentation on the use of RunDll32 entrypoints can be found
+ * at http://support.microsoft.com/kb/164787
+ */
+void CALLBACK
+LogonEventHandlerA(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
+{
+ HANDLE hf = NULL;
+ char commandline[MAX_PATH+256] = "";
+ STARTUPINFO startupinfo;
+ PROCESS_INFORMATION procinfo;
+
+ DebugEvent0("LogonEventHandler - Start");
+
+ /* Validate lpszCmdLine as a file */
+ hf = CreateFile(lpszCmdLine, GENERIC_READ | DELETE, 0, NULL, OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL, NULL);
+ if (hf == INVALID_HANDLE_VALUE) {
+ DebugEvent("LogonEventHandler - \"%s\" cannot be opened", lpszCmdLine);
+ return;
+ }
+ CloseHandle(hf);
+
+
+ _snprintf(commandline, sizeof(commandline), "kfwcpcc.exe \"%s\"", lpszCmdLine);
+
+ GetStartupInfo(&startupinfo);
+ SetLastError(0);
+ if (CreateProcess( NULL,
+ commandline,
+ NULL,
+ NULL,
+ FALSE,
+ CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS,
+ NULL,
+ NULL,
+ &startupinfo,
+ &procinfo))
+ {
+ DebugEvent("KFW_Logon_Event - CommandLine %s", commandline);
+
+ WaitForSingleObject(procinfo.hProcess, 30000);
+
+ CloseHandle(procinfo.hThread);
+ CloseHandle(procinfo.hProcess);
+ } else {
+ DebugEvent("KFW_Logon_Event - CreateProcessFailed \"%s\" GLE 0x%x",
+ commandline, GetLastError());
+ DebugEvent("KFW_Logon_Event PATH %s", getenv("PATH"));
+ }
+
+ DeleteFile(lpszCmdLine);
+
+ DebugEvent0("KFW_Logon_Event - End");
+}
diff --git a/src/windows/kfwlogon/kfwlogon.h b/src/windows/kfwlogon/kfwlogon.h
index cfbe4fd381..2f1a62b6ed 100644
--- a/src/windows/kfwlogon/kfwlogon.h
+++ b/src/windows/kfwlogon/kfwlogon.h
@@ -1,215 +1,215 @@
-/*
-
-Copyright 2005,2006 by the Massachusetts Institute of Technology
-Copyright 2007 by Secure Endpoints Inc.
-
-All rights reserved.
-
-Permission to use, copy, modify, and distribute this software and its
-documentation for any purpose and without fee is hereby granted,
-provided that the above copyright notice appear in all copies and that
-both that copyright notice and this permission notice appear in
-supporting documentation, and that the name of the Massachusetts
-Institute of Technology (M.I.T.) not be used in advertising or publicity
-pertaining to distribution of the software without specific, written
-prior permission.
-
-M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
-M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
-WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
-ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
-SOFTWARE.
-
-*/
-
-/* We only support VC 1200 and above anyway */
-#pragma once
-
-/* _WIN32_WINNT must be 0x0501 or greater to pull in definition of
- * all required LSA data types when the Vista SDK NtSecAPI.h is used.
- */
-#ifndef _WIN32_WINNT
-#define _WIN32_WINNT 0x0501
-#else
-#if _WIN32_WINNT < 0x0501
-#undef _WIN32_WINNT
-#define _WIN32_WINNT 0x0501
-#endif
-#endif
-
-#include <windows.h>
-#include <npapi.h>
-#define SECURITY_WIN32
-#include <security.h>
-#include <ntsecapi.h>
-#include <tchar.h>
-#include <strsafe.h>
-
-typedef int errcode_t;
-
-#include <loadfuncs-lsa.h>
-#include <krb5.h>
-#include <loadfuncs-com_err.h>
-#include <loadfuncs-krb5.h>
-#include <loadfuncs-profile.h>
-#include <loadfuncs-leash.h>
-
-// service definitions
-#define SERVICE_DLL "advapi32.dll"
-typedef SC_HANDLE (WINAPI *FP_OpenSCManagerA)(char *, char *, DWORD);
-typedef SC_HANDLE (WINAPI *FP_OpenServiceA)(SC_HANDLE, char *, DWORD);
-typedef BOOL (WINAPI *FP_QueryServiceStatus)(SC_HANDLE, LPSERVICE_STATUS);
-typedef BOOL (WINAPI *FP_CloseServiceHandle)(SC_HANDLE);
-
-/* In order to avoid including the private CCAPI headers */
-typedef int cc_int32;
-
-#define CC_API_VER_1 1
-#define CC_API_VER_2 2
-
-#define CCACHE_API cc_int32
-
-/*
-** The Official Error Codes
-*/
-#define CC_NOERROR 0
-#define CC_BADNAME 1
-#define CC_NOTFOUND 2
-#define CC_END 3
-#define CC_IO 4
-#define CC_WRITE 5
-#define CC_NOMEM 6
-#define CC_FORMAT 7
-#define CC_LOCKED 8
-#define CC_BAD_API_VERSION 9
-#define CC_NO_EXIST 10
-#define CC_NOT_SUPP 11
-#define CC_BAD_PARM 12
-#define CC_ERR_CACHE_ATTACH 13
-#define CC_ERR_CACHE_RELEASE 14
-#define CC_ERR_CACHE_FULL 15
-#define CC_ERR_CRED_VERSION 16
-
-enum {
- CC_CRED_VUNKNOWN = 0, // For validation
- CC_CRED_V4 = 1,
- CC_CRED_V5 = 2,
- CC_CRED_VMAX = 3 // For validation
-};
-
-typedef struct opaque_dll_control_block_type* apiCB;
-typedef struct _infoNC {
- char* name;
- char* principal;
- cc_int32 vers;
-} infoNC;
-
-TYPEDEF_FUNC(
-CCACHE_API,
-CALLCONV_C,
-cc_initialize,
- (
- apiCB** cc_ctx, // < DLL's primary control structure.
- // returned here, passed everywhere else
- cc_int32 api_version, // > ver supported by caller (use CC_API_VER_1)
- cc_int32* api_supported, // < if ~NULL, max ver supported by DLL
- const char** vendor // < if ~NULL, vendor name in read only C string
- )
-);
-
-TYPEDEF_FUNC(
-CCACHE_API,
-CALLCONV_C,
-cc_shutdown,
- (
- apiCB** cc_ctx // <> DLL's primary control structure. NULL after
- )
-);
-
-TYPEDEF_FUNC(
-CCACHE_API,
-CALLCONV_C,
-cc_get_NC_info,
- (
- apiCB* cc_ctx, // > DLL's primary control structure
- struct _infoNC*** ppNCi // < (NULL before call) null terminated,
- // list of a structs (free via cc_free_infoNC())
- )
-);
-
-TYPEDEF_FUNC(
-CCACHE_API,
-CALLCONV_C,
-cc_free_NC_info,
- (
- apiCB* cc_ctx,
- struct _infoNC*** ppNCi // < free list of structs returned by
- // cc_get_cache_names(). set to NULL on return
- )
-);
-/* End private ccapiv2 headers */
-
-#define CCAPI_DLL "krbcc32.dll"
-
-
-/* */
-#define MAX_USERNAME_LENGTH 256
-#define MAX_PASSWORD_LENGTH 256
-#define MAX_DOMAIN_LENGTH 256
-
-#define KFW_LOGON_EVENT_NAME TEXT("MIT Kerberos")
-
-BOOLEAN APIENTRY DllEntryPoint(HANDLE dll, DWORD reason, PVOID reserved);
-
-DWORD APIENTRY NPGetCaps(DWORD index);
-
-DWORD APIENTRY NPLogonNotify(
- PLUID lpLogonId,
- LPCWSTR lpAuthentInfoType,
- LPVOID lpAuthentInfo,
- LPCWSTR lpPreviousAuthentInfoType,
- LPVOID lpPreviousAuthentInfo,
- LPWSTR lpStationName,
- LPVOID StationHandle,
- LPWSTR *lpLogonScript);
-
-DWORD APIENTRY NPPasswordChangeNotify(
- LPCWSTR lpAuthentInfoType,
- LPVOID lpAuthentInfo,
- LPCWSTR lpPreviousAuthentInfoType,
- LPVOID lpPreviousAuthentInfo,
- LPWSTR lpStationName,
- LPVOID StationHandle,
- DWORD dwChangeInfo);
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-void UnloadFuncs(FUNC_INFO [], HINSTANCE);
-
-int LoadFuncs(const char*, FUNC_INFO [], HINSTANCE*, int*, int, int, int);
-
-void DebugEvent0(char *a);
-void DebugEvent(char *b,...);
-
-DWORD MapAuthError(DWORD code);
-
-static BOOL WINAPI UnicodeStringToANSI(UNICODE_STRING uInputString, LPSTR lpszOutputString, int nOutStringLen);
-
-int KFW_is_available(void);
-int KFW_get_cred( char * username, char * password, int lifetime, char ** reasonP );
-void KFW_copy_cache_to_system_file(const char * user, const char * filename);
-int KFW_destroy_tickets_for_principal(char * user);
-int KFW_set_ccache_dacl(char *filename, HANDLE hUserToken);
-int KFW_set_ccache_dacl_with_user_sid(char *filename, PSID pUserSID);
-int KFW_obtain_user_temp_directory(HANDLE hUserToken, char *newfilename, int size);
-void KFW_cleanup_orphaned_caches(void);
-
-void CALLBACK LogonEventHandlerA(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow);
-
-#ifdef __cplusplus
-}
-#endif
+/*
+
+Copyright 2005,2006 by the Massachusetts Institute of Technology
+Copyright 2007 by Secure Endpoints Inc.
+
+All rights reserved.
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of the Massachusetts
+Institute of Technology (M.I.T.) not be used in advertising or publicity
+pertaining to distribution of the software without specific, written
+prior permission.
+
+M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+*/
+
+/* We only support VC 1200 and above anyway */
+#pragma once
+
+/* _WIN32_WINNT must be 0x0501 or greater to pull in definition of
+ * all required LSA data types when the Vista SDK NtSecAPI.h is used.
+ */
+#ifndef _WIN32_WINNT
+#define _WIN32_WINNT 0x0501
+#else
+#if _WIN32_WINNT < 0x0501
+#undef _WIN32_WINNT
+#define _WIN32_WINNT 0x0501
+#endif
+#endif
+
+#include <windows.h>
+#include <npapi.h>
+#define SECURITY_WIN32
+#include <security.h>
+#include <ntsecapi.h>
+#include <tchar.h>
+#include <strsafe.h>
+
+typedef int errcode_t;
+
+#include <loadfuncs-lsa.h>
+#include <krb5.h>
+#include <loadfuncs-com_err.h>
+#include <loadfuncs-krb5.h>
+#include <loadfuncs-profile.h>
+#include <loadfuncs-leash.h>
+
+// service definitions
+#define SERVICE_DLL "advapi32.dll"
+typedef SC_HANDLE (WINAPI *FP_OpenSCManagerA)(char *, char *, DWORD);
+typedef SC_HANDLE (WINAPI *FP_OpenServiceA)(SC_HANDLE, char *, DWORD);
+typedef BOOL (WINAPI *FP_QueryServiceStatus)(SC_HANDLE, LPSERVICE_STATUS);
+typedef BOOL (WINAPI *FP_CloseServiceHandle)(SC_HANDLE);
+
+/* In order to avoid including the private CCAPI headers */
+typedef int cc_int32;
+
+#define CC_API_VER_1 1
+#define CC_API_VER_2 2
+
+#define CCACHE_API cc_int32
+
+/*
+** The Official Error Codes
+*/
+#define CC_NOERROR 0
+#define CC_BADNAME 1
+#define CC_NOTFOUND 2
+#define CC_END 3
+#define CC_IO 4
+#define CC_WRITE 5
+#define CC_NOMEM 6
+#define CC_FORMAT 7
+#define CC_LOCKED 8
+#define CC_BAD_API_VERSION 9
+#define CC_NO_EXIST 10
+#define CC_NOT_SUPP 11
+#define CC_BAD_PARM 12
+#define CC_ERR_CACHE_ATTACH 13
+#define CC_ERR_CACHE_RELEASE 14
+#define CC_ERR_CACHE_FULL 15
+#define CC_ERR_CRED_VERSION 16
+
+enum {
+ CC_CRED_VUNKNOWN = 0, // For validation
+ CC_CRED_V4 = 1,
+ CC_CRED_V5 = 2,
+ CC_CRED_VMAX = 3 // For validation
+};
+
+typedef struct opaque_dll_control_block_type* apiCB;
+typedef struct _infoNC {
+ char* name;
+ char* principal;
+ cc_int32 vers;
+} infoNC;
+
+TYPEDEF_FUNC(
+CCACHE_API,
+CALLCONV_C,
+cc_initialize,
+ (
+ apiCB** cc_ctx, // < DLL's primary control structure.
+ // returned here, passed everywhere else
+ cc_int32 api_version, // > ver supported by caller (use CC_API_VER_1)
+ cc_int32* api_supported, // < if ~NULL, max ver supported by DLL
+ const char** vendor // < if ~NULL, vendor name in read only C string
+ )
+);
+
+TYPEDEF_FUNC(
+CCACHE_API,
+CALLCONV_C,
+cc_shutdown,
+ (
+ apiCB** cc_ctx // <> DLL's primary control structure. NULL after
+ )
+);
+
+TYPEDEF_FUNC(
+CCACHE_API,
+CALLCONV_C,
+cc_get_NC_info,
+ (
+ apiCB* cc_ctx, // > DLL's primary control structure
+ struct _infoNC*** ppNCi // < (NULL before call) null terminated,
+ // list of a structs (free via cc_free_infoNC())
+ )
+);
+
+TYPEDEF_FUNC(
+CCACHE_API,
+CALLCONV_C,
+cc_free_NC_info,
+ (
+ apiCB* cc_ctx,
+ struct _infoNC*** ppNCi // < free list of structs returned by
+ // cc_get_cache_names(). set to NULL on return
+ )
+);
+/* End private ccapiv2 headers */
+
+#define CCAPI_DLL "krbcc32.dll"
+
+
+/* */
+#define MAX_USERNAME_LENGTH 256
+#define MAX_PASSWORD_LENGTH 256
+#define MAX_DOMAIN_LENGTH 256
+
+#define KFW_LOGON_EVENT_NAME TEXT("MIT Kerberos")
+
+BOOLEAN APIENTRY DllEntryPoint(HANDLE dll, DWORD reason, PVOID reserved);
+
+DWORD APIENTRY NPGetCaps(DWORD index);
+
+DWORD APIENTRY NPLogonNotify(
+ PLUID lpLogonId,
+ LPCWSTR lpAuthentInfoType,
+ LPVOID lpAuthentInfo,
+ LPCWSTR lpPreviousAuthentInfoType,
+ LPVOID lpPreviousAuthentInfo,
+ LPWSTR lpStationName,
+ LPVOID StationHandle,
+ LPWSTR *lpLogonScript);
+
+DWORD APIENTRY NPPasswordChangeNotify(
+ LPCWSTR lpAuthentInfoType,
+ LPVOID lpAuthentInfo,
+ LPCWSTR lpPreviousAuthentInfoType,
+ LPVOID lpPreviousAuthentInfo,
+ LPWSTR lpStationName,
+ LPVOID StationHandle,
+ DWORD dwChangeInfo);
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void UnloadFuncs(FUNC_INFO [], HINSTANCE);
+
+int LoadFuncs(const char*, FUNC_INFO [], HINSTANCE*, int*, int, int, int);
+
+void DebugEvent0(char *a);
+void DebugEvent(char *b,...);
+
+DWORD MapAuthError(DWORD code);
+
+static BOOL WINAPI UnicodeStringToANSI(UNICODE_STRING uInputString, LPSTR lpszOutputString, int nOutStringLen);
+
+int KFW_is_available(void);
+int KFW_get_cred( char * username, char * password, int lifetime, char ** reasonP );
+void KFW_copy_cache_to_system_file(const char * user, const char * filename);
+int KFW_destroy_tickets_for_principal(char * user);
+int KFW_set_ccache_dacl(char *filename, HANDLE hUserToken);
+int KFW_set_ccache_dacl_with_user_sid(char *filename, PSID pUserSID);
+int KFW_obtain_user_temp_directory(HANDLE hUserToken, char *newfilename, int size);
+void KFW_cleanup_orphaned_caches(void);
+
+void CALLBACK LogonEventHandlerA(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/windows/winlevel.h b/src/windows/winlevel.h
index c7af75c03c..fc8f4c6d83 100644
--- a/src/windows/winlevel.h
+++ b/src/windows/winlevel.h
@@ -1,33 +1,33 @@
-/*
- * winlevel.h
- *
- * Copyright (C) 2006 by the Massachusetts Institute of Technology.
- * All rights reserved.
- *
- * Export of this software from the United States of America may
- * require a specific license from the United States Government.
- * It is the responsibility of any person or organization contemplating
- * export to obtain such a license before exporting.
- *
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
- * distribute this software and its documentation for any purpose and
- * without fee is hereby granted, provided that the above copyright
- * notice appear in all copies and that both that copyright notice and
- * this permission notice appear in supporting documentation, and that
- * the name of M.I.T. not be used in advertising or publicity pertaining
- * to distribution of the software without specific, written prior
- * permission. Furthermore if you modify this software you must label
- * your software as modified software and not distribute it in such a
- * fashion that it might be confused with the original M.I.T. software.
- * M.I.T. makes no representations about the suitability of
- * this software for any purpose. It is provided "as is" without express
- * or implied warranty.
- */
-
-/*
- * This is the slave file for Windows version stamping purposes.
-/* This value should be an ever increasing number that is
- * updated for each alpha, beta, final release. This will ensure
- * that file identifiers are unique
- */
-#define KRB5_BUILDLEVEL 0
+/*
+ * winlevel.h
+ *
+ * Copyright (C) 2006 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
+
+/*
+ * This is the slave file for Windows version stamping purposes.
+/* This value should be an ever increasing number that is
+ * updated for each alpha, beta, final release. This will ensure
+ * that file identifiers are unique
+ */
+#define KRB5_BUILDLEVEL 0