aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin Coffman <kwc@citi.umich.edu>2007-04-20 19:41:32 +0000
committerKevin Coffman <kwc@citi.umich.edu>2007-04-20 19:41:32 +0000
commit4e4b733e8329599d0405b84c3407910c6f798ab0 (patch)
treebeb01cdf5a2cdfd2acd6b9fa9de06f3e955ee893
parent7b432127b1aba67d74cb721c23f9bb39c30e3a2e (diff)
downloadkrb5-4e4b733e8329599d0405b84c3407910c6f798ab0.zip
krb5-4e4b733e8329599d0405b84c3407910c6f798ab0.tar.gz
krb5-4e4b733e8329599d0405b84c3407910c6f798ab0.tar.bz2
Pullup r19183:r19510 from trunk
git-svn-id: svn://anonsvn.mit.edu/krb5/users/coffman/pkinit@19511 dc483132-0cff-0310-8789-dd5450dbe970
-rw-r--r--README11
-rw-r--r--doc/copyright.texinfo2
-rw-r--r--doc/implementor.texinfo21
-rw-r--r--src/aclocal.m4162
-rw-r--r--src/appl/Makefile.in7
-rw-r--r--src/appl/configure.in21
-rw-r--r--src/appl/gss-sample/Makefile.in40
-rw-r--r--src/appl/gss-sample/gss-misc.c3
-rw-r--r--src/appl/libpty/Makefile.in2
-rw-r--r--src/appl/libpty/configure.in3
-rw-r--r--src/appl/sample/Makefile.in4
-rw-r--r--src/appl/sample/sclient/Makefile.in4
-rw-r--r--src/appl/sample/sserver/Makefile.in4
-rw-r--r--src/appl/simple/Makefile.in4
-rw-r--r--src/appl/simple/client/Makefile.in4
-rw-r--r--src/appl/simple/server/Makefile.in4
-rw-r--r--src/appl/telnet/configure.in2
-rw-r--r--src/appl/telnet/libtelnet/Makefile.in1
-rw-r--r--src/appl/telnet/telnetd/state.c3
-rw-r--r--src/appl/telnet/telnetd/sys_term.c25
-rw-r--r--src/appl/user_user/Makefile.in4
-rw-r--r--src/clients/kcpytkt/Makefile.in18
-rw-r--r--src/clients/kdeltkt/Makefile.in18
-rw-r--r--src/clients/kdestroy/Makefile.in18
-rw-r--r--src/clients/kinit/Makefile.in18
-rw-r--r--src/clients/klist/Makefile.in18
-rw-r--r--src/clients/kpasswd/Makefile.in18
-rw-r--r--src/clients/kvno/Makefile.in19
-rw-r--r--src/config/libnodeps.in4
-rw-r--r--src/config/libpriv.in13
-rw-r--r--src/config/pre.in23
-rw-r--r--src/config/shlib.conf4
-rw-r--r--src/configure.in77
-rw-r--r--src/include/k5-int.h1
-rw-r--r--src/include/k5-platform.h32
-rw-r--r--src/include/k5-thread.h19
-rw-r--r--src/include/win-mac.h3
-rw-r--r--src/kadmin/cli/Makefile.in12
-rwxr-xr-xsrc/kadmin/cli/k5srvutil.sh2
-rw-r--r--src/kadmin/cli/kadmin.M22
-rw-r--r--src/kadmin/cli/keytab.c27
-rw-r--r--src/kadmin/cli/keytab_local.c9
-rw-r--r--src/kadmin/dbutil/Makefile.in19
-rw-r--r--src/kadmin/dbutil/kadm5_create.c27
-rw-r--r--src/kadmin/server/kadm_rpc_svc.c8
-rw-r--r--src/kadmin/server/misc.c9
-rw-r--r--src/kadmin/server/misc.h2
-rw-r--r--src/kadmin/server/ovsec_kadmd.c28
-rw-r--r--src/kadmin/server/schpw.c9
-rw-r--r--src/kadmin/server/server_stubs.c311
-rw-r--r--src/kadmin/testing/Makefile.in2
-rw-r--r--src/kdc/Makefile.in2
-rw-r--r--src/kdc/do_tgs_req.c26
-rw-r--r--src/kdc/kdc_util.c1
-rw-r--r--src/kdc/main.c6
-rw-r--r--src/kdc/network.c387
-rw-r--r--src/krb524/Makefile.in26
-rw-r--r--src/lib/apputils/Makefile.in5
-rw-r--r--src/lib/apputils/configure.in6
-rw-r--r--src/lib/crypto/decrypt.c6
-rw-r--r--src/lib/gssapi/Makefile.in3
-rw-r--r--src/lib/gssapi/generic/util_ordering.c6
-rw-r--r--src/lib/gssapi/mechglue/g_initialize.c40
-rw-r--r--src/lib/kadm5/admin.h10
-rw-r--r--src/lib/kadm5/logger.c10
-rw-r--r--src/lib/kadm5/srv/libkadm5srv.exports1
-rw-r--r--src/lib/kadm5/srv/svr_principal.c55
-rw-r--r--src/lib/krb5/ccache/Makefile.in9
-rw-r--r--src/lib/krb5/ccache/cc_mslsa.c108
-rw-r--r--src/lib/krb5/keytab/Makefile.in2
-rw-r--r--src/lib/krb5/krb/conv_princ.c2
-rw-r--r--src/lib/krb5/krb/gc_frm_kdc.c1
-rw-r--r--src/lib/krb5/krb/gen_seqnum.c13
-rw-r--r--src/lib/krb5/krb/gen_subkey.c13
-rw-r--r--src/lib/krb5/krb/get_in_tkt.c34
-rw-r--r--src/lib/krb5/krb/init_ctx.c1
-rw-r--r--src/lib/krb5/krb/mk_cred.c17
-rw-r--r--src/lib/krb5/krb/mk_error.c3
-rw-r--r--src/lib/krb5/krb/mk_priv.c5
-rw-r--r--src/lib/krb5/krb/mk_rep.c3
-rw-r--r--src/lib/krb5/krb/mk_req_ext.c5
-rw-r--r--src/lib/krb5/krb/mk_safe.c4
-rw-r--r--src/lib/krb5/krb/preauth2.c18
-rw-r--r--src/lib/krb5/krb/rd_cred.c24
-rw-r--r--src/lib/krb5/krb/rd_error.c3
-rw-r--r--src/lib/krb5/krb/rd_priv.c11
-rw-r--r--src/lib/krb5/krb/rd_rep.c3
-rw-r--r--src/lib/krb5/krb/rd_req.c18
-rw-r--r--src/lib/krb5/krb/rd_req_dec.c5
-rw-r--r--src/lib/krb5/krb/rd_safe.c11
-rw-r--r--src/lib/krb5/krb/ser_ctx.c12
-rw-r--r--src/lib/krb5/krb/serialize.c8
-rw-r--r--src/lib/krb5/os/an_to_ln.c2
-rw-r--r--src/lib/krb5/os/c_ustime.c1
-rw-r--r--src/lib/krb5/os/hst_realm.c6
-rw-r--r--src/lib/krb5/os/init_os_ctx.c2
-rw-r--r--src/lib/krb5/os/locate_kdc.c43
-rw-r--r--src/lib/krb5/os/sendto_kdc.c52
-rw-r--r--src/plugins/kdb/db2/Makefile.in11
-rw-r--r--src/plugins/kdb/db2/configure.in27
-rw-r--r--src/plugins/kdb/db2/libdb2/Makefile.in1
-rw-r--r--src/plugins/kdb/db2/libdb2/configure.in1
-rw-r--r--src/plugins/kdb/ldap/libkdb_ldap/Makefile.in2
-rw-r--r--src/plugins/kdb/ldap/libkdb_ldap/configure.in2
-rw-r--r--src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c1
-rw-r--r--src/plugins/locate/python/Makefile.in8
-rw-r--r--src/plugins/locate/python/configure.in10
-rw-r--r--src/plugins/locate/python/py-locate.c2
-rw-r--r--src/plugins/preauth/cksum_body/configure.in4
-rw-r--r--src/plugins/preauth/pkinit/configure.in2
-rw-r--r--src/plugins/preauth/wpse/configure.in4
-rw-r--r--src/t_krbconf12
-rw-r--r--src/tests/Makefile.in4
-rw-r--r--src/tests/asn.1/Makefile.in4
-rw-r--r--src/tests/configure.in30
-rw-r--r--src/tests/create/Makefile.in4
-rw-r--r--src/tests/dejagnu/Makefile.in7
-rw-r--r--src/tests/dejagnu/config/default.exp27
-rw-r--r--src/tests/dejagnu/t_inetd.c2
-rw-r--r--src/tests/gss-threads/Makefile.in4
-rw-r--r--src/tests/gss-threads/gss-server.c1
-rw-r--r--src/tests/gssapi/Makefile.in4
-rw-r--r--src/tests/hammer/Makefile.in4
-rw-r--r--src/tests/misc/Makefile.in4
-rw-r--r--src/tests/resolve/Makefile.in11
-rw-r--r--src/tests/resolve/resolve.c1
-rw-r--r--src/tests/shlib/Makefile.in4
-rw-r--r--src/tests/threads/Makefile.in4
-rw-r--r--src/tests/verify/Makefile.in4
-rw-r--r--src/util/et/com_err.c14
-rw-r--r--src/util/profile/Makefile.in8
-rw-r--r--src/util/ss/Makefile.in7
-rw-r--r--src/util/ss/configure.in17
-rw-r--r--src/util/support/fake-addrinfo.c2
-rw-r--r--src/util/support/plugins.c12
-rw-r--r--src/windows/build/BKWconfig.xml181
-rw-r--r--src/windows/build/Logger.pm87
-rw-r--r--src/windows/build/bkw-automation.html355
-rw-r--r--src/windows/build/bkw.pl669
-rw-r--r--src/windows/build/bootstrap.xml19
-rw-r--r--src/windows/build/commandandcontrol.pl170
-rw-r--r--src/windows/build/copyfiles.pl137
-rw-r--r--src/windows/build/copyfiles.xml218
-rw-r--r--src/windows/build/corebinaryfiles.xml85
-rw-r--r--src/windows/build/css/main-action(1).css54
-rw-r--r--src/windows/build/css/main-action.css1032
-rw-r--r--src/windows/build/makeZip.pl84
-rw-r--r--src/windows/build/pruneFiles.pl34
-rw-r--r--src/windows/build/repository1.pl90
-rw-r--r--src/windows/build/sdkfiles.xml23
-rw-r--r--src/windows/build/signFiles.pl27
-rw-r--r--src/windows/build/site-local.sed2
-rw-r--r--src/windows/build/tee.pl79
-rw-r--r--src/windows/build/which.pl69
-rw-r--r--src/windows/build/zipXML.pl21
-rw-r--r--src/windows/identity/Makefile2
-rw-r--r--src/windows/identity/apiversion.txt132
-rw-r--r--src/windows/identity/config/Makefile.w2k12
-rw-r--r--src/windows/identity/config/Makefile.w3212
-rw-r--r--src/windows/identity/config/ccsv.pl6
-rw-r--r--src/windows/identity/config/csvschema.cfg6
-rw-r--r--src/windows/identity/doc/Makefile7
-rw-r--r--src/windows/identity/doc/cred_aquisition.h129
-rw-r--r--src/windows/identity/doc/cred_data_types.h82
-rw-r--r--src/windows/identity/doc/cred_main.h1
-rw-r--r--src/windows/identity/doc/cred_msgs.h5
-rw-r--r--src/windows/identity/doc/cred_prop_pages.h3
-rw-r--r--src/windows/identity/doc/doxyfile.cfg703
-rw-r--r--src/windows/identity/doc/footer.html4
-rw-r--r--src/windows/identity/doc/header.html3
-rw-r--r--src/windows/identity/doc/images/modules_plugins_krb5.pngbin0 -> 22193 bytes
-rw-r--r--src/windows/identity/doc/main_page.h92
-rwxr-xr-xsrc/windows/identity/doc/netidmgr.docbin3294720 -> 5850112 bytes
-rwxr-xr-xsrc/windows/identity/doc/netidmgr.pdfbin1345437 -> 1473877 bytes
-rw-r--r--src/windows/identity/doc/plugin_framework.h164
-rw-r--r--src/windows/identity/doc/plugin_locale.h6
-rw-r--r--src/windows/identity/doc/plugin_main.h79
-rw-r--r--src/windows/identity/doc/plugin_structure.h13
-rw-r--r--src/windows/identity/doc/stylesheet.css178
-rw-r--r--src/windows/identity/doc/ui_actions.h1
-rw-r--r--src/windows/identity/doc/ui_context.h7
-rw-r--r--src/windows/identity/doc/ui_main.h1
-rw-r--r--src/windows/identity/doc/ui_menus.h1
-rw-r--r--src/windows/identity/help/Makefile2
-rw-r--r--src/windows/identity/help/html/act_chpw.htm15
-rw-r--r--src/windows/identity/help/html/act_destroy_creds.htm13
-rw-r--r--src/windows/identity/help/html/act_import_creds.htm24
-rw-r--r--src/windows/identity/help/html/act_new_creds.htm54
-rw-r--r--src/windows/identity/help/html/act_renew_creds.htm26
-rw-r--r--src/windows/identity/help/html/act_set_default.htm8
-rw-r--r--src/windows/identity/help/html/bugs.htm13
-rw-r--r--src/windows/identity/help/html/cmdline_netidmgr.htm38
-rw-r--r--src/windows/identity/help/html/concept_cred_pro.htm26
-rw-r--r--src/windows/identity/help/html/concept_credential.htm31
-rw-r--r--src/windows/identity/help/html/concept_ident_pro.htm22
-rw-r--r--src/windows/identity/help/html/concept_identity.htm25
-rw-r--r--src/windows/identity/help/html/concepts.htm31
-rw-r--r--src/windows/identity/help/html/copyright.htm6
-rw-r--r--src/windows/identity/help/html/howdoi.htm6
-rw-r--r--src/windows/identity/help/html/images/appicon_empty.bmpbin1062 -> 0 bytes
-rw-r--r--src/windows/identity/help/html/images/appicon_empty.pngbin0 -> 878 bytes
-rw-r--r--src/windows/identity/help/html/images/appicon_expired.bmpbin1062 -> 0 bytes
-rw-r--r--src/windows/identity/help/html/images/appicon_expired.pngbin0 -> 1071 bytes
-rw-r--r--src/windows/identity/help/html/images/appicon_good.bmpbin1062 -> 0 bytes
-rw-r--r--src/windows/identity/help/html/images/appicon_good.pngbin0 -> 1065 bytes
-rw-r--r--src/windows/identity/help/html/images/appicon_warnexp.bmpbin1062 -> 0 bytes
-rw-r--r--src/windows/identity/help/html/images/appicon_warnexp.pngbin0 -> 1036 bytes
-rw-r--r--src/windows/identity/help/html/images/appicon_warning.bmpbin1062 -> 0 bytes
-rw-r--r--src/windows/identity/help/html/images/appicon_warning.pngbin0 -> 1064 bytes
-rw-r--r--src/windows/identity/help/html/images/notification_icon_menu.pngbin0 -> 7038 bytes
-rw-r--r--src/windows/identity/help/html/images/screen_app_icon.bmpbin143574 -> 0 bytes
-rw-r--r--src/windows/identity/help/html/images/screen_app_icon.pngbin0 -> 10789 bytes
-rw-r--r--src/windows/identity/help/html/images/screen_chng_pwd.pngbin0 -> 10508 bytes
-rw-r--r--src/windows/identity/help/html/images/screen_config_appearance.pngbin0 -> 20195 bytes
-rw-r--r--src/windows/identity/help/html/images/screen_config_cred_provider.pngbin0 -> 25843 bytes
-rw-r--r--src/windows/identity/help/html/images/screen_config_general.bmpbin634974 -> 0 bytes
-rw-r--r--src/windows/identity/help/html/images/screen_config_general.pngbin0 -> 30809 bytes
-rw-r--r--src/windows/identity/help/html/images/screen_config_global_krb4.pngbin0 -> 20681 bytes
-rw-r--r--src/windows/identity/help/html/images/screen_config_global_krb5.pngbin0 -> 21934 bytes
-rw-r--r--src/windows/identity/help/html/images/screen_config_ident.bmpbin634974 -> 0 bytes
-rw-r--r--src/windows/identity/help/html/images/screen_config_ident.pngbin0 -> 26360 bytes
-rw-r--r--src/windows/identity/help/html/images/screen_config_ident_krb4.pngbin0 -> 18158 bytes
-rw-r--r--src/windows/identity/help/html/images/screen_config_ident_krb5.pngbin0 -> 22456 bytes
-rw-r--r--src/windows/identity/help/html/images/screen_config_ident_provider.pngbin0 -> 26029 bytes
-rw-r--r--src/windows/identity/help/html/images/screen_config_idents.bmpbin634974 -> 0 bytes
-rw-r--r--src/windows/identity/help/html/images/screen_config_idents.pngbin0 -> 23875 bytes
-rw-r--r--src/windows/identity/help/html/images/screen_config_notifications.pngbin0 -> 17223 bytes
-rw-r--r--src/windows/identity/help/html/images/screen_config_plug_in_krb4.pngbin0 -> 19313 bytes
-rw-r--r--src/windows/identity/help/html/images/screen_config_plug_in_krb5.pngbin0 -> 21145 bytes
-rw-r--r--src/windows/identity/help/html/images/screen_config_plug_in_krb5_ccache.pngbin0 -> 18848 bytes
-rw-r--r--src/windows/identity/help/html/images/screen_config_plug_in_krb5_realm.pngbin0 -> 25097 bytes
-rw-r--r--src/windows/identity/help/html/images/screen_config_plug_ins.pngbin0 -> 23714 bytes
-rw-r--r--src/windows/identity/help/html/images/screen_main_wnd.bmpbin1070434 -> 0 bytes
-rw-r--r--src/windows/identity/help/html/images/screen_main_wnd.pngbin0 -> 49149 bytes
-rw-r--r--src/windows/identity/help/html/images/screen_main_wnd_basic.pngbin0 -> 24630 bytes
-rw-r--r--src/windows/identity/help/html/images/screen_menu_bar.bmpbin15330 -> 0 bytes
-rw-r--r--src/windows/identity/help/html/images/screen_menu_bar.pngbin0 -> 871 bytes
-rw-r--r--src/windows/identity/help/html/images/screen_menu_credential.bmpbin153574 -> 0 bytes
-rw-r--r--src/windows/identity/help/html/images/screen_menu_credential.pngbin0 -> 9870 bytes
-rw-r--r--src/windows/identity/help/html/images/screen_menu_file.bmpbin48334 -> 0 bytes
-rw-r--r--src/windows/identity/help/html/images/screen_menu_file.pngbin0 -> 2952 bytes
-rw-r--r--src/windows/identity/help/html/images/screen_menu_help.bmpbin74574 -> 0 bytes
-rw-r--r--src/windows/identity/help/html/images/screen_menu_help.pngbin0 -> 5812 bytes
-rw-r--r--src/windows/identity/help/html/images/screen_menu_options.bmpbin97638 -> 0 bytes
-rw-r--r--src/windows/identity/help/html/images/screen_menu_options.pngbin0 -> 4877 bytes
-rw-r--r--src/windows/identity/help/html/images/screen_menu_view.bmpbin52054 -> 0 bytes
-rw-r--r--src/windows/identity/help/html/images/screen_menu_view.pngbin0 -> 6386 bytes
-rw-r--r--src/windows/identity/help/html/images/screen_menu_view_cols.bmpbin617742 -> 0 bytes
-rw-r--r--src/windows/identity/help/html/images/screen_menu_view_cols.pngbin0 -> 14875 bytes
-rwxr-xr-xsrc/windows/identity/help/html/images/screen_new_creds.bmpbin409086 -> 0 bytes
-rw-r--r--src/windows/identity/help/html/images/screen_new_creds.pngbin0 -> 11571 bytes
-rwxr-xr-xsrc/windows/identity/help/html/images/screen_new_creds_err01.bmpbin211690 -> 0 bytes
-rw-r--r--src/windows/identity/help/html/images/screen_new_creds_err01.pngbin0 -> 11757 bytes
-rwxr-xr-xsrc/windows/identity/help/html/images/screen_new_creds_exp.bmpbin531414 -> 0 bytes
-rw-r--r--src/windows/identity/help/html/images/screen_new_creds_exp.pngbin0 -> 23631 bytes
-rw-r--r--src/windows/identity/help/html/images/screen_tb_standard.bmpbin52634 -> 0 bytes
-rw-r--r--src/windows/identity/help/html/images/screen_tb_standard.pngbin0 -> 10327 bytes
-rw-r--r--src/windows/identity/help/html/images/screen_tray_icon.bmpbin40122 -> 0 bytes
-rw-r--r--src/windows/identity/help/html/images/screen_tray_icon.pngbin0 -> 5846 bytes
-rw-r--r--src/windows/identity/help/html/menu_all.htm6
-rw-r--r--src/windows/identity/help/html/menu_credential.htm45
-rw-r--r--src/windows/identity/help/html/menu_file.htm19
-rw-r--r--src/windows/identity/help/html/menu_help.htm34
-rw-r--r--src/windows/identity/help/html/menu_options.htm50
-rw-r--r--src/windows/identity/help/html/menu_view.htm40
-rw-r--r--src/windows/identity/help/html/tb_standard.htm18
-rw-r--r--src/windows/identity/help/html/template.htm2
-rw-r--r--src/windows/identity/help/html/use_config.htm394
-rw-r--r--src/windows/identity/help/html/use_icon.htm44
-rw-r--r--src/windows/identity/help/html/use_layout.htm22
-rw-r--r--src/windows/identity/help/html/use_start.htm29
-rw-r--r--src/windows/identity/help/html/using.htm45
-rw-r--r--src/windows/identity/help/html/welcome.htm110
-rw-r--r--src/windows/identity/help/html/wnd_main.htm29
-rw-r--r--src/windows/identity/help/khhelp.h2
-rw-r--r--src/windows/identity/help/popups_newcreds.txt2
-rw-r--r--src/windows/identity/help/popups_password.txt2
-rw-r--r--src/windows/identity/include/Makefile2
-rw-r--r--src/windows/identity/include/kherror.h5
-rw-r--r--src/windows/identity/include/khlist.h43
-rw-r--r--src/windows/identity/include/khmsgtypes.h9
-rw-r--r--src/windows/identity/kconfig/Makefile3
-rw-r--r--src/windows/identity/kconfig/api.c188
-rw-r--r--src/windows/identity/kconfig/kconfig.h6
-rw-r--r--src/windows/identity/kcreddb/Makefile2
-rw-r--r--src/windows/identity/kcreddb/credset.c15
-rw-r--r--src/windows/identity/kcreddb/identity.c16
-rw-r--r--src/windows/identity/kcreddb/kcreddb.h16
-rw-r--r--src/windows/identity/kherr/Makefile2
-rw-r--r--src/windows/identity/kmm/Makefile2
-rw-r--r--src/windows/identity/kmm/kmm_registrar.c74
-rw-r--r--src/windows/identity/kmm/kmminternal.h12
-rw-r--r--src/windows/identity/kmq/Makefile2
-rw-r--r--src/windows/identity/kmq/consumer.c126
-rw-r--r--src/windows/identity/kmq/init.c66
-rw-r--r--src/windows/identity/kmq/kmq.h159
-rw-r--r--src/windows/identity/kmq/kmqinternal.h127
-rw-r--r--src/windows/identity/kmq/msgtype.c27
-rw-r--r--src/windows/identity/kmq/publisher.c77
-rw-r--r--src/windows/identity/nidmgrdll/Makefile5
-rw-r--r--src/windows/identity/nidmgrdll/nidmgrdll.rc6
-rw-r--r--src/windows/identity/plugins/common/Makefile4
-rw-r--r--src/windows/identity/plugins/common/dynimport.c6
-rw-r--r--src/windows/identity/plugins/common/dynimport.h14
-rw-r--r--src/windows/identity/plugins/common/krb5common.c8
-rw-r--r--src/windows/identity/plugins/krb4/krb4funcs.c1
-rw-r--r--src/windows/identity/plugins/krb4/krb4funcs.h13
-rw-r--r--src/windows/identity/plugins/krb4/krb4newcreds.c75
-rw-r--r--src/windows/identity/plugins/krb4/lang/en_us/langres.rc13
-rw-r--r--src/windows/identity/plugins/krb4/langres.h55
-rw-r--r--src/windows/identity/plugins/krb5/krb5configdlg.c142
-rw-r--r--src/windows/identity/plugins/krb5/krb5configids.c75
-rw-r--r--src/windows/identity/plugins/krb5/krb5funcs.c939
-rw-r--r--src/windows/identity/plugins/krb5/krb5funcs.h125
-rw-r--r--src/windows/identity/plugins/krb5/krb5identpro.c297
-rw-r--r--src/windows/identity/plugins/krb5/krb5newcreds.c434
-rw-r--r--src/windows/identity/plugins/krb5/krbconfig.csv2
-rw-r--r--src/windows/identity/plugins/krb5/krbcred.h6
-rw-r--r--src/windows/identity/plugins/krb5/lang/en_us/langres.rc40
-rw-r--r--src/windows/identity/plugins/krb5/langres.h3
-rw-r--r--src/windows/identity/ui/Makefile5
-rw-r--r--src/windows/identity/ui/aboutwnd.c5
-rw-r--r--src/windows/identity/ui/addrchange.c2
-rw-r--r--src/windows/identity/ui/appglobal.h52
-rw-r--r--src/windows/identity/ui/cfg_general_wnd.c76
-rw-r--r--src/windows/identity/ui/cfg_identities_wnd.c14
-rw-r--r--src/windows/identity/ui/configwnd.c13
-rw-r--r--src/windows/identity/ui/credfuncs.c112
-rw-r--r--src/windows/identity/ui/credfuncs.h3
-rw-r--r--src/windows/identity/ui/credwnd.c1335
-rw-r--r--src/windows/identity/ui/credwnd.h81
-rw-r--r--src/windows/identity/ui/htmlwnd.h0
-rw-r--r--src/windows/identity/ui/htwnd.c115
-rw-r--r--src/windows/identity/ui/khmapp.h16
-rw-r--r--src/windows/identity/ui/lang/en_us/khapp.rc170
-rw-r--r--src/windows/identity/ui/main.c246
-rw-r--r--src/windows/identity/ui/mainmenu.c342
-rw-r--r--src/windows/identity/ui/mainmenu.h6
-rw-r--r--src/windows/identity/ui/mainwnd.c2355
-rw-r--r--src/windows/identity/ui/mainwnd.h20
-rw-r--r--src/windows/identity/ui/newcredwnd.c4901
-rw-r--r--src/windows/identity/ui/newcredwnd.h292
-rw-r--r--src/windows/identity/ui/notifier.c3008
-rw-r--r--src/windows/identity/ui/notifier.h6
-rw-r--r--src/windows/identity/ui/propertywnd.c2
-rw-r--r--src/windows/identity/ui/reqdaemon.c2
-rw-r--r--src/windows/identity/ui/resource.h63
-rw-r--r--src/windows/identity/ui/statusbar.c25
-rw-r--r--src/windows/identity/ui/statusbar.h1
-rw-r--r--src/windows/identity/ui/taskbar.c87
-rw-r--r--src/windows/identity/ui/taskbar.h38
-rw-r--r--src/windows/identity/ui/timer.c17
-rw-r--r--src/windows/identity/ui/toolbar.c47
-rw-r--r--src/windows/identity/ui/toolbar.h12
-rw-r--r--src/windows/identity/ui/uiconfig.csv38
-rw-r--r--src/windows/identity/uilib/Makefile3
-rw-r--r--src/windows/identity/uilib/accel.csv1
-rw-r--r--src/windows/identity/uilib/action.c200
-rw-r--r--src/windows/identity/uilib/actiondef.cfg1
-rw-r--r--src/windows/identity/uilib/actions.csv1
-rw-r--r--src/windows/identity/uilib/alert.c61
-rw-r--r--src/windows/identity/uilib/creddlg.c3
-rw-r--r--src/windows/identity/uilib/intaction.h64
-rw-r--r--src/windows/identity/uilib/intalert.h136
-rw-r--r--src/windows/identity/uilib/khaction.h153
-rw-r--r--src/windows/identity/uilib/khactiondef.h1
-rw-r--r--src/windows/identity/uilib/khalerts.h181
-rw-r--r--src/windows/identity/uilib/khnewcred.h16
-rw-r--r--src/windows/identity/uilib/khuidefs.h25
-rw-r--r--src/windows/identity/uilib/rescache.c2
-rw-r--r--src/windows/identity/uilib/uibind.c3
-rw-r--r--src/windows/identity/util/Makefile2
-rw-r--r--src/windows/identity/util/hashtable.c11
-rw-r--r--src/windows/identity/util/hashtable.h18
-rw-r--r--src/windows/identity/util/perfstat.c188
-rw-r--r--src/windows/identity/util/perfstat.h19
-rw-r--r--src/windows/installer/nsis/kfw-fixed.nsi40
-rw-r--r--src/windows/installer/nsis/nsi-includes-tagged.nsi8
-rw-r--r--src/windows/installer/nsis/nsi-includes.nsi8
-rw-r--r--src/windows/installer/nsis/site-local-tagged.nsi13
-rw-r--r--src/windows/installer/nsis/site-local.nsi13
-rw-r--r--src/windows/installer/wix/files.wxi17
-rw-r--r--src/windows/installer/wix/msi-deployment-guide.txt212
-rw-r--r--src/windows/installer/wix/site-local-tagged.wxi (renamed from src/windows/installer/wix/site-local.wxi)202
-rw-r--r--src/windows/kfwlogon/Makefile.in26
-rw-r--r--src/windows/kfwlogon/kfwcommon.c384
-rw-r--r--src/windows/kfwlogon/kfwcpcc.c2
-rw-r--r--src/windows/kfwlogon/kfwcpcc.rc10
-rw-r--r--src/windows/kfwlogon/kfwlogon.c285
-rw-r--r--src/windows/kfwlogon/kfwlogon.def2
-rw-r--r--src/windows/kfwlogon/kfwlogon.h19
-rw-r--r--src/windows/kfwlogon/kfwlogon.rc10
-rw-r--r--src/windows/ms2mit/Makefile.in24
-rw-r--r--src/windows/version.rc108
394 files changed, 20614 insertions, 7341 deletions
diff --git a/README b/README
index ad3e760..771767d 100644
--- a/README
+++ b/README
@@ -160,7 +160,7 @@ for a current listing with links to the complete tickets.
Copyright and Other Legal Notices
---------------------------------
-Copyright (C) 1985-2006 by the Massachusetts Institute of Technology.
+Copyright (C) 1985-2007 by the Massachusetts Institute of Technology.
All rights reserved.
@@ -520,7 +520,8 @@ past and present: Danilo Almeida, Jeffrey Altman, Justin Anderson,
Richard Basch, Jay Berkenbilt, Mitch Berger, Andrew Boardman, Joe
Calzaretta, John Carr, Don Davis, Alexandra Ellwood, Nancy Gilman,
Matt Hancher, Sam Hartman, Paul Hill, Marc Horowitz, Eva Jacobus,
-Miroslav Jurisic, Barry Jaspan, Geoffrey King, John Kohl, Peter
-Litwack, Scott McGuire, Kevin Mitchell, Cliff Neuman, Paul Park, Ezra
-Peisach, Chris Provenzano, Ken Raeburn, Jon Rochlis, Jeff Schiller,
-Jen Selby, Brad Thompson, Harry Tsai, Ted Ts'o, Marshall Vale, Tom Yu.
+Miroslav Jurisic, Barry Jaspan, Geoffrey King, Kevin Koch, John Kohl,
+Peter Litwack, Scott McGuire, Kevin Mitchell, Cliff Neuman, Paul Park,
+Ezra Peisach, Chris Provenzano, Ken Raeburn, Jon Rochlis, Jeff
+Schiller, Jen Selby, Brad Thompson, Harry Tsai, Ted Ts'o, Marshall
+Vale, Tom Yu.
diff --git a/doc/copyright.texinfo b/doc/copyright.texinfo
index fd80641..5d513e5 100644
--- a/doc/copyright.texinfo
+++ b/doc/copyright.texinfo
@@ -1,4 +1,4 @@
-Copyright @copyright{} 1985-2006 by the Massachusetts Institute of Technology.
+Copyright @copyright{} 1985-2007 by the Massachusetts Institute of Technology.
@quotation
Export of software employing encryption from the United States of
diff --git a/doc/implementor.texinfo b/doc/implementor.texinfo
index 169dee8..7133186 100644
--- a/doc/implementor.texinfo
+++ b/doc/implementor.texinfo
@@ -1048,6 +1048,7 @@ building shared libraries for Kerberos.
@menu
* AIX Shared Library Support::
* Alpha OSF/1 Shared Library Support::
+* ELF Shared Library Support::
@end menu
@node AIX Shared Library Support, Alpha OSF/1 Shared Library Support, Operating System Notes for Shared Libraries, Operating System Notes for Shared Libraries
@@ -1073,7 +1074,7 @@ compiler works fine. In addition, the AIX 4.1 linker is able to build a
shared @samp{libkrb5.a} when GNU C is used.
-@node Alpha OSF/1 Shared Library Support, , AIX Shared Library Support, Operating System Notes for Shared Libraries
+@node Alpha OSF/1 Shared Library Support, ELF Shared Library Support, AIX Shared Library Support, Operating System Notes for Shared Libraries
@subsection Alpha OSF/1 Shared Library Support
Shared library support has been tested with V2.1 and higher of the
@@ -1091,7 +1092,23 @@ instead of a possibly installed library. The loader uses the contents of
@samp{-rpath} before LD_LIBRARY_PATH so we must specify a dummy _RLD_ROOT
and complete LD_LIBRARY_PATH in our tests.
-The one disadvantage with the method we are using....
+The one disadvantage with the method we are using.... [What?? This
+never got finished!]
+
+@node ELF Shared Library Support, , Alpha OSF/1 Shared Library Support, Operating System Notes for Shared Libraries
+@subsection ELF Shared Library Support
+
+It's tempting to add @samp{-Bsymbolic} to the commands for generating
+shared libraries. We don't explicitly support overriding our
+(internal or public) symbol names by applications, and binding at
+shared library creation time would result in smaller libraries that
+would load faster. However, it won't work. At least with the GNU and
+Solaris linkers and runtime environments, an executable using a data
+symbol exported by a shared library gets a copy of that data,
+initialized at run time by copying, and the program will only function
+properly if that definition can override the one present in the shared
+library. And, sadly, some of our shared libraries export variables
+that are directly referenced from programs.
@node Porting Issues, , Shared Libraries, Top
@chapter Porting Issues
diff --git a/src/aclocal.m4 b/src/aclocal.m4
index 12daf2a..2f02c5f 100644
--- a/src/aclocal.m4
+++ b/src/aclocal.m4
@@ -98,6 +98,10 @@ libobj_frag=$srcdir/$ac_config_fragdir/libobj.in
AC_SUBST_FILE(libobj_frag)
libnover_frag=$srcdir/$ac_config_fragdir/libnover.in
AC_SUBST_FILE(libnover_frag)
+libpriv_frag=$srcdir/$ac_config_fragdir/libpriv.in
+AC_SUBST_FILE(libpriv_frag)
+libnodeps_frag=$srcdir/$ac_config_fragdir/libnodeps.in
+AC_SUBST_FILE(libnodeps_frag)
dnl
KRB5_AC_PRAGMA_WEAK_REF
WITH_LDAP
@@ -1118,33 +1122,6 @@ dnl
dnl Pull in the necessary stuff to create the libraries.
AC_DEFUN(KRB5_BUILD_LIBRARY,
-[KRB5_BUILD_LIBRARY_WITH_DEPS
-# null out SHLIB_EXPFLAGS because we lack any dependencies
-SHLIB_EXPFLAGS=])
-
-dnl
-dnl KRB5_BUILD_LIBRARY_STATIC
-dnl
-dnl Force static library build.
-
-AC_DEFUN(KRB5_AC_FORCE_STATIC,[dnl
-AC_BEFORE([$0],[KRB5_LIB_AUX])dnl
-krb5_force_static=yes])
-AC_DEFUN(KRB5_BUILD_LIBRARY_STATIC,
-dnl Use define rather than AC_DEFUN to avoid ordering problems.
-[AC_REQUIRE([KRB5_AC_FORCE_STATIC])dnl
-KRB5_BUILD_LIBRARY
-# If we're only building static libraries, they're for build-time use only,
-# so don't install.
-LIBINSTLIST=])
-
-dnl
-dnl KRB5_BUILD_LIBRARY_WITH_DEPS
-dnl
-dnl Like KRB5_BUILD_LIBRARY, but adds in explicit dependencies in the
-dnl generated shared library.
-
-AC_DEFUN(KRB5_BUILD_LIBRARY_WITH_DEPS,
[AC_REQUIRE([KRB5_LIB_AUX])dnl
AC_REQUIRE([AC_PROG_LN_S])dnl
AC_REQUIRE([AC_PROG_RANLIB])dnl
@@ -1219,96 +1196,61 @@ dnl Parse configure options related to library building.
AC_DEFUN(KRB5_LIB_AUX,
[AC_REQUIRE([KRB5_LIB_PARAMS])dnl
-# Check whether to build static libraries.
-dnl AC_HELP_STRING([--enable-static],[build static libraries @<:@disabled for most platforms@:>@])
-dnl AC_HELP_STRING([--disable-static],[don't build static libraries])
-AC_ARG_ENABLE([static],, ,
-[enable_static=$default_static])
-
-if test "$enable_static" = yes; then
+AC_ARG_ENABLE([static],,
+[if test "$enableval" != no; then
AC_MSG_ERROR([Sorry, static libraries do not work in this release.])
+fi])
+AC_ARG_ENABLE([shared], ,
+[if test "$enableval" != yes; then
+ AC_MSG_ERROR([Sorry, this release builds only shared libraries, cannot disable them.])
+fi])
+
+if test "$SHLIBEXT" = ".so-nobuild"; then
+ AC_MSG_ERROR([Shared libraries are not yet supported on this platform.])
fi
-if test "$enable_static" = no && test "$krb5_force_static" != yes; then
- AC_MSG_NOTICE([disabling static libraries])
- LIBLINKS=
- LIBLIST=
- OBJLISTS=
-else
+DEPLIBEXT=$SHLIBEXT
+
+if test "$krb5_force_static" = "yes"; then
LIBLIST='lib$(LIBBASE)$(STLIBEXT)'
LIBLINKS='$(TOPLIBD)/lib$(LIBBASE)$(STLIBEXT)'
OBJLISTS=OBJS.ST
- LIBINSTLIST=install-static
- DEPLIBEXT=$STLIBEXT
+ # This used to be install-static, but now we only follow this
+ # path for internal libraries we don't want installed, not for
+ # configure-time requests for installed static libraries.
+ LIBINSTLIST=
# CFLAGS="$CFLAGS -D_KDB5_STATIC_LINK"
-fi
-
-# Check whether to build shared libraries.
-AC_ARG_ENABLE([shared],
-dnl AC_HELP_STRING([--enable-shared],[build shared libraries @<:@enabled for most platforms@:>@])
-dnl AC_HELP_STRING([--disable-shared],[don't build shared libraries])
-, ,
-[enable_shared=$default_shared])
-if test "$enable_shared" != yes; then
- AC_MSG_ERROR([Sorry, this release builds only shared libraries, cannot disable them.])
-fi
+ AC_MSG_RESULT([Forcing static libraries.])
+ # avoid duplicate rules generation for AIX and such
+ SHLIBEXT=.so-nobuild
+ SHLIBVEXT=.so.v-nobuild
+ SHLIBSEXT=.so.s-nobuild
+else
+ AC_MSG_NOTICE([using shared libraries])
-if test "$enable_shared" = yes; then
- case "$SHLIBEXT" in
- .so-nobuild)
- AC_MSG_WARN([shared libraries not supported on this architecture])
- RUN_ENV=
- CC_LINK="$CC_LINK_STATIC"
+ # Clear some stuff in case of AIX, etc.
+ if test "$STLIBEXT" = "$SHLIBEXT" ; then
+ STLIBEXT=.a-nobuild
+ fi
+ case "$SHLIBSEXT" in
+ .so.s-nobuild)
+ SHLIB_HAVE_MINOR_VERS=no
+ LIBLIST='lib$(LIBBASE)$(SHLIBEXT)'
+ LIBLINKS='$(TOPLIBD)/lib$(LIBBASE)$(SHLIBEXT) $(TOPLIBD)/lib$(LIBBASE)$(SHLIBVEXT)'
+ LIBINSTLIST="install-shared"
;;
*)
- # set this now because some logic below may reset SHLIBEXT
- DEPLIBEXT=$SHLIBEXT
- if test "$krb5_force_static" = "yes"; then
- AC_MSG_RESULT([Forcing static libraries.])
- # avoid duplicate rules generation for AIX and such
- SHLIBEXT=.so-nobuild
- SHLIBVEXT=.so.v-nobuild
- SHLIBSEXT=.so.s-nobuild
- else
- AC_MSG_NOTICE([enabling shared libraries])
- # Clear some stuff in case of AIX, etc.
- if test "$STLIBEXT" = "$SHLIBEXT" ; then
- STLIBEXT=.a-nobuild
- LIBLIST=
- LIBLINKS=
- OBJLISTS=
- LIBINSTLIST=
- fi
- LIBLIST="$LIBLIST "'lib$(LIBBASE)$(SHLIBEXT)'
- LIBLINKS="$LIBLINKS "'$(TOPLIBD)/lib$(LIBBASE)$(SHLIBEXT) $(TOPLIBD)/lib$(LIBBASE)$(SHLIBVEXT)'
- case "$SHLIBSEXT" in
- .so.s-nobuild)
- LIBINSTLIST="$LIBINSTLIST install-shared"
- ;;
- *)
- LIBLIST="$LIBLIST "'lib$(LIBBASE)$(SHLIBSEXT)'
- LIBLINKS="$LIBLINKS "'$(TOPLIBD)/lib$(LIBBASE)$(SHLIBSEXT)'
- LIBINSTLIST="$LIBINSTLIST install-shlib-soname"
- ;;
- esac
- OBJLISTS="$OBJLISTS OBJS.SH"
- fi
- CC_LINK="$CC_LINK_SHARED"
+ SHLIB_HAVE_MINOR_VERS=yes
+ LIBLIST='lib$(LIBBASE)$(SHLIBEXT) lib$(LIBBASE)$(SHLIBSEXT)'
+ LIBLINKS='$(TOPLIBD)/lib$(LIBBASE)$(SHLIBEXT) $(TOPLIBD)/lib$(LIBBASE)$(SHLIBVEXT) $(TOPLIBD)/lib$(LIBBASE)$(SHLIBSEXT)'
+ LIBINSTLIST="install-shlib-soname"
;;
esac
-else
- RUN_ENV=
- CC_LINK="$CC_LINK_STATIC"
- SHLIBEXT=.so-nobuild
- SHLIBVEXT=.so.v-nobuild
- SHLIBSEXT=.so.s-nobuild
-fi
-
-if test "$build_dynobj" = yes; then
- OBJLISTS=`echo $OBJLISTS | sed -e s/OBJS.ST//g -e s/OBJS.SH//g`
- OBJLISTS="$OBJLISTS OBJS.SH"
+ OBJLISTS="OBJS.SH"
fi
+CC_LINK="$CC_LINK_SHARED"
+AC_SUBST(SHLIB_HAVE_MINOR_VERS)
if test -z "$LIBLIST"; then
AC_MSG_ERROR([must enable one of shared or static libraries])
@@ -1320,20 +1262,6 @@ dnl [ --enable-profiled build profiled libraries @<:@disabled@:>@]
,
[if test "$enableval" = yes; then
AC_MSG_ERROR([Sorry, profiled libraries do not work in this release.])
-fi
-if false; then
- case $PFLIBEXT in
- .po-nobuild)
- AC_MSG_WARN([Profiled libraries not supported on this architecture.])
- ;;
- *)
- AC_MSG_NOTICE([enabling profiled libraries])
- LIBLIST="$LIBLIST "'lib$(LIBBASE)$(PFLIBEXT)'
- LIBLINKS="$LIBLINKS "'$(TOPLIBD)/lib$(LIBBASE)$(PFLIBEXT)'
- OBJLISTS="$OBJLISTS OBJS.PF"
- LIBINSTLIST="$LIBINSTLIST install-profiled"
- ;;
- esac
fi])])
dnl
diff --git a/src/appl/Makefile.in b/src/appl/Makefile.in
index 2a7d80a..abe6c0b 100644
--- a/src/appl/Makefile.in
+++ b/src/appl/Makefile.in
@@ -1,7 +1,8 @@
-thisconfigdir=.
+thisconfigdir=..
myfulldir=appl
-mydir=.
+mydir=appl
BUILDTOP=$(REL)..
-LOCAL_SUBDIRS= sample simple user_user gss-sample
+LOCAL_SUBDIRS= sample simple user_user gss-sample \
+ libpty bsd gssftp telnet
diff --git a/src/appl/configure.in b/src/appl/configure.in
deleted file mode 100644
index e8d2f65..0000000
--- a/src/appl/configure.in
+++ /dev/null
@@ -1,21 +0,0 @@
-K5_AC_INIT(configure.in)
-CONFIG_RULES
-KRB5_AC_INET6
-AC_PROG_INSTALL
-AC_CHECK_HEADERS(unistd.h stdlib.h string.h)
-AC_C_CONST
-dnl gss-misc.c needs this:
-AC_CHECK_HEADERS(sys/time.h time.h)
-dnl
-dnl Kludge for simple server --- FIXME is this the best way to do this?
-dnl
-if test "$ac_cv_lib_socket" = "yes" -a "$ac_cv_lib_nsl" = "yes"; then
- AC_DEFINE(BROKEN_STREAMS_SOCKETS,1,[Define if socket can't be bound to 0.0.0.0])
-fi
-dnl
-dnl
-KRB5_GETSOCKNAME_ARGS
-KRB5_GETPEERNAME_ARGS
-KRB5_BUILD_PROGRAM
-AC_CONFIG_SUBDIRS(libpty bsd gssftp telnet)
-V5_AC_OUTPUT_MAKEFILE(. sample sample/sclient sample/sserver simple simple/client simple/server gss-sample user_user)
diff --git a/src/appl/gss-sample/Makefile.in b/src/appl/gss-sample/Makefile.in
index f43bdc9..a77f3a2 100644
--- a/src/appl/gss-sample/Makefile.in
+++ b/src/appl/gss-sample/Makefile.in
@@ -1,6 +1,6 @@
-thisconfigdir=./..
+thisconfigdir=../..
myfulldir=appl/gss-sample
-mydir=gss-sample
+mydir=appl/gss-sample
BUILDTOP=$(REL)..$(S)..
DEFINES = -DUSE_AUTOCONF_H -DGSSAPI_V2
PROG_LIBPATH=-L$(TOPLIBD)
@@ -11,7 +11,23 @@ SRCS= $(srcdir)/gss-client.c $(srcdir)/gss-misc.c $(srcdir)/gss-server.c
OBJS= gss-client.o gss-misc.o gss-server.o
all-unix:: gss-server gss-client
-all-windows:: $(OUTPRE)gss-server.exe $(OUTPRE)gss-client.exe
+
+##WIN32##VERSIONRC = $(BUILDTOP)\windows\version.rc
+##WIN32##RCFLAGS=$(CPPFLAGS) -I$(SRCTOP) -D_WIN32 -DRES_ONLY
+
+##WIN32##GSSCLIENT=$(OUTPRE)gss-client.exe
+##WIN32##GSSSERVER=$(OUTPRE)gss-server.exe
+
+##WIN32##CLIENTRES=$(GSSCLIENT:.exe=.res)
+##WIN32##SERVERRES=$(GSSSERVER:.exe=.res)
+
+##WIN32##$(CLIENTRES): $(VERSIONRC)
+##WIN32## $(RC) $(RCFLAGS) -DGSS_CLIENT_APP -fo $@ -r $**
+##WIN32##$(SERVERRES): $(VERSIONRC)
+##WIN32## $(RC) $(RCFLAGS) -DGSS_SERVER_APP -fo $@ -r $**
+
+
+##WIN32##all-windows:: $(OUTPRE)gss-server.exe $(OUTPRE)gss-client.exe
gss-server: gss-server.o gss-misc.o $(GSS_DEPLIBS) $(KRB5_BASE_DEPLIBS)
$(CC_LINK) -o gss-server gss-server.o gss-misc.o $(GSS_LIBS) $(KRB5_BASE_LIBS)
@@ -19,13 +35,13 @@ gss-server: gss-server.o gss-misc.o $(GSS_DEPLIBS) $(KRB5_BASE_DEPLIBS)
gss-client: gss-client.o gss-misc.o $(GSS_DEPLIBS) $(KRB5_BASE_DEPLIBS)
$(CC_LINK) -o gss-client gss-client.o gss-misc.o $(GSS_LIBS) $(KRB5_BASE_LIBS)
-$(OUTPRE)gss-server.exe: $(OUTPRE)gss-server.obj $(OUTPRE)gss-misc.obj $(GLIB) $(KLIB)
- link $(EXE_LINKOPTS) -out:$@ $** ws2_32.lib $(SCLIB)
- $(_VC_MANIFEST_EMBED_EXE)
+##WIN32##$(GSSSERVER): $(OUTPRE)gss-server.obj $(OUTPRE)gss-misc.obj $(GLIB) $(KLIB) $(SERVERRES)
+##WIN32## link $(EXE_LINKOPTS) -out:$@ $** ws2_32.lib $(SCLIB)
+##WIN32## $(_VC_MANIFEST_EMBED_EXE)
-$(OUTPRE)gss-client.exe: $(OUTPRE)gss-client.obj $(OUTPRE)gss-misc.obj $(GLIB) $(KLIB)
- link $(EXE_LINKOPTS) -out:$@ $** ws2_32.lib $(SCLIB)
- $(_VC_MANIFEST_EMBED_EXE)
+##WIN32##$(GSSCLIENT): $(OUTPRE)gss-client.obj $(OUTPRE)gss-misc.obj $(GLIB) $(KLIB) $(CLIENTRES)
+##WIN32## link $(EXE_LINKOPTS) -out:$@ $** ws2_32.lib $(SCLIB)
+##WIN32## $(_VC_MANIFEST_EMBED_EXE)
clean-unix::
$(RM) gss-server gss-client
@@ -41,9 +57,9 @@ install-unix::
$(OUTPRE)gss-client.$(OBJEXT): $(BUILDTOP)/include/gssapi/gssapi.h \
$(BUILDTOP)/include/gssapi/gssapi_generic.h gss-client.c \
gss-misc.h
-$(OUTPRE)gss-misc.$(OBJEXT): $(BUILDTOP)/include/gssapi/gssapi.h \
- $(BUILDTOP)/include/gssapi/gssapi_generic.h gss-misc.c \
- gss-misc.h
+$(OUTPRE)gss-misc.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+ $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_generic.h \
+ gss-misc.c gss-misc.h
$(OUTPRE)gss-server.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
$(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_generic.h \
$(SRCTOP)/include/port-sockets.h gss-misc.h gss-server.c
diff --git a/src/appl/gss-sample/gss-misc.c b/src/appl/gss-sample/gss-misc.c
index fe578d1..cfaa0f8 100644
--- a/src/appl/gss-sample/gss-misc.c
+++ b/src/appl/gss-sample/gss-misc.c
@@ -57,6 +57,9 @@ static char *rcsid = "$Header$";
#include <sys/socket.h>
#endif
#include <errno.h>
+
+#include <autoconf.h>
+
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
diff --git a/src/appl/libpty/Makefile.in b/src/appl/libpty/Makefile.in
index 521341d..92b33f8 100644
--- a/src/appl/libpty/Makefile.in
+++ b/src/appl/libpty/Makefile.in
@@ -106,7 +106,7 @@ pty_err.c: pty_err.et
$(BUILDTOP)/include/autoconf.h: $(SRCTOP)/include/autoconf.h.in
(cd $(BUILDTOP)/include; $(MAKE) autoconf.h)
-
+@libpriv_frag@
@lib_frag@
@libobj_frag@
diff --git a/src/appl/libpty/configure.in b/src/appl/libpty/configure.in
index cb5fe7e..22af702 100644
--- a/src/appl/libpty/configure.in
+++ b/src/appl/libpty/configure.in
@@ -255,8 +255,7 @@ fi
dnl
KRB5_AC_INET6
AC_C_CONST
-dnl KRB5_BUILD_LIBRARY_WITH_DEPS
-KRB5_BUILD_LIBRARY_STATIC
+KRB5_BUILD_LIBRARY
KRB5_BUILD_LIBOBJS
KRB5_BUILD_PROGRAM
KRB5_RUN_FLAGS
diff --git a/src/appl/sample/Makefile.in b/src/appl/sample/Makefile.in
index a580359..4047796 100644
--- a/src/appl/sample/Makefile.in
+++ b/src/appl/sample/Makefile.in
@@ -1,5 +1,5 @@
-thisconfigdir=./..
+thisconfigdir=../..
myfulldir=appl/sample
-mydir=sample
+mydir=appl/sample
LOCAL_SUBDIRS = sclient sserver
BUILDTOP=$(REL)..$(S)..
diff --git a/src/appl/sample/sclient/Makefile.in b/src/appl/sample/sclient/Makefile.in
index 868f678..db69a13 100644
--- a/src/appl/sample/sclient/Makefile.in
+++ b/src/appl/sample/sclient/Makefile.in
@@ -1,6 +1,6 @@
-thisconfigdir=./../..
+thisconfigdir=../../..
myfulldir=appl/sample/sclient
-mydir=sample/sclient
+mydir=appl/sample/sclient
BUILDTOP=$(REL)..$(S)..$(S)..
PROG_LIBPATH=-L$(TOPLIBD)
diff --git a/src/appl/sample/sserver/Makefile.in b/src/appl/sample/sserver/Makefile.in
index 32e8864..e5ca92f 100644
--- a/src/appl/sample/sserver/Makefile.in
+++ b/src/appl/sample/sserver/Makefile.in
@@ -1,6 +1,6 @@
-thisconfigdir=./../..
+thisconfigdir=../../..
myfulldir=appl/sample/sserver
-mydir=sample/sserver
+mydir=appl/sample/sserver
BUILDTOP=$(REL)..$(S)..$(S)..
PROG_LIBPATH=-L$(TOPLIBD)
diff --git a/src/appl/simple/Makefile.in b/src/appl/simple/Makefile.in
index 9e6f16d..11d945f 100644
--- a/src/appl/simple/Makefile.in
+++ b/src/appl/simple/Makefile.in
@@ -1,5 +1,5 @@
-thisconfigdir=./..
+thisconfigdir=../..
myfulldir=appl/simple
-mydir=simple
+mydir=appl/simple
LOCAL_SUBDIRS = client server
BUILDTOP=$(REL)..$(S)..
diff --git a/src/appl/simple/client/Makefile.in b/src/appl/simple/client/Makefile.in
index c7023ca..c6840fe 100644
--- a/src/appl/simple/client/Makefile.in
+++ b/src/appl/simple/client/Makefile.in
@@ -1,6 +1,6 @@
-thisconfigdir=./../..
+thisconfigdir=../../..
myfulldir=appl/simple/client
-mydir=simple/client
+mydir=appl/simple/client
BUILDTOP=$(REL)..$(S)..$(S)..
PROG_LIBPATH=-L$(TOPLIBD)
PROG_RPATH=$(KRB5_LIBDIR)
diff --git a/src/appl/simple/server/Makefile.in b/src/appl/simple/server/Makefile.in
index d670eda..12b2b04 100644
--- a/src/appl/simple/server/Makefile.in
+++ b/src/appl/simple/server/Makefile.in
@@ -1,6 +1,6 @@
-thisconfigdir=./../..
+thisconfigdir=../../..
myfulldir=appl/simple/server
-mydir=simple/server
+mydir=appl/simple/server
BUILDTOP=$(REL)..$(S)..$(S)..
LOCALINCLUDES= -I.. -I$(srcdir)/..
diff --git a/src/appl/telnet/configure.in b/src/appl/telnet/configure.in
index 04173af..d4870ec 100644
--- a/src/appl/telnet/configure.in
+++ b/src/appl/telnet/configure.in
@@ -24,7 +24,7 @@ else
AC_MSG_RESULT(Kerberos 4 authentication enabled)
AC_DEFINE(KRB4,1,[Define if krb4 authentication is enabled])
fi
-KRB5_BUILD_LIBRARY_STATIC
+KRB5_BUILD_LIBRARY
KRB5_BUILD_LIBOBJS
dnl
old_LIBS="$LIBS"
diff --git a/src/appl/telnet/libtelnet/Makefile.in b/src/appl/telnet/libtelnet/Makefile.in
index 2a6c7dc..38ff905 100644
--- a/src/appl/telnet/libtelnet/Makefile.in
+++ b/src/appl/telnet/libtelnet/Makefile.in
@@ -89,6 +89,7 @@ enc_des.o: key-proto.h
enc_des.o: misc-proto.h
install::
+@libpriv_frag@
@lib_frag@
@libobj_frag@
diff --git a/src/appl/telnet/telnetd/state.c b/src/appl/telnet/telnetd/state.c
index e08c5bb..4693fc9 100644
--- a/src/appl/telnet/telnetd/state.c
+++ b/src/appl/telnet/telnetd/state.c
@@ -1665,7 +1665,8 @@ static int envvarok(varp)
strcmp(varp, "RESOLV_HOST_CONF") && /* linux */
strcmp(varp, "NLSPATH") && /* locale stuff */
strncmp(varp, "LC_", strlen("LC_")) && /* locale stuff */
- strcmp(varp, "IFS")) {
+ strcmp(varp, "IFS") &&
+ (varp[0] != '-')) {
return 1;
} else {
syslog(LOG_INFO, "Rejected the attempt to modify the environment variable \"%s\"", varp);
diff --git a/src/appl/telnet/telnetd/sys_term.c b/src/appl/telnet/telnetd/sys_term.c
index bfd1f81..d78c2e8 100644
--- a/src/appl/telnet/telnetd/sys_term.c
+++ b/src/appl/telnet/telnetd/sys_term.c
@@ -1287,12 +1287,25 @@ start_login(host, autologin, name)
#endif
#if defined (AUTHENTICATION)
if (auth_level >= 0 && autologin == AUTH_VALID) {
+ if (name[0] == '-') {
+ /*
+ * Authenticated and authorized to log in to an
+ * account starting with '-'? Even if that
+ * unlikely case comes to pass, the current login
+ * program will not parse the resulting command
+ * line properly.
+ */
+ syslog(LOG_ERR, "user name cannot start with '-'");
+ fatal(net, "user name cannot start with '-'");
+ exit(1);
+ }
# if !defined(NO_LOGIN_F)
#if defined(LOGIN_CAP_F)
argv = addarg(argv, "-F");
#else
argv = addarg(argv, "-f");
#endif
+ argv = addarg(argv, "--");
argv = addarg(argv, name);
# else
# if defined(LOGIN_R)
@@ -1371,17 +1384,27 @@ start_login(host, autologin, name)
pty = xpty;
}
# else
+ argv = addarg(argv, "--");
argv = addarg(argv, name);
# endif
# endif
} else
#endif
if (getenv("USER")) {
- argv = addarg(argv, getenv("USER"));
+ char *user = getenv("USER");
+ if (user[0] == '-') {
+ /* "telnet -l-x ..." */
+ syslog(LOG_ERR, "user name cannot start with '-'");
+ fatal(net, "user name cannot start with '-'");
+ exit(1);
+ }
+ argv = addarg(argv, "--");
+ argv = addarg(argv, user);
#if defined(LOGIN_ARGS) && defined(NO_LOGIN_P)
{
register char **cpp;
for (cpp = environ; *cpp; cpp++)
+ if ((*cpp)[0] != '-')
argv = addarg(argv, *cpp);
}
#endif
diff --git a/src/appl/user_user/Makefile.in b/src/appl/user_user/Makefile.in
index e55eda8..b321cc5 100644
--- a/src/appl/user_user/Makefile.in
+++ b/src/appl/user_user/Makefile.in
@@ -1,6 +1,6 @@
-thisconfigdir=./..
+thisconfigdir=../..
myfulldir=appl/user_user
-mydir=user_user
+mydir=appl/user_user
BUILDTOP=$(REL)..$(S)..
DEFINES = -DDEBUG
PROG_LIBPATH=-L$(TOPLIBD)
diff --git a/src/clients/kcpytkt/Makefile.in b/src/clients/kcpytkt/Makefile.in
index a989b50..a47ac5f 100644
--- a/src/clients/kcpytkt/Makefile.in
+++ b/src/clients/kcpytkt/Makefile.in
@@ -6,16 +6,26 @@ BUILDTOP=$(REL)..$(S)..
PROG_LIBPATH=-L$(TOPLIBD)
PROG_RPATH=$(KRB5_LIBDIR)
+##WIN32##VERSIONRC = $(BUILDTOP)\windows\version.rc
+##WIN32##RCFLAGS=$(CPPFLAGS) -I$(SRCTOP) -D_WIN32 -DRES_ONLY
+
+##WIN32##KCPYTKT=$(OUTPRE)kcpytkt.exe
+
+##WIN32##EXERES=$(KCPYTKT:.exe=.res)
+
+##WIN32##$(EXERES): $(VERSIONRC)
+##WIN32## $(RC) $(RCFLAGS) -DKCPYTKT_APP -fo $@ -r $**
+
all-unix:: kcpytkt
-all-windows:: $(OUTPRE)kcpytkt.exe
+##WIN32##all-windows:: $(KCPYTKT)
all-mac::
kcpytkt: kcpytkt.o $(KRB4COMPAT_DEPLIBS)
$(CC_LINK) -o $@ kcpytkt.o $(KRB4COMPAT_LIBS)
-$(OUTPRE)kcpytkt.exe: $(OUTPRE)kcpytkt.obj $(BUILDTOP)\util\windows\$(OUTPRE)getopt.obj $(KLIB) $(CLIB)
- link $(EXE_LINKOPTS) /out:$@ $**
- $(_VC_MANIFEST_EMBED_EXE)
+##WIN32##$(KCPYTKT): $(OUTPRE)kcpytkt.obj $(BUILDTOP)\util\windows\$(OUTPRE)getopt.obj $(KLIB) $(CLIB) $(EXERES)
+##WIN32## link $(EXE_LINKOPTS) /out:$@ $**
+##WIN32## $(_VC_MANIFEST_EMBED_EXE)
clean-unix::
$(RM) kcpytkt.o kcpytkt
diff --git a/src/clients/kdeltkt/Makefile.in b/src/clients/kdeltkt/Makefile.in
index f5f746f..dbd4b71 100644
--- a/src/clients/kdeltkt/Makefile.in
+++ b/src/clients/kdeltkt/Makefile.in
@@ -6,16 +6,26 @@ BUILDTOP=$(REL)..$(S)..
PROG_LIBPATH=-L$(TOPLIBD)
PROG_RPATH=$(KRB5_LIBDIR)
+##WIN32##VERSIONRC = $(BUILDTOP)\windows\version.rc
+##WIN32##RCFLAGS=$(CPPFLAGS) -I$(SRCTOP) -D_WIN32 -DRES_ONLY
+
+##WIN32##KDELTKT=$(OUTPRE)kdeltkt.exe
+
+##WIN32##EXERES=$(KDELTKT:.exe=.res)
+
+##WIN32##$(EXERES): $(VERSIONRC)
+##WIN32## $(RC) $(RCFLAGS) -DKDELTKT_APP -fo $@ -r $**
+
all-unix:: kdeltkt
-all-windows:: $(OUTPRE)kdeltkt.exe
+##WIN32##all-windows:: $(KDELTKT)
all-mac::
kdeltkt: kdeltkt.o $(KRB4COMPAT_DEPLIBS)
$(CC_LINK) -o $@ kdeltkt.o $(KRB4COMPAT_LIBS)
-$(OUTPRE)kdeltkt.exe: $(OUTPRE)kdeltkt.obj $(BUILDTOP)\util\windows\$(OUTPRE)getopt.obj $(KLIB) $(CLIB)
- link $(EXE_LINKOPTS) /out:$@ $**
- $(_VC_MANIFEST_EMBED_EXE)
+##WIN32##$(KDELTKT): $(OUTPRE)kdeltkt.obj $(BUILDTOP)\util\windows\$(OUTPRE)getopt.obj $(KLIB) $(CLIB) $(EXERES)
+##WIN32## link $(EXE_LINKOPTS) /out:$@ $**
+##WIN32## $(_VC_MANIFEST_EMBED_EXE)
clean-unix::
$(RM) kdeltkt.o kdeltkt
diff --git a/src/clients/kdestroy/Makefile.in b/src/clients/kdestroy/Makefile.in
index ce273af..51cf5cf 100644
--- a/src/clients/kdestroy/Makefile.in
+++ b/src/clients/kdestroy/Makefile.in
@@ -9,15 +9,25 @@ SRCS=kdestroy.c
PROG_LIBPATH=-L$(TOPLIBD)
PROG_RPATH=$(KRB5_LIBDIR)
+##WIN32##VERSIONRC = $(BUILDTOP)\windows\version.rc
+##WIN32##RCFLAGS=$(CPPFLAGS) -I$(SRCTOP) -D_WIN32 -DRES_ONLY
+
+##WIN32##KDESTROY=$(OUTPRE)kdestroy.exe
+
+##WIN32##EXERES=$(KDESTROY:.exe=.res)
+
+##WIN32##$(EXERES): $(VERSIONRC)
+##WIN32## $(RC) $(RCFLAGS) -DKDESTROY_APP -fo $@ -r $**
+
all-unix:: kdestroy
-all-windows:: $(OUTPRE)kdestroy.exe
+##WIN32##all-windows:: $(KDESTROY)
kdestroy: kdestroy.o $(KRB4COMPAT_DEPLIBS)
$(CC_LINK) -o $@ kdestroy.o $(KRB4COMPAT_LIBS)
-$(OUTPRE)kdestroy.exe: $(OUTPRE)kdestroy.obj $(BUILDTOP)\util\windows\$(OUTPRE)getopt.obj $(KLIB) $(CLIB)
- link $(EXE_LINKOPTS) -out:$@ $**
- $(_VC_MANIFEST_EMBED_EXE)
+##WIN32##$(KDESTROY): $(OUTPRE)kdestroy.obj $(BUILDTOP)\util\windows\$(OUTPRE)getopt.obj $(KLIB) $(CLIB) $(EXERES)
+##WIN32## link $(EXE_LINKOPTS) -out:$@ $**
+##WIN32## $(_VC_MANIFEST_EMBED_EXE)
clean-unix::
$(RM) kdestroy.o kdestroy
diff --git a/src/clients/kinit/Makefile.in b/src/clients/kinit/Makefile.in
index ec023b7..ead20cf 100644
--- a/src/clients/kinit/Makefile.in
+++ b/src/clients/kinit/Makefile.in
@@ -12,15 +12,25 @@ SRCS=kinit.c
##WIN32##LOCALINCLUDES=-I$(BUILDTOP)\util\windows
##WIN32##DEFINES=-DGETOPT_LONG
+##WIN32##VERSIONRC = $(BUILDTOP)\windows\version.rc
+##WIN32##RCFLAGS=$(CPPFLAGS) -I$(SRCTOP) -D_WIN32 -DRES_ONLY
+
+##WIN32##KINIT=$(OUTPRE)kinit.exe
+
+##WIN32##EXERES=$(KINIT:.exe=.res)
+
+##WIN32##$(EXERES): $(VERSIONRC)
+##WIN32## $(RC) $(RCFLAGS) -DKINIT_APP -fo $@ -r $**
+
all-unix:: kinit
-all-windows:: $(OUTPRE)kinit.exe
+##WIN32##all-windows:: $(KINIT)
kinit: kinit.o $(KRB4COMPAT_DEPLIBS)
$(CC_LINK) -o $@ kinit.o $(KRB4COMPAT_LIBS)
-$(OUTPRE)kinit.exe: $(OUTPRE)kinit.obj $(BUILDTOP)\util\windows\$(OUTPRE)getopt.lib $(KLIB) $(CLIB)
- link $(EXE_LINKOPTS) -out:$@ $** advapi32.lib
- $(_VC_MANIFEST_EMBED_EXE)
+##WIN32##$(KINIT): $(OUTPRE)kinit.obj $(BUILDTOP)\util\windows\$(OUTPRE)getopt.lib $(KLIB) $(CLIB) $(EXERES)
+##WIN32## link $(EXE_LINKOPTS) -out:$@ $** advapi32.lib
+##WIN32## $(_VC_MANIFEST_EMBED_EXE)
clean-unix::
$(RM) kinit.o kinit
diff --git a/src/clients/klist/Makefile.in b/src/clients/klist/Makefile.in
index 7a83404..66d0c4a 100644
--- a/src/clients/klist/Makefile.in
+++ b/src/clients/klist/Makefile.in
@@ -9,15 +9,25 @@ PROG_RPATH=$(KRB5_LIBDIR)
SRCS = klist.c
+##WIN32##VERSIONRC = $(BUILDTOP)\windows\version.rc
+##WIN32##RCFLAGS=$(CPPFLAGS) -I$(SRCTOP) -D_WIN32 -DRES_ONLY
+
+##WIN32##KLIST=$(OUTPRE)klist.exe
+
+##WIN32##EXERES=$(KLIST:.exe=.res)
+
+##WIN32##$(EXERES): $(VERSIONRC)
+##WIN32## $(RC) $(RCFLAGS) -DKLIST_APP -fo $@ -r $**
+
all-unix:: klist
-all-windows:: $(OUTPRE)klist.exe
+##WIN32##all-windows:: $(KLIST)
klist: klist.o $(KRB4COMPAT_DEPLIBS)
$(CC_LINK) -o $@ klist.o $(KRB4COMPAT_LIBS)
-$(OUTPRE)klist.exe: $(OUTPRE)klist.obj $(BUILDTOP)\util\windows\$(OUTPRE)getopt.lib $(SLIB) $(KLIB) $(CLIB)
- link $(EXE_LINKOPTS) -out:$@ $** ws2_32.lib $(SCLIB)
- $(_VC_MANIFEST_EMBED_EXE)
+##WIN32##$(KLIST): $(OUTPRE)klist.obj $(BUILDTOP)\util\windows\$(OUTPRE)getopt.lib $(SLIB) $(KLIB) $(CLIB) $(EXERES)
+##WIN32## link $(EXE_LINKOPTS) -out:$@ $** ws2_32.lib $(SCLIB)
+##WIN32## $(_VC_MANIFEST_EMBED_EXE)
clean-unix::
$(RM) klist.o klist
diff --git a/src/clients/kpasswd/Makefile.in b/src/clients/kpasswd/Makefile.in
index 0627334..bfa26f7 100644
--- a/src/clients/kpasswd/Makefile.in
+++ b/src/clients/kpasswd/Makefile.in
@@ -17,6 +17,16 @@ ksetpwd: ksetpwd.o $(KRB5_BASE_DEPLIBS)
kpasswd.o: $(srcdir)/kpasswd.c
ksetpwd.o: $(srcdir)/ksetpwd.c
+##WIN32##VERSIONRC = $(BUILDTOP)\windows\version.rc
+##WIN32##RCFLAGS=$(CPPFLAGS) -I$(SRCTOP) -D_WIN32 -DRES_ONLY
+
+##WIN32##KPWD=$(OUTPRE)kpasswd.exe
+
+##WIN32##EXERES=$(KPWD:.exe=.res)
+
+##WIN32##$(EXERES): $(VERSIONRC)
+##WIN32## $(RC) $(RCFLAGS) -DKPASSWD_APP -fo $@ -r $**
+
all-unix:: kpasswd ksetpwd
clean-unix::
@@ -26,10 +36,12 @@ install-all install-kdc install-server install-client install-unix::
$(INSTALL_PROGRAM) kpasswd $(DESTDIR)$(CLIENT_BINDIR)/`echo kpasswd|sed '$(transform)'`
$(INSTALL_DATA) $(srcdir)/kpasswd.M $(DESTDIR)$(CLIENT_MANDIR)/`echo kpasswd|sed '$(transform)'`.1;
-all-windows:: $(OUTPRE)kpasswd.exe
+##WIN32##all-windows:: $(KPWD)
+
+##WIN32##$(KPWD): $(OUTPRE)kpasswd.obj $(KLIB) $(CLIB) $(EXERES)
+##WIN32## link $(EXE_LINKOPTS) -out:$@ $** $(SCLIB)
+##WIN32## $(_VC_MANIFEST_EMBED_EXE)
-$(OUTPRE)kpasswd.exe: $(OUTPRE)kpasswd.obj $(KLIB) $(CLIB)
- link $(EXE_LINKOPTS) -out:$@ $** $(SCLIB)
# +++ Dependency line eater +++
#
# Makefile dependencies follow. This must be the last section in
diff --git a/src/clients/kvno/Makefile.in b/src/clients/kvno/Makefile.in
index 7072931..047c25b 100644
--- a/src/clients/kvno/Makefile.in
+++ b/src/clients/kvno/Makefile.in
@@ -9,15 +9,26 @@ SRCS=kvno.c
PROG_LIBPATH=-L$(TOPLIBD)
PROG_RPATH=$(KRB5_LIBDIR)
+##WIN32##VERSIONRC = $(BUILDTOP)\windows\version.rc
+##WIN32##RCFLAGS=$(CPPFLAGS) -I$(SRCTOP) -D_WIN32 -DRES_ONLY
+
+##WIN32##KVNO=$(OUTPRE)kvno.exe
+
+##WIN32##EXERES=$(KVNO:.exe=.res)
+
+##WIN32##$(EXERES): $(VERSIONRC)
+##WIN32## $(RC) $(RCFLAGS) -DKVNO_APP -fo $@ -r $**
+
all-unix:: kvno
-all-windows:: $(OUTPRE)kvno.exe
+
+##WIN32##all-windows:: $(KVNO)
kvno: kvno.o $(KRB4COMPAT_DEPLIBS)
$(CC_LINK) -o $@ kvno.o $(KRB4COMPAT_LIBS)
-$(OUTPRE)kvno.exe: $(OUTPRE)kvno.obj $(BUILDTOP)\util\windows\$(OUTPRE)getopt.obj $(KLIB) $(CLIB)
- link $(EXE_LINKOPTS) /out:$@ $**
- $(_VC_MANIFEST_EMBED_EXE)
+##WIN32##$(KVNO): $(OUTPRE)kvno.obj $(BUILDTOP)\util\windows\$(OUTPRE)getopt.obj $(KLIB) $(CLIB) $(EXERES)
+##WIN32## link $(EXE_LINKOPTS) /out:$@ $**
+##WIN32## $(_VC_MANIFEST_EMBED_EXE)
clean-unix::
$(RM) kvno.o kvno
diff --git a/src/config/libnodeps.in b/src/config/libnodeps.in
new file mode 100644
index 0000000..6416a30
--- /dev/null
+++ b/src/config/libnodeps.in
@@ -0,0 +1,4 @@
+# Must override when there are no dependencies, because on some
+# platforms there's a prefix stuck in front of the library path that
+# we won't set (SHLIB_RDIRS).
+SHLIB_EXPFLAGS=
diff --git a/src/config/libpriv.in b/src/config/libpriv.in
new file mode 100644
index 0000000..c7e3443
--- /dev/null
+++ b/src/config/libpriv.in
@@ -0,0 +1,13 @@
+# Additional definitions for private libraries, which we build as archive
+# libraries (or equivalent) and do not install.
+#
+# The defaults (for installed shared libraries) are in pre.in. We
+# override them here, before lib.in uses them.
+LIBLIST=lib$(LIBBASE)$(STLIBEXT)
+LIBLINKS=$(TOPLIBD)/lib$(LIBBASE)$(STLIBEXT)
+OBJLISTS=OBJS.ST
+LIBINSTLIST=
+SHLIBEXT=.so-nobuild
+SHLIBVEXT=.so.v-nobuild
+SHLIBSEXT=.so.s-nobuild
+STLIBEXT=$(STLIBEXT_if_static)
diff --git a/src/config/pre.in b/src/config/pre.in
index 1c151bb..01c083b 100644
--- a/src/config/pre.in
+++ b/src/config/pre.in
@@ -472,6 +472,12 @@ MAKE_COMMANDS-k5= $(BUILDTOP)/util/ss/mk_cmds
## Parameters to be set by configure for use in lib.in:
##
+#
+# These settings are for building shared libraries only. Including
+# libpriv.in will override with values appropriate for static
+# libraries that we don't install. Some values will depend on whether
+# the platform supports major and minor version number extensions on
+# shared libraries, hence the FOO_@@ settings.
LN_S=@LN_S@
AR=@AR@
@@ -479,19 +485,26 @@ AR=@AR@
# Set to "lib$(LIBBASE)$(STEXT) lib$(LIBBASE)$(SHEXT) lib$(LIBBASE)$(PFEXT)" or
# some subset thereof by configure; determines which types of libs get
# built.
-LIBLIST=@LIBLIST@
+LIBLIST=$(LIBLIST_@SHLIB_HAVE_MINOR_VERS@)
+LIBLIST_yes=lib$(LIBBASE)$(SHLIBEXT) lib$(LIBBASE)$(SHLIBSEXT)
+LIBLIST_no=lib$(LIBBASE)$(SHLIBEXT)
# Set by configure; list of library symlinks to make to $(TOPLIBD)
-LIBLINKS=@LIBLINKS@
+LIBLINKS=$(LIBLINKS_@SHLIB_HAVE_MINOR_VERS@)
+LIBLINKS_yes=$(TOPLIBD)/lib$(LIBBASE)$(SHLIBEXT) $(TOPLIBD)/lib$(LIBBASE)$(SHLIBVEXT) $(TOPLIBD)/lib$(LIBBASE)$(SHLIBSEXT)
+LIBLINKS_no=$(TOPLIBD)/lib$(LIBBASE)$(SHLIBEXT) $(TOPLIBD)/lib$(LIBBASE)$(SHLIBVEXT)
# Set by configure; list of install targets
-LIBINSTLIST=@LIBINSTLIST@
+LIBINSTLIST=$(LIBINSTLIST_@SHLIB_HAVE_MINOR_VERS@)
+LIBINSTLIST_yes=install-shlib-soname
+LIBINSTLIST_no=install-shared
# Some of these should really move to pre.in, since programs will need
# it too. (e.g. stuff that has dependencies on the libraries)
# usually .a
-STLIBEXT=@STLIBEXT@
+STLIBEXT_if_static=@STLIBEXT@
+STLIBEXT=.a-nobuild
# usually .so.$(LIBMAJOR).$(LIBMINOR)
SHLIBVEXT=@SHLIBVEXT@
@@ -533,7 +546,7 @@ SHLIB_EXPFLAGS=@SHLIB_EXPFLAGS@
# Set to "OBJS.ST OBJS.SH OBJS.PF" or some subset thereof by
# configure; determines which types of object files get built.
-OBJLISTS=@OBJLISTS@
+OBJLISTS=OBJS.SH
# Note that $(LIBSRCS) *cannot* contain any variable references, or
# the suffix substitution will break on some platforms!
diff --git a/src/config/shlib.conf b/src/config/shlib.conf
index 3e75b87..c10ce4f 100644
--- a/src/config/shlib.conf
+++ b/src/config/shlib.conf
@@ -58,7 +58,7 @@ alpha*-dec-osf*)
# Alpha OSF/1 doesn't need separate PIC objects
SHOBJEXT=.o
INIT_FINI_PREP=initfini=
- LDCOMBINE='$(CC) $(PTHREAD_CFLAGS) -shared -Wl,-expect_unresolved -Wl,\* -Wl,-update_registry -Wl,$(BUILDTOP)/so_locations -Wl,-soname -Wl,$(LIBPREFIX)$(LIBBASE)$(SHLIBSEXT) -Wl,-hidden -Wl,-input,osf1.exports $$initfini'
+ LDCOMBINE='$(CC) $(CFLAGS) $(PTHREAD_CFLAGS) -shared -Wl,-expect_unresolved -Wl,\* -Wl,-update_registry -Wl,$(BUILDTOP)/so_locations -Wl,-soname -Wl,$(LIBPREFIX)$(LIBBASE)$(SHLIBSEXT) -Wl,-hidden -Wl,-input,osf1.exports $$initfini'
SHLIB_EXPORT_FILE_DEP=osf1.exports
use_linker_init_option=yes
use_linker_fini_option=yes
@@ -369,7 +369,7 @@ mips-*-netbsd*)
SHLIBEXT=.so
# Linux ld doesn't default to stuffing the SONAME field...
# Use objdump -x to examine the fields of the library
- LDCOMBINE='$(CC) -shared -fPIC -Wl,-h,$(LIBPREFIX)$(LIBBASE)$(SHLIBSEXT) $(LDFLAGS)'
+ LDCOMBINE='$(CC) -shared -fPIC -Wl,-h,$(LIBPREFIX)$(LIBBASE)$(SHLIBSEXT),--no-undefined $(LDFLAGS)'
#
LDCOMBINE_TAIL='-Wl,--version-script binutils.versions && $(PERL) -w $(SRCTOP)/util/export-check.pl $(SHLIB_EXPORT_FILE) $@'
SHLIB_EXPORT_FILE_DEP=binutils.versions
diff --git a/src/configure.in b/src/configure.in
index a397c56..515d4a0 100644
--- a/src/configure.in
+++ b/src/configure.in
@@ -41,7 +41,7 @@ dnl configure.in...
dnl
AC_CHECK_FUNCS(memmove)
KRB5_BUILD_LIBOBJS
-KRB5_BUILD_LIBRARY_WITH_DEPS
+KRB5_BUILD_LIBRARY
KRB5_BUILD_PROGRAM
dnl for slave
AC_TYPE_MODE_T
@@ -125,7 +125,7 @@ dnl from old include/configure.in
AH_TEMPLATE([HAVE_STRUCT_SOCKADDR_STORAGE],
[Define if "struct sockaddr_storage" is available.])
dnl
-AC_CONFIG_HEADER(include/autoconf.h)
+AC_CONFIG_HEADER(include/autoconf.h, [: autoconf.h cmds], [: autoconf.h init cmds])
AC_PROG_INSTALL
AC_PROG_AWK
AC_PROG_LEX
@@ -558,6 +558,11 @@ AC_CHECK_TYPES([uint32_t, int32_t, uint64_t, int64_t, uint_least32_t, uintptr_t,
# include <inttypes.h>
#endif
])
+AC_CHECK_TYPES([struct cmsghdr, struct in_pktinfo, struct in6_pktinfo], , , [
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+])
dnl
dnl stuff for util/profile
dnl
@@ -844,6 +849,43 @@ case "$krb5_cv_host" in
esac
changequote([, ])
AC_SUBST(PASS)
+
+dnl for lib/apputils
+AC_REPLACE_FUNCS(daemon)
+
+dnl for tests/
+if test x"$RUNTEST" != x; then
+ HAVE_RUNTEST=yes
+else
+ HAVE_RUNTEST=no
+fi
+AC_SUBST(HAVE_RUNTEST)
+if test "$KRB4_LIB" = ''; then
+ KRB4_DEJAGNU_TEST="KRBIV=0"
+else
+ AC_MSG_RESULT(Kerberos 4 testing enabled)
+ KRB4_DEJAGNU_TEST="KRBIV=1"
+fi
+AC_SUBST(KRB4_DEJAGNU_TEST)
+
+dnl for plugins/kdb/db2
+dnl
+dnl AIX is unusual in that it wants all symbols resolved at link time
+dnl Fortunately, it will allow us to link the kdb library now, even if
+dnl it is linked again later.
+case $krb5_cv_host in
+*-*-aix*)
+ DB_EXTRA_LIBS=-ldb
+ ;;
+*)
+ DB_EXTRA_LIBS=
+ ;;
+esac
+AC_SUBST(DB_EXTRA_LIBS)
+if test "$DB_VERSION" = k5; then
+ AC_CONFIG_SUBDIRS(plugins/kdb/db2/libdb2)
+fi
+
dnl
dnl
dnl Check for thread safety issues.
@@ -891,11 +933,10 @@ AC_SUBST(SUPPORTLIB_MAJOR)
dnl
dnl
if test "$COM_ERR_VERSION" = k5 ; then
-dnl AC_CONFIG_SUBDIRS(util/et)
K5_GEN_MAKEFILE(util/et)
fi
if test "$SS_VERSION" = k5 ; then
- AC_CONFIG_SUBDIRS(util/ss)
+ K5_GEN_MAKEFILE(util/ss)
fi
if test -n "$KRB4_LIB"; then
K5_GEN_MAKEFILE(lib/krb4)
@@ -920,12 +961,19 @@ if test -n "$OPENLDAP_PLUGIN"; then
fi
AC_SUBST(ldap_plugin_dir)
-AC_CONFIG_SUBDIRS(lib/apputils plugins/kdb/db2 plugins/preauth/wpse plugins/preauth/cksum_body plugins/preauth/pkinit appl tests)
+AC_CONFIG_SUBDIRS(plugins/preauth/wpse plugins/preauth/cksum_body)
+AC_CONFIG_SUBDIRS(plugins/preauth/pkinit)
+
+AC_CHECK_HEADERS(Python.h python2.3/Python.h)
+
+dnl
+dnl Kludge for simple server --- FIXME is this the best way to do this?
dnl
-if false; then
- AC_CHECK_HEADERS(Python.h python2.3/Python.h)
- AC_CONFIG_SUBDIRS(plugins/locate/python)
+if test "$ac_cv_lib_socket" = "yes" -a "$ac_cv_lib_nsl" = "yes"; then
+ AC_DEFINE(BROKEN_STREAMS_SOCKETS,1,[Define if socket can't be bound to 0.0.0.0])
fi
+dnl
+AC_CONFIG_SUBDIRS(appl/libpty appl/bsd appl/gssftp appl/telnet)
AC_CONFIG_FILES(krb5-config, [chmod +x krb5-config])
V5_AC_OUTPUT_MAKEFILE(.
@@ -950,9 +998,14 @@ V5_AC_OUTPUT_MAKEFILE(.
lib/kadm5 lib/kadm5/clnt lib/kadm5/srv lib/kadm5/unit-test
+ lib/apputils
+
kdc slave krb524 config-files gen-manpages include
include/kerberosIV
+ plugins/locate/python
+ plugins/kdb/db2
+
clients clients/klist clients/kinit clients/kvno
clients/kdestroy clients/kpasswd clients/ksu
@@ -960,4 +1013,12 @@ V5_AC_OUTPUT_MAKEFILE(.
kadmin/passwd/unit-test kadmin/ktutil kadmin/server
kadmin/testing kadmin/testing/scripts kadmin/testing/util
+ appl
+ appl/sample appl/sample/sclient appl/sample/sserver
+ appl/simple appl/simple/client appl/simple/server
+ appl/gss-sample appl/user_user
+
+ tests tests/resolve tests/asn.1 tests/create tests/hammer
+ tests/verify tests/gssapi tests/dejagnu tests/threads tests/shlib
+ tests/gss-threads tests/misc
)
diff --git a/src/include/k5-int.h b/src/include/k5-int.h
index 2387e11..bdeb540 100644
--- a/src/include/k5-int.h
+++ b/src/include/k5-int.h
@@ -1218,7 +1218,6 @@ struct _krb5_context {
krb5_flags library_options;
krb5_boolean profile_secure;
int fcc_default_format;
- int scc_default_format;
krb5_prompt_type *prompt_types;
/* Message size above which we'll try TCP first in send-to-kdc
type code. Aside from the 2**16 size limit, we put no
diff --git a/src/include/k5-platform.h b/src/include/k5-platform.h
index 876335f..757b122 100644
--- a/src/include/k5-platform.h
+++ b/src/include/k5-platform.h
@@ -39,6 +39,8 @@
#define K5_PLATFORM_H
#include "autoconf.h"
+/* for memcpy */
+#include <string.h>
/* Initialization and finalization function support for libraries.
@@ -655,6 +657,36 @@ load_64_le (const unsigned char *p)
#endif
}
+static inline unsigned short
+load_16_n (const unsigned char *p)
+{
+#ifdef _WIN32
+ unsigned __int16 n;
+#else
+ uint16_t n;
+#endif
+ memcpy(&n, p, 2);
+ return n;
+}
+static inline unsigned int
+load_32_n (const unsigned char *p)
+{
+#ifdef _WIN32
+ unsigned __int32 n;
+#else
+ uint32_t n;
+#endif
+ memcpy(&n, p, 4);
+ return n;
+}
+static inline UINT64_TYPE
+load_64_n (const unsigned char *p)
+{
+ UINT64_TYPE n;
+ memcpy(&n, p, 8);
+ return n;
+}
+
/* Make the interfaces to getpwnam and getpwuid consistent.
Model the wrappers on the POSIX thread-safe versions, but
use the unsafe system versions if the safe ones don't exist
diff --git a/src/include/k5-thread.h b/src/include/k5-thread.h
index 73036c6..21c0688 100644
--- a/src/include/k5-thread.h
+++ b/src/include/k5-thread.h
@@ -1,7 +1,7 @@
/*
* include/k5-thread.h
*
- * Copyright 2004,2005,2006 by the Massachusetts Institute of Technology.
+ * Copyright 2004,2005,2006,2007 by the Massachusetts Institute of Technology.
* All Rights Reserved.
*
* Export of this software from the United States of America may
@@ -271,6 +271,23 @@ void KRB5_CALLCONV krb5int_mutex_report_stats(/* k5_mutex_t *m */);
+/* The mutex structure we use, k5_mutex_t, has some OS-specific bits,
+ and some non-OS-specific bits for debugging and profiling.
+
+ The OS specific bits, in k5_os_mutex, break down into three primary
+ implementations, POSIX threads, Windows threads, and no thread
+ support. However, the POSIX thread version is further subdivided:
+ In one case, we can determine at run time whether the thread
+ library is linked into the application, and use it only if it is
+ present; in the other case, we cannot, and the thread library must
+ be linked in always, but can be used unconditionally. In the
+ former case, the k5_os_mutex structure needs to hold both the POSIX
+ and the non-threaded versions.
+
+ The various k5_os_mutex_* operations are the OS-specific versions,
+ applied to the OS-specific data, and k5_mutex_* uses k5_os_mutex_*
+ to do the OS-specific parts of the work. */
+
/* Define the OS mutex bit. */
/* First, if we're not actually doing multiple threads, do we
diff --git a/src/include/win-mac.h b/src/include/win-mac.h
index 5c08fab..923fe60 100644
--- a/src/include/win-mac.h
+++ b/src/include/win-mac.h
@@ -83,6 +83,9 @@ typedef unsigned __int64 uint64_t;
typedef __int64 int64_t;
#endif
#ifndef SSIZE_T_DEFINED
+#ifdef ssize_t
+#undef ssize_t
+#endif
#ifdef _WIN64
typedef __int64 ssize_t;
#else
diff --git a/src/kadmin/cli/Makefile.in b/src/kadmin/cli/Makefile.in
index 7c9320b..b630240 100644
--- a/src/kadmin/cli/Makefile.in
+++ b/src/kadmin/cli/Makefile.in
@@ -8,7 +8,9 @@ KDB_DEP_LIB=$(DL_LIB) $(THREAD_LINKOPTS)
DEFS=
PROG = kadmin
-OBJS = kadmin.o kadmin_ct.o ss_wrapper.o getdate.o keytab.o
+COMMON_OBJS = kadmin.o kadmin_ct.o ss_wrapper.o getdate.o
+KADMIN_OBJS = $(COMMON_OBJS) keytab.o
+LOCAL_OBJS = $(COMMON_OBJS) keytab_local.o
SRCS = kadmin.c kadmin_ct.c ss_wrapper.c getdate.c keytab.c
@@ -16,11 +18,11 @@ LOCALINCLUDES=-I$(srcdir)
all:: $(PROG).local $(PROG)
-$(PROG).local: $(OBJS) $(SS_DEPLIB) $(KADMSRV_DEPLIBS) $(KRB5_BASE_DEPLIBS)
- $(CC_LINK) -o $(PROG).local $(OBJS) $(SS_LIB) $(KADMSRV_LIBS) $(KDB_DEP_LIB) $(KRB5_BASE_LIBS)
+$(PROG).local: $(LOCAL_OBJS) $(SS_DEPLIB) $(KADMSRV_DEPLIBS) $(KRB5_BASE_DEPLIBS)
+ $(CC_LINK) -o $(PROG).local $(LOCAL_OBJS) $(SS_LIB) $(KADMSRV_LIBS) $(KDB_DEP_LIB) $(KRB5_BASE_LIBS)
-$(PROG): $(OBJS) $(SS_DEPLIB) $(KADMCLNT_DEPLIBS) $(KRB5_BASE_DEPLIBS)
- $(CC_LINK) -o $(PROG) $(OBJS) $(SS_LIB) $(KADMCLNT_LIBS) $(KRB5_BASE_LIBS)
+$(PROG): $(KADMIN_OBJS) $(SS_DEPLIB) $(KADMCLNT_DEPLIBS) $(KRB5_BASE_DEPLIBS)
+ $(CC_LINK) -o $(PROG) $(KADMIN_OBJS) $(SS_LIB) $(KADMCLNT_LIBS) $(KRB5_BASE_LIBS)
kadmin_ct.o: kadmin_ct.c
diff --git a/src/kadmin/cli/k5srvutil.sh b/src/kadmin/cli/k5srvutil.sh
index 70b1b85..e1284e6 100755
--- a/src/kadmin/cli/k5srvutil.sh
+++ b/src/kadmin/cli/k5srvutil.sh
@@ -4,7 +4,7 @@
# returns a list of principals in the keytab
# sorted and uniquified
list_princs() {
- klist -k $keytab | tail +4 | awk '{print $2}' | sort | uniq
+ klist -k $keytab | awk '(NR > 3) {print $2}' | sort | uniq
}
set_command() {
diff --git a/src/kadmin/cli/kadmin.M b/src/kadmin/cli/kadmin.M
index 20958e8..7739bbb 100644
--- a/src/kadmin/cli/kadmin.M
+++ b/src/kadmin/cli/kadmin.M
@@ -749,11 +749,29 @@ kadmin:
.TP
\fBktadd\fP [\fB\-k\fP \fIkeytab\fP] [\fB\-q\fP] [\fB\-e\fP \fIkeysaltlist\fP]
.br
-[\fIprincipal\fP | \fB\-glob\fP \fIprinc-exp\fP] [\fI...\fP]
+[\fB\-norandkey\fP] [[\fIprincipal\fP | \fB\-glob\fP \fIprinc-exp\fP] [\fI...\fP]
.br
Adds a principal or all principals matching
.I princ-exp
-to a keytab, randomizing each principal's key in the process. Requires the
+to a keytab.
+It randomizes each principal's key in the process, to prevent a
+compromised admin account from reading out all of the keys from the
+database. However,
+.B kadmin.local
+has the
+.B \-norandkey
+option, which leaves the keys and their version numbers unchanged,
+similar to the Kerberos V4
+.B ext_srvtab
+command.
+That allows users to continue to use the passwords they know
+to login normally, while simultaneously allowing scripts
+to login to the same account using a keytab.
+There is no significant security risk added since
+.B kadmin.local
+must be run by root on the KDC anyway.
+.sp
+Requires the
.I inquire
and
.I changepw
diff --git a/src/kadmin/cli/keytab.c b/src/kadmin/cli/keytab.c
index d0fca77..297b799 100644
--- a/src/kadmin/cli/keytab.c
+++ b/src/kadmin/cli/keytab.c
@@ -55,9 +55,17 @@ static char *etype_string(krb5_enctype enctype);
static int quiet;
+#ifdef KADMIN_LOCAL
+static int norandkey;
+#endif
+
static void add_usage()
{
+#ifdef KADMIN_LOCAL
+ fprintf(stderr, "Usage: ktadd [-k[eytab] keytab] [-q] [-e keysaltlist] [-norandkey] [principal | -glob princ-exp] [...]\n");
+#else
fprintf(stderr, "Usage: ktadd [-k[eytab] keytab] [-q] [-e keysaltlist] [principal | -glob princ-exp] [...]\n");
+#endif
}
static void rem_usage()
@@ -126,6 +134,9 @@ void kadmin_keytab_add(int argc, char **argv)
argc--; argv++;
quiet = 0;
+#ifdef KADMIN_LOCAL
+ norandkey = 0;
+#endif
while (argc) {
if (strncmp(*argv, "-k", 2) == 0) {
argc--; argv++;
@@ -136,6 +147,10 @@ void kadmin_keytab_add(int argc, char **argv)
keytab_str = *argv;
} else if (strcmp(*argv, "-q") == 0) {
quiet++;
+#ifdef KADMIN_LOCAL
+ } else if (strcmp(*argv, "-norandkey") == 0) {
+ norandkey++;
+#endif
} else if (strcmp(*argv, "-e") == 0) {
argc--;
if (argc < 1) {
@@ -160,6 +175,13 @@ void kadmin_keytab_add(int argc, char **argv)
return;
}
+#ifdef KADMIN_LOCAL
+ if (norandkey && ks_tuple) {
+ fprintf(stderr, "cannot specify keysaltlist when not changing key\n");
+ return;
+ }
+#endif
+
if (process_keytab(context, &keytab_str, &keytab))
return;
@@ -261,6 +283,11 @@ int add_principal(void *lhandle, char *keytab_str, krb5_keytab keytab,
goto cleanup;
}
+#ifdef KADMIN_LOCAL
+ if (norandkey)
+ code = kadm5_get_principal_keys(handle, princ, &keys, &nkeys);
+ else
+#endif
if (keepold || ks_tuple != NULL) {
code = kadm5_randkey_principal_3(lhandle, princ,
keepold, n_ks_tuple, ks_tuple,
diff --git a/src/kadmin/cli/keytab_local.c b/src/kadmin/cli/keytab_local.c
new file mode 100644
index 0000000..1f029a7
--- /dev/null
+++ b/src/kadmin/cli/keytab_local.c
@@ -0,0 +1,9 @@
+/*
+ * A wrapper around keytab.c used by kadmin.local to expose the -norandkey
+ * flag. This avoids building two object files from the same source file,
+ * which is otherwise tricky with compilers that don't support -c and -o
+ * at the same time.
+ */
+
+#define KADMIN_LOCAL
+#include "keytab.c"
diff --git a/src/kadmin/dbutil/Makefile.in b/src/kadmin/dbutil/Makefile.in
index b16c179..77a0ef7 100644
--- a/src/kadmin/dbutil/Makefile.in
+++ b/src/kadmin/dbutil/Makefile.in
@@ -78,15 +78,16 @@ $(OUTPRE)kadm5_create.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
$(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \
$(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/krb5/krb5.h \
$(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
- $(COM_ERR_DEPS) $(SRCTOP)/include/adm_proto.h $(SRCTOP)/include/gssrpc/auth.h \
- $(SRCTOP)/include/gssrpc/auth_gss.h $(SRCTOP)/include/gssrpc/auth_unix.h \
- $(SRCTOP)/include/gssrpc/clnt.h $(SRCTOP)/include/gssrpc/rename.h \
- $(SRCTOP)/include/gssrpc/rpc.h $(SRCTOP)/include/gssrpc/rpc_msg.h \
- $(SRCTOP)/include/gssrpc/svc.h $(SRCTOP)/include/gssrpc/svc_auth.h \
- $(SRCTOP)/include/gssrpc/xdr.h $(SRCTOP)/include/k5-err.h \
- $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
- $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
- $(SRCTOP)/include/kdb.h $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+ $(COM_ERR_DEPS) $(SRCTOP)/include/adm_proto.h $(SRCTOP)/include/fake-addrinfo.h \
+ $(SRCTOP)/include/gssrpc/auth.h $(SRCTOP)/include/gssrpc/auth_gss.h \
+ $(SRCTOP)/include/gssrpc/auth_unix.h $(SRCTOP)/include/gssrpc/clnt.h \
+ $(SRCTOP)/include/gssrpc/rename.h $(SRCTOP)/include/gssrpc/rpc.h \
+ $(SRCTOP)/include/gssrpc/rpc_msg.h $(SRCTOP)/include/gssrpc/svc.h \
+ $(SRCTOP)/include/gssrpc/svc_auth.h $(SRCTOP)/include/gssrpc/xdr.h \
+ $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int.h \
+ $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+ $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+ $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
$(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
$(SRCTOP)/include/socket-utils.h kadm5_create.c kdb5_util.h \
string_table.h
diff --git a/src/kadmin/dbutil/kadm5_create.c b/src/kadmin/dbutil/kadm5_create.c
index 878300a..ff0d294 100644
--- a/src/kadmin/dbutil/kadm5_create.c
+++ b/src/kadmin/dbutil/kadm5_create.c
@@ -40,6 +40,8 @@
#include <kadm5/admin.h>
#include <adm_proto.h>
+#include "fake-addrinfo.h"
+
#include <krb5.h>
#include <kdb.h>
@@ -172,20 +174,33 @@ static int add_admin_princs(void *handle, krb5_context context, char *realm)
krb5_error_code ret = 0;
char service_name[MAXHOSTNAMELEN + 8];
char localname[MAXHOSTNAMELEN];
- struct hostent *hp;
+ struct addrinfo *ai, ai_hints;
+ int gai_error;
if (gethostname(localname, MAXHOSTNAMELEN)) {
ret = errno;
perror("gethostname");
goto clean_and_exit;
}
- hp = gethostbyname(localname);
- if (hp == NULL) {
- ret = errno;
- perror("gethostbyname");
+ memset(&ai_hints, 0, sizeof(ai_hints));
+ ai_hints.ai_flags = AI_CANONNAME;
+ gai_error = getaddrinfo(localname, (char *)NULL, &ai_hints, &ai);
+ if (gai_error) {
+ ret = EINVAL;
+ fprintf(stderr, "getaddrinfo(%s): %s\n", localname,
+ gai_strerror(gai_error));
+ goto clean_and_exit;
+ }
+ if (ai->ai_canonname == NULL) {
+ ret = EINVAL;
+ fprintf(stderr,
+ "getaddrinfo(%s): Cannot determine canonical hostname.\n",
+ localname);
+ freeaddrinfo(ai);
goto clean_and_exit;
}
- sprintf(service_name, "kadmin/%s", hp->h_name);
+ sprintf(service_name, "kadmin/%s", ai->ai_canonname);
+ freeaddrinfo(ai);
if ((ret = add_admin_princ(handle, context,
service_name, realm,
diff --git a/src/kadmin/server/kadm_rpc_svc.c b/src/kadmin/server/kadm_rpc_svc.c
index 978ca3c..cd1f0d2 100644
--- a/src/kadmin/server/kadm_rpc_svc.c
+++ b/src/kadmin/server/kadm_rpc_svc.c
@@ -250,6 +250,8 @@ check_rpcsec_auth(struct svc_req *rqstp)
krb5_data *c1, *c2, *realm;
gss_buffer_desc gss_str;
kadm5_server_handle_t handle;
+ size_t slen;
+ char *sdots;
success = 0;
handle = (kadm5_server_handle_t)global_server_handle;
@@ -274,6 +276,8 @@ check_rpcsec_auth(struct svc_req *rqstp)
if (ret == 0)
goto fail_name;
+ slen = gss_str.length;
+ trunc_name(&slen, &sdots);
/*
* Since we accept with GSS_C_NO_NAME, the client can authenticate
* against the entire kdb. Therefore, ensure that the service
@@ -296,8 +300,8 @@ check_rpcsec_auth(struct svc_req *rqstp)
fail_princ:
if (!success) {
- krb5_klog_syslog(LOG_ERR, "bad service principal %.*s",
- gss_str.length, gss_str.value);
+ krb5_klog_syslog(LOG_ERR, "bad service principal %.*s%s",
+ slen, gss_str.value, sdots);
}
gss_release_buffer(&min_stat, &gss_str);
krb5_free_principal(kctx, princ);
diff --git a/src/kadmin/server/misc.c b/src/kadmin/server/misc.c
index fa4ca91..ed51100 100644
--- a/src/kadmin/server/misc.c
+++ b/src/kadmin/server/misc.c
@@ -171,3 +171,12 @@ check_min_life(void *server_handle, krb5_principal principal,
return kadm5_free_principal_ent(handle->lhandle, &princ);
}
+
+#define MAXPRINCLEN 125
+
+void
+trunc_name(size_t *len, char **dots)
+{
+ *dots = *len > MAXPRINCLEN ? "..." : "";
+ *len = *len > MAXPRINCLEN ? MAXPRINCLEN : *len;
+}
diff --git a/src/kadmin/server/misc.h b/src/kadmin/server/misc.h
index b519ba0..a020874 100644
--- a/src/kadmin/server/misc.h
+++ b/src/kadmin/server/misc.h
@@ -45,3 +45,5 @@ krb5_error_code process_chpw_request(krb5_context context,
#ifdef SVC_GETARGS
void kadm_1(struct svc_req *, SVCXPRT *);
#endif
+
+void trunc_name(size_t *len, char **dots);
diff --git a/src/kadmin/server/ovsec_kadmd.c b/src/kadmin/server/ovsec_kadmd.c
index afae95a..a3ce421 100644
--- a/src/kadmin/server/ovsec_kadmd.c
+++ b/src/kadmin/server/ovsec_kadmd.c
@@ -992,6 +992,8 @@ void log_badverf(gss_name_t client_name, gss_name_t server_name,
rpcproc_t proc;
int i;
const char *procname;
+ size_t clen, slen;
+ char *cdots, *sdots;
client.length = 0;
client.value = NULL;
@@ -1000,10 +1002,20 @@ void log_badverf(gss_name_t client_name, gss_name_t server_name,
(void) gss_display_name(&minor, client_name, &client, &gss_type);
(void) gss_display_name(&minor, server_name, &server, &gss_type);
- if (client.value == NULL)
+ if (client.value == NULL) {
client.value = "(null)";
- if (server.value == NULL)
+ clen = sizeof("(null)") -1;
+ } else {
+ clen = client.length;
+ }
+ trunc_name(&clen, &cdots);
+ if (server.value == NULL) {
server.value = "(null)";
+ slen = sizeof("(null)") - 1;
+ } else {
+ slen = server.length;
+ }
+ trunc_name(&slen, &sdots);
a = inet_ntoa(rqst->rq_xprt->xp_raddr.sin_addr);
proc = msg->rm_call.cb_proc;
@@ -1016,14 +1028,14 @@ void log_badverf(gss_name_t client_name, gss_name_t server_name,
}
if (procname != NULL)
krb5_klog_syslog(LOG_NOTICE, "WARNING! Forged/garbled request: %s, "
- "claimed client = %s, server = %s, addr = %s",
- procname, client.value,
- server.value, a);
+ "claimed client = %.*s%s, server = %.*s%s, addr = %s",
+ procname, clen, client.value, cdots,
+ slen, server.value, sdots, a);
else
krb5_klog_syslog(LOG_NOTICE, "WARNING! Forged/garbled request: %d, "
- "claimed client = %s, server = %s, addr = %s",
- proc, client.value,
- server.value, a);
+ "claimed client = %.*s%s, server = %.*s%s, addr = %s",
+ proc, clen, client.value, cdots,
+ slen, server.value, sdots, a);
(void) gss_release_buffer(&minor, &client);
(void) gss_release_buffer(&minor, &server);
diff --git a/src/kadmin/server/schpw.c b/src/kadmin/server/schpw.c
index b30c2d5..e974beb 100644
--- a/src/kadmin/server/schpw.c
+++ b/src/kadmin/server/schpw.c
@@ -40,6 +40,8 @@ process_chpw_request(context, server_handle, realm, s, keytab, sockin,
int numresult;
char strresult[1024];
char *clientstr;
+ size_t clen;
+ char *cdots;
ret = 0;
rep->length = 0;
@@ -258,9 +260,12 @@ process_chpw_request(context, server_handle, realm, s, keytab, sockin,
free(ptr);
clear.length = 0;
- krb5_klog_syslog(LOG_NOTICE, "chpw request from %s for %s: %s",
+ clen = strlen(clientstr);
+ trunc_name(&clen, &cdots);
+ krb5_klog_syslog(LOG_NOTICE, "chpw request from %s for %.*s%s: %s",
inet_ntoa(((struct sockaddr_in *)&remote_addr)->sin_addr),
- clientstr, ret ? krb5_get_error_message (context, ret) : "success");
+ clen, clientstr, cdots,
+ ret ? krb5_get_error_message (context, ret) : "success");
krb5_free_unparsed_name(context, clientstr);
if (ret) {
diff --git a/src/kadmin/server/server_stubs.c b/src/kadmin/server/server_stubs.c
index ee5d653c..cf82398 100644
--- a/src/kadmin/server/server_stubs.c
+++ b/src/kadmin/server/server_stubs.c
@@ -14,6 +14,7 @@
#include <arpa/inet.h> /* inet_ntoa */
#include <adm_proto.h> /* krb5_klog_syslog */
#include "misc.h"
+#include <string.h>
#define LOG_UNAUTH "Unauthorized request: %s, %s, client=%s, service=%s, addr=%s"
#define LOG_DONE "Request: %s, %s, %s, client=%s, service=%s, addr=%s"
@@ -237,6 +238,61 @@ gss_name_to_string(gss_name_t gss_name, gss_buffer_desc *str)
return 0;
}
+static int
+log_unauth(
+ char *op,
+ char *target,
+ gss_buffer_t client,
+ gss_buffer_t server,
+ struct svc_req *rqstp)
+{
+ size_t tlen, clen, slen;
+ char *tdots, *cdots, *sdots;
+
+ tlen = strlen(target);
+ trunc_name(&tlen, &tdots);
+ clen = client->length;
+ trunc_name(&clen, &cdots);
+ slen = server->length;
+ trunc_name(&slen, &sdots);
+
+ return krb5_klog_syslog(LOG_NOTICE,
+ "Unauthorized request: %s, %.*s%s, "
+ "client=%.*s%s, service=%.*s%s, addr=%s",
+ op, tlen, target, tdots,
+ clen, client->value, cdots,
+ slen, server->value, sdots,
+ inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr));
+}
+
+static int
+log_done(
+ char *op,
+ char *target,
+ char *errmsg,
+ gss_buffer_t client,
+ gss_buffer_t server,
+ struct svc_req *rqstp)
+{
+ size_t tlen, clen, slen;
+ char *tdots, *cdots, *sdots;
+
+ tlen = strlen(target);
+ trunc_name(&tlen, &tdots);
+ clen = client->length;
+ trunc_name(&clen, &cdots);
+ slen = server->length;
+ trunc_name(&slen, &sdots);
+
+ return krb5_klog_syslog(LOG_NOTICE,
+ "Request: %s, %.*s%s, %s, "
+ "client=%.*s%s, service=%.*s%s, addr=%s",
+ op, tlen, target, tdots, errmsg,
+ clen, client->value, cdots,
+ slen, server->value, sdots,
+ inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr));
+}
+
generic_ret *
create_principal_2_svc(cprinc_arg *arg, struct svc_req *rqstp)
{
@@ -275,9 +331,8 @@ create_principal_2_svc(cprinc_arg *arg, struct svc_req *rqstp)
|| kadm5int_acl_impose_restrictions(handle->context,
&arg->rec, &arg->mask, rp)) {
ret.code = KADM5_AUTH_ADD;
- krb5_klog_syslog(LOG_NOTICE, LOG_UNAUTH, "kadm5_create_principal",
- prime_arg, client_name.value, service_name.value,
- inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr));
+ log_unauth("kadm5_create_principal", prime_arg,
+ &client_name, &service_name, rqstp);
} else {
ret.code = kadm5_create_principal((void *)handle,
&arg->rec, arg->mask,
@@ -287,10 +342,8 @@ create_principal_2_svc(cprinc_arg *arg, struct svc_req *rqstp)
else
errmsg = krb5_get_error_message(handle ? handle->context : NULL, ret.code);
- krb5_klog_syslog(LOG_NOTICE, LOG_DONE, "kadm5_create_principal",
- prime_arg, errmsg,
- client_name.value, service_name.value,
- inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr));
+ log_done("kadm5_create_principal", prime_arg, errmsg,
+ &client_name, &service_name, rqstp);
/* no need to check for NULL. Even if it is NULL, atleast error_code will be returned */
}
@@ -341,9 +394,8 @@ create_principal3_2_svc(cprinc3_arg *arg, struct svc_req *rqstp)
|| kadm5int_acl_impose_restrictions(handle->context,
&arg->rec, &arg->mask, rp)) {
ret.code = KADM5_AUTH_ADD;
- krb5_klog_syslog(LOG_NOTICE, LOG_UNAUTH, "kadm5_create_principal",
- prime_arg, client_name.value, service_name.value,
- inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr));
+ log_unauth("kadm5_create_principal", prime_arg,
+ &client_name, &service_name, rqstp);
} else {
ret.code = kadm5_create_principal_3((void *)handle,
&arg->rec, arg->mask,
@@ -355,10 +407,8 @@ create_principal3_2_svc(cprinc3_arg *arg, struct svc_req *rqstp)
else
errmsg = krb5_get_error_message(handle ? handle->context : NULL, ret.code);
- krb5_klog_syslog(LOG_NOTICE, LOG_DONE, "kadm5_create_principal",
- prime_arg, errmsg,
- client_name.value, service_name.value,
- inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr));
+ log_done("kadm5_create_principal", prime_arg, errmsg,
+ &client_name, &service_name, rqstp);
/* no need to check for NULL. Even if it is NULL, atleast error_code will be returned */
}
@@ -406,9 +456,8 @@ delete_principal_2_svc(dprinc_arg *arg, struct svc_req *rqstp)
|| !kadm5int_acl_check(handle->context, rqst2name(rqstp), ACL_DELETE,
arg->princ, NULL)) {
ret.code = KADM5_AUTH_DELETE;
- krb5_klog_syslog(LOG_NOTICE, LOG_UNAUTH, "kadm5_delete_principal",
- prime_arg, client_name.value, service_name.value,
- inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr));
+ log_unauth("kadm5_delete_principal", prime_arg,
+ &client_name, &service_name, rqstp);
} else {
ret.code = kadm5_delete_principal((void *)handle, arg->princ);
if( ret.code == 0 )
@@ -416,10 +465,8 @@ delete_principal_2_svc(dprinc_arg *arg, struct svc_req *rqstp)
else
errmsg = krb5_get_error_message(handle ? handle->context : NULL, ret.code);
- krb5_klog_syslog(LOG_NOTICE, LOG_DONE, "kadm5_delete_principal",
- prime_arg, errmsg,
- client_name.value, service_name.value,
- inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr));
+ log_done("kadm5_delete_principal", prime_arg, errmsg,
+ &client_name, &service_name, rqstp);
/* no need to check for NULL. Even if it is NULL, atleast error_code will be returned */
}
@@ -469,9 +516,8 @@ modify_principal_2_svc(mprinc_arg *arg, struct svc_req *rqstp)
|| kadm5int_acl_impose_restrictions(handle->context,
&arg->rec, &arg->mask, rp)) {
ret.code = KADM5_AUTH_MODIFY;
- krb5_klog_syslog(LOG_NOTICE, LOG_UNAUTH, "kadm5_modify_principal",
- prime_arg, client_name.value, service_name.value,
- inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr));
+ log_unauth("kadm5_modify_principal", prime_arg,
+ &client_name, &service_name, rqstp);
} else {
ret.code = kadm5_modify_principal((void *)handle, &arg->rec,
arg->mask);
@@ -480,10 +526,8 @@ modify_principal_2_svc(mprinc_arg *arg, struct svc_req *rqstp)
else
errmsg = krb5_get_error_message(handle ? handle->context : NULL, ret.code);
- krb5_klog_syslog(LOG_NOTICE, LOG_DONE, "kadm5_modify_principal",
- prime_arg, errmsg,
- client_name.value, service_name.value,
- inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr));
+ log_done("kadm5_modify_principal", prime_arg, errmsg,
+ &client_name, &service_name, rqstp);
/* no need to check for NULL. Even if it is NULL, atleast error_code will be returned */
}
@@ -546,9 +590,8 @@ rename_principal_2_svc(rprinc_arg *arg, struct svc_req *rqstp)
} else
ret.code = KADM5_AUTH_INSUFFICIENT;
if (ret.code != KADM5_OK) {
- krb5_klog_syslog(LOG_NOTICE, LOG_UNAUTH, "kadm5_rename_principal",
- prime_arg, client_name.value, service_name.value,
- inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr));
+ log_unauth("kadm5_rename_principal", prime_arg,
+ &client_name, &service_name, rqstp);
} else {
ret.code = kadm5_rename_principal((void *)handle, arg->src,
arg->dest);
@@ -557,10 +600,8 @@ rename_principal_2_svc(rprinc_arg *arg, struct svc_req *rqstp)
else
errmsg = krb5_get_error_message(handle ? handle->context : NULL, ret.code);
- krb5_klog_syslog(LOG_NOTICE, LOG_DONE, "kadm5_rename_principal",
- prime_arg, errmsg,
- client_name.value, service_name.value,
- inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr));
+ log_done("kadm5_rename_principal", prime_arg, errmsg,
+ &client_name, &service_name, rqstp);
}
free_server_handle(handle);
free(prime_arg1);
@@ -614,9 +655,8 @@ get_principal_2_svc(gprinc_arg *arg, struct svc_req *rqstp)
arg->princ,
NULL))) {
ret.code = KADM5_AUTH_GET;
- krb5_klog_syslog(LOG_NOTICE, LOG_UNAUTH, funcname,
- prime_arg, client_name.value, service_name.value,
- inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr));
+ log_unauth(funcname, prime_arg,
+ &client_name, &service_name, rqstp);
} else {
if (handle->api_version == KADM5_API_VERSION_1) {
ret.code = kadm5_get_principal_v1((void *)handle,
@@ -636,11 +676,8 @@ get_principal_2_svc(gprinc_arg *arg, struct svc_req *rqstp)
else
errmsg = krb5_get_error_message(handle ? handle->context : NULL, ret.code);
- krb5_klog_syslog(LOG_NOTICE, LOG_DONE, funcname,
- prime_arg,
- errmsg,
- client_name.value, service_name.value,
- inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr));
+ log_done(funcname, prime_arg, errmsg,
+ &client_name, &service_name, rqstp);
}
free_server_handle(handle);
@@ -688,9 +725,8 @@ get_princs_2_svc(gprincs_arg *arg, struct svc_req *rqstp)
NULL,
NULL)) {
ret.code = KADM5_AUTH_LIST;
- krb5_klog_syslog(LOG_NOTICE, LOG_UNAUTH, "kadm5_get_principals",
- prime_arg, client_name.value, service_name.value,
- inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr));
+ log_unauth("kadm5_get_principals", prime_arg,
+ &client_name, &service_name, rqstp);
} else {
ret.code = kadm5_get_principals((void *)handle,
arg->exp, &ret.princs,
@@ -700,11 +736,8 @@ get_princs_2_svc(gprincs_arg *arg, struct svc_req *rqstp)
else
errmsg = krb5_get_error_message(handle ? handle->context : NULL, ret.code);
- krb5_klog_syslog(LOG_NOTICE, LOG_DONE, "kadm5_get_principals",
- prime_arg,
- errmsg,
- client_name.value, service_name.value,
- inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr));
+ log_done("kadm5_get_principals", prime_arg, errmsg,
+ &client_name, &service_name, rqstp);
}
free_server_handle(handle);
@@ -755,9 +788,8 @@ chpass_principal_2_svc(chpass_arg *arg, struct svc_req *rqstp)
ret.code = kadm5_chpass_principal((void *)handle, arg->princ,
arg->pass);
} else {
- krb5_klog_syslog(LOG_NOTICE, LOG_UNAUTH, "kadm5_chpass_principal",
- prime_arg, client_name.value, service_name.value,
- inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr));
+ log_unauth("kadm5_chpass_principal", prime_arg,
+ &client_name, &service_name, rqstp);
ret.code = KADM5_AUTH_CHANGEPW;
}
@@ -767,10 +799,8 @@ chpass_principal_2_svc(chpass_arg *arg, struct svc_req *rqstp)
else
errmsg = krb5_get_error_message(handle ? handle->context : NULL, ret.code);
- krb5_klog_syslog(LOG_NOTICE, LOG_DONE, "kadm5_chpass_principal",
- prime_arg, errmsg,
- client_name.value, service_name.value,
- inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr));
+ log_done("kadm5_chpass_principal", prime_arg, errmsg,
+ &client_name, &service_name, rqstp);
}
free_server_handle(handle);
@@ -828,9 +858,8 @@ chpass_principal3_2_svc(chpass3_arg *arg, struct svc_req *rqstp)
arg->ks_tuple,
arg->pass);
} else {
- krb5_klog_syslog(LOG_NOTICE, LOG_UNAUTH, "kadm5_chpass_principal",
- prime_arg, client_name.value, service_name.value,
- inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr));
+ log_unauth("kadm5_chpass_principal", prime_arg,
+ &client_name, &service_name, rqstp);
ret.code = KADM5_AUTH_CHANGEPW;
}
@@ -840,10 +869,8 @@ chpass_principal3_2_svc(chpass3_arg *arg, struct svc_req *rqstp)
else
errmsg = krb5_get_error_message(handle ? handle->context : NULL, ret.code);
- krb5_klog_syslog(LOG_NOTICE, LOG_DONE, "kadm5_chpass_principal",
- prime_arg, errmsg,
- client_name.value, service_name.value,
- inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr));
+ log_done("kadm5_chpass_principal", prime_arg, errmsg,
+ &client_name, &service_name, rqstp);
}
free_server_handle(handle);
@@ -892,9 +919,8 @@ setv4key_principal_2_svc(setv4key_arg *arg, struct svc_req *rqstp)
ret.code = kadm5_setv4key_principal((void *)handle, arg->princ,
arg->keyblock);
} else {
- krb5_klog_syslog(LOG_NOTICE, LOG_UNAUTH, "kadm5_setv4key_principal",
- prime_arg, client_name.value, service_name.value,
- inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr));
+ log_unauth("kadm5_setv4key_principal", prime_arg,
+ &client_name, &service_name, rqstp);
ret.code = KADM5_AUTH_SETKEY;
}
@@ -904,10 +930,8 @@ setv4key_principal_2_svc(setv4key_arg *arg, struct svc_req *rqstp)
else
errmsg = krb5_get_error_message(handle ? handle->context : NULL, ret.code);
- krb5_klog_syslog(LOG_NOTICE, LOG_DONE, "kadm5_setv4key_principal",
- prime_arg, errmsg,
- client_name.value, service_name.value,
- inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr));
+ log_done("kadm5_setv4key_principal", prime_arg, errmsg,
+ &client_name, &service_name, rqstp);
}
free_server_handle(handle);
@@ -956,9 +980,8 @@ setkey_principal_2_svc(setkey_arg *arg, struct svc_req *rqstp)
ret.code = kadm5_setkey_principal((void *)handle, arg->princ,
arg->keyblocks, arg->n_keys);
} else {
- krb5_klog_syslog(LOG_NOTICE, LOG_UNAUTH, "kadm5_setkey_principal",
- prime_arg, client_name.value, service_name.value,
- inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr));
+ log_unauth("kadm5_setkey_principal", prime_arg,
+ &client_name, &service_name, rqstp);
ret.code = KADM5_AUTH_SETKEY;
}
@@ -968,10 +991,8 @@ setkey_principal_2_svc(setkey_arg *arg, struct svc_req *rqstp)
else
errmsg = krb5_get_error_message(handle ? handle->context : NULL, ret.code);
- krb5_klog_syslog(LOG_NOTICE, LOG_DONE, "kadm5_setkey_principal",
- prime_arg, errmsg,
- client_name.value, service_name.value,
- inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr));
+ log_done("kadm5_setkey_principal", prime_arg, errmsg,
+ &client_name, &service_name, rqstp);
}
free_server_handle(handle);
@@ -1023,9 +1044,8 @@ setkey_principal3_2_svc(setkey3_arg *arg, struct svc_req *rqstp)
arg->ks_tuple,
arg->keyblocks, arg->n_keys);
} else {
- krb5_klog_syslog(LOG_NOTICE, LOG_UNAUTH, "kadm5_setkey_principal",
- prime_arg, client_name.value, service_name.value,
- inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr));
+ log_unauth("kadm5_setkey_principal", prime_arg,
+ &client_name, &service_name, rqstp);
ret.code = KADM5_AUTH_SETKEY;
}
@@ -1035,10 +1055,8 @@ setkey_principal3_2_svc(setkey3_arg *arg, struct svc_req *rqstp)
else
errmsg = krb5_get_error_message(handle ? handle->context : NULL, ret.code);
- krb5_klog_syslog(LOG_NOTICE, LOG_DONE, "kadm5_setkey_principal",
- prime_arg, errmsg,
- client_name.value, service_name.value,
- inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr));
+ log_done("kadm5_setkey_principal", prime_arg, errmsg,
+ &client_name, &service_name, rqstp);
}
free_server_handle(handle);
@@ -1097,9 +1115,8 @@ chrand_principal_2_svc(chrand_arg *arg, struct svc_req *rqstp)
ret.code = kadm5_randkey_principal((void *)handle, arg->princ,
&k, &nkeys);
} else {
- krb5_klog_syslog(LOG_NOTICE, LOG_UNAUTH, funcname,
- prime_arg, client_name.value, service_name.value,
- inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr));
+ log_unauth(funcname, prime_arg,
+ &client_name, &service_name, rqstp);
ret.code = KADM5_AUTH_CHANGEPW;
}
@@ -1119,10 +1136,8 @@ chrand_principal_2_svc(chrand_arg *arg, struct svc_req *rqstp)
else
errmsg = krb5_get_error_message(handle ? handle->context : NULL, ret.code);
- krb5_klog_syslog(LOG_NOTICE, LOG_DONE, funcname,
- prime_arg, errmsg,
- client_name.value, service_name.value,
- inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr));
+ log_done(funcname, prime_arg, errmsg,
+ &client_name, &service_name, rqstp);
}
free_server_handle(handle);
free(prime_arg);
@@ -1185,9 +1200,8 @@ chrand_principal3_2_svc(chrand3_arg *arg, struct svc_req *rqstp)
arg->ks_tuple,
&k, &nkeys);
} else {
- krb5_klog_syslog(LOG_NOTICE, LOG_UNAUTH, funcname,
- prime_arg, client_name.value, service_name.value,
- inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr));
+ log_unauth(funcname, prime_arg,
+ &client_name, &service_name, rqstp);
ret.code = KADM5_AUTH_CHANGEPW;
}
@@ -1207,10 +1221,8 @@ chrand_principal3_2_svc(chrand3_arg *arg, struct svc_req *rqstp)
else
errmsg = krb5_get_error_message(handle ? handle->context : NULL, ret.code);
- krb5_klog_syslog(LOG_NOTICE, LOG_DONE, funcname,
- prime_arg, errmsg,
- client_name.value, service_name.value,
- inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr));
+ log_done(funcname, prime_arg, errmsg,
+ &client_name, &service_name, rqstp);
}
free_server_handle(handle);
free(prime_arg);
@@ -1253,10 +1265,9 @@ create_policy_2_svc(cpol_arg *arg, struct svc_req *rqstp)
rqst2name(rqstp),
ACL_ADD, NULL, NULL)) {
ret.code = KADM5_AUTH_ADD;
- krb5_klog_syslog(LOG_NOTICE, LOG_UNAUTH, "kadm5_create_policy",
- prime_arg, client_name.value, service_name.value,
- inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr));
-
+ log_unauth("kadm5_create_policy", prime_arg,
+ &client_name, &service_name, rqstp);
+
} else {
ret.code = kadm5_create_policy((void *)handle, &arg->rec,
arg->mask);
@@ -1265,11 +1276,9 @@ create_policy_2_svc(cpol_arg *arg, struct svc_req *rqstp)
else
errmsg = krb5_get_error_message(handle ? handle->context : NULL, ret.code);
- krb5_klog_syslog(LOG_NOTICE, LOG_DONE, "kadm5_create_policy",
- ((prime_arg == NULL) ? "(null)" : prime_arg),
- errmsg,
- client_name.value, service_name.value,
- inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr));
+ log_done("kadm5_create_policy",
+ ((prime_arg == NULL) ? "(null)" : prime_arg), errmsg,
+ &client_name, &service_name, rqstp);
}
free_server_handle(handle);
gss_release_buffer(&minor_stat, &client_name);
@@ -1310,9 +1319,8 @@ delete_policy_2_svc(dpol_arg *arg, struct svc_req *rqstp)
if (CHANGEPW_SERVICE(rqstp) || !kadm5int_acl_check(handle->context,
rqst2name(rqstp),
ACL_DELETE, NULL, NULL)) {
- krb5_klog_syslog(LOG_NOTICE, LOG_UNAUTH, "kadm5_delete_policy",
- prime_arg, client_name.value, service_name.value,
- inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr));
+ log_unauth("kadm5_delete_policy", prime_arg,
+ &client_name, &service_name, rqstp);
ret.code = KADM5_AUTH_DELETE;
} else {
ret.code = kadm5_delete_policy((void *)handle, arg->name);
@@ -1321,11 +1329,9 @@ delete_policy_2_svc(dpol_arg *arg, struct svc_req *rqstp)
else
errmsg = krb5_get_error_message(handle ? handle->context : NULL, ret.code);
- krb5_klog_syslog(LOG_NOTICE, LOG_DONE, "kadm5_delete_policy",
- ((prime_arg == NULL) ? "(null)" : prime_arg),
- errmsg,
- client_name.value, service_name.value,
- inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr));
+ log_done("kadm5_delete_policy",
+ ((prime_arg == NULL) ? "(null)" : prime_arg), errmsg,
+ &client_name, &service_name, rqstp);
}
free_server_handle(handle);
gss_release_buffer(&minor_stat, &client_name);
@@ -1366,9 +1372,8 @@ modify_policy_2_svc(mpol_arg *arg, struct svc_req *rqstp)
if (CHANGEPW_SERVICE(rqstp) || !kadm5int_acl_check(handle->context,
rqst2name(rqstp),
ACL_MODIFY, NULL, NULL)) {
- krb5_klog_syslog(LOG_NOTICE, LOG_UNAUTH, "kadm5_modify_policy",
- prime_arg, client_name.value, service_name.value,
- inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr));
+ log_unauth("kadm5_modify_policy", prime_arg,
+ &client_name, &service_name, rqstp);
ret.code = KADM5_AUTH_MODIFY;
} else {
ret.code = kadm5_modify_policy((void *)handle, &arg->rec,
@@ -1378,11 +1383,9 @@ modify_policy_2_svc(mpol_arg *arg, struct svc_req *rqstp)
else
errmsg = krb5_get_error_message(handle ? handle->context : NULL, ret.code);
- krb5_klog_syslog(LOG_NOTICE, LOG_DONE, "kadm5_modify_policy",
- ((prime_arg == NULL) ? "(null)" : prime_arg),
- errmsg,
- client_name.value, service_name.value,
- inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr));
+ log_done("kadm5_modify_policy",
+ ((prime_arg == NULL) ? "(null)" : prime_arg), errmsg,
+ &client_name, &service_name, rqstp);
}
free_server_handle(handle);
gss_release_buffer(&minor_stat, &client_name);
@@ -1464,15 +1467,12 @@ get_policy_2_svc(gpol_arg *arg, struct svc_req *rqstp)
else
errmsg = krb5_get_error_message(handle ? handle->context : NULL, ret.code);
- krb5_klog_syslog(LOG_NOTICE, LOG_DONE, funcname,
- ((prime_arg == NULL) ? "(null)" : prime_arg),
- errmsg,
- client_name.value, service_name.value,
- inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr));
+ log_done(funcname,
+ ((prime_arg == NULL) ? "(null)" : prime_arg), errmsg,
+ &client_name, &service_name, rqstp);
} else {
- krb5_klog_syslog(LOG_NOTICE, LOG_UNAUTH, funcname,
- prime_arg, client_name.value, service_name.value,
- inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr));
+ log_unauth(funcname, prime_arg,
+ &client_name, &service_name, rqstp);
}
free_server_handle(handle);
gss_release_buffer(&minor_stat, &client_name);
@@ -1517,9 +1517,8 @@ get_pols_2_svc(gpols_arg *arg, struct svc_req *rqstp)
rqst2name(rqstp),
ACL_LIST, NULL, NULL)) {
ret.code = KADM5_AUTH_LIST;
- krb5_klog_syslog(LOG_NOTICE, LOG_UNAUTH, "kadm5_get_policies",
- prime_arg, client_name.value, service_name.value,
- inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr));
+ log_unauth("kadm5_get_policies", prime_arg,
+ &client_name, &service_name, rqstp);
} else {
ret.code = kadm5_get_policies((void *)handle,
arg->exp, &ret.pols,
@@ -1529,11 +1528,8 @@ get_pols_2_svc(gpols_arg *arg, struct svc_req *rqstp)
else
errmsg = krb5_get_error_message(handle ? handle->context : NULL, ret.code);
- krb5_klog_syslog(LOG_NOTICE, LOG_DONE, "kadm5_get_policies",
- prime_arg,
- errmsg,
- client_name.value, service_name.value,
- inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr));
+ log_done("kadm5_get_policies", prime_arg, errmsg,
+ &client_name, &service_name, rqstp);
}
free_server_handle(handle);
gss_release_buffer(&minor_stat, &client_name);
@@ -1573,11 +1569,8 @@ getprivs_ret * get_privs_2_svc(krb5_ui_4 *arg, struct svc_req *rqstp)
else
errmsg = krb5_get_error_message(handle ? handle->context : NULL, ret.code);
- krb5_klog_syslog(LOG_NOTICE, LOG_DONE, "kadm5_get_privs",
- client_name.value,
- errmsg,
- client_name.value, service_name.value,
- inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr));
+ log_done("kadm5_get_privs", client_name.value, errmsg,
+ &client_name, &service_name, rqstp);
free_server_handle(handle);
gss_release_buffer(&minor_stat, &client_name);
@@ -1594,6 +1587,8 @@ generic_ret *init_2_svc(krb5_ui_4 *arg, struct svc_req *rqstp)
kadm5_server_handle_t handle;
OM_uint32 minor_stat;
char *errmsg = 0;
+ size_t clen, slen;
+ char *cdots, *sdots;
xdr_free(xdr_generic_ret, &ret);
@@ -1612,14 +1607,22 @@ generic_ret *init_2_svc(krb5_ui_4 *arg, struct svc_req *rqstp)
if (ret.code != 0)
errmsg = krb5_get_error_message(handle ? handle->context : NULL, ret.code);
- krb5_klog_syslog(LOG_NOTICE, LOG_DONE ", flavor=%d",
- (ret.api_version == KADM5_API_VERSION_1 ?
- "kadm5_init (V1)" : "kadm5_init"),
- client_name.value,
- (ret.code == 0) ? "success" : errmsg,
- client_name.value, service_name.value,
- inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr),
- rqstp->rq_cred.oa_flavor);
+ else
+ errmsg = "success";
+
+ clen = client_name.length;
+ trunc_name(&clen, &cdots);
+ slen = service_name.length;
+ trunc_name(&slen, &sdots);
+ krb5_klog_syslog(LOG_NOTICE, "Request: %s, %.*s%s, %s, "
+ "client=%.*s%s, service=%.*s%s, addr=%s, flavor=%d",
+ (ret.api_version == KADM5_API_VERSION_1 ?
+ "kadm5_init (V1)" : "kadm5_init"),
+ clen, client_name.value, cdots, errmsg,
+ clen, client_name.value, cdots,
+ slen, service_name.value, sdots,
+ inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr),
+ rqstp->rq_cred.oa_flavor);
gss_release_buffer(&minor_stat, &client_name);
gss_release_buffer(&minor_stat, &service_name);
diff --git a/src/kadmin/testing/Makefile.in b/src/kadmin/testing/Makefile.in
index 74600d1..9fae207 100644
--- a/src/kadmin/testing/Makefile.in
+++ b/src/kadmin/testing/Makefile.in
@@ -7,4 +7,4 @@ LOCAL_SUBDIRS = scripts util
all::
clean::
- -$(RM) -r krb5-test-root
+ -$(RM) -r krb5-test-root admin_* init-* kadmin_* kdc_rcache.* ovsec-*
diff --git a/src/kdc/Makefile.in b/src/kdc/Makefile.in
index 0c3a161..4b21d76 100644
--- a/src/kdc/Makefile.in
+++ b/src/kdc/Makefile.in
@@ -86,7 +86,7 @@ install::
fi
clean::
- $(RM) kdc5_err.h kdc5_err.c krb5kdc rtest.o rtest
+ $(RM) kdc5_err.h kdc5_err.c krb5kdc rtest.o rtest fakeka.o fakeka
# +++ Dependency line eater +++
#
diff --git a/src/kdc/do_tgs_req.c b/src/kdc/do_tgs_req.c
index c722124..8e960cb 100644
--- a/src/kdc/do_tgs_req.c
+++ b/src/kdc/do_tgs_req.c
@@ -491,28 +491,38 @@ tgt_again:
newtransited = 1;
}
if (!isflagset (request->kdc_options, KDC_OPT_DISABLE_TRANSITED_CHECK)) {
+ unsigned int tlen;
+ char *tdots;
+
errcode = krb5_check_transited_list (kdc_context,
&enc_tkt_reply.transited.tr_contents,
krb5_princ_realm (kdc_context, header_ticket->enc_part2->client),
krb5_princ_realm (kdc_context, request->server));
+ tlen = enc_tkt_reply.transited.tr_contents.length;
+ tdots = tlen > 125 ? "..." : "";
+ tlen = tlen > 125 ? 125 : tlen;
+
if (errcode == 0) {
setflag (enc_tkt_reply.flags, TKT_FLG_TRANSIT_POLICY_CHECKED);
} else if (errcode == KRB5KRB_AP_ERR_ILL_CR_TKT)
krb5_klog_syslog (LOG_INFO,
- "bad realm transit path from '%s' to '%s' via '%.*s'",
+ "bad realm transit path from '%s' to '%s' "
+ "via '%.*s%s'",
cname ? cname : "<unknown client>",
sname ? sname : "<unknown server>",
- enc_tkt_reply.transited.tr_contents.length,
- enc_tkt_reply.transited.tr_contents.data);
+ tlen,
+ enc_tkt_reply.transited.tr_contents.data,
+ tdots);
else {
const char *emsg = krb5_get_error_message(kdc_context, errcode);
krb5_klog_syslog (LOG_ERR,
- "unexpected error checking transit from '%s' to '%s' via '%.*s': %s",
+ "unexpected error checking transit from "
+ "'%s' to '%s' via '%.*s%s': %s",
cname ? cname : "<unknown client>",
sname ? sname : "<unknown server>",
- enc_tkt_reply.transited.tr_contents.length,
+ tlen,
enc_tkt_reply.transited.tr_contents.data,
- emsg);
+ tdots, emsg);
krb5_free_error_message(kdc_context, emsg);
}
} else
@@ -542,6 +552,9 @@ tgt_again:
if (!krb5_principal_compare(kdc_context, request->server, client2)) {
if ((errcode = krb5_unparse_name(kdc_context, client2, &tmp)))
tmp = 0;
+ if (tmp != NULL)
+ limit_string(tmp);
+
krb5_klog_syslog(LOG_INFO,
"TGS_REQ %s: 2ND_TKT_MISMATCH: "
"authtime %d, %s for %s, 2nd tkt client %s",
@@ -816,6 +829,7 @@ find_alternate_tgs(krb5_kdc_req *request, krb5_db_entry *server,
krb5_klog_syslog(LOG_INFO,
"TGS_REQ: issuing alternate <un-unparseable> TGT");
} else {
+ limit_string(sname);
krb5_klog_syslog(LOG_INFO,
"TGS_REQ: issuing TGT %s", sname);
free(sname);
diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c
index 7325d45..aeabc5c 100644
--- a/src/kdc/kdc_util.c
+++ b/src/kdc/kdc_util.c
@@ -404,6 +404,7 @@ kdc_get_server_key(krb5_ticket *ticket, krb5_keyblock **key, krb5_kvno *kvno)
krb5_db_free_principal(kdc_context, &server, nprincs);
if (!krb5_unparse_name(kdc_context, ticket->server, &sname)) {
+ limit_string(sname);
krb5_klog_syslog(LOG_ERR,"TGS_REQ: UNKNOWN SERVER: server='%s'",
sname);
free(sname);
diff --git a/src/kdc/main.c b/src/kdc/main.c
index 7ee3d45..0e4c579 100644
--- a/src/kdc/main.c
+++ b/src/kdc/main.c
@@ -403,9 +403,9 @@ setup_sam(void)
void
usage(char *name)
{
- fprintf(stderr, "usage: %s [-x db_args]* [-d dbpathname] [-r dbrealmname] [-R replaycachename ]\n\t[-m] [-k masterenctype] [-M masterkeyname] [-p port] [-4 v4mode] [-X] [-n]\n"
- "\nwhere,\n\t[-x db_args]* - any number of database specific arguments.\n"
- "\t\t\tLook at each database documentation for supported arguments\n",
+ fprintf(stderr, "usage: %s [-x db_args]* [-d dbpathname] [-r dbrealmname]\n\t\t[-R replaycachename] [-m] [-k masterenctype] [-M masterkeyname]\n\t\t[-p port] [-4 v4mode] [-X] [-n]\n"
+ "\nwhere,\n\t[-x db_args]* - Any number of database specific arguments. Look at\n"
+ "\t\t\teach database module documentation for supported\n\t\t\targuments\n",
name);
return;
}
diff --git a/src/kdc/network.c b/src/kdc/network.c
index 3cb4400..e73352f 100644
--- a/src/kdc/network.c
+++ b/src/kdc/network.c
@@ -1,7 +1,7 @@
/*
* kdc/network.c
*
- * Copyright 1990,2000 by the Massachusetts Institute of Technology.
+ * Copyright 1990,2000,2007 by the Massachusetts Institute of Technology.
*
* Export of this software from the United States of America may
* require a specific license from the United States Government.
@@ -115,6 +115,33 @@ setv6only(int sock, int value)
}
#endif
+static int
+set_pktinfo(int sock, int family)
+{
+ int sockopt = 1;
+ int option = 0, proto = 0;
+
+ switch (family) {
+#if defined(IP_PKTINFO) && defined(HAVE_STRUCT_IN_PKTINFO)
+ case AF_INET:
+ proto = IPPROTO_IP;
+ option = IP_PKTINFO;
+ break;
+#endif
+#if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
+ case AF_INET6:
+ proto = IPPROTO_IPV6;
+ option = IPV6_PKTINFO;
+ break;
+#endif
+ default:
+ return EINVAL;
+ }
+ if (setsockopt(sock, proto, option, &sockopt, sizeof(sockopt)))
+ return errno;
+ return 0;
+}
+
static const char *paddr (struct sockaddr *sa)
{
@@ -138,7 +165,7 @@ static const char *paddr (struct sockaddr *sa)
/* KDC data. */
-enum kdc_conn_type { CONN_UDP, CONN_TCP_LISTENER, CONN_TCP };
+enum kdc_conn_type { CONN_UDP, CONN_UDP_PKTINFO, CONN_TCP_LISTENER, CONN_TCP };
/* Per-connection info. */
struct connection {
@@ -147,12 +174,17 @@ struct connection {
void (*service)(struct connection *, const char *, int);
union {
/* Type-specific information. */
+#if 0
struct {
int x;
} udp;
struct {
int x;
+ } udp_pktinfo;
+ struct {
+ int x;
} tcp_listener;
+#endif
struct {
/* connection */
struct sockaddr_storage addr_s;
@@ -206,8 +238,8 @@ struct connection {
#define DEL(set, idx) \
(set.data[idx] = set.data[--set.n], 0)
-#define FREE_SET_DATA(set) if(set.data) free(set.data); \
- (set.data = 0, set.max = 0)
+#define FREE_SET_DATA(set) \
+ (free(set.data), set.data = 0, set.max = 0)
/* Set<struct connection *> connections; */
@@ -268,6 +300,9 @@ static krb5_error_code add_tcp_port(int port)
struct socksetup {
const char *prog;
krb5_error_code retval;
+ int udp_flags;
+#define UDP_DO_IPV4 1
+#define UDP_DO_IPV6 2
};
static struct connection *
@@ -303,9 +338,10 @@ static void accept_tcp_connection(struct connection *, const char *, int);
static void process_tcp_connection(struct connection *, const char *, int);
static struct connection *
-add_udp_fd (struct socksetup *data, int sock)
+add_udp_fd (struct socksetup *data, int sock, int pktinfo)
{
- return add_fd(data, sock, CONN_UDP, process_packet);
+ return add_fd(data, sock, pktinfo ? CONN_UDP_PKTINFO : CONN_UDP,
+ process_packet);
}
static struct connection *
@@ -484,15 +520,139 @@ setup_tcp_listener_ports(struct socksetup *data)
return 0;
}
+#if defined(CMSG_SPACE) && defined(HAVE_STRUCT_CMSGHDR) && (defined(IP_PKTINFO) || defined(IPV6_PKTINFO))
+union pktinfo {
+#ifdef HAVE_STRUCT_IN6_PKTINFO
+ struct in6_pktinfo pi6;
+#endif
+#ifdef HAVE_STRUCT_IN_PKTINFO
+ struct in_pktinfo pi4;
+#endif
+ char c;
+};
+
+static int
+setup_udp_port_1(struct socksetup *data, struct sockaddr *addr,
+ char *haddrbuf, int pktinfo);
+
+static void
+setup_udp_pktinfo_ports(struct socksetup *data)
+{
+#ifdef IP_PKTINFO
+ {
+ struct sockaddr_in sa;
+ int r;
+
+ memset(&sa, 0, sizeof(sa));
+ sa.sin_family = AF_INET;
+#ifdef HAVE_SA_LEN
+ sa.sin_len = sizeof(sa);
+#endif
+ r = setup_udp_port_1(data, (struct sockaddr *) &sa, "0.0.0.0", 4);
+ if (r == 0)
+ data->udp_flags &= ~UDP_DO_IPV4;
+ }
+#endif
+#ifdef IPV6_PKTINFO
+ {
+ struct sockaddr_in6 sa;
+ int r;
+
+ memset(&sa, 0, sizeof(sa));
+ sa.sin6_family = AF_INET6;
+#ifdef HAVE_SA_LEN
+ sa.sin6_len = sizeof(sa);
+#endif
+ r = setup_udp_port_1(data, (struct sockaddr *) &sa, "::", 6);
+ if (r == 0)
+ data->udp_flags &= ~UDP_DO_IPV6;
+ }
+#endif
+}
+#else /* no pktinfo compile-time support */
+static void
+setup_udp_pktinfo_ports(struct socksetup *data)
+{
+}
+#endif
+
+static int
+setup_udp_port_1(struct socksetup *data, struct sockaddr *addr,
+ char *haddrbuf, int pktinfo)
+{
+ int sock = -1, i, r;
+ u_short port;
+
+ FOREACH_ELT (udp_port_data, i, port) {
+ sock = socket (addr->sa_family, SOCK_DGRAM, 0);
+ if (sock == -1) {
+ data->retval = errno;
+ com_err(data->prog, data->retval,
+ "Cannot create server socket for port %d address %s",
+ port, haddrbuf);
+ return 1;
+ }
+#ifdef KRB5_USE_INET6
+ if (addr->sa_family == AF_INET6) {
+#ifdef IPV6_V6ONLY
+ if (setv6only(sock, 1))
+ com_err(data->prog, errno, "setsockopt(IPV6_V6ONLY,1) failed");
+ else
+ com_err(data->prog, 0, "setsockopt(IPV6_V6ONLY,1) worked");
+#else
+ krb5_klog_syslog(LOG_INFO, "no IPV6_V6ONLY socket option support");
+#endif /* IPV6_V6ONLY */
+ }
+#endif
+ set_sa_port(addr, htons(port));
+ if (bind (sock, (struct sockaddr *)addr, socklen (addr)) == -1) {
+ data->retval = errno;
+ com_err(data->prog, data->retval,
+ "Cannot bind server socket to port %d address %s",
+ port, haddrbuf);
+ close(sock);
+ return 1;
+ }
+#if !(defined(CMSG_SPACE) && defined(HAVE_STRUCT_CMSGHDR) && (defined(IP_PKTINFO) || defined(IPV6_PKTINFO)))
+ assert(pktinfo == 0);
+#endif
+ if (pktinfo) {
+ r = set_pktinfo(sock, addr->sa_family);
+ if (r) {
+ com_err(data->prog, r,
+ "Cannot request packet info for udp socket address %s port %d",
+ haddrbuf, port);
+ close(sock);
+ return 1;
+ }
+ }
+ FD_SET (sock, &sstate.rfds);
+ if (sock >= sstate.max)
+ sstate.max = sock + 1;
+ krb5_klog_syslog (LOG_INFO, "listening on fd %d: udp %s%s", sock,
+ paddr((struct sockaddr *)addr),
+ pktinfo ? " (pktinfo)" : "");
+ if (add_udp_fd (data, sock, pktinfo) == 0) {
+ close(sock);
+ return 1;
+ }
+ }
+ return 0;
+}
+
static int
setup_udp_port(void *P_data, struct sockaddr *addr)
{
struct socksetup *data = P_data;
- int sock = -1, i;
char haddrbuf[NI_MAXHOST];
int err;
- u_short port;
+ if (addr->sa_family == AF_INET && !(data->udp_flags & UDP_DO_IPV4))
+ return 0;
+#ifdef AF_INET6
+ if (addr->sa_family == AF_INET6 && !(data->udp_flags & UDP_DO_IPV6))
+ return 0;
+#endif
err = getnameinfo(addr, socklen(addr), haddrbuf, sizeof(haddrbuf),
0, 0, NI_NUMERICHOST);
if (err)
@@ -530,33 +690,7 @@ setup_udp_port(void *P_data, struct sockaddr *addr)
addr->sa_family);
return 0;
}
-
- FOREACH_ELT (udp_port_data, i, port) {
- sock = socket (addr->sa_family, SOCK_DGRAM, 0);
- if (sock == -1) {
- data->retval = errno;
- com_err(data->prog, data->retval,
- "Cannot create server socket for port %d address %s",
- port, haddrbuf);
- return 1;
- }
- set_sa_port(addr, htons(port));
- if (bind (sock, (struct sockaddr *)addr, socklen (addr)) == -1) {
- data->retval = errno;
- com_err(data->prog, data->retval,
- "Cannot bind server socket to port %d address %s",
- port, haddrbuf);
- return 1;
- }
- FD_SET (sock, &sstate.rfds);
- if (sock >= sstate.max)
- sstate.max = sock + 1;
- krb5_klog_syslog (LOG_INFO, "listening on fd %d: udp %s", sock,
- paddr((struct sockaddr *)addr));
- if (add_udp_fd (data, sock) == 0)
- return 1;
- }
- return 0;
+ return setup_udp_port_1(data, addr, haddrbuf, 0);
}
#if 1
@@ -662,8 +796,12 @@ setup_network(const char *prog)
so we might need only one UDP socket; fall back to binding
sockets on each address only if IPV6_PKTINFO isn't
supported. */
- if (foreach_localaddr (&setup_data, setup_udp_port, 0, 0)) {
- return setup_data.retval;
+ setup_data.udp_flags = UDP_DO_IPV4 | UDP_DO_IPV6;
+ setup_udp_pktinfo_ports(&setup_data);
+ if (setup_data.udp_flags) {
+ if (foreach_localaddr (&setup_data, setup_udp_port, 0, 0)) {
+ return setup_data.retval;
+ }
}
setup_tcp_listener_ports(&setup_data);
krb5_klog_syslog (LOG_INFO, "set up %d sockets", n_sockets);
@@ -707,14 +845,164 @@ static void init_addr(krb5_fulladdr *faddr, struct sockaddr *sa)
}
}
+static int
+recv_from_to(int s, void *buf, size_t len, int flags,
+ struct sockaddr *from, socklen_t *fromlen,
+ struct sockaddr *to, socklen_t *tolen)
+{
+#if (!defined(IP_PKTINFO) && !defined(IPV6_PKTINFO)) || !defined(CMSG_SPACE)
+ if (to && tolen)
+ *tolen = 0;
+ return recvfrom(s, buf, len, flags, from, fromlen);
+#else
+ int r;
+ struct iovec iov;
+ char cmsg[CMSG_SPACE(sizeof(union pktinfo))];
+ struct cmsghdr *cmsgptr;
+ struct msghdr msg;
+
+ if (!to || !tolen)
+ return recvfrom(s, buf, len, flags, from, fromlen);
+
+ iov.iov_base = buf;
+ iov.iov_len = len;
+ memset(&msg, 0, sizeof(msg));
+ msg.msg_name = from;
+ msg.msg_namelen = *fromlen;
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = cmsg;
+ msg.msg_controllen = sizeof(cmsg);
+
+ r = recvmsg(s, &msg, flags);
+ if (r < 0)
+ return r;
+ *fromlen = msg.msg_namelen;
+
+ /* On Darwin (and presumably all *BSD with KAME stacks),
+ CMSG_FIRSTHDR doesn't check for a non-zero controllen. RFC
+ 3542 recommends making this check, even though the (new) spec
+ for CMSG_FIRSTHDR says it's supposed to do the check. */
+ if (msg.msg_controllen) {
+ cmsgptr = CMSG_FIRSTHDR(&msg);
+ while (cmsgptr) {
+#ifdef IP_PKTINFO
+ if (cmsgptr->cmsg_level == IPPROTO_IP
+ && cmsgptr->cmsg_type == IP_PKTINFO
+ && *tolen >= sizeof(struct sockaddr_in)) {
+ struct in_pktinfo *pktinfo;
+ memset(to, 0, sizeof(struct sockaddr_in));
+ pktinfo = (struct in_pktinfo *)CMSG_DATA(cmsgptr);
+ ((struct sockaddr_in *)to)->sin_addr = pktinfo->ipi_addr;
+ ((struct sockaddr_in *)to)->sin_family = AF_INET;
+ *tolen = sizeof(struct sockaddr_in);
+ return r;
+ }
+#endif
+#if defined(KRB5_USE_INET6) && defined(IPV6_PKTINFO)
+ if (cmsgptr->cmsg_level == IPPROTO_IPV6
+ && cmsgptr->cmsg_type == IPV6_PKTINFO
+ && *tolen >= sizeof(struct sockaddr_in6)) {
+ struct in6_pktinfo *pktinfo;
+ memset(to, 0, sizeof(struct sockaddr_in6));
+ pktinfo = (struct in6_pktinfo *)CMSG_DATA(cmsgptr);
+ ((struct sockaddr_in6 *)to)->sin6_addr = pktinfo->ipi6_addr;
+ ((struct sockaddr_in6 *)to)->sin6_family = AF_INET6;
+ *tolen = sizeof(struct sockaddr_in6);
+ return r;
+ }
+#endif
+ cmsgptr = CMSG_NXTHDR(&msg, cmsgptr);
+ }
+ }
+ /* No info about destination addr was available. */
+ *tolen = 0;
+ return r;
+#endif
+}
+
+static int
+send_to_from(int s, void *buf, size_t len, int flags,
+ const struct sockaddr *to, socklen_t tolen,
+ const struct sockaddr *from, socklen_t fromlen)
+{
+#if (!defined(IP_PKTINFO) && !defined(IPV6_PKTINFO)) || !defined(CMSG_SPACE)
+ return sendto(s, buf, len, flags, to, tolen);
+#else
+ struct iovec iov;
+ struct msghdr msg;
+ struct cmsghdr *cmsgptr;
+ char cbuf[CMSG_SPACE(sizeof(union pktinfo))];
+
+ if (from == 0 || fromlen == 0 || from->sa_family != to->sa_family) {
+ use_sendto:
+ return sendto(s, buf, len, flags, to, tolen);
+ }
+
+ iov.iov_base = buf;
+ iov.iov_len = len;
+ /* Truncation? */
+ if (iov.iov_len != len)
+ return EINVAL;
+ memset(cbuf, 0, sizeof(cbuf));
+ memset(&msg, 0, sizeof(msg));
+ msg.msg_name = (void *) to;
+ msg.msg_namelen = tolen;
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = cbuf;
+ /* CMSG_FIRSTHDR needs a non-zero controllen, or it'll return NULL
+ on Linux. */
+ msg.msg_controllen = sizeof(cbuf);
+ cmsgptr = CMSG_FIRSTHDR(&msg);
+ msg.msg_controllen = 0;
+
+ switch (from->sa_family) {
+#if defined(IP_PKTINFO)
+ case AF_INET:
+ if (fromlen != sizeof(struct sockaddr_in))
+ goto use_sendto;
+ cmsgptr->cmsg_level = IPPROTO_IP;
+ cmsgptr->cmsg_type = IP_PKTINFO;
+ cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
+ {
+ struct in_pktinfo *p = (struct in_pktinfo *)CMSG_DATA(cmsgptr);
+ const struct sockaddr_in *from4 = (const struct sockaddr_in *)from;
+ p->ipi_spec_dst = from4->sin_addr;
+ }
+ msg.msg_controllen = CMSG_SPACE(sizeof(struct in_pktinfo));
+ break;
+#endif
+#if defined(KRB5_USE_INET6) && defined(IPV6_PKTINFO)
+ case AF_INET6:
+ if (fromlen != sizeof(struct sockaddr_in6))
+ goto use_sendto;
+ cmsgptr->cmsg_level = IPPROTO_IPV6;
+ cmsgptr->cmsg_type = IPV6_PKTINFO;
+ cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
+ {
+ struct in6_pktinfo *p = (struct in6_pktinfo *)CMSG_DATA(cmsgptr);
+ const struct sockaddr_in6 *from6 = (const struct sockaddr_in6 *)from;
+ p->ipi6_addr = from6->sin6_addr;
+ }
+ msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
+ break;
+#endif
+ default:
+ goto use_sendto;
+ }
+ return sendmsg(s, &msg, flags);
+#endif
+}
+
static void process_packet(struct connection *conn, const char *prog,
int selflags)
{
int cc;
- socklen_t saddr_len;
+ socklen_t saddr_len, daddr_len;
krb5_fulladdr faddr;
krb5_error_code retval;
- struct sockaddr_storage saddr;
+ struct sockaddr_storage saddr, daddr;
krb5_address addr;
krb5_data request;
krb5_data *response;
@@ -723,8 +1011,10 @@ static void process_packet(struct connection *conn, const char *prog,
response = NULL;
saddr_len = sizeof(saddr);
- cc = recvfrom(port_fd, pktbuf, sizeof(pktbuf), 0,
- (struct sockaddr *)&saddr, &saddr_len);
+ daddr_len = sizeof(daddr);
+ cc = recv_from_to(port_fd, pktbuf, sizeof(pktbuf), 0,
+ (struct sockaddr *)&saddr, &saddr_len,
+ (struct sockaddr *)&daddr, &daddr_len);
if (cc == -1) {
if (errno != EINTR
/* This is how Linux indicates that a previous
@@ -738,6 +1028,16 @@ static void process_packet(struct connection *conn, const char *prog,
if (!cc)
return; /* zero-length packet? */
+#if 0
+ if (daddr_len > 0) {
+ char addrbuf[100];
+ if (getnameinfo(ss2sa(&daddr), daddr_len, addrbuf, sizeof(addrbuf),
+ 0, 0, NI_NUMERICHOST))
+ strcpy(addrbuf, "?");
+ com_err(prog, 0, "pktinfo says local addr is %s", addrbuf);
+ }
+#endif
+
request.length = cc;
request.data = pktbuf;
faddr.address = &addr;
@@ -747,8 +1047,9 @@ static void process_packet(struct connection *conn, const char *prog,
com_err(prog, retval, "while dispatching (udp)");
return;
}
- cc = sendto(port_fd, response->data, (socklen_t) response->length, 0,
- (struct sockaddr *)&saddr, saddr_len);
+ cc = send_to_from(port_fd, response->data, (socklen_t) response->length, 0,
+ (struct sockaddr *)&saddr, saddr_len,
+ (struct sockaddr *)&daddr, daddr_len);
if (cc == -1) {
char addrbuf[46];
krb5_free_data(kdc_context, response);
diff --git a/src/krb524/Makefile.in b/src/krb524/Makefile.in
index c1c69ca..08ad1e7 100644
--- a/src/krb524/Makefile.in
+++ b/src/krb524/Makefile.in
@@ -38,6 +38,7 @@ PROG_RPATH=$(KRB5_LIBDIR)
##WIN32##K4LIB=$(USE_ALTERNATE_KRB4_LIB)
##WIN32##!endif
+K524EXE = $(OUTPRE)k524init.exe
K524LIB = $(OUTPRE)krb524.lib
K524DEP = $(K524LIB)
K524DEF = krb524.def
@@ -69,9 +70,20 @@ EXTRADEPSRCS = \
##WIN32##K524DEP=$(STLIBOBJS)
##WIN32##!endif
+##WIN32##VERSIONRC = $(BUILDTOP)\windows\version.rc
+##WIN32##RCFLAGS=$(CPPFLAGS) -I$(SRCTOP) -D_WIN32 -DRES_ONLY
+
+##WIN32##EXERES=$(K524EXE:.exe=.res)
+##WIN32##LIBRES=$(K524LIB:.lib=.res)
+
+##WIN32##$(EXERES): $(VERSIONRC)
+##WIN32## $(RC) $(RCFLAGS) -DKRB524_INIT -fo $@ -r $**
+##WIN32##$(LIBRES): $(VERSIONRC)
+##WIN32## $(RC) $(RCFLAGS) -DKRB524_LIB -fo $@ -r $**
+
all-unix:: krb524d krb524test k524init
-all-windows:: $(OUTPRE)k524init.exe $(K524LIB)
+##WIN32##all-windows:: $(K524EXE) $(K524LIB)
krb524test: test.o $(KRB5_DEPLIB) $(KRB4COMPAT_DEPLIBS)
$(CC_LINK) -o krb524test test.o $(KRB5_LIB) $(KRB4COMPAT_LIBS)
@@ -85,13 +97,13 @@ krb524d: $(SERVER_OBJS) $(KADMSRV_DEPLIBS) $(KRB5_DEPLIB) $(KRB4COMPAT_DEPLIBS)
k524init: $(CLIENT_OBJS) $(KRB5_DEPLIB) $(KRB4COMPAT_DEPLIBS)
$(CC_LINK) -o k524init $(CLIENT_OBJS) $(KRB5_LIB) $(KRB4COMPAT_LIBS)
-$(K524LIB): $(OUTPRE)krb524.$(OBJEXT) $(OUTPRE)libinit.$(OBJEXT) $(KLIB) $(CLIB)
- link $(DLL_LINKOPTS) -def:$(K524DEF) -out:$*.dll $** $(WINLIBS)
- $(_VC_MANIFEST_EMBED_DLL)
+##WIN32##$(K524LIB): $(OUTPRE)krb524.$(OBJEXT) $(OUTPRE)libinit.$(OBJEXT) $(KLIB) $(CLIB) $(LIBRES)
+##WIN32## link $(DLL_LINKOPTS) -def:$(K524DEF) -out:$*.dll $** $(WINLIBS)
+##WIN32## $(_VC_MANIFEST_EMBED_DLL)
-$(OUTPRE)k524init.exe: $(OUTPRE)k524init.$(OBJEXT) $(KLIB) $(K4LIB) $(CLIB) $(BUILDTOP)\util\windows\$(OUTPRE)getopt.lib
- link $(EXE_LINKOPTS) -out:$@ $** $(WINLIBS) $(SCLIB)
- $(_VC_MANIFEST_EMBED_EXE)
+##WIN32##$(K524EXE): $(OUTPRE)k524init.$(OBJEXT) $(KLIB) $(K4LIB) $(CLIB) $(EXERES) $(BUILDTOP)\util\windows\$(OUTPRE)getopt.lib
+##WIN32## link $(EXE_LINKOPTS) -out:$@ $** $(WINLIBS) $(SCLIB)
+##WIN32## $(_VC_MANIFEST_EMBED_EXE)
install-unix::
$(INSTALL_PROGRAM) krb524d $(DESTDIR)$(SERVER_BINDIR)/krb524d
diff --git a/src/lib/apputils/Makefile.in b/src/lib/apputils/Makefile.in
index bc8b8a0..7c5e5e8 100644
--- a/src/lib/apputils/Makefile.in
+++ b/src/lib/apputils/Makefile.in
@@ -2,9 +2,9 @@ prefix=@prefix@
bindir=@bindir@
datadir=@datadir@
mydatadir=$(datadir)/apputils
-thisconfigdir=.
+thisconfigdir=../..
myfulldir=lib/apputils
-mydir=.
+mydir=lib/apputils
BUILDTOP=$(REL)..$(S)..
RELDIR=../lib/apputils
SED = sed
@@ -32,6 +32,7 @@ LIBOBJS=$(OUTPRE)daemon.$(OBJEXT)
SRCS= $(srcdir)/daemon.c \
$(srcdir)/dummy.c
+@libpriv_frag@
@lib_frag@
@libobj_frag@
diff --git a/src/lib/apputils/configure.in b/src/lib/apputils/configure.in
deleted file mode 100644
index 73e9a87..0000000
--- a/src/lib/apputils/configure.in
+++ /dev/null
@@ -1,6 +0,0 @@
-K5_AC_INIT(daemon.c)
-CONFIG_RULES
-AC_REPLACE_FUNCS(daemon)
-KRB5_BUILD_LIBRARY_STATIC
-KRB5_BUILD_LIBOBJS
-V5_AC_OUTPUT_MAKEFILE
diff --git a/src/lib/crypto/decrypt.c b/src/lib/crypto/decrypt.c
index c252eb7..96861bd 100644
--- a/src/lib/crypto/decrypt.c
+++ b/src/lib/crypto/decrypt.c
@@ -39,8 +39,12 @@ krb5_c_decrypt(krb5_context context, const krb5_keyblock *key,
break;
}
- if (i == krb5_enctypes_length)
+ if (i == krb5_enctypes_length) {
+ krb5int_set_error(&context->err, KRB5_BAD_ENCTYPE,
+ "Bad encryption type (type %d unknown)",
+ key->enctype);
return(KRB5_BAD_ENCTYPE);
+ }
if ((input->enctype != ENCTYPE_UNKNOWN) &&
(krb5_enctypes_list[i].etype != input->enctype))
diff --git a/src/lib/gssapi/Makefile.in b/src/lib/gssapi/Makefile.in
index 79fe58d..b265154 100644
--- a/src/lib/gssapi/Makefile.in
+++ b/src/lib/gssapi/Makefile.in
@@ -47,8 +47,9 @@ clean-unix:: clean-liblinks clean-libs clean-libobjs clean-misc-unix
clean-windows::
$(RM) gssapi.lib gssapi.bak
-clean-misc-unix:
+clean-misc-unix: clean-recurse
$(RM) merged-gssapi-header.h
+ $(RM) -r $(EHDRDIR)
EHDRDIR=$(BUILDTOP)$(S)include$(S)gssapi
EXPORTED_HEADERS= \
diff --git a/src/lib/gssapi/generic/util_ordering.c b/src/lib/gssapi/generic/util_ordering.c
index f7cf666..218462b 100644
--- a/src/lib/gssapi/generic/util_ordering.c
+++ b/src/lib/gssapi/generic/util_ordering.c
@@ -96,6 +96,12 @@ g_order_init(void **vqueue, gssint_uint64 seqnum,
if ((q = (queue *) malloc(sizeof(queue))) == NULL)
return(ENOMEM);
+ /* This stops valgrind from complaining about writing uninitialized
+ data if the caller exports the context and writes it to a file.
+ We don't actually use those bytes at all, but valgrind still
+ complains. */
+ memset(q, 0xfe, sizeof(*q));
+
q->do_replay = do_replay;
q->do_sequence = do_sequence;
q->mask = wide_nums ? ~(gssint_uint64)0 : 0xffffffffUL;
diff --git a/src/lib/gssapi/mechglue/g_initialize.c b/src/lib/gssapi/mechglue/g_initialize.c
index 0c4513c..d948b98 100644
--- a/src/lib/gssapi/mechglue/g_initialize.c
+++ b/src/lib/gssapi/mechglue/g_initialize.c
@@ -44,9 +44,11 @@
/* Local functions */
static gss_mech_info searchMechList(const gss_OID);
static void updateMechList(void);
+static void freeMechList(void);
static void register_mech(gss_mechanism, const char *, void *);
static OM_uint32 build_mechSet(void);
+static void free_mechSet(void);
static void init_hardcoded(void);
/*
@@ -74,6 +76,8 @@ gssint_mechglue_fini(void)
{
k5_mutex_destroy(&g_mechSetLock);
k5_mutex_destroy(&g_mechListLock);
+ free_mechSet();
+ freeMechList();
}
@@ -219,6 +223,21 @@ gss_OID_set *mechSet;
} /* gss_indicate_mechs */
+/* Call with g_mechSetLock held, or during final cleanup. */
+static void
+free_mechSet(void)
+{
+ int i;
+
+ if (g_mechSet.count != 0) {
+ for (i = 0; i < g_mechSet.count; i++)
+ free(g_mechSet.elements[i].elements);
+ free(g_mechSet.elements);
+ g_mechSet.elements = NULL;
+ g_mechSet.count = 0;
+ }
+}
+
static OM_uint32
build_mechSet(void)
{
@@ -244,13 +263,7 @@ build_mechSet(void)
(void) k5_mutex_lock(&g_mechSetLock);
/* if the oid list already exists we must free it first */
- if (g_mechSet.count != 0) {
- for (i = 0; i < g_mechSet.count; i++)
- free(g_mechSet.elements[i].elements);
- free(g_mechSet.elements);
- g_mechSet.elements = NULL;
- g_mechSet.count = 0;
- }
+ free_mechSet();
/* determine how many elements to have in the list */
mList = g_mechList;
@@ -453,6 +466,19 @@ updateMechList(void)
} /* updateMechList */
+static void
+freeMechList(void)
+{
+ gss_mech_info cf, next_cf;
+
+ for (cf = g_mechList; cf != NULL; cf = next_cf) {
+ next_cf = cf->next;
+ free(cf->uLibName);
+ free(cf->mechNameStr);
+ free(cf);
+ }
+}
+
/*
* Register a mechanism. Called with g_mechListLock held.
*/
diff --git a/src/lib/kadm5/admin.h b/src/lib/kadm5/admin.h
index 99d18d4..adbd6c8 100644
--- a/src/lib/kadm5/admin.h
+++ b/src/lib/kadm5/admin.h
@@ -494,6 +494,16 @@ kadm5_ret_t kadm5_free_name_list(void *server_handle, char **names,
krb5_error_code kadm5_init_krb5_context (krb5_context *);
+/*
+ * kadm5_get_principal_keys is used only by kadmin.local to extract existing
+ * keys from the database without changing them. It should never be exposed
+ * to the network protocol.
+ */
+kadm5_ret_t kadm5_get_principal_keys(void *server_handle,
+ krb5_principal principal,
+ krb5_keyblock **keyblocks,
+ int *n_keys);
+
#if USE_KADM5_API_VERSION == 1
/*
* OVSEC_KADM_API_VERSION_1 should be, if possible, compile-time
diff --git a/src/lib/kadm5/logger.c b/src/lib/kadm5/logger.c
index 212034b..e6fe44d 100644
--- a/src/lib/kadm5/logger.c
+++ b/src/lib/kadm5/logger.c
@@ -41,7 +41,7 @@
#endif /* HAVE_SYSLOG_H */
#include <stdarg.h>
-#define KRB5_KLOG_MAX_ERRMSG_SIZE 1024
+#define KRB5_KLOG_MAX_ERRMSG_SIZE 2048
#ifndef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN 256
#endif /* MAXHOSTNAMELEN */
@@ -257,7 +257,9 @@ klog_com_err_proc(const char *whoami, long int code, const char *format, va_list
#endif /* HAVE_SYSLOG */
/* Now format the actual message */
-#if HAVE_VSPRINTF
+#if HAVE_VSNPRINTF
+ vsnprintf(cp, sizeof(outbuf) - (cp - outbuf), actual_format, ap);
+#elif HAVE_VSPRINTF
vsprintf(cp, actual_format, ap);
#else /* HAVE_VSPRINTF */
sprintf(cp, actual_format, ((int *) ap)[0], ((int *) ap)[1],
@@ -846,7 +848,9 @@ klog_vsyslog(int priority, const char *format, va_list arglist)
syslogp = &outbuf[strlen(outbuf)];
/* Now format the actual message */
-#ifdef HAVE_VSPRINTF
+#ifdef HAVE_VSNPRINTF
+ vsnprintf(syslogp, sizeof(outbuf) - (syslogp - outbuf), format, arglist);
+#elif HAVE_VSPRINTF
vsprintf(syslogp, format, arglist);
#else /* HAVE_VSPRINTF */
sprintf(syslogp, format, ((int *) arglist)[0], ((int *) arglist)[1],
diff --git a/src/lib/kadm5/srv/libkadm5srv.exports b/src/lib/kadm5/srv/libkadm5srv.exports
index 96a3e40..23a4ee1 100644
--- a/src/lib/kadm5/srv/libkadm5srv.exports
+++ b/src/lib/kadm5/srv/libkadm5srv.exports
@@ -35,6 +35,7 @@ kadm5_get_config_params
kadm5_get_policies
kadm5_get_policy
kadm5_get_principal
+kadm5_get_principal_keys
kadm5_get_principals
kadm5_get_privs
kadm5_init
diff --git a/src/lib/kadm5/srv/svr_principal.c b/src/lib/kadm5/srv/svr_principal.c
index 0a66a06..a7636e7 100644
--- a/src/lib/kadm5/srv/svr_principal.c
+++ b/src/lib/kadm5/srv/svr_principal.c
@@ -1996,6 +1996,61 @@ done:
}
/*
+ * Return the list of keys like kadm5_randkey_principal,
+ * but don't modify the principal.
+ */
+kadm5_ret_t
+kadm5_get_principal_keys(void *server_handle /* IN */,
+ krb5_principal principal /* IN */,
+ krb5_keyblock **keyblocks /* OUT */,
+ int *n_keys /* OUT */)
+{
+ krb5_db_entry kdb;
+ osa_princ_ent_rec adb;
+ krb5_key_data *key_data;
+ kadm5_ret_t ret;
+ kadm5_server_handle_t handle = server_handle;
+
+ if (keyblocks)
+ *keyblocks = NULL;
+
+ CHECK_HANDLE(server_handle);
+
+ if (principal == NULL)
+ return EINVAL;
+
+ if ((ret = kdb_get_entry(handle, principal, &kdb, &adb)))
+ return(ret);
+
+ if (keyblocks) {
+ if (handle->api_version == KADM5_API_VERSION_1) {
+ /* Version 1 clients will expect to see a DES_CRC enctype. */
+ if ((ret = krb5_dbe_find_enctype(handle->context, &kdb,
+ ENCTYPE_DES_CBC_CRC,
+ -1, -1, &key_data)))
+ goto done;
+
+ if ((ret = decrypt_key_data(handle->context, 1, key_data,
+ keyblocks, NULL)))
+ goto done;
+ } else {
+ ret = decrypt_key_data(handle->context,
+ kdb.n_key_data, kdb.key_data,
+ keyblocks, n_keys);
+ if (ret)
+ goto done;
+ }
+ }
+
+ ret = KADM5_OK;
+done:
+ kdb_free_entry(handle, &kdb, &adb);
+
+ return ret;
+}
+
+
+/*
* Allocate an array of n_key_data krb5_keyblocks, fill in each
* element with the results of decrypting the nth key in key_data with
* master_keyblock, and if n_keys is not NULL fill it in with the
diff --git a/src/lib/krb5/ccache/Makefile.in b/src/lib/krb5/ccache/Makefile.in
index 69ab934..101f0b1 100644
--- a/src/lib/krb5/ccache/Makefile.in
+++ b/src/lib/krb5/ccache/Makefile.in
@@ -213,8 +213,13 @@ ser_cc.so ser_cc.po $(OUTPRE)ser_cc.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
$(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
$(SRCTOP)/include/socket-utils.h ser_cc.c
t_cc.so t_cc.po $(OUTPRE)t_cc.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
- $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(SRCTOP)/include/krb5.h \
- t_cc.c
+ $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+ $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+ $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+ $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+ $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+ $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+ $(SRCTOP)/include/socket-utils.h t_cc.c
t_cccursor.so t_cccursor.po $(OUTPRE)t_cccursor.$(OBJEXT): \
$(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
$(COM_ERR_DEPS) $(SRCTOP)/include/krb5.h t_cccursor.c
diff --git a/src/lib/krb5/ccache/cc_mslsa.c b/src/lib/krb5/ccache/cc_mslsa.c
index 381484c..eca9fd6 100644
--- a/src/lib/krb5/ccache/cc_mslsa.c
+++ b/src/lib/krb5/ccache/cc_mslsa.c
@@ -1,6 +1,8 @@
/*
* lib/krb5/ccache/cc_mslsa.c
*
+ * Copyright 2007 Secure Endpoints Inc.
+ *
* Copyright 2003,2004 by the Massachusetts Institute of Technology.
* All Rights Reserved.
*
@@ -60,16 +62,25 @@
#include <stdlib.h>
#include <conio.h>
#include <time.h>
+
#define SECURITY_WIN32
#include <security.h>
+#ifdef _WIN32_WINNT
+#undef _WIN32_WINNT
+#endif
+#define _WIN32_WINNT 0x0600
#include <ntsecapi.h>
#include <ntstatus.h>
-#ifdef COMMENT
-/* The following two features can only be built using a version of the
- * Microsoft Windows Platform SDK which is not currently public. These
- * features will be disabled until the SDK is made publicly available.
+
+/* The following two features can only be built using the version of the
+ * Platform SDK for Microsoft Windows Vista. If AES support is defined
+ * in NTSecAPI.h then we know that we have the required data structures.
+ *
+ * To build with the Windows XP SP2 SDK, the NTSecAPI.h from the Vista
+ * SDK should be used in place of the XP SP2 SDK version.
*/
+#ifdef TRUST_ATTRIBUTE_TRUST_USES_AES_KEYS
#define KERB_SUBMIT_TICKET 1
#define HAVE_CACHE_INFO_EX2 1
#endif
@@ -136,6 +147,61 @@ is_windows_xp (void)
return fIsWinXP;
}
+static BOOL
+is_windows_vista (void)
+{
+ static BOOL fChecked = FALSE;
+ static BOOL fIsVista = 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)
+ fIsVista = TRUE;
+ }
+ fChecked = TRUE;
+ }
+
+ return fIsVista;
+}
+
+static BOOL
+is_process_uac_limited (void)
+{
+ static BOOL fChecked = FALSE;
+ static BOOL fIsUAC = FALSE;
+
+ if (!fChecked)
+ {
+ NTSTATUS Status = 0;
+ HANDLE TokenHandle;
+ DWORD ElevationLevel;
+ DWORD ReqLen;
+ BOOL Success;
+
+ if (is_windows_vista()) {
+ Success = OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &TokenHandle );
+ if ( Success ) {
+ Success = GetTokenInformation( TokenHandle,
+ TokenOrigin+1 /* ElevationLevel */,
+ &ElevationLevel, sizeof(DWORD), &ReqLen );
+ CloseHandle( TokenHandle );
+ if ( Success && ElevationLevel == 3 /* Limited */ )
+ fIsUAC = TRUE;
+ }
+ }
+ fChecked = TRUE;
+ }
+ return fIsUAC;
+
+}
+
typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
static BOOL
@@ -375,6 +441,24 @@ MSSessionKeyToMITKeyblock(KERB_CRYPTO_KEY *mskey, krb5_context context, krb5_key
krb5_copy_keyblock_contents(context, &tmpblock, keyblock);
}
+static BOOL
+IsMSSessionKeyNull(KERB_CRYPTO_KEY *mskey)
+{
+ DWORD i;
+
+ if (is_process_uac_limited())
+ return TRUE;
+
+ if (mskey->KeyType == KERB_ETYPE_NULL)
+ return TRUE;
+
+ for ( i=0; i<mskey->Length; i++ ) {
+ if (mskey->Value[i])
+ return FALSE;
+ }
+
+ return TRUE;
+}
static void
MSFlagsToMITFlags(ULONG msflags, ULONG *mitflags)
@@ -1036,8 +1120,10 @@ KerbSubmitTicket( HANDLE LogonHandle, ULONG PackageId,
krb5_auth_con_getsendsubkey(context, auth_context, &keyblock);
if (keyblock == NULL)
krb5_auth_con_getkey(context, auth_context, &keyblock);
-#ifdef TESTING
- /* do not use this code unless testing the LSA */
+
+ /* make up a key, any key, that can be used to generate the
+ * encrypted KRB_CRED pdu. The Vista release LSA requires
+ * that an enctype other than NULL be used. */
if (keyblock == NULL) {
keyblock = (krb5_keyblock *)malloc(sizeof(krb5_keyblock));
keyblock->enctype = ENCTYPE_ARCFOUR_HMAC;
@@ -1061,7 +1147,6 @@ KerbSubmitTicket( HANDLE LogonHandle, ULONG PackageId,
keyblock->contents[15] = 0xd;
krb5_auth_con_setsendsubkey(context, auth_context, keyblock);
}
-#endif
rc = krb5_mk_1cred(context, auth_context, cred, &krb_cred, &replaydata);
if (rc) {
krb5_auth_con_free(context, auth_context);
@@ -1191,6 +1276,11 @@ GetMSTGT(krb5_context context, HANDLE LogonHandle, ULONG PackageId, KERB_EXTERNA
int ignore_cache = 0;
krb5_enctype *etype_list = NULL, *ptr = NULL, etype = 0;
+ if (is_process_uac_limited()) {
+ Status = STATUS_ACCESS_DENIED;
+ goto cleanup;
+ }
+
memset(&CacheRequest, 0, sizeof(KERB_QUERY_TKT_CACHE_REQUEST));
CacheRequest.MessageType = KerbRetrieveTicketMessage;
CacheRequest.LogonId.LowPart = 0;
@@ -1286,7 +1376,7 @@ GetMSTGT(krb5_context context, HANDLE LogonHandle, ULONG PackageId, KERB_EXTERNA
#else
/* Check Supported Enctypes */
if ( !enforce_tgs_enctypes ||
- pTicketResponse->Ticket.SessionKey.KeyType == KERB_ETYPE_NULL ||
+ IsMSSessionKeyNull(&pTicketResponse->Ticket.SessionKey) ||
krb5_is_permitted_tgs_enctype(context, NULL, pTicketResponse->Ticket.SessionKey.KeyType) ) {
FILETIME Now, MinLife, EndTime, LocalEndTime;
__int64 temp;
@@ -2264,7 +2354,7 @@ krb5_lcc_next_cred(krb5_context context, krb5_ccache id, krb5_cc_cursor *cursor,
}
/* Don't return tickets with NULL Session Keys */
- if ( msticket->SessionKey.KeyType == KERB_ETYPE_NULL) {
+ if ( IsMSSessionKeyNull(&msticket->SessionKey) ) {
LsaFreeReturnBuffer(msticket);
goto next_cred;
}
diff --git a/src/lib/krb5/keytab/Makefile.in b/src/lib/krb5/keytab/Makefile.in
index 0a375c9..176a581 100644
--- a/src/lib/krb5/keytab/Makefile.in
+++ b/src/lib/krb5/keytab/Makefile.in
@@ -150,7 +150,7 @@ kt_memory.so kt_memory.po $(OUTPRE)kt_memory.$(OBJEXT): \
$(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
$(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
$(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
- kt_memory.c
+ kt-int.h kt_memory.c
kt_srvtab.so kt_srvtab.po $(OUTPRE)kt_srvtab.$(OBJEXT): \
$(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
$(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
diff --git a/src/lib/krb5/krb/conv_princ.c b/src/lib/krb5/krb/conv_princ.c
index b0abae3..3a1ca63 100644
--- a/src/lib/krb5/krb/conv_princ.c
+++ b/src/lib/krb5/krb/conv_princ.c
@@ -128,7 +128,7 @@ static const struct krb_convert sconv_list[] = {
* This falls in the "should have been in the ANSI C library"
* category. :-)
*/
-static char *strnchr(register char *s, register char c,
+static char *strnchr(register char *s, register int c,
register unsigned int n)
{
if (n < 1)
diff --git a/src/lib/krb5/krb/gc_frm_kdc.c b/src/lib/krb5/krb/gc_frm_kdc.c
index c936661..4890bad 100644
--- a/src/lib/krb5/krb/gc_frm_kdc.c
+++ b/src/lib/krb5/krb/gc_frm_kdc.c
@@ -462,6 +462,7 @@ find_nxt_kdc(struct tr_state *ts)
if (ts->ntgts > 0) {
/* Punt NXT_TGT from KDC_TGTS if bogus. */
krb5_free_creds(ts->ctx, ts->kdc_tgts[--ts->ntgts]);
+ ts->kdc_tgts[ts->ntgts] = NULL;
}
TR_DBG_RET(ts, "find_nxt_kdc", KRB5_KDCREP_MODIFIED);
return KRB5_KDCREP_MODIFIED;
diff --git a/src/lib/krb5/krb/gen_seqnum.c b/src/lib/krb5/krb/gen_seqnum.c
index 3737640..06564ee 100644
--- a/src/lib/krb5/krb/gen_seqnum.c
+++ b/src/lib/krb5/krb/gen_seqnum.c
@@ -35,14 +35,23 @@
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#endif
+static inline krb5_data
+key2data (krb5_keyblock k)
+{
+ krb5_data d;
+ d.magic = KV5M_DATA;
+ d.length = k.length;
+ d.data = (char *) k.contents;
+ return d;
+}
+
krb5_error_code
krb5_generate_seq_number(krb5_context context, const krb5_keyblock *key, krb5_ui_4 *seqno)
{
krb5_data seed;
krb5_error_code retval;
- seed.length = key->length;
- seed.data = key->contents;
+ seed = key2data(*key);
if ((retval = krb5_c_random_add_entropy(context, KRB5_C_RANDSOURCE_TRUSTEDPARTY, &seed)))
return(retval);
diff --git a/src/lib/krb5/krb/gen_subkey.c b/src/lib/krb5/krb/gen_subkey.c
index 7ffc91f..ad8d4bb 100644
--- a/src/lib/krb5/krb/gen_subkey.c
+++ b/src/lib/krb5/krb/gen_subkey.c
@@ -29,14 +29,23 @@
#include "k5-int.h"
+static inline krb5_data
+key2data (krb5_keyblock k)
+{
+ krb5_data d;
+ d.magic = KV5M_DATA;
+ d.length = k.length;
+ d.data = (char *) k.contents;
+ return d;
+}
+
krb5_error_code
krb5_generate_subkey(krb5_context context, const krb5_keyblock *key, krb5_keyblock **subkey)
{
krb5_error_code retval;
krb5_data seed;
- seed.length = key->length;
- seed.data = key->contents;
+ seed = key2data(*key);
if ((retval = krb5_c_random_add_entropy(context, KRB5_C_RANDSOURCE_TRUSTEDPARTY, &seed)))
return(retval);
diff --git a/src/lib/krb5/krb/get_in_tkt.c b/src/lib/krb5/krb/get_in_tkt.c
index 937cdc4..a4e2b01 100644
--- a/src/lib/krb5/krb/get_in_tkt.c
+++ b/src/lib/krb5/krb/get_in_tkt.c
@@ -1084,8 +1084,21 @@ krb5_get_init_creds(krb5_context context,
* XXX we know they are the same size... and we should do
* something better than just the current time
*/
- request.nonce = (krb5_int32) time_now;
-
+ {
+ unsigned char random_buf[4];
+ krb5_data random_data;
+
+ random_data.length = 4;
+ random_data.data = random_buf;
+ if (krb5_c_random_make_octets(context, &random_data) == 0)
+ /* See RT ticket 3196 at MIT. If we set the high bit, we
+ may have compatibility problems with Heimdal, because
+ we (incorrectly) encode this value as signed. */
+ request.nonce = 0x7fffffff & load_32_n(random_buf);
+ else
+ /* XXX Yuck. Old version. */
+ request.nonce = (krb5_int32) time_now;
+ }
/* give the preauth plugins a chance to prep the request body */
krb5_preauth_prepare_request(context, options, &request);
ret = encode_krb5_kdc_req_body(&request, &encoded_request_body);
@@ -1269,6 +1282,23 @@ krb5_get_init_creds(krb5_context context,
ret = 0;
cleanup:
+ if (ret != 0) {
+ char *client_name;
+ /* See if we can produce a more detailed error message. */
+ switch (ret) {
+ case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN:
+ client_name = NULL;
+ if (krb5_unparse_name(context, client, &client_name) == 0) {
+ krb5_set_error_message(context, ret,
+ "Client '%s' not found in Kerberos database",
+ client_name);
+ free(client_name);
+ }
+ break;
+ default:
+ break;
+ }
+ }
krb5_preauth_request_context_fini(context);
if (encoded_previous_request != NULL) {
krb5_free_data(context, encoded_previous_request);
diff --git a/src/lib/krb5/krb/init_ctx.c b/src/lib/krb5/krb/init_ctx.c
index b80fd50..be20c40 100644
--- a/src/lib/krb5/krb/init_ctx.c
+++ b/src/lib/krb5/krb/init_ctx.c
@@ -234,7 +234,6 @@ init_common (krb5_context *context, krb5_boolean secure, krb5_boolean kdc)
profile_get_integer(ctx->profile, "libdefaults", "ccache_type",
0, DEFAULT_CCACHE_TYPE, &tmp);
ctx->fcc_default_format = tmp + 0x0500;
- ctx->scc_default_format = tmp + 0x0500;
ctx->prompt_types = 0;
ctx->use_conf_ktypes = 0;
diff --git a/src/lib/krb5/krb/mk_cred.c b/src/lib/krb5/krb/mk_cred.c
index 04248c0..cb44647 100644
--- a/src/lib/krb5/krb/mk_cred.c
+++ b/src/lib/krb5/krb/mk_cred.c
@@ -21,7 +21,8 @@
* encrypt the enc_part of krb5_cred
*/
static krb5_error_code
-encrypt_credencpart(krb5_context context, krb5_cred_enc_part *pcredpart, krb5_keyblock *pkeyblock, krb5_enc_data *pencdata)
+encrypt_credencpart(krb5_context context, krb5_cred_enc_part *pcredpart,
+ krb5_keyblock *pkeyblock, krb5_enc_data *pencdata)
{
krb5_error_code retval;
krb5_data * scratch;
@@ -62,7 +63,11 @@ encrypt_credencpart(krb5_context context, krb5_cred_enc_part *pcredpart, krb5_ke
/*----------------------- krb5_mk_ncred_basic -----------------------*/
static krb5_error_code
-krb5_mk_ncred_basic(krb5_context context, krb5_creds **ppcreds, krb5_int32 nppcreds, krb5_keyblock *keyblock, krb5_replay_data *replaydata, krb5_address *local_addr, krb5_address *remote_addr, krb5_cred *pcred)
+krb5_mk_ncred_basic(krb5_context context,
+ krb5_creds **ppcreds, krb5_int32 nppcreds,
+ krb5_keyblock *keyblock, krb5_replay_data *replaydata,
+ krb5_address *local_addr, krb5_address *remote_addr,
+ krb5_cred *pcred)
{
krb5_cred_enc_part credenc;
krb5_error_code retval;
@@ -145,7 +150,9 @@ cleanup:
* outputs an encoded KRB_CRED message suitable for krb5_rd_cred
*/
krb5_error_code KRB5_CALLCONV
-krb5_mk_ncred(krb5_context context, krb5_auth_context auth_context, krb5_creds **ppcreds, krb5_data **ppdata, krb5_replay_data *outdata)
+krb5_mk_ncred(krb5_context context, krb5_auth_context auth_context,
+ krb5_creds **ppcreds, krb5_data **ppdata,
+ krb5_replay_data *outdata)
{
krb5_address * premote_fulladdr = NULL;
krb5_address * plocal_fulladdr = NULL;
@@ -286,7 +293,9 @@ error:
* A convenience function that calls krb5_mk_ncred.
*/
krb5_error_code KRB5_CALLCONV
-krb5_mk_1cred(krb5_context context, krb5_auth_context auth_context, krb5_creds *pcreds, krb5_data **ppdata, krb5_replay_data *outdata)
+krb5_mk_1cred(krb5_context context, krb5_auth_context auth_context,
+ krb5_creds *pcreds, krb5_data **ppdata,
+ krb5_replay_data *outdata)
{
krb5_error_code retval;
krb5_creds **ppcreds;
diff --git a/src/lib/krb5/krb/mk_error.c b/src/lib/krb5/krb/mk_error.c
index 0444a5d..819d29d 100644
--- a/src/lib/krb5/krb/mk_error.c
+++ b/src/lib/krb5/krb/mk_error.c
@@ -38,7 +38,8 @@
returns system errors
*/
krb5_error_code KRB5_CALLCONV
-krb5_mk_error(krb5_context context, const krb5_error *dec_err, krb5_data *enc_err)
+krb5_mk_error(krb5_context context, const krb5_error *dec_err,
+ krb5_data *enc_err)
{
krb5_error_code retval;
krb5_data *new_enc_err;
diff --git a/src/lib/krb5/krb/mk_priv.c b/src/lib/krb5/krb/mk_priv.c
index efe254a..08cbee9 100644
--- a/src/lib/krb5/krb/mk_priv.c
+++ b/src/lib/krb5/krb/mk_priv.c
@@ -32,7 +32,10 @@
#include "auth_con.h"
static krb5_error_code
-krb5_mk_priv_basic(krb5_context context, const krb5_data *userdata, const krb5_keyblock *keyblock, krb5_replay_data *replaydata, krb5_address *local_addr, krb5_address *remote_addr, krb5_pointer i_vector, krb5_data *outbuf)
+krb5_mk_priv_basic(krb5_context context, const krb5_data *userdata,
+ const krb5_keyblock *keyblock, krb5_replay_data *replaydata,
+ krb5_address *local_addr, krb5_address *remote_addr,
+ krb5_pointer i_vector, krb5_data *outbuf)
{
krb5_error_code retval;
krb5_priv privmsg;
diff --git a/src/lib/krb5/krb/mk_rep.c b/src/lib/krb5/krb/mk_rep.c
index 393f634..b512f09 100644
--- a/src/lib/krb5/krb/mk_rep.c
+++ b/src/lib/krb5/krb/mk_rep.c
@@ -40,7 +40,8 @@
*/
krb5_error_code KRB5_CALLCONV
-krb5_mk_rep(krb5_context context, krb5_auth_context auth_context, krb5_data *outbuf)
+krb5_mk_rep(krb5_context context, krb5_auth_context auth_context,
+ krb5_data *outbuf)
{
krb5_error_code retval;
krb5_ap_rep_enc_part repl;
diff --git a/src/lib/krb5/krb/mk_req_ext.c b/src/lib/krb5/krb/mk_req_ext.c
index e5cb43a..6d40e5d 100644
--- a/src/lib/krb5/krb/mk_req_ext.c
+++ b/src/lib/krb5/krb/mk_req_ext.c
@@ -258,7 +258,10 @@ cleanup:
}
static krb5_error_code
-krb5_generate_authenticator(krb5_context context, krb5_authenticator *authent, krb5_principal client, krb5_checksum *cksum, krb5_keyblock *key, krb5_ui_4 seq_number, krb5_authdata **authorization)
+krb5_generate_authenticator(krb5_context context, krb5_authenticator *authent,
+ krb5_principal client, krb5_checksum *cksum,
+ krb5_keyblock *key, krb5_ui_4 seq_number,
+ krb5_authdata **authorization)
{
krb5_error_code retval;
diff --git a/src/lib/krb5/krb/mk_safe.c b/src/lib/krb5/krb/mk_safe.c
index eefcab7..0517f42 100644
--- a/src/lib/krb5/krb/mk_safe.c
+++ b/src/lib/krb5/krb/mk_safe.c
@@ -110,7 +110,9 @@ cleanup_checksum:
}
krb5_error_code KRB5_CALLCONV
-krb5_mk_safe(krb5_context context, krb5_auth_context auth_context, const krb5_data *userdata, krb5_data *outbuf, krb5_replay_data *outdata)
+krb5_mk_safe(krb5_context context, krb5_auth_context auth_context,
+ const krb5_data *userdata, krb5_data *outbuf,
+ krb5_replay_data *outdata)
{
krb5_error_code retval;
krb5_keyblock * keyblock;
diff --git a/src/lib/krb5/krb/preauth2.c b/src/lib/krb5/krb/preauth2.c
index f99ade8..5cd81d8 100644
--- a/src/lib/krb5/krb/preauth2.c
+++ b/src/lib/krb5/krb/preauth2.c
@@ -225,7 +225,7 @@ krb5_preauth_supply_preauth_data(krb5_context context,
const char *attr,
const char *value)
{
- krb5_error_code retval;
+ krb5_error_code retval = 0;
int i;
void *pctx;
const char *emsg = NULL;
@@ -596,6 +596,16 @@ krb5_run_preauth_plugins(krb5_context kcontext,
return 0;
}
+static inline krb5_data
+padata2data(krb5_pa_data p)
+{
+ krb5_data d;
+ d.magic = KV5M_DATA;
+ d.length = p.length;
+ d.data = (char *) p.contents;
+ return d;
+}
+
static
krb5_error_code pa_salt(krb5_context context,
krb5_kdc_req *request,
@@ -609,11 +619,9 @@ krb5_error_code pa_salt(krb5_context context,
{
krb5_data tmp;
- tmp.data = in_padata->contents;
- tmp.length = in_padata->length;
+ tmp = padata2data(*in_padata);
krb5_free_data_contents(context, salt);
krb5int_copy_data_contents(context, &tmp, salt);
-
if (in_padata->pa_type == KRB5_PADATA_AFS3_SALT)
salt->length = SALT_TYPE_AFS_LENGTH;
@@ -1623,7 +1631,7 @@ krb5_do_preauth(krb5_context context,
if (!realdone) {
krb5_init_preauth_context(context);
if (context->preauth_context != NULL) {
- int module_ret, module_flags;
+ int module_ret = 0, module_flags;
#ifdef DEBUG
fprintf (stderr, "trying modules for pa_type %d, flag %d\n",
in_padata[i]->pa_type, paorder[h]);
diff --git a/src/lib/krb5/krb/rd_cred.c b/src/lib/krb5/krb/rd_cred.c
index a29eb05..965ed9a 100644
--- a/src/lib/krb5/krb/rd_cred.c
+++ b/src/lib/krb5/krb/rd_cred.c
@@ -12,7 +12,8 @@
* decrypt the enc_part of a krb5_cred
*/
static krb5_error_code
-decrypt_credencdata(krb5_context context, krb5_cred *pcred, krb5_keyblock *pkeyblock, krb5_cred_enc_part *pcredenc)
+decrypt_credencdata(krb5_context context, krb5_cred *pcred,
+ krb5_keyblock *pkeyblock, krb5_cred_enc_part *pcredenc)
{
krb5_cred_enc_part * ppart = NULL;
krb5_error_code retval;
@@ -51,7 +52,9 @@ cleanup:
/*----------------------- krb5_rd_cred_basic -----------------------*/
static krb5_error_code
-krb5_rd_cred_basic(krb5_context context, krb5_data *pcreddata, krb5_keyblock *pkeyblock, krb5_replay_data *replaydata, krb5_creds ***pppcreds)
+krb5_rd_cred_basic(krb5_context context, krb5_data *pcreddata,
+ krb5_keyblock *pkeyblock, krb5_replay_data *replaydata,
+ krb5_creds ***pppcreds)
{
krb5_error_code retval;
krb5_cred * pcred;
@@ -162,7 +165,9 @@ cleanup_cred:
* outputs the nonce and an array of the forwarded credentials.
*/
krb5_error_code KRB5_CALLCONV
-krb5_rd_cred(krb5_context context, krb5_auth_context auth_context, krb5_data *pcreddata, krb5_creds ***pppcreds, krb5_replay_data *outdata)
+krb5_rd_cred(krb5_context context, krb5_auth_context auth_context,
+ krb5_data *pcreddata, krb5_creds ***pppcreds,
+ krb5_replay_data *outdata)
{
krb5_error_code retval;
krb5_keyblock * keyblock;
@@ -183,19 +188,20 @@ krb5_rd_cred(krb5_context context, krb5_auth_context auth_context, krb5_data *pc
return KRB5_RC_REQUIRED;
-/* If decrypting with the first keyblock we try fails, perhaps the
- * credentials are stored in the session key so try decrypting with
- * that.
-*/
+ /*
+ * If decrypting with the first keyblock we try fails, perhaps the
+ * credentials are stored in the session key so try decrypting with
+ * that.
+ */
if ((retval = krb5_rd_cred_basic(context, pcreddata, keyblock,
&replaydata, pppcreds))) {
if ((retval = krb5_rd_cred_basic(context, pcreddata,
auth_context->keyblock,
&replaydata, pppcreds))) {
return retval;
+ }
}
- }
-
+
if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) {
krb5_donot_replay replay;
krb5_timestamp currenttime;
diff --git a/src/lib/krb5/krb/rd_error.c b/src/lib/krb5/krb/rd_error.c
index e81727c..2c61715 100644
--- a/src/lib/krb5/krb/rd_error.c
+++ b/src/lib/krb5/krb/rd_error.c
@@ -40,7 +40,8 @@
*/
krb5_error_code KRB5_CALLCONV
-krb5_rd_error(krb5_context context, const krb5_data *enc_errbuf, krb5_error **dec_error)
+krb5_rd_error(krb5_context context, const krb5_data *enc_errbuf,
+ krb5_error **dec_error)
{
if (!krb5_is_krb_error(enc_errbuf))
return KRB5KRB_AP_ERR_MSG_TYPE;
diff --git a/src/lib/krb5/krb/rd_priv.c b/src/lib/krb5/krb/rd_priv.c
index cf74807..9d93497 100644
--- a/src/lib/krb5/krb/rd_priv.c
+++ b/src/lib/krb5/krb/rd_priv.c
@@ -55,7 +55,11 @@ Returns system errors, integrity errors.
*/
static krb5_error_code
-krb5_rd_priv_basic(krb5_context context, const krb5_data *inbuf, const krb5_keyblock *keyblock, const krb5_address *local_addr, const krb5_address *remote_addr, krb5_pointer i_vector, krb5_replay_data *replaydata, krb5_data *outbuf)
+krb5_rd_priv_basic(krb5_context context, const krb5_data *inbuf,
+ const krb5_keyblock *keyblock,
+ const krb5_address *local_addr,
+ const krb5_address *remote_addr, krb5_pointer i_vector,
+ krb5_replay_data *replaydata, krb5_data *outbuf)
{
krb5_error_code retval;
krb5_priv * privmsg;
@@ -149,7 +153,9 @@ cleanup_privmsg:;
}
krb5_error_code KRB5_CALLCONV
-krb5_rd_priv(krb5_context context, krb5_auth_context auth_context, const krb5_data *inbuf, krb5_data *outbuf, krb5_replay_data *outdata)
+krb5_rd_priv(krb5_context context, krb5_auth_context auth_context,
+ const krb5_data *inbuf, krb5_data *outbuf,
+ krb5_replay_data *outdata)
{
krb5_error_code retval;
krb5_keyblock * keyblock;
@@ -207,6 +213,7 @@ krb5_rd_priv(krb5_context context, krb5_auth_context auth_context, const krb5_da
}
}
+ memset(&replaydata, 0, sizeof(replaydata));
if ((retval = krb5_rd_priv_basic(context, inbuf, keyblock,
plocal_fulladdr,
premote_fulladdr,
diff --git a/src/lib/krb5/krb/rd_rep.c b/src/lib/krb5/krb/rd_rep.c
index 6742d8a..901de43 100644
--- a/src/lib/krb5/krb/rd_rep.c
+++ b/src/lib/krb5/krb/rd_rep.c
@@ -42,7 +42,8 @@
*/
krb5_error_code KRB5_CALLCONV
-krb5_rd_rep(krb5_context context, krb5_auth_context auth_context, const krb5_data *inbuf, krb5_ap_rep_enc_part **repl)
+krb5_rd_rep(krb5_context context, krb5_auth_context auth_context,
+ const krb5_data *inbuf, krb5_ap_rep_enc_part **repl)
{
krb5_error_code retval;
krb5_ap_rep * reply;
diff --git a/src/lib/krb5/krb/rd_req.c b/src/lib/krb5/krb/rd_req.c
index 9a2f458..28f4f93 100644
--- a/src/lib/krb5/krb/rd_req.c
+++ b/src/lib/krb5/krb/rd_req.c
@@ -46,14 +46,10 @@
*/
krb5_error_code KRB5_CALLCONV
-krb5_rd_req(krb5_context context, krb5_auth_context *auth_context, const krb5_data *inbuf, krb5_const_principal server, krb5_keytab keytab, krb5_flags *ap_req_options, krb5_ticket **ticket)
-
-
-
- /* XXX do we really need this */
-
-
-
+krb5_rd_req(krb5_context context, krb5_auth_context *auth_context,
+ const krb5_data *inbuf, krb5_const_principal server,
+ krb5_keytab keytab, krb5_flags *ap_req_options,
+ krb5_ticket **ticket)
{
krb5_error_code retval;
krb5_ap_req * request;
@@ -85,9 +81,11 @@ krb5_rd_req(krb5_context context, krb5_auth_context *auth_context, const krb5_da
/* Get an rcache if necessary. */
if (((*auth_context)->rcache == NULL)
&& ((*auth_context)->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME)
-&& server) {
+ && server) {
if ((retval = krb5_get_server_rcache(context,
- krb5_princ_component(context,server,0), &(*auth_context)->rcache)))
+ krb5_princ_component(context,
+ server,0),
+ &(*auth_context)->rcache)))
goto cleanup_auth_context;
}
diff --git a/src/lib/krb5/krb/rd_req_dec.c b/src/lib/krb5/krb/rd_req_dec.c
index 6f53b11..a2b275c 100644
--- a/src/lib/krb5/krb/rd_req_dec.c
+++ b/src/lib/krb5/krb/rd_req_dec.c
@@ -61,12 +61,13 @@
static krb5_error_code decrypt_authenticator
(krb5_context, const krb5_ap_req *, krb5_authenticator **,
- int);
+ int);
#define in_clock_skew(date) (labs((date)-currenttime) < context->clockskew)
static krb5_error_code
-krb5_rd_req_decrypt_tkt_part(krb5_context context, const krb5_ap_req *req, krb5_keytab keytab)
+krb5_rd_req_decrypt_tkt_part(krb5_context context, const krb5_ap_req *req,
+ krb5_keytab keytab)
{
krb5_error_code retval;
krb5_enctype enctype;
diff --git a/src/lib/krb5/krb/rd_safe.c b/src/lib/krb5/krb/rd_safe.c
index 15dc6dc..2fa8ec4 100644
--- a/src/lib/krb5/krb/rd_safe.c
+++ b/src/lib/krb5/krb/rd_safe.c
@@ -47,7 +47,11 @@
returns system errors, integrity errors
*/
static krb5_error_code
-krb5_rd_safe_basic(krb5_context context, const krb5_data *inbuf, const krb5_keyblock *keyblock, const krb5_address *recv_addr, const krb5_address *sender_addr, krb5_replay_data *replaydata, krb5_data *outbuf)
+krb5_rd_safe_basic(krb5_context context, const krb5_data *inbuf,
+ const krb5_keyblock *keyblock,
+ const krb5_address *recv_addr,
+ const krb5_address *sender_addr,
+ krb5_replay_data *replaydata, krb5_data *outbuf)
{
krb5_error_code retval;
krb5_safe * message;
@@ -154,7 +158,9 @@ cleanup:
}
krb5_error_code KRB5_CALLCONV
-krb5_rd_safe(krb5_context context, krb5_auth_context auth_context, const krb5_data *inbuf, krb5_data *outbuf, krb5_replay_data *outdata)
+krb5_rd_safe(krb5_context context, krb5_auth_context auth_context,
+ const krb5_data *inbuf, krb5_data *outbuf,
+ krb5_replay_data *outdata)
{
krb5_error_code retval;
krb5_keyblock * keyblock;
@@ -211,6 +217,7 @@ krb5_rd_safe(krb5_context context, krb5_auth_context auth_context, const krb5_da
}
}
+ memset(&replaydata, 0, sizeof(replaydata));
if ((retval = krb5_rd_safe_basic(context, inbuf, keyblock,
plocal_fulladdr, premote_fulladdr,
&replaydata, outbuf))) {
diff --git a/src/lib/krb5/krb/ser_ctx.c b/src/lib/krb5/krb/ser_ctx.c
index d48f61e..e76b650 100644
--- a/src/lib/krb5/krb/ser_ctx.c
+++ b/src/lib/krb5/krb/ser_ctx.c
@@ -117,7 +117,6 @@ krb5_context_size(krb5_context kcontext, krb5_pointer arg, size_t *sizep)
* krb5_int32 for library_options
* krb5_int32 for profile_secure
* krb5_int32 for fcc_default_format
- * krb5_int32 for scc_default_format
* <> for os_context
* <> for db_context
* <> for profile
@@ -282,12 +281,6 @@ krb5_context_externalize(krb5_context kcontext, krb5_pointer arg, krb5_octet **b
if (kret)
return (kret);
- /* Now scc_default_format */
- kret = krb5_ser_pack_int32((krb5_int32) context->scc_default_format,
- &bp, &remain);
- if (kret)
- return (kret);
-
/* Now handle os_context, if appropriate */
if (context->os_context) {
kret = krb5_externalize_opaque(kcontext, KV5M_OS_CONTEXT,
@@ -456,11 +449,6 @@ krb5_context_internalize(krb5_context kcontext, krb5_pointer *argp, krb5_octet *
goto cleanup;
context->fcc_default_format = (int) ibuf;
- /* scc_default_format */
- if ((kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain)))
- goto cleanup;
- context->scc_default_format = (int) ibuf;
-
/* Attempt to read in the os_context. It's an array now, but
we still treat it in most places as a separate object with
a pointer. */
diff --git a/src/lib/krb5/krb/serialize.c b/src/lib/krb5/krb/serialize.c
index 9cbcef7..d3f5258 100644
--- a/src/lib/krb5/krb/serialize.c
+++ b/src/lib/krb5/krb/serialize.c
@@ -58,7 +58,7 @@ krb5_error_code
krb5_register_serializer(krb5_context kcontext, const krb5_ser_entry *entry)
{
krb5_error_code kret;
- krb5_ser_handle stable;
+ krb5_ser_entry * stable;
kret = 0;
/* See if it's already there, if so, we're good to go. */
@@ -66,12 +66,12 @@ krb5_register_serializer(krb5_context kcontext, const krb5_ser_entry *entry)
/*
* Can't find our type. Create a new entry.
*/
- if ((stable = (krb5_ser_handle) malloc(sizeof(krb5_ser_entry) *
- (kcontext->ser_ctx_count+1)))) {
+ if ((stable = (krb5_ser_entry *) malloc(sizeof(krb5_ser_entry) *
+ (kcontext->ser_ctx_count+1)))) {
/* Copy in old table */
if (kcontext->ser_ctx_count)
memcpy(stable, kcontext->ser_ctx,
- sizeof(krb5_ser_entry) * kcontext->ser_ctx_count);
+ sizeof(krb5_ser_entry) * kcontext->ser_ctx_count);
/* Copy in new entry */
memcpy(&stable[kcontext->ser_ctx_count], entry,
sizeof(krb5_ser_entry));
diff --git a/src/lib/krb5/os/an_to_ln.c b/src/lib/krb5/os/an_to_ln.c
index 1df75b1..0d31883 100644
--- a/src/lib/krb5/os/an_to_ln.c
+++ b/src/lib/krb5/os/an_to_ln.c
@@ -47,7 +47,7 @@
#include <regexpr.h>
#endif /* !HAVE_REGCOMP && HAVE_REGEXP_H && HAVE_COMPILE */
-#define MAX_FORMAT_BUFFER 1024
+#define MAX_FORMAT_BUFFER ((size_t)1024)
#ifndef min
#define min(a,b) ((a>b) ? b : a)
#endif /* min */
diff --git a/src/lib/krb5/os/c_ustime.c b/src/lib/krb5/os/c_ustime.c
index c752a4a..fbb6d61 100644
--- a/src/lib/krb5/os/c_ustime.c
+++ b/src/lib/krb5/os/c_ustime.c
@@ -81,6 +81,7 @@ krb5_crypto_us_timeofday(krb5_int32 *seconds, krb5_int32 *microseconds)
struct time_now now;
krb5_error_code err;
+ now.sec = now.usec = 0;
err = get_time_now(&now);
if (err)
return err;
diff --git a/src/lib/krb5/os/hst_realm.c b/src/lib/krb5/os/hst_realm.c
index e660164..7e24b8d 100644
--- a/src/lib/krb5/os/hst_realm.c
+++ b/src/lib/krb5/os/hst_realm.c
@@ -302,12 +302,16 @@ krb5int_translate_gai_error (int num)
return EAFNOSUPPORT;
case EAI_MEMORY:
return ENOMEM;
-#if EAI_NODATA != EAI_NONAME
+#if defined(EAI_NODATA) && EAI_NODATA != EAI_NONAME
case EAI_NODATA:
return KRB5_EAI_NODATA;
#endif
case EAI_NONAME:
return KRB5_EAI_NONAME;
+#if defined(EAI_OVERFLOW)
+ case EAI_OVERFLOW:
+ return EINVAL; /* XXX */
+#endif
case EAI_SERVICE:
return KRB5_EAI_SERVICE;
case EAI_SOCKTYPE:
diff --git a/src/lib/krb5/os/init_os_ctx.c b/src/lib/krb5/os/init_os_ctx.c
index beb697a..d692fb2 100644
--- a/src/lib/krb5/os/init_os_ctx.c
+++ b/src/lib/krb5/os/init_os_ctx.c
@@ -336,7 +336,7 @@ os_init_paths(krb5_context ctx, krb5_boolean kdc)
retval = os_get_default_config_files(&files, secure);
- if (retval == 0)
+ if (retval == 0 && kdc)
retval = add_kdc_config_file(&files);
if (!retval) {
diff --git a/src/lib/krb5/os/locate_kdc.c b/src/lib/krb5/os/locate_kdc.c
index 059a5c1..566213d 100644
--- a/src/lib/krb5/os/locate_kdc.c
+++ b/src/lib/krb5/os/locate_kdc.c
@@ -157,13 +157,18 @@ static int translate_ai_error (int err)
#ifdef EAI_ADDRFAMILY
case EAI_ADDRFAMILY:
#endif
-#if EAI_NODATA != EAI_NONAME
+#if defined(EAI_NODATA) && EAI_NODATA != EAI_NONAME
case EAI_NODATA:
#endif
case EAI_NONAME:
/* Name not known or no address data, but no error. Do
nothing more. */
return 0;
+#ifdef EAI_OVERFLOW
+ case EAI_OVERFLOW:
+ /* An argument buffer overflowed. */
+ return EINVAL; /* XXX */
+#endif
#ifdef EAI_SYSTEM
case EAI_SYSTEM:
/* System error, obviously. */
@@ -786,28 +791,28 @@ krb5int_locate_server (krb5_context context, const krb5_data *realm,
code = module_locate_server(context, realm, &al, svc, socktype, family);
Tprintf("module_locate_server returns %d\n", code);
- if (code != KRB5_PLUGIN_NO_HANDLE) {
- *addrlist = al;
- return code;
- }
-
- /*
- * We always try the local file before DNS
- */
-
- code = prof_locate_server(context, realm, &al, svc, socktype, family);
+ if (code == KRB5_PLUGIN_NO_HANDLE) {
+ /*
+ * We always try the local file before DNS. Note that there
+ * is no way to indicate "service not available" via the
+ * config file.
+ */
- /* We could put more heuristics here, like looking up a hostname
- of "kerberos."+REALM, etc. */
+ code = prof_locate_server(context, realm, &al, svc, socktype, family);
#ifdef KRB5_DNS_LOOKUP
- if (code) {
- krb5_error_code code2;
- code2 = dns_locate_server(context, realm, &al, svc, socktype, family);
- if (code2 != KRB5_PLUGIN_NO_HANDLE)
- code = code2;
- }
+ if (code) { /* Try DNS for all profile errors? */
+ krb5_error_code code2;
+ code2 = dns_locate_server(context, realm, &al, svc, socktype,
+ family);
+ if (code2 != KRB5_PLUGIN_NO_HANDLE)
+ code = code2;
+ }
#endif /* KRB5_DNS_LOOKUP */
+
+ /* We could put more heuristics here, like looking up a hostname
+ of "kerberos."+REALM, etc. */
+ }
if (code == 0)
Tprintf ("krb5int_locate_server found %d addresses\n",
al.naddrs);
diff --git a/src/lib/krb5/os/sendto_kdc.c b/src/lib/krb5/os/sendto_kdc.c
index 764aafe..a476ef4 100644
--- a/src/lib/krb5/os/sendto_kdc.c
+++ b/src/lib/krb5/os/sendto_kdc.c
@@ -66,12 +66,14 @@ int krb5int_debug_sendto_kdc = 0;
static void default_debug_handler (const void *data, size_t len)
{
#if 0
- FILE *logfile;
- logfile = fopen("/tmp/sendto_kdc.log", "a");
- if (logfile == NULL)
- return;
+ static FILE *logfile;
+ if (logfile == NULL) {
+ logfile = fopen("/tmp/sendto_kdc.log", "a");
+ if (logfile == NULL)
+ return;
+ setbuf(logfile, NULL);
+ }
fwrite(data, 1, len, logfile);
- fclose(logfile);
#else
fwrite(data, 1, len, stderr);
/* stderr is unbuffered */
@@ -124,9 +126,21 @@ krb5int_debug_fprint (const char *fmt, ...)
for (; *fmt; fmt++) {
if (*fmt != '%') {
- /* Possible optimization: Look for % and print all chars
- up to it in one call. */
- put(fmt, 1);
+ const char *fmt2;
+ size_t len;
+ for (fmt2 = fmt+1; *fmt2; fmt2++)
+ if (*fmt2 == '%')
+ break;
+ len = fmt2 - fmt;
+ if (0) {
+ FILE *f = fopen("/dev/pts/0", "w+");
+ if (f) {
+ fprintf(f, "krb5int_debug_fprint: format <%s> fmt2 <%s> put %lu next <%s>\n",
+ fmt, fmt2, (unsigned long) len, fmt+len-1);
+ }
+ }
+ put(fmt, len);
+ fmt += len - 1; /* then fmt++ in loop header */
continue;
}
/* After this, always processing a '%' sequence. */
@@ -383,7 +397,8 @@ krb5_sendto_kdc (krb5_context context, const krb5_data *message,
if (addrs.naddrs > 0) {
retval = krb5int_sendto (context, message, &addrs, 0, reply, 0, 0,
0, 0, &addr_used);
- if (retval == 0) {
+ switch (retval) {
+ case 0:
/*
* Set use_master to 1 if we ended up talking to a master when
* we didn't explicitly request to
@@ -401,7 +416,15 @@ krb5_sendto_kdc (krb5_context context, const krb5_data *message,
}
krb5int_free_addrlist (&addrs);
return 0;
- }
+ default:
+ break;
+ /* Cases here are for constructing useful error messages. */
+ case KRB5_KDC_UNREACH:
+ krb5_set_error_message(context, retval,
+ "Cannot contact any KDC for realm '%.*s'",
+ realm->length, realm->data);
+ break;
+ }
krb5int_free_addrlist (&addrs);
}
return retval;
@@ -1022,10 +1045,15 @@ service_fds (struct select_state *selstate,
int e, selret;
e = 0;
- while (selstate->nfds > 0
- && (e = krb5int_cm_call_select(selstate, seltemp, &selret)) == 0) {
+ while (selstate->nfds > 0) {
int i;
+ e = krb5int_cm_call_select(selstate, seltemp, &selret);
+ if (e == EINTR)
+ continue;
+ if (e != 0)
+ break;
+
dprint("service_fds examining results, selret=%d\n", selret);
if (selret == 0)
diff --git a/src/plugins/kdb/db2/Makefile.in b/src/plugins/kdb/db2/Makefile.in
index ea949d7..84511a3 100644
--- a/src/plugins/kdb/db2/Makefile.in
+++ b/src/plugins/kdb/db2/Makefile.in
@@ -1,6 +1,6 @@
-thisconfigdir=.
+thisconfigdir=../../..
myfulldir=plugins/kdb/db2
-mydir=.
+mydir=plugins/kdb/db2
BUILDTOP=$(REL)..$(S)..$(S)..
KRB5_RUN_ENV = @KRB5_RUN_ENV@
KRB5_CONFIG_SETUP = KRB5_CONFIG=$(SRCTOP)/config-files/krb5.conf ; export KRB5_CONFIG ;
@@ -9,6 +9,11 @@ PROG_RPATH=$(KRB5_LIBDIR)
MODULE_INSTALL_DIR = $(KRB5_DB_MODULE_DIR)
DEFS=
+SUBDIRS= $(SUBDIRS-@DB_VERSION@)
+SUBDIRS-sys=
+SUBDIRS-redirect=
+SUBDIRS-k5= libdb2
+
LOCALINCLUDES = -I../../../lib/kdb -I$(srcdir)/../../../lib/kdb
DEFINES = -DPLUGIN
@@ -34,7 +39,7 @@ SHLIB_EXPDEPS = \
$(GSSRPC_DEPLIBS) \
$(TOPLIBD)/libk5crypto$(SHLIBEXT) \
$(TOPLIBD)/libkrb5$(SHLIBEXT)
-SHLIB_EXPLIBS= $(GSSRPC_LIBS) -lkrb5 -lcom_err -lk5crypto $(KDB5_DB_LIB) $(SUPPORT_LIB) $(LIBS)
+SHLIB_EXPLIBS= $(GSSRPC_LIBS) -lkrb5 -lcom_err -lk5crypto $(KDB5_DB_LIB) $(SUPPORT_LIB) $(LIBS) @DB_EXTRA_LIBS@
SHLIB_DIRS=-L$(TOPLIBD)
SHLIB_RDIRS=$(KRB5_LIBDIR)
diff --git a/src/plugins/kdb/db2/configure.in b/src/plugins/kdb/db2/configure.in
deleted file mode 100644
index 9f958db..0000000
--- a/src/plugins/kdb/db2/configure.in
+++ /dev/null
@@ -1,27 +0,0 @@
-K5_AC_INIT(configure.in)
-enable_shared=yes
-build_dynobj=yes
-CONFIG_RULES
-AC_CHECK_HEADERS(unistd.h)
-AC_TYPE_MODE_T
-AC_TYPE_OFF_T
-
-AC_CHECK_FUNCS(srand48 srand srandom umask)
-
-dnl AIX is unusual in that it wants all symbols resolved at link time
-dnl Fortunately, it will allow us to link the kdb library now, even if
-dnl it is linked again later.
-case $krb5_cv_host in
-*-*-aix*)
- LIBS="$LIBS -ldb"
- ;;
-esac
-KRB5_RUN_FLAGS
-dnl The following is for check...
-KRB5_BUILD_PROGRAM
-KRB5_BUILD_LIBOBJS
-KRB5_BUILD_LIBRARY_WITH_DEPS
-if test "$DB_VERSION" = k5 ; then
- AC_CONFIG_SUBDIRS(libdb2)
-fi
-V5_AC_OUTPUT_MAKEFILE
diff --git a/src/plugins/kdb/db2/libdb2/Makefile.in b/src/plugins/kdb/db2/libdb2/Makefile.in
index c993f34..77326a2 100644
--- a/src/plugins/kdb/db2/libdb2/Makefile.in
+++ b/src/plugins/kdb/db2/libdb2/Makefile.in
@@ -40,4 +40,5 @@ $(srcdir)/include/autoconf.stmp: $(srcdir)/configure.in $(SRCTOP)/aclocal.m4
clean-includes::
$(RM) $(HDRS) include/*.stmp
+@libnodeps_frag@
@lib_frag@
diff --git a/src/plugins/kdb/db2/libdb2/configure.in b/src/plugins/kdb/db2/libdb2/configure.in
index 5c0455e..a1b00d3 100644
--- a/src/plugins/kdb/db2/libdb2/configure.in
+++ b/src/plugins/kdb/db2/libdb2/configure.in
@@ -1,6 +1,5 @@
K5_AC_INIT(db/db.c)
AC_CONFIG_HEADER(include/config.h include/db-config.h)
-build_dynobj=yes
CONFIG_RULES
AC_PATH_PROG(FALSE,false,:)
diff --git a/src/plugins/kdb/ldap/libkdb_ldap/Makefile.in b/src/plugins/kdb/ldap/libkdb_ldap/Makefile.in
index 301f359..7aa0f3b 100644
--- a/src/plugins/kdb/ldap/libkdb_ldap/Makefile.in
+++ b/src/plugins/kdb/ldap/libkdb_ldap/Makefile.in
@@ -31,7 +31,7 @@ SHLIB_EXPDEPS = \
$(TOPLIBD)/libk5crypto$(SHLIBEXT) \
$(SUPPORT_DEPLIB) \
$(TOPLIBD)/libkrb5$(SHLIBEXT)
-SHLIB_EXPLIBS= $(GSSRPC_LIBS) -lkrb5 -lk5crypto $(COM_ERR_LIB) $(SUPPORT_LIB) @LDAP_LIBS@ $(LIBS)
+SHLIB_EXPLIBS= $(KADMSRV_LIBS) -lkrb5 -lk5crypto $(COM_ERR_LIB) $(SUPPORT_LIB) @LDAP_LIBS@ $(LIBS)
SHLIB_DIRS=-L$(TOPLIBD)
SHLIB_RDIRS=$(KRB5_LIBDIR)
diff --git a/src/plugins/kdb/ldap/libkdb_ldap/configure.in b/src/plugins/kdb/ldap/libkdb_ldap/configure.in
index aee6916..61271a8 100644
--- a/src/plugins/kdb/ldap/libkdb_ldap/configure.in
+++ b/src/plugins/kdb/ldap/libkdb_ldap/configure.in
@@ -31,6 +31,6 @@ KRB5_RUN_FLAGS
dnl The following is for check...
KRB5_BUILD_PROGRAM
KRB5_BUILD_LIBOBJS
-KRB5_BUILD_LIBRARY_WITH_DEPS
+KRB5_BUILD_LIBRARY
dnl
V5_AC_OUTPUT_MAKEFILE
diff --git a/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c b/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c
index 7725648..c25804b 100644
--- a/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c
+++ b/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c
@@ -194,7 +194,6 @@ krb5_ldap_iterate(context, match_expr, func, func_arg)
for (ent=ldap_first_entry(ld, result); ent != NULL; ent=ldap_next_entry(ld, ent)) {
if ((values=ldap_get_values(ld, ent, "krbprincipalname")) != NULL) {
for (i=0; values[i] != NULL; ++i) {
- if (values[i])
if (krb5_ldap_parse_principal_name(values[i], &princ_name) != 0)
continue;
if (krb5_parse_name(context, princ_name, &principal) != 0)
diff --git a/src/plugins/locate/python/Makefile.in b/src/plugins/locate/python/Makefile.in
index 3804432..ab36991 100644
--- a/src/plugins/locate/python/Makefile.in
+++ b/src/plugins/locate/python/Makefile.in
@@ -1,6 +1,6 @@
-thisconfigdir=.
+thisconfigdir=../../..
myfulldir=plugins/locate/python
-mydir=.
+mydir=plugins/locate/python
BUILDTOP=$(REL)..$(S)..$(S)..
LIBBASE=python
@@ -10,8 +10,8 @@ SO_EXT=.so
RELDIR=../plugins/locate/python
MODULE_INSTALL_DIR = $(KRB5_LIBKRB5_MODULE_DIR)
-SHLIB_EXPDEPS= $(KRB5_DEPLIB)
-SHLIB_EXPLIBS= -lpython2.3 $(KRB5_LIB)
+SHLIB_EXPDEPS= $(KRB5_DEPLIB) $(SUPPORT_DEPLIB)
+SHLIB_EXPLIBS= -lpython2.3 $(KRB5_LIB) $(SUPPORT_LIB)
SHLIB_DIRS=-L$(TOPLIBD)
SHLIB_RDIRS=$(KRB5_LIBDIR)
diff --git a/src/plugins/locate/python/configure.in b/src/plugins/locate/python/configure.in
deleted file mode 100644
index 34f8306..0000000
--- a/src/plugins/locate/python/configure.in
+++ /dev/null
@@ -1,10 +0,0 @@
-K5_AC_INIT(configure.in)
-enable_shared=yes
-build_dynobj=yes
-CONFIG_RULES
-AC_CHECK_HEADERS(Python.h python2.3/Python.h)
-dnl AC_CHECK_LIB(python2.3)
-
-KRB5_BUILD_LIBOBJS
-KRB5_BUILD_LIBRARY_WITH_DEPS
-V5_AC_OUTPUT_MAKEFILE
diff --git a/src/plugins/locate/python/py-locate.c b/src/plugins/locate/python/py-locate.c
index 37342ac..4f840fc 100644
--- a/src/plugins/locate/python/py-locate.c
+++ b/src/plugins/locate/python/py-locate.c
@@ -61,6 +61,7 @@
/* Include Python.h before autoconf.h, because our autoconf.h seems
to confuse Python's headers. */
+#include <autoconf.h>
#if HAVE_PYTHON_H
#include <Python.h>
#elif HAVE_PYTHON2_3_PYTHON_H
@@ -68,7 +69,6 @@
#else
#error "Where's the Python header file?"
#endif
-#include <autoconf.h>
#include <errno.h>
#include "k5-platform.h" /* for init/fini macros */
#include "fake-addrinfo.h"
diff --git a/src/plugins/preauth/cksum_body/configure.in b/src/plugins/preauth/cksum_body/configure.in
index 868dfd5..53870b5 100644
--- a/src/plugins/preauth/cksum_body/configure.in
+++ b/src/plugins/preauth/cksum_body/configure.in
@@ -1,6 +1,4 @@
K5_AC_INIT(configure.in)
-enable_shared=yes
-build_dynobj=yes
CONFIG_RULES
AC_CHECK_HEADERS(errno.h string.h)
@@ -9,6 +7,6 @@ KRB5_RUN_FLAGS
dnl The following is for check...
KRB5_BUILD_PROGRAM
KRB5_BUILD_LIBOBJS
-KRB5_BUILD_LIBRARY_WITH_DEPS
+KRB5_BUILD_LIBRARY
AC_CONFIG_HEADERS(config.h)
V5_AC_OUTPUT_MAKEFILE
diff --git a/src/plugins/preauth/pkinit/configure.in b/src/plugins/preauth/pkinit/configure.in
index 59ece38..5819289 100644
--- a/src/plugins/preauth/pkinit/configure.in
+++ b/src/plugins/preauth/pkinit/configure.in
@@ -15,5 +15,5 @@ KRB5_RUN_FLAGS
dnl The following is for check...
KRB5_BUILD_PROGRAM
KRB5_BUILD_LIBOBJS
-KRB5_BUILD_LIBRARY_WITH_DEPS
+KRB5_BUILD_LIBRARY
V5_AC_OUTPUT_MAKEFILE
diff --git a/src/plugins/preauth/wpse/configure.in b/src/plugins/preauth/wpse/configure.in
index 868dfd5..53870b5 100644
--- a/src/plugins/preauth/wpse/configure.in
+++ b/src/plugins/preauth/wpse/configure.in
@@ -1,6 +1,4 @@
K5_AC_INIT(configure.in)
-enable_shared=yes
-build_dynobj=yes
CONFIG_RULES
AC_CHECK_HEADERS(errno.h string.h)
@@ -9,6 +7,6 @@ KRB5_RUN_FLAGS
dnl The following is for check...
KRB5_BUILD_PROGRAM
KRB5_BUILD_LIBOBJS
-KRB5_BUILD_LIBRARY_WITH_DEPS
+KRB5_BUILD_LIBRARY
AC_CONFIG_HEADERS(config.h)
V5_AC_OUTPUT_MAKEFILE
diff --git a/src/t_krbconf b/src/t_krbconf
index caca81d..9fe898c 100644
--- a/src/t_krbconf
+++ b/src/t_krbconf
@@ -24,15 +24,15 @@
echo "Testing if krb5-config outputs shell variables"
echo " Testing --libs argument"
-if `./krb5-config --libs kdb | egrep -s '\\$'`; then
- echo "Error './krb5-config --libs kdb' contains shell variables";
- exit 1;
+if ./krb5-config --libs kdb | egrep -s '\$' > /dev/null; then
+ echo "Error './krb5-config --libs kdb' contains shell variables"
+ exit 1
fi
echo " Testing --cflags argument"
-if `./krb5-config --cflags | egrep -s '\\$'`; then \
- echo "Error './krb5-config --cflags' contains shell variables"; \
- exit 1; \
+if ./krb5-config --cflags | egrep -s '\$' > /dev/null; then
+ echo "Error './krb5-config --cflags' contains shell variables"
+ exit 1
fi
echo "krb5-config tests pass"
exit 0
diff --git a/src/tests/Makefile.in b/src/tests/Makefile.in
index 89cbb04..a02346c 100644
--- a/src/tests/Makefile.in
+++ b/src/tests/Makefile.in
@@ -1,5 +1,5 @@
-thisconfigdir=.
-mydir=.
+thisconfigdir=..
+mydir=tests
myfulldir=tests
BUILDTOP=$(REL)..
LOCAL_SUBDIRS = resolve asn.1 create hammer verify gssapi dejagnu shlib \
diff --git a/src/tests/asn.1/Makefile.in b/src/tests/asn.1/Makefile.in
index 202153b..7c7b1b1 100644
--- a/src/tests/asn.1/Makefile.in
+++ b/src/tests/asn.1/Makefile.in
@@ -1,6 +1,6 @@
-thisconfigdir=./..
+thisconfigdir=../..
myfulldir=tests/asn.1
-mydir=asn.1
+mydir=tests/asn.1
BUILDTOP=$(REL)..$(S)..
PROG_LIBPATH=-L$(TOPLIBD)
PROG_RPATH=$(KRB5_LIBDIR)
diff --git a/src/tests/configure.in b/src/tests/configure.in
deleted file mode 100644
index 9b8619b..0000000
--- a/src/tests/configure.in
+++ /dev/null
@@ -1,30 +0,0 @@
-K5_AC_INIT(configure.in)
-CONFIG_RULES
-KRB5_RUN_FLAGS
-KRB5_BUILD_PROGRAM
-dnl Set krb5_cv_host
-KRB5_LIB_PARAMS
-dnl
-AC_HEADER_STDC
-AC_CHECK_FUNCS(strchr sem_init sem_trywait)
-AC_CHECK_HEADERS(unistd.h stdlib.h sys/param.h sys/socket.h dlfcn.h semaphore.h)
-AC_C_CONST
-AC_PROG_INSTALL
-AC_CHECK_PROG(RUNTEST,runtest,runtest)
-if test x"$RUNTEST" != x; then
- HAVE_RUNTEST=yes
-else
- HAVE_RUNTEST=no
-fi
-AC_SUBST(HAVE_RUNTEST)
-AC_TYPE_SIGNAL
-CHECK_SIGNALS
-if test "$KRB4_LIB" = ''; then
- KRB4_DEJAGNU_TEST="KRBIV=0"
-else
- AC_MSG_RESULT(Kerberos 4 testing enabled)
- KRB4_DEJAGNU_TEST="KRBIV=1"
-fi
-AC_SUBST(KRB4_DEJAGNU_TEST)
-KRB5_AC_PRIOCNTL_HACK
-V5_AC_OUTPUT_MAKEFILE(. resolve asn.1 create hammer verify gssapi dejagnu threads shlib gss-threads misc)
diff --git a/src/tests/create/Makefile.in b/src/tests/create/Makefile.in
index ff7aa88..ae41e1d 100644
--- a/src/tests/create/Makefile.in
+++ b/src/tests/create/Makefile.in
@@ -1,6 +1,6 @@
-thisconfigdir=./..
+thisconfigdir=../..
myfulldir=tests/create
-mydir=create
+mydir=tests/create
BUILDTOP=$(REL)..$(S)..
PROG_LIBPATH=-L$(TOPLIBD)
PROG_RPATH=$(KRB5_LIBDIR)
diff --git a/src/tests/dejagnu/Makefile.in b/src/tests/dejagnu/Makefile.in
index 61fbed0..75db997 100644
--- a/src/tests/dejagnu/Makefile.in
+++ b/src/tests/dejagnu/Makefile.in
@@ -1,6 +1,6 @@
-thisconfigdir=./..
+thisconfigdir=../..
myfulldir=tests/dejagnu
-mydir=dejagnu
+mydir=tests/dejagnu
BUILDTOP=$(REL)..$(S)..
RUNTEST = @RUNTEST@ $(DEJAFLAGS)
RUNTESTFLAGS =
@@ -51,4 +51,5 @@ site.exp: runenv.vals Makefile
# Makefile dependencies follow. This must be the last section in
# the Makefile.in file
#
-$(OUTPRE)t_inetd.$(OBJEXT): $(COM_ERR_DEPS) t_inetd.c
+$(OUTPRE)t_inetd.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+ $(COM_ERR_DEPS) t_inetd.c
diff --git a/src/tests/dejagnu/config/default.exp b/src/tests/dejagnu/config/default.exp
index 0c40553..e2695d0 100644
--- a/src/tests/dejagnu/config/default.exp
+++ b/src/tests/dejagnu/config/default.exp
@@ -83,7 +83,8 @@ if { [string length $VALGRIND] } {
set inflags 0
# Only run valgrind for local programs, not
# system ones.
- if [string match "/" [string index $arg 0]]&&![string match "/bin/sh" $arg]&&![string match "/bin/ls" $arg]&&![regexp {/kshd$} $arg] {
+#&&![string match "/bin/sh" $arg] sh is used to start kadmind!
+ if [string match "/" [string index $arg 0]]&&![string match "/bin/ls" $arg]&&![regexp {/kshd$} $arg] {
set newargs [concat $newargs $VALGRIND]
}
}
@@ -179,18 +180,6 @@ set passes {
{dummy=[verbose -log "AES + DES enctypes"]}
}
{
- aesonly
- mode=udp
- des3_krbtgt=0
- {supported_enctypes=aes256-cts-hmac-sha1-96:normal}
- {kdc_supported_enctypes=aes256-cts-hmac-sha1-96:normal}
- {permitted_enctypes(kdc)=aes256-cts-hmac-sha1-96}
- {permitted_enctypes(client)=aes256-cts-hmac-sha1-96}
- {permitted_enctypes(server)=aes256-cts-hmac-sha1-96}
- {master_key_type=aes256-cts-hmac-sha1-96}
- {dummy=[verbose -log "AES enctypes"]}
- }
- {
aes-tcp
mode=tcp
des3_krbtgt=0
@@ -362,18 +351,6 @@ set unused_passes {
}
{dummy=[verbose -log "DES3 TGT, default enctypes"]}
}
- # This won't work for anything using GSSAPI until it gets AES support.
- {
- aes-only
- des3_krbtgt=0
- {supported_enctypes=aes256-cts-hmac-sha1-96:normal}
- {kdc_supported_enctypes=aes256-cts-hmac-sha1-96:normal}
- {permitted_enctypes(kdc)=aes256-cts-hmac-sha1-96}
- {permitted_enctypes(client)=aes256-cts-hmac-sha1-96}
- {permitted_enctypes(server)=aes256-cts-hmac-sha1-96}
- {master_key_type=aes256-cts-hmac-sha1-96}
- {dummy=[verbose -log "AES only, no DES or DES3 support"]}
- }
}
# {supported_enctypes=des-cbc-md5:normal des-cbc-crc:normal twofish256-hmac-sha1:normal }
# {kdc_supported_enctypes= des-cbc-md5:normal des-cbc-crc:normal twofish256-hmac-sha1:normal}
diff --git a/src/tests/dejagnu/t_inetd.c b/src/tests/dejagnu/t_inetd.c
index 80835b5..6dc91cb 100644
--- a/src/tests/dejagnu/t_inetd.c
+++ b/src/tests/dejagnu/t_inetd.c
@@ -33,7 +33,7 @@
*
*/
-
+#include "autoconf.h"
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
diff --git a/src/tests/gss-threads/Makefile.in b/src/tests/gss-threads/Makefile.in
index b95cbcd..2435704 100644
--- a/src/tests/gss-threads/Makefile.in
+++ b/src/tests/gss-threads/Makefile.in
@@ -1,8 +1,8 @@
# Derived from appl/gss-sample, January 2005.
-thisconfigdir=./..
+thisconfigdir=../..
myfulldir=tests/gss-threads
-mydir=gss-threads
+mydir=tests/gss-threads
BUILDTOP=$(REL)..$(S)..
DEFINES = -DUSE_AUTOCONF_H -DGSSAPI_V2
PROG_LIBPATH=-L$(TOPLIBD)
diff --git a/src/tests/gss-threads/gss-server.c b/src/tests/gss-threads/gss-server.c
index 6cbac84..922a016 100644
--- a/src/tests/gss-threads/gss-server.c
+++ b/src/tests/gss-threads/gss-server.c
@@ -55,6 +55,7 @@
#include <pthread.h>
#include <signal.h>
#endif
+#include "autoconf.h"
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
diff --git a/src/tests/gssapi/Makefile.in b/src/tests/gssapi/Makefile.in
index 846a241..19c6fd3 100644
--- a/src/tests/gssapi/Makefile.in
+++ b/src/tests/gssapi/Makefile.in
@@ -1,6 +1,6 @@
-thisconfigdir=./..
+thisconfigdir=../..
myfulldir=tests/gssapi
-mydir=gssapi
+mydir=tests/gssapi
BUILDTOP=$(REL)..$(S)..
DEFINES = -DUSE_AUTOCONF_H
PROG_LIBPATH=-L$(TOPLIBD)
diff --git a/src/tests/hammer/Makefile.in b/src/tests/hammer/Makefile.in
index 4bf6153..0c499ef 100644
--- a/src/tests/hammer/Makefile.in
+++ b/src/tests/hammer/Makefile.in
@@ -1,6 +1,6 @@
-thisconfigdir=./..
+thisconfigdir=../..
myfulldir=tests/hammer
-mydir=hammer
+mydir=tests/hammer
BUILDTOP=$(REL)..$(S)..
PROG_LIBPATH=-L$(TOPLIBD)
PROG_RPATH=$(KRB5_LIBDIR)
diff --git a/src/tests/misc/Makefile.in b/src/tests/misc/Makefile.in
index a22acde..0dc4260 100644
--- a/src/tests/misc/Makefile.in
+++ b/src/tests/misc/Makefile.in
@@ -1,6 +1,6 @@
-thisconfigdir=./..
+thisconfigdir=../..
myfulldir=tests/misc
-mydir=misc
+mydir=tests/misc
BUILDTOP=$(REL)..$(S)..
RUN_SETUP = @KRB5_RUN_ENV@
PROG_LIBPATH=-L$(TOPLIBD)
diff --git a/src/tests/resolve/Makefile.in b/src/tests/resolve/Makefile.in
index 65981d2..2f08156 100644
--- a/src/tests/resolve/Makefile.in
+++ b/src/tests/resolve/Makefile.in
@@ -1,6 +1,6 @@
-thisconfigdir=./..
+thisconfigdir=../..
myfulldir=tests/resolve
-mydir=resolve
+mydir=tests/resolve
BUILDTOP=$(REL)..$(S)..
RUN_SETUP = @KRB5_RUN_ENV@
PROG_LIBPATH=-L$(TOPLIBD)
@@ -21,7 +21,7 @@ addrinfo-test: addrinfo-test.o
fake-addrinfo-test: fake-addrinfo-test.o
$(CC_LINK) -o $@ fake-addrinfo-test.o $(SUPPORT_LIB) $(LIBS)
-check:: resolve addrinfo-test
+check:: resolve addrinfo-test fake-addrinfo-test
$(RUN_SETUP) $(VALGRIND) ./resolve
$(RUN_SETUP) $(VALGRIND) ./addrinfo-test -p telnet
$(RUN_SETUP) $(VALGRIND) ./fake-addrinfo-test -p telnet
@@ -29,14 +29,15 @@ check:: resolve addrinfo-test
install::
clean::
- $(RM) resolve addrinfo-test
+ $(RM) resolve addrinfo-test fake-addrinfo-test
# +++ Dependency line eater +++
#
# Makefile dependencies follow. This must be the last section in
# the Makefile.in file
#
-$(OUTPRE)resolve.$(OBJEXT): resolve.c
+$(OUTPRE)resolve.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+ resolve.c
$(OUTPRE)addrinfo-test.$(OBJEXT): addrinfo-test.c
$(OUTPRE)fake-addrinfo-test.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
$(SRCTOP)/include/fake-addrinfo.h $(SRCTOP)/include/k5-platform.h \
diff --git a/src/tests/resolve/resolve.c b/src/tests/resolve/resolve.c
index b1fe969..62768af 100644
--- a/src/tests/resolve/resolve.c
+++ b/src/tests/resolve/resolve.c
@@ -41,6 +41,7 @@
/* This program tests the resolve library and sees if it is broken... */
+#include "autoconf.h"
#include <stdio.h>
#if STDC_HEADERS
diff --git a/src/tests/shlib/Makefile.in b/src/tests/shlib/Makefile.in
index 523dd12..6b8bb6f 100644
--- a/src/tests/shlib/Makefile.in
+++ b/src/tests/shlib/Makefile.in
@@ -1,6 +1,6 @@
-thisconfigdir=./..
+thisconfigdir=../..
myfulldir=tests/shlib
-mydir=shlib
+mydir=tests/shlib
BUILDTOP=$(REL)..$(S)..
PROG_LIBPATH=-L$(TOPLIBD)
PROG_RPATH=$(KRB5_LIBDIR)
diff --git a/src/tests/threads/Makefile.in b/src/tests/threads/Makefile.in
index b6da0b0..62ba589 100644
--- a/src/tests/threads/Makefile.in
+++ b/src/tests/threads/Makefile.in
@@ -1,6 +1,6 @@
-thisconfigdir=./..
+thisconfigdir=../..
myfulldir=tests/threads
-mydir=threads
+mydir=tests/threads
BUILDTOP=$(REL)..$(S)..
PROG_LIBPATH=-L$(TOPLIBD)
PROG_RPATH=$(KRB5_LIBDIR)
diff --git a/src/tests/verify/Makefile.in b/src/tests/verify/Makefile.in
index 6ede305..61b78f9 100644
--- a/src/tests/verify/Makefile.in
+++ b/src/tests/verify/Makefile.in
@@ -1,6 +1,6 @@
-thisconfigdir=./..
+thisconfigdir=../..
myfulldir=tests/verify
-mydir=verify
+mydir=tests/verify
BUILDTOP=$(REL)..$(S)..
PROG_LIBPATH=-L$(TOPLIBD)
PROG_RPATH=$(KRB5_LIBDIR)
diff --git a/src/util/et/com_err.c b/src/util/et/com_err.c
index 5a274d2..c759e17 100644
--- a/src/util/et/com_err.c
+++ b/src/util/et/com_err.c
@@ -33,6 +33,16 @@
static /*@null@*/ et_old_error_hook_func com_err_hook = 0;
k5_mutex_t com_err_hook_lock = K5_MUTEX_PARTIAL_INITIALIZER;
+#if defined(_WIN32)
+BOOL isGuiApp() {
+ DWORD mypid;
+ HANDLE myprocess;
+ mypid = GetCurrentProcessId();
+ myprocess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, mypid);
+ return GetGuiResources(myprocess, 1) > 0;
+ }
+#endif
+
static void default_com_err_proc (const char *whoami, errcode_t code,
const char *fmt, va_list ap)
{
@@ -55,14 +65,12 @@ static void default_com_err_proc (const char *whoami, errcode_t code,
vsprintf (errbuf + strlen (errbuf), fmt, ap);
errbuf[sizeof(errbuf) - 1] = '\0';
-#ifdef _WIN32
- if (_isatty(_fileno(stderr))) {
+ if (_isatty(_fileno(stderr)) || !isGuiApp()) {
fputs(errbuf, stderr);
fputc('\r', stderr);
fputc('\n', stderr);
fflush(stderr);
} else
-#endif /* _WIN32 */
MessageBox ((HWND)NULL, errbuf, "Kerberos", MB_ICONEXCLAMATION);
#else /* !_WIN32 */
diff --git a/src/util/profile/Makefile.in b/src/util/profile/Makefile.in
index 5c52413..8ef538a 100644
--- a/src/util/profile/Makefile.in
+++ b/src/util/profile/Makefile.in
@@ -2,7 +2,7 @@ thisconfigdir=../..
myfulldir=util/profile
mydir=util/profile
BUILDTOP=$(REL)..$(S)..
-PROG_LIBPATH=-L$(TOPLIBD) $(TCL_LIBPATH)
+PROG_LIBPATH=-L$(TOPLIBD) $(TCL_LIBPATH) -L.
PROG_RPATH=$(KRB5_LIBDIR)$(TCL_RPATH)
KRB5_RUN_ENV=@KRB5_RUN_ENV@
DEFS=
@@ -77,7 +77,7 @@ includes:: profile.h
fi
clean-unix::
- $(RM) $(BUILDTOP)/include/profile.h
+ $(RM) $(BUILDTOP)/include/profile.h test2.ini test3.ini test2.ini.bak
##DOS##LIBOBJS = $(OBJS)
@@ -120,10 +120,10 @@ prof_err.o: prof_err.c
$(srcdir)/profile_tcl.c: profile.swg
# (cd $(srcdir) && swig -tcl8 -o profile_tcl.c profile.swg)
profile_tcl.o: $(srcdir)/profile_tcl.c profile.h
-profile_tcl: profile_tcl.o libprofile.a
+profile_tcl: profile_tcl.o $(PROF_DEPLIB) $(COM_ERR_DEPLIB) $(SUPPORT_DEPLIB)
$(CC_LINK) -o profile_tcl profile_tcl.o \
$(TCL_MAYBE_RPATH) \
- -L../et -L../.. libprofile.a $(TCL_LIBS) $(MLIBS)
+ -L../et -L../.. -lprofile $(TCL_LIBS) $(MLIBS)
clean-unix:: clean-libs clean-libobjs
$(RM) $(PROGS) *.o *~ test_parse core prof_err.h \
diff --git a/src/util/ss/Makefile.in b/src/util/ss/Makefile.in
index fe39c39..f9610d3 100644
--- a/src/util/ss/Makefile.in
+++ b/src/util/ss/Makefile.in
@@ -1,6 +1,6 @@
-thisconfigdir=.
+thisconfigdir=../..
myfulldir=util/ss
-mydir=.
+mydir=util/ss
BUILDTOP=$(REL)..$(S)..
SED = sed
DEFS=
@@ -113,6 +113,7 @@ $(HDRDIR)/ss_err.h: ss_err.h $(HDRDIR)/timestamp
clean-unix::
$(RM) $(HDRS) $(HDRDIR)/timestamp
+ $(RM) -r $(HDRDIR)
std_rqs.c: std_rqs.ct mk_cmds ct_c.sed ct_c.awk
@@ -165,7 +166,7 @@ clean::
ss.ar ss.tar \
TAGS test_ss
-
+@libpriv_frag@
@lib_frag@
@libobj_frag@
diff --git a/src/util/ss/configure.in b/src/util/ss/configure.in
deleted file mode 100644
index f68c533..0000000
--- a/src/util/ss/configure.in
+++ /dev/null
@@ -1,17 +0,0 @@
-K5_AC_INIT(ct.y)
-CONFIG_RULES
-AC_PROG_LEX
-AC_PROG_YACC
-AC_PROG_AWK
-HAVE_YYLINENO
-AC_CHECK_FUNCS(strdup)
-CHECK_DIRENT
-CHECK_WAIT_TYPE
-CHECK_SIGNALS
-CHECK_SIGPROCMASK
-AC_TYPE_SIGNAL
-AC_HEADER_STDARG
-AC_CHECK_HEADERS(stdlib.h)
-KRB5_BUILD_LIBRARY_STATIC
-KRB5_BUILD_LIBOBJS
-V5_AC_OUTPUT_MAKEFILE
diff --git a/src/util/support/fake-addrinfo.c b/src/util/support/fake-addrinfo.c
index 2cd8d92..8ebf195 100644
--- a/src/util/support/fake-addrinfo.c
+++ b/src/util/support/fake-addrinfo.c
@@ -545,6 +545,7 @@ static inline int fai_add_entry (struct addrinfo **result, void *addr,
sin4 = malloc (sizeof (struct sockaddr_in));
if (sin4 == 0)
return EAI_MEMORY;
+ memset (sin4, 0, sizeof (struct sockaddr_in)); /* for sin_zero */
n->ai_addr = (struct sockaddr *) sin4;
sin4->sin_family = AF_INET;
sin4->sin_addr = *(struct in_addr *)addr;
@@ -559,6 +560,7 @@ static inline int fai_add_entry (struct addrinfo **result, void *addr,
sin6 = malloc (sizeof (struct sockaddr_in6));
if (sin6 == 0)
return EAI_MEMORY;
+ memset (sin6, 0, sizeof (struct sockaddr_in6)); /* for sin_zero */
n->ai_addr = (struct sockaddr *) sin6;
sin6->sin6_family = AF_INET6;
sin6->sin6_addr = *(struct in6_addr *)addr;
diff --git a/src/util/support/plugins.c b/src/util/support/plugins.c
index bccb522..b26726f 100644
--- a/src/util/support/plugins.c
+++ b/src/util/support/plugins.c
@@ -455,17 +455,9 @@ krb5int_open_plugin_dirs (const char * const *dirnames,
} else {
/* load all plugins in each directory */
#ifndef _WIN32
- DIR *dir = NULL;
+ DIR *dir = opendir (dirnames[i]);
- if (!err) {
- dir = opendir(dirnames[i]);
- if (dir == NULL) {
- err = errno;
- Tprintf ("-> error %d/%s\n", err, strerror (err));
- }
- }
-
- while (!err) {
+ while (dir != NULL && !err) {
struct dirent *d = NULL;
char *filepath = NULL;
struct plugin_file_handle *handle = NULL;
diff --git a/src/windows/build/BKWconfig.xml b/src/windows/build/BKWconfig.xml
new file mode 100644
index 0000000..93167f3
--- /dev/null
+++ b/src/windows/build/BKWconfig.xml
@@ -0,0 +1,181 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!-- BKW: Build Kerberos for Windows -->
+<BKW_Config>
+ <Config>
+ <!-- All the parameters are specified here. Most can be over-ridden
+ on the command line.
+
+ Parameters are grouped into Options, Directories, Repository and Environment.
+
+ Attributes a parameter can have:
+ def: defined or not. A value of 'A' for 'always' means the
+ option can't be negated on the command line.
+ value: string value, if the option can have a value. If the option
+ can't take a value, omit the value attribute.
+ options: space-delimited list, the 1st element is the default.
+ Synonyms for a valid option are concatenated with '|'.
+ env: an environment variable will be set to value or deleted,
+ depending on def.
+ -->
+ <!-- Options: -->
+ <clean def="0" />
+ <debug def="0" />
+ <help def="0" />
+ <logfile def="1" value="bkw.pl.log" />
+ <make def="1" />
+ <package def="1" />
+ <repository def="1" value="skip" options="skip checkout|co update|up" />
+ <sign def="0" />
+ <verbose def="0" />
+ <vverbose def="0" />
+
+ <!-- Directory settings: -->
+ <!-- Sources will be checked out of repositories into <src>. The structure
+ of the repositories will cause pismere/athena to be created under <src>. -->
+ <src def="A" value="C:\KfW" /> <!-- Must be absolute path. -->
+ <out def="A" value="C:\KfW\public" /> <!-- Must be absolute path. -->
+
+ <!-- Repository settings: -->
+ <cvstag def="0" value="" />
+ <svntag def="0" value="" />
+ <svnbranch def="0" value="" />
+ <CVSROOT def="A" value=":kserver:cvs.mit.edu:/cvs/pismere" />
+ <SVNURL def="A" value="svn.mit.edu" /> <!-- NB: No protocol or slashes!! -->
+ <username def="0" value="" /> <!-- Needed for svn/plink. Override from command line -->
+
+ <!-- Environment variables: -->
+ <KH_RELEASE def="1" env="1" value="OFFICIAL" options="OFFICIAL PRERELEASE PRIVATE" />
+ <NODEBUG def="1" env="1" /> <!-- Interacts with /DEBUG -->
+ </Config>
+ <Stages>
+ <FetchSources>
+ <Zips>
+ <Zip dummy="foo" /> <!-- To force desired XML::Simple behavior -->
+ <Zip name="SRC" filename="%filestem%-src.zip" topdir="%filestem%-final">
+ <CopyList>
+ <Files>
+ <!-- File from paths are relative to <src>/pismere. -->
+ <!-- File to paths are relative to <out>. -->
+ <File dummy="foo" /> <!-- Forces XML::Simple behavior -->
+ <!-- Without this, XML::Simple does not make an anonymous array and I can't figure out how to iterate over it. -->
+ <File name="*.*" from="athena" to="src\athena" />
+ <File name="*.*" from="doc" to="src\doc" />
+ <File name="*.*" from="scripts" to="src\scripts" />
+ </Files>
+ </CopyList>
+ <Prunes> <!-- Files to be removed from current build to match what is in the 3.1 distribution: -->
+ <Prune dummy="foo" />
+ <Prune name="CVS" />
+ <Prune name=".cvsignore" flags="i" />
+ <Prune name="Changelog" flags="i" />
+<!-- <Prune name="site" /> -->
+ </Prunes>
+ <Requires>
+ <Switch dummy="foo" />
+ <Switch name="REPOSITORY" value="CHECKOUT"/>
+ <ErrorMsg text="Can't build source zip unless /REPOSITORY CHECKOUT is specified." />
+ </Requires>
+ </Zip>
+ </Zips>
+ </FetchSources>
+ <Make>
+ <!-- Script checks for prunes. -->
+ </Make>
+ <PrePackage>
+ <CopyList>
+ <Config>
+ <!-- Debug and Release build results go in different places.
+ The otherwise identical paths differ in one section. For example:
+ .../target/bin/i386/bin/rel/filename and .../target/bin/i386/dbg/filename.
+ Here we define the two differing sections: -->
+ <DebugArea value="dbg" />
+ <ReleaseArea value="rel" />
+ <!-- Paths in the file list that include <AlwaysTag> will always have the tag replaced
+ with <DebugArea> or <ReleaseArea>, depending on the type of build.
+ Paths that include <DebugTag> (or <ReleaseTag>) will only have the tag substituted
+ and be copied when doing a debug (or release) build. Examples:
+ Will always be copied, from a build-dependent directory:
+ <File name="kfwlogon.dll" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ Will only be copied in debug build:
+ <File name="netidmgr.exe.static.manifest" from="..\target\bin\i386\%debug%\" to="\bin\i386" notrequired="true" />
+ Will always be copied, from a build-independent directory:
+ <File name="des.h" from="auth\krb4\include\" to="\inc\krb4" newname="foo.h"/>
+ -->
+ <AlwaysTag value="%bldtype%" /> <!-- Pick a string that won't appear in a path. -->
+ <DebugTag value="%debug%" /> <!-- Pick a string that won't appear in a path. -->
+ <ReleaseTag value="%release%" /> <!-- Pick a string that won't appear in a path. -->
+ </Config>
+ <Files>
+ <Include path="copyfiles.xml" />
+ </Files> <!-- Relative to location of bkw.pl. -->
+ </CopyList>
+ </PrePackage>
+ <Package>
+ <Config>
+ <Paths>
+ <Versions path="pismere/athena/include/kerberos.ver" /> <!-- Relative to <src>. -->
+ </Paths>
+ </Config>
+ <MSI></MSI>
+ <NSIS></NSIS> <!-- NB: Most config is done in site-local.nsi. -->
+ </Package>
+ <PostPackage>
+ <Config> <!-- This config info will be copied into each CopyList in PostPackage. -->
+ <FileStem name="kfw-%VERSION_MAJOR%-%VERSION_MINOR%-%VERSION_PATCH%" /> <!-- <FileStem> will be substituted for %filestem%. -->
+ <Signing>
+ <CommandTemplate value="signtool sign /a /d &quot;MIT Kerberos for Windows&quot; /du &quot;http://web.mit.edu/kerberos&quot; /t TIMESTAMPSERVERGOESHERE %filename%" />
+ <FilePatterns value="*.exe *.dll *.cpl *.msi" />
+ </Signing>
+ </Config>
+ <Zips>
+ <Zip dummy="foo" /> <!-- To force desired XML::Simple behavior -->
+ <!-- Files will be copied into directory <topdir>; <topdir> will appear in the paths of the files. -->
+ <!-- File from paths are relative to <src>/pismere. -->
+ <!-- File to paths are relative to <out>. -->
+ <Zip name="Core Binaries" filename="%filestem%.zip" topdir="%filestem%-final">
+ <CopyList>
+ <Config>
+ <DebugArea value="dbg" />
+ <ReleaseArea value="rel" />
+ <AlwaysTag value="%bldtype%" /> <!-- Pick a string that won't appear in a path. -->
+ <DebugTag value="%debug%" /> <!-- Pick a string that won't appear in a path. -->
+ <ReleaseTag value="%release%" /> <!-- Pick a string that won't appear in a path. -->
+ </Config>
+ <Files>
+ <Include path="corebinaryfiles.xml" /> <!-- Includeed file is relative to location of bkw.pl. -->
+ </Files>
+ </CopyList>
+ </Zip>
+ <Zip name="SDK" filename="%filestem%-sdk.zip" topdir="%filestem%-final">
+ <CopyList>
+ <Files>
+ <Include path="sdkfiles.xml" /> <!-- Included file is relative to location of bkw.pl. -->
+ </Files>
+ </CopyList>
+ <Prunes>
+ <Prune dummy="foo" />
+ <Prune name="*.exe" />
+ <Prune name="*.msi" />
+ <Prune name="*.dll" />
+ <Prune name="*.obj" />
+ <Prune name="*.wixobj" />
+ <Prune name="custom.lib" />
+ <Prune name="custom.exp" />
+ </Prunes>
+ </Zip>
+ </Zips>
+ <CopyList> <!-- Copied at end of post-package step. -->
+ <Files>
+ <File dummy="foo" />
+ <!-- File from paths are relative to <src/pismere>. -->
+ <!-- File to paths are relative to <out>. -->
+ <File name="msi-deployment-guide.txt" from="staging\install\wix\" to="" />
+ <File name="netidmgr_userdoc.pdf" from="staging\doc" to="" />
+ <File name="kfw.msi" from="buildwix" to="" newname="%filestem%.msi" />
+ <File name="MITKerberosForWindows%-DEBUG%.exe" from="buildnsi" to="" newname="%filestem%%-DEBUG%.exe" />
+ <File name="relnotes.html" from="staging\doc" to="" />
+ </Files>
+ </CopyList>
+ </PostPackage>
+ </Stages>
+</BKW_Config> \ No newline at end of file
diff --git a/src/windows/build/Logger.pm b/src/windows/build/Logger.pm
new file mode 100644
index 0000000..f74c218
--- /dev/null
+++ b/src/windows/build/Logger.pm
@@ -0,0 +1,87 @@
+package Logger;
+
+use strict;
+use IO::File;
+use FindBin;
+
+my $bStarted = 0;
+
+sub new {
+ my $class = shift;
+ my $file = shift;
+ my $append = shift;
+ $file || die "Usage: \$foo = new Logger filename [append]\n";
+ my $self = {};
+ bless $self, $class;
+ $self->{FILE} = $file;
+ $self->{APPEND} = $append?'-a':'';
+ return $self;
+}
+
+sub start {
+ my $self = shift;
+
+ return 1 if $self->{PIPE};
+
+ STDOUT->flush;
+ STDERR->flush;
+
+ my $fh_out = new IO::File;
+ my $fh_err = new IO::File;
+ my $fh_pipe = new IO::File;
+
+ $self->{OUT} = $fh_out;
+ $self->{ERR} = $fh_err;
+ $self->{PIPE} = $fh_pipe;
+
+ $fh_out->open(">&STDOUT") || die;
+ $fh_err->open(">&STDERR") || die;
+ $fh_pipe->open("|$^X $FindBin::Bin/tee.pl $self->{APPEND} $self->{FILE}") || die;
+
+ STDOUT->fdopen(fileno $fh_pipe, "w") || die;
+ STDERR->fdopen(fileno $fh_pipe, "w") || die;
+
+ STDOUT->autoflush(1);
+ STDERR->autoflush(1);
+
+ $SIG{__DIE__} = sub {
+ print STDERR $_[0];
+ $self->stop;
+ die "\n";
+ };
+
+ $bStarted = 1;
+ return 1;
+}
+
+# 20070314 kpkoch:
+# There appears to be a bug in ActivePerl where Logger's games with streams
+# and the SIG DIE handler cause eval to throw exceptions. By deleting the DIE handler,
+# subsequent evals do not fail.
+sub no_die_handler {
+ delete $SIG{__DIE__};
+ }
+
+sub stop {
+ my $self = shift;
+
+ return 0 if !$self->{PIPE};
+
+ STDOUT->close;
+ STDERR->close;
+ $self->{PIPE}->close;
+ STDOUT->fdopen(fileno $self->{OUT}, "w");
+ STDERR->fdopen(fileno $self->{ERR}, "w");
+ delete $self->{OUT};
+ delete $self->{ERR};
+ delete $self->{PIPE};
+ $bStarted = 0;
+ return 1;
+}
+
+sub DESTROY {
+ my $self = shift;
+ $self->stop if ($bStarted);
+ }
+
+1;
diff --git a/src/windows/build/bkw-automation.html b/src/windows/build/bkw-automation.html
new file mode 100644
index 0000000..4583e54
--- /dev/null
+++ b/src/windows/build/bkw-automation.html
@@ -0,0 +1,355 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3c.org/TR/1999/REC-html401-19991224/loose.dtd">
+<!-- saved from url=(0066)https://confab.mit.edu/confluence/display/ISDA/lore-bkw-automation --><HTML><HEAD>
+ <TITLE>lore-bkw-automation - Confluence</TITLE>
+ <META http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <META http-equiv="Pragma" content="no-cache">
+ <META http-equiv="Expires" content="-1">
+ <LINK href="css/main-action.css" type="text/css" rel="stylesheet">
+ <LINK href="css\main-action(1).css" type="text/css" rel="stylesheet">
+ <META content="MSHTML 6.00.2900.3059" name="GENERATOR"></HEAD>
+ <BODY>
+ <DIV style="MARGIN-LEFT: 10px; MARGIN-RIGHT: 10px" align="left">
+ <DIV class="wiki-content" style="MARGIN-TOP: 5px; MARGIN-BOTTOM: 5px" align="left">The
+ Kerberos for Windows (KfW) build is automated.&nbsp; A script will fetch the
+ sources from a repository and then build, sign and package all the KfW
+ distribution components.
+ </DIV>
+ <DIV class="wiki-content" style="MARGIN-TOP: 5px; MARGIN-BOTTOM: 5px" align="left">This
+ description consists of
+ </DIV>
+ <UL>
+ <LI>
+ <A href="#Environment">Setting up the build environment</A>
+ <LI>
+ <A href="#Running">Running the script</A>
+ <LI>
+ <A href="Details">Script internal details</A>
+ <LI>
+ <A href="#Remainingwork">Remaining work / bug list</A>
+ <LI>
+ <A href="#Troubleshooting">Troubleshooting</A>
+ </LI>
+ </UL>
+ <H2>Setting Up the Build Environment</H2>
+ <P>KfW is built on a Windows PC, in the default Windows shell (cmd.exe). These
+ components must be installed:</P>
+ <UL>
+ <LI>
+ Visual Studio 2003<BR>
+ Versions of Visual Studio before or after 2003 are not supported.
+ <LI>
+ A recent release of the
+ <SPAN class="nobr">
+ <A href="http://www.microsoft.com/downloads/details.aspx?FamilyId=0BAF2B35-C656-4969-ACE8-E4C0C0716ADB&amp;displaylang=en">
+ Microsoft Platform SDK</A></SPAN>
+ &nbsp;
+ <LI>
+ <SPAN class="nobr">
+ <A title="Visit page outside Confluence" href="http://www.activestate.com" rel="nofollow">
+ ActiveState Perl 5.8 or more recent</A></SPAN><BR>
+ Build 631 is known to work.
+ <LI>
+ <SPAN class="nobr">
+ <A title="Visit page outside Confluence" href="http://www.doxygen.org/" rel="nofollow">
+ Doxygen</A></SPAN>
+ <LI>
+ sed, awk, cat, rm and find<BR>
+ These can be obtained from the
+ <SPAN class="nobr">
+ <A title="Visit page outside Confluence" href="http://cygwin.com/" rel="nofollow">Cygwin
+ distribution</A></SPAN>.
+ <BR clear="all">
+ <BR clear="all">
+ find must be in C:\tools\cygwin\bin, so install Cygwin in C:\tools\cygwin.
+ <BR>
+ <BR>
+ The cygwin awk is a link and the MS shell doesn't deal well with that.&nbsp; <TT>C</TT>
+ opy <TT>c:\tools\cygwin\bin\gawk</TT> to <TT>c:\tools\cygwin\bin\awk</TT>.
+ <LI>
+ <SPAN class="nobr">
+ <A title="Visit page outside Confluence" href="http://sourceforge.net/project/showfiles.php?group_id=105970"
+ rel="nofollow">Wix</A></SPAN>
+ <LI>
+ <SPAN class="nobr">
+ <A title="Visit page outside Confluence" href="http://nsis.sourceforge.net" rel="nofollow">
+ NSIS</A></SPAN></LI></UL>
+ <H3>Environment variables</H3>
+ <P>
+ All the components above must be in PATH. Installing ActivePerl puts perl in
+ the PATH. Doxygen, Cygwin, hhc, wix and&nbsp;nsis need to be added.</P>
+ <P>perl must be installed so that .pl files are automatically executed with perl.
+ The ActivePerl installation will do this for you.</P>
+ <P>In the INCLUDE path, the Microsoft Platform SDK must come before the Microsoft
+ Visual C++ include files. Using a Platform SDK Build Environment window will
+ set this up the right way.&nbsp;</P>
+ <P>If you make your path modifications permanent via Control Panel / System /
+ Advanced / Environment Variables:&nbsp; If you use a Platform SDK Build
+ Environment window, it appears that you need to put your PATH components in the
+ System PATH, not the User PATH.</P>
+ <P>Visual Studio installs hhc in C:\Program Files\HTML Help Workshop.</P>
+ <P>nmake must be in PATH. If you use a Platform SDK build environment window, it is
+ already done for you.</P>
+ <h2>Running the Script<A name="Running"></A></h2>
+ <P>
+ The build is a perl script controlled by command line switches and an XML
+ configuration file. The config file is required. Settings in the config file
+ can be overridden by optional command line switches.&nbsp;</P>
+ <P>There are options for controlling most steps of the build process.&nbsp; The
+ steps are</P>
+ <UL>
+ <LI>
+ Verifying the environment
+ <LI>
+ Fetching the sources from repositories
+ <LI>
+ Building the sources
+ <LI>
+ Setting up the packaging environment
+ <LI>
+ Building the installers
+ <LI>
+ Building the rest of the components
+ </LI>
+ </UL>
+ <P>The usage message shows the switches that control these steps:</P>
+ <P><TT>C:\Projects\KfW&gt;perl bkw.pl /?</TT><BR>
+ <TT>Usage: bkw.pl [options] NMAKE-options</TT></P>
+ <P><TT>&nbsp; Options are case insensitive. </TT>
+ </P>
+ <P><TT>&nbsp; Options:&nbsp;
+ <BR>
+ </TT><TT>&nbsp; /help /?&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ usage information (what you now see).
+ <BR>
+ &nbsp; /config /f path&nbsp;&nbsp; Path to config file. Default is
+ bkwconfig.xml.
+ <BR>
+ &nbsp; /src /r dir&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Source directory to use.
+ Should contain
+ <BR>
+ &nbsp;&nbsp;&nbsp;
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ pismere/athena. If cvstag or svntag is&nbsp;null,
+ <BR>
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ the directory should be prepopulated.
+ <BR>
+ &nbsp; /out /o dir&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Directory to be created
+ where build results will go
+ <BR>
+ </TT><TT>&nbsp; /repository checkout | co \ What repository action to take.
+ <BR>
+ &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ update&nbsp;&nbsp; | up&nbsp; ) Options are to checkout, update or
+ <BR>
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ skip&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/ take no
+ action [skip].
+ <BR>
+ &nbsp; /username /u name username used to access svn if checking out.
+ <BR>
+ &nbsp; /cvstag /c tag&nbsp;&nbsp;&nbsp; use -r &lt;tag&gt;
+ <TAG>in cvs
+command <BR>&nbsp; /svnbranch /b tag use
+/branches/&lt;tag&gt;<TAG>&nbsp;instead of /trunk.<BR>&nbsp; /svntag /s tag&nbsp;&nbsp;&nbsp; use
+/tags/&lt;tag&gt;<TAG>&nbsp;instead of /trunk.<BR>&nbsp; /debug
+/d&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Do&nbsp;debug make instead of
+release make. <BR>&nbsp;
+/[no]make&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+Control the make
+step. <BR>&nbsp;
+/clean&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Build
+clean target. <BR>&nbsp;
+/[no]package&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Control the packaging step. <BR>&nbsp;
+/[no]sign&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Control
+signing
+of executable&nbsp;files. <BR>&nbsp; /verbose
+/v&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Debug mode - verbose output. <BR>&nbsp; /logfile /l path&nbsp; Where to write output.
+Default is bkw.pl.log. <BR>&nbsp;
+ /nolog&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Don't
+ save output. </TT>
+ </P>
+ <P><TT>&nbsp; Other:
+ <BR>
+ &nbsp;&nbsp;&nbsp; NMAKE-options any options you want to pass to NMAKE, which
+ can be:
+ <BR>
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ (note: /nologo is always used)<BR>
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NODEBUG=1</TT></P>
+ <P><TT>NMAKE-options any options you want to pass to NMAKE, which can be:</TT><BR>
+ <TT>(note: /nologo is always used)</TT><BR>
+ <TT>[ nmake options follow ]</TT></P>
+ <P><BR>
+ Notes on the script steps:</P>
+ <P><STRONG>Verifying the environment</STRONG>:&nbsp;
+ <BR>
+ The script tests for each program that it needs and warns if the program isn't
+ found.</P>
+ <P><STRONG>Fetching sources from repositories</STRONG>:&nbsp;
+ <BR>
+ If building from a source distribution kit, this section does not apply.</P>
+ <P>CVSROOT and SVNURL must be specified in the configuration file.</P>
+ <P>A source zip file can only be produced if checking out fresh sources from a
+ repository.&nbsp;</P>
+ <P>If checking out, the entire pismere directory will be deleted.&nbsp; A warning
+ message requires that you confirm this action.</P>
+ <P><STRONG>Building the sources:</STRONG><BR>
+ /DEBUG controls whether a debug or release build is done.&nbsp; /CLEAN will
+ build the CLEAN target.</P>
+ <P><STRONG>Setting up the packaging environment :<BR>
+ </STRONG>The pre-package steps gathers up build results and puts them in a <FONT face="Courier">
+ staging</FONT> area.&nbsp;
+ </P>
+ <P>If /SIGN is specified, <FONT face="Courier">.exe</FONT>s, <FONT face="Courier">.dll</FONT>s
+ and <FONT face="Courier">.cpl</FONT>s are signed.&nbsp; The signing command
+ template is in the configuration file.</P>
+ <P><STRONG>Building the installers:</STRONG><BR>
+ The <FONT face="Courier">staging </FONT>area is copied into a fresh area for
+ each of the installers.&nbsp; The installer results are copied back to the <FONT face="Courier">
+ staging </FONT>area.</P>
+ <P><STRONG>Building the rest of the components:</STRONG><BR>
+ Zip files are built in temporary areas and copied to <FONT face="Courier">outdir</FONT>.&nbsp;
+ The installers and assorted files are copied from <FONT face="Courier">staging</FONT>
+ to <FONT face="Courier">outdir</FONT>.&nbsp; If /SIGN is specified, the
+ installers will be signed.</P>
+ <P>&nbsp;</P>
+ <H2><A name="Details"></A>Script Internal Details</H2>
+ <H3><A name="Copylists"></A>Copy Lists</H3>
+ <P>CopyLists are used in many places.&nbsp;&nbsp;For example, files to be put into
+ a .zip are copied to a fresh directory which is then zipped up.&nbsp; There is
+ an optional Configuration section and a required Files section.&nbsp;</P>
+ <P>The configuration section defines the roots of the from and to paths and can
+ optionally define path substitutions.&nbsp;
+ </P>
+ <P>The to and from paths are forced by the script rather than being set in the
+ config file.&nbsp; Comments in the copyfile xml indicate this.</P>
+ <P>Lengthy copy lists can be kept in separate files and included with the Include
+ directive.&nbsp; Example:</P>
+ <P><TT>&lt;Include path="sdkfiles.xml" /&gt;</TT></P>
+ <H3>Substitution tags</H3>
+ <P>Filenames in copylists can contain variable 'tags' that are replaced before the
+ file is copied.&nbsp; Some configuration files contain substitution tags which
+ customize the configuration.&nbsp; The supported tags are</P>
+ <P>
+ <TABLE id="Table3" height="0" cellSpacing="1" cellPadding="1" border="1">
+ <TR>
+ <TD width="136">%VERSION_MAJOR%</TD>
+ <TD height="21">KfW Version from pismere/athena/include/kerberos.ver.</TD>
+ </TR>
+ <TR>
+ <TD width="136">%VERSION_MINOR%</TD>
+ <TD height="9">KfW Version from pismere/athena/include/kerberos.ver.</TD>
+ </TR>
+ <TR>
+ <TD width="136">%VERSION_PATCH%</TD>
+ <TD height="17">KfW Version from pismere/athena/include/kerberos.ver.</TD>
+ </TR>
+ <TR>
+ <TD width="136">%filestem%</TD>
+ <TD height="17">Defined as kfw-%VERSION_MAJOR%-%VERSION_MINOR%-%VERSION_PATCH%.</TD>
+ </TR>
+ <TR>
+ <TD width="136">%debug%</TD>
+ <TD>'dbg.'&nbsp; Only substituted during a debug build.&nbsp;</TD>
+ </TR>
+ <TR>
+ <TD width="136">%release%</TD>
+ <TD>'rel.'&nbsp; Only substituted during a release build.&nbsp;
+ </TD>
+ </TR>
+ <TR>
+ <TD width="136">%bldtype%</TD>
+ <TD>Always substituted, to 'dbg' or 'rel,' depending on the type of build.</TD>
+ </TR>
+ <TR>
+ <TD width="136">%-DEBUG%</TD>
+ <TD>'-DEBUG' during a debug build; otherwise empty.</TD>
+ </TR>
+ <TR>
+ <TD width="136">%BUILDDIR%</TD>
+ <TD>SRCDIR\pismere.&nbsp; Used in site-local installer configuration files.</TD>
+ </TR>
+ <TR>
+ <TD width="136">%TARGETDIR%</TD>
+ <TD>SRCDIR\pismere\staging.&nbsp; Used in site-local installer configuration files.</TD>
+ </TR>
+ <TR>
+ <TD width="136">%CONFIGDIR-WIX%</TD>
+ <TD>SRCDIR\pismere\staging\sample.&nbsp; Used in site-local installer configuration
+ files.</TD>
+ </TR>
+ <TR>
+ <TD width="136">%CONFIGDIR-NSI%</TD>
+ <TD>SRCDIR\pismere\staging.&nbsp; Used in site-local installer configuration files.</TD>
+ </TR>
+ </TABLE>
+ </P>
+ <P>The overall build configuration specifies a debug or release build.&nbsp; Debug
+ and release results are put in different places.&nbsp; Files whose location
+ depend on the build type can use %bldtype% in their names.&nbsp; The script
+ will substitute %bldtype% with either dbg or rel, depending on the build
+ type.&nbsp;<STRONG></P>
+ </DIV>
+ <DIV style="MARGIN-LEFT: 10px; MARGIN-RIGHT: 10px" align="left">
+ <H3>Example</H3>
+ </STRONG>
+ <P>Here is&nbsp;a copylist entry.&nbsp; Each segment of the file's path that comes
+ from a different place is in a different color.</P>
+ <P>Release build.&nbsp; Config file:
+ </P>
+ <P>
+ <TABLE id="Table2" cellSpacing="1" cellPadding="1" border="0">
+ <TR>
+ <TD colSpan="4"><FONT face="courier">&lt;BKW_Config&gt;</FONT></TD>
+ </TR>
+ <TR>
+ <TD width="23"></TD>
+ <TD colSpan="3"><FONT face="courier">&lt;Config&gt;</FONT></TD>
+ </TR>
+ <TR>
+ <TD width="23"></TD>
+ <TD width="20"></TD>
+ <TD><FONT face="courier">&lt;src&nbsp;value ="<FONT color="#000099">C:\bkw"</FONT> /&gt;</FONT>
+ </TD>
+ </TR>
+ </TABLE>
+ </P>
+ <P>Copylist comments:</P>
+ <P><tt>&lt;!-- File from paths are relative to
+ <src>\<FONT color="#ff00cc">pismere\athena</FONT> --&gt; <BR>&lt;!-- File to paths are relative to <src>\<FONT color="#00ff00">
+ pismere\staging</FONT>
+ --&gt; </tt>
+ </P>
+ <P>When the script processes this copylist, it will force the from and to paths as
+ indicated.</P>
+ <P>This line
+ </P>
+ <P><tt>&lt;File name="<FONT color="#00ffff">comerr32.dll</FONT>" from="<FONT color="#ff9933">..\target\bin\i386</FONT>\<FONT color="#ff0000">%bldtype%</FONT>\"
+ to="\<FONT color="#9966ff">bin\i386</FONT>" /&gt;</tt></P>
+ <P>will result in <FONT face="Courier"><FONT color="#000099">C:\bkw</FONT>\<FONT color="#ff00cc">pismere\athena</FONT>\<FONT color="#ff9933">..\target\bin\i386</FONT>\<FONT color="#ff0000">rel</FONT>\<FONT color="#00ffff">comerr32.dll</FONT></FONT></P>
+ <P>being copied to <FONT face="Courier"><FONT color="#000099">C:\bkw</FONT>\<FONT color="#00ff00">pismere\staging</FONT>\<FONT color="#9966ff">bin\i386</FONT>\<FONT color="#00ffff">comerr32.dll</FONT></FONT>.</P>
+ <P>Other possible attributes in a copylist entry:</P>
+ <UL>
+ <LI>
+ <TT>notrequired</TT>
+ <LI>
+ <TT>newname="filename"</TT>
+ </LI>
+ </UL>
+ <P>By default, copylist entries are required and the script will die if they aren't
+ present. To ignore missing files, add <TT>notrequired</TT>.</P>
+ <P>To rename the file, set the <TT>newname</TT> attribute.</P>
+ <H2><FONT face="Verdana"><A name="Remainingwork"></A>Remaining Work / Bug List</FONT></H2>
+ <P>Implement RETAIL, OFFICIAL, PRERELEASE, PRIVATE, SPECIAL.</P>
+ <P>Figure out what MIT_ONLY, BUILD_KFW, DEBUG_SYMBOL should be.</P>
+ <P>TARGET, APPVER.</P>
+ <P>NODEBUG=1.&nbsp; Set if release build.</P>
+ <H2><FONT face="Verdana"><A name="Troubleshooting"></A>Troubleshooting</FONT>
+ </H2>
+ <P><STRONG>Can't clean directory; can't delete file or directory</STRONG><BR>
+ Make sure a file in the named directory isn't open in another application.</P>
+ </DIV>
+ </BODY>
+</HTML>
diff --git a/src/windows/build/bkw.pl b/src/windows/build/bkw.pl
new file mode 100644
index 0000000..8b8b1ab
--- /dev/null
+++ b/src/windows/build/bkw.pl
@@ -0,0 +1,669 @@
+#!perl -w
+
+#use strict;
+use FindBin;
+use File::Spec;
+use File::Basename;
+use lib "$FindBin::Bin/build/lib";
+use Getopt::Long;
+use Cwd;
+use XML::Simple;
+use Data::Dumper;
+use Archive::Zip;
+use Logger;
+require "copyfiles.pl";
+require "prunefiles.pl";
+require "signfiles.pl";
+require "zipXML.pl";
+
+my $BAIL;
+$0 = fileparse($0);
+my $OPT = {foo => 'bar'};
+my $MAKE = 'NMAKE';
+our $config;
+
+sub get_info {
+ my $cmd = shift || die;
+ my $which = $^X.' which.pl';
+ my $full = `$which $cmd`;
+ return 0 if ($? / 256);
+ chomp($full);
+ $full = "\"".$full."\"";
+ return { cmd => $cmd, full => $full};
+ }
+
+sub usage {
+ print <<USAGE;
+Usage: $0 [options] NMAKE-options
+
+ Options are case insensitive.
+
+ Options:
+ /help /? usage information (what you now see).
+ /config /f path Path to config file. Default is bkwconfig.xml.
+ /srcdir /r dir Source directory to use. Should contain
+ pismere/athena. If cvstag or svntag is null,
+ the directory should be prepopulated.
+ /outdir /o dir Directory to be created where build results will go
+ /repository checkout | co \\ What repository action to take.
+ update | up ) Options are to checkout, update or
+ skip / take no action [skip].
+ /username /u name username used to access svn if checking out.
+ /cvstag /c tag use -r <tag> in cvs command
+ /svnbranch /b tag use /branches/<tag> instead of /trunk.
+ /svntag /s tag use /tags/<tag> instead of /trunk.
+ /debug /d Do debug make instead of release make.
+ /[no]make Control the make step.
+ /clean Build clean target.
+ /[no]package Control the packaging step.
+ /[no]sign Control signing of executable files.
+ /verbose /v Debug mode - verbose output.
+ /logfile /l path Where to write output. Default is bkw.pl.log.
+ /nolog Don't save output.
+ Other:
+ NMAKE-options any options you want to pass to NMAKE, which can be:
+ (note: /nologo is always used)
+
+USAGE
+ system("$MAKE /?");
+ }
+
+sub handler {
+ my $sig = shift;
+ my $bailmsg = "Bailing out due to SIG$sig!\n";
+ my $warnmsg = <<EOH;
+*********************************
+* FUTURE BUILDS MAY FAIL UNLESS *
+* BUILD DIRECTORIES ARE CLEANED *
+*********************************
+EOH
+ $BAIL = $bailmsg.$warnmsg;
+}
+
+sub main {
+ local $cmdline = "bkw.pl";
+ foreach $arg (@ARGV) {$cmdline .= " $arg";}
+
+ Getopt::Long::Configure('no_bundling', 'no_auto_abbrev',
+ 'no_getopt_compat', 'require_order',
+ 'ignore_case', 'pass_through',
+ 'prefix_pattern=(--|-|\+|\/)',
+ );
+ GetOptions($OPT,
+ 'help|h|?',
+ 'cvstag|c:s',
+ 'svntag|s:s',
+ 'svnbranch|b:s',
+ 'src|r:s',
+ 'out|o:s',
+ 'debug|d',
+ 'nodebug',
+ 'config|f=s',
+ 'logfile|l:s',
+ 'nolog',
+ 'repository:s',
+ 'username|u:s',
+ 'verbose|v',
+ 'vverbose',
+ 'make!',
+ 'clean',
+ 'package!',
+ 'sign!',
+ );
+
+ if ( $OPT->{help} ) {
+ usage();
+ exit(0);
+ }
+
+ delete $OPT->{foo};
+
+##++ Validate required conditions:
+
+ local $argvsize = @ARGV;
+ if ($argvsize > 0) {
+ print "Error -- invalid argument: $ARGV[0]\n";
+ usage();
+ die;
+ }
+
+ if (! exists $OPT->{config}) {$OPT->{config} = "bkwconfig.xml";}
+
+ # List of programs which must be in PATH:
+ my @required_list = ('sed', 'awk', 'which', 'cat', 'rm', 'cvs', 'svn', 'doxygen',
+ 'hhc', 'candle', 'light', 'makensis', 'nmake', 'plink', 'filever');
+ my $requirements_met = 1;
+ my $first_missing = 0;
+ my $error_list = "";
+ foreach my $required (@required_list) {
+ if (!get_info($required)) {
+ $requirements_met = 0;
+ if (!$first_missing) {
+ $first_missing = 1;
+ $error_list = "Fatal -- Environment problem! The following program(s) are not in PATH:\n";
+ }
+ $error_list .= "$required\n";
+ }
+ }
+ if (!$requirements_met) {
+ print $error_list;
+ print "Info -- Update PATH or install the programs and try again.\n";
+ exit(0);
+ }
+
+##-- Validate required conditions.
+
+ use Time::gmtime;
+ $ENV{DATE} = gmctime()." GMT";
+ our $originalDir = `cd`;
+ $originalDir =~ s/\n//g;
+
+##++ Assemble configuration from config file and command line:
+
+ my $configfile = $OPT->{config};
+ my $bOutputCleaned = 0;
+
+ print "Info -- Reading configuration from $configfile.\n";
+
+ # Get configuration file:
+ my $xml = new XML::Simple();
+ $config = $xml->XMLin($configfile);
+ # Set up convenience variables:
+ local $odr = $config->{Config}; ## Options, directories, repository, environment.
+
+#while ($v = each %$OPT) {print "$v: $OPT->{$v}\n";}
+
+ # Scan the configuration for switch definitions:
+ while (($sw, $val) = each %$odr) {
+ next if (! exists $val->{def}); ## ?? Should always exist.
+
+ # Set/clear environment variables:
+ if ($val->{env}) {
+ if ($val->{def}) {$ENV{$sw} = (exists $val->{value}) ? $val->{value} : 1; }
+ else {delete $ENV{$sw}; }
+ }
+
+ # If the switch is in the command line, override the stored value:
+ if (exists $OPT->{$sw}) {
+ if (exists $val->{value}) {
+ $val->{value} = $OPT->{$sw};
+ $val->{def} = 1;
+ }
+ else {
+ $val->{def} = $OPT->{$sw}; ## If no<switch>, value will be zero.
+ }
+ }
+ # If the switch can be negated, test that, too:
+ if ( ! ($val->{def} =~ /A/)) {
+ local $nosw = "no".$sw;
+ if (exists $OPT->{$nosw}) {
+ $val->{def} = 0;
+ }
+ }
+
+ # For any switch definition with fixed values ("options"), validate:
+ if (exists $val->{options}) {
+ local $bValid = 0;
+ # options can be like value1|syn1 value2|syn2|syn3
+ foreach $option (split(/ /, $val->{options})) {
+ local $bFirst = 1;
+ local $sFirst;
+ foreach $opt (split(/\|/, $option)) {
+ # opt will be like value2, syn2, syn3
+ if ($bFirst) {
+ $sFirst = $opt; ## Remember the full name of the option.
+ $bFirst = 0;
+ }
+ if ($val->{value} =~ /$opt/i) {
+ $val->{value} = $sFirst; ## Save the full name.
+ $bValid = 1;
+ }
+ }
+ }
+ if (! $bValid) {
+ print "Fatal -- invalid $sw value $val->{value}. Possible values are $val->{options}.\n";
+ usage();
+ die;
+ }
+ }
+ }
+
+ # Set up convenience variables:
+ our $verbose = $odr->{verbose}->{def};
+ our $vverbose = $odr->{vverbose}->{def};
+ our $clean = $clean->{clean}->{def};
+ local $src = $odr->{src}->{value};
+ local $out = $odr->{out}->{value};
+
+ if ($clean && $odr->{package}->{def}) {
+ print "Info -- /clean forces /nopackage.\n";
+ $odr->{package}->{def} = 0;
+ }
+
+ if ($vverbose) {print "Debug -- Config: ".Dumper($config);}
+
+ # Test the unix find command:
+ if (! exists $odr->{unixfind}->{value}) {
+ $odr->{unixfind}->{value} = "C:\\tools\\cygwin\\bin";
+ }
+ local $unixfind = $odr->{unixfind}->{value};
+
+ local $savedPATH = $ENV{PATH};
+ $ENV{PATH} = $unixfind.";".$savedPATH;
+ print "Info -- chdir to ".`cd`."\n" if ($verbose);
+ if (-e "a.tmp") {!system("rm a.tmp") or die "Fatal -- Couldn't clean temporary file a.tmp.";}
+ !system("find . -maxdepth 0 -name a.tmp > b.tmp 2>&1") or die "Fatal -- find test failed.";
+ local $filesize = -s "b.tmp";
+ $ENV{PATH} = $savedPATH;
+ if ($filesize > 0) {
+ die "Fatal -- $unixfind does not appear to be a path to a UNIX find command.";
+ }
+
+ # Don't allow /svntag and /svnbranch simultaneously:
+ if ( (length $odr->{svntag}->{value} > 0) &&
+ (length $odr->{svnbranch}->{value} > 0) ) {
+ die "Fatal -- Can't specify both /SVNTAG and /SVNBRANCH.";
+ }
+
+##-- Assemble configuration from config file and command line.
+
+ local $rverb = $odr->{repository}->{value};
+ if ( ($rverb =~ /checkout/) && $clean) {
+ print "Warning -- Because sources afe being checked out, make clean will not be run.\n";
+ $clean = $odr->{clean}->{def} = 0;
+ }
+
+ my $wd = $src."\\pismere";
+
+ if (! ($rverb =~ /skip/)) {
+ local $len = 0;
+ if (exists $odr->{username}->{value}) {
+ $len = length $odr->{username}->{value};
+ }
+ if ($len < 1) {
+ die "Fatal -- you won't get far accessing the repository without specifying a username.";
+ }
+ }
+
+ if ( ($rverb =~ /checkout/) && (-d $wd) ){
+ print "\n\nHEADS UP!!\n\n";
+ print "/REPOSITORY CHECKOUT will cause everything under $wd to be deleted.\n";
+ print "If this is not what you intended, here's your chance to bail out!\n\n\n";
+ print "Are you sure you want to remove everything under $wd? ";
+ my $char = getc;
+ if (! ($char =~ /y/i)) {die "Info -- operation aborted by user."}
+ !system("rm -rf $wd/*") or die "Fatal -- Couldn't clean $wd.";
+ !system("rmdir $wd") or die "Fatal -- Couldn't remove $wd.";
+ }
+
+# Begin logging:
+ my $l;
+ if ($odr->{logfile}->{def}) {
+ print "Info -- logging to $odr->{logfile}->{value}.\n";
+ $l = new Logger $odr->{logfile}->{value};
+ $l->start;
+ $l->no_die_handler; ## Needed so XML::Simple won't throw exceptions.
+ }
+
+ print "Executing $cmdline\n";
+
+##++ Begin repository action:
+ if ($rverb =~ /skip/) {print "Info -- *** Skipping repository access.\n" if ($verbose);}
+ else {
+ if ($verbose) {print "Info -- *** Begin fetching sources.\n";}
+ local $cvspath = "$src";
+ if (! -d $cvspath) { ## xcopy will create the entire path for us.
+ !system("echo foo > a.tmp") or die "Fatal -- Couldn't create temporary file in ".`cd`;
+ !system("echo F | xcopy a.tmp $cvspath\\a.tmp") or die "Fatal -- Couldn't xcopy to $cvspath.";
+ !system("rm a.tmp") or die "Fatal -- Couldn't remove temporary file.";
+ !system("rm $cvspath\\a.tmp") or die "Fatal -- Couldn't remove temporary file.";
+ }
+
+ # Set up cvs environment variables:
+ $ENV{CVSROOT} = $odr->{CVSROOT}->{value};
+ local $krb5dir = "$wd\\athena\\auth\\krb5";
+
+ local $cvscmdroot = "cvs $rverb";
+ if (length $odr->{cvstag}->{value} > 0) {
+ $cvscmdroot .= " -r $odr->{cvstag}->{value}";
+ }
+
+ if ($rverb =~ /checkout/) {
+ chdir($src) or die "Fatal -- couldn't chdir to $src\n";
+ print "Info -- chdir to ".`cd`."\n" if ($verbose);
+ my @cvsmodules = (
+ 'krb',
+ 'pismere/athena/util/lib/delaydlls',
+ 'pismere/athena/util/lib/getopt',
+ 'pismere/athena/util/guiwrap'
+ );
+
+ foreach my $module (@cvsmodules) {
+ local $cvscmd = $cvscmdroot." ".$module;
+ if ($verbose) {print "Info -- cvs command: $cvscmd\n";}
+ !system($cvscmd) or die "Fatal -- command \"$cvscmd\" failed; return code $?\n";
+ }
+ }
+ else { ## Update.
+ chdir($wd) or die "Fatal -- couldn't chdir to $wd\n";
+ print "Info -- chdir to ".`cd`."\n" if ($verbose);
+ if ($verbose) {print "Info -- cvs command: $cvscmdroot\n";}
+ !system($cvscmdroot) or die "Fatal -- command \"$cvscmdroot\" failed; return code $?\n";
+ }
+
+ # Set up svn environment variable:
+ $ENV{SVN_SSH} = "plink.exe";
+ # If the directory structure doesn't exist, many cd commands will fail.
+ if (! -d $krb5dir) { ## xcopy will create the entire path for us.
+ !system("echo foo > a.tmp") or die "Fatal -- Couldn't create temporary file in ".`cd`;
+ !system("echo F | xcopy a.tmp $krb5dir\\a.tmp") or die "Fatal -- Couldn't xcopy to $krb5dir.";
+ !system("rm a.tmp") or die "Fatal -- Couldn't remove temporary file.";
+ !system("rm $krb5dir\\a.tmp") or die "Fatal -- Couldn't remove temporary file.";
+ }
+
+ chdir($krb5dir) or die "Fatal -- Couldn't chdir to $krb5dir";
+ print "Info -- chdir to ".`cd`."\n" if ($verbose);
+ my $svncmd = "svn $rverb ";
+ if ($rverb =~ /checkout/) { # Append the rest of the checkout command:
+ chdir("..");
+ $svncmd .= "svn+ssh://".$odr->{username}->{value}."@".$odr->{SVNURL}->{value}."/krb5/";
+ if (length $odr->{svntag}->{value} > 0) {
+ $svncmd .= "tags/$odr->{svntag}->{value}";
+ }
+ elsif (length $odr->{svnbranch}->{value} > 0) {
+ $svncmd .= "branches/$odr->{svnbranch}->{value}";
+ }
+ else {
+ $svncmd .= "trunk";
+ }
+
+ $svncmd .= " krb5";
+
+ }
+ if ($verbose) {print "Info -- svn command: $svncmd\n";}
+ !system($svncmd) or die "Fatal -- command \"$svncmd\" failed; return code $?\n";
+ if ($verbose) {print "Info -- *** End fetching sources.\n";}
+ }
+##-- End repository action.
+
+ ##++ Read in the version information to be able to update the
+ # site-local files in the install build areas.
+ # ** Do this now (after repository update and before first zip)
+ # because making zip files requires some configuration data be set up.
+ local $version_path = $config->{Stages}->{Package}->{Config}->{Paths}->{Versions}->{path};
+ open(DAT, "$src/$version_path") or die "Could not open $version_path.";
+ @raw = <DAT>;
+ close DAT;
+ foreach $line (@raw) {
+ chomp $line;
+ if ($line =~ /#define/) { # Process #define lines:
+ $line =~ s/#define//; # Remove #define token
+ $line =~ s/^\s+//; # and leading & trailing whitespace
+ $line =~ s/\s+$//;
+ local @qr = split("\"", $line); # Try splitting with quotes
+ if (exists $qr[1]) {
+ $qr[0] =~ s/^\s+//; # Clean up whitespace
+ $qr[0] =~ s/\s+$//;
+ $config->{Versions}->{$qr[0]} = $qr[1]; # Save string
+ }
+ else { # No quotes, so
+ local @ar = split(" ", $line); # split with space
+ $ar[0] =~ s/^\s+//; # Clean up whitespace
+ $ar[0] =~ s/\s+$//;
+ $config->{Versions}->{$ar[0]} = $ar[1]; # and save numeric value
+ }
+ }
+ }
+
+ # Check that the versions we will need for site-local have been defined:
+ my @required_versions = ('VER_PROD_MAJOR', 'VER_PROD_MINOR', 'VER_PROD_REV',
+ 'VER_PROD_MAJOR_STR', 'VER_PROD_MINOR_STR', 'VER_PROD_REV_STR',
+ 'VER_PRODUCTNAME_STR');
+ $requirements_met = 1;
+ $first_missing = 0;
+ $error_list = "";
+ foreach my $required (@required_versions) {
+ if (! exists $config->{Versions}->{$required}) {
+ $requirements_met = 0;
+ if (!$first_missing) {
+ $first_missing = 1;
+ $error_list = "Fatal -- The following version(s) are not defined in $src/$version_path.\n";
+ }
+ $error_list .= "$required\n";
+ }
+ }
+ if (!$requirements_met) {
+ print $error_list;
+ exit(0);
+ }
+
+ # Apply any of these tags to filestem:
+ my $filestem = $config->{Stages}->{PostPackage}->{Config}->{FileStem}->{name};
+ $filestem =~ s/%VERSION_MAJOR%/$config->{Versions}->{'VER_PROD_MAJOR_STR'}/;
+ $filestem =~ s/%VERSION_MINOR%/$config->{Versions}->{'VER_PROD_MINOR_STR'}/;
+ $filestem =~ s/%VERSION_PATCH%/$config->{Versions}->{'VER_PROD_REV_STR'}/;
+ $config->{Stages}->{PostPackage}->{Config}->{FileStem}->{name} = $filestem;
+ ##-- Read in the version information & set config info.
+
+##++ Repository action, part 2:
+ if ($rverb =~ /checkout/) {
+ if (! $bOutputCleaned) { ## In case somebody cleaned $out before us.
+ if (-d $out) {!system("rm -rf $out/*") or die "Fatal -- Couldn't clean $out."} ## Clean output directory.
+ else {mkdir($out);}
+ $bOutputCleaned = 1;
+ }
+ zipXML($config->{Stages}->{FetchSources}, $config); ## Make zips.
+ }
+##-- End repository action, part 2.
+
+##++ Make action:
+ if ( ($odr->{make}->{def}) ) {
+ if ($verbose) {print "Info -- *** Begin preparing for build.\n";}
+
+ chdir("$wd") or die "Fatal -- couldn't chdir to $wd\n";
+ print "Info -- chdir to ".`cd`."\n" if ($verbose);
+
+ my ($path, $destpath);
+
+ # Copy athena\scripts\site\graft\krb5\Makefile.src to athena\auth\krb5:
+ $path = "scripts\\site\\graft\\krb5\\Makefile.src";
+ if (!-e $path) {die "Fatal -- Expected file $wd\\$path not found.";}
+ $destpath = "athena\\auth\\krb5\\Makefile.src";
+ !system("echo F | xcopy /D $wd\\$path $wd\\$destpath /Y > NUL") or die "Fatal -- Copy of $wd\\$path to $wd\\$destpath failed.";
+ print "Info -- copied $wd\\$path to $wd\\$destpath\n" if ($verbose);;
+
+ # Add DEBUG_SYMBOL to .../wshelper/Makefile.src:
+ $path = "athena\\wshelper\\wshelper\\Makefile.src";
+ if (!-e $path) {die "Fatal -- Expected file $wd\\$path not found.";}
+ if (system("grep DEBUG_SYMBOL $path > NUL") != 0) {
+ !system ("echo DEBUG_SYMBOL=1 >> $wd\\$path") or die "Fatal -- Append line to file failed.\n";
+ print "Info -- Added DEBUG_SYMBOL to $wd\\$path\n" if ($verbose);
+ }
+
+ # Prune any unwanted directories before the build:
+ pruneFiles($config->{Stages}->{Make}, $config);
+
+ if ($verbose) {print "Info -- *** End preparing for build.\n";}
+
+ my ($buildtarget, $buildtext);
+ if ($clean) {
+ $buildtarget = "clean" ;
+ $buildtext = " clean."
+ }
+ else {
+ $buildtarget = "" ;
+ $buildtext = "."
+ }
+
+ chdir("$wd\\athena") or die "Fatal -- couldn't chdir to source directory $wd\\athena\n";
+ print "Info -- chdir to ".`cd`."\n" if ($verbose);
+ local $dbgswitch = ($odr->{debug}->{def}) ? " " : "NODEBUG=1";
+ !system("perl ../scripts/build.pl --softdirs --nolog $buildtarget $dbgswitch BUILD_KFW=1 BUILD_OFFICIAL=1 DEBUG_SYMBOL=1")
+ or die "Fatal -- build $buildtarget failed.";
+
+ chdir("$wd") or die "Fatal -- couldn't chdir to $wd.";
+ print "Info -- chdir to ".`cd`."\n" if ($verbose);
+ if ($clean) {
+ if (-d "staging") {
+ !system("rm -rf staging") or die "Fatal -- Couldn't remove $wd\\staging.";
+ }
+ }
+
+ if ($verbose) {print "Info -- *** End build".$buildtext."\n";}
+ } ## End make conditional.
+ else {print "Info -- *** Skipping build.\n" if ($verbose);}
+##-- Make action.
+
+##++ Package action:
+ if (! $odr->{package}->{def}) { ## If /clean, nopackage will be set.
+ print "Info -- *** Skipping packaging.\n";
+ if ((-d $out) && ! $bOutputCleaned) {
+ print "Warning -- *** Output directory $out will not be cleaned.\n";
+ }
+ }
+ else {
+ if ($verbose) {print "Info -- *** Begin prepackage.\n";}
+
+ if (! $bOutputCleaned) { ## In case somebody cleaned $out before us.
+ if (-d $out) {!system("rm -rf $out/*") or die "Fatal -- Couldn't clean $out."} ## Clean output directory.
+ else {mkdir($out);}
+ $bOutputCleaned = 1;
+ }
+
+ # The build results are copied to a staging area, where the packager expects to find them.
+ # We put the staging area in the fixed area .../pismere/staging.
+ my $prepackage = $config->{Stages}->{PrePackage};
+ my $staging = "$wd\\staging";
+ chdir($wd) or die "Fatal -- couldn't chdir to $wd\n";
+ print "Info -- chdir to ".`cd`."\n" if ($verbose);
+ if (-d "staging") {
+ !system("rm -rf $staging/*") or die "Fatal -- Couldn't clean $staging.";
+ }
+ else {
+ mkdir($staging) or die "Fatal -- Couldn't create $staging.";
+ }
+
+ # Force Where From and To are relative to:
+ $prepackage->{CopyList}->{Config}->{From}->{root} = "$wd\\athena";
+ $prepackage->{CopyList}->{Config}->{To}->{root} = "$wd\\staging";
+ copyFiles($prepackage->{CopyList}, $config); ## Copy any files [this step takes a while]
+
+ # Sign files:
+ chdir($staging) or die "Fatal -- couldn't chdir to $staging\n";
+ print "Info -- chdir to ".`cd`."\n" if ($verbose);
+ if ($odr->{sign}->{def}) {
+ signFiles($config->{Stages}->{PostPackage}->{Config}->{Signing}, $config);
+ }
+
+ # Create working directories for building the installers:
+ if (-d "$wd\\buildwix") {!system("rm -rf $wd\\buildwix/*") or die "Fatal -- Couldn't clean $wd\\buildwix."}
+ !system("echo D | xcopy /s $wd\\staging\\install\\wix\\*.* $wd\\buildwix") or die "Fatal -- Couldn't create $wd\\buildwix.";
+ if (-d "$wd\\buildnsi") {!system("rm -rf $wd\\buildnsi/*") or die "Fatal -- Couldn't clean $wd\\buildnsi."}
+ !system("echo D | xcopy /s $wd\\staging\\install\\nsis\\*.* $wd\\buildnsi") or die "Fatal -- Couldn't create $wd\\buildnsi.";
+
+ chdir("$staging\\install\\wix") or die "Fatal -- Couldn't cd to $staging\\install\\wix";
+ print "Info -- chdir to ".`cd`."\n" if ($verbose);
+ # Correct errors in files.wxi:
+ !system("sed 's/WorkingDirectory=\"\\[dirbin\\]\"/WorkingDirectory=\"dirbin\"/g' files.wxi > a.tmp") or die "Fatal -- Couldn't modify files.wxi.";
+ !system("mv a.tmp files.wxi") or die "Fatal -- Couldn't update files.wxi.";
+
+ # Make sed script to run on the site-local configuration files:
+ local $tmpfile = "site-local.sed" ;
+ if (-e $tmpfile) {system("del $tmpfile");}
+ # Basic substitutions:
+ local $dblback_wd = $wd;
+ $dblback_wd =~ s/\\/\\\\/g;
+ !system("echo s/%BUILDDIR%/$dblback_wd/ >> $tmpfile") or die "Fatal -- Couldn't modify $tmpfile.";
+ local $dblback_staging = "$wd\\staging";
+ $dblback_staging =~ s/\\/\\\\/g;
+ !system("echo s/%TARGETDIR%/$dblback_staging/ >> $tmpfile") or die "Fatal -- Couldn't modify $tmpfile.";
+ local $dblback_sample = "$wd\\staging\\sample";
+ $dblback_sample =~ s/\\/\\\\/g;
+ !system("echo s/%CONFIGDIR-WIX%/$dblback_sample/ >> $tmpfile") or die "Fatal -- Couldn't modify $tmpfile.";
+ !system("echo s/%CONFIGDIR-NSI%/$dblback_staging/ >> $tmpfile") or die "Fatal -- Couldn't modify $tmpfile.";
+ !system("echo s/%VERSION_MAJOR%/$config->{Versions}->{'VER_PROD_MAJOR_STR'}/ >> $tmpfile") or die "Fatal -- Couldn't modify $tmpfile.";
+ !system("echo s/%VERSION_MINOR%/$config->{Versions}->{'VER_PROD_MINOR_STR'}/ >> $tmpfile") or die "Fatal -- Couldn't modify $tmpfile.";
+ !system("echo s/%VERSION_PATCH%/$config->{Versions}->{'VER_PROD_REV_STR'}/ >> $tmpfile") or die "Fatal -- Couldn't modify $tmpfile.";
+ # Strip out some defines so they can be replaced: [used for site-local.nsi]
+ !system("echo /\^!define\.\*RELEASE\.\*\$/d >> $tmpfile") or die "Fatal -- Couldn't modify $tmpfile.";
+ !system("echo /\^!define\.\*DEBUG\.\*\$/d >> $tmpfile") or die "Fatal -- Couldn't modify $tmpfile.";
+ !system("echo /\^!define\.\*BETA\.\*\$/d >> $tmpfile") or die "Fatal -- Couldn't modify $tmpfile.";
+
+ # Run the script on site-local.wxi:
+ !system("sed -f $tmpfile site-local-tagged.wxi > $wd\\buildwix\\site-local.wxi") or die "Fatal -- Couldn't modify site-local.wxi.";
+
+ # Now update site-local.nsi:
+ chdir "..\\nsis";
+ print "Info -- chdir to ".`cd`."\n" if ($verbose);
+ !system("sed -f ..\\wix\\$tmpfile site-local-tagged.nsi > b.tmp") or die "Fatal -- Couldn't modify site-local.wxi.";
+ # Add DEBUG or RELEASE:
+ if ($odr->{debug}->{def}) { ## debug build
+ !system("echo !define DEBUG >> b.tmp") or die "Fatal -- Couldn't modify b.tmp.";
+ }
+ else { ## release build
+ !system("echo !define RELEASE >> b.tmp") or die "Fatal -- Couldn't modify b.tmp.";
+ }
+ # Add BETA if present:
+ if (exists $config->{Versions}->{'BETA_STR'}) {
+ !system("echo !define BETA $config->{Versions}->{'BETA_STR'} >> b.tmp") or die "Fatal -- Couldn't modify b.tmp.";
+ }
+ !system("mv -f b.tmp $wd\\buildnsi\\site-local.nsi") or die "Fatal -- Couldn't replace site-local.nsi.";
+
+ # Run the script on nsi-includes-tagged.nsi:
+ !system("sed -f ..\\wix\\$tmpfile nsi-includes-tagged.nsi > $wd\\buildnsi\\nsi-includes.nsi") or die "Fatal -- Couldn't modify nsi-includes.nsi.";
+ !system("rm ..\\wix\\$tmpfile") or die "Fatal -- Couldn't remove $tmpfile.";
+
+ if ($verbose) {print "Info -- *** End prepackage.\n";}
+
+ if ($verbose) {print "Info -- *** Begin package.\n";}
+ # Make the msi:
+ chdir("$wd\\buildwix") or die "Fatal -- Couldn't cd to $wd\\buildwix";
+ print "Info -- *** Make .msi:\n" if ($verbose);
+ print "Info -- chdir to ".`cd`."\n" if ($verbose);
+ !system("$MAKE") or die "Error -- msi installer build failed.";
+
+ chdir("$wd\\buildnsi") or die "Fatal -- Couldn't cd to $wd\\buildnsi";
+ print "Info -- *** Make NSIS:\n" if ($verbose);
+ print "Info -- chdir to ".`cd`."\n" if ($verbose);
+ !system("cl.exe killer.cpp advapi32.lib") or die "Error -- nsis killer.exe not built.";
+ !system("rename killer.exe Killer.exe") or die "Error -- Couldn't rename killer.exe";
+ !system("makensis kfw.nsi") or die "Error -- executable installer build failed.";
+
+# Begin packaging extra items:
+ chdir($wd) or die "Fatal -- Couldn't cd to $wd";
+ print "Info -- chdir to ".`cd`."\n" if ($verbose);
+
+ zipXML($config->{Stages}->{PostPackage}, $config); ## Make zips.
+
+ $config->{Stages}->{PostPackage}->{CopyList}->{Config} = $config->{Stages}->{PostPackage}->{Config}; ## Use the post package config.
+ $config->{Stages}->{PostPackage}->{CopyList}->{Config}->{From}->{root} = "$src\\pismere";
+ $config->{Stages}->{PostPackage}->{CopyList}->{Config}->{To}->{root} = $out;
+ copyFiles($config->{Stages}->{PostPackage}->{CopyList}, $config); ## Copy any files
+
+ !system("rm -rf $wd\\buildwix") or die "Fatal -- Couldn't remove $wd\\buildwix.";
+ !system("rm -rf $wd\\buildnsi") or die "Fatal -- Couldn't remove $wd\\buildnsi.";
+
+ chdir($out) or die "Fatal -- Couldn't cd to $out";
+ print "Info -- chdir to ".`cd`."\n" if ($verbose);
+ if ($odr->{sign}->{def}) {
+ signFiles($config->{Stages}->{PostPackage}->{Config}->{Signing}, $config);
+ }
+
+ if ($verbose) {print "Info -- *** End package.\n";}
+ }
+##-- Package action.
+
+ system("rm -rf $src/a.tmp"); ## Clean up junk.
+ system("rm -rf $out/a.tmp"); ## Clean up junk.
+ system("rm -rf $out/ziptemp"); ## Clean up junk.
+
+# End logging:
+ if ($odr->{logfile}->{def}) {$l->stop;}
+
+ return 0;
+ } ## End subroutine main.
+
+$SIG{'INT'} = \&handler;
+$SIG{'QUIT'} = \&handler;
+
+exit(main()); \ No newline at end of file
diff --git a/src/windows/build/bootstrap.xml b/src/windows/build/bootstrap.xml
new file mode 100644
index 0000000..d0767b0
--- /dev/null
+++ b/src/windows/build/bootstrap.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!-- BKW: Build Kerberos for Windows -->
+<BKW_Config>
+ <Config>
+ <!-- Options: -->
+ <repository def="1" value="skip" options="skip checkout|co update|up" />
+ <src def="A" value="C:\KfW" /> <!-- Must be absolute path. -->
+
+ <!-- Repository settings: -->
+ <cvstag def="0" value="" />
+ <svntag def="0" value="" />
+ <svnbranch def="0" value="" />
+ <CVSROOT def="A" value=":kserver:cvs.mit.edu:/cvs/pismere" />
+ <SVNURL def="A" value="svn.mit.edu" /> <!-- NB: No protocol or slashes!! -->
+ <username def="0" value="" /> <!-- Needed for svn/plink. Override from command line -->
+
+ </Config>
+
+</BKW_Config> \ No newline at end of file
diff --git a/src/windows/build/commandandcontrol.pl b/src/windows/build/commandandcontrol.pl
new file mode 100644
index 0000000..53f8407
--- /dev/null
+++ b/src/windows/build/commandandcontrol.pl
@@ -0,0 +1,170 @@
+#!perl -w
+
+#use strict;
+
+sub commandandcontrol {
+ local ($configdefault, $bIgnoreCmdlineConfig) = @_;
+ local $OPT = {foo => 'bar'};
+
+ Getopt::Long::Configure('no_bundling', 'no_auto_abbrev',
+ 'no_getopt_compat', 'require_order',
+ 'ignore_case', 'pass_through',
+ 'prefix_pattern=(--|-|\+|\/)'
+ );
+ GetOptions($OPT,
+ 'help|h|?',
+ 'cvstag|c:s',
+ 'svntag|s:s',
+ 'svnbranch|b:s',
+ 'src|r:s',
+ 'out|o:s',
+ 'debug|d',
+ 'nodebug',
+ 'config|f=s',
+ 'logfile|l:s',
+ 'nolog',
+ 'repository:s',
+ 'username|u:s',
+ 'verbose|v',
+ 'vverbose',
+ 'make!',
+ 'clean',
+ 'package!',
+ 'sign!',
+ );
+
+ if ( $OPT->{help} ) {
+ usage();
+ exit(0);
+ }
+
+ delete $OPT->{foo};
+
+ local $argvsize = @ARGV;
+ if ($argvsize > 0) {
+ print "Error -- invalid argument: $ARGV[0]\n";
+ usage();
+ die;
+ }
+ # The first time C&C is called, it is OK to override the default (./bkwconfig.xml)
+ # with a value from the command line.
+ # The second time C&C is called, the repository has been updated and C&C will be passed
+ # <src>/pismere/athena/auth/krb5/windows/build/bkwconfig.xml. That value MUST be used.
+ if ($bIgnoreCmdlineConfig) {$OPT->{config} = $configdefault;}
+ elsif (! exists $OPT->{config}) {$OPT->{config} = $configdefault;}
+
+ my $configfile = $OPT->{config};
+ my $bOutputCleaned = 0;
+
+ print "Info -- Reading configuration from $configfile.\n";
+
+ # Get configuration file:
+ local $xml = new XML::Simple();
+ my $config = $xml->XMLin($configfile);
+ # Set up convenience variables:
+ local $odr = $config->{Config}; ## Options, directories, repository, environment.
+
+#while ($v = each %$OPT) {print "$v: $OPT->{$v}\n";}
+
+ # Scan the configuration for switch definitions:
+ while (($sw, $val) = each %$odr) {
+ next if (! exists $val->{def}); ## ?? Should always exist.
+
+ # Set/clear environment variables:
+ if ($val->{env}) {
+ if ($val->{def}) {$ENV{$sw} = (exists $val->{value}) ? $val->{value} : 1; }
+ else {delete $ENV{$sw}; }
+ }
+
+ # If the switch is in the command line, override the stored value:
+ if (exists $OPT->{$sw}) {
+ if (exists $val->{value}) {
+ $val->{value} = $OPT->{$sw};
+ $val->{def} = 1;
+ }
+ else {
+ $val->{def} = $OPT->{$sw}; ## If no<switch>, value will be zero.
+ }
+ }
+ # If the switch can be negated, test that, too:
+ if ( ! ($val->{def} =~ /A/)) {
+ local $nosw = "no".$sw;
+ if (exists $OPT->{$nosw}) {
+ $val->{def} = 0;
+ }
+ }
+
+ # For any switch definition with fixed values ("options"), validate:
+ if (exists $val->{options}) {
+ local $bValid = 0;
+ # options can be like value1|syn1 value2|syn2|syn3
+ foreach $option (split(/ /, $val->{options})) {
+ local $bFirst = 1;
+ local $sFirst;
+ foreach $opt (split(/\|/, $option)) {
+ # opt will be like value2, syn2, syn3
+ if ($bFirst) {
+ $sFirst = $opt; ## Remember the full name of the option.
+ $bFirst = 0;
+ }
+ if ($val->{value} =~ /$opt/i) {
+ $val->{value} = $sFirst; ## Save the full name.
+ $bValid = 1;
+ }
+ }
+ }
+ if (! $bValid) {
+ print "Fatal -- invalid $sw value $val->{value}. Possible values are $val->{options}.\n";
+ usage();
+ die;
+ }
+ }
+ }
+
+ # Don't allow /svntag and /svnbranch simultaneously:
+ if ( (length $odr->{svntag}->{value} > 0) &&
+ (length $odr->{svnbranch}->{value} > 0) ) {
+ die "Fatal -- Can't specify both /SVNTAG and /SVNBRANCH.";
+ }
+
+ return $config;
+ }
+
+
+sub usage {
+ print <<USAGE;
+Usage: $0 [options] NMAKE-options
+
+ Options are case insensitive.
+
+ Options:
+ /help /? usage information (what you now see).
+ /config /f path Path to config file. Default is bkwconfig.xml.
+ /srcdir /r dir Source directory to use. Should contain
+ pismere/athena. If cvstag or svntag is null,
+ the directory should be prepopulated.
+ /outdir /o dir Directory to be created where build results will go
+ /repository checkout | co \\ What repository action to take.
+ update | up ) Options are to checkout, update or
+ skip / take no action [skip].
+ /username /u name username used to access svn if checking out.
+ /cvstag /c tag use -r <tag> in cvs command
+ /svnbranch /b tag use /branches/<tag> instead of /trunk.
+ /svntag /s tag use /tags/<tag> instead of /trunk.
+ /debug /d Do debug make instead of release make.
+ /[no]make Control the make step.
+ /clean Build clean target.
+ /[no]package Control the packaging step.
+ /[no]sign Control signing of executable files.
+ /verbose /v Debug mode - verbose output.
+ /logfile /l path Where to write output. Default is bkw.pl.log.
+ /nolog Don't save output.
+ Other:
+ NMAKE-options any options you want to pass to NMAKE, which can be:
+ (note: /nologo is always used)
+
+USAGE
+ system("$MAKE /?");
+ }
+
+return 1; \ No newline at end of file
diff --git a/src/windows/build/copyfiles.pl b/src/windows/build/copyfiles.pl
new file mode 100644
index 0000000..79b6e15
--- /dev/null
+++ b/src/windows/build/copyfiles.pl
@@ -0,0 +1,137 @@
+#!perl -w
+
+#use strict;
+use XML::Simple;
+use Data::Dumper;
+
+sub copyFiles {
+ local ($xml, $config) = @_;
+ local @odr = $config->{Config};
+ local @files = $xml->{Files};
+ # Check for includes:
+ if (exists $xml->{Files}->{Include}->{path}) {
+ my $includepath = $xml->{Files}->{Include}->{path};
+ print "Info -- Including files from $includepath\n";
+ my $savedDir = `cd`;
+ $savedDir =~ s/\n//g;
+ chdir $originalDir; ## Includes are relative to where we were invoked.
+ print "Info -- chdir to ".`cd`."\n" if ($verbose);
+ my $tmp = new XML::Simple;
+ my $includeXML = $tmp->XMLin($includepath);
+ chdir $savedDir;
+ print "Info -- chdir to ".`cd`."\n" if ($verbose);
+
+ local $i = 0;
+ while ($includeXML->{File}[$i]) { ## Copy File entries from includeXML.
+ $files[0]->{File}[++$#{$files[0]->{File}}] = $includeXML->{File}[$i];
+ $i++;
+ }
+ delete $files->{Include};
+ }
+ ##++ Set up path substitution variables for use inside the copy loop:
+ # A path can contain a variable part, which will be handled here. If the variable part is
+ # the Always or BuildDependent tag, then the variable will be changed to the
+ # build-type-dependent PathFragment.
+ # If the variable part is the IgnoreTag, then the file will not be copied.
+ # If the variable part is %filestem%, it will be replaced with Config->FileStem->name.
+ my ($PathFragment, $BuildDependentTag, $IgnoreTag, $FileStemFragment, $fromRoot, $toRoot);
+ my $bPathTags = (exists $xml->{Config}->{DebugArea}) && (exists $xml->{Config}->{ReleaseArea});
+ my $bFileStem = (exists $xml->{Config}->{FileStem});
+
+ if ($odr->{debug}->{def}) { ## Debug build tags:
+ $PathFragment = $xml->{Config}->{DebugArea}->{value};
+ $BuildDependentTag = $xml->{Config}->{DebugTag}->{value};
+ $IgnoreTag = $xml->{Config}->{ReleaseTag}->{value};
+ }
+ else { ## Release build tags:
+ $PathFragment = $xml->{Config}->{ReleaseArea}->{value};
+ $BuildDependentTag = $xml->{Config}->{ReleaseTag}->{value};
+ $IgnoreTag = $xml->{Config}->{DebugTag}->{value};
+ }
+ my $AlwaysTag = $xml->{Config}->{AlwaysTag}->{value};
+ $FileStemFragment = $xml->{Config}->{FileStem}->{name};
+ $fromRoot = $xml->{Config}->{From}->{root};
+ $toRoot = $xml->{Config}->{To}->{root};
+ ##-- Set up path substitution variables for use inside the copy loop.
+ # For each file in the file list:
+ # Substitute any variable parts of the path name.
+ # Handle wildcards
+ # Copy
+
+ local $i = 0;
+ my $bOldDot = 1;
+ my $bDot = 0;
+ while ($files[0]->{File}[$i]) {
+
+ my ($name, $newname, $from, $to, $file);
+ $file = $files[0]->{File}->[$i];
+ $name = $file->{name};
+ if (exists $file->{newname}) {$newname = $file->{newname};}
+ else {$newname = $name;}
+ if ($name && (! exists $file->{ignore})) { ## Ignore or process this entry?
+ $from = "$fromRoot\\$file->{from}\\$name";
+ $to = "$toRoot\\$file->{to}\\$newname";
+ # Copy this file? Check for ignore tag [debug-only in release mode or vice versa].
+ if ( $bPathTags || $bFileStem || (index($from.$to, $IgnoreTag) <0) ) {
+ if ($bPathTags) { ## Apply PathTag substitutions:
+ $from =~ s/$AlwaysTag/$PathFragment/g;
+ $to =~ s/$AlwaysTag/$PathFragment/g;
+ $from =~ s/$BuildDependentTag/$PathFragment/g;
+ $to =~ s/$BuildDependentTag/$PathFragment/g;
+ }
+ if ($bFileStem) { ## FileStem substitution?
+ $from =~ s/%filestem%/$FileStemFragment/g;
+ $to =~ s/%filestem%/$FileStemFragment/g;
+ }
+ # %-DEBUG% substitution:
+ local $DebugFragment = ($odr->{debug}->{def}) ? "-DEBUG" : "";
+ $from =~ s/%\-DEBUG%/$DebugFragment/g;
+ $to =~ s/%\-DEBUG%/$DebugFragment/g;
+ $to =~ s/\*.*//; ## Truncate to path before any wildcard
+
+ my $bCopyOK = 1;
+ my $fromcheck = $from;
+ my $bRequired = ! (exists $file->{notrequired});
+ if ($name =~ /\*/) { ## Wildcard case
+ $fromcheck =~ s/\*.*//;
+ if ($bRequired && (! -d $fromcheck)) {
+ if ($bDot) {print "\n";}
+ die "Fatal -- Can't find $fromcheck";
+ }
+ $bCopyOK = !system("echo D | xcopy /D /F /Y /S $from $to > a.tmp 2>NUL");
+ }
+ else { ## Specific file case
+ if ($bRequired && (! -e $fromcheck)) {
+ if ($bDot) {print "\n";}
+ die "Fatal -- Can't find $fromcheck";
+ }
+ $bCopyOK = !system("echo F | xcopy /D /F /Y $from $to > a.tmp 2>NUL");
+ }
+
+ if ($bCopyOK) { ## xcopy OK - show progress
+ # To show progress when files aren't copied, print a string of dots.
+ open(MYINPUTFILE, "<a.tmp");
+ my(@lines) = <MYINPUTFILE>;
+ foreach $line (@lines) {
+ $bDot = ($line =~ /^0/);
+ }
+ close(MYINPUTFILE);
+ if (!$bDot && $bOldDot) {print "\n";}
+ if ($bDot) {print "."; STDOUT->flush;}
+ else {print "$from copied to $to\n";}
+ $bOldDot = $bDot;
+ }
+ else { ## xcopy failed
+ if (!exists $file->{notrequired}) {
+ if ($bDot) {print "\n";}
+ die "Fatal -- Copy of $from to $to failed";
+ }
+ } ## End xcopy succeed or fail
+ } ## End not dummy entry nor ignored
+ }
+ $i++;
+ }
+ if ($bDot) {print "\n";}
+ }
+
+return 1;
diff --git a/src/windows/build/copyfiles.xml b/src/windows/build/copyfiles.xml
new file mode 100644
index 0000000..2fb3747
--- /dev/null
+++ b/src/windows/build/copyfiles.xml
@@ -0,0 +1,218 @@
+<?xml version="1.0" encoding="utf-8" ?>
+ <Files>
+ <!-- File from paths are relative to <src>\pismere\athena -->
+ <!-- File to paths are relative to <src>\pismere\staging -->
+ <File dummy="foo" /> <!-- Forces XML::Simple behavior -->
+ <!-- Without this, XML::Simple does not make an anonymous array and I can't figure out how to iterate over it. -->
+
+ <!-- Build-dependent files (from release or debug build): -->
+ <File name="netidmgr_version.h" from="auth\krb5\src\windows\identity\obj\i386\%bldtype%\inc\" to="\inc\netidmgr"/>
+ <File name="netidmgr.h" from="auth\krb5\src\windows\identity\obj\i386\%bldtype%\inc\" to="\inc\netidmgr" />
+ <File name="perfstat.h" from="auth\krb5\src\windows\identity\obj\i386\%bldtype%\inc\" to="\inc\netidmgr"/>
+ <File name="utils.h" from="auth\krb5\src\windows\identity\obj\i386\%bldtype%\inc\" to="\inc\netidmgr" />
+ <File name="sync.h" from="auth\krb5\src\windows\identity\obj\i386\%bldtype%\inc\" to="\inc\netidmgr" />
+ <File name="mstring.h" from="auth\krb5\src\windows\identity\obj\i386\%bldtype%\inc\" to="\inc\netidmgr" />
+ <File name="kplugin.h" from="auth\krb5\src\windows\identity\obj\i386\%bldtype%\inc\" to="\inc\netidmgr" />
+ <File name="kmq.h" from="auth\krb5\src\windows\identity\obj\i386\%bldtype%\inc\" to="\inc\netidmgr" />
+ <File name="kmm.h" from="auth\krb5\src\windows\identity\obj\i386\%bldtype%\inc\" to="\inc\netidmgr" />
+ <File name="khuidefs.h" from="auth\krb5\src\windows\identity\obj\i386\%bldtype%\inc\" to="\inc\netidmgr" />
+ <File name="khtracker.h" from="auth\krb5\src\windows\identity\obj\i386\%bldtype%\inc\" to="\inc\netidmgr" />
+ <File name="khrescache.h" from="auth\krb5\src\windows\identity\obj\i386\%bldtype%\inc\" to="\inc\netidmgr" />
+ <File name="khremote.h" from="auth\krb5\src\windows\identity\obj\i386\%bldtype%\inc\" to="\inc\netidmgr" />
+ <File name="khprops.h" from="auth\krb5\src\windows\identity\obj\i386\%bldtype%\inc\" to="\inc\netidmgr" />
+ <File name="khnewcred.h" from="auth\krb5\src\windows\identity\obj\i386\%bldtype%\inc\" to="\inc\netidmgr" />
+ <File name="khmsgtypes.h" from="auth\krb5\src\windows\identity\obj\i386\%bldtype%\inc\" to="\inc\netidmgr" />
+ <File name="khlist.h" from="auth\krb5\src\windows\identity\obj\i386\%bldtype%\inc\" to="\inc\netidmgr" />
+ <File name="khhtlink.h" from="auth\krb5\src\windows\identity\obj\i386\%bldtype%\inc\" to="\inc\netidmgr" />
+ <File name="kherror.h" from="auth\krb5\src\windows\identity\obj\i386\%bldtype%\inc\" to="\inc\netidmgr" />
+ <File name="kherr.h" from="auth\krb5\src\windows\identity\obj\i386\%bldtype%\inc\" to="\inc\netidmgr" />
+ <File name="khdefs.h" from="auth\krb5\src\windows\identity\obj\i386\%bldtype%\inc\" to="\inc\netidmgr" />
+ <File name="khconfigui.h" from="auth\krb5\src\windows\identity\obj\i386\%bldtype%\inc\" to="\inc\netidmgr" />
+ <File name="khalerts.h" from="auth\krb5\src\windows\identity\obj\i386\%bldtype%\inc\" to="\inc\netidmgr" />
+ <File name="khactiondef.h" from="auth\krb5\src\windows\identity\obj\i386\%bldtype%\inc\" to="\inc\netidmgr" />
+ <File name="khaction.h" from="auth\krb5\src\windows\identity\obj\i386\%bldtype%\inc\" to="\inc\netidmgr" />
+ <File name="kcreddb.h" from="auth\krb5\src\windows\identity\obj\i386\%bldtype%\inc\" to="\inc\netidmgr" />
+ <File name="kconfig.h" from="auth\krb5\src\windows\identity\obj\i386\%bldtype%\inc\" to="\inc\netidmgr" />
+ <File name="hashtable.h" from="auth\krb5\src\windows\identity\obj\i386\%bldtype%\inc\" to="\inc\netidmgr" />
+ <File name="nidmgr32.lib" from="..\target\lib\i386\%bldtype%\" to="\lib\i386" />
+ <File name="xpprof32.lib" from="..\target\lib\i386\%bldtype%\" to="\lib\i386" />
+ <File name="wshelp32.lib" from="..\target\lib\i386\%bldtype%\" to="\lib\i386" />
+ <File name="loadfuncs.lib" from="..\target\lib\i386\%bldtype%\" to="\lib\i386" />
+ <File name="leashw32.lib" from="..\target\lib\i386\%bldtype%\" to="\lib\i386" />
+ <File name="krbv4w32.lib" from="..\target\lib\i386\%bldtype%\" to="\lib\i386" />
+ <File name="krbcc32.lib" from="..\target\lib\i386\%bldtype%\" to="\lib\i386" />
+ <File name="krb5_32.lib" from="..\target\lib\i386\%bldtype%\" to="\lib\i386" />
+ <File name="krb524.lib" from="..\target\lib\i386\%bldtype%\" to="\lib\i386" />
+ <File name="kclnt32.lib" from="..\target\lib\i386\%bldtype%\" to="\lib\i386" />
+ <File name="gssapi32.lib" from="..\target\lib\i386\%bldtype%\" to="\lib\i386" />
+ <File name="getopt.lib" from="..\target\lib\i386\%bldtype%\" to="\lib\i386" />
+ <File name="delaydlls.lib" from="..\target\lib\i386\%bldtype%\" to="\lib\i386" />
+ <File name="comerr32.lib" from="..\target\lib\i386\%bldtype%\" to="\lib\i386" />
+ <File name="netidmgr.exe" from="auth\krb5\src\windows\identity\obj\i386\%bldtype%\w2k\" to="\bin\i386\w2k" />
+ <File name="nidmgr32.dll" from="auth\krb5\src\windows\identity\obj\i386\%bldtype%\w2k\" to="\bin\i386\w2k" />
+ <File name="netidmgr.pdb" from="auth\krb5\src\windows\identity\obj\i386\%bldtype%\w2k\" to="\bin\i386\w2k" />
+ <File name="nidmgr32.pdb" from="auth\krb5\src\windows\identity\obj\i386\%bldtype%\w2k\" to="\bin\i386\w2k" />
+ <File name="kfwcpcc.pdb" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="kfwlogon.pdb" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="netidmgr.pdb" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="nidmgr32.pdb" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="krb4cred.pdb" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="krb5cred.pdb" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="mit2ms.pdb" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="kdeltkt.pdb" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="kcpytkt.pdb" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="xpprof32.pdb" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="wshelp32.pdb" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="ms2mit.pdb" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="leashw32.pdb" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="leash32.pdb" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="leash32.chm" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="kpasswd.pdb" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="kvno.pdb" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="krbv4w32.pdb" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="krbcc32s.pdb" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="krbcc32.pdb" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="k5sprt32.pdb" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="krb5_32.pdb" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="krb524.pdb" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="klist.pdb" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="kinit.pdb" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="kdestroy.pdb" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="kclnt32.pdb" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="k524init.pdb" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="gssapi32.pdb" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="gss-server.pdb" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="gss-client.pdb" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="gss.pdb" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="comerr32.pdb" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="kfwcpcc.exe" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="kfwlogon.dll" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="netidmgr.chm" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="netidmgr.exe" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="nidmgr32.dll" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="krb4cred_en_us.dll" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="krb4cred.dll" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="krb5cred_en_us.dll" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="krb5cred.dll" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="mit2ms.exe" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="kdeltkt.exe" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="kcpytkt.exe" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="xpprof32.dll" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="wshelp32.dll" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="ms2mit.exe" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="leashw32.dll" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="leash32.exe" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="kpasswd.exe" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="kvno.exe" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="krbv4w32.dll" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="krbcc32s.exe" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="krbcc32.dll" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="k5sprt32.dll" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="krb5_32.dll" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="krb524.dll" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="klist.exe" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="kinit.exe" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="kdestroy.exe" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="kclnt32.dll" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="k524init.exe" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="gssapi32.dll" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="gss-server.exe" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="gss-client.exe" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="gss.exe" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="comerr32.dll" from="..\target\bin\i386\%bldtype%\" to="\bin\i386" />
+ <File name="netiddev.chm" from="..\target\bin\i386\%bldtype%\" to="\doc" />
+<!-- why copy twice? <File name="NetIddev.chm" from="auth\krb5\src\windows\identity\obj\i386\%bldtype%\doc\" to="\doc" newname="netiddev.chm" /> -->
+
+ <!-- Build-INdependent files, always copied: -->
+ <File name="relnotes.html" from="..\doc\kerberos\" to="\doc" />
+ <File name="leash_userdoc.pdf" from="auth\leash\help\" to="\doc" />
+ <File name="NetIdMgr.pdf" from="auth\krb5\src\windows\identity\doc\" to="\doc" newname="netidmgr_userdoc.pdf" />
+ <File name="msi-deployment-guide.txt" from="auth\krb5\src\windows\installer\wix\" to="\doc" />
+ <File name="*" from="auth\krb5\src\windows\identity\sample\templates\credprov\" to="\sample\templates\credprov\" />
+ <File name="*" from="auth\krb5\src\windows\identity\sample\templates\credprov\images\" to="\sample\templates\credprov\images" />
+ <File name="*" from="auth\krb5\src\windows\identity\sample\templates\credprov\lang\" to="\sample\templates\credprov\lang" />
+ <File name="*" from="auth\krb5\src\windows\identity\sample\templates\credprov\lang\en_us\" to="\sample\templates\credprov\lang\en_us" />
+ <File name="kclient.h" from="auth\krb4\kclient\include\" to="\inc\kclient" />
+ <File name="kcmacerr.h" from="auth\krb4\kclient\include\" to="\inc\kclient" />
+ <File name="com_err.h" from="auth\krb4\include\" to="\inc\krb4" />
+ <File name="conf-pc.h" from="auth\krb4\include\" to="\inc\krb4" />
+ <File name="conf.h" from="auth\krb4\include\" to="\inc\krb4" />
+ <File name="des.h" from="auth\krb4\include\" to="\inc\krb4" />
+ <File name="kadm_err.h" from="auth\krb4\include\" to="\inc\krb4" />
+ <File name="krb.h" from="auth\krb4\include\" to="\inc\krb4" />
+ <File name="krberr.h" from="auth\krb4\include\" to="\inc\krb4" />
+ <File name="mit_copy.h" from="auth\krb4\include\" to="\inc\krb4" />
+ <File name="osconf.h" from="auth\krb4\include\" to="\inc\krb4" />
+ <File name="com_err.h" from="auth\krb5\src\include\" to="\inc\krb5" />
+ <File name="krb5.h" from="auth\krb5\src\include\" to="\inc\krb5" />
+ <File name="profile.h" from="auth\krb5\src\include\" to="\inc\krb5" />
+ <File name="win-mac.h" from="auth\krb5\src\include\" to="\inc\krb5" />
+ <File name="krb5.h" from="auth\krb5\src\include\krb5\" to="\inc\krb5\krb5" notrequired="true" />
+ <File name="gssapi.h" from="auth\krb5\src\include\gssapi\" to="\inc\krb5\gssapi" />
+ <File name="gssapi_generic.h" from="auth\krb5\src\include\gssapi\" to="\inc\krb5\gssapi" />
+ <File name="gssapi_krb5.h" from="auth\krb5\src\include\gssapi\" to="\inc\krb5\gssapi" />
+ <File name="des.h" from="auth\krb5\src\include\KerberosIV\" to="\inc\krb5\KerberosIV" />
+ <File name="kadm_err.h" from="auth\krb5\src\include\KerberosIV\" to="\inc\krb5\KerberosIV" />
+ <File name="krb_err.h" from="auth\krb5\src\include\KerberosIV\" to="\inc\krb5\KerberosIV" />
+ <File name="krb.h" from="auth\krb5\src\include\KerberosIV\" to="\inc\krb5\KerberosIV" />
+ <File name="mit-copyright.h" from="auth\krb5\src\include\KerberosIV\" to="\inc\krb5\KerberosIV" />
+ <File name="cacheapi.h" from="auth\krbcc\include\" to="\inc\krbcc" />
+ <File name="leasherr.h" from="auth\leash\include\" to="\inc\leash" />
+ <File name="leashinfo.h" from="auth\leash\include\" to="\inc\leash" />
+ <File name="leashwin.h" from="auth\leash\include\" to="\inc\leash" />
+ <File name="loadfuncs-afs.h" from="util\loadfuncs\" to="\inc\loadfuncs" />
+ <File name="loadfuncs-afs36.h" from="util\loadfuncs\" to="\inc\loadfuncs" />
+ <File name="loadfuncs-com_err.h" from="util\loadfuncs\" to="\inc\loadfuncs" />
+ <File name="loadfuncs-krb.h" from="util\loadfuncs\" to="\inc\loadfuncs" />
+ <File name="loadfuncs-krb5.h" from="util\loadfuncs\" to="\inc\loadfuncs" />
+ <File name="loadfuncs-krb524.h" from="util\loadfuncs\" to="\inc\loadfuncs" />
+ <File name="loadfuncs-leash.h" from="util\loadfuncs\" to="\inc\loadfuncs" />
+ <File name="loadfuncs-lsa.h" from="util\loadfuncs\" to="\inc\loadfuncs" />
+ <File name="loadfuncs-profile.h" from="util\loadfuncs\" to="\inc\loadfuncs" />
+ <File name="loadfuncs-wshelper.h" from="util\loadfuncs\" to="\inc\loadfuncs" />
+ <File name="loadfuncs.c" from="util\loadfuncs\" to="\inc\loadfuncs" />
+ <File name="loadfuncs.h" from="util\loadfuncs\" to="\inc\loadfuncs" />
+ <File name="nameser.h" from="wshelper\include\arpa\" to="\inc\wshelper\arpa" />
+ <File name="hesiod.h" from="wshelper\include\" to="\inc\wshelper" />
+ <File name="mitwhich.h" from="wshelper\include\" to="\inc\wshelper" />
+ <File name="resolv.h" from="wshelper\include\" to="\inc\wshelper" />
+ <File name="wshelper.h" from="wshelper\include\" to="\inc\wshelper" />
+ <File name="kfw-fixed.nsi" from="auth\krb5\src\windows\installer\nsis\" to="\install\nsis" />
+ <File name="kfw.ico" from="auth\krb5\src\windows\installer\nsis\" to="\install\nsis" />
+ <File name="kfw.nsi" from="auth\krb5\src\windows\installer\nsis\" to="\install\nsis" />
+ <File name="KfWConfigPage.ini" from="auth\krb5\src\windows\installer\nsis\" to="\install\nsis" />
+ <File name="KfWConfigPage2.ini" from="auth\krb5\src\windows\installer\nsis\" to="\install\nsis" />
+ <File name="killer.cpp" from="auth\krb5\src\windows\installer\nsis\" to="\install\nsis" />
+ <File name="licenses.rtf" from="auth\krb5\src\windows\installer\nsis\" to="\install\nsis" />
+ <File name="site-local-tagged.nsi" from="auth\krb5\src\windows\installer\nsis\" to="\install\nsis" />
+ <File name="nsi-includes-tagged.nsi" from="auth\krb5\src\windows\installer\nsis\" to="\install\nsis" />
+ <File name="utils.nsi" from="auth\krb5\src\windows\installer\nsis\" to="\install\nsis" />
+ <File name="msi-deployment-guide.txt" from="auth\krb5\src\windows\installer\wix\" to="\install\wix" />
+ <File name="config.wxi" from="auth\krb5\src\windows\installer\wix\" to="\install\wix" />
+ <File name="features.wxi" from="auth\krb5\src\windows\installer\wix\" to="\install\wix" />
+ <File name="files.wxi" from="auth\krb5\src\windows\installer\wix\" to="\install\wix" />
+ <File name="kfw.wxs" from="auth\krb5\src\windows\installer\wix\" to="\install\wix" />
+ <File name="Makefile" from="auth\krb5\src\windows\installer\wix\" to="\install\wix" />
+ <File name="property.wxi" from="auth\krb5\src\windows\installer\wix\" to="\install\wix" />
+ <File name="site-local-tagged.wxi" from="auth\krb5\src\windows\installer\wix\" to="\install\wix" />
+ <File name="bannrbmp.bmp" from="auth\krb5\src\windows\installer\wix\Binary\" to="\install\wix\Binary" />
+ <File name="completi.ico" from="auth\krb5\src\windows\installer\wix\Binary\" to="\install\wix\Binary" />
+ <File name="custicon.ico" from="auth\krb5\src\windows\installer\wix\Binary\" to="\install\wix\Binary" />
+ <File name="dlgbmp.bmp" from="auth\krb5\src\windows\installer\wix\Binary\" to="\install\wix\Binary" />
+ <File name="exclamic.ico" from="auth\krb5\src\windows\installer\wix\Binary\" to="\install\wix\Binary" />
+ <File name="info.bmp" from="auth\krb5\src\windows\installer\wix\Binary\" to="\install\wix\Binary" />
+ <File name="insticon.ico" from="auth\krb5\src\windows\installer\wix\Binary\" to="\install\wix\Binary" />
+ <File name="new.bmp" from="auth\krb5\src\windows\installer\wix\Binary\" to="\install\wix\Binary" />
+ <File name="removico.ico" from="auth\krb5\src\windows\installer\wix\Binary\" to="\install\wix\Binary" />
+ <File name="repairic.ico" from="auth\krb5\src\windows\installer\wix\Binary\" to="\install\wix\Binary" />
+ <File name="up.bmp" from="auth\krb5\src\windows\installer\wix\Binary\" to="\install\wix\Binary" />
+ <File name="custom.cpp" from="auth\krb5\src\windows\installer\wix\custom\" to="\install\wix\custom" />
+ <File name="custom.h" from="auth\krb5\src\windows\installer\wix\custom\" to="\install\wix\custom" />
+ <File name="config_1033.wxi" from="auth\krb5\src\windows\installer\wix\lang\" to="\install\wix\lang" />
+ <File name="strings_1033.wxl" from="auth\krb5\src\windows\installer\wix\lang\" to="\install\wix\lang" />
+ <File name="ui_1033.wxi" from="auth\krb5\src\windows\installer\wix\lang\" to="\install\wix\lang" />
+ <File name="license.rtf" from="auth\krb5\src\windows\installer\wix\lang\" to="\install\wix\lang" />
+ <File name="krb5.conf" from="auth\krb5\src\config-files\" to="\sample" newname="krb5.ini" />
+ <File name="krb.con" from="auth\krb4\sample-config\" to="\sample" />
+ <File name="krbrealm.con" from="auth\krb4\sample-config\" to="\sample" />
+ </Files> \ No newline at end of file
diff --git a/src/windows/build/corebinaryfiles.xml b/src/windows/build/corebinaryfiles.xml
new file mode 100644
index 0000000..bf51b0e
--- /dev/null
+++ b/src/windows/build/corebinaryfiles.xml
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="utf-8" ?>
+ <Files>
+ <!-- File from paths are relative to <src>/pismere. -->
+ <!-- File to paths are relative to <out>. -->
+ <File dummy="foo" /> <!-- Forces XML::Simple behavior -->
+ <!-- Without this, XML::Simple does not make an anonymous array and I can't figure out how to iterate over it. -->
+
+ <File name="netidmgr_userdoc.pdf" from="staging\doc" to="doc" />
+ <File name="leash_userdoc.pdf" from="staging\doc" to="doc" />
+ <File name="relnotes.html" from="doc\kerberos" to="doc" />
+
+ <File name="comerr32.dll" from="staging\bin\i386" to="\bin\i386\" />
+ <File name="comerr32.pdb" from="staging\bin\i386" to="\bin\i386\" />
+ <File name="gss-client.exe" from="staging\bin\i386" to="\bin\i386\" />
+ <File name="gss-client.pdb" from="staging\bin\i386" to="\bin\i386\" />
+ <File name="gss-server.exe" from="staging\bin\i386" to="\bin\i386\" />
+ <File name="gss-server.pdb" from="staging\bin\i386" to="\bin\i386\" />
+ <File name="gss.exe" from="staging\bin\i386" to="\bin\i386\" />
+ <File name="gss.pdb" from="staging\bin\i386" to="\bin\i386\" />
+ <File name="gssapi32.dll" from="staging\bin\i386" to="\bin\i386\" />
+ <File name="gssapi32.pdb" from="staging\bin\i386" to="\bin\i386\" />
+ <File name="k524init.exe" from="staging\bin\i386" to="\bin\i386\" />
+ <File name="k524init.pdb" from="staging\bin\i386" to="\bin\i386\" />
+ <File name="k5sprt32.dll" from="staging\bin\i386" to="\bin\i386\" />
+ <File name="k5sprt32.pdb" from="staging\bin\i386" to="\bin\i386\" />
+ <File name="kclnt32.dll" from="staging\bin\i386" to="\bin\i386\" />
+ <File name="kclnt32.pdb" from="staging\bin\i386" to="\bin\i386\" />
+ <File name="kcpytkt.exe" from="staging\bin\i386" to="\bin\i386\" />
+ <File name="kcpytkt.pdb" from="staging\bin\i386" to="\bin\i386\" />
+ <File name="kdeltkt.exe" from="staging\bin\i386" to="\bin\i386\" />
+ <File name="kdeltkt.pdb" from="staging\bin\i386" to="\bin\i386\" />
+ <File name="kdestroy.exe" from="staging\bin\i386" to="\bin\i386\" />
+ <File name="kdestroy.pdb" from="staging\bin\i386" to="\bin\i386\" />
+ <File name="kfwcpcc.exe" from="staging\bin\i386" to="\bin\i386\" />
+ <File name="kfwcpcc.pdb" from="staging\bin\i386" to="\bin\i386\" />
+ <File name="kfwlogon.dll" from="staging\bin\i386" to="\bin\i386\" />
+ <File name="kfwlogon.pdb" from="staging\bin\i386" to="\bin\i386\" />
+ <File name="kinit.exe" from="staging\bin\i386" to="\bin\i386\" />
+ <File name="kinit.pdb" from="staging\bin\i386" to="\bin\i386\" />
+ <File name="klist.exe" from="staging\bin\i386" to="\bin\i386\" />
+ <File name="klist.pdb" from="staging\bin\i386" to="\bin\i386\" />
+ <File name="kpasswd.exe" from="staging\bin\i386" to="\bin\i386\" />
+ <File name="kpasswd.pdb" from="staging\bin\i386" to="\bin\i386\" />
+ <File name="krb4cred.dll" from="staging\bin\i386" to="\bin\i386\" />
+ <File name="krb4cred.pdb" from="staging\bin\i386" to="\bin\i386\" />
+ <File name="krb4cred_en_us.dll" from="staging\bin\i386" to="\bin\i386\" />
+ <File name="krb524.dll" from="staging\bin\i386" to="\bin\i386\" />
+ <File name="krb524.pdb" from="staging\bin\i386" to="\bin\i386\" />
+ <File name="krb5cred.dll" from="staging\bin\i386" to="\bin\i386\" />
+ <File name="krb5cred.pdb" from="staging\bin\i386" to="\bin\i386\" />
+ <File name="krb5cred_en_us.dll" from="staging\bin\i386" to="\bin\i386\" />
+ <File name="krb5_32.dll" from="staging\bin\i386" to="\bin\i386\" />
+ <File name="krb5_32.pdb" from="staging\bin\i386" to="\bin\i386\" />
+ <File name="krbcc32.dll" from="staging\bin\i386" to="\bin\i386\" />
+ <File name="krbcc32.pdb" from="staging\bin\i386" to="\bin\i386\" />
+ <File name="krbcc32s.exe" from="staging\bin\i386" to="\bin\i386\" />
+ <File name="krbcc32s.pdb" from="staging\bin\i386" to="\bin\i386\" />
+ <File name="krbv4w32.dll" from="staging\bin\i386" to="\bin\i386\" />
+ <File name="krbv4w32.pdb" from="staging\bin\i386" to="\bin\i386\" />
+ <File name="kvno.exe" from="staging\bin\i386" to="\bin\i386\" />
+ <File name="kvno.pdb" from="staging\bin\i386" to="\bin\i386\" />
+ <File name="leash32.chm" from="staging\bin\i386" to="\bin\i386\" />
+ <File name="leash32.exe" from="staging\bin\i386" to="\bin\i386\" />
+ <File name="leash32.pdb" from="staging\bin\i386" to="\bin\i386\" />
+ <File name="leashw32.dll" from="staging\bin\i386" to="\bin\i386\" />
+ <File name="leashw32.pdb" from="staging\bin\i386" to="\bin\i386\" />
+ <File name="mit2ms.exe" from="staging\bin\i386" to="\bin\i386\" />
+ <File name="mit2ms.pdb" from="staging\bin\i386" to="\bin\i386\" />
+ <File name="ms2mit.exe" from="staging\bin\i386" to="\bin\i386\" />
+ <File name="ms2mit.pdb" from="staging\bin\i386" to="\bin\i386\" />
+ <File name="netidmgr.chm" from="staging\bin\i386" to="\bin\i386\" />
+ <File name="netidmgr.exe" from="staging\bin\i386" to="\bin\i386\" />
+ <File name="netidmgr.pdb" from="staging\bin\i386" to="\bin\i386\" />
+ <File name="nidmgr32.dll" from="staging\bin\i386" to="\bin\i386\" />
+ <File name="nidmgr32.pdb" from="staging\bin\i386" to="\bin\i386\" />
+ <File name="wshelp32.dll" from="staging\bin\i386" to="\bin\i386\" />
+ <File name="wshelp32.pdb" from="staging\bin\i386" to="\bin\i386\" />
+ <File name="xpprof32.dll" from="staging\bin\i386" to="\bin\i386\" />
+ <File name="xpprof32.pdb" from="staging\bin\i386" to="\bin\i386\" />
+
+ <File name="netidmgr.exe" from="staging\bin\i386\w2k" to="\bin\i386\w2k" />
+ <File name="netidmgr.pdb" from="staging\bin\i386\w2k" to="\bin\i386\w2k" />
+ <File name="nidmgr32.dll" from="staging\bin\i386\w2k" to="\bin\i386\w2k" />
+ <File name="nidmgr32.pdb" from="staging\bin\i386\w2k" to="\bin\i386\w2k" />
+ </Files> \ No newline at end of file
diff --git a/src/windows/build/css/main-action(1).css b/src/windows/build/css/main-action(1).css
new file mode 100644
index 0000000..a2302bc
--- /dev/null
+++ b/src/windows/build/css/main-action(1).css
@@ -0,0 +1,54 @@
+.sidebar {
+ BACKGROUND-COLOR: #f0f0f0
+}
+#logodiv {
+ PADDING-RIGHT: 15px; PADDING-LEFT: 10px; PADDING-BOTTOM: 10px; PADDING-TOP: 10px; TEXT-ALIGN: center
+}
+#menu {
+ WIDTH: 150px
+}
+.leftnav H1 {
+ PADDING-RIGHT: 4px; BORDER-TOP: white 1px solid; PADDING-LEFT: 4px; FONT-WEIGHT: bold; FONT-SIZE: 11px; PADDING-BOTTOM: 4px; MARGIN: 0px; PADDING-TOP: 4px; BORDER-BOTTOM: #ccc 1px solid
+}
+.leftnav H5 {
+ PADDING-RIGHT: 0px; BORDER-TOP: white 1px solid; PADDING-LEFT: 0px; FONT-WEIGHT: bold; FONT-SIZE: 11px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px; BORDER-BOTTOM: #ccc 1px solid
+}
+.leftnav H5 A {
+ BORDER-TOP-WIDTH: 0px; PADDING-RIGHT: 5px; DISPLAY: block; PADDING-LEFT: 5px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; PADDING-BOTTOM: 5px; PADDING-TOP: 5px; BORDER-RIGHT-WIDTH: 0px; TEXT-DECORATION: none
+}
+.leftnav H5 A:hover {
+ BORDER-TOP-WIDTH: 0px; DISPLAY: block; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BACKGROUND-COLOR: white; BORDER-RIGHT-WIDTH: 0px; TEXT-DECORATION: none
+}
+.leftnav UL {
+ PADDING-RIGHT: 0px; DISPLAY: inline; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px; LIST-STYLE-TYPE: none
+}
+.leftnav LI {
+ PADDING-RIGHT: 0px; DISPLAY: inline; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px
+}
+.leftnav LI A {
+ PADDING-RIGHT: 2px; DISPLAY: block; PADDING-LEFT: 5px; PADDING-BOTTOM: 2px; MARGIN: 0px; COLOR: white; PADDING-TOP: 2px; TEXT-DECORATION: none
+}
+.leftnav LI A.current {
+ COLOR: white; BACKGROUND-COLOR: #003366
+}
+.leftnav LI A:active {
+ COLOR: white
+}
+.leftnav LI A:visited {
+ COLOR: white
+}
+.leftnav LI A:hover {
+ COLOR: white; BACKGROUND-COLOR: #003366
+}
+.leftnav LI.current {
+ BACKGROUND-COLOR: #487bb7
+}
+.leftnav LI.current A {
+ COLOR: #3c78b5
+}
+#PageContent {
+ PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px; BACKGROUND-COLOR: #fff; TEXT-ALIGN: left
+}
+H1 {
+ PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-WEIGHT: bold; FONT-SIZE: 22px; BORDER-BOTTOM-WIDTH: 0px; PADDING-BOTTOM: 0px; MARGIN: 27px 0px 4px; COLOR: #660000; PADDING-TOP: 0px; FONT-FAMILY: Arial, sans-serif; BACKGROUND-COLOR: #fff
+}
diff --git a/src/windows/build/css/main-action.css b/src/windows/build/css/main-action.css
new file mode 100644
index 0000000..e34af6a
--- /dev/null
+++ b/src/windows/build/css/main-action.css
@@ -0,0 +1,1032 @@
+BODY {
+ FONT-WEIGHT: normal; FONT-SIZE: 11px; COLOR: #000000; LINE-HEIGHT: 16px; FONT-FAMILY: Verdana, arial, sans-serif
+}
+P {
+ FONT-WEIGHT: normal; FONT-SIZE: 11px; COLOR: #000000; LINE-HEIGHT: 16px; FONT-FAMILY: Verdana, arial, sans-serif
+}
+TD {
+ FONT-WEIGHT: normal; FONT-SIZE: 11px; COLOR: #000000; LINE-HEIGHT: 16px; FONT-FAMILY: Verdana, arial, sans-serif
+}
+TABLE {
+ FONT-WEIGHT: normal; FONT-SIZE: 11px; COLOR: #000000; LINE-HEIGHT: 16px; FONT-FAMILY: Verdana, arial, sans-serif
+}
+TR {
+ FONT-WEIGHT: normal; FONT-SIZE: 11px; COLOR: #000000; LINE-HEIGHT: 16px; FONT-FAMILY: Verdana, arial, sans-serif
+}
+.bodytext {
+ FONT-WEIGHT: normal; FONT-SIZE: 11px; COLOR: #000000; LINE-HEIGHT: 16px; FONT-FAMILY: Verdana, arial, sans-serif
+}
+.stepfield {
+ FONT-WEIGHT: normal; FONT-SIZE: 11px; COLOR: #000000; LINE-HEIGHT: 16px; FONT-FAMILY: Verdana, arial, sans-serif
+}
+#PageContent {
+ PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 20px; MARGIN: 0px; PADDING-TOP: 0px; BACKGROUND-COLOR: #fff; TEXT-ALIGN: left
+}
+BODY {
+ PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px; BACKGROUND-COLOR: #ffffff; TEXT-ALIGN: center
+}
+.monospaceInput {
+ FONT: 12px monospace
+}
+.wiki-content P {
+ PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 16px 0px; PADDING-TOP: 0px
+}
+.commentblock P {
+ PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 16px 0px; PADDING-TOP: 0px
+}
+.wiki-content-preview {
+ BORDER-RIGHT: #3c78b5 1px solid; PADDING-RIGHT: 5px; PADDING-LEFT: 5px; PADDING-BOTTOM: 5px; BORDER-LEFT: #3c78b5 1px solid; PADDING-TOP: 5px
+}
+UL {
+ MARGIN-TOP: 2px; MARGIN-BOTTOM: 2px; PADDING-BOTTOM: 0px; PADDING-TOP: 0px
+}
+OL {
+ MARGIN-TOP: 2px; MARGIN-BOTTOM: 2px; PADDING-BOTTOM: 0px; PADDING-TOP: 0px
+}
+PRE {
+ PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 5px 5px 5px 15px; PADDING-TOP: 0px; TEXT-ALIGN: left
+}
+.helpheading {
+ PADDING-RIGHT: 4px; PADDING-LEFT: 4px; FONT-WEIGHT: bold; PADDING-BOTTOM: 4px; MARGIN: 10px 0px 0px; PADDING-TOP: 4px; BORDER-BOTTOM: #3c78b5 1px solid; BACKGROUND-COLOR: #d0d9bd
+}
+.helpcontent {
+ PADDING-RIGHT: 4px; PADDING-LEFT: 4px; PADDING-BOTTOM: 20px; PADDING-TOP: 4px; BACKGROUND-COLOR: #f5f7f1
+}
+.code {
+ BORDER-RIGHT: #3c78b5 1px dashed; BORDER-TOP: #3c78b5 1px dashed; FONT-SIZE: 11px; MARGIN: 10px; BORDER-LEFT: #3c78b5 1px dashed; LINE-HEIGHT: 13px; BORDER-BOTTOM: #3c78b5 1px dashed; FONT-FAMILY: Courier
+}
+.focusedComment {
+ BACKGROUND: #ffffce
+}
+.commentBox {
+ BORDER-RIGHT: #bbb 1px solid; PADDING-RIGHT: 10px; BORDER-TOP: #bbb 1px solid; PADDING-LEFT: 10px; PADDING-BOTTOM: 10px; MARGIN: 5px 0px; BORDER-LEFT: #bbb 1px solid; PADDING-TOP: 10px; BORDER-BOTTOM: #bbb 1px solid
+}
+.focusedComment {
+ BORDER-RIGHT: #bbb 1px solid; PADDING-RIGHT: 10px; BORDER-TOP: #bbb 1px solid; PADDING-LEFT: 10px; PADDING-BOTTOM: 10px; MARGIN: 5px 0px; BORDER-LEFT: #bbb 1px solid; PADDING-TOP: 10px; BORDER-BOTTOM: #bbb 1px solid
+}
+.codeHeader {
+ PADDING-RIGHT: 3px; PADDING-LEFT: 3px; PADDING-BOTTOM: 3px; PADDING-TOP: 3px; BORDER-BOTTOM: #3c78b5 1px dashed; BACKGROUND-COLOR: #eeefcc; TEXT-ALIGN: center
+}
+.codeContent {
+ PADDING-RIGHT: 3px; PADDING-LEFT: 3px; PADDING-BOTTOM: 3px; PADDING-TOP: 3px; BACKGROUND-COLOR: #eeefcc; TEXT-ALIGN: left
+}
+.preformatted {
+ BORDER-RIGHT: #3c78b5 1px dashed; BORDER-TOP: #3c78b5 1px dashed; FONT-SIZE: 11px; MARGIN: 10px; BORDER-LEFT: #3c78b5 1px dashed; LINE-HEIGHT: 13px; BORDER-BOTTOM: #3c78b5 1px dashed; FONT-FAMILY: Courier
+}
+.preformattedHeader {
+ PADDING-RIGHT: 3px; PADDING-LEFT: 3px; PADDING-BOTTOM: 3px; PADDING-TOP: 3px; BORDER-BOTTOM: #3c78b5 1px dashed; BACKGROUND-COLOR: #eeefcc; TEXT-ALIGN: center
+}
+.preformattedContent {
+ PADDING-RIGHT: 3px; PADDING-LEFT: 3px; PADDING-BOTTOM: 3px; PADDING-TOP: 3px; BACKGROUND-COLOR: #eeefcc
+}
+.panel {
+ BORDER-RIGHT: #3c78b5 1px dashed; BORDER-TOP: #3c78b5 1px dashed; MARGIN: 0px 10px 10px; BORDER-LEFT: #3c78b5 1px dashed; BORDER-BOTTOM: #3c78b5 1px dashed
+}
+.panelHeader {
+ PADDING-RIGHT: 3px; PADDING-LEFT: 3px; PADDING-BOTTOM: 3px; PADDING-TOP: 3px; BORDER-BOTTOM: #3c78b5 1px dashed; BACKGROUND-COLOR: #eeefcc; TEXT-ALIGN: center
+}
+.panelContent {
+ PADDING-RIGHT: 5px; PADDING-LEFT: 5px; PADDING-BOTTOM: 5px; PADDING-TOP: 5px; BACKGROUND-COLOR: #eeefcc
+}
+.anonymousAlert {
+ BORDER-RIGHT: red 1px dashed; PADDING-RIGHT: 5px; BORDER-TOP: red 1px dashed; PADDING-LEFT: 5px; FONT-SIZE: 11px; PADDING-BOTTOM: 10px; MARGIN: 4px; BORDER-LEFT: red 1px dashed; LINE-HEIGHT: 13px; PADDING-TOP: 10px; BORDER-BOTTOM: red 1px dashed; BACKGROUND-COLOR: #eeefcc
+}
+.lockAlert {
+ BORDER-RIGHT: red 1px dashed; PADDING-RIGHT: 5px; BORDER-TOP: red 1px dashed; PADDING-LEFT: 5px; FONT-SIZE: 11px; PADDING-BOTTOM: 10px; MARGIN: 4px; BORDER-LEFT: red 1px dashed; WIDTH: 50%; LINE-HEIGHT: 13px; PADDING-TOP: 10px; BORDER-BOTTOM: red 1px dashed; BACKGROUND-COLOR: #eeefcc
+}
+.code-keyword {
+ COLOR: #000091
+}
+.code-object {
+ COLOR: #910091
+}
+.code-quote {
+ COLOR: #009100
+}
+.code-comment {
+ COLOR: #808080
+}
+.code-xml .code-keyword {
+ FONT-WEIGHT: bold
+}
+.code-tag {
+ COLOR: #000091
+}
+.breadcrumbs {
+ BORDER-RIGHT: #3c78b5 0px solid; PADDING-RIGHT: 0px; BORDER-TOP: #3c78b5 1px solid; PADDING-LEFT: 0px; FONT-SIZE: 11px; PADDING-BOTTOM: 3px; BORDER-LEFT: #3c78b5 0px solid; PADDING-TOP: 3px; BORDER-BOTTOM: #3c78b5 1px solid; BACKGROUND-COLOR: #eeefcc
+}
+.navmenu {
+ BORDER-RIGHT: #ccc 1px solid; BORDER-TOP: #ccc 1px solid; BORDER-LEFT: #ccc 1px solid; BORDER-BOTTOM: #ccc 1px solid
+}
+.menuheading {
+ PADDING-RIGHT: 4px; PADDING-LEFT: 4px; FONT-WEIGHT: bold; PADDING-BOTTOM: 2px; PADDING-TOP: 4px; BORDER-BOTTOM: #3c78b5 1px solid; BACKGROUND-COLOR: #eeefcc
+}
+.menuitems {
+ PADDING-RIGHT: 4px; PADDING-LEFT: 4px; PADDING-BOTTOM: 20px; PADDING-TOP: 4px
+}
+.rightpanel {
+ BORDER-LEFT: #ccc 1px solid; BORDER-BOTTOM: #ccc 1px solid
+}
+#helpheading {
+ PADDING-RIGHT: 4px; PADDING-LEFT: 4px; FONT-WEIGHT: bold; PADDING-BOTTOM: 4px; MARGIN: 0px; PADDING-TOP: 4px; BORDER-BOTTOM: #3c78b5 1px solid; BACKGROUND-COLOR: #d0d9bd; TEXT-ALIGN: left
+}
+#helpcontent {
+ PADDING-RIGHT: 4px; PADDING-LEFT: 4px; PADDING-BOTTOM: 4px; PADDING-TOP: 4px; BACKGROUND-COLOR: #f5f7f1
+}
+.helptab-unselected {
+ PADDING-RIGHT: 5px; PADDING-LEFT: 5px; FONT-WEIGHT: bold; PADDING-BOTTOM: 5px; PADDING-TOP: 5px; BACKGROUND-COLOR: #f5f7f1
+}
+.helptab-selected {
+ PADDING-RIGHT: 5px; PADDING-LEFT: 5px; FONT-WEIGHT: bold; PADDING-BOTTOM: 5px; PADDING-TOP: 5px; BACKGROUND-COLOR: #d0d9bd
+}
+.helptabs {
+ PADDING-RIGHT: 5px; PADDING-LEFT: 5px; PADDING-BOTTOM: 5px; MARGIN: 0px; PADDING-TOP: 5px; BACKGROUND-COLOR: #f5f7f1
+}
+.infopanel-heading {
+ PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-WEIGHT: bold; PADDING-BOTTOM: 2px; PADDING-TOP: 4px
+}
+.pagebody {
+
+}
+.pageheader {
+ PADDING-RIGHT: 5px; PADDING-LEFT: 0px; PADDING-BOTTOM: 5px; PADDING-TOP: 5px; BORDER-BOTTOM: #3c78b5 1px solid
+}
+.pagetitle {
+ FONT-WEIGHT: bold; FONT-SIZE: 22px; COLOR: #003366; FONT-FAMILY: Arial, sans-serif
+}
+.newpagetitle {
+ COLOR: #ccc! important
+}
+.steptitle {
+ FONT-WEIGHT: bold; FONT-SIZE: 18px; MARGIN-BOTTOM: 7px; COLOR: #003366; FONT-FAMILY: Arial, sans-serif
+}
+.substeptitle {
+ PADDING-RIGHT: 4px; PADDING-LEFT: 4px; FONT-WEIGHT: bold; FONT-SIZE: 12px; PADDING-BOTTOM: 1px; MARGIN: 2px 4px 4px; COLOR: #003366; PADDING-TOP: 2px; FONT-FAMILY: Arial, sans-serif
+}
+.stepdesc {
+ MARGIN-TOP: 7px; FONT-WEIGHT: normal; FONT-SIZE: 11px; MARGIN-BOTTOM: 7px; COLOR: #666666; LINE-HEIGHT: 16px; FONT-FAMILY: Verdana, arial, sans-serif
+}
+.steplabel {
+ FONT-WEIGHT: bold; FLOAT: left; WIDTH: 15%; COLOR: black; MARGIN-RIGHT: 4px; TEXT-ALIGN: right
+}
+.stepfield {
+ PADDING-RIGHT: 5px; PADDING-LEFT: 5px; BACKGROUND: #eeefcc; PADDING-BOTTOM: 5px; PADDING-TOP: 5px
+}
+.submitButtons {
+ MARGIN-TOP: 5px; TEXT-ALIGN: right
+}
+.formtitle {
+ FONT-WEIGHT: bold; FONT-SIZE: 12px; COLOR: #003366; FONT-FAMILY: Arial, sans-serif
+}
+.sectionbottom {
+ BORDER-BOTTOM: #3c78b5 1px solid
+}
+.topRow {
+ BORDER-TOP: #3c78b5 2px solid
+}
+.tabletitle {
+ PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-WEIGHT: bold; FONT-SIZE: 14px; PADDING-BOTTOM: 2px; MARGIN: 8px 4px 2px 0px; COLOR: #003366; PADDING-TOP: 3px; BORDER-BOTTOM: #3c78b5 2px solid; FONT-FAMILY: Arial, sans-serif
+}
+.pagesubheading {
+ PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-SIZE: 10px; PADDING-BOTTOM: 5px; COLOR: #666666; PADDING-TOP: 0px
+}
+HR {
+
+}
+A:link {
+ COLOR: #003366
+}
+A:visited {
+ COLOR: #003366
+}
+A:active {
+ COLOR: #003366
+}
+A:hover {
+ COLOR: #003366
+}
+H1 A:link {
+ TEXT-DECORATION: none
+}
+H1 A:visited {
+ TEXT-DECORATION: none
+}
+H1 A:active {
+ TEXT-DECORATION: none
+}
+H1 A:hover {
+ BORDER-BOTTOM: #003366 1px dotted
+}
+UNKNOWN {
+ MARGIN-TOP: 3px
+}
+.logocell {
+ PADDING-RIGHT: 10px; PADDING-LEFT: 10px; PADDING-BOTTOM: 10px; PADDING-TOP: 10px
+}
+INPUT {
+ FONT-SIZE: 11px; COLOR: #000000; FONT-FAMILY: verdana, geneva, arial, sans-serif
+}
+TEXTAREA {
+ FONT-SIZE: 11px; COLOR: #333333; FONT-FAMILY: verdana, geneva, arial, sans-serif
+}
+TEXTAREA.editor {
+ FONT-SIZE: 11px; COLOR: #333333; FONT-FAMILY: verdana, geneva, arial, sans-serif
+}
+.spacenametitle-printable {
+ MARGIN: 0px; FONT: 100 20px/25px Impact, Arial, Helvetica; COLOR: #999999
+}
+.spacenametitle-printable A {
+ COLOR: #999999; TEXT-DECORATION: none
+}
+.spacenametitle-printable A:visited {
+ COLOR: #999999; TEXT-DECORATION: none
+}
+.blogDate {
+ FONT-WEIGHT: bold; COLOR: black; TEXT-DECORATION: none
+}
+.blogSurtitle {
+ BORDER-RIGHT: #ddd 1px solid; PADDING-RIGHT: 3px; BORDER-TOP: #ddd 1px solid; PADDING-LEFT: 3px; BACKGROUND: #eeefcc; PADDING-BOTTOM: 3px; MARGIN: 1px 1px 10px; BORDER-LEFT: #ddd 1px solid; PADDING-TOP: 3px; BORDER-BOTTOM: #ddd 1px solid
+}
+.blogHeading {
+ PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-WEIGHT: bold; FONT-SIZE: 20px; PADDING-BOTTOM: 0px; MARGIN: 0px; LINE-HEIGHT: normal; PADDING-TOP: 0px
+}
+.blogHeading A {
+ COLOR: black; TEXT-DECORATION: none
+}
+.endsection {
+ MARGIN-TOP: 10px; COLOR: #666666; align: right
+}
+.endsectionleftnav {
+ MARGIN-TOP: 10px; COLOR: #666666; align: right
+}
+H1 {
+ PADDING-RIGHT: 2px; PADDING-LEFT: 2px; FONT-WEIGHT: bold; FONT-SIZE: 24px; PADDING-BOTTOM: 2px; MARGIN: 36px 0px 4px; COLOR: #003366; LINE-HEIGHT: normal; PADDING-TOP: 2px; BORDER-BOTTOM: #3c78b5 1px solid; BACKGROUND-COLOR: #eeefcc
+}
+H2 {
+ PADDING-RIGHT: 2px; PADDING-LEFT: 2px; FONT-WEIGHT: bold; FONT-SIZE: 18px; PADDING-BOTTOM: 2px; MARGIN: 27px 0px 4px; LINE-HEIGHT: normal; PADDING-TOP: 2px; BORDER-BOTTOM: #3c78b5 1px solid; BACKGROUND-COLOR: #eeefcc
+}
+H3 {
+ PADDING-RIGHT: 2px; PADDING-LEFT: 2px; FONT-WEIGHT: bold; FONT-SIZE: 14px; PADDING-BOTTOM: 2px; MARGIN: 21px 0px 4px; LINE-HEIGHT: normal; PADDING-TOP: 2px; BACKGROUND-COLOR: #eeefcc
+}
+H4 {
+ PADDING-RIGHT: 2px; PADDING-LEFT: 2px; FONT-WEIGHT: bold; FONT-SIZE: 12px; PADDING-BOTTOM: 2px; MARGIN: 18px 0px 4px; LINE-HEIGHT: normal; PADDING-TOP: 2px; BACKGROUND-COLOR: #eeefcc
+}
+H4.search {
+ PADDING-RIGHT: 4px; PADDING-LEFT: 4px; FONT-WEIGHT: normal; FONT-SIZE: 12px; PADDING-BOTTOM: 4px; MARGIN: 18px 0px 4px; LINE-HEIGHT: normal; PADDING-TOP: 4px; BACKGROUND-COLOR: #eeefcc
+}
+H5 {
+ PADDING-RIGHT: 2px; PADDING-LEFT: 2px; FONT-WEIGHT: bold; FONT-SIZE: 10px; PADDING-BOTTOM: 2px; MARGIN: 14px 0px 4px; LINE-HEIGHT: normal; PADDING-TOP: 2px; BACKGROUND-COLOR: #eeefcc
+}
+H6 {
+ PADDING-RIGHT: 2px; PADDING-LEFT: 2px; FONT-WEIGHT: bold; FONT-SIZE: 8px; PADDING-BOTTOM: 2px; MARGIN: 14px 0px 4px; LINE-HEIGHT: normal; PADDING-TOP: 2px; BACKGROUND-COLOR: #eeefcc
+}
+.smallfont {
+ FONT-SIZE: 10px
+}
+.descfont {
+ FONT-SIZE: 10px; COLOR: #666666
+}
+.smallerfont {
+ FONT-SIZE: 9px
+}
+.smalltext {
+ FONT-SIZE: 10px; COLOR: #666666
+}
+.smalltext A {
+ COLOR: #666666
+}
+.smalltext-blue {
+ FONT-SIZE: 10px; COLOR: #3c78b5
+}
+.surtitle {
+ FONT-SIZE: 14px; MARGIN-BOTTOM: 5px; MARGIN-LEFT: 1px; COLOR: #666666
+}
+.navItemOver {
+ FONT-WEIGHT: bold; FONT-SIZE: 10px; CURSOR: pointer; COLOR: #ffffff; BACKGROUND-COLOR: #003366; voice-family: inherit
+}
+.navItemOver A {
+ COLOR: #ffffff; BACKGROUND-COLOR: #003366; TEXT-DECORATION: none
+}
+.navItemOver A:visited {
+ COLOR: #ffffff; BACKGROUND-COLOR: #003366; TEXT-DECORATION: none
+}
+.navItemOver A:hover {
+ COLOR: #ffffff; BACKGROUND-COLOR: #003366; TEXT-DECORATION: none
+}
+.navItem {
+ FONT-WEIGHT: bold; FONT-SIZE: 10px; COLOR: #ffffff; BACKGROUND-COLOR: #3c78b5
+}
+.navItem A {
+ COLOR: #ffffff; TEXT-DECORATION: none
+}
+.navItem A:hover {
+ COLOR: #ffffff; TEXT-DECORATION: none
+}
+.navItem A:visited {
+ COLOR: #ffffff; TEXT-DECORATION: none
+}
+DIV.padded {
+ PADDING-RIGHT: 4px; PADDING-LEFT: 4px; PADDING-BOTTOM: 4px; PADDING-TOP: 4px
+}
+DIV.thickPadded {
+ PADDING-RIGHT: 10px; PADDING-LEFT: 10px; PADDING-BOTTOM: 10px; PADDING-TOP: 10px
+}
+H3.macrolibrariestitle {
+ MARGIN: 0px
+}
+DIV.centered {
+ MARGIN: 10px; TEXT-ALIGN: center
+}
+DIV.centered TABLE {
+ MARGIN: 0px auto; TEXT-ALIGN: left
+}
+.tableview TABLE {
+ MARGIN: 0px
+}
+.tableview TH {
+ PADDING-RIGHT: 0px; PADDING-LEFT: 5px; FONT-SIZE: 12px; PADDING-BOTTOM: 0px; COLOR: #003366; PADDING-TOP: 5px; BORDER-BOTTOM: #3c78b5 2px solid; TEXT-ALIGN: left
+}
+.tableview TD {
+ BORDER-RIGHT: #ccc 0px solid; PADDING-RIGHT: 10px; BORDER-TOP: #ccc 0px solid; PADDING-LEFT: 5px; PADDING-BOTTOM: 4px; MARGIN: 0px; BORDER-LEFT: #ccc 0px solid; PADDING-TOP: 4px; BORDER-BOTTOM: #ccc 1px solid; TEXT-ALIGN: left
+}
+.grid {
+ MARGIN: 2px 0px 5px; BORDER-COLLAPSE: collapse
+}
+.grid TH {
+ BORDER-RIGHT: #ccc 1px solid; PADDING-RIGHT: 4px; BORDER-TOP: #ccc 1px solid; PADDING-LEFT: 4px; BACKGROUND: #eeefcc; PADDING-BOTTOM: 2px; BORDER-LEFT: #ccc 1px solid; PADDING-TOP: 2px; BORDER-BOTTOM: #ccc 1px solid; TEXT-ALIGN: center
+}
+.grid TD {
+ BORDER-RIGHT: #ccc 1px solid; PADDING-RIGHT: 4px; BORDER-TOP: #ccc 1px solid; PADDING-LEFT: 4px; PADDING-BOTTOM: 3px; BORDER-LEFT: #ccc 1px solid; PADDING-TOP: 3px; BORDER-BOTTOM: #ccc 1px solid
+}
+.gridHover {
+ BACKGROUND-COLOR: #f9f9f9
+}
+TD.infocell {
+ BACKGROUND-COLOR: #eeefcc
+}
+.label {
+ FONT-WEIGHT: bold; COLOR: #003366
+}
+LABEL {
+ FONT-WEIGHT: bold; COLOR: #003366
+}
+.error {
+ BACKGROUND-COLOR: #fcc
+}
+.errorBox {
+ BORDER-RIGHT: #c00 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #c00 1px solid; PADDING-LEFT: 5px; PADDING-BOTTOM: 5px; MARGIN: 5px; BORDER-LEFT: #c00 1px solid; PADDING-TOP: 5px; BORDER-BOTTOM: #c00 1px solid; BACKGROUND-COLOR: #fcc
+}
+.errorMessage {
+ COLOR: #c00
+}
+.success {
+ BACKGROUND-COLOR: #dfd
+}
+.successBox {
+ BORDER-RIGHT: #090 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #090 1px solid; MARGIN-TOP: 5px; PADDING-LEFT: 5px; MARGIN-BOTTOM: 5px; PADDING-BOTTOM: 5px; BORDER-LEFT: #090 1px solid; PADDING-TOP: 5px; BORDER-BOTTOM: #090 1px solid; BACKGROUND-COLOR: #dfd
+}
+BLOCKQUOTE {
+ PADDING-RIGHT: 10px; PADDING-LEFT: 10px; MARGIN-LEFT: 5px; BORDER-LEFT: #3c78b5 1px solid; MARGIN-RIGHT: 0px
+}
+TABLE.confluenceTable {
+ MARGIN: 5px; BORDER-COLLAPSE: collapse
+}
+TABLE.confluenceTable TD.confluenceTd {
+ BORDER-RIGHT: #ccc 1px solid; PADDING-RIGHT: 4px; BORDER-TOP: #ccc 1px solid; PADDING-LEFT: 4px; PADDING-BOTTOM: 3px; BORDER-LEFT: #ccc 1px solid; PADDING-TOP: 3px; BORDER-BOTTOM: #ccc 1px solid
+}
+TABLE.confluenceTable TH.confluenceTh {
+ BORDER-RIGHT: #ccc 1px solid; PADDING-RIGHT: 4px; BORDER-TOP: #ccc 1px solid; PADDING-LEFT: 4px; PADDING-BOTTOM: 3px; BORDER-LEFT: #ccc 1px solid; PADDING-TOP: 3px; BORDER-BOTTOM: #ccc 1px solid; BACKGROUND-COLOR: #eeefcc; TEXT-ALIGN: center
+}
+TD.confluenceTd {
+ BORDER-RIGHT: #ccc 1px solid; PADDING-RIGHT: 4px; BORDER-TOP: #ccc 1px solid; PADDING-LEFT: 4px; PADDING-BOTTOM: 3px; BORDER-LEFT: #ccc 1px solid; PADDING-TOP: 3px; BORDER-BOTTOM: #ccc 1px solid
+}
+TH.confluenceTh {
+ BORDER-RIGHT: #ccc 1px solid; PADDING-RIGHT: 4px; BORDER-TOP: #ccc 1px solid; PADDING-LEFT: 4px; PADDING-BOTTOM: 3px; BORDER-LEFT: #ccc 1px solid; PADDING-TOP: 3px; BORDER-BOTTOM: #ccc 1px solid; BACKGROUND-COLOR: #eeefcc; TEXT-ALIGN: center
+}
+DIV.small {
+ FONT-SIZE: 9px
+}
+H1.pagename {
+ MARGIN-TOP: 0px
+}
+IMG.inline {
+
+}
+.loginform {
+ BORDER-RIGHT: #ccc 1px solid; BORDER-TOP: #ccc 1px solid; MARGIN: 5px; BORDER-LEFT: #ccc 1px solid; BORDER-BOTTOM: #ccc 1px solid
+}
+.previewnote {
+ FONT-SIZE: 11px; COLOR: red; TEXT-ALIGN: center
+}
+.previewcontent {
+ BACKGROUND: #e0e0e0
+}
+.messagecontent {
+ BACKGROUND: #e0e0e0
+}
+.conflictnote {
+
+}
+.createlink {
+ COLOR: maroon
+}
+A.createlink {
+ COLOR: maroon
+}
+.templateparameter {
+ FONT-SIZE: 9px; COLOR: darkblue
+}
+.diffadded {
+ PADDING-RIGHT: 1px; PADDING-LEFT: 4px; BACKGROUND: #ddffdd; PADDING-BOTTOM: 1px; BORDER-LEFT: darkgreen 4px solid; PADDING-TOP: 1px
+}
+.diffdeleted {
+ PADDING-RIGHT: 1px; PADDING-LEFT: 4px; BACKGROUND: #ffdddd; PADDING-BOTTOM: 1px; BORDER-LEFT: darkred 4px solid; COLOR: #999; PADDING-TOP: 1px
+}
+.diffnochange {
+ PADDING-RIGHT: 1px; PADDING-LEFT: 4px; PADDING-BOTTOM: 1px; BORDER-LEFT: lightgrey 4px solid; PADDING-TOP: 1px
+}
+.differror {
+ BACKGROUND: brown
+}
+.diff {
+ FONT-SIZE: 12px; LINE-HEIGHT: 14px; FONT-FAMILY: lucida console, courier new, fixed-width
+}
+.diffaddedchars {
+ FONT-WEIGHT: bolder; BACKGROUND-COLOR: #99ff99
+}
+.diffremovedchars {
+ FONT-WEIGHT: bolder; BACKGROUND-COLOR: #ff9999; TEXT-DECORATION: line-through
+}
+.greybackground {
+ BACKGROUND: #eeefcc
+}
+.greybox {
+ BORDER-RIGHT: #ddd 1px solid; PADDING-RIGHT: 3px; BORDER-TOP: #ddd 1px solid; PADDING-LEFT: 3px; PADDING-BOTTOM: 3px; MARGIN: 1px 1px 10px; BORDER-LEFT: #ddd 1px solid; PADDING-TOP: 3px; BORDER-BOTTOM: #ddd 1px solid
+}
+.borderedGreyBox {
+ BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 10px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 10px; PADDING-BOTTOM: 10px; BORDER-LEFT: #cccccc 1px solid; PADDING-TOP: 10px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeefcc
+}
+.greyboxfilled {
+ BORDER-RIGHT: #ddd 1px solid; PADDING-RIGHT: 3px; BORDER-TOP: #ddd 1px solid; PADDING-LEFT: 3px; BACKGROUND: #eeefcc; PADDING-BOTTOM: 3px; MARGIN: 1px 1px 10px; BORDER-LEFT: #ddd 1px solid; PADDING-TOP: 3px; BORDER-BOTTOM: #ddd 1px solid
+}
+.navBackgroundBox {
+ PADDING-RIGHT: 5px; PADDING-LEFT: 5px; FONT-WEIGHT: bold; FONT-SIZE: 22px; BACKGROUND: #3c78b5; PADDING-BOTTOM: 5px; COLOR: white; PADDING-TOP: 5px; FONT-FAMILY: Arial, sans-serif; TEXT-DECORATION: none
+}
+.previewBoxTop {
+ BORDER-RIGHT: #3c78b5 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #3c78b5 1px solid; PADDING-LEFT: 5px; PADDING-BOTTOM: 5px; MARGIN: 5px 0px 0px; BORDER-LEFT: #3c78b5 1px solid; PADDING-TOP: 5px; BORDER-BOTTOM: #3c78b5 0px solid; BACKGROUND-COLOR: #eeefcc; TEXT-ALIGN: center
+}
+.previewContent {
+ BORDER-RIGHT: #3c78b5 1px solid; PADDING-RIGHT: 10px; BORDER-TOP: #3c78b5 0px solid; PADDING-LEFT: 10px; PADDING-BOTTOM: 10px; MARGIN: 0px; BORDER-LEFT: #3c78b5 1px solid; PADDING-TOP: 10px; BORDER-BOTTOM: #3c78b5 0px solid; BACKGROUND-COLOR: #fff
+}
+.previewBoxBottom {
+ BORDER-RIGHT: #3c78b5 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #3c78b5 0px solid; PADDING-LEFT: 5px; PADDING-BOTTOM: 5px; MARGIN: 0px 0px 5px; BORDER-LEFT: #3c78b5 1px solid; PADDING-TOP: 5px; BORDER-BOTTOM: #3c78b5 1px solid; BACKGROUND-COLOR: #eeefcc; TEXT-ALIGN: center
+}
+.functionbox {
+ BORDER-RIGHT: #3c78b5 1px solid; PADDING-RIGHT: 3px; BORDER-TOP: #3c78b5 1px solid; PADDING-LEFT: 3px; PADDING-BOTTOM: 3px; MARGIN: 1px 1px 10px; BORDER-LEFT: #3c78b5 1px solid; PADDING-TOP: 3px; BORDER-BOTTOM: #3c78b5 1px solid; BACKGROUND-COLOR: #eeefcc
+}
+.functionbox-greyborder {
+ BORDER-RIGHT: #ddd 1px solid; PADDING-RIGHT: 3px; BORDER-TOP: #ddd 1px solid; PADDING-LEFT: 3px; PADDING-BOTTOM: 3px; MARGIN: 1px 1px 10px; BORDER-LEFT: #ddd 1px solid; PADDING-TOP: 3px; BORDER-BOTTOM: #ddd 1px solid; BACKGROUND-COLOR: #eeefcc
+}
+.search-highlight {
+ BACKGROUND-COLOR: #ffffcc
+}
+.rowNormal {
+ BACKGROUND-COLOR: #ffffff
+}
+.rowAlternate {
+ BACKGROUND-COLOR: #f7f7f7
+}
+.rowAlternateNoBottomColor {
+ BACKGROUND-COLOR: #f7f7f7
+}
+.rowAlternateNoBottomNoColor {
+
+}
+.rowAlternateNoBottomColor TD {
+ BORDER-BOTTOM-WIDTH: 0px
+}
+.rowAlternateNoBottomNoColor TD {
+ BORDER-BOTTOM-WIDTH: 0px
+}
+.rowHighlight {
+ BACKGROUND-COLOR: #eeefcc
+}
+TD.greenbar {
+ BORDER-RIGHT: #9c9c9c 1px solid; PADDING-RIGHT: 0px; BORDER-TOP: #9c9c9c 1px solid; PADDING-LEFT: 0px; FONT-SIZE: 2px; BACKGROUND: #00df00; PADDING-BOTTOM: 0px; BORDER-LEFT: #9c9c9c 1px solid; PADDING-TOP: 0px; BORDER-BOTTOM: #9c9c9c 1px solid
+}
+TD.redbar {
+ BORDER-RIGHT: #9c9c9c 1px solid; PADDING-RIGHT: 0px; BORDER-TOP: #9c9c9c 1px solid; PADDING-LEFT: 0px; FONT-SIZE: 2px; BACKGROUND: #df0000; PADDING-BOTTOM: 0px; BORDER-LEFT: #9c9c9c 1px solid; PADDING-TOP: 0px; BORDER-BOTTOM: #9c9c9c 1px solid
+}
+TD.darkredbar {
+ BORDER-RIGHT: #9c9c9c 1px solid; PADDING-RIGHT: 0px; BORDER-TOP: #9c9c9c 1px solid; PADDING-LEFT: 0px; FONT-SIZE: 2px; BACKGROUND: #af0000; PADDING-BOTTOM: 0px; BORDER-LEFT: #9c9c9c 1px solid; PADDING-TOP: 0px; BORDER-BOTTOM: #9c9c9c 1px solid
+}
+TR.testpassed {
+ PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-SIZE: 2px; BACKGROUND: #ddffdd; PADDING-BOTTOM: 0px; PADDING-TOP: 0px
+}
+TR.testfailed {
+ PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-SIZE: 2px; BACKGROUND: #ffdddd; PADDING-BOTTOM: 0px; PADDING-TOP: 0px
+}
+.toolbar {
+ MARGIN: 0px; BORDER-COLLAPSE: collapse
+}
+.toolbar TD {
+ BORDER-RIGHT: #ccc 1px solid; PADDING-RIGHT: 2px; BORDER-TOP: #ccc 1px solid; PADDING-LEFT: 2px; PADDING-BOTTOM: 2px; BORDER-LEFT: #ccc 1px solid; COLOR: #ccc; PADDING-TOP: 2px; BORDER-BOTTOM: #ccc 1px solid
+}
+TD.noformatting {
+ BORDER-RIGHT: 0px; PADDING-RIGHT: 0px; BORDER-TOP: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; BORDER-LEFT: 0px; PADDING-TOP: 0px; BORDER-BOTTOM: 0px; TEXT-ALIGN: center
+}
+.commentblock {
+ MARGIN: 12px 0px
+}
+.license-eval {
+ BORDER-TOP: #bbbbbb 1px solid; FONT-SIZE: 10px; FONT-FAMILY: Verdana, Arial, Helvetica, sans-serif; TEXT-ALIGN: center
+}
+.license-none {
+ BORDER-TOP: #bbbbbb 1px solid; FONT-SIZE: 10px; FONT-FAMILY: Verdana, Arial, Helvetica, sans-serif; TEXT-ALIGN: center
+}
+.license-nonprofit {
+ BORDER-TOP: #bbbbbb 1px solid; FONT-SIZE: 10px; FONT-FAMILY: Verdana, Arial, Helvetica, sans-serif; TEXT-ALIGN: center
+}
+.license-eval {
+ BACKGROUND-COLOR: #ffcccc
+}
+.license-none {
+ BACKGROUND-COLOR: #ffcccc
+}
+.license-eval B {
+ COLOR: #990000
+}
+.license-none B {
+ COLOR: #990000
+}
+.license-nonprofit {
+ BACKGROUND-COLOR: #ffffff
+}
+.bottomshadow {
+ BACKGROUND-IMAGE: url(/confluence/images/border/border_bottom.gif); BACKGROUND-REPEAT: repeat-x; HEIGHT: 12px
+}
+.navmenu .operations LI {
+ PADDING-LEFT: 0px; MARGIN-LEFT: 0px; LIST-STYLE-TYPE: none
+}
+.navmenu .operations UL {
+ PADDING-LEFT: 0px; MARGIN-LEFT: 0px; LIST-STYLE-TYPE: none
+}
+.navmenu .operations UL {
+ MARGIN-BOTTOM: 9px
+}
+.navmenu .label {
+
+}
+.toolbar DIV {
+ DISPLAY: none
+}
+.toolbar .label {
+ DISPLAY: none
+}
+.toolbar .operations {
+ DISPLAY: block
+}
+.toolbar .operations UL {
+ DISPLAY: inline; PADDING-LEFT: 0px; MARGIN-LEFT: 10px; LIST-STYLE-TYPE: none
+}
+.toolbar .operations LI {
+ DISPLAY: inline; LIST-STYLE-TYPE: none
+}
+#foldertab {
+ PADDING-RIGHT: 0px; PADDING-LEFT: 8px; PADDING-BOTTOM: 3px; FONT: bold 11px Verdana, sans-serif; MARGIN-LEFT: 0px; PADDING-TOP: 3px; BORDER-BOTTOM: #3c78b5 1px solid
+}
+#foldertab LI {
+ DISPLAY: inline; MARGIN: 0px; LIST-STYLE-TYPE: none
+}
+#foldertab LI A {
+ BORDER-RIGHT: #3c78b5 1px solid; PADDING-RIGHT: 0.5em; BORDER-TOP: #3c78b5 1px solid; PADDING-LEFT: 0.5em; BACKGROUND: #3c78b5; PADDING-BOTTOM: 3px; MARGIN-LEFT: 3px; BORDER-LEFT: #3c78b5 1px solid; PADDING-TOP: 3px; BORDER-BOTTOM: #3c78b5 1px; TEXT-DECORATION: none
+}
+#foldertab LI A:link {
+ COLOR: #ffffff
+}
+#foldertab LI A:visited {
+ COLOR: #ffffff
+}
+#foldertab LI A:hover {
+ BORDER-LEFT-COLOR: #003366; BACKGROUND: #003366; BORDER-BOTTOM-COLOR: #003366; COLOR: #ffffff; BORDER-TOP-COLOR: #003366; BORDER-RIGHT-COLOR: #003366
+}
+#foldertab LI A.current {
+ BACKGROUND: white; COLOR: black; BORDER-BOTTOM: white 1px solid
+}
+#foldertab LI A.current:link {
+ COLOR: black
+}
+#foldertab LI A.current:visited {
+ COLOR: black
+}
+#foldertab LI A.current:hover {
+ BACKGROUND: white; COLOR: black; BORDER-BOTTOM: white 1px solid
+}
+UL#squaretab {
+ PADDING-LEFT: 0px; FONT: bold 8px Verdana, sans-serif; MARGIN-LEFT: 0px; WHITE-SPACE: nowrap
+}
+#squaretab LI {
+ DISPLAY: inline; LIST-STYLE-TYPE: none
+}
+#squaretab A {
+ BORDER-RIGHT: #3c78b5 1px solid; PADDING-RIGHT: 6px; BORDER-TOP: #3c78b5 1px solid; PADDING-LEFT: 6px; PADDING-BOTTOM: 2px; BORDER-LEFT: #3c78b5 1px solid; PADDING-TOP: 2px; BORDER-BOTTOM: #3c78b5 1px solid
+}
+#squaretab A:link {
+ COLOR: #fff; BACKGROUND-COLOR: #3c78b5; TEXT-DECORATION: none
+}
+#squaretab A:visited {
+ COLOR: #fff; BACKGROUND-COLOR: #3c78b5; TEXT-DECORATION: none
+}
+#squaretab A:hover {
+ BORDER-LEFT-COLOR: #003366; BORDER-BOTTOM-COLOR: #003366; COLOR: #ffffff; BORDER-TOP-COLOR: #003366; BACKGROUND-COLOR: #003366; TEXT-DECORATION: none; BORDER-RIGHT-COLOR: #003366
+}
+#squaretab LI A#current {
+ BACKGROUND: white; COLOR: black
+}
+.blogcalendar {
+ PADDING-RIGHT: 2px; PADDING-LEFT: 2px; FONT-WEIGHT: normal; FONT-SIZE: x-small; PADDING-BOTTOM: 2px; LINE-HEIGHT: 140%; PADDING-TOP: 2px; FONT-FAMILY: verdana, arial, sans-serif
+}
+TABLE.blogcalendar {
+ BORDER-RIGHT: #3c78b5 1px solid; BORDER-TOP: #3c78b5 1px solid; BORDER-LEFT: #3c78b5 1px solid; BORDER-BOTTOM: #3c78b5 1px solid
+}
+.blogcalendar TH.calendarhead {
+ PADDING-RIGHT: 2px; PADDING-LEFT: 2px; FONT-WEIGHT: bold; FONT-SIZE: x-small; PADDING-BOTTOM: 2px; TEXT-TRANSFORM: uppercase; COLOR: #ffffff; PADDING-TOP: 2px; LETTER-SPACING: 0.3em; BACKGROUND-COLOR: #3c78b5
+}
+A.calendarhead {
+ PADDING-RIGHT: 2px; PADDING-LEFT: 2px; FONT-WEIGHT: bold; FONT-SIZE: x-small; PADDING-BOTTOM: 2px; TEXT-TRANSFORM: uppercase; COLOR: #ffffff; PADDING-TOP: 2px; LETTER-SPACING: 0.3em; BACKGROUND-COLOR: #3c78b5
+}
+.calendarhead:visited {
+ COLOR: white
+}
+.calendarhead:active {
+ COLOR: white
+}
+.calendarhead:hover {
+ COLOR: white
+}
+.blogcalendar TH {
+ PADDING-RIGHT: 2px; PADDING-LEFT: 2px; FONT-WEIGHT: bold; FONT-SIZE: x-small; PADDING-BOTTOM: 2px; PADDING-TOP: 2px; BACKGROUND-COLOR: #eeefcc
+}
+.blogcalendar TD {
+ FONT-WEIGHT: normal; FONT-SIZE: x-small
+}
+.searchGroup {
+ PADDING-RIGHT: 0px; PADDING-LEFT: 0px; BACKGROUND: #eeefcc; PADDING-BOTTOM: 10px; PADDING-TOP: 0px
+}
+.searchGroupHeading {
+ PADDING-RIGHT: 4px; PADDING-LEFT: 4px; FONT-WEIGHT: bold; FONT-SIZE: 10px; PADDING-BOTTOM: 1px; COLOR: #ffffff; PADDING-TOP: 2px; BACKGROUND-COLOR: #3c78b5
+}
+.searchItem {
+ PADDING-RIGHT: 4px; PADDING-LEFT: 4px; PADDING-BOTTOM: 1px; PADDING-TOP: 1px
+}
+.searchItemSelected {
+ PADDING-RIGHT: 4px; PADDING-LEFT: 4px; FONT-WEIGHT: bold; BACKGROUND: #ddd; PADDING-BOTTOM: 1px; PADDING-TOP: 1px
+}
+.permissionHeading {
+ BORDER-RIGHT: 0px solid; BORDER-TOP: 0px solid; FONT-SIZE: 16px; BORDER-LEFT: 0px solid; BORDER-BOTTOM: #bbb 1px solid; TEXT-ALIGN: left
+}
+.permissionTab {
+ BORDER-RIGHT: 0px solid; BORDER-TOP: 0px solid; FONT-SIZE: 10px; BACKGROUND: #3c78b5; BORDER-LEFT: 1px solid; COLOR: #ffffff; BORDER-BOTTOM: 0px solid
+}
+.permissionSuperTab {
+ BORDER-RIGHT: 0px solid; BORDER-TOP: 0px solid; BACKGROUND: #003366; BORDER-LEFT: 1px solid; COLOR: #ffffff; BORDER-BOTTOM: 0px solid
+}
+.permissionCell {
+ BORDER-RIGHT: 0px solid; BORDER-TOP: 0px solid; BORDER-LEFT: #bbb 1px solid; BORDER-BOTTOM: 0px solid
+}
+.warningPanel {
+ BORDER-RIGHT: #f0c000 1px solid; PADDING-RIGHT: 8px; BORDER-TOP: #f0c000 1px solid; PADDING-LEFT: 8px; BACKGROUND: #ffffce; PADDING-BOTTOM: 8px; MARGIN: 10px; BORDER-LEFT: #f0c000 1px solid; PADDING-TOP: 8px; BORDER-BOTTOM: #f0c000 1px solid
+}
+.alertPanel {
+ BORDER-RIGHT: #c00 1px solid; PADDING-RIGHT: 8px; BORDER-TOP: #c00 1px solid; PADDING-LEFT: 8px; BACKGROUND: #ffcccc; PADDING-BOTTOM: 8px; MARGIN: 10px; BORDER-LEFT: #c00 1px solid; PADDING-TOP: 8px; BORDER-BOTTOM: #c00 1px solid
+}
+.infoPanel {
+ BORDER-RIGHT: #3c78b5 1px solid; PADDING-RIGHT: 8px; BORDER-TOP: #3c78b5 1px solid; PADDING-LEFT: 8px; BACKGROUND: #d8e4f1; PADDING-BOTTOM: 8px; MARGIN: 10px; BORDER-LEFT: #3c78b5 1px solid; PADDING-TOP: 8px; BORDER-BOTTOM: #3c78b5 1px solid
+}
+.optionPadded {
+ PADDING-RIGHT: 2px; PADDING-LEFT: 2px; PADDING-BOTTOM: 2px; PADDING-TOP: 2px
+}
+.optionSelected {
+ BORDER-RIGHT: #ddd 1px solid; PADDING-RIGHT: 2px; BORDER-TOP: #ddd 1px solid; PADDING-LEFT: 2px; PADDING-BOTTOM: 2px; MARGIN: -1px; BORDER-LEFT: #ddd 1px solid; PADDING-TOP: 2px; BORDER-BOTTOM: #ddd 1px solid; BACKGROUND-COLOR: #ffffcc
+}
+.optionSelected A {
+ FONT-WEIGHT: bold; COLOR: black; TEXT-DECORATION: none
+}
+.noteMacro {
+ BORDER-RIGHT: #f0c000 1px solid; BORDER-TOP: #f0c000 1px solid; MARGIN-TOP: 5px; MARGIN-BOTTOM: 5px; BORDER-LEFT: #f0c000 1px solid; BORDER-BOTTOM: #f0c000 1px solid; BACKGROUND-COLOR: #ffffce; TEXT-ALIGN: left
+}
+.warningMacro {
+ BORDER-RIGHT: #c00 1px solid; BORDER-TOP: #c00 1px solid; MARGIN-TOP: 5px; MARGIN-BOTTOM: 5px; BORDER-LEFT: #c00 1px solid; BORDER-BOTTOM: #c00 1px solid; BACKGROUND-COLOR: #fcc; TEXT-ALIGN: left
+}
+.infoMacro {
+ BORDER-RIGHT: #3c78b5 1px solid; BORDER-TOP: #3c78b5 1px solid; MARGIN-TOP: 5px; MARGIN-BOTTOM: 5px; BORDER-LEFT: #3c78b5 1px solid; BORDER-BOTTOM: #3c78b5 1px solid; BACKGROUND-COLOR: #d8e4f1; TEXT-ALIGN: left
+}
+.tipMacro {
+ BORDER-RIGHT: #090 1px solid; BORDER-TOP: #090 1px solid; MARGIN-TOP: 5px; MARGIN-BOTTOM: 5px; BORDER-LEFT: #090 1px solid; BORDER-BOTTOM: #090 1px solid; BACKGROUND-COLOR: #dfd; TEXT-ALIGN: left
+}
+.informationMacroPadding {
+ PADDING-RIGHT: 0px; PADDING-LEFT: 5px; PADDING-BOTTOM: 0px; PADDING-TOP: 5px
+}
+TABLE.infoMacro TD {
+ BORDER-TOP-STYLE: none; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: none; BORDER-BOTTOM-STYLE: none
+}
+TABLE.warningMacro TD {
+ BORDER-TOP-STYLE: none; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: none; BORDER-BOTTOM-STYLE: none
+}
+TABLE.tipMacro TD {
+ BORDER-TOP-STYLE: none; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: none; BORDER-BOTTOM-STYLE: none
+}
+TABLE.noteMacro TD {
+ BORDER-TOP-STYLE: none; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: none; BORDER-BOTTOM-STYLE: none
+}
+TABLE.sectionMacro TD {
+ BORDER-TOP-STYLE: none; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: none; BORDER-BOTTOM-STYLE: none
+}
+TABLE.sectionMacroWithBorder TD.columnMacro {
+ BORDER-RIGHT: #cccccc 1px dashed; BORDER-TOP: #cccccc 1px dashed; BORDER-LEFT: #cccccc 1px dashed; BORDER-BOTTOM: #cccccc 1px dashed
+}
+.pagecontent {
+ PADDING-RIGHT: 10px; PADDING-LEFT: 10px; PADDING-BOTTOM: 10px; PADDING-TOP: 10px; TEXT-ALIGN: left
+}
+.topBarDiv A:link {
+ COLOR: #ffffff
+}
+.topBarDiv A:visited {
+ COLOR: #ffffff
+}
+.topBarDiv A:active {
+ COLOR: #ffffff
+}
+.topBarDiv A:hover {
+ COLOR: #ffffff
+}
+.topBarDiv {
+ COLOR: #ffffff
+}
+.topBar {
+ BACKGROUND-COLOR: #003366
+}
+.greyLinks A:link {
+ COLOR: #666666; TEXT-DECORATION: underline
+}
+.greyLinks A:visited {
+ COLOR: #666666; TEXT-DECORATION: underline
+}
+.greyLinks A:active {
+ COLOR: #666666; TEXT-DECORATION: underline
+}
+.greyLinks A:hover {
+ COLOR: #666666; TEXT-DECORATION: underline
+}
+.greyLinks {
+ PADDING-RIGHT: 10px; DISPLAY: block; PADDING-LEFT: 10px; PADDING-BOTTOM: 10px; COLOR: #666666; PADDING-TOP: 10px
+}
+.logoSpaceLink {
+ COLOR: #999999; TEXT-DECORATION: none
+}
+.logoSpaceLink A:link {
+ COLOR: #999999; TEXT-DECORATION: none
+}
+.logoSpaceLink A:visited {
+ COLOR: #999999; TEXT-DECORATION: none
+}
+.logoSpaceLink A:active {
+ COLOR: #999999; TEXT-DECORATION: none
+}
+.logoSpaceLink A:hover {
+ COLOR: #003366; TEXT-DECORATION: none
+}
+.basicPanelContainer {
+ BORDER-RIGHT: #3c78b5 1px solid; BORDER-TOP: #3c78b5 1px solid; MARGIN-TOP: 2px; MARGIN-BOTTOM: 8px; BORDER-LEFT: #3c78b5 1px solid; WIDTH: 100%; BORDER-BOTTOM: #3c78b5 1px solid
+}
+.basicPanelTitle {
+ PADDING-RIGHT: 5px; PADDING-LEFT: 5px; FONT-WEIGHT: bold; PADDING-BOTTOM: 5px; MARGIN: 0px; COLOR: black; PADDING-TOP: 5px; BACKGROUND-COLOR: #eeefcc
+}
+.basicPanelBody {
+ PADDING-RIGHT: 5px; PADDING-LEFT: 5px; PADDING-BOTTOM: 5px; MARGIN: 0px; PADDING-TOP: 5px
+}
+.separatorLinks A:link {
+ COLOR: white
+}
+.separatorLinks A:visited {
+ COLOR: white
+}
+.separatorLinks A:active {
+ COLOR: white
+}
+.greynavbar {
+ BORDER-TOP: #3c78b5 1px solid; MARGIN-TOP: 2px; BACKGROUND-COLOR: #eeefcc
+}
+DIV.headerField {
+ FLOAT: left; WIDTH: auto; HEIGHT: 100%
+}
+.headerFloat {
+ MARGIN-LEFT: auto; WIDTH: 50%
+}
+.headerFloatLeft {
+ FLOAT: left; MARGIN-BOTTOM: 10px; MARGIN-RIGHT: 20px
+}
+#headerRow {
+ PADDING-RIGHT: 10px; PADDING-LEFT: 10px; PADDING-BOTTOM: 10px; PADDING-TOP: 10px
+}
+DIV.license-personal {
+ COLOR: #ffffff; BACKGROUND-COLOR: #003366
+}
+DIV.license-personal A {
+ COLOR: #ffffff
+}
+.greyFormBox {
+ BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 5px; PADDING-BOTTOM: 5px; BORDER-LEFT: #cccccc 1px solid; PADDING-TOP: 5px; BORDER-BOTTOM: #cccccc 1px solid
+}
+.marginlessForm {
+ MARGIN: 0px
+}
+.openPageHighlight {
+ BORDER-RIGHT: #ddd 1px solid; PADDING-RIGHT: 2px; BORDER-TOP: #ddd 1px solid; PADDING-LEFT: 2px; PADDING-BOTTOM: 2px; BORDER-LEFT: #ddd 1px solid; PADDING-TOP: 2px; BORDER-BOTTOM: #ddd 1px solid; BACKGROUND-COLOR: #ffffcc
+}
+.editPageInsertLinks {
+ FONT-WEIGHT: bold; FONT-SIZE: 10px; COLOR: #666666
+}
+.editPageInsertLinks A {
+ FONT-WEIGHT: bold; FONT-SIZE: 10px; COLOR: #666666
+}
+.top10 A {
+ FONT-WEIGHT: bold; FONT-SIZE: 2em; COLOR: #003366
+}
+.top25 A {
+ FONT-WEIGHT: bold; FONT-SIZE: 1.6em; COLOR: #003366
+}
+.top50 A {
+ FONT-SIZE: 1.4em; COLOR: #003366
+}
+.top100 A {
+ FONT-SIZE: 1.2em; COLOR: #003366
+}
+.heatmap {
+ MARGIN: 0px auto; WIDTH: 95%; LIST-STYLE-TYPE: none
+}
+.heatmap A {
+ TEXT-DECORATION: none
+}
+.heatmap A:hover {
+ TEXT-DECORATION: underline
+}
+.heatmap LI {
+ DISPLAY: inline
+}
+.minitab {
+ PADDING-RIGHT: 0px; MARGIN-TOP: 1px; PADDING-LEFT: 8px; FLOAT: none; MARGIN-BOTTOM: 0px; PADDING-BOTTOM: 3px; FONT: bold 9px Verdana, sans-serif; MARGIN-LEFT: 0px; PADDING-TOP: 3px; BORDER-BOTTOM: #3c78b5 1px solid; TEXT-DECORATION: none
+}
+.selectedminitab {
+ BORDER-RIGHT: #3c78b5 1px solid; PADDING-RIGHT: 0.5em; BORDER-TOP: #3c78b5 1px solid; MARGIN-TOP: 1px; PADDING-LEFT: 0.5em; BACKGROUND: white; PADDING-BOTTOM: 3px; MARGIN-LEFT: 3px; BORDER-LEFT: #3c78b5 1px solid; COLOR: #000000; PADDING-TOP: 3px; BORDER-BOTTOM: white 1px solid; TEXT-DECORATION: none
+}
+.unselectedminitab {
+ BORDER-RIGHT: #3c78b5 1px solid; PADDING-RIGHT: 0.5em; BORDER-TOP: #3c78b5 1px solid; MARGIN-TOP: 1px; PADDING-LEFT: 0.5em; BACKGROUND: #3c78b5; PADDING-BOTTOM: 3px; MARGIN-LEFT: 3px; BORDER-LEFT: #3c78b5 1px solid; COLOR: #ffffff; PADDING-TOP: 3px; BORDER-BOTTOM: #3c78b5 1px; TEXT-DECORATION: none
+}
+A.unselectedminitab:hover {
+ BORDER-LEFT-COLOR: #003366; BACKGROUND: #003366; BORDER-BOTTOM-COLOR: #003366; COLOR: #ffffff; BORDER-TOP-COLOR: #003366; BORDER-RIGHT-COLOR: #003366
+}
+A.unselectedminitab:link {
+ COLOR: white
+}
+A.unselectedminitab:visited {
+ COLOR: white
+}
+A.selectedminitab:link {
+ COLOR: black
+}
+A.selectedminitab:visited {
+ COLOR: black
+}
+.linkerror {
+ BACKGROUND-COLOR: #fcc
+}
+A.labelOperationLink:link {
+ TEXT-DECORATION: underline
+}
+A.labelOperationLink:active {
+ TEXT-DECORATION: underline
+}
+A.labelOperationLink:visited {
+ TEXT-DECORATION: underline
+}
+A.labelOperationLink:hover {
+ TEXT-DECORATION: underline
+}
+A.newLabel:link {
+ BACKGROUND-COLOR: #ddffdd
+}
+A.newLabel:active {
+ BACKGROUND-COLOR: #ddffdd
+}
+A.newLabel:visited {
+ BACKGROUND-COLOR: #ddffdd
+}
+A.newLabel:hover {
+ BACKGROUND-COLOR: #ddffdd
+}
+UL.square {
+ LIST-STYLE-TYPE: square
+}
+.inline-control-link {
+ PADDING-RIGHT: 2px; PADDING-LEFT: 2px; FONT-SIZE: 9px; BACKGROUND: #ffc; PADDING-BOTTOM: 2px; TEXT-TRANSFORM: uppercase; COLOR: #666; PADDING-TOP: 2px; TEXT-DECORATION: none
+}
+.inline-control-link A:link {
+ TEXT-DECORATION: none
+}
+.inline-control-link A:active {
+ TEXT-DECORATION: none
+}
+.inline-control-link A:visited {
+ TEXT-DECORATION: none
+}
+.inline-control-link A:hover {
+ TEXT-DECORATION: none
+}
+.inline-control-link {
+ PADDING-RIGHT: 2px; PADDING-LEFT: 2px; FONT-SIZE: 9px; BACKGROUND: #ffc; PADDING-BOTTOM: 2px; TEXT-TRANSFORM: uppercase; CURSOR: pointer; COLOR: #666; PADDING-TOP: 2px; TEXT-DECORATION: none
+}
+DIV.auto_complete {
+ BACKGROUND: #fff; WIDTH: 350px
+}
+DIV.auto_complete UL {
+ BORDER-RIGHT: #888 1px solid; PADDING-RIGHT: 0px; BORDER-TOP: #888 1px solid; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; BORDER-LEFT: #888 1px solid; WIDTH: 100%; PADDING-TOP: 0px; BORDER-BOTTOM: #888 1px solid; LIST-STYLE-TYPE: none
+}
+DIV.auto_complete UL LI {
+ PADDING-RIGHT: 3px; PADDING-LEFT: 3px; PADDING-BOTTOM: 3px; MARGIN: 0px; PADDING-TOP: 3px
+}
+DIV.auto_complete UL LI.selected {
+ BACKGROUND-COLOR: #ffb
+}
+DIV.auto_complete UL STRONG.highlight {
+ PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; COLOR: #800; PADDING-TOP: 0px
+}
+.toogleFormDiv {
+ BORDER-RIGHT: #a7a6aa 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #a7a6aa 1px solid; MARGIN-TOP: 5px; PADDING-LEFT: 5px; PADDING-BOTTOM: 5px; BORDER-LEFT: #a7a6aa 1px solid; PADDING-TOP: 5px; BORDER-BOTTOM: #a7a6aa 1px solid; BACKGROUND-COLOR: white
+}
+.toogleInfoDiv {
+ BORDER-RIGHT: #a7a6aa 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #a7a6aa 1px solid; MARGIN-TOP: 10px; DISPLAY: none; PADDING-LEFT: 5px; PADDING-BOTTOM: 5px; BORDER-LEFT: #a7a6aa 1px solid; PADDING-TOP: 5px; BORDER-BOTTOM: #a7a6aa 1px solid; BACKGROUND-COLOR: white
+}
+.inputSection {
+ MARGIN-BOTTOM: 20px
+}
+#editBox {
+ BACKGROUND-COLOR: #eeefcc
+}
+.leftnav LI A {
+ PADDING-RIGHT: 2px; BORDER-TOP: #3c78b5 1px solid; DISPLAY: block; PADDING-LEFT: 5px; PADDING-BOTTOM: 2px; MARGIN: 0px; COLOR: white; PADDING-TOP: 2px; BACKGROUND-COLOR: #3c78b5; TEXT-DECORATION: none
+}
+.leftnav LI A:active {
+ COLOR: white
+}
+.leftnav LI A:visited {
+ COLOR: white
+}
+.leftnav LI A:hover {
+ COLOR: white; BACKGROUND-COLOR: #003366
+}
+.replaced {
+ BACKGROUND-COLOR: #33cc66
+}
+.topPadding {
+ MARGIN-TOP: 20px
+}
+.form-block {
+ PADDING-RIGHT: 6px; PADDING-LEFT: 6px; PADDING-BOTTOM: 6px; PADDING-TOP: 6px
+}
+.form-error-block {
+ PADDING-RIGHT: 12px; BORDER-TOP: #eeefcc 1px solid; PADDING-LEFT: 12px; BACKGROUND: #fcc; MARGIN-BOTTOM: 6px; PADDING-BOTTOM: 0px; PADDING-TOP: 0px; BORDER-BOTTOM: #eeefcc 1px solid
+}
+.form-element-large {
+ FONT-WEIGHT: bold; FONT-SIZE: 16px; COLOR: #003366; FONT-FAMILY: Arial, sans-serif
+}
+.form-element-small {
+ FONT-WEIGHT: bold; FONT-SIZE: 12px; COLOR: #003366; FONT-FAMILY: Arial, sans-serif
+}
+.form-header {
+ PADDING-RIGHT: 12px; BORDER-TOP: #eeefcc 1px solid; PADDING-LEFT: 12px; BACKGROUND: lightyellow; MARGIN-BOTTOM: 6px; PADDING-BOTTOM: 0px; PADDING-TOP: 0px; BORDER-BOTTOM: #eeefcc 1px solid
+}
+.form-header P {
+ MARGIN: 12px 0px; LINE-HEIGHT: normal
+}
+.form-block P {
+ MARGIN: 12px 0px; LINE-HEIGHT: normal
+}
+.form-error-block P {
+ MARGIN: 12px 0px; LINE-HEIGHT: normal
+}
+.form-example {
+ FONT-SIZE: 11px; COLOR: #888
+}
+.form-divider {
+ MARGIN-BOTTOM: 6px; BORDER-BOTTOM: #ccc 1px solid
+}
+.form-buttons {
+ PADDING-RIGHT: 10px; BORDER-TOP: #ccc 1px solid; MARGIN-TOP: 6px; PADDING-LEFT: 10px; BACKGROUND: #eeefcc; PADDING-BOTTOM: 10px; PADDING-TOP: 10px; BORDER-BOTTOM: #ccc 1px solid; TEXT-ALIGN: center
+}
+.form-buttons INPUT {
+ WIDTH: 100px
+}
+.form-block .error {
+ PADDING-RIGHT: 6px; PADDING-LEFT: 6px; MARGIN-BOTTOM: 6px; PADDING-BOTTOM: 6px; PADDING-TOP: 6px
+}
diff --git a/src/windows/build/makeZip.pl b/src/windows/build/makeZip.pl
new file mode 100644
index 0000000..1a1b533
--- /dev/null
+++ b/src/windows/build/makeZip.pl
@@ -0,0 +1,84 @@
+#!perl -w
+
+#use strict;
+
+require "prunefiles.pl";
+
+use Data::Dumper;
+
+sub makeZip {
+ local ($zip, $config) = @_;
+
+ local $odr = $config->{Config}; ## Options, directories, repository, environment.
+ local $src = $odr->{src}->{value};
+ local $out = $odr->{out}->{value};
+ local $zipname = $zip->{filename};
+ local $filestem = $config->{Stages}->{PostPackage}->{Config}->{FileStem}->{name};
+ $zipname =~ s/%filestem%/$filestem/g;
+ if (exists $zip->{Requires}) {
+ local $bMakeIt = 1;
+ local $rverb = $odr->{repository}->{value};
+ local $j = 0;
+ while ($zip->{Requires}->{Switch}[$j]) { ## Check Require switches
+ local $switch = $zip->{Requires}->{Switch}[$j];
+ if (exists $switch->{name}) { ## Ignore dummy entry
+ # We handle REPOSITORY and CLEAN switches:
+ if ($switch->{name} =~ /REPOSITORY/i) {
+ $bMakeIt &&= ($switch->{value} =~ /$rverb/i); ## Repository verb must match requirement
+ }
+ elsif ($switch->{name} =~ /CLEAN/i) { ## Clean must be specified
+ $bMakeIt &&= $clean;
+ }
+ else {print "Error -- Unsupported switch $switch->{name} in Requires in ".Dumper($zip);
+ $bMakeIt = 0;
+ }
+ }
+ $j++;
+ }
+ if ( !$bMakeIt ) {
+ if (exists $zip->{Requires}->{ErrorMsg}) {
+ print "Error -- $zip->{Requires}->{ErrorMsg}->{text}\n";
+ }
+ else {
+ print "Error -- requirements not met for building $zipname.\n";
+ }
+ return 0;
+ }
+ }
+
+ local $ziptemp = "$out\\ziptemp";
+ chdir "$out";
+ print "Info -- chdir to ".`cd`."\n" if ($verbose);
+ system("rm -rf $ziptemp") if (-d $ziptemp);
+ die "Fatal -- Couldn't remove $ziptemp" if (-d $ziptemp);
+ mkdir($ziptemp);
+ # Set up the zip's config section:
+ $zip->{Config} = $config->{Stages}->{PostPackage}->{Config};
+ # Add to the copylist's config section. Don't copy Postpackage->Config,
+ # because the CopyList's Config might contain substitution tags.
+ $zip->{CopyList}->{Config}->{FileStem}->{name} = $config->{Stages}->{PostPackage}->{Config}->{FileStem}->{name};
+ $zip->{CopyList}->{Config}->{From}->{root} = "$src\\pismere"; ## Add zip-specific config settings.
+ $zip->{CopyList}->{Config}->{To}->{root} = $ziptemp;
+ copyFiles($zip->{CopyList}, $config);
+ # Drop down into <out>/ziptemp so the path to the added file won't include <out>:
+ chdir $ziptemp;
+ print "Info -- chdir to ".`cd`."\n" if ($verbose);
+
+ # Prune any unwanted files or directories from the directory we're about to zip:
+ pruneFiles($zip, $config);
+
+ local $zipfile = Archive::Zip->new();
+ local $topdir = $zip->{topdir};
+ $topdir =~ s/%filestem%/$filestem/g;
+ $zipfile->addTree('.', $topdir);
+ if (-e $zipname) {!system("rm -f $zipname") or die "Error -- Couldn't remove $zipname.";}
+ $zipfile->writeToFileNamed($zipname);
+ chdir("$out");
+ print "Info -- chdir to ".`cd`."\n" if ($verbose);
+ # move .zip from <out>/ziptemp to <out>.
+ !system("mv -f ziptemp/$zipname .") or die "Error -- Couldn't move $zipname to ..";
+ system("rm -rf ziptemp") if (-d "ziptemp"); ## Clean up any temp directory.
+ print "Info -- created $out\\$zipname.\n" if ($verbose);
+ }
+
+return 1; \ No newline at end of file
diff --git a/src/windows/build/pruneFiles.pl b/src/windows/build/pruneFiles.pl
new file mode 100644
index 0000000..091a6a0
--- /dev/null
+++ b/src/windows/build/pruneFiles.pl
@@ -0,0 +1,34 @@
+#!perl -w
+
+#use strict;
+require "makeZip.pl";
+
+sub pruneFiles {
+ local ($xml, $config) = @_;
+ local $prunes = $xml->{Prunes};
+ if (! $prunes) {return 0;}
+
+ # Use Unix find instead of Windows find. Save PATH so we can restore it when we're done:
+ local $savedPATH = $ENV{PATH};
+ $ENV{PATH} = $config->{Config}->{unixfind}->{value}.";".$savedPATH;
+ local $j=0;
+ print "Info -- Processing prunes in ".`cd`."\n" if ($verbose);
+ while ($prunes->{Prune}->[$j]) {
+ if (exists $prunes->{Prune}->[$j]->{name}) { ## Don't process dummy entry!
+ local $prune = $prunes->{Prune}->[$j]->{name};
+ local $flags = $prunes->{Prune}->[$j]->{flags};
+ $flags = "" if (!$flags);
+ local $cmd = "find . -".$flags."name $prune";
+ print "Info -- Looking for filenames containing $prune\n";
+ local $list = `$cmd`;
+ foreach $target (split("\n", $list)) {
+ print "Info -- Pruning $target\n" if ($verbose);
+ ! system("rm -rf $target") or die "Unable to prune $target";
+ }
+ }
+ $j++;
+ }
+ $ENV{PATH} = $savedPATH;
+ }
+
+return 1;
diff --git a/src/windows/build/repository1.pl b/src/windows/build/repository1.pl
new file mode 100644
index 0000000..03ee519
--- /dev/null
+++ b/src/windows/build/repository1.pl
@@ -0,0 +1,90 @@
+#!perl -w
+
+#use strict;
+
+sub repository1 {
+ local ($config) = @_;
+ local $odr = $config->{Config}; ## Options, directories, repository, environment.
+ local $src = $odr->{src}->{value};
+ local $rverb = $odr->{repository}->{value};
+ local $wd = $src."\\pismere";
+
+ if ($rverb =~ /skip/) {print "Info -- *** Skipping repository access.\n" if ($verbose);}
+ else {
+ if ($verbose) {print "Info -- *** Begin fetching sources.\n";}
+ local $cvspath = "$src";
+ if (! -d $cvspath) { ## xcopy will create the entire path for us.
+ !system("echo foo > a.tmp") or die "Fatal -- Couldn't create temporary file in ".`cd`;
+ !system("echo F | xcopy a.tmp $cvspath\\a.tmp") or die "Fatal -- Couldn't xcopy to $cvspath.";
+ !system("rm a.tmp") or die "Fatal -- Couldn't remove temporary file.";
+ !system("rm $cvspath\\a.tmp") or die "Fatal -- Couldn't remove temporary file.";
+ }
+
+ # Set up cvs environment variables:
+ $ENV{CVSROOT} = $odr->{CVSROOT}->{value};
+ local $krb5dir = "$wd\\athena\\auth\\krb5";
+
+ local $cvscmdroot = "cvs $rverb";
+ if (length $odr->{cvstag}->{value} > 0) {
+ $cvscmdroot .= " -r $odr->{cvstag}->{value}";
+ }
+
+ if ($rverb =~ /checkout/) {
+ chdir($src) or die "Fatal -- couldn't chdir to $src\n";
+ print "Info -- chdir to ".`cd`."\n" if ($verbose);
+ my @cvsmodules = (
+ 'krb',
+ 'pismere/athena/util/lib/delaydlls',
+ 'pismere/athena/util/lib/getopt',
+ 'pismere/athena/util/guiwrap'
+ );
+
+ foreach my $module (@cvsmodules) {
+ local $cvscmd = $cvscmdroot." ".$module;
+ if ($verbose) {print "Info -- cvs command: $cvscmd\n";}
+ !system($cvscmd) or die "Fatal -- command \"$cvscmd\" failed; return code $?\n";
+ }
+ }
+ else { ## Update.
+ chdir($wd) or die "Fatal -- couldn't chdir to $wd\n";
+ print "Info -- chdir to ".`cd`."\n" if ($verbose);
+ if ($verbose) {print "Info -- cvs command: $cvscmdroot\n";}
+ !system($cvscmdroot) or die "Fatal -- command \"$cvscmdroot\" failed; return code $?\n";
+ }
+
+ # Set up svn environment variable:
+ $ENV{SVN_SSH} = "plink.exe";
+ # If the directory structure doesn't exist, many cd commands will fail.
+ if (! -d $krb5dir) { ## xcopy will create the entire path for us.
+ !system("echo foo > a.tmp") or die "Fatal -- Couldn't create temporary file in ".`cd`;
+ !system("echo F | xcopy a.tmp $krb5dir\\a.tmp") or die "Fatal -- Couldn't xcopy to $krb5dir.";
+ !system("rm a.tmp") or die "Fatal -- Couldn't remove temporary file.";
+ !system("rm $krb5dir\\a.tmp") or die "Fatal -- Couldn't remove temporary file.";
+ }
+
+ chdir($krb5dir) or die "Fatal -- Couldn't chdir to $krb5dir";
+ print "Info -- chdir to ".`cd`."\n" if ($verbose);
+ my $svncmd = "svn $rverb ";
+ if ($rverb =~ /checkout/) { # Append the rest of the checkout command:
+ chdir("..");
+ $svncmd .= "svn+ssh://".$odr->{username}->{value}."@".$odr->{SVNURL}->{value}."/krb5/";
+ if (length $odr->{svntag}->{value} > 0) {
+ $svncmd .= "tags/$odr->{svntag}->{value}";
+ }
+ elsif (length $odr->{svnbranch}->{value} > 0) {
+ $svncmd .= "branches/$odr->{svnbranch}->{value}";
+ }
+ else {
+ $svncmd .= "trunk";
+ }
+
+ $svncmd .= " krb5";
+
+ }
+ if ($verbose) {print "Info -- svn command: $svncmd\n";}
+ !system($svncmd) or die "Fatal -- command \"$svncmd\" failed; return code $?\n";
+ if ($verbose) {print "Info -- *** End fetching sources.\n";}
+ }
+ }
+
+return 1; \ No newline at end of file
diff --git a/src/windows/build/sdkfiles.xml b/src/windows/build/sdkfiles.xml
new file mode 100644
index 0000000..3c1481f
--- /dev/null
+++ b/src/windows/build/sdkfiles.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8" ?>
+ <Files>
+ <!-- File from paths are relative to <src>/pismere. -->
+ <!-- File to paths are relative to <out>. -->
+ <File dummy="foo" /> <!-- Forces XML::Simple behavior -->
+ <!-- Without this, XML::Simple does not make an anonymous array and I can't figure out how to iterate over it. -->
+
+ <File name="relnotes.html" from="doc\kerberos" to="doc" />
+ <File name="kclient.rtf" from="athena\auth\krb4\kclient\doc" to="doc" />
+ <File name="msi-deployment-guide.txt" from="athena\auth\krb5\src\windows\installer\wix\" to="\doc" />
+
+ <File name="*.*" from="staging\inc" to="inc" />
+ <!-- loadfuncs.c is deliberately here. Otherwise, *.h would work. -->
+
+ <File name="*.*" from="staging\install\nsis" to="install\nsis\" />
+ <!-- We'll clean up the exes in the target directory in a later step. -->
+
+ <File name="*.*" from="staging\install\wix" to="install\wix\" />
+ <!-- We'll clean up the msi in the target directory in a later step. -->
+
+ <File name="*.lib" from="staging\lib\i386" to="lib\i386\" />
+
+ </Files> \ No newline at end of file
diff --git a/src/windows/build/signFiles.pl b/src/windows/build/signFiles.pl
new file mode 100644
index 0000000..65ccb0a
--- /dev/null
+++ b/src/windows/build/signFiles.pl
@@ -0,0 +1,27 @@
+#!perl -w
+
+#use strict;
+use Data::Dumper;
+
+sub signFiles {
+ local ($signing, $config) = @_;
+ local $exprs = $signing->{FilePatterns}->{value};
+ local $template = $signing->{CommandTemplate}->{value};
+ # Use Unix find instead of Windows find. Save PATH so we can restore it when we're done:
+ local $savedPATH= $ENV{PATH};
+ $ENV{PATH} = $config->{Config}->{unixfind}->{value}.";".$savedPATH;
+ foreach $expr (split(" ", $exprs)) { ## exprs is something like "*.exe *.dll"
+ local $cmd = "find . -iname \"$expr\"";
+ local $list = `$cmd`; ## $list is files matching *.exe, for example.
+ foreach $target (split("\n", $list)) {
+ $target =~ s|/|\\|g; ## Flip path separators from unix-style to windows-style.
+ local $template2 = $template;
+ $template2 =~ s/%filename%/$target/;
+ print "Info -- Signing $target\n" if ($verbose);
+ !system("$template2") or die "Fatal -- Error signing $target.";
+ }
+ }
+ $ENV{PATH} = $savedPATH;
+ }
+
+return 1; \ No newline at end of file
diff --git a/src/windows/build/site-local.sed b/src/windows/build/site-local.sed
new file mode 100644
index 0000000..34d68ff
--- /dev/null
+++ b/src/windows/build/site-local.sed
@@ -0,0 +1,2 @@
+s/<?define TargetDir="c:.temp.*"?>/<?define TargetDir="%%TARGETDIR%%"?>/
+s/<?define ConfigDir="c:.temp.*"?>/<?define ConfigDir="%%CONFIGDIR%%"?>/ \ No newline at end of file
diff --git a/src/windows/build/tee.pl b/src/windows/build/tee.pl
new file mode 100644
index 0000000..a9c30fb
--- /dev/null
+++ b/src/windows/build/tee.pl
@@ -0,0 +1,79 @@
+# Usage 'tee filename'
+# Make sure that when using this as a perl pipe you
+# print a EOF char!
+# (This may be a bug in perl 4 for NT)
+#
+# Use it like:
+# open(PIPE, "|$^X tee.pl foo.log") || die "Can't pipe";
+# open(STDOUT, ">&PIPE") || die "Can't dup pipe to stdout";
+# open(STDERR, ">&PIPE") || die "Can't dup pipe to stderr";
+
+use IO::File;
+
+#$SIG{'INT'} = \&handler;
+#$SIG{'QUIT'} = \&handler;
+
+$SIG{'INT'} = 'IGNORE';
+$SIG{'QUIT'} = \&handler;
+
+my $fh = new IO::File;
+
+my $arg = shift;
+my $file;
+my $access = ">";
+
+while ($arg) {
+ if ($arg =~ /-a/) {
+ $access = ">>";
+ } elsif ($arg =~ /-i/) {
+ $SIG{'INT'} = 'IGNORE';
+ $SIG{'QUIT'} = 'IGNORE';
+ } else {
+ $file = $arg;
+ last;
+ }
+ $arg = shift;
+}
+
+STDOUT->autoflush(1);
+
+if ($file) {
+ $fh->open($access.$file) || die "Could not open $file\n";
+ $fh->autoflush(1);
+}
+
+while (<>) {
+ $_ = &logtime.$_;
+ print $_;
+ print $fh $_ if $file;
+}
+
+sub logtime {
+ my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
+ $mon = $mon + 1;
+ $year %= 100;
+ sprintf ("[%02d/%02d/%02d %02d:%02d:%02d] ",
+ $year, $mon, $mday,
+ $hour, $min, $sec);
+}
+
+sub handler {
+ my $sig = shift;
+ my $bailmsg = &logtime."Bailing out due to SIG$sig!\n";
+ my $warnmsg = <<EOH;
+*********************************
+* FUTURE BUILDS MAY FAIL UNLESS *
+* BUILD DIRECTORIES ARE CLEANED *
+*********************************
+EOH
+ print $bailmsg, $warnmsg;
+ print $fh $bailmsg, $warnmsg;
+ print "Closing log...";
+ undef $fh if $fh;
+ print "closed!\n";
+ exit(2);
+}
+
+END {
+ undef $fh if $fh;
+}
diff --git a/src/windows/build/which.pl b/src/windows/build/which.pl
new file mode 100644
index 0000000..1cf89ce
--- /dev/null
+++ b/src/windows/build/which.pl
@@ -0,0 +1,69 @@
+#!perl -w
+
+use strict;
+use Config;
+use File::Basename;
+use Getopt::Long;
+
+$0 = fileparse($0);
+
+sub main
+{
+ Getopt::Long::Configure('bundling', 'no_auto_abbrev',
+ 'no_getopt_compat', 'require_order',
+ 'ignore_case', 'pass_through',
+ 'prefix_pattern=(--|-|\+|\/)',
+ );
+ my $OPT = {};
+ GetOptions($OPT,
+ 'help|h|?',
+ 'all|a',
+ 'quiet|q',
+ 'debug|d',
+ 'path:s',
+ );
+
+ my $f = shift @ARGV;
+ if ($OPT->{help} || !$f) {
+ usage();
+ exit(0) if $OPT->{help};
+ exit(1);
+ }
+
+ my $p = $OPT->{path} || $ENV{PATH};
+ my $s = $Config{path_sep};
+ my @d = split(/$s/, $p);
+ my @e = split(/$s/, lc($ENV{PATHEXT} || '.bat;.exe;.com'));
+ my @f = ($f, map { $f.$_; } @e);
+ my $found = 0;
+ foreach my $d (@d) {
+ print "(Searching $d)\n" if $OPT->{debug};
+ foreach my $f (@f) {
+ my $df = $d.'\\'.$f; # cannot use $File::Spec->catfile due to UNC.
+ print "(Checking for $df)\n" if $OPT->{debug};
+ if (-f $df) {
+ exit(0) if $OPT->{quiet};
+ print "$df\n";
+ exit(0) if !$OPT->{all};
+ $found = 1;
+ }
+ }
+ }
+ print "Could not find $f\n" if !$found && !$OPT->{quiet};
+ exit($found?0:1);
+}
+
+sub usage
+{
+ print <<USAGE;
+Usage: $0 [options] command
+ command find file executed by this command by looking at PATH
+ -d, --debug debug output
+ -a, --all find all such commands in PATH
+ -q, --quiet no output, exit with non-zero errorcode if not found
+ --path PATHARG search PATHARG instead of the PATH environment variable
+ -?, -H, --help help
+USAGE
+}
+
+main();
diff --git a/src/windows/build/zipXML.pl b/src/windows/build/zipXML.pl
new file mode 100644
index 0000000..0c50e96
--- /dev/null
+++ b/src/windows/build/zipXML.pl
@@ -0,0 +1,21 @@
+#!perl -w
+
+#use strict;
+require "makeZip.pl";
+
+use Data::Dumper;
+
+sub zipXML {
+ local ($xml, $config) = @_;
+ my $zipsXML = $xml->{Zips};
+ if (! $zipsXML) {return 0;}
+
+ local $i = 0;
+ while ($zipsXML->{Zip}[$i]) {
+ local $zip = $zipsXML->{Zip}[$i];
+ makeZip($zip, $config) if (exists $zip->{name}); ## Ignore dummy entry.
+ $i++;
+ } ## End zip in xml.
+ }
+
+return 1;
diff --git a/src/windows/identity/Makefile b/src/windows/identity/Makefile
index e8fb501..375bdce 100644
--- a/src/windows/identity/Makefile
+++ b/src/windows/identity/Makefile
@@ -160,7 +160,7 @@ krb5plugin: plugincommon
$(ECHO) -- Done with $@
!ifndef NO_KRB4
-doc: krb4plugin
+finale: krb4plugin
krb4plugin: plugincommon
$(ECHO) -- Entering $@
diff --git a/src/windows/identity/apiversion.txt b/src/windows/identity/apiversion.txt
index 9681ccc..2f3ef6d 100644
--- a/src/windows/identity/apiversion.txt
+++ b/src/windows/identity/apiversion.txt
@@ -220,8 +220,134 @@ Date=(TBD)
#----------------------------------------------------------------
Version=7
AppVersion=1.1.9.0
-Date=(TBD)
-# Released with KFW 3.2.0
+Date=Feb 16, 2007
+# Released with KFW 3.2 Alpha 1
+KHUI_ACTION_UICB
-# Internal action to dispatch a UI callback \ No newline at end of file
+# Internal action to dispatch a UI callback
+
++WMNC_UPDATE_LAYOUT
+# Used to update the layout and size of the dialogs during a new
+# credentials operation.
+
+- NCDLG_TAB_HEIGHT, NCDLG_TAB_WIDTH
+# No longer used
+
+- NCDLG_BBAR_WIDTH
+# Moved to internal header file
+
++ KCDB_IDENT_FLAG_UNKNOWN
+# Used to indicate that an authority could not be contacted to
+# determine the validity of an identity.
+
++ khui_refresh_actions()
+# Force a refresh of the application menus and toolbars.
+
++ khui_action_lock()
++ khui_action_unlock()
+# Synchronization of action and menu operations.
+
+! khui_alert
+# Structure definition is now internal
+
+! khui_action
+# Structure definition is now internal
+
++ khui_alert_set_type()
++ khui_alert_set_ctx()
++ khui_alert_get_response()
+# Additional functions to setup an alert.
+
+! kmq_message
+# Added field "aborted"
+
++ kmq_abort_call()
++ kmq_is_call_aborted()
+# Added placeholders
+
+! kmq_message_ref
+! kmq_queue
+! kmq_msg_subscription
+! kmq_msg_type
+# Structure definition now internal
+
+! KMQ_MSG_TYPE_MAX
+! KMQ_MAXCCH_TYPE_NAME
+! KMQ_MAXCB_TYPE_NAME
+! KMQ_MSG_SUB_MAGIC
+! KMQ_RCPTTYPE_CB
+! KMQ_RCPTTYPE_HWND
+! KMQ_QUEUE_FLAG_DELETED
+# Macros not internal
+
+#----------------------------------------------------------------
+Version=8
+AppVersion=1.1.10.0
+Date=(TBD)
+# Released with (TBD)
+
+! hash_add(), hash_del(), hash_lookup(), hash_exist()
+# 'key' parameter is now (const void *)
+
+! struct tag_has_bin, hash_bin
+# 'key' member is now (const void *)
+
+
++WMNC_UPDATE_LAYOUT
+# Used to update the layout and size of the dialogs during a new
+# credentials operation.
+
+- NCDLG_TAB_HEIGHT, NCDLG_TAB_WIDTH
+# No longer used
+
+- NCDLG_BBAR_WIDTH
+# Moved to internal header file
+
++ KCDB_IDENT_FLAG_UNKNOWN
+# Used to indicate that an authority could not be contacted to
+# determine the validity of an identity.
+
++ khui_refresh_actions()
+# Force a refresh of the application menus and toolbars.
+
++ khui_action_lock()
++ khui_action_unlock()
+# Synchronization of action and menu operations.
+
+! khui_alert
+# Structure definition is now internal
+
+! khui_action
+# Structure definition is now internal
+
++ khui_alert_set_type()
++ khui_alert_set_ctx()
++ khui_alert_get_response()
+# Additional functions to setup an alert.
+
+! kmq_message
+# Added field "aborted"
+
++ kmq_abort_call()
++ kmq_is_call_aborted()
+# Added placeholders
+
+! kmq_message_ref
+! kmq_queue
+! kmq_msg_subscription
+! kmq_msg_type
+# Structure definition now internal
+
+! KMQ_MSG_TYPE_MAX
+! KMQ_MAXCCH_TYPE_NAME
+! KMQ_MAXCB_TYPE_NAME
+! KMQ_MSG_SUB_MAGIC
+! KMQ_RCPTTYPE_CB
+! KMQ_RCPTTYPE_HWND
+! KMQ_QUEUE_FLAG_DELETED
+# Macros not internal
+
+! khc_value_exists()
+# Behavior change with respect to shadowed handles. If a value
+# doesn't exist in the top level handle, then each shadowed handle
+# will be tried in turn until the value is found.
diff --git a/src/windows/identity/config/Makefile.w2k b/src/windows/identity/config/Makefile.w2k
index f297778..efd7fbd 100644
--- a/src/windows/identity/config/Makefile.w2k
+++ b/src/windows/identity/config/Makefile.w2k
@@ -46,9 +46,9 @@ KHIMAIRA_WIN32_CONFIG=1
# Version info
NETIDMGR_VERSION_MAJOR=1
-NETIDMGR_VERSION_MINOR=1
-NETIDMGR_VERSION_PATCH=9
-NETIDMGR_VERSION_AUX=0
+NETIDMGR_VERSION_MINOR=2
+NETIDMGR_VERSION_PATCH=0
+NETIDMGR_VERSION_AUX=2
NETIDMGR_RELEASEDESC=
# The API version. This number must be incremented each time the API
@@ -58,7 +58,7 @@ NETIDMGR_RELEASEDESC=
#
# Changes to the API version numbers should be documented in
# apiversion.txt at the root of the source tree.
-NETIDMGR_VERSION_API=7
+NETIDMGR_VERSION_API=8
# Minimum backwards compatible version. API versions from
# NETIDMGR_VERSION_API_MINCOMPAT through NETIDMGR_VERSION_API
@@ -208,6 +208,10 @@ khcwarn=/Wp64
khcwarn=$(khcwarn) /WX
!endif
+!if "$(CPU)" == "i386"
+khdefines=$(khdefines) -D_USE_32BIT_TIME_T
+!endif
+
#DEBUG_SYMBOLS
ldebug=$(ldebug) /DEBUG
cdebug=$(cdebug) -Os -Zi
diff --git a/src/windows/identity/config/Makefile.w32 b/src/windows/identity/config/Makefile.w32
index e327a70..5f274a4 100644
--- a/src/windows/identity/config/Makefile.w32
+++ b/src/windows/identity/config/Makefile.w32
@@ -46,9 +46,9 @@ KHIMAIRA_WIN32_CONFIG=1
# Version info
NETIDMGR_VERSION_MAJOR=1
-NETIDMGR_VERSION_MINOR=1
-NETIDMGR_VERSION_PATCH=9
-NETIDMGR_VERSION_AUX=0
+NETIDMGR_VERSION_MINOR=2
+NETIDMGR_VERSION_PATCH=0
+NETIDMGR_VERSION_AUX=2
NETIDMGR_RELEASEDESC=
# The API version. This number must be incremented each time the API
@@ -58,7 +58,7 @@ NETIDMGR_RELEASEDESC=
#
# Changes to the API version numbers should be documented in
# apiversion.txt at the root of the source tree.
-NETIDMGR_VERSION_API=7
+NETIDMGR_VERSION_API=8
# Minimum backwards compatible version. API versions from
# NETIDMGR_VERSION_API_MINCOMPAT through NETIDMGR_VERSION_API
@@ -221,6 +221,10 @@ khcwarn=/Wp64
khcwarn=$(khcwarn) /WX
!endif
+!if "$(CPU)" == "i386"
+khdefines=$(khdefines) -D_USE_32BIT_TIME_T
+!endif
+
#DEBUG_SYMBOLS
ldebug=$(ldebug) /DEBUG
cdebug=$(cdebug) -Os -Zi
diff --git a/src/windows/identity/config/ccsv.pl b/src/windows/identity/config/ccsv.pl
index c6c8281..a377797 100644
--- a/src/windows/identity/config/ccsv.pl
+++ b/src/windows/identity/config/ccsv.pl
@@ -88,10 +88,10 @@ $first_line = 1;
while(<IN>) {
chomp $_;
- if($skip_lines > 0) {
- $skip_lines--;
- } elsif (m/^\#/) {
+ if (m/^\#/) {
# ignore
+ } elsif ($skip_lines > 0) {
+ $skip_lines--;
} else {
if($first_line == 0){
print OUT $record_sep;
diff --git a/src/windows/identity/config/csvschema.cfg b/src/windows/identity/config/csvschema.cfg
index ba3bf9b..cc8acd2 100644
--- a/src/windows/identity/config/csvschema.cfg
+++ b/src/windows/identity/config/csvschema.cfg
@@ -55,13 +55,11 @@ $skip_lines = 1;
sub rec_handler {
$arr = shift;
if($$arr[1] =~ "KC_STRING") {
- $$arr[2] = "(khm_int64) L\"".$$arr[2]."\"";
$$arr[2] =~ s/\[\~\]/\\0/g;
+ $$arr[2] = "(khm_int64) L\"".$$arr[2]."\"";
}
- if($#$arr == 2){
- $$arr[3] = "";
- }
+ $$arr[3] = "";
}
$record_parser = \&rec_handler;
diff --git a/src/windows/identity/doc/Makefile b/src/windows/identity/doc/Makefile
index 8500399..89380af 100644
--- a/src/windows/identity/doc/Makefile
+++ b/src/windows/identity/doc/Makefile
@@ -1,5 +1,6 @@
#
# Copyright (c) 2004 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
@@ -53,6 +54,8 @@ INPUT += "$(SRC)\kmm"
INPUT += "$(SRC)\kherr"
!ifdef BUILD_AFS
INPUT += "$(SRC)\plugins\afs"
+
+ALIASES = "apiversion=$(NETIDMGR_VERSION_API)"
!endif
IMAGE_PATH = "$(SRC)\doc\images"
@@ -64,5 +67,5 @@ CHM_FILE = "$(DOCDIR)\netiddev.chm"
-$(HHC) $(DOCDIR)\html\index.hhp
clean::
- $(RMDIR) /s /q $(DOCDIR)\html
- $(RM) $(DOCDIR)\*.*
+ if exist "$(DOCDIR)/html" $(RMDIR) /s /q "$(DOCDIR)\html"
+ if exist "$(DOCDIR)" $(RM) "$(DOCDIR)\*.*"
diff --git a/src/windows/identity/doc/cred_aquisition.h b/src/windows/identity/doc/cred_aquisition.h
index 251b5b2..30f626f 100644
--- a/src/windows/identity/doc/cred_aquisition.h
+++ b/src/windows/identity/doc/cred_aquisition.h
@@ -1,5 +1,6 @@
/*
* 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
@@ -26,36 +27,36 @@
/*! \page cred_acq Managed credential acquisition
- Credential providers and the identity provider must participate in
+ 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 obtain
- new credentials for an existing identity.
+ 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 initial credentials, while
- the other is the acquisition of new crednetials. Both processes
- acquire new credentials (or replace existing credentials with new
- ones). The difference between the two processes lie in the way the
- new credentials are obtained. Initial credentials are obtained
- using user supplied username and password while new credentials
- are obtained using other existing credentials.
+ 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_init Initial Credentials
+ \section cred_acq_new New Credentials
When a user initiates the process of initial credential
- acquisition, NetIDMgr broadcasts a
- <::KMSG_CRED,::KMSG_CRED_INITIAL_CREDS> message. Credential
- providers which need to participate in the initial credential
- acquisition should respond to this message as detailed in
- \ref cred_acq_handle.
+ 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_new New Credentials
+ \section cred_acq_renew Renew Credentials
- When a user initiates the process of obtaining new credentials
- based on existing credentials, NetIDMgr broadcasts a
- <::KMSG_CRED,::KMSG_CRED_NEW_CREDS> message. Credential providers
- which need to participate in the initial credential acquisition
- should respond to this message as detailed in \ref cred_acq_handle.
+ 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:
@@ -65,13 +66,12 @@
/*! \page cred_acq_new_resp Handling new credentials acquisition
- The process of acquiring new credentials whether they are initial
- credentials or not, happen as follows :
+ The process of acquiring credentials happens as follows:
- - NetIDMgr creates a ::khui_new_creds object and a credentials
- acquisition window.
+ - Network Identity Manager creates a ::khui_new_creds object and a
+ credentials acquisition window.
- - <::KMSG_CRED,::KMSG_CRED_INITIAL_CREDS> or
+ - <::KMSG_CRED,::KMSG_CRED_RENEW_CREDS> or
<::KMSG_CRED,::KMSG_CRED_NEW_CREDS> is sent to all the
credentials providers.
@@ -79,7 +79,7 @@
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.
+ ::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
@@ -95,53 +95,58 @@
are done through ::KHUI_WM_NC_NOTIFY messages to the dialog
procedures.
- - Once the dialog completes, NetIDMgr sends
- <::KMSG_CRED,::KMSG_CRED_DIALOG_END> message to all the
- credentials providers. The UI portion ends here. The
- individual dialog controls are destroyed as a result of the main
- credentials acquisition window being destroyed.
-
- - NetIDMgr 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
- 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.
+ - 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_INITIAL_CREDS> and <::KMSG_CRED,
- ::KMSG_CRED_NEW_CREDS>. They are structured as follows :
+ <::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_INITIAL_CREDS or ::KMSG_CRED_NEW_CREDS
+ - \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 an
- initial credentials acquisition or a new credentials acquisition
- at any point.
+ 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_cred_panel structure.
+ 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_cred_panel structure that describes the panel can be
+ ::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. Optionally,
+ 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
@@ -155,12 +160,13 @@
name). Then the panels without a positive ordianl are arranged
behind these in increasing order of \a name.
- The \a hwnd_panel field is used to specify the handle to the
- dialog or window of the panel. The parent of this window should
- be set to the \a hwnd parameter of the ::khui_new_creds structure
- which is passed in to the message handler.
+ 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 a code snippet which suggests how this could be done:
+ Following is example code which suggests how this could be done:
\code
// Message handling code for KMSG_CRED_NEW_CREDS or
@@ -181,11 +187,10 @@
t->icon = LoadIcon(my_hInstance, MAKEINTRESOURCE(IDI_PANEL_ICON));
t->tooltip = L"Configure credentials of my type";
- t->hwnd_panel = CreateDialog(
- my_hInstance,
- MAKEINTRESOURCE(IDD_MY_PANEL),
- c->hwnd,
- my_dialog_proc);
+ // 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
@@ -195,7 +200,7 @@
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_DIALOG_PROCESS> message is received.
+ <::KMSG_CRED,::KMSG_CRED_END> message is received.
For information on how the dialog procedure should be written, see
\ref cred_acq_dlgproc .
diff --git a/src/windows/identity/doc/cred_data_types.h b/src/windows/identity/doc/cred_data_types.h
index 8fa7b1f..dcd1152 100644
--- a/src/windows/identity/doc/cred_data_types.h
+++ b/src/windows/identity/doc/cred_data_types.h
@@ -1,5 +1,6 @@
/*
* 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
@@ -24,20 +25,21 @@
/* $Id$ */
-/*! \page cred_data_types Data types in NetIDMgr
+/*! \page cred_data_types Data types in Network Identity Manager
- NetIDMgr'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.
+ 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.
+ 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.
+ 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
@@ -47,13 +49,17 @@
\subsubsection kcdb_pg_idt_v Void
- Pretty useless. This data type is used to indicate that the associated
- object doesn't actually contain any data.
+ 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
- A unicode string that is terminated with a unicode NULL (L'\\0'). By
- default, the type has the following flags :
+ 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
@@ -63,18 +69,23 @@
\subsubsection kcdb_pg_idt_d Date
- Dates and times in NetIDMgr are stored as \a FILETIME structures. Utility
- functions are provided for converting from other formats such as \a time_t.
+ 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
- Stores an interval of time. Stored as a 64 bit signed integer. The
+ 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 designate an interval of time.
+ Date data type and designates an interval of time.
The special value _I64_MAX (which is defined in limits.h as
- 0x7fffffffffffffff, or in otherwords, the largest positive value
- that can be stored in a 64 bit signed integer) is used to
+ 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
@@ -94,27 +105,34 @@
\subsubsection kcdb_pg_idt_i32 Int32
- A signed 32 bit integer.
+ Type identifier : ::KCDB_TYPE_INT32
+
+ A signed 32-bit integer.
\subsubsection kcdb_pg_idt_i64 Int64
- A signed 64 bit integer.
+ Type identifier : ::KCDB_TYPE_INT64
+
+ A signed 64-bit integer.
\subsubsection kcdb_pg_idt_da 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.
+ 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 NetIDMgr Credentials Database are defined using
- \a kcdb_type structures which must include several callback functions.
- The expected behavior of these callback functions is documented below.
+ 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
@@ -172,7 +190,7 @@
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 :
+ The return value \a r should be as follows:
\a r < 0 : if \a data1 < \a data2
diff --git a/src/windows/identity/doc/cred_main.h b/src/windows/identity/doc/cred_main.h
index b5be8ad..a9949ae 100644
--- a/src/windows/identity/doc/cred_main.h
+++ b/src/windows/identity/doc/cred_main.h
@@ -1,5 +1,6 @@
/*
* 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
diff --git a/src/windows/identity/doc/cred_msgs.h b/src/windows/identity/doc/cred_msgs.h
index 49f644c..6d7cd3d 100644
--- a/src/windows/identity/doc/cred_msgs.h
+++ b/src/windows/identity/doc/cred_msgs.h
@@ -1,5 +1,6 @@
/*
* 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
@@ -26,7 +27,7 @@
/*! \page cred_msgs Handling credentials provider messages
-A credentials provider plugin receives a number of messages during the
+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.
@@ -34,7 +35,7 @@ handling these messages.
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 plugin. See the following
+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
diff --git a/src/windows/identity/doc/cred_prop_pages.h b/src/windows/identity/doc/cred_prop_pages.h
index e4d41b1..fd1da5a 100644
--- a/src/windows/identity/doc/cred_prop_pages.h
+++ b/src/windows/identity/doc/cred_prop_pages.h
@@ -1,5 +1,6 @@
/*
* 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
@@ -62,7 +63,7 @@
- The property sheet is created and made visible with a call to
khui_ps_show_sheet().
- - The NetIDMgr message loop takes over. Further interaction
+ - 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.
diff --git a/src/windows/identity/doc/doxyfile.cfg b/src/windows/identity/doc/doxyfile.cfg
index 7aac802..e269235 100644
--- a/src/windows/identity/doc/doxyfile.cfg
+++ b/src/windows/identity/doc/doxyfile.cfg
@@ -1,4 +1,4 @@
-# Doxyfile 1.2.18
+# Doxyfile 1.5.2
# This file describes the settings to be used by the documentation system
# doxygen (www.doxygen.org) for a project
@@ -11,13 +11,21 @@
# Values that contain spaces should be placed between quotes (" ")
#---------------------------------------------------------------------------
-# General configuration options
+# Project related configuration options
#---------------------------------------------------------------------------
+# This tag specifies the encoding used for all characters in the config file that
+# follow. The default is UTF-8 which is also the encoding used for all text before
+# the first occurrence of this tag. Doxygen uses libiconv (or the iconv built into
+# libc) for the transcoding. See http://www.gnu.org/software/libiconv for the list of
+# possible encodings.
+
+DOXYFILE_ENCODING = UTF-8
+
# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
# by quotes) that should identify the project.
-PROJECT_NAME = NetIDMgr
+PROJECT_NAME = "Network Identity Manager"
# The PROJECT_NUMBER tag can be used to enter a project or revision number.
# This could be handy for archiving the generated documentation or
@@ -32,17 +40,192 @@ PROJECT_NUMBER =
OUTPUT_DIRECTORY =
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS = NO
+
# The OUTPUT_LANGUAGE tag is used to specify the language in which all
# documentation generated by doxygen is written. Doxygen will use this
# information to generate all constant output in the proper language.
# The default language is English, other supported languages are:
-# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch,
-# Finnish, French, German, Greek, Hungarian, Italian, Japanese, Japanese-en
-# (Japanese with english messages), Korean, Norwegian, Polish, Portuguese,
-# Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish and Ukrainian.
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
+# Croatian, Czech, Danish, Dutch, Finnish, French, German, Greek, Hungarian,
+# Italian, Japanese, Japanese-en (Japanese with English messages), Korean,
+# Korean-en, Lithuanian, Norwegian, Polish, Portuguese, Romanian, Russian,
+# Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian.
OUTPUT_LANGUAGE = English
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like the Qt-style comments (thus requiring an
+# explicit @brief command for a brief description.
+
+JAVADOC_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen
+# will output the detailed description near the top, like JavaDoc.
+# If set to NO, the detailed description appears after the member
+# documentation.
+
+DETAILS_AT_TOP = YES
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 4
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
+# sources only. Doxygen will then generate output that is more tailored for Java.
+# For instance, namespaces will be presented as packages, qualified scopes
+# will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want to
+# include (a tag file for) the STL sources as input, then you should
+# set this tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
+# func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+
+CPP_CLI_SUPPORT = NO
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING = YES
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
# documentation are documented, even if no documentation was available.
# Private class members and static file members will be hidden unless
@@ -66,6 +249,13 @@ EXTRACT_STATIC = NO
EXTRACT_LOCAL_CLASSES = YES
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS = NO
+
# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
# undocumented members of documented classes, files or namespaces.
# If set to NO (the default) these members will be included in the
@@ -76,7 +266,7 @@ HIDE_UNDOC_MEMBERS = NO
# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
# undocumented classes that are normally visible in the class hierarchy.
-# If set to NO (the default) these class will be included in the various
+# If set to NO (the default) these classes will be included in the various
# overviews. This option has no effect if EXTRACT_ALL is enabled.
HIDE_UNDOC_CLASSES = NO
@@ -88,47 +278,12 @@ HIDE_UNDOC_CLASSES = NO
HIDE_FRIEND_COMPOUNDS = NO
-# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
-# include brief member descriptions after the members that are listed in
-# the file and class documentation (similar to JavaDoc).
-# Set to NO to disable this.
-
-BRIEF_MEMBER_DESC = YES
-
-# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will
-# prepend the brief description of a member or function before the
-# detailed description. Note: if both HIDE_UNDOC_MEMBERS and
-# BRIEF_MEMBER_DESC are set to NO, the brief descriptions will be
-# completely suppressed.
-
-REPEAT_BRIEF = YES
-
-# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
-# Doxygen will generate a detailed section even if there is only a brief
-# description.
-
-ALWAYS_DETAILED_SEC = NO
-
-# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show
-# all inherited members of a class in the documentation of that class
-# as if those members were ordinary class members. Constructors,
-# destructors and assignment operators of the base classes will not be
-# shown.
-
-INLINE_INHERITED_MEMB = NO
-
-# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
-# path before files name in the file list and in the header files. If set
-# to NO the shortest path that makes the file name unique will be used.
-
-FULL_PATH_NAMES = NO
-
-# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
-# can be used to strip a user defined part of the path. Stripping is
-# only done if one of the specified strings matches the left-hand part of
-# the path. It is allowed to use relative paths in the argument list.
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
-STRIP_FROM_PATH =
+HIDE_IN_BODY_DOCS = NO
# The INTERNAL_DOCS tag determines if documentation
# that is typed after a \internal command is included. If the tag is set
@@ -137,73 +292,26 @@ STRIP_FROM_PATH =
INTERNAL_DOCS = YES
-# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
-# doxygen to hide any special comment blocks from generated source code
-# fragments. Normal C and C++ comments will always remain visible.
-
-STRIP_CODE_COMMENTS = YES
-
# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
-# file names in lower case letters. If set to YES upper case letters are also
+# file names in lower-case letters. If set to YES upper-case letters are also
# allowed. This is useful if you have classes or files whose names only differ
# in case and if your file system supports case sensitive file names. Windows
-# users are adviced to set this option to NO.
+# and Mac users are advised to set this option to NO.
CASE_SENSE_NAMES = YES
-# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
-# (but less readable) file names. This can be useful is your file systems
-# doesn't support long names like on DOS, Mac, or CD-ROM.
-
-SHORT_NAMES = NO
-
# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
# will show members with their full class and namespace scopes in the
# documentation. If set to YES the scope will be hidden.
HIDE_SCOPE_NAMES = NO
-# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
-# will generate a verbatim copy of the header file for each class for
-# which an include is specified. Set to NO to disable this.
-
-VERBATIM_HEADERS = NO
-
# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
-# will put list of the files that are included by a file in the documentation
+# will put a list of the files that are included by a file in the documentation
# of that file.
SHOW_INCLUDE_FILES = YES
-# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
-# will interpret the first line (until the first dot) of a JavaDoc-style
-# comment as the brief description. If set to NO, the JavaDoc
-# comments will behave just like the Qt-style comments (thus requiring an
-# explict @brief command for a brief description.
-
-JAVADOC_AUTOBRIEF = NO
-
-# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
-# treat a multi-line C++ special comment block (i.e. a block of //! or ///
-# comments) as a brief description. This used to be the default behaviour.
-# The new default is to treat a multi-line C++ comment block as a detailed
-# description. Set this tag to YES if you prefer the old behaviour instead.
-
-MULTILINE_CPP_IS_BRIEF = NO
-
-# If the DETAILS_AT_TOP tag is set to YES then Doxygen
-# will output the detailed description near the top, like JavaDoc.
-# If set to NO, the detailed description appears after the member
-# documentation.
-
-DETAILS_AT_TOP = YES
-
-# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
-# member inherits the documentation from any documented member that it
-# reimplements.
-
-INHERIT_DOCS = YES
-
# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
# is inserted in the documentation for inline members.
@@ -216,17 +324,22 @@ INLINE_INFO = YES
SORT_MEMBER_DOCS = YES
-# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
-# tag is set to YES, then doxygen will reuse the documentation of the first
-# member in the group (if any) for the other members of the group. By default
-# all members of a group must be documented explicitly.
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
-DISTRIBUTE_GROUP_DOC = NO
+SORT_BRIEF_DOCS = NO
-# The TAB_SIZE tag can be used to set the number of spaces in a tab.
-# Doxygen uses this value to replace tabs by spaces in code fragments.
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
-TAB_SIZE = 4
+SORT_BY_SCOPE_NAME = NO
# The GENERATE_TODOLIST tag can be used to enable (YES) or
# disable (NO) the todo list. This list is created by putting \todo
@@ -247,26 +360,18 @@ GENERATE_TESTLIST = YES
GENERATE_BUGLIST = YES
# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
-# disable (NO) the deprecated list. This list is created by putting \deprecated commands in the documentation.
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
GENERATE_DEPRECATEDLIST= YES
-# This tag can be used to specify a number of aliases that acts
-# as commands in the documentation. An alias has the form "name=value".
-# For example adding "sideeffect=\par Side Effects:\n" will allow you to
-# put the command \sideeffect (or @sideeffect) in the documentation, which
-# will result in a user defined paragraph with heading "Side Effects:".
-# You can put \n's in the value part of an alias to insert newlines.
-
-ALIASES =
-
# The ENABLED_SECTIONS tag can be used to enable conditional
# documentation sections, marked by \if sectionname ... \endif.
ENABLED_SECTIONS =
# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
-# the initial value of a variable or define consist of for it to appear in
+# the initial value of a variable or define consists of for it to appear in
# the documentation. If the initializer consists of more lines than specified
# here it will be hidden. Use a value of 0 to hide initializers completely.
# The appearance of the initializer of individual variables and defines in the
@@ -275,28 +380,28 @@ ENABLED_SECTIONS =
MAX_INITIALIZER_LINES = 30
-# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
-# only. Doxygen will then generate output that is more tailored for C.
-# For instance some of the names that are used will be different. The list
-# of all members will be omitted, etc.
-
-OPTIMIZE_OUTPUT_FOR_C = YES
-
-# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources
-# only. Doxygen will then generate output that is more tailored for Java.
-# For instance namespaces will be presented as packages, qualified scopes
-# will look different, etc.
-
-OPTIMIZE_OUTPUT_JAVA = NO
-
# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
# at the bottom of the documentation of classes and structs. If set to YES the
# list will mention the files that were used to generate the documentation.
SHOW_USED_FILES = YES
+# If the sources in your project are distributed over multiple directories
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
+# in the documentation. The default is NO.
+
SHOW_DIRECTORIES = NO
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from the
+# version control system). Doxygen will invoke the program by executing (via
+# popen()) the command <command> <input-file>, where <command> is the value of
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
+# provided by doxygen. Whatever the program writes to standard output
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER =
+
#---------------------------------------------------------------------------
# configuration options related to warning and progress messages
#---------------------------------------------------------------------------
@@ -318,10 +423,27 @@ WARNINGS = YES
WARN_IF_UNDOCUMENTED = YES
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR = YES
+
+# This WARN_NO_PARAMDOC option can be abled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
+# documentation.
+
+WARN_NO_PARAMDOC = NO
+
# The WARN_FORMAT tag determines the format of the warning messages that
# doxygen can produce. The string should contain the $file, $line, and $text
# tags, which will be replaced by the file and line number from which the
-# warning originated and the warning text.
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
WARN_FORMAT = "$file:$line: $text"
@@ -342,12 +464,19 @@ WARN_LOGFILE =
INPUT =
+# This tag can be used to specify the character encoding of the source files that
+# doxygen parses. Internally doxygen uses the UTF-8 encoding, which is also the default
+# input encoding. Doxygen uses libiconv (or the iconv built into libc) for the transcoding.
+# See http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+INPUT_ENCODING = UTF-8
+
# If the value of the INPUT tag contains directories, you can use the
# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
# and *.h) to filter out the source-files in the directories. If left
# blank the following patterns are tested:
-# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp
-# *.h++ *.idl *.odl
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py
FILE_PATTERNS =
@@ -363,17 +492,27 @@ RECURSIVE = NO
EXCLUDE =
-# The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories
-# that are symbolic links (a Unix filesystem feature) are excluded from the input.
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
+# directories that are symbolic links (a Unix filesystem feature) are excluded
+# from the input.
EXCLUDE_SYMLINKS = NO
# If the value of the INPUT tag contains directories, you can use the
# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
-# certain files from those directories.
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
+# for example use the pattern */test/*
EXCLUDE_PATTERNS =
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the output.
+# The symbol name can be a fully qualified name, a word, or if the wildcard * is used,
+# a substring. Examples: ANamespace, AClass, AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS =
+
# The EXAMPLE_PATH tag can be used to specify one or more files or
# directories that contain example code fragments that are included (see
# the \include command).
@@ -405,10 +544,20 @@ IMAGE_PATH =
# by executing (via popen()) the command <filter> <input-file>, where <filter>
# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
# input file. Doxygen will then use the output that the filter program writes
-# to standard output.
+# to standard output. If FILTER_PATTERNS is specified, this tag will be
+# ignored.
INPUT_FILTER =
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
+# is applied to all files.
+
+FILTER_PATTERNS =
+
# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
# INPUT_FILTER) will be used to filter the input files when producing source
# files to browse (i.e. when SOURCE_BROWSER is set to YES).
@@ -420,7 +569,9 @@ FILTER_SOURCE_FILES = NO
#---------------------------------------------------------------------------
# If the SOURCE_BROWSER tag is set to YES then a list of source files will
-# be generated. Documented entities will be cross-referenced with these sources.
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
SOURCE_BROWSER = NO
@@ -429,6 +580,12 @@ SOURCE_BROWSER = NO
INLINE_SOURCES = NO
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS = YES
+
# If the REFERENCED_BY_RELATION tag is set to YES (the default)
# then for each documented function all documented
# functions referencing it will be listed.
@@ -441,6 +598,27 @@ REFERENCED_BY_RELATION = YES
REFERENCES_RELATION = YES
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code. Otherwise they will link to the documentstion.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
+# will need version 4.8.6 or higher.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = NO
+
#---------------------------------------------------------------------------
# configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
@@ -497,10 +675,12 @@ HTML_HEADER = header.html
HTML_FOOTER = footer.html
-# The HTML_STYLESHEET tag can be used to specify a user defined cascading
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
# style sheet that is used by each HTML page. It can be used to
# fine-tune the look of the HTML output. If the tag is left blank doxygen
-# will generate a default style sheet
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# stylesheet in the HTML output directory as well, or it will be erased!
HTML_STYLESHEET = stylesheet.css
@@ -520,14 +700,14 @@ GENERATE_HTMLHELP = YES
# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
# be used to specify the file name of the resulting .chm file. You
# can add a path in front of the file if the result should not be
-# written to the html output dir.
+# written to the html output directory.
CHM_FILE =
# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
# be used to specify the location (absolute path including file name) of
-# the HTML help compiler (hhc.exe). If non empty doxygen will try to run
-# the html help compiler on the generated index.hhp.
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
HHC_LOCATION =
@@ -544,7 +724,7 @@ GENERATE_CHI = NO
BINARY_TOC = NO
# The TOC_EXPAND flag can be set to YES to add extra items for group members
-# to the contents of the Html help documentation and to the tree view.
+# to the contents of the HTML help documentation and to the tree view.
TOC_EXPAND = YES
@@ -560,15 +740,13 @@ DISABLE_INDEX = NO
ENUM_VALUES_PER_LINE = 4
# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
-# generated containing a tree-like index structure (just like the one
-# that is generated for HTML Help). For this to work a browser that
-# supports JavaScript and frames is required (for instance Mozilla,
-# Netscape 4.0+, or Internet explorer 4.0+). Note that for large
-# projects the tree generation can take a very long time. In such
-# cases it is better to disable this feature. Windows users are
+# generated containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
# probably better off using the HTML help feature.
-GENERATE_TREEVIEW = NO
+GENERATE_TREEVIEW = YES
# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
# used to set the initial width (in pixels) of the frame in which the tree
@@ -591,7 +769,8 @@ GENERATE_LATEX = NO
LATEX_OUTPUT = latex
-# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be invoked. If left blank `latex' will be used as the default command name.
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
LATEX_CMD_NAME = latex
@@ -645,12 +824,18 @@ USE_PDFLATEX = NO
LATEX_BATCHMODE = NO
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES = NO
+
#---------------------------------------------------------------------------
# configuration options related to the RTF output
#---------------------------------------------------------------------------
# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
-# The RTF output is optimised for Word 97 and may not look very pretty with
+# The RTF output is optimized for Word 97 and may not look very pretty with
# other RTF readers or editors.
GENERATE_RTF = NO
@@ -677,7 +862,7 @@ COMPACT_RTF = NO
RTF_HYPERLINKS = NO
# Load stylesheet definitions from file. Syntax is similar to doxygen's
-# config file, i.e. a series of assigments. You only have to provide
+# config file, i.e. a series of assignments. You only have to provide
# replacements, missing definitions are set to their default value.
RTF_STYLESHEET_FILE =
@@ -721,12 +906,16 @@ MAN_LINKS = NO
# If the GENERATE_XML tag is set to YES Doxygen will
# generate an XML file that captures the structure of
-# the code including all documentation. Note that this
-# feature is still experimental and incomplete at the
-# moment.
+# the code including all documentation.
GENERATE_XML = NO
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT = xml
+
# The XML_SCHEMA tag can be used to specify an XML schema,
# which can be used by a validating XML parser to check the
# syntax of the XML files.
@@ -739,6 +928,13 @@ XML_SCHEMA =
XML_DTD =
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING = YES
+
#---------------------------------------------------------------------------
# configuration options for the AutoGen Definitions output
#---------------------------------------------------------------------------
@@ -752,6 +948,39 @@ XML_DTD =
GENERATE_AUTOGEN_DEF = NO
#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader. This is useful
+# if you want to understand what is going on. On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
@@ -770,7 +999,7 @@ MACRO_EXPANSION = NO
# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
# then the macro expansion is limited to the macros specified with the
-# PREDEFINED and EXPAND_AS_PREDEFINED tags.
+# PREDEFINED and EXPAND_AS_DEFINED tags.
EXPAND_ONLY_PREDEF = NO
@@ -796,32 +1025,47 @@ INCLUDE_FILE_PATTERNS =
# are defined before the preprocessor is started (similar to the -D option of
# gcc). The argument of the tag is a list of macros of the form: name
# or name=definition (no spaces). If the definition and the = are
-# omitted =1 is assumed.
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
PREDEFINED = _WIN32 \
UNICODE \
_UNICODE
-# If the MACRO_EXPANSION and EXPAND_PREDEF_ONLY tags are set to YES then
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
# this tag can be used to specify a list of macro names that should be expanded.
# The macro definition that is found in the sources will be used.
# Use the PREDEFINED tag if you want to use a different macro definition.
EXPAND_AS_DEFINED =
-# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
-# doxygen's preprocessor will remove all function-like macros that are
-# alone on a line, have an all uppercase name, and do not end with a
-# semicolon. Such function macros are typically used for boiler-plate
-# code, and will confuse the parser if not removed.
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all function-like macros that are alone
+# on a line, have an all uppercase name, and do not end with a semicolon. Such
+# function macros are typically used for boiler-plate code, and will confuse
+# the parser if not removed.
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------
-# Configuration::addtions related to external references
+# Configuration::additions related to external references
#---------------------------------------------------------------------------
-# The TAGFILES tag can be used to specify one or more tagfiles.
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen
+# is run, you must also specify the path to the tagfile here.
TAGFILES =
@@ -852,13 +1096,22 @@ PERL_PATH = /usr/bin/perl
#---------------------------------------------------------------------------
# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
-# generate a inheritance diagram (in Html, RTF and LaTeX) for classes with base or
-# super classes. Setting the tag to NO turns the diagrams off. Note that this
-# option is superceded by the HAVE_DOT option below. This is only a fallback. It is
-# recommended to install and use dot, since it yield more powerful graphs.
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option is superseded by the HAVE_DOT option below. This is only a
+# fallback. It is recommended to install and use dot, since it yields more
+# powerful graphs.
CLASS_DIAGRAMS = YES
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see http://www.mcternan.me.uk/mscgen/) to
+# produce the chart and insert it in the documentation. The MSCGEN_PATH tag allows you to
+# specify the directory where the mscgen tool resides. If left empty the tool is assumed to
+# be found in the default search path.
+
+MSCGEN_PATH =
+
# If set to YES, the inheritance and collaboration graphs will hide
# inheritance and usage relations if the target is undocumented
# or is not a class.
@@ -886,6 +1139,17 @@ CLASS_GRAPH = YES
COLLABORATION_GRAPH = YES
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK = NO
+
# If set to YES, the inheritance and collaboration graphs will show the
# relations between templates and their instances.
@@ -905,11 +1169,34 @@ INCLUDE_GRAPH = YES
INCLUDED_BY_GRAPH = YES
+# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will
+# generate a call dependency graph for every global function or class method.
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then doxygen will
+# generate a caller dependency graph for every global function or class method.
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command.
+
+CALLER_GRAPH = NO
+
# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
# will graphical hierarchy of all classes instead of a textual one.
GRAPHICAL_HIERARCHY = YES
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH = YES
+
# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
# generated by dot. Possible values are png, jpg, or gif
# If left blank png will be used.
@@ -917,7 +1204,7 @@ GRAPHICAL_HIERARCHY = YES
DOT_IMAGE_FORMAT = png
# The tag DOT_PATH can be used to specify the path where the dot tool can be
-# found. If left blank, it is assumed the dot tool can be found on the path.
+# found. If left blank, it is assumed the dot tool can be found in the path.
DOT_PATH =
@@ -927,21 +1214,28 @@ DOT_PATH =
DOTFILE_DIRS =
-# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width
-# (in pixels) of the graphs generated by dot. If a graph becomes larger than
-# this value, doxygen will try to truncate the graph, so that it fits within
-# the specified constraint. Beware that most browsers cannot cope with very
-# large images.
+# The MAX_DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
+# nodes that will be shown in the graph. If the number of nodes in a graph
+# becomes larger than this value, doxygen will truncate the graph, which is
+# visualized by representing a node as a red box. Note that doxygen will always
+# show the root nodes and its direct children regardless of this setting.
+
+DOT_GRAPH_MAX_NODES = 50
-MAX_DOT_GRAPH_WIDTH = 1024
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, which results in a white background.
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
-# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height
-# (in pixels) of the graphs generated by dot. If a graph becomes larger than
-# this value, doxygen will try to truncate the graph, so that it fits within
-# the specified constraint. Beware that most browsers cannot cope with very
-# large images.
+DOT_TRANSPARENT = NO
-MAX_DOT_GRAPH_HEIGHT = 1024
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS = NO
# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
# generate a legend page explaining the meaning of the various boxes and
@@ -950,51 +1244,16 @@ MAX_DOT_GRAPH_HEIGHT = 1024
GENERATE_LEGEND = YES
# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
-# remove the intermedate dot files that are used to generate
+# remove the intermediate dot files that are used to generate
# the various graphs.
DOT_CLEANUP = YES
#---------------------------------------------------------------------------
-# Configuration::addtions related to the search engine
+# Configuration::additions related to the search engine
#---------------------------------------------------------------------------
# The SEARCHENGINE tag specifies whether or not a search engine should be
# used. If set to NO the values of all tags below this one will be ignored.
SEARCHENGINE = NO
-
-# The CGI_NAME tag should be the name of the CGI script that
-# starts the search engine (doxysearch) with the correct parameters.
-# A script with this name will be generated by doxygen.
-
-CGI_NAME = search.cgi
-
-# The CGI_URL tag should be the absolute URL to the directory where the
-# cgi binaries are located. See the documentation of your http daemon for
-# details.
-
-CGI_URL =
-
-# The DOC_URL tag should be the absolute URL to the directory where the
-# documentation is located. If left blank the absolute path to the
-# documentation, with file:// prepended to it, will be used.
-
-DOC_URL =
-
-# The DOC_ABSPATH tag should be the absolute path to the directory where the
-# documentation is located. If left blank the directory on the local machine
-# will be used.
-
-DOC_ABSPATH =
-
-# The BIN_ABSPATH tag must point to the directory where the doxysearch binary
-# is installed.
-
-BIN_ABSPATH = /usr/local/bin/
-
-# The EXT_DOC_PATHS tag can be used to specify one or more paths to
-# documentation generated for other projects. This allows doxysearch to search
-# the documentation for these projects as well.
-
-EXT_DOC_PATHS =
diff --git a/src/windows/identity/doc/footer.html b/src/windows/identity/doc/footer.html
index fb3b621..c46b939 100644
--- a/src/windows/identity/doc/footer.html
+++ b/src/windows/identity/doc/footer.html
@@ -5,7 +5,9 @@
<td>
<address style="align:right;">
<small>Generated on $datetime for $projectname $projectnumber by&nbsp;<a href="http://www.doxygen.org/index.html">Doxygen</a> $doxygenversion<br>
- &copy; 2004-2007 Massachusetts Institute of Technology. Contact <a href="mailto:khimaira@mit.edu">khimaira@mit.edu</a><br>
+ &copy; 2004-2007 Massachusetts Institute of Technology.<br>
+ &copy; 2005-2007 Secure Endpoints Inc.<br>
+ Contact <a href="mailto:khimaira@mit.edu">khimaira@mit.edu</a><br>
</small>
</address>
</td>
diff --git a/src/windows/identity/doc/header.html b/src/windows/identity/doc/header.html
index 4235468..d696ed5 100644
--- a/src/windows/identity/doc/header.html
+++ b/src/windows/identity/doc/header.html
@@ -1,5 +1,6 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<title>$title</title>
<link href="$relpath$stylesheet.css" rel="stylesheet" type="text/css">
+<link href="$relpath$tabs.css" rel="stylesheet" type="text/css">
</head><body>
diff --git a/src/windows/identity/doc/images/modules_plugins_krb5.png b/src/windows/identity/doc/images/modules_plugins_krb5.png
new file mode 100644
index 0000000..127e89e
--- /dev/null
+++ b/src/windows/identity/doc/images/modules_plugins_krb5.png
Binary files differ
diff --git a/src/windows/identity/doc/main_page.h b/src/windows/identity/doc/main_page.h
index 34b3d1d..55ccb69 100644
--- a/src/windows/identity/doc/main_page.h
+++ b/src/windows/identity/doc/main_page.h
@@ -25,15 +25,17 @@
/* $Id$ */
-/*! \mainpage NetIDMgr
+/*! \mainpage Network Identity Manager
\image html khimaira_logo.png
\section main_dev Documentation for Developers
- NetIDMgr is a credentials manager, which currently manages
- Kerberos IV, Kerberos V and AFS credentials. This document
- describes the API that is implemented by the NetIDMgr system.
+ 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
@@ -41,16 +43,20 @@
- \subpage releases
&copy; 2004-2007 Massachusetts Institute of Technology
+
+ &copy; 2005-2007 Secure Endpoints Inc.
*/
/*!
\page license License agreement and credits
- NetIDMgr is distributed under the MIT License.
+ 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
@@ -74,33 +80,87 @@
\section license_credits Credits
- NetIDMgr was developed at the Massachusetts Institute of
- Technology.
+ 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
- NetIDMgr bugs can be reported to
- <a href="mailto:kfw-bugs@mit.edu">kfw-bugs@mit.edu</a> for now.
-
- In the future, there will actually be a place to track NetIDMgr 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 diagnose the problem. More guidelines about
- reporting bugs will appear here at some point in time.
+ 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.0 beta.
+ Released along with Kerberos for Windows 3.0 beta.
- - <b>0.1.2</b> Second Alpha release <em>Nov 30, 2005</em>\n
- Released along with Kerberos for Windows 3.0.0 beta 2.
*/
diff --git a/src/windows/identity/doc/netidmgr.doc b/src/windows/identity/doc/netidmgr.doc
index 41a0cda..5cff07e 100755
--- a/src/windows/identity/doc/netidmgr.doc
+++ b/src/windows/identity/doc/netidmgr.doc
Binary files differ
diff --git a/src/windows/identity/doc/netidmgr.pdf b/src/windows/identity/doc/netidmgr.pdf
index f28e577..089f860 100755
--- a/src/windows/identity/doc/netidmgr.pdf
+++ b/src/windows/identity/doc/netidmgr.pdf
Binary files differ
diff --git a/src/windows/identity/doc/plugin_framework.h b/src/windows/identity/doc/plugin_framework.h
index c714284..a10af2a 100644
--- a/src/windows/identity/doc/plugin_framework.h
+++ b/src/windows/identity/doc/plugin_framework.h
@@ -1,5 +1,6 @@
/*
* 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
@@ -25,107 +26,158 @@
/* $Id$ */
/*!
-\page pi_framework Plugin Framework
+\page pi_framework Plug-in Framework
-\section pi_fw_pnm Plugins and Modules
+\section pi_fw_pnm Introduction to Plug-ins, Modules and Messages
-\subsection pi_fw_pnm_p Plugins
+\subsection pi_fw_pnm_p Plug-ins
-A NetIDMgr plugin is a package that implements a defined API that will
-perform credentials management or related tasks on behalf of NetIDMgr.
-The core NetIDMgr codebase does not interact directly with Kerberos of
-AFS or any other external entity directly. Instead, plugins are used
-to abstract out this task.
+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.
-Each plugin has a name. The name should be unique among the loaded
-plugins, or the plugin will fail to load.
+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 method in which NetIDMgr communicates with a plugin depends on the
-plugin type. For more information on each plugin type, please refer
-to \ref pi_pt.
-
-Most plugin types rely on a message processor for communication.
-During plugin registration, the module specifies the message processor
-for the plugin, which acts as the only point of contact between the
-NetIDMgr core and the plugin. Some other plugins require exporting
-specific functions.
+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 plugins can be bundled together into a module. A module
-is essentially a dynamically loadable library which contain a specific
-set of callbacks. Currently, the only two required callbacks for a
-module are :
+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()
-\section pi_fw_pm Plugin/Module Manager
+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 ...
-The plugin manager maintains a separate thread for loading and
-registering modules. When a module is successfully loaded and it
-registers one or more plugins, a new thread is created for each
-plugin. Plugin specific initialization and other callback functions
-are called from within this new thread. This is to prevent one plugin
-from "hanging" other plugins and the main NetIDMgr UI threads.
+*/
+
+/*!
+
+\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, the following sequence of events
-happen.
+When kmm_load_module() is called to load a specific module, the
+following sequence of events occur:
-- The standard system search path is used to locate the binary.
+- The registration information for the module is located on the
+ registry key \c
+ \Software\MIT\NetIDMgr\PluginManager\Modules\[ModuleName].
-- The binary is loaded into the address space of NetIDMgr along with
- any dependencies not already loaded.
+- 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.
-- If the NetIDMgr 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 binary is loaded into the address space of Network Identity
+ Manager along with any dependencies not already loaded.
-- init_module() for the loaded module is called. If this function
- returns an error or if no plugins are registered, then the module is
- unloaded. See \ref pi_fw_pm_unload.
+- 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
- plugins that it is implementing by calling kmm_register_plugin() for
+ plug-ins that it is implementing by calling kmm_register_plugin() for
each.
-- Once init_module() returns, each plugin is initialized. The method
- by which a plugin is initialized depends on the plugin type. The
- initialization code for the plugin may indicate that it didn't
- initialize properly, in which case the plugin is immediately
- unregistered. No further calls are made to the plugin.
+- 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 plugin is successfully loaded, the module is unloaded. See
+- If no plug-in is successfully loaded, the module is unloaded. See
\ref pi_fw_pm_unload.
-- During normal operation, any registered plugins for a module can be
- unloaded explicitly, or the plugin itself may signal that it should
- be unloaded. If at anytime, all the plugins for the module are
- unloaded, then the module itself is also unloaded.
+- 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 plugins that are registered for a module, the exit
+- 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
- plugin type. The plugin is not given a chance to object to the
- decision to unload. Each plugin is responsible for performing
+ 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.
-- exit_module() is called for the module.
+- 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 6c3774f..646f895 100644
--- a/src/windows/identity/doc/plugin_locale.h
+++ b/src/windows/identity/doc/plugin_locale.h
@@ -1,5 +1,6 @@
/*
* 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
@@ -32,10 +33,10 @@ 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 plugin is
+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 plugin.
+does not manage these libraries for the plug-in.
\section pi_loc_spec Specification of localized resources
@@ -105,3 +106,4 @@ the regular WIN32 API.
*/
+
diff --git a/src/windows/identity/doc/plugin_main.h b/src/windows/identity/doc/plugin_main.h
index ed06c6d..70040b2 100644
--- a/src/windows/identity/doc/plugin_main.h
+++ b/src/windows/identity/doc/plugin_main.h
@@ -1,5 +1,6 @@
/*
* 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
@@ -26,75 +27,78 @@
/*!
-\page plugins NetIDMgr Modules and Plugins
+\page plug-ins Network Identity Manager Modules and Plug-ins
-Plugins and localization are handled by the NetIDMgr Module Manager
-API. Each plugin consists of a dynamically loadable library and zero
-or more associated resource libraries.
+ 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.
-For more information about NetIDMgr Plugins, see the following
-sections:
+ Plug-ins and localization are handled by the Network Identity
+ Manager Module Manager API.
-- \subpage pi_framework
-- \subpage pi_pt
-- \subpage pi_structure
-- \subpage pi_localization
+ The following sections describe plug-ins in detail:
+
+ - \subpage pi_framework
+ - \subpage pi_pt
+ - \subpage pi_structure
+ - \subpage pi_localization
*/
-/*! \page pi_pt Plugin Types
+/*! \page pi_pt Plug-in Types
-The types of plugins that are currently supported by NetIDMgr are :
+The types of plug-ins that are currently supported by Network Identity
+Manager are :
\section pi_pt_cred Credential Provider
-A credential provider plugin essentially acts as an interface between
-NetIDMgr and some entity which defines the credentials for the purpose
-of managing those credentials.
+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 NetIDMgr 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.
+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 plugins, <::KMSG_SYSTEM,::KMSG_SYSTEM_INIT> is
+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 plugin is assume to not be loaded and
-immediately unregistered.
+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 plugin can use the <::KMSG_SYSTEM,::KMSG_SYSTEM_INIT>
+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 plugins that may depend
+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 plugin is to be removed, the module manager sends a
+When the plug-in is to be removed, the module manager sends a
<::KMSG_SYSTEM,::KMSG_SYSTEM_EXIT> to the message processor. The
-plugin must perform any necessary shutdown operations, free up
+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 plugin if the plugin unsubsribes from all
+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
@@ -106,21 +110,6 @@ unsubscribed from as they are automatically removed.
Since credential managers may receive privileged information, the
signature requirements for credential managers are specially strict.
-\section pi_pt_conf Configuration Provider
-
-Provides configuration information.
-[TODO: fill in]
-
-\subsection pi_pt_conf_comm Communication
-[TODO: fill in]
-
-\subsection pi_pt_conf_init Initialization
-[TODO: fill in]
-
-\subsection pi_pt_conf_exit Uninitialization
-[TODO: fill in]
-
-\subsection pi_pt_conf_other Other Notes
-
*/
+
diff --git a/src/windows/identity/doc/plugin_structure.h b/src/windows/identity/doc/plugin_structure.h
index b41ff3a..452029e 100644
--- a/src/windows/identity/doc/plugin_structure.h
+++ b/src/windows/identity/doc/plugin_structure.h
@@ -1,5 +1,6 @@
/*
* 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
@@ -28,16 +29,20 @@
\page pi_structure Structure of a module
-A NetIDMgr module is essentially a dynamically loadable library with a
-specific set of exported symbols. Each export symbol and general
-notes about writing a plugin module are documented below.
+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 NetIDMgr API functions from
+stage. Specifically, do not call any Network Identity Manager API functions from
within DllMain.
\section pi_str_cb Callbacks
diff --git a/src/windows/identity/doc/stylesheet.css b/src/windows/identity/doc/stylesheet.css
index fc3e062..ddc3d1f 100644
--- a/src/windows/identity/doc/stylesheet.css
+++ b/src/windows/identity/doc/stylesheet.css
@@ -1,62 +1,87 @@
BODY,H1,H2,H3,H4,H5,H6,P,CENTER,TD,TH,UL,DL,DIV {
font-family: Geneva, Arial, Helvetica, sans-serif;
}
+BODY,TD {
+ font-size: 90%;
+}
H1 {
text-align: center;
+ font-size: 160%;
+}
+H2 {
+ font-size: 120%;
+}
+H3 {
+ font-size: 100%;
}
CAPTION { font-weight: bold }
DIV.qindex {
width: 100%;
- background-color: #000000;
- border: 1px solid #000000;
+ background-color: #e8eef2;
+ border: 1px solid #84b0c7;
+ text-align: center;
margin: 2px;
padding: 2px;
- line-height: 100%;
- color: #ffffff
+ line-height: 140%;
}
DIV.nav {
width: 100%;
- background-color: #000000;
- border: 1px solid #000000;
+ background-color: #e8eef2;
+ border: 1px solid #84b0c7;
text-align: center;
margin: 2px;
padding: 2px;
- line-height: 100%;
- color: #ffffff;
+ line-height: 140%;
+}
+DIV.navtab {
+ background-color: #e8eef2;
+ border: 1px solid #84b0c7;
+ text-align: center;
+ margin: 2px;
+ margin-right: 15px;
+ padding: 2px;
+}
+TD.navtab {
+ font-size: 70%;
}
A.qindex {
text-decoration: none;
- color: #ffffff;
+ font-weight: bold;
+ color: #1A419D;
}
A.qindex:visited {
text-decoration: none;
- color: #ffffff;
+ font-weight: bold;
+ color: #1A419D
}
A.qindex:hover {
text-decoration: none;
- background-color: #ffffff;
- color: #000000
+ background-color: #ddddff;
}
A.qindexHL {
text-decoration: none;
font-weight: bold;
+ background-color: #6666cc;
+ color: #ffffff;
+ border: 1px double #9295C2;
}
A.qindexHL:hover {
text-decoration: none;
- background-color: #333333;
+ background-color: #6666cc;
color: #ffffff;
}
-A.qindexHL:visited { text-decoration: none; background-color: #333333; color: #ffffff }
-A.el { text-decoration: none; }
-A.elRef { }
+A.qindexHL:visited { text-decoration: none; background-color: #6666cc; color: #ffffff }
+A.el { text-decoration: none; font-weight: bold }
+A.elRef { font-weight: bold }
A.code:link { text-decoration: none; font-weight: normal; color: #0000FF}
A.code:visited { text-decoration: none; font-weight: normal; color: #0000FF}
A.codeRef:link { font-weight: normal; color: #0000FF}
A.codeRef:visited { font-weight: normal; color: #0000FF}
-A:hover { text-decoration: none; background-color: #cccccc }
+A:hover { text-decoration: none; background-color: #f2f2ff }
DL.el { margin-left: -1cm }
.fragment {
- font-family: monospace
+ font-family: monospace, fixed;
+ font-size: 95%;
}
PRE.fragment {
border: 1px solid #CCCCCC;
@@ -71,16 +96,14 @@ PRE.fragment {
padding-bottom: 4px;
}
DIV.ah { background-color: black; font-weight: bold; color: #ffffff; margin-bottom: 3px; margin-top: 3px }
-TD.md { background-color: #cccccc; font-weight: bold; }
-TD.mdname1 { background-color: #cccccc; font-weight: bold; color: #000000; }
-TD.mdname { background-color: #cccccc; font-weight: bold; color: #000000; width: 600px; }
+
DIV.groupHeader {
margin-left: 16px;
margin-top: 12px;
margin-bottom: 6px;
font-weight: bold;
}
-DIV.groupText { margin-left: 16px; font-style: italic; font-size: 14px }
+DIV.groupText { margin-left: 16px; font-style: italic; font-size: 90% }
BODY {
background: white;
color: black;
@@ -88,7 +111,7 @@ BODY {
margin-left: 20px;
}
TD.indexkey {
- background-color: #cccccc;
+ background-color: #e8eef2;
font-weight: bold;
padding-right : 10px;
padding-top : 2px;
@@ -101,7 +124,7 @@ TD.indexkey {
border: 1px solid #CCCCCC;
}
TD.indexvalue {
- background-color: #cccccc;
+ background-color: #e8eef2;
font-style: italic;
padding-right : 10px;
padding-top : 2px;
@@ -114,7 +137,7 @@ TD.indexvalue {
border: 1px solid #CCCCCC;
}
TR.memlist {
- background-color: #f0f0f0;
+ background-color: #f0f0f0;
}
P.formulaDsp { text-align: center; }
IMG.formulaDsp { }
@@ -126,16 +149,9 @@ SPAN.comment { color: #800000 }
SPAN.preprocessor { color: #806020 }
SPAN.stringliteral { color: #002080 }
SPAN.charliteral { color: #008080 }
-.mdTable {
- border: 1px solid #cccccc;
- background-color: #cccccc;
-}
-.mdRow {
- padding: 8px 10px;
-}
.mdescLeft {
padding: 0px 8px 4px 8px;
- font-size: 12px;
+ font-size: 80%;
font-style: italic;
background-color: #FAFAFA;
border-top: 1px none #E0E0E0;
@@ -146,7 +162,7 @@ SPAN.charliteral { color: #008080 }
}
.mdescRight {
padding: 0px 8px 4px 8px;
- font-size: 12px;
+ font-size: 80%;
font-style: italic;
background-color: #FAFAFA;
border-top: 1px none #E0E0E0;
@@ -171,7 +187,7 @@ SPAN.charliteral { color: #008080 }
border-bottom-style: none;
border-left-style: none;
background-color: #FAFAFA;
- font-size: 12px;
+ font-size: 80%;
}
.memItemRight {
padding: 1px 8px 0px 8px;
@@ -189,7 +205,7 @@ SPAN.charliteral { color: #008080 }
border-bottom-style: none;
border-left-style: none;
background-color: #FAFAFA;
- font-size: 13px;
+ font-size: 80%;
}
.memTemplItemLeft {
padding: 1px 0px 0px 8px;
@@ -207,7 +223,7 @@ SPAN.charliteral { color: #008080 }
border-bottom-style: none;
border-left-style: none;
background-color: #FAFAFA;
- font-size: 12px;
+ font-size: 80%;
}
.memTemplItemRight {
padding: 1px 8px 0px 8px;
@@ -225,7 +241,7 @@ SPAN.charliteral { color: #008080 }
border-bottom-style: none;
border-left-style: none;
background-color: #FAFAFA;
- font-size: 13px;
+ font-size: 80%;
}
.memTemplParams {
padding: 1px 0px 0px 8px;
@@ -244,7 +260,7 @@ SPAN.charliteral { color: #008080 }
border-left-style: none;
color: #606060;
background-color: #FAFAFA;
- font-size: 12px;
+ font-size: 80%;
}
.search { color: #003399;
font-weight: bold;
@@ -256,16 +272,88 @@ FORM.search {
INPUT.search { font-size: 75%;
color: #000080;
font-weight: normal;
- background-color: #ffcc99;
+ background-color: #e8eef2;
}
TD.tiny { font-size: 75%;
}
a {
- color: #0000ff;
+ color: #1A41A8;
}
a:visited {
- color: #0000ff;
+ color: #2A3798;
+}
+.dirtab { padding: 4px;
+ border-collapse: collapse;
+ border: 1px solid #84b0c7;
+}
+TH.dirtab { background: #e8eef2;
+ font-weight: bold;
+}
+HR { height: 1px;
+ border: none;
+ border-top: 1px solid black;
+ border-color: #88b7c8;
+}
+
+/* Style for detailed member documentation */
+.memtemplate {
+ font-size: 80%;
+ color: #606060;
+ font-weight: normal;
+}
+.memnav {
+ background-color: #e8eef2;
+ border: 1px solid #84b0c7;
+ text-align: center;
+ margin: 2px;
+ margin-right: 15px;
+ padding: 2px;
+}
+.memitem {
+ padding: 4px;
+ background-color: #eef3f5;
+ border-width: 1px;
+ border-style: solid;
+ border-color: #dedeee;
+ -moz-border-radius: 8px 8px 8px 8px;
+}
+.memname {
+ white-space: nowrap;
+ font-weight: bold;
+}
+.memdoc{
+ padding-left: 10px;
+}
+.memproto {
+ background-color: #d5e1e8;
+ width: 100%;
+ border-width: 1px;
+ border-style: solid;
+ border-color: #84b0c7;
+ font-weight: bold;
+ -moz-border-radius: 8px 8px 8px 8px;
+}
+.paramkey {
+ text-align: right;
+}
+.paramtype {
+ white-space: nowrap;
+}
+.paramname {
+ color: #602020;
+ font-style: italic;
+ white-space: nowrap;
+}
+/* End Styling for detailed member documentation */
+
+/* for the tree view */
+.ftvtree {
+ font-family: sans-serif;
+ margin:0.5em;
}
-.anchor {
- color: #000000;
-} \ No newline at end of file
+.directory { font-size: 9pt; font-weight: bold; }
+.directory h3 { margin: 0px; margin-top: 1em; font-size: 11pt; }
+.directory > h3 { margin-top: 0; }
+.directory p { margin: 0px; white-space: nowrap; }
+.directory div { display: none; margin: 0px; }
+.directory img { vertical-align: -30%; }
diff --git a/src/windows/identity/doc/ui_actions.h b/src/windows/identity/doc/ui_actions.h
index de4e802..43bf3a9 100644
--- a/src/windows/identity/doc/ui_actions.h
+++ b/src/windows/identity/doc/ui_actions.h
@@ -1,5 +1,6 @@
/*
* 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
diff --git a/src/windows/identity/doc/ui_context.h b/src/windows/identity/doc/ui_context.h
index b9bfadd..12843fb 100644
--- a/src/windows/identity/doc/ui_context.h
+++ b/src/windows/identity/doc/ui_context.h
@@ -1,5 +1,6 @@
/*
* 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
@@ -38,7 +39,7 @@
context functions and data structures provide access to this
information.
- The NetIDMgr user interface presents an outline view of all the
+ 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.
@@ -99,12 +100,12 @@
obtain and store the context in a location that is accessible to
the handlers of the message.
- If a plugin needs to obtain the UI context, it should do so by
+ 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 plugin is done with the
+ 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
diff --git a/src/windows/identity/doc/ui_main.h b/src/windows/identity/doc/ui_main.h
index 6e17980..d7bc6be 100644
--- a/src/windows/identity/doc/ui_main.h
+++ b/src/windows/identity/doc/ui_main.h
@@ -1,5 +1,6 @@
/*
* 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
diff --git a/src/windows/identity/doc/ui_menus.h b/src/windows/identity/doc/ui_menus.h
index 09cc16e..794aef6 100644
--- a/src/windows/identity/doc/ui_menus.h
+++ b/src/windows/identity/doc/ui_menus.h
@@ -1,5 +1,6 @@
/*
* 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
diff --git a/src/windows/identity/help/Makefile b/src/windows/identity/help/Makefile
index fa76b02..8cb7f71 100644
--- a/src/windows/identity/help/Makefile
+++ b/src/windows/identity/help/Makefile
@@ -36,4 +36,4 @@ $(CHMFILE): netidmgr.hhp
$(CP) netidmgr.chm $(CHMFILE)
clean::
- $(RM) $(CHMFILE) \ No newline at end of file
+ if exist '..\obj' $(RM) $(INCFILES)
diff --git a/src/windows/identity/help/html/act_chpw.htm b/src/windows/identity/help/html/act_chpw.htm
index 40f9705..33ec3a2 100644
--- a/src/windows/identity/help/html/act_chpw.htm
+++ b/src/windows/identity/help/html/act_chpw.htm
@@ -1,21 +1,26 @@
<html>
<head>
- <title>Change Password</title>
+ <title>Network Identity Manager - Change Password</title>
<meta name="description" content="change password">
<meta name="keywords" content="change password dialog">
<link rel="stylesheet" type="text/css" href="nidmgr.css">
+
+ <Object type="application/x-oleobject" classid="clsid:1e2a7bd0-dab9-11d0-b93a-00c04fc99f9e">
+<param name="Keyword" value="Changing Passwords">
+</OBJECT>
</head>
<body>
-<h1>Change Password</h1>
+<h1>Network Identity Manager - Change Password</h1>
<p>The change password dialog can be invoked from the <a
href="menu_credential.htm">Credentials</a> menu. This is used to
change the password for the primary credentials provider (currently
-Kerberos 5).
+Kerberos v5).
</p>
+<p><img border="0" src="images/screen_chng_pwd.png" width="456" height="244"></p>
-<p>For the default identity provider (Kerberos 5), there are two input
+<p>For the default identity provider (Kerberos v5), there are two input
boxes to specify the identity for which the password is to be changed.
The identity uniquely maps to the Kerberos principal of the same name.
Then the current password must be entered along with the new password
@@ -23,7 +28,7 @@ twice.
</p>
<p>Note that currently, when the password for an identity is being
-changed, only the associated Kerberos 5 password is changed.
+changed, only the associated Kerberos v5 password is changed.
</p>
</body>
diff --git a/src/windows/identity/help/html/act_destroy_creds.htm b/src/windows/identity/help/html/act_destroy_creds.htm
index ff24561..f1643f1 100644
--- a/src/windows/identity/help/html/act_destroy_creds.htm
+++ b/src/windows/identity/help/html/act_destroy_creds.htm
@@ -1,17 +1,20 @@
<html>
<head>
- <title>Destroy Credentials</title>
+ <title>Network Identity Manager - Destroy Credentials</title>
<meta name="description" content="Destroy Credentials">
<meta name="keywords" content="destroy credentials">
<link rel="stylesheet" type="text/css" href="nidmgr.css">
-</head>
+<Object type="application/x-oleobject" classid="clsid:1e2a7bd0-dab9-11d0-b93a-00c04fc99f9e">
+<param name="Keyword" value="Destroying Credentials">
+<param name="Keyword" value="Ctrl + D">
+<param name="Keyword" value="Delete key">
+</OBJECT></head>
<body>
-<h1>Destroy Credentials</h1>
+<h1>Network Identity Manager - Destroy Credentials</h1>
<p>This action will attempt to destroy the credentials that are
-currently selected in the credentials window. How the credentials are
-destroyed is up to each credentials provider.
+currently selected in the credentials window.
</p>
<p>In some cases, you may need to select all the credentials of a
diff --git a/src/windows/identity/help/html/act_import_creds.htm b/src/windows/identity/help/html/act_import_creds.htm
index 550bb39..59ab2db 100644
--- a/src/windows/identity/help/html/act_import_creds.htm
+++ b/src/windows/identity/help/html/act_import_creds.htm
@@ -1,26 +1,30 @@
<html>
<head>
- <title>Import Credentials</title>
+ <title>Network Identity Manager - Import Credentials</title>
<meta name="description" content="Import Credentials">
<meta name="keywords" content="Import Credentials">
<link rel="stylesheet" type="text/css" href="nidmgr.css">
-</head>
+
+<Object type="application/x-oleobject" classid="clsid:1e2a7bd0-dab9-11d0-b93a-00c04fc99f9e">
+<param name="Keyword" value="Importing Credentials">
+<param name="Keyword" value="Ctrl + I">
+<param name="Keyword" value="MSLSA">
+</OBJECT></head>
<body>
-<h1>Import Credentials</h1>
+<h1>Network Identity Manager - Import Credentials</h1>
-<p>Allows you to import credentials from the Windows LSA credentials
-cache into any of the caches under the control of any credentials
-provider. Currently, the only credentials provider that supports
-importing is Kerberos 5.
+<p>Allows you to import credentials from the Microsoft Windows LSA credentials
+cache. Currently, the only credentials provider that supports
+importing is Kerberos v5.
</p>
<p>This action can be invoked via the <a
href="menu_credential.htm">Credentials</a> menu or by pressing <span
-class="pre">Ctrl + I</span>. In addition, the Kerberos 5
+class="pre">Ctrl + I</span>. In addition, the Kerberos v5
configuration pane accessible via the <a
-href="menu_options.htm">Options</a> menu provides an options that
-control how the importing of credentials happen.
+href="menu_options.htm">Options</a> menu contain settings that
+control when the importing of credentials are performed at startup.
</p>
</body>
diff --git a/src/windows/identity/help/html/act_new_creds.htm b/src/windows/identity/help/html/act_new_creds.htm
index f2769e0..7f1dbc6 100644
--- a/src/windows/identity/help/html/act_new_creds.htm
+++ b/src/windows/identity/help/html/act_new_creds.htm
@@ -1,13 +1,22 @@
<html>
<head>
- <title>New Credentials</title>
+ <title>Network Identity Manager - New Credentials</title>
<meta name="description" content="obtain new credentials">
<meta name="keywords" content="new creds">
<link rel="stylesheet" type="text/css" href="nidmgr.css">
+
+ <Object type="application/x-oleobject" classid="clsid:1e2a7bd0-dab9-11d0-b93a-00c04fc99f9e">
+<param name="Keyword" value="Obtaining New Credentials">
+<param name="Keyword" value="Ctrl + N">
+<param name="Keyword" value="New Credentials Dialog">
+<param name="Keyword" value="Kerberos v5 ticket flags">
+<param name="Keyword" value="Changing Passwords">
+<param name="Keyword" value="Obtain New Credentials at Startup">
+</OBJECT>
</head>
<body>
-<h1>New Credentials</h1>
+<h1>Network Identity Manager - New Credentials</h1>
<p>The new credentials dialog can be invoked from the <a
href="menu_credential.htm">Credentials</a> menu, by typing <span
@@ -21,14 +30,11 @@ following:
</p>
<p>
-<img src="images/screen_new_creds.bmp" alt="New credentials dialog"/>
+<img src="images/screen_new_creds.png" alt="New credentials dialog"/>
<p class="caption">New credentials dialog with a valid identity
-selected.</p> <p class="caption"><i>Note that the above screenshot is
-from an instance of NetIDMgr with Kerberos 5, Kerberos 4 and OpenAFS
-plugins with a Kerberos 5 identity manager. Actual display may be
-different depending on the plugins that are active.</i></p>
+selected.</p>
-<p>If the Kerberos 5 identity provider is used, the dialog will ask
+<p>If the Kerberos v5 identity provider is used, the dialog will ask
for a username and a realm to determine the identity for which new
credentials will be obtained for. Depending on the selected identity,
you may be required to provide a password or other form of
@@ -36,31 +42,35 @@ authentication for new credentials to be obtained.
</p>
<p>Below the prompts is the credentials summary window. This window
-provides an overview of the credentals that will be obtained when the
+provides an overview of the credentials that will be obtained when the
dialog is completed.
</p>
<h3>Expanded view</h3>
<p>If you click any of the credentials type hyperlinks in the
-credentials summary window or select the <span class="pre">Options
-&gt;&gt;</span> button, the dialog will switch to the exanded view.
+credentials summary window or select the <span class="pre">&gt;&gt;</span> button, the dialog will switch to the expanded view.
An example of this is shown below:
</p>
<p>
-<img src="images/screen_new_creds_exp.bmp"
+<img src="images/screen_new_creds_exp.png"
alt="Expanded new credentials window" />
-<p class="caption">Expanded view of the new credetials dialog</p>
+<p class="caption">Expanded view of the new credentials dialogg</p>
<p>
The expanded view provides access to additional options available for
-each credential provider. For example, the Kerberos 5 credentials
+each credential provider. For example, the Kerberos v5 credentials
provider allows you to set the lifetime of the obtained Kerberos
ticket as well as ticket flags such as <i>renewable</i> or
<i>forwardable</i>.
</p>
+<p>
+<i>Note that the above screenshot is
+from an instance of NetIDMgr with Kerberos v5, Kerberos v4, OpenAFS and
+Kerberized Certificate Authority providers with a Kerberos v5 identity provider. Actual display may be
+different depending on the providers that are active.</i></p>
<h3>Credentials summary window</h3>
@@ -76,22 +86,21 @@ window will display a message describing the problem. For example:
</p>
<p>
-<img src="images/screen_new_creds_err01.bmp" alt="Credentials summary window showing an invalid identity" />
+<img src="images/screen_new_creds_err01.png" alt="Credentials summary window showing an invalid identity" />
</p>
<p>
The above is an example of what you would see if the provided identity
-is invalid. Once the identity provider (in this case, Kerberos 5)
+is invalid. Once the identity provider (in this case, Kerberos v5)
indicates that the identity is invalid, it will be displayed as above
along with a brief description of why the identity was found to be
-invalid. Here, the Kerberos 5 identity provider is reporting that the
+invalid. Here, the Kerberos v5 identity provider is reporting that the
specified principal does not exist in the Kerberos database.
</p>
<h3>Additional notes</h3>
-<p>
-The new credentials dialog can be invoked from the command line using
+<p>The new credentials dialog can be invoked from the command line using
the <span class="pre"> -i </span> or <span class="pre"> --kinit
</span> command line option. Additionally, if you specify the <span
class="pre"> -a </span> or <span class="pre"> --autoinit </span>
@@ -100,10 +109,9 @@ there are no credentials available.
</p>
<p>
-Setting the <span class="pre">Prompt for new credentials if there
-aren't any at startup</span> option is set in the <span
-class="pre">General</span> configuration panel, then the behavior is
-similar to the <span class="pre">--autoinit</span> option.
+Setting the <span class="pre">Obtain new credentials at startup (if none are present)</span> option in the <span
+class="pre">General</span> configuration panel causes NetIDMgr to behave as if
+the <span class="pre">--autoinit</span> option is specified at each execution.
</p>
</body>
diff --git a/src/windows/identity/help/html/act_renew_creds.htm b/src/windows/identity/help/html/act_renew_creds.htm
index 0bd196a..e582b23 100644
--- a/src/windows/identity/help/html/act_renew_creds.htm
+++ b/src/windows/identity/help/html/act_renew_creds.htm
@@ -1,32 +1,40 @@
<html>
<head>
- <title>Renew Credentials</title>
+ <title>Network Identity Manager - Renew Credentials</title>
<meta name="description" content="Renew Credentials">
<meta name="keywords" content="renew, credentials">
<link rel="stylesheet" type="text/css" href="nidmgr.css">
+
+ <Object type="application/x-oleobject" classid="clsid:1e2a7bd0-dab9-11d0-b93a-00c04fc99f9e">
+<param name="Keyword" value="Renewing Credentials">
+<param name="Keyword" value="Ctrl + R">
+<param name="Keyword" value="Monitor Credential Expiration">
+<param name="Keyword" value="krb524 translator">
+<param name="Keyword" value="">
+<param name="Keyword" value="">
+</OBJECT>
</head>
<body>
-<h1>Renew Credentials</h1>
+<h1>Network Identity Manager - Renew Credentials</h1>
<p>The renew credentials action can be invoked via the <a
href="">Credential</a> menu or by pressing <span class="pre">Ctrl +
-R</span>. Additionally, if <span class="pre">Monitor credentials
+R</span>. Additionally, if the <span class="pre">Monitor credential
expiration</span> option is enabled for all identities or for a
specific identity, then those credentials will be automatically
-renewed before they expire.</p>
+renewed whenever possible before they expire.</p>
<p>An identity must be selected before invoking the renew credentials
action.</p>
<p>Not all credentials can be renewed. The actual logic of renewing
-the credentials is up to each credentials provider. In general
-NetIDMgr will invoke each credentials provider to renew their
-respective credentials. For Kerberos 5, if the initial ticket is
+the credentials is up to each credentials provider. In general, NetIDMgr will invoke each credentials provider to renew their
+respective credentials. For Kerberos v5, if the initial ticket is
renewable and not expired, then it will obtain a renewed initial
-ticket. For Kerberos 4, once a renewed Kerberos 5 initial ticket is
+ticket. For Kerberos v4, once a renewed Kerberos v5 initial ticket is
obtained, it will try to use a Krb524 translator to obtain a new
-Kerberos 4 initial ticket.</p>
+Kerberos v4 initial ticket.</p>
</body>
</html> \ No newline at end of file
diff --git a/src/windows/identity/help/html/act_set_default.htm b/src/windows/identity/help/html/act_set_default.htm
index 382b3c1..6dccd23 100644
--- a/src/windows/identity/help/html/act_set_default.htm
+++ b/src/windows/identity/help/html/act_set_default.htm
@@ -1,15 +1,19 @@
<html>
<head>
- <title>Set As Default Identity</title>
+ <title>Network Identity Manager - Set As Default Identity</title>
<meta name="description" content="Set the default identity">
<meta name="keywords" content="default, identity">
<link rel="stylesheet" type="text/css" href="nidmgr.css">
</head>
<body>
-<h1>Set As Default Identity</h1>
+<h1>Network Identity Manager - Set As Default Identity</h1>
<p>
+One identity can be designated as the default identity. The default identity is the
+identity used by Kerberos v5 and GSS-API based applications which use the default
+Kerberos v5 credential cache and
+never request the use of a network identity by name.
</p>
</body>
diff --git a/src/windows/identity/help/html/bugs.htm b/src/windows/identity/help/html/bugs.htm
index fcc563c..f934dff 100644
--- a/src/windows/identity/help/html/bugs.htm
+++ b/src/windows/identity/help/html/bugs.htm
@@ -1,22 +1,21 @@
<html>
<head>
- <title>Reporting Bugs</title>
+ <title>Network Identity Manager - Reporting Bugs</title>
<meta name="description" content="Reporting bugs and feature requests">
<meta name="keywords" content="bugs,features">
<link rel="stylesheet" type="text/css" href="nidmgr.css">
</head>
<body>
-<h1>Reporting Bugs</h1>
+<h1>Network Identity Manager - Reporting Bugs</h1>
-<p>If you encounter a bug in the software, please email
-<a href="mailto:kfw-bugs@MIT.EDU" class="mail">kfw-bugs@MIT.EDU</a>
-and report it. Please include as much information as possible to
-enable us to reproduce the problem.
+<p>If you encounter a bug in the software, please send a bug report via e-mail to
+<a href="mailto:kfw-bugs@MIT.EDU" class="mail">kfw-bugs@MIT.EDU</a>.
+Please include as much information as possible to assist us in reproducing the problem.
</p>
<p><a href="mailto:kerberos@MIT.EDU" class="mail">kerberos@MIT.EDU</a>
-is a mailing list set up for discussing Kerberos issues. It is
+is a mailing list set up for discussing end user Kerberos issues. It is
gatewayed to the Usenet newsgroup 'comp.protocols.kerberos'. If you
prefer to read it via mail, send a subscription request to
<a href="mailto:kerberos-request@MIT.EDU" class="mail">kerberos-request@MIT.EDU</a>
diff --git a/src/windows/identity/help/html/cmdline_netidmgr.htm b/src/windows/identity/help/html/cmdline_netidmgr.htm
new file mode 100644
index 0000000..f77c475
--- /dev/null
+++ b/src/windows/identity/help/html/cmdline_netidmgr.htm
@@ -0,0 +1,38 @@
+<html>
+<head>
+ <title>Network Identity Manager Command Line Options</title>
+ <meta name="description" content="">
+ <meta name="keywords" content="">
+ <link rel="stylesheet" type="text/css" href="nidmgr.css">
+</head>
+<body>
+
+<h1>Network Identity Manager Command Line Options</h1>
+<p>Command line options for Network Identity Manager are:</p>
+<table border="1" width="57%" id="table1">
+ <tr>
+ <td width="140"><font size="1">-a or --autoinit</font></td>
+ <td><font size="1">Automatic Initialization of Credentials</font></td>
+ </tr>
+ <tr>
+ <td width="140"><font size="1">-i or --kinit</font></td>
+ <td><font size="1">Obtain New Credentials and then exit</font></td>
+ </tr>
+ <tr>
+ <td width="140"><font size="1">-d or --destroy</font></td>
+ <td><font size="1">Destroy Credentials belonging to the default identity
+ and then exit</font></td>
+ </tr>
+ <tr>
+ <td width="140"><font size="1">-r or --renew</font></td>
+ <td><font size="1">Renew all Credentials and then exit</font></td>
+ </tr>
+ <tr>
+ <td width="140"><font size="1">-x or --exit</font></td>
+ <td><font size="1">Signal the running instance of Network Identity
+ Manager to exit</font></td>
+ </tr>
+</table>
+
+</body>
+</html> \ No newline at end of file
diff --git a/src/windows/identity/help/html/concept_cred_pro.htm b/src/windows/identity/help/html/concept_cred_pro.htm
index 37fec76..db936aa 100644
--- a/src/windows/identity/help/html/concept_cred_pro.htm
+++ b/src/windows/identity/help/html/concept_cred_pro.htm
@@ -1,16 +1,38 @@
<html>
<head>
- <title>NetIDMgr Concepts: Credentials Provider</title>
+ <title>Network Identity Manager Concepts: Credentials Provider</title>
<meta name="description" content="NetIDMgr Concepts: Credentials Provider">
<meta name="keywords" content="credentials provider, concepts">
<link rel="stylesheet" type="text/css" href="nidmgr.css">
</head>
<body>
-<h1>NetIDMgr Concepts: Credentials Provider</h1>
+<h1>Network Identity Manager Concepts: Credentials Provider</h1>
<p>
+Network Identity Manager relies on plug-ins to provide the majority
+of its functionality. A <b>credentials provider</b> is a plug-in
+that manages one or more types of credentials. The responsibilities
+of a credential provider are:
</p>
+<ul>
+ <li>to maintain the list of credentials and their properties for the supported type</li>
+ <li>to monitor credential expiration</li>
+ <li>to provide the logic necessary to obtain additional credentials once the
+ <a href="concept_ident_pro.htm">identity provider</a> has obtained the
+ initial credential</li>
+ <li>to provide the user interface panels necessary to permit the user to
+ configure the credential provider</li>
+</ul>
+
+
+<p>MIT Kerberos for Windows ships with two Network Identity Manager credential
+providers supporting Kerberos v5 and Kerberos v4.&nbsp; Credential providers for
+the Andrew File System and the Kerberized Certificate Authority are available
+separately.</p>
+<p>
+<img border="0" src="images/screen_config_cred_provider.png" width="542" height="393"></p>
+
</body>
</html> \ No newline at end of file
diff --git a/src/windows/identity/help/html/concept_credential.htm b/src/windows/identity/help/html/concept_credential.htm
new file mode 100644
index 0000000..eca302e
--- /dev/null
+++ b/src/windows/identity/help/html/concept_credential.htm
@@ -0,0 +1,31 @@
+<html>
+<head>
+ <title>Network Identity Manager Concepts: Credential</title>
+ <meta name="description" content="NetIDMgr Concepts: Credential">
+ <meta name="keywords" content="credential, concepts">
+ <link rel="stylesheet" type="text/css" href="nidmgr.css">
+</head>
+<body>
+
+<h1>Network Identity Manager Concepts: Credential</h1>
+
+<p>
+In Network Identity Manager, a <b>credential</b> is any digital object that can
+be used by a network authentication protocol to assert a specific
+<a href="concept_identity.htm">identity</a>.</p>
+<p>
+As of this writing, Network Identity Manager supports four different types of
+credentials:</p>
+<ul>
+ <li>Kerberos v5 tickets</li>
+ <li>Kerberos v4 tickets</li>
+ <li>AFS tokens</li>
+ <li>X.509 certificates issued by a Kerberized Certificate Authority</li>
+</ul>
+<p>Of these, only Kerberos v5 initial ticket granting tickets can be used as an
+identity provider credential.</p>
+<p>&nbsp;</p>
+
+
+</body>
+</html> \ No newline at end of file
diff --git a/src/windows/identity/help/html/concept_ident_pro.htm b/src/windows/identity/help/html/concept_ident_pro.htm
index 5c4601c..d17c23b 100644
--- a/src/windows/identity/help/html/concept_ident_pro.htm
+++ b/src/windows/identity/help/html/concept_ident_pro.htm
@@ -1,16 +1,32 @@
<html>
<head>
- <title>NetIDMgr Concepts: Identity Provider</title>
+ <title>Network Identity Manager Concepts: Identity Provider</title>
<meta name="description" content="NetIDMgr Concepts: Identity Provider">
<meta name="keywords" content="identity provider, concepts">
<link rel="stylesheet" type="text/css" href="nidmgr.css">
</head>
<body>
-<h1>NetIDMgr Concepts: Identity Provider</h1>
+<h1>Network Identity Manager Concepts: Identity Provider</h1>
<p>
-</p>
+Network Identity Manager relies on plug-ins to provide the majority
+of its functionality. One of the requirements is that there be at
+least one plug-in that is registered as an <strong>identity provider</strong>. The identity
+provider:</p>
+
+<ul>
+ <li>defines the identity</li>
+ <li>provides the engine that drives the <i>Obtain New Credentials</i> dialog</li>
+ <li>performs the initial authentication which results in a network credential that
+ can be used in conjunction with subsequent credential providers</li>
+</ul>
+
+<p>Naturally, the identity provider plug-in that is distributed with MIT Kerberos for Windows
+is Kerberos v5 based and obtains Kerberos v5 ticket granting tickets as the network credential
+that represents the identity.</p>
+<img src="images/screen_config_ident_provider.png">
+<p></p>
</body>
</html> \ No newline at end of file
diff --git a/src/windows/identity/help/html/concept_identity.htm b/src/windows/identity/help/html/concept_identity.htm
index ae2dda0..4340679 100644
--- a/src/windows/identity/help/html/concept_identity.htm
+++ b/src/windows/identity/help/html/concept_identity.htm
@@ -1,18 +1,18 @@
<html>
<head>
- <title>NetIDMgr Concepts: Identity</title>
+ <title>Network Identity Manager Concepts: Identity</title>
<meta name="description" content="NetIDMgr Concepts: Identity">
<meta name="keywords" content="identity,concepts">
<link rel="stylesheet" type="text/css" href="nidmgr.css">
</head>
<body>
-<h1>NetIDMgr Concepts: Identity</h1>
+<h1>Network Identity Manager Concepts: Identity</h1>
<p>While there are many approaches to defining what an identity is, as
-far as the NetIDMgr framework is considered, an identity is the unique
-security principal that is identified by a service. Each credential
-that is managed by NetIDMgr is assumed to map to a unique identity.
+far as the Network Identity Manager (NetIDMgr) is considered, an identity is the unique
+user identifier that is accepted by a network service. Each credential
+that is managed by NetIDMgr is assumed to map to a single identity.
The collection of credentials that map to a single identity is
considered to belong to that identity.
</p>
@@ -23,16 +23,11 @@ considered to belong to that identity.
<a name="default_identity" />
<h3>Default Identity</h3>
-<p>The default identity is the identity that will be picked up by
-other applications as being the default. For example, an application
-that uses Kerberos 5 can use the credentials found in the default
-Kerberos 5 credentials cache. Therefore, the Kerberos 5 plug-in
-considers the principal that corresponds to the default credentials
-cache as being the default identity.
+<p>The default identity is the identity that will be used by
+applications when a specific identity has not been requested.
+The Kerberos v5 plug-in will mark the credential cache that
+contains the default identity as the default credentials
+cache for the current logon session.
</p>
-
-<p>
-</p>
-
</body>
</html> \ No newline at end of file
diff --git a/src/windows/identity/help/html/concepts.htm b/src/windows/identity/help/html/concepts.htm
index 0031872..2ce38e9 100644
--- a/src/windows/identity/help/html/concepts.htm
+++ b/src/windows/identity/help/html/concepts.htm
@@ -1,32 +1,31 @@
<html>
<head>
- <title>NetIDMgr Concepts</title>
+ <title>Network Identity Manager Concepts</title>
<meta name="description" content="NetIDMgr Concepts">
<meta name="keywords" content="concepts">
<link rel="stylesheet" type="text/css" href="nidmgr.css">
</head>
<body>
-<h1>NetIDMgr Concepts</h1>
+<h1>Network Identity Manager Concepts</h1>
-<p>The Network Identity manager organizes and manages your credentials
-based on how they identify you to external services which use those
-credentials for authentication. To this end, it is assumed that each
-credential will uniquely identify the user to a service as a single
-principal or <a href="concept_identity.htm">identity</a>. For
-Kerberos, the identity is conceptually the same as the principal.
+<p>The Network Identity Manager (NetIDMgr) organizes and manages credentials
+based on how they identify the user to network services. To this end, it is assumed that each
+<a href="concept_credential.htm">credential </a>will uniquely identify the user to a service as a single
+<a href="concept_identity.htm">identity</a>. When using Kerberos v5 the
+identity is the Kerberos principal name.
</p>
-<p>At it's core, NetIDMgr does not possess any knowlege about specific
-credentials that might be available for the user or how to manage
-them. It relies on several types of plugins to provide the
+<p>At it's core, NetIDMgr does not possess any knowledge about specific
+credentials that might be available to the user or how to manage
+them. It relies on several types of plug-ins to provide the
information it needs, and to carry out credentials management tasks.
One primary task is to identify and manage identities. These services
-are provided by a plugin called the <a
+are provided by a plug-in called the <a
href="concept_ident_pro.htm">identity provider</a>. Information about
individual credentials are provided by <a
-href="concept_cred_pro.htm">credentials providers</a>. Other plugins
-may extend the functionaility of these plugins or provide additional
+href="concept_cred_pro.htm">credential providers</a>. Other plug-ins
+may extend the functionality of these plug-ins or provide additional
functionality for NetIDMgr.
</p>
@@ -41,7 +40,9 @@ functionality for NetIDMgr.
<li><a href="concept_ident_pro.htm">Identity Provider</a></li>
<li><a href="concept_cred_pro.htm">Credentials Provider</a></li>
+
+ <li><a href="concept_credential.htm">Credential</a></li>
</ul>
</body>
-</html>
+</html> \ No newline at end of file
diff --git a/src/windows/identity/help/html/copyright.htm b/src/windows/identity/help/html/copyright.htm
index b98a156..b62753d 100644
--- a/src/windows/identity/help/html/copyright.htm
+++ b/src/windows/identity/help/html/copyright.htm
@@ -1,13 +1,13 @@
<html>
<head>
- <title>License</title>
+ <title>Network Identity Manager - License</title>
<meta name="description" content="License agreement">
<meta name="keywords" content="license">
<link rel="stylesheet" type="text/css" href="nidmgr.css">
</head>
<body>
-<h1>Network Identity Manager License</h1>
+<h1>Network Identity Manager - License</h1>
<p>This software is being provided to you, the LICENSEE, by the
Massachusetts Institute of Technology (M.I.T) under the following
@@ -23,7 +23,7 @@ the same appear on ALL copies of the software and documentation,
including modifications that you make for internal use or for
distribution:</p>
-<p>Copyright 1992-2006 by the Massachusetts Institute of Technology. All
+<p>Copyright 1992-2007 by the Massachusetts Institute of Technology. All
rights reserved.</p>
<p>THIS SOFTWARE IS PROVIDED "AS IS", AND M.I.T. MAKES NO REPRESENTATIONS
diff --git a/src/windows/identity/help/html/howdoi.htm b/src/windows/identity/help/html/howdoi.htm
index 7a380c8..9826ac2 100644
--- a/src/windows/identity/help/html/howdoi.htm
+++ b/src/windows/identity/help/html/howdoi.htm
@@ -1,18 +1,18 @@
<html>
<head>
- <title>How do I ...</title>
+ <title>Network Identity Manager - How do I ...</title>
<meta name="description" content="How do I ...">
<meta name="keywords" content="howto, how do I">
<link rel="stylesheet" type="text/css" href="nidmgr.css">
</head>
<body>
-<h1>How do I ...</h1>
+<h1>Network Identity Manager - How do I ...</h1>
<h3>Startup</h3>
<ul>
- <li><a href="use_start.htm">Start NetIDMgr or open the NetIDMgr
+ <li><a href="use_start.htm">Start or Open the Network Identity Manager
window</a></li>
</ul>
diff --git a/src/windows/identity/help/html/images/appicon_empty.bmp b/src/windows/identity/help/html/images/appicon_empty.bmp
deleted file mode 100644
index 6938c8e..0000000
--- a/src/windows/identity/help/html/images/appicon_empty.bmp
+++ /dev/null
Binary files differ
diff --git a/src/windows/identity/help/html/images/appicon_empty.png b/src/windows/identity/help/html/images/appicon_empty.png
new file mode 100644
index 0000000..1f50907
--- /dev/null
+++ b/src/windows/identity/help/html/images/appicon_empty.png
Binary files differ
diff --git a/src/windows/identity/help/html/images/appicon_expired.bmp b/src/windows/identity/help/html/images/appicon_expired.bmp
deleted file mode 100644
index d617465..0000000
--- a/src/windows/identity/help/html/images/appicon_expired.bmp
+++ /dev/null
Binary files differ
diff --git a/src/windows/identity/help/html/images/appicon_expired.png b/src/windows/identity/help/html/images/appicon_expired.png
new file mode 100644
index 0000000..3aa90d6
--- /dev/null
+++ b/src/windows/identity/help/html/images/appicon_expired.png
Binary files differ
diff --git a/src/windows/identity/help/html/images/appicon_good.bmp b/src/windows/identity/help/html/images/appicon_good.bmp
deleted file mode 100644
index b8bc9d3..0000000
--- a/src/windows/identity/help/html/images/appicon_good.bmp
+++ /dev/null
Binary files differ
diff --git a/src/windows/identity/help/html/images/appicon_good.png b/src/windows/identity/help/html/images/appicon_good.png
new file mode 100644
index 0000000..d8789da
--- /dev/null
+++ b/src/windows/identity/help/html/images/appicon_good.png
Binary files differ
diff --git a/src/windows/identity/help/html/images/appicon_warnexp.bmp b/src/windows/identity/help/html/images/appicon_warnexp.bmp
deleted file mode 100644
index 339c25d..0000000
--- a/src/windows/identity/help/html/images/appicon_warnexp.bmp
+++ /dev/null
Binary files differ
diff --git a/src/windows/identity/help/html/images/appicon_warnexp.png b/src/windows/identity/help/html/images/appicon_warnexp.png
new file mode 100644
index 0000000..becdf9e
--- /dev/null
+++ b/src/windows/identity/help/html/images/appicon_warnexp.png
Binary files differ
diff --git a/src/windows/identity/help/html/images/appicon_warning.bmp b/src/windows/identity/help/html/images/appicon_warning.bmp
deleted file mode 100644
index 53df9ec..0000000
--- a/src/windows/identity/help/html/images/appicon_warning.bmp
+++ /dev/null
Binary files differ
diff --git a/src/windows/identity/help/html/images/appicon_warning.png b/src/windows/identity/help/html/images/appicon_warning.png
new file mode 100644
index 0000000..e72901a
--- /dev/null
+++ b/src/windows/identity/help/html/images/appicon_warning.png
Binary files differ
diff --git a/src/windows/identity/help/html/images/notification_icon_menu.png b/src/windows/identity/help/html/images/notification_icon_menu.png
new file mode 100644
index 0000000..ab75b74
--- /dev/null
+++ b/src/windows/identity/help/html/images/notification_icon_menu.png
Binary files differ
diff --git a/src/windows/identity/help/html/images/screen_app_icon.bmp b/src/windows/identity/help/html/images/screen_app_icon.bmp
deleted file mode 100644
index 49e2fb0..0000000
--- a/src/windows/identity/help/html/images/screen_app_icon.bmp
+++ /dev/null
Binary files differ
diff --git a/src/windows/identity/help/html/images/screen_app_icon.png b/src/windows/identity/help/html/images/screen_app_icon.png
new file mode 100644
index 0000000..86bd210
--- /dev/null
+++ b/src/windows/identity/help/html/images/screen_app_icon.png
Binary files differ
diff --git a/src/windows/identity/help/html/images/screen_chng_pwd.png b/src/windows/identity/help/html/images/screen_chng_pwd.png
new file mode 100644
index 0000000..0f3704e
--- /dev/null
+++ b/src/windows/identity/help/html/images/screen_chng_pwd.png
Binary files differ
diff --git a/src/windows/identity/help/html/images/screen_config_appearance.png b/src/windows/identity/help/html/images/screen_config_appearance.png
new file mode 100644
index 0000000..e2ed861
--- /dev/null
+++ b/src/windows/identity/help/html/images/screen_config_appearance.png
Binary files differ
diff --git a/src/windows/identity/help/html/images/screen_config_cred_provider.png b/src/windows/identity/help/html/images/screen_config_cred_provider.png
new file mode 100644
index 0000000..5c72a06
--- /dev/null
+++ b/src/windows/identity/help/html/images/screen_config_cred_provider.png
Binary files differ
diff --git a/src/windows/identity/help/html/images/screen_config_general.bmp b/src/windows/identity/help/html/images/screen_config_general.bmp
deleted file mode 100644
index 6c6e57e..0000000
--- a/src/windows/identity/help/html/images/screen_config_general.bmp
+++ /dev/null
Binary files differ
diff --git a/src/windows/identity/help/html/images/screen_config_general.png b/src/windows/identity/help/html/images/screen_config_general.png
new file mode 100644
index 0000000..ce7e528
--- /dev/null
+++ b/src/windows/identity/help/html/images/screen_config_general.png
Binary files differ
diff --git a/src/windows/identity/help/html/images/screen_config_global_krb4.png b/src/windows/identity/help/html/images/screen_config_global_krb4.png
new file mode 100644
index 0000000..90a5664
--- /dev/null
+++ b/src/windows/identity/help/html/images/screen_config_global_krb4.png
Binary files differ
diff --git a/src/windows/identity/help/html/images/screen_config_global_krb5.png b/src/windows/identity/help/html/images/screen_config_global_krb5.png
new file mode 100644
index 0000000..d0e28d9
--- /dev/null
+++ b/src/windows/identity/help/html/images/screen_config_global_krb5.png
Binary files differ
diff --git a/src/windows/identity/help/html/images/screen_config_ident.bmp b/src/windows/identity/help/html/images/screen_config_ident.bmp
deleted file mode 100644
index 2ac15fe..0000000
--- a/src/windows/identity/help/html/images/screen_config_ident.bmp
+++ /dev/null
Binary files differ
diff --git a/src/windows/identity/help/html/images/screen_config_ident.png b/src/windows/identity/help/html/images/screen_config_ident.png
new file mode 100644
index 0000000..ac6278a
--- /dev/null
+++ b/src/windows/identity/help/html/images/screen_config_ident.png
Binary files differ
diff --git a/src/windows/identity/help/html/images/screen_config_ident_krb4.png b/src/windows/identity/help/html/images/screen_config_ident_krb4.png
new file mode 100644
index 0000000..5c4c6f4
--- /dev/null
+++ b/src/windows/identity/help/html/images/screen_config_ident_krb4.png
Binary files differ
diff --git a/src/windows/identity/help/html/images/screen_config_ident_krb5.png b/src/windows/identity/help/html/images/screen_config_ident_krb5.png
new file mode 100644
index 0000000..484b94d
--- /dev/null
+++ b/src/windows/identity/help/html/images/screen_config_ident_krb5.png
Binary files differ
diff --git a/src/windows/identity/help/html/images/screen_config_ident_provider.png b/src/windows/identity/help/html/images/screen_config_ident_provider.png
new file mode 100644
index 0000000..2ab9c4d
--- /dev/null
+++ b/src/windows/identity/help/html/images/screen_config_ident_provider.png
Binary files differ
diff --git a/src/windows/identity/help/html/images/screen_config_idents.bmp b/src/windows/identity/help/html/images/screen_config_idents.bmp
deleted file mode 100644
index 8f55a05..0000000
--- a/src/windows/identity/help/html/images/screen_config_idents.bmp
+++ /dev/null
Binary files differ
diff --git a/src/windows/identity/help/html/images/screen_config_idents.png b/src/windows/identity/help/html/images/screen_config_idents.png
new file mode 100644
index 0000000..a67fd17
--- /dev/null
+++ b/src/windows/identity/help/html/images/screen_config_idents.png
Binary files differ
diff --git a/src/windows/identity/help/html/images/screen_config_notifications.png b/src/windows/identity/help/html/images/screen_config_notifications.png
new file mode 100644
index 0000000..e8069ba
--- /dev/null
+++ b/src/windows/identity/help/html/images/screen_config_notifications.png
Binary files differ
diff --git a/src/windows/identity/help/html/images/screen_config_plug_in_krb4.png b/src/windows/identity/help/html/images/screen_config_plug_in_krb4.png
new file mode 100644
index 0000000..f763a9a
--- /dev/null
+++ b/src/windows/identity/help/html/images/screen_config_plug_in_krb4.png
Binary files differ
diff --git a/src/windows/identity/help/html/images/screen_config_plug_in_krb5.png b/src/windows/identity/help/html/images/screen_config_plug_in_krb5.png
new file mode 100644
index 0000000..e3e651a
--- /dev/null
+++ b/src/windows/identity/help/html/images/screen_config_plug_in_krb5.png
Binary files differ
diff --git a/src/windows/identity/help/html/images/screen_config_plug_in_krb5_ccache.png b/src/windows/identity/help/html/images/screen_config_plug_in_krb5_ccache.png
new file mode 100644
index 0000000..206386b
--- /dev/null
+++ b/src/windows/identity/help/html/images/screen_config_plug_in_krb5_ccache.png
Binary files differ
diff --git a/src/windows/identity/help/html/images/screen_config_plug_in_krb5_realm.png b/src/windows/identity/help/html/images/screen_config_plug_in_krb5_realm.png
new file mode 100644
index 0000000..e016aa1
--- /dev/null
+++ b/src/windows/identity/help/html/images/screen_config_plug_in_krb5_realm.png
Binary files differ
diff --git a/src/windows/identity/help/html/images/screen_config_plug_ins.png b/src/windows/identity/help/html/images/screen_config_plug_ins.png
new file mode 100644
index 0000000..ec9c749
--- /dev/null
+++ b/src/windows/identity/help/html/images/screen_config_plug_ins.png
Binary files differ
diff --git a/src/windows/identity/help/html/images/screen_main_wnd.bmp b/src/windows/identity/help/html/images/screen_main_wnd.bmp
deleted file mode 100644
index 0763318..0000000
--- a/src/windows/identity/help/html/images/screen_main_wnd.bmp
+++ /dev/null
Binary files differ
diff --git a/src/windows/identity/help/html/images/screen_main_wnd.png b/src/windows/identity/help/html/images/screen_main_wnd.png
new file mode 100644
index 0000000..b520c85
--- /dev/null
+++ b/src/windows/identity/help/html/images/screen_main_wnd.png
Binary files differ
diff --git a/src/windows/identity/help/html/images/screen_main_wnd_basic.png b/src/windows/identity/help/html/images/screen_main_wnd_basic.png
new file mode 100644
index 0000000..488fff3
--- /dev/null
+++ b/src/windows/identity/help/html/images/screen_main_wnd_basic.png
Binary files differ
diff --git a/src/windows/identity/help/html/images/screen_menu_bar.bmp b/src/windows/identity/help/html/images/screen_menu_bar.bmp
deleted file mode 100644
index 5f80c19..0000000
--- a/src/windows/identity/help/html/images/screen_menu_bar.bmp
+++ /dev/null
Binary files differ
diff --git a/src/windows/identity/help/html/images/screen_menu_bar.png b/src/windows/identity/help/html/images/screen_menu_bar.png
new file mode 100644
index 0000000..00b775b
--- /dev/null
+++ b/src/windows/identity/help/html/images/screen_menu_bar.png
Binary files differ
diff --git a/src/windows/identity/help/html/images/screen_menu_credential.bmp b/src/windows/identity/help/html/images/screen_menu_credential.bmp
deleted file mode 100644
index 92a1ec3..0000000
--- a/src/windows/identity/help/html/images/screen_menu_credential.bmp
+++ /dev/null
Binary files differ
diff --git a/src/windows/identity/help/html/images/screen_menu_credential.png b/src/windows/identity/help/html/images/screen_menu_credential.png
new file mode 100644
index 0000000..588117c
--- /dev/null
+++ b/src/windows/identity/help/html/images/screen_menu_credential.png
Binary files differ
diff --git a/src/windows/identity/help/html/images/screen_menu_file.bmp b/src/windows/identity/help/html/images/screen_menu_file.bmp
deleted file mode 100644
index 4a90546..0000000
--- a/src/windows/identity/help/html/images/screen_menu_file.bmp
+++ /dev/null
Binary files differ
diff --git a/src/windows/identity/help/html/images/screen_menu_file.png b/src/windows/identity/help/html/images/screen_menu_file.png
new file mode 100644
index 0000000..5836662
--- /dev/null
+++ b/src/windows/identity/help/html/images/screen_menu_file.png
Binary files differ
diff --git a/src/windows/identity/help/html/images/screen_menu_help.bmp b/src/windows/identity/help/html/images/screen_menu_help.bmp
deleted file mode 100644
index dc1a8f6..0000000
--- a/src/windows/identity/help/html/images/screen_menu_help.bmp
+++ /dev/null
Binary files differ
diff --git a/src/windows/identity/help/html/images/screen_menu_help.png b/src/windows/identity/help/html/images/screen_menu_help.png
new file mode 100644
index 0000000..d39b257
--- /dev/null
+++ b/src/windows/identity/help/html/images/screen_menu_help.png
Binary files differ
diff --git a/src/windows/identity/help/html/images/screen_menu_options.bmp b/src/windows/identity/help/html/images/screen_menu_options.bmp
deleted file mode 100644
index 5762e65..0000000
--- a/src/windows/identity/help/html/images/screen_menu_options.bmp
+++ /dev/null
Binary files differ
diff --git a/src/windows/identity/help/html/images/screen_menu_options.png b/src/windows/identity/help/html/images/screen_menu_options.png
new file mode 100644
index 0000000..528e01e
--- /dev/null
+++ b/src/windows/identity/help/html/images/screen_menu_options.png
Binary files differ
diff --git a/src/windows/identity/help/html/images/screen_menu_view.bmp b/src/windows/identity/help/html/images/screen_menu_view.bmp
deleted file mode 100644
index e47e54a..0000000
--- a/src/windows/identity/help/html/images/screen_menu_view.bmp
+++ /dev/null
Binary files differ
diff --git a/src/windows/identity/help/html/images/screen_menu_view.png b/src/windows/identity/help/html/images/screen_menu_view.png
new file mode 100644
index 0000000..f977bda
--- /dev/null
+++ b/src/windows/identity/help/html/images/screen_menu_view.png
Binary files differ
diff --git a/src/windows/identity/help/html/images/screen_menu_view_cols.bmp b/src/windows/identity/help/html/images/screen_menu_view_cols.bmp
deleted file mode 100644
index 25779bf..0000000
--- a/src/windows/identity/help/html/images/screen_menu_view_cols.bmp
+++ /dev/null
Binary files differ
diff --git a/src/windows/identity/help/html/images/screen_menu_view_cols.png b/src/windows/identity/help/html/images/screen_menu_view_cols.png
new file mode 100644
index 0000000..79954d2
--- /dev/null
+++ b/src/windows/identity/help/html/images/screen_menu_view_cols.png
Binary files differ
diff --git a/src/windows/identity/help/html/images/screen_new_creds.bmp b/src/windows/identity/help/html/images/screen_new_creds.bmp
deleted file mode 100755
index bf5be31..0000000
--- a/src/windows/identity/help/html/images/screen_new_creds.bmp
+++ /dev/null
Binary files differ
diff --git a/src/windows/identity/help/html/images/screen_new_creds.png b/src/windows/identity/help/html/images/screen_new_creds.png
new file mode 100644
index 0000000..eb461bf
--- /dev/null
+++ b/src/windows/identity/help/html/images/screen_new_creds.png
Binary files differ
diff --git a/src/windows/identity/help/html/images/screen_new_creds_err01.bmp b/src/windows/identity/help/html/images/screen_new_creds_err01.bmp
deleted file mode 100755
index 44bf0f9..0000000
--- a/src/windows/identity/help/html/images/screen_new_creds_err01.bmp
+++ /dev/null
Binary files differ
diff --git a/src/windows/identity/help/html/images/screen_new_creds_err01.png b/src/windows/identity/help/html/images/screen_new_creds_err01.png
new file mode 100644
index 0000000..4999db8
--- /dev/null
+++ b/src/windows/identity/help/html/images/screen_new_creds_err01.png
Binary files differ
diff --git a/src/windows/identity/help/html/images/screen_new_creds_exp.bmp b/src/windows/identity/help/html/images/screen_new_creds_exp.bmp
deleted file mode 100755
index 5caa632..0000000
--- a/src/windows/identity/help/html/images/screen_new_creds_exp.bmp
+++ /dev/null
Binary files differ
diff --git a/src/windows/identity/help/html/images/screen_new_creds_exp.png b/src/windows/identity/help/html/images/screen_new_creds_exp.png
new file mode 100644
index 0000000..f533c97
--- /dev/null
+++ b/src/windows/identity/help/html/images/screen_new_creds_exp.png
Binary files differ
diff --git a/src/windows/identity/help/html/images/screen_tb_standard.bmp b/src/windows/identity/help/html/images/screen_tb_standard.bmp
deleted file mode 100644
index bd07cf2..0000000
--- a/src/windows/identity/help/html/images/screen_tb_standard.bmp
+++ /dev/null
Binary files differ
diff --git a/src/windows/identity/help/html/images/screen_tb_standard.png b/src/windows/identity/help/html/images/screen_tb_standard.png
new file mode 100644
index 0000000..5d2f070
--- /dev/null
+++ b/src/windows/identity/help/html/images/screen_tb_standard.png
Binary files differ
diff --git a/src/windows/identity/help/html/images/screen_tray_icon.bmp b/src/windows/identity/help/html/images/screen_tray_icon.bmp
deleted file mode 100644
index b2fb1ee..0000000
--- a/src/windows/identity/help/html/images/screen_tray_icon.bmp
+++ /dev/null
Binary files differ
diff --git a/src/windows/identity/help/html/images/screen_tray_icon.png b/src/windows/identity/help/html/images/screen_tray_icon.png
new file mode 100644
index 0000000..6d935d6
--- /dev/null
+++ b/src/windows/identity/help/html/images/screen_tray_icon.png
Binary files differ
diff --git a/src/windows/identity/help/html/menu_all.htm b/src/windows/identity/help/html/menu_all.htm
index 2710d59..6cd8113 100644
--- a/src/windows/identity/help/html/menu_all.htm
+++ b/src/windows/identity/help/html/menu_all.htm
@@ -1,12 +1,12 @@
<html>
<head>
- <title>The Menu Bar</title>
+ <title>Network Identity Manager - The Menu Bar</title>
<meta name="description" content="The Menu Bar">
<meta name="keywords" content="menu bar">
<link rel="stylesheet" type="text/css" href="nidmgr.css">
</head>
<body>
-<h1>The Menu Bar</h1>
+<h1>Network Identity Manager - The Menu Bar</h1>
<p>
Click an item on the menu to go to the description of the submenu, or
@@ -26,7 +26,7 @@ highlighted character on the submenu.
</map>
<p>
-<img src="images/screen_menu_bar.bmp" usemap="#menu_bar_map"/>
+<img src="images/screen_menu_bar.png" usemap="#menu_bar_map"/>
</p>
<ul>
diff --git a/src/windows/identity/help/html/menu_credential.htm b/src/windows/identity/help/html/menu_credential.htm
index 8c537ea..f343128 100644
--- a/src/windows/identity/help/html/menu_credential.htm
+++ b/src/windows/identity/help/html/menu_credential.htm
@@ -1,19 +1,19 @@
<html>
<head>
- <title>Credential Menu</title>
+ <title>Network Identity Manager - Credential Menu</title>
<meta name="description" content="credential menu">
<meta name="keywords" content="credential menu">
<link rel="stylesheet" type="text/css" href="nidmgr.css">
</head>
<body>
-<h1>Credential Menu</h1>
+<h1>Network Identity Manager - Credential Menu</h1>
<p>
Click an item on the menu to go to the description of the action, or
choose from the list below. You can activate the by pressing <span
class="pre">Alt + C</span> and you can activate each action by
-pressing the highlited character.
+pressing the highlighted character.
</p>
<p>
@@ -22,21 +22,21 @@ right of the action. You can use the hot key to trigger the action
without invoking the <span class="pre">Credential</span> menu.
</p>
-<map id="menumap">
-<area shape = "rect" coords = "18,21,248,46" href = "#new">
-<area shape = "rect" coords = "18,52,244,77" href = "#renew">
-<area shape = "rect" coords = "19,76,241,98" href = "#import">
-<area shape = "rect" coords = "19,98,231,121" href = "#destroy">
-<area shape = "rect" coords = "20,129,160,155" href = "#def">
-<area shape = "rect" coords = "21,164,225,185" href = "#chpw">
-</map>
-
<p>
-<img src="images/screen_menu_credential.bmp" usemap="#menumap"/>
+<map name="FPMap0">
+<area href="#new" shape="rect" coords="29, 18, 220, 44">
+<area href="#renew" shape="rect" coords="29, 42, 219, 67">
+<area href="#renew" shape="rect" coords="213, 44, 464, 113">
+<area href="#destroy" shape="rect" coords="29, 65, 220, 83">
+<area href="#import" shape="rect" coords="29, 81, 217, 104">
+<area href="#chpw" shape="rect" coords="28, 131, 218, 156">
+<area href="#def" shape="rect" coords="28, 102, 216, 133">
+</map>
+<img src="images/screen_menu_credential.png" usemap="#FPMap0"/>
</p>
<ul>
- <li><a name="new" /> <span class="title">New Credentials ...</span>:
+ <li><a name="new"></a> <span class="title">New Credentials ...</span>:
Opens the new credentials acquisition dialog box. If an identity
was selected, then that identity would be made the default for the
new credentials acquisition. However, it can easily be changed in
@@ -46,17 +46,17 @@ without invoking the <span class="pre">Credential</span> menu.
Action</a></span> for more information.
</p></li>
- <li><a name="renew"/> <span class="title">Renew credentials</span>:
+ <li><a name="renew"></a> <span class="title">Renew credentials</span>:
Renews the selected credentials or identity. This action requires
that the selected credentials be renewable.
<p>
See <span class="pre"><a href="act_renew_creds.htm">Renew
Credentials Action</a></span> for more information.</p></li>
- <li><a name="destroy"/> <span class="title">Destroy
+ <li><a name="destroy"></a> <span class="title">Destroy
credentials...</span>: Destroys the selected credentials.</li>
- <li><a name="def"/> <span class="title">Set as default</span>: Sets
+ <li><a name="def"></a> <span class="title">Set as default</span>: Sets
the selected identity as the default, if it is not already the
default. The implications of this operation is dependent on the
current <a href="concept_ident_pro.htm">identity provider</a>.
@@ -64,17 +64,16 @@ without invoking the <span class="pre">Credential</span> menu.
See <span class="pre"><a href="act_set_default.htm">Set As Default
Action</a></span> for more information.</p></li>
- <li><a name="chpw" /> <span class="title">Change password...</span>:
+ <li><a name="chpw"></a> <span class="title">Change password...</span>:
Changes the password for the selected identity. However, once the
new password dialog opens, you can change the identity for which the
password is getting changed.</li>
- <li><a name="import" /> <span class="title">Import
+ <li><a name="import"></a> <span class="title">Import
Credentials</span>: Import any existing credentials from external
- sources. With the Kerberos 5 <a
- href="concept_cred_pro.htm">credentials provider</a>, the Kerberos
- tickets from the Microsoft Windows LSA cache will be imported to MIT
- Kerberos ticket caches.</li>
+ sources. With the Kerberos v5 <a
+ href="concept_cred_pro.htm">credentials provider</a>, the Windows logon
+ identity stored in the Microsoft Windows LSA cache will be imported.</li>
</ul>
diff --git a/src/windows/identity/help/html/menu_file.htm b/src/windows/identity/help/html/menu_file.htm
index a7f79fe..2f734af 100644
--- a/src/windows/identity/help/html/menu_file.htm
+++ b/src/windows/identity/help/html/menu_file.htm
@@ -1,13 +1,13 @@
<html>
<head>
- <title>File Menu</title>
+ <title>Network Identity Manager - File Menu</title>
<meta name="description" content="File menu">
<meta name="keywords" content="file menu">
<link rel="stylesheet" type="text/css" href="nidmgr.css">
</head>
<body>
-<h1>File Menu</h1>
+<h1>Network Identity File Menu</h1>
<p>
Click an item on the menu to go to the description of the action, or
@@ -22,22 +22,21 @@ right of the action. You can use the hot key to trigger the action
without invoking the <span class="pre">File</span> menu.
</p>
-<map id="menumap">
-<area shape = "rect" coords = "12,24,115,46" href = "#properties">
-<area shape = "rect" coords = "12,55,166,76" href = "#exit">
-</map>
-
<p>
-<img src="images/screen_menu_file.bmp" usemap="#menumap"/>
+<map name="FPMap0">
+<area href="#properties" shape="rect" coords="1, 21, 131, 42">
+<area href="#exit" shape="rect" coords="1, 40, 129, 65">
+</map>
+<img src="images/screen_menu_file.png" usemap="#FPMap0"/>
</p>
<ul>
- <li><a name="properties"/>
+ <li><a name="properties"></a>
<span class="title">Properties...</span>: Displays a property
sheet for the selected credential, identity or credential type.</li>
- <li><a name="exit" />
+ <li><a name="exit"></a>
<span class="title">Exit</span>: Exits Network Identity Manager</li>
</ul>
diff --git a/src/windows/identity/help/html/menu_help.htm b/src/windows/identity/help/html/menu_help.htm
index d1ac6ae..7cd368e 100644
--- a/src/windows/identity/help/html/menu_help.htm
+++ b/src/windows/identity/help/html/menu_help.htm
@@ -1,13 +1,13 @@
<html>
<head>
- <title>Help Menu</title>
+ <title>Network Identity Manager - Help Menu</title>
<meta name="description" content="Help Menu">
<meta name="keywords" content="help menu">
<link rel="stylesheet" type="text/css" href="nidmgr.css">
</head>
<body>
-<h1>Help Menu</h1>
+<h1>Network Identity Manager - Help Menu</h1>
<p>
You can activate the menu by pressing <span class="pre">Alt + H</span>
@@ -21,32 +21,30 @@ the question mark icon in the title bar and then clicking on the
dialog box control that you want help with.
</p>
-<map id="menumap">
-
-<area shape = "rect" coords = "12,27,166,48" href = "#ctx">
-<area shape = "rect" coords = "13,53,167,76" href = "#contents">
-<area shape = "rect" coords = "14,77,160,101" href = "#index">
-<area shape = "rect" coords = "15,107,173,132" href = "#about">
-
-</map>
<p>
-<img src="images/screen_menu_help.bmp" usemap="#menumap"/>
+<map name="FPMap0">
+<area href="#contents" shape="rect" coords="173, 22, 373, 43">
+<area href="#index" shape="rect" coords="173, 43, 373, 68">
+<area href="#about" shape="rect" coords="172, 103, 373, 128">
+<area href="#plug-in" shape="rect" coords="173, 67, 372, 102">
+</map>
+<img src="images/screen_menu_help.png" usemap="#FPMap0"/>
</p>
<ul>
- <li><a name="ctx" /><span class="title">Context</span>: Provides
- context sensitive help. You can invoke help at any time by pressing
- <span class="pre">F1</span></li>
+
- <li><a name="contents" /><span class="title">Contents</span>: Opens
+ <li><a name="contents"></a><span class="title">Contents</span>: Opens
the table of contents for the user documentation</li>
- <li><a name="index" /><span class="title">Index</span>: Opens the
+ <li><a name="index"></a><span class="title">Index</span>: Opens the
index for the user documentation</li>
-
- <li><a name="about" /><span class="title">About</span>: Opens a
+
+ <li><a name="plug-in"></a><span class="title">Plug-in specific help</span>:
+ Plug-ins can register their own on-line help.</li>
+ <li><a name="about"></a><span class="title">About</span>: Opens a
dialog box containing information about this version of NetIDMgr as
well as the modules that are currently loaded.</li>
diff --git a/src/windows/identity/help/html/menu_options.htm b/src/windows/identity/help/html/menu_options.htm
index 08aad4f..df10f2e 100644
--- a/src/windows/identity/help/html/menu_options.htm
+++ b/src/windows/identity/help/html/menu_options.htm
@@ -1,68 +1,60 @@
<html>
<head>
- <title>Options Menu</title>
+ <title>Network Identity Manager - Options Menu</title>
<meta name="description" content="options menu">
<meta name="keywords" content="options menu">
<link rel="stylesheet" type="text/css" href="nidmgr.css">
</head>
<body>
-<h1>Options Menu</h1>
+<h1>Network Identity Manager - Options Menu</h1>
<p>
Click an item on the menu to go to the description of the action, or
-choose from the list below. You can activate the by pressing <span
+choose from the list below. You can activate the menu by pressing <span
class="pre">Alt + O</span> and you can activate each action by
-pressing the highlited character.
+pressing the highlighted character.
</p>
-<p>
-Actions which have an associated hot key show this hot key to the
-right of the action. You can use the hot key to trigger the action
-without invoking the <span class="pre">Options</span> menu.
-</p>
-
-<map id="menumap">
-
-<area shape = "rect" coords = "12,24,139,48" href = "#general">
-<area shape = "rect" coords = "11,46,144,68" href = "#apperance">
-<area shape = "rect" coords = "11,68,142,89" href = "#identities">
-<area shape = "rect" coords = "12,91,139,111" href = "#notifications">
-<area shape = "rect" coords = "14,111,134,133" href = "#plugins">
-<area shape = "rect" coords = "12,141,139,208" href = "#pluginspec">
-
-</map>
<p>
-<img src="images/screen_menu_options.bmp" usemap="#menumap"/>
+<map name="FPMap0">
+<area href="#general" shape="rect" coords="124, 20, 239, 40">
+<area href="#appearance" shape="rect" coords="124, 38, 239, 56">
+<area href="#identities" shape="rect" coords="122, 54, 239, 73">
+<area href="#notifications" shape="rect" coords="123, 71, 239, 93">
+<area href="#plugins" shape="rect" coords="123, 91, 239, 112">
+<area href="#pluginspec" shape="rect" coords="124, 110, 239, 169">
+</map>
+<img src="images/screen_menu_options.png" usemap="#FPMap0"/>
</p>
<ul>
-<li><a name="general" /><span class="title">General ...</span>: Opens
+<li><a name="general"></a><span class="title">General ...</span>: Opens
the NetIDMgr general configuration panel. This panel allows you to
configure settings related to the startup/shutdown of NetIDMgr in
addition to debugging and monitoring options.</li>
-<li><a name="apperance" /><span class="title">Appearance ...</span>:
+<li><a name="appearance"></a><span class="title">Appearance ...</span>:
Provides options for customizing the appearance of the credentials
window. Currently, the only options provided are for selecting the
font used for the credentials list.</li>
-<li><a name="identities" /><span class="title">Identities ...</span>:
+<li><a name="identities"></a><span class="title">Identities ...</span>:
Opens the identities configuration panel. These options control
credentials defaults for all identities or for specific identities.</li>
-<li><a name="notifications" /><span class="title">Notifications
+<li><a name="notifications"></a><span class="title">Notifications
...</span>: The notifications configuration panel controls the
settings used by the NetIDMgr timer that triggers warnings and
identity renewals.</li>
-<li><a name="plugins" /><span class="title">Plugins ...</span>:
-Options for enabling or disabling specific plugins and also for
-viewing information about loaded plugins.</li>
+<li><a name="plugins"></a><span class="title">plug-ins ...</span>:
+Options for enabling or disabling specific plug-ins and also for
+viewing information about loaded plug-ins.</li>
-<li><a name="pluginspec" /><span class="title">Plugin specific
+<li><a name="pluginspec"></a><span class="title">Plugin specific
configuration panels</span>: Each registered plugin can register one
or more configuration panels which will appear on the <span
class="pre">Options</span> menu.</li>
diff --git a/src/windows/identity/help/html/menu_view.htm b/src/windows/identity/help/html/menu_view.htm
index 2401b3c..0080559 100644
--- a/src/windows/identity/help/html/menu_view.htm
+++ b/src/windows/identity/help/html/menu_view.htm
@@ -1,13 +1,13 @@
<html>
<head>
- <title>View Menu</title>
+ <title>Network Identity Manager - View Menu</title>
<meta name="description" content="View menu">
<meta name="keywords" content="view menu">
<link rel="stylesheet" type="text/css" href="nidmgr.css">
</head>
<body>
-<h1>View Menu</h1>
+<h1>Network Identity Manager - View Menu</h1>
<p>
Click an item on the menu to go to the description of the action, or
@@ -22,28 +22,38 @@ right of the action. You can use the hot key to trigger the action
without invoking the <span class="pre">View</span> menu.
</p>
-<map id="menumap">
-<area shape = "rect" coords = "11,24,159,45" href = "#choosecol">
-<area shape = "rect" coords = "11,47,160,70" href = "#layout">
-<area shape = "rect" coords = "11,74,159,100" href = "#refresh">
-</map>
-
<p>
-<img src="images/screen_menu_view.bmp" usemap="#menumap"/>
+<map name="menumap">
+<area href="#advanced" shape="rect" coords="91, 20, 230, 39">
+<area href="#choosecol" shape="rect" coords="89, 38, 230, 57">
+<area href="#layout" shape="rect" coords="89, 52, 229, 76">
+<area href="#layout" shape="rect" coords="225, 54, 319, 125">
+<area href="#refresh" shape="rect" coords="91, 77, 226, 101">
+</map>
+<img src="images/screen_menu_view.png" usemap="#menumap" />
</p>
<ul>
-<li><a name="choosecol" /> <span class="title">View columns</span>:
+<li><a name="advanced"></a> <span class="title">Advanced F7</span>:
+
+Toggles the display mode between <b>basic</b> and <b>advanced</b> modes.
+In basic mode, the Network Identity Manager displays a list of identities
+and their current status. In the advanced mode, NetIdMgr provides a
+customizable list of all discovered credentials.
+</li>
+
+<li><a name="choosecol"></a> <span class="title">View columns</span>:
+<i>Only available in Advanced mode.</i>
Invokes a submenu from which you can choose the columns that are
displayed in the credentials window. If you change the columns, or
their order, a new custom layout will be created for you which you can
later use using the <span class="pre">Layout</span> submenu later. For
-more information about managing layouts, see the <a
-href="use_layout.htm">Layout</a> topic.</li>
+more information about managing layouts, see the <a href="use_layout.htm">Layout</a> topic.</li>
-<li><a name="layout" /> <span class="title">Layout</span>: Opens a
+<li><a name="layout"></a> <span class="title">Layout</span>:
+<i>Only available in Advanced mode.</i> Opens a
submenu where you can select the layout for the credentials
display.
<ul>
@@ -73,8 +83,8 @@ display.
</li>
-<li><a name="refresh" /> <span class="title">Refresh</span>: Refresh
-the credentials view. This queries each <a
+<li><a name="refresh"></a> <span class="title">Refresh view F5</span>: Refresh
+the contents of the credentials view. This queries each <a
href="concept_cred_pro.htm">credential provider</a> for any
credentials and redraws the credentials view.</li>
diff --git a/src/windows/identity/help/html/tb_standard.htm b/src/windows/identity/help/html/tb_standard.htm
index 945063f..e0f041b 100644
--- a/src/windows/identity/help/html/tb_standard.htm
+++ b/src/windows/identity/help/html/tb_standard.htm
@@ -1,20 +1,32 @@
<html>
<head>
- <title>Standard Toolbar</title>
+ <title>Network Identity Manager - Standard Toolbar</title>
<meta name="description" content="Standard Toolbar">
<meta name="keywords" content="standard toolbar">
<link rel="stylesheet" type="text/css" href="nidmgr.css">
+ <Object type="application/x-oleobject" classid="clsid:1e2a7bd0-dab9-11d0-b93a-00c04fc99f9e">
+<param name="Keyword" value="Changing Passwords">
+<param name="Keyword" value="New Credentials">
+<param name="Keyword" value="Renew Credentials">
+<param name="Keyword" value="Import Credentials">
+<param name="Keyword" value="Destroy Credentials">
+<param name="Keyword" value="Change Password">
+<param name="Keyword" value="Refresh View">
+<param name="Keyword" value="Help">
+<param name="Keyword" value="Toolbar">
+</OBJECT>
+
</head>
<body>
-<h1>Standard Toolbar</h1>
+<h1>Network Identity Manager - Standard Toolbar</h1>
<p>The standard toolbar appears below along with descriptions of what
each button does.
</p>
<p>
-<img src="images/screen_tb_standard.bmp" />
+<img src="images/screen_tb_standard.png" />
</p>
<ol>
diff --git a/src/windows/identity/help/html/template.htm b/src/windows/identity/help/html/template.htm
index 5e39963..3357741 100644
--- a/src/windows/identity/help/html/template.htm
+++ b/src/windows/identity/help/html/template.htm
@@ -1,6 +1,6 @@
<html>
<head>
- <title>title</title>
+ <title>Network Identity Manager - title</title>
<meta name="description" content="">
<meta name="keywords" content="">
<link rel="stylesheet" type="text/css" href="nidmgr.css">
diff --git a/src/windows/identity/help/html/use_config.htm b/src/windows/identity/help/html/use_config.htm
index 6d4cbeb..9d71848 100644
--- a/src/windows/identity/help/html/use_config.htm
+++ b/src/windows/identity/help/html/use_config.htm
@@ -1,132 +1,306 @@
<html>
+
<head>
- <title>Configuring NetIDMgr and identities</title>
- <meta name="description" content="">
- <meta name="keywords" content="configuration">
- <link rel="stylesheet" type="text/css" href="nidmgr.css">
+<title>Network Identity Manager - Configuration</title>
+<meta name="description" content>
+<meta name="keywords" content="configuration">
+<link rel="stylesheet" type="text/css" href="nidmgr.css">
+<Object type="application/x-oleobject" classid="clsid:1e2a7bd0-dab9-11d0-b93a-00c04fc99f9e">
+<param name="Keyword" value="Configuration">
+<param name="Keyword" value="General Options">
+<param name="Keyword" value="Appearance Options">
+<param name="Keyword" value="Notification Options">
+<param name="Keyword" value="Plug-in Management">
+<param name="Keyword" value="Kerberos v5 Configuration">
+<param name="Keyword" value="Kerberos v4 Configuration">
+<param name="Keyword" value="Identity Default Configuration">
+<param name="Keyword" value="Identity Configuration">
+</OBJECT>
+<style>
+<!--
+ li.MsoNormal
+ {mso-style-parent:"";
+ margin-bottom:.0001pt;
+ text-autospace:none;
+ font-size:10.0pt;
+ font-family:"Times New Roman";
+ margin-left:0pt; margin-right:0pt; margin-top:0pt}
+-->
+</style>
</head>
-<body>
-<h1>Configuring NetIDMgr and identities</h1>
+<body>
-<p>All NetIDMgr configuration options can be accessed via the <span
-class="pre">Options</span> menu. The available configuration panels
-are:
+<h1>Network Identity Manager - Configuration</h1>
+<p>All Network Identity Manager configuration options can be accessed via the
+<span class="pre">Options</span> menu. The available configuration panels are:
</p>
-
-<p>
<ul>
- <li><p><span class="title">General</span>: General application options
- for NetIDMgr.</p>
-
- <ul>
-
- <li><p><span class="title">Obtain new credentials at
- startup</span>: If checked, NetIDMgr will check there are initial
- credentials for the default identity. If no such credentials are
- found, NetIDMgr will display a new credentials dialog.</p> </li>
-
- <li><p><span class="title">Run NetIDMgr in system tray after
- window close</span>: If checked, NetIDMgr will continue running in
- the system notification area (sometimes referred to as the system
- tray) after you close the NetIDMgr window.</p> </li>
-
- <li><p><span class="title">Monitor network connectivity</span>: When
- changes to network connectivity are detected, NetIDMgr can notify
- individual plug-ins about these changes. Doing so allows each
- plug-in to respond to the change by obtaining new credentials etc.
- If this option is cleared, no such notifications are sent and the
- application would not respond to network changes.</p></li>
-
- <li><p><span class="title">Log trace events</span>: NetIDMgr can
- generate debugging information during the course of performing
- certain actions. This information aids the developers in fixing
- problems that you may encounter while using NetIDMgr.</p> </li>
-
- </ul>
-
- </li>
-
- <li><p><span class="title">Appearance</span>: Allows you to set the
- font used by NetIDMgr.</p></li>
-
- <li><p><span class="title">Identities</span>: Default settings for all
- identities and settings for each identity. Details <a
- href="#cfg_idents">below</a>.</p></li>
-
- <li><p><span class="title">Notifications</span>: Notification and timer
- options. NetIDMgr can issue warnings when credentials are about to
- expire. This configuration panel allows you to set the thresholds at
- which these warnings are issued. For example, if the warning
- timeout is set for 10 minutes, NetIDMgr will issue a warning 10
- minutes before a credential expires.</p>
-
- <p>The panel also allows you to control the credentials renew timer.
- If the timer is disabled, NetIDMgr will not automatically attempt to
- renew credentials. If the <span class="pre">Renew at half life
- intervals when possible</span> option is set, then the timer will
- expire after the credential has less than half its lifetime left.
- If the renewal operation fails, it will attempt another renwal after
- half of the remaining liftime is over (i.e. when the credential has
- less than 1/4 of its original lifetime left) and so on.
- </p>
-
- </li>
-
- <li><p><span class="title">Plugins</span>: Enable/disable and check
- the status of registered plug-ins. Enabling or disabling a plug-in
- only takes effect after a restart of NetIDMgr.</p></li>
-
+ <li>
+ <p><span class="title">General</span>: General application options for NetIDMgr.</p>
+ </li>
+ <li>
+ <p><span class="title">Appearance</span>: Allows you to set the font used by
+ NetIDMgr.</p>
+ </li>
+ <li>
+ <p><span class="title">Identities</span>: Default settings for all identities
+ and settings for each identity. Details <a href="#cfg_idents">below</a>.</p>
+ </li>
+ <li>
+ <p><span class="title">Notifications</span>: Notification and timer options.
+ NetIDMgr can issue warnings when credentials are about to expire. This configuration
+ panel allows you to set the thresholds at which these warnings are issued. For
+ example, if the warning timeout is set for 10 minutes, NetIDMgr will issue a
+ warning 10 minutes before a credential expires.</p>
+ <p>The panel also allows you to control the credentials renew timer. If the
+ timer is disabled, NetIDMgr will not automatically attempt to renew credentials.
+ If the <span class="pre">Renew at half life intervals when possible</span> option
+ is set, then the timer will expire after the credential has less than half its
+ lifetime left. If the renewal operation fails, it will attempt another renwal
+ after half of the remaining liftime is over (i.e. when the credential has less
+ than 1/4 of its original lifetime left) and so on. </p>
+ </li>
+ <li>
+ <p><span class="title">Plugins</span>: Enable/disable and check the status of
+ registered plug-ins. Enabling or disabling a plug-in only takes effect after
+ a restart of NetIDMgr.</p>
+ </li>
+ <li>
+ <p><span class="title">Kerberos v5</span>: Kerberos v5 Credential Provider Configuration</p>
+ </li>
+ <li>
+ <p><span class="title">Kerberos v4</span>: Kerberos v4 Credential Provider Configuration</p>
+ </li>
</ul>
-</p>
+<p></p>
+<h3>General Options</h3>
+<p>The General options dialog, accessed via the Options menu, allows you to configure
+operational properties specific to the NetIdMgr application.</p>
+<p><img src="images/screen_config_general.png" /> </p>
+<p>The <b>Obtain new credentials at startup (if none are present)</b> checkbox will
+determine whether or not NetIdMgr will display the New Credentials dialog at startup
+when no valid credentials exist.</p>
+<p>The <b>Destroy all credentials on exit </b>option can be used to empty all of
+the credential caches when the NetIdMgr is terminated.</p>
+<p>The <b>Run NetIdMgr in taskbar notification area after window close </b>checkbox
+determines the behavior of the window close button. When checked, NetIdMgr will
+close the window but will continue running and can be accessed from the taskbar
+notification area. When unchecked, NetIdMgr will behave as if File-&gt;Exit was selected
+from the menu.</p>
+<p><b>Clicking on the notification icon</b> can be configured to either Show Network
+Identity Manager or Obtain New Credentials. This option controls which menu item
+on the notification icon menu is the default action.</p>
+<p>The <b>Monitor network connectivity</b> option determines whether or not NetIdMgr
+monitors the configuration of IP addresses on the machine. When IP addresses are
+added or removed and this feature is activated, the NetIdMgr will probe the identity
+management servers (e.g., Kerberos Key Distribution Centers) to determine if they
+are reachable and if so will automatically obtain credentials.</p>
+<p>The <b>Log trace events to trace log at the following location</b> option is
+used to activate a log file that can be used to help debug the behavior of NetIdMgr
+and its plug-ins. Press the <b>Show log</b> button to view the log file in Windows
+Notepad. </p>
-<p><img src="images/screen_config_general.bmp" />
-</p>
+<h3>Appearance Options</h3>
+<p>The Appearance Options page can be used to select an alternate typeface to be
+used when displaying credentials in the NetIdMgr.</p>
+<p><img src="images/screen_config_appearance.png" /> </p>
-<a name="cfg_idents" />
+
+<a name="cfg_idents"></a>
<h3>Configuration of default settings for all identities</h3>
+<p>The <span class="pre">Identities</span> configuration panel allows you to set
+the defaults that will be used for all identities. However, most of the settings
+displayed here can be overridden with specific per-identity settings. </p>
+<p>The panel will have a number of sub panels (or tabs) corresponding to each plug-in
+that maintains per-identity configuration. </p>
+<p>A list of identities for which configuration information is maintained will be
+shown under the main <span class="pre">Identities</span> configuration panel name.
+Each of these correspond to a <a href="#cfg_ident">per identity</a> configuration
+panel. </p>
+<p>Note that adding or removing an identity in the configuration panel only has
+the effect of adding or removing the identity to or from the list of identities
+for which configuration information is maintained. </p>
-<p>The <span class="pre">Identities</span> configuration panel allows
-you to set the defaults that will be used for all identities.
-However, most of the settings displayed here can be overridden with
-specific per-identity settings.
-</p>
+<h4>Global Identity Settings</h4>
+<p><img src="images/screen_config_idents.png" /> </p>
+<p class="MsoNormal">There are three general settings that can be used to set
+global defaults.</p>
+<p class="MsoNormal">The <b>Monitor credential expiration</b> setting determines
+whether or not NetIdMgr should monitor the credential lifetimes and issue
+expiration notifications.&nbsp;&nbsp; This value is used as the default for all new
+identities.</p>
+<p class="MsoNormal">The <b>Automatically renew</b> setting determines if <i>
+renewable</i> credentials are automatically renewed prior to expiration.&nbsp; This
+value is used as the default for all new identities.</p>
+<p class="MsoNormal">The <b>Always show in the credentials list (Pinned)</b>
+setting determines whether new identities are always pinned within the
+credentials list.&nbsp; A pinned identity will always be displayed regardless of
+whether or not there are credentials associated with it.</p>
-<p>The panel will have a number of sub panels (or tabs) corresponding
-to each plug-in that maintains per-identity configuration.
-</p>
+<h4>Global Kerberos v5 Identity Settings</h4>
+<p><img src="images/screen_config_global_krb5.png" /> </p>
+<p class="MsoNormal">The global Kerberos v5 settings define default credential
+lifetimes and minimum and maximum values for use in constructing the slider
+controls used to set the lifetimes.&nbsp; </p>
+<p class="MsoNormal">There are two expiration times associated with Kerberos
+tickets.&nbsp; The first specifies the length of the time period during which the
+tickets are valid for use.&nbsp; The second specifies the length of the renewable
+lifetime.&nbsp; Valid Kerberos tickets may have their valid use lifetime repeatedly
+extended up until the renewable lifetime expires.&nbsp; The settings on this page are
+used to configure default lifetime values for NetIdMgr to use when requesting
+Kerberos tickets from the Kerberos server (key distribution center).&nbsp; The
+Kerberos server may issue tickets with shorter lifetimes than were requested.</p>
+<p class="MsoNormal">The <b>Renewable</b>, <b>Forwardable</b>, and <b>
+Addressless</b> options determine whether or not new identities default to
+obtaining Kerberos v5 tickets with these options.</p>
+<p class="MsoNormal">When <b>Forwardable </b>tickets are received from the
+Kerberos Server, these tickets can be forwarded to a remote host when you
+connect via telnet, ssh, ftp, rlogin, or similar applications.&nbsp; When tickets are
+forwarded, there is no need to obtain Kerberos tickets again to access
+Kerberized services on the remote host.&nbsp;&nbsp; <b>Forwardable</b> tickets are often
+required when authenticating to a remote host using ssh or ftp when the remote
+host requires the ability to authenticate to a remote file system such as AFS.</p>
+<p class="MsoNormal">When <b>Renewable</b> tickets are received from the
+Kerberos Server, the ticket lifetimes may be renewed without prompting the user
+for her password.&nbsp; This allows Kerberos tickets to be issued with short
+lifetimes allowing compromised accounts to be disabled on short notice without
+requiring the user to enter a password every few hours.&nbsp; When combined with <b>
+Automatic Ticket Renewal</b>, NetIdMgr can maintain valid tickets for a week, a
+month, or longer by automatically renewing tickets prior to their expiration.&nbsp;
+The ability to renew tickets without a password is limited by the ticket’s
+renewable lifetime as issued by the Kerberos Server.</p>
+<p class="MsoNormal">When <b>Addressless</b> is selected, the tickets do not
+contain IP address information.&nbsp; This enables the tickets to be used from behind
+Network Address Translators which are frequently found in Cable and DSL Modems.</p>
+<p class="MsoNormal">The minimum and maximum ranges are used by the ticket
+initialization dialog box when constructing the Lifetime and Renewable Lifetime
+sliders.&nbsp; These sliders can be used to modify the requested ticket lifetimes
+when Kerberos tickets are initialized.</p>
-<p>A list of identities for which configuration information is
-maintained will be shown under the main <span
-class="pre">Identities</span> configuration panel name. Each of these
-correspond to a <a href="#cfg_ident">per identity</a> configuration
-panel.
-</p>
+<h4>Global Kerberos v4 Identity Settings</h4>
+<p><img src="images/screen_config_global_krb4.png" /> </p>
+<p class="MsoNormal">When the <b>Obtain Kerberos v4 credentials</b> button is
+checked, NetIdMgr will attempt to retrieve Kerberos v4 credentials when ticket
+initialization, renewal, or importation is performed. &nbsp;Kerberos realms are
+increasingly configured to support only Kerberos v5 (e.g., Windows Active
+Directory Domains.)&nbsp; If the realms you use do not support Kerberos v4 it is
+suggested that this button be unchecked.</p>
+<p class="MsoNormal">Be aware that only the default identity can obtain Kerberos
+v4 credentials.&nbsp;&nbsp; This limitation is due to the inability of Kerberos v4
+applications on Microsoft Windows to specify a credentials cache. </p>
-<p>Note that adding or removing an identity in the configuration panel
-only has the effect of adding or removing the identity to or from the
-list of identities for which configuration information is maintained.
-</p>
-
-<p><img src="images/screen_config_idents.bmp" />
-</p>
-<a name="cfg_ident" />
+<a name="cfg_ident"></a>
<h3>Per identity configuration</h3>
+<p>You can access the per-identity configuration panel for a specific identity by
+selecting the identity name from the list of configuration panels in the configuration
+dialog. </p>
+<p>These panels are similar to the <span class="pre">Identities</span> configuration
+panel, but they change per-identity settings. Changes you make in these panels will
+override the defaults set in the <span class="pre">Identities</span> panel. </p>
+<h4>Per identity General Configuration</h4>
+<p><img src="images/screen_config_ident.png" /> </p>
+<p class="MsoNormal">The General page contains a <b>Remove Identity</b> button
+that can be used to delete this Identity from the Network Identity Manager.</p>
-<p>You can access the per-identity configuration panel for a specific
-identity by selecting the identity name from the list of configuration
-panels in the configuration dialog.
-</p>
+<h4>Per identity Kerberos v5 Configuration</h4>
-<p>These panels are similar to the <span class="pre">Identities</span>
-configuration panel, but they change per-identity settings. Changes
-you make in these panels will override the defaults set in the <span
-class="pre">Identities</span> panel.
-</p>
+<p><img src="images/screen_config_ident_krb5.png" /> </p>
+<p class="MsoNormal">The Kerberos v5 page displays the name of the credential
+cache currently associated with the Identity.</p>
-<p><img src="images/screen_config_ident.bmp" />
-</p>
+<h4>Per identity Kerberos v4 Configuration</h4>
+
+<p><img src="images/screen_config_ident_krb4.png" /></p>
+<p class="MsoNormal">The Kerberos v4 page is optional and may not appear on all
+systems.&nbsp; Only one identity can obtain Kerberos v4 credentials at a time.&nbsp; </p>
+
+<h3>Notification Configuration</h3>
+
+<p><img src="images/screen_config_notifications.png" /> </p>
+<p class="MsoNormal">The <b>Renew automatically at</b> check box determines
+whether or not renewable tickets will be renewed by NetIdMgr when they reach the
+specified time remaining.&nbsp;&nbsp; </p>
+<p class="MsoNormal">The <b>Initial warning at</b> check box determines whether
+or not a warning will be issued when the specified time remaining is reached.</p>
+<p class="MsoNormal">The <b>Final warning at</b> check box determines whether or
+not a warning will be issued when the specified time remaining is reached.</p>
+<p class="MsoNormal">Notifications are performed in two ways.&nbsp; First, icons are
+displayed next to the affected credentials in the flags column of the display.&nbsp;
+Second, a balloon tip is displayed off of the NetIdMgr taskbar notification area
+icon.</p>
+
+<h3>Plug-in Configuration</h3>
+<p><img src="images/screen_config_plug_ins.png" /> </p>
+<p><span style="font-size: 10.0pt; font-family: Times New Roman">The Plug-ins
+and Modules page provides status information on the currently loaded plug-ins
+and modules include a description of their purpose; whether or not it was loaded
+properly; which other modules are required; and what organization developed it.
+</span> </p>
+
+<h4>Kerberos v5 Plug-in Configuration</h4>
+
+<p><img src="images/screen_config_plug_in_krb5.png" /> </p>
+<p class="MsoNormal">The <b>Kerberos v5 Configuration</b> tab allows you to
+alter the behavior of&nbsp; the Kerberos v5 identity provider.&nbsp; </p>
+<p class="MsoNormal">In the <b>Default Realm</b> field, select a Kerberos realm
+from the dropdown list.</p>
+<p class="MsoBodyTextIndent2" style="text-indent:0pt">The <b>Include all
+configured realms in New Credentials realm list</b> determines whether all of
+the realms declared in the Kerberos v5 Configuration file are included in the
+realms list of the <b>Obtain New Credentials</b> dialog.&nbsp; If disabled, only the
+realms previously used to obtain credentials are displayed.</p>
+<p class="MsoBodyTextIndent2" style="text-indent:0pt">The <b>Configuration File
+</b>field displays the path to the Kerberos v5 configuration file, krb5.ini.</p>
+<p class="MsoNormal"><span style="display: none">The Kerberos libraries depend
+on configuration files for their proper operation.&nbsp; When <b>Create file if
+missing </b>is checked, NetIdMgr will construct replacements for missing
+configuration files upon startup.&nbsp; This is performed by extracting Kerberos
+configuration information from the local Windows registry and the Domain Name
+System.&nbsp; The contents of the created file may then be edited using the <b>
+Kerberos Properties Dialog</b>.&nbsp; [This functionality is not available in this
+release.]</span></p>
+<p class="MsoNormal">The field labeled <b>Host Name</b> displays the name of
+your local machine.&nbsp; The <b>Domain Name</b> field displays the domain to which
+your local machine currently belongs.&nbsp;</p>
+<p class="MsoNormal">The <b>Import Tickets</b> listbox allows you to configure
+how NetIdMgr interacts with the Microsoft Kerberos Authentication Provider.&nbsp;
+NetIdMgr will automatically import Kerberos Tickets from the Microsoft LSA at
+startup depending upon the selected option and whether or not the Kerberos
+Authentication Provider was used for Windows Logon authorization.&nbsp; </p>
+<ul style="margin-top: 0pt; margin-bottom: 0pt" type="disc">
+ <li class="MsoNormal"><b>Never</b> means do not import tickets from the
+ MSLSA; </li>
+ <li class="MsoNormal"><b>Always</b> means do import tickets from the MSLSA;
+ and </li>
+ <li class="MsoNormal"><b>Only when the Principal matches</b> means import
+ tickets from the MSLSA only if the MSLSA Kerberos principal belongs to the
+ Default Realm.</li>
+</ul>
+<p class="MsoNormal">When the Windows Logon identity is imported and is
+configured as the default identity, the MIT credential cache will be used in
+preference to the MSLSA credential cache.</p>
+
+<h4>Kerberos v5 Realm Configuration</h4>
+<p><img src="images/screen_config_plug_in_krb5_realm.png" /> </p>
+
+<h4>Kerberos v5 Credential Cache Configuration</h4>
+<p><img src="images/screen_config_plug_in_krb5_ccache.png" /> </p>
+<p class="MsoNormal">The Kerberos Realm Configuration dialog can be used to
+manage the contents of the [Realms] and [Domain_Realm] sections of the Kerberos
+v5 configuration file.</p>
+
+<h4>Kerberos v4 Plug-in Configuration</h4>
+<p><img src="images/screen_config_plug_in_krb4.png" /> </p>
+<p class="MsoBodyTextIndent2" style="text-indent:0pt">Here, you can specify the
+name of the in-memory cache used to store the Kerberos v4 tickets.&nbsp; The format
+of the name is “API:” followed by the cache name.&nbsp; Disk caches are not supported
+by Kerberos for Windows.</p>
+<p class="MsoNormal">The paths to the Kerberos v4 configuration files: krb.con
+and krbrealm.con may be viewed from this dialog.&nbsp; The default is to store the
+configuration files in the Windows directory.</p>
</body>
-</html>
+
+</html> \ No newline at end of file
diff --git a/src/windows/identity/help/html/use_icon.htm b/src/windows/identity/help/html/use_icon.htm
index 212099e..353443f 100644
--- a/src/windows/identity/help/html/use_icon.htm
+++ b/src/windows/identity/help/html/use_icon.htm
@@ -1,17 +1,16 @@
<html>
<head>
- <title>NetIDMgr Notification Icon</title>
+ <title>Network Identity Manager Notification Icon</title>
<meta name="description" content="NetIDMgr Notification Icon">
<meta name="keywords" content="icon, netidmgr, notification, tray">
<link rel="stylesheet" type="text/css" href="nidmgr.css">
</head>
<body>
-<h1>NetIDMgr Notification Icon</h1>
+<h1>Network Identity Manager Notification Icon</h1>
+<h3>Visual Representation of Identity State Information</h3>
-<p>When NetIDMgr is running, an icon will be placed in the system
-notification area (sometimes referred to as the "tray" area, or the
-"system tray"). The icon will change to reflect the current state of
+<p>When Network Identity Manager is running, an icon will appear in the taskbar notification area.&nbsp; The icon will change to reflect the current state of
the managed credentials.</p>
<p>The icons and their meanings are described below:</p>
@@ -19,33 +18,56 @@ the managed credentials.</p>
<table width="100%" border="1">
<tr>
-<td><img src="images/appicon_empty.bmp" /></td>
+<td><img src="images/appicon_empty.png" /></td>
<td>There are no managed credentials for any identity.</td>
</tr>
<tr>
-<td><img src="images/appicon_good.bmp" /></td>
+<td><img src="images/appicon_good.png" /></td>
<td>There are valid credentials for all the identities.</td>
</tr>
<tr>
-<td><img src="images/appicon_warnexp.bmp" /></td> <td>Some of the
+<td><img src="images/appicon_warnexp.png" /></td> <td>Some of the
credentials will expire in the next few minutes. This icon will be
displayed even if automatic renewals are enabled. In this case, the
credentials in question may get renewed before they expire, and the
icon will change to reflect this change.</td> </tr>
<tr>
-<td><img src="images/appicon_expired.bmp" /></td>
-<td>some of the managed credentials have expired.</td>
+<td><img src="images/appicon_expired.png" /></td>
+<td>At least one identity's credentials have expired.</td>
</tr>
<tr>
-<td><img src="images/appicon_warning.bmp" /></td> <td>A warning
+<td><img src="images/appicon_warning.png" /></td> <td>A warning
message is waiting to be displayed. Click the icon to view the
warning message.</td> </tr>
</table>
+<h3>Notification Icon Menu</h3>
+<p>Clicking on the notification with the second mouse button displays a menu
+(see right) which contains the most commonly used Network Identity Manager
+operations.&nbsp; </p>
+
+<ul>
+ <li><a href="act_new_creds.htm">Obtaining new credentials</a></li>
+ <li><a href="act_destroy_creds.htm">Destroying credentials</a></li>
+ <li><a href="act_import_creds.htm">Import credentials from the Microsoft Logon
+ Session cache</a></li>
+ <li><a href="act_renew_creds.htm">Renew credentials</a></li>
+ <li><a href="act_chpw.htm">Change password</a></li>
+</ul>
+
+<div class="sidebar">
+<img src="images/notification_icon_menu.png" />
+<p class="caption">Figure 1. Notification Icon Menu</p>
+</div>
+<p></p>
+<h3>Notification Icon Default Action</h3>
+
+<p>Clicking on the icon with the first mouse button will open or close the Network Identity Manager application window or open the Obtain New Credentials dialog based upon the current configuration. The behavior can be adjusted from the Options-&gt;General page. Clicking with the second mouse button will display a menu of commands.</p>
+
</body>
</html> \ No newline at end of file
diff --git a/src/windows/identity/help/html/use_layout.htm b/src/windows/identity/help/html/use_layout.htm
index 7a0d070..425af0b 100644
--- a/src/windows/identity/help/html/use_layout.htm
+++ b/src/windows/identity/help/html/use_layout.htm
@@ -1,13 +1,19 @@
<html>
<head>
- <title>Managing the credentials view layout</title>
+ <title>Network Identity Manager - Managing the credentials view layout</title>
<meta name="description" content="Managing the credentials view layout">
<meta name="keywords" content="view, layout">
<link rel="stylesheet" type="text/css" href="nidmgr.css">
+ <Object type="application/x-oleobject" classid="clsid:1e2a7bd0-dab9-11d0-b93a-00c04fc99f9e">
+<param name="Keyword" value="Credential View Layouts">
+<param name="Keyword" value="Sorting credentials by a column">
+<param name="Keyword" value="Grouping credentials by a column">
+<param name="Keyword" value="Selecting Columns">
+</OBJECT>
</head>
<body>
-<h1>Managing the credentials view layout</h1>
+<h1>Network Identity Manager - Managing the credentials view layout</h1>
<p>The credentials view layout provides an outlined view of the
credentials that are being managed by NetIDMgr. The columns that are
@@ -24,8 +30,8 @@ customizations that can be performed:</p>
<li><a href="#group">Grouping by a column.</a></li>
</ul>
-<a name="predef" />
-<h3>Predefined layouts</h3>
+<a name="predef"></a>
+<h3>Pre-defined layouts</h3>
<p>The predefined layouts in NetIDMgr are:</p>
@@ -46,7 +52,7 @@ customizations that can be performed:</p>
</ul>
-<a name="addcol" />
+<a name="addcol"></a>
<h3>Adding and removing columns</h3>
<p>The <span class="pre">View Columns</span> menu lists all the
@@ -60,9 +66,9 @@ display.</p>
area or by invoking the <span class="pre">View</span> menu. The menu
is shown below.</p>
-<p><img src="images/screen_menu_view_cols.bmp"/> </p>
+<p><img src="images/screen_menu_view_cols.png"/> </p>
-<a name="sort" />
+<a name="sort"></a>
<h3>Sorting by a column</h3>
<p>Clicking on a column header will change the sort order of the
@@ -73,7 +79,7 @@ will start sorting in increasing order by that column.</p>
<p>Double-clicking a column that is not used for grouping will stop
sorting by that column.</p>
-<a name="group" />
+<a name="group"></a>
<h3>Grouping by a column</h3>
<p>Double-clicking on a column header will start grouping by that
diff --git a/src/windows/identity/help/html/use_start.htm b/src/windows/identity/help/html/use_start.htm
index 1f1a7d6..4c1b7ab 100644
--- a/src/windows/identity/help/html/use_start.htm
+++ b/src/windows/identity/help/html/use_start.htm
@@ -1,24 +1,24 @@
<html>
<head>
- <title>Starting NetIDMgr</title>
+ <title>Network Identity Manager - Starting Network Identity Manager</title>
<meta name="description" content="starting NetIDMgr">
<meta name="keywords" content="starting">
<link rel="stylesheet" type="text/css" href="nidmgr.css">
</head>
<body>
-<h1>Starting NetIDMgr</h1>
+<h1>Network Identity Manager - Starting Network Identity Manager</h1>
-<h3>Opening the NetIDMgr window from the notification icon</h3>
+<h3>Opening the Network Identity Manager window from the notification icon</h3>
-<p>Depending on how you have installed NetIDMgr, it may start as soon
-as you login, or it may need to be started manually. NetIDMgr is a
-tray application. Hence it doesn't appear on your task bar. This is
-based on the assumption that you don't need to run NetIDMgr very
-often, and helps reduce clutter on the desktop.</p>
+<p>Depending on how Network Identity Manager was installed, it may be configured
+with a shortcut in the Startup Folder, or it may require a manual start. NetIDMgr is a
+notification tray application and therefore it is not listed in the Microsoft
+Windows task bar.&nbsp; This design is based on the assumption that most users
+rarely interact directly with the application.</p>
<div class="sidebar">
-<img src="images/screen_tray_icon.bmp"/>
+<img src="images/screen_tray_icon.png"/>
<p class="caption">Figure 1: NetIDMgr notification icon</p>
</div>
@@ -27,14 +27,15 @@ notification area (sometimes referred to as the "system tray") as
shown in figure 1. Details about the state information represented by
the icon can be found <a href="use_icon.htm">here</a>.</p>
-<p>Clicking on this icon brings up the NetIDMgr window. Right
-clicking on the icon, on the other hand, brings up a menu.</p>
+<p>Left clicking on this icon executes the default action which either changes
+the view state of the credential list or displays the <i>Obtain New Credentials</i>
+dialog. Right clicking on the icon displays a menu.</p>
-<h3>Starting NetIDMgr from the Start Menu or command line</h3>
+<h3>Starting Network Identity Manager from the Start Menu or command line</h3>
<div class="sidebar">
-<img src="images/screen_app_icon.bmp" />
-<p class="caption">Figure 2: NetIDMgr application icon</p>
+<img src="images/screen_app_icon.png" />
+<p class="caption">Figure 2: NetIDMgr application shortcut</p>
</div>
<p>If NetIDMgr was not configured to start automatically when you
diff --git a/src/windows/identity/help/html/using.htm b/src/windows/identity/help/html/using.htm
index c66ee8a..103ae5f 100644
--- a/src/windows/identity/help/html/using.htm
+++ b/src/windows/identity/help/html/using.htm
@@ -1,28 +1,35 @@
<html>
<head>
- <title>Using NetIDMgr</title>
+ <title>Using Network Identity Manager</title>
<meta name="description" content="Using NetIDMgr">
<meta name="keywords" content="using">
<link rel="stylesheet" type="text/css" href="nidmgr.css">
</head>
<body>
-<h1>Using NetIDMgr</h1>
+<h1>Using Network Identity Manager</h1>
<p>
-Depending on how NetIDMgr was installed, it might already be running
-in the system notification area or it might need to be started
-manually. See the topic <a href="use_start.htm">starting
-NetIDMgr</a> for details. Essentially, to open the NetIDMgr window,
-you either have to click the <a href="use_icon.htm">application
-icon</a> in the system notification area, select the icon from the
-start menu, or type 'netidmgr' at a command prompt.
+Depending on how Network Identity Manager was installed, it might already be running
+in the Windows taskbar notification area or it might need to be started
+manually. See the topic <a href="use_start.htm">Starting
+Network Identity Manager</a> for details.&nbsp;
+</p>
+<p>
+To open the NetIDMgr window when the <a href="use_icon.htm">application
+icon</a> is displayed in the Windows taskbar notification area, click on the
+icon with the 2nd mouse button (usually the right mouse button) and select <b>Show Network Identity Manager window</b> from the menu.
+</p>
+<p>
+If NetIdMgr is not displayed in the Windows taskbar notification area, it can be
+started from the
+Start Menu, or type 'netidmgr' at a command prompt.
</p>
<p>
-Once you open the NetIDMgr window, you will be presented with a view
-of your existing credentials, or a message notifying you that you
-don't have any. Details of the credentials view objects <a
+Once the NetIDMgr window is visible, you will be presented with a view
+of your existing identities, or a message notifying you that you
+don't have any.&nbsp;&nbsp; Details of the credentials view objects <a
href="wnd_main.htm">can be found here.</a>
</p>
@@ -31,18 +38,20 @@ Brief overviews of how to perform common tasks are linked below:
</p>
<ul>
- <li><a href="act_new_creds.htm">Getting new credentials</a></li>
+ <li><a href="act_new_creds.htm">Obtaining new credentials</a></li>
<li><a href="act_destroy_creds.htm">Destroying credentials</a></li>
- <li><a href="act_import_creds.htm">Import credentials from the MSLSA cache</a></li>
+ <li><a href="act_import_creds.htm">Import credentials from the Microsoft Logon
+ Session cache</a></li>
<li><a href="act_renew_creds.htm">Renew credentials</a></li>
<li><a href="act_chpw.htm">Change password</a></li>
- <li><a href="use_layout.htm">Managing the credentials view layout</a></li>
- <li><a href="use_config.htm">Configuring NetIDMgr and identities</a></li>
+ <li><a href="use_layout.htm">Customizing the advanced credentials view layout</a></li>
+ <li><a href="use_config.htm">Configuring Network Identity Manager</a></li>
+ <li><a href="tb_standard.htm">Using the Toobar</a></li>
</ul>
<p>
-A more comprehensive list of how-to topics can be found in the <span
-class="pre"><a href="howdoi.htm">How do I...</a></span> section.</p>
+A more comprehensive list of how-to topics can be found in the
+<a href="howdoi.htm">How do I...</a> section.</p>
</body>
</html> \ No newline at end of file
diff --git a/src/windows/identity/help/html/welcome.htm b/src/windows/identity/help/html/welcome.htm
index 18a6312..263be8c 100644
--- a/src/windows/identity/help/html/welcome.htm
+++ b/src/windows/identity/help/html/welcome.htm
@@ -4,6 +4,8 @@
<meta name="description" content="Welcome">
<meta name="keywords" content="welcome">
<link rel="stylesheet" type="text/css" href="nidmgr.css">
+ <style>
+</style>
</head>
<h1>Welcome to the Network Identity Manager</h1>
@@ -12,25 +14,76 @@
<img src="images/logo.jpg" width="100" height="100"/>
</div>
-<p>
-The Network Identity Manager (or NetIDMgr for short) allows you to
-manage your network identities and the associated credentials
-(Kerberos tickets, AFS tokens, etc.).
-</p>
-
-<p>
-NetIDMgr is extensible using plugins. In fact, most of the features
-are implemented in plugins, some of which are themselves extensible.
-Support for additional protocols and credential types can be added by
-installing the appropriate plugins.
+<p>Network Identity Manager (NetIdMgr) is a graphical
+tool designed to simplify the management of network identities and their credentials
+which are used by network authentication protocols while providing
+secure access to network services.&nbsp; When NetIDMgr is used with Kerberos v5 each
+network identity is a unique Kerberos principal name and the credentials
+are Kerberos v5 tickets.&nbsp; Kerberos v5 tickets can be used by NetIDMgr to
+obtain Andrew File System (AFS) tokens and X.509 public key certificates if the
+appropriate plug-ins are available.</p>
+<p>When you log into Microsoft Windows with a domain account,
+your account name and the Windows Domain name when combined form a Kerberos
+principal name.&nbsp; As an example, “WINDOWS\jaltman” is actually a short form
+representation of
+jaltman@WINDOWS.SECURE-ENDPOINTS.COM.&nbsp;&nbsp; Microsoft Windows uses
+Kerberos-based network identities for all domain-based network authentications.&nbsp;
</p>
-
+<p>Since Microsoft Windows already provides a network
+identity, why do you need NetIdMgr?&nbsp; Here are some examples:</p>
+<ol>
+ <li>Your only network identity is your Windows Domain
+ account but you have third-party applications that rely on MIT Kerberos for
+ authentication for access to remote files, e-mail, web data, or other
+ services.&nbsp; In this scenario, NetIdMgr will automatically import your Windows
+ Domain credentials into a form that can be used by applications that rely on
+ MIT Kerberos.</li>
+ <li>You do not have a Windows Domain account but you must
+ obtain network credentials in order to securely access a network service.&nbsp;
+ In this scenario, NetIdMgr can be used to obtain new credentials for network
+ identities and can automatically renew them before they expire.</li>
+ <li>You have Kerberos credentials for a network identity
+ and you have third-party applications that require an alternative form of
+ network credential, such as an AFS token or a X.509 certificate, which can
+ be obtained via a Kerberos authentication.&nbsp; In this scenario, NetIdMgr can
+ automatically use your existing credentials to obtain and renew the
+ additional network credentials types.</li>
+ <li>You have a Windows Domain account but you need to
+ authenticate to a service belonging to a Kerberos realm outside the Windows
+ Domain.&nbsp; In this scenario, NetIdMgr can be used to manage multiple network
+ identities, the Windows Domain identity as well as the additional Kerberos
+ identity required for the external network services.&nbsp; </li>
+ <li>You have multiple network identities within the same
+ Kerberos realm which are used for different roles.&nbsp; For example, an
+ unprivileged user identity and a privileged identity that is only meant to
+ be used for system administration.&nbsp; In this scenario, NetIdMgr can be used
+ to obtain credentials for all of your identities and automatically renew
+ them as necessary.</li>
+</ol>
+<p>NetIdMgr’s automated credential acquisition and renewal
+makes it an invaluable tool which provides users with a Single Sign-on
+experience. </p>
+<p>NetIdMgr is most commonly configured as a StartUp item that runs an icon in the Taskbar Notification Area until you logout.&nbsp;
+While running, NetIDMgr automatically renews your credentials, notifies you of
+pending expirations and prompts you when a Kerberized application requires
+credentials that have not already been obtained.&nbsp; </p>
+<p>When configured to do so, NetIdMgr will prompt you
+immediately after it starts to obtain Kerberos credentials.&nbsp; This is often
+referred to as logging on to Kerberos.&nbsp; NetIdMgr does not perform a logon in the
+sense of the Windows Logon Service.&nbsp; A logon service would do more than manage
+Kerberos tickets. A logon service would authenticate you to the local machine,
+validate access to your local file system and performs additional set-up tasks.
+These are beyond the scope of NetIdMgr. NetIdMgr simply allows you to manage
+Kerberos identities on behalf of compatible applications and to change your
+Kerberos password.</p>
<p>
-This version is distributed as a part of the MIT Kerberos for Windows
-product along with the Kerberos 5 and Kerberos 4 plugins. The OpenAFS
-plugin, which is required for supporting AFS tokens, is
-distributed separately.
-</p>
+NetIDMgr is distributed as a part of MIT Kerberos for Windows
+along with the Kerberos v5 and Kerberos v4 plug-ins. Plug-ins for additional
+credential types including AFS tokens and KCA certificates are available as
+separate distributions.&nbsp; The OpenAFS plug-in, which is required for supporting AFS tokens, is
+distributed as part of <a href="http://www.openafs.org/windows.html">OpenAFS for
+Windows</a>.&nbsp; The KCA plug-in is distributed by
+<a href="http://www.secure-endpoints.com/">Secure Endpoints Inc.</a></p>
<ul>
<li><a href="copyright.htm">Legal information</a></li>
@@ -43,34 +96,35 @@ distributed separately.
<li><a href="concepts.htm">NetIDMgr concepts</a></li>
<li><a href="using.htm">Using NetIDMgr</a></li>
<li><a href="howdoi.htm">How do I ...</a></li>
+<li><a href="menu_all.htm">All Menus</a></li>
</ul>
<h3>Information for developers</h3>
<p>
-If you are interested in developing plugins or extending the features
-of NetIDMgr, your first stop should be the NetIDMgr SDK. This is
-included in the Kerberos for Windows SDK, which itself is a part of
-the Kerberos for Windows distribution.
-</p>
+If you are interested in developing plug-ins or extending the features
+of NetIDMgr, your first stop should be the NetIDMgr SDK which is included in the
+MIT Kerberos for Windows SDK.</p>
<p>
-We highly recommend interested developers to contact the <a
+Contact the <a
href="mailto:netidmgr@secure-endpoints.com">netidmgr@secure-endpoints.com</a>
-mailing list.
-</p>
+mailing list with questions or comments.</p>
<h3>External links</h3>
<ul>
-<li><a class="external" href="http://web.mit.edu/kerberos">http://web.mit.edu/kerbeors</a>:
+<li><a class="external" href="http://web.mit.edu/kerberos">http://web.mit.edu/kerberos</a>:
MIT Kerberos distribution
</li>
-<li><a class="external" href="http://openafs.org">http://openafs.org</a>:
+<li><a class="external" href="http://www.openafs.org/windows.html">http://www.openafs.org/windows.html</a>:
-OpenAFS
+OpenAFS for Windows
</li>
+<li>
+<a class="external" href="http://www.secure-endpoints.com/">http://www.secure-endpoints.com/</a>:
+Secure Endpoints Inc.</li>
</ul>
</html> \ No newline at end of file
diff --git a/src/windows/identity/help/html/wnd_main.htm b/src/windows/identity/help/html/wnd_main.htm
index 3c10378..211120a 100644
--- a/src/windows/identity/help/html/wnd_main.htm
+++ b/src/windows/identity/help/html/wnd_main.htm
@@ -1,17 +1,36 @@
<html>
<head>
- <title>Main Window</title>
+ <title>Network Identity Manager - Application Window</title>
<meta name="description" content="Main Window">
<meta name="keywords" content="main window">
<link rel="stylesheet" type="text/css" href="nidmgr.css">
+
+<Object type="application/x-oleobject" classid="clsid:1e2a7bd0-dab9-11d0-b93a-00c04fc99f9e">
+ <param name="Keyword" value="Application Window Basic View">
+ <param name="Keyword" value="Application Windows Advanced View">
+ <param name="Keyword" value="Identity Views">
+</OBJECT>
+
</head>
<body>
-<h1>Main Window</h1>
+<h1>Network Identity Manager - Application Window</h1>
+
+<p>The application window of Network Identity Manager can be displayed in two modes: <b>basic</b> and <b>advanced</b>.</p>
+
+<p>The basic view provides status information of the currently available identities whereas the advanced
+view provides more detailed information of all the active credentials.</p>
+
+<div>
+<img src="images/screen_main_wnd_basic.png"/>
+<p class="caption">Figure 1. Network Identity Manager Basic View</p>
+</div>
-<p>The main window of Network Identity Manager is structured as follows</p>
+<div>
-<img src="images/screen_main_wnd.bmp" usemap="#main_wnd_map"/>
+<img src="images/screen_main_wnd.png"/>
+<p class="caption">Figure 2. Network Identity Manager Advanced View</p>
+</div>
<ol>
<li>Menu bar</li>
@@ -65,4 +84,4 @@ The threshold for this is always zero.
</p>
</body>
-</html>
+</html> \ No newline at end of file
diff --git a/src/windows/identity/help/khhelp.h b/src/windows/identity/help/khhelp.h
index 88f73c0..fbfef60 100644
--- a/src/windows/identity/help/khhelp.h
+++ b/src/windows/identity/help/khhelp.h
@@ -28,6 +28,6 @@
#define IDH_NC_CANCEL 3002
#define IDH_NC_HELP 3003
#define IDH_NC_TABBUTTON 3004
-#define IDH_NC_OPTIONS 3005
+#define IDH_NC_ADVANCED 3005
#define IDH_NC_TABMAIN 3006
#define IDH_NC_SETDEF 3007
diff --git a/src/windows/identity/help/popups_newcreds.txt b/src/windows/identity/help/popups_newcreds.txt
index 52c6124..74a3936 100644
--- a/src/windows/identity/help/popups_newcreds.txt
+++ b/src/windows/identity/help/popups_newcreds.txt
@@ -13,7 +13,7 @@ Cancels the new credentials operation.
.topic IDH_NC_HELP
Provides help for this dialog box.
-.topic IDH_NC_OPTIONS
+.topic IDH_NC_ADVANCED
Expands the dialog and allows you to set additional
options for the credentials that will be obtained
by this dialog.
diff --git a/src/windows/identity/help/popups_password.txt b/src/windows/identity/help/popups_password.txt
index 3958325..e92b30e 100644
--- a/src/windows/identity/help/popups_password.txt
+++ b/src/windows/identity/help/popups_password.txt
@@ -10,7 +10,7 @@ Change the password for the selected identity.
.topic IDH_NC_CANCEL
Cancel the change password operation.
-.topic IDH_NC_OPTIONS
+.topic IDH_NC_ADVANCED
Expand the dialog and make the option pages visible for the credential
types for which you will be changing the password for.
diff --git a/src/windows/identity/include/Makefile b/src/windows/identity/include/Makefile
index be4ddf9..10d2962 100644
--- a/src/windows/identity/include/Makefile
+++ b/src/windows/identity/include/Makefile
@@ -35,4 +35,4 @@ INCFILES= \
all: $(INCFILES)
clean::
- $(RM) $(INCFILES)
+ if exist '..\obj' $(RM) $(INCFILES)
diff --git a/src/windows/identity/include/kherror.h b/src/windows/identity/include/kherror.h
index f11e285..ae381ff 100644
--- a/src/windows/identity/include/kherror.h
+++ b/src/windows/identity/include/kherror.h
@@ -168,6 +168,11 @@
/*! \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 */
diff --git a/src/windows/identity/include/khlist.h b/src/windows/identity/include/khlist.h
index 2eb8586..8bf4369 100644
--- a/src/windows/identity/include/khlist.h
+++ b/src/windows/identity/include/khlist.h
@@ -116,6 +116,15 @@
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; \
@@ -150,6 +159,17 @@
#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); \
@@ -158,16 +178,37 @@
#define TQINIT(pe) \
do { \
+ LINIT(pe); \
QINIT(pe); \
(pe)->parent = NULL; } while(0)
-#define TQADDCHILD(pt,pe) \
+#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 f1d42c2..77397f9 100644
--- a/src/windows/identity/include/khmsgtypes.h
+++ b/src/windows/identity/include/khmsgtypes.h
@@ -232,13 +232,16 @@
#define KMSG_ACT_ACTIVATE 6
/*! \brief Internal */
-#define KMSG_ACT_BEGIN_CMDLINE 128
+#define KMSG_ACT_BEGIN_CMDLINE 128
/*! \brief Internal */
-#define KMSG_ACT_CONTINUE_CMDLINE 129
+#define KMSG_ACT_CONTINUE_CMDLINE 129
/*! \brief Internal */
-#define KMSG_ACT_SYNC_CFG 130
+#define KMSG_ACT_SYNC_CFG 130
+
+/*! \brief Internal */
+#define KMSG_ACT_END_CMDLINE 131
/*@}*/
diff --git a/src/windows/identity/kconfig/Makefile b/src/windows/identity/kconfig/Makefile
index 26619c0..98e9c25 100644
--- a/src/windows/identity/kconfig/Makefile
+++ b/src/windows/identity/kconfig/Makefile
@@ -35,8 +35,7 @@ OBJFILES= \
all: mkdirs $(INCFILES) $(OBJFILES)
clean::
- $(RM) $(INCFILES)
-
+ if exist '..\obj' $(RM) $(INCFILES)
# Tests
test:: util_test
diff --git a/src/windows/identity/kconfig/api.c b/src/windows/identity/kconfig/api.c
index b3b4eb6..6098435 100644
--- a/src/windows/identity/kconfig/api.c
+++ b/src/windows/identity/kconfig/api.c
@@ -26,6 +26,7 @@
#include<shlwapi.h>
#include<kconfiginternal.h>
+#include<netidmgr_intver.h>
#include<assert.h>
kconf_conf_space * conf_root = NULL;
@@ -86,6 +87,111 @@ void exit_kconf(void) {
}
}
+#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)
@@ -180,6 +286,29 @@ khcint_space_hold(kconf_conf_space * s) {
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) {
@@ -200,6 +329,15 @@ khcint_space_release(kconf_conf_space * s) {
(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
}
}
@@ -673,10 +811,10 @@ khcint_free_space(kconf_conf_space * r) {
if(!r)
return;
- LPOP(&r->children, &c);
+ TPOPCHILD(r, &c);
while(c) {
khcint_free_space(c);
- LPOP(&r->children, &c);
+ TPOPCHILD(r, &c);
}
if(r->name)
@@ -847,8 +985,8 @@ khc_open_space(khm_handle parent, const wchar_t * cspace, khm_int32 flags,
flags |= KCONF_FLAG_USER | KCONF_FLAG_MACHINE | KCONF_FLAG_SCHEMA;
if(cspace == NULL) {
- khcint_space_release(p);
*result = (khm_handle) khcint_handle_from_space(p, flags);
+ khcint_space_release(p);
return KHM_ERROR_SUCCESS;
}
@@ -897,6 +1035,9 @@ khc_open_space(khm_handle parent, const wchar_t * cspace, khm_int32 flags,
} else
*result = NULL;
+ if (c)
+ khcint_space_release(c);
+
return rv;
}
@@ -1877,26 +2018,35 @@ khc_value_exists(khm_handle conf, const wchar_t * value) {
if(!khc_is_handle(conf))
return KHM_ERROR_INVALID_PARAM;
- c = khc_space_from_handle(conf);
+ 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 (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(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(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;
}
@@ -2318,7 +2468,7 @@ khc_unload_schema(khm_handle conf, const kconf_schema * schema)
return KHM_ERROR_INVALID_PARAM;
EnterCriticalSection(&cs_conf_global);
- rv = khcint_unload_schema_i(conf, schema, 0, NULL);
+ rv = khcint_unload_schema_i(conf, schema, 0, NULL);
LeaveCriticalSection(&cs_conf_global);
return rv;
diff --git a/src/windows/identity/kconfig/kconfig.h b/src/windows/identity/kconfig/kconfig.h
index 518dc4f..b550d13 100644
--- a/src/windows/identity/kconfig/kconfig.h
+++ b/src/windows/identity/kconfig/kconfig.h
@@ -792,6 +792,12 @@ khc_get_type(khm_handle conf, const wchar_t * value_name);
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.
diff --git a/src/windows/identity/kcreddb/Makefile b/src/windows/identity/kcreddb/Makefile
index 24cc033..579e454 100644
--- a/src/windows/identity/kcreddb/Makefile
+++ b/src/windows/identity/kcreddb/Makefile
@@ -49,4 +49,4 @@ $(OBJ)\kcredres.res: lang\en_us\kcredres.rc
all: mkdirs $(INCFILES) $(OBJ)\kcredres.res $(OBJFILES)
clean::
- $(RM) $(INCFILES)
+ if exist '..\obj' $(RM) $(INCFILES) \ No newline at end of file
diff --git a/src/windows/identity/kcreddb/credset.c b/src/windows/identity/kcreddb/credset.c
index dda9817..2d7eeeb 100644
--- a/src/windows/identity/kcreddb/credset.c
+++ b/src/windows/identity/kcreddb/credset.c
@@ -321,6 +321,10 @@ kcdb_credset_collect(khm_handle cs_dest,
if(c_sel)
PFREE(c_sel);
+ if (cs_dest == NULL) {
+ kcdb_identity_refresh_all();
+ }
+
return code;
}
@@ -422,6 +426,10 @@ kcdb_credset_collect_filtered(khm_handle cs_dest,
if(c_sel)
PFREE(c_sel);
+ if (cs_dest == NULL) {
+ kcdb_identity_refresh_all();
+ }
+
return code;
}
@@ -1047,7 +1055,8 @@ kcdb_credset_unseal(khm_handle credset) {
}
-/* wrapper for qsort and also parameter gobbling FSM. */
+/* 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)
{
@@ -1091,12 +1100,16 @@ kcdb_credset_sort(khm_handle credset,
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;
}
diff --git a/src/windows/identity/kcreddb/identity.c b/src/windows/identity/kcreddb/identity.c
index 3f60206..5d76384 100644
--- a/src/windows/identity/kcreddb/identity.c
+++ b/src/windows/identity/kcreddb/identity.c
@@ -55,7 +55,7 @@ kcdb_identity_set_provider(khm_handle sub)
EnterCriticalSection(&cs_ident);
if (sub != kcdb_ident_sub) {
if(kcdb_ident_sub != NULL) {
- kmq_post_sub_msg(kcdb_ident_sub,
+ kmq_send_sub_msg(kcdb_ident_sub,
KMSG_IDENT,
KMSG_IDENT_EXIT,
0,
@@ -231,7 +231,7 @@ kcdb_identity_create(const wchar_t *name,
StringCbCopy(id->name, namesize, name);
id->flags = (flags & KCDB_IDENT_FLAGMASK_RDWR);
- id->flags |= KCDB_IDENT_FLAG_ACTIVE;
+ id->flags |= KCDB_IDENT_FLAG_ACTIVE | KCDB_IDENT_FLAG_EMPTY;
LINIT(id);
EnterCriticalSection(&cs_ident);
@@ -425,10 +425,12 @@ kcdb_identity_set_flags(khm_handle vid,
id->flags = (id->flags & ~mask) | (flag & mask);
- if (flag & KCDB_IDENT_FLAG_VALID)
- id->flags &= ~KCDB_IDENT_FLAG_INVALID;
- if (flag & KCDB_IDENT_FLAG_INVALID)
- id->flags &= ~KCDB_IDENT_FLAG_VALID;
+ 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;
@@ -466,7 +468,9 @@ kcdb_identity_get_flags(khm_handle vid,
id = (kcdb_identity *) vid;
+ EnterCriticalSection(&cs_ident);
*flags = id->flags;
+ LeaveCriticalSection(&cs_ident);
return KHM_ERROR_SUCCESS;
}
diff --git a/src/windows/identity/kcreddb/kcreddb.h b/src/windows/identity/kcreddb/kcreddb.h
index 060f556..4b15a24 100644
--- a/src/windows/identity/kcreddb/kcreddb.h
+++ b/src/windows/identity/kcreddb/kcreddb.h
@@ -232,11 +232,21 @@ Functions, macros etc. for manipulating identities.
*/
#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 0x00000fffL
+#define KCDB_IDENT_FLAGMASK_RDWR 0x00001fffL
/*@}*/
@@ -431,7 +441,9 @@ kcdb_identity_delete(khm_handle id);
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.
+ 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:
diff --git a/src/windows/identity/kherr/Makefile b/src/windows/identity/kherr/Makefile
index 84f9da5..26021d4 100644
--- a/src/windows/identity/kherr/Makefile
+++ b/src/windows/identity/kherr/Makefile
@@ -40,4 +40,4 @@ SDKLIBFILES= \
all: mkdirs $(INCFILES) $(OBJFILES)
clean::
- $(RM) $(INCFILES)
+ if exist '..\obj' $(RM) $(INCFILES) \ No newline at end of file
diff --git a/src/windows/identity/kmm/Makefile b/src/windows/identity/kmm/Makefile
index 6135cdc..6a3edfa 100644
--- a/src/windows/identity/kmm/Makefile
+++ b/src/windows/identity/kmm/Makefile
@@ -51,4 +51,4 @@ $(OBJ)\kmm_msgs.rc: lang\kmm_msgs.mc
all: mkdirs $(INCFILES) $(MSGRESFILE) $(OBJFILES)
clean::
- $(RM) $(INCFILES)
+ if exist '..\obj' $(RM) $(INCFILES) \ No newline at end of file
diff --git a/src/windows/identity/kmm/kmm_registrar.c b/src/windows/identity/kmm/kmm_registrar.c
index f93363e..636e857 100644
--- a/src/windows/identity/kmm/kmm_registrar.c
+++ b/src/windows/identity/kmm/kmm_registrar.c
@@ -131,6 +131,9 @@ khm_boolean KHMAPI kmmint_reg_cb(khm_int32 msg_type,
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);
@@ -140,6 +143,9 @@ DWORD WINAPI kmmint_registrar(LPVOID lpParameter)
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;
@@ -156,6 +162,8 @@ 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();
@@ -324,8 +332,13 @@ void kmmint_init_plugin(kmm_plugin_i * p) {
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;
@@ -435,6 +448,10 @@ void kmmint_init_plugin(kmm_plugin_i * p) {
} 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);
@@ -485,9 +502,18 @@ _exit:
_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
@@ -522,14 +548,15 @@ void kmmint_exit_plugin(kmm_plugin_i * p) {
EnterCriticalSection(&cs_kmm);
/* undo reference count done in kmmint_init_plugin() */
- if(p->state == KMM_PLUGIN_STATE_EXITED ||
- p->state == KMM_PLUGIN_STATE_HOLD) {
+ if(p->flags & KMM_PLUGIN_FLAG_IN_MODCOUNT) {
np = --(p->module->plugin_count);
+ p->flags &= ~KMM_PLUGIN_FLAG_IN_MODCOUNT;
} else {
- /* the plugin was never active. We can't base a module unload
- decision on np */
+ /* 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;
}
@@ -915,16 +942,23 @@ void kmmint_exit_module(kmm_module_i * m) {
p = kmm_listed_plugins;
while(p) {
- if(p->module == m) {
+ 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
@@ -933,6 +967,21 @@ void kmmint_exit_module(kmm_module_i * m) {
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) {
@@ -968,6 +1017,14 @@ void kmmint_exit_module(kmm_module_i * m) {
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() */
@@ -975,13 +1032,6 @@ void kmmint_exit_module(kmm_module_i * m) {
/* Last but not least, now see if there are any modules left that
are running. If not, we can safely signal an exit. */
-
-#ifdef DEBUG
- assert(kmm_active_modules > 0);
-#endif
-
- kmm_active_modules--;
-
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 41eaa73..38fce24 100644
--- a/src/windows/identity/kmm/kmminternal.h
+++ b/src/windows/identity/kmm/kmminternal.h
@@ -40,6 +40,9 @@
#include<khmsgtypes.h>
#include<kherror.h>
#include<kplugin.h>
+
+#define NOEXPORT
+
#include<utils.h>
#include<kconfig.h>
#include<kcreddb.h>
@@ -104,6 +107,9 @@ typedef struct kmm_module_i_t {
(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;
@@ -142,13 +148,17 @@ typedef struct kmm_plugin_i_t {
/* 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 0x0400
+ #define KMM_PLUGIN_FLAG_DISABLED 0x00000400
*/
diff --git a/src/windows/identity/kmq/Makefile b/src/windows/identity/kmq/Makefile
index 1f11e0f..20f65b1 100644
--- a/src/windows/identity/kmq/Makefile
+++ b/src/windows/identity/kmq/Makefile
@@ -45,4 +45,4 @@ $(OBJ)\kmqconfig.c: kmqconfig.csv $(CONFDIR)\csvschema.cfg
all: mkdirs $(INCFILES) $(OBJFILES)
clean::
- $(RM) $(INCFILES)
+ if exist '..\obj' $(RM) $(INCFILES) \ No newline at end of file
diff --git a/src/windows/identity/kmq/consumer.c b/src/windows/identity/kmq/consumer.c
index ed7d548..d604177 100644
--- a/src/windows/identity/kmq/consumer.c
+++ b/src/windows/identity/kmq/consumer.c
@@ -36,6 +36,70 @@ 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 */
@@ -89,9 +153,15 @@ kmq_queue * kmqint_get_thread_queue(void) {
*/
void kmqint_get_queue_message_ref(kmq_queue * q, kmq_message_ref ** r) {
EnterCriticalSection(&q->cs);
- QGET(q,r);
- if(QTOP(q))
- SetEvent(q->wait_o);
+
+ if (q->flags & KMQ_QUEUE_FLAG_DELETED) {
+ *r = NULL;
+ } else {
+ QGET(q,r);
+ if(QTOP(q))
+ SetEvent(q->wait_o);
+ }
+
LeaveCriticalSection(&q->cs);
}
@@ -102,6 +172,13 @@ void kmqint_get_queue_message_ref(kmq_queue * q, kmq_message_ref ** r) {
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);
@@ -142,11 +219,8 @@ void kmqint_post(kmq_msg_subscription * s, kmq_message * m, khm_boolean try_send
if (IsBadCodePtr(s->recipient.cb)) {
rv = KHM_ERROR_INVALID_OPERATION;
} else {
- if (IsBadCodePtr(s->recipient.cb))
- rv = KHM_ERROR_INVALID_OPERATION;
- else
- rv = s->recipient.cb(m->type, m->subtype,
- m->uparam, m->vparam);
+ rv = s->recipient.cb(m->type, m->subtype,
+ m->uparam, m->vparam);
}
m->refcount--;
if(KHM_SUCCEEDED(rv))
@@ -154,6 +228,14 @@ void kmqint_post(kmq_msg_subscription * s, kmq_message * m, khm_boolean try_send
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);
@@ -173,8 +255,6 @@ void kmqint_post(kmq_msg_subscription * s, kmq_message * m, khm_boolean try_send
#ifdef _WIN32
else if(s->rcpt_type == KMQ_RCPTTYPE_HWND) {
- m->refcount++;
-
if(try_send &&
GetCurrentThreadId() == GetWindowThreadProcessId(s->recipient.hwnd,
NULL)) {
@@ -185,11 +265,24 @@ void kmqint_post(kmq_msg_subscription * s, kmq_message * m, khm_boolean try_send
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);
}
@@ -202,8 +295,6 @@ void kmqint_post(kmq_msg_subscription * s, kmq_message * m, khm_boolean try_send
deleted an ad-hoc subscription. */
#ifdef DEBUG
assert(FALSE);
-#else
- return;
#endif
}
}
@@ -401,6 +492,11 @@ KHMEXP LRESULT KHMAPI kmq_wm_dispatch(LPARAM lparm, kmq_callback_t cb) {
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,
@@ -428,6 +524,12 @@ KHMEXP khm_int32 KHMAPI kmq_dispatch(kmq_timer timeout) {
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);
diff --git a/src/windows/identity/kmq/init.c b/src/windows/identity/kmq/init.c
index 00b8f6f..875e3ea 100644
--- a/src/windows/identity/kmq/init.c
+++ b/src/windows/identity/kmq/init.c
@@ -115,11 +115,58 @@ void kmqint_detach_this_thread(void) {
q = (kmq_queue *) TlsGetValue(kmq_tls_queue);
if(q) {
+ kmq_message_ref * r;
+ kmq_message * m;
+
EnterCriticalSection(&q->cs);
- q->flags |= KMQ_QUEUE_FLAG_DELETED;
+
+ 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);
- /* TODO: free up the queued messages */
+ /* 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. */
}
}
@@ -139,6 +186,8 @@ 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 {
@@ -249,3 +298,16 @@ KHMEXP khm_int32 KHMAPI kmq_exit(void) {
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 fef6a30..46ce74f 100644
--- a/src/windows/identity/kmq/kmq.h
+++ b/src/windows/identity/kmq/kmq.h
@@ -112,92 +112,18 @@ typedef struct tag_kmq_message {
kherr_context * err_ctx; /*!< Error context for the message */
- khm_int32 refcount;
+ khm_boolean aborted; /*!< TRUE if the message has been
+ aborted. */
- LDCL(struct tag_kmq_message);
+ 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;
-/*! \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 0x0008
-
-/*! \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
-
/* publishers */
/*! \brief A completion handler for a message
@@ -214,43 +140,14 @@ typedef struct tag_kmq_msg_subscription {
*/
typedef void (KHMAPI *kmq_msg_completion_handler)(kmq_message *);
-/*! \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))
+#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
@@ -750,6 +647,46 @@ KHMEXP khm_boolean KHMAPI kmq_has_completed(kmq_call call);
*/
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.
diff --git a/src/windows/identity/kmq/kmqinternal.h b/src/windows/identity/kmq/kmqinternal.h
index aeaf336..1d6196b 100644
--- a/src/windows/identity/kmq/kmqinternal.h
+++ b/src/windows/identity/kmq/kmqinternal.h
@@ -33,9 +33,135 @@
#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"
@@ -69,6 +195,7 @@ 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;
diff --git a/src/windows/identity/kmq/msgtype.c b/src/windows/identity/kmq/msgtype.c
index 3fd31ec..1b0868d 100644
--- a/src/windows/identity/kmq/msgtype.c
+++ b/src/windows/identity/kmq/msgtype.c
@@ -81,9 +81,30 @@ int kmqint_notify_msg_completion(kmq_message * m) {
/* called with cs_mkq_global && cs_kmq_types held */
void kmqint_free_msg_type(int t) {
- /*TODO: free the message type*/
- /* must set handler to NULL before freeing type */
- /* must set msg_type[t] = NULL before starting to free type */
+ 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
diff --git a/src/windows/identity/kmq/publisher.c b/src/windows/identity/kmq/publisher.c
index af1f555..66360fb 100644
--- a/src/windows/identity/kmq/publisher.c
+++ b/src/windows/identity/kmq/publisher.c
@@ -30,6 +30,66 @@ 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 */
@@ -181,6 +241,12 @@ kmq_post_message_ex(khm_int32 type, khm_int32 subtype,
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
*/
@@ -445,15 +511,21 @@ kmq_post_thread_quit_message(kmq_thread_id thread,
return KHM_ERROR_SUCCESS;
}
-/* TODO:Implement these */
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) {
- return (call->nCompleted + call->nFailed == call->nSent);
+ khm_boolean completed;
+
+ EnterCriticalSection(&cs_kmq_msg);
+ completed = (call->nCompleted + call->nFailed == call->nSent);
+ LeaveCriticalSection(&cs_kmq_msg);
+
+ return completed;
}
KHMEXP khm_int32 KHMAPI
@@ -481,3 +553,4 @@ kmq_set_completion_handler(khm_int32 type,
return kmqint_msg_type_set_handler(type, handler);
}
+
diff --git a/src/windows/identity/nidmgrdll/Makefile b/src/windows/identity/nidmgrdll/Makefile
index d18ac51..7525b91 100644
--- a/src/windows/identity/nidmgrdll/Makefile
+++ b/src/windows/identity/nidmgrdll/Makefile
@@ -91,6 +91,7 @@ OBJFILES= \
$(UIDIR)\acceldef.obj \
$(UIDIR)\configui.obj \
$(UIDIR)\trackerwnd.obj \
+ $(UIDIR)\uibind.obj \
$(UIDIR)\version.obj
RESFILES= \
@@ -119,5 +120,5 @@ $(DLLFILE): $(OBJFILES) $(RESFILES)
all: mkdirs $(DLLFILE)
clean::
- $(RM) $(DLLFILE)
- $(RM) $(DLLFILE).manifest
+ if exist '$(DLLFILE)' $(RM) $(DLLFILE)
+ if exist '$(DLLFILE).manifest' $(RM) $(DLLFILE).manifest
diff --git a/src/windows/identity/nidmgrdll/nidmgrdll.rc b/src/windows/identity/nidmgrdll/nidmgrdll.rc
index b091bdb..1f600b6 100644
--- a/src/windows/identity/nidmgrdll/nidmgrdll.rc
+++ b/src/windows/identity/nidmgrdll/nidmgrdll.rc
@@ -47,12 +47,12 @@ BEGIN
BEGIN
VALUE "CompanyName", KH_VERSTR_COMPANY_1033
VALUE "FileDescription", "Network Identity Manager API"
- VALUE "FileVersion", KH_VERSION_STRING
+ VALUE "FileVersion", KH_VERSTR_VERSION_1033
VALUE "InternalName", "nidmgr32"
VALUE "LegalCopyright", KH_VERSTR_COPYRIGHT_1033
VALUE "OriginalFilename", "nidmgr32.dll"
- VALUE "ProductName", KH_VERSTR_PRODUCT_1033
- VALUE "ProductVersion", KH_VERSTR_VERSION_1033
+ VALUE "ProductName", "Network Identity Manager"
+ VALUE "ProductVersion", KH_VERSTR_PRODUCT_1033
#ifdef KH_VERSTR_COMMENT_1033
VALUE "Comments", KH_VERSTR_COMMENT_1033
#endif
diff --git a/src/windows/identity/plugins/common/Makefile b/src/windows/identity/plugins/common/Makefile
index 5107edc..4e97c66 100644
--- a/src/windows/identity/plugins/common/Makefile
+++ b/src/windows/identity/plugins/common/Makefile
@@ -36,8 +36,8 @@ OBJFILES= \
all: mkdirs $(INCFILES) $(OBJFILES)
clean::
- $(RM) $(INCFILES)
- $(RM) $(OBJFILES)
+ if exist '..\..\obj' $(RM) $(INCFILES)
+ if exist '..\..\obj' $(RM) $(OBJFILES)
{}.c{$(LIBDIR)}.obj:
$(C2OBJ)
diff --git a/src/windows/identity/plugins/common/dynimport.c b/src/windows/identity/plugins/common/dynimport.c
index b3d7644..f49987c 100644
--- a/src/windows/identity/plugins/common/dynimport.c
+++ b/src/windows/identity/plugins/common/dynimport.c
@@ -144,6 +144,7 @@ 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);
@@ -160,12 +161,14 @@ 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);
@@ -289,6 +292,7 @@ FUNC_INFO k5_fi[] = {
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
};
@@ -305,12 +309,14 @@ FUNC_INFO profile_fi[] = {
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
};
diff --git a/src/windows/identity/plugins/common/dynimport.h b/src/windows/identity/plugins/common/dynimport.h
index a9561bc..7f3f598 100644
--- a/src/windows/identity/plugins/common/dynimport.h
+++ b/src/windows/identity/plugins/common/dynimport.h
@@ -30,7 +30,18 @@
/* 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;
@@ -256,6 +267,7 @@ 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);
@@ -272,12 +284,14 @@ 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);
diff --git a/src/windows/identity/plugins/common/krb5common.c b/src/windows/identity/plugins/common/krb5common.c
index 5ba59df..6c39586 100644
--- a/src/windows/identity/plugins/common/krb5common.c
+++ b/src/windows/identity/plugins/common/krb5common.c
@@ -90,8 +90,8 @@ khm_krb5_initialize(khm_handle ident,
return(0);
#else
- LPCSTR functionName;
- int freeContextFlag;
+ LPCSTR functionName = NULL;
+ int freeContextFlag = 0;
krb5_error_code rc = 0;
krb5_flags flags = 0;
@@ -164,8 +164,10 @@ khm_krb5_initialize(khm_handle ident,
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)
+ if (*cache != NULL) {
(*pkrb5_cc_close)(*ctx, *cache);
+ *cache = NULL;
+ }
}
return rc;
}
diff --git a/src/windows/identity/plugins/krb4/krb4funcs.c b/src/windows/identity/plugins/krb4/krb4funcs.c
index 306437a..b2b5fef 100644
--- a/src/windows/identity/plugins/krb4/krb4funcs.c
+++ b/src/windows/identity/plugins/krb4/krb4funcs.c
@@ -32,7 +32,6 @@ modified and adapted for NetIDMgr */
#define SECURITY_WIN32
#include <security.h>
-#include <ntsecapi.h>
#include <string.h>
#include <time.h>
diff --git a/src/windows/identity/plugins/krb4/krb4funcs.h b/src/windows/identity/plugins/krb4/krb4funcs.h
index 742d136..5ec11cc 100644
--- a/src/windows/identity/plugins/krb4/krb4funcs.h
+++ b/src/windows/identity/plugins/krb4/krb4funcs.h
@@ -35,7 +35,18 @@
#include <windows.h>
#define SECURITY_WIN32
#include <security.h>
-#include <ntsecapi.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>
diff --git a/src/windows/identity/plugins/krb4/krb4newcreds.c b/src/windows/identity/plugins/krb4/krb4newcreds.c
index 851f2e8..54feae5 100644
--- a/src/windows/identity/plugins/krb4/krb4newcreds.c
+++ b/src/windows/identity/plugins/krb4/krb4newcreds.c
@@ -55,33 +55,25 @@ typedef struct tag_k4_dlg_data {
time_t lifetime;
} k4_dlg_data;
-void k4_update_display(k4_dlg_data * d) {
- int i;
-
+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_PWD ), 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_PWD ), 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
- CheckDlgButton(d->hwnd, method_to_id[d->method], BST_CHECKED);
-
- for (i=0; i < ARRAYLENGTH(method_to_id); i++) {
- if (i != d->method && method_to_id[i] != 0)
- CheckDlgButton(d->hwnd, method_to_id[d->method],
- BST_UNCHECKED);
- }
+ 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);
}
@@ -103,7 +95,7 @@ void k4_update_data(k4_dlg_data * d) {
khui_cw_enable_type(d->nc, credtype_id_krb4, d->k4_enabled);
}
- d->method = 0;
+ 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) {
@@ -119,19 +111,16 @@ khm_boolean k4_should_identity_get_k4(khm_handle ident) {
khm_handle csp_ident = NULL;
khm_handle csp_k4 = NULL;
khm_boolean get_k4 = TRUE;
-
- if (KHM_SUCCEEDED(khc_read_int32(csp_params, L"Krb4NewCreds", &t)) &&
- !t)
- return FALSE;
+ 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. */
+ 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;
@@ -146,16 +135,27 @@ khm_boolean k4_should_identity_get_k4(khm_handle 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)) &&
- !t)
- get_k4 = FALSE;
+
+ 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);
}
- return get_k4;
+ /* 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) {
@@ -257,8 +257,9 @@ void k4_handle_wmnc_notify(k4_dlg_data * d,
kcdb_identity_get_flags(d->nc->identities[0], &flags);
- if (flags & KCDB_IDENT_FLAG_INVALID)
+ if (!(flags & KCDB_IDENT_FLAG_VALID)) {
break;
+ }
cb = sizeof(idname);
kcdb_identity_get_name(d->nc->identities[0], idname,
@@ -321,7 +322,7 @@ void k4_handle_wmnc_notify(k4_dlg_data * d,
case WMNC_IDENTITY_CHANGE:
k4_read_identity_data(d);
- k4_update_display(d);
+ k4_update_display(d, TRUE);
break;
case WMNC_CREDTEXT_LINK:
@@ -343,7 +344,7 @@ void k4_handle_wmnc_notify(k4_dlg_data * d,
if (!wcscmp(wids, L"Enable")) {
d->k4_enabled = TRUE;
- k4_update_display(d);
+ k4_update_display(d, TRUE);
khui_cw_enable_type(d->nc, credtype_id_krb4, TRUE);
}
}
@@ -378,17 +379,24 @@ INT_PTR CALLBACK k4_nc_dlg_proc(HWND hwnd,
d->k4_enabled = TRUE;
d->method = K4_METHOD_AUTO;
- k4_update_display(d);
+ k4_update_display(d, TRUE);
}
break;
case WM_COMMAND:
{
- d = (k4_dlg_data *) (LONG_PTR)
- GetWindowLongPtr(hwnd, DWLP_USER);
+ 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);
+ }
- k4_update_data(d);
- k4_update_display(d);
+ return TRUE;
+ }
}
break;
@@ -853,6 +861,9 @@ krb4_msg_newcred(khm_int32 msg_type, khm_int32 msg_subtype,
if (nct->name)
PFREE(nct->name);
+ if (nct->credtext)
+ PFREE(nct->credtext);
+
PFREE(nct);
}
break;
diff --git a/src/windows/identity/plugins/krb4/lang/en_us/langres.rc b/src/windows/identity/plugins/krb4/lang/en_us/langres.rc
index 865f010..12c3903 100644
--- a/src/windows/identity/plugins/krb4/lang/en_us/langres.rc
+++ b/src/windows/identity/plugins/krb4/lang/en_us/langres.rc
@@ -53,16 +53,16 @@ END
//
IDD_NC_KRB4 DIALOGEX 0, 0, 300, 166
-STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_SYSMENU
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD
EXSTYLE WS_EX_CONTROLPARENT
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
CONTROL "Kerberos v4 Ticket Options",IDC_STATIC,"Static",SS_LEFTNOWORDWRAP | SS_SUNKEN | WS_GROUP,7,7,286,11
- CONTROL "Obtain Kerberos v4 credentials",IDC_NCK4_OBTAIN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,26,97,10
+ CONTROL "Obtain Kerberos v4 credentials",IDC_NCK4_OBTAIN,"Button",BS_AUTOCHECKBOX | BS_NOTIFY | WS_TABSTOP,7,26,128,10
GROUPBOX "Obtain Kerberos v4 credentials using",IDC_STATIC,7,43,286,72,WS_GROUP
- CONTROL "Automatically determine method",IDC_NCK4_AUTO,"Button",BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,23,58,119,10
- CONTROL "Kerberos v5 to v4 translation",IDC_NCK4_K524,"Button",BS_AUTORADIOBUTTON,23,76,101,10
- CONTROL "Password",IDC_NCK4_PWD,"Button",BS_AUTORADIOBUTTON,23,94,47,10
+ CONTROL "Automatically determine method",IDC_NCK4_AUTO,"Button",BS_AUTORADIOBUTTON,22,59,119,10
+ CONTROL "Kerberos v5 to v4 translation",IDC_NCK4_K524,"Button",BS_AUTORADIOBUTTON,22,76,109,10
+ CONTROL "Password",IDC_NCK4_PWD,"Button",BS_AUTORADIOBUTTON,22,93,47,10
END
IDD_CFG_KRB4 DIALOGEX 0, 0, 255, 182
@@ -95,7 +95,7 @@ EXSTYLE WS_EX_CONTROLPARENT
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
CONTROL "Obtain Kerberos v4 credentials for this identity",IDC_CFG_GETTIX,
- "Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,7,7,147,10
+ "Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,7,7,165,10
END
@@ -202,3 +202,4 @@ END
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED
+
diff --git a/src/windows/identity/plugins/krb4/langres.h b/src/windows/identity/plugins/krb4/langres.h
index 2cf0de1..c78ae41 100644
--- a/src/windows/identity/plugins/krb4/langres.h
+++ b/src/windows/identity/plugins/krb4/langres.h
@@ -2,76 +2,27 @@
// 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 IDS_UNK_ADDR_FMT 101
-#define IDS_KRB5_CREDTEXT_0 102
#define IDD_NC_KRB4 103
#define IDS_PLUGIN_DESC 103
-#define IDS_KEY_ENCTYPE_SHORT_DESC 104
#define IDD_CFG_KRB4 104
#define IDS_NC_K4_SHORT 104
-#define IDS_TKT_ENCTYPE_SHORT_DESC 105
#define IDS_ERR_REALM 105
#define IDD_CFG_IDS_KRB4 105
-#define IDS_KEY_ENCTYPE_LONG_DESC 106
#define IDS_ERR_PRINCIPAL 106
#define IDD_CFG_ID_KRB4 106
-#define IDS_TKT_ENCTYPE_LONG_DESC 107
#define IDS_ERR_INVINST 107
-#define IDI_ICON1 107
#define IDI_PLUGIN 107
-#define IDS_ADDR_LIST_SHORT_DESC 108
#define IDS_ERR_PWINTKT 108
-#define IDS_ADDR_LIST_LONG_DESC 109
#define IDS_CT_DISABLED 109
-#define IDS_ETYPE_NULL 110
#define IDS_CT_TGTFOR 110
-#define IDS_ETYPE_DES_CBC_CRC 111
#define IDS_METHOD_AUTO 111
-#define IDS_ETYPE_DES_CBC_MD4 112
#define IDS_METHOD_PWD 112
-#define IDS_ETYPE_DES_CBC_MD5 113
#define IDS_METHOD_K524 113
-#define IDS_ETYPE_DES_CBC_RAW 114
#define IDS_CFG_IDS_KRB4_SHORT 114
-#define IDS_ETYPE_DES3_CBC_SHA 115
-#define IDS_ETYPE_DES3_CBC_RAW 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_CFG_KRB4_LONG 135
#define IDS_CFG_KRB4_SHORT 136
-#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_CACHE 1025
#define IDC_CFG_LBL_CFGFILE 1026
#define IDC_CFG_LBL_RLMPATH 1027
@@ -81,9 +32,9 @@
#define IDC_CFG_CFGBROW 1031
#define IDC_CFG_RLMBROW 1032
#define IDC_NCK4_OBTAIN 1033
-#define IDC_NCK4_PWD 1034
+#define IDC_NCK4_AUTO 1034
#define IDC_NCK4_K524 1035
-#define IDC_NCK4_AUTO 1036
+#define IDC_NCK4_PWD 1036
#define IDC_CFG_GETTIX 1037
// Next default values for new objects
@@ -92,7 +43,7 @@
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 108
#define _APS_NEXT_COMMAND_VALUE 40001
-#define _APS_NEXT_CONTROL_VALUE 1039
+#define _APS_NEXT_CONTROL_VALUE 1043
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
diff --git a/src/windows/identity/plugins/krb5/krb5configdlg.c b/src/windows/identity/plugins/krb5/krb5configdlg.c
index 9c8af5d..36936cd 100644
--- a/src/windows/identity/plugins/krb5/krb5configdlg.c
+++ b/src/windows/identity/plugins/krb5/krb5configdlg.c
@@ -120,35 +120,6 @@ typedef struct tag_k5_config_data {
#define K5_CDFLAG_MOD_INC_REALMS 0x00000100
#define K5_CDFLAG_MOD_REALMS 0x00001000
-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
-k5_parse_boolean(const char *s)
-{
- const char *const *p;
-
- for(p=conf_yes; *p; p++) {
- if (!_stricmp(*p,s))
- return 1;
- }
-
- for(p=conf_no; *p; p++) {
- if (!_stricmp(*p,s))
- return 0;
- }
-
- /* Default to "no" */
- return 0;
-}
-
void
k5_init_config_data(k5_config_data * d) {
ZeroMemory(d, sizeof(*d));
@@ -263,6 +234,7 @@ k5_is_profile_loaded(void) {
assert(pprofile_add_relation);
assert(pprofile_update_relation);
assert(pprofile_flush);
+ assert(pprofile_rename_section);
#endif
if (!pprofile_init ||
@@ -276,7 +248,8 @@ k5_is_profile_loaded(void) {
!pprofile_clear_relation ||
!pprofile_add_relation ||
!pprofile_update_relation ||
- !pprofile_flush)
+ !pprofile_flush ||
+ !pprofile_rename_section)
return FALSE;
@@ -325,7 +298,12 @@ k5_read_config_data(k5_config_data * d) {
rv = pprofile_get_string(profile, "libdefaults", "dns_lookup_kdc",
NULL, NULL, &boolv);
if (!rv && boolv) {
- d->dns_lookup_kdc = k5_parse_boolean(boolv);
+ khm_boolean b;
+
+ if (!khm_krb5_parse_boolean(boolv, &b))
+ d->dns_lookup_kdc = b;
+ else
+ d->dns_lookup_kdc = FALSE;
pprofile_release_string(boolv);
} else
d->dns_lookup_kdc = FALSE;
@@ -333,7 +311,12 @@ k5_read_config_data(k5_config_data * d) {
rv = pprofile_get_string(profile, "libdefaults", "dns_lookup_realm",
NULL, NULL, &boolv);
if (!rv && boolv) {
- d->dns_lookup_realm = k5_parse_boolean(boolv);
+ khm_boolean b;
+
+ if (!khm_krb5_parse_boolean(boolv, &b))
+ d->dns_lookup_realm = b;
+ else
+ d->dns_lookup_realm = FALSE;
pprofile_release_string(boolv);
} else
d->dns_lookup_realm = FALSE;
@@ -341,7 +324,12 @@ k5_read_config_data(k5_config_data * d) {
rv = pprofile_get_string(profile, "libdefaults", "dns_fallback",
NULL, NULL, &boolv);
if (!rv && boolv) {
- d->dns_fallback = k5_parse_boolean(boolv);
+ khm_boolean b;
+
+ if (!khm_krb5_parse_boolean(boolv, &b))
+ d->dns_fallback = b;
+ else
+ d->dns_fallback = FALSE;
pprofile_release_string(boolv);
} else
d->dns_fallback = FALSE;
@@ -349,7 +337,12 @@ k5_read_config_data(k5_config_data * d) {
rv = pprofile_get_string(profile, "libdefaults", "noaddresses",
NULL, NULL, &boolv);
if (!rv && boolv) {
- d->noaddresses = k5_parse_boolean(boolv);
+ khm_boolean b;
+
+ if (!khm_krb5_parse_boolean(boolv, &b))
+ d->noaddresses = b;
+ else
+ d->noaddresses = TRUE;
pprofile_release_string(boolv);
} else
d->noaddresses = TRUE;
@@ -538,7 +531,7 @@ k5_read_config_data(k5_config_data * d) {
d->flags = 0;
}
-void
+int
k5_write_config_data(k5_config_data * d) {
char astr[MAX_PATH * 2];
char config_file[MAX_PATH];
@@ -546,22 +539,25 @@ k5_write_config_data(k5_config_data * d) {
const char *filenames[2];
long rv;
khm_size s;
+ int applied = FALSE;
if (d->flags == 0)
- return;
+ return FALSE;
if (!k5_is_profile_loaded())
- return;
+ return FALSE;
/* write the MSLSA import setting */
if (d->flags & K5_CDFLAG_MOD_LSA_IMPORT) {
khc_write_int32(csp_params, L"MsLsaImport", d->lsa_import);
d->flags &= ~K5_CDFLAG_MOD_LSA_IMPORT;
+ applied = TRUE;
}
if (d->flags & K5_CDFLAG_MOD_INC_REALMS) {
khc_write_int32(csp_params, L"UseFullRealmList", d->inc_realms);
d->flags &= ~K5_CDFLAG_MOD_INC_REALMS;
+ applied = TRUE;
}
if (!(d->flags &
@@ -575,7 +571,7 @@ k5_write_config_data(k5_config_data * d) {
K5_CDFLAG_MOD_REALMS))) {
d->flags = 0;
- return;
+ return applied;
}
khm_krb5_get_profile_file(config_file, ARRAYLENGTH(config_file));
@@ -629,6 +625,7 @@ k5_write_config_data(k5_config_data * d) {
rv = pprofile_add_relation(profile, sec_libdefaults,
defrealm);
+ applied = TRUE;
}
d->flags &= ~K5_CDFLAG_MOD_DEF_REALM;
}
@@ -641,9 +638,10 @@ k5_write_config_data(k5_config_data * d) {
rv = pprofile_add_relation(profile, sec_libdefaults,
(d->dns_lookup_kdc)?
- conf_yes[0]:
- conf_no[0]);
+ KRB5_CONF_YES:
+ KRB5_CONF_NO);
d->flags &= ~K5_CDFLAG_MOD_DNS_LOOKUP_KDC;
+ applied = TRUE;
}
if (d->flags & K5_CDFLAG_MOD_DNS_LOOKUP_RLM) {
@@ -654,10 +652,11 @@ k5_write_config_data(k5_config_data * d) {
rv = pprofile_add_relation(profile, sec_libdefaults,
(d->dns_lookup_realm)?
- conf_yes[0]:
- conf_no[0]);
+ KRB5_CONF_YES:
+ KRB5_CONF_NO);
d->flags &= ~K5_CDFLAG_MOD_DNS_LOOKUP_RLM;
+ applied = TRUE;
}
if (d->flags & K5_CDFLAG_MOD_DNS_FALLBACK) {
@@ -668,10 +667,11 @@ k5_write_config_data(k5_config_data * d) {
rv = pprofile_add_relation(profile, sec_libdefaults,
(d->dns_fallback)?
- conf_yes[0]:
- conf_no[0]);
+ KRB5_CONF_YES:
+ KRB5_CONF_NO);
d->flags &= ~K5_CDFLAG_MOD_DNS_FALLBACK;
+ applied = TRUE;
}
if (d->flags & K5_CDFLAG_MOD_NOADDRESSES) {
@@ -682,10 +682,11 @@ k5_write_config_data(k5_config_data * d) {
rv = pprofile_add_relation(profile, sec_libdefaults,
(d->noaddresses)?
- conf_yes[0]:
- conf_no[0]);
+ KRB5_CONF_YES:
+ KRB5_CONF_NO);
d->flags &= ~K5_CDFLAG_MOD_NOADDRESSES;
+ applied = TRUE;
}
/* now we look at the [realms] section */
@@ -735,7 +736,10 @@ k5_write_config_data(k5_config_data * d) {
pprofile_add_relation(profile, sec_admin,
host);
- d->realms[r].kdcs[k].flags &= ~K5_RKFLAG_NEW;
+ d->realms[r].kdcs[k].flags &= ~ (K5_RKFLAG_NEW |
+ K5_RKFLAG_MOD_MASTER |
+ K5_RKFLAG_MOD_ADMIN);
+ applied = TRUE;
}
}
@@ -754,6 +758,7 @@ k5_write_config_data(k5_config_data * d) {
is deleted and not in the profile file
anymore. */
d->realms[r].domain_maps[m].flags |= K5_DMFLAG_NEW;
+ applied = TRUE;
} else if (!(d->realms[r].domain_maps[m].flags &
K5_DMFLAG_DELETED) &&
(d->realms[r].domain_maps[m].flags &
@@ -762,10 +767,12 @@ k5_write_config_data(k5_config_data * d) {
realm);
d->realms[r].domain_maps[m].flags &= ~K5_DMFLAG_NEW;
+ applied = TRUE;
}
}
- d->realms[r].flags &= ~K5_RDFLAG_NEW;
+ d->realms[r].flags &= ~(K5_RDFLAG_NEW |
+ K5_RDFLAG_MODIFED);
} else if ((d->realms[r].flags & K5_RDFLAG_DELETED) &&
!(d->realms[r].flags & K5_RDFLAG_NEW)) {
@@ -783,7 +790,10 @@ k5_write_config_data(k5_config_data * d) {
sec_all[2] = values[v];
pprofile_clear_relation(profile, sec_all);
}
+ sec_all[2] = NULL;
+ pprofile_rename_section(profile, sec_all, NULL);
pprofile_free_list(values);
+ applied = TRUE;
}
rv = pprofile_get_relation_names(profile, sec_domain_realm,
@@ -803,6 +813,7 @@ k5_write_config_data(k5_config_data * d) {
values[v]);
pprofile_clear_relation(profile,
sec_domain_map);
+ applied = TRUE;
}
pprofile_release_string(maprealm);
}
@@ -815,7 +826,8 @@ k5_write_config_data(k5_config_data * d) {
deleted and is not in the profile file. */
d->realms[r].flags |= K5_RDFLAG_NEW;
- } else if (!(d->realms[r].flags & K5_RDFLAG_DELETED)) {
+ } else if (!(d->realms[r].flags & K5_RDFLAG_DELETED) &&
+ (d->realms[r].flags & K5_RDFLAG_MODIFED)) {
khm_size k;
khm_size m;
@@ -839,6 +851,8 @@ k5_write_config_data(k5_config_data * d) {
pprofile_update_relation(profile, sec_master,
host, NULL);
+ applied = TRUE;
+
/* as above, setting 'new' flag to indicate
that the item does not exist in the profile
file. */
@@ -858,7 +872,10 @@ k5_write_config_data(k5_config_data * d) {
pprofile_add_relation(profile, sec_admin,
host);
- d->realms[r].kdcs[k].flags &= ~K5_RKFLAG_NEW;
+ d->realms[r].kdcs[k].flags &= ~(K5_RKFLAG_NEW |
+ K5_RKFLAG_MOD_ADMIN |
+ K5_RKFLAG_MOD_MASTER);
+ applied = TRUE;
continue;
}
@@ -873,6 +890,7 @@ k5_write_config_data(k5_config_data * d) {
host);
}
+ applied = TRUE;
d->realms[r].kdcs[k].flags &= ~K5_RKFLAG_MOD_MASTER;
}
@@ -887,6 +905,7 @@ k5_write_config_data(k5_config_data * d) {
host, NULL);
}
+ applied = TRUE;
d->realms[r].kdcs[k].flags &= ~K5_RKFLAG_MOD_ADMIN;
}
}
@@ -904,6 +923,7 @@ k5_write_config_data(k5_config_data * d) {
pprofile_clear_relation(profile, sec_domain_map);
d->realms[r].domain_maps[m].flags |= K5_DMFLAG_NEW;
+ applied = TRUE;
} else if (!(d->realms[r].domain_maps[m].flags &
K5_DMFLAG_DELETED) &&
@@ -914,6 +934,8 @@ k5_write_config_data(k5_config_data * d) {
pprofile_add_relation(profile, sec_domain_map,
realm);
d->realms[r].domain_maps[m].flags &= ~K5_DMFLAG_NEW;
+ applied = TRUE;
+
}
}
@@ -954,6 +976,8 @@ k5_write_config_data(k5_config_data * d) {
}
d->flags = 0;
+
+ return applied;
}
/* actual dialog stuff */
@@ -1208,13 +1232,14 @@ k5_config_dlgproc(HWND hwnd,
if (HIWORD(wParam) == WMCFG_APPLY) {
khm_int32 oflags;
+ int applied;
oflags = d->flags;
- k5_write_config_data(d);
+ applied = k5_write_config_data(d);
if (d->flags != oflags) {
khui_cfg_set_flags(d->node_main,
- KHUI_CNFLAG_APPLIED,
+ (applied ? KHUI_CNFLAG_APPLIED : 0),
KHUI_CNFLAG_APPLIED |
KHUI_CNFLAG_MODIFIED);
}
@@ -2673,12 +2698,11 @@ k5_realms_dlgproc(HWND hwnd,
case KHUI_WM_CFG_NOTIFY:
/* the realms dialog receives this notification after the top
- level krb5 configuration panel has received it. Therefore,
- we assume that any changes have already been applied. When
- applying changes, we switch the mod bits off to indicate
- that the changes have been written. We just have to
- repaint the screen at this point. */
+ level krb5 configuration panel has received it. */
if (HIWORD(wParam) == WMCFG_APPLY) {
+ int applied;
+
+ applied = k5_write_config_data(d);
k5_purge_config_data(d, TRUE, TRUE, TRUE);
k5_update_realms_display(GetDlgItem(hwnd, IDC_CFG_REALMS), d);
if (d->c_realm != -1) {
@@ -2688,6 +2712,10 @@ k5_realms_dlgproc(HWND hwnd,
k5_update_kdcs_display(GetDlgItem(hwnd, IDC_CFG_KDC), NULL, 0);
k5_update_dmap_display(GetDlgItem(hwnd, IDC_CFG_DMAP), NULL, 0);
}
+ khui_cfg_set_flags(d->node_realm,
+ (applied ? KHUI_CNFLAG_APPLIED : 0),
+ KHUI_CNFLAG_APPLIED);
+
}
break;
}
diff --git a/src/windows/identity/plugins/krb5/krb5configids.c b/src/windows/identity/plugins/krb5/krb5configids.c
index afd86e5..5f47292 100644
--- a/src/windows/identity/plugins/krb5/krb5configids.c
+++ b/src/windows/identity/plugins/krb5/krb5configids.c
@@ -31,6 +31,11 @@
#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;
@@ -48,6 +53,10 @@ typedef struct tag_k5_ids_dlg_data {
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
@@ -57,7 +66,10 @@ k5_ids_is_mod(k5_ids_dlg_data * d) {
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->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;
}
@@ -96,6 +108,9 @@ k5_ids_write_params(k5_ids_dlg_data * d) {
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
@@ -106,36 +121,23 @@ k5_ids_write_params(k5_ids_dlg_data * d) {
static void
k5_ids_read_params(k5_ids_dlg_data * d) {
- khm_int32 t;
- khm_int32 rv;
-
-#ifdef DEBUG
- assert(csp_params);
-#endif
+ k5_params p;
- rv = khc_read_int32(csp_params, L"DefaultLifetime", &t);
- assert(KHM_SUCCEEDED(rv));
- d->life = t;
+ khm_krb5_get_identity_params(NULL, &p);
- rv = khc_read_int32(csp_params, L"DefaultRenewLifetime", &t);
- assert(KHM_SUCCEEDED(rv));
- d->renew_life = t;
+ d->life = p.lifetime;
+ d->life_max = p.lifetime_max;
+ d->life_min = p.lifetime_min;
- rv = khc_read_int32(csp_params, L"MaxLifetime", &t);
- assert(KHM_SUCCEEDED(rv));
- d->life_max = t;
+ d->renew_life = p.renew_life;
+ d->renew_max = p.renew_life_max;
+ d->renew_min = p.renew_life_min;
- rv = khc_read_int32(csp_params, L"MinLifetime", &t);
- assert(KHM_SUCCEEDED(rv));
- d->life_min = t;
+ d->opt_saved.forwardable = p.forwardable;
+ d->opt_saved.renewable = p.renewable;
+ d->opt_saved.addressless = p.addressless;
- rv = khc_read_int32(csp_params, L"MaxRenewLifetime", &t);
- assert(KHM_SUCCEEDED(rv));
- d->renew_max = t;
-
- rv = khc_read_int32(csp_params, L"MinRenewLifetime", &t);
- assert(KHM_SUCCEEDED(rv));
- d->renew_min = t;
+ d->opt = d->opt_saved;
khui_tracker_initialize(&d->tc_life);
d->tc_life.current = d->life;
@@ -209,6 +211,10 @@ k5_ids_tab_dlgproc(HWND hwnd,
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:
@@ -217,6 +223,22 @@ k5_ids_tab_dlgproc(HWND hwnd,
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;
@@ -245,3 +267,4 @@ k5_ids_tab_dlgproc(HWND hwnd,
return FALSE;
}
+
diff --git a/src/windows/identity/plugins/krb5/krb5funcs.c b/src/windows/identity/plugins/krb5/krb5funcs.c
index 8cf2b86..e66e755 100644
--- a/src/windows/identity/plugins/krb5/krb5funcs.c
+++ b/src/windows/identity/plugins/krb5/krb5funcs.c
@@ -33,7 +33,6 @@
#define SECURITY_WIN32
#include <security.h>
-#include <ntsecapi.h>
#include <string.h>
#include <time.h>
@@ -229,9 +228,91 @@ typedef struct tag_identlist {
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 *
@@ -287,42 +368,102 @@ tc_add_ident_to_list(identlist * idlist, khm_handle ident) {
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
- kcdb_identity_set_attr(idlist->list[i].ident,
- attr_id_krb5_ccname,
- idlist->list[i].ccname,
- KCDB_CBSIZE_AUTO);
+ 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,
- KCDB_ATTR_EXPIRE,
- &idlist->list[i].ft_expire,
- sizeof(idlist->list[i].ft_expire));
+ 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_ISSUE,
- &idlist->list[i].ft_issue,
- sizeof(idlist->list[i].ft_issue));
+ 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,
- attr_id_krb5_flags,
- &idlist->list[i].krb5_flags,
- sizeof(idlist->list[i].krb5_flags));
+ kcdb_identity_set_attr(idlist->list[i].ident,
+ KCDB_ATTR_ISSUE,
+ &idlist->list[i].ft_issue,
+ sizeof(idlist->list[i].ft_issue));
- 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);
+ 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 {
- kcdb_identity_set_attr(idlist->list[i].ident,
- KCDB_ATTR_RENEW_EXPIRE,
- &idlist->list[i].ft_renewexpire,
- sizeof(idlist->list[i].ft_renewexpire));
+ /* 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. */
+ }
}
}
}
@@ -919,7 +1060,7 @@ khm_krb5_renew_cred(khm_handle cred)
#endif
if (strlen("krbtgt") != krb5_princ_name(ctx, server)->length ||
- strncmp("krbtgt", krb5_princ_name(ctx, server)->data, 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) {
@@ -1004,8 +1145,8 @@ khm_krb5_renew_ident(khm_handle identity)
krb5_creds my_creds;
krb5_data *realm = NULL;
wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
- char cidname[KCDB_IDENT_MAXCCH_NAME];
khm_size cb;
+ khm_int32 k5_flags;
memset(&my_creds, 0, sizeof(krb5_creds));
@@ -1016,19 +1157,129 @@ khm_krb5_renew_ident(khm_handle identity)
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 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 = 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);
@@ -1917,7 +2168,8 @@ IsKerberosLogon(VOID)
BOOL
-khm_krb5_ms2mit(char * match_princ, BOOL match_realm, BOOL save_creds)
+khm_krb5_ms2mit(char * match_princ, BOOL match_realm, BOOL save_creds,
+ khm_handle * ret_ident)
{
#ifdef NO_KRB5
return(FALSE);
@@ -2002,11 +2254,11 @@ khm_krb5_ms2mit(char * match_princ, BOOL match_realm, BOOL save_creds)
wname[0] = L'\0';
- kcdb_identity_get_config(ident, 0, &idconfig);
+ kcdb_identity_get_config(ident, KHM_FLAG_CREATE, &idconfig);
if (idconfig == NULL)
goto _done_checking_config;
- khc_open_space(idconfig, CSNAME_KRB5CRED, 0, &k5config);
+ khc_open_space(idconfig, CSNAME_KRB5CRED, KHM_FLAG_CREATE, &k5config);
if (k5config == NULL)
goto _done_checking_config;
@@ -2059,9 +2311,15 @@ khm_krb5_ms2mit(char * match_princ, BOOL match_realm, BOOL save_creds)
/* 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)))
@@ -2092,6 +2350,9 @@ cleanup:
pkrb5_cc_close(kcontext, mslsa_ccache);
if (kcontext)
pkrb5_free_context(kcontext);
+ if (ident)
+ kcdb_identity_release(ident);
+
return(rc);
#endif /* NO_KRB5 */
}
@@ -2389,6 +2650,10 @@ khm_krb5_get_default_realm(void)
char * def = 0;
pkrb5_init_context(&ctx);
+
+ if (ctx == 0)
+ return NULL;
+
pkrb5_get_default_realm(ctx,&def);
if (def) {
@@ -2575,7 +2840,7 @@ khm_krb5_set_identity_flags(khm_handle identity,
}
t &= ~flag_mask;
- t |= flag_value | flag_mask;
+ t |= (flag_value & flag_mask);
kcdb_identity_set_attr(identity,
attr_id_krb5_idflags,
@@ -2612,3 +2877,611 @@ khm_krb5_get_temp_ccache(krb5_context ctx,
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 ece4f79..b4ab452 100644
--- a/src/windows/identity/plugins/krb5/krb5funcs.h
+++ b/src/windows/identity/plugins/krb5/krb5funcs.h
@@ -35,7 +35,18 @@
#include <windows.h>
#define SECURITY_WIN32
#include <security.h>
-#include <ntsecapi.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>
@@ -50,12 +61,55 @@
#define KRB5_MAXCCH_CCNAME 1024
-// Function Prototypes.
+#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);
+ BOOL save_creds,
+ khm_handle * ret_ident);
int
khm_krb5_kinit(krb5_context alt_ctx,
@@ -92,36 +146,23 @@ khm_krb5_renew_cred(khm_handle cred);
int
khm_krb5_renew_ident(khm_handle identity);
-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);
-
long
khm_krb5_list_tickets(krb5_context *krbv5Context);
-long
-khm_krb4_list_tickets(void);
-
-wchar_t *
-khm_get_realm_from_princ(wchar_t * princ);
-
long
khm_krb5_copy_ccache_by_name(krb5_context in_ctx,
wchar_t * wscc_dest,
wchar_t * wscc_src);
long
-khm_krb5_canon_cc_name(wchar_t * wcc_name,
- size_t cb_cc_name);
+khm_krb5_get_temp_ccache(krb5_context ctx,
+ krb5_ccache * cc);
-int
-khm_krb5_cc_name_cmp(const wchar_t * cc_name_1,
- const wchar_t * cc_name_2);
+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);
@@ -129,8 +170,19 @@ khm_krb5_get_profile_file(LPSTR confname, UINT szConfname);
BOOL
khm_krb5_get_temp_profile_file(LPSTR confname, UINT szConfname);
-khm_int32 KHMAPI
-khm_krb5_creds_is_equal(khm_handle vcred1, khm_handle vcred2, void * dummy);
+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,
@@ -140,7 +192,26 @@ khm_krb5_set_identity_flags(khm_handle identity,
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_get_temp_ccache(krb5_context ctx,
- krb5_ccache * cc);
+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 43d6d3d..0072b96 100644
--- a/src/windows/identity/plugins/krb5/krb5identpro.c
+++ b/src/windows/identity/plugins/krb5/krb5identpro.c
@@ -461,7 +461,7 @@ ui_cb(khui_new_creds * nc,
(L"COMBOBOX",
L"",
CBS_DROPDOWN | CBS_AUTOHSCROLL | CBS_SORT |
- WS_CHILD | WS_VISIBLE | WS_TABSTOP,
+ WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL,
0, 0, 100, 100, /* bogus values */
hw_parent,
(HMENU) K5_NCID_UN,
@@ -502,7 +502,7 @@ ui_cb(khui_new_creds * nc,
(L"COMBOBOX",
L"",
CBS_DROPDOWN | CBS_AUTOHSCROLL | CBS_SORT |
- WS_CHILD | WS_VISIBLE | WS_TABSTOP,
+ WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL,
0, 0, 100, 100, /* bogus */
hw_parent,
(HMENU) K5_NCID_REALM,
@@ -742,7 +742,7 @@ ui_cb(khui_new_creds * nc,
}
static khm_int32
-k5_ident_valiate_name(khm_int32 msg_type,
+k5_ident_validate_name(khm_int32 msg_type,
khm_int32 msg_subtype,
khm_ui_4 uparam,
void * vparam) {
@@ -802,6 +802,107 @@ k5_update_last_default_identity(khm_handle ident) {
}
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,
@@ -815,14 +916,7 @@ k5_ident_set_default(khm_int32 msg_type,
if (uparam) {
/* an identity is being made default */
khm_handle def_ident = (khm_handle) vparam;
- 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];
+ khm_int32 rv;
#ifdef DEBUG
assert(def_ident != NULL);
@@ -840,84 +934,11 @@ k5_ident_set_default(khm_int32 msg_type,
_describe();
}
- cb = sizeof(id_ccname);
- if (KHM_FAILED(kcdb_identity_get_attr(def_ident,
- attr_id_krb5_ccname,
- NULL,
- id_ccname,
- &cb))) {
- _reportf(L"The specified identity does not have the Krb5CCName property");
- _end_task();
- return KHM_ERROR_NOT_FOUND;
- }
-
- 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);
- }
+ rv = k5_ident_set_default_int(def_ident);
- RegCloseKey(hk_ccname);
+ _end_task();
- if (l == ERROR_SUCCESS) {
- _reportf(L"Successfully set the default ccache");
- k5_update_last_default_identity(def_ident);
- _end_task();
- return KHM_ERROR_SUCCESS;
- } else {
- _reportf(L"Can't set the registry value : %d", l);
- _end_task();
- return KHM_ERROR_UNKNOWN;
- }
+ return rv;
} else {
/* the default identity is being forgotten */
@@ -1354,10 +1375,102 @@ k5_ident_init(khm_int32 msg_type,
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;
}
@@ -1422,10 +1535,10 @@ k5_msg_ident(khm_int32 msg_type,
vparam);
case KMSG_IDENT_VALIDATE_NAME:
- return k5_ident_valiate_name(msg_type,
- msg_subtype,
- uparam,
- vparam);
+ return k5_ident_validate_name(msg_type,
+ msg_subtype,
+ uparam,
+ vparam);
case KMSG_IDENT_VALIDATE_IDENTITY:
/* TODO: handle KMSG_IDENT_VALIDATE_IDENTITY */
@@ -1533,6 +1646,8 @@ DWORD WINAPI k5_ccname_monitor_thread(LPVOID lpParameter) {
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,
diff --git a/src/windows/identity/plugins/krb5/krb5newcreds.c b/src/windows/identity/plugins/krb5/krb5newcreds.c
index 087d937..edd6472 100644
--- a/src/windows/identity/plugins/krb5/krb5newcreds.c
+++ b/src/windows/identity/plugins/krb5/krb5newcreds.c
@@ -635,19 +635,41 @@ k5_kinit_fiber_proc(PVOID lpParameter)
_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.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:
@@ -753,19 +775,9 @@ k5_cached_kinit_prompter(void) {
/* already expired */
goto _cleanup;
} else {
- FILETIME lifetime;
- khm_int32 t;
-
- /* make the cache expire at some point */
- GetSystemTimeAsFileTime(&current);
- khc_read_int32(csp_params, L"PromptCacheLifetime", &t);
- if (t == 0)
- t = 172800; /* 48 hours */
- TimetToFileTimeInterval(t, &lifetime);
- expiry = FtAdd(&current, &lifetime);
- iexpiry = FtToInt(&expiry);
-
- khc_write_int64(csp_prcache, L"ExpiresOn", iexpiry);
+ /* if there is no value for ExpiresOn, we assume the prompts
+ have already expired. */
+ goto _cleanup;
}
/* we found a prompt cache. We take this to imply that the
@@ -946,7 +958,20 @@ k5_kinit_prompter(krb5_context context,
#endif
/* we got prompts? Then we assume that the principal is valid */
- g_fjob.valid_principal = TRUE;
+
+ 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;
@@ -1132,9 +1157,16 @@ k5_kinit_prompter(krb5_context context,
(khm_int32) num_prompts);
GetSystemTimeAsFileTime(&current);
+#ifdef USE_PROMPT_CACHE_LIFETIME
khc_read_int32(csp_params, L"PromptCacheLifetime", &t);
if (t == 0)
t = 172800; /* 48 hours */
+#else
+ khc_read_int32(csp_params, L"MaxRenewLifetime", &t);
+ if (t == 0)
+ t = 2592000; /* 30 days */
+ t += 604800; /* + 7 days */
+#endif
TimetToFileTimeInterval(t, &lifetime);
expiry = FtAdd(&current, &lifetime);
iexpiry = FtToInt(&expiry);
@@ -1198,7 +1230,7 @@ k5_kinit_prompter(krb5_context context,
actual acquisition of credentials. */
if(g_fjob.command != FIBER_CMD_CONTINUE &&
g_fjob.command != FIBER_CMD_KINIT) {
- code = -2;
+ code = KRB5_LIBOS_PWDINTR;
goto _exit;
}
@@ -1241,164 +1273,32 @@ k5_kinit_prompter(krb5_context context,
/* entering a NULL password is equivalent to cancelling out */
if (g_fjob.null_password)
- return -2;
+ return KRB5_LIBOS_PWDINTR;
else
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
-k5_open_config_handle(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 done;
-
- rv = khc_open_space(csp_i, CSNAME_KRB5CRED, flags, &csp_ik5);
- if (KHM_FAILED(rv))
- goto done;
-
- 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_realm)
- rv = khc_shadow_space(csp_ik5, csp_realm);
- else
- rv = khc_shadow_space(csp_ik5, csp_params);
-
- csp_rv = csp_ik5;
-
- } else {
-
- /* No valid identity specified. We default to the parameters key. */
- 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;
+void
+k5_read_dlg_params(k5_dlg_data * d, khm_handle identity)
+{
+ k5_params p;
- /* 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);
- if (csp_realm)
- khc_close_space(csp_realm);
- if (csp_plugins)
- khc_close_space(csp_plugins);
- if (csp_krbcfg)
- khc_close_space(csp_krbcfg);
+ khm_krb5_get_identity_params(identity, &p);
- return rv;
-}
+ d->renewable = p.renewable;
+ d->forwardable = p.forwardable;
+ d->proxiable = p.proxiable;
+ d->addressless = p.addressless;
+ d->publicIP = p.publicIP;
-void
-k5_read_dlg_params(khm_handle conf,
- k5_dlg_data * d)
-{
- khm_int32 i;
+ d->tc_lifetime.current = p.lifetime;
+ d->tc_lifetime.max = p.lifetime_max;
+ d->tc_lifetime.min = p.lifetime_min;
- khc_read_int32(conf, L"Renewable", &i);
- d->renewable = i;
- khc_read_int32(conf, L"Forwardable", &i);
- d->forwardable = i;
- khc_read_int32(conf, L"Proxiable", &i);
- d->proxiable = i;
- khc_read_int32(conf, L"Addressless", &i);
- d->addressless = i;
- khc_read_int32(conf, L"PublicIP", &i);
- d->publicIP = i;
-
- khc_read_int32(conf, L"DefaultLifetime", &i);
- d->tc_lifetime.current = i;
- khc_read_int32(conf, L"MaxLifetime", &i);
- d->tc_lifetime.max = i;
- khc_read_int32(conf, L"MinLifetime", &i);
- d->tc_lifetime.min = i;
-
- khc_read_int32(conf, L"DefaultRenewLifetime", &i);
- d->tc_renew.current = i;
- khc_read_int32(conf, L"MaxRenewLifetime", &i);
- d->tc_renew.max = i;
- khc_read_int32(conf, L"MinRenewLifetime", &i);
- d->tc_renew.min = i;
+ 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. */
@@ -1431,28 +1331,32 @@ k5_read_dlg_params(khm_handle conf,
}
void
-k5_write_dlg_params(khm_handle conf,
- k5_dlg_data * d)
+k5_write_dlg_params(k5_dlg_data * d, khm_handle identity)
{
- khc_write_int32(conf, L"Renewable", d->renewable);
- khc_write_int32(conf, L"Forwardable", d->forwardable);
- khc_write_int32(conf, L"Proxiable", d->proxiable);
- khc_write_int32(conf, L"Addressless", d->addressless);
- khc_write_int32(conf, L"PublicIP", d->publicIP);
-
- khc_write_int32(conf, L"DefaultLifetime",
- (khm_int32) d->tc_lifetime.current);
- khc_write_int32(conf, L"MaxLifetime",
- (khm_int32) d->tc_lifetime.max);
- khc_write_int32(conf, L"MinLifetime",
- (khm_int32) d->tc_lifetime.min);
-
- khc_write_int32(conf, L"DefaultRenewLifetime",
- (khm_int32) d->tc_renew.current);
- khc_write_int32(conf, L"MaxRenewLifetime",
- (khm_int32) d->tc_renew.max);
- khc_write_int32(conf, L"MinRenewLifetime",
- (khm_int32) d->tc_renew.min);
+
+ 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 */
@@ -1460,6 +1364,24 @@ k5_write_dlg_params(khm_handle conf,
}
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;
@@ -1489,8 +1411,9 @@ k5_prep_kinit_job(khui_new_creds * nc)
kcdb_identity_get_name(ident, idname, &cbbuf);
StringCchLength(idname, ARRAYLENGTH(idname), &size);
size++;
-
- ZeroMemory(&g_fjob, sizeof(g_fjob));
+
+ k5_free_kinit_job();
+
g_fjob.command = FIBER_CMD_KINIT;
g_fjob.nc = nc;
g_fjob.nct = nct;
@@ -1509,6 +1432,13 @@ k5_prep_kinit_job(khui_new_creds * nc)
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) &&
@@ -1571,24 +1501,6 @@ k5_prep_kinit_job(khui_new_creds * nc)
/* leave identity held, since we added a reference above */
}
-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));
-}
-
static khm_int32 KHMAPI
k5_find_tgt_filter(khm_handle cred,
khm_int32 flags,
@@ -1890,7 +1802,7 @@ k5_msg_cred_dialog(khm_int32 msg_type,
}
if (nc->subtype == KMSG_CRED_NEW_CREDS) {
- k5_read_dlg_params(csp_params, d);
+ k5_read_dlg_params(d, NULL);
}
PostMessage(hwnd, KHUI_WM_NC_NOTIFY,
@@ -1925,22 +1837,10 @@ k5_msg_cred_dialog(khm_int32 msg_type,
if(/* !d->dirty && */ nc->n_identities > 0 &&
nc->subtype == KMSG_CRED_NEW_CREDS) {
- khm_handle h_idcfg = NULL;
+ k5_read_dlg_params(d, nc->identities[0]);
- do {
- if (KHM_FAILED
- (k5_open_config_handle(nc->identities[0],
- 0, &h_idcfg)))
- break;
-
- k5_read_dlg_params(h_idcfg, d);
-
- PostMessage(nct->hwnd_panel, KHUI_WM_NC_NOTIFY,
- MAKEWPARAM(0,WMNC_DIALOG_SETUP), 0);
- } while(FALSE);
-
- if(h_idcfg)
- khc_close_space(h_idcfg);
+ PostMessage(nct->hwnd_panel, KHUI_WM_NC_NOTIFY,
+ MAKEWPARAM(0,WMNC_DIALOG_SETUP), 0);
}
khui_cw_unlock_nc(nc);
@@ -2014,6 +1914,15 @@ k5_msg_cred_dialog(khm_int32 msg_type,
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;
@@ -2121,6 +2030,12 @@ k5_msg_cred_dialog(khm_int32 msg_type,
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. */
@@ -2245,7 +2160,19 @@ k5_msg_cred_dialog(khm_int32 msg_type,
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];
@@ -2282,7 +2209,6 @@ k5_msg_cred_dialog(khm_int32 msg_type,
} else if (nc->result == KHUI_NC_RESULT_PROCESS &&
g_fjob.state == FIBER_STATE_NONE) {
- khm_handle csp_idcfg = NULL;
krb5_context ctx = NULL;
_reportf(L"Tickets successfully acquired");
@@ -2297,16 +2223,7 @@ k5_msg_cred_dialog(khm_int32 msg_type,
assert(nc->n_identities > 0);
assert(nc->identities[0]);
- if (KHM_SUCCEEDED
- (k5_open_config_handle(nc->identities[0],
- KHM_FLAG_CREATE |
- KCONF_FLAG_WRITEIFMOD,
- &csp_idcfg))) {
- k5_write_dlg_params(csp_idcfg, d);
- }
-
- if(csp_idcfg != NULL)
- khc_close_space(csp_idcfg);
+ k5_write_dlg_params(d, nc->identities[0]);
/* We should also quickly refresh the credentials
so that the identity flags and ccache
@@ -2617,16 +2534,8 @@ k5_msg_cred_dialog(khm_int32 msg_type,
/* since this was just a password change,
we need to load new credentials options
from the configuration store. */
-
- if (KHM_SUCCEEDED
- (k5_open_config_handle(nc->identities[0],
- KHM_FLAG_CREATE |
- KCONF_FLAG_WRITEIFMOD,
- &csp_idcfg))) {
- k5_read_dlg_params(csp_idcfg, d);
- khc_close_space(csp_idcfg);
- csp_idcfg = NULL;
- }
+
+ k5_read_dlg_params(d, nc->identities[0]);
}
/* the password change phase is now done */
@@ -2655,14 +2564,9 @@ k5_msg_cred_dialog(khm_int32 msg_type,
/* save the settings that we used for
obtaining the ticket. */
- if (nc->subtype == KMSG_CRED_NEW_CREDS &&
- KHM_SUCCEEDED
- (k5_open_config_handle(nc->identities[0],
- KHM_FLAG_CREATE |
- KCONF_FLAG_WRITEIFMOD,
- &csp_idcfg))) {
- k5_write_dlg_params(csp_idcfg, d);
- khc_close_space(csp_idcfg);
+ 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]);
@@ -2790,6 +2694,8 @@ k5_msg_cred_dialog(khm_int32 msg_type,
PFREE(nct->credtext);
PFREE(nct);
+
+ k5_free_kinit_job();
}
break;
@@ -2804,14 +2710,34 @@ k5_msg_cred_dialog(khm_int32 msg_type,
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);
+ 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;
diff --git a/src/windows/identity/plugins/krb5/krbconfig.csv b/src/windows/identity/plugins/krb5/krbconfig.csv
index 205cbcb..4dc5b7d 100644
--- a/src/windows/identity/plugins/krb5/krbconfig.csv
+++ b/src/windows/identity/plugins/krb5/krbconfig.csv
@@ -13,7 +13,7 @@ Krb5Cred,KC_SPACE,0,Kerberos V Credentials Provider
DefaultLifetime,KC_INT32,36000,Default ticket lifetime
MaxLifetime,KC_INT32,86400,Maximum lifetime
MinLifetime,KC_INT32,60,Minimum lifetime
- Forwardable,KC_INT32,0,Obtain forwardable tickets (boolean)
+ Forwardable,KC_INT32,1,Obtain forwardable tickets (boolean)
Proxiable,KC_INT32,0,Obtain proxiable tickets (boolean)
Addressless,KC_INT32,1,Obtain addressless tickets (boolean)
PublicIP,KC_INT32,0,Additional public IP address to use (int32)
diff --git a/src/windows/identity/plugins/krb5/krbcred.h b/src/windows/identity/plugins/krb5/krbcred.h
index 44b7733..d552fd0 100644
--- a/src/windows/identity/plugins/krb5/krbcred.h
+++ b/src/windows/identity/plugins/krb5/krbcred.h
@@ -176,6 +176,7 @@ typedef struct _fiber_job_t {
BOOL null_password;
BOOL valid_principal;
+ BOOL retry_if_valid_principal;
} fiber_job;
extern fiber_job g_fjob; /* global fiber job object */
@@ -184,8 +185,9 @@ extern fiber_job g_fjob; /* global fiber job object */
#define FIBER_CMD_CANCEL 2
#define FIBER_CMD_CONTINUE 3
-#define FIBER_STATE_NONE 0
-#define FIBER_STATE_KINIT 1
+#define FIBER_STATE_NONE 0
+#define FIBER_STATE_KINIT 1
+#define FIBER_STATE_RETRY_KINIT 2
#define K5_SET_CRED_MSG WMNC_USER
diff --git a/src/windows/identity/plugins/krb5/lang/en_us/langres.rc b/src/windows/identity/plugins/krb5/lang/en_us/langres.rc
index d93b441..67492da 100644
--- a/src/windows/identity/plugins/krb5/lang/en_us/langres.rc
+++ b/src/windows/identity/plugins/krb5/lang/en_us/langres.rc
@@ -81,7 +81,7 @@ BEGIN
LTEXT "Valid till",IDC_STATIC,7,39,24,8
LTEXT "Renewable till",IDC_STATIC,7,55,45,12
LTEXT "Issued on",IDC_STATIC,7,23,32,8
- LTEXT "Credential flags",IDC_STATIC,7,75,37,8
+ LTEXT "Credential flags",IDC_STATIC,7,75,51,8
EDITTEXT IDC_PPK5_NAME,72,7,156,12,ES_AUTOHSCROLL | ES_READONLY
EDITTEXT IDC_PPK5_ISSUE,72,23,156,12,ES_AUTOHSCROLL | ES_READONLY
EDITTEXT IDC_PPK5_VALID,72,39,156,12,ES_AUTOHSCROLL | ES_READONLY
@@ -156,20 +156,23 @@ STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_SYSMENU
EXSTYLE WS_EX_CONTROLPARENT
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
- LTEXT "Credential lifetime",IDC_CFG_LBL_DEFLIFE,7,10,44,8
- EDITTEXT IDC_CFG_DEFLIFE,91,7,137,14,ES_AUTOHSCROLL
- LTEXT "Credential renewable lifetime",IDC_CFG_LBL_DEFRLIFE,7,29,80,8
- EDITTEXT IDC_CFG_DEFRLIFE,91,26,137,14,ES_AUTOHSCROLL
- GROUPBOX "Credential lifetime range",IDC_CFG_LIFEGRP,7,43,221,49
- LTEXT "Minimum",IDC_STATIC,13,56,28,8
- EDITTEXT IDC_CFG_LRNG_MIN,91,53,131,14,ES_AUTOHSCROLL
- LTEXT "Maximum",IDC_STATIC,13,75,30,8
- EDITTEXT IDC_CFG_LRNG_MAX,91,72,131,14,ES_AUTOHSCROLL
- GROUPBOX "Credential renewable lifetime range",IDC_STATIC,7,95,221,49
- LTEXT "Minimum",IDC_STATIC,13,108,28,8
- EDITTEXT IDC_CFG_RLRNG_MIN,91,105,131,14,ES_AUTOHSCROLL
- LTEXT "Maximum",IDC_STATIC,13,128,30,8
- EDITTEXT IDC_CFG_RLRNG_MAX,91,125,131,14,ES_AUTOHSCROLL
+ LTEXT "Ticket &lifetime",IDC_CFG_LBL_DEFLIFE,7,10,44,8
+ EDITTEXT IDC_CFG_DEFLIFE,94,7,134,14,ES_AUTOHSCROLL
+ LTEXT "Ticket re&newable lifetime",IDC_CFG_LBL_DEFRLIFE,7,29,80,8
+ EDITTEXT IDC_CFG_DEFRLIFE,94,26,134,14,ES_AUTOHSCROLL
+ CONTROL "&Renewable",IDC_CFG_RENEW,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,47,51,10
+ CONTROL "&Forwardable",IDC_CFG_FORWARD,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,94,47,56,10
+ CONTROL "&Addressless",IDC_CFG_ADDRESSLESS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,63,54,10
+ GROUPBOX "Credential lifetime range",IDC_CFG_LIFEGRP,7,79,221,31
+ LTEXT "From",IDC_STATIC,13,93,17,8
+ EDITTEXT IDC_CFG_LRNG_MIN,38,90,79,14,ES_AUTOHSCROLL
+ LTEXT "To",IDC_STATIC,125,93,9,8
+ EDITTEXT IDC_CFG_LRNG_MAX,143,90,79,14,ES_AUTOHSCROLL
+ GROUPBOX "Credential renewable lifetime range",IDC_STATIC,7,113,221,31
+ LTEXT "From",IDC_STATIC,13,128,17,8
+ EDITTEXT IDC_CFG_RLRNG_MIN,38,125,79,14,ES_AUTOHSCROLL
+ LTEXT "To",IDC_STATIC,125,128,9,8
+ EDITTEXT IDC_CFG_RLRNG_MAX,143,125,79,14,ES_AUTOHSCROLL
END
IDD_CFG_ID_TAB DIALOGEX 0, 0, 235, 151
@@ -177,7 +180,7 @@ STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_SYSMENU
EXSTYLE WS_EX_CONTROLPARENT
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
- LTEXT "Credential lifetime",IDC_CFG_LBL_DEFLIFE,7,10,44,8
+ LTEXT "Credential lifetime",IDC_CFG_LBL_DEFLIFE,7,10,58,8
EDITTEXT IDC_CFG_DEFLIFE,91,7,137,14,ES_AUTOHSCROLL
CONTROL "Renewable for",IDC_CFG_RENEW,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,41,63,10
EDITTEXT IDC_CFG_DEFRLIFE,91,39,137,14,ES_AUTOHSCROLL
@@ -280,7 +283,7 @@ BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 228
VERTGUIDE, 13
- VERTGUIDE, 91
+ VERTGUIDE, 94
VERTGUIDE, 222
TOPMARGIN, 7
BOTTOMMARGIN, 144
@@ -338,7 +341,7 @@ IDI_MODIFIED ICON "..\\..\\images\\modified.ico"
STRINGTABLE
BEGIN
IDS_UNK_ADDR_FMT "Unknown address type %d"
- IDS_KRB5_CREDTEXT_0 "<p><a id=""SwitchPanel"" param=""Krb5Cred""><b>Krb5</b></a><tab>: Creds for realm %s</p>"
+ IDS_KRB5_CREDTEXT_0 "<p><a id=""SwitchPanel"" param=""Krb5Cred""><b>Krb5</b></a><tab>: Tickets for realm %s</p>"
IDS_KRB5_CCNAME_SHORT_DESC "Kerberos v5 CCache"
IDS_KEY_ENCTYPE_SHORT_DESC "Session EncType"
IDS_TKT_ENCTYPE_SHORT_DESC "Service EncType"
@@ -501,3 +504,4 @@ END
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED
+
diff --git a/src/windows/identity/plugins/krb5/langres.h b/src/windows/identity/plugins/krb5/langres.h
index 9381b99..0e62ecd 100644
--- a/src/windows/identity/plugins/krb5/langres.h
+++ b/src/windows/identity/plugins/krb5/langres.h
@@ -201,6 +201,7 @@
#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
@@ -209,7 +210,7 @@
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 219
#define _APS_NEXT_COMMAND_VALUE 40002
-#define _APS_NEXT_CONTROL_VALUE 1079
+#define _APS_NEXT_CONTROL_VALUE 1080
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
diff --git a/src/windows/identity/ui/Makefile b/src/windows/identity/ui/Makefile
index c335504..7091104 100644
--- a/src/windows/identity/ui/Makefile
+++ b/src/windows/identity/ui/Makefile
@@ -49,6 +49,7 @@ OBJFILES= \
$(OBJ)\reqdaemon.obj \
$(OBJ)\addrchange.obj \
$(OBJ)\debugfuncs.obj \
+ $(OBJ)\taskbar.obj \
$(OBJ)\cfg_general_wnd.obj \
$(OBJ)\cfg_identities_wnd.obj \
$(OBJ)\cfg_notif_wnd.obj \
@@ -70,7 +71,9 @@ SDKLIBFILES= \
shell32.lib \
htmlhelp.lib \
iphlpapi.lib \
- shlwapi.lib
+ shlwapi.lib \
+ msimg32.lib \
+ ole32.lib
$(OBJ)\uiconfig.c: uiconfig.csv $(CONFDIR)\csvschema.cfg
$(CCSV) $** $@
diff --git a/src/windows/identity/ui/aboutwnd.c b/src/windows/identity/ui/aboutwnd.c
index f4dcfcc..68aef02 100644
--- a/src/windows/identity/ui/aboutwnd.c
+++ b/src/windows/identity/ui/aboutwnd.c
@@ -124,6 +124,11 @@ about_dlg_proc(HWND hwnd,
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();
diff --git a/src/windows/identity/ui/addrchange.c b/src/windows/identity/ui/addrchange.c
index 3e5467c..b37fca5 100644
--- a/src/windows/identity/ui/addrchange.c
+++ b/src/windows/identity/ui/addrchange.c
@@ -39,6 +39,8 @@ addr_change_thread(LPVOID dummy) {
OVERLAPPED overlap;
DWORD ret;
+ PDESCTHREAD(L"Address change waiter", L"App");
+
ZeroMemory(&overlap, sizeof(overlap));
h_notify = NULL;
diff --git a/src/windows/identity/ui/appglobal.h b/src/windows/identity/ui/appglobal.h
index 8660de2..3e44282 100644
--- a/src/windows/identity/ui/appglobal.h
+++ b/src/windows/identity/ui/appglobal.h
@@ -36,18 +36,19 @@ extern int khm_nCmdShow;
extern const wchar_t * khm_facility;
extern kconf_schema schema_uiconfig[];
extern khm_ui_4 khm_commctl_version;
-extern khm_version app_version;
+extern const khm_version app_version;
#define IS_COMMCTL6() (khm_commctl_version >= 0x60000)
-typedef struct tag_khm_startup_options_v1 {
+/* 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;
- LONG pending_renewals;
BOOL destroy;
BOOL autoinit;
@@ -55,10 +56,51 @@ typedef struct tag_khm_startup_options_v1 {
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;
@@ -92,8 +134,10 @@ 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 ELIPSIS L"..."
+#define ELLIPSIS L"..."
#endif
diff --git a/src/windows/identity/ui/cfg_general_wnd.c b/src/windows/identity/ui/cfg_general_wnd.c
index 71edb26..fa7ac6f 100644
--- a/src/windows/identity/ui/cfg_general_wnd.c
+++ b/src/windows/identity/ui/cfg_general_wnd.c
@@ -36,6 +36,7 @@ typedef struct tag_cfg_data {
BOOL auto_detect_net;
BOOL log_to_file;
BOOL destroy_creds;
+ khm_int32 notif_action;
} cfg_data;
typedef struct tag_dlg_data {
@@ -81,6 +82,9 @@ read_params(dlg_data * dd) {
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;
@@ -144,6 +148,11 @@ write_params(dlg_data * dd) {
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,
@@ -165,7 +174,8 @@ check_for_modification(dlg_data * dd) {
!!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->destroy_creds != !!s->destroy_creds ||
+ d->notif_action != s->notif_action) {
khui_cfg_set_flags(dd->node,
KHUI_CNFLAG_MODIFIED,
@@ -180,9 +190,22 @@ check_for_modification(dlg_data * dd) {
}
}
+
+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));
@@ -199,6 +222,44 @@ refresh_view(HWND hwnd, dlg_data * d) {
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,
@@ -212,6 +273,8 @@ refresh_view(HWND hwnd, dlg_data * d) {
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)
@@ -226,6 +289,14 @@ refresh_data(HWND hwnd, dlg_data * d) {
== 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
@@ -323,6 +394,9 @@ khm_cfg_general_proc(HWND hwnd,
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);
diff --git a/src/windows/identity/ui/cfg_identities_wnd.c b/src/windows/identity/ui/cfg_identities_wnd.c
index 3f92ad8..a8813d1 100644
--- a/src/windows/identity/ui/cfg_identities_wnd.c
+++ b/src/windows/identity/ui/cfg_identities_wnd.c
@@ -483,10 +483,7 @@ write_params_ident(ident_data * d) {
static void
write_params_idents(void) {
-#if 0
- int i;
-#endif
- khm_handle csp_cw;
+ khm_handle csp_cw = NULL;
if (KHM_SUCCEEDED(khc_open_space(NULL, L"CredWindow",
KHM_FLAG_CREATE, &csp_cw))) {
@@ -503,12 +500,14 @@ write_params_idents(void) {
cfg_idents.applied = TRUE;
}
if (cfg_idents.work.sticky != cfg_idents.saved.sticky) {
- khc_write_int32(csp_cw, L"DefaultMonitor",
+ 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
@@ -530,7 +529,7 @@ init_idents_data(void) {
khm_size cb;
int n_tries = 0;
int i;
- khm_handle csp_cw;
+ khm_handle csp_cw = NULL;
if (cfg_idents.valid)
return;
@@ -559,6 +558,9 @@ init_idents_data(void) {
else
cfg_idents.saved.sticky = FALSE;
+ khc_close_space(csp_cw);
+ csp_cw = NULL;
+
} else {
cfg_idents.saved.monitor = TRUE;
diff --git a/src/windows/identity/ui/configwnd.c b/src/windows/identity/ui/configwnd.c
index 660c1fa..03eec9a 100644
--- a/src/windows/identity/ui/configwnd.c
+++ b/src/windows/identity/ui/configwnd.c
@@ -784,10 +784,14 @@ cfgui_dlgproc(HWND 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:
@@ -1043,6 +1047,8 @@ void khm_refresh_config(void) {
if (omenu == NULL)
goto _cleanup;
+ khui_action_lock();
+
do {
khm_int32 action;
khm_int32 flags;
@@ -1099,8 +1105,11 @@ void khm_refresh_config(void) {
break;
} while(cfg_r);
- if (refresh_menu)
- khm_menu_refresh_items();
+ khui_action_unlock();
+
+ if (refresh_menu) {
+ khui_refresh_actions();
+ }
_cleanup:
if (cfg_ids)
diff --git a/src/windows/identity/ui/credfuncs.c b/src/windows/identity/ui/credfuncs.c
index e70b852..2f1ac80 100644
--- a/src/windows/identity/ui/credfuncs.c
+++ b/src/windows/identity/ui/credfuncs.c
@@ -34,6 +34,7 @@ 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) {
@@ -65,9 +66,28 @@ khm_cred_begin_dialog(void) {
EnterCriticalSection(&cs_dialog);
- if (in_dialog)
+ if (in_dialog) {
rv = FALSE;
- else {
+
+ /* 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);
@@ -87,6 +107,10 @@ khm_cred_end_dialog(khui_new_creds * nc) {
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]) {
@@ -156,7 +180,11 @@ khm_cred_wait_for_dialog(DWORD timeout, khm_int32 * result,
return rv;
}
-/* completion handler for KMSG_CRED messages */
+/* 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)
{
@@ -183,7 +211,7 @@ kmsg_cred_completion(kmq_message *m)
nc = (khui_new_creds *) m->vparam;
/* khm_cred_dispatch_process_message() deals with the case
- where there are not credential types that wants to
+ where there are no credential types that wants to
participate in this operation. */
khm_cred_dispatch_process_message(nc);
break;
@@ -281,6 +309,8 @@ kmsg_cred_completion(kmq_message *m)
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],
@@ -293,10 +323,17 @@ kmsg_cred_completion(kmq_message *m)
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],
@@ -308,10 +345,17 @@ kmsg_cred_completion(kmq_message *m)
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,
@@ -323,6 +367,11 @@ kmsg_cred_completion(kmq_message *m)
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 {
@@ -342,6 +391,22 @@ kmsg_cred_completion(kmq_message *m)
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);
@@ -374,11 +439,6 @@ kmsg_cred_completion(kmq_message *m)
if (nc->subtype == KMSG_CRED_NEW_CREDS ||
nc->subtype == KMSG_CRED_PASSWORD) {
- /*
- if (nc->subtype == KMSG_CRED_NEW_CREDS)
- khui_context_reset();
- */
-
khm_cred_end_dialog(nc);
} else if (nc->subtype == KMSG_CRED_RENEW_CREDS) {
@@ -743,6 +803,7 @@ void khm_cred_change_password(wchar_t * title)
khui_cw_create_cred_blob(&nc);
nc->subtype = KMSG_CRED_PASSWORD;
+ dialog_nc = nc;
khui_context_get(&nc->ctx);
@@ -793,6 +854,31 @@ void khm_cred_change_password(wchar_t * title)
}
}
+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;
@@ -804,6 +890,7 @@ void khm_cred_obtain_new_creds(wchar_t * title)
khui_cw_create_cred_blob(&nc);
nc->subtype = KMSG_CRED_NEW_CREDS;
+ dialog_nc = nc;
khui_context_get(&nc->ctx);
@@ -1169,6 +1256,9 @@ khm_cred_process_startup_actions(void) {
/* 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)
@@ -1182,7 +1272,9 @@ khm_cred_begin_startup_actions(void) {
if (khm_startup.seen)
return;
- if (KHM_SUCCEEDED(khc_open_space(NULL, L"CredWindow", 0, &csp_cw))) {
+ 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);
diff --git a/src/windows/identity/ui/credfuncs.h b/src/windows/identity/ui/credfuncs.h
index b3c88fa..761cbf5 100644
--- a/src/windows/identity/ui/credfuncs.h
+++ b/src/windows/identity/ui/credfuncs.h
@@ -53,6 +53,9 @@ 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);
diff --git a/src/windows/identity/ui/credwnd.c b/src/windows/identity/ui/credwnd.c
index 5bdbdb7..d72d169 100644
--- a/src/windows/identity/ui/credwnd.c
+++ b/src/windows/identity/ui/credwnd.c
@@ -289,8 +289,15 @@ cw_save_view(khui_credwnd_tbl * tbl, wchar_t * view_name) {
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)) {
- view_name = L"Custom_0";
+ if (!(tbl->flags & KHUI_CW_TBL_EXPIDENT)) {
+ view_name = L"Custom_0";
+ } else {
+ view_name = L"Custom_1";
+ }
}
if (view_name) {
@@ -309,7 +316,9 @@ cw_save_view(khui_credwnd_tbl * tbl, wchar_t * view_name) {
/* 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, L"DefaultView", L"Custom_0");
+ khc_write_string(csp_cw, ((!(tbl->flags & KHUI_CW_TBL_EXPIDENT))?
+ L"DefaultView":
+ L"DefaultViewMini"), view_name);
}
} else {
@@ -319,6 +328,22 @@ cw_save_view(khui_credwnd_tbl * tbl, wchar_t * view_name) {
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)))
@@ -369,6 +394,12 @@ cw_save_view(khui_credwnd_tbl * tbl, wchar_t * view_name) {
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) {
@@ -389,6 +420,19 @@ cw_save_view(khui_credwnd_tbl * tbl, wchar_t * view_name) {
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;
@@ -403,9 +447,17 @@ cw_load_view(khui_credwnd_tbl * tbl, wchar_t * view, HWND hwnd) {
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;
@@ -415,37 +467,67 @@ cw_load_view(khui_credwnd_tbl * tbl, wchar_t * view, HWND hwnd) {
if(!view) {
cbsize = sizeof(buf);
- if(KHM_FAILED(khc_read_string(hc_cw, L"DefaultView", buf, &cbsize)))
+ 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);
-
- kmq_post_message(KMSG_ACT, KMSG_ACT_REFRESH, 0, 0);
- } else {
- khc_write_string(hc_cw, L"DefaultView", view);
+ 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 */
}
- if(KHM_FAILED(khc_open_space(hc_vs, view, KHM_PERM_READ, &hc_v)))
+ 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, &hc_cs)))
+ 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;
@@ -466,6 +548,18 @@ cw_load_view(khui_credwnd_tbl * tbl, wchar_t * view, HWND hwnd) {
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) {
@@ -503,7 +597,9 @@ cw_load_view(khui_credwnd_tbl * tbl, wchar_t * view, HWND hwnd) {
tbl->cols[i].attr_id = attr_id;
- if(KHM_SUCCEEDED(khc_open_space(hc_cs, iter, KHM_PERM_READ, &hc_c))) {
+ 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))))
@@ -579,21 +675,47 @@ _skip_col:
0,
LR_DEFAULTCOLOR));
- tbl->hb_normal = CreateSolidBrush(RGB(255,255,255));
- tbl->hb_grey = CreateSolidBrush(RGB(240,240,240));
- tbl->hb_sel = CreateSolidBrush(RGB(230,230,255));
- tbl->hb_hdr_bg = CreateSolidBrush(RGB(230,230,230));
- tbl->hb_hdr_bg_sel = CreateSolidBrush(RGB(0,0,255));
- tbl->hb_hdr_bg_crit = CreateSolidBrush(RGB(240,133,117));
- tbl->hb_hdr_bg_warn = CreateSolidBrush(RGB(251,199,77));
- tbl->hb_hdr_bg_exp = CreateSolidBrush(RGB(255,144,144));
- tbl->hb_hdr_bg_def = CreateSolidBrush(RGB(186,254,184));
-
- tbl->cr_normal = RGB(0,0,0);
- tbl->cr_sel = RGB(0,0,0);
- tbl->cr_hdr_outline = RGB(0,0,0);
- tbl->cr_hdr_normal = RGB(0,0,0);
- tbl->cr_hdr_sel = RGB(255,255,255);
+ {
+#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);
{
@@ -633,12 +755,30 @@ _skip_col:
#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);
@@ -652,6 +792,122 @@ _exit:
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)
{
@@ -751,6 +1007,15 @@ cw_update_creds(khui_credwnd_tbl * tbl)
}
}
+ /* 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);
}
@@ -772,7 +1037,7 @@ cw_del_outline(khui_credwnd_outline *o) {
o->data)
PFREE(o->data);
- if ((o->flags & KHUI_CW_O_STICKY) &&
+ if ((o->flags & KHUI_CW_O_RELIDENT) &&
o->data)
kcdb_identity_release((khm_handle) o->data);
@@ -782,6 +1047,7 @@ cw_del_outline(khui_credwnd_outline *o) {
LPOP(&(o->children), &c);
}
+ ZeroMemory(o, sizeof(*o));
PFREE(o);
}
@@ -798,6 +1064,7 @@ cw_new_outline_node(wchar_t * heading) {
o->header = PMALLOC(cblen);
StringCbCopy(o->header, cblen, heading);
}
+ o->start = -1;
return o;
}
@@ -839,6 +1106,9 @@ cw_get_buf_exp_flags(khui_credwnd_tbl * tbl, khm_handle buf)
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,
@@ -852,46 +1122,96 @@ cw_timer_proc(HWND hwnd,
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))
- return; /* we only know what to do with cred rows */
+ 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;
+ }
+ }
- 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);
+ if (timer_set)
+ r->flags |= KHUI_CW_ROW_TIMERSET;
+ }
} else {
- /* just invalidate the row */
- RECT r,rr,ri;
+ khui_credwnd_outline * o;
+ khui_credwnd_ident * cwi;
+ FILETIME ft_now;
- GetClientRect(tbl->hwnd, &r);
- r.top += tbl->header_height;
- rr.top = r.top + (long)nr * tbl->cell_height - tbl->scr_top;
- rr.bottom = rr.top + tbl->cell_height;
- rr.left = r.left;
- rr.right = r.right;
-
- if(IntersectRect(&ri, &r, &rr))
- InvalidateRect(tbl->hwnd, &ri, FALSE);
- }
+ 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
- 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);
+ 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;
}
}
}
@@ -957,6 +1277,38 @@ cw_set_tbl_row_header(khui_credwnd_tbl * tbl,
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
@@ -1068,8 +1420,8 @@ cw_update_outline(khui_credwnd_tbl * tbl)
continue;
/* if this credential appears to be the same as another for
- this view, we skip it */
- if(prevcred) {
+ 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))
@@ -1224,24 +1576,13 @@ cw_update_outline(khui_credwnd_tbl * tbl)
/* now ol points at the node at level j we want to be
in */
ol->start = n_rows;
- ol->idx_start = i;
ol->length = 0;
- ol->flags &= ~CW_EXPSTATE_MASK;
- ol->flags &= ~KHUI_CW_O_SHOWFLAG;
- ol->flags &= ~KHUI_CW_O_STICKY;
-
- 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));
+ 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. */
@@ -1255,29 +1596,58 @@ cw_update_outline(khui_credwnd_tbl * tbl)
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);
- flags = cw_get_buf_exp_flags(tbl, thiscred);
-
- if(visible) {
+ 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]);
- kcdb_cred_get_flags(thiscred, &c_flags);
+
+ 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))
+ (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;
@@ -1300,7 +1670,8 @@ cw_update_outline(khui_credwnd_tbl * tbl)
prevcred = NULL;
}
- /* Add any sticky identities that we haven't seen yet */
+ /* Add any default identities with no credentials and sticky
+ identities that we haven't seen yet */
if (n_grouping > 0 &&
tbl->cols[grouping[0]].attr_id == KCDB_ATTR_ID_NAME) {
@@ -1312,6 +1683,63 @@ cw_update_outline(khui_credwnd_tbl * tbl)
wchar_t ** idarray = NULL;
int i;
+ /* see if the defualt identity is in the list */
+ {
+ khm_handle id_def = NULL;
+ wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
+ khm_size cb;
+ khm_int32 flags;
+
+ if (KHM_FAILED(kcdb_identity_get_default(&id_def))) {
+ goto done_with_defident;
+ }
+
+ kcdb_identity_get_flags(id_def, &flags);
+ cb = sizeof(idname);
+ kcdb_identity_get_name(id_def, idname, &cb);
+
+ for (o = tbl->outline; o; o = LNEXT(o)) {
+ if (!wcscmp(idname, o->header))
+ break;
+ }
+
+ if (o == NULL) {
+ o = cw_new_outline_node(idname);
+ LPUSH(&tbl->outline, o);
+ o->flags = KHUI_CW_O_VISIBLE | KHUI_CW_O_RELIDENT | 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,
@@ -1357,27 +1785,38 @@ cw_update_outline(khui_credwnd_tbl * tbl)
/* found it */
if (o->start != -1) /* already visible? */
continue;
- o->flags &= KHUI_CW_O_STICKY;
- o->flags |= KHUI_CW_O_VISIBLE;
+ 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]);
- o->flags = KHUI_CW_O_VISIBLE;
+ 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 = (void *) h;
+ o->data = h;
+ kcdb_identity_hold(h);
+ o->attr_id = KCDB_ATTR_ID;
}
- if (o->flags & KHUI_CW_O_STICKY)
- kcdb_identity_release(h);
- else
- /* leave identity held in this case */
- o->flags |= KHUI_CW_O_STICKY;
+ 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);
@@ -1408,10 +1847,10 @@ _exit:
* 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)
+ else if ((expstate & CW_EXPSTATE_EXPIRED) == CW_EXPSTATE_EXPIRED)
khm_notify_icon_expstate(KHM_NOTIF_EXP);
- else if ((expstate & CW_EXPSTATE_WARN) ||
- (expstate & CW_EXPSTATE_CRITICAL))
+ 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);
@@ -1432,18 +1871,30 @@ cw_unload_view(khui_credwnd_tbl * tbl)
SafeDeleteObject(tbl->hf_normal);
SafeDeleteObject(tbl->hf_bold);
SafeDeleteObject(tbl->hf_bold_header);
+
SafeDeleteObject(tbl->hb_grey);
SafeDeleteObject(tbl->hb_normal);
- SafeDeleteObject(tbl->hb_sel);
+ SafeDeleteObject(tbl->hb_s);
+
SafeDeleteObject(tbl->hb_hdr_bg);
- SafeDeleteObject(tbl->hb_hdr_bg_sel);
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;
@@ -1492,6 +1943,21 @@ cw_unload_view(khui_credwnd_tbl * tbl)
}
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
@@ -1553,19 +2019,71 @@ cw_get_cell_height(HDC hdc, HFONT hf) {
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, ext_y;
+ 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;
@@ -1589,7 +2107,38 @@ cw_update_extents(khui_credwnd_tbl * tbl,
tbl->cell_height = height + tbl->vpad * 2;
}
- ext_y = (int) tbl->n_rows * tbl->cell_height;
+ 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;
@@ -1710,7 +2259,7 @@ cw_erase_rect(HDC hdc,
break;
case CW_ER_SEL:
- hbr = tbl->hb_sel;
+ hbr = tbl->hb_s;
break;
default:
@@ -1798,22 +2347,35 @@ cw_draw_header(HDC hdc,
{
HBRUSH hbr;
- if(selected)
- hbr = tbl->hb_hdr_bg_sel;
- 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;
+
+ 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);
@@ -1821,29 +2383,35 @@ cw_draw_header(HDC hdc,
SelectObject(hdc, pold);
DeleteObject(pl);
- if (o->flags & KHUI_CW_O_STICKY) {
- /* khui_ilist_draw_id(tbl->ilist, IDB_TK_NEW_SM, hdc,
- r->left, r->bottom - KHUI_SMICON_CY, 0); */
- } else 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->bottom - KHUI_SMICON_CY, 0);
- } else {
- khui_ilist_draw_id(tbl->ilist, IDB_WDG_COLLAPSE_HI,
- hdc, r->left, r->bottom - KHUI_SMICON_CY, 0);
- }
- } else {
- if(o->flags & KHUI_CW_O_EXPAND) {
- khui_ilist_draw_id(tbl->ilist, IDB_WDG_EXPAND,
- hdc, r->left, r->bottom - KHUI_SMICON_CY, 0);
+ 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 {
- khui_ilist_draw_id(tbl->ilist, IDB_WDG_COLLAPSE,
- hdc, r->left, r->bottom - KHUI_SMICON_CY, 0);
+ 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;
+ 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) {
@@ -1858,48 +2426,187 @@ cw_draw_header(HDC hdc,
IDB_WDG_STUCK:
IDB_WDG_STICK)),
hdc,
- r->left, r->bottom - KHUI_SMICON_CY,
- 0);
+ r->left,
+ (r->top + r->bottom - KHUI_SMICON_CY) / 2, 0);
r->left += KHUI_SMICON_CX * 3 / 2;
- khui_ilist_draw_id(tbl->ilist,
- ((o->flags & KHUI_CW_O_STICKY)?
- IDB_ID_DIS_SM:
- IDB_ID_SM),
- hdc,
- r->left, r->bottom - KHUI_SMICON_CY,
- 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 ;
+ }
}
- /* ok, now o->header contains the string representation of the
- outline value */
- /* for now just write out the value */
- SetTextAlign(hdc, TA_BOTTOM | TA_LEFT);
- if(selected)
- SetTextColor(hdc, tbl->cr_hdr_sel);
- else
- SetTextColor(hdc, tbl->cr_hdr_normal);
+ 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));
- TextOut(hdc, r->left, r->bottom - tbl->vpad, o->header, (int) wcslen(o->header));
+ GetTextExtentPoint32(hdc, o->header, (int) wcslen(o->header),
+ &size);
- if (colattr == KCDB_ATTR_ID_NAME &&
- (idf & KCDB_IDENT_FLAG_DEFAULT)) {
- wchar_t defstr[64];
+ 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
- LoadString(khm_hInstance, IDS_CW_DEFAULT,
- defstr, ARRAYLENGTH(defstr));
+ cwi = cw_find_ident(tbl, o->data);
- GetTextExtentPoint32(hdc, o->header, (int) wcslen(o->header),
- &size);
+ 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
- r->left += size.cx + KHUI_SMICON_CX * 2;
+ len = (int) wcslen(buf);
- TextOut(hdc, r->left, r->bottom - tbl->vpad,
- defstr, (int) wcslen(defstr));
+ 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);
+ }
+ }
}
}
@@ -1923,6 +2630,8 @@ cw_handle_header_msg(khui_credwnd_tbl * tbl, LPNMHEADER ph) {
}
case HDN_TRACK:
+ return FALSE;
+
case HDN_ENDTRACK:
{
int width;
@@ -1945,7 +2654,7 @@ cw_handle_header_msg(khui_credwnd_tbl * tbl, LPNMHEADER ph) {
hi.mask = HDI_ORDER;
Header_GetItem(tbl->hwnd_header, ph->iItem, &hi);
- if (tbl->cols[hi.iOrder].flags & KHUI_CW_COL_FIXED_WIDTH) {
+ if (tbl->cols[hi.iOrder].flags & KHUI_CW_COL_FIXED_POS) {
return TRUE;
} else {
return FALSE;
@@ -1978,7 +2687,7 @@ cw_handle_header_msg(khui_credwnd_tbl * tbl, LPNMHEADER ph) {
/* we don't allow dragging in to the "fixed" area. */
for (i=0; i < tbl->n_cols; i++) {
- if (tbl->cols[i].attr_id >= 0)
+ if (!(tbl->cols[i].flags & KHUI_CW_COL_FIXED_POS))
break;
}
@@ -2068,7 +2777,10 @@ cw_handle_header_msg(khui_credwnd_tbl * tbl, LPNMHEADER ph) {
Header_GetItem(tbl->hwnd_header, ph->iItem, &hi);
idx = hi.iOrder;
- if (idx == 0 || idx >= tbl->n_cols)
+ 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 &
@@ -2274,6 +2986,7 @@ cw_wm_create(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
cw_update_creds(tbl);
cw_update_outline(tbl);
+ cw_update_selection_state(tbl);
cw_update_extents(tbl, FALSE);
{
@@ -2334,6 +3047,7 @@ cw_wm_paint(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
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);
@@ -2380,11 +3094,9 @@ cw_wm_paint(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
/* We *NEED* all the meta columns to be on the left */
- row_s = tbl->scr_top / tbl->cell_height;
- ys = row_s * tbl->cell_height;
- row_e = (tbl->scr_top + (r.bottom - r.top)) / tbl->cell_height + 1;
- if(row_e > (int) tbl->n_rows)
- row_e = (int) tbl->n_rows;
+ row_s = 0;
+ ys = 0;
+ row_e = (int) tbl->n_rows;
x = 0;
col_s = -1;
col_e = -1;
@@ -2422,6 +3134,7 @@ cw_wm_paint(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
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)
@@ -2439,7 +3152,7 @@ cw_wm_paint(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
for(j=col_s; j < tbl->rows[i].col; j++)
rh.right += tbl->cols[j].width;
rh.top = y;
- rh.bottom = y + tbl->cell_height;
+ rh.bottom = y + rowheight;
if(rh.right > rh.left) {
cw_erase_rect(hdc, tbl, &r, &rh, (selected)?CW_ER_SEL:CW_ER_BLANK);
}
@@ -2448,15 +3161,15 @@ cw_wm_paint(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
cw_draw_header(hdc, tbl, i, &rh);
}
-
+
if(selected)
- SetTextColor(hdc, tbl->cr_sel);
+ SetTextColor(hdc, tbl->cr_s);
else
SetTextColor(hdc, tbl->cr_normal);
x = xs;
rh.top = y;
- rh.bottom = y + tbl->cell_height;
+ rh.bottom = y + rowheight;
for(j=col_s; j < col_e; x += tbl->cols[j++].width) {
wchar_t buf[256];
khm_size cbbuf;
@@ -2539,7 +3252,7 @@ cw_wm_paint(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
SelectFont(hdc, tbl->hf_normal);
}
- y += tbl->cell_height;
+ y += rowheight;
}
@@ -2570,8 +3283,9 @@ cw_wm_paint(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
tbl->hwnd_notif = khm_create_htwnd(
tbl->hwnd,
buf,
- r.left,r.top,r.right - r.left,(r.bottom - r.top) /2,
- WS_EX_TRANSPARENT,
+ 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);
@@ -2609,7 +3323,7 @@ cw_wm_size(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
rect.left,
tbl->header_height,
rect.right - rect.left,
- (rect.bottom - tbl->header_height) / 2,
+ tbl->cell_height * 4,
0);
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
@@ -2620,7 +3334,6 @@ 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) {
@@ -2685,6 +3398,8 @@ cw_kmq_wm_dispatch(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
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);
}
@@ -2718,6 +3433,7 @@ cw_kmq_wm_dispatch(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
cw_update_creds(tbl);
cw_update_outline(tbl);
+ cw_update_selection_state(tbl);
cw_update_extents(tbl, TRUE);
InvalidateRect(tbl->hwnd, NULL, TRUE);
@@ -2884,6 +3600,54 @@ cw_select_outline(khui_credwnd_outline * o,
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)
{
@@ -2891,10 +3655,8 @@ cw_unselect_all(khui_credwnd_tbl * tbl)
for(i=0; i<tbl->n_rows; i++) {
tbl->rows[i].flags &= ~KHUI_CW_ROW_SELECTED;
- if (!(tbl->rows[i].flags & KHUI_CW_ROW_HEADER))
- kcdb_cred_set_flags((khm_handle) tbl->rows[i].data,
- 0,
- KCDB_CRED_FLAG_SELECTED);
+
+ cw_select_row_creds(tbl, i, FALSE);
}
cw_select_outline_level(tbl->outline, FALSE);
@@ -3114,10 +3876,7 @@ cw_select_all(khui_credwnd_tbl * tbl)
for(i=0; i<tbl->n_rows; i++) {
tbl->rows[i].flags |= KHUI_CW_ROW_SELECTED;
- if (!(tbl->rows[i].flags & KHUI_CW_ROW_HEADER))
- kcdb_cred_set_flags((khm_handle) tbl->rows[i].data,
- KCDB_CRED_FLAG_SELECTED,
- KCDB_CRED_FLAG_SELECTED);
+ cw_select_row_creds(tbl, i, TRUE);
}
cw_select_outline_level(tbl->outline, TRUE);
@@ -3173,11 +3932,7 @@ cw_select_row(khui_credwnd_tbl * tbl, int row, WPARAM wParam)
for (i = group_begin; i <= group_end; i++) {
tbl->rows[i].flags |= KHUI_CW_ROW_SELECTED;
- if (!(tbl->rows[i].flags & KHUI_CW_ROW_HEADER)) {
- kcdb_cred_set_flags((khm_handle) tbl->rows[i].data,
- KCDB_CRED_FLAG_SELECTED,
- KCDB_CRED_FLAG_SELECTED);
- }
+ cw_select_row_creds(tbl, i, TRUE);
}
} else if (toggle) {
BOOL select;
@@ -3193,11 +3948,7 @@ cw_select_row(khui_credwnd_tbl * tbl, int row, WPARAM wParam)
else
tbl->rows[i].flags &= ~KHUI_CW_ROW_SELECTED;
- if (!(tbl->rows[i].flags & KHUI_CW_ROW_HEADER)) {
- kcdb_cred_set_flags((khm_handle) tbl->rows[i].data,
- (select)?KCDB_CRED_FLAG_SELECTED:0,
- KCDB_CRED_FLAG_SELECTED);
- }
+ cw_select_row_creds(tbl, i, select);
}
} else if (extend) {
int range_begin;
@@ -3211,11 +3962,7 @@ cw_select_row(khui_credwnd_tbl * tbl, int row, WPARAM wParam)
for (i = range_begin; i <= range_end; i++) {
tbl->rows[i].flags |= KHUI_CW_ROW_SELECTED;
- if (!(tbl->rows[i].flags & KHUI_CW_ROW_HEADER)) {
- kcdb_cred_set_flags((khm_handle) tbl->rows[i].data,
- KCDB_CRED_FLAG_SELECTED,
- KCDB_CRED_FLAG_SELECTED);
- }
+ cw_select_row_creds(tbl, i, TRUE);
}
tbl->cursor_row = row;
@@ -3292,7 +4039,16 @@ cw_wm_mouse(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
x += tbl->scr_left;
y += tbl->scr_top - tbl->header_height;
- row = y / tbl->cell_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;
@@ -3313,22 +4069,41 @@ cw_wm_mouse(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
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[tbl->rows[row].col].x;
- 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;
+ 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;
+ }
}
}
}
@@ -3408,12 +4183,23 @@ cw_wm_mouse(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
InvalidateRect(tbl->hwnd, &r, TRUE);
}
if(tbl->mouse_state & CW_MOUSE_WSTICKY) {
- 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;
+ 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);
}
@@ -3436,12 +4222,23 @@ cw_wm_mouse(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
InvalidateRect(tbl->hwnd, &r, TRUE);
}
if(tbl->mouse_state & CW_MOUSE_WSTICKY) {
- 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;
+ 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) {
@@ -4200,6 +4997,7 @@ cw_wm_command(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
cw_update_creds(tbl);
cw_update_outline(tbl);
+ cw_update_selection_state(tbl);
cw_update_extents(tbl, TRUE);
InvalidateRect(tbl->hwnd, NULL, TRUE);
@@ -4216,12 +5014,11 @@ cw_wm_command(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
cw_update_creds(tbl);
cw_update_outline(tbl);
- cw_update_extents(tbl, FALSE);
+ cw_update_selection_state(tbl);
+ cw_update_extents(tbl, TRUE);
InvalidateRect(tbl->hwnd, NULL, TRUE);
- khui_check_radio_action(khui_find_menu(KHUI_MENU_LAYOUT), KHUI_ACTION_LAYOUT_ID);
- kmq_post_message(KMSG_ACT, KMSG_ACT_REFRESH, 0, 0);
}
break;
@@ -4235,13 +5032,11 @@ cw_wm_command(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
cw_update_creds(tbl);
cw_update_outline(tbl);
- cw_update_extents(tbl, FALSE);
+ cw_update_selection_state(tbl);
+ cw_update_extents(tbl, TRUE);
InvalidateRect(tbl->hwnd, NULL, TRUE);
- khui_check_radio_action(khui_find_menu(KHUI_MENU_LAYOUT),
- KHUI_ACTION_LAYOUT_LOC);
- kmq_post_message(KMSG_ACT, KMSG_ACT_REFRESH, 0, 0);
}
break;
@@ -4255,13 +5050,11 @@ cw_wm_command(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
cw_update_creds(tbl);
cw_update_outline(tbl);
- cw_update_extents(tbl, FALSE);
+ cw_update_selection_state(tbl);
+ cw_update_extents(tbl, TRUE);
InvalidateRect(tbl->hwnd, NULL, TRUE);
- khui_check_radio_action(khui_find_menu(KHUI_MENU_LAYOUT),
- KHUI_ACTION_LAYOUT_TYPE);
- kmq_post_message(KMSG_ACT, KMSG_ACT_REFRESH, 0, 0);
}
break;
@@ -4275,13 +5068,28 @@ cw_wm_command(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
cw_update_creds(tbl);
cw_update_outline(tbl);
- cw_update_extents(tbl, FALSE);
+ cw_update_selection_state(tbl);
+ cw_update_extents(tbl, TRUE);
InvalidateRect(tbl->hwnd, NULL, TRUE);
- khui_check_radio_action(khui_find_menu(KHUI_MENU_LAYOUT),
- KHUI_ACTION_LAYOUT_CUST);
- kmq_post_message(KMSG_ACT, KMSG_ACT_REFRESH, 0, 0);
+ }
+ 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;
@@ -4513,7 +5321,24 @@ cw_wm_contextmenu(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
- row = y / tbl->cell_height;
+ 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;
@@ -4618,7 +5443,7 @@ khm_register_credwnd_class(void) {
wcx.hInstance = khm_hInstance;
wcx.hIcon = NULL;
wcx.hCursor = LoadCursor((HINSTANCE) NULL, IDC_ARROW);
- wcx.hbrBackground = (HBRUSH) (COLOR_BACKGROUND + 1);
+ wcx.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
wcx.lpszMenuName = NULL;
wcx.lpszClassName = KHUI_CREDWND_CLASS_NAME;
wcx.hIconSm = NULL;
@@ -4658,7 +5483,7 @@ khm_create_credwnd(HWND parent) {
(0,
MAKEINTATOM(khui_credwnd_cls),
L"",
- WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL,
+ WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
r.left,
r.top,
r.right - r.left,
diff --git a/src/windows/identity/ui/credwnd.h b/src/windows/identity/ui/credwnd.h
index 50b7a11..adecb9f 100644
--- a/src/windows/identity/ui/credwnd.h
+++ b/src/windows/identity/ui/credwnd.h
@@ -67,6 +67,10 @@ typedef struct khui_credwnd_outline_t {
#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;
@@ -74,12 +78,15 @@ typedef struct khui_credwnd_row_t {
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 */
@@ -109,6 +116,7 @@ typedef struct khui_credwnd_col_t {
#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
@@ -119,6 +127,27 @@ typedef struct khui_credwnd_col_t {
#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 */
@@ -163,31 +192,36 @@ typedef struct khui_credwnd_tbl_t {
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 grey background brush */
- HBRUSH hb_sel; /* selected 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 */
- COLORREF cr_normal; /* normal text color */
- COLORREF cr_sel; /* selected text color */
- COLORREF cr_hdr_normal; /* normal header text color */
- COLORREF cr_hdr_sel; /* selected header text color */
- HBRUSH hb_hdr_bg; /* header background color (normal) */
- HBRUSH hb_hdr_bg_exp; /* header background color (expired) */
- HBRUSH hb_hdr_bg_warn; /* header background color (warn) */
- HBRUSH hb_hdr_bg_crit; /* header background color (critical) */
- HBRUSH hb_hdr_bg_sel; /* header background color (selected) */
- HBRUSH hb_hdr_bg_def; /* header background color (default) */
+
HCURSOR hc_hand; /* the HAND cursor */
khui_ilist * ilist; /* image list */
-#if 0
- /* icon indices */
- int idx_expand; /* index of 'expanded' icon in image list */
- int idx_expand_hi; /* index of 'expanded' icon (highlighted) in image list */
- int idx_collapse; /* index of 'collapsed' icon in image list */
- int idx_collapse_hi; /* index of 'collapsed' icon (highlighted) in image list */
- int idx_ident; /* index of 'identity' icon in image list */
-#endif
+ HICON hi_lg_ident; /* large identity icon */
/* mouse state */
khm_int32 mouse_state; /* state of the mouse can be combo of CW_MOUSE_* values */
@@ -198,6 +232,11 @@ typedef struct khui_credwnd_tbl_t {
/* 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
@@ -209,6 +248,8 @@ typedef struct khui_credwnd_tbl_t {
#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 */
diff --git a/src/windows/identity/ui/htmlwnd.h b/src/windows/identity/ui/htmlwnd.h
deleted file mode 100644
index e69de29..0000000
--- a/src/windows/identity/ui/htmlwnd.h
+++ /dev/null
diff --git a/src/windows/identity/ui/htwnd.c b/src/windows/identity/ui/htwnd.c
index afb68aa..b7c0378 100644
--- a/src/windows/identity/ui/htwnd.c
+++ b/src/windows/identity/ui/htwnd.c
@@ -94,7 +94,7 @@ htw_size_table[] = {
htw_align_table[] = {
{L"left", ALIGN_LEFT},
- {L"center", ALIGN_LEFT},
+ {L"center", ALIGN_CENTER},
{L"right", ALIGN_RIGHT}
};
@@ -661,9 +661,10 @@ static LRESULT htw_paint(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
DrawEdge(hdc, &r, EDGE_SUNKEN, BF_ADJUST | BF_RECT | BF_FLAT);
#endif
- hbk = CreateSolidBrush(RGB(255,255,255));
+ hbk = GetSysColorBrush(COLOR_WINDOW);
FillRect(hdc, &r, hbk);
- DeleteObject(hbk);
+ hbk = NULL; /* We don't need to destroy system
+ brushes */
/* push the default format */
format_init(&s_stack);
@@ -671,7 +672,7 @@ static LRESULT htw_paint(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
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 = d->scroll_top + r.top;
+ y = r.top - d->scroll_top;
par_start = text;
@@ -732,10 +733,15 @@ static LRESULT htw_paint(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
x = r.left - d->scroll_left;
- if(align == ALIGN_CENTER)
- x += (r.right - r.left)/2 - p_width / 2;
- else if(align == ALIGN_RIGHT)
- x += (r.right - r.left) - p_width;
+ 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;
@@ -743,7 +749,7 @@ static LRESULT htw_paint(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
p_width = 0;
- while(*p) {
+ while(p && *p) {
if(*p == L'<') {
int talign = -1;
int n;
@@ -766,7 +772,7 @@ static LRESULT htw_paint(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
align = talign;
} else {
HFONT hfold;
- RECT rd,rt;
+ RECT rd;
c = wcschr(p, L'<');
if(!c)
@@ -777,15 +783,13 @@ static LRESULT htw_paint(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
SetTextColor(hdc, format_color(&s_stack));
GetTextExtentPoint32(hdc, p, (int)(c - p), &s);
- rd.left = x + p_width - d->scroll_left;
- rd.top = y - d->scroll_top;
- rd.right = x + p_width + s.cx - d->scroll_left;
- rd.bottom = y + l_height - d->scroll_top;
-
- if(IntersectRect(&rt, &rd, &r)) {
- DrawText(hdc, p, (int)(c - p), &rd,
- DT_BOTTOM | DT_LEFT | DT_SINGLELINE | DT_NOPREFIX);
- }
+ 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;
@@ -994,18 +998,39 @@ LRESULT CALLBACK khui_htwnd_proc(HWND hwnd,
case WM_ERASEBKGND:
{
+ HDC hdc = (HDC) wParam;
khui_htwnd_data * d;
+ HBRUSH hbr;
+ RECT r;
+
d = (khui_htwnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, 0);
- if(d->flags & KHUI_HTWND_TRANSPARENT)
- return TRUE;
+ GetClientRect(hwnd, &r);
+ hbr = GetSysColorBrush(COLOR_WINDOW);
+ FillRect(hdc, &r, hbr);
- return FALSE;
+ /* 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);
- break;
+ return 0;
case WM_SETCURSOR:
{
@@ -1088,9 +1113,17 @@ LRESULT CALLBACK khui_htwnd_proc(HWND hwnd,
old_pos = new_pos = d->scroll_left;
ext = d->ext_width;
- switch(HIWORD(wParam)) {
- case SB_THUMBTRACK:
+ 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;
@@ -1122,12 +1155,8 @@ LRESULT CALLBACK khui_htwnd_proc(HWND hwnd,
GetClientRect(hwnd, &r);
-#if 0
if (new_pos > ext - (r.right - r.left))
new_pos = ext - (r.right - r.left);
-#endif
- if (new_pos > ext)
- new_pos = ext;
if (new_pos < 0)
new_pos = 0;
@@ -1180,13 +1209,15 @@ LRESULT CALLBACK khui_htwnd_proc(HWND hwnd,
if(d->active_link != nl) {
if(d->active_link >= 0) {
- if(d->flags & KHUI_HTWND_TRANSPARENT)
- {
- HWND parent = GetParent(hwnd);
- if(parent) {
- InvalidateRect(parent, NULL, TRUE);
- }
+ 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);
@@ -1195,13 +1226,15 @@ LRESULT CALLBACK khui_htwnd_proc(HWND hwnd,
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) {
- InvalidateRect(parent, NULL, TRUE);
- }
+ 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);
}
}
diff --git a/src/windows/identity/ui/khmapp.h b/src/windows/identity/ui/khmapp.h
index 203f5b0..54beb2a 100644
--- a/src/windows/identity/ui/khmapp.h
+++ b/src/windows/identity/ui/khmapp.h
@@ -36,19 +36,14 @@
#define KHERR_HMODULE khm_hInstance
#define KHERR_FACILITY khm_facility
#define KHERR_FACILITY_ID 3
+
#define NOEXPORT
-#include<khdefs.h>
-#include<khlist.h>
-#include<kherror.h>
-#include<kconfig.h>
-#include<kcreddb.h>
-#include<kmq.h>
-#include<khmsgtypes.h>
-#include<kmm.h>
+#include<netidmgr.h>
+
#include<khhelp.h>
-#include<khuidefs.h>
-#include<utils.h>
+#include<intaction.h>
+#include<intalert.h>
#include<resource.h>
#include<credfuncs.h>
@@ -65,6 +60,7 @@
#include<configwnd.h>
#include<aboutwnd.h>
#include<debugfuncs.h>
+#include<taskbar.h>
#include<reqdaemon.h>
#include<notifier.h>
diff --git a/src/windows/identity/ui/lang/en_us/khapp.rc b/src/windows/identity/ui/lang/en_us/khapp.rc
index 862872d..3ba3677 100644
--- a/src/windows/identity/ui/lang/en_us/khapp.rc
+++ b/src/windows/identity/ui/lang/en_us/khapp.rc
@@ -8,7 +8,6 @@
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
-
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
@@ -34,13 +33,12 @@ END
2 TEXTINCLUDE
BEGIN
- "#include ""afxres.h""\r\n"
+ "#include ""afxres.h\0"
END
3 TEXTINCLUDE
BEGIN
- "\r\n"
- "\0"
+ "\r\0"
END
#endif // APSTUDIO_INVOKED
@@ -174,28 +172,22 @@ BEGIN
LTEXT "TplInput",IDC_NC_TPL_INPUT,54,7,240,13,NOT WS_VISIBLE | WS_BORDER
LTEXT "TplLabelLg",IDC_NC_TPL_LABEL_LG,7,33,146,10,NOT WS_VISIBLE | WS_BORDER
LTEXT "TplInputLg",IDC_NC_TPL_INPUT_LG,155,31,139,13,NOT WS_VISIBLE | WS_BORDER
- LTEXT "&Credentials",IDC_NC_CREDTEXT_LABEL,7,66,41,10,NOT WS_GROUP
- CONTROL "",IDC_NC_CREDTEXT,"KhmHtWnd",WS_TABSTOP,54,65,240,73,WS_EX_CLIENTEDGE
- PUSHBUTTON "&Ok",IDOK,57,142,89,18,WS_DISABLED
- PUSHBUTTON "&Cancel",IDCANCEL,158,142,54,18
- PUSHBUTTON "&Options >>",IDC_NC_OPTIONS,223,142,71,18
-END
-
-IDD_NC_BBAR DIALOGEX 0, 0, 60, 181
-STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_SYSMENU
-EXSTYLE WS_EX_CONTROLPARENT
-FONT 8, "MS Shell Dlg", 400, 0, 0x1
-BEGIN
- DEFPUSHBUTTON "&Ok",IDOK,0,7,53,41,WS_DISABLED
- PUSHBUTTON "&Cancel",IDCANCEL,0,58,53,19
- PUSHBUTTON "&Help",IDC_NC_HELP,0,155,53,19
+ LTEXT "&Credentials",IDC_NC_CREDTEXT_LABEL,7,66,41,10,NOT WS_VISIBLE | NOT WS_GROUP
+ CONTROL "",IDC_NC_CREDTEXT,"KhmHtWnd",NOT WS_VISIBLE | WS_TABSTOP,54,65,240,95,WS_EX_CLIENTEDGE
+ PUSHBUTTON "&Ok",IDOK,101,142,89,18,WS_DISABLED
+ PUSHBUTTON "&Cancel",IDCANCEL,198,142,54,18
+ PUSHBUTTON "&>>",IDC_NC_ADVANCED,260,142,34,18
END
-IDD_NC_TS DIALOGEX 0, 0, 300, 15
+IDD_NC_BBAR DIALOGEX 0, 0, 66, 190
STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_SYSMENU
EXSTYLE WS_EX_CONTROLPARENT
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
+ DEFPUSHBUTTON "&Ok",IDOK,7,7,52,41,WS_DISABLED
+ PUSHBUTTON "&Cancel",IDCANCEL,7,58,52,19
+ PUSHBUTTON "<<",IDC_NC_BASIC,7,144,52,14
+ PUSHBUTTON "&Help",IDC_NC_HELP,7,164,52,19
END
IDD_PP_IDENT DIALOGEX 0, 0, 235, 156
@@ -247,23 +239,25 @@ IDD_CFG_GENERAL DIALOGEX 0, 0, 255, 182
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_SYSMENU
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
- GROUPBOX "Startup / Shutdown",IDC_CFG_STARTUP_GROUP,7,7,241,50
+ GROUPBOX "Startup / Shutdown",IDC_CFG_STARTUP_GROUP,7,7,241,44
CONTROL "&Obtain new credentials at startup (if none are present)",IDC_CFG_AUTOINIT,
- "Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,22,196,10
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,20,196,10
CONTROL "&Destroy all credentials on exit",IDC_CFG_DESTROYALL,
- "Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,39,111,10
- CONTROL "&Start Network Identity Manager during Windows logon",IDC_CFG_AUTOSTART,
- "Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_DISABLED | WS_TABSTOP,16,48,135,10
- GROUPBOX "Other",IDC_CFG_OTHER,7,63,241,85
- CONTROL "&Run Network Identity Manager in system tray after window close",IDC_CFG_KEEPRUNNING,
- "Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,78,230,10
- CONTROL "Monitor network connectivity",IDC_CFG_NETDETECT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,96,106,10
- CONTROL "Log trace events to trace log at the following location:",IDC_CFG_LOGTOFILE,
- "Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,113,225,10
- EDITTEXT IDC_CFG_LOGPATH,16,127,173,14,ES_AUTOHSCROLL | ES_READONLY
- PUSHBUTTON "Show log ...",IDC_CFG_SHOWLOG,193,127,50,14
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,36,111,10
+ GROUPBOX "Other",IDC_CFG_OTHER,7,55,241,120
+ CONTROL "&Run from taskbar notification area after window close",IDC_CFG_KEEPRUNNING,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,68,230,10
+ LTEXT "Clicking on the &notification icon",IDC_CFG_NOTACT_STATIC,26,87,99,8
+ COMBOBOX IDC_CFG_NOTACTION,133,85,110,48,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+ CONTROL "&Monitor network connectivity",IDC_CFG_NETDETECT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,104,106,10
+ CONTROL "&Log trace events to trace log at the following location:",IDC_CFG_LOGTOFILE,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,121,225,10
+ EDITTEXT IDC_CFG_LOGPATH,16,135,173,14,ES_AUTOHSCROLL | ES_READONLY
+ PUSHBUTTON "&Show log",IDC_CFG_SHOWLOG,193,135,50,14
CONTROL "A&utomatically import Windows logon identity",IDC_CFG_AUTOIMPORT,
- "Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_TABSTOP,16,158,165,10
+ "Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_TABSTOP,16,156,165,10
+ CONTROL "&Start Network Identity Manager during Windows logon",IDC_CFG_AUTOSTART,
+ "Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_DISABLED | WS_TABSTOP,113,165,135,10
END
IDD_CFG_IDENTITIES DIALOGEX 0, 0, 255, 182
@@ -349,18 +343,18 @@ BEGIN
PUSHBUTTON "Remove identity ...",IDC_CFG_REMOVE,139,122,78,14
END
-IDD_ABOUT DIALOGEX 0, 0, 268, 170
+IDD_ABOUT DIALOGEX 0, 0, 324, 238
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "About Network Identity Manager"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
- DEFPUSHBUTTON "OK",IDOK,211,7,50,14
- LTEXT "Productname",IDC_PRODUCT,41,7,163,13,NOT WS_GROUP
- LTEXT "© 2005-2007 Massachusetts Institute of Technology\n© 2006-2007 Secure Endpoints Inc.",IDC_COPYRIGHT,41,23,220,18,NOT WS_GROUP
- LTEXT "BuildInfo",IDC_BUILDINFO,41,43,220,15,NOT WS_GROUP
- ICON IDI_MAIN_APP,IDC_STATIC,6,7,20,20
- CONTROL "",IDC_MODULES,"SysListView32",LVS_REPORT | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,41,72,220,91
- LTEXT "Loaded modules",IDC_STATIC,41,60,52,8
+ DEFPUSHBUTTON "OK",IDOK,267,7,50,14
+ LTEXT "Productname",IDC_PRODUCT,41,7,225,13,NOT WS_GROUP
+ LTEXT "© 2005-2007 Massachusetts Institute of Technology\n© 2006-2007 Secure Endpoints Inc.",IDC_COPYRIGHT,41,23,276,23,NOT WS_GROUP
+ LTEXT "BuildInfo",IDC_BUILDINFO,41,49,276,20,NOT WS_GROUP
+ ICON IDI_MAIN_APP,IDC_STATIC,6,7,21,20
+ CONTROL "",IDC_MODULES,"SysListView32",LVS_REPORT | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,41,88,276,143
+ LTEXT "Loaded modules",IDC_STATIC,41,76,52,8
END
IDD_CFG_APPEAR DIALOGEX 0, 0, 255, 182
@@ -414,9 +408,10 @@ BEGIN
IDD_NC_BBAR, DIALOG
BEGIN
- RIGHTMARGIN, 53
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 59
TOPMARGIN, 7
- BOTTOMMARGIN, 174
+ BOTTOMMARGIN, 183
END
IDD_PP_IDENT, DIALOG
@@ -513,11 +508,11 @@ BEGIN
IDD_ABOUT, DIALOG
BEGIN
LEFTMARGIN, 6
- RIGHTMARGIN, 261
+ RIGHTMARGIN, 317
VERTGUIDE, 41
- VERTGUIDE, 204
+ VERTGUIDE, 266
TOPMARGIN, 7
- BOTTOMMARGIN, 163
+ BOTTOMMARGIN, 231
END
IDD_CFG_APPEAR, DIALOG
@@ -560,17 +555,17 @@ STRINGTABLE
BEGIN
IDS_MENU_OPTIONS "&Options"
IDS_MENU_HELP "&Help"
- IDS_ACTION_PROPERTIES "&Properties ..."
+ IDS_ACTION_PROPERTIES "&Properties"
IDS_ACTION_EXIT "E&xit"
IDS_CFG_ROOT_NAME "Network Identity Manager"
IDS_ACTION_SET_DEF_ID "Set as &default"
IDS_ACTION_SET_SRCH_ID "Allow applications to &search"
IDS_CFG_ROOT_TITLE "Network Identity Manager Configuration"
IDS_CFG_GENERAL_SHORT "General"
- IDS_ACTION_NEW_CRED "&New credentials ..."
- IDS_ACTION_PASSWD_ID "Change &password ..."
+ IDS_ACTION_NEW_CRED "Obtain &new credentials ..."
+ IDS_ACTION_PASSWD_ID "Change &password"
IDS_ACTION_CHOOSE_COLS "View columns"
- IDS_ACTION_DEBUG_WINDOW "Debug window ..."
+ IDS_ACTION_DEBUG_WINDOW "Debug window"
IDS_ACTION_VIEW_REFRESH "Refresh view"
IDS_MENU_LAYOUT "Layout"
IDS_MENU_TOOLBARS "Toolbars"
@@ -582,16 +577,16 @@ BEGIN
IDS_ACTION_LAYOUT_TYPE "By type"
IDS_ACTION_LAYOUT_LOC "By location"
IDS_ACTION_TB_STANDARD "Standard"
- IDS_ACTION_OPT_KHIM "General ..."
- IDS_ACTION_OPT_IDENTS "Identities ..."
- IDS_ACTION_OPT_NOTIF "Notifications ..."
- IDS_ACTION_HELP_CTX "Help Index"
- IDS_ACTION_HELP_CONTENTS "Contents ..."
- IDS_ACTION_HELP_INDEX "Index ..."
- IDS_ACTION_HELP_ABOUT "About Network Identity Manager ..."
+ IDS_ACTION_OPT_KHIM "General"
+ IDS_ACTION_OPT_IDENTS "Identities"
+ IDS_ACTION_OPT_NOTIF "Notifications"
+ IDS_ACTION_HELP_CTX "Help Contents"
+ IDS_ACTION_HELP_CONTENTS "Contents"
+ IDS_ACTION_HELP_INDEX "Index"
+ IDS_ACTION_HELP_ABOUT "About Network Identity Manager"
IDS_CFG_GENERAL_LONG "General options"
IDS_SAMPLE_STRING "Wxy"
- IDS_NO_CREDS "<large><center>You currently have no credentials.Click <a id=""NewCreds"">here</a> to obtain new credentials.</center></large>"
+ IDS_NO_CREDS "<large><p align=""center"">You currently have no credentials.</p><p align=""center"">Click <a id=""NewCreds"">here</a> to obtain new credentials.</p></large>"
IDS_WT_INIT_CREDS "Obtain initial credentials"
IDS_WT_NEW_CREDS "Obtain new credentials"
END
@@ -607,7 +602,7 @@ BEGIN
IDS_WTPOST_INIT_CREDS " - Initial credentials"
IDS_WTPOST_NEW_CREDS " - New credentials"
IDS_ACTION_RENEW_CRED "R&enew credentials"
- IDS_ACTION_DESTROY_CRED "De&stroy credentials ..."
+ IDS_ACTION_DESTROY_CRED "De&stroy credentials"
IDS_DEFAULT_FONT "MS Shell Dlg"
IDS_NC_CREDTEXT_TABS "<settab pos=""15""><settab pos=""30""><settab pos=""45"">"
IDS_NOTIFY_PREFIX "Network Identity Manager - "
@@ -629,7 +624,7 @@ BEGIN
IDS_PROP_COL_VALUE "Value"
IDS_NC_NEW_IDENT "( New identity ... )"
IDS_NC_CREDTEXT_ID_CHECKING "<font color=""grey"">%s (Checking...)</font>"
- IDS_ACTION_OPEN_APP "Open Network Identity Manager ..."
+ IDS_ACTION_OPEN_APP "Show Network Identity Manager window"
IDS_CTX_NEW_IDENT "Obaining new identity"
IDS_CTX_NEW_CREDS "Obtaining new credentials"
IDS_CTX_RENEW_CREDS "Renewing credentials"
@@ -640,7 +635,7 @@ STRINGTABLE
BEGIN
IDS_CTX_PROC_NEW_CREDS "Obtaining new credentials for %1!s!"
IDS_CTX_PROC_RENEW_CREDS "Renewing credentials for %1!s!"
- IDS_ACTION_CLOSE_APP "Close Network Identity Manager window"
+ IDS_ACTION_CLOSE_APP "Hide Network Identity Manager window"
IDS_NC_FAILED_TITLE "Failed to acquire credentials"
IDS_CFG_IDENTITIES_SHORT "Identities"
IDS_CFG_IDENTITIES_LONG "Global Identity settings"
@@ -688,11 +683,11 @@ BEGIN
IDS_PISTATE_EXIT "Stopped"
IDS_CTX_PASSWORD "Changing password"
IDS_WT_PASSWORD "Changing password"
- IDS_WTPOST_PASSWORD " - Changing password"
+ IDS_WTPOST_PASSWORD " - Changing password"
IDS_CTX_PROC_PASSWORD "Changing password for %1!s!"
IDS_NC_PWD_FAILED_TITLE "Failed to change password"
- IDS_CMDLINE_HELP "Command line options for Network Identity Manager are :\n\n-a or --autoinit: Auto initialize credentials\n-i or --kinit: Obtain new credentials\n-d or --destroy: Destroy default identity\n-r or --renew: Renew all credentials"
- IDS_PACTION_NEXT "Next alert..."
+ IDS_CMDLINE_HELP "Command line options for Network Identity Manager are :\n\n-a or --autoinit: Auto initialize credentials\n-i or --kinit: Obtain new credentials\n-d or --destroy: Destroy default identity\n-r or --renew: Renew all credentials\n-x or --exit: Exit the running instance of Network Identity Manager"
+ IDS_PACTION_NEXT "Next alert"
IDS_ERR_TITLE_NO_IDENTPRO "Cannot proceed without identity provider"
END
@@ -703,7 +698,7 @@ BEGIN
"This is quite possibly caused by the identity provider module failing to load properly."
IDS_NC_REN_FAILED_TITLE "Failed to renew credentials"
IDS_CW_DEFAULT "(Default)"
- IDS_ACTION_OPT_PLUGINS "Plugins ..."
+ IDS_ACTION_OPT_PLUGINS "Plugins"
IDS_NC_SETDEF "&Set as default identity"
IDS_NC_ID_DEF "<p>This identity is the default</p>"
IDS_NC_ID_WDEF "<p>Will be the default. (<a id=""NotDef"">Don't make default</a>)</p>"
@@ -745,7 +740,7 @@ BEGIN
IDS_APR_SAMPLE_TEXT_NORMAL "Sample text (normal). 01234567890"
IDS_CFG_APPEAR_SHORT "Appearance"
IDS_CFG_APPEAR_LONG "Appearance"
- IDS_ACTION_OPT_APPEAR "Appearance ..."
+ IDS_ACTION_OPT_APPEAR "Appearance"
IDS_APR_SAMPLE_TEXT_SEL "Sample text (selected). 01234567890"
IDS_CFG_IDNAME_INV "The identity name %s is invalid."
IDS_CFG_IDNAME_PRB "Can't add new identity %s"
@@ -780,15 +775,41 @@ END
STRINGTABLE
BEGIN
- IDS_NC_REN_FAILED_TITLE_I "Failed to renew creds for %s"
+ IDS_NC_REN_FAILED_TITLE_I "Failed to renew credentials for %s"
IDS_CFG_IDNAME_NON "No identity selected. Please select an identity and try again."
- IDS_MENU_DESTROY_CRED "Destroy ..."
- IDS_MENU_RENEW_CRED "Renew ..."
- IDS_ACTION_DESTROY_ALL "All identities"
- IDS_ACTION_RENEW_ALL "All identities"
- IDS_IDACTION_RENEW "Renew credentials for %s"
- IDS_IDACTION_DESTROY "Destroy credentials for %s"
+ IDS_MENU_DESTROY_CRED "Destroy"
+ IDS_MENU_RENEW_CRED "Renew"
+ IDS_ACTION_DESTROY_ALL "Destroy all identities"
+ IDS_ACTION_RENEW_ALL "Renew all identities"
+ IDS_IDACTION_RENEW "Renew %s"
+ IDS_IDACTION_DESTROY "Destroy %s"
IDS_CTX_DESTROY_ID "Destroying identity %1!s!"
+ IDS_NCN_IDENT_INVALID "Identity %s is invalid."
+ IDS_NCN_IDENT_CHECKING "Checking identity %s ..."
+ IDS_NCN_IDENT_UNKNOWN "Validity of identity %s coudn't be determined."
+ IDS_REMOTE_FAIL "The instance of Network Identity Manager that is already running is not responding to the remote request properly. Please check if you are running the latest version of Network Identity Manger software included with MIT Kerberos for Windows."
+ IDS_REMOTE_FAIL_TITLE "Failed to communicate with Network Identity Manager"
+ IDS_IDACTION_NEW "Obtain new credentials for %s"
+ IDS_IDACTIONT_NEW "New credentials for %s"
+END
+
+STRINGTABLE
+BEGIN
+ IDS_IDACTIONT_RENEW "Renew credentials for %s"
+ IDS_IDACTIONT_DESTROY "Destroy credentials for %s"
+ IDS_ALERTTYPE_PLUGIN "Failed to load plug-in"
+ IDS_ALERTTYPE_EXPIRE "Credential expiration warning"
+ IDS_ALERTTYPE_RENEWFAIL "Failed to renew credentials"
+ IDS_ALERTTYPE_ACQUIREFAIL "Failed to acquire credentials"
+ IDS_ALERTTYPE_CHPW "Failed to change password"
+ IDS_ACTION_LAYOUT_MINI "&Advanced"
+ IDS_IDEXPDISP_NOCRED "(This identity has no credentials)"
+ IDS_IDEXPDISP_1CRED "(This identity has 1 credential)"
+ IDS_IDEXPDISP_NCRED "(This identity has %d credentials)"
+ IDS_CW_DEFAULTTF "(Default, %s)"
+ IDS_CW_TYPEF "(%s)"
+ IDS_CW_EXPIREF "Expires in %s"
+ IDS_CW_EXPIRED "(Expired)"
END
#endif // English (U.S.) resources
@@ -806,3 +827,4 @@ END
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED
+
diff --git a/src/windows/identity/ui/main.c b/src/windows/identity/ui/main.c
index c05fa6b..3e3a94f 100644
--- a/src/windows/identity/ui/main.c
+++ b/src/windows/identity/ui/main.c
@@ -30,6 +30,12 @@
#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;
@@ -39,9 +45,14 @@ khm_ui_4 khm_commctl_version = 0;
khm_startup_options khm_startup;
-khm_version app_version = {KH_VERSION_LIST};
+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();
@@ -49,9 +60,11 @@ void khm_init_gui(void) {
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();
@@ -59,6 +72,11 @@ void khm_exit_gui(void) {
khui_exit_menu();
khui_exit_rescache();
khui_exit_actions();
+
+ if (hr_coinitialize == S_OK ||
+ hr_coinitialize == S_FALSE) {
+ CoUninitialize();
+ }
}
void khm_parse_commandline(void) {
@@ -106,6 +124,13 @@ void khm_parse_commandline(void) {
!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];
@@ -122,7 +147,8 @@ void khm_parse_commandline(void) {
/* special: always enable renew when other options aren't specified */
if (!khm_startup.exit &&
!khm_startup.destroy &&
- !khm_startup.init)
+ !khm_startup.init &&
+ !khm_startup.remote_exit)
khm_startup.renew = TRUE;
}
@@ -188,9 +214,7 @@ 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;
- /* we set .active=FALSE for now. We don't need this to have a
- meaningful value until we enter a modal loop */
- khui_dialogs[n_khui_dialogs].active = FALSE;
+ khui_dialogs[n_khui_dialogs].active = TRUE;
n_khui_dialogs++;
} else {
#if DEBUG
@@ -283,17 +307,25 @@ void khm_leave_modal(void) {
} 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);
}
}
@@ -502,6 +534,20 @@ 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,
@@ -510,6 +556,7 @@ int WINAPI WinMain(HINSTANCE hInstance,
int rv = 0;
HANDLE h_appmutex;
BOOL slave = FALSE;
+ int mutex_retries = 5;
khm_hInstance = hInstance;
khm_nCmdShow = nCmdShow;
@@ -519,6 +566,11 @@ int WINAPI WinMain(HINSTANCE hInstance,
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;
@@ -531,6 +583,8 @@ int WINAPI WinMain(HINSTANCE hInstance,
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
@@ -545,8 +599,8 @@ int WINAPI WinMain(HINSTANCE hInstance,
/* we only open a main window if this is the only instance
of the application that is running. */
kmq_init();
- kmm_init();
khm_init_gui();
+ kmm_init();
kmq_set_completion_handler(KMSG_CRED, kmsg_cred_completion);
@@ -574,9 +628,9 @@ int WINAPI WinMain(HINSTANCE hInstance,
khm_exit_request_daemon();
+ kmm_exit();
khm_exit_gui();
khm_unregister_window_classes();
- kmm_exit();
kmq_exit();
CloseHandle(h_appmutex);
@@ -588,6 +642,9 @@ int WINAPI WinMain(HINSTANCE hInstance,
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);
@@ -598,11 +655,21 @@ int WINAPI WinMain(HINSTANCE hInstance,
break;
retries--;
+
+ /* if the app was just starting, we might have to wait
+ till the main window is created. */
+
Sleep(1000);
}
- if (!hwnd)
- return 2;
+ 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 */
@@ -647,6 +714,31 @@ int WINAPI WinMain(HINSTANCE hInstance,
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
@@ -656,43 +748,149 @@ int WINAPI WinMain(HINSTANCE hInstance,
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,
- 4096,
+ (DWORD) cb,
mapname);
if (hmap == NULL)
return 3;
- xfer = MapViewOfFile(hmap,
- FILE_MAP_WRITE,
- 0, 0,
- sizeof(khm_startup));
+ /* make the call */
- if (xfer) {
- memcpy(xfer, &khm_startup, sizeof(khm_startup));
+ if (use_cmd_v2) {
+ /* use the v2 structure */
+ struct tag_khm_startup_options_v2 v2opt;
- SendMessage(hwnd, WM_KHUI_ASSIGN_COMMANDLINE,
- 0, (LPARAM) tid);
+ 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 (xfer)
- UnmapViewOfFile(xfer);
+ 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))
- /* writes a report of memory leaks to the specified file. Should
- only be enabled on development versions. */
- PDUMP("memleak.txt");
+#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 c99cafa..6634549 100644
--- a/src/windows/identity/ui/mainmenu.c
+++ b/src/windows/identity/ui/mainmenu.c
@@ -49,6 +49,8 @@ void khui_init_menu(void) {
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) {
@@ -76,6 +78,50 @@ int khui_get_icon_index(int id) {
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;
@@ -93,13 +139,7 @@ void add_action_to_menu(HMENU hm, khui_action * act,
} else {
khui_menu_def * def;
- if (act->caption) {
- StringCbCopy(buf, sizeof(buf), act->caption);
- } else {
- LoadString(khm_hInstance,
- act->is_caption,
- buf, ARRAYLENGTH(buf));
- }
+ khm_get_action_caption(act->cmd, buf, sizeof(buf));
if(khui_get_cmd_accel_string(act->cmd, accel,
ARRAYLENGTH(accel))) {
@@ -141,8 +181,10 @@ void add_action_to_menu(HMENU hm, khui_action * act,
}
}
- if(flags & KHUI_ACTIONREF_DEFAULT)
+ if(flags & KHUI_ACTIONREF_DEFAULT) {
+ mii.fMask |= MIIM_STATE;
mii.fState |= MFS_DEFAULT;
+ }
}
InsertMenuItem(hm,idx,TRUE,&mii);
@@ -150,95 +192,126 @@ void add_action_to_menu(HMENU hm, khui_action * act,
static void refresh_menu(HMENU hm, khui_menu_def * def);
-static void refresh_menu_item(HMENU hm, khui_action * act,
- int idx, int flags) {
+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 (act == NULL)
- return;
- else {
- khui_menu_def * def;
-
- /* first check if the menu item is there. Otherwise we need
- to add it. */
- mii.fMask = MIIM_STATE;
- if (!GetMenuItemInfo(hm, act->cmd, FALSE, &mii)) {
- /* the 1000 is fairly arbitrary, but there should be much
- less menu items on a menu anyway. If there are that
- many items, the system would be unusable to the extent
- that the order of the items would be the least of our
- worries. */
- add_action_to_menu(hm, act, 1000, flags);
- return;
+ 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;
}
- mii.fMask = 0;
+ return 0;
+ }
- if(act->state & KHUI_ACTIONSTATE_DISABLED) {
- mii.fMask |= MIIM_STATE;
- mii.fState = MFS_DISABLED;
- } else {
+ /* 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_ENABLED;
+ 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;
}
+ }
- if(act->type & KHUI_ACTIONTYPE_TOGGLE) {
- mii.fMask |= MIIM_STATE;
- if (act->state & KHUI_ACTIONSTATE_CHECKED) {
- mii.fState |= MFS_CHECKED;
- } else {
- mii.fState |= MFS_UNCHECKED;
- }
+ 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);
+ SetMenuItemInfo(hm, act->cmd, FALSE, &mii);
- def = khui_find_menu(act->cmd);
- if(def) {
- MENUITEMINFO mii2;
+ def = khui_find_menu(act->cmd);
- mii2.cbSize = sizeof(mii2);
- mii2.fMask = MIIM_SUBMENU;
+ if(def) {
+ MENUITEMINFO mii2;
- if (GetMenuItemInfo(hm, act->cmd, FALSE, &mii2)) {
- refresh_menu(mii2.hSubMenu, def);
- }
+ 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;
- int i;
+ khm_size i, n;
- act = def->items;
- i = 0;
- while ((def->n_items == -1 && act->action != KHUI_MENU_END) ||
- (def->n_items >= 0 && i < (int) def->n_items)) {
- refresh_menu_item(hm, khui_find_action(act->action), i, act->flags);
- act++; i++;
+ 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;
- int i;
+ khm_size i, n;
if (main)
hm = CreateMenu();
else
hm = CreatePopupMenu();
- act = def->items;
- i = 0;
- while((!(def->state & KHUI_MENUSTATE_ALLOCD) && act->action != KHUI_MENU_END) ||
- ((def->state & KHUI_MENUSTATE_ALLOCD) && i < (int) def->n_items)) {
- add_action_to_menu(hm,khui_find_action(act->action),i,act->flags);
- act++; i++;
+ 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;
@@ -419,12 +492,8 @@ LRESULT khm_menu_handle_select(WPARAM wParam, LPARAM lParam) {
if(act == NULL || (act->is_tooltip == 0 && act->tooltip == NULL))
khm_statusbar_set_part(KHUI_SBPART_INFO, NULL, NULL);
else {
- if (act->tooltip)
- StringCbCopy(buf, sizeof(buf), act->tooltip);
- else
- LoadString(khm_hInstance,
- act->is_tooltip,
- buf, ARRAYLENGTH(buf));
+ khm_get_action_tooltip(act->cmd, buf, sizeof(buf));
+
khm_statusbar_set_part(KHUI_SBPART_INFO, NULL, buf);
}
}
@@ -566,6 +635,7 @@ struct identity_action_map {
khm_handle identity;
khm_int32 renew_cmd;
khm_int32 destroy_cmd;
+ khm_int32 new_cmd;
int refreshcycle;
};
@@ -583,7 +653,9 @@ 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) {
@@ -611,26 +683,55 @@ create_identity_cmd_map(khm_handle ident) {
actmap->identity = ident;
kcdb_identity_hold(ident);
- fmt[0] = L'\0';
- LoadString(khm_hInstance, IDS_IDACTION_RENEW,
- fmt, ARRAYLENGTH(fmt));
- StringCbPrintf(tooltip, sizeof(tooltip), fmt, idname);
+#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(NULL, idname, tooltip, NULL,
+ khui_action_create(actionname, caption, tooltip, NULL,
KHUI_ACTIONTYPE_TRIGGER, NULL);
- fmt[0] = L'\0';
- LoadString(khm_hInstance, IDS_IDACTION_DESTROY,
- fmt, ARRAYLENGTH(fmt));
- StringCbPrintf(tooltip, sizeof(tooltip), fmt, idname);
+ /* 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(NULL, idname, tooltip, NULL,
+ 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;
}
@@ -673,8 +774,8 @@ get_identity_cmd_map(khm_handle ident) {
}
}
-static khm_int32
-get_identity_renew_command(khm_handle ident) {
+khm_int32
+khm_get_identity_renew_action(khm_handle ident) {
struct identity_action_map * map;
map = get_identity_cmd_map(ident);
@@ -685,8 +786,8 @@ get_identity_renew_command(khm_handle ident) {
return 0;
}
-static khm_int32
-get_identity_destroy_command(khm_handle ident) {
+khm_int32
+khm_get_identity_destroy_action(khm_handle ident) {
struct identity_action_map * map;
map = get_identity_cmd_map(ident);
@@ -697,6 +798,18 @@ get_identity_destroy_command(khm_handle ident) {
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;
@@ -707,6 +820,20 @@ khm_refresh_identity_menus(void) {
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++;
@@ -747,6 +874,18 @@ khm_refresh_identity_menus(void) {
} 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
@@ -759,17 +898,18 @@ khm_refresh_identity_menus(void) {
khui_menu_remove_action(renew_def, 0);
t--;
}
- khui_menu_insert_action(renew_def, 0, KHUI_ACTION_RENEW_ALL, 0);
t = khui_menu_get_size(dest_def);
while(t) {
khui_menu_remove_action(dest_def, 0);
t--;
}
- khui_menu_insert_action(dest_def, 0, KHUI_ACTION_DESTROY_ALL, 0);
- if (idlist != NULL && n_idents > 0) {
+ 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);
}
@@ -785,18 +925,36 @@ khm_refresh_identity_menus(void) {
}
khui_menu_insert_action(renew_def, 1000,
- get_identity_renew_command(identity),
+ khm_get_identity_renew_action(identity),
0);
khui_menu_insert_action(dest_def, 1000,
- get_identity_destroy_command(identity),
+ 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
@@ -838,6 +996,12 @@ khm_check_identity_menu_action(khm_int32 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;
+ }
}
}
@@ -853,10 +1017,14 @@ void khm_menu_refresh_items(void) {
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);
}
diff --git a/src/windows/identity/ui/mainmenu.h b/src/windows/identity/ui/mainmenu.h
index a0f64a0..e8da77f 100644
--- a/src/windows/identity/ui/mainmenu.h
+++ b/src/windows/identity/ui/mainmenu.h
@@ -49,6 +49,12 @@ 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);
diff --git a/src/windows/identity/ui/mainwnd.c b/src/windows/identity/ui/mainwnd.c
index 71e09df..d177b11 100644
--- a/src/windows/identity/ui/mainwnd.c
+++ b/src/windows/identity/ui/mainwnd.c
@@ -1,997 +1,1358 @@
-/*
- * 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<intaction.h>
-#include<assert.h>
-
-ATOM khm_main_window_class;
-ATOM khm_null_window_class;
-HWND khm_hwnd_null;
-HWND khm_hwnd_main;
-HWND khm_hwnd_rebar;
-HWND khm_hwnd_main_cred;
-
-#define MW_RESIZE_TIMER 1
-#define MW_RESIZE_TIMEOUT 2000
-#define MW_REFRESH_TIMER 2
-#define MW_REFRESH_TIMEOUT 600
-
-void
-khm_set_dialog_result(HWND hwnd, LRESULT lr) {
-#pragma warning(push)
-#pragma warning(disable: 4244)
- SetWindowLongPtr(hwnd, DWLP_MSGRESULT, lr);
-#pragma warning(pop)
-}
-
-static void
-mw_restart_refresh_timer(HWND hwnd) {
- khm_handle csp_cw;
- khm_int32 timeout;
-
- KillTimer(hwnd, MW_REFRESH_TIMER);
- if (KHM_SUCCEEDED(khc_open_space(NULL,
- L"CredWindow",
- KHM_PERM_READ,
- &csp_cw))) {
- if (KHM_FAILED(khc_read_int32(csp_cw,
- L"RefreshTimeout",
- &timeout)))
- timeout = MW_REFRESH_TIMEOUT;
- khc_close_space(csp_cw);
- } else {
- timeout = MW_REFRESH_TIMEOUT;
- }
-
- timeout *= 1000; /* convert to milliseconds */
-
- SetTimer(hwnd, MW_REFRESH_TIMER, timeout, NULL);
-}
-
-khm_int32 KHMAPI
-mw_select_cred(khm_handle cred, void * rock) {
- if (cred)
- kcdb_cred_set_flags(cred,
- KCDB_CRED_FLAG_SELECTED,
- KCDB_CRED_FLAG_SELECTED);
-
- return KHM_ERROR_SUCCESS;
-}
-
-/* perform shutdown operations */
-static void
-khm_pre_shutdown(void) {
- khm_handle csp_cw = NULL;
- khm_handle credset = NULL;
- khm_int32 t;
- khm_size s;
-
- /* Check if we should destroy all credentials on exit... */
-
- if (KHM_FAILED(khc_open_space(NULL, L"CredWindow", 0, &csp_cw)))
- return;
-
- if (KHM_FAILED(khc_read_int32(csp_cw, L"DestroyCredsOnExit", &t)) ||
- !t)
- goto _cleanup;
-
- if (KHM_FAILED(kcdb_credset_create(&credset)))
- goto _cleanup;
-
- if (KHM_FAILED(kcdb_credset_extract(credset, NULL, NULL,
- KCDB_TYPE_INVALID)))
- goto _cleanup;
-
- if (KHM_FAILED(kcdb_credset_get_size(credset, &s)) ||
- s == 0)
- goto _cleanup;
-
- kcdb_credset_apply(credset, mw_select_cred, NULL);
-
- khui_context_set(KHUI_SCOPE_GROUP,
- NULL,
- KCDB_CREDTYPE_INVALID,
- NULL,
- NULL,
- 0,
- credset);
-
- khm_cred_destroy_creds(TRUE, TRUE);
-
- _cleanup:
-
- if (credset)
- kcdb_credset_delete(credset);
-
- if (csp_cw)
- khc_close_space(csp_cw);
-}
-
-void
-khm_process_query_app_ver(khm_query_app_version * papp_ver) {
-
- if (!papp_ver || papp_ver->magic != KHM_QUERY_APP_VER_MAGIC)
- return;
-
- papp_ver->ver_remote = app_version;
-
- /* the remote instance has requested swapping in. we check the
- version numbers and if the remote instance is newer than us,
- then we exit and let the remote instance take over. */
- if (papp_ver->request_swap) {
- khm_version ver_caller = papp_ver->ver_caller;
-
- if (ver_caller.major > app_version.major ||
-
- (ver_caller.major == app_version.major &&
- ver_caller.minor > app_version.minor) ||
-
- (ver_caller.major == app_version.major &&
- ver_caller.minor == app_version.minor &&
- ver_caller.aux > app_version.aux) ||
-
- (ver_caller.major == app_version.major &&
- ver_caller.minor == app_version.minor &&
- ver_caller.aux == app_version.aux &&
- ver_caller.patch > app_version.patch)) {
-
- papp_ver->request_swap = TRUE;
-
- if (khm_hwnd_main)
- DestroyWindow(khm_hwnd_main);
-
- } else {
-
- papp_ver->request_swap = FALSE;
-
- }
- }
-
- papp_ver->code = KHM_ERROR_SUCCESS;
-}
-
-static void
-khm_ui_cb(LPARAM lParam) {
- khui_ui_callback_data * pcbdata;
-
- pcbdata = (khui_ui_callback_data *) lParam;
-
- if (pcbdata == NULL || pcbdata->magic != KHUI_UICBDATA_MAGIC) {
-#ifdef DEBUG
- assert(FALSE);
-#endif
- return;
- }
-
-#ifdef DEBUG
- assert(pcbdata->cb);
-#endif
-
- /* make the call */
- pcbdata->rv = (*pcbdata->cb)(khm_hwnd_main, pcbdata->rock);
-}
-
-LRESULT CALLBACK
-khm_main_wnd_proc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam)
-{
- LPNMHDR lpnm;
-
- switch(uMsg) {
- case WM_CREATE:
- khm_create_main_window_controls(hwnd);
- kmq_subscribe_hwnd(KMSG_CRED, hwnd);
- kmq_subscribe_hwnd(KMSG_ACT, hwnd);
- kmq_subscribe_hwnd(KMSG_KMM, hwnd);
- mw_restart_refresh_timer(hwnd);
-
- if (!kmm_load_pending())
- kmq_post_message(KMSG_ACT, KMSG_ACT_BEGIN_CMDLINE, 0, 0);
- break;
-
- case WM_DESTROY:
- khm_pre_shutdown();
- kmq_unsubscribe_hwnd(KMSG_ACT, hwnd);
- kmq_unsubscribe_hwnd(KMSG_CRED, hwnd);
- HtmlHelp(NULL, NULL, HH_CLOSE_ALL, 0);
- PostQuitMessage(0);
- break;
-
- case WM_NOTIFY:
- lpnm = (LPNMHDR) lParam;
- if(lpnm->hwndFrom == khui_main_menu_toolbar) {
- return khm_menu_notify_main(lpnm);
- } else if(lpnm->hwndFrom == khui_hwnd_standard_toolbar) {
- return khm_toolbar_notify(lpnm);
- } else if(lpnm->hwndFrom == khm_hwnd_rebar) {
- return khm_rebar_notify(lpnm);
- } else if(lpnm->hwndFrom == khm_hwnd_statusbar) {
- return khm_statusbar_notify(lpnm);
- }
- break;
-
- case WM_HELP:
- khm_html_help(khm_hwnd_main, NULL, HH_HELP_CONTEXT, IDH_WELCOME);
- break;
-
- case WM_COMMAND:
- switch(LOWORD(wParam)) {
- /* general actions */
- case KHUI_ACTION_VIEW_REFRESH:
- khm_cred_refresh();
- InvalidateRect(khm_hwnd_main_cred, NULL, FALSE);
- return 0;
-
- case KHUI_ACTION_PASSWD_ID:
- if (khm_startup.processing)
- return 0;
-
- khm_cred_change_password(NULL);
- return 0;
-
- case KHUI_ACTION_NEW_CRED:
- if (khm_startup.processing)
- return 0;
-
- khm_cred_obtain_new_creds(NULL);
- return 0;
-
- case KHUI_ACTION_RENEW_CRED:
- if (khm_startup.processing)
- return 0;
-
- khm_cred_renew_creds();
- return 0;
-
- case KHUI_ACTION_DESTROY_CRED:
- if (khm_startup.processing)
- return 0;
-
- khm_cred_destroy_creds(FALSE, FALSE);
- return 0;
-
- case KHUI_ACTION_SET_DEF_ID:
- if (khm_startup.processing)
- return 0;
-
- khm_cred_set_default();
- return 0;
-
- case KHUI_ACTION_EXIT:
- DestroyWindow(hwnd);
- break;
-
- case KHUI_ACTION_OPEN_APP:
- khm_show_main_window();
- break;
-
- case KHUI_ACTION_CLOSE_APP:
- khm_hide_main_window();
- break;
-
- case KHUI_ACTION_OPT_KHIM: {
- khui_config_node node = NULL;
-
- khui_cfg_open(NULL, L"KhmGeneral", &node);
- khm_show_config_pane(node);
- }
- break;
-
- case KHUI_ACTION_OPT_IDENTS: {
- khui_config_node node = NULL;
-
- khui_cfg_open(NULL, L"KhmIdentities", &node);
- khm_show_config_pane(node);
- }
- break;
-
- case KHUI_ACTION_OPT_APPEAR: {
- khui_config_node node = NULL;
-
- khui_cfg_open(NULL, L"KhmAppear", &node);
- khm_show_config_pane(node);
- }
- break;
-
- case KHUI_ACTION_OPT_NOTIF: {
- khui_config_node node = NULL;
-
- khui_cfg_open(NULL, L"KhmNotifications", &node);
- khm_show_config_pane(node);
- }
- break;
-
- case KHUI_ACTION_OPT_PLUGINS: {
- khui_config_node node = NULL;
-
- khui_cfg_open(NULL, L"KhmPlugins", &node);
- khm_show_config_pane(node);
- }
- break;
-
- case KHUI_ACTION_HELP_CTX:
- khm_html_help(khm_hwnd_main, NULL, HH_HELP_CONTEXT, IDH_WELCOME);
- break;
-
- case KHUI_ACTION_HELP_CONTENTS:
- khm_html_help(khm_hwnd_main, NULL, HH_DISPLAY_TOC, 0);
- break;
-
- case KHUI_ACTION_HELP_INDEX:
- khm_html_help(khm_hwnd_main, NULL, HH_DISPLAY_INDEX, (DWORD_PTR) L"");
- break;
-
- case KHUI_ACTION_HELP_ABOUT:
- khm_create_about_window();
- break;
-
- case KHUI_ACTION_IMPORT:
- khm_cred_import();
- break;
-
- case KHUI_ACTION_PROPERTIES:
- /* properties are not handled by the main window.
- Just bounce it to credwnd. However, use SendMessage
- instead of PostMessage so we don't lose context */
- return SendMessage(khm_hwnd_main_cred, uMsg,
- wParam, lParam);
-
- case KHUI_ACTION_UICB:
- khm_ui_cb(lParam);
- break;
-
- /* menu commands */
- case KHUI_PACTION_MENU:
- if(HIWORD(lParam) == 1)
- mm_last_hot_item = LOWORD(lParam);
- return khm_menu_activate(MENU_ACTIVATE_DEFAULT);
-
- case KHUI_PACTION_ESC:
- /* if esc is pressed while no menu is active, we close the
- main window */
- if (mm_last_hot_item == -1) {
- khm_close_main_window();
- return 0;
- }
-
- /* generic, retargetting */
- case KHUI_PACTION_UP:
- case KHUI_PACTION_UP_TOGGLE:
- case KHUI_PACTION_UP_EXTEND:
- case KHUI_PACTION_PGUP:
- case KHUI_PACTION_PGUP_EXTEND:
- case KHUI_PACTION_DOWN:
- case KHUI_PACTION_DOWN_TOGGLE:
- case KHUI_PACTION_DOWN_EXTEND:
- case KHUI_PACTION_PGDN:
- case KHUI_PACTION_PGDN_EXTEND:
- case KHUI_PACTION_LEFT:
- case KHUI_PACTION_RIGHT:
- case KHUI_PACTION_ENTER:
- /* menu tracking */
- if(mm_last_hot_item != -1) {
- switch(LOWORD(wParam)) {
- case KHUI_PACTION_LEFT:
- khm_menu_activate(MENU_ACTIVATE_LEFT);
- break;
-
- case KHUI_PACTION_RIGHT:
- khm_menu_activate(MENU_ACTIVATE_RIGHT);
- break;
-
- case KHUI_PACTION_ESC:
- case KHUI_PACTION_ENTER:
- khm_menu_activate(MENU_ACTIVATE_NONE);
- break;
-
- case KHUI_PACTION_DOWN:
- khm_menu_track_current();
- break;
- }
- return 0;
- }
-
- /*FALLTHROUGH*/
- case KHUI_PACTION_DELETE:
-
- case KHUI_PACTION_SELALL:
- case KHUI_ACTION_LAYOUT_ID:
- case KHUI_ACTION_LAYOUT_TYPE:
- case KHUI_ACTION_LAYOUT_LOC:
- case KHUI_ACTION_LAYOUT_CUST:
- case KHUI_ACTION_LAYOUT_RELOAD:
- /* otherwise fallthrough and bounce to the creds window */
- return SendMessage(khm_hwnd_main_cred, uMsg,
- wParam, lParam);
-
- default:
- /* handle custom actions here */
- {
- khui_action * act;
-
- /* check if this is an identity menu action. (custom
- actions that were created for renewing or
- destroying specific identities). */
- if (khm_check_identity_menu_action(LOWORD(wParam)))
- break;
-
- act = khui_find_action(LOWORD(wParam));
- if (act && act->listener) {
- kmq_post_sub_msg(act->listener, KMSG_ACT, KMSG_ACT_ACTIVATE, act->cmd, NULL);
- }
- }
- }
- break; /* WM_COMMAND */
-
- case WM_SYSCOMMAND:
- switch(wParam & 0xfff0) {
- case SC_MINIMIZE:
- khm_hide_main_window();
- return 0;
-
- case SC_CLOSE:
- khm_close_main_window();
- return 0;
- }
- break;
-
- case WM_MEASUREITEM:
- /* sent to measure the bitmaps associated with a menu item */
- if(!wParam) /* sent by menu */
- return khm_menu_measure_item(wParam, lParam);
- break;
-
- case WM_DRAWITEM:
- /* sent to draw a menu item */
- if(!wParam)
- return khm_menu_draw_item(wParam, lParam);
- break;
-
- case WM_ERASEBKGND:
- /* Don't erase the background. The whole client area is
- covered with children. It doesn't need to be erased */
- return TRUE;
- break;
-
- case WM_SIZE:
- if(hwnd == khm_hwnd_main &&
- (wParam == SIZE_MAXIMIZED || wParam == SIZE_RESTORED)) {
- int cwidth, cheight;
- RECT r_rebar, r_status;
-
- cwidth = LOWORD(lParam);
- cheight = HIWORD(lParam);
-
- /* resize the rebar control */
- SendMessage(khm_hwnd_rebar, WM_SIZE, 0, 0);
-
- khm_update_statusbar(hwnd);
-
- GetWindowRect(khm_hwnd_rebar, &r_rebar);
- GetWindowRect(khm_hwnd_statusbar, &r_status);
-
- /* the cred window fills the area between the rebar
- and the status bar */
- MoveWindow(khm_hwnd_main_cred, 0,
- r_rebar.bottom - r_rebar.top,
- r_status.right - r_status.left,
- r_status.top - r_rebar.bottom, TRUE);
-
- SetTimer(hwnd,
- MW_RESIZE_TIMER,
- MW_RESIZE_TIMEOUT,
- NULL);
- return 0;
- }
- break;
-
- case WM_MOVE:
- {
- SetTimer(hwnd,
- MW_RESIZE_TIMER,
- MW_RESIZE_TIMEOUT,
- NULL);
- }
- break;
-
- case WM_TIMER:
- if (wParam == MW_RESIZE_TIMER) {
- RECT r;
- khm_handle csp_cw;
- khm_handle csp_mw;
-
- KillTimer(hwnd, wParam);
-
- GetWindowRect(hwnd, &r);
-
- if (KHM_SUCCEEDED(khc_open_space(NULL,
- L"CredWindow",
- KHM_PERM_WRITE,
- &csp_cw))) {
- if (KHM_SUCCEEDED(khc_open_space(csp_cw,
- L"Windows\\Main",
- KHM_PERM_WRITE,
- &csp_mw))) {
- khc_write_int32(csp_mw, L"XPos", r.left);
- khc_write_int32(csp_mw, L"YPos", r.top);
- khc_write_int32(csp_mw, L"Width",
- r.right - r.left);
- khc_write_int32(csp_mw, L"Height",
- r.bottom - r.top);
-
- khc_close_space(csp_mw);
- }
- khc_close_space(csp_cw);
- }
- } else if (wParam == MW_REFRESH_TIMER) {
- kmq_post_message(KMSG_CRED, KMSG_CRED_REFRESH, 0, 0);
- }
- break;
-
- case WM_MENUSELECT:
- return khm_menu_handle_select(wParam, lParam);
- break;
-
- case KMQ_WM_DISPATCH:
- {
- kmq_message * m;
- khm_int32 rv = KHM_ERROR_SUCCESS;
-
- kmq_wm_begin(lParam, &m);
- if (m->type == KMSG_ACT &&
- m->subtype == KMSG_ACT_REFRESH) {
- khm_menu_refresh_items();
- khm_update_standard_toolbar();
- } else if (m->type == KMSG_ACT &&
- m->subtype == KMSG_ACT_BEGIN_CMDLINE) {
- khm_cred_begin_startup_actions();
- } else if (m->type == KMSG_ACT &&
- m->subtype == KMSG_ACT_CONTINUE_CMDLINE) {
- khm_cred_process_startup_actions();
- } else if (m->type == KMSG_ACT &&
- m->subtype == KMSG_ACT_SYNC_CFG) {
- khm_refresh_config();
- } else if (m->type == KMSG_ACT &&
- m->subtype == KMSG_ACT_ACTIVATE) {
- /* some custom action fired */
-
- khm_int32 action;
- khui_action * paction;
-
- action = m->uparam;
- paction = khui_find_action(action);
- if (paction && paction->data == (void *) CFGACTION_MAGIC) {
- /* a custom configuration needs to be invoked */
- khui_config_node node;
-
- if (KHM_SUCCEEDED(khui_cfg_open(NULL, paction->name, &node))) {
- khm_show_config_pane(node);
- khui_cfg_release(node);
- }
- }
- } else if (m->type == KMSG_CRED &&
- m->subtype == KMSG_CRED_REFRESH) {
- mw_restart_refresh_timer(hwnd);
- } else if (m->type == KMSG_CRED &&
- m->subtype == KMSG_CRED_ADDR_CHANGE) {
- khm_cred_addr_change();
- } else if (m->type == KMSG_CRED &&
- m->subtype == KMSG_CRED_ROOTDELTA) {
- khm_refresh_identity_menus();
- } else if (m->type == KMSG_KMM &&
- m->subtype == KMSG_KMM_I_DONE) {
- kmq_post_message(KMSG_ACT, KMSG_ACT_BEGIN_CMDLINE, 0, 0);
- }
- return kmq_wm_end(m, rv);
- }
- break;
-
- case WM_KHUI_ASSIGN_COMMANDLINE:
- {
- HANDLE hmap;
- void * xfer;
- wchar_t mapname[256];
-
- StringCbPrintf(mapname, sizeof(mapname),
- COMMANDLINE_MAP_FMT, (DWORD) lParam);
-
- hmap = OpenFileMapping(FILE_MAP_READ, FALSE, mapname);
-
- if (hmap == NULL)
- return 1;
-
- xfer = MapViewOfFile(hmap, FILE_MAP_READ, 0, 0,
- sizeof(khm_startup));
-
- if (xfer) {
- memcpy(&khm_startup, xfer, sizeof(khm_startup));
-
- UnmapViewOfFile(xfer);
- }
-
- CloseHandle(hmap);
-
- if(InSendMessage())
- ReplyMessage(0);
-
- khm_startup.exit = FALSE;
-
- khm_startup.seen = FALSE;
- khm_startup.processing = FALSE;
-
- khm_cred_begin_startup_actions();
- }
- break;
-
- case WM_KHUI_QUERY_APP_VERSION:
- {
- HANDLE hmap;
- void * xfer;
- wchar_t mapname[256];
-
- StringCbPrintf(mapname, sizeof(mapname),
- QUERY_APP_VER_MAP_FMT, (DWORD) lParam);
-
- hmap = OpenFileMapping(FILE_MAP_READ | FILE_MAP_WRITE,
- FALSE, mapname);
-
- if (hmap == NULL)
- return 1;
-
- xfer = MapViewOfFile(hmap, FILE_MAP_WRITE, 0, 0,
- sizeof(khm_query_app_version));
-
- if (xfer) {
- khm_process_query_app_ver((khm_query_app_version *) xfer);
-
- UnmapViewOfFile(xfer);
- }
-
- CloseHandle(hmap);
- }
- break;
-
- }
- return DefWindowProc(hwnd,uMsg,wParam,lParam);
-}
-
-LRESULT CALLBACK
-khm_null_wnd_proc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam) {
- return DefWindowProc(hwnd, uMsg, wParam, lParam);
-}
-
-LRESULT
-khm_rebar_notify(LPNMHDR lpnm) {
- switch(lpnm->code) {
-#if (_WIN32_WINNT >= 0x0501)
- case RBN_AUTOBREAK:
- {
- LPNMREBARAUTOBREAK lpra = (LPNMREBARAUTOBREAK) lpnm;
- lpra->fAutoBreak = TRUE;
- }
- break;
-#endif
- case RBN_BEGINDRAG:
- {
- LPNMREBAR lprb = (LPNMREBAR) lpnm;
- if ((lprb->dwMask & RBNM_ID) &&
- lprb->wID == 0)
- return 1;
- else
- return 0;
- }
- break;
-
- case NM_CUSTOMDRAW:
- return CDRF_DODEFAULT;
- break;
- }
-
- return 1;
-}
-
-void
-khm_create_main_window_controls(HWND hwnd_main) {
- REBARINFO rbi;
- HWND hwRebar;
-
- khm_menu_create_main(hwnd_main);
-
- hwRebar =
- CreateWindowEx(WS_EX_TOOLWINDOW,
- REBARCLASSNAME,
- L"Rebar",
- WS_CHILD |
- WS_VISIBLE|
- WS_CLIPSIBLINGS |
- WS_CLIPCHILDREN |
- CCS_NODIVIDER |
- RBS_VARHEIGHT |
- RBS_FIXEDORDER,
- 0,0,0,0,
- hwnd_main,
- NULL,
- khm_hInstance,
- NULL);
-
- if(!hwRebar) {
- DWORD dwe = GetLastError();
- return;
- }
-
- khm_hwnd_rebar = hwRebar;
-
- rbi.cbSize = sizeof(rbi);
- rbi.fMask = 0;
- rbi.himl = (HIMAGELIST) NULL;
- if(!SendMessage(hwRebar, RB_SETBARINFO, 0, (LPARAM) &rbi))
- return;
-
- /* self attach */
- khm_create_standard_toolbar(hwRebar);
- khm_create_statusbar(hwnd_main);
-
- /* manual attach */
- khm_hwnd_main_cred = khm_create_credwnd(hwnd_main);
-}
-
-void
-khm_create_main_window(void) {
- wchar_t buf[1024];
- khm_handle csp_cw = NULL;
- khm_handle csp_mw = NULL;
- int x,y,width,height;
-
- LoadString(khm_hInstance, IDS_MAIN_WINDOW_TITLE,
- buf, ARRAYLENGTH(buf));
-
- khm_hwnd_null =
- CreateWindow(MAKEINTATOM(khm_null_window_class),
- buf,
- 0, /* Style */
- 0, 0, /* x, y */
- 100, 100, /* width, height */
- NULL, /* parent */
- NULL, /* menu */
- NULL, /* HINSTANCE */
- 0); /* lparam */
-
- if (!khm_hwnd_null)
- return;
-
- x = CW_USEDEFAULT;
- y = CW_USEDEFAULT;
- width = CW_USEDEFAULT;
- height = CW_USEDEFAULT;
-
- if (KHM_SUCCEEDED(khc_open_space(NULL, L"CredWindow",
- KHM_PERM_READ,
- &csp_cw))) {
- if (KHM_SUCCEEDED(khc_open_space(csp_cw,
- L"Windows\\Main",
- KHM_PERM_READ,
- &csp_mw))) {
- khm_int32 t;
-
- if (KHM_SUCCEEDED(khc_read_int32(csp_mw, L"XPos", &t)))
- x = t;
- if (KHM_SUCCEEDED(khc_read_int32(csp_mw, L"YPos", &t)))
- y = t;
- if (KHM_SUCCEEDED(khc_read_int32(csp_mw, L"Width", &t)))
- width = t;
- if (KHM_SUCCEEDED(khc_read_int32(csp_mw, L"Height", &t)))
- height = t;
-
- khc_close_space(csp_mw);
- }
- khc_close_space(csp_cw);
- }
-
- khm_hwnd_main =
- CreateWindowEx(WS_EX_OVERLAPPEDWINDOW,
- MAKEINTATOM(khm_main_window_class),
- buf,
- WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN |
- WS_CLIPSIBLINGS,
- x, y, width, height,
- khm_hwnd_null,
- NULL,
- NULL,
- NULL);
-
- khui_set_main_window(khm_hwnd_main);
-}
-
-void
-khm_show_main_window(void) {
-
- if (khm_nCmdShow == SW_RESTORE) {
- HWND hw;
-
- hw = GetForegroundWindow();
- if (hw != khm_hwnd_main)
- SetForegroundWindow(khm_hwnd_main);
- }
-
- if (khm_nCmdShow == SW_SHOWMINIMIZED ||
- khm_nCmdShow == SW_SHOWMINNOACTIVE ||
- khm_nCmdShow == SW_MINIMIZE) {
- khm_hide_main_window();
- } else {
- ShowWindow(khm_hwnd_main, khm_nCmdShow);
- UpdateWindow(khm_hwnd_main);
- }
-
- khm_nCmdShow = SW_RESTORE;
-}
-
-void
-khm_activate_main_window(void) {
-
- if (!SetForegroundWindow(khm_hwnd_main)) {
- FLASHWINFO finfo;
-
- SetActiveWindow(khm_hwnd_main);
-
- ZeroMemory(&finfo, sizeof(finfo));
- finfo.cbSize = sizeof(finfo);
- finfo.hwnd = khm_hwnd_main;
- finfo.dwFlags = FLASHW_ALL;
- finfo.uCount = 3;
- finfo.dwTimeout = 0;
-
- FlashWindowEx(&finfo);
- }
-}
-
-void
-khm_close_main_window(void) {
- khm_handle csp_cw;
- BOOL keep_running = FALSE;
-
- if (KHM_SUCCEEDED(khc_open_space(NULL, L"CredWindow",
- KHM_PERM_READ, &csp_cw))) {
- khm_int32 t;
-
- if (KHM_SUCCEEDED(khc_read_int32(csp_cw, L"KeepRunning",
- &t))) {
- keep_running = t;
- } else {
-#ifdef DEBUG
- assert(FALSE);
-#endif
- }
-
- khc_close_space(csp_cw);
- } else {
-#ifdef DEBUG
- assert(FALSE);
-#endif
- }
-
- if (keep_running)
- khm_hide_main_window();
- else
- DestroyWindow(khm_hwnd_main);
-}
-
-void
-khm_hide_main_window(void) {
- khm_handle csp_notices = NULL;
- khm_int32 show_warning = FALSE;
-
- if (khm_nCmdShow != SW_MINIMIZE &&
- KHM_SUCCEEDED(khc_open_space(NULL, L"CredWindow\\Notices",
- KHM_PERM_WRITE, &csp_notices)) &&
- KHM_SUCCEEDED(khc_read_int32(csp_notices, L"MinimizeWarning",
- &show_warning)) &&
- show_warning != 0) {
-
- khui_alert * alert;
- wchar_t title[KHUI_MAXCCH_TITLE];
- wchar_t msg[KHUI_MAXCCH_MESSAGE];
-
- LoadString(khm_hInstance, IDS_WARN_WM_TITLE,
- title, ARRAYLENGTH(title));
- LoadString(khm_hInstance, IDS_WARN_WM_MSG,
- msg, ARRAYLENGTH(msg));
-
- khui_alert_create_simple(title, msg, KHERR_INFO, &alert);
- khui_alert_set_flags(alert, KHUI_ALERT_FLAG_REQUEST_BALLOON,
- KHUI_ALERT_FLAG_REQUEST_BALLOON);
-
- khui_alert_show(alert);
-
- khc_write_int32(csp_notices, L"MinimizeWarning", 0);
- }
-
- if (csp_notices != NULL)
- khc_close_space(csp_notices);
-
- ShowWindow(khm_hwnd_main, SW_HIDE);
-}
-
-BOOL
-khm_is_main_window_visible(void) {
- return IsWindowVisible(khm_hwnd_main);
-}
-
-BOOL
-khm_is_main_window_active(void) {
- if (!IsWindowVisible(khm_hwnd_main))
- return FALSE;
- if (GetForegroundWindow() == khm_hwnd_main)
- return TRUE;
- return khm_is_dialog_active();
-}
-
-void
-khm_register_main_wnd_class(void) {
- WNDCLASSEX wc;
-
- wc.cbSize = sizeof(WNDCLASSEX);
- wc.style = 0;
- wc.lpfnWndProc = khm_null_wnd_proc;
- wc.cbClsExtra = 0;
- wc.cbWndExtra = 0;
- wc.hInstance = khm_hInstance;
- wc.hIcon = LoadIcon(khm_hInstance, MAKEINTRESOURCE(IDI_MAIN_APP));
- wc.hCursor = LoadCursor((HINSTANCE) NULL, MAKEINTRESOURCE(IDC_ARROW));
- wc.hIconSm = LoadImage(khm_hInstance, MAKEINTRESOURCE(IDI_MAIN_APP), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE);
- wc.hbrBackground = (HBRUSH) (COLOR_APPWORKSPACE);
- wc.lpszMenuName = NULL;
- wc.lpszClassName = KHUI_NULL_WINDOW_CLASS;
-
- khm_null_window_class = RegisterClassEx(&wc);
-
- wc.cbSize = sizeof(WNDCLASSEX);
- wc.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
- wc.lpfnWndProc = khm_main_wnd_proc;
- wc.cbClsExtra = 0;
- wc.cbWndExtra = 0;
- wc.hInstance = khm_hInstance;
- wc.hIcon = LoadIcon(khm_hInstance, MAKEINTRESOURCE(IDI_MAIN_APP));
- wc.hCursor = LoadCursor((HINSTANCE) NULL, MAKEINTRESOURCE(IDC_ARROW));
- wc.hIconSm = LoadImage(khm_hInstance, MAKEINTRESOURCE(IDI_MAIN_APP), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE);
- wc.hbrBackground = (HBRUSH) (COLOR_APPWORKSPACE);
- wc.lpszMenuName = NULL;
- wc.lpszClassName = KHUI_MAIN_WINDOW_CLASS;
-
- khm_main_window_class = RegisterClassEx(&wc);
-}
-
-void
-khm_unregister_main_wnd_class(void) {
- UnregisterClass(MAKEINTATOM(khm_main_window_class),khm_hInstance);
- UnregisterClass(MAKEINTATOM(khm_null_window_class),khm_hInstance);
-}
+/*
+ * 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<intaction.h>
+#include<assert.h>
+
+ATOM khm_main_window_class;
+ATOM khm_null_window_class;
+HWND khm_hwnd_null;
+HWND khm_hwnd_main;
+HWND khm_hwnd_rebar;
+HWND khm_hwnd_main_cred;
+
+int khm_main_wnd_mode = KHM_MAIN_WND_NORMAL;
+
+#define MW_RESIZE_TIMER 1
+#define MW_RESIZE_TIMEOUT 2000
+#define MW_REFRESH_TIMER 2
+#define MW_REFRESH_TIMEOUT 600
+
+void
+khm_set_dialog_result(HWND hwnd, LRESULT lr) {
+#pragma warning(push)
+#pragma warning(disable: 4244)
+ SetWindowLongPtr(hwnd, DWLP_MSGRESULT, lr);
+#pragma warning(pop)
+}
+
+static void
+mw_restart_refresh_timer(HWND hwnd) {
+ khm_handle csp_cw;
+ khm_int32 timeout;
+
+ KillTimer(hwnd, MW_REFRESH_TIMER);
+ if (KHM_SUCCEEDED(khc_open_space(NULL,
+ L"CredWindow",
+ KHM_PERM_READ,
+ &csp_cw))) {
+ if (KHM_FAILED(khc_read_int32(csp_cw,
+ L"RefreshTimeout",
+ &timeout)))
+ timeout = MW_REFRESH_TIMEOUT;
+ khc_close_space(csp_cw);
+ } else {
+ timeout = MW_REFRESH_TIMEOUT;
+ }
+
+ timeout *= 1000; /* convert to milliseconds */
+
+ SetTimer(hwnd, MW_REFRESH_TIMER, timeout, NULL);
+}
+
+khm_int32 KHMAPI
+mw_select_cred(khm_handle cred, void * rock) {
+ if (cred)
+ kcdb_cred_set_flags(cred,
+ KCDB_CRED_FLAG_SELECTED,
+ KCDB_CRED_FLAG_SELECTED);
+
+ return KHM_ERROR_SUCCESS;
+}
+
+/* perform shutdown operations */
+static void
+khm_pre_shutdown(void) {
+ khm_handle csp_cw = NULL;
+ khm_handle credset = NULL;
+ khm_int32 t;
+ khm_size s;
+
+ /* Check if we should destroy all credentials on exit... */
+
+ if (KHM_FAILED(khc_open_space(NULL, L"CredWindow", 0, &csp_cw)))
+ return;
+
+ if (KHM_FAILED(khc_read_int32(csp_cw, L"DestroyCredsOnExit", &t)) ||
+ !t)
+ goto _cleanup;
+
+ if (KHM_FAILED(kcdb_credset_create(&credset)))
+ goto _cleanup;
+
+ if (KHM_FAILED(kcdb_credset_extract(credset, NULL, NULL,
+ KCDB_TYPE_INVALID)))
+ goto _cleanup;
+
+ if (KHM_FAILED(kcdb_credset_get_size(credset, &s)) ||
+ s == 0)
+ goto _cleanup;
+
+ kcdb_credset_apply(credset, mw_select_cred, NULL);
+
+ khui_context_set(KHUI_SCOPE_GROUP,
+ NULL,
+ KCDB_CREDTYPE_INVALID,
+ NULL,
+ NULL,
+ 0,
+ credset);
+
+ khm_cred_destroy_creds(TRUE, TRUE);
+
+ _cleanup:
+
+ if (credset)
+ kcdb_credset_delete(credset);
+
+ if (csp_cw)
+ khc_close_space(csp_cw);
+}
+
+void
+khm_process_query_app_ver(khm_query_app_version * papp_ver) {
+
+ if (!papp_ver || papp_ver->magic != KHM_QUERY_APP_VER_MAGIC)
+ return;
+
+ papp_ver->ver_remote = app_version;
+
+ /* the remote instance has requested swapping in. we check the
+ version numbers and if the remote instance is newer than us,
+ then we exit and let the remote instance take over. */
+ if (papp_ver->request_swap) {
+ khm_version ver_caller = papp_ver->ver_caller;
+
+ if (ver_caller.major > app_version.major ||
+
+ (ver_caller.major == app_version.major &&
+ ver_caller.minor > app_version.minor) ||
+
+ (ver_caller.major == app_version.major &&
+ ver_caller.minor == app_version.minor &&
+ ver_caller.aux > app_version.aux) ||
+
+ (ver_caller.major == app_version.major &&
+ ver_caller.minor == app_version.minor &&
+ ver_caller.aux == app_version.aux &&
+ ver_caller.patch > app_version.patch)) {
+
+ papp_ver->request_swap = TRUE;
+
+ if (khm_hwnd_main)
+ DestroyWindow(khm_hwnd_main);
+
+ } else {
+
+ papp_ver->request_swap = FALSE;
+
+ }
+ }
+
+ papp_ver->code = KHM_ERROR_SUCCESS;
+}
+
+static void
+khm_ui_cb(LPARAM lParam) {
+ khui_ui_callback_data * pcbdata;
+
+ pcbdata = (khui_ui_callback_data *) lParam;
+
+ if (pcbdata == NULL || pcbdata->magic != KHUI_UICBDATA_MAGIC) {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ return;
+ }
+
+#ifdef DEBUG
+ assert(pcbdata->cb);
+#endif
+
+ /* make the call */
+ if (!IsBadCodePtr(pcbdata->cb))
+ pcbdata->rv = (*pcbdata->cb)(khm_hwnd_main, pcbdata->rock);
+ else {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ pcbdata->rv = KHM_ERROR_INVALID_PARAM;
+ }
+}
+
+LRESULT CALLBACK
+khm_main_wnd_proc(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ LPNMHDR lpnm;
+
+ switch(uMsg) {
+ case WM_CREATE:
+ khm_create_main_window_controls(hwnd);
+ kmq_subscribe_hwnd(KMSG_CRED, hwnd);
+ kmq_subscribe_hwnd(KMSG_ACT, hwnd);
+ kmq_subscribe_hwnd(KMSG_KMM, hwnd);
+ mw_restart_refresh_timer(hwnd);
+
+ /* if the plug-ins finished loading before the window was
+ created, we would have missed the KMSG_KMM_I_DONE message.
+ So we check if the module load is complete and if so, fire
+ off KMSG_ACT_BEGIN_CMDLINE. */
+ if (!kmm_load_pending())
+ kmq_post_message(KMSG_ACT, KMSG_ACT_BEGIN_CMDLINE, 0, 0);
+ break;
+
+ case WM_DESTROY:
+ khm_pre_shutdown();
+ kmq_unsubscribe_hwnd(KMSG_ACT, hwnd);
+ kmq_unsubscribe_hwnd(KMSG_CRED, hwnd);
+ kmq_unsubscribe_hwnd(KMSG_KMM, hwnd);
+ HtmlHelp(NULL, NULL, HH_CLOSE_ALL, 0);
+ PostQuitMessage(0);
+ break;
+
+ case WM_NOTIFY:
+ lpnm = (LPNMHDR) lParam;
+ if(lpnm->hwndFrom == khui_main_menu_toolbar) {
+ return khm_menu_notify_main(lpnm);
+ } else if(lpnm->hwndFrom == khui_hwnd_standard_toolbar) {
+ return khm_toolbar_notify(lpnm);
+ } else if(lpnm->hwndFrom == khm_hwnd_rebar) {
+ return khm_rebar_notify(lpnm);
+ } else if(lpnm->hwndFrom == khm_hwnd_statusbar) {
+ return khm_statusbar_notify(lpnm);
+ }
+ break;
+
+ case WM_HELP:
+ khm_html_help(khm_hwnd_main, NULL, HH_HELP_CONTEXT, IDH_WELCOME);
+ break;
+
+ case WM_COMMAND:
+ switch(LOWORD(wParam)) {
+ /* general actions */
+ case KHUI_ACTION_VIEW_REFRESH:
+ khm_cred_refresh();
+ InvalidateRect(khm_hwnd_main_cred, NULL, FALSE);
+ return 0;
+
+ case KHUI_ACTION_PASSWD_ID:
+ if (khm_startup.processing)
+ return 0;
+
+ khm_cred_change_password(NULL);
+ return 0;
+
+ case KHUI_ACTION_NEW_CRED:
+ if (khm_startup.processing)
+ return 0;
+
+ khm_cred_obtain_new_creds(NULL);
+ return 0;
+
+ case KHUI_ACTION_RENEW_CRED:
+ if (khm_startup.processing)
+ return 0;
+
+ khm_cred_renew_creds();
+ return 0;
+
+ case KHUI_ACTION_DESTROY_CRED:
+ if (khm_startup.processing)
+ return 0;
+
+ khm_cred_destroy_creds(FALSE, FALSE);
+ return 0;
+
+ case KHUI_ACTION_SET_DEF_ID:
+ if (khm_startup.processing)
+ return 0;
+
+ khm_cred_set_default();
+ return 0;
+
+ case KHUI_ACTION_EXIT:
+ DestroyWindow(hwnd);
+ return 0;
+
+ case KHUI_ACTION_OPEN_APP:
+ khm_show_main_window();
+ return 0;
+
+ case KHUI_ACTION_CLOSE_APP:
+ khm_hide_main_window();
+ return 0;
+
+ case KHUI_ACTION_OPT_KHIM: {
+ khui_config_node node = NULL;
+
+ khui_cfg_open(NULL, L"KhmGeneral", &node);
+ khm_show_config_pane(node);
+ }
+ return 0;
+
+ case KHUI_ACTION_OPT_IDENTS: {
+ khui_config_node node = NULL;
+
+ khui_cfg_open(NULL, L"KhmIdentities", &node);
+ khm_show_config_pane(node);
+ }
+ return 0;
+
+ case KHUI_ACTION_OPT_APPEAR: {
+ khui_config_node node = NULL;
+
+ khui_cfg_open(NULL, L"KhmAppear", &node);
+ khm_show_config_pane(node);
+ }
+ return 0;
+
+ case KHUI_ACTION_OPT_NOTIF: {
+ khui_config_node node = NULL;
+
+ khui_cfg_open(NULL, L"KhmNotifications", &node);
+ khm_show_config_pane(node);
+ }
+ return 0;
+
+ case KHUI_ACTION_OPT_PLUGINS: {
+ khui_config_node node = NULL;
+
+ khui_cfg_open(NULL, L"KhmPlugins", &node);
+ khm_show_config_pane(node);
+ }
+ return 0;
+
+ case KHUI_ACTION_HELP_CTX:
+ khm_html_help(khm_hwnd_main, NULL, HH_HELP_CONTEXT, IDH_WELCOME);
+ return 0;
+
+ case KHUI_ACTION_HELP_CONTENTS:
+ khm_html_help(khm_hwnd_main, NULL, HH_DISPLAY_TOC, 0);
+ return 0;
+
+ case KHUI_ACTION_HELP_INDEX:
+ khm_html_help(khm_hwnd_main, NULL, HH_DISPLAY_INDEX, (DWORD_PTR) L"");
+ return 0;
+
+ case KHUI_ACTION_HELP_ABOUT:
+ khm_create_about_window();
+ return 0;
+
+ case KHUI_ACTION_IMPORT:
+ khm_cred_import();
+ return 0;
+
+ case KHUI_ACTION_PROPERTIES:
+ /* properties are not handled by the main window.
+ Just bounce it to credwnd. However, use SendMessage
+ instead of PostMessage so we don't lose context */
+ return SendMessage(khm_hwnd_main_cred, uMsg,
+ wParam, lParam);
+
+ case KHUI_ACTION_UICB:
+ khm_ui_cb(lParam);
+ return 0;
+
+ /* layout control */
+ case KHUI_ACTION_LAYOUT_MINI:
+ if (khm_main_wnd_mode == KHM_MAIN_WND_MINI) {
+ khm_set_main_window_mode(KHM_MAIN_WND_NORMAL);
+ } else {
+ khm_set_main_window_mode(KHM_MAIN_WND_MINI);
+ }
+ return SendMessage(khm_hwnd_main_cred, uMsg,
+ wParam, lParam);
+
+ case KHUI_ACTION_LAYOUT_RELOAD:
+ return SendMessage(khm_hwnd_main_cred, uMsg,
+ wParam, lParam);
+
+ case KHUI_ACTION_LAYOUT_ID:
+ case KHUI_ACTION_LAYOUT_TYPE:
+ case KHUI_ACTION_LAYOUT_LOC:
+ case KHUI_ACTION_LAYOUT_CUST:
+ khm_set_main_window_mode(KHM_MAIN_WND_NORMAL);
+ return SendMessage(khm_hwnd_main_cred, uMsg,
+ wParam, lParam);
+
+ /* menu commands */
+ case KHUI_PACTION_MENU:
+ if(HIWORD(lParam) == 1)
+ mm_last_hot_item = LOWORD(lParam);
+ return khm_menu_activate(MENU_ACTIVATE_DEFAULT);
+
+ case KHUI_PACTION_ESC:
+ /* if esc is pressed while no menu is active, we close the
+ main window */
+ if (mm_last_hot_item == -1) {
+ khm_close_main_window();
+ return 0;
+ }
+
+ /* generic, retargetting */
+ case KHUI_PACTION_UP:
+ case KHUI_PACTION_UP_TOGGLE:
+ case KHUI_PACTION_UP_EXTEND:
+ case KHUI_PACTION_PGUP:
+ case KHUI_PACTION_PGUP_EXTEND:
+ case KHUI_PACTION_DOWN:
+ case KHUI_PACTION_DOWN_TOGGLE:
+ case KHUI_PACTION_DOWN_EXTEND:
+ case KHUI_PACTION_PGDN:
+ case KHUI_PACTION_PGDN_EXTEND:
+ case KHUI_PACTION_LEFT:
+ case KHUI_PACTION_RIGHT:
+ case KHUI_PACTION_ENTER:
+ /* menu tracking */
+ if(mm_last_hot_item != -1) {
+ switch(LOWORD(wParam)) {
+ case KHUI_PACTION_LEFT:
+ khm_menu_activate(MENU_ACTIVATE_LEFT);
+ break;
+
+ case KHUI_PACTION_RIGHT:
+ khm_menu_activate(MENU_ACTIVATE_RIGHT);
+ break;
+
+ case KHUI_PACTION_ESC:
+ case KHUI_PACTION_ENTER:
+ khm_menu_activate(MENU_ACTIVATE_NONE);
+ break;
+
+ case KHUI_PACTION_DOWN:
+ khm_menu_track_current();
+ break;
+ }
+ return 0;
+ }
+
+ /*FALLTHROUGH*/
+ case KHUI_PACTION_DELETE:
+
+ case KHUI_PACTION_SELALL:
+ /* otherwise fallthrough and bounce to the creds window */
+ return SendMessage(khm_hwnd_main_cred, uMsg,
+ wParam, lParam);
+
+ default:
+ /* handle custom actions here */
+ {
+ khui_action * act;
+
+ /* check if this is an identity menu action. (custom
+ actions that were created for renewing or
+ destroying specific identities). */
+ if (khm_check_identity_menu_action(LOWORD(wParam)))
+ break;
+
+ act = khui_find_action(LOWORD(wParam));
+ if (act && act->listener) {
+ kmq_post_sub_msg(act->listener, KMSG_ACT, KMSG_ACT_ACTIVATE, act->cmd, NULL);
+ return 0;
+ }
+ }
+ }
+ break; /* WM_COMMAND */
+
+ case WM_SYSCOMMAND:
+ switch(wParam & 0xfff0) {
+ case SC_MINIMIZE:
+ khm_hide_main_window();
+ return 0;
+
+ case SC_CLOSE:
+ khm_close_main_window();
+ return 0;
+ }
+ break;
+
+ case WM_MEASUREITEM:
+ /* sent to measure the bitmaps associated with a menu item */
+ if(!wParam) /* sent by menu */
+ return khm_menu_measure_item(wParam, lParam);
+ break;
+
+ case WM_DRAWITEM:
+ /* sent to draw a menu item */
+ if(!wParam)
+ return khm_menu_draw_item(wParam, lParam);
+ break;
+
+ case WM_ERASEBKGND:
+ /* Don't erase the background. The whole client area is
+ covered with children. It doesn't need to be erased */
+ return TRUE;
+ break;
+
+ case WM_SIZE:
+ if(hwnd == khm_hwnd_main &&
+ (wParam == SIZE_MAXIMIZED || wParam == SIZE_RESTORED)) {
+ int cwidth, cheight;
+ RECT r_rebar, r_status;
+
+ cwidth = LOWORD(lParam);
+ cheight = HIWORD(lParam);
+
+ /* resize the rebar control */
+ SendMessage(khm_hwnd_rebar, WM_SIZE, 0, 0);
+
+ khm_update_statusbar(hwnd);
+
+ GetWindowRect(khm_hwnd_rebar, &r_rebar);
+ GetWindowRect(khm_hwnd_statusbar, &r_status);
+
+ /* the cred window fills the area between the rebar
+ and the status bar */
+ MoveWindow(khm_hwnd_main_cred, 0,
+ r_rebar.bottom - r_rebar.top,
+ r_status.right - r_status.left,
+ r_status.top - r_rebar.bottom, TRUE);
+
+ SetTimer(hwnd,
+ MW_RESIZE_TIMER,
+ MW_RESIZE_TIMEOUT,
+ NULL);
+ return 0;
+ }
+ break;
+
+ case WM_MOVE:
+ {
+ SetTimer(hwnd,
+ MW_RESIZE_TIMER,
+ MW_RESIZE_TIMEOUT,
+ NULL);
+
+ return 0;
+ }
+ break;
+
+ case WM_MOVING:
+ {
+ RECT * r;
+
+ r = (RECT *) lParam;
+ khm_adjust_window_dimensions_for_display(r,
+ KHM_DOCK_AUTO | KHM_DOCKF_XBORDER);
+ }
+ return TRUE;
+
+ case WM_TIMER:
+ if (wParam == MW_RESIZE_TIMER) {
+ RECT r;
+ khm_handle csp_cw;
+ khm_handle csp_mw;
+ const wchar_t * wconfig;
+
+ if (khm_main_wnd_mode == KHM_MAIN_WND_MINI)
+ wconfig = L"Windows\\MainMini";
+ else
+ wconfig = L"Windows\\Main";
+
+ KillTimer(hwnd, wParam);
+
+ GetWindowRect(hwnd, &r);
+
+ if (KHM_SUCCEEDED(khc_open_space(NULL,
+ L"CredWindow",
+ KHM_PERM_WRITE,
+ &csp_cw))) {
+ if (KHM_SUCCEEDED(khc_open_space(csp_cw,
+ wconfig,
+ KHM_PERM_WRITE,
+ &csp_mw))) {
+ khm_int32 t;
+
+ khc_write_int32(csp_mw, L"XPos", r.left);
+ khc_write_int32(csp_mw, L"YPos", r.top);
+ khc_write_int32(csp_mw, L"Width",
+ r.right - r.left);
+ khc_write_int32(csp_mw, L"Height",
+ r.bottom - r.top);
+
+ if (KHM_SUCCEEDED(khc_read_int32(csp_mw, L"Dock", &t)) &&
+ t != KHM_DOCK_NONE) {
+ khc_write_int32(csp_mw, L"Dock", KHM_DOCK_AUTO);
+ }
+
+ khc_close_space(csp_mw);
+ }
+ khc_close_space(csp_cw);
+ }
+
+ return 0;
+
+ } else if (wParam == MW_REFRESH_TIMER) {
+ kmq_post_message(KMSG_CRED, KMSG_CRED_REFRESH, 0, 0);
+
+ return 0;
+
+ }
+ break;
+
+ case WM_MENUSELECT:
+ return khm_menu_handle_select(wParam, lParam);
+
+ case KMQ_WM_DISPATCH:
+ {
+ kmq_message * m;
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+
+ kmq_wm_begin(lParam, &m);
+ if (m->type == KMSG_ACT &&
+ m->subtype == KMSG_ACT_REFRESH) {
+ khm_menu_refresh_items();
+ khm_update_standard_toolbar();
+ } else if (m->type == KMSG_ACT &&
+ m->subtype == KMSG_ACT_BEGIN_CMDLINE) {
+ khm_cred_begin_startup_actions();
+ } else if (m->type == KMSG_ACT &&
+ m->subtype == KMSG_ACT_CONTINUE_CMDLINE) {
+ khm_cred_process_startup_actions();
+ } else if (m->type == KMSG_ACT &&
+ m->subtype == KMSG_ACT_END_CMDLINE) {
+ /* nothing yet */
+ } else if (m->type == KMSG_ACT &&
+ m->subtype == KMSG_ACT_SYNC_CFG) {
+ khm_refresh_config();
+ } else if (m->type == KMSG_ACT &&
+ m->subtype == KMSG_ACT_ACTIVATE) {
+ /* some custom action fired */
+
+ khm_int32 action;
+ khui_action * paction;
+
+ action = m->uparam;
+ paction = khui_find_action(action);
+ if (paction && paction->data == (void *) CFGACTION_MAGIC) {
+ /* a custom configuration needs to be invoked */
+ khui_config_node node;
+
+ if (KHM_SUCCEEDED(khui_cfg_open(NULL, paction->name, &node))) {
+ khm_show_config_pane(node);
+ khui_cfg_release(node);
+ }
+ }
+ } else if (m->type == KMSG_CRED &&
+ m->subtype == KMSG_CRED_REFRESH) {
+ mw_restart_refresh_timer(hwnd);
+ } else if (m->type == KMSG_CRED &&
+ m->subtype == KMSG_CRED_ADDR_CHANGE) {
+ khm_cred_addr_change();
+ } else if (m->type == KMSG_CRED &&
+ m->subtype == KMSG_CRED_ROOTDELTA) {
+ khm_refresh_identity_menus();
+ } else if (m->type == KMSG_KMM &&
+ m->subtype == KMSG_KMM_I_DONE) {
+ kmq_post_message(KMSG_ACT, KMSG_ACT_BEGIN_CMDLINE, 0, 0);
+ }
+
+ return kmq_wm_end(m, rv);
+ }
+ return 0;
+
+ case WM_KHUI_ASSIGN_COMMANDLINE_V1:
+ {
+ HANDLE hmap;
+ void * xfer;
+ wchar_t mapname[256];
+ struct tag_khm_startup_options_v1 * pv1opt;
+ int code = KHM_ERROR_SUCCESS;
+
+ StringCbPrintf(mapname, sizeof(mapname),
+ COMMANDLINE_MAP_FMT, (DWORD) lParam);
+
+ hmap = OpenFileMapping(FILE_MAP_READ, FALSE, mapname);
+
+ if (hmap == NULL)
+ return 1;
+
+ xfer = MapViewOfFile(hmap, FILE_MAP_READ, 0, 0,
+ sizeof(*pv1opt));
+
+ if (xfer) {
+ pv1opt = (struct tag_khm_startup_options_v1 *) xfer;
+
+ khm_startup.init = pv1opt->init;
+ khm_startup.import = pv1opt->import;
+ khm_startup.renew = pv1opt->renew;
+ khm_startup.destroy = pv1opt->destroy;
+
+ khm_startup.autoinit = pv1opt->autoinit;
+ khm_startup.error_exit = FALSE;
+
+ khm_startup.no_main_window = FALSE;
+ khm_startup.remote_exit = FALSE;
+
+ UnmapViewOfFile(xfer);
+ } else {
+ code = KHM_ERROR_NOT_FOUND;
+ }
+
+ CloseHandle(hmap);
+
+ if(InSendMessage())
+ ReplyMessage(code);
+
+ if (code == KHM_ERROR_SUCCESS) {
+ khm_startup.exit = FALSE;
+
+ khm_startup.seen = FALSE;
+ khm_startup.remote = TRUE;
+#ifdef DEBUG
+ assert(!khm_startup.processing);
+#endif
+ khm_startup.processing = FALSE;
+
+ khm_cred_begin_startup_actions();
+ }
+
+ return code;
+ }
+
+ case WM_KHUI_ASSIGN_COMMANDLINE_V2:
+ {
+ HANDLE hmap;
+ void * xfer;
+ wchar_t mapname[256];
+ struct tag_khm_startup_options_v2 *pv2opt;
+ int code = KHM_ERROR_SUCCESS;
+
+ StringCbPrintf(mapname, sizeof(mapname),
+ COMMANDLINE_MAP_FMT, (DWORD) lParam);
+
+ hmap = OpenFileMapping(FILE_MAP_WRITE, FALSE, mapname);
+
+ if (hmap == NULL)
+ return 1;
+
+ xfer = MapViewOfFile(hmap, FILE_MAP_WRITE, 0, 0,
+ sizeof(*pv2opt));
+
+ if (xfer) {
+ pv2opt = (struct tag_khm_startup_options_v2 *) xfer;
+
+ if (pv2opt->magic != STARTUP_OPTIONS_MAGIC ||
+ pv2opt->cb_size != sizeof(*pv2opt)) {
+ code = KHM_ERROR_INVALID_PARAM;
+ goto done_with_v2_opt;
+ }
+
+ khm_startup.init = pv2opt->init;
+ khm_startup.import = pv2opt->import;
+ khm_startup.renew = pv2opt->renew;
+ khm_startup.destroy = pv2opt->destroy;
+
+ khm_startup.autoinit = pv2opt->autoinit;
+ khm_startup.exit = pv2opt->remote_exit;
+
+ pv2opt->code = KHM_ERROR_SUCCESS;
+
+ done_with_v2_opt:
+ UnmapViewOfFile(xfer);
+ } else {
+ code = KHM_ERROR_NOT_FOUND;
+ }
+
+ CloseHandle(hmap);
+
+ if(InSendMessage())
+ ReplyMessage(code);
+
+ if (code == KHM_ERROR_SUCCESS) {
+ khm_startup.seen = FALSE;
+ khm_startup.remote = TRUE;
+#ifdef DEBUG
+ assert(!khm_startup.processing);
+#endif
+ khm_startup.processing = FALSE;
+
+ khm_cred_begin_startup_actions();
+ }
+
+ return code;
+ }
+
+ case WM_KHUI_QUERY_APP_VERSION:
+ {
+ HANDLE hmap;
+ void * xfer;
+ wchar_t mapname[256];
+
+ StringCbPrintf(mapname, sizeof(mapname),
+ QUERY_APP_VER_MAP_FMT, (DWORD) lParam);
+
+ hmap = OpenFileMapping(FILE_MAP_READ | FILE_MAP_WRITE,
+ FALSE, mapname);
+
+ if (hmap == NULL)
+ return 1;
+
+ xfer = MapViewOfFile(hmap, FILE_MAP_WRITE, 0, 0,
+ sizeof(khm_query_app_version));
+
+ if (xfer) {
+ khm_process_query_app_ver((khm_query_app_version *) xfer);
+
+ UnmapViewOfFile(xfer);
+ }
+
+ CloseHandle(hmap);
+ }
+ return 0;
+
+ }
+ return DefWindowProc(hwnd,uMsg,wParam,lParam);
+}
+
+LRESULT CALLBACK
+khm_null_wnd_proc(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam) {
+ return DefWindowProc(hwnd, uMsg, wParam, lParam);
+}
+
+LRESULT
+khm_rebar_notify(LPNMHDR lpnm) {
+ switch(lpnm->code) {
+#if (_WIN32_WINNT >= 0x0501)
+ case RBN_AUTOBREAK:
+ {
+ LPNMREBARAUTOBREAK lpra = (LPNMREBARAUTOBREAK) lpnm;
+ lpra->fAutoBreak = TRUE;
+ }
+ break;
+#endif
+ case RBN_BEGINDRAG:
+ {
+ LPNMREBAR lprb = (LPNMREBAR) lpnm;
+ if ((lprb->dwMask & RBNM_ID) &&
+ lprb->wID == 0)
+ return 1;
+ else
+ return 0;
+ }
+ break;
+
+ case NM_CUSTOMDRAW:
+ return CDRF_DODEFAULT;
+ break;
+ }
+
+ return 1;
+}
+
+void
+khm_create_main_window_controls(HWND hwnd_main) {
+ REBARINFO rbi;
+ HWND hwRebar;
+
+ khm_menu_create_main(hwnd_main);
+
+ hwRebar =
+ CreateWindowEx(WS_EX_TOOLWINDOW,
+ REBARCLASSNAME,
+ L"Rebar",
+ WS_CHILD |
+ WS_VISIBLE|
+ WS_CLIPSIBLINGS |
+ WS_CLIPCHILDREN |
+ CCS_NODIVIDER |
+ RBS_VARHEIGHT |
+ RBS_FIXEDORDER,
+ 0,0,0,0,
+ hwnd_main,
+ NULL,
+ khm_hInstance,
+ NULL);
+
+ if(!hwRebar) {
+ DWORD dwe = GetLastError();
+ return;
+ }
+
+ khm_hwnd_rebar = hwRebar;
+
+ rbi.cbSize = sizeof(rbi);
+ rbi.fMask = 0;
+ rbi.himl = (HIMAGELIST) NULL;
+ if(!SendMessage(hwRebar, RB_SETBARINFO, 0, (LPARAM) &rbi))
+ return;
+
+ /* self attach */
+ khm_create_standard_toolbar(hwRebar);
+ khm_create_statusbar(hwnd_main);
+
+ /* manual attach */
+ khm_hwnd_main_cred = khm_create_credwnd(hwnd_main);
+}
+
+void
+khm_adjust_window_dimensions_for_display(RECT * pr, int dock) {
+
+ HMONITOR hmon;
+ RECT rm;
+ long x, y, width, height;
+
+ x = pr->left;
+ y = pr->top;
+ width = pr->right - pr->left;
+ height = pr->bottom - pr->top;
+
+ /* if the rect doesn't intersect with the display area of any
+ monitor, we just default to the primary monitor. */
+ hmon = MonitorFromRect(pr, MONITOR_DEFAULTTOPRIMARY);
+
+ if (hmon == NULL) {
+ /* huh? we'll just center this on the primary screen */
+ goto nomonitor;
+ } else {
+ MONITORINFO mi;
+
+ ZeroMemory(&mi, sizeof(mi));
+ mi.cbSize = sizeof(mi);
+
+ if (!GetMonitorInfo(hmon, &mi))
+ goto nomonitor;
+
+ CopyRect(&rm, &mi.rcWork);
+
+ goto adjust_dims;
+ }
+
+ nomonitor:
+ /* for some reason we couldn't get a handle on a monitor or we
+ couldn't get the metrics for that monitor. We default to
+ setting things up on the primary monitor. */
+
+ SetRectEmpty(&rm);
+ if (!SystemParametersInfo(SPI_GETWORKAREA, 0, (PVOID) &rm, 0))
+ goto done_with_monitor;
+
+ adjust_dims:
+
+ if (width > (rm.right - rm.left))
+ width = rm.right - rm.left;
+ if (height > (rm.bottom - rm.top))
+ height = rm.bottom - rm.top;
+
+ switch (dock & KHM_DOCKF_DOCKHINT) {
+ case KHM_DOCK_TOPLEFT:
+ x = rm.left;
+ y = rm.top;
+ break;
+
+ case KHM_DOCK_TOPRIGHT:
+ x = rm.right - width;
+ y = rm.top;
+ break;
+
+ case KHM_DOCK_BOTTOMRIGHT:
+ x = rm.right - width;
+ y = rm.bottom - height;
+ break;
+
+ case KHM_DOCK_BOTTOMLEFT:
+ x = rm.left;
+ y = rm.bottom - height;
+ break;
+
+ case KHM_DOCK_AUTO:
+ {
+ int cxt, cyt;
+
+ cxt = GetSystemMetrics(SM_CXDRAG);
+ cyt = GetSystemMetrics(SM_CYDRAG);
+
+ if (x > rm.left && (x - rm.left) < cxt)
+ x = rm.left;
+ else if ((x + width) < rm.right && (rm.right - (x + width)) < cxt)
+ x = rm.right - width;
+
+ if (y > rm.top && (y - rm.top) < cyt)
+ y = rm.top;
+ else if ((y + height) < rm.bottom && (rm.bottom - (y + height)) < cyt)
+ y = rm.bottom - height;
+ }
+ break;
+ }
+
+ if (!(dock & KHM_DOCKF_XBORDER)) {
+ if (x < rm.left)
+ x = rm.left;
+ if (x + width > rm.right)
+ x = rm.right - width;
+ if (y < rm.top)
+ y = rm.top;
+ if (y + height > rm.bottom)
+ y = rm.bottom - height;
+ }
+
+ done_with_monitor:
+ pr->left = x;
+ pr->top = y;
+ pr->right = x + width;
+ pr->bottom = y + height;
+
+}
+
+void
+khm_get_main_window_rect(RECT * pr) {
+ khm_handle csp_mw = NULL;
+ int x,y,width,height,dock;
+ RECT r;
+ const wchar_t * wconfig;
+
+ x = CW_USEDEFAULT;
+ y = CW_USEDEFAULT;
+ width = CW_USEDEFAULT;
+ height = CW_USEDEFAULT;
+ dock = KHM_DOCK_NONE;
+
+ if (khm_main_wnd_mode == KHM_MAIN_WND_MINI)
+ wconfig = L"CredWindow\\Windows\\MainMini";
+ else
+ wconfig = L"CredWindow\\Windows\\Main";
+
+ if (KHM_SUCCEEDED(khc_open_space(NULL,
+ wconfig,
+ KHM_PERM_READ,
+ &csp_mw))) {
+ khm_int32 t;
+
+ if (KHM_SUCCEEDED(khc_read_int32(csp_mw, L"XPos", &t)))
+ x = t;
+ if (KHM_SUCCEEDED(khc_read_int32(csp_mw, L"YPos", &t)))
+ y = t;
+ if (KHM_SUCCEEDED(khc_read_int32(csp_mw, L"Width", &t)))
+ width = t;
+ if (KHM_SUCCEEDED(khc_read_int32(csp_mw, L"Height", &t)))
+ height = t;
+ if (KHM_SUCCEEDED(khc_read_int32(csp_mw, L"Dock", &t)))
+ dock = t;
+
+ khc_close_space(csp_mw);
+ }
+
+ /* If there were no default values, we default to using 1/4 of the
+ work area centered on the primary monitor. If there were any
+ docking hints, then the next call to
+ khm_adjust_window_dimensions_for_display() will reposition the
+ window. */
+ if (width == CW_USEDEFAULT || x == CW_USEDEFAULT) {
+ RECT wr;
+
+ SetRectEmpty(&wr);
+ SystemParametersInfo(SPI_GETWORKAREA, 0, &wr, 0);
+
+ if (width == CW_USEDEFAULT) {
+ width = (wr.right - wr.left) / 2;
+ height = (wr.bottom - wr.top) / 2;
+ }
+
+ if (x == CW_USEDEFAULT) {
+ x = (wr.left + wr.right) / 2 - width / 2;
+ y = (wr.top + wr.bottom) / 2 - height / 2;
+ }
+ }
+
+ /* The saved dimensions might not actually be visible if the user
+ has changed the resolution of the display or if it's a multiple
+ monitor system where the monitor on which the Network Identity
+ Manager window was on previously is no longer connected. We
+ have to check for that and adjust the dimensions if needed. */
+ SetRect(&r, x, y, x + width, y + height);
+ khm_adjust_window_dimensions_for_display(&r, dock);
+
+ *pr = r;
+}
+
+void
+khm_set_main_window_mode(int mode) {
+
+ RECT r;
+ khm_handle csp_cw;
+
+ if (mode == khm_main_wnd_mode)
+ return;
+
+ khui_check_action(KHUI_ACTION_LAYOUT_MINI,
+ ((mode == KHM_MAIN_WND_MINI)? FALSE : TRUE));
+ khui_enable_action(KHUI_MENU_LAYOUT,
+ ((mode == KHM_MAIN_WND_MINI)? FALSE : TRUE));
+ khui_enable_action(KHUI_MENU_COLUMNS,
+ ((mode == KHM_MAIN_WND_MINI)? FALSE : TRUE));
+
+ khui_refresh_actions();
+
+ khm_main_wnd_mode = mode;
+ if (khm_hwnd_main) {
+ khm_get_main_window_rect(&r);
+
+ SetWindowPos(khm_hwnd_main,
+ NULL,
+ r.left, r.top,
+ r.right - r.left, r.bottom - r.top,
+ SWP_NOACTIVATE | SWP_NOOWNERZORDER |
+ SWP_NOZORDER);
+ }
+
+ if (KHM_SUCCEEDED(khc_open_space(NULL, L"CredWindow", KHM_PERM_WRITE,
+ &csp_cw))) {
+
+ khc_write_int32(csp_cw, L"DefaultWindowMode", mode);
+ khc_close_space(csp_cw);
+
+ }
+
+ khm_cred_refresh();
+}
+
+void
+khm_create_main_window(void) {
+ wchar_t buf[1024];
+ khm_handle csp_cw = NULL;
+ RECT r;
+
+ LoadString(khm_hInstance, IDS_MAIN_WINDOW_TITLE,
+ buf, ARRAYLENGTH(buf));
+
+ khm_hwnd_null =
+ CreateWindow(MAKEINTATOM(khm_null_window_class),
+ buf,
+ 0, /* Style */
+ 0, 0, /* x, y */
+ 100, 100, /* width, height */
+ NULL, /* parent */
+ NULL, /* menu */
+ NULL, /* HINSTANCE */
+ 0); /* lparam */
+
+ if (!khm_hwnd_null)
+ return;
+
+ if (KHM_SUCCEEDED(khc_open_space(NULL, L"CredWindow",
+ KHM_PERM_READ,
+ &csp_cw))) {
+ khm_int32 t;
+
+ if (KHM_SUCCEEDED(khc_read_int32(csp_cw, L"DefaultWindowMode", &t))) {
+ khm_set_main_window_mode(t);
+ }
+
+ khc_close_space(csp_cw);
+ }
+
+ khm_get_main_window_rect(&r);
+
+ khm_hwnd_main =
+ CreateWindowEx(WS_EX_OVERLAPPEDWINDOW | WS_EX_APPWINDOW,
+ MAKEINTATOM(khm_main_window_class),
+ buf,
+ WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN |
+ WS_CLIPSIBLINGS,
+ r.left, r.top,
+ r.right - r.left,
+ r.bottom - r.top,
+ khm_hwnd_null,
+ NULL,
+ NULL,
+ NULL);
+
+ khui_set_main_window(khm_hwnd_main);
+}
+
+void
+khm_show_main_window(void) {
+
+ if (khm_nCmdShow == SW_RESTORE) {
+ HWND hw;
+
+ hw = GetForegroundWindow();
+ if (hw != khm_hwnd_main)
+ SetForegroundWindow(khm_hwnd_main);
+ }
+
+ if (khm_nCmdShow == SW_SHOWMINIMIZED ||
+ khm_nCmdShow == SW_SHOWMINNOACTIVE ||
+ khm_nCmdShow == SW_MINIMIZE) {
+ khm_hide_main_window();
+ } else {
+ ShowWindow(khm_hwnd_main, khm_nCmdShow);
+ UpdateWindow(khm_hwnd_main);
+
+ khm_cred_refresh();
+ }
+
+ khm_nCmdShow = SW_RESTORE;
+}
+
+void
+khm_activate_main_window(void) {
+
+ if (!SetForegroundWindow(khm_hwnd_main)) {
+ FLASHWINFO finfo;
+
+ SetActiveWindow(khm_hwnd_main);
+
+ ZeroMemory(&finfo, sizeof(finfo));
+ finfo.cbSize = sizeof(finfo);
+ finfo.hwnd = khm_hwnd_main;
+ finfo.dwFlags = FLASHW_ALL;
+ finfo.uCount = 3;
+ finfo.dwTimeout = 0;
+
+ FlashWindowEx(&finfo);
+ }
+}
+
+void
+khm_close_main_window(void) {
+ khm_handle csp_cw;
+ BOOL keep_running = FALSE;
+
+ if (KHM_SUCCEEDED(khc_open_space(NULL, L"CredWindow",
+ KHM_PERM_READ, &csp_cw))) {
+ khm_int32 t;
+
+ if (KHM_SUCCEEDED(khc_read_int32(csp_cw, L"KeepRunning",
+ &t))) {
+ keep_running = t;
+ } else {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ }
+
+ khc_close_space(csp_cw);
+ } else {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ }
+
+ if (keep_running)
+ khm_hide_main_window();
+ else
+ DestroyWindow(khm_hwnd_main);
+}
+
+void
+khm_hide_main_window(void) {
+ khm_handle csp_notices = NULL;
+ khm_int32 show_warning = FALSE;
+
+ if (khm_nCmdShow != SW_MINIMIZE &&
+ KHM_SUCCEEDED(khc_open_space(NULL, L"CredWindow\\Notices",
+ KHM_PERM_WRITE, &csp_notices)) &&
+ KHM_SUCCEEDED(khc_read_int32(csp_notices, L"MinimizeWarning",
+ &show_warning)) &&
+ show_warning != 0) {
+
+ khui_alert * alert;
+ wchar_t title[KHUI_MAXCCH_TITLE];
+ wchar_t msg[KHUI_MAXCCH_MESSAGE];
+
+ LoadString(khm_hInstance, IDS_WARN_WM_TITLE,
+ title, ARRAYLENGTH(title));
+ LoadString(khm_hInstance, IDS_WARN_WM_MSG,
+ msg, ARRAYLENGTH(msg));
+
+ khui_alert_create_simple(title, msg, KHERR_INFO, &alert);
+ khui_alert_set_flags(alert, KHUI_ALERT_FLAG_REQUEST_BALLOON,
+ KHUI_ALERT_FLAG_REQUEST_BALLOON);
+
+ khui_alert_show(alert);
+
+ khc_write_int32(csp_notices, L"MinimizeWarning", 0);
+ }
+
+ if (csp_notices != NULL)
+ khc_close_space(csp_notices);
+
+ ShowWindow(khm_hwnd_main, SW_HIDE);
+}
+
+BOOL
+khm_is_main_window_visible(void) {
+ return IsWindowVisible(khm_hwnd_main);
+}
+
+BOOL
+khm_is_main_window_active(void) {
+ if (!IsWindowVisible(khm_hwnd_main))
+ return FALSE;
+ if (GetForegroundWindow() == khm_hwnd_main)
+ return TRUE;
+ return khm_is_dialog_active();
+}
+
+void
+khm_register_main_wnd_class(void) {
+ WNDCLASSEX wc;
+
+ wc.cbSize = sizeof(WNDCLASSEX);
+ wc.style = 0;
+ wc.lpfnWndProc = khm_null_wnd_proc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hInstance = khm_hInstance;
+ wc.hIcon = LoadIcon(khm_hInstance, MAKEINTRESOURCE(IDI_MAIN_APP));
+ wc.hCursor = LoadCursor((HINSTANCE) NULL, MAKEINTRESOURCE(IDC_ARROW));
+ wc.hIconSm = LoadImage(khm_hInstance, MAKEINTRESOURCE(IDI_MAIN_APP), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE);
+ wc.hbrBackground = (HBRUSH) (COLOR_APPWORKSPACE);
+ wc.lpszMenuName = NULL;
+ wc.lpszClassName = KHUI_NULL_WINDOW_CLASS;
+
+ khm_null_window_class = RegisterClassEx(&wc);
+
+ wc.cbSize = sizeof(WNDCLASSEX);
+ wc.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
+ wc.lpfnWndProc = khm_main_wnd_proc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hInstance = khm_hInstance;
+ wc.hIcon = LoadIcon(khm_hInstance, MAKEINTRESOURCE(IDI_MAIN_APP));
+ wc.hCursor = LoadCursor((HINSTANCE) NULL, MAKEINTRESOURCE(IDC_ARROW));
+ wc.hIconSm = LoadImage(khm_hInstance, MAKEINTRESOURCE(IDI_MAIN_APP), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE);
+ wc.hbrBackground = (HBRUSH) (COLOR_APPWORKSPACE);
+ wc.lpszMenuName = NULL;
+ wc.lpszClassName = KHUI_MAIN_WINDOW_CLASS;
+
+ khm_main_window_class = RegisterClassEx(&wc);
+}
+
+void
+khm_unregister_main_wnd_class(void) {
+ UnregisterClass(MAKEINTATOM(khm_main_window_class),khm_hInstance);
+ UnregisterClass(MAKEINTATOM(khm_null_window_class),khm_hInstance);
+}
diff --git a/src/windows/identity/ui/mainwnd.h b/src/windows/identity/ui/mainwnd.h
index 5d0bdc5..7b14d35 100644
--- a/src/windows/identity/ui/mainwnd.h
+++ b/src/windows/identity/ui/mainwnd.h
@@ -33,6 +33,12 @@
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);
@@ -40,10 +46,12 @@ 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
@@ -55,10 +63,20 @@ khm_main_wnd_proc(HWND hwnd,
WPARAM wParam,
LPARAM lParam);
-#define WM_KHUI_ASSIGN_COMMANDLINE 32808
#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/newcredwnd.c b/src/windows/identity/ui/newcredwnd.c
index 75ebef4..6c8ea60 100644
--- a/src/windows/identity/ui/newcredwnd.c
+++ b/src/windows/identity/ui/newcredwnd.c
@@ -1,1993 +1,2908 @@
-/*
- * 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 khui_newcredwnd_cls;
-
-/* forward dcl */
-static void
-nc_position_credtext(khui_nc_wnd_data * d);
-
-/* Common dialog procedure. Be careful. This is used by more than
- one dialog. */
-static INT_PTR CALLBACK
-nc_common_dlg_proc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam)
-{
- switch(uMsg) {
- case WM_INITDIALOG:
- {
- khui_nc_wnd_data * d;
-
- d = (khui_nc_wnd_data *) lParam;
-
-#pragma warning(push)
-#pragma warning(disable: 4244)
- SetWindowLongPtr(hwnd, DWLP_USER, lParam);
-#pragma warning(pop)
- if (d->nc->subtype == KMSG_CRED_PASSWORD) {
- ShowWindow(GetDlgItem(hwnd, IDC_NC_OPTIONS),
- SW_HIDE);
- }
- }
- return TRUE;
-
- case WM_COMMAND:
- {
- int ctrl_id;
-
- ctrl_id = LOWORD(wParam);
- if (ctrl_id < KHUI_CW_ID_MIN ||
- ctrl_id > KHUI_CW_ID_MAX) {
- /* pump it to the parent */
- PostMessage(GetParent(hwnd), WM_COMMAND, wParam, lParam);
- return TRUE;
- } /* else we allow the message to fall through and get
- passed into the identity provider's message
- handler. */
- }
- break;
-
-#if 0
- /* someday this will be used to draw custom tab buttons. But
- that's not today */
- case WM_DRAWITEM:
- {
- khui_nc_wnd_data * d;
- int id;
- LPDRAWITEMSTRUCT ds;
-
- d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, DWLP_USER);
- id = wParam;
- ds = (LPDRAWITEMSTRUCT) lParam;
-
- if(id >= NC_TS_CTRL_ID_MIN && id <= NC_TS_CTRL_ID_MAX) {
- /*TODO: custom draw the buttons */
- }
- else
- return FALSE;
- }
- break;
-#endif
-
- case KHUI_WM_NC_NOTIFY:
- {
- khui_nc_wnd_data * d;
- d = (khui_nc_wnd_data *)(LONG_PTR)
- GetWindowLongPtr(hwnd, DWLP_USER);
-
- /* message sent by parent to notify us of something */
- switch(HIWORD(wParam)) {
- case WMNC_DIALOG_EXPAND:
- if(hwnd == d->dlg_main) {
- HWND hw;
-
- if(hw = GetDlgItem(hwnd, IDOK))
- ShowWindow(hw, SW_HIDE);
- if(hw = GetDlgItem(hwnd, IDCANCEL))
- ShowWindow(hw, SW_HIDE);
- if(hw = GetDlgItem(hwnd, IDC_NC_OPTIONS))
- ShowWindow(hw, SW_HIDE);
-
- d->r_credtext.bottom = d->r_area.bottom;
-
- nc_position_credtext(d);
-
- return TRUE;
- }
- }
- }
- return TRUE;
- }
-
- /* check if we have a wnd_data, and if so pass the message on to
- the identity provider callback. */
- {
- khui_nc_wnd_data * d;
-
- d = (khui_nc_wnd_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);
- }
- }
-
- return FALSE;
-}
-
-static void
-nc_position_credtext(khui_nc_wnd_data * d)
-{
- HWND hw;
-
- hw = GetDlgItem(d->dlg_main, IDC_NC_CREDTEXT);
-#ifdef DEBUG
- assert(hw);
-#endif
-
- if (d->r_credtext.bottom < d->r_credtext.top + d->r_row.bottom * 2) {
- /* not enough room */
- if (d->nc->mode == KHUI_NC_MODE_MINI &&
- d->nc->subtype != KMSG_CRED_PASSWORD) {
- PostMessage(d->nc->hwnd, KHUI_WM_NC_NOTIFY,
- MAKEWPARAM(0, WMNC_DIALOG_EXPAND), 0);
- return;
- } else {
- ShowWindow(hw, SW_HIDE);
- return;
- }
- } else {
- ShowWindow(hw, SW_SHOW);
- }
-
- SetWindowPos(hw, NULL,
- d->r_credtext.left + d->r_n_input.left, /* x */
- d->r_credtext.top, /* y */
- d->r_n_input.right - d->r_n_input.left, /* width */
- d->r_credtext.bottom - d->r_credtext.top, /* height */
- SWP_NOACTIVATE | SWP_NOOWNERZORDER |
- SWP_NOZORDER);
-
- hw = GetDlgItem(d->dlg_main, IDC_NC_CREDTEXT_LABEL);
-
- SetWindowPos(hw, NULL,
- d->r_credtext.left + d->r_n_label.left, /* x */
- d->r_credtext.top, /* y */
- d->r_n_label.right - d->r_n_label.left, /* width */
- d->r_n_label.bottom - d->r_n_label.top, /* height */
- SWP_NOACTIVATE | SWP_NOOWNERZORDER |
- SWP_NOZORDER);
-}
-
-/* sorts tab buttons */
-static int __cdecl
-nc_tab_sort_func(const void * v1, const void * v2)
-{
- /* v1 and v2 and of type : khui_new_creds_by_type ** */
- khui_new_creds_by_type *t1, *t2;
-
- t1 = *((khui_new_creds_by_type **) v1);
- t2 = *((khui_new_creds_by_type **) v2);
-
- if(t1->ordinal != -1) {
- if(t2->ordinal != -1) {
- if(t1->ordinal == t2->ordinal)
- return wcscmp(t1->name, t2->name);
- else
- /* safe to convert to an int here */
- return (int) (t1->ordinal - t2->ordinal);
- } else
- return -1;
- } else {
- if(t2->ordinal != -1)
- return 1;
- else if (t1->name && t2->name)
- return wcscmp(t1->name, t2->name);
- else
- return 0;
- }
-}
-
-static void
-nc_notify_types_async(khui_new_creds * c, UINT uMsg,
- WPARAM wParam, LPARAM lParam)
-{
- khm_size i;
-
- for(i=0; i<c->n_types; i++) {
- PostMessage(c->types[i]->hwnd_panel, uMsg, wParam, lParam);
- }
-}
-
-static void
-nc_notify_types(khui_new_creds * c, UINT uMsg,
- WPARAM wParam, LPARAM lParam)
-{
- khm_size i;
-
- for(i=0; i<c->n_types; i++) {
- SendMessage(c->types[i]->hwnd_panel, uMsg, wParam, lParam);
- }
-}
-
-static void
-nc_clear_password_fields(khui_nc_wnd_data * d)
-{
- khm_size i;
- khm_boolean need_sync = FALSE;
-
- khui_cw_lock_nc(d->nc);
-
- for (i=0; i < d->nc->n_prompts; i++) {
- if ((d->nc->prompts[i]->flags & KHUI_NCPROMPT_FLAG_HIDDEN) &&
- d->nc->prompts[i]->hwnd_edit) {
- SetWindowText(d->nc->prompts[i]->hwnd_edit,
- L"");
- need_sync = TRUE;
- }
- }
-
- khui_cw_unlock_nc(d->nc);
-
- if (need_sync) {
- khui_cw_sync_prompt_values(d->nc);
- }
-}
-
-struct nc_enum_wnd_data {
- khui_nc_wnd_data * d;
- khm_boolean enable;
-};
-
-static
-BOOL CALLBACK
-nc_enum_wnd_proc(HWND hwnd,
- LPARAM lParam)
-{
- struct nc_enum_wnd_data * wd;
-
- wd = (struct nc_enum_wnd_data *) lParam;
-
- EnableWindow(hwnd, wd->enable);
-
- return TRUE;
-}
-
-static void
-nc_enable_controls(khui_nc_wnd_data * d, khm_boolean enable)
-{
- struct nc_enum_wnd_data wd;
-
- ZeroMemory(&wd, sizeof(wd));
-
- wd.d = d;
- wd.enable = enable;
-
- EnumChildWindows(d->dlg_main, nc_enum_wnd_proc, (LPARAM) &wd);
-}
-
-#define NC_MAXCCH_CREDTEXT 16384
-#define NC_MAXCB_CREDTEXT (NC_MAXCCH_CREDTEXT * sizeof(wchar_t))
-
-static void
-nc_update_credtext(khui_nc_wnd_data * d)
-{
- wchar_t * ctbuf = NULL;
- wchar_t * buf;
- BOOL okEnable = FALSE;
- BOOL validId = FALSE;
- HWND hw = NULL;
- size_t cch = 0;
-
- ctbuf = PMALLOC(NC_MAXCB_CREDTEXT);
-
- assert(ctbuf != NULL);
-
- LoadString(khm_hInstance, IDS_NC_CREDTEXT_TABS, ctbuf, NC_MAXCCH_CREDTEXT);
- StringCchLength(ctbuf, NC_MAXCCH_CREDTEXT, &cch);
- buf = ctbuf + cch;
- nc_notify_types(d->nc, KHUI_WM_NC_NOTIFY,
- MAKEWPARAM(0, WMNC_UPDATE_CREDTEXT), (LPARAM) d->nc);
-
- /* hopefully all the types have updated their credential texts */
- if(d->nc->n_identities == 1) {
- wchar_t main_fmt[256];
- wchar_t id_fmt[256];
- wchar_t id_name[KCDB_IDENT_MAXCCH_NAME];
- wchar_t id_string[KCDB_IDENT_MAXCCH_NAME + 256];
- khm_size cbbuf;
- khm_int32 flags;
-
- LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_ONE,
- main_fmt, (int) ARRAYLENGTH(main_fmt));
-
- cbbuf = sizeof(id_name);
- kcdb_identity_get_name(d->nc->identities[0], id_name, &cbbuf);
-
- kcdb_identity_get_flags(d->nc->identities[0], &flags);
-
- if (flags & KCDB_IDENT_FLAG_INVALID) {
- LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_INVALID,
- id_fmt, (int) ARRAYLENGTH(id_fmt));
- } else if(flags & KCDB_IDENT_FLAG_VALID) {
- LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_VALID,
- id_fmt, (int) ARRAYLENGTH(id_fmt));
- } else if(d->nc->subtype == KMSG_CRED_NEW_CREDS) {
- LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_CHECKING,
- id_fmt, (int) ARRAYLENGTH(id_fmt));
- } else {
- LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_UNCHECKED,
- id_fmt, (int) ARRAYLENGTH(id_fmt));
- }
-
- StringCbPrintf(id_string, sizeof(id_string), id_fmt, id_name);
-
- StringCbPrintf(buf, NC_MAXCB_CREDTEXT - cch*sizeof(wchar_t),
- main_fmt, id_string);
-
- if (flags & KCDB_IDENT_FLAG_VALID) {
- if (flags & KCDB_IDENT_FLAG_DEFAULT)
- LoadString(khm_hInstance, IDS_NC_ID_DEF,
- id_string, ARRAYLENGTH(id_string));
- else if (d->nc->set_default)
- LoadString(khm_hInstance, IDS_NC_ID_WDEF,
- id_string, ARRAYLENGTH(id_string));
- else
- LoadString(khm_hInstance, IDS_NC_ID_NDEF,
- id_string, ARRAYLENGTH(id_string));
-
- StringCbCat(buf, NC_MAXCB_CREDTEXT - cch * sizeof(wchar_t),
- id_string);
- }
-
- } else if(d->nc->n_identities > 1) {
- wchar_t *ids_string;
- khm_size cb_ids_string;
-
- wchar_t id_name[KCDB_IDENT_MAXCCH_NAME];
- wchar_t id_fmt[256];
- wchar_t id_string[KCDB_IDENT_MAXCCH_NAME + 256];
-
- wchar_t main_fmt[256];
- khm_size cbbuf;
-
- LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_MANY,
- main_fmt, (int) ARRAYLENGTH(main_fmt));
-
- /* we are going to concatenate all the identity names into
- a comma separated string */
-
- /* d->nc->n_identities is at least 2 */
- ids_string = PMALLOC((KCDB_IDENT_MAXCB_NAME + sizeof(id_fmt)) *
- (d->nc->n_identities - 1));
- cb_ids_string =
- (KCDB_IDENT_MAXCB_NAME + sizeof(id_fmt)) *
- (d->nc->n_identities - 1);
-
- assert(ids_string != NULL);
-
- ids_string[0] = 0;
-
- {
- khm_size i;
- khm_int32 flags;
-
- for(i=1; i<d->nc->n_identities; i++) {
- if(i>1) {
- StringCbCat(ids_string, cb_ids_string, L",");
- }
-
- flags = 0;
-
- cbbuf = sizeof(id_name);
- kcdb_identity_get_name(d->nc->identities[i], id_name, &cbbuf);
- kcdb_identity_get_flags(d->nc->identities[i], &flags);
- if(flags & KCDB_IDENT_FLAG_INVALID) {
- LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_INVALID,
- id_fmt, (int) ARRAYLENGTH(id_fmt));
- } else if(flags & KCDB_IDENT_FLAG_VALID) {
- LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_VALID,
- id_fmt, (int) ARRAYLENGTH(id_fmt));
- } else {
- LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_UNCHECKED,
- id_fmt, (int) ARRAYLENGTH(id_fmt));
- }
-
- StringCbPrintf(id_string, sizeof(id_string), id_fmt, id_name);
- StringCbCat(ids_string, cb_ids_string, id_string);
- }
-
- cbbuf = sizeof(id_name);
- kcdb_identity_get_name(d->nc->identities[0], id_name, &cbbuf);
- kcdb_identity_get_flags(d->nc->identities[0], &flags);
- if(flags & KCDB_IDENT_FLAG_INVALID) {
- LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_INVALID,
- id_fmt, (int) ARRAYLENGTH(id_fmt));
- } else if(flags & KCDB_IDENT_FLAG_VALID) {
- LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_VALID,
- id_fmt, (int) ARRAYLENGTH(id_fmt));
- } else {
- LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_UNCHECKED,
- id_fmt, (int) ARRAYLENGTH(id_fmt));
- }
- StringCbPrintf(id_string, sizeof(id_string), id_fmt, id_name);
-
- StringCbPrintf(buf, NC_MAXCB_CREDTEXT - cch*sizeof(wchar_t),
- main_fmt, id_string, ids_string);
-
- PFREE(ids_string);
- }
- } else {
- LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_NONE,
- buf, (int)(NC_MAXCCH_CREDTEXT - cch));
- }
-
- /* now, append the credtext string from each of the cred types */
- {
- khm_size i;
- size_t cb;
- wchar_t * buf;
-
- cb = NC_MAXCB_CREDTEXT;
- buf = ctbuf;
-
- for(i=0; i<d->nc->n_types; i++) {
- if(d->nc->types[i]->credtext != NULL) {
- StringCbCatEx(buf, cb,
- d->nc->types[i]->credtext,
- &buf, &cb,
- 0);
- }
- }
- }
-
- SetDlgItemText(d->dlg_main, IDC_NC_CREDTEXT, ctbuf);
-
- PFREE(ctbuf);
-
- /* so depending on whether the primary identity was found to be
- invalid, we need to disable the Ok button and set the title to
- reflect this */
-
- if(d->nc->n_identities > 0) {
- khm_int32 flags = 0;
-
- if(KHM_SUCCEEDED(kcdb_identity_get_flags(d->nc->identities[0],
- &flags)) &&
- (flags & KCDB_IDENT_FLAG_VALID)) {
- validId = TRUE;
- }
- }
-
- if (d->nc->window_title == NULL) {
- if(validId) {
- wchar_t wpostfix[256];
- wchar_t wtitle[KCDB_IDENT_MAXCCH_NAME + 256];
- khm_size cbsize;
-
- cbsize = sizeof(wtitle);
- kcdb_identity_get_name(d->nc->identities[0], wtitle, &cbsize);
-
- if (d->nc->subtype == KMSG_CRED_PASSWORD)
- LoadString(khm_hInstance, IDS_WTPOST_PASSWORD,
- wpostfix, (int) ARRAYLENGTH(wpostfix));
- else
- LoadString(khm_hInstance, IDS_WTPOST_NEW_CREDS,
- wpostfix, (int) ARRAYLENGTH(wpostfix));
-
- StringCbCat(wtitle, sizeof(wtitle), wpostfix);
-
- SetWindowText(d->nc->hwnd, wtitle);
- } else {
- wchar_t wtitle[256];
-
- if (d->nc->subtype == KMSG_CRED_PASSWORD)
- LoadString(khm_hInstance, IDS_WT_PASSWORD,
- wtitle, (int) ARRAYLENGTH(wtitle));
- else
- LoadString(khm_hInstance, IDS_WT_NEW_CREDS,
- wtitle, (int) ARRAYLENGTH(wtitle));
-
- SetWindowText(d->nc->hwnd, wtitle);
- }
- }
-
- if (!(d->nc->response & KHUI_NC_RESPONSE_PROCESSING)) {
- if(validId ||
- d->nc->subtype == KMSG_CRED_PASSWORD) {
- /* TODO: check if all the required fields have valid values
- before enabling the Ok button */
- okEnable = TRUE;
- }
-
- hw = GetDlgItem(d->dlg_main, IDOK);
- EnableWindow(hw, okEnable);
- hw = GetDlgItem(d->dlg_bb, IDOK);
- EnableWindow(hw, okEnable);
- }
-}
-
-#define CW_PARAM DWLP_USER
-
-static void
-nc_add_control_row(khui_nc_wnd_data * d,
- HWND label,
- HWND input,
- khui_control_size size);
-
-static LRESULT
-nc_handle_wm_create(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam)
-{
- LPCREATESTRUCT lpc;
- khui_new_creds * c;
- khui_nc_wnd_data * ncd;
- int x, y;
- int width, height;
- RECT r;
- khm_int32 t;
-
- lpc = (LPCREATESTRUCT) lParam;
-
- ncd = PMALLOC(sizeof(*ncd));
- ZeroMemory(ncd, sizeof(*ncd));
-
- c = (khui_new_creds *) lpc->lpCreateParams;
- ncd->nc = c;
- c->hwnd = hwnd;
-
-#pragma warning(push)
-#pragma warning(disable: 4244)
- SetWindowLongPtr(hwnd, CW_PARAM, (LONG_PTR) ncd);
-#pragma warning(pop)
-
- /* first try to create the main dialog panel */
-
- assert(c->subtype == KMSG_CRED_NEW_CREDS ||
- c->subtype == KMSG_CRED_PASSWORD);
-
- ncd->dlg_main = CreateDialogParam(khm_hInstance,
- MAKEINTRESOURCE(IDD_NC_PASSWORD),
- hwnd,
- nc_common_dlg_proc,
- (LPARAM) ncd);
-#ifdef DEBUG
- assert(ncd->dlg_main);
-#endif
-
- {
- RECT r_main;
- RECT r_area;
- RECT r_row;
- HWND hw;
-
- /* pick out metrics for use by the custom prompter stuff */
- GetWindowRect(ncd->dlg_main, &r_main);
-
- hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_PANEL);
-#ifdef DEBUG
- assert(hw);
-#endif
- GetWindowRect(hw, &r_area);
- OffsetRect(&r_area,-r_main.left, -r_main.top);
- CopyRect(&ncd->r_area, &r_area);
-
- hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_ROW);
-#ifdef DEBUG
- assert(hw);
-#endif
- GetWindowRect(hw, &r);
- CopyRect(&r_row, &r);
- OffsetRect(&r,-r.left, -r.top);
- CopyRect(&ncd->r_row, &r);
-
- hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_LABEL);
-#ifdef DEBUG
- assert(hw);
-#endif
- GetWindowRect(hw, &r);
- OffsetRect(&r,-r_row.left, -r_row.top);
- CopyRect(&ncd->r_n_label, &r);
-
- hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_INPUT);
-#ifdef DEBUG
- assert(hw);
-#endif
- GetWindowRect(hw, &r);
- OffsetRect(&r, -r_row.left, -r_row.top);
- CopyRect(&ncd->r_n_input, &r);
-
- hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_ROW_LG);
-#ifdef DEBUG
- assert(hw);
-#endif
- GetWindowRect(hw, &r_row);
-
- hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_LABEL_LG);
-#ifdef DEBUG
- assert(hw);
-#endif
- GetWindowRect(hw, &r);
- OffsetRect(&r, -r_row.left, -r_row.top);
- CopyRect(&ncd->r_e_label, &r);
-
- hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_INPUT_LG);
-#ifdef DEBUG
- assert(hw);
-#endif
- GetWindowRect(hw, &r);
- OffsetRect(&r, -r_row.left, -r_row.top);
- CopyRect(&ncd->r_e_input, &r);
-
- CopyRect(&ncd->r_credtext, &ncd->r_area);
- CopyRect(&ncd->r_idspec, &ncd->r_area);
-
- ncd->r_idspec.bottom = ncd->r_idspec.top;
-
- hw = GetDlgItem(ncd->dlg_main, IDC_NC_CREDTEXT);
-#ifdef DEBUG
- assert(hw);
-#endif
- GetWindowRect(hw, &r);
- OffsetRect(&r, -r_main.left, -r_main.top);
- ncd->r_credtext.bottom = r.bottom;
- }
-
- /* if the mode is 'mini'*/
- r.left = 0;
- r.top = 0;
- if(c->mode == KHUI_NC_MODE_MINI) {
- r.right = NCDLG_WIDTH;
- r.bottom = NCDLG_HEIGHT;
- } else {
- r.right = NCDLG_WIDTH + NCDLG_BBAR_WIDTH;
- r.bottom = NCDLG_HEIGHT + NCDLG_TAB_HEIGHT;
- }
-
- MapDialogRect(ncd->dlg_main, &r);
-
- ncd->r_main.left = 0;
- ncd->r_main.top = 0;
- ncd->r_main.right = NCDLG_WIDTH;
- ncd->r_main.bottom = NCDLG_HEIGHT;
-
- ncd->r_ts.left = 0;
- ncd->r_ts.top = ncd->r_main.bottom;
- ncd->r_ts.right = ncd->r_main.right;
- ncd->r_ts.bottom = ncd->r_ts.top + NCDLG_TAB_HEIGHT;
-
- ncd->r_bb.left = ncd->r_main.right;
- ncd->r_bb.top = 0;
- ncd->r_bb.right = ncd->r_bb.left + NCDLG_BBAR_WIDTH;
- ncd->r_bb.bottom = ncd->r_ts.bottom;
-
- MapDialogRect(ncd->dlg_main, &(ncd->r_main));
- MapDialogRect(ncd->dlg_main, &(ncd->r_ts));
- MapDialogRect(ncd->dlg_main, &(ncd->r_bb));
-
- /* center the new creds window over the main NetIDMgr window */
- width = r.right - r.left;
- height = r.bottom - r.top;
-
- /* adjust width and height to accomodate NC area */
- {
- RECT wr,cr;
-
- GetWindowRect(hwnd, &wr);
- GetClientRect(hwnd, &cr);
-
- /* the non-client and client areas have already been calculated
- at this point. We just use the difference to adjust the width
- and height */
- width += (wr.right - wr.left) - (cr.right - cr.left);
- height += (wr.bottom - wr.top) - (cr.bottom - cr.top);
- }
-
- GetWindowRect(lpc->hwndParent, &r);
- x = (r.right + r.left)/2 - width / 2;
- y = (r.top + r.bottom)/2 - height / 2;
-
- MoveWindow(hwnd, x, y, width, height, FALSE);
-
- SetWindowPos(ncd->dlg_main,
- NULL,
- ncd->r_main.left,
- ncd->r_main.top,
- ncd->r_main.right - ncd->r_main.left,
- ncd->r_main.bottom - ncd->r_main.top,
- SWP_DEFERERASE | SWP_NOACTIVATE | SWP_NOOWNERZORDER |
- SWP_NOREDRAW | SWP_NOZORDER);
-
- /* IDD_NC_BBAR is the button bar that sits on the right of the
- dialog when the new creds window is in 'expanded' mode. */
-
- ncd->dlg_bb = CreateDialogParam(khm_hInstance,
- MAKEINTRESOURCE(IDD_NC_BBAR),
- hwnd,
- nc_common_dlg_proc,
- (LPARAM) ncd);
-
-#ifdef DEBUG
- assert(ncd->dlg_bb);
-#endif
-
- SetWindowPos(ncd->dlg_bb,
- NULL,
- ncd->r_bb.left,
- ncd->r_bb.top,
- ncd->r_bb.right - ncd->r_bb.left,
- ncd->r_bb.bottom - ncd->r_bb.top,
- SWP_DEFERERASE | SWP_NOACTIVATE | SWP_NOOWNERZORDER |
- SWP_NOREDRAW | SWP_NOZORDER);
-
- /* IDD_NC_TS is the tab strip that sits below the main panel when
- the new creds window is in 'expanded' mode */
-
- ncd->dlg_ts = CreateDialogParam(khm_hInstance,
- MAKEINTRESOURCE(IDD_NC_TS),
- hwnd,
- nc_common_dlg_proc,
- (LPARAM) ncd);
-
-#ifdef DEBUG
- assert(ncd->dlg_ts);
-#endif
-
- SetWindowPos(ncd->dlg_ts,
- NULL,
- ncd->r_ts.left,
- ncd->r_ts.top,
- ncd->r_ts.right - ncd->r_ts.left,
- ncd->r_ts.bottom - ncd->r_ts.top,
- SWP_DEFERERASE | SWP_NOACTIVATE | SWP_NOOWNERZORDER |
- SWP_NOREDRAW | SWP_NOZORDER);
-
- if(c->mode == KHUI_NC_MODE_MINI) {
- /* hide and show stuff */
- ShowWindow(ncd->dlg_main, SW_SHOW);
- ShowWindow(ncd->dlg_bb, SW_HIDE);
- ShowWindow(ncd->dlg_ts, SW_HIDE);
-
- nc_position_credtext(ncd);
-
- } else {
- /* hide and show stuff */
- ShowWindow(ncd->dlg_main, SW_SHOW);
- ShowWindow(ncd->dlg_bb, SW_SHOW);
- ShowWindow(ncd->dlg_ts, SW_SHOW);
-
- PostMessage(ncd->dlg_main, KHUI_WM_NC_NOTIFY,
- MAKEWPARAM(0, WMNC_DIALOG_EXPAND), 0);
- }
-
- /* Call the identity provider callback to set the identity
- selector controls */
- c->ident_cb(c, WMNC_IDENT_INIT, NULL, 0, 0, (LPARAM) ncd->dlg_main);
-
-#if 0
- {
- HWND hw;
- wchar_t wcaption[64];
-
- LoadString(khm_hInstance, IDS_NC_SETDEF, wcaption,
- ARRAYLENGTH(wcaption));
-
- /* Now create the set as default button */
- hw = CreateWindow
- (L"BUTTON",
- wcaption,
- WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_AUTOCHECKBOX,
- 0, 0, 100, 100,
- ncd->dlg_main,
- (HMENU) NC_BN_SET_DEF_ID,
- khm_hInstance,
- NULL);
-
- nc_add_control_row(ncd, NULL, hw, KHUI_CTRLSIZE_HALF);
- }
-#endif
- /* we defer the creation of the tab buttons for later */
-
- /* bring the window to the top, if necessary */
- if (KHM_SUCCEEDED(khc_read_int32(NULL,
- L"CredWindow\\Windows\\NewCred\\ForceToTop",
- &t)) &&
- t != 0 &&
- !khm_is_dialog_active()) {
-
- /* if the main window is not visible, then the SetWindowPos()
- call is sufficient to bring the new creds window to the
- top. However, if the main window is visible but not
- active, the main window needs to be activated before a
- child window can be activated. */
- khm_activate_main_window();
-
- SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0,
- (SWP_NOMOVE | SWP_NOSIZE));
-
- }
-
- /* add this to the dialog chain */
- khm_add_dialog(hwnd);
-
- return TRUE;
-}
-
-static void
-nc_add_control_row(khui_nc_wnd_data * d,
- HWND label,
- HWND input,
- khui_control_size size)
-{
- RECT r_row;
- RECT r_label;
- RECT r_input;
- HFONT hf;
-
- hf = (HFONT) SendMessage(d->dlg_main, WM_GETFONT, 0, 0);
- SendMessage(label, WM_SETFONT, (WPARAM) hf, FALSE);
- SendMessage(input, WM_SETFONT, (WPARAM) hf, FALSE);
-
- CopyRect(&r_row, &d->r_row);
- OffsetRect(&r_row, d->r_idspec.left, d->r_idspec.bottom);
-
- if (size == KHUI_CTRLSIZE_SMALL) {
- CopyRect(&r_label, &d->r_n_label);
- CopyRect(&r_input, &d->r_n_input);
- OffsetRect(&r_label, r_row.left, r_row.top);
- OffsetRect(&r_input, r_row.left, r_row.top);
- } else if (size == KHUI_CTRLSIZE_HALF) {
- CopyRect(&r_label, &d->r_e_label);
- CopyRect(&r_input, &d->r_e_input);
- OffsetRect(&r_label, r_row.left, r_row.top);
- OffsetRect(&r_input, r_row.left, r_row.top);
- } else if (size == KHUI_CTRLSIZE_FULL) {
- CopyRect(&r_label, &d->r_n_label);
- r_label.right = d->r_row.right;
- CopyRect(&r_input, &d->r_n_input);
- OffsetRect(&r_input, r_row.left, r_row.top);
- OffsetRect(&r_input, 0, r_input.bottom);
- r_row.bottom += r_input.bottom;
- OffsetRect(&r_label, r_row.left, r_row.top);
- } else {
- SetRectEmpty(&r_label);
- SetRectEmpty(&r_input);
-#ifdef DEBUG
- assert(FALSE);
-#endif
- return;
- }
-
- if (label)
- SetWindowPos(label,
- ((d->hwnd_last_idspec != NULL)?
- d->hwnd_last_idspec:
- HWND_TOP),
- r_label.left, r_label.top,
- r_label.right - r_label.left,
- r_label.bottom - r_label.top,
- SWP_DEFERERASE | SWP_NOACTIVATE |
- SWP_NOOWNERZORDER);
-
- if (input)
- SetWindowPos(input,
- (label ? label : ((d->hwnd_last_idspec != NULL)?
- d->hwnd_last_idspec:
- HWND_TOP)),
- r_input.left, r_input.top,
- r_input.right - r_input.left,
- r_input.bottom - r_input.top,
- SWP_DEFERERASE | SWP_NOACTIVATE |
- SWP_NOOWNERZORDER);
-
- d->hwnd_last_idspec = input;
-
- d->r_idspec.bottom = r_row.bottom;
-
- d->r_credtext.top = r_row.bottom;
-
- nc_position_credtext(d);
-}
-
-
-static LRESULT
-nc_handle_wm_destroy(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam)
-{
- khui_nc_wnd_data * d;
- khm_size i;
-
- /* remove self from dialog chain */
- khm_del_dialog(hwnd);
-
- d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM);
-
- d->nc->ident_cb(d->nc, WMNC_IDENT_EXIT, NULL, 0, 0, 0);
-
- if(d->hwnd_tc_main)
- DestroyWindow(d->hwnd_tc_main);
- for(i=0;i<d->nc->n_types;i++) {
- if(d->nc->types[i]->hwnd_tc) {
- DestroyWindow(d->nc->types[i]->hwnd_tc);
- d->nc->types[i]->hwnd_tc = NULL;
- }
- }
-
- if(d->dlg_bb)
- DestroyWindow(d->dlg_bb);
- if(d->dlg_main)
- DestroyWindow(d->dlg_main);
- if(d->dlg_ts)
- DestroyWindow(d->dlg_ts);
-
- d->dlg_bb = NULL;
- d->dlg_main = NULL;
- d->dlg_ts = NULL;
-
- PFREE(d);
-
- return TRUE;
-}
-
-static LRESULT
-nc_handle_wm_command(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam)
-{
- khui_nc_wnd_data * d;
- int id;
-
- d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM);
-
- switch(HIWORD(wParam)) {
- case BN_CLICKED:
- switch(LOWORD(wParam)) {
-
- case IDOK:
- d->nc->result = KHUI_NC_RESULT_PROCESS;
-
- /* fallthrough */
-
- case IDCANCEL:
- /* the default value for d->nc->result is set to
- KHUI_NC_RESULT_CANCEL */
- d->nc->response = KHUI_NC_RESPONSE_PROCESSING;
-
- nc_enable_controls(d, FALSE);
-
- nc_notify_types(d->nc,
- KHUI_WM_NC_NOTIFY,
- MAKEWPARAM(0,WMNC_DIALOG_PREPROCESS),
- (LPARAM) d->nc);
-
- khui_cw_sync_prompt_values(d->nc);
-
- khm_cred_dispatch_process_message(d->nc);
-
- /* we won't know whether to abort or not until we get
- feedback from the plugins, even if the command was
- to cancel */
- {
- HWND hw;
-
- hw = GetDlgItem(d->dlg_main, IDOK);
- EnableWindow(hw, FALSE);
- hw = GetDlgItem(d->dlg_main, IDCANCEL);
- EnableWindow(hw, FALSE);
- hw = GetDlgItem(d->dlg_main, IDC_NC_OPTIONS);
- EnableWindow(hw, FALSE);
- hw = GetDlgItem(d->dlg_bb, IDOK);
- EnableWindow(hw, FALSE);
- hw = GetDlgItem(d->dlg_bb, IDCANCEL);
- EnableWindow(hw, FALSE);
- }
- return FALSE;
-
- case IDC_NC_HELP:
- khm_html_help(hwnd, NULL, HH_HELP_CONTEXT, IDH_ACTION_NEW_ID);
- return FALSE;
-
- case IDC_NC_OPTIONS:
- /* the Options button in the main window was clicked. we
- respond by expanding the dialog. */
- PostMessage(hwnd, KHUI_WM_NC_NOTIFY,
- MAKEWPARAM(0, WMNC_DIALOG_EXPAND), 0);
- return FALSE;
-
- case IDC_NC_CREDTEXT: /* credtext link activated */
- {
- khui_htwnd_link * l;
- wchar_t sid[KHUI_MAXCCH_HTLINK_FIELD];
- wchar_t sparam[KHUI_MAXCCH_HTLINK_FIELD];
- wchar_t * colon;
-
- l = (khui_htwnd_link *) lParam;
-
- /* do we have a valid link? */
- if(l->id == NULL || l->id_len >= ARRAYLENGTH(sid))
- return TRUE; /* nope */
-
- StringCchCopyN(sid, ARRAYLENGTH(sid), l->id, l->id_len);
- sid[l->id_len] = L'\0'; /* just make sure */
-
- if(l->param != NULL &&
- l->param_len < ARRAYLENGTH(sparam) &&
- l->param_len > 0) {
-
- StringCchCopyN(sparam, ARRAYLENGTH(sparam),
- l->param, l->param_len);
- sparam[l->param_len] = L'\0';
-
- } else {
- sparam[0] = L'\0';
- }
-
- /* If the ID is of the form '<credtype>:<link_tag>'
- and <credtype> is a valid name of a credentials
- type that is participating in the credentials
- acquisition process, then we forward the message to
- the panel that is providing the UI for that cred
- type. We also switch to that panel first, unless
- the link is of the form '<credtype>:!<link_tag>'. */
-
- colon = wcschr(sid, L':');
- if (colon != NULL) {
- khm_int32 credtype;
- khui_new_creds_by_type * t;
-
- *colon = L'\0';
- if (KHM_SUCCEEDED(kcdb_credtype_get_id(sid, &credtype)) &&
- KHM_SUCCEEDED(khui_cw_find_type(d->nc, credtype, &t))){
- *colon = L':';
-
- if (t->ordinal != d->ctab &&
- *(colon + 1) != L'!')
- PostMessage(hwnd,
- KHUI_WM_NC_NOTIFY,
- MAKEWPARAM(t->ordinal,
- WMNC_DIALOG_SWITCH_PANEL),
- 0);
-
- return SendMessage(t->hwnd_panel,
- KHUI_WM_NC_NOTIFY,
- MAKEWPARAM(0, WMNC_CREDTEXT_LINK),
- lParam);
- } else {
- *colon = L':';
- }
- }
-
- /* if it was for us, then we need to process the message */
- if(!_wcsicmp(sid, CTLINKID_SWITCH_PANEL)) {
- khm_int32 credtype;
- khui_new_creds_by_type * t;
-
- if (KHM_SUCCEEDED(kcdb_credtype_get_id(sparam,
- &credtype)) &&
- KHM_SUCCEEDED(khui_cw_find_type(d->nc,
- credtype, &t))) {
- if (t->ordinal != d->ctab)
- PostMessage(hwnd,
- KHUI_WM_NC_NOTIFY,
- MAKEWPARAM(t->ordinal,
- WMNC_DIALOG_SWITCH_PANEL),
- 0);
- }
- } else if (!_wcsicmp(sid, L"NotDef")) {
- d->nc->set_default = FALSE;
- nc_update_credtext(d);
- } else if (!_wcsicmp(sid, L"MakeDef")) {
- d->nc->set_default = TRUE;
- nc_update_credtext(d);
- }
- }
- return FALSE;
-
-#if 0
- case NC_BN_SET_DEF_ID:
- {
- d->nc->set_default =
- (IsDlgButtonChecked(d->dlg_main, NC_BN_SET_DEF_ID)
- == BST_CHECKED);
- }
- return FALSE;
-#endif
-
- default:
- /* if one of the tab strip buttons were pressed, then
- we should switch to that panel */
- id = LOWORD(wParam);
- if(id >= NC_TS_CTRL_ID_MIN && id <= NC_TS_CTRL_ID_MAX) {
- id -= NC_TS_CTRL_ID_MIN;
- PostMessage(hwnd, KHUI_WM_NC_NOTIFY,
- MAKEWPARAM(id, WMNC_DIALOG_SWITCH_PANEL),0);
- return FALSE;
- }
- }
- break;
- }
-
- return TRUE;
-}
-
-static LRESULT nc_handle_wm_moving(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam)
-{
- khui_nc_wnd_data * d;
-
- d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM);
-
- nc_notify_types(d->nc, KHUI_WM_NC_NOTIFY,
- MAKEWPARAM(0, WMNC_DIALOG_MOVE), (LPARAM) d->nc);
-
- return FALSE;
-}
-
-static LRESULT nc_handle_wm_nc_notify(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam)
-{
- khui_nc_wnd_data * d;
- RECT r;
- int width, height;
- khm_size id;
-
- d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM);
-
- switch(HIWORD(wParam)) {
-
- case WMNC_DIALOG_SWITCH_PANEL:
- id = LOWORD(wParam);
- if(id >= 0 && id <= d->nc->n_types) {
- /* one of the tab buttons were pressed */
- if(d->ctab == id) {
- return TRUE; /* nothign to do */
- }
-
- if(d->ctab == 0) {
- ShowWindow(d->dlg_main, SW_HIDE);
- SendMessage(d->hwnd_tc_main,
- BM_SETCHECK, BST_UNCHECKED, 0);
- } else {
- ShowWindow(d->nc->types[d->ctab - 1]->hwnd_panel, SW_HIDE);
- SendMessage(d->nc->types[d->ctab - 1]->hwnd_tc,
- BM_SETCHECK, BST_UNCHECKED, 0);
- }
-
- d->ctab = id;
-
- if(d->ctab == 0) {
- ShowWindow(d->dlg_main, SW_SHOW);
- SendMessage(d->hwnd_tc_main,
- BM_SETCHECK, BST_CHECKED, 0);
- } else {
- ShowWindow(d->nc->types[id - 1]->hwnd_panel, SW_SHOW);
- SendMessage(d->nc->types[id - 1]->hwnd_tc,
- BM_SETCHECK, BST_CHECKED, 0);
- }
- }
-
- if(d->nc->mode == KHUI_NC_MODE_EXPANDED)
- return TRUE;
- /*else*/
- /* fallthrough */
-
- case WMNC_DIALOG_EXPAND:
- /* we are expanding the dialog box */
-
- /* nothing to do? */
- if (d->nc->mode == KHUI_NC_MODE_EXPANDED)
- break;
-
- d->nc->mode = KHUI_NC_MODE_EXPANDED;
-
- r.top = 0;
- r.left = 0;
- r.right = NCDLG_WIDTH + NCDLG_BBAR_WIDTH;
- r.bottom = NCDLG_HEIGHT + NCDLG_TAB_HEIGHT;
-
- MapDialogRect(d->dlg_main, &r);
-
- width = r.right - r.left;
- height = r.bottom - r.top;
-
- /* adjust width and height to accomodate NC area */
- {
- RECT wr,cr;
-
- GetWindowRect(hwnd, &wr);
- GetClientRect(hwnd, &cr);
-
- /* the non-client and client areas have already been
- calculated at this point. We just use the difference
- to adjust the width and height */
- width += (wr.right - wr.left) - (cr.right - cr.left);
- height += (wr.bottom - wr.top) - (cr.bottom - cr.top);
- }
-
- SendMessage(d->dlg_main,
- KHUI_WM_NC_NOTIFY,
- MAKEWPARAM(0,WMNC_DIALOG_EXPAND),
- 0);
-
- SetWindowPos(hwnd,
- NULL,
- 0, 0,
- width, height,
- SWP_NOCOPYBITS | SWP_NOMOVE | SWP_NOOWNERZORDER |
- SWP_NOZORDER);
-
- ShowWindow(d->dlg_bb, SW_SHOW);
- ShowWindow(d->dlg_ts, SW_SHOW);
- break;
-
- case WMNC_DIALOG_SETUP:
- if(d->nc->n_types > 0) {
- khm_size i;
- for(i=0; i < d->nc->n_types;i++) {
-
- if (d->nc->types[i]->dlg_proc == NULL) {
- d->nc->types[i]->hwnd_panel = NULL;
- } else {
- /* Create the dialog panel */
- d->nc->types[i]->hwnd_panel =
- CreateDialogParam(d->nc->types[i]->h_module,
- d->nc->types[i]->dlg_template,
- d->nc->hwnd,
- d->nc->types[i]->dlg_proc,
- (LPARAM) d->nc);
-
-#ifdef DEBUG
- assert(d->nc->types[i]->hwnd_panel);
-#endif
- }
- }
- }
- break;
-
- case WMNC_DIALOG_ACTIVATE:
- {
- int x,y,width,height;
- RECT r;
- int id;
- wchar_t wbuf[256];
- HFONT hf;
-
- /* now we create all the tab strip controls */
- r.left = 0;
- r.top = 0;
- r.right = NCDLG_TAB_WIDTH;
- r.bottom = NCDLG_TAB_HEIGHT;
- MapDialogRect(d->dlg_main, &r);
-
- width = r.right - r.left;
- height = r.bottom - r.top;
-
- x = 0;
- y = 0;
-
- id = NC_TS_CTRL_ID_MIN;
-
- /* if we have too many buttons than would fit on the
- button bar, we have to adjust the width of the buttons.
- Of course, having too many of them would be bad and
- make the buttons fairly useless. This is just an
- interim measure. */
-
- khui_cw_lock_nc(d->nc);
-
- GetWindowRect(d->dlg_ts, &r);
- if (x + width * (d->nc->n_types + 1) > (khm_size) (r.right - r.left)) {
- width = (int)(((r.right - r.left) - x) / (d->nc->n_types + 1));
- }
-
- /* first, the control for the main panel */
- LoadString(khm_hInstance, IDS_NC_IDENTITY,
- wbuf, ARRAYLENGTH(wbuf));
-
- d->hwnd_tc_main =
- CreateWindow(L"BUTTON",
- wbuf,
- WS_VISIBLE | WS_CHILD | WS_TABSTOP |
- BS_PUSHLIKE | BS_CHECKBOX | BS_TEXT,
- x,y,width,height,
- d->dlg_ts,
- (HMENU)(INT_PTR) id,
- khm_hInstance,
- NULL);
-
- hf = (HFONT) SendMessage(d->dlg_main, WM_GETFONT, 0, 0);
- SendMessage(d->hwnd_tc_main, WM_SETFONT, (WPARAM) hf, 0);
- SendMessage(d->hwnd_tc_main, BM_SETCHECK, BST_CHECKED, 0);
-
- id++;
- x += width;
-
- if(d->nc->n_types > 0) {
- khm_size i;
- /* we should sort the tabs first */
- qsort(d->nc->types,
- d->nc->n_types,
- sizeof(*(d->nc->types)),
- nc_tab_sort_func);
-
- for(i=0; i < d->nc->n_types;i++) {
- wchar_t * name = NULL;
-
- d->nc->types[i]->ordinal = i + 1;
-
- if(d->nc->types[i]->name)
- name = d->nc->types[i]->name;
- else {
- khm_size cbsize;
-
- if(kcdb_credtype_describe
- (d->nc->types[i]->type,
- NULL,
- &cbsize,
- KCDB_TS_SHORT) == KHM_ERROR_TOO_LONG) {
-
- name = PMALLOC(cbsize);
- kcdb_credtype_describe(d->nc->types[i]->type,
- name,
- &cbsize,
- KCDB_TS_SHORT);
- } else {
-#ifdef DEBUG
- assert(FALSE);
-#endif
- continue;
- }
- }
-
- d->nc->types[i]->hwnd_tc =
- CreateWindow(L"BUTTON",
- name,
- WS_VISIBLE | WS_CHILD | WS_TABSTOP |
- BS_PUSHLIKE | BS_CHECKBOX | BS_TEXT |
- ((d->nc->types[i]->hwnd_panel == NULL)?
- WS_DISABLED : 0),
- x,y,width,height,
- d->dlg_ts,
- (HMENU)(INT_PTR) id,
- khm_hInstance,
- NULL);
-
- SendMessage(d->nc->types[i]->hwnd_tc, WM_SETFONT,
- (WPARAM)hf, 0);
-
-#if 0
- if(d->nc->types[i]->flags & KHUI_NCT_FLAG_DISABLED)
- SendMessage(d->nc->types[i]->hwnd_tc,
- BM_SETIMAGE,
- IMAGE_ICON,
- LoadIcon(khm_hInstance, MAKEINTRESOURCE(IDI_DISABLED)));
- else
- SendMessage(d->nc->types[i]->hwnd_tc,
- BM_SETIMAGE,
- IMAGE_ICON,
- LoadIcon(khm_hInstance, MAKEINTRESOURCE(IDI_ENABLED)));
-#endif
-
- id++;
- x += width;
-
- if(!(d->nc->types[i]->name))
- PFREE(name);
-
- /* Now set the position of the type panel */
- ShowWindow(d->nc->types[i]->hwnd_panel, SW_HIDE);
- SetWindowPos(d->nc->types[i]->hwnd_panel,
- NULL,
- d->r_main.left,
- d->r_main.top,
- d->r_main.right - d->r_main.left,
- d->r_main.bottom - d->r_main.top,
- SWP_DEFERERASE | SWP_NOACTIVATE |
- SWP_NOOWNERZORDER | SWP_NOREDRAW |
- SWP_NOZORDER);
-
- }
- }
-
- khui_cw_unlock_nc(d->nc);
-
- nc_update_credtext(d);
-
- ShowWindow(hwnd, SW_SHOWNOACTIVATE);
- SetFocus(hwnd);
-
- if (d->nc->n_identities == 0)
- break;
- /* else */
- /* fallthrough */
- }
-
- case WMNC_IDENTITY_CHANGE:
- {
- BOOL okEnable = FALSE;
-
- nc_notify_types(d->nc, KHUI_WM_NC_NOTIFY,
- MAKEWPARAM(0, WMNC_IDENTITY_CHANGE), (LPARAM) d->nc);
-
- if (d->nc->subtype == KMSG_CRED_NEW_CREDS &&
- d->nc->n_identities > 0 &&
- d->nc->identities[0]) {
- khm_int32 f = 0;
-
- kcdb_identity_get_flags(d->nc->identities[0], &f);
-
- if (!(f & KCDB_IDENT_FLAG_DEFAULT)) {
- d->nc->set_default = FALSE;
- }
- }
-
- nc_update_credtext(d);
-
- }
- break;
-
- case WMNC_TYPE_STATE:
- /* fallthrough */
- case WMNC_UPDATE_CREDTEXT:
- nc_update_credtext(d);
- break;
-
- case WMNC_CLEAR_PROMPTS:
- {
- khm_size i;
-
- khui_cw_lock_nc(d->nc);
-
- if(d->hwnd_banner != NULL) {
- DestroyWindow(d->hwnd_banner);
- d->hwnd_banner = NULL;
- }
-
- if(d->hwnd_name != NULL) {
- DestroyWindow(d->hwnd_name);
- d->hwnd_name = NULL;
- }
-
- for(i=0;i<d->nc->n_prompts;i++) {
- if(!(d->nc->prompts[i]->flags &
- KHUI_NCPROMPT_FLAG_STOCK)) {
- if(d->nc->prompts[i]->hwnd_static != NULL)
- DestroyWindow(d->nc->prompts[i]->hwnd_static);
-
- if(d->nc->prompts[i]->hwnd_edit != NULL)
- DestroyWindow(d->nc->prompts[i]->hwnd_edit);
- }
-
- d->nc->prompts[i]->hwnd_static = NULL;
- d->nc->prompts[i]->hwnd_edit = NULL;
- }
-
- khui_cw_unlock_nc(d->nc);
-
- d->r_credtext.top = d->r_idspec.bottom;
-
- nc_position_credtext(d);
- }
- break;
-
- case WMNC_SET_PROMPTS:
- {
- khm_size i;
- int y;
- HWND hw, hw_prev;
- HFONT hf, hfold;
- HDC hdc;
- BOOL use_large_lables = FALSE;
-
- /* we assume that WMNC_CLEAR_PROMPTS has already been
- received */
-
- khui_cw_lock_nc(d->nc);
-
-#if 0
- /* special case, we have one prompt and it is a password
- prompt. very common */
- if(d->nc->n_prompts == 1 &&
- d->nc->prompts[0]->type == KHUI_NCPROMPT_TYPE_PASSWORD) {
-
- hw = GetDlgItem(d->dlg_main, IDC_NC_PASSWORD);
- EnableWindow(hw, TRUE);
-
- d->nc->prompts[0]->flags |= KHUI_NCPROMPT_FLAG_STOCK;
- d->nc->prompts[0]->hwnd_edit = hw;
- d->nc->prompts[0]->hwnd_static = NULL; /* don't care */
-
- khui_cw_unlock_nc(d->nc);
- break;
- }
-#endif
- /* for everything else */
-
- /* hide the stock password controls */
-#if 0
- /* TAGREMOVE */
- hw = GetDlgItem(d->dlg_main, IDC_NC_PASSWORD);
- ShowWindow(hw, SW_HIDE);
- hw = GetDlgItem(d->dlg_main, IDC_NC_PASSWORD_LABEL);
- ShowWindow(hw, SW_HIDE);
-#endif
-
- y = d->r_idspec.bottom;
-
- hf = (HFONT) SendMessage(d->dlg_main, WM_GETFONT, 0, 0);
-
- if (d->nc->pname != NULL) {
- hw =
- CreateWindowEx
- (0,
- L"STATIC",
- d->nc->pname,
- SS_SUNKEN | WS_CHILD,
- d->r_area.left, y,
- d->r_row.right,
- d->r_n_label.bottom - d->r_n_label.top,
- d->dlg_main,
- NULL,
- khm_hInstance,
- NULL);
-
-#ifdef DEBUG
- assert(hw);
-#endif
- d->hwnd_name = hw;
- SendMessage(hw, WM_SETFONT, (WPARAM)hf, (LPARAM) TRUE);
- ShowWindow(hw, SW_SHOW);
-
- y += d->r_n_label.bottom - d->r_n_label.top;
- }
-
- if (d->nc->banner != NULL) {
- hw =
- CreateWindowEx
- (0,
- L"STATIC",
- d->nc->banner,
- WS_CHILD,
- d->r_area.left, y,
- d->r_row.right, d->r_row.bottom,
- d->dlg_main,
- NULL,
- khm_hInstance,
- NULL);
-#ifdef DEBUG
- assert(hw);
-#endif
- d->hwnd_banner = hw;
- SendMessage(hw, WM_SETFONT, (WPARAM)hf, (LPARAM)TRUE);
- ShowWindow(hw, SW_SHOW);
- y += d->r_row.bottom;
- }
-
- hw_prev = d->hwnd_last_idspec;
-
- hdc = GetWindowDC(d->dlg_main);
- hfold = SelectObject(hdc,hf);
-
- /* first do a trial run and see if we should use the
- larger text labels or not. This is so that all the
- labels and input controls align properly. */
- for (i=0; i < d->nc->n_prompts; i++) {
- if (d->nc->prompts[i]->prompt != NULL) {
- SIZE s;
-
- GetTextExtentPoint32(hdc,
- d->nc->prompts[i]->prompt,
- (int) wcslen(d->nc->prompts[i]->prompt),
- &s);
-
- if(s.cx >= d->r_n_label.right - d->r_n_label.left) {
- use_large_lables = TRUE;
- break;
- }
- }
- }
-
- for(i=0; i<d->nc->n_prompts; i++) {
- RECT pr, er;
- SIZE s;
- int dy;
-
- if(d->nc->prompts[i]->prompt != NULL) {
- GetTextExtentPoint32(hdc,
- d->nc->prompts[i]->prompt,
- (int) wcslen(d->nc->prompts[i]->prompt),
- &s);
- if(s.cx < d->r_n_label.right - d->r_n_label.left &&
- !use_large_lables) {
- CopyRect(&pr, &d->r_n_label);
- CopyRect(&er, &d->r_n_input);
- dy = d->r_row.bottom;
- } else if(s.cx <
- d->r_e_label.right - d->r_e_label.left) {
- CopyRect(&pr, &d->r_e_label);
- CopyRect(&er, &d->r_e_input);
- dy = d->r_row.bottom;
- } else {
- /* oops. the prompt doesn't fit in our
- controls. we need to use up two lines */
- pr.left = 0;
- pr.right = d->r_row.right;
- pr.top = 0;
- pr.bottom = d->r_n_label.bottom -
- d->r_n_label.top;
- CopyRect(&er, &d->r_n_input);
- OffsetRect(&er, 0, pr.bottom);
- dy = er.bottom + (d->r_row.bottom -
- d->r_n_input.bottom);
- }
- } else {
- SetRectEmpty(&pr);
- CopyRect(&er, &d->r_n_input);
- dy = d->r_row.bottom;
- }
-
- if(IsRectEmpty(&pr)) {
- d->nc->prompts[i]->hwnd_static = NULL;
- } else {
- OffsetRect(&pr, d->r_area.left, y);
-
- hw = CreateWindowEx
- (0,
- L"STATIC",
- d->nc->prompts[i]->prompt,
- WS_CHILD,
- pr.left, pr.top,
- pr.right - pr.left, pr.bottom - pr.top,
- d->dlg_main,
- NULL,
- khm_hInstance,
- NULL);
-#ifdef DEBUG
- assert(hw);
-#endif
-
- SendMessage(hw, WM_SETFONT,
- (WPARAM) hf, (LPARAM) TRUE);
-
- SetWindowPos(hw, hw_prev,
- 0, 0, 0, 0,
- SWP_NOACTIVATE | SWP_NOMOVE |
- SWP_NOOWNERZORDER | SWP_NOSIZE |
- SWP_SHOWWINDOW);
-
- d->nc->prompts[i]->hwnd_static = hw;
- hw_prev = hw;
- }
-
- OffsetRect(&er, d->r_area.left, y);
-
- hw = CreateWindowEx
- (0,
- L"EDIT",
- (d->nc->prompts[i]->def ?
- d->nc->prompts[i]->def : L""),
- WS_CHILD | WS_TABSTOP |
- WS_BORDER |
- ((d->nc->prompts[i]->flags &
- KHUI_NCPROMPT_FLAG_HIDDEN)? ES_PASSWORD:0),
- er.left, er.top,
- er.right - er.left, er.bottom - er.top,
- d->dlg_main,
- NULL,
- khm_hInstance,
- NULL);
-
-#ifdef DEBUG
- assert(hw);
-#endif
-
- SendMessage(hw, WM_SETFONT,
- (WPARAM) hf, (LPARAM) TRUE);
-
- SetWindowPos(hw, hw_prev,
- 0, 0, 0, 0,
- SWP_NOACTIVATE | SWP_NOMOVE |
- SWP_NOOWNERZORDER | SWP_NOSIZE |
- SWP_SHOWWINDOW);
-
- SendMessage(hw, EM_SETLIMITTEXT,
- KHUI_MAXCCH_PROMPT_VALUE -1,
- 0);
-
- d->nc->prompts[i]->hwnd_edit = hw;
-
- hw_prev = hw;
-
- y += dy;
- }
-
- if (d->nc->n_prompts > 0 &&
- d->nc->prompts[0]->hwnd_edit) {
-
- SetFocus(d->nc->prompts[0]->hwnd_edit);
-
- }
-
- SelectObject(hdc, hfold);
- ReleaseDC(d->dlg_main, hdc);
-
- khui_cw_unlock_nc(d->nc);
-
- d->r_credtext.top = y;
-
- nc_position_credtext(d);
- }
- break;
-
- case WMNC_DIALOG_PROCESS_COMPLETE:
- {
- khui_new_creds * nc;
-
- nc = d->nc;
-
- nc->response &= ~KHUI_NC_RESPONSE_PROCESSING;
-
- if(nc->response & KHUI_NC_RESPONSE_NOEXIT) {
- HWND hw;
-
- nc_enable_controls(d, TRUE);
-
- /* reset state */
- nc->result = KHUI_NC_RESULT_CANCEL;
-
- hw = GetDlgItem(d->dlg_main, IDOK);
- EnableWindow(hw, TRUE);
- hw = GetDlgItem(d->dlg_main, IDCANCEL);
- EnableWindow(hw, TRUE);
- hw = GetDlgItem(d->dlg_main, IDC_NC_OPTIONS);
- EnableWindow(hw, TRUE);
- hw = GetDlgItem(d->dlg_bb, IDOK);
- EnableWindow(hw, TRUE);
- hw = GetDlgItem(d->dlg_bb, IDCANCEL);
- EnableWindow(hw, TRUE);
-
- nc_clear_password_fields(d);
-
- return TRUE;
- }
-
- DestroyWindow(hwnd);
-
- kmq_post_message(KMSG_CRED, KMSG_CRED_END, 0, (void *) nc);
- }
- break;
-
- /* MUST be called with SendMessage */
- case WMNC_ADD_CONTROL_ROW:
- {
- khui_control_row * row;
-
- row = (khui_control_row *) lParam;
-
-#ifdef DEBUG
- assert(row->label);
- assert(row->input);
-#endif
-
- nc_add_control_row(d, row->label, row->input, row->size);
- }
- break;
- } /* switch(HIWORD(wParam)) */
-
- return TRUE;
-}
-
-static LRESULT nc_handle_wm_help(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam) {
- static DWORD ctxids[] = {
- NC_TS_CTRL_ID_MIN, IDH_NC_TABMAIN,
- NC_TS_CTRL_ID_MIN + 1, IDH_NC_TABBUTTON,
- NC_TS_CTRL_ID_MIN + 2, IDH_NC_TABBUTTON,
- NC_TS_CTRL_ID_MIN + 3, IDH_NC_TABBUTTON,
- NC_TS_CTRL_ID_MIN + 4, IDH_NC_TABBUTTON,
- NC_TS_CTRL_ID_MIN + 5, IDH_NC_TABBUTTON,
- NC_TS_CTRL_ID_MIN + 6, IDH_NC_TABBUTTON,
- NC_TS_CTRL_ID_MIN + 7, IDH_NC_TABBUTTON,
- IDOK, IDH_NC_OK,
- IDCANCEL, IDH_NC_CANCEL,
- IDC_NC_HELP, IDH_NC_HELP,
- IDC_NC_OPTIONS, IDH_NC_OPTIONS,
- IDC_NC_CREDTEXT, IDH_NC_CREDWND,
- 0
- };
-
- HELPINFO * hlp;
- HWND hw = NULL;
- HWND hw_ctrl;
- khui_nc_wnd_data * d;
-
- d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM);
-
- hlp = (HELPINFO *) lParam;
-
- if (d->nc->subtype != KMSG_CRED_NEW_CREDS &&
- d->nc->subtype != KMSG_CRED_PASSWORD)
- return TRUE;
-
- if (hlp->iContextType != HELPINFO_WINDOW)
- return TRUE;
-
- if (hlp->hItemHandle != NULL &&
- hlp->hItemHandle != hwnd) {
- DWORD id;
- int i;
-
- hw_ctrl =hlp->hItemHandle;
-
- id = GetWindowLong(hw_ctrl, GWL_ID);
- for (i=0; ctxids[i] != 0; i += 2)
- if (ctxids[i] == id)
- break;
-
- if (ctxids[i] != 0)
- hw = khm_html_help(hw_ctrl,
- ((d->nc->subtype == KMSG_CRED_NEW_CREDS)?
- L"::popups_newcreds.txt":
- L"::popups_password.txt"),
- HH_TP_HELP_WM_HELP,
- (DWORD_PTR) ctxids);
- }
-
- if (hw == NULL) {
- khm_html_help(hwnd, NULL, HH_HELP_CONTEXT,
- ((d->nc->subtype == KMSG_CRED_NEW_CREDS)?
- IDH_ACTION_NEW_ID: IDH_ACTION_PASSWD_ID));
- }
-
- return TRUE;
-}
-
-static LRESULT CALLBACK nc_window_proc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam)
-{
- switch(uMsg) {
- case WM_CREATE:
- return nc_handle_wm_create(hwnd, uMsg, wParam, lParam);
-
- case WM_DESTROY:
- return nc_handle_wm_destroy(hwnd, uMsg, wParam, lParam);
-
- case WM_COMMAND:
- return nc_handle_wm_command(hwnd, uMsg, wParam, lParam);
-
- case WM_MOVE:
- case WM_MOVING:
- return nc_handle_wm_moving(hwnd, uMsg, wParam, lParam);
-
- case WM_HELP:
- return nc_handle_wm_help(hwnd, uMsg, wParam, lParam);
-
- case KHUI_WM_NC_NOTIFY:
- return nc_handle_wm_nc_notify(hwnd, uMsg, wParam, lParam);
- }
-
- /* Note that this is technically a dialog box */
- return DefDlgProc(hwnd, uMsg, wParam, lParam);
-}
-
-void khm_register_newcredwnd_class(void)
-{
- WNDCLASSEX wcx;
-
- wcx.cbSize = sizeof(wcx);
- wcx.style = CS_DBLCLKS | CS_OWNDC;
- wcx.lpfnWndProc = nc_window_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((HINSTANCE) NULL, IDC_ARROW);
- wcx.hbrBackground = (HBRUSH) (COLOR_BACKGROUND + 1);
- wcx.lpszMenuName = NULL;
- wcx.lpszClassName = KHUI_NEWCREDWND_CLASS;
- wcx.hIconSm = NULL;
-
- khui_newcredwnd_cls = RegisterClassEx(&wcx);
-}
-
-void khm_unregister_newcredwnd_class(void)
-{
- UnregisterClass((LPWSTR) khui_newcredwnd_cls, khm_hInstance);
-}
-
-HWND khm_create_newcredwnd(HWND parent, khui_new_creds * c)
-{
- wchar_t wtitle[256];
- HWND hwnd;
-
- if (c->window_title == NULL) {
- if (c->subtype == KMSG_CRED_PASSWORD)
- LoadString(khm_hInstance,
- IDS_WT_PASSWORD,
- wtitle,
- ARRAYLENGTH(wtitle));
- else
- LoadString(khm_hInstance,
- IDS_WT_NEW_CREDS,
- wtitle,
- ARRAYLENGTH(wtitle));
- }
-
- hwnd = CreateWindowEx(WS_EX_DLGMODALFRAME | WS_EX_CONTEXTHELP,
- MAKEINTATOM(khui_newcredwnd_cls),
- ((c->window_title)?c->window_title: wtitle),
- WS_DLGFRAME | WS_POPUPWINDOW | WS_CLIPCHILDREN,
- 0,0,400,400, /* bogus values. the window
- is going to resize and
- reposition itself
- anyway */
- parent,
- NULL,
- khm_hInstance,
- (LPVOID) c);
-
-#ifdef DEBUG
- assert(hwnd != NULL);
-#endif
-
- /* note that the window is not visible yet. That's because, at
- this point we don't know what the panels are */
-
- return hwnd;
-}
-
-void khm_prep_newcredwnd(HWND hwnd)
-{
- SendMessage(hwnd, KHUI_WM_NC_NOTIFY,
- MAKEWPARAM(0, WMNC_DIALOG_SETUP), 0);
-}
-
-void khm_show_newcredwnd(HWND hwnd)
-{
- /* add all the panels in and prep UI */
- SendMessage(hwnd, KHUI_WM_NC_NOTIFY,
- MAKEWPARAM(0, WMNC_DIALOG_ACTIVATE), 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 the OEMRESOURCE constants for locating standard icon
+ resources. */
+#define OEMRESOURCE
+
+#include<khmapp.h>
+#include<assert.h>
+
+ATOM khui_newcredwnd_cls;
+
+/* forward dcl */
+static void
+nc_position_credtext(khui_nc_wnd_data * d);
+
+/* Common dialog procedure used by the main credential panel
+ (IDD_NC_NEWCRED) and the button bar (IDC_NC_BBAR). */
+
+static void
+nc_layout_main_panel(khui_nc_wnd_data * d);
+
+static void
+nc_layout_new_cred_window(khui_nc_wnd_data * d);
+
+static INT_PTR CALLBACK
+nc_common_dlg_proc(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ switch(uMsg) {
+ case WM_INITDIALOG:
+ {
+ khui_nc_wnd_data * d;
+
+ d = (khui_nc_wnd_data *) lParam;
+
+#pragma warning(push)
+#pragma warning(disable: 4244)
+ SetWindowLongPtr(hwnd, DWLP_USER, lParam);
+#pragma warning(pop)
+
+ if (d->nc->subtype == KMSG_CRED_PASSWORD) {
+ ShowWindow(GetDlgItem(hwnd, IDC_NC_ADVANCED),
+ SW_HIDE);
+ }
+ }
+ return TRUE;
+
+ case WM_COMMAND:
+ {
+ int ctrl_id;
+
+ ctrl_id = LOWORD(wParam);
+ if (ctrl_id < KHUI_CW_ID_MIN ||
+ ctrl_id > KHUI_CW_ID_MAX) {
+ /* pump it to the parent */
+ PostMessage(GetParent(hwnd), WM_COMMAND, wParam, lParam);
+ return TRUE;
+ } /* else we allow the message to fall through and get
+ passed into the identity provider's message
+ handler. */
+ }
+ break;
+
+ case KHUI_WM_NC_NOTIFY:
+ {
+ khui_nc_wnd_data * d;
+ d = (khui_nc_wnd_data *)(LONG_PTR)
+ GetWindowLongPtr(hwnd, DWLP_USER);
+
+ /* message sent by parent to notify us of something */
+ switch(HIWORD(wParam)) {
+ case WMNC_DIALOG_EXPAND:
+ /* fallthrough */
+ case WMNC_UPDATE_LAYOUT:
+ if(hwnd == d->dlg_main) {
+
+ nc_layout_main_panel(d);
+
+ return TRUE;
+ }
+ break; /* nop */
+ }
+ }
+ return TRUE;
+ }
+
+ /* check if we have a wnd_data, and if so pass the message on to
+ the identity provider callback. */
+ {
+ khui_nc_wnd_data * d;
+
+ d = (khui_nc_wnd_data *) (LONG_PTR)
+ GetWindowLongPtr(hwnd, DWLP_USER);
+
+ /* TODO: filter out and forward only the messages that
+ originated or pertain to the identity selection
+ controls. */
+ if (d && d->nc && d->nc->ident_cb) {
+ return d->nc->ident_cb(d->nc, WMNC_IDENT_WMSG, hwnd, uMsg,
+ wParam, lParam);
+ }
+ }
+
+ return FALSE;
+}
+
+static void
+nc_notify_clear(khui_nc_wnd_data * d) {
+
+ if (d->notif_type == NC_NOTIFY_NONE)
+ /* there are no notifications anyway. */
+ return;
+
+ if (d->hwnd_notif_label)
+ DestroyWindow(d->hwnd_notif_label);
+
+ if (d->hwnd_notif_aux)
+ DestroyWindow(d->hwnd_notif_aux);
+
+ d->hwnd_notif_label = NULL;
+ d->hwnd_notif_aux = NULL;
+
+ SetRectEmpty(&d->r_notif);
+
+ d->notif_type = NC_NOTIFY_NONE;
+
+ /* Note that we must call nc_layout_main_panel() after calling
+ this to adjust the layout of the main panel. However we aren't
+ calling it here since we might want to add another set of
+ notifications or make other changes to the main panel content
+ before calling nc_layout_main_panel(). */
+}
+
+static void
+nc_notify_marquee(khui_nc_wnd_data * d, const wchar_t * label) {
+
+#if (_WIN32_IE >= 0x0600)
+ HDC hdc;
+ size_t length;
+ SIZE label_size;
+#endif
+
+ RECT r_label;
+ RECT r_mq;
+ RECT r_row;
+ HFONT hfont;
+ HWND hwnd;
+ HDWP hdefer;
+
+ /* Clear the notification area. We only support one notification
+ at a time. */
+ nc_notify_clear(d);
+
+#ifdef DEBUG
+ assert(d->dlg_main);
+#endif
+
+#if (_WIN32_IE >= 0x0600)
+
+ /* We can only show the marquee control if the comctl32 DLL is
+ version 6.0 or later. Otherwise we only show the label. */
+
+ if (FAILED(StringCchLength(label, KHUI_MAXCCH_SHORT_DESC, &length))) {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ length = KHUI_MAXCCH_SHORT_DESC;
+ }
+
+ /* See how big the notification control needs to be. */
+
+ hdc = GetDC(d->dlg_main);
+#ifdef DEBUG
+ assert(hdc != NULL);
+#endif
+
+ GetTextExtentPoint32(hdc, label, (int) length, &label_size);
+
+ ReleaseDC(d->dlg_main, hdc);
+
+ CopyRect(&r_row, &d->r_row);
+
+ if (label_size.cx > d->r_e_label.right - d->r_e_label.left) {
+ /* using an entire row */
+ CopyRect(&r_label, &d->r_row);
+ CopyRect(&r_mq, &d->r_n_input);
+ OffsetRect(&r_mq, 0, r_row.bottom - r_row.top);
+ r_row.bottom += r_row.bottom - r_row.top;
+ } else if (label_size.cx > d->r_n_label.right - d->r_n_label.left) {
+ /* using large labels */
+ CopyRect(&r_label, &d->r_e_label);
+ CopyRect(&r_mq, &d->r_e_input);
+ } else {
+ /* normal labels */
+ CopyRect(&r_label, &d->r_n_label);
+ CopyRect(&r_mq, &d->r_n_input);
+ }
+
+ InflateRect(&r_mq, 0, - ((r_mq.bottom - r_mq.top) / 4));
+
+#else /* _WIN32_IE < 0x0600 */
+
+ /* We are just showing the label */
+ CopyRect(&r_row, &d->r_row);
+ CopyRect(&r_label, &r_row);
+ SetRectEmpty(&r_mq);
+
+#endif /* _WIN32_IE >= 0x0600 */
+
+ {
+ long y;
+
+ if (IsRectEmpty(&d->r_custprompt)) {
+ y = d->r_idspec.bottom;
+ } else {
+ y = d->r_custprompt.bottom;
+ }
+
+ OffsetRect(&r_row, d->r_area.left, y);
+ OffsetRect(&r_label, r_row.left, r_row.top);
+ OffsetRect(&r_mq, r_row.left, r_row.top);
+ }
+
+ hfont = (HFONT) SendMessage(d->dlg_main, WM_GETFONT, 0, 0);
+
+ hdefer = BeginDeferWindowPos(2);
+
+ /* the label */
+ hwnd = CreateWindowEx(0,
+ L"STATIC",
+ label,
+ WS_CHILD | SS_ENDELLIPSIS,
+ r_label.left, r_label.top,
+ r_label.right - r_label.left,
+ r_label.bottom - r_label.top,
+ d->dlg_main,
+ NULL, NULL, NULL);
+#ifdef DEBUG
+ assert(hwnd != NULL);
+#endif
+ SendMessage(hwnd, WM_SETFONT, (WPARAM) hfont, (LPARAM) TRUE);
+
+ DeferWindowPos(hdefer, hwnd, NULL,
+ 0, 0, 0, 0,
+ SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER |
+ SWP_NOSIZE | SWP_SHOWWINDOW);
+
+ d->hwnd_notif_label = hwnd;
+
+ /* and the marquee */
+
+#if (_WIN32_IE >= 0x0600)
+
+ /* unfortunately, the marquee is only available on comctl32
+ version 6.0 or later. On previous versions, we only display
+ the message label. */
+
+ hwnd = CreateWindowEx(0,
+ PROGRESS_CLASS,
+ L"",
+ WS_CHILD | PBS_MARQUEE,
+ r_mq.left, r_mq.top,
+ r_mq.right - r_mq.left,
+ r_mq.bottom - r_mq.top,
+ d->dlg_main,
+ NULL, NULL, NULL);
+#ifdef DEBUG
+ assert(hwnd != NULL);
+#endif
+
+ SendMessage(hwnd, PBM_SETMARQUEE, TRUE, 100);
+
+ DeferWindowPos(hdefer, hwnd, NULL,
+ 0, 0, 0, 0,
+ SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER |
+ SWP_NOSIZE | SWP_SHOWWINDOW);
+
+ d->hwnd_notif_aux = hwnd;
+
+#endif /* _WIN32_IE >= 0x0600 */
+
+ EndDeferWindowPos(hdefer);
+
+ CopyRect(&d->r_notif, &r_row);
+
+ d->notif_type = NC_NOTIFY_MARQUEE;
+
+ /* Note that we must call nc_layout_main_panel() after calling
+ this to adjust the layout of the main panel. However we aren't
+ calling it here since we might want to add another set of
+ notifications or make other changes to the main panel content
+ before calling nc_layout_main_panel(). */
+}
+
+static void
+nc_notify_message(khui_nc_wnd_data * d,
+ kherr_severity severity,
+ const wchar_t * message) {
+
+ SIZE icon_size;
+ LPCTSTR icon_res;
+ HICON h_icon;
+ HWND hwnd;
+ HFONT hfont;
+ HDWP hdefer;
+
+ RECT r_row;
+ RECT r_label;
+ RECT r_icon;
+
+ nc_notify_clear(d);
+
+ icon_size.cx = GetSystemMetrics(SM_CXSMICON);
+ icon_size.cy = GetSystemMetrics(SM_CYSMICON);
+
+ switch(severity) {
+ case KHERR_INFO:
+ icon_res = MAKEINTRESOURCE(OIC_INFORMATION);
+ break;
+
+ case KHERR_WARNING:
+ icon_res = MAKEINTRESOURCE(OIC_WARNING);
+ break;
+
+ case KHERR_ERROR:
+ icon_res = MAKEINTRESOURCE(OIC_ERROR);
+ break;
+
+ default:
+ icon_res = NULL;
+ }
+
+ if (icon_res != NULL) {
+ h_icon = (HICON) LoadImage(NULL,
+ icon_res,
+ IMAGE_ICON,
+ icon_size.cx,
+ icon_size.cy,
+ LR_DEFAULTCOLOR | LR_SHARED);
+ } else {
+ h_icon = NULL;
+ }
+
+ CopyRect(&r_row, &d->r_row);
+
+#define CENTERVALUE(w,v) ((w)/2 - (v)/2)
+
+ SetRect(&r_icon,
+ 0, CENTERVALUE(r_row.bottom - r_row.top, icon_size.cy),
+ icon_size.cx,
+ CENTERVALUE(r_row.bottom - r_row.top, icon_size.cy) + icon_size.cy);
+
+#undef CENTERVALUE
+
+ CopyRect(&r_label, &r_row);
+ OffsetRect(&r_label, -r_label.left, -r_label.top);
+ r_label.left += (icon_size.cx * 3) / 2;
+
+ {
+ long y;
+
+ if (IsRectEmpty(&d->r_custprompt)) {
+ y = d->r_idspec.bottom;
+ } else {
+ y = d->r_custprompt.bottom;
+ }
+
+ OffsetRect(&r_row, d->r_area.left, y);
+ OffsetRect(&r_label, r_row.left, r_row.top);
+ OffsetRect(&r_icon, r_row.left, r_row.top);
+ }
+
+ hfont = (HFONT) SendMessage(d->dlg_main, WM_GETFONT, 0, 0);
+
+ hdefer = BeginDeferWindowPos(2);
+
+ hwnd = CreateWindowEx(0,
+ L"STATIC",
+ message,
+ WS_CHILD | SS_ENDELLIPSIS | SS_CENTER,
+ r_label.left, r_label.top,
+ r_label.right - r_label.left,
+ r_label.bottom - r_label.top,
+ d->dlg_main,
+ NULL, NULL, NULL);
+#ifdef DEBUG
+ assert(hwnd != NULL);
+#endif
+ SendMessage(hwnd, WM_SETFONT, (WPARAM) hfont, (LPARAM) TRUE);
+
+ DeferWindowPos(hdefer, hwnd, NULL,
+ 0, 0, 0, 0,
+ SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER |
+ SWP_NOSIZE | SWP_SHOWWINDOW);
+
+ d->hwnd_notif_label = hwnd;
+
+ hwnd = CreateWindowEx(0,
+ L"STATIC",
+ NULL,
+ WS_CHILD | SS_ICON |
+#if (_WIN32_IE >= 0x0600)
+ SS_REALSIZECONTROL
+#else
+ 0
+#endif
+ ,
+ r_icon.left, r_icon.top,
+ r_icon.right - r_icon.left,
+ r_icon.bottom - r_icon.top,
+ d->dlg_main,
+ NULL, NULL, NULL);
+#ifdef DEBUG
+ assert(hwnd != NULL);
+#endif
+
+ if (h_icon && hwnd)
+ SendMessage(hwnd, STM_SETICON, (WPARAM) h_icon, 0);
+
+ DeferWindowPos(hdefer, hwnd, NULL,
+ 0, 0, 0, 0,
+ SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER |
+ SWP_NOSIZE | SWP_SHOWWINDOW | SWP_NOZORDER);
+
+ d->hwnd_notif_aux = hwnd;
+
+ EndDeferWindowPos(hdefer);
+
+ CopyRect(&d->r_notif, &r_row);
+
+ d->notif_type = NC_NOTIFY_MESSAGE;
+
+ /* Note that we must call nc_layout_main_panel() after calling
+ this to adjust the layout of the main panel. However we aren't
+ calling it here since we might want to add another set of
+ notifications or make other changes to the main panel content
+ before calling nc_layout_main_panel(). */
+}
+
+static void
+nc_layout_main_panel(khui_nc_wnd_data * d)
+{
+ RECT r_main;
+ HWND hw_ct;
+ HWND hw_ct_label;
+ HDWP hdwp;
+ RECT r_used; /* extent used by identity specifiers,
+ custom prompts and notificaiton
+ controls. */
+
+ RECT r_wmain; /* extents of the main window in screen
+ coordinates. */
+
+ r_main.left = 0;
+ r_main.top = 0;
+ r_main.bottom = NCDLG_HEIGHT;
+ r_main.right = NCDLG_WIDTH;
+
+ MapDialogRect(d->dlg_main, &r_main);
+
+ CopyRect(&r_used, &d->r_idspec);
+
+ GetWindowRect(d->dlg_main, &r_wmain);
+
+ hdwp = BeginDeferWindowPos(7);
+
+ /* check if the notification area and the custom prompt area are
+ overlapping. */
+
+ if (d->notif_type != NC_NOTIFY_NONE) {
+ long delta_y = 0;
+ RECT r;
+
+ CopyRect(&r, &d->r_custprompt);
+
+ if (IsRectEmpty(&d->r_custprompt)) {
+ /* if there are no custom prompts, then the notification
+ area should be immediately below the identitify
+ specifers. */
+
+ delta_y = d->r_idspec.bottom - d->r_notif.top;
+ } else {
+ /* otherwise, the notification area should be immediately
+ below the custom prompt area */
+
+ delta_y = d->r_custprompt.bottom - d->r_notif.top;
+ }
+
+ if (delta_y != 0) {
+ RECT r_lbl;
+ RECT r_aux;
+
+ if (d->hwnd_notif_label) {
+ GetWindowRect(d->hwnd_notif_label, &r_lbl);
+ OffsetRect(&r_lbl, -r_wmain.left, delta_y - r_wmain.top);
+
+ DeferWindowPos(hdwp, d->hwnd_notif_label, NULL,
+ r_lbl.left, r_lbl.top, 0, 0,
+ SWP_NOACTIVATE | SWP_NOOWNERZORDER |
+ SWP_NOZORDER | SWP_NOSIZE);
+ }
+
+ if (d->hwnd_notif_aux) {
+ GetWindowRect(d->hwnd_notif_aux, &r_aux);
+ OffsetRect(&r_aux, -r_wmain.left, delta_y - r_wmain.top);
+
+ DeferWindowPos(hdwp, d->hwnd_notif_aux, NULL,
+ r_aux.left, r_aux.top, 0, 0,
+ SWP_NOACTIVATE | SWP_NOOWNERZORDER |
+ SWP_NOZORDER | SWP_NOSIZE);
+ }
+
+ OffsetRect(&d->r_notif, 0, delta_y);
+ }
+ }
+
+ if (!IsRectEmpty(&d->r_custprompt)) {
+ r_used.bottom = max(d->r_custprompt.bottom,
+ r_used.bottom);
+ }
+
+ if (!IsRectEmpty(&d->r_notif)) {
+ r_used.bottom = max(d->r_notif.bottom,
+ r_used.bottom);
+ }
+
+ if (d->nc->mode == KHUI_NC_MODE_MINI) {
+ RECT r_ok;
+ RECT r_cancel;
+ RECT r_advanced;
+ HWND hw;
+
+ hw = GetDlgItem(d->dlg_main, IDOK);
+#ifdef DEBUG
+ assert(hw != NULL);
+#endif
+ GetWindowRect(hw, &r_ok);
+ OffsetRect(&r_ok, -r_wmain.left, -r_ok.top + r_used.bottom);
+
+ DeferWindowPos(hdwp, hw, NULL,
+ r_ok.left, r_ok.top, 0, 0,
+ SWP_NOACTIVATE | SWP_NOOWNERZORDER |
+ SWP_NOZORDER | SWP_NOSIZE | SWP_SHOWWINDOW);
+
+ hw = GetDlgItem(d->dlg_main, IDCANCEL);
+#ifdef DEBUG
+ assert(hw != NULL);
+#endif
+ GetWindowRect(hw, &r_cancel);
+ OffsetRect(&r_cancel, -r_wmain.left, -r_cancel.top + r_used.bottom);
+
+ DeferWindowPos(hdwp, hw, NULL,
+ r_cancel.left, r_cancel.top, 0, 0,
+ SWP_NOACTIVATE | SWP_NOOWNERZORDER |
+ SWP_NOZORDER | SWP_NOSIZE | SWP_SHOWWINDOW);
+
+ hw = GetDlgItem(d->dlg_main, IDC_NC_ADVANCED);
+#ifdef DEBUG
+ assert(hw != NULL);
+#endif
+ GetWindowRect(hw, &r_advanced);
+ OffsetRect(&r_advanced, -r_wmain.left, -r_advanced.top + r_used.bottom);
+
+ DeferWindowPos(hdwp, hw, NULL,
+ r_advanced.left, r_advanced.top, 0, 0,
+ SWP_NOACTIVATE | SWP_NOOWNERZORDER |
+ SWP_NOZORDER | SWP_NOSIZE | SWP_SHOWWINDOW);
+
+ /* and now update the extents of the main panel */
+ r_main.bottom = r_used.bottom + (r_ok.bottom - r_ok.top) + d->r_area.top;
+
+ CopyRect(&d->r_main, &r_main);
+
+ } else {
+
+ HWND hw;
+
+ hw = GetDlgItem(d->dlg_main, IDOK);
+#ifdef DEBUG
+ assert(hw != NULL);
+#endif
+ if (IsWindowVisible(hw))
+ DeferWindowPos(hdwp, hw, NULL,
+ 0, 0, 0, 0,
+ SWP_HIDEWINDOW | SWP_NOMOVE | SWP_NOSIZE |
+ SWP_NOOWNERZORDER | SWP_NOZORDER);
+
+ hw = GetDlgItem(d->dlg_main, IDCANCEL);
+#ifdef DEBUG
+ assert(hw != NULL);
+#endif
+ if (IsWindowVisible(hw))
+ DeferWindowPos(hdwp, hw, NULL,
+ 0, 0, 0, 0,
+ SWP_HIDEWINDOW | SWP_NOMOVE | SWP_NOSIZE |
+ SWP_NOOWNERZORDER | SWP_NOZORDER);
+
+ hw = GetDlgItem(d->dlg_main, IDC_NC_ADVANCED);
+#ifdef DEBUG
+ assert(hw != NULL);
+#endif
+ if (IsWindowVisible(hw))
+ DeferWindowPos(hdwp, hw, NULL,
+ 0, 0, 0, 0,
+ SWP_HIDEWINDOW | SWP_NOMOVE | SWP_NOSIZE |
+ SWP_NOOWNERZORDER | SWP_NOZORDER);
+
+ d->r_credtext.top = r_used.bottom;
+
+ CopyRect(&d->r_main, &r_main);
+ }
+
+ /* now update the layout of the credentials text window */
+
+ hw_ct = GetDlgItem(d->dlg_main, IDC_NC_CREDTEXT);
+ hw_ct_label = GetDlgItem(d->dlg_main, IDC_NC_CREDTEXT_LABEL);
+#ifdef DEBUG
+ assert(hw_ct != NULL);
+ assert(hw_ct_label != NULL);
+#endif
+
+ if (d->nc->mode == KHUI_NC_MODE_MINI ||
+ d->r_credtext.bottom < d->r_credtext.top + d->r_row.bottom * 2) {
+
+ /* either we aren't supposed to show the credentials text
+ window, or we don't have enough room. */
+ if (IsWindowVisible(hw_ct) || IsWindowVisible(hw_ct_label)) {
+
+ DeferWindowPos(hdwp, hw_ct, NULL,
+ 0, 0, 0, 0,
+ SWP_HIDEWINDOW | SWP_NOOWNERZORDER |
+ SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE);
+
+ DeferWindowPos(hdwp, hw_ct_label, NULL,
+ 0, 0, 0, 0,
+ SWP_HIDEWINDOW | SWP_NOOWNERZORDER |
+ SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE);
+
+ }
+
+ } else {
+
+ DeferWindowPos(hdwp,
+ hw_ct, NULL,
+ d->r_credtext.left + d->r_n_input.left, /* x */
+ d->r_credtext.top, /* y */
+ d->r_n_input.right - d->r_n_input.left, /* width */
+ d->r_credtext.bottom - d->r_credtext.top, /* height */
+ SWP_NOACTIVATE | SWP_NOOWNERZORDER |
+ SWP_NOZORDER | SWP_SHOWWINDOW);
+
+ DeferWindowPos(hdwp,
+ hw_ct_label, NULL,
+ d->r_credtext.left + d->r_n_label.left, /* x */
+ d->r_credtext.top, /* y */
+ d->r_n_label.right - d->r_n_label.left, /* width */
+ d->r_n_label.bottom - d->r_n_label.top, /* height */
+ SWP_NOACTIVATE | SWP_NOOWNERZORDER |
+ SWP_NOZORDER | SWP_SHOWWINDOW);
+ }
+
+ EndDeferWindowPos(hdwp);
+
+ /* NOTE: although we updated d->r_main, if the new credentials
+ window is in mini mode, we must call
+ nc_layout_new_cred_window() to adjust the size of the new
+ credentials window to fit the main panel. We don't do it here
+ because we need to keep these two operations separate. */
+}
+
+/* Credential type panel comparison function. Tabs are sorted based
+ on the following criteria:
+
+ 1) By ordinal - Panels with ordinal -1 will be ranked after panels
+ whose ordinal is not -1.
+
+ 2) By name - Case insensitive comparison of the name. If the panel
+ does not have a name (i.e. the ->name member is NULL, it will be
+ ranked after panels which have a name.
+ */
+static int __cdecl
+nc_tab_sort_func(const void * v1, const void * v2)
+{
+ /* v1 and v2 and of type : khui_new_creds_by_type ** */
+ khui_new_creds_by_type *t1, *t2;
+
+ t1 = *((khui_new_creds_by_type **) v1);
+ t2 = *((khui_new_creds_by_type **) v2);
+
+ if(t1->ordinal != -1) {
+ if(t2->ordinal != -1) {
+ if(t1->ordinal == t2->ordinal) {
+ if (t1->name && t2->name)
+ return _wcsicmp(t1->name, t2->name);
+ else if (t1->name)
+ return -1;
+ else if (t2->name)
+ return 1;
+ else
+ return 0;
+ } else {
+ /* safe to convert to an int here */
+ return (int) (t1->ordinal - t2->ordinal);
+ }
+ } else
+ return -1;
+ } else {
+ if(t2->ordinal != -1)
+ return 1;
+ else if (t1->name && t2->name)
+ return wcscmp(t1->name, t2->name);
+ else if (t1->name)
+ return -1;
+ else if (t2->name)
+ return 1;
+ else
+ return 0;
+ }
+}
+
+static void
+nc_notify_types(khui_new_creds * c, UINT uMsg,
+ WPARAM wParam, LPARAM lParam, BOOL sync)
+{
+ khm_size i;
+
+ for(i=0; i<c->n_types; i++) {
+
+ if (c->types[i]->hwnd_panel == NULL)
+ continue;
+
+ if (sync)
+ SendMessage(c->types[i]->hwnd_panel, uMsg, wParam, lParam);
+ else
+ PostMessage(c->types[i]->hwnd_panel, uMsg, wParam, lParam);
+ }
+}
+
+static void
+nc_clear_password_fields(khui_nc_wnd_data * d)
+{
+ khm_size i;
+ khm_boolean need_sync = FALSE;
+
+ khui_cw_lock_nc(d->nc);
+
+ for (i=0; i < d->nc->n_prompts; i++) {
+ if ((d->nc->prompts[i]->flags & KHUI_NCPROMPT_FLAG_HIDDEN) &&
+ d->nc->prompts[i]->hwnd_edit) {
+ SetWindowText(d->nc->prompts[i]->hwnd_edit,
+ L"");
+ need_sync = TRUE;
+ }
+ }
+
+ khui_cw_unlock_nc(d->nc);
+
+ if (need_sync) {
+ khui_cw_sync_prompt_values(d->nc);
+ }
+}
+
+/* used by nc_enable_controls */
+
+struct nc_enum_wnd_data {
+ khui_nc_wnd_data * d;
+ khm_boolean enable;
+};
+
+static
+BOOL CALLBACK
+nc_enum_wnd_proc(HWND hwnd,
+ LPARAM lParam)
+{
+ struct nc_enum_wnd_data * wd;
+
+ wd = (struct nc_enum_wnd_data *) lParam;
+
+ EnableWindow(hwnd, wd->enable);
+
+ return TRUE;
+}
+
+static void
+nc_enable_controls(khui_nc_wnd_data * d, khm_boolean enable)
+{
+ struct nc_enum_wnd_data wd;
+
+ ZeroMemory(&wd, sizeof(wd));
+
+ wd.d = d;
+ wd.enable = enable;
+
+ EnumChildWindows(d->dlg_main, nc_enum_wnd_proc, (LPARAM) &wd);
+}
+
+#define NC_MAXCCH_CREDTEXT 16384
+#define NC_MAXCB_CREDTEXT (NC_MAXCCH_CREDTEXT * sizeof(wchar_t))
+
+static void
+nc_update_credtext(khui_nc_wnd_data * d)
+{
+ wchar_t * ctbuf = NULL;
+ wchar_t * buf;
+ BOOL okEnable = FALSE;
+ BOOL validId = FALSE;
+ HWND hw = NULL;
+ size_t cch = 0;
+
+ ctbuf = PMALLOC(NC_MAXCB_CREDTEXT);
+
+ assert(ctbuf != NULL);
+
+ LoadString(khm_hInstance, IDS_NC_CREDTEXT_TABS, ctbuf, NC_MAXCCH_CREDTEXT);
+ StringCchLength(ctbuf, NC_MAXCCH_CREDTEXT, &cch);
+ buf = ctbuf + cch;
+ nc_notify_types(d->nc, KHUI_WM_NC_NOTIFY,
+ MAKEWPARAM(0, WMNC_UPDATE_CREDTEXT), (LPARAM) d->nc, TRUE);
+
+ /* hopefully all the types have updated their credential texts */
+
+ /* if the dialog is in the mini mode, we have to display
+ exceptions using a notification. */
+ if (d->nc->mode == KHUI_NC_MODE_MINI) {
+ BOOL need_layout = FALSE;
+ if (d->nc->n_identities == 0) {
+
+ /* There are no identities selected. We don't show any
+ notifications here. */
+ if (d->notif_type != NC_NOTIFY_NONE) {
+ nc_notify_clear(d);
+ need_layout = TRUE;
+ }
+
+ } else {
+
+ wchar_t id_name[KCDB_IDENT_MAXCCH_NAME];
+ wchar_t format[256];
+ wchar_t msg[ARRAYLENGTH(format) + ARRAYLENGTH(id_name)];
+ khm_size cbbuf;
+ khm_int32 flags;
+
+ kcdb_identity_get_flags(d->nc->identities[0], &flags);
+
+ cbbuf = sizeof(id_name);
+ kcdb_identity_get_name(d->nc->identities[0], id_name, &cbbuf);
+
+ if (flags & KCDB_IDENT_FLAG_INVALID) {
+
+ /* identity is invalid */
+ LoadString(khm_hInstance, IDS_NCN_IDENT_INVALID,
+ format, ARRAYLENGTH(format));
+ StringCbPrintf(msg, sizeof(msg), format, id_name);
+
+ nc_notify_message(d, KHERR_ERROR, msg);
+
+ need_layout = TRUE;
+
+ } else if ((flags & KCDB_IDENT_FLAG_VALID) ||
+ d->nc->subtype == KMSG_CRED_PASSWORD) {
+ /* special case: If we are going to change the
+ password, we don't expect the identity provider to
+ validate the identity in real time. As such, we
+ assume that the identity is valid. */
+
+ /* identity is valid */
+ if (d->notif_type != NC_NOTIFY_NONE) {
+ nc_notify_clear(d);
+ need_layout = TRUE;
+ }
+
+ } else if (flags & KCDB_IDENT_FLAG_UNKNOWN) {
+
+ /* unknown state */
+ LoadString(khm_hInstance, IDS_NCN_IDENT_UNKNOWN,
+ format, ARRAYLENGTH(format));
+ StringCbPrintf(msg, sizeof(msg), format, id_name);
+
+ nc_notify_message(d, KHERR_WARNING, msg);
+
+ need_layout = TRUE;
+
+ } else {
+
+ /* still checking */
+ LoadString(khm_hInstance, IDS_NCN_IDENT_CHECKING,
+ format, ARRAYLENGTH(format));
+ StringCbPrintf(msg, sizeof(msg), format, id_name);
+
+ nc_notify_marquee(d, msg);
+
+ need_layout = TRUE;
+
+ }
+ }
+
+ if (need_layout) {
+ nc_layout_main_panel(d);
+ nc_layout_new_cred_window(d);
+ }
+ }
+
+ if(d->nc->n_identities == 1) {
+ wchar_t main_fmt[256];
+ wchar_t id_fmt[256];
+ wchar_t id_name[KCDB_IDENT_MAXCCH_NAME];
+ wchar_t id_string[KCDB_IDENT_MAXCCH_NAME + 256];
+ khm_size cbbuf;
+ khm_int32 flags;
+
+ LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_ONE,
+ main_fmt, (int) ARRAYLENGTH(main_fmt));
+
+ cbbuf = sizeof(id_name);
+ kcdb_identity_get_name(d->nc->identities[0], id_name, &cbbuf);
+
+ kcdb_identity_get_flags(d->nc->identities[0], &flags);
+
+ if (flags & KCDB_IDENT_FLAG_INVALID) {
+ LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_INVALID,
+ id_fmt, (int) ARRAYLENGTH(id_fmt));
+ } else if(flags & KCDB_IDENT_FLAG_VALID) {
+ LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_VALID,
+ id_fmt, (int) ARRAYLENGTH(id_fmt));
+ } else if(flags & KCDB_IDENT_FLAG_UNKNOWN) {
+ LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_UNCHECKED,
+ id_fmt, (int) ARRAYLENGTH(id_fmt));
+ } else if(d->nc->subtype == KMSG_CRED_NEW_CREDS) {
+ LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_CHECKING,
+ id_fmt, (int) ARRAYLENGTH(id_fmt));
+ } else {
+ LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_UNCHECKED,
+ id_fmt, (int) ARRAYLENGTH(id_fmt));
+ }
+
+ StringCbPrintf(id_string, sizeof(id_string), id_fmt, id_name);
+
+ StringCbPrintf(buf, NC_MAXCB_CREDTEXT - cch*sizeof(wchar_t),
+ main_fmt, id_string);
+
+ if (flags & KCDB_IDENT_FLAG_VALID) {
+ if (flags & KCDB_IDENT_FLAG_DEFAULT)
+ LoadString(khm_hInstance, IDS_NC_ID_DEF,
+ id_string, ARRAYLENGTH(id_string));
+ else if (d->nc->set_default)
+ LoadString(khm_hInstance, IDS_NC_ID_WDEF,
+ id_string, ARRAYLENGTH(id_string));
+ else
+ LoadString(khm_hInstance, IDS_NC_ID_NDEF,
+ id_string, ARRAYLENGTH(id_string));
+
+ StringCbCat(buf, NC_MAXCB_CREDTEXT - cch * sizeof(wchar_t),
+ id_string);
+ }
+
+ } else if(d->nc->n_identities > 1) {
+ wchar_t *ids_string;
+ khm_size cb_ids_string;
+
+ wchar_t id_name[KCDB_IDENT_MAXCCH_NAME];
+ wchar_t id_fmt[256];
+ wchar_t id_string[KCDB_IDENT_MAXCCH_NAME + 256];
+
+ wchar_t main_fmt[256];
+ khm_size cbbuf;
+
+ LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_MANY,
+ main_fmt, (int) ARRAYLENGTH(main_fmt));
+
+ /* we are going to concatenate all the identity names into
+ a comma separated string */
+
+ /* d->nc->n_identities is at least 2 */
+ ids_string = PMALLOC((KCDB_IDENT_MAXCB_NAME + sizeof(id_fmt)) *
+ (d->nc->n_identities - 1));
+ cb_ids_string =
+ (KCDB_IDENT_MAXCB_NAME + sizeof(id_fmt)) *
+ (d->nc->n_identities - 1);
+
+ assert(ids_string != NULL);
+
+ ids_string[0] = 0;
+
+ {
+ khm_size i;
+ khm_int32 flags;
+
+ for(i=1; i<d->nc->n_identities; i++) {
+ if(i>1) {
+ StringCbCat(ids_string, cb_ids_string, L",");
+ }
+
+ flags = 0;
+
+ cbbuf = sizeof(id_name);
+ kcdb_identity_get_name(d->nc->identities[i], id_name, &cbbuf);
+ kcdb_identity_get_flags(d->nc->identities[i], &flags);
+ if(flags & KCDB_IDENT_FLAG_INVALID) {
+ LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_INVALID,
+ id_fmt, (int) ARRAYLENGTH(id_fmt));
+ } else if(flags & KCDB_IDENT_FLAG_VALID) {
+ LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_VALID,
+ id_fmt, (int) ARRAYLENGTH(id_fmt));
+ } else {
+ LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_UNCHECKED,
+ id_fmt, (int) ARRAYLENGTH(id_fmt));
+ }
+
+ StringCbPrintf(id_string, sizeof(id_string), id_fmt, id_name);
+ StringCbCat(ids_string, cb_ids_string, id_string);
+ }
+
+ cbbuf = sizeof(id_name);
+ kcdb_identity_get_name(d->nc->identities[0], id_name, &cbbuf);
+ kcdb_identity_get_flags(d->nc->identities[0], &flags);
+ if(flags & KCDB_IDENT_FLAG_INVALID) {
+ LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_INVALID,
+ id_fmt, (int) ARRAYLENGTH(id_fmt));
+ } else if(flags & KCDB_IDENT_FLAG_VALID) {
+ LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_VALID,
+ id_fmt, (int) ARRAYLENGTH(id_fmt));
+ } else {
+ LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_UNCHECKED,
+ id_fmt, (int) ARRAYLENGTH(id_fmt));
+ }
+ StringCbPrintf(id_string, sizeof(id_string), id_fmt, id_name);
+
+ StringCbPrintf(buf, NC_MAXCB_CREDTEXT - cch*sizeof(wchar_t),
+ main_fmt, id_string, ids_string);
+
+ PFREE(ids_string);
+ }
+ } else {
+ LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_NONE,
+ buf, (int)(NC_MAXCCH_CREDTEXT - cch));
+ }
+
+ /* now, append the credtext string from each of the cred types */
+ {
+ khm_size i;
+ size_t cb;
+ wchar_t * buf;
+
+ cb = NC_MAXCB_CREDTEXT;
+ buf = ctbuf;
+
+ for(i=0; i<d->nc->n_types; i++) {
+ if(d->nc->types[i]->credtext != NULL) {
+ StringCbCatEx(buf, cb,
+ d->nc->types[i]->credtext,
+ &buf, &cb,
+ 0);
+ }
+ }
+ }
+
+ SetDlgItemText(d->dlg_main, IDC_NC_CREDTEXT, ctbuf);
+
+ PFREE(ctbuf);
+
+ /* so depending on whether the primary identity was found to be
+ invalid, we need to disable the Ok button and set the title to
+ reflect this */
+
+ if(d->nc->n_identities > 0) {
+ khm_int32 flags = 0;
+
+ if(KHM_SUCCEEDED(kcdb_identity_get_flags(d->nc->identities[0],
+ &flags)) &&
+ (flags & KCDB_IDENT_FLAG_VALID)) {
+ validId = TRUE;
+ }
+ }
+
+ if (d->nc->window_title == NULL) {
+ if(validId) {
+ wchar_t wpostfix[256];
+ wchar_t wtitle[KCDB_IDENT_MAXCCH_NAME + 256];
+ khm_size cbsize;
+
+ cbsize = sizeof(wtitle);
+ kcdb_identity_get_name(d->nc->identities[0], wtitle, &cbsize);
+
+ if (d->nc->subtype == KMSG_CRED_PASSWORD)
+ LoadString(khm_hInstance, IDS_WTPOST_PASSWORD,
+ wpostfix, (int) ARRAYLENGTH(wpostfix));
+ else
+ LoadString(khm_hInstance, IDS_WTPOST_NEW_CREDS,
+ wpostfix, (int) ARRAYLENGTH(wpostfix));
+
+ StringCbCat(wtitle, sizeof(wtitle), wpostfix);
+
+ SetWindowText(d->nc->hwnd, wtitle);
+ } else {
+ wchar_t wtitle[256];
+
+ if (d->nc->subtype == KMSG_CRED_PASSWORD)
+ LoadString(khm_hInstance, IDS_WT_PASSWORD,
+ wtitle, (int) ARRAYLENGTH(wtitle));
+ else
+ LoadString(khm_hInstance, IDS_WT_NEW_CREDS,
+ wtitle, (int) ARRAYLENGTH(wtitle));
+
+ SetWindowText(d->nc->hwnd, wtitle);
+ }
+ }
+
+ if (!(d->nc->response & KHUI_NC_RESPONSE_PROCESSING)) {
+ if(validId ||
+ d->nc->subtype == KMSG_CRED_PASSWORD) {
+ /* TODO: check if all the required fields have valid values
+ before enabling the Ok button */
+ okEnable = TRUE;
+ }
+
+ hw = GetDlgItem(d->dlg_main, IDOK);
+ EnableWindow(hw, okEnable);
+ hw = GetDlgItem(d->dlg_bb, IDOK);
+ EnableWindow(hw, okEnable);
+ }
+}
+
+static void
+nc_layout_new_cred_window(khui_nc_wnd_data * ncd) {
+ khui_new_creds * c;
+ RECT r_main;
+ RECT r_ncdialog;
+ HDWP hdefer;
+
+ c = ncd->nc;
+
+ r_main.left = 0;
+ r_main.top = 0;
+ r_main.right = NCDLG_WIDTH;
+ r_main.bottom = NCDLG_HEIGHT;
+
+ MapDialogRect(ncd->dlg_main, &r_main);
+
+ hdefer = BeginDeferWindowPos(5);
+
+ if (c->mode == KHUI_NC_MODE_MINI) {
+
+ if (IsWindowVisible(ncd->tab_wnd)) {
+ DeferWindowPos(hdefer,
+ ncd->tab_wnd, NULL,
+ 0, 0, 0, 0,
+ SWP_HIDEWINDOW |
+ SWP_NOMOVE | SWP_NOOWNERZORDER |
+ SWP_NOSIZE | SWP_NOZORDER);
+ }
+
+ if (IsWindowVisible(ncd->dlg_bb)) {
+ DeferWindowPos(hdefer,
+ ncd->dlg_bb, NULL,
+ 0, 0, 0, 0,
+ SWP_HIDEWINDOW |
+ SWP_NOMOVE | SWP_NOOWNERZORDER |
+ SWP_NOSIZE | SWP_NOZORDER);
+ }
+
+ DeferWindowPos(hdefer, ncd->dlg_main, NULL,
+ r_main.left, r_main.top,
+ r_main.right - r_main.left,
+ r_main.bottom - r_main.top,
+ SWP_NOACTIVATE | SWP_NOOWNERZORDER |
+ SWP_NOZORDER | SWP_SHOWWINDOW);
+
+ /* note that the ncd->r_main.bottom may not be the same as
+ r_main.bottom because ncd->r_main.bottom is set dynamically
+ depending on custom controls. ncd->r_main is valid only
+ once nc_layout_main_panel() is called.*/
+ CopyRect(&ncd->r_required, &ncd->r_main);
+
+ } else {
+ RECT r_tabctrl;
+ RECT r_displayarea;
+ RECT r_bbar;
+ khm_size i;
+
+ /* calculate the size of the tab control so that it fits
+ snugly around the expanded main panel. */
+ CopyRect(&r_tabctrl, &r_main);
+ TabCtrl_AdjustRect(ncd->tab_wnd, TRUE, &r_tabctrl);
+
+ if (r_tabctrl.left < 0 ||
+ r_tabctrl.top < 0) {
+
+ OffsetRect(&r_tabctrl,
+ (r_tabctrl.left < 0)? -r_tabctrl.left : 0,
+ (r_tabctrl.top < 0)? -r_tabctrl.top : 0);
+
+ }
+
+#ifdef DEBUG
+ assert(r_tabctrl.left == 0);
+ assert(r_tabctrl.top == 0);
+#endif
+
+ OffsetRect(&r_tabctrl, 0, ncd->r_area.top);
+
+ /* and now calculate the rectangle where the main panel should
+ be inside the tab control. */
+ CopyRect(&r_displayarea, &r_tabctrl);
+ TabCtrl_AdjustRect(ncd->tab_wnd, FALSE, &r_displayarea);
+
+ DeferWindowPos(hdefer,
+ ncd->tab_wnd, HWND_BOTTOM,
+ r_tabctrl.left, r_tabctrl.top,
+ r_tabctrl.right - r_tabctrl.left,
+ r_tabctrl.bottom - r_tabctrl.top,
+ SWP_NOACTIVATE | SWP_NOOWNERZORDER |
+ SWP_SHOWWINDOW);
+
+ /* we have to place the button bar just to the right of the
+ tab panel. */
+ r_bbar.left = 0;
+ r_bbar.top = 0;
+ r_bbar.right = NCDLG_BBAR_WIDTH;
+ r_bbar.bottom = NCDLG_BBAR_HEIGHT;
+
+ MapDialogRect(ncd->dlg_main, &r_bbar);
+
+ OffsetRect(&r_bbar, r_tabctrl.right, 0);
+
+ DeferWindowPos(hdefer,
+ ncd->dlg_bb, NULL,
+ r_bbar.left, r_bbar.top,
+ r_bbar.right - r_bbar.left,
+ r_bbar.bottom - r_bbar.top,
+ SWP_NOACTIVATE | SWP_NOOWNERZORDER |
+ SWP_NOZORDER | SWP_SHOWWINDOW);
+
+ /* move the main panel inside the tab control... */
+ DeferWindowPos(hdefer,
+ ncd->dlg_main, NULL,
+ r_displayarea.left, r_displayarea.top,
+ r_displayarea.right - r_displayarea.left,
+ r_displayarea.bottom - r_displayarea.top,
+ SWP_NOACTIVATE | SWP_NOOWNERZORDER |
+ SWP_NOZORDER |
+ (ncd->current_panel == 0 ? SWP_SHOWWINDOW : SWP_HIDEWINDOW));
+
+ /* and also move all the credential type panels (if they have
+ been created) inside the tab control too. */
+ khui_cw_lock_nc(c);
+
+ for (i=0; i < c->n_types; i++) {
+ if (c->types[i]->hwnd_panel != NULL) {
+ DeferWindowPos(hdefer,
+ c->types[i]->hwnd_panel, NULL,
+ r_displayarea.left, r_displayarea.top,
+ r_displayarea.right - r_displayarea.left,
+ r_displayarea.bottom - r_displayarea.top,
+ SWP_NOACTIVATE | SWP_NOOWNERZORDER |
+ SWP_NOZORDER |
+ (ncd->current_panel == c->types[i]->ordinal ?
+ SWP_SHOWWINDOW : SWP_HIDEWINDOW));
+ }
+ }
+
+ khui_cw_unlock_nc(c);
+
+ /* then update the required size of the new credentials
+ dialog. */
+ ncd->r_required.left = 0;
+ ncd->r_required.top = 0;
+ ncd->r_required.right = r_bbar.right;
+ ncd->r_required.bottom = max(r_tabctrl.bottom, r_bbar.bottom) + ncd->r_area.top;
+ }
+
+ /* commit all the window moves, resizes and hides/shows we did*/
+ EndDeferWindowPos(hdefer);
+
+ /* now we have to see if the client area of the new credentials
+ window is the right size. */
+
+ GetClientRect(c->hwnd, &r_ncdialog);
+
+ if (
+
+ ((r_ncdialog.right - r_ncdialog.left !=
+ ncd->r_required.right - ncd->r_required.left)
+
+ ||
+
+ (r_ncdialog.bottom - r_ncdialog.top !=
+ ncd->r_required.bottom - ncd->r_required.top))
+
+ &&
+
+ /* we don't bother if the new creds window is already in the
+ process of changing the size. */
+ !ncd->size_changing) {
+
+ /* if not, notify the window that the size needs adjusting. */
+ if (IsWindowVisible(c->hwnd))
+ PostMessage(c->hwnd, KHUI_WM_NC_NOTIFY,
+ MAKEWPARAM(0, WMNC_UPDATE_LAYOUT), 0);
+ else
+ SendMessage(c->hwnd, KHUI_WM_NC_NOTIFY,
+ MAKEWPARAM(0, WMNC_UPDATE_LAYOUT), 0);
+ }
+}
+
+#define CW_PARAM DWLP_USER
+
+static LRESULT
+nc_handle_wm_create(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ LPCREATESTRUCT lpc;
+ khui_new_creds * c;
+ khui_nc_wnd_data * ncd;
+ int x, y;
+ int width, height;
+ RECT r;
+ HFONT hf_main;
+
+ lpc = (LPCREATESTRUCT) lParam;
+
+ ncd = PMALLOC(sizeof(*ncd));
+ ZeroMemory(ncd, sizeof(*ncd));
+
+ c = (khui_new_creds *) lpc->lpCreateParams;
+ ncd->nc = c;
+ c->hwnd = hwnd;
+
+#ifdef DEBUG
+ assert(c->subtype == KMSG_CRED_NEW_CREDS ||
+ c->subtype == KMSG_CRED_PASSWORD);
+#endif
+
+#pragma warning(push)
+#pragma warning(disable: 4244)
+ SetWindowLongPtr(hwnd, CW_PARAM, (LONG_PTR) ncd);
+#pragma warning(pop)
+
+ /* first, create the tab control that will house the main dialog
+ panel as well as the plug-in specific panels */
+ ncd->tab_wnd = CreateWindowEx(0, /* extended style */
+ WC_TABCONTROL,
+ L"TabControloxxrz", /* window name */
+ TCS_HOTTRACK | TCS_RAGGEDRIGHT |
+ TCS_SINGLELINE | TCS_TABS |
+ WS_CHILD | WS_TABSTOP | WS_CLIPSIBLINGS,
+ 0, 0, 100, 100, /* x,y,width height.
+ We'll be changing
+ these later
+ anyway. */
+ hwnd,
+ (HMENU) IDC_NC_TABS,
+ NULL,
+ 0);
+
+#ifdef DEBUG
+ assert(ncd->tab_wnd != NULL);
+#endif
+
+ /* try to create the main dialog panel */
+
+ ncd->dlg_main = CreateDialogParam(khm_hInstance,
+ MAKEINTRESOURCE(IDD_NC_NEWCRED),
+ hwnd,
+ nc_common_dlg_proc,
+ (LPARAM) ncd);
+#ifdef DEBUG
+ assert(ncd->dlg_main != NULL);
+#endif
+
+ hf_main = (HFONT) SendMessage(ncd->dlg_main, WM_GETFONT, 0, 0);
+ if (hf_main)
+ SendMessage(ncd->tab_wnd, WM_SETFONT, (WPARAM) hf_main, FALSE);
+
+ {
+ RECT r_main;
+ RECT r_area;
+ RECT r_row;
+ HWND hw;
+
+ /* During the operation of the new credentials window, we will
+ need to dynamically change the layout of the controls as a
+ result of custom prompting from credentials providers and
+ identity selectors from identity providers. In order to
+ guide the dynamic layout, we pick out a few metrics from
+ the dialog template for the main panel. The metrics come
+ from hidden STATIC controls in the dialog template. */
+
+ GetWindowRect(ncd->dlg_main, &r_main);
+
+ /* IDC_NC_TPL_PANEL spans the full extent of the dialog that
+ we can populate with custom controls. */
+ hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_PANEL);
+#ifdef DEBUG
+ assert(hw);
+#endif
+ GetWindowRect(hw, &r_area);
+ OffsetRect(&r_area,-r_main.left, -r_main.top);
+ CopyRect(&ncd->r_area, &r_area);
+
+ /* IDC_NC_TPL_ROW spans the extent of a row of normal sized
+ custom controls. A row of custom controls typicall consist
+ of a text label and an input control. */
+ hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_ROW);
+#ifdef DEBUG
+ assert(hw);
+#endif
+ GetWindowRect(hw, &r);
+ CopyRect(&r_row, &r);
+ OffsetRect(&r,-r.left, -r.top);
+ CopyRect(&ncd->r_row, &r);
+
+ /* IDC_NC_TPL_LABEL spans the extent that a normal sized
+ label. The control overlaps IDC_NC_TPL_ROW so we can get
+ coordinates relative to the row extents. */
+ hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_LABEL);
+#ifdef DEBUG
+ assert(hw);
+#endif
+ GetWindowRect(hw, &r);
+ OffsetRect(&r,-r_row.left, -r_row.top);
+ CopyRect(&ncd->r_n_label, &r);
+
+ /* IDC_NC_TPL_INPUT spans the extent of a normal sized input
+ control in a custom control row. The control overlaps
+ IDC_NC_TPL_ROW so we can get relative coordinates. */
+ hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_INPUT);
+#ifdef DEBUG
+ assert(hw);
+#endif
+ GetWindowRect(hw, &r);
+ OffsetRect(&r, -r_row.left, -r_row.top);
+ CopyRect(&ncd->r_n_input, &r);
+
+ /* IDC_NC_TPL_ROW_LG spans the extent of a row of large sized
+ controls. */
+ hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_ROW_LG);
+#ifdef DEBUG
+ assert(hw);
+#endif
+ GetWindowRect(hw, &r_row);
+
+ /* IDC_NC_TPL_LABEL_LG is a large sized label. The control
+ overlaps IDC_NC_TPL_ROW_LG. */
+ hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_LABEL_LG);
+#ifdef DEBUG
+ assert(hw);
+#endif
+ GetWindowRect(hw, &r);
+ OffsetRect(&r, -r_row.left, -r_row.top);
+ CopyRect(&ncd->r_e_label, &r);
+
+ /* IDC_NC_TPL_INPUT_LG is a large sized input control.
+ Overlaps IDC_NC_TPL_ROW_LG. */
+ hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_INPUT_LG);
+#ifdef DEBUG
+ assert(hw);
+#endif
+ GetWindowRect(hw, &r);
+ OffsetRect(&r, -r_row.left, -r_row.top);
+ CopyRect(&ncd->r_e_input, &r);
+
+ CopyRect(&ncd->r_credtext, &ncd->r_area);
+ CopyRect(&ncd->r_idspec, &ncd->r_area);
+
+ ncd->r_idspec.bottom = ncd->r_idspec.top;
+
+ /* And finally the credential text window. The only metric we
+ take from here is the Y coordinate of the bottom of the
+ control since the actual size and position of the
+ credentials window will change depending on the custom
+ controls being displayed. */
+ hw = GetDlgItem(ncd->dlg_main, IDC_NC_CREDTEXT);
+#ifdef DEBUG
+ assert(hw);
+#endif
+ GetWindowRect(hw, &r);
+ OffsetRect(&r, -r_main.left, -r_main.top);
+ ncd->r_credtext.bottom = r.bottom;
+ }
+
+ /* if the mode is 'mini'*/
+ r.left = 0;
+ r.top = 0;
+
+ if(c->mode == KHUI_NC_MODE_MINI) {
+ r.right = NCDLG_WIDTH;
+ r.bottom = NCDLG_HEIGHT;
+ } else {
+ r.right = NCDLG_WIDTH + NCDLG_BBAR_WIDTH;
+ r.bottom = NCDLG_BBAR_HEIGHT;
+ }
+
+ MapDialogRect(ncd->dlg_main, &r);
+
+ /* position the new credentials dialog */
+ width = r.right - r.left;
+ height = r.bottom - r.top;
+
+ /* adjust width and height to accomodate NC area */
+ {
+ RECT wr,cr;
+
+ GetWindowRect(hwnd, &wr);
+ GetClientRect(hwnd, &cr);
+
+ /* the non-client and client areas have already been calculated
+ at this point. We just use the difference to adjust the width
+ and height */
+ width += (wr.right - wr.left) - (cr.right - cr.left);
+ height += (wr.bottom - wr.top) - (cr.bottom - cr.top);
+ }
+
+ /* if the parent window is visible, we center the new credentials
+ dialog over the parent. Otherwise, we center it on the primary
+ display. */
+
+ if (IsWindowVisible(lpc->hwndParent)) {
+ GetWindowRect(lpc->hwndParent, &r);
+ } else {
+ if(!SystemParametersInfo(SPI_GETWORKAREA, 0, (PVOID) &r, 0)) {
+ /* failover to the window coordinates */
+ GetWindowRect(lpc->hwndParent, &r);
+ }
+ }
+ x = (r.right + r.left)/2 - width / 2;
+ y = (r.top + r.bottom)/2 - height / 2;
+
+ MoveWindow(hwnd, x, y, width, height, FALSE);
+
+ ncd->dlg_bb = CreateDialogParam(khm_hInstance,
+ MAKEINTRESOURCE(IDD_NC_BBAR),
+ hwnd,
+ nc_common_dlg_proc,
+ (LPARAM) ncd);
+
+#ifdef DEBUG
+ assert(ncd->dlg_bb);
+#endif
+
+ /* Call the identity provider callback to set the identity
+ selector controls. These controls need to be there before we
+ layout the main panel. */
+ c->ident_cb(c, WMNC_IDENT_INIT, NULL, 0, 0, (LPARAM) ncd->dlg_main);
+
+ if (c->mode == KHUI_NC_MODE_EXPANDED) {
+ SendMessage(ncd->dlg_main, KHUI_WM_NC_NOTIFY,
+ MAKEWPARAM(0, WMNC_DIALOG_EXPAND), 0);
+ } else {
+ /* we don't call nc_layout_main_panel() if the dialog is
+ expanded because posting WMNC_DIALOG_EXPAND to the main
+ panel results in it getting called anyway. */
+ nc_layout_main_panel(ncd);
+ }
+
+ nc_layout_new_cred_window(ncd);
+
+ /* add this to the dialog chain */
+ khm_add_dialog(hwnd);
+
+ return TRUE;
+}
+
+/* add a control row supplied by an identity provider */
+static void
+nc_add_control_row(khui_nc_wnd_data * d,
+ HWND label,
+ HWND input,
+ khui_control_size size)
+{
+ RECT r_row;
+ RECT r_label;
+ RECT r_input;
+ HFONT hf;
+ HDWP hdefer;
+
+ hf = (HFONT) SendMessage(d->dlg_main, WM_GETFONT, 0, 0);
+ SendMessage(label, WM_SETFONT, (WPARAM) hf, FALSE);
+ SendMessage(input, WM_SETFONT, (WPARAM) hf, FALSE);
+
+ CopyRect(&r_row, &d->r_row);
+ OffsetRect(&r_row, d->r_idspec.left, d->r_idspec.bottom);
+
+ if (size == KHUI_CTRLSIZE_SMALL) {
+ CopyRect(&r_label, &d->r_n_label);
+ CopyRect(&r_input, &d->r_n_input);
+ OffsetRect(&r_label, r_row.left, r_row.top);
+ OffsetRect(&r_input, r_row.left, r_row.top);
+ } else if (size == KHUI_CTRLSIZE_HALF) {
+ CopyRect(&r_label, &d->r_e_label);
+ CopyRect(&r_input, &d->r_e_input);
+ OffsetRect(&r_label, r_row.left, r_row.top);
+ OffsetRect(&r_input, r_row.left, r_row.top);
+ } else if (size == KHUI_CTRLSIZE_FULL) {
+ CopyRect(&r_label, &d->r_n_label);
+ r_label.right = d->r_row.right;
+ CopyRect(&r_input, &d->r_n_input);
+ OffsetRect(&r_input, r_row.left, r_row.top);
+ OffsetRect(&r_input, 0, r_input.bottom);
+ r_row.bottom += r_input.bottom;
+ OffsetRect(&r_label, r_row.left, r_row.top);
+ } else {
+ SetRectEmpty(&r_label);
+ SetRectEmpty(&r_input);
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ return;
+ }
+
+ hdefer = BeginDeferWindowPos(2);
+
+ if (label)
+ DeferWindowPos(hdefer, label,
+ ((d->hwnd_last_idspec != NULL)?
+ d->hwnd_last_idspec:
+ HWND_TOP),
+ r_label.left, r_label.top,
+ r_label.right - r_label.left,
+ r_label.bottom - r_label.top,
+ SWP_NOACTIVATE | SWP_NOOWNERZORDER);
+
+ if (input)
+ DeferWindowPos(hdefer, input,
+ (label ? label : ((d->hwnd_last_idspec != NULL)?
+ d->hwnd_last_idspec:
+ HWND_TOP)),
+ r_input.left, r_input.top,
+ r_input.right - r_input.left,
+ r_input.bottom - r_input.top,
+ SWP_NOACTIVATE | SWP_NOOWNERZORDER);
+
+ EndDeferWindowPos(hdefer);
+
+ d->hwnd_last_idspec = (input ? input : label);
+
+ d->r_idspec.bottom = r_row.bottom;
+
+ /* we don't update the layout of the main panel yet, since these
+ control additions happen before the main panel is displayed. A
+ call to nc_layout_main_panel() will be made before the main
+ panel is shown anyway. */
+
+}
+
+
+static LRESULT
+nc_handle_wm_destroy(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ khui_nc_wnd_data * d;
+
+ /* remove self from dialog chain */
+ khm_del_dialog(hwnd);
+
+ d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM);
+
+ d->nc->ident_cb(d->nc, WMNC_IDENT_EXIT, NULL, 0, 0, 0);
+
+ if (d->hwnd_notif_label)
+ DestroyWindow(d->hwnd_notif_label);
+ if (d->hwnd_notif_aux)
+ DestroyWindow(d->hwnd_notif_aux);
+
+ if(d->dlg_bb)
+ DestroyWindow(d->dlg_bb);
+ if(d->dlg_main)
+ DestroyWindow(d->dlg_main);
+
+ d->dlg_bb = NULL;
+ d->dlg_main = NULL;
+
+ PFREE(d);
+
+ return TRUE;
+}
+
+static LRESULT
+nc_handle_wm_command(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ khui_nc_wnd_data * d;
+
+ d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM);
+
+ switch(HIWORD(wParam)) {
+ case BN_CLICKED:
+ switch(LOWORD(wParam)) {
+
+ case IDOK:
+ d->nc->result = KHUI_NC_RESULT_PROCESS;
+
+ /* fallthrough */
+
+ case IDCANCEL:
+ /* the default value for d->nc->result is set to
+ KHUI_NC_RESULT_CANCEL */
+ d->nc->response = KHUI_NC_RESPONSE_PROCESSING;
+
+ nc_enable_controls(d, FALSE);
+
+ nc_notify_types(d->nc,
+ KHUI_WM_NC_NOTIFY,
+ MAKEWPARAM(0,WMNC_DIALOG_PREPROCESS),
+ (LPARAM) d->nc,
+ TRUE);
+
+ khui_cw_sync_prompt_values(d->nc);
+
+ khm_cred_dispatch_process_message(d->nc);
+
+ /* we won't know whether to abort or not until we get
+ feedback from the plugins, even if the command was
+ to cancel */
+ {
+ HWND hw;
+
+ hw = GetDlgItem(d->dlg_main, IDOK);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(d->dlg_main, IDCANCEL);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(d->dlg_main, IDC_NC_ADVANCED);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(d->dlg_bb, IDOK);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(d->dlg_bb, IDCANCEL);
+ EnableWindow(hw, FALSE);
+ }
+ return FALSE;
+
+ case IDC_NC_HELP:
+ khm_html_help(hwnd, NULL, HH_HELP_CONTEXT, IDH_ACTION_NEW_ID);
+ return FALSE;
+
+ case IDC_NC_BASIC:
+ case IDC_NC_ADVANCED:
+ /* the Options button in the main window was clicked. we
+ respond by expanding the dialog. */
+ PostMessage(hwnd, KHUI_WM_NC_NOTIFY,
+ MAKEWPARAM(0, WMNC_DIALOG_EXPAND), 0);
+ return FALSE;
+
+ case IDC_NC_CREDTEXT: /* credtext link activated */
+ {
+ khui_htwnd_link * l;
+ wchar_t sid[KHUI_MAXCCH_HTLINK_FIELD];
+ wchar_t sparam[KHUI_MAXCCH_HTLINK_FIELD];
+ wchar_t * colon;
+
+ l = (khui_htwnd_link *) lParam;
+
+ /* do we have a valid link? */
+ if(l->id == NULL || l->id_len >= ARRAYLENGTH(sid))
+ return TRUE; /* nope */
+
+ StringCchCopyN(sid, ARRAYLENGTH(sid), l->id, l->id_len);
+ sid[l->id_len] = L'\0'; /* just make sure */
+
+ if(l->param != NULL &&
+ l->param_len < ARRAYLENGTH(sparam) &&
+ l->param_len > 0) {
+
+ StringCchCopyN(sparam, ARRAYLENGTH(sparam),
+ l->param, l->param_len);
+ sparam[l->param_len] = L'\0';
+
+ } else {
+ sparam[0] = L'\0';
+ }
+
+ /* If the ID is of the form '<credtype>:<link_tag>'
+ and <credtype> is a valid name of a credentials
+ type that is participating in the credentials
+ acquisition process, then we forward the message to
+ the panel that is providing the UI for that cred
+ type. We also switch to that panel first, unless
+ the link is of the form '<credtype>:!<link_tag>'. */
+
+ colon = wcschr(sid, L':');
+ if (colon != NULL) {
+ khm_int32 credtype;
+ khui_new_creds_by_type * t;
+
+ *colon = L'\0';
+ if (KHM_SUCCEEDED(kcdb_credtype_get_id(sid, &credtype)) &&
+ KHM_SUCCEEDED(khui_cw_find_type(d->nc, credtype, &t))){
+ *colon = L':';
+
+ if (t->ordinal != d->current_panel &&
+ *(colon + 1) != L'!')
+ PostMessage(hwnd,
+ KHUI_WM_NC_NOTIFY,
+ MAKEWPARAM(t->ordinal,
+ WMNC_DIALOG_SWITCH_PANEL),
+ 0);
+
+ return SendMessage(t->hwnd_panel,
+ KHUI_WM_NC_NOTIFY,
+ MAKEWPARAM(0, WMNC_CREDTEXT_LINK),
+ lParam);
+ } else {
+ *colon = L':';
+ }
+ }
+
+ /* if it was for us, then we need to process the message */
+ if(!_wcsicmp(sid, CTLINKID_SWITCH_PANEL)) {
+ khm_int32 credtype;
+ khui_new_creds_by_type * t;
+
+ if (KHM_SUCCEEDED(kcdb_credtype_get_id(sparam,
+ &credtype)) &&
+ KHM_SUCCEEDED(khui_cw_find_type(d->nc,
+ credtype, &t))) {
+ if (t->ordinal != d->current_panel)
+ PostMessage(hwnd,
+ KHUI_WM_NC_NOTIFY,
+ MAKEWPARAM(t->ordinal,
+ WMNC_DIALOG_SWITCH_PANEL),
+ 0);
+ }
+ } else if (!_wcsicmp(sid, L"NotDef")) {
+ d->nc->set_default = FALSE;
+ nc_update_credtext(d);
+ } else if (!_wcsicmp(sid, L"MakeDef")) {
+ d->nc->set_default = TRUE;
+ nc_update_credtext(d);
+ }
+ }
+ return FALSE;
+
+#if 0
+ case NC_BN_SET_DEF_ID:
+ {
+ d->nc->set_default =
+ (IsDlgButtonChecked(d->dlg_main, NC_BN_SET_DEF_ID)
+ == BST_CHECKED);
+ }
+ return FALSE;
+#endif
+ }
+ break;
+ }
+
+ return TRUE;
+}
+
+static LRESULT nc_handle_wm_moving(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ khui_nc_wnd_data * d;
+
+ d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM);
+
+ nc_notify_types(d->nc, KHUI_WM_NC_NOTIFY,
+ MAKEWPARAM(0, WMNC_DIALOG_MOVE), (LPARAM) d->nc, TRUE);
+
+ return FALSE;
+}
+
+static LRESULT nc_handle_wm_nc_notify(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ khui_nc_wnd_data * d;
+ int id;
+
+ d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM);
+
+ switch(HIWORD(wParam)) {
+
+ case WMNC_DIALOG_SWITCH_PANEL:
+ id = LOWORD(wParam);
+ if(id >= 0 && id <= (int) d->nc->n_types) {
+ /* one of the tab buttons were pressed */
+ if(d->current_panel == id) {
+ return TRUE; /* nothing to do */
+ }
+
+ d->current_panel = id;
+
+ TabCtrl_SetCurSel(d->tab_wnd, id);
+ }
+
+ if(d->nc->mode == KHUI_NC_MODE_EXPANDED) {
+ nc_layout_new_cred_window(d);
+ return TRUE;
+ }
+ /*else*/
+ /* fallthrough */
+
+ case WMNC_DIALOG_EXPAND:
+ /* we are switching from basic to advanced or vice versa */
+
+ if (d->nc->mode == KHUI_NC_MODE_EXPANDED) {
+ d->nc->mode = KHUI_NC_MODE_MINI;
+ } else {
+ d->nc->mode = KHUI_NC_MODE_EXPANDED;
+ }
+
+ /* if we are switching to the advanced mode, we clear any
+ notifications because we now have a credential text area
+ for that. */
+ if (d->nc->mode == KHUI_NC_MODE_EXPANDED)
+ nc_notify_clear(d);
+
+ nc_layout_main_panel(d);
+
+ nc_layout_new_cred_window(d);
+
+ break;
+
+ case WMNC_DIALOG_SETUP:
+
+ if(d->nc->n_types > 0) {
+ khm_size i;
+ for(i=0; i < d->nc->n_types;i++) {
+
+ if (d->nc->types[i]->dlg_proc == NULL) {
+ d->nc->types[i]->hwnd_panel = NULL;
+ } else {
+ /* Create the dialog panel */
+ d->nc->types[i]->hwnd_panel =
+ CreateDialogParam(d->nc->types[i]->h_module,
+ d->nc->types[i]->dlg_template,
+ d->nc->hwnd,
+ d->nc->types[i]->dlg_proc,
+ (LPARAM) d->nc);
+
+#ifdef DEBUG
+ assert(d->nc->types[i]->hwnd_panel);
+#endif
+ }
+ }
+ }
+
+ break;
+
+ case WMNC_DIALOG_ACTIVATE:
+ {
+ wchar_t wname[KCDB_MAXCCH_NAME];
+ TCITEM tabitem;
+ khm_int32 t;
+
+ /* About to activate the window. We should add all the
+ panels to the tab control. */
+
+#ifdef DEBUG
+ assert(d->tab_wnd != NULL);
+#endif
+
+ ZeroMemory(&tabitem, sizeof(tabitem));
+
+ tabitem.mask = TCIF_PARAM | TCIF_TEXT;
+
+ LoadString(khm_hInstance, IDS_NC_IDENTITY,
+ wname, ARRAYLENGTH(wname));
+
+ tabitem.pszText = wname;
+ tabitem.lParam = 0; /* ordinal */
+
+ TabCtrl_InsertItem(d->tab_wnd, 0, &tabitem);
+
+ khui_cw_lock_nc(d->nc);
+
+ if(d->nc->n_types > 0) {
+ khm_size i;
+
+ /* We should sort the tabs first. See
+ nc_tab_sort_func() for sort criteria. */
+ qsort(d->nc->types,
+ d->nc->n_types,
+ sizeof(*(d->nc->types)),
+ nc_tab_sort_func);
+
+ for(i=0; i < d->nc->n_types;i++) {
+
+ d->nc->types[i]->ordinal = i + 1;
+
+ if(d->nc->types[i]->name)
+ tabitem.pszText = d->nc->types[i]->name;
+ else {
+ khm_size cbsize;
+
+ cbsize = sizeof(wname);
+
+ if(KHM_FAILED
+ (kcdb_credtype_describe
+ (d->nc->types[i]->type,
+ wname,
+ &cbsize,
+ KCDB_TS_SHORT))) {
+
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ wname[0] = L'\0';
+
+ }
+
+ tabitem.pszText = wname;
+
+ }
+
+ tabitem.lParam = d->nc->types[i]->ordinal;
+
+ TabCtrl_InsertItem(d->tab_wnd, d->nc->types[i]->ordinal,
+ &tabitem);
+ }
+ }
+
+ khui_cw_unlock_nc(d->nc);
+
+ nc_update_credtext(d);
+
+ TabCtrl_SetCurSel(d->tab_wnd, 0); /* the first selected
+ tab is the main
+ panel. */
+
+ /* bring the window to the top, if necessary */
+ if (KHM_SUCCEEDED(khc_read_int32(NULL,
+ L"CredWindow\\Windows\\NewCred\\ForceToTop",
+ &t)) &&
+
+ t != 0) {
+ /* it used to be that the above condition also called
+ !khm_is_dialog_active() to find out whether there
+ was a dialog active. If there was, we wouldn't try
+ to bring the new cred window to the foreground. But
+ that was not the behavior we want. */
+
+ /* if the main window is not visible, then the SetWindowPos()
+ call is sufficient to bring the new creds window to the
+ top. However, if the main window is visible but not
+ active, the main window needs to be activated before a
+ child window can be activated. */
+ khm_activate_main_window();
+
+ SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0,
+ (SWP_NOMOVE | SWP_NOSIZE));
+ }
+
+ ShowWindow(hwnd, SW_SHOWNOACTIVATE);
+
+ /* we don't enable animations until a specific timeout
+ elapses after showing the window. We don't need to
+ animate any size changes if the user has barely had a
+ chance to notice the original size. This prevents the
+ new cred window from appearing in an animated state. */
+ SetTimer(hwnd, NC_TIMER_ENABLEANIMATE, ENABLEANIMATE_TIMEOUT, NULL);
+
+ SetFocus(hwnd);
+
+ if (d->nc->n_identities == 0)
+ break;
+ /* else */
+ /* fallthrough */
+ }
+
+ case WMNC_IDENTITY_CHANGE:
+ {
+ BOOL okEnable = FALSE;
+
+ nc_notify_types(d->nc, KHUI_WM_NC_NOTIFY,
+ MAKEWPARAM(0, WMNC_IDENTITY_CHANGE), (LPARAM) d->nc,
+ TRUE);
+
+ if (d->nc->subtype == KMSG_CRED_NEW_CREDS &&
+ d->nc->n_identities > 0 &&
+ d->nc->identities[0]) {
+ khm_int32 f = 0;
+
+ kcdb_identity_get_flags(d->nc->identities[0], &f);
+
+ if (!(f & KCDB_IDENT_FLAG_DEFAULT)) {
+ d->nc->set_default = FALSE;
+ }
+ }
+
+ nc_update_credtext(d);
+
+ }
+ break;
+
+ case WMNC_TYPE_STATE:
+ /* fallthrough */
+ case WMNC_UPDATE_CREDTEXT:
+ nc_update_credtext(d);
+ break;
+
+ case WMNC_CLEAR_PROMPTS:
+ {
+ khm_size i;
+
+ khui_cw_lock_nc(d->nc);
+
+ if(d->hwnd_banner != NULL) {
+ DestroyWindow(d->hwnd_banner);
+ d->hwnd_banner = NULL;
+ }
+
+ if(d->hwnd_name != NULL) {
+ DestroyWindow(d->hwnd_name);
+ d->hwnd_name = NULL;
+ }
+
+ for(i=0;i<d->nc->n_prompts;i++) {
+ if(!(d->nc->prompts[i]->flags &
+ KHUI_NCPROMPT_FLAG_STOCK)) {
+ if(d->nc->prompts[i]->hwnd_static != NULL)
+ DestroyWindow(d->nc->prompts[i]->hwnd_static);
+
+ if(d->nc->prompts[i]->hwnd_edit != NULL)
+ DestroyWindow(d->nc->prompts[i]->hwnd_edit);
+ }
+
+ d->nc->prompts[i]->hwnd_static = NULL;
+ d->nc->prompts[i]->hwnd_edit = NULL;
+ }
+
+ khui_cw_unlock_nc(d->nc);
+
+ SetRectEmpty(&d->r_custprompt);
+
+ nc_layout_main_panel(d);
+
+ nc_layout_new_cred_window(d);
+ }
+ break;
+
+ case WMNC_SET_PROMPTS:
+ {
+ khm_size i;
+ int y;
+ HWND hw, hw_prev;
+ HFONT hf, hfold;
+ HDC hdc;
+ BOOL use_large_lables = FALSE;
+
+ /* we assume that WMNC_CLEAR_PROMPTS has already been
+ received */
+
+#ifdef DEBUG
+ assert(IsRectEmpty(&d->r_custprompt));
+#endif
+
+ khui_cw_lock_nc(d->nc);
+
+#if 0
+ /* special case, we have one prompt and it is a password
+ prompt. very common */
+ if(d->nc->n_prompts == 1 &&
+ d->nc->prompts[0]->type == KHUI_NCPROMPT_TYPE_PASSWORD) {
+
+ hw = GetDlgItem(d->dlg_main, IDC_NC_PASSWORD);
+ EnableWindow(hw, TRUE);
+
+ d->nc->prompts[0]->flags |= KHUI_NCPROMPT_FLAG_STOCK;
+ d->nc->prompts[0]->hwnd_edit = hw;
+ d->nc->prompts[0]->hwnd_static = NULL; /* don't care */
+
+ khui_cw_unlock_nc(d->nc);
+ break;
+ }
+#endif
+ /* for everything else */
+
+ y = d->r_idspec.bottom;
+
+ d->r_custprompt.left = d->r_area.left;
+ d->r_custprompt.right = d->r_area.right;
+ d->r_custprompt.top = y;
+
+ hf = (HFONT) SendMessage(d->dlg_main, WM_GETFONT, 0, 0);
+
+ if (d->nc->pname != NULL) {
+ hw =
+ CreateWindowEx
+ (0,
+ L"STATIC",
+ d->nc->pname,
+ SS_SUNKEN | WS_CHILD,
+ d->r_area.left, y,
+ d->r_row.right,
+ d->r_n_label.bottom - d->r_n_label.top,
+ d->dlg_main,
+ NULL,
+ khm_hInstance,
+ NULL);
+
+#ifdef DEBUG
+ assert(hw);
+#endif
+ d->hwnd_name = hw;
+ SendMessage(hw, WM_SETFONT, (WPARAM)hf, (LPARAM) TRUE);
+ ShowWindow(hw, SW_SHOW);
+
+ y += d->r_n_label.bottom - d->r_n_label.top;
+ }
+
+ if (d->nc->banner != NULL) {
+ hw =
+ CreateWindowEx
+ (0,
+ L"STATIC",
+ d->nc->banner,
+ WS_CHILD,
+ d->r_area.left, y,
+ d->r_row.right, d->r_row.bottom,
+ d->dlg_main,
+ NULL,
+ khm_hInstance,
+ NULL);
+#ifdef DEBUG
+ assert(hw);
+#endif
+ d->hwnd_banner = hw;
+ SendMessage(hw, WM_SETFONT, (WPARAM)hf, (LPARAM)TRUE);
+ ShowWindow(hw, SW_SHOW);
+ y += d->r_row.bottom;
+ }
+
+ hw_prev = d->hwnd_last_idspec;
+
+ hdc = GetWindowDC(d->dlg_main);
+ hfold = SelectObject(hdc,hf);
+
+ /* first do a trial run and see if we should use the
+ larger text labels or not. This is so that all the
+ labels and input controls align properly. */
+ for (i=0; i < d->nc->n_prompts; i++) {
+ if (d->nc->prompts[i]->prompt != NULL) {
+ SIZE s;
+
+ GetTextExtentPoint32(hdc,
+ d->nc->prompts[i]->prompt,
+ (int) wcslen(d->nc->prompts[i]->prompt),
+ &s);
+
+ if(s.cx >= d->r_n_label.right - d->r_n_label.left) {
+ use_large_lables = TRUE;
+ break;
+ }
+ }
+ }
+
+ for(i=0; i<d->nc->n_prompts; i++) {
+ RECT pr, er;
+ SIZE s;
+ int dy;
+
+ if(d->nc->prompts[i]->prompt != NULL) {
+ GetTextExtentPoint32(hdc,
+ d->nc->prompts[i]->prompt,
+ (int) wcslen(d->nc->prompts[i]->prompt),
+ &s);
+ if(s.cx < d->r_n_label.right - d->r_n_label.left &&
+ !use_large_lables) {
+ CopyRect(&pr, &d->r_n_label);
+ CopyRect(&er, &d->r_n_input);
+ dy = d->r_row.bottom;
+ } else if(s.cx <
+ d->r_e_label.right - d->r_e_label.left) {
+ CopyRect(&pr, &d->r_e_label);
+ CopyRect(&er, &d->r_e_input);
+ dy = d->r_row.bottom;
+ } else {
+ /* oops. the prompt doesn't fit in our
+ controls. we need to use up two lines */
+ pr.left = 0;
+ pr.right = d->r_row.right;
+ pr.top = 0;
+ pr.bottom = d->r_n_label.bottom -
+ d->r_n_label.top;
+ CopyRect(&er, &d->r_n_input);
+ OffsetRect(&er, 0, pr.bottom);
+ dy = er.bottom + (d->r_row.bottom -
+ d->r_n_input.bottom);
+ }
+ } else {
+ SetRectEmpty(&pr);
+ CopyRect(&er, &d->r_n_input);
+ dy = d->r_row.bottom;
+ }
+
+ if(IsRectEmpty(&pr)) {
+ d->nc->prompts[i]->hwnd_static = NULL;
+ } else {
+ OffsetRect(&pr, d->r_area.left, y);
+
+ hw = CreateWindowEx
+ (0,
+ L"STATIC",
+ d->nc->prompts[i]->prompt,
+ WS_CHILD,
+ pr.left, pr.top,
+ pr.right - pr.left, pr.bottom - pr.top,
+ d->dlg_main,
+ NULL,
+ khm_hInstance,
+ NULL);
+#ifdef DEBUG
+ assert(hw);
+#endif
+
+ SendMessage(hw, WM_SETFONT,
+ (WPARAM) hf, (LPARAM) TRUE);
+
+ SetWindowPos(hw, hw_prev,
+ 0, 0, 0, 0,
+ SWP_NOACTIVATE | SWP_NOMOVE |
+ SWP_NOOWNERZORDER | SWP_NOSIZE |
+ SWP_SHOWWINDOW);
+
+ d->nc->prompts[i]->hwnd_static = hw;
+ hw_prev = hw;
+ }
+
+ OffsetRect(&er, d->r_area.left, y);
+
+ hw = CreateWindowEx
+ (0,
+ L"EDIT",
+ (d->nc->prompts[i]->def ?
+ d->nc->prompts[i]->def : L""),
+ WS_CHILD | WS_TABSTOP |
+ WS_BORDER |
+ ((d->nc->prompts[i]->flags &
+ KHUI_NCPROMPT_FLAG_HIDDEN)? ES_PASSWORD:0),
+ er.left, er.top,
+ er.right - er.left, er.bottom - er.top,
+ d->dlg_main,
+ NULL,
+ khm_hInstance,
+ NULL);
+
+#ifdef DEBUG
+ assert(hw);
+#endif
+
+ SendMessage(hw, WM_SETFONT,
+ (WPARAM) hf, (LPARAM) TRUE);
+
+ SetWindowPos(hw, hw_prev,
+ 0, 0, 0, 0,
+ SWP_NOACTIVATE | SWP_NOMOVE |
+ SWP_NOOWNERZORDER | SWP_NOSIZE |
+ SWP_SHOWWINDOW);
+
+ SendMessage(hw, EM_SETLIMITTEXT,
+ KHUI_MAXCCH_PROMPT_VALUE -1,
+ 0);
+
+ d->nc->prompts[i]->hwnd_edit = hw;
+
+ hw_prev = hw;
+
+ y += dy;
+ }
+
+ if (d->nc->n_prompts > 0 &&
+ d->nc->prompts[0]->hwnd_edit) {
+
+ PostMessage(d->dlg_main, WM_NEXTDLGCTL,
+ (WPARAM) d->nc->prompts[0]->hwnd_edit,
+ MAKELPARAM(TRUE, 0));
+
+ }
+
+ SelectObject(hdc, hfold);
+ ReleaseDC(d->dlg_main, hdc);
+
+ khui_cw_unlock_nc(d->nc);
+
+ d->r_custprompt.bottom = y;
+
+ if (d->r_custprompt.bottom == d->r_custprompt.top)
+ SetRectEmpty(&d->r_custprompt);
+
+ nc_layout_main_panel(d);
+
+ nc_layout_new_cred_window(d);
+ }
+ break;
+
+ case WMNC_DIALOG_PROCESS_COMPLETE:
+ {
+ khui_new_creds * nc;
+
+ nc = d->nc;
+
+ nc->response &= ~KHUI_NC_RESPONSE_PROCESSING;
+
+ if(nc->response & KHUI_NC_RESPONSE_NOEXIT) {
+ HWND hw;
+
+ nc_enable_controls(d, TRUE);
+
+ /* reset state */
+ nc->result = KHUI_NC_RESULT_CANCEL;
+
+ hw = GetDlgItem(d->dlg_main, IDOK);
+ EnableWindow(hw, TRUE);
+ hw = GetDlgItem(d->dlg_main, IDCANCEL);
+ EnableWindow(hw, TRUE);
+ hw = GetDlgItem(d->dlg_main, IDC_NC_ADVANCED);
+ EnableWindow(hw, TRUE);
+ hw = GetDlgItem(d->dlg_bb, IDOK);
+ EnableWindow(hw, TRUE);
+ hw = GetDlgItem(d->dlg_bb, IDCANCEL);
+ EnableWindow(hw, TRUE);
+
+ nc_clear_password_fields(d);
+
+ return TRUE;
+ }
+
+ DestroyWindow(hwnd);
+
+ kmq_post_message(KMSG_CRED, KMSG_CRED_END, 0, (void *) nc);
+ }
+ break;
+
+ /* MUST be called with SendMessage */
+ case WMNC_ADD_CONTROL_ROW:
+ {
+ khui_control_row * row;
+
+ row = (khui_control_row *) lParam;
+
+#ifdef DEBUG
+ assert(row->label);
+ assert(row->input);
+#endif
+
+ nc_add_control_row(d, row->label, row->input, row->size);
+ }
+ break;
+
+ case WMNC_UPDATE_LAYOUT:
+ {
+
+ RECT r_client;
+ khm_int32 animate;
+ khm_int32 steps;
+ khm_int32 timeout;
+
+ /* We are already adjusting the size of the window. The
+ next time the timer fires, it will notice if the target
+ size has changed. */
+ if (d->size_changing)
+ return TRUE;
+
+ GetClientRect(hwnd, &r_client);
+
+ if ((r_client.right - r_client.left ==
+ d->r_required.right - d->r_required.left) &&
+ (r_client.bottom - r_client.top ==
+ d->r_required.bottom - d->r_required.top)) {
+
+ /* the window is already at the right size */
+ return TRUE;
+
+ }
+
+ if (!IsWindowVisible(hwnd)) {
+ /* The window is not visible yet. There's no need to
+ animate anything. */
+
+ animate = FALSE;
+
+ } else if (KHM_FAILED(khc_read_int32(NULL,
+ L"CredWindow\\Windows\\NewCred\\AnimateSizeChanges",
+ &animate))) {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ animate = TRUE;
+ }
+
+ /* if we aren't animating the window resize, then we just
+ do it in one call. */
+ if (!animate || !d->animation_enabled) {
+ RECT r_window;
+
+ CopyRect(&r_window, &d->r_required);
+ AdjustWindowRectEx(&r_window, NC_WINDOW_STYLES, FALSE,
+ NC_WINDOW_EX_STYLES);
+
+ SetWindowPos(hwnd, NULL, 0, 0,
+ r_window.right - r_window.left,
+ r_window.bottom - r_window.top,
+ SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER |
+ SWP_NOZORDER);
+
+ return TRUE;
+ }
+
+ if (KHM_FAILED(khc_read_int32(NULL,
+ L"CredWindow\\Windows\\NewCred\\AnimationSteps",
+ &steps))) {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ steps = NC_SZ_STEPS_DEF;
+ } else {
+
+ if (steps < NC_SZ_STEPS_MIN)
+ steps = NC_SZ_STEPS_MIN;
+ else if (steps > NC_SZ_STEPS_MAX)
+ steps = NC_SZ_STEPS_MAX;
+
+ }
+
+ if (KHM_FAILED(khc_read_int32(NULL,
+ L"CredWindow\\Windows\\NewCred\\AnimationStepTimeout",
+ &timeout))) {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ timeout = NC_SZ_TIMEOUT_DEF;
+ } else {
+
+ if (timeout < NC_SZ_TIMEOUT_MIN)
+ timeout = NC_SZ_TIMEOUT_MIN;
+ else if (timeout > NC_SZ_TIMEOUT_MAX)
+ timeout = NC_SZ_TIMEOUT_MAX;
+
+ }
+
+ CopyRect(&d->sz_ch_source, &r_client);
+ OffsetRect(&d->sz_ch_source, -d->sz_ch_source.left, -d->sz_ch_source.top);
+ CopyRect(&d->sz_ch_target, &d->r_required);
+ OffsetRect(&d->sz_ch_target, -d->sz_ch_target.left, -d->sz_ch_target.top);
+ d->sz_ch_increment = 0;
+ d->sz_ch_max = steps;
+ d->sz_ch_timeout = timeout;
+ d->size_changing = TRUE;
+
+ SetTimer(hwnd, NC_TIMER_SIZER, timeout, NULL);
+ }
+ break;
+ } /* switch(HIWORD(wParam)) */
+
+ return TRUE;
+}
+
+static LRESULT nc_handle_wm_timer(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam) {
+ khui_nc_wnd_data * d;
+
+ d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM);
+
+ if (wParam == NC_TIMER_SIZER) {
+
+ RECT r_now;
+
+ /* are we done with this sizing operation? */
+ if (!d->size_changing ||
+ d->sz_ch_increment >= d->sz_ch_max) {
+
+ d->size_changing = FALSE;
+ KillTimer(hwnd, NC_TIMER_SIZER);
+ return 0;
+ }
+
+ /* have the requirements changed while we were processing the
+ sizing operation? */
+ if ((d->r_required.right - d->r_required.left !=
+ d->sz_ch_target.right)
+
+ ||
+
+ (d->r_required.bottom - d->r_required.top !=
+ d->sz_ch_target.bottom)) {
+
+ /* the target size has changed. we need to restart the
+ sizing operation. */
+
+ RECT r_client;
+
+ GetClientRect(hwnd, &r_client);
+
+ CopyRect(&d->sz_ch_source, &r_client);
+ OffsetRect(&d->sz_ch_source, -d->sz_ch_source.left, -d->sz_ch_source.top);
+ CopyRect(&d->sz_ch_target, &d->r_required);
+ OffsetRect(&d->sz_ch_target, -d->sz_ch_target.left, -d->sz_ch_target.top);
+ d->sz_ch_increment = 0;
+
+ /* leave the other fields alone */
+
+#ifdef DEBUG
+ assert(d->sz_ch_max >= NC_SZ_STEPS_MIN);
+ assert(d->sz_ch_max <= NC_SZ_STEPS_MAX);
+ assert(d->sz_ch_timeout >= NC_SZ_TIMEOUT_MIN);
+ assert(d->sz_ch_timeout <= NC_SZ_TIMEOUT_MAX);
+ assert(d->size_changing);
+#endif
+ }
+
+ /* we are going to do the next increment */
+ d->sz_ch_increment ++;
+
+ /* now, figure out the size of the client area for this
+ step */
+
+ r_now.left = 0;
+ r_now.top = 0;
+
+#define PROPORTION(v1, v2, i, s) (((v1) * ((s) - (i)) + (v2) * (i)) / (s))
+
+ r_now.right = PROPORTION(d->sz_ch_source.right, d->sz_ch_target.right,
+ d->sz_ch_increment, d->sz_ch_max);
+
+ r_now.bottom = PROPORTION(d->sz_ch_source.bottom, d->sz_ch_target.bottom,
+ d->sz_ch_increment, d->sz_ch_max);
+
+#undef PROPORTION
+
+#ifdef DEBUG
+ {
+ long dx = (r_now.right - d->sz_ch_target.right) *
+ (d->sz_ch_source.right - d->sz_ch_target.right);
+
+ long dy = (r_now.bottom - d->sz_ch_target.bottom) *
+ (d->sz_ch_source.bottom - d->sz_ch_target.bottom);
+
+ if (dx < 0 || dy < 0) {
+ KillTimer(hwnd, NC_TIMER_SIZER);
+ assert(dx >= 0);
+ assert(dy >= 0);
+ SetTimer(hwnd, NC_TIMER_SIZER, d->sz_ch_timeout, NULL);
+ }
+ }
+#endif
+
+ AdjustWindowRectEx(&r_now, NC_WINDOW_STYLES, FALSE,
+ NC_WINDOW_EX_STYLES);
+
+ SetWindowPos(hwnd, NULL,
+ 0, 0,
+ r_now.right - r_now.left,
+ r_now.bottom - r_now.top,
+ SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER |
+ SWP_NOZORDER);
+
+ /* and now we wait for the next timer message */
+
+ return 0;
+ } else if (wParam == NC_TIMER_ENABLEANIMATE) {
+
+ d->animation_enabled = TRUE;
+ KillTimer(hwnd, NC_TIMER_ENABLEANIMATE);
+ }
+
+ return 0;
+}
+
+static LRESULT nc_handle_wm_notify(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam) {
+
+ LPNMHDR nmhdr;
+ khui_nc_wnd_data * d;
+
+ d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM);
+ nmhdr = (LPNMHDR) lParam;
+
+ if (nmhdr->code == TCN_SELCHANGE) {
+ /* the current tab has changed. */
+ int idx;
+ TCITEM tcitem;
+
+ idx = TabCtrl_GetCurSel(d->tab_wnd);
+ ZeroMemory(&tcitem, sizeof(tcitem));
+
+ tcitem.mask = TCIF_PARAM;
+ TabCtrl_GetItem(d->tab_wnd, idx, &tcitem);
+
+ d->current_panel = (int) tcitem.lParam;
+
+ nc_layout_new_cred_window(d);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static LRESULT nc_handle_wm_help(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam) {
+ static DWORD ctxids[] = {
+ NC_TS_CTRL_ID_MIN, IDH_NC_TABMAIN,
+ NC_TS_CTRL_ID_MIN + 1, IDH_NC_TABBUTTON,
+ NC_TS_CTRL_ID_MIN + 2, IDH_NC_TABBUTTON,
+ NC_TS_CTRL_ID_MIN + 3, IDH_NC_TABBUTTON,
+ NC_TS_CTRL_ID_MIN + 4, IDH_NC_TABBUTTON,
+ NC_TS_CTRL_ID_MIN + 5, IDH_NC_TABBUTTON,
+ NC_TS_CTRL_ID_MIN + 6, IDH_NC_TABBUTTON,
+ NC_TS_CTRL_ID_MIN + 7, IDH_NC_TABBUTTON,
+ IDOK, IDH_NC_OK,
+ IDCANCEL, IDH_NC_CANCEL,
+ IDC_NC_HELP, IDH_NC_HELP,
+ IDC_NC_ADVANCED, IDH_NC_ADVANCED,
+ IDC_NC_CREDTEXT, IDH_NC_CREDWND,
+ 0
+ };
+
+ HELPINFO * hlp;
+ HWND hw = NULL;
+ HWND hw_ctrl;
+ khui_nc_wnd_data * d;
+
+ d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM);
+
+ hlp = (HELPINFO *) lParam;
+
+ if (d->nc->subtype != KMSG_CRED_NEW_CREDS &&
+ d->nc->subtype != KMSG_CRED_PASSWORD)
+ return TRUE;
+
+ if (hlp->iContextType != HELPINFO_WINDOW)
+ return TRUE;
+
+ if (hlp->hItemHandle != NULL &&
+ hlp->hItemHandle != hwnd) {
+ DWORD id;
+ int i;
+
+ hw_ctrl =hlp->hItemHandle;
+
+ id = GetWindowLong(hw_ctrl, GWL_ID);
+ for (i=0; ctxids[i] != 0; i += 2)
+ if (ctxids[i] == id)
+ break;
+
+ if (ctxids[i] != 0)
+ hw = khm_html_help(hw_ctrl,
+ ((d->nc->subtype == KMSG_CRED_NEW_CREDS)?
+ L"::popups_newcreds.txt":
+ L"::popups_password.txt"),
+ HH_TP_HELP_WM_HELP,
+ (DWORD_PTR) ctxids);
+ }
+
+ if (hw == NULL) {
+ khm_html_help(hwnd, NULL, HH_HELP_CONTEXT,
+ ((d->nc->subtype == KMSG_CRED_NEW_CREDS)?
+ IDH_ACTION_NEW_ID: IDH_ACTION_PASSWD_ID));
+ }
+
+ return TRUE;
+}
+
+static LRESULT CALLBACK nc_window_proc(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ switch(uMsg) {
+ case WM_CREATE:
+ return nc_handle_wm_create(hwnd, uMsg, wParam, lParam);
+
+ case WM_DESTROY:
+ return nc_handle_wm_destroy(hwnd, uMsg, wParam, lParam);
+
+ case WM_COMMAND:
+ return nc_handle_wm_command(hwnd, uMsg, wParam, lParam);
+
+ case WM_NOTIFY:
+ return nc_handle_wm_notify(hwnd, uMsg, wParam, lParam);
+
+ case WM_MOVE:
+ case WM_MOVING:
+ return nc_handle_wm_moving(hwnd, uMsg, wParam, lParam);
+
+ case WM_TIMER:
+ return nc_handle_wm_timer(hwnd, uMsg, wParam, lParam);
+
+ case WM_HELP:
+ return nc_handle_wm_help(hwnd, uMsg, wParam, lParam);
+
+ case KHUI_WM_NC_NOTIFY:
+ return nc_handle_wm_nc_notify(hwnd, uMsg, wParam, lParam);
+ }
+
+ /* Note that this is technically a dialog box */
+ return DefDlgProc(hwnd, uMsg, wParam, lParam);
+}
+
+void khm_register_newcredwnd_class(void)
+{
+ WNDCLASSEX wcx;
+
+ wcx.cbSize = sizeof(wcx);
+ wcx.style = CS_DBLCLKS | CS_OWNDC;
+ wcx.lpfnWndProc = nc_window_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((HINSTANCE) NULL, IDC_ARROW);
+ wcx.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1);
+ wcx.lpszMenuName = NULL;
+ wcx.lpszClassName = KHUI_NEWCREDWND_CLASS;
+ wcx.hIconSm = NULL;
+
+ khui_newcredwnd_cls = RegisterClassEx(&wcx);
+}
+
+void khm_unregister_newcredwnd_class(void)
+{
+ UnregisterClass((LPWSTR) khui_newcredwnd_cls, khm_hInstance);
+}
+
+HWND khm_create_newcredwnd(HWND parent, khui_new_creds * c)
+{
+ wchar_t wtitle[256];
+ HWND hwnd;
+
+ if (c->window_title == NULL) {
+ if (c->subtype == KMSG_CRED_PASSWORD)
+ LoadString(khm_hInstance,
+ IDS_WT_PASSWORD,
+ wtitle,
+ ARRAYLENGTH(wtitle));
+ else
+ LoadString(khm_hInstance,
+ IDS_WT_NEW_CREDS,
+ wtitle,
+ ARRAYLENGTH(wtitle));
+ }
+
+ hwnd = CreateWindowEx(NC_WINDOW_EX_STYLES,
+ MAKEINTATOM(khui_newcredwnd_cls),
+ ((c->window_title)?c->window_title: wtitle),
+ NC_WINDOW_STYLES,
+ 0,0,400,400, /* bogus values. the window
+ is going to resize and
+ reposition itself
+ anyway */
+ parent,
+ NULL,
+ khm_hInstance,
+ (LPVOID) c);
+
+#ifdef DEBUG
+ assert(hwnd != NULL);
+#endif
+
+ /* note that the window is not visible yet. That's because, at
+ this point we don't know what the panels are */
+
+ return hwnd;
+}
+
+void khm_prep_newcredwnd(HWND hwnd)
+{
+ SendMessage(hwnd, KHUI_WM_NC_NOTIFY,
+ MAKEWPARAM(0, WMNC_DIALOG_SETUP), 0);
+}
+
+void khm_show_newcredwnd(HWND hwnd)
+{
+ /* add all the panels in and prep UI */
+ PostMessage(hwnd, KHUI_WM_NC_NOTIFY,
+ MAKEWPARAM(0, WMNC_DIALOG_ACTIVATE), 0);
+}
diff --git a/src/windows/identity/ui/newcredwnd.h b/src/windows/identity/ui/newcredwnd.h
index 7813e1c..22819a6 100644
--- a/src/windows/identity/ui/newcredwnd.h
+++ b/src/windows/identity/ui/newcredwnd.h
@@ -1,103 +1,189 @@
-/*
- * Copyright (c) 2005 Massachusetts Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF 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_NEWCREDWND_H
-#define __KHIMAIRA_NEWCREDWND_H
-
-#include<khuidefs.h>
-
-#define KHUI_NEWCREDWND_CLASS L"KhmNewCredWnd"
-
-typedef struct khui_nc_wnd_data_t {
- khui_new_creds * nc;
-
- HWND dlg_main; /* main dialog */
- RECT r_main;
- HWND dlg_bb; /* button bar */
- RECT r_bb;
- HWND dlg_ts; /* tab strip */
- RECT r_ts;
-
- khm_size ctab; /* current tab */
-
- HWND hwnd_tc_main; /* tab control button for main dialog */
-
- HWND hwnd_banner; /* static control for banner */
- HWND hwnd_name; /* static control for name */
-
- HWND hwnd_last_idspec; /* last identity specifier control */
-
- /* metrics for custom prompts and identity specifiers */
-
- RECT r_idspec; /* Area used by identity specifiers
- (relative to client) */
- RECT r_row; /* Metrics for a control row
- (top=0,left=0,right=width,
- bottom=height) */
- RECT r_area; /* Area available for controls (relative
- to client) */
- RECT r_n_label; /* coords of the static control (relative
- to row) */
- RECT r_n_input; /* coords of the edit control (relative to
- row) */
- RECT r_e_label; /* coords of the extended edit control
- (relative to row) */
- RECT r_e_input; /* coords of the extended edit control
- (relative to row) */
- RECT r_credtext; /* Area for credtext window (relative to
- row) */
-} khui_nc_wnd_data;
-
-void khm_register_newcredwnd_class(void);
-void khm_unregister_newcredwnd_class(void);
-HWND khm_create_newcredwnd(HWND parent, khui_new_creds * c);
-void khm_prep_newcredwnd(HWND hwnd);
-void khm_show_newcredwnd(HWND hwnd);
-
-/* This is the first control ID that is created in the custom tabstrip
- control buttons. Subsequent buttons get consecutive IDs starting
- from this one. */
-#define NC_TS_CTRL_ID_MIN 8001
-
-/* Maximum number of controls */
-#define NC_TS_MAX_CTRLS 8
-
-/* Maximum control ID */
-#define NC_TS_CTRL_ID_MAX (NC_TS_CTRL_ID_MIN + NC_TS_MAX_CTRLS - 1)
-
-#define NC_BN_SET_DEF_ID 8012
-
-/* the first control ID that may be used by an identity provider */
-#define NC_IS_CTRL_ID_MIN 8016
-
-/* the maximum number of controls that may be created by an identity
- provider*/
-#define NC_IS_CTRL_MAX_CTRLS 8
-
-/* the maximum control ID that may be used by an identity provider */
-#define NC_IS_CTRL_ID_MAX (NC_IS_CTRL_ID_MIN + NC_IS_MAX_CTRLS - 1)
-
-#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_NEWCREDWND_H
+#define __KHIMAIRA_NEWCREDWND_H
+
+#include<khuidefs.h>
+
+#define KHUI_NEWCREDWND_CLASS L"KhmNewCredWnd"
+
+typedef enum tag_nc_notification_types {
+ NC_NOTIFY_NONE = 0, /* no notification */
+ NC_NOTIFY_MARQUEE, /* marquee type notification */
+ NC_NOTIFY_PROGRESS, /* progress notification */
+ NC_NOTIFY_MESSAGE, /* a message */
+} nc_notification_type;
+
+typedef struct khui_nc_wnd_data_t {
+ khui_new_creds * nc;
+
+ /* The tab control */
+
+ HWND tab_wnd; /* tab control */
+ int current_panel; /* ordinal of the current panel being
+ displayed. */
+
+ /* The main panel */
+ HWND dlg_main; /* main dialog */
+ RECT r_main; /* the extent of the main panel that
+ we have used so far. The rect
+ includes the size of the area used
+ by the identity selector controls,
+ the custom controls added by
+ credentials providers and the
+ buttons that may be required when
+ in the mini mode. */
+ RECT r_required; /* required size of the main window */
+
+ /* The button bar */
+
+ HWND dlg_bb; /* button bar */
+
+ /* Sizing the new credentials window */
+
+ BOOL animation_enabled; /* Flag indicating whether animation
+ is enabled for the dialg. If this
+ flag is off, we don't animate size
+ changes even if the configuration
+ says so. */
+ BOOL size_changing; /* flag indicating that the size of
+ the main window is being
+ adjusted. */
+ RECT sz_ch_source; /* Source size, from which we are
+ going towards target size in
+ sz_ch_max steps. The RECT is self
+ relative (i.e. left=0 and top=0)*/
+ RECT sz_ch_target; /* If we are doing an incremental size
+ change, this holds the target size
+ that we were going for. Note that
+ the target size might change while
+ we are adjusting the size. So this
+ helps keep track of whether we need
+ to start the size change again. The
+ RECT is self relative (i.e. left=0
+ and top=0). */
+ int sz_ch_increment; /* Current step of the incremental
+ size change operation. */
+ int sz_ch_max; /* Max number of steps in the size
+ change operation. */
+ int sz_ch_timeout; /* Milliseconds between each increment */
+
+ /* Custom controls and identity specifiers */
+
+ HWND hwnd_banner; /* static control for banner */
+ HWND hwnd_name; /* static control for name */
+
+ HWND hwnd_last_idspec; /* last identity specifier control */
+
+ /* Notification windows */
+
+ nc_notification_type notif_type; /* Type of notification */
+ HWND hwnd_notif_label; /* Label for notifications */
+ HWND hwnd_notif_aux; /* Other control for notifications */
+
+ /* Areas of the main panel */
+
+ RECT r_idspec; /* Area used by identity specifiers
+ (relative to client) */
+ RECT r_custprompt; /* Area used by custom controls (relative
+ to client) */
+ RECT r_notif; /* Area used for notifications. */
+
+ /* Metrics for custom prompts and identity specifiers */
+
+ RECT r_row; /* Metrics for a control row (left=0,
+ top=0, right=width, bottom=height) */
+ RECT r_area; /* Area available for controls (relative
+ to client) */
+ RECT r_n_label; /* coords of the static control (relative
+ to row) */
+ RECT r_n_input; /* coords of the edit control (relative to
+ row) */
+ RECT r_e_label; /* coords of the extended edit control
+ (relative to row) */
+ RECT r_e_input; /* coords of the extended edit control
+ (relative to row) */
+ RECT r_credtext; /* Area for credtext window (relative to
+ row) */
+} khui_nc_wnd_data;
+
+void khm_register_newcredwnd_class(void);
+void khm_unregister_newcredwnd_class(void);
+HWND khm_create_newcredwnd(HWND parent, khui_new_creds * c);
+void khm_prep_newcredwnd(HWND hwnd);
+void khm_show_newcredwnd(HWND hwnd);
+
+/* Width of the button bar in dialog units */
+#define NCDLG_BBAR_WIDTH 66
+/* Height of the button bar in dialog units */
+#define NCDLG_BBAR_HEIGHT 190
+
+/* Control identifier for the tab control in the new credentials
+ dialog. We declare this here since we will be creating the control
+ manually. */
+#define IDC_NC_TABS 8001
+
+/* This is the first control ID that is created in the custom tabstrip
+ control buttons. Subsequent buttons get consecutive IDs starting
+ from this one. */
+#define NC_TS_CTRL_ID_MIN 8002
+
+/* Maximum number of controls */
+#define NC_TS_MAX_CTRLS 8
+
+/* Maximum control ID */
+#define NC_TS_CTRL_ID_MAX (NC_TS_CTRL_ID_MIN + NC_TS_MAX_CTRLS - 1)
+
+#define NC_BN_SET_DEF_ID 8012
+
+/* the first control ID that may be used by an identity provider */
+#define NC_IS_CTRL_ID_MIN 8016
+
+/* the maximum number of controls that may be created by an identity
+ provider*/
+#define NC_IS_CTRL_MAX_CTRLS 8
+
+/* the maximum control ID that may be used by an identity provider */
+#define NC_IS_CTRL_ID_MAX (NC_IS_CTRL_ID_MIN + NC_IS_MAX_CTRLS - 1)
+
+#define NC_WINDOW_EX_STYLES (WS_EX_DLGMODALFRAME | WS_EX_CONTEXTHELP | WS_EX_APPWINDOW)
+#define NC_WINDOW_STYLES (WS_DLGFRAME | WS_POPUPWINDOW | WS_CLIPCHILDREN)
+
+#define NC_SZ_STEPS_MIN 3
+#define NC_SZ_STEPS_DEF 10
+#define NC_SZ_STEPS_MAX 100
+
+#define NC_SZ_TIMEOUT_MIN 5
+#define NC_SZ_TIMEOUT_DEF 10
+#define NC_SZ_TIMEOUT_MAX 500
+
+#define NC_TIMER_SIZER 1001
+#define NC_TIMER_ENABLEANIMATE 1002
+
+#define ENABLEANIMATE_TIMEOUT 400
+
+#endif
diff --git a/src/windows/identity/ui/notifier.c b/src/windows/identity/ui/notifier.c
index 9804abf..e0582eb 100644
--- a/src/windows/identity/ui/notifier.c
+++ b/src/windows/identity/ui/notifier.c
@@ -17,7 +17,7 @@
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * ACTION OF CONTRACT TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
@@ -31,13 +31,70 @@
#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 KHUI_ALERT_QUEUE_MAX 64
+#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 */
@@ -45,35 +102,57 @@ 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;
-khm_boolean notifier_modal_loop = 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;
-khui_alert * current_alert = NULL;
+/* 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;
-int iid_normal = IDI_NOTIFY_NONE;
-
#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
-add_to_alert_queue(khui_alert * a) {
+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 *
-del_from_alert_queue(void) {
+alert_queue_get_alert(void) {
khui_alert * a;
if (is_alert_queue_empty()) return NULL;
@@ -83,57 +162,140 @@ del_from_alert_queue(void) {
return a; /* held */
}
-static khui_alert *
-peek_alert_queue(void) {
- if (is_alert_queue_empty()) return NULL;
- return alert_queue[alert_queue_head];
+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 void
-check_for_queued_alerts(void) {
- if (!is_alert_queue_empty()) {
- khui_alert * a;
+static khui_alert *
+alert_queue_get_alert_by_pos(int pos) {
+ khui_alert * a;
- a = peek_alert_queue();
+ if (is_alert_queue_empty() ||
+ pos >= alert_queue_get_size() ||
+ pos < 0) {
+ return NULL;
+ }
- if (a->title) {
- HICON hi;
- int res;
+ a = alert_queue[(alert_queue_head + pos) % KHUI_ALERT_QUEUE_MAX];
+ if (a) {
+ khui_alert_hold(a);
+ }
+ return a;
+}
- if (a->severity == KHERR_ERROR)
- res = OIC_ERROR;
- else if (a->severity == KHERR_WARNING)
- res = OIC_WARNING;
- else
- res = OIC_INFORMATION;
+static int
+alert_queue_delete_alert(khui_alert * a) {
+ int idx;
+ int succ;
- hi = LoadImage(0, MAKEINTRESOURCE(res),
- IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON),
- LR_SHARED);
+ idx = alert_queue_head;
+ while(idx != alert_queue_tail) {
+ if (alert_queue[idx] == a)
+ break;
- khm_statusbar_set_part(KHUI_SBPART_NOTICE,
- hi,
- a->title);
- }
- } else {
- khm_statusbar_set_part(KHUI_SBPART_NOTICE,
- NULL, NULL);
+ 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
-/* forward dcls */
-static khm_int32
-alert_show(khui_alert * a);
+ A list of alerts. Currently has a fixed upper limit, but the limit
+ is high enough for now.
+***********************************************************************/
-static khm_int32
-alert_show_minimized(khui_alert * a);
+typedef struct tag_alert_list {
+ khui_alert * alerts[KHUI_ALERT_QUEUE_MAX];
+ int n_alerts;
+ wchar_t title[KHUI_MAXCCH_TITLE];
+} alert_list;
-static khm_int32
-alert_show_normal(khui_alert * a);
+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_enqueue(khui_alert * a);
+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
@@ -156,15 +318,6 @@ alert_enqueue(khui_alert * a);
#endif
-/**********************************************************************
- Notifier
-***********************************************************************
-
-The notifier is a message only window that listens for notifier
-messages. This window will exist for the lifetime of the application
-and will use alerter windows as needed to show application alerts.
-*/
-
static LRESULT CALLBACK
notifier_wnd_proc(HWND hwnd,
UINT uMsg,
@@ -182,13 +335,29 @@ notifier_wnd_proc(HWND hwnd,
/* handle notifier messages */
switch(m->subtype) {
case KMSG_ALERT_SHOW:
- rv = alert_show((khui_alert *) m->vparam);
- khui_alert_release((khui_alert *) m->vparam);
+ {
+ 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:
- rv = alert_enqueue((khui_alert *) m->vparam);
- khui_alert_release((khui_alert *) m->vparam);
+ {
+ 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:
@@ -196,16 +365,7 @@ notifier_wnd_proc(HWND hwnd,
break;
case KMSG_ALERT_SHOW_QUEUED:
- if (current_alert == NULL) {
- khui_alert * a;
-
- a = del_from_alert_queue();
- if (a) {
- rv = alert_show(a);
- check_for_queued_alerts();
- khui_alert_release(a);
- }
- }
+ show_queued_alerts();
break;
case KMSG_ALERT_SHOW_MODAL:
@@ -213,15 +373,20 @@ notifier_wnd_proc(HWND hwnd,
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);
- khui_alert_release(a);
if (KHM_SUCCEEDED(rv)) {
- notifier_modal_loop = TRUE;
-
- khm_message_loop_int(&notifier_modal_loop);
+ khm_message_loop_int(&a->displayed);
}
+
+ khui_alert_release(a);
}
break;
}
@@ -246,56 +411,120 @@ notifier_wnd_proc(HWND hwnd,
{
POINT pt;
int menu_id;
+ khui_menu_def * mdef;
+ khui_action_ref * act;
+ khm_size i, n;
+ khm_int32 def_cmd;
- GetCursorPos(&pt);
+ /* 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())
+ if (khm_is_main_window_visible()) {
menu_id = KHUI_MENU_ICO_CTX_NORMAL;
- else
+
+ 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 WM_LBUTTONDOWN:
- /* we actually wait for the WM_LBUTTONUP before doing
- anything */
- break;
-
- case WM_LBUTTONUP:
- /* fall through */
case NIN_SELECT:
/* fall through */
case NIN_KEYSELECT:
- khm_show_main_window();
+ /* 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 (current_alert) {
- if ((current_alert->flags & KHUI_ALERT_FLAG_DEFACTION) &&
- current_alert->n_alert_commands > 0) {
+ 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(current_alert->alert_commands[0],
+ MAKEWPARAM(a->alert_commands[0],
0),
0);
- } else if (current_alert->flags &
+ } else if (a->flags &
KHUI_ALERT_FLAG_REQUEST_WINDOW) {
khm_show_main_window();
- alert_show_normal(current_alert);
+ alert_show_normal(a);
}
+
+ khui_alert_unlock(a);
+ khui_alert_release(a);
+ } else {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
}
- /* fallthrough */
+ break;
+
case NIN_BALLOONHIDE:
case NIN_BALLOONTIMEOUT:
khm_notify_icon_change(KHERR_NONE);
- if (current_alert) {
- khui_alert_release(current_alert);
- current_alert = NULL;
+ 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;
}
@@ -342,85 +571,1431 @@ khm_register_notifier_wnd_class(void)
Alerter
**********************************************************************/
-typedef struct tag_alerter_wnd_data {
+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;
- BOOL metrics_done;
+ wchar_t caption[KHUI_MAXCCH_TITLE]; /* the original
+ caption for the
+ dialog. */
- HWND hwnd_buttons[KHUI_MAX_ALERT_COMMANDS];
+ HWND hw_bin;
+ HWND hw_scroll;
+ HWND hw_close;
- /* various metrics */
+ int scroll_top;
- /* calculated during WM_CREATE and adjusted during WM_PAINT */
- int dy_message;
- int dy_suggestion;
+ 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 */
- int dx_button;
- int dy_button;
- int dx_button_incr;
- int dx_margin;
- int dy_margin;
- int dy_bb;
- int x_message;
- int dx_message;
- int dx_icon;
- int dy_icon;
- int dx_suggest_pad;
-
- /* calculated during WM_CREATE and adjusted during WM_PAINT */
- int dx_client;
- int dy_client;
-
- /* calculated during WM_PAINT */
- int y_message;
- int y_suggestion;
-
- LDCL(struct tag_alerter_wnd_data);
-} alerter_wnd_data;
+ 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. */
-alerter_wnd_data * khui_alerts = NULL;
+ 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_MARGIN 5
+#define NTF_WIDTH 200
+#define NTF_MAXHEIGHT 150
-#define NTF_BB_HEIGHT 15
+#define NTF_TITLE_X NTF_MARGIN
+#define NTF_TITLE_WIDTH (NTF_WIDTH - NTF_MARGIN*2)
+#define NTF_TITLE_HEIGHT 10
-#define NTF_ICON_X NTF_MARGIN
-#define NTF_ICON_WIDTH 20
-#define NTF_ICON_HEIGHT 20
+#define NTF_TEXT_PAD 2
-#define NTF_MSG_X (NTF_ICON_X + NTF_ICON_WIDTH + NTF_MARGIN)
-#define NTF_MSG_WIDTH ((NTF_WIDTH - NTF_MARGIN) - NTF_MSG_X)
-#define NTF_MSG_HEIGHT 15
+#define NTF_BUTTON_HEIGHT 14
-#define NTF_SUG_X NTF_MSG_X
-#define NTF_SUG_WIDTH NTF_MSG_WIDTH
-#define NTF_SUG_HEIGHT NTF_MSG_HEIGHT
-#define NTF_SUG_PAD 2
+#define NTF_TIMEOUT 20000
-#define NTF_BUTTON_X NTF_MSG_X
+#define ALERT_WINDOW_EX_SYLES (WS_EX_DLGMODALFRAME | WS_EX_CONTEXTHELP)
+#define ALERT_WINDOW_STYLES (WS_DLGFRAME | WS_POPUPWINDOW | WS_CLIPCHILDREN | DS_NOIDLEMSG)
-#define NTF_BUTTON_WIDTH ((NTF_MSG_WIDTH - 3*NTF_MARGIN) / 4)
-#define NTF_BUTTON_XINCR (NTF_BUTTON_WIDTH + NTF_MARGIN)
-#define NTF_BUTTON_HEIGHT (NTF_BB_HEIGHT - NTF_MARGIN)
+/* Control ids */
+#define IDC_NTF_ALERTBIN 998
+#define IDC_NTF_CLOSE 999
-#define NTF_TIMEOUT 20000
+#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];
- wchar_t mbuf[256];
+ 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)
- return KHM_ERROR_SUCCESS;
+ goto done;
if (a->title == NULL) {
LoadString(khm_hInstance, IDS_ALERT_DEFAULT,
@@ -454,24 +2029,41 @@ alert_show_minimized(khui_alert * a) {
a->flags |= KHUI_ALERT_FLAG_DISPLAY_BALLOON;
-#if (_WIN32_IE >= 0x0501)
- current_alert = a;
- khui_alert_hold(a);
+#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);
+ tbuf,
+ mbuf,
+ NTF_TIMEOUT);
+
+ done:
+ khui_alert_unlock(a);
return KHM_ERROR_SUCCESS;
}
static khm_int32
alert_show_normal(khui_alert * a) {
- HWND hwa;
wchar_t buf[256];
wchar_t * title;
+ alert_list alist;
+
+ khui_alert_lock(a);
if(a->title == NULL) {
LoadString(khm_hInstance, IDS_ALERT_DEFAULT,
@@ -480,73 +2072,226 @@ alert_show_normal(khui_alert * a) {
} else
title = a->title;
- /* if we don't have any commands, we just add a "close" button */
- if (a->n_alert_commands == 0) {
- khui_alert_add_command(a, KHUI_PACTION_CLOSE);
- }
+ khui_alert_unlock(a);
- /* if there are other alerts queued up, we should add a 'Next
- alert...' button that when clicked, would show the next queued
- alert. However, we only do this if the current alert doesn't
- actually require a command response. Otherwise, clicking the
- 'next' button will be the equivalent of cancelling out of the
- alert without selecting any of the commands. */
- if (!is_alert_queue_empty() &&
- a->n_alert_commands == 1 &&
- a->alert_commands[0] == KHUI_PACTION_CLOSE) {
+ alert_list_init(&alist);
+ alert_list_set_title(&alist, title);
+ alert_list_add_alert(&alist, a);
- khui_alert_add_command(a, KHUI_PACTION_NEXT);
- }
+ 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(WS_EX_DLGMODALFRAME | WS_EX_CONTEXTHELP,
+ CreateWindowEx(ALERT_WINDOW_EX_SYLES,
MAKEINTATOM(atom_alerter),
- title,
- WS_DLGFRAME | WS_POPUPWINDOW | WS_CLIPCHILDREN,
+ alist->title,
+ ALERT_WINDOW_STYLES,
0, 0, 300, 300, // bogus values
khm_hwnd_main,
(HMENU) NULL,
khm_hInstance,
- (LPVOID) a);
+ (LPVOID) alist);
ShowWindow(hwa, SW_SHOW);
- return KHM_ERROR_SUCCESS;
+ 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 (current_alert) {
- return alert_enqueue(a);
+ 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;
}
- /* the window has already been shown */
if((a->flags & KHUI_ALERT_FLAG_DISPLAY_WINDOW) ||
- ((a->flags & KHUI_ALERT_FLAG_DISPLAY_BALLOON) &&
- !(a->flags & KHUI_ALERT_FLAG_REQUEST_WINDOW)))
- return KHM_ERROR_SUCCESS;
+ ((a->flags & KHUI_ALERT_FLAG_DISPLAY_BALLOON) &&
+ !(a->flags & KHUI_ALERT_FLAG_REQUEST_WINDOW))) {
- if(a->err_context != NULL ||
- a->err_event != NULL) {
- khui_alert_lock(a);
- a->flags |= KHUI_ALERT_FLAG_VALID_ERROR;
- khui_alert_unlock(a);
+ /* 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;
+
+ }
}
- /* 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)))
+ khui_alert_unlock(a);
+
+ if (show_normal)
return alert_show_normal(a);
- else
+ 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
@@ -554,7 +2299,7 @@ alert_enqueue(khui_alert * a) {
if (is_alert_queue_full())
return KHM_ERROR_NO_RESOURCES;
- add_to_alert_queue(a);
+ alert_queue_put_alert(a);
check_for_queued_alerts();
return KHM_ERROR_SUCCESS;
@@ -570,29 +2315,14 @@ alerter_wnd_proc(HWND hwnd,
switch(uMsg) {
case WM_CREATE:
{
- LONG dlgb;
- HWND hwnd_parent;
- RECT r_parent;
- POINT pos;
- SIZE s;
LPCREATESTRUCT lpcs;
- khui_alert * a;
+ alert_list * alist;
alerter_wnd_data * d;
lpcs = (LPCREATESTRUCT) lParam;
- a = (khui_alert *) lpcs->lpCreateParams;
- khui_alert_hold(a);
-
- d = PMALLOC(sizeof(*d));
- ZeroMemory(d, sizeof(*d));
-
- d->alert = a;
- d->hwnd = hwnd;
-
- khui_alert_lock(a);
+ alist = (alert_list *) lpcs->lpCreateParams;
- a->flags |= KHUI_ALERT_FLAG_DISPLAY_WINDOW;
- LPUSH(&khui_alerts, d);
+ d = create_alerter_wnd_data(hwnd, alist);
#pragma warning(push)
#pragma warning(disable: 4244)
@@ -602,444 +2332,424 @@ alerter_wnd_proc(HWND hwnd,
khm_add_dialog(hwnd);
khm_enter_modal(hwnd);
- /* now figure out the size and position of the window */
+ estimate_alerter_wnd_sizes(d);
+ setup_alerter_window_controls(d);
- hwnd_parent = GetWindow(hwnd, GW_OWNER);
- GetWindowRect(hwnd_parent, &r_parent);
-
- dlgb = GetDialogBaseUnits();
+ if (d->hw_close) {
+ SetFocus(d->hw_close);
+ }
-#define DLG2SCNX(x) MulDiv((x), LOWORD(dlgb), 4)
-#define DLG2SCNY(y) MulDiv((y), HIWORD(dlgb), 8)
+ return TRUE;
+ }
+ break; /* not reached */
- d->dx_margin = DLG2SCNX(NTF_MARGIN);
- d->dy_margin = DLG2SCNY(NTF_MARGIN);
+ case WM_DESTROY:
+ {
+ alerter_wnd_data * d;
- d->x_message = DLG2SCNX(NTF_MSG_X);
- d->dx_message = DLG2SCNX(NTF_MSG_WIDTH);
+ /* 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);
- if (a->message) {
- d->dy_message = DLG2SCNY(NTF_MSG_HEIGHT);
- }
+ d = (alerter_wnd_data *)(LONG_PTR)
+ GetWindowLongPtr(hwnd, NTF_PARAM);
- if (a->suggestion) {
- d->dy_suggestion = DLG2SCNY(NTF_SUG_HEIGHT);
- d->dx_suggest_pad = DLG2SCNX(NTF_SUG_PAD);
- }
+ destroy_alerter_wnd_data(d);
- d->dy_bb = DLG2SCNY(NTF_BB_HEIGHT);
- d->dx_button = DLG2SCNX(NTF_BUTTON_WIDTH);
- d->dy_button = DLG2SCNY(NTF_BUTTON_HEIGHT);
- d->dx_button_incr = DLG2SCNX(NTF_BUTTON_XINCR);
+ return TRUE;
+ }
+ break;
- d->dx_icon = DLG2SCNX(NTF_ICON_WIDTH);
- d->dy_icon = DLG2SCNY(NTF_ICON_HEIGHT);
+ case WM_COMMAND:
+ {
+ alerter_wnd_data * d;
- d->dx_client = DLG2SCNX(NTF_WIDTH);
- d->dy_client = max(d->dy_icon,
- d->dy_message +
- ((d->dy_suggestion > 0)?
- (d->dy_suggestion + d->dy_margin):
- 0)) +
- d->dy_margin * 3 + d->dy_bb;
+ d = (alerter_wnd_data *)(LONG_PTR)
+ GetWindowLongPtr(hwnd, NTF_PARAM);
- /* adjust for client rect */
- s.cx = d->dx_client;
- s.cy = d->dy_client;
+ if(HIWORD(wParam) == BN_CLICKED) {
+ if (LOWORD(wParam) == IDC_NTF_CLOSE ||
+ LOWORD(wParam) == KHUI_PACTION_NEXT) {
- {
- RECT c_r;
- RECT w_r;
+ khm_leave_modal();
- GetWindowRect(hwnd, &w_r);
- GetClientRect(hwnd, &c_r);
+ DestroyWindow(hwnd);
- s.cx += (w_r.right - w_r.left) - (c_r.right - c_r.left);
- s.cy += (w_r.bottom - w_r.top) - (c_r.bottom - c_r.top);
+ return 0;
+ }
}
+ }
+ break;
- pos.x = (r_parent.left + r_parent.right - s.cx) / 2;
- pos.y = (r_parent.top + r_parent.bottom - s.cy) / 2;
+ case WM_CLOSE:
+ {
+ khm_leave_modal();
- SetWindowPos(hwnd,
- HWND_TOP,
- pos.x, pos.y,
- s.cx, s.cy,
- SWP_SHOWWINDOW);
+ DestroyWindow(hwnd);
- {
- LOGFONT lf;
- HDC hdc_dt;
-
- hdc_dt = GetDC(NULL);
-
- lf.lfHeight = -MulDiv(8,
- GetDeviceCaps(hdc_dt, LOGPIXELSY),
- 72);
- lf.lfWidth = 0;
- lf.lfEscapement = 0;
- lf.lfOrientation = 0;
- lf.lfWeight = FW_NORMAL;
- lf.lfItalic = FALSE;
- lf.lfUnderline = FALSE;
- lf.lfStrikeOut = FALSE;
- 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->hfont = CreateFontIndirect(&lf);
-
- ReleaseDC(NULL, hdc_dt);
- }
+ return 0;
+ }
+ }
- /* create dialog controls now */
- {
- int x,y;
- int width, height;
- int i;
+ /* Since this is a custom built dialog, we use DefDlgProc instead
+ of DefWindowProc. */
+ return DefDlgProc(hwnd, uMsg, wParam, lParam);
+}
- x = d->x_message;
- y = d->dy_client - d->dy_bb;
- width = d->dx_button;
- height = d->dy_button;
+static LRESULT CALLBACK
+alert_bin_wnd_proc(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ BOOL in_printclient = FALSE;
- for(i=0; i<a->n_alert_commands; i++) {
- wchar_t caption[256];
- khui_action * action;
- HWND hw_button;
+ switch(uMsg) {
+ case WM_CREATE:
+ {
+ LPCREATESTRUCT lpcs;
+ alerter_wnd_data * d;
- if(a->alert_commands[i] == 0)
- continue;
+ lpcs = (LPCREATESTRUCT) lParam;
+ d = (alerter_wnd_data *) lpcs->lpCreateParams;
- action = khui_find_action(a->alert_commands[i]);
- if(action == NULL)
- continue;
+#pragma warning(push)
+#pragma warning(disable: 4244)
+ SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) d);
+#pragma warning(pop)
+ }
+ return 0;
- LoadString(khm_hInstance, action->is_caption,
- caption, ARRAYLENGTH(caption));
-
- hw_button =
- CreateWindowEx(0,
- L"BUTTON",
- caption,
- WS_VISIBLE | WS_CHILD |
- /* the first button is the default */
- ((i==0)? BS_DEFPUSHBUTTON: 0),
- x,y,width,height,
- hwnd,
- (HMENU)(INT_PTR) (action->cmd),
- khm_hInstance,
- NULL);
+ case WM_ERASEBKGND:
+ /* we erase the background when we are drawing the alerts
+ anyway. */
+ return 0;
- SendMessage(hw_button, WM_SETFONT,
- (WPARAM) d->hfont, MAKELPARAM(TRUE, 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->hwnd_buttons[i] = hw_button;
+ d = (alerter_wnd_data *) (LONG_PTR) GetWindowLongPtr(hwnd, GWLP_USERDATA);
+#ifdef DEBUG
+ assert(d);
+#endif
- x += d->dx_button_incr;
- }
+ if (in_printclient) {
+ hdc = (HDC) wParam;
+ } else {
+ hdc = BeginPaint(hwnd, &ps);
}
- if (d->hwnd_buttons[0])
- SetFocus(d->hwnd_buttons[0]);
-
- khm_notify_icon_change(a->severity);
-
- khui_alert_unlock(a);
-
- d->metrics_done = FALSE;
-
- return TRUE;
- }
- break; /* not reached */
+#ifdef DEBUG
+ assert(hdc);
+ assert(d->hfont);
+#endif
- case WM_DESTROY:
- {
- alerter_wnd_data * d;
+#ifdef ALERT_STATIC_BACKGROUND
+ if (in_printclient || ps.fErase) {
+ HBRUSH hb_background;
- /* 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);
+ hb_background = GetSysColorBrush(COLOR_BTNFACE);
- d = (alerter_wnd_data *)(LONG_PTR)
- GetWindowLongPtr(hwnd, NTF_PARAM);
+ GetClientRect(hwnd, &r);
+ FillRect(hdc, &r, hb_background);
+ }
+#endif
- LDELETE(&khui_alerts, d);
+ SetBkMode(hdc, TRANSPARENT);
- khui_alert_lock(d->alert);
- d->alert->flags &= ~KHUI_ALERT_FLAG_DISPLAY_WINDOW;
- if (d->alert->flags & KHUI_ALERT_FLAG_MODAL)
- notifier_modal_loop = FALSE;
- khui_alert_unlock(d->alert);
+ hf_old = SelectFont(hdc, d->hfont);
- khui_alert_release(d->alert);
+ 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;
+ }
- DeleteObject(d->hfont);
+ gr.UpperLeft = 0;
+ gr.LowerRight = 1;
+ GradientFill(hdc, v, 2, &gr, 1, GRADIENT_FILL_RECT_V);
+ }
+#undef ALPHA
+#undef MIX_C
+#endif
- PFREE(d);
+ a = adata->alert;
+#ifdef DEBUG
+ assert(a != NULL);
+#endif
+ khui_alert_lock(a);
- khm_notify_icon_change(KHERR_NONE);
+ if (!IsRectEmpty(&adata->r_title)) {
- return TRUE;
- }
- break;
+ CopyRect(&r, &adata->r_title);
+ OffsetRect(&r, 0, y);
- case WM_PAINT:
- {
- RECT r_update;
- PAINTSTRUCT ps;
- HDC hdc;
- LONG dlgb;
- alerter_wnd_data * d;
- HFONT hf_old;
- BOOL need_resize = FALSE;
+ StringCchLength(a->title, KHUI_MAXCCH_TITLE, &len);
- if(!GetUpdateRect(hwnd, &r_update, TRUE))
- return FALSE;
+ DrawEdge(hdc, &r, EDGE_RAISED, BF_RECT | BF_MIDDLE);
- d = (alerter_wnd_data *)(LONG_PTR)
- GetWindowLongPtr(hwnd, NTF_PARAM);
+ InflateRect(&r, -d->s_pad.cx, -d->s_pad.cy);
- dlgb = GetDialogBaseUnits();
+ DrawText(hdc, a->title, (int) len, &r,
+ DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS);
+ }
- hdc = BeginPaint(hwnd, &ps);
+ {
+ 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);
+ }
- hf_old = SelectFont(hdc, d->hfont);
+ if (a->message) {
- khui_alert_lock(d->alert);
+ CopyRect(&r, &adata->r_message);
+ OffsetRect(&r, 0, y);
- // draw the severity icon
- {
- HICON hicon;
- int x,y;
- int iid;
-
- /* GOINGHERE! If the metrics for the window haven't
- been calculated yet, then calculate them. If the
- hight needs to be expanded, then do that and wait
- for the next repaint cycle. Also move the button
- controls down. */
- x = d->dx_margin;
- y = d->dy_margin;
-
- if(d->alert->severity == KHERR_ERROR)
- iid = OIC_HAND;
- else if(d->alert->severity == KHERR_WARNING)
- iid = OIC_BANG;
- else
- iid = OIC_NOTE;
-
- hicon = LoadImage(NULL,
- MAKEINTRESOURCE(iid),
- IMAGE_ICON,
- GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON),
- LR_SHARED);
-
- DrawIcon(hdc, x, y, hicon);
- }
+ StringCchLength(a->message, KHUI_MAXCCH_MESSAGE, &len);
- // draw the message
- if(d->alert->message) {
- RECT r;
- int width;
- int height;
- size_t cch;
-
- r.left = d->x_message;
- r.top = d->dy_margin;
- width = d->dx_message;
- r.right = r.left + width;
- height = d->dy_message;
- r.bottom = r.top + height;
-
- StringCchLength(d->alert->message,
- KHUI_MAXCCH_MESSAGE, &cch);
-
- height = DrawText(hdc,
- d->alert->message,
- (int) cch,
- &r,
- DT_WORDBREAK |
- DT_CALCRECT);
-
- if (height > d->dy_message) {
- d->dy_message = height;
- need_resize = TRUE;
- } else {
- DrawText(hdc,
- d->alert->message,
- (int) cch,
- &r,
+ DrawText(hdc, a->message, (int) len, &r,
DT_WORDBREAK);
}
- d->y_message = r.top;
- }
+ if (a->suggestion) {
+ HICON hicon;
+ SIZE sz;
- // and the suggestion
- if (d->alert->suggestion) {
- RECT r, ro;
- int height;
- size_t cch;
- HICON h_sug_ico;
-
- r.left = d->x_message;
- r.top = d->y_message + d->dy_message + d->dy_margin;
- r.right = r.left + d->dx_message;
- r.bottom = r.top + d->dy_suggestion;
-
- CopyRect(&ro, &r);
-
- // adjust for icon and padding
- r.left += GetSystemMetrics(SM_CXSMICON) + d->dx_suggest_pad * 2;
- r.top += d->dx_suggest_pad;
- r.right -= d->dx_suggest_pad;
- r.bottom -= d->dx_suggest_pad;
-
- StringCchLength(d->alert->suggestion,
- KHUI_MAXCCH_SUGGESTION, &cch);
-
- height = DrawText(hdc,
- d->alert->suggestion,
- (int) cch,
- &r,
- DT_WORDBREAK |
- DT_CALCRECT);
-
- if (height > d->dy_suggestion) {
- d->dy_suggestion = height;
- need_resize = TRUE;
- } else {
- int old_bk_mode;
+ CopyRect(&r, &adata->r_suggestion);
+ OffsetRect(&r, 0, y);
- ro.bottom = r.bottom + d->dx_suggest_pad;
+ DrawEdge(hdc, &r, EDGE_SUNKEN, BF_RECT | BF_MIDDLE);
- FillRect(hdc, &ro, (HBRUSH) (COLOR_INFOBK + 1));
- DrawEdge(hdc, &ro, EDGE_SUNKEN, BF_FLAT | BF_RECT);
+ InflateRect(&r, -d->s_pad.cx, -d->s_pad.cy);
- h_sug_ico =
- LoadImage(0,
- MAKEINTRESOURCE(OIC_INFORMATION),
- IMAGE_ICON,
- GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON),
- LR_SHARED);
+ sz.cx = GetSystemMetrics(SM_CXSMICON);
+ sz.cy = GetSystemMetrics(SM_CYSMICON);
- assert(h_sug_ico != NULL);
+ hicon = (HICON) LoadImage(NULL,
+ MAKEINTRESOURCE(OIC_NOTE),
+ IMAGE_ICON,
+ sz.cx,
+ sz.cy,
+ LR_SHARED);
- DrawIconEx(hdc,
- ro.left + d->dx_suggest_pad,
- ro.top + d->dx_suggest_pad,
- h_sug_ico,
- GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON),
- 0, NULL,
+ DrawIconEx(hdc, r.left, r.top, hicon, sz.cx, sz.cy, 0, NULL,
DI_NORMAL);
- old_bk_mode = SetBkMode(hdc, TRANSPARENT);
+ r.left += d->s_pad.cx + GetSystemMetrics(SM_CXSMICON);
- DrawText(hdc,
- d->alert->suggestion,
- (int) cch,
- &r,
- DT_WORDBREAK);
+ StringCchLength(a->suggestion, KHUI_MAXCCH_SUGGESTION, &len);
- SetBkMode(hdc, old_bk_mode);
+ DrawText(hdc, a->suggestion, (int) len, &r,
+ DT_WORDBREAK);
}
+ khui_alert_unlock(a);
+
+ y += adata->r_alert.bottom;
+ idx++;
- d->y_suggestion = r.top;
+ adata = QNEXT(adata);
}
- khui_alert_unlock(d->alert);
+ SelectFont(hdc, hf_old);
- SelectObject(hdc, hf_old);
+ if (!in_printclient) {
+ EndPaint(hwnd, &ps);
+ }
+ }
+ return 0;
- EndPaint(hwnd, &ps);
+ case WM_VSCROLL:
+ {
+ alerter_wnd_data * d;
+ int new_pos = 0;
+ SCROLLINFO si;
- if (need_resize) {
- RECT r;
- int x,y;
- int width, height;
- int i;
-
- GetClientRect(hwnd, &r);
+ 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 */
- height = max(d->dy_icon,
- d->dy_message +
- ((d->dy_suggestion > 0)?
- (d->dy_suggestion + d->dy_margin):
- 0)) +
- d->dy_margin * 3 + d->dy_bb;
- r.bottom = r.top + height;
-
- d->dy_client = height;
-
- AdjustWindowRectEx(&r,
- GetWindowLongPtr(hwnd, GWL_STYLE),
- FALSE,
- GetWindowLongPtr(hwnd, GWL_EXSTYLE));
-
- SetWindowPos(hwnd,
- NULL,
- 0, 0,
- r.right - r.left,
- r.bottom - r.top,
- SWP_NOACTIVATE | SWP_NOCOPYBITS |
- SWP_NOMOVE | SWP_NOOWNERZORDER |
- SWP_NOZORDER);
-
- InvalidateRect(hwnd, NULL, TRUE);
-
- x = d->x_message;
- y = d->dy_client - d->dy_bb;
- width = d->dx_button;
- height = d->dy_button;
-
- for(i=0; i<d->alert->n_alert_commands; i++) {
- MoveWindow(d->hwnd_buttons[i],
- x,y,
- width,height,
- TRUE);
-
- x += d->dx_button_incr;
- }
+ 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;
}
- return FALSE;
+ scroll_to_position(d, new_pos, FALSE);
}
- break; /* not reached */
+ return 0;
case WM_COMMAND:
{
alerter_wnd_data * d;
- d = (alerter_wnd_data *)(LONG_PTR)
- GetWindowLongPtr(hwnd, NTF_PARAM);
+ d = (alerter_wnd_data *) (LONG_PTR) GetWindowLongPtr(hwnd, GWLP_USERDATA);
+#ifdef DEBUG
+ assert(d);
+#endif
+ if (d == NULL)
+ break;
- if(HIWORD(wParam) == BN_CLICKED) {
- khui_alert_lock(d->alert);
- d->alert->response = LOWORD(wParam);
- khui_alert_unlock(d->alert);
+ 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;
- khm_leave_modal();
+ case WM_LBUTTONUP:
+ {
+ alerter_wnd_data * d;
+ int x,y;
- DestroyWindow(hwnd);
+ d = (alerter_wnd_data *) (LONG_PTR) GetWindowLongPtr(hwnd, GWLP_USERDATA);
+#ifdef DEBUG
+ assert(d);
+#endif
+ if (d == NULL)
+ break;
- if (LOWORD(wParam) == KHUI_PACTION_NEXT)
- kmq_post_message(KMSG_ALERT, KMSG_ALERT_SHOW_QUEUED, 0, 0);
- return 0;
- }
+ 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 DefDlgProc(hwnd, uMsg, wParam, lParam);
- //return DefWindowProc(hwnd, uMsg, wParam, lParam);
+ return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
ATOM khm_register_alerter_wnd_class(void)
@@ -1061,7 +2771,7 @@ ATOM khm_register_alerter_wnd_class(void)
wcx.hInstance = khm_hInstance;
wcx.hIcon = LoadIcon(khm_hInstance, MAKEINTRESOURCE(IDI_MAIN_APP));
wcx.hCursor = LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW));
- wcx.hbrBackground = (HBRUSH)(COLOR_BACKGROUND + 1);
+ wcx.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
wcx.lpszMenuName = NULL;
wcx.lpszClassName = KHUI_ALERTER_CLASS;
wcx.hIconSm = NULL;
@@ -1071,6 +2781,31 @@ ATOM khm_register_alerter_wnd_class(void)
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
***********************************************************************/
@@ -1096,11 +2831,11 @@ void khm_notify_icon_add(void) {
Shell_NotifyIcon(NIM_ADD, &ni);
+ DestroyIcon(ni.hIcon);
+
ni.cbSize = sizeof(ni);
ni.uVersion = NOTIFYICON_VERSION;
Shell_NotifyIcon(NIM_SETVERSION, &ni);
-
- DestroyIcon(ni.hIcon);
}
void
@@ -1140,19 +2875,20 @@ khm_notify_icon_balloon(khm_int32 severity,
/* too long? */
StringCchCopyN(ni.szInfo, ARRAYLENGTH(ni.szInfo),
msg,
- ARRAYLENGTH(ni.szInfo) - ARRAYLENGTH(ELIPSIS));
+ ARRAYLENGTH(ni.szInfo) - ARRAYLENGTH(ELLIPSIS));
StringCchCat(ni.szInfo, ARRAYLENGTH(ni.szInfo),
- ELIPSIS);
+ ELLIPSIS);
}
if (FAILED(StringCbCopy(ni.szInfoTitle, sizeof(ni.szInfoTitle),
title))) {
StringCchCopyN(ni.szInfoTitle, ARRAYLENGTH(ni.szInfoTitle),
title,
- ARRAYLENGTH(ni.szInfoTitle) - ARRAYLENGTH(ELIPSIS));
+ ARRAYLENGTH(ni.szInfoTitle) - ARRAYLENGTH(ELLIPSIS));
StringCchCat(ni.szInfoTitle, ARRAYLENGTH(ni.szInfoTitle),
- ELIPSIS);
+ ELLIPSIS);
}
+
ni.uTimeout = timeout;
Shell_NotifyIcon(NIM_MODIFY, &ni);
@@ -1177,7 +2913,7 @@ void khm_notify_icon_expstate(enum khm_notif_expstate expseverity) {
iid_normal = new_iid;
- if (current_alert == NULL)
+ if (balloon_alert == NULL)
khm_notify_icon_change(KHERR_NONE);
}
@@ -1227,6 +2963,102 @@ void khm_notify_icon_remove(void) {
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
**********************************************************************/
@@ -1239,6 +3071,9 @@ void khm_init_notifier(void)
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,
@@ -1255,12 +3090,11 @@ void khm_init_notifier(void)
notifier_ready = TRUE;
khm_notify_icon_add();
- }
+ } else {
#ifdef DEBUG
- else {
assert(hwnd_notifier != NULL);
- }
#endif
+ }
khm_timer_init();
khm_addr_change_notifier_init();
@@ -1290,5 +3124,37 @@ void khm_exit_notifier(void)
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 140d02c..a42e63f 100644
--- a/src/windows/identity/ui/notifier.h
+++ b/src/windows/identity/ui/notifier.h
@@ -36,6 +36,9 @@ enum khm_notif_expstate {
KHM_NOTIF_EXP
};
+extern khm_int32 khm_notifier_actions[];
+extern khm_size n_khm_notifier_actions;
+
void
khm_init_notifier(void);
@@ -54,4 +57,7 @@ khm_notify_icon_balloon(khm_int32 severity,
void
khm_notify_icon_expstate(enum khm_notif_expstate expseverity);
+void
+khm_notify_icon_activate(void);
+
#endif
diff --git a/src/windows/identity/ui/propertywnd.c b/src/windows/identity/ui/propertywnd.c
index 79a6cc3..4061cd7 100644
--- a/src/windows/identity/ui/propertywnd.c
+++ b/src/windows/identity/ui/propertywnd.c
@@ -230,7 +230,7 @@ khm_int32 khm_register_propertywnd_class(void)
wcx.hInstance = khm_hInstance;
wcx.hIcon = NULL;
wcx.hCursor = LoadCursor((HINSTANCE) NULL, IDC_ARROW);
- wcx.hbrBackground = (HBRUSH) (COLOR_BACKGROUND + 1);
+ wcx.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1);
wcx.lpszMenuName = NULL;
wcx.lpszClassName = KHUI_PROPERTYWND_CLASS_NAME;
wcx.hIconSm = NULL;
diff --git a/src/windows/identity/ui/reqdaemon.c b/src/windows/identity/ui/reqdaemon.c
index b95f02d..e72e3e2 100644
--- a/src/windows/identity/ui/reqdaemon.c
+++ b/src/windows/identity/ui/reqdaemon.c
@@ -350,6 +350,8 @@ khm_reqdaemon_thread_proc(LPVOID vparam) {
DWORD dw;
#endif
+ PDESCTHREAD(L"Remote Request Daemon", L"App");
+
khm_register_reqdaemonwnd_class();
#ifdef DEBUG
diff --git a/src/windows/identity/ui/resource.h b/src/windows/identity/ui/resource.h
index f430fe0..7be9a84 100644
--- a/src/windows/identity/ui/resource.h
+++ b/src/windows/identity/ui/resource.h
@@ -3,14 +3,12 @@
// Used by C:\work\pismere\athena\auth\krb5\src\windows\identity\ui\lang\en_us\khapp.rc
//
#define IDI_MAIN_APP 104
-#define IDD_PROPPAGE_MEDIUM 106
#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_IDENTITY 110
#define IDS_MENU_CRED 110
#define IDB_ID_DELETE 111
#define IDS_MENU_VIEW 111
@@ -23,17 +21,13 @@
#define IDB_TK_DELETE 115
#define IDS_ACTION_EXIT 115
#define IDB_TK_NEW 116
-#define IDS_ACTION_NEW_ID 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 IDS_ACTION_DESTROY_ID 119
#define IDR_MENU_BAR 119
#define IDS_CFG_ROOT_TITLE 119
-#define IDS_ACTION_RENEW_ID 120
#define IDS_CFG_GENERAL_SHORT 120
-#define IDS_ACTION_ADD_CRED 121
#define IDB_TB_BLANK 121
#define IDS_ACTION_NEW_CRED 121
#define IDS_ACTION_PASSWD_ID 122
@@ -57,7 +51,6 @@
#define IDB_ID_NEW_DIS_SM 131
#define IDS_ACTION_OPT_KHIM 132
#define IDB_ID_NEW_SM 132
-#define IDS_ACTION_OPT_INIT 133
#define IDB_ID_REFRESH_DIS 133
#define IDS_ACTION_OPT_IDENTS 133
#define IDS_ACTION_OPT_NOTIF 134
@@ -71,7 +64,6 @@
#define IDS_ACTION_HELP_ABOUT 138
#define IDB_TK_DELETE_SM 138
#define IDB_TK_DIS_SM 139
-#define IDS_ACTIONINFO_NEW_ID 139
#define IDS_CFG_GENERAL_LONG 139
#define IDB_TK_NEW_DIS 140
#define IDS_SAMPLE_STRING 140
@@ -82,7 +74,6 @@
#define IDB_TK_REFRESH_DIS 143
#define IDS_WT_NEW_CREDS 143
#define IDB_TK_REFRESH_DIS_SM 144
-#define IDS_NC_PASSWORD 144
#define IDS_NC_IDENTITY 144
#define IDB_TK_REFRESH_SM 145
#define IDS_NC_IDENTS 145
@@ -116,12 +107,10 @@
#define IDS_PACTION_OK 160
#define IDB_FLAG_CRITICAL 161
#define IDS_PACTION_CANCEL 161
-#define IDD_NC_PASSWORD 162
#define IDS_PACTION_CLOSE 162
#define IDD_NC_NEWCRED 162
#define IDD_NC_BBAR 163
#define IDS_ALERT_NOSEL_TITLE 163
-#define IDD_NC_TS 164
#define IDS_ALERT_NOSEL 164
#define IDI_ENABLED 165
#define IDS_NC_CREDTEXT_ID_VALID 165
@@ -166,7 +155,6 @@
#define IDS_CFG_IDENTITY_SHORT 186
#define IDI_CFG_DELETED 186
#define IDS_CFG_IDENTITY_LONG 187
-#define IDI_ICON1 187
#define IDI_ID 187
#define IDS_CTX_DESTROY_CREDS 188
#define IDB_IMPORT_SM_DIS 188
@@ -204,7 +192,6 @@
#define IDS_PISTATE_FAILUNK 205
#define IDI_APPICON_EXP 205
#define IDS_PISTATE_FAILMAX 206
-#define IDI_ICON4 206
#define IDI_APPICON_OK 206
#define IDS_PISTATE_FAILREG 207
#define IDI_CFG_PLUGIN 207
@@ -301,38 +288,46 @@
#define IDS_IDACTION_RENEW 294
#define IDS_IDACTION_DESTROY 295
#define IDS_CTX_DESTROY_ID 296
-#define IDC_NC_USERNAME 1007
-#define IDC_NC_PASSWORD 1008
+#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_PASSWORD_LABEL 1010
-#define IDC_NC_USERNAME_LABEL 1011
#define IDC_NC_CREDTEXT 1012
#define IDC_NC_HELP 1017
-#define IDC_NC_OPTIONS 1019
+#define IDC_NC_ADVANCED 1019
#define IDC_PP_IDNAME 1026
#define IDC_PP_IDDEF 1027
#define IDC_PP_IDSEARCH 1028
-#define IDC_PP_IDSTATUS 1029
-#define IDC_PP_IDSTATUSIMG 1030
-#define IDC_PP_IDVALID 1031
-#define IDC_PP_IDRENEW 1032
-#define IDC_NC_IDENTITY 1033
-#define IDC_NC_IDENTITY_LABEL 1034
#define IDC_PP_PROPLIST 1035
#define IDC_PP_CPROPLIST 1036
-#define IDC_NC_REALM 1037
-#define IDC_NC_REALM_LABEL 1038
#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_ROW2 1045
#define IDC_NC_TPL_ROW_LG 1045
#define IDC_CFG_NODELIST 1045
#define IDAPPLY 1048
-#define IDC_CFG_SUMMARY 1049
#define IDC_CFG_TITLE 1050
#define IDC_CFG_PANE 1051
#define IDC_NOTIF_MONITOR 1053
@@ -351,15 +346,11 @@
#define IDC_CFG_OTHER 1066
#define IDC_CFG_MONITOR 1069
#define IDC_CFG_STICKY 1070
-#define IDC_CFG_IDENTS 1071
-#define IDC_CFG_IDENTITY 1072
#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_PLUGINGRP 1080
-#define IDC_CFG_LBL_DESC 1083
#define IDC_CFG_DESC 1084
#define IDC_CFG_LBL_STATE 1085
#define IDC_CFG_STATE 1086
@@ -367,7 +358,6 @@
#define IDC_CFG_DEPS 1088
#define IDC_CFG_DISABLE 1089
#define IDC_CFG_ENABLE 1090
-#define IDC_CFG_PROVGRP 1091
#define IDC_CFG_LBL_MOD 1092
#define IDC_CFG_MODULE 1093
#define IDC_CFG_LBL_VEN 1094
@@ -378,7 +368,6 @@
#define IDC_PRODUCT 1100
#define IDC_COPYRIGHT 1101
#define IDC_BUILDINFO 1102
-#define IDC_LIST1 1103
#define IDC_MODULES 1103
#define IDC_PP_CONFIG 1104
#define IDC_CFG_UNREGISTER 1107
@@ -396,7 +385,6 @@
#define IDC_CFG_BOLD 1131
#define IDC_CFG_ITALICS 1132
#define IDC_CFG_ADDIDENT 1133
-#define IDC_CFG_IDNAME 1134
#define IDC_SM_CTL 1134
#define IDC_CFG_SHOWLOG 1135
#define IDC_MED_CTL 1135
@@ -404,6 +392,9 @@
#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
@@ -418,7 +409,7 @@
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 212
#define _APS_NEXT_COMMAND_VALUE 40010
-#define _APS_NEXT_CONTROL_VALUE 1140
+#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 5bcf2c2..e5f7e20 100644
--- a/src/windows/identity/ui/statusbar.c
+++ b/src/windows/identity/ui/statusbar.c
@@ -30,9 +30,13 @@
#endif
khm_statusbar_part khm_statusbar_parts[] = {
- {KHUI_SBPART_INFO, 0, KHUI_SB_WTYPE_FILLER},
- {KHUI_SBPART_NOTICE, 40, KHUI_SB_WTYPE_RELATIVE},
- {KHUI_SBPART_LOC, 40, KHUI_SB_WTYPE_ABSOLUTE}
+ {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);
@@ -178,10 +182,22 @@ void khm_statusbar_set_part(int id, HICON icon, wchar_t * text) {
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) icon);
+ (LPARAM) (khm_statusbar_parts[idx].hIcon ? khm_statusbar_parts[idx].hIcon:icon));
SendMessage(khm_hwnd_statusbar,
SB_SETTEXT,
@@ -189,3 +205,4 @@ void khm_statusbar_set_part(int id, HICON icon, wchar_t * text) {
(LPARAM) text);
}
+
diff --git a/src/windows/identity/ui/statusbar.h b/src/windows/identity/ui/statusbar.h
index 2fd267e..6a2b3dd 100644
--- a/src/windows/identity/ui/statusbar.h
+++ b/src/windows/identity/ui/statusbar.h
@@ -31,6 +31,7 @@ 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
diff --git a/src/windows/identity/ui/taskbar.c b/src/windows/identity/ui/taskbar.c
new file mode 100644
index 0000000..48a575f
--- /dev/null
+++ b/src/windows/identity/ui/taskbar.c
@@ -0,0 +1,87 @@
+/*
+ * 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>
+
+#define COBJMACROS
+
+#include<shobjidl.h>
+
+#ifdef DEBUG
+#include<assert.h>
+#endif
+
+ITaskbarList *itbl = NULL;
+
+void
+khm_init_taskbar_funcs(void) {
+ HRESULT hr = NOERROR;
+
+ hr = CoCreateInstance(&CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER,
+ &IID_ITaskbarList, &itbl);
+
+#ifdef DEBUG
+ assert(itbl != NULL);
+#endif
+
+ if (itbl) {
+ hr = ITaskbarList_HrInit(itbl);
+#ifdef DEBUG
+ assert(hr == NOERROR);
+#endif
+ }
+}
+
+void
+khm_exit_taskbar_funcs(void) {
+ if (itbl) {
+ ITaskbarList_Release(itbl);
+ }
+}
+
+void
+khm_taskbar_add_window(HWND hwnd) {
+ HRESULT hr = NOERROR;
+
+ if (itbl) {
+ hr = ITaskbarList_AddTab(itbl, hwnd);
+#ifdef DEBUG
+ assert(hr == NOERROR);
+#endif
+ }
+}
+
+void
+khm_taskbar_remove_window(HWND hwnd) {
+ HRESULT hr = NOERROR;
+
+ if (itbl) {
+ hr = ITaskbarList_DeleteTab(itbl, hwnd);
+#ifdef DEBUG
+ assert(hr == NOERROR);
+#endif
+ }
+}
diff --git a/src/windows/identity/ui/taskbar.h b/src/windows/identity/ui/taskbar.h
new file mode 100644
index 0000000..32adf5c
--- /dev/null
+++ b/src/windows/identity/ui/taskbar.h
@@ -0,0 +1,38 @@
+/*
+ * 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_TASKBAR_H
+#define NETIDMGR_TASKBAR_H
+
+void khm_init_taskbar_funcs(void);
+
+void khm_exit_taskbar_funcs(void);
+
+void khm_taskbar_add_window(HWND hwnd);
+
+void khm_taskbar_remove_window(HWND hwnd);
+
+#endif
diff --git a/src/windows/identity/ui/timer.c b/src/windows/identity/ui/timer.c
index 3adf9e9..7024481 100644
--- a/src/windows/identity/ui/timer.c
+++ b/src/windows/identity/ui/timer.c
@@ -256,8 +256,21 @@ tmr_fire_timer(void) {
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_REQUEST_BALLOON);
+ 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);
}
diff --git a/src/windows/identity/ui/toolbar.c b/src/windows/identity/ui/toolbar.c
index f3781b9..a464009 100644
--- a/src/windows/identity/ui/toolbar.c
+++ b/src/windows/identity/ui/toolbar.c
@@ -106,6 +106,28 @@ LRESULT khm_toolbar_notify(LPNMHDR notice) {
}
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;
@@ -156,11 +178,14 @@ LRESULT khm_toolbar_notify(LPNMHDR notice) {
return CDRF_DODEFAULT;
CopyRect(&r, &(nmcd->nmcd.rc));
- r.left += ((r.right - r.left) -
- KHUI_TOOLBAR_IMAGE_WIDTH) / 2;
+ 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,
@@ -317,17 +342,12 @@ void khm_create_standard_toolbar(HWND rebar) {
return;
}
- hwtb = CreateWindowEx(0
-#if (_WIN32_IE >= 0x0501)
- | TBSTYLE_EX_MIXEDBUTTONS
-#endif
- ,
+ hwtb = CreateWindowEx(0 ,
TOOLBARCLASSNAME,
(LPWSTR) NULL,
WS_CHILD |
TBSTYLE_FLAT |
TBSTYLE_AUTOSIZE |
- TBSTYLE_LIST |
TBSTYLE_TOOLTIPS |
CCS_NORESIZE |
CCS_NOPARENTALIGN |
@@ -344,6 +364,11 @@ void khm_create_standard_toolbar(HWND rebar) {
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,
@@ -395,7 +420,9 @@ void khm_create_standard_toolbar(HWND rebar) {
act = khui_find_action(aref->action);
khui_add_action_to_toolbar(hwtb,
act,
- KHUI_TOOLBAR_ADD_BITMAP,
+ KHUI_TOOLBAR_ADD_BITMAP |
+ ((aref->flags & KHUI_ACTIONREF_SUBMENU)?
+ KHUI_TOOLBAR_ADD_DROPDOWN: 0),
hiList);
}
aref ++;
diff --git a/src/windows/identity/ui/toolbar.h b/src/windows/identity/ui/toolbar.h
index 89700f2..8068a6b 100644
--- a/src/windows/identity/ui/toolbar.h
+++ b/src/windows/identity/ui/toolbar.h
@@ -37,12 +37,12 @@ void khui_add_action_to_toolbar(HWND toolbar, khui_action * act, int opt, HIMAGE
void khm_update_standard_toolbar(void);
/* options for khui_add_action_to_toolbar */
-#define KHUI_TOOLBAR_ADD_TEXT 1
-#define KHUI_TOOLBAR_ADD_BITMAP 2
-#define KHUI_TOOLBAR_ADD_LONGTEXT 5
-#define KHUI_TOOLBAR_ADD_DROPDOWN 8
-#define KHUI_TOOLBAR_ADD_SEP 16
-#define KHUI_TOOLBAR_VARSIZE 32
+#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
diff --git a/src/windows/identity/ui/uiconfig.csv b/src/windows/identity/ui/uiconfig.csv
index 9f5e5e4..2013048 100644
--- a/src/windows/identity/ui/uiconfig.csv
+++ b/src/windows/identity/ui/uiconfig.csv
@@ -6,6 +6,7 @@ CredWindow,KC_SPACE,0,Options for the credentials window
AutoDetectNet,KC_INT32,1,Automatically detect network connectivity changes
KeepRunning,KC_INT32,1,Keep running after closing Khimaira
DefaultView,KC_STRING,ByIdentity,
+ DefaultViewMini,KC_STRING,CompactIdentity,
ViewList,KC_STRING,"ByIdentity,ByLocation,ByType",
PaddingHorizontal,KC_INT32,4,
PaddingVertical,KC_INT32,2,
@@ -26,17 +27,28 @@ CredWindow,KC_SPACE,0,Options for the credentials window
MinThreshold,KC_INT32,10,Min value for a threshold (0)
LogToFile,KC_INT32,0,Boolean. If true logs trace events to a nidmdbg.log in the temp folder
DestroyCredsOnExit,KC_INT32,0,Boolean. If true; all credentials will be destroyed when NetIDMgr exits.
+ NotificationAction,KC_INT32,50025,Action to perform when the user clicks on the notification icon.
+ DefaultWindowMode,KC_INT32,1,(0-normal; 1-mini)
Windows,KC_SPACE,0,Window parameters
_Schema,KC_SPACE,0,Schema
Width,KC_INT32,0,
Height,KC_INT32,0,
XPos,KC_INT32,0,
YPos,KC_INT32,0,
+ Dock,KC_INT32,0,Dock on window corner (0-none; 1-top left; 2-top right; 3-bottom right; 4-bottom left)
_Schema,KC_ENDSPACE,0,
Main,KC_SPACE,0,Main window
Main,KC_ENDSPACE,0,
+ MainMini,KC_SPACE,0,Main window (mini mode)
+ Width,KC_INT32,470,
+ Height,KC_INT32,500,
+ Dock,KC_INT32,3,
+ MainMini,KC_ENDSPACE,0,
NewCred,KC_SPACE,0,New credentials window
ForceToTop,KC_INT32,1,Force new creds window to the top
+ AnimateSizeChanges,KC_INT32,1,Animate the new creds window when the size needs changing.
+ AnimationSteps,KC_INT32,7,Number of steps in size-change animation
+ AnimationStepTimeout,KC_INT32,40,Number of milliseconds to wait between each step of the size-change animation
NewCred,KC_ENDSPACE,0,
Windows,KC_ENDSPACE,0,
Views,KC_SPACE,0,Preconfigured views for credentials
@@ -166,6 +178,32 @@ CredWindow,KC_SPACE,0,Options for the credentials window
TimeLeft,KC_ENDSPACE,0
Columns,KC_ENDSPACE,0
ByLocation,KC_ENDSPACE,0
+ CompactIdentity,KC_SPACE,0,Default Compact View by Identity
+ Description,KC_STRING,Compact view of identities
+ ColumnList,KC_STRING,"IdentityName",
+ ExpandedIdentity,KC_INT32,1,Use expanded display of identity headers
+ NoHeader,KC_INT32,1,Suppress the column header
+ Columns,KC_SPACE,0,
+ IdentityName,KC_SPACE,0,
+ Width,KC_INT32,415,
+ SortIndex,KC_INT32,0,
+ Flags,KC_INT32,171
+ IdentityName,KC_ENDSPACE,0,
+ Columns,KC_ENDSPACE,0,
+ CompactIdentity,KC_ENDSPACE,0
+ Custom_1,KC_SPACE,0,Default Compact View by Identity
+ Description,KC_STRING,Compact view of identities
+ ColumnList,KC_STRING,"IdentityName",
+ ExpandedIdentity,KC_INT32,1,Use expanded display of identity headers
+ NoHeader,KC_INT32,1,Suppress the column header
+ Columns,KC_SPACE,0,
+ IdentityName,KC_SPACE,0,
+ Width,KC_INT32,415,
+ SortIndex,KC_INT32,0,
+ Flags,KC_INT32,171
+ IdentityName,KC_ENDSPACE,0,
+ Columns,KC_ENDSPACE,0,
+ Custom_1,KC_ENDSPACE,0
Views,KC_ENDSPACE,0
Notices,KC_SPACE,0,Notices and alerts
MinimizeWarning,KC_INT32,1,Show the minimize warning?
diff --git a/src/windows/identity/uilib/Makefile b/src/windows/identity/uilib/Makefile
index 6a9fb53..5686db5 100644
--- a/src/windows/identity/uilib/Makefile
+++ b/src/windows/identity/uilib/Makefile
@@ -52,7 +52,8 @@ INCFILES= \
$(INCDIR)\khconfigui.h \
$(INCDIR)\khtracker.h \
$(INCDIR)\khremote.h \
- $(INCDIR)\intaction.h
+ $(INCDIR)\intaction.h \
+ $(INCDIR)\intalert.h
$(OBJ)\actiondef.c: actions.csv actiondef.cfg
$(CCSV) $** $@
diff --git a/src/windows/identity/uilib/accel.csv b/src/windows/identity/uilib/accel.csv
index f95e89b..2984eba 100644
--- a/src/windows/identity/uilib/accel.csv
+++ b/src/windows/identity/uilib/accel.csv
@@ -22,4 +22,5 @@ KHUI_ACTION_NEW_CRED,FCONTROL|FVIRTKEY,\'N\',KHUI_ACCEL_SCOPE_GLOBAL
KHUI_ACTION_RENEW_CRED,FCONTROL|FVIRTKEY,\'R\',KHUI_ACCEL_SCOPE_GLOBAL
KHUI_ACTION_IMPORT,FCONTROL|FVIRTKEY,\'I\',KHUI_ACCEL_SCOPE_GLOBAL
KHUI_ACTION_DESTROY_CRED,FCONTROL|FVIRTKEY,\'D\',KHUI_ACCEL_SCOPE_GLOBAL
+KHUI_ACTION_LAYOUT_MINI,FVIRTKEY,VK_F7,KHUI_ACCEL_SCOPE_GLOBAL
KHUI_PACTION_SELALL,FCONTROL|FVIRTKEY,\'A\',KHUI_ACCEL_SCOPE_GLOBAL
diff --git a/src/windows/identity/uilib/action.c b/src/windows/identity/uilib/action.c
index e387268..ae017e1 100644
--- a/src/windows/identity/uilib/action.c
+++ b/src/windows/identity/uilib/action.c
@@ -52,9 +52,9 @@ khui_action_ref khui_menu_file[] = {
khui_action_ref khui_menu_cred[] = {
MENU_ACTION(KHUI_ACTION_NEW_CRED),
MENU_SEP(),
- MENU_ACTION(KHUI_ACTION_RENEW_CRED),
+ MENU_SUBMENU(KHUI_MENU_RENEW_CRED),
MENU_ACTION(KHUI_ACTION_IMPORT),
- MENU_ACTION(KHUI_ACTION_DESTROY_CRED),
+ MENU_SUBMENU(KHUI_MENU_DESTROY_CRED),
MENU_SEP(),
MENU_ACTION(KHUI_ACTION_SET_DEF_ID),
#if 0
@@ -80,6 +80,7 @@ khui_action_ref khui_menu_toolbars[] = {
};
khui_action_ref khui_menu_view[] = {
+ MENU_ACTION(KHUI_ACTION_LAYOUT_MINI),
MENU_SUBMENU(KHUI_MENU_COLUMNS),
MENU_SUBMENU(KHUI_MENU_LAYOUT),
#if 0
@@ -109,7 +110,6 @@ khui_action_ref khui_menu_options[] = {
khui_action_ref khui_menu_help[] = {
MENU_ACTION(KHUI_ACTION_HELP_CTX),
MENU_SEP(),
- MENU_ACTION(KHUI_ACTION_HELP_CONTENTS),
MENU_ACTION(KHUI_ACTION_HELP_INDEX),
MENU_SEP(),
MENU_ACTION(KHUI_ACTION_HELP_ABOUT),
@@ -118,9 +118,9 @@ khui_action_ref khui_menu_help[] = {
khui_action_ref khui_toolbar_standard[] = {
MENU_ACTION(KHUI_ACTION_NEW_CRED),
- MENU_ACTION(KHUI_ACTION_RENEW_CRED),
+ MENU_SUBMENU(KHUI_ACTION_RENEW_CRED),
MENU_ACTION(KHUI_ACTION_IMPORT),
- MENU_ACTION(KHUI_ACTION_DESTROY_CRED),
+ MENU_SUBMENU(KHUI_ACTION_DESTROY_CRED),
MENU_SEP(),
MENU_ACTION(KHUI_ACTION_PASSWD_ID),
MENU_SEP(),
@@ -156,8 +156,14 @@ khui_action_ref khui_menu_ico_ctx_min[] = {
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()
};
@@ -167,8 +173,14 @@ khui_action_ref khui_menu_ico_ctx_normal[] = {
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()
};
@@ -261,6 +273,21 @@ 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,
@@ -273,7 +300,8 @@ khui_action_create(const wchar_t * name,
int i;
size_t s;
- if (!caption ||
+ 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)) {
@@ -350,29 +378,36 @@ khui_action_create(const wchar_t * name,
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)
- return NULL;
+ if (act == NULL || (act->state & KHUI_ACTIONSTATE_DELETED))
+ data = NULL;
else
- return act->data;
+ 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)
+ 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. */
- EnterCriticalSection(&cs_actions);
act->state |= KHUI_ACTIONSTATE_DELETED;
if (act->name)
PFREE(act->name);
@@ -470,6 +505,8 @@ khui_menu_dup(khui_menu_def * src)
size_t i;
size_t n;
+ EnterCriticalSection(&cs_actions);
+
d = khui_menu_create(src->cmd);
if (!(src->state & KHUI_MENUSTATE_ALLOCD))
@@ -485,6 +522,8 @@ khui_menu_dup(khui_menu_def * src)
}
}
+ LeaveCriticalSection(&cs_actions);
+
return d;
}
@@ -504,13 +543,13 @@ khui_menu_delete(khui_menu_def * d)
}
EnterCriticalSection(&cs_actions);
+
for (i=0; i < khui_n_cust_menus; i++) {
if (khui_cust_menus[i] == d) {
khui_cust_menus[i] = NULL;
break;
}
}
- LeaveCriticalSection(&cs_actions);
for(i=0; i< (int) d->n_items; i++) {
if(d->items[i].flags & KHUI_ACTIONREF_FREE_PACTION)
@@ -520,6 +559,8 @@ khui_menu_delete(khui_menu_def * d)
if(d->items)
PFREE(d->items);
PFREE(d);
+
+ LeaveCriticalSection(&cs_actions);
}
static void
@@ -563,6 +604,10 @@ menu_const_to_allocd(khui_menu_def * d)
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);
@@ -584,15 +629,29 @@ khui_menu_insert_action(khui_menu_def * d, khm_size idx, khm_int32 action, khm_i
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);
@@ -611,50 +670,81 @@ khui_menu_insert_paction(khui_menu_def * d, khm_size idx, khui_action * 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)
- return;
+ 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--;
- 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)
- return d->n_items;
+ size = d->n_items;
else
- return khui_action_list_length(d->items);
+ 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)
- return NULL;
+ act = NULL;
+ else
+ act = &d->items[idx];
+
+ LeaveCriticalSection(&cs_actions);
- return &d->items[idx];
+ return act;
}
KHMEXP khui_menu_def * KHMAPI
@@ -663,6 +753,9 @@ khui_find_menu(khm_int32 id) {
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)
@@ -707,7 +800,7 @@ khui_find_action(khm_int32 id) {
#ifdef DEBUG
assert(!act || act->cmd == id);
#endif
- if (act && act->state & KHUI_ACTIONSTATE_DELETED)
+ if (act && (act->state & KHUI_ACTIONSTATE_DELETED))
act = NULL;
}
LeaveCriticalSection(&cs_actions);
@@ -732,30 +825,43 @@ khui_find_named_action(const wchar_t * 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)
- return NULL;
- else
- return pact[i];
+
+ if (!(pact[i]->state & KHUI_ACTIONSTATE_DELETED)) {
+ act = pact[i];
+ }
+ break;
}
}
- return NULL;
+ 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;
}
@@ -765,6 +871,8 @@ 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)) {
@@ -783,6 +891,8 @@ khui_check_radio_action(khui_menu_def * d, khm_int32 cmd)
r++;
}
+ LeaveCriticalSection(&cs_actions);
+
kmq_post_message(KMSG_ACT, KMSG_ACT_CHECK, 0, 0);
}
@@ -794,12 +904,18 @@ khui_check_action(khm_int32 cmd, khm_boolean check) {
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
+ else {
+ LeaveCriticalSection(&cs_actions);
return;
+ }
+
+ LeaveCriticalSection(&cs_actions);
kmq_post_message(KMSG_ACT, KMSG_ACT_CHECK, 0, 0);
}
@@ -811,6 +927,8 @@ khui_enable_actions(khui_menu_def * d, khm_boolean enable)
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)) {
@@ -834,6 +952,8 @@ khui_enable_actions(khui_menu_def * d, khm_boolean enable)
r++;
}
+ LeaveCriticalSection(&cs_actions);
+
if(delta) {
kmq_post_message(KMSG_ACT, KMSG_ACT_ENABLE, 0, 0);
}
@@ -847,12 +967,18 @@ khui_enable_action(khm_int32 cmd, khm_boolean enable) {
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
+ } else {
+ LeaveCriticalSection(&cs_actions);
return;
+ }
+
+ LeaveCriticalSection(&cs_actions);
kmq_post_message(KMSG_ACT, KMSG_ACT_ENABLE, 0, 0);
}
@@ -972,6 +1098,14 @@ khui_get_cmd_accel_string(khm_int32 cmd,
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;
@@ -1356,12 +1490,8 @@ khui_context_refresh(void) {
if (khui_ctx.scope != KHUI_SCOPE_NONE) {
khui_enable_action(KHUI_ACTION_PROPERTIES, TRUE);
- khui_enable_action(KHUI_ACTION_DESTROY_CRED, TRUE);
- khui_enable_action(KHUI_ACTION_RENEW_CRED, TRUE);
} else {
khui_enable_action(KHUI_ACTION_PROPERTIES, FALSE);
- khui_enable_action(KHUI_ACTION_DESTROY_CRED, FALSE);
- khui_enable_action(KHUI_ACTION_RENEW_CRED, FALSE);
}
LeaveCriticalSection(&cs_actions);
diff --git a/src/windows/identity/uilib/actiondef.cfg b/src/windows/identity/uilib/actiondef.cfg
index 0627a67..5613352 100644
--- a/src/windows/identity/uilib/actiondef.cfg
+++ b/src/windows/identity/uilib/actiondef.cfg
@@ -33,6 +33,7 @@ Do not modify directly.
#include<khuidefs.h>
#include<khhelp.h>
+#include<intaction.h>
#include"../ui/resource.h"
khui_action khui_actions [] = {
diff --git a/src/windows/identity/uilib/actions.csv b/src/windows/identity/uilib/actions.csv
index 88ac440..36a43df 100644
--- a/src/windows/identity/uilib/actions.csv
+++ b/src/windows/identity/uilib/actions.csv
@@ -21,6 +21,7 @@ KHUI_ACTION_LAYOUT_ID,KHUI_ACTIONTYPE_TRIGGER | KHUI_ACTIONTYPE_TOGGLE,,0,0,0,0,
KHUI_ACTION_LAYOUT_TYPE,KHUI_ACTIONTYPE_TRIGGER | KHUI_ACTIONTYPE_TOGGLE,,0,0,0,0,0,IDS_ACTION_LAYOUT_TYPE,0,0,0
KHUI_ACTION_LAYOUT_LOC,KHUI_ACTIONTYPE_TRIGGER | KHUI_ACTIONTYPE_TOGGLE,,0,0,0,0,0,IDS_ACTION_LAYOUT_LOC,0,0,0
KHUI_ACTION_LAYOUT_CUST,KHUI_ACTIONTYPE_TRIGGER | KHUI_ACTIONTYPE_TOGGLE,,0,0,0,0,0,IDS_ACTION_LAYOUT_CUST,0,0,0
+KHUI_ACTION_LAYOUT_MINI,KHUI_ACTIONTYPE_TRIGGER | KHUI_ACTIONTYPE_TOGGLE,,0,0,0,0,0,IDS_ACTION_LAYOUT_MINI,0,0,0
KHUI_ACTION_TB_STANDARD,KHUI_ACTIONTYPE_TRIGGER | KHUI_ACTIONTYPE_TOGGLE,,0,0,0,0,0,IDS_ACTION_TB_STANDARD,0,0,KHUI_ACTIONSTATE_CHECKED|KHUI_ACTIONSTATE_DISABLED
KHUI_ACTION_DEBUG_WINDOW,KHUI_ACTIONTYPE_TRIGGER,,0,0,0,0,0,IDS_ACTION_DEBUG_WINDOW,0,IDH_ACTION_DEBUG_WINDOW,KHUI_ACTIONSTATE_DISABLED
KHUI_ACTION_VIEW_REFRESH,KHUI_ACTIONTYPE_TRIGGER,,IDB_VW_REFRESH,0,0,IDB_VW_REFRESH_SM,0,IDS_ACTION_VIEW_REFRESH,IDS_ACTIONT_VIEW_REFRESH,IDH_ACTION_VIEW_REFRESH,0
diff --git a/src/windows/identity/uilib/alert.c b/src/windows/identity/uilib/alert.c
index 9643654..e398690 100644
--- a/src/windows/identity/uilib/alert.c
+++ b/src/windows/identity/uilib/alert.c
@@ -26,6 +26,7 @@
#include<khuidefs.h>
#include<utils.h>
+#include<intalert.h>
#include<assert.h>
#include<strsafe.h>
@@ -62,7 +63,11 @@ khui_alert_create_empty(khui_alert ** result)
/* 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);
@@ -253,6 +258,57 @@ khui_alert_add_command(khui_alert * alert, khm_int32 command_id)
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)
{
@@ -347,6 +403,9 @@ free_alert(khui_alert * alert)
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;
diff --git a/src/windows/identity/uilib/creddlg.c b/src/windows/identity/uilib/creddlg.c
index 1d36d3c..c89a446 100644
--- a/src/windows/identity/uilib/creddlg.c
+++ b/src/windows/identity/uilib/creddlg.c
@@ -418,6 +418,9 @@ cw_free_prompts(khui_new_creds * c)
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);
diff --git a/src/windows/identity/uilib/intaction.h b/src/windows/identity/uilib/intaction.h
index 2b4a66a..44348b9 100644
--- a/src/windows/identity/uilib/intaction.h
+++ b/src/windows/identity/uilib/intaction.h
@@ -41,4 +41,68 @@ typedef struct tag_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/intalert.h b/src/windows/identity/uilib/intalert.h
new file mode 100644
index 0000000..dc4fbc6
--- /dev/null
+++ b/src/windows/identity/uilib/intalert.h
@@ -0,0 +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_KHALERTS_H_INTERNAL
+#define __KHIMAIRA_KHALERTS_H_INTERNAL
+
+#include<khalerts.h>
+#include<khaction.h>
+
+/*! \addtogroup khui_alert
+
+@{ */
+
+/*! \internal
+
+ \brief An alert
+
+ Describes an alert message that will be shown to the user in a
+ variety of ways depending on the state of the NetIDMgr
+ application.
+ */
+typedef struct tag_khui_alert {
+ khm_int32 magic;
+ /*!< Magic number. Always set to
+ KHUI_ALERT_MAGIC */
+
+ khm_int32 severity;
+ /*!< The severity of the alert. One
+ of KHERR_ERROR, KHERR_WARNING or
+ KHERR_INFO. The default is
+ KHERR_INFO. Do not set directly.
+ Use khui_alert_set_severity(). */
+
+ khm_int32 alert_commands[KHUI_MAX_ALERT_COMMANDS];
+ /*!< The command buttons associated
+ with the alert. Use
+ khui_alert_add_command() to add a
+ command. The buttons will appear in
+ the order in which they were added.
+ The first button will be the
+ default. Each command should be a
+ known action identifier. */
+ khm_int32 n_alert_commands;
+ /*!< The number of commands in
+ alert_commands[]. */
+
+ wchar_t * title; /*!< The title of the alert. Subject
+ to ::KHUI_MAXCCH_TITLE. Use
+ khui_alert_set_title() to set. Do
+ not modify directly. */
+
+ wchar_t * message;
+ /*!< The main message of the alert.
+ Subject to ::KHUI_MAXCCH_MESSAGE.
+ Use khui_alert_set_message() to set.
+ Do not modify direcly. */
+
+ wchar_t * suggestion;
+ /*!< A suggestion. Appears below the
+ message text. Use
+ khui_alert_set_suggestion() to set.
+ Do not modify directly. */
+
+ khm_int32 flags; /*!< combination of
+ ::khui_alert_flags. Do not modify
+ directly. */
+
+ kherr_context * err_context;
+ /*!< If non-NULL at the time the alert
+ window is shown, this indicates that
+ the alert window should provide an
+ error viewer for the given error
+ context. */
+
+ kherr_event * err_event;
+ /*!< If non-NULL at the time the alert
+ window is shown, this indicates that
+ the alert window should provide an
+ error viewer for the given error
+ event. If an \a err_context is also
+ given, the error viewer for the
+ context will be below this error. */
+
+ khui_alert_type alert_type;
+ /*!< The type of alert. */
+
+ khui_action_context ctx; /*!< Context to which this alert
+ applies to. */
+
+ khm_int32 response;
+ /*!< Once the alert is displayed to
+ the user, when the user clicks one
+ of the command buttons, the command
+ ID will be assigned here. */
+
+ int refcount;
+ /*!< internal */
+
+ khm_boolean displayed;
+ /*!< TRUE when then the alert is being
+ displayed on screen. Also used
+ internally to determine when to
+ terminate the modal loop */
+
+ LDCL(struct tag_khui_alert);
+ /*!< internal */
+} khui_alert;
+
+#define KHUI_ALERT_MAGIC 0x48c39ce9
+
+/*@}*/
+
+#endif
diff --git a/src/windows/identity/uilib/khaction.h b/src/windows/identity/uilib/khaction.h
index e8f6cd6..92fa7b0 100644
--- a/src/windows/identity/uilib/khaction.h
+++ b/src/windows/identity/uilib/khaction.h
@@ -32,64 +32,8 @@
/*! \defgroup khui_actions 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;
+struct tag_khui_action;
+typedef struct tag_khui_action khui_action;
/*! \brief Unknown action type
@@ -221,6 +165,11 @@ typedef struct tag_khui_action_ref {
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
@@ -343,6 +292,40 @@ extern int khui_n_all_menus;
/* 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
@@ -408,11 +391,10 @@ khui_menu_delete(khui_menu_def * d);
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.
-
- \note The ::khui_menu_def structure is not thread safe. Multiple
- threads modifying the same ::khui_menu_def structure may cause
- thread safety issues.
+ 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);
@@ -445,11 +427,10 @@ khui_menu_insert_action(khui_menu_def * d, khm_size idx, khm_int32 cmd, khm_int3
::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.
-
- \note The ::khui_menu_def structure is not thread safe. Multiple
- threads modifying the same ::khui_menu_def structure may cause
- thread safety issues.
+ 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);
@@ -485,9 +466,6 @@ khui_menu_get_size(khui_menu_def * d);
If the specified index is out of bounds, then the function returns
NULL.
- \note The ::khui_menu_def structure is not thread safe. Multiple
- threads modifying the same ::khui_menu_def structure may cause
- thread safety issues.
*/
KHMEXP khui_action_ref *
khui_menu_get_action(khui_menu_def * d, khm_size idx);
@@ -887,9 +865,28 @@ KHMEXP size_t KHMAPI khui_action_list_length(khui_action_ref * ref);
/*! \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)
+ 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
@@ -900,11 +897,7 @@ KHMEXP size_t KHMAPI khui_action_list_length(khui_action_ref * ref);
by KHUI_MAXCCH_SHORT_DESC) (Optional, set to NULL if there is
no tooltip associated with the action)
- \param[in] hsub The subscription that is notified when the action
- is triggered. (Optional) The subscription can be created with
- kmq_create_subscription(). The handle will be released when
- it is no longer needed. Hence, the caller should not release
- it.
+ \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
@@ -912,7 +905,11 @@ KHMEXP size_t KHMAPI khui_action_list_length(khui_action_ref * ref);
initial state will be unchecked. Use khui_check_action()
function to change the checked state of the action.
- \param[in] userdata A custom value.
+ \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.
diff --git a/src/windows/identity/uilib/khactiondef.h b/src/windows/identity/uilib/khactiondef.h
index 31866ba..87e2355 100644
--- a/src/windows/identity/uilib/khactiondef.h
+++ b/src/windows/identity/uilib/khactiondef.h
@@ -69,6 +69,7 @@
#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
diff --git a/src/windows/identity/uilib/khalerts.h b/src/windows/identity/uilib/khalerts.h
index f10ffa1..7f0e624 100644
--- a/src/windows/identity/uilib/khalerts.h
+++ b/src/windows/identity/uilib/khalerts.h
@@ -37,86 +37,10 @@
/*!\defgroup khui_alert Alerter and Error Reporting
@{*/
-#define KHUI_MAX_ALERT_COMMANDS 4
-
-/*! \brief An alert
-
- Describes an alert message that will be shown to the user in a
- variety of ways depending on the state of the NetIDMgr
- application.
- */
-typedef struct tag_khui_alert {
- khm_int32 magic; /*!< Magic number. Always set to
- KHUI_ALERT_MAGIC */
-
- khm_int32 severity; /*!< The severity of the alert. One
- of KHERR_ERROR, KHERR_WARNING or
- KHERR_INFO. The default is
- KHERR_INFO. Do not set directly.
- Use khui_alert_set_severity(). */
-
- khm_int32 alert_commands[KHUI_MAX_ALERT_COMMANDS];
- /*!< The command buttons associated
- with the alert. Use
- khui_alert_add_command() to add a
- command. The buttons will appear in
- the order in which they were added.
- The first button will be the
- default. Each command should be a
- known action identifier. */
- khm_int32 n_alert_commands;
-
- wchar_t * title; /*!< The title of the alert. Subject
- to ::KHUI_MAXCCH_TITLE. Use
- khui_alert_set_title() to set. Do
- not modify directly. */
-
- wchar_t * message; /*!< The main message of the alert.
- Subject to ::KHUI_MAXCCH_MESSAGE.
- Use khui_alert_set_message() to
- set. Do not modify direcly. */
-
- wchar_t * suggestion; /*!< A suggestion. Appears below
- the message text. Use
- khui_alert_set_suggestion() to
- set. Do not modify directly. */
-
-#ifdef _WIN32
- POINT target;
-#endif
-
- khm_int32 flags; /*!< combination of
- ::khui_alert_flags. Do not modify
- directly. */
-
- kherr_context * err_context;
- /*!< If non-NULL at the time the alert
- window is shown, this indicates that
- the alert window should provide an
- error viewer for the given error
- context. */
-
- kherr_event * err_event;
- /*!< If non-NULL at the time the alert
- window is shown, this indicates that
- the alert window should provide an
- error viewer for the given error
- event. If an \a err_context is also
- given, the error viewer for the
- context will be below this error. */
-
- khm_int32 response;
- /*!< Once the alert is displayed to
- the user, when the user clicks one
- of the command buttons, the command
- ID will be assigned here. */
+struct tag_khui_alert;
+typedef struct tag_khui_alert khui_alert;
- int refcount; /* internal */
-
- LDCL(struct tag_khui_alert); /* internal */
-} khui_alert;
-
-#define KHUI_ALERT_MAGIC 0x48c39ce9
+#define KHUI_MAX_ALERT_COMMANDS 4
/*! \brief Maximum number of characters in title including terminating NULL
*/
@@ -161,11 +85,19 @@ enum khui_alert_flags {
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,
- /*!< There is a valid target for the alert */
+ /*!< Internal. There is a valid target for the alert */
KHUI_ALERT_FLAG_VALID_ERROR =0x00020000,
- /*!< There is a valid error context associated with the alert */
+ /*!< 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 */
@@ -180,12 +112,33 @@ enum khui_alert_flags {
/*!< The alert should be displayed in a balloon */
KHUI_ALERT_FLAG_MODAL =0x10000000,
- /*!< Modal alert. Do not set direclty. */
+ /*!< Internal. Modal alert. Do not set direclty. */
- KHUI_ALERT_FLAGMASK_RDWR =0x0C000010,
+ 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.
@@ -267,12 +220,39 @@ khui_alert_clear_commands(khui_alert * alert);
/*! \brief Add a command to an alert object
- The command ID should be a valid registered command.
+ 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
@@ -294,8 +274,8 @@ khui_alert_add_command(khui_alert * alert,
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 have the same effect as
- choosing the first command in the action.
+ 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
@@ -305,6 +285,32 @@ khui_alert_add_command(khui_alert * alert,
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);
@@ -317,7 +323,6 @@ khui_alert_show(khui_alert * alert);
This function always opens an alert window (never shows a
balloon).
- \note Should only be called from the UI thread.
*/
KHMEXP khm_int32 KHMAPI
khui_alert_show_modal(khui_alert * alert);
@@ -377,7 +382,7 @@ khui_alert_release(khui_alert * alert);
disallows access to all other alerts as well.
\note Calling khui_alert_lock() is only necessary if you are
- modifying the ::khui_alert structure directly. Calling any of
+ 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.
diff --git a/src/windows/identity/uilib/khnewcred.h b/src/windows/identity/uilib/khnewcred.h
index 1785d59..e22e1f7 100644
--- a/src/windows/identity/uilib/khnewcred.h
+++ b/src/windows/identity/uilib/khnewcred.h
@@ -69,7 +69,8 @@
*/
enum khui_wm_nc_notifications {
WMNC_DIALOG_EXPAND = 1,
- /*!< The dialog is getting expanded.
+ /*!< 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
@@ -146,6 +147,10 @@ enum khui_wm_nc_notifications {
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
@@ -551,13 +556,6 @@ typedef struct tag_khui_new_creds_by_type {
/*! \brief Height of a new creds dialog panel in dialog units*/
#define NCDLG_HEIGHT 166
-/*! \brief Width of the button bar in dialog units */
-#define NCDLG_BBAR_WIDTH 60
-/*! \brief Height of a tab button in dialog units */
-#define NCDLG_TAB_HEIGHT 15
-/*! \brief Width of a tab button in dialog units */
-#define NCDLG_TAB_WIDTH 60
-
/*! \brief A custom prompt */
typedef struct tag_khui_new_creds_prompt {
khm_size index; /*!< Set to the zero based index
@@ -944,7 +942,7 @@ khui_cw_set_response(khui_new_creds * c,
/*! \brief Check whether a specified credential type panel succeeded
- This is called during the processing of KMSG_CRED_DIALOG_PROCESS
+ 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
diff --git a/src/windows/identity/uilib/khuidefs.h b/src/windows/identity/uilib/khuidefs.h
index 845f781..9b38556 100644
--- a/src/windows/identity/uilib/khuidefs.h
+++ b/src/windows/identity/uilib/khuidefs.h
@@ -37,7 +37,6 @@
#include<khaction.h>
#include<khactiondef.h>
-#include<khrescache.h>
#include<khhtlink.h>
#include<khnewcred.h>
#include<khprops.h>
@@ -45,6 +44,10 @@
#include<khconfigui.h>
#include<khtracker.h>
+#ifdef NOEXPORT
+#include<khrescache.h>
+#endif
+
#include<khremote.h>
/*! \internal */
@@ -115,9 +118,23 @@ typedef khm_int32
any windows it wishes to create and interact with the user
directly.
- Note that 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.
+ 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
*/
diff --git a/src/windows/identity/uilib/rescache.c b/src/windows/identity/uilib/rescache.c
index 6d52591..b84608a 100644
--- a/src/windows/identity/uilib/rescache.c
+++ b/src/windows/identity/uilib/rescache.c
@@ -24,6 +24,8 @@
/* $Id$ */
+#define NOEXPORT
+
#include<khuidefs.h>
#include<utils.h>
diff --git a/src/windows/identity/uilib/uibind.c b/src/windows/identity/uilib/uibind.c
index ac5e136..11da4e4 100644
--- a/src/windows/identity/uilib/uibind.c
+++ b/src/windows/identity/uilib/uibind.c
@@ -53,6 +53,7 @@ khui_request_UI_callback(khm_ui_callback cb, void * rock) {
MAKEWPARAM(KHUI_ACTION_UICB, 0),
(LPARAM) &cbdata);
- return KHM_ERROR_SUCCESS;
+ return cbdata.rv;
}
+
diff --git a/src/windows/identity/util/Makefile b/src/windows/identity/util/Makefile
index 9d1cad2..97aff0e 100644
--- a/src/windows/identity/util/Makefile
+++ b/src/windows/identity/util/Makefile
@@ -45,4 +45,4 @@ SDKLIBFILES=
all: mkdirs $(INCFILES) $(OBJFILES)
clean::
- $(RM) $(INCFILES)
+ if exist '..\obj' $(RM) $(INCFILES) \ No newline at end of file
diff --git a/src/windows/identity/util/hashtable.c b/src/windows/identity/util/hashtable.c
index 1a4233d..ddf7b1b 100644
--- a/src/windows/identity/util/hashtable.c
+++ b/src/windows/identity/util/hashtable.c
@@ -63,10 +63,13 @@ KHMEXP void KHMAPI hash_del_hashtable(hashtable * h) {
}
}
+ if (h->bins)
+ PFREE(h->bins);
+
PFREE(h);
}
-KHMEXP void KHMAPI hash_add(hashtable * h, void * key, void * data) {
+KHMEXP void KHMAPI hash_add(hashtable * h, const void * key, void * data) {
int hv;
hash_bin * b;
@@ -97,7 +100,7 @@ KHMEXP void KHMAPI hash_add(hashtable * h, void * key, void * data) {
}
}
-KHMEXP void KHMAPI hash_del(hashtable * h, void * key) {
+KHMEXP void KHMAPI hash_del(hashtable * h, const void * key) {
hash_bin * b;
int hv;
@@ -117,7 +120,7 @@ KHMEXP void KHMAPI hash_del(hashtable * h, void * key) {
}
}
-KHMEXP void * KHMAPI hash_lookup(hashtable * h, void * key) {
+KHMEXP void * KHMAPI hash_lookup(hashtable * h, const void * key) {
hash_bin * b;
int hv;
@@ -135,7 +138,7 @@ KHMEXP void * KHMAPI hash_lookup(hashtable * h, void * key) {
return NULL;
}
-KHMEXP khm_boolean KHMAPI hash_exist(hashtable * h, void * key) {
+KHMEXP khm_boolean KHMAPI hash_exist(hashtable * h, const void * key) {
hash_bin * b;
int hv;
diff --git a/src/windows/identity/util/hashtable.h b/src/windows/identity/util/hashtable.h
index fc7d829..1a3fb4b 100644
--- a/src/windows/identity/util/hashtable.h
+++ b/src/windows/identity/util/hashtable.h
@@ -83,7 +83,7 @@ typedef void (*del_ref_function_t)(const void *key, void *data);
typedef struct tag_hash_bin {
void * data;
- void * key;
+ const void * key;
LDCL(struct tag_hash_bin);
} hash_bin;
@@ -147,7 +147,7 @@ KHMEXP void KHMAPI hash_del_hashtable(hashtable * h);
\note Not thread-safe. Applications must serialize calls that
reference the same hashtable.
*/
-KHMEXP void KHMAPI hash_add(hashtable * h, void * key, void * data);
+KHMEXP void KHMAPI hash_add(hashtable * h, const void * key, void * data);
/*! \brief Delete an object from a hashtable
@@ -161,7 +161,7 @@ KHMEXP void KHMAPI hash_add(hashtable * h, void * key, void * data);
\note Not thread-safe. Applications must serialize calls that
reference the same hashtable.
*/
-KHMEXP void KHMAPI hash_del(hashtable * h, void * key);
+KHMEXP void KHMAPI hash_del(hashtable * h, const void * key);
/*! \brief Resolve and association
@@ -175,7 +175,7 @@ KHMEXP void KHMAPI hash_del(hashtable * h, void * key);
\note Not thread-safe. Applications must serialize calls that
reference the same hashtable.
*/
-KHMEXP void * KHMAPI hash_lookup(hashtable * h, void * key);
+KHMEXP void * KHMAPI hash_lookup(hashtable * h, const void * key);
/*! \brief Check for the presence of an association
@@ -190,7 +190,7 @@ KHMEXP void * KHMAPI hash_lookup(hashtable * h, void * key);
\note Not thead-safe. Application must serialize calls that
reference the same hashtable.
*/
-KHMEXP khm_boolean KHMAPI hash_exist(hashtable * h, void * key);
+KHMEXP khm_boolean KHMAPI hash_exist(hashtable * h, const void * key);
/*! \brief Compute a hashvalue for a unicode string
@@ -202,6 +202,10 @@ KHMEXP khm_boolean KHMAPI hash_exist(hashtable * h, void * key);
\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);
@@ -214,6 +218,10 @@ KHMEXP khm_int32 hash_string(const void *str);
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);
diff --git a/src/windows/identity/util/perfstat.c b/src/windows/identity/util/perfstat.c
index 4d7e8fa..cc27d93 100644
--- a/src/windows/identity/util/perfstat.c
+++ b/src/windows/identity/util/perfstat.c
@@ -37,7 +37,7 @@
#define HASHPTR(p) (((size_t) (p)) % HASHSIZE)
typedef struct tag_allocation {
- char file[8];
+ const char * file;
int line;
size_t size;
void * ptr;
@@ -54,10 +54,49 @@ 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);
@@ -68,9 +107,18 @@ static void perf_once(void) {
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 {
- while(!perf_ready) {
+ DWORD this_thread = GetCurrentThreadId();
+
+ while(!perf_ready &&
+ init_thread != this_thread) {
Sleep(0); /* relinquish control to the thread
that is initializing the alloc
data. */
@@ -99,7 +147,7 @@ static allocation * get_allocation(void) {
#define MAXCB_STR 32768
KHMEXP wchar_t *
-perf_wcsdup(char * file, int line, const wchar_t * str) {
+perf_wcsdup(const char * file, int line, const wchar_t * str) {
size_t cb;
wchar_t * dest;
@@ -114,7 +162,7 @@ perf_wcsdup(char * file, int line, const wchar_t * str) {
}
KHMEXP char *
-perf_strdup(char * file, int line, const char * str) {
+perf_strdup(const char * file, int line, const char * str) {
size_t cb;
char * dest;
@@ -129,7 +177,7 @@ perf_strdup(char * file, int line, const char * str) {
}
KHMEXP void *
-perf_calloc(char * file, int line, size_t num, size_t size) {
+perf_calloc(const char * file, int line, size_t num, size_t size) {
void * ptr;
size_t tsize;
@@ -145,10 +193,11 @@ perf_calloc(char * file, int line, size_t num, size_t size) {
}
KHMEXP void *
-perf_malloc(char * file, int line, size_t s) {
+perf_malloc(const char * file, int line, size_t s) {
allocation * a;
void * ptr;
size_t h;
+ char * fn_copy = NULL;
perf_once();
@@ -164,7 +213,33 @@ perf_malloc(char * file, int line, size_t s) {
if (file[0] == '.' && file[1] == '\\')
file += 2;
- StringCbCopyA(a->file, sizeof(a->file), file);
+ 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;
@@ -181,7 +256,7 @@ perf_malloc(char * file, int line, size_t s) {
}
KHMEXP void *
-perf_realloc(char * file, int line, void * data, size_t s) {
+perf_realloc(const char * file, int line, void * data, size_t s) {
void * n_data;
allocation * a;
size_t h;
@@ -237,41 +312,100 @@ perf_free (void * b) {
LeaveCriticalSection(&cs_alloc);
}
-KHMEXP void
-perf_dump(char * file) {
- FILE * f;
+KHMEXP void KHMAPI
+perf_dump(FILE * f) {
size_t i;
allocation * a;
size_t total = 0;
+ thread_info * t;
perf_once();
EnterCriticalSection(&cs_alloc);
-#if _MSC_VER >= 1400
- if (fopen_s(&f, file, "w"))
- return;
-#else
- f = fopen(file, "w");
- if (!f)
- return;
-#endif
- fprintf(f, "Leaked allocations list ....\n");
- fprintf(f, "File\tLine\tThread\tSize\n");
+ 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, "%s\t%6d\t%6d\t%6d\n", a->file, a->line,
- a->thread, a->size);
+ 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, "----------------------------------------\n");
- fprintf(f, "Total\t\t%d\n", total);
- fprintf(f, "----------------- End ------------------\n");
+ 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);
+ }
+ }
+ }
- fclose(f);
+ 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 d8d5951..a4a0f27 100644
--- a/src/windows/identity/util/perfstat.h
+++ b/src/windows/identity/util/perfstat.h
@@ -37,6 +37,7 @@
#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)
@@ -45,27 +46,29 @@
#define PDUMP(f) ((void) 0)
#define PWCSDUP(s) wcsdup(s)
#define PSTRDUP(s) strdup(s)
+#define PDESCTHREAD(n,c)
#endif
KHMEXP void *
-perf_malloc(char * file, int line, size_t s);
+perf_malloc(const char * file, int line, size_t s);
KHMEXP void *
-perf_realloc(char * file, int line, void * data, size_t s);
+perf_realloc(const char * file, int line, void * data, size_t s);
KHMEXP void
perf_free (void * b);
-KHMEXP void
-perf_dump (char * filename);
-
KHMEXP wchar_t *
-perf_wcsdup(char * file, int line, const wchar_t * str);
+perf_wcsdup(const char * file, int line, const wchar_t * str);
KHMEXP char *
-perf_strdup(char * file, int line, const char * str);
+perf_strdup(const char * file, int line, const char * str);
KHMEXP void *
-perf_calloc(char * file, int line, size_t num, size_t size);
+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/installer/nsis/kfw-fixed.nsi b/src/windows/installer/nsis/kfw-fixed.nsi
index c61f5a1..df80187 100644
--- a/src/windows/installer/nsis/kfw-fixed.nsi
+++ b/src/windows/installer/nsis/kfw-fixed.nsi
@@ -1,7 +1,7 @@
;-----------------------------------------------------------------
; KfW defines and functionality
-; Copyright (c) 2004 Massachusetts Institute of Technology
-; Copyright (c) 2006 Secure Endpoints Inc.
+; Copyright (c) 2004,2005,2006,2007 Massachusetts Institute of Technology
+; Copyright (c) 2006,2007 Secure Endpoints Inc.
!define KFW_VERSION "${KFW_MAJORVERSION}.${KFW_MINORVERSION}.${KFW_PATCHLEVEL}"
@@ -30,10 +30,10 @@ Name "MIT ${PROGRAM_NAME} ${KFW_VERSION} ${__DATE__} ${__TIME__} Checked/Debug"
VIProductVersion "${KFW_MAJORVERSION}.${KFW_MINORVERSION}.${KFW_PATCHLEVEL}.00"
VIAddVersionKey "ProductName" "${PROGRAM_NAME}"
VIAddVersionKey "CompanyName" "Massachusetts Institute of Technology"
-VIAddVersionKey "ProductVersion" ${VIProductVersion}
-VIAddVersionKey "FileVersion" ${VIProductVersion}
+VIAddVersionKey "FileVersion" ${VIProductVersion}
+VIAddVersionKey "ProductVersion" "${KFW_MAJORVERSION}.${KFW_MINORVERSION}.${KFW_PATCHLEVEL}.0"
VIAddVersionKey "FileDescription" "MIT Kerberos for Windows Installer"
-VIAddVersionKey "LegalCopyright" "(C)2004,2005,2006"
+VIAddVersionKey "LegalCopyright" "(C)2004,2005,2006,2007"
!ifdef DEBUG
VIAddVersionKey "PrivateBuild" "Checked/Debug"
!endif ; End DEBUG
@@ -146,9 +146,9 @@ VIAddVersionKey "PrivateBuild" "Checked/Debug"
LangString REINSTALL_DOCS ${LANG_ENGLISH} "Re-install Kerberos Documentation"
LangString DOWNGRADE_DOCS ${LANG_ENGLISH} "Downgrade Kerberos Documentation"
- ReserveFile "${KFW_CONFIG_DIR}\krb.con"
- ReserveFile "${KFW_CONFIG_DIR}\krbrealm.con"
- ReserveFile "${KFW_CONFIG_DIR}\krb5.ini"
+ ReserveFile "${KFW_CONFIG_DIR}\sample\krb.con"
+ ReserveFile "${KFW_CONFIG_DIR}\sample\krbrealm.con"
+ ReserveFile "${KFW_CONFIG_DIR}\sample\krb5.ini"
!insertmacro MUI_RESERVEFILE_INSTALLOPTIONS ;InstallOptions plug-in
!insertmacro MUI_RESERVEFILE_LANGDLL ;Language selection dialog
@@ -188,9 +188,6 @@ Section "KfW Client" secClient
; Do client components
SetOutPath "$INSTDIR\bin"
-!ifdef AKLOG
- !insertmacro ReplaceDLL "${KFW_BIN_DIR}\aklog.exe" "$INSTDIR\bin\aklog.exe" "$INSTDIR"
-!endif
!insertmacro ReplaceDLL "${KFW_BIN_DIR}\comerr32.dll" "$INSTDIR\bin\comerr32.dll" "$INSTDIR"
!insertmacro ReplaceDLL "${KFW_BIN_DIR}\gss.exe" "$INSTDIR\bin\gss.exe" "$INSTDIR"
!insertmacro ReplaceDLL "${KFW_BIN_DIR}\gss-client.exe" "$INSTDIR\bin\gss-client.exe" "$INSTDIR"
@@ -447,9 +444,6 @@ skipAllowTgtKey:
WriteRegDWORD HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\kinit" "Flags" 0x408
WriteRegDWORD HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\klist" "Flags" 0x408
WriteRegDWORD HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\kdestroy" "Flags" 0x408
-!ifdef AKLOG
- WriteRegDWORD HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\aklog" "Flags" 0x408
-!endif
WriteRegDWORD HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\gss" "Flags" 0x408
WriteRegDWORD HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\gss-client" "Flags" 0x408
WriteRegDWORD HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\gss-server" "Flags" 0x408
@@ -469,9 +463,6 @@ SectionEnd
Section "Debug Symbols" secDebug
SetOutPath "$INSTDIR\bin"
-!ifdef AKLOG
- File "${KFW_BIN_DIR}\aklog.pdb"
-!endif
File "${KFW_BIN_DIR}\comerr32.pdb"
File "${KFW_BIN_DIR}\gss.pdb"
File "${KFW_BIN_DIR}\gss-client.pdb"
@@ -1147,9 +1138,6 @@ StartRemove:
Delete "$INSTDIR\doc\netidmgr_userdoc.pdf"
Delete "$INSTDIR\doc\netiddev.chm"
-!ifdef AKLOG
- Delete /REBOOTOK "$INSTDIR\bin\aklog.exe"
-!endif
Delete /REBOOTOK "$INSTDIR\bin\comerr32.dll"
Delete /REBOOTOK "$INSTDIR\bin\gss.exe"
Delete /REBOOTOK "$INSTDIR\bin\gss-client.exe"
@@ -1185,9 +1173,6 @@ StartRemove:
Delete /REBOOTOK "$SYSDIR\bin\kfwlogon.dll"
Delete /REBOOTOK "$SYSDIR\bin\kfwcpcc.exe"
-!ifdef AKLOG
- Delete /REBOOTOK "$INSTDIR\bin\aklog.pdb"
-!endif
Delete /REBOOTOK "$INSTDIR\bin\comerr32.pdb"
Delete /REBOOTOK "$INSTDIR\bin\gss.pdb"
Delete /REBOOTOK "$INSTDIR\bin\gss-client.pdb"
@@ -1344,9 +1329,6 @@ StartRemove:
DeleteRegKey HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\kinit"
DeleteRegKey HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\klist"
DeleteRegKey HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\kdestroy"
-!ifdef AKLOG
- DeleteRegKey HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\aklog"
-!endif
DeleteRegKey HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\gss"
DeleteRegKey HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\gss-client"
DeleteRegKey HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\gss-server"
@@ -1424,9 +1406,9 @@ DoDownload:
UsePackaged:
SetOutPath "$WINDIR"
- File "${KFW_CONFIG_DIR}\krb5.ini"
- File "${KFW_CONFIG_DIR}\krb.con"
- File "${KFW_CONFIG_DIR}\krbrealm.con"
+ File "${KFW_CONFIG_DIR}\sample\krb5.ini"
+ File "${KFW_CONFIG_DIR}\sample\krb.con"
+ File "${KFW_CONFIG_DIR}\sample\krbrealm.con"
goto done
CheckOther:
diff --git a/src/windows/installer/nsis/nsi-includes-tagged.nsi b/src/windows/installer/nsis/nsi-includes-tagged.nsi
new file mode 100644
index 0000000..acf77c0
--- /dev/null
+++ b/src/windows/installer/nsis/nsi-includes-tagged.nsi
@@ -0,0 +1,8 @@
+!define KFW_TARGETDIR %BUILDDIR%\target
+!define KFW_EXTRADIR "%BUILDDIR%\target"
+!define KFW_VERSION %VERSION_MAJOR%.%VERSION_MINOR%
+!define KFW_MAJORVERSION %VERSION_MAJOR%
+!define KFW_MINORVERSION %VERSION_MINOR%
+!define KFW_PATCHLEVEL %VERSION_PATCH%
+!define CL_1310
+
diff --git a/src/windows/installer/nsis/nsi-includes.nsi b/src/windows/installer/nsis/nsi-includes.nsi
deleted file mode 100644
index bc1c4c7..0000000
--- a/src/windows/installer/nsis/nsi-includes.nsi
+++ /dev/null
@@ -1,8 +0,0 @@
-!define KFW_TARGETDIR c:\temp\kfw\kfw-3.1.0-alpha
-!define KFW_EXTRADIR c:\temp\kfw\kfw-2.5-extra
-!define KFW_VERSION 3.1
-!define KFW_MAJORVERSION 3
-!define KFW_MINORVERSION 1
-!define KFW_PATCHLEVEL 0000
-!define CL_1310
-
diff --git a/src/windows/installer/nsis/site-local-tagged.nsi b/src/windows/installer/nsis/site-local-tagged.nsi
new file mode 100644
index 0000000..26ad541
--- /dev/null
+++ b/src/windows/installer/nsis/site-local-tagged.nsi
@@ -0,0 +1,13 @@
+!define KFW_TARGETDIR %TARGETDIR%
+!define KFW_CONFIG_DIR %CONFIGDIR-NSI%
+!define KFW_MAJORVERSION %VERSION_MAJOR%
+!define KFW_MINORVERSION %VERSION_MINOR%
+!define KFW_PATCHLEVEL %VERSION_PATCH%
+!define CL_1310
+
+!define RELEASE
+!define NOT_DEBUG
+!define BETA 1
+!define SAMPLE_CONFIG_REALM "ATHENA.MIT.EDU"
+!define HTTP_CONFIG_URL "[Obtain a URL from your Kerberos administrator]"
+
diff --git a/src/windows/installer/nsis/site-local.nsi b/src/windows/installer/nsis/site-local.nsi
deleted file mode 100644
index 13e5dce..0000000
--- a/src/windows/installer/nsis/site-local.nsi
+++ /dev/null
@@ -1,13 +0,0 @@
-!define KFW_TARGETDIR c:\temp\kfw\kfw-3.1.0-alpha
-!define KFW_CONFIG_DIR "c:\temp\kfw\kfw-2.5-extra\sample-config"
-!define KFW_MAJORVERSION 3
-!define KFW_MINORVERSION 1
-!define KFW_PATCHLEVEL 0
-!define CL_1310
-
-!define RELEASE
-!define NOT_DEBUG
-!define BETA 1
-!define SAMPLE_CONFIG_REALM "ATHENA.MIT.EDU"
-!define HTTP_CONFIG_URL "[Obtain a URL from your Kerberos administrator]"
-
diff --git a/src/windows/installer/wix/files.wxi b/src/windows/installer/wix/files.wxi
index 5fc0966..aa37d79 100644
--- a/src/windows/installer/wix/files.wxi
+++ b/src/windows/installer/wix/files.wxi
@@ -29,12 +29,12 @@
<Directory Id="SystemFolder" SourceName="System">
<Component Id="cmf_kfwlogon_DLL" Guid="2F104FEB-2D61-458A-BAE3-B153F151E728">
<File Id="filekfwlogon_DLL" Name="kfwlogon.dll" LongName="kfwlogon.dll" KeyPath="yes" DiskId="1" src="$(var.BinDir)kfwlogon.dll" />
- <Registry Id="reg_kfwlogon01" Root="HKLM" Key="SOFTWARE\Microsoft\Windows NT\CurrentVersion\WinLogon\Notify\KFWLogon" Action="createKeyAndRemoveKeyOnUninstall" />
- <Registry Id="reg_kfwlogon02" Root="HKLM" Key="SOFTWARE\Microsoft\Windows NT\CurrentVersion\WinLogon\Notify\KFWLogon" />
- <Registry Id="reg_kfwlogon03" Root="HKLM" Key="SOFTWARE\Microsoft\Windows NT\CurrentVersion\WinLogon\Notify\KFWLogon" Name="Asynchronous" Type="integer" Value="0" />
- <Registry Id="reg_kfwlogon04" Root="HKLM" Key="SOFTWARE\Microsoft\Windows NT\CurrentVersion\WinLogon\Notify\KFWLogon" Name="Impersonate" Type="integer" Value="0" />
- <Registry Id="reg_kfwlogon05" Root="HKLM" Key="SOFTWARE\Microsoft\Windows NT\CurrentVersion\WinLogon\Notify\KFWLogon" Name="DLLName" Type="string" Value="[#filekfwlogon_DLL]" />
- <Registry Id="reg_kfwlogon06" Root="HKLM" Key="SOFTWARE\Microsoft\Windows NT\CurrentVersion\WinLogon\Notify\KFWLogon" Name="Logon" Type="string" Value="KFW_Logon_Event" />
+ <Registry Id="reg_kfwlogon01" Root="HKLM" Key="SOFTWARE\Microsoft\Windows NT\CurrentVersion\WinLogon\Notify\MIT_KFW" Action="createKeyAndRemoveKeyOnUninstall" />
+ <Registry Id="reg_kfwlogon02" Root="HKLM" Key="SOFTWARE\Microsoft\Windows NT\CurrentVersion\WinLogon\Notify\MIT_KFW" />
+ <Registry Id="reg_kfwlogon03" Root="HKLM" Key="SOFTWARE\Microsoft\Windows NT\CurrentVersion\WinLogon\Notify\MIT_KFW" Name="Asynchronous" Type="integer" Value="0" />
+ <Registry Id="reg_kfwlogon04" Root="HKLM" Key="SOFTWARE\Microsoft\Windows NT\CurrentVersion\WinLogon\Notify\MIT_KFW" Name="Impersonate" Type="integer" Value="0" />
+ <Registry Id="reg_kfwlogon05" Root="HKLM" Key="SOFTWARE\Microsoft\Windows NT\CurrentVersion\WinLogon\Notify\MIT_KFW" Name="DLLName" Type="string" Value="[#filekfwlogon_DLL]" />
+ <Registry Id="reg_kfwlogon06" Root="HKLM" Key="SOFTWARE\Microsoft\Windows NT\CurrentVersion\WinLogon\Notify\MIT_KFW" Name="Logon" Type="string" Value="KFW_Logon_Event" />
<Registry Id="reg_kfwlogon07" Root="HKLM" Key="SYSTEM\CurrentControlSet\Services\MIT Kerberos\NetworkProvider" Action="createKeyAndRemoveKeyOnUninstall" />
<Registry Id="reg_kfwlogon08" Root="HKLM" Key="SYSTEM\CurrentControlSet\Services\MIT Kerberos\NetworkProvider" Name="AuthentProviderPath" Type="expandable" Value="[SystemFolder]kfwlogon.dll"/>
<Registry Id="reg_kfwlogon09" Root="HKLM" Key="SYSTEM\CurrentControlSet\Services\MIT Kerberos\NetworkProvider"/>
@@ -777,7 +777,8 @@
<File Id="fil_KfWConfigPage2_ini" LongName="KfWConfigPage2.ini" Name="KFWCONP2.INI" />
<File Id="fil_killer_cpp" LongName="killer.cpp" Name="killer.cpp" />
<File Id="fil_licenses_rtf" LongName="licenses.rtf" Name="licenses.rtf" />
- <File Id="fil_site_local_nsi" LongName="site-local.nsi" Name="SITE-LCN.NSI" />
+ <File Id="fil_site_local_nsi" LongName="site-local-tagged.nsi" Name="SITE-LCN.NSI" />
+ <File Id="fil_nsi_incl" LongName="nsi-includes-tagged.nsi" Name="NSI-INCL.NSI" />
<File Id="fil_utils_nsi" LongName="utils.nsi" Name="utils.nsi" />
</Component>
</Directory>
@@ -789,7 +790,7 @@
<File Id="fil_kfw_wxs" LongName="kfw.wxs" Name="kfw.wxs" KeyPath="yes" />
<File Id="fil_Makefile_" LongName="Makefile" Name="Makefile" />
<File Id="fil_property_wxi" LongName="property.wxi" Name="property.wxi" />
- <File Id="fil_site_local_wxi" LongName="site-local.wxi" Name="SITE-LCL.WXI" />
+ <File Id="fil_site_local_wxi" LongName="site-local-tagged.wxi" Name="SITE-LCL.WXI" />
</Component>
<Directory Id="dirinstall_wix_lang" Name="lang" src="$(var.InstallDir)wix\lang\">
<Component Id="cmp_dirinstall_wix_lang" Guid="70741A69-1103-4B54-B146-2E14C271945D" DiskId="1">
diff --git a/src/windows/installer/wix/msi-deployment-guide.txt b/src/windows/installer/wix/msi-deployment-guide.txt
index 7085d18..8270a9f 100644
--- a/src/windows/installer/wix/msi-deployment-guide.txt
+++ b/src/windows/installer/wix/msi-deployment-guide.txt
@@ -481,6 +481,45 @@ Kerberos for Windows
Registry key : 'Software\MIT\NetIDMgr\CredWindow'
--------------
+ Value : AllowAutoRenew
+ Type : DWORD (Boolean)
+ Default : 1
+
+ Enables automatic credential renewal.
+
+
+ Value : AllowCritical
+ Type : DWORD (Boolean)
+ Default : 1
+
+ Enables critical warning notifications.
+
+
+ Value : AllowWarn
+ Type : DWORD (Boolean)
+ Default : 1
+
+ Enables warning notifications.
+
+
+ Value : AutoDetectNet
+ Type : DWORD (0 or 1)
+ Default : 1
+
+ If '1', automatically detects network connectivity changes.
+ Network connectivity change notifications are then sent out to
+ individual plug-ins which can perform actions such as renewing
+ credentials or obtaining new credentials.
+
+
+ Value : AutoImport
+ Type : DWORD (0 or 1)
+ Default : 1
+
+ If '1', imports credentials from the Windows LSA cache when
+ NetIDMgr starts.
+
+
Value : AutoInit
Type : DWORD (0 or 1)
Default : 0
@@ -488,21 +527,52 @@ Kerberos for Windows
If this value is '1', shows the new credentials dialog if
there are no credentials when NetIDMgr starts.
- Value : AutoImport
+
+ Value : AutoStart
+ Type : DWORD (0 or 1)
+ Default : 0
+
+ Start NetIDMgr when Windows starts
+
+
+ Value : AutoRenewThreshold
+ Type : DWORD (seconds)
+ Default : 600
+
+ Specifies the time period before credential expiration that will
+ trigger a credential renewal. Requires AllowAutoRenew to be enabled.
+
+
+ Value : CriticalThreshold
+ Type : DWORD (seconds)
+ Default : 300
+
+ Specifies the time period before credential expiration that will
+ trigger the second and final warning balloon. Requires AllowCritical
+ to be enabled.
+
+
+ Value : DefaultAllowAutoRenew
+ Type : DWORD (Boolean)
+ Default : 1
+
+ Specifies the Default AllowAutoRenew value for new identities.
+
+
+ Value : DefaultSticky
Type : DWORD (0 or 1)
Default : 1
- If '1', imports credentials from the Windows LSA cache when
- NetIDMgr starts.
+ If '0', new identities will not be pinned to the display by default.
+ If '1', new identities will be pinned to the display by default.
- Value : AutoDetectNet
+
+ Value : DefaultWindowMode
Type : DWORD (0 or 1)
Default : 1
- If '1', automatically detects network connectivity changes.
- Network connectivity change notifications are then sent out to
- individual plug-ins which can perform actions such as renewing
- credentials or obtaining new credentials.
+ If '0', Advanced mode is used
+ If '1', Basic mode is used
Value : DestroyCredsOnExit
Type : DWORD (0 or 1)
@@ -520,6 +590,45 @@ Kerberos for Windows
option. If '0', closing the application will cause it to
exit completely.
+ Value : LogToFile
+ Type : DWORD (0 or 1)
+ Default : 0
+
+ If '1', debugging information is logged to %TEMP%\nidmdbg.log
+
+
+ Value : NotificationAction
+ Type : DWORD (50008 or 50025)
+ Default : 50025
+
+ If '50025', the default notification icon menu action will be to
+ Show the Network Identity Manager application windows.
+ If '50008', the default notification icon menu action will be to
+ display the Obtain New Credentials dialog.
+
+
+ Value : RefreshTimeout
+ Type : DWORD (seconds)
+ Default : 60
+
+ Specifies how often the credential list is refreshed.
+
+
+ Value : RenewAtHalfLife
+ Type : DWORD (Boolean)
+ Default : 1
+
+ Enables the use of a half-life algorithm for credential renewals.
+
+
+ Value : WarnThreshold
+ Type : DWORD (seconds)
+ Default : 900
+
+ Specifies the time period before credential expiration that will
+ trigger the first warning balloon. Requires AllowWarn to be enabled.
+
+
3.1.2 Common Plug-in settings
Registry key : 'Software\MIT\NetIDMgr\PluginManager\Plugins\<plug-in name>'
@@ -555,6 +664,14 @@ Kerberos for Windows
Registry key : 'Software\MIT\NetIDMgr\PluginManager\Plugins\Krb5Cred\Parameters'
--------------
+ Value : AutoRenewTickets
+ Type : DWORD (0 or 1)
+ Default : 1
+
+ If '1', automatically renews expiring tickets. The thresholds
+ at which renewals happen are controlled in general NetIDMgr
+ settings.
+
Value : CreateMissingConfig
Type : DWORD (0 or 1)
Default : 0
@@ -585,13 +702,6 @@ Kerberos for Windows
If '1', includes credentials from the MSLSA cache in the
credentials listing.
- Value : AutoRenewTickets
- Type : DWORD (0 or 1)
- Default : 1
-
- If '1', automatically renews expiring tickets. The thresholds
- at which renewals happen are controlled in general NetIDMgr
- settings.
Value : UseFullRealmList
Type : DWORD (0 or 1)
@@ -602,6 +712,7 @@ Kerberos for Windows
If this is '0', only the last recently used list of realms
will be used.
+
3.1.3.1 Per-identity settings
Registry key 1: 'Software\MIT\NetIDMgr\KCDB\Identity\<principal name>\Krb5Cred'
@@ -616,12 +727,38 @@ Kerberos for Windows
turn. Global defaults should be set in the global parameters key
(key 3).
+ Value : Addressless
+ Type : DWORD (boolean)
+ Default : 1
+
+ Determines if addressless tickets will be obtained for new identities.
+
+
Value : DefaultLifetime
Type : DWORD
Default : 36000
Default ticket lifetime, in seconds.
+ Value : DefaultRenewLifetime
+ Type : DWORD
+ Default : 604800
+
+ Default renewable lifetime, in seconds.
+
+ Value : FileCCList
+ Type : SZ
+ Default : <not specified>
+
+ Specifies a comma delimited list of FILE credential caches to monitor
+ for credentials.
+
+ Value : Forwardable
+ Type : DWORD (0 or 1)
+ Default : 0
+
+ Obtain forwardable tickets.
+
Value : MaxLifetime
Type : DWORD
Default : 86400
@@ -630,6 +767,14 @@ Kerberos for Windows
range of the user interface controls that allow setting the
lifetime of a ticket.
+ Value : MaxRenewLifetime
+ Type : DWORD
+ Default : 2592000
+
+ Maximum renewable lifetime, in seconds. The value is used to
+ set the range of the user interface controls that allow
+ setting the renewable lifetime of a ticket.
+
Value : MinLifetime
Type : DWORD
Default : 60
@@ -638,11 +783,13 @@ Kerberos for Windows
range of the user interface controls that allow setting the
lifetime of a ticket.
- Value : Forwardable
- Type : DWORD (0 or 1)
- Default : 0
+ Value : MinRenewLifetime
+ Type : DWORD
+ Default : 60
- Obtain forwardable tickets.
+ Minimum renewable lifetime, in seconds. This value is used to
+ set the range of the user interface controls that allow
+ setting the renewable lifetime of a ticket.
Value : Proxiable
Type : DWORD (0 or 1)
@@ -650,39 +797,12 @@ Kerberos for Windows
Obtain proxiable tickets.
- Value : Addressless
- Type : DWORD (0 or 1)
- Default : 1
-
- Obtain addressless tickets.
-
Value : Renewable
Type : DWORD (0 or 1)
Default : 1
Obtain renewable tickets.
- Value : DefaultRenewLifetime
- Type : DWORD
- Default : 604800
-
- Default renewable lifetime, in seconds.
-
- Value : MaxRenewLifetime
- Type : DWORD
- Default : 2592000
-
- Maximum renewable lifetime, in seconds. The value is used to
- set the range of the user interface controls that allow
- setting the renewable lifetime of a ticket.
-
- Value : MinRenewLifetime
- Type : DWORD
- Default : 60
-
- Minimum renewable lifetime, in seconds. This value is used to
- set the range of the user interface controls that allow
- setting the renewable lifetime of a ticket.
3.1.4 Settings for the Kerberos 4 Credentials Provider Plug-in
diff --git a/src/windows/installer/wix/site-local.wxi b/src/windows/installer/wix/site-local-tagged.wxi
index 2e27082..2b48e50 100644
--- a/src/windows/installer/wix/site-local.wxi
+++ b/src/windows/installer/wix/site-local-tagged.wxi
@@ -1,99 +1,105 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Include xmlns="http://schemas.microsoft.com/wix/2003/01/wi">
-
- <!-- User configurable options -->
-
- <!-- TargetDir should point to build target directory and must end with
- a backslash. If not specified, assume we are in TargetDir\install -->
-
- <?define TargetDir="c:\temp\kfw\kfw-3.1.0-alpha\"?>
-
- <!-- ConfigDir should point to directory containing configuration files
- (krb5.ini, krb.con, krbrealm.con) to be bundled with the installer.
- The directory name should end with a backslash. -->
-
- <?define ConfigDir="c:\temp\kfw\kfw-2.5-extra\sample-config\"?>
-
- <!-- VersionMajor, VersionMinor and VersionPatch must all be specified, or
- none should be specified (in which case, the defaults will be
- selected below. -->
-
- <!-- version defs go here -->
-
- <!-- BuildLang is the language code for the installation. If you are
- changing this, you should also change the ProductCode below. -->
- <?ifndef BuildLang?>
- <?define BuildLang="1033"?>
- <?endif?>
-
- <!-- ProductCode is an uppercase GUID. Each release should have its
- own ProductCode. If one is not defined, we generate a random one. -->
- <?ifndef ProductCode?>
- <?define ProductCode="????????-????-????-????-????????????"?>
- <?endif?>
-
- <!-- DefaultRealm, is your default realm. Must be uppercase -->
- <?define DefaultRealm="ATHENA.MIT.EDU"?>
-
- <!-- One of the following must be defined and must correspond to the
- version of compiler used for building Kerberos for Windows -->
-
- <!-- <?define CL1200?> -->
- <!-- <?define CL1300?> -->
- <?define CL1310?>
- <!-- <?define CL1400?> -->
-
- <!-- At most one of the following could be defined and must correspond
- to the type of build performed. -->
- <!-- <?define Debug?> -->
- <?define Release?>
-
- <!-- We are including debug symbols anyway. Undefine this for a leaner
- installer without debug syms. -->
- <?define DebugSyms?>
-
- <!-- Optional defines -->
- <?define Beta="1"?> <!-- Numeric Beta identifier -->
- <!-- <?define OldHelp?> --> <!-- Specifies the use of the old leash32.hlp file
- instead of the new leash32.chm file -->
-
-
- <!-- End of user configurable options -->
-
- <!-- Assert that required options are defined, or select defaults if
- they weren't -->
-
- <?ifndef TargetDir?>
- <?define TargetDir="$(sys.SOURCEFILEDIR)..\"?>
- <?endif?>
-
- <?ifndef ConfigDir?>
- <?define ConfigDir="$(env.SystemRoot)\"?>
- <?endif?>
-
- <?ifndef VersionMajor?>
- <?define VersionMajor="3"?>
- <?define VersionMinor="1"?>
- <?define VersionPatch="0"?>
- <?else?>
- <?if Not ($(var.VersionMinor) And $(var.VersionPatch))?>
- <?error VersionMajor, VersionMinor and VersionPatch should be specified together?>
- <?endif?>
- <?endif?>
-
- <?ifndef ProductCode?>
- <?error Must define ProductCode?>
- <?endif?>
-
- <?ifndef BuildLang?>
- <?error Must define BuildLang?>
- <?endif?>
-
- <!-- DefaultRealm. Must be uppercase. -->
- <?ifndef DefaultRealm?>
- <?error Must define DefaultRealm?>
- <?endif?>
-
- <!-- The build makefile defines 'Date' and 'Time' which are strings that
- identify the time at which the build was performed. -->
+<?xml version="1.0" encoding="utf-8"?>
+<Include xmlns="http://schemas.microsoft.com/wix/2003/01/wi">
+
+ <!-- User configurable options -->
+
+ <!-- Items enclosed in double percent marks will be substituted by
+ the build script. -->
+
+ <!-- TargetDir should point to build target directory and must end with
+ a backslash. If not specified, assume we are in TargetDir\install -->
+
+ <?define TargetDir="%TARGETDIR%\"?>
+
+ <!-- ConfigDir should point to directory containing configuration files
+ (krb5.ini, krb.con, krbrealm.con) to be bundled with the installer.
+ The directory name should end with a backslash. -->
+
+ <?define ConfigDir="%CONFIGDIR-WIX%\"?>
+
+ <!-- VersionMajor, VersionMinor and VersionPatch must all be specified, or
+ none should be specified (in which case, the defaults will be
+ selected below. -->
+
+ <!-- version defs go here -->
+ <?define VersionMajor="%VERSION_MAJOR%"?>
+ <?define VersionMinor="%VERSION_MINOR%"?>
+ <?define VersionPatch="%VERSION_PATCH%"?>
+
+ <!-- BuildLang is the language code for the installation. If you are
+ changing this, you should also change the ProductCode below. -->
+ <?ifndef BuildLang?>
+ <?define BuildLang="1033"?>
+ <?endif?>
+
+ <!-- ProductCode is an uppercase GUID. Each release should have its
+ own ProductCode. If one is not defined, we generate a random one. -->
+ <?ifndef ProductCode?>
+ <?define ProductCode="????????-????-????-????-????????????"?>
+ <?endif?>
+
+ <!-- DefaultRealm, is your default realm. Must be uppercase -->
+ <?define DefaultRealm="ATHENA.MIT.EDU"?>
+
+ <!-- One of the following must be defined and must correspond to the
+ version of compiler used for building Kerberos for Windows -->
+
+ <!-- <?define CL1200?> -->
+ <!-- <?define CL1300?> -->
+ <?define CL1310?>
+ <!-- <?define CL1400?> -->
+
+ <!-- At most one of the following could be defined and must correspond
+ to the type of build performed. -->
+ <!-- <?define Debug?> -->
+ <?define Release?>
+
+ <!-- We are including debug symbols anyway. Undefine this for a leaner
+ installer without debug syms. -->
+ <?define DebugSyms?>
+
+ <!-- Optional defines -->
+ <?define Beta="1"?> <!-- Numeric Beta identifier -->
+ <!-- <?define OldHelp?> --> <!-- Specifies the use of the old leash32.hlp file
+ instead of the new leash32.chm file -->
+
+
+ <!-- End of user configurable options -->
+
+ <!-- Assert that required options are defined, or select defaults if
+ they weren't -->
+
+ <?ifndef TargetDir?>
+ <?define TargetDir="$(sys.SOURCEFILEDIR)..\"?>
+ <?endif?>
+
+ <?ifndef ConfigDir?>
+ <?define ConfigDir="$(env.SystemRoot)\"?>
+ <?endif?>
+
+ <?ifndef VersionMajor?>
+ <?define VersionMajor="3"?>
+ <?define VersionMinor="2"?>
+ <?define VersionPatch="0"?>
+ <?else?>
+ <?if Not ($(var.VersionMinor) And $(var.VersionPatch))?>
+ <?error VersionMajor, VersionMinor and VersionPatch should be specified together?>
+ <?endif?>
+ <?endif?>
+
+ <?ifndef ProductCode?>
+ <?error Must define ProductCode?>
+ <?endif?>
+
+ <?ifndef BuildLang?>
+ <?error Must define BuildLang?>
+ <?endif?>
+
+ <!-- DefaultRealm. Must be uppercase. -->
+ <?ifndef DefaultRealm?>
+ <?error Must define DefaultRealm?>
+ <?endif?>
+
+ <!-- The build makefile defines 'Date' and 'Time' which are strings that
+ identify the time at which the build was performed. -->
</Include> \ No newline at end of file
diff --git a/src/windows/kfwlogon/Makefile.in b/src/windows/kfwlogon/Makefile.in
index 96562ec..0d7fcc5 100644
--- a/src/windows/kfwlogon/Makefile.in
+++ b/src/windows/kfwlogon/Makefile.in
@@ -13,21 +13,29 @@ LOCALINCLUDES = -I$(BUILDTOP) -I$(PISMERE)\athena\util\loadfuncs \
PROG_LIBPATH=-L$(TOPLIBD) -L$(KRB5_LIBDIR)
SYSLIBS = kernel32.lib user32.lib advapi32.lib wsock32.lib secur32.lib userenv.lib
-RFLAGS = $(LOCALINCLUDES)
-RCFLAGS = $(RFLAGS) -D_WIN32
-all-windows:: $(OUTPRE)kfwlogon.dll $(OUTPRE)kfwcpcc.exe
+VERSIONRC = $(BUILDTOP)\windows\version.rc
+RCFLAGS=$(CPPFLAGS) -I$(SRCTOP) -D_WIN32 -DRES_ONLY
+
+KFWLOGON=$(OUTPRE)kfwlogon.dll
+KFWCPCC=$(OUTPRE)kfwcpcc.exe
-$(OUTPRE)kfwlogon.res: kfwlogon.rc ..\version.rc
+LIBRES=$(KFWLOGON:.dll=.res)
+EXERES=$(KFWCPCC:.exe=.res)
-$(OUTPRE)kfwcpcc.res: kfwcpcc.rc ..\version.rc
+$(LIBRES): $(VERSIONRC)
+ $(RC) $(RCFLAGS) -DKFWLOGON_LIB -fo $@ -r $**
+$(EXERES): $(VERSIONRC)
+ $(RC) $(RCFLAGS) -DKFWCPCC_APP -fo $@ -r $**
+
+all-windows:: $(OUTPRE)kfwlogon.dll $(OUTPRE)kfwcpcc.exe
-$(OUTPRE)kfwlogon.dll: $(OUTPRE)kfwlogon.obj $(OUTPRE)kfwcommon.obj $(OUTPRE)kfwlogon.res
- link $(DLL_LINKOPTS) -out:$@ $(OUTPRE)kfwlogon.obj $(OUTPRE)kfwcommon.obj -entry:DllEntryPoint -def:kfwlogon.def $(SYSLIBS) $(KLIB) $(CLIB)
+$(KFWLOGON): $(OUTPRE)kfwlogon.obj $(OUTPRE)kfwcommon.obj $(LIBRES)
+ link $(DLL_LINKOPTS) -out:$@ $(OUTPRE)kfwlogon.obj $(OUTPRE)kfwcommon.obj -entry:DllEntryPoint -def:kfwlogon.def $(SYSLIBS) $(KLIB) $(CLIB) $(LIBRES)
$(_VC_MANIFEST_EMBED_DLL)
-$(OUTPRE)kfwcpcc.exe: $(OUTPRE)kfwcpcc.obj $(OUTPRE)kfwcommon.obj $(OUTPRE)kfwcpcc.res
- link $(EXE_LINKOPTS) -out:$@ $(OUTPRE)kfwcpcc.obj $(OUTPRE)kfwcommon.obj $(SYSLIBS) $(KLIB) $(CLIB)
+$(KFWCPCC): $(OUTPRE)kfwcpcc.obj $(OUTPRE)kfwcommon.obj $(EXERES)
+ link $(EXE_LINKOPTS) -out:$@ $(OUTPRE)kfwcpcc.obj $(OUTPRE)kfwcommon.obj $(SYSLIBS) $(KLIB) $(CLIB) $(EXERES)
$(_VC_MANIFEST_EMBED_EXE)
install::
diff --git a/src/windows/kfwlogon/kfwcommon.c b/src/windows/kfwlogon/kfwcommon.c
index 14beef9..ea9410e 100644
--- a/src/windows/kfwlogon/kfwcommon.c
+++ b/src/windows/kfwlogon/kfwcommon.c
@@ -1,5 +1,6 @@
/*
Copyright 2005,2006 by the Massachusetts Institute of Technology
+Copyright 2007 by Secure Endpoints Inc.
All rights reserved.
@@ -23,7 +24,7 @@ SOFTWARE.
*/
#include "kfwlogon.h"
-#include <winbase.h>
+#include <windows.h>
#include <Aclapi.h>
#include <userenv.h>
#include <Sddl.h>
@@ -37,6 +38,10 @@ SOFTWARE.
#include <lm.h>
#include <nb30.h>
+#include <errno.h>
+#include <malloc.h>
+
+
/* Function Pointer Declarations for Delayed Loading */
// CCAPI
DECL_FUNC_PTR(cc_initialize);
@@ -290,34 +295,59 @@ 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)
{
-#ifdef DEBUG
HANDLE h; char *ptbuf[1];
- h = RegisterEventSource(NULL, KFW_LOGON_EVENT_NAME);
- ptbuf[0] = a;
- ReportEvent(h, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, (const char **)ptbuf, NULL);
- DeregisterEventSource(h);
-#endif
+ 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,...)
{
-#ifdef DEBUG
HANDLE h; char *ptbuf[1],buf[MAXBUF_+1];
va_list marker;
- h = RegisterEventSource(NULL, KFW_LOGON_EVENT_NAME);
- 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);
-#endif
+ 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
@@ -698,7 +728,7 @@ KFW_get_cred( char * username,
char * pname = 0;
krb5_error_code code;
- if (!pkrb5_init_context || !username || !password)
+ if (!pkrb5_init_context || !username || !password || !password[0])
return 0;
DebugEvent0(username);
@@ -730,22 +760,23 @@ KFW_get_cred( char * username,
if ( code ) goto cleanup;
DebugEvent0("got ccache");
+
if ( lifetime == 0 )
lifetime = pLeash_get_default_lifetime();
- if ( password[0] ) {
- 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;
- }
+ 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 )
@@ -778,6 +809,8 @@ int KFW_set_ccache_dacl(char *filename, HANDLE hUserToken)
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());
@@ -833,7 +866,7 @@ int KFW_set_ccache_dacl(char *filename, HANDLE hUserToken)
ccacheACL,
NULL)) {
gle = GetLastError();
- DebugEvent("SetNamedSecurityInfo DACL failed: GLE = 0x%lX", gle);
+ DebugEvent("SetNamedSecurityInfo DACL (1) failed: GLE = 0x%lX", gle);
if (gle != ERROR_NO_TOKEN)
ret = 1;
}
@@ -844,7 +877,7 @@ int KFW_set_ccache_dacl(char *filename, HANDLE hUserToken)
NULL,
NULL)) {
gle = GetLastError();
- DebugEvent("SetNamedSecurityInfo DACL failed: GLE = 0x%lX", gle);
+ DebugEvent("SetNamedSecurityInfo OWNER (2) failed: GLE = 0x%lX", gle);
if (gle != ERROR_NO_TOKEN)
ret = 1;
}
@@ -856,7 +889,7 @@ int KFW_set_ccache_dacl(char *filename, HANDLE hUserToken)
ccacheACL,
NULL)) {
gle = GetLastError();
- DebugEvent("SetNamedSecurityInfo DACL failed: GLE = 0x%lX", gle);
+ DebugEvent("SetNamedSecurityInfo DACL (3) failed: GLE = 0x%lX", gle);
if (gle != ERROR_NO_TOKEN)
ret = 1;
}
@@ -872,6 +905,101 @@ int KFW_set_ccache_dacl(char *filename, HANDLE hUserToken)
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;
@@ -879,7 +1007,7 @@ int KFW_obtain_user_temp_directory(HANDLE hUserToken, char *newfilename, int siz
DWORD dwLen = 0;
if (!hUserToken || !newfilename || size <= 0)
- return;
+ return 1;
*newfilename = '\0';
@@ -894,10 +1022,8 @@ int KFW_obtain_user_temp_directory(HANDLE hUserToken, char *newfilename, int siz
}
void
-KFW_copy_cache_to_system_file(char * user, char * szLogonId)
+KFW_copy_cache_to_system_file(const char * user, const char * filename)
{
- char filename[MAX_PATH] = "";
- DWORD count;
char cachename[MAX_PATH + 8] = "FILE:";
krb5_context ctx = 0;
krb5_error_code code;
@@ -906,24 +1032,11 @@ KFW_copy_cache_to_system_file(char * user, char * szLogonId)
krb5_ccache ncc = 0;
PSECURITY_ATTRIBUTES pSA = NULL;
- if (!pkrb5_init_context || !user || !szLogonId)
+ if (!pkrb5_init_context || !user || !filename)
return;
- count = GetEnvironmentVariable("TEMP", filename, sizeof(filename));
- if ( count > sizeof(filename) || count == 0 ) {
- GetWindowsDirectory(filename, sizeof(filename));
- }
-
- DebugEvent0(filename);
- if ( strlen(filename) + strlen(szLogonId) + 2 > sizeof(filename) ) {
- DebugEvent0("filename buffer too small");
- return;
- }
-
- strcat(filename, "\\");
- strcat(filename, szLogonId);
-
- strcat(cachename, filename);
+ strncat(cachename, filename, sizeof(cachename));
+ cachename[sizeof(cachename)-1] = '\0';
DebugEvent("KFW_Logon_Event - ccache %s", cachename);
@@ -984,10 +1097,87 @@ KFW_copy_file_cache_to_default_cache(char * filename)
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) ctx = 0;
+ if (code) return 1;
+
+ strcat(cachename, filename);
code = pkrb5_cc_resolve(ctx, cachename, &cc);
if (code) {
@@ -1001,7 +1191,15 @@ KFW_copy_file_cache_to_default_cache(char * filename)
goto cleanup;
}
- code = pkrb5_cc_default(ctx, &ncc);
+ 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;
@@ -1024,6 +1222,9 @@ KFW_copy_file_cache_to_default_cache(char * filename)
retval=0; /* success */
cleanup:
+ if (name)
+ pkrb5_free_unparsed_name(ctx, name);
+
if ( cc ) {
pkrb5_cc_close(ctx, cc);
cc = 0;
@@ -1055,7 +1256,7 @@ KFW_destroy_tickets_for_principal(char * user)
return 0;
code = pkrb5_init_context(&ctx);
- if (code) ctx = 0;
+ if (code) return 1;
code = pkrb5_parse_name(ctx, user, &princ);
if (code) goto loop_cleanup;
@@ -1080,3 +1281,72 @@ KFW_destroy_tickets_for_principal(char * user)
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 c3485c0..5ff7785 100644
--- a/src/windows/kfwlogon/kfwcpcc.c
+++ b/src/windows/kfwlogon/kfwcpcc.c
@@ -33,7 +33,7 @@ int main(int argc, char *argv[])
KFW_initialize();
- return KFW_copy_file_cache_to_default_cache(argv[1]);
+ return KFW_copy_file_cache_to_api_cache(argv[1]);
}
diff --git a/src/windows/kfwlogon/kfwcpcc.rc b/src/windows/kfwlogon/kfwcpcc.rc
deleted file mode 100644
index 5b0bbf2..0000000
--- a/src/windows/kfwlogon/kfwcpcc.rc
+++ /dev/null
@@ -1,10 +0,0 @@
-#include <windows.h>
-#include <winver.h>
-#include "patchlevel.h"
-
-#define K5_DESCRIPTION "Kerberos for Windows Logon Network Provider\0"
-#define K5_FILETYPE VFT_APP
-#define K5_INTERNAL_NAME "KFWLOGON\0"
-#define K5_ORIGINAL_NAME "kfwcpcc.exe\0"
-
-#include "..\version.rc"
diff --git a/src/windows/kfwlogon/kfwlogon.c b/src/windows/kfwlogon/kfwlogon.c
index 6dcd998..8422f58 100644
--- a/src/windows/kfwlogon/kfwlogon.c
+++ b/src/windows/kfwlogon/kfwlogon.c
@@ -1,5 +1,6 @@
/*
Copyright 2005,2006 by the Massachusetts Institute of Technology
+Copyright 2007 by Secure Endpoints Inc.
All rights reserved.
@@ -25,6 +26,7 @@ SOFTWARE.
#include "kfwlogon.h"
#include <io.h>
+#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
@@ -62,15 +64,12 @@ BOOLEAN APIENTRY DllEntryPoint(HANDLE dll, DWORD reason, PVOID reserved)
return TRUE;
}
-
-
DWORD APIENTRY NPGetCaps(DWORD index)
{
switch (index) {
case WNNC_NET_TYPE:
- /* Don't have our own type; use somebody else's. */
+ /* 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;
@@ -80,6 +79,7 @@ DWORD APIENTRY NPGetCaps(DWORD index)
}
}
+
static BOOL
WINAPI
UnicodeStringToANSI(UNICODE_STRING uInputString, LPSTR lpszOutputString, int nOutStringLen)
@@ -107,6 +107,76 @@ UnicodeStringToANSI(UNICODE_STRING uInputString, LPSTR lpszOutputString, int nOu
} // 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,
@@ -117,10 +187,9 @@ DWORD APIENTRY NPLogonNotify(
LPVOID StationHandle,
LPWSTR *lpLogonScript)
{
- char uname[MAX_USERNAME_LENGTH]="";
- char password[MAX_PASSWORD_LENGTH]="";
- char logonDomain[MAX_DOMAIN_LENGTH]="";
- char szLogonId[128] = "";
+ char uname[MAX_USERNAME_LENGTH+1]="";
+ char password[MAX_PASSWORD_LENGTH+1]="";
+ char logonDomain[MAX_DOMAIN_LENGTH+1]="";
MSV1_0_INTERACTIVE_LOGON *IL;
@@ -129,14 +198,43 @@ DWORD APIENTRY NPLogonNotify(
char *reason;
char *ctemp;
- BOOLEAN interactive;
+ BOOLEAN interactive = TRUE;
HWND hwndOwner = (HWND)StationHandle;
BOOLEAN lowercased_name = TRUE;
+ /* Can we load KFW binaries? */
if ( !KFW_is_available() )
- return 0;
+ 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();
- DebugEvent("NPLogonNotify - LoginId(%d,%d)", lpLogonId->HighPart, lpLogonId->LowPart);
+ /* 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;
@@ -144,11 +242,11 @@ DWORD APIENTRY NPLogonNotify(
/* MSV1_0_INTERACTIVE_LOGON and KERB_INTERACTIVE_LOGON are equivalent for
* our purposes */
- if ( wcscmp(lpAuthentInfoType,L"MSV1_0:Interactive") &&
- wcscmp(lpAuthentInfoType,L"Kerberos:Interactive") )
+ if ( wcsicmp(lpAuthentInfoType,L"MSV1_0:Interactive") &&
+ wcsicmp(lpAuthentInfoType,L"Kerberos:Interactive") )
{
char msg[64];
- WideCharToMultiByte(CP_ACP, 0, lpAuthentInfoType, 0,
+ WideCharToMultiByte(CP_ACP, 0, lpAuthentInfoType, -1,
msg, sizeof(msg), NULL, NULL);
msg[sizeof(msg)-1]='\0';
DebugEvent("NPLogonNotify - Unsupported Authentication Info Type: %s", msg);
@@ -157,9 +255,6 @@ DWORD APIENTRY NPLogonNotify(
IL = (MSV1_0_INTERACTIVE_LOGON *) lpAuthentInfo;
- /* Are we interactive? */
- interactive = (wcscmp(lpStationName, L"WinSta0") == 0);
-
/* Convert from Unicode to ANSI */
/*TODO: Use SecureZeroMemory to erase passwords */
@@ -187,8 +282,94 @@ DWORD APIENTRY NPLogonNotify(
* for this user
*/
if (!code) {
- sprintf(szLogonId,"kfwlogon-%d.%d",lpLogonId->HighPart, lpLogonId->LowPart);
- KFW_copy_cache_to_system_file(uname, szLogonId);
+ 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);
@@ -202,8 +383,7 @@ DWORD APIENTRY NPLogonNotify(
h = RegisterEventSource(NULL, KFW_LOGON_EVENT_NAME);
ptbuf[0] = msg;
- ReportEvent(h, EVENTLOG_WARNING_TYPE, 0, 1008, NULL,
- 1, 0, ptbuf, NULL);
+ ReportEvent(h, EVENTLOG_WARNING_TYPE, 0, 1008, NULL, 1, 0, ptbuf, NULL);
DeregisterEventSource(h);
SetLastError(code);
}
@@ -287,6 +467,7 @@ GetSecurityLogonSessionData(HANDLE hToken, PSECURITY_LOGON_SESSION_DATA * ppSess
VOID KFW_Logon_Event( PWLX_NOTIFICATION_INFO pInfo )
{
+#ifdef USE_WINLOGON_EVENT
WCHAR szUserW[128] = L"";
char szUserA[128] = "";
char szPath[MAX_PATH] = "";
@@ -312,7 +493,7 @@ VOID KFW_Logon_Event( PWLX_NOTIFICATION_INFO pInfo )
LogonId = pLogonSessionData->LogonId;
DebugEvent("KFW_Logon_Event - LogonId(%d,%d)", LogonId.HighPart, LogonId.LowPart);
- sprintf(szLogonId,"kfwlogon-%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");
@@ -365,7 +546,7 @@ VOID KFW_Logon_Event( PWLX_NOTIFICATION_INFO pInfo )
return;
}
- sprintf(commandline, "kfwcpcc.exe \"%s\"", newfilename);
+ _snprintf(commandline, sizeof(commandline), "kfwcpcc.exe \"%s\"", newfilename);
GetStartupInfo(&startupinfo);
if (CreateProcessAsUser( pInfo->hToken,
@@ -390,8 +571,64 @@ VOID KFW_Logon_Event( PWLX_NOTIFICATION_INFO pInfo )
DebugEvent0("KFW_Logon_Event - CreateProcessFailed");
}
- DeleteFile(filename);
+ 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.def b/src/windows/kfwlogon/kfwlogon.def
index 52af990..05e5b3b 100644
--- a/src/windows/kfwlogon/kfwlogon.def
+++ b/src/windows/kfwlogon/kfwlogon.def
@@ -7,6 +7,8 @@ EXPORTS
NPLogonNotify
NPPasswordChangeNotify
KFW_Logon_Event
+ LogonEventHandlerA
+
diff --git a/src/windows/kfwlogon/kfwlogon.h b/src/windows/kfwlogon/kfwlogon.h
index d3fa670..cfbe4fd 100644
--- a/src/windows/kfwlogon/kfwlogon.h
+++ b/src/windows/kfwlogon/kfwlogon.h
@@ -1,6 +1,7 @@
/*
Copyright 2005,2006 by the Massachusetts Institute of Technology
+Copyright 2007 by Secure Endpoints Inc.
All rights reserved.
@@ -26,8 +27,16 @@ 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 0x0500
+#define _WIN32_WINNT 0x0501
+#else
+#if _WIN32_WINNT < 0x0501
+#undef _WIN32_WINNT
+#define _WIN32_WINNT 0x0501
+#endif
#endif
#include <windows.h>
@@ -150,7 +159,7 @@ cc_free_NC_info,
#define MAX_PASSWORD_LENGTH 256
#define MAX_DOMAIN_LENGTH 256
-#define KFW_LOGON_EVENT_NAME TEXT("KFW Logon")
+#define KFW_LOGON_EVENT_NAME TEXT("MIT Kerberos")
BOOLEAN APIENTRY DllEntryPoint(HANDLE dll, DWORD reason, PVOID reserved);
@@ -192,10 +201,14 @@ static BOOL WINAPI UnicodeStringToANSI(UNICODE_STRING uInputString, LPSTR lpszOu
int KFW_is_available(void);
int KFW_get_cred( char * username, char * password, int lifetime, char ** reasonP );
-void KFW_copy_cache_to_system_file(char * user, char * szLogonId);
+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
}
diff --git a/src/windows/kfwlogon/kfwlogon.rc b/src/windows/kfwlogon/kfwlogon.rc
deleted file mode 100644
index 1a3cb15..0000000
--- a/src/windows/kfwlogon/kfwlogon.rc
+++ /dev/null
@@ -1,10 +0,0 @@
-#include <windows.h>
-#include <winver.h>
-#include "patchlevel.h"
-
-#define K5_DESCRIPTION "Kerberos for Windows Logon Network Provider\0"
-#define K5_FILETYPE VFT_DLL
-#define K5_INTERNAL_NAME "KFWLOGON\0"
-#define K5_ORIGINAL_NAME "kfwlogon.dll\0"
-
-#include "..\version.rc"
diff --git a/src/windows/ms2mit/Makefile.in b/src/windows/ms2mit/Makefile.in
index 6162eb0..0bb4d8d 100644
--- a/src/windows/ms2mit/Makefile.in
+++ b/src/windows/ms2mit/Makefile.in
@@ -9,14 +9,28 @@ BUILDTOP=$(REL)..$(S)..
DEFINES =
PROG_LIBPATH=-L$(TOPLIBD) -L$(KRB5_LIBDIR)
-all-windows:: $(OUTPRE)ms2mit.exe $(OUTPRE)mit2ms.exe
+VERSIONRC = $(BUILDTOP)\windows\version.rc
+RCFLAGS=$(CPPFLAGS) -I$(SRCTOP) -D_WIN32 -DRES_ONLY
-$(OUTPRE)ms2mit.exe: $(OUTPRE)ms2mit.obj
- link $(EXE_LINKOPTS) -out:$@ $(OUTPRE)ms2mit.obj $(BUILDTOP)\util\windows\$(OUTPRE)getopt.obj user32.lib advapi32.lib $(KLIB) $(CLIB)
+MS2MIT=$(OUTPRE)ms2mit.exe
+MIT2MS=$(OUTPRE)mit2ms.exe
+
+MS2MITRES=$(MS2MIT:.exe=.res)
+MIT2MSRES=$(MIT2MS:.exe=.res)
+
+$(MS2MITRES): $(VERSIONRC)
+ $(RC) $(RCFLAGS) -DMS2MIT_APP -fo $@ -r $**
+$(MIT2MSRES): $(VERSIONRC)
+ $(RC) $(RCFLAGS) -DMIT2MS_APP -fo $@ -r $**
+
+all-windows:: $(MS2MIT) $(MIT2MS)
+
+$(MS2MIT): $(OUTPRE)ms2mit.obj $(MS2MITRES)
+ link $(EXE_LINKOPTS) -out:$@ $(OUTPRE)ms2mit.obj $(BUILDTOP)\util\windows\$(OUTPRE)getopt.obj user32.lib advapi32.lib $(KLIB) $(CLIB) $(MS2MITRES)
$(_VC_MANIFEST_EMBED_EXE)
-$(OUTPRE)mit2ms.exe: $(OUTPRE)mit2ms.obj
- link $(EXE_LINKOPTS) -out:$@ $(OUTPRE)mit2ms.obj $(BUILDTOP)\util\windows\$(OUTPRE)getopt.obj user32.lib advapi32.lib $(KLIB) $(CLIB)
+$(MIT2MS): $(OUTPRE)mit2ms.obj $(MIT2MSRES)
+ link $(EXE_LINKOPTS) -out:$@ $(OUTPRE)mit2ms.obj $(BUILDTOP)\util\windows\$(OUTPRE)getopt.obj user32.lib advapi32.lib $(KLIB) $(CLIB) $(MIT2MSRES)
$(_VC_MANIFEST_EMBED_EXE)
install::
diff --git a/src/windows/version.rc b/src/windows/version.rc
index 3f5b1af..de4daff 100644
--- a/src/windows/version.rc
+++ b/src/windows/version.rc
@@ -41,7 +41,7 @@
#define K5_PRODUCT_VERSION_STRING MAJOR_MINOR MAYBE_PATCH RELTAIL "\0"
#define K5_PRODUCT_VERSION KRB5_MAJOR_RELEASE, KRB5_MINOR_RELEASE, KRB5_PATCHLEVEL, KRB5_BUILDLEVEL
-#define K5_COPYRIGHT "Copyright (C) 1997-2006 by the Massachusetts Institute of Technology\0"
+#define K5_COPYRIGHT "Copyright (C) 1997-2007 by the Massachusetts Institute of Technology\0"
#define K5_COMPANY_NAME "Massachusetts Institute of Technology.\0"
/*
@@ -162,6 +162,112 @@
#define K5_ORIGINAL_NAME "telnet.exe\0"
#endif
+#ifdef KRB524_LIB
+#define K5_DESCRIPTION "Kerberos v5 to v4 - MIT GSS / Kerberos v5 distribution\0"
+#define K5_INTERNAL_NAME "krb524\0"
+#define K5_FILETYPE VFT_DLL
+#define K5_ORIGINAL_NAME "krb524.dll\0"
+#endif /* KRB524_LIB */
+
+#ifdef KRB524_INIT
+#define K5_DESCRIPTION "Kerberos v5 to v4 Application - MIT GSS / Kerberos v5 distribution\0"
+#define K5_INTERNAL_NAME "krb524_init\0"
+#define K5_FILETYPE VFT_DLL
+#define K5_ORIGINAL_NAME "krb524_init.exe\0"
+#endif /* KRB524_INIT */
+
+#ifdef MS2MIT_APP
+#define K5_DESCRIPTION "Microsoft LSA to MIT Credential Cache Application - MIT GSS / Kerberos v5 distribution\0"
+#define K5_INTERNAL_NAME "ms2mit\0"
+#define K5_FILETYPE VFT_DLL
+#define K5_ORIGINAL_NAME "ms2mit.exe\0"
+#endif /* MS2MIT_APP */
+
+#ifdef MIT2MS_APP
+#define K5_DESCRIPTION "MIT to Microsoft LSA Credential Cache Application - MIT GSS / Kerberos v5 distribution\0"
+#define K5_INTERNAL_NAME "mit2ms\0"
+#define K5_FILETYPE VFT_DLL
+#define K5_ORIGINAL_NAME "mit2ms.exe\0"
+#endif /* MIT2MS_APP */
+
+#ifdef KVNO_APP
+#define K5_DESCRIPTION "Key Version Number Application - MIT GSS / Kerberos v5 distribution\0"
+#define K5_INTERNAL_NAME "kvno\0"
+#define K5_FILETYPE VFT_DLL
+#define K5_ORIGINAL_NAME "kvno.exe\0"
+#endif /* KVNO_APP */
+
+#ifdef KPASSWD_APP
+#define K5_DESCRIPTION "Kerberos Change Password Application - MIT GSS / Kerberos v5 distribution\0"
+#define K5_INTERNAL_NAME "kpasswd\0"
+#define K5_FILETYPE VFT_DLL
+#define K5_ORIGINAL_NAME "kpasswd.exe\0"
+#endif /* KPASSWD_APP */
+
+#ifdef KFWLOGON_LIB
+#define K5_DESCRIPTION "Kerberos Network Provider - MIT GSS / Kerberos v5 distribution\0"
+#define K5_INTERNAL_NAME "kfwlogon\0"
+#define K5_FILETYPE VFT_DLL
+#define K5_ORIGINAL_NAME "kfwlogon.dll\0"
+#endif /* KFWLOGON_LIB */
+
+#ifdef KFWCPCC_APP
+#define K5_DESCRIPTION "Copy Credential Cache Application - MIT GSS / Kerberos v5 distribution\0"
+#define K5_INTERNAL_NAME "kfwcpcc\0"
+#define K5_FILETYPE VFT_DLL
+#define K5_ORIGINAL_NAME "kfwcpcc.exe\0"
+#endif /* KFWCPCC_APP */
+
+#ifdef KCPYTKT_APP
+#define K5_DESCRIPTION "Kerberos Copy Ticket Application - MIT GSS / Kerberos v5 distribution\0"
+#define K5_INTERNAL_NAME "kcpytkt\0"
+#define K5_FILETYPE VFT_DLL
+#define K5_ORIGINAL_NAME "kcpytkt.exe\0"
+#endif /* KCPYTKT_APP */
+
+#ifdef KDELTKT_APP
+#define K5_DESCRIPTION "Kerberos Delete Ticket Application - MIT GSS / Kerberos v5 distribution\0"
+#define K5_INTERNAL_NAME "kdeltkt\0"
+#define K5_FILETYPE VFT_DLL
+#define K5_ORIGINAL_NAME "kdeltkt.exe\0"
+#endif /* KDELTKT_APP */
+
+#ifdef KDESTROY_APP
+#define K5_DESCRIPTION "Kerberos Destroy Credential Cache Application - MIT GSS / Kerberos v5 distribution\0"
+#define K5_INTERNAL_NAME "kdestroy\0"
+#define K5_FILETYPE VFT_DLL
+#define K5_ORIGINAL_NAME "kdestroy.exe\0"
+#endif /* KDESTROY_APP */
+
+#ifdef KINIT_APP
+#define K5_DESCRIPTION "Kerberos Initialize Credential Cache Application - MIT GSS / Kerberos v5 distribution\0"
+#define K5_INTERNAL_NAME "kinit\0"
+#define K5_FILETYPE VFT_DLL
+#define K5_ORIGINAL_NAME "kinit.exe\0"
+#endif /* KINIT_APP */
+
+#ifdef KLIST_APP
+#define K5_DESCRIPTION "Kerberos List Credential Cache Application - MIT GSS / Kerberos v5 distribution\0"
+#define K5_INTERNAL_NAME "klist\0"
+#define K5_FILETYPE VFT_DLL
+#define K5_ORIGINAL_NAME "klist.exe\0"
+#endif /* KLIST_APP */
+
+#ifdef GSS_CLIENT_APP
+#define K5_DESCRIPTION "GSS Sample Client Application - MIT GSS / Kerberos v5 distribution\0"
+#define K5_INTERNAL_NAME "gss-client\0"
+#define K5_FILETYPE VFT_DLL
+#define K5_ORIGINAL_NAME "gss-client.exe\0"
+#endif /* GSS_CLIENT_APP */
+
+#ifdef GSS_SERVER_APP
+#define K5_DESCRIPTION "GSS Sample Server Application - MIT GSS / Kerberos v5 distribution\0"
+#define K5_INTERNAL_NAME "gss-server\0"
+#define K5_FILETYPE VFT_DLL
+#define K5_ORIGINAL_NAME "gss-server.exe\0"
+#endif /* GSS_SERVER_APP */
+
+
/*
* END SPECIFIC VERSION INFO
*/